DFG JIT cannot compile op_new_object, op_new_array,
[WebKit.git] / Source / JavaScriptCore / dfg / DFGNode.h
1 /*
2  * Copyright (C) 2011 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
24  */
25
26 #ifndef DFGNode_h
27 #define DFGNode_h
28
29 #include <wtf/BoundsCheckedPointer.h>
30 #include <wtf/Platform.h>
31
32 // Emit various logging information for debugging, including dumping the dataflow graphs.
33 #define ENABLE_DFG_DEBUG_VERBOSE 0
34 // Emit dumps during propagation, in addition to just after.
35 #define ENABLE_DFG_DEBUG_PROPAGATION_VERBOSE 0
36 // Emit logging for OSR exit value recoveries at every node, not just nodes that
37 // actually has speculation checks.
38 #define ENABLE_DFG_VERBOSE_VALUE_RECOVERIES 0
39 // Enable generation of dynamic checks into the instruction stream.
40 #if !ASSERT_DISABLED
41 #define ENABLE_DFG_JIT_ASSERT 1
42 #else
43 #define ENABLE_DFG_JIT_ASSERT 0
44 #endif
45 // Consistency check contents compiler data structures.
46 #define ENBALE_DFG_CONSISTENCY_CHECK 0
47 // Emit a breakpoint into the head of every generated function, to aid debugging in GDB.
48 #define ENABLE_DFG_JIT_BREAK_ON_EVERY_FUNCTION 0
49 // Emit a breakpoint into the head of every generated node, to aid debugging in GDB.
50 #define ENABLE_DFG_JIT_BREAK_ON_EVERY_BLOCK 0
51 // Emit a breakpoint into the head of every generated node, to aid debugging in GDB.
52 #define ENABLE_DFG_JIT_BREAK_ON_EVERY_NODE 0
53 // Emit a breakpoint into the speculation failure code.
54 #define ENABLE_DFG_JIT_BREAK_ON_SPECULATION_FAILURE 0
55 // Log every speculation failure.
56 #define ENABLE_DFG_VERBOSE_SPECULATION_FAILURE 0
57 // Disable the DFG JIT without having to touch Platform.h!
58 #define DFG_DEBUG_LOCAL_DISBALE 0
59 // Enable OSR entry from baseline JIT.
60 #define ENABLE_DFG_OSR_ENTRY ENABLE_DFG_JIT
61 // Generate stats on how successful we were in making use of the DFG jit, and remaining on the hot path.
62 #define ENABLE_DFG_SUCCESS_STATS 0
63
64
65 #if ENABLE(DFG_JIT)
66
67 #include "CodeBlock.h"
68 #include "JSValue.h"
69 #include "PredictedType.h"
70 #include "ValueProfile.h"
71 #include <wtf/Vector.h>
72
73 namespace JSC { namespace DFG {
74
75 // Type for a virtual register number (spill location).
76 // Using an enum to make this type-checked at compile time, to avert programmer errors.
77 enum VirtualRegister { InvalidVirtualRegister = -1 };
78 COMPILE_ASSERT(sizeof(VirtualRegister) == sizeof(int), VirtualRegister_is_32bit);
79
80 // Type for a reference to another node in the graph.
81 typedef uint32_t NodeIndex;
82 static const NodeIndex NoNode = UINT_MAX;
83
84 // Information used to map back from an exception to any handler/source information,
85 // and to implement OSR.
86 // (Presently implemented as a bytecode index).
87 class CodeOrigin {
88 public:
89     CodeOrigin()
90         : m_bytecodeIndex(std::numeric_limits<uint32_t>::max())
91     {
92     }
93     
94     explicit CodeOrigin(uint32_t bytecodeIndex)
95         : m_bytecodeIndex(bytecodeIndex)
96     {
97     }
98     
99     bool isSet() const { return m_bytecodeIndex != std::numeric_limits<uint32_t>::max(); }
100     
101     uint32_t bytecodeIndex() const
102     {
103         ASSERT(isSet());
104         return m_bytecodeIndex;
105     }
106     
107 private:
108     uint32_t m_bytecodeIndex;
109 };
110
111 typedef unsigned ArithNodeFlags;
112 #define NodeUseBottom      0x00
113 #define NodeUsedAsNumber   0x01
114 #define NodeNeedsNegZero   0x02
115 #define NodeUsedAsMask     0x03
116 #define NodeMayOverflow    0x04
117 #define NodeMayNegZero     0x08
118 #define NodeBehaviorMask   0x0c
119
120 static inline bool nodeUsedAsNumber(ArithNodeFlags flags)
121 {
122     return !!(flags & NodeUsedAsNumber);
123 }
124
125 static inline bool nodeCanTruncateInteger(ArithNodeFlags flags)
126 {
127     return !nodeUsedAsNumber(flags);
128 }
129
130 static inline bool nodeCanIgnoreNegativeZero(ArithNodeFlags flags)
131 {
132     return !(flags & NodeNeedsNegZero);
133 }
134
135 static inline bool nodeCanSpeculateInteger(ArithNodeFlags flags)
136 {
137     if (flags & NodeMayOverflow)
138         return !nodeUsedAsNumber(flags);
139     
140     if (flags & NodeMayNegZero)
141         return nodeCanIgnoreNegativeZero(flags);
142     
143     return true;
144 }
145
146 #ifndef NDEBUG
147 static inline const char* arithNodeFlagsAsString(ArithNodeFlags flags)
148 {
149     if (!flags)
150         return "<empty>";
151
152     static const int size = 64;
153     static char description[size];
154     BoundsCheckedPointer<char> ptr(description, size);
155     
156     bool hasPrinted = false;
157     
158     if (flags & NodeUsedAsNumber) {
159         ptr.strcat("UsedAsNum");
160         hasPrinted = true;
161     }
162     
163     if (flags & NodeNeedsNegZero) {
164         if (hasPrinted)
165             ptr.strcat("|");
166         ptr.strcat("NeedsNegZero");
167         hasPrinted = true;
168     }
169     
170     if (flags & NodeMayOverflow) {
171         if (hasPrinted)
172             ptr.strcat("|");
173         ptr.strcat("MayOverflow");
174         hasPrinted = true;
175     }
176     
177     if (flags & NodeMayNegZero) {
178         if (hasPrinted)
179             ptr.strcat("|");
180         ptr.strcat("MayNegZero");
181         hasPrinted = true;
182     }
183     
184     *ptr++ = 0;
185     
186     return description;
187 }
188 #endif
189
190 // Entries in the NodeType enum (below) are composed of an id, a result type (possibly none)
191 // and some additional informative flags (must generate, is constant, etc).
192 #define NodeIdMask           0xFFF
193 #define NodeResultMask      0xF000
194 #define NodeMustGenerate   0x10000 // set on nodes that have side effects, and may not trivially be removed by DCE.
195 #define NodeIsConstant     0x20000
196 #define NodeIsJump         0x40000
197 #define NodeIsBranch       0x80000
198 #define NodeIsTerminal    0x100000
199 #define NodeHasVarArgs    0x200000
200 #define NodeClobbersWorld 0x400000
201 #define NodeMightClobber  0x800000
202
203 // These values record the result type of the node (as checked by NodeResultMask, above), 0 for no result.
204 #define NodeResultJS        0x1000
205 #define NodeResultNumber    0x2000
206 #define NodeResultInt32     0x3000
207 #define NodeResultBoolean   0x4000
208 #define NodeResultStorage   0x5000
209
210 // This macro defines a set of information about all known node types, used to populate NodeId, NodeType below.
211 #define FOR_EACH_DFG_OP(macro) \
212     /* Nodes for constants. */\
213     macro(JSConstant, NodeResultJS) \
214     \
215     /* Nodes for handling functions (both as call and as construct). */\
216     macro(ConvertThis, NodeResultJS) \
217     macro(CreateThis, NodeResultJS) /* Note this is not MustGenerate since we're returning it anyway. */ \
218     macro(GetCallee, NodeResultJS) \
219     \
220     /* Nodes for local variable access. */\
221     macro(GetLocal, NodeResultJS) \
222     macro(SetLocal, 0) \
223     macro(Phantom, NodeMustGenerate) \
224     macro(Phi, 0) \
225     \
226     /* Nodes for bitwise operations. */\
227     macro(BitAnd, NodeResultInt32) \
228     macro(BitOr, NodeResultInt32) \
229     macro(BitXor, NodeResultInt32) \
230     macro(BitLShift, NodeResultInt32) \
231     macro(BitRShift, NodeResultInt32) \
232     macro(BitURShift, NodeResultInt32) \
233     /* Bitwise operators call ToInt32 on their operands. */\
234     macro(ValueToInt32, NodeResultInt32 | NodeMustGenerate) \
235     /* Used to box the result of URShift nodes (result has range 0..2^32-1). */\
236     macro(UInt32ToNumber, NodeResultNumber) \
237     \
238     /* Nodes for arithmetic operations. */\
239     macro(ArithAdd, NodeResultNumber) \
240     macro(ArithSub, NodeResultNumber) \
241     macro(ArithMul, NodeResultNumber) \
242     macro(ArithDiv, NodeResultNumber) \
243     macro(ArithMod, NodeResultNumber) \
244     macro(ArithAbs, NodeResultNumber) \
245     macro(ArithMin, NodeResultNumber) \
246     macro(ArithMax, NodeResultNumber) \
247     macro(ArithSqrt, NodeResultNumber) \
248     /* Arithmetic operators call ToNumber on their operands. */\
249     macro(ValueToNumber, NodeResultNumber | NodeMustGenerate) \
250     \
251     /* A variant of ValueToNumber, which a hint that the parents will always use this as a double. */\
252     macro(ValueToDouble, NodeResultNumber | NodeMustGenerate) \
253     \
254     /* Add of values may either be arithmetic, or result in string concatenation. */\
255     macro(ValueAdd, NodeResultJS | NodeMustGenerate | NodeMightClobber) \
256     \
257     /* Property access. */\
258     /* PutByValAlias indicates a 'put' aliases a prior write to the same property. */\
259     /* Since a put to 'length' may invalidate optimizations here, */\
260     /* this must be the directly subsequent property put. */\
261     macro(GetByVal, NodeResultJS | NodeMustGenerate) \
262     macro(PutByVal, NodeMustGenerate | NodeClobbersWorld) \
263     macro(PutByValAlias, NodeMustGenerate | NodeClobbersWorld) \
264     macro(GetById, NodeResultJS | NodeMustGenerate | NodeClobbersWorld) \
265     macro(PutById, NodeMustGenerate | NodeClobbersWorld) \
266     macro(PutByIdDirect, NodeMustGenerate | NodeClobbersWorld) \
267     macro(CheckStructure, NodeResultStorage | NodeMustGenerate) \
268     macro(GetByOffset, NodeResultJS) \
269     macro(GetArrayLength, NodeResultInt32) \
270     macro(GetMethod, NodeResultJS | NodeMustGenerate) \
271     macro(CheckMethod, NodeResultJS | NodeMustGenerate) \
272     macro(GetScopeChain, NodeResultJS) \
273     macro(GetScopedVar, NodeResultJS | NodeMustGenerate) \
274     macro(PutScopedVar, NodeMustGenerate | NodeClobbersWorld) \
275     macro(GetGlobalVar, NodeResultJS | NodeMustGenerate) \
276     macro(PutGlobalVar, NodeMustGenerate | NodeClobbersWorld) \
277     \
278     /* Nodes for comparison operations. */\
279     macro(CompareLess, NodeResultBoolean | NodeMustGenerate | NodeMightClobber) \
280     macro(CompareLessEq, NodeResultBoolean | NodeMustGenerate | NodeMightClobber) \
281     macro(CompareGreater, NodeResultBoolean | NodeMustGenerate | NodeMightClobber) \
282     macro(CompareGreaterEq, NodeResultBoolean | NodeMustGenerate | NodeMightClobber) \
283     macro(CompareEq, NodeResultBoolean | NodeMustGenerate | NodeMightClobber) \
284     macro(CompareStrictEq, NodeResultBoolean) \
285     \
286     /* Calls. */\
287     macro(Call, NodeResultJS | NodeMustGenerate | NodeHasVarArgs | NodeClobbersWorld) \
288     macro(Construct, NodeResultJS | NodeMustGenerate | NodeHasVarArgs | NodeClobbersWorld) \
289     \
290     /* Allocations. */\
291     macro(NewObject, NodeResultJS) \
292     macro(NewArray, NodeResultJS | NodeHasVarArgs) \
293     macro(NewArrayBuffer, NodeResultJS) \
294     macro(NewRegexp, NodeResultJS) \
295     \
296     /* Resolve nodes. */\
297     macro(Resolve, NodeResultJS | NodeMustGenerate | NodeClobbersWorld) \
298     macro(ResolveBase, NodeResultJS | NodeMustGenerate | NodeClobbersWorld) \
299     macro(ResolveBaseStrictPut, NodeResultJS | NodeMustGenerate | NodeClobbersWorld) \
300     macro(ResolveGlobal, NodeResultJS | NodeMustGenerate | NodeClobbersWorld) \
301     \
302     /* Nodes for misc operations. */\
303     macro(Breakpoint, NodeMustGenerate | NodeClobbersWorld) \
304     macro(CheckHasInstance, NodeMustGenerate) \
305     macro(InstanceOf, NodeResultBoolean) \
306     macro(LogicalNot, NodeResultBoolean | NodeMightClobber) \
307     macro(ToPrimitive, NodeResultJS | NodeMustGenerate | NodeClobbersWorld) \
308     macro(StrCat, NodeResultJS | NodeMustGenerate | NodeHasVarArgs | NodeClobbersWorld) \
309     \
310     /* Block terminals. */\
311     macro(Jump, NodeMustGenerate | NodeIsTerminal | NodeIsJump) \
312     macro(Branch, NodeMustGenerate | NodeIsTerminal | NodeIsBranch) \
313     macro(Return, NodeMustGenerate | NodeIsTerminal) \
314     macro(Throw, NodeMustGenerate | NodeIsTerminal) \
315     macro(ThrowReferenceError, NodeMustGenerate | NodeIsTerminal) \
316     \
317     /* This is a pseudo-terminal. It means that execution should fall out of DFG at */\
318     /* this point, but execution does continue in the basic block - just in a */\
319     /* different compiler. */\
320     macro(ForceOSRExit, NodeMustGenerate)
321
322 // This enum generates a monotonically increasing id for all Node types,
323 // and is used by the subsequent enum to fill out the id (as accessed via the NodeIdMask).
324 enum NodeId {
325 #define DFG_OP_ENUM(opcode, flags) opcode##_id,
326     FOR_EACH_DFG_OP(DFG_OP_ENUM)
327 #undef DFG_OP_ENUM
328     LastNodeId
329 };
330
331 // Entries in this enum describe all Node types.
332 // The enum value contains a monotonically increasing id, a result type, and additional flags.
333 enum NodeType {
334 #define DFG_OP_ENUM(opcode, flags) opcode = opcode##_id | (flags),
335     FOR_EACH_DFG_OP(DFG_OP_ENUM)
336 #undef DFG_OP_ENUM
337 };
338
339 // This type used in passing an immediate argument to Node constructor;
340 // distinguishes an immediate value (typically an index into a CodeBlock data structure - 
341 // a constant index, argument, or identifier) from a NodeIndex.
342 struct OpInfo {
343     explicit OpInfo(int32_t value) : m_value(static_cast<uintptr_t>(value)) { }
344     explicit OpInfo(uint32_t value) : m_value(static_cast<uintptr_t>(value)) { }
345     explicit OpInfo(size_t value) : m_value(static_cast<uintptr_t>(value)) { }
346     explicit OpInfo(void* value) : m_value(reinterpret_cast<uintptr_t>(value)) { }
347     uintptr_t m_value;
348 };
349
350 // === Node ===
351 //
352 // Node represents a single operation in the data flow graph.
353 struct Node {
354     enum VarArgTag { VarArg };
355
356     // Construct a node with up to 3 children, no immediate value.
357     Node(NodeType op, CodeOrigin codeOrigin, NodeIndex child1 = NoNode, NodeIndex child2 = NoNode, NodeIndex child3 = NoNode)
358         : op(op)
359         , codeOrigin(codeOrigin)
360         , m_virtualRegister(InvalidVirtualRegister)
361         , m_refCount(0)
362     {
363         ASSERT(!(op & NodeHasVarArgs));
364         ASSERT(!hasArithNodeFlags());
365         children.fixed.child1 = child1;
366         children.fixed.child2 = child2;
367         children.fixed.child3 = child3;
368     }
369
370     // Construct a node with up to 3 children and an immediate value.
371     Node(NodeType op, CodeOrigin codeOrigin, OpInfo imm, NodeIndex child1 = NoNode, NodeIndex child2 = NoNode, NodeIndex child3 = NoNode)
372         : op(op)
373         , codeOrigin(codeOrigin)
374         , m_virtualRegister(InvalidVirtualRegister)
375         , m_refCount(0)
376         , m_opInfo(imm.m_value)
377     {
378         ASSERT(!(op & NodeHasVarArgs));
379         children.fixed.child1 = child1;
380         children.fixed.child2 = child2;
381         children.fixed.child3 = child3;
382     }
383
384     // Construct a node with up to 3 children and two immediate values.
385     Node(NodeType op, CodeOrigin codeOrigin, OpInfo imm1, OpInfo imm2, NodeIndex child1 = NoNode, NodeIndex child2 = NoNode, NodeIndex child3 = NoNode)
386         : op(op)
387         , codeOrigin(codeOrigin)
388         , m_virtualRegister(InvalidVirtualRegister)
389         , m_refCount(0)
390         , m_opInfo(imm1.m_value)
391         , m_opInfo2(safeCast<unsigned>(imm2.m_value))
392     {
393         ASSERT(!(op & NodeHasVarArgs));
394         children.fixed.child1 = child1;
395         children.fixed.child2 = child2;
396         children.fixed.child3 = child3;
397     }
398     
399     // Construct a node with a variable number of children and two immediate values.
400     Node(VarArgTag, NodeType op, CodeOrigin codeOrigin, OpInfo imm1, OpInfo imm2, unsigned firstChild, unsigned numChildren)
401         : op(op)
402         , codeOrigin(codeOrigin)
403         , m_virtualRegister(InvalidVirtualRegister)
404         , m_refCount(0)
405         , m_opInfo(imm1.m_value)
406         , m_opInfo2(safeCast<unsigned>(imm2.m_value))
407     {
408         ASSERT(op & NodeHasVarArgs);
409         children.variable.firstChild = firstChild;
410         children.variable.numChildren = numChildren;
411     }
412
413     bool mustGenerate()
414     {
415         return op & NodeMustGenerate;
416     }
417
418     bool isConstant()
419     {
420         return op == JSConstant;
421     }
422     
423     bool hasConstant()
424     {
425         return isConstant() || hasMethodCheckData();
426     }
427
428     unsigned constantNumber()
429     {
430         ASSERT(isConstant());
431         return m_opInfo;
432     }
433     
434     // NOTE: this only works for JSConstant nodes.
435     JSValue valueOfJSConstantNode(CodeBlock* codeBlock)
436     {
437         return codeBlock->constantRegister(FirstConstantRegisterIndex + constantNumber()).get();
438     }
439
440     bool isInt32Constant(CodeBlock* codeBlock)
441     {
442         return isConstant() && valueOfJSConstantNode(codeBlock).isInt32();
443     }
444     
445     bool isDoubleConstant(CodeBlock* codeBlock)
446     {
447         bool result = isConstant() && valueOfJSConstantNode(codeBlock).isDouble();
448         if (result)
449             ASSERT(!isInt32Constant(codeBlock));
450         return result;
451     }
452     
453     bool isNumberConstant(CodeBlock* codeBlock)
454     {
455         bool result = isConstant() && valueOfJSConstantNode(codeBlock).isNumber();
456         ASSERT(result == (isInt32Constant(codeBlock) || isDoubleConstant(codeBlock)));
457         return result;
458     }
459     
460     bool isBooleanConstant(CodeBlock* codeBlock)
461     {
462         return isConstant() && valueOfJSConstantNode(codeBlock).isBoolean();
463     }
464     
465     bool hasLocal()
466     {
467         return op == GetLocal || op == SetLocal;
468     }
469
470     VirtualRegister local()
471     {
472         ASSERT(hasLocal());
473         return (VirtualRegister)m_opInfo;
474     }
475
476 #if !ASSERT_DISABLED
477     bool hasIdentifier()
478     {
479         switch (op) {
480         case GetById:
481         case PutById:
482         case PutByIdDirect:
483         case GetMethod:
484         case CheckMethod:
485         case Resolve:
486         case ResolveBase:
487         case ResolveBaseStrictPut:
488             return true;
489         default:
490             return false;
491         }
492     }
493 #endif
494
495     unsigned identifierNumber()
496     {
497         ASSERT(hasIdentifier());
498         return m_opInfo;
499     }
500     
501     unsigned resolveGlobalDataIndex()
502     {
503         ASSERT(op == ResolveGlobal);
504         return m_opInfo;
505     }
506
507     bool hasArithNodeFlags()
508     {
509         switch (op) {
510         case ValueToNumber:
511         case ValueToDouble:
512         case UInt32ToNumber:
513         case ArithAdd:
514         case ArithSub:
515         case ArithMul:
516         case ArithAbs:
517         case ArithMin:
518         case ArithMax:
519         case ArithMod:
520         case ArithDiv:
521         case ValueAdd:
522             return true;
523         default:
524             return false;
525         }
526     }
527     
528     ArithNodeFlags rawArithNodeFlags()
529     {
530         ASSERT(hasArithNodeFlags());
531         return m_opInfo;
532     }
533     
534     // This corrects the arithmetic node flags, so that irrelevant bits are
535     // ignored. In particular, anything other than ArithMul does not need
536     // to know if it can speculate on negative zero.
537     ArithNodeFlags arithNodeFlags()
538     {
539         ArithNodeFlags result = rawArithNodeFlags();
540         if (op == ArithMul)
541             return result;
542         return result & ~NodeNeedsNegZero;
543     }
544     
545     ArithNodeFlags arithNodeFlagsForCompare()
546     {
547         if (hasArithNodeFlags())
548             return arithNodeFlags();
549         return 0;
550     }
551     
552     void setArithNodeFlag(ArithNodeFlags flags)
553     {
554         ASSERT(hasArithNodeFlags());
555         m_opInfo = flags;
556     }
557     
558     bool mergeArithNodeFlags(ArithNodeFlags flags)
559     {
560         if (!hasArithNodeFlags())
561             return false;
562         ArithNodeFlags newFlags = m_opInfo | flags;
563         if (newFlags == m_opInfo)
564             return false;
565         m_opInfo = newFlags;
566         return true;
567     }
568     
569     bool hasConstantBuffer()
570     {
571         return op == NewArrayBuffer;
572     }
573     
574     unsigned startConstant()
575     {
576         ASSERT(hasConstantBuffer());
577         return m_opInfo;
578     }
579     
580     unsigned numConstants()
581     {
582         ASSERT(hasConstantBuffer());
583         return m_opInfo2;
584     }
585     
586     bool hasRegexpIndex()
587     {
588         return op == NewRegexp;
589     }
590     
591     unsigned regexpIndex()
592     {
593         ASSERT(hasRegexpIndex());
594         return m_opInfo;
595     }
596     
597     bool hasVarNumber()
598     {
599         return op == GetGlobalVar || op == PutGlobalVar || op == GetScopedVar || op == PutScopedVar;
600     }
601
602     unsigned varNumber()
603     {
604         ASSERT(hasVarNumber());
605         return m_opInfo;
606     }
607
608     bool hasScopeChainDepth()
609     {
610         return op == GetScopeChain;
611     }
612     
613     unsigned scopeChainDepth()
614     {
615         ASSERT(hasScopeChainDepth());
616         return m_opInfo;
617     }
618
619     bool hasResult()
620     {
621         return op & NodeResultMask;
622     }
623
624     bool hasInt32Result()
625     {
626         return (op & NodeResultMask) == NodeResultInt32;
627     }
628     
629     bool hasNumberResult()
630     {
631         return (op & NodeResultMask) == NodeResultNumber;
632     }
633     
634     bool hasJSResult()
635     {
636         return (op & NodeResultMask) == NodeResultJS;
637     }
638     
639     bool hasBooleanResult()
640     {
641         return (op & NodeResultMask) == NodeResultBoolean;
642     }
643
644     bool isJump()
645     {
646         return op & NodeIsJump;
647     }
648
649     bool isBranch()
650     {
651         return op & NodeIsBranch;
652     }
653
654     bool isTerminal()
655     {
656         return op & NodeIsTerminal;
657     }
658
659     unsigned takenBytecodeOffset()
660     {
661         ASSERT(isBranch() || isJump());
662         return m_opInfo;
663     }
664
665     unsigned notTakenBytecodeOffset()
666     {
667         ASSERT(isBranch());
668         return m_opInfo2;
669     }
670     
671     bool hasPrediction()
672     {
673         switch (op) {
674         case GetById:
675         case GetMethod:
676         case GetByVal:
677         case Call:
678         case Construct:
679         case GetByOffset:
680         case GetScopedVar:
681         case Resolve:
682         case ResolveBase:
683         case ResolveBaseStrictPut:
684         case ResolveGlobal:
685             return true;
686         default:
687             return false;
688         }
689     }
690     
691     PredictedType getPrediction()
692     {
693         ASSERT(hasPrediction());
694         return static_cast<PredictedType>(m_opInfo2);
695     }
696     
697     bool predict(PredictedType prediction)
698     {
699         ASSERT(hasPrediction());
700         
701         return mergePrediction(m_opInfo2, prediction);
702     }
703     
704     bool hasMethodCheckData()
705     {
706         return op == CheckMethod;
707     }
708     
709     unsigned methodCheckDataIndex()
710     {
711         ASSERT(hasMethodCheckData());
712         return m_opInfo2;
713     }
714     
715     bool hasStructure()
716     {
717         return op == CheckStructure;
718     }
719     
720     Structure* structure()
721     {
722         return reinterpret_cast<Structure*>(m_opInfo);
723     }
724     
725     bool hasStorageAccessData()
726     {
727         return op == GetByOffset;
728     }
729     
730     unsigned storageAccessDataIndex()
731     {
732         return m_opInfo;
733     }
734     
735     bool hasVirtualRegister()
736     {
737         return m_virtualRegister != InvalidVirtualRegister;
738     }
739     
740     VirtualRegister virtualRegister()
741     {
742         ASSERT(hasResult());
743         ASSERT(m_virtualRegister != InvalidVirtualRegister);
744         return m_virtualRegister;
745     }
746
747     void setVirtualRegister(VirtualRegister virtualRegister)
748     {
749         ASSERT(hasResult());
750         ASSERT(m_virtualRegister == InvalidVirtualRegister);
751         m_virtualRegister = virtualRegister;
752     }
753
754     bool shouldGenerate()
755     {
756         return m_refCount && op != Phi;
757     }
758
759     unsigned refCount()
760     {
761         return m_refCount;
762     }
763
764     // returns true when ref count passes from 0 to 1.
765     bool ref()
766     {
767         return !m_refCount++;
768     }
769
770     unsigned adjustedRefCount()
771     {
772         return mustGenerate() ? m_refCount - 1 : m_refCount;
773     }
774     
775     void setRefCount(unsigned refCount)
776     {
777         m_refCount = refCount;
778     }
779     
780     NodeIndex child1()
781     {
782         ASSERT(!(op & NodeHasVarArgs));
783         return children.fixed.child1;
784     }
785     
786     // This is useful if you want to do a fast check on the first child
787     // before also doing a check on the opcode. Use this with care and
788     // avoid it if possible.
789     NodeIndex child1Unchecked()
790     {
791         return children.fixed.child1;
792     }
793
794     NodeIndex child2()
795     {
796         ASSERT(!(op & NodeHasVarArgs));
797         return children.fixed.child2;
798     }
799
800     NodeIndex child3()
801     {
802         ASSERT(!(op & NodeHasVarArgs));
803         return children.fixed.child3;
804     }
805     
806     unsigned firstChild()
807     {
808         ASSERT(op & NodeHasVarArgs);
809         return children.variable.firstChild;
810     }
811     
812     unsigned numChildren()
813     {
814         ASSERT(op & NodeHasVarArgs);
815         return children.variable.numChildren;
816     }
817     
818     // This enum value describes the type of the node.
819     NodeType op;
820     // Used to look up exception handling information (currently implemented as a bytecode index).
821     CodeOrigin codeOrigin;
822     // References to up to 3 children (0 for no child).
823     union {
824         struct {
825             NodeIndex child1, child2, child3;
826         } fixed;
827         struct {
828             unsigned firstChild;
829             unsigned numChildren;
830         } variable;
831     } children;
832
833 private:
834     // The virtual register number (spill location) associated with this .
835     VirtualRegister m_virtualRegister;
836     // The number of uses of the result of this operation (+1 for 'must generate' nodes, which have side-effects).
837     unsigned m_refCount;
838     // Immediate values, accesses type-checked via accessors above. The first one is
839     // big enough to store a pointer.
840     uintptr_t m_opInfo;
841     unsigned m_opInfo2;
842 };
843
844 } } // namespace JSC::DFG
845
846 #endif
847 #endif