summaryrefslogtreecommitdiff
path: root/js/src/jit/IonOptimizationLevels.h
diff options
context:
space:
mode:
Diffstat (limited to 'js/src/jit/IonOptimizationLevels.h')
-rw-r--r--js/src/jit/IonOptimizationLevels.h302
1 files changed, 302 insertions, 0 deletions
diff --git a/js/src/jit/IonOptimizationLevels.h b/js/src/jit/IonOptimizationLevels.h
new file mode 100644
index 0000000000..c38eb69a2d
--- /dev/null
+++ b/js/src/jit/IonOptimizationLevels.h
@@ -0,0 +1,302 @@
+/* -*- 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/. */
+
+#ifndef jit_IonOptimizationLevels_h
+#define jit_IonOptimizationLevels_h
+
+#include "mozilla/EnumeratedArray.h"
+
+#include "jsbytecode.h"
+#include "jstypes.h"
+
+#include "jit/JitOptions.h"
+#include "js/TypeDecls.h"
+
+namespace js {
+namespace jit {
+
+enum class OptimizationLevel : uint8_t
+{
+ Normal,
+ Wasm,
+ Count,
+ DontCompile
+};
+
+#ifdef JS_JITSPEW
+inline const char*
+OptimizationLevelString(OptimizationLevel level)
+{
+ switch (level) {
+ case OptimizationLevel::DontCompile:
+ return "Optimization_DontCompile";
+ case OptimizationLevel::Normal:
+ return "Optimization_Normal";
+ case OptimizationLevel::Wasm:
+ return "Optimization_Wasm";
+ case OptimizationLevel::Count:;
+ }
+ MOZ_CRASH("Invalid OptimizationLevel");
+}
+#endif
+
+class OptimizationInfo
+{
+ public:
+ OptimizationLevel level_;
+
+ // Toggles whether Effective Address Analysis is performed.
+ bool eaa_;
+
+ // Toggles whether Alignment Mask Analysis is performed.
+ bool ama_;
+
+ // Toggles whether Edge Case Analysis is used.
+ bool edgeCaseAnalysis_;
+
+ // Toggles whether redundant checks get removed.
+ bool eliminateRedundantChecks_;
+
+ // Toggles whether interpreted scripts get inlined.
+ bool inlineInterpreted_;
+
+ // Toggles whether native scripts get inlined.
+ bool inlineNative_;
+
+ // Toggles whether eager unboxing of SIMD is used.
+ bool eagerSimdUnbox_;
+
+ // Toggles whether global value numbering is used.
+ bool gvn_;
+
+ // Toggles whether loop invariant code motion is performed.
+ bool licm_;
+
+ // Toggles whether Range Analysis is used.
+ bool rangeAnalysis_;
+
+ // Toggles whether loop unrolling is performed.
+ bool loopUnrolling_;
+
+ // Toggles whether instruction reordering is performed.
+ bool reordering_;
+
+ // Toggles whether Truncation based on Range Analysis is used.
+ bool autoTruncate_;
+
+ // Toggles whether sincos is used.
+ bool sincos_;
+
+ // Toggles whether sink is used.
+ bool sink_;
+
+ // Describes which register allocator to use.
+ IonRegisterAllocator registerAllocator_;
+
+ // The maximum total bytecode size of an inline call site. We use a lower
+ // value if off-thread compilation is not available, to avoid stalling the
+ // main thread.
+ uint32_t inlineMaxBytecodePerCallSiteOffThread_;
+ uint32_t inlineMaxBytecodePerCallSiteMainThread_;
+
+ // The maximum value we allow for baselineScript->inlinedBytecodeLength_
+ // when inlining.
+ uint16_t inlineMaxCalleeInlinedBytecodeLength_;
+
+ // The maximum bytecode length we'll inline in a single compilation.
+ uint32_t inlineMaxTotalBytecodeLength_;
+
+ // The maximum bytecode length the caller may have,
+ // before we stop inlining large functions in that caller.
+ uint32_t inliningMaxCallerBytecodeLength_;
+
+ // The maximum inlining depth.
+ uint32_t maxInlineDepth_;
+
+ // Toggles whether scalar replacement is used.
+ bool scalarReplacement_;
+
+ // The maximum inlining depth for functions.
+ //
+ // Inlining small functions has almost no compiling overhead
+ // and removes the otherwise needed call overhead.
+ // The value is currently very low.
+ // Actually it is only needed to make sure we don't blow out the stack.
+ uint32_t smallFunctionMaxInlineDepth_;
+
+ // How many invocations or loop iterations are needed before functions
+ // are compiled.
+ uint32_t compilerWarmUpThreshold_;
+
+ // Default compiler warmup threshold, unless it is overridden.
+ static const uint32_t CompilerWarmupThreshold = 1000;
+
+ // How many invocations or loop iterations are needed before small functions
+ // are compiled.
+ uint32_t compilerSmallFunctionWarmUpThreshold_;
+
+ // Default small function compiler warmup threshold, unless it is overridden.
+ static const uint32_t CompilerSmallFunctionWarmupThreshold = 100;
+
+ // How many invocations or loop iterations are needed before calls
+ // are inlined, as a fraction of compilerWarmUpThreshold.
+ double inliningWarmUpThresholdFactor_;
+
+ // How many invocations or loop iterations are needed before a function
+ // is hot enough to recompile the outerScript to inline that function,
+ // as a multiplication of inliningWarmUpThreshold.
+ uint32_t inliningRecompileThresholdFactor_;
+
+ OptimizationInfo()
+ { }
+
+ void initNormalOptimizationInfo();
+ void initWasmOptimizationInfo();
+
+ OptimizationLevel level() const {
+ return level_;
+ }
+
+ bool inlineInterpreted() const {
+ return inlineInterpreted_ && !JitOptions.disableInlining;
+ }
+
+ bool inlineNative() const {
+ return inlineNative_ && !JitOptions.disableInlining;
+ }
+
+ uint32_t compilerWarmUpThreshold(JSScript* script, jsbytecode* pc = nullptr) const;
+
+ bool eagerSimdUnboxEnabled() const {
+ return eagerSimdUnbox_ && !JitOptions.disableEagerSimdUnbox;
+ }
+
+ bool gvnEnabled() const {
+ return gvn_ && !JitOptions.disableGvn;
+ }
+
+ bool licmEnabled() const {
+ return licm_ && !JitOptions.disableLicm;
+ }
+
+ bool rangeAnalysisEnabled() const {
+ return rangeAnalysis_ && !JitOptions.disableRangeAnalysis;
+ }
+
+ bool loopUnrollingEnabled() const {
+ return loopUnrolling_ && !JitOptions.disableLoopUnrolling;
+ }
+
+ bool instructionReorderingEnabled() const {
+ return reordering_ && !JitOptions.disableInstructionReordering;
+ }
+
+ bool autoTruncateEnabled() const {
+ return autoTruncate_ && rangeAnalysisEnabled();
+ }
+
+ bool sincosEnabled() const {
+ return sincos_ && !JitOptions.disableSincos;
+ }
+
+ bool sinkEnabled() const {
+ return sink_ && !JitOptions.disableSink;
+ }
+
+ bool eaaEnabled() const {
+ return eaa_ && !JitOptions.disableEaa;
+ }
+
+ bool amaEnabled() const {
+ return ama_ && !JitOptions.disableAma;
+ }
+
+ bool edgeCaseAnalysisEnabled() const {
+ return edgeCaseAnalysis_ && !JitOptions.disableEdgeCaseAnalysis;
+ }
+
+ bool eliminateRedundantChecksEnabled() const {
+ return eliminateRedundantChecks_;
+ }
+
+ bool flowAliasAnalysisEnabled() const {
+ return !JitOptions.disableFlowAA;
+ }
+
+ IonRegisterAllocator registerAllocator() const {
+ if (JitOptions.forcedRegisterAllocator.isSome())
+ return JitOptions.forcedRegisterAllocator.ref();
+ return registerAllocator_;
+ }
+
+ bool scalarReplacementEnabled() const {
+ return scalarReplacement_ && !JitOptions.disableScalarReplacement;
+ }
+
+ uint32_t smallFunctionMaxInlineDepth() const {
+ return smallFunctionMaxInlineDepth_;
+ }
+
+ bool isSmallFunction(JSScript* script) const;
+
+ uint32_t maxInlineDepth() const {
+ return maxInlineDepth_;
+ }
+
+ uint32_t inlineMaxBytecodePerCallSite(bool offThread) const {
+ return (offThread || !JitOptions.limitScriptSize)
+ ? inlineMaxBytecodePerCallSiteOffThread_
+ : inlineMaxBytecodePerCallSiteMainThread_;
+ }
+
+ uint16_t inlineMaxCalleeInlinedBytecodeLength() const {
+ return inlineMaxCalleeInlinedBytecodeLength_;
+ }
+
+ uint32_t inlineMaxTotalBytecodeLength() const {
+ return inlineMaxTotalBytecodeLength_;
+ }
+
+ uint32_t inliningMaxCallerBytecodeLength() const {
+ return inliningMaxCallerBytecodeLength_;
+ }
+
+ uint32_t inliningWarmUpThreshold() const {
+ uint32_t compilerWarmUpThreshold = compilerWarmUpThreshold_;
+ if (JitOptions.forcedDefaultIonWarmUpThreshold.isSome())
+ compilerWarmUpThreshold = JitOptions.forcedDefaultIonWarmUpThreshold.ref();
+ return compilerWarmUpThreshold * inliningWarmUpThresholdFactor_;
+ }
+
+ uint32_t inliningRecompileThreshold() const {
+ return inliningWarmUpThreshold() * inliningRecompileThresholdFactor_;
+ }
+};
+
+class OptimizationLevelInfo
+{
+ private:
+ mozilla::EnumeratedArray<OptimizationLevel, OptimizationLevel::Count, OptimizationInfo> infos_;
+
+ public:
+ OptimizationLevelInfo();
+
+ const OptimizationInfo* get(OptimizationLevel level) const {
+ return &infos_[level];
+ }
+
+ OptimizationLevel nextLevel(OptimizationLevel level) const;
+ OptimizationLevel firstLevel() const;
+ bool isLastLevel(OptimizationLevel level) const;
+ OptimizationLevel levelForScript(JSScript* script, jsbytecode* pc = nullptr) const;
+};
+
+extern OptimizationLevelInfo IonOptimizations;
+
+} // namespace jit
+} // namespace js
+
+#endif /* jit_IonOptimizationLevels_h */