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"); } } }
JS_DumpCompartmentPCCounts(JSContext *cx) { for (CellIter i(cx->zone(), gc::FINALIZE_SCRIPT); !i.done(); i.next()) { JSScript *script = i.get<JSScript>(); if (script->compartment() != cx->compartment()) continue; if (script->hasScriptCounts()) JS_DumpPCCounts(cx, script); } #if defined(JS_ION) for (unsigned thingKind = FINALIZE_OBJECT0; thingKind < FINALIZE_OBJECT_LIMIT; thingKind++) { for (CellIter i(cx->zone(), (AllocKind) thingKind); !i.done(); i.next()) { JSObject *obj = i.get<JSObject>(); if (obj->compartment() != cx->compartment()) continue; if (obj->is<AsmJSModuleObject>()) { AsmJSModule &module = obj->as<AsmJSModuleObject>().module(); Sprinter sprinter(cx); if (!sprinter.init()) return; fprintf(stdout, "--- Asm.js Module ---\n"); for (size_t i = 0; i < module.numFunctionCounts(); i++) { jit::IonScriptCounts *counts = module.functionCounts(i); DumpIonScriptCounts(&sprinter, counts); } fputs(sprinter.string(), stdout); fprintf(stdout, "--- END Asm.js Module ---\n"); } } } #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); }