mirror of
https://github.com/golang/go.git
synced 2025-05-07 16:43:03 +00:00
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
This commit is contained in:
parent
83940d7c4a
commit
9346c6d901
128
src/cmd/gc/dcl.c
128
src/cmd/gc/dcl.c
@ -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);
|
||||||
|
n->type = ptrto(a->type);
|
||||||
|
n->class = PPARAM;
|
||||||
|
n->xoffset = narg*types[tptr]->width;
|
||||||
|
n->addable = 1;
|
||||||
|
n->ullman = 1;
|
||||||
|
narg++;
|
||||||
|
a->heapaddr = n;
|
||||||
|
|
||||||
// now the original arguments.
|
a->xoffset = 0;
|
||||||
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;
|
// unlink from actual ONAME in symbol table
|
||||||
if(a != N) {
|
a->closure->closure = a->outer;
|
||||||
if(a->stackparam != N)
|
|
||||||
a = a->stackparam;
|
|
||||||
a->xoffset += shift;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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.
|
// 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)
|
|||||||
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
|
||||||
|
@ -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
|
// SUBL $siz, SP
|
||||||
*p++ = 0xbe;
|
*p++ = 0x81;
|
||||||
*(byte**)p = q;
|
*p++ = 0xec;
|
||||||
p += 4;
|
*(uint32*)p = siz;
|
||||||
|
|
||||||
// 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;
|
p += 4;
|
||||||
|
|
||||||
// REP; MOVSL
|
// MOVL $q, SI
|
||||||
*p++ = 0xf3;
|
*p++ = 0xbe;
|
||||||
*p++ = 0xa5;
|
*(byte**)p = q;
|
||||||
|
p += 4;
|
||||||
|
|
||||||
|
// 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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// call fn
|
// call fn
|
||||||
|
@ -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() {
|
|||||||
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() {
|
|||||||
|
|
||||||
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");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user