From 38a3d61831ec894dec9aee150cd501947d7cea07 Mon Sep 17 00:00:00 2001 From: deadprogram Date: Thu, 29 Feb 2024 12:37:33 +0100 Subject: [PATCH] engine, interp: connect ExternalReferences to Interpreters Signed-off-by: deadprogram --- engine/engine_test.go | 8 +++-- engine/interp.go | 2 ++ engine/references.go | 4 +-- interp/tester/interp.go | 59 ++++++++++++++++++++++++++++++++++++ interp/wasman/interp.go | 9 ++++++ interp/wasman/interp_test.go | 4 +++ interp/wazero/interp.go | 8 +++++ interp/wazero/interp_test.go | 4 +++ 8 files changed, 93 insertions(+), 5 deletions(-) diff --git a/engine/engine_test.go b/engine/engine_test.go index dea2992..55a357d 100644 --- a/engine/engine_test.go +++ b/engine/engine_test.go @@ -1,8 +1,6 @@ package engine -import ( - "testing" -) +import "testing" func TestEngine(t *testing.T) { t.Run("cannot init without interpreter", func(t *testing.T) { @@ -53,3 +51,7 @@ func (i *mockInterpreter) DefineFunc(modulename, funcname string, f interface{}) func (i *mockInterpreter) MemoryData(ptr, sz uint32) ([]byte, error) { return nil, nil } + +func (i *mockInterpreter) References() *ExternalReferences { + return nil +} diff --git a/engine/interp.go b/engine/interp.go index bfbc81d..b1572a2 100644 --- a/engine/interp.go +++ b/engine/interp.go @@ -15,4 +15,6 @@ type Interpreter interface { DefineFunc(module, name string, f interface{}) error // MemoryData returns a slice of memory data from the memory managed by the host. MemoryData(ptr, sz uint32) ([]byte, error) + // References are the external references managed by the host module. + References() *ExternalReferences } diff --git a/engine/references.go b/engine/references.go index 0f8594a..78bc944 100644 --- a/engine/references.go +++ b/engine/references.go @@ -12,8 +12,8 @@ type ExternalReferences struct { } // NewReferences creates a new ExternalReferences store. -func NewReferences() *ExternalReferences { - return &ExternalReferences{ +func NewReferences() ExternalReferences { + return ExternalReferences{ refs: make(map[int32]uintptr), } } diff --git a/interp/tester/interp.go b/interp/tester/interp.go index 1b14081..ab70a53 100644 --- a/interp/tester/interp.go +++ b/interp/tester/interp.go @@ -2,6 +2,7 @@ package tester import ( "testing" + "unsafe" "github.com/hybridgroup/mechanoid/engine" ) @@ -11,6 +12,14 @@ func InitTest(t *testing.T, i engine.Interpreter) { if err != nil { t.Errorf("Interpreter.Init() failed: %v", err) } + + if i.Name() == "" { + t.Errorf("Interpreter.Name() failed: %v", i.Name()) + } + + if i.References() == nil { + t.Errorf("Interpreter.References() failed: %v", i.References()) + } } func LoadTest(t *testing.T, i engine.Interpreter) { @@ -51,3 +60,53 @@ func HaltTest(t *testing.T, i engine.Interpreter) { t.Errorf("Interpreter.Halt() failed: %v", err) } } + +func ReferencesTest(t *testing.T, i engine.Interpreter) { + err := i.Init() + if err != nil { + t.Errorf("Interpreter.Init() failed: %v", err) + } + if i.References() == nil { + t.Errorf("Interpreter.References() failed: %v", i.References()) + } + + var id1, id2 int32 + thing1 := &testingType{ + val1: "hello", + val2: "world", + } + thing2 := &testingType{ + val1: "hola", + val2: "mundo", + } + + t.Run("add references", func(t *testing.T) { + id1 = i.References().Add(unsafe.Pointer(&thing1)) + id2 = i.References().Add(unsafe.Pointer(&thing2)) + + if id1 == id2 { + t.Errorf("id1 and id2 should not be the same") + } + }) + + t.Run("get references", func(t *testing.T) { + if i.References().Get(id1) != uintptr(unsafe.Pointer(&thing1)) { + t.Errorf("refs.Get(id1) failed") + } + if i.References().Get(id2) != uintptr(unsafe.Pointer(&thing2)) { + t.Errorf("refs.Get(id2) failed") + } + }) + + t.Run("remove references", func(t *testing.T) { + i.References().Remove(id1) + i.References().Remove(id2) + + if i.References().Get(id1) != uintptr(0) { + t.Errorf("refs.Get(id1) failed") + } + if i.References().Get(id2) != uintptr(0) { + t.Errorf("refs.Get(id2) failed") + } + }) +} diff --git a/interp/wasman/interp.go b/interp/wasman/interp.go index 6dc6eab..1187d95 100644 --- a/interp/wasman/interp.go +++ b/interp/wasman/interp.go @@ -14,6 +14,8 @@ type Interpreter struct { module *wasmaneng.Module instance *wasmaneng.Instance Memory []byte + + references engine.ExternalReferences } func (i *Interpreter) Name() string { @@ -34,6 +36,8 @@ func (i *Interpreter) Init() error { } } + i.references = engine.NewReferences() + return nil } @@ -115,3 +119,8 @@ func (i *Interpreter) MemoryData(ptr, sz uint32) ([]byte, error) { return i.instance.Memory.Value[ptr : ptr+sz], nil } + +// References are the external references managed by the host module. +func (i *Interpreter) References() *engine.ExternalReferences { + return &i.references +} diff --git a/interp/wasman/interp_test.go b/interp/wasman/interp_test.go index 2eb0476..f6b6266 100644 --- a/interp/wasman/interp_test.go +++ b/interp/wasman/interp_test.go @@ -29,6 +29,10 @@ func TestHalt(t *testing.T) { tester.HaltTest(t, &Interpreter{}) } +func TestExternalReferences(t *testing.T) { + tester.ReferencesTest(t, &Interpreter{}) +} + func TestDefineFunc(t *testing.T) { t.Skip("TODO: implement TestDefineFunc") } diff --git a/interp/wazero/interp.go b/interp/wazero/interp.go index f35dab7..58bb25d 100644 --- a/interp/wazero/interp.go +++ b/interp/wazero/interp.go @@ -14,6 +14,8 @@ type Interpreter struct { runtime wazero.Runtime defs map[string]map[string]any module api.Module + + references engine.ExternalReferences } func (i *Interpreter) Name() string { @@ -26,6 +28,7 @@ func (i *Interpreter) Init() error { conf = conf.WithDebugInfoEnabled(false) conf = conf.WithMemoryLimitPages(1) i.runtime = wazero.NewRuntimeWithConfig(ctx, conf) + i.references = engine.NewReferences() return nil } @@ -95,6 +98,11 @@ func (i *Interpreter) MemoryData(ptr, sz uint32) ([]byte, error) { return data, nil } +// References are the external references managed by the host module. +func (i *Interpreter) References() *engine.ExternalReferences { + return &i.references +} + // A fake RandSource for having fewer memory allocations. // // Should not be used with modules that do need an access to random functions. diff --git a/interp/wazero/interp_test.go b/interp/wazero/interp_test.go index 5a723ca..a908456 100644 --- a/interp/wazero/interp_test.go +++ b/interp/wazero/interp_test.go @@ -29,6 +29,10 @@ func TestHalt(t *testing.T) { tester.HaltTest(t, &Interpreter{}) } +func TestExternalReferences(t *testing.T) { + tester.ReferencesTest(t, &Interpreter{}) +} + func TestDefineFunc(t *testing.T) { t.Skip("TODO: implement TestDefineFunc") }