]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/compile, etc: use name offset in method tables
authorDavid Crawshaw <crawshaw@golang.org>
Tue, 29 Mar 2016 01:51:10 +0000 (21:51 -0400)
committerDavid Crawshaw <crawshaw@golang.org>
Mon, 18 Apr 2016 09:12:41 +0000 (09:12 +0000)
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>
src/cmd/compile/internal/gc/reflect.go
src/cmd/link/internal/ld/decodesym.go
src/cmd/link/internal/ld/symtab.go
src/reflect/export_test.go
src/reflect/type.go
src/reflect/value.go
src/runtime/iface.go
src/runtime/runtime1.go
src/runtime/type.go

index b8b9369f3786da68f0d3f8bd1dca735833a711d1..f782ce097488556f77431a9cf5f007fca64b4767 100644 (file)
@@ -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
index 4725b91d01bf2503c6448a8b284543c29cc797ea..5eb20c2fb2241fd5dceed98928d33d2f3b0dfb8b 100644 (file)
@@ -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)
 }
index 96e8de5030640ec21a2674cdd358d2a5a373e798..1f07a4eb77b63f26cc64f2763978c4a63068fce9 100644 (file)
@@ -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 {
index 2769e0db40a51f06c9f49214babef739e803cc2a..f527434f0db869a4fccc1359cb1bcfe05ad1e698 100644 (file)
@@ -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 {
index b8c778cc2b6382cd71b3641a332c89e234dd41fe..0cae69a79cee31ca9acd93eeec459ab0227ae967 100644 (file)
@@ -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)),
index d4d317436a423cc5eabf7e50fa309068e3ff58f5..e6b846e5d1003886ae9847693025ea9ce122c974 100644 (file)
@@ -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()
index 84f0ee8f0c89fbdbc04d6ee9d31ff948bf3a0ee8..8f179bac802894b7ca6ca7e169a376c2494fb4af 100644 (file)
@@ -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
index 02aeedaf75ee2ac61e7362859476d982f4a6053e..90893839045119621a87e2c1981931e8befc5032 100644 (file)
@@ -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 {
index 711753bab54511f7a46f601bb072a8dcbe40bbf8..31f7ff81b8afe93287bc8651d01dd92b4118fa3f 100644 (file)
@@ -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
                        }
                }