diff options
Diffstat (limited to 'libgo/go/runtime/mbitmap.go')
-rw-r--r-- | libgo/go/runtime/mbitmap.go | 72 |
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 } |