]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/compile, etc: bring back ptrToThis
authorDavid Crawshaw <crawshaw@golang.org>
Thu, 23 Jun 2016 14:59:38 +0000 (10:59 -0400)
committerDavid Crawshaw <crawshaw@golang.org>
Thu, 23 Jun 2016 17:39:38 +0000 (17:39 +0000)
This was removed in CL 19695 but it slows down reflect.New, which ends
up on the hot path of things like JSON decoding.

There is no immediate cost in binary size, but it will make it harder to
further shrink run time type information in Go 1.8.

Before

BenchmarkNew-40         30000000                36.3 ns/op

After

BenchmarkNew-40         50000000                29.5 ns/op

Fixes #16161
Updates #16117

Change-Id: If7cb7f3e745d44678f3f5cf3a5338c59847529d2
Reviewed-on: https://go-review.googlesource.com/24400
Reviewed-by: Ian Lance Taylor <iant@golang.org>
src/cmd/compile/internal/gc/reflect.go
src/reflect/all_test.go
src/reflect/type.go
src/runtime/type.go

index c4268f646f5fcc412646a8f2b042a2964d68f2b4..f1a7d3bc8641538136c50734c3114c26981e9d90 100644 (file)
@@ -820,14 +820,10 @@ func dcommontype(s *Sym, ot int, t *Type) int {
                algsym = dalgsym(t)
        }
 
+       var sptr *Sym
        tptr := Ptrto(t)
        if !t.IsPtr() && (t.Sym != nil || methods(tptr) != nil) {
-               sptr := dtypesym(tptr)
-               r := obj.Addrel(Linksym(s))
-               r.Off = 0
-               r.Siz = 0
-               r.Sym = sptr.Lsym
-               r.Type = obj.R_USETYPE
+               sptr = dtypesym(tptr)
        }
 
        gcsym, useGCProg, ptrdata := dgcsym(t)
@@ -845,7 +841,7 @@ func dcommontype(s *Sym, ot int, t *Type) int {
        //              alg           *typeAlg
        //              gcdata        *byte
        //              str           nameOff
-       //              _             int32
+       //              ptrToThis     typeOff
        //      }
        ot = duintptr(s, ot, uint64(t.Width))
        ot = duintptr(s, ot, uint64(ptrdata))
@@ -909,8 +905,12 @@ func dcommontype(s *Sym, ot int, t *Type) int {
        ot = dsymptr(s, ot, gcsym, 0) // gcdata
 
        nsym := dname(p, "", nil, exported)
-       ot = dsymptrOffLSym(Linksym(s), ot, nsym, 0)
-       ot = duint32(s, ot, 0)
+       ot = dsymptrOffLSym(Linksym(s), ot, nsym, 0) // str
+       if sptr == nil {
+               ot = duint32(s, ot, 0)
+       } else {
+               ot = dsymptrOffLSym(Linksym(s), ot, Linksym(sptr), 0) // ptrToThis
+       }
 
        return ot
 }
index 97086b1852fbba6a38d7e09b139b4cddcfca9ddd..adde5829dc60aec7b81625993e0dc35f90ae8b9b 100644 (file)
@@ -5741,3 +5741,10 @@ func TestOffsetLock(t *testing.T) {
        }
        wg.Wait()
 }
+
+func BenchmarkNew(b *testing.B) {
+       v := TypeOf(XM{})
+       for i := 0; i < b.N; i++ {
+               New(v)
+       }
+}
index 7996ae284b328f623fdaef999051b84688cd782e..b37fb9f0a55a119789a165a2d1016c1b07e4b293 100644 (file)
@@ -285,7 +285,7 @@ type rtype struct {
        alg        *typeAlg // algorithm table
        gcdata     *byte    // garbage collection data
        str        nameOff  // string form
-       _          int32    // unused; keeps rtype always a multiple of ptrSize
+       ptrToThis  typeOff  // type for pointer to this type, may be zero
 }
 
 // a copy of runtime.typeAlg
@@ -1430,6 +1430,10 @@ func PtrTo(t Type) Type {
 }
 
 func (t *rtype) ptrTo() *rtype {
+       if t.ptrToThis != 0 {
+               return t.typeOff(t.ptrToThis)
+       }
+
        // Check the cache.
        ptrMap.RLock()
        if m := ptrMap.m; m != nil {
@@ -1927,6 +1931,7 @@ func MapOf(key, elem Type) Type {
        mt.bucketsize = uint16(mt.bucket.size)
        mt.reflexivekey = isReflexive(ktyp)
        mt.needkeyupdate = needKeyUpdate(ktyp)
+       mt.ptrToThis = 0
 
        return cachePut(ckey, &mt.rtype)
 }
@@ -2065,6 +2070,7 @@ func FuncOf(in, out []Type, variadic bool) Type {
 
        // Populate the remaining fields of ft and store in cache.
        ft.str = resolveReflectName(newName(str, "", "", false))
+       ft.ptrToThis = 0
        funcLookupCache.m[hash] = append(funcLookupCache.m[hash], &ft.rtype)
 
        return &ft.rtype
@@ -2295,6 +2301,7 @@ func SliceOf(t Type) Type {
        slice.str = resolveReflectName(newName(s, "", "", false))
        slice.hash = fnv1(typ.hash, '[')
        slice.elem = typ
+       slice.ptrToThis = 0
 
        return cachePut(ckey, &slice.rtype)
 }
@@ -2842,6 +2849,7 @@ func ArrayOf(count int, elem Type) Type {
        }
        array.hash = fnv1(array.hash, ']')
        array.elem = typ
+       array.ptrToThis = 0
        max := ^uintptr(0) / typ.size
        if uintptr(count) > max {
                panic("reflect.ArrayOf: array size would exceed virtual address space")
index 786f2b96f6155c6c076ec02a35112ca1ac14a396..5ae5c73a226637a8351f53a2845be4943ee633c2 100644 (file)
@@ -36,9 +36,9 @@ type _type struct {
        // gcdata stores the GC type data for the garbage collector.
        // If the KindGCProg bit is set in kind, gcdata is a GC program.
        // Otherwise it is a ptrmask bitmap. See mbitmap.go for details.
-       gcdata *byte
-       str    nameOff
-       _      int32
+       gcdata    *byte
+       str       nameOff
+       ptrToThis typeOff
 }
 
 func (t *_type) string() string {