github.com/tetratelabs/wazero@v1.7.3-0.20240513003603-48f702e154b5/internal/engine/wazevo/hostmodule.go (about) 1 package wazevo 2 3 import ( 4 "encoding/binary" 5 "reflect" 6 "unsafe" 7 8 "github.com/tetratelabs/wazero/experimental" 9 "github.com/tetratelabs/wazero/internal/wasm" 10 ) 11 12 func buildHostModuleOpaque(m *wasm.Module, listeners []experimental.FunctionListener) moduleContextOpaque { 13 size := len(m.CodeSection)*16 + 32 14 ret := newAlignedOpaque(size) 15 16 binary.LittleEndian.PutUint64(ret[0:], uint64(uintptr(unsafe.Pointer(m)))) 17 18 if len(listeners) > 0 { 19 sliceHeader := (*reflect.SliceHeader)(unsafe.Pointer(&listeners)) 20 binary.LittleEndian.PutUint64(ret[8:], uint64(sliceHeader.Data)) 21 binary.LittleEndian.PutUint64(ret[16:], uint64(sliceHeader.Len)) 22 binary.LittleEndian.PutUint64(ret[24:], uint64(sliceHeader.Cap)) 23 } 24 25 offset := 32 26 for i := range m.CodeSection { 27 goFn := m.CodeSection[i].GoFunc 28 writeIface(goFn, ret[offset:]) 29 offset += 16 30 } 31 return ret 32 } 33 34 func hostModuleFromOpaque(opaqueBegin uintptr) *wasm.Module { 35 var opaqueViewOverSlice []byte 36 sh := (*reflect.SliceHeader)(unsafe.Pointer(&opaqueViewOverSlice)) 37 sh.Data = opaqueBegin 38 sh.Len = 32 39 sh.Cap = 32 40 return *(**wasm.Module)(unsafe.Pointer(&opaqueViewOverSlice[0])) 41 } 42 43 func hostModuleListenersSliceFromOpaque(opaqueBegin uintptr) []experimental.FunctionListener { 44 var opaqueViewOverSlice []byte 45 sh := (*reflect.SliceHeader)(unsafe.Pointer(&opaqueViewOverSlice)) 46 sh.Data = opaqueBegin 47 sh.Len = 32 48 sh.Cap = 32 49 50 b := binary.LittleEndian.Uint64(opaqueViewOverSlice[8:]) 51 l := binary.LittleEndian.Uint64(opaqueViewOverSlice[16:]) 52 c := binary.LittleEndian.Uint64(opaqueViewOverSlice[24:]) 53 var ret []experimental.FunctionListener 54 sh = (*reflect.SliceHeader)(unsafe.Pointer(&ret)) 55 sh.Data = uintptr(b) 56 setSliceLimits(sh, uintptr(l), uintptr(c)) 57 return ret 58 } 59 60 func hostModuleGoFuncFromOpaque[T any](index int, opaqueBegin uintptr) T { 61 offset := uintptr(index*16) + 32 62 ptr := opaqueBegin + offset 63 64 var opaqueViewOverFunction []byte 65 sh := (*reflect.SliceHeader)(unsafe.Pointer(&opaqueViewOverFunction)) 66 sh.Data = ptr 67 sh.Len = 16 68 sh.Cap = 16 69 return readIface(opaqueViewOverFunction).(T) 70 } 71 72 func writeIface(goFn interface{}, buf []byte) { 73 goFnIface := *(*[2]uint64)(unsafe.Pointer(&goFn)) 74 binary.LittleEndian.PutUint64(buf, goFnIface[0]) 75 binary.LittleEndian.PutUint64(buf[8:], goFnIface[1]) 76 } 77 78 func readIface(buf []byte) interface{} { 79 b := binary.LittleEndian.Uint64(buf) 80 s := binary.LittleEndian.Uint64(buf[8:]) 81 return *(*interface{})(unsafe.Pointer(&[2]uint64{b, s})) 82 }