2 * Copyright (C) 2011 Apple Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
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.
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.
29 #include <wtf/Platform.h>
33 #include "CodeBlock.h"
34 #include "CodeOrigin.h"
35 #include "DFGCommon.h"
36 #include "DFGOperands.h"
37 #include "DFGVariableAccessData.h"
39 #include "PredictedType.h"
40 #include "ValueProfile.h"
41 #include <wtf/BoundsCheckedPointer.h>
42 #include <wtf/Vector.h>
44 namespace JSC { namespace DFG {
46 struct StructureTransitionData {
47 Structure* previousStructure;
48 Structure* newStructure;
50 StructureTransitionData() { }
52 StructureTransitionData(Structure* previousStructure, Structure* newStructure)
53 : previousStructure(previousStructure)
54 , newStructure(newStructure)
59 typedef unsigned ArithNodeFlags;
60 #define NodeUseBottom 0x00
61 #define NodeUsedAsNumber 0x01
62 #define NodeNeedsNegZero 0x02
63 #define NodeUsedAsMask 0x03
64 #define NodeMayOverflow 0x04
65 #define NodeMayNegZero 0x08
66 #define NodeBehaviorMask 0x0c
68 static inline bool nodeUsedAsNumber(ArithNodeFlags flags)
70 return !!(flags & NodeUsedAsNumber);
73 static inline bool nodeCanTruncateInteger(ArithNodeFlags flags)
75 return !nodeUsedAsNumber(flags);
78 static inline bool nodeCanIgnoreNegativeZero(ArithNodeFlags flags)
80 return !(flags & NodeNeedsNegZero);
83 static inline bool nodeMayOverflow(ArithNodeFlags flags)
85 return !!(flags & NodeMayOverflow);
88 static inline bool nodeCanSpeculateInteger(ArithNodeFlags flags)
90 if (flags & NodeMayOverflow)
91 return !nodeUsedAsNumber(flags);
93 if (flags & NodeMayNegZero)
94 return nodeCanIgnoreNegativeZero(flags);
100 static inline const char* arithNodeFlagsAsString(ArithNodeFlags flags)
105 static const int size = 64;
106 static char description[size];
107 BoundsCheckedPointer<char> ptr(description, size);
109 bool hasPrinted = false;
111 if (flags & NodeUsedAsNumber) {
112 ptr.strcat("UsedAsNum");
116 if (flags & NodeNeedsNegZero) {
119 ptr.strcat("NeedsNegZero");
123 if (flags & NodeMayOverflow) {
126 ptr.strcat("MayOverflow");
130 if (flags & NodeMayNegZero) {
133 ptr.strcat("MayNegZero");
143 // Entries in the NodeType enum (below) are composed of an id, a result type (possibly none)
144 // and some additional informative flags (must generate, is constant, etc).
145 #define NodeIdMask 0xFFF
146 #define NodeResultMask 0xF000
147 #define NodeMustGenerate 0x10000 // set on nodes that have side effects, and may not trivially be removed by DCE.
148 #define NodeIsConstant 0x20000
149 #define NodeIsJump 0x40000
150 #define NodeIsBranch 0x80000
151 #define NodeIsTerminal 0x100000
152 #define NodeHasVarArgs 0x200000
153 #define NodeClobbersWorld 0x400000
154 #define NodeMightClobber 0x800000
156 // These values record the result type of the node (as checked by NodeResultMask, above), 0 for no result.
157 #define NodeResultJS 0x1000
158 #define NodeResultNumber 0x2000
159 #define NodeResultInt32 0x3000
160 #define NodeResultBoolean 0x4000
161 #define NodeResultStorage 0x5000
163 // This macro defines a set of information about all known node types, used to populate NodeId, NodeType below.
164 #define FOR_EACH_DFG_OP(macro) \
165 /* A constant in the CodeBlock's constant pool. */\
166 macro(JSConstant, NodeResultJS) \
168 /* A constant not in the CodeBlock's constant pool. Uses get patched to jumps that exit the */\
170 macro(WeakJSConstant, NodeResultJS) \
172 /* Nodes for handling functions (both as call and as construct). */\
173 macro(ConvertThis, NodeResultJS) \
174 macro(CreateThis, NodeResultJS) /* Note this is not MustGenerate since we're returning it anyway. */ \
175 macro(GetCallee, NodeResultJS) \
177 /* Nodes for local variable access. */\
178 macro(GetLocal, NodeResultJS) \
180 macro(Phantom, NodeMustGenerate) \
182 macro(Flush, NodeMustGenerate) \
184 /* Marker for arguments being set. */\
185 macro(SetArgument, 0) \
187 /* Hint that inlining begins here. No code is generated for this node. It's only */\
188 /* used for copying OSR data into inline frame data, to support reification of */\
189 /* call frames of inlined functions. */\
190 macro(InlineStart, 0) \
192 /* Nodes for bitwise operations. */\
193 macro(BitAnd, NodeResultInt32) \
194 macro(BitOr, NodeResultInt32) \
195 macro(BitXor, NodeResultInt32) \
196 macro(BitLShift, NodeResultInt32) \
197 macro(BitRShift, NodeResultInt32) \
198 macro(BitURShift, NodeResultInt32) \
199 /* Bitwise operators call ToInt32 on their operands. */\
200 macro(ValueToInt32, NodeResultInt32 | NodeMustGenerate) \
201 /* Used to box the result of URShift nodes (result has range 0..2^32-1). */\
202 macro(UInt32ToNumber, NodeResultNumber) \
204 /* Nodes for arithmetic operations. */\
205 macro(ArithAdd, NodeResultNumber) \
206 macro(ArithSub, NodeResultNumber) \
207 macro(ArithMul, NodeResultNumber) \
208 macro(ArithDiv, NodeResultNumber) \
209 macro(ArithMod, NodeResultNumber) \
210 macro(ArithAbs, NodeResultNumber) \
211 macro(ArithMin, NodeResultNumber) \
212 macro(ArithMax, NodeResultNumber) \
213 macro(ArithSqrt, NodeResultNumber) \
214 /* Arithmetic operators call ToNumber on their operands. */\
215 macro(ValueToNumber, NodeResultNumber | NodeMustGenerate) \
217 /* A variant of ValueToNumber, which a hint that the parents will always use this as a double. */\
218 macro(ValueToDouble, NodeResultNumber | NodeMustGenerate) \
220 /* Add of values may either be arithmetic, or result in string concatenation. */\
221 macro(ValueAdd, NodeResultJS | NodeMustGenerate | NodeMightClobber) \
223 /* Property access. */\
224 /* PutByValAlias indicates a 'put' aliases a prior write to the same property. */\
225 /* Since a put to 'length' may invalidate optimizations here, */\
226 /* this must be the directly subsequent property put. */\
227 macro(GetByVal, NodeResultJS | NodeMustGenerate | NodeMightClobber) \
228 macro(PutByVal, NodeMustGenerate | NodeClobbersWorld) \
229 macro(PutByValAlias, NodeMustGenerate | NodeClobbersWorld) \
230 macro(GetById, NodeResultJS | NodeMustGenerate | NodeClobbersWorld) \
231 macro(PutById, NodeMustGenerate | NodeClobbersWorld) \
232 macro(PutByIdDirect, NodeMustGenerate | NodeClobbersWorld) \
233 macro(CheckStructure, NodeMustGenerate) \
234 macro(PutStructure, NodeMustGenerate | NodeClobbersWorld) \
235 macro(GetPropertyStorage, NodeResultStorage) \
236 macro(GetByOffset, NodeResultJS) \
237 macro(PutByOffset, NodeMustGenerate | NodeClobbersWorld) \
238 macro(GetArrayLength, NodeResultInt32) \
239 macro(GetStringLength, NodeResultInt32) \
240 macro(GetByteArrayLength, NodeResultInt32) \
241 macro(GetScopeChain, NodeResultJS) \
242 macro(GetScopedVar, NodeResultJS | NodeMustGenerate) \
243 macro(PutScopedVar, NodeMustGenerate | NodeClobbersWorld) \
244 macro(GetGlobalVar, NodeResultJS | NodeMustGenerate) \
245 macro(PutGlobalVar, NodeMustGenerate | NodeClobbersWorld) \
246 macro(CheckFunction, NodeMustGenerate) \
248 /* Optimizations for array mutation. */\
249 macro(ArrayPush, NodeResultJS | NodeMustGenerate | NodeClobbersWorld) \
250 macro(ArrayPop, NodeResultJS | NodeMustGenerate | NodeClobbersWorld) \
252 /* Optimizations for string access */ \
253 macro(StringCharCodeAt, NodeResultInt32) \
254 macro(StringCharAt, NodeResultJS) \
256 /* Nodes for comparison operations. */\
257 macro(CompareLess, NodeResultBoolean | NodeMustGenerate | NodeMightClobber) \
258 macro(CompareLessEq, NodeResultBoolean | NodeMustGenerate | NodeMightClobber) \
259 macro(CompareGreater, NodeResultBoolean | NodeMustGenerate | NodeMightClobber) \
260 macro(CompareGreaterEq, NodeResultBoolean | NodeMustGenerate | NodeMightClobber) \
261 macro(CompareEq, NodeResultBoolean | NodeMustGenerate | NodeMightClobber) \
262 macro(CompareStrictEq, NodeResultBoolean) \
265 macro(Call, NodeResultJS | NodeMustGenerate | NodeHasVarArgs | NodeClobbersWorld) \
266 macro(Construct, NodeResultJS | NodeMustGenerate | NodeHasVarArgs | NodeClobbersWorld) \
269 macro(NewObject, NodeResultJS) \
270 macro(NewArray, NodeResultJS | NodeHasVarArgs) \
271 macro(NewArrayBuffer, NodeResultJS) \
272 macro(NewRegexp, NodeResultJS) \
274 /* Resolve nodes. */\
275 macro(Resolve, NodeResultJS | NodeMustGenerate | NodeClobbersWorld) \
276 macro(ResolveBase, NodeResultJS | NodeMustGenerate | NodeClobbersWorld) \
277 macro(ResolveBaseStrictPut, NodeResultJS | NodeMustGenerate | NodeClobbersWorld) \
278 macro(ResolveGlobal, NodeResultJS | NodeMustGenerate | NodeClobbersWorld) \
280 /* Nodes for misc operations. */\
281 macro(Breakpoint, NodeMustGenerate | NodeClobbersWorld) \
282 macro(CheckHasInstance, NodeMustGenerate) \
283 macro(InstanceOf, NodeResultBoolean) \
284 macro(LogicalNot, NodeResultBoolean | NodeMightClobber) \
285 macro(ToPrimitive, NodeResultJS | NodeMustGenerate | NodeClobbersWorld) \
286 macro(StrCat, NodeResultJS | NodeMustGenerate | NodeHasVarArgs | NodeClobbersWorld) \
288 /* Block terminals. */\
289 macro(Jump, NodeMustGenerate | NodeIsTerminal | NodeIsJump) \
290 macro(Branch, NodeMustGenerate | NodeIsTerminal | NodeIsBranch) \
291 macro(Return, NodeMustGenerate | NodeIsTerminal) \
292 macro(Throw, NodeMustGenerate | NodeIsTerminal) \
293 macro(ThrowReferenceError, NodeMustGenerate | NodeIsTerminal) \
295 /* This is a pseudo-terminal. It means that execution should fall out of DFG at */\
296 /* this point, but execution does continue in the basic block - just in a */\
297 /* different compiler. */\
298 macro(ForceOSRExit, NodeMustGenerate)
300 // This enum generates a monotonically increasing id for all Node types,
301 // and is used by the subsequent enum to fill out the id (as accessed via the NodeIdMask).
303 #define DFG_OP_ENUM(opcode, flags) opcode##_id,
304 FOR_EACH_DFG_OP(DFG_OP_ENUM)
309 // Entries in this enum describe all Node types.
310 // The enum value contains a monotonically increasing id, a result type, and additional flags.
312 #define DFG_OP_ENUM(opcode, flags) opcode = opcode##_id | (flags),
313 FOR_EACH_DFG_OP(DFG_OP_ENUM)
317 // This type used in passing an immediate argument to Node constructor;
318 // distinguishes an immediate value (typically an index into a CodeBlock data structure -
319 // a constant index, argument, or identifier) from a NodeIndex.
321 explicit OpInfo(int32_t value) : m_value(static_cast<uintptr_t>(value)) { }
322 explicit OpInfo(uint32_t value) : m_value(static_cast<uintptr_t>(value)) { }
323 #if OS(DARWIN) || USE(JSVALUE64)
324 explicit OpInfo(size_t value) : m_value(static_cast<uintptr_t>(value)) { }
326 explicit OpInfo(void* value) : m_value(reinterpret_cast<uintptr_t>(value)) { }
332 // Node represents a single operation in the data flow graph.
334 enum VarArgTag { VarArg };
336 // Construct a node with up to 3 children, no immediate value.
337 Node(NodeType op, CodeOrigin codeOrigin, NodeIndex child1 = NoNode, NodeIndex child2 = NoNode, NodeIndex child3 = NoNode)
339 , codeOrigin(codeOrigin)
340 , m_virtualRegister(InvalidVirtualRegister)
342 , m_prediction(PredictNone)
344 ASSERT(!(op & NodeHasVarArgs));
345 ASSERT(!hasArithNodeFlags());
346 children.fixed.child1 = child1;
347 children.fixed.child2 = child2;
348 children.fixed.child3 = child3;
351 // Construct a node with up to 3 children and an immediate value.
352 Node(NodeType op, CodeOrigin codeOrigin, OpInfo imm, NodeIndex child1 = NoNode, NodeIndex child2 = NoNode, NodeIndex child3 = NoNode)
354 , codeOrigin(codeOrigin)
355 , m_virtualRegister(InvalidVirtualRegister)
357 , m_opInfo(imm.m_value)
358 , m_prediction(PredictNone)
360 ASSERT(!(op & NodeHasVarArgs));
361 children.fixed.child1 = child1;
362 children.fixed.child2 = child2;
363 children.fixed.child3 = child3;
366 // Construct a node with up to 3 children and two immediate values.
367 Node(NodeType op, CodeOrigin codeOrigin, OpInfo imm1, OpInfo imm2, NodeIndex child1 = NoNode, NodeIndex child2 = NoNode, NodeIndex child3 = NoNode)
369 , codeOrigin(codeOrigin)
370 , m_virtualRegister(InvalidVirtualRegister)
372 , m_opInfo(imm1.m_value)
373 , m_opInfo2(safeCast<unsigned>(imm2.m_value))
374 , m_prediction(PredictNone)
376 ASSERT(!(op & NodeHasVarArgs));
377 children.fixed.child1 = child1;
378 children.fixed.child2 = child2;
379 children.fixed.child3 = child3;
382 // Construct a node with a variable number of children and two immediate values.
383 Node(VarArgTag, NodeType op, CodeOrigin codeOrigin, OpInfo imm1, OpInfo imm2, unsigned firstChild, unsigned numChildren)
385 , codeOrigin(codeOrigin)
386 , m_virtualRegister(InvalidVirtualRegister)
388 , m_opInfo(imm1.m_value)
389 , m_opInfo2(safeCast<unsigned>(imm2.m_value))
390 , m_prediction(PredictNone)
392 ASSERT(op & NodeHasVarArgs);
393 children.variable.firstChild = firstChild;
394 children.variable.numChildren = numChildren;
399 return op & NodeMustGenerate;
404 return op == JSConstant;
407 bool isWeakConstant()
409 return op == WeakJSConstant;
414 return isConstant() || isWeakConstant();
417 unsigned constantNumber()
419 ASSERT(isConstant());
423 JSCell* weakConstant()
425 return bitwise_cast<JSCell*>(m_opInfo);
428 JSValue valueOfJSConstant(CodeBlock* codeBlock)
430 if (op == WeakJSConstant)
431 return JSValue(weakConstant());
432 return codeBlock->constantRegister(FirstConstantRegisterIndex + constantNumber()).get();
435 bool isInt32Constant(CodeBlock* codeBlock)
437 return isConstant() && valueOfJSConstant(codeBlock).isInt32();
440 bool isDoubleConstant(CodeBlock* codeBlock)
442 bool result = isConstant() && valueOfJSConstant(codeBlock).isDouble();
444 ASSERT(!isInt32Constant(codeBlock));
448 bool isNumberConstant(CodeBlock* codeBlock)
450 bool result = isConstant() && valueOfJSConstant(codeBlock).isNumber();
451 ASSERT(result == (isInt32Constant(codeBlock) || isDoubleConstant(codeBlock)));
455 bool isBooleanConstant(CodeBlock* codeBlock)
457 return isConstant() && valueOfJSConstant(codeBlock).isBoolean();
460 bool hasVariableAccessData()
476 return hasVariableAccessData();
479 VariableAccessData* variableAccessData()
481 ASSERT(hasVariableAccessData());
482 return reinterpret_cast<VariableAccessData*>(m_opInfo)->find();
485 VirtualRegister local()
487 return variableAccessData()->local();
499 case ResolveBaseStrictPut:
507 unsigned identifierNumber()
509 ASSERT(hasIdentifier());
513 unsigned resolveGlobalDataIndex()
515 ASSERT(op == ResolveGlobal);
519 bool hasArithNodeFlags()
540 ArithNodeFlags rawArithNodeFlags()
542 ASSERT(hasArithNodeFlags());
546 // This corrects the arithmetic node flags, so that irrelevant bits are
547 // ignored. In particular, anything other than ArithMul does not need
548 // to know if it can speculate on negative zero.
549 ArithNodeFlags arithNodeFlags()
551 ArithNodeFlags result = rawArithNodeFlags();
554 return result & ~NodeNeedsNegZero;
557 ArithNodeFlags arithNodeFlagsForCompare()
559 if (hasArithNodeFlags())
560 return arithNodeFlags();
564 void setArithNodeFlag(ArithNodeFlags flags)
566 ASSERT(hasArithNodeFlags());
570 bool mergeArithNodeFlags(ArithNodeFlags flags)
572 if (!hasArithNodeFlags())
574 ArithNodeFlags newFlags = m_opInfo | flags;
575 if (newFlags == m_opInfo)
581 bool hasConstantBuffer()
583 return op == NewArrayBuffer;
586 unsigned startConstant()
588 ASSERT(hasConstantBuffer());
592 unsigned numConstants()
594 ASSERT(hasConstantBuffer());
598 bool hasRegexpIndex()
600 return op == NewRegexp;
603 unsigned regexpIndex()
605 ASSERT(hasRegexpIndex());
611 return op == GetGlobalVar || op == PutGlobalVar || op == GetScopedVar || op == PutScopedVar;
616 ASSERT(hasVarNumber());
620 bool hasScopeChainDepth()
622 return op == GetScopeChain;
625 unsigned scopeChainDepth()
627 ASSERT(hasScopeChainDepth());
633 return op & NodeResultMask;
636 bool hasInt32Result()
638 return (op & NodeResultMask) == NodeResultInt32;
641 bool hasNumberResult()
643 return (op & NodeResultMask) == NodeResultNumber;
648 return (op & NodeResultMask) == NodeResultJS;
651 bool hasBooleanResult()
653 return (op & NodeResultMask) == NodeResultBoolean;
658 return op & NodeIsJump;
663 return op & NodeIsBranch;
668 return op & NodeIsTerminal;
671 unsigned takenBytecodeOffsetDuringParsing()
673 ASSERT(isBranch() || isJump());
677 unsigned notTakenBytecodeOffsetDuringParsing()
683 void setTakenBlockIndex(BlockIndex blockIndex)
685 ASSERT(isBranch() || isJump());
686 m_opInfo = blockIndex;
689 void setNotTakenBlockIndex(BlockIndex blockIndex)
692 m_opInfo2 = blockIndex;
695 BlockIndex takenBlockIndex()
697 ASSERT(isBranch() || isJump());
701 BlockIndex notTakenBlockIndex()
707 bool hasHeapPrediction()
718 case ResolveBaseStrictPut:
728 PredictedType getHeapPrediction()
730 ASSERT(hasHeapPrediction());
731 return static_cast<PredictedType>(m_opInfo2);
734 bool predictHeap(PredictedType prediction)
736 ASSERT(hasHeapPrediction());
738 return mergePrediction(m_opInfo2, prediction);
741 bool hasFunctionCheckData()
743 return op == CheckFunction;
746 JSFunction* function()
748 ASSERT(hasFunctionCheckData());
749 return reinterpret_cast<JSFunction*>(m_opInfo);
752 bool hasStructureTransitionData()
754 return op == PutStructure;
757 StructureTransitionData& structureTransitionData()
759 ASSERT(hasStructureTransitionData());
760 return *reinterpret_cast<StructureTransitionData*>(m_opInfo);
763 bool hasStructureSet()
765 return op == CheckStructure;
768 StructureSet& structureSet()
770 ASSERT(hasStructureSet());
771 return *reinterpret_cast<StructureSet*>(m_opInfo);
774 bool hasStorageAccessData()
776 return op == GetByOffset || op == PutByOffset;
779 unsigned storageAccessDataIndex()
784 bool hasVirtualRegister()
786 return m_virtualRegister != InvalidVirtualRegister;
789 VirtualRegister virtualRegister()
792 ASSERT(m_virtualRegister != InvalidVirtualRegister);
793 return m_virtualRegister;
796 void setVirtualRegister(VirtualRegister virtualRegister)
799 ASSERT(m_virtualRegister == InvalidVirtualRegister);
800 m_virtualRegister = virtualRegister;
803 bool shouldGenerate()
805 return m_refCount && op != Phi && op != Flush;
813 // returns true when ref count passes from 0 to 1.
816 return !m_refCount++;
819 unsigned adjustedRefCount()
821 return mustGenerate() ? m_refCount - 1 : m_refCount;
824 void setRefCount(unsigned refCount)
826 m_refCount = refCount;
831 ASSERT(!(op & NodeHasVarArgs));
832 return children.fixed.child1;
835 // This is useful if you want to do a fast check on the first child
836 // before also doing a check on the opcode. Use this with care and
837 // avoid it if possible.
838 NodeIndex child1Unchecked()
840 return children.fixed.child1;
845 ASSERT(!(op & NodeHasVarArgs));
846 return children.fixed.child2;
851 ASSERT(!(op & NodeHasVarArgs));
852 return children.fixed.child3;
855 unsigned firstChild()
857 ASSERT(op & NodeHasVarArgs);
858 return children.variable.firstChild;
861 unsigned numChildren()
863 ASSERT(op & NodeHasVarArgs);
864 return children.variable.numChildren;
867 PredictedType prediction()
872 bool predict(PredictedType prediction)
874 return mergePrediction(m_prediction, prediction);
877 bool shouldSpeculateInteger()
879 return isInt32Prediction(prediction());
882 bool shouldSpeculateDouble()
884 return isDoublePrediction(prediction());
887 bool shouldSpeculateNumber()
889 return isNumberPrediction(prediction()) || prediction() == PredictNone;
892 bool shouldNotSpeculateInteger()
894 return !!(prediction() & PredictDouble);
897 bool shouldSpeculateFinalObject()
899 return isFinalObjectPrediction(prediction());
902 bool shouldSpeculateFinalObjectOrOther()
904 return isFinalObjectOrOtherPrediction(prediction());
907 bool shouldSpeculateArray()
909 return isArrayPrediction(prediction());
912 bool shouldSpeculateByteArray()
914 return !!(prediction() & PredictByteArray);
917 bool shouldSpeculateArrayOrOther()
919 return isArrayOrOtherPrediction(prediction());
922 bool shouldSpeculateObject()
924 return isObjectPrediction(prediction());
927 bool shouldSpeculateCell()
929 return isCellPrediction(prediction());
932 static bool shouldSpeculateInteger(Node& op1, Node& op2)
934 return op1.shouldSpeculateInteger() && op2.shouldSpeculateInteger();
937 static bool shouldSpeculateNumber(Node& op1, Node& op2)
939 return op1.shouldSpeculateNumber() && op2.shouldSpeculateNumber();
942 static bool shouldSpeculateFinalObject(Node& op1, Node& op2)
944 return (op1.shouldSpeculateFinalObject() && op2.shouldSpeculateObject())
945 || (op1.shouldSpeculateObject() && op2.shouldSpeculateFinalObject());
948 static bool shouldSpeculateArray(Node& op1, Node& op2)
950 return (op1.shouldSpeculateArray() && op2.shouldSpeculateObject())
951 || (op1.shouldSpeculateObject() && op2.shouldSpeculateArray());
954 bool canSpeculateInteger()
956 return nodeCanSpeculateInteger(arithNodeFlags());
960 void dumpChildren(FILE* out)
962 if (child1() == NoNode)
964 fprintf(out, "@%u", child1());
965 if (child2() == NoNode)
967 fprintf(out, ", @%u", child2());
968 if (child3() == NoNode)
970 fprintf(out, ", @%u", child3());
974 // This enum value describes the type of the node.
976 // Used to look up exception handling information (currently implemented as a bytecode index).
977 CodeOrigin codeOrigin;
978 // References to up to 3 children (0 for no child).
981 NodeIndex child1, child2, child3;
985 unsigned numChildren;
990 // The virtual register number (spill location) associated with this .
991 VirtualRegister m_virtualRegister;
992 // The number of uses of the result of this operation (+1 for 'must generate' nodes, which have side-effects).
994 // Immediate values, accesses type-checked via accessors above. The first one is
995 // big enough to store a pointer.
998 // The prediction ascribed to this node after propagation.
999 PredictedType m_prediction;
1002 } } // namespace JSC::DFG