Changeset 223159 in webkit


Ignore:
Timestamp:
Oct 10, 2017 5:09:20 PM (7 years ago)
Author:
rmorisset@apple.com
Message:

Avoid allocating useless landingBlocks in DFGByteCodeParser::handleInlining()
https://bugs.webkit.org/show_bug.cgi?id=177926

Reviewed by Saam Barati.

When doing polyvariant inlining, there used to be a landing block for each callee, each of which was then linked to a continuation block.
With this change, we allocate the continuation block first, and pass it to the inlining routine so that op_ret in the callee link directly to it.
The only subtlety is that when inlining an intrinsic we must do the jump by hand, and also remember to call processSetLocalQueue with nextOffset before it.

  • dfg/DFGByteCodeParser.cpp:

(JSC::DFG::ByteCodeParser::inlineCall):
(JSC::DFG::ByteCodeParser::attemptToInlineCall):
(JSC::DFG::ByteCodeParser::handleInlining):
(JSC::DFG::ByteCodeParser::InlineStackEntry::InlineStackEntry):
(JSC::DFG::ByteCodeParser::parse):

Location:
trunk/Source/JavaScriptCore
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/ChangeLog

    r223155 r223159  
     12017-10-10  Robin Morisset  <rmorisset@apple.com>
     2
     3        Avoid allocating useless landingBlocks in DFGByteCodeParser::handleInlining()
     4        https://bugs.webkit.org/show_bug.cgi?id=177926
     5
     6        Reviewed by Saam Barati.
     7
     8        When doing polyvariant inlining, there used to be a landing block for each callee, each of which was then linked to a continuation block.
     9        With this change, we allocate the continuation block first, and pass it to the inlining routine so that op_ret in the callee link directly to it.
     10        The only subtlety is that when inlining an intrinsic we must do the jump by hand, and also remember to call processSetLocalQueue with nextOffset before it.
     11
     12        * dfg/DFGByteCodeParser.cpp:
     13        (JSC::DFG::ByteCodeParser::inlineCall):
     14        (JSC::DFG::ByteCodeParser::attemptToInlineCall):
     15        (JSC::DFG::ByteCodeParser::handleInlining):
     16        (JSC::DFG::ByteCodeParser::InlineStackEntry::InlineStackEntry):
     17        (JSC::DFG::ByteCodeParser::parse):
     18
    1192017-10-10  Guillaume Emont  <guijemont@igalia.com>
    220
  • trunk/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp

    r223112 r223159  
    229229    bool handleInlining(Node* callTargetNode, int resultOperand, const CallLinkStatus&, int registerOffset, VirtualRegister thisArgument, VirtualRegister argumentsArgument, unsigned argumentsOffset, int argumentCountIncludingThis, unsigned nextOffset, NodeType callOp, InlineCallFrame::Kind, SpeculatedType prediction);
    230230    template<typename ChecksFunctor>
    231     bool attemptToInlineCall(Node* callTargetNode, int resultOperand, CallVariant, int registerOffset, int argumentCountIncludingThis, unsigned nextOffset, InlineCallFrame::Kind, SpeculatedType prediction, unsigned& inliningBalance, const ChecksFunctor& insertChecks);
     231    bool attemptToInlineCall(Node* callTargetNode, int resultOperand, CallVariant, int registerOffset, int argumentCountIncludingThis, unsigned nextOffset, InlineCallFrame::Kind, SpeculatedType prediction, unsigned& inliningBalance, BasicBlock* continuationBlock, const ChecksFunctor& insertChecks);
    232232    template<typename ChecksFunctor>
    233     void inlineCall(Node* callTargetNode, int resultOperand, CallVariant, int registerOffset, int argumentCountIncludingThis, unsigned nextOffset, InlineCallFrame::Kind, const ChecksFunctor& insertChecks);
     233    void inlineCall(Node* callTargetNode, int resultOperand, CallVariant, int registerOffset, int argumentCountIncludingThis, unsigned nextOffset, InlineCallFrame::Kind, BasicBlock* continuationBlock, const ChecksFunctor& insertChecks);
    234234    void cancelLinkingForBlock(InlineStackEntry*, BasicBlock*); // Only works when the given block is the last one to have been added for that inline stack entry.
    235235    // Handle intrinsic functions. Return true if it succeeded, false if we need to plant a call.
     
    11581158            VirtualRegister inlineCallFrameStart,
    11591159            int argumentCountIncludingThis,
    1160             InlineCallFrame::Kind);
     1160            InlineCallFrame::Kind,
     1161            BasicBlock* continuationBlock);
    11611162       
    11621163        ~InlineStackEntry()
     
    15111512
    15121513template<typename ChecksFunctor>
    1513 void ByteCodeParser::inlineCall(Node* callTargetNode, int resultOperand, CallVariant callee, int registerOffset, int argumentCountIncludingThis, unsigned nextOffset, InlineCallFrame::Kind kind, const ChecksFunctor& insertChecks)
     1514void ByteCodeParser::inlineCall(Node* callTargetNode, int resultOperand, CallVariant callee, int registerOffset, int argumentCountIncludingThis, unsigned nextOffset, InlineCallFrame::Kind kind, BasicBlock* continuationBlock, const ChecksFunctor& insertChecks)
    15141515{
    15151516    CodeSpecializationKind specializationKind = InlineCallFrame::specializationKindFor(kind);
     
    16071608
    16081609    InlineStackEntry inlineStackEntry(this, codeBlock, codeBlock, callee.function(), resultReg,
    1609         (VirtualRegister)inlineCallFrameStart, argumentCountIncludingThis, kind);
     1610        (VirtualRegister)inlineCallFrameStart, argumentCountIncludingThis, kind, continuationBlock);
    16101611
    16111612    // This is where the actual inlining really happens.
     
    16591660
    16601661template<typename ChecksFunctor>
    1661 bool ByteCodeParser::attemptToInlineCall(Node* callTargetNode, int resultOperand, CallVariant callee, int registerOffset, int argumentCountIncludingThis, unsigned nextOffset, InlineCallFrame::Kind kind, SpeculatedType prediction, unsigned& inliningBalance, const ChecksFunctor& insertChecks)
     1662bool ByteCodeParser::attemptToInlineCall(Node* callTargetNode, int resultOperand, CallVariant callee, int registerOffset, int argumentCountIncludingThis, unsigned nextOffset, InlineCallFrame::Kind kind, SpeculatedType prediction, unsigned& inliningBalance, BasicBlock* continuationBlock, const ChecksFunctor& insertChecks)
    16621663{
    16631664    CodeSpecializationKind specializationKind = InlineCallFrame::specializationKindFor(kind);
     
    16821683            didInsertChecks = true;
    16831684        };
     1685
     1686        auto endSpecialCase = [&] () {
     1687            RELEASE_ASSERT(didInsertChecks);
     1688            addToGraph(Phantom, callTargetNode);
     1689            emitArgumentPhantoms(registerOffset, argumentCountIncludingThis);
     1690            inliningBalance--;
     1691            if (continuationBlock) {
     1692                m_currentIndex = nextOffset;
     1693                m_exitOK = true;
     1694                processSetLocalQueue();
     1695                addJumpTo(continuationBlock);
     1696            }
     1697        };
    16841698   
    16851699        if (InternalFunction* function = callee.internalFunction()) {
    16861700            if (handleConstantInternalFunction(callTargetNode, resultOperand, function, registerOffset, argumentCountIncludingThis, specializationKind, prediction, insertChecksWithAccounting)) {
    1687                 RELEASE_ASSERT(didInsertChecks);
    1688                 addToGraph(Phantom, callTargetNode);
    1689                 emitArgumentPhantoms(registerOffset, argumentCountIncludingThis);
    1690                 inliningBalance--;
     1701                endSpecialCase();
    16911702                return true;
    16921703            }
     
    16981709        if (intrinsic != NoIntrinsic) {
    16991710            if (handleIntrinsicCall(callTargetNode, resultOperand, intrinsic, registerOffset, argumentCountIncludingThis, prediction, insertChecksWithAccounting)) {
    1700                 RELEASE_ASSERT(didInsertChecks);
    1701                 addToGraph(Phantom, callTargetNode);
    1702                 emitArgumentPhantoms(registerOffset, argumentCountIncludingThis);
    1703                 inliningBalance--;
     1711                endSpecialCase();
    17041712                return true;
    17051713            }
     
    17121720            if (const DOMJIT::Signature* signature = callee.signatureFor(specializationKind)) {
    17131721                if (handleDOMJITCall(callTargetNode, resultOperand, signature, registerOffset, argumentCountIncludingThis, prediction, insertChecksWithAccounting)) {
    1714                     RELEASE_ASSERT(didInsertChecks);
    1715                     addToGraph(Phantom, callTargetNode);
    1716                     emitArgumentPhantoms(registerOffset, argumentCountIncludingThis);
    1717                     inliningBalance--;
     1722                    endSpecialCase();
    17181723                    return true;
    17191724                }
     
    17281733
    17291734    Instruction* savedCurrentInstruction = m_currentInstruction;
    1730     inlineCall(callTargetNode, resultOperand, callee, registerOffset, argumentCountIncludingThis, nextOffset, kind, insertChecks);
     1735    inlineCall(callTargetNode, resultOperand, callee, registerOffset, argumentCountIncludingThis, nextOffset, kind, continuationBlock, insertChecks);
    17311736    inliningBalance -= myInliningCost;
    17321737    m_currentInstruction = savedCurrentInstruction;
     
    17961801            callTargetNode, resultOperand, callLinkStatus[0], registerOffset,
    17971802            argumentCountIncludingThis, nextOffset, kind, prediction,
    1798             inliningBalance, [&] (CodeBlock* codeBlock) {
     1803            inliningBalance, nullptr, [&] (CodeBlock* codeBlock) {
    17991804                emitFunctionChecks(callLinkStatus[0], callTargetNode, thisArgument);
    18001805
     
    19401945    m_currentBlock->didLink();
    19411946   
    1942     // Each inlined callee will have a landing block that it returns at. They should all have jumps
    1943     // to the continuation block, which we create last.
    1944     Vector<BasicBlock*> landingBlocks;
     1947    BasicBlock* continuationBlock = allocateUntargetableBlock();
     1948    VERBOSE_LOG("Adding untargetable block ", RawPointer(continuationBlock), " (continuation)\n");
    19451949   
    19461950    // We may force this true if we give up on inlining any of the edges.
     
    19611965            myCallTargetNode, resultOperand, callLinkStatus[i], registerOffset,
    19621966            argumentCountIncludingThis, nextOffset, kind, prediction,
    1963             inliningBalance, [&] (CodeBlock*) { });
     1967            inliningBalance, continuationBlock, [&] (CodeBlock*) { });
    19641968       
    19651969        if (!inliningResult) {
     
    19841988        }
    19851989        data.cases.append(SwitchCase(m_graph.freeze(thingToCaseOn), calleeEntryBlock));
    1986         m_currentIndex = nextOffset;
    1987         m_exitOK = true;
    1988         processSetLocalQueue(); // This only comes into play for intrinsics, since normal inlined code will leave an empty queue.
    1989         if (Node* terminal = m_currentBlock->terminal())
    1990             ASSERT_UNUSED(terminal, terminal->op() == TailCall || terminal->op() == TailCallVarargs || terminal->op() == TailCallForwardVarargs);
    1991         else {
    1992             // FIXME: https://bugs.webkit.org/show_bug.cgi?id=177926 we can avoid this indirection in the case of normal inlined call
    1993             // by passing the continuation block all the way into inlineStackEntry->m_continuationBlock in inlineCall.
    1994             // It is not trivial because of the SetLocalQueue managed by intrinsics.
    1995             addToGraph(Jump);
    1996             landingBlocks.append(m_currentBlock);
    1997         }
    1998         VERBOSE_LOG("Marking ", RawPointer(m_currentBlock), " as linked (tail of poly inlinee)\n");
    1999         m_currentBlock->didLink();
    2000 
    20011990        VERBOSE_LOG("Finished inlining ", callLinkStatus[i], " at ", currentCodeOrigin(), ".\n");
    20021991    }
    2003    
    2004     BasicBlock* slowPathBlock = allocateUntargetableBlock();
     1992
     1993    // Slow path block
     1994    m_currentBlock = allocateUntargetableBlock();
    20051995    m_currentIndex = oldOffset;
    20061996    m_exitOK = true;
    2007     data.fallThrough = BranchTarget(slowPathBlock);
    2008     VERBOSE_LOG("Marking ", RawPointer(slowPathBlock), " as linked (slow path block)\n");
    2009     slowPathBlock->didLink();
     1997    data.fallThrough = BranchTarget(m_currentBlock);
    20101998    prepareToParseBlock();
    2011     m_currentBlock = slowPathBlock;
    20121999    Node* myCallTargetNode = getDirect(calleeReg);
    20132000    if (couldTakeSlowPath) {
     
    20222009       
    20232010        set(VirtualRegister(resultOperand), addToGraph(BottomValue));
    2024         VERBOSE_LOG("coultTakeSlowPath was wrong\n");
     2011        VERBOSE_LOG("couldTakeSlowPath was false\n");
    20252012    }
    20262013
     
    20282015    m_exitOK = true; // Origin changed, so it's fine to exit again.
    20292016    processSetLocalQueue();
     2017
    20302018    if (Node* terminal = m_currentBlock->terminal())
    20312019        ASSERT_UNUSED(terminal, terminal->op() == TailCall || terminal->op() == TailCallVarargs || terminal->op() == TailCallForwardVarargs);
    20322020    else {
    2033         addToGraph(Jump);
    2034         landingBlocks.append(m_currentBlock);
    2035     }
    2036 
    2037     // Continuation block
    2038     m_currentBlock = allocateUntargetableBlock();
    2039     VERBOSE_LOG("Adding untargetable block ", RawPointer(m_currentBlock), " (continuation)\n");
     2021        addJumpTo(continuationBlock);
     2022    }
     2023
    20402024    prepareToParseBlock();
    2041 
    2042     for (auto &landingBlock : landingBlocks) {
    2043         landingBlock->terminal()->targetBlock() = m_currentBlock;
    2044         landingBlock->didLink();
    2045         VERBOSE_LOG("We linked ", RawPointer(m_currentBlock), " (landing block) to the continuation block \n");
    2046     }
    20472025   
    20482026    m_currentIndex = oldOffset;
     2027    m_currentBlock = continuationBlock;
    20492028    m_exitOK = true;
    20502029   
     
    61526131    VirtualRegister inlineCallFrameStart,
    61536132    int argumentCountIncludingThis,
    6154     InlineCallFrame::Kind kind)
     6133    InlineCallFrame::Kind kind,
     6134    BasicBlock* continuationBlock)
    61556135    : m_byteCodeParser(byteCodeParser)
    61566136    , m_codeBlock(codeBlock)
    61576137    , m_profiledBlock(profiledBlock)
    6158     , m_continuationBlock(nullptr)
     6138    , m_continuationBlock(continuationBlock)
    61596139    , m_returnValue(returnValueVR)
    61606140    , m_caller(byteCodeParser->m_inlineStackTop)
     
    63616341    InlineStackEntry inlineStackEntry(
    63626342        this, m_codeBlock, m_profiledBlock, 0, VirtualRegister(), VirtualRegister(),
    6363         m_codeBlock->numParameters(), InlineCallFrame::Call);
     6343        m_codeBlock->numParameters(), InlineCallFrame::Call, nullptr);
    63646344   
    63656345    parseCodeBlock();
Note: See TracChangeset for help on using the changeset viewer.