Commit e369490f authored by David Crawshaw's avatar David Crawshaw

cmd/compile, etc: bring back ptrToThis

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/24400Reviewed-by: default avatarIan Lance Taylor <iant@golang.org>
parent aa6345d3
...@@ -820,14 +820,10 @@ func dcommontype(s *Sym, ot int, t *Type) int { ...@@ -820,14 +820,10 @@ func dcommontype(s *Sym, ot int, t *Type) int {
algsym = dalgsym(t) algsym = dalgsym(t)
} }
var sptr *Sym
tptr := Ptrto(t) tptr := Ptrto(t)
if !t.IsPtr() && (t.Sym != nil || methods(tptr) != nil) { if !t.IsPtr() && (t.Sym != nil || methods(tptr) != nil) {
sptr := dtypesym(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) gcsym, useGCProg, ptrdata := dgcsym(t)
...@@ -845,7 +841,7 @@ func dcommontype(s *Sym, ot int, t *Type) int { ...@@ -845,7 +841,7 @@ func dcommontype(s *Sym, ot int, t *Type) int {
// alg *typeAlg // alg *typeAlg
// gcdata *byte // gcdata *byte
// str nameOff // str nameOff
// _ int32 // ptrToThis typeOff
// } // }
ot = duintptr(s, ot, uint64(t.Width)) ot = duintptr(s, ot, uint64(t.Width))
ot = duintptr(s, ot, uint64(ptrdata)) ot = duintptr(s, ot, uint64(ptrdata))
...@@ -909,8 +905,12 @@ func dcommontype(s *Sym, ot int, t *Type) int { ...@@ -909,8 +905,12 @@ func dcommontype(s *Sym, ot int, t *Type) int {
ot = dsymptr(s, ot, gcsym, 0) // gcdata ot = dsymptr(s, ot, gcsym, 0) // gcdata
nsym := dname(p, "", nil, exported) nsym := dname(p, "", nil, exported)
ot = dsymptrOffLSym(Linksym(s), ot, nsym, 0) ot = dsymptrOffLSym(Linksym(s), ot, nsym, 0) // str
ot = duint32(s, ot, 0) if sptr == nil {
ot = duint32(s, ot, 0)
} else {
ot = dsymptrOffLSym(Linksym(s), ot, Linksym(sptr), 0) // ptrToThis
}
return ot return ot
} }
......
...@@ -5741,3 +5741,10 @@ func TestOffsetLock(t *testing.T) { ...@@ -5741,3 +5741,10 @@ func TestOffsetLock(t *testing.T) {
} }
wg.Wait() wg.Wait()
} }
func BenchmarkNew(b *testing.B) {
v := TypeOf(XM{})
for i := 0; i < b.N; i++ {
New(v)
}
}
...@@ -285,7 +285,7 @@ type rtype struct { ...@@ -285,7 +285,7 @@ type rtype struct {
alg *typeAlg // algorithm table alg *typeAlg // algorithm table
gcdata *byte // garbage collection data gcdata *byte // garbage collection data
str nameOff // string form 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 // a copy of runtime.typeAlg
...@@ -1430,6 +1430,10 @@ func PtrTo(t Type) Type { ...@@ -1430,6 +1430,10 @@ func PtrTo(t Type) Type {
} }
func (t *rtype) ptrTo() *rtype { func (t *rtype) ptrTo() *rtype {
if t.ptrToThis != 0 {
return t.typeOff(t.ptrToThis)
}
// Check the cache. // Check the cache.
ptrMap.RLock() ptrMap.RLock()
if m := ptrMap.m; m != nil { if m := ptrMap.m; m != nil {
...@@ -1927,6 +1931,7 @@ func MapOf(key, elem Type) Type { ...@@ -1927,6 +1931,7 @@ func MapOf(key, elem Type) Type {
mt.bucketsize = uint16(mt.bucket.size) mt.bucketsize = uint16(mt.bucket.size)
mt.reflexivekey = isReflexive(ktyp) mt.reflexivekey = isReflexive(ktyp)
mt.needkeyupdate = needKeyUpdate(ktyp) mt.needkeyupdate = needKeyUpdate(ktyp)
mt.ptrToThis = 0
return cachePut(ckey, &mt.rtype) return cachePut(ckey, &mt.rtype)
} }
...@@ -2065,6 +2070,7 @@ func FuncOf(in, out []Type, variadic bool) Type { ...@@ -2065,6 +2070,7 @@ func FuncOf(in, out []Type, variadic bool) Type {
// Populate the remaining fields of ft and store in cache. // Populate the remaining fields of ft and store in cache.
ft.str = resolveReflectName(newName(str, "", "", false)) ft.str = resolveReflectName(newName(str, "", "", false))
ft.ptrToThis = 0
funcLookupCache.m[hash] = append(funcLookupCache.m[hash], &ft.rtype) funcLookupCache.m[hash] = append(funcLookupCache.m[hash], &ft.rtype)
return &ft.rtype return &ft.rtype
...@@ -2295,6 +2301,7 @@ func SliceOf(t Type) Type { ...@@ -2295,6 +2301,7 @@ func SliceOf(t Type) Type {
slice.str = resolveReflectName(newName(s, "", "", false)) slice.str = resolveReflectName(newName(s, "", "", false))
slice.hash = fnv1(typ.hash, '[') slice.hash = fnv1(typ.hash, '[')
slice.elem = typ slice.elem = typ
slice.ptrToThis = 0
return cachePut(ckey, &slice.rtype) return cachePut(ckey, &slice.rtype)
} }
...@@ -2842,6 +2849,7 @@ func ArrayOf(count int, elem Type) Type { ...@@ -2842,6 +2849,7 @@ func ArrayOf(count int, elem Type) Type {
} }
array.hash = fnv1(array.hash, ']') array.hash = fnv1(array.hash, ']')
array.elem = typ array.elem = typ
array.ptrToThis = 0
max := ^uintptr(0) / typ.size max := ^uintptr(0) / typ.size
if uintptr(count) > max { if uintptr(count) > max {
panic("reflect.ArrayOf: array size would exceed virtual address space") panic("reflect.ArrayOf: array size would exceed virtual address space")
......
...@@ -36,9 +36,9 @@ type _type struct { ...@@ -36,9 +36,9 @@ type _type struct {
// gcdata stores the GC type data for the garbage collector. // gcdata stores the GC type data for the garbage collector.
// If the KindGCProg bit is set in kind, gcdata is a GC program. // If the KindGCProg bit is set in kind, gcdata is a GC program.
// Otherwise it is a ptrmask bitmap. See mbitmap.go for details. // Otherwise it is a ptrmask bitmap. See mbitmap.go for details.
gcdata *byte gcdata *byte
str nameOff str nameOff
_ int32 ptrToThis typeOff
} }
func (t *_type) string() string { func (t *_type) string() string {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment