github.com/wasilibs/wazerox@v0.0.0-20240124024944-4923be63ab5f/internal/engine/wazevo/hostmodule.go (about) 1 package wazevo 2 3 import ( 4 "encoding/binary" 5 "reflect" 6 "unsafe" 7 8 "github.com/wasilibs/wazerox/experimental" 9 "github.com/wasilibs/wazerox/internal/wasm" 10 ) 11 12 func buildHostModuleOpaque(m *wasm.Module, listeners []experimental.FunctionListener) moduleContextOpaque { 13 size := len(m.CodeSection)*16 + 32 14 ret := make(moduleContextOpaque, 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 sh.Len = int(l) 57 sh.Cap = int(c) 58 return ret 59 } 60 61 func hostModuleGoFuncFromOpaque[T any](index int, opaqueBegin uintptr) T { 62 offset := uintptr(index*16) + 32 63 ptr := opaqueBegin + offset 64 65 var opaqueViewOverFunction []byte 66 sh := (*reflect.SliceHeader)(unsafe.Pointer(&opaqueViewOverFunction)) 67 sh.Data = ptr 68 sh.Len = 16 69 sh.Cap = 16 70 return readIface(opaqueViewOverFunction).(T) 71 } 72 73 func writeIface(goFn interface{}, buf []byte) { 74 goFnIface := *(*[2]uint64)(unsafe.Pointer(&goFn)) 75 binary.LittleEndian.PutUint64(buf, goFnIface[0]) 76 binary.LittleEndian.PutUint64(buf[8:], goFnIface[1]) 77 } 78 79 func readIface(buf []byte) interface{} { 80 b := binary.LittleEndian.Uint64(buf) 81 s := binary.LittleEndian.Uint64(buf[8:]) 82 return *(*interface{})(unsafe.Pointer(&[2]uint64{b, s})) 83 }