2 * Copyright (C) 2011 Apple Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 // Emit various logging information for debugging, including dumping the dataflow graphs.
30 #define DFG_DEBUG_VERBOSE 0
31 // Enable generation of dynamic checks into the instruction stream.
32 #define DFG_JIT_ASSERT 0
33 // Consistency check contents compiler data structures.
34 #define DFG_CONSISTENCY_CHECK 0
35 // Emit a breakpoint into the head of every generated function, to aid debugging in GDB.
36 #define DFG_JIT_BREAK_ON_EVERY_FUNCTION 0
37 // Emit a breakpoint into the head of every generated node, to aid debugging in GDB.
38 #define DFG_JIT_BREAK_ON_EVERY_BLOCK 0
39 // Emit a breakpoint into the head of every generated node, to aid debugging in GDB.
40 #define DFG_JIT_BREAK_ON_EVERY_NODE 0
41 // Disable the DFG JIT without having to touch Platform.h!
42 #define DFG_DEBUG_LOCAL_DISBALE 0
43 // Disable the SpeculativeJIT without having to touch Platform.h!
44 #define DFG_DEBUG_LOCAL_DISBALE_SPECULATIVE 0
45 // Generate stats on how successful we were in making use of the DFG jit, and remaining on the hot path.
46 #define DFG_SUCCESS_STATS 0
51 #include <wtf/Vector.h>
53 namespace JSC
{ namespace DFG
{
55 // Type for a virtual register number (spill location).
56 // Using an enum to make this type-checked at compile time, to avert programmer errors.
57 enum VirtualRegister
{ InvalidVirtualRegister
= -1 };
58 COMPILE_ASSERT(sizeof(VirtualRegister
) == sizeof(int), VirtualRegister_is_32bit
);
60 // Type for a reference to another node in the graph.
61 typedef uint32_t NodeIndex
;
62 static const NodeIndex NoNode
= UINT_MAX
;
64 // Information used to map back from an exception to any handler/source information.
65 // (Presently implemented as a bytecode index).
66 typedef uint32_t ExceptionInfo
;
68 // Entries in the NodeType enum (below) are composed of an id, a result type (possibly none)
69 // and some additional informative flags (must generate, is constant, etc).
70 #define NodeIdMask 0xFFF
71 #define NodeResultMask 0xF000
72 #define NodeMustGenerate 0x10000 // set on nodes that have side effects, and may not trivially be removed by DCE.
73 #define NodeIsConstant 0x20000
74 #define NodeIsJump 0x40000
75 #define NodeIsBranch 0x80000
76 #define NodeIsTerminal 0x100000
78 // These values record the result type of the node (as checked by NodeResultMask, above), 0 for no result.
79 #define NodeResultJS 0x1000
80 #define NodeResultDouble 0x2000
81 #define NodeResultInt32 0x3000
83 // This macro defines a set of information about all known node types, used to populate NodeId, NodeType below.
84 #define FOR_EACH_DFG_OP(macro) \
85 /* Nodes for constants. */\
86 macro(JSConstant, NodeResultJS | NodeIsConstant) \
87 macro(Int32Constant, NodeResultJS | NodeIsConstant) \
88 macro(DoubleConstant, NodeResultJS | NodeIsConstant) \
89 macro(ConvertThis, NodeResultJS) \
91 /* Nodes for local variable access. */\
92 macro(GetLocal, NodeResultJS) \
96 /* Nodes for bitwise operations. */\
97 macro(BitAnd, NodeResultInt32) \
98 macro(BitOr, NodeResultInt32) \
99 macro(BitXor, NodeResultInt32) \
100 macro(BitLShift, NodeResultInt32) \
101 macro(BitRShift, NodeResultInt32) \
102 macro(BitURShift, NodeResultInt32) \
103 /* Bitwise operators call ToInt32 on their operands. */\
104 macro(NumberToInt32, NodeResultInt32) \
105 macro(ValueToInt32, NodeResultInt32 | NodeMustGenerate) \
106 /* Used to box the result of URShift nodes (result has range 0..2^32-1). */\
107 macro(UInt32ToNumber, NodeResultDouble) \
109 /* Nodes for arithmetic operations. */\
110 macro(ArithAdd, NodeResultDouble) \
111 macro(ArithSub, NodeResultDouble) \
112 macro(ArithMul, NodeResultDouble) \
113 macro(ArithDiv, NodeResultDouble) \
114 macro(ArithMod, NodeResultDouble) \
115 /* Arithmetic operators call ToNumber on their operands. */\
116 macro(Int32ToNumber, NodeResultDouble) \
117 macro(ValueToNumber, NodeResultDouble | NodeMustGenerate) \
119 /* Add of values may either be arithmetic, or result in string concatenation. */\
120 macro(ValueAdd, NodeResultJS | NodeMustGenerate) \
122 /* Property access. */\
123 /* PutByValAlias indicates a 'put' aliases a prior write to the same property. */\
124 /* Since a put to 'length' may invalidate optimizations here, */\
125 /* this must be the directly subsequent property put. */\
126 macro(GetByVal, NodeResultJS | NodeMustGenerate) \
127 macro(PutByVal, NodeMustGenerate) \
128 macro(PutByValAlias, NodeMustGenerate) \
129 macro(GetById, NodeResultJS | NodeMustGenerate) \
130 macro(PutById, NodeMustGenerate) \
131 macro(PutByIdDirect, NodeMustGenerate) \
132 macro(GetGlobalVar, NodeResultJS | NodeMustGenerate) \
133 macro(PutGlobalVar, NodeMustGenerate) \
135 /* Nodes for comparison operations. */\
136 macro(CompareLess, NodeResultJS | NodeMustGenerate) \
137 macro(CompareLessEq, NodeResultJS | NodeMustGenerate) \
138 macro(CompareEq, NodeResultJS | NodeMustGenerate) \
139 macro(CompareStrictEq, NodeResultJS) \
141 /* Nodes for misc operations. */\
142 macro(LogicalNot, NodeResultJS) \
144 /* Block terminals. */\
145 macro(Jump, NodeMustGenerate | NodeIsTerminal | NodeIsJump) \
146 macro(Branch, NodeMustGenerate | NodeIsTerminal | NodeIsBranch) \
147 macro(Return, NodeMustGenerate | NodeIsTerminal)
149 // This enum generates a monotonically increasing id for all Node types,
150 // and is used by the subsequent enum to fill out the id (as accessed via the NodeIdMask).
152 #define DFG_OP_ENUM(opcode, flags) opcode##_id,
153 FOR_EACH_DFG_OP(DFG_OP_ENUM
)
157 // Entries in this enum describe all Node types.
158 // The enum value contains a monotonically increasing id, a result type, and additional flags.
160 #define DFG_OP_ENUM(opcode, flags) opcode = opcode##_id | (flags),
161 FOR_EACH_DFG_OP(DFG_OP_ENUM
)
165 // This type used in passing an immediate argument to Node constructor;
166 // distinguishes an immediate value (typically an index into a CodeBlock data structure -
167 // a constant index, argument, or identifier) from a NodeIndex.
169 explicit OpInfo(unsigned value
) : m_value(value
) {}
175 // Node represents a single operation in the data flow graph.
177 // Construct a node with up to 3 children, no immediate value.
178 Node(NodeType op
, ExceptionInfo exceptionInfo
, NodeIndex child1
= NoNode
, NodeIndex child2
= NoNode
, NodeIndex child3
= NoNode
)
180 , exceptionInfo(exceptionInfo
)
184 , m_virtualRegister(InvalidVirtualRegister
)
189 // Construct a node with up to 3 children and an immediate value.
190 Node(NodeType op
, ExceptionInfo exceptionInfo
, OpInfo imm
, NodeIndex child1
= NoNode
, NodeIndex child2
= NoNode
, NodeIndex child3
= NoNode
)
192 , exceptionInfo(exceptionInfo
)
196 , m_virtualRegister(InvalidVirtualRegister
)
198 , m_opInfo(imm
.m_value
)
202 // Construct a node with up to 3 children and two immediate values.
203 Node(NodeType op
, ExceptionInfo exceptionInfo
, OpInfo imm1
, OpInfo imm2
, NodeIndex child1
= NoNode
, NodeIndex child2
= NoNode
, NodeIndex child3
= NoNode
)
205 , exceptionInfo(exceptionInfo
)
209 , m_virtualRegister(InvalidVirtualRegister
)
211 , m_opInfo(imm1
.m_value
)
213 m_constantValue
.opInfo2
= imm2
.m_value
;
218 return op
& NodeMustGenerate
;
223 return op
& NodeIsConstant
;
226 unsigned constantNumber()
228 ASSERT(isConstant());
234 return op
== GetLocal
|| op
== SetLocal
;
237 VirtualRegister
local()
240 return (VirtualRegister
)m_opInfo
;
245 return op
== GetById
|| op
== PutById
|| op
== PutByIdDirect
;
248 unsigned identifierNumber()
250 ASSERT(hasIdentifier());
256 return op
== GetGlobalVar
|| op
== PutGlobalVar
;
261 ASSERT(hasVarNumber());
267 return op
& NodeResultMask
;
270 bool hasInt32Result()
272 return (op
& NodeResultMask
) == NodeResultInt32
;
275 bool hasDoubleResult()
277 return (op
& NodeResultMask
) == NodeResultDouble
;
282 return (op
& NodeResultMask
) == NodeResultJS
;
285 // Check for integers or doubles.
286 bool hasNumericResult()
288 // This check will need updating if more result types are added.
289 ASSERT((hasInt32Result() || hasDoubleResult()) == !hasJSResult());
290 return !hasJSResult();
293 int32_t int32Constant()
295 ASSERT(op
== Int32Constant
);
296 return m_constantValue
.asInt32
;
299 void setInt32Constant(int32_t value
)
301 ASSERT(op
== Int32Constant
);
302 m_constantValue
.asInt32
= value
;
305 double numericConstant()
307 ASSERT(op
== DoubleConstant
);
308 return m_constantValue
.asDouble
;
311 void setDoubleConstant(double value
)
313 ASSERT(op
== DoubleConstant
);
314 m_constantValue
.asDouble
= value
;
319 return op
& NodeIsJump
;
324 return op
& NodeIsBranch
;
329 return op
& NodeIsTerminal
;
332 unsigned takenBytecodeOffset()
334 ASSERT(isBranch() || isJump());
338 unsigned notTakenBytecodeOffset()
341 return m_constantValue
.opInfo2
;
344 VirtualRegister
virtualRegister()
347 ASSERT(m_virtualRegister
!= InvalidVirtualRegister
);
348 return m_virtualRegister
;
351 void setVirtualRegister(VirtualRegister virtualRegister
)
354 ASSERT(m_virtualRegister
== InvalidVirtualRegister
);
355 m_virtualRegister
= virtualRegister
;
358 bool shouldGenerate()
360 return m_refCount
&& op
!= Phi
;
368 // returns true when ref count passes from 0 to 1.
371 return !m_refCount
++;
374 unsigned adjustedRefCount()
376 return mustGenerate() ? m_refCount
- 1 : m_refCount
;
379 // This enum value describes the type of the node.
381 // Used to look up exception handling information (currently implemented as a bytecode index).
382 ExceptionInfo exceptionInfo
;
383 // References to up to 3 children (0 for no child).
384 NodeIndex child1
, child2
, child3
;
387 // The virtual register number (spill location) associated with this .
388 VirtualRegister m_virtualRegister
;
389 // The number of uses of the result of this operation (+1 for 'must generate' nodes, which have side-effects).
391 // An immediate value, accesses type-checked via accessors above.
393 // The value of an int32/double constant.
401 } } // namespace JSC::DFG