Ignore:
Timestamp:
Feb 2, 2015, 10:38:08 AM (10 years ago)
Author:
[email protected]
Message:

Polymorphic call inlining should be based on polymorphic call inline caching rather than logging
https://bugs.webkit.org/show_bug.cgi?id=140660

Reviewed by Geoffrey Garen.

When we first implemented polymorphic call inlining, we did the profiling based on a call
edge log. The idea was to store each call edge (a tuple of call site and callee) into a
global log that was processed lazily. Processing the log would give precise counts of call
edges, and could be used to drive well-informed inlining decisions - polymorphic or not.
This was a speed-up on throughput tests but a slow-down for latency tests. It was a net win
nonetheless.

Experience with this code shows three things. First, the call edge profiler is buggy and
complex. It would take work to fix the bugs. Second, the call edge profiler incurs lots of
overhead for latency code that we care deeply about. Third, it's not at all clear that
having call edge counts for every possible callee is any better than just having call edge
counts for the limited number of callees that an inline cache would catch.

So, this patch removes the call edge profiler and replaces it with a polymorphic call inline
cache. If we miss the basic call inline cache, we inflate the cache to be a jump to an
out-of-line stub that cases on the previously known callees. If that misses again, then we
rewrite that stub to include the new callee. We do this up to some number of callees. If we
hit the limit then we switch to using a plain virtual call.

Substantial speed-up on V8Spider; undoes the slow-down that the original call edge profiler
caused. Might be a SunSpider speed-up (below 1%), depending on hardware.

Rolling this back in after fixing https://bugs.webkit.org/show_bug.cgi?id=141107.

(JSC::CallEdge::count):
(JSC::CallEdge::CallEdge):

  • bytecode/CallEdgeProfile.cpp: Removed.
  • bytecode/CallEdgeProfile.h: Removed.
  • bytecode/CallEdgeProfileInlines.h: Removed.
  • bytecode/CallLinkInfo.cpp:

(JSC::CallLinkInfo::unlink):
(JSC::CallLinkInfo::visitWeak):

  • bytecode/CallLinkInfo.h:
  • bytecode/CallLinkStatus.cpp:

(JSC::CallLinkStatus::CallLinkStatus):
(JSC::CallLinkStatus::computeFor):
(JSC::CallLinkStatus::computeFromCallLinkInfo):
(JSC::CallLinkStatus::isClosureCall):
(JSC::CallLinkStatus::makeClosureCall):
(JSC::CallLinkStatus::dump):
(JSC::CallLinkStatus::computeFromCallEdgeProfile): Deleted.

  • bytecode/CallLinkStatus.h:

(JSC::CallLinkStatus::CallLinkStatus):
(JSC::CallLinkStatus::isSet):
(JSC::CallLinkStatus::variants):
(JSC::CallLinkStatus::size):
(JSC::CallLinkStatus::at):
(JSC::CallLinkStatus::operator[]):
(JSC::CallLinkStatus::canOptimize):
(JSC::CallLinkStatus::edges): Deleted.
(JSC::CallLinkStatus::canTrustCounts): Deleted.

  • bytecode/CallVariant.cpp:

(JSC::variantListWithVariant):
(JSC::despecifiedVariantList):

  • bytecode/CallVariant.h:
  • bytecode/CodeBlock.cpp:

(JSC::CodeBlock::~CodeBlock):
(JSC::CodeBlock::linkIncomingPolymorphicCall):
(JSC::CodeBlock::unlinkIncomingCalls):
(JSC::CodeBlock::noticeIncomingCall):

  • bytecode/CodeBlock.h:

(JSC::CodeBlock::isIncomingCallAlreadyLinked): Deleted.

  • dfg/DFGAbstractInterpreterInlines.h:

(JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects):

  • dfg/DFGByteCodeParser.cpp:

(JSC::DFG::ByteCodeParser::addCallWithoutSettingResult):
(JSC::DFG::ByteCodeParser::handleCall):
(JSC::DFG::ByteCodeParser::handleInlining):

  • dfg/DFGClobberize.h:

(JSC::DFG::clobberize):

  • dfg/DFGConstantFoldingPhase.cpp:

(JSC::DFG::ConstantFoldingPhase::foldConstants):

  • dfg/DFGDoesGC.cpp:

(JSC::DFG::doesGC):

  • dfg/DFGDriver.cpp:

(JSC::DFG::compileImpl):

  • dfg/DFGFixupPhase.cpp:

(JSC::DFG::FixupPhase::fixupNode):

  • dfg/DFGNode.h:

(JSC::DFG::Node::hasHeapPrediction):

  • dfg/DFGNodeType.h:
  • dfg/DFGOperations.cpp:
  • dfg/DFGPredictionPropagationPhase.cpp:

(JSC::DFG::PredictionPropagationPhase::propagate):

  • dfg/DFGSafeToExecute.h:

(JSC::DFG::safeToExecute):

  • dfg/DFGSpeculativeJIT32_64.cpp:

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

  • dfg/DFGSpeculativeJIT64.cpp:

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

  • dfg/DFGTierUpCheckInjectionPhase.cpp:

(JSC::DFG::TierUpCheckInjectionPhase::run):
(JSC::DFG::TierUpCheckInjectionPhase::removeFTLProfiling): Deleted.

  • ftl/FTLCapabilities.cpp:

(JSC::FTL::canCompile):

  • heap/Heap.cpp:

(JSC::Heap::collect):

  • jit/BinarySwitch.h:
  • jit/ClosureCallStubRoutine.cpp: Removed.
  • jit/ClosureCallStubRoutine.h: Removed.
  • jit/JITCall.cpp:

(JSC::JIT::compileOpCall):

  • jit/JITCall32_64.cpp:

(JSC::JIT::compileOpCall):

  • jit/JITOperations.cpp:
  • jit/JITOperations.h:

(JSC::operationLinkPolymorphicCallFor):
(JSC::operationLinkClosureCallFor): Deleted.

  • jit/JITStubRoutine.h:
  • jit/JITWriteBarrier.h:
  • jit/PolymorphicCallStubRoutine.cpp: Added.

(JSC::PolymorphicCallNode::~PolymorphicCallNode):
(JSC::PolymorphicCallNode::unlink):
(JSC::PolymorphicCallCase::dump):
(JSC::PolymorphicCallStubRoutine::PolymorphicCallStubRoutine):
(JSC::PolymorphicCallStubRoutine::~PolymorphicCallStubRoutine):
(JSC::PolymorphicCallStubRoutine::variants):
(JSC::PolymorphicCallStubRoutine::edges):
(JSC::PolymorphicCallStubRoutine::visitWeak):
(JSC::PolymorphicCallStubRoutine::markRequiredObjectsInternal):

  • jit/PolymorphicCallStubRoutine.h: Added.

(JSC::PolymorphicCallNode::PolymorphicCallNode):
(JSC::PolymorphicCallCase::PolymorphicCallCase):
(JSC::PolymorphicCallCase::variant):
(JSC::PolymorphicCallCase::codeBlock):

  • jit/Repatch.cpp:

(JSC::linkSlowFor):
(JSC::linkFor):
(JSC::revertCall):
(JSC::unlinkFor):
(JSC::linkVirtualFor):
(JSC::linkPolymorphicCall):
(JSC::linkClosureCall): Deleted.

  • jit/Repatch.h:
  • jit/ThunkGenerators.cpp:

(JSC::linkPolymorphicCallForThunkGenerator):
(JSC::linkPolymorphicCallThunkGenerator):
(JSC::linkPolymorphicCallThatPreservesRegsThunkGenerator):
(JSC::linkClosureCallForThunkGenerator): Deleted.
(JSC::linkClosureCallThunkGenerator): Deleted.
(JSC::linkClosureCallThatPreservesRegsThunkGenerator): Deleted.

  • jit/ThunkGenerators.h:

(JSC::linkPolymorphicCallThunkGeneratorFor):
(JSC::linkClosureCallThunkGeneratorFor): Deleted.

  • llint/LLIntSlowPaths.cpp:

(JSC::LLInt::jitCompileAndSetHeuristics):

  • runtime/Options.h:
  • runtime/VM.cpp:

(JSC::VM::prepareToDiscardCode):
(JSC::VM::ensureCallEdgeLog): Deleted.

  • runtime/VM.h:
File:
1 edited

Legend:

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

    r179392 r179478  
    11/*
    2  * Copyright (C) 2008, 2009, 2010, 2012, 2013, 2014 Apple Inc. All rights reserved.
     2 * Copyright (C) 2008-2010, 2012-2015 Apple Inc. All rights reserved.
    33 * Copyright (C) 2008 Cameron Zwarich <[email protected]>
    44 *
     
    21752175    while (m_incomingCalls.begin() != m_incomingCalls.end())
    21762176        m_incomingCalls.begin()->remove();
     2177    while (m_incomingPolymorphicCalls.begin() != m_incomingPolymorphicCalls.end())
     2178        m_incomingPolymorphicCalls.begin()->remove();
    21772179   
    21782180    // Note that our outgoing calls will be removed from other CodeBlocks'
     
    30413043    m_incomingCalls.push(incoming);
    30423044}
     3045
     3046void CodeBlock::linkIncomingPolymorphicCall(ExecState* callerFrame, PolymorphicCallNode* incoming)
     3047{
     3048    noticeIncomingCall(callerFrame);
     3049    m_incomingPolymorphicCalls.push(incoming);
     3050}
    30433051#endif // ENABLE(JIT)
    30443052
     
    30483056        m_incomingLLIntCalls.begin()->unlink();
    30493057#if ENABLE(JIT)
    3050     if (m_incomingCalls.isEmpty())
     3058    if (m_incomingCalls.isEmpty() && m_incomingPolymorphicCalls.isEmpty())
    30513059        return;
    30523060    RepatchBuffer repatchBuffer(this);
    30533061    while (m_incomingCalls.begin() != m_incomingCalls.end())
    30543062        m_incomingCalls.begin()->unlink(repatchBuffer);
     3063    while (m_incomingPolymorphicCalls.begin() != m_incomingPolymorphicCalls.end())
     3064        m_incomingPolymorphicCalls.begin()->unlink(repatchBuffer);
    30553065#endif // ENABLE(JIT)
    30563066}
     
    32463256   
    32473257    if (Options::verboseCallLink())
    3248         dataLog("Noticing call link from ", *callerCodeBlock, " to ", *this, "\n");
    3249    
     3258        dataLog("Noticing call link from ", pointerDump(callerCodeBlock), " to ", *this, "\n");
     3259   
     3260#if ENABLE(DFG_JIT)
    32503261    if (!m_shouldAlwaysBeInlined)
    32513262        return;
    3252 
    3253 #if ENABLE(DFG_JIT)
     3263   
     3264    if (!callerCodeBlock) {
     3265        m_shouldAlwaysBeInlined = false;
     3266        if (Options::verboseCallLink())
     3267            dataLog("    Clearing SABI because caller is native.\n");
     3268        return;
     3269    }
     3270
    32543271    if (!hasBaselineJITProfiling())
    32553272        return;
     
    32793296    }
    32803297   
     3298    if (JITCode::isOptimizingJIT(callerCodeBlock->jitType())) {
     3299        m_shouldAlwaysBeInlined = false;
     3300        if (Options::verboseCallLink())
     3301            dataLog("    Clearing SABI bcause caller was already optimized.\n");
     3302        return;
     3303    }
     3304   
    32813305    if (callerCodeBlock->codeType() != FunctionCode) {
    32823306        // If the caller is either eval or global code, assume that that won't be
     
    32993323        return;
    33003324    }
    3301 
    3302     RELEASE_ASSERT(callerCodeBlock->m_capabilityLevelState != DFG::CapabilityLevelNotSet);
     3325   
     3326    if (callerCodeBlock->m_capabilityLevelState == DFG::CapabilityLevelNotSet) {
     3327        dataLog("In call from ", *callerCodeBlock, " ", callerFrame->codeOrigin(), " to ", *this, ": caller's DFG capability level is not set.\n");
     3328        CRASH();
     3329    }
    33033330   
    33043331    if (canCompile(callerCodeBlock->m_capabilityLevelState))
Note: See TracChangeset for help on using the changeset viewer.