]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/compile: remove rtype.ptrToThis
authorDavid Crawshaw <crawshaw@golang.org>
Thu, 18 Feb 2016 11:31:57 +0000 (06:31 -0500)
committerDavid Crawshaw <crawshaw@golang.org>
Thu, 25 Feb 2016 17:47:42 +0000 (17:47 +0000)
Simplifies some code as ptrToThis was unreliable under dynamic
linking. Now the same type lookup is used regardless of execution
mode.

A synthetic relocation, R_USETYPE, is introduced to make sure the
linker includes *T on use of T, if *T is carrying methods.

Changes the heap dump format. Anything reading the format needs to
look at the last bool of a type of an interface value to determine
if the type should be the pointer-to type.

Reduces binary size of cmd/go by 0.2%.
For #6853.

Change-Id: I79fcb19a97402bdb0193f3c7f6d94ddf061ee7b2
Reviewed-on: https://go-review.googlesource.com/19695
Reviewed-by: Keith Randall <khr@golang.org>
Run-TryBot: David Crawshaw <crawshaw@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>

src/cmd/compile/internal/gc/reflect.go
src/cmd/internal/obj/link.go
src/cmd/link/internal/ld/decodesym.go
src/reflect/type.go
src/runtime/heapdump.go
src/runtime/type.go

index d2f00d0a054b5126359cb647170105277e58873d..4fdbbd6967fe7cadbcac1234bb47559193b46abc 100644 (file)
@@ -701,12 +701,14 @@ func dcommontype(s *Sym, ot int, t *Type) int {
                algsym = dalgsym(t)
        }
 
-       var sptr *Sym
        tptr := Ptrto(t)
        if !Isptr[t.Etype] && (t.Sym != nil || methods(tptr) != nil) {
-               sptr = dtypesym(tptr)
-       } else {
-               sptr = weaktypesym(tptr)
+               sptr := dtypesym(tptr)
+               r := obj.Addrel(Linksym(s))
+               r.Off = 0
+               r.Siz = 0
+               r.Sym = sptr.Lsym
+               r.Type = obj.R_USETYPE
        }
 
        gcsym, useGCProg, ptrdata := dgcsym(t)
@@ -725,7 +727,6 @@ func dcommontype(s *Sym, ot int, t *Type) int {
        //              gcdata        *byte
        //              string        *string
        //              *uncommonType
-       //              ptrToThis     *rtype
        //      }
        ot = duintptr(s, ot, uint64(t.Width))
        ot = duintptr(s, ot, uint64(ptrdata))
@@ -779,7 +780,6 @@ func dcommontype(s *Sym, ot int, t *Type) int {
        // otherwise linker will assume 0.
        ot += Widthptr
 
-       ot = dsymptr(s, ot, sptr, 0) // ptrto type
        return ot
 }
 
@@ -1009,7 +1009,7 @@ ok:
        switch t.Etype {
        default:
                ot = dcommontype(s, ot, t)
-               xt = ot - 2*Widthptr
+               xt = ot - 1*Widthptr
 
        case TARRAY:
                if t.Bound >= 0 {
@@ -1021,7 +1021,7 @@ ok:
                        t2.Bound = -1 // slice
                        s2 := dtypesym(t2)
                        ot = dcommontype(s, ot, t)
-                       xt = ot - 2*Widthptr
+                       xt = ot - 1*Widthptr
                        ot = dsymptr(s, ot, s1, 0)
                        ot = dsymptr(s, ot, s2, 0)
                        ot = duintptr(s, ot, uint64(t.Bound))
@@ -1030,7 +1030,7 @@ ok:
                        s1 := dtypesym(t.Type)
 
                        ot = dcommontype(s, ot, t)
-                       xt = ot - 2*Widthptr
+                       xt = ot - 1*Widthptr
                        ot = dsymptr(s, ot, s1, 0)
                }
 
@@ -1039,7 +1039,7 @@ ok:
                s1 := dtypesym(t.Type)
 
                ot = dcommontype(s, ot, t)
-               xt = ot - 2*Widthptr
+               xt = ot - 1*Widthptr
                ot = dsymptr(s, ot, s1, 0)
                ot = duintptr(s, ot, uint64(t.Chan))
 
@@ -1058,7 +1058,7 @@ ok:
                }
 
                ot = dcommontype(s, ot, t)
-               xt = ot - 2*Widthptr
+               xt = ot - 1*Widthptr
                ot = duint8(s, ot, uint8(obj.Bool2int(isddd)))
 
                // two slice headers: in and out.
@@ -1096,7 +1096,7 @@ ok:
                // ../../../../runtime/type.go:/interfaceType
                ot = dcommontype(s, ot, t)
 
-               xt = ot - 2*Widthptr
+               xt = ot - 1*Widthptr
                ot = dsymptr(s, ot, s, ot+Widthptr+2*Widthint)
                ot = duintxx(s, ot, uint64(n), Widthint)
                ot = duintxx(s, ot, uint64(n), Widthint)
@@ -1116,7 +1116,7 @@ ok:
                s3 := dtypesym(mapbucket(t))
                s4 := dtypesym(hmap(t))
                ot = dcommontype(s, ot, t)
-               xt = ot - 2*Widthptr
+               xt = ot - 1*Widthptr
                ot = dsymptr(s, ot, s1, 0)
                ot = dsymptr(s, ot, s2, 0)
                ot = dsymptr(s, ot, s3, 0)
@@ -1153,7 +1153,7 @@ ok:
                s1 := dtypesym(t.Type)
 
                ot = dcommontype(s, ot, t)
-               xt = ot - 2*Widthptr
+               xt = ot - 1*Widthptr
                ot = dsymptr(s, ot, s1, 0)
 
        // ../../../../runtime/type.go:/structType
@@ -1167,7 +1167,7 @@ ok:
                }
 
                ot = dcommontype(s, ot, t)
-               xt = ot - 2*Widthptr
+               xt = ot - 1*Widthptr
                ot = dsymptr(s, ot, s, ot+Widthptr+2*Widthint)
                ot = duintxx(s, ot, uint64(n), Widthint)
                ot = duintxx(s, ot, uint64(n), Widthint)
@@ -1206,21 +1206,7 @@ ok:
        // we want be able to find.
        if t.Sym == nil {
                switch t.Etype {
-               case TPTR32, TPTR64:
-                       // The ptrto field of the type data cannot be relied on when
-                       // dynamic linking: a type T may be defined in a module that makes
-                       // no use of pointers to that type, but another module can contain
-                       // a package that imports the first one and does use *T pointers.
-                       // The second module will end up defining type data for *T and a
-                       // type.*T symbol pointing at it. It's important that calling
-                       // .PtrTo() on the reflect.Type for T returns this type data and
-                       // not some synthesized object, so we need reflect to be able to
-                       // find it!
-                       if !Ctxt.Flag_dynlink {
-                               break
-                       }
-                       fallthrough
-               case TARRAY, TCHAN, TFUNC, TMAP:
+               case TPTR32, TPTR64, TARRAY, TCHAN, TFUNC, TMAP:
                        slink := typelinksym(t)
                        dsymptr(slink, 0, s, 0)
                        ggloblsym(slink, int32(Widthptr), int16(dupok|obj.RODATA))
index c63c8e3c56611caa00417da39e72a56224cca1c5..e89c1412e2c2a693ea5814d7d6f7b835b19ec48d 100644 (file)
@@ -444,6 +444,11 @@ const (
        R_PLT1
        R_PLT2
        R_USEFIELD
+       // R_USETYPE resolves to an *rtype, but no relocation is created. The
+       // linker uses this as a signal that the pointed-to type information
+       // should be linked into the final binary, even if there are no other
+       // direct references. (This is used for types reachable by reflection.)
+       R_USETYPE
        R_POWER_TOC
        R_GOTPCREL
        // R_JMPMIPS (only used on mips64) resolves to non-PC-relative target address
index 8a16b0565685fc3509ee3cc663c63361a729701c..52eb46bb5c318f8b9b35889fb6cae102180f595d 100644 (file)
@@ -47,7 +47,7 @@ func decode_inuxi(p []byte, sz int) uint64 {
 // commonsize returns the size of the common prefix for all type
 // structures (runtime._type).
 func commonsize() int {
-       return 8*Thearch.Ptrsize + 8
+       return 7*Thearch.Ptrsize + 8
 }
 
 // Type.commonType.kind
index 3fce24e8497ee9045b1abe8f8d5cad2cc60bc8a6..2c7c1fb30bba5c3dcd8f94448fdf5952fc0ebbd0 100644 (file)
@@ -256,7 +256,6 @@ type rtype struct {
        gcdata        *byte    // garbage collection data
        string        string   // string form; unnecessary but undeniably useful
        *uncommonType          // (relatively) uncommon fields
-       ptrToThis     *rtype   // type for pointer to this type, if used in binary or has methods
 }
 
 // a copy of runtime.typeAlg
@@ -1030,15 +1029,7 @@ func PtrTo(t Type) Type {
 }
 
 func (t *rtype) ptrTo() *rtype {
-       if p := t.ptrToThis; p != nil {
-               return p
-       }
-
-       // Otherwise, synthesize one.
-       // This only happens for pointers with no methods.
-       // We keep the mapping in a map on the side, because
-       // this operation is rare and a separate map lets us keep
-       // the type structures in read-only memory.
+       // Check the cache.
        ptrMap.RLock()
        if m := ptrMap.m; m != nil {
                if p := m[t]; p != nil {
@@ -1047,6 +1038,7 @@ func (t *rtype) ptrTo() *rtype {
                }
        }
        ptrMap.RUnlock()
+
        ptrMap.Lock()
        if ptrMap.m == nil {
                ptrMap.m = make(map[*rtype]*ptrType)
@@ -1086,7 +1078,6 @@ func (t *rtype) ptrTo() *rtype {
        p.hash = fnv1(t.hash, '*')
 
        p.uncommonType = nil
-       p.ptrToThis = nil
        p.elem = t
 
        ptrMap.m[t] = p
@@ -1310,7 +1301,7 @@ func haveIdenticalUnderlyingType(T, V *rtype) bool {
 // Note that strings are not unique identifiers for types:
 // there can be more than one with a given string.
 // Only types we might want to look up are included:
-// channels, maps, slices, and arrays.
+// pointers, channels, maps, slices, and arrays.
 func typelinks() [][]*rtype
 
 // typesByString returns the subslice of typelinks() whose elements have
@@ -1465,7 +1456,6 @@ func ChanOf(dir ChanDir, t Type) Type {
        ch.hash = fnv1(typ.hash, 'c', byte(dir))
        ch.elem = typ
        ch.uncommonType = nil
-       ch.ptrToThis = nil
 
        return cachePut(ckey, &ch.rtype)
 }
@@ -1528,7 +1518,6 @@ func MapOf(key, elem Type) Type {
        mt.reflexivekey = isReflexive(ktyp)
        mt.needkeyupdate = needKeyUpdate(ktyp)
        mt.uncommonType = nil
-       mt.ptrToThis = nil
 
        return cachePut(ckey, &mt.rtype)
 }
@@ -1607,7 +1596,6 @@ func FuncOf(in, out []Type, variadic bool) Type {
        // Populate the remaining fields of ft and store in cache.
        ft.string = str
        ft.uncommonType = nil
-       ft.ptrToThis = nil
        funcLookupCache.m[hash] = append(funcLookupCache.m[hash], &ft.rtype)
 
        return &ft.rtype
@@ -1837,7 +1825,6 @@ func SliceOf(t Type) Type {
        slice.hash = fnv1(typ.hash, '[')
        slice.elem = typ
        slice.uncommonType = nil
-       slice.ptrToThis = nil
 
        return cachePut(ckey, &slice.rtype)
 }
@@ -1895,7 +1882,6 @@ func ArrayOf(count int, elem Type) Type {
        array.align = typ.align
        array.fieldAlign = typ.fieldAlign
        array.uncommonType = nil
-       array.ptrToThis = nil
        array.len = uintptr(count)
        array.slice = slice.(*rtype)
 
index 20ca27bc356767f18aa13ced4d477bc4571e2ea3..1e1157d0548b634b6c17994a39be8f8fb05d18b5 100644 (file)
@@ -502,28 +502,10 @@ func dumpparams() {
 
 func itab_callback(tab *itab) {
        t := tab._type
-       // Dump a map from itab* to the type of its data field.
-       // We want this map so we can deduce types of interface referents.
-       if t.kind&kindDirectIface == 0 {
-               // indirect - data slot is a pointer to t.
-               dumptype(t.ptrto)
-               dumpint(tagItab)
-               dumpint(uint64(uintptr(unsafe.Pointer(tab))))
-               dumpint(uint64(uintptr(unsafe.Pointer(t.ptrto))))
-       } else if t.kind&kindNoPointers == 0 {
-               // t is pointer-like - data slot is a t.
-               dumptype(t)
-               dumpint(tagItab)
-               dumpint(uint64(uintptr(unsafe.Pointer(tab))))
-               dumpint(uint64(uintptr(unsafe.Pointer(t))))
-       } else {
-               // Data slot is a scalar.  Dump type just for fun.
-               // With pointer-only interfaces, this shouldn't happen.
-               dumptype(t)
-               dumpint(tagItab)
-               dumpint(uint64(uintptr(unsafe.Pointer(tab))))
-               dumpint(uint64(uintptr(unsafe.Pointer(t))))
-       }
+       dumptype(t)
+       dumpint(tagItab)
+       dumpint(uint64(uintptr(unsafe.Pointer(tab))))
+       dumpint(uint64(uintptr(unsafe.Pointer(t))))
 }
 
 func dumpitabs() {
@@ -639,7 +621,7 @@ func dumpmemprof() {
        }
 }
 
-var dumphdr = []byte("go1.6 heap dump\n")
+var dumphdr = []byte("go1.7 heap dump\n")
 
 func mdump() {
        // make sure we're done sweeping
index 1323adaf6410def11796bdd0a20c271c2d17e475..8304ad7b7731671449309541434800ef9d3d48a5 100644 (file)
@@ -26,7 +26,6 @@ type _type struct {
        gcdata  *byte
        _string string
        x       *uncommontype
-       ptrto   *_type
 }
 
 type method struct {