1
0
mirror of https://github.com/golang/go synced 2024-11-23 03:50:03 -07:00

runtime: redefine _type to abi.Type; add rtype for methods.

Change-Id: I1c478b704d84811caa209006c657dda82d9c4cf9
Reviewed-on: https://go-review.googlesource.com/c/go/+/488435
Reviewed-by: Keith Randall <khr@golang.org>
Run-TryBot: David Chase <drchase@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Keith Randall <khr@google.com>
This commit is contained in:
David Chase 2023-04-24 15:45:33 -04:00
parent 48f8c5c037
commit a2838ec5f2
19 changed files with 76 additions and 75 deletions

View File

@ -1802,7 +1802,7 @@ func dwarfGenerateDebugInfo(ctxt *Link) {
// Needed by the prettyprinter code for interface inspection.
for _, typ := range []string{
"type:runtime._type",
"type:internal/abi.Type",
"type:internal/abi.ArrayType",
"type:internal/abi.ChanType",
"type:runtime.functype",

View File

@ -56,7 +56,7 @@ func TestRuntimeTypesPresent(t *testing.T) {
}
want := map[string]bool{
"runtime._type": true,
"internal/abi.Type": true,
"internal/abi.ArrayType": true,
"internal/abi.ChanType": true,
"runtime.functype": true,

View File

@ -279,8 +279,7 @@ const Ptr = Pointer
// to describe a non-defined type with no methods.
type uncommonType = abi.UncommonType
// rtype is the common implementation of most values.
// It is embedded in other struct types.
// rtype is a wrapper that allows us to define exactly the type.Reflect methods.
type rtype struct {
t *abi.Type
}

View File

@ -106,7 +106,7 @@ func interhash(p unsafe.Pointer, h uintptr) uintptr {
// typehash, but we want to report the topmost type in
// the error text (e.g. in a struct with a field of slice type
// we want to report the struct, not the slice).
panic(errorString("hash of unhashable type " + t.string()))
panic(errorString("hash of unhashable type " + toRType(t).string()))
}
if isDirectIface(t) {
return c1 * typehash(t, unsafe.Pointer(&a.data), h^c0)
@ -123,7 +123,7 @@ func nilinterhash(p unsafe.Pointer, h uintptr) uintptr {
}
if t.Equal == nil {
// See comment in interhash above.
panic(errorString("hash of unhashable type " + t.string()))
panic(errorString("hash of unhashable type " + toRType(t).string()))
}
if isDirectIface(t) {
return c1 * typehash(t, unsafe.Pointer(&a.data), h^c0)
@ -174,7 +174,7 @@ func typehash(t *_type, p unsafe.Pointer, h uintptr) uintptr {
case kindArray:
a := (*arraytype)(unsafe.Pointer(t))
for i := uintptr(0); i < a.Len; i++ {
h = typehash(toType(a.Elem), add(p, i*a.Elem.Size_), h)
h = typehash(a.Elem, add(p, i*a.Elem.Size_), h)
}
return h
case kindStruct:
@ -189,7 +189,7 @@ func typehash(t *_type, p unsafe.Pointer, h uintptr) uintptr {
default:
// Should never happen, as typehash should only be called
// with comparable types.
panic(errorString("hash of unhashable type " + t.string()))
panic(errorString("hash of unhashable type " + toRType(t).string()))
}
}
@ -247,7 +247,7 @@ func efaceeq(t *_type, x, y unsafe.Pointer) bool {
}
eq := t.Equal
if eq == nil {
panic(errorString("comparing uncomparable type " + t.string()))
panic(errorString("comparing uncomparable type " + toRType(t).string()))
}
if isDirectIface(t) {
// Direct interface types are ptr, chan, map, func, and single-element structs/arrays thereof.
@ -264,7 +264,7 @@ func ifaceeq(tab *itab, x, y unsafe.Pointer) bool {
t := tab._type
eq := t.Equal
if eq == nil {
panic(errorString("comparing uncomparable type " + t.string()))
panic(errorString("comparing uncomparable type " + toRType(t).string()))
}
if isDirectIface(t) {
// See comment in efaceeq.

View File

@ -466,11 +466,11 @@ func cgoCheckArg(t *_type, p unsafe.Pointer, indir, top bool, msg string) {
if at.Len != 1 {
throw("can't happen")
}
cgoCheckArg(toType(at.Elem), p, at.Elem.Kind_&kindDirectIface == 0, top, msg)
cgoCheckArg(at.Elem, p, at.Elem.Kind_&kindDirectIface == 0, top, msg)
return
}
for i := uintptr(0); i < at.Len; i++ {
cgoCheckArg(toType(at.Elem), p, true, top, msg)
cgoCheckArg(at.Elem, p, true, top, msg)
p = add(p, at.Elem.Size_)
}
case kindChan, kindMap:

View File

@ -249,7 +249,7 @@ func cgoCheckUsingType(typ *_type, src unsafe.Pointer, off, size uintptr) {
at := (*arraytype)(unsafe.Pointer(typ))
for i := uintptr(0); i < at.Len; i++ {
if off < at.Elem.Size_ {
cgoCheckUsingType(toType(at.Elem), src, off, size)
cgoCheckUsingType(at.Elem, src, off, size)
}
src = add(src, at.Elem.Size_)
skipped := off

View File

@ -104,11 +104,11 @@ func makechan(t *chantype, size int) *hchan {
default:
// Elements contain pointers.
c = new(hchan)
c.buf = mallocgc(mem, toType(elem), true)
c.buf = mallocgc(mem, elem, true)
}
c.elemsize = uint16(elem.Size_)
c.elemtype = toType(elem)
c.elemtype = elem
c.dataqsiz = uint(size)
lockInit(&c.lock, lockRankHchan)

View File

@ -30,18 +30,18 @@ func (*TypeAssertionError) RuntimeError() {}
func (e *TypeAssertionError) Error() string {
inter := "interface"
if e._interface != nil {
inter = e._interface.string()
inter = toRType(e._interface).string()
}
as := e.asserted.string()
as := toRType(e.asserted).string()
if e.concrete == nil {
return "interface conversion: " + inter + " is nil, not " + as
}
cs := e.concrete.string()
cs := toRType(e.concrete).string()
if e.missingMethod == "" {
msg := "interface conversion: " + inter + " is " + cs + ", not " + as
if cs == as {
// provide slightly clearer error message
if e.concrete.pkgpath() != e.asserted.pkgpath() {
if toRType(e.concrete).pkgpath() != toRType(e.asserted).pkgpath() {
msg += " (types from different packages)"
} else {
msg += " (types from different scopes)"
@ -256,7 +256,7 @@ func printany(i any) {
func printanycustomtype(i any) {
eface := efaceOf(&i)
typestring := eface._type.string()
typestring := toRType(eface._type).string()
switch eface._type.Kind_ {
case kindString:

View File

@ -194,11 +194,12 @@ func dumptype(t *_type) {
dumpint(tagType)
dumpint(uint64(uintptr(unsafe.Pointer(t))))
dumpint(uint64(t.Size_))
if x := t.uncommon(); x == nil || t.nameOff(x.PkgPath).name() == "" {
dumpstr(t.string())
rt := toRType(t)
if x := t.Uncommon(); x == nil || rt.nameOff(x.PkgPath).name() == "" {
dumpstr(rt.string())
} else {
pkgpath := t.nameOff(x.PkgPath).name()
name := t.name()
pkgpath := rt.nameOff(x.PkgPath).name()
name := rt.name()
dumpint(uint64(uintptr(len(pkgpath)) + 1 + uintptr(len(name))))
dwrite(unsafe.Pointer(unsafe.StringData(pkgpath)), uintptr(len(pkgpath)))
dwritebyte('.')

View File

@ -41,7 +41,7 @@ func getitab(inter *interfacetype, typ *_type, canfail bool) *itab {
if canfail {
return nil
}
name := inter.typ.nameOff(inter.mhdr[0].Name)
name := toRType(&inter.typ).nameOff(inter.mhdr[0].Name)
panic(&TypeAssertionError{nil, typ, &inter.typ, name.name()})
}
@ -192,7 +192,7 @@ func (t *itabTableType) add(m *itab) {
func (m *itab) init() string {
inter := m.inter
typ := m._type
x := typ.uncommon()
x := typ.Uncommon()
// both inter and typ have method sorted by name,
// and interface names are unique,
@ -207,8 +207,8 @@ func (m *itab) init() string {
imethods:
for k := 0; k < ni; k++ {
i := &inter.mhdr[k]
itype := inter.typ.typeOff(i.Typ)
name := inter.typ.nameOff(i.Name)
itype := toRType(&inter.typ).typeOff(i.Typ)
name := toRType(&inter.typ).nameOff(i.Name)
iname := name.name()
ipkg := name.pkgPath()
if ipkg == "" {
@ -216,15 +216,16 @@ imethods:
}
for ; j < nt; j++ {
t := &xmhdr[j]
tname := typ.nameOff(t.Name)
if typ.typeOff(t.Mtyp) == itype && tname.name() == iname {
rtyp := toRType(typ)
tname := rtyp.nameOff(t.Name)
if rtyp.typeOff(t.Mtyp) == itype && tname.name() == iname {
pkgPath := tname.pkgPath()
if pkgPath == "" {
pkgPath = typ.nameOff(x.PkgPath).name()
pkgPath = rtyp.nameOff(x.PkgPath).name()
}
if tname.isExported() || pkgPath == ipkg {
if m != nil {
ifn := typ.textOff(t.Ifn)
ifn := rtyp.textOff(t.Ifn)
if k == 0 {
fun0 = ifn // we'll set m.fun[0] at the end
} else {

View File

@ -155,7 +155,7 @@ import (
// anywhere in the bulk barrier or memmove.
//
//go:nosplit
func typedmemmove(typ *_type, dst, src unsafe.Pointer) {
func typedmemmove(typ *abi.Type, dst, src unsafe.Pointer) {
if dst == src {
return
}

View File

@ -683,11 +683,11 @@ func typeBitsBulkBarrier(typ *_type, dst, src, size uintptr) {
throw("runtime: typeBitsBulkBarrier without type")
}
if typ.Size_ != size {
println("runtime: typeBitsBulkBarrier with type ", typ.string(), " of size ", typ.Size_, " but memory size", size)
println("runtime: typeBitsBulkBarrier with type ", toRType(typ).string(), " of size ", typ.Size_, " but memory size", size)
throw("runtime: invalid typeBitsBulkBarrier")
}
if typ.Kind_&kindGCProg != 0 {
println("runtime: typeBitsBulkBarrier with type ", typ.string(), " with GC prog")
println("runtime: typeBitsBulkBarrier with type ", toRType(typ).string(), " with GC prog")
throw("runtime: invalid typeBitsBulkBarrier")
}
if !writeBarrier.needed {

View File

@ -372,7 +372,7 @@ func SetFinalizer(obj any, finalizer any) {
throw("runtime.SetFinalizer: first argument is nil")
}
if etyp.Kind_&kindMask != kindPtr {
throw("runtime.SetFinalizer: first argument is " + etyp.string() + ", not pointer")
throw("runtime.SetFinalizer: first argument is " + toRType(etyp).string() + ", not pointer")
}
ot := (*ptrtype)(unsafe.Pointer(etyp))
if ot.elem == nil {
@ -431,14 +431,14 @@ func SetFinalizer(obj any, finalizer any) {
}
if ftyp.Kind_&kindMask != kindFunc {
throw("runtime.SetFinalizer: second argument is " + ftyp.string() + ", not a function")
throw("runtime.SetFinalizer: second argument is " + toRType(ftyp).string() + ", not a function")
}
ft := (*functype)(unsafe.Pointer(ftyp))
if ft.dotdotdot() {
throw("runtime.SetFinalizer: cannot pass " + etyp.string() + " to finalizer " + ftyp.string() + " because dotdotdot")
throw("runtime.SetFinalizer: cannot pass " + toRType(etyp).string() + " to finalizer " + toRType(ftyp).string() + " because dotdotdot")
}
if ft.inCount != 1 {
throw("runtime.SetFinalizer: cannot pass " + etyp.string() + " to finalizer " + ftyp.string())
throw("runtime.SetFinalizer: cannot pass " + toRType(etyp).string() + " to finalizer " + toRType(ftyp).string())
}
fint := ft.in()[0]
switch {
@ -446,7 +446,7 @@ func SetFinalizer(obj any, finalizer any) {
// ok - same type
goto okarg
case fint.Kind_&kindMask == kindPtr:
if (fint.uncommon() == nil || etyp.uncommon() == nil) && (*ptrtype)(unsafe.Pointer(fint)).elem == ot.elem {
if (fint.Uncommon() == nil || etyp.Uncommon() == nil) && (*ptrtype)(unsafe.Pointer(fint)).elem == ot.elem {
// ok - not same type, but both pointers,
// one or the other is unnamed, and same element type, so assignable.
goto okarg
@ -461,7 +461,7 @@ func SetFinalizer(obj any, finalizer any) {
goto okarg
}
}
throw("runtime.SetFinalizer: cannot pass " + etyp.string() + " to finalizer " + ftyp.string())
throw("runtime.SetFinalizer: cannot pass " + toRType(etyp).string() + " to finalizer " + toRType(ftyp).string())
okarg:
// compute size needed for return parameters
nret := uintptr(0)

View File

@ -1230,7 +1230,7 @@ func tracealloc(p unsafe.Pointer, size uintptr, typ *_type) {
if typ == nil {
print("tracealloc(", p, ", ", hex(size), ")\n")
} else {
print("tracealloc(", p, ", ", hex(size), ", ", typ.string(), ")\n")
print("tracealloc(", p, ", ", hex(size), ", ", toRType(typ).string(), ")\n")
}
if gp.m.curg == nil || gp == gp.m.curg {
goroutineheader(gp)

View File

@ -573,7 +573,7 @@ func preprintpanics(p *_panic) {
case string:
throw(text + ": " + r)
default:
throw(text + ": type " + efaceOf(&r)._type.string())
throw(text + ": type " + toRType(efaceOf(&r)._type).string())
}
}()
for p != nil {

View File

@ -79,7 +79,7 @@ func plugin_lastmoduleinit() (path string, syms map[string]any, initTasks []*ini
syms = make(map[string]any, len(md.ptab))
for _, ptab := range md.ptab {
symName := resolveNameOff(unsafe.Pointer(md.types), ptab.name)
t := (*_type)(unsafe.Pointer(md.types)).typeOff(ptab.typ)
t := toRType((*_type)(unsafe.Pointer(md.types))).typeOff(ptab.typ) // TODO can this stack of conversions be simpler?
var val any
valp := (*[2]unsafe.Pointer)(unsafe.Pointer(&val))
(*valp)[0] = unsafe.Pointer(t)

View File

@ -608,14 +608,14 @@ func reflect_resolveNameOff(ptrInModule unsafe.Pointer, off int32) unsafe.Pointe
//
//go:linkname reflect_resolveTypeOff reflect.resolveTypeOff
func reflect_resolveTypeOff(rtype unsafe.Pointer, off int32) unsafe.Pointer {
return unsafe.Pointer((*_type)(rtype).typeOff(typeOff(off)))
return unsafe.Pointer(toRType((*_type)(rtype)).typeOff(typeOff(off)))
}
// reflect_resolveTextOff resolves a function pointer offset from a base type.
//
//go:linkname reflect_resolveTextOff reflect.resolveTextOff
func reflect_resolveTextOff(rtype unsafe.Pointer, off int32) unsafe.Pointer {
return (*_type)(rtype).textOff(textOff(off))
return toRType((*_type)(rtype)).textOff(textOff(off))
}
@ -630,7 +630,7 @@ func reflectlite_resolveNameOff(ptrInModule unsafe.Pointer, off int32) unsafe.Po
//
//go:linkname reflectlite_resolveTypeOff internal/reflectlite.resolveTypeOff
func reflectlite_resolveTypeOff(rtype unsafe.Pointer, off int32) unsafe.Pointer {
return unsafe.Pointer((*_type)(rtype).typeOff(typeOff(off)))
return unsafe.Pointer(toRType((*_type)(rtype)).typeOff(typeOff(off)))
}
// reflect_addReflectOff adds a pointer to the reflection offset lookup map.

View File

@ -200,7 +200,7 @@ func (p *abiDesc) tryRegAssignArg(t *_type, offset uintptr) bool {
}
// Pointer-sized types such as maps and channels are currently
// not supported.
panic("compileCallabck: type " + t.string() + " is currently not supported for use in system callbacks")
panic("compileCallback: type " + toRType(t).string() + " is currently not supported for use in system callbacks")
}
// assignReg attempts to assign a single register for an

View File

@ -15,15 +15,14 @@ type nameOff = abi.NameOff
type typeOff = abi.TypeOff
type textOff = abi.TextOff
// Needs to be in sync with ../cmd/link/internal/ld/decodesym.go:/^func.commonsize,
// ../cmd/compile/internal/reflectdata/reflect.go:/^func.dcommontype and
// ../reflect/type.go:/^type.rtype.
// ../internal/reflectlite/type.go:/^type.rtype.
type _type struct {
abi.Type
type _type = abi.Type
// rtype is a wrapper that allows us to define additional methods.
type rtype struct {
*abi.Type // embedding is okay here (unlike reflect) because none of this is public
}
func (t *_type) string() string {
func (t rtype) string() string {
s := t.nameOff(t.Str).name()
if t.TFlag&abi.TFlagExtraStar != 0 {
return s[1:]
@ -31,11 +30,11 @@ func (t *_type) string() string {
return s
}
func (t *_type) uncommon() *uncommontype {
func (t rtype) uncommon() *uncommontype {
return t.Uncommon()
}
func (t *_type) name() string {
func (t rtype) name() string {
if t.TFlag&abi.TFlagNamed == 0 {
return ""
}
@ -58,16 +57,16 @@ func (t *_type) name() string {
// available. This is not the same as the reflect package's PkgPath
// method, in that it returns the package path for struct and interface
// types, not just named types.
func (t *_type) pkgpath() string {
func (t rtype) pkgpath() string {
if u := t.uncommon(); u != nil {
return t.nameOff(u.PkgPath).name()
}
switch t.Kind_ & kindMask {
case kindStruct:
st := (*structtype)(unsafe.Pointer(t))
st := (*structtype)(unsafe.Pointer(t.Type))
return st.pkgPath.name()
case kindInterface:
it := (*interfacetype)(unsafe.Pointer(t))
it := (*interfacetype)(unsafe.Pointer(t.Type))
return it.pkgpath.name()
}
return ""
@ -137,8 +136,8 @@ func resolveNameOff(ptrInModule unsafe.Pointer, off nameOff) name {
return name{(*byte)(res)}
}
func (t *_type) nameOff(off nameOff) name {
return resolveNameOff(unsafe.Pointer(t), off)
func (t rtype) nameOff(off nameOff) name {
return resolveNameOff(unsafe.Pointer(t.Type), off)
}
func resolveTypeOff(ptrInModule unsafe.Pointer, off typeOff) *_type {
@ -179,17 +178,17 @@ func resolveTypeOff(ptrInModule unsafe.Pointer, off typeOff) *_type {
return (*_type)(unsafe.Pointer(res))
}
func (t *_type) typeOff(off typeOff) *_type {
return resolveTypeOff(unsafe.Pointer(t), off)
func (t rtype) typeOff(off typeOff) *_type {
return resolveTypeOff(unsafe.Pointer(t.Type), off)
}
func (t *_type) textOff(off textOff) unsafe.Pointer {
func (t rtype) textOff(off textOff) unsafe.Pointer {
if off == -1 {
// -1 is the sentinel value for unreachable code.
// See cmd/link/internal/ld/data.go:relocsym.
return unsafe.Pointer(abi.FuncPCABIInternal(unreachableMethod))
}
base := uintptr(unsafe.Pointer(t))
base := uintptr(unsafe.Pointer(t.Type))
var md *moduledata
for next := &firstmoduledata; next != nil; next = next.next {
if base >= next.types && base < next.etypes {
@ -440,8 +439,8 @@ type _typePair struct {
t2 *_type
}
func toType(t *abi.Type) *_type {
return (*_type)(unsafe.Pointer(t))
func toRType(t *abi.Type) rtype {
return rtype{t}
}
// typesEqual reports whether two types are equal.
@ -474,17 +473,18 @@ func typesEqual(t, v *_type, seen map[_typePair]struct{}) bool {
if kind != v.Kind_&kindMask {
return false
}
if t.string() != v.string() {
rt, rv := toRType(t), toRType(v)
if rt.string() != rv.string() {
return false
}
ut := t.uncommon()
uv := v.uncommon()
ut := t.Uncommon()
uv := v.Uncommon()
if ut != nil || uv != nil {
if ut == nil || uv == nil {
return false
}
pkgpatht := t.nameOff(ut.PkgPath).name()
pkgpathv := v.nameOff(uv.PkgPath).name()
pkgpatht := rt.nameOff(ut.PkgPath).name()
pkgpathv := rv.nameOff(uv.PkgPath).name()
if pkgpatht != pkgpathv {
return false
}
@ -498,11 +498,11 @@ func typesEqual(t, v *_type, seen map[_typePair]struct{}) bool {
case kindArray:
at := (*arraytype)(unsafe.Pointer(t))
av := (*arraytype)(unsafe.Pointer(v))
return typesEqual(toType(at.Elem), toType(av.Elem), seen) && at.Len == av.Len
return typesEqual(at.Elem, av.Elem, seen) && at.Len == av.Len
case kindChan:
ct := (*chantype)(unsafe.Pointer(t))
cv := (*chantype)(unsafe.Pointer(v))
return ct.Dir == cv.Dir && typesEqual(toType(ct.Elem), toType(cv.Elem), seen)
return ct.Dir == cv.Dir && typesEqual(ct.Elem, cv.Elem, seen)
case kindFunc:
ft := (*functype)(unsafe.Pointer(t))
fv := (*functype)(unsafe.Pointer(v))