mirror of
https://github.com/golang/go
synced 2024-11-12 08:10:21 -07:00
cmd/gc: enable inlining in generated method wrappers.
Method calls on interfaces with large stored values will call the pointer receiver method which may be a wrapper over a method with value receiver. This is particularly inefficient for very small bodies. Inlining the wrapped method body saves a potentially expensive function call. benchmark old ns/op new ns/op delta BenchmarkSortString1K 802295 641387 -20.06% BenchmarkSortInt1K 359914 238234 -33.81% BenchmarkSortInt64K 35764226 22803078 -36.24% Fixes #4707. R=golang-dev, daniel.morsing, rsc CC=golang-dev https://golang.org/cl/7214044
This commit is contained in:
parent
404e4a90cb
commit
386ad0ab90
@ -565,24 +565,31 @@ mkinlcall1(Node **np, Node *fn, int isddd)
|
|||||||
inlretvars = nil;
|
inlretvars = nil;
|
||||||
i = 0;
|
i = 0;
|
||||||
// Make temp names to use instead of the originals
|
// Make temp names to use instead of the originals
|
||||||
for(ll = dcl; ll; ll=ll->next)
|
for(ll = dcl; ll; ll=ll->next) {
|
||||||
|
if(ll->n->class == PPARAMOUT) // return values handled below.
|
||||||
|
continue;
|
||||||
if(ll->n->op == ONAME) {
|
if(ll->n->op == ONAME) {
|
||||||
ll->n->inlvar = inlvar(ll->n);
|
ll->n->inlvar = inlvar(ll->n);
|
||||||
// Typecheck because inlvar is not necessarily a function parameter.
|
// Typecheck because inlvar is not necessarily a function parameter.
|
||||||
typecheck(&ll->n->inlvar, Erv);
|
typecheck(&ll->n->inlvar, Erv);
|
||||||
if ((ll->n->class&~PHEAP) != PAUTO)
|
if ((ll->n->class&~PHEAP) != PAUTO)
|
||||||
ninit = list(ninit, nod(ODCL, ll->n->inlvar, N)); // otherwise gen won't emit the allocations for heapallocs
|
ninit = list(ninit, nod(ODCL, ll->n->inlvar, N)); // otherwise gen won't emit the allocations for heapallocs
|
||||||
if (ll->n->class == PPARAMOUT) // we rely on the order being correct here
|
|
||||||
inlretvars = list(inlretvars, ll->n->inlvar);
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// anonymous return values, synthesize names for use in assignment that replaces return
|
// temporaries for return values.
|
||||||
if(inlretvars == nil && fn->type->outtuple > 0)
|
for(t = getoutargx(fn->type)->type; t; t = t->down) {
|
||||||
for(t = getoutargx(fn->type)->type; t; t = t->down) {
|
if(t != T && t->nname != N && !isblank(t->nname)) {
|
||||||
|
m = inlvar(t->nname);
|
||||||
|
typecheck(&m, Erv);
|
||||||
|
t->nname->inlvar = m;
|
||||||
|
} else {
|
||||||
|
// anonymous return values, synthesize names for use in assignment that replaces return
|
||||||
m = retvar(t, i++);
|
m = retvar(t, i++);
|
||||||
ninit = list(ninit, nod(ODCL, m, N));
|
|
||||||
inlretvars = list(inlretvars, m);
|
|
||||||
}
|
}
|
||||||
|
ninit = list(ninit, nod(ODCL, m, N));
|
||||||
|
inlretvars = list(inlretvars, m);
|
||||||
|
}
|
||||||
|
|
||||||
// assign receiver.
|
// assign receiver.
|
||||||
if(fn->type->thistuple && n->left->op == ODOTMETH) {
|
if(fn->type->thistuple && n->left->op == ODOTMETH) {
|
||||||
|
@ -16,6 +16,8 @@ static void dumpglobls(void);
|
|||||||
void
|
void
|
||||||
dumpobj(void)
|
dumpobj(void)
|
||||||
{
|
{
|
||||||
|
NodeList *externs, *tmp;
|
||||||
|
|
||||||
bout = Bopen(outfile, OWRITE);
|
bout = Bopen(outfile, OWRITE);
|
||||||
if(bout == nil) {
|
if(bout == nil) {
|
||||||
flusherrors();
|
flusherrors();
|
||||||
@ -31,8 +33,20 @@ dumpobj(void)
|
|||||||
|
|
||||||
outhist(bout);
|
outhist(bout);
|
||||||
|
|
||||||
|
externs = nil;
|
||||||
|
if(externdcl != nil)
|
||||||
|
externs = externdcl->end;
|
||||||
|
|
||||||
dumpglobls();
|
dumpglobls();
|
||||||
dumptypestructs();
|
dumptypestructs();
|
||||||
|
|
||||||
|
// Dump extra globals.
|
||||||
|
tmp = externdcl;
|
||||||
|
if(externs != nil)
|
||||||
|
externdcl = externs->next;
|
||||||
|
dumpglobls();
|
||||||
|
externdcl = tmp;
|
||||||
|
|
||||||
dumpdata();
|
dumpdata();
|
||||||
dumpfuncs();
|
dumpfuncs();
|
||||||
|
|
||||||
|
@ -2565,6 +2565,7 @@ genwrapper(Type *rcvr, Type *method, Sym *newnam, int iface)
|
|||||||
fn->dupok = 1;
|
fn->dupok = 1;
|
||||||
typecheck(&fn, Etop);
|
typecheck(&fn, Etop);
|
||||||
typechecklist(fn->nbody, Etop);
|
typechecklist(fn->nbody, Etop);
|
||||||
|
inlcalls(fn);
|
||||||
curfn = nil;
|
curfn = nil;
|
||||||
funccompile(fn, 0);
|
funccompile(fn, 0);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user