github.com/grailbio/bigslice@v0.0.0-20230519005545-30c4c12152ad/frame/unsafe.go (about) 1 // Copyright 2018 GRAIL, Inc. All rights reserved. 2 // Use of this source code is governed by the Apache 2.0 3 // license that can be found in the LICENSE file. 4 5 package frame 6 7 import ( 8 "reflect" 9 "unsafe" 10 ) 11 12 const ptrSize = 4 << (^uintptr(0) >> 63) 13 14 // Pointers reports whether type t contains any pointers. It is used 15 // to decide whether write barriers need to be applied in memory 16 // operations. 17 func pointers(t reflect.Type) bool { 18 switch t.Kind() { 19 case reflect.Bool, reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, 20 reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr, 21 reflect.Float32, reflect.Float64, reflect.Complex64, reflect.Complex128: 22 return false 23 case reflect.Array: 24 return pointers(t.Elem()) 25 case reflect.Struct: 26 for i := 0; i < t.NumField(); i++ { 27 if pointers(t.Field(i).Type) { 28 return true 29 } 30 } 31 return false 32 default: 33 return true 34 } 35 } 36 37 // sliceHeader is a safe version of SliceHeader used within this package. 38 type sliceHeader struct { 39 Data unsafe.Pointer 40 Len int 41 Cap int 42 } 43 44 // Assign copies src to dst where the data are the provided type. 45 func assign(typ dataType, dst, src unsafe.Pointer) { 46 if typ.pointers { 47 if typ.size == ptrSize { 48 *(*unsafe.Pointer)(dst) = *(*unsafe.Pointer)(src) 49 return 50 } 51 } else { 52 switch typ.size { 53 case 8: 54 *(*int64)(dst) = *(*int64)(src) 55 return 56 case 4: 57 *(*int32)(dst) = *(*int32)(src) 58 return 59 case 2: 60 *(*int16)(dst) = *(*int16)(src) 61 return 62 case 1: 63 *(*int8)(dst) = *(*int8)(src) 64 return 65 } 66 // TODO(marius): see if using copy() is cheaper than typedmemove 67 // in these cases. 68 } 69 typedmemmove(typ.ptr, dst, src) 70 } 71 72 func add(base unsafe.Pointer, off uintptr) unsafe.Pointer { 73 return unsafe.Pointer(uintptr(base) + off) 74 } 75 76 //go:linkname typedslicecopy reflect.typedslicecopy 77 func typedslicecopy(elemType unsafe.Pointer, dst, src sliceHeader) int 78 79 //go:linkname typedmemmove reflect.typedmemmove 80 func typedmemmove(t unsafe.Pointer, dst, src unsafe.Pointer)