summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--dom/workers/RuntimeService.cpp67
-rw-r--r--dom/workers/RuntimeService.h13
-rw-r--r--dom/workers/WorkerPrefs.h3
-rw-r--r--dom/workers/WorkerPrivate.cpp60
-rw-r--r--dom/workers/WorkerPrivate.h5
-rw-r--r--dom/workers/Workers.h8
-rw-r--r--ipc/testshell/XPCShellEnvironment.cpp18
-rw-r--r--js/src/builtin/TestingFunctions.cpp208
-rw-r--r--js/src/devtools/automation/variants/compacting1
-rw-r--r--js/src/devtools/automation/variants/rootanalysis1
-rw-r--r--js/src/gc/Allocator.cpp7
-rw-r--r--js/src/gc/GCInternals.h45
-rw-r--r--js/src/gc/GCRuntime.h116
-rw-r--r--js/src/gc/Heap.h16
-rw-r--r--js/src/gc/Nursery.cpp91
-rw-r--r--js/src/gc/Nursery.h12
-rw-r--r--js/src/gc/Verifier.cpp414
-rw-r--r--js/src/gc/Zone.h6
-rw-r--r--js/src/jit-test/tests/ion/bug730152.js4
-rw-r--r--js/src/jit-test/tests/ion/bug732758.js1
-rw-r--r--js/src/jit/CompileWrappers.h4
-rw-r--r--js/src/jit/VMFunctions.cpp10
-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/jsapi.h13
-rw-r--r--js/src/jsgc.cpp661
-rw-r--r--js/src/jsgc.h25
-rw-r--r--js/src/jsgcinlines.h6
-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/tests/shell.js15
-rw-r--r--js/src/vm/Caches-inl.h3
-rw-r--r--js/src/vm/EnvironmentObject.h3
-rw-r--r--js/src/vm/Interpreter.cpp10
-rw-r--r--js/src/vm/Runtime.cpp3
-rw-r--r--js/src/vm/Runtime.h2
-rw-r--r--js/xpconnect/idl/xpccomponents.idl5
-rw-r--r--js/xpconnect/src/XPCComponents.cpp9
-rw-r--r--js/xpconnect/src/XPCJSContext.cpp10
-rw-r--r--js/xpconnect/src/XPCShellImpl.cpp18
-rw-r--r--testing/specialpowers/content/specialpowersAPI.js4
48 files changed, 11 insertions, 2050 deletions
diff --git a/dom/workers/RuntimeService.cpp b/dom/workers/RuntimeService.cpp
index d1d76e3d1..1f5616873 100644
--- a/dom/workers/RuntimeService.cpp
+++ b/dom/workers/RuntimeService.cpp
@@ -290,13 +290,6 @@ LoadContextOptions(const char* aPrefName, void* /* aClosure */)
return;
}
-#ifdef JS_GC_ZEAL
- if (prefName.EqualsLiteral(PREF_JS_OPTIONS_PREFIX PREF_GCZEAL) ||
- prefName.EqualsLiteral(PREF_WORKERS_OPTIONS_PREFIX PREF_GCZEAL)) {
- return;
- }
-#endif
-
// Context options.
JS::ContextOptions contextOptions;
contextOptions.setAsmJS(GetWorkerPref<bool>(NS_LITERAL_CSTRING("asmjs")))
@@ -317,37 +310,6 @@ LoadContextOptions(const char* aPrefName, void* /* aClosure */)
}
}
-#ifdef JS_GC_ZEAL
-void
-LoadGCZealOptions(const char* /* aPrefName */, void* /* aClosure */)
-{
- AssertIsOnMainThread();
-
- RuntimeService* rts = RuntimeService::GetService();
- if (!rts) {
- // May be shutting down, just bail.
- return;
- }
-
- int32_t gczeal = GetWorkerPref<int32_t>(NS_LITERAL_CSTRING(PREF_GCZEAL), -1);
- if (gczeal < 0) {
- gczeal = 0;
- }
-
- int32_t frequency =
- GetWorkerPref<int32_t>(NS_LITERAL_CSTRING("gcZeal.frequency"), -1);
- if (frequency < 0) {
- frequency = JS_DEFAULT_ZEAL_FREQ;
- }
-
- RuntimeService::SetDefaultGCZeal(uint8_t(gczeal), uint32_t(frequency));
-
- if (rts) {
- rts->UpdateAllWorkerGCZeal();
- }
-}
-#endif
-
void
UpdateCommonJSGCMemoryOption(RuntimeService* aRuntimeService,
const nsACString& aPrefName, JSGCParamKey aKey)
@@ -994,10 +956,6 @@ InitJSContextForWorker(WorkerPrivate* aWorkerPrivate, JSContext* aWorkerCx)
js::SetCTypesActivityCallback(aWorkerCx, CTypesActivityCallback);
-#ifdef JS_GC_ZEAL
- JS_SetGCZeal(aWorkerCx, settings.gcZeal, settings.gcZealFrequency);
-#endif
-
return true;
}
@@ -1981,10 +1939,6 @@ RuntimeService::Init()
sDefaultJSSettings.chrome.maxScriptRuntime = -1;
sDefaultJSSettings.chrome.compartmentOptions.behaviors().setVersion(JSVERSION_LATEST);
sDefaultJSSettings.content.maxScriptRuntime = MAX_SCRIPT_RUN_TIME_SEC;
-#ifdef JS_GC_ZEAL
- sDefaultJSSettings.gcZealFrequency = JS_DEFAULT_ZEAL_FREQ;
- sDefaultJSSettings.gcZeal = 0;
-#endif
SetDefaultJSGCSettings(JSGC_MAX_BYTES, WORKER_DEFAULT_RUNTIME_HEAPSIZE);
SetDefaultJSGCSettings(JSGC_ALLOCATION_THRESHOLD,
WORKER_DEFAULT_ALLOCATION_THRESHOLD);
@@ -2033,12 +1987,6 @@ RuntimeService::Init()
LoadJSGCMemoryOptions,
PREF_WORKERS_OPTIONS_PREFIX PREF_MEM_OPTIONS_PREFIX,
nullptr)) ||
-#ifdef JS_GC_ZEAL
- NS_FAILED(Preferences::RegisterCallback(
- LoadGCZealOptions,
- PREF_JS_OPTIONS_PREFIX PREF_GCZEAL,
- nullptr)) ||
-#endif
#define WORKER_SIMPLE_PREF(name, getter, NAME) \
NS_FAILED(Preferences::RegisterCallbackAndCall( \
@@ -2227,12 +2175,6 @@ RuntimeService::Cleanup()
#undef WORKER_SIMPLE_PREF
#undef WORKER_PREF
-#ifdef JS_GC_ZEAL
- NS_FAILED(Preferences::UnregisterCallback(
- LoadGCZealOptions,
- PREF_JS_OPTIONS_PREFIX PREF_GCZEAL,
- nullptr)) ||
-#endif
NS_FAILED(Preferences::UnregisterCallback(
LoadJSGCMemoryOptions,
PREF_JS_OPTIONS_PREFIX PREF_MEM_OPTIONS_PREFIX,
@@ -2644,15 +2586,6 @@ RuntimeService::UpdateAllWorkerMemoryParameter(JSGCParamKey aKey,
BROADCAST_ALL_WORKERS(UpdateJSWorkerMemoryParameter, aKey, aValue);
}
-#ifdef JS_GC_ZEAL
-void
-RuntimeService::UpdateAllWorkerGCZeal()
-{
- BROADCAST_ALL_WORKERS(UpdateGCZeal, sDefaultJSSettings.gcZeal,
- sDefaultJSSettings.gcZealFrequency);
-}
-#endif
-
void
RuntimeService::GarbageCollectAllWorkers(bool aShrinking)
{
diff --git a/dom/workers/RuntimeService.h b/dom/workers/RuntimeService.h
index 2e5cc1dad..2ab8cbabe 100644
--- a/dom/workers/RuntimeService.h
+++ b/dom/workers/RuntimeService.h
@@ -215,19 +215,6 @@ public:
void
UpdateAllWorkerMemoryParameter(JSGCParamKey aKey, uint32_t aValue);
-#ifdef JS_GC_ZEAL
- static void
- SetDefaultGCZeal(uint8_t aGCZeal, uint32_t aFrequency)
- {
- AssertIsOnMainThread();
- sDefaultJSSettings.gcZeal = aGCZeal;
- sDefaultJSSettings.gcZealFrequency = aFrequency;
- }
-
- void
- UpdateAllWorkerGCZeal();
-#endif
-
void
GarbageCollectAllWorkers(bool aShrinking);
diff --git a/dom/workers/WorkerPrefs.h b/dom/workers/WorkerPrefs.h
index c9b605a84..9a1be4801 100644
--- a/dom/workers/WorkerPrefs.h
+++ b/dom/workers/WorkerPrefs.h
@@ -44,6 +44,3 @@ WORKER_PREF("intl.accept_languages", PrefLanguagesChanged)
WORKER_PREF("general.appname.override", AppNameOverrideChanged)
WORKER_PREF("general.appversion.override", AppVersionOverrideChanged)
WORKER_PREF("general.platform.override", PlatformOverrideChanged)
-#ifdef JS_GC_ZEAL
-WORKER_PREF("dom.workers.options.gcZeal", LoadGCZealOptions)
-#endif
diff --git a/dom/workers/WorkerPrivate.cpp b/dom/workers/WorkerPrivate.cpp
index 1df4e5551..c2ab4aca3 100644
--- a/dom/workers/WorkerPrivate.cpp
+++ b/dom/workers/WorkerPrivate.cpp
@@ -1391,30 +1391,6 @@ private:
}
};
-#ifdef JS_GC_ZEAL
-class UpdateGCZealRunnable final : public WorkerControlRunnable
-{
- uint8_t mGCZeal;
- uint32_t mFrequency;
-
-public:
- UpdateGCZealRunnable(WorkerPrivate* aWorkerPrivate,
- uint8_t aGCZeal,
- uint32_t aFrequency)
- : WorkerControlRunnable(aWorkerPrivate, WorkerThreadUnchangedBusyCount),
- mGCZeal(aGCZeal), mFrequency(aFrequency)
- { }
-
-private:
- virtual bool
- WorkerRun(JSContext* aCx, WorkerPrivate* aWorkerPrivate) override
- {
- aWorkerPrivate->UpdateGCZealInternal(aCx, mGCZeal, mFrequency);
- return true;
- }
-};
-#endif
-
class GarbageCollectRunnable final : public WorkerControlRunnable
{
bool mShrinking;
@@ -3148,27 +3124,6 @@ WorkerPrivateParent<Derived>::UpdateJSWorkerMemoryParameter(JSGCParamKey aKey,
}
}
-#ifdef JS_GC_ZEAL
-template <class Derived>
-void
-WorkerPrivateParent<Derived>::UpdateGCZeal(uint8_t aGCZeal, uint32_t aFrequency)
-{
- AssertIsOnParentThread();
-
- {
- MutexAutoLock lock(mMutex);
- mJSSettings.gcZeal = aGCZeal;
- mJSSettings.gcZealFrequency = aFrequency;
- }
-
- RefPtr<UpdateGCZealRunnable> runnable =
- new UpdateGCZealRunnable(ParentAsWorkerPrivate(), aGCZeal, aFrequency);
- if (!runnable->Dispatch()) {
- NS_WARNING("Failed to update worker gczeal!");
- }
-}
-#endif
-
template <class Derived>
void
WorkerPrivateParent<Derived>::GarbageCollect(bool aShrinking)
@@ -6323,21 +6278,6 @@ WorkerPrivate::UpdateJSWorkerMemoryParameterInternal(JSContext* aCx,
}
}
-#ifdef JS_GC_ZEAL
-void
-WorkerPrivate::UpdateGCZealInternal(JSContext* aCx, uint8_t aGCZeal,
- uint32_t aFrequency)
-{
- AssertIsOnWorkerThread();
-
- JS_SetGCZeal(aCx, aGCZeal, aFrequency);
-
- for (uint32_t index = 0; index < mChildWorkers.Length(); index++) {
- mChildWorkers[index]->UpdateGCZeal(aGCZeal, aFrequency);
- }
-}
-#endif
-
void
WorkerPrivate::GarbageCollectInternal(JSContext* aCx, bool aShrinking,
bool aCollectChildren)
diff --git a/dom/workers/WorkerPrivate.h b/dom/workers/WorkerPrivate.h
index ad906b054..8008f30e5 100644
--- a/dom/workers/WorkerPrivate.h
+++ b/dom/workers/WorkerPrivate.h
@@ -386,11 +386,6 @@ public:
void
UpdateJSWorkerMemoryParameter(JSGCParamKey key, uint32_t value);
-#ifdef JS_GC_ZEAL
- void
- UpdateGCZeal(uint8_t aGCZeal, uint32_t aFrequency);
-#endif
-
void
GarbageCollect(bool aShrinking);
diff --git a/dom/workers/Workers.h b/dom/workers/Workers.h
index 89e2ccfca..ad083d3b8 100644
--- a/dom/workers/Workers.h
+++ b/dom/workers/Workers.h
@@ -143,15 +143,7 @@ struct JSSettings
JSGCSettingsArray gcSettings;
JS::ContextOptions contextOptions;
-#ifdef JS_GC_ZEAL
- uint8_t gcZeal;
- uint32_t gcZealFrequency;
-#endif
-
JSSettings()
-#ifdef JS_GC_ZEAL
- : gcZeal(0), gcZealFrequency(0)
-#endif
{
for (uint32_t index = 0; index < ArrayLength(gcSettings); index++) {
new (gcSettings + index) JSGCSetting();
diff --git a/ipc/testshell/XPCShellEnvironment.cpp b/ipc/testshell/XPCShellEnvironment.cpp
index a6979ccae..455a14610 100644
--- a/ipc/testshell/XPCShellEnvironment.cpp
+++ b/ipc/testshell/XPCShellEnvironment.cpp
@@ -231,21 +231,6 @@ GC(JSContext *cx,
return true;
}
-#ifdef JS_GC_ZEAL
-static bool
-GCZeal(JSContext *cx, unsigned argc, JS::Value *vp)
-{
- CallArgs args = CallArgsFromVp(argc, vp);
-
- uint32_t zeal;
- if (!ToUint32(cx, args.get(0), &zeal))
- return false;
-
- JS_SetGCZeal(cx, uint8_t(zeal), JS_DEFAULT_ZEAL_FREQ);
- return true;
-}
-#endif
-
const JSFunctionSpec gGlobalFunctions[] =
{
JS_FS("print", Print, 0,0),
@@ -255,9 +240,6 @@ const JSFunctionSpec gGlobalFunctions[] =
JS_FS("dumpXPC", DumpXPC, 1,0),
JS_FS("dump", Dump, 1,0),
JS_FS("gc", GC, 0,0),
- #ifdef JS_GC_ZEAL
- JS_FS("gczeal", GCZeal, 1,0),
- #endif
JS_FS_END
};
diff --git a/js/src/builtin/TestingFunctions.cpp b/js/src/builtin/TestingFunctions.cpp
index 5bc69a346..acf449b7e 100644
--- a/js/src/builtin/TestingFunctions.cpp
+++ b/js/src/builtin/TestingFunctions.cpp
@@ -188,14 +188,6 @@ GetBuildConfiguration(JSContext* cx, unsigned argc, Value* vp)
if (!JS_SetProperty(cx, info, "tsan", value))
return false;
-#ifdef JS_GC_ZEAL
- value = BooleanValue(true);
-#else
- value = BooleanValue(false);
-#endif
- if (!JS_SetProperty(cx, info, "has-gczeal", value))
- return false;
-
#ifdef JS_MORE_DETERMINISTIC
value = BooleanValue(true);
#else
@@ -731,171 +723,6 @@ GCPreserveCode(JSContext* cx, unsigned argc, Value* vp)
return true;
}
-#ifdef JS_GC_ZEAL
-static bool
-GCZeal(JSContext* cx, unsigned argc, Value* vp)
-{
- CallArgs args = CallArgsFromVp(argc, vp);
-
- if (args.length() > 2) {
- RootedObject callee(cx, &args.callee());
- ReportUsageErrorASCII(cx, callee, "Too many arguments");
- return false;
- }
-
- uint32_t zeal;
- if (!ToUint32(cx, args.get(0), &zeal))
- return false;
-
- if (zeal > uint32_t(gc::ZealMode::Limit)) {
- JS_ReportErrorASCII(cx, "gczeal argument out of range");
- return false;
- }
-
- uint32_t frequency = JS_DEFAULT_ZEAL_FREQ;
- if (args.length() >= 2) {
- if (!ToUint32(cx, args.get(1), &frequency))
- return false;
- }
-
- JS_SetGCZeal(cx, (uint8_t)zeal, frequency);
- args.rval().setUndefined();
- return true;
-}
-
-static bool
-ScheduleGC(JSContext* cx, unsigned argc, Value* vp)
-{
- CallArgs args = CallArgsFromVp(argc, vp);
-
- if (args.length() > 1) {
- RootedObject callee(cx, &args.callee());
- ReportUsageErrorASCII(cx, callee, "Too many arguments");
- return false;
- }
-
- if (args.length() == 0) {
- /* Fetch next zeal trigger only. */
- } else if (args[0].isInt32()) {
- /* Schedule a GC to happen after |arg| allocations. */
- JS_ScheduleGC(cx, args[0].toInt32());
- } else if (args[0].isObject()) {
- /* Ensure that |zone| is collected during the next GC. */
- Zone* zone = UncheckedUnwrap(&args[0].toObject())->zone();
- PrepareZoneForGC(zone);
- } else if (args[0].isString()) {
- /* This allows us to schedule the atoms zone for GC. */
- Zone* zone = args[0].toString()->zoneFromAnyThread();
- if (!CurrentThreadCanAccessZone(zone)) {
- RootedObject callee(cx, &args.callee());
- ReportUsageErrorASCII(cx, callee, "Specified zone not accessible for GC");
- return false;
- }
- PrepareZoneForGC(zone);
- } else {
- RootedObject callee(cx, &args.callee());
- ReportUsageErrorASCII(cx, callee, "Bad argument - expecting integer, object or string");
- return false;
- }
-
- uint32_t zealBits;
- uint32_t freq;
- uint32_t next;
- JS_GetGCZealBits(cx, &zealBits, &freq, &next);
- args.rval().setInt32(next);
- return true;
-}
-
-static bool
-SelectForGC(JSContext* cx, unsigned argc, Value* vp)
-{
- CallArgs args = CallArgsFromVp(argc, vp);
-
- /*
- * The selectedForMarking set is intended to be manually marked at slice
- * start to detect missing pre-barriers. It is invalid for nursery things
- * to be in the set, so evict the nursery before adding items.
- */
- JSRuntime* rt = cx->runtime();
- rt->gc.evictNursery();
-
- for (unsigned i = 0; i < args.length(); i++) {
- if (args[i].isObject()) {
- if (!rt->gc.selectForMarking(&args[i].toObject()))
- return false;
- }
- }
-
- args.rval().setUndefined();
- return true;
-}
-
-static bool
-VerifyPreBarriers(JSContext* cx, unsigned argc, Value* vp)
-{
- CallArgs args = CallArgsFromVp(argc, vp);
-
- if (args.length() > 0) {
- RootedObject callee(cx, &args.callee());
- ReportUsageErrorASCII(cx, callee, "Too many arguments");
- return false;
- }
-
- gc::VerifyBarriers(cx->runtime(), gc::PreBarrierVerifier);
- args.rval().setUndefined();
- return true;
-}
-
-static bool
-VerifyPostBarriers(JSContext* cx, unsigned argc, Value* vp)
-{
- // This is a no-op since the post barrier verifier was removed.
- CallArgs args = CallArgsFromVp(argc, vp);
- if (args.length()) {
- RootedObject callee(cx, &args.callee());
- ReportUsageErrorASCII(cx, callee, "Too many arguments");
- return false;
- }
- args.rval().setUndefined();
- return true;
-}
-
-static bool
-GCState(JSContext* cx, unsigned argc, Value* vp)
-{
- CallArgs args = CallArgsFromVp(argc, vp);
-
- if (args.length() != 0) {
- RootedObject callee(cx, &args.callee());
- ReportUsageErrorASCII(cx, callee, "Too many arguments");
- return false;
- }
-
- const char* state = StateName(cx->runtime()->gc.state());
- JSString* str = JS_NewStringCopyZ(cx, state);
- if (!str)
- return false;
- args.rval().setString(str);
- return true;
-}
-
-static bool
-DeterministicGC(JSContext* cx, unsigned argc, Value* vp)
-{
- CallArgs args = CallArgsFromVp(argc, vp);
-
- if (args.length() != 1) {
- RootedObject callee(cx, &args.callee());
- ReportUsageErrorASCII(cx, callee, "Wrong number of arguments");
- return false;
- }
-
- cx->runtime()->gc.setDeterministic(ToBoolean(args[0]));
- args.rval().setUndefined();
- return true;
-}
-#endif /* JS_GC_ZEAL */
-
static bool
StartGC(JSContext* cx, unsigned argc, Value* vp)
{
@@ -1437,8 +1264,6 @@ OOMTest(JSContext* cx, unsigned argc, Value* vp)
MOZ_ASSERT(!cx->isExceptionPending());
rt->hadOutOfMemory = false;
- JS_SetGCZeal(cx, 0, JS_DEFAULT_ZEAL_FREQ);
-
for (unsigned thread = threadStart; thread < threadEnd; thread++) {
if (verbose)
fprintf(stderr, "thread %d\n", thread);
@@ -4387,39 +4212,6 @@ JS_FN_HELP("rejectPromise", RejectPromise, 2, 0,
"gcPreserveCode()",
" Preserve JIT code during garbage collections."),
-#ifdef JS_GC_ZEAL
- JS_FN_HELP("gczeal", GCZeal, 2, 0,
-"gczeal(level, [N])",
-gc::ZealModeHelpText),
-
- JS_FN_HELP("schedulegc", ScheduleGC, 1, 0,
-"schedulegc([num | obj | string])",
-" If num is given, schedule a GC after num allocations.\n"
-" If obj is given, schedule a GC of obj's zone.\n"
-" If string is given, schedule a GC of the string's zone if possible.\n"
-" Returns the number of allocations before the next trigger."),
-
- JS_FN_HELP("selectforgc", SelectForGC, 0, 0,
-"selectforgc(obj1, obj2, ...)",
-" Schedule the given objects to be marked in the next GC slice."),
-
- JS_FN_HELP("verifyprebarriers", VerifyPreBarriers, 0, 0,
-"verifyprebarriers()",
-" Start or end a run of the pre-write barrier verifier."),
-
- JS_FN_HELP("verifypostbarriers", VerifyPostBarriers, 0, 0,
-"verifypostbarriers()",
-" Does nothing (the post-write barrier verifier has been remove)."),
-
- JS_FN_HELP("gcstate", GCState, 0, 0,
-"gcstate()",
-" Report the global GC state."),
-
- JS_FN_HELP("deterministicgc", DeterministicGC, 1, 0,
-"deterministicgc(true|false)",
-" If true, only allow determinstic GCs to run."),
-#endif
-
JS_FN_HELP("startgc", StartGC, 1, 0,
"startgc([n [, 'shrinking']])",
" Start an incremental GC and run a slice that processes about n objects.\n"
diff --git a/js/src/devtools/automation/variants/compacting b/js/src/devtools/automation/variants/compacting
index cd1891bfe..2ffade6ac 100644
--- a/js/src/devtools/automation/variants/compacting
+++ b/js/src/devtools/automation/variants/compacting
@@ -3,7 +3,6 @@
"optimize": true,
"debug": true,
"env": {
- "JS_GC_ZEAL": "Compact",
"JITTEST_EXTRA_ARGS": "--jitflags=debug --ignore-timeouts={DIR}/cgc-jittest-timeouts.txt",
"JSTESTS_EXTRA_ARGS": "--exclude-file={DIR}/cgc-jstests-slow.txt"
},
diff --git a/js/src/devtools/automation/variants/rootanalysis b/js/src/devtools/automation/variants/rootanalysis
index c5ed4dfcd..508e1e2db 100644
--- a/js/src/devtools/automation/variants/rootanalysis
+++ b/js/src/devtools/automation/variants/rootanalysis
@@ -3,7 +3,6 @@
"optimize": true,
"debug": true,
"env": {
- "JS_GC_ZEAL": "GenerationalGC",
"JSTESTS_EXTRA_ARGS": "--jitflags=debug"
}
}
diff --git a/js/src/gc/Allocator.cpp b/js/src/gc/Allocator.cpp
index f7dc50d02..3994d5a5b 100644
--- a/js/src/gc/Allocator.cpp
+++ b/js/src/gc/Allocator.cpp
@@ -190,7 +190,7 @@ GCRuntime::checkAllocatorState(JSContext* cx, AllocKind kind)
return false;
}
-#if defined(JS_GC_ZEAL) || defined(DEBUG)
+#if defined(DEBUG)
MOZ_ASSERT_IF(cx->compartment()->isAtomsCompartment(),
kind == AllocKind::ATOM ||
kind == AllocKind::FAT_INLINE_ATOM ||
@@ -223,11 +223,6 @@ GCRuntime::checkAllocatorState(JSContext* cx, AllocKind kind)
bool
GCRuntime::gcIfNeededPerAllocation(JSContext* cx)
{
-#ifdef JS_GC_ZEAL
- if (needZealousGC())
- runDebugGC();
-#endif
-
// Invoking the interrupt callback can fail and we can't usefully
// handle that here. Just check in case we need to collect instead.
if (rt->hasPendingInterrupt())
diff --git a/js/src/gc/GCInternals.h b/js/src/gc/GCInternals.h
index 722539e1c..4919b87a5 100644
--- a/js/src/gc/GCInternals.h
+++ b/js/src/gc/GCInternals.h
@@ -61,51 +61,6 @@ class MOZ_RAII AutoPrepareForTracing
AbortReason
IsIncrementalGCUnsafe(JSRuntime* rt);
-#ifdef JS_GC_ZEAL
-
-class MOZ_RAII AutoStopVerifyingBarriers
-{
- GCRuntime* gc;
- bool restartPreVerifier;
-
- public:
- AutoStopVerifyingBarriers(JSRuntime* rt, bool isShutdown)
- : gc(&rt->gc)
- {
- if (gc->isVerifyPreBarriersEnabled()) {
- gc->endVerifyPreBarriers();
- restartPreVerifier = !isShutdown;
- } else {
- restartPreVerifier = false;
- }
- }
-
- ~AutoStopVerifyingBarriers() {
- // Nasty special case: verification runs a minor GC, which *may* nest
- // inside of an outer minor GC. This is not allowed by the
- // gc::Statistics phase tree. So we pause the "real" GC, if in fact one
- // is in progress.
- gcstats::Phase outer = gc->stats.currentPhase();
- if (outer != gcstats::PHASE_NONE)
- gc->stats.endPhase(outer);
- MOZ_ASSERT((gc->stats.currentPhase() == gcstats::PHASE_NONE) ||
- (gc->stats.currentPhase() == gcstats::PHASE_GC_BEGIN) ||
- (gc->stats.currentPhase() == gcstats::PHASE_GC_END));
-
- if (restartPreVerifier)
- gc->startVerifyPreBarriers();
-
- if (outer != gcstats::PHASE_NONE)
- gc->stats.beginPhase(outer);
- }
-};
-#else
-struct MOZ_RAII AutoStopVerifyingBarriers
-{
- AutoStopVerifyingBarriers(JSRuntime*, bool) {}
-};
-#endif /* JS_GC_ZEAL */
-
#ifdef JSGC_HASH_TABLE_CHECKS
void CheckHashTablesAfterMovingGC(JSRuntime* rt);
void CheckHeapAfterGC(JSRuntime* rt);
diff --git a/js/src/gc/GCRuntime.h b/js/src/gc/GCRuntime.h
index 8c9322849..19737c9ee 100644
--- a/js/src/gc/GCRuntime.h
+++ b/js/src/gc/GCRuntime.h
@@ -600,11 +600,6 @@ class GCRuntime
void finishRoots();
void finish();
- inline bool hasZealMode(ZealMode mode);
- inline void clearZealMode(ZealMode mode);
- inline bool upcomingZealousGC();
- inline bool needZealousGC();
-
MOZ_MUST_USE bool addRoot(Value* vp, const char* name);
void removeRoot(Value* vp);
void setMarkStackLimit(size_t limit, AutoLockGC& lock);
@@ -638,7 +633,6 @@ class GCRuntime
MOZ_RELEASE_ASSERT(triggerGC(JS::gcreason::ALLOC_TRIGGER));
}
- void runDebugGC();
inline void poke();
enum TraceOrMarkRuntime {
@@ -653,19 +647,6 @@ class GCRuntime
void onOutOfMallocMemory();
void onOutOfMallocMemory(const AutoLockGC& lock);
-#ifdef JS_GC_ZEAL
- const void* addressOfZealModeBits() { return &zealModeBits; }
- void getZealBits(uint32_t* zealBits, uint32_t* frequency, uint32_t* nextScheduled);
- void setZeal(uint8_t zeal, uint32_t frequency);
- bool parseAndSetZeal(const char* str);
- void setNextScheduled(uint32_t count);
- void verifyPreBarriers();
- void maybeVerifyPreBarriers(bool always);
- bool selectForMarking(JSObject* object);
- void clearSelectedForMarking();
- void setDeterministic(bool enable);
-#endif
-
size_t maxMallocBytesAllocated() { return maxMallocBytes; }
uint64_t nextCellUniqueId() {
@@ -851,15 +832,6 @@ class GCRuntime
AutoMaybeStartBackgroundAllocation& maybeStartBGAlloc);
void recycleChunk(Chunk* chunk, const AutoLockGC& lock);
-#ifdef JS_GC_ZEAL
- void startVerifyPreBarriers();
- void endVerifyPreBarriers();
- void finishVerifier();
- bool isVerifyPreBarriersEnabled() const { return !!verifyPreData; }
-#else
- bool isVerifyPreBarriersEnabled() const { return false; }
-#endif
-
// Free certain LifoAlloc blocks when it is safe to do so.
void freeUnusedLifoBlocksAfterSweeping(LifoAlloc* lifo);
void freeAllLifoBlocksAfterSweeping(LifoAlloc* lifo);
@@ -948,7 +920,6 @@ class GCRuntime
void incrementalCollectSlice(SliceBudget& budget, JS::gcreason::Reason reason,
AutoLockForExclusiveAccess& lock);
- void pushZealSelectedObjects();
void purgeRuntime(AutoLockForExclusiveAccess& lock);
MOZ_MUST_USE bool beginMarkPhase(JS::gcreason::Reason reason, AutoLockForExclusiveAccess& lock);
bool shouldPreserveJITCode(JSCompartment* comp, int64_t currentTime,
@@ -1004,10 +975,6 @@ class GCRuntime
void releaseRelocatedArenasWithoutUnlocking(Arena* arenaList, const AutoLockGC& lock);
void finishCollection(JS::gcreason::Reason reason);
- void computeNonIncrementalMarkingForValidation(AutoLockForExclusiveAccess& lock);
- void validateIncrementalMarking();
- void finishMarkingValidation();
-
#ifdef DEBUG
void checkForCompartmentMismatches();
#endif
@@ -1219,10 +1186,6 @@ class GCRuntime
ZoneList zonesToMaybeCompact;
Arena* relocatedArenasToRelease;
-#ifdef JS_GC_ZEAL
- MarkingValidator* markingValidator;
-#endif
-
/*
* Indicates that a GC slice has taken place in the middle of an animation
* frame, rather than at the beginning. In this case, the next slice will be
@@ -1274,40 +1237,6 @@ class GCRuntime
bool poked;
- /*
- * These options control the zealousness of the GC. At every allocation,
- * nextScheduled is decremented. When it reaches zero we do a full GC.
- *
- * At this point, if zeal_ is one of the types that trigger periodic
- * collection, then nextScheduled is reset to the value of zealFrequency.
- * Otherwise, no additional GCs take place.
- *
- * You can control these values in several ways:
- * - Set the JS_GC_ZEAL environment variable
- * - Call gczeal() or schedulegc() from inside shell-executed JS code
- * (see the help for details)
- *
- * If gcZeal_ == 1 then we perform GCs in select places (during MaybeGC and
- * whenever a GC poke happens). This option is mainly useful to embedders.
- *
- * We use zeal_ == 4 to enable write barrier verification. See the comment
- * in jsgc.cpp for more information about this.
- *
- * zeal_ values from 8 to 10 periodically run different types of
- * incremental GC.
- *
- * zeal_ value 14 performs periodic shrinking collections.
- */
-#ifdef JS_GC_ZEAL
- uint32_t zealModeBits;
- int zealFrequency;
- int nextScheduled;
- bool deterministicOnly;
- int incrementalLimit;
-
- Vector<JSObject*, 0, SystemAllocPolicy> selectedForMarking;
-#endif
-
bool fullCompartmentChecks;
Callback<JSGCCallback> gcCallback;
@@ -1415,51 +1344,6 @@ class MOZ_RAII AutoMaybeStartBackgroundAllocation
}
};
-#ifdef JS_GC_ZEAL
-
-inline bool
-GCRuntime::hasZealMode(ZealMode mode)
-{
- static_assert(size_t(ZealMode::Limit) < sizeof(zealModeBits) * 8,
- "Zeal modes must fit in zealModeBits");
- return zealModeBits & (1 << uint32_t(mode));
-}
-
-inline void
-GCRuntime::clearZealMode(ZealMode mode)
-{
- zealModeBits &= ~(1 << uint32_t(mode));
- MOZ_ASSERT(!hasZealMode(mode));
-}
-
-inline bool
-GCRuntime::upcomingZealousGC() {
- return nextScheduled == 1;
-}
-
-inline bool
-GCRuntime::needZealousGC() {
- if (nextScheduled > 0 && --nextScheduled == 0) {
- if (hasZealMode(ZealMode::Alloc) ||
- hasZealMode(ZealMode::GenerationalGC) ||
- hasZealMode(ZealMode::IncrementalRootsThenFinish) ||
- hasZealMode(ZealMode::IncrementalMarkAllThenFinish) ||
- hasZealMode(ZealMode::IncrementalMultipleSlices) ||
- hasZealMode(ZealMode::Compact))
- {
- nextScheduled = zealFrequency;
- }
- return true;
- }
- return false;
-}
-#else
-inline bool GCRuntime::hasZealMode(ZealMode mode) { return false; }
-inline void GCRuntime::clearZealMode(ZealMode mode) { }
-inline bool GCRuntime::upcomingZealousGC() { return false; }
-inline bool GCRuntime::needZealousGC() { return false; }
-#endif
-
} /* namespace gc */
} /* namespace js */
diff --git a/js/src/gc/Heap.h b/js/src/gc/Heap.h
index 2a9390e91..697803380 100644
--- a/js/src/gc/Heap.h
+++ b/js/src/gc/Heap.h
@@ -1322,22 +1322,6 @@ TenuredCell::writeBarrierPre(TenuredCell* thing)
if (!thing)
return;
-#ifdef JS_GC_ZEAL
- // When verifying pre barriers we need to switch on all barriers, even
- // those on the Atoms Zone. Normally, we never enter a parse task when
- // collecting in the atoms zone, so will filter out atoms below.
- // Unfortuantely, If we try that when verifying pre-barriers, we'd never be
- // able to handle OMT parse tasks at all as we switch on the verifier any
- // time we're not doing GC. This would cause us to deadlock, as OMT parsing
- // is meant to resume after GC work completes. Instead we filter out any
- // OMT barriers that reach us and assert that they would normally not be
- // possible.
- if (!CurrentThreadCanAccessRuntime(thing->runtimeFromAnyThread())) {
- AssertSafeToSkipBarrier(thing);
- return;
- }
-#endif
-
JS::shadow::Zone* shadowZone = thing->shadowZoneFromAnyThread();
if (shadowZone->needsIncrementalBarrier()) {
MOZ_ASSERT(!RuntimeFromMainThreadIsHeapMajorCollecting(shadowZone));
diff --git a/js/src/gc/Nursery.cpp b/js/src/gc/Nursery.cpp
index 2c402fe0b..bce2b74aa 100644
--- a/js/src/gc/Nursery.cpp
+++ b/js/src/gc/Nursery.cpp
@@ -74,14 +74,6 @@ struct js::Nursery::SweepAction
#endif
};
-#ifdef JS_GC_ZEAL
-struct js::Nursery::Canary
-{
- uintptr_t magicValue;
- Canary* next;
-};
-#endif
-
inline void
js::Nursery::NurseryChunk::poisonAndInit(JSRuntime* rt, uint8_t poison)
{
@@ -124,9 +116,6 @@ js::Nursery::Nursery(JSRuntime* rt)
, minorGcCount_(0)
, freeMallocedBuffersTask(nullptr)
, sweepActions_(nullptr)
-#ifdef JS_GC_ZEAL
- , lastCanary_(nullptr)
-#endif
{}
bool
@@ -199,7 +188,6 @@ void
js::Nursery::enable()
{
MOZ_ASSERT(isEmpty());
- MOZ_ASSERT(!runtime()->gc.isVerifyPreBarriersEnabled());
if (isEnabled())
return;
@@ -209,10 +197,6 @@ js::Nursery::enable()
setCurrentChunk(0);
setStartPosition();
-#ifdef JS_GC_ZEAL
- if (runtime()->hasZealMode(ZealMode::GenerationalGC))
- enterZealMode();
-#endif
MOZ_ALWAYS_TRUE(runtime()->gc.storeBuffer.enable());
return;
@@ -235,31 +219,11 @@ js::Nursery::isEmpty() const
MOZ_ASSERT(runtime_);
if (!isEnabled())
return true;
-
- if (!runtime_->hasZealMode(ZealMode::GenerationalGC)) {
- MOZ_ASSERT(currentStartChunk_ == 0);
- MOZ_ASSERT(currentStartPosition_ == chunk(0).start());
- }
+ MOZ_ASSERT(currentStartChunk_ == 0);
+ MOZ_ASSERT(currentStartPosition_ == chunk(0).start());
return position() == currentStartPosition_;
}
-#ifdef JS_GC_ZEAL
-void
-js::Nursery::enterZealMode() {
- if (isEnabled())
- updateNumChunks(maxNurseryChunks_);
-}
-
-void
-js::Nursery::leaveZealMode() {
- if (isEnabled()) {
- MOZ_ASSERT(isEmpty());
- setCurrentChunk(0);
- setStartPosition();
- }
-}
-#endif // JS_GC_ZEAL
-
JSObject*
js::Nursery::allocateObject(JSContext* cx, size_t size, size_t numDynamic, const js::Class* clasp)
{
@@ -305,12 +269,6 @@ js::Nursery::allocate(size_t size)
MOZ_ASSERT(position() % gc::CellSize == 0);
MOZ_ASSERT(size % gc::CellSize == 0);
-#ifdef JS_GC_ZEAL
- static const size_t CanarySize = (sizeof(Nursery::Canary) + CellSize - 1) & ~CellMask;
- if (runtime()->gc.hasZealMode(ZealMode::CheckNursery))
- size += CanarySize;
-#endif
-
if (currentEnd() < position() + size) {
if (currentChunk_ + 1 == numChunks())
return nullptr;
@@ -322,19 +280,6 @@ js::Nursery::allocate(size_t size)
JS_EXTRA_POISON(thing, JS_ALLOCATED_NURSERY_PATTERN, size);
-#ifdef JS_GC_ZEAL
- if (runtime()->gc.hasZealMode(ZealMode::CheckNursery)) {
- auto canary = reinterpret_cast<Canary*>(position() - CanarySize);
- canary->magicValue = CanaryMagicValue;
- canary->next = nullptr;
- if (lastCanary_) {
- MOZ_ASSERT(!lastCanary_->next);
- lastCanary_->next = canary;
- }
- lastCanary_ = canary;
- }
-#endif
-
MemProfiler::SampleNursery(reinterpret_cast<void*>(thing), size);
return thing;
}
@@ -561,14 +506,6 @@ js::Nursery::collect(JSRuntime* rt, JS::gcreason::Reason reason)
rt->gc.incMinorGcNumber();
-#ifdef JS_GC_ZEAL
- if (rt->gc.hasZealMode(ZealMode::CheckNursery)) {
- for (auto canary = lastCanary_; canary; canary = canary->next)
- MOZ_ASSERT(canary->magicValue == CanaryMagicValue);
- }
- lastCanary_ = nullptr;
-#endif
-
rt->gc.stats.beginNurseryCollection(reason);
TraceMinorGCStart();
@@ -659,7 +596,6 @@ js::Nursery::doCollection(JSRuntime* rt, JS::gcreason::Reason reason,
{
AutoTraceSession session(rt, JS::HeapState::MinorCollecting);
AutoSetThreadIsPerformingGC performingGC;
- AutoStopVerifyingBarriers av(rt, false);
AutoDisableProxyCheck disableStrictProxyChecking(rt);
mozilla::DebugOnly<AutoEnterOOMUnsafeRegion> oomUnsafeRegion;
@@ -752,10 +688,6 @@ js::Nursery::doCollection(JSRuntime* rt, JS::gcreason::Reason reason,
// Make sure hashtables have been updated after the collection.
maybeStartProfile(ProfileKey::CheckHashTables);
-#ifdef JS_GC_ZEAL
- if (rt->hasZealMode(ZealMode::CheckHashTablesOnMinorGC))
- CheckHashTablesAfterMovingGC(rt);
-#endif
maybeEndProfile(ProfileKey::CheckHashTables);
// Calculate and return the promotion rate.
@@ -828,17 +760,6 @@ js::Nursery::sweep()
runSweepActions();
sweepDictionaryModeObjects();
-#ifdef JS_GC_ZEAL
- /* Poison the nursery contents so touching a freed object will crash. */
- for (unsigned i = 0; i < numChunks(); i++)
- chunk(i).poisonAndInit(runtime(), JS_SWEPT_NURSERY_PATTERN);
-
- if (runtime()->hasZealMode(ZealMode::GenerationalGC)) {
- /* Only reset the alloc point when we are close to the end. */
- if (currentChunk_ + 1 == numChunks())
- setCurrentChunk(0);
- } else
-#endif
{
#ifdef JS_CRASH_DIAGNOSTICS
for (unsigned i = 0; i < numChunks(); ++i)
@@ -916,20 +837,12 @@ js::Nursery::growAllocableSpace()
void
js::Nursery::shrinkAllocableSpace()
{
-#ifdef JS_GC_ZEAL
- if (runtime()->hasZealMode(ZealMode::GenerationalGC))
- return;
-#endif
updateNumChunks(Max(numChunks() - 1, 1u));
}
void
js::Nursery::minimizeAllocableSpace()
{
-#ifdef JS_GC_ZEAL
- if (runtime()->hasZealMode(ZealMode::GenerationalGC))
- return;
-#endif
updateNumChunks(1);
}
diff --git a/js/src/gc/Nursery.h b/js/src/gc/Nursery.h
index 69fb66b7a..0d215d997 100644
--- a/js/src/gc/Nursery.h
+++ b/js/src/gc/Nursery.h
@@ -58,8 +58,6 @@ class NativeObject;
class Nursery;
class HeapSlot;
-void SetGCZeal(JSRuntime*, uint8_t, uint32_t);
-
namespace gc {
class AutoMaybeStartBackgroundAllocation;
struct Cell;
@@ -252,11 +250,6 @@ class Nursery
(numChunks() - currentChunk_ - 1) * NurseryChunkUsableSize;
}
-#ifdef JS_GC_ZEAL
- void enterZealMode();
- void leaveZealMode();
-#endif
-
/* Print total profile times on shutdown. */
void printTotalProfileTimes();
@@ -374,11 +367,6 @@ class Nursery
using NativeObjectVector = Vector<NativeObject*, 0, SystemAllocPolicy>;
NativeObjectVector dictionaryModeObjects_;
-#ifdef JS_GC_ZEAL
- struct Canary;
- Canary* lastCanary_;
-#endif
-
NurseryChunk* allocChunk();
NurseryChunk& chunk(unsigned index) const {
diff --git a/js/src/gc/Verifier.cpp b/js/src/gc/Verifier.cpp
index dd4031606..3ebbbb4f6 100644
--- a/js/src/gc/Verifier.cpp
+++ b/js/src/gc/Verifier.cpp
@@ -26,420 +26,6 @@
using namespace js;
using namespace js::gc;
-#ifdef JS_GC_ZEAL
-
-/*
- * Write barrier verification
- *
- * The next few functions are for write barrier verification.
- *
- * The VerifyBarriers function is a shorthand. It checks if a verification phase
- * is currently running. If not, it starts one. Otherwise, it ends the current
- * phase and starts a new one.
- *
- * The user can adjust the frequency of verifications, which causes
- * VerifyBarriers to be a no-op all but one out of N calls. However, if the
- * |always| parameter is true, it starts a new phase no matter what.
- *
- * Pre-Barrier Verifier:
- * When StartVerifyBarriers is called, a snapshot is taken of all objects in
- * the GC heap and saved in an explicit graph data structure. Later,
- * EndVerifyBarriers traverses the heap again. Any pointer values that were in
- * the snapshot and are no longer found must be marked; otherwise an assertion
- * triggers. Note that we must not GC in between starting and finishing a
- * verification phase.
- */
-
-struct EdgeValue
-{
- void* thing;
- JS::TraceKind kind;
- const char* label;
-};
-
-struct VerifyNode
-{
- void* thing;
- JS::TraceKind kind;
- uint32_t count;
- EdgeValue edges[1];
-};
-
-typedef HashMap<void*, VerifyNode*, DefaultHasher<void*>, SystemAllocPolicy> NodeMap;
-
-/*
- * The verifier data structures are simple. The entire graph is stored in a
- * single block of memory. At the beginning is a VerifyNode for the root
- * node. It is followed by a sequence of EdgeValues--the exact number is given
- * in the node. After the edges come more nodes and their edges.
- *
- * The edgeptr and term fields are used to allocate out of the block of memory
- * for the graph. If we run out of memory (i.e., if edgeptr goes beyond term),
- * we just abandon the verification.
- *
- * The nodemap field is a hashtable that maps from the address of the GC thing
- * to the VerifyNode that represents it.
- */
-class js::VerifyPreTracer final : public JS::CallbackTracer
-{
- JS::AutoDisableGenerationalGC noggc;
-
- void onChild(const JS::GCCellPtr& thing) override;
-
- public:
- /* The gcNumber when the verification began. */
- uint64_t number;
-
- /* This counts up to gcZealFrequency to decide whether to verify. */
- int count;
-
- /* This graph represents the initial GC "snapshot". */
- VerifyNode* curnode;
- VerifyNode* root;
- char* edgeptr;
- char* term;
- NodeMap nodemap;
-
- explicit VerifyPreTracer(JSRuntime* rt)
- : JS::CallbackTracer(rt), noggc(rt), number(rt->gc.gcNumber()), count(0), curnode(nullptr),
- root(nullptr), edgeptr(nullptr), term(nullptr)
- {}
-
- ~VerifyPreTracer() {
- js_free(root);
- }
-};
-
-/*
- * This function builds up the heap snapshot by adding edges to the current
- * node.
- */
-void
-VerifyPreTracer::onChild(const JS::GCCellPtr& thing)
-{
- MOZ_ASSERT(!IsInsideNursery(thing.asCell()));
-
- // Skip things in other runtimes.
- if (thing.asCell()->asTenured().runtimeFromAnyThread() != runtime())
- return;
-
- edgeptr += sizeof(EdgeValue);
- if (edgeptr >= term) {
- edgeptr = term;
- return;
- }
-
- VerifyNode* node = curnode;
- uint32_t i = node->count;
-
- node->edges[i].thing = thing.asCell();
- node->edges[i].kind = thing.kind();
- node->edges[i].label = contextName();
- node->count++;
-}
-
-static VerifyNode*
-MakeNode(VerifyPreTracer* trc, void* thing, JS::TraceKind kind)
-{
- NodeMap::AddPtr p = trc->nodemap.lookupForAdd(thing);
- if (!p) {
- VerifyNode* node = (VerifyNode*)trc->edgeptr;
- trc->edgeptr += sizeof(VerifyNode) - sizeof(EdgeValue);
- if (trc->edgeptr >= trc->term) {
- trc->edgeptr = trc->term;
- return nullptr;
- }
-
- node->thing = thing;
- node->count = 0;
- node->kind = kind;
- if (!trc->nodemap.add(p, thing, node)) {
- trc->edgeptr = trc->term;
- return nullptr;
- }
-
- return node;
- }
- return nullptr;
-}
-
-static VerifyNode*
-NextNode(VerifyNode* node)
-{
- if (node->count == 0)
- return (VerifyNode*)((char*)node + sizeof(VerifyNode) - sizeof(EdgeValue));
- else
- return (VerifyNode*)((char*)node + sizeof(VerifyNode) +
- sizeof(EdgeValue)*(node->count - 1));
-}
-
-void
-gc::GCRuntime::startVerifyPreBarriers()
-{
- if (verifyPreData || isIncrementalGCInProgress())
- return;
-
- if (IsIncrementalGCUnsafe(rt) != AbortReason::None)
- return;
-
- number++;
-
- VerifyPreTracer* trc = js_new<VerifyPreTracer>(rt);
- if (!trc)
- return;
-
- AutoPrepareForTracing prep(rt->contextFromMainThread(), WithAtoms);
-
- for (auto chunk = allNonEmptyChunks(); !chunk.done(); chunk.next())
- chunk->bitmap.clear();
-
- gcstats::AutoPhase ap(stats, gcstats::PHASE_TRACE_HEAP);
-
- const size_t size = 64 * 1024 * 1024;
- trc->root = (VerifyNode*)js_malloc(size);
- if (!trc->root)
- goto oom;
- trc->edgeptr = (char*)trc->root;
- trc->term = trc->edgeptr + size;
-
- if (!trc->nodemap.init())
- goto oom;
-
- /* Create the root node. */
- trc->curnode = MakeNode(trc, nullptr, JS::TraceKind(0));
-
- incrementalState = State::MarkRoots;
-
- /* Make all the roots be edges emanating from the root node. */
- traceRuntime(trc, prep.session().lock);
-
- VerifyNode* node;
- node = trc->curnode;
- if (trc->edgeptr == trc->term)
- goto oom;
-
- /* For each edge, make a node for it if one doesn't already exist. */
- while ((char*)node < trc->edgeptr) {
- for (uint32_t i = 0; i < node->count; i++) {
- EdgeValue& e = node->edges[i];
- VerifyNode* child = MakeNode(trc, e.thing, e.kind);
- if (child) {
- trc->curnode = child;
- js::TraceChildren(trc, e.thing, e.kind);
- }
- if (trc->edgeptr == trc->term)
- goto oom;
- }
-
- node = NextNode(node);
- }
-
- verifyPreData = trc;
- incrementalState = State::Mark;
- marker.start();
-
- for (ZonesIter zone(rt, WithAtoms); !zone.done(); zone.next()) {
- PurgeJITCaches(zone);
- if (!zone->usedByExclusiveThread) {
- zone->setNeedsIncrementalBarrier(true, Zone::UpdateJit);
- zone->arenas.purge();
- }
- }
-
- return;
-
-oom:
- incrementalState = State::NotActive;
- js_delete(trc);
- verifyPreData = nullptr;
-}
-
-static bool
-IsMarkedOrAllocated(TenuredCell* cell)
-{
- return cell->isMarked() || cell->arena()->allocatedDuringIncremental;
-}
-
-struct CheckEdgeTracer : public JS::CallbackTracer {
- VerifyNode* node;
- explicit CheckEdgeTracer(JSRuntime* rt) : JS::CallbackTracer(rt), node(nullptr) {}
- void onChild(const JS::GCCellPtr& thing) override;
-};
-
-static const uint32_t MAX_VERIFIER_EDGES = 1000;
-
-/*
- * This function is called by EndVerifyBarriers for every heap edge. If the edge
- * already existed in the original snapshot, we "cancel it out" by overwriting
- * it with nullptr. EndVerifyBarriers later asserts that the remaining
- * non-nullptr edges (i.e., the ones from the original snapshot that must have
- * been modified) must point to marked objects.
- */
-void
-CheckEdgeTracer::onChild(const JS::GCCellPtr& thing)
-{
- // Skip things in other runtimes.
- if (thing.asCell()->asTenured().runtimeFromAnyThread() != runtime())
- return;
-
- /* Avoid n^2 behavior. */
- if (node->count > MAX_VERIFIER_EDGES)
- return;
-
- for (uint32_t i = 0; i < node->count; i++) {
- if (node->edges[i].thing == thing.asCell()) {
- MOZ_ASSERT(node->edges[i].kind == thing.kind());
- node->edges[i].thing = nullptr;
- return;
- }
- }
-}
-
-void
-js::gc::AssertSafeToSkipBarrier(TenuredCell* thing)
-{
- Zone* zone = thing->zoneFromAnyThread();
- MOZ_ASSERT(!zone->needsIncrementalBarrier() || zone->isAtomsZone());
-}
-
-static bool
-IsMarkedOrAllocated(const EdgeValue& edge)
-{
- if (!edge.thing || IsMarkedOrAllocated(TenuredCell::fromPointer(edge.thing)))
- return true;
-
- // Permanent atoms and well-known symbols aren't marked during graph traversal.
- if (edge.kind == JS::TraceKind::String && static_cast<JSString*>(edge.thing)->isPermanentAtom())
- return true;
- if (edge.kind == JS::TraceKind::Symbol && static_cast<JS::Symbol*>(edge.thing)->isWellKnownSymbol())
- return true;
-
- return false;
-}
-
-void
-gc::GCRuntime::endVerifyPreBarriers()
-{
- VerifyPreTracer* trc = verifyPreData;
-
- if (!trc)
- return;
-
- MOZ_ASSERT(!JS::IsGenerationalGCEnabled(rt));
-
- AutoPrepareForTracing prep(rt->contextFromMainThread(), SkipAtoms);
-
- bool compartmentCreated = false;
-
- /* We need to disable barriers before tracing, which may invoke barriers. */
- for (ZonesIter zone(rt, WithAtoms); !zone.done(); zone.next()) {
- if (!zone->needsIncrementalBarrier())
- compartmentCreated = true;
-
- zone->setNeedsIncrementalBarrier(false, Zone::UpdateJit);
- PurgeJITCaches(zone);
- }
-
- /*
- * We need to bump gcNumber so that the methodjit knows that jitcode has
- * been discarded.
- */
- MOZ_ASSERT(trc->number == number);
- number++;
-
- verifyPreData = nullptr;
- incrementalState = State::NotActive;
-
- if (!compartmentCreated && IsIncrementalGCUnsafe(rt) == AbortReason::None) {
- CheckEdgeTracer cetrc(rt);
-
- /* Start after the roots. */
- VerifyNode* node = NextNode(trc->root);
- while ((char*)node < trc->edgeptr) {
- cetrc.node = node;
- js::TraceChildren(&cetrc, node->thing, node->kind);
-
- if (node->count <= MAX_VERIFIER_EDGES) {
- for (uint32_t i = 0; i < node->count; i++) {
- EdgeValue& edge = node->edges[i];
- if (!IsMarkedOrAllocated(edge)) {
- char msgbuf[1024];
- SprintfLiteral(msgbuf,
- "[barrier verifier] Unmarked edge: %s %p '%s' edge to %s %p",
- JS::GCTraceKindToAscii(node->kind), node->thing,
- edge.label,
- JS::GCTraceKindToAscii(edge.kind), edge.thing);
- MOZ_ReportAssertionFailure(msgbuf, __FILE__, __LINE__);
- MOZ_CRASH();
- }
- }
- }
-
- node = NextNode(node);
- }
- }
-
- marker.reset();
- marker.stop();
-
- js_delete(trc);
-}
-
-/*** Barrier Verifier Scheduling ***/
-
-void
-gc::GCRuntime::verifyPreBarriers()
-{
- if (verifyPreData)
- endVerifyPreBarriers();
- else
- startVerifyPreBarriers();
-}
-
-void
-gc::VerifyBarriers(JSRuntime* rt, VerifierType type)
-{
- if (type == PreBarrierVerifier)
- rt->gc.verifyPreBarriers();
-}
-
-void
-gc::GCRuntime::maybeVerifyPreBarriers(bool always)
-{
- if (!hasZealMode(ZealMode::VerifierPre))
- return;
-
- if (rt->mainThread.suppressGC)
- return;
-
- if (verifyPreData) {
- if (++verifyPreData->count < zealFrequency && !always)
- return;
-
- endVerifyPreBarriers();
- }
-
- startVerifyPreBarriers();
-}
-
-void
-js::gc::MaybeVerifyBarriers(JSContext* cx, bool always)
-{
- GCRuntime* gc = &cx->runtime()->gc;
- gc->maybeVerifyPreBarriers(always);
-}
-
-void
-js::gc::GCRuntime::finishVerifier()
-{
- if (verifyPreData) {
- js_delete(verifyPreData);
- verifyPreData = nullptr;
- }
-}
-
-#endif /* JS_GC_ZEAL */
-
#ifdef JSGC_HASH_TABLE_CHECKS
class CheckHeapTracer : public JS::CallbackTracer
diff --git a/js/src/gc/Zone.h b/js/src/gc/Zone.h
index a3a6dc07f..50d06319d 100644
--- a/js/src/gc/Zone.h
+++ b/js/src/gc/Zone.h
@@ -253,12 +253,6 @@ struct Zone : public JS::shadow::Zone,
// possibly at other times too.
uint64_t gcNumber();
- bool compileBarriers() const { return compileBarriers(needsIncrementalBarrier()); }
- bool compileBarriers(bool needsIncrementalBarrier) const {
- return needsIncrementalBarrier ||
- runtimeFromMainThread()->hasZealMode(js::gc::ZealMode::VerifierPre);
- }
-
enum ShouldUpdateJit { DontUpdateJit, UpdateJit };
void setNeedsIncrementalBarrier(bool needs, ShouldUpdateJit updateJit);
const bool* addressOfNeedsIncrementalBarrier() const { return &needsIncrementalBarrier_; }
diff --git a/js/src/jit-test/tests/ion/bug730152.js b/js/src/jit-test/tests/ion/bug730152.js
deleted file mode 100644
index fe4ecfe14..000000000
--- a/js/src/jit-test/tests/ion/bug730152.js
+++ /dev/null
@@ -1,4 +0,0 @@
-if (typeof verifybarriers !== "undefined") {
- for (var i = 0; i < 30; i++) {}
- for (i in Function("gc(verifybarriers()); yield")()) {}
-}
diff --git a/js/src/jit-test/tests/ion/bug732758.js b/js/src/jit-test/tests/ion/bug732758.js
index 91da521c7..8196c3e03 100644
--- a/js/src/jit-test/tests/ion/bug732758.js
+++ b/js/src/jit-test/tests/ion/bug732758.js
@@ -38,5 +38,4 @@ tryItOut("{t:g}");
tryItOut("r");
tryItOut("p");
tryItOut("gc()");
-tryItOut("verifybarriers()");
tryItOut("/**/yield");
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..4edbc3c83 100644
--- a/js/src/jit/VMFunctions.cpp
+++ b/js/src/jit/VMFunctions.cpp
@@ -135,7 +135,6 @@ CheckOverRecursed(JSContext* cx)
#else
JS_CHECK_RECURSION(cx, return false);
#endif
- gc::MaybeVerifyBarriers(cx);
return cx->runtime()->handleInterrupt(cx);
}
@@ -180,7 +179,6 @@ CheckOverRecursedWithExtra(JSContext* cx, BaselineFrame* frame,
JS_CHECK_RECURSION_WITH_SP(cx, checkSp, return false);
#endif
- gc::MaybeVerifyBarriers(cx);
return cx->runtime()->handleInterrupt(cx);
}
@@ -465,8 +463,6 @@ SetProperty(JSContext* cx, HandleObject obj, HandlePropertyName name, HandleValu
bool
InterruptCheck(JSContext* cx)
{
- gc::MaybeVerifyBarriers(cx);
-
{
JSRuntime* rt = cx->runtime();
JitRuntime::AutoPreventBackedgePatching apbp(rt);
@@ -627,11 +623,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/jsapi.h b/js/src/jsapi.h
index 6700a6c51..9ad3e757f 100644
--- a/js/src/jsapi.h
+++ b/js/src/jsapi.h
@@ -5761,19 +5761,6 @@ JS_NewObjectForConstructor(JSContext* cx, const JSClass* clasp, const JS::CallAr
/************************************************************************/
-#ifdef JS_GC_ZEAL
-#define JS_DEFAULT_ZEAL_FREQ 100
-
-extern JS_PUBLIC_API(void)
-JS_GetGCZealBits(JSContext* cx, uint32_t* zealBits, uint32_t* frequency, uint32_t* nextScheduled);
-
-extern JS_PUBLIC_API(void)
-JS_SetGCZeal(JSContext* cx, uint8_t zeal, uint32_t frequency);
-
-extern JS_PUBLIC_API(void)
-JS_ScheduleGC(JSContext* cx, uint32_t count);
-#endif
-
extern JS_PUBLIC_API(void)
JS_SetParallelParsingEnabled(JSContext* cx, bool enabled);
diff --git a/js/src/jsgc.cpp b/js/src/jsgc.cpp
index 42d10283c..45301dac8 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;
@@ -1315,7 +1153,6 @@ GCRuntime::setMarkStackLimit(size_t limit, AutoLockGC& lock)
{
MOZ_ASSERT(!rt->isHeapBusy());
AutoUnlockGC unlock(lock);
- AutoStopVerifyingBarriers pauseVerification(rt, false);
marker.setMaxCapacity(limit);
}
@@ -2635,7 +2472,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 +2885,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 +2907,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 +3240,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,292 +3885,6 @@ 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
DropStringWrappers(JSRuntime* rt)
{
@@ -4988,8 +4519,6 @@ GCRuntime::beginSweepingZoneGroup(AutoLockForExclusiveAccess& lock)
#endif
}
- validateIncrementalMarking();
-
FreeOp fop(rt);
SweepAtomsTask sweepAtomsTask(rt);
SweepCCWrappersTask sweepCCWrappersTask(rt);
@@ -5215,8 +4744,6 @@ GCRuntime::beginSweepPhase(bool destroyingRuntime, AutoLockForExclusiveAccess& l
releaseHeldRelocatedArenas();
- computeNonIncrementalMarkingForValidation(lock);
-
gcstats::AutoPhase ap(stats, gcstats::PHASE_SWEEP);
sweepOnBackgroundThread =
@@ -5462,8 +4989,6 @@ GCRuntime::endSweepPhase(bool destroyingRuntime, AutoLockForExclusiveAccess& loc
rt->setGCGrayBitsValid(true);
}
- finishMarkingValidation();
-
#ifdef DEBUG
for (ZonesIter zone(rt, WithAtoms); !zone.done(); zone.next()) {
for (auto i : AllAllocKinds()) {
@@ -5782,16 +5307,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
IsShutdownGC(JS::gcreason::Reason reason)
{
@@ -5817,31 +5332,9 @@ 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();
- if (useZeal && (hasZealMode(ZealMode::IncrementalRootsThenFinish) ||
- hasZealMode(ZealMode::IncrementalMarkAllThenFinish)))
- {
- /*
- * Yields between slices occurs at predetermined points in these modes;
- * the budget is not used.
- */
- budget.makeUnlimited();
- }
-
switch (incrementalState) {
case State::NotActive:
initialReason = reason;
@@ -5859,14 +5352,8 @@ GCRuntime::incrementalCollectSlice(SliceBudget& budget, JS::gcreason::Reason rea
return;
}
- if (!destroyingRuntime)
- pushZealSelectedObjects();
-
incrementalState = State::Mark;
- if (isIncremental && useZeal && hasZealMode(ZealMode::IncrementalRootsThenFinish))
- break;
-
MOZ_FALLTHROUGH;
case State::Mark:
@@ -5895,10 +5382,7 @@ GCRuntime::incrementalCollectSlice(SliceBudget& budget, JS::gcreason::Reason rea
* We will need to mark anything new on the stack when we resume, so
* we stay in Mark state.
*/
- if (!lastMarkSlice && isIncremental &&
- ((initialState == State::Mark &&
- !(useZeal && hasZealMode(ZealMode::IncrementalRootsThenFinish))) ||
- (useZeal && hasZealMode(ZealMode::IncrementalMarkAllThenFinish))))
+ if (!lastMarkSlice && isIncremental && initialState == State::Mark)
{
lastMarkSlice = true;
break;
@@ -5914,13 +5398,6 @@ GCRuntime::incrementalCollectSlice(SliceBudget& budget, JS::gcreason::Reason rea
if (budget.isOverBudget())
break;
- /*
- * Always yield here when running in incremental multi-slice zeal
- * mode, so RunDebugGC can reset the slice buget.
- */
- if (isIncremental && useZeal && hasZealMode(ZealMode::IncrementalMultipleSlices))
- break;
-
MOZ_FALLTHROUGH;
case State::Sweep:
@@ -6202,11 +5679,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 +5690,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 +5755,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;
}
@@ -6319,7 +5769,6 @@ GCRuntime::collect(bool nonincrementalByAPI, SliceBudget budget, JS::gcreason::R
return;
AutoTraceLog logGC(TraceLoggerForMainThread(rt), TraceLogger_GC);
- AutoStopVerifyingBarriers av(rt, IsShutdownGC(reason));
AutoEnqueuePendingParseTasksAfterGC aept(*this);
AutoScheduleZonesForGC asz(rt);
@@ -6360,13 +5809,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()
@@ -6442,7 +5884,6 @@ GCRuntime::abortGC()
checkCanCallAPI();
MOZ_ASSERT(!rt->mainThread.suppressGC);
- AutoStopVerifyingBarriers av(rt, false);
AutoEnqueuePendingParseTasksAfterGC aept(*this);
gcstats::AutoGCSlice agc(stats, scanZonesBeforeGC(), invocationKind,
@@ -6460,17 +5901,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 +5996,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())
@@ -6754,92 +6179,12 @@ 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
GCRuntime::setFullCompartmentChecks(bool enabled)
{
MOZ_ASSERT(!rt->isHeapMajorCollecting());
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 */
@@ -7337,7 +6682,7 @@ JS::IsIncrementalGCEnabled(JSContext* cx)
JS_PUBLIC_API(bool)
JS::IsIncrementalGCInProgress(JSContext* cx)
{
- return cx->gc.isIncrementalGCInProgress() && !cx->gc.isVerifyPreBarriersEnabled();
+ return cx->gc.isIncrementalGCInProgress();
}
JS_PUBLIC_API(bool)
diff --git a/js/src/jsgc.h b/js/src/jsgc.h
index 79ac9596c..7ad176d84 100644
--- a/js/src/jsgc.h
+++ b/js/src/jsgc.h
@@ -1264,31 +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)
-{
-}
-
-static inline void
-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/jsgcinlines.h b/js/src/jsgcinlines.h
index 9cebb03a4..c6988d7af 100644
--- a/js/src/jsgcinlines.h
+++ b/js/src/jsgcinlines.h
@@ -42,12 +42,6 @@ inline void
GCRuntime::poke()
{
poked = true;
-
-#ifdef JS_GC_ZEAL
- /* Schedule a GC to happen "soon" after a GC poke. */
- if (hasZealMode(ZealMode::Poke))
- nextScheduled = 1;
-#endif
}
class ArenaIter
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/tests/shell.js b/js/src/tests/shell.js
index 36dbc79da..c7a57953e 100644
--- a/js/src/tests/shell.js
+++ b/js/src/tests/shell.js
@@ -32,8 +32,6 @@
// Certain cached functionality only exists (and is only needed) when
// running in the browser. Segregate that caching here.
- var SpecialPowersSetGCZeal =
- global.SpecialPowers ? global.SpecialPowers.setGCZeal : undefined;
}
var runningInShell = typeof window === "undefined";
@@ -205,19 +203,6 @@
global.quit = quit;
}
- var gczeal = global.gczeal;
- if (typeof gczeal !== "function") {
- if (typeof SpecialPowersSetGCZeal === "function") {
- gczeal = function gczeal(z) {
- SpecialPowersSetGCZeal(z);
- };
- } else {
- gczeal = function() {}; // no-op if not available
- }
-
- global.gczeal = gczeal;
- }
-
/******************************************************
* TEST METADATA EXPORTS (these are of dubious value) *
******************************************************/
diff --git a/js/src/vm/Caches-inl.h b/js/src/vm/Caches-inl.h
index 4eb8ecaa6..56e69a0d9 100644
--- a/js/src/vm/Caches-inl.h
+++ b/js/src/vm/Caches-inl.h
@@ -57,9 +57,6 @@ NewObjectCache::newObjectFromHit(JSContext* cx, EntryIndex entryIndex, gc::Initi
if (group->shouldPreTenure())
heap = gc::TenuredHeap;
- if (cx->runtime()->gc.upcomingZealousGC())
- return nullptr;
-
NativeObject* obj = static_cast<NativeObject*>(Allocate<JSObject, NoGC>(cx, entry->kind, 0,
heap, group->clasp()));
if (!obj)
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.
diff --git a/js/src/vm/Interpreter.cpp b/js/src/vm/Interpreter.cpp
index 3ca379d01..fbf526ae5 100644
--- a/js/src/vm/Interpreter.cpp
+++ b/js/src/vm/Interpreter.cpp
@@ -1647,7 +1647,6 @@ Interpret(JSContext* cx, RunState& state)
#define ADVANCE_AND_DISPATCH(N) \
JS_BEGIN_MACRO \
REGS.pc += (N); \
- SANITY_CHECKS(); \
DISPATCH_TO(*REGS.pc | activation.opMask()); \
JS_END_MACRO
@@ -1727,12 +1726,6 @@ Interpret(JSContext* cx, RunState& state)
activation.enableInterruptsUnconditionally(); \
JS_END_MACRO
-#define SANITY_CHECKS() \
- JS_BEGIN_MACRO \
- js::gc::MaybeVerifyBarriers(cx); \
- JS_END_MACRO
-
- gc::MaybeVerifyBarriers(cx, true);
MOZ_ASSERT(!cx->zone()->types.activeAnalysis);
InterpreterFrame* entryFrame = state.pushInterpreterFrame(cx);
@@ -1863,7 +1856,6 @@ CASE(EnableInterruptsPseudoOpcode)
activation.clearInterruptsMask();
/* Commence executing the actual opcode. */
- SANITY_CHECKS();
DISPATCH_TO(op);
}
@@ -4184,8 +4176,6 @@ DEFAULT()
REGS.fp()->epilogue(cx, REGS.pc);
}
- gc::MaybeVerifyBarriers(cx, true);
-
TraceLogStopEvent(logger, TraceLogger_Engine);
TraceLogStopEvent(logger, scriptEvent);
diff --git a/js/src/vm/Runtime.cpp b/js/src/vm/Runtime.cpp
index 646d48299..0d6a3922c 100644
--- a/js/src/vm/Runtime.cpp
+++ b/js/src/vm/Runtime.cpp
@@ -868,8 +868,7 @@ bool
JSRuntime::activeGCInAtomsZone()
{
Zone* zone = atomsCompartment_->zone();
- return (zone->needsIncrementalBarrier() && !gc.isVerifyPreBarriersEnabled()) ||
- zone->wasGCStarted();
+ return zone->needsIncrementalBarrier() || zone->wasGCStarted();
}
void
diff --git a/js/src/vm/Runtime.h b/js/src/vm/Runtime.h
index 4f7755b9d..734543c4e 100644
--- a/js/src/vm/Runtime.h
+++ b/js/src/vm/Runtime.h
@@ -866,8 +866,6 @@ struct JSRuntime : public JS::shadow::Runtime,
/* Garbage collector state has been successfully initialized. */
bool gcInitialized;
- bool hasZealMode(js::gc::ZealMode mode) { return gc.hasZealMode(mode); }
-
void lockGC() {
gc.lockGC();
}
diff --git a/js/xpconnect/idl/xpccomponents.idl b/js/xpconnect/idl/xpccomponents.idl
index 711ea4c64..611091c4b 100644
--- a/js/xpconnect/idl/xpccomponents.idl
+++ b/js/xpconnect/idl/xpccomponents.idl
@@ -123,7 +123,7 @@ interface ScheduledGCCallback : nsISupports
/**
* interface of Components.utils
*/
-[scriptable, uuid(86003fe3-ee9a-4620-91dc-eef8b1e58815)]
+[scriptable, uuid(a6e66965-4b9a-4846-8985-985e71aaf549)]
interface nsIXPCComponents_Utils : nsISupports
{
@@ -530,9 +530,6 @@ interface nsIXPCComponents_Utils : nsISupports
attribute boolean ion;
[implicit_jscontext]
- void setGCZeal(in long zeal);
-
- [implicit_jscontext]
void nukeSandbox(in jsval obj);
/*
diff --git a/js/xpconnect/src/XPCComponents.cpp b/js/xpconnect/src/XPCComponents.cpp
index ca78234c9..dbb63092e 100644
--- a/js/xpconnect/src/XPCComponents.cpp
+++ b/js/xpconnect/src/XPCComponents.cpp
@@ -3005,15 +3005,6 @@ GENERATE_JSCONTEXTOPTION_GETTER_SETTER(Ion, ion, setIon)
#undef GENERATE_JSCONTEXTOPTION_GETTER_SETTER
NS_IMETHODIMP
-nsXPCComponents_Utils::SetGCZeal(int32_t aValue, JSContext* cx)
-{
-#ifdef JS_GC_ZEAL
- JS_SetGCZeal(cx, uint8_t(aValue), JS_DEFAULT_ZEAL_FREQ);
-#endif
- return NS_OK;
-}
-
-NS_IMETHODIMP
nsXPCComponents_Utils::NukeSandbox(HandleValue obj, JSContext* cx)
{
PROFILER_LABEL_FUNC(js::ProfileEntry::Category::JS);
diff --git a/js/xpconnect/src/XPCJSContext.cpp b/js/xpconnect/src/XPCJSContext.cpp
index 6981b525c..defd1b785 100644
--- a/js/xpconnect/src/XPCJSContext.cpp
+++ b/js/xpconnect/src/XPCJSContext.cpp
@@ -1473,16 +1473,6 @@ ReloadPrefsCallback(const char* pref, void* data)
sExtraWarningsForSystemJS = Preferences::GetBool(JS_OPTIONS_DOT_STR "strict.debug");
#endif
-#ifdef JS_GC_ZEAL
- int32_t zeal = Preferences::GetInt(JS_OPTIONS_DOT_STR "gczeal", -1);
- int32_t zeal_frequency =
- Preferences::GetInt(JS_OPTIONS_DOT_STR "gczeal.frequency",
- JS_DEFAULT_ZEAL_FREQ);
- if (zeal >= 0) {
- JS_SetGCZeal(cx, (uint8_t)zeal, zeal_frequency);
- }
-#endif // JS_GC_ZEAL
-
JS::ContextOptionsRef(cx).setBaseline(useBaseline)
.setIon(useIon)
.setAsmJS(useAsmJS)
diff --git a/js/xpconnect/src/XPCShellImpl.cpp b/js/xpconnect/src/XPCShellImpl.cpp
index d86b5c5d3..d9629bfed 100644
--- a/js/xpconnect/src/XPCShellImpl.cpp
+++ b/js/xpconnect/src/XPCShellImpl.cpp
@@ -440,21 +440,6 @@ GC(JSContext* cx, unsigned argc, Value* vp)
return true;
}
-#ifdef JS_GC_ZEAL
-static bool
-GCZeal(JSContext* cx, unsigned argc, Value* vp)
-{
- CallArgs args = CallArgsFromVp(argc, vp);
- uint32_t zeal;
- if (!ToUint32(cx, args.get(0), &zeal))
- return false;
-
- JS_SetGCZeal(cx, uint8_t(zeal), JS_DEFAULT_ZEAL_FREQ);
- args.rval().setUndefined();
- return true;
-}
-#endif
-
static bool
SendCommand(JSContext* cx, unsigned argc, Value* vp)
{
@@ -652,9 +637,6 @@ static const JSFunctionSpec glob_functions[] = {
JS_FS("dumpXPC", DumpXPC, 1,0),
JS_FS("dump", Dump, 1,0),
JS_FS("gc", GC, 0,0),
-#ifdef JS_GC_ZEAL
- JS_FS("gczeal", GCZeal, 1,0),
-#endif
JS_FS("options", Options, 0,0),
JS_FS("sendCommand", SendCommand, 1,0),
JS_FS("atob", xpc::Atob, 1,0),
diff --git a/testing/specialpowers/content/specialpowersAPI.js b/testing/specialpowers/content/specialpowersAPI.js
index ee94e84a3..8f1ff7465 100644
--- a/testing/specialpowers/content/specialpowersAPI.js
+++ b/testing/specialpowers/content/specialpowersAPI.js
@@ -1479,10 +1479,6 @@ SpecialPowersAPI.prototype = {
Cu.schedulePreciseGC(genGCCallback(callback));
},
- setGCZeal: function(zeal) {
- Cu.setGCZeal(zeal);
- },
-
isMainProcess: function() {
try {
return Cc["@mozilla.org/xre/app-info;1"].