Generates typeIDs at compilation time (#1218)
Signed-off-by: Takeshi Yoneda <takeshi@tetrate.io>
This commit is contained in:
@@ -328,6 +328,13 @@ func (b *hostModuleBuilder) Compile(ctx context.Context) (CompiledModule, error)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// typeIDs are static and compile-time known.
|
||||
typeIDs, err := b.r.store.GetFunctionTypeIDs(module.TypeSection)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
c.typeIDs = typeIDs
|
||||
|
||||
return c, nil
|
||||
}
|
||||
|
||||
|
||||
@@ -279,6 +279,11 @@ func TestNewHostModuleBuilder_Compile(t *testing.T) {
|
||||
|
||||
require.Equal(t, b.r.store.Engine, m.compiledEngine)
|
||||
|
||||
// TypeIDs must be assigned to compiledModule.
|
||||
expTypeIDs, err := b.r.store.GetFunctionTypeIDs(tc.expected.TypeSection)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, expTypeIDs, m.typeIDs)
|
||||
|
||||
// Built module must be instantiable by Engine.
|
||||
mod, err := b.r.InstantiateModule(testCtx, m, NewModuleConfig())
|
||||
require.NoError(t, err)
|
||||
@@ -353,6 +358,8 @@ func requireHostModuleEquals(t *testing.T, expected, actual *wasm.Module) {
|
||||
// `require.Equal(t, expected, actual)` fails reflect pointers don't match, so brute compare:
|
||||
for _, tp := range expected.TypeSection {
|
||||
tp.CacheNumInUint64()
|
||||
// When creating the compiled module, we get the type IDs for types, which results in caching type keys.
|
||||
_ = tp.String()
|
||||
}
|
||||
require.Equal(t, expected.TypeSection, actual.TypeSection)
|
||||
require.Equal(t, expected.ImportSection, actual.ImportSection)
|
||||
|
||||
@@ -27,6 +27,18 @@ func TestCompilationCache(t *testing.T) {
|
||||
foo, bar := getCacheSharedRuntimes(ctx, t)
|
||||
cacheInst := foo.cache
|
||||
|
||||
// Create a different type id on the bar's store so that we can emulate that bar instantiated the module before facWasm.
|
||||
_, err := bar.store.GetFunctionTypeIDs(
|
||||
// Arbitrary one is fine as long as it is not used in facWasm.
|
||||
[]*wasm.FunctionType{{Params: []wasm.ValueType{
|
||||
wasm.ValueTypeI32, wasm.ValueTypeI32, wasm.ValueTypeI32, wasm.ValueTypeI32, wasm.ValueTypeI32, wasm.ValueTypeI32,
|
||||
wasm.ValueTypeI32, wasm.ValueTypeV128, wasm.ValueTypeI32, wasm.ValueTypeV128, wasm.ValueTypeI32, wasm.ValueTypeI32,
|
||||
wasm.ValueTypeI32, wasm.ValueTypeV128, wasm.ValueTypeI32, wasm.ValueTypeV128, wasm.ValueTypeI32, wasm.ValueTypeI32,
|
||||
wasm.ValueTypeI32, wasm.ValueTypeV128, wasm.ValueTypeI32, wasm.ValueTypeV128, wasm.ValueTypeI32, wasm.ValueTypeI32,
|
||||
wasm.ValueTypeI32, wasm.ValueTypeI32, wasm.ValueTypeI32, wasm.ValueTypeI32, wasm.ValueTypeI32, wasm.ValueTypeI32,
|
||||
}}})
|
||||
require.NoError(t, err)
|
||||
|
||||
// add interpreter first, to ensure compiler support isn't order dependent
|
||||
eng := foo.cache.engs[engineKindInterpreter]
|
||||
if platform.CompilerSupported() {
|
||||
@@ -41,8 +53,12 @@ func TestCompilationCache(t *testing.T) {
|
||||
barCompiled, err := bar.CompileModule(ctx, facWasm)
|
||||
require.NoError(t, err)
|
||||
|
||||
// Ensures compiled modules are the same.
|
||||
require.Equal(t, compiled, barCompiled)
|
||||
// Ensures compiled modules are the same modulo type IDs, which is unique per store.
|
||||
require.Equal(t, compiled.(*compiledModule).module, barCompiled.(*compiledModule).module)
|
||||
require.Equal(t, compiled.(*compiledModule).closeWithModule, barCompiled.(*compiledModule).closeWithModule)
|
||||
require.Equal(t, compiled.(*compiledModule).compiledEngine, barCompiled.(*compiledModule).compiledEngine)
|
||||
// TypeIDs must be different as we create a different type ID on bar beforehand.
|
||||
require.NotEqual(t, compiled.(*compiledModule).typeIDs, barCompiled.(*compiledModule).typeIDs)
|
||||
|
||||
// Two runtimes are completely separate except the compilation cache,
|
||||
// therefore it should be ok to instantiate the same name module for each of them.
|
||||
|
||||
@@ -333,6 +333,7 @@ type compiledModule struct {
|
||||
compiledEngine wasm.Engine
|
||||
// closeWithModule prevents leaking compiled code when a module is compiled implicitly.
|
||||
closeWithModule bool
|
||||
typeIDs []wasm.FunctionTypeID
|
||||
}
|
||||
|
||||
// Name implements CompiledModule.Name
|
||||
|
||||
@@ -264,7 +264,10 @@ func TestCompiler_SliceAllocatedOnHeap(t *testing.T) {
|
||||
err = s.Engine.CompileModule(testCtx, hm, nil, false)
|
||||
require.NoError(t, err)
|
||||
|
||||
_, err = s.Instantiate(testCtx, hm, hostModuleName, nil)
|
||||
typeIDs, err := s.GetFunctionTypeIDs(hm.TypeSection)
|
||||
require.NoError(t, err)
|
||||
|
||||
_, err = s.Instantiate(testCtx, hm, hostModuleName, nil, typeIDs)
|
||||
require.NoError(t, err)
|
||||
|
||||
const stackCorruption = "value_stack_corruption"
|
||||
@@ -320,7 +323,10 @@ func TestCompiler_SliceAllocatedOnHeap(t *testing.T) {
|
||||
err = s.Engine.CompileModule(testCtx, m, nil, false)
|
||||
require.NoError(t, err)
|
||||
|
||||
mi, err := s.Instantiate(testCtx, m, t.Name(), nil)
|
||||
typeIDs, err = s.GetFunctionTypeIDs(m.TypeSection)
|
||||
require.NoError(t, err)
|
||||
|
||||
mi, err := s.Instantiate(testCtx, m, t.Name(), nil, typeIDs)
|
||||
require.NoError(t, err)
|
||||
|
||||
for _, fnName := range []string{stackCorruption, callStackCorruption} {
|
||||
|
||||
@@ -337,7 +337,10 @@ func addSpectestModule(t *testing.T, ctx context.Context, s *wasm.Store, enabled
|
||||
err = s.Engine.CompileModule(ctx, mod, nil, false)
|
||||
require.NoError(t, err)
|
||||
|
||||
_, err = s.Instantiate(ctx, mod, mod.NameSection.ModuleName, sys.DefaultContext(nil))
|
||||
typeIDs, err := s.GetFunctionTypeIDs(mod.TypeSection)
|
||||
require.NoError(t, err)
|
||||
|
||||
_, err = s.Instantiate(ctx, mod, mod.NameSection.ModuleName, sys.DefaultContext(nil), typeIDs)
|
||||
require.NoError(t, err)
|
||||
}
|
||||
|
||||
@@ -404,7 +407,10 @@ func Run(t *testing.T, testDataFS embed.FS, ctx context.Context, fc filecache.Ca
|
||||
err = s.Engine.CompileModule(ctx, mod, nil, false)
|
||||
require.NoError(t, err, msg)
|
||||
|
||||
_, err = s.Instantiate(ctx, mod, moduleName, nil)
|
||||
typeIDs, err := s.GetFunctionTypeIDs(mod.TypeSection)
|
||||
require.NoError(t, err)
|
||||
|
||||
_, err = s.Instantiate(ctx, mod, moduleName, nil, typeIDs)
|
||||
lastInstantiatedModuleName = moduleName
|
||||
require.NoError(t, err)
|
||||
case "register":
|
||||
@@ -542,7 +548,10 @@ func Run(t *testing.T, testDataFS embed.FS, ctx context.Context, fc filecache.Ca
|
||||
err = s.Engine.CompileModule(ctx, mod, nil, false)
|
||||
require.NoError(t, err, msg)
|
||||
|
||||
_, err = s.Instantiate(ctx, mod, t.Name(), nil)
|
||||
typeIDs, err := s.GetFunctionTypeIDs(mod.TypeSection)
|
||||
require.NoError(t, err)
|
||||
|
||||
_, err = s.Instantiate(ctx, mod, t.Name(), nil, typeIDs)
|
||||
require.NoError(t, err, msg)
|
||||
} else {
|
||||
requireInstantiationError(t, ctx, s, buf, msg)
|
||||
@@ -578,7 +587,10 @@ func requireInstantiationError(t *testing.T, ctx context.Context, s *wasm.Store,
|
||||
return
|
||||
}
|
||||
|
||||
_, err = s.Instantiate(ctx, mod, t.Name(), nil)
|
||||
typeIDs, err := s.GetFunctionTypeIDs(mod.TypeSection)
|
||||
require.NoError(t, err)
|
||||
|
||||
_, err = s.Instantiate(ctx, mod, t.Name(), nil, typeIDs)
|
||||
require.Error(t, err, msg)
|
||||
}
|
||||
|
||||
|
||||
@@ -74,7 +74,10 @@ func RunTestEngine_MemoryGrowInRecursiveCall(t *testing.T, et EngineTester) {
|
||||
err = s.Engine.CompileModule(testCtx, hm, nil, false)
|
||||
require.NoError(t, err)
|
||||
|
||||
_, err = s.Instantiate(testCtx, hm, hostModuleName, nil)
|
||||
typeIDs, err := s.GetFunctionTypeIDs(hm.TypeSection)
|
||||
require.NoError(t, err)
|
||||
|
||||
_, err = s.Instantiate(testCtx, hm, hostModuleName, nil, typeIDs)
|
||||
require.NoError(t, err)
|
||||
|
||||
m := &wasm.Module{
|
||||
@@ -106,7 +109,10 @@ func RunTestEngine_MemoryGrowInRecursiveCall(t *testing.T, et EngineTester) {
|
||||
err = s.Engine.CompileModule(testCtx, m, nil, false)
|
||||
require.NoError(t, err)
|
||||
|
||||
inst, err := s.Instantiate(testCtx, m, t.Name(), nil)
|
||||
typeIDs, err = s.GetFunctionTypeIDs(m.TypeSection)
|
||||
require.NoError(t, err)
|
||||
|
||||
inst, err := s.Instantiate(testCtx, m, t.Name(), nil, typeIDs)
|
||||
require.NoError(t, err)
|
||||
|
||||
growFn = inst.Function(2)
|
||||
|
||||
@@ -39,7 +39,7 @@ func TestCallContext_String(t *testing.T) {
|
||||
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
// Ensure paths that can create the host module can see the name.
|
||||
m, err := s.Instantiate(testCtx, &Module{}, tc.moduleName, nil)
|
||||
m, err := s.Instantiate(testCtx, &Module{}, tc.moduleName, nil, nil)
|
||||
defer m.Close(testCtx) //nolint
|
||||
|
||||
require.NoError(t, err)
|
||||
@@ -78,7 +78,7 @@ func TestCallContext_Close(t *testing.T) {
|
||||
t.Run(fmt.Sprintf("%s calls ns.CloseWithExitCode(module.name))", tc.name), func(t *testing.T) {
|
||||
for _, ctx := range []context.Context{nil, testCtx} { // Ensure it doesn't crash on nil!
|
||||
moduleName := t.Name()
|
||||
m, err := s.Instantiate(ctx, &Module{}, moduleName, nil)
|
||||
m, err := s.Instantiate(ctx, &Module{}, moduleName, nil, nil)
|
||||
require.NoError(t, err)
|
||||
|
||||
// We use side effects to see if Close called ns.CloseWithExitCode (without repeating store_test.go).
|
||||
@@ -107,7 +107,7 @@ func TestCallContext_Close(t *testing.T) {
|
||||
_, err := fsCtx.OpenFile(testFS, "/foo", os.O_RDONLY, 0)
|
||||
require.NoError(t, err)
|
||||
|
||||
m, err := s.Instantiate(testCtx, &Module{}, t.Name(), sysCtx)
|
||||
m, err := s.Instantiate(testCtx, &Module{}, t.Name(), sysCtx, nil)
|
||||
require.NoError(t, err)
|
||||
|
||||
// We use side effects to determine if Close in fact called Context.Close (without repeating sys_test.go).
|
||||
@@ -142,7 +142,7 @@ func TestCallContext_Close(t *testing.T) {
|
||||
_, err := fsCtx.OpenFile(testFS, "/foo", os.O_RDONLY, 0)
|
||||
require.NoError(t, err)
|
||||
|
||||
m, err := s.Instantiate(testCtx, &Module{}, t.Name(), sysCtx)
|
||||
m, err := s.Instantiate(testCtx, &Module{}, t.Name(), sysCtx, nil)
|
||||
require.NoError(t, err)
|
||||
|
||||
require.EqualError(t, m.Close(testCtx), "error closing")
|
||||
@@ -182,7 +182,7 @@ func TestCallContext_CallDynamic(t *testing.T) {
|
||||
t.Run(fmt.Sprintf("%s calls ns.CloseWithExitCode(module.name))", tc.name), func(t *testing.T) {
|
||||
for _, ctx := range []context.Context{nil, testCtx} { // Ensure it doesn't crash on nil!
|
||||
moduleName := t.Name()
|
||||
m, err := s.Instantiate(ctx, &Module{}, moduleName, nil)
|
||||
m, err := s.Instantiate(ctx, &Module{}, moduleName, nil, nil)
|
||||
require.NoError(t, err)
|
||||
|
||||
// We use side effects to see if Close called ns.CloseWithExitCode (without repeating store_test.go).
|
||||
@@ -211,7 +211,7 @@ func TestCallContext_CallDynamic(t *testing.T) {
|
||||
_, err := fsCtx.OpenFile(testFS, "/foo", os.O_RDONLY, 0)
|
||||
require.NoError(t, err)
|
||||
|
||||
m, err := s.Instantiate(testCtx, &Module{}, t.Name(), sysCtx)
|
||||
m, err := s.Instantiate(testCtx, &Module{}, t.Name(), sysCtx, nil)
|
||||
require.NoError(t, err)
|
||||
|
||||
// We use side effects to determine if Close in fact called Context.Close (without repeating sys_test.go).
|
||||
@@ -240,7 +240,7 @@ func TestCallContext_CallDynamic(t *testing.T) {
|
||||
_, err := fsCtx.OpenFile(testFS, path, os.O_RDONLY, 0)
|
||||
require.NoError(t, err)
|
||||
|
||||
m, err := s.Instantiate(testCtx, &Module{}, t.Name(), sysCtx)
|
||||
m, err := s.Instantiate(testCtx, &Module{}, t.Name(), sysCtx, nil)
|
||||
require.NoError(t, err)
|
||||
|
||||
require.EqualError(t, m.Close(testCtx), "error closing")
|
||||
|
||||
@@ -296,7 +296,7 @@ func TestPublicModule_Global(t *testing.T) {
|
||||
s := newStore()
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
// Instantiate the module and get the export of the above global
|
||||
module, err := s.Instantiate(context.Background(), tc.module, t.Name(), nil)
|
||||
module, err := s.Instantiate(context.Background(), tc.module, t.Name(), nil, nil)
|
||||
require.NoError(t, err)
|
||||
|
||||
if global := module.ExportedGlobal("global"); tc.expected != nil {
|
||||
|
||||
@@ -286,6 +286,7 @@ func (s *Store) Instantiate(
|
||||
module *Module,
|
||||
name string,
|
||||
sys *internalsys.Context,
|
||||
typeIDs []FunctionTypeID,
|
||||
) (*CallContext, error) {
|
||||
// Collect any imported modules to avoid locking the store too long.
|
||||
importedModuleNames := map[string]struct{}{}
|
||||
@@ -305,7 +306,7 @@ func (s *Store) Instantiate(
|
||||
}
|
||||
|
||||
// Instantiate the module and add it to the store so that other modules can import it.
|
||||
if callCtx, err := s.instantiate(ctx, module, name, sys, importedModules); err != nil {
|
||||
if callCtx, err := s.instantiate(ctx, module, name, sys, importedModules, typeIDs); err != nil {
|
||||
_ = s.deleteModule(name)
|
||||
return nil, err
|
||||
} else {
|
||||
@@ -325,12 +326,8 @@ func (s *Store) instantiate(
|
||||
name string,
|
||||
sysCtx *internalsys.Context,
|
||||
modules map[string]*ModuleInstance,
|
||||
typeIDs []FunctionTypeID,
|
||||
) (*CallContext, error) {
|
||||
typeIDs, err := s.getFunctionTypeIDs(module.TypeSection)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
importedFunctions, importedGlobals, importedTables, importedMemory, err := resolveImports(module, modules)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -562,7 +559,7 @@ func executeConstExpression(importedGlobals []*GlobalInstance, expr *ConstantExp
|
||||
return
|
||||
}
|
||||
|
||||
func (s *Store) getFunctionTypeIDs(ts []*FunctionType) ([]FunctionTypeID, error) {
|
||||
func (s *Store) GetFunctionTypeIDs(ts []*FunctionType) ([]FunctionTypeID, error) {
|
||||
ret := make([]FunctionTypeID, len(ts))
|
||||
for i, t := range ts {
|
||||
inst, err := s.getFunctionTypeID(t)
|
||||
|
||||
@@ -80,7 +80,7 @@ func TestModuleInstance_Memory(t *testing.T) {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
s := newStore()
|
||||
|
||||
instance, err := s.Instantiate(testCtx, tc.input, "test", nil)
|
||||
instance, err := s.Instantiate(testCtx, tc.input, "test", nil, nil)
|
||||
require.NoError(t, err)
|
||||
|
||||
mem := instance.ExportedMemory("memory")
|
||||
@@ -109,7 +109,7 @@ func TestStore_Instantiate(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
|
||||
sysCtx := sys.DefaultContext(nil)
|
||||
mod, err := s.Instantiate(testCtx, m, "", sysCtx)
|
||||
mod, err := s.Instantiate(testCtx, m, "", sysCtx, []FunctionTypeID{0})
|
||||
require.NoError(t, err)
|
||||
defer mod.Close(testCtx)
|
||||
|
||||
@@ -150,7 +150,7 @@ func TestStore_CloseWithExitCode(t *testing.T) {
|
||||
CodeSection: []*Code{{Body: []byte{OpcodeEnd}}},
|
||||
ExportSection: []*Export{{Type: ExternTypeFunc, Index: 0, Name: "fn"}},
|
||||
FunctionDefinitionSection: []*FunctionDefinition{{funcType: v_v}},
|
||||
}, importedModuleName, nil)
|
||||
}, importedModuleName, nil, []FunctionTypeID{0})
|
||||
require.NoError(t, err)
|
||||
|
||||
m2, err := s.Instantiate(testCtx, &Module{
|
||||
@@ -160,7 +160,7 @@ func TestStore_CloseWithExitCode(t *testing.T) {
|
||||
MemoryDefinitionSection: []*MemoryDefinition{{}},
|
||||
GlobalSection: []*Global{{Type: &GlobalType{}, Init: &ConstantExpression{Opcode: OpcodeI32Const, Data: const1}}},
|
||||
TableSection: []*Table{{Min: 10}},
|
||||
}, importingModuleName, nil)
|
||||
}, importingModuleName, nil, []FunctionTypeID{0})
|
||||
require.NoError(t, err)
|
||||
|
||||
if tc.testClosed {
|
||||
@@ -187,7 +187,7 @@ func TestStore_hammer(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
|
||||
s := newStore()
|
||||
imported, err := s.Instantiate(testCtx, m, importedModuleName, nil)
|
||||
imported, err := s.Instantiate(testCtx, m, importedModuleName, nil, []FunctionTypeID{0})
|
||||
require.NoError(t, err)
|
||||
|
||||
_, ok := s.nameToNode[imported.Name()]
|
||||
@@ -219,7 +219,7 @@ func TestStore_hammer(t *testing.T) {
|
||||
N = 100
|
||||
}
|
||||
hammer.NewHammer(t, P, N).Run(func(name string) {
|
||||
mod, instantiateErr := s.Instantiate(testCtx, importingModule, name, sys.DefaultContext(nil))
|
||||
mod, instantiateErr := s.Instantiate(testCtx, importingModule, name, sys.DefaultContext(nil), []FunctionTypeID{0})
|
||||
require.NoError(t, instantiateErr)
|
||||
require.NoError(t, mod.Close(testCtx))
|
||||
}, nil)
|
||||
@@ -241,7 +241,7 @@ func TestStore_hammer_close(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
|
||||
s := newStore()
|
||||
imported, err := s.Instantiate(testCtx, m, importedModuleName, nil)
|
||||
imported, err := s.Instantiate(testCtx, m, importedModuleName, nil, []FunctionTypeID{0})
|
||||
require.NoError(t, err)
|
||||
|
||||
_, ok := s.nameToNode[imported.Name()]
|
||||
@@ -267,7 +267,7 @@ func TestStore_hammer_close(t *testing.T) {
|
||||
const instCount = 10000
|
||||
instances := make([]api.Module, instCount)
|
||||
for i := 0; i < instCount; i++ {
|
||||
mod, instantiateErr := s.Instantiate(testCtx, importingModule, strconv.Itoa(i), sys.DefaultContext(nil))
|
||||
mod, instantiateErr := s.Instantiate(testCtx, importingModule, strconv.Itoa(i), sys.DefaultContext(nil), []FunctionTypeID{0})
|
||||
require.NoError(t, instantiateErr)
|
||||
instances[i] = mod
|
||||
}
|
||||
@@ -301,17 +301,17 @@ func TestStore_Instantiate_Errors(t *testing.T) {
|
||||
|
||||
t.Run("Fails if module name already in use", func(t *testing.T) {
|
||||
s := newStore()
|
||||
_, err = s.Instantiate(testCtx, m, importedModuleName, nil)
|
||||
_, err = s.Instantiate(testCtx, m, importedModuleName, nil, []FunctionTypeID{0})
|
||||
require.NoError(t, err)
|
||||
|
||||
// Trying to register it again should fail
|
||||
_, err = s.Instantiate(testCtx, m, importedModuleName, nil)
|
||||
_, err = s.Instantiate(testCtx, m, importedModuleName, nil, []FunctionTypeID{0})
|
||||
require.EqualError(t, err, "module[imported] has already been instantiated")
|
||||
})
|
||||
|
||||
t.Run("fail resolve import", func(t *testing.T) {
|
||||
s := newStore()
|
||||
_, err = s.Instantiate(testCtx, m, importedModuleName, nil)
|
||||
_, err = s.Instantiate(testCtx, m, importedModuleName, nil, []FunctionTypeID{0})
|
||||
require.NoError(t, err)
|
||||
|
||||
hm := s.nameToNode[importedModuleName]
|
||||
@@ -325,14 +325,14 @@ func TestStore_Instantiate_Errors(t *testing.T) {
|
||||
// But the second one tries to import uninitialized-module ->
|
||||
{Type: ExternTypeFunc, Module: "non-exist", Name: "fn", DescFunc: 0},
|
||||
},
|
||||
}, importingModuleName, nil)
|
||||
}, importingModuleName, nil, nil)
|
||||
require.EqualError(t, err, "module[non-exist] not instantiated")
|
||||
})
|
||||
|
||||
t.Run("creating engine failed", func(t *testing.T) {
|
||||
s := newStore()
|
||||
|
||||
_, err = s.Instantiate(testCtx, m, importedModuleName, nil)
|
||||
_, err = s.Instantiate(testCtx, m, importedModuleName, nil, []FunctionTypeID{0})
|
||||
require.NoError(t, err)
|
||||
|
||||
hm := s.nameToNode[importedModuleName]
|
||||
@@ -354,7 +354,7 @@ func TestStore_Instantiate_Errors(t *testing.T) {
|
||||
}
|
||||
importingModule.BuildFunctionDefinitions()
|
||||
|
||||
_, err = s.Instantiate(testCtx, importingModule, importingModuleName, nil)
|
||||
_, err = s.Instantiate(testCtx, importingModule, importingModuleName, nil, []FunctionTypeID{0})
|
||||
require.EqualError(t, err, "some engine creation error")
|
||||
})
|
||||
|
||||
@@ -363,7 +363,7 @@ func TestStore_Instantiate_Errors(t *testing.T) {
|
||||
engine := s.Engine.(*mockEngine)
|
||||
engine.callFailIndex = 1
|
||||
|
||||
_, err = s.Instantiate(testCtx, m, importedModuleName, nil)
|
||||
_, err = s.Instantiate(testCtx, m, importedModuleName, nil, []FunctionTypeID{0})
|
||||
require.NoError(t, err)
|
||||
|
||||
hm := s.nameToNode[importedModuleName]
|
||||
@@ -381,7 +381,7 @@ func TestStore_Instantiate_Errors(t *testing.T) {
|
||||
}
|
||||
importingModule.BuildFunctionDefinitions()
|
||||
|
||||
_, err = s.Instantiate(testCtx, importingModule, importingModuleName, nil)
|
||||
_, err = s.Instantiate(testCtx, importingModule, importingModuleName, nil, []FunctionTypeID{0})
|
||||
require.EqualError(t, err, "start function[1] failed: call failed")
|
||||
})
|
||||
}
|
||||
|
||||
@@ -203,6 +203,13 @@ func (r *runtime) CompileModule(ctx context.Context, binary []byte) (CompiledMod
|
||||
|
||||
c := &compiledModule{module: internal, compiledEngine: r.store.Engine}
|
||||
|
||||
// typeIDs are static and compile-time known.
|
||||
typeIDs, err := r.store.GetFunctionTypeIDs(internal.TypeSection)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
c.typeIDs = typeIDs
|
||||
|
||||
listeners, err := buildListeners(ctx, internal)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -276,7 +283,7 @@ func (r *runtime) InstantiateModule(
|
||||
}
|
||||
|
||||
// Instantiate the module.
|
||||
mod, err = r.store.Instantiate(ctx, code.module, name, sysCtx)
|
||||
mod, err = r.store.Instantiate(ctx, code.module, name, sysCtx, code.typeIDs)
|
||||
if err != nil {
|
||||
// If there was an error, don't leak the compiled module.
|
||||
if code.closeWithModule {
|
||||
|
||||
@@ -44,32 +44,32 @@ func TestRuntime_CompileModule(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
runtime Runtime
|
||||
wasm []byte
|
||||
wasm *wasm.Module
|
||||
moduleBuilder HostModuleBuilder
|
||||
expected func(CompiledModule)
|
||||
}{
|
||||
{
|
||||
name: "no name section",
|
||||
wasm: binaryencoding.EncodeModule(&wasm.Module{}),
|
||||
wasm: &wasm.Module{},
|
||||
},
|
||||
{
|
||||
name: "empty NameSection.ModuleName",
|
||||
wasm: binaryencoding.EncodeModule(&wasm.Module{NameSection: &wasm.NameSection{}}),
|
||||
wasm: &wasm.Module{NameSection: &wasm.NameSection{}},
|
||||
},
|
||||
{
|
||||
name: "NameSection.ModuleName",
|
||||
wasm: binaryencoding.EncodeModule(&wasm.Module{NameSection: &wasm.NameSection{ModuleName: "test"}}),
|
||||
wasm: &wasm.Module{NameSection: &wasm.NameSection{ModuleName: "test"}},
|
||||
expected: func(compiled CompiledModule) {
|
||||
require.Equal(t, "test", compiled.Name())
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "FunctionSection, but not exported",
|
||||
wasm: binaryencoding.EncodeModule(&wasm.Module{
|
||||
wasm: &wasm.Module{
|
||||
TypeSection: []*wasm.FunctionType{{Params: []api.ValueType{api.ValueTypeI32}}},
|
||||
FunctionSection: []wasm.Index{0},
|
||||
CodeSection: []*wasm.Code{{Body: []byte{wasm.OpcodeEnd}}},
|
||||
}),
|
||||
},
|
||||
expected: func(compiled CompiledModule) {
|
||||
require.Nil(t, compiled.ImportedFunctions())
|
||||
require.Zero(t, len(compiled.ExportedFunctions()))
|
||||
@@ -77,7 +77,7 @@ func TestRuntime_CompileModule(t *testing.T) {
|
||||
},
|
||||
{
|
||||
name: "FunctionSection exported",
|
||||
wasm: binaryencoding.EncodeModule(&wasm.Module{
|
||||
wasm: &wasm.Module{
|
||||
TypeSection: []*wasm.FunctionType{{Params: []api.ValueType{api.ValueTypeI32}}},
|
||||
FunctionSection: []wasm.Index{0},
|
||||
CodeSection: []*wasm.Code{{Body: []byte{wasm.OpcodeEnd}}},
|
||||
@@ -86,7 +86,7 @@ func TestRuntime_CompileModule(t *testing.T) {
|
||||
Name: "function",
|
||||
Index: 0,
|
||||
}},
|
||||
}),
|
||||
},
|
||||
expected: func(compiled CompiledModule) {
|
||||
require.Nil(t, compiled.ImportedFunctions())
|
||||
f := compiled.ExportedFunctions()["function"]
|
||||
@@ -95,9 +95,9 @@ func TestRuntime_CompileModule(t *testing.T) {
|
||||
},
|
||||
{
|
||||
name: "MemorySection, but not exported",
|
||||
wasm: binaryencoding.EncodeModule(&wasm.Module{
|
||||
wasm: &wasm.Module{
|
||||
MemorySection: &wasm.Memory{Min: 2, Max: 3, IsMaxEncoded: true},
|
||||
}),
|
||||
},
|
||||
expected: func(compiled CompiledModule) {
|
||||
require.Nil(t, compiled.ImportedMemories())
|
||||
require.Zero(t, len(compiled.ExportedMemories()))
|
||||
@@ -105,14 +105,14 @@ func TestRuntime_CompileModule(t *testing.T) {
|
||||
},
|
||||
{
|
||||
name: "MemorySection exported",
|
||||
wasm: binaryencoding.EncodeModule(&wasm.Module{
|
||||
wasm: &wasm.Module{
|
||||
MemorySection: &wasm.Memory{Min: 2, Max: 3, IsMaxEncoded: true},
|
||||
ExportSection: []*wasm.Export{{
|
||||
Type: wasm.ExternTypeMemory,
|
||||
Name: "memory",
|
||||
Index: 0,
|
||||
}},
|
||||
}),
|
||||
},
|
||||
expected: func(compiled CompiledModule) {
|
||||
require.Nil(t, compiled.ImportedMemories())
|
||||
mem := compiled.ExportedMemories()["memory"]
|
||||
@@ -124,20 +124,29 @@ func TestRuntime_CompileModule(t *testing.T) {
|
||||
},
|
||||
}
|
||||
|
||||
r := NewRuntime(testCtx)
|
||||
defer r.Close(testCtx)
|
||||
_r := NewRuntime(testCtx)
|
||||
defer _r.Close(testCtx)
|
||||
|
||||
r := _r.(*runtime)
|
||||
|
||||
for _, tt := range tests {
|
||||
tc := tt
|
||||
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
m, err := r.CompileModule(testCtx, tc.wasm)
|
||||
bin := binaryencoding.EncodeModule(tc.wasm)
|
||||
|
||||
m, err := r.CompileModule(testCtx, bin)
|
||||
require.NoError(t, err)
|
||||
if tc.expected == nil {
|
||||
tc.expected = func(CompiledModule) {}
|
||||
}
|
||||
tc.expected(m)
|
||||
require.Equal(t, r.(*runtime).store.Engine, m.(*compiledModule).compiledEngine)
|
||||
require.Equal(t, r.store.Engine, m.(*compiledModule).compiledEngine)
|
||||
|
||||
// TypeIDs must be assigned to compiledModule.
|
||||
expTypeIDs, err := r.store.GetFunctionTypeIDs(tc.wasm.TypeSection)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, expTypeIDs, m.(*compiledModule).typeIDs)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user