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#ifndef DFGNode_h 27#define DFGNode_h 28 29#if ENABLE(DFG_JIT) 30 31#include "CodeBlock.h" 32#include "DFGAbstractValue.h" 33#include "DFGAdjacencyList.h" 34#include "DFGArithMode.h" 35#include "DFGArrayMode.h" 36#include "DFGCommon.h" 37#include "DFGLazyJSValue.h" 38#include "DFGNodeFlags.h" 39#include "DFGNodeOrigin.h" 40#include "DFGNodeType.h" 41#include "DFGUseKind.h" 42#include "DFGVariableAccessData.h" 43#include "GetByIdVariant.h" 44#include "JSCJSValue.h" 45#include "Operands.h" 46#include "PutByIdVariant.h" 47#include "SpeculatedType.h" 48#include "StructureSet.h" 49#include "ValueProfile.h" 50#include <wtf/ListDump.h> 51 52namespace JSC { namespace DFG { 53 54class Graph; 55struct BasicBlock; 56 57struct MultiGetByOffsetData { 58 unsigned identifierNumber; 59 Vector<GetByIdVariant, 2> variants; 60}; 61 62struct MultiPutByOffsetData { 63 unsigned identifierNumber; 64 Vector<PutByIdVariant, 2> variants; 65 66 bool writesStructures() const; 67 bool reallocatesStorage() const; 68}; 69 70struct StructureTransitionData { 71 Structure* previousStructure; 72 Structure* newStructure; 73 74 StructureTransitionData() { } 75 76 StructureTransitionData(Structure* previousStructure, Structure* newStructure) 77 : previousStructure(previousStructure) 78 , newStructure(newStructure) 79 { 80 } 81}; 82 83struct NewArrayBufferData { 84 unsigned startConstant; 85 unsigned numConstants; 86 IndexingType indexingType; 87}; 88 89struct BranchTarget { 90 BranchTarget() 91 : block(0) 92 , count(PNaN) 93 { 94 } 95 96 explicit BranchTarget(BasicBlock* block) 97 : block(block) 98 , count(PNaN) 99 { 100 } 101 102 void setBytecodeIndex(unsigned bytecodeIndex) 103 { 104 block = bitwise_cast<BasicBlock*>(static_cast<uintptr_t>(bytecodeIndex)); 105 } 106 unsigned bytecodeIndex() const { return bitwise_cast<uintptr_t>(block); } 107 108 void dump(PrintStream&) const; 109 110 BasicBlock* block; 111 float count; 112}; 113 114struct BranchData { 115 static BranchData withBytecodeIndices( 116 unsigned takenBytecodeIndex, unsigned notTakenBytecodeIndex) 117 { 118 BranchData result; 119 result.taken.block = bitwise_cast<BasicBlock*>(static_cast<uintptr_t>(takenBytecodeIndex)); 120 result.notTaken.block = bitwise_cast<BasicBlock*>(static_cast<uintptr_t>(notTakenBytecodeIndex)); 121 return result; 122 } 123 124 unsigned takenBytecodeIndex() const { return taken.bytecodeIndex(); } 125 unsigned notTakenBytecodeIndex() const { return notTaken.bytecodeIndex(); } 126 127 BasicBlock*& forCondition(bool condition) 128 { 129 if (condition) 130 return taken.block; 131 return notTaken.block; 132 } 133 134 BranchTarget taken; 135 BranchTarget notTaken; 136}; 137 138// The SwitchData and associated data structures duplicate the information in 139// JumpTable. The DFG may ultimately end up using the JumpTable, though it may 140// instead decide to do something different - this is entirely up to the DFG. 141// These data structures give the DFG a higher-level semantic description of 142// what is going on, which will allow it to make the right decision. 143// 144// Note that there will never be multiple SwitchCases in SwitchData::cases that 145// have the same SwitchCase::value, since the bytecode's JumpTables never have 146// duplicates - since the JumpTable maps a value to a target. It's a 147// one-to-many mapping. So we may have duplicate targets, but never duplicate 148// values. 149struct SwitchCase { 150 SwitchCase() 151 { 152 } 153 154 SwitchCase(LazyJSValue value, BasicBlock* target) 155 : value(value) 156 , target(target) 157 { 158 } 159 160 static SwitchCase withBytecodeIndex(LazyJSValue value, unsigned bytecodeIndex) 161 { 162 SwitchCase result; 163 result.value = value; 164 result.target.setBytecodeIndex(bytecodeIndex); 165 return result; 166 } 167 168 LazyJSValue value; 169 BranchTarget target; 170}; 171 172enum SwitchKind { 173 SwitchImm, 174 SwitchChar, 175 SwitchString 176}; 177 178struct SwitchData { 179 // Initializes most fields to obviously invalid values. Anyone 180 // constructing this should make sure to initialize everything they 181 // care about manually. 182 SwitchData() 183 : kind(static_cast<SwitchKind>(-1)) 184 , switchTableIndex(UINT_MAX) 185 , didUseJumpTable(false) 186 { 187 } 188 189 Vector<SwitchCase> cases; 190 BranchTarget fallThrough; 191 SwitchKind kind; 192 unsigned switchTableIndex; 193 bool didUseJumpTable; 194}; 195 196// This type used in passing an immediate argument to Node constructor; 197// distinguishes an immediate value (typically an index into a CodeBlock data structure - 198// a constant index, argument, or identifier) from a Node*. 199struct OpInfo { 200 explicit OpInfo(int32_t value) : m_value(static_cast<uintptr_t>(value)) { } 201 explicit OpInfo(uint32_t value) : m_value(static_cast<uintptr_t>(value)) { } 202#if OS(DARWIN) || USE(JSVALUE64) 203 explicit OpInfo(size_t value) : m_value(static_cast<uintptr_t>(value)) { } 204#endif 205 explicit OpInfo(void* value) : m_value(reinterpret_cast<uintptr_t>(value)) { } 206 uintptr_t m_value; 207}; 208 209// === Node === 210// 211// Node represents a single operation in the data flow graph. 212struct Node { 213 enum VarArgTag { VarArg }; 214 215 Node() { } 216 217 Node(NodeType op, NodeOrigin nodeOrigin, const AdjacencyList& children) 218 : origin(nodeOrigin) 219 , children(children) 220 , m_virtualRegister(VirtualRegister()) 221 , m_refCount(1) 222 , m_prediction(SpecNone) 223 { 224 misc.replacement = 0; 225 setOpAndDefaultFlags(op); 226 } 227 228 // Construct a node with up to 3 children, no immediate value. 229 Node(NodeType op, NodeOrigin nodeOrigin, Edge child1 = Edge(), Edge child2 = Edge(), Edge child3 = Edge()) 230 : origin(nodeOrigin) 231 , children(AdjacencyList::Fixed, child1, child2, child3) 232 , m_virtualRegister(VirtualRegister()) 233 , m_refCount(1) 234 , m_prediction(SpecNone) 235 , m_opInfo(0) 236 , m_opInfo2(0) 237 { 238 misc.replacement = 0; 239 setOpAndDefaultFlags(op); 240 ASSERT(!(m_flags & NodeHasVarArgs)); 241 } 242 243 // Construct a node with up to 3 children, no immediate value. 244 Node(NodeFlags result, NodeType op, NodeOrigin nodeOrigin, Edge child1 = Edge(), Edge child2 = Edge(), Edge child3 = Edge()) 245 : origin(nodeOrigin) 246 , children(AdjacencyList::Fixed, child1, child2, child3) 247 , m_virtualRegister(VirtualRegister()) 248 , m_refCount(1) 249 , m_prediction(SpecNone) 250 , m_opInfo(0) 251 , m_opInfo2(0) 252 { 253 misc.replacement = 0; 254 setOpAndDefaultFlags(op); 255 setResult(result); 256 ASSERT(!(m_flags & NodeHasVarArgs)); 257 } 258 259 // Construct a node with up to 3 children and an immediate value. 260 Node(NodeType op, NodeOrigin nodeOrigin, OpInfo imm, Edge child1 = Edge(), Edge child2 = Edge(), Edge child3 = Edge()) 261 : origin(nodeOrigin) 262 , children(AdjacencyList::Fixed, child1, child2, child3) 263 , m_virtualRegister(VirtualRegister()) 264 , m_refCount(1) 265 , m_prediction(SpecNone) 266 , m_opInfo(imm.m_value) 267 , m_opInfo2(0) 268 { 269 misc.replacement = 0; 270 setOpAndDefaultFlags(op); 271 ASSERT(!(m_flags & NodeHasVarArgs)); 272 } 273 274 // Construct a node with up to 3 children and an immediate value. 275 Node(NodeFlags result, NodeType op, NodeOrigin nodeOrigin, OpInfo imm, Edge child1 = Edge(), Edge child2 = Edge(), Edge child3 = Edge()) 276 : origin(nodeOrigin) 277 , children(AdjacencyList::Fixed, child1, child2, child3) 278 , m_virtualRegister(VirtualRegister()) 279 , m_refCount(1) 280 , m_prediction(SpecNone) 281 , m_opInfo(imm.m_value) 282 , m_opInfo2(0) 283 { 284 misc.replacement = 0; 285 setOpAndDefaultFlags(op); 286 setResult(result); 287 ASSERT(!(m_flags & NodeHasVarArgs)); 288 } 289 290 // Construct a node with up to 3 children and two immediate values. 291 Node(NodeType op, NodeOrigin nodeOrigin, OpInfo imm1, OpInfo imm2, Edge child1 = Edge(), Edge child2 = Edge(), Edge child3 = Edge()) 292 : origin(nodeOrigin) 293 , children(AdjacencyList::Fixed, child1, child2, child3) 294 , m_virtualRegister(VirtualRegister()) 295 , m_refCount(1) 296 , m_prediction(SpecNone) 297 , m_opInfo(imm1.m_value) 298 , m_opInfo2(imm2.m_value) 299 { 300 misc.replacement = 0; 301 setOpAndDefaultFlags(op); 302 ASSERT(!(m_flags & NodeHasVarArgs)); 303 } 304 305 // Construct a node with a variable number of children and two immediate values. 306 Node(VarArgTag, NodeType op, NodeOrigin nodeOrigin, OpInfo imm1, OpInfo imm2, unsigned firstChild, unsigned numChildren) 307 : origin(nodeOrigin) 308 , children(AdjacencyList::Variable, firstChild, numChildren) 309 , m_virtualRegister(VirtualRegister()) 310 , m_refCount(1) 311 , m_prediction(SpecNone) 312 , m_opInfo(imm1.m_value) 313 , m_opInfo2(imm2.m_value) 314 { 315 misc.replacement = 0; 316 setOpAndDefaultFlags(op); 317 ASSERT(m_flags & NodeHasVarArgs); 318 } 319 320 NodeType op() const { return static_cast<NodeType>(m_op); } 321 NodeFlags flags() const { return m_flags; } 322 323 // This is not a fast method. 324 unsigned index() const; 325 326 void setOp(NodeType op) 327 { 328 m_op = op; 329 } 330 331 void setFlags(NodeFlags flags) 332 { 333 m_flags = flags; 334 } 335 336 bool mergeFlags(NodeFlags flags) 337 { 338 ASSERT(!(flags & NodeDoesNotExit)); 339 NodeFlags newFlags = m_flags | flags; 340 if (newFlags == m_flags) 341 return false; 342 m_flags = newFlags; 343 return true; 344 } 345 346 bool filterFlags(NodeFlags flags) 347 { 348 ASSERT(flags & NodeDoesNotExit); 349 NodeFlags newFlags = m_flags & flags; 350 if (newFlags == m_flags) 351 return false; 352 m_flags = newFlags; 353 return true; 354 } 355 356 bool clearFlags(NodeFlags flags) 357 { 358 return filterFlags(~flags); 359 } 360 361 void setResult(NodeFlags result) 362 { 363 ASSERT(!(result & ~NodeResultMask)); 364 clearFlags(NodeResultMask); 365 mergeFlags(result); 366 } 367 368 NodeFlags result() const 369 { 370 return flags() & NodeResultMask; 371 } 372 373 void setOpAndDefaultFlags(NodeType op) 374 { 375 m_op = op; 376 m_flags = defaultFlags(op); 377 } 378 379 void convertToPhantom() 380 { 381 setOpAndDefaultFlags(Phantom); 382 } 383 384 void convertToPhantomUnchecked() 385 { 386 setOpAndDefaultFlags(Phantom); 387 } 388 389 void convertToIdentity(); 390 391 bool mustGenerate() 392 { 393 return m_flags & NodeMustGenerate; 394 } 395 396 void setCanExit(bool exits) 397 { 398 if (exits) 399 m_flags &= ~NodeDoesNotExit; 400 else 401 m_flags |= NodeDoesNotExit; 402 } 403 404 bool canExit() 405 { 406 return !(m_flags & NodeDoesNotExit); 407 } 408 409 bool isConstant() 410 { 411 switch (op()) { 412 case JSConstant: 413 case DoubleConstant: 414 case Int52Constant: 415 return true; 416 default: 417 return false; 418 } 419 } 420 421 bool isWeakConstant() 422 { 423 return op() == WeakJSConstant; 424 } 425 426 bool isPhantomArguments() 427 { 428 return op() == PhantomArguments; 429 } 430 431 bool hasConstant() 432 { 433 switch (op()) { 434 case JSConstant: 435 case DoubleConstant: 436 case Int52Constant: 437 case WeakJSConstant: 438 case PhantomArguments: 439 return true; 440 default: 441 return false; 442 } 443 } 444 445 unsigned constantNumber() 446 { 447 ASSERT(isConstant()); 448 return m_opInfo; 449 } 450 451 void convertToConstant(unsigned constantNumber) 452 { 453 if (hasDoubleResult()) 454 m_op = DoubleConstant; 455 else if (hasInt52Result()) 456 m_op = Int52Constant; 457 else 458 m_op = JSConstant; 459 m_flags &= ~(NodeMustGenerate | NodeMightClobber | NodeClobbersWorld); 460 m_opInfo = constantNumber; 461 children.reset(); 462 } 463 464 void convertToWeakConstant(JSCell* cell) 465 { 466 m_op = WeakJSConstant; 467 m_flags &= ~(NodeMustGenerate | NodeMightClobber | NodeClobbersWorld); 468 m_opInfo = bitwise_cast<uintptr_t>(cell); 469 children.reset(); 470 } 471 472 void convertToConstantStoragePointer(void* pointer) 473 { 474 ASSERT(op() == GetIndexedPropertyStorage); 475 m_op = ConstantStoragePointer; 476 m_opInfo = bitwise_cast<uintptr_t>(pointer); 477 } 478 479 void convertToGetLocalUnlinked(VirtualRegister local) 480 { 481 m_op = GetLocalUnlinked; 482 m_flags &= ~(NodeMustGenerate | NodeMightClobber | NodeClobbersWorld); 483 m_opInfo = local.offset(); 484 m_opInfo2 = VirtualRegister().offset(); 485 children.reset(); 486 } 487 488 void convertToStructureTransitionWatchpoint(Structure* structure) 489 { 490 ASSERT(m_op == CheckStructure || m_op == ArrayifyToStructure); 491 ASSERT(!child2()); 492 ASSERT(!child3()); 493 m_opInfo = bitwise_cast<uintptr_t>(structure); 494 m_op = StructureTransitionWatchpoint; 495 } 496 497 void convertToStructureTransitionWatchpoint() 498 { 499 convertToStructureTransitionWatchpoint(structureSet().singletonStructure()); 500 } 501 502 void convertToGetByOffset(unsigned storageAccessDataIndex, Edge storage) 503 { 504 ASSERT(m_op == GetById || m_op == GetByIdFlush || m_op == MultiGetByOffset); 505 m_opInfo = storageAccessDataIndex; 506 children.setChild2(children.child1()); 507 children.child2().setUseKind(KnownCellUse); 508 children.setChild1(storage); 509 m_op = GetByOffset; 510 m_flags &= ~NodeClobbersWorld; 511 } 512 513 void convertToPutByOffset(unsigned storageAccessDataIndex, Edge storage) 514 { 515 ASSERT(m_op == PutById || m_op == PutByIdDirect || m_op == MultiPutByOffset); 516 m_opInfo = storageAccessDataIndex; 517 children.setChild3(children.child2()); 518 children.setChild2(children.child1()); 519 children.setChild1(storage); 520 m_op = PutByOffset; 521 m_flags &= ~NodeClobbersWorld; 522 } 523 524 void convertToPhantomLocal() 525 { 526 ASSERT(m_op == Phantom && (child1()->op() == Phi || child1()->op() == SetLocal || child1()->op() == SetArgument)); 527 m_op = PhantomLocal; 528 m_opInfo = child1()->m_opInfo; // Copy the variableAccessData. 529 children.setChild1(Edge()); 530 } 531 532 void convertToGetLocal(VariableAccessData* variable, Node* phi) 533 { 534 ASSERT(m_op == GetLocalUnlinked); 535 m_op = GetLocal; 536 m_opInfo = bitwise_cast<uintptr_t>(variable); 537 m_opInfo2 = 0; 538 children.setChild1(Edge(phi)); 539 } 540 541 void convertToToString() 542 { 543 ASSERT(m_op == ToPrimitive); 544 m_op = ToString; 545 } 546 547 JSCell* weakConstant() 548 { 549 ASSERT(op() == WeakJSConstant); 550 return bitwise_cast<JSCell*>(m_opInfo); 551 } 552 553 JSValue valueOfJSConstant(CodeBlock* codeBlock) 554 { 555 switch (op()) { 556 case WeakJSConstant: 557 return JSValue(weakConstant()); 558 case JSConstant: 559 case DoubleConstant: 560 case Int52Constant: 561 return codeBlock->constantRegister(FirstConstantRegisterIndex + constantNumber()).get(); 562 case PhantomArguments: 563 return JSValue(); 564 default: 565 RELEASE_ASSERT_NOT_REACHED(); 566 return JSValue(); // Have to return something in release mode. 567 } 568 } 569 570 bool isInt32Constant(CodeBlock* codeBlock) 571 { 572 return isConstant() && valueOfJSConstant(codeBlock).isInt32(); 573 } 574 575 bool isDoubleConstant(CodeBlock* codeBlock) 576 { 577 bool result = isConstant() && valueOfJSConstant(codeBlock).isDouble(); 578 if (result) 579 ASSERT(!isInt32Constant(codeBlock)); 580 return result; 581 } 582 583 bool isNumberConstant(CodeBlock* codeBlock) 584 { 585 bool result = isConstant() && valueOfJSConstant(codeBlock).isNumber(); 586 ASSERT(result == (isInt32Constant(codeBlock) || isDoubleConstant(codeBlock))); 587 return result; 588 } 589 590 bool isMachineIntConstant(CodeBlock* codeBlock) 591 { 592 return isConstant() && valueOfJSConstant(codeBlock).isMachineInt(); 593 } 594 595 bool isBooleanConstant(CodeBlock* codeBlock) 596 { 597 return isConstant() && valueOfJSConstant(codeBlock).isBoolean(); 598 } 599 600 bool containsMovHint() 601 { 602 switch (op()) { 603 case MovHint: 604 case ZombieHint: 605 return true; 606 default: 607 return false; 608 } 609 } 610 611 bool hasVariableAccessData(Graph&); 612 bool hasLocal(Graph& graph) 613 { 614 return hasVariableAccessData(graph); 615 } 616 617 // This is useful for debugging code, where a node that should have a variable 618 // access data doesn't have one because it hasn't been initialized yet. 619 VariableAccessData* tryGetVariableAccessData() 620 { 621 VariableAccessData* result = reinterpret_cast<VariableAccessData*>(m_opInfo); 622 if (!result) 623 return 0; 624 return result->find(); 625 } 626 627 VariableAccessData* variableAccessData() 628 { 629 return reinterpret_cast<VariableAccessData*>(m_opInfo)->find(); 630 } 631 632 VirtualRegister local() 633 { 634 return variableAccessData()->local(); 635 } 636 637 VirtualRegister machineLocal() 638 { 639 return variableAccessData()->machineLocal(); 640 } 641 642 bool hasUnlinkedLocal() 643 { 644 switch (op()) { 645 case GetLocalUnlinked: 646 case ExtractOSREntryLocal: 647 case MovHint: 648 case ZombieHint: 649 return true; 650 default: 651 return false; 652 } 653 } 654 655 VirtualRegister unlinkedLocal() 656 { 657 ASSERT(hasUnlinkedLocal()); 658 return static_cast<VirtualRegister>(m_opInfo); 659 } 660 661 bool hasUnlinkedMachineLocal() 662 { 663 return op() == GetLocalUnlinked; 664 } 665 666 void setUnlinkedMachineLocal(VirtualRegister reg) 667 { 668 ASSERT(hasUnlinkedMachineLocal()); 669 m_opInfo2 = reg.offset(); 670 } 671 672 VirtualRegister unlinkedMachineLocal() 673 { 674 ASSERT(hasUnlinkedMachineLocal()); 675 return VirtualRegister(m_opInfo2); 676 } 677 678 bool hasPhi() 679 { 680 return op() == Upsilon; 681 } 682 683 Node* phi() 684 { 685 ASSERT(hasPhi()); 686 return bitwise_cast<Node*>(m_opInfo); 687 } 688 689 bool isStoreBarrier() 690 { 691 switch (op()) { 692 case StoreBarrier: 693 case StoreBarrierWithNullCheck: 694 return true; 695 default: 696 return false; 697 } 698 } 699 700 bool hasIdentifier() 701 { 702 switch (op()) { 703 case GetById: 704 case GetByIdFlush: 705 case PutById: 706 case PutByIdFlush: 707 case PutByIdDirect: 708 return true; 709 default: 710 return false; 711 } 712 } 713 714 unsigned identifierNumber() 715 { 716 ASSERT(hasIdentifier()); 717 return m_opInfo; 718 } 719 720 bool hasArithNodeFlags() 721 { 722 switch (op()) { 723 case UInt32ToNumber: 724 case ArithAdd: 725 case ArithSub: 726 case ArithNegate: 727 case ArithMul: 728 case ArithAbs: 729 case ArithMin: 730 case ArithMax: 731 case ArithMod: 732 case ArithDiv: 733 case ValueAdd: 734 return true; 735 default: 736 return false; 737 } 738 } 739 740 // This corrects the arithmetic node flags, so that irrelevant bits are 741 // ignored. In particular, anything other than ArithMul does not need 742 // to know if it can speculate on negative zero. 743 NodeFlags arithNodeFlags() 744 { 745 NodeFlags result = m_flags & NodeArithFlagsMask; 746 if (op() == ArithMul || op() == ArithDiv || op() == ArithMod || op() == ArithNegate || op() == DoubleAsInt32) 747 return result; 748 return result & ~NodeBytecodeNeedsNegZero; 749 } 750 751 bool hasConstantBuffer() 752 { 753 return op() == NewArrayBuffer; 754 } 755 756 NewArrayBufferData* newArrayBufferData() 757 { 758 ASSERT(hasConstantBuffer()); 759 return reinterpret_cast<NewArrayBufferData*>(m_opInfo); 760 } 761 762 unsigned startConstant() 763 { 764 return newArrayBufferData()->startConstant; 765 } 766 767 unsigned numConstants() 768 { 769 return newArrayBufferData()->numConstants; 770 } 771 772 bool hasIndexingType() 773 { 774 switch (op()) { 775 case NewArray: 776 case NewArrayWithSize: 777 case NewArrayBuffer: 778 return true; 779 default: 780 return false; 781 } 782 } 783 784 IndexingType indexingType() 785 { 786 ASSERT(hasIndexingType()); 787 if (op() == NewArrayBuffer) 788 return newArrayBufferData()->indexingType; 789 return m_opInfo; 790 } 791 792 bool hasTypedArrayType() 793 { 794 switch (op()) { 795 case NewTypedArray: 796 return true; 797 default: 798 return false; 799 } 800 } 801 802 TypedArrayType typedArrayType() 803 { 804 ASSERT(hasTypedArrayType()); 805 TypedArrayType result = static_cast<TypedArrayType>(m_opInfo); 806 ASSERT(isTypedView(result)); 807 return result; 808 } 809 810 bool hasInlineCapacity() 811 { 812 return op() == CreateThis; 813 } 814 815 unsigned inlineCapacity() 816 { 817 ASSERT(hasInlineCapacity()); 818 return m_opInfo; 819 } 820 821 void setIndexingType(IndexingType indexingType) 822 { 823 ASSERT(hasIndexingType()); 824 m_opInfo = indexingType; 825 } 826 827 bool hasRegexpIndex() 828 { 829 return op() == NewRegexp; 830 } 831 832 unsigned regexpIndex() 833 { 834 ASSERT(hasRegexpIndex()); 835 return m_opInfo; 836 } 837 838 bool hasVarNumber() 839 { 840 return op() == GetClosureVar || op() == PutClosureVar; 841 } 842 843 int varNumber() 844 { 845 ASSERT(hasVarNumber()); 846 return m_opInfo; 847 } 848 849 bool hasRegisterPointer() 850 { 851 return op() == GetGlobalVar || op() == PutGlobalVar; 852 } 853 854 WriteBarrier<Unknown>* registerPointer() 855 { 856 return bitwise_cast<WriteBarrier<Unknown>*>(m_opInfo); 857 } 858 859 bool hasResult() 860 { 861 return !!result(); 862 } 863 864 bool hasInt32Result() 865 { 866 return result() == NodeResultInt32; 867 } 868 869 bool hasInt52Result() 870 { 871 return result() == NodeResultInt52; 872 } 873 874 bool hasNumberResult() 875 { 876 return result() == NodeResultNumber; 877 } 878 879 bool hasDoubleResult() 880 { 881 return result() == NodeResultDouble; 882 } 883 884 bool hasJSResult() 885 { 886 return result() == NodeResultJS; 887 } 888 889 bool hasBooleanResult() 890 { 891 return result() == NodeResultBoolean; 892 } 893 894 bool hasStorageResult() 895 { 896 return result() == NodeResultStorage; 897 } 898 899 UseKind defaultUseKind() 900 { 901 return useKindForResult(result()); 902 } 903 904 Edge defaultEdge() 905 { 906 return Edge(this, defaultUseKind()); 907 } 908 909 bool isJump() 910 { 911 return op() == Jump; 912 } 913 914 bool isBranch() 915 { 916 return op() == Branch; 917 } 918 919 bool isSwitch() 920 { 921 return op() == Switch; 922 } 923 924 bool isTerminal() 925 { 926 switch (op()) { 927 case Jump: 928 case Branch: 929 case Switch: 930 case Return: 931 case Unreachable: 932 return true; 933 default: 934 return false; 935 } 936 } 937 938 unsigned targetBytecodeOffsetDuringParsing() 939 { 940 ASSERT(isJump()); 941 return m_opInfo; 942 } 943 944 BasicBlock*& targetBlock() 945 { 946 ASSERT(isJump()); 947 return *bitwise_cast<BasicBlock**>(&m_opInfo); 948 } 949 950 BranchData* branchData() 951 { 952 ASSERT(isBranch()); 953 return bitwise_cast<BranchData*>(m_opInfo); 954 } 955 956 SwitchData* switchData() 957 { 958 ASSERT(isSwitch()); 959 return bitwise_cast<SwitchData*>(m_opInfo); 960 } 961 962 unsigned numSuccessors() 963 { 964 switch (op()) { 965 case Jump: 966 return 1; 967 case Branch: 968 return 2; 969 case Switch: 970 return switchData()->cases.size() + 1; 971 default: 972 return 0; 973 } 974 } 975 976 BasicBlock*& successor(unsigned index) 977 { 978 if (isSwitch()) { 979 if (index < switchData()->cases.size()) 980 return switchData()->cases[index].target.block; 981 RELEASE_ASSERT(index == switchData()->cases.size()); 982 return switchData()->fallThrough.block; 983 } 984 switch (index) { 985 case 0: 986 if (isJump()) 987 return targetBlock(); 988 return branchData()->taken.block; 989 case 1: 990 return branchData()->notTaken.block; 991 default: 992 RELEASE_ASSERT_NOT_REACHED(); 993 return targetBlock(); 994 } 995 } 996 997 BasicBlock*& successorForCondition(bool condition) 998 { 999 return branchData()->forCondition(condition); 1000 } 1001 1002 bool hasHeapPrediction() 1003 { 1004 switch (op()) { 1005 case GetById: 1006 case GetByIdFlush: 1007 case GetByVal: 1008 case GetMyArgumentByVal: 1009 case GetMyArgumentByValSafe: 1010 case Call: 1011 case Construct: 1012 case GetByOffset: 1013 case MultiGetByOffset: 1014 case GetClosureVar: 1015 case ArrayPop: 1016 case ArrayPush: 1017 case RegExpExec: 1018 case RegExpTest: 1019 case GetGlobalVar: 1020 return true; 1021 default: 1022 return false; 1023 } 1024 } 1025 1026 SpeculatedType getHeapPrediction() 1027 { 1028 ASSERT(hasHeapPrediction()); 1029 return static_cast<SpeculatedType>(m_opInfo2); 1030 } 1031 1032 bool predictHeap(SpeculatedType prediction) 1033 { 1034 ASSERT(hasHeapPrediction()); 1035 1036 return mergeSpeculation(m_opInfo2, prediction); 1037 } 1038 1039 void setHeapPrediction(SpeculatedType prediction) 1040 { 1041 ASSERT(hasHeapPrediction()); 1042 m_opInfo2 = prediction; 1043 } 1044 1045 bool hasFunction() 1046 { 1047 switch (op()) { 1048 case CheckFunction: 1049 case AllocationProfileWatchpoint: 1050 return true; 1051 default: 1052 return false; 1053 } 1054 } 1055 1056 JSCell* function() 1057 { 1058 ASSERT(hasFunction()); 1059 JSCell* result = reinterpret_cast<JSFunction*>(m_opInfo); 1060 ASSERT(JSValue(result).isFunction()); 1061 return result; 1062 } 1063 1064 bool hasExecutable() 1065 { 1066 return op() == CheckExecutable; 1067 } 1068 1069 ExecutableBase* executable() 1070 { 1071 return jsCast<ExecutableBase*>(reinterpret_cast<JSCell*>(m_opInfo)); 1072 } 1073 1074 bool hasVariableWatchpointSet() 1075 { 1076 return op() == NotifyWrite || op() == VariableWatchpoint; 1077 } 1078 1079 VariableWatchpointSet* variableWatchpointSet() 1080 { 1081 return reinterpret_cast<VariableWatchpointSet*>(m_opInfo); 1082 } 1083 1084 bool hasTypedArray() 1085 { 1086 return op() == TypedArrayWatchpoint; 1087 } 1088 1089 JSArrayBufferView* typedArray() 1090 { 1091 return reinterpret_cast<JSArrayBufferView*>(m_opInfo); 1092 } 1093 1094 bool hasStoragePointer() 1095 { 1096 return op() == ConstantStoragePointer; 1097 } 1098 1099 void* storagePointer() 1100 { 1101 return reinterpret_cast<void*>(m_opInfo); 1102 } 1103 1104 bool hasStructureTransitionData() 1105 { 1106 switch (op()) { 1107 case PutStructure: 1108 case PhantomPutStructure: 1109 case AllocatePropertyStorage: 1110 case ReallocatePropertyStorage: 1111 return true; 1112 default: 1113 return false; 1114 } 1115 } 1116 1117 StructureTransitionData& structureTransitionData() 1118 { 1119 ASSERT(hasStructureTransitionData()); 1120 return *reinterpret_cast<StructureTransitionData*>(m_opInfo); 1121 } 1122 1123 bool hasStructureSet() 1124 { 1125 switch (op()) { 1126 case CheckStructure: 1127 return true; 1128 default: 1129 return false; 1130 } 1131 } 1132 1133 StructureSet& structureSet() 1134 { 1135 ASSERT(hasStructureSet()); 1136 return *reinterpret_cast<StructureSet*>(m_opInfo); 1137 } 1138 1139 bool hasStructure() 1140 { 1141 switch (op()) { 1142 case StructureTransitionWatchpoint: 1143 case ArrayifyToStructure: 1144 case NewObject: 1145 case NewStringObject: 1146 return true; 1147 default: 1148 return false; 1149 } 1150 } 1151 1152 Structure* structure() 1153 { 1154 ASSERT(hasStructure()); 1155 return reinterpret_cast<Structure*>(m_opInfo); 1156 } 1157 1158 bool hasStorageAccessData() 1159 { 1160 return op() == GetByOffset || op() == PutByOffset; 1161 } 1162 1163 unsigned storageAccessDataIndex() 1164 { 1165 ASSERT(hasStorageAccessData()); 1166 return m_opInfo; 1167 } 1168 1169 bool hasMultiGetByOffsetData() 1170 { 1171 return op() == MultiGetByOffset; 1172 } 1173 1174 MultiGetByOffsetData& multiGetByOffsetData() 1175 { 1176 return *reinterpret_cast<MultiGetByOffsetData*>(m_opInfo); 1177 } 1178 1179 bool hasMultiPutByOffsetData() 1180 { 1181 return op() == MultiPutByOffset; 1182 } 1183 1184 MultiPutByOffsetData& multiPutByOffsetData() 1185 { 1186 return *reinterpret_cast<MultiPutByOffsetData*>(m_opInfo); 1187 } 1188 1189 bool hasFunctionDeclIndex() 1190 { 1191 return op() == NewFunction 1192 || op() == NewFunctionNoCheck; 1193 } 1194 1195 unsigned functionDeclIndex() 1196 { 1197 ASSERT(hasFunctionDeclIndex()); 1198 return m_opInfo; 1199 } 1200 1201 bool hasFunctionExprIndex() 1202 { 1203 return op() == NewFunctionExpression; 1204 } 1205 1206 unsigned functionExprIndex() 1207 { 1208 ASSERT(hasFunctionExprIndex()); 1209 return m_opInfo; 1210 } 1211 1212 bool hasSymbolTable() 1213 { 1214 return op() == FunctionReentryWatchpoint; 1215 } 1216 1217 SymbolTable* symbolTable() 1218 { 1219 ASSERT(hasSymbolTable()); 1220 return reinterpret_cast<SymbolTable*>(m_opInfo); 1221 } 1222 1223 bool hasArrayMode() 1224 { 1225 switch (op()) { 1226 case GetIndexedPropertyStorage: 1227 case GetArrayLength: 1228 case PutByValDirect: 1229 case PutByVal: 1230 case PutByValAlias: 1231 case GetByVal: 1232 case StringCharAt: 1233 case StringCharCodeAt: 1234 case CheckArray: 1235 case Arrayify: 1236 case ArrayifyToStructure: 1237 case ArrayPush: 1238 case ArrayPop: 1239 return true; 1240 default: 1241 return false; 1242 } 1243 } 1244 1245 ArrayMode arrayMode() 1246 { 1247 ASSERT(hasArrayMode()); 1248 if (op() == ArrayifyToStructure) 1249 return ArrayMode::fromWord(m_opInfo2); 1250 return ArrayMode::fromWord(m_opInfo); 1251 } 1252 1253 bool setArrayMode(ArrayMode arrayMode) 1254 { 1255 ASSERT(hasArrayMode()); 1256 if (this->arrayMode() == arrayMode) 1257 return false; 1258 m_opInfo = arrayMode.asWord(); 1259 return true; 1260 } 1261 1262 bool hasArithMode() 1263 { 1264 switch (op()) { 1265 case ArithAdd: 1266 case ArithSub: 1267 case ArithNegate: 1268 case ArithMul: 1269 case ArithDiv: 1270 case ArithMod: 1271 case UInt32ToNumber: 1272 case DoubleAsInt32: 1273 return true; 1274 default: 1275 return false; 1276 } 1277 } 1278 1279 Arith::Mode arithMode() 1280 { 1281 ASSERT(hasArithMode()); 1282 return static_cast<Arith::Mode>(m_opInfo); 1283 } 1284 1285 void setArithMode(Arith::Mode mode) 1286 { 1287 m_opInfo = mode; 1288 } 1289 1290 bool hasVirtualRegister() 1291 { 1292 return m_virtualRegister.isValid(); 1293 } 1294 1295 VirtualRegister virtualRegister() 1296 { 1297 ASSERT(hasResult()); 1298 ASSERT(m_virtualRegister.isValid()); 1299 return m_virtualRegister; 1300 } 1301 1302 void setVirtualRegister(VirtualRegister virtualRegister) 1303 { 1304 ASSERT(hasResult()); 1305 ASSERT(!m_virtualRegister.isValid()); 1306 m_virtualRegister = virtualRegister; 1307 } 1308 1309 bool hasExecutionCounter() 1310 { 1311 return op() == CountExecution; 1312 } 1313 1314 Profiler::ExecutionCounter* executionCounter() 1315 { 1316 return bitwise_cast<Profiler::ExecutionCounter*>(m_opInfo); 1317 } 1318 1319 bool shouldGenerate() 1320 { 1321 return m_refCount; 1322 } 1323 1324 bool willHaveCodeGenOrOSR() 1325 { 1326 switch (op()) { 1327 case SetLocal: 1328 case MovHint: 1329 case ZombieHint: 1330 case PhantomArguments: 1331 return true; 1332 case Phantom: 1333 case HardPhantom: 1334 return child1().useKindUnchecked() != UntypedUse || child2().useKindUnchecked() != UntypedUse || child3().useKindUnchecked() != UntypedUse; 1335 default: 1336 return shouldGenerate(); 1337 } 1338 } 1339 1340 bool isSemanticallySkippable() 1341 { 1342 return op() == CountExecution; 1343 } 1344 1345 unsigned refCount() 1346 { 1347 return m_refCount; 1348 } 1349 1350 unsigned postfixRef() 1351 { 1352 return m_refCount++; 1353 } 1354 1355 unsigned adjustedRefCount() 1356 { 1357 return mustGenerate() ? m_refCount - 1 : m_refCount; 1358 } 1359 1360 void setRefCount(unsigned refCount) 1361 { 1362 m_refCount = refCount; 1363 } 1364 1365 Edge& child1() 1366 { 1367 ASSERT(!(m_flags & NodeHasVarArgs)); 1368 return children.child1(); 1369 } 1370 1371 // This is useful if you want to do a fast check on the first child 1372 // before also doing a check on the opcode. Use this with care and 1373 // avoid it if possible. 1374 Edge child1Unchecked() 1375 { 1376 return children.child1Unchecked(); 1377 } 1378 1379 Edge& child2() 1380 { 1381 ASSERT(!(m_flags & NodeHasVarArgs)); 1382 return children.child2(); 1383 } 1384 1385 Edge& child3() 1386 { 1387 ASSERT(!(m_flags & NodeHasVarArgs)); 1388 return children.child3(); 1389 } 1390 1391 unsigned firstChild() 1392 { 1393 ASSERT(m_flags & NodeHasVarArgs); 1394 return children.firstChild(); 1395 } 1396 1397 unsigned numChildren() 1398 { 1399 ASSERT(m_flags & NodeHasVarArgs); 1400 return children.numChildren(); 1401 } 1402 1403 UseKind binaryUseKind() 1404 { 1405 ASSERT(child1().useKind() == child2().useKind()); 1406 return child1().useKind(); 1407 } 1408 1409 bool isBinaryUseKind(UseKind left, UseKind right) 1410 { 1411 return child1().useKind() == left && child2().useKind() == right; 1412 } 1413 1414 bool isBinaryUseKind(UseKind useKind) 1415 { 1416 return isBinaryUseKind(useKind, useKind); 1417 } 1418 1419 Edge childFor(UseKind useKind) 1420 { 1421 if (child1().useKind() == useKind) 1422 return child1(); 1423 if (child2().useKind() == useKind) 1424 return child2(); 1425 if (child3().useKind() == useKind) 1426 return child3(); 1427 return Edge(); 1428 } 1429 1430 SpeculatedType prediction() 1431 { 1432 return m_prediction; 1433 } 1434 1435 bool predict(SpeculatedType prediction) 1436 { 1437 return mergeSpeculation(m_prediction, prediction); 1438 } 1439 1440 bool shouldSpeculateInt32() 1441 { 1442 return isInt32Speculation(prediction()); 1443 } 1444 1445 bool sawBooleans() 1446 { 1447 return !!(prediction() & SpecBoolean); 1448 } 1449 1450 bool shouldSpeculateInt32OrBoolean() 1451 { 1452 return isInt32OrBooleanSpeculation(prediction()); 1453 } 1454 1455 bool shouldSpeculateInt32ForArithmetic() 1456 { 1457 return isInt32SpeculationForArithmetic(prediction()); 1458 } 1459 1460 bool shouldSpeculateInt32OrBooleanForArithmetic() 1461 { 1462 return isInt32OrBooleanSpeculationForArithmetic(prediction()); 1463 } 1464 1465 bool shouldSpeculateInt32OrBooleanExpectingDefined() 1466 { 1467 return isInt32OrBooleanSpeculationExpectingDefined(prediction()); 1468 } 1469 1470 bool shouldSpeculateMachineInt() 1471 { 1472 return isMachineIntSpeculation(prediction()); 1473 } 1474 1475 bool shouldSpeculateDouble() 1476 { 1477 return isDoubleSpeculation(prediction()); 1478 } 1479 1480 bool shouldSpeculateNumber() 1481 { 1482 return isFullNumberSpeculation(prediction()); 1483 } 1484 1485 bool shouldSpeculateNumberOrBoolean() 1486 { 1487 return isFullNumberOrBooleanSpeculation(prediction()); 1488 } 1489 1490 bool shouldSpeculateNumberOrBooleanExpectingDefined() 1491 { 1492 return isFullNumberOrBooleanSpeculationExpectingDefined(prediction()); 1493 } 1494 1495 bool shouldSpeculateBoolean() 1496 { 1497 return isBooleanSpeculation(prediction()); 1498 } 1499 1500 bool shouldSpeculateOther() 1501 { 1502 return isOtherSpeculation(prediction()); 1503 } 1504 1505 bool shouldSpeculateMisc() 1506 { 1507 return isMiscSpeculation(prediction()); 1508 } 1509 1510 bool shouldSpeculateStringIdent() 1511 { 1512 return isStringIdentSpeculation(prediction()); 1513 } 1514 1515 bool shouldSpeculateNotStringVar() 1516 { 1517 return isNotStringVarSpeculation(prediction()); 1518 } 1519 1520 bool shouldSpeculateString() 1521 { 1522 return isStringSpeculation(prediction()); 1523 } 1524 1525 bool shouldSpeculateStringObject() 1526 { 1527 return isStringObjectSpeculation(prediction()); 1528 } 1529 1530 bool shouldSpeculateStringOrStringObject() 1531 { 1532 return isStringOrStringObjectSpeculation(prediction()); 1533 } 1534 1535 bool shouldSpeculateFinalObject() 1536 { 1537 return isFinalObjectSpeculation(prediction()); 1538 } 1539 1540 bool shouldSpeculateFinalObjectOrOther() 1541 { 1542 return isFinalObjectOrOtherSpeculation(prediction()); 1543 } 1544 1545 bool shouldSpeculateArray() 1546 { 1547 return isArraySpeculation(prediction()); 1548 } 1549 1550 bool shouldSpeculateArguments() 1551 { 1552 return isArgumentsSpeculation(prediction()); 1553 } 1554 1555 bool shouldSpeculateInt8Array() 1556 { 1557 return isInt8ArraySpeculation(prediction()); 1558 } 1559 1560 bool shouldSpeculateInt16Array() 1561 { 1562 return isInt16ArraySpeculation(prediction()); 1563 } 1564 1565 bool shouldSpeculateInt32Array() 1566 { 1567 return isInt32ArraySpeculation(prediction()); 1568 } 1569 1570 bool shouldSpeculateUint8Array() 1571 { 1572 return isUint8ArraySpeculation(prediction()); 1573 } 1574 1575 bool shouldSpeculateUint8ClampedArray() 1576 { 1577 return isUint8ClampedArraySpeculation(prediction()); 1578 } 1579 1580 bool shouldSpeculateUint16Array() 1581 { 1582 return isUint16ArraySpeculation(prediction()); 1583 } 1584 1585 bool shouldSpeculateUint32Array() 1586 { 1587 return isUint32ArraySpeculation(prediction()); 1588 } 1589 1590 bool shouldSpeculateFloat32Array() 1591 { 1592 return isFloat32ArraySpeculation(prediction()); 1593 } 1594 1595 bool shouldSpeculateFloat64Array() 1596 { 1597 return isFloat64ArraySpeculation(prediction()); 1598 } 1599 1600 bool shouldSpeculateArrayOrOther() 1601 { 1602 return isArrayOrOtherSpeculation(prediction()); 1603 } 1604 1605 bool shouldSpeculateObject() 1606 { 1607 return isObjectSpeculation(prediction()); 1608 } 1609 1610 bool shouldSpeculateObjectOrOther() 1611 { 1612 return isObjectOrOtherSpeculation(prediction()); 1613 } 1614 1615 bool shouldSpeculateCell() 1616 { 1617 return isCellSpeculation(prediction()); 1618 } 1619 1620 static bool shouldSpeculateBoolean(Node* op1, Node* op2) 1621 { 1622 return op1->shouldSpeculateBoolean() && op2->shouldSpeculateBoolean(); 1623 } 1624 1625 static bool shouldSpeculateInt32(Node* op1, Node* op2) 1626 { 1627 return op1->shouldSpeculateInt32() && op2->shouldSpeculateInt32(); 1628 } 1629 1630 static bool shouldSpeculateInt32OrBoolean(Node* op1, Node* op2) 1631 { 1632 return op1->shouldSpeculateInt32OrBoolean() 1633 && op2->shouldSpeculateInt32OrBoolean(); 1634 } 1635 1636 static bool shouldSpeculateInt32OrBooleanForArithmetic(Node* op1, Node* op2) 1637 { 1638 return op1->shouldSpeculateInt32OrBooleanForArithmetic() 1639 && op2->shouldSpeculateInt32OrBooleanForArithmetic(); 1640 } 1641 1642 static bool shouldSpeculateInt32OrBooleanExpectingDefined(Node* op1, Node* op2) 1643 { 1644 return op1->shouldSpeculateInt32OrBooleanExpectingDefined() 1645 && op2->shouldSpeculateInt32OrBooleanExpectingDefined(); 1646 } 1647 1648 static bool shouldSpeculateMachineInt(Node* op1, Node* op2) 1649 { 1650 return op1->shouldSpeculateMachineInt() && op2->shouldSpeculateMachineInt(); 1651 } 1652 1653 static bool shouldSpeculateNumber(Node* op1, Node* op2) 1654 { 1655 return op1->shouldSpeculateNumber() && op2->shouldSpeculateNumber(); 1656 } 1657 1658 static bool shouldSpeculateNumberOrBoolean(Node* op1, Node* op2) 1659 { 1660 return op1->shouldSpeculateNumberOrBoolean() 1661 && op2->shouldSpeculateNumberOrBoolean(); 1662 } 1663 1664 static bool shouldSpeculateNumberOrBooleanExpectingDefined(Node* op1, Node* op2) 1665 { 1666 return op1->shouldSpeculateNumberOrBooleanExpectingDefined() 1667 && op2->shouldSpeculateNumberOrBooleanExpectingDefined(); 1668 } 1669 1670 static bool shouldSpeculateFinalObject(Node* op1, Node* op2) 1671 { 1672 return op1->shouldSpeculateFinalObject() && op2->shouldSpeculateFinalObject(); 1673 } 1674 1675 static bool shouldSpeculateArray(Node* op1, Node* op2) 1676 { 1677 return op1->shouldSpeculateArray() && op2->shouldSpeculateArray(); 1678 } 1679 1680 bool canSpeculateInt32(RareCaseProfilingSource source) 1681 { 1682 return nodeCanSpeculateInt32(arithNodeFlags(), source); 1683 } 1684 1685 bool canSpeculateInt52(RareCaseProfilingSource source) 1686 { 1687 return nodeCanSpeculateInt52(arithNodeFlags(), source); 1688 } 1689 1690 RareCaseProfilingSource sourceFor(PredictionPass pass) 1691 { 1692 if (pass == PrimaryPass || child1()->sawBooleans() || (child2() && child2()->sawBooleans())) 1693 return DFGRareCase; 1694 return AllRareCases; 1695 } 1696 1697 bool canSpeculateInt32(PredictionPass pass) 1698 { 1699 return canSpeculateInt32(sourceFor(pass)); 1700 } 1701 1702 bool canSpeculateInt52(PredictionPass pass) 1703 { 1704 return canSpeculateInt52(sourceFor(pass)); 1705 } 1706 1707 void dumpChildren(PrintStream& out) 1708 { 1709 if (!child1()) 1710 return; 1711 out.printf("@%u", child1()->index()); 1712 if (!child2()) 1713 return; 1714 out.printf(", @%u", child2()->index()); 1715 if (!child3()) 1716 return; 1717 out.printf(", @%u", child3()->index()); 1718 } 1719 1720 // NB. This class must have a trivial destructor. 1721 1722 NodeOrigin origin; 1723 1724 // References to up to 3 children, or links to a variable length set of children. 1725 AdjacencyList children; 1726 1727private: 1728 unsigned m_op : 10; // real type is NodeType 1729 unsigned m_flags : 22; 1730 // The virtual register number (spill location) associated with this . 1731 VirtualRegister m_virtualRegister; 1732 // The number of uses of the result of this operation (+1 for 'must generate' nodes, which have side-effects). 1733 unsigned m_refCount; 1734 // The prediction ascribed to this node after propagation. 1735 SpeculatedType m_prediction; 1736 // Immediate values, accesses type-checked via accessors above. The first one is 1737 // big enough to store a pointer. 1738 uintptr_t m_opInfo; 1739 uintptr_t m_opInfo2; 1740 1741public: 1742 // Fields used by various analyses. 1743 AbstractValue value; 1744 1745 // Miscellaneous data that is usually meaningless, but can hold some analysis results 1746 // if you ask right. For example, if you do Graph::initializeNodeOwners(), misc.owner 1747 // will tell you which basic block a node belongs to. You cannot rely on this persisting 1748 // across transformations unless you do the maintenance work yourself. Other phases use 1749 // misc.replacement, but they do so manually: first you do Graph::clearReplacements() 1750 // and then you set, and use, replacement's yourself. 1751 // 1752 // Bottom line: don't use these fields unless you initialize them yourself, or by 1753 // calling some appropriate methods that initialize them the way you want. Otherwise, 1754 // these fields are meaningless. 1755 union { 1756 Node* replacement; 1757 BasicBlock* owner; 1758 } misc; 1759}; 1760 1761inline bool nodeComparator(Node* a, Node* b) 1762{ 1763 return a->index() < b->index(); 1764} 1765 1766template<typename T> 1767CString nodeListDump(const T& nodeList) 1768{ 1769 return sortedListDump(nodeList, nodeComparator); 1770} 1771 1772template<typename T> 1773CString nodeMapDump(const T& nodeMap, DumpContext* context = 0) 1774{ 1775 Vector<typename T::KeyType> keys; 1776 for ( 1777 typename T::const_iterator iter = nodeMap.begin(); 1778 iter != nodeMap.end(); ++iter) 1779 keys.append(iter->key); 1780 std::sort(keys.begin(), keys.end(), nodeComparator); 1781 StringPrintStream out; 1782 CommaPrinter comma; 1783 for(unsigned i = 0; i < keys.size(); ++i) 1784 out.print(comma, keys[i], "=>", inContext(nodeMap.get(keys[i]), context)); 1785 return out.toCString(); 1786} 1787 1788} } // namespace JSC::DFG 1789 1790namespace WTF { 1791 1792void printInternal(PrintStream&, JSC::DFG::SwitchKind); 1793void printInternal(PrintStream&, JSC::DFG::Node*); 1794 1795inline JSC::DFG::Node* inContext(JSC::DFG::Node* node, JSC::DumpContext*) { return node; } 1796 1797} // namespace WTF 1798 1799using WTF::inContext; 1800 1801#endif 1802#endif 1803