Beispiel #1
0
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
}
Beispiel #4
0
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);
}