diff options
| author | Austin Clements <austin@google.com> | 2017-12-08 22:24:59 -0500 |
|---|---|---|
| committer | Austin Clements <austin@google.com> | 2018-02-15 21:12:17 +0000 |
| commit | f61057c497e9ccb88dae093778d97aeee941af13 (patch) | |
| tree | 4192f575e03e42c259a5b3872e27bfc8df55680b /src/runtime | |
| parent | 29e9c4d4a4064fcd5edcb47d4782bd96082a068e (diff) | |
| download | go-f61057c497e9ccb88dae093778d97aeee941af13.tar.xz | |
runtime: fix various contiguous bitmap assumptions
There are various places that assume the heap bitmap is contiguous and
scan it sequentially. We're about to split up the heap bitmap. This
commit modifies all of these except heapBitsSetType to use the
heapBits abstractions so they can transparently switch to a
discontiguous bitmap.
Updates #10460. This is a step toward supporting sparse heaps.
Change-Id: I2f3994a5785e4dccb66602fb3950bbd290d9392c
Reviewed-on: https://go-review.googlesource.com/85882
Run-TryBot: Austin Clements <austin@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Rick Hudson <rlh@golang.org>
Diffstat (limited to 'src/runtime')
| -rw-r--r-- | src/runtime/mbitmap.go | 52 |
1 files changed, 32 insertions, 20 deletions
diff --git a/src/runtime/mbitmap.go b/src/runtime/mbitmap.go index 8e414ecaf3..e4f6b52b88 100644 --- a/src/runtime/mbitmap.go +++ b/src/runtime/mbitmap.go @@ -86,8 +86,9 @@ const ( bitPointer = 1 << 0 bitScan = 1 << 4 - heapBitsShift = 1 // shift offset between successive bitPointer or bitScan entries - heapBitmapScale = sys.PtrSize * (8 / 2) // number of data bytes described by one heap bitmap byte + heapBitsShift = 1 // shift offset between successive bitPointer or bitScan entries + heapBitmapScale = sys.PtrSize * (8 / 2) // number of data bytes described by one heap bitmap byte + wordsPerBitmapByte = 8 / 2 // heap words described by one bitmap byte // all scan/pointer bits in a byte bitScanAll = bitScan | bitScan<<heapBitsShift | bitScan<<(2*heapBitsShift) | bitScan<<(3*heapBitsShift) @@ -460,6 +461,14 @@ func (h heapBits) forward(n uintptr) heapBits { return heapBits{addb(h.bitp, n/4), uint32(n%4) * heapBitsShift} } +// forwardOrBoundary is like forward, but stops at boundaries between +// contiguous sections of the bitmap. It returns the number of words +// advanced over, which will be <= n. +func (h heapBits) forwardOrBoundary(n uintptr) (heapBits, uintptr) { + // The bitmap is contiguous right now, so this is just forward. + return h.forward(n), n +} + // The caller can test morePointers and isPointer by &-ing with bitScan and bitPointer. // The result includes in its higher bits the bits for subsequent words // described by the same bitmap byte. @@ -717,23 +726,28 @@ func (h heapBits) initSpan(s *mspan) { s.allocBits = newAllocBits(s.nelems) // Clear bits corresponding to objects. - if total%heapBitmapScale != 0 { + nw := total / sys.PtrSize + if nw%wordsPerBitmapByte != 0 { throw("initSpan: unaligned length") } if h.shift != 0 { throw("initSpan: unaligned base") } - nbyte := total / heapBitmapScale - if sys.PtrSize == 8 && size == sys.PtrSize { - bitp := h.bitp - end := addb(bitp, nbyte) - for bitp != end { - *bitp = bitPointerAll | bitScanAll - bitp = add1(bitp) + for nw > 0 { + hNext, anw := h.forwardOrBoundary(nw) + nbyte := anw / wordsPerBitmapByte + if sys.PtrSize == 8 && size == sys.PtrSize { + bitp := h.bitp + for i := uintptr(0); i < nbyte; i++ { + *bitp = bitPointerAll | bitScanAll + bitp = add1(bitp) + } + } else { + memclrNoHeapPointers(unsafe.Pointer(h.bitp), nbyte) } - return + h = hNext + nw -= anw } - memclrNoHeapPointers(unsafe.Pointer(h.bitp), nbyte) } // initCheckmarkSpan initializes a span for being checkmarked. @@ -745,10 +759,9 @@ func (h heapBits) initCheckmarkSpan(size, n, total uintptr) { // Only possible on 64-bit system, since minimum size is 8. // Must clear type bit (checkmark bit) of every word. // The type bit is the lower of every two-bit pair. - bitp := h.bitp - for i := uintptr(0); i < n; i += 4 { - *bitp &^= bitPointerAll - bitp = add1(bitp) + for i := uintptr(0); i < n; i += wordsPerBitmapByte { + *h.bitp &^= bitPointerAll + h = h.forward(wordsPerBitmapByte) } return } @@ -769,10 +782,9 @@ func (h heapBits) clearCheckmarkSpan(size, n, total uintptr) { // Only possible on 64-bit system, since minimum size is 8. // Must clear type bit (checkmark bit) of every word. // The type bit is the lower of every two-bit pair. - bitp := h.bitp - for i := uintptr(0); i < n; i += 4 { - *bitp |= bitPointerAll - bitp = add1(bitp) + for i := uintptr(0); i < n; i += wordsPerBitmapByte { + *h.bitp |= bitPointerAll + h = h.forward(wordsPerBitmapByte) } } } |
