summaryrefslogtreecommitdiffstats
path: root/js/src/jit/IonOptimizationLevels.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'js/src/jit/IonOptimizationLevels.cpp')
-rw-r--r--js/src/jit/IonOptimizationLevels.cpp178
1 files changed, 178 insertions, 0 deletions
diff --git a/js/src/jit/IonOptimizationLevels.cpp b/js/src/jit/IonOptimizationLevels.cpp
new file mode 100644
index 000000000..ece02fdc0
--- /dev/null
+++ b/js/src/jit/IonOptimizationLevels.cpp
@@ -0,0 +1,178 @@
+/* -*- 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/IonOptimizationLevels.h"
+
+#include "jsscript.h"
+
+#include "jit/Ion.h"
+
+using namespace js;
+using namespace js::jit;
+
+namespace js {
+namespace jit {
+
+OptimizationLevelInfo IonOptimizations;
+
+void
+OptimizationInfo::initNormalOptimizationInfo()
+{
+ level_ = OptimizationLevel::Normal;
+
+ autoTruncate_ = true;
+ eaa_ = true;
+ eagerSimdUnbox_ = true;
+ edgeCaseAnalysis_ = true;
+ eliminateRedundantChecks_ = true;
+ inlineInterpreted_ = true;
+ inlineNative_ = true;
+ licm_ = true;
+ loopUnrolling_ = true;
+ gvn_ = true;
+ rangeAnalysis_ = true;
+ reordering_ = true;
+ sincos_ = true;
+ sink_ = true;
+
+ registerAllocator_ = RegisterAllocator_Backtracking;
+
+ inlineMaxBytecodePerCallSiteMainThread_ = 550;
+ inlineMaxBytecodePerCallSiteOffThread_ = 1100;
+ inlineMaxCalleeInlinedBytecodeLength_ = 3550;
+ inlineMaxTotalBytecodeLength_ = 85000;
+ inliningMaxCallerBytecodeLength_ = 1600;
+ maxInlineDepth_ = 3;
+ scalarReplacement_ = true;
+ smallFunctionMaxInlineDepth_ = 10;
+ compilerWarmUpThreshold_ = CompilerWarmupThreshold;
+ compilerSmallFunctionWarmUpThreshold_ = CompilerSmallFunctionWarmupThreshold;
+ inliningWarmUpThresholdFactor_ = 0.125;
+ inliningRecompileThresholdFactor_ = 4;
+}
+
+void
+OptimizationInfo::initWasmOptimizationInfo()
+{
+ // The Wasm optimization level
+ // Disables some passes that don't work well with wasm.
+
+ // Take normal option values for not specified values.
+ initNormalOptimizationInfo();
+
+ level_ = OptimizationLevel::Wasm;
+
+ ama_ = true;
+ autoTruncate_ = false;
+ eagerSimdUnbox_ = false; // wasm has no boxing / unboxing.
+ edgeCaseAnalysis_ = false;
+ eliminateRedundantChecks_ = false;
+ scalarReplacement_ = false; // wasm has no objects.
+ sincos_ = false;
+ sink_ = false;
+}
+
+uint32_t
+OptimizationInfo::compilerWarmUpThreshold(JSScript* script, jsbytecode* pc) const
+{
+ MOZ_ASSERT(pc == nullptr || pc == script->code() || JSOp(*pc) == JSOP_LOOPENTRY);
+
+ if (pc == script->code())
+ pc = nullptr;
+
+ uint32_t warmUpThreshold = compilerWarmUpThreshold_;
+ if (JitOptions.forcedDefaultIonWarmUpThreshold.isSome())
+ warmUpThreshold = JitOptions.forcedDefaultIonWarmUpThreshold.ref();
+
+ if (JitOptions.isSmallFunction(script)) {
+ warmUpThreshold = compilerSmallFunctionWarmUpThreshold_;
+ if (JitOptions.forcedDefaultIonSmallFunctionWarmUpThreshold.isSome())
+ warmUpThreshold = JitOptions.forcedDefaultIonSmallFunctionWarmUpThreshold.ref();
+ }
+
+ // If the script is too large to compile on the main thread, we can still
+ // compile it off thread. In these cases, increase the warm-up counter
+ // threshold to improve the compilation's type information and hopefully
+ // avoid later recompilation.
+
+ if (script->length() > MAX_MAIN_THREAD_SCRIPT_SIZE)
+ warmUpThreshold *= (script->length() / (double) MAX_MAIN_THREAD_SCRIPT_SIZE);
+
+ uint32_t numLocalsAndArgs = NumLocalsAndArgs(script);
+ if (numLocalsAndArgs > MAX_MAIN_THREAD_LOCALS_AND_ARGS)
+ warmUpThreshold *= (numLocalsAndArgs / (double) MAX_MAIN_THREAD_LOCALS_AND_ARGS);
+
+ if (!pc || JitOptions.eagerCompilation)
+ return warmUpThreshold;
+
+ // It's more efficient to enter outer loops, rather than inner loops, via OSR.
+ // To accomplish this, we use a slightly higher threshold for inner loops.
+ // Note that the loop depth is always > 0 so we will prefer non-OSR over OSR.
+ uint32_t loopDepth = LoopEntryDepthHint(pc);
+ MOZ_ASSERT(loopDepth > 0);
+ return warmUpThreshold + loopDepth * 100;
+}
+
+OptimizationLevelInfo::OptimizationLevelInfo()
+{
+ infos_[OptimizationLevel::Normal].initNormalOptimizationInfo();
+ infos_[OptimizationLevel::Wasm].initWasmOptimizationInfo();
+
+#ifdef DEBUG
+ OptimizationLevel level = firstLevel();
+ while (!isLastLevel(level)) {
+ OptimizationLevel next = nextLevel(level);
+ MOZ_ASSERT_IF(level != OptimizationLevel::DontCompile, level < next);
+ level = next;
+ }
+#endif
+}
+
+OptimizationLevel
+OptimizationLevelInfo::nextLevel(OptimizationLevel level) const
+{
+ MOZ_ASSERT(!isLastLevel(level));
+ switch (level) {
+ case OptimizationLevel::DontCompile:
+ return OptimizationLevel::Normal;
+ case OptimizationLevel::Normal:
+ case OptimizationLevel::Wasm:
+ case OptimizationLevel::Count:;
+ }
+ MOZ_CRASH("Unknown optimization level.");
+}
+
+OptimizationLevel
+OptimizationLevelInfo::firstLevel() const
+{
+ return nextLevel(OptimizationLevel::DontCompile);
+}
+
+bool
+OptimizationLevelInfo::isLastLevel(OptimizationLevel level) const
+{
+ return level == OptimizationLevel::Normal;
+}
+
+OptimizationLevel
+OptimizationLevelInfo::levelForScript(JSScript* script, jsbytecode* pc) const
+{
+ OptimizationLevel prev = OptimizationLevel::DontCompile;
+
+ while (!isLastLevel(prev)) {
+ OptimizationLevel level = nextLevel(prev);
+ const OptimizationInfo* info = get(level);
+ if (script->getWarmUpCount() < info->compilerWarmUpThreshold(script, pc))
+ return prev;
+
+ prev = level;
+ }
+
+ return prev;
+}
+
+} // namespace jit
+} // namespace js