From 4d0783188ecbe1135fb95113af8286ce8bd52016 Mon Sep 17 00:00:00 2001 From: Ryan VanderMeulen Date: Mon, 5 Jan 2015 12:38:18 -0500 Subject: [PATCH] Backed out 5 changesets (bug 1099152, bug 1117098) for causing frequent B2G debug timeouts. Backed out changeset 4feee07c34ad (bug 1117098) Backed out changeset 168e5b9bf198 (bug 1099152) Backed out changeset 9192d432d87e (bug 1099152) Backed out changeset 8b891ebcd21f (bug 1099152) Backed out changeset 24dae3ce853d (bug 1099152) --- dom/base/nsJSEnvironment.cpp | 9 +- dom/workers/WorkerPrivate.cpp | 4 +- js/public/GCAPI.h | 105 +++--- js/src/builtin/TestingFunctions.cpp | 6 +- js/src/devtools/rootAnalysis/loadCallgraph.js | 2 +- js/src/gc/GCRuntime.h | 12 +- js/src/jsapi-tests/testGCFinalizeCallback.cpp | 10 +- js/src/jsapi-tests/testPreserveJitCode.cpp | 4 +- js/src/jsapi-tests/tests.h | 2 +- js/src/jsfriendapi.cpp | 220 ++++++++++++ js/src/jsgc.cpp | 332 +++--------------- js/src/jsgc.h | 11 + js/xpconnect/src/XPCComponents.cpp | 10 +- xpcom/base/CycleCollectedJSRuntime.cpp | 2 +- 14 files changed, 349 insertions(+), 380 deletions(-) diff --git a/dom/base/nsJSEnvironment.cpp b/dom/base/nsJSEnvironment.cpp index 4e56a2d1cbac..fa422ff87088 100644 --- a/dom/base/nsJSEnvironment.cpp +++ b/dom/base/nsJSEnvironment.cpp @@ -1459,7 +1459,7 @@ nsJSContext::GarbageCollectNow(JS::gcreason::Reason aReason, if (sCCLockedOut && aIncremental == IncrementalGC) { // We're in the middle of incremental GC. Do another slice. JS::PrepareForIncrementalGC(sRuntime); - JS::IncrementalGCSlice(sRuntime, aReason, aSliceMillis); + JS::IncrementalGC(sRuntime, aReason, aSliceMillis); return; } @@ -1472,10 +1472,11 @@ nsJSContext::GarbageCollectNow(JS::gcreason::Reason aReason, if (aIncremental == IncrementalGC) { MOZ_ASSERT(aShrinking == NonShrinkingGC); - JS::StartIncrementalGC(sRuntime, GC_NORMAL, aReason, aSliceMillis); + JS::IncrementalGC(sRuntime, aReason, aSliceMillis); + } else if (aShrinking == ShrinkingGC) { + JS::ShrinkingGC(sRuntime, aReason); } else { - JSGCInvocationKind gckind = aShrinking == ShrinkingGC ? GC_SHRINK : GC_NORMAL; - JS::GCForReason(sRuntime, gckind, aReason); + JS::GCForReason(sRuntime, aReason); } } diff --git a/dom/workers/WorkerPrivate.cpp b/dom/workers/WorkerPrivate.cpp index c4bdd9ffa433..fefc1b959e88 100644 --- a/dom/workers/WorkerPrivate.cpp +++ b/dom/workers/WorkerPrivate.cpp @@ -6026,14 +6026,14 @@ WorkerPrivate::GarbageCollectInternal(JSContext* aCx, bool aShrinking, JS::PrepareForFullGC(rt); if (aShrinking) { - JS::GCForReason(rt, GC_SHRINK, JS::gcreason::DOM_WORKER); + JS::ShrinkingGC(rt, JS::gcreason::DOM_WORKER); if (!aCollectChildren) { LOG(("Worker %p collected idle garbage\n", this)); } } else { - JS::GCForReason(rt, GC_NORMAL, JS::gcreason::DOM_WORKER); + JS::GCForReason(rt, JS::gcreason::DOM_WORKER); LOG(("Worker %p collected garbage\n", this)); } } diff --git a/js/public/GCAPI.h b/js/public/GCAPI.h index ad6c70147fc0..67843d40fe3a 100644 --- a/js/public/GCAPI.h +++ b/js/public/GCAPI.h @@ -31,17 +31,6 @@ typedef enum JSGCMode { JSGC_MODE_INCREMENTAL = 2 } JSGCMode; -/* - * Kinds of js_GC invocation. - */ -typedef enum JSGCInvocationKind { - /* Normal invocation. */ - GC_NORMAL = 0, - - /* Minimize GC triggers and release empty GC chunks right away. */ - GC_SHRINK = 1 -} JSGCInvocationKind; - namespace JS { #define GCREASONS(D) \ @@ -60,7 +49,6 @@ namespace JS { D(EVICT_NURSERY) \ D(FULL_STORE_BUFFER) \ D(SHARED_MEMORY_LIMIT) \ - D(INCREMENTAL_ALLOC_TRIGGER) \ \ /* These are reserved for future use. */ \ D(RESERVED0) \ @@ -81,6 +69,7 @@ namespace JS { D(RESERVED15) \ D(RESERVED16) \ D(RESERVED17) \ + D(RESERVED18) \ \ /* Reasons from Firefox */ \ D(DOM_WINDOW_UTILS) \ @@ -141,13 +130,13 @@ enum Reason { /* * Schedule the given zone to be collected as part of the next GC. */ -extern JS_PUBLIC_API(void) +extern JS_FRIEND_API(void) PrepareZoneForGC(Zone *zone); /* * Schedule all zones to be collected in the next GC. */ -extern JS_PUBLIC_API(void) +extern JS_FRIEND_API(void) PrepareForFullGC(JSRuntime *rt); /* @@ -155,21 +144,21 @@ PrepareForFullGC(JSRuntime *rt); * previous incremental slice must be selected in subsequent slices as well. * This function selects those slices automatically. */ -extern JS_PUBLIC_API(void) +extern JS_FRIEND_API(void) PrepareForIncrementalGC(JSRuntime *rt); /* * Returns true if any zone in the system has been scheduled for GC with one of * the functions above or by the JS engine. */ -extern JS_PUBLIC_API(bool) +extern JS_FRIEND_API(bool) IsGCScheduled(JSRuntime *rt); /* * Undoes the effect of the Prepare methods above. The given zone will not be * collected in the next GC. */ -extern JS_PUBLIC_API(void) +extern JS_FRIEND_API(void) SkipZoneForGC(Zone *zone); /* @@ -179,16 +168,20 @@ SkipZoneForGC(Zone *zone); */ /* - * Performs a non-incremental collection of all selected zones. - * - * If the gckind argument is GC_NORMAL, then some objects that are unreachable - * from the program may still be alive afterwards because of internal - * references; if GC_SHRINK is passed then caches and other temporary references - * to objects will be cleared and all unreferenced objects will be removed from - * the system. + * Performs a non-incremental collection of all selected zones. Some objects + * that are unreachable from the program may still be alive afterwards because + * of internal references. */ -extern JS_PUBLIC_API(void) -GCForReason(JSRuntime *rt, JSGCInvocationKind gckind, gcreason::Reason reason); +extern JS_FRIEND_API(void) +GCForReason(JSRuntime *rt, gcreason::Reason reason); + +/* + * Perform a non-incremental collection after clearing caches and other + * temporary references to objects. This will remove all unreferenced objects + * in the system. + */ +extern JS_FRIEND_API(void) +ShrinkingGC(JSRuntime *rt, gcreason::Reason reason); /* * Incremental GC: @@ -214,28 +207,16 @@ GCForReason(JSRuntime *rt, JSGCInvocationKind gckind, gcreason::Reason reason); */ /* - * Begin an incremental collection and perform one slice worth of work. When - * this function returns, the collection may not be complete. - * IncrementalGCSlice() must be called repeatedly until - * !IsIncrementalGCInProgress(rt). + * Begin an incremental collection and perform one slice worth of work or + * perform a slice of an ongoing incremental collection. When this function + * returns, the collection is not complete. This function must be called + * repeatedly until !IsIncrementalGCInProgress(rt). * * Note: SpiderMonkey's GC is not realtime. Slices in practice may be longer or * shorter than the requested interval. */ -extern JS_PUBLIC_API(void) -StartIncrementalGC(JSRuntime *rt, JSGCInvocationKind gckind, gcreason::Reason reason, - int64_t millis = 0); - -/* - * Perform a slice of an ongoing incremental collection. When this function - * returns, the collection may not be complete. It must be called repeatedly - * until !IsIncrementalGCInProgress(rt). - * - * Note: SpiderMonkey's GC is not realtime. Slices in practice may be longer or - * shorter than the requested interval. - */ -extern JS_PUBLIC_API(void) -IncrementalGCSlice(JSRuntime *rt, gcreason::Reason reason, int64_t millis = 0); +extern JS_FRIEND_API(void) +IncrementalGC(JSRuntime *rt, gcreason::Reason reason, int64_t millis = 0); /* * If IsIncrementalGCInProgress(rt), this call finishes the ongoing collection @@ -243,7 +224,7 @@ IncrementalGCSlice(JSRuntime *rt, gcreason::Reason reason, int64_t millis = 0); * this is equivalent to GCForReason. When this function returns, * IsIncrementalGCInProgress(rt) will always be false. */ -extern JS_PUBLIC_API(void) +extern JS_FRIEND_API(void) FinishIncrementalGC(JSRuntime *rt, gcreason::Reason reason); enum GCProgress { @@ -263,7 +244,7 @@ enum GCProgress { GC_CYCLE_END }; -struct JS_PUBLIC_API(GCDescription) { +struct JS_FRIEND_API(GCDescription) { bool isCompartment_; explicit GCDescription(bool isCompartment) @@ -281,7 +262,7 @@ typedef void * callback may be used for GC notifications as well as to perform additional * marking. */ -extern JS_PUBLIC_API(GCSliceCallback) +extern JS_FRIEND_API(GCSliceCallback) SetGCSliceCallback(JSRuntime *rt, GCSliceCallback callback); /* @@ -290,7 +271,7 @@ SetGCSliceCallback(JSRuntime *rt, GCSliceCallback callback); * There is not currently a way to re-enable incremental GC once it has been * disabled on the runtime. */ -extern JS_PUBLIC_API(void) +extern JS_FRIEND_API(void) DisableIncrementalGC(JSRuntime *rt); /* @@ -301,7 +282,7 @@ DisableIncrementalGC(JSRuntime *rt); * GCDescription returned by GCSliceCallback may help narrow down the cause if * collections are not happening incrementally when expected. */ -extern JS_PUBLIC_API(bool) +extern JS_FRIEND_API(bool) IsIncrementalGCEnabled(JSRuntime *rt); /* @@ -310,20 +291,20 @@ IsIncrementalGCEnabled(JSRuntime *rt); * pointer callbacks. There is not currently a way to re-enable compacting GC * once it has been disabled on the runtime. */ -extern JS_PUBLIC_API(void) +extern JS_FRIEND_API(void) DisableCompactingGC(JSRuntime *rt); /* * Returns true if compacting GC is enabled. */ -extern JS_PUBLIC_API(bool) +extern JS_FRIEND_API(bool) IsCompactingGCEnabled(JSRuntime *rt); /* * Returns true while an incremental GC is ongoing, both when actively * collecting and between slices. */ -extern JS_PUBLIC_API(bool) +JS_FRIEND_API(bool) IsIncrementalGCInProgress(JSRuntime *rt); /* @@ -331,29 +312,29 @@ IsIncrementalGCInProgress(JSRuntime *rt); * This is generally only true when running mutator code in-between GC slices. * At other times, the barrier may be elided for performance. */ -extern JS_PUBLIC_API(bool) +extern JS_FRIEND_API(bool) IsIncrementalBarrierNeeded(JSRuntime *rt); -extern JS_PUBLIC_API(bool) +extern JS_FRIEND_API(bool) IsIncrementalBarrierNeeded(JSContext *cx); /* * Notify the GC that a reference to a GC thing is about to be overwritten. * These methods must be called if IsIncrementalBarrierNeeded. */ -extern JS_PUBLIC_API(void) +extern JS_FRIEND_API(void) IncrementalReferenceBarrier(GCCellPtr thing); -extern JS_PUBLIC_API(void) +extern JS_FRIEND_API(void) IncrementalValueBarrier(const Value &v); -extern JS_PUBLIC_API(void) +extern JS_FRIEND_API(void) IncrementalObjectBarrier(JSObject *obj); /* * Returns true if the most recent GC ran incrementally. */ -extern JS_PUBLIC_API(bool) +extern JS_FRIEND_API(bool) WasIncrementalGC(JSRuntime *rt); /* @@ -365,7 +346,7 @@ WasIncrementalGC(JSRuntime *rt); */ /* Ensure that generational GC is disabled within some scope. */ -class JS_PUBLIC_API(AutoDisableGenerationalGC) +class JS_FRIEND_API(AutoDisableGenerationalGC) { js::gc::GCRuntime *gc; #ifdef JS_GC_ZEAL @@ -381,7 +362,7 @@ class JS_PUBLIC_API(AutoDisableGenerationalGC) * Returns true if generational allocation and collection is currently enabled * on the given runtime. */ -extern JS_PUBLIC_API(bool) +extern JS_FRIEND_API(bool) IsGenerationalGCEnabled(JSRuntime *rt); /* @@ -389,7 +370,7 @@ IsGenerationalGCEnabled(JSRuntime *rt); * of GCs that have been run, but is guaranteed to be monotonically increasing * with GC activity. */ -extern JS_PUBLIC_API(size_t) +extern JS_FRIEND_API(size_t) GetGCNumber(); /* @@ -397,7 +378,7 @@ GetGCNumber(); * back to the system incase it is needed soon afterwards. This call forces the * GC to return this memory immediately. */ -extern JS_PUBLIC_API(void) +extern JS_FRIEND_API(void) ShrinkGCBuffers(JSRuntime *rt); /* diff --git a/js/src/builtin/TestingFunctions.cpp b/js/src/builtin/TestingFunctions.cpp index 8718f4c8fe42..faf5484aa35f 100644 --- a/js/src/builtin/TestingFunctions.cpp +++ b/js/src/builtin/TestingFunctions.cpp @@ -238,8 +238,10 @@ GC(JSContext *cx, unsigned argc, jsval *vp) else JS::PrepareForFullGC(cx->runtime()); - JSGCInvocationKind gckind = shrinking ? GC_SHRINK : GC_NORMAL; - JS::GCForReason(cx->runtime(), gckind, JS::gcreason::API); + if (shrinking) + JS::ShrinkingGC(cx->runtime(), JS::gcreason::API); + else + JS::GCForReason(cx->runtime(), JS::gcreason::API); char buf[256] = { '\0' }; #ifndef JS_MORE_DETERMINISTIC diff --git a/js/src/devtools/rootAnalysis/loadCallgraph.js b/js/src/devtools/rootAnalysis/loadCallgraph.js index 022fcdeb8a84..6a1a040740a1 100644 --- a/js/src/devtools/rootAnalysis/loadCallgraph.js +++ b/js/src/devtools/rootAnalysis/loadCallgraph.js @@ -160,7 +160,7 @@ function loadCallgraph(file) suppressedFunctions[name] = true; } - for (var gcName of [ 'void js::gc::GCRuntime::collect(uint8, js::SliceBudget, uint32)', + for (var gcName of [ 'void js::gc::GCRuntime::collect(uint8, js::SliceBudget*, uint32, uint32)', 'void js::gc::GCRuntime::minorGC(uint32)', 'void js::gc::GCRuntime::minorGC(uint32)' ]) { diff --git a/js/src/gc/GCRuntime.h b/js/src/gc/GCRuntime.h index 197fbc9a3294..0b9001c6122d 100644 --- a/js/src/gc/GCRuntime.h +++ b/js/src/gc/GCRuntime.h @@ -326,9 +326,8 @@ class GCRuntime } bool gcIfNeeded(JSContext *cx = nullptr); void gc(JSGCInvocationKind gckind, JS::gcreason::Reason reason); - void startGC(JSGCInvocationKind gckind, JS::gcreason::Reason reason, int64_t millis = 0); - void gcSlice(JS::gcreason::Reason reason, int64_t millis = 0); - void finishGC(JS::gcreason::Reason reason); + void gcSlice(JSGCInvocationKind gckind, JS::gcreason::Reason reason, int64_t millis = 0); + void gcFinalSlice(JSGCInvocationKind gckind, JS::gcreason::Reason reason); void gcDebugSlice(SliceBudget &budget); void runDebugGC(); @@ -568,9 +567,10 @@ class GCRuntime void startBackgroundAllocTaskIfIdle(); void requestMajorGC(JS::gcreason::Reason reason); - SliceBudget defaultBudget(JS::gcreason::Reason reason, int64_t millis); - void collect(bool incremental, SliceBudget budget, JS::gcreason::Reason reason); - bool gcCycle(bool incremental, SliceBudget &budget, JS::gcreason::Reason reason); + void collect(bool incremental, SliceBudget &budget, JSGCInvocationKind gckind, + JS::gcreason::Reason reason); + bool gcCycle(bool incremental, SliceBudget &budget, JSGCInvocationKind gckind, + JS::gcreason::Reason reason); gcstats::ZoneGCStats scanZonesBeforeGC(); void budgetIncrementalGC(SliceBudget &budget); void resetIncrementalGC(const char *reason); diff --git a/js/src/jsapi-tests/testGCFinalizeCallback.cpp b/js/src/jsapi-tests/testGCFinalizeCallback.cpp index b7c681b9aabb..e526ce1c1173 100644 --- a/js/src/jsapi-tests/testGCFinalizeCallback.cpp +++ b/js/src/jsapi-tests/testGCFinalizeCallback.cpp @@ -24,7 +24,7 @@ BEGIN_TEST(testGCFinalizeCallback) /* Full GC, incremental. */ FinalizeCalls = 0; JS::PrepareForFullGC(rt); - JS::StartIncrementalGC(rt, GC_NORMAL, JS::gcreason::API, 1000000); + JS::IncrementalGC(rt, JS::gcreason::API, 1000000); CHECK(!rt->gc.isIncrementalGCInProgress()); CHECK(rt->gc.isFullGc()); CHECK(checkMultipleGroups()); @@ -41,7 +41,7 @@ BEGIN_TEST(testGCFinalizeCallback) /* Compartment GC, non-incremental, single compartment. */ FinalizeCalls = 0; JS::PrepareZoneForGC(global1->zone()); - JS::GCForReason(rt, GC_NORMAL, JS::gcreason::API); + JS::GCForReason(rt, JS::gcreason::API); CHECK(!rt->gc.isFullGc()); CHECK(checkSingleGroup()); CHECK(checkFinalizeStatus()); @@ -52,7 +52,7 @@ BEGIN_TEST(testGCFinalizeCallback) JS::PrepareZoneForGC(global1->zone()); JS::PrepareZoneForGC(global2->zone()); JS::PrepareZoneForGC(global3->zone()); - JS::GCForReason(rt, GC_NORMAL, JS::gcreason::API); + JS::GCForReason(rt, JS::gcreason::API); CHECK(!rt->gc.isFullGc()); CHECK(checkSingleGroup()); CHECK(checkFinalizeStatus()); @@ -61,7 +61,7 @@ BEGIN_TEST(testGCFinalizeCallback) /* Compartment GC, incremental, single compartment. */ FinalizeCalls = 0; JS::PrepareZoneForGC(global1->zone()); - JS::StartIncrementalGC(rt, GC_NORMAL, JS::gcreason::API, 1000000); + JS::IncrementalGC(rt, JS::gcreason::API, 1000000); CHECK(!rt->gc.isIncrementalGCInProgress()); CHECK(!rt->gc.isFullGc()); CHECK(checkSingleGroup()); @@ -73,7 +73,7 @@ BEGIN_TEST(testGCFinalizeCallback) JS::PrepareZoneForGC(global1->zone()); JS::PrepareZoneForGC(global2->zone()); JS::PrepareZoneForGC(global3->zone()); - JS::StartIncrementalGC(rt, GC_NORMAL, JS::gcreason::API, 1000000); + JS::IncrementalGC(rt, JS::gcreason::API, 1000000); CHECK(!rt->gc.isIncrementalGCInProgress()); CHECK(!rt->gc.isFullGc()); CHECK(checkMultipleGroups()); diff --git a/js/src/jsapi-tests/testPreserveJitCode.cpp b/js/src/jsapi-tests/testPreserveJitCode.cpp index 40ee89a8d030..fd7d328a3e0c 100644 --- a/js/src/jsapi-tests/testPreserveJitCode.cpp +++ b/js/src/jsapi-tests/testPreserveJitCode.cpp @@ -65,10 +65,10 @@ testPreserveJitCode(bool preserveJitCode, unsigned remainingIonScripts) CHECK_EQUAL(value.toInt32(), 45); CHECK_EQUAL(countIonScripts(global), 1u); - GCForReason(rt, GC_NORMAL, gcreason::API); + GCForReason(rt, gcreason::API); CHECK_EQUAL(countIonScripts(global), remainingIonScripts); - GCForReason(rt, GC_SHRINK, gcreason::API); + ShrinkingGC(rt, gcreason::API); CHECK_EQUAL(countIonScripts(global), 0u); return true; diff --git a/js/src/jsapi-tests/tests.h b/js/src/jsapi-tests/tests.h index 20bd5ea2f798..d01113d93802 100644 --- a/js/src/jsapi-tests/tests.h +++ b/js/src/jsapi-tests/tests.h @@ -428,7 +428,7 @@ class AutoLeaveZeal JS_GetGCZeal(cx_, &zeal_, &frequency_); JS_SetGCZeal(cx_, 0, 0); JS::PrepareForFullGC(JS_GetRuntime(cx_)); - JS::GCForReason(JS_GetRuntime(cx_), GC_SHRINK, JS::gcreason::DEBUG_GC); + JS::ShrinkingGC(JS_GetRuntime(cx_), JS::gcreason::DEBUG_GC); } ~AutoLeaveZeal() { JS_SetGCZeal(cx_, zeal_, frequency_); diff --git a/js/src/jsfriendapi.cpp b/js/src/jsfriendapi.cpp index 7169c4527edf..c9645f7853a6 100644 --- a/js/src/jsfriendapi.cpp +++ b/js/src/jsfriendapi.cpp @@ -153,6 +153,72 @@ JS_NewObjectWithUniqueType(JSContext *cx, const JSClass *clasp, HandleObject pro return obj; } +JS_FRIEND_API(void) +JS::PrepareZoneForGC(Zone *zone) +{ + zone->scheduleGC(); +} + +JS_FRIEND_API(void) +JS::PrepareForFullGC(JSRuntime *rt) +{ + for (ZonesIter zone(rt, WithAtoms); !zone.done(); zone.next()) + zone->scheduleGC(); +} + +JS_FRIEND_API(void) +JS::PrepareForIncrementalGC(JSRuntime *rt) +{ + if (!JS::IsIncrementalGCInProgress(rt)) + return; + + for (ZonesIter zone(rt, WithAtoms); !zone.done(); zone.next()) { + if (zone->wasGCStarted()) + PrepareZoneForGC(zone); + } +} + +JS_FRIEND_API(bool) +JS::IsGCScheduled(JSRuntime *rt) +{ + for (ZonesIter zone(rt, WithAtoms); !zone.done(); zone.next()) { + if (zone->isGCScheduled()) + return true; + } + + return false; +} + +JS_FRIEND_API(void) +JS::SkipZoneForGC(Zone *zone) +{ + zone->unscheduleGC(); +} + +JS_FRIEND_API(void) +JS::GCForReason(JSRuntime *rt, gcreason::Reason reason) +{ + rt->gc.gc(GC_NORMAL, reason); +} + +JS_FRIEND_API(void) +JS::ShrinkingGC(JSRuntime *rt, gcreason::Reason reason) +{ + rt->gc.gc(GC_SHRINK, reason); +} + +JS_FRIEND_API(void) +JS::IncrementalGC(JSRuntime *rt, gcreason::Reason reason, int64_t millis) +{ + rt->gc.gcSlice(GC_NORMAL, reason, millis); +} + +JS_FRIEND_API(void) +JS::FinishIncrementalGC(JSRuntime *rt, gcreason::Reason reason) +{ + rt->gc.gcFinalSlice(GC_NORMAL, reason); +} + JS_FRIEND_API(JSPrincipals *) JS_GetCompartmentPrincipals(JSCompartment *compartment) { @@ -997,6 +1063,12 @@ js::IsContextRunningJS(JSContext *cx) return cx->currentlyRunning(); } +JS_FRIEND_API(JS::GCSliceCallback) +JS::SetGCSliceCallback(JSRuntime *rt, GCSliceCallback callback) +{ + return rt->gc.setSliceCallback(callback); +} + JS_FRIEND_API(int64_t) GetMaxGCPauseSinceClear(JSRuntime *rt) { @@ -1009,12 +1081,160 @@ ClearMaxGCPauseAccumulator(JSRuntime *rt) return rt->gc.stats.clearMaxGCPauseAccumulator(); } +JS_FRIEND_API(bool) +JS::WasIncrementalGC(JSRuntime *rt) +{ + return rt->gc.isIncrementalGc(); +} + +char16_t * +JS::GCDescription::formatMessage(JSRuntime *rt) const +{ + return rt->gc.stats.formatMessage(); +} + +char16_t * +JS::GCDescription::formatJSON(JSRuntime *rt, uint64_t timestamp) const +{ + return rt->gc.stats.formatJSON(timestamp); +} + JS_FRIEND_API(void) JS::NotifyDidPaint(JSRuntime *rt) { rt->gc.notifyDidPaint(); } +JS_FRIEND_API(bool) +JS::IsIncrementalGCEnabled(JSRuntime *rt) +{ + return rt->gc.isIncrementalGCEnabled(); +} + +JS_FRIEND_API(bool) +JS::IsIncrementalGCInProgress(JSRuntime *rt) +{ + return rt->gc.isIncrementalGCInProgress() && !rt->gc.isVerifyPreBarriersEnabled(); +} + +JS_FRIEND_API(void) +JS::DisableIncrementalGC(JSRuntime *rt) +{ + rt->gc.disallowIncrementalGC(); +} + +JS_FRIEND_API(void) +JS::DisableCompactingGC(JSRuntime *rt) +{ +#ifdef JSGC_COMPACTING + rt->gc.disableCompactingGC(); +#endif +} + +JS_FRIEND_API(bool) +JS::IsCompactingGCEnabled(JSRuntime *rt) +{ +#ifdef JSGC_COMPACTING + return rt->gc.isCompactingGCEnabled(); +#else + return false; +#endif +} + +JS::AutoDisableGenerationalGC::AutoDisableGenerationalGC(JSRuntime *rt) + : gc(&rt->gc) +#ifdef JS_GC_ZEAL + , restartVerifier(false) +#endif +{ +#ifdef JS_GC_ZEAL + restartVerifier = gc->endVerifyPostBarriers(); +#endif + gc->disableGenerationalGC(); +} + +JS::AutoDisableGenerationalGC::~AutoDisableGenerationalGC() +{ + gc->enableGenerationalGC(); +#ifdef JS_GC_ZEAL + if (restartVerifier) { + MOZ_ASSERT(gc->isGenerationalGCEnabled()); + gc->startVerifyPostBarriers(); + } +#endif +} + +extern JS_FRIEND_API(bool) +JS::IsGenerationalGCEnabled(JSRuntime *rt) +{ + return rt->gc.isGenerationalGCEnabled(); +} + +JS_FRIEND_API(bool) +JS::IsIncrementalBarrierNeeded(JSRuntime *rt) +{ + return rt->gc.state() == gc::MARK && !rt->isHeapBusy(); +} + +JS_FRIEND_API(bool) +JS::IsIncrementalBarrierNeeded(JSContext *cx) +{ + return IsIncrementalBarrierNeeded(cx->runtime()); +} + +JS_FRIEND_API(void) +JS::IncrementalObjectBarrier(JSObject *obj) +{ + if (!obj) + return; + + MOZ_ASSERT(!obj->zone()->runtimeFromMainThread()->isHeapMajorCollecting()); + + JSObject::writeBarrierPre(obj); +} + +JS_FRIEND_API(void) +JS::IncrementalReferenceBarrier(GCCellPtr thing) +{ + if (!thing) + return; + + if (thing.isString() && StringIsPermanentAtom(thing.toString())) + return; + +#ifdef DEBUG + Zone *zone = thing.isObject() + ? thing.toObject()->zone() + : thing.asCell()->asTenured().zone(); + MOZ_ASSERT(!zone->runtimeFromMainThread()->isHeapMajorCollecting()); +#endif + + switch(thing.kind()) { + case JSTRACE_OBJECT: return JSObject::writeBarrierPre(thing.toObject()); + case JSTRACE_STRING: return JSString::writeBarrierPre(thing.toString()); + case JSTRACE_SCRIPT: return JSScript::writeBarrierPre(thing.toScript()); + case JSTRACE_SYMBOL: return JS::Symbol::writeBarrierPre(thing.toSymbol()); + case JSTRACE_LAZY_SCRIPT: + return LazyScript::writeBarrierPre(static_cast(thing.asCell())); + case JSTRACE_JITCODE: + return jit::JitCode::writeBarrierPre(static_cast(thing.asCell())); + case JSTRACE_SHAPE: + return Shape::writeBarrierPre(static_cast(thing.asCell())); + case JSTRACE_BASE_SHAPE: + return BaseShape::writeBarrierPre(static_cast(thing.asCell())); + case JSTRACE_TYPE_OBJECT: + return types::TypeObject::writeBarrierPre(static_cast(thing.asCell())); + default: + MOZ_CRASH("Invalid trace kind in IncrementalReferenceBarrier."); + } +} + +JS_FRIEND_API(void) +JS::IncrementalValueBarrier(const Value &v) +{ + js::HeapValue::writeBarrierPre(v); +} + JS_FRIEND_API(void) JS::PokeGC(JSRuntime *rt) { diff --git a/js/src/jsgc.cpp b/js/src/jsgc.cpp index 60597e3bb93c..beec59c69fb7 100644 --- a/js/src/jsgc.cpp +++ b/js/src/jsgc.cpp @@ -3263,7 +3263,7 @@ GCRuntime::maybeAllocTriggerZoneGC(Zone *zone, const AutoLockGC &lock) // to try to avoid performing non-incremental GCs on zones // which allocate a lot of data, even when incremental slices // can't be triggered via scheduling in the event loop. - triggerZoneGC(zone, JS::gcreason::INCREMENTAL_ALLOC_TRIGGER); + triggerZoneGC(zone, JS::gcreason::ALLOC_TRIGGER); // Delay the next slice until a certain amount of allocation // has been performed. @@ -3332,7 +3332,7 @@ GCRuntime::maybeGC(Zone *zone) !isBackgroundSweeping()) { PrepareZoneForGC(zone); - gc(GC_NORMAL, JS::gcreason::MAYBEGC); + gcSlice(GC_NORMAL, JS::gcreason::MAYBEGC); return true; } @@ -3358,7 +3358,7 @@ GCRuntime::maybePeriodicFullGC() numArenasFreeCommitted > decommitThreshold) { JS::PrepareForFullGC(rt); - gc(GC_SHRINK, JS::gcreason::MAYBEGC); + gcSlice(GC_SHRINK, JS::gcreason::MAYBEGC); } else { nextFullGCTime = now + GC_IDLE_FULL_SPAN; } @@ -5785,16 +5785,9 @@ GCRuntime::resetIncrementalGC(const char *reason) /* Finish sweeping the current zone group, then abort. */ abortSweepAfterCurrentGroup = true; - - /* Don't perform any compaction after sweeping. */ - JSGCInvocationKind oldInvocationKind = invocationKind; - invocationKind = GC_NORMAL; - SliceBudget budget; incrementalCollectSlice(budget, JS::gcreason::RESET); - invocationKind = oldInvocationKind; - { gcstats::AutoPhase ap(stats, gcstats::PHASE_WAIT_BACKGROUND_THREAD); rt->gc.waitBackgroundSweepOrAllocEnd(); @@ -6117,7 +6110,8 @@ class AutoDisableStoreBuffer * to run another cycle. */ MOZ_NEVER_INLINE bool -GCRuntime::gcCycle(bool incremental, SliceBudget &budget, JS::gcreason::Reason reason) +GCRuntime::gcCycle(bool incremental, SliceBudget &budget, JSGCInvocationKind gckind, + JS::gcreason::Reason reason) { evictNursery(reason); @@ -6180,6 +6174,10 @@ GCRuntime::gcCycle(bool incremental, SliceBudget &budget, JS::gcreason::Reason r TraceMajorGCStart(); + /* Set the invocation kind in the first slice. */ + if (!isIncrementalGCInProgress()) + invocationKind = gckind; + incrementalCollectSlice(budget, reason); #ifndef JS_MORE_DETERMINISTIC @@ -6264,7 +6262,8 @@ GCRuntime::scanZonesBeforeGC() } void -GCRuntime::collect(bool incremental, SliceBudget budget, JS::gcreason::Reason reason) +GCRuntime::collect(bool incremental, SliceBudget &budget, JSGCInvocationKind gckind, + JS::gcreason::Reason reason) { /* GC shouldn't be running in parallel execution mode */ MOZ_ALWAYS_TRUE(!InParallelSection()); @@ -6291,9 +6290,9 @@ GCRuntime::collect(bool incremental, SliceBudget budget, JS::gcreason::Reason re AutoStopVerifyingBarriers av(rt, reason == JS::gcreason::SHUTDOWN_CC || reason == JS::gcreason::DESTROY_RUNTIME); - gcstats::AutoGCSlice agc(stats, scanZonesBeforeGC(), invocationKind, reason); + gcstats::AutoGCSlice agc(stats, scanZonesBeforeGC(), gckind, reason); - cleanUpEverything = ShouldCleanUpEverything(reason, invocationKind); + cleanUpEverything = ShouldCleanUpEverything(reason, gckind); bool repeat = false; do { @@ -6308,7 +6307,7 @@ GCRuntime::collect(bool incremental, SliceBudget budget, JS::gcreason::Reason re } poked = false; - bool wasReset = gcCycle(incremental, budget, reason); + bool wasReset = gcCycle(incremental, budget, gckind, reason); if (!isIncrementalGCInProgress()) { gcstats::AutoPhase ap(stats, gcstats::PHASE_GC_END); @@ -6350,48 +6349,34 @@ GCRuntime::collect(bool incremental, SliceBudget budget, JS::gcreason::Reason re EnqueuePendingParseTasksAfterGC(rt); } -SliceBudget -GCRuntime::defaultBudget(JS::gcreason::Reason reason, int64_t millis) -{ - if (millis == 0) { - if (reason == JS::gcreason::ALLOC_TRIGGER) - millis = sliceBudget; - else if (schedulingState.inHighFrequencyGCMode() && tunables.isDynamicMarkSliceEnabled()) - millis = sliceBudget * IGC_MARK_SLICE_MULTIPLIER; - else - millis = sliceBudget; - } - - return SliceBudget(TimeBudget(millis)); -} - void GCRuntime::gc(JSGCInvocationKind gckind, JS::gcreason::Reason reason) { - invocationKind = gckind; - collect(false, SliceBudget(), reason); + SliceBudget budget; + collect(false, budget, gckind, reason); } void -GCRuntime::startGC(JSGCInvocationKind gckind, JS::gcreason::Reason reason, int64_t millis) +GCRuntime::gcSlice(JSGCInvocationKind gckind, JS::gcreason::Reason reason, int64_t millis) { - MOZ_ASSERT(!isIncrementalGCInProgress()); - invocationKind = gckind; - collect(true, defaultBudget(reason, millis), reason); + SliceBudget budget; + if (millis) + budget = SliceBudget(TimeBudget(millis)); + else if (reason == JS::gcreason::ALLOC_TRIGGER) + budget = SliceBudget(TimeBudget(sliceBudget)); + else if (schedulingState.inHighFrequencyGCMode() && tunables.isDynamicMarkSliceEnabled()) + budget = SliceBudget(TimeBudget(sliceBudget * IGC_MARK_SLICE_MULTIPLIER)); + else + budget = SliceBudget(TimeBudget(sliceBudget)); + + collect(true, budget, gckind, reason); } void -GCRuntime::gcSlice(JS::gcreason::Reason reason, int64_t millis) +GCRuntime::gcFinalSlice(JSGCInvocationKind gckind, JS::gcreason::Reason reason) { - MOZ_ASSERT(isIncrementalGCInProgress()); - collect(true, defaultBudget(reason, millis), reason); -} - -void -GCRuntime::finishGC(JS::gcreason::Reason reason) -{ - MOZ_ASSERT(isIncrementalGCInProgress()); - collect(true, SliceBudget(), reason); + SliceBudget budget; + collect(true, budget, gckind, reason); } void @@ -6410,14 +6395,14 @@ GCRuntime::notifyDidPaint() if (zealMode == ZealFrameGCValue) { JS::PrepareForFullGC(rt); - gc(GC_NORMAL, JS::gcreason::REFRESH_FRAME); + gcSlice(GC_NORMAL, JS::gcreason::REFRESH_FRAME); return; } #endif - if (isIncrementalGCInProgress() && !interFrameGC) { + if (JS::IsIncrementalGCInProgress(rt) && !interFrameGC) { JS::PrepareForIncrementalGC(rt); - gcSlice(JS::gcreason::REFRESH_FRAME); + gcSlice(GC_NORMAL, JS::gcreason::REFRESH_FRAME); } interFrameGC = false; @@ -6437,14 +6422,12 @@ void GCRuntime::gcDebugSlice(SliceBudget &budget) { if (!ZonesSelected(rt)) { - if (isIncrementalGCInProgress()) + if (JS::IsIncrementalGCInProgress(rt)) JS::PrepareForIncrementalGC(rt); else JS::PrepareForFullGC(rt); } - if (!isIncrementalGCInProgress()) - invocationKind = GC_NORMAL; - collect(true, budget, JS::gcreason::DEBUG_GC); + collect(true, budget, GC_NORMAL, JS::gcreason::DEBUG_GC); } /* Schedule a full GC unless a zone will already be collected. */ @@ -6455,7 +6438,7 @@ js::PrepareForDebugGC(JSRuntime *rt) JS::PrepareForFullGC(rt); } -JS_PUBLIC_API(void) +JS_FRIEND_API(void) JS::ShrinkGCBuffers(JSRuntime *rt) { rt->gc.shrinkBuffers(); @@ -6563,14 +6546,7 @@ GCRuntime::gcIfNeeded(JSContext *cx /* = nullptr */) } if (majorGCRequested) { - if (majorGCTriggerReason == JS::gcreason::INCREMENTAL_ALLOC_TRIGGER) { - if (!isIncrementalGCInProgress()) - startGC(GC_NORMAL, majorGCTriggerReason); - else - gcSlice(majorGCTriggerReason); - } else { - gc(GC_NORMAL, majorGCTriggerReason); - } + gcSlice(GC_NORMAL, rt->gc.majorGCTriggerReason); return true; } @@ -6735,9 +6711,7 @@ GCRuntime::runDebugGC() budget = SliceBudget(WorkBudget(1)); } - if (!isIncrementalGCInProgress()) - invocationKind = GC_NORMAL; - collect(true, budget, JS::gcreason::DEBUG_GC); + collect(true, budget, GC_NORMAL, JS::gcreason::DEBUG_GC); /* * For multi-slice zeal, reset the slice size when we get to the sweep @@ -6749,9 +6723,9 @@ GCRuntime::runDebugGC() incrementalLimit = zealFrequency / 2; } } else if (type == ZealCompactValue) { - gc(GC_SHRINK, JS::gcreason::DEBUG_GC); + collect(false, budget, GC_SHRINK, JS::gcreason::DEBUG_GC); } else { - gc(GC_NORMAL, JS::gcreason::DEBUG_GC); + collect(false, budget, GC_NORMAL, JS::gcreason::DEBUG_GC); } #endif @@ -6978,7 +6952,7 @@ js::gc::AssertGCThingHasType(js::gc::Cell *cell, JSGCTraceKind kind) MOZ_ASSERT(MapAllocToTraceKind(cell->asTenured().getAllocKind()) == kind); } -JS_PUBLIC_API(size_t) +JS_FRIEND_API(size_t) JS::GetGCNumber() { JSRuntime *rt = js::TlsPerThreadData.get()->runtimeFromMainThread(); @@ -7116,225 +7090,3 @@ js::gc::CheckHashTablesAfterMovingGC(JSRuntime *rt) } } #endif - -JS_PUBLIC_API(void) -JS::PrepareZoneForGC(Zone *zone) -{ - zone->scheduleGC(); -} - -JS_PUBLIC_API(void) -JS::PrepareForFullGC(JSRuntime *rt) -{ - for (ZonesIter zone(rt, WithAtoms); !zone.done(); zone.next()) - zone->scheduleGC(); -} - -JS_PUBLIC_API(void) -JS::PrepareForIncrementalGC(JSRuntime *rt) -{ - if (!JS::IsIncrementalGCInProgress(rt)) - return; - - for (ZonesIter zone(rt, WithAtoms); !zone.done(); zone.next()) { - if (zone->wasGCStarted()) - PrepareZoneForGC(zone); - } -} - -JS_PUBLIC_API(bool) -JS::IsGCScheduled(JSRuntime *rt) -{ - for (ZonesIter zone(rt, WithAtoms); !zone.done(); zone.next()) { - if (zone->isGCScheduled()) - return true; - } - - return false; -} - -JS_PUBLIC_API(void) -JS::SkipZoneForGC(Zone *zone) -{ - zone->unscheduleGC(); -} - -JS_PUBLIC_API(void) -JS::GCForReason(JSRuntime *rt, JSGCInvocationKind gckind, gcreason::Reason reason) -{ - MOZ_ASSERT(gckind == GC_NORMAL || gckind == GC_SHRINK); - rt->gc.gc(gckind, reason); -} - -JS_PUBLIC_API(void) -JS::StartIncrementalGC(JSRuntime *rt, JSGCInvocationKind gckind, gcreason::Reason reason, int64_t millis) -{ - MOZ_ASSERT(gckind == GC_NORMAL || gckind == GC_SHRINK); - rt->gc.startGC(gckind, reason, millis); -} - -JS_PUBLIC_API(void) -JS::IncrementalGCSlice(JSRuntime *rt, gcreason::Reason reason, int64_t millis) -{ - rt->gc.gcSlice(reason, millis); -} - -JS_PUBLIC_API(void) -JS::FinishIncrementalGC(JSRuntime *rt, gcreason::Reason reason) -{ - rt->gc.finishGC(reason); -} - -char16_t * -JS::GCDescription::formatMessage(JSRuntime *rt) const -{ - return rt->gc.stats.formatMessage(); -} - -char16_t * -JS::GCDescription::formatJSON(JSRuntime *rt, uint64_t timestamp) const -{ - return rt->gc.stats.formatJSON(timestamp); -} - -JS_PUBLIC_API(JS::GCSliceCallback) -JS::SetGCSliceCallback(JSRuntime *rt, GCSliceCallback callback) -{ - return rt->gc.setSliceCallback(callback); -} - -JS_PUBLIC_API(void) -JS::DisableIncrementalGC(JSRuntime *rt) -{ - rt->gc.disallowIncrementalGC(); -} - -JS_PUBLIC_API(bool) -JS::IsIncrementalGCEnabled(JSRuntime *rt) -{ - return rt->gc.isIncrementalGCEnabled(); -} - -JS_PUBLIC_API(void) -JS::DisableCompactingGC(JSRuntime *rt) -{ -#ifdef JSGC_COMPACTING - rt->gc.disableCompactingGC(); -#endif -} - -JS_PUBLIC_API(bool) -JS::IsCompactingGCEnabled(JSRuntime *rt) -{ -#ifdef JSGC_COMPACTING - return rt->gc.isCompactingGCEnabled(); -#else - return false; -#endif -} - -JS_PUBLIC_API(bool) -JS::IsIncrementalGCInProgress(JSRuntime *rt) -{ - return rt->gc.isIncrementalGCInProgress() && !rt->gc.isVerifyPreBarriersEnabled(); -} - -JS_PUBLIC_API(bool) -JS::IsIncrementalBarrierNeeded(JSRuntime *rt) -{ - return rt->gc.state() == gc::MARK && !rt->isHeapBusy(); -} - -JS_PUBLIC_API(bool) -JS::IsIncrementalBarrierNeeded(JSContext *cx) -{ - return IsIncrementalBarrierNeeded(cx->runtime()); -} - -JS_PUBLIC_API(void) -JS::IncrementalReferenceBarrier(GCCellPtr thing) -{ - if (!thing) - return; - - if (thing.isString() && StringIsPermanentAtom(thing.toString())) - return; - -#ifdef DEBUG - Zone *zone = thing.isObject() - ? thing.toObject()->zone() - : thing.asCell()->asTenured().zone(); - MOZ_ASSERT(!zone->runtimeFromMainThread()->isHeapMajorCollecting()); -#endif - - switch(thing.kind()) { - case JSTRACE_OBJECT: return JSObject::writeBarrierPre(thing.toObject()); - case JSTRACE_STRING: return JSString::writeBarrierPre(thing.toString()); - case JSTRACE_SCRIPT: return JSScript::writeBarrierPre(thing.toScript()); - case JSTRACE_SYMBOL: return JS::Symbol::writeBarrierPre(thing.toSymbol()); - case JSTRACE_LAZY_SCRIPT: - return LazyScript::writeBarrierPre(static_cast(thing.asCell())); - case JSTRACE_JITCODE: - return jit::JitCode::writeBarrierPre(static_cast(thing.asCell())); - case JSTRACE_SHAPE: - return Shape::writeBarrierPre(static_cast(thing.asCell())); - case JSTRACE_BASE_SHAPE: - return BaseShape::writeBarrierPre(static_cast(thing.asCell())); - case JSTRACE_TYPE_OBJECT: - return types::TypeObject::writeBarrierPre(static_cast(thing.asCell())); - default: - MOZ_CRASH("Invalid trace kind in IncrementalReferenceBarrier."); - } -} - -JS_PUBLIC_API(void) -JS::IncrementalValueBarrier(const Value &v) -{ - js::HeapValue::writeBarrierPre(v); -} - -JS_PUBLIC_API(void) -JS::IncrementalObjectBarrier(JSObject *obj) -{ - if (!obj) - return; - - MOZ_ASSERT(!obj->zone()->runtimeFromMainThread()->isHeapMajorCollecting()); - - JSObject::writeBarrierPre(obj); -} - -JS_PUBLIC_API(bool) -JS::WasIncrementalGC(JSRuntime *rt) -{ - return rt->gc.isIncrementalGc(); -} - -JS::AutoDisableGenerationalGC::AutoDisableGenerationalGC(JSRuntime *rt) - : gc(&rt->gc) -#ifdef JS_GC_ZEAL - , restartVerifier(false) -#endif -{ -#ifdef JS_GC_ZEAL - restartVerifier = gc->endVerifyPostBarriers(); -#endif - gc->disableGenerationalGC(); -} - -JS::AutoDisableGenerationalGC::~AutoDisableGenerationalGC() -{ - gc->enableGenerationalGC(); -#ifdef JS_GC_ZEAL - if (restartVerifier) { - MOZ_ASSERT(gc->isGenerationalGCEnabled()); - gc->startVerifyPostBarriers(); - } -#endif -} - -JS_PUBLIC_API(bool) -JS::IsGenerationalGCEnabled(JSRuntime *rt) -{ - return rt->gc.isGenerationalGCEnabled(); -} diff --git a/js/src/jsgc.h b/js/src/jsgc.h index d9940e4febc5..4ca9ab92b3b2 100644 --- a/js/src/jsgc.h +++ b/js/src/jsgc.h @@ -945,6 +945,17 @@ TraceRuntime(JSTracer *trc); extern void ReleaseAllJITCode(FreeOp *op); +/* + * Kinds of js_GC invocation. + */ +typedef enum JSGCInvocationKind { + /* Normal invocation. */ + GC_NORMAL = 0, + + /* Minimize GC triggers and release empty GC chunks right away. */ + GC_SHRINK = 1 +} JSGCInvocationKind; + extern void PrepareForDebugGC(JSRuntime *rt); diff --git a/js/xpconnect/src/XPCComponents.cpp b/js/xpconnect/src/XPCComponents.cpp index 6af61cbdd8ed..e6aa4593281e 100644 --- a/js/xpconnect/src/XPCComponents.cpp +++ b/js/xpconnect/src/XPCComponents.cpp @@ -2750,7 +2750,7 @@ nsXPCComponents_Utils::ForceGC() { JSRuntime* rt = nsXPConnect::GetRuntimeInstance()->Runtime(); PrepareForFullGC(rt); - GCForReason(rt, GC_NORMAL, gcreason::COMPONENT_UTILS); + GCForReason(rt, gcreason::COMPONENT_UTILS); return NS_OK; } @@ -2800,7 +2800,7 @@ nsXPCComponents_Utils::ForceShrinkingGC() { JSRuntime* rt = nsXPConnect::GetRuntimeInstance()->Runtime(); PrepareForFullGC(rt); - GCForReason(rt, GC_SHRINK, gcreason::COMPONENT_UTILS); + ShrinkingGC(rt, gcreason::COMPONENT_UTILS); return NS_OK; } @@ -2823,8 +2823,10 @@ class PreciseGCRunnable : public nsRunnable } PrepareForFullGC(rt); - JSGCInvocationKind gckind = mShrinking ? GC_SHRINK : GC_NORMAL; - GCForReason(rt, gckind, gcreason::COMPONENT_UTILS); + if (mShrinking) + ShrinkingGC(rt, gcreason::COMPONENT_UTILS); + else + GCForReason(rt, gcreason::COMPONENT_UTILS); mCallback->Callback(); return NS_OK; diff --git a/xpcom/base/CycleCollectedJSRuntime.cpp b/xpcom/base/CycleCollectedJSRuntime.cpp index 0e10a427c394..e4e6b5be3d4e 100644 --- a/xpcom/base/CycleCollectedJSRuntime.cpp +++ b/xpcom/base/CycleCollectedJSRuntime.cpp @@ -1025,7 +1025,7 @@ CycleCollectedJSRuntime::GarbageCollect(uint32_t aReason) const JS::gcreason::Reason gcreason = static_cast(aReason); JS::PrepareForFullGC(mJSRuntime); - JS::GCForReason(mJSRuntime, GC_NORMAL, gcreason); + JS::GCForReason(mJSRuntime, gcreason); } void