[DOMJIT] Add a way for DOMJIT::Patchpoint to express effects
[WebKit-https.git] / Source / JavaScriptCore / dfg / DFGNode.h
1 /*
2  * Copyright (C) 2011-2016 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 #pragma once
27
28 #if ENABLE(DFG_JIT)
29
30 #include "BasicBlockLocation.h"
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 "DFGEpoch.h"
38 #include "DFGLazyJSValue.h"
39 #include "DFGMultiGetByOffsetData.h"
40 #include "DFGNodeFlags.h"
41 #include "DFGNodeOrigin.h"
42 #include "DFGNodeType.h"
43 #include "DFGObjectMaterializationData.h"
44 #include "DFGOpInfo.h"
45 #include "DFGTransition.h"
46 #include "DFGUseKind.h"
47 #include "DFGVariableAccessData.h"
48 #include "GetByIdVariant.h"
49 #include "JSCJSValue.h"
50 #include "Operands.h"
51 #include "PutByIdVariant.h"
52 #include "SpeculatedType.h"
53 #include "StructureSet.h"
54 #include "TypeLocation.h"
55 #include "ValueProfile.h"
56 #include <type_traits>
57 #include <wtf/ListDump.h>
58
59 namespace JSC {
60
61 namespace DOMJIT {
62 class GetterSetter;
63 class Patchpoint;
64 class CallDOMPatchpoint;
65 }
66
67 namespace Profiler {
68 class ExecutionCounter;
69 }
70
71 namespace DFG {
72
73 class Graph;
74 class PromotedLocationDescriptor;
75 struct BasicBlock;
76
77 struct StorageAccessData {
78     PropertyOffset offset;
79     unsigned identifierNumber;
80
81     // This needs to know the inferred type. For puts, this is necessary because we need to remember
82     // what check is needed. For gets, this is necessary because otherwise AI might forget what type is
83     // guaranteed.
84     InferredType::Descriptor inferredType;
85 };
86
87 struct MultiPutByOffsetData {
88     unsigned identifierNumber;
89     Vector<PutByIdVariant, 2> variants;
90     
91     bool writesStructures() const;
92     bool reallocatesStorage() const;
93 };
94
95 struct NewArrayBufferData {
96     unsigned startConstant;
97     unsigned numConstants;
98     IndexingType indexingType;
99 };
100
101 struct BranchTarget {
102     BranchTarget()
103         : block(0)
104         , count(PNaN)
105     {
106     }
107     
108     explicit BranchTarget(BasicBlock* block)
109         : block(block)
110         , count(PNaN)
111     {
112     }
113     
114     void setBytecodeIndex(unsigned bytecodeIndex)
115     {
116         block = bitwise_cast<BasicBlock*>(static_cast<uintptr_t>(bytecodeIndex));
117     }
118     unsigned bytecodeIndex() const { return bitwise_cast<uintptr_t>(block); }
119     
120     void dump(PrintStream&) const;
121     
122     BasicBlock* block;
123     float count;
124 };
125
126 struct BranchData {
127     static BranchData withBytecodeIndices(
128         unsigned takenBytecodeIndex, unsigned notTakenBytecodeIndex)
129     {
130         BranchData result;
131         result.taken.block = bitwise_cast<BasicBlock*>(static_cast<uintptr_t>(takenBytecodeIndex));
132         result.notTaken.block = bitwise_cast<BasicBlock*>(static_cast<uintptr_t>(notTakenBytecodeIndex));
133         return result;
134     }
135     
136     unsigned takenBytecodeIndex() const { return taken.bytecodeIndex(); }
137     unsigned notTakenBytecodeIndex() const { return notTaken.bytecodeIndex(); }
138     
139     BasicBlock*& forCondition(bool condition)
140     {
141         if (condition)
142             return taken.block;
143         return notTaken.block;
144     }
145     
146     BranchTarget taken;
147     BranchTarget notTaken;
148 };
149
150 // The SwitchData and associated data structures duplicate the information in
151 // JumpTable. The DFG may ultimately end up using the JumpTable, though it may
152 // instead decide to do something different - this is entirely up to the DFG.
153 // These data structures give the DFG a higher-level semantic description of
154 // what is going on, which will allow it to make the right decision.
155 //
156 // Note that there will never be multiple SwitchCases in SwitchData::cases that
157 // have the same SwitchCase::value, since the bytecode's JumpTables never have
158 // duplicates - since the JumpTable maps a value to a target. It's a
159 // one-to-many mapping. So we may have duplicate targets, but never duplicate
160 // values.
161 struct SwitchCase {
162     SwitchCase()
163     {
164     }
165     
166     SwitchCase(LazyJSValue value, BasicBlock* target)
167         : value(value)
168         , target(target)
169     {
170     }
171     
172     static SwitchCase withBytecodeIndex(LazyJSValue value, unsigned bytecodeIndex)
173     {
174         SwitchCase result;
175         result.value = value;
176         result.target.setBytecodeIndex(bytecodeIndex);
177         return result;
178     }
179     
180     LazyJSValue value;
181     BranchTarget target;
182 };
183
184 struct SwitchData {
185     // Initializes most fields to obviously invalid values. Anyone
186     // constructing this should make sure to initialize everything they
187     // care about manually.
188     SwitchData()
189         : kind(static_cast<SwitchKind>(-1))
190         , switchTableIndex(UINT_MAX)
191         , didUseJumpTable(false)
192     {
193     }
194     
195     Vector<SwitchCase> cases;
196     BranchTarget fallThrough;
197     SwitchKind kind;
198     unsigned switchTableIndex;
199     bool didUseJumpTable;
200 };
201
202 struct CallVarargsData {
203     int firstVarArgOffset;
204 };
205
206 struct LoadVarargsData {
207     VirtualRegister start; // Local for the first element. This is the first actual argument, not this.
208     VirtualRegister count; // Local for the count.
209     VirtualRegister machineStart;
210     VirtualRegister machineCount;
211     unsigned offset; // Which array element to start with. Usually this is 0.
212     unsigned mandatoryMinimum; // The number of elements on the stack that must be initialized; if the array is too short then the missing elements must get undefined. Does not include "this".
213     unsigned limit; // Maximum number of elements to load. Includes "this".
214 };
215
216 struct StackAccessData {
217     StackAccessData()
218         : format(DeadFlush)
219     {
220     }
221     
222     StackAccessData(VirtualRegister local, FlushFormat format)
223         : local(local)
224         , format(format)
225     {
226     }
227     
228     VirtualRegister local;
229     VirtualRegister machineLocal;
230     FlushFormat format;
231     
232     FlushedAt flushedAt() { return FlushedAt(format, machineLocal); }
233 };
234
235 struct CallDOMData {
236     DOMJIT::GetterSetter* domJIT { nullptr };
237     DOMJIT::CallDOMPatchpoint* patchpoint { nullptr };
238 };
239
240 // === Node ===
241 //
242 // Node represents a single operation in the data flow graph.
243 struct Node {
244 public:
245     enum VarArgTag { VarArg };
246     
247     Node() { }
248     
249     Node(NodeType op, NodeOrigin nodeOrigin, const AdjacencyList& children)
250         : origin(nodeOrigin)
251         , children(children)
252         , m_virtualRegister(VirtualRegister())
253         , m_refCount(1)
254         , m_prediction(SpecNone)
255         , owner(nullptr)
256     {
257         m_misc.replacement = nullptr;
258         setOpAndDefaultFlags(op);
259     }
260     
261     // Construct a node with up to 3 children, no immediate value.
262     Node(NodeType op, NodeOrigin nodeOrigin, Edge child1 = Edge(), Edge child2 = Edge(), Edge child3 = Edge())
263         : origin(nodeOrigin)
264         , children(AdjacencyList::Fixed, child1, child2, child3)
265         , m_virtualRegister(VirtualRegister())
266         , m_refCount(1)
267         , m_prediction(SpecNone)
268         , owner(nullptr)
269     {
270         m_misc.replacement = nullptr;
271         setOpAndDefaultFlags(op);
272         ASSERT(!(m_flags & NodeHasVarArgs));
273     }
274
275     // Construct a node with up to 3 children, no immediate value.
276     Node(NodeFlags result, NodeType op, NodeOrigin nodeOrigin, Edge child1 = Edge(), Edge child2 = Edge(), Edge child3 = Edge())
277         : origin(nodeOrigin)
278         , children(AdjacencyList::Fixed, child1, child2, child3)
279         , m_virtualRegister(VirtualRegister())
280         , m_refCount(1)
281         , m_prediction(SpecNone)
282         , owner(nullptr)
283     {
284         m_misc.replacement = nullptr;
285         setOpAndDefaultFlags(op);
286         setResult(result);
287         ASSERT(!(m_flags & NodeHasVarArgs));
288     }
289
290     // Construct a node with up to 3 children and an immediate value.
291     Node(NodeType op, NodeOrigin nodeOrigin, OpInfo imm, Edge child1 = Edge(), Edge child2 = Edge(), Edge child3 = Edge())
292         : origin(nodeOrigin)
293         , children(AdjacencyList::Fixed, child1, child2, child3)
294         , m_virtualRegister(VirtualRegister())
295         , m_refCount(1)
296         , m_prediction(SpecNone)
297         , m_opInfo(imm.m_value)
298         , owner(nullptr)
299     {
300         m_misc.replacement = nullptr;
301         setOpAndDefaultFlags(op);
302         ASSERT(!(m_flags & NodeHasVarArgs));
303     }
304
305     // Construct a node with up to 3 children and an immediate value.
306     Node(NodeFlags result, NodeType op, NodeOrigin nodeOrigin, OpInfo imm, Edge child1 = Edge(), Edge child2 = Edge(), Edge child3 = Edge())
307         : origin(nodeOrigin)
308         , children(AdjacencyList::Fixed, child1, child2, child3)
309         , m_virtualRegister(VirtualRegister())
310         , m_refCount(1)
311         , m_prediction(SpecNone)
312         , m_opInfo(imm.m_value)
313         , owner(nullptr)
314     {
315         m_misc.replacement = nullptr;
316         setOpAndDefaultFlags(op);
317         setResult(result);
318         ASSERT(!(m_flags & NodeHasVarArgs));
319     }
320
321     // Construct a node with up to 3 children and two immediate values.
322     Node(NodeType op, NodeOrigin nodeOrigin, OpInfo imm1, OpInfo imm2, Edge child1 = Edge(), Edge child2 = Edge(), Edge child3 = Edge())
323         : origin(nodeOrigin)
324         , children(AdjacencyList::Fixed, child1, child2, child3)
325         , m_virtualRegister(VirtualRegister())
326         , m_refCount(1)
327         , m_prediction(SpecNone)
328         , m_opInfo(imm1.m_value)
329         , m_opInfo2(imm2.m_value)
330         , owner(nullptr)
331     {
332         m_misc.replacement = nullptr;
333         setOpAndDefaultFlags(op);
334         ASSERT(!(m_flags & NodeHasVarArgs));
335     }
336     
337     // Construct a node with a variable number of children and two immediate values.
338     Node(VarArgTag, NodeType op, NodeOrigin nodeOrigin, OpInfo imm1, OpInfo imm2, unsigned firstChild, unsigned numChildren)
339         : origin(nodeOrigin)
340         , children(AdjacencyList::Variable, firstChild, numChildren)
341         , m_virtualRegister(VirtualRegister())
342         , m_refCount(1)
343         , m_prediction(SpecNone)
344         , m_opInfo(imm1.m_value)
345         , m_opInfo2(imm2.m_value)
346         , owner(nullptr)
347     {
348         m_misc.replacement = nullptr;
349         setOpAndDefaultFlags(op);
350         ASSERT(m_flags & NodeHasVarArgs);
351     }
352     
353     NodeType op() const { return static_cast<NodeType>(m_op); }
354     NodeFlags flags() const { return m_flags; }
355
356     unsigned index() const { return m_index; }
357     
358     void setOp(NodeType op)
359     {
360         m_op = op;
361     }
362     
363     void setFlags(NodeFlags flags)
364     {
365         m_flags = flags;
366     }
367     
368     bool mergeFlags(NodeFlags flags)
369     {
370         NodeFlags newFlags = m_flags | flags;
371         if (newFlags == m_flags)
372             return false;
373         m_flags = newFlags;
374         return true;
375     }
376     
377     bool filterFlags(NodeFlags flags)
378     {
379         NodeFlags newFlags = m_flags & flags;
380         if (newFlags == m_flags)
381             return false;
382         m_flags = newFlags;
383         return true;
384     }
385     
386     bool clearFlags(NodeFlags flags)
387     {
388         return filterFlags(~flags);
389     }
390     
391     void setResult(NodeFlags result)
392     {
393         ASSERT(!(result & ~NodeResultMask));
394         clearFlags(NodeResultMask);
395         mergeFlags(result);
396     }
397     
398     NodeFlags result() const
399     {
400         return flags() & NodeResultMask;
401     }
402     
403     void setOpAndDefaultFlags(NodeType op)
404     {
405         m_op = op;
406         m_flags = defaultFlags(op);
407     }
408
409     void remove();
410
411     void convertToCheckStructure(StructureSet* set)
412     {
413         setOpAndDefaultFlags(CheckStructure);
414         m_opInfo = set; 
415     }
416
417     void convertToCheckStructureImmediate(Node* structure)
418     {
419         ASSERT(op() == CheckStructure);
420         m_op = CheckStructureImmediate;
421         children.setChild1(Edge(structure, CellUse));
422     }
423     
424     void replaceWith(Node* other)
425     {
426         remove();
427         setReplacement(other);
428     }
429
430     void convertToIdentity();
431     void convertToIdentityOn(Node*);
432
433     bool mustGenerate()
434     {
435         return m_flags & NodeMustGenerate;
436     }
437     
438     bool isConstant()
439     {
440         switch (op()) {
441         case JSConstant:
442         case DoubleConstant:
443         case Int52Constant:
444             return true;
445         default:
446             return false;
447         }
448     }
449     
450     bool hasConstant()
451     {
452         switch (op()) {
453         case JSConstant:
454         case DoubleConstant:
455         case Int52Constant:
456             return true;
457             
458         case PhantomDirectArguments:
459         case PhantomClonedArguments:
460             // These pretend to be the empty value constant for the benefit of the DFG backend, which
461             // otherwise wouldn't take kindly to a node that doesn't compute a value.
462             return true;
463             
464         default:
465             return false;
466         }
467     }
468
469     FrozenValue* constant()
470     {
471         ASSERT(hasConstant());
472         
473         if (op() == PhantomDirectArguments || op() == PhantomClonedArguments) {
474             // These pretend to be the empty value constant for the benefit of the DFG backend, which
475             // otherwise wouldn't take kindly to a node that doesn't compute a value.
476             return FrozenValue::emptySingleton();
477         }
478         
479         return m_opInfo.as<FrozenValue*>();
480     }
481     
482     // Don't call this directly - use Graph::convertToConstant() instead!
483     void convertToConstant(FrozenValue* value)
484     {
485         if (hasDoubleResult())
486             m_op = DoubleConstant;
487         else if (hasInt52Result())
488             m_op = Int52Constant;
489         else
490             m_op = JSConstant;
491         m_flags &= ~NodeMustGenerate;
492         m_opInfo = value;
493         children.reset();
494     }
495
496     void convertToLazyJSConstant(Graph&, LazyJSValue);
497     
498     void convertToConstantStoragePointer(void* pointer)
499     {
500         ASSERT(op() == GetIndexedPropertyStorage);
501         m_op = ConstantStoragePointer;
502         m_opInfo = pointer;
503         children.reset();
504     }
505     
506     void convertToGetLocalUnlinked(VirtualRegister local)
507     {
508         m_op = GetLocalUnlinked;
509         m_flags &= ~NodeMustGenerate;
510         m_opInfo = local.offset();
511         m_opInfo2 = VirtualRegister().offset();
512         children.reset();
513     }
514     
515     void convertToPutStack(StackAccessData* data)
516     {
517         m_op = PutStack;
518         m_flags |= NodeMustGenerate;
519         m_opInfo = data;
520         m_opInfo2 = OpInfoWrapper();
521     }
522     
523     void convertToGetStack(StackAccessData* data)
524     {
525         m_op = GetStack;
526         m_flags &= ~NodeMustGenerate;
527         m_opInfo = data;
528         m_opInfo2 = OpInfoWrapper();
529         children.reset();
530     }
531     
532     void convertToGetByOffset(StorageAccessData& data, Edge storage, Edge base)
533     {
534         ASSERT(m_op == GetById || m_op == GetByIdFlush || m_op == MultiGetByOffset);
535         m_opInfo = &data;
536         children.setChild1(storage);
537         children.setChild2(base);
538         m_op = GetByOffset;
539         m_flags &= ~NodeMustGenerate;
540     }
541     
542     void convertToMultiGetByOffset(MultiGetByOffsetData* data)
543     {
544         ASSERT(m_op == GetById || m_op == GetByIdFlush);
545         m_opInfo = data;
546         child1().setUseKind(CellUse);
547         m_op = MultiGetByOffset;
548         ASSERT(m_flags & NodeMustGenerate);
549     }
550     
551     void convertToPutByOffset(StorageAccessData& data, Edge storage, Edge base)
552     {
553         ASSERT(m_op == PutById || m_op == PutByIdDirect || m_op == PutByIdFlush || m_op == MultiPutByOffset);
554         m_opInfo = &data;
555         children.setChild3(children.child2());
556         children.setChild2(base);
557         children.setChild1(storage);
558         m_op = PutByOffset;
559     }
560     
561     void convertToMultiPutByOffset(MultiPutByOffsetData* data)
562     {
563         ASSERT(m_op == PutById || m_op == PutByIdDirect || m_op == PutByIdFlush);
564         m_opInfo = data;
565         m_op = MultiPutByOffset;
566     }
567     
568     void convertToPutHint(const PromotedLocationDescriptor&, Node* base, Node* value);
569     
570     void convertToPutByOffsetHint();
571     void convertToPutStructureHint(Node* structure);
572     void convertToPutClosureVarHint();
573     
574     void convertToPhantomNewObject()
575     {
576         ASSERT(m_op == NewObject || m_op == MaterializeNewObject);
577         m_op = PhantomNewObject;
578         m_flags &= ~NodeHasVarArgs;
579         m_flags |= NodeMustGenerate;
580         m_opInfo = OpInfoWrapper();
581         m_opInfo2 = OpInfoWrapper();
582         children = AdjacencyList();
583     }
584
585     void convertToPhantomNewFunction()
586     {
587         ASSERT(m_op == NewFunction || m_op == NewGeneratorFunction);
588         m_op = PhantomNewFunction;
589         m_flags |= NodeMustGenerate;
590         m_opInfo = OpInfoWrapper();
591         m_opInfo2 = OpInfoWrapper();
592         children = AdjacencyList();
593     }
594
595     void convertToPhantomNewGeneratorFunction()
596     {
597         ASSERT(m_op == NewGeneratorFunction);
598         m_op = PhantomNewGeneratorFunction;
599         m_flags |= NodeMustGenerate;
600         m_opInfo = OpInfoWrapper();
601         m_opInfo2 = OpInfoWrapper();
602         children = AdjacencyList();
603     }
604
605     void convertToPhantomCreateActivation()
606     {
607         ASSERT(m_op == CreateActivation || m_op == MaterializeCreateActivation);
608         m_op = PhantomCreateActivation;
609         m_flags &= ~NodeHasVarArgs;
610         m_flags |= NodeMustGenerate;
611         m_opInfo = OpInfoWrapper();
612         m_opInfo2 = OpInfoWrapper();
613         children = AdjacencyList();
614     }
615
616     void convertPhantomToPhantomLocal()
617     {
618         ASSERT(m_op == Phantom && (child1()->op() == Phi || child1()->op() == SetLocal || child1()->op() == SetArgument));
619         m_op = PhantomLocal;
620         m_opInfo = child1()->m_opInfo; // Copy the variableAccessData.
621         children.setChild1(Edge());
622     }
623     
624     void convertFlushToPhantomLocal()
625     {
626         ASSERT(m_op == Flush);
627         m_op = PhantomLocal;
628         children = AdjacencyList();
629     }
630     
631     void convertToGetLocal(VariableAccessData* variable, Node* phi)
632     {
633         ASSERT(m_op == GetLocalUnlinked);
634         m_op = GetLocal;
635         m_opInfo = variable;
636         m_opInfo2 = OpInfoWrapper();
637         children.setChild1(Edge(phi));
638     }
639     
640     void convertToToString()
641     {
642         ASSERT(m_op == ToPrimitive);
643         m_op = ToString;
644     }
645
646     void convertToArithNegate()
647     {
648         ASSERT(m_op == ArithAbs && child1().useKind() == Int32Use);
649         m_op = ArithNegate;
650     }
651     
652     void convertToDirectCall(FrozenValue*);
653     
654     JSValue asJSValue()
655     {
656         return constant()->value();
657     }
658      
659     bool isInt32Constant()
660     {
661         return isConstant() && constant()->value().isInt32();
662     }
663      
664     int32_t asInt32()
665     {
666         return asJSValue().asInt32();
667     }
668      
669     uint32_t asUInt32()
670     {
671         return asInt32();
672     }
673      
674     bool isDoubleConstant()
675     {
676         return isConstant() && constant()->value().isDouble();
677     }
678      
679     bool isNumberConstant()
680     {
681         return isConstant() && constant()->value().isNumber();
682     }
683     
684     double asNumber()
685     {
686         return asJSValue().asNumber();
687     }
688      
689     bool isAnyIntConstant()
690     {
691         return isConstant() && constant()->value().isAnyInt();
692     }
693      
694     int64_t asAnyInt()
695     {
696         return asJSValue().asAnyInt();
697     }
698      
699     bool isBooleanConstant()
700     {
701         return isConstant() && constant()->value().isBoolean();
702     }
703      
704     bool asBoolean()
705     {
706         return constant()->value().asBoolean();
707     }
708
709     bool isUndefinedOrNullConstant()
710     {
711         return isConstant() && constant()->value().isUndefinedOrNull();
712     }
713
714     bool isCellConstant()
715     {
716         return isConstant() && constant()->value() && constant()->value().isCell();
717     }
718      
719     JSCell* asCell()
720     {
721         return constant()->value().asCell();
722     }
723      
724     template<typename T>
725     T dynamicCastConstant()
726     {
727         if (!isCellConstant())
728             return nullptr;
729         return jsDynamicCast<T>(asCell());
730     }
731     
732     template<typename T>
733     T castConstant()
734     {
735         T result = dynamicCastConstant<T>();
736         RELEASE_ASSERT(result);
737         return result;
738     }
739
740     bool hasLazyJSValue()
741     {
742         return op() == LazyJSConstant;
743     }
744
745     LazyJSValue lazyJSValue()
746     {
747         ASSERT(hasLazyJSValue());
748         return *m_opInfo.as<LazyJSValue*>();
749     }
750
751     String tryGetString(Graph&);
752
753     JSValue initializationValueForActivation() const
754     {
755         ASSERT(op() == CreateActivation);
756         return m_opInfo2.as<FrozenValue*>()->value();
757     }
758
759     bool hasArgumentsChild()
760     {
761         switch (op()) {
762         case GetMyArgumentByVal:
763         case GetMyArgumentByValOutOfBounds:
764         case LoadVarargs:
765         case ForwardVarargs:
766         case CallVarargs:
767         case CallForwardVarargs:
768         case ConstructVarargs:
769         case ConstructForwardVarargs:
770         case TailCallVarargs:
771         case TailCallForwardVarargs:
772         case TailCallVarargsInlinedCaller:
773         case TailCallForwardVarargsInlinedCaller:
774             return true;
775         default:
776             return false;
777         }
778     }
779
780     Edge& argumentsChild()
781     {
782         switch (op()) {
783         case GetMyArgumentByVal:
784         case GetMyArgumentByValOutOfBounds:
785         case LoadVarargs:
786         case ForwardVarargs:
787             return child1();
788         case CallVarargs:
789         case CallForwardVarargs:
790         case ConstructVarargs:
791         case ConstructForwardVarargs:
792         case TailCallVarargs:
793         case TailCallForwardVarargs:
794         case TailCallVarargsInlinedCaller:
795         case TailCallForwardVarargsInlinedCaller:
796             return child3();
797         default:
798             RELEASE_ASSERT_NOT_REACHED();
799             return child1();
800         }
801     }
802
803     bool containsMovHint()
804     {
805         switch (op()) {
806         case MovHint:
807         case ZombieHint:
808             return true;
809         default:
810             return false;
811         }
812     }
813     
814     bool hasVariableAccessData(Graph&);
815     bool accessesStack(Graph& graph)
816     {
817         return hasVariableAccessData(graph);
818     }
819     
820     // This is useful for debugging code, where a node that should have a variable
821     // access data doesn't have one because it hasn't been initialized yet.
822     VariableAccessData* tryGetVariableAccessData()
823     {
824         VariableAccessData* result = m_opInfo.as<VariableAccessData*>();
825         if (!result)
826             return 0;
827         return result->find();
828     }
829     
830     VariableAccessData* variableAccessData()
831     {
832         return m_opInfo.as<VariableAccessData*>()->find();
833     }
834     
835     VirtualRegister local()
836     {
837         return variableAccessData()->local();
838     }
839     
840     VirtualRegister machineLocal()
841     {
842         return variableAccessData()->machineLocal();
843     }
844     
845     bool hasUnlinkedLocal()
846     {
847         switch (op()) {
848         case GetLocalUnlinked:
849         case ExtractOSREntryLocal:
850         case MovHint:
851         case ZombieHint:
852         case KillStack:
853             return true;
854         default:
855             return false;
856         }
857     }
858     
859     VirtualRegister unlinkedLocal()
860     {
861         ASSERT(hasUnlinkedLocal());
862         return VirtualRegister(m_opInfo.as<int32_t>());
863     }
864     
865     bool hasUnlinkedMachineLocal()
866     {
867         return op() == GetLocalUnlinked;
868     }
869     
870     void setUnlinkedMachineLocal(VirtualRegister reg)
871     {
872         ASSERT(hasUnlinkedMachineLocal());
873         m_opInfo2 = reg.offset();
874     }
875     
876     VirtualRegister unlinkedMachineLocal()
877     {
878         ASSERT(hasUnlinkedMachineLocal());
879         return VirtualRegister(m_opInfo2.as<int32_t>());
880     }
881     
882     bool hasStackAccessData()
883     {
884         switch (op()) {
885         case PutStack:
886         case GetStack:
887             return true;
888         default:
889             return false;
890         }
891     }
892     
893     StackAccessData* stackAccessData()
894     {
895         ASSERT(hasStackAccessData());
896         return m_opInfo.as<StackAccessData*>();
897     }
898     
899     bool hasPhi()
900     {
901         return op() == Upsilon;
902     }
903     
904     Node* phi()
905     {
906         ASSERT(hasPhi());
907         return m_opInfo.as<Node*>();
908     }
909
910     bool isStoreBarrier()
911     {
912         return op() == StoreBarrier || op() == FencedStoreBarrier;
913     }
914
915     bool hasIdentifier()
916     {
917         switch (op()) {
918         case TryGetById:
919         case GetById:
920         case GetByIdFlush:
921         case GetByIdWithThis:
922         case PutById:
923         case PutByIdFlush:
924         case PutByIdDirect:
925         case PutByIdWithThis:
926         case PutGetterById:
927         case PutSetterById:
928         case PutGetterSetterById:
929         case DeleteById:
930         case GetDynamicVar:
931         case PutDynamicVar:
932         case ResolveScope:
933             return true;
934         default:
935             return false;
936         }
937     }
938
939     unsigned identifierNumber()
940     {
941         ASSERT(hasIdentifier());
942         return m_opInfo.as<unsigned>();
943     }
944
945     bool hasGetPutInfo()
946     {
947         switch (op()) {
948         case GetDynamicVar:
949         case PutDynamicVar:
950             return true;
951         default:
952             return false;
953         }
954     }
955
956     unsigned getPutInfo()
957     {
958         ASSERT(hasGetPutInfo());
959         return m_opInfo2.as<unsigned>();
960     }
961
962     bool hasAccessorAttributes()
963     {
964         switch (op()) {
965         case PutGetterById:
966         case PutSetterById:
967         case PutGetterSetterById:
968         case PutGetterByVal:
969         case PutSetterByVal:
970             return true;
971         default:
972             return false;
973         }
974     }
975
976     int32_t accessorAttributes()
977     {
978         ASSERT(hasAccessorAttributes());
979         switch (op()) {
980         case PutGetterById:
981         case PutSetterById:
982         case PutGetterSetterById:
983             return m_opInfo2.as<int32_t>();
984         case PutGetterByVal:
985         case PutSetterByVal:
986             return m_opInfo.as<int32_t>();
987         default:
988             RELEASE_ASSERT_NOT_REACHED();
989             return 0;
990         }
991     }
992     
993     bool hasPromotedLocationDescriptor()
994     {
995         return op() == PutHint;
996     }
997     
998     PromotedLocationDescriptor promotedLocationDescriptor();
999     
1000     // This corrects the arithmetic node flags, so that irrelevant bits are
1001     // ignored. In particular, anything other than ArithMul does not need
1002     // to know if it can speculate on negative zero.
1003     NodeFlags arithNodeFlags()
1004     {
1005         NodeFlags result = m_flags & NodeArithFlagsMask;
1006         if (op() == ArithMul || op() == ArithDiv || op() == ArithMod || op() == ArithNegate || op() == ArithPow || op() == ArithRound || op() == ArithFloor || op() == ArithCeil || op() == ArithTrunc || op() == DoubleAsInt32)
1007             return result;
1008         return result & ~NodeBytecodeNeedsNegZero;
1009     }
1010
1011     bool mayHaveNonIntResult()
1012     {
1013         return m_flags & NodeMayHaveNonIntResult;
1014     }
1015     
1016     bool mayHaveDoubleResult()
1017     {
1018         return m_flags & NodeMayHaveDoubleResult;
1019     }
1020     
1021     bool mayHaveNonNumberResult()
1022     {
1023         return m_flags & NodeMayHaveNonNumberResult;
1024     }
1025
1026     bool hasConstantBuffer()
1027     {
1028         return op() == NewArrayBuffer;
1029     }
1030     
1031     NewArrayBufferData* newArrayBufferData()
1032     {
1033         ASSERT(hasConstantBuffer());
1034         return m_opInfo.as<NewArrayBufferData*>();
1035     }
1036     
1037     unsigned startConstant()
1038     {
1039         return newArrayBufferData()->startConstant;
1040     }
1041     
1042     unsigned numConstants()
1043     {
1044         return newArrayBufferData()->numConstants;
1045     }
1046     
1047     bool hasIndexingType()
1048     {
1049         switch (op()) {
1050         case NewArray:
1051         case NewArrayWithSize:
1052         case NewArrayBuffer:
1053             return true;
1054         default:
1055             return false;
1056         }
1057     }
1058
1059     // Return the indexing type that an array allocation *wants* to use. It may end up using a different
1060     // type if we're having a bad time. You can determine the actual indexing type by asking the global
1061     // object:
1062     //
1063     //     m_graph.globalObjectFor(node->origin.semantic)->arrayStructureForIndexingTypeDuringAllocation(node->indexingType())
1064     //
1065     // This will give you a Structure*, and that will have some indexing type that may be different from
1066     // the this one.
1067     IndexingType indexingType()
1068     {
1069         ASSERT(hasIndexingType());
1070         if (op() == NewArrayBuffer)
1071             return newArrayBufferData()->indexingType;
1072         return static_cast<IndexingType>(m_opInfo.as<uint32_t>());
1073     }
1074     
1075     bool hasTypedArrayType()
1076     {
1077         switch (op()) {
1078         case NewTypedArray:
1079             return true;
1080         default:
1081             return false;
1082         }
1083     }
1084     
1085     TypedArrayType typedArrayType()
1086     {
1087         ASSERT(hasTypedArrayType());
1088         TypedArrayType result = static_cast<TypedArrayType>(m_opInfo.as<uint32_t>());
1089         ASSERT(isTypedView(result));
1090         return result;
1091     }
1092     
1093     bool hasInlineCapacity()
1094     {
1095         return op() == CreateThis;
1096     }
1097
1098     unsigned inlineCapacity()
1099     {
1100         ASSERT(hasInlineCapacity());
1101         return m_opInfo.as<unsigned>();
1102     }
1103
1104     void setIndexingType(IndexingType indexingType)
1105     {
1106         ASSERT(hasIndexingType());
1107         m_opInfo = indexingType;
1108     }
1109     
1110     bool hasScopeOffset()
1111     {
1112         return op() == GetClosureVar || op() == PutClosureVar;
1113     }
1114
1115     ScopeOffset scopeOffset()
1116     {
1117         ASSERT(hasScopeOffset());
1118         return ScopeOffset(m_opInfo.as<uint32_t>());
1119     }
1120     
1121     bool hasDirectArgumentsOffset()
1122     {
1123         return op() == GetFromArguments || op() == PutToArguments;
1124     }
1125     
1126     DirectArgumentsOffset capturedArgumentsOffset()
1127     {
1128         ASSERT(hasDirectArgumentsOffset());
1129         return DirectArgumentsOffset(m_opInfo.as<uint32_t>());
1130     }
1131     
1132     bool hasRegisterPointer()
1133     {
1134         return op() == GetGlobalVar || op() == GetGlobalLexicalVariable || op() == PutGlobalVariable;
1135     }
1136     
1137     WriteBarrier<Unknown>* variablePointer()
1138     {
1139         return m_opInfo.as<WriteBarrier<Unknown>*>();
1140     }
1141     
1142     bool hasCallVarargsData()
1143     {
1144         switch (op()) {
1145         case CallVarargs:
1146         case CallForwardVarargs:
1147         case TailCallVarargs:
1148         case TailCallForwardVarargs:
1149         case TailCallVarargsInlinedCaller:
1150         case TailCallForwardVarargsInlinedCaller:
1151         case ConstructVarargs:
1152         case ConstructForwardVarargs:
1153             return true;
1154         default:
1155             return false;
1156         }
1157     }
1158     
1159     CallVarargsData* callVarargsData()
1160     {
1161         ASSERT(hasCallVarargsData());
1162         return m_opInfo.as<CallVarargsData*>();
1163     }
1164     
1165     bool hasLoadVarargsData()
1166     {
1167         return op() == LoadVarargs || op() == ForwardVarargs;
1168     }
1169     
1170     LoadVarargsData* loadVarargsData()
1171     {
1172         ASSERT(hasLoadVarargsData());
1173         return m_opInfo.as<LoadVarargsData*>();
1174     }
1175
1176     bool hasQueriedType()
1177     {
1178         return op() == IsCellWithType;
1179     }
1180
1181     JSType queriedType()
1182     {
1183         static_assert(std::is_same<uint8_t, std::underlying_type<JSType>::type>::value, "Ensure that uint8_t is the underlying type for JSType.");
1184         return static_cast<JSType>(m_opInfo.as<uint32_t>());
1185     }
1186
1187     bool hasSpeculatedTypeForQuery()
1188     {
1189         return op() == IsCellWithType;
1190     }
1191
1192     SpeculatedType speculatedTypeForQuery()
1193     {
1194         return speculationFromJSType(queriedType());
1195     }
1196     
1197     bool hasResult()
1198     {
1199         return !!result();
1200     }
1201     
1202     bool hasInt52Result()
1203     {
1204         return result() == NodeResultInt52;
1205     }
1206     
1207     bool hasNumberResult()
1208     {
1209         return result() == NodeResultNumber;
1210     }
1211     
1212     bool hasDoubleResult()
1213     {
1214         return result() == NodeResultDouble;
1215     }
1216     
1217     bool hasJSResult()
1218     {
1219         return result() == NodeResultJS;
1220     }
1221     
1222     bool hasBooleanResult()
1223     {
1224         return result() == NodeResultBoolean;
1225     }
1226
1227     bool hasStorageResult()
1228     {
1229         return result() == NodeResultStorage;
1230     }
1231     
1232     UseKind defaultUseKind()
1233     {
1234         return useKindForResult(result());
1235     }
1236     
1237     Edge defaultEdge()
1238     {
1239         return Edge(this, defaultUseKind());
1240     }
1241
1242     bool isJump()
1243     {
1244         return op() == Jump;
1245     }
1246
1247     bool isBranch()
1248     {
1249         return op() == Branch;
1250     }
1251     
1252     bool isSwitch()
1253     {
1254         return op() == Switch;
1255     }
1256
1257     bool isTerminal()
1258     {
1259         switch (op()) {
1260         case Jump:
1261         case Branch:
1262         case Switch:
1263         case Return:
1264         case TailCall:
1265         case DirectTailCall:
1266         case TailCallVarargs:
1267         case TailCallForwardVarargs:
1268         case Unreachable:
1269             return true;
1270         default:
1271             return false;
1272         }
1273     }
1274
1275     bool isFunctionTerminal()
1276     {
1277         if (isTerminal() && !numSuccessors())
1278             return true;
1279
1280         return false;
1281     }
1282
1283     unsigned targetBytecodeOffsetDuringParsing()
1284     {
1285         ASSERT(isJump());
1286         return m_opInfo.as<unsigned>();
1287     }
1288
1289     BasicBlock*& targetBlock()
1290     {
1291         ASSERT(isJump());
1292         return *bitwise_cast<BasicBlock**>(&m_opInfo.u.pointer);
1293     }
1294     
1295     BranchData* branchData()
1296     {
1297         ASSERT(isBranch());
1298         return m_opInfo.as<BranchData*>();
1299     }
1300     
1301     SwitchData* switchData()
1302     {
1303         ASSERT(isSwitch());
1304         return m_opInfo.as<SwitchData*>();
1305     }
1306     
1307     unsigned numSuccessors()
1308     {
1309         switch (op()) {
1310         case Jump:
1311             return 1;
1312         case Branch:
1313             return 2;
1314         case Switch:
1315             return switchData()->cases.size() + 1;
1316         default:
1317             return 0;
1318         }
1319     }
1320     
1321     BasicBlock*& successor(unsigned index)
1322     {
1323         if (isSwitch()) {
1324             if (index < switchData()->cases.size())
1325                 return switchData()->cases[index].target.block;
1326             RELEASE_ASSERT(index == switchData()->cases.size());
1327             return switchData()->fallThrough.block;
1328         }
1329         switch (index) {
1330         case 0:
1331             if (isJump())
1332                 return targetBlock();
1333             return branchData()->taken.block;
1334         case 1:
1335             return branchData()->notTaken.block;
1336         default:
1337             RELEASE_ASSERT_NOT_REACHED();
1338             return targetBlock();
1339         }
1340     }
1341     
1342     class SuccessorsIterable {
1343     public:
1344         SuccessorsIterable()
1345             : m_terminal(nullptr)
1346         {
1347         }
1348         
1349         SuccessorsIterable(Node* terminal)
1350             : m_terminal(terminal)
1351         {
1352         }
1353         
1354         class iterator {
1355         public:
1356             iterator()
1357                 : m_terminal(nullptr)
1358                 , m_index(UINT_MAX)
1359             {
1360             }
1361             
1362             iterator(Node* terminal, unsigned index)
1363                 : m_terminal(terminal)
1364                 , m_index(index)
1365             {
1366             }
1367             
1368             BasicBlock* operator*()
1369             {
1370                 return m_terminal->successor(m_index);
1371             }
1372             
1373             iterator& operator++()
1374             {
1375                 m_index++;
1376                 return *this;
1377             }
1378             
1379             bool operator==(const iterator& other) const
1380             {
1381                 return m_index == other.m_index;
1382             }
1383             
1384             bool operator!=(const iterator& other) const
1385             {
1386                 return !(*this == other);
1387             }
1388         private:
1389             Node* m_terminal;
1390             unsigned m_index;
1391         };
1392         
1393         iterator begin()
1394         {
1395             return iterator(m_terminal, 0);
1396         }
1397         
1398         iterator end()
1399         {
1400             return iterator(m_terminal, m_terminal->numSuccessors());
1401         }
1402
1403         size_t size() const { return m_terminal->numSuccessors(); }
1404         BasicBlock* at(size_t index) const { return m_terminal->successor(index); }
1405         BasicBlock* operator[](size_t index) const { return at(index); }
1406         
1407     private:
1408         Node* m_terminal;
1409     };
1410     
1411     SuccessorsIterable successors()
1412     {
1413         return SuccessorsIterable(this);
1414     }
1415     
1416     BasicBlock*& successorForCondition(bool condition)
1417     {
1418         return branchData()->forCondition(condition);
1419     }
1420     
1421     bool hasHeapPrediction()
1422     {
1423         switch (op()) {
1424         case ArithAbs:
1425         case ArithRound:
1426         case ArithFloor:
1427         case ArithCeil:
1428         case ArithTrunc:
1429         case GetDirectPname:
1430         case GetById:
1431         case GetByIdFlush:
1432         case GetByIdWithThis:
1433         case TryGetById:
1434         case GetByVal:
1435         case GetByValWithThis:
1436         case Call:
1437         case DirectCall:
1438         case TailCallInlinedCaller:
1439         case DirectTailCallInlinedCaller:
1440         case Construct:
1441         case DirectConstruct:
1442         case CallVarargs:
1443         case CallEval:
1444         case TailCallVarargsInlinedCaller:
1445         case ConstructVarargs:
1446         case CallForwardVarargs:
1447         case TailCallForwardVarargsInlinedCaller:
1448         case GetByOffset:
1449         case MultiGetByOffset:
1450         case GetClosureVar:
1451         case GetFromArguments:
1452         case ArrayPop:
1453         case ArrayPush:
1454         case RegExpExec:
1455         case RegExpTest:
1456         case GetGlobalVar:
1457         case GetGlobalLexicalVariable:
1458         case StringReplace:
1459         case StringReplaceRegExp:
1460         case ToNumber:
1461         case LoadFromJSMapBucket:
1462         case CallDOM:
1463             return true;
1464         default:
1465             return false;
1466         }
1467     }
1468     
1469     SpeculatedType getHeapPrediction()
1470     {
1471         ASSERT(hasHeapPrediction());
1472         return m_opInfo2.as<SpeculatedType>();
1473     }
1474
1475     void setHeapPrediction(SpeculatedType prediction)
1476     {
1477         ASSERT(hasHeapPrediction());
1478         m_opInfo2 = prediction;
1479     }
1480     
1481     bool hasCellOperand()
1482     {
1483         switch (op()) {
1484         case CheckCell:
1485         case OverridesHasInstance:
1486         case NewFunction:
1487         case NewGeneratorFunction:
1488         case CreateActivation:
1489         case MaterializeCreateActivation:
1490         case NewRegexp:
1491         case CompareEqPtr:
1492         case DirectCall:
1493         case DirectTailCall:
1494         case DirectConstruct:
1495         case DirectTailCallInlinedCaller:
1496             return true;
1497         default:
1498             return false;
1499         }
1500     }
1501
1502     FrozenValue* cellOperand()
1503     {
1504         ASSERT(hasCellOperand());
1505         return m_opInfo.as<FrozenValue*>();
1506     }
1507     
1508     template<typename T>
1509     T castOperand()
1510     {
1511         return cellOperand()->cast<T>();
1512     }
1513     
1514     void setCellOperand(FrozenValue* value)
1515     {
1516         ASSERT(hasCellOperand());
1517         m_opInfo = value;
1518     }
1519     
1520     bool hasWatchpointSet()
1521     {
1522         return op() == NotifyWrite;
1523     }
1524     
1525     WatchpointSet* watchpointSet()
1526     {
1527         ASSERT(hasWatchpointSet());
1528         return m_opInfo.as<WatchpointSet*>();
1529     }
1530     
1531     bool hasStoragePointer()
1532     {
1533         return op() == ConstantStoragePointer;
1534     }
1535     
1536     void* storagePointer()
1537     {
1538         ASSERT(hasStoragePointer());
1539         return m_opInfo.as<void*>();
1540     }
1541
1542     bool hasUidOperand()
1543     {
1544         return op() == CheckStringIdent;
1545     }
1546
1547     UniquedStringImpl* uidOperand()
1548     {
1549         ASSERT(hasUidOperand());
1550         return m_opInfo.as<UniquedStringImpl*>();
1551     }
1552
1553     bool hasTypeInfoOperand()
1554     {
1555         return op() == CheckTypeInfoFlags;
1556     }
1557
1558     unsigned typeInfoOperand()
1559     {
1560         ASSERT(hasTypeInfoOperand() && m_opInfo.as<uint32_t>() <= static_cast<uint32_t>(UCHAR_MAX));
1561         return m_opInfo.as<uint32_t>();
1562     }
1563
1564     bool hasTransition()
1565     {
1566         switch (op()) {
1567         case PutStructure:
1568         case AllocatePropertyStorage:
1569         case ReallocatePropertyStorage:
1570             return true;
1571         default:
1572             return false;
1573         }
1574     }
1575     
1576     Transition* transition()
1577     {
1578         ASSERT(hasTransition());
1579         return m_opInfo.as<Transition*>();
1580     }
1581     
1582     bool hasStructureSet()
1583     {
1584         switch (op()) {
1585         case CheckStructure:
1586         case CheckStructureImmediate:
1587         case MaterializeNewObject:
1588             return true;
1589         default:
1590             return false;
1591         }
1592     }
1593     
1594     StructureSet& structureSet()
1595     {
1596         ASSERT(hasStructureSet());
1597         return *m_opInfo.as<StructureSet*>();
1598     }
1599     
1600     bool hasStructure()
1601     {
1602         switch (op()) {
1603         case ArrayifyToStructure:
1604         case NewObject:
1605         case NewStringObject:
1606             return true;
1607         default:
1608             return false;
1609         }
1610     }
1611     
1612     Structure* structure()
1613     {
1614         ASSERT(hasStructure());
1615         return m_opInfo.as<Structure*>();
1616     }
1617     
1618     bool hasStorageAccessData()
1619     {
1620         switch (op()) {
1621         case GetByOffset:
1622         case PutByOffset:
1623         case GetGetterSetterByOffset:
1624             return true;
1625         default:
1626             return false;
1627         }
1628     }
1629     
1630     StorageAccessData& storageAccessData()
1631     {
1632         ASSERT(hasStorageAccessData());
1633         return *m_opInfo.as<StorageAccessData*>();
1634     }
1635     
1636     bool hasMultiGetByOffsetData()
1637     {
1638         return op() == MultiGetByOffset;
1639     }
1640     
1641     MultiGetByOffsetData& multiGetByOffsetData()
1642     {
1643         ASSERT(hasMultiGetByOffsetData());
1644         return *m_opInfo.as<MultiGetByOffsetData*>();
1645     }
1646     
1647     bool hasMultiPutByOffsetData()
1648     {
1649         return op() == MultiPutByOffset;
1650     }
1651     
1652     MultiPutByOffsetData& multiPutByOffsetData()
1653     {
1654         ASSERT(hasMultiPutByOffsetData());
1655         return *m_opInfo.as<MultiPutByOffsetData*>();
1656     }
1657     
1658     bool hasObjectMaterializationData()
1659     {
1660         switch (op()) {
1661         case MaterializeNewObject:
1662         case MaterializeCreateActivation:
1663             return true;
1664
1665         default:
1666             return false;
1667         }
1668     }
1669     
1670     ObjectMaterializationData& objectMaterializationData()
1671     {
1672         ASSERT(hasObjectMaterializationData());
1673         return *m_opInfo2.as<ObjectMaterializationData*>();
1674     }
1675
1676     bool isObjectAllocation()
1677     {
1678         switch (op()) {
1679         case NewObject:
1680         case MaterializeNewObject:
1681             return true;
1682         default:
1683             return false;
1684         }
1685     }
1686     
1687     bool isPhantomObjectAllocation()
1688     {
1689         switch (op()) {
1690         case PhantomNewObject:
1691             return true;
1692         default:
1693             return false;
1694         }
1695     }
1696     
1697     bool isActivationAllocation()
1698     {
1699         switch (op()) {
1700         case CreateActivation:
1701         case MaterializeCreateActivation:
1702             return true;
1703         default:
1704             return false;
1705         }
1706     }
1707
1708     bool isPhantomActivationAllocation()
1709     {
1710         switch (op()) {
1711         case PhantomCreateActivation:
1712             return true;
1713         default:
1714             return false;
1715         }
1716     }
1717
1718     bool isFunctionAllocation()
1719     {
1720         switch (op()) {
1721         case NewFunction:
1722         case NewGeneratorFunction:
1723             return true;
1724         default:
1725             return false;
1726         }
1727     }
1728
1729     bool isPhantomFunctionAllocation()
1730     {
1731         switch (op()) {
1732         case PhantomNewFunction:
1733         case PhantomNewGeneratorFunction:
1734             return true;
1735         default:
1736             return false;
1737         }
1738     }
1739
1740     bool isPhantomAllocation()
1741     {
1742         switch (op()) {
1743         case PhantomNewObject:
1744         case PhantomDirectArguments:
1745         case PhantomClonedArguments:
1746         case PhantomNewFunction:
1747         case PhantomNewGeneratorFunction:
1748         case PhantomCreateActivation:
1749             return true;
1750         default:
1751             return false;
1752         }
1753     }
1754     
1755     bool hasArrayMode()
1756     {
1757         switch (op()) {
1758         case GetIndexedPropertyStorage:
1759         case GetArrayLength:
1760         case PutByValDirect:
1761         case PutByVal:
1762         case PutByValAlias:
1763         case GetByVal:
1764         case StringCharAt:
1765         case StringCharCodeAt:
1766         case CheckArray:
1767         case Arrayify:
1768         case ArrayifyToStructure:
1769         case ArrayPush:
1770         case ArrayPop:
1771         case HasIndexedProperty:
1772             return true;
1773         default:
1774             return false;
1775         }
1776     }
1777     
1778     ArrayMode arrayMode()
1779     {
1780         ASSERT(hasArrayMode());
1781         if (op() == ArrayifyToStructure)
1782             return ArrayMode::fromWord(m_opInfo2.as<uint32_t>());
1783         return ArrayMode::fromWord(m_opInfo.as<uint32_t>());
1784     }
1785     
1786     bool setArrayMode(ArrayMode arrayMode)
1787     {
1788         ASSERT(hasArrayMode());
1789         if (this->arrayMode() == arrayMode)
1790             return false;
1791         m_opInfo = arrayMode.asWord();
1792         return true;
1793     }
1794     
1795     bool hasArithMode()
1796     {
1797         switch (op()) {
1798         case ArithAbs:
1799         case ArithAdd:
1800         case ArithSub:
1801         case ArithNegate:
1802         case ArithMul:
1803         case ArithDiv:
1804         case ArithMod:
1805         case UInt32ToNumber:
1806         case DoubleAsInt32:
1807             return true;
1808         default:
1809             return false;
1810         }
1811     }
1812
1813     Arith::Mode arithMode()
1814     {
1815         ASSERT(hasArithMode());
1816         return static_cast<Arith::Mode>(m_opInfo.as<uint32_t>());
1817     }
1818     
1819     void setArithMode(Arith::Mode mode)
1820     {
1821         m_opInfo = mode;
1822     }
1823
1824     bool hasArithRoundingMode()
1825     {
1826         return op() == ArithRound || op() == ArithFloor || op() == ArithCeil || op() == ArithTrunc;
1827     }
1828
1829     Arith::RoundingMode arithRoundingMode()
1830     {
1831         ASSERT(hasArithRoundingMode());
1832         return static_cast<Arith::RoundingMode>(m_opInfo.as<uint32_t>());
1833     }
1834
1835     void setArithRoundingMode(Arith::RoundingMode mode)
1836     {
1837         ASSERT(hasArithRoundingMode());
1838         m_opInfo = static_cast<uint32_t>(mode);
1839     }
1840     
1841     bool hasVirtualRegister()
1842     {
1843         return m_virtualRegister.isValid();
1844     }
1845     
1846     VirtualRegister virtualRegister()
1847     {
1848         ASSERT(hasResult());
1849         ASSERT(m_virtualRegister.isValid());
1850         return m_virtualRegister;
1851     }
1852     
1853     void setVirtualRegister(VirtualRegister virtualRegister)
1854     {
1855         ASSERT(hasResult());
1856         ASSERT(!m_virtualRegister.isValid());
1857         m_virtualRegister = virtualRegister;
1858     }
1859     
1860     bool hasExecutionCounter()
1861     {
1862         return op() == CountExecution;
1863     }
1864     
1865     Profiler::ExecutionCounter* executionCounter()
1866     {
1867         return m_opInfo.as<Profiler::ExecutionCounter*>();
1868     }
1869
1870     bool shouldGenerate()
1871     {
1872         return m_refCount;
1873     }
1874     
1875     bool isSemanticallySkippable()
1876     {
1877         return op() == CountExecution;
1878     }
1879
1880     unsigned refCount()
1881     {
1882         return m_refCount;
1883     }
1884
1885     unsigned postfixRef()
1886     {
1887         return m_refCount++;
1888     }
1889
1890     unsigned adjustedRefCount()
1891     {
1892         return mustGenerate() ? m_refCount - 1 : m_refCount;
1893     }
1894     
1895     void setRefCount(unsigned refCount)
1896     {
1897         m_refCount = refCount;
1898     }
1899     
1900     Edge& child1()
1901     {
1902         ASSERT(!(m_flags & NodeHasVarArgs));
1903         return children.child1();
1904     }
1905     
1906     // This is useful if you want to do a fast check on the first child
1907     // before also doing a check on the opcode. Use this with care and
1908     // avoid it if possible.
1909     Edge child1Unchecked()
1910     {
1911         return children.child1Unchecked();
1912     }
1913
1914     Edge& child2()
1915     {
1916         ASSERT(!(m_flags & NodeHasVarArgs));
1917         return children.child2();
1918     }
1919
1920     Edge& child3()
1921     {
1922         ASSERT(!(m_flags & NodeHasVarArgs));
1923         return children.child3();
1924     }
1925     
1926     unsigned firstChild()
1927     {
1928         ASSERT(m_flags & NodeHasVarArgs);
1929         return children.firstChild();
1930     }
1931     
1932     unsigned numChildren()
1933     {
1934         ASSERT(m_flags & NodeHasVarArgs);
1935         return children.numChildren();
1936     }
1937     
1938     UseKind binaryUseKind()
1939     {
1940         ASSERT(child1().useKind() == child2().useKind());
1941         return child1().useKind();
1942     }
1943     
1944     bool isBinaryUseKind(UseKind left, UseKind right)
1945     {
1946         return child1().useKind() == left && child2().useKind() == right;
1947     }
1948     
1949     bool isBinaryUseKind(UseKind useKind)
1950     {
1951         return isBinaryUseKind(useKind, useKind);
1952     }
1953     
1954     Edge childFor(UseKind useKind)
1955     {
1956         if (child1().useKind() == useKind)
1957             return child1();
1958         if (child2().useKind() == useKind)
1959             return child2();
1960         if (child3().useKind() == useKind)
1961             return child3();
1962         return Edge();
1963     }
1964     
1965     SpeculatedType prediction()
1966     {
1967         return m_prediction;
1968     }
1969     
1970     bool predict(SpeculatedType prediction)
1971     {
1972         return mergeSpeculation(m_prediction, prediction);
1973     }
1974     
1975     bool shouldSpeculateInt32()
1976     {
1977         return isInt32Speculation(prediction());
1978     }
1979     
1980     bool sawBooleans()
1981     {
1982         return !!(prediction() & SpecBoolean);
1983     }
1984     
1985     bool shouldSpeculateInt32OrBoolean()
1986     {
1987         return isInt32OrBooleanSpeculation(prediction());
1988     }
1989     
1990     bool shouldSpeculateInt32ForArithmetic()
1991     {
1992         return isInt32SpeculationForArithmetic(prediction());
1993     }
1994     
1995     bool shouldSpeculateInt32OrBooleanForArithmetic()
1996     {
1997         return isInt32OrBooleanSpeculationForArithmetic(prediction());
1998     }
1999     
2000     bool shouldSpeculateInt32OrBooleanExpectingDefined()
2001     {
2002         return isInt32OrBooleanSpeculationExpectingDefined(prediction());
2003     }
2004     
2005     bool shouldSpeculateAnyInt()
2006     {
2007         return isAnyIntSpeculation(prediction());
2008     }
2009     
2010     bool shouldSpeculateDouble()
2011     {
2012         return isDoubleSpeculation(prediction());
2013     }
2014     
2015     bool shouldSpeculateDoubleReal()
2016     {
2017         return isDoubleRealSpeculation(prediction());
2018     }
2019     
2020     bool shouldSpeculateNumber()
2021     {
2022         return isFullNumberSpeculation(prediction());
2023     }
2024     
2025     bool shouldSpeculateNumberOrBoolean()
2026     {
2027         return isFullNumberOrBooleanSpeculation(prediction());
2028     }
2029     
2030     bool shouldSpeculateNumberOrBooleanExpectingDefined()
2031     {
2032         return isFullNumberOrBooleanSpeculationExpectingDefined(prediction());
2033     }
2034     
2035     bool shouldSpeculateBoolean()
2036     {
2037         return isBooleanSpeculation(prediction());
2038     }
2039     
2040     bool shouldSpeculateOther()
2041     {
2042         return isOtherSpeculation(prediction());
2043     }
2044     
2045     bool shouldSpeculateMisc()
2046     {
2047         return isMiscSpeculation(prediction());
2048     }
2049    
2050     bool shouldSpeculateStringIdent()
2051     {
2052         return isStringIdentSpeculation(prediction());
2053     }
2054     
2055     bool shouldSpeculateNotStringVar()
2056     {
2057         return isNotStringVarSpeculation(prediction());
2058     }
2059  
2060     bool shouldSpeculateString()
2061     {
2062         return isStringSpeculation(prediction());
2063     }
2064  
2065     bool shouldSpeculateStringOrOther()
2066     {
2067         return isStringOrOtherSpeculation(prediction());
2068     }
2069  
2070     bool shouldSpeculateStringObject()
2071     {
2072         return isStringObjectSpeculation(prediction());
2073     }
2074     
2075     bool shouldSpeculateStringOrStringObject()
2076     {
2077         return isStringOrStringObjectSpeculation(prediction());
2078     }
2079
2080     bool shouldSpeculateRegExpObject()
2081     {
2082         return isRegExpObjectSpeculation(prediction());
2083     }
2084     
2085     bool shouldSpeculateSymbol()
2086     {
2087         return isSymbolSpeculation(prediction());
2088     }
2089     
2090     bool shouldSpeculateFinalObject()
2091     {
2092         return isFinalObjectSpeculation(prediction());
2093     }
2094     
2095     bool shouldSpeculateFinalObjectOrOther()
2096     {
2097         return isFinalObjectOrOtherSpeculation(prediction());
2098     }
2099     
2100     bool shouldSpeculateArray()
2101     {
2102         return isArraySpeculation(prediction());
2103     }
2104
2105     bool shouldSpeculateProxyObject()
2106     {
2107         return isProxyObjectSpeculation(prediction());
2108     }
2109
2110     bool shouldSpeculateDerivedArray()
2111     {
2112         return isDerivedArraySpeculation(prediction());
2113     }
2114     
2115     bool shouldSpeculateDirectArguments()
2116     {
2117         return isDirectArgumentsSpeculation(prediction());
2118     }
2119     
2120     bool shouldSpeculateScopedArguments()
2121     {
2122         return isScopedArgumentsSpeculation(prediction());
2123     }
2124     
2125     bool shouldSpeculateInt8Array()
2126     {
2127         return isInt8ArraySpeculation(prediction());
2128     }
2129     
2130     bool shouldSpeculateInt16Array()
2131     {
2132         return isInt16ArraySpeculation(prediction());
2133     }
2134     
2135     bool shouldSpeculateInt32Array()
2136     {
2137         return isInt32ArraySpeculation(prediction());
2138     }
2139     
2140     bool shouldSpeculateUint8Array()
2141     {
2142         return isUint8ArraySpeculation(prediction());
2143     }
2144
2145     bool shouldSpeculateUint8ClampedArray()
2146     {
2147         return isUint8ClampedArraySpeculation(prediction());
2148     }
2149     
2150     bool shouldSpeculateUint16Array()
2151     {
2152         return isUint16ArraySpeculation(prediction());
2153     }
2154     
2155     bool shouldSpeculateUint32Array()
2156     {
2157         return isUint32ArraySpeculation(prediction());
2158     }
2159     
2160     bool shouldSpeculateFloat32Array()
2161     {
2162         return isFloat32ArraySpeculation(prediction());
2163     }
2164     
2165     bool shouldSpeculateFloat64Array()
2166     {
2167         return isFloat64ArraySpeculation(prediction());
2168     }
2169     
2170     bool shouldSpeculateArrayOrOther()
2171     {
2172         return isArrayOrOtherSpeculation(prediction());
2173     }
2174     
2175     bool shouldSpeculateObject()
2176     {
2177         return isObjectSpeculation(prediction());
2178     }
2179     
2180     bool shouldSpeculateObjectOrOther()
2181     {
2182         return isObjectOrOtherSpeculation(prediction());
2183     }
2184
2185     bool shouldSpeculateCell()
2186     {
2187         return isCellSpeculation(prediction());
2188     }
2189     
2190     bool shouldSpeculateCellOrOther()
2191     {
2192         return isCellOrOtherSpeculation(prediction());
2193     }
2194     
2195     bool shouldSpeculateNotCell()
2196     {
2197         return isNotCellSpeculation(prediction());
2198     }
2199     
2200     bool shouldSpeculateUntypedForArithmetic()
2201     {
2202         return isUntypedSpeculationForArithmetic(prediction());
2203     }
2204
2205     static bool shouldSpeculateUntypedForArithmetic(Node* op1, Node* op2)
2206     {
2207         return op1->shouldSpeculateUntypedForArithmetic() || op2->shouldSpeculateUntypedForArithmetic();
2208     }
2209     
2210     bool shouldSpeculateUntypedForBitOps()
2211     {
2212         return isUntypedSpeculationForBitOps(prediction());
2213     }
2214     
2215     static bool shouldSpeculateUntypedForBitOps(Node* op1, Node* op2)
2216     {
2217         return op1->shouldSpeculateUntypedForBitOps() || op2->shouldSpeculateUntypedForBitOps();
2218     }
2219     
2220     static bool shouldSpeculateBoolean(Node* op1, Node* op2)
2221     {
2222         return op1->shouldSpeculateBoolean() && op2->shouldSpeculateBoolean();
2223     }
2224     
2225     static bool shouldSpeculateInt32(Node* op1, Node* op2)
2226     {
2227         return op1->shouldSpeculateInt32() && op2->shouldSpeculateInt32();
2228     }
2229     
2230     static bool shouldSpeculateInt32OrBoolean(Node* op1, Node* op2)
2231     {
2232         return op1->shouldSpeculateInt32OrBoolean()
2233             && op2->shouldSpeculateInt32OrBoolean();
2234     }
2235     
2236     static bool shouldSpeculateInt32OrBooleanForArithmetic(Node* op1, Node* op2)
2237     {
2238         return op1->shouldSpeculateInt32OrBooleanForArithmetic()
2239             && op2->shouldSpeculateInt32OrBooleanForArithmetic();
2240     }
2241     
2242     static bool shouldSpeculateInt32OrBooleanExpectingDefined(Node* op1, Node* op2)
2243     {
2244         return op1->shouldSpeculateInt32OrBooleanExpectingDefined()
2245             && op2->shouldSpeculateInt32OrBooleanExpectingDefined();
2246     }
2247     
2248     static bool shouldSpeculateAnyInt(Node* op1, Node* op2)
2249     {
2250         return op1->shouldSpeculateAnyInt() && op2->shouldSpeculateAnyInt();
2251     }
2252     
2253     static bool shouldSpeculateNumber(Node* op1, Node* op2)
2254     {
2255         return op1->shouldSpeculateNumber() && op2->shouldSpeculateNumber();
2256     }
2257     
2258     static bool shouldSpeculateNumberOrBoolean(Node* op1, Node* op2)
2259     {
2260         return op1->shouldSpeculateNumberOrBoolean()
2261             && op2->shouldSpeculateNumberOrBoolean();
2262     }
2263     
2264     static bool shouldSpeculateNumberOrBooleanExpectingDefined(Node* op1, Node* op2)
2265     {
2266         return op1->shouldSpeculateNumberOrBooleanExpectingDefined()
2267             && op2->shouldSpeculateNumberOrBooleanExpectingDefined();
2268     }
2269
2270     static bool shouldSpeculateSymbol(Node* op1, Node* op2)
2271     {
2272         return op1->shouldSpeculateSymbol() && op2->shouldSpeculateSymbol();
2273     }
2274     
2275     static bool shouldSpeculateFinalObject(Node* op1, Node* op2)
2276     {
2277         return op1->shouldSpeculateFinalObject() && op2->shouldSpeculateFinalObject();
2278     }
2279
2280     static bool shouldSpeculateArray(Node* op1, Node* op2)
2281     {
2282         return op1->shouldSpeculateArray() && op2->shouldSpeculateArray();
2283     }
2284     
2285     bool canSpeculateInt32(RareCaseProfilingSource source)
2286     {
2287         return nodeCanSpeculateInt32(arithNodeFlags(), source);
2288     }
2289     
2290     bool canSpeculateInt52(RareCaseProfilingSource source)
2291     {
2292         return nodeCanSpeculateInt52(arithNodeFlags(), source);
2293     }
2294     
2295     RareCaseProfilingSource sourceFor(PredictionPass pass)
2296     {
2297         if (pass == PrimaryPass || child1()->sawBooleans() || (child2() && child2()->sawBooleans()))
2298             return DFGRareCase;
2299         return AllRareCases;
2300     }
2301     
2302     bool canSpeculateInt32(PredictionPass pass)
2303     {
2304         return canSpeculateInt32(sourceFor(pass));
2305     }
2306     
2307     bool canSpeculateInt52(PredictionPass pass)
2308     {
2309         return canSpeculateInt52(sourceFor(pass));
2310     }
2311
2312     bool hasTypeLocation()
2313     {
2314         return op() == ProfileType;
2315     }
2316
2317     TypeLocation* typeLocation()
2318     {
2319         ASSERT(hasTypeLocation());
2320         return m_opInfo.as<TypeLocation*>();
2321     }
2322
2323     bool hasBasicBlockLocation()
2324     {
2325         return op() == ProfileControlFlow;
2326     }
2327
2328     BasicBlockLocation* basicBlockLocation()
2329     {
2330         ASSERT(hasBasicBlockLocation());
2331         return m_opInfo.as<BasicBlockLocation*>();
2332     }
2333
2334     bool hasCheckDOMPatchpoint() const
2335     {
2336         return op() == CheckDOM;
2337     }
2338
2339     DOMJIT::Patchpoint* checkDOMPatchpoint()
2340     {
2341         ASSERT(hasCheckDOMPatchpoint());
2342         return m_opInfo.as<DOMJIT::Patchpoint*>();
2343     }
2344
2345     bool hasCallDOMData() const
2346     {
2347         return op() == CallDOM;
2348     }
2349
2350     CallDOMData* callDOMData()
2351     {
2352         ASSERT(hasCallDOMData());
2353         return m_opInfo.as<CallDOMData*>();
2354     }
2355
2356     bool hasClassInfo() const
2357     {
2358         return op() == CheckDOM;
2359     }
2360
2361     const ClassInfo* classInfo()
2362     {
2363         return m_opInfo2.as<const ClassInfo*>();
2364     }
2365
2366     Node* replacement() const
2367     {
2368         return m_misc.replacement;
2369     }
2370     
2371     void setReplacement(Node* replacement)
2372     {
2373         m_misc.replacement = replacement;
2374     }
2375     
2376     Epoch epoch() const
2377     {
2378         return Epoch::fromUnsigned(m_misc.epoch);
2379     }
2380     
2381     void setEpoch(Epoch epoch)
2382     {
2383         m_misc.epoch = epoch.toUnsigned();
2384     }
2385
2386     unsigned numberOfArgumentsToSkip()
2387     {
2388         ASSERT(op() == CreateRest || op() == GetRestLength);
2389         return m_opInfo.as<unsigned>();
2390     }
2391
2392     void dumpChildren(PrintStream& out)
2393     {
2394         if (!child1())
2395             return;
2396         out.printf("@%u", child1()->index());
2397         if (!child2())
2398             return;
2399         out.printf(", @%u", child2()->index());
2400         if (!child3())
2401             return;
2402         out.printf(", @%u", child3()->index());
2403     }
2404     
2405     // NB. This class must have a trivial destructor.
2406
2407     NodeOrigin origin;
2408
2409     // References to up to 3 children, or links to a variable length set of children.
2410     AdjacencyList children;
2411
2412 private:
2413     friend class Graph;
2414
2415     unsigned m_index { std::numeric_limits<unsigned>::max() };
2416     unsigned m_op : 10; // real type is NodeType
2417     unsigned m_flags : 20;
2418     // The virtual register number (spill location) associated with this .
2419     VirtualRegister m_virtualRegister;
2420     // The number of uses of the result of this operation (+1 for 'must generate' nodes, which have side-effects).
2421     unsigned m_refCount;
2422     // The prediction ascribed to this node after propagation.
2423     SpeculatedType m_prediction { SpecNone };
2424     // Immediate values, accesses type-checked via accessors above.
2425     struct OpInfoWrapper {
2426         OpInfoWrapper()
2427         {
2428             u.int64 = 0;
2429         }
2430         OpInfoWrapper(uint32_t intValue)
2431         {
2432             u.int64 = 0;
2433             u.int32 = intValue;
2434         }
2435         OpInfoWrapper(uint64_t intValue)
2436         {
2437             u.int64 = intValue;
2438         }
2439         OpInfoWrapper(void* pointer)
2440         {
2441             u.int64 = 0;
2442             u.pointer = pointer;
2443         }
2444         OpInfoWrapper(const void* constPointer)
2445         {
2446             u.int64 = 0;
2447             u.constPointer = constPointer;
2448         }
2449         OpInfoWrapper& operator=(uint32_t int32)
2450         {
2451             u.int64 = 0;
2452             u.int32 = int32;
2453             return *this;
2454         }
2455         OpInfoWrapper& operator=(int32_t int32)
2456         {
2457             u.int64 = 0;
2458             u.int32 = int32;
2459             return *this;
2460         }
2461         OpInfoWrapper& operator=(uint64_t int64)
2462         {
2463             u.int64 = int64;
2464             return *this;
2465         }
2466         OpInfoWrapper& operator=(void* pointer)
2467         {
2468             u.int64 = 0;
2469             u.pointer = pointer;
2470             return *this;
2471         }
2472         OpInfoWrapper& operator=(const void* constPointer)
2473         {
2474             u.int64 = 0;
2475             u.constPointer = constPointer;
2476             return *this;
2477         }
2478         template <typename T>
2479         ALWAYS_INLINE auto as() const -> typename std::enable_if<std::is_pointer<T>::value && !std::is_const<typename std::remove_pointer<T>::type>::value, T>::type
2480         {
2481             return static_cast<T>(u.pointer);
2482         }
2483         template <typename T>
2484         ALWAYS_INLINE auto as() const -> typename std::enable_if<std::is_pointer<T>::value && std::is_const<typename std::remove_pointer<T>::type>::value, T>::type
2485         {
2486             return static_cast<T>(u.constPointer);
2487         }
2488         template <typename T>
2489         ALWAYS_INLINE auto as() const -> typename std::enable_if<std::is_integral<T>::value && sizeof(T) == 4, T>::type
2490         {
2491             return u.int32;
2492         }
2493         template <typename T>
2494         ALWAYS_INLINE auto as() const -> typename std::enable_if<std::is_integral<T>::value && sizeof(T) == 8, T>::type
2495         {
2496             return u.int64;
2497         }
2498         union {
2499             uint32_t int32;
2500             uint64_t int64;
2501             void* pointer;
2502             const void* constPointer;
2503         } u;
2504     };
2505     OpInfoWrapper m_opInfo;
2506     OpInfoWrapper m_opInfo2;
2507
2508     // Miscellaneous data that is usually meaningless, but can hold some analysis results
2509     // if you ask right. For example, if you do Graph::initializeNodeOwners(), Node::owner
2510     // will tell you which basic block a node belongs to. You cannot rely on this persisting
2511     // across transformations unless you do the maintenance work yourself. Other phases use
2512     // Node::replacement, but they do so manually: first you do Graph::clearReplacements()
2513     // and then you set, and use, replacement's yourself. Same thing for epoch.
2514     //
2515     // Bottom line: don't use these fields unless you initialize them yourself, or by
2516     // calling some appropriate methods that initialize them the way you want. Otherwise,
2517     // these fields are meaningless.
2518 private:
2519     union {
2520         Node* replacement;
2521         unsigned epoch;
2522     } m_misc;
2523 public:
2524     BasicBlock* owner;
2525 };
2526
2527 inline bool nodeComparator(Node* a, Node* b)
2528 {
2529     return a->index() < b->index();
2530 }
2531
2532 template<typename T>
2533 CString nodeListDump(const T& nodeList)
2534 {
2535     return sortedListDump(nodeList, nodeComparator);
2536 }
2537
2538 template<typename T>
2539 CString nodeMapDump(const T& nodeMap, DumpContext* context = 0)
2540 {
2541     Vector<typename T::KeyType> keys;
2542     for (
2543         typename T::const_iterator iter = nodeMap.begin();
2544         iter != nodeMap.end(); ++iter)
2545         keys.append(iter->key);
2546     std::sort(keys.begin(), keys.end(), nodeComparator);
2547     StringPrintStream out;
2548     CommaPrinter comma;
2549     for(unsigned i = 0; i < keys.size(); ++i)
2550         out.print(comma, keys[i], "=>", inContext(nodeMap.get(keys[i]), context));
2551     return out.toCString();
2552 }
2553
2554 template<typename T>
2555 CString nodeValuePairListDump(const T& nodeValuePairList, DumpContext* context = 0)
2556 {
2557     using V = typename T::ValueType;
2558     T sortedList = nodeValuePairList;
2559     std::sort(sortedList.begin(), sortedList.end(), [](const V& a, const V& b) {
2560         return nodeComparator(a.node, b.node);
2561     });
2562
2563     StringPrintStream out;
2564     CommaPrinter comma;
2565     for (const auto& pair : sortedList)
2566         out.print(comma, pair.node, "=>", inContext(pair.value, context));
2567     return out.toCString();
2568 }
2569
2570 } } // namespace JSC::DFG
2571
2572 namespace WTF {
2573
2574 void printInternal(PrintStream&, JSC::DFG::SwitchKind);
2575 void printInternal(PrintStream&, JSC::DFG::Node*);
2576
2577 inline JSC::DFG::Node* inContext(JSC::DFG::Node* node, JSC::DumpContext*) { return node; }
2578
2579 } // namespace WTF
2580
2581 using WTF::inContext;
2582
2583 #endif