aboutsummaryrefslogtreecommitdiff
path: root/src/runtime/mbitmap.go
diff options
context:
space:
mode:
authorRick Hudson <rlh@golang.org>2016-04-27 18:19:16 -0400
committerRick Hudson <rlh@golang.org>2016-04-27 18:46:52 -0400
commit23aeb34df172b17b7bfaa85fb59ca64bef9073bb (patch)
treea8ab866f1e50f0059856ce628f036d93ab620155 /src/runtime/mbitmap.go
parent1354b32cd70f2702381764fd595dd2faa996840c (diff)
parentd3c79d324acd7300b6f705e66af8ca711af00d9f (diff)
downloadgo-23aeb34df172b17b7bfaa85fb59ca64bef9073bb.tar.xz
[dev.garbage] Merge remote-tracking branch 'origin/master' into HEAD
Change-Id: I282fd9ce9db435dfd35e882a9502ab1abc185297
Diffstat (limited to 'src/runtime/mbitmap.go')
-rw-r--r--src/runtime/mbitmap.go63
1 files changed, 56 insertions, 7 deletions
diff --git a/src/runtime/mbitmap.go b/src/runtime/mbitmap.go
index b342de600e..af89577703 100644
--- a/src/runtime/mbitmap.go
+++ b/src/runtime/mbitmap.go
@@ -88,6 +88,7 @@ const (
// addb returns the byte pointer p+n.
//go:nowritebarrier
+//go:nosplit
func addb(p *byte, n uintptr) *byte {
// Note: wrote out full expression instead of calling add(p, n)
// to reduce the number of temporaries generated by the
@@ -99,6 +100,7 @@ func addb(p *byte, n uintptr) *byte {
// subtractb is typically used when traversing the pointer tables referred to by hbits
// which are arranged in reverse order.
//go:nowritebarrier
+//go:nosplit
func subtractb(p *byte, n uintptr) *byte {
// Note: wrote out full expression instead of calling add(p, -n)
// to reduce the number of temporaries generated by the
@@ -108,6 +110,7 @@ func subtractb(p *byte, n uintptr) *byte {
// add1 returns the byte pointer p+1.
//go:nowritebarrier
+//go:nosplit
func add1(p *byte) *byte {
// Note: wrote out full expression instead of calling addb(p, 1)
// to reduce the number of temporaries generated by the
@@ -596,10 +599,10 @@ func (h heapBits) setCheckmarked(size uintptr) {
// heapBitsBulkBarrier executes writebarrierptr_nostore
// for every pointer slot in the memory range [p, p+size),
-// using the heap bitmap to locate those pointer slots.
+// using the heap, data, or BSS bitmap to locate those pointer slots.
// This executes the write barriers necessary after a memmove.
// Both p and size must be pointer-aligned.
-// The range [p, p+size) must lie within a single allocation.
+// The range [p, p+size) must lie within a single object.
//
// Callers should call heapBitsBulkBarrier immediately after
// calling memmove(p, src, size). This function is marked nosplit
@@ -643,6 +646,22 @@ func heapBitsBulkBarrier(p, size uintptr) {
systemstack(func() {
gcUnwindBarriers(gp, p)
})
+ return
+ }
+
+ // If p is a global, use the data or BSS bitmaps to
+ // execute write barriers.
+ for datap := &firstmoduledata; datap != nil; datap = datap.next {
+ if datap.data <= p && p < datap.edata {
+ bulkBarrierBitmap(p, size, p-datap.data, datap.gcdatamask.bytedata)
+ return
+ }
+ }
+ for datap := &firstmoduledata; datap != nil; datap = datap.next {
+ if datap.bss <= p && p < datap.ebss {
+ bulkBarrierBitmap(p, size, p-datap.bss, datap.gcbssmask.bytedata)
+ return
+ }
}
return
}
@@ -657,6 +676,36 @@ func heapBitsBulkBarrier(p, size uintptr) {
}
}
+// bulkBarrierBitmap executes write barriers for [p, p+size) using a
+// 1-bit pointer bitmap. p is assumed to start maskOffset bytes into
+// the data covered by the bitmap in bits.
+//
+// This is used by heapBitsBulkBarrier for writes to data and BSS.
+//
+//go:nosplit
+func bulkBarrierBitmap(p, size, maskOffset uintptr, bits *uint8) {
+ word := maskOffset / sys.PtrSize
+ bits = addb(bits, word/8)
+ mask := uint8(1) << (word % 8)
+
+ for i := uintptr(0); i < size; i += sys.PtrSize {
+ if mask == 0 {
+ bits = addb(bits, 1)
+ if *bits == 0 {
+ // Skip 8 words.
+ i += 7 * sys.PtrSize
+ continue
+ }
+ mask = 1
+ }
+ if *bits&mask != 0 {
+ x := (*uintptr)(unsafe.Pointer(p + i))
+ writebarrierptr_nostore(x, *x)
+ }
+ mask <<= 1
+ }
+}
+
// typeBitsBulkBarrier executes writebarrierptr_nostore
// for every pointer slot in the memory range [p, p+size),
// using the type bitmap to locate those pointer slots.
@@ -676,11 +725,11 @@ func typeBitsBulkBarrier(typ *_type, p, size uintptr) {
throw("runtime: typeBitsBulkBarrier without type")
}
if typ.size != size {
- println("runtime: typeBitsBulkBarrier with type ", typ._string, " of size ", typ.size, " but memory size", size)
+ println("runtime: typeBitsBulkBarrier with type ", typ.string(), " of size ", typ.size, " but memory size", size)
throw("runtime: invalid typeBitsBulkBarrier")
}
if typ.kind&kindGCProg != 0 {
- println("runtime: typeBitsBulkBarrier with type ", typ._string, " with GC prog")
+ println("runtime: typeBitsBulkBarrier with type ", typ.string(), " with GC prog")
throw("runtime: invalid typeBitsBulkBarrier")
}
if !writeBarrier.needed {
@@ -1128,7 +1177,7 @@ func heapBitsSetType(x, size, dataSize uintptr, typ *_type) {
}
if nw == 0 {
// No pointers! Caller was supposed to check.
- println("runtime: invalid type ", typ._string)
+ println("runtime: invalid type ", typ.string())
throw("heapBitsSetType: called with non-pointer type")
return
}
@@ -1314,7 +1363,7 @@ Phase4:
if doubleCheck {
end := heapBitsForAddr(x + size)
if typ.kind&kindGCProg == 0 && (hbitp != end.bitp || (w == nw+2) != (end.shift == 2)) {
- println("ended at wrong bitmap byte for", typ._string, "x", dataSize/typ.size)
+ println("ended at wrong bitmap byte for", typ.string(), "x", dataSize/typ.size)
print("typ.size=", typ.size, " typ.ptrdata=", typ.ptrdata, " dataSize=", dataSize, " size=", size, "\n")
print("w=", w, " nw=", nw, " b=", hex(b), " nb=", nb, " hb=", hex(hb), "\n")
h0 := heapBitsForAddr(x)
@@ -1350,7 +1399,7 @@ Phase4:
}
}
if have != want {
- println("mismatch writing bits for", typ._string, "x", dataSize/typ.size)
+ println("mismatch writing bits for", typ.string(), "x", dataSize/typ.size)
print("typ.size=", typ.size, " typ.ptrdata=", typ.ptrdata, " dataSize=", dataSize, " size=", size, "\n")
print("kindGCProg=", typ.kind&kindGCProg != 0, "\n")
print("w=", w, " nw=", nw, " b=", hex(b), " nb=", nb, " hb=", hex(hb), "\n")