wazevo: supports for LookupFunction API (#1704)
Signed-off-by: Takeshi Yoneda <t.y.mathetake@gmail.com>
This commit is contained in:
@@ -53,11 +53,6 @@ func TestCompiler_MemoryGrowInRecursiveCall(t *testing.T) {
|
||||
enginetest.RunTestEngineMemoryGrowInRecursiveCall(t, et)
|
||||
}
|
||||
|
||||
func TestCompiler_ModuleEngine_LookupFunction(t *testing.T) {
|
||||
defer functionLog.Reset()
|
||||
enginetest.RunTestModuleEngineLookupFunction(t, et)
|
||||
}
|
||||
|
||||
func TestCompiler_ModuleEngine_Call(t *testing.T) {
|
||||
defer functionLog.Reset()
|
||||
requireSupportedOSArch(t)
|
||||
|
||||
@@ -92,10 +92,6 @@ func TestInterpreter_Engine_NewModuleEngine(t *testing.T) {
|
||||
enginetest.RunTestEngineNewModuleEngine(t, et)
|
||||
}
|
||||
|
||||
func TestInterpreter_ModuleEngine_LookupFunction(t *testing.T) {
|
||||
enginetest.RunTestModuleEngineLookupFunction(t, et)
|
||||
}
|
||||
|
||||
func TestInterpreter_ModuleEngine_Call(t *testing.T) {
|
||||
defer functionLog.Reset()
|
||||
enginetest.RunTestModuleEngineCall(t, et)
|
||||
|
||||
@@ -141,6 +141,10 @@ func (c *callEngine) CallWithStack(ctx context.Context, paramResultStack []uint6
|
||||
err = builder.FromRecovered(r)
|
||||
|
||||
// TODO: Abort listener.
|
||||
} else {
|
||||
if err != wasmruntime.ErrRuntimeStackOverflow { // Stackoverflow case shouldn't be panic (to avoid extreme stack unwinding).
|
||||
err = c.parent.module.FailIfClosed()
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
@@ -212,7 +216,7 @@ func (c *callEngine) CallWithStack(ctx context.Context, paramResultStack []uint6
|
||||
}
|
||||
|
||||
func (c *callEngine) callerModuleInstance() *wasm.ModuleInstance {
|
||||
return *(**wasm.ModuleInstance)(unsafe.Pointer(c.execCtx.callerModuleContextPtr))
|
||||
return moduleInstanceFromOpaquePtr(c.execCtx.callerModuleContextPtr)
|
||||
}
|
||||
|
||||
func opaqueViewFromPtr(ptr uintptr) []byte {
|
||||
|
||||
@@ -27,12 +27,12 @@ const (
|
||||
f64 = wasm.ValueTypeF64
|
||||
)
|
||||
|
||||
// TODO: migrate to integration_test/spectest/v1/spec_test.go by the time when closing https://github.com/tetratelabs/wazero/issues/1496
|
||||
func TestSpectestV1(t *testing.T) {
|
||||
config := wazero.NewRuntimeConfigCompiler().WithCoreFeatures(api.CoreFeaturesV1)
|
||||
// Configure the new optimizing backend!
|
||||
wazevo.ConfigureWazevo(config)
|
||||
|
||||
// TODO: migrate to integration_test/spectest/v1/spec_test.go by the time when closing https://github.com/tetratelabs/wazero/issues/1496
|
||||
for _, tc := range []struct {
|
||||
name string
|
||||
}{
|
||||
@@ -120,6 +120,7 @@ func TestSpectestV1(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: migrate to integration_test/spectest/v2/spec_test.go by the time when closing https://github.com/tetratelabs/wazero/issues/1496
|
||||
func TestSpectestV2(t *testing.T) {
|
||||
config := wazero.NewRuntimeConfigCompiler().WithCoreFeatures(api.CoreFeaturesV2)
|
||||
// Configure the new optimizing backend!
|
||||
|
||||
@@ -3,6 +3,7 @@ package wazevo
|
||||
import (
|
||||
"context"
|
||||
"encoding/hex"
|
||||
"errors"
|
||||
"fmt"
|
||||
"runtime"
|
||||
"sort"
|
||||
@@ -464,7 +465,7 @@ func (e *engine) NewModuleEngine(m *wasm.Module, mi *wasm.ModuleInstance) (wasm.
|
||||
|
||||
compiled, ok := e.compiledModules[m.ID]
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("binary of module %q is not compiled", mi.ModuleName)
|
||||
return nil, errors.New("source module must be compiled before instantiation")
|
||||
}
|
||||
me.parent = compiled
|
||||
me.module = mi
|
||||
|
||||
@@ -7,6 +7,7 @@ import (
|
||||
"github.com/tetratelabs/wazero/api"
|
||||
"github.com/tetratelabs/wazero/internal/engine/wazevo/wazevoapi"
|
||||
"github.com/tetratelabs/wazero/internal/wasm"
|
||||
"github.com/tetratelabs/wazero/internal/wasmruntime"
|
||||
)
|
||||
|
||||
type (
|
||||
@@ -25,6 +26,7 @@ type (
|
||||
executable *byte
|
||||
moduleContextOpaquePtr *byte
|
||||
typeID wasm.FunctionTypeID
|
||||
indexInModule wasm.Index
|
||||
}
|
||||
|
||||
importedFunction struct {
|
||||
@@ -217,15 +219,16 @@ func (m *moduleEngine) FunctionInstanceReference(funcIndex wasm.Index) wasm.Refe
|
||||
begin, _, _ := m.parent.offsets.ImportedFunctionOffset(funcIndex)
|
||||
return uintptr(unsafe.Pointer(&m.opaque[begin]))
|
||||
}
|
||||
funcIndex -= m.module.Source.ImportFunctionCount
|
||||
localIndex := funcIndex - m.module.Source.ImportFunctionCount
|
||||
p := m.parent
|
||||
executable := &p.executable[p.functionOffsets[funcIndex].nativeBegin()]
|
||||
typeID := m.module.TypeIDs[m.module.Source.FunctionSection[funcIndex]]
|
||||
executable := &p.executable[p.functionOffsets[localIndex].nativeBegin()]
|
||||
typeID := m.module.TypeIDs[m.module.Source.FunctionSection[localIndex]]
|
||||
|
||||
lf := &functionInstance{
|
||||
executable: executable,
|
||||
moduleContextOpaquePtr: m.opaquePtr,
|
||||
typeID: typeID,
|
||||
indexInModule: funcIndex,
|
||||
}
|
||||
m.localFunctionInstances = append(m.localFunctionInstances, lf)
|
||||
return uintptr(unsafe.Pointer(lf))
|
||||
@@ -233,5 +236,33 @@ func (m *moduleEngine) FunctionInstanceReference(funcIndex wasm.Index) wasm.Refe
|
||||
|
||||
// LookupFunction implements wasm.ModuleEngine.
|
||||
func (m *moduleEngine) LookupFunction(t *wasm.TableInstance, typeId wasm.FunctionTypeID, tableOffset wasm.Index) (*wasm.ModuleInstance, wasm.Index) {
|
||||
panic("TODO")
|
||||
if tableOffset >= uint32(len(t.References)) || t.Type != wasm.RefTypeFuncref {
|
||||
panic(wasmruntime.ErrRuntimeInvalidTableAccess)
|
||||
}
|
||||
rawPtr := t.References[tableOffset]
|
||||
if rawPtr == 0 {
|
||||
panic(wasmruntime.ErrRuntimeInvalidTableAccess)
|
||||
}
|
||||
|
||||
tf := functionFromUintptr(rawPtr)
|
||||
if tf.typeID != typeId {
|
||||
panic(wasmruntime.ErrRuntimeIndirectCallTypeMismatch)
|
||||
}
|
||||
return moduleInstanceFromOpaquePtr(tf.moduleContextOpaquePtr), tf.indexInModule
|
||||
}
|
||||
|
||||
// functionFromUintptr resurrects the original *function from the given uintptr
|
||||
// which comes from either funcref table or OpcodeRefFunc instruction.
|
||||
func functionFromUintptr(ptr uintptr) *functionInstance {
|
||||
// Wraps ptrs as the double pointer in order to avoid the unsafe access as detected by race detector.
|
||||
//
|
||||
// For example, if we have (*function)(unsafe.Pointer(ptr)) instead, then the race detector's "checkptr"
|
||||
// subroutine wanrs as "checkptr: pointer arithmetic result points to invalid allocation"
|
||||
// https://github.com/golang/go/blob/1ce7fcf139417d618c2730010ede2afb41664211/src/runtime/checkptr.go#L69
|
||||
var wrapped *uintptr = &ptr
|
||||
return *(**functionInstance)(unsafe.Pointer(wrapped))
|
||||
}
|
||||
|
||||
func moduleInstanceFromOpaquePtr(ptr *byte) *wasm.ModuleInstance {
|
||||
return *(**wasm.ModuleInstance)(unsafe.Pointer(ptr))
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
"context"
|
||||
_ "embed"
|
||||
"math"
|
||||
"runtime"
|
||||
"strconv"
|
||||
"testing"
|
||||
"time"
|
||||
@@ -11,11 +12,14 @@ import (
|
||||
|
||||
"github.com/tetratelabs/wazero"
|
||||
"github.com/tetratelabs/wazero/api"
|
||||
"github.com/tetratelabs/wazero/experimental/table"
|
||||
"github.com/tetratelabs/wazero/internal/engine/wazevo"
|
||||
"github.com/tetratelabs/wazero/internal/platform"
|
||||
"github.com/tetratelabs/wazero/internal/testing/binaryencoding"
|
||||
"github.com/tetratelabs/wazero/internal/testing/proxy"
|
||||
"github.com/tetratelabs/wazero/internal/testing/require"
|
||||
"github.com/tetratelabs/wazero/internal/wasm"
|
||||
"github.com/tetratelabs/wazero/internal/wasmruntime"
|
||||
"github.com/tetratelabs/wazero/sys"
|
||||
)
|
||||
|
||||
@@ -30,43 +34,62 @@ var memoryCapacityPages = uint32(2)
|
||||
|
||||
var moduleConfig = wazero.NewModuleConfig()
|
||||
|
||||
var tests = map[string]func(t *testing.T, r wazero.Runtime){
|
||||
"huge stack": testHugeStack,
|
||||
"unreachable": testUnreachable,
|
||||
"recursive entry": testRecursiveEntry,
|
||||
"host func memory": testHostFuncMemory,
|
||||
"host function with context parameter": testHostFunctionContextParameter,
|
||||
"host function with nested context": testNestedGoContext,
|
||||
"host function with numeric parameter": testHostFunctionNumericParameter,
|
||||
"close module with in-flight calls": testCloseInFlight,
|
||||
"multiple instantiation from same source": testMultipleInstantiation,
|
||||
"exported function that grows memory": testMemOps,
|
||||
"import functions with reference type in signature": testReftypeImports,
|
||||
"overflow integer addition": testOverflow,
|
||||
"un-signed extend global": testGlobalExtend,
|
||||
"user-defined primitive in host func": testUserDefinedPrimitiveHostFunc,
|
||||
"ensures invocations terminate on module close": testEnsureTerminationOnClose,
|
||||
"call host function indirectly": callHostFunctionIndirect,
|
||||
type testCase struct {
|
||||
f func(t *testing.T, r wazero.Runtime)
|
||||
wazevoSkip bool
|
||||
}
|
||||
|
||||
var tests = map[string]testCase{
|
||||
"huge stack": {f: testHugeStack, wazevoSkip: true},
|
||||
"unreachable": {f: testUnreachable},
|
||||
"recursive entry": {f: testRecursiveEntry},
|
||||
"host func memory": {f: testHostFuncMemory},
|
||||
"host function with context parameter": {f: testHostFunctionContextParameter},
|
||||
"host function with nested context": {f: testNestedGoContext},
|
||||
"host function with numeric parameter": {f: testHostFunctionNumericParameter},
|
||||
"close module with in-flight calls": {f: testCloseInFlight},
|
||||
"multiple instantiation from same source": {f: testMultipleInstantiation},
|
||||
"exported function that grows memory": {f: testMemOps, wazevoSkip: true},
|
||||
"import functions with reference type in signature": {f: testReftypeImports, wazevoSkip: true},
|
||||
"overflow integer addition": {f: testOverflow},
|
||||
"un-signed extend global": {f: testGlobalExtend},
|
||||
"user-defined primitive in host func": {f: testUserDefinedPrimitiveHostFunc},
|
||||
"ensures invocations terminate on module close": {f: testEnsureTerminationOnClose, wazevoSkip: true},
|
||||
"call host function indirectly": {f: callHostFunctionIndirect, wazevoSkip: true},
|
||||
"lookup function": {f: testLookupFunction},
|
||||
}
|
||||
|
||||
func TestEngineCompiler(t *testing.T) {
|
||||
if !platform.CompilerSupported() {
|
||||
t.Skip()
|
||||
}
|
||||
runAllTests(t, tests, wazero.NewRuntimeConfigCompiler().WithCloseOnContextDone(true))
|
||||
runAllTests(t, tests, wazero.NewRuntimeConfigCompiler().WithCloseOnContextDone(true), false)
|
||||
}
|
||||
|
||||
func TestEngineInterpreter(t *testing.T) {
|
||||
runAllTests(t, tests, wazero.NewRuntimeConfigInterpreter().WithCloseOnContextDone(true))
|
||||
runAllTests(t, tests, wazero.NewRuntimeConfigInterpreter().WithCloseOnContextDone(true), false)
|
||||
}
|
||||
|
||||
func runAllTests(t *testing.T, tests map[string]func(t *testing.T, r wazero.Runtime), config wazero.RuntimeConfig) {
|
||||
for name, testf := range tests {
|
||||
name := name // pin
|
||||
testf := testf // pin
|
||||
func TestEngineWazevo(t *testing.T) {
|
||||
if runtime.GOARCH != "arm64" {
|
||||
t.Skip()
|
||||
}
|
||||
config := wazero.NewRuntimeConfigInterpreter()
|
||||
wazevo.ConfigureWazevo(config)
|
||||
runAllTests(t, tests, config.WithCloseOnContextDone(true), true)
|
||||
}
|
||||
|
||||
func runAllTests(t *testing.T, tests map[string]testCase, config wazero.RuntimeConfig, isWazevo bool) {
|
||||
for name, tc := range tests {
|
||||
name := name
|
||||
tc := tc
|
||||
if isWazevo && tc.wazevoSkip {
|
||||
t.Logf("skipping %s because it is not supported by wazevo", name)
|
||||
continue
|
||||
}
|
||||
t.Run(name, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
testf(t, wazero.NewRuntimeWithConfig(testCtx, config))
|
||||
tc.f(t, wazero.NewRuntimeWithConfig(testCtx, config))
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -798,3 +821,61 @@ func testMultipleInstantiation(t *testing.T, r wazero.Runtime) {
|
||||
require.Equal(t, uint64(1000), after)
|
||||
}
|
||||
}
|
||||
|
||||
func testLookupFunction(t *testing.T, r wazero.Runtime) {
|
||||
bin := binaryencoding.EncodeModule(&wasm.Module{
|
||||
TypeSection: []wasm.FunctionType{{Results: []wasm.ValueType{i32}}},
|
||||
FunctionSection: []wasm.Index{0, 0, 0},
|
||||
CodeSection: []wasm.Code{
|
||||
{Body: []byte{wasm.OpcodeI32Const, 1, wasm.OpcodeEnd}},
|
||||
{Body: []byte{wasm.OpcodeI32Const, 2, wasm.OpcodeEnd}},
|
||||
{Body: []byte{wasm.OpcodeI32Const, 3, wasm.OpcodeEnd}},
|
||||
},
|
||||
TableSection: []wasm.Table{{Min: 10, Type: wasm.RefTypeFuncref}},
|
||||
ElementSection: []wasm.ElementSegment{
|
||||
{
|
||||
OffsetExpr: wasm.ConstantExpression{
|
||||
Opcode: wasm.OpcodeI32Const,
|
||||
Data: []byte{0},
|
||||
},
|
||||
TableIndex: 0,
|
||||
Init: []wasm.Index{2, 0},
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
inst, err := r.Instantiate(testCtx, bin)
|
||||
require.NoError(t, err)
|
||||
|
||||
t.Run("null reference", func(t *testing.T) {
|
||||
err = require.CapturePanic(func() {
|
||||
table.LookupFunction(inst, 0, 3, nil, []wasm.ValueType{i32})
|
||||
})
|
||||
require.Equal(t, wasmruntime.ErrRuntimeInvalidTableAccess, err)
|
||||
})
|
||||
|
||||
t.Run("out of range", func(t *testing.T) {
|
||||
err = require.CapturePanic(func() {
|
||||
table.LookupFunction(inst, 0, 1000, nil, []wasm.ValueType{i32})
|
||||
})
|
||||
require.Equal(t, wasmruntime.ErrRuntimeInvalidTableAccess, err)
|
||||
})
|
||||
|
||||
t.Run("type mismatch", func(t *testing.T) {
|
||||
err = require.CapturePanic(func() {
|
||||
table.LookupFunction(inst, 0, 0, []wasm.ValueType{i32}, nil)
|
||||
})
|
||||
require.Equal(t, wasmruntime.ErrRuntimeIndirectCallTypeMismatch, err)
|
||||
})
|
||||
t.Run("ok", func(t *testing.T) {
|
||||
f2 := table.LookupFunction(inst, 0, 0, nil, []wasm.ValueType{i32})
|
||||
res, err := f2.Call(testCtx)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, uint64(3), res[0])
|
||||
|
||||
f0 := table.LookupFunction(inst, 0, 1, nil, []wasm.ValueType{i32})
|
||||
res, err = f0.Call(testCtx)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, uint64(1), res[0])
|
||||
})
|
||||
}
|
||||
|
||||
@@ -2,32 +2,43 @@ package adhoc
|
||||
|
||||
import (
|
||||
"context"
|
||||
"runtime"
|
||||
"sync"
|
||||
"testing"
|
||||
|
||||
"github.com/tetratelabs/wazero"
|
||||
"github.com/tetratelabs/wazero/api"
|
||||
"github.com/tetratelabs/wazero/internal/engine/wazevo"
|
||||
"github.com/tetratelabs/wazero/internal/platform"
|
||||
"github.com/tetratelabs/wazero/internal/testing/hammer"
|
||||
"github.com/tetratelabs/wazero/internal/testing/require"
|
||||
"github.com/tetratelabs/wazero/sys"
|
||||
)
|
||||
|
||||
var hammers = map[string]func(t *testing.T, r wazero.Runtime){
|
||||
var hammers = map[string]testCase{
|
||||
// Tests here are similar to what's described in /RATIONALE.md, but deviate as they involve blocking functions.
|
||||
"close importing module while in use": closeImportingModuleWhileInUse,
|
||||
"close imported module while in use": closeImportedModuleWhileInUse,
|
||||
"close importing module while in use": {f: closeImportingModuleWhileInUse, wazevoSkip: true},
|
||||
"close imported module while in use": {f: closeImportedModuleWhileInUse, wazevoSkip: true},
|
||||
}
|
||||
|
||||
func TestEngineCompiler_hammer(t *testing.T) {
|
||||
if !platform.CompilerSupported() {
|
||||
t.Skip()
|
||||
}
|
||||
runAllTests(t, hammers, wazero.NewRuntimeConfigCompiler())
|
||||
runAllTests(t, hammers, wazero.NewRuntimeConfigCompiler(), false)
|
||||
}
|
||||
|
||||
func TestEngineInterpreter_hammer(t *testing.T) {
|
||||
runAllTests(t, hammers, wazero.NewRuntimeConfigInterpreter())
|
||||
runAllTests(t, hammers, wazero.NewRuntimeConfigInterpreter(), false)
|
||||
}
|
||||
|
||||
func TestEngineWazevo_hammer(t *testing.T) {
|
||||
if runtime.GOARCH != "arm64" {
|
||||
t.Skip()
|
||||
}
|
||||
c := wazero.NewRuntimeConfigInterpreter()
|
||||
wazevo.ConfigureWazevo(c)
|
||||
runAllTests(t, hammers, c, true)
|
||||
}
|
||||
|
||||
func closeImportingModuleWhileInUse(t *testing.T, r wazero.Runtime) {
|
||||
|
||||
@@ -16,6 +16,9 @@
|
||||
//
|
||||
// Note: These tests intentionally avoid using wasm.Store as it is important to know both the dependencies and
|
||||
// the capabilities at the wasm.Engine abstraction.
|
||||
//
|
||||
// TODO: the purpose of enginetest overlaps with the purpose of internal/integration_test/engine. We should
|
||||
// migrate there since the tests here are costly maintenance-wise.
|
||||
package enginetest
|
||||
|
||||
import (
|
||||
@@ -33,7 +36,6 @@ import (
|
||||
"github.com/tetratelabs/wazero/internal/u64"
|
||||
"github.com/tetratelabs/wazero/internal/wasm"
|
||||
"github.com/tetratelabs/wazero/internal/wasmdebug"
|
||||
"github.com/tetratelabs/wazero/internal/wasmruntime"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -235,89 +237,6 @@ func RunTestModuleEngineCallWithStack(t *testing.T, et EngineTester) {
|
||||
})
|
||||
}
|
||||
|
||||
func RunTestModuleEngineLookupFunction(t *testing.T, et EngineTester) {
|
||||
e := et.NewEngine(api.CoreFeaturesV1)
|
||||
|
||||
mod := &wasm.Module{
|
||||
TypeSection: []wasm.FunctionType{{}, {Params: []wasm.ValueType{wasm.ValueTypeV128}}},
|
||||
FunctionSection: []wasm.Index{0, 0, 0},
|
||||
CodeSection: []wasm.Code{
|
||||
{
|
||||
Body: []byte{wasm.OpcodeEnd},
|
||||
}, {Body: []byte{wasm.OpcodeEnd}}, {Body: []byte{wasm.OpcodeEnd}},
|
||||
},
|
||||
}
|
||||
|
||||
err := e.CompileModule(testCtx, mod, nil, false)
|
||||
require.NoError(t, err)
|
||||
m := &wasm.ModuleInstance{
|
||||
TypeIDs: []wasm.FunctionTypeID{0, 1},
|
||||
Source: mod,
|
||||
}
|
||||
m.Tables = []*wasm.TableInstance{
|
||||
{Min: 2, References: make([]wasm.Reference, 2), Type: wasm.RefTypeFuncref},
|
||||
{Min: 2, References: make([]wasm.Reference, 2), Type: wasm.RefTypeExternref},
|
||||
{Min: 10, References: make([]wasm.Reference, 10), Type: wasm.RefTypeFuncref},
|
||||
}
|
||||
|
||||
me, err := e.NewModuleEngine(mod, m)
|
||||
require.NoError(t, err)
|
||||
linkModuleToEngine(m, me)
|
||||
|
||||
t.Run("null reference", func(t *testing.T) {
|
||||
err = require.CapturePanic(func() {
|
||||
m.LookupFunction(m.Tables[0], m.TypeIDs[0], 0) // offset 0 is not initialized yet.
|
||||
})
|
||||
require.Equal(t, wasmruntime.ErrRuntimeInvalidTableAccess, err)
|
||||
err = require.CapturePanic(func() {
|
||||
m.LookupFunction(m.Tables[0], m.TypeIDs[0], 1) // offset 1 is not initialized yet.
|
||||
})
|
||||
require.Equal(t, wasmruntime.ErrRuntimeInvalidTableAccess, err)
|
||||
})
|
||||
|
||||
m.Tables[0].References[0] = me.FunctionInstanceReference(2)
|
||||
m.Tables[0].References[1] = me.FunctionInstanceReference(0)
|
||||
|
||||
t.Run("initialized", func(t *testing.T) {
|
||||
f1 := m.LookupFunction(m.Tables[0], m.TypeIDs[0], 0) // offset 0 is now initialized.
|
||||
require.Equal(t, wasm.Index(2), f1.Definition().Index())
|
||||
f2 := m.LookupFunction(m.Tables[0], m.TypeIDs[0], 1) // offset 1 is now initialized.
|
||||
require.Equal(t, wasm.Index(0), f2.Definition().Index())
|
||||
})
|
||||
|
||||
t.Run("out of range", func(t *testing.T) {
|
||||
err = require.CapturePanic(func() {
|
||||
me.LookupFunction(m.Tables[0], m.TypeIDs[0], 100 /* out of range */)
|
||||
})
|
||||
require.Equal(t, wasmruntime.ErrRuntimeInvalidTableAccess, err)
|
||||
})
|
||||
|
||||
t.Run("access to externref table", func(t *testing.T) {
|
||||
err := require.CapturePanic(func() {
|
||||
m.LookupFunction(m.Tables[1], /* table[1] has externref type. */
|
||||
m.TypeIDs[0], 0)
|
||||
})
|
||||
require.Equal(t, wasmruntime.ErrRuntimeInvalidTableAccess, err)
|
||||
})
|
||||
|
||||
t.Run("access to externref table", func(t *testing.T) {
|
||||
err = require.CapturePanic(func() {
|
||||
me.LookupFunction(m.Tables[0], /* type mismatch */
|
||||
m.TypeIDs[1], 0)
|
||||
})
|
||||
require.Equal(t, wasmruntime.ErrRuntimeIndirectCallTypeMismatch, err)
|
||||
})
|
||||
|
||||
m.Tables[2].References[0] = me.FunctionInstanceReference(1)
|
||||
m.Tables[2].References[5] = me.FunctionInstanceReference(2)
|
||||
t.Run("initialized - tables[2]", func(t *testing.T) {
|
||||
f1 := m.LookupFunction(m.Tables[2], m.TypeIDs[0], 0)
|
||||
require.Equal(t, wasm.Index(1), f1.Definition().Index())
|
||||
f2 := m.LookupFunction(m.Tables[2], m.TypeIDs[0], 5)
|
||||
require.Equal(t, wasm.Index(2), f2.Definition().Index())
|
||||
})
|
||||
}
|
||||
|
||||
func runTestModuleEngineCallHostFnMem(t *testing.T, et EngineTester, readMem *wasm.Code) {
|
||||
e := et.NewEngine(api.CoreFeaturesV1)
|
||||
defer e.Close()
|
||||
@@ -1188,7 +1107,10 @@ func setupCallTests(t *testing.T, e wasm.Engine, divBy *wasm.Code, fnlf experime
|
||||
lns := buildFunctionListeners(fnlf, hostModule)
|
||||
err := e.CompileModule(testCtx, hostModule, lns, false)
|
||||
require.NoError(t, err)
|
||||
host := &wasm.ModuleInstance{ModuleName: hostModule.NameSection.ModuleName, TypeIDs: []wasm.FunctionTypeID{0}}
|
||||
host := &wasm.ModuleInstance{
|
||||
ModuleName: hostModule.NameSection.ModuleName, TypeIDs: []wasm.FunctionTypeID{0},
|
||||
Source: hostModule,
|
||||
}
|
||||
host.Exports = exportMap(hostModule)
|
||||
|
||||
hostME, err := e.NewModuleEngine(hostModule, host)
|
||||
@@ -1223,6 +1145,7 @@ func setupCallTests(t *testing.T, e wasm.Engine, divBy *wasm.Code, fnlf experime
|
||||
require.NoError(t, err)
|
||||
|
||||
imported := &wasm.ModuleInstance{
|
||||
Source: importedModule,
|
||||
ModuleName: importedModule.NameSection.ModuleName, TypeIDs: []wasm.FunctionTypeID{0},
|
||||
}
|
||||
imported.Exports = exportMap(importedModule)
|
||||
@@ -1256,7 +1179,10 @@ func setupCallTests(t *testing.T, e wasm.Engine, divBy *wasm.Code, fnlf experime
|
||||
require.NoError(t, err)
|
||||
|
||||
// Add the exported function.
|
||||
importing := &wasm.ModuleInstance{ModuleName: importingModule.NameSection.ModuleName, TypeIDs: []wasm.FunctionTypeID{0}}
|
||||
importing := &wasm.ModuleInstance{
|
||||
ModuleName: importingModule.NameSection.ModuleName, TypeIDs: []wasm.FunctionTypeID{0},
|
||||
Source: importingModule,
|
||||
}
|
||||
importing.Exports = exportMap(importingModule)
|
||||
|
||||
// Compile the importing module
|
||||
|
||||
Reference in New Issue
Block a user