1/*
2 * Copyright (C) 2012, 2013, 2014 Apple Inc. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
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.
12 *
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.
24 */
25
26#ifndef DFGNodeType_h
27#define DFGNodeType_h
28
29#if ENABLE(DFG_JIT)
30
31#include "DFGNodeFlags.h"
32
33namespace JSC { namespace DFG {
34
35// This macro defines a set of information about all known node types, used to populate NodeId, NodeType below.
36#define FOR_EACH_DFG_OP(macro) \
37    /* A constant in the CodeBlock's constant pool. */\
38    macro(JSConstant, NodeResultJS | NodeDoesNotExit) \
39    \
40    /* Constants with specific representations. */\
41    macro(DoubleConstant, NodeResultDouble | NodeDoesNotExit) \
42    macro(Int52Constant, NodeResultInt52 | NodeDoesNotExit) \
43    \
44    /* A constant not in the CodeBlock's constant pool. Uses get patched to jumps that exit the */\
45    /* code block. */\
46    macro(WeakJSConstant, NodeResultJS | NodeDoesNotExit) \
47    \
48    /* Marker to indicate that an operation was optimized entirely and all that is left */\
49    /* is to make one node alias another. CSE will later usually eliminate this node, */\
50    /* though it may choose not to if it would corrupt predictions (very rare). */\
51    macro(Identity, NodeResultJS) \
52    \
53    /* Nodes for handling functions (both as call and as construct). */\
54    macro(ToThis, NodeResultJS) \
55    macro(CreateThis, NodeResultJS) /* Note this is not MustGenerate since we're returning it anyway. */ \
56    macro(GetCallee, NodeResultJS) \
57    \
58    /* Nodes for local variable access. These nodes are linked together using Phi nodes. */\
59    /* Any two nodes that are part of the same Phi graph will share the same */\
60    /* VariableAccessData, and thus will share predictions. */\
61    macro(GetLocal, NodeResultJS) \
62    macro(SetLocal, 0) \
63    macro(MovHint, NodeDoesNotExit) \
64    macro(ZombieHint, NodeDoesNotExit) \
65    macro(GetArgument, NodeResultJS | NodeMustGenerate) \
66    macro(Phantom, NodeMustGenerate) \
67    macro(HardPhantom, NodeMustGenerate) /* Like Phantom, but we never remove any of its children. */ \
68    macro(Check, 0) /* Used if we want just a type check but not liveness. DCE eithers kills this or converts it to Phantom. */\
69    macro(Upsilon, NodeDoesNotExit | NodeRelevantToOSR) \
70    macro(Phi, NodeDoesNotExit | NodeRelevantToOSR) \
71    macro(Flush, NodeMustGenerate | NodeDoesNotExit) \
72    macro(PhantomLocal, NodeMustGenerate | NodeDoesNotExit) \
73    \
74    /* Hint that this is where bytecode thinks is a good place to OSR. Note that this */\
75    /* will exist even in inlined loops. This has no execution semantics but it must */\
76    /* survive all DCE. We treat this as being a can-exit because tier-up to FTL may */\
77    /* want all state. */\
78    macro(LoopHint, NodeMustGenerate) \
79    \
80    /* Special node for OSR entry into the FTL. Indicates that we're loading a local */\
81    /* variable from the scratch buffer. */\
82    macro(ExtractOSREntryLocal, NodeResultJS) \
83    \
84    /* Tier-up checks from the DFG to the FTL. */\
85    macro(CheckTierUpInLoop, NodeMustGenerate) \
86    macro(CheckTierUpAndOSREnter, NodeMustGenerate) \
87    macro(CheckTierUpAtReturn, NodeMustGenerate) \
88    \
89    /* Get the value of a local variable, without linking into the VariableAccessData */\
90    /* network. This is only valid for variable accesses whose predictions originated */\
91    /* as something other than a local access, and thus had their own profiling. */\
92    macro(GetLocalUnlinked, NodeResultJS) \
93    \
94    /* Marker for an argument being set at the prologue of a function. */\
95    macro(SetArgument, NodeDoesNotExit) \
96    \
97    /* Marker of location in the IR where we may possibly perform jump replacement to */\
98    /* invalidate this code block. */\
99    macro(InvalidationPoint, NodeMustGenerate) \
100    \
101    /* Nodes for bitwise operations. */\
102    macro(BitAnd, NodeResultInt32) \
103    macro(BitOr, NodeResultInt32) \
104    macro(BitXor, NodeResultInt32) \
105    macro(BitLShift, NodeResultInt32) \
106    macro(BitRShift, NodeResultInt32) \
107    macro(BitURShift, NodeResultInt32) \
108    /* Bitwise operators call ToInt32 on their operands. */\
109    macro(ValueToInt32, NodeResultInt32) \
110    /* Used to box the result of URShift nodes (result has range 0..2^32-1). */\
111    macro(UInt32ToNumber, NodeResultNumber) \
112    /* Converts booleans to numbers but passes everything else through. */\
113    macro(BooleanToNumber, NodeResultJS) \
114    \
115    /* Attempt to truncate a double to int32; this will exit if it can't do it. */\
116    macro(DoubleAsInt32, NodeResultInt32) \
117    \
118    /* Change the representation of a value. */\
119    macro(DoubleRep, NodeResultDouble) \
120    macro(Int52Rep, NodeResultInt52) \
121    macro(ValueRep, NodeResultJS) \
122    \
123    /* Bogus type asserting node. Useful for testing, disappears during Fixup. */\
124    macro(FiatInt52, NodeResultJS) \
125    \
126    /* Nodes for arithmetic operations. */\
127    macro(ArithAdd, NodeResultNumber) \
128    macro(ArithSub, NodeResultNumber) \
129    macro(ArithNegate, NodeResultNumber) \
130    macro(ArithMul, NodeResultNumber) \
131    macro(ArithIMul, NodeResultInt32) \
132    macro(ArithDiv, NodeResultNumber) \
133    macro(ArithMod, NodeResultNumber) \
134    macro(ArithAbs, NodeResultNumber) \
135    macro(ArithMin, NodeResultNumber) \
136    macro(ArithMax, NodeResultNumber) \
137    macro(ArithFRound, NodeResultNumber) \
138    macro(ArithSqrt, NodeResultNumber) \
139    macro(ArithSin, NodeResultNumber) \
140    macro(ArithCos, NodeResultNumber) \
141    \
142    /* Add of values may either be arithmetic, or result in string concatenation. */\
143    macro(ValueAdd, NodeResultJS | NodeMustGenerate | NodeClobbersWorld) \
144    \
145    /* Property access. */\
146    /* PutByValAlias indicates a 'put' aliases a prior write to the same property. */\
147    /* Since a put to 'length' may invalidate optimizations here, */\
148    /* this must be the directly subsequent property put. Note that PutByVal */\
149    /* opcodes use VarArgs beause they may have up to 4 children. */\
150    macro(GetByVal, NodeResultJS | NodeMustGenerate | NodeMightClobber) \
151    macro(PutByValDirect, NodeMustGenerate | NodeHasVarArgs | NodeMightClobber) \
152    macro(PutByVal, NodeMustGenerate | NodeHasVarArgs | NodeMightClobber) \
153    macro(PutByValAlias, NodeMustGenerate | NodeHasVarArgs | NodeMightClobber) \
154    macro(GetById, NodeResultJS | NodeMustGenerate | NodeClobbersWorld) \
155    macro(GetByIdFlush, NodeResultJS | NodeMustGenerate | NodeClobbersWorld) \
156    macro(PutById, NodeMustGenerate | NodeClobbersWorld) \
157    macro(PutByIdFlush, NodeMustGenerate | NodeMustGenerate | NodeClobbersWorld) \
158    macro(PutByIdDirect, NodeMustGenerate | NodeClobbersWorld) \
159    macro(CheckStructure, NodeMustGenerate) \
160    macro(CheckExecutable, NodeMustGenerate) \
161    /* Transition watchpoints are a contract between the party setting the watchpoint */\
162    /* and the runtime system, where the party promises that the child object once had */\
163    /* the structure being watched, and the runtime system in turn promises that the */\
164    /* watchpoint will be turned into an OSR exit if any object with that structure */\
165    /* ever transitions to a different structure. Hence, the child object must have */\
166    /* previously had a CheckStructure executed on it or we're dealing with an object */\
167    /* constant (WeakJSConstant) and the object was known to have that structure at */\
168    /* compile-time. In the latter case this means that no structure checks have to be */\
169    /* performed for this object by JITted code. In the former case this means that*/\
170    /* the object's structure does not need to be rechecked due to side-effecting */\
171    /* (clobbering) operations. */\
172    macro(StructureTransitionWatchpoint, NodeMustGenerate) \
173    macro(PutStructure, NodeMustGenerate) \
174    macro(PhantomPutStructure, NodeMustGenerate | NodeDoesNotExit) \
175    macro(AllocatePropertyStorage, NodeMustGenerate | NodeDoesNotExit | NodeResultStorage) \
176    macro(ReallocatePropertyStorage, NodeMustGenerate | NodeDoesNotExit | NodeResultStorage) \
177    macro(GetButterfly, NodeResultStorage) \
178    macro(CheckArray, NodeMustGenerate) \
179    macro(Arrayify, NodeMustGenerate) \
180    macro(ArrayifyToStructure, NodeMustGenerate) \
181    macro(GetIndexedPropertyStorage, NodeResultStorage) \
182    macro(ConstantStoragePointer, NodeResultStorage) \
183    macro(TypedArrayWatchpoint, NodeMustGenerate) \
184    macro(GetByOffset, NodeResultJS) \
185    macro(MultiGetByOffset, NodeResultJS) \
186    macro(PutByOffset, NodeMustGenerate) \
187    macro(MultiPutByOffset, NodeMustGenerate) \
188    macro(GetArrayLength, NodeResultInt32) \
189    macro(GetTypedArrayByteOffset, NodeResultInt32) \
190    macro(GetScope, NodeResultJS) \
191    macro(GetMyScope, NodeResultJS) \
192    macro(SkipTopScope, NodeResultJS) \
193    macro(SkipScope, NodeResultJS) \
194    macro(GetClosureRegisters, NodeResultStorage) \
195    macro(GetClosureVar, NodeResultJS) \
196    macro(PutClosureVar, NodeMustGenerate) \
197    macro(GetGlobalVar, NodeResultJS) \
198    macro(PutGlobalVar, NodeMustGenerate) \
199    macro(NotifyWrite, NodeMustGenerate) \
200    macro(VariableWatchpoint, NodeMustGenerate) \
201    macro(VarInjectionWatchpoint, NodeMustGenerate) \
202    macro(FunctionReentryWatchpoint, NodeMustGenerate) \
203    macro(CheckFunction, NodeMustGenerate) \
204    macro(AllocationProfileWatchpoint, NodeMustGenerate) \
205    macro(CheckInBounds, NodeMustGenerate) \
206    \
207    /* Optimizations for array mutation. */\
208    macro(ArrayPush, NodeResultJS | NodeMustGenerate | NodeClobbersWorld) \
209    macro(ArrayPop, NodeResultJS | NodeMustGenerate | NodeClobbersWorld) \
210    \
211    /* Optimizations for regular expression matching. */\
212    macro(RegExpExec, NodeResultJS | NodeMustGenerate) \
213    macro(RegExpTest, NodeResultJS | NodeMustGenerate) \
214    \
215    /* Optimizations for string access */ \
216    macro(StringCharCodeAt, NodeResultInt32) \
217    macro(StringCharAt, NodeResultJS) \
218    macro(StringFromCharCode, NodeResultJS) \
219    \
220    /* Nodes for comparison operations. */\
221    macro(CompareLess, NodeResultBoolean | NodeMustGenerate | NodeClobbersWorld) \
222    macro(CompareLessEq, NodeResultBoolean | NodeMustGenerate | NodeClobbersWorld) \
223    macro(CompareGreater, NodeResultBoolean | NodeMustGenerate | NodeClobbersWorld) \
224    macro(CompareGreaterEq, NodeResultBoolean | NodeMustGenerate | NodeClobbersWorld) \
225    macro(CompareEq, NodeResultBoolean | NodeMustGenerate | NodeClobbersWorld) \
226    macro(CompareEqConstant, NodeResultBoolean) \
227    macro(CompareStrictEq, NodeResultBoolean) \
228    \
229    /* Calls. */\
230    macro(Call, NodeResultJS | NodeMustGenerate | NodeHasVarArgs | NodeClobbersWorld) \
231    macro(Construct, NodeResultJS | NodeMustGenerate | NodeHasVarArgs | NodeClobbersWorld) \
232    \
233    /* Allocations. */\
234    macro(NewObject, NodeResultJS) \
235    macro(NewArray, NodeResultJS | NodeHasVarArgs) \
236    macro(NewArrayWithSize, NodeResultJS | NodeMustGenerate) \
237    macro(NewArrayBuffer, NodeResultJS) \
238    macro(NewTypedArray, NodeResultJS | NodeClobbersWorld | NodeMustGenerate) \
239    macro(NewRegexp, NodeResultJS) \
240    \
241    /* Nodes for misc operations. */\
242    macro(Breakpoint, NodeMustGenerate) \
243    macro(ProfileWillCall, NodeMustGenerate) \
244    macro(ProfileDidCall, NodeMustGenerate) \
245    macro(CheckHasInstance, NodeMustGenerate) \
246    macro(InstanceOf, NodeResultBoolean) \
247    macro(IsUndefined, NodeResultBoolean) \
248    macro(IsBoolean, NodeResultBoolean) \
249    macro(IsNumber, NodeResultBoolean) \
250    macro(IsString, NodeResultBoolean) \
251    macro(IsObject, NodeResultBoolean) \
252    macro(IsFunction, NodeResultBoolean) \
253    macro(TypeOf, NodeResultJS) \
254    macro(LogicalNot, NodeResultBoolean) \
255    macro(ToPrimitive, NodeResultJS | NodeMustGenerate | NodeClobbersWorld) \
256    macro(ToString, NodeResultJS | NodeMustGenerate | NodeMightClobber) \
257    macro(NewStringObject, NodeResultJS) \
258    macro(MakeRope, NodeResultJS) \
259    macro(In, NodeResultBoolean | NodeMustGenerate | NodeClobbersWorld) \
260    \
261    /* Nodes used for activations. Activation support works by having it anchored at */\
262    /* epilgoues via TearOffActivation, and all CreateActivation nodes kept alive by */\
263    /* being threaded with each other. */\
264    macro(CreateActivation, NodeResultJS) \
265    macro(TearOffActivation, NodeMustGenerate) \
266    \
267    /* Nodes used for arguments. Similar to activation support, only it makes even less */\
268    /* sense. */\
269    macro(CreateArguments, NodeResultJS) \
270    macro(PhantomArguments, NodeResultJS | NodeDoesNotExit) \
271    macro(TearOffArguments, NodeMustGenerate) \
272    macro(GetMyArgumentsLength, NodeResultJS | NodeMustGenerate) \
273    macro(GetMyArgumentByVal, NodeResultJS | NodeMustGenerate) \
274    macro(GetMyArgumentsLengthSafe, NodeResultJS | NodeMustGenerate | NodeClobbersWorld) \
275    macro(GetMyArgumentByValSafe, NodeResultJS | NodeMustGenerate | NodeClobbersWorld) \
276    macro(CheckArgumentsNotCreated, NodeMustGenerate) \
277    \
278    /* Nodes for creating functions. */\
279    macro(NewFunctionNoCheck, NodeResultJS) \
280    macro(NewFunction, NodeResultJS) \
281    macro(NewFunctionExpression, NodeResultJS) \
282    \
283    /* These aren't terminals but always exit */ \
284    macro(Throw, NodeMustGenerate) \
285    macro(ThrowReferenceError, NodeMustGenerate) \
286    \
287    /* Block terminals. */\
288    macro(Jump, NodeMustGenerate) \
289    macro(Branch, NodeMustGenerate) \
290    macro(Switch, NodeMustGenerate) \
291    macro(Return, NodeMustGenerate) \
292    macro(Unreachable, NodeMustGenerate) \
293    \
294    /* Count execution. */\
295    macro(CountExecution, NodeMustGenerate) \
296    \
297    /* This is a pseudo-terminal. It means that execution should fall out of DFG at */\
298    /* this point, but execution does continue in the basic block - just in a */\
299    /* different compiler. */\
300    macro(ForceOSRExit, NodeMustGenerate) \
301    \
302    /* Checks the watchdog timer. If the timer has fired, we OSR exit to the */ \
303    /* baseline JIT to redo the watchdog timer check, and service the timer. */ \
304    macro(CheckWatchdogTimer, NodeMustGenerate) \
305    /* Write barriers ! */\
306    macro(StoreBarrier, NodeMustGenerate) \
307    macro(StoreBarrierWithNullCheck, NodeMustGenerate) \
308
309// This enum generates a monotonically increasing id for all Node types,
310// and is used by the subsequent enum to fill out the id (as accessed via the NodeIdMask).
311enum NodeType {
312#define DFG_OP_ENUM(opcode, flags) opcode,
313    FOR_EACH_DFG_OP(DFG_OP_ENUM)
314#undef DFG_OP_ENUM
315    LastNodeType
316};
317
318// Specifies the default flags for each node.
319inline NodeFlags defaultFlags(NodeType op)
320{
321    switch (op) {
322#define DFG_OP_ENUM(opcode, flags) case opcode: return flags;
323    FOR_EACH_DFG_OP(DFG_OP_ENUM)
324#undef DFG_OP_ENUM
325    default:
326        RELEASE_ASSERT_NOT_REACHED();
327        return 0;
328    }
329}
330
331} } // namespace JSC::DFG
332
333#endif // ENABLE(DFG_JIT)
334
335#endif // DFGNodeType_h
336
337