summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRuss Cox <rsc@golang.org>2009-07-28 20:01:00 -0700
committerRuss Cox <rsc@golang.org>2009-07-28 20:01:00 -0700
commit4869307ff6c636b983ddb53a8facbe4ea08519cd (patch)
tree8a67b2efe49f8ab0283f63357abc34358617d955
parentd1b8b013577b54a472f3340d10ce6a5f0b1d8ad5 (diff)
downloadgo-4869307ff6c636b983ddb53a8facbe4ea08519cd.tar.gz
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
-rw-r--r--src/cmd/gc/dcl.c128
-rw-r--r--src/pkg/runtime/386/closure.c61
-rw-r--r--src/pkg/runtime/amd64/closure.c66
-rw-r--r--test/closure.go12
4 files changed, 138 insertions, 129 deletions
diff --git a/src/cmd/gc/dcl.c b/src/cmd/gc/dcl.c
index 31393cf8a..da09cedd0 100644
--- a/src/cmd/gc/dcl.c
+++ b/src/cmd/gc/dcl.c
@@ -553,77 +553,73 @@ funclit1(Node *ntype, NodeList *body)
// as we referred to variables from the outer function,
// we accumulated a list of PHEAP names in func->cvars.
narg = 0;
- if(func->cvars == nil)
- ft = type;
- else {
- // add PHEAP versions as function arguments.
- 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
+ // add PHEAP versions as function arguments.
+ in = nil;
+ for(l=func->cvars; l; l=l->next) {
+ a = l->n;
d = nod(ODCLFIELD, a, N);
- d->type = types[TUINTPTR];
+ d->type = ptrto(a->type);
in = list(in, d);
- // slide param offset to make room for ptrs above.
- // narg+1 to skip over caller pc.
- shift = (narg+1)*types[tptr]->width;
-
- // now the original arguments.
- for(t=structfirst(&save, getinarg(type)); t; t=structnext(&save)) {
- 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;
- }
- }
+ // 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;
+ }
- // out arguments
- 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;
- }
+ // add a dummy arg for the closure's caller pc
+ d = nod(ODCLFIELD, N, N);
+ d->type = types[TUINTPTR];
+ in = list(in, d);
+
+ // slide param offset to make room for ptrs above.
+ // narg+1 to skip over caller pc.
+ shift = (narg+1)*types[tptr]->width;
+
+ // now the original arguments.
+ for(t=structfirst(&save, getinarg(type)); t; t=structnext(&save)) {
+ 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);
- ft->outnamed = type->outnamed;
+ // out arguments
+ 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.
vargen++;
snprint(namebuf, sizeof(namebuf), "_f%.3ld·%s", vargen, filename);
@@ -642,10 +638,6 @@ funclit1(Node *ntype, NodeList *body)
funcdepth--;
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.
in = nil;
d = nod(ODCLFIELD, N, N); // siz
@@ -1655,7 +1647,7 @@ variter(NodeList *vl, Node *nt, NodeList *el)
Type *tv;
NodeList *r;
Type *t;
-
+
t = T;
if(nt) {
walkexpr(nt, Etype, &nt->ninit);
diff --git a/src/pkg/runtime/386/closure.c b/src/pkg/runtime/386/closure.c
index 6ccbe3b8b..1a211bd1f 100644
--- a/src/pkg/runtime/386/closure.c
+++ b/src/pkg/runtime/386/closure.c
@@ -43,41 +43,44 @@ sys·closure(int32 siz, byte *fn, byte *arg0)
p = mal(n);
*ret = p;
q = p + n - siz;
- mcpy(q, (byte*)&arg0, siz);
- // SUBL $siz, SP
- *p++ = 0x81;
- *p++ = 0xec;
- *(uint32*)p = siz;
- p += 4;
-
- // MOVL $q, SI
- *p++ = 0xbe;
- *(byte**)p = q;
- p += 4;
+ if(siz > 0) {
+ mcpy(q, (byte*)&arg0, siz);
- // MOVL SP, DI
- *p++ = 0x89;
- *p++ = 0xe7;
+ // SUBL $siz, SP
+ *p++ = 0x81;
+ *p++ = 0xec;
+ *(uint32*)p = siz;
+ p += 4;
- // CLD
- *p++ = 0xfc;
+ // MOVL $q, SI
+ *p++ = 0xbe;
+ *(byte**)p = q;
+ p += 4;
- if(siz <= 4*4) {
- for(i=0; i<siz; i+=4) {
- // MOVSL
+ // MOVL SP, DI
+ *p++ = 0x89;
+ *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;
}
- } 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
diff --git a/src/pkg/runtime/amd64/closure.c b/src/pkg/runtime/amd64/closure.c
index 5717d3c5e..21ac7c383 100644
--- a/src/pkg/runtime/amd64/closure.c
+++ b/src/pkg/runtime/amd64/closure.c
@@ -43,47 +43,49 @@ sys·closure(int32 siz, byte *fn, byte *arg0)
p = mal(n);
*ret = p;
q = p + n - siz;
- mcpy(q, (byte*)&arg0, siz);
- // SUBQ $siz, SP
- *p++ = 0x48;
- *p++ = 0x81;
- *p++ = 0xec;
- *(uint32*)p = siz;
- p += 4;
+ if(siz > 0) {
+ mcpy(q, (byte*)&arg0, siz);
- // MOVQ $q, SI
- *p++ = 0x48;
- *p++ = 0xbe;
- *(byte**)p = q;
- p += 8;
+ // SUBQ $siz, SP
+ *p++ = 0x48;
+ *p++ = 0x81;
+ *p++ = 0xec;
+ *(uint32*)p = siz;
+ p += 4;
- // MOVQ SP, DI
- *p++ = 0x48;
- *p++ = 0x89;
- *p++ = 0xe7;
+ // MOVQ $q, SI
+ *p++ = 0x48;
+ *p++ = 0xbe;
+ *(byte**)p = q;
+ p += 8;
- if(siz <= 4*8) {
- for(i=0; i<siz; i+=8) {
- // MOVSQ
+ // MOVQ SP, DI
+ *p++ = 0x48;
+ *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++ = 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
pcrel = fn - (p+5);
if((int32)pcrel == pcrel) {
diff --git a/test/closure.go b/test/closure.go
index 97361a1df..8bb516d29 100644
--- a/test/closure.go
+++ b/test/closure.go
@@ -73,6 +73,10 @@ func h() {
f(500);
}
+func newfunc() (func(int) int) {
+ return func(x int) int { return x }
+}
+
func main() {
go f();
@@ -85,4 +89,12 @@ func main() {
go h();
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");
+ }
}