github.com/cloudwego/frugal@v0.1.15/internal/rt/runtime.go (about)

     1  /*
     2   * Copyright 2022 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  const (
    25      MaxFastMap = 128
    26  )
    27  
    28  const (
    29      T_uncommon = 1 << 0
    30  )
    31  
    32  const (
    33      F_direct    = 1 << 5
    34      F_kind_mask = (1 << 5) - 1
    35  )
    36  
    37  var (
    38      reflectRtypeItab = findReflectRtypeItab()
    39  )
    40  
    41  type (
    42      GoNameOffset int32
    43      GoTypeOffset int32
    44      GoTextOffset int32
    45  )
    46  
    47  func (self GoNameOffset) Resolve(vt *GoType) GoName {
    48      if self == -1 {
    49          return GoName{}
    50      } else {
    51          return resolveNameOff(unsafe.Pointer(vt), self)
    52      }
    53  }
    54  
    55  func (self GoTypeOffset) Resolve(vt *GoType) *GoType {
    56      if self == -1 {
    57          return nil
    58      } else {
    59          return resolveTypeOff(unsafe.Pointer(vt), self)
    60      }
    61  }
    62  
    63  func (self GoTextOffset) Resolve(vt *GoType) unsafe.Pointer {
    64      if self == -1 {
    65          return nil
    66      } else {
    67          return resolveTextOff(unsafe.Pointer(vt), self)
    68      }
    69  }
    70  
    71  type GoName struct {
    72      b *[1 << 16]byte
    73  }
    74  
    75  func (self GoName) read(p int) (i int, v int) {
    76      for i, v = 0, 0;; i++ {
    77  		if v += int(self.b[p + i] & 0x7f) << (7 * i); self.b[p + i] & 0x80 == 0 {
    78  			return i + 1, v
    79  		}
    80      }
    81  }
    82  
    83  func (self GoName) mkstr(i int, n int) (s string) {
    84      (*GoString)(unsafe.Pointer(&s)).Len = n
    85      (*GoString)(unsafe.Pointer(&s)).Ptr = unsafe.Pointer(&self.b[i])
    86      return
    87  }
    88  
    89  func (self GoName) Name() string {
    90      if self.b == nil {
    91          return ""
    92      } else if i, n := self.read(1); n == 0 {
    93          return ""
    94      } else {
    95          return self.mkstr(i + 1, n)
    96      }
    97  }
    98  
    99  func (self GoName) IsExported() bool {
   100      return self.b != nil && self.b[0] & (1 << 0) != 0
   101  }
   102  
   103  type GoType struct {
   104      Size       uintptr
   105      PtrData    uintptr
   106      Hash       uint32
   107      Flags      uint8
   108      Align      uint8
   109      FieldAlign uint8
   110      KindFlags  uint8
   111      Equal      func(unsafe.Pointer, unsafe.Pointer) bool
   112      GCData     *byte
   113      Str        GoNameOffset
   114      PtrToSelf  GoTypeOffset
   115  }
   116  
   117  func (self *GoType) mtab() []GoMethod {
   118      switch self.Kind() {
   119          case reflect.Ptr    : return (*struct { GoPtrType    ; GoUncommonType })(unsafe.Pointer(self)).Methods()
   120          case reflect.Struct : return (*struct { GoStructType ; GoUncommonType })(unsafe.Pointer(self)).Methods()
   121          default             : return nil
   122      }
   123  }
   124  
   125  func (self *GoType) Kind() reflect.Kind {
   126      return reflect.Kind(self.KindFlags & F_kind_mask)
   127  }
   128  
   129  func (self *GoType) Pack() (t reflect.Type) {
   130      (*GoIface)(unsafe.Pointer(&t)).Itab = reflectRtypeItab
   131      (*GoIface)(unsafe.Pointer(&t)).Value = unsafe.Pointer(self)
   132      return
   133  }
   134  
   135  func (self *GoType) String() string {
   136      return self.Pack().String()
   137  }
   138  
   139  func (self *GoType) Methods() []GoMethod {
   140      if !self.IsUncommon() {
   141          return nil
   142      } else {
   143          return self.mtab()
   144      }
   145  }
   146  
   147  func (self *GoType) IsUncommon() bool {
   148      return (self.Flags & T_uncommon) != 0
   149  }
   150  
   151  func (self *GoType) IsIndirect() bool {
   152      return (self.KindFlags & F_direct) == 0
   153  }
   154  
   155  type GoPtrType struct {
   156      GoType
   157      Elem *GoType
   158  }
   159  
   160  type GoMapType struct {
   161      GoType
   162      Key        *GoType
   163      Elem       *GoType
   164      Bucket     *GoType
   165      Hasher     func(unsafe.Pointer, uintptr) uintptr
   166      KeySize    uint8
   167      ElemSize   uint8
   168      BucketSize uint16
   169      Flags      uint32
   170  }
   171  
   172  func (self *GoMapType) IsFastMap() bool {
   173      return self.Elem.Size <= MaxFastMap
   174  }
   175  
   176  type GoSliceType struct {
   177      GoType
   178      Elem *GoType
   179  }
   180  
   181  type GoStructType struct {
   182      GoType
   183      PkgPath GoName
   184      Fields  []GoStructField
   185  }
   186  
   187  type GoMethod struct {
   188      Name  GoNameOffset
   189      Type  GoTypeOffset
   190      IFunc GoTextOffset
   191      TFunc GoTextOffset
   192  }
   193  
   194  type GoStructField struct {
   195      Name        GoName
   196      Type        *GoType
   197      OffsetEmbed uintptr
   198  }
   199  
   200  type GoUncommonType struct {
   201      PkgPath      int32
   202      NumMethod    uint16
   203      NumExported  uint16
   204      MethodOffset uint32
   205      _            uint32
   206  }
   207  
   208  func (self *GoUncommonType) mbuf() unsafe.Pointer {
   209      return unsafe.Pointer(uintptr(unsafe.Pointer(self)) + uintptr(self.MethodOffset))
   210  }
   211  
   212  func (self *GoUncommonType) Methods() []GoMethod {
   213      if self.NumMethod == 0 {
   214          return nil
   215      } else {
   216          return (*[1 << 16]GoMethod)(self.mbuf())[:self.NumMethod:self.NumMethod]
   217      }
   218  }
   219  
   220  type GoItab struct {
   221      it unsafe.Pointer
   222      vt *GoType
   223      hv uint32
   224      _  [4]byte
   225      fn [1]uintptr
   226  }
   227  
   228  const (
   229      GoItabFuncBase = unsafe.Offsetof(GoItab{}.fn)
   230  )
   231  
   232  type GoIface struct {
   233      Itab  *GoItab
   234      Value unsafe.Pointer
   235  }
   236  
   237  type GoEface struct {
   238      Type  *GoType
   239      Value unsafe.Pointer
   240  }
   241  
   242  type GoSlice struct {
   243      Ptr unsafe.Pointer
   244      Len int
   245      Cap int
   246  }
   247  
   248  func (self GoSlice) Set(i int, v byte) {
   249      *(*byte)(unsafe.Pointer(uintptr(self.Ptr) + uintptr(i))) = v
   250  }
   251  
   252  type GoString struct {
   253      Ptr unsafe.Pointer
   254      Len int
   255  }
   256  
   257  type GoMap struct {
   258      Count      int
   259      Flags      uint8
   260      B          uint8
   261      Overflow   uint16
   262      Hash0      uint32
   263      Buckets    unsafe.Pointer
   264      OldBuckets unsafe.Pointer
   265      Evacuate   uintptr
   266      Extra      unsafe.Pointer
   267  }
   268  
   269  type GoMapIterator struct {
   270      K           unsafe.Pointer
   271      V           unsafe.Pointer
   272      T           *GoMapType
   273      H           *GoMap
   274      Buckets     unsafe.Pointer
   275      Bptr        *unsafe.Pointer
   276      Overflow    *[]unsafe.Pointer
   277      OldOverflow *[]unsafe.Pointer
   278      StartBucket uintptr
   279      Offset      uint8
   280      Wrapped     bool
   281      B           uint8
   282      I           uint8
   283      Bucket      uintptr
   284      CheckBucket uintptr
   285  }
   286  
   287  func (self *GoMapIterator) Next() bool {
   288      mapiternext(self)
   289      return self.K != nil
   290  }
   291  
   292  func IsPtr(t *GoType) bool {
   293      return t.Kind() == reflect.Ptr || t.Kind() == reflect.UnsafePointer
   294  }
   295  
   296  func PtrElem(t *GoType) *GoType {
   297      if t.Kind() != reflect.Ptr {
   298          panic("t is not a ptr")
   299      } else {
   300          return (*GoPtrType)(unsafe.Pointer(t)).Elem
   301      }
   302  }
   303  
   304  func MapType(t *GoType) *GoMapType {
   305      if t.Kind() != reflect.Map {
   306          panic("t is not a map")
   307      } else {
   308          return (*GoMapType)(unsafe.Pointer(t))
   309      }
   310  }
   311  
   312  func Dereference(t *GoType) *GoType {
   313      for t.Kind() == reflect.Ptr { t = PtrElem(t) }
   314      return t
   315  }
   316  
   317  func FuncAddr(f interface{}) unsafe.Pointer {
   318      if vv := UnpackEface(f); vv.Type.Kind() != reflect.Func {
   319          panic("f is not a function")
   320      } else {
   321          return *(*unsafe.Pointer)(vv.Value)
   322      }
   323  }
   324  
   325  func SliceElem(t *GoType) *GoType {
   326      if t.Kind() != reflect.Slice {
   327          panic("t is not a slice")
   328      } else {
   329          return (*GoSliceType)(unsafe.Pointer(t)).Elem
   330      }
   331  }
   332  
   333  func BytesFrom(p unsafe.Pointer, n int, c int) (r []byte) {
   334      (*GoSlice)(unsafe.Pointer(&r)).Ptr = p
   335      (*GoSlice)(unsafe.Pointer(&r)).Len = n
   336      (*GoSlice)(unsafe.Pointer(&r)).Cap = c
   337      return
   338  }
   339  
   340  func StringPtr(s string) unsafe.Pointer {
   341      return (*GoString)(unsafe.Pointer(&s)).Ptr
   342  }
   343  
   344  func StringFrom(p unsafe.Pointer, n int) (r string) {
   345      (*GoString)(unsafe.Pointer(&r)).Ptr = p
   346      (*GoString)(unsafe.Pointer(&r)).Len = n
   347      return
   348  }
   349  
   350  func UnpackType(t reflect.Type) *GoType {
   351      return (*GoType)((*GoIface)(unsafe.Pointer(&t)).Value)
   352  }
   353  
   354  func UnpackEface(v interface{}) GoEface {
   355      return *(*GoEface)(unsafe.Pointer(&v))
   356  }
   357  
   358  func findReflectRtypeItab() *GoItab {
   359      v := reflect.TypeOf(struct{}{})
   360      return (*GoIface)(unsafe.Pointer(&v)).Itab
   361  }