2 * Copyright (C) 2011-2015 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.
31 #include "BasicBlockLocation.h"
32 #include "CodeBlock.h"
33 #include "DFGAbstractValue.h"
34 #include "DFGAdjacencyList.h"
35 #include "DFGArithMode.h"
36 #include "DFGArrayMode.h"
37 #include "DFGCommon.h"
39 #include "DFGLazyJSValue.h"
40 #include "DFGNodeFlags.h"
41 #include "DFGNodeOrigin.h"
42 #include "DFGNodeType.h"
43 #include "DFGObjectMaterializationData.h"
44 #include "DFGTransition.h"
45 #include "DFGUseKind.h"
46 #include "DFGVariableAccessData.h"
47 #include "GetByIdVariant.h"
48 #include "JSCJSValue.h"
50 #include "PutByIdVariant.h"
51 #include "SpeculatedType.h"
52 #include "StructureSet.h"
53 #include "TypeLocation.h"
54 #include "ValueProfile.h"
55 #include <wtf/ListDump.h>
57 namespace JSC { namespace DFG {
60 class PromotedLocationDescriptor;
63 struct StorageAccessData {
64 PropertyOffset offset;
65 unsigned identifierNumber;
68 struct MultiGetByOffsetData {
69 unsigned identifierNumber;
70 Vector<GetByIdVariant, 2> variants;
73 struct MultiPutByOffsetData {
74 unsigned identifierNumber;
75 Vector<PutByIdVariant, 2> variants;
77 bool writesStructures() const;
78 bool reallocatesStorage() const;
81 struct NewArrayBufferData {
82 unsigned startConstant;
83 unsigned numConstants;
84 IndexingType indexingType;
94 explicit BranchTarget(BasicBlock* block)
100 void setBytecodeIndex(unsigned bytecodeIndex)
102 block = bitwise_cast<BasicBlock*>(static_cast<uintptr_t>(bytecodeIndex));
104 unsigned bytecodeIndex() const { return bitwise_cast<uintptr_t>(block); }
106 void dump(PrintStream&) const;
113 static BranchData withBytecodeIndices(
114 unsigned takenBytecodeIndex, unsigned notTakenBytecodeIndex)
117 result.taken.block = bitwise_cast<BasicBlock*>(static_cast<uintptr_t>(takenBytecodeIndex));
118 result.notTaken.block = bitwise_cast<BasicBlock*>(static_cast<uintptr_t>(notTakenBytecodeIndex));
122 unsigned takenBytecodeIndex() const { return taken.bytecodeIndex(); }
123 unsigned notTakenBytecodeIndex() const { return notTaken.bytecodeIndex(); }
125 BasicBlock*& forCondition(bool condition)
129 return notTaken.block;
133 BranchTarget notTaken;
136 // The SwitchData and associated data structures duplicate the information in
137 // JumpTable. The DFG may ultimately end up using the JumpTable, though it may
138 // instead decide to do something different - this is entirely up to the DFG.
139 // These data structures give the DFG a higher-level semantic description of
140 // what is going on, which will allow it to make the right decision.
142 // Note that there will never be multiple SwitchCases in SwitchData::cases that
143 // have the same SwitchCase::value, since the bytecode's JumpTables never have
144 // duplicates - since the JumpTable maps a value to a target. It's a
145 // one-to-many mapping. So we may have duplicate targets, but never duplicate
152 SwitchCase(LazyJSValue value, BasicBlock* target)
158 static SwitchCase withBytecodeIndex(LazyJSValue value, unsigned bytecodeIndex)
161 result.value = value;
162 result.target.setBytecodeIndex(bytecodeIndex);
171 // Initializes most fields to obviously invalid values. Anyone
172 // constructing this should make sure to initialize everything they
173 // care about manually.
175 : kind(static_cast<SwitchKind>(-1))
176 , switchTableIndex(UINT_MAX)
177 , didUseJumpTable(false)
181 Vector<SwitchCase> cases;
182 BranchTarget fallThrough;
184 unsigned switchTableIndex;
185 bool didUseJumpTable;
188 struct CallVarargsData {
189 int firstVarArgOffset;
192 struct LoadVarargsData {
193 VirtualRegister start; // Local for the first element. This is the first actual argument, not this.
194 VirtualRegister count; // Local for the count.
195 VirtualRegister machineStart;
196 VirtualRegister machineCount;
197 unsigned offset; // Which array element to start with. Usually this is 0.
198 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".
199 unsigned limit; // Maximum number of elements to load. Includes "this".
202 struct StackAccessData {
208 StackAccessData(VirtualRegister local, FlushFormat format)
214 VirtualRegister local;
215 VirtualRegister machineLocal;
218 FlushedAt flushedAt() { return FlushedAt(format, machineLocal); }
221 // This type used in passing an immediate argument to Node constructor;
222 // distinguishes an immediate value (typically an index into a CodeBlock data structure -
223 // a constant index, argument, or identifier) from a Node*.
225 OpInfo() : m_value(0) { }
226 explicit OpInfo(int32_t value) : m_value(static_cast<uintptr_t>(value)) { }
227 explicit OpInfo(uint32_t value) : m_value(static_cast<uintptr_t>(value)) { }
228 #if OS(DARWIN) || USE(JSVALUE64)
229 explicit OpInfo(size_t value) : m_value(static_cast<uintptr_t>(value)) { }
231 explicit OpInfo(void* value) : m_value(reinterpret_cast<uintptr_t>(value)) { }
237 // Node represents a single operation in the data flow graph.
239 enum VarArgTag { VarArg };
243 Node(NodeType op, NodeOrigin nodeOrigin, const AdjacencyList& children)
246 , m_virtualRegister(VirtualRegister())
248 , m_prediction(SpecNone)
251 m_misc.replacement = nullptr;
252 setOpAndDefaultFlags(op);
255 // Construct a node with up to 3 children, no immediate value.
256 Node(NodeType op, NodeOrigin nodeOrigin, Edge child1 = Edge(), Edge child2 = Edge(), Edge child3 = Edge())
258 , children(AdjacencyList::Fixed, child1, child2, child3)
259 , m_virtualRegister(VirtualRegister())
261 , m_prediction(SpecNone)
266 m_misc.replacement = nullptr;
267 setOpAndDefaultFlags(op);
268 ASSERT(!(m_flags & NodeHasVarArgs));
271 // Construct a node with up to 3 children, no immediate value.
272 Node(NodeFlags result, NodeType op, NodeOrigin nodeOrigin, Edge child1 = Edge(), Edge child2 = Edge(), Edge child3 = Edge())
274 , children(AdjacencyList::Fixed, child1, child2, child3)
275 , m_virtualRegister(VirtualRegister())
277 , m_prediction(SpecNone)
282 m_misc.replacement = nullptr;
283 setOpAndDefaultFlags(op);
285 ASSERT(!(m_flags & NodeHasVarArgs));
288 // Construct a node with up to 3 children and an immediate value.
289 Node(NodeType op, NodeOrigin nodeOrigin, OpInfo imm, Edge child1 = Edge(), Edge child2 = Edge(), Edge child3 = Edge())
291 , children(AdjacencyList::Fixed, child1, child2, child3)
292 , m_virtualRegister(VirtualRegister())
294 , m_prediction(SpecNone)
295 , m_opInfo(imm.m_value)
299 m_misc.replacement = nullptr;
300 setOpAndDefaultFlags(op);
301 ASSERT(!(m_flags & NodeHasVarArgs));
304 // Construct a node with up to 3 children and an immediate value.
305 Node(NodeFlags result, NodeType op, NodeOrigin nodeOrigin, OpInfo imm, Edge child1 = Edge(), Edge child2 = Edge(), Edge child3 = Edge())
307 , children(AdjacencyList::Fixed, child1, child2, child3)
308 , m_virtualRegister(VirtualRegister())
310 , m_prediction(SpecNone)
311 , m_opInfo(imm.m_value)
315 m_misc.replacement = nullptr;
316 setOpAndDefaultFlags(op);
318 ASSERT(!(m_flags & NodeHasVarArgs));
321 // Construct a node with up to 3 children and two immediate values.
322 Node(NodeType op, NodeOrigin nodeOrigin, OpInfo imm1, OpInfo imm2, Edge child1 = Edge(), Edge child2 = Edge(), Edge child3 = Edge())
324 , children(AdjacencyList::Fixed, child1, child2, child3)
325 , m_virtualRegister(VirtualRegister())
327 , m_prediction(SpecNone)
328 , m_opInfo(imm1.m_value)
329 , m_opInfo2(imm2.m_value)
332 m_misc.replacement = nullptr;
333 setOpAndDefaultFlags(op);
334 ASSERT(!(m_flags & NodeHasVarArgs));
337 // Construct a node with a variable number of children and two immediate values.
338 Node(VarArgTag, NodeType op, NodeOrigin nodeOrigin, OpInfo imm1, OpInfo imm2, unsigned firstChild, unsigned numChildren)
340 , children(AdjacencyList::Variable, firstChild, numChildren)
341 , m_virtualRegister(VirtualRegister())
343 , m_prediction(SpecNone)
344 , m_opInfo(imm1.m_value)
345 , m_opInfo2(imm2.m_value)
348 m_misc.replacement = nullptr;
349 setOpAndDefaultFlags(op);
350 ASSERT(m_flags & NodeHasVarArgs);
353 NodeType op() const { return static_cast<NodeType>(m_op); }
354 NodeFlags flags() const { return m_flags; }
356 // This is not a fast method.
357 unsigned index() const;
359 void setOp(NodeType op)
364 void setFlags(NodeFlags flags)
369 bool mergeFlags(NodeFlags flags)
371 NodeFlags newFlags = m_flags | flags;
372 if (newFlags == m_flags)
378 bool filterFlags(NodeFlags flags)
380 NodeFlags newFlags = m_flags & flags;
381 if (newFlags == m_flags)
387 bool clearFlags(NodeFlags flags)
389 return filterFlags(~flags);
392 void setResult(NodeFlags result)
394 ASSERT(!(result & ~NodeResultMask));
395 clearFlags(NodeResultMask);
399 NodeFlags result() const
401 return flags() & NodeResultMask;
404 void setOpAndDefaultFlags(NodeType op)
407 m_flags = defaultFlags(op);
412 void convertToCheckStructure(StructureSet* set)
414 setOpAndDefaultFlags(CheckStructure);
415 m_opInfo = bitwise_cast<uintptr_t>(set);
418 void convertToCheckStructureImmediate(Node* structure)
420 ASSERT(op() == CheckStructure);
421 m_op = CheckStructureImmediate;
422 children.setChild1(Edge(structure, CellUse));
425 void replaceWith(Node* other)
428 setReplacement(other);
431 void convertToIdentity();
432 void convertToIdentityOn(Node*);
436 return m_flags & NodeMustGenerate;
459 case PhantomDirectArguments:
460 case PhantomClonedArguments:
461 // These pretend to be the empty value constant for the benefit of the DFG backend, which
462 // otherwise wouldn't take kindly to a node that doesn't compute a value.
470 FrozenValue* constant()
472 ASSERT(hasConstant());
474 if (op() == PhantomDirectArguments || op() == PhantomClonedArguments) {
475 // These pretend to be the empty value constant for the benefit of the DFG backend, which
476 // otherwise wouldn't take kindly to a node that doesn't compute a value.
477 return FrozenValue::emptySingleton();
480 return bitwise_cast<FrozenValue*>(m_opInfo);
483 // Don't call this directly - use Graph::convertToConstant() instead!
484 void convertToConstant(FrozenValue* value)
486 if (hasDoubleResult())
487 m_op = DoubleConstant;
488 else if (hasInt52Result())
489 m_op = Int52Constant;
492 m_flags &= ~NodeMustGenerate;
493 m_opInfo = bitwise_cast<uintptr_t>(value);
497 void convertToConstantStoragePointer(void* pointer)
499 ASSERT(op() == GetIndexedPropertyStorage);
500 m_op = ConstantStoragePointer;
501 m_opInfo = bitwise_cast<uintptr_t>(pointer);
505 void convertToGetLocalUnlinked(VirtualRegister local)
507 m_op = GetLocalUnlinked;
508 m_flags &= ~NodeMustGenerate;
509 m_opInfo = local.offset();
510 m_opInfo2 = VirtualRegister().offset();
514 void convertToPutStack(StackAccessData* data)
517 m_flags |= NodeMustGenerate;
518 m_opInfo = bitwise_cast<uintptr_t>(data);
522 void convertToGetStack(StackAccessData* data)
525 m_flags &= ~NodeMustGenerate;
526 m_opInfo = bitwise_cast<uintptr_t>(data);
531 void convertToGetByOffset(StorageAccessData& data, Edge storage)
533 ASSERT(m_op == GetById || m_op == GetByIdFlush || m_op == MultiGetByOffset);
534 m_opInfo = bitwise_cast<uintptr_t>(&data);
535 children.setChild2(children.child1());
536 children.child2().setUseKind(KnownCellUse);
537 children.setChild1(storage);
539 m_flags &= ~NodeMustGenerate;
542 void convertToMultiGetByOffset(MultiGetByOffsetData* data)
544 ASSERT(m_op == GetById || m_op == GetByIdFlush);
545 m_opInfo = bitwise_cast<intptr_t>(data);
546 child1().setUseKind(CellUse);
547 m_op = MultiGetByOffset;
548 ASSERT(m_flags & NodeMustGenerate);
551 void convertToPutByOffset(StorageAccessData& data, Edge storage)
553 ASSERT(m_op == PutById || m_op == PutByIdDirect || m_op == PutByIdFlush || m_op == MultiPutByOffset);
554 m_opInfo = bitwise_cast<uintptr_t>(&data);
555 children.setChild3(children.child2());
556 children.setChild2(children.child1());
557 children.setChild1(storage);
561 void convertToMultiPutByOffset(MultiPutByOffsetData* data)
563 ASSERT(m_op == PutById || m_op == PutByIdDirect || m_op == PutByIdFlush);
564 m_opInfo = bitwise_cast<intptr_t>(data);
565 m_op = MultiPutByOffset;
568 void convertToPutHint(const PromotedLocationDescriptor&, Node* base, Node* value);
570 void convertToPutByOffsetHint();
571 void convertToPutStructureHint(Node* structure);
572 void convertToPutClosureVarHint();
574 void convertToPhantomNewObject()
576 ASSERT(m_op == NewObject || m_op == MaterializeNewObject);
577 m_op = PhantomNewObject;
578 m_flags &= ~NodeHasVarArgs;
579 m_flags |= NodeMustGenerate;
582 children = AdjacencyList();
585 void convertToPhantomNewFunction()
587 ASSERT(m_op == NewFunction);
588 m_op = PhantomNewFunction;
589 m_flags |= NodeMustGenerate;
592 children = AdjacencyList();
595 void convertToPhantomCreateActivation()
597 ASSERT(m_op == CreateActivation || m_op == MaterializeCreateActivation);
598 m_op = PhantomCreateActivation;
599 m_flags &= ~NodeHasVarArgs;
600 m_flags |= NodeMustGenerate;
603 children = AdjacencyList();
606 void convertPhantomToPhantomLocal()
608 ASSERT(m_op == Phantom && (child1()->op() == Phi || child1()->op() == SetLocal || child1()->op() == SetArgument));
610 m_opInfo = child1()->m_opInfo; // Copy the variableAccessData.
611 children.setChild1(Edge());
614 void convertFlushToPhantomLocal()
616 ASSERT(m_op == Flush);
618 children = AdjacencyList();
621 void convertToGetLocal(VariableAccessData* variable, Node* phi)
623 ASSERT(m_op == GetLocalUnlinked);
625 m_opInfo = bitwise_cast<uintptr_t>(variable);
627 children.setChild1(Edge(phi));
630 void convertToToString()
632 ASSERT(m_op == ToPrimitive);
636 void convertToArithSqrt()
638 ASSERT(m_op == ArithPow);
645 return constant()->value();
648 bool isInt32Constant()
650 return isConstant() && constant()->value().isInt32();
655 return asJSValue().asInt32();
663 bool isDoubleConstant()
665 return isConstant() && constant()->value().isDouble();
668 bool isNumberConstant()
670 return isConstant() && constant()->value().isNumber();
675 return asJSValue().asNumber();
678 bool isMachineIntConstant()
680 return isConstant() && constant()->value().isMachineInt();
683 int64_t asMachineInt()
685 return asJSValue().asMachineInt();
688 bool isBooleanConstant()
690 return isConstant() && constant()->value().isBoolean();
695 return constant()->value().asBoolean();
698 bool isCellConstant()
700 return isConstant() && constant()->value() && constant()->value().isCell();
705 return constant()->value().asCell();
709 T dynamicCastConstant()
711 if (!isCellConstant())
713 return jsDynamicCast<T>(asCell());
719 T result = dynamicCastConstant<T>();
720 RELEASE_ASSERT(result);
724 bool containsMovHint()
735 bool hasVariableAccessData(Graph&);
736 bool hasLocal(Graph& graph)
738 return hasVariableAccessData(graph);
741 // This is useful for debugging code, where a node that should have a variable
742 // access data doesn't have one because it hasn't been initialized yet.
743 VariableAccessData* tryGetVariableAccessData()
745 VariableAccessData* result = reinterpret_cast<VariableAccessData*>(m_opInfo);
748 return result->find();
751 VariableAccessData* variableAccessData()
753 return reinterpret_cast<VariableAccessData*>(m_opInfo)->find();
756 VirtualRegister local()
758 return variableAccessData()->local();
761 VirtualRegister machineLocal()
763 return variableAccessData()->machineLocal();
766 bool hasUnlinkedLocal()
769 case GetLocalUnlinked:
770 case ExtractOSREntryLocal:
780 VirtualRegister unlinkedLocal()
782 ASSERT(hasUnlinkedLocal());
783 return static_cast<VirtualRegister>(m_opInfo);
786 bool hasUnlinkedMachineLocal()
788 return op() == GetLocalUnlinked;
791 void setUnlinkedMachineLocal(VirtualRegister reg)
793 ASSERT(hasUnlinkedMachineLocal());
794 m_opInfo2 = reg.offset();
797 VirtualRegister unlinkedMachineLocal()
799 ASSERT(hasUnlinkedMachineLocal());
800 return VirtualRegister(m_opInfo2);
803 bool hasStackAccessData()
814 StackAccessData* stackAccessData()
816 ASSERT(hasStackAccessData());
817 return bitwise_cast<StackAccessData*>(m_opInfo);
822 return op() == Upsilon;
828 return bitwise_cast<Node*>(m_opInfo);
831 bool isStoreBarrier()
833 return op() == StoreBarrier;
850 unsigned identifierNumber()
852 ASSERT(hasIdentifier());
856 bool hasPromotedLocationDescriptor()
858 return op() == PutHint;
861 PromotedLocationDescriptor promotedLocationDescriptor();
863 // This corrects the arithmetic node flags, so that irrelevant bits are
864 // ignored. In particular, anything other than ArithMul does not need
865 // to know if it can speculate on negative zero.
866 NodeFlags arithNodeFlags()
868 NodeFlags result = m_flags & NodeArithFlagsMask;
869 if (op() == ArithMul || op() == ArithDiv || op() == ArithMod || op() == ArithNegate || op() == ArithPow || op() == ArithRound || op() == DoubleAsInt32)
871 return result & ~NodeBytecodeNeedsNegZero;
874 bool hasConstantBuffer()
876 return op() == NewArrayBuffer;
879 NewArrayBufferData* newArrayBufferData()
881 ASSERT(hasConstantBuffer());
882 return reinterpret_cast<NewArrayBufferData*>(m_opInfo);
885 unsigned startConstant()
887 return newArrayBufferData()->startConstant;
890 unsigned numConstants()
892 return newArrayBufferData()->numConstants;
895 bool hasIndexingType()
899 case NewArrayWithSize:
907 IndexingType indexingType()
909 ASSERT(hasIndexingType());
910 if (op() == NewArrayBuffer)
911 return newArrayBufferData()->indexingType;
915 bool hasTypedArrayType()
925 TypedArrayType typedArrayType()
927 ASSERT(hasTypedArrayType());
928 TypedArrayType result = static_cast<TypedArrayType>(m_opInfo);
929 ASSERT(isTypedView(result));
933 bool hasInlineCapacity()
935 return op() == CreateThis;
938 unsigned inlineCapacity()
940 ASSERT(hasInlineCapacity());
944 void setIndexingType(IndexingType indexingType)
946 ASSERT(hasIndexingType());
947 m_opInfo = indexingType;
950 bool hasRegexpIndex()
952 return op() == NewRegexp;
955 unsigned regexpIndex()
957 ASSERT(hasRegexpIndex());
961 bool hasScopeOffset()
963 return op() == GetClosureVar || op() == PutClosureVar;
966 ScopeOffset scopeOffset()
968 ASSERT(hasScopeOffset());
969 return ScopeOffset(m_opInfo);
972 bool hasDirectArgumentsOffset()
974 return op() == GetFromArguments || op() == PutToArguments;
977 DirectArgumentsOffset capturedArgumentsOffset()
979 ASSERT(hasDirectArgumentsOffset());
980 return DirectArgumentsOffset(m_opInfo);
983 bool hasRegisterPointer()
985 return op() == GetGlobalVar || op() == PutGlobalVar;
988 WriteBarrier<Unknown>* variablePointer()
990 return bitwise_cast<WriteBarrier<Unknown>*>(m_opInfo);
993 bool hasCallVarargsData()
997 case CallForwardVarargs:
998 case ConstructVarargs:
999 case ConstructForwardVarargs:
1006 CallVarargsData* callVarargsData()
1008 ASSERT(hasCallVarargsData());
1009 return bitwise_cast<CallVarargsData*>(m_opInfo);
1012 bool hasLoadVarargsData()
1014 return op() == LoadVarargs || op() == ForwardVarargs;
1017 LoadVarargsData* loadVarargsData()
1019 ASSERT(hasLoadVarargsData());
1020 return bitwise_cast<LoadVarargsData*>(m_opInfo);
1028 bool hasInt32Result()
1030 return result() == NodeResultInt32;
1033 bool hasInt52Result()
1035 return result() == NodeResultInt52;
1038 bool hasNumberResult()
1040 return result() == NodeResultNumber;
1043 bool hasDoubleResult()
1045 return result() == NodeResultDouble;
1050 return result() == NodeResultJS;
1053 bool hasBooleanResult()
1055 return result() == NodeResultBoolean;
1058 bool hasStorageResult()
1060 return result() == NodeResultStorage;
1063 UseKind defaultUseKind()
1065 return useKindForResult(result());
1070 return Edge(this, defaultUseKind());
1075 return op() == Jump;
1080 return op() == Branch;
1085 return op() == Switch;
1102 unsigned targetBytecodeOffsetDuringParsing()
1108 BasicBlock*& targetBlock()
1111 return *bitwise_cast<BasicBlock**>(&m_opInfo);
1114 BranchData* branchData()
1117 return bitwise_cast<BranchData*>(m_opInfo);
1120 SwitchData* switchData()
1123 return bitwise_cast<SwitchData*>(m_opInfo);
1126 unsigned numSuccessors()
1134 return switchData()->cases.size() + 1;
1140 BasicBlock*& successor(unsigned index)
1143 if (index < switchData()->cases.size())
1144 return switchData()->cases[index].target.block;
1145 RELEASE_ASSERT(index == switchData()->cases.size());
1146 return switchData()->fallThrough.block;
1151 return targetBlock();
1152 return branchData()->taken.block;
1154 return branchData()->notTaken.block;
1156 RELEASE_ASSERT_NOT_REACHED();
1157 return targetBlock();
1161 class SuccessorsIterable {
1163 SuccessorsIterable()
1164 : m_terminal(nullptr)
1168 SuccessorsIterable(Node* terminal)
1169 : m_terminal(terminal)
1176 : m_terminal(nullptr)
1181 iterator(Node* terminal, unsigned index)
1182 : m_terminal(terminal)
1187 BasicBlock* operator*()
1189 return m_terminal->successor(m_index);
1192 iterator& operator++()
1198 bool operator==(const iterator& other) const
1200 return m_index == other.m_index;
1203 bool operator!=(const iterator& other) const
1205 return !(*this == other);
1214 return iterator(m_terminal, 0);
1219 return iterator(m_terminal, m_terminal->numSuccessors());
1226 SuccessorsIterable successors()
1228 return SuccessorsIterable(this);
1231 BasicBlock*& successorForCondition(bool condition)
1233 return branchData()->forCondition(condition);
1236 bool hasHeapPrediction()
1240 case GetDirectPname:
1247 case ConstructVarargs:
1248 case CallForwardVarargs:
1250 case NativeConstruct:
1252 case MultiGetByOffset:
1254 case GetFromArguments:
1266 SpeculatedType getHeapPrediction()
1268 ASSERT(hasHeapPrediction());
1269 return static_cast<SpeculatedType>(m_opInfo2);
1272 void setHeapPrediction(SpeculatedType prediction)
1274 ASSERT(hasHeapPrediction());
1275 m_opInfo2 = prediction;
1278 bool hasCellOperand()
1282 case NativeConstruct:
1285 case CreateActivation:
1286 case MaterializeCreateActivation:
1293 FrozenValue* cellOperand()
1295 ASSERT(hasCellOperand());
1296 return reinterpret_cast<FrozenValue*>(m_opInfo);
1299 template<typename T>
1302 return cellOperand()->cast<T>();
1305 void setCellOperand(FrozenValue* value)
1307 ASSERT(hasCellOperand());
1308 m_opInfo = bitwise_cast<uintptr_t>(value);
1311 bool hasWatchpointSet()
1313 return op() == NotifyWrite;
1316 WatchpointSet* watchpointSet()
1318 ASSERT(hasWatchpointSet());
1319 return reinterpret_cast<WatchpointSet*>(m_opInfo);
1322 bool hasStoragePointer()
1324 return op() == ConstantStoragePointer;
1327 void* storagePointer()
1329 ASSERT(hasStoragePointer());
1330 return reinterpret_cast<void*>(m_opInfo);
1333 bool hasTransition()
1337 case AllocatePropertyStorage:
1338 case ReallocatePropertyStorage:
1345 Transition* transition()
1347 ASSERT(hasTransition());
1348 return reinterpret_cast<Transition*>(m_opInfo);
1351 bool hasStructureSet()
1354 case CheckStructure:
1355 case CheckStructureImmediate:
1356 case MaterializeNewObject:
1363 StructureSet& structureSet()
1365 ASSERT(hasStructureSet());
1366 return *reinterpret_cast<StructureSet*>(m_opInfo);
1372 case ArrayifyToStructure:
1374 case NewStringObject:
1381 Structure* structure()
1383 ASSERT(hasStructure());
1384 return reinterpret_cast<Structure*>(m_opInfo);
1387 bool hasStorageAccessData()
1392 case GetGetterSetterByOffset:
1399 StorageAccessData& storageAccessData()
1401 ASSERT(hasStorageAccessData());
1402 return *bitwise_cast<StorageAccessData*>(m_opInfo);
1405 bool hasMultiGetByOffsetData()
1407 return op() == MultiGetByOffset;
1410 MultiGetByOffsetData& multiGetByOffsetData()
1412 ASSERT(hasMultiGetByOffsetData());
1413 return *reinterpret_cast<MultiGetByOffsetData*>(m_opInfo);
1416 bool hasMultiPutByOffsetData()
1418 return op() == MultiPutByOffset;
1421 MultiPutByOffsetData& multiPutByOffsetData()
1423 ASSERT(hasMultiPutByOffsetData());
1424 return *reinterpret_cast<MultiPutByOffsetData*>(m_opInfo);
1427 bool hasObjectMaterializationData()
1430 case MaterializeNewObject:
1431 case MaterializeCreateActivation:
1439 ObjectMaterializationData& objectMaterializationData()
1441 ASSERT(hasObjectMaterializationData());
1442 return *reinterpret_cast<ObjectMaterializationData*>(m_opInfo2);
1445 bool isObjectAllocation()
1449 case MaterializeNewObject:
1456 bool isPhantomObjectAllocation()
1459 case PhantomNewObject:
1466 bool isActivationAllocation()
1469 case CreateActivation:
1470 case MaterializeCreateActivation:
1477 bool isPhantomActivationAllocation()
1480 case PhantomCreateActivation:
1487 bool isFunctionAllocation()
1497 bool isPhantomFunctionAllocation()
1500 case PhantomNewFunction:
1507 bool isPhantomAllocation()
1510 case PhantomNewObject:
1511 case PhantomDirectArguments:
1512 case PhantomClonedArguments:
1513 case PhantomNewFunction:
1514 case PhantomCreateActivation:
1524 case GetIndexedPropertyStorage:
1525 case GetArrayLength:
1526 case PutByValDirect:
1531 case StringCharCodeAt:
1534 case ArrayifyToStructure:
1537 case HasIndexedProperty:
1544 ArrayMode arrayMode()
1546 ASSERT(hasArrayMode());
1547 if (op() == ArrayifyToStructure)
1548 return ArrayMode::fromWord(m_opInfo2);
1549 return ArrayMode::fromWord(m_opInfo);
1552 bool setArrayMode(ArrayMode arrayMode)
1554 ASSERT(hasArrayMode());
1555 if (this->arrayMode() == arrayMode)
1557 m_opInfo = arrayMode.asWord();
1570 case UInt32ToNumber:
1578 Arith::Mode arithMode()
1580 ASSERT(hasArithMode());
1581 return static_cast<Arith::Mode>(m_opInfo);
1584 void setArithMode(Arith::Mode mode)
1589 bool hasArithRoundingMode()
1591 return op() == ArithRound;
1594 Arith::RoundingMode arithRoundingMode()
1596 ASSERT(hasArithRoundingMode());
1597 return static_cast<Arith::RoundingMode>(m_opInfo);
1600 void setArithRoundingMode(Arith::RoundingMode mode)
1602 ASSERT(hasArithRoundingMode());
1603 m_opInfo = static_cast<uintptr_t>(mode);
1606 bool hasVirtualRegister()
1608 return m_virtualRegister.isValid();
1611 VirtualRegister virtualRegister()
1613 ASSERT(hasResult());
1614 ASSERT(m_virtualRegister.isValid());
1615 return m_virtualRegister;
1618 void setVirtualRegister(VirtualRegister virtualRegister)
1620 ASSERT(hasResult());
1621 ASSERT(!m_virtualRegister.isValid());
1622 m_virtualRegister = virtualRegister;
1625 bool hasExecutionCounter()
1627 return op() == CountExecution;
1630 Profiler::ExecutionCounter* executionCounter()
1632 return bitwise_cast<Profiler::ExecutionCounter*>(m_opInfo);
1635 bool shouldGenerate()
1640 bool isSemanticallySkippable()
1642 return op() == CountExecution;
1650 unsigned postfixRef()
1652 return m_refCount++;
1655 unsigned adjustedRefCount()
1657 return mustGenerate() ? m_refCount - 1 : m_refCount;
1660 void setRefCount(unsigned refCount)
1662 m_refCount = refCount;
1667 ASSERT(!(m_flags & NodeHasVarArgs));
1668 return children.child1();
1671 // This is useful if you want to do a fast check on the first child
1672 // before also doing a check on the opcode. Use this with care and
1673 // avoid it if possible.
1674 Edge child1Unchecked()
1676 return children.child1Unchecked();
1681 ASSERT(!(m_flags & NodeHasVarArgs));
1682 return children.child2();
1687 ASSERT(!(m_flags & NodeHasVarArgs));
1688 return children.child3();
1691 unsigned firstChild()
1693 ASSERT(m_flags & NodeHasVarArgs);
1694 return children.firstChild();
1697 unsigned numChildren()
1699 ASSERT(m_flags & NodeHasVarArgs);
1700 return children.numChildren();
1703 UseKind binaryUseKind()
1705 ASSERT(child1().useKind() == child2().useKind());
1706 return child1().useKind();
1709 bool isBinaryUseKind(UseKind left, UseKind right)
1711 return child1().useKind() == left && child2().useKind() == right;
1714 bool isBinaryUseKind(UseKind useKind)
1716 return isBinaryUseKind(useKind, useKind);
1719 Edge childFor(UseKind useKind)
1721 if (child1().useKind() == useKind)
1723 if (child2().useKind() == useKind)
1725 if (child3().useKind() == useKind)
1730 SpeculatedType prediction()
1732 return m_prediction;
1735 bool predict(SpeculatedType prediction)
1737 return mergeSpeculation(m_prediction, prediction);
1740 bool shouldSpeculateInt32()
1742 return isInt32Speculation(prediction());
1747 return !!(prediction() & SpecBoolean);
1750 bool shouldSpeculateInt32OrBoolean()
1752 return isInt32OrBooleanSpeculation(prediction());
1755 bool shouldSpeculateInt32ForArithmetic()
1757 return isInt32SpeculationForArithmetic(prediction());
1760 bool shouldSpeculateInt32OrBooleanForArithmetic()
1762 return isInt32OrBooleanSpeculationForArithmetic(prediction());
1765 bool shouldSpeculateInt32OrBooleanExpectingDefined()
1767 return isInt32OrBooleanSpeculationExpectingDefined(prediction());
1770 bool shouldSpeculateMachineInt()
1772 return isMachineIntSpeculation(prediction());
1775 bool shouldSpeculateDouble()
1777 return isDoubleSpeculation(prediction());
1780 bool shouldSpeculateDoubleReal()
1782 return isDoubleRealSpeculation(prediction());
1785 bool shouldSpeculateNumber()
1787 return isFullNumberSpeculation(prediction());
1790 bool shouldSpeculateNumberOrBoolean()
1792 return isFullNumberOrBooleanSpeculation(prediction());
1795 bool shouldSpeculateNumberOrBooleanExpectingDefined()
1797 return isFullNumberOrBooleanSpeculationExpectingDefined(prediction());
1800 bool shouldSpeculateBoolean()
1802 return isBooleanSpeculation(prediction());
1805 bool shouldSpeculateOther()
1807 return isOtherSpeculation(prediction());
1810 bool shouldSpeculateMisc()
1812 return isMiscSpeculation(prediction());
1815 bool shouldSpeculateStringIdent()
1817 return isStringIdentSpeculation(prediction());
1820 bool shouldSpeculateNotStringVar()
1822 return isNotStringVarSpeculation(prediction());
1825 bool shouldSpeculateString()
1827 return isStringSpeculation(prediction());
1830 bool shouldSpeculateStringObject()
1832 return isStringObjectSpeculation(prediction());
1835 bool shouldSpeculateStringOrStringObject()
1837 return isStringOrStringObjectSpeculation(prediction());
1840 bool shouldSpeculateFinalObject()
1842 return isFinalObjectSpeculation(prediction());
1845 bool shouldSpeculateFinalObjectOrOther()
1847 return isFinalObjectOrOtherSpeculation(prediction());
1850 bool shouldSpeculateArray()
1852 return isArraySpeculation(prediction());
1855 bool shouldSpeculateDirectArguments()
1857 return isDirectArgumentsSpeculation(prediction());
1860 bool shouldSpeculateScopedArguments()
1862 return isScopedArgumentsSpeculation(prediction());
1865 bool shouldSpeculateInt8Array()
1867 return isInt8ArraySpeculation(prediction());
1870 bool shouldSpeculateInt16Array()
1872 return isInt16ArraySpeculation(prediction());
1875 bool shouldSpeculateInt32Array()
1877 return isInt32ArraySpeculation(prediction());
1880 bool shouldSpeculateUint8Array()
1882 return isUint8ArraySpeculation(prediction());
1885 bool shouldSpeculateUint8ClampedArray()
1887 return isUint8ClampedArraySpeculation(prediction());
1890 bool shouldSpeculateUint16Array()
1892 return isUint16ArraySpeculation(prediction());
1895 bool shouldSpeculateUint32Array()
1897 return isUint32ArraySpeculation(prediction());
1900 bool shouldSpeculateFloat32Array()
1902 return isFloat32ArraySpeculation(prediction());
1905 bool shouldSpeculateFloat64Array()
1907 return isFloat64ArraySpeculation(prediction());
1910 bool shouldSpeculateArrayOrOther()
1912 return isArrayOrOtherSpeculation(prediction());
1915 bool shouldSpeculateObject()
1917 return isObjectSpeculation(prediction());
1920 bool shouldSpeculateObjectOrOther()
1922 return isObjectOrOtherSpeculation(prediction());
1925 bool shouldSpeculateCell()
1927 return isCellSpeculation(prediction());
1930 bool shouldSpeculateNotCell()
1932 return isNotCellSpeculation(prediction());
1935 static bool shouldSpeculateBoolean(Node* op1, Node* op2)
1937 return op1->shouldSpeculateBoolean() && op2->shouldSpeculateBoolean();
1940 static bool shouldSpeculateInt32(Node* op1, Node* op2)
1942 return op1->shouldSpeculateInt32() && op2->shouldSpeculateInt32();
1945 static bool shouldSpeculateInt32OrBoolean(Node* op1, Node* op2)
1947 return op1->shouldSpeculateInt32OrBoolean()
1948 && op2->shouldSpeculateInt32OrBoolean();
1951 static bool shouldSpeculateInt32OrBooleanForArithmetic(Node* op1, Node* op2)
1953 return op1->shouldSpeculateInt32OrBooleanForArithmetic()
1954 && op2->shouldSpeculateInt32OrBooleanForArithmetic();
1957 static bool shouldSpeculateInt32OrBooleanExpectingDefined(Node* op1, Node* op2)
1959 return op1->shouldSpeculateInt32OrBooleanExpectingDefined()
1960 && op2->shouldSpeculateInt32OrBooleanExpectingDefined();
1963 static bool shouldSpeculateMachineInt(Node* op1, Node* op2)
1965 return op1->shouldSpeculateMachineInt() && op2->shouldSpeculateMachineInt();
1968 static bool shouldSpeculateNumber(Node* op1, Node* op2)
1970 return op1->shouldSpeculateNumber() && op2->shouldSpeculateNumber();
1973 static bool shouldSpeculateNumberOrBoolean(Node* op1, Node* op2)
1975 return op1->shouldSpeculateNumberOrBoolean()
1976 && op2->shouldSpeculateNumberOrBoolean();
1979 static bool shouldSpeculateNumberOrBooleanExpectingDefined(Node* op1, Node* op2)
1981 return op1->shouldSpeculateNumberOrBooleanExpectingDefined()
1982 && op2->shouldSpeculateNumberOrBooleanExpectingDefined();
1985 static bool shouldSpeculateFinalObject(Node* op1, Node* op2)
1987 return op1->shouldSpeculateFinalObject() && op2->shouldSpeculateFinalObject();
1990 static bool shouldSpeculateArray(Node* op1, Node* op2)
1992 return op1->shouldSpeculateArray() && op2->shouldSpeculateArray();
1995 bool canSpeculateInt32(RareCaseProfilingSource source)
1997 return nodeCanSpeculateInt32(arithNodeFlags(), source);
2000 bool canSpeculateInt52(RareCaseProfilingSource source)
2002 return nodeCanSpeculateInt52(arithNodeFlags(), source);
2005 RareCaseProfilingSource sourceFor(PredictionPass pass)
2007 if (pass == PrimaryPass || child1()->sawBooleans() || (child2() && child2()->sawBooleans()))
2009 return AllRareCases;
2012 bool canSpeculateInt32(PredictionPass pass)
2014 return canSpeculateInt32(sourceFor(pass));
2017 bool canSpeculateInt52(PredictionPass pass)
2019 return canSpeculateInt52(sourceFor(pass));
2022 bool hasTypeLocation()
2024 return op() == ProfileType;
2027 TypeLocation* typeLocation()
2029 ASSERT(hasTypeLocation());
2030 return reinterpret_cast<TypeLocation*>(m_opInfo);
2033 bool hasBasicBlockLocation()
2035 return op() == ProfileControlFlow;
2038 BasicBlockLocation* basicBlockLocation()
2040 ASSERT(hasBasicBlockLocation());
2041 return reinterpret_cast<BasicBlockLocation*>(m_opInfo);
2044 Node* replacement() const
2046 return m_misc.replacement;
2049 void setReplacement(Node* replacement)
2051 m_misc.replacement = replacement;
2056 return Epoch::fromUnsigned(m_misc.epoch);
2059 void setEpoch(Epoch epoch)
2061 m_misc.epoch = epoch.toUnsigned();
2064 void dumpChildren(PrintStream& out)
2068 out.printf("@%u", child1()->index());
2071 out.printf(", @%u", child2()->index());
2074 out.printf(", @%u", child3()->index());
2077 // NB. This class must have a trivial destructor.
2081 // References to up to 3 children, or links to a variable length set of children.
2082 AdjacencyList children;
2085 unsigned m_op : 10; // real type is NodeType
2086 unsigned m_flags : 22;
2087 // The virtual register number (spill location) associated with this .
2088 VirtualRegister m_virtualRegister;
2089 // The number of uses of the result of this operation (+1 for 'must generate' nodes, which have side-effects).
2090 unsigned m_refCount;
2091 // The prediction ascribed to this node after propagation.
2092 SpeculatedType m_prediction;
2093 // Immediate values, accesses type-checked via accessors above. The first one is
2094 // big enough to store a pointer.
2096 uintptr_t m_opInfo2;
2099 // Fields used by various analyses.
2100 AbstractValue value;
2102 // Miscellaneous data that is usually meaningless, but can hold some analysis results
2103 // if you ask right. For example, if you do Graph::initializeNodeOwners(), Node::owner
2104 // will tell you which basic block a node belongs to. You cannot rely on this persisting
2105 // across transformations unless you do the maintenance work yourself. Other phases use
2106 // Node::replacement, but they do so manually: first you do Graph::clearReplacements()
2107 // and then you set, and use, replacement's yourself. Same thing for epoch.
2109 // Bottom line: don't use these fields unless you initialize them yourself, or by
2110 // calling some appropriate methods that initialize them the way you want. Otherwise,
2111 // these fields are meaningless.
2121 inline bool nodeComparator(Node* a, Node* b)
2123 return a->index() < b->index();
2126 template<typename T>
2127 CString nodeListDump(const T& nodeList)
2129 return sortedListDump(nodeList, nodeComparator);
2132 template<typename T>
2133 CString nodeMapDump(const T& nodeMap, DumpContext* context = 0)
2135 Vector<typename T::KeyType> keys;
2137 typename T::const_iterator iter = nodeMap.begin();
2138 iter != nodeMap.end(); ++iter)
2139 keys.append(iter->key);
2140 std::sort(keys.begin(), keys.end(), nodeComparator);
2141 StringPrintStream out;
2143 for(unsigned i = 0; i < keys.size(); ++i)
2144 out.print(comma, keys[i], "=>", inContext(nodeMap.get(keys[i]), context));
2145 return out.toCString();
2148 } } // namespace JSC::DFG
2152 void printInternal(PrintStream&, JSC::DFG::SwitchKind);
2153 void printInternal(PrintStream&, JSC::DFG::Node*);
2155 inline JSC::DFG::Node* inContext(JSC::DFG::Node* node, JSC::DumpContext*) { return node; }
2159 using WTF::inContext;