131edfc73299204a122fd0768cb2ff8b102276d3
[WebKit-https.git] / Source / JavaScriptCore / dfg / DFGNodeType.h
1 /*
2  * Copyright (C) 2012, 2013 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 #include <wtf/Platform.h>
30
31 #if ENABLE(DFG_JIT)
32
33 #include "DFGNodeFlags.h"
34
35 namespace JSC { namespace DFG {
36
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) \
41     \
42     /* A constant not in the CodeBlock's constant pool. Uses get patched to jumps that exit the */\
43     /* code block. */\
44     macro(WeakJSConstant, NodeResultJS | NodeDoesNotExit) \
45     \
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) \
50     \
51     /* Nodes for handling functions (both as call and as construct). */\
52     macro(ToThis, NodeResultJS) \
53     macro(CreateThis, NodeResultJS) /* Note this is not MustGenerate since we're returning it anyway. */ \
54     macro(GetCallee, NodeResultJS) \
55     \
56     /* Nodes for local variable access. These nodes are linked together using Phi nodes. */\
57     /* Any two nodes that are part of the same Phi graph will share the same */\
58     /* VariableAccessData, and thus will share predictions. */\
59     macro(GetLocal, NodeResultJS) \
60     macro(SetLocal, NodeExitsForward) \
61     macro(MovHintAndCheck, NodeMustGenerate | NodeExitsForward) \
62     macro(MovHint, NodeDoesNotExit) \
63     macro(ZombieHint, NodeDoesNotExit) \
64     macro(GetArgument, NodeResultJS | NodeMustGenerate) \
65     macro(Phantom, NodeMustGenerate) \
66     macro(Upsilon, NodeDoesNotExit | NodeRelevantToOSR) \
67     macro(Phi, NodeDoesNotExit | NodeRelevantToOSR) \
68     macro(Flush, NodeMustGenerate | NodeDoesNotExit) \
69     macro(PhantomLocal, NodeMustGenerate | NodeDoesNotExit) \
70     \
71     /* Hint that this is where bytecode thinks is a good place to OSR. Note that this */\
72     /* will exist even in inlined loops. This has no execution semantics but it must */\
73     /* survive all DCE. We treat this as being a can-exit because tier-up to FTL may */\
74     /* want all state. */\
75     macro(LoopHint, NodeMustGenerate) \
76     \
77     /* Special node for OSR entry into the FTL. Indicates that we're loading a local */\
78     /* variable from the scratch buffer. */\
79     macro(ExtractOSREntryLocal, NodeResultJS) \
80     \
81     /* Tier-up checks from the DFG to the FTL. */\
82     macro(CheckTierUpInLoop, NodeMustGenerate) \
83     macro(CheckTierUpAndOSREnter, NodeMustGenerate) \
84     macro(CheckTierUpAtReturn, NodeMustGenerate) \
85     \
86     /* Get the value of a local variable, without linking into the VariableAccessData */\
87     /* network. This is only valid for variable accesses whose predictions originated */\
88     /* as something other than a local access, and thus had their own profiling. */\
89     macro(GetLocalUnlinked, NodeResultJS) \
90     \
91     /* Marker for an argument being set at the prologue of a function. */\
92     macro(SetArgument, NodeDoesNotExit) \
93     \
94     /* Marker of location in the IR where we may possibly perform jump replacement to */\
95     /* invalidate this code block. */\
96     macro(InvalidationPoint, NodeMustGenerate) \
97     \
98     /* Nodes for bitwise operations. */\
99     macro(BitAnd, NodeResultInt32 | NodeMustGenerate) \
100     macro(BitOr, NodeResultInt32 | NodeMustGenerate) \
101     macro(BitXor, NodeResultInt32 | NodeMustGenerate) \
102     macro(BitLShift, NodeResultInt32 | NodeMustGenerate) \
103     macro(BitRShift, NodeResultInt32 | NodeMustGenerate) \
104     macro(BitURShift, NodeResultInt32 | NodeMustGenerate) \
105     /* Bitwise operators call ToInt32 on their operands. */\
106     macro(ValueToInt32, NodeResultInt32) \
107     /* Used to box the result of URShift nodes (result has range 0..2^32-1). */\
108     macro(UInt32ToNumber, NodeResultNumber | NodeExitsForward) \
109     \
110     /* Used to cast known integers to doubles, so as to separate the double form */\
111     /* of the value from the integer form. */\
112     macro(Int32ToDouble, NodeResultNumber) \
113     /* Used to speculate that a double value is actually an integer. */\
114     macro(DoubleAsInt32, NodeResultInt32 | NodeExitsForward) \
115     /* Used to separate representation and register allocation of Int52's represented */\
116     /* as values. */\
117     macro(Int52ToValue, NodeResultJS) \
118     macro(Int52ToDouble, NodeResultNumber) \
119     \
120     /* Nodes for arithmetic operations. */\
121     macro(ArithAdd, NodeResultNumber | NodeMustGenerate) \
122     macro(ArithSub, NodeResultNumber | NodeMustGenerate) \
123     macro(ArithNegate, NodeResultNumber | NodeMustGenerate) \
124     macro(ArithMul, NodeResultNumber | NodeMustGenerate) \
125     macro(ArithIMul, NodeResultInt32 | NodeMustGenerate) \
126     macro(ArithDiv, NodeResultNumber | NodeMustGenerate) \
127     macro(ArithMod, NodeResultNumber | NodeMustGenerate) \
128     macro(ArithAbs, NodeResultNumber | NodeMustGenerate) \
129     macro(ArithMin, NodeResultNumber | NodeMustGenerate) \
130     macro(ArithMax, NodeResultNumber | NodeMustGenerate) \
131     macro(ArithSqrt, NodeResultNumber | NodeMustGenerate) \
132     macro(ArithSin, NodeResultNumber | NodeMustGenerate) \
133     macro(ArithCos, NodeResultNumber | NodeMustGenerate) \
134     \
135     /* Add of values may either be arithmetic, or result in string concatenation. */\
136     macro(ValueAdd, NodeResultJS | NodeMustGenerate | NodeMightClobber) \
137     \
138     /* Property access. */\
139     /* PutByValAlias indicates a 'put' aliases a prior write to the same property. */\
140     /* Since a put to 'length' may invalidate optimizations here, */\
141     /* this must be the directly subsequent property put. Note that PutByVal */\
142     /* opcodes use VarArgs beause they may have up to 4 children. */\
143     macro(GetByVal, NodeResultJS | NodeMustGenerate | NodeMightClobber) \
144     macro(PutByValDirect, NodeMustGenerate | NodeHasVarArgs | NodeMightClobber) \
145     macro(PutByVal, NodeMustGenerate | NodeHasVarArgs | NodeMightClobber) \
146     macro(PutByValAlias, NodeMustGenerate | NodeHasVarArgs | NodeMightClobber) \
147     macro(GetById, NodeResultJS | NodeMustGenerate | NodeClobbersWorld) \
148     macro(GetByIdFlush, NodeResultJS | NodeMustGenerate | NodeClobbersWorld) \
149     macro(PutById, NodeMustGenerate | NodeClobbersWorld) \
150     macro(PutByIdDirect, NodeMustGenerate | NodeClobbersWorld) \
151     macro(CheckStructure, NodeMustGenerate) \
152     macro(CheckExecutable, NodeMustGenerate) \
153     /* Transition watchpoints are a contract between the party setting the watchpoint */\
154     /* and the runtime system, where the party promises that the child object once had */\
155     /* the structure being watched, and the runtime system in turn promises that the */\
156     /* watchpoint will be turned into an OSR exit if any object with that structure */\
157     /* ever transitions to a different structure. Hence, the child object must have */\
158     /* previously had a CheckStructure executed on it or we're dealing with an object */\
159     /* constant (WeakJSConstant) and the object was known to have that structure at */\
160     /* compile-time. In the latter case this means that no structure checks have to be */\
161     /* performed for this object by JITted code. In the former case this means that*/\
162     /* the object's structure does not need to be rechecked due to side-effecting */\
163     /* (clobbering) operations. */\
164     macro(StructureTransitionWatchpoint, NodeMustGenerate) \
165     macro(PutStructure, NodeMustGenerate) \
166     macro(PhantomPutStructure, NodeMustGenerate | NodeDoesNotExit) \
167     macro(AllocatePropertyStorage, NodeMustGenerate | NodeDoesNotExit | NodeResultStorage) \
168     macro(ReallocatePropertyStorage, NodeMustGenerate | NodeDoesNotExit | NodeResultStorage) \
169     macro(GetButterfly, NodeResultStorage) \
170     macro(CheckArray, NodeMustGenerate) \
171     macro(Arrayify, NodeMustGenerate) \
172     macro(ArrayifyToStructure, NodeMustGenerate) \
173     macro(GetIndexedPropertyStorage, NodeResultStorage) \
174     macro(ConstantStoragePointer, NodeResultStorage) \
175     macro(TypedArrayWatchpoint, NodeMustGenerate) \
176     macro(GetByOffset, NodeResultJS) \
177     macro(PutByOffset, NodeMustGenerate) \
178     macro(GetArrayLength, NodeResultInt32) \
179     macro(GetTypedArrayByteOffset, NodeResultInt32) \
180     macro(GetScope, NodeResultJS) \
181     macro(GetMyScope, NodeResultJS) \
182     macro(SkipTopScope, NodeResultJS) \
183     macro(SkipScope, NodeResultJS) \
184     macro(GetClosureRegisters, NodeResultStorage) \
185     macro(GetClosureVar, NodeResultJS) \
186     macro(PutClosureVar, NodeMustGenerate) \
187     macro(GetGlobalVar, NodeResultJS) \
188     macro(PutGlobalVar, NodeMustGenerate) \
189     macro(NotifyWrite, NodeMustGenerate) \
190     macro(VariableWatchpoint, NodeMustGenerate) \
191     macro(VarInjectionWatchpoint, NodeMustGenerate) \
192     macro(FunctionReentryWatchpoint, NodeMustGenerate) \
193     macro(CheckFunction, NodeMustGenerate) \
194     macro(AllocationProfileWatchpoint, NodeMustGenerate) \
195     macro(CheckInBounds, NodeMustGenerate) \
196     \
197     /* Optimizations for array mutation. */\
198     macro(ArrayPush, NodeResultJS | NodeMustGenerate | NodeClobbersWorld) \
199     macro(ArrayPop, NodeResultJS | NodeMustGenerate | NodeClobbersWorld) \
200     \
201     /* Optimizations for regular expression matching. */\
202     macro(RegExpExec, NodeResultJS | NodeMustGenerate) \
203     macro(RegExpTest, NodeResultJS | NodeMustGenerate) \
204     \
205     /* Optimizations for string access */ \
206     macro(StringCharCodeAt, NodeResultInt32) \
207     macro(StringCharAt, NodeResultJS) \
208     macro(StringFromCharCode, NodeResultJS) \
209     \
210     /* Nodes for comparison operations. */\
211     macro(CompareLess, NodeResultBoolean | NodeMustGenerate | NodeMightClobber) \
212     macro(CompareLessEq, NodeResultBoolean | NodeMustGenerate | NodeMightClobber) \
213     macro(CompareGreater, NodeResultBoolean | NodeMustGenerate | NodeMightClobber) \
214     macro(CompareGreaterEq, NodeResultBoolean | NodeMustGenerate | NodeMightClobber) \
215     macro(CompareEq, NodeResultBoolean | NodeMustGenerate | NodeMightClobber) \
216     macro(CompareEqConstant, NodeResultBoolean | NodeMustGenerate) \
217     macro(CompareStrictEq, NodeResultBoolean) \
218     macro(CompareStrictEqConstant, NodeResultBoolean) \
219     \
220     /* Calls. */\
221     macro(Call, NodeResultJS | NodeMustGenerate | NodeHasVarArgs | NodeClobbersWorld) \
222     macro(Construct, NodeResultJS | NodeMustGenerate | NodeHasVarArgs | NodeClobbersWorld) \
223     \
224     /* Allocations. */\
225     macro(NewObject, NodeResultJS) \
226     macro(NewArray, NodeResultJS | NodeHasVarArgs) \
227     macro(NewArrayWithSize, NodeResultJS) \
228     macro(NewArrayBuffer, NodeResultJS) \
229     macro(NewTypedArray, NodeResultJS | NodeClobbersWorld | NodeMustGenerate) \
230     macro(NewRegexp, NodeResultJS) \
231     \
232     /* Nodes for misc operations. */\
233     macro(Breakpoint, NodeMustGenerate | NodeClobbersWorld) \
234     macro(CheckHasInstance, NodeMustGenerate) \
235     macro(InstanceOf, NodeResultBoolean) \
236     macro(IsUndefined, NodeResultBoolean) \
237     macro(IsBoolean, NodeResultBoolean) \
238     macro(IsNumber, NodeResultBoolean) \
239     macro(IsString, NodeResultBoolean) \
240     macro(IsObject, NodeResultBoolean) \
241     macro(IsFunction, NodeResultBoolean) \
242     macro(TypeOf, NodeResultJS) \
243     macro(LogicalNot, NodeResultBoolean) \
244     macro(ToPrimitive, NodeResultJS | NodeMustGenerate | NodeClobbersWorld) \
245     macro(ToString, NodeResultJS | NodeMustGenerate | NodeMightClobber) \
246     macro(NewStringObject, NodeResultJS) \
247     macro(MakeRope, NodeResultJS) \
248     macro(In, NodeResultBoolean | NodeMustGenerate | NodeClobbersWorld) \
249     \
250     /* Nodes used for activations. Activation support works by having it anchored at */\
251     /* epilgoues via TearOffActivation, and all CreateActivation nodes kept alive by */\
252     /* being threaded with each other. */\
253     macro(CreateActivation, NodeResultJS) \
254     macro(TearOffActivation, NodeMustGenerate) \
255     \
256     /* Nodes used for arguments. Similar to activation support, only it makes even less */\
257     /* sense. */\
258     macro(CreateArguments, NodeResultJS) \
259     macro(PhantomArguments, NodeResultJS | NodeDoesNotExit) \
260     macro(TearOffArguments, NodeMustGenerate) \
261     macro(GetMyArgumentsLength, NodeResultJS | NodeMustGenerate) \
262     macro(GetMyArgumentByVal, NodeResultJS | NodeMustGenerate) \
263     macro(GetMyArgumentsLengthSafe, NodeResultJS | NodeMustGenerate | NodeClobbersWorld) \
264     macro(GetMyArgumentByValSafe, NodeResultJS | NodeMustGenerate | NodeClobbersWorld) \
265     macro(CheckArgumentsNotCreated, NodeMustGenerate) \
266     \
267     /* Nodes for creating functions. */\
268     macro(NewFunctionNoCheck, NodeResultJS) \
269     macro(NewFunction, NodeResultJS) \
270     macro(NewFunctionExpression, NodeResultJS) \
271     \
272     /* These aren't terminals but always exit */ \
273     macro(Throw, NodeMustGenerate) \
274     macro(ThrowReferenceError, NodeMustGenerate) \
275     \
276     /* Block terminals. */\
277     macro(Jump, NodeMustGenerate) \
278     macro(Branch, NodeMustGenerate) \
279     macro(Switch, NodeMustGenerate) \
280     macro(Return, NodeMustGenerate) \
281     macro(Unreachable, NodeMustGenerate) \
282     \
283     /* Count execution. */\
284     macro(CountExecution, NodeMustGenerate) \
285     \
286     /* This is a pseudo-terminal. It means that execution should fall out of DFG at */\
287     /* this point, but execution does continue in the basic block - just in a */\
288     /* different compiler. */\
289     macro(ForceOSRExit, NodeMustGenerate) \
290     \
291     /* Checks the watchdog timer. If the timer has fired, we OSR exit to the */ \
292     /* baseline JIT to redo the watchdog timer check, and service the timer. */ \
293     macro(CheckWatchdogTimer, NodeMustGenerate) \
294
295 // This enum generates a monotonically increasing id for all Node types,
296 // and is used by the subsequent enum to fill out the id (as accessed via the NodeIdMask).
297 enum NodeType {
298 #define DFG_OP_ENUM(opcode, flags) opcode,
299     FOR_EACH_DFG_OP(DFG_OP_ENUM)
300 #undef DFG_OP_ENUM
301     LastNodeType
302 };
303
304 // Specifies the default flags for each node.
305 inline NodeFlags defaultFlags(NodeType op)
306 {
307     switch (op) {
308 #define DFG_OP_ENUM(opcode, flags) case opcode: return flags;
309     FOR_EACH_DFG_OP(DFG_OP_ENUM)
310 #undef DFG_OP_ENUM
311     default:
312         RELEASE_ASSERT_NOT_REACHED();
313         return 0;
314     }
315 }
316
317 inline bool permitsOSRBackwardRewiring(NodeType op)
318 {
319     switch (op) {
320     case Identity:
321         RELEASE_ASSERT_NOT_REACHED();
322         return true;
323     case UInt32ToNumber:
324     case Int52ToValue:
325     case Int52ToDouble:
326         // These are the only node where we do:
327         //
328         //     b: UInt32ToNumber(@a)
329         //     c: SetLocal(@b)
330         //
331         // and then also have some uses of @a without Phantom'ing @b.
332         return true;
333     default:
334         return false;
335     }
336 }
337
338 // Returns the priority with which we should select the given node for forward
339 // rewiring. Higher is better. Zero means that the node is not useful for rewiring.
340 // By convention, we use 100 to mean that the node is totally equivalent to its
341 // input with no information loss.
342 inline unsigned forwardRewiringSelectionScore(NodeType op)
343 {
344     switch (op) {
345     case Identity:
346         // We shouldn't see these by the time we get to OSR even though it clearly
347         // is a perfect identity function.
348         RELEASE_ASSERT_NOT_REACHED();
349         return 100;
350         
351     case DoubleAsInt32:
352         // This speculates that the incoming double is convertible to an int32. So
353         // its result is totally equivalent.
354         return 100;
355         
356     case Int32ToDouble:
357         // This converts an int32 to a double, but that loses a bit of information.
358         // OTOH it's still an equivalent number.
359         return 75;
360         
361     case UInt32ToNumber:
362         // It's completely fine to use this for OSR exit, since the uint32 isn't
363         // actually representable in bytecode.
364         return 100;
365
366     case ValueToInt32:
367         // This loses information. Only use it if there are no better alternatives.
368         return 25;
369         
370     case Int52ToValue:
371         // Loses no information. It just boxes the value, which is what OSR wants
372         // to do anyway.
373         return 100;
374         
375     case Int52ToDouble:
376         // This is like Int32ToDouble; we can use it because it gives a semantically
377         // equivalent value but that value may be an int32 in a double, so we'd
378         // rather not if we can avoid it.
379         return 75;
380         
381     default:
382         return 0;
383     }
384 }
385
386 inline bool permitsOSRForwardRewiring(NodeType op)
387 {
388     return forwardRewiringSelectionScore(op) > 0;
389 }
390
391 } } // namespace JSC::DFG
392
393 #endif // ENABLE(DFG_JIT)
394
395 #endif // DFGNodeType_h
396