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  }