1
0
mirror of https://github.com/golang/go synced 2024-10-02 06:28:33 -06:00

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>
This commit is contained in:
Austin Clements 2017-12-08 22:24:59 -05:00
parent 29e9c4d4a4
commit f61057c497

View File

@ -88,6 +88,7 @@ const (
heapBitsShift = 1 // shift offset between successive bitPointer or bitScan entries 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 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 // all scan/pointer bits in a byte
bitScanAll = bitScan | bitScan<<heapBitsShift | bitScan<<(2*heapBitsShift) | bitScan<<(3*heapBitsShift) 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} 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 caller can test morePointers and isPointer by &-ing with bitScan and bitPointer.
// The result includes in its higher bits the bits for subsequent words // The result includes in its higher bits the bits for subsequent words
// described by the same bitmap byte. // described by the same bitmap byte.
@ -717,23 +726,28 @@ func (h heapBits) initSpan(s *mspan) {
s.allocBits = newAllocBits(s.nelems) s.allocBits = newAllocBits(s.nelems)
// Clear bits corresponding to objects. // Clear bits corresponding to objects.
if total%heapBitmapScale != 0 { nw := total / sys.PtrSize
if nw%wordsPerBitmapByte != 0 {
throw("initSpan: unaligned length") throw("initSpan: unaligned length")
} }
if h.shift != 0 { if h.shift != 0 {
throw("initSpan: unaligned base") throw("initSpan: unaligned base")
} }
nbyte := total / heapBitmapScale for nw > 0 {
hNext, anw := h.forwardOrBoundary(nw)
nbyte := anw / wordsPerBitmapByte
if sys.PtrSize == 8 && size == sys.PtrSize { if sys.PtrSize == 8 && size == sys.PtrSize {
bitp := h.bitp bitp := h.bitp
end := addb(bitp, nbyte) for i := uintptr(0); i < nbyte; i++ {
for bitp != end {
*bitp = bitPointerAll | bitScanAll *bitp = bitPointerAll | bitScanAll
bitp = add1(bitp) bitp = add1(bitp)
} }
return } else {
}
memclrNoHeapPointers(unsafe.Pointer(h.bitp), nbyte) memclrNoHeapPointers(unsafe.Pointer(h.bitp), nbyte)
}
h = hNext
nw -= anw
}
} }
// initCheckmarkSpan initializes a span for being checkmarked. // 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. // Only possible on 64-bit system, since minimum size is 8.
// Must clear type bit (checkmark bit) of every word. // Must clear type bit (checkmark bit) of every word.
// The type bit is the lower of every two-bit pair. // The type bit is the lower of every two-bit pair.
bitp := h.bitp for i := uintptr(0); i < n; i += wordsPerBitmapByte {
for i := uintptr(0); i < n; i += 4 { *h.bitp &^= bitPointerAll
*bitp &^= bitPointerAll h = h.forward(wordsPerBitmapByte)
bitp = add1(bitp)
} }
return return
} }
@ -769,10 +782,9 @@ func (h heapBits) clearCheckmarkSpan(size, n, total uintptr) {
// Only possible on 64-bit system, since minimum size is 8. // Only possible on 64-bit system, since minimum size is 8.
// Must clear type bit (checkmark bit) of every word. // Must clear type bit (checkmark bit) of every word.
// The type bit is the lower of every two-bit pair. // The type bit is the lower of every two-bit pair.
bitp := h.bitp for i := uintptr(0); i < n; i += wordsPerBitmapByte {
for i := uintptr(0); i < n; i += 4 { *h.bitp |= bitPointerAll
*bitp |= bitPointerAll h = h.forward(wordsPerBitmapByte)
bitp = add1(bitp)
} }
} }
} }