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