2 * Copyright (C) 2011-2016 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.
30 #include "BasicBlockLocation.h"
31 #include "CodeBlock.h"
32 #include "DFGAbstractValue.h"
33 #include "DFGAdjacencyList.h"
34 #include "DFGArithMode.h"
35 #include "DFGArrayMode.h"
36 #include "DFGCommon.h"
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"
53 #include "PutByIdVariant.h"
54 #include "SpeculatedType.h"
55 #include "StructureSet.h"
56 #include "TypeLocation.h"
57 #include "ValueProfile.h"
58 #include <type_traits>
59 #include <wtf/ListDump.h>
66 class CallDOMGetterPatchpoint;
71 class ExecutionCounter;
77 class PromotedLocationDescriptor;
80 struct StorageAccessData {
81 PropertyOffset offset;
82 unsigned identifierNumber;
84 // This needs to know the inferred type. For puts, this is necessary because we need to remember
85 // what check is needed. For gets, this is necessary because otherwise AI might forget what type is
87 InferredType::Descriptor inferredType;
90 struct MultiPutByOffsetData {
91 unsigned identifierNumber;
92 Vector<PutByIdVariant, 2> variants;
94 bool writesStructures() const;
95 bool reallocatesStorage() const;
98 struct NewArrayBufferData {
99 unsigned startConstant;
100 unsigned numConstants;
101 IndexingType indexingType;
104 struct BranchTarget {
111 explicit BranchTarget(BasicBlock* block)
117 void setBytecodeIndex(unsigned bytecodeIndex)
119 block = bitwise_cast<BasicBlock*>(static_cast<uintptr_t>(bytecodeIndex));
121 unsigned bytecodeIndex() const { return bitwise_cast<uintptr_t>(block); }
123 void dump(PrintStream&) const;
130 static BranchData withBytecodeIndices(
131 unsigned takenBytecodeIndex, unsigned notTakenBytecodeIndex)
134 result.taken.block = bitwise_cast<BasicBlock*>(static_cast<uintptr_t>(takenBytecodeIndex));
135 result.notTaken.block = bitwise_cast<BasicBlock*>(static_cast<uintptr_t>(notTakenBytecodeIndex));
139 unsigned takenBytecodeIndex() const { return taken.bytecodeIndex(); }
140 unsigned notTakenBytecodeIndex() const { return notTaken.bytecodeIndex(); }
142 BasicBlock*& forCondition(bool condition)
146 return notTaken.block;
150 BranchTarget notTaken;
153 // The SwitchData and associated data structures duplicate the information in
154 // JumpTable. The DFG may ultimately end up using the JumpTable, though it may
155 // instead decide to do something different - this is entirely up to the DFG.
156 // These data structures give the DFG a higher-level semantic description of
157 // what is going on, which will allow it to make the right decision.
159 // Note that there will never be multiple SwitchCases in SwitchData::cases that
160 // have the same SwitchCase::value, since the bytecode's JumpTables never have
161 // duplicates - since the JumpTable maps a value to a target. It's a
162 // one-to-many mapping. So we may have duplicate targets, but never duplicate
169 SwitchCase(LazyJSValue value, BasicBlock* target)
175 static SwitchCase withBytecodeIndex(LazyJSValue value, unsigned bytecodeIndex)
178 result.value = value;
179 result.target.setBytecodeIndex(bytecodeIndex);
188 // Initializes most fields to obviously invalid values. Anyone
189 // constructing this should make sure to initialize everything they
190 // care about manually.
192 : kind(static_cast<SwitchKind>(-1))
193 , switchTableIndex(UINT_MAX)
194 , didUseJumpTable(false)
198 Vector<SwitchCase> cases;
199 BranchTarget fallThrough;
201 unsigned switchTableIndex;
202 bool didUseJumpTable;
205 struct CallVarargsData {
206 int firstVarArgOffset;
209 struct LoadVarargsData {
210 VirtualRegister start; // Local for the first element. This is the first actual argument, not this.
211 VirtualRegister count; // Local for the count.
212 VirtualRegister machineStart;
213 VirtualRegister machineCount;
214 unsigned offset; // Which array element to start with. Usually this is 0.
215 unsigned mandatoryMinimum; // The number of elements on the stack that must be initialized; if the array is too short then the missing elements must get undefined. Does not include "this".
216 unsigned limit; // Maximum number of elements to load. Includes "this".
219 struct StackAccessData {
225 StackAccessData(VirtualRegister local, FlushFormat format)
231 VirtualRegister local;
232 VirtualRegister machineLocal;
235 FlushedAt flushedAt() { return FlushedAt(format, machineLocal); }
238 struct CallDOMGetterData {
239 DOMJIT::GetterSetter* domJIT { nullptr };
240 DOMJIT::CallDOMGetterPatchpoint* patchpoint { nullptr };
241 unsigned identifierNumber { 0 };
246 // Node represents a single operation in the data flow graph.
249 enum VarArgTag { VarArg };
253 Node(NodeType op, NodeOrigin nodeOrigin, const AdjacencyList& children)
256 , m_virtualRegister(VirtualRegister())
258 , m_prediction(SpecNone)
261 m_misc.replacement = nullptr;
262 setOpAndDefaultFlags(op);
265 // Construct a node with up to 3 children, no immediate value.
266 Node(NodeType op, NodeOrigin nodeOrigin, Edge child1 = Edge(), Edge child2 = Edge(), Edge child3 = Edge())
268 , children(AdjacencyList::Fixed, child1, child2, child3)
269 , m_virtualRegister(VirtualRegister())
271 , m_prediction(SpecNone)
274 m_misc.replacement = nullptr;
275 setOpAndDefaultFlags(op);
276 ASSERT(!(m_flags & NodeHasVarArgs));
279 // Construct a node with up to 3 children, no immediate value.
280 Node(NodeFlags result, NodeType op, NodeOrigin nodeOrigin, Edge child1 = Edge(), Edge child2 = Edge(), Edge child3 = Edge())
282 , children(AdjacencyList::Fixed, child1, child2, child3)
283 , m_virtualRegister(VirtualRegister())
285 , m_prediction(SpecNone)
288 m_misc.replacement = nullptr;
289 setOpAndDefaultFlags(op);
291 ASSERT(!(m_flags & NodeHasVarArgs));
294 // Construct a node with up to 3 children and an immediate value.
295 Node(NodeType op, NodeOrigin nodeOrigin, OpInfo imm, Edge child1 = Edge(), Edge child2 = Edge(), Edge child3 = Edge())
297 , children(AdjacencyList::Fixed, child1, child2, child3)
298 , m_virtualRegister(VirtualRegister())
300 , m_prediction(SpecNone)
301 , m_opInfo(imm.m_value)
304 m_misc.replacement = nullptr;
305 setOpAndDefaultFlags(op);
306 ASSERT(!(m_flags & NodeHasVarArgs));
309 // Construct a node with up to 3 children and an immediate value.
310 Node(NodeFlags result, NodeType op, NodeOrigin nodeOrigin, OpInfo imm, Edge child1 = Edge(), Edge child2 = Edge(), Edge child3 = Edge())
312 , children(AdjacencyList::Fixed, child1, child2, child3)
313 , m_virtualRegister(VirtualRegister())
315 , m_prediction(SpecNone)
316 , m_opInfo(imm.m_value)
319 m_misc.replacement = nullptr;
320 setOpAndDefaultFlags(op);
322 ASSERT(!(m_flags & NodeHasVarArgs));
325 // Construct a node with up to 3 children and two immediate values.
326 Node(NodeType op, NodeOrigin nodeOrigin, OpInfo imm1, OpInfo imm2, Edge child1 = Edge(), Edge child2 = Edge(), Edge child3 = Edge())
328 , children(AdjacencyList::Fixed, child1, child2, child3)
329 , m_virtualRegister(VirtualRegister())
331 , m_prediction(SpecNone)
332 , m_opInfo(imm1.m_value)
333 , m_opInfo2(imm2.m_value)
336 m_misc.replacement = nullptr;
337 setOpAndDefaultFlags(op);
338 ASSERT(!(m_flags & NodeHasVarArgs));
341 // Construct a node with a variable number of children and two immediate values.
342 Node(VarArgTag, NodeType op, NodeOrigin nodeOrigin, OpInfo imm1, OpInfo imm2, unsigned firstChild, unsigned numChildren)
344 , children(AdjacencyList::Variable, firstChild, numChildren)
345 , m_virtualRegister(VirtualRegister())
347 , m_prediction(SpecNone)
348 , m_opInfo(imm1.m_value)
349 , m_opInfo2(imm2.m_value)
352 m_misc.replacement = nullptr;
353 setOpAndDefaultFlags(op);
354 ASSERT(m_flags & NodeHasVarArgs);
357 NodeType op() const { return static_cast<NodeType>(m_op); }
358 NodeFlags flags() const { return m_flags; }
360 unsigned index() const { return m_index; }
362 void setOp(NodeType op)
367 void setFlags(NodeFlags flags)
372 bool mergeFlags(NodeFlags flags)
374 NodeFlags newFlags = m_flags | flags;
375 if (newFlags == m_flags)
381 bool filterFlags(NodeFlags flags)
383 NodeFlags newFlags = m_flags & flags;
384 if (newFlags == m_flags)
390 bool clearFlags(NodeFlags flags)
392 return filterFlags(~flags);
395 void setResult(NodeFlags result)
397 ASSERT(!(result & ~NodeResultMask));
398 clearFlags(NodeResultMask);
402 NodeFlags result() const
404 return flags() & NodeResultMask;
407 void setOpAndDefaultFlags(NodeType op)
410 m_flags = defaultFlags(op);
415 void convertToCheckStructure(RegisteredStructureSet* set)
417 setOpAndDefaultFlags(CheckStructure);
421 void convertToCheckStructureImmediate(Node* structure)
423 ASSERT(op() == CheckStructure);
424 m_op = CheckStructureImmediate;
425 children.setChild1(Edge(structure, CellUse));
428 void replaceWith(Node* other)
431 setReplacement(other);
434 void convertToIdentity();
435 void convertToIdentityOn(Node*);
439 return m_flags & NodeMustGenerate;
462 case PhantomDirectArguments:
463 case PhantomClonedArguments:
464 // These pretend to be the empty value constant for the benefit of the DFG backend, which
465 // otherwise wouldn't take kindly to a node that doesn't compute a value.
473 FrozenValue* constant()
475 ASSERT(hasConstant());
477 if (op() == PhantomDirectArguments || op() == PhantomClonedArguments) {
478 // These pretend to be the empty value constant for the benefit of the DFG backend, which
479 // otherwise wouldn't take kindly to a node that doesn't compute a value.
480 return FrozenValue::emptySingleton();
483 return m_opInfo.as<FrozenValue*>();
486 // Don't call this directly - use Graph::convertToConstant() instead!
487 void convertToConstant(FrozenValue* value)
489 if (hasDoubleResult())
490 m_op = DoubleConstant;
491 else if (hasInt52Result())
492 m_op = Int52Constant;
495 m_flags &= ~NodeMustGenerate;
500 void convertToLazyJSConstant(Graph&, LazyJSValue);
502 void convertToConstantStoragePointer(void* pointer)
504 ASSERT(op() == GetIndexedPropertyStorage);
505 m_op = ConstantStoragePointer;
510 void convertToGetLocalUnlinked(VirtualRegister local)
512 m_op = GetLocalUnlinked;
513 m_flags &= ~NodeMustGenerate;
514 m_opInfo = local.offset();
515 m_opInfo2 = VirtualRegister().offset();
519 void convertToPutStack(StackAccessData* data)
522 m_flags |= NodeMustGenerate;
524 m_opInfo2 = OpInfoWrapper();
527 void convertToGetStack(StackAccessData* data)
530 m_flags &= ~NodeMustGenerate;
532 m_opInfo2 = OpInfoWrapper();
536 void convertToGetByOffset(StorageAccessData& data, Edge storage, Edge base)
538 ASSERT(m_op == GetById || m_op == GetByIdFlush || m_op == MultiGetByOffset);
540 children.setChild1(storage);
541 children.setChild2(base);
543 m_flags &= ~NodeMustGenerate;
546 void convertToMultiGetByOffset(MultiGetByOffsetData* data)
548 ASSERT(m_op == GetById || m_op == GetByIdFlush);
550 child1().setUseKind(CellUse);
551 m_op = MultiGetByOffset;
552 ASSERT(m_flags & NodeMustGenerate);
555 void convertToPutByOffset(StorageAccessData& data, Edge storage, Edge base)
557 ASSERT(m_op == PutById || m_op == PutByIdDirect || m_op == PutByIdFlush || m_op == MultiPutByOffset);
559 children.setChild3(children.child2());
560 children.setChild2(base);
561 children.setChild1(storage);
565 void convertToMultiPutByOffset(MultiPutByOffsetData* data)
567 ASSERT(m_op == PutById || m_op == PutByIdDirect || m_op == PutByIdFlush);
569 m_op = MultiPutByOffset;
572 void convertToPutHint(const PromotedLocationDescriptor&, Node* base, Node* value);
574 void convertToPutByOffsetHint();
575 void convertToPutStructureHint(Node* structure);
576 void convertToPutClosureVarHint();
578 void convertToPhantomNewObject()
580 ASSERT(m_op == NewObject || m_op == MaterializeNewObject);
581 m_op = PhantomNewObject;
582 m_flags &= ~NodeHasVarArgs;
583 m_flags |= NodeMustGenerate;
584 m_opInfo = OpInfoWrapper();
585 m_opInfo2 = OpInfoWrapper();
586 children = AdjacencyList();
589 void convertToPhantomNewFunction()
591 ASSERT(m_op == NewFunction || m_op == NewGeneratorFunction || m_op == NewAsyncFunction);
592 m_op = PhantomNewFunction;
593 m_flags |= NodeMustGenerate;
594 m_opInfo = OpInfoWrapper();
595 m_opInfo2 = OpInfoWrapper();
596 children = AdjacencyList();
599 void convertToPhantomNewGeneratorFunction()
601 ASSERT(m_op == NewGeneratorFunction);
602 m_op = PhantomNewGeneratorFunction;
603 m_flags |= NodeMustGenerate;
604 m_opInfo = OpInfoWrapper();
605 m_opInfo2 = OpInfoWrapper();
606 children = AdjacencyList();
609 void convertToPhantomNewAsyncFunction()
611 ASSERT(m_op == NewAsyncFunction);
612 m_op = PhantomNewAsyncFunction;
613 m_flags |= NodeMustGenerate;
614 m_opInfo = OpInfoWrapper();
615 m_opInfo2 = OpInfoWrapper();
616 children = AdjacencyList();
619 void convertToPhantomCreateActivation()
621 ASSERT(m_op == CreateActivation || m_op == MaterializeCreateActivation);
622 m_op = PhantomCreateActivation;
623 m_flags &= ~NodeHasVarArgs;
624 m_flags |= NodeMustGenerate;
625 m_opInfo = OpInfoWrapper();
626 m_opInfo2 = OpInfoWrapper();
627 children = AdjacencyList();
630 void convertPhantomToPhantomLocal()
632 ASSERT(m_op == Phantom && (child1()->op() == Phi || child1()->op() == SetLocal || child1()->op() == SetArgument));
634 m_opInfo = child1()->m_opInfo; // Copy the variableAccessData.
635 children.setChild1(Edge());
638 void convertFlushToPhantomLocal()
640 ASSERT(m_op == Flush);
642 children = AdjacencyList();
645 void convertToGetLocal(VariableAccessData* variable, Node* phi)
647 ASSERT(m_op == GetLocalUnlinked);
650 m_opInfo2 = OpInfoWrapper();
651 children.setChild1(Edge(phi));
654 void convertToToString()
656 ASSERT(m_op == ToPrimitive);
660 void convertToArithNegate()
662 ASSERT(m_op == ArithAbs && child1().useKind() == Int32Use);
666 void convertToDirectCall(FrozenValue*);
668 void convertToCallDOM(Graph&);
672 return constant()->value();
675 bool isInt32Constant()
677 return isConstant() && constant()->value().isInt32();
682 return asJSValue().asInt32();
690 bool isDoubleConstant()
692 return isConstant() && constant()->value().isDouble();
695 bool isNumberConstant()
697 return isConstant() && constant()->value().isNumber();
702 return asJSValue().asNumber();
705 bool isAnyIntConstant()
707 return isConstant() && constant()->value().isAnyInt();
712 return asJSValue().asAnyInt();
715 bool isBooleanConstant()
717 return isConstant() && constant()->value().isBoolean();
722 return constant()->value().asBoolean();
725 bool isUndefinedOrNullConstant()
727 return isConstant() && constant()->value().isUndefinedOrNull();
730 bool isCellConstant()
732 return isConstant() && constant()->value() && constant()->value().isCell();
737 return constant()->value().asCell();
741 T dynamicCastConstant(VM& vm)
743 if (!isCellConstant())
745 return jsDynamicCast<T>(vm, asCell());
749 T castConstant(VM& vm)
751 T result = dynamicCastConstant<T>(vm);
752 RELEASE_ASSERT(result);
756 bool hasLazyJSValue()
758 return op() == LazyJSConstant;
761 LazyJSValue lazyJSValue()
763 ASSERT(hasLazyJSValue());
764 return *m_opInfo.as<LazyJSValue*>();
767 String tryGetString(Graph&);
769 JSValue initializationValueForActivation() const
771 ASSERT(op() == CreateActivation);
772 return m_opInfo2.as<FrozenValue*>()->value();
775 bool hasArgumentsChild()
778 case GetMyArgumentByVal:
779 case GetMyArgumentByValOutOfBounds:
783 case CallForwardVarargs:
784 case ConstructVarargs:
785 case ConstructForwardVarargs:
786 case TailCallVarargs:
787 case TailCallForwardVarargs:
788 case TailCallVarargsInlinedCaller:
789 case TailCallForwardVarargsInlinedCaller:
796 Edge& argumentsChild()
799 case GetMyArgumentByVal:
800 case GetMyArgumentByValOutOfBounds:
805 case CallForwardVarargs:
806 case ConstructVarargs:
807 case ConstructForwardVarargs:
808 case TailCallVarargs:
809 case TailCallForwardVarargs:
810 case TailCallVarargsInlinedCaller:
811 case TailCallForwardVarargsInlinedCaller:
814 RELEASE_ASSERT_NOT_REACHED();
819 bool containsMovHint()
830 bool hasVariableAccessData(Graph&);
831 bool accessesStack(Graph& graph)
833 return hasVariableAccessData(graph);
836 // This is useful for debugging code, where a node that should have a variable
837 // access data doesn't have one because it hasn't been initialized yet.
838 VariableAccessData* tryGetVariableAccessData()
840 VariableAccessData* result = m_opInfo.as<VariableAccessData*>();
843 return result->find();
846 VariableAccessData* variableAccessData()
848 return m_opInfo.as<VariableAccessData*>()->find();
851 VirtualRegister local()
853 return variableAccessData()->local();
856 VirtualRegister machineLocal()
858 return variableAccessData()->machineLocal();
861 bool hasUnlinkedLocal()
864 case GetLocalUnlinked:
865 case ExtractOSREntryLocal:
875 VirtualRegister unlinkedLocal()
877 ASSERT(hasUnlinkedLocal());
878 return VirtualRegister(m_opInfo.as<int32_t>());
881 bool hasUnlinkedMachineLocal()
883 return op() == GetLocalUnlinked;
886 void setUnlinkedMachineLocal(VirtualRegister reg)
888 ASSERT(hasUnlinkedMachineLocal());
889 m_opInfo2 = reg.offset();
892 VirtualRegister unlinkedMachineLocal()
894 ASSERT(hasUnlinkedMachineLocal());
895 return VirtualRegister(m_opInfo2.as<int32_t>());
898 bool hasStackAccessData()
909 StackAccessData* stackAccessData()
911 ASSERT(hasStackAccessData());
912 return m_opInfo.as<StackAccessData*>();
917 return op() == Upsilon;
923 return m_opInfo.as<Node*>();
926 bool isStoreBarrier()
928 return op() == StoreBarrier || op() == FencedStoreBarrier;
937 case GetByIdWithThis:
941 case PutByIdWithThis:
944 case PutGetterSetterById:
955 unsigned identifierNumber()
957 ASSERT(hasIdentifier());
958 return m_opInfo.as<unsigned>();
972 unsigned getPutInfo()
974 ASSERT(hasGetPutInfo());
975 return m_opInfo2.as<unsigned>();
978 bool hasAccessorAttributes()
983 case PutGetterSetterById:
992 int32_t accessorAttributes()
994 ASSERT(hasAccessorAttributes());
998 case PutGetterSetterById:
999 return m_opInfo2.as<int32_t>();
1000 case PutGetterByVal:
1001 case PutSetterByVal:
1002 return m_opInfo.as<int32_t>();
1004 RELEASE_ASSERT_NOT_REACHED();
1009 bool hasPromotedLocationDescriptor()
1011 return op() == PutHint;
1014 PromotedLocationDescriptor promotedLocationDescriptor();
1016 // This corrects the arithmetic node flags, so that irrelevant bits are
1017 // ignored. In particular, anything other than ArithMul does not need
1018 // to know if it can speculate on negative zero.
1019 NodeFlags arithNodeFlags()
1021 NodeFlags result = m_flags & NodeArithFlagsMask;
1022 if (op() == ArithMul || op() == ArithDiv || op() == ArithMod || op() == ArithNegate || op() == ArithPow || op() == ArithRound || op() == ArithFloor || op() == ArithCeil || op() == ArithTrunc || op() == DoubleAsInt32)
1024 return result & ~NodeBytecodeNeedsNegZero;
1027 bool mayHaveNonIntResult()
1029 return m_flags & NodeMayHaveNonIntResult;
1032 bool mayHaveDoubleResult()
1034 return m_flags & NodeMayHaveDoubleResult;
1037 bool mayHaveNonNumberResult()
1039 return m_flags & NodeMayHaveNonNumberResult;
1042 bool hasConstantBuffer()
1044 return op() == NewArrayBuffer;
1047 NewArrayBufferData* newArrayBufferData()
1049 ASSERT(hasConstantBuffer());
1050 return m_opInfo.as<NewArrayBufferData*>();
1053 unsigned startConstant()
1055 return newArrayBufferData()->startConstant;
1058 unsigned numConstants()
1060 return newArrayBufferData()->numConstants;
1063 bool hasIndexingType()
1067 case NewArrayWithSize:
1068 case NewArrayBuffer:
1075 BitVector* bitVector()
1077 ASSERT(op() == NewArrayWithSpread || op() == PhantomNewArrayWithSpread);
1078 return m_opInfo.as<BitVector*>();
1081 // Return the indexing type that an array allocation *wants* to use. It may end up using a different
1082 // type if we're having a bad time. You can determine the actual indexing type by asking the global
1085 // m_graph.globalObjectFor(node->origin.semantic)->arrayStructureForIndexingTypeDuringAllocation(node->indexingType())
1087 // This will give you a Structure*, and that will have some indexing type that may be different from
1089 IndexingType indexingType()
1091 ASSERT(hasIndexingType());
1092 if (op() == NewArrayBuffer)
1093 return newArrayBufferData()->indexingType;
1094 return static_cast<IndexingType>(m_opInfo.as<uint32_t>());
1097 bool hasTypedArrayType()
1107 TypedArrayType typedArrayType()
1109 ASSERT(hasTypedArrayType());
1110 TypedArrayType result = static_cast<TypedArrayType>(m_opInfo.as<uint32_t>());
1111 ASSERT(isTypedView(result));
1115 bool hasInlineCapacity()
1117 return op() == CreateThis;
1120 unsigned inlineCapacity()
1122 ASSERT(hasInlineCapacity());
1123 return m_opInfo.as<unsigned>();
1126 void setIndexingType(IndexingType indexingType)
1128 ASSERT(hasIndexingType());
1129 m_opInfo = indexingType;
1132 bool hasScopeOffset()
1134 return op() == GetClosureVar || op() == PutClosureVar;
1137 ScopeOffset scopeOffset()
1139 ASSERT(hasScopeOffset());
1140 return ScopeOffset(m_opInfo.as<uint32_t>());
1143 bool hasDirectArgumentsOffset()
1145 return op() == GetFromArguments || op() == PutToArguments;
1148 DirectArgumentsOffset capturedArgumentsOffset()
1150 ASSERT(hasDirectArgumentsOffset());
1151 return DirectArgumentsOffset(m_opInfo.as<uint32_t>());
1154 bool hasRegisterPointer()
1156 return op() == GetGlobalVar || op() == GetGlobalLexicalVariable || op() == PutGlobalVariable;
1159 WriteBarrier<Unknown>* variablePointer()
1161 return m_opInfo.as<WriteBarrier<Unknown>*>();
1164 bool hasCallVarargsData()
1168 case CallForwardVarargs:
1169 case TailCallVarargs:
1170 case TailCallForwardVarargs:
1171 case TailCallVarargsInlinedCaller:
1172 case TailCallForwardVarargsInlinedCaller:
1173 case ConstructVarargs:
1174 case ConstructForwardVarargs:
1181 CallVarargsData* callVarargsData()
1183 ASSERT(hasCallVarargsData());
1184 return m_opInfo.as<CallVarargsData*>();
1187 bool hasLoadVarargsData()
1189 return op() == LoadVarargs || op() == ForwardVarargs;
1192 LoadVarargsData* loadVarargsData()
1194 ASSERT(hasLoadVarargsData());
1195 return m_opInfo.as<LoadVarargsData*>();
1198 bool hasQueriedType()
1200 return op() == IsCellWithType;
1203 JSType queriedType()
1205 static_assert(std::is_same<uint8_t, std::underlying_type<JSType>::type>::value, "Ensure that uint8_t is the underlying type for JSType.");
1206 return static_cast<JSType>(m_opInfo.as<uint32_t>());
1209 bool hasSpeculatedTypeForQuery()
1211 return op() == IsCellWithType;
1214 SpeculatedType speculatedTypeForQuery()
1216 return speculationFromJSType(queriedType());
1224 bool hasInt52Result()
1226 return result() == NodeResultInt52;
1229 bool hasNumberResult()
1231 return result() == NodeResultNumber;
1234 bool hasDoubleResult()
1236 return result() == NodeResultDouble;
1241 return result() == NodeResultJS;
1244 bool hasBooleanResult()
1246 return result() == NodeResultBoolean;
1249 bool hasStorageResult()
1251 return result() == NodeResultStorage;
1254 UseKind defaultUseKind()
1256 return useKindForResult(result());
1261 return Edge(this, defaultUseKind());
1266 return op() == Jump;
1271 return op() == Branch;
1276 return op() == Switch;
1287 case DirectTailCall:
1288 case TailCallVarargs:
1289 case TailCallForwardVarargs:
1297 bool isFunctionTerminal()
1299 if (isTerminal() && !numSuccessors())
1305 unsigned targetBytecodeOffsetDuringParsing()
1308 return m_opInfo.as<unsigned>();
1311 BasicBlock*& targetBlock()
1314 return *bitwise_cast<BasicBlock**>(&m_opInfo.u.pointer);
1317 BranchData* branchData()
1320 return m_opInfo.as<BranchData*>();
1323 SwitchData* switchData()
1326 return m_opInfo.as<SwitchData*>();
1329 unsigned numSuccessors()
1337 return switchData()->cases.size() + 1;
1343 BasicBlock*& successor(unsigned index)
1346 if (index < switchData()->cases.size())
1347 return switchData()->cases[index].target.block;
1348 RELEASE_ASSERT(index == switchData()->cases.size());
1349 return switchData()->fallThrough.block;
1354 return targetBlock();
1355 return branchData()->taken.block;
1357 return branchData()->notTaken.block;
1359 RELEASE_ASSERT_NOT_REACHED();
1360 return targetBlock();
1364 class SuccessorsIterable {
1366 SuccessorsIterable()
1367 : m_terminal(nullptr)
1371 SuccessorsIterable(Node* terminal)
1372 : m_terminal(terminal)
1379 : m_terminal(nullptr)
1384 iterator(Node* terminal, unsigned index)
1385 : m_terminal(terminal)
1390 BasicBlock* operator*()
1392 return m_terminal->successor(m_index);
1395 iterator& operator++()
1401 bool operator==(const iterator& other) const
1403 return m_index == other.m_index;
1406 bool operator!=(const iterator& other) const
1408 return !(*this == other);
1417 return iterator(m_terminal, 0);
1422 return iterator(m_terminal, m_terminal->numSuccessors());
1425 size_t size() const { return m_terminal->numSuccessors(); }
1426 BasicBlock* at(size_t index) const { return m_terminal->successor(index); }
1427 BasicBlock* operator[](size_t index) const { return at(index); }
1433 SuccessorsIterable successors()
1435 return SuccessorsIterable(this);
1438 BasicBlock*& successorForCondition(bool condition)
1440 return branchData()->forCondition(condition);
1443 bool hasHeapPrediction()
1451 case GetDirectPname:
1454 case GetByIdWithThis:
1457 case GetByValWithThis:
1460 case TailCallInlinedCaller:
1461 case DirectTailCallInlinedCaller:
1463 case DirectConstruct:
1466 case TailCallVarargsInlinedCaller:
1467 case ConstructVarargs:
1468 case CallForwardVarargs:
1469 case TailCallForwardVarargsInlinedCaller:
1471 case MultiGetByOffset:
1473 case GetFromArguments:
1480 case GetGlobalLexicalVariable:
1482 case StringReplaceRegExp:
1484 case LoadFromJSMapBucket:
1494 SpeculatedType getHeapPrediction()
1496 ASSERT(hasHeapPrediction());
1497 return m_opInfo2.as<SpeculatedType>();
1500 void setHeapPrediction(SpeculatedType prediction)
1502 ASSERT(hasHeapPrediction());
1503 m_opInfo2 = prediction;
1506 bool hasCellOperand()
1510 case OverridesHasInstance:
1512 case NewGeneratorFunction:
1513 case NewAsyncFunction:
1514 case CreateActivation:
1515 case MaterializeCreateActivation:
1519 case DirectTailCall:
1520 case DirectConstruct:
1521 case DirectTailCallInlinedCaller:
1528 FrozenValue* cellOperand()
1530 ASSERT(hasCellOperand());
1531 return m_opInfo.as<FrozenValue*>();
1534 template<typename T>
1537 return cellOperand()->cast<T>();
1540 void setCellOperand(FrozenValue* value)
1542 ASSERT(hasCellOperand());
1546 bool hasWatchpointSet()
1548 return op() == NotifyWrite;
1551 WatchpointSet* watchpointSet()
1553 ASSERT(hasWatchpointSet());
1554 return m_opInfo.as<WatchpointSet*>();
1557 bool hasStoragePointer()
1559 return op() == ConstantStoragePointer;
1562 void* storagePointer()
1564 ASSERT(hasStoragePointer());
1565 return m_opInfo.as<void*>();
1568 bool hasUidOperand()
1570 return op() == CheckStringIdent;
1573 UniquedStringImpl* uidOperand()
1575 ASSERT(hasUidOperand());
1576 return m_opInfo.as<UniquedStringImpl*>();
1579 bool hasTypeInfoOperand()
1581 return op() == CheckTypeInfoFlags;
1584 unsigned typeInfoOperand()
1586 ASSERT(hasTypeInfoOperand() && m_opInfo.as<uint32_t>() <= static_cast<uint32_t>(UCHAR_MAX));
1587 return m_opInfo.as<uint32_t>();
1590 bool hasTransition()
1594 case AllocatePropertyStorage:
1595 case ReallocatePropertyStorage:
1602 Transition* transition()
1604 ASSERT(hasTransition());
1605 return m_opInfo.as<Transition*>();
1608 bool hasStructureSet()
1611 case CheckStructure:
1612 case CheckStructureImmediate:
1613 case MaterializeNewObject:
1620 const RegisteredStructureSet& structureSet()
1622 ASSERT(hasStructureSet());
1623 return *m_opInfo.as<RegisteredStructureSet*>();
1629 case ArrayifyToStructure:
1631 case NewStringObject:
1638 RegisteredStructure structure()
1640 ASSERT(hasStructure());
1641 return m_opInfo.asRegisteredStructure();
1644 bool hasStorageAccessData()
1649 case GetGetterSetterByOffset:
1656 StorageAccessData& storageAccessData()
1658 ASSERT(hasStorageAccessData());
1659 return *m_opInfo.as<StorageAccessData*>();
1662 bool hasMultiGetByOffsetData()
1664 return op() == MultiGetByOffset;
1667 MultiGetByOffsetData& multiGetByOffsetData()
1669 ASSERT(hasMultiGetByOffsetData());
1670 return *m_opInfo.as<MultiGetByOffsetData*>();
1673 bool hasMultiPutByOffsetData()
1675 return op() == MultiPutByOffset;
1678 MultiPutByOffsetData& multiPutByOffsetData()
1680 ASSERT(hasMultiPutByOffsetData());
1681 return *m_opInfo.as<MultiPutByOffsetData*>();
1684 bool hasObjectMaterializationData()
1687 case MaterializeNewObject:
1688 case MaterializeCreateActivation:
1696 ObjectMaterializationData& objectMaterializationData()
1698 ASSERT(hasObjectMaterializationData());
1699 return *m_opInfo2.as<ObjectMaterializationData*>();
1702 bool isObjectAllocation()
1706 case MaterializeNewObject:
1713 bool isPhantomObjectAllocation()
1716 case PhantomNewObject:
1723 bool isActivationAllocation()
1726 case CreateActivation:
1727 case MaterializeCreateActivation:
1734 bool isPhantomActivationAllocation()
1737 case PhantomCreateActivation:
1744 bool isFunctionAllocation()
1748 case NewGeneratorFunction:
1749 case NewAsyncFunction:
1756 bool isPhantomFunctionAllocation()
1759 case PhantomNewFunction:
1760 case PhantomNewGeneratorFunction:
1761 case PhantomNewAsyncFunction:
1768 bool isPhantomAllocation()
1771 case PhantomNewObject:
1772 case PhantomDirectArguments:
1773 case PhantomCreateRest:
1775 case PhantomNewArrayWithSpread:
1776 case PhantomClonedArguments:
1777 case PhantomNewFunction:
1778 case PhantomNewGeneratorFunction:
1779 case PhantomNewAsyncFunction:
1780 case PhantomCreateActivation:
1790 case GetIndexedPropertyStorage:
1791 case GetArrayLength:
1793 case PutByValDirect:
1798 case StringCharCodeAt:
1801 case ArrayifyToStructure:
1804 case HasIndexedProperty:
1811 ArrayMode arrayMode()
1813 ASSERT(hasArrayMode());
1814 if (op() == ArrayifyToStructure)
1815 return ArrayMode::fromWord(m_opInfo2.as<uint32_t>());
1816 return ArrayMode::fromWord(m_opInfo.as<uint32_t>());
1819 bool setArrayMode(ArrayMode arrayMode)
1821 ASSERT(hasArrayMode());
1822 if (this->arrayMode() == arrayMode)
1824 m_opInfo = arrayMode.asWord();
1838 case UInt32ToNumber:
1846 Arith::Mode arithMode()
1848 ASSERT(hasArithMode());
1849 return static_cast<Arith::Mode>(m_opInfo.as<uint32_t>());
1852 void setArithMode(Arith::Mode mode)
1857 bool hasArithRoundingMode()
1859 return op() == ArithRound || op() == ArithFloor || op() == ArithCeil || op() == ArithTrunc;
1862 Arith::RoundingMode arithRoundingMode()
1864 ASSERT(hasArithRoundingMode());
1865 return static_cast<Arith::RoundingMode>(m_opInfo.as<uint32_t>());
1868 void setArithRoundingMode(Arith::RoundingMode mode)
1870 ASSERT(hasArithRoundingMode());
1871 m_opInfo = static_cast<uint32_t>(mode);
1874 bool hasVirtualRegister()
1876 return m_virtualRegister.isValid();
1879 VirtualRegister virtualRegister()
1881 ASSERT(hasResult());
1882 ASSERT(m_virtualRegister.isValid());
1883 return m_virtualRegister;
1886 void setVirtualRegister(VirtualRegister virtualRegister)
1888 ASSERT(hasResult());
1889 ASSERT(!m_virtualRegister.isValid());
1890 m_virtualRegister = virtualRegister;
1893 bool hasExecutionCounter()
1895 return op() == CountExecution;
1898 Profiler::ExecutionCounter* executionCounter()
1900 return m_opInfo.as<Profiler::ExecutionCounter*>();
1903 bool shouldGenerate()
1908 bool isSemanticallySkippable()
1910 return op() == CountExecution;
1918 unsigned postfixRef()
1920 return m_refCount++;
1923 unsigned adjustedRefCount()
1925 return mustGenerate() ? m_refCount - 1 : m_refCount;
1928 void setRefCount(unsigned refCount)
1930 m_refCount = refCount;
1935 ASSERT(!(m_flags & NodeHasVarArgs));
1936 return children.child1();
1939 // This is useful if you want to do a fast check on the first child
1940 // before also doing a check on the opcode. Use this with care and
1941 // avoid it if possible.
1942 Edge child1Unchecked()
1944 return children.child1Unchecked();
1949 ASSERT(!(m_flags & NodeHasVarArgs));
1950 return children.child2();
1955 ASSERT(!(m_flags & NodeHasVarArgs));
1956 return children.child3();
1959 unsigned firstChild()
1961 ASSERT(m_flags & NodeHasVarArgs);
1962 return children.firstChild();
1965 unsigned numChildren()
1967 ASSERT(m_flags & NodeHasVarArgs);
1968 return children.numChildren();
1971 UseKind binaryUseKind()
1973 ASSERT(child1().useKind() == child2().useKind());
1974 return child1().useKind();
1977 bool isBinaryUseKind(UseKind left, UseKind right)
1979 return child1().useKind() == left && child2().useKind() == right;
1982 bool isBinaryUseKind(UseKind useKind)
1984 return isBinaryUseKind(useKind, useKind);
1987 Edge childFor(UseKind useKind)
1989 if (child1().useKind() == useKind)
1991 if (child2().useKind() == useKind)
1993 if (child3().useKind() == useKind)
1998 SpeculatedType prediction()
2000 return m_prediction;
2003 bool predict(SpeculatedType prediction)
2005 return mergeSpeculation(m_prediction, prediction);
2008 bool shouldSpeculateInt32()
2010 return isInt32Speculation(prediction());
2013 bool shouldSpeculateNotInt32()
2015 return isNotInt32Speculation(prediction());
2020 return !!(prediction() & SpecBoolean);
2023 bool shouldSpeculateInt32OrBoolean()
2025 return isInt32OrBooleanSpeculation(prediction());
2028 bool shouldSpeculateInt32ForArithmetic()
2030 return isInt32SpeculationForArithmetic(prediction());
2033 bool shouldSpeculateInt32OrBooleanForArithmetic()
2035 return isInt32OrBooleanSpeculationForArithmetic(prediction());
2038 bool shouldSpeculateInt32OrBooleanExpectingDefined()
2040 return isInt32OrBooleanSpeculationExpectingDefined(prediction());
2043 bool shouldSpeculateAnyInt()
2045 return isAnyIntSpeculation(prediction());
2048 bool shouldSpeculateDouble()
2050 return isDoubleSpeculation(prediction());
2053 bool shouldSpeculateDoubleReal()
2055 return isDoubleRealSpeculation(prediction());
2058 bool shouldSpeculateNumber()
2060 return isFullNumberSpeculation(prediction());
2063 bool shouldSpeculateNumberOrBoolean()
2065 return isFullNumberOrBooleanSpeculation(prediction());
2068 bool shouldSpeculateNumberOrBooleanExpectingDefined()
2070 return isFullNumberOrBooleanSpeculationExpectingDefined(prediction());
2073 bool shouldSpeculateBoolean()
2075 return isBooleanSpeculation(prediction());
2078 bool shouldSpeculateNotBoolean()
2080 return isNotBooleanSpeculation(prediction());
2083 bool shouldSpeculateOther()
2085 return isOtherSpeculation(prediction());
2088 bool shouldSpeculateMisc()
2090 return isMiscSpeculation(prediction());
2093 bool shouldSpeculateStringIdent()
2095 return isStringIdentSpeculation(prediction());
2098 bool shouldSpeculateNotStringVar()
2100 return isNotStringVarSpeculation(prediction());
2103 bool shouldSpeculateString()
2105 return isStringSpeculation(prediction());
2108 bool shouldSpeculateNotString()
2110 return isNotStringSpeculation(prediction());
2113 bool shouldSpeculateStringOrOther()
2115 return isStringOrOtherSpeculation(prediction());
2118 bool shouldSpeculateStringObject()
2120 return isStringObjectSpeculation(prediction());
2123 bool shouldSpeculateStringOrStringObject()
2125 return isStringOrStringObjectSpeculation(prediction());
2128 bool shouldSpeculateRegExpObject()
2130 return isRegExpObjectSpeculation(prediction());
2133 bool shouldSpeculateSymbol()
2135 return isSymbolSpeculation(prediction());
2138 bool shouldSpeculateFinalObject()
2140 return isFinalObjectSpeculation(prediction());
2143 bool shouldSpeculateFinalObjectOrOther()
2145 return isFinalObjectOrOtherSpeculation(prediction());
2148 bool shouldSpeculateArray()
2150 return isArraySpeculation(prediction());
2153 bool shouldSpeculateProxyObject()
2155 return isProxyObjectSpeculation(prediction());
2158 bool shouldSpeculateDerivedArray()
2160 return isDerivedArraySpeculation(prediction());
2163 bool shouldSpeculateDirectArguments()
2165 return isDirectArgumentsSpeculation(prediction());
2168 bool shouldSpeculateScopedArguments()
2170 return isScopedArgumentsSpeculation(prediction());
2173 bool shouldSpeculateInt8Array()
2175 return isInt8ArraySpeculation(prediction());
2178 bool shouldSpeculateInt16Array()
2180 return isInt16ArraySpeculation(prediction());
2183 bool shouldSpeculateInt32Array()
2185 return isInt32ArraySpeculation(prediction());
2188 bool shouldSpeculateUint8Array()
2190 return isUint8ArraySpeculation(prediction());
2193 bool shouldSpeculateUint8ClampedArray()
2195 return isUint8ClampedArraySpeculation(prediction());
2198 bool shouldSpeculateUint16Array()
2200 return isUint16ArraySpeculation(prediction());
2203 bool shouldSpeculateUint32Array()
2205 return isUint32ArraySpeculation(prediction());
2208 bool shouldSpeculateFloat32Array()
2210 return isFloat32ArraySpeculation(prediction());
2213 bool shouldSpeculateFloat64Array()
2215 return isFloat64ArraySpeculation(prediction());
2218 bool shouldSpeculateArrayOrOther()
2220 return isArrayOrOtherSpeculation(prediction());
2223 bool shouldSpeculateObject()
2225 return isObjectSpeculation(prediction());
2228 bool shouldSpeculateObjectOrOther()
2230 return isObjectOrOtherSpeculation(prediction());
2233 bool shouldSpeculateCell()
2235 return isCellSpeculation(prediction());
2238 bool shouldSpeculateCellOrOther()
2240 return isCellOrOtherSpeculation(prediction());
2243 bool shouldSpeculateNotCell()
2245 return isNotCellSpeculation(prediction());
2248 bool shouldSpeculateUntypedForArithmetic()
2250 return isUntypedSpeculationForArithmetic(prediction());
2253 static bool shouldSpeculateUntypedForArithmetic(Node* op1, Node* op2)
2255 return op1->shouldSpeculateUntypedForArithmetic() || op2->shouldSpeculateUntypedForArithmetic();
2258 bool shouldSpeculateUntypedForBitOps()
2260 return isUntypedSpeculationForBitOps(prediction());
2263 static bool shouldSpeculateUntypedForBitOps(Node* op1, Node* op2)
2265 return op1->shouldSpeculateUntypedForBitOps() || op2->shouldSpeculateUntypedForBitOps();
2268 static bool shouldSpeculateBoolean(Node* op1, Node* op2)
2270 return op1->shouldSpeculateBoolean() && op2->shouldSpeculateBoolean();
2273 static bool shouldSpeculateInt32(Node* op1, Node* op2)
2275 return op1->shouldSpeculateInt32() && op2->shouldSpeculateInt32();
2278 static bool shouldSpeculateInt32OrBoolean(Node* op1, Node* op2)
2280 return op1->shouldSpeculateInt32OrBoolean()
2281 && op2->shouldSpeculateInt32OrBoolean();
2284 static bool shouldSpeculateInt32OrBooleanForArithmetic(Node* op1, Node* op2)
2286 return op1->shouldSpeculateInt32OrBooleanForArithmetic()
2287 && op2->shouldSpeculateInt32OrBooleanForArithmetic();
2290 static bool shouldSpeculateInt32OrBooleanExpectingDefined(Node* op1, Node* op2)
2292 return op1->shouldSpeculateInt32OrBooleanExpectingDefined()
2293 && op2->shouldSpeculateInt32OrBooleanExpectingDefined();
2296 static bool shouldSpeculateAnyInt(Node* op1, Node* op2)
2298 return op1->shouldSpeculateAnyInt() && op2->shouldSpeculateAnyInt();
2301 static bool shouldSpeculateNumber(Node* op1, Node* op2)
2303 return op1->shouldSpeculateNumber() && op2->shouldSpeculateNumber();
2306 static bool shouldSpeculateNumberOrBoolean(Node* op1, Node* op2)
2308 return op1->shouldSpeculateNumberOrBoolean()
2309 && op2->shouldSpeculateNumberOrBoolean();
2312 static bool shouldSpeculateNumberOrBooleanExpectingDefined(Node* op1, Node* op2)
2314 return op1->shouldSpeculateNumberOrBooleanExpectingDefined()
2315 && op2->shouldSpeculateNumberOrBooleanExpectingDefined();
2318 static bool shouldSpeculateSymbol(Node* op1, Node* op2)
2320 return op1->shouldSpeculateSymbol() && op2->shouldSpeculateSymbol();
2323 static bool shouldSpeculateFinalObject(Node* op1, Node* op2)
2325 return op1->shouldSpeculateFinalObject() && op2->shouldSpeculateFinalObject();
2328 static bool shouldSpeculateArray(Node* op1, Node* op2)
2330 return op1->shouldSpeculateArray() && op2->shouldSpeculateArray();
2333 bool canSpeculateInt32(RareCaseProfilingSource source)
2335 return nodeCanSpeculateInt32(arithNodeFlags(), source);
2338 bool canSpeculateInt52(RareCaseProfilingSource source)
2340 return nodeCanSpeculateInt52(arithNodeFlags(), source);
2343 RareCaseProfilingSource sourceFor(PredictionPass pass)
2345 if (pass == PrimaryPass || child1()->sawBooleans() || (child2() && child2()->sawBooleans()))
2347 return AllRareCases;
2350 bool canSpeculateInt32(PredictionPass pass)
2352 return canSpeculateInt32(sourceFor(pass));
2355 bool canSpeculateInt52(PredictionPass pass)
2357 return canSpeculateInt52(sourceFor(pass));
2360 bool hasTypeLocation()
2362 return op() == ProfileType;
2365 TypeLocation* typeLocation()
2367 ASSERT(hasTypeLocation());
2368 return m_opInfo.as<TypeLocation*>();
2371 bool hasBasicBlockLocation()
2373 return op() == ProfileControlFlow;
2376 BasicBlockLocation* basicBlockLocation()
2378 ASSERT(hasBasicBlockLocation());
2379 return m_opInfo.as<BasicBlockLocation*>();
2382 bool hasCheckDOMPatchpoint() const
2384 return op() == CheckDOM;
2387 DOMJIT::Patchpoint* checkDOMPatchpoint()
2389 ASSERT(hasCheckDOMPatchpoint());
2390 return m_opInfo.as<DOMJIT::Patchpoint*>();
2393 bool hasCallDOMGetterData() const
2395 return op() == CallDOMGetter;
2398 CallDOMGetterData* callDOMGetterData()
2400 ASSERT(hasCallDOMGetterData());
2401 return m_opInfo.as<CallDOMGetterData*>();
2404 bool hasClassInfo() const
2406 return op() == CheckDOM;
2409 const ClassInfo* classInfo()
2411 return m_opInfo2.as<const ClassInfo*>();
2414 bool hasSignature() const
2416 // Note that this does not include TailCall node types intentionally.
2417 // CallDOM node types are always converted from Call.
2418 return op() == Call || op() == CallDOM;
2421 const DOMJIT::Signature* signature()
2423 return m_opInfo.as<const DOMJIT::Signature*>();
2426 bool hasInternalMethodType() const
2428 return op() == HasIndexedProperty;
2431 PropertySlot::InternalMethodType internalMethodType() const
2433 ASSERT(hasInternalMethodType());
2434 return static_cast<PropertySlot::InternalMethodType>(m_opInfo2.as<uint32_t>());
2437 void setInternalMethodType(PropertySlot::InternalMethodType type)
2439 ASSERT(hasInternalMethodType());
2440 m_opInfo2 = static_cast<uint32_t>(type);
2443 Node* replacement() const
2445 return m_misc.replacement;
2448 void setReplacement(Node* replacement)
2450 m_misc.replacement = replacement;
2455 return Epoch::fromUnsigned(m_misc.epoch);
2458 void setEpoch(Epoch epoch)
2460 m_misc.epoch = epoch.toUnsigned();
2463 unsigned numberOfArgumentsToSkip()
2465 ASSERT(op() == CreateRest || op() == PhantomCreateRest || op() == GetRestLength || op() == GetMyArgumentByVal || op() == GetMyArgumentByValOutOfBounds);
2466 return m_opInfo.as<unsigned>();
2469 bool hasArgumentIndex()
2471 return op() == GetArgument;
2474 unsigned argumentIndex()
2476 ASSERT(hasArgumentIndex());
2477 return m_opInfo.as<unsigned>();
2480 void dumpChildren(PrintStream& out)
2484 out.printf("@%u", child1()->index());
2487 out.printf(", @%u", child2()->index());
2490 out.printf(", @%u", child3()->index());
2493 // NB. This class must have a trivial destructor.
2497 // References to up to 3 children, or links to a variable length set of children.
2498 AdjacencyList children;
2503 unsigned m_index { std::numeric_limits<unsigned>::max() };
2504 unsigned m_op : 10; // real type is NodeType
2505 unsigned m_flags : 20;
2506 // The virtual register number (spill location) associated with this .
2507 VirtualRegister m_virtualRegister;
2508 // The number of uses of the result of this operation (+1 for 'must generate' nodes, which have side-effects).
2509 unsigned m_refCount;
2510 // The prediction ascribed to this node after propagation.
2511 SpeculatedType m_prediction { SpecNone };
2512 // Immediate values, accesses type-checked via accessors above.
2513 struct OpInfoWrapper {
2518 OpInfoWrapper(uint32_t intValue)
2523 OpInfoWrapper(uint64_t intValue)
2527 OpInfoWrapper(void* pointer)
2530 u.pointer = pointer;
2532 OpInfoWrapper(const void* constPointer)
2535 u.constPointer = constPointer;
2537 OpInfoWrapper(RegisteredStructure structure)
2540 u.pointer = bitwise_cast<void*>(structure);
2542 OpInfoWrapper& operator=(uint32_t int32)
2548 OpInfoWrapper& operator=(int32_t int32)
2554 OpInfoWrapper& operator=(uint64_t int64)
2559 OpInfoWrapper& operator=(void* pointer)
2562 u.pointer = pointer;
2565 OpInfoWrapper& operator=(const void* constPointer)
2568 u.constPointer = constPointer;
2571 OpInfoWrapper& operator=(RegisteredStructure structure)
2574 u.pointer = bitwise_cast<void*>(structure);
2577 template <typename T>
2578 ALWAYS_INLINE auto as() const -> typename std::enable_if<std::is_pointer<T>::value && !std::is_const<typename std::remove_pointer<T>::type>::value, T>::type
2580 return static_cast<T>(u.pointer);
2582 template <typename T>
2583 ALWAYS_INLINE auto as() const -> typename std::enable_if<std::is_pointer<T>::value && std::is_const<typename std::remove_pointer<T>::type>::value, T>::type
2585 return static_cast<T>(u.constPointer);
2587 template <typename T>
2588 ALWAYS_INLINE auto as() const -> typename std::enable_if<std::is_integral<T>::value && sizeof(T) == 4, T>::type
2592 template <typename T>
2593 ALWAYS_INLINE auto as() const -> typename std::enable_if<std::is_integral<T>::value && sizeof(T) == 8, T>::type
2597 ALWAYS_INLINE RegisteredStructure asRegisteredStructure() const
2599 return bitwise_cast<RegisteredStructure>(u.pointer);
2606 const void* constPointer;
2609 OpInfoWrapper m_opInfo;
2610 OpInfoWrapper m_opInfo2;
2612 // Miscellaneous data that is usually meaningless, but can hold some analysis results
2613 // if you ask right. For example, if you do Graph::initializeNodeOwners(), Node::owner
2614 // will tell you which basic block a node belongs to. You cannot rely on this persisting
2615 // across transformations unless you do the maintenance work yourself. Other phases use
2616 // Node::replacement, but they do so manually: first you do Graph::clearReplacements()
2617 // and then you set, and use, replacement's yourself. Same thing for epoch.
2619 // Bottom line: don't use these fields unless you initialize them yourself, or by
2620 // calling some appropriate methods that initialize them the way you want. Otherwise,
2621 // these fields are meaningless.
2631 struct NodeComparator {
2632 template<typename NodePtrType>
2633 bool operator()(NodePtrType a, NodePtrType b) const
2635 return a->index() < b->index();
2639 template<typename T>
2640 CString nodeListDump(const T& nodeList)
2642 return sortedListDump(nodeList, NodeComparator());
2645 template<typename T>
2646 CString nodeMapDump(const T& nodeMap, DumpContext* context = 0)
2648 Vector<typename T::KeyType> keys;
2650 typename T::const_iterator iter = nodeMap.begin();
2651 iter != nodeMap.end(); ++iter)
2652 keys.append(iter->key);
2653 std::sort(keys.begin(), keys.end(), NodeComparator());
2654 StringPrintStream out;
2656 for(unsigned i = 0; i < keys.size(); ++i)
2657 out.print(comma, keys[i], "=>", inContext(nodeMap.get(keys[i]), context));
2658 return out.toCString();
2661 template<typename T>
2662 CString nodeValuePairListDump(const T& nodeValuePairList, DumpContext* context = 0)
2664 using V = typename T::ValueType;
2665 T sortedList = nodeValuePairList;
2666 std::sort(sortedList.begin(), sortedList.end(), [](const V& a, const V& b) {
2667 return NodeComparator()(a.node, b.node);
2670 StringPrintStream out;
2672 for (const auto& pair : sortedList)
2673 out.print(comma, pair.node, "=>", inContext(pair.value, context));
2674 return out.toCString();
2677 } } // namespace JSC::DFG
2681 void printInternal(PrintStream&, JSC::DFG::SwitchKind);
2682 void printInternal(PrintStream&, JSC::DFG::Node*);
2684 inline JSC::DFG::Node* inContext(JSC::DFG::Node* node, JSC::DumpContext*) { return node; }
2688 using WTF::inContext;