summaryrefslogtreecommitdiffstats
path: root/js/src/gc/Marking.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'js/src/gc/Marking.cpp')
-rw-r--r--js/src/gc/Marking.cpp137
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;