1
0
mirror of https://github.com/golang/go synced 2024-09-25 05:20:13 -06: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:
Rémy Oudompheng 2013-03-11 21:24:51 +01:00
parent 404e4a90cb
commit 386ad0ab90
3 changed files with 30 additions and 8 deletions

View File

@ -565,24 +565,31 @@ mkinlcall1(Node **np, Node *fn, int isddd)
inlretvars = nil;
i = 0;
// 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) {
ll->n->inlvar = inlvar(ll->n);
// Typecheck because inlvar is not necessarily a function parameter.
typecheck(&ll->n->inlvar, Erv);
if ((ll->n->class&~PHEAP) != PAUTO)
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
if(inlretvars == nil && fn->type->outtuple > 0)
for(t = getoutargx(fn->type)->type; t; t = t->down) {
// temporaries for return values.
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++);
ninit = list(ninit, nod(ODCL, m, N));
inlretvars = list(inlretvars, m);
}
ninit = list(ninit, nod(ODCL, m, N));
inlretvars = list(inlretvars, m);
}
// assign receiver.
if(fn->type->thistuple && n->left->op == ODOTMETH) {

View File

@ -16,6 +16,8 @@ static void dumpglobls(void);
void
dumpobj(void)
{
NodeList *externs, *tmp;
bout = Bopen(outfile, OWRITE);
if(bout == nil) {
flusherrors();
@ -31,8 +33,20 @@ dumpobj(void)
outhist(bout);
externs = nil;
if(externdcl != nil)
externs = externdcl->end;
dumpglobls();
dumptypestructs();
// Dump extra globals.
tmp = externdcl;
if(externs != nil)
externdcl = externs->next;
dumpglobls();
externdcl = tmp;
dumpdata();
dumpfuncs();

View File

@ -2565,6 +2565,7 @@ genwrapper(Type *rcvr, Type *method, Sym *newnam, int iface)
fn->dupok = 1;
typecheck(&fn, Etop);
typechecklist(fn->nbody, Etop);
inlcalls(fn);
curfn = nil;
funccompile(fn, 0);
}