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 "DFGAbstractState.h" 
  31 #include "CodeBlock.h" 
  32 #include "DFGBasicBlock.h" 
  33 #include "GetByIdStatus.h" 
  34 #include "Operations.h" 
  35 #include "PutByIdStatus.h" 
  36 #include "StringObject.h" 
  38 namespace JSC 
{ namespace DFG 
{ 
  40 AbstractState::AbstractState(Graph
& graph
) 
  41     : m_codeBlock(graph
.m_codeBlock
) 
  43     , m_variables(m_codeBlock
->numParameters(), graph
.m_localVars
) 
  48 AbstractState::~AbstractState() { } 
  50 void AbstractState::beginBasicBlock(BasicBlock
* basicBlock
) 
  54     ASSERT(basicBlock
->variablesAtHead
.numberOfLocals() == basicBlock
->valuesAtHead
.numberOfLocals()); 
  55     ASSERT(basicBlock
->variablesAtTail
.numberOfLocals() == basicBlock
->valuesAtTail
.numberOfLocals()); 
  56     ASSERT(basicBlock
->variablesAtHead
.numberOfLocals() == basicBlock
->variablesAtTail
.numberOfLocals()); 
  58     for (size_t i 
= 0; i 
< basicBlock
->size(); i
++) 
  59         forNode(basicBlock
->at(i
)).clear(); 
  61     m_variables 
= basicBlock
->valuesAtHead
; 
  62     m_haveStructures 
= false; 
  63     for (size_t i 
= 0; i 
< m_variables
.numberOfArguments(); ++i
) { 
  64         if (m_variables
.argument(i
).m_currentKnownStructure
.isNeitherClearNorTop()) { 
  65             m_haveStructures 
= true; 
  69     for (size_t i 
= 0; i 
< m_variables
.numberOfLocals(); ++i
) { 
  70         if (m_variables
.local(i
).m_currentKnownStructure
.isNeitherClearNorTop()) { 
  71             m_haveStructures 
= true; 
  76     basicBlock
->cfaShouldRevisit 
= false; 
  77     basicBlock
->cfaHasVisited 
= true; 
  80     m_foundConstants 
= false; 
  81     m_branchDirection 
= InvalidBranchDirection
; 
  84 void AbstractState::initialize(Graph
& graph
) 
  86     BasicBlock
* root 
= graph
.m_blocks
[0].get(); 
  87     root
->cfaShouldRevisit 
= true; 
  88     root
->cfaHasVisited 
= false; 
  89     root
->cfaFoundConstants 
= false; 
  90     for (size_t i 
= 0; i 
< root
->valuesAtHead
.numberOfArguments(); ++i
) { 
  91         Node
* node 
= root
->variablesAtHead
.argument(i
); 
  92         ASSERT(node
->op() == SetArgument
); 
  93         if (!node
->variableAccessData()->shouldUnboxIfPossible()) { 
  94             root
->valuesAtHead
.argument(i
).makeTop(); 
  98         SpeculatedType prediction 
= node
->variableAccessData()->prediction(); 
  99         if (isInt32Speculation(prediction
)) 
 100             root
->valuesAtHead
.argument(i
).set(SpecInt32
); 
 101         else if (isBooleanSpeculation(prediction
)) 
 102             root
->valuesAtHead
.argument(i
).set(SpecBoolean
); 
 103         else if (isCellSpeculation(prediction
)) 
 104             root
->valuesAtHead
.argument(i
).set(SpecCell
); 
 106             root
->valuesAtHead
.argument(i
).makeTop(); 
 108         root
->valuesAtTail
.argument(i
).clear(); 
 110     for (size_t i 
= 0; i 
< root
->valuesAtHead
.numberOfLocals(); ++i
) { 
 111         Node
* node 
= root
->variablesAtHead
.local(i
); 
 112         if (node 
&& node
->variableAccessData()->isCaptured()) 
 113             root
->valuesAtHead
.local(i
).makeTop(); 
 115             root
->valuesAtHead
.local(i
).clear(); 
 116         root
->valuesAtTail
.local(i
).clear(); 
 118     for (BlockIndex blockIndex 
= 1 ; blockIndex 
< graph
.m_blocks
.size(); ++blockIndex
) { 
 119         BasicBlock
* block 
= graph
.m_blocks
[blockIndex
].get(); 
 122         if (!block
->isReachable
) 
 124         block
->cfaShouldRevisit 
= false; 
 125         block
->cfaHasVisited 
= false; 
 126         block
->cfaFoundConstants 
= false; 
 127         for (size_t i 
= 0; i 
< block
->valuesAtHead
.numberOfArguments(); ++i
) { 
 128             block
->valuesAtHead
.argument(i
).clear(); 
 129             block
->valuesAtTail
.argument(i
).clear(); 
 131         for (size_t i 
= 0; i 
< block
->valuesAtHead
.numberOfLocals(); ++i
) { 
 132             block
->valuesAtHead
.local(i
).clear(); 
 133             block
->valuesAtTail
.local(i
).clear(); 
 135         if (!block
->isOSRTarget
) 
 137         if (block
->bytecodeBegin 
!= graph
.m_osrEntryBytecodeIndex
) 
 139         for (size_t i 
= 0; i 
< graph
.m_mustHandleValues
.size(); ++i
) { 
 141             value
.setMostSpecific(graph
.m_mustHandleValues
[i
]); 
 142             int operand 
= graph
.m_mustHandleValues
.operandForIndex(i
); 
 143             block
->valuesAtHead
.operand(operand
).merge(value
); 
 144 #if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE) 
 145             dataLogF("    Initializing Block #%u, operand r%d, to ", blockIndex
, operand
); 
 146             block
->valuesAtHead
.operand(operand
).dump(WTF::dataFile()); 
 150         block
->cfaShouldRevisit 
= true; 
 154 bool AbstractState::endBasicBlock(MergeMode mergeMode
) 
 158     BasicBlock
* block 
= m_block
; // Save the block for successor merging. 
 160     block
->cfaFoundConstants 
= m_foundConstants
; 
 161     block
->cfaDidFinish 
= m_isValid
; 
 162     block
->cfaBranchDirection 
= m_branchDirection
; 
 169     bool changed 
= false; 
 171     if (mergeMode 
!= DontMerge 
|| !ASSERT_DISABLED
) { 
 172         for (size_t argument 
= 0; argument 
< block
->variablesAtTail
.numberOfArguments(); ++argument
) { 
 173 #if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE) 
 174             dataLogF("        Merging state for argument %zu.\n", argument
); 
 176             AbstractValue
& destination 
= block
->valuesAtTail
.argument(argument
); 
 177             changed 
|= mergeStateAtTail(destination
, m_variables
.argument(argument
), block
->variablesAtTail
.argument(argument
)); 
 180         for (size_t local 
= 0; local 
< block
->variablesAtTail
.numberOfLocals(); ++local
) { 
 181 #if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE) 
 182             dataLogF("        Merging state for local %zu.\n", local
); 
 184             AbstractValue
& destination 
= block
->valuesAtTail
.local(local
); 
 185             changed 
|= mergeStateAtTail(destination
, m_variables
.local(local
), block
->variablesAtTail
.local(local
)); 
 189     ASSERT(mergeMode 
!= DontMerge 
|| !changed
); 
 191 #if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE) 
 192     dataLogF("        Branch direction = %s\n", branchDirectionToString(m_branchDirection
)); 
 197     if (mergeMode 
!= MergeToSuccessors
) 
 200     return mergeToSuccessors(m_graph
, block
); 
 203 void AbstractState::reset() 
 207     m_branchDirection 
= InvalidBranchDirection
; 
 210 AbstractState::BooleanResult 
AbstractState::booleanResult(Node
* node
, AbstractValue
& value
) 
 212     JSValue childConst 
= value
.value(); 
 214         if (childConst
.toBoolean(m_codeBlock
->globalObjectFor(node
->codeOrigin
)->globalExec())) 
 215             return DefinitelyTrue
; 
 216         return DefinitelyFalse
; 
 219     // Next check if we can fold because we know that the source is an object or string and does not equal undefined. 
 220     if (isCellSpeculation(value
.m_type
) 
 221         && value
.m_currentKnownStructure
.hasSingleton()) { 
 222         Structure
* structure 
= value
.m_currentKnownStructure
.singleton(); 
 223         if (!structure
->masqueradesAsUndefined(m_codeBlock
->globalObjectFor(node
->codeOrigin
)) 
 224             && structure
->typeInfo().type() != StringType
) 
 225             return DefinitelyTrue
; 
 228     return UnknownBooleanResult
; 
 231 bool AbstractState::startExecuting(Node
* node
) 
 236     m_didClobber 
= false; 
 238     node
->setCanExit(false); 
 240     if (!node
->shouldGenerate()) 
 246 bool AbstractState::startExecuting(unsigned indexInBlock
) 
 248     return startExecuting(m_block
->at(indexInBlock
)); 
 251 void AbstractState::executeEdges(Node
* node
) 
 253     DFG_NODE_DO_TO_CHILDREN(m_graph
, node
, filterEdgeByUse
); 
 256 void AbstractState::executeEdges(unsigned indexInBlock
) 
 258     executeEdges(m_block
->at(indexInBlock
)); 
 261 void AbstractState::verifyEdge(Node
*, Edge edge
) 
 263     RELEASE_ASSERT(!(forNode(edge
).m_type 
& ~typeFilterFor(edge
.useKind()))); 
 266 void AbstractState::verifyEdges(Node
* node
) 
 268     DFG_NODE_DO_TO_CHILDREN(m_graph
, node
, verifyEdge
); 
 271 bool AbstractState::executeEffects(unsigned indexInBlock
, Node
* node
) 
 273     if (!ASSERT_DISABLED
) 
 276     switch (node
->op()) { 
 279     case PhantomArguments
: { 
 280         forNode(node
).set(m_graph
.valueOfJSConstant(node
)); 
 285         forNode(node
) = forNode(node
->child1()); 
 290         VariableAccessData
* variableAccessData 
= node
->variableAccessData(); 
 291         if (variableAccessData
->prediction() == SpecNone
) { 
 295         AbstractValue value 
= m_variables
.operand(variableAccessData
->local()); 
 296         if (!variableAccessData
->isCaptured()) { 
 298                 node
->setCanExit(true); 
 301             m_foundConstants 
= true; 
 302         forNode(node
) = value
; 
 306     case GetLocalUnlinked
: { 
 307         AbstractValue value 
= m_variables
.operand(node
->unlinkedLocal()); 
 309             m_foundConstants 
= true; 
 310         forNode(node
) = value
; 
 315         m_variables
.operand(node
->local()) = forNode(node
->child1()); 
 319     case MovHintAndCheck
: { 
 320         // Don't need to do anything. A MovHint is effectively a promise that the SetLocal 
 327         RELEASE_ASSERT_NOT_REACHED(); 
 332         // Assert that the state of arguments has been set. 
 333         ASSERT(!m_block
->valuesAtHead
.operand(node
->local()).isClear()); 
 342         JSValue left 
= forNode(node
->child1()).value(); 
 343         JSValue right 
= forNode(node
->child2()).value(); 
 344         if (left 
&& right 
&& left
.isInt32() && right
.isInt32()) { 
 345             int32_t a 
= left
.asInt32(); 
 346             int32_t b 
= right
.asInt32(); 
 348             switch (node
->op()) { 
 350                 constantWasSet 
= trySetConstant(node
, JSValue(a 
& b
)); 
 353                 constantWasSet 
= trySetConstant(node
, JSValue(a 
| b
)); 
 356                 constantWasSet 
= trySetConstant(node
, JSValue(a 
^ b
)); 
 359                 constantWasSet 
= trySetConstant(node
, JSValue(a 
>> static_cast<uint32_t>(b
))); 
 362                 constantWasSet 
= trySetConstant(node
, JSValue(a 
<< static_cast<uint32_t>(b
))); 
 365                 constantWasSet 
= trySetConstant(node
, JSValue(static_cast<uint32_t>(a
) >> static_cast<uint32_t>(b
))); 
 368                 RELEASE_ASSERT_NOT_REACHED(); 
 369                 constantWasSet 
= false; 
 371             if (constantWasSet
) { 
 372                 m_foundConstants 
= true; 
 376         forNode(node
).set(SpecInt32
); 
 380     case UInt32ToNumber
: { 
 381         JSValue child 
= forNode(node
->child1()).value(); 
 382         if (child 
&& child
.isNumber()) { 
 383             ASSERT(child
.isInt32()); 
 384             if (trySetConstant(node
, JSValue(child
.asUInt32()))) { 
 385                 m_foundConstants 
= true; 
 389         if (!node
->canSpeculateInteger()) 
 390             forNode(node
).set(SpecDouble
); 
 392             forNode(node
).set(SpecInt32
); 
 393             node
->setCanExit(true); 
 398     case DoubleAsInt32
: { 
 399         JSValue child 
= forNode(node
->child1()).value(); 
 400         if (child 
&& child
.isNumber()) { 
 401             double asDouble 
= child
.asNumber(); 
 402             int32_t asInt 
= JSC::toInt32(asDouble
); 
 403             if (bitwise_cast
<int64_t>(static_cast<double>(asInt
)) == bitwise_cast
<int64_t>(asDouble
) 
 404                 && trySetConstant(node
, JSValue(asInt
))) { 
 405                 m_foundConstants 
= true; 
 409         node
->setCanExit(true); 
 410         forNode(node
).set(SpecInt32
); 
 415         JSValue child 
= forNode(node
->child1()).value(); 
 416         if (child 
&& child
.isNumber()) { 
 419                 constantWasSet 
= trySetConstant(node
, child
); 
 421                 constantWasSet 
= trySetConstant(node
, JSValue(JSC::toInt32(child
.asDouble()))); 
 422             if (constantWasSet
) { 
 423                 m_foundConstants 
= true; 
 428         forNode(node
).set(SpecInt32
); 
 433     case ForwardInt32ToDouble
: { 
 434         JSValue child 
= forNode(node
->child1()).value(); 
 435         if (child 
&& child
.isNumber() 
 436             && trySetConstant(node
, JSValue(JSValue::EncodeAsDouble
, child
.asNumber()))) { 
 437             m_foundConstants 
= true; 
 440         if (isInt32Speculation(forNode(node
->child1()).m_type
)) 
 441             forNode(node
).set(SpecDoubleReal
); 
 443             forNode(node
).set(SpecDouble
); 
 449         JSValue left 
= forNode(node
->child1()).value(); 
 450         JSValue right 
= forNode(node
->child2()).value(); 
 451         if (left 
&& right 
&& left
.isNumber() && right
.isNumber() 
 452             && trySetConstant(node
, JSValue(left
.asNumber() + right
.asNumber()))) { 
 453             m_foundConstants 
= true; 
 456         switch (node
->binaryUseKind()) { 
 458             forNode(node
).set(SpecInt32
); 
 459             if (!nodeCanTruncateInteger(node
->arithNodeFlags())) 
 460                 node
->setCanExit(true); 
 463             if (isRealNumberSpeculation(forNode(node
->child1()).m_type
) 
 464                 && isRealNumberSpeculation(forNode(node
->child2()).m_type
)) 
 465                 forNode(node
).set(SpecDoubleReal
); 
 467                 forNode(node
).set(SpecDouble
); 
 470             RELEASE_ASSERT(node
->op() == ValueAdd
); 
 471             clobberWorld(node
->codeOrigin
, indexInBlock
); 
 472             forNode(node
).set(SpecString 
| SpecInt32 
| SpecNumber
); 
 479         forNode(node
).set(m_graph
.m_vm
.stringStructure
.get()); 
 484         JSValue left 
= forNode(node
->child1()).value(); 
 485         JSValue right 
= forNode(node
->child2()).value(); 
 486         if (left 
&& right 
&& left
.isNumber() && right
.isNumber() 
 487             && trySetConstant(node
, JSValue(left
.asNumber() - right
.asNumber()))) { 
 488             m_foundConstants 
= true; 
 491         switch (node
->binaryUseKind()) { 
 493             forNode(node
).set(SpecInt32
); 
 494             if (!nodeCanTruncateInteger(node
->arithNodeFlags())) 
 495                 node
->setCanExit(true); 
 498             forNode(node
).set(SpecDouble
); 
 501             RELEASE_ASSERT_NOT_REACHED(); 
 508         JSValue child 
= forNode(node
->child1()).value(); 
 509         if (child 
&& child
.isNumber() 
 510             && trySetConstant(node
, JSValue(-child
.asNumber()))) { 
 511             m_foundConstants 
= true; 
 514         switch (node
->child1().useKind()) { 
 516             forNode(node
).set(SpecInt32
); 
 517             if (!nodeCanTruncateInteger(node
->arithNodeFlags())) 
 518                 node
->setCanExit(true); 
 521             forNode(node
).set(SpecDouble
); 
 524             RELEASE_ASSERT_NOT_REACHED(); 
 531         JSValue left 
= forNode(node
->child1()).value(); 
 532         JSValue right 
= forNode(node
->child2()).value(); 
 533         if (left 
&& right 
&& left
.isNumber() && right
.isNumber() 
 534             && trySetConstant(node
, JSValue(left
.asNumber() * right
.asNumber()))) { 
 535             m_foundConstants 
= true; 
 538         switch (node
->binaryUseKind()) { 
 540             forNode(node
).set(SpecInt32
); 
 541             if (!nodeCanTruncateInteger(node
->arithNodeFlags()) 
 542                 || !nodeCanIgnoreNegativeZero(node
->arithNodeFlags())) 
 543                 node
->setCanExit(true); 
 546             if (isRealNumberSpeculation(forNode(node
->child1()).m_type
) 
 547                 || isRealNumberSpeculation(forNode(node
->child2()).m_type
)) 
 548                 forNode(node
).set(SpecDoubleReal
); 
 550                 forNode(node
).set(SpecDouble
); 
 553             RELEASE_ASSERT_NOT_REACHED(); 
 560         forNode(node
).set(SpecInt32
); 
 568         JSValue left 
= forNode(node
->child1()).value(); 
 569         JSValue right 
= forNode(node
->child2()).value(); 
 570         if (left 
&& right 
&& left
.isNumber() && right
.isNumber()) { 
 571             double a 
= left
.asNumber(); 
 572             double b 
= right
.asNumber(); 
 574             switch (node
->op()) { 
 576                 constantWasSet 
= trySetConstant(node
, JSValue(a 
/ b
)); 
 579                 constantWasSet 
= trySetConstant(node
, JSValue(a 
< b 
? a 
: (b 
<= a 
? b 
: a 
+ b
))); 
 582                 constantWasSet 
= trySetConstant(node
, JSValue(a 
> b 
? a 
: (b 
>= a 
? b 
: a 
+ b
))); 
 585                 constantWasSet 
= trySetConstant(node
, JSValue(fmod(a
, b
))); 
 588                 RELEASE_ASSERT_NOT_REACHED(); 
 589                 constantWasSet 
= false; 
 592             if (constantWasSet
) { 
 593                 m_foundConstants 
= true; 
 597         switch (node
->binaryUseKind()) { 
 599             forNode(node
).set(SpecInt32
); 
 600             node
->setCanExit(true); 
 603             forNode(node
).set(SpecDouble
); 
 606             RELEASE_ASSERT_NOT_REACHED(); 
 613         JSValue child 
= forNode(node
->child1()).value(); 
 614         if (child 
&& child
.isNumber() 
 615             && trySetConstant(node
, JSValue(fabs(child
.asNumber())))) { 
 616             m_foundConstants 
= true; 
 619         switch (node
->child1().useKind()) { 
 621             forNode(node
).set(SpecInt32
); 
 622             node
->setCanExit(true); 
 625             forNode(node
).set(SpecDouble
); 
 628             RELEASE_ASSERT_NOT_REACHED(); 
 635         JSValue child 
= forNode(node
->child1()).value(); 
 636         if (child 
&& child
.isNumber() 
 637             && trySetConstant(node
, JSValue(sqrt(child
.asNumber())))) { 
 638             m_foundConstants 
= true; 
 641         forNode(node
).set(SpecDouble
); 
 646         bool didSetConstant 
= false; 
 647         switch (booleanResult(node
, forNode(node
->child1()))) { 
 649             didSetConstant 
= trySetConstant(node
, jsBoolean(false)); 
 651         case DefinitelyFalse
: 
 652             didSetConstant 
= trySetConstant(node
, jsBoolean(true)); 
 657         if (didSetConstant
) { 
 658             m_foundConstants 
= true; 
 661         switch (node
->child1().useKind()) { 
 667         case ObjectOrOtherUse
: 
 668             node
->setCanExit(true); 
 671             RELEASE_ASSERT_NOT_REACHED(); 
 674         forNode(node
).set(SpecBoolean
); 
 684         node
->setCanExit(node
->op() == IsUndefined 
&& m_codeBlock
->globalObjectFor(node
->codeOrigin
)->masqueradesAsUndefinedWatchpoint()->isStillValid()); 
 685         JSValue child 
= forNode(node
->child1()).value(); 
 688             switch (node
->op()) { 
 690                 if (m_codeBlock
->globalObjectFor(node
->codeOrigin
)->masqueradesAsUndefinedWatchpoint()->isStillValid()) { 
 691                     constantWasSet 
= trySetConstant(node
, jsBoolean( 
 694                         : child
.isUndefined())); 
 696                     constantWasSet 
= trySetConstant(node
, jsBoolean( 
 698                         ? child
.asCell()->structure()->masqueradesAsUndefined(m_codeBlock
->globalObjectFor(node
->codeOrigin
)) 
 699                         : child
.isUndefined())); 
 703                 constantWasSet 
= trySetConstant(node
, jsBoolean(child
.isBoolean())); 
 706                 constantWasSet 
= trySetConstant(node
, jsBoolean(child
.isNumber())); 
 709                 constantWasSet 
= trySetConstant(node
, jsBoolean(isJSString(child
))); 
 712                 if (child
.isNull() || !child
.isObject()) { 
 713                     constantWasSet 
= trySetConstant(node
, jsBoolean(child
.isNull())); 
 717                 constantWasSet 
= false; 
 720             if (constantWasSet
) { 
 721                 m_foundConstants 
= true; 
 726         forNode(node
).set(SpecBoolean
); 
 731         VM
* vm 
= m_codeBlock
->vm(); 
 732         JSValue child 
= forNode(node
->child1()).value(); 
 733         AbstractValue
& abstractChild 
= forNode(node
->child1()); 
 735             JSValue typeString 
= jsTypeStringForValue(*vm
, m_codeBlock
->globalObjectFor(node
->codeOrigin
), child
); 
 736             if (trySetConstant(node
, typeString
)) { 
 737                 m_foundConstants 
= true; 
 740         } else if (isNumberSpeculation(abstractChild
.m_type
)) { 
 741             if (trySetConstant(node
, vm
->smallStrings
.numberString())) { 
 742                 forNode(node
->child1()).filter(SpecNumber
); 
 743                 m_foundConstants 
= true; 
 746         } else if (isStringSpeculation(abstractChild
.m_type
)) { 
 747             if (trySetConstant(node
, vm
->smallStrings
.stringString())) { 
 748                 forNode(node
->child1()).filter(SpecString
); 
 749                 m_foundConstants 
= true; 
 752         } else if (isFinalObjectSpeculation(abstractChild
.m_type
) || isArraySpeculation(abstractChild
.m_type
) || isArgumentsSpeculation(abstractChild
.m_type
)) { 
 753             if (trySetConstant(node
, vm
->smallStrings
.objectString())) { 
 754                 forNode(node
->child1()).filter(SpecFinalObject 
| SpecArray 
| SpecArguments
); 
 755                 m_foundConstants 
= true; 
 758         } else if (isFunctionSpeculation(abstractChild
.m_type
)) { 
 759             if (trySetConstant(node
, vm
->smallStrings
.functionString())) { 
 760                 forNode(node
->child1()).filter(SpecFunction
); 
 761                 m_foundConstants 
= true; 
 764         } else if (isBooleanSpeculation(abstractChild
.m_type
)) { 
 765             if (trySetConstant(node
, vm
->smallStrings
.booleanString())) { 
 766                 forNode(node
->child1()).filter(SpecBoolean
); 
 767                 m_foundConstants 
= true; 
 772         switch (node
->child1().useKind()) { 
 775             node
->setCanExit(true); 
 780             RELEASE_ASSERT_NOT_REACHED(); 
 783         forNode(node
).set(m_graph
.m_vm
.stringStructure
.get()); 
 790     case CompareGreaterEq
: 
 792     case CompareEqConstant
: { 
 793         bool constantWasSet 
= false; 
 795         JSValue leftConst 
= forNode(node
->child1()).value(); 
 796         JSValue rightConst 
= forNode(node
->child2()).value(); 
 797         if (leftConst 
&& rightConst 
&& leftConst
.isNumber() && rightConst
.isNumber()) { 
 798             double a 
= leftConst
.asNumber(); 
 799             double b 
= rightConst
.asNumber(); 
 800             switch (node
->op()) { 
 802                 constantWasSet 
= trySetConstant(node
, jsBoolean(a 
< b
)); 
 805                 constantWasSet 
= trySetConstant(node
, jsBoolean(a 
<= b
)); 
 808                 constantWasSet 
= trySetConstant(node
, jsBoolean(a 
> b
)); 
 810             case CompareGreaterEq
: 
 811                 constantWasSet 
= trySetConstant(node
, jsBoolean(a 
>= b
)); 
 814                 constantWasSet 
= trySetConstant(node
, jsBoolean(a 
== b
)); 
 817                 RELEASE_ASSERT_NOT_REACHED(); 
 818                 constantWasSet 
= false; 
 823         if (!constantWasSet 
&& (node
->op() == CompareEqConstant 
|| node
->op() == CompareEq
)) { 
 824             SpeculatedType leftType 
= forNode(node
->child1()).m_type
; 
 825             SpeculatedType rightType 
= forNode(node
->child2()).m_type
; 
 826             if ((isInt32Speculation(leftType
) && isOtherSpeculation(rightType
)) 
 827                 || (isOtherSpeculation(leftType
) && isInt32Speculation(rightType
))) 
 828                 constantWasSet 
= trySetConstant(node
, jsBoolean(false)); 
 831         if (constantWasSet
) { 
 832             m_foundConstants 
= true; 
 836         forNode(node
).set(SpecBoolean
); 
 838         // This is overly conservative. But the only thing this prevents is store elimination, 
 839         // and how likely is it, really, that you'll have redundant stores across a comparison 
 840         // operation? Comparison operations are typically at the end of basic blocks, so 
 841         // unless we have global store elimination (super unlikely given how unprofitable that 
 842         // optimization is to begin with), you aren't going to be wanting to store eliminate 
 843         // across an equality op. 
 844         node
->setCanExit(true); 
 848     case CompareStrictEq
: 
 849     case CompareStrictEqConstant
: { 
 850         Node
* leftNode 
= node
->child1().node(); 
 851         Node
* rightNode 
= node
->child2().node(); 
 852         JSValue left 
= forNode(leftNode
).value(); 
 853         JSValue right 
= forNode(rightNode
).value(); 
 854         if (left 
&& right 
&& left
.isNumber() && right
.isNumber() 
 855             && trySetConstant(node
, jsBoolean(left
.asNumber() == right
.asNumber()))) { 
 856             m_foundConstants 
= true; 
 859         forNode(node
).set(SpecBoolean
); 
 860         node
->setCanExit(true); // This is overly conservative. 
 864     case StringCharCodeAt
: 
 865         node
->setCanExit(true); 
 866         forNode(node
).set(SpecInt32
); 
 869     case StringFromCharCode
: 
 870         forNode(node
).set(SpecString
); 
 874         node
->setCanExit(true); 
 875         forNode(node
).set(m_graph
.m_vm
.stringStructure
.get()); 
 879         node
->setCanExit(true); 
 880         switch (node
->arrayMode().type()) { 
 881         case Array::SelectUsingPredictions
: 
 882         case Array::Unprofiled
: 
 883         case Array::Undecided
: 
 884             RELEASE_ASSERT_NOT_REACHED(); 
 886         case Array::ForceExit
: 
 890             clobberWorld(node
->codeOrigin
, indexInBlock
); 
 891             forNode(node
).makeTop(); 
 894             forNode(node
).set(m_graph
.m_vm
.stringStructure
.get()); 
 896         case Array::Arguments
: 
 897             forNode(node
).makeTop(); 
 900             if (node
->arrayMode().isOutOfBounds()) { 
 901                 clobberWorld(node
->codeOrigin
, indexInBlock
); 
 902                 forNode(node
).makeTop(); 
 904                 forNode(node
).set(SpecInt32
); 
 907             if (node
->arrayMode().isOutOfBounds()) { 
 908                 clobberWorld(node
->codeOrigin
, indexInBlock
); 
 909                 forNode(node
).makeTop(); 
 910             } else if (node
->arrayMode().isSaneChain()) 
 911                 forNode(node
).set(SpecDouble
); 
 913                 forNode(node
).set(SpecDoubleReal
); 
 915         case Array::Contiguous
: 
 916         case Array::ArrayStorage
: 
 917         case Array::SlowPutArrayStorage
: 
 918             if (node
->arrayMode().isOutOfBounds()) 
 919                 clobberWorld(node
->codeOrigin
, indexInBlock
); 
 920             forNode(node
).makeTop(); 
 922         case Array::Int8Array
: 
 923             forNode(node
).set(SpecInt32
); 
 925         case Array::Int16Array
: 
 926             forNode(node
).set(SpecInt32
); 
 928         case Array::Int32Array
: 
 929             forNode(node
).set(SpecInt32
); 
 931         case Array::Uint8Array
: 
 932             forNode(node
).set(SpecInt32
); 
 934         case Array::Uint8ClampedArray
: 
 935             forNode(node
).set(SpecInt32
); 
 937         case Array::Uint16Array
: 
 938             forNode(node
).set(SpecInt32
); 
 940         case Array::Uint32Array
: 
 941             if (node
->shouldSpeculateInteger()) 
 942                 forNode(node
).set(SpecInt32
); 
 944                 forNode(node
).set(SpecDouble
); 
 946         case Array::Float32Array
: 
 947             forNode(node
).set(SpecDouble
); 
 949         case Array::Float64Array
: 
 950             forNode(node
).set(SpecDouble
); 
 953             RELEASE_ASSERT_NOT_REACHED(); 
 960     case PutByValAlias
: { 
 961         node
->setCanExit(true); 
 962         switch (node
->arrayMode().modeForPut().type()) { 
 963         case Array::ForceExit
: 
 967             clobberWorld(node
->codeOrigin
, indexInBlock
); 
 970             if (node
->arrayMode().isOutOfBounds()) 
 971                 clobberWorld(node
->codeOrigin
, indexInBlock
); 
 974             if (node
->arrayMode().isOutOfBounds()) 
 975                 clobberWorld(node
->codeOrigin
, indexInBlock
); 
 977         case Array::Contiguous
: 
 978         case Array::ArrayStorage
: 
 979             if (node
->arrayMode().isOutOfBounds()) 
 980                 clobberWorld(node
->codeOrigin
, indexInBlock
); 
 982         case Array::SlowPutArrayStorage
: 
 983             if (node
->arrayMode().mayStoreToHole()) 
 984                 clobberWorld(node
->codeOrigin
, indexInBlock
); 
 993         node
->setCanExit(true); 
 994         clobberWorld(node
->codeOrigin
, indexInBlock
); 
 995         forNode(node
).set(SpecNumber
); 
 999         node
->setCanExit(true); 
1000         clobberWorld(node
->codeOrigin
, indexInBlock
); 
1001         forNode(node
).makeTop(); 
1005         forNode(node
).makeTop(); 
1009         forNode(node
).set(SpecBoolean
); 
1016         Node
* child 
= node
->child1().node(); 
1017         BooleanResult result 
= booleanResult(node
, forNode(child
)); 
1018         if (result 
== DefinitelyTrue
) { 
1019             m_branchDirection 
= TakeTrue
; 
1022         if (result 
== DefinitelyFalse
) { 
1023             m_branchDirection 
= TakeFalse
; 
1026         // FIXME: The above handles the trivial cases of sparse conditional 
1027         // constant propagation, but we can do better: 
1028         // We can specialize the source variable's value on each direction of 
1030         node
->setCanExit(true); // This is overly conservative. 
1031         m_branchDirection 
= TakeBoth
; 
1040     case ThrowReferenceError
: 
1042         node
->setCanExit(true); 
1046         JSValue childConst 
= forNode(node
->child1()).value(); 
1047         if (childConst 
&& childConst
.isNumber() && trySetConstant(node
, childConst
)) { 
1048             m_foundConstants 
= true; 
1052         ASSERT(node
->child1().useKind() == UntypedUse
); 
1054         AbstractValue
& source 
= forNode(node
->child1()); 
1055         AbstractValue
& destination 
= forNode(node
); 
1057         // NB. The more canonical way of writing this would have been: 
1059         // destination = source; 
1060         // if (destination.m_type & !(SpecNumber | SpecString | SpecBoolean)) { 
1061         //     destination.filter(SpecNumber | SpecString | SpecBoolean); 
1062         //     AbstractValue string; 
1063         //     string.set(vm->stringStructure); 
1064         //     destination.merge(string); 
1067         // The reason why this would, in most other cases, have been better is that 
1068         // then destination would preserve any non-SpeculatedType knowledge of source. 
1069         // As it stands, the code below forgets any non-SpeculatedType knowledge that 
1070         // source would have had. Fortunately, though, for things like strings and 
1071         // numbers and booleans, we don't care about the non-SpeculatedType knowedge: 
1072         // the structure won't tell us anything we don't already know, and neither 
1073         // will ArrayModes. And if the source was a meaningful constant then we 
1074         // would have handled that above. Unfortunately, this does mean that 
1075         // ToPrimitive will currently forget string constants. But that's not a big 
1076         // deal since we don't do any optimization on those currently. 
1078         clobberWorld(node
->codeOrigin
, indexInBlock
); 
1080         SpeculatedType type 
= source
.m_type
; 
1081         if (type 
& ~(SpecNumber 
| SpecString 
| SpecBoolean
)) 
1082             type 
= (SpecTop 
& ~SpecCell
) | SpecString
; 
1084         destination
.set(type
); 
1089         switch (node
->child1().useKind()) { 
1090         case StringObjectUse
: 
1091             // This also filters that the StringObject has the primordial StringObject 
1093             forNode(node
->child1()).filter(m_graph
.globalObjectFor(node
->codeOrigin
)->stringObjectStructure()); 
1094             node
->setCanExit(true); // We could be more precise but it's likely not worth it. 
1096         case StringOrStringObjectUse
: 
1097             node
->setCanExit(true); // We could be more precise but it's likely not worth it. 
1101             clobberWorld(node
->codeOrigin
, indexInBlock
); 
1104             RELEASE_ASSERT_NOT_REACHED(); 
1107         forNode(node
).set(m_graph
.m_vm
.stringStructure
.get()); 
1111     case NewStringObject
: { 
1112         ASSERT(node
->structure()->classInfo() == &StringObject::s_info
); 
1113         forNode(node
).set(node
->structure()); 
1118         node
->setCanExit(true); 
1119         forNode(node
).set(m_graph
.globalObjectFor(node
->codeOrigin
)->arrayStructureForIndexingTypeDuringAllocation(node
->indexingType())); 
1120         m_haveStructures 
= true; 
1123     case NewArrayBuffer
: 
1124         node
->setCanExit(true); 
1125         forNode(node
).set(m_graph
.globalObjectFor(node
->codeOrigin
)->arrayStructureForIndexingTypeDuringAllocation(node
->indexingType())); 
1126         m_haveStructures 
= true; 
1129     case NewArrayWithSize
: 
1130         node
->setCanExit(true); 
1131         forNode(node
).set(SpecArray
); 
1132         m_haveStructures 
= true; 
1136         forNode(node
).set(m_graph
.globalObjectFor(node
->codeOrigin
)->regExpStructure()); 
1137         m_haveStructures 
= true; 
1141         AbstractValue
& source 
= forNode(node
->child1()); 
1142         AbstractValue
& destination 
= forNode(node
); 
1144         destination 
= source
; 
1145         destination
.merge(SpecObjectOther
); 
1150         forNode(node
).set(SpecFinalObject
); 
1154     case AllocationProfileWatchpoint
: 
1155         node
->setCanExit(true); 
1159         forNode(node
).set(node
->structure()); 
1160         m_haveStructures 
= true; 
1163     case CreateActivation
: 
1164         forNode(node
).set(m_codeBlock
->globalObjectFor(node
->codeOrigin
)->activationStructure()); 
1165         m_haveStructures 
= true; 
1168     case CreateArguments
: 
1169         forNode(node
).set(m_codeBlock
->globalObjectFor(node
->codeOrigin
)->argumentsStructure()); 
1170         m_haveStructures 
= true; 
1173     case TearOffActivation
: 
1174     case TearOffArguments
: 
1175         // Does nothing that is user-visible. 
1178     case CheckArgumentsNotCreated
: 
1179         if (isEmptySpeculation( 
1180                 m_variables
.operand( 
1181                     m_graph
.argumentsRegisterFor(node
->codeOrigin
)).m_type
)) 
1182             m_foundConstants 
= true; 
1184             node
->setCanExit(true); 
1187     case GetMyArgumentsLength
: 
1188         // We know that this executable does not escape its arguments, so we can optimize 
1189         // the arguments a bit. Note that this is not sufficient to force constant folding 
1190         // of GetMyArgumentsLength, because GetMyArgumentsLength is a clobbering operation. 
1191         // We perform further optimizations on this later on. 
1192         if (node
->codeOrigin
.inlineCallFrame
) 
1193             forNode(node
).set(jsNumber(node
->codeOrigin
.inlineCallFrame
->arguments
.size() - 1)); 
1195             forNode(node
).set(SpecInt32
); 
1197             !isEmptySpeculation( 
1198                 m_variables
.operand( 
1199                     m_graph
.argumentsRegisterFor(node
->codeOrigin
)).m_type
)); 
1202     case GetMyArgumentsLengthSafe
: 
1203         // This potentially clobbers all structures if the arguments object had a getter 
1204         // installed on the length property. 
1205         clobberWorld(node
->codeOrigin
, indexInBlock
); 
1206         // We currently make no guarantee about what this returns because it does not 
1207         // speculate that the length property is actually a length. 
1208         forNode(node
).makeTop(); 
1211     case GetMyArgumentByVal
: 
1212         node
->setCanExit(true); 
1213         // We know that this executable does not escape its arguments, so we can optimize 
1214         // the arguments a bit. Note that this ends up being further optimized by the 
1215         // ArgumentsSimplificationPhase. 
1216         forNode(node
).makeTop(); 
1219     case GetMyArgumentByValSafe
: 
1220         node
->setCanExit(true); 
1221         // This potentially clobbers all structures if the property we're accessing has 
1222         // a getter. We don't speculate against this. 
1223         clobberWorld(node
->codeOrigin
, indexInBlock
); 
1224         // And the result is unknown. 
1225         forNode(node
).makeTop(); 
1229         AbstractValue
& value 
= forNode(node
); 
1230         value 
= forNode(node
->child1()); 
1232         if (!(value
.m_type 
& SpecEmpty
)) { 
1233             m_foundConstants 
= true; 
1237         value
.set((value
.m_type 
& ~SpecEmpty
) | SpecFunction
); 
1241     case NewFunctionExpression
: 
1242     case NewFunctionNoCheck
: 
1243         forNode(node
).set(m_codeBlock
->globalObjectFor(node
->codeOrigin
)->functionStructure()); 
1247         forNode(node
).set(SpecFunction
); 
1254     case GetScope
: // FIXME: We could get rid of these if we know that the JSFunction is a constant. https://bugs.webkit.org/show_bug.cgi?id=106202 
1257         forNode(node
).set(SpecObjectOther
); 
1261         JSValue child 
= forNode(node
->child1()).value(); 
1262         if (child 
&& trySetConstant(node
, JSValue(jsCast
<JSScope
*>(child
.asCell())->next()))) { 
1263             m_foundConstants 
= true; 
1266         forNode(node
).set(SpecObjectOther
); 
1270     case GetScopeRegisters
: 
1271         forNode(node
).clear(); // The result is not a JS value. 
1275         forNode(node
).makeTop(); 
1279         clobberCapturedVars(node
->codeOrigin
); 
1284         node
->setCanExit(true); 
1285         if (!node
->prediction()) { 
1289         if (isCellSpeculation(node
->child1()->prediction())) { 
1290             if (Structure
* structure 
= forNode(node
->child1()).bestProvenStructure()) { 
1291                 GetByIdStatus status 
= GetByIdStatus::computeFor( 
1292                     m_graph
.m_vm
, structure
, 
1293                     m_graph
.m_codeBlock
->identifier(node
->identifierNumber())); 
1294                 if (status
.isSimple()) { 
1295                     // Assert things that we can't handle and that the computeFor() method 
1296                     // above won't be able to return. 
1297                     ASSERT(status
.structureSet().size() == 1); 
1298                     ASSERT(status
.chain().isEmpty()); 
1300                     if (status
.specificValue()) 
1301                         forNode(node
).set(status
.specificValue()); 
1303                         forNode(node
).makeTop(); 
1304                     forNode(node
->child1()).filter(status
.structureSet()); 
1306                     m_foundConstants 
= true; 
1311         clobberWorld(node
->codeOrigin
, indexInBlock
); 
1312         forNode(node
).makeTop(); 
1315     case GetArrayLength
: 
1316         node
->setCanExit(true); // Lies, but it's true for the common case of JSArray, so it's good enough. 
1317         forNode(node
).set(SpecInt32
); 
1320     case CheckExecutable
: { 
1321         // FIXME: We could track executables in AbstractValue, which would allow us to get rid of these checks 
1322         // more thoroughly. https://bugs.webkit.org/show_bug.cgi?id=106200 
1323         // FIXME: We could eliminate these entirely if we know the exact value that flows into this. 
1324         // https://bugs.webkit.org/show_bug.cgi?id=106201 
1325         node
->setCanExit(true); 
1329     case CheckStructure
: 
1330     case ForwardCheckStructure
: { 
1331         // FIXME: We should be able to propagate the structure sets of constants (i.e. prototypes). 
1332         AbstractValue
& value 
= forNode(node
->child1()); 
1333         ASSERT(!(value
.m_type 
& ~SpecCell
)); // Edge filtering should have already ensured this. 
1334         // If this structure check is attempting to prove knowledge already held in 
1335         // the futurePossibleStructure set then the constant folding phase should 
1336         // turn this into a watchpoint instead. 
1337         StructureSet
& set 
= node
->structureSet(); 
1338         if (value
.m_futurePossibleStructure
.isSubsetOf(set
) 
1339             || value
.m_currentKnownStructure
.isSubsetOf(set
)) 
1340             m_foundConstants 
= true; 
1341         if (!value
.m_currentKnownStructure
.isSubsetOf(set
)) 
1342             node
->setCanExit(true); 
1344         m_haveStructures 
= true; 
1348     case StructureTransitionWatchpoint
: 
1349     case ForwardStructureTransitionWatchpoint
: { 
1350         AbstractValue
& value 
= forNode(node
->child1()); 
1352         // It's only valid to issue a structure transition watchpoint if we already 
1353         // know that the watchpoint covers a superset of the structures known to 
1354         // belong to the set of future structures that this value may have. 
1355         // Currently, we only issue singleton watchpoints (that check one structure) 
1356         // and our futurePossibleStructure set can only contain zero, one, or an 
1357         // infinity of structures. 
1358         ASSERT(value
.m_futurePossibleStructure
.isSubsetOf(StructureSet(node
->structure()))); 
1360         value
.filter(node
->structure()); 
1361         m_haveStructures 
= true; 
1362         node
->setCanExit(true); 
1367     case PhantomPutStructure
: 
1368         if (!forNode(node
->child1()).m_currentKnownStructure
.isClear()) { 
1369             clobberStructures(indexInBlock
); 
1370             forNode(node
->child1()).set(node
->structureTransitionData().newStructure
); 
1371             m_haveStructures 
= true; 
1375     case AllocatePropertyStorage
: 
1376     case ReallocatePropertyStorage
: 
1377         forNode(node
).clear(); // The result is not a JS value. 
1380         if (node
->arrayMode().alreadyChecked(m_graph
, node
, forNode(node
->child1()))) { 
1381             m_foundConstants 
= true; 
1384         node
->setCanExit(true); // Lies, but this is followed by operations (like GetByVal) that always exit, so there is no point in us trying to be clever here. 
1385         switch (node
->arrayMode().type()) { 
1387             forNode(node
->child1()).filter(SpecString
); 
1391         case Array::Contiguous
: 
1392         case Array::ArrayStorage
: 
1393         case Array::SlowPutArrayStorage
: 
1395         case Array::Arguments
: 
1396             forNode(node
->child1()).filter(SpecArguments
); 
1398         case Array::Int8Array
: 
1399             forNode(node
->child1()).filter(SpecInt8Array
); 
1401         case Array::Int16Array
: 
1402             forNode(node
->child1()).filter(SpecInt16Array
); 
1404         case Array::Int32Array
: 
1405             forNode(node
->child1()).filter(SpecInt32Array
); 
1407         case Array::Uint8Array
: 
1408             forNode(node
->child1()).filter(SpecUint8Array
); 
1410         case Array::Uint8ClampedArray
: 
1411             forNode(node
->child1()).filter(SpecUint8ClampedArray
); 
1413         case Array::Uint16Array
: 
1414             forNode(node
->child1()).filter(SpecUint16Array
); 
1416         case Array::Uint32Array
: 
1417             forNode(node
->child1()).filter(SpecUint32Array
); 
1419         case Array::Float32Array
: 
1420             forNode(node
->child1()).filter(SpecFloat32Array
); 
1422         case Array::Float64Array
: 
1423             forNode(node
->child1()).filter(SpecFloat64Array
); 
1426             RELEASE_ASSERT_NOT_REACHED(); 
1429         forNode(node
->child1()).filterArrayModes(node
->arrayMode().arrayModesThatPassFiltering()); 
1430         m_haveStructures 
= true; 
1434         if (node
->arrayMode().alreadyChecked(m_graph
, node
, forNode(node
->child1()))) { 
1435             m_foundConstants 
= true; 
1438         ASSERT(node
->arrayMode().conversion() == Array::Convert
 
1439             || node
->arrayMode().conversion() == Array::RageConvert
); 
1440         node
->setCanExit(true); 
1441         clobberStructures(indexInBlock
); 
1442         forNode(node
->child1()).filterArrayModes(node
->arrayMode().arrayModesThatPassFiltering()); 
1443         m_haveStructures 
= true; 
1446     case ArrayifyToStructure
: { 
1447         AbstractValue
& value 
= forNode(node
->child1()); 
1448         StructureSet set 
= node
->structure(); 
1449         if (value
.m_futurePossibleStructure
.isSubsetOf(set
) 
1450             || value
.m_currentKnownStructure
.isSubsetOf(set
)) 
1451             m_foundConstants 
= true; 
1452         node
->setCanExit(true); 
1453         clobberStructures(indexInBlock
); 
1455         m_haveStructures 
= true; 
1458     case GetIndexedPropertyStorage
: { 
1459         forNode(node
).clear(); 
1463         forNode(node
).makeTop(); 
1471     case CheckFunction
: { 
1472         JSValue value 
= forNode(node
->child1()).value(); 
1473         if (value 
== node
->function()) { 
1474             m_foundConstants 
= true; 
1479         node
->setCanExit(true); // Lies! We can do better. 
1480         forNode(node
->child1()).filterByValue(node
->function()); 
1486         node
->setCanExit(true); 
1487         if (Structure
* structure 
= forNode(node
->child1()).bestProvenStructure()) { 
1488             PutByIdStatus status 
= PutByIdStatus::computeFor( 
1490                 m_graph
.globalObjectFor(node
->codeOrigin
), 
1492                 m_graph
.m_codeBlock
->identifier(node
->identifierNumber()), 
1493                 node
->op() == PutByIdDirect
); 
1494             if (status
.isSimpleReplace()) { 
1495                 forNode(node
->child1()).filter(structure
); 
1496                 m_foundConstants 
= true; 
1499             if (status
.isSimpleTransition()) { 
1500                 clobberStructures(indexInBlock
); 
1501                 forNode(node
->child1()).set(status
.newStructure()); 
1502                 m_haveStructures 
= true; 
1503                 m_foundConstants 
= true; 
1507         clobberWorld(node
->codeOrigin
, indexInBlock
); 
1511         forNode(node
).makeTop(); 
1514     case GlobalVarWatchpoint
: 
1515         node
->setCanExit(true); 
1519     case PutGlobalVarCheck
: 
1522     case CheckHasInstance
: 
1523         node
->setCanExit(true); 
1524         // Sadly, we don't propagate the fact that we've done CheckHasInstance 
1528         node
->setCanExit(true); 
1529         // Again, sadly, we don't propagate the fact that we've done InstanceOf 
1530         forNode(node
).set(SpecBoolean
); 
1543     case ResolveBaseStrictPut
: 
1545         node
->setCanExit(true); 
1546         clobberWorld(node
->codeOrigin
, indexInBlock
); 
1547         forNode(node
).makeTop(); 
1551         clobberWorld(node
->codeOrigin
, indexInBlock
); 
1552         forNode(node
).makeTop(); 
1556         node
->setCanExit(true); 
1560     case CheckWatchdogTimer
: 
1561         node
->setCanExit(true); 
1567     case CountExecution
: 
1571         RELEASE_ASSERT_NOT_REACHED(); 
1578 bool AbstractState::executeEffects(unsigned indexInBlock
) 
1580     return executeEffects(indexInBlock
, m_block
->at(indexInBlock
)); 
1583 bool AbstractState::execute(unsigned indexInBlock
) 
1585     Node
* node 
= m_block
->at(indexInBlock
); 
1586     if (!startExecuting(node
)) 
1590     return executeEffects(indexInBlock
, node
); 
1593 inline void AbstractState::clobberWorld(const CodeOrigin
& codeOrigin
, unsigned indexInBlock
) 
1595     clobberCapturedVars(codeOrigin
); 
1596     clobberStructures(indexInBlock
); 
1599 inline void AbstractState::clobberCapturedVars(const CodeOrigin
& codeOrigin
) 
1601     if (codeOrigin
.inlineCallFrame
) { 
1602         const BitVector
& capturedVars 
= codeOrigin
.inlineCallFrame
->capturedVars
; 
1603         for (size_t i 
= capturedVars
.size(); i
--;) { 
1604             if (!capturedVars
.quickGet(i
)) 
1606             m_variables
.local(i
).makeTop(); 
1609         for (size_t i 
= m_codeBlock
->m_numVars
; i
--;) { 
1610             if (m_codeBlock
->isCaptured(i
)) 
1611                 m_variables
.local(i
).makeTop(); 
1615     for (size_t i 
= m_variables
.numberOfArguments(); i
--;) { 
1616         if (m_codeBlock
->isCaptured(argumentToOperand(i
))) 
1617             m_variables
.argument(i
).makeTop(); 
1621 inline void AbstractState::clobberStructures(unsigned indexInBlock
) 
1623     if (!m_haveStructures
) 
1625     for (size_t i 
= indexInBlock 
+ 1; i
--;) 
1626         forNode(m_block
->at(i
)).clobberStructures(); 
1627     for (size_t i 
= m_variables
.numberOfArguments(); i
--;) 
1628         m_variables
.argument(i
).clobberStructures(); 
1629     for (size_t i 
= m_variables
.numberOfLocals(); i
--;) 
1630         m_variables
.local(i
).clobberStructures(); 
1631     m_haveStructures 
= false; 
1632     m_didClobber 
= true; 
1635 inline bool AbstractState::mergeStateAtTail(AbstractValue
& destination
, AbstractValue
& inVariable
, Node
* node
) 
1640     AbstractValue source
; 
1642     if (node
->variableAccessData()->isCaptured()) { 
1643         // If it's captured then we know that whatever value was stored into the variable last is the 
1644         // one we care about. This is true even if the variable at tail is dead, which might happen if 
1645         // the last thing we did to the variable was a GetLocal and then ended up now using the 
1646         // GetLocal's result. 
1648         source 
= inVariable
; 
1649 #if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE) 
1650         dataLogF("          Transfering "); 
1651         source
.dump(WTF::dataFile()); 
1652         dataLogF(" from last access due to captured variable.\n"); 
1655 #if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE) 
1656         dataLogF("          It's live, node @%u.\n", node
->index()); 
1659         switch (node
->op()) { 
1664             // The block transfers the value from head to tail. 
1665             source 
= inVariable
; 
1666 #if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE) 
1667             dataLogF("          Transfering "); 
1668             source
.dump(WTF::dataFile()); 
1669             dataLogF(" from head to tail.\n"); 
1674             // The block refines the value with additional speculations. 
1675             source 
= forNode(node
); 
1676 #if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE) 
1677             dataLogF("          Refining to "); 
1678             source
.dump(WTF::dataFile()); 
1684             // The block sets the variable, and potentially refines it, both 
1685             // before and after setting it. 
1686             if (node
->variableAccessData()->shouldUseDoubleFormat()) { 
1687                 // FIXME: This unnecessarily loses precision. 
1688                 source
.set(SpecDouble
); 
1690                 source 
= forNode(node
->child1()); 
1691 #if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE) 
1692             dataLogF("          Setting to "); 
1693             source
.dump(WTF::dataFile()); 
1699             RELEASE_ASSERT_NOT_REACHED(); 
1704     if (destination 
== source
) { 
1705         // Abstract execution did not change the output value of the variable, for this 
1706         // basic block, on this iteration. 
1707 #if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE) 
1708         dataLogF("          Not changed!\n"); 
1713     // Abstract execution reached a new conclusion about the speculations reached about 
1714     // this variable after execution of this basic block. Update the state, and return 
1715     // true to indicate that the fixpoint must go on! 
1716     destination 
= source
; 
1717 #if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE) 
1718     dataLogF("          Changed!\n"); 
1723 inline bool AbstractState::merge(BasicBlock
* from
, BasicBlock
* to
) 
1725     ASSERT(from
->variablesAtTail
.numberOfArguments() == to
->variablesAtHead
.numberOfArguments()); 
1726     ASSERT(from
->variablesAtTail
.numberOfLocals() == to
->variablesAtHead
.numberOfLocals()); 
1728     bool changed 
= false; 
1730     for (size_t argument 
= 0; argument 
< from
->variablesAtTail
.numberOfArguments(); ++argument
) { 
1731         AbstractValue
& destination 
= to
->valuesAtHead
.argument(argument
); 
1732         changed 
|= mergeVariableBetweenBlocks(destination
, from
->valuesAtTail
.argument(argument
), to
->variablesAtHead
.argument(argument
), from
->variablesAtTail
.argument(argument
)); 
1735     for (size_t local 
= 0; local 
< from
->variablesAtTail
.numberOfLocals(); ++local
) { 
1736         AbstractValue
& destination 
= to
->valuesAtHead
.local(local
); 
1737         changed 
|= mergeVariableBetweenBlocks(destination
, from
->valuesAtTail
.local(local
), to
->variablesAtHead
.local(local
), from
->variablesAtTail
.local(local
)); 
1740     if (!to
->cfaHasVisited
) 
1743     to
->cfaShouldRevisit 
|= changed
; 
1748 inline bool AbstractState::mergeToSuccessors(Graph
& graph
, BasicBlock
* basicBlock
) 
1750     Node
* terminal 
= basicBlock
->last(); 
1752     ASSERT(terminal
->isTerminal()); 
1754     switch (terminal
->op()) { 
1756         ASSERT(basicBlock
->cfaBranchDirection 
== InvalidBranchDirection
); 
1757 #if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE) 
1758         dataLogF("        Merging to block #%u.\n", terminal
->takenBlockIndex()); 
1760         return merge(basicBlock
, graph
.m_blocks
[terminal
->takenBlockIndex()].get()); 
1764         ASSERT(basicBlock
->cfaBranchDirection 
!= InvalidBranchDirection
); 
1765         bool changed 
= false; 
1766 #if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE) 
1767         dataLogF("        Merging to block #%u.\n", terminal
->takenBlockIndex()); 
1769         if (basicBlock
->cfaBranchDirection 
!= TakeFalse
) 
1770             changed 
|= merge(basicBlock
, graph
.m_blocks
[terminal
->takenBlockIndex()].get()); 
1771 #if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE) 
1772         dataLogF("        Merging to block #%u.\n", terminal
->notTakenBlockIndex()); 
1774         if (basicBlock
->cfaBranchDirection 
!= TakeTrue
) 
1775             changed 
|= merge(basicBlock
, graph
.m_blocks
[terminal
->notTakenBlockIndex()].get()); 
1781     case ThrowReferenceError
: 
1782         ASSERT(basicBlock
->cfaBranchDirection 
== InvalidBranchDirection
); 
1786         RELEASE_ASSERT_NOT_REACHED(); 
1791 inline bool AbstractState::mergeVariableBetweenBlocks(AbstractValue
& destination
, AbstractValue
& source
, Node
* destinationNode
, Node
* sourceNode
) 
1793     if (!destinationNode
) 
1796     ASSERT_UNUSED(sourceNode
, sourceNode
); 
1798     // FIXME: We could do some sparse conditional propagation here! 
1800     return destination
.merge(source
); 
1803 void AbstractState::dump(PrintStream
& out
) 
1806     for (size_t i 
= 0; i 
< m_block
->size(); ++i
) { 
1807         Node
* node 
= m_block
->at(i
); 
1808         AbstractValue
& value 
= forNode(node
); 
1809         if (value
.isClear()) 
1815         out
.printf("@%lu:", static_cast<unsigned long>(node
->index())); 
1820 } } // namespace JSC::DFG 
1822 #endif // ENABLE(DFG_JIT)