Bug 1751959 - Part 2: Remove the auxillary mark stack and use a single stack for both black and gray marking r=sfink

Differential Revision: https://phabricator.services.mozilla.com/D136915
This commit is contained in:
Jon Coppeard 2022-02-02 17:29:05 +00:00
Родитель bdcdcd67bf
Коммит fbad14b1c7
4 изменённых файлов: 29 добавлений и 86 удалений

Просмотреть файл

@ -23,7 +23,6 @@ class WeakMapBase;
static const size_t NON_INCREMENTAL_MARK_STACK_BASE_CAPACITY = 4096;
static const size_t INCREMENTAL_MARK_STACK_BASE_CAPACITY = 32768;
static const size_t SMALL_MARK_STACK_BASE_CAPACITY = 256;
enum class SlotsOrElementsKind { Elements, FixedSlots, DynamicSlots };
@ -144,11 +143,8 @@ class MarkStack {
size_t position() const { return topIndex_; }
enum StackType { MainStack, AuxiliaryStack };
[[nodiscard]] bool init(StackType which, bool incrementalGCEnabled);
[[nodiscard]] bool setStackCapacity(StackType which,
bool incrementalGCEnabled);
[[nodiscard]] bool init(bool incrementalGCEnabled);
[[nodiscard]] bool setStackCapacity(bool incrementalGCEnabled);
size_t maxCapacity() const { return maxCapacity_; }
void setMaxCapacity(size_t maxCapacity);
@ -315,13 +311,8 @@ class GCMarker final : public JSTracer {
* objects that are still reachable.
*/
void setMarkColor(gc::MarkColor newColor);
void setMarkColorUnchecked(gc::MarkColor newColor);
gc::MarkColor markColor() const { return color; }
// Declare which color the main mark stack will be used for. The whole stack
// must be empty when this is called.
void setMainStackColor(gc::MarkColor newColor);
bool enterWeakMarkingMode();
void leaveWeakMarkingMode();
@ -364,7 +355,7 @@ class GCMarker final : public JSTracer {
void setIncrementalGCEnabled(bool enabled) {
// Ignore failure to resize the stack and keep using the existing stack.
(void)stack.setStackCapacity(gc::MarkStack::MainStack, enabled);
(void)stack.setStackCapacity(enabled);
}
size_t sizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf) const;
@ -440,27 +431,11 @@ class GCMarker final : public JSTracer {
inline void pushValueRange(JSObject* obj, SlotsOrElementsKind kind,
size_t start, size_t end);
gc::MarkStack& getStack(gc::MarkColor which) {
return which == mainStackColor ? stack : auxStack;
}
const gc::MarkStack& getStack(gc::MarkColor which) const {
return which == mainStackColor ? stack : auxStack;
}
bool isMarkStackEmpty() { return stack.isEmpty(); }
gc::MarkStack& currentStack() {
MOZ_ASSERT(currentStackPtr);
return *currentStackPtr;
}
bool hasBlackEntries() const { return stack.position() > grayPosition; }
bool isMarkStackEmpty() { return stack.isEmpty() && auxStack.isEmpty(); }
bool hasBlackEntries() const {
return !getStack(gc::MarkColor::Black).isEmpty();
}
bool hasGrayEntries() const {
return !getStack(gc::MarkColor::Gray).isEmpty();
}
bool hasGrayEntries() const { return grayPosition > 0 && !stack.isEmpty(); }
inline void processMarkStackTop(SliceBudget& budget);
@ -491,25 +466,18 @@ class GCMarker final : public JSTracer {
friend class gc::BarrierTracer;
/*
* The mark stack. Pointers in this stack are "gray" in the GC sense, but may
* mark the contained items either black or gray (in the CC sense) depending
* on mainStackColor.
* The mark stack. Pointers in this stack are "gray" in the GC sense, but
* their references may be marked either black or gray (in the CC sense)
* depending on whether they are above or below grayPosition.
*/
gc::MarkStack stack;
/*
* A smaller, auxiliary stack, currently only used to accumulate the rare
* objects that need to be marked black during gray marking.
*/
gc::MarkStack auxStack;
/* Stack entries at positions below this are considered gray. */
MainThreadOrGCTaskData<size_t> grayPosition;
/* The color is only applied to objects and functions. */
MainThreadOrGCTaskData<gc::MarkColor> color;
MainThreadOrGCTaskData<gc::MarkColor> mainStackColor;
MainThreadOrGCTaskData<gc::MarkStack*> currentStackPtr;
/* Pointer to the top of the stack of arenas we are delaying marking on. */
MainThreadOrGCTaskData<js::gc::Arena*> delayedMarkingList;

Просмотреть файл

@ -1387,7 +1387,6 @@ inline void js::GCMarker::eagerlyMarkChildren(JSRope* rope) {
// users of the stack. This also assumes that a rope can only point to
// other ropes or linear strings, it cannot refer to GC things of other
// types.
gc::MarkStack& stack = currentStack();
size_t savedPos = stack.position();
MOZ_DIAGNOSTIC_ASSERT(rope->getTraceKind() == JS::TraceKind::String);
while (true) {
@ -1922,8 +1921,6 @@ inline void GCMarker::processMarkStackTop(SliceBudget& budget) {
size_t index; // Index of the next slot to mark.
size_t end; // End of slot range to mark.
gc::MarkStack& stack = currentStack();
switch (stack.peekTag()) {
case MarkStack::SlotsOrElementsRangeTag: {
auto range = stack.popSlotsOrElementsRange();
@ -2196,17 +2193,14 @@ MarkStack::~MarkStack() {
MOZ_ASSERT(iteratorCount_ == 0);
}
bool MarkStack::init(StackType which, bool incrementalGCEnabled) {
bool MarkStack::init(bool incrementalGCEnabled) {
MOZ_ASSERT(isEmpty());
return setStackCapacity(which, incrementalGCEnabled);
return setStackCapacity(incrementalGCEnabled);
}
bool MarkStack::setStackCapacity(StackType which, bool incrementalGCEnabled) {
bool MarkStack::setStackCapacity(bool incrementalGCEnabled) {
size_t capacity;
if (which == AuxiliaryStack) {
capacity = SMALL_MARK_STACK_BASE_CAPACITY;
} else if (incrementalGCEnabled) {
if (incrementalGCEnabled) {
capacity = INCREMENTAL_MARK_STACK_BASE_CAPACITY;
} else {
capacity = NON_INCREMENTAL_MARK_STACK_BASE_CAPACITY;
@ -2394,8 +2388,8 @@ GCMarker::GCMarker(JSRuntime* rt)
JS::TraceOptions(JS::WeakMapTraceAction::Expand,
JS::WeakEdgeTraceAction::Skip)),
stack(),
auxStack(),
mainStackColor(MarkColor::Black),
grayPosition(0),
color(MarkColor::Black),
delayedMarkingList(nullptr),
delayedMarkingWorkAdded(false),
state(MarkingState::NotActive),
@ -2410,13 +2404,11 @@ GCMarker::GCMarker(JSRuntime* rt)
queuePos(0)
#endif
{
setMarkColorUnchecked(MarkColor::Black);
}
bool GCMarker::init() {
bool incrementalGCEnabled = runtime()->gc.isIncrementalGCEnabled();
return stack.init(gc::MarkStack::MainStack, incrementalGCEnabled) &&
auxStack.init(gc::MarkStack::AuxiliaryStack, incrementalGCEnabled);
return stack.init(incrementalGCEnabled);
}
bool GCMarker::isDrained() {
@ -2461,8 +2453,6 @@ void GCMarker::stop() {
barrierBuffer().clearAndFree();
stack.clear();
auxStack.clear();
setMainStackColor(MarkColor::Black);
ClearEphemeronEdges(runtime());
}
@ -2482,8 +2472,6 @@ void GCMarker::reset() {
barrierBuffer().clearAndFree();
stack.clear();
auxStack.clear();
setMainStackColor(MarkColor::Black);
ClearEphemeronEdges(runtime());
MOZ_ASSERT(isMarkStackEmpty());
@ -2502,31 +2490,25 @@ void GCMarker::reset() {
}
void GCMarker::setMarkColor(gc::MarkColor newColor) {
if (color != newColor) {
MOZ_ASSERT(runtime()->gc.state() == State::Sweep);
setMarkColorUnchecked(newColor);
if (color == newColor) {
return;
}
}
void GCMarker::setMarkColorUnchecked(gc::MarkColor newColor) {
MOZ_ASSERT(runtime()->gc.state() == State::Sweep);
MOZ_ASSERT(!hasBlackEntries());
color = newColor;
currentStackPtr = &getStack(color);
}
void GCMarker::setMainStackColor(gc::MarkColor newColor) {
MOZ_ASSERT(isMarkStackEmpty());
if (newColor != mainStackColor) {
mainStackColor = newColor;
// Update currentStackPtr without changing the mark color.
setMarkColorUnchecked(color);
if (color == MarkColor::Black) {
grayPosition = stack.position();
} else {
grayPosition = SIZE_MAX;
}
}
template <typename T>
inline void GCMarker::pushTaggedPtr(T* ptr) {
checkZone(ptr);
if (!currentStack().push(ptr)) {
if (!stack.push(ptr)) {
delayMarkingChildrenOnOOM(ptr);
}
}
@ -2541,7 +2523,7 @@ void GCMarker::pushValueRange(JSObject* obj, SlotsOrElementsKind kind,
return;
}
if (!currentStack().push(obj, kind, start)) {
if (!stack.push(obj, kind, start)) {
delayMarkingChildrenOnOOM(obj);
}
}
@ -2779,7 +2761,6 @@ void GCMarker::checkZone(void* p) {
size_t GCMarker::sizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf) const {
size_t size = stack.sizeOfExcludingThis(mallocSizeOf);
size += auxStack.sizeOfExcludingThis(mallocSizeOf);
size += barrierBuffer_.ref().sizeOfExcludingThis(mallocSizeOf);
return size;
}

Просмотреть файл

@ -1062,7 +1062,6 @@ IncrementalProgress GCRuntime::beginMarkingSweepGroup(JSFreeOp* fop,
}
AutoSetMarkColor setColorGray(marker, MarkColor::Gray);
marker.setMainStackColor(MarkColor::Gray);
// Mark incoming gray pointers from previously swept compartments.
markIncomingGrayCrossCompartmentPointers();
@ -1087,7 +1086,6 @@ IncrementalProgress GCRuntime::markGray(JSFreeOp* fop, SliceBudget& budget) {
return NotFinished;
}
marker.setMainStackColor(MarkColor::Black);
return Finished;
}
@ -1106,7 +1104,6 @@ IncrementalProgress GCRuntime::endMarkingSweepGroup(JSFreeOp* fop,
}
AutoSetMarkColor setColorGray(marker, MarkColor::Gray);
marker.setMainStackColor(MarkColor::Gray);
// Mark transitively inside the current compartment group.
if (markWeakReferencesInCurrentGroup(budget) == NotFinished) {
@ -1114,7 +1111,6 @@ IncrementalProgress GCRuntime::endMarkingSweepGroup(JSFreeOp* fop,
}
MOZ_ASSERT(marker.isDrained());
marker.setMainStackColor(MarkColor::Black);
// We must not yield after this point before we start sweeping the group.
safeToYield = false;

Просмотреть файл

@ -618,11 +618,9 @@ void js::gc::MarkingValidator::nonIncrementalMark(AutoGCSession& session) {
}
AutoSetMarkColor setColorGray(*gcmarker, MarkColor::Gray);
gcmarker->setMainStackColor(MarkColor::Gray);
gc->markAllGrayReferences(gcstats::PhaseKind::SWEEP_MARK_GRAY);
gc->markAllWeakReferences();
gc->marker.setMainStackColor(MarkColor::Black);
/* Restore zone state. */
for (GCZonesIter zone(gc); !zone.done(); zone.next()) {