DFG should only have two mechanisms for describing effectfulness of nodes; previously...
[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;
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;
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 &= ~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         ASSERT(m_flags & NodeMustGenerate);
491     }
492     
493     void convertToPutByOffset(StorageAccessData& data, Edge storage)
494     {
495         ASSERT(m_op == PutById || m_op == PutByIdDirect || m_op == PutByIdFlush || m_op == MultiPutByOffset);
496         m_opInfo = bitwise_cast<uintptr_t>(&data);
497         children.setChild3(children.child2());
498         children.setChild2(children.child1());
499         children.setChild1(storage);
500         m_op = PutByOffset;
501     }
502     
503     void convertToMultiPutByOffset(MultiPutByOffsetData* data)
504     {
505         ASSERT(m_op == PutById || m_op == PutByIdDirect || m_op == PutByIdFlush);
506         m_opInfo = bitwise_cast<intptr_t>(data);
507         m_op = MultiPutByOffset;
508     }
509     
510     void convertToPutByOffsetHint()
511     {
512         ASSERT(m_op == PutByOffset);
513         m_opInfo = storageAccessData().identifierNumber;
514         m_op = PutByOffsetHint;
515         child1() = child2();
516         child2() = child3();
517         child3() = Edge();
518     }
519     
520     void convertToPutStructureHint(Node* structure)
521     {
522         ASSERT(m_op == PutStructure);
523         ASSERT(structure->castConstant<Structure*>() == transition()->next);
524         m_op = PutStructureHint;
525         m_opInfo = 0;
526         child2() = Edge(structure, KnownCellUse);
527     }
528     
529     void convertToPhantomNewObject()
530     {
531         ASSERT(m_op == NewObject || m_op == MaterializeNewObject);
532         m_op = PhantomNewObject;
533         m_flags &= ~NodeHasVarArgs;
534         m_opInfo = 0;
535         m_opInfo2 = 0;
536         children = AdjacencyList();
537     }
538     
539     void convertPhantomToPhantomLocal()
540     {
541         ASSERT(m_op == Phantom && (child1()->op() == Phi || child1()->op() == SetLocal || child1()->op() == SetArgument));
542         m_op = PhantomLocal;
543         m_opInfo = child1()->m_opInfo; // Copy the variableAccessData.
544         children.setChild1(Edge());
545     }
546     
547     void convertFlushToPhantomLocal()
548     {
549         ASSERT(m_op == Flush);
550         m_op = PhantomLocal;
551         children = AdjacencyList();
552     }
553     
554     void convertToGetLocal(VariableAccessData* variable, Node* phi)
555     {
556         ASSERT(m_op == GetLocalUnlinked);
557         m_op = GetLocal;
558         m_opInfo = bitwise_cast<uintptr_t>(variable);
559         m_opInfo2 = 0;
560         children.setChild1(Edge(phi));
561     }
562     
563     void convertToToString()
564     {
565         ASSERT(m_op == ToPrimitive);
566         m_op = ToString;
567     }
568     
569     JSValue asJSValue()
570     {
571         return constant()->value();
572     }
573      
574     bool isInt32Constant()
575     {
576         return isConstant() && constant()->value().isInt32();
577     }
578      
579     int32_t asInt32()
580     {
581         return asJSValue().asInt32();
582     }
583      
584     uint32_t asUInt32()
585     {
586         return asInt32();
587     }
588      
589     bool isDoubleConstant()
590     {
591         return isConstant() && constant()->value().isDouble();
592     }
593      
594     bool isNumberConstant()
595     {
596         return isConstant() && constant()->value().isNumber();
597     }
598     
599     double asNumber()
600     {
601         return asJSValue().asNumber();
602     }
603      
604     bool isMachineIntConstant()
605     {
606         return isConstant() && constant()->value().isMachineInt();
607     }
608      
609     int64_t asMachineInt()
610     {
611         return asJSValue().asMachineInt();
612     }
613      
614     bool isBooleanConstant()
615     {
616         return isConstant() && constant()->value().isBoolean();
617     }
618      
619     bool asBoolean()
620     {
621         return constant()->value().asBoolean();
622     }
623      
624     bool isCellConstant()
625     {
626         return isConstant() && constant()->value() && constant()->value().isCell();
627     }
628      
629     JSCell* asCell()
630     {
631         return constant()->value().asCell();
632     }
633      
634     template<typename T>
635     T dynamicCastConstant()
636     {
637         if (!isCellConstant())
638             return nullptr;
639         return jsDynamicCast<T>(asCell());
640     }
641     
642     template<typename T>
643     T castConstant()
644     {
645         T result = dynamicCastConstant<T>();
646         RELEASE_ASSERT(result);
647         return result;
648     }
649      
650     bool containsMovHint()
651     {
652         switch (op()) {
653         case MovHint:
654         case ZombieHint:
655             return true;
656         default:
657             return false;
658         }
659     }
660     
661     bool hasVariableAccessData(Graph&);
662     bool hasLocal(Graph& graph)
663     {
664         return hasVariableAccessData(graph);
665     }
666     
667     // This is useful for debugging code, where a node that should have a variable
668     // access data doesn't have one because it hasn't been initialized yet.
669     VariableAccessData* tryGetVariableAccessData()
670     {
671         VariableAccessData* result = reinterpret_cast<VariableAccessData*>(m_opInfo);
672         if (!result)
673             return 0;
674         return result->find();
675     }
676     
677     VariableAccessData* variableAccessData()
678     {
679         return reinterpret_cast<VariableAccessData*>(m_opInfo)->find();
680     }
681     
682     VirtualRegister local()
683     {
684         return variableAccessData()->local();
685     }
686     
687     VirtualRegister machineLocal()
688     {
689         return variableAccessData()->machineLocal();
690     }
691     
692     bool hasUnlinkedLocal()
693     {
694         switch (op()) {
695         case GetLocalUnlinked:
696         case ExtractOSREntryLocal:
697         case MovHint:
698         case ZombieHint:
699         case KillLocal:
700             return true;
701         default:
702             return false;
703         }
704     }
705     
706     VirtualRegister unlinkedLocal()
707     {
708         ASSERT(hasUnlinkedLocal());
709         return static_cast<VirtualRegister>(m_opInfo);
710     }
711     
712     bool hasUnlinkedMachineLocal()
713     {
714         return op() == GetLocalUnlinked;
715     }
716     
717     void setUnlinkedMachineLocal(VirtualRegister reg)
718     {
719         ASSERT(hasUnlinkedMachineLocal());
720         m_opInfo2 = reg.offset();
721     }
722     
723     VirtualRegister unlinkedMachineLocal()
724     {
725         ASSERT(hasUnlinkedMachineLocal());
726         return VirtualRegister(m_opInfo2);
727     }
728     
729     bool hasPhi()
730     {
731         return op() == Upsilon;
732     }
733     
734     Node* phi()
735     {
736         ASSERT(hasPhi());
737         return bitwise_cast<Node*>(m_opInfo);
738     }
739
740     bool isStoreBarrier()
741     {
742         switch (op()) {
743         case StoreBarrier:
744         case StoreBarrierWithNullCheck:
745             return true;
746         default:
747             return false;
748         }
749     }
750
751     bool hasIdentifier()
752     {
753         switch (op()) {
754         case GetById:
755         case GetByIdFlush:
756         case PutById:
757         case PutByIdFlush:
758         case PutByIdDirect:
759         case PutByOffsetHint:
760             return true;
761         default:
762             return false;
763         }
764     }
765
766     unsigned identifierNumber()
767     {
768         ASSERT(hasIdentifier());
769         return m_opInfo;
770     }
771     
772     // This corrects the arithmetic node flags, so that irrelevant bits are
773     // ignored. In particular, anything other than ArithMul does not need
774     // to know if it can speculate on negative zero.
775     NodeFlags arithNodeFlags()
776     {
777         NodeFlags result = m_flags & NodeArithFlagsMask;
778         if (op() == ArithMul || op() == ArithDiv || op() == ArithMod || op() == ArithNegate || op() == DoubleAsInt32)
779             return result;
780         return result & ~NodeBytecodeNeedsNegZero;
781     }
782     
783     bool hasConstantBuffer()
784     {
785         return op() == NewArrayBuffer;
786     }
787     
788     NewArrayBufferData* newArrayBufferData()
789     {
790         ASSERT(hasConstantBuffer());
791         return reinterpret_cast<NewArrayBufferData*>(m_opInfo);
792     }
793     
794     unsigned startConstant()
795     {
796         return newArrayBufferData()->startConstant;
797     }
798     
799     unsigned numConstants()
800     {
801         return newArrayBufferData()->numConstants;
802     }
803     
804     bool hasIndexingType()
805     {
806         switch (op()) {
807         case NewArray:
808         case NewArrayWithSize:
809         case NewArrayBuffer:
810             return true;
811         default:
812             return false;
813         }
814     }
815     
816     IndexingType indexingType()
817     {
818         ASSERT(hasIndexingType());
819         if (op() == NewArrayBuffer)
820             return newArrayBufferData()->indexingType;
821         return m_opInfo;
822     }
823     
824     bool hasTypedArrayType()
825     {
826         switch (op()) {
827         case NewTypedArray:
828             return true;
829         default:
830             return false;
831         }
832     }
833     
834     TypedArrayType typedArrayType()
835     {
836         ASSERT(hasTypedArrayType());
837         TypedArrayType result = static_cast<TypedArrayType>(m_opInfo);
838         ASSERT(isTypedView(result));
839         return result;
840     }
841     
842     bool hasInlineCapacity()
843     {
844         return op() == CreateThis;
845     }
846
847     unsigned inlineCapacity()
848     {
849         ASSERT(hasInlineCapacity());
850         return m_opInfo;
851     }
852
853     void setIndexingType(IndexingType indexingType)
854     {
855         ASSERT(hasIndexingType());
856         m_opInfo = indexingType;
857     }
858     
859     bool hasRegexpIndex()
860     {
861         return op() == NewRegexp;
862     }
863     
864     unsigned regexpIndex()
865     {
866         ASSERT(hasRegexpIndex());
867         return m_opInfo;
868     }
869     
870     bool hasVarNumber()
871     {
872         return op() == GetClosureVar || op() == PutClosureVar;
873     }
874
875     int varNumber()
876     {
877         ASSERT(hasVarNumber());
878         return m_opInfo;
879     }
880     
881     bool hasRegisterPointer()
882     {
883         return op() == GetGlobalVar || op() == PutGlobalVar;
884     }
885     
886     WriteBarrier<Unknown>* registerPointer()
887     {
888         return bitwise_cast<WriteBarrier<Unknown>*>(m_opInfo);
889     }
890     
891     bool hasResult()
892     {
893         return !!result();
894     }
895
896     bool hasInt32Result()
897     {
898         return result() == NodeResultInt32;
899     }
900     
901     bool hasInt52Result()
902     {
903         return result() == NodeResultInt52;
904     }
905     
906     bool hasNumberResult()
907     {
908         return result() == NodeResultNumber;
909     }
910     
911     bool hasDoubleResult()
912     {
913         return result() == NodeResultDouble;
914     }
915     
916     bool hasJSResult()
917     {
918         return result() == NodeResultJS;
919     }
920     
921     bool hasBooleanResult()
922     {
923         return result() == NodeResultBoolean;
924     }
925
926     bool hasStorageResult()
927     {
928         return result() == NodeResultStorage;
929     }
930     
931     UseKind defaultUseKind()
932     {
933         return useKindForResult(result());
934     }
935     
936     Edge defaultEdge()
937     {
938         return Edge(this, defaultUseKind());
939     }
940
941     bool isJump()
942     {
943         return op() == Jump;
944     }
945
946     bool isBranch()
947     {
948         return op() == Branch;
949     }
950     
951     bool isSwitch()
952     {
953         return op() == Switch;
954     }
955
956     bool isTerminal()
957     {
958         switch (op()) {
959         case Jump:
960         case Branch:
961         case Switch:
962         case Return:
963         case Unreachable:
964             return true;
965         default:
966             return false;
967         }
968     }
969
970     unsigned targetBytecodeOffsetDuringParsing()
971     {
972         ASSERT(isJump());
973         return m_opInfo;
974     }
975
976     BasicBlock*& targetBlock()
977     {
978         ASSERT(isJump());
979         return *bitwise_cast<BasicBlock**>(&m_opInfo);
980     }
981     
982     BranchData* branchData()
983     {
984         ASSERT(isBranch());
985         return bitwise_cast<BranchData*>(m_opInfo);
986     }
987     
988     SwitchData* switchData()
989     {
990         ASSERT(isSwitch());
991         return bitwise_cast<SwitchData*>(m_opInfo);
992     }
993     
994     unsigned numSuccessors()
995     {
996         switch (op()) {
997         case Jump:
998             return 1;
999         case Branch:
1000             return 2;
1001         case Switch:
1002             return switchData()->cases.size() + 1;
1003         default:
1004             return 0;
1005         }
1006     }
1007     
1008     BasicBlock*& successor(unsigned index)
1009     {
1010         if (isSwitch()) {
1011             if (index < switchData()->cases.size())
1012                 return switchData()->cases[index].target.block;
1013             RELEASE_ASSERT(index == switchData()->cases.size());
1014             return switchData()->fallThrough.block;
1015         }
1016         switch (index) {
1017         case 0:
1018             if (isJump())
1019                 return targetBlock();
1020             return branchData()->taken.block;
1021         case 1:
1022             return branchData()->notTaken.block;
1023         default:
1024             RELEASE_ASSERT_NOT_REACHED();
1025             return targetBlock();
1026         }
1027     }
1028     
1029     BasicBlock*& successorForCondition(bool condition)
1030     {
1031         return branchData()->forCondition(condition);
1032     }
1033     
1034     bool hasHeapPrediction()
1035     {
1036         switch (op()) {
1037         case GetDirectPname:
1038         case GetById:
1039         case GetByIdFlush:
1040         case GetByVal:
1041         case GetMyArgumentByVal:
1042         case GetMyArgumentByValSafe:
1043         case Call:
1044         case Construct:
1045         case NativeCall:
1046         case NativeConstruct:
1047         case GetByOffset:
1048         case MultiGetByOffset:
1049         case GetClosureVar:
1050         case ArrayPop:
1051         case ArrayPush:
1052         case RegExpExec:
1053         case RegExpTest:
1054         case GetGlobalVar:
1055             return true;
1056         default:
1057             return false;
1058         }
1059     }
1060     
1061     SpeculatedType getHeapPrediction()
1062     {
1063         ASSERT(hasHeapPrediction());
1064         return static_cast<SpeculatedType>(m_opInfo2);
1065     }
1066     
1067     bool predictHeap(SpeculatedType prediction)
1068     {
1069         ASSERT(hasHeapPrediction());
1070         
1071         return mergeSpeculation(m_opInfo2, prediction);
1072     }
1073     
1074     void setHeapPrediction(SpeculatedType prediction)
1075     {
1076         ASSERT(hasHeapPrediction());
1077         m_opInfo2 = prediction;
1078     }
1079     
1080     bool hasCellOperand()
1081     {
1082         switch (op()) {
1083         case AllocationProfileWatchpoint:
1084         case CheckCell:
1085         case NativeConstruct:
1086         case NativeCall:
1087             return true;
1088         default:
1089             return false;
1090         }
1091     }
1092
1093     FrozenValue* cellOperand()
1094     {
1095         ASSERT(hasCellOperand());
1096         return reinterpret_cast<FrozenValue*>(m_opInfo);
1097     }
1098     
1099     void setCellOperand(FrozenValue* value)
1100     {
1101         ASSERT(hasCellOperand());
1102         m_opInfo = bitwise_cast<uintptr_t>(value);
1103     }
1104     
1105     bool hasVariableWatchpointSet()
1106     {
1107         return op() == NotifyWrite || op() == VariableWatchpoint;
1108     }
1109     
1110     VariableWatchpointSet* variableWatchpointSet()
1111     {
1112         return reinterpret_cast<VariableWatchpointSet*>(m_opInfo);
1113     }
1114     
1115     bool hasTypedArray()
1116     {
1117         return op() == TypedArrayWatchpoint;
1118     }
1119     
1120     JSArrayBufferView* typedArray()
1121     {
1122         return reinterpret_cast<JSArrayBufferView*>(m_opInfo);
1123     }
1124     
1125     bool hasStoragePointer()
1126     {
1127         return op() == ConstantStoragePointer;
1128     }
1129     
1130     void* storagePointer()
1131     {
1132         return reinterpret_cast<void*>(m_opInfo);
1133     }
1134
1135     bool hasTransition()
1136     {
1137         switch (op()) {
1138         case PutStructure:
1139         case AllocatePropertyStorage:
1140         case ReallocatePropertyStorage:
1141             return true;
1142         default:
1143             return false;
1144         }
1145     }
1146     
1147     Transition* transition()
1148     {
1149         ASSERT(hasTransition());
1150         return reinterpret_cast<Transition*>(m_opInfo);
1151     }
1152     
1153     bool hasStructureSet()
1154     {
1155         switch (op()) {
1156         case CheckStructure:
1157             return true;
1158         default:
1159             return false;
1160         }
1161     }
1162     
1163     StructureSet& structureSet()
1164     {
1165         ASSERT(hasStructureSet());
1166         return *reinterpret_cast<StructureSet*>(m_opInfo);
1167     }
1168     
1169     bool hasStructure()
1170     {
1171         switch (op()) {
1172         case ArrayifyToStructure:
1173         case NewObject:
1174         case NewStringObject:
1175             return true;
1176         default:
1177             return false;
1178         }
1179     }
1180     
1181     Structure* structure()
1182     {
1183         ASSERT(hasStructure());
1184         return reinterpret_cast<Structure*>(m_opInfo);
1185     }
1186     
1187     bool hasStorageAccessData()
1188     {
1189         switch (op()) {
1190         case GetByOffset:
1191         case PutByOffset:
1192         case GetGetterSetterByOffset:
1193             return true;
1194         default:
1195             return false;
1196         }
1197     }
1198     
1199     StorageAccessData& storageAccessData()
1200     {
1201         ASSERT(hasStorageAccessData());
1202         return *bitwise_cast<StorageAccessData*>(m_opInfo);
1203     }
1204     
1205     bool hasMultiGetByOffsetData()
1206     {
1207         return op() == MultiGetByOffset;
1208     }
1209     
1210     MultiGetByOffsetData& multiGetByOffsetData()
1211     {
1212         return *reinterpret_cast<MultiGetByOffsetData*>(m_opInfo);
1213     }
1214     
1215     bool hasMultiPutByOffsetData()
1216     {
1217         return op() == MultiPutByOffset;
1218     }
1219     
1220     MultiPutByOffsetData& multiPutByOffsetData()
1221     {
1222         return *reinterpret_cast<MultiPutByOffsetData*>(m_opInfo);
1223     }
1224     
1225     bool hasObjectMaterializationData()
1226     {
1227         return op() == MaterializeNewObject;
1228     }
1229     
1230     ObjectMaterializationData& objectMaterializationData()
1231     {
1232         return *reinterpret_cast<ObjectMaterializationData*>(m_opInfo);
1233     }
1234     
1235     bool isPhantomObjectAllocation()
1236     {
1237         switch (op()) {
1238         case PhantomNewObject:
1239             return true;
1240         default:
1241             return false;
1242         }
1243     }
1244     
1245     bool hasFunctionDeclIndex()
1246     {
1247         return op() == NewFunction
1248             || op() == NewFunctionNoCheck;
1249     }
1250     
1251     unsigned functionDeclIndex()
1252     {
1253         ASSERT(hasFunctionDeclIndex());
1254         return m_opInfo;
1255     }
1256     
1257     bool hasFunctionExprIndex()
1258     {
1259         return op() == NewFunctionExpression;
1260     }
1261     
1262     unsigned functionExprIndex()
1263     {
1264         ASSERT(hasFunctionExprIndex());
1265         return m_opInfo;
1266     }
1267     
1268     bool hasSymbolTable()
1269     {
1270         return op() == FunctionReentryWatchpoint;
1271     }
1272     
1273     SymbolTable* symbolTable()
1274     {
1275         ASSERT(hasSymbolTable());
1276         return reinterpret_cast<SymbolTable*>(m_opInfo);
1277     }
1278     
1279     bool hasArrayMode()
1280     {
1281         switch (op()) {
1282         case GetIndexedPropertyStorage:
1283         case GetArrayLength:
1284         case PutByValDirect:
1285         case PutByVal:
1286         case PutByValAlias:
1287         case GetByVal:
1288         case StringCharAt:
1289         case StringCharCodeAt:
1290         case CheckArray:
1291         case Arrayify:
1292         case ArrayifyToStructure:
1293         case ArrayPush:
1294         case ArrayPop:
1295         case HasIndexedProperty:
1296             return true;
1297         default:
1298             return false;
1299         }
1300     }
1301     
1302     ArrayMode arrayMode()
1303     {
1304         ASSERT(hasArrayMode());
1305         if (op() == ArrayifyToStructure)
1306             return ArrayMode::fromWord(m_opInfo2);
1307         return ArrayMode::fromWord(m_opInfo);
1308     }
1309     
1310     bool setArrayMode(ArrayMode arrayMode)
1311     {
1312         ASSERT(hasArrayMode());
1313         if (this->arrayMode() == arrayMode)
1314             return false;
1315         m_opInfo = arrayMode.asWord();
1316         return true;
1317     }
1318     
1319     bool hasArithMode()
1320     {
1321         switch (op()) {
1322         case ArithAdd:
1323         case ArithSub:
1324         case ArithNegate:
1325         case ArithMul:
1326         case ArithDiv:
1327         case ArithMod:
1328         case UInt32ToNumber:
1329         case DoubleAsInt32:
1330             return true;
1331         default:
1332             return false;
1333         }
1334     }
1335
1336     Arith::Mode arithMode()
1337     {
1338         ASSERT(hasArithMode());
1339         return static_cast<Arith::Mode>(m_opInfo);
1340     }
1341     
1342     void setArithMode(Arith::Mode mode)
1343     {
1344         m_opInfo = mode;
1345     }
1346     
1347     bool hasVirtualRegister()
1348     {
1349         return m_virtualRegister.isValid();
1350     }
1351     
1352     VirtualRegister virtualRegister()
1353     {
1354         ASSERT(hasResult());
1355         ASSERT(m_virtualRegister.isValid());
1356         return m_virtualRegister;
1357     }
1358     
1359     void setVirtualRegister(VirtualRegister virtualRegister)
1360     {
1361         ASSERT(hasResult());
1362         ASSERT(!m_virtualRegister.isValid());
1363         m_virtualRegister = virtualRegister;
1364     }
1365     
1366     bool hasExecutionCounter()
1367     {
1368         return op() == CountExecution;
1369     }
1370     
1371     Profiler::ExecutionCounter* executionCounter()
1372     {
1373         return bitwise_cast<Profiler::ExecutionCounter*>(m_opInfo);
1374     }
1375
1376     bool shouldGenerate()
1377     {
1378         return m_refCount;
1379     }
1380     
1381     bool willHaveCodeGenOrOSR()
1382     {
1383         switch (op()) {
1384         case SetLocal:
1385         case PutLocal:
1386         case KillLocal:
1387         case MovHint:
1388         case ZombieHint:
1389         case PhantomArguments:
1390             return true;
1391         case Phantom:
1392         case HardPhantom:
1393             return child1().useKindUnchecked() != UntypedUse || child2().useKindUnchecked() != UntypedUse || child3().useKindUnchecked() != UntypedUse;
1394         default:
1395             return shouldGenerate();
1396         }
1397     }
1398     
1399     bool isSemanticallySkippable()
1400     {
1401         return op() == CountExecution;
1402     }
1403
1404     unsigned refCount()
1405     {
1406         return m_refCount;
1407     }
1408
1409     unsigned postfixRef()
1410     {
1411         return m_refCount++;
1412     }
1413
1414     unsigned adjustedRefCount()
1415     {
1416         return mustGenerate() ? m_refCount - 1 : m_refCount;
1417     }
1418     
1419     void setRefCount(unsigned refCount)
1420     {
1421         m_refCount = refCount;
1422     }
1423     
1424     Edge& child1()
1425     {
1426         ASSERT(!(m_flags & NodeHasVarArgs));
1427         return children.child1();
1428     }
1429     
1430     // This is useful if you want to do a fast check on the first child
1431     // before also doing a check on the opcode. Use this with care and
1432     // avoid it if possible.
1433     Edge child1Unchecked()
1434     {
1435         return children.child1Unchecked();
1436     }
1437
1438     Edge& child2()
1439     {
1440         ASSERT(!(m_flags & NodeHasVarArgs));
1441         return children.child2();
1442     }
1443
1444     Edge& child3()
1445     {
1446         ASSERT(!(m_flags & NodeHasVarArgs));
1447         return children.child3();
1448     }
1449     
1450     unsigned firstChild()
1451     {
1452         ASSERT(m_flags & NodeHasVarArgs);
1453         return children.firstChild();
1454     }
1455     
1456     unsigned numChildren()
1457     {
1458         ASSERT(m_flags & NodeHasVarArgs);
1459         return children.numChildren();
1460     }
1461     
1462     UseKind binaryUseKind()
1463     {
1464         ASSERT(child1().useKind() == child2().useKind());
1465         return child1().useKind();
1466     }
1467     
1468     bool isBinaryUseKind(UseKind left, UseKind right)
1469     {
1470         return child1().useKind() == left && child2().useKind() == right;
1471     }
1472     
1473     bool isBinaryUseKind(UseKind useKind)
1474     {
1475         return isBinaryUseKind(useKind, useKind);
1476     }
1477     
1478     Edge childFor(UseKind useKind)
1479     {
1480         if (child1().useKind() == useKind)
1481             return child1();
1482         if (child2().useKind() == useKind)
1483             return child2();
1484         if (child3().useKind() == useKind)
1485             return child3();
1486         return Edge();
1487     }
1488     
1489     SpeculatedType prediction()
1490     {
1491         return m_prediction;
1492     }
1493     
1494     bool predict(SpeculatedType prediction)
1495     {
1496         return mergeSpeculation(m_prediction, prediction);
1497     }
1498     
1499     bool shouldSpeculateInt32()
1500     {
1501         return isInt32Speculation(prediction());
1502     }
1503     
1504     bool sawBooleans()
1505     {
1506         return !!(prediction() & SpecBoolean);
1507     }
1508     
1509     bool shouldSpeculateInt32OrBoolean()
1510     {
1511         return isInt32OrBooleanSpeculation(prediction());
1512     }
1513     
1514     bool shouldSpeculateInt32ForArithmetic()
1515     {
1516         return isInt32SpeculationForArithmetic(prediction());
1517     }
1518     
1519     bool shouldSpeculateInt32OrBooleanForArithmetic()
1520     {
1521         return isInt32OrBooleanSpeculationForArithmetic(prediction());
1522     }
1523     
1524     bool shouldSpeculateInt32OrBooleanExpectingDefined()
1525     {
1526         return isInt32OrBooleanSpeculationExpectingDefined(prediction());
1527     }
1528     
1529     bool shouldSpeculateMachineInt()
1530     {
1531         return isMachineIntSpeculation(prediction());
1532     }
1533     
1534     bool shouldSpeculateDouble()
1535     {
1536         return isDoubleSpeculation(prediction());
1537     }
1538     
1539     bool shouldSpeculateNumber()
1540     {
1541         return isFullNumberSpeculation(prediction());
1542     }
1543     
1544     bool shouldSpeculateNumberOrBoolean()
1545     {
1546         return isFullNumberOrBooleanSpeculation(prediction());
1547     }
1548     
1549     bool shouldSpeculateNumberOrBooleanExpectingDefined()
1550     {
1551         return isFullNumberOrBooleanSpeculationExpectingDefined(prediction());
1552     }
1553     
1554     bool shouldSpeculateBoolean()
1555     {
1556         return isBooleanSpeculation(prediction());
1557     }
1558     
1559     bool shouldSpeculateOther()
1560     {
1561         return isOtherSpeculation(prediction());
1562     }
1563     
1564     bool shouldSpeculateMisc()
1565     {
1566         return isMiscSpeculation(prediction());
1567     }
1568    
1569     bool shouldSpeculateStringIdent()
1570     {
1571         return isStringIdentSpeculation(prediction());
1572     }
1573     
1574     bool shouldSpeculateNotStringVar()
1575     {
1576         return isNotStringVarSpeculation(prediction());
1577     }
1578  
1579     bool shouldSpeculateString()
1580     {
1581         return isStringSpeculation(prediction());
1582     }
1583  
1584     bool shouldSpeculateStringObject()
1585     {
1586         return isStringObjectSpeculation(prediction());
1587     }
1588     
1589     bool shouldSpeculateStringOrStringObject()
1590     {
1591         return isStringOrStringObjectSpeculation(prediction());
1592     }
1593     
1594     bool shouldSpeculateFinalObject()
1595     {
1596         return isFinalObjectSpeculation(prediction());
1597     }
1598     
1599     bool shouldSpeculateFinalObjectOrOther()
1600     {
1601         return isFinalObjectOrOtherSpeculation(prediction());
1602     }
1603     
1604     bool shouldSpeculateArray()
1605     {
1606         return isArraySpeculation(prediction());
1607     }
1608     
1609     bool shouldSpeculateArguments()
1610     {
1611         return isArgumentsSpeculation(prediction());
1612     }
1613     
1614     bool shouldSpeculateInt8Array()
1615     {
1616         return isInt8ArraySpeculation(prediction());
1617     }
1618     
1619     bool shouldSpeculateInt16Array()
1620     {
1621         return isInt16ArraySpeculation(prediction());
1622     }
1623     
1624     bool shouldSpeculateInt32Array()
1625     {
1626         return isInt32ArraySpeculation(prediction());
1627     }
1628     
1629     bool shouldSpeculateUint8Array()
1630     {
1631         return isUint8ArraySpeculation(prediction());
1632     }
1633
1634     bool shouldSpeculateUint8ClampedArray()
1635     {
1636         return isUint8ClampedArraySpeculation(prediction());
1637     }
1638     
1639     bool shouldSpeculateUint16Array()
1640     {
1641         return isUint16ArraySpeculation(prediction());
1642     }
1643     
1644     bool shouldSpeculateUint32Array()
1645     {
1646         return isUint32ArraySpeculation(prediction());
1647     }
1648     
1649     bool shouldSpeculateFloat32Array()
1650     {
1651         return isFloat32ArraySpeculation(prediction());
1652     }
1653     
1654     bool shouldSpeculateFloat64Array()
1655     {
1656         return isFloat64ArraySpeculation(prediction());
1657     }
1658     
1659     bool shouldSpeculateArrayOrOther()
1660     {
1661         return isArrayOrOtherSpeculation(prediction());
1662     }
1663     
1664     bool shouldSpeculateObject()
1665     {
1666         return isObjectSpeculation(prediction());
1667     }
1668     
1669     bool shouldSpeculateObjectOrOther()
1670     {
1671         return isObjectOrOtherSpeculation(prediction());
1672     }
1673
1674     bool shouldSpeculateCell()
1675     {
1676         return isCellSpeculation(prediction());
1677     }
1678     
1679     bool shouldSpeculateNotCell()
1680     {
1681         return isNotCellSpeculation(prediction());
1682     }
1683     
1684     static bool shouldSpeculateBoolean(Node* op1, Node* op2)
1685     {
1686         return op1->shouldSpeculateBoolean() && op2->shouldSpeculateBoolean();
1687     }
1688     
1689     static bool shouldSpeculateInt32(Node* op1, Node* op2)
1690     {
1691         return op1->shouldSpeculateInt32() && op2->shouldSpeculateInt32();
1692     }
1693     
1694     static bool shouldSpeculateInt32OrBoolean(Node* op1, Node* op2)
1695     {
1696         return op1->shouldSpeculateInt32OrBoolean()
1697             && op2->shouldSpeculateInt32OrBoolean();
1698     }
1699     
1700     static bool shouldSpeculateInt32OrBooleanForArithmetic(Node* op1, Node* op2)
1701     {
1702         return op1->shouldSpeculateInt32OrBooleanForArithmetic()
1703             && op2->shouldSpeculateInt32OrBooleanForArithmetic();
1704     }
1705     
1706     static bool shouldSpeculateInt32OrBooleanExpectingDefined(Node* op1, Node* op2)
1707     {
1708         return op1->shouldSpeculateInt32OrBooleanExpectingDefined()
1709             && op2->shouldSpeculateInt32OrBooleanExpectingDefined();
1710     }
1711     
1712     static bool shouldSpeculateMachineInt(Node* op1, Node* op2)
1713     {
1714         return op1->shouldSpeculateMachineInt() && op2->shouldSpeculateMachineInt();
1715     }
1716     
1717     static bool shouldSpeculateNumber(Node* op1, Node* op2)
1718     {
1719         return op1->shouldSpeculateNumber() && op2->shouldSpeculateNumber();
1720     }
1721     
1722     static bool shouldSpeculateNumberOrBoolean(Node* op1, Node* op2)
1723     {
1724         return op1->shouldSpeculateNumberOrBoolean()
1725             && op2->shouldSpeculateNumberOrBoolean();
1726     }
1727     
1728     static bool shouldSpeculateNumberOrBooleanExpectingDefined(Node* op1, Node* op2)
1729     {
1730         return op1->shouldSpeculateNumberOrBooleanExpectingDefined()
1731             && op2->shouldSpeculateNumberOrBooleanExpectingDefined();
1732     }
1733     
1734     static bool shouldSpeculateFinalObject(Node* op1, Node* op2)
1735     {
1736         return op1->shouldSpeculateFinalObject() && op2->shouldSpeculateFinalObject();
1737     }
1738
1739     static bool shouldSpeculateArray(Node* op1, Node* op2)
1740     {
1741         return op1->shouldSpeculateArray() && op2->shouldSpeculateArray();
1742     }
1743     
1744     bool canSpeculateInt32(RareCaseProfilingSource source)
1745     {
1746         return nodeCanSpeculateInt32(arithNodeFlags(), source);
1747     }
1748     
1749     bool canSpeculateInt52(RareCaseProfilingSource source)
1750     {
1751         return nodeCanSpeculateInt52(arithNodeFlags(), source);
1752     }
1753     
1754     RareCaseProfilingSource sourceFor(PredictionPass pass)
1755     {
1756         if (pass == PrimaryPass || child1()->sawBooleans() || (child2() && child2()->sawBooleans()))
1757             return DFGRareCase;
1758         return AllRareCases;
1759     }
1760     
1761     bool canSpeculateInt32(PredictionPass pass)
1762     {
1763         return canSpeculateInt32(sourceFor(pass));
1764     }
1765     
1766     bool canSpeculateInt52(PredictionPass pass)
1767     {
1768         return canSpeculateInt52(sourceFor(pass));
1769     }
1770
1771     TypeLocation* typeLocation()
1772     {
1773         return reinterpret_cast<TypeLocation*>(m_opInfo);
1774     }
1775
1776     BasicBlockLocation* basicBlockLocation()
1777     {
1778         return reinterpret_cast<BasicBlockLocation*>(m_opInfo);
1779     }
1780     
1781     void dumpChildren(PrintStream& out)
1782     {
1783         if (!child1())
1784             return;
1785         out.printf("@%u", child1()->index());
1786         if (!child2())
1787             return;
1788         out.printf(", @%u", child2()->index());
1789         if (!child3())
1790             return;
1791         out.printf(", @%u", child3()->index());
1792     }
1793     
1794     // NB. This class must have a trivial destructor.
1795
1796     NodeOrigin origin;
1797
1798     // References to up to 3 children, or links to a variable length set of children.
1799     AdjacencyList children;
1800
1801 private:
1802     unsigned m_op : 10; // real type is NodeType
1803     unsigned m_flags : 22;
1804     // The virtual register number (spill location) associated with this .
1805     VirtualRegister m_virtualRegister;
1806     // The number of uses of the result of this operation (+1 for 'must generate' nodes, which have side-effects).
1807     unsigned m_refCount;
1808     // The prediction ascribed to this node after propagation.
1809     SpeculatedType m_prediction;
1810     // Immediate values, accesses type-checked via accessors above. The first one is
1811     // big enough to store a pointer.
1812     uintptr_t m_opInfo;
1813     uintptr_t m_opInfo2;
1814
1815 public:
1816     // Fields used by various analyses.
1817     AbstractValue value;
1818     
1819     // Miscellaneous data that is usually meaningless, but can hold some analysis results
1820     // if you ask right. For example, if you do Graph::initializeNodeOwners(), Node::owner
1821     // will tell you which basic block a node belongs to. You cannot rely on this persisting
1822     // across transformations unless you do the maintenance work yourself. Other phases use
1823     // Node::replacement, but they do so manually: first you do Graph::clearReplacements()
1824     // and then you set, and use, replacement's yourself.
1825     //
1826     // Bottom line: don't use these fields unless you initialize them yourself, or by
1827     // calling some appropriate methods that initialize them the way you want. Otherwise,
1828     // these fields are meaningless.
1829     Node* replacement;
1830     BasicBlock* owner;
1831 };
1832
1833 inline bool nodeComparator(Node* a, Node* b)
1834 {
1835     return a->index() < b->index();
1836 }
1837
1838 template<typename T>
1839 CString nodeListDump(const T& nodeList)
1840 {
1841     return sortedListDump(nodeList, nodeComparator);
1842 }
1843
1844 template<typename T>
1845 CString nodeMapDump(const T& nodeMap, DumpContext* context = 0)
1846 {
1847     Vector<typename T::KeyType> keys;
1848     for (
1849         typename T::const_iterator iter = nodeMap.begin();
1850         iter != nodeMap.end(); ++iter)
1851         keys.append(iter->key);
1852     std::sort(keys.begin(), keys.end(), nodeComparator);
1853     StringPrintStream out;
1854     CommaPrinter comma;
1855     for(unsigned i = 0; i < keys.size(); ++i)
1856         out.print(comma, keys[i], "=>", inContext(nodeMap.get(keys[i]), context));
1857     return out.toCString();
1858 }
1859
1860 } } // namespace JSC::DFG
1861
1862 namespace WTF {
1863
1864 void printInternal(PrintStream&, JSC::DFG::SwitchKind);
1865 void printInternal(PrintStream&, JSC::DFG::Node*);
1866
1867 inline JSC::DFG::Node* inContext(JSC::DFG::Node* node, JSC::DumpContext*) { return node; }
1868
1869 } // namespace WTF
1870
1871 using WTF::inContext;
1872
1873 #endif
1874 #endif