mirror of
https://github.com/golang/go
synced 2024-11-25 05:57:57 -07:00
gc: elide call to runtime.closure for function literals called in-place.
before: runtime_test.BenchmarkCallClosure 5000000 499 ns/op runtime_test.BenchmarkCallClosure1 5000000 681 ns/op after: runtime_test.BenchmarkCallClosure 500000000 5 ns/op runtime_test.BenchmarkCallClosure1 10000000 160 ns/op R=rsc CC=golang-dev https://golang.org/cl/4515167
This commit is contained in:
parent
6216307e25
commit
9b82408f6d
@ -199,3 +199,41 @@ walkclosure(Node *func, NodeList **init)
|
|||||||
walkexpr(&call, init);
|
walkexpr(&call, init);
|
||||||
return call;
|
return call;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Special case for closures that get called in place.
|
||||||
|
// Optimize runtime.closure(X, __func__xxxx_, .... ) away
|
||||||
|
// to __func__xxxx_(Y ....).
|
||||||
|
// On entry, expect n->op == OCALL, n->left->op == OCLOSURE.
|
||||||
|
void
|
||||||
|
walkcallclosure(Node *n, NodeList **init)
|
||||||
|
{
|
||||||
|
Node *z;
|
||||||
|
NodeList *ll, *cargs;
|
||||||
|
|
||||||
|
walkexpr(&n->left, init);
|
||||||
|
cargs = n->left // FUNC runtime.closure
|
||||||
|
->list // arguments
|
||||||
|
->next // skip first
|
||||||
|
->next; // skip second
|
||||||
|
|
||||||
|
n->left = n->left // FUNC runtime.closure
|
||||||
|
->list // arguments
|
||||||
|
->next // skip first
|
||||||
|
->n // AS (to indreg)
|
||||||
|
->right; // argument == the generated function
|
||||||
|
|
||||||
|
// New arg list for n. First the closure-args, stolen from
|
||||||
|
// runtime.closure's 3rd and following,
|
||||||
|
ll = nil;
|
||||||
|
for (; cargs; cargs = cargs->next)
|
||||||
|
ll = list(ll, cargs->n->right); // cargs->n is the OAS(INDREG, arg)
|
||||||
|
|
||||||
|
// then an extra zero, to fill the dummy return pointer slot,
|
||||||
|
z = nod(OXXX, N, N);
|
||||||
|
nodconst(z, types[TUINTPTR], 0);
|
||||||
|
z->typecheck = 1;
|
||||||
|
ll = list(ll, z);
|
||||||
|
|
||||||
|
// and finally the original parameter list.
|
||||||
|
n->list = concat(ll, n->list);
|
||||||
|
}
|
||||||
|
@ -817,6 +817,7 @@ Node* closurebody(NodeList *body);
|
|||||||
void closurehdr(Node *ntype);
|
void closurehdr(Node *ntype);
|
||||||
void typecheckclosure(Node *func);
|
void typecheckclosure(Node *func);
|
||||||
Node* walkclosure(Node *func, NodeList **init);
|
Node* walkclosure(Node *func, NodeList **init);
|
||||||
|
void walkcallclosure(Node *n, NodeList **init);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* const.c
|
* const.c
|
||||||
|
@ -770,8 +770,15 @@ walkexpr(Node **np, NodeList **init)
|
|||||||
t = n->left->type;
|
t = n->left->type;
|
||||||
if(n->list && n->list->n->op == OAS)
|
if(n->list && n->list->n->op == OAS)
|
||||||
goto ret;
|
goto ret;
|
||||||
|
|
||||||
|
if(n->left->op == OCLOSURE) {
|
||||||
|
walkcallclosure(n, init);
|
||||||
|
t = n->left->type;
|
||||||
|
} else
|
||||||
walkexpr(&n->left, init);
|
walkexpr(&n->left, init);
|
||||||
|
|
||||||
walkexprlist(n->list, init);
|
walkexprlist(n->list, init);
|
||||||
|
|
||||||
ll = ascompatte(n->op, n->isddd, getinarg(t), n->list, 0, init);
|
ll = ascompatte(n->op, n->isddd, getinarg(t), n->list, 0, init);
|
||||||
n->list = reorder1(ll);
|
n->list = reorder1(ll);
|
||||||
if(isselect(n)) {
|
if(isselect(n)) {
|
||||||
|
21
src/pkg/runtime/closure_test.go
Normal file
21
src/pkg/runtime/closure_test.go
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
// Copyright 2011 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.
|
||||||
|
package runtime_test
|
||||||
|
|
||||||
|
import "testing"
|
||||||
|
|
||||||
|
var s int
|
||||||
|
|
||||||
|
func BenchmarkCallClosure(b *testing.B) {
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
s += func(ii int) int { return 2 * ii }(i)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkCallClosure1(b *testing.B) {
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
j := i
|
||||||
|
s += func(ii int) int { return 2*ii + j }(i)
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user