<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[278029] trunk/Source/JavaScriptCore</title>
</head>
<body>

<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt;  }
#msg dl a { font-weight: bold}
#msg dl a:link    { color:#fc3; }
#msg dl a:active  { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff  {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta">
<dt>Revision</dt> <dd><a href="http://trac.webkit.org/projects/webkit/changeset/278029">278029</a></dd>
<dt>Author</dt> <dd>mark.lam@apple.com</dd>
<dt>Date</dt> <dd>2021-05-25 11:03:20 -0700 (Tue, 25 May 2021)</dd>
</dl>

<h3>Log Message</h3>
<pre>Reduce Baseline JIT emitted code size for op_jfalse, op_jtrue, op_get_from_scope, op_resolve_scope.
https://bugs.webkit.org/show_bug.cgi?id=226107

Reviewed by Saam Barati.

Benchmarking with JetStream2 and Speedometer2 on M1 Mac shows that performance is
neutral.

This patch reduces Baseline JIT emitted code side on a run of JetStream2 CLI by
another ~6.6M:
                Base                     New                      Diff

   BaselineJIT: 64955116 (61.946026 MB)  57991704 (55.305199 MB)  0.89x (reduction)
           DFG: 36382012 (34.696590 MB)  36540652 (34.847881 MB)  1.00x
         Thunk: 23217692 (22.142117 MB)  23115852 (22.044994 MB)  1.00x
   InlineCache: 22228140 (21.198406 MB)  22262572 (21.231243 MB)  1.00x
           FTL: 6025320 (5.746193 MB)    6164332 (5.878765 MB)    1.02x
          Wasm: 2327604 (2.219776 MB)    2297036 (2.190624 MB)    0.99x
       YarrJIT: 1547172 (1.475498 MB)    1522584 (1.452049 MB)    0.98x
        CSSJIT: 0                        0
 Uncategorized: 0                        0

Cumulative diff since the start of this effort to reduce Baseline JIT code size:

                Base                     New                      Diff

   BaselineJIT: 89089964 (84.962811 MB)  57991704 (55.305199 MB)  0.65x (reduction)
           DFG: 39117360 (37.305222 MB)  36540652 (34.847881 MB)  0.93x (reduction)
         Thunk: 23230968 (22.154778 MB)  23115852 (22.044994 MB)  1.00x
   InlineCache: 22027416 (21.006981 MB)  22262572 (21.231243 MB)  1.01x
           FTL: 6575772 (6.271145 MB)    6164332 (5.878765 MB)    0.94x (reduction)
          Wasm: 2302724 (2.196049 MB)    2297036 (2.190624 MB)    1.00x
       YarrJIT: 1538956 (1.467663 MB)    1522584 (1.452049 MB)    0.99x
        CSSJIT: 0                        0
 Uncategorized: 0                        0

* bytecode/CodeBlock.h:
(JSC::CodeBlock::offsetInMetadataTable):
(JSC::CodeBlock::offsetOfMetadataTable):
* jit/AssemblyHelpers.cpp:
(JSC::AssemblyHelpers::branchIfValue):
* jit/AssemblyHelpers.h:
(JSC::AssemblyHelpers::branchIfTruthy):
(JSC::AssemblyHelpers::branchIfFalsey):
* jit/JIT.cpp:
(JSC::JIT::privateCompileSlowCases):
* jit/JIT.h:
* jit/JITOpcodes.cpp:
(JSC::JIT::emit_op_jfalse):
(JSC::JIT::valueIsFalseyGenerator):
(JSC::JIT::emit_op_jtrue):
(JSC::JIT::valueIsTruthyGenerator):
* jit/JITOperations.cpp:
(JSC::JSC_DEFINE_JIT_OPERATION):
* jit/JITOperations.h:
* jit/JITPropertyAccess.cpp:
(JSC::JIT::emit_op_resolve_scope):
(JSC::JIT::generateOpResolveScopeThunk):
(JSC::JIT::slow_op_resolve_scopeGenerator):
(JSC::JIT::emitSlow_op_get_from_scope):
(JSC::JIT::emit_op_get_from_scope):
(JSC::JIT::generateOpGetFromScopeThunk):
(JSC::JIT::slow_op_get_from_scopeGenerator):
* jit/ThunkGenerators.cpp:
(JSC::popThunkStackPreservesAndHandleExceptionGenerator):
* runtime/GetPutInfo.h:
* runtime/JSGlobalObject.h:
(JSC::JSGlobalObject::offsetOfGlobalLexicalEnvironment):
(JSC::JSGlobalObject::offsetOfGlobalLexicalBindingEpoch):</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkSourceJavaScriptCoreChangeLog">trunk/Source/JavaScriptCore/ChangeLog</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecodeCodeBlockh">trunk/Source/JavaScriptCore/bytecode/CodeBlock.h</a></li>
<li><a href="#trunkSourceJavaScriptCorejitAssemblyHelperscpp">trunk/Source/JavaScriptCore/jit/AssemblyHelpers.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorejitAssemblyHelpersh">trunk/Source/JavaScriptCore/jit/AssemblyHelpers.h</a></li>
<li><a href="#trunkSourceJavaScriptCorejitJITcpp">trunk/Source/JavaScriptCore/jit/JIT.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorejitJITh">trunk/Source/JavaScriptCore/jit/JIT.h</a></li>
<li><a href="#trunkSourceJavaScriptCorejitJITOpcodescpp">trunk/Source/JavaScriptCore/jit/JITOpcodes.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorejitJITOperationscpp">trunk/Source/JavaScriptCore/jit/JITOperations.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorejitJITOperationsh">trunk/Source/JavaScriptCore/jit/JITOperations.h</a></li>
<li><a href="#trunkSourceJavaScriptCorejitJITPropertyAccesscpp">trunk/Source/JavaScriptCore/jit/JITPropertyAccess.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorejitThunkGeneratorscpp">trunk/Source/JavaScriptCore/jit/ThunkGenerators.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeGetPutInfoh">trunk/Source/JavaScriptCore/runtime/GetPutInfo.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeJSGlobalObjecth">trunk/Source/JavaScriptCore/runtime/JSGlobalObject.h</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceJavaScriptCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ChangeLog (278028 => 278029)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ChangeLog    2021-05-25 17:34:04 UTC (rev 278028)
+++ trunk/Source/JavaScriptCore/ChangeLog       2021-05-25 18:03:20 UTC (rev 278029)
</span><span class="lines">@@ -1,3 +1,75 @@
</span><ins>+2021-05-25  Mark Lam  <mark.lam@apple.com>
+
+        Reduce Baseline JIT emitted code size for op_jfalse, op_jtrue, op_get_from_scope, op_resolve_scope.
+        https://bugs.webkit.org/show_bug.cgi?id=226107
+
+        Reviewed by Saam Barati.
+
+        Benchmarking with JetStream2 and Speedometer2 on M1 Mac shows that performance is
+        neutral.
+
+        This patch reduces Baseline JIT emitted code side on a run of JetStream2 CLI by
+        another ~6.6M:
+                        Base                     New                      Diff
+
+           BaselineJIT: 64955116 (61.946026 MB)  57991704 (55.305199 MB)  0.89x (reduction)
+                   DFG: 36382012 (34.696590 MB)  36540652 (34.847881 MB)  1.00x
+                 Thunk: 23217692 (22.142117 MB)  23115852 (22.044994 MB)  1.00x
+           InlineCache: 22228140 (21.198406 MB)  22262572 (21.231243 MB)  1.00x
+                   FTL: 6025320 (5.746193 MB)    6164332 (5.878765 MB)    1.02x
+                  Wasm: 2327604 (2.219776 MB)    2297036 (2.190624 MB)    0.99x
+               YarrJIT: 1547172 (1.475498 MB)    1522584 (1.452049 MB)    0.98x
+                CSSJIT: 0                        0
+         Uncategorized: 0                        0
+
+        Cumulative diff since the start of this effort to reduce Baseline JIT code size:
+
+                        Base                     New                      Diff
+
+           BaselineJIT: 89089964 (84.962811 MB)  57991704 (55.305199 MB)  0.65x (reduction)
+                   DFG: 39117360 (37.305222 MB)  36540652 (34.847881 MB)  0.93x (reduction)
+                 Thunk: 23230968 (22.154778 MB)  23115852 (22.044994 MB)  1.00x
+           InlineCache: 22027416 (21.006981 MB)  22262572 (21.231243 MB)  1.01x
+                   FTL: 6575772 (6.271145 MB)    6164332 (5.878765 MB)    0.94x (reduction)
+                  Wasm: 2302724 (2.196049 MB)    2297036 (2.190624 MB)    1.00x
+               YarrJIT: 1538956 (1.467663 MB)    1522584 (1.452049 MB)    0.99x
+                CSSJIT: 0                        0
+         Uncategorized: 0                        0
+
+        * bytecode/CodeBlock.h:
+        (JSC::CodeBlock::offsetInMetadataTable):
+        (JSC::CodeBlock::offsetOfMetadataTable):
+        * jit/AssemblyHelpers.cpp:
+        (JSC::AssemblyHelpers::branchIfValue):
+        * jit/AssemblyHelpers.h:
+        (JSC::AssemblyHelpers::branchIfTruthy):
+        (JSC::AssemblyHelpers::branchIfFalsey):
+        * jit/JIT.cpp:
+        (JSC::JIT::privateCompileSlowCases):
+        * jit/JIT.h:
+        * jit/JITOpcodes.cpp:
+        (JSC::JIT::emit_op_jfalse):
+        (JSC::JIT::valueIsFalseyGenerator):
+        (JSC::JIT::emit_op_jtrue):
+        (JSC::JIT::valueIsTruthyGenerator):
+        * jit/JITOperations.cpp:
+        (JSC::JSC_DEFINE_JIT_OPERATION):
+        * jit/JITOperations.h:
+        * jit/JITPropertyAccess.cpp:
+        (JSC::JIT::emit_op_resolve_scope):
+        (JSC::JIT::generateOpResolveScopeThunk):
+        (JSC::JIT::slow_op_resolve_scopeGenerator):
+        (JSC::JIT::emitSlow_op_get_from_scope):
+        (JSC::JIT::emit_op_get_from_scope):
+        (JSC::JIT::generateOpGetFromScopeThunk):
+        (JSC::JIT::slow_op_get_from_scopeGenerator):
+        * jit/ThunkGenerators.cpp:
+        (JSC::popThunkStackPreservesAndHandleExceptionGenerator):
+        * runtime/GetPutInfo.h:
+        * runtime/JSGlobalObject.h:
+        (JSC::JSGlobalObject::offsetOfGlobalLexicalEnvironment):
+        (JSC::JSGlobalObject::offsetOfGlobalLexicalBindingEpoch):
+
</ins><span class="cx"> 2021-05-24  Robin Morisset  <rmorisset@apple.com>
</span><span class="cx"> 
</span><span class="cx">         When running with --reportTotalPhaseTimes=1, we should also log the max time in a phase
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecodeCodeBlockh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecode/CodeBlock.h (278028 => 278029)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/CodeBlock.h 2021-05-25 17:34:04 UTC (rev 278028)
+++ trunk/Source/JavaScriptCore/bytecode/CodeBlock.h    2021-05-25 18:03:20 UTC (rev 278029)
</span><span class="lines">@@ -890,6 +890,12 @@
</span><span class="cx">         return bitwise_cast<Metadata*>(m_metadata->get(opcodeID))[metadataID];
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    template<typename Metadata>
+    ptrdiff_t offsetInMetadataTable(Metadata* metadata)
+    {
+        return bitwise_cast<uint8_t*>(metadata) - bitwise_cast<uint8_t*>(metadataTable());
+    }
+
</ins><span class="cx">     size_t metadataSizeInBytes()
</span><span class="cx">     {
</span><span class="cx">         return m_unlinkedCode->metadataSizeInBytes();
</span><span class="lines">@@ -898,6 +904,7 @@
</span><span class="cx">     MetadataTable* metadataTable() { return m_metadata.get(); }
</span><span class="cx">     const void* instructionsRawPointer() { return m_instructionsRawPointer; }
</span><span class="cx"> 
</span><ins>+    static ptrdiff_t offsetOfMetadataTable() { return OBJECT_OFFSETOF(CodeBlock, m_metadata); }
</ins><span class="cx">     static ptrdiff_t offsetOfInstructionsRawPointer() { return OBJECT_OFFSETOF(CodeBlock, m_instructionsRawPointer); }
</span><span class="cx"> 
</span><span class="cx">     bool loopHintsAreEligibleForFuzzingEarlyReturn()
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitAssemblyHelperscpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/AssemblyHelpers.cpp (278028 => 278029)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/AssemblyHelpers.cpp      2021-05-25 17:34:04 UTC (rev 278028)
+++ trunk/Source/JavaScriptCore/jit/AssemblyHelpers.cpp 2021-05-25 18:03:20 UTC (rev 278029)
</span><span class="lines">@@ -797,7 +797,7 @@
</span><span class="cx">     done.link(this);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-AssemblyHelpers::JumpList AssemblyHelpers::branchIfValue(VM& vm, JSValueRegs value, GPRReg scratch, GPRReg scratchIfShouldCheckMasqueradesAsUndefined, FPRReg valueAsFPR, FPRReg tempFPR, bool shouldCheckMasqueradesAsUndefined, JSGlobalObject* globalObject, bool invert)
</del><ins>+AssemblyHelpers::JumpList AssemblyHelpers::branchIfValue(VM& vm, JSValueRegs value, GPRReg scratch, GPRReg scratchIfShouldCheckMasqueradesAsUndefined, FPRReg valueAsFPR, FPRReg tempFPR, bool shouldCheckMasqueradesAsUndefined, Variant<JSGlobalObject*, GPRReg> globalObject, bool invert)
</ins><span class="cx"> {
</span><span class="cx">     // Implements the following control flow structure:
</span><span class="cx">     // if (value is cell) {
</span><span class="lines">@@ -829,7 +829,10 @@
</span><span class="cx">         JumpList isNotMasqueradesAsUndefined;
</span><span class="cx">         isNotMasqueradesAsUndefined.append(branchTest8(Zero, Address(value.payloadGPR(), JSCell::typeInfoFlagsOffset()), TrustedImm32(MasqueradesAsUndefined)));
</span><span class="cx">         emitLoadStructure(vm, value.payloadGPR(), scratch, scratchIfShouldCheckMasqueradesAsUndefined);
</span><del>-        move(TrustedImmPtr(globalObject), scratchIfShouldCheckMasqueradesAsUndefined);
</del><ins>+        if (WTF::holds_alternative<JSGlobalObject*>(globalObject))
+            move(TrustedImmPtr(WTF::get<JSGlobalObject*>(globalObject)), scratchIfShouldCheckMasqueradesAsUndefined);
+        else
+            move(WTF::get<GPRReg>(globalObject), scratchIfShouldCheckMasqueradesAsUndefined);
</ins><span class="cx">         isNotMasqueradesAsUndefined.append(branchPtr(NotEqual, Address(scratch, Structure::globalObjectOffset()), scratchIfShouldCheckMasqueradesAsUndefined));
</span><span class="cx"> 
</span><span class="cx">         // We act like we are "undefined" here.
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitAssemblyHelpersh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/AssemblyHelpers.h (278028 => 278029)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/AssemblyHelpers.h        2021-05-25 17:34:04 UTC (rev 278028)
+++ trunk/Source/JavaScriptCore/jit/AssemblyHelpers.h   2021-05-25 18:03:20 UTC (rev 278029)
</span><span class="lines">@@ -44,6 +44,7 @@
</span><span class="cx"> #include "TagRegistersMode.h"
</span><span class="cx"> #include "TypeofType.h"
</span><span class="cx"> #include "VM.h"
</span><ins>+#include <wtf/Variant.h>
</ins><span class="cx"> 
</span><span class="cx"> namespace JSC {
</span><span class="cx"> 
</span><span class="lines">@@ -1896,12 +1897,12 @@
</span><span class="cx">         storePtr(TrustedImmPtr(nullptr), Address(resultGPR, JSObject::butterflyOffset()));
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    JumpList branchIfValue(VM&, JSValueRegs, GPRReg scratch, GPRReg scratchIfShouldCheckMasqueradesAsUndefined, FPRReg, FPRReg, bool shouldCheckMasqueradesAsUndefined, JSGlobalObject*, bool negateResult);
-    JumpList branchIfTruthy(VM& vm, JSValueRegs value, GPRReg scratch, GPRReg scratchIfShouldCheckMasqueradesAsUndefined, FPRReg scratchFPR0, FPRReg scratchFPR1, bool shouldCheckMasqueradesAsUndefined, JSGlobalObject* globalObject)
</del><ins>+    JumpList branchIfValue(VM&, JSValueRegs, GPRReg scratch, GPRReg scratchIfShouldCheckMasqueradesAsUndefined, FPRReg, FPRReg, bool shouldCheckMasqueradesAsUndefined, Variant<JSGlobalObject*, GPRReg>, bool negateResult);
+    JumpList branchIfTruthy(VM& vm, JSValueRegs value, GPRReg scratch, GPRReg scratchIfShouldCheckMasqueradesAsUndefined, FPRReg scratchFPR0, FPRReg scratchFPR1, bool shouldCheckMasqueradesAsUndefined, Variant<JSGlobalObject*, GPRReg> globalObject)
</ins><span class="cx">     {
</span><span class="cx">         return branchIfValue(vm, value, scratch, scratchIfShouldCheckMasqueradesAsUndefined, scratchFPR0, scratchFPR1, shouldCheckMasqueradesAsUndefined, globalObject, false);
</span><span class="cx">     }
</span><del>-    JumpList branchIfFalsey(VM& vm, JSValueRegs value, GPRReg scratch, GPRReg scratchIfShouldCheckMasqueradesAsUndefined, FPRReg scratchFPR0, FPRReg scratchFPR1, bool shouldCheckMasqueradesAsUndefined, JSGlobalObject* globalObject)
</del><ins>+    JumpList branchIfFalsey(VM& vm, JSValueRegs value, GPRReg scratch, GPRReg scratchIfShouldCheckMasqueradesAsUndefined, FPRReg scratchFPR0, FPRReg scratchFPR1, bool shouldCheckMasqueradesAsUndefined, Variant<JSGlobalObject*, GPRReg> globalObject)
</ins><span class="cx">     {
</span><span class="cx">         return branchIfValue(vm, value, scratch, scratchIfShouldCheckMasqueradesAsUndefined, scratchFPR0, scratchFPR1, shouldCheckMasqueradesAsUndefined, globalObject, true);
</span><span class="cx">     }
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitJITcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/JIT.cpp (278028 => 278029)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/JIT.cpp  2021-05-25 17:34:04 UTC (rev 278028)
+++ trunk/Source/JavaScriptCore/jit/JIT.cpp     2021-05-25 18:03:20 UTC (rev 278029)
</span><span class="lines">@@ -589,7 +589,9 @@
</span><span class="cx">         DEFINE_SLOWCASE_OP(op_del_by_id)
</span><span class="cx">         DEFINE_SLOWCASE_OP(op_sub)
</span><span class="cx">         DEFINE_SLOWCASE_OP(op_has_enumerable_indexed_property)
</span><ins>+#if !ENABLE(EXTRA_CTI_THUNKS)
</ins><span class="cx">         DEFINE_SLOWCASE_OP(op_get_from_scope)
</span><ins>+#endif
</ins><span class="cx">         DEFINE_SLOWCASE_OP(op_put_to_scope)
</span><span class="cx"> 
</span><span class="cx">         DEFINE_SLOWCASE_OP(op_iterator_open)
</span><span class="lines">@@ -624,7 +626,9 @@
</span><span class="cx">         DEFINE_SLOWCASE_SLOW_OP(has_enumerable_structure_property)
</span><span class="cx">         DEFINE_SLOWCASE_SLOW_OP(has_own_structure_property)
</span><span class="cx">         DEFINE_SLOWCASE_SLOW_OP(in_structure_property)
</span><ins>+#if !ENABLE(EXTRA_CTI_THUNKS)
</ins><span class="cx">         DEFINE_SLOWCASE_SLOW_OP(resolve_scope)
</span><ins>+#endif
</ins><span class="cx">         DEFINE_SLOWCASE_SLOW_OP(check_tdz)
</span><span class="cx">         DEFINE_SLOWCASE_SLOW_OP(to_property_key)
</span><span class="cx">         default:
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitJITh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/JIT.h (278028 => 278029)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/JIT.h    2021-05-25 17:34:04 UTC (rev 278028)
+++ trunk/Source/JavaScriptCore/jit/JIT.h       2021-05-25 18:03:20 UTC (rev 278029)
</span><span class="lines">@@ -730,7 +730,9 @@
</span><span class="cx">         void emit_op_put_to_scope(const Instruction*);
</span><span class="cx">         void emit_op_get_from_arguments(const Instruction*);
</span><span class="cx">         void emit_op_put_to_arguments(const Instruction*);
</span><ins>+#if !ENABLE(EXTRA_CTI_THUNKS)
</ins><span class="cx">         void emitSlow_op_get_from_scope(const Instruction*, Vector<SlowCaseEntry>::iterator&);
</span><ins>+#endif
</ins><span class="cx">         void emitSlow_op_put_to_scope(const Instruction*, Vector<SlowCaseEntry>::iterator&);
</span><span class="cx"> 
</span><span class="cx">         void emitSlowCaseCall(const Instruction*, Vector<SlowCaseEntry>::iterator&, SlowPathFunction);
</span><span class="lines">@@ -796,13 +798,46 @@
</span><span class="cx">         static MacroAssemblerCodeRef<JITThunkPtrTag> slow_op_put_by_val_prepareCallGenerator(VM&);
</span><span class="cx">         static MacroAssemblerCodeRef<JITThunkPtrTag> slow_op_put_private_name_prepareCallGenerator(VM&);
</span><span class="cx">         static MacroAssemblerCodeRef<JITThunkPtrTag> slow_op_put_to_scopeGenerator(VM&);
</span><ins>+        static MacroAssemblerCodeRef<JITThunkPtrTag> slow_op_resolve_scopeGenerator(VM&);
</ins><span class="cx"> 
</span><span class="cx">         static MacroAssemblerCodeRef<JITThunkPtrTag> op_check_traps_handlerGenerator(VM&);
</span><span class="cx">         static MacroAssemblerCodeRef<JITThunkPtrTag> op_enter_handlerGenerator(VM&);
</span><span class="cx">         static MacroAssemblerCodeRef<JITThunkPtrTag> op_ret_handlerGenerator(VM&);
</span><span class="cx">         static MacroAssemblerCodeRef<JITThunkPtrTag> op_throw_handlerGenerator(VM&);
</span><del>-#endif
</del><span class="cx"> 
</span><ins>+        static constexpr bool thunkIsUsedForOpGetFromScope(ResolveType resolveType)
+        {
+            // GlobalVar because it is more efficient to emit inline than use a thunk.
+            // LocalClosureVar and ModuleVar because we don't use these types with op_get_from_scope.
+            return !(resolveType == GlobalVar || resolveType == LocalClosureVar || resolveType == ModuleVar);
+        }
+
+#define DECLARE_GET_FROM_SCOPE_GENERATOR(resolveType) \
+        static MacroAssemblerCodeRef<JITThunkPtrTag> op_get_from_scope_##resolveType##Generator(VM&);
+        FOR_EACH_RESOLVE_TYPE(DECLARE_GET_FROM_SCOPE_GENERATOR)
+#undef DECLARE_GET_FROM_SCOPE_GENERATOR
+
+        MacroAssemblerCodeRef<JITThunkPtrTag> generateOpGetFromScopeThunk(ResolveType, const char* thunkName);
+
+        static constexpr bool thunkIsUsedForOpResolveScope(ResolveType resolveType)
+        {
+            // ModuleVar because it is more efficient to emit inline than use a thunk.
+            // LocalClosureVar because we don't use these types with op_resolve_scope.
+            return !(resolveType == LocalClosureVar || resolveType == ModuleVar);
+        }
+
+#define DECLARE_RESOLVE_SCOPE_GENERATOR(resolveType) \
+        static MacroAssemblerCodeRef<JITThunkPtrTag> op_resolve_scope_##resolveType##Generator(VM&);
+        FOR_EACH_RESOLVE_TYPE(DECLARE_RESOLVE_SCOPE_GENERATOR)
+#undef DECLARE_RESOLVE_SCOPE_GENERATOR
+
+        MacroAssemblerCodeRef<JITThunkPtrTag> generateOpResolveScopeThunk(ResolveType, const char* thunkName);
+
+        static MacroAssemblerCodeRef<JITThunkPtrTag> valueIsFalseyGenerator(VM&);
+        static MacroAssemblerCodeRef<JITThunkPtrTag> valueIsTruthyGenerator(VM&);
+
+#endif // ENABLE(EXTRA_CTI_THUNKS)
+
</ins><span class="cx">         Jump getSlowCase(Vector<SlowCaseEntry>::iterator& iter)
</span><span class="cx">         {
</span><span class="cx">             return iter++->from;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitJITOpcodescpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/JITOpcodes.cpp (278028 => 278029)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/JITOpcodes.cpp   2021-05-25 17:34:04 UTC (rev 278028)
+++ trunk/Source/JavaScriptCore/jit/JITOpcodes.cpp      2021-05-25 18:03:20 UTC (rev 278029)
</span><span class="lines">@@ -447,15 +447,54 @@
</span><span class="cx">     auto bytecode = currentInstruction->as<OpJfalse>();
</span><span class="cx">     unsigned target = jumpTarget(currentInstruction, bytecode.m_targetLabel);
</span><span class="cx"> 
</span><del>-    GPRReg value = regT0;
-    GPRReg scratch1 = regT1;
-    GPRReg scratch2 = regT2;
-    bool shouldCheckMasqueradesAsUndefined = true;
</del><ins>+    constexpr GPRReg value = regT0;
</ins><span class="cx"> 
</span><span class="cx">     emitGetVirtualRegister(bytecode.m_condition, value);
</span><ins>+#if !ENABLE(EXTRA_CTI_THUNKS)
+    constexpr GPRReg scratch1 = regT1;
+    constexpr GPRReg scratch2 = regT2;
+    constexpr bool shouldCheckMasqueradesAsUndefined = true;
</ins><span class="cx">     addJump(branchIfFalsey(vm(), JSValueRegs(value), scratch1, scratch2, fpRegT0, fpRegT1, shouldCheckMasqueradesAsUndefined, m_codeBlock->globalObject()), target);
</span><ins>+#else
+    emitNakedNearCall(vm().getCTIStub(valueIsFalseyGenerator).retaggedCode<NoPtrTag>());
+    addJump(branchTest32(NonZero, regT0), target);
+#endif
</ins><span class="cx"> }
</span><span class="cx"> 
</span><ins>+#if ENABLE(EXTRA_CTI_THUNKS)
+MacroAssemblerCodeRef<JITThunkPtrTag> JIT::valueIsFalseyGenerator(VM& vm)
+{
+    // The thunk generated by this function can only work with the LLInt / Baseline JIT because
+    // it makes assumptions about the right globalObject being available from CallFrame::codeBlock().
+    // DFG/FTL may inline functions belonging to other globalObjects, which may not match
+    // CallFrame::codeBlock().
+    JIT jit(vm);
+
+    constexpr GPRReg value = regT0;
+    constexpr GPRReg scratch1 = regT1;
+    constexpr GPRReg scratch2 = regT2;
+    constexpr bool shouldCheckMasqueradesAsUndefined = true;
+
+    jit.tagReturnAddress();
+
+    constexpr GPRReg globalObjectGPR = regT3;
+    jit.loadPtr(addressFor(CallFrameSlot::codeBlock), globalObjectGPR);
+    jit.loadPtr(Address(globalObjectGPR, CodeBlock::offsetOfGlobalObject()), globalObjectGPR);
+    auto isFalsey = jit.branchIfFalsey(vm, JSValueRegs(value), scratch1, scratch2, fpRegT0, fpRegT1, shouldCheckMasqueradesAsUndefined, globalObjectGPR);
+    jit.move(TrustedImm32(0), regT0);
+    Jump done = jit.jump();
+
+    isFalsey.link(&jit);
+    jit.move(TrustedImm32(1), regT0);
+
+    done.link(&jit);
+    jit.ret();
+
+    LinkBuffer patchBuffer(jit, GLOBAL_THUNK_ID, LinkBuffer::Profile::Thunk);
+    return FINALIZE_CODE(patchBuffer, JITThunkPtrTag, "Baseline: valueIsfalsey");
+}
+#endif // ENABLE(EXTRA_CTI_THUNKS)
+
</ins><span class="cx"> void JIT::emit_op_jeq_null(const Instruction* currentInstruction)
</span><span class="cx"> {
</span><span class="cx">     auto bytecode = currentInstruction->as<OpJeqNull>();
</span><span class="lines">@@ -568,14 +607,54 @@
</span><span class="cx">     auto bytecode = currentInstruction->as<OpJtrue>();
</span><span class="cx">     unsigned target = jumpTarget(currentInstruction, bytecode.m_targetLabel);
</span><span class="cx"> 
</span><del>-    GPRReg value = regT0;
-    GPRReg scratch1 = regT1;
-    GPRReg scratch2 = regT2;
-    bool shouldCheckMasqueradesAsUndefined = true;
</del><ins>+    constexpr GPRReg value = regT0;
+
</ins><span class="cx">     emitGetVirtualRegister(bytecode.m_condition, value);
</span><ins>+#if !ENABLE(EXTRA_CTI_THUNKS)
+    constexpr GPRReg scratch1 = regT1;
+    constexpr GPRReg scratch2 = regT2;
+    constexpr bool shouldCheckMasqueradesAsUndefined = true;
</ins><span class="cx">     addJump(branchIfTruthy(vm(), JSValueRegs(value), scratch1, scratch2, fpRegT0, fpRegT1, shouldCheckMasqueradesAsUndefined, m_codeBlock->globalObject()), target);
</span><ins>+#else
+    emitNakedNearCall(vm().getCTIStub(valueIsTruthyGenerator).retaggedCode<NoPtrTag>());
+    addJump(branchTest32(NonZero, regT0), target);
+#endif
</ins><span class="cx"> }
</span><span class="cx"> 
</span><ins>+#if ENABLE(EXTRA_CTI_THUNKS)
+MacroAssemblerCodeRef<JITThunkPtrTag> JIT::valueIsTruthyGenerator(VM& vm)
+{
+    // The thunk generated by this function can only work with the LLInt / Baseline JIT because
+    // it makes assumptions about the right globalObject being available from CallFrame::codeBlock().
+    // DFG/FTL may inline functions belonging to other globalObjects, which may not match
+    // CallFrame::codeBlock().
+    JIT jit(vm);
+
+    constexpr GPRReg value = regT0;
+    constexpr GPRReg scratch1 = regT1;
+    constexpr GPRReg scratch2 = regT2;
+    constexpr bool shouldCheckMasqueradesAsUndefined = true;
+
+    jit.tagReturnAddress();
+
+    constexpr GPRReg globalObjectGPR = regT3;
+    jit.loadPtr(addressFor(CallFrameSlot::codeBlock), globalObjectGPR);
+    jit.loadPtr(Address(globalObjectGPR, CodeBlock::offsetOfGlobalObject()), globalObjectGPR);
+    auto isTruthy = jit.branchIfTruthy(vm, JSValueRegs(value), scratch1, scratch2, fpRegT0, fpRegT1, shouldCheckMasqueradesAsUndefined, globalObjectGPR);
+    jit.move(TrustedImm32(0), regT0);
+    Jump done = jit.jump();
+
+    isTruthy.link(&jit);
+    jit.move(TrustedImm32(1), regT0);
+
+    done.link(&jit);
+    jit.ret();
+
+    LinkBuffer patchBuffer(jit, GLOBAL_THUNK_ID, LinkBuffer::Profile::Thunk);
+    return FINALIZE_CODE(patchBuffer, JITThunkPtrTag, "Baseline: valueIsfalsey");
+}
+#endif // ENABLE(EXTRA_CTI_THUNKS)
+
</ins><span class="cx"> void JIT::emit_op_neq(const Instruction* currentInstruction)
</span><span class="cx"> {
</span><span class="cx">     auto bytecode = currentInstruction->as<OpNeq>();
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitJITOperationscpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/JITOperations.cpp (278028 => 278029)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/JITOperations.cpp        2021-05-25 17:34:04 UTC (rev 278028)
+++ trunk/Source/JavaScriptCore/jit/JITOperations.cpp   2021-05-25 18:03:20 UTC (rev 278029)
</span><span class="lines">@@ -2898,6 +2898,60 @@
</span><span class="cx">     return reinterpret_cast<char*>(result);
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+#if ENABLE(EXTRA_CTI_THUNKS)
+JSC_DEFINE_JIT_OPERATION(operationResolveScopeForBaseline, EncodedJSValue, (JSGlobalObject* globalObject, const Instruction* pc))
+{
+    VM& vm = globalObject->vm();
+    CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
+    JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
+    auto throwScope = DECLARE_THROW_SCOPE(vm);
+
+    CodeBlock* codeBlock = callFrame->codeBlock();
+
+    auto bytecode = pc->as<OpResolveScope>();
+    const Identifier& ident = codeBlock->identifier(bytecode.m_var);
+    JSScope* scope = callFrame->uncheckedR(bytecode.m_scope).Register::scope();
+    JSObject* resolvedScope = JSScope::resolve(globalObject, scope, ident);
+    // Proxy can throw an error here, e.g. Proxy in with statement's @unscopables.
+    RETURN_IF_EXCEPTION(throwScope, { });
+
+    auto& metadata = bytecode.metadata(codeBlock);
+    ResolveType resolveType = metadata.m_resolveType;
+
+    // ModuleVar does not keep the scope register value alive in DFG.
+    ASSERT(resolveType != ModuleVar);
+
+    switch (resolveType) {
+    case GlobalProperty:
+    case GlobalPropertyWithVarInjectionChecks:
+    case UnresolvedProperty:
+    case UnresolvedPropertyWithVarInjectionChecks: {
+        if (resolvedScope->isGlobalObject()) {
+            JSGlobalObject* globalObject = jsCast<JSGlobalObject*>(resolvedScope);
+            bool hasProperty = globalObject->hasProperty(globalObject, ident);
+            RETURN_IF_EXCEPTION(throwScope, { });
+            if (hasProperty) {
+                ConcurrentJSLocker locker(codeBlock->m_lock);
+                metadata.m_resolveType = needsVarInjectionChecks(resolveType) ? GlobalPropertyWithVarInjectionChecks : GlobalProperty;
+                metadata.m_globalObject.set(vm, codeBlock, globalObject);
+                metadata.m_globalLexicalBindingEpoch = globalObject->globalLexicalBindingEpoch();
+            }
+        } else if (resolvedScope->isGlobalLexicalEnvironment()) {
+            JSGlobalLexicalEnvironment* globalLexicalEnvironment = jsCast<JSGlobalLexicalEnvironment*>(resolvedScope);
+            ConcurrentJSLocker locker(codeBlock->m_lock);
+            metadata.m_resolveType = needsVarInjectionChecks(resolveType) ? GlobalLexicalVarWithVarInjectionChecks : GlobalLexicalVar;
+            metadata.m_globalLexicalEnvironment.set(vm, codeBlock, globalLexicalEnvironment);
+        }
+        break;
+    }
+    default:
+        break;
+    }
+
+    return JSValue::encode(resolvedScope);
+}
+#endif
+
</ins><span class="cx"> JSC_DEFINE_JIT_OPERATION(operationGetFromScope, EncodedJSValue, (JSGlobalObject* globalObject, const Instruction* pc))
</span><span class="cx"> {
</span><span class="cx">     VM& vm = globalObject->vm();
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitJITOperationsh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/JITOperations.h (278028 => 278029)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/JITOperations.h  2021-05-25 17:34:04 UTC (rev 278028)
+++ trunk/Source/JavaScriptCore/jit/JITOperations.h     2021-05-25 18:03:20 UTC (rev 278029)
</span><span class="lines">@@ -285,6 +285,9 @@
</span><span class="cx"> JSC_DECLARE_JIT_OPERATION(operationSwitchCharWithUnknownKeyType, char*, (JSGlobalObject*, EncodedJSValue key, size_t tableIndex, int32_t min));
</span><span class="cx"> JSC_DECLARE_JIT_OPERATION(operationSwitchImmWithUnknownKeyType, char*, (VM*, EncodedJSValue key, size_t tableIndex, int32_t min));
</span><span class="cx"> JSC_DECLARE_JIT_OPERATION(operationSwitchStringWithUnknownKeyType, char*, (JSGlobalObject*, EncodedJSValue key, size_t tableIndex));
</span><ins>+#if ENABLE(EXTRA_CTI_THUNKS)
+JSC_DECLARE_JIT_OPERATION(operationResolveScopeForBaseline, EncodedJSValue, (JSGlobalObject*, const Instruction* bytecodePC));
+#endif
</ins><span class="cx"> JSC_DECLARE_JIT_OPERATION(operationGetFromScope, EncodedJSValue, (JSGlobalObject*, const Instruction* bytecodePC));
</span><span class="cx"> JSC_DECLARE_JIT_OPERATION(operationPutToScope, void, (JSGlobalObject*, const Instruction* bytecodePC));
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitJITPropertyAccesscpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/JITPropertyAccess.cpp (278028 => 278029)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/JITPropertyAccess.cpp    2021-05-25 17:34:04 UTC (rev 278028)
+++ trunk/Source/JavaScriptCore/jit/JITPropertyAccess.cpp       2021-05-25 18:03:20 UTC (rev 278029)
</span><span class="lines">@@ -1589,6 +1589,7 @@
</span><span class="cx">     emitPutVirtualRegister(dst);
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+#if !ENABLE(EXTRA_CTI_THUNKS)
</ins><span class="cx"> void JIT::emit_op_resolve_scope(const Instruction* currentInstruction)
</span><span class="cx"> {
</span><span class="cx">     auto bytecode = currentInstruction->as<OpResolveScope>();
</span><span class="lines">@@ -1692,7 +1693,253 @@
</span><span class="cx">         break;
</span><span class="cx">     }
</span><span class="cx"> }
</span><ins>+#else // ENABLE(EXTRA_CTI_THUNKS)
</ins><span class="cx"> 
</span><ins>+void JIT::emit_op_resolve_scope(const Instruction* currentInstruction)
+{
+    auto bytecode = currentInstruction->as<OpResolveScope>();
+    auto& metadata = bytecode.metadata(m_codeBlock);
+    VirtualRegister dst = bytecode.m_dst;
+    VirtualRegister scope = bytecode.m_scope;
+    ResolveType resolveType = metadata.m_resolveType;
+
+    VM& vm = this->vm();
+    uint32_t bytecodeOffset = m_bytecodeIndex.offset();
+    ASSERT(BytecodeIndex(bytecodeOffset) == m_bytecodeIndex);
+    ASSERT(m_codeBlock->instructionAt(m_bytecodeIndex) == currentInstruction);
+
+    constexpr GPRReg metadataGPR = regT7;
+    constexpr GPRReg scopeGPR = regT6;
+    constexpr GPRReg bytecodeOffsetGPR = regT5;
+
+    if (resolveType == ModuleVar)
+        move(TrustedImmPtr(metadata.m_lexicalEnvironment.get()), regT0);
+    else {
+        ptrdiff_t metadataOffset = m_codeBlock->offsetInMetadataTable(&metadata);
+
+#define RESOLVE_SCOPE_GENERATOR(resolveType) op_resolve_scope_##resolveType##Generator,
+        static const ThunkGenerator generators[] = {
+            FOR_EACH_RESOLVE_TYPE(RESOLVE_SCOPE_GENERATOR)
+        };
+#undef RESOLVE_SCOPE_GENERATOR
+
+        emitGetVirtualRegister(scope, scopeGPR);
+        move(TrustedImmPtr(metadataOffset), metadataGPR);
+        move(TrustedImm32(bytecodeOffset), bytecodeOffsetGPR);
+        emitNakedNearCall(vm.getCTIStub(generators[resolveType]).retaggedCode<NoPtrTag>());
+    }
+
+    emitPutVirtualRegister(dst);
+}
+
+MacroAssemblerCodeRef<JITThunkPtrTag> JIT::generateOpResolveScopeThunk(ResolveType resolveType, const char* thunkName)
+{
+    // The thunk generated by this function can only work with the LLInt / Baseline JIT because
+    // it makes assumptions about the right globalObject being available from CallFrame::codeBlock().
+    // DFG/FTL may inline functions belonging to other globalObjects, which may not match
+    // CallFrame::codeBlock().
+    using Metadata = OpResolveScope::Metadata;
+    constexpr GPRReg metadataGPR = regT7; // incoming
+    constexpr GPRReg scopeGPR = regT6; // incoming
+    constexpr GPRReg bytecodeOffsetGPR = regT5; // incoming - pass thru to slow path.
+    constexpr GPRReg globalObjectGPR = regT4;
+    UNUSED_PARAM(bytecodeOffsetGPR);
+    RELEASE_ASSERT(thunkIsUsedForOpResolveScope(resolveType));
+
+    tagReturnAddress();
+
+    loadPtr(addressFor(CallFrameSlot::codeBlock), regT3);
+    loadPtr(Address(regT3, CodeBlock::offsetOfMetadataTable()), regT3);
+    addPtr(regT3, metadataGPR);
+
+    JumpList slowCase;
+
+    auto emitVarInjectionCheck = [&] (bool needsVarInjectionChecks, GPRReg globalObjectGPR = InvalidGPRReg) {
+        if (!needsVarInjectionChecks)
+            return;
+        if (globalObjectGPR == InvalidGPRReg) {
+            globalObjectGPR = regT4;
+            loadPtr(addressFor(CallFrameSlot::codeBlock), regT3);
+            loadPtr(Address(regT3, CodeBlock::offsetOfGlobalObject()), globalObjectGPR);
+        }
+        loadPtr(Address(globalObjectGPR, OBJECT_OFFSETOF(JSGlobalObject, m_varInjectionWatchpoint)), regT3);
+        slowCase.append(branch8(Equal, Address(regT3, WatchpointSet::offsetOfState()), TrustedImm32(IsInvalidated)));
+    };
+
+    auto emitResolveClosure = [&] (bool needsVarInjectionChecks) {
+        emitVarInjectionCheck(needsVarInjectionChecks);
+        move(scopeGPR, regT0);
+        load32(Address(metadataGPR, OBJECT_OFFSETOF(Metadata, m_localScopeDepth)), regT1);
+
+        Label loop = label();
+        Jump done = branchTest32(Zero, regT1);
+        {
+            loadPtr(Address(regT0, JSScope::offsetOfNext()), regT0);
+            sub32(TrustedImm32(1), regT1);
+            jump().linkTo(loop, this);
+        }
+        done.link(this);
+    };
+
+    auto emitCode = [&] (ResolveType resolveType) {
+        switch (resolveType) {
+        case GlobalProperty:
+        case GlobalPropertyWithVarInjectionChecks: {
+            // JSScope::constantScopeForCodeBlock() loads codeBlock->globalObject().
+            loadPtr(addressFor(CallFrameSlot::codeBlock), regT3);
+            loadPtr(Address(regT3, CodeBlock::offsetOfGlobalObject()), globalObjectGPR);
+            emitVarInjectionCheck(needsVarInjectionChecks(resolveType), globalObjectGPR);
+            load32(Address(metadataGPR, OBJECT_OFFSETOF(Metadata, m_globalLexicalBindingEpoch)), regT1);
+            slowCase.append(branch32(NotEqual, Address(globalObjectGPR, JSGlobalObject::offsetOfGlobalLexicalBindingEpoch()), regT1));
+            move(globalObjectGPR, regT0);
+            break;
+        }
+
+        case GlobalVar:
+        case GlobalVarWithVarInjectionChecks:
+        case GlobalLexicalVar:
+        case GlobalLexicalVarWithVarInjectionChecks: {
+            // JSScope::constantScopeForCodeBlock() loads codeBlock->globalObject() for GlobalVar*,
+            // and codeBlock->globalObject()->globalLexicalEnvironment() for GlobalLexicalVar*.
+            loadPtr(addressFor(CallFrameSlot::codeBlock), regT3);
+            loadPtr(Address(regT3, CodeBlock::offsetOfGlobalObject()), regT0);
+            emitVarInjectionCheck(needsVarInjectionChecks(resolveType), regT0);
+            if (resolveType == GlobalLexicalVar || resolveType == GlobalLexicalVarWithVarInjectionChecks)
+                loadPtr(Address(regT0, JSGlobalObject::offsetOfGlobalLexicalEnvironment()), regT0);
+            break;
+        }
+        case ClosureVar:
+        case ClosureVarWithVarInjectionChecks:
+            emitResolveClosure(needsVarInjectionChecks(resolveType));
+            break;
+        case Dynamic:
+            slowCase.append(jump());
+            break;
+        case LocalClosureVar:
+        case ModuleVar:
+        case UnresolvedProperty:
+        case UnresolvedPropertyWithVarInjectionChecks:
+            RELEASE_ASSERT_NOT_REACHED();
+        }
+    };
+
+    switch (resolveType) {
+    case GlobalProperty:
+    case GlobalPropertyWithVarInjectionChecks: {
+        JumpList skipToEnd;
+        load32(Address(metadataGPR, OBJECT_OFFSETOF(Metadata, m_resolveType)), regT0);
+
+        Jump notGlobalProperty = branch32(NotEqual, regT0, TrustedImm32(resolveType));
+        emitCode(resolveType);
+        skipToEnd.append(jump());
+
+        notGlobalProperty.link(this);
+        emitCode(needsVarInjectionChecks(resolveType) ? GlobalLexicalVarWithVarInjectionChecks : GlobalLexicalVar);
+
+        skipToEnd.link(this);
+        break;
+    }
+    case UnresolvedProperty:
+    case UnresolvedPropertyWithVarInjectionChecks: {
+        JumpList skipToEnd;
+        load32(Address(metadataGPR, OBJECT_OFFSETOF(Metadata, m_resolveType)), regT0);
+
+        Jump notGlobalProperty = branch32(NotEqual, regT0, TrustedImm32(GlobalProperty));
+        emitCode(GlobalProperty);
+        skipToEnd.append(jump());
+        notGlobalProperty.link(this);
+
+        Jump notGlobalPropertyWithVarInjections = branch32(NotEqual, regT0, TrustedImm32(GlobalPropertyWithVarInjectionChecks));
+        emitCode(GlobalPropertyWithVarInjectionChecks);
+        skipToEnd.append(jump());
+        notGlobalPropertyWithVarInjections.link(this);
+
+        Jump notGlobalLexicalVar = branch32(NotEqual, regT0, TrustedImm32(GlobalLexicalVar));
+        emitCode(GlobalLexicalVar);
+        skipToEnd.append(jump());
+        notGlobalLexicalVar.link(this);
+
+        Jump notGlobalLexicalVarWithVarInjections = branch32(NotEqual, regT0, TrustedImm32(GlobalLexicalVarWithVarInjectionChecks));
+        emitCode(GlobalLexicalVarWithVarInjectionChecks);
+        skipToEnd.append(jump());
+        notGlobalLexicalVarWithVarInjections.link(this);
+
+        slowCase.append(jump());
+        skipToEnd.link(this);
+        break;
+    }
+
+    default:
+        emitCode(resolveType);
+        break;
+    }
+
+    ret();
+
+    LinkBuffer patchBuffer(*this, GLOBAL_THUNK_ID, LinkBuffer::Profile::Thunk);
+    auto slowCaseHandler = vm().getCTIStub(slow_op_resolve_scopeGenerator);
+    patchBuffer.link(slowCase, CodeLocationLabel(slowCaseHandler.retaggedCode<NoPtrTag>()));
+    return FINALIZE_CODE(patchBuffer, JITThunkPtrTag, thunkName);
+}
+
+#define DEFINE_RESOLVE_SCOPE_GENERATOR(resolveType) \
+MacroAssemblerCodeRef<JITThunkPtrTag> JIT::op_resolve_scope_##resolveType##Generator(VM& vm) \
+    { \
+        if constexpr (!thunkIsUsedForOpResolveScope(resolveType)) \
+            return { }; \
+        JIT jit(vm); \
+        return jit.generateOpResolveScopeThunk(resolveType, "Baseline: op_resolve_scope_" #resolveType); \
+    }
+FOR_EACH_RESOLVE_TYPE(DEFINE_RESOLVE_SCOPE_GENERATOR)
+#undef DEFINE_RESOLVE_SCOPE_GENERATOR
+
+MacroAssemblerCodeRef<JITThunkPtrTag> JIT::slow_op_resolve_scopeGenerator(VM& vm)
+{
+    // The thunk generated by this function can only work with the LLInt / Baseline JIT because
+    // it makes assumptions about the right globalObject being available from CallFrame::codeBlock().
+    // DFG/FTL may inline functions belonging to other globalObjects, which may not match
+    // CallFrame::codeBlock().
+    JIT jit(vm);
+
+    // The fast path already pushed the return address.
+#if CPU(X86_64)
+    jit.push(X86Registers::ebp);
+#elif CPU(ARM64)
+    jit.pushPair(framePointerRegister, linkRegister);
+#endif
+
+    constexpr GPRReg bytecodeOffsetGPR = regT5;
+    jit.store32(bytecodeOffsetGPR, tagFor(CallFrameSlot::argumentCountIncludingThis));
+
+    constexpr GPRReg codeBlockGPR = argumentGPR3;
+    constexpr GPRReg globalObjectGPR = argumentGPR0;
+    constexpr GPRReg instructionGPR = argumentGPR1;
+
+    jit.loadPtr(addressFor(CallFrameSlot::codeBlock), codeBlockGPR);
+    jit.loadPtr(Address(codeBlockGPR, CodeBlock::offsetOfGlobalObject()), globalObjectGPR);
+    jit.loadPtr(Address(codeBlockGPR, CodeBlock::offsetOfInstructionsRawPointer()), instructionGPR);
+    jit.addPtr(bytecodeOffsetGPR, instructionGPR);
+
+    jit.setupArguments<decltype(operationResolveScopeForBaseline)>(globalObjectGPR, instructionGPR);
+    jit.prepareCallOperation(vm);
+    Call operation = jit.call(OperationPtrTag);
+    Jump exceptionCheck = jit.emitNonPatchableExceptionCheck(vm);
+
+#if CPU(X86_64)
+    jit.pop(X86Registers::ebp);
+#elif CPU(ARM64)
+    jit.popPair(CCallHelpers::framePointerRegister, CCallHelpers::linkRegister);
+#endif
+    jit.ret();
+
+    LinkBuffer patchBuffer(jit, GLOBAL_THUNK_ID, LinkBuffer::Profile::Thunk);
+    patchBuffer.link(operation, FunctionPtr<OperationPtrTag>(operationResolveScopeForBaseline));
+    auto handler = vm.getCTIStub(popThunkStackPreservesAndHandleExceptionGenerator);
+    patchBuffer.link(exceptionCheck, CodeLocationLabel(handler.retaggedCode<NoPtrTag>()));
+    return FINALIZE_CODE(patchBuffer, JITThunkPtrTag, "Baseline: slow_op_resolve_scope");
+}
+#endif // ENABLE(EXTRA_CTI_THUNKS)
+
</ins><span class="cx"> void JIT::emitLoadWithStructureCheck(VirtualRegister scope, Structure** structureSlot)
</span><span class="cx"> {
</span><span class="cx">     loadPtr(structureSlot, regT1);
</span><span class="lines">@@ -1719,6 +1966,7 @@
</span><span class="cx">     loadPtr(Address(regT0, JSLexicalEnvironment::offsetOfVariables() + operand * sizeof(Register)), regT0);
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+#if !ENABLE(EXTRA_CTI_THUNKS)
</ins><span class="cx"> void JIT::emit_op_get_from_scope(const Instruction* currentInstruction)
</span><span class="cx"> {
</span><span class="cx">     auto bytecode = currentInstruction->as<OpGetFromScope>();
</span><span class="lines">@@ -1844,26 +2092,232 @@
</span><span class="cx">     auto bytecode = currentInstruction->as<OpGetFromScope>();
</span><span class="cx">     auto& metadata = bytecode.metadata(m_codeBlock);
</span><span class="cx">     VirtualRegister dst = bytecode.m_dst;
</span><ins>+    callOperationWithProfile(metadata, operationGetFromScope, dst, TrustedImmPtr(m_codeBlock->globalObject()), currentInstruction);
+}
</ins><span class="cx"> 
</span><del>-#if !ENABLE(EXTRA_CTI_THUNKS)
-    callOperationWithProfile(metadata, operationGetFromScope, dst, TrustedImmPtr(m_codeBlock->globalObject()), currentInstruction);
-#else
</del><ins>+#else // ENABLE(EXTRA_CTI_THUNKS)
+
+void JIT::emit_op_get_from_scope(const Instruction* currentInstruction)
+{
+    auto bytecode = currentInstruction->as<OpGetFromScope>();
+    auto& metadata = bytecode.metadata(m_codeBlock);
+    VirtualRegister dst = bytecode.m_dst;
+    VirtualRegister scope = bytecode.m_scope;
+    ResolveType resolveType = metadata.m_getPutInfo.resolveType();
+
</ins><span class="cx">     VM& vm = this->vm();
</span><span class="cx">     uint32_t bytecodeOffset = m_bytecodeIndex.offset();
</span><span class="cx">     ASSERT(BytecodeIndex(bytecodeOffset) == m_bytecodeIndex);
</span><span class="cx">     ASSERT(m_codeBlock->instructionAt(m_bytecodeIndex) == currentInstruction);
</span><span class="cx"> 
</span><del>-    constexpr GPRReg bytecodeOffsetGPR = argumentGPR2;
-    move(TrustedImm32(bytecodeOffset), bytecodeOffsetGPR);
</del><ins>+    constexpr GPRReg metadataGPR = regT7;
+    constexpr GPRReg scopeGPR = regT6;
+    constexpr GPRReg bytecodeOffsetGPR = regT5;
</ins><span class="cx"> 
</span><del>-    emitNakedNearCall(vm.getCTIStub(slow_op_get_from_scopeGenerator).retaggedCode<NoPtrTag>());
</del><ins>+    if (resolveType == GlobalVar) {
+        uintptr_t* operandSlot = reinterpret_cast<uintptr_t*>(&metadata.m_operand);
+        emitGetVarFromPointer(bitwise_cast<JSValue*>(*operandSlot), regT0);
+    } else {
+        ptrdiff_t metadataOffset = m_codeBlock->offsetInMetadataTable(&metadata);
</ins><span class="cx"> 
</span><del>-    emitValueProfilingSite(metadata, returnValueGPR);
-    emitPutVirtualRegister(dst, returnValueGPR);
-#endif // ENABLE(EXTRA_CTI_THUNKS)
</del><ins>+#define GET_FROM_SCOPE_GENERATOR(resolveType) op_get_from_scope_##resolveType##Generator,
+        static const ThunkGenerator generators[] = {
+            FOR_EACH_RESOLVE_TYPE(GET_FROM_SCOPE_GENERATOR)
+        };
+#undef GET_FROM_SCOPE_GENERATOR
+
+        emitGetVirtualRegister(scope, scopeGPR);
+        move(TrustedImmPtr(metadataOffset), metadataGPR);
+        move(TrustedImm32(bytecodeOffset), bytecodeOffsetGPR);
+        emitNakedNearCall(vm.getCTIStub(generators[resolveType]).retaggedCode<NoPtrTag>());
+    }
+    emitPutVirtualRegister(dst);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-#if ENABLE(EXTRA_CTI_THUNKS)
</del><ins>+MacroAssemblerCodeRef<JITThunkPtrTag> JIT::generateOpGetFromScopeThunk(ResolveType resolveType, const char* thunkName)
+{
+    // The thunk generated by this function can only work with the LLInt / Baseline JIT because
+    // it makes assumptions about the right globalObject being available from CallFrame::codeBlock().
+    // DFG/FTL may inline functions belonging to other globalObjects, which may not match
+    // CallFrame::codeBlock().
+    using Metadata = OpGetFromScope::Metadata;
+    constexpr GPRReg metadataGPR = regT7;
+    constexpr GPRReg scopeGPR = regT6;
+    RELEASE_ASSERT(thunkIsUsedForOpGetFromScope(resolveType));
+
+    tagReturnAddress();
+
+    loadPtr(addressFor(CallFrameSlot::codeBlock), regT3);
+    loadPtr(Address(regT3, CodeBlock::offsetOfMetadataTable()), regT3);
+    addPtr(regT3, metadataGPR);
+
+    JumpList slowCase;
+
+    auto emitLoadWithStructureCheck = [&] (GPRReg scopeGPR, int32_t metadataStructureOffset) {
+        loadPtr(Address(metadataGPR, metadataStructureOffset), regT1);
+        move(scopeGPR, regT0);
+        slowCase.append(branchTestPtr(Zero, regT1));
+        load32(Address(regT1, Structure::structureIDOffset()), regT1);
+        slowCase.append(branch32(NotEqual, Address(regT0, JSCell::structureIDOffset()), regT1));
+    };
+
+    auto emitVarInjectionCheck = [&] (bool needsVarInjectionChecks) {
+        if (!needsVarInjectionChecks)
+            return;
+        loadPtr(addressFor(CallFrameSlot::codeBlock), regT3);
+        loadPtr(Address(regT3, CodeBlock::offsetOfGlobalObject()), regT3);
+        loadPtr(Address(regT3, OBJECT_OFFSETOF(JSGlobalObject, m_varInjectionWatchpoint)), regT3);
+        slowCase.append(branch8(Equal, Address(regT3, WatchpointSet::offsetOfState()), TrustedImm32(IsInvalidated)));
+    };
+    
+    auto emitGetVarFromPointer = [&] (int32_t operand, GPRReg reg) {
+        loadPtr(Address(metadataGPR, operand), reg);
+        loadPtr(reg, reg);
+    };
+
+    auto emitGetVarFromIndirectPointer = [&] (int32_t operand, GPRReg reg) {
+        loadPtr(Address(metadataGPR, operand), reg);
+        loadPtr(reg, reg);
+    };
+
+    auto emitGetClosureVar = [&] (GPRReg scopeGPR, GPRReg operandGPR) {
+        static_assert(1 << 3 == sizeof(Register));
+        lshift64(TrustedImm32(3), operandGPR);
+        addPtr(scopeGPR, operandGPR);
+        loadPtr(Address(operandGPR, JSLexicalEnvironment::offsetOfVariables()), regT0);
+    };
+
+    auto emitCode = [&] (ResolveType resolveType, bool indirectLoadForOperand) {
+        switch (resolveType) {
+        case GlobalProperty:
+        case GlobalPropertyWithVarInjectionChecks: {
+            emitLoadWithStructureCheck(scopeGPR, OBJECT_OFFSETOF(Metadata, m_structure)); // Structure check covers var injection since we don't cache structures for anything but the GlobalObject. Additionally, resolve_scope handles checking for the var injection.
+
+            constexpr GPRReg base = regT0;
+            constexpr GPRReg result = regT0;
+            constexpr GPRReg offset = regT1;
+            constexpr GPRReg scratch = regT2;
+
+            jitAssert(scopedLambda<Jump(void)>([&] () -> Jump {
+                loadPtr(addressFor(CallFrameSlot::codeBlock), regT3);
+                loadPtr(Address(regT3, CodeBlock::offsetOfGlobalObject()), regT3);
+                return branchPtr(Equal, base, regT3);
+            }));
+
+            loadPtr(Address(metadataGPR, OBJECT_OFFSETOF(Metadata, m_operand)), offset);
+            if (ASSERT_ENABLED) {
+                Jump isOutOfLine = branch32(GreaterThanOrEqual, offset, TrustedImm32(firstOutOfLineOffset));
+                abortWithReason(JITOffsetIsNotOutOfLine);
+                isOutOfLine.link(this);
+            }
+            loadPtr(Address(base, JSObject::butterflyOffset()), scratch);
+            neg32(offset);
+            signExtend32ToPtr(offset, offset);
+            load64(BaseIndex(scratch, offset, TimesEight, (firstOutOfLineOffset - 2) * sizeof(EncodedJSValue)), result);
+            break;
+        }
+        case GlobalVar:
+        case GlobalVarWithVarInjectionChecks:
+        case GlobalLexicalVar:
+        case GlobalLexicalVarWithVarInjectionChecks:
+            emitVarInjectionCheck(needsVarInjectionChecks(resolveType));
+            if (indirectLoadForOperand)
+                emitGetVarFromIndirectPointer(OBJECT_OFFSETOF(Metadata, m_operand), regT0);
+            else
+                emitGetVarFromPointer(OBJECT_OFFSETOF(Metadata, m_operand), regT0);
+            if (resolveType == GlobalLexicalVar || resolveType == GlobalLexicalVarWithVarInjectionChecks) // TDZ check.
+                slowCase.append(branchIfEmpty(regT0));
+            break;
+        case ClosureVar:
+        case ClosureVarWithVarInjectionChecks:
+            emitVarInjectionCheck(needsVarInjectionChecks(resolveType));
+            loadPtr(Address(metadataGPR, OBJECT_OFFSETOF(Metadata, m_operand)), regT3);
+            emitGetClosureVar(scopeGPR, regT3);
+            break;
+        case Dynamic:
+            slowCase.append(jump());
+            break;
+        case LocalClosureVar:
+        case ModuleVar:
+        case UnresolvedProperty:
+        case UnresolvedPropertyWithVarInjectionChecks:
+            RELEASE_ASSERT_NOT_REACHED();
+        }
+    };
+
+    switch (resolveType) {
+    case GlobalProperty:
+    case GlobalPropertyWithVarInjectionChecks: {
+        JumpList skipToEnd;
+        load32(Address(metadataGPR, OBJECT_OFFSETOF(Metadata, m_getPutInfo)), regT0);
+        and32(TrustedImm32(GetPutInfo::typeBits), regT0); // Load ResolveType into T0
+
+        Jump isNotGlobalProperty = branch32(NotEqual, regT0, TrustedImm32(resolveType));
+        emitCode(resolveType, false);
+        skipToEnd.append(jump());
+
+        isNotGlobalProperty.link(this);
+        emitCode(needsVarInjectionChecks(resolveType) ? GlobalLexicalVarWithVarInjectionChecks : GlobalLexicalVar, true);
+
+        skipToEnd.link(this);
+        break;
+    }
+    case UnresolvedProperty:
+    case UnresolvedPropertyWithVarInjectionChecks: {
+        JumpList skipToEnd;
+        load32(Address(metadataGPR, OBJECT_OFFSETOF(Metadata, m_getPutInfo)), regT0);
+        and32(TrustedImm32(GetPutInfo::typeBits), regT0); // Load ResolveType into T0
+
+        Jump isGlobalProperty = branch32(Equal, regT0, TrustedImm32(GlobalProperty));
+        Jump notGlobalPropertyWithVarInjections = branch32(NotEqual, regT0, TrustedImm32(GlobalPropertyWithVarInjectionChecks));
+        isGlobalProperty.link(this);
+        emitCode(GlobalProperty, false);
+        skipToEnd.append(jump());
+        notGlobalPropertyWithVarInjections.link(this);
+
+        Jump notGlobalLexicalVar = branch32(NotEqual, regT0, TrustedImm32(GlobalLexicalVar));
+        emitCode(GlobalLexicalVar, true);
+        skipToEnd.append(jump());
+        notGlobalLexicalVar.link(this);
+
+        Jump notGlobalLexicalVarWithVarInjections = branch32(NotEqual, regT0, TrustedImm32(GlobalLexicalVarWithVarInjectionChecks));
+        emitCode(GlobalLexicalVarWithVarInjectionChecks, true);
+        skipToEnd.append(jump());
+        notGlobalLexicalVarWithVarInjections.link(this);
+
+        slowCase.append(jump());
+
+        skipToEnd.link(this);
+        break;
+    }
+
+    default:
+        emitCode(resolveType, false);
+        break;
+    }
+
+    static_assert(ValueProfile::numberOfBuckets == 1);
+    store64(regT0, Address(metadataGPR, OBJECT_OFFSETOF(Metadata, m_profile)));
+
+    ret();
+
+    LinkBuffer patchBuffer(*this, GLOBAL_THUNK_ID, LinkBuffer::Profile::Thunk);
+    auto slowCaseHandler = vm().getCTIStub(slow_op_get_from_scopeGenerator);
+    patchBuffer.link(slowCase, CodeLocationLabel(slowCaseHandler.retaggedCode<NoPtrTag>()));
+    return FINALIZE_CODE(patchBuffer, JITThunkPtrTag, thunkName);
+}
+
+#define DEFINE_GET_FROM_SCOPE_GENERATOR(resolveType) \
+MacroAssemblerCodeRef<JITThunkPtrTag> JIT::op_get_from_scope_##resolveType##Generator(VM& vm) \
+    { \
+        if constexpr (!thunkIsUsedForOpGetFromScope(resolveType)) \
+            return { }; \
+        JIT jit(vm); \
+        return jit.generateOpGetFromScopeThunk(resolveType, "Baseline: op_get_from_scope_" #resolveType); \
+    }
+FOR_EACH_RESOLVE_TYPE(DEFINE_GET_FROM_SCOPE_GENERATOR)
+#undef DEFINE_GET_FROM_SCOPE_GENERATOR
+
</ins><span class="cx"> MacroAssemblerCodeRef<JITThunkPtrTag> JIT::slow_op_get_from_scopeGenerator(VM& vm)
</span><span class="cx"> {
</span><span class="cx">     // The thunk generated by this function can only work with the LLInt / Baseline JIT because
</span><span class="lines">@@ -1875,11 +2329,12 @@
</span><span class="cx"> #if CPU(X86_64)
</span><span class="cx">     jit.push(X86Registers::ebp);
</span><span class="cx"> #elif CPU(ARM64)
</span><del>-    jit.tagReturnAddress();
</del><span class="cx">     jit.pushPair(framePointerRegister, linkRegister);
</span><span class="cx"> #endif
</span><span class="cx"> 
</span><del>-    constexpr GPRReg bytecodeOffsetGPR = argumentGPR2;
</del><ins>+    using Metadata = OpGetFromScope::Metadata;
+    constexpr GPRReg metadataGPR = regT7;
+    constexpr GPRReg bytecodeOffsetGPR = regT5;
</ins><span class="cx">     jit.store32(bytecodeOffsetGPR, tagFor(CallFrameSlot::argumentCountIncludingThis));
</span><span class="cx"> 
</span><span class="cx">     constexpr GPRReg codeBlockGPR = argumentGPR3;
</span><span class="lines">@@ -1891,11 +2346,16 @@
</span><span class="cx">     jit.loadPtr(Address(codeBlockGPR, CodeBlock::offsetOfInstructionsRawPointer()), instructionGPR);
</span><span class="cx">     jit.addPtr(bytecodeOffsetGPR, instructionGPR);
</span><span class="cx"> 
</span><ins>+    ASSERT(RegisterSet::calleeSaveRegisters().contains(GPRInfo::numberTagRegister));
+    jit.move(metadataGPR, GPRInfo::numberTagRegister); // Preserve metadata in a callee saved register.
</ins><span class="cx">     jit.setupArguments<decltype(operationGetFromScope)>(globalObjectGPR, instructionGPR);
</span><span class="cx">     jit.prepareCallOperation(vm);
</span><del>-    CCallHelpers::Call operation = jit.call(OperationPtrTag);
-    CCallHelpers::Jump exceptionCheck = jit.emitNonPatchableExceptionCheck(vm);
</del><ins>+    Call operation = jit.call(OperationPtrTag);
+    Jump exceptionCheck = jit.emitNonPatchableExceptionCheck(vm);
</ins><span class="cx"> 
</span><ins>+    jit.store64(regT0, Address(GPRInfo::numberTagRegister, OBJECT_OFFSETOF(Metadata, m_profile)));
+    jit.move(TrustedImm64(JSValue::NumberTag), GPRInfo::numberTagRegister);
+
</ins><span class="cx"> #if CPU(X86_64)
</span><span class="cx">     jit.pop(X86Registers::ebp);
</span><span class="cx"> #elif CPU(ARM64)
</span><span class="lines">@@ -1903,10 +2363,14 @@
</span><span class="cx"> #endif
</span><span class="cx">     jit.ret();
</span><span class="cx"> 
</span><ins>+    exceptionCheck.link(&jit);
+    jit.move(TrustedImm64(JSValue::NumberTag), GPRInfo::numberTagRegister);
+    Jump jumpToHandler = jit.jump();
+
</ins><span class="cx">     LinkBuffer patchBuffer(jit, GLOBAL_THUNK_ID, LinkBuffer::Profile::ExtraCTIThunk);
</span><span class="cx">     patchBuffer.link(operation, FunctionPtr<OperationPtrTag>(operationGetFromScope));
</span><span class="cx">     auto handler = vm.getCTIStub(popThunkStackPreservesAndHandleExceptionGenerator);
</span><del>-    patchBuffer.link(exceptionCheck, CodeLocationLabel(handler.retaggedCode<NoPtrTag>()));
</del><ins>+    patchBuffer.link(jumpToHandler, CodeLocationLabel(handler.retaggedCode<NoPtrTag>()));
</ins><span class="cx">     return FINALIZE_CODE(patchBuffer, JITThunkPtrTag, "Baseline: slow_op_get_from_scope");
</span><span class="cx"> }
</span><span class="cx"> #endif // ENABLE(EXTRA_CTI_THUNKS)
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitThunkGeneratorscpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/ThunkGenerators.cpp (278028 => 278029)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/ThunkGenerators.cpp      2021-05-25 17:34:04 UTC (rev 278028)
+++ trunk/Source/JavaScriptCore/jit/ThunkGenerators.cpp 2021-05-25 18:03:20 UTC (rev 278029)
</span><span class="lines">@@ -91,7 +91,6 @@
</span><span class="cx"> 
</span><span class="cx">     LinkBuffer patchBuffer(jit, GLOBAL_THUNK_ID, LinkBuffer::Profile::ExtraCTIThunk);
</span><span class="cx">     auto handler = vm.getCTIStub(handleExceptionGenerator);
</span><del>-    RELEASE_ASSERT(handler);
</del><span class="cx">     patchBuffer.link(continuation, CodeLocationLabel(handler.retaggedCode<NoPtrTag>()));
</span><span class="cx">     return FINALIZE_CODE(patchBuffer, JITThunkPtrTag, "popThunkStackPreservesAndHandleException");
</span><span class="cx"> }
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeGetPutInfoh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/GetPutInfo.h (278028 => 278029)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/GetPutInfo.h 2021-05-25 17:34:04 UTC (rev 278028)
+++ trunk/Source/JavaScriptCore/runtime/GetPutInfo.h    2021-05-25 18:03:20 UTC (rev 278029)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> /*
</span><del>- * Copyright (C) 2015-2020 Apple Inc. All Rights Reserved.
</del><ins>+ * Copyright (C) 2015-2021 Apple Inc. All Rights Reserved.
</ins><span class="cx">  *
</span><span class="cx">  * Redistribution and use in source and binary forms, with or without
</span><span class="cx">  * modification, are permitted provided that the following conditions
</span><span class="lines">@@ -39,6 +39,21 @@
</span><span class="cx">     DoNotThrowIfNotFound
</span><span class="cx"> };
</span><span class="cx"> 
</span><ins>+#define FOR_EACH_RESOLVE_TYPE(v) \
+    v(GlobalProperty) \
+    v(GlobalVar) \
+    v(GlobalLexicalVar) \
+    v(ClosureVar) \
+    v(LocalClosureVar) \
+    v(ModuleVar) \
+    v(GlobalPropertyWithVarInjectionChecks) \
+    v(GlobalVarWithVarInjectionChecks) \
+    v(GlobalLexicalVarWithVarInjectionChecks) \
+    v(ClosureVarWithVarInjectionChecks) \
+    v(UnresolvedProperty) \
+    v(UnresolvedPropertyWithVarInjectionChecks) \
+    v(Dynamic)
+
</ins><span class="cx"> enum ResolveType : unsigned {
</span><span class="cx">     // Lexical scope guaranteed a certain type of variable access.
</span><span class="cx">     GlobalProperty,
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeJSGlobalObjecth"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/JSGlobalObject.h (278028 => 278029)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/JSGlobalObject.h     2021-05-25 17:34:04 UTC (rev 278028)
+++ trunk/Source/JavaScriptCore/runtime/JSGlobalObject.h        2021-05-25 18:03:20 UTC (rev 278029)
</span><span class="lines">@@ -883,6 +883,8 @@
</span><span class="cx">     static ptrdiff_t regExpGlobalDataOffset() { return OBJECT_OFFSETOF(JSGlobalObject, m_regExpGlobalData); }
</span><span class="cx"> 
</span><span class="cx">     static ptrdiff_t offsetOfVM() { return OBJECT_OFFSETOF(JSGlobalObject, m_vm); }
</span><ins>+    static ptrdiff_t offsetOfGlobalLexicalEnvironment() { return OBJECT_OFFSETOF(JSGlobalObject, m_globalLexicalEnvironment); }
+    static ptrdiff_t offsetOfGlobalLexicalBindingEpoch() { return OBJECT_OFFSETOF(JSGlobalObject, m_globalLexicalBindingEpoch); }
</ins><span class="cx"> 
</span><span class="cx"> #if ENABLE(REMOTE_INSPECTOR)
</span><span class="cx">     Inspector::JSGlobalObjectInspectorController& inspectorController() const { return *m_inspectorController.get(); }
</span></span></pre>
</div>
</div>

</body>
</html>