diff --git a/js/public/RootingAPI.h b/js/public/RootingAPI.h index cec10467e555..53c23a048a78 100644 --- a/js/public/RootingAPI.h +++ b/js/public/RootingAPI.h @@ -196,9 +196,6 @@ namespace JS { template class Rooted; template class PersistentRooted; -/* This is exposing internal state of the GC for inlining purposes. */ -JS_FRIEND_API(bool) isGCEnabled(); - JS_FRIEND_API(void) HeapObjectPostBarrier(JSObject** objp, JSObject* prev, JSObject* next); JS_FRIEND_API(void) HeapStringPostBarrier(JSString** objp, JSString* prev, JSString* next); diff --git a/js/src/gc/GC.cpp b/js/src/gc/GC.cpp index a830da259198..d2d5f2beb1d8 100644 --- a/js/src/gc/GC.cpp +++ b/js/src/gc/GC.cpp @@ -1698,7 +1698,7 @@ void GCRuntime::callGCCallback(JSGCStatus status) const { MOZ_ASSERT(gcCallback.op); - gcCallback.op(TlsContext.get(), status, gcCallback.data); + gcCallback.op(rt->mainContextFromOwnThread(), status, gcCallback.data); } void @@ -1713,7 +1713,7 @@ void GCRuntime::callObjectsTenuredCallback() { if (tenuredCallback.op) - tenuredCallback.op(TlsContext.get(), tenuredCallback.data); + tenuredCallback.op(rt->mainContextFromOwnThread(), tenuredCallback.data); } bool @@ -1763,8 +1763,9 @@ GCRuntime::removeWeakPointerZonesCallback(JSWeakPointerZonesCallback callback) void GCRuntime::callWeakPointerZonesCallbacks() const { + JSContext* cx = rt->mainContextFromOwnThread(); for (auto const& p : updateWeakPointerZonesCallbacks.ref()) - p.op(TlsContext.get(), p.data); + p.op(cx, p.data); } bool @@ -1788,8 +1789,9 @@ GCRuntime::removeWeakPointerCompartmentCallback(JSWeakPointerCompartmentCallback void GCRuntime::callWeakPointerCompartmentCallbacks(JSCompartment* comp) const { + JSContext* cx = rt->mainContextFromOwnThread(); for (auto const& p : updateWeakPointerCompartmentCallbacks.ref()) - p.op(TlsContext.get(), comp, p.data); + p.op(cx, comp, p.data); } JS::GCSliceCallback @@ -2063,7 +2065,7 @@ GCRuntime::shouldCompact() bool GCRuntime::isCompactingGCEnabled() const { - return compactingEnabled && TlsContext.get()->compactingDisabledCount == 0; + return compactingEnabled && rt->mainContextFromOwnThread()->compactingDisabledCount == 0; } AutoDisableCompactingGC::AutoDisableCompactingGC(JSContext* cx) @@ -3213,7 +3215,7 @@ GCRuntime::requestMajorGC(JS::gcreason::Reason reason) // There's no need to use RequestInterruptUrgent here. It's slower because // it has to interrupt (looping) Ion code, but loops in Ion code that // affect GC will have an explicit interrupt check. - TlsContext.get()->requestInterrupt(JSContext::RequestInterruptCanWait); + rt->mainContextFromOwnThread()->requestInterrupt(JSContext::RequestInterruptCanWait); } void @@ -3228,7 +3230,7 @@ Nursery::requestMinorGC(JS::gcreason::Reason reason) const minorGCTriggerReason_ = reason; // See comment in requestMajorGC. - TlsContext.get()->requestInterrupt(JSContext::RequestInterruptCanWait); + runtime()->mainContextFromOwnThread()->requestInterrupt(JSContext::RequestInterruptCanWait); } bool @@ -3318,7 +3320,7 @@ GCRuntime::triggerZoneGC(Zone* zone, JS::gcreason::Reason reason, size_t used, s if (zone->isAtomsZone()) { /* We can't do a zone GC of the atoms compartment. */ - if (TlsContext.get()->keepAtoms || rt->hasHelperThreadZones()) { + if (rt->mainContextFromOwnThread()->keepAtoms || rt->hasHelperThreadZones()) { /* Skip GC and retrigger later, since atoms zone won't be collected * if keepAtoms is true. */ fullGCForAtomsRequested_ = true; @@ -3740,7 +3742,7 @@ JSCompartment::destroy(FreeOp* fop) if (auto callback = rt->destroyCompartmentCallback) callback(fop, this); if (principals()) - JS_DropPrincipals(TlsContext.get(), principals()); + JS_DropPrincipals(rt->mainContextFromOwnThread(), principals()); fop->delete_(this); rt->gc.stats().sweptCompartment(); } @@ -4077,11 +4079,12 @@ CompartmentCheckTracer::onChild(const JS::GCCellPtr& thing) void GCRuntime::checkForCompartmentMismatches() { - if (TlsContext.get()->disableStrictProxyCheckingCount) + JSContext* cx = rt->mainContextFromOwnThread(); + if (cx->disableStrictProxyCheckingCount) return; CompartmentCheckTracer trc(rt); - AutoAssertEmptyNursery empty(TlsContext.get()); + AutoAssertEmptyNursery empty(cx); for (ZonesIter zone(rt, SkipAtoms); !zone.done(); zone.next()) { trc.zone = zone; for (auto thingKind : AllAllocKinds()) { @@ -4103,9 +4106,9 @@ RelazifyFunctions(Zone* zone, AllocKind kind) MOZ_ASSERT(kind == AllocKind::FUNCTION || kind == AllocKind::FUNCTION_EXTENDED); - AutoAssertEmptyNursery empty(TlsContext.get()); - JSRuntime* rt = zone->runtimeFromActiveCooperatingThread(); + AutoAssertEmptyNursery empty(rt->mainContextFromOwnThread()); + for (auto i = zone->cellIter(kind, empty); !i.done(); i.next()) { JSFunction* fun = &i->as(); if (fun->hasScript()) @@ -4197,7 +4200,7 @@ GCRuntime::prepareZonesForCollection(JS::gcreason::Reason reason, bool* isFullOu } if (!cleanUpEverything && canAllocateMoreCode) { - jit::JitActivationIterator activation(TlsContext.get()); + jit::JitActivationIterator activation(rt->mainContextFromOwnThread()); if (!activation.done()) activation->compartment()->zone()->setPreservingCode(true); } @@ -4946,7 +4949,7 @@ GCRuntime::groupZonesForSweeping(JS::gcreason::Reason reason) MOZ_ASSERT(zone->gcSweepGroupEdges().empty()); #endif - JSContext* cx = TlsContext.get(); + JSContext* cx = rt->mainContextFromOwnThread(); Zone* maybeAtomsZone = atomsZone->wasGCStarted() ? atomsZone.ref() : nullptr; ZoneComponentFinder finder(cx->nativeStackLimit[JS::StackForSystemCode], maybeAtomsZone); if (!isIncremental || !findInterZoneEdges()) @@ -6597,7 +6600,7 @@ GCRuntime::compactPhase(JS::gcreason::Reason reason, SliceBudget& sliceBudget, // middle of relocating an arena, invalid JSScript pointers may be // accessed. Suppress all sampling until a finer-grained solution can be // found. See bug 1295775. - AutoSuppressProfilerSampling suppressSampling(TlsContext.get()); + AutoSuppressProfilerSampling suppressSampling(rt->mainContextFromOwnThread()); ZoneList relocatedZones; Arena* relocatedArenas = nullptr; @@ -6711,8 +6714,9 @@ AllNurseriesAreEmpty(JSRuntime* rt) /* Start a new heap session. */ AutoTraceSession::AutoTraceSession(JSRuntime* rt, JS::HeapState heapState) : runtime(rt), - prevState(TlsContext.get()->heapState), - pseudoFrame(TlsContext.get(), HeapStateToLabel(heapState), ProfileEntry::Category::GC) + prevState(rt->mainContextFromOwnThread()->heapState), + pseudoFrame(rt->mainContextFromOwnThread(), HeapStateToLabel(heapState), + ProfileEntry::Category::GC) { MOZ_ASSERT(prevState == JS::HeapState::Idle); MOZ_ASSERT(heapState != JS::HeapState::Idle); @@ -6721,13 +6725,13 @@ AutoTraceSession::AutoTraceSession(JSRuntime* rt, JS::HeapState heapState) // Session always begins with lock held, see comment in class definition. maybeLock.emplace(rt); - TlsContext.get()->heapState = heapState; + rt->mainContextFromOwnThread()->heapState = heapState; } AutoTraceSession::~AutoTraceSession() { MOZ_ASSERT(JS::CurrentThreadIsHeapBusy()); - TlsContext.get()->heapState = prevState; + runtime->mainContextFromOwnThread()->heapState = prevState; } JS_PUBLIC_API(JS::HeapState) @@ -6736,20 +6740,6 @@ JS::CurrentThreadHeapState() return TlsContext.get()->heapState; } -bool -GCRuntime::canChangeActiveContext(JSContext* cx) -{ - // Threads cannot be in the middle of any operation that affects GC - // behavior when execution transfers to another thread for cooperative - // scheduling. - return cx->heapState == JS::HeapState::Idle - && !cx->suppressGC - && !cx->inUnsafeRegion - && !cx->generationalDisabled - && !cx->compactingDisabledCount - && !cx->keepAtoms; -} - GCRuntime::IncrementalResult GCRuntime::resetIncrementalGC(gc::AbortReason reason, AutoTraceSession& session) { @@ -7141,7 +7131,7 @@ GCRuntime::incrementalCollectSlice(SliceBudget& budget, JS::gcreason::Reason rea gc::AbortReason gc::IsIncrementalGCUnsafe(JSRuntime* rt) { - MOZ_ASSERT(!TlsContext.get()->suppressGC); + MOZ_ASSERT(!rt->mainContextFromOwnThread()->suppressGC); if (!rt->gc.isIncrementalGCAllowed()) return gc::AbortReason::IncrementalDisabled; @@ -7353,10 +7343,10 @@ GCRuntime::gcCycle(bool nonincrementalByAPI, SliceBudget& budget, JS::gcreason:: // It's ok if threads other than the active thread have suppressGC set, as // they are operating on zones which will not be collected from here. - MOZ_ASSERT(!TlsContext.get()->suppressGC); + MOZ_ASSERT(!rt->mainContextFromOwnThread()->suppressGC); // Assert if this is a GC unsafe region. - TlsContext.get()->verifyIsSafeToGC(); + rt->mainContextFromOwnThread()->verifyIsSafeToGC(); { gcstats::AutoPhase ap(stats(), gcstats::PhaseKind::WAIT_BACKGROUND_THREAD); @@ -7476,13 +7466,13 @@ GCRuntime::checkCanCallAPI() /* If we attempt to invoke the GC while we are running in the GC, assert. */ MOZ_RELEASE_ASSERT(!JS::CurrentThreadIsHeapBusy()); - MOZ_ASSERT(TlsContext.get()->isAllocAllowed()); + MOZ_ASSERT(rt->mainContextFromOwnThread()->isAllocAllowed()); } bool GCRuntime::checkIfGCAllowedInCurrentState(JS::gcreason::Reason reason) { - if (TlsContext.get()->suppressGC) + if (rt->mainContextFromOwnThread()->suppressGC) return false; // Only allow shutdown GCs when we're destroying the runtime. This keeps @@ -7609,7 +7599,7 @@ void GCRuntime::startGC(JSGCInvocationKind gckind, JS::gcreason::Reason reason, int64_t millis) { MOZ_ASSERT(!isIncrementalGCInProgress()); - if (!JS::IsIncrementalGCEnabled(TlsContext.get())) { + if (!JS::IsIncrementalGCEnabled(rt->mainContextFromOwnThread())) { gc(gckind, reason); return; } @@ -7649,7 +7639,7 @@ GCRuntime::abortGC() { MOZ_ASSERT(isIncrementalGCInProgress()); checkCanCallAPI(); - MOZ_ASSERT(!TlsContext.get()->suppressGC); + MOZ_ASSERT(!rt->mainContextFromOwnThread()->suppressGC); collect(false, SliceBudget::unlimited(), JS::gcreason::ABORT_GC); } @@ -7729,7 +7719,7 @@ GCRuntime::minorGC(JS::gcreason::Reason reason, gcstats::PhaseKind phase) { MOZ_ASSERT(!JS::CurrentThreadIsHeapBusy()); - if (TlsContext.get()->suppressGC) + if (rt->mainContextFromOwnThread()->suppressGC) return; gcstats::AutoPhase ap(rt->gc.stats(), phase); @@ -7775,7 +7765,7 @@ JS::AutoDisableGenerationalGC::~AutoDisableGenerationalGC() JS_PUBLIC_API(bool) JS::IsGenerationalGCEnabled(JSRuntime* rt) { - return !TlsContext.get()->generationalDisabled; + return !rt->mainContextFromOwnThread()->generationalDisabled; } bool @@ -7788,7 +7778,7 @@ GCRuntime::gcIfRequested() if (majorGCRequested()) { if (majorGCTriggerReason == JS::gcreason::DELAYED_ATOMS_GC && - !TlsContext.get()->canCollectAtoms()) + !rt->mainContextFromOwnThread()->canCollectAtoms()) { // A GC was requested to collect the atoms zone, but it's no longer // possible. Skip this collection. @@ -8108,7 +8098,7 @@ void GCRuntime::runDebugGC() { #ifdef JS_GC_ZEAL - if (TlsContext.get()->suppressGC) + if (rt->mainContextFromOwnThread()->suppressGC) return; if (hasZealMode(ZealMode::GenerationalGC)) diff --git a/js/src/gc/GCRuntime.h b/js/src/gc/GCRuntime.h index b9a95df4bd65..0efad69dec66 100644 --- a/js/src/gc/GCRuntime.h +++ b/js/src/gc/GCRuntime.h @@ -255,8 +255,6 @@ class GCRuntime void startDebugGC(JSGCInvocationKind gckind, SliceBudget& budget); void debugGCSlice(SliceBudget& budget); - bool canChangeActiveContext(JSContext* cx); - void triggerFullGCForAtoms(JSContext* cx); void runDebugGC(); diff --git a/js/src/gc/Nursery.cpp b/js/src/gc/Nursery.cpp index d803b7ba5d06..ce49d4f94188 100644 --- a/js/src/gc/Nursery.cpp +++ b/js/src/gc/Nursery.cpp @@ -690,21 +690,20 @@ IsFullStoreBufferReason(JS::gcreason::Reason reason) void js::Nursery::collect(JS::gcreason::Reason reason) { - MOZ_ASSERT(!TlsContext.get()->suppressGC); + JSRuntime* rt = runtime(); + MOZ_ASSERT(!rt->mainContextFromOwnThread()->suppressGC); if (!isEnabled() || isEmpty()) { // Our barriers are not always exact, and there may be entries in the // storebuffer even when the nursery is disabled or empty. It's not safe // to keep these entries as they may refer to tenured cells which may be // freed after this point. - runtime()->gc.storeBuffer().clear(); + rt->gc.storeBuffer().clear(); } if (!isEnabled()) return; - JSRuntime* rt = runtime(); - #ifdef JS_GC_ZEAL if (rt->gc.hasZealMode(ZealMode::CheckNursery)) { for (auto canary = lastCanary_; canary; canary = canary->next) @@ -750,7 +749,7 @@ js::Nursery::collect(JS::gcreason::Reason reason) IsFullStoreBufferReason(reason); if (shouldPretenure) { - JSContext* cx = TlsContext.get(); + JSContext* cx = rt->mainContextFromOwnThread(); for (auto& entry : tenureCounts.entries) { if (entry.count >= 3000) { ObjectGroup* group = entry.group; diff --git a/js/src/gc/Statistics.cpp b/js/src/gc/Statistics.cpp index 0567f8b05df2..57dbb00f2ba5 100644 --- a/js/src/gc/Statistics.cpp +++ b/js/src/gc/Statistics.cpp @@ -966,7 +966,7 @@ Statistics::beginNurseryCollection(JS::gcreason::Reason reason) count(STAT_MINOR_GC); startingMinorGCNumber = runtime->gc.minorGCCount(); if (nurseryCollectionCallback) { - (*nurseryCollectionCallback)(TlsContext.get(), + (*nurseryCollectionCallback)(runtime->mainContextFromOwnThread(), JS::GCNurseryProgress::GC_NURSERY_COLLECTION_START, reason); } @@ -976,7 +976,7 @@ void Statistics::endNurseryCollection(JS::gcreason::Reason reason) { if (nurseryCollectionCallback) { - (*nurseryCollectionCallback)(TlsContext.get(), + (*nurseryCollectionCallback)(runtime->mainContextFromOwnThread(), JS::GCNurseryProgress::GC_NURSERY_COLLECTION_END, reason); } @@ -1011,7 +1011,7 @@ Statistics::beginSlice(const ZoneGCStats& zoneStats, JSGCInvocationKind gckind, // Slice callbacks should only fire for the outermost level. bool wasFullGC = zoneStats.isFullCollection(); if (sliceCallback) { - JSContext* cx = TlsContext.get(); + JSContext* cx = runtime->mainContextFromOwnThread(); JS::GCDescription desc(!wasFullGC, false, gckind, reason); if (first) (*sliceCallback)(cx, JS::GC_CYCLE_BEGIN, desc); @@ -1082,7 +1082,7 @@ Statistics::endSlice() if (!aborted) { bool wasFullGC = zoneStats.isFullCollection(); if (sliceCallback) { - JSContext* cx = TlsContext.get(); + JSContext* cx = runtime->mainContextFromOwnThread(); JS::GCDescription desc(!wasFullGC, last, gckind, slices_.back().reason); (*sliceCallback)(cx, JS::GC_SLICE_END, desc); if (last) diff --git a/js/src/gc/Verifier.cpp b/js/src/gc/Verifier.cpp index e6614d4f8c9a..2b1c021ffee0 100644 --- a/js/src/gc/Verifier.cpp +++ b/js/src/gc/Verifier.cpp @@ -101,7 +101,7 @@ class js::VerifyPreTracer final : public JS::CallbackTracer NodeMap nodemap; explicit VerifyPreTracer(JSRuntime* rt) - : JS::CallbackTracer(rt), noggc(TlsContext.get()), number(rt->gc.gcNumber()), + : JS::CallbackTracer(rt), noggc(rt->mainContextFromOwnThread()), number(rt->gc.gcNumber()), count(0), curnode(nullptr), root(nullptr), edgeptr(nullptr), term(nullptr) {} @@ -180,7 +180,7 @@ gc::GCRuntime::startVerifyPreBarriers() return; if (IsIncrementalGCUnsafe(rt) != AbortReason::None || - TlsContext.get()->keepAtoms || + rt->mainContextFromOwnThread()->keepAtoms || rt->hasHelperThreadZones()) { return; @@ -192,7 +192,7 @@ gc::GCRuntime::startVerifyPreBarriers() if (!trc) return; - JSContext* cx = TlsContext.get(); + JSContext* cx = rt->mainContextFromOwnThread(); AutoPrepareForTracing prep(cx); { @@ -357,7 +357,7 @@ gc::GCRuntime::endVerifyPreBarriers() if (!compartmentCreated && IsIncrementalGCUnsafe(rt) == AbortReason::None && - !TlsContext.get()->keepAtoms && + !rt->mainContextFromOwnThread()->keepAtoms && !rt->hasHelperThreadZones()) { CheckEdgeTracer cetrc(rt); @@ -418,7 +418,7 @@ gc::GCRuntime::maybeVerifyPreBarriers(bool always) if (!hasZealMode(ZealMode::VerifierPre)) return; - if (TlsContext.get()->suppressGC) + if (rt->mainContextFromOwnThread()->suppressGC) return; if (verifyPreData) { diff --git a/js/src/gc/Zone.cpp b/js/src/gc/Zone.cpp index 231728d589f8..c1bc274ef98c 100644 --- a/js/src/gc/Zone.cpp +++ b/js/src/gc/Zone.cpp @@ -313,9 +313,11 @@ Zone::canCollect() void Zone::notifyObservingDebuggers() { + JSRuntime* rt = runtimeFromActiveCooperatingThread(); + JSContext* cx = rt->mainContextFromOwnThread(); + for (CompartmentsInZoneIter comps(this); !comps.done(); comps.next()) { - JSRuntime* rt = runtimeFromAnyThread(); - RootedGlobalObject global(TlsContext.get(), comps->unsafeUnbarrieredMaybeGlobal()); + RootedGlobalObject global(cx, comps->unsafeUnbarrieredMaybeGlobal()); if (!global) continue; diff --git a/js/src/irregexp/RegExpStack.cpp b/js/src/irregexp/RegExpStack.cpp index f910c2fe7909..d2d2ce7aac4d 100644 --- a/js/src/irregexp/RegExpStack.cpp +++ b/js/src/irregexp/RegExpStack.cpp @@ -48,7 +48,7 @@ bool irregexp::GrowBacktrackStack(JSRuntime* rt) { AutoUnsafeCallWithABI unsafe; - return TlsContext.get()->regexpStack.ref().grow(); + return rt->mainContextFromOwnThread()->regexpStack.ref().grow(); } RegExpStack::RegExpStack() diff --git a/js/src/jit/JitFrames.cpp b/js/src/jit/JitFrames.cpp index 42ea774448c9..e31d4fa4c5cb 100644 --- a/js/src/jit/JitFrames.cpp +++ b/js/src/jit/JitFrames.cpp @@ -1311,7 +1311,7 @@ void UpdateJitActivationsForMinorGC(JSRuntime* rt) { MOZ_ASSERT(JS::CurrentThreadIsHeapMinorCollecting()); - JSContext* cx = TlsContext.get(); + JSContext* cx = rt->mainContextFromOwnThread(); for (JitActivationIterator activations(cx); !activations.done(); ++activations) { for (OnlyJSJitFrameIter iter(activations); !iter.done(); ++iter) { if (iter.frame().type() == JitFrame_IonJS) diff --git a/js/src/jit/JitcodeMap.cpp b/js/src/jit/JitcodeMap.cpp index cc463f1cc73c..b72354f6dbe0 100644 --- a/js/src/jit/JitcodeMap.cpp +++ b/js/src/jit/JitcodeMap.cpp @@ -742,7 +742,8 @@ JitcodeGlobalTable::traceForMinorGC(JSTracer* trc) MOZ_ASSERT(trc->runtime()->geckoProfiler().enabled()); MOZ_ASSERT(JS::CurrentThreadIsHeapMinorCollecting()); - AutoSuppressProfilerSampling suppressSampling(TlsContext.get()); + JSContext* cx = trc->runtime()->mainContextFromOwnThread(); + AutoSuppressProfilerSampling suppressSampling(cx); JitcodeGlobalEntry::IonEntry* entry = nurseryEntries_; while (entry) { entry->trace(trc); @@ -830,7 +831,7 @@ JitcodeGlobalTable::markIteratively(GCMarker* marker) void JitcodeGlobalTable::sweep(JSRuntime* rt) { - AutoSuppressProfilerSampling suppressSampling(TlsContext.get()); + AutoSuppressProfilerSampling suppressSampling(rt->mainContextFromOwnThread()); for (Enum e(*this, rt); !e.empty(); e.popFront()) { JitcodeGlobalEntry* entry = e.front(); diff --git a/js/src/jsapi.cpp b/js/src/jsapi.cpp index a24219f8a937..db1b8f7b57ee 100644 --- a/js/src/jsapi.cpp +++ b/js/src/jsapi.cpp @@ -459,16 +459,6 @@ JS_GetBoundFunctionTarget(JSFunction* fun) /************************************************************************/ -#ifdef DEBUG -JS_FRIEND_API(bool) -JS::isGCEnabled() -{ - return !TlsContext.get()->suppressGC; -} -#else -JS_FRIEND_API(bool) JS::isGCEnabled() { return true; } -#endif - JS_PUBLIC_API(JSContext*) JS_NewContext(uint32_t maxbytes, uint32_t maxNurseryBytes, JSRuntime* parentRuntime) { diff --git a/js/src/vm/Runtime.cpp b/js/src/vm/Runtime.cpp index fddfbd161b52..0c30f90d9944 100644 --- a/js/src/vm/Runtime.cpp +++ b/js/src/vm/Runtime.cpp @@ -281,7 +281,7 @@ JSRuntime::destroyRuntime() * Finish any in-progress GCs first. This ensures the parseWaitingOnGC * list is empty in CancelOffThreadParses. */ - JSContext* cx = TlsContext.get(); + JSContext* cx = mainContextFromOwnThread(); if (JS::IsIncrementalGCInProgress(cx)) FinishGC(cx); @@ -804,7 +804,7 @@ JSRuntime::clearUsedByHelperThread(Zone* zone) MOZ_ASSERT(zone->group()->usedByHelperThread()); zone->group()->clearUsedByHelperThread(); numActiveHelperThreadZones--; - JSContext* cx = TlsContext.get(); + JSContext* cx = mainContextFromOwnThread(); if (gc.fullGCForAtomsRequested() && cx->canCollectAtoms()) gc.triggerFullGCForAtoms(cx); }