Backed out changeset ab845ce2e822 (bug 1837192) for causing spidermonkey build bustages. CLOSED TREE

This commit is contained in:
Iulian Moraru 2023-07-11 19:40:57 +03:00
Родитель 9c7a1ae2e1
Коммит 804da488b4
10 изменённых файлов: 35 добавлений и 236 удалений

Просмотреть файл

@ -1655,12 +1655,6 @@ static void InvalidateAfterBailout(JSContext* cx, HandleScript outerScript,
return;
}
// Record a invalidation for this script in the jit hints map
if (cx->runtime()->jitRuntime()->hasJitHintsMap()) {
JitHintsMap* jitHints = cx->runtime()->jitRuntime()->getJitHintsMap();
jitHints->recordInvalidation(outerScript);
}
MOZ_ASSERT(!outerScript->ionScript()->invalidated());
JitSpew(JitSpew_BaselineBailouts, "Invalidating due to %s", reason);

Просмотреть файл

@ -1476,7 +1476,7 @@ bool BaselineCompilerCodeGen::emitWarmUpCounterIncrement() {
const OptimizationInfo* info =
IonOptimizations.get(OptimizationLevel::Normal);
uint32_t warmUpThreshold = info->compilerWarmUpThreshold(cx, script, pc);
uint32_t warmUpThreshold = info->compilerWarmUpThreshold(script, pc);
masm.branch32(Assembler::LessThan, countReg, Imm32(warmUpThreshold), &done);
// Don't trigger Warp compilations from trial-inlined scripts.

Просмотреть файл

@ -14161,12 +14161,6 @@ bool CodeGenerator::link(JSContext* cx, const WarpSnapshot* snapshot) {
vtune::MarkScript(code, script, "ion");
#endif
// Set a Ion counter hint for this script.
if (cx->runtime()->jitRuntime()->hasJitHintsMap()) {
JitHintsMap* jitHints = cx->runtime()->jitRuntime()->getJitHintsMap();
jitHints->recordIonCompilation(script);
}
// for marking during GC.
if (safepointIndices_.length()) {
ionScript->copySafepointIndices(&safepointIndices_[0]);

Просмотреть файл

@ -1858,7 +1858,7 @@ static MethodStatus Compile(JSContext* cx, HandleScript script,
}
OptimizationLevel optimizationLevel =
IonOptimizations.levelForScript(cx, script, osrPc);
IonOptimizations.levelForScript(script, osrPc);
if (optimizationLevel == OptimizationLevel::DontCompile) {
return Method_Skipped;
}

Просмотреть файл

@ -59,8 +59,7 @@ void OptimizationInfo::initWasmOptimizationInfo() {
sink_ = false;
}
uint32_t OptimizationInfo::compilerWarmUpThreshold(JSContext* cx,
JSScript* script,
uint32_t OptimizationInfo::compilerWarmUpThreshold(JSScript* script,
jsbytecode* pc) const {
MOZ_ASSERT(pc == nullptr || pc == script->code() ||
JSOp(*pc) == JSOp::LoopHead);
@ -69,21 +68,12 @@ uint32_t OptimizationInfo::compilerWarmUpThreshold(JSContext* cx,
// wrong. See bug 1602681.
MOZ_ASSERT_IF(pc && JSOp(*pc) == JSOp::LoopHead, pc > script->code());
uint32_t warmUpThreshold = baseCompilerWarmUpThreshold();
// If an Ion counter hint is present, override the threshold.
if (cx->runtime()->jitRuntime()->hasJitHintsMap()) {
JitHintsMap* jitHints = cx->runtime()->jitRuntime()->getJitHintsMap();
uint32_t hintThreshold;
if (jitHints->getIonThresholdHint(script, hintThreshold)) {
warmUpThreshold = hintThreshold;
}
}
if (pc == script->code()) {
pc = nullptr;
}
uint32_t warmUpThreshold = baseCompilerWarmUpThreshold();
// 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
@ -112,12 +102,11 @@ uint32_t OptimizationInfo::compilerWarmUpThreshold(JSContext* cx,
return warmUpThreshold + loopDepth * (baseCompilerWarmUpThreshold() / 10);
}
uint32_t OptimizationInfo::recompileWarmUpThreshold(JSContext* cx,
JSScript* script,
uint32_t OptimizationInfo::recompileWarmUpThreshold(JSScript* script,
jsbytecode* pc) const {
MOZ_ASSERT(pc == script->code() || JSOp(*pc) == JSOp::LoopHead);
uint32_t threshold = compilerWarmUpThreshold(cx, script, pc);
uint32_t threshold = compilerWarmUpThreshold(script, pc);
if (JSOp(*pc) != JSOp::LoopHead || JitOptions.eagerIonCompilation()) {
return threshold;
}
@ -138,12 +127,10 @@ OptimizationLevelInfo::OptimizationLevelInfo() {
infos_[OptimizationLevel::Wasm].initWasmOptimizationInfo();
}
OptimizationLevel OptimizationLevelInfo::levelForScript(JSContext* cx,
JSScript* script,
OptimizationLevel OptimizationLevelInfo::levelForScript(JSScript* script,
jsbytecode* pc) const {
const OptimizationInfo* info = get(OptimizationLevel::Normal);
if (script->getWarmUpCount() <
info->compilerWarmUpThreshold(cx, script, pc)) {
if (script->getWarmUpCount() < info->compilerWarmUpThreshold(script, pc)) {
return OptimizationLevel::DontCompile;
}

Просмотреть файл

@ -124,11 +124,10 @@ class OptimizationInfo {
return inlineNative_ && !JitOptions.disableInlining;
}
uint32_t compilerWarmUpThreshold(JSContext* cx, JSScript* script,
uint32_t compilerWarmUpThreshold(JSScript* script,
jsbytecode* pc = nullptr) const;
uint32_t recompileWarmUpThreshold(JSContext* cx, JSScript* script,
jsbytecode* pc) const;
uint32_t recompileWarmUpThreshold(JSScript* script, jsbytecode* pc) const;
bool gvnEnabled() const { return gvn_ && !JitOptions.disableGvn; }
@ -192,7 +191,7 @@ class OptimizationLevelInfo {
return &infos_[level];
}
OptimizationLevel levelForScript(JSContext* cx, JSScript* script,
OptimizationLevel levelForScript(JSScript* script,
jsbytecode* pc = nullptr) const;
};

Просмотреть файл

@ -20,12 +20,12 @@ inline JitHintsMap::ScriptKey JitHintsMap::getScriptKey(
return 0;
}
inline void JitHintsMap::incrementBaselineEntryCount() {
inline void JitHintsMap::incrementEntryCount() {
// Clear the cache if we've exceeded the false positivity rate
// calculated by MaxEntries.
if (++baselineEntryCount_ > MaxEntries_) {
baselineHintMap_.clear();
baselineEntryCount_ = 0;
if (++entryCount_ > MaxEntries_) {
map_.clear();
entryCount_ = 0;
}
}
@ -36,20 +36,20 @@ inline void JitHintsMap::setEagerBaselineHint(JSScript* script) {
}
// If the entry already exists, don't increment entryCount.
if (baselineHintMap_.mightContain(key)) {
if (map_.mightContain(key)) {
return;
}
// Increment entry count, and possibly clear the cache.
incrementBaselineEntryCount();
incrementEntryCount();
script->setNoEagerBaselineHint(false);
baselineHintMap_.add(key);
map_.add(key);
}
inline bool JitHintsMap::mightHaveEagerBaselineHint(JSScript* script) const {
if (ScriptKey key = getScriptKey(script)) {
return baselineHintMap_.mightContain(key);
return map_.mightContain(key);
}
script->setNoEagerBaselineHint(true);
return false;

Просмотреть файл

@ -1,93 +0,0 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
* vim: set ts=8 sts=2 et sw=2 tw=80:
* 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/JitHints-inl.h"
#include "vm/JSScript-inl.h"
using namespace js;
using namespace js::jit;
JitHintsMap::~JitHintsMap() {
while (!ionHintQueue_.isEmpty()) {
IonHint* e = ionHintQueue_.popFirst();
js_delete(e);
}
ionHintMap_.clear();
}
JitHintsMap::IonHint* JitHintsMap::addIonHint(ScriptKey key,
ScriptToHintMap::AddPtr& p) {
if (ionHintMap_.count() >= IonHintCacheSize) {
IonHint* h = ionHintQueue_.popFirst();
ionHintMap_.remove(h->key());
js_delete(h);
}
IonHint* hint = js_new<IonHint>(key);
if (!hint) {
return nullptr;
}
if (!ionHintMap_.add(p, key, hint)) {
return nullptr;
}
ionHintQueue_.insertBack(hint);
return hint;
}
void JitHintsMap::updateAsRecentlyUsed(IonHint* hint) {
hint->remove();
ionHintQueue_.insertBack(hint);
}
bool JitHintsMap::recordIonCompilation(JSScript* script) {
ScriptKey key = getScriptKey(script);
if (!key) {
return true;
}
auto p = ionHintMap_.lookupForAdd(key);
IonHint* hint = nullptr;
if (p) {
// Don't modify existing threshold values.
hint = p->value();
updateAsRecentlyUsed(hint);
} else {
hint = addIonHint(key, p);
if (!hint) {
return false;
}
}
return true;
}
bool JitHintsMap::getIonThresholdHint(JSScript* script,
uint32_t& thresholdOut) {
ScriptKey key = getScriptKey(script);
if (key) {
auto p = ionHintMap_.lookup(key);
if (p) {
IonHint* hint = p->value();
updateAsRecentlyUsed(hint);
thresholdOut = hint->threshold();
return true;
}
}
return false;
}
void JitHintsMap::recordInvalidation(JSScript* script) {
ScriptKey key = getScriptKey(script);
if (key) {
auto p = ionHintMap_.lookup(key);
if (p) {
p->value()->incThreshold(InvalidationThresholdIncrement);
}
}
}

Просмотреть файл

@ -8,102 +8,29 @@
#define jit_JitHints_h
#include "mozilla/BloomFilter.h"
#include "mozilla/HashTable.h"
#include "mozilla/LinkedList.h"
#include "vm/JSScript.h"
namespace js::jit {
/*
* The JitHintsMap implements a BitBloomFilter to track whether or not a script,
* identified by filename+sourceStart, has been baseline compiled before in the
* same process. This can occur frequently during navigations.
*
* [SMDOC] JitHintsMap
*
* The Jit hints map is an in process cache used to collect Baseline and Ion
* JIT hints to try and skip as much of the warmup as possible and jump
* straight into those tiers. Whenever a script enters one of these tiers
* a hint is recorded in this cache using the script's filename+sourceStart
* value, and if we ever encounter this script again later, e.g. during a
* navigation, then we try to eagerly compile it into baseline and ion
* based on its previous execution history.
* The bloom filter allows us to have very efficient storage and lookup costs,
* at the expense of occasional false positives. The number of entries added
* to the bloom filter is monitored in order to try and keep the false
* positivity rate below 1%. If the entry count exceeds MaxEntries_, which
* indicates the false positivity rate may exceed 1.5%, then the filter is
* completely cleared to reset the cache.
*/
class JitHintsMap {
// ScriptKey is a hash on the filename+sourceStart.
using ScriptKey = HashNumber;
ScriptKey getScriptKey(JSScript* script) const;
/* Ion Hints
* -------------------------------------------------------------------------
* This implementation uses a combination of a HashMap and PriorityQueue
* to store a threshold value for each script that has been Ion compiled.
* The PriorityQueue is used to track the least recently used entries so
* that the cache does not exceed |IonHintCacheSize| entries.
*
* After a script has entered Ion the first time, an eager threshold hint
* value of |JitOptions.trialInliningWarmUpThreshold+50| is set and if that
* script is bailout invalidated, the threshold value is incremented by
* |InvalidationThresholdIncrement| up to a maximum value of
* |JitOptions.normalIonWarmUpThreshold|.
*
*/
class IonHint : public mozilla::LinkedListElement<IonHint> {
ScriptKey key_ = 0;
uint32_t threshold_ = 0;
public:
explicit IonHint(ScriptKey key) {
key_ = key;
threshold_ = IonHintEagerThresholdValue();
}
uint32_t threshold() { return threshold_; }
void incThreshold(uint32_t inc) {
uint32_t newThreshold = threshold() + inc;
threshold_ = (newThreshold > JitOptions.normalIonWarmUpThreshold)
? JitOptions.normalIonWarmUpThreshold
: newThreshold;
}
ScriptKey key() {
MOZ_ASSERT(key_ != 0, "Should have valid key.");
return key_;
}
};
using ScriptToHintMap =
HashMap<ScriptKey, IonHint*, js::DefaultHasher<ScriptKey>,
js::SystemAllocPolicy>;
using IonHintPriorityQueue = mozilla::LinkedList<IonHint>;
static constexpr uint32_t InvalidationThresholdIncrement = 500;
static constexpr uint32_t IonHintCacheSize = 5000;
static constexpr uint32_t InitialIonHintThresholdModifier = 50;
static uint32_t IonHintEagerThresholdValue() {
return JitOptions.trialInliningWarmUpThreshold +
InitialIonHintThresholdModifier;
}
ScriptToHintMap ionHintMap_;
IonHintPriorityQueue ionHintQueue_;
/* Baseline Hints
* --------------------------------------------------------------------------
* This implementation uses a BitBloomFilter to track whether or not a script
* has been baseline compiled before in the same process. This can occur
* frequently during navigations.
*
* The bloom filter allows us to have very efficient storage and lookup costs,
* at the expense of occasional false positives. Using a bloom filter also
* allows us to have many more entries at minimal memory and allocation cost.
* The number of entries added to the bloom filter is monitored in order to
* try and keep the false positivity rate below 1%. If the entry count
* exceeds MaxEntries_, which indicates the false positivity rate may exceed
* 1.5%, then the filter is completely cleared to reset the cache.
*/
static constexpr uint32_t EagerBaselineCacheSize_ = 16;
mozilla::BitBloomFilter<EagerBaselineCacheSize_, ScriptKey> baselineHintMap_;
static constexpr uint32_t CacheSize_ = 16;
mozilla::BitBloomFilter<CacheSize_, ScriptKey> map_;
/*
* MaxEntries_ is the approximate entry count for which the
@ -112,25 +39,17 @@ class JitHintsMap {
* MaxEntries_ = floor(m / (-k / ln(1-exp(ln(p) / k))))
*/
static constexpr uint32_t MaxEntries_ = 4281;
static_assert(EagerBaselineCacheSize_ == 16 && MaxEntries_ == 4281,
static_assert(CacheSize_ == 16 && MaxEntries_ == 4281,
"MaxEntries should be recalculated for given CacheSize.");
uint32_t baselineEntryCount_ = 0;
void incrementBaselineEntryCount();
uint32_t entryCount_ = 0;
void updateAsRecentlyUsed(IonHint* hint);
IonHint* addIonHint(ScriptKey key, ScriptToHintMap::AddPtr& p);
ScriptKey getScriptKey(JSScript* script) const;
void incrementEntryCount();
public:
~JitHintsMap();
void setEagerBaselineHint(JSScript* script);
bool mightHaveEagerBaselineHint(JSScript* script) const;
bool recordIonCompilation(JSScript* script);
bool getIonThresholdHint(JSScript* script, uint32_t& thresholdOut);
void recordInvalidation(JSScript* script);
};
} // namespace js::jit

Просмотреть файл

@ -52,7 +52,6 @@ UNIFIED_SOURCES += [
"JitcodeMap.cpp",
"JitContext.cpp",
"JitFrames.cpp",
"JitHints.cpp",
"JitOptions.cpp",
"JitScript.cpp",
"JitSpewer.cpp",