From: Austin Clements Date: Thu, 12 Mar 2015 18:26:04 +0000 (-0400) Subject: runtime: factor object dumping code out of greyobject X-Git-Tag: go1.5beta1~1547 X-Git-Url: http://www.git.cypherpunks.su/?a=commitdiff_plain;h=506615d83ebbbaba33aaf98d79a285b0b367a094;p=gostls13.git runtime: factor object dumping code out of greyobject 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 --- diff --git a/src/runtime/mgcmark.go b/src/runtime/mgcmark.go index 5d3a9efbb3..4a3cc4d769 100644 --- a/src/runtime/mgcmark.go +++ b/src/runtime/mgcmark.go @@ -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() { @@ -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) {