Skip to content

Commit

Permalink
cmd/gc, reflect, runtime: switch to indirect func value representation
Browse files Browse the repository at this point in the history
Step 1 of http://golang.org/s/go11func.

R=golang-dev, r, daniel.morsing, remyoudompheng
CC=golang-dev
https://golang.org/cl/7393045
  • Loading branch information
rsc committed Feb 21, 2013
1 parent 4335e69 commit 1903ad7
Show file tree
Hide file tree
Showing 38 changed files with 316 additions and 89 deletions.
2 changes: 1 addition & 1 deletion src/cmd/5g/gg.h
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,7 @@ int isfat(Type*);
int dotaddable(Node*, Node*);
void sudoclean(void);
int sudoaddable(int, Node*, Addr*, int*);
void afunclit(Addr*);
void afunclit(Addr*, Node*);
void datagostring(Strlit*, Addr*);
void split64(Node*, Node*, Node*);
void splitclean(void);
Expand Down
39 changes: 33 additions & 6 deletions src/cmd/5g/ggen.c
Original file line number Diff line number Diff line change
Expand Up @@ -52,15 +52,17 @@ fixautoused(Prog* p)
/*
* generate:
* call f
* proc=-1 normal call but no return
* proc=0 normal call
* proc=1 goroutine run in new proc
* proc=2 defer call save away stack
* proc=3 normal call to C pointer (not Go func value)
*/
void
ginscall(Node *f, int proc)
{
Prog *p;
Node n1, r, con;
Node n1, r, r1, con;

switch(proc) {
default:
Expand All @@ -69,10 +71,24 @@ ginscall(Node *f, int proc)

case 0: // normal call
case -1: // normal call but no return
p = gins(ABL, N, f);
afunclit(&p->to);
if(proc == -1 || noreturn(p))
gins(AUNDEF, N, N);
if(f->op == ONAME && f->class == PFUNC) {
p = gins(ABL, N, f);
afunclit(&p->to, f);
if(proc == -1 || noreturn(p))
gins(AUNDEF, N, N);
break;
}
nodreg(&r, types[tptr], 0);
nodreg(&r1, types[tptr], 1);
gmove(f, &r);
r.op = OINDREG;
gmove(&r, &r1);
r1.op = OINDREG;
gins(ABL, N, &r1);
break;

case 3: // normal call of c function pointer
gins(ABL, N, f);
break;

case 1: // call in new proc (go)
Expand Down Expand Up @@ -139,6 +155,7 @@ cgen_callinter(Node *n, Node *res, int proc)
int r;
Node *i, *f;
Node tmpi, nodo, nodr, nodsp;
Prog *p;

i = n->left;
if(i->op != ODOTINTER)
Expand Down Expand Up @@ -183,7 +200,17 @@ cgen_callinter(Node *n, Node *res, int proc)
cgen(&nodo, &nodr); // REG = 0(REG) -- i.tab

nodo.xoffset = n->left->xoffset + 3*widthptr + 8;
cgen(&nodo, &nodr); // REG = 20+offset(REG) -- i.tab->fun[f]

if(proc == 0) {
// plain call: use direct c function pointer - more efficient
cgen(&nodo, &nodr); // REG = 20+offset(REG) -- i.tab->fun[f]
nodr.op = OINDREG;
proc = 3;
} else {
// go/defer. generate go func value.
p = gins(AMOVW, &nodo, &nodr);
p->from.type = D_CONST; // REG = &(20+offset(REG)) -- i.tab->fun[f]
}

// BOTCH nodr.type = fntype;
nodr.type = n->left->type;
Expand Down
5 changes: 4 additions & 1 deletion src/cmd/5g/gsubr.c
Original file line number Diff line number Diff line change
Expand Up @@ -257,10 +257,12 @@ isfat(Type *t)
* also fix up direct register references to be D_OREG.
*/
void
afunclit(Addr *a)
afunclit(Addr *a, Node *n)
{
if(a->type == D_CONST && a->name == D_EXTERN || a->type == D_REG) {
a->type = D_OREG;
if(n->op == ONAME)
a->sym = n->sym;
}
}

Expand Down Expand Up @@ -1315,6 +1317,7 @@ naddr(Node *n, Addr *a, int canemitcode)
case PFUNC:
a->name = D_EXTERN;
a->type = D_CONST;
a->sym = funcsym(a->sym);
break;
}
break;
Expand Down
2 changes: 1 addition & 1 deletion src/cmd/6g/gg.h
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@ Plist* newplist(void);
int isfat(Type*);
void sudoclean(void);
int sudoaddable(int, Node*, Addr*);
void afunclit(Addr*);
void afunclit(Addr*, Node*);
void nodfconst(Node*, Type*, Mpflt*);
void gtrack(Sym*);

Expand Down
32 changes: 27 additions & 5 deletions src/cmd/6g/ggen.c
Original file line number Diff line number Diff line change
Expand Up @@ -50,9 +50,11 @@ fixautoused(Prog* p)
/*
* generate:
* call f
* proc=-1 normal call but no return
* proc=0 normal call
* proc=1 goroutine run in new proc
* proc=2 defer call save away stack
* proc=3 normal call to C pointer (not Go func value)
*/
void
ginscall(Node *f, int proc)
Expand All @@ -68,10 +70,23 @@ ginscall(Node *f, int proc)

case 0: // normal call
case -1: // normal call but no return
p = gins(ACALL, N, f);
afunclit(&p->to);
if(proc == -1 || noreturn(p))
gins(AUNDEF, N, N);
if(f->op == ONAME && f->class == PFUNC) {
p = gins(ACALL, N, f);
afunclit(&p->to, f);
if(proc == -1 || noreturn(p))
gins(AUNDEF, N, N);
break;
}
nodreg(&reg, types[tptr], D_AX);
nodreg(&r1, types[tptr], D_BX);
gmove(f, &reg);
reg.op = OINDREG;
gmove(&reg, &r1);
gins(ACALL, N, &r1);
break;

case 3: // normal call of c function pointer
gins(ACALL, N, f);
break;

case 1: // call in new proc (go)
Expand Down Expand Up @@ -153,7 +168,14 @@ cgen_callinter(Node *n, Node *res, int proc)
fatal("cgen_callinter: badwidth");
nodo.op = OINDREG;
nodo.xoffset = n->left->xoffset + 3*widthptr + 8;
cgen(&nodo, &nodr); // REG = 32+offset(REG) -- i.tab->fun[f]
if(proc == 0) {
// plain call: use direct c function pointer - more efficient
cgen(&nodo, &nodr); // REG = 32+offset(REG) -- i.tab->fun[f]
proc = 3;
} else {
// go/defer. generate go func value.
gins(ALEAQ, &nodo, &nodr); // REG = &(32+offset(REG)) -- i.tab->fun[f]
}

// BOTCH nodr.type = fntype;
nodr.type = n->left->type;
Expand Down
4 changes: 3 additions & 1 deletion src/cmd/6g/gsubr.c
Original file line number Diff line number Diff line change
Expand Up @@ -254,11 +254,12 @@ isfat(Type *t)
* call afunclit to fix up the argument.
*/
void
afunclit(Addr *a)
afunclit(Addr *a, Node *n)
{
if(a->type == D_ADDR && a->index == D_EXTERN) {
a->type = D_EXTERN;
a->index = D_NONE;
a->sym = n->sym;
}
}

Expand Down Expand Up @@ -1195,6 +1196,7 @@ naddr(Node *n, Addr *a, int canemitcode)
a->index = D_EXTERN;
a->type = D_ADDR;
a->width = widthptr;
a->sym = funcsym(a->sym);
break;
}
break;
Expand Down
2 changes: 1 addition & 1 deletion src/cmd/8g/gg.h
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,7 @@ int isfat(Type*);
void sudoclean(void);
int sudoaddable(int, Node*, Addr*);
int dotaddable(Node*, Node*);
void afunclit(Addr*);
void afunclit(Addr*, Node*);
void split64(Node*, Node*, Node*);
void splitclean(void);
void nswap(Node*, Node*);
Expand Down
35 changes: 29 additions & 6 deletions src/cmd/8g/ggen.c
Original file line number Diff line number Diff line change
Expand Up @@ -94,15 +94,17 @@ clearfat(Node *nl)
/*
* generate:
* call f
* proc=-1 normal call but no return
* proc=0 normal call
* proc=1 goroutine run in new proc
* proc=2 defer call save away stack
* proc=3 normal call to C pointer (not Go func value)
*/
void
ginscall(Node *f, int proc)
{
Prog *p;
Node reg, con;
Node reg, r1, con;

switch(proc) {
default:
Expand All @@ -111,10 +113,23 @@ ginscall(Node *f, int proc)

case 0: // normal call
case -1: // normal call but no return
p = gins(ACALL, N, f);
afunclit(&p->to);
if(proc == -1 || noreturn(p))
gins(AUNDEF, N, N);
if(f->op == ONAME && f->class == PFUNC) {
p = gins(ACALL, N, f);
afunclit(&p->to, f);
if(proc == -1 || noreturn(p))
gins(AUNDEF, N, N);
break;
}
nodreg(&reg, types[tptr], D_AX);
nodreg(&r1, types[tptr], D_BX);
gmove(f, &reg);
reg.op = OINDREG;
gmove(&reg, &r1);
gins(ACALL, N, &r1);
break;

case 3: // normal call of c function pointer
gins(ACALL, N, f);
break;

case 1: // call in new proc (go)
Expand Down Expand Up @@ -186,7 +201,15 @@ cgen_callinter(Node *n, Node *res, int proc)
fatal("cgen_callinter: badwidth");
nodo.op = OINDREG;
nodo.xoffset = n->left->xoffset + 3*widthptr + 8;
cgen(&nodo, &nodr); // REG = 20+offset(REG) -- i.tab->fun[f]

if(proc == 0) {
// plain call: use direct c function pointer - more efficient
cgen(&nodo, &nodr); // REG = 20+offset(REG) -- i.tab->fun[f]
proc = 3;
} else {
// go/defer. generate go func value.
gins(ALEAL, &nodo, &nodr); // REG = &(20+offset(REG)) -- i.tab->fun[f]
}

// BOTCH nodr.type = fntype;
nodr.type = n->left->type;
Expand Down
4 changes: 3 additions & 1 deletion src/cmd/8g/gsubr.c
Original file line number Diff line number Diff line change
Expand Up @@ -255,11 +255,12 @@ isfat(Type *t)
* call afunclit to fix up the argument.
*/
void
afunclit(Addr *a)
afunclit(Addr *a, Node *n)
{
if(a->type == D_ADDR && a->index == D_EXTERN) {
a->type = D_EXTERN;
a->index = D_NONE;
a->sym = n->sym;
}
}

Expand Down Expand Up @@ -2273,6 +2274,7 @@ naddr(Node *n, Addr *a, int canemitcode)
case PFUNC:
a->index = D_EXTERN;
a->type = D_ADDR;
a->sym = funcsym(a->sym);
break;
}
break;
Expand Down
18 changes: 18 additions & 0 deletions src/cmd/gc/dcl.c
Original file line number Diff line number Diff line change
Expand Up @@ -1436,3 +1436,21 @@ funccompile(Node *n, int isclosure)
funcdepth = 0;
dclcontext = PEXTERN;
}

Sym*
funcsym(Sym *s)
{
char *p;
Sym *s1;

p = smprint("%s·f", s->name);
s1 = pkglookup(p, s->pkg);
free(p);
if(s1->def == N) {
s1->def = newname(s1);
s1->def->shortname = newname(s);
funcsyms = list(funcsyms, s1->def);
}
return s1;
}

2 changes: 1 addition & 1 deletion src/cmd/gc/gen.c
Original file line number Diff line number Diff line change
Expand Up @@ -281,7 +281,7 @@ gen(Node *n)

switch(n->op) {
default:
fatal("gen: unknown op %N", n);
fatal("gen: unknown op %+hN", n);
break;

case OCASE:
Expand Down
2 changes: 2 additions & 0 deletions src/cmd/gc/go.h
Original file line number Diff line number Diff line change
Expand Up @@ -907,6 +907,7 @@ EXTERN NodeList* externdcl;
EXTERN NodeList* closures;
EXTERN NodeList* exportlist;
EXTERN NodeList* importlist; // imported functions and methods with inlinable bodies
EXTERN NodeList* funcsyms;
EXTERN int dclcontext; // PEXTERN/PAUTO
EXTERN int incannedimport;
EXTERN int statuniqgen; // name generator for static temps
Expand Down Expand Up @@ -1058,6 +1059,7 @@ Node* typedcl0(Sym *s);
Node* typedcl1(Node *n, Node *t, int local);
Node* typenod(Type *t);
NodeList* variter(NodeList *vl, Node *t, NodeList *el);
Sym* funcsym(Sym*);

/*
* esc.c
Expand Down
6 changes: 6 additions & 0 deletions src/cmd/gc/obj.c
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,12 @@ dumpglobls(void)

ggloblnod(n, n->type->width);
}

for(l=funcsyms; l; l=l->next) {
n = l->n;
dsymptr(n->sym, 0, n->sym->def->shortname->sym, 0);
ggloblsym(n->sym, widthptr, 1, 1);
}
}

void
Expand Down
2 changes: 1 addition & 1 deletion src/cmd/gc/pgen.c
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ compile(Node *fn)
ptxt = gins(ATEXT, isblank(curfn->nname) ? N : curfn->nname, &nod1);
if(fn->dupok)
ptxt->TEXTFLAG = DUPOK;
afunclit(&ptxt->from);
afunclit(&ptxt->from, curfn->nname);

ginit();

Expand Down
3 changes: 1 addition & 2 deletions src/cmd/gc/walk.c
Original file line number Diff line number Diff line change
Expand Up @@ -416,7 +416,7 @@ walkexpr(Node **np, NodeList **init)
switch(n->op) {
default:
dump("walk", n);
fatal("walkexpr: switch 1 unknown op %N", n);
fatal("walkexpr: switch 1 unknown op %+hN", n);
break;

case OTYPE:
Expand All @@ -442,7 +442,6 @@ walkexpr(Node **np, NodeList **init)
usefield(n);
walkexpr(&n->left, init);
goto ret;


case OEFACE:
walkexpr(&n->left, init);
Expand Down
Loading

0 comments on commit 1903ad7

Please sign in to comment.