Remove excessive headers from JavaScriptCore
[WebKit-https.git] / Source / JavaScriptCore / dfg / DFGCommon.h
1 /*
2  * Copyright (C) 2011-2016 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 #pragma once
27
28 #include "DFGCompilationMode.h"
29
30 #if ENABLE(DFG_JIT)
31
32 #include "Options.h"
33 #include <limits.h>
34 #include <wtf/text/StringImpl.h>
35
36 namespace JSC { namespace DFG {
37
38 struct Node;
39
40 typedef uint32_t BlockIndex;
41 static const BlockIndex NoBlock = UINT_MAX;
42
43 // Use RefChildren if the child ref counts haven't already been adjusted using
44 // other means and either of the following is true:
45 // - The node you're creating is MustGenerate.
46 // - The place where you're inserting a reference to the node you're creating
47 //   will not also do RefChildren.
48 enum RefChildrenMode {
49     RefChildren,
50     DontRefChildren
51 };
52
53 // Use RefNode if you know that the node will be used from another node, and you
54 // will not already be ref'ing the node to account for that use.
55 enum RefNodeMode {
56     RefNode,
57     DontRefNode
58 };
59
60 enum SwitchKind {
61     SwitchImm,
62     SwitchChar,
63     SwitchString,
64     SwitchCell
65 };
66
67 inline bool verboseCompilationEnabled(CompilationMode mode = DFGMode)
68 {
69     return Options::verboseCompilation() || Options::dumpGraphAtEachPhase() || (isFTL(mode) && Options::verboseFTLCompilation());
70 }
71
72 inline bool logCompilationChanges(CompilationMode mode = DFGMode)
73 {
74     return verboseCompilationEnabled(mode) || Options::logCompilationChanges();
75 }
76
77 inline bool shouldDumpGraphAtEachPhase(CompilationMode mode)
78 {
79     if (isFTL(mode))
80         return Options::dumpGraphAtEachPhase() || Options::dumpDFGFTLGraphAtEachPhase();
81     return Options::dumpGraphAtEachPhase() || Options::dumpDFGGraphAtEachPhase();
82 }
83
84 inline bool validationEnabled()
85 {
86 #if !ASSERT_DISABLED
87     return true;
88 #else
89     return Options::validateGraph() || Options::validateGraphAtEachPhase();
90 #endif
91 }
92
93 inline bool enableInt52()
94 {
95 #if USE(JSVALUE64)
96     return true;
97 #else
98     return false;
99 #endif
100 }
101
102 // The prediction propagator effectively does four passes, with the last pass
103 // being done by the separate FixuPhase.
104 enum PredictionPass {
105     // We're converging in a straight-forward forward flow fixpoint. This is the
106     // most conventional part of the propagator - it makes only monotonic decisions
107     // based on value profiles and rare case profiles. It ignores baseline JIT rare
108     // case profiles. The goal here is to develop a good guess of which variables
109     // are likely to be purely numerical, which generally doesn't require knowing
110     // the rare case profiles.
111     PrimaryPass,
112     
113     // At this point we know what is numerical and what isn't. Non-numerical inputs
114     // to arithmetic operations will not have useful information in the Baseline JIT
115     // rare case profiles because Baseline may take slow path on non-numerical
116     // inputs even if the DFG could handle the input on the fast path. Boolean
117     // inputs are the most obvious example. This pass of prediction propagation will
118     // use Baseline rare case profiles for purely numerical operations and it will
119     // ignore them for everything else. The point of this pass is to develop a good
120     // guess of which variables are likely to be doubles.
121     //
122     // This pass is intentionally weird and goes against what is considered good
123     // form when writing a static analysis: a new data flow of booleans will cause
124     // us to ignore rare case profiles except that by then, we will have already
125     // propagated double types based on our prior assumption that we shouldn't
126     // ignore rare cases. This probably won't happen because the PrimaryPass is
127     // almost certainly going to establish what is and isn't numerical. But it's
128     // conceivable that during this pass we will discover a new boolean data flow.
129     // This ends up being sound because the prediction propagator could literally
130     // make any guesses it wants and still be sound (worst case, we OSR exit more
131     // often or use too general of types are run a bit slower). This will converge
132     // because we force monotonicity on the types of nodes and variables. So, the
133     // worst thing that can happen is that we violate basic laws of theoretical
134     // decency.
135     RareCasePass,
136     
137     // At this point we know what is numerical and what isn't, and we also know what
138     // is a double and what isn't. So, we start forcing variables to be double.
139     // Doing so may have a cascading effect so this is a fixpoint. It's monotonic
140     // in the sense that once a variable is forced double, it cannot be forced in
141     // the other direction.
142     DoubleVotingPass,
143     
144     // This pass occurs once we have converged. At this point we are just installing
145     // type checks based on the conclusions we have already reached. It's important
146     // for this pass to reach the same conclusions that DoubleVotingPass reached.
147     FixupPass
148 };
149
150 enum StructureRegistrationState { HaveNotStartedRegistering, AllStructuresAreRegistered };
151
152 enum StructureRegistrationResult { StructureRegisteredNormally, StructureRegisteredAndWatched };
153
154 enum OptimizationFixpointState { BeforeFixpoint, FixpointNotConverged, FixpointConverged };
155
156 // Describes the form you can expect the entire graph to be in.
157 enum GraphForm {
158     // LoadStore form means that basic blocks may freely use GetLocal, SetLocal,
159     // GetLocalUnlinked, and Flush for accessing local variables and indicating
160     // where their live ranges ought to be. Data flow between local accesses is
161     // implicit. Liveness is only explicit at block heads (variablesAtHead).
162     // This is only used by the DFG simplifier and is only preserved by same.
163     //
164     // For example, LoadStore form gives no easy way to determine which SetLocal's
165     // flow into a GetLocal. As well, LoadStore form implies no restrictions on
166     // redundancy: you can freely emit multiple GetLocals, or multiple SetLocals
167     // (or any combination thereof) to the same local in the same block. LoadStore
168     // form does not require basic blocks to declare how they affect or use locals,
169     // other than implicitly by using the local ops and by preserving
170     // variablesAtHead. Finally, LoadStore allows flexibility in how liveness of
171     // locals is extended; for example you can replace a GetLocal with a Phantom
172     // and so long as the Phantom retains the GetLocal's children (i.e. the Phi
173     // most likely) then it implies that the local is still live but that it need
174     // not be stored to the stack necessarily. This implies that Phantom can
175     // reference nodes that have no result, as long as those nodes are valid
176     // GetLocal children (i.e. Phi, SetLocal, SetArgument).
177     //
178     // LoadStore form also implies that Phis need not have children. By default,
179     // they end up having no children if you enter LoadStore using the canonical
180     // way (call Graph::dethread).
181     //
182     // LoadStore form is suitable for CFG transformations, as well as strength
183     // reduction, folding, and CSE.
184     LoadStore,
185     
186     // ThreadedCPS form means that basic blocks list up-front which locals they
187     // expect to be live at the head, and which locals they make available at the
188     // tail. ThreadedCPS form also implies that:
189     //
190     // - GetLocals and SetLocals are not redundant within a basic block.
191     //
192     // - All GetLocals and Flushes are linked directly to the last access point
193     //   of the variable, which must not be another GetLocal.
194     //
195     // - Phantom(Phi) is not legal, but PhantomLocal is.
196     //
197     // ThreadedCPS form is suitable for data flow analysis (CFA, prediction
198     // propagation), register allocation, and code generation.
199     ThreadedCPS,
200     
201     // SSA form. See DFGSSAConversionPhase.h for a description.
202     SSA
203 };
204
205 // Describes the state of the UnionFind structure of VariableAccessData's.
206 enum UnificationState {
207     // BasicBlock-local accesses to variables are appropriately unified with each other.
208     LocallyUnified,
209     
210     // Unification has been performed globally.
211     GloballyUnified
212 };
213
214 // Describes how reference counts in the graph behave.
215 enum RefCountState {
216     // Everything has refCount() == 1.
217     EverythingIsLive,
218
219     // Set after DCE has run.
220     ExactRefCount
221 };
222
223 enum OperandSpeculationMode { AutomaticOperandSpeculation, ManualOperandSpeculation };
224
225 enum ProofStatus { NeedsCheck, IsProved };
226
227 inline bool isProved(ProofStatus proofStatus)
228 {
229     ASSERT(proofStatus == IsProved || proofStatus == NeedsCheck);
230     return proofStatus == IsProved;
231 }
232
233 inline ProofStatus proofStatusForIsProved(bool isProved)
234 {
235     return isProved ? IsProved : NeedsCheck;
236 }
237
238 enum KillStatus { DoesNotKill, DoesKill };
239
240 inline bool doesKill(KillStatus killStatus)
241 {
242     ASSERT(killStatus == DoesNotKill || killStatus == DoesKill);
243     return killStatus == DoesKill;
244 }
245
246 inline KillStatus killStatusForDoesKill(bool doesKill)
247 {
248     return doesKill ? DoesKill : DoesNotKill;
249 }
250
251 enum class PlanStage {
252     Initial,
253     AfterFixup
254 };
255
256 // If possible, this will acquire a lock to make sure that if multiple threads
257 // start crashing at the same time, you get coherent dump output. Use this only
258 // when you're forcing a crash with diagnostics.
259 void startCrashing();
260
261 JS_EXPORT_PRIVATE bool isCrashing();
262
263 struct NodeAndIndex {
264     NodeAndIndex()
265         : node(nullptr)
266         , index(UINT_MAX)
267     {
268     }
269     
270     NodeAndIndex(Node* node, unsigned index)
271         : node(node)
272         , index(index)
273     {
274         ASSERT(!node == (index == UINT_MAX));
275     }
276     
277     bool operator!() const
278     {
279         return !node;
280     }
281     
282     Node* node;
283     unsigned index;
284 };
285
286 // A less-than operator for strings that is useful for generating string switches. Sorts by <
287 // relation on characters. Ensures that if a is a prefix of b, then a < b.
288 bool stringLessThan(StringImpl& a, StringImpl& b);
289
290 } } // namespace JSC::DFG
291
292 namespace WTF {
293
294 void printInternal(PrintStream&, JSC::DFG::OptimizationFixpointState);
295 void printInternal(PrintStream&, JSC::DFG::GraphForm);
296 void printInternal(PrintStream&, JSC::DFG::UnificationState);
297 void printInternal(PrintStream&, JSC::DFG::RefCountState);
298 void printInternal(PrintStream&, JSC::DFG::ProofStatus);
299
300 } // namespace WTF
301
302 #endif // ENABLE(DFG_JIT)
303
304 namespace JSC { namespace DFG {
305
306 // Put things here that must be defined even if ENABLE(DFG_JIT) is false.
307
308 enum CapabilityLevel {
309     CannotCompile,
310     CanCompile,
311     CanCompileAndInline,
312     CapabilityLevelNotSet
313 };
314
315 inline bool canCompile(CapabilityLevel level)
316 {
317     switch (level) {
318     case CanCompile:
319     case CanCompileAndInline:
320         return true;
321     default:
322         return false;
323     }
324 }
325
326 inline bool canInline(CapabilityLevel level)
327 {
328     switch (level) {
329     case CanCompileAndInline:
330         return true;
331     default:
332         return false;
333     }
334 }
335
336 inline CapabilityLevel leastUpperBound(CapabilityLevel a, CapabilityLevel b)
337 {
338     switch (a) {
339     case CannotCompile:
340         return CannotCompile;
341     case CanCompile:
342         switch (b) {
343         case CanCompile:
344         case CanCompileAndInline:
345             return CanCompile;
346         default:
347             return CannotCompile;
348         }
349     case CanCompileAndInline:
350         return b;
351     case CapabilityLevelNotSet:
352         ASSERT_NOT_REACHED();
353         return CannotCompile;
354     }
355     ASSERT_NOT_REACHED();
356     return CannotCompile;
357 }
358
359 // Unconditionally disable DFG disassembly support if the DFG is not compiled in.
360 inline bool shouldDumpDisassembly(CompilationMode mode = DFGMode)
361 {
362 #if ENABLE(DFG_JIT)
363     return Options::dumpDisassembly() || Options::dumpDFGDisassembly() || (isFTL(mode) && Options::dumpFTLDisassembly());
364 #else
365     UNUSED_PARAM(mode);
366     return false;
367 #endif
368 }
369
370 } } // namespace JSC::DFG
371
372 namespace WTF {
373
374 void printInternal(PrintStream&, JSC::DFG::CapabilityLevel);
375
376 } // namespace WTF