diff options
Diffstat (limited to 'js/src/gc/Marking.cpp')
-rw-r--r-- | js/src/gc/Marking.cpp | 137 |
1 files changed, 129 insertions, 8 deletions
diff --git a/js/src/gc/Marking.cpp b/js/src/gc/Marking.cpp index b92cd5f3ac..0201e20aa7 100644 --- a/js/src/gc/Marking.cpp +++ b/js/src/gc/Marking.cpp @@ -1307,9 +1307,20 @@ bool GCMarker::doMarking(SliceBudget& budget, ShouldReportMarkTime reportTime) { return true; } +class MOZ_RAII gc::AutoUpdateMarkStackRanges { + GCMarker& marker_; + + public: + explicit AutoUpdateMarkStackRanges(GCMarker& marker) : marker_(marker) { + marker_.updateRangesAtStartOfSlice(); + } + ~AutoUpdateMarkStackRanges() { marker_.updateRangesAtEndOfSlice(); } +}; + template <uint32_t opts, MarkColor color> bool GCMarker::markOneColor(SliceBudget& budget) { AutoSetMarkColor setColor(*this, color); + AutoUpdateMarkStackRanges updateRanges(*this); while (processMarkStackTop<opts>(budget)) { if (stack.isEmpty()) { @@ -1321,6 +1332,8 @@ bool GCMarker::markOneColor(SliceBudget& budget) { } bool GCMarker::markCurrentColorInParallel(SliceBudget& budget) { + AutoUpdateMarkStackRanges updateRanges(*this); + ParallelMarker::AtomicCount& waitingTaskCount = parallelMarker_->waitingTaskCountRef(); @@ -1340,6 +1353,26 @@ bool GCMarker::markCurrentColorInParallel(SliceBudget& budget) { return false; } +#ifdef DEBUG +bool GCMarker::markOneObjectForTest(JSObject* obj) { + MOZ_ASSERT(obj->zone()->isGCMarking()); + MOZ_ASSERT(!obj->isMarked(markColor())); + + size_t oldPosition = stack.position(); + markAndTraverse<NormalMarkingOptions>(obj); + if (stack.position() == oldPosition) { + return false; + } + + AutoUpdateMarkStackRanges updateRanges(*this); + + SliceBudget unlimited = SliceBudget::unlimited(); + processMarkStackTop<NormalMarkingOptions>(unlimited); + + return true; +} +#endif + static inline void CheckForCompartmentMismatch(JSObject* obj, JSObject* obj2) { #ifdef DEBUG if (MOZ_UNLIKELY(obj->compartment() != obj2->compartment())) { @@ -1366,6 +1399,47 @@ static inline size_t NumUsedDynamicSlots(NativeObject* obj) { return nslots - nfixed; } +void GCMarker::updateRangesAtStartOfSlice() { + for (MarkStackIter iter(stack); !iter.done(); iter.next()) { + if (iter.isSlotsOrElementsRange()) { + MarkStack::SlotsOrElementsRange& range = iter.slotsOrElementsRange(); + JSObject* obj = range.ptr().asRangeObject(); + if (!obj->is<NativeObject>()) { + range.setEmpty(); + } else if (range.kind() == SlotsOrElementsKind::Elements) { + NativeObject* obj = &range.ptr().asRangeObject()->as<NativeObject>(); + size_t index = range.start(); + size_t numShifted = obj->getElementsHeader()->numShiftedElements(); + index -= std::min(numShifted, index); + range.setStart(index); + } + } + } + +#ifdef DEBUG + MOZ_ASSERT(!stack.elementsRangesAreValid); + stack.elementsRangesAreValid = true; +#endif +} + +void GCMarker::updateRangesAtEndOfSlice() { + for (MarkStackIter iter(stack); !iter.done(); iter.next()) { + if (iter.isSlotsOrElementsRange()) { + MarkStack::SlotsOrElementsRange& range = iter.slotsOrElementsRange(); + if (range.kind() == SlotsOrElementsKind::Elements) { + NativeObject* obj = &range.ptr().asRangeObject()->as<NativeObject>(); + size_t numShifted = obj->getElementsHeader()->numShiftedElements(); + range.setStart(range.start() + numShifted); + } + } + } + +#ifdef DEBUG + MOZ_ASSERT(stack.elementsRangesAreValid); + stack.elementsRangesAreValid = false; +#endif +} + template <uint32_t opts> inline bool GCMarker::processMarkStackTop(SliceBudget& budget) { /* @@ -1379,6 +1453,7 @@ inline bool GCMarker::processMarkStackTop(SliceBudget& budget) { */ MOZ_ASSERT(!stack.isEmpty()); + MOZ_ASSERT(stack.elementsRangesAreValid); MOZ_ASSERT_IF(markColor() == MarkColor::Gray, !hasBlackEntries()); JSObject* obj; // The object being scanned. @@ -1409,12 +1484,7 @@ inline bool GCMarker::processMarkStackTop(SliceBudget& budget) { case SlotsOrElementsKind::Elements: { base = nobj->getDenseElements(); - - // Account for shifted elements. - size_t numShifted = nobj->getElementsHeader()->numShiftedElements(); - size_t initlen = nobj->getDenseInitializedLength(); - index = std::max(index, numShifted) - numShifted; - end = initlen; + end = nobj->getDenseInitializedLength(); break; } @@ -1590,17 +1660,17 @@ struct MapTypeToMarkStackTag<BaseScript*> { static const auto value = MarkStack::ScriptTag; }; -#ifdef DEBUG static inline bool TagIsRangeTag(MarkStack::Tag tag) { return tag == MarkStack::SlotsOrElementsRangeTag; } -#endif inline MarkStack::TaggedPtr::TaggedPtr(Tag tag, Cell* ptr) : bits(tag | uintptr_t(ptr)) { assertValid(); } +inline uintptr_t MarkStack::TaggedPtr::asBits() const { return bits; } + inline uintptr_t MarkStack::TaggedPtr::tagUnchecked() const { return bits & TagMask; } @@ -1661,6 +1731,17 @@ inline size_t MarkStack::SlotsOrElementsRange::start() const { return startAndKind_ >> StartShift; } +inline void MarkStack::SlotsOrElementsRange::setStart(size_t newStart) { + startAndKind_ = (newStart << StartShift) | uintptr_t(kind()); + MOZ_ASSERT(start() == newStart); +} + +inline void MarkStack::SlotsOrElementsRange::setEmpty() { + TaggedPtr entry = TaggedPtr(ObjectTag, ptr().asRangeObject()); + ptr_ = entry; + startAndKind_ = entry.asBits(); +} + inline MarkStack::TaggedPtr MarkStack::SlotsOrElementsRange::ptr() const { return ptr_; } @@ -1931,6 +2012,45 @@ size_t MarkStack::sizeOfExcludingThis( return stack().sizeOfExcludingThis(mallocSizeOf); } +MarkStackIter::MarkStackIter(MarkStack& stack) + : stack_(stack), pos_(stack.position()) {} + +inline size_t MarkStackIter::position() const { return pos_; } + +inline bool MarkStackIter::done() const { return position() == 0; } + +inline void MarkStackIter::next() { + if (isSlotsOrElementsRange()) { + MOZ_ASSERT(position() >= ValueRangeWords); + pos_ -= ValueRangeWords; + return; + } + + MOZ_ASSERT(!done()); + pos_--; +} + +inline bool MarkStackIter::isSlotsOrElementsRange() const { + return TagIsRangeTag(peekTag()); +} + +inline MarkStack::Tag MarkStackIter::peekTag() const { return peekPtr().tag(); } + +inline MarkStack::TaggedPtr MarkStackIter::peekPtr() const { + MOZ_ASSERT(!done()); + return stack_.stack()[pos_ - 1]; +} + +inline MarkStack::SlotsOrElementsRange& MarkStackIter::slotsOrElementsRange() { + MOZ_ASSERT(TagIsRangeTag(peekTag())); + MOZ_ASSERT(position() >= ValueRangeWords); + + MarkStack::TaggedPtr* ptr = &stack_.stack()[pos_ - ValueRangeWords]; + auto& range = *reinterpret_cast<MarkStack::SlotsOrElementsRange*>(ptr); + range.assertValid(); + return range; +} + /*** GCMarker ***************************************************************/ /* @@ -2244,6 +2364,7 @@ void GCRuntime::processDelayedMarkingList(MarkColor color) { // were added. AutoSetMarkColor setColor(marker(), color); + AutoUpdateMarkStackRanges updateRanges(marker()); do { delayedMarkingWorkAdded = false; |