]>
Commit | Line | Data |
---|---|---|
6fe7ccc8 | 1 | /* |
93a37866 | 2 | * Copyright (C) 2011, 2012, 2013 Apple Inc. All rights reserved. |
6fe7ccc8 A |
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 DFGCommon_h | |
27 | #define DFGCommon_h | |
28 | ||
29 | #include <wtf/Platform.h> | |
30 | ||
31 | #if ENABLE(DFG_JIT) | |
32 | ||
33 | #include "CodeOrigin.h" | |
93a37866 | 34 | #include "Options.h" |
6fe7ccc8 A |
35 | #include "VirtualRegister.h" |
36 | ||
37 | /* DFG_ENABLE() - turn on a specific features in the DFG JIT */ | |
93a37866 | 38 | #define DFG_ENABLE(DFG_FEATURE) (defined DFG_ENABLE_##DFG_FEATURE && DFG_ENABLE_##DFG_FEATURE) |
6fe7ccc8 A |
39 | |
40 | // Emit various logging information for debugging, including dumping the dataflow graphs. | |
41 | #define DFG_ENABLE_DEBUG_VERBOSE 0 | |
42 | // Emit dumps during propagation, in addition to just after. | |
43 | #define DFG_ENABLE_DEBUG_PROPAGATION_VERBOSE 0 | |
44 | // Emit logging for OSR exit value recoveries at every node, not just nodes that | |
45 | // actually has speculation checks. | |
46 | #define DFG_ENABLE_VERBOSE_VALUE_RECOVERIES 0 | |
47 | // Enable generation of dynamic checks into the instruction stream. | |
48 | #if !ASSERT_DISABLED | |
49 | #define DFG_ENABLE_JIT_ASSERT 1 | |
50 | #else | |
51 | #define DFG_ENABLE_JIT_ASSERT 0 | |
52 | #endif | |
53 | // Consistency check contents compiler data structures. | |
54 | #define DFG_ENABLE_CONSISTENCY_CHECK 0 | |
55 | // Emit a breakpoint into the head of every generated function, to aid debugging in GDB. | |
56 | #define DFG_ENABLE_JIT_BREAK_ON_EVERY_FUNCTION 0 | |
57 | // Emit a breakpoint into the head of every generated block, to aid debugging in GDB. | |
58 | #define DFG_ENABLE_JIT_BREAK_ON_EVERY_BLOCK 0 | |
59 | // Emit a breakpoint into the head of every generated node, to aid debugging in GDB. | |
60 | #define DFG_ENABLE_JIT_BREAK_ON_EVERY_NODE 0 | |
61 | // Emit a pair of xorPtr()'s on regT0 with the node index to make it easy to spot node boundaries in disassembled code. | |
62 | #define DFG_ENABLE_XOR_DEBUG_AID 0 | |
63 | // Emit a breakpoint into the speculation failure code. | |
64 | #define DFG_ENABLE_JIT_BREAK_ON_SPECULATION_FAILURE 0 | |
6fe7ccc8 A |
65 | // Disable the DFG JIT without having to touch Platform.h |
66 | #define DFG_DEBUG_LOCAL_DISBALE 0 | |
67 | // Enable OSR entry from baseline JIT. | |
68 | #define DFG_ENABLE_OSR_ENTRY ENABLE(DFG_JIT) | |
69 | // Generate stats on how successful we were in making use of the DFG jit, and remaining on the hot path. | |
70 | #define DFG_ENABLE_SUCCESS_STATS 0 | |
71 | // Enable verification that the DFG is able to insert code for control flow edges. | |
72 | #define DFG_ENABLE_EDGE_CODE_VERIFICATION 0 | |
6fe7ccc8 A |
73 | |
74 | namespace JSC { namespace DFG { | |
75 | ||
93a37866 | 76 | struct Node; |
6fe7ccc8 A |
77 | |
78 | typedef uint32_t BlockIndex; | |
79 | static const BlockIndex NoBlock = UINT_MAX; | |
80 | ||
93a37866 A |
81 | struct NodePointerTraits { |
82 | static Node* defaultValue() { return 0; } | |
83 | static void dump(Node* value, PrintStream& out); | |
6fe7ccc8 A |
84 | }; |
85 | ||
93a37866 A |
86 | // Use RefChildren if the child ref counts haven't already been adjusted using |
87 | // other means and either of the following is true: | |
88 | // - The node you're creating is MustGenerate. | |
89 | // - The place where you're inserting a reference to the node you're creating | |
90 | // will not also do RefChildren. | |
91 | enum RefChildrenMode { | |
92 | RefChildren, | |
93 | DontRefChildren | |
6fe7ccc8 A |
94 | }; |
95 | ||
93a37866 A |
96 | // Use RefNode if you know that the node will be used from another node, and you |
97 | // will not already be ref'ing the node to account for that use. | |
98 | enum RefNodeMode { | |
99 | RefNode, | |
100 | DontRefNode | |
101 | }; | |
102 | ||
103 | inline bool verboseCompilationEnabled() | |
6fe7ccc8 | 104 | { |
93a37866 A |
105 | #if DFG_ENABLE(DEBUG_VERBOSE) |
106 | return true; | |
107 | #else | |
108 | return Options::verboseCompilation() || Options::dumpGraphAtEachPhase(); | |
109 | #endif | |
6fe7ccc8 A |
110 | } |
111 | ||
93a37866 | 112 | inline bool logCompilationChanges() |
6fe7ccc8 | 113 | { |
93a37866 | 114 | #if DFG_ENABLE(DEBUG_VERBOSE) |
6fe7ccc8 A |
115 | return true; |
116 | #else | |
93a37866 | 117 | return verboseCompilationEnabled() || Options::logCompilationChanges(); |
6fe7ccc8 A |
118 | #endif |
119 | } | |
120 | ||
93a37866 A |
121 | inline bool shouldDumpGraphAtEachPhase() |
122 | { | |
123 | #if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE) | |
124 | return true; | |
125 | #else | |
126 | return Options::dumpGraphAtEachPhase(); | |
127 | #endif | |
128 | } | |
129 | ||
130 | inline bool validationEnabled() | |
131 | { | |
132 | #if !ASSERT_DISABLED | |
133 | return true; | |
134 | #else | |
135 | return Options::validateGraph() || Options::validateGraphAtEachPhase(); | |
136 | #endif | |
137 | } | |
138 | ||
139 | enum SpillRegistersMode { NeedToSpill, DontSpill }; | |
140 | ||
141 | enum NoResultTag { NoResult }; | |
142 | ||
143 | enum OptimizationFixpointState { BeforeFixpoint, FixpointNotConverged, FixpointConverged }; | |
144 | ||
145 | // Describes the form you can expect the entire graph to be in. | |
146 | enum GraphForm { | |
147 | // LoadStore form means that basic blocks may freely use GetLocal, SetLocal, | |
148 | // GetLocalUnlinked, and Flush for accessing local variables and indicating | |
149 | // where their live ranges ought to be. Data flow between local accesses is | |
150 | // implicit. Liveness is only explicit at block heads (variablesAtHead). | |
151 | // This is only used by the DFG simplifier and is only preserved by same. | |
152 | // | |
153 | // For example, LoadStore form gives no easy way to determine which SetLocal's | |
154 | // flow into a GetLocal. As well, LoadStore form implies no restrictions on | |
155 | // redundancy: you can freely emit multiple GetLocals, or multiple SetLocals | |
156 | // (or any combination thereof) to the same local in the same block. LoadStore | |
157 | // form does not require basic blocks to declare how they affect or use locals, | |
158 | // other than implicitly by using the local ops and by preserving | |
159 | // variablesAtHead. Finally, LoadStore allows flexibility in how liveness of | |
160 | // locals is extended; for example you can replace a GetLocal with a Phantom | |
161 | // and so long as the Phantom retains the GetLocal's children (i.e. the Phi | |
162 | // most likely) then it implies that the local is still live but that it need | |
163 | // not be stored to the stack necessarily. This implies that Phantom can | |
164 | // reference nodes that have no result, as long as those nodes are valid | |
165 | // GetLocal children (i.e. Phi, SetLocal, SetArgument). | |
166 | // | |
167 | // LoadStore form also implies that Phis need not have children. By default, | |
168 | // they end up having no children if you enter LoadStore using the canonical | |
169 | // way (call Graph::dethread). | |
170 | // | |
171 | // LoadStore form is suitable for CFG transformations, as well as strength | |
172 | // reduction, folding, and CSE. | |
173 | LoadStore, | |
174 | ||
175 | // ThreadedCPS form means that basic blocks list up-front which locals they | |
176 | // expect to be live at the head, and which locals they make available at the | |
177 | // tail. ThreadedCPS form also implies that: | |
178 | // | |
179 | // - GetLocals and SetLocals to uncaptured variables are not redundant within | |
180 | // a basic block. | |
181 | // | |
182 | // - All GetLocals and Flushes are linked directly to the last access point | |
183 | // of the variable, which must not be another GetLocal if the variable is | |
184 | // uncaptured. | |
185 | // | |
186 | // - Phantom(Phi) is not legal, but PhantomLocal is. | |
187 | // | |
188 | // ThreadedCPS form is suitable for data flow analysis (CFA, prediction | |
189 | // propagation), register allocation, and code generation. | |
190 | ThreadedCPS | |
191 | }; | |
192 | ||
193 | // Describes the state of the UnionFind structure of VariableAccessData's. | |
194 | enum UnificationState { | |
195 | // BasicBlock-local accesses to variables are appropriately unified with each other. | |
196 | LocallyUnified, | |
197 | ||
198 | // Unification has been performed globally. | |
199 | GloballyUnified | |
200 | }; | |
201 | ||
202 | // Describes how reference counts in the graph behave. | |
203 | enum RefCountState { | |
204 | // Everything has refCount() == 1. | |
205 | EverythingIsLive, | |
206 | ||
207 | // Set after DCE has run. | |
208 | ExactRefCount | |
209 | }; | |
210 | ||
211 | enum OperandSpeculationMode { AutomaticOperandSpeculation, ManualOperandSpeculation }; | |
212 | ||
213 | enum SpeculationDirection { ForwardSpeculation, BackwardSpeculation }; | |
214 | ||
215 | enum ProofStatus { NeedsCheck, IsProved }; | |
216 | ||
217 | inline bool isProved(ProofStatus proofStatus) | |
218 | { | |
219 | ASSERT(proofStatus == IsProved || proofStatus == NeedsCheck); | |
220 | return proofStatus == IsProved; | |
221 | } | |
222 | ||
223 | inline ProofStatus proofStatusForIsProved(bool isProved) | |
224 | { | |
225 | return isProved ? IsProved : NeedsCheck; | |
226 | } | |
227 | ||
228 | template<typename T, typename U> | |
229 | bool checkAndSet(T& left, U right) | |
230 | { | |
231 | if (left == right) | |
232 | return false; | |
233 | left = right; | |
234 | return true; | |
235 | } | |
236 | ||
6fe7ccc8 A |
237 | } } // namespace JSC::DFG |
238 | ||
93a37866 A |
239 | namespace WTF { |
240 | ||
241 | void printInternal(PrintStream&, JSC::DFG::OptimizationFixpointState); | |
242 | void printInternal(PrintStream&, JSC::DFG::GraphForm); | |
243 | void printInternal(PrintStream&, JSC::DFG::UnificationState); | |
244 | void printInternal(PrintStream&, JSC::DFG::RefCountState); | |
245 | void printInternal(PrintStream&, JSC::DFG::ProofStatus); | |
246 | ||
247 | } // namespace WTF | |
248 | ||
6fe7ccc8 A |
249 | #endif // ENABLE(DFG_JIT) |
250 | ||
93a37866 A |
251 | namespace JSC { namespace DFG { |
252 | ||
253 | // Put things here that must be defined even if ENABLE(DFG_JIT) is false. | |
254 | ||
255 | enum CapabilityLevel { CannotCompile, MayInline, CanCompile, CapabilityLevelNotSet }; | |
256 | ||
257 | // Unconditionally disable DFG disassembly support if the DFG is not compiled in. | |
258 | inline bool shouldShowDisassembly() | |
259 | { | |
260 | #if ENABLE(DFG_JIT) | |
261 | return Options::showDisassembly() || Options::showDFGDisassembly(); | |
262 | #else | |
263 | return false; | |
264 | #endif | |
265 | } | |
266 | ||
267 | } } // namespace JSC::DFG | |
268 | ||
6fe7ccc8 A |
269 | #endif // DFGCommon_h |
270 |