IonOptimizationLevels.cpp (3736B)
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- 2 * vim: set ts=8 sts=2 et sw=2 tw=80: 3 * This Source Code Form is subject to the terms of the Mozilla Public 4 * License, v. 2.0. If a copy of the MPL was not distributed with this 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 7 #include "jit/IonOptimizationLevels.h" 8 9 #include "jit/Ion.h" 10 #include "jit/JitHints.h" 11 #include "jit/JitRuntime.h" 12 #include "js/Prefs.h" 13 #include "vm/JSScript.h" 14 15 #include "vm/JSScript-inl.h" 16 17 using namespace js; 18 using namespace js::jit; 19 20 namespace js { 21 namespace jit { 22 23 /*static*/ 24 uint32_t OptimizationInfo::baseWarmUpThresholdForScript(JSContext* cx, 25 JSScript* script) { 26 // If an Ion counter hint is present, override the threshold. 27 if (cx->runtime()->jitRuntime()->hasJitHintsMap()) { 28 JitHintsMap* jitHints = cx->runtime()->jitRuntime()->getJitHintsMap(); 29 uint32_t hintThreshold; 30 if (jitHints->getIonThresholdHint(script, hintThreshold)) { 31 return hintThreshold; 32 } 33 } 34 return JitOptions.normalIonWarmUpThreshold; 35 } 36 37 /*static*/ 38 uint32_t OptimizationInfo::warmUpThresholdForPC(JSScript* script, 39 jsbytecode* pc, 40 uint32_t baseThreshold) { 41 MOZ_ASSERT(pc == nullptr || pc == script->code() || 42 JSOp(*pc) == JSOp::LoopHead); 43 44 // The script must not start with a LoopHead op or the code below would be 45 // wrong. See bug 1602681. 46 MOZ_ASSERT_IF(pc && JSOp(*pc) == JSOp::LoopHead, pc > script->code()); 47 48 uint32_t warmUpThreshold = baseThreshold; 49 50 if (pc == script->code()) { 51 pc = nullptr; 52 } 53 54 // If the script is too large to compile on the main thread, we can still 55 // compile it off thread. In these cases, increase the warm-up counter 56 // threshold to improve the compilation's type information and hopefully 57 // avoid later recompilation. 58 59 if (script->length() > JitOptions.ionMaxScriptSizeMainThread) { 60 warmUpThreshold *= 61 (script->length() / double(JitOptions.ionMaxScriptSizeMainThread)); 62 } 63 64 uint32_t numLocalsAndArgs = NumLocalsAndArgs(script); 65 if (numLocalsAndArgs > JitOptions.ionMaxLocalsAndArgsMainThread) { 66 warmUpThreshold *= 67 (numLocalsAndArgs / double(JitOptions.ionMaxLocalsAndArgsMainThread)); 68 } 69 70 if (!pc || JitOptions.eagerIonCompilation()) { 71 return warmUpThreshold; 72 } 73 74 // It's more efficient to enter outer loops, rather than inner loops, via OSR. 75 // To accomplish this, we use a slightly higher threshold for inner loops. 76 // Note that the loop depth is always > 0 so we will prefer non-OSR over OSR. 77 uint32_t loopDepth = LoopHeadDepthHint(pc); 78 MOZ_ASSERT(loopDepth > 0); 79 return warmUpThreshold + loopDepth * (baseThreshold / 10); 80 } 81 82 OptimizationLevel OptimizationLevelInfo::levelForScript(JSContext* cx, 83 JSScript* script, 84 jsbytecode* pc) const { 85 uint32_t baseThreshold = 86 OptimizationInfo::baseWarmUpThresholdForScript(cx, script); 87 if (script->getWarmUpCount() < 88 OptimizationInfo::warmUpThresholdForPC(script, pc, baseThreshold)) { 89 return OptimizationLevel::DontCompile; 90 } 91 92 return OptimizationLevel::Normal; 93 } 94 95 IonRegisterAllocator OptimizationInfo::registerAllocator() const { 96 switch (JS::Prefs::ion_regalloc()) { 97 case 0: 98 default: 99 // Use the default register allocator. 100 return registerAllocator_; 101 case 1: 102 return RegisterAllocator_Backtracking; 103 case 2: 104 return RegisterAllocator_Simple; 105 } 106 MOZ_CRASH("Unreachable"); 107 } 108 109 } // namespace jit 110 } // namespace js