void JSCompartment::traceRoots(JSTracer* trc, js::gc::GCRuntime::TraceOrMarkRuntime traceOrMark) { if (objectMetadataState.is<PendingMetadata>()) { TraceRoot(trc, objectMetadataState.as<PendingMetadata>().unsafeGet(), "on-stack object pending metadata"); } if (!trc->runtime()->isHeapMinorCollecting()) { // JIT code and the global are never nursery allocated, so we only need // to trace them when not doing a minor collection. if (jitCompartment_) jitCompartment_->mark(trc, this); // If a compartment is on-stack, we mark its global so that // JSContext::global() remains valid. if (enterCompartmentDepth && global_.unbarrieredGet()) TraceRoot(trc, global_.unsafeGet(), "on-stack compartment global"); } // Nothing below here needs to be treated as a root if we aren't marking // this zone for a collection. if (traceOrMark == js::gc::GCRuntime::MarkRuntime && !zone()->isCollecting()) return; // During a GC, these are treated as weak pointers. if (traceOrMark == js::gc::GCRuntime::TraceRuntime) { if (watchpointMap) watchpointMap->markAll(trc); } /* Mark debug scopes, if present */ if (debugScopes) debugScopes->mark(trc); if (lazyArrayBuffers) lazyArrayBuffers->trace(trc); if (objectMetadataTable) objectMetadataTable->trace(trc); if (scriptCountsMap && !trc->runtime()->isHeapMinorCollecting()) { MOZ_ASSERT_IF(!trc->runtime()->isBeingDestroyed(), collectCoverage()); for (ScriptCountsMap::Range r = scriptCountsMap->all(); !r.empty(); r.popFront()) { JSScript* script = const_cast<JSScript*>(r.front().key()); MOZ_ASSERT(script->hasScriptCounts()); TraceRoot(trc, &script, "profilingScripts"); MOZ_ASSERT(script == r.front().key(), "const_cast is only a work-around"); } } }
void JSCompartment::clearScriptCounts() { if (!scriptCountsMap) return; // Clear all hasScriptCounts_ flags of JSScript, in order to release all // ScriptCounts entry of the current compartment. for (ScriptCountsMap::Range r = scriptCountsMap->all(); !r.empty(); r.popFront()) { ScriptCounts* value = &r.front().value(); r.front().key()->takeOverScriptCountsMapEntry(value); } js_delete(scriptCountsMap); scriptCountsMap = nullptr; }
void JSCompartment::fixupAfterMovingGC() { fixupGlobal(); fixupInitialShapeTable(); objectGroups.fixupTablesAfterMovingGC(); #ifdef DEBUG // Assert that none of the JSScript pointers, which are used as key of the // scriptCountsMap HashMap are moved. We do not mark these keys because we // need weak references. We do not use a WeakMap because these entries would // be collected before the JSScript::finalize calls which is used to // summarized the content of the code coverage. if (scriptCountsMap) { for (ScriptCountsMap::Range r = scriptCountsMap->all(); !r.empty(); r.popFront()) MOZ_ASSERT(!IsForwarded(r.front().key())); } #endif }
void JSCompartment::traceRoots(JSTracer* trc, js::gc::GCRuntime::TraceOrMarkRuntime traceOrMark) { if (objectMetadataState.is<PendingMetadata>()) { TraceRoot(trc, &objectMetadataState.as<PendingMetadata>(), "on-stack object pending metadata"); } if (!trc->runtime()->isHeapMinorCollecting()) { // JIT code and the global are never nursery allocated, so we only need // to trace them when not doing a minor collection. if (jitCompartment_) jitCompartment_->trace(trc, this); // If a compartment is on-stack, we mark its global so that // JSContext::global() remains valid. if (enterCompartmentDepth && global_.unbarrieredGet()) TraceRoot(trc, global_.unsafeUnbarrieredForTracing(), "on-stack compartment global"); } // Nothing below here needs to be treated as a root if we aren't marking // this zone for a collection. if (traceOrMark == js::gc::GCRuntime::MarkRuntime && !zone()->isCollecting()) return; // During a GC, these are treated as weak pointers. if (traceOrMark == js::gc::GCRuntime::TraceRuntime) { if (watchpointMap) watchpointMap->trace(trc); } /* Mark debug scopes, if present */ if (debugEnvs) debugEnvs->trace(trc); if (lazyArrayBuffers) lazyArrayBuffers->trace(trc); if (objectMetadataTable) objectMetadataTable->trace(trc); // If code coverage is only enabled with the Debugger or the LCovOutput, // then the following comment holds. // // The scriptCountsMap maps JSScript weak-pointers to ScriptCounts // structures. It uses a HashMap instead of a WeakMap, so that we can keep // the data alive for the JSScript::finalize call. Thus, we do not trace the // keys of the HashMap to avoid adding a strong reference to the JSScript // pointers. // // If the code coverage is either enabled with the --dump-bytecode command // line option, or with the PCCount JSFriend API functions, then we mark the // keys of the map to hold the JSScript alive. if (scriptCountsMap && trc->runtime()->profilingScripts && !trc->runtime()->isHeapMinorCollecting()) { MOZ_ASSERT_IF(!trc->runtime()->isBeingDestroyed(), collectCoverage()); for (ScriptCountsMap::Range r = scriptCountsMap->all(); !r.empty(); r.popFront()) { JSScript* script = const_cast<JSScript*>(r.front().key()); MOZ_ASSERT(script->hasScriptCounts()); TraceRoot(trc, &script, "profilingScripts"); MOZ_ASSERT(script == r.front().key(), "const_cast is only a work-around"); } } if (nonSyntacticLexicalEnvironments_) nonSyntacticLexicalEnvironments_->trace(trc); wasm.trace(trc); }