Commit 21ea5103 authored by Carl Shapiro's avatar Carl Shapiro

cmd/gc, runtime: use type information to scan interface values

R=golang-dev, rsc, dvyukov
CC=golang-dev
https://golang.org/cl/12785045
parent 2f6e9a1e
...@@ -257,7 +257,6 @@ walktype1(Type *t, vlong *xoffset, Bvec *bv) ...@@ -257,7 +257,6 @@ walktype1(Type *t, vlong *xoffset, Bvec *bv)
bvset(bv, ((*xoffset / widthptr) * BitsPerPointer) + 1); bvset(bv, ((*xoffset / widthptr) * BitsPerPointer) + 1);
if(isnilinter(t)) if(isnilinter(t))
bvset(bv, ((*xoffset / widthptr) * BitsPerPointer)); bvset(bv, ((*xoffset / widthptr) * BitsPerPointer));
bvset(bv, ((*xoffset + widthptr) / widthptr) * BitsPerPointer);
*xoffset += t->width; *xoffset += t->width;
break; break;
......
...@@ -36,6 +36,10 @@ enum { ...@@ -36,6 +36,10 @@ enum {
// Pointer map // Pointer map
BitsPerPointer = 2, BitsPerPointer = 2,
BitsNoPointer = 0,
BitsPointer = 1,
BitsIface = 2,
BitsEface = 3,
}; };
// Bits in per-word bitmap. // Bits in per-word bitmap.
...@@ -1398,26 +1402,52 @@ struct BitVector ...@@ -1398,26 +1402,52 @@ struct BitVector
uint32 data[]; uint32 data[];
}; };
// Scans an interface data value when the interface type indicates
// that it is a pointer.
static void
scaninterfacedata(uintptr bits, byte *scanp, bool inprologue)
{
Itab *tab;
Type *type;
if(!inprologue) {
if(bits == BitsIface) {
tab = *(Itab**)scanp;
if(tab->type->size <= sizeof(void*) && (tab->type->kind & KindNoPointers))
return;
} else { // bits == BitsEface
type = *(Type**)scanp;
if(type->size <= sizeof(void*) && (type->kind & KindNoPointers))
return;
}
}
addroot((Obj){scanp+PtrSize, PtrSize, 0});
}
// Starting from scanp, scans words corresponding to set bits. // Starting from scanp, scans words corresponding to set bits.
static void static void
scanbitvector(byte *scanp, BitVector *bv) scanbitvector(byte *scanp, BitVector *bv, bool inprologue)
{ {
uint32 *wp; uintptr word, bits;
uint32 w; uint32 *wordp;
int32 i, remptrs; int32 i, remptrs;
wp = bv->data; wordp = bv->data;
for(remptrs = bv->n; remptrs > 0; remptrs -= 32) { for(remptrs = bv->n; remptrs > 0; remptrs -= 32) {
w = *wp++; word = *wordp++;
if(remptrs < 32) if(remptrs < 32)
i = remptrs; i = remptrs;
else else
i = 32; i = 32;
i /= BitsPerPointer; i /= BitsPerPointer;
for(; i > 0; i--) { for(; i > 0; i--) {
if(w & 3) bits = word & 3;
if(bits != BitsNoPointer && *(void**)scanp != nil)
if(bits == BitsPointer)
addroot((Obj){scanp, PtrSize, 0}); addroot((Obj){scanp, PtrSize, 0});
w >>= BitsPerPointer; else
scaninterfacedata(bits, scanp, inprologue);
word >>= BitsPerPointer;
scanp += PtrSize; scanp += PtrSize;
} }
} }
...@@ -1430,12 +1460,14 @@ addframeroots(Stkframe *frame, void*) ...@@ -1430,12 +1460,14 @@ addframeroots(Stkframe *frame, void*)
Func *f; Func *f;
BitVector *args, *locals; BitVector *args, *locals;
uintptr size; uintptr size;
bool afterprologue;
f = frame->fn; f = frame->fn;
// Scan local variables if stack frame has been allocated. // Scan local variables if stack frame has been allocated.
// Use pointer information if known. // Use pointer information if known.
if(frame->varp > (byte*)frame->sp) { afterprologue = (frame->varp > (byte*)frame->sp);
if(afterprologue) {
locals = runtime·funcdata(f, FUNCDATA_GCLocals); locals = runtime·funcdata(f, FUNCDATA_GCLocals);
if(locals == nil) { if(locals == nil) {
// No locals information, scan everything. // No locals information, scan everything.
...@@ -1450,7 +1482,7 @@ addframeroots(Stkframe *frame, void*) ...@@ -1450,7 +1482,7 @@ addframeroots(Stkframe *frame, void*)
// Locals bitmap information, scan just the // Locals bitmap information, scan just the
// pointers in locals. // pointers in locals.
size = (locals->n*PtrSize) / BitsPerPointer; size = (locals->n*PtrSize) / BitsPerPointer;
scanbitvector(frame->varp - size, locals); scanbitvector(frame->varp - size, locals, false);
} }
} }
...@@ -1458,7 +1490,7 @@ addframeroots(Stkframe *frame, void*) ...@@ -1458,7 +1490,7 @@ addframeroots(Stkframe *frame, void*)
// Use pointer information if known. // Use pointer information if known.
args = runtime·funcdata(f, FUNCDATA_GCArgs); args = runtime·funcdata(f, FUNCDATA_GCArgs);
if(args != nil && args->n > 0) if(args != nil && args->n > 0)
scanbitvector(frame->argp, args); scanbitvector(frame->argp, args, !afterprologue);
else else
addroot((Obj){frame->argp, frame->arglen, 0}); addroot((Obj){frame->argp, frame->arglen, 0});
} }
......
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