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