fastvalue.go raw

   1  /*
   2   * Copyright 2021 ByteDance Inc.
   3   *
   4   * Licensed under the Apache License, Version 2.0 (the "License");
   5   * you may not use this file except in compliance with the License.
   6   * You may obtain a copy of the License at
   7   *
   8   *     http://www.apache.org/licenses/LICENSE-2.0
   9   *
  10   * Unless required by applicable law or agreed to in writing, software
  11   * distributed under the License is distributed on an "AS IS" BASIS,
  12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13   * See the License for the specific language governing permissions and
  14   * limitations under the License.
  15   */
  16  
  17  package rt
  18  
  19  import (
  20  	"reflect"
  21  	"unsafe"
  22  )
  23  
  24  var (
  25  	reflectRtypeItab = findReflectRtypeItab()
  26  )
  27  
  28  // GoType.KindFlags const
  29  const (
  30  	F_direct    = 1 << 5
  31  	F_kind_mask = (1 << 5) - 1
  32  )
  33  
  34  // GoType.Flags const
  35  const (
  36  	tflagUncommon      uint8 = 1 << 0
  37  	tflagExtraStar     uint8 = 1 << 1
  38  	tflagNamed         uint8 = 1 << 2
  39  	tflagRegularMemory uint8 = 1 << 3
  40  )
  41  
  42  type GoType struct {
  43  	Size       uintptr
  44  	PtrData    uintptr
  45  	Hash       uint32
  46  	Flags      uint8
  47  	Align      uint8
  48  	FieldAlign uint8
  49  	KindFlags  uint8
  50  	Traits     unsafe.Pointer
  51  	GCData     *byte
  52  	Str        int32
  53  	PtrToSelf  int32
  54  }
  55  
  56  func (self *GoType) IsNamed() bool {
  57  	return (self.Flags & tflagNamed) != 0
  58  }
  59  
  60  func (self *GoType) Kind() reflect.Kind {
  61  	return reflect.Kind(self.KindFlags & F_kind_mask)
  62  }
  63  
  64  func (self *GoType) Pack() (t reflect.Type) {
  65  	(*GoIface)(unsafe.Pointer(&t)).Itab = reflectRtypeItab
  66  	(*GoIface)(unsafe.Pointer(&t)).Value = unsafe.Pointer(self)
  67  	return
  68  }
  69  
  70  func (self *GoType) String() string {
  71  	return self.Pack().String()
  72  }
  73  
  74  func (self *GoType) Indirect() bool {
  75  	return self.KindFlags&F_direct == 0
  76  }
  77  
  78  type GoItab struct {
  79  	it unsafe.Pointer
  80  	Vt *GoType
  81  	hv uint32
  82  	_  [4]byte
  83  	fn [1]uintptr
  84  }
  85  
  86  type GoIface struct {
  87  	Itab  *GoItab
  88  	Value unsafe.Pointer
  89  }
  90  
  91  type GoEface struct {
  92  	Type  *GoType
  93  	Value unsafe.Pointer
  94  }
  95  
  96  func (self GoEface) Pack() (v interface{}) {
  97  	*(*GoEface)(unsafe.Pointer(&v)) = self
  98  	return
  99  }
 100  
 101  type GoPtrType struct {
 102  	GoType
 103  	Elem *GoType
 104  }
 105  
 106  type GoMapType struct {
 107  	GoType
 108  	Key        *GoType
 109  	Elem       *GoType
 110  	Bucket     *GoType
 111  	Hasher     func(unsafe.Pointer, uintptr) uintptr
 112  	KeySize    uint8
 113  	ElemSize   uint8
 114  	BucketSize uint16
 115  	Flags      uint32
 116  }
 117  
 118  func (self *GoMapType) IndirectElem() bool {
 119  	return self.Flags&2 != 0
 120  }
 121  
 122  type GoStructType struct {
 123  	GoType
 124  	Pkg    *byte
 125  	Fields []GoStructField
 126  }
 127  
 128  type GoStructField struct {
 129  	Name     *byte
 130  	Type     *GoType
 131  	OffEmbed uintptr
 132  }
 133  
 134  type GoInterfaceType struct {
 135  	GoType
 136  	PkgPath *byte
 137  	Methods []GoInterfaceMethod
 138  }
 139  
 140  type GoInterfaceMethod struct {
 141  	Name int32
 142  	Type int32
 143  }
 144  
 145  type GoSlice struct {
 146  	Ptr unsafe.Pointer
 147  	Len int
 148  	Cap int
 149  }
 150  
 151  type GoString struct {
 152  	Ptr unsafe.Pointer
 153  	Len int
 154  }
 155  
 156  func PtrElem(t *GoType) *GoType {
 157  	return (*GoPtrType)(unsafe.Pointer(t)).Elem
 158  }
 159  
 160  func MapType(t *GoType) *GoMapType {
 161  	return (*GoMapType)(unsafe.Pointer(t))
 162  }
 163  
 164  func IfaceType(t *GoType) *GoInterfaceType {
 165  	return (*GoInterfaceType)(unsafe.Pointer(t))
 166  }
 167  
 168  func UnpackType(t reflect.Type) *GoType {
 169  	return (*GoType)((*GoIface)(unsafe.Pointer(&t)).Value)
 170  }
 171  
 172  func UnpackEface(v interface{}) GoEface {
 173  	return *(*GoEface)(unsafe.Pointer(&v))
 174  }
 175  
 176  func UnpackIface(v interface{}) GoIface {
 177  	return *(*GoIface)(unsafe.Pointer(&v))
 178  }
 179  
 180  func findReflectRtypeItab() *GoItab {
 181  	v := reflect.TypeOf(struct{}{})
 182  	return (*GoIface)(unsafe.Pointer(&v)).Itab
 183  }
 184  
 185  func AssertI2I2(t *GoType, i GoIface) (r GoIface) {
 186  	inter := IfaceType(t)
 187  	tab := i.Itab
 188  	if tab == nil {
 189  		return
 190  	}
 191  	if (*GoInterfaceType)(tab.it) != inter {
 192  		tab = GetItab(inter, tab.Vt, true)
 193  		if tab == nil {
 194  			return
 195  		}
 196  	}
 197  	r.Itab = tab
 198  	r.Value = i.Value
 199  	return
 200  }
 201  
 202  func (t *GoType) IsInt64() bool {
 203  	return t.Kind() == reflect.Int64 || (t.Kind() == reflect.Int && t.Size == 8)
 204  }
 205  
 206  func (t *GoType) IsInt32() bool {
 207  	return t.Kind() == reflect.Int32 || (t.Kind() == reflect.Int && t.Size == 4)
 208  }
 209  
 210  //go:nosplit
 211  func (t *GoType) IsUint64() bool {
 212  	isUint := t.Kind() == reflect.Uint || t.Kind() == reflect.Uintptr
 213  	return t.Kind() == reflect.Uint64 || (isUint && t.Size == 8)
 214  }
 215  
 216  //go:nosplit
 217  func (t *GoType) IsUint32() bool {
 218  	isUint := t.Kind() == reflect.Uint || t.Kind() == reflect.Uintptr
 219  	return t.Kind() == reflect.Uint32 || (isUint && t.Size == 4)
 220  }
 221  
 222  //go:nosplit
 223  func PtrAdd(ptr unsafe.Pointer, offset uintptr) unsafe.Pointer {
 224  	return unsafe.Pointer(uintptr(ptr) + offset)
 225  }
 226  
 227  //go:noescape
 228  //go:linkname GetItab runtime.getitab
 229  func GetItab(inter *GoInterfaceType, typ *GoType, canfail bool) *GoItab
 230  
 231  
 232