void JSCompartment::sweep(FreeOp *fop, bool releaseTypes) { JS_ASSERT(!activeAnalysis); { gcstats::AutoPhase ap(rt->gcStats, gcstats::PHASE_SWEEP_DISCARD_CODE); discardJitCode(fop, !zone()->isPreservingCode()); } /* This function includes itself in PHASE_SWEEP_TABLES. */ sweepCrossCompartmentWrappers(); { gcstats::AutoPhase ap(rt->gcStats, gcstats::PHASE_SWEEP_TABLES); /* Remove dead references held weakly by the compartment. */ sweepBaseShapeTable(); sweepInitialShapeTable(); sweepNewTypeObjectTable(newTypeObjects); sweepNewTypeObjectTable(lazyTypeObjects); sweepBreakpoints(fop); sweepCallsiteClones(); if (global_ && IsObjectAboutToBeFinalized(global_.unsafeGet())) global_ = NULL; #ifdef JS_ION if (ionCompartment_) ionCompartment_->sweep(fop); #endif /* * JIT code increments activeUseCount for any RegExpShared used by jit * code for the lifetime of the JIT script. Thus, we must perform * sweeping after clearing jit code. */ regExps.sweep(rt); if (debugScopes) debugScopes->sweep(rt); /* Finalize unreachable (key,value) pairs in all weak maps. */ WeakMapBase::sweepCompartment(this); } if (!zone()->isPreservingCode()) { JS_ASSERT(!types.constrainedOutputs); gcstats::AutoPhase ap(rt->gcStats, gcstats::PHASE_DISCARD_ANALYSIS); /* * Clear the analysis pool, but don't release its data yet. While * sweeping types any live data will be allocated into the pool. */ LifoAlloc oldAlloc(typeLifoAlloc.defaultChunkSize()); oldAlloc.steal(&typeLifoAlloc); /* * Periodically release observed types for all scripts. This is safe to * do when there are no frames for the compartment on the stack. */ if (active) releaseTypes = false; /* * Sweep analysis information and everything depending on it from the * compartment, including all remaining mjit code if inference is * enabled in the compartment. */ if (types.inferenceEnabled) { gcstats::AutoPhase ap2(rt->gcStats, gcstats::PHASE_DISCARD_TI); for (CellIterUnderGC i(this, FINALIZE_SCRIPT); !i.done(); i.next()) { RawScript script = i.get<JSScript>(); if (script->types) { types::TypeScript::Sweep(fop, script); if (releaseTypes) { script->types->destroy(); script->types = NULL; } } } } { gcstats::AutoPhase ap2(rt->gcStats, gcstats::PHASE_SWEEP_TYPES); types.sweep(fop); } { gcstats::AutoPhase ap2(rt->gcStats, gcstats::PHASE_CLEAR_SCRIPT_ANALYSIS); for (CellIterUnderGC i(this, FINALIZE_SCRIPT); !i.done(); i.next()) { JSScript *script = i.get<JSScript>(); script->clearAnalysis(); script->clearPropertyReadTypes(); } } { gcstats::AutoPhase ap2(rt->gcStats, gcstats::PHASE_FREE_TI_ARENA); rt->freeLifoAlloc.transferFrom(&analysisLifoAlloc); rt->freeLifoAlloc.transferFrom(&oldAlloc); } } NativeIterator *ni = enumerators->next(); while (ni != enumerators) { JSObject *iterObj = ni->iterObj(); NativeIterator *next = ni->next(); if (gc::IsObjectAboutToBeFinalized(&iterObj)) ni->unlink(); ni = next; } active = false; }
void JSCompartment::sweep(FreeOp *fop, bool releaseTypes) { { gcstats::AutoPhase ap(rt->gcStats, gcstats::PHASE_SWEEP_DISCARD_CODE); discardJitCode(fop, !activeAnalysis && !gcPreserveCode); } /* This function includes itself in PHASE_SWEEP_TABLES. */ sweepCrossCompartmentWrappers(); { gcstats::AutoPhase ap(rt->gcStats, gcstats::PHASE_SWEEP_TABLES); /* Remove dead references held weakly by the compartment. */ sweepBaseShapeTable(); sweepInitialShapeTable(); sweepNewTypeObjectTable(newTypeObjects); sweepNewTypeObjectTable(lazyTypeObjects); if (emptyTypeObject && !IsTypeObjectMarked(emptyTypeObject.unsafeGet())) emptyTypeObject = NULL; sweepBreakpoints(fop); if (global_ && !IsObjectMarked(&global_)) global_ = NULL; #ifdef JS_ION if (ionCompartment_) ionCompartment_->sweep(fop); #endif /* JIT code can hold references on RegExpShared, so sweep regexps after clearing code. */ regExps.sweep(rt); } if (!activeAnalysis && !gcPreserveCode) { JS_ASSERT(!types.constrainedOutputs); gcstats::AutoPhase ap(rt->gcStats, gcstats::PHASE_DISCARD_ANALYSIS); /* * Clear the analysis pool, but don't release its data yet. While * sweeping types any live data will be allocated into the pool. */ LifoAlloc oldAlloc(typeLifoAlloc.defaultChunkSize()); oldAlloc.steal(&typeLifoAlloc); /* * Periodically release observed types for all scripts. This is safe to * do when there are no frames for the compartment on the stack. */ if (active) releaseTypes = false; /* * Sweep analysis information and everything depending on it from the * compartment, including all remaining mjit code if inference is * enabled in the compartment. */ if (types.inferenceEnabled) { gcstats::AutoPhase ap2(rt->gcStats, gcstats::PHASE_DISCARD_TI); for (CellIterUnderGC i(this, FINALIZE_SCRIPT); !i.done(); i.next()) { JSScript *script = i.get<JSScript>(); if (script->types) { types::TypeScript::Sweep(fop, script); if (releaseTypes) { script->types->destroy(); script->types = NULL; } } } } { gcstats::AutoPhase ap2(rt->gcStats, gcstats::PHASE_SWEEP_TYPES); types.sweep(fop); } { gcstats::AutoPhase ap2(rt->gcStats, gcstats::PHASE_CLEAR_SCRIPT_ANALYSIS); for (CellIterUnderGC i(this, FINALIZE_SCRIPT); !i.done(); i.next()) { JSScript *script = i.get<JSScript>(); script->clearAnalysis(); script->clearPropertyReadTypes(); } } { gcstats::AutoPhase ap2(rt->gcStats, gcstats::PHASE_FREE_TI_ARENA); rt->freeLifoAlloc.transferFrom(&analysisLifoAlloc); rt->freeLifoAlloc.transferFrom(&oldAlloc); } } active = false; }