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