github.com/volts-dev/volts@v0.0.0-20240120094013-5e9c65924106/internal/test/router/reflect.go (about) 1 package router 2 3 import ( 4 "reflect" 5 "sync" 6 "unsafe" 7 ) 8 9 const ( 10 kindDirectIface = 1 << 5 11 //kindGCProg = 1 << 6 // Type.gc points to GC program 12 kindMask = (1 << 5) - 1 13 // tflagUncommon means that there is a pointer, *uncommonType, 14 // just beyond the outer type structure. 15 // 16 // For example, if t.Kind() == Struct and t.tflag&tflagUncommon != 0, 17 // then t has uncommonType data and it can be accessed as: 18 // 19 // type tUncommon struct { 20 // structType 21 // u uncommonType 22 // } 23 // u := &(*tUncommon)(unsafe.Pointer(t)).u 24 tflagUncommon tflag = 1 << 0 25 ) 26 const ( 27 flagKindWidth = 5 // there are 27 kinds 28 flagKindMask flag = 1<<flagKindWidth - 1 29 flagStickyRO flag = 1 << 5 30 flagEmbedRO flag = 1 << 6 31 flagIndir flag = 1 << 7 32 flagAddr flag = 1 << 8 33 flagMethod flag = 1 << 9 34 flagMethodShift = 10 35 flagRO flag = flagStickyRO | flagEmbedRO 36 ) 37 38 type flag uintptr 39 40 func (f flag) kind() reflect.Kind { 41 return reflect.Kind(f & flagKindMask) 42 } 43 44 func (f flag) ro() flag { 45 if f&flagRO != 0 { 46 return flagStickyRO 47 } 48 return 0 49 } 50 51 type nameOff int32 // offset to a name 52 type typeOff int32 // offset to an *rtype 53 type textOff int32 // offset from top of text section 54 55 // tflag is used by an rtype to signal what extra type information is 56 // available in the memory directly following the rtype value. 57 // 58 // tflag values must be kept in sync with copies in: 59 // cmd/compile/internal/reflectdata/reflect.go 60 // cmd/link/internal/ld/decodesym.go 61 // runtime/type.go 62 type tflag uint8 63 64 // String is the runtime representation of a string. 65 // It cannot be used safely or portably and its representation may 66 // change in a later release. 67 // 68 // Unlike reflect.StringHeader, its Data field is sufficient to guarantee the 69 // data it references will not be garbage collected. 70 type String struct { 71 Data unsafe.Pointer 72 Len int 73 } 74 75 // name is an encoded type name with optional extra data. 76 // 77 // The first byte is a bit field containing: 78 // 79 // 1<<0 the name is exported 80 // 1<<1 tag data follows the name 81 // 1<<2 pkgPath nameOff follows the name and tag 82 // 83 // Following that, there is a varint-encoded length of the name, 84 // followed by the name itself. 85 // 86 // If tag data is present, it also has a varint-encoded length 87 // followed by the tag itself. 88 // 89 // If the import path follows, then 4 bytes at the end of 90 // the data form a nameOff. The import path is only set for concrete 91 // methods that are defined in a different package than their type. 92 // 93 // If a name starts with "*", then the exported bit represents 94 // whether the pointed to type is exported. 95 // 96 // Note: this encoding must match here and in: 97 // cmd/compile/internal/reflectdata/reflect.go 98 // runtime/type.go 99 // internal/reflectlite/type.go 100 // cmd/link/internal/ld/decodesym.go 101 102 type name struct { 103 bytes *byte 104 } 105 type Value struct { 106 typ *rtype 107 ptr unsafe.Pointer 108 flag 109 } 110 111 // imethod represents a method on an interface type 112 type imethod struct { 113 name nameOff // name of method 114 typ typeOff // .(*FuncType) underneath 115 } 116 117 // interfaceType represents an interface type. 118 type interfaceType struct { 119 rtype 120 pkgPath name // import path 121 methods []imethod // sorted by hash 122 } 123 124 func (n name) data(off int, whySafe string) *byte { 125 return (*byte)(add(unsafe.Pointer(n.bytes), uintptr(off), whySafe)) 126 } 127 128 // readVarint parses a varint as encoded by encoding/binary. 129 // It returns the number of encoded bytes and the encoded value. 130 func (n name) readVarint(off int) (int, int) { 131 v := 0 132 for i := 0; ; i++ { 133 x := *n.data(off+i, "read varint") 134 v += int(x&0x7f) << (7 * i) 135 if x&0x80 == 0 { 136 return i + 1, v 137 } 138 } 139 } 140 func (n name) name() (s string) { 141 if n.bytes == nil { 142 return 143 } 144 i, l := n.readVarint(1) 145 hdr := (*String)(unsafe.Pointer(&s)) 146 hdr.Data = unsafe.Pointer(n.data(1+i, "non-empty string")) 147 hdr.Len = l 148 return 149 } 150 151 type ( 152 // rtype is the common implementation of most values. 153 // It is embedded in other struct types. 154 // 155 // rtype must be kept in sync with ../runtime/type.go:/^type._type. 156 rtype struct { 157 size uintptr 158 ptrdata uintptr // number of bytes in the type that can contain pointers 159 hash uint32 // hash of type; avoids computation in hash tables 160 tflag tflag // extra type information flags 161 align uint8 // alignment of variable with this type 162 fieldAlign uint8 // alignment of struct field with this type 163 kind uint8 // enumeration for C 164 // function for comparing objects of this type 165 // (ptr to object A, ptr to object B) -> ==? 166 equal func(unsafe.Pointer, unsafe.Pointer) bool 167 gcdata *byte // garbage collection data 168 str nameOff // string form 169 ptrToThis typeOff // type for pointer to this type, may be zero 170 } 171 172 // uncommonType is present only for defined types or types with methods 173 // (if T is a defined type, the uncommonTypes for T and *T have methods). 174 // Using a pointer to this struct reduces the overall size required 175 // to describe a non-defined type with no methods. 176 uncommonType struct { 177 pkgPath nameOff // import path; empty for built-in types like int, string 178 mcount uint16 // number of methods 179 xcount uint16 // number of exported methods 180 moff uint32 // offset from this uncommontype to [mcount]method 181 _ uint32 // unused 182 } 183 // Method on non-interface type 184 method struct { 185 name nameOff // name of method 186 mtyp typeOff // method type (without receiver) 187 ifn textOff // fn used in interface call (one-word receiver) 188 tfn textOff // fn used for normal method call 189 } 190 191 // ptrType represents a pointer type. 192 ptrType struct { 193 rtype 194 elem *rtype // pointer element (pointed at) type 195 } 196 ) 197 198 // ValueOf returns a new Value initialized to the concrete value 199 // stored in the interface i. ValueOf(nil) returns the zero Value. 200 func ValueOf(i interface{}) Value { 201 if i == nil { 202 return Value{} 203 } 204 205 // TODO: Maybe allow contents of a Value to live on the stack. 206 // For now we make the contents always escape to the heap. It 207 // makes life easier in a few places (see chanrecv/mapassign 208 // comment below). 209 //escapes(i) 210 211 e := (*emptyInterface)(unsafe.Pointer(&i)) 212 // NOTE: don't read e.word until we know whether it is really a pointer or not. 213 t := e.typ 214 if t == nil { 215 return Value{} 216 } 217 f := flag(t.Kind()) 218 if t.kind&kindDirectIface == 0 { 219 f |= flagIndir 220 } 221 222 //return *(*reflect.Value)(unsafe.Pointer(&Value{t, e.word, f})) 223 return Value{t, e.word, f} 224 } 225 226 // MethodByName returns a function value corresponding to the method 227 // of v with the given name. 228 // The arguments to a Call on the returned function should not include 229 // a receiver; the returned function will always use v as the receiver. 230 // It returns the zero Value if no method was found. 231 func (v Value) MethodByName(name string) Value { 232 if v.typ == nil { 233 //panic(&ValueError{"reflect.Value.MethodByName", Invalid}) 234 } 235 if v.flag&flagMethod != 0 { 236 return Value{} 237 } 238 m, ok := v.typ.MethodByName(name) 239 if !ok { 240 return Value{} 241 } 242 return v.Method(m.Index) 243 } 244 245 // Interface returns v's current value as an interface{}. 246 // It is equivalent to: 247 // var i interface{} = (v's underlying value) 248 // It panics if the Value was obtained by accessing 249 // unexported struct fields. 250 func (v Value) Interface() (i interface{}) { 251 return valueInterface(v, true) 252 } 253 254 // ifaceIndir reports whether t is stored indirectly in an interface value. 255 func ifaceIndir(t *rtype) bool { 256 return t.kind&kindDirectIface == 0 257 } 258 259 //go:linkname unsafe_New reflect.unsafe_New 260 func unsafe_New(rtype unsafe.Pointer) unsafe.Pointer 261 262 //go:linkname typedmemmove reflect.typedmemmove 263 func typedmemmove(rtype unsafe.Pointer, dst, src unsafe.Pointer) 264 265 //go:linkname unsafe_NewArray reflect.unsafe_NewArray 266 func unsafe_NewArray(rtype unsafe.Pointer, length int) unsafe.Pointer 267 268 // packEface converts v to the empty interface. 269 func packEface(v Value) any { 270 t := v.typ 271 var i any 272 e := (*emptyInterface)(unsafe.Pointer(&i)) 273 // First, fill in the data portion of the interface. 274 switch { 275 case ifaceIndir(t): 276 if v.flag&flagIndir == 0 { 277 panic("bad indir") 278 } 279 // Value is indirect, and so is the interface we're making. 280 ptr := v.ptr 281 if v.flag&flagAddr != 0 { 282 // TODO: pass safe boolean from valueInterface so 283 // we don't need to copy if safe==true? 284 c := unsafe_New((unsafe.Pointer)(t)) 285 typedmemmove((unsafe.Pointer)(t), c, ptr) 286 ptr = c 287 } 288 e.word = ptr 289 case v.flag&flagIndir != 0: 290 // Value is indirect, but interface is direct. We need 291 // to load the data at v.ptr into the interface data word. 292 e.word = *(*unsafe.Pointer)(v.ptr) 293 default: 294 // Value is direct, and so is the interface. 295 e.word = v.ptr 296 } 297 // Now, fill in the type portion. We're very careful here not 298 // to have any operation between the e.word and e.typ assignments 299 // that would let the garbage collector observe the partially-built 300 // interface value. 301 e.typ = t 302 return i 303 } 304 305 func valueInterface(v Value, safe bool) any { 306 if v.flag == 0 { 307 //panic(&ValueError{"reflect.Value.Interface", Invalid}) 308 } 309 if safe && v.flag&flagRO != 0 { 310 // Do not allow access to unexported values via Interface, 311 // because they might be pointers that should not be 312 // writable or methods or function that should not be callable. 313 panic("reflect.Value.Interface: cannot return value obtained from unexported field or method") 314 } 315 //// 本身就是个 method 316 if v.flag&flagMethod != 0 { 317 //v = makeMethodValue("Interface", v) 318 } 319 /* 320 if v.kind() == reflect.Interface { 321 // Special case: return the element inside the interface. 322 // Empty interface has one layout, all interfaces with 323 // methods have a second layout. 324 if v.NumMethod() == 0 { 325 return *(*any)(v.ptr) 326 } 327 return *(*interface { 328 M() 329 })(v.ptr) 330 } 331 */ 332 // TODO: pass safe to packEface so we don't need to copy if safe==true? 333 return packEface(v) 334 } 335 336 // Method returns a function value corresponding to v's i'th method. 337 // The arguments to a Call on the returned function should not include 338 // a receiver; the returned function will always use v as the receiver. 339 // Method panics if i is out of range or if v is a nil interface value. 340 func (v Value) Method(i int) Value { 341 if v.typ == nil { 342 //panic(&ValueError{"reflect.Value.Method", Invalid}) 343 } 344 if v.flag&flagMethod != 0 || uint(i) >= uint(v.typ.NumMethod()) { 345 panic("reflect: Method index out of range") 346 } 347 if v.typ.Kind() == reflect.Interface && v.IsNil() { 348 panic("reflect: Method on nil interface value") 349 } 350 fl := v.flag.ro() | (v.flag & flagIndir) 351 fl |= flag(reflect.Func) 352 fl |= flag(i)<<flagMethodShift | flagMethod 353 return Value{v.typ, v.ptr, fl} 354 } 355 356 // IsNil reports whether its argument v is nil. The argument must be 357 // a chan, func, interface, map, pointer, or slice value; if it is 358 // not, IsNil panics. Note that IsNil is not always equivalent to a 359 // regular comparison with nil in Go. For example, if v was created 360 // by calling ValueOf with an uninitialized interface variable i, 361 // i==nil will be true but v.IsNil will panic as v will be the zero 362 // Value. 363 func (v Value) IsNil() bool { 364 k := v.kind() 365 switch k { 366 case reflect.Chan, reflect.Func, reflect.Map, reflect.Pointer, reflect.UnsafePointer: 367 if v.flag&flagMethod != 0 { 368 return false 369 } 370 ptr := v.ptr 371 if v.flag&flagIndir != 0 { 372 ptr = *(*unsafe.Pointer)(ptr) 373 } 374 return ptr == nil 375 case reflect.Interface, reflect.Slice: 376 // Both interface and slice are nil if first word is 0. 377 // Both are always bigger than a word; assume flagIndir. 378 return *(*unsafe.Pointer)(v.ptr) == nil 379 } 380 panic(&reflect.ValueError{Method: "reflect.Value.IsNil", Kind: v.kind()}) 381 } 382 func (t *rtype) Kind() reflect.Kind { return reflect.Kind(t.kind & kindMask) } 383 384 //go:linkname resolveTypeOff reflect.resolveTypeOff 385 func resolveTypeOff(rtype unsafe.Pointer, off int32) unsafe.Pointer 386 387 // ptrMap is the cache for PointerTo. 388 var ptrMap sync.Map // map[*rtype]*ptrType 389 func (t *rtype) typeOff(off typeOff) *rtype { 390 return (*rtype)(resolveTypeOff(unsafe.Pointer(t), int32(off))) 391 } 392 func (t *rtype) uncommon() *uncommonType { 393 if t.tflag&tflagUncommon == 0 { 394 return nil 395 } 396 switch t.Kind() { 397 case reflect.Struct: 398 //return &(*structTypeUncommon)(unsafe.Pointer(t)).u 399 return nil 400 case reflect.Pointer: 401 type u struct { 402 ptrType 403 u uncommonType 404 } 405 return &(*u)(unsafe.Pointer(t)).u 406 407 case reflect.Func: 408 return nil 409 /* type u struct { 410 funcType 411 u uncommonType 412 } 413 return &(*u)(unsafe.Pointer(t)).u 414 case Slice: 415 type u struct { 416 sliceType 417 u uncommonType 418 } 419 return &(*u)(unsafe.Pointer(t)).u 420 case Array: 421 type u struct { 422 arrayType 423 u uncommonType 424 } 425 return &(*u)(unsafe.Pointer(t)).u 426 case Chan: 427 type u struct { 428 chanType 429 u uncommonType 430 } 431 return &(*u)(unsafe.Pointer(t)).u 432 case Map: 433 type u struct { 434 mapType 435 u uncommonType 436 } 437 return &(*u)(unsafe.Pointer(t)).u 438 case Interface: 439 type u struct { 440 interfaceType 441 u uncommonType 442 } 443 return &(*u)(unsafe.Pointer(t)).u 444 */ 445 default: 446 type u struct { 447 rtype 448 u uncommonType 449 } 450 return &(*u)(unsafe.Pointer(t)).u 451 } 452 } 453 454 func resolveNameOff(ptrInModule unsafe.Pointer, off nameOff) name { 455 if off == 0 { 456 return name{} 457 } 458 base := uintptr(ptrInModule) 459 for md := &Firstmoduledata; md != nil; md = md.next { 460 if base >= md.types && base < md.etypes { 461 res := md.types + uintptr(off) 462 if res > md.etypes { 463 //println("runtime: nameOff", hex(off), "out of range", hex(md.types), "-", hex(md.etypes)) 464 //throw("runtime: name offset out of range") 465 } 466 return name{(*byte)(unsafe.Pointer(res))} 467 } 468 } 469 return name{} 470 // No module found. see if it is a run time name. 471 /* 472 reflectOffsLock() 473 res, found := reflectOffs.m[int32(off)] 474 reflectOffsUnlock() 475 if !found { 476 println("runtime: nameOff", hex(off), "base", hex(base), "not in ranges:") 477 for next := &firstmoduledata; next != nil; next = next.next { 478 println("\ttypes", hex(next.types), "etypes", hex(next.etypes)) 479 } 480 throw("runtime: name offset base pointer out of range") 481 } 482 483 return name{(*byte)(res)} 484 */ 485 } 486 487 func reflect_resolveNameOff(ptrInModule unsafe.Pointer, off int32) unsafe.Pointer { 488 return unsafe.Pointer(resolveNameOff(ptrInModule, nameOff(off)).bytes) 489 } 490 491 func (t *rtype) nameOff(off nameOff) name { 492 return name{(*byte)(reflect_resolveNameOff(unsafe.Pointer(t), int32(off)))} 493 } 494 495 func (t *rtype) exportedMethods() []method { 496 ut := t.uncommon() 497 if ut == nil { 498 return nil 499 } 500 return ut.exportedMethods() 501 } 502 503 func (t *rtype) NumMethod() int { 504 if t.Kind() == reflect.Interface { 505 tt := (*interfaceType)(unsafe.Pointer(t)) 506 return tt.NumMethod() 507 } 508 return len(t.exportedMethods()) 509 } 510 511 func (t *rtype) SetMethodByName(name, newName string) { 512 if t.Kind() == reflect.Interface { 513 //tt := (*interfaceType)(unsafe.Pointer(t)) 514 //return tt.MethodByName(name) 515 } 516 ut := t.uncommon() 517 518 // TODO(mdempsky): Binary search. 519 for _, p := range ut.exportedMethods() { 520 if t.nameOff(p.name).name() == name { 521 //return t.Method(i), true 522 //str:=[]byte{'a','d'} 523 //t.nameOff(p.name).bytes = (*byte)(unsafe.Pointer(&str)) 524 } 525 } 526 527 } 528 529 func (t *rtype) MethodByName(name string) (m reflect.Method, ok bool) { 530 if t.Kind() == reflect.Interface { 531 //tt := (*interfaceType)(unsafe.Pointer(t)) 532 //return tt.MethodByName(name) 533 } 534 ut := t.uncommon() 535 if ut == nil { 536 return reflect.Method{}, false 537 } 538 // TODO(mdempsky): Binary search. 539 for _, p := range ut.exportedMethods() { 540 if t.nameOff(p.name).name() == name { 541 //return t.Method(i), true 542 } 543 } 544 return reflect.Method{}, false 545 } 546 547 // add returns p+x. 548 // 549 // The whySafe string is ignored, so that the function still inlines 550 // as efficiently as p+x, but all call sites should use the string to 551 // record why the addition is safe, which is to say why the addition 552 // does not cause x to advance to the very end of p's allocation 553 // and therefore point incorrectly at the next block in memory. 554 func add(p unsafe.Pointer, x uintptr, whySafe string) unsafe.Pointer { 555 return unsafe.Pointer(uintptr(p) + x) 556 } 557 558 func (t *uncommonType) methods() []method { 559 if t.mcount == 0 { 560 return nil 561 } 562 return (*[1 << 16]method)(add(unsafe.Pointer(t), uintptr(t.moff), "t.mcount > 0"))[:t.mcount:t.mcount] 563 } 564 565 func (t *uncommonType) exportedMethods() []method { 566 if t.xcount == 0 { 567 return nil 568 } 569 return (*[1 << 16]method)(add(unsafe.Pointer(t), uintptr(t.moff), "t.xcount > 0"))[:t.xcount:t.xcount] 570 }