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