]> Cypherpunks repositories - gostls13.git/commitdiff
make every func literal expression allocate,
authorRuss Cox <rsc@golang.org>
Wed, 29 Jul 2009 03:01:00 +0000 (20:01 -0700)
committerRuss Cox <rsc@golang.org>
Wed, 29 Jul 2009 03:01:00 +0000 (20:01 -0700)
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

src/cmd/gc/dcl.c
src/pkg/runtime/386/closure.c
src/pkg/runtime/amd64/closure.c
test/closure.go

index 31393cf8a1eab5f07ebb27c3ab66f457d9ae7a58..da09cedd016c4f91ec2500ad8916fb9cb29bfe7b 100644 (file)
@@ -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);
index 6ccbe3b8b6edd7d7d88f32849a17bc5577482a64..1a211bd1f36e8004d99e6ff5fa2988195604c599 100644 (file)
@@ -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
index 5717d3c5e8a4f585e00d27606b0b51ee587432c4..21ac7c38341673c040dac6cfcde36c77916d9c6d 100644 (file)
@@ -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) {
index 97361a1dfdbc28283bd5b37b9dd3c07d67850043..8bb516d29cadaaf2052d772cd34bb0eb6d2641d5 100644 (file)
@@ -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");
+       }
 }