2  * Copyright (C) 2011, 2012, 2013 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 "Operations.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
); 
  60 #if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE) 
  63         // 1) propagate predictions 
  68             // Forward propagation is near-optimal for both topologically-sorted and 
  74             // Backward propagation reduces the likelihood that pathological code will 
  75             // cause slowness. Loops (especially nested ones) resemble backward flow. 
  76             // This pass captures two cases: (1) it detects if the forward fixpoint 
  77             // found a sound solution and (2) short-circuits backward flow. 
  82         // 2) repropagate predictions while doing double voting. 
  86             doRoundOfDoubleVoting(); 
  97     bool setPrediction(SpeculatedType prediction
) 
  99         ASSERT(m_currentNode
->hasResult()); 
 101         // setPrediction() is used when we know that there is no way that we can change 
 102         // our minds about what the prediction is going to be. There is no semantic 
 103         // difference between setPrediction() and mergeSpeculation() other than the 
 104         // increased checking to validate this property. 
 105         ASSERT(m_currentNode
->prediction() == SpecNone 
|| m_currentNode
->prediction() == prediction
); 
 107         return m_currentNode
->predict(prediction
); 
 110     bool mergePrediction(SpeculatedType prediction
) 
 112         ASSERT(m_currentNode
->hasResult()); 
 114         return m_currentNode
->predict(prediction
); 
 117     SpeculatedType 
speculatedDoubleTypeForPrediction(SpeculatedType value
) 
 119         if (!isNumberSpeculation(value
)) 
 121         if (value 
& SpecDoubleNaN
) 
 123         return SpecDoubleReal
; 
 126     SpeculatedType 
speculatedDoubleTypeForPredictions(SpeculatedType left
, SpeculatedType right
) 
 128         return speculatedDoubleTypeForPrediction(mergeSpeculations(left
, right
)); 
 131     void propagate(Node
* node
) 
 133         NodeType op 
= node
->op(); 
 135 #if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE) 
 136         dataLog("   ", Graph::opName(op
), " ", m_currentNode
, ": ", NodeFlagsDump(node
->flags()), " "); 
 139         bool changed 
= false; 
 143         case WeakJSConstant
: { 
 144             changed 
|= setPrediction(speculationFromValue(m_graph
.valueOfJSConstant(node
))); 
 149             VariableAccessData
* variableAccessData 
= node
->variableAccessData(); 
 150             SpeculatedType prediction 
= variableAccessData
->prediction(); 
 152                 changed 
|= mergePrediction(prediction
); 
 157             VariableAccessData
* variableAccessData 
= node
->variableAccessData(); 
 158             changed 
|= variableAccessData
->predict(node
->child1()->prediction()); 
 169             changed 
|= setPrediction(SpecInt32
); 
 174             changed 
|= setPrediction(SpecInt32
); 
 184         case GetMyArgumentByValSafe
: 
 192         case ResolveBaseStrictPut
: 
 193         case ResolveGlobal
: { 
 194             changed 
|= setPrediction(node
->getHeapPrediction()); 
 198         case StringCharCodeAt
: { 
 199             changed 
|= setPrediction(SpecInt32
); 
 203         case UInt32ToNumber
: { 
 204             if (nodeCanSpeculateInteger(node
->arithNodeFlags())) 
 205                 changed 
|= mergePrediction(SpecInt32
); 
 207                 changed 
|= mergePrediction(SpecNumber
); 
 212             SpeculatedType left 
= node
->child1()->prediction(); 
 213             SpeculatedType right 
= node
->child2()->prediction(); 
 216                 if (isNumberSpeculationExpectingDefined(left
) && isNumberSpeculationExpectingDefined(right
)) { 
 217                     if (m_graph
.addSpeculationMode(node
) != DontSpeculateInteger
) 
 218                         changed 
|= mergePrediction(SpecInt32
); 
 220                         changed 
|= mergePrediction(speculatedDoubleTypeForPredictions(left
, right
)); 
 221                 } else if (!(left 
& SpecNumber
) || !(right 
& SpecNumber
)) { 
 222                     // left or right is definitely something other than a number. 
 223                     changed 
|= mergePrediction(SpecString
); 
 225                     changed 
|= mergePrediction(SpecString 
| SpecInt32 
| SpecDouble
); 
 231             SpeculatedType left 
= node
->child1()->prediction(); 
 232             SpeculatedType right 
= node
->child2()->prediction(); 
 235                 if (m_graph
.addSpeculationMode(node
) != DontSpeculateInteger
) 
 236                     changed 
|= mergePrediction(SpecInt32
); 
 238                     changed 
|= mergePrediction(speculatedDoubleTypeForPredictions(left
, right
)); 
 244             SpeculatedType left 
= node
->child1()->prediction(); 
 245             SpeculatedType right 
= node
->child2()->prediction(); 
 248                 if (m_graph
.addSpeculationMode(node
) != DontSpeculateInteger
) 
 249                     changed 
|= mergePrediction(SpecInt32
); 
 251                     changed 
|= mergePrediction(speculatedDoubleTypeForPredictions(left
, right
)); 
 257             if (node
->child1()->prediction()) { 
 258                 if (m_graph
.negateShouldSpeculateInteger(node
)) 
 259                     changed 
|= mergePrediction(SpecInt32
); 
 261                     changed 
|= mergePrediction(speculatedDoubleTypeForPrediction(node
->child1()->prediction())); 
 267             SpeculatedType left 
= node
->child1()->prediction(); 
 268             SpeculatedType right 
= node
->child2()->prediction(); 
 271                 if (Node::shouldSpeculateIntegerForArithmetic(node
->child1().node(), node
->child2().node()) 
 272                     && nodeCanSpeculateInteger(node
->arithNodeFlags())) 
 273                     changed 
|= mergePrediction(SpecInt32
); 
 275                     changed 
|= mergePrediction(speculatedDoubleTypeForPredictions(left
, right
)); 
 281             SpeculatedType left 
= node
->child1()->prediction(); 
 282             SpeculatedType right 
= node
->child2()->prediction(); 
 285                 if (m_graph
.mulShouldSpeculateInteger(node
)) 
 286                     changed 
|= mergePrediction(SpecInt32
); 
 288                     changed 
|= mergePrediction(speculatedDoubleTypeForPredictions(left
, right
)); 
 294             SpeculatedType left 
= node
->child1()->prediction(); 
 295             SpeculatedType right 
= node
->child2()->prediction(); 
 298                 if (Node::shouldSpeculateIntegerForArithmetic(node
->child1().node(), node
->child2().node()) 
 299                     && nodeCanSpeculateInteger(node
->arithNodeFlags())) 
 300                     changed 
|= mergePrediction(SpecInt32
); 
 302                     changed 
|= mergePrediction(SpecDouble
); 
 308             SpeculatedType left 
= node
->child1()->prediction(); 
 309             SpeculatedType right 
= node
->child2()->prediction(); 
 312                 if (Node::shouldSpeculateIntegerForArithmetic(node
->child1().node(), node
->child2().node()) 
 313                     && nodeCanSpeculateInteger(node
->arithNodeFlags())) 
 314                     changed 
|= mergePrediction(SpecInt32
); 
 316                     changed 
|= mergePrediction(SpecDouble
); 
 322             changed 
|= setPrediction(SpecDouble
); 
 327             SpeculatedType child 
= node
->child1()->prediction(); 
 328             if (isInt32SpeculationForArithmetic(child
) 
 329                 && nodeCanSpeculateInteger(node
->arithNodeFlags())) 
 330                 changed 
|= mergePrediction(SpecInt32
); 
 332                 changed 
|= mergePrediction(speculatedDoubleTypeForPrediction(child
)); 
 340         case CompareGreaterEq
: 
 342         case CompareEqConstant
: 
 343         case CompareStrictEq
: 
 344         case CompareStrictEqConstant
: 
 352             changed 
|= setPrediction(SpecBoolean
); 
 357             changed 
|= setPrediction(SpecString
); 
 362             if (node
->child1()->shouldSpeculateFloat32Array() 
 363                 || node
->child1()->shouldSpeculateFloat64Array()) 
 364                 changed 
|= mergePrediction(SpecDouble
); 
 366                 changed 
|= mergePrediction(node
->getHeapPrediction()); 
 370         case GetMyArgumentsLengthSafe
: { 
 371             changed 
|= setPrediction(SpecInt32
); 
 375         case GetScopeRegisters
:             
 377         case GetIndexedPropertyStorage
: 
 378         case AllocatePropertyStorage
: 
 379         case ReallocatePropertyStorage
: { 
 380             changed 
|= setPrediction(SpecOther
); 
 385             SpeculatedType prediction 
= node
->child1()->prediction(); 
 387                 if (prediction 
& ~SpecObject
) { 
 388                     prediction 
&= SpecObject
; 
 389                     prediction 
= mergeSpeculations(prediction
, SpecObjectOther
); 
 391                 changed 
|= mergePrediction(prediction
); 
 399             changed 
|= setPrediction(SpecObjectOther
); 
 404             changed 
|= setPrediction(SpecFunction
); 
 410             changed 
|= setPrediction(SpecFinalObject
); 
 415         case NewArrayWithSize
: 
 416         case NewArrayBuffer
: { 
 417             changed 
|= setPrediction(SpecArray
); 
 422         case CreateActivation
: { 
 423             changed 
|= setPrediction(SpecObjectOther
); 
 427         case StringFromCharCode
: { 
 428             changed 
|= setPrediction(SpecString
); 
 429             changed 
|= node
->child1()->mergeFlags(NodeUsedAsNumber 
| NodeUsedAsInt
);             
 435             changed 
|= setPrediction(SpecString
); 
 440             SpeculatedType child 
= node
->child1()->prediction(); 
 442                 changed 
|= mergePrediction(resultOfToPrimitive(child
)); 
 446         case NewStringObject
: { 
 447             changed 
|= setPrediction(SpecStringObject
); 
 451         case CreateArguments
: { 
 452             changed 
|= setPrediction(SpecArguments
); 
 457             SpeculatedType child 
= node
->child1()->prediction(); 
 458             if (child 
& SpecEmpty
) 
 459                 changed 
|= mergePrediction((child 
& ~SpecEmpty
) | SpecFunction
); 
 461                 changed 
|= mergePrediction(child
); 
 465         case NewFunctionNoCheck
: 
 466         case NewFunctionExpression
: { 
 467             changed 
|= setPrediction(SpecFunction
); 
 474         case ForwardInt32ToDouble
: 
 476         case GetLocalUnlinked
: 
 477         case GetMyArgumentsLength
: 
 478         case GetMyArgumentByVal
: 
 479         case PhantomPutStructure
: 
 480         case PhantomArguments
: 
 483         case ArrayifyToStructure
: 
 485         case MovHintAndCheck
: 
 487             // This node should never be visible at this stage of compilation. It is 
 488             // inserted by fixup(), which follows this phase. 
 494             // Phis should not be visible here since we're iterating the all-but-Phi's 
 495             // part of basic blocks. 
 500             changed 
|= setPrediction(SpecObjectOther
); 
 504             changed 
|= mergePrediction(node
->child1()->prediction()); 
 508         // These get ignored because they don't return anything. 
 521         case CheckHasInstance
: 
 522         case ThrowReferenceError
: 
 526         case CheckExecutable
: 
 527         case ForwardCheckStructure
: 
 528         case StructureTransitionWatchpoint
: 
 529         case ForwardStructureTransitionWatchpoint
: 
 532         case TearOffActivation
: 
 533         case TearOffArguments
: 
 534         case CheckArgumentsNotCreated
: 
 535         case GlobalVarWatchpoint
: 
 537         case AllocationProfileWatchpoint
: 
 540         case PutGlobalVarCheck
: 
 541         case CheckWatchdogTimer
: 
 544         // These gets ignored because it doesn't do anything. 
 561 #if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE) 
 562         dataLog(SpeculationDump(node
->prediction()), "\n"); 
 565         m_changed 
|= changed
; 
 568     void propagateForward() 
 570 #if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE) 
 571         dataLogF("Propagating predictions forward [%u]\n", ++m_count
); 
 573         for (BlockIndex blockIndex 
= 0; blockIndex 
< m_graph
.m_blocks
.size(); ++blockIndex
) { 
 574             BasicBlock
* block 
= m_graph
.m_blocks
[blockIndex
].get(); 
 577             ASSERT(block
->isReachable
); 
 578             for (unsigned i 
= 0; i 
< block
->size(); ++i
) { 
 579                 m_currentNode 
= block
->at(i
); 
 580                 propagate(m_currentNode
); 
 585     void propagateBackward() 
 587 #if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE) 
 588         dataLogF("Propagating predictions backward [%u]\n", ++m_count
); 
 590         for (BlockIndex blockIndex 
= m_graph
.m_blocks
.size(); blockIndex
--;) { 
 591             BasicBlock
* block 
= m_graph
.m_blocks
[blockIndex
].get(); 
 594             ASSERT(block
->isReachable
); 
 595             for (unsigned i 
= block
->size(); i
--;) { 
 596                 m_currentNode 
= block
->at(i
); 
 597                 propagate(m_currentNode
); 
 602     void doDoubleVoting(Node
* node
) 
 604         switch (node
->op()) { 
 608             SpeculatedType left 
= node
->child1()->prediction(); 
 609             SpeculatedType right 
= node
->child2()->prediction(); 
 613             if (isNumberSpeculationExpectingDefined(left
) && isNumberSpeculationExpectingDefined(right
) 
 614                 && !m_graph
.addShouldSpeculateInteger(node
)) 
 619             m_graph
.voteNode(node
->child1(), ballot
); 
 620             m_graph
.voteNode(node
->child2(), ballot
); 
 625             SpeculatedType left 
= node
->child1()->prediction(); 
 626             SpeculatedType right 
= node
->child2()->prediction(); 
 630             if (isNumberSpeculation(left
) && isNumberSpeculation(right
) 
 631                 && !m_graph
.mulShouldSpeculateInteger(node
)) 
 636             m_graph
.voteNode(node
->child1(), ballot
); 
 637             m_graph
.voteNode(node
->child2(), ballot
); 
 645             SpeculatedType left 
= node
->child1()->prediction(); 
 646             SpeculatedType right 
= node
->child2()->prediction(); 
 650             if (isNumberSpeculation(left
) && isNumberSpeculation(right
) 
 651                 && !(Node::shouldSpeculateIntegerForArithmetic(node
->child1().node(), node
->child2().node()) && node
->canSpeculateInteger())) 
 656             m_graph
.voteNode(node
->child1(), ballot
); 
 657             m_graph
.voteNode(node
->child2(), ballot
); 
 663             if (!(node
->child1()->shouldSpeculateIntegerForArithmetic() && node
->canSpeculateInteger())) 
 668             m_graph
.voteNode(node
->child1(), ballot
); 
 672             m_graph
.voteNode(node
->child1(), VoteDouble
); 
 676             SpeculatedType prediction 
= node
->child1()->prediction(); 
 677             if (isDoubleSpeculation(prediction
)) 
 678                 node
->variableAccessData()->vote(VoteDouble
); 
 679             else if (!isNumberSpeculation(prediction
) || isInt32Speculation(prediction
)) 
 680                 node
->variableAccessData()->vote(VoteValue
); 
 685         case PutByValAlias
: { 
 686             Edge child1 
= m_graph
.varArgChild(node
, 0); 
 687             Edge child2 
= m_graph
.varArgChild(node
, 1); 
 688             Edge child3 
= m_graph
.varArgChild(node
, 2); 
 689             m_graph
.voteNode(child1
, VoteValue
); 
 690             m_graph
.voteNode(child2
, VoteValue
); 
 691             switch (node
->arrayMode().type()) { 
 693                 m_graph
.voteNode(child3
, VoteDouble
); 
 696                 m_graph
.voteNode(child3
, VoteValue
); 
 703             m_graph
.voteChildren(node
, VoteValue
); 
 708     void doRoundOfDoubleVoting() 
 710 #if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE) 
 711         dataLogF("Voting on double uses of locals [%u]\n", m_count
); 
 713         for (unsigned i 
= 0; i 
< m_graph
.m_variableAccessData
.size(); ++i
) 
 714             m_graph
.m_variableAccessData
[i
].find()->clearVotes(); 
 715         for (BlockIndex blockIndex 
= 0; blockIndex 
< m_graph
.m_blocks
.size(); ++blockIndex
) { 
 716             BasicBlock
* block 
= m_graph
.m_blocks
[blockIndex
].get(); 
 719             ASSERT(block
->isReachable
); 
 720             for (unsigned i 
= 0; i 
< block
->size(); ++i
) { 
 721                 m_currentNode 
= block
->at(i
); 
 722                 doDoubleVoting(m_currentNode
); 
 725         for (unsigned i 
= 0; i 
< m_graph
.m_variableAccessData
.size(); ++i
) { 
 726             VariableAccessData
* variableAccessData 
= &m_graph
.m_variableAccessData
[i
]; 
 727             if (!variableAccessData
->isRoot()) 
 729             m_changed 
|= variableAccessData
->tallyVotesForShouldUseDoubleFormat(); 
 731         for (unsigned i 
= 0; i 
< m_graph
.m_argumentPositions
.size(); ++i
) 
 732             m_changed 
|= m_graph
.m_argumentPositions
[i
].mergeArgumentPredictionAwareness(); 
 733         for (unsigned i 
= 0; i 
< m_graph
.m_variableAccessData
.size(); ++i
) { 
 734             VariableAccessData
* variableAccessData 
= &m_graph
.m_variableAccessData
[i
]; 
 735             if (!variableAccessData
->isRoot()) 
 737             m_changed 
|= variableAccessData
->makePredictionForDoubleFormat(); 
 744 #if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE) 
 749 bool performPredictionPropagation(Graph
& graph
) 
 751     SamplingRegion 
samplingRegion("DFG Prediction Propagation Phase"); 
 752     return runPhase
<PredictionPropagationPhase
>(graph
); 
 755 } } // namespace JSC::DFG 
 757 #endif // ENABLE(DFG_JIT)