diff options
author | Russ Cox <rsc@golang.org> | 2009-07-28 20:01:00 -0700 |
---|---|---|
committer | Russ Cox <rsc@golang.org> | 2009-07-28 20:01:00 -0700 |
commit | e585bd5cd555f24e31b50b792f86cd2057a4e203 (patch) | |
tree | 8a67b2efe49f8ab0283f63357abc34358617d955 | |
parent | 7bba2df39505a609a1d3c5a134b3707a46045c1b (diff) | |
download | golang-e585bd5cd555f24e31b50b792f86cd2057a4e203.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.c | 128 | ||||
-rw-r--r-- | src/pkg/runtime/386/closure.c | 61 | ||||
-rw-r--r-- | src/pkg/runtime/amd64/closure.c | 66 | ||||
-rw-r--r-- | test/closure.go | 12 |
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"); + } } |