diff --git a/builder.go b/builder.go index 6093fdd1..aa9a744e 100644 --- a/builder.go +++ b/builder.go @@ -237,7 +237,7 @@ func (h *hostFunctionBuilder) WithGoFunction(fn api.GoFunction, params, results h.fn = &wasm.HostFunc{ ParamTypes: params, ResultTypes: results, - Code: &wasm.Code{IsHostFunction: true, GoFunc: fn}, + Code: &wasm.Code{GoFunc: fn}, } return h } @@ -247,7 +247,7 @@ func (h *hostFunctionBuilder) WithGoModuleFunction(fn api.GoModuleFunction, para h.fn = &wasm.HostFunc{ ParamTypes: params, ResultTypes: results, - Code: &wasm.Code{IsHostFunction: true, GoFunc: fn}, + Code: &wasm.Code{GoFunc: fn}, } return h } diff --git a/builder_test.go b/builder_test.go index 4476df81..e635317d 100644 --- a/builder_test.go +++ b/builder_test.go @@ -171,7 +171,7 @@ func TestNewHostModuleBuilder_Compile(t *testing.T) { }, FunctionSection: []wasm.Index{0}, CodeSection: []*wasm.Code{ - {IsHostFunction: true, GoFunc: gofunc1}, + {GoFunc: gofunc1}, }, ExportSection: []wasm.Export{ {Name: "1", Type: wasm.ExternTypeFunc, Index: 0}, @@ -195,7 +195,7 @@ func TestNewHostModuleBuilder_Compile(t *testing.T) { }, FunctionSection: []wasm.Index{0}, CodeSection: []*wasm.Code{ - {IsHostFunction: true, GoFunc: gofunc1}, + {GoFunc: gofunc1}, }, ExportSection: []wasm.Export{ {Name: "1", Type: wasm.ExternTypeFunc, Index: 0}, @@ -223,7 +223,7 @@ func TestNewHostModuleBuilder_Compile(t *testing.T) { }, FunctionSection: []wasm.Index{0}, CodeSection: []*wasm.Code{ - {IsHostFunction: true, GoFunc: gofunc2}, + {GoFunc: gofunc2}, }, ExportSection: []wasm.Export{ {Name: "1", Type: wasm.ExternTypeFunc, Index: 0}, @@ -252,8 +252,8 @@ func TestNewHostModuleBuilder_Compile(t *testing.T) { }, FunctionSection: []wasm.Index{0, 1}, CodeSection: []*wasm.Code{ - {IsHostFunction: true, GoFunc: gofunc1}, - {IsHostFunction: true, GoFunc: gofunc2}, + {GoFunc: gofunc1}, + {GoFunc: gofunc2}, }, ExportSection: []wasm.Export{ {Name: "1", Type: wasm.ExternTypeFunc, Index: 0}, @@ -310,7 +310,7 @@ func TestNewHostModuleBuilder_Compile_Errors(t *testing.T) { WithFunc(&wasm.HostFunc{ ExportNames: []string{"fn"}, ResultTypes: []wasm.ValueType{wasm.ValueTypeI32}, - Code: &wasm.Code{IsHostFunction: true, Body: []byte{wasm.OpcodeEnd}}, + Code: &wasm.Code{Body: []byte{wasm.OpcodeEnd}}, }).Export("fn") }, expectedErr: `invalid function[0] export["fn"]: not enough results @@ -378,7 +378,6 @@ func requireHostModuleEquals(t *testing.T, expected, actual *wasm.Module) { require.Equal(t, len(expected.CodeSection), len(actual.CodeSection)) for i, c := range expected.CodeSection { actualCode := actual.CodeSection[i] - require.True(t, actualCode.IsHostFunction) require.Equal(t, c.GoFunc, actualCode.GoFunc) // Not wasm diff --git a/imports/assemblyscript/assemblyscript.go b/imports/assemblyscript/assemblyscript.go index 2b7cd6c9..5bf2ee09 100644 --- a/imports/assemblyscript/assemblyscript.go +++ b/imports/assemblyscript/assemblyscript.go @@ -142,10 +142,7 @@ var abortMessageEnabled = &wasm.HostFunc{ Name: "~lib/builtins/abort", ParamTypes: []api.ValueType{i32, i32, i32, i32}, ParamNames: []string{"message", "fileName", "lineNumber", "columnNumber"}, - Code: &wasm.Code{ - IsHostFunction: true, - GoFunc: api.GoModuleFunc(abortWithMessage), - }, + Code: &wasm.Code{GoFunc: api.GoModuleFunc(abortWithMessage)}, } var abortMessageDisabled = abortMessageEnabled.WithGoModuleFunc(abort) @@ -184,7 +181,7 @@ func abort(ctx context.Context, mod api.Module, _ []uint64) { } // traceDisabled ignores the input. -var traceDisabled = traceStdout.WithWasm([]byte{wasm.OpcodeEnd}) +var traceDisabled = traceStdout.WithGoModuleFunc(func(context.Context, api.Module, []uint64) {}) // traceStdout implements trace to the configured Stdout. var traceStdout = &wasm.HostFunc{ @@ -193,7 +190,6 @@ var traceStdout = &wasm.HostFunc{ ParamTypes: []api.ValueType{i32, i32, f64, f64, f64, f64, f64}, ParamNames: []string{"message", "nArgs", "arg0", "arg1", "arg2", "arg3", "arg4"}, Code: &wasm.Code{ - IsHostFunction: true, GoFunc: api.GoModuleFunc(func(_ context.Context, mod api.Module, stack []uint64) { fsc := mod.(*wasm.CallContext).Sys.FS() traceTo(mod, stack, internalsys.WriterForFile(fsc, internalsys.FdStdout)) @@ -279,7 +275,6 @@ var seed = &wasm.HostFunc{ ResultTypes: []api.ValueType{f64}, ResultNames: []string{"rand"}, Code: &wasm.Code{ - IsHostFunction: true, GoFunc: api.GoModuleFunc(func(ctx context.Context, mod api.Module, stack []uint64) { r := mod.(*wasm.CallContext).Sys.RandSource() buf := make([]byte, 8) diff --git a/imports/assemblyscript/assemblyscript_test.go b/imports/assemblyscript/assemblyscript_test.go index 9e2cb601..f72a7aa7 100644 --- a/imports/assemblyscript/assemblyscript_test.go +++ b/imports/assemblyscript/assemblyscript_test.go @@ -212,12 +212,11 @@ func TestFunctionExporter_Trace(t *testing.T) { expected, expectedLog string }{ { - name: "disabled", - exporter: NewFunctionExporter(), - params: noArgs, - expected: "", - // expect no host call since it is disabled. ==> is host and --> is wasm. - expectedLog: strings.ReplaceAll(noArgsLog, "==", "--"), + name: "disabled", + exporter: NewFunctionExporter(), + params: noArgs, + expected: "", + expectedLog: noArgsLog, }, { name: "ToStderr", diff --git a/imports/emscripten/emscripten.go b/imports/emscripten/emscripten.go index e9e7573a..49c42627 100644 --- a/imports/emscripten/emscripten.go +++ b/imports/emscripten/emscripten.go @@ -98,7 +98,7 @@ var notifyMemoryGrowth = &wasm.HostFunc{ Name: functionNotifyMemoryGrowth, ParamTypes: []wasm.ValueType{wasm.ValueTypeI32}, ParamNames: []string{"memory_index"}, - Code: &wasm.Code{IsHostFunction: true, Body: []byte{wasm.OpcodeEnd}}, + Code: &wasm.Code{GoFunc: api.GoModuleFunc(func(context.Context, api.Module, []uint64) {})}, } // All `invoke_` functions have an initial "index" parameter of @@ -139,10 +139,7 @@ var invokeI = &wasm.HostFunc{ ParamTypes: []api.ValueType{i32}, ParamNames: []string{"index"}, ResultTypes: []api.ValueType{i32}, - Code: &wasm.Code{ - IsHostFunction: true, - GoFunc: api.GoModuleFunc(invokeIFn), - }, + Code: &wasm.Code{GoFunc: api.GoModuleFunc(invokeIFn)}, } func invokeIFn(ctx context.Context, mod api.Module, stack []uint64) { @@ -159,10 +156,7 @@ var invokeIi = &wasm.HostFunc{ ParamTypes: []api.ValueType{i32, i32}, ParamNames: []string{"index", "a1"}, ResultTypes: []api.ValueType{i32}, - Code: &wasm.Code{ - IsHostFunction: true, - GoFunc: api.GoModuleFunc(invokeIiFn), - }, + Code: &wasm.Code{GoFunc: api.GoModuleFunc(invokeIiFn)}, } func invokeIiFn(ctx context.Context, mod api.Module, stack []uint64) { @@ -179,10 +173,7 @@ var invokeIii = &wasm.HostFunc{ ParamTypes: []api.ValueType{i32, i32, i32}, ParamNames: []string{"index", "a1", "a2"}, ResultTypes: []api.ValueType{i32}, - Code: &wasm.Code{ - IsHostFunction: true, - GoFunc: api.GoModuleFunc(invokeIiiFn), - }, + Code: &wasm.Code{GoFunc: api.GoModuleFunc(invokeIiiFn)}, } func invokeIiiFn(ctx context.Context, mod api.Module, stack []uint64) { @@ -199,10 +190,7 @@ var invokeIiii = &wasm.HostFunc{ ParamTypes: []api.ValueType{i32, i32, i32, i32}, ParamNames: []string{"index", "a1", "a2", "a3"}, ResultTypes: []api.ValueType{i32}, - Code: &wasm.Code{ - IsHostFunction: true, - GoFunc: api.GoModuleFunc(invokeIiiiFn), - }, + Code: &wasm.Code{GoFunc: api.GoModuleFunc(invokeIiiiFn)}, } func invokeIiiiFn(ctx context.Context, mod api.Module, stack []uint64) { @@ -219,10 +207,7 @@ var invokeIiiii = &wasm.HostFunc{ ParamTypes: []api.ValueType{i32, i32, i32, i32, i32}, ParamNames: []string{"index", "a1", "a2", "a3", "a4"}, ResultTypes: []api.ValueType{i32}, - Code: &wasm.Code{ - IsHostFunction: true, - GoFunc: api.GoModuleFunc(invokeIiiiiFn), - }, + Code: &wasm.Code{GoFunc: api.GoModuleFunc(invokeIiiiiFn)}, } func invokeIiiiiFn(ctx context.Context, mod api.Module, stack []uint64) { @@ -239,10 +224,7 @@ var invokeV = &wasm.HostFunc{ ParamTypes: []api.ValueType{i32}, ParamNames: []string{"index"}, ResultTypes: []api.ValueType{}, - Code: &wasm.Code{ - IsHostFunction: true, - GoFunc: api.GoModuleFunc(invokeVFn), - }, + Code: &wasm.Code{GoFunc: api.GoModuleFunc(invokeVFn)}, } func invokeVFn(ctx context.Context, mod api.Module, stack []uint64) { @@ -258,10 +240,7 @@ var invokeVi = &wasm.HostFunc{ ParamTypes: []api.ValueType{i32, i32}, ParamNames: []string{"index", "a1"}, ResultTypes: []api.ValueType{}, - Code: &wasm.Code{ - IsHostFunction: true, - GoFunc: api.GoModuleFunc(invokeViFn), - }, + Code: &wasm.Code{GoFunc: api.GoModuleFunc(invokeViFn)}, } func invokeViFn(ctx context.Context, mod api.Module, stack []uint64) { @@ -277,10 +256,7 @@ var invokeVii = &wasm.HostFunc{ ParamTypes: []api.ValueType{i32, i32, i32}, ParamNames: []string{"index", "a1", "a2"}, ResultTypes: []api.ValueType{}, - Code: &wasm.Code{ - IsHostFunction: true, - GoFunc: api.GoModuleFunc(invokeViiFn), - }, + Code: &wasm.Code{GoFunc: api.GoModuleFunc(invokeViiFn)}, } func invokeViiFn(ctx context.Context, mod api.Module, stack []uint64) { @@ -296,10 +272,7 @@ var invokeViii = &wasm.HostFunc{ ParamTypes: []api.ValueType{i32, i32, i32, i32}, ParamNames: []string{"index", "a1", "a2", "a3"}, ResultTypes: []api.ValueType{}, - Code: &wasm.Code{ - IsHostFunction: true, - GoFunc: api.GoModuleFunc(invokeViiiFn), - }, + Code: &wasm.Code{GoFunc: api.GoModuleFunc(invokeViiiFn)}, } func invokeViiiFn(ctx context.Context, mod api.Module, stack []uint64) { @@ -315,10 +288,7 @@ var invokeViiii = &wasm.HostFunc{ ParamTypes: []api.ValueType{i32, i32, i32, i32, i32}, ParamNames: []string{"index", "a1", "a2", "a3", "a4"}, ResultTypes: []api.ValueType{}, - Code: &wasm.Code{ - IsHostFunction: true, - GoFunc: api.GoModuleFunc(invokeViiiiFn), - }, + Code: &wasm.Code{GoFunc: api.GoModuleFunc(invokeViiiiFn)}, } func invokeViiiiFn(ctx context.Context, mod api.Module, stack []uint64) { diff --git a/imports/emscripten/emscripten_test.go b/imports/emscripten/emscripten_test.go index bc2f9d96..698e287d 100644 --- a/imports/emscripten/emscripten_test.go +++ b/imports/emscripten/emscripten_test.go @@ -51,7 +51,7 @@ func TestGrow(t *testing.T) { require.Zero(t, err.(*sys.ExitError).ExitCode()) // We expect the memory no-op memory growth hook to be invoked as wasm. - require.Contains(t, log.String(), "--> env.emscripten_notify_memory_growth(memory_index=0)") + require.Contains(t, log.String(), "==> env.emscripten_notify_memory_growth(memory_index=0)") } func TestInvoke(t *testing.T) { diff --git a/imports/wasi_snapshot_preview1/fs_test.go b/imports/wasi_snapshot_preview1/fs_test.go index 7550bf46..db5909cb 100644 --- a/imports/wasi_snapshot_preview1/fs_test.go +++ b/imports/wasi_snapshot_preview1/fs_test.go @@ -457,8 +457,8 @@ func Test_fdFdstatSetFlags(t *testing.T) { func Test_fdFdstatSetRights(t *testing.T) { log := requireErrnoNosys(t, FdFdstatSetRightsName, 0, 0, 0) require.Equal(t, ` ---> wasi_snapshot_preview1.fd_fdstat_set_rights(fd=0,fs_rights_base=,fs_rights_inheriting=) -<-- errno=ENOSYS +==> wasi_snapshot_preview1.fd_fdstat_set_rights(fd=0,fs_rights_base=,fs_rights_inheriting=) +<== errno=ENOSYS `, log) } diff --git a/imports/wasi_snapshot_preview1/proc.go b/imports/wasi_snapshot_preview1/proc.go index f8c31697..5c76387e 100644 --- a/imports/wasi_snapshot_preview1/proc.go +++ b/imports/wasi_snapshot_preview1/proc.go @@ -24,8 +24,7 @@ var procExit = &wasm.HostFunc{ ParamTypes: []api.ValueType{i32}, ParamNames: []string{"rval"}, Code: &wasm.Code{ - IsHostFunction: true, - GoFunc: api.GoModuleFunc(procExitFn), + GoFunc: api.GoModuleFunc(procExitFn), }, } diff --git a/imports/wasi_snapshot_preview1/proc_test.go b/imports/wasi_snapshot_preview1/proc_test.go index 8ab55e44..85fed4c2 100644 --- a/imports/wasi_snapshot_preview1/proc_test.go +++ b/imports/wasi_snapshot_preview1/proc_test.go @@ -55,7 +55,7 @@ func Test_procExit(t *testing.T) { func Test_procRaise(t *testing.T) { log := requireErrnoNosys(t, ProcRaiseName, 0) require.Equal(t, ` ---> wasi_snapshot_preview1.proc_raise(sig=0) -<-- errno=ENOSYS +==> wasi_snapshot_preview1.proc_raise(sig=0) +<== errno=ENOSYS `, log) } diff --git a/imports/wasi_snapshot_preview1/sock_test.go b/imports/wasi_snapshot_preview1/sock_test.go index 98cbc056..a2dc0c36 100644 --- a/imports/wasi_snapshot_preview1/sock_test.go +++ b/imports/wasi_snapshot_preview1/sock_test.go @@ -11,8 +11,8 @@ import ( func Test_sockAccept(t *testing.T) { log := requireErrnoNosys(t, SockAcceptName, 0, 0, 0) require.Equal(t, ` ---> wasi_snapshot_preview1.sock_accept(fd=0,flags=0,result.fd=0) -<-- errno=ENOSYS +==> wasi_snapshot_preview1.sock_accept(fd=0,flags=0,result.fd=0) +<== errno=ENOSYS `, log) } @@ -20,8 +20,8 @@ func Test_sockAccept(t *testing.T) { func Test_sockRecv(t *testing.T) { log := requireErrnoNosys(t, SockRecvName, 0, 0, 0, 0, 0, 0) require.Equal(t, ` ---> wasi_snapshot_preview1.sock_recv(fd=0,ri_data=0,ri_data_count=0,ri_flags=0,result.ro_datalen=0,result.ro_flags=0) -<-- errno=ENOSYS +==> wasi_snapshot_preview1.sock_recv(fd=0,ri_data=0,ri_data_count=0,ri_flags=0,result.ro_datalen=0,result.ro_flags=0) +<== errno=ENOSYS `, log) } @@ -29,8 +29,8 @@ func Test_sockRecv(t *testing.T) { func Test_sockSend(t *testing.T) { log := requireErrnoNosys(t, SockSendName, 0, 0, 0, 0, 0) require.Equal(t, ` ---> wasi_snapshot_preview1.sock_send(fd=0,si_data=0,si_data_count=0,si_flags=0,result.so_datalen=0) -<-- errno=ENOSYS +==> wasi_snapshot_preview1.sock_send(fd=0,si_data=0,si_data_count=0,si_flags=0,result.so_datalen=0) +<== errno=ENOSYS `, log) } @@ -38,7 +38,7 @@ func Test_sockSend(t *testing.T) { func Test_sockShutdown(t *testing.T) { log := requireErrnoNosys(t, SockShutdownName, 0, 0) require.Equal(t, ` ---> wasi_snapshot_preview1.sock_shutdown(fd=0,how=0) -<-- errno=ENOSYS +==> wasi_snapshot_preview1.sock_shutdown(fd=0,how=0) +<== errno=ENOSYS `, log) } diff --git a/imports/wasi_snapshot_preview1/wasi.go b/imports/wasi_snapshot_preview1/wasi.go index 480024be..e650dce1 100644 --- a/imports/wasi_snapshot_preview1/wasi.go +++ b/imports/wasi_snapshot_preview1/wasi.go @@ -268,7 +268,7 @@ func newHostFunc( ParamNames: paramNames, ResultTypes: []api.ValueType{i32}, ResultNames: []string{"errno"}, - Code: &wasm.Code{IsHostFunction: true, GoFunc: goFunc}, + Code: &wasm.Code{GoFunc: goFunc}, } } @@ -292,8 +292,7 @@ func stubFunction(name string, paramTypes []wasm.ValueType, paramNames ...string ResultTypes: []api.ValueType{i32}, ResultNames: []string{"errno"}, Code: &wasm.Code{ - IsHostFunction: true, - Body: []byte{wasm.OpcodeI32Const, byte(ErrnoNosys), wasm.OpcodeEnd}, + GoFunc: api.GoModuleFunc(func(_ context.Context, _ api.Module, stack []uint64) { stack[0] = uint64(ErrnoNosys) }), }, } } diff --git a/internal/engine/interpreter/interpreter.go b/internal/engine/interpreter/interpreter.go index 819e96ca..64a91b51 100644 --- a/internal/engine/interpreter/interpreter.go +++ b/internal/engine/interpreter/interpreter.go @@ -178,7 +178,6 @@ type code struct { body []*interpreterOp listener experimental.FunctionListener hostFn interface{} - isHostFunction bool ensureTermination bool } @@ -251,7 +250,6 @@ func (e *engine) CompileModule(ctx context.Context, module *wasm.Module, listene compiled.listener = lsn } compiled.source = module - compiled.isHostFunction = ir.IsHostFunction compiled.ensureTermination = ir.EnsureTermination funcs[i] = compiled } @@ -887,7 +885,7 @@ func (ce *callEngine) callNativeFunc(ctx context.Context, callCtx *wasm.CallCont moduleInst := f.source.Module functions := moduleInst.Engine.(*moduleEngine).functions var memoryInst *wasm.MemoryInstance - if f.parent.isHostFunction { + if f.parent.hostFn != nil { memoryInst = ce.callerMemory() } else { memoryInst = moduleInst.Memory @@ -4160,14 +4158,7 @@ func (ce *callEngine) callNativeFunc(ctx context.Context, callCtx *wasm.CallCont // callerMemory returns the caller context memory. func (ce *callEngine) callerMemory() *wasm.MemoryInstance { - // Search through the call frame stack from the top until we find a non host function. - for i := len(ce.frames) - 1; i >= 0; i-- { - f := ce.frames[i].f - if !f.parent.isHostFunction { - return f.source.Module.Memory - } - } - return nil + return ce.frames[len(ce.frames)-1].f.source.Module.Memory } func WasmCompatMax32bits(v1, v2 uint32) uint64 { diff --git a/internal/gojs/goarch/wasm.go b/internal/gojs/goarch/wasm.go index d7d95d88..0ebb023a 100644 --- a/internal/gojs/goarch/wasm.go +++ b/internal/gojs/goarch/wasm.go @@ -20,7 +20,7 @@ func StubFunction(name string) *wasm.HostFunc { Name: name, ParamTypes: []wasm.ValueType{wasm.ValueTypeI32}, ParamNames: []string{"sp"}, - Code: &wasm.Code{IsHostFunction: true, Body: []byte{wasm.OpcodeUnreachable, wasm.OpcodeEnd}}, + Code: &wasm.Code{GoFunc: api.GoModuleFunc(func(ctx context.Context, _ api.Module, stack []uint64) {})}, } } diff --git a/internal/gojs/util/util.go b/internal/gojs/util/util.go index d1a2f08a..83834843 100644 --- a/internal/gojs/util/util.go +++ b/internal/gojs/util/util.go @@ -41,6 +41,6 @@ func NewFunc(name string, goFunc api.GoModuleFunc) *wasm.HostFunc { Name: name, ParamTypes: []api.ValueType{api.ValueTypeI32}, ParamNames: []string{"sp"}, - Code: &wasm.Code{IsHostFunction: true, GoFunc: goFunc}, + Code: &wasm.Code{GoFunc: goFunc}, } } diff --git a/internal/integration_test/bench/hostfunc_bench_test.go b/internal/integration_test/bench/hostfunc_bench_test.go index c8729c2d..c01779a7 100644 --- a/internal/integration_test/bench/hostfunc_bench_test.go +++ b/internal/integration_test/bench/hostfunc_bench_test.go @@ -22,9 +22,6 @@ const ( // callGoReflectHostName is the name of exported function which calls the // Go-implemented host function defined in reflection. callGoReflectHostName = "call_go_reflect_host" - // callWasmHostName is the name of exported function which calls the - // Wasm-implemented host function. - callWasmHostName = "call_wasm_host" ) // BenchmarkHostFunctionCall measures the cost of host function calls whose target functions are either @@ -45,7 +42,7 @@ func BenchmarkHostFunctionCall(b *testing.B) { binary.LittleEndian.PutUint32(m.Memory.Buffer[offset:], math.Float32bits(val)) - for _, fn := range []string{callGoReflectHostName, callGoHostName, callWasmHostName} { + for _, fn := range []string{callGoReflectHostName, callGoHostName} { fn := fn b.Run(fn, func(b *testing.B) { @@ -77,16 +74,12 @@ func TestBenchmarkFunctionCall(t *testing.T) { require.NoError(t, err) }) - callWasmHost, err := getCallEngine(m, callWasmHostName) - require.NoError(t, err) - callGoHost, err := getCallEngine(m, callGoHostName) require.NoError(t, err) callGoReflectHost, err := getCallEngine(m, callGoReflectHostName) require.NoError(t, err) - require.NotNil(t, callWasmHost) require.NotNil(t, callGoHost) require.NotNil(t, callGoReflectHost) @@ -107,7 +100,6 @@ func TestBenchmarkFunctionCall(t *testing.T) { }{ {name: "go", ce: callGoHost}, {name: "go-reflect", ce: callGoReflectHost}, - {name: "wasm", ce: callWasmHost}, } { f := f t.Run(f.name, func(t *testing.T) { @@ -145,10 +137,9 @@ func setupHostCallBench(requireNoError func(error)) *wasm.ModuleInstance { // Build the host module. hostModule := &wasm.Module{ TypeSection: []*wasm.FunctionType{ft}, - FunctionSection: []wasm.Index{0, 0, 0}, + FunctionSection: []wasm.Index{0, 0}, CodeSection: []*wasm.Code{ { - IsHostFunction: true, GoFunc: api.GoModuleFunc(func(_ context.Context, mod api.Module, stack []uint64) { ret, ok := mod.Memory().ReadUint32Le(uint32(stack[0])) if !ok { @@ -166,20 +157,10 @@ func setupHostCallBench(requireNoError func(error)) *wasm.ModuleInstance { return math.Float32frombits(ret) }, ), - { - IsHostFunction: true, - Body: []byte{ - wasm.OpcodeLocalGet, 0, - wasm.OpcodeI32Load, 0x2, 0x0, // offset = 0 - wasm.OpcodeF32ReinterpretI32, - wasm.OpcodeEnd, - }, - }, }, ExportSection: []wasm.Export{ {Name: "go", Type: wasm.ExternTypeFunc, Index: 0}, {Name: "go-reflect", Type: wasm.ExternTypeFunc, Index: 1}, - {Name: "wasm", Type: wasm.ExternTypeFunc, Index: 2}, }, ID: wasm.ModuleID{1, 2, 3, 4, 5}, } @@ -212,7 +193,6 @@ func setupHostCallBench(requireNoError func(error)) *wasm.ModuleInstance { ExportSection: []wasm.Export{ {Name: callGoHostName, Type: wasm.ExternTypeFunc, Index: 3}, {Name: callGoReflectHostName, Type: wasm.ExternTypeFunc, Index: 4}, - {Name: callWasmHostName, Type: wasm.ExternTypeFunc, Index: 5}, }, CodeSection: []*wasm.Code{ {Body: []byte{wasm.OpcodeLocalGet, 0, wasm.OpcodeCall, 0, wasm.OpcodeEnd}}, // Calling the index 0 = host.go. diff --git a/internal/testing/enginetest/enginetest.go b/internal/testing/enginetest/enginetest.go index 83e8c84a..d170027f 100644 --- a/internal/testing/enginetest/enginetest.go +++ b/internal/testing/enginetest/enginetest.go @@ -311,7 +311,6 @@ func runTestModuleEngine_Call_HostFn_Mem(t *testing.T, et EngineTester, readMem func RunTestModuleEngine_Call_HostFn(t *testing.T, et EngineTester) { t.Run("wasm", func(t *testing.T) { runTestModuleEngine_Call_HostFn(t, et, hostDivByWasm) - runTestModuleEngine_Call_HostFn_Mem(t, et, hostReadMemWasm) }) t.Run("go", func(t *testing.T) { runTestModuleEngine_Call_HostFn(t, et, hostDivByGo) @@ -617,7 +616,7 @@ var hostDivByGo = wasm.MustParseGoReflectFuncCode(divByGo) // (func (export "div_by.wasm") (param i32) (result i32) (i32.div_u (i32.const 1) (local.get 0))) var ( divByWasm = []byte{wasm.OpcodeI32Const, 1, wasm.OpcodeLocalGet, 0, wasm.OpcodeI32DivU, wasm.OpcodeEnd} - hostDivByWasm = &wasm.Code{IsHostFunction: true, Body: divByWasm} + hostDivByWasm = &wasm.Code{Body: divByWasm} ) const ( @@ -635,12 +634,6 @@ func readMemGo(_ context.Context, m api.Module) uint64 { var hostReadMemGo = wasm.MustParseGoReflectFuncCode(readMemGo) -// (func (export "wasm_read_mem") (result i64) i32.const 0 i64.load) -var ( - readMemWasm = []byte{wasm.OpcodeI32Const, 0, wasm.OpcodeI64Load, 0x3, 0x0, wasm.OpcodeEnd} - hostReadMemWasm = &wasm.Code{IsHostFunction: true, Body: readMemWasm} -) - func setupCallTests(t *testing.T, e wasm.Engine, divBy *wasm.Code, fnlf experimental.FunctionListenerFactory) (*wasm.ModuleInstance, *wasm.ModuleInstance, *wasm.ModuleInstance, func()) { ft := &wasm.FunctionType{Params: []wasm.ValueType{i32}, Results: []wasm.ValueType{i32}, ParamNumInUint64: 1, ResultNumInUint64: 1} diff --git a/internal/wasm/func_validation.go b/internal/wasm/func_validation.go index 9c5064eb..89cd683b 100644 --- a/internal/wasm/func_validation.go +++ b/internal/wasm/func_validation.go @@ -95,7 +95,7 @@ func (m *Module) validateFunctionWithMaxStackValues( } if OpcodeI32Load <= op && op <= OpcodeI64Store32 { - if memory == nil && !code.IsHostFunction { + if memory == nil { return fmt.Errorf("memory must exist for %s", InstructionName(op)) } pc++ @@ -277,7 +277,7 @@ func (m *Module) validateFunctionWithMaxStackValues( } } } else if OpcodeMemorySize <= op && op <= OpcodeMemoryGrow { - if memory == nil && !code.IsHostFunction { + if memory == nil { return fmt.Errorf("memory must exist for %s", InstructionName(op)) } pc++ @@ -1113,7 +1113,7 @@ func (m *Module) validateFunctionWithMaxStackValues( OpcodeVecV128Load32x2s, OpcodeVecV128Load32x2u, OpcodeVecV128Load8Splat, OpcodeVecV128Load16Splat, OpcodeVecV128Load32Splat, OpcodeVecV128Load64Splat, OpcodeVecV128Load32zero, OpcodeVecV128Load64zero: - if memory == nil && !code.IsHostFunction { + if memory == nil { return fmt.Errorf("memory must exist for %s", VectorInstructionName(vecOpcode)) } pc++ @@ -1151,7 +1151,7 @@ func (m *Module) validateFunctionWithMaxStackValues( } valueTypeStack.push(ValueTypeV128) case OpcodeVecV128Store: - if memory == nil && !code.IsHostFunction { + if memory == nil { return fmt.Errorf("memory must exist for %s", VectorInstructionName(vecOpcode)) } pc++ @@ -1170,7 +1170,7 @@ func (m *Module) validateFunctionWithMaxStackValues( return fmt.Errorf("cannot pop the operand for %s: %v", OpcodeVecV128StoreName, err) } case OpcodeVecV128Load8Lane, OpcodeVecV128Load16Lane, OpcodeVecV128Load32Lane, OpcodeVecV128Load64Lane: - if memory == nil && !code.IsHostFunction { + if memory == nil { return fmt.Errorf("memory must exist for %s", VectorInstructionName(vecOpcode)) } attr := vecLoadLanes[vecOpcode] @@ -1198,7 +1198,7 @@ func (m *Module) validateFunctionWithMaxStackValues( } valueTypeStack.push(ValueTypeV128) case OpcodeVecV128Store8Lane, OpcodeVecV128Store16Lane, OpcodeVecV128Store32Lane, OpcodeVecV128Store64Lane: - if memory == nil && !code.IsHostFunction { + if memory == nil { return fmt.Errorf("memory must exist for %s", VectorInstructionName(vecOpcode)) } attr := vecStoreLanes[vecOpcode] diff --git a/internal/wasm/gofunc.go b/internal/wasm/gofunc.go index c98ce1a0..2c75c34b 100644 --- a/internal/wasm/gofunc.go +++ b/internal/wasm/gofunc.go @@ -254,7 +254,7 @@ func parseGoReflectFunc(fn interface{}) (params, results []ValueType, code *Code return } - code = &Code{IsHostFunction: true} + code = &Code{} if pk == paramsKindContextModule { code.GoFunc = &reflectGoModuleFunction{fn: &fnV, params: params, results: results} } else { diff --git a/internal/wasm/host.go b/internal/wasm/host.go index 15e542b6..311982fd 100644 --- a/internal/wasm/host.go +++ b/internal/wasm/host.go @@ -49,14 +49,14 @@ func (f *HostFunc) MustGoReflectFunc(fn interface{}) *HostFunc { // WithGoFunc returns a copy of the function, replacing its Code.GoFunc. func (f *HostFunc) WithGoFunc(fn api.GoFunc) *HostFunc { ret := *f - ret.Code = &Code{IsHostFunction: true, GoFunc: fn} + ret.Code = &Code{GoFunc: fn} return &ret } // WithGoModuleFunc returns a copy of the function, replacing its Code.GoFunc. func (f *HostFunc) WithGoModuleFunc(fn api.GoModuleFunc) *HostFunc { ret := *f - ret.Code = &Code{IsHostFunction: true, GoFunc: fn} + ret.Code = &Code{GoFunc: fn} return &ret } @@ -68,16 +68,6 @@ func (f *HostFunc) WithGoReflectFunc(fn interface{}) (*HostFunc, error) { return &ret, err } -// WithWasm returns a copy of the function, replacing its Code.Body. -func (f *HostFunc) WithWasm(body []byte) *HostFunc { - ret := *f - ret.Code = &Code{IsHostFunction: true, Body: body} - if f.Code != nil { - ret.Code.LocalTypes = f.Code.LocalTypes - } - return &ret -} - type HostFuncNames struct { Name string ParamNames []string diff --git a/internal/wasm/host_test.go b/internal/wasm/host_test.go index c675d692..dc86a5ac 100644 --- a/internal/wasm/host_test.go +++ b/internal/wasm/host_test.go @@ -142,7 +142,6 @@ func requireHostModuleEquals(t *testing.T, expected, actual *Module) { require.Equal(t, len(expected.CodeSection), len(actual.CodeSection)) for i, c := range expected.CodeSection { actualCode := actual.CodeSection[i] - require.True(t, actualCode.IsHostFunction) require.Equal(t, c.GoFunc, actualCode.GoFunc) // Not wasm diff --git a/internal/wasm/module.go b/internal/wasm/module.go index e19bc71d..9d4bea7f 100644 --- a/internal/wasm/module.go +++ b/internal/wasm/module.go @@ -835,15 +835,6 @@ type Export struct { // Code is an entry in the Module.CodeSection containing the locals and body of the function. // See https://www.w3.org/TR/2019/REC-wasm-core-1-20191205/#binary-code type Code struct { - // IsHostFunction returns true if the function was implemented by the - // embedder (ex via wazero.HostModuleBuilder) instead of a wasm binary. - // - // Notably, host functions can use the caller's memory, which might be - // different from its defining module. - // - // See https://www.w3.org/TR/wasm-core-1/#host-functions%E2%91%A0 - IsHostFunction bool - // LocalTypes are any function-scoped variables in insertion order. // See https://www.w3.org/TR/2019/REC-wasm-core-1-20191205/#binary-local LocalTypes []ValueType diff --git a/internal/wazeroir/compiler.go b/internal/wazeroir/compiler.go index 529528b2..a8d75400 100644 --- a/internal/wazeroir/compiler.go +++ b/internal/wazeroir/compiler.go @@ -209,10 +209,6 @@ func (c *compiler) resetUnreachable() { } type CompilationResult struct { - // IsHostFunction is the data returned by the same field documented on - // wasm.Code. - IsHostFunction bool - // GoFunc is the data returned by the same field documented on wasm.Code. // In this case, IsHostFunction is true and other fields can be ignored. GoFunc interface{} @@ -284,6 +280,7 @@ func CompileFunctions(enabledFeatures api.CoreFeatures, callFrameStackSizeInUint wasmTypes: types, } + var goFuncExists bool controlFramesStack := &controlFrames{} var ret []*CompilationResult for funcIndex := range module.FunctionSection { @@ -295,13 +292,17 @@ func CompileFunctions(enabledFeatures api.CoreFeatures, callFrameStackSizeInUint _, usesMemory := code.GoFunc.(api.GoModuleFunction) ret = append(ret, &CompilationResult{ - IsHostFunction: true, - UsesMemory: usesMemory, - GoFunc: code.GoFunc, - Signature: sig, + UsesMemory: usesMemory, + GoFunc: code.GoFunc, + Signature: sig, }) + goFuncExists = true continue } + + if goFuncExists { + panic("BUG: host functions must be implemented as Go functions") + } r, err := compile(enabledFeatures, callFrameStackSizeInUint64, sig, code.Body, code.LocalTypes, types, functions, globals, code.BodyOffsetInCodeSection, module.DWARFLines != nil, ensureTermination, funcTypeToSigs, controlFramesStack) @@ -309,7 +310,6 @@ func CompileFunctions(enabledFeatures api.CoreFeatures, callFrameStackSizeInUint def := module.FunctionDefinitionSection[uint32(funcIndex)+module.ImportFuncCount()] return nil, fmt.Errorf("failed to lower func[%s] to wazeroir: %w", def.DebugName(), err) } - r.IsHostFunction = code.IsHostFunction r.Globals = globals r.Functions = functions r.Types = types diff --git a/internal/wazeroir/compiler_test.go b/internal/wazeroir/compiler_test.go index 7b4cc4f6..2d3f1804 100644 --- a/internal/wazeroir/compiler_test.go +++ b/internal/wazeroir/compiler_test.go @@ -63,10 +63,9 @@ func TestCompile(t *testing.T) { module: &wasm.Module{ TypeSection: []*wasm.FunctionType{v_v}, FunctionSection: []wasm.Index{0}, - CodeSection: []*wasm.Code{{IsHostFunction: true, Body: []byte{wasm.OpcodeEnd}}}, + CodeSection: []*wasm.Code{{Body: []byte{wasm.OpcodeEnd}}}, }, expected: &CompilationResult{ - IsHostFunction: true, Operations: []Operation{ // begin with params: [] OperationBr{Target: Label{Kind: LabelKindReturn}}, // return! }, @@ -84,7 +83,7 @@ func TestCompile(t *testing.T) { FunctionSection: []wasm.Index{0}, CodeSection: []*wasm.Code{wasm.MustParseGoReflectFuncCode(func() {})}, }, - expected: &CompilationResult{IsHostFunction: true}, + expected: &CompilationResult{}, }, { name: "host go context.Context api.Module uses memory", @@ -93,7 +92,7 @@ func TestCompile(t *testing.T) { FunctionSection: []wasm.Index{0}, CodeSection: []*wasm.Code{wasm.MustParseGoReflectFuncCode(func(context.Context, api.Module) {})}, }, - expected: &CompilationResult{IsHostFunction: true, UsesMemory: true}, + expected: &CompilationResult{UsesMemory: true}, }, { name: "identity", @@ -157,7 +156,7 @@ func TestCompile(t *testing.T) { module: &wasm.Module{ TypeSection: []*wasm.FunctionType{v_v}, FunctionSection: []wasm.Index{0}, - CodeSection: []*wasm.Code{{IsHostFunction: true, Body: []byte{ + CodeSection: []*wasm.Code{{Body: []byte{ wasm.OpcodeI32Const, 8, // memory offset to load wasm.OpcodeI32Load, 0x2, 0x0, // load alignment=2 (natural alignment) staticOffset=0 wasm.OpcodeDrop, @@ -165,7 +164,6 @@ func TestCompile(t *testing.T) { }}}, }, expected: &CompilationResult{ - IsHostFunction: true, Operations: []Operation{ // begin with params: [] OperationConstI32{Value: 8}, // [8] OperationLoad{Type: UnsignedTypeI32, Arg: MemoryArg{Alignment: 2, Offset: 0}}, // [x] @@ -231,7 +229,6 @@ func TestCompile(t *testing.T) { fn := res[0] if fn.GoFunc != nil { // can't compare functions // Special case because reflect.Value can't be compared with Equals - require.True(t, fn.IsHostFunction) require.Equal(t, tc.expected.UsesMemory, fn.UsesMemory) require.Equal(t, &tc.module.CodeSection[0].GoFunc, &fn.GoFunc) } else {