Commit 9346c6d9 authored by Russ Cox's avatar Russ Cox

make every func literal expression allocate,

so that == on func means that the
functions originated in the same
execution of a func literal or definition.

before, there was an inconsistency:

	func() {x++} != func() {x++}

but

	func() {} == func() {}

this CL makes the second case != too,
just like

	make(map[int]int) != make(map[int]int)

R=r
DELTA=202  (71 added, 62 deleted, 69 changed)
OCL=32393
CL=32398
parent 83940d7c
...@@ -553,77 +553,73 @@ funclit1(Node *ntype, NodeList *body) ...@@ -553,77 +553,73 @@ funclit1(Node *ntype, NodeList *body)
// as we referred to variables from the outer function, // as we referred to variables from the outer function,
// we accumulated a list of PHEAP names in func->cvars. // we accumulated a list of PHEAP names in func->cvars.
narg = 0; narg = 0;
if(func->cvars == nil) // add PHEAP versions as function arguments.
ft = type; in = nil;
else { for(l=func->cvars; l; l=l->next) {
// add PHEAP versions as function arguments. a = l->n;
in = nil;
for(l=func->cvars; l; l=l->next) {
a = l->n;
d = nod(ODCLFIELD, a, N);
d->type = ptrto(a->type);
in = list(in, d);
// while we're here, set up a->heapaddr for back end
n = nod(ONAME, N, N);
snprint(namebuf, sizeof namebuf, "&%s", a->sym->name);
n->sym = lookup(namebuf);
n->type = ptrto(a->type);
n->class = PPARAM;
n->xoffset = narg*types[tptr]->width;
n->addable = 1;
n->ullman = 1;
narg++;
a->heapaddr = n;
a->xoffset = 0;
// unlink from actual ONAME in symbol table
a->closure->closure = a->outer;
}
// add a dummy arg for the closure's caller pc
d = nod(ODCLFIELD, a, N); d = nod(ODCLFIELD, a, N);
d->type = types[TUINTPTR]; d->type = ptrto(a->type);
in = list(in, d); in = list(in, d);
// slide param offset to make room for ptrs above. // while we're here, set up a->heapaddr for back end
// narg+1 to skip over caller pc. n = nod(ONAME, N, N);
shift = (narg+1)*types[tptr]->width; snprint(namebuf, sizeof namebuf, "&%s", a->sym->name);
n->sym = lookup(namebuf);
// now the original arguments. n->type = ptrto(a->type);
for(t=structfirst(&save, getinarg(type)); t; t=structnext(&save)) { n->class = PPARAM;
d = nod(ODCLFIELD, t->nname, N); n->xoffset = narg*types[tptr]->width;
d->type = t->type; n->addable = 1;
in = list(in, d); n->ullman = 1;
narg++;
a = t->nname; a->heapaddr = n;
if(a != N) {
if(a->stackparam != N) a->xoffset = 0;
a = a->stackparam;
a->xoffset += shift; // unlink from actual ONAME in symbol table
} a->closure->closure = a->outer;
} }
// out arguments // add a dummy arg for the closure's caller pc
out = nil; d = nod(ODCLFIELD, N, N);
for(t=structfirst(&save, getoutarg(type)); t; t=structnext(&save)) { d->type = types[TUINTPTR];
d = nod(ODCLFIELD, t->nname, N); in = list(in, d);
d->type = t->type;
out = list(out, d); // slide param offset to make room for ptrs above.
// narg+1 to skip over caller pc.
a = t->nname; shift = (narg+1)*types[tptr]->width;
if(a != N) {
if(a->stackparam != N) // now the original arguments.
a = a->stackparam; for(t=structfirst(&save, getinarg(type)); t; t=structnext(&save)) {
a->xoffset += shift; d = nod(ODCLFIELD, t->nname, N);
} d->type = t->type;
in = list(in, d);
a = t->nname;
if(a != N) {
if(a->stackparam != N)
a = a->stackparam;
a->xoffset += shift;
} }
}
ft = functype(N, in, out); // out arguments
ft->outnamed = type->outnamed; out = nil;
for(t=structfirst(&save, getoutarg(type)); t; t=structnext(&save)) {
d = nod(ODCLFIELD, t->nname, N);
d->type = t->type;
out = list(out, d);
a = t->nname;
if(a != N) {
if(a->stackparam != N)
a = a->stackparam;
a->xoffset += shift;
}
} }
ft = functype(N, in, out);
ft->outnamed = type->outnamed;
// declare function. // declare function.
vargen++; vargen++;
snprint(namebuf, sizeof(namebuf), "_f%.3ld·%s", vargen, filename); snprint(namebuf, sizeof(namebuf), "_f%.3ld·%s", vargen, filename);
...@@ -642,10 +638,6 @@ funclit1(Node *ntype, NodeList *body) ...@@ -642,10 +638,6 @@ funclit1(Node *ntype, NodeList *body)
funcdepth--; funcdepth--;
autodcl = func->dcl; autodcl = func->dcl;
// if there's no closure, we can use f directly
if(func->cvars == nil)
return f;
// build up type for this instance of the closure func. // build up type for this instance of the closure func.
in = nil; in = nil;
d = nod(ODCLFIELD, N, N); // siz d = nod(ODCLFIELD, N, N); // siz
...@@ -1655,7 +1647,7 @@ variter(NodeList *vl, Node *nt, NodeList *el) ...@@ -1655,7 +1647,7 @@ variter(NodeList *vl, Node *nt, NodeList *el)
Type *tv; Type *tv;
NodeList *r; NodeList *r;
Type *t; Type *t;
t = T; t = T;
if(nt) { if(nt) {
walkexpr(nt, Etype, &nt->ninit); walkexpr(nt, Etype, &nt->ninit);
......
...@@ -43,41 +43,44 @@ sys·closure(int32 siz, byte *fn, byte *arg0) ...@@ -43,41 +43,44 @@ sys·closure(int32 siz, byte *fn, byte *arg0)
p = mal(n); p = mal(n);
*ret = p; *ret = p;
q = p + n - siz; q = p + n - siz;
mcpy(q, (byte*)&arg0, siz);
// SUBL $siz, SP if(siz > 0) {
*p++ = 0x81; mcpy(q, (byte*)&arg0, siz);
*p++ = 0xec;
*(uint32*)p = siz;
p += 4;
// MOVL $q, SI
*p++ = 0xbe;
*(byte**)p = q;
p += 4;
// MOVL SP, DI // SUBL $siz, SP
*p++ = 0x89; *p++ = 0x81;
*p++ = 0xe7; *p++ = 0xec;
*(uint32*)p = siz;
p += 4;
// CLD // MOVL $q, SI
*p++ = 0xfc; *p++ = 0xbe;
*(byte**)p = q;
p += 4;
if(siz <= 4*4) { // MOVL SP, DI
for(i=0; i<siz; i+=4) { *p++ = 0x89;
// MOVSL *p++ = 0xe7;
// CLD
*p++ = 0xfc;
if(siz <= 4*4) {
for(i=0; i<siz; i+=4) {
// MOVSL
*p++ = 0xa5;
}
} else {
// MOVL $(siz/4), CX [32-bit immediate siz/4]
*p++ = 0xc7;
*p++ = 0xc1;
*(uint32*)p = siz/4;
p += 4;
// REP; MOVSL
*p++ = 0xf3;
*p++ = 0xa5; *p++ = 0xa5;
} }
} else {
// MOVL $(siz/4), CX [32-bit immediate siz/4]
*p++ = 0xc7;
*p++ = 0xc1;
*(uint32*)p = siz/4;
p += 4;
// REP; MOVSL
*p++ = 0xf3;
*p++ = 0xa5;
} }
// call fn // call fn
......
...@@ -43,47 +43,49 @@ sys·closure(int32 siz, byte *fn, byte *arg0) ...@@ -43,47 +43,49 @@ sys·closure(int32 siz, byte *fn, byte *arg0)
p = mal(n); p = mal(n);
*ret = p; *ret = p;
q = p + n - siz; q = p + n - siz;
mcpy(q, (byte*)&arg0, siz);
// SUBQ $siz, SP if(siz > 0) {
*p++ = 0x48; mcpy(q, (byte*)&arg0, siz);
*p++ = 0x81;
*p++ = 0xec;
*(uint32*)p = siz;
p += 4;
// MOVQ $q, SI // SUBQ $siz, SP
*p++ = 0x48; *p++ = 0x48;
*p++ = 0xbe; *p++ = 0x81;
*(byte**)p = q; *p++ = 0xec;
p += 8; *(uint32*)p = siz;
p += 4;
// MOVQ SP, DI // MOVQ $q, SI
*p++ = 0x48; *p++ = 0x48;
*p++ = 0x89; *p++ = 0xbe;
*p++ = 0xe7; *(byte**)p = q;
p += 8;
if(siz <= 4*8) { // MOVQ SP, DI
for(i=0; i<siz; i+=8) { *p++ = 0x48;
// MOVSQ *p++ = 0x89;
*p++ = 0xe7;
if(siz <= 4*8) {
for(i=0; i<siz; i+=8) {
// MOVSQ
*p++ = 0x48;
*p++ = 0xa5;
}
} else {
// MOVQ $(siz/8), CX [32-bit immediate siz/8]
*p++ = 0x48;
*p++ = 0xc7;
*p++ = 0xc1;
*(uint32*)p = siz/8;
p += 4;
// REP; MOVSQ
*p++ = 0xf3;
*p++ = 0x48; *p++ = 0x48;
*p++ = 0xa5; *p++ = 0xa5;
} }
} else {
// MOVQ $(siz/8), CX [32-bit immediate siz/8]
*p++ = 0x48;
*p++ = 0xc7;
*p++ = 0xc1;
*(uint32*)p = siz/8;
p += 4;
// REP; MOVSQ
*p++ = 0xf3;
*p++ = 0x48;
*p++ = 0xa5;
} }
// call fn // call fn
pcrel = fn - (p+5); pcrel = fn - (p+5);
if((int32)pcrel == pcrel) { if((int32)pcrel == pcrel) {
......
...@@ -73,6 +73,10 @@ func h() { ...@@ -73,6 +73,10 @@ func h() {
f(500); f(500);
} }
func newfunc() (func(int) int) {
return func(x int) int { return x }
}
func main() { func main() {
go f(); go f();
...@@ -85,4 +89,12 @@ func main() { ...@@ -85,4 +89,12 @@ func main() {
go h(); go h();
check([]int{100,200,101,201,500,101,201,500}); check([]int{100,200,101,201,500,101,201,500});
x, y := newfunc(), newfunc();
if x == y {
panicln("newfunc returned same func");
}
if x(1) != 1 || y(2) != 2 {
panicln("newfunc returned broken funcs");
}
} }
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment