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 *OldMapType or *SwissMapType, 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  func (t *Type) Key() *Type {
   468  	if t.Kind() == Map {
   469  		return (*mapType)(unsafe.Pointer(t)).Key
   470  	}
   471  	return nil
   472  }
   473  
   474  type SliceType struct {
   475  	Type
   476  	Elem *Type // slice element type
   477  }
   478  
   479  // funcType represents a function type.
   480  //
   481  // A *Type for each in and out parameter is stored in an array that
   482  // directly follows the funcType (and possibly its uncommonType). So
   483  // a function type with one method, one input, and one output is:
   484  //
   485  //	struct {
   486  //		funcType
   487  //		uncommonType
   488  //		[2]*rtype    // [0] is in, [1] is out
   489  //	}
   490  type FuncType struct {
   491  	Type
   492  	InCount  uint16
   493  	OutCount uint16 // top bit is set if last input parameter is ...
   494  }
   495  
   496  func (t *FuncType) In(i int) *Type {
   497  	return t.InSlice()[i]
   498  }
   499  
   500  func (t *FuncType) NumIn() int {
   501  	return int(t.InCount)
   502  }
   503  
   504  func (t *FuncType) NumOut() int {
   505  	return int(t.OutCount & (1<<15 - 1))
   506  }
   507  
   508  func (t *FuncType) Out(i int) *Type {
   509  	return (t.OutSlice()[i])
   510  }
   511  
   512  func (t *FuncType) InSlice() []*Type {
   513  	uadd := unsafe.Sizeof(*t)
   514  	if t.TFlag&TFlagUncommon != 0 {
   515  		uadd += unsafe.Sizeof(UncommonType{})
   516  	}
   517  	if t.InCount == 0 {
   518  		return nil
   519  	}
   520  	return (*[1 << 16]*Type)(addChecked(unsafe.Pointer(t), uadd, "t.inCount > 0"))[:t.InCount:t.InCount]
   521  }
   522  func (t *FuncType) OutSlice() []*Type {
   523  	outCount := uint16(t.NumOut())
   524  	if outCount == 0 {
   525  		return nil
   526  	}
   527  	uadd := unsafe.Sizeof(*t)
   528  	if t.TFlag&TFlagUncommon != 0 {
   529  		uadd += unsafe.Sizeof(UncommonType{})
   530  	}
   531  	return (*[1 << 17]*Type)(addChecked(unsafe.Pointer(t), uadd, "outCount > 0"))[t.InCount : t.InCount+outCount : t.InCount+outCount]
   532  }
   533  
   534  func (t *FuncType) IsVariadic() bool {
   535  	return t.OutCount&(1<<15) != 0
   536  }
   537  
   538  type PtrType struct {
   539  	Type
   540  	Elem *Type // pointer element (pointed at) type
   541  }
   542  
   543  type StructField struct {
   544  	Name   Name    // name is always non-empty
   545  	Typ    *Type   // type of field
   546  	Offset uintptr // byte offset of field
   547  }
   548  
   549  func (f *StructField) Embedded() bool {
   550  	return f.Name.IsEmbedded()
   551  }
   552  
   553  type StructType struct {
   554  	Type
   555  	PkgPath Name
   556  	Fields  []StructField
   557  }
   558  
   559  // Name is an encoded type Name with optional extra data.
   560  //
   561  // The first byte is a bit field containing:
   562  //
   563  //	1<<0 the name is exported
   564  //	1<<1 tag data follows the name
   565  //	1<<2 pkgPath nameOff follows the name and tag
   566  //	1<<3 the name is of an embedded (a.k.a. anonymous) field
   567  //
   568  // Following that, there is a varint-encoded length of the name,
   569  // followed by the name itself.
   570  //
   571  // If tag data is present, it also has a varint-encoded length
   572  // followed by the tag itself.
   573  //
   574  // If the import path follows, then 4 bytes at the end of
   575  // the data form a nameOff. The import path is only set for concrete
   576  // methods that are defined in a different package than their type.
   577  //
   578  // If a name starts with "*", then the exported bit represents
   579  // whether the pointed to type is exported.
   580  //
   581  // Note: this encoding must match here and in:
   582  //   cmd/compile/internal/reflectdata/reflect.go
   583  //   cmd/link/internal/ld/decodesym.go
   584  
   585  type Name struct {
   586  	Bytes *byte
   587  }
   588  
   589  // DataChecked does pointer arithmetic on n's Bytes, and that arithmetic is asserted to
   590  // be safe for the reason in whySafe (which can appear in a backtrace, etc.)
   591  func (n Name) DataChecked(off int, whySafe string) *byte {
   592  	return (*byte)(addChecked(unsafe.Pointer(n.Bytes), uintptr(off), whySafe))
   593  }
   594  
   595  // Data does pointer arithmetic on n's Bytes, and that arithmetic is asserted to
   596  // be safe because the runtime made the call (other packages use DataChecked)
   597  func (n Name) Data(off int) *byte {
   598  	return (*byte)(addChecked(unsafe.Pointer(n.Bytes), uintptr(off), "the runtime doesn't need to give you a reason"))
   599  }
   600  
   601  // IsExported returns "is n exported?"
   602  func (n Name) IsExported() bool {
   603  	return (*n.Bytes)&(1<<0) != 0
   604  }
   605  
   606  // HasTag returns true iff there is tag data following this name
   607  func (n Name) HasTag() bool {
   608  	return (*n.Bytes)&(1<<1) != 0
   609  }
   610  
   611  // IsEmbedded returns true iff n is embedded (an anonymous field).
   612  func (n Name) IsEmbedded() bool {
   613  	return (*n.Bytes)&(1<<3) != 0
   614  }
   615  
   616  // ReadVarint parses a varint as encoded by encoding/binary.
   617  // It returns the number of encoded bytes and the encoded value.
   618  func (n Name) ReadVarint(off int) (int, int) {
   619  	v := 0
   620  	for i := 0; ; i++ {
   621  		x := *n.DataChecked(off+i, "read varint")
   622  		v += int(x&0x7f) << (7 * i)
   623  		if x&0x80 == 0 {
   624  			return i + 1, v
   625  		}
   626  	}
   627  }
   628  
   629  // IsBlank indicates whether n is "_".
   630  func (n Name) IsBlank() bool {
   631  	if n.Bytes == nil {
   632  		return false
   633  	}
   634  	_, l := n.ReadVarint(1)
   635  	return l == 1 && *n.Data(2) == '_'
   636  }
   637  
   638  // writeVarint writes n to buf in varint form. Returns the
   639  // number of bytes written. n must be nonnegative.
   640  // Writes at most 10 bytes.
   641  func writeVarint(buf []byte, n int) int {
   642  	for i := 0; ; i++ {
   643  		b := byte(n & 0x7f)
   644  		n >>= 7
   645  		if n == 0 {
   646  			buf[i] = b
   647  			return i + 1
   648  		}
   649  		buf[i] = b | 0x80
   650  	}
   651  }
   652  
   653  // Name returns the tag string for n, or empty if there is none.
   654  func (n Name) Name() string {
   655  	if n.Bytes == nil {
   656  		return ""
   657  	}
   658  	i, l := n.ReadVarint(1)
   659  	return unsafe.String(n.DataChecked(1+i, "non-empty string"), l)
   660  }
   661  
   662  // Tag returns the tag string for n, or empty if there is none.
   663  func (n Name) Tag() string {
   664  	if !n.HasTag() {
   665  		return ""
   666  	}
   667  	i, l := n.ReadVarint(1)
   668  	i2, l2 := n.ReadVarint(1 + i + l)
   669  	return unsafe.String(n.DataChecked(1+i+l+i2, "non-empty string"), l2)
   670  }
   671  
   672  func NewName(n, tag string, exported, embedded bool) Name {
   673  	if len(n) >= 1<<29 {
   674  		panic("abi.NewName: name too long: " + n[:1024] + "...")
   675  	}
   676  	if len(tag) >= 1<<29 {
   677  		panic("abi.NewName: tag too long: " + tag[:1024] + "...")
   678  	}
   679  	var nameLen [10]byte
   680  	var tagLen [10]byte
   681  	nameLenLen := writeVarint(nameLen[:], len(n))
   682  	tagLenLen := writeVarint(tagLen[:], len(tag))
   683  
   684  	var bits byte
   685  	l := 1 + nameLenLen + len(n)
   686  	if exported {
   687  		bits |= 1 << 0
   688  	}
   689  	if len(tag) > 0 {
   690  		l += tagLenLen + len(tag)
   691  		bits |= 1 << 1
   692  	}
   693  	if embedded {
   694  		bits |= 1 << 3
   695  	}
   696  
   697  	b := make([]byte, l)
   698  	b[0] = bits
   699  	copy(b[1:], nameLen[:nameLenLen])
   700  	copy(b[1+nameLenLen:], n)
   701  	if len(tag) > 0 {
   702  		tb := b[1+nameLenLen+len(n):]
   703  		copy(tb, tagLen[:tagLenLen])
   704  		copy(tb[tagLenLen:], tag)
   705  	}
   706  
   707  	return Name{Bytes: &b[0]}
   708  }
   709  
   710  const (
   711  	TraceArgsLimit    = 10 // print no more than 10 args/components
   712  	TraceArgsMaxDepth = 5  // no more than 5 layers of nesting
   713  
   714  	// maxLen is a (conservative) upper bound of the byte stream length. For
   715  	// each arg/component, it has no more than 2 bytes of data (size, offset),
   716  	// and no more than one {, }, ... at each level (it cannot have both the
   717  	// data and ... unless it is the last one, just be conservative). Plus 1
   718  	// for _endSeq.
   719  	TraceArgsMaxLen = (TraceArgsMaxDepth*3+2)*TraceArgsLimit + 1
   720  )
   721  
   722  // Populate the data.
   723  // The data is a stream of bytes, which contains the offsets and sizes of the
   724  // non-aggregate arguments or non-aggregate fields/elements of aggregate-typed
   725  // arguments, along with special "operators". Specifically,
   726  //   - for each non-aggregate arg/field/element, its offset from FP (1 byte) and
   727  //     size (1 byte)
   728  //   - special operators:
   729  //   - 0xff - end of sequence
   730  //   - 0xfe - print { (at the start of an aggregate-typed argument)
   731  //   - 0xfd - print } (at the end of an aggregate-typed argument)
   732  //   - 0xfc - print ... (more args/fields/elements)
   733  //   - 0xfb - print _ (offset too large)
   734  const (
   735  	TraceArgsEndSeq         = 0xff
   736  	TraceArgsStartAgg       = 0xfe
   737  	TraceArgsEndAgg         = 0xfd
   738  	TraceArgsDotdotdot      = 0xfc
   739  	TraceArgsOffsetTooLarge = 0xfb
   740  	TraceArgsSpecial        = 0xf0 // above this are operators, below this are ordinary offsets
   741  )
   742  
   743  // MaxPtrmaskBytes is the maximum length of a GC ptrmask bitmap,
   744  // which holds 1-bit entries describing where pointers are in a given type.
   745  // Above this length, the GC information is recorded as a GC program,
   746  // which can express repetition compactly. In either form, the
   747  // information is used by the runtime to initialize the heap bitmap,
   748  // and for large types (like 128 or more words), they are roughly the
   749  // same speed. GC programs are never much larger and often more
   750  // compact. (If large arrays are involved, they can be arbitrarily
   751  // more compact.)
   752  //
   753  // The cutoff must be large enough that any allocation large enough to
   754  // use a GC program is large enough that it does not share heap bitmap
   755  // bytes with any other objects, allowing the GC program execution to
   756  // assume an aligned start and not use atomic operations. In the current
   757  // runtime, this means all malloc size classes larger than the cutoff must
   758  // be multiples of four words. On 32-bit systems that's 16 bytes, and
   759  // all size classes >= 16 bytes are 16-byte aligned, so no real constraint.
   760  // On 64-bit systems, that's 32 bytes, and 32-byte alignment is guaranteed
   761  // for size classes >= 256 bytes. On a 64-bit system, 256 bytes allocated
   762  // is 32 pointers, the bits for which fit in 4 bytes. So MaxPtrmaskBytes
   763  // must be >= 4.
   764  //
   765  // We used to use 16 because the GC programs do have some constant overhead
   766  // to get started, and processing 128 pointers seems to be enough to
   767  // amortize that overhead well.
   768  //
   769  // To make sure that the runtime's chansend can call typeBitsBulkBarrier,
   770  // we raised the limit to 2048, so that even 32-bit systems are guaranteed to
   771  // use bitmaps for objects up to 64 kB in size.
   772  const MaxPtrmaskBytes = 2048
   773  

View as plain text