author | Steve Fink <sfink@mozilla.com> |
Mon, 06 Feb 2017 10:56:16 -0800 | |
changeset 344829 | 96b7a5189c50 |
parent 344828 | 1d4116cb3c9d |
child 344830 | f36062d04d16 |
child 344885 | 82cdbd24d06f |
push id | 31417 |
push user | kwierso@gmail.com |
push date | Sat, 25 Feb 2017 00:46:36 +0000 |
treeherder | mozilla-central@f36062d04d16 [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | jonco |
bugs | 1337072 |
milestone | 54.0a1 |
first release with | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
js/src/gc/Heap.h | file | annotate | diff | comparison | revisions | |
js/src/gc/Marking.cpp | file | annotate | diff | comparison | revisions |
--- a/js/src/gc/Heap.h +++ b/js/src/gc/Heap.h @@ -1368,11 +1368,57 @@ TenuredCell::isAligned() const return Arena::isAligned(address(), arena()->getThingSize()); } #endif static const int32_t ChunkLocationOffsetFromLastByte = int32_t(gc::ChunkLocationOffset) - int32_t(gc::ChunkMask); } /* namespace gc */ + +namespace debug { + +// Utility functions meant to be called from an interactive debugger. +enum class MarkInfo : int { + BLACK = js::gc::BLACK, + GRAY = js::gc::GRAY, + UNMARKED = -1, + NURSERY = -2, +}; + +// Get the mark color for a cell, in a way easily usable from a debugger. +MOZ_NEVER_INLINE MarkInfo +GetMarkInfo(js::gc::Cell* cell); + +// Sample usage from gdb: +// +// (gdb) p $word = js::debug::GetMarkWordAddress(obj) +// $1 = (uintptr_t *) 0x7fa56d5fe360 +// (gdb) p/x $mask = js::debug::GetMarkMask(obj, js::gc::GRAY) +// $2 = 0x200000000 +// (gdb) watch *$word +// Hardware watchpoint 7: *$word +// (gdb) cond 7 *$word & $mask +// (gdb) cont +// +// Note that this is *not* a watchpoint on a single bit. It is a watchpoint on +// the whole word, which will trigger whenever the word changes and the +// selected bit is set after the change. +// +// So if the bit changing is the desired one, this is exactly what you want. +// But if a different bit changes (either set or cleared), you may still stop +// execution if the $mask bit happened to already be set. gdb does not expose +// enough information to restrict the watchpoint to just a single bit. + +// Return the address of the word containing the mark bits for the given cell, +// or nullptr if the cell is in the nursery. +MOZ_NEVER_INLINE uintptr_t* +GetMarkWordAddress(js::gc::Cell* cell); + +// Return the mask for the given cell and color, or 0 if the cell is in the +// nursery. +MOZ_NEVER_INLINE uintptr_t +GetMarkMask(js::gc::Cell* cell, uint32_t color); + +} /* namespace debug */ } /* namespace js */ #endif /* gc_Heap_h */
--- a/js/src/gc/Marking.cpp +++ b/js/src/gc/Marking.cpp @@ -3368,8 +3368,52 @@ js::UnmarkGrayShapeRecursively(Shape* sh return TypedUnmarkGrayCellRecursively(shape); } JS_FRIEND_API(bool) JS::UnmarkGrayGCThingRecursively(JS::GCCellPtr thing) { return js::UnmarkGrayCellRecursively(thing.asCell(), thing.kind()); } + +namespace js { +namespace debug { + +MarkInfo +GetMarkInfo(Cell* rawCell) +{ + if (!rawCell->isTenured()) + return MarkInfo::NURSERY; + + TenuredCell* cell = &rawCell->asTenured(); + if (cell->isMarked(GRAY)) + return MarkInfo::GRAY; + if (cell->isMarked(BLACK)) + return MarkInfo::BLACK; + return MarkInfo::UNMARKED; +} + +uintptr_t* +GetMarkWordAddress(Cell* cell) +{ + if (!cell->isTenured()) + return nullptr; + + uintptr_t* wordp; + uintptr_t mask; + js::gc::detail::GetGCThingMarkWordAndMask(uintptr_t(cell), js::gc::BLACK, &wordp, &mask); + return wordp; +} + +uintptr_t +GetMarkMask(Cell* cell, uint32_t color) +{ + if (!cell->isTenured()) + return 0; + + uintptr_t* wordp; + uintptr_t mask; + js::gc::detail::GetGCThingMarkWordAndMask(uintptr_t(cell), color, &wordp, &mask); + return mask; +} + +} +}