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