1/* 2 * Copyright (C) 2011, 2012, 2013, 2014 Apple Inc. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 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. 12 * 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. 24 */ 25 26#include "config.h" 27#include "DFGPredictionPropagationPhase.h" 28 29#if ENABLE(DFG_JIT) 30 31#include "DFGGraph.h" 32#include "DFGPhase.h" 33#include "JSCInlines.h" 34 35namespace JSC { namespace DFG { 36 37SpeculatedType resultOfToPrimitive(SpeculatedType type) 38{ 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); 43 } 44 45 return type; 46} 47 48class PredictionPropagationPhase : public Phase { 49public: 50 PredictionPropagationPhase(Graph& graph) 51 : Phase(graph, "prediction propagation") 52 { 53 } 54 55 bool run() 56 { 57 ASSERT(m_graph.m_form == ThreadedCPS); 58 ASSERT(m_graph.m_unificationState == GloballyUnified); 59 60 m_pass = PrimaryPass; 61 propagateToFixpoint(); 62 63 m_pass = RareCasePass; 64 propagateToFixpoint(); 65 66 m_pass = DoubleVotingPass; 67 do { 68 m_changed = false; 69 doRoundOfDoubleVoting(); 70 if (!m_changed) 71 break; 72 m_changed = false; 73 propagateForward(); 74 } while (m_changed); 75 76 return true; 77 } 78 79private: 80 void propagateToFixpoint() 81 { 82 do { 83 m_changed = false; 84 85 // Forward propagation is near-optimal for both topologically-sorted and 86 // DFS-sorted code. 87 propagateForward(); 88 if (!m_changed) 89 break; 90 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. 95 m_changed = false; 96 propagateBackward(); 97 } while (m_changed); 98 } 99 100 bool setPrediction(SpeculatedType prediction) 101 { 102 ASSERT(m_currentNode->hasResult()); 103 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); 109 110 return m_currentNode->predict(prediction); 111 } 112 113 bool mergePrediction(SpeculatedType prediction) 114 { 115 ASSERT(m_currentNode->hasResult()); 116 117 return m_currentNode->predict(prediction); 118 } 119 120 SpeculatedType speculatedDoubleTypeForPrediction(SpeculatedType value) 121 { 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; 129 return result; 130 } 131 132 SpeculatedType speculatedDoubleTypeForPredictions(SpeculatedType left, SpeculatedType right) 133 { 134 return speculatedDoubleTypeForPrediction(mergeSpeculations(left, right)); 135 } 136 137 void propagate(Node* node) 138 { 139 NodeType op = node->op(); 140 141 bool changed = false; 142 143 switch (op) { 144 case JSConstant: 145 case WeakJSConstant: { 146 SpeculatedType type = speculationFromValue(m_graph.valueOfJSConstant(node)); 147 if (type == SpecInt52AsDouble && enableInt52()) 148 type = SpecInt52; 149 changed |= setPrediction(type); 150 break; 151 } 152 153 case GetLocal: { 154 VariableAccessData* variable = node->variableAccessData(); 155 SpeculatedType prediction = variable->prediction(); 156 if (!variable->couldRepresentInt52() && (prediction & SpecInt52)) 157 prediction = (prediction | SpecInt52AsDouble) & ~SpecInt52; 158 if (prediction) 159 changed |= mergePrediction(prediction); 160 break; 161 } 162 163 case SetLocal: { 164 VariableAccessData* variableAccessData = node->variableAccessData(); 165 changed |= variableAccessData->predict(node->child1()->prediction()); 166 break; 167 } 168 169 case BitAnd: 170 case BitOr: 171 case BitXor: 172 case BitRShift: 173 case BitLShift: 174 case BitURShift: 175 case ArithIMul: { 176 changed |= setPrediction(SpecInt32); 177 break; 178 } 179 180 case ArrayPop: 181 case ArrayPush: 182 case RegExpExec: 183 case RegExpTest: 184 case GetById: 185 case GetByIdFlush: 186 case GetMyArgumentByValSafe: 187 case GetByOffset: 188 case MultiGetByOffset: 189 case Call: 190 case Construct: 191 case GetGlobalVar: 192 case GetClosureVar: { 193 changed |= setPrediction(node->getHeapPrediction()); 194 break; 195 } 196 197 case StringCharCodeAt: { 198 changed |= setPrediction(SpecInt32); 199 break; 200 } 201 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); 207 else 208 changed |= mergePrediction(SpecBytecodeNumber); 209 break; 210 } 211 212 case ValueAdd: { 213 SpeculatedType left = node->child1()->prediction(); 214 SpeculatedType right = node->child2()->prediction(); 215 216 if (left && right) { 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); 223 else 224 changed |= mergePrediction(speculatedDoubleTypeForPredictions(left, right)); 225 } else if ( 226 !(left & (SpecFullNumber | SpecBoolean)) 227 || !(right & (SpecFullNumber | SpecBoolean))) { 228 // left or right is definitely something other than a number. 229 changed |= mergePrediction(SpecString); 230 } else 231 changed |= mergePrediction(SpecString | SpecInt32 | SpecBytecodeDouble); 232 } 233 break; 234 } 235 236 case ArithAdd: { 237 SpeculatedType left = node->child1()->prediction(); 238 SpeculatedType right = node->child2()->prediction(); 239 240 if (left && right) { 241 if (m_graph.addSpeculationMode(node, m_pass) != DontSpeculateInt32) 242 changed |= mergePrediction(SpecInt32); 243 else if (m_graph.addShouldSpeculateMachineInt(node)) 244 changed |= mergePrediction(SpecInt52); 245 else 246 changed |= mergePrediction(speculatedDoubleTypeForPredictions(left, right)); 247 } 248 break; 249 } 250 251 case ArithSub: { 252 SpeculatedType left = node->child1()->prediction(); 253 SpeculatedType right = node->child2()->prediction(); 254 255 if (left && right) { 256 if (m_graph.addSpeculationMode(node, m_pass) != DontSpeculateInt32) 257 changed |= mergePrediction(SpecInt32); 258 else if (m_graph.addShouldSpeculateMachineInt(node)) 259 changed |= mergePrediction(SpecInt52); 260 else 261 changed |= mergePrediction(speculatedDoubleTypeForPredictions(left, right)); 262 } 263 break; 264 } 265 266 case ArithNegate: 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); 272 else 273 changed |= mergePrediction(speculatedDoubleTypeForPrediction(node->child1()->prediction())); 274 } 275 break; 276 277 case ArithMin: 278 case ArithMax: { 279 SpeculatedType left = node->child1()->prediction(); 280 SpeculatedType right = node->child2()->prediction(); 281 282 if (left && right) { 283 if (Node::shouldSpeculateInt32OrBooleanForArithmetic(node->child1().node(), node->child2().node()) 284 && node->canSpeculateInt32(m_pass)) 285 changed |= mergePrediction(SpecInt32); 286 else 287 changed |= mergePrediction(speculatedDoubleTypeForPredictions(left, right)); 288 } 289 break; 290 } 291 292 case ArithMul: { 293 SpeculatedType left = node->child1()->prediction(); 294 SpeculatedType right = node->child2()->prediction(); 295 296 if (left && right) { 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); 301 else 302 changed |= mergePrediction(speculatedDoubleTypeForPredictions(left, right)); 303 } 304 break; 305 } 306 307 case ArithDiv: { 308 SpeculatedType left = node->child1()->prediction(); 309 SpeculatedType right = node->child2()->prediction(); 310 311 if (left && right) { 312 if (Node::shouldSpeculateInt32OrBooleanForArithmetic(node->child1().node(), node->child2().node()) 313 && node->canSpeculateInt32(m_pass)) 314 changed |= mergePrediction(SpecInt32); 315 else 316 changed |= mergePrediction(SpecBytecodeDouble); 317 } 318 break; 319 } 320 321 case ArithMod: { 322 SpeculatedType left = node->child1()->prediction(); 323 SpeculatedType right = node->child2()->prediction(); 324 325 if (left && right) { 326 if (Node::shouldSpeculateInt32OrBooleanForArithmetic(node->child1().node(), node->child2().node()) 327 && node->canSpeculateInt32(m_pass)) 328 changed |= mergePrediction(SpecInt32); 329 else 330 changed |= mergePrediction(SpecBytecodeDouble); 331 } 332 break; 333 } 334 335 case ArithSqrt: 336 case ArithFRound: 337 case ArithSin: 338 case ArithCos: { 339 changed |= setPrediction(SpecBytecodeDouble); 340 break; 341 } 342 343 case ArithAbs: { 344 SpeculatedType child = node->child1()->prediction(); 345 if (isInt32OrBooleanSpeculationForArithmetic(child) 346 && node->canSpeculateInt32(m_pass)) 347 changed |= mergePrediction(SpecInt32); 348 else 349 changed |= mergePrediction(speculatedDoubleTypeForPrediction(child)); 350 break; 351 } 352 353 case LogicalNot: 354 case CompareLess: 355 case CompareLessEq: 356 case CompareGreater: 357 case CompareGreaterEq: 358 case CompareEq: 359 case CompareEqConstant: 360 case CompareStrictEq: 361 case InstanceOf: 362 case IsUndefined: 363 case IsBoolean: 364 case IsNumber: 365 case IsString: 366 case IsObject: 367 case IsFunction: { 368 changed |= setPrediction(SpecBoolean); 369 break; 370 } 371 372 case TypeOf: { 373 changed |= setPrediction(SpecString); 374 break; 375 } 376 377 case GetByVal: { 378 if (!node->child1()->prediction()) 379 break; 380 381 ArrayMode arrayMode = node->arrayMode().refine( 382 m_graph, node, 383 node->child1()->prediction(), 384 node->child2()->prediction(), 385 SpecNone, node->flags()); 386 387 switch (arrayMode.type()) { 388 case Array::Double: 389 if (arrayMode.isOutOfBounds()) 390 changed |= mergePrediction(node->getHeapPrediction() | SpecDoubleReal); 391 else 392 changed |= mergePrediction(SpecDoubleReal); 393 break; 394 case Array::Float32Array: 395 case Array::Float64Array: 396 changed |= mergePrediction(SpecFullDouble); 397 break; 398 case Array::Uint32Array: 399 if (isInt32Speculation(node->getHeapPrediction())) 400 changed |= mergePrediction(SpecInt32); 401 else if (enableInt52()) 402 changed |= mergePrediction(SpecMachineInt); 403 else 404 changed |= mergePrediction(SpecInt32 | SpecInt52AsDouble); 405 break; 406 default: 407 changed |= mergePrediction(node->getHeapPrediction()); 408 break; 409 } 410 break; 411 } 412 413 case GetMyArgumentsLengthSafe: { 414 changed |= setPrediction(SpecInt32); 415 break; 416 } 417 418 case GetClosureRegisters: 419 case GetButterfly: 420 case GetIndexedPropertyStorage: 421 case AllocatePropertyStorage: 422 case ReallocatePropertyStorage: { 423 changed |= setPrediction(SpecOther); 424 break; 425 } 426 427 case ToThis: { 428 SpeculatedType prediction = node->child1()->prediction(); 429 if (prediction) { 430 if (prediction & ~SpecObject) { 431 prediction &= SpecObject; 432 prediction = mergeSpeculations(prediction, SpecObjectOther); 433 } 434 changed |= mergePrediction(prediction); 435 } 436 break; 437 } 438 439 case GetMyScope: 440 case SkipTopScope: 441 case SkipScope: { 442 changed |= setPrediction(SpecObjectOther); 443 break; 444 } 445 446 case GetCallee: { 447 changed |= setPrediction(SpecFunction); 448 break; 449 } 450 451 case CreateThis: 452 case NewObject: { 453 changed |= setPrediction(SpecFinalObject); 454 break; 455 } 456 457 case NewArray: 458 case NewArrayWithSize: 459 case NewArrayBuffer: { 460 changed |= setPrediction(SpecArray); 461 break; 462 } 463 464 case NewTypedArray: { 465 changed |= setPrediction(speculationFromTypedArrayType(node->typedArrayType())); 466 break; 467 } 468 469 case NewRegexp: 470 case CreateActivation: { 471 changed |= setPrediction(SpecObjectOther); 472 break; 473 } 474 475 case StringFromCharCode: { 476 changed |= setPrediction(SpecString); 477 changed |= node->child1()->mergeFlags(NodeBytecodeUsesAsNumber | NodeBytecodeUsesAsInt); 478 break; 479 } 480 case StringCharAt: 481 case ToString: 482 case MakeRope: { 483 changed |= setPrediction(SpecString); 484 break; 485 } 486 487 case ToPrimitive: { 488 SpeculatedType child = node->child1()->prediction(); 489 if (child) 490 changed |= mergePrediction(resultOfToPrimitive(child)); 491 break; 492 } 493 494 case NewStringObject: { 495 changed |= setPrediction(SpecStringObject); 496 break; 497 } 498 499 case CreateArguments: { 500 changed |= setPrediction(SpecArguments); 501 break; 502 } 503 504 case NewFunction: { 505 SpeculatedType child = node->child1()->prediction(); 506 if (child & SpecEmpty) 507 changed |= mergePrediction((child & ~SpecEmpty) | SpecFunction); 508 else 509 changed |= mergePrediction(child); 510 break; 511 } 512 513 case NewFunctionNoCheck: 514 case NewFunctionExpression: { 515 changed |= setPrediction(SpecFunction); 516 break; 517 } 518 519 case FiatInt52: { 520 RELEASE_ASSERT(enableInt52()); 521 changed |= setPrediction(SpecMachineInt); 522 break; 523 } 524 525 case PutByValAlias: 526 case GetArrayLength: 527 case GetTypedArrayByteOffset: 528 case DoubleAsInt32: 529 case GetLocalUnlinked: 530 case GetMyArgumentsLength: 531 case GetMyArgumentByVal: 532 case PhantomPutStructure: 533 case PhantomArguments: 534 case CheckArray: 535 case Arrayify: 536 case ArrayifyToStructure: 537 case CheckTierUpInLoop: 538 case CheckTierUpAtReturn: 539 case CheckTierUpAndOSREnter: 540 case InvalidationPoint: 541 case CheckInBounds: 542 case ValueToInt32: 543 case HardPhantom: 544 case DoubleRep: 545 case ValueRep: 546 case Int52Rep: 547 case DoubleConstant: 548 case Int52Constant: 549 case Identity: 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(); 554 break; 555 } 556 557 case Phi: 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(); 561 break; 562 563 case Upsilon: 564 case GetArgument: 565 // These don't get inserted until we go into SSA. 566 RELEASE_ASSERT_NOT_REACHED(); 567 break; 568 569 case GetScope: 570 changed |= setPrediction(SpecObjectOther); 571 break; 572 573 case In: 574 changed |= setPrediction(SpecBoolean); 575 break; 576 577#ifndef NDEBUG 578 // These get ignored because they don't return anything. 579 case StoreBarrier: 580 case StoreBarrierWithNullCheck: 581 case PutByValDirect: 582 case PutByVal: 583 case PutClosureVar: 584 case Return: 585 case Throw: 586 case PutById: 587 case PutByIdFlush: 588 case PutByIdDirect: 589 case PutByOffset: 590 case MultiPutByOffset: 591 case DFG::Jump: 592 case Branch: 593 case Switch: 594 case Breakpoint: 595 case ProfileWillCall: 596 case ProfileDidCall: 597 case CheckHasInstance: 598 case ThrowReferenceError: 599 case ForceOSRExit: 600 case SetArgument: 601 case CheckStructure: 602 case CheckExecutable: 603 case StructureTransitionWatchpoint: 604 case CheckFunction: 605 case PutStructure: 606 case TearOffActivation: 607 case TearOffArguments: 608 case CheckArgumentsNotCreated: 609 case VariableWatchpoint: 610 case VarInjectionWatchpoint: 611 case AllocationProfileWatchpoint: 612 case Phantom: 613 case Check: 614 case PutGlobalVar: 615 case CheckWatchdogTimer: 616 case Unreachable: 617 case LoopHint: 618 case NotifyWrite: 619 case FunctionReentryWatchpoint: 620 case TypedArrayWatchpoint: 621 case ConstantStoragePointer: 622 case MovHint: 623 case ZombieHint: 624 break; 625 626 // This gets ignored because it already has a prediction. 627 case ExtractOSREntryLocal: 628 break; 629 630 // These gets ignored because it doesn't do anything. 631 case CountExecution: 632 case PhantomLocal: 633 case Flush: 634 break; 635 636 case LastNodeType: 637 RELEASE_ASSERT_NOT_REACHED(); 638 break; 639#else 640 default: 641 break; 642#endif 643 } 644 645 m_changed |= changed; 646 } 647 648 void propagateForward() 649 { 650 for (BlockIndex blockIndex = 0; blockIndex < m_graph.numBlocks(); ++blockIndex) { 651 BasicBlock* block = m_graph.block(blockIndex); 652 if (!block) 653 continue; 654 ASSERT(block->isReachable); 655 for (unsigned i = 0; i < block->size(); ++i) { 656 m_currentNode = block->at(i); 657 propagate(m_currentNode); 658 } 659 } 660 } 661 662 void propagateBackward() 663 { 664 for (BlockIndex blockIndex = m_graph.numBlocks(); blockIndex--;) { 665 BasicBlock* block = m_graph.block(blockIndex); 666 if (!block) 667 continue; 668 ASSERT(block->isReachable); 669 for (unsigned i = block->size(); i--;) { 670 m_currentNode = block->at(i); 671 propagate(m_currentNode); 672 } 673 } 674 } 675 676 void doDoubleVoting(Node* node, float weight) 677 { 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) 682 weight = 1; 683 684 switch (node->op()) { 685 case ValueAdd: 686 case ArithAdd: 687 case ArithSub: { 688 SpeculatedType left = node->child1()->prediction(); 689 SpeculatedType right = node->child2()->prediction(); 690 691 DoubleBallot ballot; 692 693 if (isFullNumberSpeculation(left) 694 && isFullNumberSpeculation(right) 695 && !m_graph.addShouldSpeculateInt32(node, m_pass) 696 && !m_graph.addShouldSpeculateMachineInt(node)) 697 ballot = VoteDouble; 698 else 699 ballot = VoteValue; 700 701 m_graph.voteNode(node->child1(), ballot, weight); 702 m_graph.voteNode(node->child2(), ballot, weight); 703 break; 704 } 705 706 case ArithMul: { 707 SpeculatedType left = node->child1()->prediction(); 708 SpeculatedType right = node->child2()->prediction(); 709 710 DoubleBallot ballot; 711 712 if (isFullNumberSpeculation(left) 713 && isFullNumberSpeculation(right) 714 && !m_graph.mulShouldSpeculateInt32(node, m_pass) 715 && !m_graph.mulShouldSpeculateMachineInt(node, m_pass)) 716 ballot = VoteDouble; 717 else 718 ballot = VoteValue; 719 720 m_graph.voteNode(node->child1(), ballot, weight); 721 m_graph.voteNode(node->child2(), ballot, weight); 722 break; 723 } 724 725 case ArithMin: 726 case ArithMax: 727 case ArithMod: 728 case ArithDiv: { 729 SpeculatedType left = node->child1()->prediction(); 730 SpeculatedType right = node->child2()->prediction(); 731 732 DoubleBallot ballot; 733 734 if (isFullNumberSpeculation(left) 735 && isFullNumberSpeculation(right) 736 && !(Node::shouldSpeculateInt32OrBooleanForArithmetic(node->child1().node(), node->child2().node()) && node->canSpeculateInt32(m_pass))) 737 ballot = VoteDouble; 738 else 739 ballot = VoteValue; 740 741 m_graph.voteNode(node->child1(), ballot, weight); 742 m_graph.voteNode(node->child2(), ballot, weight); 743 break; 744 } 745 746 case ArithAbs: 747 DoubleBallot ballot; 748 if (node->child1()->shouldSpeculateNumber() 749 && !(node->child1()->shouldSpeculateInt32OrBooleanForArithmetic() && node->canSpeculateInt32(m_pass))) 750 ballot = VoteDouble; 751 else 752 ballot = VoteValue; 753 754 m_graph.voteNode(node->child1(), ballot, weight); 755 break; 756 757 case ArithSqrt: 758 case ArithCos: 759 case ArithSin: 760 if (node->child1()->shouldSpeculateNumber()) 761 m_graph.voteNode(node->child1(), VoteDouble, weight); 762 else 763 m_graph.voteNode(node->child1(), VoteValue, weight); 764 break; 765 766 case SetLocal: { 767 SpeculatedType prediction = node->child1()->prediction(); 768 if (isDoubleSpeculation(prediction)) 769 node->variableAccessData()->vote(VoteDouble, weight); 770 else if ( 771 !isFullNumberSpeculation(prediction) 772 || isInt32Speculation(prediction) || isMachineIntSpeculation(prediction)) 773 node->variableAccessData()->vote(VoteValue, weight); 774 break; 775 } 776 777 case PutByValDirect: 778 case PutByVal: 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()) { 786 case Array::Double: 787 m_graph.voteNode(child3, VoteDouble, weight); 788 break; 789 default: 790 m_graph.voteNode(child3, VoteValue, weight); 791 break; 792 } 793 break; 794 } 795 796 case MovHint: 797 // Ignore these since they have no effect on in-DFG execution. 798 break; 799 800 default: 801 m_graph.voteChildren(node, VoteValue, weight); 802 break; 803 } 804 } 805 806 void doRoundOfDoubleVoting() 807 { 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); 812 if (!block) 813 continue; 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); 818 } 819 } 820 for (unsigned i = 0; i < m_graph.m_variableAccessData.size(); ++i) { 821 VariableAccessData* variableAccessData = &m_graph.m_variableAccessData[i]; 822 if (!variableAccessData->isRoot()) 823 continue; 824 m_changed |= variableAccessData->tallyVotesForShouldUseDoubleFormat(); 825 } 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()) 831 continue; 832 m_changed |= variableAccessData->makePredictionForDoubleFormat(); 833 } 834 } 835 836 Node* m_currentNode; 837 bool m_changed; 838 PredictionPass m_pass; // We use different logic for considering predictions depending on how far along we are in propagation. 839}; 840 841bool performPredictionPropagation(Graph& graph) 842{ 843 SamplingRegion samplingRegion("DFG Prediction Propagation Phase"); 844 return runPhase<PredictionPropagationPhase>(graph); 845} 846 847} } // namespace JSC::DFG 848 849#endif // ENABLE(DFG_JIT) 850 851