2 * Copyright (C) 2011 Apple Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 #include <wtf/Platform.h>
31 // Emit various logging information for debugging, including dumping the dataflow graphs.
32 #define ENABLE_DFG_DEBUG_VERBOSE 0
33 // Emit logging for OSR exit value recoveries at every node, not just nodes that
34 // actually has speculation checks.
35 #define ENABLE_DFG_VERBOSE_VALUE_RECOVERIES 0
36 // Enable generation of dynamic checks into the instruction stream.
38 #define ENABLE_DFG_JIT_ASSERT 1
40 #define ENABLE_DFG_JIT_ASSERT 0
42 // Consistency check contents compiler data structures.
43 #define ENBALE_DFG_CONSISTENCY_CHECK 0
44 // Emit a breakpoint into the head of every generated function, to aid debugging in GDB.
45 #define ENABLE_DFG_JIT_BREAK_ON_EVERY_FUNCTION 0
46 // Emit a breakpoint into the head of every generated node, to aid debugging in GDB.
47 #define ENABLE_DFG_JIT_BREAK_ON_EVERY_BLOCK 0
48 // Emit a breakpoint into the head of every generated node, to aid debugging in GDB.
49 #define ENABLE_DFG_JIT_BREAK_ON_EVERY_NODE 0
50 // Emit a breakpoint into the speculation failure code.
51 #define ENABLE_DFG_JIT_BREAK_ON_SPECULATION_FAILURE 0
52 // Log every speculation failure.
53 #define ENABLE_DFG_VERBOSE_SPECULATION_FAILURE 0
54 // Disable the DFG JIT without having to touch Platform.h!
55 #define DFG_DEBUG_LOCAL_DISBALE 0
56 // Disable the SpeculativeJIT without having to touch Platform.h!
57 #define DFG_DEBUG_LOCAL_DISBALE_SPECULATIVE 0
58 // Enable OSR entry from baseline JIT.
59 #define ENABLE_DFG_OSR_ENTRY ENABLE_TIERED_COMPILATION
60 // Disable the non-speculative JIT and use OSR instead.
61 #define ENABLE_DFG_OSR_EXIT ENABLE_TIERED_COMPILATION
62 // Generate stats on how successful we were in making use of the DFG jit, and remaining on the hot path.
63 #define ENABLE_DFG_SUCCESS_STATS 0
68 #include "CodeBlock.h"
70 #include "PredictedType.h"
71 #include "ValueProfile.h"
72 #include <wtf/Vector.h>
74 namespace JSC { namespace DFG {
76 // Type for a virtual register number (spill location).
77 // Using an enum to make this type-checked at compile time, to avert programmer errors.
78 enum VirtualRegister { InvalidVirtualRegister = -1 };
79 COMPILE_ASSERT(sizeof(VirtualRegister) == sizeof(int), VirtualRegister_is_32bit);
81 // Type for a reference to another node in the graph.
82 typedef uint32_t NodeIndex;
83 static const NodeIndex NoNode = UINT_MAX;
85 // Information used to map back from an exception to any handler/source information,
86 // and to implement OSR.
87 // (Presently implemented as a bytecode index).
91 : m_bytecodeIndex(std::numeric_limits<uint32_t>::max())
95 explicit CodeOrigin(uint32_t bytecodeIndex)
96 : m_bytecodeIndex(bytecodeIndex)
100 bool isSet() const { return m_bytecodeIndex != std::numeric_limits<uint32_t>::max(); }
102 uint32_t bytecodeIndex() const
105 return m_bytecodeIndex;
109 uint32_t m_bytecodeIndex;
112 // Entries in the NodeType enum (below) are composed of an id, a result type (possibly none)
113 // and some additional informative flags (must generate, is constant, etc).
114 #define NodeIdMask 0xFFF
115 #define NodeResultMask 0xF000
116 #define NodeMustGenerate 0x10000 // set on nodes that have side effects, and may not trivially be removed by DCE.
117 #define NodeIsConstant 0x20000
118 #define NodeIsJump 0x40000
119 #define NodeIsBranch 0x80000
120 #define NodeIsTerminal 0x100000
121 #define NodeHasVarArgs 0x200000
123 // These values record the result type of the node (as checked by NodeResultMask, above), 0 for no result.
124 #define NodeResultJS 0x1000
125 #define NodeResultNumber 0x2000
126 #define NodeResultInt32 0x3000
127 #define NodeResultBoolean 0x4000
129 // This macro defines a set of information about all known node types, used to populate NodeId, NodeType below.
130 #define FOR_EACH_DFG_OP(macro) \
131 /* Nodes for constants. */\
132 macro(JSConstant, NodeResultJS) \
133 macro(ConvertThis, NodeResultJS) \
135 /* Nodes for local variable access. */\
136 macro(GetLocal, NodeResultJS) \
140 /* Nodes for bitwise operations. */\
141 macro(BitAnd, NodeResultInt32) \
142 macro(BitOr, NodeResultInt32) \
143 macro(BitXor, NodeResultInt32) \
144 macro(BitLShift, NodeResultInt32) \
145 macro(BitRShift, NodeResultInt32) \
146 macro(BitURShift, NodeResultInt32) \
147 /* Bitwise operators call ToInt32 on their operands. */\
148 macro(ValueToInt32, NodeResultInt32 | NodeMustGenerate) \
149 /* Used to box the result of URShift nodes (result has range 0..2^32-1). */\
150 macro(UInt32ToNumber, NodeResultNumber) \
152 /* Nodes for arithmetic operations. */\
153 macro(ArithAdd, NodeResultNumber) \
154 macro(ArithSub, NodeResultNumber) \
155 macro(ArithMul, NodeResultNumber) \
156 macro(ArithDiv, NodeResultNumber) \
157 macro(ArithMod, NodeResultNumber) \
158 /* Arithmetic operators call ToNumber on their operands. */\
159 macro(ValueToNumber, NodeResultNumber | NodeMustGenerate) \
161 /* A variant of ValueToNumber, which a hint that the parents will always use this as a double. */\
162 macro(ValueToDouble, NodeResultNumber | NodeMustGenerate) \
164 /* Add of values may either be arithmetic, or result in string concatenation. */\
165 macro(ValueAdd, NodeResultJS | NodeMustGenerate) \
167 /* Property access. */\
168 /* PutByValAlias indicates a 'put' aliases a prior write to the same property. */\
169 /* Since a put to 'length' may invalidate optimizations here, */\
170 /* this must be the directly subsequent property put. */\
171 macro(GetByVal, NodeResultJS | NodeMustGenerate) \
172 macro(PutByVal, NodeMustGenerate) \
173 macro(PutByValAlias, NodeMustGenerate) \
174 macro(GetById, NodeResultJS | NodeMustGenerate) \
175 macro(PutById, NodeMustGenerate) \
176 macro(PutByIdDirect, NodeMustGenerate) \
177 macro(GetMethod, NodeResultJS | NodeMustGenerate) \
178 macro(GetGlobalVar, NodeResultJS | NodeMustGenerate) \
179 macro(PutGlobalVar, NodeMustGenerate) \
181 /* Nodes for comparison operations. */\
182 macro(CompareLess, NodeResultBoolean | NodeMustGenerate) \
183 macro(CompareLessEq, NodeResultBoolean | NodeMustGenerate) \
184 macro(CompareGreater, NodeResultBoolean | NodeMustGenerate) \
185 macro(CompareGreaterEq, NodeResultBoolean | NodeMustGenerate) \
186 macro(CompareEq, NodeResultBoolean | NodeMustGenerate) \
187 macro(CompareStrictEq, NodeResultBoolean) \
190 macro(Call, NodeResultJS | NodeMustGenerate | NodeHasVarArgs) \
191 macro(Construct, NodeResultJS | NodeMustGenerate | NodeHasVarArgs) \
193 /* Resolve nodes. */\
194 macro(Resolve, NodeResultJS | NodeMustGenerate) \
195 macro(ResolveBase, NodeResultJS | NodeMustGenerate) \
196 macro(ResolveBaseStrictPut, NodeResultJS | NodeMustGenerate) \
198 /* Nodes for misc operations. */\
199 macro(Breakpoint, NodeMustGenerate) \
200 macro(CheckHasInstance, NodeMustGenerate) \
201 macro(InstanceOf, NodeResultBoolean) \
202 macro(LogicalNot, NodeResultBoolean) \
204 /* Block terminals. */\
205 macro(Jump, NodeMustGenerate | NodeIsTerminal | NodeIsJump) \
206 macro(Branch, NodeMustGenerate | NodeIsTerminal | NodeIsBranch) \
207 macro(Return, NodeMustGenerate | NodeIsTerminal)
209 // This enum generates a monotonically increasing id for all Node types,
210 // and is used by the subsequent enum to fill out the id (as accessed via the NodeIdMask).
212 #define DFG_OP_ENUM(opcode, flags) opcode##_id,
213 FOR_EACH_DFG_OP(DFG_OP_ENUM)
217 // Entries in this enum describe all Node types.
218 // The enum value contains a monotonically increasing id, a result type, and additional flags.
220 #define DFG_OP_ENUM(opcode, flags) opcode = opcode##_id | (flags),
221 FOR_EACH_DFG_OP(DFG_OP_ENUM)
225 // This type used in passing an immediate argument to Node constructor;
226 // distinguishes an immediate value (typically an index into a CodeBlock data structure -
227 // a constant index, argument, or identifier) from a NodeIndex.
229 explicit OpInfo(unsigned value) : m_value(value) {}
235 // Node represents a single operation in the data flow graph.
237 enum VarArgTag { VarArg };
239 // Construct a node with up to 3 children, no immediate value.
240 Node(NodeType op, CodeOrigin codeOrigin, NodeIndex child1 = NoNode, NodeIndex child2 = NoNode, NodeIndex child3 = NoNode)
242 , codeOrigin(codeOrigin)
243 , m_virtualRegister(InvalidVirtualRegister)
246 ASSERT(!(op & NodeHasVarArgs));
247 children.fixed.child1 = child1;
248 children.fixed.child2 = child2;
249 children.fixed.child3 = child3;
252 // Construct a node with up to 3 children and an immediate value.
253 Node(NodeType op, CodeOrigin codeOrigin, OpInfo imm, NodeIndex child1 = NoNode, NodeIndex child2 = NoNode, NodeIndex child3 = NoNode)
255 , codeOrigin(codeOrigin)
256 , m_virtualRegister(InvalidVirtualRegister)
258 , m_opInfo(imm.m_value)
260 ASSERT(!(op & NodeHasVarArgs));
261 children.fixed.child1 = child1;
262 children.fixed.child2 = child2;
263 children.fixed.child3 = child3;
266 // Construct a node with up to 3 children and two immediate values.
267 Node(NodeType op, CodeOrigin codeOrigin, OpInfo imm1, OpInfo imm2, NodeIndex child1 = NoNode, NodeIndex child2 = NoNode, NodeIndex child3 = NoNode)
269 , codeOrigin(codeOrigin)
270 , m_virtualRegister(InvalidVirtualRegister)
272 , m_opInfo(imm1.m_value)
273 , m_opInfo2(imm2.m_value)
275 ASSERT(!(op & NodeHasVarArgs));
276 children.fixed.child1 = child1;
277 children.fixed.child2 = child2;
278 children.fixed.child3 = child3;
281 // Construct a node with a variable number of children and two immediate values.
282 Node(VarArgTag, NodeType op, CodeOrigin codeOrigin, OpInfo imm1, OpInfo imm2, unsigned firstChild, unsigned numChildren)
284 , codeOrigin(codeOrigin)
285 , m_virtualRegister(InvalidVirtualRegister)
287 , m_opInfo(imm1.m_value)
288 , m_opInfo2(imm2.m_value)
290 ASSERT(op & NodeHasVarArgs);
291 children.variable.firstChild = firstChild;
292 children.variable.numChildren = numChildren;
297 return op & NodeMustGenerate;
302 return op == JSConstant;
305 unsigned constantNumber()
307 ASSERT(isConstant());
311 JSValue valueOfJSConstant(CodeBlock* codeBlock)
313 return codeBlock->constantRegister(FirstConstantRegisterIndex + constantNumber()).get();
316 bool isInt32Constant(CodeBlock* codeBlock)
318 return isConstant() && valueOfJSConstant(codeBlock).isInt32();
321 bool isDoubleConstant(CodeBlock* codeBlock)
323 bool result = isConstant() && valueOfJSConstant(codeBlock).isDouble();
325 ASSERT(!isInt32Constant(codeBlock));
329 bool isNumberConstant(CodeBlock* codeBlock)
331 bool result = isConstant() && valueOfJSConstant(codeBlock).isNumber();
332 ASSERT(result == (isInt32Constant(codeBlock) || isDoubleConstant(codeBlock)));
336 bool isBooleanConstant(CodeBlock* codeBlock)
338 return isConstant() && valueOfJSConstant(codeBlock).isBoolean();
341 int32_t valueOfInt32Constant(CodeBlock* codeBlock)
343 ASSERT(isInt32Constant(codeBlock));
344 return valueOfJSConstant(codeBlock).asInt32();
347 double valueOfNumberConstant(CodeBlock* codeBlock)
349 ASSERT(isNumberConstant(codeBlock));
350 return valueOfJSConstant(codeBlock).uncheckedGetNumber();
353 bool valueOfBooleanConstant(CodeBlock* codeBlock)
355 ASSERT(isBooleanConstant(codeBlock));
356 return valueOfJSConstant(codeBlock).getBoolean();
361 return op == GetLocal || op == SetLocal;
364 VirtualRegister local()
367 return (VirtualRegister)m_opInfo;
371 // If we want to use this in production code, should make it faster -
372 // e.g. make hasIdentifier a flag in the bitfield.
375 return op == GetById || op == PutById || op == PutByIdDirect || op == GetMethod
376 || op == Resolve || op == ResolveBase || op == ResolveBaseStrictPut;
380 unsigned identifierNumber()
382 ASSERT(hasIdentifier());
388 return op == GetGlobalVar || op == PutGlobalVar;
393 ASSERT(hasVarNumber());
399 return op & NodeResultMask;
402 bool hasInt32Result()
404 return (op & NodeResultMask) == NodeResultInt32;
407 bool hasNumberResult()
409 return (op & NodeResultMask) == NodeResultNumber;
414 return (op & NodeResultMask) == NodeResultJS;
417 bool hasBooleanResult()
419 return (op & NodeResultMask) == NodeResultBoolean;
424 return op & NodeIsJump;
429 return op & NodeIsBranch;
434 return op & NodeIsTerminal;
437 unsigned takenBytecodeOffset()
439 ASSERT(isBranch() || isJump());
443 unsigned notTakenBytecodeOffset()
463 PredictedType getPrediction()
465 ASSERT(hasPrediction());
466 return static_cast<PredictedType>(m_opInfo2);
469 bool predict(PredictedType prediction, PredictionSource source)
471 ASSERT(hasPrediction());
473 // We have previously found empirically that ascribing static predictions
474 // to heap loads as well as calls is not profitable, as these predictions
475 // are wrong too often. Hence, this completely ignores static predictions.
476 if (source == WeakPrediction)
479 if (prediction == PredictNone)
482 ASSERT(source == StrongPrediction);
484 return mergePrediction(m_opInfo2, makePrediction(prediction, source));
487 VirtualRegister virtualRegister()
490 ASSERT(m_virtualRegister != InvalidVirtualRegister);
491 return m_virtualRegister;
494 void setVirtualRegister(VirtualRegister virtualRegister)
497 ASSERT(m_virtualRegister == InvalidVirtualRegister);
498 m_virtualRegister = virtualRegister;
501 bool shouldGenerate()
503 return m_refCount && op != Phi;
511 // returns true when ref count passes from 0 to 1.
514 return !m_refCount++;
517 unsigned adjustedRefCount()
519 return mustGenerate() ? m_refCount - 1 : m_refCount;
524 ASSERT(!(op & NodeHasVarArgs));
525 return children.fixed.child1;
528 // This is useful if you want to do a fast check on the first child
529 // before also doing a check on the opcode. Use this with care and
530 // avoid it if possible.
531 NodeIndex child1Unchecked()
533 return children.fixed.child1;
538 ASSERT(!(op & NodeHasVarArgs));
539 return children.fixed.child2;
544 ASSERT(!(op & NodeHasVarArgs));
545 return children.fixed.child3;
548 unsigned firstChild()
550 ASSERT(op & NodeHasVarArgs);
551 return children.variable.firstChild;
554 unsigned numChildren()
556 ASSERT(op & NodeHasVarArgs);
557 return children.variable.numChildren;
560 // This enum value describes the type of the node.
562 // Used to look up exception handling information (currently implemented as a bytecode index).
563 CodeOrigin codeOrigin;
564 // References to up to 3 children (0 for no child).
567 NodeIndex child1, child2, child3;
571 unsigned numChildren;
576 // The virtual register number (spill location) associated with this .
577 VirtualRegister m_virtualRegister;
578 // The number of uses of the result of this operation (+1 for 'must generate' nodes, which have side-effects).
580 // Immediate values, accesses type-checked via accessors above.
581 unsigned m_opInfo, m_opInfo2;
584 } } // namespace JSC::DFG