From fd4e49a4901637ddde50518bf03290e8b5b5b700 Mon Sep 17 00:00:00 2001 From: Basilisk-Dev Date: Wed, 15 Apr 2026 23:56:36 -0400 Subject: [PATCH] Issue #3049 - Guard minimal JIT direct-call fast path --- js/src/jit/LoongArchMinimalJit.cpp | 53 ++++++++++++++++++++++++++++++ js/src/jit/LoongArchMinimalJit.h | 2 ++ js/src/vm/Interpreter.cpp | 8 +++++ 3 files changed, 63 insertions(+) diff --git a/js/src/jit/LoongArchMinimalJit.cpp b/js/src/jit/LoongArchMinimalJit.cpp index 75ea23b914..9b5ca7ea09 100644 --- a/js/src/jit/LoongArchMinimalJit.cpp +++ b/js/src/jit/LoongArchMinimalJit.cpp @@ -16,6 +16,7 @@ #include "jsopcode.h" #include "jsscript.h" #include "vm/Interpreter.h" +#include "vm/Stack.h" using namespace js; @@ -563,6 +564,34 @@ CanUseMinimalJit(JSScript* script, const CallArgs& args) return true; } +static bool +CanDirectCallMinimalJit(JSContext* cx, HandleFunction fun, JSScript* script, const CallArgs& args) +{ + if (!fun || !fun->isInterpreted() || !script) + return false; + + if (!CanUseMinimalJit(script, args)) + return false; + + if (fun->isSelfHostedBuiltin() || fun->isArrow() || fun->needsSomeEnvironmentObject()) + return false; + + if (script->selfHosted() || script->strict() || script->treatAsRunOnce()) + return false; + + if (cx->compartment()->isDebuggee() || cx->runtime()->profilingScripts || + cx->runtime()->spsProfiler.enabled()) + { + return false; + } + + Activation* activation = cx->runtime()->activation(); + if (!activation || !activation->isInterpreter()) + return false; + + return true; +} + static bool CanUseMinimalJit(RunState& state, InvokeState& invoke) { @@ -612,6 +641,30 @@ LookupOrCompileMinimalJit(JSContext* cx, JSScript* script, TinyLoongArchJitCode* } // namespace +bool +TryCallLoongArchMinimalJit(JSContext* cx, HandleFunction fun, const CallArgs& args, bool* handled) +{ + *handled = false; + + JSScript* script = fun ? fun->nonLazyScript() : nullptr; + if (!CanDirectCallMinimalJit(cx, fun, script, args)) + return true; + + TinyLoongArchJitCode fn; + if (!LookupOrCompileMinimalJit(cx, script, &fn)) + return true; + + int32_t result = 0; + int32_t arg0 = script->numArgs() >= 1 ? args[0].toInt32() : 0; + int32_t arg1 = script->numArgs() >= 2 ? args[1].toInt32() : 0; + if (!fn(arg0, arg1, &result)) + return true; + + args.rval().setInt32(result); + *handled = true; + return true; +} + bool TryEnterLoongArchMinimalJit(JSContext* cx, RunState& state) { diff --git a/js/src/jit/LoongArchMinimalJit.h b/js/src/jit/LoongArchMinimalJit.h index 81e5084559..f814075d97 100644 --- a/js/src/jit/LoongArchMinimalJit.h +++ b/js/src/jit/LoongArchMinimalJit.h @@ -7,6 +7,7 @@ #define jit_LoongArchMinimalJit_h #include "jspubtd.h" +#include "js/CallArgs.h" namespace js { @@ -15,6 +16,7 @@ class RunState; namespace jit { [[nodiscard]] bool TryEnterLoongArchMinimalJit(JSContext* cx, RunState& state); +[[nodiscard]] bool TryCallLoongArchMinimalJit(JSContext* cx, HandleFunction fun, const CallArgs& args, bool* handled); } // namespace jit } // namespace js diff --git a/js/src/vm/Interpreter.cpp b/js/src/vm/Interpreter.cpp index 77bc861ee8..fef8f61f29 100644 --- a/js/src/vm/Interpreter.cpp +++ b/js/src/vm/Interpreter.cpp @@ -503,6 +503,14 @@ js::InternalCallOrConstruct(JSContext* cx, const CallArgs& args, MaybeConstruct if (!JSFunction::getOrCreateScript(cx, fun)) return false; + if (construct != CONSTRUCT) { + bool handled; + if (!jit::TryCallLoongArchMinimalJit(cx, fun, args, &handled)) + return false; + if (handled) + return true; + } + /* Run function until JSOP_RETRVAL, JSOP_RETURN or error. */ InvokeState state(cx, args, construct);