summaryrefslogtreecommitdiffstats
path: root/js/src
diff options
context:
space:
mode:
Diffstat (limited to 'js/src')
-rw-r--r--js/src/jit/CompileWrappers.h4
-rw-r--r--js/src/jit/VMFunctions.cpp6
-rw-r--r--js/src/js-config.h.in4
-rw-r--r--js/src/jsapi-tests/testGCFinalizeCallback.cpp30
-rw-r--r--js/src/jsapi-tests/testGCHeapPostBarriers.cpp4
-rw-r--r--js/src/jsapi-tests/testGCMarking.cpp25
-rw-r--r--js/src/jsapi-tests/testGCUniqueId.cpp4
-rw-r--r--js/src/jsapi-tests/tests.h35
-rw-r--r--js/src/jsapi.cpp20
-rw-r--r--js/src/jsgc.cpp595
-rw-r--r--js/src/jsgc.h15
-rw-r--r--js/src/jspubtd.h2
-rw-r--r--js/src/jsutil.h2
-rw-r--r--js/src/old-configure.in11
-rw-r--r--js/src/shell/js.cpp27
-rw-r--r--js/src/vm/EnvironmentObject.h3
16 files changed, 4 insertions, 783 deletions
diff --git a/js/src/jit/CompileWrappers.h b/js/src/jit/CompileWrappers.h
index bbec9ffa3..ccded4f13 100644
--- a/js/src/jit/CompileWrappers.h
+++ b/js/src/jit/CompileWrappers.h
@@ -51,10 +51,6 @@ class CompileRuntime
// &runtime()->activation_
const void* addressOfActivation();
-#ifdef JS_GC_ZEAL
- const void* addressOfGCZealModeBits();
-#endif
-
const void* addressOfInterruptUint32();
// We have to bake JSContext* into JIT code, but this pointer shouldn't be
diff --git a/js/src/jit/VMFunctions.cpp b/js/src/jit/VMFunctions.cpp
index 628b31fae..a299d27a5 100644
--- a/js/src/jit/VMFunctions.cpp
+++ b/js/src/jit/VMFunctions.cpp
@@ -627,11 +627,7 @@ PostWriteElementBarrier(JSRuntime* rt, JSObject* obj, int32_t index)
if (obj->is<NativeObject>() &&
!obj->as<NativeObject>().isInWholeCellBuffer() &&
uint32_t(index) < obj->as<NativeObject>().getDenseInitializedLength() &&
- (obj->as<NativeObject>().getDenseInitializedLength() > MAX_WHOLE_CELL_BUFFER_SIZE
-#ifdef JS_GC_ZEAL
- || rt->hasZealMode(gc::ZealMode::ElementsBarrier)
-#endif
- ))
+ (obj->as<NativeObject>().getDenseInitializedLength() > MAX_WHOLE_CELL_BUFFER_SIZE))
{
rt->gc.storeBuffer.putSlot(&obj->as<NativeObject>(), HeapSlot::Element, index, 1);
return;
diff --git a/js/src/js-config.h.in b/js/src/js-config.h.in
index f2ce93e12..779446fd7 100644
--- a/js/src/js-config.h.in
+++ b/js/src/js-config.h.in
@@ -38,10 +38,6 @@
/* Define to 1 if SpiderMonkey should include ctypes support. */
#undef JS_HAS_CTYPES
-/* Define to 1 if SpiderMonkey should support the ability to perform
- entirely too much GC. */
-#undef JS_GC_ZEAL
-
/* Define to 1 if SpiderMonkey should use small chunks. */
#undef JS_GC_SMALL_CHUNK_SIZE
diff --git a/js/src/jsapi-tests/testGCFinalizeCallback.cpp b/js/src/jsapi-tests/testGCFinalizeCallback.cpp
index 48003ab0c..a8f7ba7f8 100644
--- a/js/src/jsapi-tests/testGCFinalizeCallback.cpp
+++ b/js/src/jsapi-tests/testGCFinalizeCallback.cpp
@@ -94,36 +94,6 @@ BEGIN_TEST(testGCFinalizeCallback)
CHECK(checkFinalizeStatus());
CHECK(checkFinalizeIsZoneGC(true));
-#ifdef JS_GC_ZEAL
-
- /* Full GC with reset due to new zone, becoming zone GC. */
-
- FinalizeCalls = 0;
- JS_SetGCZeal(cx, 9, 1000000);
- JS::PrepareForFullGC(cx);
- js::SliceBudget budget(js::WorkBudget(1));
- cx->gc.startDebugGC(GC_NORMAL, budget);
- CHECK(cx->gc.state() == js::gc::State::Mark);
- CHECK(cx->gc.isFullGc());
-
- JS::RootedObject global4(cx, createTestGlobal());
- budget = js::SliceBudget(js::WorkBudget(1));
- cx->gc.debugGCSlice(budget);
- while (cx->gc.isIncrementalGCInProgress())
- cx->gc.debugGCSlice(budget);
- CHECK(!cx->gc.isIncrementalGCInProgress());
- CHECK(!cx->gc.isFullGc());
- CHECK(checkMultipleGroups());
- CHECK(checkFinalizeStatus());
-
- for (unsigned i = 0; i < FinalizeCalls - 1; ++i)
- CHECK(!IsZoneGCBuffer[i]);
- CHECK(IsZoneGCBuffer[FinalizeCalls - 1]);
-
- JS_SetGCZeal(cx, 0, 0);
-
-#endif
-
/*
* Make some use of the globals here to ensure the compiler doesn't optimize
* them away in release builds, causing the zones to be collected and
diff --git a/js/src/jsapi-tests/testGCHeapPostBarriers.cpp b/js/src/jsapi-tests/testGCHeapPostBarriers.cpp
index 74512a53f..00d47f111 100644
--- a/js/src/jsapi-tests/testGCHeapPostBarriers.cpp
+++ b/js/src/jsapi-tests/testGCHeapPostBarriers.cpp
@@ -40,10 +40,6 @@ JSFunction* CreateGCThing(JSContext* cx)
BEGIN_TEST(testGCHeapPostBarriers)
{
-#ifdef JS_GC_ZEAL
- AutoLeaveZeal nozeal(cx);
-#endif /* JS_GC_ZEAL */
-
/* Sanity check - objects start in the nursery and then become tenured. */
JS_GC(cx);
JS::RootedObject obj(cx, CreateGCThing<JSObject>(cx));
diff --git a/js/src/jsapi-tests/testGCMarking.cpp b/js/src/jsapi-tests/testGCMarking.cpp
index 684397392..b475c2d69 100644
--- a/js/src/jsapi-tests/testGCMarking.cpp
+++ b/js/src/jsapi-tests/testGCMarking.cpp
@@ -101,10 +101,6 @@ class CCWTestTracer : public JS::CallbackTracer {
BEGIN_TEST(testTracingIncomingCCWs)
{
-#ifdef JS_GC_ZEAL
- // Disable zeal modes because this test needs to control exactly when the GC happens.
- JS_SetGCZeal(cx, 0, 100);
-#endif
JS_GC(cx);
JS::RootedObject global1(cx, JS::CurrentGlobalOrNull(cx));
@@ -146,10 +142,6 @@ countWrappers(JSCompartment* comp)
BEGIN_TEST(testDeadNurseryCCW)
{
-#ifdef JS_GC_ZEAL
- // Disable zeal modes because this test needs to control exactly when the GC happens.
- JS_SetGCZeal(cx, 0, 100);
-#endif
JS_GC(cx);
JS::RootedObject global1(cx, JS::CurrentGlobalOrNull(cx));
@@ -177,10 +169,6 @@ END_TEST(testDeadNurseryCCW)
BEGIN_TEST(testLiveNurseryCCW)
{
-#ifdef JS_GC_ZEAL
- // Disable zeal modes because this test needs to control exactly when the GC happens.
- JS_SetGCZeal(cx, 0, 100);
-#endif
JS_GC(cx);
JS::RootedObject global1(cx, JS::CurrentGlobalOrNull(cx));
@@ -208,10 +196,6 @@ END_TEST(testLiveNurseryCCW)
BEGIN_TEST(testLiveNurseryWrapperCCW)
{
-#ifdef JS_GC_ZEAL
- // Disable zeal modes because this test needs to control exactly when the GC happens.
- JS_SetGCZeal(cx, 0, 100);
-#endif
JS_GC(cx);
JS::RootedObject global1(cx, JS::CurrentGlobalOrNull(cx));
@@ -244,10 +228,6 @@ END_TEST(testLiveNurseryWrapperCCW)
BEGIN_TEST(testLiveNurseryWrappeeCCW)
{
-#ifdef JS_GC_ZEAL
- // Disable zeal modes because this test needs to control exactly when the GC happens.
- JS_SetGCZeal(cx, 0, 100);
-#endif
JS_GC(cx);
JS::RootedObject global1(cx, JS::CurrentGlobalOrNull(cx));
@@ -280,11 +260,6 @@ BEGIN_TEST(testIncrementalRoots)
{
JSRuntime* rt = cx->runtime();
-#ifdef JS_GC_ZEAL
- // Disable zeal modes because this test needs to control exactly when the GC happens.
- JS_SetGCZeal(cx, 0, 100);
-#endif
-
// Construct a big object graph to mark. In JS, the resulting object graph
// is equivalent to:
//
diff --git a/js/src/jsapi-tests/testGCUniqueId.cpp b/js/src/jsapi-tests/testGCUniqueId.cpp
index 71d66b722..d03d51b04 100644
--- a/js/src/jsapi-tests/testGCUniqueId.cpp
+++ b/js/src/jsapi-tests/testGCUniqueId.cpp
@@ -23,10 +23,6 @@ MinimizeHeap(JSContext* cx)
BEGIN_TEST(testGCUID)
{
-#ifdef JS_GC_ZEAL
- AutoLeaveZeal nozeal(cx);
-#endif /* JS_GC_ZEAL */
-
uint64_t uid = 0;
uint64_t tmp = 0;
diff --git a/js/src/jsapi-tests/tests.h b/js/src/jsapi-tests/tests.h
index 9955621ef..7f7309c16 100644
--- a/js/src/jsapi-tests/tests.h
+++ b/js/src/jsapi-tests/tests.h
@@ -418,39 +418,4 @@ class TestJSPrincipals : public JSPrincipals
}
};
-#ifdef JS_GC_ZEAL
-/*
- * Temporarily disable the GC zeal setting. This is only useful in tests that
- * need very explicit GC behavior and should not be used elsewhere.
- */
-class AutoLeaveZeal
-{
- JSContext* cx_;
- uint32_t zealBits_;
- uint32_t frequency_;
-
- public:
- explicit AutoLeaveZeal(JSContext* cx) : cx_(cx) {
- uint32_t dummy;
- JS_GetGCZealBits(cx_, &zealBits_, &frequency_, &dummy);
- JS_SetGCZeal(cx_, 0, 0);
- JS::PrepareForFullGC(cx_);
- JS::GCForReason(cx_, GC_SHRINK, JS::gcreason::DEBUG_GC);
- }
- ~AutoLeaveZeal() {
- for (size_t i = 0; i < sizeof(zealBits_) * 8; i++) {
- if (zealBits_ & (1 << i))
- JS_SetGCZeal(cx_, i, frequency_);
- }
-
-#ifdef DEBUG
- uint32_t zealBitsAfter, frequencyAfter, dummy;
- JS_GetGCZealBits(cx_, &zealBitsAfter, &frequencyAfter, &dummy);
- MOZ_ASSERT(zealBitsAfter == zealBits_);
- MOZ_ASSERT(frequencyAfter == frequency_);
-#endif
- }
-};
-#endif /* JS_GC_ZEAL */
-
#endif /* jsapi_tests_tests_h */
diff --git a/js/src/jsapi.cpp b/js/src/jsapi.cpp
index e4e86effa..ee9c61059 100644
--- a/js/src/jsapi.cpp
+++ b/js/src/jsapi.cpp
@@ -6263,26 +6263,6 @@ JS_AbortIfWrongThread(JSContext* cx)
MOZ_CRASH();
}
-#ifdef JS_GC_ZEAL
-JS_PUBLIC_API(void)
-JS_GetGCZealBits(JSContext* cx, uint32_t* zealBits, uint32_t* frequency, uint32_t* nextScheduled)
-{
- cx->runtime()->gc.getZealBits(zealBits, frequency, nextScheduled);
-}
-
-JS_PUBLIC_API(void)
-JS_SetGCZeal(JSContext* cx, uint8_t zeal, uint32_t frequency)
-{
- cx->gc.setZeal(zeal, frequency);
-}
-
-JS_PUBLIC_API(void)
-JS_ScheduleGC(JSContext* cx, uint32_t count)
-{
- cx->runtime()->gc.setNextScheduled(count);
-}
-#endif
-
JS_PUBLIC_API(void)
JS_SetParallelParsingEnabled(JSContext* cx, bool enabled)
{
diff --git a/js/src/jsgc.cpp b/js/src/jsgc.cpp
index 42d10283c..4fa51417f 100644
--- a/js/src/jsgc.cpp
+++ b/js/src/jsgc.cpp
@@ -844,9 +844,6 @@ GCRuntime::GCRuntime(JSRuntime* rt) :
arenasAllocatedDuringSweep(nullptr),
startedCompacting(false),
relocatedArenasToRelease(nullptr),
-#ifdef JS_GC_ZEAL
- markingValidator(nullptr),
-#endif
interFrameGC(false),
defaultTimeBudget_(SliceBudget::UnlimitedTimeBudget),
incrementalAllowed(true),
@@ -856,13 +853,6 @@ GCRuntime::GCRuntime(JSRuntime* rt) :
manipulatingDeadZones(false),
objectsMarkedInDeadZones(0),
poked(false),
-#ifdef JS_GC_ZEAL
- zealModeBits(0),
- zealFrequency(0),
- nextScheduled(0),
- deterministicOnly(false),
- incrementalLimit(0),
-#endif
fullCompartmentChecks(false),
mallocBytesUntilGC(0),
mallocGCTriggered(false),
@@ -881,147 +871,6 @@ GCRuntime::GCRuntime(JSRuntime* rt) :
setGCMode(JSGC_MODE_GLOBAL);
}
-#ifdef JS_GC_ZEAL
-
-void
-GCRuntime::getZealBits(uint32_t* zealBits, uint32_t* frequency, uint32_t* scheduled)
-{
- *zealBits = zealModeBits;
- *frequency = zealFrequency;
- *scheduled = nextScheduled;
-}
-
-const char* gc::ZealModeHelpText =
- " Specifies how zealous the garbage collector should be. Some of these modes can\n"
- " be set simultaneously, by passing multiple level options, e.g. \"2;4\" will activate\n"
- " both modes 2 and 4. Modes can be specified by name or number.\n"
- " \n"
- " Values:\n"
- " 0: (None) Normal amount of collection (resets all modes)\n"
- " 1: (Poke) Collect when roots are added or removed\n"
- " 2: (Alloc) Collect when every N allocations (default: 100)\n"
- " 3: (FrameGC) Collect when the window paints (browser only)\n"
- " 4: (VerifierPre) Verify pre write barriers between instructions\n"
- " 5: (FrameVerifierPre) Verify pre write barriers between paints\n"
- " 6: (StackRooting) Verify stack rooting\n"
- " 7: (GenerationalGC) Collect the nursery every N nursery allocations\n"
- " 8: (IncrementalRootsThenFinish) Incremental GC in two slices: 1) mark roots 2) finish collection\n"
- " 9: (IncrementalMarkAllThenFinish) Incremental GC in two slices: 1) mark all 2) new marking and finish\n"
- " 10: (IncrementalMultipleSlices) Incremental GC in multiple slices\n"
- " 11: (IncrementalMarkingValidator) Verify incremental marking\n"
- " 12: (ElementsBarrier) Always use the individual element post-write barrier, regardless of elements size\n"
- " 13: (CheckHashTablesOnMinorGC) Check internal hashtables on minor GC\n"
- " 14: (Compact) Perform a shrinking collection every N allocations\n"
- " 15: (CheckHeapAfterGC) Walk the heap to check its integrity after every GC\n"
- " 16: (CheckNursery) Check nursery integrity on minor GC\n";
-
-void
-GCRuntime::setZeal(uint8_t zeal, uint32_t frequency)
-{
- MOZ_ASSERT(zeal <= unsigned(ZealMode::Limit));
-
- if (verifyPreData)
- VerifyBarriers(rt, PreBarrierVerifier);
-
- if (zeal == 0 && hasZealMode(ZealMode::GenerationalGC)) {
- evictNursery(JS::gcreason::DEBUG_GC);
- nursery.leaveZealMode();
- }
-
- ZealMode zealMode = ZealMode(zeal);
- if (zealMode == ZealMode::GenerationalGC)
- nursery.enterZealMode();
-
- // Zeal modes 8-10 are mutually exclusive. If we're setting one of those,
- // we first reset all of them.
- if (zealMode >= ZealMode::IncrementalRootsThenFinish &&
- zealMode <= ZealMode::IncrementalMultipleSlices)
- {
- clearZealMode(ZealMode::IncrementalRootsThenFinish);
- clearZealMode(ZealMode::IncrementalMarkAllThenFinish);
- clearZealMode(ZealMode::IncrementalMultipleSlices);
- }
-
- bool schedule = zealMode >= ZealMode::Alloc;
- if (zeal != 0)
- zealModeBits |= 1 << unsigned(zeal);
- else
- zealModeBits = 0;
- zealFrequency = frequency;
- nextScheduled = schedule ? frequency : 0;
-}
-
-void
-GCRuntime::setNextScheduled(uint32_t count)
-{
- nextScheduled = count;
-}
-
-bool
-GCRuntime::parseAndSetZeal(const char* str)
-{
- int frequency = -1;
- bool foundFrequency = false;
- mozilla::Vector<int, 0, SystemAllocPolicy> zeals;
-
- static const struct {
- const char* const zealMode;
- size_t length;
- uint32_t zeal;
- } zealModes[] = {
-#define ZEAL_MODE(name, value) {#name, sizeof(#name) - 1, value},
- JS_FOR_EACH_ZEAL_MODE(ZEAL_MODE)
-#undef ZEAL_MODE
- {"None", 4, 0}
- };
-
- do {
- int zeal = -1;
-
- const char* p = nullptr;
- if (isdigit(str[0])) {
- zeal = atoi(str);
-
- size_t offset = strspn(str, "0123456789");
- p = str + offset;
- } else {
- for (auto z : zealModes) {
- if (!strncmp(str, z.zealMode, z.length)) {
- zeal = z.zeal;
- p = str + z.length;
- break;
- }
- }
- }
- if (p) {
- if (!*p || *p == ';') {
- frequency = JS_DEFAULT_ZEAL_FREQ;
- } else if (*p == ',') {
- frequency = atoi(p + 1);
- foundFrequency = true;
- }
- }
-
- if (zeal < 0 || zeal > int(ZealMode::Limit) || frequency <= 0) {
- fprintf(stderr, "Format: JS_GC_ZEAL=level(;level)*[,N]\n");
- fputs(ZealModeHelpText, stderr);
- return false;
- }
-
- if (!zeals.emplaceBack(zeal)) {
- return false;
- }
- } while (!foundFrequency &&
- (str = strchr(str, ';')) != nullptr &&
- str++);
-
- for (auto z : zeals)
- setZeal(z, frequency);
- return true;
-}
-
-#endif
-
/*
* Lifetime in number of major GCs for type sets attached to scripts containing
* observed types.
@@ -1063,12 +912,6 @@ GCRuntime::init(uint32_t maxbytes, uint32_t maxNurseryBytes)
}
}
-#ifdef JS_GC_ZEAL
- const char* zealSpec = getenv("JS_GC_ZEAL");
- if (zealSpec && zealSpec[0] && !parseAndSetZeal(zealSpec))
- return false;
-#endif
-
if (!InitTrace(*this))
return false;
@@ -1094,11 +937,6 @@ GCRuntime::finish()
allocTask.cancel(GCParallelTask::CancelAndWait);
decommitTask.cancel(GCParallelTask::CancelAndWait);
-#ifdef JS_GC_ZEAL
- /* Free memory associated with GC verification. */
- finishVerifier();
-#endif
-
/* Delete all remaining zones. */
if (rt->gcInitialized) {
AutoSetThreadIsSweeping threadIsSweeping;
@@ -2635,7 +2473,7 @@ GCRuntime::releaseRelocatedArenasWithoutUnlocking(Arena* arenaList, const AutoLo
// Mark arena as empty
arena->setAsFullyUnused();
-#if defined(JS_CRASH_DIAGNOSTICS) || defined(JS_GC_ZEAL)
+#if defined(JS_CRASH_DIAGNOSTICS)
JS_POISON(reinterpret_cast<void*>(arena->thingsStart()),
JS_MOVED_TENURED_PATTERN, arena->getThingsSpan());
#endif
@@ -3048,13 +2886,6 @@ GCRuntime::triggerZoneGC(Zone* zone, JS::gcreason::Reason reason)
if (rt->isHeapCollecting())
return false;
-#ifdef JS_GC_ZEAL
- if (hasZealMode(ZealMode::Alloc)) {
- MOZ_RELEASE_ASSERT(triggerGC(reason));
- return true;
- }
-#endif
-
if (zone->isAtomsZone()) {
/* We can't do a zone GC of the atoms compartment. */
if (rt->keepAtoms()) {
@@ -3077,14 +2908,6 @@ GCRuntime::maybeGC(Zone* zone)
{
MOZ_ASSERT(CurrentThreadCanAccessRuntime(rt));
-#ifdef JS_GC_ZEAL
- if (hasZealMode(ZealMode::Alloc) || hasZealMode(ZealMode::Poke)) {
- JS::PrepareForFullGC(rt->contextFromMainThread());
- gc(GC_NORMAL, JS::gcreason::DEBUG_GC);
- return;
- }
-#endif
-
if (gcIfRequested())
return;
@@ -3418,11 +3241,6 @@ GCRuntime::shouldReleaseObservedTypes()
{
bool releaseTypes = false;
-#ifdef JS_GC_ZEAL
- if (zealModeBits != 0)
- releaseTypes = true;
-#endif
-
/* We may miss the exact target GC due to resets. */
if (majorGCNumber >= jitReleaseNumber)
releaseTypes = true;
@@ -4068,290 +3886,19 @@ GCRuntime::markAllGrayReferences(gcstats::Phase phase)
markGrayReferences<GCZonesIter, GCCompartmentsIter>(phase);
}
-#ifdef JS_GC_ZEAL
-
-struct GCChunkHasher {
- typedef gc::Chunk* Lookup;
-
- /*
- * Strip zeros for better distribution after multiplying by the golden
- * ratio.
- */
- static HashNumber hash(gc::Chunk* chunk) {
- MOZ_ASSERT(!(uintptr_t(chunk) & gc::ChunkMask));
- return HashNumber(uintptr_t(chunk) >> gc::ChunkShift);
- }
-
- static bool match(gc::Chunk* k, gc::Chunk* l) {
- MOZ_ASSERT(!(uintptr_t(k) & gc::ChunkMask));
- MOZ_ASSERT(!(uintptr_t(l) & gc::ChunkMask));
- return k == l;
- }
-};
-
-class js::gc::MarkingValidator
-{
- public:
- explicit MarkingValidator(GCRuntime* gc);
- ~MarkingValidator();
- void nonIncrementalMark(AutoLockForExclusiveAccess& lock);
- void validate();
-
- private:
- GCRuntime* gc;
- bool initialized;
-
- typedef HashMap<Chunk*, ChunkBitmap*, GCChunkHasher, SystemAllocPolicy> BitmapMap;
- BitmapMap map;
-};
-
-js::gc::MarkingValidator::MarkingValidator(GCRuntime* gc)
- : gc(gc),
- initialized(false)
-{}
-
-js::gc::MarkingValidator::~MarkingValidator()
-{
- if (!map.initialized())
- return;
-
- for (BitmapMap::Range r(map.all()); !r.empty(); r.popFront())
- js_delete(r.front().value());
-}
-
-void
-js::gc::MarkingValidator::nonIncrementalMark(AutoLockForExclusiveAccess& lock)
-{
- /*
- * Perform a non-incremental mark for all collecting zones and record
- * the results for later comparison.
- *
- * Currently this does not validate gray marking.
- */
-
- if (!map.init())
- return;
-
- JSRuntime* runtime = gc->rt;
- GCMarker* gcmarker = &gc->marker;
-
- gc->waitBackgroundSweepEnd();
-
- /* Save existing mark bits. */
- for (auto chunk = gc->allNonEmptyChunks(); !chunk.done(); chunk.next()) {
- ChunkBitmap* bitmap = &chunk->bitmap;
- ChunkBitmap* entry = js_new<ChunkBitmap>();
- if (!entry)
- return;
-
- memcpy((void*)entry->bitmap, (void*)bitmap->bitmap, sizeof(bitmap->bitmap));
- if (!map.putNew(chunk, entry))
- return;
- }
-
- /*
- * Temporarily clear the weakmaps' mark flags for the compartments we are
- * collecting.
- */
-
- WeakMapSet markedWeakMaps;
- if (!markedWeakMaps.init())
- return;
-
- /*
- * For saving, smush all of the keys into one big table and split them back
- * up into per-zone tables when restoring.
- */
- gc::WeakKeyTable savedWeakKeys(SystemAllocPolicy(), runtime->randomHashCodeScrambler());
- if (!savedWeakKeys.init())
- return;
-
- for (GCZonesIter zone(runtime); !zone.done(); zone.next()) {
- if (!WeakMapBase::saveZoneMarkedWeakMaps(zone, markedWeakMaps))
- return;
-
- AutoEnterOOMUnsafeRegion oomUnsafe;
- for (gc::WeakKeyTable::Range r = zone->gcWeakKeys.all(); !r.empty(); r.popFront()) {
- if (!savedWeakKeys.put(Move(r.front().key), Move(r.front().value)))
- oomUnsafe.crash("saving weak keys table for validator");
- }
-
- if (!zone->gcWeakKeys.clear())
- oomUnsafe.crash("clearing weak keys table for validator");
- }
-
- /*
- * After this point, the function should run to completion, so we shouldn't
- * do anything fallible.
- */
- initialized = true;
-
- /* Re-do all the marking, but non-incrementally. */
- js::gc::State state = gc->incrementalState;
- gc->incrementalState = State::MarkRoots;
-
- {
- gcstats::AutoPhase ap(gc->stats, gcstats::PHASE_MARK);
-
- {
- gcstats::AutoPhase ap(gc->stats, gcstats::PHASE_UNMARK);
-
- for (GCZonesIter zone(runtime); !zone.done(); zone.next())
- WeakMapBase::unmarkZone(zone);
-
- MOZ_ASSERT(gcmarker->isDrained());
- gcmarker->reset();
-
- for (auto chunk = gc->allNonEmptyChunks(); !chunk.done(); chunk.next())
- chunk->bitmap.clear();
- }
-
- gc->traceRuntimeForMajorGC(gcmarker, lock);
-
- gc->incrementalState = State::Mark;
- auto unlimited = SliceBudget::unlimited();
- MOZ_RELEASE_ASSERT(gc->marker.drainMarkStack(unlimited));
- }
-
- gc->incrementalState = State::Sweep;
- {
- gcstats::AutoPhase ap1(gc->stats, gcstats::PHASE_SWEEP);
- gcstats::AutoPhase ap2(gc->stats, gcstats::PHASE_SWEEP_MARK);
-
- gc->markAllWeakReferences(gcstats::PHASE_SWEEP_MARK_WEAK);
-
- /* Update zone state for gray marking. */
- for (GCZonesIter zone(runtime); !zone.done(); zone.next()) {
- MOZ_ASSERT(zone->isGCMarkingBlack());
- zone->setGCState(Zone::MarkGray);
- }
- gc->marker.setMarkColorGray();
-
- gc->markAllGrayReferences(gcstats::PHASE_SWEEP_MARK_GRAY);
- gc->markAllWeakReferences(gcstats::PHASE_SWEEP_MARK_GRAY_WEAK);
-
- /* Restore zone state. */
- for (GCZonesIter zone(runtime); !zone.done(); zone.next()) {
- MOZ_ASSERT(zone->isGCMarkingGray());
- zone->setGCState(Zone::Mark);
- }
- MOZ_ASSERT(gc->marker.isDrained());
- gc->marker.setMarkColorBlack();
- }
-
- /* Take a copy of the non-incremental mark state and restore the original. */
- for (auto chunk = gc->allNonEmptyChunks(); !chunk.done(); chunk.next()) {
- ChunkBitmap* bitmap = &chunk->bitmap;
- ChunkBitmap* entry = map.lookup(chunk)->value();
- Swap(*entry, *bitmap);
- }
-
- for (GCZonesIter zone(runtime); !zone.done(); zone.next()) {
- WeakMapBase::unmarkZone(zone);
- AutoEnterOOMUnsafeRegion oomUnsafe;
- if (!zone->gcWeakKeys.clear())
- oomUnsafe.crash("clearing weak keys table for validator");
- }
-
- WeakMapBase::restoreMarkedWeakMaps(markedWeakMaps);
-
- for (gc::WeakKeyTable::Range r = savedWeakKeys.all(); !r.empty(); r.popFront()) {
- AutoEnterOOMUnsafeRegion oomUnsafe;
- Zone* zone = gc::TenuredCell::fromPointer(r.front().key.asCell())->zone();
- if (!zone->gcWeakKeys.put(Move(r.front().key), Move(r.front().value)))
- oomUnsafe.crash("restoring weak keys table for validator");
- }
-
- gc->incrementalState = state;
-}
-
-void
-js::gc::MarkingValidator::validate()
-{
- /*
- * Validates the incremental marking for a single compartment by comparing
- * the mark bits to those previously recorded for a non-incremental mark.
- */
-
- if (!initialized)
- return;
-
- gc->waitBackgroundSweepEnd();
-
- for (auto chunk = gc->allNonEmptyChunks(); !chunk.done(); chunk.next()) {
- BitmapMap::Ptr ptr = map.lookup(chunk);
- if (!ptr)
- continue; /* Allocated after we did the non-incremental mark. */
-
- ChunkBitmap* bitmap = ptr->value();
- ChunkBitmap* incBitmap = &chunk->bitmap;
-
- for (size_t i = 0; i < ArenasPerChunk; i++) {
- if (chunk->decommittedArenas.get(i))
- continue;
- Arena* arena = &chunk->arenas[i];
- if (!arena->allocated())
- continue;
- if (!arena->zone->isGCSweeping())
- continue;
- if (arena->allocatedDuringIncremental)
- continue;
-
- AllocKind kind = arena->getAllocKind();
- uintptr_t thing = arena->thingsStart();
- uintptr_t end = arena->thingsEnd();
- while (thing < end) {
- Cell* cell = (Cell*)thing;
-
- /*
- * If a non-incremental GC wouldn't have collected a cell, then
- * an incremental GC won't collect it.
- */
- MOZ_ASSERT_IF(bitmap->isMarked(cell, BLACK), incBitmap->isMarked(cell, BLACK));
-
- /*
- * If the cycle collector isn't allowed to collect an object
- * after a non-incremental GC has run, then it isn't allowed to
- * collected it after an incremental GC.
- */
- MOZ_ASSERT_IF(!bitmap->isMarked(cell, GRAY), !incBitmap->isMarked(cell, GRAY));
-
- thing += Arena::thingSize(kind);
- }
- }
- }
-}
-
-#endif // JS_GC_ZEAL
-
void
GCRuntime::computeNonIncrementalMarkingForValidation(AutoLockForExclusiveAccess& lock)
{
-#ifdef JS_GC_ZEAL
- MOZ_ASSERT(!markingValidator);
- if (isIncremental && hasZealMode(ZealMode::IncrementalMarkingValidator))
- markingValidator = js_new<MarkingValidator>(this);
- if (markingValidator)
- markingValidator->nonIncrementalMark(lock);
-#endif
}
void
GCRuntime::validateIncrementalMarking()
{
-#ifdef JS_GC_ZEAL
- if (markingValidator)
- markingValidator->validate();
-#endif
}
void
GCRuntime::finishMarkingValidation()
{
-#ifdef JS_GC_ZEAL
- js_delete(markingValidator);
- markingValidator = nullptr;
-#endif
}
static void
@@ -5785,11 +5332,6 @@ AutoGCSlice::~AutoGCSlice()
void
GCRuntime::pushZealSelectedObjects()
{
-#ifdef JS_GC_ZEAL
- /* Push selected objects onto the mark stack and clear the list. */
- for (JSObject** obj = selectedForMarking.begin(); obj != selectedForMarking.end(); obj++)
- TraceManuallyBarrieredEdge(&marker, obj, "selected obj");
-#endif
}
static bool
@@ -5818,16 +5360,6 @@ GCRuntime::incrementalCollectSlice(SliceBudget& budget, JS::gcreason::Reason rea
gc::State initialState = incrementalState;
bool useZeal = false;
-#ifdef JS_GC_ZEAL
- if (reason == JS::gcreason::DEBUG_GC && !budget.isUnlimited()) {
- /*
- * Do the incremental collection type specified by zeal mode if the
- * collection was triggered by runDebugGC() and incremental GC has not
- * been cancelled by resetIncrementalGC().
- */
- useZeal = true;
- }
-#endif
MOZ_ASSERT_IF(isIncrementalGCInProgress(), isIncremental);
isIncremental = !budget.isUnlimited();
@@ -6202,11 +5734,6 @@ GCRuntime::gcCycle(bool nonincrementalByAPI, SliceBudget& budget, JS::gcreason::
chunkAllocationSinceLastGC = false;
-#ifdef JS_GC_ZEAL
- /* Keeping these around after a GC is dangerous. */
- clearSelectedForMarking();
-#endif
-
/* Clear gcMallocBytes for all zones. */
for (ZonesIter zone(rt, WithAtoms); !zone.done(); zone.next())
zone->resetGCMallocBytes();
@@ -6218,23 +5745,6 @@ GCRuntime::gcCycle(bool nonincrementalByAPI, SliceBudget& budget, JS::gcreason::
return false;
}
-#ifdef JS_GC_ZEAL
-static bool
-IsDeterministicGCReason(JS::gcreason::Reason reason)
-{
- if (reason > JS::gcreason::DEBUG_GC &&
- reason != JS::gcreason::CC_FORCED && reason != JS::gcreason::SHUTDOWN_CC)
- {
- return false;
- }
-
- if (reason == JS::gcreason::EAGER_ALLOC_TRIGGER)
- return false;
-
- return true;
-}
-#endif
-
gcstats::ZoneGCStats
GCRuntime::scanZonesBeforeGC()
{
@@ -6300,11 +5810,6 @@ GCRuntime::checkIfGCAllowedInCurrentState(JS::gcreason::Reason reason)
if (rt->isBeingDestroyed() && !IsShutdownGC(reason))
return false;
-#ifdef JS_GC_ZEAL
- if (deterministicOnly && !IsDeterministicGCReason(reason))
- return false;
-#endif
-
return true;
}
@@ -6360,13 +5865,6 @@ GCRuntime::collect(bool nonincrementalByAPI, SliceBudget budget, JS::gcreason::R
if (reason == JS::gcreason::COMPARTMENT_REVIVED)
maybeDoCycleCollection();
-
-#ifdef JS_GC_ZEAL
- if (rt->hasZealMode(ZealMode::CheckHeapAfterGC)) {
- gcstats::AutoPhase ap(rt->gc.stats, gcstats::PHASE_TRACE_HEAP);
- CheckHeapAfterGC(rt);
- }
-#endif
}
js::AutoEnqueuePendingParseTasksAfterGC::~AutoEnqueuePendingParseTasksAfterGC()
@@ -6460,17 +5958,6 @@ GCRuntime::notifyDidPaint()
{
MOZ_ASSERT(CurrentThreadCanAccessRuntime(rt));
-#ifdef JS_GC_ZEAL
- if (hasZealMode(ZealMode::FrameVerifierPre))
- verifyPreBarriers();
-
- if (hasZealMode(ZealMode::FrameGC)) {
- JS::PrepareForFullGC(rt->contextFromMainThread());
- gc(GC_NORMAL, JS::gcreason::REFRESH_FRAME);
- return;
- }
-#endif
-
if (isIncrementalGCInProgress() && !interFrameGC && tunables.areRefreshFrameSlicesEnabled()) {
JS::PrepareForIncrementalGC(rt->contextFromMainThread());
gcSlice(JS::gcreason::REFRESH_FRAME);
@@ -6566,11 +6053,6 @@ GCRuntime::minorGC(JS::gcreason::Reason reason, gcstats::Phase phase)
blocksToFreeAfterMinorGC.freeAll();
-#ifdef JS_GC_ZEAL
- if (rt->hasZealMode(ZealMode::CheckHeapAfterGC))
- CheckHeapAfterGC(rt);
-#endif
-
{
AutoLockGC lock(rt);
for (ZonesIter zone(rt, WithAtoms); !zone.done(); zone.next())
@@ -6756,59 +6238,6 @@ gc::MergeCompartments(JSCompartment* source, JSCompartment* target)
void
GCRuntime::runDebugGC()
{
-#ifdef JS_GC_ZEAL
- if (rt->mainThread.suppressGC)
- return;
-
- if (hasZealMode(ZealMode::GenerationalGC))
- return minorGC(JS::gcreason::DEBUG_GC);
-
- PrepareForDebugGC(rt);
-
- auto budget = SliceBudget::unlimited();
- if (hasZealMode(ZealMode::IncrementalRootsThenFinish) ||
- hasZealMode(ZealMode::IncrementalMarkAllThenFinish) ||
- hasZealMode(ZealMode::IncrementalMultipleSlices))
- {
- js::gc::State initialState = incrementalState;
- if (hasZealMode(ZealMode::IncrementalMultipleSlices)) {
- /*
- * Start with a small slice limit and double it every slice. This
- * ensure that we get multiple slices, and collection runs to
- * completion.
- */
- if (!isIncrementalGCInProgress())
- incrementalLimit = zealFrequency / 2;
- else
- incrementalLimit *= 2;
- budget = SliceBudget(WorkBudget(incrementalLimit));
- } else {
- // This triggers incremental GC but is actually ignored by IncrementalMarkSlice.
- budget = SliceBudget(WorkBudget(1));
- }
-
- if (!isIncrementalGCInProgress())
- invocationKind = GC_SHRINK;
- collect(false, budget, JS::gcreason::DEBUG_GC);
-
- /*
- * For multi-slice zeal, reset the slice size when we get to the sweep
- * or compact phases.
- */
- if (hasZealMode(ZealMode::IncrementalMultipleSlices)) {
- if ((initialState == State::Mark && incrementalState == State::Sweep) ||
- (initialState == State::Sweep && incrementalState == State::Compact))
- {
- incrementalLimit = zealFrequency / 2;
- }
- }
- } else if (hasZealMode(ZealMode::Compact)) {
- gc(GC_SHRINK, JS::gcreason::DEBUG_GC);
- } else {
- gc(GC_NORMAL, JS::gcreason::DEBUG_GC);
- }
-
-#endif
}
void
@@ -6818,28 +6247,6 @@ GCRuntime::setFullCompartmentChecks(bool enabled)
fullCompartmentChecks = enabled;
}
-#ifdef JS_GC_ZEAL
-bool
-GCRuntime::selectForMarking(JSObject* object)
-{
- MOZ_ASSERT(!rt->isHeapMajorCollecting());
- return selectedForMarking.append(object);
-}
-
-void
-GCRuntime::clearSelectedForMarking()
-{
- selectedForMarking.clearAndFree();
-}
-
-void
-GCRuntime::setDeterministic(bool enabled)
-{
- MOZ_ASSERT(!rt->isHeapMajorCollecting());
- deterministicOnly = enabled;
-}
-#endif
-
#ifdef DEBUG
/* Should only be called manually under gdb */
diff --git a/js/src/jsgc.h b/js/src/jsgc.h
index 79ac9596c..c0d86781d 100644
--- a/js/src/jsgc.h
+++ b/js/src/jsgc.h
@@ -1264,19 +1264,6 @@ enum VerifierType {
PreBarrierVerifier
};
-#ifdef JS_GC_ZEAL
-
-extern const char* ZealModeHelpText;
-
-/* Check that write barriers have been used correctly. See jsgc.cpp. */
-void
-VerifyBarriers(JSRuntime* rt, VerifierType type);
-
-void
-MaybeVerifyBarriers(JSContext* cx, bool always = false);
-
-#else
-
static inline void
VerifyBarriers(JSRuntime* rt, VerifierType type)
{
@@ -1287,8 +1274,6 @@ MaybeVerifyBarriers(JSContext* cx, bool always = false)
{
}
-#endif
-
/*
* Instances of this class set the |JSRuntime::suppressGC| flag for the duration
* that they are live. Use of this class is highly discouraged. Please carefully
diff --git a/js/src/jspubtd.h b/js/src/jspubtd.h
index 309b9d746..20ea1ef8b 100644
--- a/js/src/jspubtd.h
+++ b/js/src/jspubtd.h
@@ -22,7 +22,7 @@
#include "js/TraceKind.h"
#include "js/TypeDecls.h"
-#if defined(JS_GC_ZEAL) || defined(DEBUG)
+#if defined(DEBUG)
# define JSGC_HASH_TABLE_CHECKS
#endif
diff --git a/js/src/jsutil.h b/js/src/jsutil.h
index 790b97ddc..8ef4cac90 100644
--- a/js/src/jsutil.h
+++ b/js/src/jsutil.h
@@ -368,7 +368,7 @@ Poison(void* ptr, uint8_t value, size_t num)
#endif
/* Enable poisoning in crash-diagnostics and zeal builds. */
-#if defined(JS_CRASH_DIAGNOSTICS) || defined(JS_GC_ZEAL)
+#if defined(JS_CRASH_DIAGNOSTICS)
# define JS_POISON(p, val, size) Poison(p, val, size)
#else
# define JS_POISON(p, val, size) ((void) 0)
diff --git a/js/src/old-configure.in b/js/src/old-configure.in
index 1c5c9e214..e4589b951 100644
--- a/js/src/old-configure.in
+++ b/js/src/old-configure.in
@@ -1806,17 +1806,6 @@ if test -n "$MOZ_DEBUG"; then
fi
dnl ========================================================
-dnl Zealous JavaScript GC
-dnl ========================================================
-MOZ_ARG_ENABLE_BOOL(gczeal,
-[ --enable-gczeal Enable zealous GCing],
- JS_GC_ZEAL=1,
- JS_GC_ZEAL= )
-if test -n "$JS_GC_ZEAL" -o -n "$MOZ_DEBUG"; then
- AC_DEFINE(JS_GC_ZEAL)
-fi
-
-dnl ========================================================
dnl Enable breakpoint for artificial OOMs
dnl ========================================================
MOZ_ARG_ENABLE_BOOL(oom-breakpoint,
diff --git a/js/src/shell/js.cpp b/js/src/shell/js.cpp
index 00a4a503c..88d482a23 100644
--- a/js/src/shell/js.cpp
+++ b/js/src/shell/js.cpp
@@ -323,10 +323,6 @@ static bool enableNativeRegExp = false;
static bool enableUnboxedArrays = false;
static bool enableSharedMemory = SHARED_MEMORY_DEFAULT;
static bool enableWasmAlwaysBaseline = false;
-#ifdef JS_GC_ZEAL
-static uint32_t gZealBits = 0;
-static uint32_t gZealFrequency = 0;
-#endif
static bool printTiming = false;
static const char* jsCacheDir = nullptr;
static const char* jsCacheAsmJSPath = nullptr;
@@ -7517,16 +7513,6 @@ SetContextOptions(JSContext* cx, const OptionParser& op)
dumpEntrainedVariables = op.getBoolOption("dump-entrained-variables");
#endif
-#ifdef JS_GC_ZEAL
- const char* zealStr = op.getStringOption("gc-zeal");
- if (zealStr) {
- if (!cx->gc.parseAndSetZeal(zealStr))
- return false;
- uint32_t nextScheduled;
- cx->gc.getZealBits(&gZealBits, &gZealFrequency, &nextScheduled);
- }
-#endif
-
return true;
}
@@ -7544,16 +7530,6 @@ SetWorkerContextOptions(JSContext* cx)
cx->setOffthreadIonCompilationEnabled(offthreadCompilation);
cx->profilingScripts = enableCodeCoverage || enableDisassemblyDumps;
-#ifdef JS_GC_ZEAL
- if (gZealBits && gZealFrequency) {
-#define ZEAL_MODE(_, value) \
- if (gZealBits & (1 << value)) \
- cx->gc.setZeal(value, gZealFrequency);
- JS_FOR_EACH_ZEAL_MODE(ZEAL_MODE)
-#undef ZEAL_MODE
- }
-#endif
-
JS_SetNativeStackQuota(cx, gMaxStackSize);
}
@@ -7838,9 +7814,6 @@ main(int argc, char** argv, char** envp)
"NUMBER of instructions.", -1)
#endif
|| !op.addIntOption('\0', "nursery-size", "SIZE-MB", "Set the maximum nursery size in MB", 16)
-#ifdef JS_GC_ZEAL
- || !op.addStringOption('z', "gc-zeal", "LEVEL(;LEVEL)*[,N]", gc::ZealModeHelpText)
-#endif
|| !op.addStringOption('\0', "module-load-path", "DIR", "Set directory to load modules from")
)
{
diff --git a/js/src/vm/EnvironmentObject.h b/js/src/vm/EnvironmentObject.h
index 6bdaac89e..d457ca839 100644
--- a/js/src/vm/EnvironmentObject.h
+++ b/js/src/vm/EnvironmentObject.h
@@ -930,9 +930,6 @@ class DebugEnvironments
void mark(JSTracer* trc);
void sweep(JSRuntime* rt);
void finish();
-#ifdef JS_GC_ZEAL
- void checkHashTablesAfterMovingGC(JSRuntime* rt);
-#endif
// If a live frame has a synthesized entry in missingEnvs, make sure it's not
// collected.