Line data Source code
1 : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2 : * vim: set ts=8 sts=4 et sw=4 tw=99:
3 : * This Source Code Form is subject to the terms of the Mozilla Public
4 : * License, v. 2.0. If a copy of the MPL was not distributed with this
5 : * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 :
7 : #ifndef jit_IonOptimizationLevels_h
8 : #define jit_IonOptimizationLevels_h
9 :
10 : #include "mozilla/EnumeratedArray.h"
11 :
12 : #include "jsbytecode.h"
13 : #include "jstypes.h"
14 :
15 : #include "jit/JitOptions.h"
16 : #include "js/TypeDecls.h"
17 :
18 : namespace js {
19 : namespace jit {
20 :
21 : enum class OptimizationLevel : uint8_t
22 : {
23 : Normal,
24 : Wasm,
25 : Count,
26 : DontCompile
27 : };
28 :
29 : #ifdef JS_JITSPEW
30 : inline const char*
31 10 : OptimizationLevelString(OptimizationLevel level)
32 : {
33 10 : switch (level) {
34 : case OptimizationLevel::DontCompile:
35 0 : return "Optimization_DontCompile";
36 : case OptimizationLevel::Normal:
37 10 : return "Optimization_Normal";
38 : case OptimizationLevel::Wasm:
39 0 : return "Optimization_Wasm";
40 : case OptimizationLevel::Count:;
41 : }
42 0 : MOZ_CRASH("Invalid OptimizationLevel");
43 : }
44 : #endif
45 :
46 : class OptimizationInfo
47 : {
48 : public:
49 : OptimizationLevel level_;
50 :
51 : // Toggles whether Effective Address Analysis is performed.
52 : bool eaa_;
53 :
54 : // Toggles whether Alignment Mask Analysis is performed.
55 : bool ama_;
56 :
57 : // Toggles whether Edge Case Analysis is used.
58 : bool edgeCaseAnalysis_;
59 :
60 : // Toggles whether redundant checks get removed.
61 : bool eliminateRedundantChecks_;
62 :
63 : // Toggles whether interpreted scripts get inlined.
64 : bool inlineInterpreted_;
65 :
66 : // Toggles whether native scripts get inlined.
67 : bool inlineNative_;
68 :
69 : // Toggles whether eager unboxing of SIMD is used.
70 : bool eagerSimdUnbox_;
71 :
72 : // Toggles whether global value numbering is used.
73 : bool gvn_;
74 :
75 : // Toggles whether loop invariant code motion is performed.
76 : bool licm_;
77 :
78 : // Toggles whether Range Analysis is used.
79 : bool rangeAnalysis_;
80 :
81 : // Toggles whether loop unrolling is performed.
82 : bool loopUnrolling_;
83 :
84 : // Toggles whether instruction reordering is performed.
85 : bool reordering_;
86 :
87 : // Toggles whether Truncation based on Range Analysis is used.
88 : bool autoTruncate_;
89 :
90 : // Toggles whether sincos is used.
91 : bool sincos_;
92 :
93 : // Toggles whether sink is used.
94 : bool sink_;
95 :
96 : // Describes which register allocator to use.
97 : IonRegisterAllocator registerAllocator_;
98 :
99 : // The maximum total bytecode size of an inline call site. We use a lower
100 : // value if off-thread compilation is not available, to avoid stalling the
101 : // active thread.
102 : uint32_t inlineMaxBytecodePerCallSiteHelperThread_;
103 : uint32_t inlineMaxBytecodePerCallSiteActiveCooperatingThread_;
104 :
105 : // The maximum value we allow for baselineScript->inlinedBytecodeLength_
106 : // when inlining.
107 : uint16_t inlineMaxCalleeInlinedBytecodeLength_;
108 :
109 : // The maximum bytecode length we'll inline in a single compilation.
110 : uint32_t inlineMaxTotalBytecodeLength_;
111 :
112 : // The maximum bytecode length the caller may have,
113 : // before we stop inlining large functions in that caller.
114 : uint32_t inliningMaxCallerBytecodeLength_;
115 :
116 : // The maximum inlining depth.
117 : uint32_t maxInlineDepth_;
118 :
119 : // Toggles whether scalar replacement is used.
120 : bool scalarReplacement_;
121 :
122 : // The maximum inlining depth for functions.
123 : //
124 : // Inlining small functions has almost no compiling overhead
125 : // and removes the otherwise needed call overhead.
126 : // The value is currently very low.
127 : // Actually it is only needed to make sure we don't blow out the stack.
128 : uint32_t smallFunctionMaxInlineDepth_;
129 :
130 : // How many invocations or loop iterations are needed before functions
131 : // are compiled.
132 : uint32_t compilerWarmUpThreshold_;
133 :
134 : // Default compiler warmup threshold, unless it is overridden.
135 : static const uint32_t CompilerWarmupThreshold = 1000;
136 :
137 : // How many invocations or loop iterations are needed before small functions
138 : // are compiled.
139 : uint32_t compilerSmallFunctionWarmUpThreshold_;
140 :
141 : // Default small function compiler warmup threshold, unless it is overridden.
142 : static const uint32_t CompilerSmallFunctionWarmupThreshold = CompilerWarmupThreshold;
143 :
144 : // How many invocations or loop iterations are needed before calls
145 : // are inlined, as a fraction of compilerWarmUpThreshold.
146 : double inliningWarmUpThresholdFactor_;
147 :
148 : // How many invocations or loop iterations are needed before a function
149 : // is hot enough to recompile the outerScript to inline that function,
150 : // as a multiplication of inliningWarmUpThreshold.
151 : uint32_t inliningRecompileThresholdFactor_;
152 :
153 6 : OptimizationInfo()
154 6 : { }
155 :
156 : void initNormalOptimizationInfo();
157 : void initWasmOptimizationInfo();
158 :
159 321 : OptimizationLevel level() const {
160 321 : return level_;
161 : }
162 :
163 62 : bool inlineInterpreted() const {
164 62 : return inlineInterpreted_ && !JitOptions.disableInlining;
165 : }
166 :
167 116 : bool inlineNative() const {
168 116 : return inlineNative_ && !JitOptions.disableInlining;
169 : }
170 :
171 : uint32_t compilerWarmUpThreshold(JSScript* script, jsbytecode* pc = nullptr) const;
172 :
173 8 : bool eagerSimdUnboxEnabled() const {
174 8 : return eagerSimdUnbox_ && !JitOptions.disableEagerSimdUnbox;
175 : }
176 :
177 16 : bool gvnEnabled() const {
178 16 : return gvn_ && !JitOptions.disableGvn;
179 : }
180 :
181 16 : bool licmEnabled() const {
182 16 : return licm_ && !JitOptions.disableLicm;
183 : }
184 :
185 24 : bool rangeAnalysisEnabled() const {
186 24 : return rangeAnalysis_ && !JitOptions.disableRangeAnalysis;
187 : }
188 :
189 8 : bool loopUnrollingEnabled() const {
190 8 : return loopUnrolling_ && !JitOptions.disableLoopUnrolling;
191 : }
192 :
193 8 : bool instructionReorderingEnabled() const {
194 8 : return reordering_ && !JitOptions.disableInstructionReordering;
195 : }
196 :
197 8 : bool autoTruncateEnabled() const {
198 8 : return autoTruncate_ && rangeAnalysisEnabled();
199 : }
200 :
201 8 : bool sincosEnabled() const {
202 8 : return sincos_ && !JitOptions.disableSincos;
203 : }
204 :
205 8 : bool sinkEnabled() const {
206 8 : return sink_ && !JitOptions.disableSink;
207 : }
208 :
209 8 : bool eaaEnabled() const {
210 8 : return eaa_ && !JitOptions.disableEaa;
211 : }
212 :
213 8 : bool amaEnabled() const {
214 8 : return ama_ && !JitOptions.disableAma;
215 : }
216 :
217 8 : bool edgeCaseAnalysisEnabled() const {
218 8 : return edgeCaseAnalysis_ && !JitOptions.disableEdgeCaseAnalysis;
219 : }
220 :
221 8 : bool eliminateRedundantChecksEnabled() const {
222 8 : return eliminateRedundantChecks_;
223 : }
224 :
225 : bool flowAliasAnalysisEnabled() const {
226 : return !JitOptions.disableFlowAA;
227 : }
228 :
229 8 : IonRegisterAllocator registerAllocator() const {
230 8 : if (JitOptions.forcedRegisterAllocator.isSome())
231 0 : return JitOptions.forcedRegisterAllocator.ref();
232 8 : return registerAllocator_;
233 : }
234 :
235 8 : bool scalarReplacementEnabled() const {
236 8 : return scalarReplacement_ && !JitOptions.disableScalarReplacement;
237 : }
238 :
239 27 : uint32_t smallFunctionMaxInlineDepth() const {
240 27 : return smallFunctionMaxInlineDepth_;
241 : }
242 :
243 : bool isSmallFunction(JSScript* script) const;
244 :
245 6 : uint32_t maxInlineDepth() const {
246 6 : return maxInlineDepth_;
247 : }
248 :
249 48 : uint32_t inlineMaxBytecodePerCallSite(bool offThread) const {
250 0 : return (offThread || !JitOptions.limitScriptSize)
251 96 : ? inlineMaxBytecodePerCallSiteHelperThread_
252 48 : : inlineMaxBytecodePerCallSiteActiveCooperatingThread_;
253 : }
254 :
255 33 : uint16_t inlineMaxCalleeInlinedBytecodeLength() const {
256 33 : return inlineMaxCalleeInlinedBytecodeLength_;
257 : }
258 :
259 33 : uint32_t inlineMaxTotalBytecodeLength() const {
260 33 : return inlineMaxTotalBytecodeLength_;
261 : }
262 :
263 6 : uint32_t inliningMaxCallerBytecodeLength() const {
264 6 : return inliningMaxCallerBytecodeLength_;
265 : }
266 :
267 53 : uint32_t inliningWarmUpThreshold() const {
268 53 : uint32_t compilerWarmUpThreshold = compilerWarmUpThreshold_;
269 53 : if (JitOptions.forcedDefaultIonWarmUpThreshold.isSome())
270 0 : compilerWarmUpThreshold = JitOptions.forcedDefaultIonWarmUpThreshold.ref();
271 53 : return compilerWarmUpThreshold * inliningWarmUpThresholdFactor_;
272 : }
273 :
274 9 : uint32_t inliningRecompileThreshold() const {
275 9 : return inliningWarmUpThreshold() * inliningRecompileThresholdFactor_;
276 : }
277 : };
278 :
279 : class OptimizationLevelInfo
280 : {
281 : private:
282 : mozilla::EnumeratedArray<OptimizationLevel, OptimizationLevel::Count, OptimizationInfo> infos_;
283 :
284 : public:
285 : OptimizationLevelInfo();
286 :
287 8018 : const OptimizationInfo* get(OptimizationLevel level) const {
288 8018 : return &infos_[level];
289 : }
290 :
291 : OptimizationLevel nextLevel(OptimizationLevel level) const;
292 : OptimizationLevel firstLevel() const;
293 : bool isLastLevel(OptimizationLevel level) const;
294 : OptimizationLevel levelForScript(JSScript* script, jsbytecode* pc = nullptr) const;
295 : };
296 :
297 : extern OptimizationLevelInfo IonOptimizations;
298 :
299 : } // namespace jit
300 : } // namespace js
301 :
302 : #endif /* jit_IonOptimizationLevels_h */
|