github.com/philpearl/plenc@v0.0.15/plenccodec/unsafetricks.go (about) 1 package plenccodec 2 3 import ( 4 "unsafe" 5 ) 6 7 //go:linkname unsafe_NewArray reflect.unsafe_NewArray 8 func unsafe_NewArray(rtype unsafe.Pointer, length int) unsafe.Pointer 9 10 // sliceheader is a safer version of reflect.SliceHeader. The Data field here is a pointer that GC will track. 11 type sliceHeader struct { 12 Data unsafe.Pointer 13 Len int 14 Cap int 15 } 16 17 // typedslicecopy copies a slice of elemType values from src to dst, 18 // returning the number of elements copied. 19 // 20 //go:linkname typedslicecopy reflect.typedslicecopy 21 //go:noescape 22 func typedslicecopy(elemType unsafe.Pointer, dst, src sliceHeader) int 23 24 //go:linkname typedmemmove runtime.typedmemmove 25 //go:noescape 26 func typedmemmove(elemType unsafe.Pointer, dst, src unsafe.Pointer) 27 28 //go:linkname typedmemclr runtime.typedmemclr 29 //go:noescape 30 func typedmemclr(elemType unsafe.Pointer, v unsafe.Pointer) 31 32 //go:linkname mapassign runtime.mapassign 33 //go:noescape 34 func mapassign(typ unsafe.Pointer, hmap unsafe.Pointer, key unsafe.Pointer) (val unsafe.Pointer) 35 36 // We could use the reflect version of mapiterinit, but that forces a heap 37 // allocation per map iteration. Instead we can use the runtime version, but 38 // then we have to allocate a runtime private struct for it to use instead. We 39 // can do this, and it uses stack memory, so that's less GC pressure and more 40 // speed. But it isn't excellent from a maintenance point of view. Things will 41 // break if the struct changes and we won't find out. But let's go for it. 42 // 43 // mapiter matches hiter in runtime/map.go. Using matching-ish types rather than 44 // a big enough array of unsafe.Pointer just in case the GC would run into an 45 // issue if something it thought was a pointer was not. Don't attempt to access 46 // any of the fields in this struct directly! On the plus side this hasn't 47 // changed significantly for 6 years 48 type mapiter struct { 49 key unsafe.Pointer 50 elem unsafe.Pointer 51 t unsafe.Pointer 52 h unsafe.Pointer 53 buckets unsafe.Pointer 54 bptr unsafe.Pointer 55 overflow unsafe.Pointer 56 oldoverflow unsafe.Pointer 57 startBucket uintptr 58 offset uint8 59 wrapped bool 60 B uint8 61 i uint8 62 bucket uintptr 63 checkBucket uintptr 64 } 65 66 //go:linkname mapiterinit runtime.mapiterinit 67 //go:noescape 68 func mapiterinit(t unsafe.Pointer, m unsafe.Pointer, hi unsafe.Pointer) 69 70 //go:linkname mapiterkey reflect.mapiterkey 71 //go:noescape 72 func mapiterkey(it unsafe.Pointer) (key unsafe.Pointer) 73 74 //go:linkname mapiterelem reflect.mapiterelem 75 //go:noescape 76 func mapiterelem(it unsafe.Pointer) (elem unsafe.Pointer) 77 78 //go:linkname mapiternext reflect.mapiternext 79 //go:noescape 80 func mapiternext(it unsafe.Pointer) 81 82 //go:linkname maplen reflect.maplen 83 //go:noescape 84 func maplen(m unsafe.Pointer) int 85 86 type eface struct { 87 rtype unsafe.Pointer 88 data unsafe.Pointer 89 } 90 91 func unpackEFace(obj interface{}) *eface { 92 return (*eface)(unsafe.Pointer(&obj)) 93 }