@@ -450,21 +450,25 @@ type structType struct {
450450// 1<<1 tag data follows the name
451451// 1<<2 pkgPath nameOff follows the name and tag
452452//
453- // The next two bytes are the data length:
453+ // Following that, there is a varint-encoded length of the name,
454+ // followed by the name itself.
454455//
455- // l := uint16(data[1])<<8 | uint16(data[2])
456- //
457- // Bytes [3:3+l] are the string data.
458- //
459- // If tag data follows then bytes 3+l and 3+l+1 are the tag length,
460- // with the data following.
456+ // If tag data is present, it also has a varint-encoded length
457+ // followed by the tag itself.
461458//
462459// If the import path follows, then 4 bytes at the end of
463460// the data form a nameOff. The import path is only set for concrete
464461// methods that are defined in a different package than their type.
465462//
466463// If a name starts with "*", then the exported bit represents
467464// whether the pointed to type is exported.
465+ //
466+ // Note: this encoding must match here and in:
467+ // cmd/compile/internal/reflectdata/reflect.go
468+ // runtime/type.go
469+ // internal/reflectlite/type.go
470+ // cmd/link/internal/ld/decodesym.go
471+
468472type name struct {
469473bytes * byte
470474}
@@ -477,49 +481,70 @@ func (n name) isExported() bool {
477481return (* n .bytes )& (1 << 0 ) != 0
478482}
479483
480- func (n name ) nameLen () int {
481- return int (uint16 (* n .data (1 , "name len field" ))<< 8 | uint16 (* n .data (2 , "name len field" )))
484+ func (n name ) hasTag () bool {
485+ return (* n .bytes )& (1 << 1 ) != 0
486+ }
487+
488+ // readVarint parses a varint as encoded by encoding/binary.
489+ // It returns the number of encoded bytes and the encoded value.
490+ func (n name ) readVarint (off int ) (int , int ) {
491+ v := 0
492+ for i := 0 ; ; i ++ {
493+ x := * n .data (off + i , "read varint" )
494+ v += int (x & 0x7f ) << (7 * i )
495+ if x & 0x80 == 0 {
496+ return i + 1 , v
497+ }
498+ }
482499}
483500
484- func (n name ) tagLen () int {
485- if * n .data (0 , "name flag field" )& (1 << 1 ) == 0 {
486- return 0
501+ // writeVarint writes n to buf in varint form. Returns the
502+ // number of bytes written. n must be nonnegative.
503+ // Writes at most 10 bytes.
504+ func writeVarint (buf []byte , n int ) int {
505+ for i := 0 ; ; i ++ {
506+ b := byte (n & 0x7f )
507+ n >>= 7
508+ if n == 0 {
509+ buf [i ] = b
510+ return i + 1
511+ }
512+ buf [i ] = b | 0x80
487513}
488- off := 3 + n .nameLen ()
489- return int (uint16 (* n .data (off , "name taglen field" ))<< 8 | uint16 (* n .data (off + 1 , "name taglen field" )))
490514}
491515
492516func (n name ) name () (s string ) {
493517if n .bytes == nil {
494518return
495519}
496- b := (* [4 ]byte )(unsafe .Pointer (n .bytes ))
497-
520+ i , l := n .readVarint (1 )
498521hdr := (* unsafeheader .String )(unsafe .Pointer (& s ))
499- hdr .Data = unsafe .Pointer (& b [ 3 ] )
500- hdr .Len = int ( b [ 1 ]) << 8 | int ( b [ 2 ])
501- return s
522+ hdr .Data = unsafe .Pointer (n . data ( 1 + i , "non-empty string" ) )
523+ hdr .Len = l
524+ return
502525}
503526
504527func (n name ) tag () (s string ) {
505- tl := n .tagLen ()
506- if tl == 0 {
528+ if ! n .hasTag () {
507529return ""
508530}
509- nl := n .nameLen ()
531+ i , l := n .readVarint (1 )
532+ i2 , l2 := n .readVarint (1 + i + l )
510533hdr := (* unsafeheader .String )(unsafe .Pointer (& s ))
511- hdr .Data = unsafe .Pointer (n .data (3 + nl + 2 , "non-empty string" ))
512- hdr .Len = tl
513- return s
534+ hdr .Data = unsafe .Pointer (n .data (1 + i + l + i2 , "non-empty string" ))
535+ hdr .Len = l2
536+ return
514537}
515538
516539func (n name ) pkgPath () string {
517540if n .bytes == nil || * n .data (0 , "name flag field" )& (1 << 2 ) == 0 {
518541return ""
519542}
520- off := 3 + n .nameLen ()
521- if tl := n .tagLen (); tl > 0 {
522- off += 2 + tl
543+ i , l := n .readVarint (1 )
544+ off := 1 + i + l
545+ if n .hasTag () {
546+ i2 , l2 := n .readVarint (off )
547+ off += i2 + l2
523548}
524549var nameOff int32
525550// Note that this field may not be aligned in memory,
@@ -530,33 +555,35 @@ func (n name) pkgPath() string {
530555}
531556
532557func newName (n , tag string , exported bool ) name {
533- if len (n ) > 1 << 16 - 1 {
534- panic ("reflect.nameFrom: name too long: " + n )
558+ if len (n ) >= 1 << 29 {
559+ panic ("reflect.nameFrom: name too long: " + n [: 1024 ] + "..." )
535560}
536- if len (tag ) > 1 << 16 - 1 {
537- panic ("reflect.nameFrom: tag too long: " + tag )
561+ if len (tag ) >= 1 << 29 {
562+ panic ("reflect.nameFrom: tag too long: " + tag [: 1024 ] + "..." )
538563}
564+ var nameLen [10 ]byte
565+ var tagLen [10 ]byte
566+ nameLenLen := writeVarint (nameLen [:], len (n ))
567+ tagLenLen := writeVarint (tagLen [:], len (tag ))
539568
540569var bits byte
541- l := 1 + 2 + len (n )
570+ l := 1 + nameLenLen + len (n )
542571if exported {
543572bits |= 1 << 0
544573}
545574if len (tag ) > 0 {
546- l += 2 + len (tag )
575+ l += tagLenLen + len (tag )
547576bits |= 1 << 1
548577}
549578
550579b := make ([]byte , l )
551580b [0 ] = bits
552- b [1 ] = uint8 (len (n ) >> 8 )
553- b [2 ] = uint8 (len (n ))
554- copy (b [3 :], n )
581+ copy (b [1 :], nameLen [:nameLenLen ])
582+ copy (b [1 + nameLenLen :], n )
555583if len (tag ) > 0 {
556- tb := b [3 + len (n ):]
557- tb [0 ] = uint8 (len (tag ) >> 8 )
558- tb [1 ] = uint8 (len (tag ))
559- copy (tb [2 :], tag )
584+ tb := b [1 + nameLenLen + len (n ):]
585+ copy (tb , tagLen [:tagLenLen ])
586+ copy (tb [tagLenLen :], tag )
560587}
561588
562589return name {bytes : & b [0 ]}
@@ -2570,7 +2597,7 @@ func StructOf(fields []StructField) Type {
25702597hash = fnv1 (hash , byte (ft .hash >> 24 ), byte (ft .hash >> 16 ), byte (ft .hash >> 8 ), byte (ft .hash ))
25712598
25722599repr = append (repr , (" " + ft .String ())... )
2573- if f .name .tagLen () > 0 {
2600+ if f .name .hasTag () {
25742601hash = fnv1 (hash , []byte (f .name .tag ())... )
25752602repr = append (repr , (" " + strconv .Quote (f .name .tag ()))... )
25762603}
0 commit comments