}
}
- aoff := uintptr(src) - mheap_.arena_start
- idx := aoff >> _PageShift
- s := mheap_.spans[idx]
+ s := spanOfUnchecked(uintptr(src))
if s.state == _MSpanManual {
// There are no heap bits for value stored on the stack.
// For a channel receive src might be on the stack of some
// in which the pointer p was found and the byte offset at which it
// was found. These are used for error reporting.
func findObject(p, refBase, refOff uintptr) (base uintptr, s *mspan, objIndex uintptr) {
- arenaStart := mheap_.arena_start
- if p < arenaStart || p >= mheap_.arena_used {
- return
- }
- off := p - arenaStart
- idx := off >> _PageShift
- // p points into the heap, but possibly to the middle of an object.
- // Consult the span table to find the block beginning.
- s = mheap_.spans[idx]
+ s = spanOf(p)
+ // If p is a bad pointer, it may not be in s's bounds.
if s == nil || p < s.base() || p >= s.limit || s.state != mSpanInUse {
if s == nil || s.state == _MSpanManual {
// If s is nil, the virtual address has never been part of the heap.
} else {
print(" to unused region of span")
}
- print(" idx=", hex(idx), " span.base()=", hex(s.base()), " span.limit=", hex(s.limit), " span.state=", s.state, "\n")
+ print(" span.base()=", hex(s.base()), " span.limit=", hex(s.limit), " span.state=", s.state, "\n")
if refBase != 0 {
print("runtime: found in object at *(", hex(refBase), "+", hex(refOff), ")\n")
gcDumpObject("object", refBase, refOff)
print(label, "=", hex(obj), " is not in the Go heap\n")
return
}
- k := obj >> _PageShift
- x := k
- x -= mheap_.arena_start >> _PageShift
- s := mheap_.spans[x]
- print(label, "=", hex(obj), " k=", hex(k))
+ s := spanOf(obj)
+ print(label, "=", hex(obj))
if s == nil {
print(" s=nil\n")
return
//go:nowritebarrier
//go:nosplit
func inheap(b uintptr) bool {
- if b == 0 || b < mheap_.arena_start || b >= mheap_.arena_used {
- return false
- }
- // Not a beginning of a block, consult span table to find the block beginning.
- s := mheap_.spans[(b-mheap_.arena_start)>>_PageShift]
- if s == nil || b < s.base() || b >= s.limit || s.state != mSpanInUse {
- return false
- }
- return true
+ return spanOfHeap(b) != nil
}
// inHeapOrStack is a variant of inheap that returns true for pointers
//go:nowritebarrier
//go:nosplit
func inHeapOrStack(b uintptr) bool {
- if b == 0 || b < mheap_.arena_start || b >= mheap_.arena_used {
- return false
- }
- // Not a beginning of a block, consult span table to find the block beginning.
- s := mheap_.spans[(b-mheap_.arena_start)>>_PageShift]
+ s := spanOf(b)
if s == nil || b < s.base() {
return false
}
}
}
-// TODO: spanOf and spanOfUnchecked are open-coded in a lot of places.
-// Use the functions instead.
-
// spanOf returns the span of p. If p does not point into the heap
// arena or no span has ever contained p, spanOf returns nil.
//
// span that does *not* contain p. If this is a possibility, the
// caller should either call spanOfHeap or check the span bounds
// explicitly.
+//
+// Must be nosplit because it has callers that are nosplit.
+//
+//go:nosplit
func spanOf(p uintptr) *mspan {
if p == 0 || p < mheap_.arena_start || p >= mheap_.arena_used {
return nil
// spanOfUnchecked is equivalent to spanOf, but the caller must ensure
// that p points into the heap (that is, mheap_.arena_start <= p <
// mheap_.arena_used).
+//
+// Must be nosplit because it has callers that are nosplit.
+//
+//go:nosplit
func spanOfUnchecked(p uintptr) *mspan {
return mheap_.spans[(p-mheap_.arena_start)>>_PageShift]
}
// spanOfHeap is like spanOf, but returns nil if p does not point to a
// heap object.
+//
+// Must be nosplit because it has callers that are nosplit.
+//
+//go:nosplit
func spanOfHeap(p uintptr) *mspan {
s := spanOf(p)
// If p is not allocated, it may point to a stale span, so we