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