Repository: WebKit/WebKit
Pull request #45781: [JSC] eval calls should not create JSCallee for each invocation
Author: login: Constellation
Labels: name: JavaScriptCore
description: For bugs in JavaScriptCore, the JS engine used by WebKit, other than kxmlcore issues.
Created: 2025-05-22T18:42:46Z | Merged: 2025-05-22T20:45:05Z

#### ab44891565710ba6b36f78d4050ae1a3b9669713
<pre>
[JSC] eval calls should not create JSCallee for each invocation
<a href="https://bugs.webkit.org/show_bug.cgi?id=293441">https://bugs.webkit.org/show_bug.cgi?id=293441</a>
<a href="https://rdar.apple.com/151868073">rdar://151868073</a>

Reviewed by Yijia Huang.

Right now eval call creates JSCallee for each invocation. But this is
wasteful since only use of this callee is getting a scope from that.

1. This patch tweaks BytecodeGenerator. When eval code is generated, we
   will never emit op_get_scope. op_enter will first get the scope at
   the beginning of the eval, and after that, we should use this scope.
   Then, we can freely change m_scope of JSCallee after that (since this
   is the beginning of the eval). We add m_topLevelScopeRegister for
   eval (and module) and use it instead of op_get_scope when necessary.
2. DFG should emit GetEvalScope instead of GetScope. They are generating
   the same code, but large difference is that GetEvalScope does not
   generate Pure result and it read(World) in the clobberzing phase.
   This models eval&apos;s scope obtainment correctly since if we call eval
   later, it may clobber scope field of the shared eval JSCallee. So
   GetEvalScope should rely on the current World state. We also remove
   constant folding / AI for GetEvalScope since they are not useful
   since it does not get JSFunction.

* Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp:
(JSC::BytecodeGenerator::BytecodeGenerator):
(JSC::BytecodeGenerator::emitResolveScopeForHoistingFuncDeclInEval):
(JSC::BytecodeGenerator::restoreScopeRegister):
(JSC::BytecodeGenerator::emitGetScope): Deleted.
* Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h:
* Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h:
(JSC::DFG::AbstractInterpreter&lt;AbstractStateType&gt;::executeEffects):
* Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp:
(JSC::DFG::ByteCodeParser::parseBlock):
* Source/JavaScriptCore/dfg/DFGClobberize.h:
(JSC::DFG::clobberize):
* Source/JavaScriptCore/dfg/DFGCloneHelper.h:
* Source/JavaScriptCore/dfg/DFGDoesGC.cpp:
(JSC::DFG::doesGC):
* Source/JavaScriptCore/dfg/DFGFixupPhase.cpp:
(JSC::DFG::FixupPhase::fixupNode):
* Source/JavaScriptCore/dfg/DFGMayExit.cpp:
* Source/JavaScriptCore/dfg/DFGNodeType.h:
* Source/JavaScriptCore/dfg/DFGObjectAllocationSinkingPhase.cpp:
* Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp:
* Source/JavaScriptCore/dfg/DFGSafeToExecute.h:
(JSC::DFG::safeToExecute):
* Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp:
* Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h:
* Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp:
(JSC::DFG::SpeculativeJIT::compile):
* Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp:
(JSC::DFG::SpeculativeJIT::emitCall):
(JSC::DFG::SpeculativeJIT::compile):
(JSC::DFG::SpeculativeJIT::compileNewBoundFunction):
* Source/JavaScriptCore/ftl/FTLAbstractHeapRepository.h:
* Source/JavaScriptCore/ftl/FTLCapabilities.cpp:
(JSC::FTL::canCompile):
* Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp:
(JSC::FTL::DFG::LowerDFGToB3::compileNode):
(JSC::FTL::DFG::LowerDFGToB3::compileNewFunction):
(JSC::FTL::DFG::LowerDFGToB3::compileNewBoundFunction):
(JSC::FTL::DFG::LowerDFGToB3::compileGetScopeOrGetEvalScope):
(JSC::FTL::DFG::LowerDFGToB3::compileCompareStrictEq):
(JSC::FTL::DFG::LowerDFGToB3::compileGetScope): Deleted.
* Source/JavaScriptCore/interpreter/Interpreter.cpp:
(JSC::Interpreter::executeEval):
* Source/JavaScriptCore/jit/JITOpcodes.cpp:
(JSC::JIT::emitGetScope):
* Source/JavaScriptCore/jit/ThunkGenerators.cpp:
(JSC::nativeForGenerator):
(JSC::boundFunctionCallGenerator):
(JSC::remoteFunctionCallGenerator):
* Source/JavaScriptCore/llint/LowLevelInterpreter32_64.asm:
* Source/JavaScriptCore/llint/LowLevelInterpreter64.asm:
* Source/JavaScriptCore/runtime/JSCallee.h:
(JSC::JSCallee::scopeUnchecked): Deleted.
* Source/JavaScriptCore/runtime/JSFunction.h:
(JSC::JSFunction::scopeUnchecked):
* Source/JavaScriptCore/runtime/JSGlobalObject.cpp:
(JSC::JSGlobalObject::init):
(JSC::JSGlobalObject::visitChildrenImpl):
* Source/JavaScriptCore/runtime/JSGlobalObject.h:
(JSC::JSGlobalObject::evalCallee):

Canonical link: <a href="https://commits.webkit.org/295296@main">https://commits.webkit.org/295296@main</a>
</pre>
<!--EWS-Status-Bubble-Start-->
https://github.com/WebKit/WebKit/commit/4ad7fb2ee6e7c51c9147f2fe7d765fc5e5452a44

| Misc | iOS, visionOS, tvOS & watchOS  | macOS  | Linux |  Windows |
| ----- | ---------------------- | ------- |  ----- |  --------- |
| [✅ 🧪 style](https://ews-build.webkit.org/#/builders/38/builds/104688 "Passed style check") | [  ~~🛠 ios~~](https://ews-build.webkit.org/#/builders/131/builds/24400 "The change is no longer eligible for processing. Pull Request was already closed when EWS attempted to process it.") | [✅ 🛠 mac](https://ews-build.webkit.org/#/builders/138/builds/14821 "Built successfully") | [✅ 🛠 wpe](https://ews-build.webkit.org/#/builders/5/builds/109902 "Built successfully") | [  ~~🛠 win~~](https://ews-build.webkit.org/#/builders/59/builds/55362 "The change is no longer eligible for processing. Pull Request was already closed when EWS attempted to process it.") 
| | [✅ 🛠 ios-sim](https://ews-build.webkit.org/#/builders/130/builds/24791 "Built successfully") | [✅ 🛠 mac-AS-debug](https://ews-build.webkit.org/#/builders/123/builds/32946 "Built successfully") | [  ~~🧪 wpe-wk2~~](https://ews-build.webkit.org/#/builders/34/builds/79500 "The change is no longer eligible for processing. Commit was outdated when EWS attempted to process it.") | [  ~~🧪 win-tests~~](https://ews-build.webkit.org/#/builders/59/builds/55362 "The change is no longer eligible for processing. Pull Request was already closed when EWS attempted to process it.") 
| [✅ 🧪 webkitperl](https://ews-build.webkit.org/#/builders/11/builds/107694 "Passed tests") | [  ~~🧪 ios-wk2~~](https://ews-build.webkit.org/#/builders/132/builds/19287 "The change is no longer eligible for processing. Pull Request was already closed when EWS attempted to process it.") | [  ~~🧪 api-mac~~](https://ews-build.webkit.org/#/builders/18/builds/94486 "The change is no longer eligible for processing. Commit was outdated when EWS attempted to process it.") | [✅ 🧪 api-wpe](https://ews-build.webkit.org/#/builders/41/builds/59806 "Passed tests") | 
| | [  ~~🧪 ios-wk2-wpt~~](https://ews-build.webkit.org/#/builders/133/builds/19054 "The change is no longer eligible for processing. Pull Request was already closed when EWS attempted to process it.") | [✅ 🧪 mac-wk1](https://ews-build.webkit.org/#/builders/135/builds/12561 "Passed tests") | [✅ 🛠 wpe-cairo](https://ews-build.webkit.org/#/builders/65/builds/54737 "Built successfully") | 
| [  ~~🛠 🧪 jsc~~](https://ews-build.webkit.org/#/builders/20/builds/97369 "The change is no longer eligible for processing. Pull Request was already closed when EWS attempted to process it.") | [  ~~🧪 api-ios~~](https://ews-build.webkit.org/#/builders/13/builds/88750 "The change is no longer eligible for processing. Pull Request was already closed when EWS attempted to process it.") | [  ~~🧪 mac-wk2~~](https://ews-build.webkit.org/#/builders/136/builds/12611 "The change is no longer eligible for processing. Pull Request was already closed when EWS attempted to process it.") | [✅ 🛠 gtk](https://ews-build.webkit.org/#/builders/2/builds/112297 "Built successfully") | 
| [✅ 🛠 🧪 jsc-arm64](https://ews-build.webkit.org/#/builders/12/builds/103306 "Built successfully and passed tests") | [  ~~🛠 vision~~](https://ews-build.webkit.org/#/builders/128/builds/31853 "The change is no longer eligible for processing. Pull Request was already closed when EWS attempted to process it.") | [  ~~🧪 mac-AS-debug-wk2~~](https://ews-build.webkit.org/#/builders/122/builds/23437 "The change is no longer eligible for processing. Pull Request was already closed when EWS attempted to process it.") | [⏳ 🧪 gtk-wk2](https://ews-build.webkit.org/#/builders/GTK-WK2-Tests-EWS "Waiting to run tests") | 
| | [  ~~🛠 vision-sim~~](https://ews-build.webkit.org/#/builders/121/builds/32217 "The change is no longer eligible for processing. Pull Request was already closed when EWS attempted to process it.") | [✅ 🧪 mac-wk2-stress](https://ews-build.webkit.org/#/builders/8/builds/90715 "Passed tests") | [⏳ 🧪 api-gtk](https://ews-build.webkit.org/#/builders/API-Tests-GTK-EWS "Waiting to run tests") | 
| | [⏳ 🧪 vision-wk2 ](https://ews-build.webkit.org/#/builders/visionOS-2-Simulator-WK2-Tests-EWS "Waiting in queue, processing has not started yet") | [  ~~🧪 mac-intel-wk2~~](https://ews-build.webkit.org/#/builders/137/builds/10868 "The change is no longer eligible for processing. Pull Request was already closed when EWS attempted to process it.") | [  ~~🛠 playstation~~](https://ews-build.webkit.org/#/builders/134/builds/27166 "The change is no longer eligible for processing. Pull Request was already closed when EWS attempted to process it.") | 
| [✅ 🛠 🧪 unsafe-merge](https://ews-build.webkit.org/#/builders/22/builds/16984 "Built successfully and passed tests") | [  ~~🛠 tv~~](https://ews-build.webkit.org/#/builders/127/builds/31778 "The change is no longer eligible for processing. Pull Request was already closed when EWS attempted to process it.") | [  ~~🛠 mac-safer-cpp~~](https://ews-build.webkit.org/#/builders/120/builds/37130 "The change is no longer eligible for processing. Pull Request was already closed when EWS attempted to process it.") | [  ~~🛠 jsc-armv7~~](https://ews-build.webkit.org/#/builders/35/builds/127585 "The change is no longer eligible for processing. Pull Request was already closed when EWS attempted to process it.") | 
| | [  ~~🛠 tv-sim~~](https://ews-build.webkit.org/#/builders/125/builds/31570 "The change is no longer eligible for processing. Pull Request was already closed when EWS attempted to process it.") | | [  ~~🧪 jsc-armv7-tests~~](https://ews-build.webkit.org/#/builders/35/builds/127585 "The change is no longer eligible for processing. Pull Request was already closed when EWS attempted to process it.") | 
| | [  ~~🛠 watch~~](https://ews-build.webkit.org/#/builders/129/builds/34911 "The change is no longer eligible for processing. Pull Request was already closed when EWS attempted to process it.") | | | 
| | [  ~~🛠 watch-sim~~](https://ews-build.webkit.org/#/builders/124/builds/33129 "The change is no longer eligible for processing. Pull Request was already closed when EWS attempted to process it.") | | | 
<!--EWS-Status-Bubble-End-->


Diff:
diff --git a/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp b/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp
index 3141c2f2f161..0fbd076d74d0 100644
--- a/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp
+++ b/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp
@@ -951,9 +951,11 @@ BytecodeGenerator::BytecodeGenerator(VM& vm, EvalNode* evalNode, UnlinkedEvalCod
     m_cachedParentTDZ = parentScopeTDZVariables;
 
     emitEnter();
-
     allocateScope();
-    
+    m_topLevelScopeRegister = addVar();
+    m_topLevelScopeRegister->ref();
+    move(m_topLevelScopeRegister, scopeRegister());
+
     for (FunctionMetadataNode* function : evalNode->functionStack()) {
         m_codeBlock->addFunctionDecl(makeFunction(function));
         m_functionsToInitialize.append(std::make_pair(function, TopLevelFunctionVariable));
@@ -1045,11 +1047,11 @@ BytecodeGenerator::BytecodeGenerator(VM& vm, ModuleProgramNode* moduleProgramNod
     }
 
     emitEnter();
-
     allocateScope();
-    RegisterID* moduleScope = addVar();
-    move(moduleScope, scopeRegister());
-    
+    m_topLevelScopeRegister = addVar();
+    m_topLevelScopeRegister->ref();
+    move(m_topLevelScopeRegister, scopeRegister());
+
     m_calleeRegister.setIndex(CallFrameSlot::callee);
 
     m_codeBlock->setNumParameters(static_cast<unsigned>(AbstractModuleRecord::Argument::NumberOfArguments) + 1); // Allocate space for "this" + async module arguments.
@@ -1091,7 +1093,7 @@ BytecodeGenerator::BytecodeGenerator(VM& vm, ModuleProgramNode* moduleProgramNod
     pushTDZVariables(lexicalVariables, TDZCheckOptimization::Optimize, TDZRequirement::UnderTDZ);
     bool isWithScope = false;
 
-    m_lexicalScopeStack.append({ moduleEnvironmentSymbolTable, moduleScope, isWithScope, constantSymbolTable->index() });
+    m_lexicalScopeStack.append({ moduleEnvironmentSymbolTable, m_topLevelScopeRegister, isWithScope, constantSymbolTable->index() });
     emitPrefillStackTDZVariables(lexicalVariables, moduleEnvironmentSymbolTable);
 
     // makeFunction assumes that there's correct TDZ stack entries.
@@ -2312,7 +2314,10 @@ RegisterID* BytecodeGenerator::emitResolveScopeForHoistingFuncDeclInEval(Registe
 {
     RefPtr<RegisterID> result = finalDestination(dst);
     RefPtr<RegisterID> scope = newTemporary();
-    OpGetScope::emit(this, scope.get());
+    if (m_topLevelScopeRegister)
+        move(scope.get(), m_topLevelScopeRegister);
+    else
+        OpGetScope::emit(this, scope.get());
     OpResolveScopeForHoistingFuncDeclInEval::emit(this, kill(result.get()), scope.get(), addConstant(property));
     return result.get();
 }
@@ -3973,11 +3978,6 @@ RegisterID* BytecodeGenerator::emitToPropertyKeyOrNumber(RegisterID* dst, Regist
     return dst;
 }
 
-void BytecodeGenerator::emitGetScope()
-{
-    OpGetScope::emit(this, scopeRegister());
-}
-
 RegisterID* BytecodeGenerator::emitPushWithScope(RegisterID* objectScope)
 {
     pushLocalControlFlowScope();
@@ -4194,7 +4194,10 @@ void BytecodeGenerator::restoreScopeRegister(int lexicalScopeIndex)
     }
     // Note that if we don't find a local scope in the current function/program,
     // we must grab the outer-most scope of this bytecode generation.
-    emitGetScope();
+    if (m_topLevelScopeRegister)
+        move(scopeRegister(), m_topLevelScopeRegister);
+    else
+        OpGetScope::emit(this, scopeRegister());
 }
 
 void BytecodeGenerator::restoreScopeRegister()
diff --git a/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h b/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h
index 84107dd70c7d..31975bf10668 100644
--- a/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h
+++ b/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h
@@ -1014,7 +1014,6 @@ namespace JSC {
         void emitPushCatchScope(VariableEnvironment&, ScopeType);
         void emitPopCatchScope(VariableEnvironment&);
 
-        void emitGetScope();
         RegisterID* emitPushWithScope(RegisterID* objectScope);
         void emitPopWithScope();
         void emitPutThisToArrowFunctionContextScope();
@@ -1319,6 +1318,7 @@ namespace JSC {
         RegisterID m_thisRegister;
         RegisterID m_calleeRegister;
         RegisterID* m_scopeRegister { nullptr };
+        RegisterID* m_topLevelScopeRegister { nullptr }; // This may not be set. Only Eval and Module will configure this register.
         RegisterID* m_argumentsRegister { nullptr };
         RegisterID* m_lexicalEnvironmentRegister { nullptr };
         RegisterID* m_generatorRegister { nullptr };
diff --git a/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h b/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h
index 80de7ae95dc3..134ce57a5408 100644
--- a/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h
+++ b/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h
@@ -4039,7 +4039,7 @@ bool AbstractInterpreter<AbstractStateType>::executeEffects(unsigned clobberLimi
         setTypeForNode(node, SpecObject);
         break;
     }
-        
+
     case GetScope: {
         JSValue value = forNode(node->child1()).value();
         if (value) {
@@ -4064,6 +4064,11 @@ bool AbstractInterpreter<AbstractStateType>::executeEffects(unsigned clobberLimi
         break;
     }
 
+    case GetEvalScope: {
+        setTypeForNode(node, SpecObjectOther);
+        break;
+    }
+
     case SkipScope: {
         if (JSValue child = forNode(node->child1()).value()) {
             if (JSScope* scope = jsDynamicCast<JSScope*>(child)) {
diff --git a/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp b/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp
index a40721686886..64d71bd966c1 100644
--- a/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp
+++ b/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp
@@ -6622,7 +6622,12 @@ void ByteCodeParser::parseBlock(unsigned limit)
                 m_currentBlock = m_inlineStackTop->m_entryBlockForRecursiveTailCall;
             }
 
-            handleGetScope(codeBlock->scopeRegister());
+            if (m_inlineStackTop->m_codeBlock->codeType() == EvalCode) {
+                Node* callee = get(VirtualRegister(CallFrameSlot::callee));
+                Node* result = addToGraph(GetEvalScope, callee);
+                set(codeBlock->scopeRegister(), result);
+            } else
+                handleGetScope(codeBlock->scopeRegister());
 
             // Normally we wouldn't be allowed to exit here, but in this case we'd
             // only be re-initializing the locals and resetting the scope register
diff --git a/Source/JavaScriptCore/dfg/DFGClobberize.h b/Source/JavaScriptCore/dfg/DFGClobberize.h
index f4c478bb10ad..df04f78c2d8b 100644
--- a/Source/JavaScriptCore/dfg/DFGClobberize.h
+++ b/Source/JavaScriptCore/dfg/DFGClobberize.h
@@ -268,6 +268,11 @@ void clobberize(Graph& graph, Node* node, const ReadFunctor& read, const WriteFu
         def(PureValue(node));
         return;
 
+    // JSCallee for Eval can change the scope field.
+    case GetEvalScope:
+        read(World);
+        return;
+
     case NumberIsFinite:
     case NumberIsNaN:
         def(PureValue(node));
diff --git a/Source/JavaScriptCore/dfg/DFGCloneHelper.h b/Source/JavaScriptCore/dfg/DFGCloneHelper.h
index ce2acdf6c984..3f9fea003723 100644
--- a/Source/JavaScriptCore/dfg/DFGCloneHelper.h
+++ b/Source/JavaScriptCore/dfg/DFGCloneHelper.h
@@ -249,6 +249,7 @@ BasicBlock* CloneHelper::cloneBlock(BasicBlock* const block, const CustomizeSucc
     CLONE_STATUS(GetRegExpObjectLastIndex, Common) \
     CLONE_STATUS(GetRestLength, Common) \
     CLONE_STATUS(GetScope, Common) \
+    CLONE_STATUS(GetEvalScope, Common) \
     CLONE_STATUS(GetUndetachedTypeArrayLength, Common) \
     CLONE_STATUS(GlobalIsNaN, Common) \
     CLONE_STATUS(HasOwnProperty, Common) \
diff --git a/Source/JavaScriptCore/dfg/DFGDoesGC.cpp b/Source/JavaScriptCore/dfg/DFGDoesGC.cpp
index c052eac75fbf..9728608220f5 100644
--- a/Source/JavaScriptCore/dfg/DFGDoesGC.cpp
+++ b/Source/JavaScriptCore/dfg/DFGDoesGC.cpp
@@ -121,6 +121,7 @@ bool doesGC(Graph& graph, Node* node)
     case CheckArrayOrEmpty:
     case CheckDetached:
     case GetScope:
+    case GetEvalScope:
     case SkipScope:
     case GetGlobalObject:
     case GetGlobalThis:
diff --git a/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp b/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp
index a13dcaf41580..bf55f95e27cb 100644
--- a/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp
+++ b/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp
@@ -2114,6 +2114,7 @@ class FixupPhase : public Phase {
 
         case SkipScope:
         case GetScope:
+        case GetEvalScope:
         case GetGetter:
         case GetSetter: {
             fixEdge<KnownCellUse>(node->child1());
diff --git a/Source/JavaScriptCore/dfg/DFGMayExit.cpp b/Source/JavaScriptCore/dfg/DFGMayExit.cpp
index 03ad277be848..10aea869d01a 100644
--- a/Source/JavaScriptCore/dfg/DFGMayExit.cpp
+++ b/Source/JavaScriptCore/dfg/DFGMayExit.cpp
@@ -82,6 +82,7 @@ ExitMode mayExitImpl(Graph& graph, Node* node, StateType& state)
     case SetArgumentCountIncludingThis:
     case GetRestLength:
     case GetScope:
+    case GetEvalScope:
     case PhantomLocal:
     case CountExecution:
     case SuperSamplerBegin:
diff --git a/Source/JavaScriptCore/dfg/DFGNodeType.h b/Source/JavaScriptCore/dfg/DFGNodeType.h
index 650ecb4c7eb7..f1c50e663aac 100644
--- a/Source/JavaScriptCore/dfg/DFGNodeType.h
+++ b/Source/JavaScriptCore/dfg/DFGNodeType.h
@@ -282,6 +282,7 @@ namespace JSC { namespace DFG {
     macro(GetTypedArrayByteOffsetAsInt52, NodeResultInt52) \
     macro(GetWebAssemblyInstanceExports, NodeResultJS) \
     macro(GetScope, NodeResultJS) \
+    macro(GetEvalScope, NodeResultJS) \
     macro(SkipScope, NodeResultJS) \
     macro(ResolveScope, NodeResultJS | NodeMustGenerate) \
     macro(ResolveScopeForHoistingFuncDeclInEval, NodeResultJS | NodeMustGenerate) \
diff --git a/Source/JavaScriptCore/dfg/DFGObjectAllocationSinkingPhase.cpp b/Source/JavaScriptCore/dfg/DFGObjectAllocationSinkingPhase.cpp
index fb00dbcfc758..b3f7f83269d2 100644
--- a/Source/JavaScriptCore/dfg/DFGObjectAllocationSinkingPhase.cpp
+++ b/Source/JavaScriptCore/dfg/DFGObjectAllocationSinkingPhase.cpp
@@ -1323,6 +1323,7 @@ class ObjectAllocationSinkingPhase : public Phase {
                 m_heap.escape(node->child1().node());
             break;
 
+        // FIXME: Consider supporting GetEvalScope too.
         case GetScope:
             target = m_heap.onlyLocalAllocation(node->child1().node());
             if (target && target->isFunctionAllocation())
diff --git a/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp b/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp
index f768b3f68f0e..713603a7e274 100644
--- a/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp
+++ b/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp
@@ -1440,6 +1440,7 @@ class PredictionPropagationPhase : public Phase {
         }
 
         case GetScope:
+        case GetEvalScope:
             setPrediction(SpecObjectOther);
             break;
 
diff --git a/Source/JavaScriptCore/dfg/DFGSafeToExecute.h b/Source/JavaScriptCore/dfg/DFGSafeToExecute.h
index 25693f8d6f71..d9ddc536cd18 100644
--- a/Source/JavaScriptCore/dfg/DFGSafeToExecute.h
+++ b/Source/JavaScriptCore/dfg/DFGSafeToExecute.h
@@ -239,6 +239,7 @@ bool safeToExecute(AbstractStateType& state, Graph& graph, Node* node, bool igno
     case CheckArray:
     case CheckArrayOrEmpty:
     case GetScope:
+    case GetEvalScope:
     case SkipScope:
     case GetGlobalObject:
     case GetGlobalThis:
diff --git a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp
index 8080a2ec33e9..45d92ffaab16 100644
--- a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp
+++ b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp
@@ -7946,11 +7946,11 @@ void SpeculativeJIT::compileGetByValOnScopedArguments(Node* node, const ScopedLa
     jsValueResult(resultRegs, node);
 }
 
-void SpeculativeJIT::compileGetScope(Node* node)
+void SpeculativeJIT::compileGetScopeOrGetEvalScope(Node* node)
 {
     SpeculateCellOperand function(this, node->child1());
     GPRTemporary result(this, Reuse, function);
-    loadPtr(Address(function.gpr(), JSFunction::offsetOfScopeChain()), result.gpr());
+    loadPtr(Address(function.gpr(), JSCallee::offsetOfScopeChain()), result.gpr());
     cellResult(result.gpr(), node);
 }
     
@@ -8218,7 +8218,7 @@ void SpeculativeJIT::compileNewFunctionCommon(GPRReg resultGPR, RegisteredStruct
     auto butterfly = TrustedImmPtr(nullptr);
     emitAllocateJSObjectWithKnownSize<ClassType>(resultGPR, TrustedImmPtr(structure), butterfly, scratch1GPR, scratch2GPR, slowPath, size, SlowAllocationResult::UndefinedBehavior);
     
-    storePtr(scopeGPR, Address(resultGPR, JSFunction::offsetOfScopeChain()));
+    storePtr(scopeGPR, Address(resultGPR, JSCallee::offsetOfScopeChain()));
     storeLinkableConstant(LinkableConstant(*this, executable), Address(resultGPR, JSFunction::offsetOfExecutableOrRareData()));
     mutatorFence(vm());
 }
diff --git a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h
index d6cdc73f49ea..b76ce24a03f4 100644
--- a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h
+++ b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h
@@ -1542,7 +1542,7 @@ class SpeculativeJIT : public JITCompiler {
     void compileGetPrivateNameById(Node*);
     void compileGetPrivateNameByVal(Node*, JSValueRegs base, JSValueRegs property);
 
-    void compileGetScope(Node*);
+    void compileGetScopeOrGetEvalScope(Node*);
     void compileSkipScope(Node*);
     void compileGetGlobalObject(Node*);
     void compileGetGlobalThis(Node*);
diff --git a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp
index 913b57835523..b193a60c04c4 100644
--- a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp
+++ b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp
@@ -3306,7 +3306,8 @@ void SpeculativeJIT::compile(Node* node)
         break;
         
     case GetScope:
-        compileGetScope(node);
+    case GetEvalScope:
+        compileGetScopeOrGetEvalScope(node);
         break;
             
     case SkipScope:
diff --git a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp
index ee06fd72bd04..b872f06fabb6 100644
--- a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp
+++ b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp
@@ -1018,7 +1018,7 @@ void SpeculativeJIT::emitCall(Node* node)
                     move(CCallHelpers::TrustedImmPtr(calleeScope), GPRInfo::argumentGPR0);
                 else {
                     emitGetFromCallFrameHeaderPtr(CallFrameSlot::callee, GPRInfo::argumentGPR2);
-                    loadPtr(Address(GPRInfo::argumentGPR2, JSFunction::offsetOfScopeChain()), GPRInfo::argumentGPR0);
+                    loadPtr(Address(GPRInfo::argumentGPR2, JSCallee::offsetOfScopeChain()), GPRInfo::argumentGPR0);
                 }
                 move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR1);
                 if (Options::useJITCage()) {
@@ -4675,7 +4675,8 @@ void SpeculativeJIT::compile(Node* node)
     }
         
     case GetScope:
-        compileGetScope(node);
+    case GetEvalScope:
+        compileGetScopeOrGetEvalScope(node);
         break;
             
     case SkipScope:
@@ -8161,7 +8162,7 @@ void SpeculativeJIT::compileNewBoundFunction(Node* node)
 
     auto butterfly = TrustedImmPtr(nullptr);
     emitAllocateJSObjectWithKnownSize<JSBoundFunction>(resultGPR, TrustedImmPtr(structure), butterfly, scratch1GPR, scratch2GPR, slowPath, sizeof(JSBoundFunction), SlowAllocationResult::UndefinedBehavior);
-    storeLinkableConstant(LinkableConstant::globalObject(*this, node), Address(resultGPR, JSBoundFunction::offsetOfScopeChain()));
+    storeLinkableConstant(LinkableConstant::globalObject(*this, node), Address(resultGPR, JSCallee::offsetOfScopeChain()));
     storeLinkableConstant(LinkableConstant(*this, executable), Address(resultGPR, JSBoundFunction::offsetOfExecutableOrRareData()));
     storeValue(JSValueRegs { targetGPR }, Address(resultGPR, JSBoundFunction::offsetOfTargetFunction()));
     storeValue(boundThisRegs, Address(resultGPR, JSBoundFunction::offsetOfBoundThis()));
diff --git a/Source/JavaScriptCore/ftl/FTLAbstractHeapRepository.h b/Source/JavaScriptCore/ftl/FTLAbstractHeapRepository.h
index a885e39e5c74..63d174742791 100644
--- a/Source/JavaScriptCore/ftl/FTLAbstractHeapRepository.h
+++ b/Source/JavaScriptCore/ftl/FTLAbstractHeapRepository.h
@@ -105,6 +105,7 @@ namespace JSC { namespace FTL {
     macro(JSBoundFunction_length, JSBoundFunction::offsetOfLength()) \
     macro(JSBoundFunction_boundArgsLength, JSBoundFunction::offsetOfBoundArgsLength()) \
     macro(JSBoundFunction_canConstruct, JSBoundFunction::offsetOfCanConstruct()) \
+    macro(JSCallee_scope, JSCallee::offsetOfScopeChain()) \
     macro(JSCell_cellState, JSCell::cellStateOffset()) \
     macro(JSCell_header, 0) \
     macro(JSCell_indexingTypeAndMisc, JSCell::indexingTypeAndMiscOffset()) \
@@ -113,7 +114,6 @@ namespace JSC { namespace FTL {
     macro(JSCell_typeInfoType, JSCell::typeInfoTypeOffset()) \
     macro(JSCell_usefulBytes, JSCell::indexingTypeAndMiscOffset()) \
     macro(JSFunction_executableOrRareData, JSFunction::offsetOfExecutableOrRareData()) \
-    macro(JSFunction_scope, JSFunction::offsetOfScopeChain()) \
     macro(JSGlobalObject_regExpGlobalData_cachedResult_lastRegExp, JSGlobalObject::regExpGlobalDataOffset() + RegExpGlobalData::offsetOfCachedResult() + RegExpCachedResult::offsetOfLastRegExp()) \
     macro(JSGlobalObject_regExpGlobalData_cachedResult_lastInput, JSGlobalObject::regExpGlobalDataOffset() + RegExpGlobalData::offsetOfCachedResult() + RegExpCachedResult::offsetOfLastInput()) \
     macro(JSGlobalObject_regExpGlobalData_cachedResult_result_start, JSGlobalObject::regExpGlobalDataOffset() + RegExpGlobalData::offsetOfCachedResult() + RegExpCachedResult::offsetOfResult() + OBJECT_OFFSETOF(MatchResult, start)) \
diff --git a/Source/JavaScriptCore/ftl/FTLCapabilities.cpp b/Source/JavaScriptCore/ftl/FTLCapabilities.cpp
index ab670aed55e1..5388b592404a 100644
--- a/Source/JavaScriptCore/ftl/FTLCapabilities.cpp
+++ b/Source/JavaScriptCore/ftl/FTLCapabilities.cpp
@@ -225,6 +225,7 @@ inline CapabilityLevel canCompile(Node* node)
     case SuperSamplerEnd:
     case GetExecutable:
     case GetScope:
+    case GetEvalScope:
     case GetCallee:
     case SetCallee:
     case GetArgumentCountIncludingThis:
diff --git a/Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp b/Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp
index a4db4022121c..ebd3a2891e44 100644
--- a/Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp
+++ b/Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp
@@ -1395,7 +1395,8 @@ class LowerDFGToB3 {
             compileSetArgumentCountIncludingThis();
             break;
         case GetScope:
-            compileGetScope();
+        case GetEvalScope:
+            compileGetScopeOrGetEvalScope();
             break;
         case SkipScope:
             compileSkipScope();
@@ -8776,7 +8777,7 @@ IGNORE_CLANG_WARNINGS_END
 
         // We don't need memory barriers since we just fast-created the function, so it
         // must be young.
-        m_out.storePtr(scope, fastObject, m_heaps.JSFunction_scope);
+        m_out.storePtr(scope, fastObject, m_heaps.JSCallee_scope);
         m_out.storePtr(weakPointer(executable), fastObject, m_heaps.JSFunction_executableOrRareData);
         mutatorFence();
 
@@ -8833,7 +8834,7 @@ IGNORE_CLANG_WARNINGS_END
 
         // We don't need memory barriers since we just fast-created the function, so it
         // must be young.
-        m_out.storePtr(weakPointer(globalObject), fastObject, m_heaps.JSFunction_scope);
+        m_out.storePtr(weakPointer(globalObject), fastObject, m_heaps.JSCallee_scope);
         m_out.storePtr(weakPointer(executable), fastObject, m_heaps.JSFunction_executableOrRareData);
         m_out.storePtr(target, fastObject, m_heaps.JSBoundFunction_targetFunction);
         m_out.store64(thisValue, fastObject, m_heaps.JSBoundFunction_boundThis);
@@ -11737,9 +11738,9 @@ IGNORE_CLANG_WARNINGS_END
         m_out.store32(m_out.constInt32(m_node->argumentCountIncludingThis()), payloadFor(VirtualRegister(CallFrameSlot::argumentCountIncludingThis)));
     }
 
-    void compileGetScope()
+    void compileGetScopeOrGetEvalScope()
     {
-        setJSValue(m_out.loadPtr(lowCell(m_node->child1()), m_heaps.JSFunction_scope));
+        setJSValue(m_out.loadPtr(lowCell(m_node->child1()), m_heaps.JSCallee_scope));
     }
 
     void compileSkipScope()
@@ -12633,7 +12634,7 @@ IGNORE_CLANG_WARNINGS_END
                         jit.move(CCallHelpers::TrustedImmPtr(calleeScope), GPRInfo::argumentGPR0);
                     else {
                         jit.emitGetFromCallFrameHeaderPtr(CallFrameSlot::callee, GPRInfo::argumentGPR2);
-                        jit.loadPtr(CCallHelpers::Address(GPRInfo::argumentGPR2, JSFunction::offsetOfScopeChain()), GPRInfo::argumentGPR0);
+                        jit.loadPtr(CCallHelpers::Address(GPRInfo::argumentGPR2, JSCallee::offsetOfScopeChain()), GPRInfo::argumentGPR0);
                     }
                     jit.move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR1);
                     if (Options::useJITCage()) {
diff --git a/Source/JavaScriptCore/interpreter/Interpreter.cpp b/Source/JavaScriptCore/interpreter/Interpreter.cpp
index bb71b74c57b9..9033a1b355d8 100644
--- a/Source/JavaScriptCore/interpreter/Interpreter.cpp
+++ b/Source/JavaScriptCore/interpreter/Interpreter.cpp
@@ -1592,11 +1592,7 @@ JSValue Interpreter::executeEval(EvalExecutable* eval, JSValue thisValue, JSScop
         }
     }
 
-    JSCallee* callee = nullptr;
-    if (scope == globalObject->globalScope())
-        callee = globalObject->globalCallee();
-    else
-        callee = JSCallee::create(vm, globalObject, scope);
+    JSCallee* callee = globalObject->evalCallee();
 
     RefPtr<JSC::JITCode> jitCode;
     ProtoCallFrame protoCallFrame;
@@ -1622,7 +1618,12 @@ JSValue Interpreter::executeEval(EvalExecutable* eval, JSValue thisValue, JSScop
     // Execute the code:
     throwScope.release();
     ASSERT(jitCode == eval->generatedJITCode().ptr());
-    return JSValue::decode(vmEntryToJavaScript(jitCode->addressForCall(), &vm, &protoCallFrame));
+    // eval code only uses scope at the beginning (op_enter).
+    // We can replace the current scope for the subsequent run.
+    callee->setScope(vm, scope);
+    EncodedJSValue result = vmEntryToJavaScript(jitCode->addressForCall(), &vm, &protoCallFrame);
+    callee->setScope(vm, globalObject->globalScope());
+    return JSValue::decode(result);
 }
 
 JSValue Interpreter::executeModuleProgram(JSModuleRecord* record, ModuleProgramExecutable* executable, JSGlobalObject* lexicalGlobalObject, JSModuleEnvironment* scope, JSValue sentValue, JSValue resumeMode)
diff --git a/Source/JavaScriptCore/jit/JITOpcodes.cpp b/Source/JavaScriptCore/jit/JITOpcodes.cpp
index ec4286cc3f4d..5b888519b8e5 100644
--- a/Source/JavaScriptCore/jit/JITOpcodes.cpp
+++ b/Source/JavaScriptCore/jit/JITOpcodes.cpp
@@ -1395,7 +1395,7 @@ void JIT::emit_op_neq_null(const JSInstruction* currentInstruction)
 void JIT::emitGetScope(VirtualRegister destination)
 {
     emitGetFromCallFrameHeaderPtr(CallFrameSlot::callee, regT0);
-    loadPtr(Address(regT0, JSFunction::offsetOfScopeChain()), regT0);
+    loadPtr(Address(regT0, JSCallee::offsetOfScopeChain()), regT0);
     boxCell(regT0, jsRegT10);
     emitPutVirtualRegister(destination, jsRegT10);
 }
diff --git a/Source/JavaScriptCore/jit/ThunkGenerators.cpp b/Source/JavaScriptCore/jit/ThunkGenerators.cpp
index 18a596e3cd0e..5cb98ad32cbe 100644
--- a/Source/JavaScriptCore/jit/ThunkGenerators.cpp
+++ b/Source/JavaScriptCore/jit/ThunkGenerators.cpp
@@ -474,7 +474,7 @@ static MacroAssemblerCodeRef<JITThunkPtrTag> nativeForGenerator(VM& vm, ThunkFun
     jit.emitGetFromCallFrameHeaderPtr(CallFrameSlot::callee, GPRInfo::argumentGPR2);
 
     if (thunkFunctionType == ThunkFunctionType::JSFunction) {
-        jit.loadPtr(CCallHelpers::Address(GPRInfo::argumentGPR2, JSFunction::offsetOfScopeChain()), GPRInfo::argumentGPR0);
+        jit.loadPtr(CCallHelpers::Address(GPRInfo::argumentGPR2, JSCallee::offsetOfScopeChain()), GPRInfo::argumentGPR0);
         jit.loadPtr(CCallHelpers::Address(GPRInfo::argumentGPR2, JSFunction::offsetOfExecutableOrRareData()), GPRInfo::argumentGPR2);
         auto hasExecutable = jit.branchTestPtr(CCallHelpers::Zero, GPRInfo::argumentGPR2, CCallHelpers::TrustedImm32(JSFunction::rareDataTag));
         jit.loadPtr(CCallHelpers::Address(GPRInfo::argumentGPR2, FunctionRareData::offsetOfExecutable() - JSFunction::rareDataTag), GPRInfo::argumentGPR2);
@@ -1232,7 +1232,7 @@ MacroAssemblerCodeRef<JITThunkPtrTag> boundFunctionCallGenerator(VM& vm)
 
     // Throw Stack Overflow exception
     jit.copyCalleeSavesToEntryFrameCalleeSavesBuffer(vm.topEntryFrame, GPRInfo::regT3);
-    jit.loadPtr(CCallHelpers::Address(GPRInfo::regT0, JSBoundFunction::offsetOfScopeChain()), GPRInfo::regT3);
+    jit.loadPtr(CCallHelpers::Address(GPRInfo::regT0, JSCallee::offsetOfScopeChain()), GPRInfo::regT3);
     jit.setupArguments<decltype(operationThrowStackOverflowErrorFromThunk)>(GPRInfo::regT3);
     jit.prepareCallOperation(vm);
     jit.move(CCallHelpers::TrustedImmPtr(tagCFunction<OperationPtrTag>(operationThrowStackOverflowErrorFromThunk)), GPRInfo::nonArgGPR0);
@@ -1396,7 +1396,7 @@ MacroAssemblerCodeRef<JITThunkPtrTag> remoteFunctionCallGenerator(VM& vm)
 
     // Throw Stack Overflow exception
     jit.copyCalleeSavesToEntryFrameCalleeSavesBuffer(vm.topEntryFrame, GPRInfo::regT3);
-    jit.loadPtr(CCallHelpers::Address(GPRInfo::regT0, JSBoundFunction::offsetOfScopeChain()), GPRInfo::regT3);
+    jit.loadPtr(CCallHelpers::Address(GPRInfo::regT0, JSCallee::offsetOfScopeChain()), GPRInfo::regT3);
     jit.setupArguments<decltype(operationThrowStackOverflowErrorFromThunk)>(GPRInfo::regT3);
     jit.prepareCallOperation(vm);
     jit.move(CCallHelpers::TrustedImmPtr(tagCFunction<OperationPtrTag>(operationThrowStackOverflowErrorFromThunk)), GPRInfo::nonArgGPR0);
diff --git a/Source/JavaScriptCore/llint/LowLevelInterpreter32_64.asm b/Source/JavaScriptCore/llint/LowLevelInterpreter32_64.asm
index 0d7c92bbbbb8..2d2998c7534f 100644
--- a/Source/JavaScriptCore/llint/LowLevelInterpreter32_64.asm
+++ b/Source/JavaScriptCore/llint/LowLevelInterpreter32_64.asm
@@ -2609,7 +2609,7 @@ macro nativeCallTrampoline(executableOffsetToFunction)
     btpz a2, (constexpr JSFunction::rareDataTag), .isExecutable
     loadp (FunctionRareData::m_executable - (constexpr JSFunction::rareDataTag))[a2], a2
 .isExecutable:
-    loadp JSFunction::m_scope[a0], a0
+    loadp JSCallee::m_scope[a0], a0
     loadp JSGlobalObject::m_vm[a0], a1
     storep cfr, VM::topCallFrame[a1]
     move cfr, a1
@@ -2622,7 +2622,7 @@ macro nativeCallTrampoline(executableOffsetToFunction)
     end
 
     loadp Callee + PayloadOffset[cfr], t3
-    loadp JSFunction::m_scope[t3], t3
+    loadp JSCallee::m_scope[t3], t3
     loadp JSGlobalObject::m_vm[t3], t3
 
     addp 8, sp
diff --git a/Source/JavaScriptCore/llint/LowLevelInterpreter64.asm b/Source/JavaScriptCore/llint/LowLevelInterpreter64.asm
index cedaea763699..b9c54caee139 100644
--- a/Source/JavaScriptCore/llint/LowLevelInterpreter64.asm
+++ b/Source/JavaScriptCore/llint/LowLevelInterpreter64.asm
@@ -2757,7 +2757,7 @@ macro nativeCallTrampoline(executableOffsetToFunction)
     btpz a2, (constexpr JSFunction::rareDataTag), .isExecutable
     loadp (FunctionRareData::m_executable - (constexpr JSFunction::rareDataTag))[a2], a2
 .isExecutable:
-    loadp JSFunction::m_scope[a0], a0
+    loadp JSCallee::m_scope[a0], a0
     loadp JSGlobalObject::m_vm[a0], a1
     storep cfr, VM::topCallFrame[a1]
     if ARM64 or ARM64E or C_LOOP
@@ -2772,7 +2772,7 @@ macro nativeCallTrampoline(executableOffsetToFunction)
     end
 
     loadp Callee[cfr], t3
-    loadp JSFunction::m_scope[t3], t3
+    loadp JSCallee::m_scope[t3], t3
     loadp JSGlobalObject::m_vm[t3], t3
 
     btpnz VM::m_exception[t3], .handleException
diff --git a/Source/JavaScriptCore/runtime/JSCallee.h b/Source/JavaScriptCore/runtime/JSCallee.h
index 16d3c3b02276..23425bbd038a 100644
--- a/Source/JavaScriptCore/runtime/JSCallee.h
+++ b/Source/JavaScriptCore/runtime/JSCallee.h
@@ -65,16 +65,6 @@ class JSCallee : public JSNonFinalObject {
         return m_scope.get();
     }
 
-    // This method may be called for host functions, in which case it
-    // will return an arbitrary value. This should only be used for
-    // optimized paths in which the return value does not matter for
-    // host functions, and checking whether the function is a host
-    // function is deemed too expensive.
-    JSScope* scopeUnchecked()
-    {
-        return m_scope.get();
-    }
-
     void setScope(VM& vm, JSScope* scope)
     {
         m_scope.set(vm, this, scope);
@@ -96,7 +86,6 @@ class JSCallee : public JSNonFinalObject {
     DECLARE_DEFAULT_FINISH_CREATION;
     DECLARE_VISIT_CHILDREN;
 
-private:
     friend class LLIntOffsetsExtractor;
 
     WriteBarrier<JSScope> m_scope;
diff --git a/Source/JavaScriptCore/runtime/JSFunction.h b/Source/JavaScriptCore/runtime/JSFunction.h
index f8f42ad03972..840700f0811e 100644
--- a/Source/JavaScriptCore/runtime/JSFunction.h
+++ b/Source/JavaScriptCore/runtime/JSFunction.h
@@ -174,6 +174,16 @@ class JSFunction : public JSCallee {
 
     bool mayHaveNonReifiedPrototype();
 
+    // This method may be called for host functions, in which case it
+    // will return an arbitrary value. This should only be used for
+    // optimized paths in which the return value does not matter for
+    // host functions, and checking whether the function is a host
+    // function is deemed too expensive.
+    JSScope* scopeUnchecked()
+    {
+        return m_scope.get();
+    }
+
 protected:
     JS_EXPORT_PRIVATE JSFunction(VM&, NativeExecutable*, JSGlobalObject*, Structure*);
     JSFunction(VM&, FunctionExecutable*, JSScope*, Structure*);
diff --git a/Source/JavaScriptCore/runtime/JSGlobalObject.cpp b/Source/JavaScriptCore/runtime/JSGlobalObject.cpp
index 6b9ad8a1d7d1..2f18a69a2ebe 100644
--- a/Source/JavaScriptCore/runtime/JSGlobalObject.cpp
+++ b/Source/JavaScriptCore/runtime/JSGlobalObject.cpp
@@ -877,6 +877,9 @@ void JSGlobalObject::init(VM& vm)
     JSCallee* globalCallee = JSCallee::create(vm, this, globalScope());
     m_globalCallee.set(vm, this, globalCallee);
 
+    JSCallee* evalCallee = JSCallee::create(vm, this, globalScope());
+    m_evalCallee.set(vm, this, evalCallee);
+
     m_partiallyInitializedFrameCallee.set(vm, this, JSCallee::create(vm, this, globalScope()));
 
     m_hostFunctionStructure.set(vm, this, JSFunction::createStructure(vm, this, m_functionPrototype.get()));
@@ -2614,6 +2617,7 @@ void JSGlobalObject::visitChildrenImpl(JSCell* cell, Visitor& visitor)
     visitor.append(thisObject->m_globalLexicalEnvironment);
     visitor.append(thisObject->m_globalScopeExtension);
     visitor.append(thisObject->m_globalCallee);
+    visitor.append(thisObject->m_evalCallee);
     visitor.append(thisObject->m_partiallyInitializedFrameCallee);
     JS_GLOBAL_OBJECT_ADDITIONS_4;
     thisObject->m_evalErrorStructure.visit(visitor);
diff --git a/Source/JavaScriptCore/runtime/JSGlobalObject.h b/Source/JavaScriptCore/runtime/JSGlobalObject.h
index 53b20656739a..09d69d6e3d81 100644
--- a/Source/JavaScriptCore/runtime/JSGlobalObject.h
+++ b/Source/JavaScriptCore/runtime/JSGlobalObject.h
@@ -229,6 +229,7 @@ class JSGlobalObject : public JSSegmentedVariableObject {
     WriteBarrier<JSScope> m_globalScopeExtension;
     WriteBarrier<JSCallee> m_globalCallee;
     WriteBarrier<JSCallee> m_partiallyInitializedFrameCallee;
+    WriteBarrier<JSCallee> m_evalCallee;
 
     JS_GLOBAL_OBJECT_ADDITIONS_1;
 
@@ -719,6 +720,7 @@ class JSGlobalObject : public JSSegmentedVariableObject {
     void clearGlobalScopeExtension();
 
     JSCallee* globalCallee() { return m_globalCallee.get(); }
+    JSCallee* evalCallee() { return m_evalCallee.get(); }
 
     // The following accessors return pristine values, even if a script 
     // replaces the global object's associated property.


Reviews:
user: login: hyjorc1
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-22T18:56:12Z
user: login: Constellation
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-05-22T19:05:09Z
user: login: hyjorc1
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-22T19:08:36Z
user: login: hyjorc1
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-22T19:46:46Z
user: login: Constellation
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-05-22T19:50:26Z
user: login: Constellation
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-05-22T19:51:00Z
user: login: hyjorc1
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-22T19:52:46Z
user: login: Constellation
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-05-22T20:03:42Z
user: login: hyjorc1
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-22T20:15:12Z
user: login: hyjorc1
body: r=me
state: APPROVED
author_association: CONTRIBUTOR
submitted_at: 2025-05-22T20:16:41Z
user: login: Constellation
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-05-22T20:19:03Z

Review comments:
diff_hunk: @@ -951,9 +951,11 @@ BytecodeGenerator::BytecodeGenerator(VM& vm, EvalNode* evalNode, UnlinkedEvalCod
     m_cachedParentTDZ = parentScopeTDZVariables;
 
     emitEnter();
-
     allocateScope();
-    
+    m_topLevelScopeRegister = addVar();
+    m_topLevelScopeRegister->ref();
+    move(m_topLevelScopeRegister, scopeRegister());
path: Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp
user: login: hyjorc1
body: We have four `BytecodeGenerator::BytecodeGenerator` constructors. So, why define `m_topLevelScopeRegister` only for these two constructors?
created_at: 2025-05-22T18:56:12Z
author_association: CONTRIBUTOR
diff_hunk: @@ -951,9 +951,11 @@ BytecodeGenerator::BytecodeGenerator(VM& vm, EvalNode* evalNode, UnlinkedEvalCod
     m_cachedParentTDZ = parentScopeTDZVariables;
 
     emitEnter();
-
     allocateScope();
-    
+    m_topLevelScopeRegister = addVar();
+    m_topLevelScopeRegister->ref();
+    move(m_topLevelScopeRegister, scopeRegister());
path: Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp
user: login: Constellation
body: This move is wasteful when we do not need this topLevelScopeRegister, and only module and eval need them. Only materializing them on these types is important to save bytecodes in functions.
created_at: 2025-05-22T19:05:09Z
author_association: MEMBER
diff_hunk: @@ -1045,11 +1047,11 @@ BytecodeGenerator::BytecodeGenerator(VM& vm, ModuleProgramNode* moduleProgramNod
     }
 
     emitEnter();
-
     allocateScope();
-    RegisterID* moduleScope = addVar();
-    move(moduleScope, scopeRegister());
path: Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp
user: login: hyjorc1
body: Why previously we didn't do `moduleScope->ref()` but the new code does `m_topLevelScopeRegister->ref()`?
created_at: 2025-05-22T19:08:36Z
author_association: CONTRIBUTOR
diff_hunk: @@ -174,6 +174,16 @@ class JSFunction : public JSCallee {
 
     bool mayHaveNonReifiedPrototype();
 
+    // This method may be called for host functions, in which case it
+    // will return an arbitrary value. This should only be used for
+    // optimized paths in which the return value does not matter for
+    // host functions, and checking whether the function is a host
+    // function is deemed too expensive.
+    JSScope* scopeUnchecked()
+    {
+        return m_scope.get();
+    }
path: Source/JavaScriptCore/runtime/JSFunction.h
user: login: hyjorc1
body: The motivation of moving `scopeUnchecked` from `JSCallee` to `JSFunction`?
created_at: 2025-05-22T19:46:46Z
author_association: CONTRIBUTOR
diff_hunk: @@ -1045,11 +1047,11 @@ BytecodeGenerator::BytecodeGenerator(VM& vm, ModuleProgramNode* moduleProgramNod
     }
 
     emitEnter();
-
     allocateScope();
-    RegisterID* moduleScope = addVar();
-    move(moduleScope, scopeRegister());
path: Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp
user: login: Constellation
body: Actually it is not necessary, but just following to what scopeRegister is doing. If it is addVar's result, basically it is not necessary.
created_at: 2025-05-22T19:50:26Z
author_association: MEMBER
diff_hunk: @@ -174,6 +174,16 @@ class JSFunction : public JSCallee {
 
     bool mayHaveNonReifiedPrototype();
 
+    // This method may be called for host functions, in which case it
+    // will return an arbitrary value. This should only be used for
+    // optimized paths in which the return value does not matter for
+    // host functions, and checking whether the function is a host
+    // function is deemed too expensive.
+    JSScope* scopeUnchecked()
+    {
+        return m_scope.get();
+    }
path: Source/JavaScriptCore/runtime/JSFunction.h
user: login: Constellation
body: We would like to limit the function touching this scope to a limited class. So limit scopeUnchecked use only for JSFunction, not for JSCallee.
created_at: 2025-05-22T19:51:00Z
author_association: MEMBER
diff_hunk: @@ -1622,7 +1618,12 @@ JSValue Interpreter::executeEval(EvalExecutable* eval, JSValue thisValue, JSScop
     // Execute the code:
     throwScope.release();
     ASSERT(jitCode == eval->generatedJITCode().ptr());
-    return JSValue::decode(vmEntryToJavaScript(jitCode->addressForCall(), &vm, &protoCallFrame));
+    // eval code only uses scope at the beginning (op_enter).
+    // We can replace the current scope for the subsequent run.
+    callee->setScope(vm, scope);
+    EncodedJSValue result = vmEntryToJavaScript(jitCode->addressForCall(), &vm, &protoCallFrame);
+    callee->setScope(vm, globalObject->globalScope());
path: Source/JavaScriptCore/interpreter/Interpreter.cpp
user: login: hyjorc1
body: Why we'd like to reset the scope with `globalObject->globalScope()` after? Since previously the case for
```
callee = JSCallee::create(vm, globalObject, scope);
```
we didn't reset that with `globalObject->globalScope()`.
created_at: 2025-05-22T19:52:46Z
author_association: CONTRIBUTOR
diff_hunk: @@ -1622,7 +1618,12 @@ JSValue Interpreter::executeEval(EvalExecutable* eval, JSValue thisValue, JSScop
     // Execute the code:
     throwScope.release();
     ASSERT(jitCode == eval->generatedJITCode().ptr());
-    return JSValue::decode(vmEntryToJavaScript(jitCode->addressForCall(), &vm, &protoCallFrame));
+    // eval code only uses scope at the beginning (op_enter).
+    // We can replace the current scope for the subsequent run.
+    callee->setScope(vm, scope);
+    EncodedJSValue result = vmEntryToJavaScript(jitCode->addressForCall(), &vm, &protoCallFrame);
+    callee->setScope(vm, globalObject->globalScope());
path: Source/JavaScriptCore/interpreter/Interpreter.cpp
user: login: Constellation
body: It is possible that we will keep the old scope from JSGlobalObject since it holds this shared evalScope, and in this case, it may keep reachable objects alive even after this scope is no longer used. So we explicitly clear this here to the global's default scope to avoid memory leaking.
created_at: 2025-05-22T20:03:42Z
author_association: MEMBER
diff_hunk: @@ -1319,6 +1318,7 @@ namespace JSC {
         RegisterID m_thisRegister;
         RegisterID m_calleeRegister;
         RegisterID* m_scopeRegister { nullptr };
+        RegisterID* m_topLevelScopeRegister { nullptr }; // This may not be set. Only Eval and Module will configure this register.
path: Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h
user: login: hyjorc1
body: If I am understanding `m_topLevelScopeRegister` correctly, it's used for holds a copy of `scopeRegister()` set at `op_enter` to avoid emitted repeated `op_get_scope`? Is that only for low tiers? So, for DFG and FTL why don't we need similar things like `m_topLevelScopeRegister`? Oh, maybe `callFrame->callee->scope()` is similar to the concept of `m_topLevelScopeRegister`?
created_at: 2025-05-22T20:15:12Z
author_association: CONTRIBUTOR
diff_hunk: @@ -1319,6 +1318,7 @@ namespace JSC {
         RegisterID m_thisRegister;
         RegisterID m_calleeRegister;
         RegisterID* m_scopeRegister { nullptr };
+        RegisterID* m_topLevelScopeRegister { nullptr }; // This may not be set. Only Eval and Module will configure this register.
path: Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h
user: login: Constellation
body: It is holding the scope obtained at the beginning since `eval`'s scope can be changed. It is for all tiers. Instead of using `op_get_scope`, we use `op_mov` so DFG / FTL will see `op_mov` and do the same thing to the lower tiers.
created_at: 2025-05-22T20:19:03Z
author_association: MEMBER

PR comments:
user: login: webkit-early-warning-system
created_at: 2025-05-22T18:42:53Z
body: EWS run on previous version of this PR (hash https://github.com/WebKit/WebKit/commit/6f5e82a701afa19a68156da82c5ea1b7e009ab7d)<details>

| Misc | iOS, visionOS, tvOS & watchOS  | macOS  | Linux |  Windows |
| ----- | ---------------------- | ------- |  ----- |  --------- |
| [✅ 🧪 style](https://ews-build.webkit.org/#/builders/38/builds/104675 "Passed style check") | [  ~~🛠 ios~~](https://ews-build.webkit.org/#/builders/131/builds/24387 "The change is no longer eligible for processing. Commit was outdated when EWS attempted to process it.") | [✅ 🛠 mac](https://ews-build.webkit.org/#/builders/138/builds/14808 "Built successfully") | [✅ 🛠 wpe](https://ews-build.webkit.org/#/builders/5/builds/109889 "Built successfully") | [  ~~🛠 win~~](https://ews-build.webkit.org/#/builders/59/builds/55349 "The change is no longer eligible for processing. Pull Request was already closed when EWS attempted to process it.") 
| | [✅ 🛠 ios-sim](https://ews-build.webkit.org/#/builders/130/builds/24778 "Built successfully") | [✅ 🛠 mac-AS-debug](https://ews-build.webkit.org/#/builders/123/builds/32933 "Built successfully") | [  ~~🧪 wpe-wk2~~](https://ews-build.webkit.org/#/builders/34/builds/79498 "The change is no longer eligible for processing. Commit was outdated when EWS attempted to process it.") | [  ~~🧪 win-tests~~](https://ews-build.webkit.org/#/builders/59/builds/55349 "The change is no longer eligible for processing. Pull Request was already closed when EWS attempted to process it.") 
| [✅ 🧪 webkitperl](https://ews-build.webkit.org/#/builders/11/builds/107681 "Passed tests") | [⏳ 🧪 ios-wk2](https://ews-build.webkit.org/#/builders/iOS-18-Simulator-WK2-Tests-EWS "Waiting to run tests") | [✅ 🧪 api-mac](https://ews-build.webkit.org/#/builders/18/builds/94473 "Passed tests") | [  ~~🧪 api-wpe~~](https://ews-build.webkit.org/#/builders/41/builds/59804 "The change is no longer eligible for processing. Commit was outdated when EWS attempted to process it.") | 
| | [⏳ 🧪 ios-wk2-wpt](https://ews-build.webkit.org/#/builders/iOS-18-Simulator-WPT-WK2-Tests-EWS "Waiting to run tests") | [✅ 🧪 mac-wk1](https://ews-build.webkit.org/#/builders/135/builds/12547 "Passed tests") | [✅ 🛠 wpe-cairo](https://ews-build.webkit.org/#/builders/65/builds/54723 "Built successfully") | 
| [  ~~🛠 🧪 jsc~~](https://ews-build.webkit.org/#/builders/20/builds/97356 "The change is no longer eligible for processing. Pull Request was already closed when EWS attempted to process it.") | [⏳ 🧪 api-ios](https://ews-build.webkit.org/#/builders/API-Tests-iOS-Simulator-EWS "Waiting to run tests") | [✅ 🧪 mac-wk2](https://ews-build.webkit.org/#/builders/136/builds/12599 "Passed tests") | [✅ 🛠 gtk](https://ews-build.webkit.org/#/builders/2/builds/112284 "Built successfully") | 
| [✅ 🛠 🧪 jsc-arm64](https://ews-build.webkit.org/#/builders/12/builds/103293 "Built successfully and passed tests") | [  ~~🛠 vision~~](https://ews-build.webkit.org/#/builders/128/builds/31840 "The change is no longer eligible for processing. Commit was outdated when EWS attempted to process it.") | [⏳ 🧪 mac-AS-debug-wk2](https://ews-build.webkit.org/#/builders/macOS-Sequoia-Debug-WK2-Tests-EWS "Waiting to run tests") | [  ~~🧪 gtk-wk2~~](https://ews-build.webkit.org/#/builders/1/builds/88583 "The change is no longer eligible for processing. Pull Request was already closed when EWS attempted to process it.") | 
| | [  ~~🛠 vision-sim~~](https://ews-build.webkit.org/#/builders/121/builds/32204 "The change is no longer eligible for processing. Commit was outdated when EWS attempted to process it.") | [✅ 🧪 mac-wk2-stress](https://ews-build.webkit.org/#/builders/8/builds/90701 "Passed tests") | [  ~~🧪 api-gtk~~](https://ews-build.webkit.org/#/builders/21/builds/88199 "The change is no longer eligible for processing. Commit was outdated when EWS attempted to process it.") | 
| | [⏳ 🧪 vision-wk2 ](https://ews-build.webkit.org/#/builders/visionOS-2-Simulator-WK2-Tests-EWS "Waiting in queue, processing has not started yet") | [⏳ 🧪 mac-intel-wk2](https://ews-build.webkit.org/#/builders/macOS-Sonoma-Release-WK2-Intel-Tests-EWS "Waiting to run tests") | [  ~~🛠 playstation~~](https://ews-build.webkit.org/#/builders/134/builds/27153 "The change is no longer eligible for processing. Pull Request was already closed when EWS attempted to process it.") | 
| | [  ~~🛠 tv~~](https://ews-build.webkit.org/#/builders/127/builds/31765 "The change is no longer eligible for processing. Commit was outdated when EWS attempted to process it.") | [  ~~🛠 mac-safer-cpp~~](https://ews-build.webkit.org/#/builders/120/builds/37117 "The change is no longer eligible for processing. Pull Request was already closed when EWS attempted to process it.") | [  ~~🛠 jsc-armv7~~](https://ews-build.webkit.org/#/builders/35/builds/127571 "The change is no longer eligible for processing. Pull Request was already closed when EWS attempted to process it.") | 
| | [  ~~🛠 tv-sim~~](https://ews-build.webkit.org/#/builders/125/builds/31557 "The change is no longer eligible for processing. Pull Request was already closed when EWS attempted to process it.") | | [  ~~🧪 jsc-armv7-tests~~](https://ews-build.webkit.org/#/builders/35/builds/127571 "The change is no longer eligible for processing. Pull Request was already closed when EWS attempted to process it.") | 
| | [  ~~🛠 watch~~](https://ews-build.webkit.org/#/builders/129/builds/34898 "The change is no longer eligible for processing. Pull Request was already closed when EWS attempted to process it.") | | | 
| | [  ~~🛠 watch-sim~~](https://ews-build.webkit.org/#/builders/124/builds/33116 "The change is no longer eligible for processing. Commit was outdated when EWS attempted to process it.") | | | </details>
author_association: COLLABORATOR
user: login: webkit-early-warning-system
created_at: 2025-05-22T20:11:47Z
body: EWS run on current version of this PR (hash https://github.com/WebKit/WebKit/commit/4ad7fb2ee6e7c51c9147f2fe7d765fc5e5452a44)<details>

| Misc | iOS, visionOS, tvOS & watchOS  | macOS  | Linux |  Windows |
| ----- | ---------------------- | ------- |  ----- |  --------- |
| [✅ 🧪 style](https://ews-build.webkit.org/#/builders/38/builds/104688 "Passed style check") | [  ~~🛠 ios~~](https://ews-build.webkit.org/#/builders/131/builds/24400 "The change is no longer eligible for processing. Pull Request was already closed when EWS attempted to process it.") | [✅ 🛠 mac](https://ews-build.webkit.org/#/builders/138/builds/14821 "Built successfully") | [✅ 🛠 wpe](https://ews-build.webkit.org/#/builders/5/builds/109902 "Built successfully") | [  ~~🛠 win~~](https://ews-build.webkit.org/#/builders/59/builds/55362 "The change is no longer eligible for processing. Pull Request was already closed when EWS attempted to process it.") 
| | [✅ 🛠 ios-sim](https://ews-build.webkit.org/#/builders/130/builds/24791 "Built successfully") | [✅ 🛠 mac-AS-debug](https://ews-build.webkit.org/#/builders/123/builds/32946 "Built successfully") | [  ~~🧪 wpe-wk2~~](https://ews-build.webkit.org/#/builders/34/builds/79500 "The change is no longer eligible for processing. Commit was outdated when EWS attempted to process it.") | [  ~~🧪 win-tests~~](https://ews-build.webkit.org/#/builders/59/builds/55362 "The change is no longer eligible for processing. Pull Request was already closed when EWS attempted to process it.") 
| [✅ 🧪 webkitperl](https://ews-build.webkit.org/#/builders/11/builds/107694 "Passed tests") | [  ~~🧪 ios-wk2~~](https://ews-build.webkit.org/#/builders/132/builds/19287 "The change is no longer eligible for processing. Pull Request was already closed when EWS attempted to process it.") | [  ~~🧪 api-mac~~](https://ews-build.webkit.org/#/builders/18/builds/94486 "The change is no longer eligible for processing. Commit was outdated when EWS attempted to process it.") | [✅ 🧪 api-wpe](https://ews-build.webkit.org/#/builders/41/builds/59806 "Passed tests") | 
| | [  ~~🧪 ios-wk2-wpt~~](https://ews-build.webkit.org/#/builders/133/builds/19054 "The change is no longer eligible for processing. Pull Request was already closed when EWS attempted to process it.") | [✅ 🧪 mac-wk1](https://ews-build.webkit.org/#/builders/135/builds/12561 "Passed tests") | [✅ 🛠 wpe-cairo](https://ews-build.webkit.org/#/builders/65/builds/54737 "Built successfully") | 
| [  ~~🛠 🧪 jsc~~](https://ews-build.webkit.org/#/builders/20/builds/97369 "The change is no longer eligible for processing. Pull Request was already closed when EWS attempted to process it.") | [  ~~🧪 api-ios~~](https://ews-build.webkit.org/#/builders/13/builds/88750 "The change is no longer eligible for processing. Pull Request was already closed when EWS attempted to process it.") | [  ~~🧪 mac-wk2~~](https://ews-build.webkit.org/#/builders/136/builds/12611 "The change is no longer eligible for processing. Pull Request was already closed when EWS attempted to process it.") | [✅ 🛠 gtk](https://ews-build.webkit.org/#/builders/2/builds/112297 "Built successfully") | 
| [✅ 🛠 🧪 jsc-arm64](https://ews-build.webkit.org/#/builders/12/builds/103306 "Built successfully and passed tests") | [  ~~🛠 vision~~](https://ews-build.webkit.org/#/builders/128/builds/31853 "The change is no longer eligible for processing. Pull Request was already closed when EWS attempted to process it.") | [  ~~🧪 mac-AS-debug-wk2~~](https://ews-build.webkit.org/#/builders/122/builds/23437 "The change is no longer eligible for processing. Pull Request was already closed when EWS attempted to process it.") | [⏳ 🧪 gtk-wk2](https://ews-build.webkit.org/#/builders/GTK-WK2-Tests-EWS "Waiting to run tests") | 
| | [  ~~🛠 vision-sim~~](https://ews-build.webkit.org/#/builders/121/builds/32217 "The change is no longer eligible for processing. Pull Request was already closed when EWS attempted to process it.") | [✅ 🧪 mac-wk2-stress](https://ews-build.webkit.org/#/builders/8/builds/90715 "Passed tests") | [⏳ 🧪 api-gtk](https://ews-build.webkit.org/#/builders/API-Tests-GTK-EWS "Waiting to run tests") | 
| | [⏳ 🧪 vision-wk2 ](https://ews-build.webkit.org/#/builders/visionOS-2-Simulator-WK2-Tests-EWS "Waiting in queue, processing has not started yet") | [  ~~🧪 mac-intel-wk2~~](https://ews-build.webkit.org/#/builders/137/builds/10868 "The change is no longer eligible for processing. Pull Request was already closed when EWS attempted to process it.") | [  ~~🛠 playstation~~](https://ews-build.webkit.org/#/builders/134/builds/27166 "The change is no longer eligible for processing. Pull Request was already closed when EWS attempted to process it.") | 
| [✅ 🛠 🧪 unsafe-merge](https://ews-build.webkit.org/#/builders/22/builds/16984 "Built successfully and passed tests") | [  ~~🛠 tv~~](https://ews-build.webkit.org/#/builders/127/builds/31778 "The change is no longer eligible for processing. Pull Request was already closed when EWS attempted to process it.") | [  ~~🛠 mac-safer-cpp~~](https://ews-build.webkit.org/#/builders/120/builds/37130 "The change is no longer eligible for processing. Pull Request was already closed when EWS attempted to process it.") | [  ~~🛠 jsc-armv7~~](https://ews-build.webkit.org/#/builders/35/builds/127585 "The change is no longer eligible for processing. Pull Request was already closed when EWS attempted to process it.") | 
| | [  ~~🛠 tv-sim~~](https://ews-build.webkit.org/#/builders/125/builds/31570 "The change is no longer eligible for processing. Pull Request was already closed when EWS attempted to process it.") | | [  ~~🧪 jsc-armv7-tests~~](https://ews-build.webkit.org/#/builders/35/builds/127585 "The change is no longer eligible for processing. Pull Request was already closed when EWS attempted to process it.") | 
| | [  ~~🛠 watch~~](https://ews-build.webkit.org/#/builders/129/builds/34911 "The change is no longer eligible for processing. Pull Request was already closed when EWS attempted to process it.") | | | 
| | [  ~~🛠 watch-sim~~](https://ews-build.webkit.org/#/builders/124/builds/33129 "The change is no longer eligible for processing. Pull Request was already closed when EWS attempted to process it.") | | | </details>
author_association: COLLABORATOR
user: login: Constellation
created_at: 2025-05-22T20:42:49Z
body: Only commit message update, and EWS was green.
author_association: MEMBER
user: login: webkit-commit-queue
created_at: 2025-05-22T20:45:04Z
body: Committed 295296@main (ab4489156571): <https://commits.webkit.org/295296@main>

Reviewed commits have been landed. Closing PR #45781 and removing active labels.
author_association: COLLABORATOR