Commit 77db737a authored by Rick Hudson's avatar Rick Hudson

[dev.garbage] runtime: Add gc mark verification pass.

This adds an independent mark phase to the GC that can be used to
verify the the default concurrent mark phase has found all reachable
objects. It uses the upper 2 bits of the boundary nibble to encode
the mark leaving the lower bits to encode the boundary and the
normal mark bit.

LGTM=rsc
R=rsc
CC=golang-codereviews
https://golang.org/cl/167130043
parent b035e973
......@@ -259,20 +259,7 @@ dumpbv(BitVector *bv, uintptr offset)
dumpint(offset + i / BitsPerPointer * PtrSize);
break;
case BitsMultiWord:
switch(bv->bytedata[(i+BitsPerPointer)/8] >> (i+BitsPerPointer)%8 & 3) {
default:
runtime·throw("unexpected garbage collection bits");
case BitsIface:
dumpint(FieldKindIface);
dumpint(offset + i / BitsPerPointer * PtrSize);
i += BitsPerPointer;
break;
case BitsEface:
dumpint(FieldKindEface);
dumpint(offset + i / BitsPerPointer * PtrSize);
i += BitsPerPointer;
break;
}
runtime·throw("bumpbv unexpected garbage collection bits");
}
}
}
......
......@@ -306,6 +306,18 @@ func mallocgc(size uintptr, typ *_type, flags int) unsafe.Pointer {
}
}
marked:
// GCmarkterminate allocates black
// All slots hold nil so no scanning is needed.
// This may be racing with GC so do it atomically if there can be
// a race marking the bit.
if gcphase == _GCmarktermination {
mp := acquirem()
mp.ptrarg[0] = x
onM(gcmarknewobject_m)
releasem(mp)
}
if raceenabled {
racemalloc(x, size)
}
......@@ -478,8 +490,12 @@ func gogc(force int32) {
// Do a concurrent heap scan before we stop the world.
onM(gcscan_m)
onM(gcinstallmarkwb_m)
onM(stoptheworld)
// onM(starttheworld)
// mark from roots scanned in gcscan_m. startthework when write barrier works
onM(gcmark_m)
// onM(stoptheworld)
if mp != acquirem() {
gothrow("gogc: rescheduled")
}
......@@ -510,6 +526,8 @@ func gogc(force int32) {
onM(gc_m)
}
onM(gccheckmark_m)
// all done
mp.gcing = 0
semrelease(&worldsema)
......@@ -524,6 +542,14 @@ func gogc(force int32) {
}
}
func GCcheckmarkenable() {
onM(gccheckmarkenable_m)
}
func GCcheckmarkdisable() {
onM(gccheckmarkdisable_m)
}
// GC runs a garbage collection.
func GC() {
gogc(2)
......
This diff is collapsed.
......@@ -45,8 +45,12 @@ enum {
// If you change these, also change scanblock.
// scanblock does "if(bits == BitsScalar || bits == BitsDead)" as "if(bits <= BitsScalar)".
BitsDead = 0,
BitsScalar = 1,
BitsPointer = 2,
BitsScalar = 1, // 01
BitsPointer = 2, // 10
BitsCheckMarkXor = 1, // 10
BitsScalarMarked = BitsScalar ^ BitsCheckMarkXor, // 00
BitsPointerMarked = BitsPointer ^ BitsCheckMarkXor, // 11
BitsMultiWord = 3,
// BitsMultiWord will be set for the first word of a multi-word item.
// When it is set, one of the following will be set for the second word.
......
......@@ -382,8 +382,6 @@ adjustpointers(byte **scanp, BitVector *bv, AdjustInfo *adjinfo, Func *f)
uintptr delta;
int32 num, i;
byte *p, *minp, *maxp;
Type *t;
Itab *tab;
minp = (byte*)adjinfo->old.lo;
maxp = (byte*)adjinfo->old.hi;
......@@ -415,43 +413,7 @@ adjustpointers(byte **scanp, BitVector *bv, AdjustInfo *adjinfo, Func *f)
}
break;
case BitsMultiWord:
switch(bv->bytedata[(i+1) / (8 / BitsPerPointer)] >> ((i+1) * BitsPerPointer & 7) & 3) {
default:
runtime·throw("unexpected garbage collection bits");
case BitsEface:
t = (Type*)scanp[i];
if(t != nil && ((t->kind & KindDirectIface) == 0 || (t->kind & KindNoPointers) == 0)) {
p = scanp[i+1];
if(minp <= p && p < maxp) {
if(StackDebug >= 3)
runtime·printf("adjust eface %p\n", p);
if(t->size > PtrSize) // currently we always allocate such objects on the heap
runtime·throw("large interface value found on stack");
scanp[i+1] = p + delta;
}
}
i++;
break;
case BitsIface:
tab = (Itab*)scanp[i];
if(tab != nil) {
t = tab->type;
//runtime·printf(" type=%p\n", t);
if((t->kind & KindDirectIface) == 0 || (t->kind & KindNoPointers) == 0) {
p = scanp[i+1];
if(minp <= p && p < maxp) {
if(StackDebug >= 3)
runtime·printf("adjust iface %p\n", p);
if(t->size > PtrSize) // currently we always allocate such objects on the heap
runtime·throw("large interface value found on stack");
scanp[i+1] = p + delta;
}
}
}
i++;
break;
}
break;
runtime·throw("adjustpointers: unexpected garbage collection bits");
}
}
}
......
......@@ -107,6 +107,12 @@ func mcacheRefill_m()
func largeAlloc_m()
func gc_m()
func gcscan_m()
func gcmark_m()
func gccheckmark_m()
func gccheckmarkenable_m()
func gccheckmarkdisable_m()
func gcinstallmarkwb_m()
func gcmarknewobject_m()
func finishsweep_m()
func scavenge_m()
func setFinalizer_m()
......
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