1
0
mirror of https://github.com/golang/go synced 2024-11-23 18:10:04 -07:00

cmd/compile, etc: use name for type pkgPath

By replacing the *string used to represent pkgPath with a
reflect.name everywhere, the embedded *string for package paths
inside the reflect.name can be replaced by an offset, nameOff.
This reduces the number of pointers in the type information.

This also moves all reflect.name types into the same section, making
it possible to use nameOff more widely in later CLs.

No significant binary size change for normal binaries, but:

linux/amd64 PIE:
	cmd/go: -440KB (3.7%)
	jujud:  -2.6MB (3.2%)

For #6853.

Change-Id: I3890b132a784a1090b1b72b32febfe0bea77eaee
Reviewed-on: https://go-review.googlesource.com/21395
Run-TryBot: David Crawshaw <crawshaw@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
This commit is contained in:
David Crawshaw 2016-03-31 10:02:10 -04:00
parent 73e2ad2022
commit f120936dff
7 changed files with 169 additions and 114 deletions

View File

@ -20,7 +20,7 @@ const (
type Pkg struct { type Pkg struct {
Name string // package name, e.g. "sys" Name string // package name, e.g. "sys"
Path string // string literal used in import statement, e.g. "runtime/internal/sys" Path string // string literal used in import statement, e.g. "runtime/internal/sys"
Pathsym *Sym Pathsym *obj.LSym
Prefix string // escaped path for use in symbol table Prefix string // escaped path for use in symbol table
Imported bool // export data of this package was parsed Imported bool // export data of this package was parsed
Exported bool // import line written in export data Exported bool // import line written in export data

View File

@ -412,8 +412,6 @@ func imethods(t *Type) []*Sig {
return methods return methods
} }
var dimportpath_gopkg *Pkg
func dimportpath(p *Pkg) { func dimportpath(p *Pkg) {
if p.Pathsym != nil { if p.Pathsym != nil {
return return
@ -426,27 +424,18 @@ func dimportpath(p *Pkg) {
return return
} }
if dimportpath_gopkg == nil { var str string
dimportpath_gopkg = mkpkg("go")
dimportpath_gopkg.Name = "go"
}
nam := "importpath." + p.Prefix + "."
n := Nod(ONAME, nil, nil)
n.Sym = Pkglookup(nam, dimportpath_gopkg)
n.Class = PEXTERN
n.Xoffset = 0
p.Pathsym = n.Sym
if p == localpkg { if p == localpkg {
// Note: myimportpath != "", or else dgopkgpath won't call dimportpath. // Note: myimportpath != "", or else dgopkgpath won't call dimportpath.
gdatastring(n, myimportpath) str = myimportpath
} else { } else {
gdatastring(n, p.Path) str = p.Path
} }
ggloblsym(n.Sym, int32(Types[TSTRING].Width), obj.DUPOK|obj.RODATA)
s := obj.Linklookup(Ctxt, "go.importpath."+p.Prefix+".", 0)
ot := dnameData(s, 0, str, "", nil, false)
ggloblLSym(s, int32(ot), obj.DUPOK|obj.RODATA)
p.Pathsym = s
} }
func dgopkgpath(s *Sym, ot int, pkg *Pkg) int { func dgopkgpath(s *Sym, ot int, pkg *Pkg) int {
@ -469,7 +458,23 @@ func dgopkgpathLSym(s *obj.LSym, ot int, pkg *Pkg) int {
} }
dimportpath(pkg) dimportpath(pkg)
return dsymptrLSym(s, ot, Linksym(pkg.Pathsym), 0) return dsymptrLSym(s, ot, pkg.Pathsym, 0)
}
// dgopkgpathOffLSym writes an offset relocation in s at offset ot to the pkg path symbol.
func dgopkgpathOffLSym(s *obj.LSym, ot int, pkg *Pkg) int {
if pkg == localpkg && myimportpath == "" {
// If we don't know the full import path of the package being compiled
// (i.e. -p was not passed on the compiler command line), emit a reference to
// go.importpath.""., which the linker will rewrite using the correct import path.
// Every package that imports this one directly defines the symbol.
// See also https://groups.google.com/forum/#!topic/golang-dev/myb9s53HxGQ.
ns := obj.Linklookup(Ctxt, `go.importpath."".`, 0)
return dsymptrOffLSym(s, ot, ns, 0)
}
dimportpath(pkg)
return dsymptrOffLSym(s, ot, pkg.Pathsym, 0)
} }
// isExportedField reports whether a struct field is exported. // isExportedField reports whether a struct field is exported.
@ -495,13 +500,12 @@ func dnameField(s *Sym, ot int, ft *Field) int {
if ft.Note != nil { if ft.Note != nil {
tag = *ft.Note tag = *ft.Note
} }
return dname(s, ot, name, tag, nil, isExportedField(ft)) nsym := dname(name, tag, nil, isExportedField(ft))
return dsymptrLSym(Linksym(s), ot, nsym, 0)
} }
var dnameCount int // dnameData writes the contents of a reflect.name into s at offset ot.
func dnameData(s *obj.LSym, ot int, name, tag string, pkg *Pkg, exported bool) int {
// dname dumps a reflect.name for a struct field or method.
func dname(s *Sym, ot int, name, tag string, pkg *Pkg, exported bool) int {
if len(name) > 1<<16-1 { if len(name) > 1<<16-1 {
Fatalf("name too long: %s", name) Fatalf("name too long: %s", name)
} }
@ -534,33 +538,48 @@ func dname(s *Sym, ot int, name, tag string, pkg *Pkg, exported bool) int {
copy(tb[2:], tag) copy(tb[2:], tag)
} }
// Very few names require a pkgPath *string (only those ot = int(s.WriteBytes(Ctxt, int64(ot), b))
// defined in a different package than their type). So if
// there is no pkgPath, we treat the name contents as string if pkg != nil {
// data that duplicates across packages. ot = dgopkgpathOffLSym(s, ot, pkg)
var bsym *obj.LSym
if pkg == nil {
_, bsym = stringsym(string(b))
} else {
// Write out data as "type.." to signal two things to the
// linker, first that when dynamically linking, the symbol
// should be moved to a relro section, and second that the
// contents should not be decoded as a type.
bsymname := fmt.Sprintf(`type..methodname."".%d`, dnameCount)
dnameCount++
bsym = obj.Linklookup(Ctxt, bsymname, 0)
bsym.P = b
boff := len(b)
boff = int(Rnd(int64(boff), int64(Widthptr)))
boff = dgopkgpathLSym(bsym, boff, pkg)
ggloblLSym(bsym, int32(boff), obj.RODATA|obj.LOCAL)
} }
ot = dsymptrLSym(Linksym(s), ot, bsym, 0)
return ot return ot
} }
var dnameCount int
// dname creates a reflect.name for a struct field or method.
func dname(name, tag string, pkg *Pkg, exported bool) *obj.LSym {
// Write out data as "type.." to signal two things to the
// linker, first that when dynamically linking, the symbol
// should be moved to a relro section, and second that the
// contents should not be decoded as a type.
sname := "type..namedata."
if pkg == nil {
// In the common case, share data with other packages.
if name == "" {
if exported {
sname += "-noname-exported." + tag
} else {
sname += "-noname-unexported." + tag
}
} else {
sname += name + "." + tag
}
} else {
sname = fmt.Sprintf(`%s"".%d`, sname, dnameCount)
dnameCount++
}
s := obj.Linklookup(Ctxt, sname, 0)
if len(s.P) > 0 {
return s
}
ot := dnameData(s, 0, name, tag, pkg, exported)
ggloblLSym(s, int32(ot), obj.DUPOK|obj.RODATA)
return s
}
// dextratype dumps the fields of a runtime.uncommontype. // dextratype dumps the fields of a runtime.uncommontype.
// dataAdd is the offset in bytes after the header where the // dataAdd is the offset in bytes after the header where the
// backing array of the []method field is written (by dextratypeData). // backing array of the []method field is written (by dextratypeData).
@ -627,7 +646,8 @@ func dextratypeData(s *Sym, ot int, t *Type) int {
if !exported && a.pkg != typePkg(t) { if !exported && a.pkg != typePkg(t) {
pkg = a.pkg pkg = a.pkg
} }
ot = dname(s, ot, a.name, "", pkg, exported) nsym := dname(a.name, "", pkg, exported)
ot = dsymptrLSym(lsym, ot, nsym, 0)
ot = dmethodptrOffLSym(lsym, ot, Linksym(dtypesym(a.mtype))) ot = dmethodptrOffLSym(lsym, ot, Linksym(dtypesym(a.mtype)))
ot = dmethodptrOffLSym(lsym, ot, Linksym(a.isym)) ot = dmethodptrOffLSym(lsym, ot, Linksym(a.isym))
ot = dmethodptrOffLSym(lsym, ot, Linksym(a.tsym)) ot = dmethodptrOffLSym(lsym, ot, Linksym(a.tsym))
@ -1213,7 +1233,8 @@ ok:
if !exported && a.pkg != tpkg { if !exported && a.pkg != tpkg {
pkg = a.pkg pkg = a.pkg
} }
ot = dname(s, ot, a.name, "", pkg, exported) nsym := dname(a.name, "", pkg, exported)
ot = dsymptrLSym(Linksym(s), ot, nsym, 0)
ot = dsymptr(s, ot, dtypesym(a.type_), 0) ot = dsymptr(s, ot, dtypesym(a.type_), 0)
} }

View File

@ -75,7 +75,11 @@ func (s *LSym) prepwrite(ctxt *Link, off int64, siz int) {
if s.Type == SBSS || s.Type == STLSBSS { if s.Type == SBSS || s.Type == STLSBSS {
ctxt.Diag("cannot supply data for BSS var") ctxt.Diag("cannot supply data for BSS var")
} }
s.Grow(off + int64(siz)) l := off + int64(siz)
s.Grow(l)
if l > s.Size {
s.Size = l
}
} }
// WriteFloat32 writes f into s at offset off. // WriteFloat32 writes f into s at offset off.
@ -150,6 +154,13 @@ func (s *LSym) WriteString(ctxt *Link, off int64, siz int, str string) {
copy(s.P[off:off+int64(siz)], str) copy(s.P[off:off+int64(siz)], str)
} }
// WriteBytes writes a slice of bytes into s at offset off.
func (s *LSym) WriteBytes(ctxt *Link, off int64, b []byte) int64 {
s.prepwrite(ctxt, off, len(b))
copy(s.P[off:], b)
return off + int64(len(b))
}
func Addrel(s *LSym) *Reloc { func Addrel(s *LSym) *Reloc {
s.R = append(s.R, Reloc{}) s.R = append(s.R, Reloc{})
return &s.R[len(s.R)-1] return &s.R[len(s.R)-1]

View File

@ -299,9 +299,9 @@ type method struct {
// Using a pointer to this struct reduces the overall size required // Using a pointer to this struct reduces the overall size required
// to describe an unnamed type with no methods. // to describe an unnamed type with no methods.
type uncommonType struct { type uncommonType struct {
pkgPath *string // import path; nil for built-in types like int, string pkgPath name // import path; empty for built-in types like int, string
mcount uint16 // number of methods mcount uint16 // number of methods
moff uint16 // offset from this uncommontype to [mcount]method moff uint16 // offset from this uncommontype to [mcount]method
} }
// ChanDir represents a channel type's direction. // ChanDir represents a channel type's direction.
@ -354,7 +354,7 @@ type imethod struct {
// interfaceType represents an interface type. // interfaceType represents an interface type.
type interfaceType struct { type interfaceType struct {
rtype `reflect:"interface"` rtype `reflect:"interface"`
pkgPath *string // import path pkgPath name // import path
methods []imethod // sorted by hash methods []imethod // sorted by hash
} }
@ -396,7 +396,7 @@ type structField struct {
// structType represents a struct type. // structType represents a struct type.
type structType struct { type structType struct {
rtype `reflect:"struct"` rtype `reflect:"struct"`
pkgPath *string pkgPath name
fields []structField // sorted by offset fields []structField // sorted by offset
} }
@ -406,7 +406,7 @@ type structType struct {
// //
// 1<<0 the name is exported // 1<<0 the name is exported
// 1<<1 tag data follows the name // 1<<1 tag data follows the name
// 1<<2 pkgPath *string follow the name and tag // 1<<2 pkgPath nameOff follows the name and tag
// //
// The next two bytes are the data length: // The next two bytes are the data length:
// //
@ -417,10 +417,9 @@ type structType struct {
// If tag data follows then bytes 3+l and 3+l+1 are the tag length, // If tag data follows then bytes 3+l and 3+l+1 are the tag length,
// with the data following. // with the data following.
// //
// If the import path follows, then ptrSize bytes at the end of // If the import path follows, then 4 bytes at the end of
// the data form a *string. The pointer is aligned to its width. // the data form a nameOff. The import path is only set for concrete
// The import path is only set for concrete methods that are defined // methods that are defined in a different package than their type.
// in a different package than their type.
type name struct { type name struct {
bytes *byte bytes *byte
} }
@ -446,6 +445,9 @@ func (n *name) tagLen() int {
} }
func (n *name) name() (s string) { func (n *name) name() (s string) {
if n.bytes == nil {
return ""
}
nl := n.nameLen() nl := n.nameLen()
if nl == 0 { if nl == 0 {
return "" return ""
@ -468,16 +470,18 @@ func (n *name) tag() (s string) {
return s return s
} }
func (n *name) pkgPath() *string { func (n *name) pkgPath() string {
if *n.data(0)&(1<<2) == 0 { if n.bytes == nil || *n.data(0)&(1<<2) == 0 {
return nil return ""
} }
off := 3 + n.nameLen() off := 3 + n.nameLen()
if tl := n.tagLen(); tl > 0 { if tl := n.tagLen(); tl > 0 {
off += 2 + tl off += 2 + tl
} }
off = int(round(uintptr(off), ptrSize)) var nameOff int32
return *(**string)(unsafe.Pointer(n.data(off))) copy((*[4]byte)(unsafe.Pointer(&nameOff))[:], (*[4]byte)(unsafe.Pointer(n.data(off)))[:])
pkgPathName := name{(*byte)(resolveTypeOff(unsafe.Pointer(n), nameOff))}
return pkgPathName.name()
} }
// round n up to a multiple of a. a must be a power of 2. // round n up to a multiple of a. a must be a power of 2.
@ -595,10 +599,10 @@ func (t *uncommonType) methods() []method {
} }
func (t *uncommonType) PkgPath() string { func (t *uncommonType) PkgPath() string {
if t == nil || t.pkgPath == nil { if t == nil {
return "" return ""
} }
return *t.pkgPath return t.pkgPath.name()
} }
// resolveTypeOff resolves an *rtype offset from a base type. // resolveTypeOff resolves an *rtype offset from a base type.
@ -752,11 +756,10 @@ func (t *rtype) Method(i int) (m Method) {
m.Name = p.name.name() m.Name = p.name.name()
fl := flag(Func) fl := flag(Func)
if !p.name.isExported() { if !p.name.isExported() {
pkgPath := p.name.pkgPath() m.PkgPath = p.name.pkgPath()
if pkgPath == nil { if m.PkgPath == "" {
pkgPath = ut.pkgPath m.PkgPath = ut.pkgPath.name()
} }
m.PkgPath = *pkgPath
fl |= flagStickyRO fl |= flagStickyRO
} }
if p.mtyp != 0 { if p.mtyp != 0 {
@ -1004,11 +1007,10 @@ func (t *interfaceType) Method(i int) (m Method) {
p := &t.methods[i] p := &t.methods[i]
m.Name = p.name.name() m.Name = p.name.name()
if !p.name.isExported() { if !p.name.isExported() {
pkgPath := p.name.pkgPath() m.PkgPath = p.name.pkgPath()
if pkgPath == nil { if m.PkgPath == "" {
pkgPath = t.pkgPath m.PkgPath = t.pkgPath.name()
} }
m.PkgPath = *pkgPath
} }
m.Type = toType(p.typ) m.Type = toType(p.typ)
m.Index = i m.Index = i
@ -1146,9 +1148,9 @@ func (t *structType) Field(i int) (f StructField) {
f.Name = t.Name() f.Name = t.Name()
f.Anonymous = true f.Anonymous = true
} }
if t.pkgPath != nil && !p.name.isExported() { if !p.name.isExported() {
// Fields never have an import path in their name. // Fields never have an import path in their name.
f.PkgPath = *t.pkgPath f.PkgPath = t.pkgPath.name()
} }
if tag := p.name.tag(); tag != "" { if tag := p.name.tag(); tag != "" {
f.Tag = StructTag(tag) f.Tag = StructTag(tag)
@ -2325,7 +2327,7 @@ func StructOf(fields []StructField) Type {
case Interface: case Interface:
ift := (*interfaceType)(unsafe.Pointer(ft)) ift := (*interfaceType)(unsafe.Pointer(ft))
for im, m := range ift.methods { for im, m := range ift.methods {
if m.name.pkgPath() != nil { if m.name.pkgPath() != "" {
// TODO(sbinet) // TODO(sbinet)
panic("reflect: embedded interface with unexported method(s) not implemented") panic("reflect: embedded interface with unexported method(s) not implemented")
} }
@ -2384,7 +2386,7 @@ func StructOf(fields []StructField) Type {
ptr := (*ptrType)(unsafe.Pointer(ft)) ptr := (*ptrType)(unsafe.Pointer(ft))
if unt := ptr.uncommon(); unt != nil { if unt := ptr.uncommon(); unt != nil {
for _, m := range unt.methods() { for _, m := range unt.methods() {
if m.name.pkgPath() != nil { if m.name.pkgPath() != "" {
// TODO(sbinet) // TODO(sbinet)
panic("reflect: embedded interface with unexported method(s) not implemented") panic("reflect: embedded interface with unexported method(s) not implemented")
} }
@ -2398,7 +2400,7 @@ func StructOf(fields []StructField) Type {
} }
if unt := ptr.elem.uncommon(); unt != nil { if unt := ptr.elem.uncommon(); unt != nil {
for _, m := range unt.methods() { for _, m := range unt.methods() {
if m.name.pkgPath() != nil { if m.name.pkgPath() != "" {
// TODO(sbinet) // TODO(sbinet)
panic("reflect: embedded interface with unexported method(s) not implemented") panic("reflect: embedded interface with unexported method(s) not implemented")
} }
@ -2413,7 +2415,7 @@ func StructOf(fields []StructField) Type {
default: default:
if unt := ft.uncommon(); unt != nil { if unt := ft.uncommon(); unt != nil {
for _, m := range unt.methods() { for _, m := range unt.methods() {
if m.name.pkgPath() != nil { if m.name.pkgPath() != "" {
// TODO(sbinet) // TODO(sbinet)
panic("reflect: embedded interface with unexported method(s) not implemented") panic("reflect: embedded interface with unexported method(s) not implemented")
} }

View File

@ -183,10 +183,11 @@ func dumptype(t *_type) {
dumpint(tagType) dumpint(tagType)
dumpint(uint64(uintptr(unsafe.Pointer(t)))) dumpint(uint64(uintptr(unsafe.Pointer(t))))
dumpint(uint64(t.size)) dumpint(uint64(t.size))
if x := t.uncommon(); x == nil || x.pkgpath == nil { if x := t.uncommon(); x == nil || x.pkgpath.name() == "" {
dumpstr(t._string) dumpstr(t._string)
} else { } else {
pkgpath := stringStructOf(x.pkgpath) pkgpathstr := x.pkgpath.name()
pkgpath := stringStructOf(&pkgpathstr)
namestr := t.name() namestr := t.name()
name := stringStructOf(&namestr) name := stringStructOf(&namestr)
dumpint(uint64(uintptr(pkgpath.len) + 1 + uintptr(name.len))) dumpint(uint64(uintptr(pkgpath.len) + 1 + uintptr(name.len)))

View File

@ -101,15 +101,15 @@ func additab(m *itab, locked, canfail bool) {
iname := i.name.name() iname := i.name.name()
itype := i._type itype := i._type
ipkg := i.name.pkgPath() ipkg := i.name.pkgPath()
if ipkg == nil { if ipkg == "" {
ipkg = inter.pkgpath ipkg = inter.pkgpath.name()
} }
for ; j < nt; j++ { for ; j < nt; j++ {
t := &xmhdr[j] t := &xmhdr[j]
if typ.typeOff(t.mtyp) == itype && t.name.name() == iname { if typ.typeOff(t.mtyp) == itype && t.name.name() == iname {
pkgPath := t.name.pkgPath() pkgPath := t.name.pkgPath()
if pkgPath == nil { if pkgPath == "" {
pkgPath = x.pkgpath pkgPath = x.pkgpath.name()
} }
if t.name.isExported() || pkgPath == ipkg { if t.name.isExported() || pkgPath == ipkg {
if m != nil { if m != nil {

View File

@ -6,10 +6,7 @@
package runtime package runtime
import ( import "unsafe"
"runtime/internal/sys"
"unsafe"
)
// tflag is documented in ../reflect/type.go. // tflag is documented in ../reflect/type.go.
type tflag uint8 type tflag uint8
@ -151,6 +148,33 @@ var reflectOffs struct {
minv map[unsafe.Pointer]int32 minv map[unsafe.Pointer]int32
} }
func resolveNameOff(ptrInModule unsafe.Pointer, off nameOff) name {
if off == 0 {
return name{}
}
base := uintptr(ptrInModule)
var md *moduledata
for next := &firstmoduledata; next != nil; next = next.next {
if base >= next.types && base < next.etypes {
md = next
break
}
}
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))
}
throw("runtime: name offset base pointer out of range")
}
res := md.types + uintptr(off)
if res > md.etypes {
println("runtime: nameOff", hex(off), "out of range", hex(md.types), "-", hex(md.etypes))
throw("runtime: name offset out of range")
}
return name{(*byte)(unsafe.Pointer(res))}
}
func (t *_type) typeOff(off typeOff) *_type { func (t *_type) typeOff(off typeOff) *_type {
if off == 0 { if off == 0 {
return nil return nil
@ -240,6 +264,7 @@ func (t *functype) dotdotdot() bool {
return t.outCount&(1<<15) != 0 return t.outCount&(1<<15) != 0
} }
type nameOff int32
type typeOff int32 type typeOff int32
type textOff int32 type textOff int32
@ -251,7 +276,7 @@ type method struct {
} }
type uncommontype struct { type uncommontype struct {
pkgpath *string pkgpath name
mcount uint16 // number of methods mcount uint16 // number of methods
moff uint16 // offset from this uncommontype to [mcount]method moff uint16 // offset from this uncommontype to [mcount]method
} }
@ -263,7 +288,7 @@ type imethod struct {
type interfacetype struct { type interfacetype struct {
typ _type typ _type
pkgpath *string pkgpath name
mhdr []imethod mhdr []imethod
} }
@ -319,7 +344,7 @@ type structfield struct {
type structtype struct { type structtype struct {
typ _type typ _type
pkgPath *string pkgPath name
fields []structfield fields []structfield
} }
@ -350,6 +375,9 @@ func (n *name) tagLen() int {
} }
func (n *name) name() (s string) { func (n *name) name() (s string) {
if n.bytes == nil {
return ""
}
nl := n.nameLen() nl := n.nameLen()
if nl == 0 { if nl == 0 {
return "" return ""
@ -372,16 +400,18 @@ func (n *name) tag() (s string) {
return s return s
} }
func (n *name) pkgPath() *string { func (n *name) pkgPath() string {
if *n.data(0)&(1<<2) == 0 { if n.bytes == nil || *n.data(0)&(1<<2) == 0 {
return nil return ""
} }
off := 3 + n.nameLen() off := 3 + n.nameLen()
if tl := n.tagLen(); tl > 0 { if tl := n.tagLen(); tl > 0 {
off += 2 + tl off += 2 + tl
} }
off = int(round(uintptr(off), sys.PtrSize)) var nameOff nameOff
return *(**string)(unsafe.Pointer(n.data(off))) copy((*[4]byte)(unsafe.Pointer(&nameOff))[:], (*[4]byte)(unsafe.Pointer(n.data(off)))[:])
pkgPathName := resolveNameOff(unsafe.Pointer(n.bytes), nameOff)
return pkgPathName.name()
} }
// typelinksinit scans the types from extra modules and builds the // typelinksinit scans the types from extra modules and builds the
@ -466,7 +496,7 @@ func typesEqual(t, v *_type) bool {
if ut == nil || uv == nil { if ut == nil || uv == nil {
return false return false
} }
if !pkgPathEqual(ut.pkgpath, uv.pkgpath) { if ut.pkgpath.name() != uv.pkgpath.name() {
return false return false
} }
} }
@ -506,7 +536,7 @@ func typesEqual(t, v *_type) bool {
case kindInterface: case kindInterface:
it := (*interfacetype)(unsafe.Pointer(t)) it := (*interfacetype)(unsafe.Pointer(t))
iv := (*interfacetype)(unsafe.Pointer(v)) iv := (*interfacetype)(unsafe.Pointer(v))
if !pkgPathEqual(it.pkgpath, iv.pkgpath) { if it.pkgpath.name() != iv.pkgpath.name() {
return false return false
} }
if len(it.mhdr) != len(iv.mhdr) { if len(it.mhdr) != len(iv.mhdr) {
@ -518,7 +548,7 @@ func typesEqual(t, v *_type) bool {
if tm.name.name() != vm.name.name() { if tm.name.name() != vm.name.name() {
return false return false
} }
if !pkgPathEqual(tm.name.pkgPath(), vm.name.pkgPath()) { if tm.name.pkgPath() != vm.name.pkgPath() {
return false return false
} }
if !typesEqual(tm._type, vm._type) { if !typesEqual(tm._type, vm._type) {
@ -550,7 +580,7 @@ func typesEqual(t, v *_type) bool {
if tf.name.name() != vf.name.name() { if tf.name.name() != vf.name.name() {
return false return false
} }
if !pkgPathEqual(tf.name.pkgPath(), vf.name.pkgPath()) { if tf.name.pkgPath() != vf.name.pkgPath() {
return false return false
} }
if !typesEqual(tf.typ, vf.typ) { if !typesEqual(tf.typ, vf.typ) {
@ -570,13 +600,3 @@ func typesEqual(t, v *_type) bool {
return false return false
} }
} }
func pkgPathEqual(p, q *string) bool {
if p == q {
return true
}
if p == nil || q == nil {
return false
}
return *p == *q
}