diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-28 14:29:10 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-28 14:29:10 +0000 |
commit | 2aa4a82499d4becd2284cdb482213d541b8804dd (patch) | |
tree | b80bf8bf13c3766139fbacc530efd0dd9d54394c /js/src/jit/TrialInlining.h | |
parent | Initial commit. (diff) | |
download | firefox-2aa4a82499d4becd2284cdb482213d541b8804dd.tar.xz firefox-2aa4a82499d4becd2284cdb482213d541b8804dd.zip |
Adding upstream version 86.0.1.upstream/86.0.1upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'js/src/jit/TrialInlining.h')
-rw-r--r-- | js/src/jit/TrialInlining.h | 156 |
1 files changed, 156 insertions, 0 deletions
diff --git a/js/src/jit/TrialInlining.h b/js/src/jit/TrialInlining.h new file mode 100644 index 0000000000..e3d6d83305 --- /dev/null +++ b/js/src/jit/TrialInlining.h @@ -0,0 +1,156 @@ +/* -*- 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/. */ + +#ifndef jit_TrialInlining_h +#define jit_TrialInlining_h + +#include "jit/CacheIR.h" +#include "jit/ICStubSpace.h" +#include "vm/BytecodeLocation.h" + +/* + * [SMDOC] Trial Inlining + * + * WarpBuilder relies on transpiling CacheIR. When inlining scripted + * functions in WarpBuilder, we want our ICs to be as monomorphic as + * possible. Functions with multiple callers complicate this. An IC in + * such a function might be monomorphic for any given caller, but + * polymorphic overall. This make the input to WarpBuilder less precise. + * + * To solve this problem, we do trial inlining. During baseline + * execution, we identify call sites for which it would be useful to + * have more precise inlining data. For each such call site, we + * allocate a fresh ICScript and replace the existing call IC with a + * new specialized IC that invokes the callee using the new + * ICScript. Other callers of the callee will continue using the + * default ICScript. When we eventually Warp-compile the script, we + * can generate code for the callee using the IC information in our + * private ICScript, which is specialized for its caller. + * + * The same approach can be used to inline recursively. + */ + +namespace js { +namespace jit { + +class BaselineFrame; +class ICEntry; +class ICScript; + +/* + * An InliningRoot is owned by a JitScript. In turn, it owns the set + * of ICScripts that are candidates for being inlined in that JitScript. + */ +class InliningRoot { + public: + explicit InliningRoot(JSContext* cx, JSScript* owningScript) + : owningScript_(owningScript), + inlinedScripts_(cx), + totalBytecodeSize_(owningScript->length()) {} + + FallbackICStubSpace* fallbackStubSpace() { return &fallbackStubSpace_; } + + void trace(JSTracer* trc); + + bool addInlinedScript(js::UniquePtr<ICScript> icScript); + void removeInlinedScript(ICScript* icScript); + + uint32_t numInlinedScripts() const { return inlinedScripts_.length(); } + + void purgeOptimizedStubs(Zone* zone); + void resetWarmUpCounts(uint32_t count); + + JSScript* owningScript() const { return owningScript_; } + + size_t totalBytecodeSize() const { return totalBytecodeSize_; } + + void addToTotalBytecodeSize(size_t size) { totalBytecodeSize_ += size; } + + private: + FallbackICStubSpace fallbackStubSpace_ = {}; + HeapPtr<JSScript*> owningScript_; + js::Vector<js::UniquePtr<ICScript>> inlinedScripts_; + + // Bytecode size of outer script and all inlined scripts. + size_t totalBytecodeSize_; +}; + +class InlinableOpData { + public: + JSFunction* target = nullptr; + ICScript* icScript = nullptr; + const uint8_t* endOfSharedPrefix = nullptr; +}; + +class InlinableCallData : public InlinableOpData { + public: + ObjOperandId calleeOperand; + CallFlags callFlags; +}; + +class InlinableGetterData : public InlinableOpData { + public: + ValOperandId receiverOperand; + bool sameRealm = false; +}; + +class InlinableSetterData : public InlinableOpData { + public: + ObjOperandId receiverOperand; + ValOperandId rhsOperand; + bool sameRealm = false; +}; + +mozilla::Maybe<InlinableOpData> FindInlinableOpData(ICCacheIRStub* stub, + BytecodeLocation loc); + +mozilla::Maybe<InlinableCallData> FindInlinableCallData(ICCacheIRStub* stub); +mozilla::Maybe<InlinableGetterData> FindInlinableGetterData( + ICCacheIRStub* stub); +mozilla::Maybe<InlinableSetterData> FindInlinableSetterData( + ICCacheIRStub* stub); + +class MOZ_RAII TrialInliner { + public: + TrialInliner(JSContext* cx, HandleScript script, ICScript* icScript, + InliningRoot* root) + : cx_(cx), script_(script), icScript_(icScript), root_(root) {} + + JSContext* cx() { return cx_; } + + [[nodiscard]] bool tryInlining(); + [[nodiscard]] bool maybeInlineCall(const ICEntry& entry, + BytecodeLocation loc); + [[nodiscard]] bool maybeInlineGetter(const ICEntry& entry, + BytecodeLocation loc); + [[nodiscard]] bool maybeInlineSetter(const ICEntry& entry, + BytecodeLocation loc); + + static bool canInline(JSFunction* target, HandleScript caller); + + private: + ICCacheIRStub* maybeSingleStub(const ICEntry& entry); + void cloneSharedPrefix(ICCacheIRStub* stub, const uint8_t* endOfPrefix, + CacheIRWriter& writer); + ICScript* createInlinedICScript(JSFunction* target, BytecodeLocation loc); + [[nodiscard]] bool replaceICStub(const ICEntry& entry, CacheIRWriter& writer, + CacheKind kind); + + bool shouldInline(JSFunction* target, ICCacheIRStub* stub, + BytecodeLocation loc); + + JSContext* cx_; + HandleScript script_; + ICScript* icScript_; + InliningRoot* root_; +}; + +bool DoTrialInlining(JSContext* cx, BaselineFrame* frame); + +} // namespace jit +} // namespace js + +#endif /* jit_TrialInlining_h */ |