diff options
Diffstat (limited to 'js/src/jit/JitOptions.cpp')
-rw-r--r-- | js/src/jit/JitOptions.cpp | 350 |
1 files changed, 350 insertions, 0 deletions
diff --git a/js/src/jit/JitOptions.cpp b/js/src/jit/JitOptions.cpp new file mode 100644 index 0000000000..145ad687b9 --- /dev/null +++ b/js/src/jit/JitOptions.cpp @@ -0,0 +1,350 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * vim: set ts=8 sts=2 et sw=2 tw=80: + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "jit/JitOptions.h" + +#include <cstdlib> +#include <type_traits> + +#include "vm/JSFunction.h" + +using namespace js; +using namespace js::jit; + +using mozilla::Maybe; + +namespace js { +namespace jit { + +DefaultJitOptions JitOptions; + +static void Warn(const char* env, const char* value) { + fprintf(stderr, "Warning: I didn't understand %s=\"%s\"\n", env, value); +} + +static Maybe<int> ParseInt(const char* str) { + char* endp; + int retval = strtol(str, &endp, 0); + if (*endp == '\0') { + return mozilla::Some(retval); + } + return mozilla::Nothing(); +} + +template <typename T> +T overrideDefault(const char* param, T dflt) { + char* str = getenv(param); + if (!str) { + return dflt; + } + if constexpr (std::is_same_v<T, bool>) { + if (strcmp(str, "true") == 0 || strcmp(str, "yes") == 0) { + return true; + } + if (strcmp(str, "false") == 0 || strcmp(str, "no") == 0) { + return false; + } + Warn(param, str); + } else { + Maybe<int> value = ParseInt(str); + if (value.isSome()) { + return value.ref(); + } + Warn(param, str); + } + return dflt; +} + +#define SET_DEFAULT(var, dflt) var = overrideDefault("JIT_OPTION_" #var, dflt) +DefaultJitOptions::DefaultJitOptions() { + // Whether to perform expensive graph-consistency DEBUG-only assertions. + // It can be useful to disable this to reduce DEBUG-compile time of large + // wasm programs. + SET_DEFAULT(checkGraphConsistency, true); + +#ifdef CHECK_OSIPOINT_REGISTERS + // Emit extra code to verify live regs at the start of a VM call + // are not modified before its OsiPoint. + SET_DEFAULT(checkOsiPointRegisters, false); +#endif + + // Whether to enable extra code to perform dynamic validation of + // RangeAnalysis results. + SET_DEFAULT(checkRangeAnalysis, false); + + // Toggles whether Alignment Mask Analysis is globally disabled. + SET_DEFAULT(disableAma, false); + + // Toggles whether Effective Address Analysis is globally disabled. + SET_DEFAULT(disableEaa, false); + + // Toggles whether Edge Case Analysis is gobally disabled. + SET_DEFAULT(disableEdgeCaseAnalysis, false); + + // Toggle whether global value numbering is globally disabled. + SET_DEFAULT(disableGvn, false); + + // Toggles whether inlining is globally disabled. + SET_DEFAULT(disableInlining, false); + + // Toggles whether loop invariant code motion is globally disabled. + SET_DEFAULT(disableLicm, false); + + // Toggle whether Profile Guided Optimization is globally disabled. + SET_DEFAULT(disablePgo, false); + + // Toggles whether instruction reordering is globally disabled. + SET_DEFAULT(disableInstructionReordering, false); + + // Toggles whether Range Analysis is globally disabled. + SET_DEFAULT(disableRangeAnalysis, false); + + // Toggles wheter Recover instructions is globally disabled. + SET_DEFAULT(disableRecoverIns, false); + + // Toggle whether eager scalar replacement is globally disabled. + SET_DEFAULT(disableScalarReplacement, false); + + // Toggles whether CacheIR stubs are used. + SET_DEFAULT(disableCacheIR, false); + + // Toggles whether sink code motion is globally disabled. + SET_DEFAULT(disableSink, true); + + // Toggles whether we verify that we don't recompile with the same CacheIR. + SET_DEFAULT(disableBailoutLoopCheck, false); + + // Whether the Baseline Interpreter is enabled. + SET_DEFAULT(baselineInterpreter, true); + + // Whether the Baseline JIT is enabled. + SET_DEFAULT(baselineJit, true); + + // Whether the IonMonkey JIT is enabled. + SET_DEFAULT(ion, true); + + // Warp compile Async functions + SET_DEFAULT(warpAsync, true); + + // Warp compile Generator functions + SET_DEFAULT(warpGenerator, true); + + // Whether the IonMonkey and Baseline JITs are enabled for Trusted Principals. + // (Ignored if ion or baselineJit is set to true.) + SET_DEFAULT(jitForTrustedPrincipals, false); + + // Whether the RegExp JIT is enabled. + SET_DEFAULT(nativeRegExp, true); + + // Whether Warp should use ICs instead of transpiling Baseline CacheIR. + SET_DEFAULT(forceInlineCaches, false); + + // Toggles whether large scripts are rejected. + SET_DEFAULT(limitScriptSize, true); + + // Toggles whether functions may be entered at loop headers. + SET_DEFAULT(osr, true); + + // Whether to enable extra code to perform dynamic validations. + SET_DEFAULT(runExtraChecks, false); + + // How many invocations or loop iterations are needed before functions + // enter the Baseline Interpreter. + SET_DEFAULT(baselineInterpreterWarmUpThreshold, 10); + + // How many invocations or loop iterations are needed before functions + // are compiled with the baseline compiler. + // Duplicated in all.js - ensure both match. + SET_DEFAULT(baselineJitWarmUpThreshold, 100); + + // How many invocations or loop iterations are needed before functions + // are considered for trial inlining. + SET_DEFAULT(trialInliningWarmUpThreshold, 500); + + // The initial warm-up count for ICScripts created by trial inlining. + // + // Note: the difference between trialInliningInitialWarmUpCount and + // trialInliningWarmUpThreshold must be: + // + // * Small enough to allow inlining multiple levels deep before the outer + // script reaches its normalIonWarmUpThreshold. + // + // * Greater than inliningEntryThreshold or no scripts can be inlined. + SET_DEFAULT(trialInliningInitialWarmUpCount, 250); + + // How many invocations or loop iterations are needed before functions + // are compiled with the Ion compiler at OptimizationLevel::Normal. + // Duplicated in all.js - ensure both match. + SET_DEFAULT(normalIonWarmUpThreshold, 1500); + + // How many invocations are needed before regexps are compiled to + // native code. + SET_DEFAULT(regexpWarmUpThreshold, 10); + + // Number of exception bailouts (resuming into catch/finally block) before + // we invalidate and forbid Ion compilation. + SET_DEFAULT(exceptionBailoutThreshold, 10); + + // Number of bailouts without invalidation before we set + // JSScript::hadFrequentBailouts and invalidate. + // Duplicated in all.js - ensure both match. + SET_DEFAULT(frequentBailoutThreshold, 10); + + // Whether to run all debug checks in debug builds. + // Disabling might make it more enjoyable to run JS in debug builds. + SET_DEFAULT(fullDebugChecks, true); + + // How many actual arguments are accepted on the C stack. + SET_DEFAULT(maxStackArgs, 4096); + + // How many times we will try to enter a script via OSR before + // invalidating the script. + SET_DEFAULT(osrPcMismatchesBeforeRecompile, 6000); + + // The bytecode length limit for small function. + SET_DEFAULT(smallFunctionMaxBytecodeLength, 130); + + // The minimum entry count for an IC stub before it can be trial-inlined. + SET_DEFAULT(inliningEntryThreshold, 100); + + // An artificial testing limit for the maximum supported offset of + // pc-relative jump and call instructions. + SET_DEFAULT(jumpThreshold, UINT32_MAX); + + // Branch pruning heuristic is based on a scoring system, which is look at + // different metrics and provide a score. The score is computed as a + // projection where each factor defines the weight of each metric. Then this + // score is compared against a threshold to prevent a branch from being + // removed. + SET_DEFAULT(branchPruningHitCountFactor, 1); + SET_DEFAULT(branchPruningInstFactor, 10); + SET_DEFAULT(branchPruningBlockSpanFactor, 100); + SET_DEFAULT(branchPruningEffectfulInstFactor, 3500); + SET_DEFAULT(branchPruningThreshold, 4000); + + // Limits on bytecode length and number of locals/arguments for Ion + // compilation. There are different (lower) limits for when off-thread Ion + // compilation isn't available. + SET_DEFAULT(ionMaxScriptSize, 100 * 1000); + SET_DEFAULT(ionMaxScriptSizeMainThread, 2 * 1000); + SET_DEFAULT(ionMaxLocalsAndArgs, 10 * 1000); + SET_DEFAULT(ionMaxLocalsAndArgsMainThread, 256); + + // Force the used register allocator instead of letting the optimization + // pass decide. + const char* forcedRegisterAllocatorEnv = "JIT_OPTION_forcedRegisterAllocator"; + if (const char* env = getenv(forcedRegisterAllocatorEnv)) { + forcedRegisterAllocator = LookupRegisterAllocator(env); + if (!forcedRegisterAllocator.isSome()) { + Warn(forcedRegisterAllocatorEnv, env); + } + } + +#if defined(JS_CODEGEN_MIPS32) || defined(JS_CODEGEN_MIPS64) + SET_DEFAULT(spectreIndexMasking, false); + SET_DEFAULT(spectreObjectMitigationsBarriers, false); + SET_DEFAULT(spectreObjectMitigationsMisc, false); + SET_DEFAULT(spectreStringMitigations, false); + SET_DEFAULT(spectreValueMasking, false); + SET_DEFAULT(spectreJitToCxxCalls, false); +#else + SET_DEFAULT(spectreIndexMasking, true); + SET_DEFAULT(spectreObjectMitigationsBarriers, true); + SET_DEFAULT(spectreObjectMitigationsMisc, true); + SET_DEFAULT(spectreStringMitigations, true); + SET_DEFAULT(spectreValueMasking, true); + SET_DEFAULT(spectreJitToCxxCalls, true); +#endif + + // These are set to their actual values in InitializeJit. + SET_DEFAULT(supportsFloatingPoint, false); + SET_DEFAULT(supportsUnalignedAccesses, false); + + // Toggles the optimization whereby offsets are folded into loads and not + // included in the bounds check. + SET_DEFAULT(wasmFoldOffsets, true); + + // Controls whether two-tiered compilation should be requested when + // compiling a new wasm module, independently of other heuristics, and + // should be delayed to test both baseline and ion paths in compiled code, + // as well as the transition from one tier to the other. + SET_DEFAULT(wasmDelayTier2, false); + + // Until which wasm bytecode size should we accumulate functions, in order + // to compile efficiently on helper threads. Baseline code compiles much + // faster than Ion code so use scaled thresholds (see also bug 1320374). + // Cranelift compiles at about half the speed of Ion, but is much more + // affected by malloc/free costs, so set its threshold relatively high, in + // order to reduce overall allocation costs. See bug 1586791. + SET_DEFAULT(wasmBatchBaselineThreshold, 10000); + SET_DEFAULT(wasmBatchIonThreshold, 1100); + SET_DEFAULT(wasmBatchCraneliftThreshold, 5000); + +#ifdef JS_TRACE_LOGGING + // Toggles whether the traceLogger should be on or off. In either case, + // some data structures will always be created and initialized such as + // the traceLoggerState. However, unless this option is set to true + // the traceLogger will not be recording any events. + SET_DEFAULT(enableTraceLogger, false); +#endif + + // Dumps a representation of parsed regexps to stderr + SET_DEFAULT(traceRegExpParser, false); + // Dumps the calls made to the regexp assembler to stderr + SET_DEFAULT(traceRegExpAssembler, false); + // Dumps the bytecodes interpreted by the regexp engine to stderr + SET_DEFAULT(traceRegExpInterpreter, false); + // Dumps the changes made by the regexp peephole optimizer to stderr + SET_DEFAULT(traceRegExpPeephole, false); + + SET_DEFAULT(enableWasmJitExit, true); + SET_DEFAULT(enableWasmJitEntry, true); + SET_DEFAULT(enableWasmIonFastCalls, true); +#ifdef WASM_CODEGEN_DEBUG + SET_DEFAULT(enableWasmImportCallSpew, false); + SET_DEFAULT(enableWasmFuncCallSpew, false); +#endif +} + +bool DefaultJitOptions::isSmallFunction(JSScript* script) const { + return script->length() <= smallFunctionMaxBytecodeLength; +} + +void DefaultJitOptions::enableGvn(bool enable) { disableGvn = !enable; } + +void DefaultJitOptions::setEagerBaselineCompilation() { + baselineInterpreterWarmUpThreshold = 0; + baselineJitWarmUpThreshold = 0; + regexpWarmUpThreshold = 0; +} + +void DefaultJitOptions::setEagerIonCompilation() { + setEagerBaselineCompilation(); + normalIonWarmUpThreshold = 0; +} + +void DefaultJitOptions::setFastWarmUp() { + baselineInterpreterWarmUpThreshold = 4; + baselineJitWarmUpThreshold = 10; + trialInliningWarmUpThreshold = 14; + trialInliningInitialWarmUpCount = 12; + normalIonWarmUpThreshold = 30; + + inliningEntryThreshold = 2; + smallFunctionMaxBytecodeLength = 2000; +} + +void DefaultJitOptions::setNormalIonWarmUpThreshold(uint32_t warmUpThreshold) { + normalIonWarmUpThreshold = warmUpThreshold; +} + +void DefaultJitOptions::resetNormalIonWarmUpThreshold() { + jit::DefaultJitOptions defaultValues; + setNormalIonWarmUpThreshold(defaultValues.normalIonWarmUpThreshold); +} + +} // namespace jit +} // namespace js |