/* -*- 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 { OptimizationInfos IonOptimizations; void OptimizationInfo::initNormalOptimizationInfo() { level_ = Optimization_Normal; eaa_ = true; edgeCaseAnalysis_ = true; eliminateRedundantChecks_ = true; inlineInterpreted_ = true; inlineNative_ = true; eagerSimdUnbox_ = true; gvn_ = true; licm_ = true; rangeAnalysis_ = true; loopUnrolling_ = true; reordering_ = true; autoTruncate_ = true; sincos_ = true; sink_ = true; registerAllocator_ = RegisterAllocator_Backtracking; inlineMaxBytecodePerCallSiteMainThread_ = 500; inlineMaxBytecodePerCallSiteOffThread_ = 1000; inlineMaxCalleeInlinedBytecodeLength_ = 3350; inlineMaxTotalBytecodeLength_ = 80000; inliningMaxCallerBytecodeLength_ = 1500; maxInlineDepth_ = 3; scalarReplacement_ = true; smallFunctionMaxInlineDepth_ = 13; compilerWarmUpThreshold_ = CompilerWarmupThreshold; inliningWarmUpThresholdFactor_ = 0.125; inliningRecompileThresholdFactor_ = 4; } void OptimizationInfo::initAsmjsOptimizationInfo() { // The AsmJS optimization level // Disables some passes that don't work well with asmjs. // Take normal option values for not specified values. initNormalOptimizationInfo(); ama_ = true; level_ = Optimization_AsmJS; eagerSimdUnbox_ = false; // AsmJS has no boxing / unboxing. edgeCaseAnalysis_ = false; eliminateRedundantChecks_ = false; autoTruncate_ = false; sincos_ = false; sink_ = false; registerAllocator_ = RegisterAllocator_Backtracking; scalarReplacement_ = false; // AsmJS has no objects. } 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 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; } OptimizationInfos::OptimizationInfos() { infos_[Optimization_Normal - 1].initNormalOptimizationInfo(); infos_[Optimization_AsmJS - 1].initAsmjsOptimizationInfo(); #ifdef DEBUG OptimizationLevel level = firstLevel(); while (!isLastLevel(level)) { OptimizationLevel next = nextLevel(level); MOZ_ASSERT(level < next); level = next; } #endif } OptimizationLevel OptimizationInfos::nextLevel(OptimizationLevel level) const { MOZ_ASSERT(!isLastLevel(level)); switch (level) { case Optimization_DontCompile: return Optimization_Normal; default: MOZ_CRASH("Unknown optimization level."); } } OptimizationLevel OptimizationInfos::firstLevel() const { return nextLevel(Optimization_DontCompile); } bool OptimizationInfos::isLastLevel(OptimizationLevel level) const { return level == Optimization_Normal; } OptimizationLevel OptimizationInfos::levelForScript(JSScript* script, jsbytecode* pc) const { OptimizationLevel prev = Optimization_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