Ignore:
Timestamp:
Nov 10, 2011, 1:59:39 PM (14 years ago)
Author:
[email protected]
Message:

DFG should not reparse code that was just parsed
https://bugs.webkit.org/show_bug.cgi?id=71977

Reviewed by Geoff Garen.

The instruction stream of a code block is now kept around until
the next GC. When doing either an optimizing compilation of an
executable, or inlining of an executable, we now try to find the
already preexisting bytecode. If we find it, we don't have to parse.
If we don't find it, we parse as before. Inlining takes the extra
step of caching code blocks, so if the same executable gets inlined
multiple times into the same caller, then we parse it at most once
even if prior to inlining that executable did not have any code
blocks with an instruction stream.

Also fixed a silly bug where the strict mode for various operations
was being determined by looking at the machine code block rather
than the inlinee.

To enable the delete-on-next-GC policy, I introduced the notion
of an ultra weak finalizer, which anyone can register during
tracing. This is thread-safe (for parallel GC) and
stop-the-world-safe (so calls to free() are postponed until the
world is resumed). This required reusing some facilities previously
created for WeakReferenceHarvester, so I created a common utility
class. I also retweaked the handling of WeakReferenceHarvesters,
since they should be executed during stop-the-world since in the
future we may want to allow them to call drain().

2% win on SunSpider. 2% win on V8, when run in my harness. Neutral
elsewhere.

(JSC::CodeBlock::CodeBlock):
(JSC::CodeBlock::visitAggregate):
(JSC::CodeBlock::copyPostParseDataFrom):
(JSC::CodeBlock::copyPostParseDataFromAlternative):
(JSC::CodeBlock::finalizeUnconditionally):

  • bytecode/CodeBlock.h:

(JSC::CodeBlock::canProduceCopyWithBytecode):
(JSC::CodeBlock::discardBytecodeLater):
(JSC::CodeBlock::handleBytecodeDiscardingOpportunity):
(JSC::GlobalCodeBlock::GlobalCodeBlock):
(JSC::ProgramCodeBlock::ProgramCodeBlock):
(JSC::EvalCodeBlock::EvalCodeBlock):
(JSC::FunctionCodeBlock::FunctionCodeBlock):
(JSC::BytecodeDestructionBlocker::BytecodeDestructionBlocker):
(JSC::BytecodeDestructionBlocker::~BytecodeDestructionBlocker):

  • dfg/DFGAssemblyHelpers.h:

(JSC::DFG::AssemblyHelpers::strictModeFor):

  • dfg/DFGByteCodeCache.h: Added.

(JSC::DFG::CodeBlockKey::CodeBlockKey):
(JSC::DFG::CodeBlockKey::operator==):
(JSC::DFG::CodeBlockKey::hash):
(JSC::DFG::CodeBlockKey::executable):
(JSC::DFG::CodeBlockKey::kind):
(JSC::DFG::CodeBlockKey::isHashTableDeletedValue):
(JSC::DFG::CodeBlockKeyHash::hash):
(JSC::DFG::CodeBlockKeyHash::equal):
(JSC::DFG::ByteCodeCache::ByteCodeCache):
(JSC::DFG::ByteCodeCache::~ByteCodeCache):
(JSC::DFG::ByteCodeCache::get):

  • dfg/DFGByteCodeParser.cpp:

(JSC::DFG::ByteCodeParser::handleInlining):

  • dfg/DFGJITCodeGenerator32_64.cpp:

(JSC::DFG::JITCodeGenerator::cachedPutById):

  • dfg/DFGJITCodeGenerator64.cpp:

(JSC::DFG::JITCodeGenerator::cachedPutById):

  • dfg/DFGSpeculativeJIT64.cpp:

(JSC::DFG::SpeculativeJIT::compile):

  • heap/Heap.cpp:

(JSC::Heap::finalizeUnconditionally):
(JSC::Heap::markRoots):
(JSC::Heap::collect):

  • heap/Heap.h:
  • heap/ListableHandler.h: Added.

(JSC::ListableHandler::ListableHandler):
(JSC::ListableHandler::~ListableHandler):
(JSC::ListableHandler::List::List):
(JSC::ListableHandler::List::addNotThreadSafe):
(JSC::ListableHandler::List::addThreadSafe):
(JSC::ListableHandler::List::hasNext):
(JSC::ListableHandler::List::removeNext):

  • heap/MarkStack.cpp:

(JSC::MarkStackThreadSharedData::MarkStackThreadSharedData):
(JSC::SlotVisitor::harvestWeakReferences):
(JSC::SlotVisitor::finalizeUnconditionally):

  • heap/MarkStack.h:

(JSC::MarkStack::addWeakReferenceHarvester):
(JSC::MarkStack::addUnconditionalFinalizer):

  • heap/SlotVisitor.h:
  • heap/UnconditionalFinalizer.h: Added.

(JSC::UnconditionalFinalizer::~UnconditionalFinalizer):

  • heap/WeakReferenceHarvester.h:

(JSC::WeakReferenceHarvester::WeakReferenceHarvester):
(JSC::WeakReferenceHarvester::~WeakReferenceHarvester):

  • runtime/Executable.cpp:

(JSC::EvalExecutable::compileInternal):
(JSC::ProgramExecutable::compileInternal):
(JSC::FunctionExecutable::baselineCodeBlockFor):
(JSC::FunctionExecutable::codeBlockWithBytecodeFor):
(JSC::FunctionExecutable::produceCodeBlockFor):
(JSC::FunctionExecutable::compileForCallInternal):
(JSC::FunctionExecutable::compileForConstructInternal):

  • runtime/Executable.h:

(JSC::FunctionExecutable::profiledCodeBlockFor):

File:
1 edited

Legend:

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

    r99810 r99898  
    14081408}
    14091409
     1410CodeBlock::CodeBlock(CopyParsedBlockTag, CodeBlock& other, SymbolTable* symTab)
     1411    : m_globalObject(other.m_globalObject)
     1412    , m_heap(other.m_heap)
     1413    , m_numCalleeRegisters(other.m_numCalleeRegisters)
     1414    , m_numVars(other.m_numVars)
     1415    , m_numCapturedVars(other.m_numCapturedVars)
     1416    , m_numParameters(other.m_numParameters)
     1417    , m_isConstructor(other.m_isConstructor)
     1418    , m_shouldDiscardBytecode(false)
     1419    , m_ownerExecutable(*other.m_globalData, other.m_ownerExecutable.get(), other.m_ownerExecutable.get())
     1420    , m_globalData(other.m_globalData)
     1421    , m_instructions(other.m_instructions)
     1422    , m_instructionCount(other.m_instructionCount)
     1423    , m_thisRegister(other.m_thisRegister)
     1424    , m_argumentsRegister(other.m_argumentsRegister)
     1425    , m_activationRegister(other.m_activationRegister)
     1426    , m_needsFullScopeChain(other.m_needsFullScopeChain)
     1427    , m_usesEval(other.m_usesEval)
     1428    , m_isNumericCompareFunction(other.m_isNumericCompareFunction)
     1429    , m_isStrictMode(other.m_isStrictMode)
     1430    , m_codeType(other.m_codeType)
     1431    , m_source(other.m_source)
     1432    , m_sourceOffset(other.m_sourceOffset)
     1433    , m_globalResolveInfos(other.m_globalResolveInfos)
     1434    , m_jumpTargets(other.m_jumpTargets)
     1435    , m_loopTargets(other.m_loopTargets)
     1436    , m_identifiers(other.m_identifiers)
     1437    , m_constantRegisters(other.m_constantRegisters)
     1438    , m_functionDecls(other.m_functionDecls)
     1439    , m_functionExprs(other.m_functionExprs)
     1440    , m_symbolTable(symTab)
     1441    , m_speculativeSuccessCounter(0)
     1442    , m_speculativeFailCounter(0)
     1443    , m_optimizationDelayCounter(0)
     1444    , m_reoptimizationRetryCounter(0)
     1445{
     1446    optimizeAfterWarmUp();
     1447   
     1448    if (other.m_rareData) {
     1449        createRareDataIfNecessary();
     1450       
     1451        m_rareData->m_exceptionHandlers = other.m_rareData->m_exceptionHandlers;
     1452        m_rareData->m_regexps = other.m_rareData->m_regexps;
     1453        m_rareData->m_constantBuffers = other.m_rareData->m_constantBuffers;
     1454        m_rareData->m_immediateSwitchJumpTables = other.m_rareData->m_immediateSwitchJumpTables;
     1455        m_rareData->m_characterSwitchJumpTables = other.m_rareData->m_characterSwitchJumpTables;
     1456        m_rareData->m_stringSwitchJumpTables = other.m_rareData->m_stringSwitchJumpTables;
     1457        m_rareData->m_expressionInfo = other.m_rareData->m_expressionInfo;
     1458        m_rareData->m_lineInfo = other.m_rareData->m_lineInfo;
     1459    }
     1460}
     1461
    14101462CodeBlock::CodeBlock(ScriptExecutable* ownerExecutable, CodeType codeType, JSGlobalObject *globalObject, PassRefPtr<SourceProvider> sourceProvider, unsigned sourceOffset, SymbolTable* symTab, bool isConstructor, PassOwnPtr<CodeBlock> alternative)
    14111463    : m_globalObject(globalObject->globalData(), ownerExecutable, globalObject)
     
    14151467    , m_numParameters(0)
    14161468    , m_isConstructor(isConstructor)
     1469    , m_shouldDiscardBytecode(false)
    14171470    , m_ownerExecutable(globalObject->globalData(), ownerExecutable, ownerExecutable)
    14181471    , m_globalData(0)
     
    15961649        valueProfile(profileIndex)->computeUpdatedPrediction();
    15971650#endif
     1651   
     1652#if ENABLE(JIT) && !ENABLE(OPCODE_SAMPLING)
     1653    // Kill off some bytecode. We can't do it here because we don't want to accidentally
     1654    // call into malloc while in stop-the-world GC mode.
     1655    if (hasInstructions() && m_shouldDiscardBytecode)
     1656        visitor.addUnconditionalFinalizer(this);
     1657#endif
    15981658}
    15991659
     
    18221882}
    18231883
    1824 void CodeBlock::copyDataFrom(CodeBlock* alternative)
     1884void CodeBlock::copyPostParseDataFrom(CodeBlock* alternative)
    18251885{
    18261886    if (!alternative)
     
    18341894}
    18351895
    1836 void CodeBlock::copyDataFromAlternative()
    1837 {
    1838     copyDataFrom(m_alternative.get());
     1896void CodeBlock::copyPostParseDataFromAlternative()
     1897{
     1898    copyPostParseDataFrom(m_alternative.get());
    18391899}
    18401900
     
    19171977}
    19181978#endif
     1979
     1980void CodeBlock::finalizeUnconditionally()
     1981{
     1982#if ENABLE(OPCODE_SAMPLING) || !ENABLE(JIT)
     1983    ASSERT_NOT_REACHED();
     1984#endif
     1985    ASSERT(m_shouldDiscardBytecode);
     1986    discardBytecode();
     1987}
    19191988
    19201989#if ENABLE(VALUE_PROFILER)
Note: See TracChangeset for help on using the changeset viewer.