--- /dev/null
+// 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.
+}
// 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.inter = inter
- m._type = typ
+ m.Inter = inter
+ m.Type = typ
// 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
// in itabsinit). The dynamically-generated itab's never participate in type switches,
// and thus the hash is irrelevant.
- // Note: m.hash is _not_ the hash used for the runtime itabTable hash table.
- m.hash = 0
- m.init()
+ // Note: m.Hash is _not_ the hash used for the runtime itabTable hash table.
+ m.Hash = 0
+ itabInit(m)
itabAdd(m)
unlock(&itabLock)
finish:
- if m.fun[0] != 0 {
+ if m.Fun[0] != 0 {
return m
}
if canfail {
// The cached result doesn't record which
// interface function was missing, so initialize
// 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.
if m == nil {
return nil
}
- if m.inter == inter && m._type == typ {
+ if m.Inter == inter && m.Type == typ {
return m
}
h += i
// See comment in find about the probe sequence.
// Insert new itab in the first empty spot in the probe sequence.
mask := t.size - 1
- h := itabHashFunc(m.inter, m._type) & mask
+ h := itabHashFunc(m.Inter, m.Type) & mask
for i := uintptr(1); ; i++ {
p := (**itab)(add(unsafe.Pointer(&t.entries), h*goarch.PtrSize))
m2 := *p
}
}
-// 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,
-// it sets m.fun[0] to 0 and returns the name of an interface function that is missing.
+// 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,
+// 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.
-func (m *itab) init() string {
- inter := m.inter
- typ := m._type
+func itabInit(m *itab) string {
+ inter := m.Inter
+ typ := m.Type
x := typ.Uncommon()
// both inter and typ have method sorted by name,
nt := int(x.Mcount)
xmhdr := (*[1 << 16]abi.Method)(add(unsafe.Pointer(x), uintptr(x.Moff)))[:nt:nt]
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
imethods:
for k := 0; k < ni; k++ {
if tname.IsExported() || pkgPath == ipkg {
ifn := rtyp.textOff(t.Ifn)
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 {
methods[k] = ifn
}
}
}
// didn't find method
- m.fun[0] = 0
+ m.Fun[0] = 0
return iname
}
- m.fun[0] = uintptr(fun0)
+ m.Fun[0] = uintptr(fun0)
return ""
}
func panicdottypeI(have *itab, want, iface *_type) {
var t *_type
if have != nil {
- t = have._type
+ t = have.Type
}
panicdottypeE(t, want, iface)
}