]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/gc: enable inlining in generated method wrappers.
authorRémy Oudompheng <oudomphe@phare.normalesup.org>
Mon, 11 Mar 2013 20:24:51 +0000 (21:24 +0100)
committerRémy Oudompheng <oudomphe@phare.normalesup.org>
Mon, 11 Mar 2013 20:24:51 +0000 (21:24 +0100)
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

src/cmd/gc/inl.c
src/cmd/gc/obj.c
src/cmd/gc/subr.c

index 1cc13a30452ded7d772364aad83f0fd5254a3157..f80aa9559b37acacd924abf81b0337487ba0b1ec 100644 (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) {
index b87d35b7bdcd6c2c6c2b02c070e3c215b7e1b7cd..e4bcd11703d80c9ac1ba9ba657a70077590e59e2 100644 (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();
 
index c53eaf28576447984460529eee4a382ac35f51bf..604cf1402039901aec9dfb012a3419b3929743bd 100644 (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);
 }