diff --git a/engine/references.go b/engine/references.go index 78bc944..1549a3d 100644 --- a/engine/references.go +++ b/engine/references.go @@ -2,32 +2,34 @@ package engine import ( "math/rand" - "unsafe" ) // ExternalReferences manages external references to be used by the Interpreter // to store references that can be passed to guest modules. type ExternalReferences struct { - refs map[int32]uintptr + refs map[int32]any } // NewReferences creates a new ExternalReferences store. func NewReferences() ExternalReferences { return ExternalReferences{ - refs: make(map[int32]uintptr), + refs: make(map[int32]any), } } // Add adds a reference to the ExternalReferences store and returns the new reference id. -func (r *ExternalReferences) Add(thing unsafe.Pointer) int32 { +func (r *ExternalReferences) Add(thing any) int32 { id := r.newReferenceId() - r.refs[id] = uintptr(thing) + r.refs[id] = thing return id } // Get returns the reference for the given id. -func (r *ExternalReferences) Get(id int32) uintptr { - return r.refs[id] +func (r *ExternalReferences) Get(id int32) any { + if val, ok := r.refs[id]; ok { + return val + } + return nil } // Remove removes the reference for the given id. @@ -35,6 +37,11 @@ func (r *ExternalReferences) Remove(id int32) { delete(r.refs, id) } +// Remove removes the reference for the given id. +func (r *ExternalReferences) Clear() { + clear(r.refs) +} + // generates a random reference id that is not already in use. func (r *ExternalReferences) newReferenceId() int32 { for { diff --git a/engine/references_test.go b/engine/references_test.go index c884bbd..de5815c 100644 --- a/engine/references_test.go +++ b/engine/references_test.go @@ -2,7 +2,6 @@ package engine import ( "testing" - "unsafe" ) type testingType struct { @@ -13,18 +12,18 @@ type testingType struct { func TestExternalReferences(t *testing.T) { refs := NewReferences() var id1, id2 int32 - thing1 := &testingType{ + thing1 := testingType{ val1: "hello", val2: "world", } - thing2 := &testingType{ + thing2 := testingType{ val1: "hola", val2: "mundo", } t.Run("add references", func(t *testing.T) { - id1 = refs.Add(unsafe.Pointer(&thing1)) - id2 = refs.Add(unsafe.Pointer(&thing2)) + id1 = refs.Add(&thing1) + id2 = refs.Add(&thing2) if id1 == id2 { t.Errorf("id1 and id2 should not be the same") @@ -32,11 +31,11 @@ func TestExternalReferences(t *testing.T) { }) t.Run("get references", func(t *testing.T) { - if refs.Get(id1) != uintptr(unsafe.Pointer(&thing1)) { - t.Errorf("refs.Get(id1) failed") + if refs.Get(id1).(*testingType).val1 != thing1.val1 { + t.Errorf("refs.Get(id1) %d failed %v %v", id1, refs.Get(id1).(*testingType).val1, thing1.val1) } - if refs.Get(id2) != uintptr(unsafe.Pointer(&thing2)) { - t.Errorf("refs.Get(id2) failed") + if refs.Get(id2).(*testingType).val2 != thing2.val2 { + t.Errorf("refs.Get(id2) %d failed %v %v", id2, refs.Get(id2).(*testingType).val2, thing1.val2) } }) @@ -44,10 +43,10 @@ func TestExternalReferences(t *testing.T) { refs.Remove(id1) refs.Remove(id2) - if refs.Get(id1) != uintptr(0) { + if refs.Get(id1) != nil { t.Errorf("refs.Get(id1) failed") } - if refs.Get(id2) != uintptr(0) { + if refs.Get(id2) != nil { t.Errorf("refs.Get(id2) failed") } }) diff --git a/go.mod b/go.mod index 5ab870a..5c87005 100644 --- a/go.mod +++ b/go.mod @@ -5,7 +5,7 @@ go 1.22.0 replace github.com/tetratelabs/wazero => github.com/orsinium-forks/wazero v0.0.0-20240217173836-b12c024bcbe4 require ( - github.com/hybridgroup/wasman v0.0.0-20240229144219-f3288962ab34 + github.com/hybridgroup/wasman v0.0.0-20240303155228-bc96a1c9a2cc github.com/tetratelabs/wazero v1.6.0 github.com/urfave/cli/v2 v2.27.1 tinygo.org/x/tinyfs v0.3.1-0.20231212053859-32ae3f6bbad9 diff --git a/go.sum b/go.sum index ada22ad..fa20a96 100644 --- a/go.sum +++ b/go.sum @@ -1,9 +1,7 @@ github.com/cpuguy83/go-md2man/v2 v2.0.2 h1:p1EgwI/C7NhT0JmVkwCD2ZBK8j4aeHQX2pMHHBfMQ6w= github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= -github.com/hybridgroup/wasman v0.0.0-20240228124029-ecd9fd3f900a h1:6q1Gn1MR643sBn4PnvgX40jCCXmAyjuNXFfk8wirpds= -github.com/hybridgroup/wasman v0.0.0-20240228124029-ecd9fd3f900a/go.mod h1:rLavUo4P0xVcDeDnViYEpPQPoACmp1py9UTLPY/R7Lg= -github.com/hybridgroup/wasman v0.0.0-20240229144219-f3288962ab34 h1:XGX7Qt+ylSTF7VrwfXePwXAy2cK2iB6At+Ni/PcaNok= -github.com/hybridgroup/wasman v0.0.0-20240229144219-f3288962ab34/go.mod h1:rLavUo4P0xVcDeDnViYEpPQPoACmp1py9UTLPY/R7Lg= +github.com/hybridgroup/wasman v0.0.0-20240303155228-bc96a1c9a2cc h1:Ld9ng9AdthISNNd5JYTK2HGx/shBtAWNZdz9Gu/Z25k= +github.com/hybridgroup/wasman v0.0.0-20240303155228-bc96a1c9a2cc/go.mod h1:rLavUo4P0xVcDeDnViYEpPQPoACmp1py9UTLPY/R7Lg= github.com/orsinium-forks/wazero v0.0.0-20240217173836-b12c024bcbe4 h1:MUh9e2izck9aROiwDsDm24UU7kHieYM2911U1t+NASs= github.com/orsinium-forks/wazero v0.0.0-20240217173836-b12c024bcbe4/go.mod h1:0U0G41+ochRKoPKCJlh0jMg1CHkyfK8kDqiirMmKY8A= github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= diff --git a/interp/tester/interp.go b/interp/tester/interp.go index ab70a53..090592f 100644 --- a/interp/tester/interp.go +++ b/interp/tester/interp.go @@ -2,7 +2,6 @@ package tester import ( "testing" - "unsafe" "github.com/hybridgroup/mechanoid/engine" ) @@ -71,18 +70,18 @@ func ReferencesTest(t *testing.T, i engine.Interpreter) { } var id1, id2 int32 - thing1 := &testingType{ + thing1 := testingType{ val1: "hello", val2: "world", } - thing2 := &testingType{ + 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)) + id1 = i.References().Add(&thing1) + id2 = i.References().Add(&thing2) if id1 == id2 { t.Errorf("id1 and id2 should not be the same") @@ -90,11 +89,11 @@ func ReferencesTest(t *testing.T, i engine.Interpreter) { }) 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(id1).(*testingType).val1 != thing1.val1 { + t.Errorf("refs.Get(id1) %d failed %v %v", id1, i.References().Get(id1).(*testingType).val1, thing1.val1) } - if i.References().Get(id2) != uintptr(unsafe.Pointer(&thing2)) { - t.Errorf("refs.Get(id2) failed") + if i.References().Get(id2).(*testingType).val2 != thing2.val2 { + t.Errorf("refs.Get(id2) %d failed %v %v", id2, i.References().Get(id2).(*testingType).val2, thing1.val2) } }) @@ -102,10 +101,10 @@ func ReferencesTest(t *testing.T, i engine.Interpreter) { i.References().Remove(id1) i.References().Remove(id2) - if i.References().Get(id1) != uintptr(0) { + if i.References().Get(id1) != nil { t.Errorf("refs.Get(id1) failed") } - if i.References().Get(id2) != uintptr(0) { + if i.References().Get(id2) != nil { t.Errorf("refs.Get(id2) failed") } }) diff --git a/interp/wasman/interp.go b/interp/wasman/interp.go index 1186f09..728060a 100644 --- a/interp/wasman/interp.go +++ b/interp/wasman/interp.go @@ -1,6 +1,8 @@ package wasman import ( + "runtime" + "github.com/hybridgroup/mechanoid" "github.com/hybridgroup/mechanoid/engine" @@ -57,6 +59,11 @@ func (i *Interpreter) Load(code []byte) error { } func (i *Interpreter) Run() (engine.Instance, error) { + ms := runtime.MemStats{} + + runtime.ReadMemStats(&ms) + println("Heap start Run Used: ", ms.HeapInuse, " Free: ", ms.HeapIdle, " Meta: ", ms.GCSys) + var err error i.instance, err = i.linker.Instantiate(i.module) if err != nil { @@ -75,7 +82,22 @@ func (i *Interpreter) Run() (engine.Instance, error) { } func (i *Interpreter) Halt() error { + ms := runtime.MemStats{} + + runtime.ReadMemStats(&ms) + println("Heap start Halt Used: ", ms.HeapInuse, " Free: ", ms.HeapIdle, " Meta: ", ms.GCSys) + + // clean up extern refs + i.references.Clear() i.instance = nil + i.module = nil + + // force a garbage collection to free memory + runtime.GC() + + runtime.ReadMemStats(&ms) + println("Heap start Halt after gc: ", ms.HeapInuse, " Free: ", ms.HeapIdle, " Meta: ", ms.GCSys) + return nil }