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 }