From 11c9da27d8b3d09835a611edea424885af1ec650 Mon Sep 17 00:00:00 2001 From: Rick Hudson Date: Mon, 10 Nov 2014 14:32:02 -0500 Subject: [dev.garbage] runtime: Coarsen the write barrier to always grey the destination. LGTM=rsc R=rsc CC=golang-codereviews https://codereview.appspot.com/174820043 --- src/runtime/mgc0.c | 38 +++++++++++++++++++++++++++++++++----- 1 file changed, 33 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/runtime/mgc0.c b/src/runtime/mgc0.c index 5300f554b..3f6cce5c0 100644 --- a/src/runtime/mgc0.c +++ b/src/runtime/mgc0.c @@ -1056,13 +1056,41 @@ shade(byte *b) return; } -// This is the Dijkstra barrier coarsened to shade grey to white whereas -// the original Dijkstra barrier only shaded black to white. +// This is the Dijkstra barrier coarsened to always shade the ptr (dst) object. +// The original Dijkstra barrier only shaded ptrs being placed in black slots. // // Shade indicates that it has seen a white pointer by adding the referent -// to wbuf. +// to wbuf as well as marking it. +// // slot is the destination (dst) in go code // ptr is the value that goes into the slot (src) in the go code +// +// Dijkstra pointed out that maintaining the no black to white +// pointers means that white to white pointers not need +// to be noted by the write barrier. Furthermore if either +// white object dies before it is reached by the +// GC then the object can be collected during this GC cycle +// instead of waiting for the next cycle. Unfortunately the cost of +// ensure that the object holding the slot doesn't concurrently +// change to black without the mutator noticing seems prohibitive. +// +// Consider the following example where the mutator writes into +// a slot and then loads the slot's mark bit while the GC thread +// writes to the slot's mark bit and then as part of scanning reads +// the slot. +// +// Initially both [slot] and [slotmark] are 0 (nil) +// Mutator thread GC thread +// st [slot], ptr st [slotmark], 1 +// +// ld r1, [slotmark] ld r2, [slot] +// +// This is a classic example of independent reads of independent writes, +// aka IRIW. The question is if r1==r2==0 is allowed and for most HW the +// answer is yes without inserting a memory barriers between the st and the ld. +// These barriers are expensive so we have decided that we will +// always grey the ptr object regardless of the slot's color. +// void runtime·gcmarkwb_m() { @@ -1081,11 +1109,11 @@ runtime·gcmarkwb_m() case GCscan: break; case GCmark: - if(ptr != nil && inheap(ptr) && shaded((byte*)slot)) + if(ptr != nil && inheap(ptr)) shade(ptr); break; case GCmarktermination: - if(ptr != nil && inheap(ptr) && shaded((byte*)slot)) + if(ptr != nil && inheap(ptr)) shade(ptr); break; } -- cgit v1.2.1