github.com/bytedance/sonic@v1.11.7-0.20240517092252-d2edb31b167b/internal/rt/fastvalue.go (about)

     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 GoMap struct {
    79      Count      int
    80      Flags      uint8
    81      B          uint8
    82      Overflow   uint16
    83      Hash0      uint32
    84      Buckets    unsafe.Pointer
    85      OldBuckets unsafe.Pointer
    86      Evacuate   uintptr
    87      Extra      unsafe.Pointer
    88  }
    89  
    90  type GoMapIterator struct {
    91      K           unsafe.Pointer
    92      V           unsafe.Pointer
    93      T           *GoMapType
    94      H           *GoMap
    95      Buckets     unsafe.Pointer
    96      Bptr        *unsafe.Pointer
    97      Overflow    *[]unsafe.Pointer
    98      OldOverflow *[]unsafe.Pointer
    99      StartBucket uintptr
   100      Offset      uint8
   101      Wrapped     bool
   102      B           uint8
   103      I           uint8
   104      Bucket      uintptr
   105      CheckBucket uintptr
   106  }
   107  
   108  type GoItab struct {
   109      it unsafe.Pointer
   110      Vt *GoType
   111      hv uint32
   112      _  [4]byte
   113      fn [1]uintptr
   114  }
   115  
   116  type GoIface struct {
   117      Itab  *GoItab
   118      Value unsafe.Pointer
   119  }
   120  
   121  type GoEface struct {
   122      Type  *GoType
   123      Value unsafe.Pointer
   124  }
   125  
   126  func (self GoEface) Pack() (v interface{}) {
   127      *(*GoEface)(unsafe.Pointer(&v)) = self
   128      return
   129  }
   130  
   131  type GoPtrType struct {
   132      GoType
   133      Elem *GoType
   134  }
   135  
   136  type GoMapType struct {
   137      GoType
   138      Key        *GoType
   139      Elem       *GoType
   140      Bucket     *GoType
   141      Hasher     func(unsafe.Pointer, uintptr) uintptr
   142      KeySize    uint8
   143      ElemSize   uint8
   144      BucketSize uint16
   145      Flags      uint32
   146  }
   147  
   148  func (self *GoMapType) IndirectElem() bool {
   149      return self.Flags & 2 != 0
   150  }
   151  
   152  type GoStructType struct {
   153      GoType
   154      Pkg    *byte
   155      Fields []GoStructField
   156  }
   157  
   158  type GoStructField struct {
   159      Name     *byte
   160      Type     *GoType
   161      OffEmbed uintptr
   162  }
   163  
   164  type GoInterfaceType struct {
   165      GoType
   166      PkgPath *byte
   167      Methods []GoInterfaceMethod
   168  }
   169  
   170  type GoInterfaceMethod struct {
   171      Name int32
   172      Type int32
   173  }
   174  
   175  type GoSlice struct {
   176      Ptr unsafe.Pointer
   177      Len int
   178      Cap int
   179  }
   180  
   181  type GoString struct {
   182      Ptr unsafe.Pointer
   183      Len int
   184  }
   185  
   186  func PtrElem(t *GoType) *GoType {
   187      return (*GoPtrType)(unsafe.Pointer(t)).Elem
   188  }
   189  
   190  func MapType(t *GoType) *GoMapType {
   191      return (*GoMapType)(unsafe.Pointer(t))
   192  }
   193  
   194  func IfaceType(t *GoType) *GoInterfaceType {
   195      return (*GoInterfaceType)(unsafe.Pointer(t))
   196  }
   197  
   198  func UnpackType(t reflect.Type) *GoType {
   199      return (*GoType)((*GoIface)(unsafe.Pointer(&t)).Value)
   200  }
   201  
   202  func UnpackEface(v interface{}) GoEface {
   203      return *(*GoEface)(unsafe.Pointer(&v))
   204  }
   205  
   206  func UnpackIface(v interface{}) GoIface {
   207      return *(*GoIface)(unsafe.Pointer(&v))
   208  }
   209  
   210  func findReflectRtypeItab() *GoItab {
   211      v := reflect.TypeOf(struct{}{})
   212      return (*GoIface)(unsafe.Pointer(&v)).Itab
   213  }
   214  
   215  func AssertI2I2(t *GoType, i GoIface) (r GoIface) {
   216      inter := IfaceType(t)
   217  	tab := i.Itab
   218  	if tab == nil {
   219  		return
   220  	}
   221  	if (*GoInterfaceType)(tab.it) != inter {
   222  		tab = Getitab(inter, tab.Vt, true)
   223  		if tab == nil {
   224  			return
   225  		}
   226  	}
   227  	r.Itab = tab
   228  	r.Value = i.Value
   229  	return
   230  }
   231  
   232  //go:noescape
   233  //go:linkname Getitab runtime.getitab
   234  func Getitab(inter *GoInterfaceType, typ *GoType, canfail bool) *GoItab
   235  
   236  
   237  func GetFuncPC(fn interface{}) uintptr {
   238      ft := UnpackEface(fn)
   239      if ft.Type.Kind() != reflect.Func {
   240          panic("not a function")
   241      }
   242      return *(*uintptr)(ft.Value)
   243  }