From befc3a0e3236ae61141721f871f867271e7667d0 Mon Sep 17 00:00:00 2001 From: Jon Coppeard Date: Thu, 10 May 2018 10:08:52 +0100 Subject: [PATCH] Bug 1459568 - Expose gray object on return from shell test function r=sfink a=abillings --- js/src/gc/Marking.cpp | 34 ++++++++++++++++++++----- js/src/jit-test/tests/gc/bug-1459568.js | 7 +++++ js/src/shell/js.cpp | 2 +- 3 files changed, 35 insertions(+), 8 deletions(-) create mode 100644 js/src/jit-test/tests/gc/bug-1459568.js diff --git a/js/src/gc/Marking.cpp b/js/src/gc/Marking.cpp index 0bc687ba785d..0358357dc0f6 100644 --- a/js/src/gc/Marking.cpp +++ b/js/src/gc/Marking.cpp @@ -995,14 +995,28 @@ js::GCMarker::traverseEdge(S source, const T& thing) namespace { -template struct ParticipatesInCC {}; +template struct TypeParticipatesInCC {}; #define EXPAND_PARTICIPATES_IN_CC(_, type, addToCCKind) \ - template <> struct ParticipatesInCC { static const bool value = addToCCKind; }; + template <> struct TypeParticipatesInCC { static const bool value = addToCCKind; }; JS_FOR_EACH_TRACEKIND(EXPAND_PARTICIPATES_IN_CC) #undef EXPAND_PARTICIPATES_IN_CC +struct ParticipatesInCCFunctor +{ + template + bool operator()() { + return TypeParticipatesInCC::value; + } +}; + } // namespace +static bool +TraceKindParticipatesInCC(JS::TraceKind kind) +{ + return DispatchTraceKindTyped(ParticipatesInCCFunctor(), kind); +} + template bool js::GCMarker::mark(T* thing) @@ -1011,7 +1025,7 @@ js::GCMarker::mark(T* thing) TenuredCell* cell = TenuredCell::fromPointer(thing); MOZ_ASSERT(!IsInsideNursery(cell)); - if (!ParticipatesInCC::value) + if (!TypeParticipatesInCC::value) return cell->markIfUnmarked(MarkColor::Black); return cell->markIfUnmarked(markColor()); @@ -2567,12 +2581,18 @@ GCMarker::markDelayedChildren(Arena* arena) MOZ_ASSERT(arena->markOverflow); arena->markOverflow = 0; + JS::TraceKind kind = MapAllocToTraceKind(arena->getAllocKind()); + + // Whether we need to mark children of gray or black cells in the arena + // depends on which kind of marking we were doing when the arena as pushed + // onto the list. We never change mark color without draining the mark + // stack though so this is the same as the current color. + bool markGrayCells = markColor() == MarkColor::Gray && TraceKindParticipatesInCC(kind); + for (ArenaCellIterUnderGC i(arena); !i.done(); i.next()) { TenuredCell* t = i.getCell(); - if (t->isMarkedAny()) { - t->markIfUnmarked(); - js::TraceChildren(this, t, MapAllocToTraceKind(arena->getAllocKind())); - } + if ((markGrayCells && t->isMarkedGray()) || (!markGrayCells && t->isMarkedBlack())) + js::TraceChildren(this, t, kind); } } diff --git a/js/src/jit-test/tests/gc/bug-1459568.js b/js/src/jit-test/tests/gc/bug-1459568.js new file mode 100644 index 000000000000..04f97207db67 --- /dev/null +++ b/js/src/jit-test/tests/gc/bug-1459568.js @@ -0,0 +1,7 @@ +gczeal(0); +gcparam("markStackLimit", 1); +gczeal(18, 1); +grayRoot()[0] = "foo"; +grayRoot()[1] = {}; +grayRoot().x = 0; +gc(); diff --git a/js/src/shell/js.cpp b/js/src/shell/js.cpp index 2951fcb95637..dad614612239 100644 --- a/js/src/shell/js.cpp +++ b/js/src/shell/js.cpp @@ -6215,7 +6215,7 @@ DumpScopeChain(JSContext* cx, unsigned argc, Value* vp) // where we can store a JSObject*, and create a new object if one doesn't // already exist. // -// Note that ensureGrayRoot() will automatically blacken the returned object, +// Note that EnsureGrayRoot() will automatically blacken the returned object, // so it will not actually end up marked gray until the following GC clears the // black bit (assuming nothing is holding onto it.) //