mirror of
https://github.com/golang/go
synced 2024-11-13 19:10:22 -07:00
runtime: mark objects with non-atomic operations
On the go.benchmarks/garbage benchmark with GOMAXPROCS=16: old ns/op new ns/op delta time 1392254 1353170 -2.81% cputime 21995751 21373999 -2.83% gc-pause-one 15044812 13050524 -13.26% gc-pause-total 213636 185317 -13.26% LGTM=rlh R=golang-codereviews, rlh CC=golang-codereviews, khr, rsc https://golang.org/cl/123380043
This commit is contained in:
parent
ba30c082c0
commit
0c32bd6262
@ -213,7 +213,7 @@ static struct {
|
|||||||
static void
|
static void
|
||||||
scanblock(byte *b, uintptr n, byte *ptrmask)
|
scanblock(byte *b, uintptr n, byte *ptrmask)
|
||||||
{
|
{
|
||||||
byte *obj, *p, *arena_start, *arena_used, **wp, *scanbuf[8];
|
byte *obj, *p, *arena_start, *arena_used, **wp, *scanbuf[8], bits8;
|
||||||
uintptr i, nobj, size, idx, *bitp, bits, xbits, shift, x, off, cached, scanbufpos;
|
uintptr i, nobj, size, idx, *bitp, bits, xbits, shift, x, off, cached, scanbufpos;
|
||||||
intptr ncached;
|
intptr ncached;
|
||||||
Workbuf *wbuf;
|
Workbuf *wbuf;
|
||||||
@ -440,16 +440,27 @@ scanblock(byte *b, uintptr n, byte *ptrmask)
|
|||||||
// Only care about not marked objects.
|
// Only care about not marked objects.
|
||||||
if((bits&bitMarked) != 0)
|
if((bits&bitMarked) != 0)
|
||||||
continue;
|
continue;
|
||||||
if(work.nproc == 1)
|
// If obj size is greater than 8, then each byte of GC bitmap
|
||||||
*bitp |= bitMarked<<shift;
|
// contains info for at most one object. In such case we use
|
||||||
|
// non-atomic byte store to mark the object. This can lead
|
||||||
|
// to double enqueue of the object for scanning, but scanning
|
||||||
|
// is an idempotent operation, so it is OK. This cannot lead
|
||||||
|
// to bitmap corruption because the single marked bit is the
|
||||||
|
// only thing that can change in the byte.
|
||||||
|
// For 8-byte objects we use non-atomic store, if the other
|
||||||
|
// quadruple is already marked. Otherwise we resort to CAS
|
||||||
|
// loop for marking.
|
||||||
|
bits8 = xbits>>(shift&~7);
|
||||||
|
if((bits8&(bitMask|(bitMask<<gcBits))) != (bitBoundary|(bitBoundary<<gcBits)))
|
||||||
|
((uint8*)bitp)[shift/8] = bits8 | (bitMarked<<(shift&7));
|
||||||
else {
|
else {
|
||||||
for(;;) {
|
for(;;) {
|
||||||
|
if(runtime·casp((void**)bitp, (void*)xbits, (void*)(xbits|(bitMarked<<shift))))
|
||||||
|
break;
|
||||||
xbits = *bitp;
|
xbits = *bitp;
|
||||||
bits = (xbits>>shift) & bitMask;
|
bits = (xbits>>shift) & bitMask;
|
||||||
if((bits&bitMarked) != 0)
|
if((bits&bitMarked) != 0)
|
||||||
break;
|
break;
|
||||||
if(runtime·casp((void**)bitp, (void*)xbits, (void*)(xbits|(bitMarked<<shift))))
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
if((bits&bitMarked) != 0)
|
if((bits&bitMarked) != 0)
|
||||||
continue;
|
continue;
|
||||||
|
Loading…
Reference in New Issue
Block a user