Changeset 244324 in webkit


Ignore:
Timestamp:
Apr 15, 2019 7:41:38 PM (5 years ago)
Author:
sbarati@apple.com
Message:

Modify how we do SetArgument when we inline varargs calls
https://bugs.webkit.org/show_bug.cgi?id=196712
<rdar://problem/49605012>

Reviewed by Michael Saboff.

JSTests:

  • stress/get-stack-wrong-type-when-inline-varargs.js: Added.

(foo):

Source/JavaScriptCore:

When we inline varargs calls, we guarantee that the number of arguments that
go on the stack are somewhere between the "mandatoryMinimum" and the "limit - 1".
However, we can't statically guarantee that the arguments between these two
ranges was filled out by Load/ForwardVarargs. This is because in the general
case we don't know the argument count statically.

However, we used to always emit SetArgumentDefinitely up to "limit - 1" for
all arguments, even when some arguments aren't guaranteed to be in a valid
state. Emitting these SetArgumentDefinitely were helpful because they let us
handle variable liveness and OSR exit metadata. However, when we converted
to SSA, we ended up emitting a GetStack for each such SetArgumentDefinitely.

This is wrong, as we can't guarantee such SetArgumentDefinitely nodes are
actually looking at a range of the stack that are guaranteed to be initialized.
This patch introduces a new form of SetArgument node: SetArgumentMaybe. In terms
of OSR exit metadata and variable liveness tracking, it behaves like SetArgumentDefinitely.

However, it differs in a couple key ways:

  1. In ThreadedCPS, GetLocal(@SetArgumentMaybe) is invalid IR, as this implies

you might be loading uninitialized stack. (This same rule applies when you do
the full data flow reachability analysis over CPS Phis.) If someone logically
wanted to emit code like this, the correct node to emit would be GetArgument,
not GetLocal. For similar reasons, PhantomLocal(@SetArgumentMaybe) is also
invalid IR.

  1. To track liveness, Flush(@SetArgumentMaybe) is valid, and is the main user

of SetArgumentMaybe.

  1. In SSA conversion, we don't lower SetArgumentMaybe to GetStack, as there

should be no data flow user of SetArgumentMaybe.

SetArgumentDefinitely guarantees that the stack slot is initialized.
SetArgumentMaybe makes no such guarantee.

  • dfg/DFGAbstractInterpreterInlines.h:

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

  • dfg/DFGByteCodeParser.cpp:

(JSC::DFG::ByteCodeParser::handleVarargsInlining):

  • dfg/DFGCPSRethreadingPhase.cpp:

(JSC::DFG::CPSRethreadingPhase::freeUnnecessaryNodes):
(JSC::DFG::CPSRethreadingPhase::canonicalizeGetLocalFor):
(JSC::DFG::CPSRethreadingPhase::canonicalizeFlushOrPhantomLocalFor):
(JSC::DFG::CPSRethreadingPhase::canonicalizeLocalsInBlock):
(JSC::DFG::CPSRethreadingPhase::propagatePhis):
(JSC::DFG::CPSRethreadingPhase::computeIsFlushed):

  • dfg/DFGClobberize.h:

(JSC::DFG::clobberize):

  • dfg/DFGCommon.h:
  • dfg/DFGDoesGC.cpp:

(JSC::DFG::doesGC):

  • dfg/DFGFixupPhase.cpp:

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

  • dfg/DFGInPlaceAbstractState.cpp:

(JSC::DFG::InPlaceAbstractState::endBasicBlock):

  • dfg/DFGLiveCatchVariablePreservationPhase.cpp:

(JSC::DFG::LiveCatchVariablePreservationPhase::handleBlockForTryCatch):

  • dfg/DFGMaximalFlushInsertionPhase.cpp:

(JSC::DFG::MaximalFlushInsertionPhase::treatRegularBlock):
(JSC::DFG::MaximalFlushInsertionPhase::treatRootBlock):

  • dfg/DFGMayExit.cpp:
  • dfg/DFGNode.cpp:

(JSC::DFG::Node::hasVariableAccessData):

  • dfg/DFGNodeType.h:
  • dfg/DFGPhantomInsertionPhase.cpp:
  • dfg/DFGPredictionPropagationPhase.cpp:
  • dfg/DFGSSAConversionPhase.cpp:

(JSC::DFG::SSAConversionPhase::run):

  • dfg/DFGSafeToExecute.h:

(JSC::DFG::safeToExecute):

  • dfg/DFGSpeculativeJIT32_64.cpp:

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

  • dfg/DFGSpeculativeJIT64.cpp:

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

  • dfg/DFGValidate.cpp:
  • ftl/FTLCapabilities.cpp:

(JSC::FTL::canCompile):

Location:
trunk
Files:
1 added
23 edited

Legend:

Unmodified
Added
Removed
  • trunk/JSTests/ChangeLog

    r244314 r244324  
     12019-04-15  Saam barati  <sbarati@apple.com>
     2
     3        Modify how we do SetArgument when we inline varargs calls
     4        https://bugs.webkit.org/show_bug.cgi?id=196712
     5        <rdar://problem/49605012>
     6
     7        Reviewed by Michael Saboff.
     8
     9        * stress/get-stack-wrong-type-when-inline-varargs.js: Added.
     10        (foo):
     11
    1122019-04-15  Saam barati  <sbarati@apple.com>
    213
  • trunk/Source/JavaScriptCore/ChangeLog

    r244323 r244324  
     12019-04-15  Saam barati  <sbarati@apple.com>
     2
     3        Modify how we do SetArgument when we inline varargs calls
     4        https://bugs.webkit.org/show_bug.cgi?id=196712
     5        <rdar://problem/49605012>
     6
     7        Reviewed by Michael Saboff.
     8
     9        When we inline varargs calls, we guarantee that the number of arguments that
     10        go on the stack are somewhere between the "mandatoryMinimum" and the "limit - 1".
     11        However, we can't statically guarantee that the arguments between these two
     12        ranges was filled out by Load/ForwardVarargs. This is because in the general
     13        case we don't know the argument count statically.
     14       
     15        However, we used to always emit SetArgumentDefinitely up to "limit - 1" for
     16        all arguments, even when some arguments aren't guaranteed to be in a valid
     17        state. Emitting these SetArgumentDefinitely were helpful because they let us
     18        handle variable liveness and OSR exit metadata. However, when we converted
     19        to SSA, we ended up emitting a GetStack for each such SetArgumentDefinitely.
     20       
     21        This is wrong, as we can't guarantee such SetArgumentDefinitely nodes are
     22        actually looking at a range of the stack that are guaranteed to be initialized.
     23        This patch introduces a new form of SetArgument node: SetArgumentMaybe. In terms
     24        of OSR exit metadata and variable liveness tracking, it behaves like SetArgumentDefinitely.
     25       
     26        However, it differs in a couple key ways:
     27        1. In ThreadedCPS, GetLocal(@SetArgumentMaybe) is invalid IR, as this implies
     28        you might be loading uninitialized stack. (This same rule applies when you do
     29        the full data flow reachability analysis over CPS Phis.) If someone logically
     30        wanted to emit code like this, the correct node to emit would be GetArgument,
     31        not GetLocal. For similar reasons, PhantomLocal(@SetArgumentMaybe) is also
     32        invalid IR.
     33        2. To track liveness, Flush(@SetArgumentMaybe) is valid, and is the main user
     34        of SetArgumentMaybe.
     35        3. In SSA conversion, we don't lower SetArgumentMaybe to GetStack, as there
     36        should be no data flow user of SetArgumentMaybe.
     37       
     38        SetArgumentDefinitely guarantees that the stack slot is initialized.
     39        SetArgumentMaybe makes no such guarantee.
     40
     41        * dfg/DFGAbstractInterpreterInlines.h:
     42        (JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects):
     43        * dfg/DFGByteCodeParser.cpp:
     44        (JSC::DFG::ByteCodeParser::handleVarargsInlining):
     45        * dfg/DFGCPSRethreadingPhase.cpp:
     46        (JSC::DFG::CPSRethreadingPhase::freeUnnecessaryNodes):
     47        (JSC::DFG::CPSRethreadingPhase::canonicalizeGetLocalFor):
     48        (JSC::DFG::CPSRethreadingPhase::canonicalizeFlushOrPhantomLocalFor):
     49        (JSC::DFG::CPSRethreadingPhase::canonicalizeLocalsInBlock):
     50        (JSC::DFG::CPSRethreadingPhase::propagatePhis):
     51        (JSC::DFG::CPSRethreadingPhase::computeIsFlushed):
     52        * dfg/DFGClobberize.h:
     53        (JSC::DFG::clobberize):
     54        * dfg/DFGCommon.h:
     55        * dfg/DFGDoesGC.cpp:
     56        (JSC::DFG::doesGC):
     57        * dfg/DFGFixupPhase.cpp:
     58        (JSC::DFG::FixupPhase::fixupNode):
     59        * dfg/DFGInPlaceAbstractState.cpp:
     60        (JSC::DFG::InPlaceAbstractState::endBasicBlock):
     61        * dfg/DFGLiveCatchVariablePreservationPhase.cpp:
     62        (JSC::DFG::LiveCatchVariablePreservationPhase::handleBlockForTryCatch):
     63        * dfg/DFGMaximalFlushInsertionPhase.cpp:
     64        (JSC::DFG::MaximalFlushInsertionPhase::treatRegularBlock):
     65        (JSC::DFG::MaximalFlushInsertionPhase::treatRootBlock):
     66        * dfg/DFGMayExit.cpp:
     67        * dfg/DFGNode.cpp:
     68        (JSC::DFG::Node::hasVariableAccessData):
     69        * dfg/DFGNodeType.h:
     70        * dfg/DFGPhantomInsertionPhase.cpp:
     71        * dfg/DFGPredictionPropagationPhase.cpp:
     72        * dfg/DFGSSAConversionPhase.cpp:
     73        (JSC::DFG::SSAConversionPhase::run):
     74        * dfg/DFGSafeToExecute.h:
     75        (JSC::DFG::safeToExecute):
     76        * dfg/DFGSpeculativeJIT32_64.cpp:
     77        (JSC::DFG::SpeculativeJIT::compile):
     78        * dfg/DFGSpeculativeJIT64.cpp:
     79        (JSC::DFG::SpeculativeJIT::compile):
     80        * dfg/DFGValidate.cpp:
     81        * ftl/FTLCapabilities.cpp:
     82        (JSC::FTL::canCompile):
     83
    1842019-04-15  Commit Queue  <commit-queue@webkit.org>
    285
  • trunk/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h

    r244313 r244324  
    324324       
    325325    case SetArgumentDefinitely:
    326         // Assert that the state of arguments has been set. SetArgumentDefinitely means
     326    case SetArgumentMaybe:
     327        // Assert that the state of arguments has been set. SetArgumentDefinitely/SetArgumentMaybe means
    327328        // that someone set the argument values out-of-band, and currently this always means setting to a
    328329        // non-clear value.
  • trunk/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp

    r244193 r244324  
    18641864       
    18651865        set(VirtualRegister(argumentStart), get(thisArgument), ImmediateNakedSet);
     1866        unsigned numSetArguments = 0;
    18661867        for (unsigned argument = 1; argument < maxNumArguments; ++argument) {
    18671868            VariableAccessData* variable = newVariableAccessData(VirtualRegister(remappedArgumentStart + argument));
     
    18831884            }
    18841885           
    1885             Node* setArgument = addToGraph(SetArgumentDefinitely, OpInfo(variable));
     1886            Node* setArgument = addToGraph(numSetArguments >= mandatoryMinimum ? SetArgumentMaybe : SetArgumentDefinitely, OpInfo(variable));
    18861887            m_currentBlock->variablesAtTail.setOperand(variable->local(), setArgument);
     1888            ++numSetArguments;
    18871889        }
    18881890    };
  • trunk/Source/JavaScriptCore/dfg/DFGCPSRethreadingPhase.cpp

    r244193 r244324  
    9595                    }
    9696                    switch (node->child1()->op()) {
     97                    case SetArgumentMaybe:
     98                        DFG_CRASH(m_graph, node, "Invalid Phantom(@SetArgumentMaybe)");
     99                        break;
    97100                    case Phi:
    98101                    case SetArgumentDefinitely:
     
    170173                    return;
    171174                }
     175                ASSERT(otherNode->op() != SetArgumentMaybe);
    172176                ASSERT(otherNode->op() == SetLocal || otherNode->op() == SetArgumentDefinitely);
    173177                break;
     
    176180            }
    177181           
     182            ASSERT(otherNode->op() != SetArgumentMaybe);
    178183            ASSERT(otherNode->op() == SetLocal || otherNode->op() == SetArgumentDefinitely || otherNode->op() == GetLocal);
    179184            ASSERT(otherNode->variableAccessData() == variable);
     
    231236            }
    232237           
    233             ASSERT(otherNode->op() == Phi || otherNode->op() == SetLocal || otherNode->op() == SetArgumentDefinitely);
     238            ASSERT(otherNode->op() == Phi || otherNode->op() == SetLocal || otherNode->op() == SetArgumentDefinitely || otherNode->op() == SetArgumentMaybe);
    234239           
    235240            if (nodeType == PhantomLocal && otherNode->op() == SetLocal) {
     
    298303            //
    299304            // Head variable: describes what is live at the head of the basic block.
    300             // Head variable links may refer to Flush, PhantomLocal, Phi, or SetArgumentDefinitely.
    301             // SetArgumentDefinitely may only appear in the root block.
     305            // Head variable links may refer to Flush, PhantomLocal, Phi, or SetArgumentDefinitely/SetArgumentMaybe.
     306            // SetArgumentDefinitely/SetArgumentMaybe may only appear in the root block.
    302307            //
    303308            // Tail variable: the last thing that happened to the variable in the block.
    304             // It may be a Flush, PhantomLocal, GetLocal, SetLocal, SetArgumentDefinitely, or Phi.
    305             // SetArgumentDefinitely may only appear in the root block. Note that if there ever
     309            // It may be a Flush, PhantomLocal, GetLocal, SetLocal, SetArgumentDefinitely/SetArgumentMaybe, or Phi.
     310            // SetArgumentDefinitely/SetArgumentMaybe may only appear in the root block. Note that if there ever
    306311            // was a GetLocal to the variable, and it was followed by PhantomLocals and
    307312            // Flushes but not SetLocals, then the tail variable will be the GetLocal.
     
    312317            //
    313318            // Child of GetLocal: the operation that the GetLocal keeps alive. It may be
    314             // a Phi from the current block. For arguments, it may be a SetArgumentDefinitely.
     319            // a Phi from the current block. For arguments, it may be a SetArgumentDefinitely
     320            // but it can't be a SetArgumentMaybe.
    315321            //
    316322            // Child of SetLocal: must be a value producing node.
    317323            //
    318324            // Child of Flush: it may be a Phi from the current block or a SetLocal. For
    319             // arguments it may also be a SetArgumentDefinitely.
     325            // arguments it may also be a SetArgumentDefinitely/SetArgumentMaybe.
    320326            //
    321327            // Child of PhantomLocal: it may be a Phi from the current block. For
    322             // arguments it may also be a SetArgumentDefinitely.
     328            // arguments it may also be a SetArgumentDefinitely/SetArgumentMaybe.
    323329            //
    324330            // Children of Phi: other Phis in the same basic block, or any of the
    325             // following from predecessor blocks: SetLocal, Phi, or SetArgumentDefinitely.
     331            // following from predecessor blocks: SetLocal, Phi, or SetArgumentDefinitely/SetArgumentMaybe.
    326332            // These are computed by looking at the tail variables of the predecessor blocks
    327             // and either using it directly (if it's a SetLocal, Phi, or SetArgumentDefinitely) or
     333            // and either using it directly (if it's a SetLocal, Phi, or SetArgumentDefinitely/SetArgumentMaybe) or
    328334            // loading that nodes child (if it's a GetLocal, PhanomLocal, or Flush - all
    329             // of these will have children that are SetLocal, Phi, or SetArgumentDefinitely).
     335            // of these will have children that are SetLocal, Phi, or SetArgumentDefinitely/SetArgumentMaybe).
    330336           
    331337            switch (node->op()) {
     
    347353               
    348354            case SetArgumentDefinitely:
     355            case SetArgumentMaybe:
    349356                canonicalizeSet(node);
    350357                break;
     
    421428                    variableInPrevious->op() == SetLocal
    422429                    || variableInPrevious->op() == Phi
    423                     || variableInPrevious->op() == SetArgumentDefinitely);
     430                    || variableInPrevious->op() == SetArgumentDefinitely
     431                    || variableInPrevious->op() == SetArgumentMaybe);
    424432         
    425433                if (!currentPhi->child1()) {
     
    484492            case SetLocal:
    485493            case SetArgumentDefinitely:
     494            case SetArgumentMaybe:
    486495                break;
    487496               
  • trunk/Source/JavaScriptCore/dfg/DFGClobberize.h

    r244193 r244324  
    452452    case PhantomLocal:
    453453    case SetArgumentDefinitely:
     454    case SetArgumentMaybe:
    454455    case Jump:
    455456    case Branch:
  • trunk/Source/JavaScriptCore/dfg/DFGCommon.h

    r244193 r244324  
    174174    // not be stored to the stack necessarily. This implies that Phantom can
    175175    // reference nodes that have no result, as long as those nodes are valid
    176     // GetLocal children (i.e. Phi, SetLocal, SetArgumentDefinitely).
     176    // GetLocal children (i.e. Phi, SetLocal, SetArgumentDefinitely, SetArgumentMaybe).
    177177    //
    178178    // LoadStore form also implies that Phis need not have children. By default,
  • trunk/Source/JavaScriptCore/dfg/DFGDoesGC.cpp

    r244193 r244324  
    8080    case PhantomLocal:
    8181    case SetArgumentDefinitely:
     82    case SetArgumentMaybe:
    8283    case ArithBitNot:
    8384    case ArithBitAnd:
  • trunk/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp

    r244238 r244324  
    23262326        // Have these no-op cases here to ensure that nobody forgets to add handlers for new opcodes.
    23272327        case SetArgumentDefinitely:
     2328        case SetArgumentMaybe:
    23282329        case JSConstant:
    23292330        case LazyJSConstant:
  • trunk/Source/JavaScriptCore/dfg/DFGInPlaceAbstractState.cpp

    r244193 r244324  
    236236            case Phi:
    237237            case SetArgumentDefinitely:
     238            case SetArgumentMaybe:
    238239            case PhantomLocal:
    239240            case Flush: {
  • trunk/Source/JavaScriptCore/dfg/DFGLiveCatchVariablePreservationPhase.cpp

    r244193 r244324  
    199199            }
    200200
    201             if (currentExceptionHandler && (node->op() == SetLocal || node->op() == SetArgumentDefinitely)) {
     201            if (currentExceptionHandler && (node->op() == SetLocal || node->op() == SetArgumentDefinitely || node->op() == SetArgumentMaybe)) {
    202202                InlineCallFrame* inlineCallFrame = node->origin.semantic.inlineCallFrame();
    203203                if (inlineCallFrame)
  • trunk/Source/JavaScriptCore/dfg/DFGMaximalFlushInsertionPhase.cpp

    r244193 r244324  
    7777                }
    7878
    79                 if (node->op() == SetLocal || (node->op() == SetArgumentDefinitely && !isPrimordialSetArgument)) {
     79                if (node->op() == SetLocal || (node->op() == SetArgumentDefinitely && !isPrimordialSetArgument) || node->op() == SetArgumentMaybe) {
    8080                    VirtualRegister operand = node->local();
    8181                    VariableAccessData* flushAccessData = currentBlockAccessData.operand(operand);
     
    137137        for (unsigned i = 0; i < block->variablesAtTail.numberOfLocals(); i++) {
    138138            VirtualRegister operand = virtualRegisterForLocal(i);
    139             DFG_ASSERT(m_graph, nullptr, initialAccessNodes.operand(operand)->op() == Flush); // We should have inserted a Flush before any SetLocal/SetArgumentDefinitely for the local that we are analyzing now.
     139            DFG_ASSERT(m_graph, nullptr, initialAccessNodes.operand(operand)->op() == Flush); // We should have inserted a Flush before any SetLocal/SetArgumentDefinitely/SetArgumentMaybe for the local that we are analyzing now.
    140140            VariableAccessData* accessData = initialAccessData.operand(operand);
    141141            DFG_ASSERT(m_graph, nullptr, accessData);
  • trunk/Source/JavaScriptCore/dfg/DFGMayExit.cpp

    r244193 r244324  
    4949    // generally make things a lot better but it might introduce subtle bugs.
    5050    case SetArgumentDefinitely:
     51    case SetArgumentMaybe:
    5152    case JSConstant:
    5253    case DoubleConstant:
  • trunk/Source/JavaScriptCore/dfg/DFGNode.cpp

    r244193 r244324  
    7575    case SetLocal:
    7676    case SetArgumentDefinitely:
     77    case SetArgumentMaybe:
    7778    case Flush:
    7879    case PhantomLocal:
  • trunk/Source/JavaScriptCore/dfg/DFGNodeType.h

    r244193 r244324  
    104104    macro(CheckTierUpAtReturn, NodeMustGenerate) \
    105105    \
    106     /* Marker for an argument being set at the prologue of a function. */\
     106    /* Marker for an argument being set at the prologue of a function. The argument is guaranteed to be set after this node. */\
    107107    macro(SetArgumentDefinitely, 0) \
     108    /* A marker like the above that we use to track variable liveness and OSR exit state. However, it's not guaranteed to be set. To verify it was set, you'd need to check the actual argument length. We use this for varargs when we're unsure how many argument may actually end up on the stack. */\
     109    macro(SetArgumentMaybe, 0) \
    108110    \
    109111    /* Marker of location in the IR where we may possibly perform jump replacement to */\
  • trunk/Source/JavaScriptCore/dfg/DFGPhantomInsertionPhase.cpp

    r244193 r244324  
    118118            case GetLocal:
    119119            case SetArgumentDefinitely:
     120            case SetArgumentMaybe:
    120121                m_values.operand(node->local()) = nullptr;
    121122                break;
  • trunk/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp

    r244238 r244324  
    12551255        case ForceOSRExit:
    12561256        case SetArgumentDefinitely:
     1257        case SetArgumentMaybe:
    12571258        case SetFunctionName:
    12581259        case CheckStructure:
  • trunk/Source/JavaScriptCore/dfg/DFGSSAConversionPhase.cpp

    r244193 r244324  
    262262        //
    263263        //   - SetArgumentDefinitely is removed. Note that GetStack nodes have already been inserted.
     264        //
     265        //   - SetArgumentMaybe is removed. It should not have any data flow uses.
    264266        Operands<Node*> valueForOperand(OperandsLike, m_graph.block(0)->variablesAtHead);
    265267        for (BasicBlock* block : m_graph.blocksInPreOrder()) {
     
    394396                }
    395397
     398                case SetArgumentMaybe: {
     399                    node->remove(m_graph);
     400                    break;
     401                }
     402                   
    396403                default:
    397404                    break;
  • trunk/Source/JavaScriptCore/dfg/DFGSafeToExecute.h

    r244314 r244324  
    199199    case PhantomLocal:
    200200    case SetArgumentDefinitely:
     201    case SetArgumentMaybe:
    201202    case ArithBitNot:
    202203    case ArithBitAnd:
  • trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp

    r244193 r244324  
    19741974
    19751975    case SetArgumentDefinitely:
     1976    case SetArgumentMaybe:
    19761977        // This is a no-op; it just marks the fact that the argument is being used.
    19771978        // But it may be profitable to use this as a hook to run speculation checks
  • trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp

    r244193 r244324  
    20732073
    20742074    case SetArgumentDefinitely:
     2075    case SetArgumentMaybe:
    20752076        // This is a no-op; it just marks the fact that the argument is being used.
    20762077        // But it may be profitable to use this as a hook to run speculation checks
  • trunk/Source/JavaScriptCore/dfg/DFGValidate.cpp

    r244193 r244324  
    495495                        edge->op() == SetLocal
    496496                        || edge->op() == SetArgumentDefinitely
    497                         || edge->op() == Flush
     497                        || edge->op() == SetArgumentMaybe
    498498                        || edge->op() == Phi);
    499499                   
     
    506506                            edge->op() == SetLocal
    507507                            || edge->op() == SetArgumentDefinitely
    508                             || edge->op() == Flush);
     508                            || edge->op() == SetArgumentMaybe);
    509509                       
    510510                        continue;
     
    538538                            prevNode->op() == SetLocal
    539539                            || prevNode->op() == SetArgumentDefinitely
     540                            || prevNode->op() == SetArgumentMaybe
    540541                            || prevNode->op() == Phi);
    541542                        if (prevNode == edge.node()) {
     
    667668                        VALIDATE((node, block), getLocalPositions.operand(node->local()) == notSet);
    668669                        VALIDATE((node, block), !!node->child1());
     670                        VALIDATE((node, block), node->child1()->op() == SetArgumentDefinitely || node->child1()->op() == Phi);
    669671                    }
    670672                    getLocalPositions.operand(node->local()) = i;
     
    683685                    setLocalPositions.operand(node->local()) = notSet;
    684686                    break;
     687                case SetArgumentMaybe:
     688                    break;
     689                case Flush:
     690                case PhantomLocal:
     691                    if (m_graph.m_form == ThreadedCPS) {
     692                        VALIDATE((node, block),
     693                            node->child1()->op() == Phi
     694                            || node->child1()->op() == SetLocal
     695                            || node->child1()->op() == SetArgumentDefinitely
     696                            || node->child1()->op() == SetArgumentMaybe);
     697                        if (node->op() == PhantomLocal)
     698                            VALIDATE((node, block), node->child1()->op() != SetArgumentMaybe);
     699                    }
     700                    break;
    685701                default:
    686702                    break;
     
    698714                checkOperand(
    699715                    block, getLocalPositions, setLocalPositions, virtualRegisterForLocal(i));
     716            }
     717        }
     718
     719        if (m_graph.m_form == ThreadedCPS) {
     720            Vector<Node*> worklist;
     721            HashSet<Node*> seen;
     722            for (BasicBlock* block : m_graph.blocksInNaturalOrder()) {
     723                for (Node* node : *block) {
     724                    if (node->op() == GetLocal || node->op() == PhantomLocal) {
     725                        worklist.append(node);
     726                        auto addResult = seen.add(node);
     727                        VALIDATE((node, block), addResult.isNewEntry);
     728                    }
     729                }
     730            }
     731
     732            while (worklist.size()) {
     733                Node* node = worklist.takeLast();
     734                switch (node->op()) {
     735                case PhantomLocal:
     736                case GetLocal: {
     737                    Node* child = node->child1().node();
     738                    if (seen.add(child).isNewEntry)
     739                        worklist.append(child);
     740                    break;
     741                }
     742                case Phi: {
     743                    for (unsigned i = 0; i < m_graph.numChildren(node); ++i) {
     744                        Edge edge = m_graph.child(node, i);
     745                        if (!edge)
     746                            continue;
     747                        if (seen.add(edge.node()).isNewEntry)
     748                            worklist.append(edge.node());
     749                    }
     750                    break;
     751                }
     752                case SetLocal:
     753                case SetArgumentDefinitely:
     754                    break;
     755                case SetArgumentMaybe:
     756                    VALIDATE((node), !"Should not reach SetArgumentMaybe. GetLocal that has data flow that reaches a SetArgumentMaybe is invalid IR.");
     757                    break;
     758                default:
     759                    VALIDATE((node), !"Unexecpted node type.");
     760                    break;
     761                }
    700762            }
    701763        }
     
    741803                case SetLocal:
    742804                case SetArgumentDefinitely:
     805                case SetArgumentMaybe:
    743806                case Phantom:
    744807                    VALIDATE((node), !"bad node type for SSA");
  • trunk/Source/JavaScriptCore/ftl/FTLCapabilities.cpp

    r244193 r244324  
    5858    case PhantomLocal:
    5959    case SetArgumentDefinitely:
     60    case SetArgumentMaybe:
    6061    case Return:
    6162    case ArithBitNot:
Note: See TracChangeset for help on using the changeset viewer.