aboutsummaryrefslogtreecommitdiff
path: root/libgo/go/runtime/mbitmap.go
diff options
context:
space:
mode:
Diffstat (limited to 'libgo/go/runtime/mbitmap.go')
-rw-r--r--libgo/go/runtime/mbitmap.go72
1 files changed, 39 insertions, 33 deletions
diff --git a/libgo/go/runtime/mbitmap.go b/libgo/go/runtime/mbitmap.go
index 0eb19d6..72cd9f3 100644
--- a/libgo/go/runtime/mbitmap.go
+++ b/libgo/go/runtime/mbitmap.go
@@ -226,16 +226,25 @@ func (s *mspan) isFree(index uintptr) bool {
return *bytep&mask == 0
}
-func (s *mspan) objIndex(p uintptr) uintptr {
- byteOffset := p - s.base()
- if byteOffset == 0 {
- return 0
- }
- if s.baseMask != 0 {
- // s.baseMask is non-0, elemsize is a power of two, so shift by s.divShift
- return byteOffset >> s.divShift
+// divideByElemSize returns n/s.elemsize.
+// n must be within [0, s.npages*_PageSize),
+// or may be exactly s.npages*_PageSize
+// if s.elemsize is from sizeclasses.go.
+func (s *mspan) divideByElemSize(n uintptr) uintptr {
+ const doubleCheck = false
+
+ // See explanation in mksizeclasses.go's computeDivMagic.
+ q := uintptr((uint64(n) * uint64(s.divMul)) >> 32)
+
+ if doubleCheck && q != n/s.elemsize {
+ println(n, "/", s.elemsize, "should be", n/s.elemsize, "but got", q)
+ throw("bad magic division")
}
- return uintptr(((uint64(byteOffset) >> s.divShift) * uint64(s.divMul)) >> s.divShift2)
+ return q
+}
+
+func (s *mspan) objIndex(p uintptr) uintptr {
+ return s.divideByElemSize(p - s.base())
}
func markBitsForAddr(p uintptr) markBits {
@@ -324,6 +333,10 @@ func heapBitsForAddr(addr uintptr) (h heapBits) {
return
}
+// clobberdeadPtr is a special value that is used by the compiler to
+// clobber dead stack slots, when -clobberdead flag is set.
+const clobberdeadPtr = uintptr(0xdeaddead | 0xdeaddead<<((^uintptr(0)>>63)*32))
+
// badPointer throws bad pointer in heap panic.
func badPointer(s *mspan, p, refBase, refOff uintptr) {
// Typically this indicates an incorrect use
@@ -336,13 +349,16 @@ func badPointer(s *mspan, p, refBase, refOff uintptr) {
// in allocated spans.
printlock()
print("runtime: pointer ", hex(p))
- state := s.state.get()
- if state != mSpanInUse {
- print(" to unallocated span")
- } else {
- print(" to unused region of span")
+ if s != nil {
+ state := s.state.get()
+ if state != mSpanInUse {
+ print(" to unallocated span")
+ } else {
+ print(" to unused region of span")
+ }
+ print(" span.base()=", hex(s.base()), " span.limit=", hex(s.limit), " span.state=", state)
}
- print(" span.base()=", hex(s.base()), " span.limit=", hex(s.limit), " span.state=", state, "\n")
+ print("\n")
if refBase != 0 {
print("runtime: found in object at *(", hex(refBase), "+", hex(refOff), ")\n")
gcDumpObject("object", refBase, refOff)
@@ -373,6 +389,12 @@ func findObject(p, refBase, refOff uintptr, forStack bool) (base uintptr, s *msp
// If s is nil, the virtual address has never been part of the heap.
// This pointer may be to some mmap'd region, so we allow it.
if s == nil {
+ if GOARCH == "amd64" && p == clobberdeadPtr && debug.invalidptr != 0 {
+ // Crash if clobberdeadPtr is seen. Only on AMD64 for now, as
+ // it is the only platform where compiler's clobberdead mode is
+ // implemented. On AMD64 clobberdeadPtr cannot be a valid address.
+ badPointer(s, p, refBase, refOff)
+ }
return
}
// If p is a bad pointer, it may not be in s's bounds.
@@ -402,24 +424,8 @@ func findObject(p, refBase, refOff uintptr, forStack bool) (base uintptr, s *msp
}
}
- // If this span holds object of a power of 2 size, just mask off the bits to
- // the interior of the object. Otherwise use the size to get the base.
- if s.baseMask != 0 {
- // optimize for power of 2 sized objects.
- base = s.base()
- base = base + (p-base)&uintptr(s.baseMask)
- objIndex = (base - s.base()) >> s.divShift
- // base = p & s.baseMask is faster for small spans,
- // but doesn't work for large spans.
- // Overall, it's faster to use the more general computation above.
- } else {
- base = s.base()
- if p-base >= s.elemsize {
- // n := (p - base) / s.elemsize, using division by multiplication
- objIndex = uintptr(p-base) >> s.divShift * uintptr(s.divMul) >> s.divShift2
- base += objIndex * s.elemsize
- }
- }
+ objIndex = s.objIndex(p)
+ base = s.base() + objIndex*s.elemsize
return
}