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