Ignore:
Timestamp:
Dec 13, 2011, 11:49:49 AM (13 years ago)
Author:
[email protected]
Message:

DFG should know exactly why recompilation was triggered
https://bugs.webkit.org/show_bug.cgi?id=74362

Reviewed by Oliver Hunt.

Each OSR exit is now individually counted, as well as counting the total number
of OSR exits that occurred in a code block. If recompilation is triggered, we
check to see if there are OSR exit sites that make up a sufficiently large
portion of the total OSR exits that occurred. For any such OSR exit sites, we
add a description of the site (bytecode index, kind) to a data structure in the
corresponding baseline CodeBlock. Then, when we recompile the code, we immediately
know which speculations would be unwise based on the fact that previous such
speculations proved to be fruitless.

This means 2% win on two of the SunSpider string tests, a 4% win on V8's deltablue,
and 5% on Kraken's imaging-darkroom. It is only a minor win in the averages, less
than 0.5%.

  • CMakeLists.txt:
  • GNUmakefile.list.am:
  • JavaScriptCore.xcodeproj/project.pbxproj:
  • Target.pri:
  • bytecode/CodeBlock.cpp:

(JSC::CodeBlock::tallyFrequentExitSites):

  • bytecode/CodeBlock.h:

(JSC::CodeBlock::addFrequentExitSite):
(JSC::CodeBlock::exitProfile):
(JSC::CodeBlock::reoptimize):
(JSC::CodeBlock::tallyFrequentExitSites):

  • bytecode/DFGExitProfile.cpp: Added.

(JSC::DFG::ExitProfile::ExitProfile):
(JSC::DFG::ExitProfile::~ExitProfile):
(JSC::DFG::ExitProfile::add):
(JSC::DFG::QueryableExitProfile::QueryableExitProfile):
(JSC::DFG::QueryableExitProfile::~QueryableExitProfile):

  • bytecode/DFGExitProfile.h: Added.

(JSC::DFG::exitKindToString):
(JSC::DFG::exitKindIsCountable):
(JSC::DFG::FrequentExitSite::FrequentExitSite):
(JSC::DFG::FrequentExitSite::operator!):
(JSC::DFG::FrequentExitSite::operator==):
(JSC::DFG::FrequentExitSite::hash):
(JSC::DFG::FrequentExitSite::bytecodeOffset):
(JSC::DFG::FrequentExitSite::kind):
(JSC::DFG::FrequentExitSite::isHashTableDeletedValue):
(JSC::DFG::FrequentExitSiteHash::hash):
(JSC::DFG::FrequentExitSiteHash::equal):
(JSC::DFG::QueryableExitProfile::hasExitSite):

  • dfg/DFGAssemblyHelpers.h:

(JSC::DFG::AssemblyHelpers::baselineCodeBlockForOriginAndBaselineCodeBlock):
(JSC::DFG::AssemblyHelpers::baselineCodeBlockFor):

  • dfg/DFGByteCodeParser.cpp:

(JSC::DFG::ByteCodeParser::makeSafe):
(JSC::DFG::ByteCodeParser::makeDivSafe):
(JSC::DFG::ByteCodeParser::handleCall):
(JSC::DFG::ByteCodeParser::handleIntrinsic):
(JSC::DFG::ByteCodeParser::parseBlock):
(JSC::DFG::ByteCodeParser::InlineStackEntry::InlineStackEntry):

  • dfg/DFGOSRExit.cpp:

(JSC::DFG::OSRExit::OSRExit):
(JSC::DFG::OSRExit::considerAddingAsFrequentExitSiteSlow):

  • dfg/DFGOSRExit.h:

(JSC::DFG::OSRExit::considerAddingAsFrequentExitSite):

  • dfg/DFGOSRExitCompiler.cpp:
  • dfg/DFGOSRExitCompiler32_64.cpp:

(JSC::DFG::OSRExitCompiler::compileExit):

  • dfg/DFGOSRExitCompiler64.cpp:

(JSC::DFG::OSRExitCompiler::compileExit):

  • dfg/DFGSpeculativeJIT.cpp:

(JSC::DFG::SpeculativeJIT::compilePeepHoleObjectEquality):
(JSC::DFG::SpeculativeJIT::checkArgumentTypes):
(JSC::DFG::SpeculativeJIT::compileGetCharCodeAt):
(JSC::DFG::SpeculativeJIT::compileGetByValOnString):
(JSC::DFG::SpeculativeJIT::compilePutByValForByteArray):
(JSC::DFG::SpeculativeJIT::compileGetByValOnByteArray):
(JSC::DFG::SpeculativeJIT::compileGetTypedArrayLength):
(JSC::DFG::SpeculativeJIT::compileGetByValOnIntTypedArray):
(JSC::DFG::SpeculativeJIT::compilePutByValForIntTypedArray):
(JSC::DFG::SpeculativeJIT::compileGetByValOnFloatTypedArray):
(JSC::DFG::SpeculativeJIT::compilePutByValForFloatTypedArray):
(JSC::DFG::SpeculativeJIT::compileInstanceOfForObject):
(JSC::DFG::SpeculativeJIT::compileSoftModulo):
(JSC::DFG::SpeculativeJIT::compileArithMul):
(JSC::DFG::SpeculativeJIT::compileGetIndexedPropertyStorage):

  • dfg/DFGSpeculativeJIT.h:

(JSC::DFG::SpeculativeJIT::speculationCheck):
(JSC::DFG::SpeculativeJIT::terminateSpeculativeExecution):

  • dfg/DFGSpeculativeJIT32_64.cpp:

(JSC::DFG::SpeculativeJIT::fillSpeculateIntInternal):
(JSC::DFG::SpeculativeJIT::fillSpeculateDouble):
(JSC::DFG::SpeculativeJIT::fillSpeculateCell):
(JSC::DFG::SpeculativeJIT::fillSpeculateBoolean):
(JSC::DFG::SpeculativeJIT::compileObjectEquality):
(JSC::DFG::SpeculativeJIT::compileObjectOrOtherLogicalNot):
(JSC::DFG::SpeculativeJIT::emitObjectOrOtherBranch):
(JSC::DFG::SpeculativeJIT::compile):

  • dfg/DFGSpeculativeJIT64.cpp:

(JSC::DFG::SpeculativeJIT::fillSpeculateIntInternal):
(JSC::DFG::SpeculativeJIT::fillSpeculateDouble):
(JSC::DFG::SpeculativeJIT::fillSpeculateCell):
(JSC::DFG::SpeculativeJIT::fillSpeculateBoolean):
(JSC::DFG::SpeculativeJIT::compileObjectEquality):
(JSC::DFG::SpeculativeJIT::compileObjectOrOtherLogicalNot):
(JSC::DFG::SpeculativeJIT::compileLogicalNot):
(JSC::DFG::SpeculativeJIT::emitObjectOrOtherBranch):
(JSC::DFG::SpeculativeJIT::emitBranch):
(JSC::DFG::SpeculativeJIT::compile):

  • runtime/Heuristics.cpp:

(JSC::Heuristics::initializeHeuristics):

  • runtime/Heuristics.h:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp

    r102545 r102694  
    632632    NodeIndex makeSafe(NodeIndex nodeIndex)
    633633    {
    634         if (!m_inlineStackTop->m_profiledBlock->likelyToTakeSlowCase(m_currentIndex))
     634        if (!m_inlineStackTop->m_profiledBlock->likelyToTakeSlowCase(m_currentIndex)
     635            && !m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, Overflow)
     636            && !m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, NegativeZero))
    635637            return nodeIndex;
    636638       
    637639#if DFG_ENABLE(DEBUG_VERBOSE)
    638         printf("Making %s @%u safe at bc#%u because slow-case counter is at %u\n", Graph::opName(m_graph[nodeIndex].op), nodeIndex, m_currentIndex, m_inlineStackTop->m_profiledBlock->rareCaseProfileForBytecodeOffset(m_currentIndex)->m_counter);
     640        printf("Making %s @%u safe at bc#%u because slow-case counter is at %u and exit profiles say %d, %d\n", Graph::opName(m_graph[nodeIndex].op), nodeIndex, m_currentIndex, m_inlineStackTop->m_profiledBlock->rareCaseProfileForBytecodeOffset(m_currentIndex)->m_counter, m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, Overflow), m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, NegativeZero));
    639641#endif
    640642       
     
    649651           
    650652        case ArithMul:
    651             if (m_inlineStackTop->m_profiledBlock->likelyToTakeDeepestSlowCase(m_currentIndex)) {
     653            if (m_inlineStackTop->m_profiledBlock->likelyToTakeDeepestSlowCase(m_currentIndex)
     654                || m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, Overflow)) {
    652655#if DFG_ENABLE(DEBUG_VERBOSE)
    653656                printf("Making ArithMul @%u take deepest slow case.\n", nodeIndex);
    654657#endif
    655658                m_graph[nodeIndex].mergeArithNodeFlags(NodeMayOverflow | NodeMayNegZero);
    656             } else {
     659            } else if (m_inlineStackTop->m_profiledBlock->likelyToTakeSlowCase(m_currentIndex)
     660                       || m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, NegativeZero)) {
    657661#if DFG_ENABLE(DEBUG_VERBOSE)
    658662                printf("Making ArithMul @%u take faster slow case.\n", nodeIndex);
     
    680684        // is what the special fast case counter tells us.
    681685       
    682         if (!m_inlineStackTop->m_profiledBlock->likelyToTakeSpecialFastCase(m_currentIndex))
     686        if (!m_inlineStackTop->m_profiledBlock->likelyToTakeSpecialFastCase(m_currentIndex)
     687            && !m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, Overflow)
     688            && !m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, NegativeZero))
    683689            return nodeIndex;
    684690       
    685691#if DFG_ENABLE(DEBUG_VERBOSE)
    686         printf("Making %s @%u safe at bc#%u because special fast-case counter is at %u\n", Graph::opName(m_graph[nodeIndex].op), nodeIndex, m_currentIndex, m_inlineStackTop->m_profiledBlock->specialFastCaseProfileForBytecodeOffset(m_currentIndex)->m_counter);
    687 #endif
    688        
     692        printf("Making %s @%u safe at bc#%u because special fast-case counter is at %u and exit profiles say %d, %d\n", Graph::opName(m_graph[nodeIndex].op), nodeIndex, m_currentIndex, m_inlineStackTop->m_profiledBlock->specialFastCaseProfileForBytecodeOffset(m_currentIndex)->m_counter, m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, Overflow), m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, NegativeZero));
     693#endif
     694       
     695        // FIXME: It might be possible to make this more granular. The DFG certainly can
     696        // distinguish between negative zero and overflow in its exit profiles.
    689697        m_graph[nodeIndex].mergeArithNodeFlags(NodeMayOverflow | NodeMayNegZero);
    690698       
     
    794802        ScriptExecutable* executable() { return m_codeBlock->ownerExecutable(); }
    795803       
     804        QueryableExitProfile m_exitProfile;
     805       
    796806        // Remapping of identifier and constant numbers from the code block being
    797807        // inlined (inline callee) to the code block that we're inlining into
     
    888898           
    889899#if DFG_ENABLE(DEBUG_VERBOSE)
    890     printf("Slow case count for call at @%lu bc#%u: %u/%u.\n", m_graph.size(), m_currentIndex, m_inlineStackTop->m_profiledBlock->rareCaseProfileForBytecodeOffset(m_currentIndex)->m_counter, m_inlineStackTop->m_profiledBlock->executionEntryCount());
     900    printf("Slow case count for call at @%lu bc#%u: %u/%u; exit profile: %d.\n", m_graph.size(), m_currentIndex, m_inlineStackTop->m_profiledBlock->rareCaseProfileForBytecodeOffset(m_currentIndex)->m_counter, m_inlineStackTop->m_profiledBlock->executionEntryCount(), m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadCache));
    891901#endif
    892902           
    893903    if (m_graph.isFunctionConstant(m_codeBlock, callTarget))
    894904        callType = ConstantFunction;
    895     else if (!!m_inlineStackTop->m_profiledBlock->getCallLinkInfo(m_currentIndex).lastSeenCallee && !m_inlineStackTop->m_profiledBlock->couldTakeSlowCase(m_currentIndex))
     905    else if (!!m_inlineStackTop->m_profiledBlock->getCallLinkInfo(m_currentIndex).lastSeenCallee
     906             && !m_inlineStackTop->m_profiledBlock->couldTakeSlowCase(m_currentIndex)
     907             && !m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadCache))
    896908        callType = LinkedFunction;
    897909    else
     
    11681180            return false;
    11691181
    1170         set(resultOperand, addToGraph(ArithAbs, OpInfo(NodeUseBottom), getToNumber(registerOffset + argumentToOperand(1))));
     1182        NodeIndex nodeIndex = addToGraph(ArithAbs, OpInfo(NodeUseBottom), getToNumber(registerOffset + argumentToOperand(1)));
     1183        if (m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, Overflow))
     1184            m_graph[nodeIndex].mergeArithNodeFlags(NodeMayOverflow);
     1185        set(resultOperand, nodeIndex);
    11711186        return true;
    11721187    }
     
    16691684            MethodCallLinkInfo& methodCall = m_inlineStackTop->m_profiledBlock->getMethodCallLinkInfo(m_currentIndex);
    16701685           
    1671             if (methodCall.seen && !!methodCall.cachedStructure && !stubInfo.seen) {
     1686            if (methodCall.seen
     1687                && !!methodCall.cachedStructure
     1688                && !stubInfo.seen
     1689                && !m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadCache)) {
    16721690                // It's monomorphic as far as we can tell, since the method_check was linked
    16731691                // but the slow path (i.e. the normal get_by_id) never fired.
     
    17121730           
    17131731#if DFG_ENABLE(DEBUG_VERBOSE)
    1714             printf("Slow case count for GetById @%lu bc#%u: %u\n", m_graph.size(), m_currentIndex, m_inlineStackTop->m_profiledBlock->rareCaseProfileForBytecodeOffset(m_currentIndex)->m_counter);
     1732            printf("Slow case count for GetById @%lu bc#%u: %u; exit profile: %d\n", m_graph.size(), m_currentIndex, m_inlineStackTop->m_profiledBlock->rareCaseProfileForBytecodeOffset(m_currentIndex)->m_counter, m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadCache));
    17151733#endif
    17161734           
    17171735            size_t offset = notFound;
    17181736            StructureSet structureSet;
    1719             if (stubInfo.seen && !m_inlineStackTop->m_profiledBlock->likelyToTakeSlowCase(m_currentIndex)) {
     1737            if (stubInfo.seen
     1738                && !m_inlineStackTop->m_profiledBlock->likelyToTakeSlowCase(m_currentIndex)
     1739                && !m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadCache)) {
    17201740                switch (stubInfo.accessType) {
    17211741                case access_get_by_id_self: {
     
    18061826           
    18071827#if DFG_ENABLE(DEBUG_VERBOSE)
    1808             printf("Slow case count for PutById @%lu bc#%u: %u\n", m_graph.size(), m_currentIndex, m_inlineStackTop->m_profiledBlock->rareCaseProfileForBytecodeOffset(m_currentIndex)->m_counter);
     1828            printf("Slow case count for PutById @%lu bc#%u: %u; exit profile: %d\n", m_graph.size(), m_currentIndex, m_inlineStackTop->m_profiledBlock->rareCaseProfileForBytecodeOffset(m_currentIndex)->m_counter, m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadCache));
    18091829#endif           
    18101830
    1811             if (stubInfo.seen && !m_inlineStackTop->m_profiledBlock->likelyToTakeSlowCase(m_currentIndex)) {
     1831            if (stubInfo.seen
     1832                && !m_inlineStackTop->m_profiledBlock->likelyToTakeSlowCase(m_currentIndex)
     1833                && !m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadCache)) {
    18121834                switch (stubInfo.accessType) {
    18131835                case access_put_by_id_replace: {
     
    24262448    , m_profiledBlock(profiledBlock)
    24272449    , m_calleeVR(calleeVR)
     2450    , m_exitProfile(profiledBlock->exitProfile())
    24282451    , m_callsiteBlockHead(callsiteBlockHead)
    24292452    , m_returnValue(returnValueVR)
Note: See TracChangeset for help on using the changeset viewer.