mirror of https://github.com/golang/go.git
cmd/compile: move runtime.itab to internal/abi.ITab
Change-Id: I44293452764dc4bc4de8d386153c6402a9cbe409 Reviewed-on: https://go-review.googlesource.com/c/go/+/549435 LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com> Reviewed-by: David Chase <drchase@google.com> Reviewed-by: Than McIntosh <thanm@google.com>
This commit is contained in:
parent
cde38c966d
commit
e0ee5b1afa
|
|
@ -201,7 +201,7 @@ func (d *deadcodePass) flood() {
|
||||||
rs := r.Sym()
|
rs := r.Sym()
|
||||||
if d.ldr.IsItab(rs) {
|
if d.ldr.IsItab(rs) {
|
||||||
// This relocation can also point at an itab, in which case it
|
// This relocation can also point at an itab, in which case it
|
||||||
// means "the _type field of that itab".
|
// means "the Type field of that itab".
|
||||||
rs = decodeItabType(d.ldr, d.ctxt.Arch, rs)
|
rs = decodeItabType(d.ldr, d.ctxt.Arch, rs)
|
||||||
}
|
}
|
||||||
if !d.ldr.IsGoType(rs) && !d.ctxt.linkShared {
|
if !d.ldr.IsGoType(rs) && !d.ctxt.linkShared {
|
||||||
|
|
|
||||||
|
|
@ -301,7 +301,7 @@ func decodetypeGcprogShlib(ctxt *Link, data []byte) uint64 {
|
||||||
return decodeInuxi(ctxt.Arch, data[2*int32(ctxt.Arch.PtrSize)+8+1*int32(ctxt.Arch.PtrSize):], ctxt.Arch.PtrSize)
|
return decodeInuxi(ctxt.Arch, data[2*int32(ctxt.Arch.PtrSize)+8+1*int32(ctxt.Arch.PtrSize):], ctxt.Arch.PtrSize)
|
||||||
}
|
}
|
||||||
|
|
||||||
// decodeItabType returns the itab._type field from an itab.
|
// decodeItabType returns the itab.Type field from an itab.
|
||||||
func decodeItabType(ldr *loader.Loader, arch *sys.Arch, symIdx loader.Sym) loader.Sym {
|
func decodeItabType(ldr *loader.Loader, arch *sys.Arch, symIdx loader.Sym) loader.Sym {
|
||||||
relocs := ldr.Relocs(symIdx)
|
relocs := ldr.Relocs(symIdx)
|
||||||
return decodeRelocSym(ldr, symIdx, &relocs, int32(arch.PtrSize))
|
return decodeRelocSym(ldr, symIdx, &relocs, int32(arch.PtrSize))
|
||||||
|
|
|
||||||
|
|
@ -1786,7 +1786,7 @@ func dwarfGenerateDebugInfo(ctxt *Link) {
|
||||||
"type:internal/abi.SliceType",
|
"type:internal/abi.SliceType",
|
||||||
"type:internal/abi.StructType",
|
"type:internal/abi.StructType",
|
||||||
"type:internal/abi.InterfaceType",
|
"type:internal/abi.InterfaceType",
|
||||||
"type:runtime.itab",
|
"type:internal/abi.ITab",
|
||||||
"type:internal/abi.Imethod"} {
|
"type:internal/abi.Imethod"} {
|
||||||
d.defgotype(d.lookupOrDiag(typ))
|
d.defgotype(d.lookupOrDiag(typ))
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -65,7 +65,7 @@ func TestRuntimeTypesPresent(t *testing.T) {
|
||||||
"internal/abi.SliceType": true,
|
"internal/abi.SliceType": true,
|
||||||
"internal/abi.StructType": true,
|
"internal/abi.StructType": true,
|
||||||
"internal/abi.InterfaceType": true,
|
"internal/abi.InterfaceType": true,
|
||||||
"runtime.itab": true,
|
"internal/abi.ITab": true,
|
||||||
}
|
}
|
||||||
|
|
||||||
found := findTypes(t, dwarf, want)
|
found := findTypes(t, dwarf, want)
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,21 @@
|
||||||
|
// Copyright 2023 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package abi
|
||||||
|
|
||||||
|
// The first word of every non-empty interface type contains an *ITab.
|
||||||
|
// It records the underlying concrete type (Type), the interface type it
|
||||||
|
// is implementing (Inter), and some ancillary information.
|
||||||
|
//
|
||||||
|
// layout of ITab known to compilers
|
||||||
|
// allocated in non-garbage-collected memory
|
||||||
|
// Needs to be in sync with
|
||||||
|
// cmd/compile/internal/reflectdata/reflect.go:/^func.WritePluginTable.
|
||||||
|
type ITab struct {
|
||||||
|
Inter *InterfaceType
|
||||||
|
Type *Type
|
||||||
|
Hash uint32 // copy of Type.Hash. Used for type switches.
|
||||||
|
_ [4]byte
|
||||||
|
Fun [1]uintptr // variable sized. fun[0]==0 means Type does not implement Inter.
|
||||||
|
}
|
||||||
|
|
@ -100,7 +100,7 @@ func interhash(p unsafe.Pointer, h uintptr) uintptr {
|
||||||
if tab == nil {
|
if tab == nil {
|
||||||
return h
|
return h
|
||||||
}
|
}
|
||||||
t := tab._type
|
t := tab.Type
|
||||||
if t.Equal == nil {
|
if t.Equal == nil {
|
||||||
// Check hashability here. We could do this check inside
|
// Check hashability here. We could do this check inside
|
||||||
// typehash, but we want to report the topmost type in
|
// typehash, but we want to report the topmost type in
|
||||||
|
|
@ -223,7 +223,7 @@ func mapKeyError2(t *_type, p unsafe.Pointer) error {
|
||||||
if a.tab == nil {
|
if a.tab == nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
t = a.tab._type
|
t = a.tab.Type
|
||||||
pdata = &a.data
|
pdata = &a.data
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -329,7 +329,7 @@ func ifaceeq(tab *itab, x, y unsafe.Pointer) bool {
|
||||||
if tab == nil {
|
if tab == nil {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
t := tab._type
|
t := tab.Type
|
||||||
eq := t.Equal
|
eq := t.Equal
|
||||||
if eq == nil {
|
if eq == nil {
|
||||||
panic(errorString("comparing uncomparable type " + toRType(t).string()))
|
panic(errorString("comparing uncomparable type " + toRType(t).string()))
|
||||||
|
|
|
||||||
|
|
@ -540,7 +540,7 @@ func dumpparams() {
|
||||||
}
|
}
|
||||||
|
|
||||||
func itab_callback(tab *itab) {
|
func itab_callback(tab *itab) {
|
||||||
t := tab._type
|
t := tab.Type
|
||||||
dumptype(t)
|
dumptype(t)
|
||||||
dumpint(tagItab)
|
dumpint(tagItab)
|
||||||
dumpint(uint64(uintptr(unsafe.Pointer(tab))))
|
dumpint(uint64(uintptr(unsafe.Pointer(tab))))
|
||||||
|
|
|
||||||
|
|
@ -66,19 +66,19 @@ func getitab(inter *interfacetype, typ *_type, canfail bool) *itab {
|
||||||
|
|
||||||
// Entry doesn't exist yet. Make a new entry & add it.
|
// Entry doesn't exist yet. Make a new entry & add it.
|
||||||
m = (*itab)(persistentalloc(unsafe.Sizeof(itab{})+uintptr(len(inter.Methods)-1)*goarch.PtrSize, 0, &memstats.other_sys))
|
m = (*itab)(persistentalloc(unsafe.Sizeof(itab{})+uintptr(len(inter.Methods)-1)*goarch.PtrSize, 0, &memstats.other_sys))
|
||||||
m.inter = inter
|
m.Inter = inter
|
||||||
m._type = typ
|
m.Type = typ
|
||||||
// The hash is used in type switches. However, compiler statically generates itab's
|
// The hash is used in type switches. However, compiler statically generates itab's
|
||||||
// for all interface/type pairs used in switches (which are added to itabTable
|
// for all interface/type pairs used in switches (which are added to itabTable
|
||||||
// in itabsinit). The dynamically-generated itab's never participate in type switches,
|
// in itabsinit). The dynamically-generated itab's never participate in type switches,
|
||||||
// and thus the hash is irrelevant.
|
// and thus the hash is irrelevant.
|
||||||
// Note: m.hash is _not_ the hash used for the runtime itabTable hash table.
|
// Note: m.Hash is _not_ the hash used for the runtime itabTable hash table.
|
||||||
m.hash = 0
|
m.Hash = 0
|
||||||
m.init()
|
itabInit(m)
|
||||||
itabAdd(m)
|
itabAdd(m)
|
||||||
unlock(&itabLock)
|
unlock(&itabLock)
|
||||||
finish:
|
finish:
|
||||||
if m.fun[0] != 0 {
|
if m.Fun[0] != 0 {
|
||||||
return m
|
return m
|
||||||
}
|
}
|
||||||
if canfail {
|
if canfail {
|
||||||
|
|
@ -90,7 +90,7 @@ finish:
|
||||||
// The cached result doesn't record which
|
// The cached result doesn't record which
|
||||||
// interface function was missing, so initialize
|
// interface function was missing, so initialize
|
||||||
// the itab again to get the missing function name.
|
// the itab again to get the missing function name.
|
||||||
panic(&TypeAssertionError{concrete: typ, asserted: &inter.Type, missingMethod: m.init()})
|
panic(&TypeAssertionError{concrete: typ, asserted: &inter.Type, missingMethod: itabInit(m)})
|
||||||
}
|
}
|
||||||
|
|
||||||
// find finds the given interface/type pair in t.
|
// find finds the given interface/type pair in t.
|
||||||
|
|
@ -110,7 +110,7 @@ func (t *itabTableType) find(inter *interfacetype, typ *_type) *itab {
|
||||||
if m == nil {
|
if m == nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
if m.inter == inter && m._type == typ {
|
if m.Inter == inter && m.Type == typ {
|
||||||
return m
|
return m
|
||||||
}
|
}
|
||||||
h += i
|
h += i
|
||||||
|
|
@ -161,7 +161,7 @@ func (t *itabTableType) add(m *itab) {
|
||||||
// See comment in find about the probe sequence.
|
// See comment in find about the probe sequence.
|
||||||
// Insert new itab in the first empty spot in the probe sequence.
|
// Insert new itab in the first empty spot in the probe sequence.
|
||||||
mask := t.size - 1
|
mask := t.size - 1
|
||||||
h := itabHashFunc(m.inter, m._type) & mask
|
h := itabHashFunc(m.Inter, m.Type) & mask
|
||||||
for i := uintptr(1); ; i++ {
|
for i := uintptr(1); ; i++ {
|
||||||
p := (**itab)(add(unsafe.Pointer(&t.entries), h*goarch.PtrSize))
|
p := (**itab)(add(unsafe.Pointer(&t.entries), h*goarch.PtrSize))
|
||||||
m2 := *p
|
m2 := *p
|
||||||
|
|
@ -186,13 +186,13 @@ func (t *itabTableType) add(m *itab) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// init fills in the m.fun array with all the code pointers for
|
// init fills in the m.Fun array with all the code pointers for
|
||||||
// the m.inter/m._type pair. If the type does not implement the interface,
|
// the m.Inter/m.Type pair. If the type does not implement the interface,
|
||||||
// it sets m.fun[0] to 0 and returns the name of an interface function that is missing.
|
// it sets m.Fun[0] to 0 and returns the name of an interface function that is missing.
|
||||||
// It is ok to call this multiple times on the same m, even concurrently.
|
// It is ok to call this multiple times on the same m, even concurrently.
|
||||||
func (m *itab) init() string {
|
func itabInit(m *itab) string {
|
||||||
inter := m.inter
|
inter := m.Inter
|
||||||
typ := m._type
|
typ := m.Type
|
||||||
x := typ.Uncommon()
|
x := typ.Uncommon()
|
||||||
|
|
||||||
// both inter and typ have method sorted by name,
|
// both inter and typ have method sorted by name,
|
||||||
|
|
@ -203,7 +203,7 @@ func (m *itab) init() string {
|
||||||
nt := int(x.Mcount)
|
nt := int(x.Mcount)
|
||||||
xmhdr := (*[1 << 16]abi.Method)(add(unsafe.Pointer(x), uintptr(x.Moff)))[:nt:nt]
|
xmhdr := (*[1 << 16]abi.Method)(add(unsafe.Pointer(x), uintptr(x.Moff)))[:nt:nt]
|
||||||
j := 0
|
j := 0
|
||||||
methods := (*[1 << 16]unsafe.Pointer)(unsafe.Pointer(&m.fun[0]))[:ni:ni]
|
methods := (*[1 << 16]unsafe.Pointer)(unsafe.Pointer(&m.Fun[0]))[:ni:ni]
|
||||||
var fun0 unsafe.Pointer
|
var fun0 unsafe.Pointer
|
||||||
imethods:
|
imethods:
|
||||||
for k := 0; k < ni; k++ {
|
for k := 0; k < ni; k++ {
|
||||||
|
|
@ -227,7 +227,7 @@ imethods:
|
||||||
if tname.IsExported() || pkgPath == ipkg {
|
if tname.IsExported() || pkgPath == ipkg {
|
||||||
ifn := rtyp.textOff(t.Ifn)
|
ifn := rtyp.textOff(t.Ifn)
|
||||||
if k == 0 {
|
if k == 0 {
|
||||||
fun0 = ifn // we'll set m.fun[0] at the end
|
fun0 = ifn // we'll set m.Fun[0] at the end
|
||||||
} else {
|
} else {
|
||||||
methods[k] = ifn
|
methods[k] = ifn
|
||||||
}
|
}
|
||||||
|
|
@ -236,10 +236,10 @@ imethods:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// didn't find method
|
// didn't find method
|
||||||
m.fun[0] = 0
|
m.Fun[0] = 0
|
||||||
return iname
|
return iname
|
||||||
}
|
}
|
||||||
m.fun[0] = uintptr(fun0)
|
m.Fun[0] = uintptr(fun0)
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -267,7 +267,7 @@ func panicdottypeE(have, want, iface *_type) {
|
||||||
func panicdottypeI(have *itab, want, iface *_type) {
|
func panicdottypeI(have *itab, want, iface *_type) {
|
||||||
var t *_type
|
var t *_type
|
||||||
if have != nil {
|
if have != nil {
|
||||||
t = have._type
|
t = have.Type
|
||||||
}
|
}
|
||||||
panicdottypeE(t, want, iface)
|
panicdottypeE(t, want, iface)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -990,17 +990,7 @@ type funcinl struct {
|
||||||
startLine int32
|
startLine int32
|
||||||
}
|
}
|
||||||
|
|
||||||
// layout of Itab known to compilers
|
type itab = abi.ITab
|
||||||
// allocated in non-garbage-collected memory
|
|
||||||
// Needs to be in sync with
|
|
||||||
// ../cmd/compile/internal/reflectdata/reflect.go:/^func.WritePluginTable.
|
|
||||||
type itab struct {
|
|
||||||
inter *interfacetype
|
|
||||||
_type *_type
|
|
||||||
hash uint32 // copy of _type.hash. Used for type switches.
|
|
||||||
_ [4]byte
|
|
||||||
fun [1]uintptr // variable sized. fun[0]==0 means _type does not implement inter.
|
|
||||||
}
|
|
||||||
|
|
||||||
// Lock-free stack node.
|
// Lock-free stack node.
|
||||||
// Also known to export_test.go.
|
// Also known to export_test.go.
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue