Ignore:
Timestamp:
Apr 2, 2014, 4:50:25 PM (11 years ago)
Author:
[email protected]
Message:

CodeBlockSet should be generational
https://bugs.webkit.org/show_bug.cgi?id=127152

Reviewed by Geoffrey Garen.

During EdenCollections we now only visit those CodeBlocks that:
a) Are new since the last collection if they were somehow otherwise reachable.
b) Are reachable from an Executable that is part of the remembered set.

  • bytecode/CodeBlock.cpp:

(JSC::CodeBlock::CodeBlock): Initialize uninitialized variables.
(JSC::CodeBlock::visitAggregate): Move the addition of the weak reference harvester after the
shouldImmediatelyAssumeLivenessDuringScan check since it's redundant if we assume liveness.

  • bytecode/CodeBlock.h:

(JSC::CodeBlock::forEachRelatedCodeBlock): Executes a functor for each CodeBlock reachable from the current CodeBlock (including this).
We use this to clear marks for the CodeBlocks of remembered Executables (see: CodeBlockSet::clearMarksForEdenCollection).
(JSC::CodeBlockSet::mark): Also check the set of new CodeBlocks for memebership when doing conservative scanning.
(JSC::ScriptExecutable::forEachCodeBlock): Executes a functor for each of this Executable's CodeBlocks.

  • heap/CodeBlockSet.cpp:

(JSC::CodeBlockSet::~CodeBlockSet):
(JSC::CodeBlockSet::add):
(JSC::CodeBlockSet::promoteYoungCodeBlocks): Moves all CodeBlocks currently in the set of new CodeBlocks into
the set of old CodeBlocks.
(JSC::CodeBlockSet::clearMarksForFullCollection): Clears the marks for all CodeBlocks.
(JSC::CodeBlockSet::clearMarksForEdenCollection): Clears the marks for CodeBlocks owned by Executables in the
remembered set. When an Executable is added to the remembered set it's typically because we need to do something
with its CodeBlock.
(JSC::CodeBlockSet::clearMarks):
(JSC::CodeBlockSet::deleteUnmarkedAndUnreferenced): Fixpoints over either just the new CodeBlocks or all CodeBlocks
to determine which CodeBlocks are dead and eagerly finalizes/deletes them.
(JSC::CodeBlockSet::remove):
(JSC::CodeBlockSet::traceMarked): Iterate only the currently executing CodeBlocks instead of all CodeBlocks.
(JSC::CodeBlockSet::rememberCurrentlyExecutingCodeBlocks): Clear m_mayBeExecuting for all currently executing
CodeBlocks because we no longer always do this at the beginning of EdenCollections.

  • heap/CodeBlockSet.h:

(JSC::CodeBlockSet::iterate):

  • heap/Heap.cpp:

(JSC::Heap::markRoots):
(JSC::Heap::deleteAllCompiledCode):
(JSC::Heap::deleteUnmarkedCompiledCode):

  • runtime/Executable.cpp:

(JSC::ScriptExecutable::installCode): Write barrier code on installation. We do this due to the following situation:
a) A CodeBlock is created and is compiled on a DFG worker thread.
b) No GC happens.
c) The CodeBlock has finished being compiled and is installed in the Executable.
d) The function never executes before the next GC.
e) The next GC needs needs to visit the new CodeBlock but the Executable won't be revisited unless

it's added to the remembered set.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/bytecode/CodeBlock.h

    r166178 r166678  
    133133    PassRefPtr<CodeBlock> releaseAlternative() { return m_alternative.release(); }
    134134    void setAlternative(PassRefPtr<CodeBlock> alternative) { m_alternative = alternative; }
     135
     136    template <typename Functor> void forEachRelatedCodeBlock(Functor&& functor)
     137    {
     138        Functor f(std::forward<Functor>(functor));
     139        Vector<CodeBlock*, 4> codeBlocks;
     140        codeBlocks.append(this);
     141
     142        while (!codeBlocks.isEmpty()) {
     143            CodeBlock* currentCodeBlock = codeBlocks.takeLast();
     144            f(currentCodeBlock);
     145
     146            if (CodeBlock* alternative = currentCodeBlock->alternative())
     147                codeBlocks.append(alternative);
     148            if (CodeBlock* osrEntryBlock = currentCodeBlock->specialOSREntryBlockOrNull())
     149                codeBlocks.append(osrEntryBlock);
     150        }
     151    }
    135152   
    136153    CodeSpecializationKind specializationKind() const
     
    12761293    if (value + 1 <= 1)
    12771294        return;
    1278    
    1279     HashSet<CodeBlock*>::iterator iter = m_set.find(static_cast<CodeBlock*>(candidateCodeBlock));
    1280     if (iter == m_set.end())
     1295
     1296    CodeBlock* codeBlock = static_cast<CodeBlock*>(candidateCodeBlock);
     1297    if (!m_oldCodeBlocks.contains(codeBlock) && !m_newCodeBlocks.contains(codeBlock))
    12811298        return;
    1282    
    1283     mark(*iter);
     1299
     1300    mark(codeBlock);
    12841301}
    12851302
     
    12931310   
    12941311    codeBlock->m_mayBeExecuting = true;
     1312    // We might not have cleared the marks for this CodeBlock, but we need to visit it.
     1313    codeBlock->m_visitAggregateHasBeenCalled = false;
    12951314#if ENABLE(GGC)
    12961315    m_currentlyExecuting.append(codeBlock);
     
    12981317}
    12991318
     1319template <typename Functor> inline void ScriptExecutable::forEachCodeBlock(Functor&& functor)
     1320{
     1321    switch (type()) {
     1322    case ProgramExecutableType: {
     1323        jsCast<ProgramExecutable*>(this)->m_programCodeBlock->forEachRelatedCodeBlock(std::forward<Functor>(functor));
     1324        break;
     1325    }
     1326       
     1327    case EvalExecutableType: {
     1328        jsCast<EvalExecutable*>(this)->m_evalCodeBlock->forEachRelatedCodeBlock(std::forward<Functor>(functor));
     1329        break;
     1330    }
     1331       
     1332    case FunctionExecutableType: {
     1333        Functor f(std::forward<Functor>(functor));
     1334        FunctionExecutable* executable = jsCast<FunctionExecutable*>(this);
     1335        if (CodeBlock* codeBlock = executable->m_codeBlockForCall.get())
     1336            codeBlock->forEachRelatedCodeBlock(f);
     1337        if (CodeBlock* codeBlock = executable->m_codeBlockForConstruct.get())
     1338            codeBlock->forEachRelatedCodeBlock(f);
     1339        break;
     1340    }
     1341    default:
     1342        RELEASE_ASSERT_NOT_REACHED();
     1343    }
     1344}
     1345
    13001346} // namespace JSC
    13011347
Note: See TracChangeset for help on using the changeset viewer.