tor-browser

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

JitHints.cpp (4697B)


      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/JitHints-inl.h"
      8 
      9 #include "gc/Pretenuring.h"
     10 
     11 #include "vm/BytecodeLocation-inl.h"
     12 #include "vm/JSScript-inl.h"
     13 
     14 using namespace js;
     15 using namespace js::jit;
     16 
     17 JitHintsMap::~JitHintsMap() {
     18  while (!ionHintQueue_.isEmpty()) {
     19    IonHint* e = ionHintQueue_.popFirst();
     20    js_delete(e);
     21  }
     22  ionHintMap_.clear();
     23 }
     24 
     25 JitHintsMap::IonHint* JitHintsMap::addIonHint(ScriptKey key,
     26                                              ScriptToHintMap::AddPtr& p) {
     27  UniquePtr<IonHint> hint = MakeUnique<IonHint>(key);
     28  if (!hint) {
     29    return nullptr;
     30  }
     31 
     32  if (!ionHintMap_.add(p, key, hint.get())) {
     33    return nullptr;
     34  }
     35 
     36  ionHintQueue_.insertBack(hint.get());
     37 
     38  if (ionHintMap_.count() > IonHintMaxEntries) {
     39    IonHint* h = ionHintQueue_.popFirst();
     40    ionHintMap_.remove(h->key());
     41    js_delete(h);
     42  }
     43 
     44  return hint.release();
     45 }
     46 
     47 void JitHintsMap::updateAsRecentlyUsed(IonHint* hint) {
     48  hint->remove();
     49  ionHintQueue_.insertBack(hint);
     50 }
     51 
     52 bool JitHintsMap::recordIonCompilation(JSScript* script) {
     53  ScriptKey key = getScriptKey(script);
     54  if (!key) {
     55    return true;
     56  }
     57 
     58  // Only add hints for scripts that will be eager baseline compiled.
     59  if (!baselineHintMap_.mightContain(key)) {
     60    return true;
     61  }
     62 
     63  auto p = ionHintMap_.lookupForAdd(key);
     64  IonHint* hint = nullptr;
     65  if (p) {
     66    // Don't modify existing threshold values.
     67    hint = p->value();
     68    updateAsRecentlyUsed(hint);
     69  } else {
     70    hint = addIonHint(key, p);
     71    if (!hint) {
     72      return false;
     73    }
     74  }
     75 
     76  uint32_t threshold = IonHintEagerThresholdValue(
     77      script->warmUpCountAtLastICStub(),
     78      script->jitScript()->hasPretenuredAllocSites());
     79 
     80  hint->initThreshold(threshold);
     81  return true;
     82 }
     83 
     84 // static
     85 uint32_t JitHintsMap::IonHintEagerThresholdValue(uint32_t lastStubCounter,
     86                                                 bool hasPretenuredAllocSites) {
     87  // Use the counter when the last IC stub was attached as the initial
     88  // threshold.
     89  uint32_t eagerThreshold = lastStubCounter;
     90 
     91  // Ensure we stay in baseline long enough to pretenure alloc sites.
     92  if (hasPretenuredAllocSites) {
     93    eagerThreshold =
     94        std::max(eagerThreshold, uint32_t(gc::NormalSiteAttentionThreshold));
     95  }
     96 
     97  // Add 10 for some wiggle room and to safeguard against cases where the
     98  // lastStubCounter is 0.
     99  eagerThreshold += 10;
    100 
    101  // Do not exceed the default Ion threshold value set in the options.
    102  return std::min(eagerThreshold, JitOptions.normalIonWarmUpThreshold);
    103 }
    104 
    105 bool JitHintsMap::getIonThresholdHint(JSScript* script,
    106                                      uint32_t& thresholdOut) {
    107  ScriptKey key = getScriptKey(script);
    108  if (key) {
    109    auto p = ionHintMap_.lookup(key);
    110    if (p) {
    111      IonHint* hint = p->value();
    112      // If the threshold is 0, the hint only contains
    113      // monomorphic inlining location information and
    114      // may not have entered Ion before.
    115      if (hint->threshold() != 0) {
    116        updateAsRecentlyUsed(hint);
    117        thresholdOut = hint->threshold();
    118        return true;
    119      }
    120    }
    121  }
    122  return false;
    123 }
    124 
    125 void JitHintsMap::recordInvalidation(JSScript* script) {
    126  ScriptKey key = getScriptKey(script);
    127  if (key) {
    128    auto p = ionHintMap_.lookup(key);
    129    if (p) {
    130      p->value()->incThreshold(InvalidationThresholdIncrement);
    131    }
    132  }
    133 }
    134 
    135 bool JitHintsMap::addMonomorphicInlineLocation(JSScript* script,
    136                                               BytecodeLocation loc) {
    137  ScriptKey key = getScriptKey(script);
    138  if (!key) {
    139    return true;
    140  }
    141 
    142  // Only add inline hints for scripts that will be eager baseline compiled.
    143  if (!baselineHintMap_.mightContain(key)) {
    144    return true;
    145  }
    146 
    147  auto p = ionHintMap_.lookupForAdd(key);
    148  IonHint* hint = nullptr;
    149  if (p) {
    150    hint = p->value();
    151  } else {
    152    hint = addIonHint(key, p);
    153    if (!hint) {
    154      return false;
    155    }
    156  }
    157 
    158  if (!hint->hasSpaceForMonomorphicInlineEntry()) {
    159    return true;
    160  }
    161 
    162  uint32_t offset = loc.bytecodeToOffset(script);
    163  return hint->addMonomorphicInlineOffset(offset);
    164 }
    165 
    166 bool JitHintsMap::hasMonomorphicInlineHintAtOffset(JSScript* script,
    167                                                   uint32_t offset) {
    168  ScriptKey key = getScriptKey(script);
    169  if (!key) {
    170    return false;
    171  }
    172 
    173  auto p = ionHintMap_.lookup(key);
    174  if (p) {
    175    return p->value()->hasMonomorphicInlineOffset(offset);
    176  }
    177 
    178  return false;
    179 }