diff options
Diffstat (limited to 'js/src/jit/JitOptions.cpp')
-rw-r--r-- | js/src/jit/JitOptions.cpp | 298 |
1 files changed, 298 insertions, 0 deletions
diff --git a/js/src/jit/JitOptions.cpp b/js/src/jit/JitOptions.cpp new file mode 100644 index 000000000..eb5a6c1c2 --- /dev/null +++ b/js/src/jit/JitOptions.cpp @@ -0,0 +1,298 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- + * vim: set ts=8 sts=4 et sw=4 tw=99: + * 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 "mozilla/TypeTraits.h" + +#include <cstdlib> +#include "jsfun.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); +} + +template<typename T> struct IsBool : mozilla::FalseType {}; +template<> struct IsBool<bool> : mozilla::TrueType {}; + +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 (IsBool<T>::value) { + 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 IonBuilder fallbacks to a call if we fail to inline. + SET_DEFAULT(disableInlineBacktracking, true); + + // Toggles whether Alignment Mask Analysis is globally disabled. + SET_DEFAULT(disableAma, false); + + // Toggles whether Effective Address Analysis is globally disabled. + SET_DEFAULT(disableEaa, false); + + // Toggle whether eager simd unboxing is globally disabled. + SET_DEFAULT(disableEagerSimdUnbox, false); + + // Toggles whether Edge Case Analysis is gobally disabled. + SET_DEFAULT(disableEdgeCaseAnalysis, false); + + // Toggles whether to use flow sensitive Alias Analysis. + SET_DEFAULT(disableFlowAA, true); + + // 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); + + // Toggles whether Loop Unrolling is globally disabled. + SET_DEFAULT(disableLoopUnrolling, true); + + // 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 shared stubs are used in Ionmonkey. + SET_DEFAULT(disableSharedStubs, false); + + // Toggles whether sincos optimization is globally disabled. + // See bug984018: The MacOS is the only one that has the sincos fast. + #if defined(XP_MACOSX) + SET_DEFAULT(disableSincos, false); + #else + SET_DEFAULT(disableSincos, true); + #endif + + // Toggles whether sink code motion is globally disabled. + SET_DEFAULT(disableSink, true); + + // Whether functions are compiled immediately. + SET_DEFAULT(eagerCompilation, false); + + // Whether IonBuilder should prefer IC generation above specialized MIR. + 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 + // are compiled with the baseline compiler. + SET_DEFAULT(baselineWarmUpThreshold, 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. + SET_DEFAULT(frequentBailoutThreshold, 10); + + // 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); + + // 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); + + // Force how many invocation or loop iterations are needed before compiling + // a function with the highest ionmonkey optimization level. + // (i.e. OptimizationLevel_Normal) + const char* forcedDefaultIonWarmUpThresholdEnv = "JIT_OPTION_forcedDefaultIonWarmUpThreshold"; + if (const char* env = getenv(forcedDefaultIonWarmUpThresholdEnv)) { + Maybe<int> value = ParseInt(env); + if (value.isSome()) + forcedDefaultIonWarmUpThreshold.emplace(value.ref()); + else + Warn(forcedDefaultIonWarmUpThresholdEnv, env); + } + + // Same but for compiling small functions. + const char* forcedDefaultIonSmallFunctionWarmUpThresholdEnv = + "JIT_OPTION_forcedDefaultIonSmallFunctionWarmUpThreshold"; + if (const char* env = getenv(forcedDefaultIonSmallFunctionWarmUpThresholdEnv)) { + Maybe<int> value = ParseInt(env); + if (value.isSome()) + forcedDefaultIonSmallFunctionWarmUpThreshold.emplace(value.ref()); + else + Warn(forcedDefaultIonSmallFunctionWarmUpThresholdEnv, env); + } + + // 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); + } + + // Toggles whether unboxed plain objects can be created by the VM. + SET_DEFAULT(disableUnboxedObjects, false); + + // Test whether Atomics are allowed in asm.js code. + SET_DEFAULT(asmJSAtomicsEnable, false); + + // Test whether wasm int64 / double NaN bits testing is enabled. + SET_DEFAULT(wasmTestMode, false); + + // Test whether wasm bounds check should always be generated. + SET_DEFAULT(wasmAlwaysCheckBounds, false); + + // Toggles the optimization whereby offsets are folded into loads and not + // included in the bounds check. + SET_DEFAULT(wasmFoldOffsets, true); + + // Determines whether we suppress using signal handlers + // for interrupting jit-ed code. This is used only for testing. + SET_DEFAULT(ionInterruptWithoutSignals, false); +} + +bool +DefaultJitOptions::isSmallFunction(JSScript* script) const +{ + return script->length() <= smallFunctionMaxBytecodeLength_; +} + +void +DefaultJitOptions::enableGvn(bool enable) +{ + disableGvn = !enable; +} + +void +DefaultJitOptions::setEagerCompilation() +{ + eagerCompilation = true; + baselineWarmUpThreshold = 0; + forcedDefaultIonWarmUpThreshold.reset(); + forcedDefaultIonWarmUpThreshold.emplace(0); + forcedDefaultIonSmallFunctionWarmUpThreshold.reset(); + forcedDefaultIonSmallFunctionWarmUpThreshold.emplace(0); +} + +void +DefaultJitOptions::setCompilerWarmUpThreshold(uint32_t warmUpThreshold) +{ + forcedDefaultIonWarmUpThreshold.reset(); + forcedDefaultIonWarmUpThreshold.emplace(warmUpThreshold); + forcedDefaultIonSmallFunctionWarmUpThreshold.reset(); + forcedDefaultIonSmallFunctionWarmUpThreshold.emplace(warmUpThreshold); + + // Undo eager compilation + if (eagerCompilation && warmUpThreshold != 0) { + jit::DefaultJitOptions defaultValues; + eagerCompilation = false; + baselineWarmUpThreshold = defaultValues.baselineWarmUpThreshold; + } +} + +void +DefaultJitOptions::resetCompilerWarmUpThreshold() +{ + forcedDefaultIonWarmUpThreshold.reset(); + + // Undo eager compilation + if (eagerCompilation) { + jit::DefaultJitOptions defaultValues; + eagerCompilation = false; + baselineWarmUpThreshold = defaultValues.baselineWarmUpThreshold; + } +} + +} // namespace jit +} // namespace js |