Ignore:
Timestamp:
Mar 8, 2013, 6:51:06 PM (12 years ago)
Author:
[email protected]
Message:

DFG overflow check elimination is too smart for its own good
https://bugs.webkit.org/show_bug.cgi?id=111832

Source/JavaScriptCore:

Reviewed by Oliver Hunt and Gavin Barraclough.

This improves overflow check elimination in three ways:

1) It reduces the amount of time the compiler will spend doing it.

2) It fixes bugs where overflow check elimination was overzealous. Precisely, for a binary operation

over @a and @b where both @a and @b will type check that their inputs (@a->children, @b->children)
are int32's and then perform a possibly-overflowing operation, we must be careful not to assume
that @a's non-int32 parts don't matter if at the point that @a runs we have as yet not proved that
@b->children are int32's and that hence @b might produce a large enough result that doubles would
start chopping low bits. The specific implication of this is that for a binary operation to not
propagate that it cares about non-int32 parts (NodeUsedAsNumber), we must prove that at least one
of the inputs is guaranteed to produce a result within 232 and that there won't be a tower of such
operations large enough to ultimately produce a double greater than 2
52 (roughly). We achieve the
latter by disabling this optimization for very large basic blocks. It's noteworthy that blocks that
large won't even make it into the DFG currently.


3) It makes the overflow check elimination more precise for cases where the inputs to an Add or Sub

are the outputs of a bit-op. For example in (@a + (@b | 0)) | 0, we don't need to propagate
NodeUsedAsNumber to either @a or @b.


This is neutral on V8v7 and a slight speed-up on compile time benchmarks.

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

(JSC::DFG::ArrayMode::refine):

  • dfg/DFGBackwardsPropagationPhase.cpp: Added.

(DFG):
(BackwardsPropagationPhase):
(JSC::DFG::BackwardsPropagationPhase::BackwardsPropagationPhase):
(JSC::DFG::BackwardsPropagationPhase::run):
(JSC::DFG::BackwardsPropagationPhase::isNotNegZero):
(JSC::DFG::BackwardsPropagationPhase::isNotZero):
(JSC::DFG::BackwardsPropagationPhase::isWithinPowerOfTwoForConstant):
(JSC::DFG::BackwardsPropagationPhase::isWithinPowerOfTwoNonRecursive):
(JSC::DFG::BackwardsPropagationPhase::isWithinPowerOfTwo):
(JSC::DFG::BackwardsPropagationPhase::mergeDefaultFlags):
(JSC::DFG::BackwardsPropagationPhase::propagate):
(JSC::DFG::performBackwardsPropagation):

  • dfg/DFGBackwardsPropagationPhase.h: Added.

(DFG):

  • dfg/DFGCPSRethreadingPhase.cpp:

(JSC::DFG::CPSRethreadingPhase::run):
(JSC::DFG::CPSRethreadingPhase::clearIsLoadedFrom):
(CPSRethreadingPhase):
(JSC::DFG::CPSRethreadingPhase::canonicalizeGetLocalFor):
(JSC::DFG::CPSRethreadingPhase::canonicalizeFlushOrPhantomLocalFor):

  • dfg/DFGDriver.cpp:

(JSC::DFG::compile):

  • dfg/DFGGraph.cpp:

(JSC::DFG::Graph::dump):

  • dfg/DFGNodeFlags.cpp:

(JSC::DFG::dumpNodeFlags):
(DFG):

  • dfg/DFGNodeFlags.h:

(DFG):

  • dfg/DFGPredictionPropagationPhase.cpp:

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

  • dfg/DFGUnificationPhase.cpp:

(JSC::DFG::UnificationPhase::run):

  • dfg/DFGVariableAccessData.h:

(JSC::DFG::VariableAccessData::VariableAccessData):
(JSC::DFG::VariableAccessData::mergeIsLoadedFrom):
(VariableAccessData):
(JSC::DFG::VariableAccessData::setIsLoadedFrom):
(JSC::DFG::VariableAccessData::isLoadedFrom):

LayoutTests:

Reviewed by Oliver Hunt and Gavin Barraclough.

  • fast/js/dfg-arith-add-overflow-check-elimination-predicted-but-not-proven-int-expected.txt: Added.
  • fast/js/dfg-arith-add-overflow-check-elimination-predicted-but-not-proven-int.html: Added.
  • fast/js/dfg-arith-add-overflow-check-elimination-tower-of-large-numbers-expected.txt: Added.
  • fast/js/dfg-arith-add-overflow-check-elimination-tower-of-large-numbers.html: Added.
  • fast/js/jsc-test-list:
  • fast/js/script-tests/dfg-arith-add-overflow-check-elimination-predicted-but-not-proven-int.js: Added.

(foo):
(bar):

  • fast/js/script-tests/dfg-arith-add-overflow-check-elimination-tower-of-large-numbers.js: Added.

(foo):
(bar):

File:
1 edited

Legend:

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

    r144939 r145299  
    107107    }
    108108   
    109     bool isNotNegZero(Node* node)
    110     {
    111         if (!m_graph.isNumberConstant(node))
    112             return false;
    113         double value = m_graph.valueOfNumberConstant(node);
    114         return !value && 1.0 / value < 0.0;
    115     }
    116    
    117     bool isNotZero(Node* node)
    118     {
    119         if (!m_graph.isNumberConstant(node))
    120             return false;
    121         return !!m_graph.valueOfNumberConstant(node);
    122     }
    123    
    124     bool isWithinPowerOfTwoForConstant(Node* node, int power)
    125     {
    126         JSValue immediateValue = node->valueOfJSConstant(codeBlock());
    127         if (!immediateValue.isInt32())
    128             return false;
    129         int32_t intImmediate = immediateValue.asInt32();
    130         return intImmediate > -(1 << power) && intImmediate < (1 << power);
    131     }
    132    
    133     bool isWithinPowerOfTwoNonRecursive(Node* node, int power)
    134     {
    135         if (node->op() != JSConstant)
    136             return false;
    137         return isWithinPowerOfTwoForConstant(node, power);
    138     }
    139    
    140     bool isWithinPowerOfTwo(Node* node, int power)
    141     {
    142         switch (node->op()) {
    143         case JSConstant: {
    144             return isWithinPowerOfTwoForConstant(node, power);
    145         }
    146            
    147         case BitAnd: {
    148             return isWithinPowerOfTwoNonRecursive(node->child1().node(), power)
    149                 || isWithinPowerOfTwoNonRecursive(node->child2().node(), power);
    150         }
    151            
    152         case BitRShift:
    153         case BitURShift: {
    154             Node* shiftAmount = node->child2().node();
    155             if (shiftAmount->op() != JSConstant)
    156                 return false;
    157             JSValue immediateValue = shiftAmount->valueOfJSConstant(codeBlock());
    158             if (!immediateValue.isInt32())
    159                 return false;
    160             return immediateValue > 32 - power;
    161         }
    162            
    163         default:
    164             return false;
    165         }
    166     }
    167 
    168109    SpeculatedType speculatedDoubleTypeForPrediction(SpeculatedType value)
    169110    {
     
    183124    {
    184125        NodeType op = node->op();
    185         NodeFlags flags = node->flags() & NodeBackPropMask;
    186126
    187127#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
    188         dataLog("   ", Graph::opName(op), " ", m_currentNode, ": ", nodeFlagsAsString(flags), " ");
     128        dataLog("   ", Graph::opName(op), " ", m_currentNode, ": ", NodeFlagsDump(node->flags()), " ");
    189129#endif
    190130       
     
    203143            if (prediction)
    204144                changed |= mergePrediction(prediction);
    205            
    206             // Assume conservatively that a SetLocal implies that the value may flow through a loop,
    207             // and so we would have overflow leading to the program "observing" numbers even if all
    208             // users of the value are doing toInt32. It might be worthwhile to revisit this at some
    209             // point and actually check if the data flow involves loops, but right now I don't think
    210             // we have evidence that this would be beneficial for benchmarks.
    211            
    212             changed |= variableAccessData->mergeFlags((flags & ~NodeUsedAsIntLocally) | NodeUsedAsNumber);
    213145            break;
    214146        }
     
    217149            VariableAccessData* variableAccessData = node->variableAccessData();
    218150            changed |= variableAccessData->predict(node->child1()->prediction());
    219 
    220             changed |= node->child1()->mergeFlags(variableAccessData->flags());
    221             break;
    222         }
    223            
    224         case Flush: {
    225             // Make sure that the analysis knows that flushed locals escape.
    226             VariableAccessData* variableAccessData = node->variableAccessData();
    227             changed |= variableAccessData->mergeFlags(NodeUsedAsValue);
    228151            break;
    229152        }
     
    236159        case BitURShift: {
    237160            changed |= setPrediction(SpecInt32);
    238             flags |= NodeUsedAsInt | NodeUsedAsIntLocally;
    239             flags &= ~(NodeUsedAsNumber | NodeNeedsNegZero | NodeUsedAsOther);
    240             changed |= node->child1()->mergeFlags(flags);
    241             changed |= node->child2()->mergeFlags(flags);
    242161            break;
    243162        }
     
    245164        case ValueToInt32: {
    246165            changed |= setPrediction(SpecInt32);
    247             flags |= NodeUsedAsInt | NodeUsedAsIntLocally;
    248             flags &= ~(NodeUsedAsNumber | NodeNeedsNegZero | NodeUsedAsOther);
    249             changed |= node->child1()->mergeFlags(flags);
    250             break;
    251         }
    252            
    253         case ArrayPop: {
    254             changed |= mergePrediction(node->getHeapPrediction());
    255             changed |= mergeDefaultFlags(node);
    256             break;
    257         }
    258 
    259         case ArrayPush: {
    260             changed |= mergePrediction(node->getHeapPrediction());
    261             changed |= node->child1()->mergeFlags(NodeUsedAsValue);
    262             changed |= node->child2()->mergeFlags(NodeUsedAsValue);
    263             break;
    264         }
    265 
     166            break;
     167        }
     168           
     169        case ArrayPop:
     170        case ArrayPush:
    266171        case RegExpExec:
    267         case RegExpTest: {
    268             changed |= mergePrediction(node->getHeapPrediction());
    269             changed |= mergeDefaultFlags(node);
     172        case RegExpTest:
     173        case GetById:
     174        case GetByIdFlush:
     175        case GetMyArgumentByValSafe:
     176        case GetByOffset:
     177        case Call:
     178        case Construct:
     179        case GetGlobalVar:
     180        case GetScopedVar:
     181        case Resolve:
     182        case ResolveBase:
     183        case ResolveBaseStrictPut:
     184        case ResolveGlobal: {
     185            changed |= setPrediction(node->getHeapPrediction());
    270186            break;
    271187        }
    272188
    273189        case StringCharCodeAt: {
    274             changed |= mergePrediction(SpecInt32);
    275             changed |= node->child1()->mergeFlags(NodeUsedAsValue);
    276             changed |= node->child2()->mergeFlags(NodeUsedAsNumber | NodeUsedAsOther | NodeUsedAsInt | NodeUsedAsIntLocally);
     190            changed |= setPrediction(SpecInt32);
    277191            break;
    278192        }
     
    283197            else
    284198                changed |= mergePrediction(SpecNumber);
    285            
    286             changed |= node->child1()->mergeFlags(flags);
    287199            break;
    288200        }
     
    291203            SpeculatedType left = node->child1()->prediction();
    292204            SpeculatedType right = node->child2()->prediction();
    293            
    294             AddSpeculationMode mode = DontSpeculateInteger;
    295205           
    296206            if (left && right) {
    297207                if (isNumberSpeculationExpectingDefined(left) && isNumberSpeculationExpectingDefined(right)) {
    298                     if ((mode = m_graph.addSpeculationMode(node)) != DontSpeculateInteger)
     208                    if (m_graph.addSpeculationMode(node) != DontSpeculateInteger)
    299209                        changed |= mergePrediction(SpecInt32);
    300210                    else
     
    306216                    changed |= mergePrediction(SpecString | SpecInt32 | SpecDouble);
    307217            }
    308            
    309             if (isNotNegZero(node->child1().node()) || isNotNegZero(node->child2().node()))
    310                 flags &= ~NodeNeedsNegZero;
    311             if (node->child1()->hasNumberResult() || node->child2()->hasNumberResult())
    312                 flags &= ~NodeUsedAsOther;
    313            
    314             if (mode != SpeculateInteger)
    315                 flags |= NodeUsedAsNumber;
    316            
    317             changed |= node->child1()->mergeFlags(flags);
    318             changed |= node->child2()->mergeFlags(flags);
    319218            break;
    320219        }
     
    324223            SpeculatedType right = node->child2()->prediction();
    325224           
    326             AddSpeculationMode mode = DontSpeculateInteger;
    327            
    328225            if (left && right) {
    329                 if ((mode = m_graph.addSpeculationMode(node)) != DontSpeculateInteger)
     226                if (m_graph.addSpeculationMode(node) != DontSpeculateInteger)
    330227                    changed |= mergePrediction(SpecInt32);
    331228                else
    332229                    changed |= mergePrediction(speculatedDoubleTypeForPredictions(left, right));
    333230            }
    334            
    335             if (isNotNegZero(node->child1().node()) || isNotNegZero(node->child2().node()))
    336                 flags &= ~NodeNeedsNegZero;
    337             flags &= ~NodeUsedAsOther;
    338            
    339             if (mode != SpeculateInteger)
    340                 flags |= NodeUsedAsNumber;
    341            
    342             changed |= node->child1()->mergeFlags(flags);
    343             changed |= node->child2()->mergeFlags(flags);
    344231            break;
    345232        }
     
    349236            SpeculatedType right = node->child2()->prediction();
    350237           
    351             AddSpeculationMode mode = DontSpeculateInteger;
    352            
    353238            if (left && right) {
    354                 if ((mode = m_graph.addSpeculationMode(node)) != DontSpeculateInteger)
     239                if (m_graph.addSpeculationMode(node) != DontSpeculateInteger)
    355240                    changed |= mergePrediction(SpecInt32);
    356241                else
    357242                    changed |= mergePrediction(speculatedDoubleTypeForPredictions(left, right));
    358243            }
    359 
    360             if (isNotZero(node->child1().node()) || isNotZero(node->child2().node()))
    361                 flags &= ~NodeNeedsNegZero;
    362             flags &= ~NodeUsedAsOther;
    363            
    364             if (mode != SpeculateInteger)
    365                 flags |= NodeUsedAsNumber;
    366            
    367             changed |= node->child1()->mergeFlags(flags);
    368             changed |= node->child2()->mergeFlags(flags);
    369244            break;
    370245        }
     
    377252                    changed |= mergePrediction(speculatedDoubleTypeForPrediction(node->child1()->prediction()));
    378253            }
    379 
    380             flags &= ~NodeUsedAsOther;
    381 
    382             changed |= node->child1()->mergeFlags(flags);
    383254            break;
    384255           
     
    395266                    changed |= mergePrediction(speculatedDoubleTypeForPredictions(left, right));
    396267            }
    397 
    398             flags |= NodeUsedAsNumber;
    399             flags &= ~NodeUsedAsOther;
    400 
    401             changed |= node->child1()->mergeFlags(flags);
    402             changed |= node->child2()->mergeFlags(flags);
    403268            break;
    404269        }
     
    414279                    changed |= mergePrediction(speculatedDoubleTypeForPredictions(left, right));
    415280            }
    416 
    417             // As soon as a multiply happens, we can easily end up in the part
    418             // of the double domain where the point at which you do truncation
    419             // can change the outcome. So, ArithMul always forces its inputs to
    420             // check for overflow. Additionally, it will have to check for overflow
    421             // itself unless we can prove that there is no way for the values
    422             // produced to cause double rounding.
    423            
    424             if (!isWithinPowerOfTwo(node->child1().node(), 22)
    425                 && !isWithinPowerOfTwo(node->child2().node(), 22))
    426                 flags |= NodeUsedAsNumber;
    427            
    428             changed |= node->mergeFlags(flags);
    429            
    430             flags |= NodeUsedAsNumber | NodeNeedsNegZero;
    431             flags &= ~NodeUsedAsOther;
    432 
    433             changed |= node->child1()->mergeFlags(flags);
    434             changed |= node->child2()->mergeFlags(flags);
    435281            break;
    436282        }
     
    447293                    changed |= mergePrediction(SpecDouble);
    448294            }
    449 
    450             // As soon as a multiply happens, we can easily end up in the part
    451             // of the double domain where the point at which you do truncation
    452             // can change the outcome. So, ArithDiv always checks for overflow
    453             // no matter what, and always forces its inputs to check as well.
    454            
    455             flags |= NodeUsedAsNumber | NodeNeedsNegZero;
    456             flags &= ~NodeUsedAsOther;
    457 
    458             changed |= node->child1()->mergeFlags(flags);
    459             changed |= node->child2()->mergeFlags(flags);
    460295            break;
    461296        }
     
    472307                    changed |= mergePrediction(SpecDouble);
    473308            }
    474            
    475             flags |= NodeUsedAsNumber | NodeNeedsNegZero;
    476             flags &= ~NodeUsedAsOther;
    477 
    478             changed |= node->child1()->mergeFlags(flags);
    479             changed |= node->child2()->mergeFlags(flags);
    480309            break;
    481310        }
     
    483312        case ArithSqrt: {
    484313            changed |= setPrediction(SpecDouble);
    485             flags |= NodeUsedAsNumber | NodeNeedsNegZero;
    486             flags &= ~NodeUsedAsOther;
    487             changed |= node->child1()->mergeFlags(flags);
    488314            break;
    489315        }
     
    496322            else
    497323                changed |= mergePrediction(speculatedDoubleTypeForPrediction(child));
    498 
    499             changed |= node->child1()->mergeFlags(flags);
    500324            break;
    501325        }
     
    518342        case IsFunction: {
    519343            changed |= setPrediction(SpecBoolean);
    520             changed |= mergeDefaultFlags(node);
    521344            break;
    522345        }
     
    524347        case TypeOf: {
    525348            changed |= setPrediction(SpecString);
    526             changed |= mergeDefaultFlags(node);
    527             break;
    528         }
    529 
    530         case GetById: {
    531             changed |= mergePrediction(node->getHeapPrediction());
    532             changed |= mergeDefaultFlags(node);
    533             break;
    534         }
    535            
    536         case GetByIdFlush:
    537             changed |= mergePrediction(node->getHeapPrediction());
    538             changed |= mergeDefaultFlags(node);
    539             break;
    540            
     349            break;
     350        }
     351
    541352        case GetByVal: {
    542353            if (node->child1()->shouldSpeculateFloat32Array()
     
    545356            else
    546357                changed |= mergePrediction(node->getHeapPrediction());
    547 
    548             changed |= node->child1()->mergeFlags(NodeUsedAsValue);
    549             changed |= node->child2()->mergeFlags(NodeUsedAsNumber | NodeUsedAsOther | NodeUsedAsInt | NodeUsedAsIntLocally);
    550             break;
    551         }
    552            
    553         case GetMyArgumentByValSafe: {
    554             changed |= mergePrediction(node->getHeapPrediction());
    555             changed |= node->child1()->mergeFlags(NodeUsedAsNumber | NodeUsedAsOther | NodeUsedAsInt | NodeUsedAsIntLocally);
    556358            break;
    557359        }
     
    568370        case ReallocatePropertyStorage: {
    569371            changed |= setPrediction(SpecOther);
    570             changed |= mergeDefaultFlags(node);
    571             break;
    572         }
    573 
    574         case GetByOffset: {
    575             changed |= mergePrediction(node->getHeapPrediction());
    576             changed |= mergeDefaultFlags(node);
    577             break;
    578         }
    579            
    580         case Call:
    581         case Construct: {
    582             changed |= mergePrediction(node->getHeapPrediction());
    583             for (unsigned childIdx = node->firstChild();
    584                 childIdx < node->firstChild() + node->numChildren();
    585                 ++childIdx)
    586                 changed |= m_graph.m_varArgChildren[childIdx]->mergeFlags(NodeUsedAsValue);
    587             break;
    588         }
    589            
     372            break;
     373        }
     374
    590375        case ConvertThis: {
    591376            SpeculatedType prediction = node->child1()->prediction();
     
    597382                changed |= mergePrediction(prediction);
    598383            }
    599             changed |= mergeDefaultFlags(node);
    600             break;
    601         }
    602            
    603         case GetGlobalVar: {
    604             changed |= mergePrediction(node->getHeapPrediction());
    605             break;
    606         }
    607            
    608         case PutGlobalVar:
    609         case PutGlobalVarCheck: {
    610             changed |= node->child1()->mergeFlags(NodeUsedAsValue);
    611             break;
    612         }
    613            
    614         case GetScopedVar:
    615         case Resolve:
    616         case ResolveBase:
    617         case ResolveBaseStrictPut:
    618         case ResolveGlobal: {
    619             SpeculatedType prediction = node->getHeapPrediction();
    620             changed |= mergePrediction(prediction);
    621384            break;
    622385        }
     
    637400        case NewObject: {
    638401            changed |= setPrediction(SpecFinalObject);
    639             changed |= mergeDefaultFlags(node);
    640             break;
    641         }
    642            
    643         case NewArray: {
    644             changed |= setPrediction(SpecArray);
    645             for (unsigned childIdx = node->firstChild();
    646                 childIdx < node->firstChild() + node->numChildren();
    647                 ++childIdx)
    648                 changed |= m_graph.m_varArgChildren[childIdx]->mergeFlags(NodeUsedAsValue);
    649             break;
    650         }
    651            
    652         case NewArrayWithSize: {
    653             changed |= setPrediction(SpecArray);
    654             changed |= node->child1()->mergeFlags(NodeUsedAsValue | NodeUsedAsInt | NodeUsedAsIntLocally);
    655             break;
    656         }
    657            
     402            break;
     403        }
     404           
     405        case NewArray:
     406        case NewArrayWithSize:
    658407        case NewArrayBuffer: {
    659408            changed |= setPrediction(SpecArray);
     
    661410        }
    662411           
    663         case NewRegexp: {
     412        case NewRegexp:
     413        case CreateActivation: {
    664414            changed |= setPrediction(SpecObjectOther);
    665415            break;
    666416        }
    667417       
    668         case StringCharAt: {
    669             changed |= setPrediction(SpecString);
    670             changed |= node->child1()->mergeFlags(NodeUsedAsValue);
    671             changed |= node->child2()->mergeFlags(NodeUsedAsNumber | NodeUsedAsOther | NodeUsedAsInt | NodeUsedAsIntLocally);
    672             break;
    673         }
    674            
     418        case StringCharAt:
    675419        case StrCat: {
    676420            changed |= setPrediction(SpecString);
    677             for (unsigned childIdx = node->firstChild();
    678                 childIdx < node->firstChild() + node->numChildren();
    679                 ++childIdx)
    680                 changed |= m_graph.m_varArgChildren[childIdx]->mergeFlags(NodeUsedAsNumber | NodeUsedAsOther);
    681421            break;
    682422        }
     
    700440                    changed |= mergePrediction(child);
    701441            }
    702             changed |= node->child1()->mergeFlags(flags);
    703             break;
    704         }
    705            
    706         case CreateActivation: {
    707             changed |= setPrediction(SpecObjectOther);
    708442            break;
    709443        }
     
    744478        }
    745479       
    746         case PutByVal:
    747             changed |= m_graph.varArgChild(node, 0)->mergeFlags(NodeUsedAsValue);
    748             changed |= m_graph.varArgChild(node, 1)->mergeFlags(NodeUsedAsNumber | NodeUsedAsOther | NodeUsedAsInt | NodeUsedAsIntLocally);
    749             changed |= m_graph.varArgChild(node, 2)->mergeFlags(NodeUsedAsValue);
    750             break;
    751 
    752         case PutScopedVar:
    753             changed |= node->child1()->mergeFlags(NodeUsedAsValue);
    754             changed |= node->child3()->mergeFlags(NodeUsedAsValue);
    755             break;
    756            
    757         case Return:
    758         case Throw:
    759             changed |= node->child1()->mergeFlags(NodeUsedAsValue);
    760             break;
    761 
    762         case PutById:
    763         case PutByIdDirect:
    764             changed |= node->child1()->mergeFlags(NodeUsedAsValue);
    765             changed |= node->child2()->mergeFlags(NodeUsedAsValue);
    766             break;
    767 
    768         case PutByOffset:
    769             changed |= node->child1()->mergeFlags(NodeUsedAsValue);
    770             changed |= node->child3()->mergeFlags(NodeUsedAsValue);
    771             break;
    772            
    773480        case Phi:
    774481            // Phis should not be visible here since we're iterating the all-but-Phi's
     
    777484            break;
    778485
     486        case GetScope:
     487            changed |= setPrediction(SpecCellOther);
     488            break;
     489
     490#ifndef NDEBUG
     491        // These get ignored because they don't return anything.
     492        case PutByVal:
     493        case PutScopedVar:
     494        case Return:
     495        case Throw:
     496        case PutById:
     497        case PutByIdDirect:
     498        case PutByOffset:
    779499        case SetCallee:
    780500        case SetMyScope:
    781             changed |= node->child1()->mergeFlags(NodeUsedAsValue);
    782             break;
    783            
    784         case GetScope:
    785             changed |= node->child1()->mergeFlags(NodeUsedAsValue);
    786             changed |= setPrediction(SpecCellOther);
    787             break;
    788 
    789 #ifndef NDEBUG
    790         // These get ignored because they don't return anything.
    791501        case DFG::Jump:
    792502        case Branch:
     
    810520        case AllocationProfileWatchpoint:
    811521        case Phantom:
    812             changed |= mergeDefaultFlags(node);
     522        case PutGlobalVar:
     523        case PutGlobalVarCheck:
    813524            break;
    814525           
     
    818529        case CountExecution:
    819530        case PhantomLocal:
     531        case Flush:
    820532            break;
    821533           
     
    825537#else
    826538        default:
    827             changed |= mergeDefaultFlags(node);
    828539            break;
    829540#endif
     
    837548    }
    838549       
    839     bool mergeDefaultFlags(Node* node)
    840     {
    841         bool changed = false;
    842         if (node->flags() & NodeHasVarArgs) {
    843             for (unsigned childIdx = node->firstChild();
    844                 childIdx < node->firstChild() + node->numChildren();
    845                 childIdx++) {
    846                 if (!!m_graph.m_varArgChildren[childIdx])
    847                     changed |= m_graph.m_varArgChildren[childIdx]->mergeFlags(NodeUsedAsValue);
    848             }
    849         } else {
    850             if (!node->child1())
    851                 return changed;
    852             changed |= node->child1()->mergeFlags(NodeUsedAsValue);
    853             if (!node->child2())
    854                 return changed;
    855             changed |= node->child2()->mergeFlags(NodeUsedAsValue);
    856             if (!node->child3())
    857                 return changed;
    858             changed |= node->child3()->mergeFlags(NodeUsedAsValue);
    859         }
    860         return changed;
    861     }
    862    
    863550    void propagateForward()
    864551    {
Note: See TracChangeset for help on using the changeset viewer.