tor-browser

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

commit 12a29323d51ed8da544013b280ff824ab889480e
parent edc1a996fb42b1106098c9604a263285a247098c
Author: Nazım Can Altınova <canaltinova@gmail.com>
Date:   Wed, 26 Nov 2025 10:52:44 +0000

Bug 2002397 - Consolidate max inlining depth constants r=iain

The maximum inlining depth was duplicated across multiple locations with
some magic numbers (8, 64) that were difficult to keep synchronized.

The actual max inlining depth used by Ion/Warp is 8. This is now defined
as InlineScriptTree::MaxDepth and used directly in multiple places.
Previously the profiler code was using 64 as the inlining depth, which
was overly conservative. Now we properly use 8 there as well.

In addition to InlineScriptTree::MaxDepth, we had to keep
ProfiledFrameRange::MaxInliningDepth in the public header since it
cannot include the private InlineScriptTree.h header. However, added a
static_assert which guarantees that it stays synchronized with
InlineScriptTree::MaxDepth.

Trial inlining uses a smaller depth of 4 (now named MaxICScriptDepth) because
it only creates private IC sets up to that depth. Beyond depth 4, inlining can
still reach depth 8 by reusing shared IC data. A static_assert ensures
MaxICScriptDepth never exceeds InlineScriptTree::MaxDepth.

Differential Revision: https://phabricator.services.mozilla.com/D274057

Diffstat:
Mjs/public/ProfilingFrameIterator.h | 7+++++--
Mjs/src/jit/InlineScriptTree.h | 7+++++++
Mjs/src/jit/JitcodeMap.cpp | 7+++++++
Mjs/src/jit/TrialInlining.cpp | 10++++++++--
Mjs/src/jit/WarpOracle.cpp | 3+--
Mjs/src/vm/Stack.cpp | 5+++--
6 files changed, 31 insertions(+), 8 deletions(-)

diff --git a/js/public/ProfilingFrameIterator.h b/js/public/ProfilingFrameIterator.h @@ -305,8 +305,11 @@ class ProfiledFrameRange { JSRuntime* rt_; void* addr_; js::jit::JitcodeGlobalEntry* entry_; - // Assume maximum inlining depth is <64 - js::jit::CallStackFrameInfo frames_[64]; + // Maximum inlining depth. This must match InlineScriptTree::MaxDepth. + // We can't use InlineScriptTree::MaxDepth directly here because this is a + // public header and InlineScriptTree.h is private. + static constexpr uint32_t MaxInliningDepth = 8; + js::jit::CallStackFrameInfo frames_[MaxInliningDepth]; uint32_t depth_; }; diff --git a/js/src/jit/InlineScriptTree.h b/js/src/jit/InlineScriptTree.h @@ -22,6 +22,13 @@ namespace jit { // To support this, use a tree that records the inlinings done during // compilation. class InlineScriptTree { + public: + // Maximum inlining depth. This is the depth used by Ion/Warp compilation. + // Trial inlining uses a smaller depth (see MaxICScriptDepth in + // TrialInlining.cpp). + static constexpr uint32_t MaxDepth = 8; + + private: // InlineScriptTree for the caller InlineScriptTree* caller_; diff --git a/js/src/jit/JitcodeMap.cpp b/js/src/jit/JitcodeMap.cpp @@ -996,6 +996,13 @@ JS_PUBLIC_API uint32_t JS::ProfiledFrameHandle::sourceId() const { JS_PUBLIC_API JS::ProfiledFrameRange JS::GetProfiledFrames(JSContext* cx, void* addr) { + // Ensure ProfiledFrameRange::MaxInliningDepth matches + // InlineScriptTree::MaxDepth. Please keep them in sync. + static_assert(ProfiledFrameRange::MaxInliningDepth == + js::jit::InlineScriptTree::MaxDepth, + "ProfiledFrameRange::MaxInliningDepth must match " + "InlineScriptTree::MaxDepth"); + JSRuntime* rt = cx->runtime(); js::jit::JitcodeGlobalTable* table = rt->jitRuntime()->getJitcodeGlobalTable(); diff --git a/js/src/jit/TrialInlining.cpp b/js/src/jit/TrialInlining.cpp @@ -15,6 +15,7 @@ #include "jit/CacheIRCloner.h" #include "jit/CacheIRHealth.h" #include "jit/CacheIRWriter.h" +#include "jit/InlineScriptTree.h" #include "jit/Ion.h" // TooManyFormalArguments #include "vm/BytecodeLocation-inl.h" @@ -72,8 +73,13 @@ bool DoTrialInlining(JSContext* cx, BaselineFrame* frame) { return true; } - const uint32_t MAX_INLINING_DEPTH = 4; - if (icScript->depth() > MAX_INLINING_DEPTH) { + // Maximum trial inlining depth for ICScripts. This is smaller than + // InlineScriptTree::MaxDepth because we can reach the bigger number if we are + // doing monomorphic inlining using shared IC data. + const uint32_t MaxICScriptDepth = 4; + static_assert(MaxICScriptDepth <= InlineScriptTree::MaxDepth, + "Trial inlining depth must not exceed max inlining depth"); + if (icScript->depth() > MaxICScriptDepth) { return true; } diff --git a/js/src/jit/WarpOracle.cpp b/js/src/jit/WarpOracle.cpp @@ -1326,9 +1326,8 @@ AbortReasonOr<bool> WarpScriptOracle::maybeInlineCall( // This is just a cheap check to limit the damage we can do to ourselves if // we try to monomorphically inline an indirectly recursive call. - const uint32_t maxInliningDepth = 8; if (!isTrialInlined && - info_->inlineScriptTree()->depth() > maxInliningDepth) { + info_->inlineScriptTree()->depth() > InlineScriptTree::MaxDepth) { return false; } diff --git a/js/src/vm/Stack.cpp b/js/src/vm/Stack.cpp @@ -13,6 +13,7 @@ #include <stdint.h> // uint8_t, uint32_t #include "gc/Tracer.h" // js::TraceRoot +#include "jit/InlineScriptTree.h" #include "jit/JitcodeMap.h" #include "jit/JitRuntime.h" #include "js/friend/ErrorMessages.h" // JSMSG_* @@ -761,8 +762,8 @@ uint32_t JS::ProfilingFrameIterator::extractStack(Frame* frames, return 1; } - // Extract the stack for the entry. Assume maximum inlining depth is <64 - jit::CallStackFrameInfo frameInfos[64]; + // Extract the stack for the entry. + jit::CallStackFrameInfo frameInfos[jit::InlineScriptTree::MaxDepth]; uint32_t depth = entry->callStackAtAddr(cx_->runtime(), jsJitIter().resumePCinCurrentFrame(), frameInfos, std::size(frameInfos));