88 "runtime"
99 "sync"
1010 "syscall"
11- "unsafe"
1211
1312 "github.com/pboyd/malloc"
1413)
@@ -26,39 +25,16 @@ func cloneFunc[T any](fn T) (*clonedFunc[T], error) {
2625 return nil , err
2726 }
2827
29- //fmt.Println(disassemble(originalCode))
30-
31- cloneAllocator .BeginMutate ()
32- defer cloneAllocator .EndMutate ()
33-
34- newCode , err := cloneAllocator .Allocate (len (originalCode ))
28+ cf , err := _cloneFunc (fn , originalCode )
3529 if err != nil {
3630 return nil , err
3731 }
3832
39- newCode , err = relocateFunc (originalCode , newCode )
40- if err != nil {
41- return nil , err
42- }
43-
44- //fmt.Println(disassemble(newCode))
45-
46- // This seems too complicated. The idea is to take our newly allocated
47- // buffer of machine instructions and convince Go that it's really a
48- // function pointer of type T.
49- codeData := unsafe .SliceData (newCode )
50- cf := clonedFunc [T ]{
51- clonedCode : newCode ,
52- // Keep a reference to codeData so it stays around.
53- ref : & codeData ,
54- }
55- cf .Func = * (* T )(unsafe .Pointer (uintptr (unsafe .Pointer (& cf .ref ))))
56-
5733 // Make a copy of the code so that no matter what it can be restored.
5834 cf .originalCode = make ([]byte , len (originalCode ))
5935 copy (cf .originalCode , originalCode )
6036
61- return & cf , nil
37+ return cf , nil
6238}
6339
6440type allocator struct {
@@ -240,10 +216,14 @@ func (cf *clonedFunc[T]) Free() {
240216 cloneAllocator .BeginMutate ()
241217 defer cloneAllocator .EndMutate ()
242218
243- cloneAllocator .Free (cf .clonedCode )
219+ if cf .clonedCode != nil {
220+ cloneAllocator .Free (cf .clonedCode )
221+ }
244222
245223 cf .clonedCode = nil
246- * cf .ref = nil
247- cf .ref = nil
224+ if cf .ref != nil {
225+ * cf .ref = nil
226+ cf .ref = nil
227+ }
248228 cf .originalCode = nil
249229}
0 commit comments