Source file src/runtime/iface.go

     1  // Copyright 2014 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 runtime
     6  
     7  import (
     8  	"internal/abi"
     9  	"internal/goarch"
    10  	"internal/runtime/atomic"
    11  	"internal/runtime/sys"
    12  	"unsafe"
    13  )
    14  
    15  const itabInitSize = 512
    16  
    17  var (
    18  	itabLock      mutex                               // lock for accessing itab table
    19  	itabTable     = &itabTableInit                    // pointer to current table
    20  	itabTableInit = itabTableType{size: itabInitSize} // starter table
    21  )
    22  
    23  // Note: change the formula in the mallocgc call in itabAdd if you change these fields.
    24  type itabTableType struct {
    25  	size    uintptr             // length of entries array. Always a power of 2.
    26  	count   uintptr             // current number of filled entries.
    27  	entries [itabInitSize]*itab // really [size] large
    28  }
    29  
    30  func itabHashFunc(inter *interfacetype, typ *_type) uintptr {
    31  	// compiler has provided some good hash codes for us.
    32  	return uintptr(inter.Type.Hash ^ typ.Hash)
    33  }
    34  
    35  // getitab should be an internal detail,
    36  // but widely used packages access it using linkname.
    37  // Notable members of the hall of shame include:
    38  //   - github.com/bytedance/sonic
    39  //
    40  // Do not remove or change the type signature.
    41  // See go.dev/issue/67401.
    42  //
    43  //go:linkname getitab
    44  func getitab(inter *interfacetype, typ *_type, canfail bool) *itab {
    45  	if len(inter.Methods) == 0 {
    46  		throw("internal error - misuse of itab")
    47  	}
    48  
    49  	// easy case
    50  	if typ.TFlag&abi.TFlagUncommon == 0 {
    51  		if canfail {
    52  			return nil
    53  		}
    54  		name := toRType(&inter.Type).nameOff(inter.Methods[0].Name)
    55  		panic(&TypeAssertionError{nil, typ, &inter.Type, name.Name()})
    56  	}
    57  
    58  	var m *itab
    59  
    60  	// First, look in the existing table to see if we can find the itab we need.
    61  	// This is by far the most common case, so do it without locks.
    62  	// Use atomic to ensure we see any previous writes done by the thread
    63  	// that updates the itabTable field (with atomic.Storep in itabAdd).
    64  	t := (*itabTableType)(atomic.Loadp(unsafe.Pointer(&itabTable)))
    65  	if m = t.find(inter, typ); m != nil {
    66  		goto finish
    67  	}
    68  
    69  	// Not found.  Grab the lock and try again.
    70  	lock(&itabLock)
    71  	if m = itabTable.find(inter, typ); m != nil {
    72  		unlock(&itabLock)
    73  		goto finish
    74  	}
    75  
    76  	// Entry doesn't exist yet. Make a new entry & add it.
    77  	m = (*itab)(persistentalloc(unsafe.Sizeof(itab{})+uintptr(len(inter.Methods)-1)*goarch.PtrSize, 0, &memstats.other_sys))
    78  	m.Inter = inter
    79  	m.Type = typ
    80  	// The hash is used in type switches. However, compiler statically generates itab's
    81  	// for all interface/type pairs used in switches (which are added to itabTable
    82  	// in itabsinit). The dynamically-generated itab's never participate in type switches,
    83  	// and thus the hash is irrelevant.
    84  	// Note: m.Hash is _not_ the hash used for the runtime itabTable hash table.
    85  	m.Hash = 0
    86  	itabInit(m, true)
    87  	itabAdd(m)
    88  	unlock(&itabLock)
    89  finish:
    90  	if m.Fun[0] != 0 {
    91  		return m
    92  	}
    93  	if canfail {
    94  		return nil
    95  	}
    96  	// this can only happen if the conversion
    97  	// was already done once using the , ok form
    98  	// and we have a cached negative result.
    99  	// The cached result doesn't record which
   100  	// interface function was missing, so initialize
   101  	// the itab again to get the missing function name.
   102  	panic(&TypeAssertionError{concrete: typ, asserted: &inter.Type, missingMethod: itabInit(m, false)})
   103  }
   104  
   105  // find finds the given interface/type pair in t.
   106  // Returns nil if the given interface/type pair isn't present.
   107  func (t *itabTableType) find(inter *interfacetype, typ *_type) *itab {
   108  	// Implemented using quadratic probing.
   109  	// Probe sequence is h(i) = h0 + i*(i+1)/2 mod 2^k.
   110  	// We're guaranteed to hit all table entries using this probe sequence.
   111  	mask := t.size - 1
   112  	h := itabHashFunc(inter, typ) & mask
   113  	for i := uintptr(1); ; i++ {
   114  		p := (**itab)(add(unsafe.Pointer(&t.entries), h*goarch.PtrSize))
   115  		// Use atomic read here so if we see m != nil, we also see
   116  		// the initializations of the fields of m.
   117  		// m := *p
   118  		m := (*itab)(atomic.Loadp(unsafe.Pointer(p)))
   119  		if m == nil {
   120  			return nil
   121  		}
   122  		if m.Inter == inter && m.Type == typ {
   123  			return m
   124  		}
   125  		h += i
   126  		h &= mask
   127  	}
   128  }
   129  
   130  // itabAdd adds the given itab to the itab hash table.
   131  // itabLock must be held.
   132  func itabAdd(m *itab) {
   133  	// Bugs can lead to calling this while mallocing is set,
   134  	// typically because this is called while panicking.
   135  	// Crash reliably, rather than only when we need to grow
   136  	// the hash table.
   137  	if getg().m.mallocing != 0 {
   138  		throw("malloc deadlock")
   139  	}
   140  
   141  	t := itabTable
   142  	if t.count >= 3*(t.size/4) { // 75% load factor
   143  		// Grow hash table.
   144  		// t2 = new(itabTableType) + some additional entries
   145  		// We lie and tell malloc we want pointer-free memory because
   146  		// all the pointed-to values are not in the heap.
   147  		t2 := (*itabTableType)(mallocgc((2+2*t.size)*goarch.PtrSize, nil, true))
   148  		t2.size = t.size * 2
   149  
   150  		// Copy over entries.
   151  		// Note: while copying, other threads may look for an itab and
   152  		// fail to find it. That's ok, they will then try to get the itab lock
   153  		// and as a consequence wait until this copying is complete.
   154  		iterate_itabs(t2.add)
   155  		if t2.count != t.count {
   156  			throw("mismatched count during itab table copy")
   157  		}
   158  		// Publish new hash table. Use an atomic write: see comment in getitab.
   159  		atomicstorep(unsafe.Pointer(&itabTable), unsafe.Pointer(t2))
   160  		// Adopt the new table as our own.
   161  		t = itabTable
   162  		// Note: the old table can be GC'ed here.
   163  	}
   164  	t.add(m)
   165  }
   166  
   167  // add adds the given itab to itab table t.
   168  // itabLock must be held.
   169  func (t *itabTableType) add(m *itab) {
   170  	// See comment in find about the probe sequence.
   171  	// Insert new itab in the first empty spot in the probe sequence.
   172  	mask := t.size - 1
   173  	h := itabHashFunc(m.Inter, m.Type) & mask
   174  	for i := uintptr(1); ; i++ {
   175  		p := (**itab)(add(unsafe.Pointer(&t.entries), h*goarch.PtrSize))
   176  		m2 := *p
   177  		if m2 == m {
   178  			// A given itab may be used in more than one module
   179  			// and thanks to the way global symbol resolution works, the
   180  			// pointed-to itab may already have been inserted into the
   181  			// global 'hash'.
   182  			return
   183  		}
   184  		if m2 == nil {
   185  			// Use atomic write here so if a reader sees m, it also
   186  			// sees the correctly initialized fields of m.
   187  			// NoWB is ok because m is not in heap memory.
   188  			// *p = m
   189  			atomic.StorepNoWB(unsafe.Pointer(p), unsafe.Pointer(m))
   190  			t.count++
   191  			return
   192  		}
   193  		h += i
   194  		h &= mask
   195  	}
   196  }
   197  
   198  // itabInit fills in the m.Fun array with all the code pointers for
   199  // the m.Inter/m.Type pair. If the type does not implement the interface,
   200  // it sets m.Fun[0] to 0 and returns the name of an interface function that is missing.
   201  // If !firstTime, itabInit will not write anything to m.Fun (see issue 65962).
   202  // It is ok to call this multiple times on the same m, even concurrently
   203  // (although it will only be called once with firstTime==true).
   204  func itabInit(m *itab, firstTime bool) string {
   205  	inter := m.Inter
   206  	typ := m.Type
   207  	x := typ.Uncommon()
   208  
   209  	// both inter and typ have method sorted by name,
   210  	// and interface names are unique,
   211  	// so can iterate over both in lock step;
   212  	// the loop is O(ni+nt) not O(ni*nt).
   213  	ni := len(inter.Methods)
   214  	nt := int(x.Mcount)
   215  	xmhdr := (*[1 << 16]abi.Method)(add(unsafe.Pointer(x), uintptr(x.Moff)))[:nt:nt]
   216  	j := 0
   217  	methods := (*[1 << 16]unsafe.Pointer)(unsafe.Pointer(&m.Fun[0]))[:ni:ni]
   218  	var fun0 unsafe.Pointer
   219  imethods:
   220  	for k := 0; k < ni; k++ {
   221  		i := &inter.Methods[k]
   222  		itype := toRType(&inter.Type).typeOff(i.Typ)
   223  		name := toRType(&inter.Type).nameOff(i.Name)
   224  		iname := name.Name()
   225  		ipkg := pkgPath(name)
   226  		if ipkg == "" {
   227  			ipkg = inter.PkgPath.Name()
   228  		}
   229  		for ; j < nt; j++ {
   230  			t := &xmhdr[j]
   231  			rtyp := toRType(typ)
   232  			tname := rtyp.nameOff(t.Name)
   233  			if rtyp.typeOff(t.Mtyp) == itype && tname.Name() == iname {
   234  				pkgPath := pkgPath(tname)
   235  				if pkgPath == "" {
   236  					pkgPath = rtyp.nameOff(x.PkgPath).Name()
   237  				}
   238  				if tname.IsExported() || pkgPath == ipkg {
   239  					ifn := rtyp.textOff(t.Ifn)
   240  					if k == 0 {
   241  						fun0 = ifn // we'll set m.Fun[0] at the end
   242  					} else if firstTime {
   243  						methods[k] = ifn
   244  					}
   245  					continue imethods
   246  				}
   247  			}
   248  		}
   249  		// didn't find method
   250  		// Leaves m.Fun[0] set to 0.
   251  		return iname
   252  	}
   253  	if firstTime {
   254  		m.Fun[0] = uintptr(fun0)
   255  	}
   256  	return ""
   257  }
   258  
   259  func itabsinit() {
   260  	lockInit(&itabLock, lockRankItab)
   261  	lock(&itabLock)
   262  	for _, md := range activeModules() {
   263  		for _, i := range md.itablinks {
   264  			itabAdd(i)
   265  		}
   266  	}
   267  	unlock(&itabLock)
   268  }
   269  
   270  // panicdottypeE is called when doing an e.(T) conversion and the conversion fails.
   271  // have = the dynamic type we have.
   272  // want = the static type we're trying to convert to.
   273  // iface = the static type we're converting from.
   274  func panicdottypeE(have, want, iface *_type) {
   275  	panic(&TypeAssertionError{iface, have, want, ""})
   276  }
   277  
   278  // panicdottypeI is called when doing an i.(T) conversion and the conversion fails.
   279  // Same args as panicdottypeE, but "have" is the dynamic itab we have.
   280  func panicdottypeI(have *itab, want, iface *_type) {
   281  	var t *_type
   282  	if have != nil {
   283  		t = have.Type
   284  	}
   285  	panicdottypeE(t, want, iface)
   286  }
   287  
   288  // panicnildottype is called when doing an i.(T) conversion and the interface i is nil.
   289  // want = the static type we're trying to convert to.
   290  func panicnildottype(want *_type) {
   291  	panic(&TypeAssertionError{nil, nil, want, ""})
   292  	// TODO: Add the static type we're converting from as well.
   293  	// It might generate a better error message.
   294  	// Just to match other nil conversion errors, we don't for now.
   295  }
   296  
   297  // The specialized convTx routines need a type descriptor to use when calling mallocgc.
   298  // We don't need the type to be exact, just to have the correct size, alignment, and pointer-ness.
   299  // However, when debugging, it'd be nice to have some indication in mallocgc where the types came from,
   300  // so we use named types here.
   301  // We then construct interface values of these types,
   302  // and then extract the type word to use as needed.
   303  type (
   304  	uint16InterfacePtr uint16
   305  	uint32InterfacePtr uint32
   306  	uint64InterfacePtr uint64
   307  	stringInterfacePtr string
   308  	sliceInterfacePtr  []byte
   309  )
   310  
   311  var (
   312  	uint16Eface any = uint16InterfacePtr(0)
   313  	uint32Eface any = uint32InterfacePtr(0)
   314  	uint64Eface any = uint64InterfacePtr(0)
   315  	stringEface any = stringInterfacePtr("")
   316  	sliceEface  any = sliceInterfacePtr(nil)
   317  
   318  	uint16Type *_type = efaceOf(&uint16Eface)._type
   319  	uint32Type *_type = efaceOf(&uint32Eface)._type
   320  	uint64Type *_type = efaceOf(&uint64Eface)._type
   321  	stringType *_type = efaceOf(&stringEface)._type
   322  	sliceType  *_type = efaceOf(&sliceEface)._type
   323  )
   324  
   325  // The conv and assert functions below do very similar things.
   326  // The convXXX functions are guaranteed by the compiler to succeed.
   327  // The assertXXX functions may fail (either panicking or returning false,
   328  // depending on whether they are 1-result or 2-result).
   329  // The convXXX functions succeed on a nil input, whereas the assertXXX
   330  // functions fail on a nil input.
   331  
   332  // convT converts a value of type t, which is pointed to by v, to a pointer that can
   333  // be used as the second word of an interface value.
   334  func convT(t *_type, v unsafe.Pointer) unsafe.Pointer {
   335  	if raceenabled {
   336  		raceReadObjectPC(t, v, sys.GetCallerPC(), abi.FuncPCABIInternal(convT))
   337  	}
   338  	if msanenabled {
   339  		msanread(v, t.Size_)
   340  	}
   341  	if asanenabled {
   342  		asanread(v, t.Size_)
   343  	}
   344  	x := mallocgc(t.Size_, t, true)
   345  	typedmemmove(t, x, v)
   346  	return x
   347  }
   348  func convTnoptr(t *_type, v unsafe.Pointer) unsafe.Pointer {
   349  	// TODO: maybe take size instead of type?
   350  	if raceenabled {
   351  		raceReadObjectPC(t, v, sys.GetCallerPC(), abi.FuncPCABIInternal(convTnoptr))
   352  	}
   353  	if msanenabled {
   354  		msanread(v, t.Size_)
   355  	}
   356  	if asanenabled {
   357  		asanread(v, t.Size_)
   358  	}
   359  
   360  	x := mallocgc(t.Size_, t, false)
   361  	memmove(x, v, t.Size_)
   362  	return x
   363  }
   364  
   365  func convT16(val uint16) (x unsafe.Pointer) {
   366  	if val < uint16(len(staticuint64s)) {
   367  		x = unsafe.Pointer(&staticuint64s[val])
   368  		if goarch.BigEndian {
   369  			x = add(x, 6)
   370  		}
   371  	} else {
   372  		x = mallocgc(2, uint16Type, false)
   373  		*(*uint16)(x) = val
   374  	}
   375  	return
   376  }
   377  
   378  func convT32(val uint32) (x unsafe.Pointer) {
   379  	if val < uint32(len(staticuint64s)) {
   380  		x = unsafe.Pointer(&staticuint64s[val])
   381  		if goarch.BigEndian {
   382  			x = add(x, 4)
   383  		}
   384  	} else {
   385  		x = mallocgc(4, uint32Type, false)
   386  		*(*uint32)(x) = val
   387  	}
   388  	return
   389  }
   390  
   391  // convT64 should be an internal detail,
   392  // but widely used packages access it using linkname.
   393  // Notable members of the hall of shame include:
   394  //   - github.com/bytedance/sonic
   395  //
   396  // Do not remove or change the type signature.
   397  // See go.dev/issue/67401.
   398  //
   399  //go:linkname convT64
   400  func convT64(val uint64) (x unsafe.Pointer) {
   401  	if val < uint64(len(staticuint64s)) {
   402  		x = unsafe.Pointer(&staticuint64s[val])
   403  	} else {
   404  		x = mallocgc(8, uint64Type, false)
   405  		*(*uint64)(x) = val
   406  	}
   407  	return
   408  }
   409  
   410  // convTstring should be an internal detail,
   411  // but widely used packages access it using linkname.
   412  // Notable members of the hall of shame include:
   413  //   - github.com/bytedance/sonic
   414  //
   415  // Do not remove or change the type signature.
   416  // See go.dev/issue/67401.
   417  //
   418  //go:linkname convTstring
   419  func convTstring(val string) (x unsafe.Pointer) {
   420  	if val == "" {
   421  		x = unsafe.Pointer(&zeroVal[0])
   422  	} else {
   423  		x = mallocgc(unsafe.Sizeof(val), stringType, true)
   424  		*(*string)(x) = val
   425  	}
   426  	return
   427  }
   428  
   429  // convTslice should be an internal detail,
   430  // but widely used packages access it using linkname.
   431  // Notable members of the hall of shame include:
   432  //   - github.com/bytedance/sonic
   433  //
   434  // Do not remove or change the type signature.
   435  // See go.dev/issue/67401.
   436  //
   437  //go:linkname convTslice
   438  func convTslice(val []byte) (x unsafe.Pointer) {
   439  	// Note: this must work for any element type, not just byte.
   440  	if (*slice)(unsafe.Pointer(&val)).array == nil {
   441  		x = unsafe.Pointer(&zeroVal[0])
   442  	} else {
   443  		x = mallocgc(unsafe.Sizeof(val), sliceType, true)
   444  		*(*[]byte)(x) = val
   445  	}
   446  	return
   447  }
   448  
   449  func assertE2I(inter *interfacetype, t *_type) *itab {
   450  	if t == nil {
   451  		// explicit conversions require non-nil interface value.
   452  		panic(&TypeAssertionError{nil, nil, &inter.Type, ""})
   453  	}
   454  	return getitab(inter, t, false)
   455  }
   456  
   457  func assertE2I2(inter *interfacetype, t *_type) *itab {
   458  	if t == nil {
   459  		return nil
   460  	}
   461  	return getitab(inter, t, true)
   462  }
   463  
   464  // typeAssert builds an itab for the concrete type t and the
   465  // interface type s.Inter. If the conversion is not possible it
   466  // panics if s.CanFail is false and returns nil if s.CanFail is true.
   467  func typeAssert(s *abi.TypeAssert, t *_type) *itab {
   468  	var tab *itab
   469  	if t == nil {
   470  		if !s.CanFail {
   471  			panic(&TypeAssertionError{nil, nil, &s.Inter.Type, ""})
   472  		}
   473  	} else {
   474  		tab = getitab(s.Inter, t, s.CanFail)
   475  	}
   476  
   477  	if !abi.UseInterfaceSwitchCache(GOARCH) {
   478  		return tab
   479  	}
   480  
   481  	// Maybe update the cache, so the next time the generated code
   482  	// doesn't need to call into the runtime.
   483  	if cheaprand()&1023 != 0 {
   484  		// Only bother updating the cache ~1 in 1000 times.
   485  		return tab
   486  	}
   487  	// Load the current cache.
   488  	oldC := (*abi.TypeAssertCache)(atomic.Loadp(unsafe.Pointer(&s.Cache)))
   489  
   490  	if cheaprand()&uint32(oldC.Mask) != 0 {
   491  		// As cache gets larger, choose to update it less often
   492  		// so we can amortize the cost of building a new cache.
   493  		return tab
   494  	}
   495  
   496  	// Make a new cache.
   497  	newC := buildTypeAssertCache(oldC, t, tab)
   498  
   499  	// Update cache. Use compare-and-swap so if multiple threads
   500  	// are fighting to update the cache, at least one of their
   501  	// updates will stick.
   502  	atomic_casPointer((*unsafe.Pointer)(unsafe.Pointer(&s.Cache)), unsafe.Pointer(oldC), unsafe.Pointer(newC))
   503  
   504  	return tab
   505  }
   506  
   507  func buildTypeAssertCache(oldC *abi.TypeAssertCache, typ *_type, tab *itab) *abi.TypeAssertCache {
   508  	oldEntries := unsafe.Slice(&oldC.Entries[0], oldC.Mask+1)
   509  
   510  	// Count the number of entries we need.
   511  	n := 1
   512  	for _, e := range oldEntries {
   513  		if e.Typ != 0 {
   514  			n++
   515  		}
   516  	}
   517  
   518  	// Figure out how big a table we need.
   519  	// We need at least one more slot than the number of entries
   520  	// so that we are guaranteed an empty slot (for termination).
   521  	newN := n * 2                         // make it at most 50% full
   522  	newN = 1 << sys.Len64(uint64(newN-1)) // round up to a power of 2
   523  
   524  	// Allocate the new table.
   525  	newSize := unsafe.Sizeof(abi.TypeAssertCache{}) + uintptr(newN-1)*unsafe.Sizeof(abi.TypeAssertCacheEntry{})
   526  	newC := (*abi.TypeAssertCache)(mallocgc(newSize, nil, true))
   527  	newC.Mask = uintptr(newN - 1)
   528  	newEntries := unsafe.Slice(&newC.Entries[0], newN)
   529  
   530  	// Fill the new table.
   531  	addEntry := func(typ *_type, tab *itab) {
   532  		h := int(typ.Hash) & (newN - 1)
   533  		for {
   534  			if newEntries[h].Typ == 0 {
   535  				newEntries[h].Typ = uintptr(unsafe.Pointer(typ))
   536  				newEntries[h].Itab = uintptr(unsafe.Pointer(tab))
   537  				return
   538  			}
   539  			h = (h + 1) & (newN - 1)
   540  		}
   541  	}
   542  	for _, e := range oldEntries {
   543  		if e.Typ != 0 {
   544  			addEntry((*_type)(unsafe.Pointer(e.Typ)), (*itab)(unsafe.Pointer(e.Itab)))
   545  		}
   546  	}
   547  	addEntry(typ, tab)
   548  
   549  	return newC
   550  }
   551  
   552  // Empty type assert cache. Contains one entry with a nil Typ (which
   553  // causes a cache lookup to fail immediately.)
   554  var emptyTypeAssertCache = abi.TypeAssertCache{Mask: 0}
   555  
   556  // interfaceSwitch compares t against the list of cases in s.
   557  // If t matches case i, interfaceSwitch returns the case index i and
   558  // an itab for the pair <t, s.Cases[i]>.
   559  // If there is no match, return N,nil, where N is the number
   560  // of cases.
   561  func interfaceSwitch(s *abi.InterfaceSwitch, t *_type) (int, *itab) {
   562  	cases := unsafe.Slice(&s.Cases[0], s.NCases)
   563  
   564  	// Results if we don't find a match.
   565  	case_ := len(cases)
   566  	var tab *itab
   567  
   568  	// Look through each case in order.
   569  	for i, c := range cases {
   570  		tab = getitab(c, t, true)
   571  		if tab != nil {
   572  			case_ = i
   573  			break
   574  		}
   575  	}
   576  
   577  	if !abi.UseInterfaceSwitchCache(GOARCH) {
   578  		return case_, tab
   579  	}
   580  
   581  	// Maybe update the cache, so the next time the generated code
   582  	// doesn't need to call into the runtime.
   583  	if cheaprand()&1023 != 0 {
   584  		// Only bother updating the cache ~1 in 1000 times.
   585  		// This ensures we don't waste memory on switches, or
   586  		// switch arguments, that only happen a few times.
   587  		return case_, tab
   588  	}
   589  	// Load the current cache.
   590  	oldC := (*abi.InterfaceSwitchCache)(atomic.Loadp(unsafe.Pointer(&s.Cache)))
   591  
   592  	if cheaprand()&uint32(oldC.Mask) != 0 {
   593  		// As cache gets larger, choose to update it less often
   594  		// so we can amortize the cost of building a new cache
   595  		// (that cost is linear in oldc.Mask).
   596  		return case_, tab
   597  	}
   598  
   599  	// Make a new cache.
   600  	newC := buildInterfaceSwitchCache(oldC, t, case_, tab)
   601  
   602  	// Update cache. Use compare-and-swap so if multiple threads
   603  	// are fighting to update the cache, at least one of their
   604  	// updates will stick.
   605  	atomic_casPointer((*unsafe.Pointer)(unsafe.Pointer(&s.Cache)), unsafe.Pointer(oldC), unsafe.Pointer(newC))
   606  
   607  	return case_, tab
   608  }
   609  
   610  // buildInterfaceSwitchCache constructs an interface switch cache
   611  // containing all the entries from oldC plus the new entry
   612  // (typ,case_,tab).
   613  func buildInterfaceSwitchCache(oldC *abi.InterfaceSwitchCache, typ *_type, case_ int, tab *itab) *abi.InterfaceSwitchCache {
   614  	oldEntries := unsafe.Slice(&oldC.Entries[0], oldC.Mask+1)
   615  
   616  	// Count the number of entries we need.
   617  	n := 1
   618  	for _, e := range oldEntries {
   619  		if e.Typ != 0 {
   620  			n++
   621  		}
   622  	}
   623  
   624  	// Figure out how big a table we need.
   625  	// We need at least one more slot than the number of entries
   626  	// so that we are guaranteed an empty slot (for termination).
   627  	newN := n * 2                         // make it at most 50% full
   628  	newN = 1 << sys.Len64(uint64(newN-1)) // round up to a power of 2
   629  
   630  	// Allocate the new table.
   631  	newSize := unsafe.Sizeof(abi.InterfaceSwitchCache{}) + uintptr(newN-1)*unsafe.Sizeof(abi.InterfaceSwitchCacheEntry{})
   632  	newC := (*abi.InterfaceSwitchCache)(mallocgc(newSize, nil, true))
   633  	newC.Mask = uintptr(newN - 1)
   634  	newEntries := unsafe.Slice(&newC.Entries[0], newN)
   635  
   636  	// Fill the new table.
   637  	addEntry := func(typ *_type, case_ int, tab *itab) {
   638  		h := int(typ.Hash) & (newN - 1)
   639  		for {
   640  			if newEntries[h].Typ == 0 {
   641  				newEntries[h].Typ = uintptr(unsafe.Pointer(typ))
   642  				newEntries[h].Case = case_
   643  				newEntries[h].Itab = uintptr(unsafe.Pointer(tab))
   644  				return
   645  			}
   646  			h = (h + 1) & (newN - 1)
   647  		}
   648  	}
   649  	for _, e := range oldEntries {
   650  		if e.Typ != 0 {
   651  			addEntry((*_type)(unsafe.Pointer(e.Typ)), e.Case, (*itab)(unsafe.Pointer(e.Itab)))
   652  		}
   653  	}
   654  	addEntry(typ, case_, tab)
   655  
   656  	return newC
   657  }
   658  
   659  // Empty interface switch cache. Contains one entry with a nil Typ (which
   660  // causes a cache lookup to fail immediately.)
   661  var emptyInterfaceSwitchCache = abi.InterfaceSwitchCache{Mask: 0}
   662  
   663  // reflect_ifaceE2I is for package reflect,
   664  // but widely used packages access it using linkname.
   665  // Notable members of the hall of shame include:
   666  //   - gitee.com/quant1x/gox
   667  //   - github.com/modern-go/reflect2
   668  //   - github.com/v2pro/plz
   669  //
   670  // Do not remove or change the type signature.
   671  //
   672  //go:linkname reflect_ifaceE2I reflect.ifaceE2I
   673  func reflect_ifaceE2I(inter *interfacetype, e eface, dst *iface) {
   674  	*dst = iface{assertE2I(inter, e._type), e.data}
   675  }
   676  
   677  //go:linkname reflectlite_ifaceE2I internal/reflectlite.ifaceE2I
   678  func reflectlite_ifaceE2I(inter *interfacetype, e eface, dst *iface) {
   679  	*dst = iface{assertE2I(inter, e._type), e.data}
   680  }
   681  
   682  func iterate_itabs(fn func(*itab)) {
   683  	// Note: only runs during stop the world or with itabLock held,
   684  	// so no other locks/atomics needed.
   685  	t := itabTable
   686  	for i := uintptr(0); i < t.size; i++ {
   687  		m := *(**itab)(add(unsafe.Pointer(&t.entries), i*goarch.PtrSize))
   688  		if m != nil {
   689  			fn(m)
   690  		}
   691  	}
   692  }
   693  
   694  // staticuint64s is used to avoid allocating in convTx for small integer values.
   695  // staticuint64s[0] == 0, staticuint64s[1] == 1, and so forth.
   696  // It is defined in assembler code so that it is read-only.
   697  var staticuint64s [256]uint64
   698  
   699  // getStaticuint64s is called by the reflect package to get a pointer
   700  // to the read-only array.
   701  //
   702  //go:linkname getStaticuint64s
   703  func getStaticuint64s() *[256]uint64 {
   704  	return &staticuint64s
   705  }
   706  
   707  // The linker redirects a reference of a method that it determined
   708  // unreachable to a reference to this function, so it will throw if
   709  // ever called.
   710  func unreachableMethod() {
   711  	throw("unreachable method called. linker bug?")
   712  }
   713  

View as plain text