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());
1297 case MaterializeCreateActivation
:
1298 return reinterpret_cast<FrozenValue
*>(m_opInfo2
);
1300 return reinterpret_cast<FrozenValue
*>(m_opInfo
);
1302 RELEASE_ASSERT_NOT_REACHED();
1305 template<typename T
>
1308 return cellOperand()->cast
<T
>();
1311 void setCellOperand(FrozenValue
* value
)
1313 ASSERT(hasCellOperand());
1314 m_opInfo
= bitwise_cast
<uintptr_t>(value
);
1317 bool hasWatchpointSet()
1319 return op() == NotifyWrite
;
1322 WatchpointSet
* watchpointSet()
1324 ASSERT(hasWatchpointSet());
1325 return reinterpret_cast<WatchpointSet
*>(m_opInfo
);
1328 bool hasStoragePointer()
1330 return op() == ConstantStoragePointer
;
1333 void* storagePointer()
1335 ASSERT(hasStoragePointer());
1336 return reinterpret_cast<void*>(m_opInfo
);
1339 bool hasTransition()
1343 case AllocatePropertyStorage
:
1344 case ReallocatePropertyStorage
:
1351 Transition
* transition()
1353 ASSERT(hasTransition());
1354 return reinterpret_cast<Transition
*>(m_opInfo
);
1357 bool hasStructureSet()
1360 case CheckStructure
:
1361 case CheckStructureImmediate
:
1368 StructureSet
& structureSet()
1370 ASSERT(hasStructureSet());
1371 return *reinterpret_cast<StructureSet
*>(m_opInfo
);
1377 case ArrayifyToStructure
:
1379 case NewStringObject
:
1386 Structure
* structure()
1388 ASSERT(hasStructure());
1389 return reinterpret_cast<Structure
*>(m_opInfo
);
1392 bool hasStorageAccessData()
1397 case GetGetterSetterByOffset
:
1404 StorageAccessData
& storageAccessData()
1406 ASSERT(hasStorageAccessData());
1407 return *bitwise_cast
<StorageAccessData
*>(m_opInfo
);
1410 bool hasMultiGetByOffsetData()
1412 return op() == MultiGetByOffset
;
1415 MultiGetByOffsetData
& multiGetByOffsetData()
1417 ASSERT(hasMultiGetByOffsetData());
1418 return *reinterpret_cast<MultiGetByOffsetData
*>(m_opInfo
);
1421 bool hasMultiPutByOffsetData()
1423 return op() == MultiPutByOffset
;
1426 MultiPutByOffsetData
& multiPutByOffsetData()
1428 ASSERT(hasMultiPutByOffsetData());
1429 return *reinterpret_cast<MultiPutByOffsetData
*>(m_opInfo
);
1432 bool hasObjectMaterializationData()
1435 case MaterializeNewObject
:
1436 case MaterializeCreateActivation
:
1444 ObjectMaterializationData
& objectMaterializationData()
1446 ASSERT(hasObjectMaterializationData());
1447 return *reinterpret_cast<ObjectMaterializationData
*>(m_opInfo
);
1450 bool isObjectAllocation()
1454 case MaterializeNewObject
:
1461 bool isPhantomObjectAllocation()
1464 case PhantomNewObject
:
1471 bool isActivationAllocation()
1474 case CreateActivation
:
1475 case MaterializeCreateActivation
:
1482 bool isPhantomActivationAllocation()
1485 case PhantomCreateActivation
:
1492 bool isFunctionAllocation()
1502 bool isPhantomFunctionAllocation()
1505 case PhantomNewFunction
:
1512 bool isPhantomAllocation()
1515 case PhantomNewObject
:
1516 case PhantomDirectArguments
:
1517 case PhantomClonedArguments
:
1518 case PhantomNewFunction
:
1519 case PhantomCreateActivation
:
1529 case GetIndexedPropertyStorage
:
1530 case GetArrayLength
:
1531 case PutByValDirect
:
1536 case StringCharCodeAt
:
1539 case ArrayifyToStructure
:
1542 case HasIndexedProperty
:
1549 ArrayMode
arrayMode()
1551 ASSERT(hasArrayMode());
1552 if (op() == ArrayifyToStructure
)
1553 return ArrayMode::fromWord(m_opInfo2
);
1554 return ArrayMode::fromWord(m_opInfo
);
1557 bool setArrayMode(ArrayMode arrayMode
)
1559 ASSERT(hasArrayMode());
1560 if (this->arrayMode() == arrayMode
)
1562 m_opInfo
= arrayMode
.asWord();
1575 case UInt32ToNumber
:
1583 Arith::Mode
arithMode()
1585 ASSERT(hasArithMode());
1586 return static_cast<Arith::Mode
>(m_opInfo
);
1589 void setArithMode(Arith::Mode mode
)
1594 bool hasArithRoundingMode()
1596 return op() == ArithRound
;
1599 Arith::RoundingMode
arithRoundingMode()
1601 ASSERT(hasArithRoundingMode());
1602 return static_cast<Arith::RoundingMode
>(m_opInfo
);
1605 void setArithRoundingMode(Arith::RoundingMode mode
)
1607 ASSERT(hasArithRoundingMode());
1608 m_opInfo
= static_cast<uintptr_t>(mode
);
1611 bool hasVirtualRegister()
1613 return m_virtualRegister
.isValid();
1616 VirtualRegister
virtualRegister()
1618 ASSERT(hasResult());
1619 ASSERT(m_virtualRegister
.isValid());
1620 return m_virtualRegister
;
1623 void setVirtualRegister(VirtualRegister virtualRegister
)
1625 ASSERT(hasResult());
1626 ASSERT(!m_virtualRegister
.isValid());
1627 m_virtualRegister
= virtualRegister
;
1630 bool hasExecutionCounter()
1632 return op() == CountExecution
;
1635 Profiler::ExecutionCounter
* executionCounter()
1637 return bitwise_cast
<Profiler::ExecutionCounter
*>(m_opInfo
);
1640 bool shouldGenerate()
1645 bool isSemanticallySkippable()
1647 return op() == CountExecution
;
1655 unsigned postfixRef()
1657 return m_refCount
++;
1660 unsigned adjustedRefCount()
1662 return mustGenerate() ? m_refCount
- 1 : m_refCount
;
1665 void setRefCount(unsigned refCount
)
1667 m_refCount
= refCount
;
1672 ASSERT(!(m_flags
& NodeHasVarArgs
));
1673 return children
.child1();
1676 // This is useful if you want to do a fast check on the first child
1677 // before also doing a check on the opcode. Use this with care and
1678 // avoid it if possible.
1679 Edge
child1Unchecked()
1681 return children
.child1Unchecked();
1686 ASSERT(!(m_flags
& NodeHasVarArgs
));
1687 return children
.child2();
1692 ASSERT(!(m_flags
& NodeHasVarArgs
));
1693 return children
.child3();
1696 unsigned firstChild()
1698 ASSERT(m_flags
& NodeHasVarArgs
);
1699 return children
.firstChild();
1702 unsigned numChildren()
1704 ASSERT(m_flags
& NodeHasVarArgs
);
1705 return children
.numChildren();
1708 UseKind
binaryUseKind()
1710 ASSERT(child1().useKind() == child2().useKind());
1711 return child1().useKind();
1714 bool isBinaryUseKind(UseKind left
, UseKind right
)
1716 return child1().useKind() == left
&& child2().useKind() == right
;
1719 bool isBinaryUseKind(UseKind useKind
)
1721 return isBinaryUseKind(useKind
, useKind
);
1724 Edge
childFor(UseKind useKind
)
1726 if (child1().useKind() == useKind
)
1728 if (child2().useKind() == useKind
)
1730 if (child3().useKind() == useKind
)
1735 SpeculatedType
prediction()
1737 return m_prediction
;
1740 bool predict(SpeculatedType prediction
)
1742 return mergeSpeculation(m_prediction
, prediction
);
1745 bool shouldSpeculateInt32()
1747 return isInt32Speculation(prediction());
1752 return !!(prediction() & SpecBoolean
);
1755 bool shouldSpeculateInt32OrBoolean()
1757 return isInt32OrBooleanSpeculation(prediction());
1760 bool shouldSpeculateInt32ForArithmetic()
1762 return isInt32SpeculationForArithmetic(prediction());
1765 bool shouldSpeculateInt32OrBooleanForArithmetic()
1767 return isInt32OrBooleanSpeculationForArithmetic(prediction());
1770 bool shouldSpeculateInt32OrBooleanExpectingDefined()
1772 return isInt32OrBooleanSpeculationExpectingDefined(prediction());
1775 bool shouldSpeculateMachineInt()
1777 return isMachineIntSpeculation(prediction());
1780 bool shouldSpeculateDouble()
1782 return isDoubleSpeculation(prediction());
1785 bool shouldSpeculateDoubleReal()
1787 return isDoubleRealSpeculation(prediction());
1790 bool shouldSpeculateNumber()
1792 return isFullNumberSpeculation(prediction());
1795 bool shouldSpeculateNumberOrBoolean()
1797 return isFullNumberOrBooleanSpeculation(prediction());
1800 bool shouldSpeculateNumberOrBooleanExpectingDefined()
1802 return isFullNumberOrBooleanSpeculationExpectingDefined(prediction());
1805 bool shouldSpeculateBoolean()
1807 return isBooleanSpeculation(prediction());
1810 bool shouldSpeculateOther()
1812 return isOtherSpeculation(prediction());
1815 bool shouldSpeculateMisc()
1817 return isMiscSpeculation(prediction());
1820 bool shouldSpeculateStringIdent()
1822 return isStringIdentSpeculation(prediction());
1825 bool shouldSpeculateNotStringVar()
1827 return isNotStringVarSpeculation(prediction());
1830 bool shouldSpeculateString()
1832 return isStringSpeculation(prediction());
1835 bool shouldSpeculateStringObject()
1837 return isStringObjectSpeculation(prediction());
1840 bool shouldSpeculateStringOrStringObject()
1842 return isStringOrStringObjectSpeculation(prediction());
1845 bool shouldSpeculateFinalObject()
1847 return isFinalObjectSpeculation(prediction());
1850 bool shouldSpeculateFinalObjectOrOther()
1852 return isFinalObjectOrOtherSpeculation(prediction());
1855 bool shouldSpeculateArray()
1857 return isArraySpeculation(prediction());
1860 bool shouldSpeculateDirectArguments()
1862 return isDirectArgumentsSpeculation(prediction());
1865 bool shouldSpeculateScopedArguments()
1867 return isScopedArgumentsSpeculation(prediction());
1870 bool shouldSpeculateInt8Array()
1872 return isInt8ArraySpeculation(prediction());
1875 bool shouldSpeculateInt16Array()
1877 return isInt16ArraySpeculation(prediction());
1880 bool shouldSpeculateInt32Array()
1882 return isInt32ArraySpeculation(prediction());
1885 bool shouldSpeculateUint8Array()
1887 return isUint8ArraySpeculation(prediction());
1890 bool shouldSpeculateUint8ClampedArray()
1892 return isUint8ClampedArraySpeculation(prediction());
1895 bool shouldSpeculateUint16Array()
1897 return isUint16ArraySpeculation(prediction());
1900 bool shouldSpeculateUint32Array()
1902 return isUint32ArraySpeculation(prediction());
1905 bool shouldSpeculateFloat32Array()
1907 return isFloat32ArraySpeculation(prediction());
1910 bool shouldSpeculateFloat64Array()
1912 return isFloat64ArraySpeculation(prediction());
1915 bool shouldSpeculateArrayOrOther()
1917 return isArrayOrOtherSpeculation(prediction());
1920 bool shouldSpeculateObject()
1922 return isObjectSpeculation(prediction());
1925 bool shouldSpeculateObjectOrOther()
1927 return isObjectOrOtherSpeculation(prediction());
1930 bool shouldSpeculateCell()
1932 return isCellSpeculation(prediction());
1935 bool shouldSpeculateNotCell()
1937 return isNotCellSpeculation(prediction());
1940 static bool shouldSpeculateBoolean(Node
* op1
, Node
* op2
)
1942 return op1
->shouldSpeculateBoolean() && op2
->shouldSpeculateBoolean();
1945 static bool shouldSpeculateInt32(Node
* op1
, Node
* op2
)
1947 return op1
->shouldSpeculateInt32() && op2
->shouldSpeculateInt32();
1950 static bool shouldSpeculateInt32OrBoolean(Node
* op1
, Node
* op2
)
1952 return op1
->shouldSpeculateInt32OrBoolean()
1953 && op2
->shouldSpeculateInt32OrBoolean();
1956 static bool shouldSpeculateInt32OrBooleanForArithmetic(Node
* op1
, Node
* op2
)
1958 return op1
->shouldSpeculateInt32OrBooleanForArithmetic()
1959 && op2
->shouldSpeculateInt32OrBooleanForArithmetic();
1962 static bool shouldSpeculateInt32OrBooleanExpectingDefined(Node
* op1
, Node
* op2
)
1964 return op1
->shouldSpeculateInt32OrBooleanExpectingDefined()
1965 && op2
->shouldSpeculateInt32OrBooleanExpectingDefined();
1968 static bool shouldSpeculateMachineInt(Node
* op1
, Node
* op2
)
1970 return op1
->shouldSpeculateMachineInt() && op2
->shouldSpeculateMachineInt();
1973 static bool shouldSpeculateNumber(Node
* op1
, Node
* op2
)
1975 return op1
->shouldSpeculateNumber() && op2
->shouldSpeculateNumber();
1978 static bool shouldSpeculateNumberOrBoolean(Node
* op1
, Node
* op2
)
1980 return op1
->shouldSpeculateNumberOrBoolean()
1981 && op2
->shouldSpeculateNumberOrBoolean();
1984 static bool shouldSpeculateNumberOrBooleanExpectingDefined(Node
* op1
, Node
* op2
)
1986 return op1
->shouldSpeculateNumberOrBooleanExpectingDefined()
1987 && op2
->shouldSpeculateNumberOrBooleanExpectingDefined();
1990 static bool shouldSpeculateFinalObject(Node
* op1
, Node
* op2
)
1992 return op1
->shouldSpeculateFinalObject() && op2
->shouldSpeculateFinalObject();
1995 static bool shouldSpeculateArray(Node
* op1
, Node
* op2
)
1997 return op1
->shouldSpeculateArray() && op2
->shouldSpeculateArray();
2000 bool canSpeculateInt32(RareCaseProfilingSource source
)
2002 return nodeCanSpeculateInt32(arithNodeFlags(), source
);
2005 bool canSpeculateInt52(RareCaseProfilingSource source
)
2007 return nodeCanSpeculateInt52(arithNodeFlags(), source
);
2010 RareCaseProfilingSource
sourceFor(PredictionPass pass
)
2012 if (pass
== PrimaryPass
|| child1()->sawBooleans() || (child2() && child2()->sawBooleans()))
2014 return AllRareCases
;
2017 bool canSpeculateInt32(PredictionPass pass
)
2019 return canSpeculateInt32(sourceFor(pass
));
2022 bool canSpeculateInt52(PredictionPass pass
)
2024 return canSpeculateInt52(sourceFor(pass
));
2027 bool hasTypeLocation()
2029 return op() == ProfileType
;
2032 TypeLocation
* typeLocation()
2034 ASSERT(hasTypeLocation());
2035 return reinterpret_cast<TypeLocation
*>(m_opInfo
);
2038 bool hasBasicBlockLocation()
2040 return op() == ProfileControlFlow
;
2043 BasicBlockLocation
* basicBlockLocation()
2045 ASSERT(hasBasicBlockLocation());
2046 return reinterpret_cast<BasicBlockLocation
*>(m_opInfo
);
2049 Node
* replacement() const
2051 return m_misc
.replacement
;
2054 void setReplacement(Node
* replacement
)
2056 m_misc
.replacement
= replacement
;
2061 return Epoch::fromUnsigned(m_misc
.epoch
);
2064 void setEpoch(Epoch epoch
)
2066 m_misc
.epoch
= epoch
.toUnsigned();
2069 void dumpChildren(PrintStream
& out
)
2073 out
.printf("@%u", child1()->index());
2076 out
.printf(", @%u", child2()->index());
2079 out
.printf(", @%u", child3()->index());
2082 // NB. This class must have a trivial destructor.
2086 // References to up to 3 children, or links to a variable length set of children.
2087 AdjacencyList children
;
2090 unsigned m_op
: 10; // real type is NodeType
2091 unsigned m_flags
: 22;
2092 // The virtual register number (spill location) associated with this .
2093 VirtualRegister m_virtualRegister
;
2094 // The number of uses of the result of this operation (+1 for 'must generate' nodes, which have side-effects).
2095 unsigned m_refCount
;
2096 // The prediction ascribed to this node after propagation.
2097 SpeculatedType m_prediction
;
2098 // Immediate values, accesses type-checked via accessors above. The first one is
2099 // big enough to store a pointer.
2101 uintptr_t m_opInfo2
;
2104 // Fields used by various analyses.
2105 AbstractValue value
;
2107 // Miscellaneous data that is usually meaningless, but can hold some analysis results
2108 // if you ask right. For example, if you do Graph::initializeNodeOwners(), Node::owner
2109 // will tell you which basic block a node belongs to. You cannot rely on this persisting
2110 // across transformations unless you do the maintenance work yourself. Other phases use
2111 // Node::replacement, but they do so manually: first you do Graph::clearReplacements()
2112 // and then you set, and use, replacement's yourself. Same thing for epoch.
2114 // Bottom line: don't use these fields unless you initialize them yourself, or by
2115 // calling some appropriate methods that initialize them the way you want. Otherwise,
2116 // these fields are meaningless.
2126 inline bool nodeComparator(Node
* a
, Node
* b
)
2128 return a
->index() < b
->index();
2131 template<typename T
>
2132 CString
nodeListDump(const T
& nodeList
)
2134 return sortedListDump(nodeList
, nodeComparator
);
2137 template<typename T
>
2138 CString
nodeMapDump(const T
& nodeMap
, DumpContext
* context
= 0)
2140 Vector
<typename
T::KeyType
> keys
;
2142 typename
T::const_iterator iter
= nodeMap
.begin();
2143 iter
!= nodeMap
.end(); ++iter
)
2144 keys
.append(iter
->key
);
2145 std::sort(keys
.begin(), keys
.end(), nodeComparator
);
2146 StringPrintStream out
;
2148 for(unsigned i
= 0; i
< keys
.size(); ++i
)
2149 out
.print(comma
, keys
[i
], "=>", inContext(nodeMap
.get(keys
[i
]), context
));
2150 return out
.toCString();
2153 } } // namespace JSC::DFG
2157 void printInternal(PrintStream
&, JSC::DFG::SwitchKind
);
2158 void printInternal(PrintStream
&, JSC::DFG::Node
*);
2160 inline JSC::DFG::Node
* inContext(JSC::DFG::Node
* node
, JSC::DumpContext
*) { return node
; }
2164 using WTF::inContext
;