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  func (t *Type) Kind() Kind { return t.Kind_ & KindMask }
   181  
   182  func (t *Type) HasName() bool {
   183  	return t.TFlag&TFlagNamed != 0
   184  }
   185  
   186  // Pointers reports whether t contains pointers.
   187  func (t *Type) Pointers() bool { return t.PtrBytes != 0 }
   188  
   189  // IfaceIndir reports whether t is stored indirectly in an interface value.
   190  func (t *Type) IfaceIndir() bool {
   191  	return t.Kind_&KindDirectIface == 0
   192  }
   193  
   194  // isDirectIface reports whether t is stored directly in an interface value.
   195  func (t *Type) IsDirectIface() bool {
   196  	return t.Kind_&KindDirectIface != 0
   197  }
   198  
   199  func (t *Type) GcSlice(begin, end uintptr) []byte {
   200  	return unsafe.Slice(t.GCData, int(end))[begin:]
   201  }
   202  
   203  // Method on non-interface type
   204  type Method struct {
   205  	Name NameOff // name of method
   206  	Mtyp TypeOff // method type (without receiver)
   207  	Ifn  TextOff // fn used in interface call (one-word receiver)
   208  	Tfn  TextOff // fn used for normal method call
   209  }
   210  
   211  // UncommonType is present only for defined types or types with methods
   212  // (if T is a defined type, the uncommonTypes for T and *T have methods).
   213  // Using a pointer to this struct reduces the overall size required
   214  // to describe a non-defined type with no methods.
   215  type UncommonType struct {
   216  	PkgPath NameOff // import path; empty for built-in types like int, string
   217  	Mcount  uint16  // number of methods
   218  	Xcount  uint16  // number of exported methods
   219  	Moff    uint32  // offset from this uncommontype to [mcount]Method
   220  	_       uint32  // unused
   221  }
   222  
   223  func (t *UncommonType) Methods() []Method {
   224  	if t.Mcount == 0 {
   225  		return nil
   226  	}
   227  	return (*[1 << 16]Method)(addChecked(unsafe.Pointer(t), uintptr(t.Moff), "t.mcount > 0"))[:t.Mcount:t.Mcount]
   228  }
   229  
   230  func (t *UncommonType) ExportedMethods() []Method {
   231  	if t.Xcount == 0 {
   232  		return nil
   233  	}
   234  	return (*[1 << 16]Method)(addChecked(unsafe.Pointer(t), uintptr(t.Moff), "t.xcount > 0"))[:t.Xcount:t.Xcount]
   235  }
   236  
   237  // addChecked returns p+x.
   238  //
   239  // The whySafe string is ignored, so that the function still inlines
   240  // as efficiently as p+x, but all call sites should use the string to
   241  // record why the addition is safe, which is to say why the addition
   242  // does not cause x to advance to the very end of p's allocation
   243  // and therefore point incorrectly at the next block in memory.
   244  func addChecked(p unsafe.Pointer, x uintptr, whySafe string) unsafe.Pointer {
   245  	return unsafe.Pointer(uintptr(p) + x)
   246  }
   247  
   248  // Imethod represents a method on an interface type
   249  type Imethod struct {
   250  	Name NameOff // name of method
   251  	Typ  TypeOff // .(*FuncType) underneath
   252  }
   253  
   254  // ArrayType represents a fixed array type.
   255  type ArrayType struct {
   256  	Type
   257  	Elem  *Type // array element type
   258  	Slice *Type // slice type
   259  	Len   uintptr
   260  }
   261  
   262  // Len returns the length of t if t is an array type, otherwise 0
   263  func (t *Type) Len() int {
   264  	if t.Kind() == Array {
   265  		return int((*ArrayType)(unsafe.Pointer(t)).Len)
   266  	}
   267  	return 0
   268  }
   269  
   270  func (t *Type) Common() *Type {
   271  	return t
   272  }
   273  
   274  type ChanDir int
   275  
   276  const (
   277  	RecvDir    ChanDir = 1 << iota         // <-chan
   278  	SendDir                                // chan<-
   279  	BothDir            = RecvDir | SendDir // chan
   280  	InvalidDir ChanDir = 0
   281  )
   282  
   283  // ChanType represents a channel type
   284  type ChanType struct {
   285  	Type
   286  	Elem *Type
   287  	Dir  ChanDir
   288  }
   289  
   290  type structTypeUncommon struct {
   291  	StructType
   292  	u UncommonType
   293  }
   294  
   295  // ChanDir returns the direction of t if t is a channel type, otherwise InvalidDir (0).
   296  func (t *Type) ChanDir() ChanDir {
   297  	if t.Kind() == Chan {
   298  		ch := (*ChanType)(unsafe.Pointer(t))
   299  		return ch.Dir
   300  	}
   301  	return InvalidDir
   302  }
   303  
   304  // Uncommon returns a pointer to T's "uncommon" data if there is any, otherwise nil
   305  func (t *Type) Uncommon() *UncommonType {
   306  	if t.TFlag&TFlagUncommon == 0 {
   307  		return nil
   308  	}
   309  	switch t.Kind() {
   310  	case Struct:
   311  		return &(*structTypeUncommon)(unsafe.Pointer(t)).u
   312  	case Pointer:
   313  		type u struct {
   314  			PtrType
   315  			u UncommonType
   316  		}
   317  		return &(*u)(unsafe.Pointer(t)).u
   318  	case Func:
   319  		type u struct {
   320  			FuncType
   321  			u UncommonType
   322  		}
   323  		return &(*u)(unsafe.Pointer(t)).u
   324  	case Slice:
   325  		type u struct {
   326  			SliceType
   327  			u UncommonType
   328  		}
   329  		return &(*u)(unsafe.Pointer(t)).u
   330  	case Array:
   331  		type u struct {
   332  			ArrayType
   333  			u UncommonType
   334  		}
   335  		return &(*u)(unsafe.Pointer(t)).u
   336  	case Chan:
   337  		type u struct {
   338  			ChanType
   339  			u UncommonType
   340  		}
   341  		return &(*u)(unsafe.Pointer(t)).u
   342  	case Map:
   343  		type u struct {
   344  			MapType
   345  			u UncommonType
   346  		}
   347  		return &(*u)(unsafe.Pointer(t)).u
   348  	case Interface:
   349  		type u struct {
   350  			InterfaceType
   351  			u UncommonType
   352  		}
   353  		return &(*u)(unsafe.Pointer(t)).u
   354  	default:
   355  		type u struct {
   356  			Type
   357  			u UncommonType
   358  		}
   359  		return &(*u)(unsafe.Pointer(t)).u
   360  	}
   361  }
   362  
   363  // Elem returns the element type for t if t is an array, channel, map, pointer, or slice, otherwise nil.
   364  func (t *Type) Elem() *Type {
   365  	switch t.Kind() {
   366  	case Array:
   367  		tt := (*ArrayType)(unsafe.Pointer(t))
   368  		return tt.Elem
   369  	case Chan:
   370  		tt := (*ChanType)(unsafe.Pointer(t))
   371  		return tt.Elem
   372  	case Map:
   373  		tt := (*MapType)(unsafe.Pointer(t))
   374  		return tt.Elem
   375  	case Pointer:
   376  		tt := (*PtrType)(unsafe.Pointer(t))
   377  		return tt.Elem
   378  	case Slice:
   379  		tt := (*SliceType)(unsafe.Pointer(t))
   380  		return tt.Elem
   381  	}
   382  	return nil
   383  }
   384  
   385  // StructType returns t cast to a *StructType, or nil if its tag does not match.
   386  func (t *Type) StructType() *StructType {
   387  	if t.Kind() != Struct {
   388  		return nil
   389  	}
   390  	return (*StructType)(unsafe.Pointer(t))
   391  }
   392  
   393  // MapType returns t cast to a *MapType, or nil if its tag does not match.
   394  func (t *Type) MapType() *MapType {
   395  	if t.Kind() != Map {
   396  		return nil
   397  	}
   398  	return (*MapType)(unsafe.Pointer(t))
   399  }
   400  
   401  // ArrayType returns t cast to a *ArrayType, or nil if its tag does not match.
   402  func (t *Type) ArrayType() *ArrayType {
   403  	if t.Kind() != Array {
   404  		return nil
   405  	}
   406  	return (*ArrayType)(unsafe.Pointer(t))
   407  }
   408  
   409  // FuncType returns t cast to a *FuncType, or nil if its tag does not match.
   410  func (t *Type) FuncType() *FuncType {
   411  	if t.Kind() != Func {
   412  		return nil
   413  	}
   414  	return (*FuncType)(unsafe.Pointer(t))
   415  }
   416  
   417  // InterfaceType returns t cast to a *InterfaceType, or nil if its tag does not match.
   418  func (t *Type) InterfaceType() *InterfaceType {
   419  	if t.Kind() != Interface {
   420  		return nil
   421  	}
   422  	return (*InterfaceType)(unsafe.Pointer(t))
   423  }
   424  
   425  // Size returns the size of data with type t.
   426  func (t *Type) Size() uintptr { return t.Size_ }
   427  
   428  // Align returns the alignment of data with type t.
   429  func (t *Type) Align() int { return int(t.Align_) }
   430  
   431  func (t *Type) FieldAlign() int { return int(t.FieldAlign_) }
   432  
   433  type InterfaceType struct {
   434  	Type
   435  	PkgPath Name      // import path
   436  	Methods []Imethod // sorted by hash
   437  }
   438  
   439  func (t *Type) ExportedMethods() []Method {
   440  	ut := t.Uncommon()
   441  	if ut == nil {
   442  		return nil
   443  	}
   444  	return ut.ExportedMethods()
   445  }
   446  
   447  func (t *Type) NumMethod() int {
   448  	if t.Kind() == Interface {
   449  		tt := (*InterfaceType)(unsafe.Pointer(t))
   450  		return tt.NumMethod()
   451  	}
   452  	return len(t.ExportedMethods())
   453  }
   454  
   455  // NumMethod returns the number of interface methods in the type's method set.
   456  func (t *InterfaceType) NumMethod() int { return len(t.Methods) }
   457  
   458  type MapType struct {
   459  	Type
   460  	Key    *Type
   461  	Elem   *Type
   462  	Bucket *Type // internal type representing a hash bucket
   463  	// function for hashing keys (ptr to key, seed) -> hash
   464  	Hasher     func(unsafe.Pointer, uintptr) uintptr
   465  	KeySize    uint8  // size of key slot
   466  	ValueSize  uint8  // size of elem slot
   467  	BucketSize uint16 // size of bucket
   468  	Flags      uint32
   469  }
   470  
   471  // Note: flag values must match those used in the TMAP case
   472  // in ../cmd/compile/internal/reflectdata/reflect.go:writeType.
   473  func (mt *MapType) IndirectKey() bool { // store ptr to key instead of key itself
   474  	return mt.Flags&1 != 0
   475  }
   476  func (mt *MapType) IndirectElem() bool { // store ptr to elem instead of elem itself
   477  	return mt.Flags&2 != 0
   478  }
   479  func (mt *MapType) ReflexiveKey() bool { // true if k==k for all keys
   480  	return mt.Flags&4 != 0
   481  }
   482  func (mt *MapType) NeedKeyUpdate() bool { // true if we need to update key on an overwrite
   483  	return mt.Flags&8 != 0
   484  }
   485  func (mt *MapType) HashMightPanic() bool { // true if hash function might panic
   486  	return mt.Flags&16 != 0
   487  }
   488  
   489  func (t *Type) Key() *Type {
   490  	if t.Kind() == Map {
   491  		return (*MapType)(unsafe.Pointer(t)).Key
   492  	}
   493  	return nil
   494  }
   495  
   496  type SliceType struct {
   497  	Type
   498  	Elem *Type // slice element type
   499  }
   500  
   501  // funcType represents a function type.
   502  //
   503  // A *Type for each in and out parameter is stored in an array that
   504  // directly follows the funcType (and possibly its uncommonType). So
   505  // a function type with one method, one input, and one output is:
   506  //
   507  //	struct {
   508  //		funcType
   509  //		uncommonType
   510  //		[2]*rtype    // [0] is in, [1] is out
   511  //	}
   512  type FuncType struct {
   513  	Type
   514  	InCount  uint16
   515  	OutCount uint16 // top bit is set if last input parameter is ...
   516  }
   517  
   518  func (t *FuncType) In(i int) *Type {
   519  	return t.InSlice()[i]
   520  }
   521  
   522  func (t *FuncType) NumIn() int {
   523  	return int(t.InCount)
   524  }
   525  
   526  func (t *FuncType) NumOut() int {
   527  	return int(t.OutCount & (1<<15 - 1))
   528  }
   529  
   530  func (t *FuncType) Out(i int) *Type {
   531  	return (t.OutSlice()[i])
   532  }
   533  
   534  func (t *FuncType) InSlice() []*Type {
   535  	uadd := unsafe.Sizeof(*t)
   536  	if t.TFlag&TFlagUncommon != 0 {
   537  		uadd += unsafe.Sizeof(UncommonType{})
   538  	}
   539  	if t.InCount == 0 {
   540  		return nil
   541  	}
   542  	return (*[1 << 16]*Type)(addChecked(unsafe.Pointer(t), uadd, "t.inCount > 0"))[:t.InCount:t.InCount]
   543  }
   544  func (t *FuncType) OutSlice() []*Type {
   545  	outCount := uint16(t.NumOut())
   546  	if outCount == 0 {
   547  		return nil
   548  	}
   549  	uadd := unsafe.Sizeof(*t)
   550  	if t.TFlag&TFlagUncommon != 0 {
   551  		uadd += unsafe.Sizeof(UncommonType{})
   552  	}
   553  	return (*[1 << 17]*Type)(addChecked(unsafe.Pointer(t), uadd, "outCount > 0"))[t.InCount : t.InCount+outCount : t.InCount+outCount]
   554  }
   555  
   556  func (t *FuncType) IsVariadic() bool {
   557  	return t.OutCount&(1<<15) != 0
   558  }
   559  
   560  type PtrType struct {
   561  	Type
   562  	Elem *Type // pointer element (pointed at) type
   563  }
   564  
   565  type StructField struct {
   566  	Name   Name    // name is always non-empty
   567  	Typ    *Type   // type of field
   568  	Offset uintptr // byte offset of field
   569  }
   570  
   571  func (f *StructField) Embedded() bool {
   572  	return f.Name.IsEmbedded()
   573  }
   574  
   575  type StructType struct {
   576  	Type
   577  	PkgPath Name
   578  	Fields  []StructField
   579  }
   580  
   581  // Name is an encoded type Name with optional extra data.
   582  //
   583  // The first byte is a bit field containing:
   584  //
   585  //	1<<0 the name is exported
   586  //	1<<1 tag data follows the name
   587  //	1<<2 pkgPath nameOff follows the name and tag
   588  //	1<<3 the name is of an embedded (a.k.a. anonymous) field
   589  //
   590  // Following that, there is a varint-encoded length of the name,
   591  // followed by the name itself.
   592  //
   593  // If tag data is present, it also has a varint-encoded length
   594  // followed by the tag itself.
   595  //
   596  // If the import path follows, then 4 bytes at the end of
   597  // the data form a nameOff. The import path is only set for concrete
   598  // methods that are defined in a different package than their type.
   599  //
   600  // If a name starts with "*", then the exported bit represents
   601  // whether the pointed to type is exported.
   602  //
   603  // Note: this encoding must match here and in:
   604  //   cmd/compile/internal/reflectdata/reflect.go
   605  //   cmd/link/internal/ld/decodesym.go
   606  
   607  type Name struct {
   608  	Bytes *byte
   609  }
   610  
   611  // DataChecked does pointer arithmetic on n's Bytes, and that arithmetic is asserted to
   612  // be safe for the reason in whySafe (which can appear in a backtrace, etc.)
   613  func (n Name) DataChecked(off int, whySafe string) *byte {
   614  	return (*byte)(addChecked(unsafe.Pointer(n.Bytes), uintptr(off), whySafe))
   615  }
   616  
   617  // Data does pointer arithmetic on n's Bytes, and that arithmetic is asserted to
   618  // be safe because the runtime made the call (other packages use DataChecked)
   619  func (n Name) Data(off int) *byte {
   620  	return (*byte)(addChecked(unsafe.Pointer(n.Bytes), uintptr(off), "the runtime doesn't need to give you a reason"))
   621  }
   622  
   623  // IsExported returns "is n exported?"
   624  func (n Name) IsExported() bool {
   625  	return (*n.Bytes)&(1<<0) != 0
   626  }
   627  
   628  // HasTag returns true iff there is tag data following this name
   629  func (n Name) HasTag() bool {
   630  	return (*n.Bytes)&(1<<1) != 0
   631  }
   632  
   633  // IsEmbedded returns true iff n is embedded (an anonymous field).
   634  func (n Name) IsEmbedded() bool {
   635  	return (*n.Bytes)&(1<<3) != 0
   636  }
   637  
   638  // ReadVarint parses a varint as encoded by encoding/binary.
   639  // It returns the number of encoded bytes and the encoded value.
   640  func (n Name) ReadVarint(off int) (int, int) {
   641  	v := 0
   642  	for i := 0; ; i++ {
   643  		x := *n.DataChecked(off+i, "read varint")
   644  		v += int(x&0x7f) << (7 * i)
   645  		if x&0x80 == 0 {
   646  			return i + 1, v
   647  		}
   648  	}
   649  }
   650  
   651  // IsBlank indicates whether n is "_".
   652  func (n Name) IsBlank() bool {
   653  	if n.Bytes == nil {
   654  		return false
   655  	}
   656  	_, l := n.ReadVarint(1)
   657  	return l == 1 && *n.Data(2) == '_'
   658  }
   659  
   660  // writeVarint writes n to buf in varint form. Returns the
   661  // number of bytes written. n must be nonnegative.
   662  // Writes at most 10 bytes.
   663  func writeVarint(buf []byte, n int) int {
   664  	for i := 0; ; i++ {
   665  		b := byte(n & 0x7f)
   666  		n >>= 7
   667  		if n == 0 {
   668  			buf[i] = b
   669  			return i + 1
   670  		}
   671  		buf[i] = b | 0x80
   672  	}
   673  }
   674  
   675  // Name returns the tag string for n, or empty if there is none.
   676  func (n Name) Name() string {
   677  	if n.Bytes == nil {
   678  		return ""
   679  	}
   680  	i, l := n.ReadVarint(1)
   681  	return unsafe.String(n.DataChecked(1+i, "non-empty string"), l)
   682  }
   683  
   684  // Tag returns the tag string for n, or empty if there is none.
   685  func (n Name) Tag() string {
   686  	if !n.HasTag() {
   687  		return ""
   688  	}
   689  	i, l := n.ReadVarint(1)
   690  	i2, l2 := n.ReadVarint(1 + i + l)
   691  	return unsafe.String(n.DataChecked(1+i+l+i2, "non-empty string"), l2)
   692  }
   693  
   694  func NewName(n, tag string, exported, embedded bool) Name {
   695  	if len(n) >= 1<<29 {
   696  		panic("abi.NewName: name too long: " + n[:1024] + "...")
   697  	}
   698  	if len(tag) >= 1<<29 {
   699  		panic("abi.NewName: tag too long: " + tag[:1024] + "...")
   700  	}
   701  	var nameLen [10]byte
   702  	var tagLen [10]byte
   703  	nameLenLen := writeVarint(nameLen[:], len(n))
   704  	tagLenLen := writeVarint(tagLen[:], len(tag))
   705  
   706  	var bits byte
   707  	l := 1 + nameLenLen + len(n)
   708  	if exported {
   709  		bits |= 1 << 0
   710  	}
   711  	if len(tag) > 0 {
   712  		l += tagLenLen + len(tag)
   713  		bits |= 1 << 1
   714  	}
   715  	if embedded {
   716  		bits |= 1 << 3
   717  	}
   718  
   719  	b := make([]byte, l)
   720  	b[0] = bits
   721  	copy(b[1:], nameLen[:nameLenLen])
   722  	copy(b[1+nameLenLen:], n)
   723  	if len(tag) > 0 {
   724  		tb := b[1+nameLenLen+len(n):]
   725  		copy(tb, tagLen[:tagLenLen])
   726  		copy(tb[tagLenLen:], tag)
   727  	}
   728  
   729  	return Name{Bytes: &b[0]}
   730  }
   731  
   732  const (
   733  	TraceArgsLimit    = 10 // print no more than 10 args/components
   734  	TraceArgsMaxDepth = 5  // no more than 5 layers of nesting
   735  
   736  	// maxLen is a (conservative) upper bound of the byte stream length. For
   737  	// each arg/component, it has no more than 2 bytes of data (size, offset),
   738  	// and no more than one {, }, ... at each level (it cannot have both the
   739  	// data and ... unless it is the last one, just be conservative). Plus 1
   740  	// for _endSeq.
   741  	TraceArgsMaxLen = (TraceArgsMaxDepth*3+2)*TraceArgsLimit + 1
   742  )
   743  
   744  // Populate the data.
   745  // The data is a stream of bytes, which contains the offsets and sizes of the
   746  // non-aggregate arguments or non-aggregate fields/elements of aggregate-typed
   747  // arguments, along with special "operators". Specifically,
   748  //   - for each non-aggregate arg/field/element, its offset from FP (1 byte) and
   749  //     size (1 byte)
   750  //   - special operators:
   751  //   - 0xff - end of sequence
   752  //   - 0xfe - print { (at the start of an aggregate-typed argument)
   753  //   - 0xfd - print } (at the end of an aggregate-typed argument)
   754  //   - 0xfc - print ... (more args/fields/elements)
   755  //   - 0xfb - print _ (offset too large)
   756  const (
   757  	TraceArgsEndSeq         = 0xff
   758  	TraceArgsStartAgg       = 0xfe
   759  	TraceArgsEndAgg         = 0xfd
   760  	TraceArgsDotdotdot      = 0xfc
   761  	TraceArgsOffsetTooLarge = 0xfb
   762  	TraceArgsSpecial        = 0xf0 // above this are operators, below this are ordinary offsets
   763  )
   764  
   765  // MaxPtrmaskBytes is the maximum length of a GC ptrmask bitmap,
   766  // which holds 1-bit entries describing where pointers are in a given type.
   767  // Above this length, the GC information is recorded as a GC program,
   768  // which can express repetition compactly. In either form, the
   769  // information is used by the runtime to initialize the heap bitmap,
   770  // and for large types (like 128 or more words), they are roughly the
   771  // same speed. GC programs are never much larger and often more
   772  // compact. (If large arrays are involved, they can be arbitrarily
   773  // more compact.)
   774  //
   775  // The cutoff must be large enough that any allocation large enough to
   776  // use a GC program is large enough that it does not share heap bitmap
   777  // bytes with any other objects, allowing the GC program execution to
   778  // assume an aligned start and not use atomic operations. In the current
   779  // runtime, this means all malloc size classes larger than the cutoff must
   780  // be multiples of four words. On 32-bit systems that's 16 bytes, and
   781  // all size classes >= 16 bytes are 16-byte aligned, so no real constraint.
   782  // On 64-bit systems, that's 32 bytes, and 32-byte alignment is guaranteed
   783  // for size classes >= 256 bytes. On a 64-bit system, 256 bytes allocated
   784  // is 32 pointers, the bits for which fit in 4 bytes. So MaxPtrmaskBytes
   785  // must be >= 4.
   786  //
   787  // We used to use 16 because the GC programs do have some constant overhead
   788  // to get started, and processing 128 pointers seems to be enough to
   789  // amortize that overhead well.
   790  //
   791  // To make sure that the runtime's chansend can call typeBitsBulkBarrier,
   792  // we raised the limit to 2048, so that even 32-bit systems are guaranteed to
   793  // use bitmaps for objects up to 64 kB in size.
   794  const MaxPtrmaskBytes = 2048
   795  

View as plain text