Source file src/internal/abi/type.go

     1  // Copyright 2023 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package abi
     6  
     7  import (
     8  	"unsafe"
     9  )
    10  
    11  // Type is the runtime representation of a Go type.
    12  //
    13  // Be careful about accessing this type at build time, as the version
    14  // of this type in the compiler/linker may not have the same layout
    15  // as the version in the target binary, due to pointer width
    16  // differences and any experiments. Use cmd/compile/internal/rttype
    17  // or the functions in compiletype.go to access this type instead.
    18  // (TODO: this admonition applies to every type in this package.
    19  // Put it in some shared location?)
    20  type Type struct {
    21  	Size_       uintptr
    22  	PtrBytes    uintptr // number of (prefix) bytes in the type that can contain pointers
    23  	Hash        uint32  // hash of type; avoids computation in hash tables
    24  	TFlag       TFlag   // extra type information flags
    25  	Align_      uint8   // alignment of variable with this type
    26  	FieldAlign_ uint8   // alignment of struct field with this type
    27  	Kind_       Kind    // enumeration for C
    28  	// function for comparing objects of this type
    29  	// (ptr to object A, ptr to object B) -> ==?
    30  	Equal func(unsafe.Pointer, unsafe.Pointer) bool
    31  	// GCData stores the GC type data for the garbage collector.
    32  	// If the KindGCProg bit is set in kind, GCData is a GC program.
    33  	// Otherwise it is a ptrmask bitmap. See mbitmap.go for details.
    34  	GCData    *byte
    35  	Str       NameOff // string form
    36  	PtrToThis TypeOff // type for pointer to this type, may be zero
    37  }
    38  
    39  // A Kind represents the specific kind of type that a Type represents.
    40  // The zero Kind is not a valid kind.
    41  type Kind uint8
    42  
    43  const (
    44  	Invalid Kind = iota
    45  	Bool
    46  	Int
    47  	Int8
    48  	Int16
    49  	Int32
    50  	Int64
    51  	Uint
    52  	Uint8
    53  	Uint16
    54  	Uint32
    55  	Uint64
    56  	Uintptr
    57  	Float32
    58  	Float64
    59  	Complex64
    60  	Complex128
    61  	Array
    62  	Chan
    63  	Func
    64  	Interface
    65  	Map
    66  	Pointer
    67  	Slice
    68  	String
    69  	Struct
    70  	UnsafePointer
    71  )
    72  
    73  const (
    74  	// TODO (khr, drchase) why aren't these in TFlag?  Investigate, fix if possible.
    75  	KindDirectIface Kind = 1 << 5
    76  	KindGCProg      Kind = 1 << 6 // Type.gc points to GC program
    77  	KindMask        Kind = (1 << 5) - 1
    78  )
    79  
    80  // TFlag is used by a Type to signal what extra type information is
    81  // available in the memory directly following the Type value.
    82  type TFlag uint8
    83  
    84  const (
    85  	// TFlagUncommon means that there is a data with a type, UncommonType,
    86  	// just beyond the shared-per-type common data.  That is, the data
    87  	// for struct types will store their UncommonType at one offset, the
    88  	// data for interface types will store their UncommonType at a different
    89  	// offset.  UncommonType is always accessed via a pointer that is computed
    90  	// using trust-us-we-are-the-implementors pointer arithmetic.
    91  	//
    92  	// For example, if t.Kind() == Struct and t.tflag&TFlagUncommon != 0,
    93  	// then t has UncommonType data and it can be accessed as:
    94  	//
    95  	//	type structTypeUncommon struct {
    96  	//		structType
    97  	//		u UncommonType
    98  	//	}
    99  	//	u := &(*structTypeUncommon)(unsafe.Pointer(t)).u
   100  	TFlagUncommon TFlag = 1 << 0
   101  
   102  	// TFlagExtraStar means the name in the str field has an
   103  	// extraneous '*' prefix. This is because for most types T in
   104  	// a program, the type *T also exists and reusing the str data
   105  	// saves binary size.
   106  	TFlagExtraStar TFlag = 1 << 1
   107  
   108  	// TFlagNamed means the type has a name.
   109  	TFlagNamed TFlag = 1 << 2
   110  
   111  	// TFlagRegularMemory means that equal and hash functions can treat
   112  	// this type as a single region of t.size bytes.
   113  	TFlagRegularMemory TFlag = 1 << 3
   114  
   115  	// TFlagUnrolledBitmap marks special types that are unrolled-bitmap
   116  	// versions of types with GC programs.
   117  	// These types need to be deallocated when the underlying object
   118  	// is freed.
   119  	TFlagUnrolledBitmap TFlag = 1 << 4
   120  )
   121  
   122  // NameOff is the offset to a name from moduledata.types.  See resolveNameOff in runtime.
   123  type NameOff int32
   124  
   125  // TypeOff is the offset to a type from moduledata.types.  See resolveTypeOff in runtime.
   126  type TypeOff int32
   127  
   128  // TextOff is an offset from the top of a text section.  See (rtype).textOff in runtime.
   129  type TextOff int32
   130  
   131  // String returns the name of k.
   132  func (k Kind) String() string {
   133  	if int(k) < len(kindNames) {
   134  		return kindNames[k]
   135  	}
   136  	return kindNames[0]
   137  }
   138  
   139  var kindNames = []string{
   140  	Invalid:       "invalid",
   141  	Bool:          "bool",
   142  	Int:           "int",
   143  	Int8:          "int8",
   144  	Int16:         "int16",
   145  	Int32:         "int32",
   146  	Int64:         "int64",
   147  	Uint:          "uint",
   148  	Uint8:         "uint8",
   149  	Uint16:        "uint16",
   150  	Uint32:        "uint32",
   151  	Uint64:        "uint64",
   152  	Uintptr:       "uintptr",
   153  	Float32:       "float32",
   154  	Float64:       "float64",
   155  	Complex64:     "complex64",
   156  	Complex128:    "complex128",
   157  	Array:         "array",
   158  	Chan:          "chan",
   159  	Func:          "func",
   160  	Interface:     "interface",
   161  	Map:           "map",
   162  	Pointer:       "ptr",
   163  	Slice:         "slice",
   164  	String:        "string",
   165  	Struct:        "struct",
   166  	UnsafePointer: "unsafe.Pointer",
   167  }
   168  
   169  // TypeOf returns the abi.Type of some value.
   170  func TypeOf(a any) *Type {
   171  	eface := *(*EmptyInterface)(unsafe.Pointer(&a))
   172  	// Types are either static (for compiler-created types) or
   173  	// heap-allocated but always reachable (for reflection-created
   174  	// types, held in the central map). So there is no need to
   175  	// escape types. noescape here help avoid unnecessary escape
   176  	// of v.
   177  	return (*Type)(NoEscape(unsafe.Pointer(eface.Type)))
   178  }
   179  
   180  // TypeFor returns the abi.Type for a type parameter.
   181  func TypeFor[T any]() *Type {
   182  	var v T
   183  	if t := TypeOf(v); t != nil {
   184  		return t // optimize for T being a non-interface kind
   185  	}
   186  	return TypeOf((*T)(nil)).Elem() // only for an interface kind
   187  }
   188  
   189  func (t *Type) Kind() Kind { return t.Kind_ & KindMask }
   190  
   191  func (t *Type) HasName() bool {
   192  	return t.TFlag&TFlagNamed != 0
   193  }
   194  
   195  // Pointers reports whether t contains pointers.
   196  func (t *Type) Pointers() bool { return t.PtrBytes != 0 }
   197  
   198  // IfaceIndir reports whether t is stored indirectly in an interface value.
   199  func (t *Type) IfaceIndir() bool {
   200  	return t.Kind_&KindDirectIface == 0
   201  }
   202  
   203  // isDirectIface reports whether t is stored directly in an interface value.
   204  func (t *Type) IsDirectIface() bool {
   205  	return t.Kind_&KindDirectIface != 0
   206  }
   207  
   208  func (t *Type) GcSlice(begin, end uintptr) []byte {
   209  	return unsafe.Slice(t.GCData, int(end))[begin:]
   210  }
   211  
   212  // Method on non-interface type
   213  type Method struct {
   214  	Name NameOff // name of method
   215  	Mtyp TypeOff // method type (without receiver)
   216  	Ifn  TextOff // fn used in interface call (one-word receiver)
   217  	Tfn  TextOff // fn used for normal method call
   218  }
   219  
   220  // UncommonType is present only for defined types or types with methods
   221  // (if T is a defined type, the uncommonTypes for T and *T have methods).
   222  // Using a pointer to this struct reduces the overall size required
   223  // to describe a non-defined type with no methods.
   224  type UncommonType struct {
   225  	PkgPath NameOff // import path; empty for built-in types like int, string
   226  	Mcount  uint16  // number of methods
   227  	Xcount  uint16  // number of exported methods
   228  	Moff    uint32  // offset from this uncommontype to [mcount]Method
   229  	_       uint32  // unused
   230  }
   231  
   232  func (t *UncommonType) Methods() []Method {
   233  	if t.Mcount == 0 {
   234  		return nil
   235  	}
   236  	return (*[1 << 16]Method)(addChecked(unsafe.Pointer(t), uintptr(t.Moff), "t.mcount > 0"))[:t.Mcount:t.Mcount]
   237  }
   238  
   239  func (t *UncommonType) ExportedMethods() []Method {
   240  	if t.Xcount == 0 {
   241  		return nil
   242  	}
   243  	return (*[1 << 16]Method)(addChecked(unsafe.Pointer(t), uintptr(t.Moff), "t.xcount > 0"))[:t.Xcount:t.Xcount]
   244  }
   245  
   246  // addChecked returns p+x.
   247  //
   248  // The whySafe string is ignored, so that the function still inlines
   249  // as efficiently as p+x, but all call sites should use the string to
   250  // record why the addition is safe, which is to say why the addition
   251  // does not cause x to advance to the very end of p's allocation
   252  // and therefore point incorrectly at the next block in memory.
   253  func addChecked(p unsafe.Pointer, x uintptr, whySafe string) unsafe.Pointer {
   254  	return unsafe.Pointer(uintptr(p) + x)
   255  }
   256  
   257  // Imethod represents a method on an interface type
   258  type Imethod struct {
   259  	Name NameOff // name of method
   260  	Typ  TypeOff // .(*FuncType) underneath
   261  }
   262  
   263  // ArrayType represents a fixed array type.
   264  type ArrayType struct {
   265  	Type
   266  	Elem  *Type // array element type
   267  	Slice *Type // slice type
   268  	Len   uintptr
   269  }
   270  
   271  // Len returns the length of t if t is an array type, otherwise 0
   272  func (t *Type) Len() int {
   273  	if t.Kind() == Array {
   274  		return int((*ArrayType)(unsafe.Pointer(t)).Len)
   275  	}
   276  	return 0
   277  }
   278  
   279  func (t *Type) Common() *Type {
   280  	return t
   281  }
   282  
   283  type ChanDir int
   284  
   285  const (
   286  	RecvDir    ChanDir = 1 << iota         // <-chan
   287  	SendDir                                // chan<-
   288  	BothDir            = RecvDir | SendDir // chan
   289  	InvalidDir ChanDir = 0
   290  )
   291  
   292  // ChanType represents a channel type
   293  type ChanType struct {
   294  	Type
   295  	Elem *Type
   296  	Dir  ChanDir
   297  }
   298  
   299  type structTypeUncommon struct {
   300  	StructType
   301  	u UncommonType
   302  }
   303  
   304  // ChanDir returns the direction of t if t is a channel type, otherwise InvalidDir (0).
   305  func (t *Type) ChanDir() ChanDir {
   306  	if t.Kind() == Chan {
   307  		ch := (*ChanType)(unsafe.Pointer(t))
   308  		return ch.Dir
   309  	}
   310  	return InvalidDir
   311  }
   312  
   313  // Uncommon returns a pointer to T's "uncommon" data if there is any, otherwise nil
   314  func (t *Type) Uncommon() *UncommonType {
   315  	if t.TFlag&TFlagUncommon == 0 {
   316  		return nil
   317  	}
   318  	switch t.Kind() {
   319  	case Struct:
   320  		return &(*structTypeUncommon)(unsafe.Pointer(t)).u
   321  	case Pointer:
   322  		type u struct {
   323  			PtrType
   324  			u UncommonType
   325  		}
   326  		return &(*u)(unsafe.Pointer(t)).u
   327  	case Func:
   328  		type u struct {
   329  			FuncType
   330  			u UncommonType
   331  		}
   332  		return &(*u)(unsafe.Pointer(t)).u
   333  	case Slice:
   334  		type u struct {
   335  			SliceType
   336  			u UncommonType
   337  		}
   338  		return &(*u)(unsafe.Pointer(t)).u
   339  	case Array:
   340  		type u struct {
   341  			ArrayType
   342  			u UncommonType
   343  		}
   344  		return &(*u)(unsafe.Pointer(t)).u
   345  	case Chan:
   346  		type u struct {
   347  			ChanType
   348  			u UncommonType
   349  		}
   350  		return &(*u)(unsafe.Pointer(t)).u
   351  	case Map:
   352  		type u struct {
   353  			MapType
   354  			u UncommonType
   355  		}
   356  		return &(*u)(unsafe.Pointer(t)).u
   357  	case Interface:
   358  		type u struct {
   359  			InterfaceType
   360  			u UncommonType
   361  		}
   362  		return &(*u)(unsafe.Pointer(t)).u
   363  	default:
   364  		type u struct {
   365  			Type
   366  			u UncommonType
   367  		}
   368  		return &(*u)(unsafe.Pointer(t)).u
   369  	}
   370  }
   371  
   372  // Elem returns the element type for t if t is an array, channel, map, pointer, or slice, otherwise nil.
   373  func (t *Type) Elem() *Type {
   374  	switch t.Kind() {
   375  	case Array:
   376  		tt := (*ArrayType)(unsafe.Pointer(t))
   377  		return tt.Elem
   378  	case Chan:
   379  		tt := (*ChanType)(unsafe.Pointer(t))
   380  		return tt.Elem
   381  	case Map:
   382  		tt := (*MapType)(unsafe.Pointer(t))
   383  		return tt.Elem
   384  	case Pointer:
   385  		tt := (*PtrType)(unsafe.Pointer(t))
   386  		return tt.Elem
   387  	case Slice:
   388  		tt := (*SliceType)(unsafe.Pointer(t))
   389  		return tt.Elem
   390  	}
   391  	return nil
   392  }
   393  
   394  // StructType returns t cast to a *StructType, or nil if its tag does not match.
   395  func (t *Type) StructType() *StructType {
   396  	if t.Kind() != Struct {
   397  		return nil
   398  	}
   399  	return (*StructType)(unsafe.Pointer(t))
   400  }
   401  
   402  // MapType returns t cast to a *MapType, or nil if its tag does not match.
   403  func (t *Type) MapType() *MapType {
   404  	if t.Kind() != Map {
   405  		return nil
   406  	}
   407  	return (*MapType)(unsafe.Pointer(t))
   408  }
   409  
   410  // ArrayType returns t cast to a *ArrayType, or nil if its tag does not match.
   411  func (t *Type) ArrayType() *ArrayType {
   412  	if t.Kind() != Array {
   413  		return nil
   414  	}
   415  	return (*ArrayType)(unsafe.Pointer(t))
   416  }
   417  
   418  // FuncType returns t cast to a *FuncType, or nil if its tag does not match.
   419  func (t *Type) FuncType() *FuncType {
   420  	if t.Kind() != Func {
   421  		return nil
   422  	}
   423  	return (*FuncType)(unsafe.Pointer(t))
   424  }
   425  
   426  // InterfaceType returns t cast to a *InterfaceType, or nil if its tag does not match.
   427  func (t *Type) InterfaceType() *InterfaceType {
   428  	if t.Kind() != Interface {
   429  		return nil
   430  	}
   431  	return (*InterfaceType)(unsafe.Pointer(t))
   432  }
   433  
   434  // Size returns the size of data with type t.
   435  func (t *Type) Size() uintptr { return t.Size_ }
   436  
   437  // Align returns the alignment of data with type t.
   438  func (t *Type) Align() int { return int(t.Align_) }
   439  
   440  func (t *Type) FieldAlign() int { return int(t.FieldAlign_) }
   441  
   442  type InterfaceType struct {
   443  	Type
   444  	PkgPath Name      // import path
   445  	Methods []Imethod // sorted by hash
   446  }
   447  
   448  func (t *Type) ExportedMethods() []Method {
   449  	ut := t.Uncommon()
   450  	if ut == nil {
   451  		return nil
   452  	}
   453  	return ut.ExportedMethods()
   454  }
   455  
   456  func (t *Type) NumMethod() int {
   457  	if t.Kind() == Interface {
   458  		tt := (*InterfaceType)(unsafe.Pointer(t))
   459  		return tt.NumMethod()
   460  	}
   461  	return len(t.ExportedMethods())
   462  }
   463  
   464  // NumMethod returns the number of interface methods in the type's method set.
   465  func (t *InterfaceType) NumMethod() int { return len(t.Methods) }
   466  
   467  type MapType struct {
   468  	Type
   469  	Key    *Type
   470  	Elem   *Type
   471  	Bucket *Type // internal type representing a hash bucket
   472  	// function for hashing keys (ptr to key, seed) -> hash
   473  	Hasher     func(unsafe.Pointer, uintptr) uintptr
   474  	KeySize    uint8  // size of key slot
   475  	ValueSize  uint8  // size of elem slot
   476  	BucketSize uint16 // size of bucket
   477  	Flags      uint32
   478  }
   479  
   480  // Note: flag values must match those used in the TMAP case
   481  // in ../cmd/compile/internal/reflectdata/reflect.go:writeType.
   482  func (mt *MapType) IndirectKey() bool { // store ptr to key instead of key itself
   483  	return mt.Flags&1 != 0
   484  }
   485  func (mt *MapType) IndirectElem() bool { // store ptr to elem instead of elem itself
   486  	return mt.Flags&2 != 0
   487  }
   488  func (mt *MapType) ReflexiveKey() bool { // true if k==k for all keys
   489  	return mt.Flags&4 != 0
   490  }
   491  func (mt *MapType) NeedKeyUpdate() bool { // true if we need to update key on an overwrite
   492  	return mt.Flags&8 != 0
   493  }
   494  func (mt *MapType) HashMightPanic() bool { // true if hash function might panic
   495  	return mt.Flags&16 != 0
   496  }
   497  
   498  func (t *Type) Key() *Type {
   499  	if t.Kind() == Map {
   500  		return (*MapType)(unsafe.Pointer(t)).Key
   501  	}
   502  	return nil
   503  }
   504  
   505  type SliceType struct {
   506  	Type
   507  	Elem *Type // slice element type
   508  }
   509  
   510  // funcType represents a function type.
   511  //
   512  // A *Type for each in and out parameter is stored in an array that
   513  // directly follows the funcType (and possibly its uncommonType). So
   514  // a function type with one method, one input, and one output is:
   515  //
   516  //	struct {
   517  //		funcType
   518  //		uncommonType
   519  //		[2]*rtype    // [0] is in, [1] is out
   520  //	}
   521  type FuncType struct {
   522  	Type
   523  	InCount  uint16
   524  	OutCount uint16 // top bit is set if last input parameter is ...
   525  }
   526  
   527  func (t *FuncType) In(i int) *Type {
   528  	return t.InSlice()[i]
   529  }
   530  
   531  func (t *FuncType) NumIn() int {
   532  	return int(t.InCount)
   533  }
   534  
   535  func (t *FuncType) NumOut() int {
   536  	return int(t.OutCount & (1<<15 - 1))
   537  }
   538  
   539  func (t *FuncType) Out(i int) *Type {
   540  	return (t.OutSlice()[i])
   541  }
   542  
   543  func (t *FuncType) InSlice() []*Type {
   544  	uadd := unsafe.Sizeof(*t)
   545  	if t.TFlag&TFlagUncommon != 0 {
   546  		uadd += unsafe.Sizeof(UncommonType{})
   547  	}
   548  	if t.InCount == 0 {
   549  		return nil
   550  	}
   551  	return (*[1 << 16]*Type)(addChecked(unsafe.Pointer(t), uadd, "t.inCount > 0"))[:t.InCount:t.InCount]
   552  }
   553  func (t *FuncType) OutSlice() []*Type {
   554  	outCount := uint16(t.NumOut())
   555  	if outCount == 0 {
   556  		return nil
   557  	}
   558  	uadd := unsafe.Sizeof(*t)
   559  	if t.TFlag&TFlagUncommon != 0 {
   560  		uadd += unsafe.Sizeof(UncommonType{})
   561  	}
   562  	return (*[1 << 17]*Type)(addChecked(unsafe.Pointer(t), uadd, "outCount > 0"))[t.InCount : t.InCount+outCount : t.InCount+outCount]
   563  }
   564  
   565  func (t *FuncType) IsVariadic() bool {
   566  	return t.OutCount&(1<<15) != 0
   567  }
   568  
   569  type PtrType struct {
   570  	Type
   571  	Elem *Type // pointer element (pointed at) type
   572  }
   573  
   574  type StructField struct {
   575  	Name   Name    // name is always non-empty
   576  	Typ    *Type   // type of field
   577  	Offset uintptr // byte offset of field
   578  }
   579  
   580  func (f *StructField) Embedded() bool {
   581  	return f.Name.IsEmbedded()
   582  }
   583  
   584  type StructType struct {
   585  	Type
   586  	PkgPath Name
   587  	Fields  []StructField
   588  }
   589  
   590  // Name is an encoded type Name with optional extra data.
   591  //
   592  // The first byte is a bit field containing:
   593  //
   594  //	1<<0 the name is exported
   595  //	1<<1 tag data follows the name
   596  //	1<<2 pkgPath nameOff follows the name and tag
   597  //	1<<3 the name is of an embedded (a.k.a. anonymous) field
   598  //
   599  // Following that, there is a varint-encoded length of the name,
   600  // followed by the name itself.
   601  //
   602  // If tag data is present, it also has a varint-encoded length
   603  // followed by the tag itself.
   604  //
   605  // If the import path follows, then 4 bytes at the end of
   606  // the data form a nameOff. The import path is only set for concrete
   607  // methods that are defined in a different package than their type.
   608  //
   609  // If a name starts with "*", then the exported bit represents
   610  // whether the pointed to type is exported.
   611  //
   612  // Note: this encoding must match here and in:
   613  //   cmd/compile/internal/reflectdata/reflect.go
   614  //   cmd/link/internal/ld/decodesym.go
   615  
   616  type Name struct {
   617  	Bytes *byte
   618  }
   619  
   620  // DataChecked does pointer arithmetic on n's Bytes, and that arithmetic is asserted to
   621  // be safe for the reason in whySafe (which can appear in a backtrace, etc.)
   622  func (n Name) DataChecked(off int, whySafe string) *byte {
   623  	return (*byte)(addChecked(unsafe.Pointer(n.Bytes), uintptr(off), whySafe))
   624  }
   625  
   626  // Data does pointer arithmetic on n's Bytes, and that arithmetic is asserted to
   627  // be safe because the runtime made the call (other packages use DataChecked)
   628  func (n Name) Data(off int) *byte {
   629  	return (*byte)(addChecked(unsafe.Pointer(n.Bytes), uintptr(off), "the runtime doesn't need to give you a reason"))
   630  }
   631  
   632  // IsExported returns "is n exported?"
   633  func (n Name) IsExported() bool {
   634  	return (*n.Bytes)&(1<<0) != 0
   635  }
   636  
   637  // HasTag returns true iff there is tag data following this name
   638  func (n Name) HasTag() bool {
   639  	return (*n.Bytes)&(1<<1) != 0
   640  }
   641  
   642  // IsEmbedded returns true iff n is embedded (an anonymous field).
   643  func (n Name) IsEmbedded() bool {
   644  	return (*n.Bytes)&(1<<3) != 0
   645  }
   646  
   647  // ReadVarint parses a varint as encoded by encoding/binary.
   648  // It returns the number of encoded bytes and the encoded value.
   649  func (n Name) ReadVarint(off int) (int, int) {
   650  	v := 0
   651  	for i := 0; ; i++ {
   652  		x := *n.DataChecked(off+i, "read varint")
   653  		v += int(x&0x7f) << (7 * i)
   654  		if x&0x80 == 0 {
   655  			return i + 1, v
   656  		}
   657  	}
   658  }
   659  
   660  // IsBlank indicates whether n is "_".
   661  func (n Name) IsBlank() bool {
   662  	if n.Bytes == nil {
   663  		return false
   664  	}
   665  	_, l := n.ReadVarint(1)
   666  	return l == 1 && *n.Data(2) == '_'
   667  }
   668  
   669  // writeVarint writes n to buf in varint form. Returns the
   670  // number of bytes written. n must be nonnegative.
   671  // Writes at most 10 bytes.
   672  func writeVarint(buf []byte, n int) int {
   673  	for i := 0; ; i++ {
   674  		b := byte(n & 0x7f)
   675  		n >>= 7
   676  		if n == 0 {
   677  			buf[i] = b
   678  			return i + 1
   679  		}
   680  		buf[i] = b | 0x80
   681  	}
   682  }
   683  
   684  // Name returns the tag string for n, or empty if there is none.
   685  func (n Name) Name() string {
   686  	if n.Bytes == nil {
   687  		return ""
   688  	}
   689  	i, l := n.ReadVarint(1)
   690  	return unsafe.String(n.DataChecked(1+i, "non-empty string"), l)
   691  }
   692  
   693  // Tag returns the tag string for n, or empty if there is none.
   694  func (n Name) Tag() string {
   695  	if !n.HasTag() {
   696  		return ""
   697  	}
   698  	i, l := n.ReadVarint(1)
   699  	i2, l2 := n.ReadVarint(1 + i + l)
   700  	return unsafe.String(n.DataChecked(1+i+l+i2, "non-empty string"), l2)
   701  }
   702  
   703  func NewName(n, tag string, exported, embedded bool) Name {
   704  	if len(n) >= 1<<29 {
   705  		panic("abi.NewName: name too long: " + n[:1024] + "...")
   706  	}
   707  	if len(tag) >= 1<<29 {
   708  		panic("abi.NewName: tag too long: " + tag[:1024] + "...")
   709  	}
   710  	var nameLen [10]byte
   711  	var tagLen [10]byte
   712  	nameLenLen := writeVarint(nameLen[:], len(n))
   713  	tagLenLen := writeVarint(tagLen[:], len(tag))
   714  
   715  	var bits byte
   716  	l := 1 + nameLenLen + len(n)
   717  	if exported {
   718  		bits |= 1 << 0
   719  	}
   720  	if len(tag) > 0 {
   721  		l += tagLenLen + len(tag)
   722  		bits |= 1 << 1
   723  	}
   724  	if embedded {
   725  		bits |= 1 << 3
   726  	}
   727  
   728  	b := make([]byte, l)
   729  	b[0] = bits
   730  	copy(b[1:], nameLen[:nameLenLen])
   731  	copy(b[1+nameLenLen:], n)
   732  	if len(tag) > 0 {
   733  		tb := b[1+nameLenLen+len(n):]
   734  		copy(tb, tagLen[:tagLenLen])
   735  		copy(tb[tagLenLen:], tag)
   736  	}
   737  
   738  	return Name{Bytes: &b[0]}
   739  }
   740  
   741  const (
   742  	TraceArgsLimit    = 10 // print no more than 10 args/components
   743  	TraceArgsMaxDepth = 5  // no more than 5 layers of nesting
   744  
   745  	// maxLen is a (conservative) upper bound of the byte stream length. For
   746  	// each arg/component, it has no more than 2 bytes of data (size, offset),
   747  	// and no more than one {, }, ... at each level (it cannot have both the
   748  	// data and ... unless it is the last one, just be conservative). Plus 1
   749  	// for _endSeq.
   750  	TraceArgsMaxLen = (TraceArgsMaxDepth*3+2)*TraceArgsLimit + 1
   751  )
   752  
   753  // Populate the data.
   754  // The data is a stream of bytes, which contains the offsets and sizes of the
   755  // non-aggregate arguments or non-aggregate fields/elements of aggregate-typed
   756  // arguments, along with special "operators". Specifically,
   757  //   - for each non-aggregate arg/field/element, its offset from FP (1 byte) and
   758  //     size (1 byte)
   759  //   - special operators:
   760  //   - 0xff - end of sequence
   761  //   - 0xfe - print { (at the start of an aggregate-typed argument)
   762  //   - 0xfd - print } (at the end of an aggregate-typed argument)
   763  //   - 0xfc - print ... (more args/fields/elements)
   764  //   - 0xfb - print _ (offset too large)
   765  const (
   766  	TraceArgsEndSeq         = 0xff
   767  	TraceArgsStartAgg       = 0xfe
   768  	TraceArgsEndAgg         = 0xfd
   769  	TraceArgsDotdotdot      = 0xfc
   770  	TraceArgsOffsetTooLarge = 0xfb
   771  	TraceArgsSpecial        = 0xf0 // above this are operators, below this are ordinary offsets
   772  )
   773  
   774  // MaxPtrmaskBytes is the maximum length of a GC ptrmask bitmap,
   775  // which holds 1-bit entries describing where pointers are in a given type.
   776  // Above this length, the GC information is recorded as a GC program,
   777  // which can express repetition compactly. In either form, the
   778  // information is used by the runtime to initialize the heap bitmap,
   779  // and for large types (like 128 or more words), they are roughly the
   780  // same speed. GC programs are never much larger and often more
   781  // compact. (If large arrays are involved, they can be arbitrarily
   782  // more compact.)
   783  //
   784  // The cutoff must be large enough that any allocation large enough to
   785  // use a GC program is large enough that it does not share heap bitmap
   786  // bytes with any other objects, allowing the GC program execution to
   787  // assume an aligned start and not use atomic operations. In the current
   788  // runtime, this means all malloc size classes larger than the cutoff must
   789  // be multiples of four words. On 32-bit systems that's 16 bytes, and
   790  // all size classes >= 16 bytes are 16-byte aligned, so no real constraint.
   791  // On 64-bit systems, that's 32 bytes, and 32-byte alignment is guaranteed
   792  // for size classes >= 256 bytes. On a 64-bit system, 256 bytes allocated
   793  // is 32 pointers, the bits for which fit in 4 bytes. So MaxPtrmaskBytes
   794  // must be >= 4.
   795  //
   796  // We used to use 16 because the GC programs do have some constant overhead
   797  // to get started, and processing 128 pointers seems to be enough to
   798  // amortize that overhead well.
   799  //
   800  // To make sure that the runtime's chansend can call typeBitsBulkBarrier,
   801  // we raised the limit to 2048, so that even 32-bit systems are guaranteed to
   802  // use bitmaps for objects up to 64 kB in size.
   803  const MaxPtrmaskBytes = 2048
   804  

View as plain text