mirror of
https://github.com/golang/go
synced 2024-11-19 16:54:44 -07:00
cmd/compile, etc: use name offset in method tables
Introduce and start using nameOff for two encoded names. This pair of changes is best done together because the linker's method decoder expects the method layouts to match. Precursor to converting all existing name and *string fields to nameOff. linux/amd64: cmd/go: -45KB (0.5%) jujud: -389KB (0.6%) linux/amd64 PIE: cmd/go: -170KB (1.4%) jujud: -1.5MB (1.8%) For #6853. Change-Id: Ia044423f010fb987ce070b94c46a16fc78666ff6 Reviewed-on: https://go-review.googlesource.com/21396 Reviewed-by: Ian Lance Taylor <iant@golang.org>
This commit is contained in:
parent
3c8d6af8e0
commit
95df0c6ab9
@ -70,7 +70,7 @@ const (
|
||||
)
|
||||
|
||||
func structfieldSize() int { return 3 * Widthptr } // Sizeof(runtime.structfield{})
|
||||
func imethodSize() int { return 2 * Widthptr } // Sizeof(runtime.imethod{})
|
||||
func imethodSize() int { return 4 + 4 } // Sizeof(runtime.imethod{})
|
||||
func uncommonSize(t *Type) int { // Sizeof(runtime.uncommontype{})
|
||||
if t.Sym == nil && len(methods(t)) == 0 {
|
||||
return 0
|
||||
@ -647,13 +647,11 @@ func dextratypeData(s *Sym, ot int, t *Type) int {
|
||||
pkg = a.pkg
|
||||
}
|
||||
nsym := dname(a.name, "", pkg, exported)
|
||||
ot = dsymptrLSym(lsym, ot, nsym, 0)
|
||||
|
||||
ot = dsymptrOffLSym(lsym, ot, nsym, 0)
|
||||
ot = dmethodptrOffLSym(lsym, ot, Linksym(dtypesym(a.mtype)))
|
||||
ot = dmethodptrOffLSym(lsym, ot, Linksym(a.isym))
|
||||
ot = dmethodptrOffLSym(lsym, ot, Linksym(a.tsym))
|
||||
if Widthptr == 8 {
|
||||
ot = duintxxLSym(lsym, ot, 0, 4) // pad to reflect.method size
|
||||
}
|
||||
}
|
||||
return ot
|
||||
}
|
||||
@ -1226,6 +1224,7 @@ ok:
|
||||
dataAdd := imethodSize() * n
|
||||
ot = dextratype(s, ot, t, dataAdd)
|
||||
|
||||
lsym := Linksym(s)
|
||||
for _, a := range m {
|
||||
// ../../../../runtime/type.go:/imethod
|
||||
exported := exportname(a.name)
|
||||
@ -1234,8 +1233,9 @@ ok:
|
||||
pkg = a.pkg
|
||||
}
|
||||
nsym := dname(a.name, "", pkg, exported)
|
||||
ot = dsymptrLSym(Linksym(s), ot, nsym, 0)
|
||||
ot = dsymptr(s, ot, dtypesym(a.type_), 0)
|
||||
|
||||
ot = dsymptrOffLSym(lsym, ot, nsym, 0)
|
||||
ot = dsymptrOffLSym(lsym, ot, Linksym(dtypesym(a.type_)), 0)
|
||||
}
|
||||
|
||||
// ../../../../runtime/type.go:/mapType
|
||||
|
@ -262,8 +262,9 @@ const (
|
||||
)
|
||||
|
||||
// decode_methodsig decodes an array of method signature information.
|
||||
// Each element of the array is size bytes. The first word is a
|
||||
// reflect.name for the name, the second word is a *rtype for the funcType.
|
||||
// Each element of the array is size bytes. The first 4 bytes is a
|
||||
// nameOff for the method name, and the next 4 bytes is a typeOff for
|
||||
// the function type.
|
||||
//
|
||||
// Conveniently this is the layout of both runtime.method and runtime.imethod.
|
||||
func decode_methodsig(s *LSym, off, size, count int) []methodsig {
|
||||
@ -271,7 +272,7 @@ func decode_methodsig(s *LSym, off, size, count int) []methodsig {
|
||||
var methods []methodsig
|
||||
for i := 0; i < count; i++ {
|
||||
buf.WriteString(decodetype_name(s, off))
|
||||
mtypSym := decode_reloc_sym(s, int32(off+SysArch.PtrSize))
|
||||
mtypSym := decode_reloc_sym(s, int32(off+4))
|
||||
|
||||
buf.WriteRune('(')
|
||||
inCount := decodetype_funcincount(mtypSym)
|
||||
@ -311,7 +312,7 @@ func decodetype_ifacemethods(s *LSym) []methodsig {
|
||||
}
|
||||
off := int(r.Add) // array of reflect.imethod values
|
||||
numMethods := int(decodetype_ifacemethodcount(s))
|
||||
sizeofIMethod := 2 * SysArch.PtrSize
|
||||
sizeofIMethod := 4 + 4
|
||||
return decode_methodsig(s, off, sizeofIMethod, numMethods)
|
||||
}
|
||||
|
||||
@ -343,12 +344,7 @@ func decodetype_methods(s *LSym) []methodsig {
|
||||
|
||||
mcount := int(decode_inuxi(s.P[off+SysArch.PtrSize:], 2))
|
||||
moff := int(decode_inuxi(s.P[off+SysArch.PtrSize+2:], 2))
|
||||
off += moff // offset to array of reflect.method values
|
||||
var sizeofMethod int // sizeof reflect.method in program
|
||||
if SysArch.PtrSize == 4 {
|
||||
sizeofMethod = 4 * SysArch.PtrSize
|
||||
} else {
|
||||
sizeofMethod = 3 * SysArch.PtrSize
|
||||
}
|
||||
off += moff // offset to array of reflect.method values
|
||||
const sizeofMethod = 4 * 4 // sizeof reflect.method in program
|
||||
return decode_methodsig(s, off, sizeofMethod, mcount)
|
||||
}
|
||||
|
@ -427,7 +427,7 @@ func symtab() {
|
||||
if !DynlinkingGo() {
|
||||
s.Attr |= AttrHidden
|
||||
}
|
||||
if UseRelro() && len(s.R) > 0 {
|
||||
if UseRelro() {
|
||||
s.Type = obj.STYPERELRO
|
||||
s.Outer = symtyperel
|
||||
} else {
|
||||
|
@ -50,7 +50,8 @@ func TypeLinks() []string {
|
||||
for i, offs := range offset {
|
||||
rodata := sections[i]
|
||||
for _, off := range offs {
|
||||
r = append(r, rtypeOff(rodata, off).string)
|
||||
typ := (*rtype)(resolveTypeOff(unsafe.Pointer(rodata), off))
|
||||
r = append(r, typ.string)
|
||||
}
|
||||
}
|
||||
return r
|
||||
@ -91,10 +92,11 @@ func FirstMethodNameBytes(t Type) *byte {
|
||||
panic("type has no methods")
|
||||
}
|
||||
m := ut.methods()[0]
|
||||
if *m.name.data(0)&(1<<2) == 0 {
|
||||
mname := t.(*rtype).nameOff(m.name)
|
||||
if *mname.data(0)&(1<<2) == 0 {
|
||||
panic("method name does not have pkgPath *string")
|
||||
}
|
||||
return m.name.bytes
|
||||
return mname.bytes
|
||||
}
|
||||
|
||||
type OtherPkgFields struct {
|
||||
|
@ -288,7 +288,7 @@ type typeAlg struct {
|
||||
|
||||
// Method on non-interface type
|
||||
type method struct {
|
||||
name name // name of method
|
||||
name nameOff // name of method
|
||||
mtyp typeOff // method type (without receiver)
|
||||
ifn textOff // fn used in interface call (one-word receiver)
|
||||
tfn textOff // fn used for normal method call
|
||||
@ -347,8 +347,8 @@ type funcType struct {
|
||||
|
||||
// imethod represents a method on an interface type
|
||||
type imethod struct {
|
||||
name name // name of method
|
||||
typ *rtype // .(*FuncType) underneath
|
||||
name nameOff // name of method
|
||||
typ typeOff // .(*FuncType) underneath
|
||||
}
|
||||
|
||||
// interfaceType represents an interface type.
|
||||
@ -424,19 +424,19 @@ type name struct {
|
||||
bytes *byte
|
||||
}
|
||||
|
||||
func (n *name) data(off int) *byte {
|
||||
func (n name) data(off int) *byte {
|
||||
return (*byte)(add(unsafe.Pointer(n.bytes), uintptr(off)))
|
||||
}
|
||||
|
||||
func (n *name) isExported() bool {
|
||||
func (n name) isExported() bool {
|
||||
return (*n.bytes)&(1<<0) != 0
|
||||
}
|
||||
|
||||
func (n *name) nameLen() int {
|
||||
func (n name) nameLen() int {
|
||||
return int(uint16(*n.data(1))<<8 | uint16(*n.data(2)))
|
||||
}
|
||||
|
||||
func (n *name) tagLen() int {
|
||||
func (n name) tagLen() int {
|
||||
if *n.data(0)&(1<<1) == 0 {
|
||||
return 0
|
||||
}
|
||||
@ -444,7 +444,7 @@ func (n *name) tagLen() int {
|
||||
return int(uint16(*n.data(off))<<8 | uint16(*n.data(off + 1)))
|
||||
}
|
||||
|
||||
func (n *name) name() (s string) {
|
||||
func (n name) name() (s string) {
|
||||
if n.bytes == nil {
|
||||
return ""
|
||||
}
|
||||
@ -458,7 +458,7 @@ func (n *name) name() (s string) {
|
||||
return s
|
||||
}
|
||||
|
||||
func (n *name) tag() (s string) {
|
||||
func (n name) tag() (s string) {
|
||||
tl := n.tagLen()
|
||||
if tl == 0 {
|
||||
return ""
|
||||
@ -470,7 +470,7 @@ func (n *name) tag() (s string) {
|
||||
return s
|
||||
}
|
||||
|
||||
func (n *name) pkgPath() string {
|
||||
func (n name) pkgPath() string {
|
||||
if n.bytes == nil || *n.data(0)&(1<<2) == 0 {
|
||||
return ""
|
||||
}
|
||||
@ -480,7 +480,7 @@ func (n *name) pkgPath() string {
|
||||
}
|
||||
var nameOff int32
|
||||
copy((*[4]byte)(unsafe.Pointer(&nameOff))[:], (*[4]byte)(unsafe.Pointer(n.data(off)))[:])
|
||||
pkgPathName := name{(*byte)(resolveTypeOff(unsafe.Pointer(n), nameOff))}
|
||||
pkgPathName := name{(*byte)(resolveTypeOff(unsafe.Pointer(n.bytes), nameOff))}
|
||||
return pkgPathName.name()
|
||||
}
|
||||
|
||||
@ -605,6 +605,11 @@ func (t *uncommonType) PkgPath() string {
|
||||
return t.pkgPath.name()
|
||||
}
|
||||
|
||||
// resolveNameOff resolves a name offset from a base pointer.
|
||||
// The (*rtype).nameOff method is a convenience wrapper for this function.
|
||||
// Implemented in the runtime package.
|
||||
func resolveNameOff(ptrInModule unsafe.Pointer, off int32) unsafe.Pointer
|
||||
|
||||
// resolveTypeOff resolves an *rtype offset from a base type.
|
||||
// The (*rtype).typeOff method is a convenience wrapper for this function.
|
||||
// Implemented in the runtime package.
|
||||
@ -620,6 +625,12 @@ func resolveTextOff(rtype unsafe.Pointer, off int32) unsafe.Pointer
|
||||
// be resolved correctly. Implemented in the runtime package.
|
||||
func addReflectOff(ptr unsafe.Pointer) int32
|
||||
|
||||
// resolveReflectType adds a name to the reflection lookup map in the runtime.
|
||||
// It returns a new nameOff that can be used to refer to the pointer.
|
||||
func resolveReflectName(n name) nameOff {
|
||||
return nameOff(addReflectOff(unsafe.Pointer(n.bytes)))
|
||||
}
|
||||
|
||||
// resolveReflectType adds a *rtype to the reflection lookup map in the runtime.
|
||||
// It returns a new typeOff that can be used to refer to the pointer.
|
||||
func resolveReflectType(t *rtype) typeOff {
|
||||
@ -633,9 +644,17 @@ func resolveReflectText(ptr unsafe.Pointer) textOff {
|
||||
return textOff(addReflectOff(ptr))
|
||||
}
|
||||
|
||||
type nameOff int32 // offset to a name
|
||||
type typeOff int32 // offset to an *rtype
|
||||
type textOff int32 // offset from top of text section
|
||||
|
||||
func (t *rtype) nameOff(off nameOff) name {
|
||||
if off == 0 {
|
||||
return name{}
|
||||
}
|
||||
return name{(*byte)(resolveNameOff(unsafe.Pointer(t), int32(off)))}
|
||||
}
|
||||
|
||||
func (t *rtype) typeOff(off typeOff) *rtype {
|
||||
if off == 0 {
|
||||
return nil
|
||||
@ -753,10 +772,11 @@ func (t *rtype) Method(i int) (m Method) {
|
||||
panic("reflect: Method index out of range")
|
||||
}
|
||||
p := ut.methods()[i]
|
||||
m.Name = p.name.name()
|
||||
pname := t.nameOff(p.name)
|
||||
m.Name = pname.name()
|
||||
fl := flag(Func)
|
||||
if !p.name.isExported() {
|
||||
m.PkgPath = p.name.pkgPath()
|
||||
if !pname.isExported() {
|
||||
m.PkgPath = pname.pkgPath()
|
||||
if m.PkgPath == "" {
|
||||
m.PkgPath = ut.pkgPath.name()
|
||||
}
|
||||
@ -796,7 +816,8 @@ func (t *rtype) MethodByName(name string) (m Method, ok bool) {
|
||||
utmethods := ut.methods()
|
||||
for i := 0; i < int(ut.mcount); i++ {
|
||||
p := utmethods[i]
|
||||
if p.name.name() == name {
|
||||
pname := t.nameOff(p.name)
|
||||
if pname.name() == name {
|
||||
return t.Method(i), true
|
||||
}
|
||||
}
|
||||
@ -1005,14 +1026,15 @@ func (t *interfaceType) Method(i int) (m Method) {
|
||||
return
|
||||
}
|
||||
p := &t.methods[i]
|
||||
m.Name = p.name.name()
|
||||
if !p.name.isExported() {
|
||||
m.PkgPath = p.name.pkgPath()
|
||||
pname := t.nameOff(p.name)
|
||||
m.Name = pname.name()
|
||||
if !pname.isExported() {
|
||||
m.PkgPath = pname.pkgPath()
|
||||
if m.PkgPath == "" {
|
||||
m.PkgPath = t.pkgPath.name()
|
||||
}
|
||||
}
|
||||
m.Type = toType(p.typ)
|
||||
m.Type = toType(t.typeOff(p.typ))
|
||||
m.Index = i
|
||||
return
|
||||
}
|
||||
@ -1028,7 +1050,7 @@ func (t *interfaceType) MethodByName(name string) (m Method, ok bool) {
|
||||
var p *imethod
|
||||
for i := range t.methods {
|
||||
p = &t.methods[i]
|
||||
if p.name.name() == name {
|
||||
if t.nameOff(p.name).name() == name {
|
||||
return t.Method(i), true
|
||||
}
|
||||
}
|
||||
@ -1468,7 +1490,7 @@ func implements(T, V *rtype) bool {
|
||||
for j := 0; j < len(v.methods); j++ {
|
||||
tm := &t.methods[i]
|
||||
vm := &v.methods[j]
|
||||
if vm.name.name() == tm.name.name() && vm.typ == tm.typ {
|
||||
if V.nameOff(vm.name).name() == t.nameOff(tm.name).name() && V.typeOff(vm.typ) == t.typeOff(tm.typ) {
|
||||
if i++; i >= len(t.methods) {
|
||||
return true
|
||||
}
|
||||
@ -1486,7 +1508,7 @@ func implements(T, V *rtype) bool {
|
||||
for j := 0; j < int(v.mcount); j++ {
|
||||
tm := &t.methods[i]
|
||||
vm := vmethods[j]
|
||||
if vm.name.name() == tm.name.name() && V.typeOff(vm.mtyp) == tm.typ {
|
||||
if V.nameOff(vm.name).name() == t.nameOff(tm.name).name() && V.typeOff(vm.mtyp) == t.typeOff(tm.typ) {
|
||||
if i++; i >= len(t.methods) {
|
||||
return true
|
||||
}
|
||||
@ -2327,12 +2349,13 @@ func StructOf(fields []StructField) Type {
|
||||
case Interface:
|
||||
ift := (*interfaceType)(unsafe.Pointer(ft))
|
||||
for im, m := range ift.methods {
|
||||
if m.name.pkgPath() != "" {
|
||||
if ift.nameOff(m.name).pkgPath() != "" {
|
||||
// TODO(sbinet)
|
||||
panic("reflect: embedded interface with unexported method(s) not implemented")
|
||||
}
|
||||
|
||||
var (
|
||||
mtyp = ift.typeOff(m.typ)
|
||||
ifield = i
|
||||
imethod = im
|
||||
ifn Value
|
||||
@ -2340,7 +2363,7 @@ func StructOf(fields []StructField) Type {
|
||||
)
|
||||
|
||||
if ft.kind&kindDirectIface != 0 {
|
||||
tfn = MakeFunc(m.typ, func(in []Value) []Value {
|
||||
tfn = MakeFunc(mtyp, func(in []Value) []Value {
|
||||
var args []Value
|
||||
var recv = in[0]
|
||||
if len(in) > 1 {
|
||||
@ -2348,7 +2371,7 @@ func StructOf(fields []StructField) Type {
|
||||
}
|
||||
return recv.Field(ifield).Method(imethod).Call(args)
|
||||
})
|
||||
ifn = MakeFunc(m.typ, func(in []Value) []Value {
|
||||
ifn = MakeFunc(mtyp, func(in []Value) []Value {
|
||||
var args []Value
|
||||
var recv = in[0]
|
||||
if len(in) > 1 {
|
||||
@ -2357,7 +2380,7 @@ func StructOf(fields []StructField) Type {
|
||||
return recv.Field(ifield).Method(imethod).Call(args)
|
||||
})
|
||||
} else {
|
||||
tfn = MakeFunc(m.typ, func(in []Value) []Value {
|
||||
tfn = MakeFunc(mtyp, func(in []Value) []Value {
|
||||
var args []Value
|
||||
var recv = in[0]
|
||||
if len(in) > 1 {
|
||||
@ -2365,7 +2388,7 @@ func StructOf(fields []StructField) Type {
|
||||
}
|
||||
return recv.Field(ifield).Method(imethod).Call(args)
|
||||
})
|
||||
ifn = MakeFunc(m.typ, func(in []Value) []Value {
|
||||
ifn = MakeFunc(mtyp, func(in []Value) []Value {
|
||||
var args []Value
|
||||
var recv = Indirect(in[0])
|
||||
if len(in) > 1 {
|
||||
@ -2376,8 +2399,8 @@ func StructOf(fields []StructField) Type {
|
||||
}
|
||||
|
||||
methods = append(methods, method{
|
||||
name: m.name,
|
||||
mtyp: resolveReflectType(m.typ),
|
||||
name: resolveReflectName(ift.nameOff(m.name)),
|
||||
mtyp: resolveReflectType(mtyp),
|
||||
ifn: resolveReflectText(unsafe.Pointer(&ifn)),
|
||||
tfn: resolveReflectText(unsafe.Pointer(&tfn)),
|
||||
})
|
||||
@ -2386,12 +2409,13 @@ func StructOf(fields []StructField) Type {
|
||||
ptr := (*ptrType)(unsafe.Pointer(ft))
|
||||
if unt := ptr.uncommon(); unt != nil {
|
||||
for _, m := range unt.methods() {
|
||||
if m.name.pkgPath() != "" {
|
||||
mname := ptr.nameOff(m.name)
|
||||
if mname.pkgPath() != "" {
|
||||
// TODO(sbinet)
|
||||
panic("reflect: embedded interface with unexported method(s) not implemented")
|
||||
}
|
||||
methods = append(methods, method{
|
||||
name: m.name,
|
||||
name: resolveReflectName(mname),
|
||||
mtyp: resolveReflectType(ptr.typeOff(m.mtyp)),
|
||||
ifn: resolveReflectText(ptr.textOff(m.ifn)),
|
||||
tfn: resolveReflectText(ptr.textOff(m.tfn)),
|
||||
@ -2400,12 +2424,13 @@ func StructOf(fields []StructField) Type {
|
||||
}
|
||||
if unt := ptr.elem.uncommon(); unt != nil {
|
||||
for _, m := range unt.methods() {
|
||||
if m.name.pkgPath() != "" {
|
||||
mname := ptr.nameOff(m.name)
|
||||
if mname.pkgPath() != "" {
|
||||
// TODO(sbinet)
|
||||
panic("reflect: embedded interface with unexported method(s) not implemented")
|
||||
}
|
||||
methods = append(methods, method{
|
||||
name: m.name,
|
||||
name: resolveReflectName(mname),
|
||||
mtyp: resolveReflectType(ptr.elem.typeOff(m.mtyp)),
|
||||
ifn: resolveReflectText(ptr.elem.textOff(m.ifn)),
|
||||
tfn: resolveReflectText(ptr.elem.textOff(m.tfn)),
|
||||
@ -2415,12 +2440,13 @@ func StructOf(fields []StructField) Type {
|
||||
default:
|
||||
if unt := ft.uncommon(); unt != nil {
|
||||
for _, m := range unt.methods() {
|
||||
if m.name.pkgPath() != "" {
|
||||
mname := ft.nameOff(m.name)
|
||||
if mname.pkgPath() != "" {
|
||||
// TODO(sbinet)
|
||||
panic("reflect: embedded interface with unexported method(s) not implemented")
|
||||
}
|
||||
methods = append(methods, method{
|
||||
name: m.name,
|
||||
name: resolveReflectName(mname),
|
||||
mtyp: resolveReflectType(ft.typeOff(m.mtyp)),
|
||||
ifn: resolveReflectText(ft.textOff(m.ifn)),
|
||||
tfn: resolveReflectText(ft.textOff(m.tfn)),
|
||||
|
@ -553,7 +553,7 @@ func methodReceiver(op string, v Value, methodIndex int) (rcvrtype, t *rtype, fn
|
||||
panic("reflect: internal error: invalid method index")
|
||||
}
|
||||
m := &tt.methods[i]
|
||||
if !m.name.isExported() {
|
||||
if !tt.nameOff(m.name).isExported() {
|
||||
panic("reflect: " + op + " of unexported method")
|
||||
}
|
||||
iface := (*nonEmptyInterface)(v.ptr)
|
||||
@ -562,7 +562,7 @@ func methodReceiver(op string, v Value, methodIndex int) (rcvrtype, t *rtype, fn
|
||||
}
|
||||
rcvrtype = iface.itab.typ
|
||||
fn = unsafe.Pointer(&iface.itab.fun[i])
|
||||
t = m.typ
|
||||
t = tt.typeOff(m.typ)
|
||||
} else {
|
||||
rcvrtype = v.typ
|
||||
ut := v.typ.uncommon()
|
||||
@ -570,7 +570,7 @@ func methodReceiver(op string, v Value, methodIndex int) (rcvrtype, t *rtype, fn
|
||||
panic("reflect: internal error: invalid method index")
|
||||
}
|
||||
m := ut.methods()[i]
|
||||
if !m.name.isExported() {
|
||||
if !v.typ.nameOff(m.name).isExported() {
|
||||
panic("reflect: " + op + " of unexported method")
|
||||
}
|
||||
ifn := v.typ.textOff(m.ifn)
|
||||
@ -1684,7 +1684,7 @@ func (v Value) Type() Type {
|
||||
panic("reflect: internal error: invalid method index")
|
||||
}
|
||||
m := &tt.methods[i]
|
||||
return m.typ
|
||||
return v.typ.typeOff(m.typ)
|
||||
}
|
||||
// Method on concrete type.
|
||||
ut := v.typ.uncommon()
|
||||
|
@ -37,7 +37,8 @@ func getitab(inter *interfacetype, typ *_type, canfail bool) *itab {
|
||||
if canfail {
|
||||
return nil
|
||||
}
|
||||
panic(&TypeAssertionError{"", typ._string, inter.typ._string, inter.mhdr[0].name.name()})
|
||||
name := inter.typ.nameOff(inter.mhdr[0].name)
|
||||
panic(&TypeAssertionError{"", typ._string, inter.typ._string, name.name()})
|
||||
}
|
||||
|
||||
h := itabhash(inter, typ)
|
||||
@ -98,20 +99,22 @@ func additab(m *itab, locked, canfail bool) {
|
||||
j := 0
|
||||
for k := 0; k < ni; k++ {
|
||||
i := &inter.mhdr[k]
|
||||
iname := i.name.name()
|
||||
itype := i._type
|
||||
ipkg := i.name.pkgPath()
|
||||
itype := inter.typ.typeOff(i.ityp)
|
||||
name := inter.typ.nameOff(i.name)
|
||||
iname := name.name()
|
||||
ipkg := name.pkgPath()
|
||||
if ipkg == "" {
|
||||
ipkg = inter.pkgpath.name()
|
||||
}
|
||||
for ; j < nt; j++ {
|
||||
t := &xmhdr[j]
|
||||
if typ.typeOff(t.mtyp) == itype && t.name.name() == iname {
|
||||
pkgPath := t.name.pkgPath()
|
||||
tname := typ.nameOff(t.name)
|
||||
if typ.typeOff(t.mtyp) == itype && tname.name() == iname {
|
||||
pkgPath := tname.pkgPath()
|
||||
if pkgPath == "" {
|
||||
pkgPath = x.pkgpath.name()
|
||||
}
|
||||
if t.name.isExported() || pkgPath == ipkg {
|
||||
if tname.isExported() || pkgPath == ipkg {
|
||||
if m != nil {
|
||||
ifn := typ.textOff(t.ifn)
|
||||
*(*unsafe.Pointer)(add(unsafe.Pointer(&m.fun[0]), uintptr(k)*sys.PtrSize)) = ifn
|
||||
|
@ -487,6 +487,12 @@ func reflect_typelinks() ([]unsafe.Pointer, [][]int32) {
|
||||
return sections, ret
|
||||
}
|
||||
|
||||
// reflect_resolveNameOff resolves a name offset from a base pointer.
|
||||
//go:linkname reflect_resolveNameOff reflect.resolveNameOff
|
||||
func reflect_resolveNameOff(ptrInModule unsafe.Pointer, off int32) unsafe.Pointer {
|
||||
return unsafe.Pointer(resolveNameOff(ptrInModule, nameOff(off)).bytes)
|
||||
}
|
||||
|
||||
// reflect_resolveTypeOff resolves an *rtype offset from a base type.
|
||||
//go:linkname reflect_resolveTypeOff reflect.resolveTypeOff
|
||||
func reflect_resolveTypeOff(rtype unsafe.Pointer, off int32) unsafe.Pointer {
|
||||
|
@ -161,11 +161,17 @@ func resolveNameOff(ptrInModule unsafe.Pointer, off nameOff) name {
|
||||
}
|
||||
}
|
||||
if md == nil {
|
||||
println("runtime: nameOff", hex(off), "base", hex(base), "not in ranges:")
|
||||
for next := &firstmoduledata; next != nil; next = next.next {
|
||||
println("\ttypes", hex(next.types), "etypes", hex(next.etypes))
|
||||
lock(&reflectOffs.lock)
|
||||
res, found := reflectOffs.m[int32(off)]
|
||||
unlock(&reflectOffs.lock)
|
||||
if !found {
|
||||
println("runtime: nameOff", hex(off), "base", hex(base), "not in ranges:")
|
||||
for next := &firstmoduledata; next != nil; next = next.next {
|
||||
println("\ttypes", hex(next.types), "etypes", hex(next.etypes))
|
||||
}
|
||||
throw("runtime: name offset base pointer out of range")
|
||||
}
|
||||
throw("runtime: name offset base pointer out of range")
|
||||
return name{(*byte)(res)}
|
||||
}
|
||||
res := md.types + uintptr(off)
|
||||
if res > md.etypes {
|
||||
@ -175,6 +181,10 @@ func resolveNameOff(ptrInModule unsafe.Pointer, off nameOff) name {
|
||||
return name{(*byte)(unsafe.Pointer(res))}
|
||||
}
|
||||
|
||||
func (t *_type) nameOff(off nameOff) name {
|
||||
return resolveNameOff(unsafe.Pointer(t), off)
|
||||
}
|
||||
|
||||
func (t *_type) typeOff(off typeOff) *_type {
|
||||
if off == 0 {
|
||||
return nil
|
||||
@ -269,7 +279,7 @@ type typeOff int32
|
||||
type textOff int32
|
||||
|
||||
type method struct {
|
||||
name name
|
||||
name nameOff
|
||||
mtyp typeOff
|
||||
ifn textOff
|
||||
tfn textOff
|
||||
@ -282,8 +292,8 @@ type uncommontype struct {
|
||||
}
|
||||
|
||||
type imethod struct {
|
||||
name name
|
||||
_type *_type
|
||||
name nameOff
|
||||
ityp typeOff
|
||||
}
|
||||
|
||||
type interfacetype struct {
|
||||
@ -354,19 +364,19 @@ type name struct {
|
||||
bytes *byte
|
||||
}
|
||||
|
||||
func (n *name) data(off int) *byte {
|
||||
func (n name) data(off int) *byte {
|
||||
return (*byte)(add(unsafe.Pointer(n.bytes), uintptr(off)))
|
||||
}
|
||||
|
||||
func (n *name) isExported() bool {
|
||||
func (n name) isExported() bool {
|
||||
return (*n.bytes)&(1<<0) != 0
|
||||
}
|
||||
|
||||
func (n *name) nameLen() int {
|
||||
func (n name) nameLen() int {
|
||||
return int(uint16(*n.data(1))<<8 | uint16(*n.data(2)))
|
||||
}
|
||||
|
||||
func (n *name) tagLen() int {
|
||||
func (n name) tagLen() int {
|
||||
if *n.data(0)&(1<<1) == 0 {
|
||||
return 0
|
||||
}
|
||||
@ -374,7 +384,7 @@ func (n *name) tagLen() int {
|
||||
return int(uint16(*n.data(off))<<8 | uint16(*n.data(off + 1)))
|
||||
}
|
||||
|
||||
func (n *name) name() (s string) {
|
||||
func (n name) name() (s string) {
|
||||
if n.bytes == nil {
|
||||
return ""
|
||||
}
|
||||
@ -388,7 +398,7 @@ func (n *name) name() (s string) {
|
||||
return s
|
||||
}
|
||||
|
||||
func (n *name) tag() (s string) {
|
||||
func (n name) tag() (s string) {
|
||||
tl := n.tagLen()
|
||||
if tl == 0 {
|
||||
return ""
|
||||
@ -400,7 +410,7 @@ func (n *name) tag() (s string) {
|
||||
return s
|
||||
}
|
||||
|
||||
func (n *name) pkgPath() string {
|
||||
func (n name) pkgPath() string {
|
||||
if n.bytes == nil || *n.data(0)&(1<<2) == 0 {
|
||||
return ""
|
||||
}
|
||||
@ -545,13 +555,15 @@ func typesEqual(t, v *_type) bool {
|
||||
for i := range it.mhdr {
|
||||
tm := &it.mhdr[i]
|
||||
vm := &iv.mhdr[i]
|
||||
if tm.name.name() != vm.name.name() {
|
||||
tname := it.typ.nameOff(tm.name)
|
||||
vname := iv.typ.nameOff(vm.name)
|
||||
if tname.name() != vname.name() {
|
||||
return false
|
||||
}
|
||||
if tm.name.pkgPath() != vm.name.pkgPath() {
|
||||
if tname.pkgPath() != vname.pkgPath() {
|
||||
return false
|
||||
}
|
||||
if !typesEqual(tm._type, vm._type) {
|
||||
if !typesEqual(it.typ.typeOff(tm.ityp), iv.typ.typeOff(vm.ityp)) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user