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 : #include "jit/JitOptions.h"
8 : #include "mozilla/TypeTraits.h"
9 :
10 : #include <cstdlib>
11 : #include "jsfun.h"
12 : using namespace js;
13 : using namespace js::jit;
14 :
15 : using mozilla::Maybe;
16 :
17 : namespace js {
18 : namespace jit {
19 :
20 3 : DefaultJitOptions JitOptions;
21 :
22 0 : static void Warn(const char* env, const char* value)
23 : {
24 0 : fprintf(stderr, "Warning: I didn't understand %s=\"%s\"\n", env, value);
25 0 : }
26 :
27 : template<typename T> struct IsBool : mozilla::FalseType {};
28 : template<> struct IsBool<bool> : mozilla::TrueType {};
29 :
30 : static Maybe<int>
31 0 : ParseInt(const char* str)
32 : {
33 : char* endp;
34 0 : int retval = strtol(str, &endp, 0);
35 0 : if (*endp == '\0')
36 0 : return mozilla::Some(retval);
37 0 : return mozilla::Nothing();
38 : }
39 :
40 : template<typename T>
41 300 : T overrideDefault(const char* param, T dflt) {
42 300 : char* str = getenv(param);
43 300 : if (!str)
44 300 : return dflt;
45 : if (IsBool<T>::value) {
46 0 : if (strcmp(str, "true") == 0 || strcmp(str, "yes") == 0)
47 0 : return true;
48 0 : if (strcmp(str, "false") == 0 || strcmp(str, "no") == 0)
49 0 : return false;
50 0 : Warn(param, str);
51 : } else {
52 0 : Maybe<int> value = ParseInt(str);
53 0 : if (value.isSome())
54 0 : return value.ref();
55 0 : Warn(param, str);
56 : }
57 0 : return dflt;
58 : }
59 :
60 : #define SET_DEFAULT(var, dflt) var = overrideDefault("JIT_OPTION_" #var, dflt)
61 6 : DefaultJitOptions::DefaultJitOptions()
62 : {
63 : // Whether to perform expensive graph-consistency DEBUG-only assertions.
64 : // It can be useful to disable this to reduce DEBUG-compile time of large
65 : // wasm programs.
66 6 : SET_DEFAULT(checkGraphConsistency, true);
67 :
68 : #ifdef CHECK_OSIPOINT_REGISTERS
69 : // Emit extra code to verify live regs at the start of a VM call
70 : // are not modified before its OsiPoint.
71 6 : SET_DEFAULT(checkOsiPointRegisters, false);
72 : #endif
73 :
74 : // Whether to enable extra code to perform dynamic validation of
75 : // RangeAnalysis results.
76 6 : SET_DEFAULT(checkRangeAnalysis, false);
77 :
78 : // Toggles whether IonBuilder fallbacks to a call if we fail to inline.
79 6 : SET_DEFAULT(disableInlineBacktracking, false);
80 :
81 : // Toggles whether Alignment Mask Analysis is globally disabled.
82 6 : SET_DEFAULT(disableAma, false);
83 :
84 : // Toggles whether Effective Address Analysis is globally disabled.
85 6 : SET_DEFAULT(disableEaa, false);
86 :
87 : // Toggle whether eager simd unboxing is globally disabled.
88 6 : SET_DEFAULT(disableEagerSimdUnbox, false);
89 :
90 : // Toggles whether Edge Case Analysis is gobally disabled.
91 6 : SET_DEFAULT(disableEdgeCaseAnalysis, false);
92 :
93 : // Toggles whether to use flow sensitive Alias Analysis.
94 6 : SET_DEFAULT(disableFlowAA, true);
95 :
96 : // Toggle whether global value numbering is globally disabled.
97 6 : SET_DEFAULT(disableGvn, false);
98 :
99 : // Toggles whether inlining is globally disabled.
100 6 : SET_DEFAULT(disableInlining, false);
101 :
102 : // Toggles whether loop invariant code motion is globally disabled.
103 6 : SET_DEFAULT(disableLicm, false);
104 :
105 : // Toggles whether Loop Unrolling is globally disabled.
106 6 : SET_DEFAULT(disableLoopUnrolling, true);
107 :
108 : // Toggles wheter optimization tracking is globally disabled.
109 6 : SET_DEFAULT(disableOptimizationTracking, true);
110 :
111 : // Toggle whether Profile Guided Optimization is globally disabled.
112 6 : SET_DEFAULT(disablePgo, false);
113 :
114 : // Toggles whether instruction reordering is globally disabled.
115 6 : SET_DEFAULT(disableInstructionReordering, false);
116 :
117 : // Toggles whether Range Analysis is globally disabled.
118 6 : SET_DEFAULT(disableRangeAnalysis, false);
119 :
120 : // Toggles wheter Recover instructions is globally disabled.
121 6 : SET_DEFAULT(disableRecoverIns, false);
122 :
123 : // Toggle whether eager scalar replacement is globally disabled.
124 6 : SET_DEFAULT(disableScalarReplacement, false);
125 :
126 : // Toggles whether CacheIR stubs are used.
127 6 : SET_DEFAULT(disableCacheIR, false);
128 :
129 : // Toggles whether shared stubs are used in Ionmonkey.
130 6 : SET_DEFAULT(disableSharedStubs, false);
131 :
132 : // Toggles whether sincos optimization is globally disabled.
133 : // See bug984018: The MacOS is the only one that has the sincos fast.
134 : #if defined(XP_MACOSX)
135 : SET_DEFAULT(disableSincos, false);
136 : #else
137 6 : SET_DEFAULT(disableSincos, true);
138 : #endif
139 :
140 : // Toggles whether sink code motion is globally disabled.
141 6 : SET_DEFAULT(disableSink, true);
142 :
143 : // Whether functions are compiled immediately.
144 6 : SET_DEFAULT(eagerCompilation, false);
145 :
146 : // Whether IonBuilder should prefer IC generation above specialized MIR.
147 6 : SET_DEFAULT(forceInlineCaches, false);
148 :
149 : // Toggles whether large scripts are rejected.
150 6 : SET_DEFAULT(limitScriptSize, true);
151 :
152 : // Toggles whether functions may be entered at loop headers.
153 6 : SET_DEFAULT(osr, true);
154 :
155 : // Whether to enable extra code to perform dynamic validations.
156 6 : SET_DEFAULT(runExtraChecks, false);
157 :
158 : // How many invocations or loop iterations are needed before functions
159 : // are compiled with the baseline compiler.
160 6 : SET_DEFAULT(baselineWarmUpThreshold, 10);
161 :
162 : // Number of exception bailouts (resuming into catch/finally block) before
163 : // we invalidate and forbid Ion compilation.
164 6 : SET_DEFAULT(exceptionBailoutThreshold, 10);
165 :
166 : // Number of bailouts without invalidation before we set
167 : // JSScript::hadFrequentBailouts and invalidate.
168 6 : SET_DEFAULT(frequentBailoutThreshold, 10);
169 :
170 : // Whether to run all debug checks in debug builds.
171 : // Disabling might make it more enjoyable to run JS in debug builds.
172 6 : SET_DEFAULT(fullDebugChecks, true);
173 :
174 : // How many actual arguments are accepted on the C stack.
175 6 : SET_DEFAULT(maxStackArgs, 4096);
176 :
177 : // How many times we will try to enter a script via OSR before
178 : // invalidating the script.
179 6 : SET_DEFAULT(osrPcMismatchesBeforeRecompile, 6000);
180 :
181 : // The bytecode length limit for small function.
182 6 : SET_DEFAULT(smallFunctionMaxBytecodeLength_, 130);
183 :
184 : // An artificial testing limit for the maximum supported offset of
185 : // pc-relative jump and call instructions.
186 6 : SET_DEFAULT(jumpThreshold, UINT32_MAX);
187 :
188 : // Whether the (ARM) simulators should always interrupt before executing any
189 : // instruction.
190 6 : SET_DEFAULT(simulatorAlwaysInterrupt, false);
191 :
192 : // Branch pruning heuristic is based on a scoring system, which is look at
193 : // different metrics and provide a score. The score is computed as a
194 : // projection where each factor defines the weight of each metric. Then this
195 : // score is compared against a threshold to prevent a branch from being
196 : // removed.
197 6 : SET_DEFAULT(branchPruningHitCountFactor, 1);
198 6 : SET_DEFAULT(branchPruningInstFactor, 10);
199 6 : SET_DEFAULT(branchPruningBlockSpanFactor, 100);
200 6 : SET_DEFAULT(branchPruningEffectfulInstFactor, 3500);
201 6 : SET_DEFAULT(branchPruningThreshold, 4000);
202 :
203 : // Force how many invocation or loop iterations are needed before compiling
204 : // a function with the highest ionmonkey optimization level.
205 : // (i.e. OptimizationLevel_Normal)
206 6 : const char* forcedDefaultIonWarmUpThresholdEnv = "JIT_OPTION_forcedDefaultIonWarmUpThreshold";
207 6 : if (const char* env = getenv(forcedDefaultIonWarmUpThresholdEnv)) {
208 0 : Maybe<int> value = ParseInt(env);
209 0 : if (value.isSome())
210 0 : forcedDefaultIonWarmUpThreshold.emplace(value.ref());
211 : else
212 0 : Warn(forcedDefaultIonWarmUpThresholdEnv, env);
213 : }
214 :
215 : // Same but for compiling small functions.
216 : const char* forcedDefaultIonSmallFunctionWarmUpThresholdEnv =
217 6 : "JIT_OPTION_forcedDefaultIonSmallFunctionWarmUpThreshold";
218 6 : if (const char* env = getenv(forcedDefaultIonSmallFunctionWarmUpThresholdEnv)) {
219 0 : Maybe<int> value = ParseInt(env);
220 0 : if (value.isSome())
221 0 : forcedDefaultIonSmallFunctionWarmUpThreshold.emplace(value.ref());
222 : else
223 0 : Warn(forcedDefaultIonSmallFunctionWarmUpThresholdEnv, env);
224 : }
225 :
226 : // Force the used register allocator instead of letting the optimization
227 : // pass decide.
228 6 : const char* forcedRegisterAllocatorEnv = "JIT_OPTION_forcedRegisterAllocator";
229 6 : if (const char* env = getenv(forcedRegisterAllocatorEnv)) {
230 0 : forcedRegisterAllocator = LookupRegisterAllocator(env);
231 0 : if (!forcedRegisterAllocator.isSome())
232 0 : Warn(forcedRegisterAllocatorEnv, env);
233 : }
234 :
235 : // Toggles whether unboxed plain objects can be created by the VM.
236 6 : SET_DEFAULT(disableUnboxedObjects, false);
237 :
238 : // Test whether Atomics are allowed in asm.js code.
239 6 : SET_DEFAULT(asmJSAtomicsEnable, false);
240 :
241 : // Test whether wasm int64 / double NaN bits testing is enabled.
242 6 : SET_DEFAULT(wasmTestMode, false);
243 :
244 : // Test whether wasm bounds check should always be generated.
245 6 : SET_DEFAULT(wasmAlwaysCheckBounds, false);
246 :
247 : // Toggles the optimization whereby offsets are folded into loads and not
248 : // included in the bounds check.
249 6 : SET_DEFAULT(wasmFoldOffsets, true);
250 :
251 : // Until which wasm bytecode size should we accumulate functions, in order
252 : // to compile efficiently on helper threads. Baseline code compiles much
253 : // faster than Ion code so use scaled thresholds (see also bug 1320374).
254 6 : SET_DEFAULT(wasmBatchBaselineThreshold, 10000);
255 6 : SET_DEFAULT(wasmBatchIonThreshold, 1100);
256 :
257 : // Determines whether we suppress using signal handlers
258 : // for interrupting jit-ed code. This is used only for testing.
259 6 : SET_DEFAULT(ionInterruptWithoutSignals, false);
260 6 : }
261 :
262 : bool
263 7905 : DefaultJitOptions::isSmallFunction(JSScript* script) const
264 : {
265 7905 : return script->length() <= smallFunctionMaxBytecodeLength_;
266 : }
267 :
268 : void
269 0 : DefaultJitOptions::enableGvn(bool enable)
270 : {
271 0 : disableGvn = !enable;
272 0 : }
273 :
274 : void
275 0 : DefaultJitOptions::setEagerCompilation()
276 : {
277 0 : eagerCompilation = true;
278 0 : baselineWarmUpThreshold = 0;
279 0 : forcedDefaultIonWarmUpThreshold.reset();
280 0 : forcedDefaultIonWarmUpThreshold.emplace(0);
281 0 : forcedDefaultIonSmallFunctionWarmUpThreshold.reset();
282 0 : forcedDefaultIonSmallFunctionWarmUpThreshold.emplace(0);
283 0 : }
284 :
285 : void
286 0 : DefaultJitOptions::setCompilerWarmUpThreshold(uint32_t warmUpThreshold)
287 : {
288 0 : forcedDefaultIonWarmUpThreshold.reset();
289 0 : forcedDefaultIonWarmUpThreshold.emplace(warmUpThreshold);
290 0 : forcedDefaultIonSmallFunctionWarmUpThreshold.reset();
291 0 : forcedDefaultIonSmallFunctionWarmUpThreshold.emplace(warmUpThreshold);
292 :
293 : // Undo eager compilation
294 0 : if (eagerCompilation && warmUpThreshold != 0) {
295 0 : jit::DefaultJitOptions defaultValues;
296 0 : eagerCompilation = false;
297 0 : baselineWarmUpThreshold = defaultValues.baselineWarmUpThreshold;
298 : }
299 0 : }
300 :
301 : void
302 3 : DefaultJitOptions::resetCompilerWarmUpThreshold()
303 : {
304 3 : forcedDefaultIonWarmUpThreshold.reset();
305 :
306 : // Undo eager compilation
307 3 : if (eagerCompilation) {
308 0 : jit::DefaultJitOptions defaultValues;
309 0 : eagerCompilation = false;
310 0 : baselineWarmUpThreshold = defaultValues.baselineWarmUpThreshold;
311 : }
312 3 : }
313 :
314 : } // namespace jit
315 : } // namespace js
|