reflect: avoid zeroing memory that will be overwritten

Avoid new'ing memory that will be overwritten by assignment.

name              old time/op    new time/op    delta
Call-4               160ns ± 4%     155ns ± 2%  -3.19%        (p=0.003 n=10+10)
FieldByName1-4      94.5ns ± 2%    95.2ns ± 1%  +0.65%          (p=0.026 n=9+9)
FieldByName2-4      3.09µs ± 4%    3.13µs ± 2%    ~           (p=0.165 n=10+10)
FieldByName3-4      19.8µs ± 1%    19.9µs ± 1%    ~            (p=0.395 n=10+8)
InterfaceBig-4      11.6ns ± 0%    11.7ns ± 0%  +0.86%          (p=0.000 n=8+9)
InterfaceSmall-4    11.7ns ± 0%    11.7ns ± 0%    ~     (all samples are equal)
New-4               26.6ns ± 0%    26.4ns ± 0%  -0.64%         (p=0.000 n=10+9)

name              old alloc/op   new alloc/op   delta
Call-4              0.00B ±NaN%    0.00B ±NaN%    ~     (all samples are equal)

name              old allocs/op  new allocs/op  delta
Call-4               0.00 ±NaN%     0.00 ±NaN%    ~     (all samples are equal)

Change-Id: I12c85d4e65245598669dd6f66beb0744ec9b9d6d
Reviewed-on: https://go-review.googlesource.com/28011
Run-TryBot: Dave Cheney <dave@cheney.net>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
This commit is contained in:
Dave Cheney 2016-08-29 09:44:50 +10:00
parent b6e3a98cf3
commit adb1e67f02

View file

@ -1456,25 +1456,24 @@ func (t *rtype) ptrTo() *rtype {
// Create a new ptrType starting with the description // Create a new ptrType starting with the description
// of an *unsafe.Pointer. // of an *unsafe.Pointer.
p = new(ptrType)
var iptr interface{} = (*unsafe.Pointer)(nil) var iptr interface{} = (*unsafe.Pointer)(nil)
prototype := *(**ptrType)(unsafe.Pointer(&iptr)) prototype := *(**ptrType)(unsafe.Pointer(&iptr))
*p = *prototype pp := *prototype
p.str = resolveReflectName(newName(s, "", "", false)) pp.str = resolveReflectName(newName(s, "", "", false))
// For the type structures linked into the binary, the // For the type structures linked into the binary, the
// compiler provides a good hash of the string. // compiler provides a good hash of the string.
// Create a good hash for the new string by using // Create a good hash for the new string by using
// the FNV-1 hash's mixing function to combine the // the FNV-1 hash's mixing function to combine the
// old hash and the new "*". // old hash and the new "*".
p.hash = fnv1(t.hash, '*') pp.hash = fnv1(t.hash, '*')
p.elem = t pp.elem = t
ptrMap.m[t] = p ptrMap.m[t] = &pp
ptrMap.Unlock() ptrMap.Unlock()
return &p.rtype return &pp.rtype
} }
// fnv1 incorporates the list of bytes into the hash x using the FNV-1 hash function. // fnv1 incorporates the list of bytes into the hash x using the FNV-1 hash function.
@ -1852,8 +1851,7 @@ func ChanOf(dir ChanDir, t Type) Type {
// Make a channel type. // Make a channel type.
var ichan interface{} = (chan unsafe.Pointer)(nil) var ichan interface{} = (chan unsafe.Pointer)(nil)
prototype := *(**chanType)(unsafe.Pointer(&ichan)) prototype := *(**chanType)(unsafe.Pointer(&ichan))
ch := new(chanType) ch := *prototype
*ch = *prototype
ch.tflag = 0 ch.tflag = 0
ch.dir = uintptr(dir) ch.dir = uintptr(dir)
ch.str = resolveReflectName(newName(s, "", "", false)) ch.str = resolveReflectName(newName(s, "", "", false))
@ -1896,8 +1894,7 @@ func MapOf(key, elem Type) Type {
// Make a map type. // Make a map type.
var imap interface{} = (map[unsafe.Pointer]unsafe.Pointer)(nil) var imap interface{} = (map[unsafe.Pointer]unsafe.Pointer)(nil)
mt := new(mapType) mt := **(**mapType)(unsafe.Pointer(&imap))
*mt = **(**mapType)(unsafe.Pointer(&imap))
mt.str = resolveReflectName(newName(s, "", "", false)) mt.str = resolveReflectName(newName(s, "", "", false))
mt.tflag = 0 mt.tflag = 0
mt.hash = fnv1(etyp.hash, 'm', byte(ktyp.hash>>24), byte(ktyp.hash>>16), byte(ktyp.hash>>8), byte(ktyp.hash)) mt.hash = fnv1(etyp.hash, 'm', byte(ktyp.hash>>24), byte(ktyp.hash>>16), byte(ktyp.hash>>8), byte(ktyp.hash))
@ -2248,15 +2245,16 @@ func bucketOf(ktyp, etyp *rtype) *rtype {
} }
} }
b := new(rtype) b := &rtype{
b.align = ptrSize align: ptrSize,
size: size,
kind: kind,
ptrdata: ptrdata,
gcdata: gcdata,
}
if overflowPad > 0 { if overflowPad > 0 {
b.align = 8 b.align = 8
} }
b.size = size
b.ptrdata = ptrdata
b.kind = kind
b.gcdata = gcdata
s := "bucket(" + ktyp.String() + "," + etyp.String() + ")" s := "bucket(" + ktyp.String() + "," + etyp.String() + ")"
b.str = resolveReflectName(newName(s, "", "", false)) b.str = resolveReflectName(newName(s, "", "", false))
return b return b
@ -2285,8 +2283,7 @@ func SliceOf(t Type) Type {
// Make a slice type. // Make a slice type.
var islice interface{} = ([]unsafe.Pointer)(nil) var islice interface{} = ([]unsafe.Pointer)(nil)
prototype := *(**sliceType)(unsafe.Pointer(&islice)) prototype := *(**sliceType)(unsafe.Pointer(&islice))
slice := new(sliceType) slice := *prototype
*slice = *prototype
slice.tflag = 0 slice.tflag = 0
slice.str = resolveReflectName(newName(s, "", "", false)) slice.str = resolveReflectName(newName(s, "", "", false))
slice.hash = fnv1(typ.hash, '[') slice.hash = fnv1(typ.hash, '[')
@ -2830,8 +2827,7 @@ func ArrayOf(count int, elem Type) Type {
// Make an array type. // Make an array type.
var iarray interface{} = [1]unsafe.Pointer{} var iarray interface{} = [1]unsafe.Pointer{}
prototype := *(**arrayType)(unsafe.Pointer(&iarray)) prototype := *(**arrayType)(unsafe.Pointer(&iarray))
array := new(arrayType) array := *prototype
*array = *prototype
array.str = resolveReflectName(newName(s, "", "", false)) array.str = resolveReflectName(newName(s, "", "", false))
array.hash = fnv1(typ.hash, '[') array.hash = fnv1(typ.hash, '[')
for n := uint32(count); n > 0; n >>= 8 { for n := uint32(count); n > 0; n >>= 8 {
@ -3071,13 +3067,14 @@ func funcLayout(t *rtype, rcvr *rtype) (frametype *rtype, argSize, retOffset uin
offset += -offset & (ptrSize - 1) offset += -offset & (ptrSize - 1)
// build dummy rtype holding gc program // build dummy rtype holding gc program
x := new(rtype) x := &rtype{
x.align = ptrSize align: ptrSize,
size: offset,
ptrdata: uintptr(ptrmap.n) * ptrSize,
}
if runtime.GOARCH == "amd64p32" { if runtime.GOARCH == "amd64p32" {
x.align = 8 x.align = 8
} }
x.size = offset
x.ptrdata = uintptr(ptrmap.n) * ptrSize
if ptrmap.n > 0 { if ptrmap.n > 0 {
x.gcdata = &ptrmap.data[0] x.gcdata = &ptrmap.data[0]
} else { } else {