tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

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