From 5ac61172616424ec0b4c86d634eef7544378489e Mon Sep 17 00:00:00 2001 From: Adrian Cole Date: Sun, 30 Oct 2022 17:56:45 -0700 Subject: [PATCH] Changes generator to not use reflection for host functions This changes the generator to avoid performance penalty in host calls due to reflection. Signed-off-by: Adrian Cole --- examples/helloworld/greeting/greet.pb.go | 2 +- examples/helloworld/greeting/greet_host.pb.go | 2 +- .../helloworld/greeting/greet_plugin.pb.go | 2 +- .../helloworld/greeting/greet_vtproto.pb.go | 2 +- examples/host-functions/greeting/greet.pb.go | 2 +- .../host-functions/greeting/greet_host.pb.go | 29 ++++++++++++++----- .../greeting/greet_plugin.pb.go | 2 +- .../greeting/greet_vtproto.pb.go | 2 +- examples/known-types/known/known.pb.go | 2 +- examples/known-types/known/known_host.pb.go | 2 +- examples/known-types/known/known_plugin.pb.go | 2 +- .../known-types/known/known_vtproto.pb.go | 2 +- examples/wasi/cat/cat.pb.go | 2 +- examples/wasi/cat/cat_host.pb.go | 2 +- examples/wasi/cat/cat_plugin.pb.go | 2 +- examples/wasi/cat/cat_vtproto.pb.go | 2 +- gen/host.go | 16 ++++++++-- tests/host-functions/proto/host_host.pb.go | 16 ++++++++-- 18 files changed, 63 insertions(+), 28 deletions(-) diff --git a/examples/helloworld/greeting/greet.pb.go b/examples/helloworld/greeting/greet.pb.go index 2371431..331d4a8 100644 --- a/examples/helloworld/greeting/greet.pb.go +++ b/examples/helloworld/greeting/greet.pb.go @@ -2,7 +2,7 @@ // versions: // protoc-gen-go-plugin v0.1.0 // protoc v3.21.5 -// source: greeting/greet.proto +// source: examples/helloworld/greeting/greet.proto package greeting diff --git a/examples/helloworld/greeting/greet_host.pb.go b/examples/helloworld/greeting/greet_host.pb.go index db38984..e75cad1 100644 --- a/examples/helloworld/greeting/greet_host.pb.go +++ b/examples/helloworld/greeting/greet_host.pb.go @@ -4,7 +4,7 @@ // versions: // protoc-gen-go-plugin v0.1.0 // protoc v3.21.5 -// source: greeting/greet.proto +// source: examples/helloworld/greeting/greet.proto package greeting diff --git a/examples/helloworld/greeting/greet_plugin.pb.go b/examples/helloworld/greeting/greet_plugin.pb.go index 03ffec0..30c35df 100644 --- a/examples/helloworld/greeting/greet_plugin.pb.go +++ b/examples/helloworld/greeting/greet_plugin.pb.go @@ -4,7 +4,7 @@ // versions: // protoc-gen-go-plugin v0.1.0 // protoc v3.21.5 -// source: greeting/greet.proto +// source: examples/helloworld/greeting/greet.proto package greeting diff --git a/examples/helloworld/greeting/greet_vtproto.pb.go b/examples/helloworld/greeting/greet_vtproto.pb.go index def5c7b..e9fec7a 100644 --- a/examples/helloworld/greeting/greet_vtproto.pb.go +++ b/examples/helloworld/greeting/greet_vtproto.pb.go @@ -2,7 +2,7 @@ // versions: // protoc-gen-go-plugin v0.1.0 // protoc v3.21.5 -// source: greeting/greet.proto +// source: examples/helloworld/greeting/greet.proto package greeting diff --git a/examples/host-functions/greeting/greet.pb.go b/examples/host-functions/greeting/greet.pb.go index 0f32dd5..a774087 100644 --- a/examples/host-functions/greeting/greet.pb.go +++ b/examples/host-functions/greeting/greet.pb.go @@ -2,7 +2,7 @@ // versions: // protoc-gen-go-plugin v0.1.0 // protoc v3.21.5 -// source: greeting/greet.proto +// source: examples/host-functions/greeting/greet.proto package greeting diff --git a/examples/host-functions/greeting/greet_host.pb.go b/examples/host-functions/greeting/greet_host.pb.go index a7006ba..31e2433 100644 --- a/examples/host-functions/greeting/greet_host.pb.go +++ b/examples/host-functions/greeting/greet_host.pb.go @@ -4,7 +4,7 @@ // versions: // protoc-gen-go-plugin v0.1.0 // protoc v3.21.5 -// source: greeting/greet.proto +// source: examples/host-functions/greeting/greet.proto package greeting @@ -22,6 +22,11 @@ import ( os "os" ) +const ( + i32 = api.ValueTypeI32 + i64 = api.ValueTypeI64 +) + type _hostFunctions struct { HostFunctions } @@ -30,9 +35,15 @@ type _hostFunctions struct { func (h _hostFunctions) Instantiate(ctx context.Context, r wazero.Runtime, ns wazero.Namespace) error { envBuilder := r.NewHostModuleBuilder("env") - envBuilder.NewFunctionBuilder().WithFunc(h._HttpGet).Export("http_get") + envBuilder.NewFunctionBuilder(). + WithGoModuleFunction(api.GoModuleFunc(h._HttpGet), []api.ValueType{i32, i32}, []api.ValueType{i64}). + WithParameterNames("offset", "size"). + Export("http_get") - envBuilder.NewFunctionBuilder().WithFunc(h._Log).Export("log") + envBuilder.NewFunctionBuilder(). + WithGoModuleFunction(api.GoModuleFunc(h._Log), []api.ValueType{i32, i32}, []api.ValueType{i64}). + WithParameterNames("offset", "size"). + Export("log") _, err := envBuilder.Instantiate(ctx, ns) return err @@ -40,7 +51,8 @@ func (h _hostFunctions) Instantiate(ctx context.Context, r wazero.Runtime, ns wa // Sends a HTTP GET request -func (h _hostFunctions) _HttpGet(ctx context.Context, m api.Module, offset, size uint32) uint64 { +func (h _hostFunctions) _HttpGet(ctx context.Context, m api.Module, params []uint64) []uint64 { + offset, size := uint32(params[0]), uint32(params[1]) buf, err := wasm.ReadMemory(ctx, m, offset, size) if err != nil { panic(err) @@ -62,12 +74,14 @@ func (h _hostFunctions) _HttpGet(ctx context.Context, m api.Module, offset, size if err != nil { panic(err) } - return (ptr << uint64(32)) | uint64(len(buf)) + ptrLen := (ptr << uint64(32)) | uint64(len(buf)) + return []uint64{ptrLen} } // Shows a log message -func (h _hostFunctions) _Log(ctx context.Context, m api.Module, offset, size uint32) uint64 { +func (h _hostFunctions) _Log(ctx context.Context, m api.Module, params []uint64) []uint64 { + offset, size := uint32(params[0]), uint32(params[1]) buf, err := wasm.ReadMemory(ctx, m, offset, size) if err != nil { panic(err) @@ -89,7 +103,8 @@ func (h _hostFunctions) _Log(ctx context.Context, m api.Module, offset, size uin if err != nil { panic(err) } - return (ptr << uint64(32)) | uint64(len(buf)) + ptrLen := (ptr << uint64(32)) | uint64(len(buf)) + return []uint64{ptrLen} } const GreeterPluginAPIVersion = 1 diff --git a/examples/host-functions/greeting/greet_plugin.pb.go b/examples/host-functions/greeting/greet_plugin.pb.go index fca774f..d20d5a3 100644 --- a/examples/host-functions/greeting/greet_plugin.pb.go +++ b/examples/host-functions/greeting/greet_plugin.pb.go @@ -4,7 +4,7 @@ // versions: // protoc-gen-go-plugin v0.1.0 // protoc v3.21.5 -// source: greeting/greet.proto +// source: examples/host-functions/greeting/greet.proto package greeting diff --git a/examples/host-functions/greeting/greet_vtproto.pb.go b/examples/host-functions/greeting/greet_vtproto.pb.go index 4202e56..eff1289 100644 --- a/examples/host-functions/greeting/greet_vtproto.pb.go +++ b/examples/host-functions/greeting/greet_vtproto.pb.go @@ -2,7 +2,7 @@ // versions: // protoc-gen-go-plugin v0.1.0 // protoc v3.21.5 -// source: greeting/greet.proto +// source: examples/host-functions/greeting/greet.proto package greeting diff --git a/examples/known-types/known/known.pb.go b/examples/known-types/known/known.pb.go index 0a3e243..d0fe04f 100644 --- a/examples/known-types/known/known.pb.go +++ b/examples/known-types/known/known.pb.go @@ -2,7 +2,7 @@ // versions: // protoc-gen-go-plugin v0.1.0 // protoc v3.21.5 -// source: known/known.proto +// source: examples/known-types/known/known.proto package known diff --git a/examples/known-types/known/known_host.pb.go b/examples/known-types/known/known_host.pb.go index b1a483a..806b777 100644 --- a/examples/known-types/known/known_host.pb.go +++ b/examples/known-types/known/known_host.pb.go @@ -4,7 +4,7 @@ // versions: // protoc-gen-go-plugin v0.1.0 // protoc v3.21.5 -// source: known/known.proto +// source: examples/known-types/known/known.proto package known diff --git a/examples/known-types/known/known_plugin.pb.go b/examples/known-types/known/known_plugin.pb.go index ea185e1..9b9205a 100644 --- a/examples/known-types/known/known_plugin.pb.go +++ b/examples/known-types/known/known_plugin.pb.go @@ -4,7 +4,7 @@ // versions: // protoc-gen-go-plugin v0.1.0 // protoc v3.21.5 -// source: known/known.proto +// source: examples/known-types/known/known.proto package known diff --git a/examples/known-types/known/known_vtproto.pb.go b/examples/known-types/known/known_vtproto.pb.go index 09aa6a3..781e50b 100644 --- a/examples/known-types/known/known_vtproto.pb.go +++ b/examples/known-types/known/known_vtproto.pb.go @@ -2,7 +2,7 @@ // versions: // protoc-gen-go-plugin v0.1.0 // protoc v3.21.5 -// source: known/known.proto +// source: examples/known-types/known/known.proto package known diff --git a/examples/wasi/cat/cat.pb.go b/examples/wasi/cat/cat.pb.go index 63db01a..e2774a2 100644 --- a/examples/wasi/cat/cat.pb.go +++ b/examples/wasi/cat/cat.pb.go @@ -2,7 +2,7 @@ // versions: // protoc-gen-go-plugin v0.1.0 // protoc v3.21.5 -// source: cat/cat.proto +// source: examples/wasi/cat/cat.proto package cat diff --git a/examples/wasi/cat/cat_host.pb.go b/examples/wasi/cat/cat_host.pb.go index 939fa9f..bfdcaa5 100644 --- a/examples/wasi/cat/cat_host.pb.go +++ b/examples/wasi/cat/cat_host.pb.go @@ -4,7 +4,7 @@ // versions: // protoc-gen-go-plugin v0.1.0 // protoc v3.21.5 -// source: cat/cat.proto +// source: examples/wasi/cat/cat.proto package cat diff --git a/examples/wasi/cat/cat_plugin.pb.go b/examples/wasi/cat/cat_plugin.pb.go index 3f5e0a6..cc14d4b 100644 --- a/examples/wasi/cat/cat_plugin.pb.go +++ b/examples/wasi/cat/cat_plugin.pb.go @@ -4,7 +4,7 @@ // versions: // protoc-gen-go-plugin v0.1.0 // protoc v3.21.5 -// source: cat/cat.proto +// source: examples/wasi/cat/cat.proto package cat diff --git a/examples/wasi/cat/cat_vtproto.pb.go b/examples/wasi/cat/cat_vtproto.pb.go index 15376aa..a3e9747 100644 --- a/examples/wasi/cat/cat_vtproto.pb.go +++ b/examples/wasi/cat/cat_vtproto.pb.go @@ -2,7 +2,7 @@ // versions: // protoc-gen-go-plugin v0.1.0 // protoc v3.21.5 -// source: cat/cat.proto +// source: examples/wasi/cat/cat.proto package cat diff --git a/gen/host.go b/gen/host.go index 9e790da..ceb1cac 100644 --- a/gen/host.go +++ b/gen/host.go @@ -35,6 +35,11 @@ func (gg *Generator) genHostFunctions(g *protogen.GeneratedFile, f *fileInfo) { // Define host functions structName := "_" + strings.ToLower(f.hostService.GoName[:1]) + f.hostService.GoName[1:] g.P(fmt.Sprintf(` + const ( + i32 = api.ValueTypeI32 + i64 = api.ValueTypeI64 + ) + type %s struct { %s } @@ -47,7 +52,10 @@ func (gg *Generator) genHostFunctions(g *protogen.GeneratedFile, f *fileInfo) { envBuilder := r.NewHostModuleBuilder("env")`, structName)) for _, method := range f.hostService.Methods { g.P(fmt.Sprintf(` - envBuilder.NewFunctionBuilder().WithFunc(h._%s).Export("%s")`, + envBuilder.NewFunctionBuilder(). + WithGoModuleFunction(api.GoModuleFunc(h._%s), []api.ValueType{i32, i32}, []api.ValueType{i64}). + WithParameterNames("offset", "size"). + Export("%s")`, method.GoName, toSnakeCase(method.GoName))) } g.P(` @@ -61,12 +69,13 @@ func (gg *Generator) genHostFunctions(g *protogen.GeneratedFile, f *fileInfo) { }` for _, method := range f.hostService.Methods { g.P(method.Comments.Leading, fmt.Sprintf(` - func (h %s) _%s(ctx %s, m %s, offset, size uint32) uint64 {`, + func (h %s) _%s(ctx %s, m %s, params []uint64) []uint64 {`, structName, method.GoName, g.QualifiedGoIdent(contextPackage.Ident("Context")), g.QualifiedGoIdent(wazeroAPIPackage.Ident("Module")), )) + g.P("offset, size := uint32(params[0]), uint32(params[1])") g.P("buf, err := ", g.QualifiedGoIdent(pluginWasmPackage.Ident("ReadMemory")), "(ctx, m, offset, size)") g.P(errorHandling) @@ -83,7 +92,8 @@ func (gg *Generator) genHostFunctions(g *protogen.GeneratedFile, f *fileInfo) { g.P("ptr, err := ", g.QualifiedGoIdent(pluginWasmPackage.Ident("WriteMemory")), "(ctx, m, buf)") g.P(errorHandling) - g.P("return (ptr << uint64(32)) | uint64(len(buf))") + g.P("ptrLen := (ptr << uint64(32)) | uint64(len(buf))") + g.P("return []uint64{ptrLen}") g.P("}") } } diff --git a/tests/host-functions/proto/host_host.pb.go b/tests/host-functions/proto/host_host.pb.go index 5f20a54..633a756 100644 --- a/tests/host-functions/proto/host_host.pb.go +++ b/tests/host-functions/proto/host_host.pb.go @@ -22,6 +22,11 @@ import ( os "os" ) +const ( + i32 = api.ValueTypeI32 + i64 = api.ValueTypeI64 +) + type _hostFunctions struct { HostFunctions } @@ -30,13 +35,17 @@ type _hostFunctions struct { func (h _hostFunctions) Instantiate(ctx context.Context, r wazero.Runtime, ns wazero.Namespace) error { envBuilder := r.NewHostModuleBuilder("env") - envBuilder.NewFunctionBuilder().WithFunc(h._ParseJson).Export("parse_json") + envBuilder.NewFunctionBuilder(). + WithGoModuleFunction(api.GoModuleFunc(h._ParseJson), []api.ValueType{i32, i32}, []api.ValueType{i64}). + WithParameterNames("offset", "size"). + Export("parse_json") _, err := envBuilder.Instantiate(ctx, ns) return err } -func (h _hostFunctions) _ParseJson(ctx context.Context, m api.Module, offset, size uint32) uint64 { +func (h _hostFunctions) _ParseJson(ctx context.Context, m api.Module, params []uint64) []uint64 { + offset, size := uint32(params[0]), uint32(params[1]) buf, err := wasm.ReadMemory(ctx, m, offset, size) if err != nil { panic(err) @@ -58,7 +67,8 @@ func (h _hostFunctions) _ParseJson(ctx context.Context, m api.Module, offset, si if err != nil { panic(err) } - return (ptr << uint64(32)) | uint64(len(buf)) + ptrLen := (ptr << uint64(32)) | uint64(len(buf)) + return []uint64{ptrLen} } const GreeterPluginAPIVersion = 1