2  * Copyright (C) 2011, 2012, 2013, 2014 Apple Inc. All rights reserved. 
   4  * Redistribution and use in source and binary forms, with or without 
   5  * modification, are permitted provided that the following conditions 
   7  * 1. Redistributions of source code must retain the above copyright 
   8  *    notice, this list of conditions and the following disclaimer. 
   9  * 2. Redistributions in binary form must reproduce the above copyright 
  10  *    notice, this list of conditions and the following disclaimer in the 
  11  *    documentation and/or other materials provided with the distribution. 
  13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY 
  14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
  15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 
  16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR 
  17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 
  18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 
  19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 
  20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 
  21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
  22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
  23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.  
  27 #include "DFGPredictionPropagationPhase.h" 
  33 #include "JSCInlines.h" 
  35 namespace JSC 
{ namespace DFG 
{ 
  37 SpeculatedType 
resultOfToPrimitive(SpeculatedType type
) 
  39     if (type 
& SpecObject
) { 
  40         // Objects get turned into strings. So if the input has hints of objectness, 
  41         // the output will have hinsts of stringiness. 
  42         return mergeSpeculations(type 
& ~SpecObject
, SpecString
); 
  48 class PredictionPropagationPhase 
: public Phase 
{ 
  50     PredictionPropagationPhase(Graph
& graph
) 
  51         : Phase(graph
, "prediction propagation") 
  57         ASSERT(m_graph
.m_form 
== ThreadedCPS
); 
  58         ASSERT(m_graph
.m_unificationState 
== GloballyUnified
); 
  61         propagateToFixpoint(); 
  63         m_pass 
= RareCasePass
; 
  64         propagateToFixpoint(); 
  66         m_pass 
= DoubleVotingPass
; 
  69             doRoundOfDoubleVoting(); 
  80     void propagateToFixpoint() 
  85             // Forward propagation is near-optimal for both topologically-sorted and 
  91             // Backward propagation reduces the likelihood that pathological code will 
  92             // cause slowness. Loops (especially nested ones) resemble backward flow. 
  93             // This pass captures two cases: (1) it detects if the forward fixpoint 
  94             // found a sound solution and (2) short-circuits backward flow. 
 100     bool setPrediction(SpeculatedType prediction
) 
 102         ASSERT(m_currentNode
->hasResult()); 
 104         // setPrediction() is used when we know that there is no way that we can change 
 105         // our minds about what the prediction is going to be. There is no semantic 
 106         // difference between setPrediction() and mergeSpeculation() other than the 
 107         // increased checking to validate this property. 
 108         ASSERT(m_currentNode
->prediction() == SpecNone 
|| m_currentNode
->prediction() == prediction
); 
 110         return m_currentNode
->predict(prediction
); 
 113     bool mergePrediction(SpeculatedType prediction
) 
 115         ASSERT(m_currentNode
->hasResult()); 
 117         return m_currentNode
->predict(prediction
); 
 120     SpeculatedType 
speculatedDoubleTypeForPrediction(SpeculatedType value
) 
 122         SpeculatedType result 
= SpecDoubleReal
; 
 123         if (value 
& SpecDoubleImpureNaN
) 
 124             result 
|= SpecDoubleImpureNaN
; 
 125         if (value 
& SpecDoublePureNaN
) 
 126             result 
|= SpecDoublePureNaN
; 
 127         if (!isFullNumberOrBooleanSpeculation(value
)) 
 128             result 
|= SpecDoublePureNaN
; 
 132     SpeculatedType 
speculatedDoubleTypeForPredictions(SpeculatedType left
, SpeculatedType right
) 
 134         return speculatedDoubleTypeForPrediction(mergeSpeculations(left
, right
)); 
 137     void propagate(Node
* node
) 
 139         NodeType op 
= node
->op(); 
 141         bool changed 
= false; 
 145         case WeakJSConstant
: { 
 146             SpeculatedType type 
= speculationFromValue(m_graph
.valueOfJSConstant(node
)); 
 147             if (type 
== SpecInt52AsDouble 
&& enableInt52()) 
 149             changed 
|= setPrediction(type
); 
 154             VariableAccessData
* variable 
= node
->variableAccessData(); 
 155             SpeculatedType prediction 
= variable
->prediction(); 
 156             if (!variable
->couldRepresentInt52() && (prediction 
& SpecInt52
)) 
 157                 prediction 
= (prediction 
| SpecInt52AsDouble
) & ~SpecInt52
; 
 159                 changed 
|= mergePrediction(prediction
); 
 164             VariableAccessData
* variableAccessData 
= node
->variableAccessData(); 
 165             changed 
|= variableAccessData
->predict(node
->child1()->prediction()); 
 176             changed 
|= setPrediction(SpecInt32
); 
 186         case GetMyArgumentByValSafe
: 
 188         case MultiGetByOffset
: 
 192         case GetClosureVar
: { 
 193             changed 
|= setPrediction(node
->getHeapPrediction()); 
 197         case StringCharCodeAt
: { 
 198             changed 
|= setPrediction(SpecInt32
); 
 202         case UInt32ToNumber
: { 
 203             // FIXME: Support Int52. 
 204             // https://bugs.webkit.org/show_bug.cgi?id=125704 
 205             if (node
->canSpeculateInt32(m_pass
)) 
 206                 changed 
|= mergePrediction(SpecInt32
); 
 208                 changed 
|= mergePrediction(SpecBytecodeNumber
); 
 213             SpeculatedType left 
= node
->child1()->prediction(); 
 214             SpeculatedType right 
= node
->child2()->prediction(); 
 217                 if (isFullNumberOrBooleanSpeculationExpectingDefined(left
) 
 218                     && isFullNumberOrBooleanSpeculationExpectingDefined(right
)) { 
 219                     if (m_graph
.addSpeculationMode(node
, m_pass
) != DontSpeculateInt32
) 
 220                         changed 
|= mergePrediction(SpecInt32
); 
 221                     else if (m_graph
.addShouldSpeculateMachineInt(node
)) 
 222                         changed 
|= mergePrediction(SpecInt52
); 
 224                         changed 
|= mergePrediction(speculatedDoubleTypeForPredictions(left
, right
)); 
 226                     !(left 
& (SpecFullNumber 
| SpecBoolean
)) 
 227                     || !(right 
& (SpecFullNumber 
| SpecBoolean
))) { 
 228                     // left or right is definitely something other than a number. 
 229                     changed 
|= mergePrediction(SpecString
); 
 231                     changed 
|= mergePrediction(SpecString 
| SpecInt32 
| SpecBytecodeDouble
); 
 237             SpeculatedType left 
= node
->child1()->prediction(); 
 238             SpeculatedType right 
= node
->child2()->prediction(); 
 241                 if (m_graph
.addSpeculationMode(node
, m_pass
) != DontSpeculateInt32
) 
 242                     changed 
|= mergePrediction(SpecInt32
); 
 243                 else if (m_graph
.addShouldSpeculateMachineInt(node
)) 
 244                     changed 
|= mergePrediction(SpecInt52
); 
 246                     changed 
|= mergePrediction(speculatedDoubleTypeForPredictions(left
, right
)); 
 252             SpeculatedType left 
= node
->child1()->prediction(); 
 253             SpeculatedType right 
= node
->child2()->prediction(); 
 256                 if (m_graph
.addSpeculationMode(node
, m_pass
) != DontSpeculateInt32
) 
 257                     changed 
|= mergePrediction(SpecInt32
); 
 258                 else if (m_graph
.addShouldSpeculateMachineInt(node
)) 
 259                     changed 
|= mergePrediction(SpecInt52
); 
 261                     changed 
|= mergePrediction(speculatedDoubleTypeForPredictions(left
, right
)); 
 267             if (node
->child1()->prediction()) { 
 268                 if (m_graph
.negateShouldSpeculateInt32(node
, m_pass
)) 
 269                     changed 
|= mergePrediction(SpecInt32
); 
 270                 else if (m_graph
.negateShouldSpeculateMachineInt(node
, m_pass
)) 
 271                     changed 
|= mergePrediction(SpecInt52
); 
 273                     changed 
|= mergePrediction(speculatedDoubleTypeForPrediction(node
->child1()->prediction())); 
 279             SpeculatedType left 
= node
->child1()->prediction(); 
 280             SpeculatedType right 
= node
->child2()->prediction(); 
 283                 if (Node::shouldSpeculateInt32OrBooleanForArithmetic(node
->child1().node(), node
->child2().node()) 
 284                     && node
->canSpeculateInt32(m_pass
)) 
 285                     changed 
|= mergePrediction(SpecInt32
); 
 287                     changed 
|= mergePrediction(speculatedDoubleTypeForPredictions(left
, right
)); 
 293             SpeculatedType left 
= node
->child1()->prediction(); 
 294             SpeculatedType right 
= node
->child2()->prediction(); 
 297                 if (m_graph
.mulShouldSpeculateInt32(node
, m_pass
)) 
 298                     changed 
|= mergePrediction(SpecInt32
); 
 299                 else if (m_graph
.mulShouldSpeculateMachineInt(node
, m_pass
)) 
 300                     changed 
|= mergePrediction(SpecInt52
); 
 302                     changed 
|= mergePrediction(speculatedDoubleTypeForPredictions(left
, right
)); 
 308             SpeculatedType left 
= node
->child1()->prediction(); 
 309             SpeculatedType right 
= node
->child2()->prediction(); 
 312                 if (Node::shouldSpeculateInt32OrBooleanForArithmetic(node
->child1().node(), node
->child2().node()) 
 313                     && node
->canSpeculateInt32(m_pass
)) 
 314                     changed 
|= mergePrediction(SpecInt32
); 
 316                     changed 
|= mergePrediction(SpecBytecodeDouble
); 
 322             SpeculatedType left 
= node
->child1()->prediction(); 
 323             SpeculatedType right 
= node
->child2()->prediction(); 
 326                 if (Node::shouldSpeculateInt32OrBooleanForArithmetic(node
->child1().node(), node
->child2().node()) 
 327                     && node
->canSpeculateInt32(m_pass
)) 
 328                     changed 
|= mergePrediction(SpecInt32
); 
 330                     changed 
|= mergePrediction(SpecBytecodeDouble
); 
 339             changed 
|= setPrediction(SpecBytecodeDouble
); 
 344             SpeculatedType child 
= node
->child1()->prediction(); 
 345             if (isInt32OrBooleanSpeculationForArithmetic(child
) 
 346                 && node
->canSpeculateInt32(m_pass
)) 
 347                 changed 
|= mergePrediction(SpecInt32
); 
 349                 changed 
|= mergePrediction(speculatedDoubleTypeForPrediction(child
)); 
 357         case CompareGreaterEq
: 
 359         case CompareEqConstant
: 
 360         case CompareStrictEq
: 
 368             changed 
|= setPrediction(SpecBoolean
); 
 373             changed 
|= setPrediction(SpecString
); 
 378             if (!node
->child1()->prediction()) 
 381             ArrayMode arrayMode 
= node
->arrayMode().refine( 
 383                 node
->child1()->prediction(), 
 384                 node
->child2()->prediction(), 
 385                 SpecNone
, node
->flags()); 
 387             switch (arrayMode
.type()) { 
 389                 if (arrayMode
.isOutOfBounds()) 
 390                     changed 
|= mergePrediction(node
->getHeapPrediction() | SpecDoubleReal
); 
 392                     changed 
|= mergePrediction(SpecDoubleReal
); 
 394             case Array::Float32Array
: 
 395             case Array::Float64Array
: 
 396                 changed 
|= mergePrediction(SpecFullDouble
); 
 398             case Array::Uint32Array
: 
 399                 if (isInt32Speculation(node
->getHeapPrediction())) 
 400                     changed 
|= mergePrediction(SpecInt32
); 
 401                 else if (enableInt52()) 
 402                     changed 
|= mergePrediction(SpecMachineInt
); 
 404                     changed 
|= mergePrediction(SpecInt32 
| SpecInt52AsDouble
); 
 407                 changed 
|= mergePrediction(node
->getHeapPrediction()); 
 413         case GetMyArgumentsLengthSafe
: { 
 414             changed 
|= setPrediction(SpecInt32
); 
 418         case GetClosureRegisters
:             
 420         case GetIndexedPropertyStorage
: 
 421         case AllocatePropertyStorage
: 
 422         case ReallocatePropertyStorage
: { 
 423             changed 
|= setPrediction(SpecOther
); 
 428             SpeculatedType prediction 
= node
->child1()->prediction(); 
 430                 if (prediction 
& ~SpecObject
) { 
 431                     prediction 
&= SpecObject
; 
 432                     prediction 
= mergeSpeculations(prediction
, SpecObjectOther
); 
 434                 changed 
|= mergePrediction(prediction
); 
 442             changed 
|= setPrediction(SpecObjectOther
); 
 447             changed 
|= setPrediction(SpecFunction
); 
 453             changed 
|= setPrediction(SpecFinalObject
); 
 458         case NewArrayWithSize
: 
 459         case NewArrayBuffer
: { 
 460             changed 
|= setPrediction(SpecArray
); 
 464         case NewTypedArray
: { 
 465             changed 
|= setPrediction(speculationFromTypedArrayType(node
->typedArrayType())); 
 470         case CreateActivation
: { 
 471             changed 
|= setPrediction(SpecObjectOther
); 
 475         case StringFromCharCode
: { 
 476             changed 
|= setPrediction(SpecString
); 
 477             changed 
|= node
->child1()->mergeFlags(NodeBytecodeUsesAsNumber 
| NodeBytecodeUsesAsInt
);             
 483             changed 
|= setPrediction(SpecString
); 
 488             SpeculatedType child 
= node
->child1()->prediction(); 
 490                 changed 
|= mergePrediction(resultOfToPrimitive(child
)); 
 494         case NewStringObject
: { 
 495             changed 
|= setPrediction(SpecStringObject
); 
 499         case CreateArguments
: { 
 500             changed 
|= setPrediction(SpecArguments
); 
 505             SpeculatedType child 
= node
->child1()->prediction(); 
 506             if (child 
& SpecEmpty
) 
 507                 changed 
|= mergePrediction((child 
& ~SpecEmpty
) | SpecFunction
); 
 509                 changed 
|= mergePrediction(child
); 
 513         case NewFunctionNoCheck
: 
 514         case NewFunctionExpression
: { 
 515             changed 
|= setPrediction(SpecFunction
); 
 520             RELEASE_ASSERT(enableInt52()); 
 521             changed 
|= setPrediction(SpecMachineInt
); 
 527         case GetTypedArrayByteOffset
: 
 529         case GetLocalUnlinked
: 
 530         case GetMyArgumentsLength
: 
 531         case GetMyArgumentByVal
: 
 532         case PhantomPutStructure
: 
 533         case PhantomArguments
: 
 536         case ArrayifyToStructure
: 
 537         case CheckTierUpInLoop
: 
 538         case CheckTierUpAtReturn
: 
 539         case CheckTierUpAndOSREnter
: 
 540         case InvalidationPoint
: 
 550         case BooleanToNumber
: { 
 551             // This node should never be visible at this stage of compilation. It is 
 552             // inserted by fixup(), which follows this phase. 
 553             RELEASE_ASSERT_NOT_REACHED(); 
 558             // Phis should not be visible here since we're iterating the all-but-Phi's 
 559             // part of basic blocks. 
 560             RELEASE_ASSERT_NOT_REACHED(); 
 565             // These don't get inserted until we go into SSA. 
 566             RELEASE_ASSERT_NOT_REACHED(); 
 570             changed 
|= setPrediction(SpecObjectOther
); 
 574             changed 
|= setPrediction(SpecBoolean
); 
 578         // These get ignored because they don't return anything. 
 580         case StoreBarrierWithNullCheck
: 
 590         case MultiPutByOffset
: 
 595         case ProfileWillCall
: 
 597         case CheckHasInstance
: 
 598         case ThrowReferenceError
: 
 602         case CheckExecutable
: 
 603         case StructureTransitionWatchpoint
: 
 606         case TearOffActivation
: 
 607         case TearOffArguments
: 
 608         case CheckArgumentsNotCreated
: 
 609         case VariableWatchpoint
: 
 610         case VarInjectionWatchpoint
: 
 611         case AllocationProfileWatchpoint
: 
 615         case CheckWatchdogTimer
: 
 619         case FunctionReentryWatchpoint
: 
 620         case TypedArrayWatchpoint
: 
 621         case ConstantStoragePointer
: 
 626         // This gets ignored because it already has a prediction. 
 627         case ExtractOSREntryLocal
: 
 630         // These gets ignored because it doesn't do anything. 
 637             RELEASE_ASSERT_NOT_REACHED(); 
 645         m_changed 
|= changed
; 
 648     void propagateForward() 
 650         for (BlockIndex blockIndex 
= 0; blockIndex 
< m_graph
.numBlocks(); ++blockIndex
) { 
 651             BasicBlock
* block 
= m_graph
.block(blockIndex
); 
 654             ASSERT(block
->isReachable
); 
 655             for (unsigned i 
= 0; i 
< block
->size(); ++i
) { 
 656                 m_currentNode 
= block
->at(i
); 
 657                 propagate(m_currentNode
); 
 662     void propagateBackward() 
 664         for (BlockIndex blockIndex 
= m_graph
.numBlocks(); blockIndex
--;) { 
 665             BasicBlock
* block 
= m_graph
.block(blockIndex
); 
 668             ASSERT(block
->isReachable
); 
 669             for (unsigned i 
= block
->size(); i
--;) { 
 670                 m_currentNode 
= block
->at(i
); 
 671                 propagate(m_currentNode
); 
 676     void doDoubleVoting(Node
* node
, float weight
) 
 678         // Loop pre-headers created by OSR entrypoint creation may have NaN weight to indicate 
 679         // that we actually don't know they weight. Assume that they execute once. This turns 
 680         // out to be an OK assumption since the pre-header doesn't have any meaningful code. 
 681         if (weight 
!= weight
) 
 684         switch (node
->op()) { 
 688             SpeculatedType left 
= node
->child1()->prediction(); 
 689             SpeculatedType right 
= node
->child2()->prediction(); 
 693             if (isFullNumberSpeculation(left
) 
 694                 && isFullNumberSpeculation(right
) 
 695                 && !m_graph
.addShouldSpeculateInt32(node
, m_pass
) 
 696                 && !m_graph
.addShouldSpeculateMachineInt(node
)) 
 701             m_graph
.voteNode(node
->child1(), ballot
, weight
); 
 702             m_graph
.voteNode(node
->child2(), ballot
, weight
); 
 707             SpeculatedType left 
= node
->child1()->prediction(); 
 708             SpeculatedType right 
= node
->child2()->prediction(); 
 712             if (isFullNumberSpeculation(left
) 
 713                 && isFullNumberSpeculation(right
) 
 714                 && !m_graph
.mulShouldSpeculateInt32(node
, m_pass
) 
 715                 && !m_graph
.mulShouldSpeculateMachineInt(node
, m_pass
)) 
 720             m_graph
.voteNode(node
->child1(), ballot
, weight
); 
 721             m_graph
.voteNode(node
->child2(), ballot
, weight
); 
 729             SpeculatedType left 
= node
->child1()->prediction(); 
 730             SpeculatedType right 
= node
->child2()->prediction(); 
 734             if (isFullNumberSpeculation(left
) 
 735                 && isFullNumberSpeculation(right
) 
 736                 && !(Node::shouldSpeculateInt32OrBooleanForArithmetic(node
->child1().node(), node
->child2().node()) && node
->canSpeculateInt32(m_pass
))) 
 741             m_graph
.voteNode(node
->child1(), ballot
, weight
); 
 742             m_graph
.voteNode(node
->child2(), ballot
, weight
); 
 748             if (node
->child1()->shouldSpeculateNumber() 
 749                 && !(node
->child1()->shouldSpeculateInt32OrBooleanForArithmetic() && node
->canSpeculateInt32(m_pass
))) 
 754             m_graph
.voteNode(node
->child1(), ballot
, weight
); 
 760             if (node
->child1()->shouldSpeculateNumber()) 
 761                 m_graph
.voteNode(node
->child1(), VoteDouble
, weight
); 
 763                 m_graph
.voteNode(node
->child1(), VoteValue
, weight
); 
 767             SpeculatedType prediction 
= node
->child1()->prediction(); 
 768             if (isDoubleSpeculation(prediction
)) 
 769                 node
->variableAccessData()->vote(VoteDouble
, weight
); 
 771                 !isFullNumberSpeculation(prediction
) 
 772                 || isInt32Speculation(prediction
) || isMachineIntSpeculation(prediction
)) 
 773                 node
->variableAccessData()->vote(VoteValue
, weight
); 
 779         case PutByValAlias
: { 
 780             Edge child1 
= m_graph
.varArgChild(node
, 0); 
 781             Edge child2 
= m_graph
.varArgChild(node
, 1); 
 782             Edge child3 
= m_graph
.varArgChild(node
, 2); 
 783             m_graph
.voteNode(child1
, VoteValue
, weight
); 
 784             m_graph
.voteNode(child2
, VoteValue
, weight
); 
 785             switch (node
->arrayMode().type()) { 
 787                 m_graph
.voteNode(child3
, VoteDouble
, weight
); 
 790                 m_graph
.voteNode(child3
, VoteValue
, weight
); 
 797             // Ignore these since they have no effect on in-DFG execution. 
 801             m_graph
.voteChildren(node
, VoteValue
, weight
); 
 806     void doRoundOfDoubleVoting() 
 808         for (unsigned i 
= 0; i 
< m_graph
.m_variableAccessData
.size(); ++i
) 
 809             m_graph
.m_variableAccessData
[i
].find()->clearVotes(); 
 810         for (BlockIndex blockIndex 
= 0; blockIndex 
< m_graph
.numBlocks(); ++blockIndex
) { 
 811             BasicBlock
* block 
= m_graph
.block(blockIndex
); 
 814             ASSERT(block
->isReachable
); 
 815             for (unsigned i 
= 0; i 
< block
->size(); ++i
) { 
 816                 m_currentNode 
= block
->at(i
); 
 817                 doDoubleVoting(m_currentNode
, block
->executionCount
); 
 820         for (unsigned i 
= 0; i 
< m_graph
.m_variableAccessData
.size(); ++i
) { 
 821             VariableAccessData
* variableAccessData 
= &m_graph
.m_variableAccessData
[i
]; 
 822             if (!variableAccessData
->isRoot()) 
 824             m_changed 
|= variableAccessData
->tallyVotesForShouldUseDoubleFormat(); 
 826         for (unsigned i 
= 0; i 
< m_graph
.m_argumentPositions
.size(); ++i
) 
 827             m_changed 
|= m_graph
.m_argumentPositions
[i
].mergeArgumentPredictionAwareness(); 
 828         for (unsigned i 
= 0; i 
< m_graph
.m_variableAccessData
.size(); ++i
) { 
 829             VariableAccessData
* variableAccessData 
= &m_graph
.m_variableAccessData
[i
]; 
 830             if (!variableAccessData
->isRoot()) 
 832             m_changed 
|= variableAccessData
->makePredictionForDoubleFormat(); 
 838     PredictionPass m_pass
; // We use different logic for considering predictions depending on how far along we are in propagation. 
 841 bool performPredictionPropagation(Graph
& graph
) 
 843     SamplingRegion 
samplingRegion("DFG Prediction Propagation Phase"); 
 844     return runPhase
<PredictionPropagationPhase
>(graph
); 
 847 } } // namespace JSC::DFG 
 849 #endif // ENABLE(DFG_JIT)