Skip to content

Commit

Permalink
runtime: factor object dumping code out of greyobject
Browse files Browse the repository at this point in the history
When checkmark fails, greyobject dumps both the object that pointed to
the unmarked object and the unmarked object. This code cluttered up
greyobject, was copy-pasted for the two objects, and the copy for
dumping the unmarked object was not entirely correct.

Extract object dumping out to a new function. This declutters
greyobject and fixes the bugs in dumping the unmarked object. The new
function is slightly cleaned up from the original code to have more
natural control flow and shows a marker on the field in the base
object that points to the unmarked object to make it easy to find.

Change-Id: Ib51318a943f50b0b99995f0941d03ee8876b9fcf
Reviewed-on: https://go-review.googlesource.com/7506
Reviewed-by: Rick Hudson <rlh@golang.org>
  • Loading branch information
aclements committed Mar 17, 2015
1 parent 830abc9 commit 506615d
Showing 1 changed file with 25 additions and 32 deletions.
57 changes: 25 additions & 32 deletions src/runtime/mgcmark.go
Original file line number Diff line number Diff line change
Expand Up @@ -522,45 +522,16 @@ func greyobject(obj, base, off uintptr, hbits heapBits, gcw *gcWorkProducer) {

if useCheckmark {
if !hbits.isMarked() {
printlock()
print("runtime:greyobject: checkmarks finds unexpected unmarked object obj=", hex(obj), "\n")
print("runtime: found obj at *(", hex(base), "+", hex(off), ")\n")

// Dump the source (base) object

kb := base >> _PageShift
xb := kb
xb -= mheap_.arena_start >> _PageShift
sb := h_spans[xb]
printlock()
print("runtime:greyobject Span: base=", hex(base), " kb=", hex(kb))
if sb == nil {
print(" sb=nil\n")
} else {
print(" sb.start*_PageSize=", hex(sb.start*_PageSize), " sb.limit=", hex(sb.limit), " sb.sizeclass=", sb.sizeclass, " sb.elemsize=", sb.elemsize, "\n")
// base is (a pointer to) the source object holding the reference to object. Create a pointer to each of the fields
// fields in base and print them out as hex values.
for i := 0; i < int(sb.elemsize/ptrSize); i++ {
print(" *(base+", i*ptrSize, ") = ", hex(*(*uintptr)(unsafe.Pointer(base + uintptr(i)*ptrSize))), "\n")
}
}
gcDumpObject("base", base, off)

// Dump the object
gcDumpObject("obj", obj, ^uintptr(0))

k := obj >> _PageShift
x := k
x -= mheap_.arena_start >> _PageShift
s := h_spans[x]
print("runtime:greyobject Span: obj=", hex(obj), " k=", hex(k))
if s == nil {
print(" s=nil\n")
} else {
print(" s.start=", hex(s.start*_PageSize), " s.limit=", hex(s.limit), " s.sizeclass=", s.sizeclass, " s.elemsize=", s.elemsize, "\n")
// NOTE(rsc): This code is using s.sizeclass as an approximation of the
// number of pointer-sized words in an object. Perhaps not what was intended.
for i := 0; i < int(s.sizeclass); i++ {
print(" *(obj+", i*ptrSize, ") = ", hex(*(*uintptr)(unsafe.Pointer(obj + uintptr(i)*ptrSize))), "\n")
}
}
throw("checkmark found unmarked object")
}
if !hbits.isCheckmarked() {
Expand Down Expand Up @@ -595,6 +566,28 @@ func greyobject(obj, base, off uintptr, hbits heapBits, gcw *gcWorkProducer) {
gcw.put(obj)
}

// gcDumpObject dumps the contents of obj for debugging and marks the
// field at byte offset off in obj.
func gcDumpObject(label string, obj, off uintptr) {
k := obj >> _PageShift
x := k
x -= mheap_.arena_start >> _PageShift
s := h_spans[x]
print(label, "=", hex(obj), " k=", hex(k))
if s == nil {
print(" s=nil\n")
return
}
print(" s.start*_PageSize=", hex(s.start*_PageSize), " s.limit=", hex(s.limit), " s.sizeclass=", s.sizeclass, " s.elemsize=", s.elemsize, "\n")
for i := uintptr(0); i < s.elemsize; i += ptrSize {
print(" *(", label, "+", i, ") = ", hex(*(*uintptr)(unsafe.Pointer(obj + uintptr(i)))))
if i == off {
print(" <==")
}
print("\n")
}
}

// When in GCmarkterminate phase we allocate black.
//go:nowritebarrier
func gcmarknewobject_m(obj uintptr) {
Expand Down

0 comments on commit 506615d

Please sign in to comment.