diff options
Diffstat (limited to 'js/src/jit/JitHints.cpp')
-rw-r--r-- | js/src/jit/JitHints.cpp | 151 |
1 files changed, 151 insertions, 0 deletions
diff --git a/js/src/jit/JitHints.cpp b/js/src/jit/JitHints.cpp new file mode 100644 index 0000000000..6b3783ea8a --- /dev/null +++ b/js/src/jit/JitHints.cpp @@ -0,0 +1,151 @@ +/* -*- 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/BytecodeLocation-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) { + UniquePtr<IonHint> hint = MakeUnique<IonHint>(key); + if (!hint) { + return nullptr; + } + + if (!ionHintMap_.add(p, key, hint.get())) { + return nullptr; + } + + ionHintQueue_.insertBack(hint.get()); + + if (ionHintMap_.count() > IonHintMaxEntries) { + IonHint* h = ionHintQueue_.popFirst(); + ionHintMap_.remove(h->key()); + js_delete(h); + } + + return hint.release(); +} + +void JitHintsMap::updateAsRecentlyUsed(IonHint* hint) { + hint->remove(); + ionHintQueue_.insertBack(hint); +} + +bool JitHintsMap::recordIonCompilation(JSScript* script) { + ScriptKey key = getScriptKey(script); + if (!key) { + return true; + } + + // Only add hints for scripts that will be eager baseline compiled. + if (!baselineHintMap_.mightContain(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; + } + } + + hint->initThreshold(script->warmUpCountAtLastICStub()); + 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(); + // If the threshold is 0, the hint only contains + // monomorphic inlining location information and + // may not have entered Ion before. + if (hint->threshold() != 0) { + 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); + } + } +} + +bool JitHintsMap::addMonomorphicInlineLocation(JSScript* script, + BytecodeLocation loc) { + ScriptKey key = getScriptKey(script); + if (!key) { + return true; + } + + // Only add inline hints for scripts that will be eager baseline compiled. + if (!baselineHintMap_.mightContain(key)) { + return true; + } + + auto p = ionHintMap_.lookupForAdd(key); + IonHint* hint = nullptr; + if (p) { + hint = p->value(); + } else { + hint = addIonHint(key, p); + if (!hint) { + return false; + } + } + + if (!hint->hasSpaceForMonomorphicInlineEntry()) { + return true; + } + + uint32_t offset = loc.bytecodeToOffset(script); + return hint->addMonomorphicInlineOffset(offset); +} + +bool JitHintsMap::hasMonomorphicInlineHintAtOffset(JSScript* script, + uint32_t offset) { + ScriptKey key = getScriptKey(script); + if (!key) { + return false; + } + + auto p = ionHintMap_.lookup(key); + if (p) { + return p->value()->hasMonomorphicInlineOffset(offset); + } + + return false; +} |