aboutsummaryrefslogtreecommitdiff
path: root/src/runtime/iface.go
diff options
context:
space:
mode:
authorJosh Bleecher Snyder <josharian@gmail.com>2018-10-29 13:54:24 -0700
committerJosh Bleecher Snyder <josharian@gmail.com>2018-11-06 00:02:14 +0000
commit5848b6c9b854546473814c8752ee117a71bb8b54 (patch)
treeba373737e5ad0d8775ae90e24f609716998a7f14 /src/runtime/iface.go
parent9e619739fdc4cbaeb00a10ef95ce3e5d6996e8a7 (diff)
downloadgo-5848b6c9b854546473814c8752ee117a71bb8b54.tar.gz
go-5848b6c9b854546473814c8752ee117a71bb8b54.zip
cmd/compile: shrink specialized convT2x call sites
convT2E16 and other specialized type-to-interface routines accept a type/itab argument and return a complete interface value. However, we know enough in the routine to do without the type. And the caller can construct the interface value using the type. Doing so shrinks the call sites of ten of the specialized convT2x routines. It also lets us unify the empty and non-empty interface routines. Cuts 12k off cmd/go. name old time/op new time/op delta ConvT2ESmall-8 2.96ns ± 2% 2.34ns ± 4% -21.01% (p=0.000 n=175+189) ConvT2EUintptr-8 3.00ns ± 3% 2.34ns ± 4% -22.02% (p=0.000 n=189+187) ConvT2ELarge-8 21.3ns ± 7% 21.5ns ± 5% +1.02% (p=0.000 n=200+197) ConvT2ISmall-8 2.99ns ± 4% 2.33ns ± 3% -21.95% (p=0.000 n=193+184) ConvT2IUintptr-8 3.02ns ± 3% 2.33ns ± 3% -22.82% (p=0.000 n=198+190) ConvT2ILarge-8 21.7ns ± 5% 22.2ns ± 4% +2.31% (p=0.000 n=199+198) ConvT2Ezero/zero/16-8 2.96ns ± 2% 2.33ns ± 3% -21.11% (p=0.000 n=174+187) ConvT2Ezero/zero/32-8 2.96ns ± 1% 2.35ns ± 4% -20.62% (p=0.000 n=163+193) ConvT2Ezero/zero/64-8 2.99ns ± 2% 2.34ns ± 4% -21.78% (p=0.000 n=183+188) ConvT2Ezero/zero/str-8 3.27ns ± 3% 2.54ns ± 3% -22.32% (p=0.000 n=195+192) ConvT2Ezero/zero/slice-8 3.46ns ± 4% 2.81ns ± 3% -18.96% (p=0.000 n=197+164) ConvT2Ezero/zero/big-8 88.4ns ±20% 90.0ns ±20% +1.84% (p=0.000 n=196+198) ConvT2Ezero/nonzero/16-8 12.6ns ± 3% 12.3ns ± 3% -2.34% (p=0.000 n=167+196) ConvT2Ezero/nonzero/32-8 12.3ns ± 4% 11.9ns ± 3% -2.95% (p=0.000 n=187+193) ConvT2Ezero/nonzero/64-8 14.2ns ± 6% 13.8ns ± 5% -2.94% (p=0.000 n=198+199) ConvT2Ezero/nonzero/str-8 27.2ns ± 5% 26.8ns ± 5% -1.33% (p=0.000 n=200+198) ConvT2Ezero/nonzero/slice-8 33.3ns ± 8% 33.1ns ± 6% -0.82% (p=0.000 n=199+200) ConvT2Ezero/nonzero/big-8 88.8ns ±22% 90.2ns ±18% +1.58% (p=0.000 n=200+199) Neligible toolspeed impact. name old alloc/op new alloc/op delta Template 35.4MB ± 0% 35.3MB ± 0% -0.06% (p=0.008 n=5+5) Unicode 29.1MB ± 0% 29.1MB ± 0% ~ (p=0.310 n=5+5) GoTypes 122MB ± 0% 122MB ± 0% -0.08% (p=0.008 n=5+5) Compiler 514MB ± 0% 513MB ± 0% -0.02% (p=0.008 n=5+5) SSA 1.94GB ± 0% 1.94GB ± 0% -0.01% (p=0.008 n=5+5) Flate 24.2MB ± 0% 24.2MB ± 0% ~ (p=0.548 n=5+5) GoParser 28.5MB ± 0% 28.5MB ± 0% -0.05% (p=0.016 n=5+5) Reflect 86.3MB ± 0% 86.2MB ± 0% -0.02% (p=0.008 n=5+5) Tar 34.9MB ± 0% 34.9MB ± 0% ~ (p=0.095 n=5+5) XML 47.1MB ± 0% 47.1MB ± 0% -0.05% (p=0.008 n=5+5) [Geo mean] 81.0MB 81.0MB -0.03% name old allocs/op new allocs/op delta Template 349k ± 0% 349k ± 0% -0.08% (p=0.008 n=5+5) Unicode 340k ± 0% 340k ± 0% ~ (p=0.111 n=5+5) GoTypes 1.28M ± 0% 1.28M ± 0% -0.09% (p=0.008 n=5+5) Compiler 4.92M ± 0% 4.92M ± 0% -0.08% (p=0.008 n=5+5) SSA 15.3M ± 0% 15.3M ± 0% -0.03% (p=0.008 n=5+5) Flate 233k ± 0% 233k ± 0% ~ (p=0.500 n=5+5) GoParser 292k ± 0% 292k ± 0% -0.06% (p=0.008 n=5+5) Reflect 1.05M ± 0% 1.05M ± 0% -0.02% (p=0.008 n=5+5) Tar 344k ± 0% 343k ± 0% -0.06% (p=0.008 n=5+5) XML 430k ± 0% 429k ± 0% -0.08% (p=0.008 n=5+5) [Geo mean] 809k 809k -0.05% name old object-bytes new object-bytes delta Template 507kB ± 0% 507kB ± 0% -0.04% (p=0.008 n=5+5) Unicode 225kB ± 0% 225kB ± 0% ~ (all equal) GoTypes 1.85MB ± 0% 1.85MB ± 0% -0.08% (p=0.008 n=5+5) Compiler 6.75MB ± 0% 6.75MB ± 0% +0.01% (p=0.008 n=5+5) SSA 21.4MB ± 0% 21.4MB ± 0% -0.02% (p=0.008 n=5+5) Flate 328kB ± 0% 328kB ± 0% -0.03% (p=0.008 n=5+5) GoParser 403kB ± 0% 402kB ± 0% -0.06% (p=0.008 n=5+5) Reflect 1.41MB ± 0% 1.41MB ± 0% -0.03% (p=0.008 n=5+5) Tar 457kB ± 0% 457kB ± 0% -0.05% (p=0.008 n=5+5) XML 601kB ± 0% 600kB ± 0% -0.16% (p=0.008 n=5+5) [Geo mean] 1.05MB 1.04MB -0.05% Change-Id: I677a4108c0ecd32617549294036aa84f9214c4fe Reviewed-on: https://go-review.googlesource.com/c/147360 Run-TryBot: Josh Bleecher Snyder <josharian@gmail.com> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Keith Randall <khr@golang.org> Reviewed-by: Martin Möhrmann <moehrmann@google.com>
Diffstat (limited to 'src/runtime/iface.go')
-rw-r--r--src/runtime/iface.go134
1 files changed, 38 insertions, 96 deletions
diff --git a/src/runtime/iface.go b/src/runtime/iface.go
index 1ef9825a48..8eca2e849d 100644
--- a/src/runtime/iface.go
+++ b/src/runtime/iface.go
@@ -267,6 +267,34 @@ func panicnildottype(want *_type) {
// Just to match other nil conversion errors, we don't for now.
}
+// The specialized convTx routines need a type descriptor to use when calling mallocgc.
+// We don't need the type to be exact, just to have the correct size, alignment, and pointer-ness.
+// However, when debugging, it'd be nice to have some indication in mallocgc where the types came from,
+// so we use named types here.
+// We then construct interface values of these types,
+// and then extract the type word to use as needed.
+type (
+ uint16InterfacePtr uint16
+ uint32InterfacePtr uint32
+ uint64InterfacePtr uint64
+ stringInterfacePtr string
+ sliceInterfacePtr []byte
+)
+
+var (
+ uint16Eface interface{} = uint16InterfacePtr(0)
+ uint32Eface interface{} = uint32InterfacePtr(0)
+ uint64Eface interface{} = uint64InterfacePtr(0)
+ stringEface interface{} = stringInterfacePtr("")
+ sliceEface interface{} = sliceInterfacePtr(nil)
+
+ uint16Type *_type = (*eface)(unsafe.Pointer(&uint16Eface))._type
+ uint32Type *_type = (*eface)(unsafe.Pointer(&uint32Eface))._type
+ uint64Type *_type = (*eface)(unsafe.Pointer(&uint64Eface))._type
+ stringType *_type = (*eface)(unsafe.Pointer(&stringEface))._type
+ sliceType *_type = (*eface)(unsafe.Pointer(&sliceEface))._type
+)
+
// The conv and assert functions below do very similar things.
// The convXXX functions are guaranteed by the compiler to succeed.
// The assertXXX functions may fail (either panicking or returning false,
@@ -290,69 +318,54 @@ func convT2E(t *_type, elem unsafe.Pointer) (e eface) {
return
}
-func convT2E16(t *_type, val uint16) (e eface) {
- var x unsafe.Pointer
+func convT16(val uint16) (x unsafe.Pointer) {
if val == 0 {
x = unsafe.Pointer(&zeroVal[0])
} else {
- x = mallocgc(2, t, false)
+ x = mallocgc(2, uint16Type, false)
*(*uint16)(x) = val
}
- e._type = t
- e.data = x
return
}
-func convT2E32(t *_type, val uint32) (e eface) {
- var x unsafe.Pointer
+func convT32(val uint32) (x unsafe.Pointer) {
if val == 0 {
x = unsafe.Pointer(&zeroVal[0])
} else {
- x = mallocgc(4, t, false)
+ x = mallocgc(4, uint32Type, false)
*(*uint32)(x) = val
}
- e._type = t
- e.data = x
return
}
-func convT2E64(t *_type, val uint64) (e eface) {
- var x unsafe.Pointer
+func convT64(val uint64) (x unsafe.Pointer) {
if val == 0 {
x = unsafe.Pointer(&zeroVal[0])
} else {
- x = mallocgc(8, t, false)
+ x = mallocgc(8, uint64Type, false)
*(*uint64)(x) = val
}
- e._type = t
- e.data = x
return
}
-func convT2Estring(t *_type, val string) (e eface) {
- var x unsafe.Pointer
+func convTstring(val string) (x unsafe.Pointer) {
if val == "" {
x = unsafe.Pointer(&zeroVal[0])
} else {
- x = mallocgc(unsafe.Sizeof(val), t, true)
+ x = mallocgc(unsafe.Sizeof(val), stringType, true)
*(*string)(x) = val
}
- e._type = t
- e.data = x
return
}
-func convT2Eslice(t *_type, val []byte) (e eface) {
+func convTslice(val []byte) (x unsafe.Pointer) {
// Note: this must work for any element type, not just byte.
- var x unsafe.Pointer
if (*slice)(unsafe.Pointer(&val)).array == nil {
x = unsafe.Pointer(&zeroVal[0])
} else {
- x = mallocgc(unsafe.Sizeof(val), t, true)
+ x = mallocgc(unsafe.Sizeof(val), sliceType, true)
*(*[]byte)(x) = val
}
- e._type = t
- e.data = x
return
}
@@ -385,77 +398,6 @@ func convT2I(tab *itab, elem unsafe.Pointer) (i iface) {
return
}
-func convT2I16(tab *itab, val uint16) (i iface) {
- t := tab._type
- var x unsafe.Pointer
- if val == 0 {
- x = unsafe.Pointer(&zeroVal[0])
- } else {
- x = mallocgc(2, t, false)
- *(*uint16)(x) = val
- }
- i.tab = tab
- i.data = x
- return
-}
-
-func convT2I32(tab *itab, val uint32) (i iface) {
- t := tab._type
- var x unsafe.Pointer
- if val == 0 {
- x = unsafe.Pointer(&zeroVal[0])
- } else {
- x = mallocgc(4, t, false)
- *(*uint32)(x) = val
- }
- i.tab = tab
- i.data = x
- return
-}
-
-func convT2I64(tab *itab, val uint64) (i iface) {
- t := tab._type
- var x unsafe.Pointer
- if val == 0 {
- x = unsafe.Pointer(&zeroVal[0])
- } else {
- x = mallocgc(8, t, false)
- *(*uint64)(x) = val
- }
- i.tab = tab
- i.data = x
- return
-}
-
-func convT2Istring(tab *itab, val string) (i iface) {
- t := tab._type
- var x unsafe.Pointer
- if val == "" {
- x = unsafe.Pointer(&zeroVal[0])
- } else {
- x = mallocgc(unsafe.Sizeof(val), t, true)
- *(*string)(x) = val
- }
- i.tab = tab
- i.data = x
- return
-}
-
-func convT2Islice(tab *itab, val []byte) (i iface) {
- // Note: this must work for any element type, not just byte.
- t := tab._type
- var x unsafe.Pointer
- if (*slice)(unsafe.Pointer(&val)).array == nil {
- x = unsafe.Pointer(&zeroVal[0])
- } else {
- x = mallocgc(unsafe.Sizeof(val), t, true)
- *(*[]byte)(x) = val
- }
- i.tab = tab
- i.data = x
- return
-}
-
func convT2Inoptr(tab *itab, elem unsafe.Pointer) (i iface) {
t := tab._type
if raceenabled {