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

View as plain text