GOARCH=amd64 benchmarks
src/pkg/runtime
benchmark old ns/op new ns/op delta
BenchmarkConvT2ESmall 10 10 +1.00%
BenchmarkConvT2EUintptr 9 0 -92.07%
BenchmarkConvT2EBig 74 74 -0.27%
BenchmarkConvT2I 27 26 -3.62%
BenchmarkConvI2E 4 4 -7.05%
BenchmarkConvI2I 20 19 -2.99%
test/bench/go1
benchmark old ns/op new ns/op delta
BenchmarkBinaryTree17
5930908000 5937260000 +0.11%
BenchmarkFannkuch11
3927057000 3933556000 +0.17%
BenchmarkGobDecode
21998090 21870620 -0.58%
BenchmarkGobEncode
12725310 12734480 +0.07%
BenchmarkGzip
567617600 567892800 +0.05%
BenchmarkGunzip
178284100 178706900 +0.24%
BenchmarkJSONEncode
87693550 86794300 -1.03%
BenchmarkJSONDecode
314212600 324115000 +3.15%
BenchmarkMandelbrot200
7016640 7073766 +0.81%
BenchmarkParse
7852100 7892085 +0.51%
BenchmarkRevcomp
1285663000 1286147000 +0.04%
BenchmarkTemplate
566823800 567606200 +0.14%
I'm not entirely sure why the JSON* numbers have changed, but
eyeballing the profile suggests that it could be spending less
and more time in runtime.{new,old}stack, so it could simply be
stack-split boundary noise.
R=rsc, dave, bsiegert, dsymonds
CC=golang-dev
https://golang.org/cl/
6280049
} else
cgen_slice(n, res);
return;
+ case OEFACE:
+ if (res->op != ONAME || !res->addable) {
+ tempname(&n1, n->type);
+ cgen_eface(n, &n1);
+ cgen(&n1, res);
+ } else
+ cgen_eface(n, res);
+ return;
}
while(n->op == OCONVNOP)
agen(&n1, res);
break;
+ case OEFACE:
+ tempname(&n1, n->type);
+ cgen_eface(n, &n1);
+ agen(&n1, res);
+ break;
+
case OINDEX:
p2 = nil; // to be patched to panicindex.
w = n->type->width;
} else
cgen_slice(n, res);
goto ret;
+ case OEFACE:
+ if (res->op != ONAME || !res->addable) {
+ tempname(&n1, n->type);
+ cgen_eface(n, &n1);
+ cgen(&n1, res);
+ } else
+ cgen_eface(n, res);
+ goto ret;
}
if(n->ullman >= UINF) {
agen(&n1, res);
break;
+ case OEFACE:
+ tempname(&n1, n->type);
+ cgen_eface(n, &n1);
+ agen(&n1, res);
+ break;
+
case OINDEX:
w = n->type->width;
if(nr->addable)
} else
cgen_slice(n, res);
return;
+ case OEFACE:
+ if (res->op != ONAME || !res->addable) {
+ tempname(&n1, n->type);
+ cgen_eface(n, &n1);
+ cgen(&n1, res);
+ } else
+ cgen_eface(n, res);
+ return;
}
while(n->op == OCONVNOP)
agen(&n1, res);
break;
+ case OEFACE:
+ tempname(&n1, n->type);
+ cgen_eface(n, &n1);
+ agen(&n1, res);
+ break;
+
case OINDEX:
p2 = nil; // to be patched to panicindex.
w = n->type->width;
;
}
+/*
+ * generate:
+ * res = iface{typ, data}
+ * n->left is typ
+ * n->right is data
+ */
+void
+cgen_eface(Node *n, Node *res)
+{
+ Node dst;
+ dst = *res;
+ dst.type = types[tptr];
+ cgen(n->left, &dst);
+ dst.xoffset += widthptr;
+ cgen(n->right, &dst);
+}
/*
* generate:
* n->left is s
* n->list is (cap(s)-lo(TUINT32), hi-lo(TUINT32)[, lo*width(TUINTPTR)])
* caller (cgen) guarantees res is an addable ONAME.
- *
*/
void
cgen_slice(Node *n, Node *res)
{
Node src, dst, *cap, *len, *offs, *add;
-// print("cgen_slice: %N = %+N\n", res, n);
-
cap = n->list->n;
len = n->list->next->n;
offs = N;
ODDD,
ODDDARG,
OINLCALL, // intermediary representation of an inlined call
+ OEFACE, // itable and data words of empty-interface value
OITAB, // itable word of interface value
// for back ends
void addrescapes(Node *n);
void cgen_as(Node *nl, Node *nr);
void cgen_callmeth(Node *n, int proc);
+void cgen_eface(Node* n, Node* res);
void cgen_slice(Node* n, Node* res);
void clearlabels(void);
void checklabels(void);
walkexpr(&n->left, init);
goto ret;
+ case OEFACE:
+ walkexpr(&n->left, init);
+ walkexpr(&n->right, init);
+ goto ret;
+
case OITAB:
walkexpr(&n->left, init);
goto ret;
goto ret;
case OCONVIFACE:
+ walkexpr(&n->left, init);
+
+ // Optimize convT2E as a two-word copy when T is uintptr-shaped.
+ if(!isinter(n->left->type) && isnilinter(n->type) &&
+ (n->left->type->width == widthptr) &&
+ isint[simsimtype(n->left->type)]) {
+ l = nod(OEFACE, typename(n->left->type), n->left);
+ l->type = n->type;
+ l->typecheck = n->typecheck;
+ n = l;
+ goto ret;
+ }
+
// Build name of function: convI2E etc.
// Not all names are possible
// (e.g., we'll never generate convE2E or convE2I).
- walkexpr(&n->left, init);
strcpy(buf, "conv");
p = buf+strlen(buf);
if(isnilinter(n->left->type))
Big [2]*int
)
-func BenchmarkConvT2E(b *testing.B) {
+func BenchmarkConvT2ESmall(b *testing.B) {
for i := 0; i < b.N; i++ {
- I = 1
+ I = uint16(1)
+ }
+}
+
+func BenchmarkConvT2EUintptr(b *testing.B) {
+ for i := 0; i < b.N; i++ {
+ I = uintptr(1)
}
}
func BenchmarkConvT2EBig(b *testing.B) {
- v := [2]*int{}
+ v := [2]uintptr{1, 2}
for i := 0; i < b.N; i++ {
I = v
}
--- /dev/null
+// run
+
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Test conversion from non-interface types to the empty interface.
+
+package main
+
+var (
+ z = struct{}{}
+ p = &z
+ pp = &p
+ u16 = uint16(1)
+ u32 = uint32(2)
+ u64 = uint64(3)
+ u128 = [2]uint64{4, 5}
+ f32 = float32(6)
+ f64 = float64(7)
+ c128 = complex128(8 + 9i)
+ s = "10"
+ b = []byte("11")
+ m = map[int]int{12: 13}
+ c = make(chan int, 14)
+)
+
+var (
+ iz interface{} = z
+ ip interface{} = p
+ ipp interface{} = pp
+ iu16 interface{} = u16
+ iu32 interface{} = u32
+ iu64 interface{} = u64
+ iu128 interface{} = u128
+ if32 interface{} = f32
+ if64 interface{} = f64
+ ic128 interface{} = c128
+ is interface{} = s
+ ib interface{} = b
+ im interface{} = m
+ ic interface{} = c
+)
+
+func second(a ...interface{}) interface{} {
+ return a[1]
+}
+
+func main() {
+ // Test equality. There are no tests for b and m, as slices and
+ // maps are not comparable by ==.
+ if z != iz {
+ panic("z != iz")
+ }
+ if p != ip {
+ panic("p != ip")
+ }
+ if pp != ipp {
+ panic("pp != ipp")
+ }
+ if u16 != iu16 {
+ panic("u16 != iu16")
+ }
+ if u32 != iu32 {
+ panic("u32 != iu32")
+ }
+ if u64 != iu64 {
+ panic("u64 != iu64")
+ }
+ if u128 != iu128 {
+ panic("u128 != iu128")
+ }
+ if f32 != if32 {
+ panic("f32 != if32")
+ }
+ if f64 != if64 {
+ panic("f64 != if64")
+ }
+ if c128 != ic128 {
+ panic("c128 != ic128")
+ }
+ if s != is {
+ panic("s != is")
+ }
+ if c != ic {
+ panic("c != ic")
+ }
+
+ // Test that non-interface types can be used as ...interface{} arguments.
+ if got := second(z, p, pp, u16, u32, u64, u128, f32, f64, c128, s, b, m, c); got != ip {
+ println("second: got", got, "want", ip)
+ panic("fail")
+ }
+
+ // Test that non-interface types can be sent on a chan interface{}.
+ const n = 100
+ uc := make(chan interface{})
+ go func() {
+ for i := 0; i < n; i++ {
+ select {
+ case uc <- nil:
+ case uc <- u32:
+ case uc <- u64:
+ case uc <- u128:
+ }
+ }
+ }()
+ for i := 0; i < n; i++ {
+ if got := <-uc; got != nil && got != u32 && got != u64 && got != u128 {
+ println("recv: i", i, "got", got)
+ panic("fail")
+ }
+ }
+}