From: Carl Shapiro Date: Wed, 21 Aug 2013 20:51:00 +0000 (-0700) Subject: undo CL 13010045 / 04f8101b46dd X-Git-Tag: go1.2rc2~461 X-Git-Url: http://www.git.cypherpunks.su/?a=commitdiff_plain;h=87fdb8fb9ab8de4e008fa7c1561b16e3df01223a;p=gostls13.git undo CL 13010045 / 04f8101b46dd Update the original change but do not read interface types in the arguments area. Once the arguments area is zeroed as the locals area is we can safely read interface type values there too. ««« original CL description undo CL 12785045 / 71ce80dc4195 This has broken the 32-bit builds. ««« original CL description cmd/gc, runtime: use type information to scan interface values R=golang-dev, rsc, dvyukov CC=golang-dev https://golang.org/cl/12785045 »»» R=khr, golang-dev, khr CC=golang-dev https://golang.org/cl/13010045 »»» R=khr, khr CC=golang-dev https://golang.org/cl/13073045 --- diff --git a/src/cmd/gc/pgen.c b/src/cmd/gc/pgen.c index f391634067..d649fc49da 100644 --- a/src/cmd/gc/pgen.c +++ b/src/cmd/gc/pgen.c @@ -257,7 +257,6 @@ walktype1(Type *t, vlong *xoffset, Bvec *bv) bvset(bv, ((*xoffset / widthptr) * BitsPerPointer) + 1); if(isnilinter(t)) bvset(bv, ((*xoffset / widthptr) * BitsPerPointer)); - bvset(bv, ((*xoffset + widthptr) / widthptr) * BitsPerPointer); *xoffset += t->width; break; diff --git a/src/pkg/runtime/mgc0.c b/src/pkg/runtime/mgc0.c index 459a980b96..7b4c6a8ba1 100644 --- a/src/pkg/runtime/mgc0.c +++ b/src/pkg/runtime/mgc0.c @@ -36,6 +36,10 @@ enum { // Pointer map BitsPerPointer = 2, + BitsNoPointer = 0, + BitsPointer = 1, + BitsIface = 2, + BitsEface = 3, }; // Bits in per-word bitmap. @@ -1398,26 +1402,52 @@ struct BitVector 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 afterprologue) +{ + Itab *tab; + Type *type; + + if(afterprologue) { + 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. static void -scanbitvector(byte *scanp, BitVector *bv) +scanbitvector(byte *scanp, BitVector *bv, bool afterprologue) { - uint32 *wp; - uint32 w; + uintptr word, bits; + uint32 *wordp; int32 i, remptrs; - wp = bv->data; + wordp = bv->data; for(remptrs = bv->n; remptrs > 0; remptrs -= 32) { - w = *wp++; + word = *wordp++; if(remptrs < 32) i = remptrs; else i = 32; i /= BitsPerPointer; for(; i > 0; i--) { - if(w & 3) - addroot((Obj){scanp, PtrSize, 0}); - w >>= BitsPerPointer; + bits = word & 3; + if(bits != BitsNoPointer && *(void**)scanp != nil) + if(bits == BitsPointer) + addroot((Obj){scanp, PtrSize, 0}); + else + scaninterfacedata(bits, scanp, afterprologue); + word >>= BitsPerPointer; scanp += PtrSize; } } @@ -1430,12 +1460,14 @@ addframeroots(Stkframe *frame, void*) Func *f; BitVector *args, *locals; uintptr size; + bool afterprologue; f = frame->fn; // Scan local variables if stack frame has been allocated. // 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); if(locals == nil) { // No locals information, scan everything. @@ -1450,7 +1482,7 @@ addframeroots(Stkframe *frame, void*) // Locals bitmap information, scan just the // pointers in locals. size = (locals->n*PtrSize) / BitsPerPointer; - scanbitvector(frame->varp - size, locals); + scanbitvector(frame->varp - size, locals, afterprologue); } } @@ -1458,7 +1490,7 @@ addframeroots(Stkframe *frame, void*) // Use pointer information if known. args = runtime·funcdata(f, FUNCDATA_GCArgs); if(args != nil && args->n > 0) - scanbitvector(frame->argp, args); + scanbitvector(frame->argp, args, false); else addroot((Obj){frame->argp, frame->arglen, 0}); }