2 * Copyright (C) 2012 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>
33 #include "DFGNodeFlags.h"
35 namespace JSC { namespace DFG {
37 // This macro defines a set of information about all known node types, used to populate NodeId, NodeType below.
38 #define FOR_EACH_DFG_OP(macro) \
39 /* A constant in the CodeBlock's constant pool. */\
40 macro(JSConstant, NodeResultJS | NodeDoesNotExit) \
42 /* A constant not in the CodeBlock's constant pool. Uses get patched to jumps that exit the */\
44 macro(WeakJSConstant, NodeResultJS | NodeDoesNotExit) \
46 /* Marker to indicate that an operation was optimized entirely and all that is left */\
47 /* is to make one node alias another. CSE will later usually eliminate this node, */\
48 /* though it may choose not to if it would corrupt predictions (very rare). */\
49 macro(Identity, NodeResultJS) \
51 /* Nodes for handling functions (both as call and as construct). */\
52 macro(ConvertThis, NodeResultJS) \
53 macro(CreateThis, NodeResultJS) /* Note this is not MustGenerate since we're returning it anyway. */ \
54 macro(GetCallee, NodeResultJS) \
55 macro(SetCallee, NodeMustGenerate) \
57 /* Nodes for local variable access. These nodes are linked together using Phi nodes. */\
58 /* Any two nodes that are part of the same Phi graph will share the same */\
59 /* VariableAccessData, and thus will share predictions. */\
60 macro(GetLocal, NodeResultJS) \
61 macro(SetLocal, NodeExitsForward) \
62 macro(MovHintAndCheck, NodeMustGenerate | NodeExitsForward) \
63 macro(MovHint, NodeDoesNotExit) \
64 macro(ZombieHint, NodeDoesNotExit) \
65 macro(Phantom, NodeMustGenerate) \
66 macro(Nop, NodeDoesNotExit) \
67 macro(Phi, NodeDoesNotExit | NodeRelevantToOSR) \
68 macro(Flush, NodeMustGenerate | NodeDoesNotExit) \
69 macro(PhantomLocal, NodeMustGenerate | NodeDoesNotExit) \
71 /* Get the value of a local variable, without linking into the VariableAccessData */\
72 /* network. This is only valid for variable accesses whose predictions originated */\
73 /* as something other than a local access, and thus had their own profiling. */\
74 macro(GetLocalUnlinked, NodeResultJS) \
76 /* Marker for an argument being set at the prologue of a function. */\
77 macro(SetArgument, 0 | NodeDoesNotExit) \
79 /* Hint that inlining begins here. No code is generated for this node. It's only */\
80 /* used for copying OSR data into inline frame data, to support reification of */\
81 /* call frames of inlined functions. */\
82 macro(InlineStart, NodeMustGenerate | NodeDoesNotExit) \
84 /* Nodes for bitwise operations. */\
85 macro(BitAnd, NodeResultInt32 | NodeMustGenerate) \
86 macro(BitOr, NodeResultInt32 | NodeMustGenerate) \
87 macro(BitXor, NodeResultInt32 | NodeMustGenerate) \
88 macro(BitLShift, NodeResultInt32 | NodeMustGenerate) \
89 macro(BitRShift, NodeResultInt32 | NodeMustGenerate) \
90 macro(BitURShift, NodeResultInt32 | NodeMustGenerate) \
91 /* Bitwise operators call ToInt32 on their operands. */\
92 macro(ValueToInt32, NodeResultInt32) \
93 /* Used to box the result of URShift nodes (result has range 0..2^32-1). */\
94 macro(UInt32ToNumber, NodeResultNumber | NodeExitsForward) \
96 /* Used to cast known integers to doubles, so as to separate the double form */\
97 /* of the value from the integer form. */\
98 macro(Int32ToDouble, NodeResultNumber) \
99 macro(ForwardInt32ToDouble, NodeResultNumber | NodeExitsForward) \
100 /* Used to speculate that a double value is actually an integer. */\
101 macro(DoubleAsInt32, NodeResultInt32 | NodeExitsForward) \
103 /* Nodes for arithmetic operations. */\
104 macro(ArithAdd, NodeResultNumber | NodeMustGenerate) \
105 macro(ArithSub, NodeResultNumber | NodeMustGenerate) \
106 macro(ArithNegate, NodeResultNumber | NodeMustGenerate) \
107 macro(ArithMul, NodeResultNumber | NodeMustGenerate) \
108 macro(ArithIMul, NodeResultInt32 | NodeMustGenerate) \
109 macro(ArithDiv, NodeResultNumber | NodeMustGenerate) \
110 macro(ArithMod, NodeResultNumber | NodeMustGenerate) \
111 macro(ArithAbs, NodeResultNumber | NodeMustGenerate) \
112 macro(ArithMin, NodeResultNumber | NodeMustGenerate) \
113 macro(ArithMax, NodeResultNumber | NodeMustGenerate) \
114 macro(ArithSqrt, NodeResultNumber | NodeMustGenerate) \
116 /* Add of values may either be arithmetic, or result in string concatenation. */\
117 macro(ValueAdd, NodeResultJS | NodeMustGenerate | NodeMightClobber) \
119 /* Property access. */\
120 /* PutByValAlias indicates a 'put' aliases a prior write to the same property. */\
121 /* Since a put to 'length' may invalidate optimizations here, */\
122 /* this must be the directly subsequent property put. Note that PutByVal */\
123 /* opcodes use VarArgs beause they may have up to 4 children. */\
124 macro(GetByVal, NodeResultJS | NodeMustGenerate | NodeMightClobber) \
125 macro(PutByVal, NodeMustGenerate | NodeHasVarArgs | NodeMightClobber) \
126 macro(PutByValAlias, NodeMustGenerate | NodeHasVarArgs | NodeMightClobber) \
127 macro(GetById, NodeResultJS | NodeMustGenerate | NodeClobbersWorld) \
128 macro(GetByIdFlush, NodeResultJS | NodeMustGenerate | NodeClobbersWorld) \
129 macro(PutById, NodeMustGenerate | NodeClobbersWorld) \
130 macro(PutByIdDirect, NodeMustGenerate | NodeClobbersWorld) \
131 macro(CheckStructure, NodeMustGenerate) \
132 macro(CheckExecutable, NodeMustGenerate) \
133 macro(ForwardCheckStructure, NodeMustGenerate | NodeExitsForward) \
134 /* Transition watchpoints are a contract between the party setting the watchpoint */\
135 /* and the runtime system, where the party promises that the child object once had */\
136 /* the structure being watched, and the runtime system in turn promises that the */\
137 /* watchpoint will be turned into an OSR exit if any object with that structure */\
138 /* ever transitions to a different structure. Hence, the child object must have */\
139 /* previously had a CheckStructure executed on it or we're dealing with an object */\
140 /* constant (WeakJSConstant) and the object was known to have that structure at */\
141 /* compile-time. In the latter case this means that no structure checks have to be */\
142 /* performed for this object by JITted code. In the former case this means that*/\
143 /* the object's structure does not need to be rechecked due to side-effecting */\
144 /* (clobbering) operations. */\
145 macro(StructureTransitionWatchpoint, NodeMustGenerate) \
146 macro(ForwardStructureTransitionWatchpoint, NodeMustGenerate | NodeExitsForward) \
147 macro(PutStructure, NodeMustGenerate) \
148 macro(PhantomPutStructure, NodeMustGenerate | NodeDoesNotExit) \
149 macro(AllocatePropertyStorage, NodeMustGenerate | NodeDoesNotExit | NodeResultStorage) \
150 macro(ReallocatePropertyStorage, NodeMustGenerate | NodeDoesNotExit | NodeResultStorage) \
151 macro(GetButterfly, NodeResultStorage) \
152 macro(CheckArray, NodeMustGenerate) \
153 macro(Arrayify, NodeMustGenerate) \
154 macro(ArrayifyToStructure, NodeMustGenerate) \
155 macro(GetIndexedPropertyStorage, NodeResultStorage) \
156 macro(GetByOffset, NodeResultJS) \
157 macro(PutByOffset, NodeMustGenerate) \
158 macro(GetArrayLength, NodeResultInt32) \
159 macro(GetScope, NodeResultJS) \
160 macro(GetMyScope, NodeResultJS) \
161 macro(SetMyScope, NodeMustGenerate) \
162 macro(SkipTopScope, NodeResultJS) \
163 macro(SkipScope, NodeResultJS) \
164 macro(GetScopeRegisters, NodeResultStorage) \
165 macro(GetScopedVar, NodeResultJS) \
166 macro(PutScopedVar, NodeMustGenerate) \
167 macro(GetGlobalVar, NodeResultJS) \
168 macro(PutGlobalVar, NodeMustGenerate) \
169 macro(GlobalVarWatchpoint, NodeMustGenerate) \
170 macro(PutGlobalVarCheck, NodeMustGenerate) \
171 macro(CheckFunction, NodeMustGenerate) \
172 macro(AllocationProfileWatchpoint, NodeMustGenerate) \
174 /* Optimizations for array mutation. */\
175 macro(ArrayPush, NodeResultJS | NodeMustGenerate | NodeClobbersWorld) \
176 macro(ArrayPop, NodeResultJS | NodeMustGenerate | NodeClobbersWorld) \
178 /* Optimizations for regular expression matching. */\
179 macro(RegExpExec, NodeResultJS | NodeMustGenerate) \
180 macro(RegExpTest, NodeResultJS | NodeMustGenerate) \
182 /* Optimizations for string access */ \
183 macro(StringCharCodeAt, NodeResultInt32) \
184 macro(StringCharAt, NodeResultJS) \
185 macro(StringFromCharCode, NodeResultJS) \
187 /* Nodes for comparison operations. */\
188 macro(CompareLess, NodeResultBoolean | NodeMustGenerate | NodeMightClobber) \
189 macro(CompareLessEq, NodeResultBoolean | NodeMustGenerate | NodeMightClobber) \
190 macro(CompareGreater, NodeResultBoolean | NodeMustGenerate | NodeMightClobber) \
191 macro(CompareGreaterEq, NodeResultBoolean | NodeMustGenerate | NodeMightClobber) \
192 macro(CompareEq, NodeResultBoolean | NodeMustGenerate | NodeMightClobber) \
193 macro(CompareEqConstant, NodeResultBoolean | NodeMustGenerate) \
194 macro(CompareStrictEq, NodeResultBoolean) \
195 macro(CompareStrictEqConstant, NodeResultBoolean) \
198 macro(Call, NodeResultJS | NodeMustGenerate | NodeHasVarArgs | NodeClobbersWorld) \
199 macro(Construct, NodeResultJS | NodeMustGenerate | NodeHasVarArgs | NodeClobbersWorld) \
202 macro(NewObject, NodeResultJS) \
203 macro(NewArray, NodeResultJS | NodeHasVarArgs) \
204 macro(NewArrayWithSize, NodeResultJS) \
205 macro(NewArrayBuffer, NodeResultJS) \
206 macro(NewRegexp, NodeResultJS) \
208 /* Resolve nodes. */\
209 macro(Resolve, NodeResultJS | NodeMustGenerate | NodeClobbersWorld) \
210 macro(ResolveBase, NodeResultJS | NodeMustGenerate | NodeClobbersWorld) \
211 macro(ResolveBaseStrictPut, NodeResultJS | NodeMustGenerate | NodeClobbersWorld) \
212 macro(ResolveGlobal, NodeResultJS | NodeMustGenerate | NodeClobbersWorld) \
214 /* Nodes for misc operations. */\
215 macro(Breakpoint, NodeMustGenerate | NodeClobbersWorld) \
216 macro(CheckHasInstance, NodeMustGenerate) \
217 macro(InstanceOf, NodeResultBoolean) \
218 macro(IsUndefined, NodeResultBoolean) \
219 macro(IsBoolean, NodeResultBoolean) \
220 macro(IsNumber, NodeResultBoolean) \
221 macro(IsString, NodeResultBoolean) \
222 macro(IsObject, NodeResultBoolean) \
223 macro(IsFunction, NodeResultBoolean) \
224 macro(TypeOf, NodeResultJS) \
225 macro(LogicalNot, NodeResultBoolean) \
226 macro(ToPrimitive, NodeResultJS | NodeMustGenerate | NodeClobbersWorld) \
227 macro(ToString, NodeResultJS | NodeMustGenerate | NodeMightClobber) \
228 macro(NewStringObject, NodeResultJS) \
229 macro(MakeRope, NodeResultJS) \
231 /* Nodes used for activations. Activation support works by having it anchored at */\
232 /* epilgoues via TearOffActivation, and all CreateActivation nodes kept alive by */\
233 /* being threaded with each other. */\
234 macro(CreateActivation, NodeResultJS) \
235 macro(TearOffActivation, NodeMustGenerate) \
237 /* Nodes used for arguments. Similar to activation support, only it makes even less */\
239 macro(CreateArguments, NodeResultJS) \
240 macro(PhantomArguments, NodeResultJS | NodeDoesNotExit) \
241 macro(TearOffArguments, NodeMustGenerate) \
242 macro(GetMyArgumentsLength, NodeResultJS | NodeMustGenerate) \
243 macro(GetMyArgumentByVal, NodeResultJS | NodeMustGenerate) \
244 macro(GetMyArgumentsLengthSafe, NodeResultJS | NodeMustGenerate | NodeClobbersWorld) \
245 macro(GetMyArgumentByValSafe, NodeResultJS | NodeMustGenerate | NodeClobbersWorld) \
246 macro(CheckArgumentsNotCreated, NodeMustGenerate) \
248 /* Nodes for creating functions. */\
249 macro(NewFunctionNoCheck, NodeResultJS) \
250 macro(NewFunction, NodeResultJS) \
251 macro(NewFunctionExpression, NodeResultJS) \
253 /* Block terminals. */\
254 macro(Jump, NodeMustGenerate) \
255 macro(Branch, NodeMustGenerate) \
256 macro(Return, NodeMustGenerate) \
257 macro(Throw, NodeMustGenerate) \
258 macro(ThrowReferenceError, NodeMustGenerate) \
260 macro(GarbageValue, NodeResultJS | NodeClobbersWorld) \
262 /* Count execution. */\
263 macro(CountExecution, NodeMustGenerate) \
265 /* This is a pseudo-terminal. It means that execution should fall out of DFG at */\
266 /* this point, but execution does continue in the basic block - just in a */\
267 /* different compiler. */\
268 macro(ForceOSRExit, NodeMustGenerate) \
270 /* Checks the watchdog timer. If the timer has fired, we OSR exit to the */ \
271 /* baseline JIT to redo the watchdog timer check, and service the timer. */ \
272 macro(CheckWatchdogTimer, NodeMustGenerate) \
274 // This enum generates a monotonically increasing id for all Node types,
275 // and is used by the subsequent enum to fill out the id (as accessed via the NodeIdMask).
277 #define DFG_OP_ENUM(opcode, flags) opcode,
278 FOR_EACH_DFG_OP(DFG_OP_ENUM)
283 // Specifies the default flags for each node.
284 inline NodeFlags defaultFlags(NodeType op)
287 #define DFG_OP_ENUM(opcode, flags) case opcode: return flags;
288 FOR_EACH_DFG_OP(DFG_OP_ENUM)
291 RELEASE_ASSERT_NOT_REACHED();
296 inline bool needsOSRBackwardRewiring(NodeType op)
298 return op == UInt32ToNumber;
301 inline bool needsOSRForwardRewiring(NodeType op)
305 case ForwardInt32ToDouble:
315 } } // namespace JSC::DFG
317 #endif // ENABLE(DFG_JIT)
319 #endif // DFGNodeType_h