<!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>[281022] branches/safari-612.1.28-branch</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/281022">281022</a></dd>
<dt>Author</dt> <dd>alancoon@apple.com</dd>
<dt>Date</dt> <dd>2021-08-13 09:50:38 -0700 (Fri, 13 Aug 2021)</dd>
</dl>

<h3>Log Message</h3>
<pre>Revert <a href="http://trac.webkit.org/projects/webkit/changeset/280760">r280760</a>. rdar://problem/81903894</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#branchessafari612128branchJSTestsChangeLog">branches/safari-612.1.28-branch/JSTests/ChangeLog</a></li>
<li><a href="#branchessafari612128branchJSTestsstressforinarraymodejs">branches/safari-612.1.28-branch/JSTests/stress/for-in-array-mode.js</a></li>
<li><a href="#branchessafari612128branchJSTestsstressforinbasereassignedlaterjs">branches/safari-612.1.28-branch/JSTests/stress/for-in-base-reassigned-later.js</a></li>
<li><a href="#branchessafari612128branchJSTestsstressforindeleteduringiterationjs">branches/safari-612.1.28-branch/JSTests/stress/for-in-delete-during-iteration.js</a></li>
<li><a href="#branchessafari612128branchJSTestsstressforintestsjs">branches/safari-612.1.28-branch/JSTests/stress/for-in-tests.js</a></li>
<li><a href="#branchessafari612128branchJSTestsstresshasownpropertystructureforinloopcorrectnessjs">branches/safari-612.1.28-branch/JSTests/stress/has-own-property-structure-for-in-loop-correctness.js</a></li>
<li><a href="#branchessafari612128branchSourceJavaScriptCoreChangeLog">branches/safari-612.1.28-branch/Source/JavaScriptCore/ChangeLog</a></li>
<li><a href="#branchessafari612128branchSourceJavaScriptCoreassemblerMacroAssemblerARM64h">branches/safari-612.1.28-branch/Source/JavaScriptCore/assembler/MacroAssemblerARM64.h</a></li>
<li><a href="#branchessafari612128branchSourceJavaScriptCoreassemblerMacroAssemblerX86Commonh">branches/safari-612.1.28-branch/Source/JavaScriptCore/assembler/MacroAssemblerX86Common.h</a></li>
<li><a href="#branchessafari612128branchSourceJavaScriptCoreassemblerMacroAssemblerX86_64h">branches/safari-612.1.28-branch/Source/JavaScriptCore/assembler/MacroAssemblerX86_64.h</a></li>
<li><a href="#branchessafari612128branchSourceJavaScriptCorebuiltinsBuiltinNamesh">branches/safari-612.1.28-branch/Source/JavaScriptCore/builtins/BuiltinNames.h</a></li>
<li><a href="#branchessafari612128branchSourceJavaScriptCorebytecodeBytecodeListrb">branches/safari-612.1.28-branch/Source/JavaScriptCore/bytecode/BytecodeList.rb</a></li>
<li><a href="#branchessafari612128branchSourceJavaScriptCorebytecodeBytecodeUseDefcpp">branches/safari-612.1.28-branch/Source/JavaScriptCore/bytecode/BytecodeUseDef.cpp</a></li>
<li><a href="#branchessafari612128branchSourceJavaScriptCorebytecodeCodeBlockcpp">branches/safari-612.1.28-branch/Source/JavaScriptCore/bytecode/CodeBlock.cpp</a></li>
<li><a href="#branchessafari612128branchSourceJavaScriptCorebytecodeLinkTimeConstanth">branches/safari-612.1.28-branch/Source/JavaScriptCore/bytecode/LinkTimeConstant.h</a></li>
<li><a href="#branchessafari612128branchSourceJavaScriptCorebytecodeOpcodeh">branches/safari-612.1.28-branch/Source/JavaScriptCore/bytecode/Opcode.h</a></li>
<li><a href="#branchessafari612128branchSourceJavaScriptCorebytecompilerBytecodeGeneratorcpp">branches/safari-612.1.28-branch/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp</a></li>
<li><a href="#branchessafari612128branchSourceJavaScriptCorebytecompilerBytecodeGeneratorh">branches/safari-612.1.28-branch/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h</a></li>
<li><a href="#branchessafari612128branchSourceJavaScriptCorebytecompilerNodesCodegencpp">branches/safari-612.1.28-branch/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp</a></li>
<li><a href="#branchessafari612128branchSourceJavaScriptCoredfgDFGAbstractInterpreterInlinesh">branches/safari-612.1.28-branch/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h</a></li>
<li><a href="#branchessafari612128branchSourceJavaScriptCoredfgDFGArrayModeh">branches/safari-612.1.28-branch/Source/JavaScriptCore/dfg/DFGArrayMode.h</a></li>
<li><a href="#branchessafari612128branchSourceJavaScriptCoredfgDFGBackwardsPropagationPhasecpp">branches/safari-612.1.28-branch/Source/JavaScriptCore/dfg/DFGBackwardsPropagationPhase.cpp</a></li>
<li><a href="#branchessafari612128branchSourceJavaScriptCoredfgDFGByteCodeParsercpp">branches/safari-612.1.28-branch/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp</a></li>
<li><a href="#branchessafari612128branchSourceJavaScriptCoredfgDFGCFAPhasecpp">branches/safari-612.1.28-branch/Source/JavaScriptCore/dfg/DFGCFAPhase.cpp</a></li>
<li><a href="#branchessafari612128branchSourceJavaScriptCoredfgDFGCapabilitiescpp">branches/safari-612.1.28-branch/Source/JavaScriptCore/dfg/DFGCapabilities.cpp</a></li>
<li><a href="#branchessafari612128branchSourceJavaScriptCoredfgDFGClobberizeh">branches/safari-612.1.28-branch/Source/JavaScriptCore/dfg/DFGClobberize.h</a></li>
<li><a href="#branchessafari612128branchSourceJavaScriptCoredfgDFGDoesGCcpp">branches/safari-612.1.28-branch/Source/JavaScriptCore/dfg/DFGDoesGC.cpp</a></li>
<li><a href="#branchessafari612128branchSourceJavaScriptCoredfgDFGFixupPhasecpp">branches/safari-612.1.28-branch/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp</a></li>
<li><a href="#branchessafari612128branchSourceJavaScriptCoredfgDFGGraphcpp">branches/safari-612.1.28-branch/Source/JavaScriptCore/dfg/DFGGraph.cpp</a></li>
<li><a href="#branchessafari612128branchSourceJavaScriptCoredfgDFGIntegerRangeOptimizationPhasecpp">branches/safari-612.1.28-branch/Source/JavaScriptCore/dfg/DFGIntegerRangeOptimizationPhase.cpp</a></li>
<li><a href="#branchessafari612128branchSourceJavaScriptCoredfgDFGMayExitcpp">branches/safari-612.1.28-branch/Source/JavaScriptCore/dfg/DFGMayExit.cpp</a></li>
<li><a href="#branchessafari612128branchSourceJavaScriptCoredfgDFGNodeh">branches/safari-612.1.28-branch/Source/JavaScriptCore/dfg/DFGNode.h</a></li>
<li><a href="#branchessafari612128branchSourceJavaScriptCoredfgDFGNodeTypeh">branches/safari-612.1.28-branch/Source/JavaScriptCore/dfg/DFGNodeType.h</a></li>
<li><a href="#branchessafari612128branchSourceJavaScriptCoredfgDFGOpInfoh">branches/safari-612.1.28-branch/Source/JavaScriptCore/dfg/DFGOpInfo.h</a></li>
<li><a href="#branchessafari612128branchSourceJavaScriptCoredfgDFGOperationscpp">branches/safari-612.1.28-branch/Source/JavaScriptCore/dfg/DFGOperations.cpp</a></li>
<li><a href="#branchessafari612128branchSourceJavaScriptCoredfgDFGOperationsh">branches/safari-612.1.28-branch/Source/JavaScriptCore/dfg/DFGOperations.h</a></li>
<li><a href="#branchessafari612128branchSourceJavaScriptCoredfgDFGPredictionPropagationPhasecpp">branches/safari-612.1.28-branch/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp</a></li>
<li><a href="#branchessafari612128branchSourceJavaScriptCoredfgDFGSSALoweringPhasecpp">branches/safari-612.1.28-branch/Source/JavaScriptCore/dfg/DFGSSALoweringPhase.cpp</a></li>
<li><a href="#branchessafari612128branchSourceJavaScriptCoredfgDFGSafeToExecuteh">branches/safari-612.1.28-branch/Source/JavaScriptCore/dfg/DFGSafeToExecute.h</a></li>
<li><a href="#branchessafari612128branchSourceJavaScriptCoredfgDFGSpeculativeJITcpp">branches/safari-612.1.28-branch/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp</a></li>
<li><a href="#branchessafari612128branchSourceJavaScriptCoredfgDFGSpeculativeJITh">branches/safari-612.1.28-branch/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h</a></li>
<li><a href="#branchessafari612128branchSourceJavaScriptCoredfgDFGSpeculativeJIT32_64cpp">branches/safari-612.1.28-branch/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp</a></li>
<li><a href="#branchessafari612128branchSourceJavaScriptCoredfgDFGSpeculativeJIT64cpp">branches/safari-612.1.28-branch/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp</a></li>
<li><a href="#branchessafari612128branchSourceJavaScriptCoredfgDFGTypeCheckHoistingPhasecpp">branches/safari-612.1.28-branch/Source/JavaScriptCore/dfg/DFGTypeCheckHoistingPhase.cpp</a></li>
<li><a href="#branchessafari612128branchSourceJavaScriptCoreftlFTLAbstractHeapRepositoryh">branches/safari-612.1.28-branch/Source/JavaScriptCore/ftl/FTLAbstractHeapRepository.h</a></li>
<li><a href="#branchessafari612128branchSourceJavaScriptCoreftlFTLCapabilitiescpp">branches/safari-612.1.28-branch/Source/JavaScriptCore/ftl/FTLCapabilities.cpp</a></li>
<li><a href="#branchessafari612128branchSourceJavaScriptCoreftlFTLLowerDFGToB3cpp">branches/safari-612.1.28-branch/Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp</a></li>
<li><a href="#branchessafari612128branchSourceJavaScriptCoreftlFTLOutputh">branches/safari-612.1.28-branch/Source/JavaScriptCore/ftl/FTLOutput.h</a></li>
<li><a href="#branchessafari612128branchSourceJavaScriptCoregeneratorDSLrb">branches/safari-612.1.28-branch/Source/JavaScriptCore/generator/DSL.rb</a></li>
<li><a href="#branchessafari612128branchSourceJavaScriptCoreinterpreterRegisterh">branches/safari-612.1.28-branch/Source/JavaScriptCore/interpreter/Register.h</a></li>
<li><a href="#branchessafari612128branchSourceJavaScriptCoreinterpreterRegisterInlinesh">branches/safari-612.1.28-branch/Source/JavaScriptCore/interpreter/RegisterInlines.h</a></li>
<li><a href="#branchessafari612128branchSourceJavaScriptCorejitAssemblyHelpersh">branches/safari-612.1.28-branch/Source/JavaScriptCore/jit/AssemblyHelpers.h</a></li>
<li><a href="#branchessafari612128branchSourceJavaScriptCorejitJITcpp">branches/safari-612.1.28-branch/Source/JavaScriptCore/jit/JIT.cpp</a></li>
<li><a href="#branchessafari612128branchSourceJavaScriptCorejitJITh">branches/safari-612.1.28-branch/Source/JavaScriptCore/jit/JIT.h</a></li>
<li><a href="#branchessafari612128branchSourceJavaScriptCorejitJITOpcodescpp">branches/safari-612.1.28-branch/Source/JavaScriptCore/jit/JITOpcodes.cpp</a></li>
<li><a href="#branchessafari612128branchSourceJavaScriptCorejitJITOpcodes32_64cpp">branches/safari-612.1.28-branch/Source/JavaScriptCore/jit/JITOpcodes32_64.cpp</a></li>
<li><a href="#branchessafari612128branchSourceJavaScriptCorejitJITPropertyAccesscpp">branches/safari-612.1.28-branch/Source/JavaScriptCore/jit/JITPropertyAccess.cpp</a></li>
<li><a href="#branchessafari612128branchSourceJavaScriptCorejitJITPropertyAccess32_64cpp">branches/safari-612.1.28-branch/Source/JavaScriptCore/jit/JITPropertyAccess32_64.cpp</a></li>
<li><a href="#branchessafari612128branchSourceJavaScriptCorellintLowLevelInterpreterasm">branches/safari-612.1.28-branch/Source/JavaScriptCore/llint/LowLevelInterpreter.asm</a></li>
<li><a href="#branchessafari612128branchSourceJavaScriptCorellintLowLevelInterpreter64asm">branches/safari-612.1.28-branch/Source/JavaScriptCore/llint/LowLevelInterpreter64.asm</a></li>
<li><a href="#branchessafari612128branchSourceJavaScriptCoreruntimeCommonSlowPathscpp">branches/safari-612.1.28-branch/Source/JavaScriptCore/runtime/CommonSlowPaths.cpp</a></li>
<li><a href="#branchessafari612128branchSourceJavaScriptCoreruntimeCommonSlowPathsh">branches/safari-612.1.28-branch/Source/JavaScriptCore/runtime/CommonSlowPaths.h</a></li>
<li><a href="#branchessafari612128branchSourceJavaScriptCoreruntimeFileBasedFuzzerAgentcpp">branches/safari-612.1.28-branch/Source/JavaScriptCore/runtime/FileBasedFuzzerAgent.cpp</a></li>
<li><a href="#branchessafari612128branchSourceJavaScriptCoreruntimeFileBasedFuzzerAgentBasecpp">branches/safari-612.1.28-branch/Source/JavaScriptCore/runtime/FileBasedFuzzerAgentBase.cpp</a></li>
<li><a href="#branchessafari612128branchSourceJavaScriptCoreruntimeJSGlobalObjectcpp">branches/safari-612.1.28-branch/Source/JavaScriptCore/runtime/JSGlobalObject.cpp</a></li>
<li><a href="#branchessafari612128branchSourceJavaScriptCoreruntimeJSPropertyNameEnumeratorcpp">branches/safari-612.1.28-branch/Source/JavaScriptCore/runtime/JSPropertyNameEnumerator.cpp</a></li>
<li><a href="#branchessafari612128branchSourceJavaScriptCoreruntimeJSPropertyNameEnumeratorh">branches/safari-612.1.28-branch/Source/JavaScriptCore/runtime/JSPropertyNameEnumerator.h</a></li>
<li><a href="#branchessafari612128branchSourceJavaScriptCoreruntimePredictionFileCreatingFuzzerAgentcpp">branches/safari-612.1.28-branch/Source/JavaScriptCore/runtime/PredictionFileCreatingFuzzerAgent.cpp</a></li>
</ul>

<h3>Removed Paths</h3>
<ul>
<li><a href="#branchessafari612128branchJSTestsmicrobenchmarksforindoublearraywithownnamedjs">branches/safari-612.1.28-branch/JSTests/microbenchmarks/for-in-double-array-with-own-named.js</a></li>
<li><a href="#branchessafari612128branchJSTestsmicrobenchmarksforindoublearrayjs">branches/safari-612.1.28-branch/JSTests/microbenchmarks/for-in-double-array.js</a></li>
<li><a href="#branchessafari612128branchJSTestsmicrobenchmarksforingettersjs">branches/safari-612.1.28-branch/JSTests/microbenchmarks/for-in-getters.js</a></li>
<li><a href="#branchessafari612128branchJSTestsmicrobenchmarksforinint32arraywithownnamedjs">branches/safari-612.1.28-branch/JSTests/microbenchmarks/for-in-int32-array-with-own-named.js</a></li>
<li><a href="#branchessafari612128branchJSTestsmicrobenchmarksforinint32arrayjs">branches/safari-612.1.28-branch/JSTests/microbenchmarks/for-in-int32-array.js</a></li>
<li><a href="#branchessafari612128branchJSTestsmicrobenchmarksforinint32objectwithownnamedandgettersjs">branches/safari-612.1.28-branch/JSTests/microbenchmarks/for-in-int32-object-with-own-named-and-getters.js</a></li>
<li><a href="#branchessafari612128branchJSTestsmicrobenchmarksforinint32objectwithownnamedjs">branches/safari-612.1.28-branch/JSTests/microbenchmarks/for-in-int32-object-with-own-named.js</a></li>
<li><a href="#branchessafari612128branchJSTestsmicrobenchmarksforinobjectwithownnamedjs">branches/safari-612.1.28-branch/JSTests/microbenchmarks/for-in-object-with-own-named.js</a></li>
<li><a href="#branchessafari612128branchJSTestsmicrobenchmarksforinstringarrayjs">branches/safari-612.1.28-branch/JSTests/microbenchmarks/for-in-string-array.js</a></li>
<li><a href="#branchessafari612128branchJSTestsmicrobenchmarksforofiteratearraymapsetjs">branches/safari-612.1.28-branch/JSTests/microbenchmarks/for-of-iterate-array-map-set.js</a></li>
<li><a href="#branchessafari612128branchJSTestsstressforinprimitiveindexonprototypejs">branches/safari-612.1.28-branch/JSTests/stress/for-in-primitive-index-on-prototype.js</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="branchessafari612128branchJSTestsChangeLog"></a>
<div class="modfile"><h4>Modified: branches/safari-612.1.28-branch/JSTests/ChangeLog (281021 => 281022)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-612.1.28-branch/JSTests/ChangeLog        2021-08-13 16:39:44 UTC (rev 281021)
+++ branches/safari-612.1.28-branch/JSTests/ChangeLog   2021-08-13 16:50:38 UTC (rev 281022)
</span><span class="lines">@@ -1,3 +1,7 @@
</span><ins>+2021-08-13  Alan Coon  <alancoon@apple.com>
+
+        Revert r280760. rdar://problem/81903894
+
</ins><span class="cx"> 2021-08-11  Yusuke Suzuki  <ysuzuki@apple.com>
</span><span class="cx"> 
</span><span class="cx">         WTFCrash in JSC::Lexer<char16_t>::append8
</span></span></pre></div>
<a id="branchessafari612128branchJSTestsmicrobenchmarksforindoublearraywithownnamedjs"></a>
<div class="delfile"><h4>Deleted: branches/safari-612.1.28-branch/JSTests/microbenchmarks/for-in-double-array-with-own-named.js (281021 => 281022)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-612.1.28-branch/JSTests/microbenchmarks/for-in-double-array-with-own-named.js    2021-08-13 16:39:44 UTC (rev 281021)
+++ branches/safari-612.1.28-branch/JSTests/microbenchmarks/for-in-double-array-with-own-named.js       2021-08-13 16:50:38 UTC (rev 281022)
</span><span class="lines">@@ -1,14 +0,0 @@
</span><del>-function test(object) {
-    sum = 0;
-    for (var i in object)
-        sum += object[i];
-    return sum;
-}
-noInline(test);
-
-for (let i = 0; i < 1e5; ++i) {
-    var o = Array(100).fill(1.123214231);
-    o.a = 0;
-    o.b = "surprise string";
-    test(o);
-}
</del></span></pre></div>
<a id="branchessafari612128branchJSTestsmicrobenchmarksforindoublearrayjs"></a>
<div class="delfile"><h4>Deleted: branches/safari-612.1.28-branch/JSTests/microbenchmarks/for-in-double-array.js (281021 => 281022)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-612.1.28-branch/JSTests/microbenchmarks/for-in-double-array.js   2021-08-13 16:39:44 UTC (rev 281021)
+++ branches/safari-612.1.28-branch/JSTests/microbenchmarks/for-in-double-array.js      2021-08-13 16:50:38 UTC (rev 281022)
</span><span class="lines">@@ -1,10 +0,0 @@
</span><del>-function test(object) {
-    sum = 0;
-    for (var i in object)
-        sum += object[i];
-    return sum;
-}
-noInline(test);
-
-for (let i = 0; i < 1e5; ++i)
-    test(Array(100).fill(1.1231241));
</del></span></pre></div>
<a id="branchessafari612128branchJSTestsmicrobenchmarksforingettersjs"></a>
<div class="delfile"><h4>Deleted: branches/safari-612.1.28-branch/JSTests/microbenchmarks/for-in-getters.js (281021 => 281022)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-612.1.28-branch/JSTests/microbenchmarks/for-in-getters.js        2021-08-13 16:39:44 UTC (rev 281021)
+++ branches/safari-612.1.28-branch/JSTests/microbenchmarks/for-in-getters.js   2021-08-13 16:50:38 UTC (rev 281022)
</span><span class="lines">@@ -1,15 +0,0 @@
</span><del>-function test(object) {
-    sum = 0;
-    for (var i in object)
-        sum += object[i];
-    return sum;
-}
-noInline(test);
-
-let o = { };
-Object.defineProperty(o, "protoValue", { get() { return "string"; }, enumerable: true });
-Object.defineProperty(o, "protoValue2", { get() { return "string1"; }, enumerable: true });
-Object.defineProperty(o, "protoValue3", { get() { return "string2"; }, enumerable: true });
-
-for (let i = 0; i < 1e5; ++i)
-    test(o);
</del></span></pre></div>
<a id="branchessafari612128branchJSTestsmicrobenchmarksforinint32arraywithownnamedjs"></a>
<div class="delfile"><h4>Deleted: branches/safari-612.1.28-branch/JSTests/microbenchmarks/for-in-int32-array-with-own-named.js (281021 => 281022)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-612.1.28-branch/JSTests/microbenchmarks/for-in-int32-array-with-own-named.js     2021-08-13 16:39:44 UTC (rev 281021)
+++ branches/safari-612.1.28-branch/JSTests/microbenchmarks/for-in-int32-array-with-own-named.js        2021-08-13 16:50:38 UTC (rev 281022)
</span><span class="lines">@@ -1,14 +0,0 @@
</span><del>-function test(object) {
-    sum = 0;
-    for (var i in object)
-        sum += object[i];
-    return sum;
-}
-noInline(test);
-
-for (let i = 0; i < 1e5; ++i) {
-    var o = Array(100).fill(1);
-    o.a = 0;
-    o.b = 2;
-    test(o);
-}
</del></span></pre></div>
<a id="branchessafari612128branchJSTestsmicrobenchmarksforinint32arrayjs"></a>
<div class="delfile"><h4>Deleted: branches/safari-612.1.28-branch/JSTests/microbenchmarks/for-in-int32-array.js (281021 => 281022)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-612.1.28-branch/JSTests/microbenchmarks/for-in-int32-array.js    2021-08-13 16:39:44 UTC (rev 281021)
+++ branches/safari-612.1.28-branch/JSTests/microbenchmarks/for-in-int32-array.js       2021-08-13 16:50:38 UTC (rev 281022)
</span><span class="lines">@@ -1,15 +0,0 @@
</span><del>-
-var count = 0;
-function test(object) {
-    sum = 0;
-    for (var i in object)
-        sum += object[i];
-    return sum;
-}
-noInline(test);
-
-
-var array = new Array(100);
-array.fill(1);
-for (let i = 0; i < 1e5; ++i)
-    test(array);
</del></span></pre></div>
<a id="branchessafari612128branchJSTestsmicrobenchmarksforinint32objectwithownnamedandgettersjs"></a>
<div class="delfile"><h4>Deleted: branches/safari-612.1.28-branch/JSTests/microbenchmarks/for-in-int32-object-with-own-named-and-getters.js (281021 => 281022)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-612.1.28-branch/JSTests/microbenchmarks/for-in-int32-object-with-own-named-and-getters.js        2021-08-13 16:39:44 UTC (rev 281021)
+++ branches/safari-612.1.28-branch/JSTests/microbenchmarks/for-in-int32-object-with-own-named-and-getters.js   2021-08-13 16:50:38 UTC (rev 281022)
</span><span class="lines">@@ -1,15 +0,0 @@
</span><del>-function test(object) {
-    sum = 0;
-    for (var i in object)
-        sum += object[i];
-    return sum;
-}
-noInline(test);
-
-Object.defineProperty(Object.prototype, "protoValue", { get() { return "string"; }, enumerable: true });
-var o = { length: 100 }
-Array.prototype.fill.call(o, 1);
-o.a = 0;
-o.b = 2;
-for (let i = 0; i < 1e5; ++i)
-    test(o);
</del></span></pre></div>
<a id="branchessafari612128branchJSTestsmicrobenchmarksforinint32objectwithownnamedjs"></a>
<div class="delfile"><h4>Deleted: branches/safari-612.1.28-branch/JSTests/microbenchmarks/for-in-int32-object-with-own-named.js (281021 => 281022)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-612.1.28-branch/JSTests/microbenchmarks/for-in-int32-object-with-own-named.js    2021-08-13 16:39:44 UTC (rev 281021)
+++ branches/safari-612.1.28-branch/JSTests/microbenchmarks/for-in-int32-object-with-own-named.js       2021-08-13 16:50:38 UTC (rev 281022)
</span><span class="lines">@@ -1,17 +0,0 @@
</span><del>-function test(object) {
-    sum = 0;
-    for (var i in object) {
-        var v = object[i];
-        sum += v;
-    }
-    return sum;
-}
-noInline(test);
-
-for (let i = 0; i < 1e5; ++i) {
-    var o = { length: 100 };
-    Array.prototype.fill.call(o, 1);
-    o.a = 0;
-    o.b = 2;
-    test(o);
-}
</del></span></pre></div>
<a id="branchessafari612128branchJSTestsmicrobenchmarksforinobjectwithownnamedjs"></a>
<div class="delfile"><h4>Deleted: branches/safari-612.1.28-branch/JSTests/microbenchmarks/for-in-object-with-own-named.js (281021 => 281022)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-612.1.28-branch/JSTests/microbenchmarks/for-in-object-with-own-named.js  2021-08-13 16:39:44 UTC (rev 281021)
+++ branches/safari-612.1.28-branch/JSTests/microbenchmarks/for-in-object-with-own-named.js     2021-08-13 16:50:38 UTC (rev 281022)
</span><span class="lines">@@ -1,17 +0,0 @@
</span><del>-function sum(o) {
-    let sum = 0;
-    for (let p in o)
-        sum += o[p];
-    return sum;
-}
-
-function opaqueSet(o) {
-    o.z = 3;
-}
-
-let object = { x: 1, y: 2 };
-opaqueSet(object);
-for (let i = 0; i < 1e5; ++i) {
-    if (sum(object) !== 6)
-        throw new Error("bad sum");
-}
</del></span></pre></div>
<a id="branchessafari612128branchJSTestsmicrobenchmarksforinstringarrayjs"></a>
<div class="delfile"><h4>Deleted: branches/safari-612.1.28-branch/JSTests/microbenchmarks/for-in-string-array.js (281021 => 281022)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-612.1.28-branch/JSTests/microbenchmarks/for-in-string-array.js   2021-08-13 16:39:44 UTC (rev 281021)
+++ branches/safari-612.1.28-branch/JSTests/microbenchmarks/for-in-string-array.js      2021-08-13 16:50:38 UTC (rev 281022)
</span><span class="lines">@@ -1,10 +0,0 @@
</span><del>-function test(object) {
-    sum = "";
-    for (var i in object)
-        sum += object[i];
-    return sum;
-}
-noInline(test);
-
-for (let i = 0; i < 1e5; ++i)
-    test(Array(100).fill("a"));
</del></span></pre></div>
<a id="branchessafari612128branchJSTestsmicrobenchmarksforofiteratearraymapsetjs"></a>
<div class="delfile"><h4>Deleted: branches/safari-612.1.28-branch/JSTests/microbenchmarks/for-of-iterate-array-map-set.js (281021 => 281022)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-612.1.28-branch/JSTests/microbenchmarks/for-of-iterate-array-map-set.js  2021-08-13 16:39:44 UTC (rev 281021)
+++ branches/safari-612.1.28-branch/JSTests/microbenchmarks/for-of-iterate-array-map-set.js     2021-08-13 16:50:38 UTC (rev 281022)
</span><span class="lines">@@ -1,26 +0,0 @@
</span><del>-function sum(obj) {
-    let result = 0;
-    for (let x of obj) {
-        if (typeof x == "number")
-            result += x;
-        else
-            result += x[0];
-    }
-    return result;
-}
-noInline(sum);
-
-let array = [1,2,3,4,5];
-let set = new Set(array);
-let map = new Map(array.map(x => [x, x]));
-let generator = function* (array) {
-    for (let i = 0; i < array.length; ++i)
-        yield array[i];
-}
-
-for (let i = 0; i < 1e5; ++i) {
-    if (sum(set) !== 15)
-        throw new Error();
-    if (sum(generator(array)) !== 15)
-        throw new Error();
-}
</del></span></pre></div>
<a id="branchessafari612128branchJSTestsstressforinarraymodejs"></a>
<div class="modfile"><h4>Modified: branches/safari-612.1.28-branch/JSTests/stress/for-in-array-mode.js (281021 => 281022)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-612.1.28-branch/JSTests/stress/for-in-array-mode.js      2021-08-13 16:39:44 UTC (rev 281021)
+++ branches/safari-612.1.28-branch/JSTests/stress/for-in-array-mode.js 2021-08-13 16:50:38 UTC (rev 281022)
</span><span class="lines">@@ -26,9 +26,8 @@
</span><span class="cx"> var funcArgAndBodyStr =
</span><span class="cx"> "(arr) {" + "\n" +
</span><span class="cx"> "    var sum = 0;" + "\n" +
</span><del>-"    for (var i in arr) {" + "\n" +
</del><ins>+"    for (var i in arr)" + "\n" +
</ins><span class="cx"> "        sum += arr[i];" + "\n" +
</span><del>-"    } " +
</del><span class="cx"> "    return sum;" + "\n" +
</span><span class="cx"> "}";
</span><span class="cx"> 
</span><span class="lines">@@ -76,7 +75,6 @@
</span><span class="cx"> 
</span><span class="cx">         if ((actual != expected) && (actual != previousResult)) {
</span><span class="cx">             print("FAIL: " + name + ": expected: " + expected + ", actual: " + actual + ", starting @ loop iteration " + i);
</span><del>-            $vm.breakpoint();
</del><span class="cx">             previousResult = actual;
</span><span class="cx">             failed = true;
</span><span class="cx">             numberOfFailures++;
</span></span></pre></div>
<a id="branchessafari612128branchJSTestsstressforinbasereassignedlaterjs"></a>
<div class="modfile"><h4>Modified: branches/safari-612.1.28-branch/JSTests/stress/for-in-base-reassigned-later.js (281021 => 281022)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-612.1.28-branch/JSTests/stress/for-in-base-reassigned-later.js   2021-08-13 16:39:44 UTC (rev 281021)
+++ branches/safari-612.1.28-branch/JSTests/stress/for-in-base-reassigned-later.js      2021-08-13 16:50:38 UTC (rev 281022)
</span><span class="lines">@@ -14,5 +14,5 @@
</span><span class="cx"> for (var i = 0; i < 10000; ++i) {
</span><span class="cx">     var result = foo({0:0, 1:1, a:2, b:3});
</span><span class="cx">     if (result != 7)
</span><del>-        throw new Error("bad result: " + result);
</del><ins>+        throw "Error: bad result: " + result;
</ins><span class="cx"> }
</span></span></pre></div>
<a id="branchessafari612128branchJSTestsstressforindeleteduringiterationjs"></a>
<div class="modfile"><h4>Modified: branches/safari-612.1.28-branch/JSTests/stress/for-in-delete-during-iteration.js (281021 => 281022)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-612.1.28-branch/JSTests/stress/for-in-delete-during-iteration.js 2021-08-13 16:39:44 UTC (rev 281021)
+++ branches/safari-612.1.28-branch/JSTests/stress/for-in-delete-during-iteration.js    2021-08-13 16:50:38 UTC (rev 281022)
</span><span class="lines">@@ -12,9 +12,8 @@
</span><span class="cx">     };
</span><span class="cx">     noInline(foo);
</span><span class="cx">     for (var i = 0; i < 10000; ++i) {
</span><del>-        var result = foo();
-        if (result !== "1235")
-            throw new Error("bad result got: " + result);
</del><ins>+        if (foo() !== "1235")
+            throw new Error("bad result");
</ins><span class="cx">     }
</span><span class="cx">     foo(null);
</span><span class="cx"> })();
</span><span class="lines">@@ -37,9 +36,8 @@
</span><span class="cx">     };
</span><span class="cx">     noInline(foo);
</span><span class="cx">     for (var i = 0; i < 10000; ++i) {
</span><del>-        var result = foo();
-        if (result !== "xz")
-            throw new Error("bad result: " + result);
</del><ins>+        if (foo() !== "xz")
+            throw new Error("bad result");
</ins><span class="cx">     }
</span><span class="cx"> })();
</span><span class="cx"> (function() {
</span></span></pre></div>
<a id="branchessafari612128branchJSTestsstressforinprimitiveindexonprototypejs"></a>
<div class="delfile"><h4>Deleted: branches/safari-612.1.28-branch/JSTests/stress/for-in-primitive-index-on-prototype.js (281021 => 281022)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-612.1.28-branch/JSTests/stress/for-in-primitive-index-on-prototype.js    2021-08-13 16:39:44 UTC (rev 281021)
+++ branches/safari-612.1.28-branch/JSTests/stress/for-in-primitive-index-on-prototype.js       2021-08-13 16:50:38 UTC (rev 281022)
</span><span class="lines">@@ -1,23 +0,0 @@
</span><del>-function test(v) {
-    let sum = 0;
-    for (var p in v)
-        sum += v[p];
-    return sum;
-}
-
-Number.prototype[2] = 4;
-for (let i = 0; i < 1e5; ++i) {
-    if (test(0) !== 4)
-        throw new Error();
-}
-
-String.prototype[2] = 5;
-for (let i = 0; i < 1e5; ++i) {
-    var result = test("");
-    if (result !== 5)
-        throw new Error();
-
-    result = test("a");
-    if (result !== "0a5")
-        throw new Error();
-}
</del></span></pre></div>
<a id="branchessafari612128branchJSTestsstressforintestsjs"></a>
<div class="modfile"><h4>Modified: branches/safari-612.1.28-branch/JSTests/stress/for-in-tests.js (281021 => 281022)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-612.1.28-branch/JSTests/stress/for-in-tests.js   2021-08-13 16:39:44 UTC (rev 281021)
+++ branches/safari-612.1.28-branch/JSTests/stress/for-in-tests.js      2021-08-13 16:50:38 UTC (rev 281022)
</span><span class="lines">@@ -105,7 +105,6 @@
</span><span class="cx">             throw new Error("bad result");
</span><span class="cx">     }
</span><span class="cx"> })();
</span><del>-
</del><span class="cx"> (function() {
</span><span class="cx">     var foo = function(a, b) {
</span><span class="cx">         for (var p in b) {
</span></span></pre></div>
<a id="branchessafari612128branchJSTestsstresshasownpropertystructureforinloopcorrectnessjs"></a>
<div class="modfile"><h4>Modified: branches/safari-612.1.28-branch/JSTests/stress/has-own-property-structure-for-in-loop-correctness.js (281021 => 281022)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-612.1.28-branch/JSTests/stress/has-own-property-structure-for-in-loop-correctness.js     2021-08-13 16:39:44 UTC (rev 281021)
+++ branches/safari-612.1.28-branch/JSTests/stress/has-own-property-structure-for-in-loop-correctness.js        2021-08-13 16:50:38 UTC (rev 281022)
</span><span class="lines">@@ -132,10 +132,7 @@
</span><span class="cx">     o.__proto__ = p;
</span><span class="cx"> 
</span><span class="cx">     for (let i = 0; i < 1000; ++i) {
</span><del>-        var c = count(o);
-        if (c)
-            print(c);
-        assert(c === 0);
</del><ins>+        assert(count(o) === 0);
</ins><span class="cx">     }
</span><span class="cx"> }
</span><span class="cx"> test5();
</span></span></pre></div>
<a id="branchessafari612128branchSourceJavaScriptCoreChangeLog"></a>
<div class="modfile"><h4>Modified: branches/safari-612.1.28-branch/Source/JavaScriptCore/ChangeLog (281021 => 281022)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-612.1.28-branch/Source/JavaScriptCore/ChangeLog  2021-08-13 16:39:44 UTC (rev 281021)
+++ branches/safari-612.1.28-branch/Source/JavaScriptCore/ChangeLog     2021-08-13 16:50:38 UTC (rev 281022)
</span><span class="lines">@@ -1,3 +1,7 @@
</span><ins>+2021-08-13  Alan Coon  <alancoon@apple.com>
+
+        Revert r280760. rdar://problem/81903894
+
</ins><span class="cx"> 2021-08-11  Yusuke Suzuki  <ysuzuki@apple.com>
</span><span class="cx"> 
</span><span class="cx">         WTFCrash in JSC::Lexer<char16_t>::append8
</span></span></pre></div>
<a id="branchessafari612128branchSourceJavaScriptCoreassemblerMacroAssemblerARM64h"></a>
<div class="modfile"><h4>Modified: branches/safari-612.1.28-branch/Source/JavaScriptCore/assembler/MacroAssemblerARM64.h (281021 => 281022)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-612.1.28-branch/Source/JavaScriptCore/assembler/MacroAssemblerARM64.h    2021-08-13 16:39:44 UTC (rev 281021)
+++ branches/safari-612.1.28-branch/Source/JavaScriptCore/assembler/MacroAssemblerARM64.h       2021-08-13 16:50:38 UTC (rev 281022)
</span><span class="lines">@@ -1069,13 +1069,6 @@
</span><span class="cx">         store32(dataTempRegister, address);
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    void or8(RegisterID src, AbsoluteAddress address)
-    {
-        load8(address.m_ptr, getCachedDataTempRegisterIDAndInvalidate());
-        or32(src, dataTempRegister, dataTempRegister);
-        store8(dataTempRegister, address.m_ptr);
-    }
-
</del><span class="cx">     void or8(TrustedImm32 imm, AbsoluteAddress address)
</span><span class="cx">     {
</span><span class="cx">         LogicalImmediate logicalImm = LogicalImmediate::create32(imm.m_value);
</span></span></pre></div>
<a id="branchessafari612128branchSourceJavaScriptCoreassemblerMacroAssemblerX86Commonh"></a>
<div class="modfile"><h4>Modified: branches/safari-612.1.28-branch/Source/JavaScriptCore/assembler/MacroAssemblerX86Common.h (281021 => 281022)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-612.1.28-branch/Source/JavaScriptCore/assembler/MacroAssemblerX86Common.h        2021-08-13 16:39:44 UTC (rev 281021)
+++ branches/safari-612.1.28-branch/Source/JavaScriptCore/assembler/MacroAssemblerX86Common.h   2021-08-13 16:50:38 UTC (rev 281022)
</span><span class="lines">@@ -625,12 +625,6 @@
</span><span class="cx">         m_assembler.orb_rm(src, dest.offset, dest.base, dest.index, dest.scale);
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    void or8(RegisterID src, AbsoluteAddress address)
-    {
-        move(TrustedImmPtr(address.m_ptr), scratchRegister());
-        or8(src, Address(scratchRegister()));
-    }
-
</del><span class="cx">     void or32(Address src, RegisterID dest)
</span><span class="cx">     {
</span><span class="cx">         m_assembler.orl_mr(src.offset, src.base, dest);
</span><span class="lines">@@ -671,12 +665,6 @@
</span><span class="cx">         m_assembler.orb_im(static_cast<int8_t>(imm.m_value), address.offset, address.base, address.index, address.scale);
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    void or8(TrustedImm32 imm, AbsoluteAddress address)
-    {
-        move(TrustedImmPtr(address.m_ptr), scratchRegister());
-        or8(imm, Address(scratchRegister()));
-    }
-
</del><span class="cx">     void or32(RegisterID op1, RegisterID op2, RegisterID dest)
</span><span class="cx">     {
</span><span class="cx">         if (op1 == op2)
</span></span></pre></div>
<a id="branchessafari612128branchSourceJavaScriptCoreassemblerMacroAssemblerX86_64h"></a>
<div class="modfile"><h4>Modified: branches/safari-612.1.28-branch/Source/JavaScriptCore/assembler/MacroAssemblerX86_64.h (281021 => 281022)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-612.1.28-branch/Source/JavaScriptCore/assembler/MacroAssemblerX86_64.h   2021-08-13 16:39:44 UTC (rev 281021)
+++ branches/safari-612.1.28-branch/Source/JavaScriptCore/assembler/MacroAssemblerX86_64.h      2021-08-13 16:50:38 UTC (rev 281022)
</span><span class="lines">@@ -97,6 +97,12 @@
</span><span class="cx">         or16(imm, Address(scratchRegister()));
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    void or8(TrustedImm32 imm, AbsoluteAddress address)
+    {
+        move(TrustedImmPtr(address.m_ptr), scratchRegister());
+        or8(imm, Address(scratchRegister()));
+    }
+
</ins><span class="cx">     void sub32(TrustedImm32 imm, AbsoluteAddress address)
</span><span class="cx">     {
</span><span class="cx">         move(TrustedImmPtr(address.m_ptr), scratchRegister());
</span><span class="lines">@@ -581,12 +587,6 @@
</span><span class="cx">         }
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    void rshift64(RegisterID src, TrustedImm32 imm, RegisterID dest)
-    {
-        move(src, dest);
-        rshift64(imm, dest);
-    }
-
</del><span class="cx">     void urshift64(TrustedImm32 imm, RegisterID dest)
</span><span class="cx">     {
</span><span class="cx">         m_assembler.shrq_i8r(imm.m_value, dest);
</span></span></pre></div>
<a id="branchessafari612128branchSourceJavaScriptCorebuiltinsBuiltinNamesh"></a>
<div class="modfile"><h4>Modified: branches/safari-612.1.28-branch/Source/JavaScriptCore/builtins/BuiltinNames.h (281021 => 281022)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-612.1.28-branch/Source/JavaScriptCore/builtins/BuiltinNames.h    2021-08-13 16:39:44 UTC (rev 281021)
+++ branches/safari-612.1.28-branch/Source/JavaScriptCore/builtins/BuiltinNames.h       2021-08-13 16:50:38 UTC (rev 281022)
</span><span class="lines">@@ -181,8 +181,7 @@
</span><span class="cx">     macro(hasOwnPropertyFunction) \
</span><span class="cx">     macro(createPrivateSymbol) \
</span><span class="cx">     macro(entries) \
</span><del>-    macro(outOfLineReactionCounts) \
-    macro(emptyPropertyNameEnumerator)
</del><ins>+    macro(outOfLineReactionCounts)
</ins><span class="cx"> 
</span><span class="cx"> 
</span><span class="cx"> namespace Symbols {
</span></span></pre></div>
<a id="branchessafari612128branchSourceJavaScriptCorebytecodeBytecodeListrb"></a>
<div class="modfile"><h4>Modified: branches/safari-612.1.28-branch/Source/JavaScriptCore/bytecode/BytecodeList.rb (281021 => 281022)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-612.1.28-branch/Source/JavaScriptCore/bytecode/BytecodeList.rb   2021-08-13 16:39:44 UTC (rev 281021)
+++ branches/safari-612.1.28-branch/Source/JavaScriptCore/bytecode/BytecodeList.rb      2021-08-13 16:50:38 UTC (rev 281022)
</span><span class="lines">@@ -29,7 +29,6 @@
</span><span class="cx">     :DebugHookType,
</span><span class="cx">     :ECMAMode,
</span><span class="cx">     :ErrorTypeWithExtension,
</span><del>-    :EnumeratorMetadata,
</del><span class="cx">     :GetByIdMode,
</span><span class="cx">     :GetByIdModeMetadata,
</span><span class="cx">     :GetByValHistory,
</span><span class="lines">@@ -1155,71 +1154,91 @@
</span><span class="cx">         basicBlockLocation: BasicBlockLocation.*,
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-op :get_property_enumerator,
</del><ins>+op :get_enumerable_length,
</ins><span class="cx">     args: {
</span><span class="cx">         dst: VirtualRegister,
</span><span class="cx">         base: VirtualRegister,
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-op :enumerator_next,
</del><ins>+op :has_enumerable_indexed_property,
</ins><span class="cx">     args: {
</span><del>-        # out
-        propertyName: VirtualRegister,
-        # in/out
-        mode: VirtualRegister, # Will always be a JS UInt32 representing a JSForInMode.
-        index: VirtualRegister, # Gets reset to zero every time mode changes.
-        # in
</del><ins>+        dst: VirtualRegister,
</ins><span class="cx">         base: VirtualRegister,
</span><del>-        enumerator: VirtualRegister,
</del><ins>+        property: VirtualRegister,
</ins><span class="cx">     },
</span><span class="cx">     metadata: {
</span><span class="cx">         arrayProfile: ArrayProfile,
</span><del>-        enumeratorMetadata: EnumeratorMetadata,
</del><span class="cx">     }
</span><span class="cx"> 
</span><del>-op :enumerator_get_by_val,
</del><ins>+op :has_enumerable_structure_property,
</ins><span class="cx">     args: {
</span><span class="cx">         dst: VirtualRegister,
</span><span class="cx">         base: VirtualRegister,
</span><del>-        mode: VirtualRegister,
-        propertyName: VirtualRegister,
-        index: VirtualRegister,
</del><ins>+        property: VirtualRegister,
</ins><span class="cx">         enumerator: VirtualRegister,
</span><del>-    },
-    metadata: {
-        profile: ValueProfile,
-        arrayProfile: ArrayProfile,
-        enumeratorMetadata: EnumeratorMetadata,
</del><span class="cx">     }
</span><span class="cx"> 
</span><del>-op :enumerator_in_by_val,
</del><ins>+op :has_own_structure_property,
</ins><span class="cx">     args: {
</span><span class="cx">         dst: VirtualRegister,
</span><span class="cx">         base: VirtualRegister,
</span><del>-        mode: VirtualRegister,
-        propertyName: VirtualRegister,
</del><ins>+        property: VirtualRegister,
+        enumerator: VirtualRegister,
+    }
+
+op :in_structure_property,
+    args: {
+        dst: VirtualRegister,
+        base: VirtualRegister,
+        property: VirtualRegister,
+        enumerator: VirtualRegister,
+    }
+
+op :has_enumerable_property,
+    args: {
+        dst: VirtualRegister,
+        base: VirtualRegister,
+        property: VirtualRegister,
+    }
+
+op :get_direct_pname,
+    args: {
+        dst: VirtualRegister,
+        base: VirtualRegister,
+        property: VirtualRegister,
</ins><span class="cx">         index: VirtualRegister,
</span><span class="cx">         enumerator: VirtualRegister,
</span><span class="cx">     },
</span><span class="cx">     metadata: {
</span><del>-        arrayProfile: ArrayProfile,
-        enumeratorMetadata: EnumeratorMetadata,
</del><ins>+        profile: ValueProfile,
</ins><span class="cx">     }
</span><span class="cx"> 
</span><del>-op :enumerator_has_own_property,
</del><ins>+op :get_property_enumerator,
</ins><span class="cx">     args: {
</span><span class="cx">         dst: VirtualRegister,
</span><span class="cx">         base: VirtualRegister,
</span><del>-        mode: VirtualRegister,
-        propertyName: VirtualRegister,
</del><ins>+    }
+
+op :enumerator_structure_pname,
+    args: {
+        dst: VirtualRegister,
+        enumerator: VirtualRegister,
</ins><span class="cx">         index: VirtualRegister,
</span><ins>+    }
+
+op :enumerator_generic_pname,
+    args: {
+        dst: VirtualRegister,
</ins><span class="cx">         enumerator: VirtualRegister,
</span><del>-    },
-    metadata: {
-        arrayProfile: ArrayProfile,
-        enumeratorMetadata: EnumeratorMetadata,
</del><ins>+        index: VirtualRegister,
</ins><span class="cx">     }
</span><span class="cx"> 
</span><ins>+op :to_index_string,
+    args: {
+        dst: VirtualRegister,
+        index: VirtualRegister,
+    }
+
</ins><span class="cx"> op :unreachable
</span><span class="cx"> 
</span><span class="cx"> op :create_rest,
</span></span></pre></div>
<a id="branchessafari612128branchSourceJavaScriptCorebytecodeBytecodeUseDefcpp"></a>
<div class="modfile"><h4>Modified: branches/safari-612.1.28-branch/Source/JavaScriptCore/bytecode/BytecodeUseDef.cpp (281021 => 281022)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-612.1.28-branch/Source/JavaScriptCore/bytecode/BytecodeUseDef.cpp        2021-08-13 16:39:44 UTC (rev 281021)
+++ branches/safari-612.1.28-branch/Source/JavaScriptCore/bytecode/BytecodeUseDef.cpp   2021-08-13 16:50:38 UTC (rev 281022)
</span><span class="lines">@@ -163,9 +163,11 @@
</span><span class="cx"> 
</span><span class="cx">     USES(OpSpread, argument)
</span><span class="cx">     USES(OpGetPropertyEnumerator, base)
</span><ins>+    USES(OpGetEnumerableLength, base)
</ins><span class="cx">     USES(OpNewFuncExp, scope)
</span><span class="cx">     USES(OpNewGeneratorFuncExp, scope)
</span><span class="cx">     USES(OpNewAsyncFuncExp, scope)
</span><ins>+    USES(OpToIndexString, index)
</ins><span class="cx">     USES(OpCreateLexicalEnvironment, scope, symbolTable, initialValue)
</span><span class="cx">     USES(OpCreateGeneratorFrameEnvironment, scope, symbolTable, initialValue)
</span><span class="cx">     USES(OpResolveScope, scope)
</span><span class="lines">@@ -219,6 +221,11 @@
</span><span class="cx">     USES(OpGetFromArguments, arguments)
</span><span class="cx">     USES(OpNewArrayBuffer, immutableButterfly)
</span><span class="cx"> 
</span><ins>+    USES(OpHasEnumerableIndexedProperty, base, property)
+    USES(OpHasEnumerableStructureProperty, base, property, enumerator)
+    USES(OpHasEnumerableProperty, base, property)
+    USES(OpEnumeratorStructurePname, enumerator, index)
+    USES(OpEnumeratorGenericPname, enumerator, index)
</ins><span class="cx">     USES(OpGetByVal, base, property)
</span><span class="cx">     USES(OpGetPrivateName, base, property)
</span><span class="cx">     USES(OpPutPrivateName, base, property, value)
</span><span class="lines">@@ -258,6 +265,8 @@
</span><span class="cx"> 
</span><span class="cx">     USES(OpGetByValWithThis, base, thisValue, property)
</span><span class="cx">     USES(OpInstanceofCustom, value, constructor, hasInstanceValue)
</span><ins>+    USES(OpHasOwnStructureProperty, base, property, enumerator)
+    USES(OpInStructureProperty, base, property, enumerator)
</ins><span class="cx"> 
</span><span class="cx">     case op_call_varargs: {
</span><span class="cx">         auto bytecode = instruction->as<OpCallVarargs>();
</span><span class="lines">@@ -275,6 +284,8 @@
</span><span class="cx">         return;
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    USES(OpGetDirectPname, base, property, index, enumerator)
+
</ins><span class="cx">     USES(OpSwitchString, scrutinee)
</span><span class="cx">     USES(OpSwitchChar, scrutinee)
</span><span class="cx">     USES(OpSwitchImm, scrutinee)
</span><span class="lines">@@ -284,11 +295,6 @@
</span><span class="cx"> 
</span><span class="cx">     USES(OpYield, argument)
</span><span class="cx"> 
</span><del>-    USES(OpEnumeratorNext, mode, index, base, enumerator)
-    USES(OpEnumeratorGetByVal, base, mode, propertyName, index, enumerator)
-    USES(OpEnumeratorInByVal, base, mode, propertyName, index, enumerator)
-    USES(OpEnumeratorHasOwnProperty, base, mode, propertyName, index, enumerator)
-
</del><span class="cx">     case op_iterator_open: {
</span><span class="cx">         auto bytecode = instruction->as<OpIteratorOpen>();
</span><span class="cx">         useAtEachCheckpointStartingWith(OpIteratorOpen::symbolCall, bytecode.m_symbolIterator, bytecode.m_iterable);
</span><span class="lines">@@ -418,7 +424,17 @@
</span><span class="cx">         return;
</span><span class="cx">     // These all have a single destination for the first argument.
</span><span class="cx">     DEFS(OpArgumentCount, dst)
</span><ins>+    DEFS(OpToIndexString, dst)
+    DEFS(OpGetEnumerableLength, dst)
+    DEFS(OpHasEnumerableIndexedProperty, dst)
+    DEFS(OpHasEnumerableStructureProperty, dst)
+    DEFS(OpHasEnumerableProperty, dst)
+    DEFS(OpHasOwnStructureProperty, dst)
+    DEFS(OpInStructureProperty, dst)
+    DEFS(OpGetDirectPname, dst)
</ins><span class="cx">     DEFS(OpGetPropertyEnumerator, dst)
</span><ins>+    DEFS(OpEnumeratorStructurePname, dst)
+    DEFS(OpEnumeratorGenericPname, dst)
</ins><span class="cx">     DEFS(OpGetParentScope, dst)
</span><span class="cx">     DEFS(OpPushWithScope, dst)
</span><span class="cx">     DEFS(OpCreateLexicalEnvironment, dst)
</span><span class="lines">@@ -551,11 +567,6 @@
</span><span class="cx"> 
</span><span class="cx">     DEFS(OpCatch, exception, thrownValue)
</span><span class="cx"> 
</span><del>-    DEFS(OpEnumeratorNext, propertyName, mode, index)
-    DEFS(OpEnumeratorGetByVal, dst)
-    DEFS(OpEnumeratorInByVal, dst)
-    DEFS(OpEnumeratorHasOwnProperty, dst)
-
</del><span class="cx">     case op_iterator_open: {
</span><span class="cx">         auto bytecode = instruction->as<OpIteratorOpen>();
</span><span class="cx"> 
</span></span></pre></div>
<a id="branchessafari612128branchSourceJavaScriptCorebytecodeCodeBlockcpp"></a>
<div class="modfile"><h4>Modified: branches/safari-612.1.28-branch/Source/JavaScriptCore/bytecode/CodeBlock.cpp (281021 => 281022)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-612.1.28-branch/Source/JavaScriptCore/bytecode/CodeBlock.cpp     2021-08-13 16:39:44 UTC (rev 281021)
+++ branches/safari-612.1.28-branch/Source/JavaScriptCore/bytecode/CodeBlock.cpp        2021-08-13 16:50:38 UTC (rev 281022)
</span><span class="lines">@@ -472,6 +472,8 @@
</span><span class="cx">         OpcodeID opcodeID = instruction->opcodeID();
</span><span class="cx">         m_bytecodeCost += opcodeLengths[opcodeID];
</span><span class="cx">         switch (opcodeID) {
</span><ins>+        LINK(OpHasEnumerableIndexedProperty)
+
</ins><span class="cx">         LINK(OpCallVarargs, profile)
</span><span class="cx">         LINK(OpTailCallVarargs, profile)
</span><span class="cx">         LINK(OpTailCallForwardArguments, profile)
</span><span class="lines">@@ -479,6 +481,7 @@
</span><span class="cx">         LINK(OpGetByVal, profile)
</span><span class="cx">         LINK(OpGetPrivateName, profile)
</span><span class="cx"> 
</span><ins>+        LINK(OpGetDirectPname, profile)
</ins><span class="cx">         LINK(OpGetByIdWithThis, profile)
</span><span class="cx">         LINK(OpTryGetById, profile)
</span><span class="cx">         LINK(OpGetByIdDirect, profile)
</span><span class="lines">@@ -500,11 +503,6 @@
</span><span class="cx"> 
</span><span class="cx">         LINK(OpGetById, profile)
</span><span class="cx"> 
</span><del>-        LINK(OpEnumeratorNext, profile)
-        LINK(OpEnumeratorInByVal, profile)
-        LINK(OpEnumeratorHasOwnProperty, profile)
-        LINK(OpEnumeratorGetByVal, profile)
-
</del><span class="cx">         LINK(OpCall, profile)
</span><span class="cx">         LINK(OpTailCall, profile)
</span><span class="cx">         LINK(OpCallEval, profile)
</span></span></pre></div>
<a id="branchessafari612128branchSourceJavaScriptCorebytecodeLinkTimeConstanth"></a>
<div class="modfile"><h4>Modified: branches/safari-612.1.28-branch/Source/JavaScriptCore/bytecode/LinkTimeConstant.h (281021 => 281022)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-612.1.28-branch/Source/JavaScriptCore/bytecode/LinkTimeConstant.h        2021-08-13 16:39:44 UTC (rev 281021)
+++ branches/safari-612.1.28-branch/Source/JavaScriptCore/bytecode/LinkTimeConstant.h   2021-08-13 16:50:38 UTC (rev 281022)
</span><span class="lines">@@ -111,7 +111,6 @@
</span><span class="cx">     v(callFunction, nullptr) \
</span><span class="cx">     v(hasOwnPropertyFunction, nullptr) \
</span><span class="cx">     v(createPrivateSymbol, nullptr) \
</span><del>-    v(emptyPropertyNameEnumerator, nullptr) \
</del><span class="cx"> 
</span><span class="cx"> 
</span><span class="cx"> #define DECLARE_LINK_TIME_CONSTANT(name, code) name,
</span></span></pre></div>
<a id="branchessafari612128branchSourceJavaScriptCorebytecodeOpcodeh"></a>
<div class="modfile"><h4>Modified: branches/safari-612.1.28-branch/Source/JavaScriptCore/bytecode/Opcode.h (281021 => 281022)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-612.1.28-branch/Source/JavaScriptCore/bytecode/Opcode.h  2021-08-13 16:39:44 UTC (rev 281021)
+++ branches/safari-612.1.28-branch/Source/JavaScriptCore/bytecode/Opcode.h     2021-08-13 16:50:38 UTC (rev 281022)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> /*
</span><del>- * Copyright (C) 2008-2021 Apple Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2008, 2009, 2013, 2014 Apple Inc. All rights reserved.
</ins><span class="cx">  * Copyright (C) 2008 Cameron Zwarich <cwzwarich@uwaterloo.ca>
</span><span class="cx">  *
</span><span class="cx">  * Redistribution and use in source and binary forms, with or without
</span><span class="lines">@@ -99,7 +99,7 @@
</span><span class="cx">     macro(OpTailCallForwardArguments) \
</span><span class="cx">     macro(OpConstructVarargs) \
</span><span class="cx">     macro(OpGetByVal) \
</span><del>-    macro(OpEnumeratorGetByVal) \
</del><ins>+    macro(OpGetDirectPname) \
</ins><span class="cx">     macro(OpGetById) \
</span><span class="cx">     macro(OpGetByIdWithThis) \
</span><span class="cx">     macro(OpTryGetById) \
</span><span class="lines">@@ -127,6 +127,7 @@
</span><span class="cx">     macro(OpGetPrivateName) \
</span><span class="cx"> 
</span><span class="cx"> #define FOR_EACH_OPCODE_WITH_ARRAY_PROFILE(macro) \
</span><ins>+    macro(OpHasEnumerableIndexedProperty) \
</ins><span class="cx">     macro(OpCallVarargs) \
</span><span class="cx">     macro(OpTailCallVarargs) \
</span><span class="cx">     macro(OpTailCallForwardArguments) \
</span><span class="lines">@@ -135,10 +136,6 @@
</span><span class="cx">     macro(OpInByVal) \
</span><span class="cx">     macro(OpPutByVal) \
</span><span class="cx">     macro(OpPutByValDirect) \
</span><del>-    macro(OpEnumeratorNext) \
-    macro(OpEnumeratorGetByVal) \
-    macro(OpEnumeratorInByVal) \
-    macro(OpEnumeratorHasOwnProperty) \
</del><span class="cx"> 
</span><span class="cx"> #define FOR_EACH_OPCODE_WITH_ARRAY_ALLOCATION_PROFILE(macro) \
</span><span class="cx">     macro(OpNewArray) \
</span></span></pre></div>
<a id="branchessafari612128branchSourceJavaScriptCorebytecompilerBytecodeGeneratorcpp"></a>
<div class="modfile"><h4>Modified: branches/safari-612.1.28-branch/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp (281021 => 281022)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-612.1.28-branch/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp 2021-08-13 16:39:44 UTC (rev 281021)
+++ branches/safari-612.1.28-branch/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp    2021-08-13 16:50:38 UTC (rev 281022)
</span><span class="lines">@@ -1503,11 +1503,11 @@
</span><span class="cx">     return m_lastInstruction.offset();
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void BytecodeGenerator::recordHasOwnPropertyInForInLoop(ForInContext& context, unsigned branchOffset, Label& genericPath)
</del><ins>+void BytecodeGenerator::recordHasOwnStructurePropertyInForInLoop(StructureForInContext& structureContext, unsigned branchOffset, Label& genericPath)
</ins><span class="cx"> {
</span><span class="cx">     RELEASE_ASSERT(genericPath.isBound());
</span><span class="cx">     RELEASE_ASSERT(!genericPath.isForward());
</span><del>-    context.addHasOwnPropertyJump(branchOffset, genericPath.location());
</del><ins>+    structureContext.addHasOwnPropertyJump(branchOffset, genericPath.location());
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> bool BytecodeGenerator::hasConstant(const Identifier& ident) const
</span><span class="lines">@@ -2581,8 +2581,12 @@
</span><span class="cx">         if (context.local() != property)
</span><span class="cx">             continue;
</span><span class="cx"> 
</span><del>-        OpEnumeratorInByVal::emit<OpcodeSize::Wide32>(this, dst, base, context.mode(), property, context.propertyOffset(), context.enumerator());
-        context.addInInst(m_lastInstruction.offset(), property->index());
</del><ins>+        if (!context.isStructureForInContext())
+            break;
+
+        StructureForInContext& structureContext = context.asStructureForInContext();
+        OpInStructureProperty::emit<OpcodeSize::Wide32>(this, dst, base, property, structureContext.enumerator());
+        structureContext.addInInst(m_lastInstruction.offset(), property->index());
</ins><span class="cx">         return dst;
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="lines">@@ -2730,9 +2734,24 @@
</span><span class="cx">         if (context.local() != property)
</span><span class="cx">             continue;
</span><span class="cx"> 
</span><del>-        // FIXME: We should have a better bytecode rewriter that can resize chunks.
-        OpEnumeratorGetByVal::emit<OpcodeSize::Wide32>(this, kill(dst), base, context.mode(), property, context.propertyOffset(), context.enumerator());
-        context.addGetInst(m_lastInstruction.offset(), property->index());
</del><ins>+        if (context.isIndexedForInContext()) {
+            auto& indexedContext = context.asIndexedForInContext();
+            kill(dst);
+            if (OpGetByVal::checkWithoutMetadataID<OpcodeSize::Narrow>(this, dst, base, property))
+                OpGetByVal::emitWithSmallestSizeRequirement<OpcodeSize::Narrow>(this, dst, base, indexedContext.index());
+            else if (OpGetByVal::checkWithoutMetadataID<OpcodeSize::Wide16>(this, dst, base, property))
+                OpGetByVal::emitWithSmallestSizeRequirement<OpcodeSize::Wide16>(this, dst, base, indexedContext.index());
+            else
+                OpGetByVal::emit<OpcodeSize::Wide32>(this, dst, base, indexedContext.index());
+            indexedContext.addGetInst(m_lastInstruction.offset(), property->index());
+            return dst;
+        }
+
+        // We cannot do the above optimization here since OpGetDirectPname => OpGetByVal conversion involves different metadata ID allocation.
+        StructureForInContext& structureContext = context.asStructureForInContext();
+        OpGetDirectPname::emit<OpcodeSize::Wide32>(this, kill(dst), base, property, structureContext.index(), structureContext.enumerator());
+
+        structureContext.addGetInst(m_lastInstruction.offset(), property->index());
</ins><span class="cx">         return dst;
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="lines">@@ -4533,17 +4552,36 @@
</span><span class="cx">     return emitGetFromScope(dst, scope.get(), var, ThrowIfNotFound);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void BytecodeGenerator::emitEnumeratorNext(RegisterID* propertyName, RegisterID* mode, RegisterID* index, RegisterID* base, RegisterID* enumerator)
</del><ins>+RegisterID* BytecodeGenerator::emitGetEnumerableLength(RegisterID* dst, RegisterID* base)
</ins><span class="cx"> {
</span><del>-    OpEnumeratorNext::emit(this, propertyName, mode, index, base, enumerator);
</del><ins>+    OpGetEnumerableLength::emit(this, dst, base);
+    return dst;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-RegisterID* BytecodeGenerator::emitEnumeratorHasOwnProperty(RegisterID* dst, RegisterID* base, RegisterID* mode, RegisterID* propertyName, RegisterID* index, RegisterID* enumerator)
</del><ins>+RegisterID* BytecodeGenerator::emitHasEnumerableIndexedProperty(RegisterID* dst, RegisterID* base, RegisterID* propertyName)
</ins><span class="cx"> {
</span><del>-    OpEnumeratorHasOwnProperty::emit(this, dst, base, mode, propertyName, index, enumerator);
</del><ins>+    OpHasEnumerableIndexedProperty::emit(this, dst, base, propertyName);
</ins><span class="cx">     return dst;
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+RegisterID* BytecodeGenerator::emitHasEnumerableStructureProperty(RegisterID* dst, RegisterID* base, RegisterID* propertyName, RegisterID* enumerator)
+{
+    OpHasEnumerableStructureProperty::emit(this, dst, base, propertyName, enumerator);
+    return dst;
+}
+
+RegisterID* BytecodeGenerator::emitHasEnumerableProperty(RegisterID* dst, RegisterID* base, RegisterID* propertyName)
+{
+    OpHasEnumerableProperty::emit(this, dst, base, propertyName);
+    return dst;
+}
+
+RegisterID* BytecodeGenerator::emitHasOwnStructureProperty(RegisterID* dst, RegisterID* base, RegisterID* propertyName, RegisterID* enumerator)
+{
+    OpHasOwnStructureProperty::emit(this, dst, base, propertyName, enumerator);
+    return dst;
+}
+
</ins><span class="cx"> RegisterID* BytecodeGenerator::emitGetPropertyEnumerator(RegisterID* dst, RegisterID* base)
</span><span class="cx"> {
</span><span class="cx">     OpGetPropertyEnumerator::emit(this, dst, base);
</span><span class="lines">@@ -4550,6 +4588,24 @@
</span><span class="cx">     return dst;
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+RegisterID* BytecodeGenerator::emitEnumeratorStructurePropertyName(RegisterID* dst, RegisterID* enumerator, RegisterID* index)
+{
+    OpEnumeratorStructurePname::emit(this, dst, enumerator, index);
+    return dst;
+}
+
+RegisterID* BytecodeGenerator::emitEnumeratorGenericPropertyName(RegisterID* dst, RegisterID* enumerator, RegisterID* index)
+{
+    OpEnumeratorGenericPname::emit(this, dst, enumerator, index);
+    return dst;
+}
+
+RegisterID* BytecodeGenerator::emitToIndexString(RegisterID* dst, RegisterID* index)
+{
+    OpToIndexString::emit(this, dst, index);
+    return dst;
+}
+
</ins><span class="cx"> RegisterID* BytecodeGenerator::emitIsCellWithType(RegisterID* dst, RegisterID* src, JSType type)
</span><span class="cx"> {
</span><span class="cx">     OpIsCellWithType::emit(this, dst, src, type);
</span><span class="lines">@@ -4592,6 +4648,23 @@
</span><span class="cx">     return dst;
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void BytecodeGenerator::pushIndexedForInScope(RegisterID* localRegister, RegisterID* indexRegister)
+{
+    if (!localRegister)
+        return;
+    unsigned bodyBytecodeStartOffset = instructions().size();
+    m_forInContextStack.append(adoptRef(*new IndexedForInContext(localRegister, indexRegister, bodyBytecodeStartOffset)));
+}
+
+void BytecodeGenerator::popIndexedForInScope(RegisterID* localRegister)
+{
+    if (!localRegister)
+        return;
+    unsigned bodyBytecodeEndOffset = instructions().size();
+    m_forInContextStack.last()->asIndexedForInContext().finalize(*this, m_codeBlock.get(), bodyBytecodeEndOffset);
+    m_forInContextStack.removeLast();
+}
+
</ins><span class="cx"> RegisterID* BytecodeGenerator::emitLoadArrowFunctionLexicalEnvironment(const Identifier& identifier)
</span><span class="cx"> {
</span><span class="cx">     ASSERT(m_codeBlock->isArrowFunction() || m_codeBlock->isArrowFunctionContext() || constructorKind() == ConstructorKind::Extends || m_codeType == EvalCode || m_codeBlock->parseMode() == SourceParseMode::ClassFieldInitializerMode);
</span><span class="lines">@@ -4695,20 +4768,20 @@
</span><span class="cx">     }
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void BytecodeGenerator::pushForInScope(RegisterID* localRegister, RegisterID* propertyNameRegister, RegisterID* propertyOffsetRegister, RegisterID* enumeratorRegister, RegisterID* modeRegister, std::optional<Variable> baseVariable)
</del><ins>+void BytecodeGenerator::pushStructureForInScope(RegisterID* localRegister, RegisterID* indexRegister, RegisterID* propertyRegister, RegisterID* enumeratorRegister, std::optional<Variable> baseVariable)
</ins><span class="cx"> {
</span><span class="cx">     if (!localRegister)
</span><span class="cx">         return;
</span><span class="cx">     unsigned bodyBytecodeStartOffset = instructions().size();
</span><del>-    m_forInContextStack.append(adoptRef(*new ForInContext(localRegister, propertyNameRegister, propertyOffsetRegister, enumeratorRegister, modeRegister, baseVariable, bodyBytecodeStartOffset)));
</del><ins>+    m_forInContextStack.append(adoptRef(*new StructureForInContext(localRegister, indexRegister, propertyRegister, enumeratorRegister, baseVariable, bodyBytecodeStartOffset)));
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-void BytecodeGenerator::popForInScope(RegisterID* localRegister)
</del><ins>+void BytecodeGenerator::popStructureForInScope(RegisterID* localRegister)
</ins><span class="cx"> {
</span><span class="cx">     if (!localRegister)
</span><span class="cx">         return;
</span><span class="cx">     unsigned bodyBytecodeEndOffset = instructions().size();
</span><del>-    m_forInContextStack.last()->finalize(*this, m_codeBlock.get(), bodyBytecodeEndOffset);
</del><ins>+    m_forInContextStack.last()->asStructureForInContext().finalize(*this, m_codeBlock.get(), bodyBytecodeEndOffset);
</ins><span class="cx">     m_forInContextStack.removeLast();
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -5311,7 +5384,34 @@
</span><span class="cx">     emitJumpIfTrue(emitIsUndefinedOrNull(newTemporary(), src), m_optionalChainTargetStack.last().get());
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-template <typename OldOpType, typename NewOpType, typename TupleType>
</del><ins>+void ForInContext::finalize(BytecodeGenerator& generator, UnlinkedCodeBlockGenerator* codeBlock, unsigned bodyBytecodeEndOffset)
+{
+    // Lexically invalidating ForInContexts is kind of weak sauce, but it only occurs if
+    // either of the following conditions is true:
+    //
+    // (1) The loop iteration variable is re-assigned within the body of the loop.
+    // (2) The loop iteration variable is captured in the lexical scope of the function.
+    //
+    // These two situations occur sufficiently rarely that it's okay to use this style of
+    // "analysis" to make iteration faster. If we didn't want to do this, we would either have
+    // to perform some flow-sensitive analysis to see if/when the loop iteration variable was
+    // reassigned, or we'd have to resort to runtime checks to see if the variable had been
+    // reassigned from its original value.
+
+    for (unsigned offset = bodyBytecodeStartOffset(); isValid() && offset < bodyBytecodeEndOffset;) {
+        auto instruction = generator.instructions().at(offset);
+        ASSERT(!instruction->is<OpEnter>());
+        for (Checkpoint checkpoint = instruction->numberOfCheckpoints(); checkpoint--;) {
+            computeDefsForBytecodeIndex(codeBlock, instruction.ptr(), checkpoint, [&] (VirtualRegister operand) {
+                if (local()->virtualRegister() == operand)
+                    invalidate();
+            });
+        }
+        offset += instruction->size();
+    }
+}
+
+template <typename OldOpType, typename TupleType>
</ins><span class="cx"> ALWAYS_INLINE void rewriteOp(BytecodeGenerator& generator, TupleType& instTuple)
</span><span class="cx"> {
</span><span class="cx">     unsigned instIndex = std::get<0>(instTuple);
</span><span class="lines">@@ -5331,8 +5431,14 @@
</span><span class="cx">     // 2. base stays the same.
</span><span class="cx">     // 3. property gets switched to the original property.
</span><span class="cx"> 
</span><del>-    static_assert(sizeof(NewOpType) <= sizeof(OldOpType));
-    NewOpType::emit(&generator, bytecode.m_dst, bytecode.m_base, VirtualRegister(propertyRegIndex));
</del><ins>+    if constexpr (std::is_same<OldOpType, OpGetDirectPname>::value) {
+        static_assert(sizeof(OpGetByVal) <= sizeof(OpGetDirectPname));
+        OpGetByVal::emit<OpcodeSize::Wide32>(&generator, bytecode.m_dst, bytecode.m_base, VirtualRegister(propertyRegIndex));
+    } else if constexpr (std::is_same<OldOpType, OpInStructureProperty>::value) {
+        static_assert(sizeof(OpInByVal) <= sizeof(OpInStructureProperty));
+        OpInByVal::emit<OpcodeSize::Wide32>(&generator, bytecode.m_dst, bytecode.m_base, VirtualRegister(propertyRegIndex));
+    } else
+        RELEASE_ASSERT_NOT_REACHED();
</ins><span class="cx"> 
</span><span class="cx">     // 4. nop out the remaining bytes
</span><span class="cx">     while (generator.m_writer.position() < end)
</span><span class="lines">@@ -5339,34 +5445,10 @@
</span><span class="cx">         OpNop::emit<OpcodeSize::Narrow>(&generator);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void ForInContext::finalize(BytecodeGenerator& generator, UnlinkedCodeBlockGenerator* codeBlock, unsigned bodyBytecodeEndOffset)
</del><ins>+void StructureForInContext::finalize(BytecodeGenerator& generator, UnlinkedCodeBlockGenerator* codeBlock, unsigned bodyBytecodeEndOffset)
</ins><span class="cx"> {
</span><del>-    // Lexically invalidating ForInContexts is kind of weak sauce, but it only occurs if
-    // either of the following conditions is true:
-    //
-    // (1) The loop iteration variable is re-assigned within the body of the loop.
-    // (2) The loop iteration variable is captured in the lexical scope of the function.
-    //
-    // These two situations occur sufficiently rarely that it's okay to use this style of
-    // "analysis" to make iteration faster. If we didn't want to do this, we would either have
-    // to perform some flow-sensitive analysis to see if/when the loop iteration variable was
-    // reassigned, or we'd have to resort to runtime checks to see if the variable had been
-    // reassigned from its original value.
-
-    bool escaped = false;
-    for (unsigned offset = bodyBytecodeStartOffset(); !escaped && offset < bodyBytecodeEndOffset;) {
-        auto instruction = generator.instructions().at(offset);
-        ASSERT(!instruction->is<OpEnter>());
-        for (Checkpoint checkpoint = instruction->numberOfCheckpoints(); checkpoint--;) {
-            computeDefsForBytecodeIndex(codeBlock, instruction.ptr(), checkpoint, [&] (VirtualRegister operand) {
-                if (local()->virtualRegister() == operand)
-                    escaped = true;
-            });
-        }
-        offset += instruction->size();
-    }
-
-    if (!escaped)
</del><ins>+    Base::finalize(generator, codeBlock, bodyBytecodeEndOffset);
+    if (isValid())
</ins><span class="cx">         return;
</span><span class="cx"> 
</span><span class="cx">     OpcodeID lastOpcodeID = generator.m_lastOpcodeID;
</span><span class="lines">@@ -5373,10 +5455,10 @@
</span><span class="cx">     InstructionStream::MutableRef lastInstruction = generator.m_lastInstruction;
</span><span class="cx"> 
</span><span class="cx">     for (const auto& instTuple : m_getInsts)
</span><del>-        rewriteOp<OpEnumeratorGetByVal, OpGetByVal>(generator, instTuple);
</del><ins>+        rewriteOp<OpGetDirectPname>(generator, instTuple);
</ins><span class="cx"> 
</span><span class="cx">     for (const auto& instTuple : m_inInsts)
</span><del>-        rewriteOp<OpEnumeratorInByVal, OpInByVal>(generator, instTuple);
</del><ins>+        rewriteOp<OpInStructureProperty>(generator, instTuple);
</ins><span class="cx"> 
</span><span class="cx">     for (const auto& hasOwnPropertyTuple : m_hasOwnPropertyJumpInsts) {
</span><span class="cx">         static_assert(sizeof(OpJmp) <= sizeof(OpJneqPtr));
</span><span class="lines">@@ -5405,6 +5487,22 @@
</span><span class="cx">     }
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void IndexedForInContext::finalize(BytecodeGenerator& generator, UnlinkedCodeBlockGenerator* codeBlock, unsigned bodyBytecodeEndOffset)
+{
+    Base::finalize(generator, codeBlock, bodyBytecodeEndOffset);
+    if (isValid())
+        return;
+
+    for (const auto& instPair : m_getInsts) {
+        unsigned instIndex = instPair.first;
+        int propertyRegIndex = instPair.second;
+        generator.m_writer.ref(instIndex)->cast<OpGetByVal>()->setProperty(VirtualRegister(propertyRegIndex), []() {
+            ASSERT_NOT_REACHED();
+            return VirtualRegister();
+        });
+    }
+}
+
</ins><span class="cx"> void StaticPropertyAnalysis::record()
</span><span class="cx"> {
</span><span class="cx">     auto* instruction = m_instructionRef.ptr();
</span><span class="lines">@@ -5430,7 +5528,7 @@
</span><span class="cx">     OpToThis::emit(this, kill(&m_thisRegister), ecmaMode());
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-ForInContext* BytecodeGenerator::findForInContext(RegisterID* property)
</del><ins>+StructureForInContext* BytecodeGenerator::findStructureForInContext(RegisterID* property)
</ins><span class="cx"> {
</span><span class="cx">     for (size_t i = m_forInContextStack.size(); i--; ) {
</span><span class="cx">         ForInContext& context = m_forInContextStack[i].get();
</span><span class="lines">@@ -5437,7 +5535,10 @@
</span><span class="cx">         if (context.local() != property)
</span><span class="cx">             continue;
</span><span class="cx"> 
</span><del>-        return &context;
</del><ins>+        if (!context.isStructureForInContext())
+            break;
+
+        return &context.asStructureForInContext();
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     return nullptr;
</span></span></pre></div>
<a id="branchessafari612128branchSourceJavaScriptCorebytecompilerBytecodeGeneratorh"></a>
<div class="modfile"><h4>Modified: branches/safari-612.1.28-branch/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h (281021 => 281022)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-612.1.28-branch/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h   2021-08-13 16:39:44 UTC (rev 281021)
+++ branches/safari-612.1.28-branch/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h      2021-08-13 16:50:38 UTC (rev 281022)
</span><span class="lines">@@ -61,7 +61,8 @@
</span><span class="cx"> 
</span><span class="cx">     class JSImmutableButterfly;
</span><span class="cx">     class Identifier;
</span><del>-    class ForInContext;
</del><ins>+    class IndexedForInContext;
+    class StructureForInContext;
</ins><span class="cx"> 
</span><span class="cx">     enum ExpectedFunction {
</span><span class="cx">         NoExpectedFunction,
</span><span class="lines">@@ -255,18 +256,71 @@
</span><span class="cx">         WTF_MAKE_FAST_ALLOCATED;
</span><span class="cx">         WTF_MAKE_NONCOPYABLE(ForInContext);
</span><span class="cx">     public:
</span><ins>+        virtual ~ForInContext() = default;
+
+        bool isValid() const { return m_isValid; }
+        void invalidate() { m_isValid = false; }
+
+        enum class Type : uint8_t {
+            IndexedForIn,
+            StructureForIn
+        };
+
+        Type type() const { return m_type; }
+        bool isIndexedForInContext() const { return m_type == Type::IndexedForIn; }
+        bool isStructureForInContext() const { return m_type == Type::StructureForIn; }
+
+        IndexedForInContext& asIndexedForInContext()
+        {
+            ASSERT(isIndexedForInContext());
+            return *reinterpret_cast<IndexedForInContext*>(this);
+        }
+
+        StructureForInContext& asStructureForInContext()
+        {
+            ASSERT(isStructureForInContext());
+            return *reinterpret_cast<StructureForInContext*>(this);
+        }
+
+        RegisterID* local() const { return m_localRegister.get(); }
+
+    protected:
+        ForInContext(RegisterID* localRegister, Type type, unsigned bodyBytecodeStartOffset)
+            : m_localRegister(localRegister)
+            , m_type(type)
+            , m_bodyBytecodeStartOffset(bodyBytecodeStartOffset)
+        { }
+
+        unsigned bodyBytecodeStartOffset() const { return m_bodyBytecodeStartOffset; }
+
+        void finalize(BytecodeGenerator&, UnlinkedCodeBlockGenerator*, unsigned bodyBytecodeEndOffset);
+
+    private:
+        RefPtr<RegisterID> m_localRegister;
+        bool m_isValid { true };
+        Type m_type;
+        unsigned m_bodyBytecodeStartOffset;
+    };
+
+    class StructureForInContext : public ForInContext {
+        using Base = ForInContext;
+    public:
</ins><span class="cx">         using GetInst = std::tuple<unsigned, int>;
</span><span class="cx">         using InInst = GetInst;
</span><span class="cx">         using HasOwnPropertyJumpInst = std::tuple<unsigned, unsigned>;
</span><span class="cx"> 
</span><del>-        bool isValid() const { return m_isValid; }
-        void invalidate() { m_isValid = false; }
</del><ins>+        StructureForInContext(RegisterID* localRegister, RegisterID* indexRegister, RegisterID* propertyRegister, RegisterID* enumeratorRegister, std::optional<Variable> baseVariable, unsigned bodyBytecodeStartOffset)
+            : ForInContext(localRegister, Type::StructureForIn, bodyBytecodeStartOffset)
+            , m_indexRegister(indexRegister)
+            , m_propertyRegister(propertyRegister)
+            , m_enumeratorRegister(enumeratorRegister)
+            , m_baseVariable(baseVariable)
+        {
+        }
</ins><span class="cx"> 
</span><del>-        RegisterID* local() const { return m_localRegister.get(); }
-        RegisterID* propertyName() const { return m_propertyName.get(); }
-        RegisterID* propertyOffset() const { return m_propertyOffset.get(); }
-        RegisterID* enumerator() const { return m_enumerator.get(); }
-        RegisterID* mode() const { return m_mode.get(); }
</del><ins>+        RegisterID* index() const { return m_indexRegister.get(); }
+        RegisterID* property() const { return m_propertyRegister.get(); }
+        RegisterID* enumerator() const { return m_enumeratorRegister.get(); }
</ins><span class="cx">         const std::optional<Variable>& baseVariable() const { return m_baseVariable; }
</span><span class="cx"> 
</span><span class="cx">         void addGetInst(unsigned instIndex, int propertyRegIndex)
</span><span class="lines">@@ -284,34 +338,37 @@
</span><span class="cx">             m_hasOwnPropertyJumpInsts.append(HasOwnPropertyJumpInst { branchInstIndex, genericPathTarget });
</span><span class="cx">         }
</span><span class="cx"> 
</span><del>-        ForInContext(RegisterID* localRegister, RegisterID* propertyName, RegisterID* propertyOffset, RegisterID* enumerator, RegisterID* mode, std::optional<Variable> baseVariable, unsigned bodyBytecodeStartOffset)
-            : m_localRegister(localRegister)
-            , m_propertyName(propertyName)
-            , m_propertyOffset(propertyOffset)
-            , m_enumerator(enumerator)
-            , m_mode(mode)
-            , m_baseVariable(baseVariable)
-            , m_bodyBytecodeStartOffset(bodyBytecodeStartOffset)
-        { }
-
-        unsigned bodyBytecodeStartOffset() const { return m_bodyBytecodeStartOffset; }
-
</del><span class="cx">         void finalize(BytecodeGenerator&, UnlinkedCodeBlockGenerator*, unsigned bodyBytecodeEndOffset);
</span><span class="cx"> 
</span><span class="cx">     private:
</span><del>-        RefPtr<RegisterID> m_localRegister;
-        RefPtr<RegisterID> m_propertyName;
-        RefPtr<RegisterID> m_propertyOffset;
-        RefPtr<RegisterID> m_enumerator;
-        RefPtr<RegisterID> m_mode;
</del><ins>+        RefPtr<RegisterID> m_indexRegister;
+        RefPtr<RegisterID> m_propertyRegister;
+        RefPtr<RegisterID> m_enumeratorRegister;
</ins><span class="cx">         std::optional<Variable> m_baseVariable;
</span><del>-        bool m_isValid { true };
-        unsigned m_bodyBytecodeStartOffset;
</del><ins>+        Vector<GetInst> m_getInsts;
</ins><span class="cx">         Vector<InInst> m_inInsts;
</span><del>-        Vector<GetInst> m_getInsts;
</del><span class="cx">         Vector<HasOwnPropertyJumpInst> m_hasOwnPropertyJumpInsts;
</span><span class="cx">     };
</span><span class="cx"> 
</span><ins>+    class IndexedForInContext : public ForInContext {
+        using Base = ForInContext;
+    public:
+        IndexedForInContext(RegisterID* localRegister, RegisterID* indexRegister, unsigned bodyBytecodeStartOffset)
+            : ForInContext(localRegister, Type::IndexedForIn, bodyBytecodeStartOffset)
+            , m_indexRegister(indexRegister)
+        {
+        }
+
+        RegisterID* index() const { return m_indexRegister.get(); }
+
+        void finalize(BytecodeGenerator&, UnlinkedCodeBlockGenerator*, unsigned bodyBytecodeEndOffset);
+        void addGetInst(unsigned instIndex, int propertyIndex) { m_getInsts.append({ instIndex, propertyIndex }); }
+
+    private:
+        RefPtr<RegisterID> m_indexRegister;
+        Vector<std::pair<unsigned, int>> m_getInsts;
+    };
+
</ins><span class="cx">     struct TryData {
</span><span class="cx">         Ref<Label> target;
</span><span class="cx">         HandlerType handlerType;
</span><span class="lines">@@ -342,10 +399,11 @@
</span><span class="cx">         WTF_MAKE_NONCOPYABLE(BytecodeGenerator);
</span><span class="cx"> 
</span><span class="cx">         friend class FinallyContext;
</span><del>-        friend class ForInContext;
</del><ins>+        friend class IndexedForInContext;
+        friend class StructureForInContext;
</ins><span class="cx">         friend class StrictModeScope;
</span><span class="cx"> 
</span><del>-        template <typename OldOpType, typename NewOpType, typename TupleType>
</del><ins>+        template <typename OldOpType, typename TupleType>
</ins><span class="cx">         friend void rewriteOp(BytecodeGenerator&, TupleType&);
</span><span class="cx"> 
</span><span class="cx">     public:
</span><span class="lines">@@ -623,7 +681,7 @@
</span><span class="cx"> 
</span><span class="cx">         void hoistSloppyModeFunctionIfNecessary(const Identifier& functionName);
</span><span class="cx"> 
</span><del>-        ForInContext* findForInContext(RegisterID* property);
</del><ins>+        StructureForInContext* findStructureForInContext(RegisterID* property);
</ins><span class="cx"> 
</span><span class="cx">     private:
</span><span class="cx">         void emitTypeProfilerExpressionInfo(const JSTextPosition& startDivot, const JSTextPosition& endDivot);
</span><span class="lines">@@ -859,7 +917,7 @@
</span><span class="cx">         void emitJumpIfNotFunctionCall(RegisterID* cond, Label& target);
</span><span class="cx">         void emitJumpIfNotFunctionApply(RegisterID* cond, Label& target);
</span><span class="cx">         unsigned emitWideJumpIfNotFunctionHasOwnProperty(RegisterID* cond, Label& target);
</span><del>-        void recordHasOwnPropertyInForInLoop(ForInContext&, unsigned branchOffset, Label& genericPath);
</del><ins>+        void recordHasOwnStructurePropertyInForInLoop(StructureForInContext&, unsigned branchOffset, Label& genericPath);
</ins><span class="cx"> 
</span><span class="cx">         template<typename BinOp, typename JmpOp>
</span><span class="cx">         bool fuseCompareAndJump(RegisterID* cond, Label& target, bool swapOperands = false);
</span><span class="lines">@@ -870,9 +928,17 @@
</span><span class="cx">         void emitEnter();
</span><span class="cx">         void emitCheckTraps();
</span><span class="cx"> 
</span><ins>+        RegisterID* emitHasEnumerableIndexedProperty(RegisterID* dst, RegisterID* base, RegisterID* propertyName);
+        RegisterID* emitHasEnumerableStructureProperty(RegisterID* dst, RegisterID* base, RegisterID* propertyName, RegisterID* enumerator);
+        RegisterID* emitHasEnumerableProperty(RegisterID* dst, RegisterID* base, RegisterID* propertyName);
+        RegisterID* emitHasOwnStructureProperty(RegisterID* dst, RegisterID* base, RegisterID* propertyName, RegisterID* enumerator);
</ins><span class="cx">         RegisterID* emitGetPropertyEnumerator(RegisterID* dst, RegisterID* base);
</span><del>-        void emitEnumeratorNext(RegisterID* propertyName, RegisterID* mode, RegisterID* index, RegisterID* base, RegisterID* enumerator);
-        RegisterID* emitEnumeratorHasOwnProperty(RegisterID* dst, RegisterID* base, RegisterID* mode, RegisterID* propertyName, RegisterID* index, RegisterID* enumerator);
</del><ins>+        RegisterID* emitGetEnumerableLength(RegisterID* dst, RegisterID* base);
+        RegisterID* emitGetStructurePropertyEnumerator(RegisterID* dst, RegisterID* base, RegisterID* length);
+        RegisterID* emitGetGenericPropertyEnumerator(RegisterID* dst, RegisterID* base, RegisterID* length, RegisterID* structureEnumerator);
+        RegisterID* emitEnumeratorStructurePropertyName(RegisterID* dst, RegisterID* enumerator, RegisterID* index);
+        RegisterID* emitEnumeratorGenericPropertyName(RegisterID* dst, RegisterID* enumerator, RegisterID* index);
+        RegisterID* emitToIndexString(RegisterID* dst, RegisterID* index);
</ins><span class="cx"> 
</span><span class="cx">         RegisterID* emitIsCellWithType(RegisterID* dst, RegisterID* src, JSType);
</span><span class="cx">         RegisterID* emitIsGenerator(RegisterID* dst, RegisterID* src) { return emitIsCellWithType(dst, src, JSGeneratorType); }
</span><span class="lines">@@ -991,8 +1057,10 @@
</span><span class="cx">         void popOptionalChainTarget(RegisterID* dst, bool isDelete);
</span><span class="cx">         void emitOptionalCheck(RegisterID* src);
</span><span class="cx"> 
</span><del>-        void pushForInScope(RegisterID* local, RegisterID* propertyName, RegisterID* propertyOffset, RegisterID* enumerator, RegisterID* mode, std::optional<Variable> base);
-        void popForInScope(RegisterID* local);
</del><ins>+        void pushIndexedForInScope(RegisterID* local, RegisterID* index);
+        void popIndexedForInScope(RegisterID* local);
+        void pushStructureForInScope(RegisterID* local, RegisterID* index, RegisterID* property, RegisterID* enumerator, std::optional<Variable> base);
+        void popStructureForInScope(RegisterID* local);
</ins><span class="cx"> 
</span><span class="cx">         LabelScope* breakTarget(const Identifier&);
</span><span class="cx">         LabelScope* continueTarget(const Identifier&);
</span></span></pre></div>
<a id="branchessafari612128branchSourceJavaScriptCorebytecompilerNodesCodegencpp"></a>
<div class="modfile"><h4>Modified: branches/safari-612.1.28-branch/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp (281021 => 281022)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-612.1.28-branch/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp      2021-08-13 16:39:44 UTC (rev 281021)
+++ branches/safari-612.1.28-branch/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp 2021-08-13 16:50:38 UTC (rev 281022)
</span><span class="lines">@@ -2131,24 +2131,24 @@
</span><span class="cx">     RELEASE_ASSERT(m_args->m_listNode && m_args->m_listNode->m_expr && !m_args->m_listNode->m_next);  
</span><span class="cx">     ExpressionNode* argument = m_args->m_listNode->m_expr;
</span><span class="cx">     RELEASE_ASSERT(argument->isResolveNode());
</span><del>-    ForInContext* context = nullptr;
</del><ins>+    StructureForInContext* structureContext = nullptr;
</ins><span class="cx">     Variable argumentVariable = generator.variable(static_cast<ResolveNode*>(argument)->identifier());
</span><span class="cx">     if (argumentVariable.isLocal()) {
</span><span class="cx">         RegisterID* property = argumentVariable.local();
</span><del>-        context = generator.findForInContext(property);
</del><ins>+        structureContext = generator.findStructureForInContext(property);
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     auto canUseFastHasOwnProperty = [&] {
</span><del>-        if (!context)
</del><ins>+        if (!structureContext)
</ins><span class="cx">             return false;
</span><del>-        if (!context->baseVariable())
</del><ins>+        if (!structureContext->baseVariable())
</ins><span class="cx">             return false;
</span><span class="cx">         if (m_base->isResolveNode())
</span><del>-            return generator.variable(static_cast<ResolveNode*>(m_base)->identifier()) == context->baseVariable().value();
</del><ins>+            return generator.variable(static_cast<ResolveNode*>(m_base)->identifier()) == structureContext->baseVariable().value();
</ins><span class="cx">         if (m_base->isThisNode()) {
</span><span class="cx">             // After generator.ensureThis (which must be invoked in |base|'s materialization), we can ensure that |this| is in local this-register.
</span><span class="cx">             ASSERT(base);
</span><del>-            return generator.variable(generator.propertyNames().builtinNames().thisPrivateName(), ThisResolutionType::Local) == context->baseVariable().value();
</del><ins>+            return generator.variable(generator.propertyNames().builtinNames().thisPrivateName(), ThisResolutionType::Local) == structureContext->baseVariable().value();
</ins><span class="cx">         }
</span><span class="cx">         return false;
</span><span class="cx">     };
</span><span class="lines">@@ -2160,7 +2160,7 @@
</span><span class="cx">         Ref<Label> end = generator.newLabel();
</span><span class="cx"> 
</span><span class="cx">         unsigned branchInsnOffset = generator.emitWideJumpIfNotFunctionHasOwnProperty(function.get(), realCall.get());
</span><del>-        generator.emitEnumeratorHasOwnProperty(returnValue.get(), base.get(), context->mode(), generator.emitNode(argument), context->propertyOffset(), context->enumerator());
</del><ins>+        generator.emitHasOwnStructureProperty(returnValue.get(), base.get(), generator.emitNode(argument), structureContext->enumerator());
</ins><span class="cx">         generator.emitJump(end.get());
</span><span class="cx"> 
</span><span class="cx">         generator.emitLabel(realCall.get());
</span><span class="lines">@@ -2172,7 +2172,7 @@
</span><span class="cx"> 
</span><span class="cx">         generator.emitLabel(end.get());
</span><span class="cx"> 
</span><del>-        generator.recordHasOwnPropertyInForInLoop(*context, branchInsnOffset, realCall);
</del><ins>+        generator.recordHasOwnStructurePropertyInForInLoop(*structureContext, branchInsnOffset, realCall);
</ins><span class="cx">     } else {
</span><span class="cx">         CallArguments callArguments(generator, m_args);
</span><span class="cx">         generator.move(callArguments.thisRegister(), base.get());
</span><span class="lines">@@ -4184,6 +4184,8 @@
</span><span class="cx">     if (generator.shouldBeConcernedWithCompletionValue() && m_statement->hasEarlyBreakOrContinue())
</span><span class="cx">         generator.emitLoad(dst, jsUndefined());
</span><span class="cx"> 
</span><ins>+    Ref<Label> end = generator.newLabel();
+
</ins><span class="cx">     RegisterID* forLoopSymbolTable = nullptr;
</span><span class="cx">     generator.pushLexicalScope(this, BytecodeGenerator::ScopeType::LetConstScope, BytecodeGenerator::TDZCheckOptimization::Optimize, BytecodeGenerator::NestedScopeType::IsNested, &forLoopSymbolTable);
</span><span class="cx"> 
</span><span class="lines">@@ -4191,11 +4193,13 @@
</span><span class="cx">         generator.emitNode(generator.ignoredResult(), m_lexpr);
</span><span class="cx"> 
</span><span class="cx">     RefPtr<RegisterID> base = generator.newTemporary();
</span><ins>+    RefPtr<RegisterID> length;
+    RefPtr<RegisterID> enumerator;
</ins><span class="cx"> 
</span><span class="cx">     generator.emitNode(base.get(), m_expr);
</span><span class="cx">     RefPtr<RegisterID> local = this->tryGetBoundLocal(generator);
</span><ins>+    RefPtr<RegisterID> enumeratorIndex;
</ins><span class="cx"> 
</span><del>-
</del><span class="cx">     std::optional<Variable> baseVariable;
</span><span class="cx">     if (m_expr->isResolveNode())
</span><span class="cx">         baseVariable = generator.variable(static_cast<ResolveNode*>(m_expr)->identifier());
</span><span class="lines">@@ -4205,46 +4209,137 @@
</span><span class="cx">         baseVariable = generator.variable(generator.propertyNames().builtinNames().thisPrivateName(), ThisResolutionType::Local);
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    // Pause at the assignment expression for each for..in iteration.
+    generator.emitDebugHook(m_lexpr);
+
</ins><span class="cx">     int profilerStartOffset = m_statement->startOffset();
</span><span class="cx">     int profilerEndOffset = m_statement->endOffset() + (m_statement->isBlock() ? 1 : 0);
</span><span class="cx"> 
</span><ins>+    enumerator = generator.emitGetPropertyEnumerator(generator.newTemporary(), base.get());
+
+    BytecodeGenerator::PreservedTDZStack preservedTDZStack;
+    generator.preserveTDZStack(preservedTDZStack);
+
+    // Indexed property loop.
</ins><span class="cx">     {
</span><del>-        RefPtr<RegisterID> enumerator = generator.newTemporary();
-        RefPtr<RegisterID> mode = generator.emitLoad(generator.newTemporary(), jsNumber(static_cast<unsigned>(JSPropertyNameEnumerator::InitMode)));
-        RefPtr<RegisterID> index = generator.emitLoad(generator.newTemporary(), jsNumber(0));
-        RefPtr<RegisterID> propertyName = generator.newTemporary();
</del><span class="cx">         Ref<LabelScope> scope = generator.newLabelScope(LabelScope::Loop);
</span><ins>+        Ref<Label> loopStart = generator.newLabel();
+        Ref<Label> loopEnd = generator.newLabel();
</ins><span class="cx"> 
</span><del>-        enumerator = generator.emitGetPropertyEnumerator(generator.newTemporary(), base.get());
-        generator.moveLinkTimeConstant(propertyName.get(), LinkTimeConstant::emptyPropertyNameEnumerator);
-        generator.emitEqualityOp<OpStricteq>(propertyName.get(), enumerator.get(), propertyName.get());
-        generator.emitJumpIfTrue(propertyName.get(), scope->breakTarget());
</del><ins>+        length = generator.emitGetEnumerableLength(generator.newTemporary(), enumerator.get());
+        RefPtr<RegisterID> i = generator.emitLoad(generator.newTemporary(), jsNumber(0));
+        RefPtr<RegisterID> propertyName = generator.newTemporary();
</ins><span class="cx"> 
</span><ins>+        generator.emitLabel(loopStart.get());
+        generator.emitLoopHint();
+
+        RefPtr<RegisterID> result = generator.emitBinaryOp<OpLess>(generator.newTemporary(), i.get(), length.get());
+        generator.emitJumpIfFalse(result.get(), loopEnd.get());
+        generator.emitHasEnumerableIndexedProperty(result.get(), base.get(), i.get());
+        generator.emitJumpIfFalse(result.get(), *scope->continueTarget());
+
+        generator.emitToIndexString(propertyName.get(), i.get());
+        this->emitLoopHeader(generator, propertyName.get());
+
+        generator.emitProfileControlFlow(profilerStartOffset);
+
+        generator.pushIndexedForInScope(local.get(), i.get());
+        generator.emitNode(dst, m_statement);
+        generator.popIndexedForInScope(local.get());
+
+        generator.emitProfileControlFlow(profilerEndOffset);
+
</ins><span class="cx">         generator.emitLabel(*scope->continueTarget());
</span><del>-        generator.emitLoopHint();
</del><span class="cx">         generator.prepareLexicalScopeForNextForLoopIteration(this, forLoopSymbolTable);
</span><ins>+        generator.emitInc(i.get());
</ins><span class="cx">         generator.emitDebugHook(m_lexpr); // Pause at the assignment expression for each for..in iteration.
</span><ins>+        generator.emitJump(loopStart.get());
</ins><span class="cx"> 
</span><del>-        // FIXME: We should have a way to see if anyone is actually using the propertyName for something other than a get_by_val. If not, we could eliminate the toString in this opcode.
-        generator.emitEnumeratorNext(propertyName.get(), mode.get(), index.get(), base.get(), enumerator.get());
</del><ins>+        generator.emitLabel(scope->breakTarget());
+        generator.emitJump(end.get());
+        generator.emitLabel(loopEnd.get());
+    }
+    generator.restoreTDZStack(preservedTDZStack);
</ins><span class="cx"> 
</span><del>-        // Note, choosing undefined or null helps please DFG's Abstract Interpreter as it doesn't distinguish null and undefined as types (via SpecOther).
-        generator.emitJumpIfTrue(generator.emitIsUndefinedOrNull(generator.newTemporary(), propertyName.get()), scope->breakTarget());
</del><ins>+    // Structure property loop.
+    {
+        Ref<LabelScope> scope = generator.newLabelScope(LabelScope::Loop);
+        Ref<Label> loopStart = generator.newLabel();
+        Ref<Label> loopEnd = generator.newLabel();
</ins><span class="cx"> 
</span><ins>+        enumeratorIndex = generator.emitLoad(generator.newTemporary(), jsNumber(0));
+        RefPtr<RegisterID> propertyName = generator.newTemporary();
+        generator.emitEnumeratorStructurePropertyName(propertyName.get(), enumerator.get(), enumeratorIndex.get());
+
+        generator.emitLabel(loopStart.get());
+        generator.emitLoopHint();
+
+        RefPtr<RegisterID> result = generator.emitIsNull(generator.newTemporary(), propertyName.get());
+        generator.emitJumpIfTrue(result.get(), loopEnd.get());
+        generator.emitHasEnumerableStructureProperty(result.get(), base.get(), propertyName.get(), enumerator.get());
+        generator.emitJumpIfFalse(result.get(), *scope->continueTarget());
+
</ins><span class="cx">         this->emitLoopHeader(generator, propertyName.get());
</span><span class="cx"> 
</span><span class="cx">         generator.emitProfileControlFlow(profilerStartOffset);
</span><span class="cx"> 
</span><del>-        generator.pushForInScope(local.get(), propertyName.get(), index.get(), enumerator.get(), mode.get(), baseVariable);
</del><ins>+        generator.pushStructureForInScope(local.get(), enumeratorIndex.get(), propertyName.get(), enumerator.get(), baseVariable);
</ins><span class="cx">         generator.emitNode(dst, m_statement);
</span><del>-        generator.popForInScope(local.get());
</del><ins>+        generator.popStructureForInScope(local.get());
</ins><span class="cx"> 
</span><span class="cx">         generator.emitProfileControlFlow(profilerEndOffset);
</span><del>-        generator.emitJump(*scope->continueTarget());
</del><span class="cx"> 
</span><ins>+        generator.emitLabel(*scope->continueTarget());
+        generator.prepareLexicalScopeForNextForLoopIteration(this, forLoopSymbolTable);
+        generator.emitInc(enumeratorIndex.get());
+        generator.emitEnumeratorStructurePropertyName(propertyName.get(), enumerator.get(), enumeratorIndex.get());
+        generator.emitDebugHook(m_lexpr); // Pause at the assignment expression for each for..in iteration.
+        generator.emitJump(loopStart.get());
+        
</ins><span class="cx">         generator.emitLabel(scope->breakTarget());
</span><ins>+        generator.emitJump(end.get());
+        generator.emitLabel(loopEnd.get());
</ins><span class="cx">     }
</span><ins>+    generator.restoreTDZStack(preservedTDZStack);
</ins><span class="cx"> 
</span><ins>+    // Generic property loop.
+    {
+        Ref<LabelScope> scope = generator.newLabelScope(LabelScope::Loop);
+        Ref<Label> loopStart = generator.newLabel();
+        Ref<Label> loopEnd = generator.newLabel();
+
+        RefPtr<RegisterID> propertyName = generator.newTemporary();
+
+        generator.emitEnumeratorGenericPropertyName(propertyName.get(), enumerator.get(), enumeratorIndex.get());
+
+        generator.emitLabel(loopStart.get());
+        generator.emitLoopHint();
+
+        RefPtr<RegisterID> result = generator.emitIsNull(generator.newTemporary(), propertyName.get());
+        generator.emitJumpIfTrue(result.get(), loopEnd.get());
+
+        generator.emitHasEnumerableProperty(result.get(), base.get(), propertyName.get());
+        generator.emitJumpIfFalse(result.get(), *scope->continueTarget());
+
+        this->emitLoopHeader(generator, propertyName.get());
+
+        generator.emitProfileControlFlow(profilerStartOffset);
+
+        generator.emitNode(dst, m_statement);
+
+        generator.emitLabel(*scope->continueTarget());
+        generator.prepareLexicalScopeForNextForLoopIteration(this, forLoopSymbolTable);
+        generator.emitInc(enumeratorIndex.get());
+        generator.emitEnumeratorGenericPropertyName(propertyName.get(), enumerator.get(), enumeratorIndex.get());
+        generator.emitDebugHook(m_lexpr); // Pause at the assignment expression for each for..in iteration.
+        generator.emitJump(loopStart.get());
+
+        generator.emitLabel(scope->breakTarget());
+        generator.emitJump(end.get());
+        generator.emitLabel(loopEnd.get());
+    }
+
+    generator.emitLabel(end.get());
</ins><span class="cx">     generator.popLexicalScope(this);
</span><span class="cx">     generator.emitProfileControlFlow(profilerEndOffset);
</span><span class="cx"> }
</span></span></pre></div>
<a id="branchessafari612128branchSourceJavaScriptCoredfgDFGAbstractInterpreterInlinesh"></a>
<div class="modfile"><h4>Modified: branches/safari-612.1.28-branch/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h (281021 => 281022)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-612.1.28-branch/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h        2021-08-13 16:39:44 UTC (rev 281021)
+++ branches/safari-612.1.28-branch/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h   2021-08-13 16:50:38 UTC (rev 281022)
</span><span class="lines">@@ -2151,14 +2151,7 @@
</span><span class="cx">     case StringCharAt:
</span><span class="cx">         setForNode(node, m_vm.stringStructure.get());
</span><span class="cx">         break;
</span><del>-
-    case EnumeratorGetByVal: {
-        // FIXME: This should be able to do code motion for OwnStructureMode but we'd need to teach AI about the enumerator's cached structure for that to be profitable.
-        clobberWorld();
-        makeHeapTopForNode(node);
-        break;
-    }
-
</del><ins>+            
</ins><span class="cx">     case GetByVal:
</span><span class="cx">     case AtomicsAdd:
</span><span class="cx">     case AtomicsAnd:
</span><span class="lines">@@ -4251,8 +4244,25 @@
</span><span class="cx">         setNonCellTypeForNode(node, SpecBoolean);
</span><span class="cx">         break;
</span><span class="cx">     }
</span><del>-
-    case HasIndexedProperty: {
</del><ins>+            
+    case GetEnumerableLength: {
+        setNonCellTypeForNode(node, SpecInt32Only);
+        break;
+    }
+    case HasEnumerableProperty: {
+        setNonCellTypeForNode(node, SpecBoolean);
+        clobberWorld();
+        break;
+    }
+    case InStructureProperty:
+    case HasOwnStructureProperty:
+    case HasEnumerableStructureProperty: {
+        setNonCellTypeForNode(node, SpecBoolean);
+        clobberWorld();
+        break;
+    }
+    case HasIndexedProperty:
+    case HasEnumerableIndexedProperty: {
</ins><span class="cx">         ArrayMode mode = node->arrayMode();
</span><span class="cx">         switch (mode.type()) {
</span><span class="cx">         case Array::Int32:
</span><span class="lines">@@ -4271,53 +4281,26 @@
</span><span class="cx">         setNonCellTypeForNode(node, SpecBoolean);
</span><span class="cx">         break;
</span><span class="cx">     }
</span><del>-
</del><ins>+    case GetDirectPname: {
+        clobberWorld();
+        makeHeapTopForNode(node);
+        break;
+    }
</ins><span class="cx">     case GetPropertyEnumerator: {
</span><span class="cx">         setTypeForNode(node, SpecCell);
</span><span class="cx">         clobberWorld();
</span><span class="cx">         break;
</span><span class="cx">     }
</span><del>-
-    case EnumeratorNextUpdateIndexAndMode: {
-        ArrayMode arrayMode = node->arrayMode();
-        if (arrayMode.isSaneChain())
-            ASSERT(node->enumeratorMetadata() == JSPropertyNameEnumerator::IndexedMode);
-        else if (node->enumeratorMetadata() != JSPropertyNameEnumerator::OwnStructureMode || m_graph.varArgChild(node, 0).useKind() != CellUse)
-            clobberWorld();
-
-        setNonCellTypeForNode(node, SpecBytecodeNumber);
</del><ins>+    case GetEnumeratorStructurePname: {
+        setTypeForNode(node, SpecString | SpecOther);
</ins><span class="cx">         break;
</span><span class="cx">     }
</span><del>-
-    case EnumeratorNextExtractMode: {
-        if (node->child1()->enumeratorMetadata() == JSPropertyNameEnumerator::IndexedMode) {
-            setConstant(node, jsNumber(static_cast<uint8_t>(JSPropertyNameEnumerator::IndexedMode)));
-            break;
-        }
-
-        if (node->child1()->enumeratorMetadata() == JSPropertyNameEnumerator::OwnStructureMode && m_graph.varArgChild(node->child1().node(), 0).useKind() == CellUse) {
-            setConstant(node, jsNumber(static_cast<uint8_t>(JSPropertyNameEnumerator::OwnStructureMode)));
-            break;
-        }
-
-        FALLTHROUGH;
-    }
-    case EnumeratorNextExtractIndex: {
-        setNonCellTypeForNode(node, SpecInt32Only);
-        break;
-    }
-
-    case EnumeratorNextUpdatePropertyName: {
</del><ins>+    case GetEnumeratorGenericPname: {
</ins><span class="cx">         setTypeForNode(node, SpecString | SpecOther);
</span><span class="cx">         break;
</span><span class="cx">     }
</span><del>-
-    case EnumeratorInByVal:
-    case EnumeratorHasOwnProperty: {
-        // FIXME: We can determine when the property definitely exists based on abstract
-        // value information.
-        clobberWorld();
-        setNonCellTypeForNode(node, SpecBoolean);
</del><ins>+    case ToIndexString: {
+        setTypeForNode(node, SpecString);
</ins><span class="cx">         break;
</span><span class="cx">     }
</span><span class="cx"> 
</span></span></pre></div>
<a id="branchessafari612128branchSourceJavaScriptCoredfgDFGArrayModeh"></a>
<div class="modfile"><h4>Modified: branches/safari-612.1.28-branch/Source/JavaScriptCore/dfg/DFGArrayMode.h (281021 => 281022)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-612.1.28-branch/Source/JavaScriptCore/dfg/DFGArrayMode.h 2021-08-13 16:39:44 UTC (rev 281021)
+++ branches/safari-612.1.28-branch/Source/JavaScriptCore/dfg/DFGArrayMode.h    2021-08-13 16:50:38 UTC (rev 281022)
</span><span class="lines">@@ -289,11 +289,6 @@
</span><span class="cx">         return speculation() == Array::OutOfBoundsSaneChain;
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    bool isSaneChain() const
-    {
-        return isInBoundsSaneChain() || isOutOfBoundsSaneChain();
-    }
-
</del><span class="cx">     bool isOutOfBounds() const
</span><span class="cx">     {
</span><span class="cx">         return speculation() == Array::OutOfBounds || speculation() == Array::OutOfBoundsSaneChain;
</span></span></pre></div>
<a id="branchessafari612128branchSourceJavaScriptCoredfgDFGBackwardsPropagationPhasecpp"></a>
<div class="modfile"><h4>Modified: branches/safari-612.1.28-branch/Source/JavaScriptCore/dfg/DFGBackwardsPropagationPhase.cpp (281021 => 281022)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-612.1.28-branch/Source/JavaScriptCore/dfg/DFGBackwardsPropagationPhase.cpp       2021-08-13 16:39:44 UTC (rev 281021)
+++ branches/safari-612.1.28-branch/Source/JavaScriptCore/dfg/DFGBackwardsPropagationPhase.cpp  2021-08-13 16:50:38 UTC (rev 281022)
</span><span class="lines">@@ -390,8 +390,7 @@
</span><span class="cx">             node->child2()->mergeFlags(flags & ~NodeBytecodeNeedsNegZero);
</span><span class="cx">             break;
</span><span class="cx">         }
</span><del>-
-        case EnumeratorGetByVal:
</del><ins>+            
</ins><span class="cx">         case GetByVal: {
</span><span class="cx">             m_graph.varArgChild(node, 0)->mergeFlags(NodeBytecodeUsesAsValue);
</span><span class="cx">             m_graph.varArgChild(node, 1)->mergeFlags(NodeBytecodeUsesAsNumber | NodeBytecodeUsesAsOther | NodeBytecodeUsesAsInt | NodeBytecodeUsesAsArrayIndex);
</span></span></pre></div>
<a id="branchessafari612128branchSourceJavaScriptCoredfgDFGByteCodeParsercpp"></a>
<div class="modfile"><h4>Modified: branches/safari-612.1.28-branch/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp (281021 => 281022)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-612.1.28-branch/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp  2021-08-13 16:39:44 UTC (rev 281021)
+++ branches/safari-612.1.28-branch/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp     2021-08-13 16:50:38 UTC (rev 281022)
</span><span class="lines">@@ -8387,137 +8387,104 @@
</span><span class="cx">             NEXT_OPCODE(op_has_private_brand);
</span><span class="cx">         }
</span><span class="cx"> 
</span><del>-        case op_get_property_enumerator: {
-            auto bytecode = currentInstruction->as<OpGetPropertyEnumerator>();
-            set(bytecode.m_dst, addToGraph(GetPropertyEnumerator, get(bytecode.m_base)));
-            NEXT_OPCODE(op_get_property_enumerator);
</del><ins>+        case op_get_enumerable_length: {
+            auto bytecode = currentInstruction->as<OpGetEnumerableLength>();
+            set(bytecode.m_dst, addToGraph(GetEnumerableLength, get(bytecode.m_base)));
+            NEXT_OPCODE(op_get_enumerable_length);
</ins><span class="cx">         }
</span><span class="cx"> 
</span><del>-        case op_enumerator_next: {
-            auto bytecode = currentInstruction->as<OpEnumeratorNext>();
-            auto& metadata = bytecode.metadata(codeBlock);
-            ArrayMode arrayMode = getArrayMode(metadata.m_arrayProfile, Array::Read);
-            Node* base = get(bytecode.m_base);
-            Node* index = get(bytecode.m_index);
-            Node* enumerator = get(bytecode.m_enumerator);
-            Node* mode = get(bytecode.m_mode);
</del><ins>+        case op_has_enumerable_structure_property: {
+            auto bytecode = currentInstruction->as<OpHasEnumerableStructureProperty>();
+            set(bytecode.m_dst, addToGraph(HasEnumerableStructureProperty,
+                get(bytecode.m_base),
+                get(bytecode.m_property),
+                get(bytecode.m_enumerator)));
+            NEXT_OPCODE(op_has_enumerable_structure_property);
+        }
</ins><span class="cx"> 
</span><del>-            auto seenModes = OptionSet<JSPropertyNameEnumerator::Mode>::fromRaw(metadata.m_enumeratorMetadata);
</del><ins>+        case op_has_enumerable_property: {
+            auto bytecode = currentInstruction->as<OpHasEnumerableProperty>();
+            set(bytecode.m_dst, addToGraph(HasEnumerableProperty, get(bytecode.m_base), get(bytecode.m_property)));
+            NEXT_OPCODE(op_has_enumerable_property);
+        }
</ins><span class="cx"> 
</span><del>-            if (!seenModes)
-                addToGraph(ForceOSRExit);
</del><ins>+        case op_has_own_structure_property: {
+            auto bytecode = currentInstruction->as<OpHasOwnStructureProperty>();
+            set(bytecode.m_dst, addToGraph(HasOwnStructureProperty,
+                get(bytecode.m_base),
+                get(bytecode.m_property),
+                get(bytecode.m_enumerator)));
+            NEXT_OPCODE(op_has_own_structure_property);
+        }
</ins><span class="cx"> 
</span><ins>+        case op_in_structure_property: {
+            auto bytecode = currentInstruction->as<OpInStructureProperty>();
+            set(bytecode.m_dst, addToGraph(InStructureProperty,
+                get(bytecode.m_base),
+                get(bytecode.m_property),
+                get(bytecode.m_enumerator)));
+            NEXT_OPCODE(op_in_structure_property);
+        }
+
+        case op_has_enumerable_indexed_property: {
+            auto bytecode = currentInstruction->as<OpHasEnumerableIndexedProperty>();
+            Node* base = get(bytecode.m_base);
+            ArrayMode arrayMode = getArrayMode(bytecode.metadata(codeBlock).m_arrayProfile, Array::Read);
+            Node* property = get(bytecode.m_property);
</ins><span class="cx">             addVarArgChild(base);
</span><del>-            addVarArgChild(index);
-            addVarArgChild(mode);
-            addVarArgChild(enumerator);
-            addVarArgChild(nullptr); // storage for IndexedMode only.
-            Node* updatedIndexAndMode = addToGraph(Node::VarArg, EnumeratorNextUpdateIndexAndMode, OpInfo(arrayMode.asWord()), OpInfo(seenModes));
-
-            Node* updatedMode = addToGraph(EnumeratorNextExtractMode, updatedIndexAndMode);
-            set(bytecode.m_mode, updatedMode);
-
-            Node* updatedIndex = addToGraph(EnumeratorNextExtractIndex, updatedIndexAndMode);
-            set(bytecode.m_index, updatedIndex);
-
-            set(bytecode.m_propertyName, addToGraph(EnumeratorNextUpdatePropertyName, OpInfo(), OpInfo(seenModes), updatedIndex, updatedMode, enumerator));
-
-            NEXT_OPCODE(op_enumerator_next);
</del><ins>+            addVarArgChild(property);
+            addVarArgChild(nullptr);
+            Node* hasIterableProperty = addToGraph(Node::VarArg, HasEnumerableIndexedProperty, OpInfo(arrayMode.asWord()));
+            m_exitOK = false; // HasIndexedProperty must be treated as if it clobbers exit state, since FixupPhase may make it generic.
+            set(bytecode.m_dst, hasIterableProperty);
+            NEXT_OPCODE(op_has_enumerable_indexed_property);
</ins><span class="cx">         }
</span><span class="cx"> 
</span><del>-        case op_enumerator_get_by_val: {
-            auto bytecode = currentInstruction->as<OpEnumeratorGetByVal>();
-            auto& metadata = bytecode.metadata(codeBlock);
-            ArrayMode arrayMode = getArrayMode(metadata.m_arrayProfile, Array::Read);
-            SpeculatedType speculation = getPredictionWithoutOSRExit();
-
</del><ins>+        case op_get_direct_pname: {
+            auto bytecode = currentInstruction->as<OpGetDirectPname>();
+            SpeculatedType prediction = getPredictionWithoutOSRExit();
+            
</ins><span class="cx">             Node* base = get(bytecode.m_base);
</span><del>-            Node* propertyName = get(bytecode.m_propertyName);
</del><ins>+            Node* property = get(bytecode.m_property);
</ins><span class="cx">             Node* index = get(bytecode.m_index);
</span><del>-            Node* mode = get(bytecode.m_mode);
</del><span class="cx">             Node* enumerator = get(bytecode.m_enumerator);
</span><span class="cx"> 
</span><del>-            auto seenModes = OptionSet<JSPropertyNameEnumerator::Mode>::fromRaw(metadata.m_enumeratorMetadata);
-            if (!seenModes)
-                addToGraph(ForceOSRExit);
-
-            if (seenModes == JSPropertyNameEnumerator::IndexedMode) {
-                Node* badMode = addToGraph(ArithBitAnd, mode, jsConstant(jsNumber(JSPropertyNameEnumerator::GenericMode | JSPropertyNameEnumerator::OwnStructureMode)));
-
-                // We know the ArithBitAnd cannot have effects so it's ok to exit here.
-                m_exitOK = true;
-                addToGraph(ExitOK);
-
-                addToGraph(CheckIsConstant, OpInfo(m_graph.freezeStrong(jsNumber(0))), badMode);
-
-                addVarArgChild(base);
-                addVarArgChild(index); // Use index so we'll use the normal indexed optimizations.
-                addVarArgChild(nullptr); // For property storage to match GetByVal.
-                set(bytecode.m_dst, addToGraph(Node::VarArg, GetByVal, OpInfo(arrayMode.asWord()), OpInfo(speculation)));
-
-                addToGraph(Phantom, propertyName);
-                addToGraph(Phantom, enumerator);
-                NEXT_OPCODE(op_enumerator_get_by_val);
-            }
-
-            // FIXME: Checking for a BadConstantValue causes us to always use the Generic variant if we switched from IndexedMode -> IndexedMode + OwnStructureMode even though that might be fine.
-            if (!seenModes.containsAny({ JSPropertyNameEnumerator::GenericMode, JSPropertyNameEnumerator::HasSeenOwnStructureModeStructureMismatch })
-                && !m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadConstantValue)) {
-                Node* modeTest = addToGraph(SameValue, mode, jsConstant(jsNumber(static_cast<uint8_t>(JSPropertyNameEnumerator::GenericMode))));
-                addToGraph(CheckIsConstant, OpInfo(m_graph.freezeStrong(jsBoolean(false))), modeTest);
-
-                addVarArgChild(base);
-                addVarArgChild(index); // Use index so we'll use the normal indexed optimizations.
-                addVarArgChild(nullptr); // For property storage to match GetByVal.
-                addVarArgChild(index);
-                addVarArgChild(mode);
-                addVarArgChild(enumerator);
-                set(bytecode.m_dst, addToGraph(Node::VarArg, EnumeratorGetByVal, OpInfo(arrayMode.asWord()), OpInfo(speculation)));
-
-                addToGraph(Phantom, propertyName);
-                NEXT_OPCODE(op_enumerator_get_by_val);
-            }
-
</del><span class="cx">             addVarArgChild(base);
</span><del>-            addVarArgChild(propertyName);
-            addVarArgChild(nullptr); // For property storage to match GetByVal.
</del><ins>+            addVarArgChild(property);
</ins><span class="cx">             addVarArgChild(index);
</span><del>-            addVarArgChild(mode);
</del><span class="cx">             addVarArgChild(enumerator);
</span><del>-            set(bytecode.m_dst, addToGraph(Node::VarArg, EnumeratorGetByVal, OpInfo(arrayMode.asWord()), OpInfo(speculation)));
</del><ins>+            set(bytecode.m_dst, addToGraph(Node::VarArg, GetDirectPname, OpInfo(0), OpInfo(prediction)));
</ins><span class="cx"> 
</span><del>-            NEXT_OPCODE(op_enumerator_get_by_val);
</del><ins>+            NEXT_OPCODE(op_get_direct_pname);
</ins><span class="cx">         }
</span><span class="cx"> 
</span><del>-        case op_enumerator_in_by_val: {
-            auto bytecode = currentInstruction->as<OpEnumeratorInByVal>();
-            auto& metadata = bytecode.metadata(codeBlock);
-            ArrayMode arrayMode = getArrayMode(metadata.m_arrayProfile, Array::Read);
</del><ins>+        case op_get_property_enumerator: {
+            auto bytecode = currentInstruction->as<OpGetPropertyEnumerator>();
+            set(bytecode.m_dst, addToGraph(GetPropertyEnumerator, get(bytecode.m_base)));
+            NEXT_OPCODE(op_get_property_enumerator);
+        }
</ins><span class="cx"> 
</span><del>-            addVarArgChild(get(bytecode.m_base));
-            addVarArgChild(get(bytecode.m_propertyName));
-            addVarArgChild(get(bytecode.m_index));
-            addVarArgChild(get(bytecode.m_mode));
-            addVarArgChild(get(bytecode.m_enumerator));
-            set(bytecode.m_dst, addToGraph(Node::VarArg, EnumeratorInByVal, OpInfo(arrayMode.asWord()), OpInfo(metadata.m_enumeratorMetadata)));
-
-            NEXT_OPCODE(op_enumerator_in_by_val);
</del><ins>+        case op_enumerator_structure_pname: {
+            auto bytecode = currentInstruction->as<OpEnumeratorStructurePname>();
+            set(bytecode.m_dst, addToGraph(GetEnumeratorStructurePname,
+                get(bytecode.m_enumerator),
+                get(bytecode.m_index)));
+            NEXT_OPCODE(op_enumerator_structure_pname);
</ins><span class="cx">         }
</span><span class="cx"> 
</span><del>-        case op_enumerator_has_own_property: {
-            auto bytecode = currentInstruction->as<OpEnumeratorHasOwnProperty>();
-            auto& metadata = bytecode.metadata(codeBlock);
-            ArrayMode arrayMode = getArrayMode(metadata.m_arrayProfile, Array::Read);
-
-            addVarArgChild(get(bytecode.m_base));
-            addVarArgChild(get(bytecode.m_propertyName));
-            addVarArgChild(get(bytecode.m_index));
-            addVarArgChild(get(bytecode.m_mode));
-            addVarArgChild(get(bytecode.m_enumerator));
-            set(bytecode.m_dst, addToGraph(Node::VarArg, EnumeratorHasOwnProperty, OpInfo(arrayMode.asWord()), OpInfo(metadata.m_enumeratorMetadata)));
-
-            NEXT_OPCODE(op_enumerator_has_own_property);
</del><ins>+        case op_enumerator_generic_pname: {
+            auto bytecode = currentInstruction->as<OpEnumeratorGenericPname>();
+            set(bytecode.m_dst, addToGraph(GetEnumeratorGenericPname,
+                get(bytecode.m_enumerator),
+                get(bytecode.m_index)));
+            NEXT_OPCODE(op_enumerator_generic_pname);
</ins><span class="cx">         }
</span><ins>+            
+        case op_to_index_string: {
+            auto bytecode = currentInstruction->as<OpToIndexString>();
+            set(bytecode.m_dst, addToGraph(ToIndexString, get(bytecode.m_index)));
+            NEXT_OPCODE(op_to_index_string);
+        }
</ins><span class="cx"> 
</span><span class="cx">         case op_get_internal_field: {
</span><span class="cx">             auto bytecode = currentInstruction->as<OpGetInternalField>();
</span></span></pre></div>
<a id="branchessafari612128branchSourceJavaScriptCoredfgDFGCFAPhasecpp"></a>
<div class="modfile"><h4>Modified: branches/safari-612.1.28-branch/Source/JavaScriptCore/dfg/DFGCFAPhase.cpp (281021 => 281022)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-612.1.28-branch/Source/JavaScriptCore/dfg/DFGCFAPhase.cpp        2021-08-13 16:39:44 UTC (rev 281021)
+++ branches/safari-612.1.28-branch/Source/JavaScriptCore/dfg/DFGCFAPhase.cpp   2021-08-13 16:50:38 UTC (rev 281022)
</span><span class="lines">@@ -164,7 +164,7 @@
</span><span class="cx">             dataLog("   Found must-handle block: ", *block, "\n");
</span><span class="cx">         
</span><span class="cx">         // This merges snapshot of stack values while CFA phase want to have proven types and values. This is somewhat tricky.
</span><del>-        // But this is OK as long as DFG OSR entry validates the inputs with *proven* AbstractValue values. And it turns out that this
</del><ins>+        // But this is OK as long as DFG OSR entry validates the inputs with *proven* AbstracValue values. And it turns out that this
</ins><span class="cx">         // type widening is critical to navier-stokes. Without it, navier-stokes has more strict constraint on OSR entry and
</span><span class="cx">         // fails OSR entry repeatedly.
</span><span class="cx">         bool changed = false;
</span></span></pre></div>
<a id="branchessafari612128branchSourceJavaScriptCoredfgDFGCapabilitiescpp"></a>
<div class="modfile"><h4>Modified: branches/safari-612.1.28-branch/Source/JavaScriptCore/dfg/DFGCapabilities.cpp (281021 => 281022)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-612.1.28-branch/Source/JavaScriptCore/dfg/DFGCapabilities.cpp    2021-08-13 16:39:44 UTC (rev 281021)
+++ branches/safari-612.1.28-branch/Source/JavaScriptCore/dfg/DFGCapabilities.cpp       2021-08-13 16:50:38 UTC (rev 281022)
</span><span class="lines">@@ -254,7 +254,17 @@
</span><span class="cx">     case op_has_private_brand:
</span><span class="cx">     case op_get_scope:
</span><span class="cx">     case op_get_from_scope:
</span><ins>+    case op_get_enumerable_length:
+    case op_has_enumerable_indexed_property:
+    case op_has_enumerable_structure_property:
+    case op_has_enumerable_property:
+    case op_has_own_structure_property:
+    case op_in_structure_property:
+    case op_get_direct_pname:
</ins><span class="cx">     case op_get_property_enumerator:
</span><ins>+    case op_enumerator_structure_pname:
+    case op_enumerator_generic_pname:
+    case op_to_index_string:
</ins><span class="cx">     case op_new_func:
</span><span class="cx">     case op_new_func_exp:
</span><span class="cx">     case op_new_generator_func:
</span><span class="lines">@@ -289,10 +299,6 @@
</span><span class="cx">     case op_set_private_brand:
</span><span class="cx">     case op_check_private_brand:
</span><span class="cx">     case op_switch_string:
</span><del>-    case op_enumerator_next:
-    case op_enumerator_get_by_val:
-    case op_enumerator_in_by_val:
-    case op_enumerator_has_own_property:
</del><span class="cx">         return CanCompileAndInline;
</span><span class="cx"> 
</span><span class="cx">     case op_call_eval:
</span></span></pre></div>
<a id="branchessafari612128branchSourceJavaScriptCoredfgDFGClobberizeh"></a>
<div class="modfile"><h4>Modified: branches/safari-612.1.28-branch/Source/JavaScriptCore/dfg/DFGClobberize.h (281021 => 281022)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-612.1.28-branch/Source/JavaScriptCore/dfg/DFGClobberize.h        2021-08-13 16:39:44 UTC (rev 281021)
+++ branches/safari-612.1.28-branch/Source/JavaScriptCore/dfg/DFGClobberize.h   2021-08-13 16:50:38 UTC (rev 281022)
</span><span class="lines">@@ -147,10 +147,6 @@
</span><span class="cx">         case CheckArray:
</span><span class="cx">         case CheckArrayOrEmpty:
</span><span class="cx">             break;
</span><del>-        case EnumeratorNextUpdateIndexAndMode:
-        case EnumeratorGetByVal:
-        case EnumeratorInByVal:
-        case EnumeratorHasOwnProperty:
</del><span class="cx">         case GetIndexedPropertyStorage:
</span><span class="cx">         case GetArrayLength:
</span><span class="cx">         case GetVectorLength:
</span><span class="lines">@@ -168,6 +164,7 @@
</span><span class="cx">         case ArrayPop:
</span><span class="cx">         case ArrayIndexOf:
</span><span class="cx">         case HasIndexedProperty:
</span><ins>+        case HasEnumerableIndexedProperty:
</ins><span class="cx">         case AtomicsAdd:
</span><span class="cx">         case AtomicsAnd:
</span><span class="cx">         case AtomicsCompareExchange:
</span><span class="lines">@@ -340,30 +337,22 @@
</span><span class="cx">         write(MathDotRandomState);
</span><span class="cx">         return;
</span><span class="cx"> 
</span><del>-    case EnumeratorNextUpdatePropertyName: {
-        def(PureValue(node, node->enumeratorMetadata().toRaw()));
</del><ins>+    case GetEnumerableLength: {
+        read(Heap);
+        write(SideState);
</ins><span class="cx">         return;
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    case EnumeratorNextExtractMode:
-    case EnumeratorNextExtractIndex: {
</del><ins>+    case ToIndexString:
+    case GetEnumeratorStructurePname:
+    case GetEnumeratorGenericPname: {
</ins><span class="cx">         def(PureValue(node));
</span><span class="cx">         return;
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    case EnumeratorNextUpdateIndexAndMode: {
</del><ins>+    case HasIndexedProperty:
+    case HasEnumerableIndexedProperty: {
</ins><span class="cx">         read(JSObject_butterfly);
</span><del>-        if (node->enumeratorMetadata() == JSPropertyNameEnumerator::OwnStructureMode && graph.varArgChild(node, 0).useKind() == CellUse) {
-            read(NamedProperties);
-            read(JSCell_structureID);
-            return;
-        }
-
-        if (node->enumeratorMetadata() != JSPropertyNameEnumerator::IndexedMode) {
-            clobberTop();
-            return;
-        }
-
</del><span class="cx">         ArrayMode mode = node->arrayMode();
</span><span class="cx">         switch (mode.type()) {
</span><span class="cx">         case Array::ForceExit: {
</span><span class="lines">@@ -371,62 +360,7 @@
</span><span class="cx">             return;
</span><span class="cx">         }
</span><span class="cx">         case Array::Int32: {
</span><del>-            if (mode.isSaneChain()) {
-                read(Butterfly_publicLength);
-                read(IndexedInt32Properties);
-                def(HeapLocation(HasIndexedPropertyLoc, IndexedInt32Properties, graph.varArgChild(node, 0), graph.varArgChild(node, 1)), LazyNode(node));
-                return;
-            }
-            break;
-        }
-
-        case Array::Double: {
-            if (mode.isSaneChain()) {
-                read(Butterfly_publicLength);
-                read(IndexedDoubleProperties);
-                def(HeapLocation(HasIndexedPropertyLoc, IndexedDoubleProperties, graph.varArgChild(node, 0), graph.varArgChild(node, 1)), LazyNode(node));
-                return;
-            }
-            break;
-        }
-
-        case Array::Contiguous: {
-            if (mode.isSaneChain()) {
-                read(Butterfly_publicLength);
-                read(IndexedContiguousProperties);
-                def(HeapLocation(HasIndexedPropertyLoc, IndexedContiguousProperties, graph.varArgChild(node, 0), graph.varArgChild(node, 1)), LazyNode(node));
-                return;
-            }
-            break;
-        }
-
-        case Array::ArrayStorage: {
</del><span class="cx">             if (mode.isInBounds()) {
</span><del>-                read(Butterfly_vectorLength);
-                read(IndexedArrayStorageProperties);
-                return;
-            }
-            break;
-        }
-
-        default:
-            break;
-        }
-
-        clobberTop();
-        return;
-    }
-
-    case HasIndexedProperty: {
-        read(JSObject_butterfly);
-        ArrayMode mode = node->arrayMode();
-        switch (mode.type()) {
-        case Array::ForceExit: {
-            write(SideState);
-            return;
-        }
-        case Array::Int32: {
-            if (mode.isInBounds()) {
</del><span class="cx">                 read(Butterfly_publicLength);
</span><span class="cx">                 read(IndexedInt32Properties);
</span><span class="cx">                 def(HeapLocation(HasIndexedPropertyLoc, IndexedInt32Properties, graph.varArgChild(node, 0), graph.varArgChild(node, 1)), LazyNode(node));
</span><span class="lines">@@ -771,8 +705,6 @@
</span><span class="cx">     case ToPrimitive:
</span><span class="cx">     case ToPropertyKey:
</span><span class="cx">     case InByVal:
</span><del>-    case EnumeratorInByVal:
-    case EnumeratorHasOwnProperty:
</del><span class="cx">     case InById:
</span><span class="cx">     case HasPrivateName:
</span><span class="cx">     case HasPrivateBrand:
</span><span class="lines">@@ -784,7 +716,12 @@
</span><span class="cx">     case ResolveScopeForHoistingFuncDeclInEval:
</span><span class="cx">     case ResolveScope:
</span><span class="cx">     case ToObject:
</span><ins>+    case HasEnumerableStructureProperty:
+    case HasEnumerableProperty:
+    case HasOwnStructureProperty:
+    case InStructureProperty:
</ins><span class="cx">     case GetPropertyEnumerator:
</span><ins>+    case GetDirectPname:
</ins><span class="cx">     case InstanceOfCustom:
</span><span class="cx">     case ToNumber:
</span><span class="cx">     case ToNumeric:
</span><span class="lines">@@ -969,11 +906,6 @@
</span><span class="cx">             write(AbstractHeap(Stack, data->start + static_cast<int>(i)));
</span><span class="cx">         return;
</span><span class="cx">     }
</span><del>-
-    case EnumeratorGetByVal: {
-        clobberTop();
-        return;
-    }
</del><span class="cx">         
</span><span class="cx">     case GetByVal: {
</span><span class="cx">         ArrayMode mode = node->arrayMode();
</span></span></pre></div>
<a id="branchessafari612128branchSourceJavaScriptCoredfgDFGDoesGCcpp"></a>
<div class="modfile"><h4>Modified: branches/safari-612.1.28-branch/Source/JavaScriptCore/dfg/DFGDoesGC.cpp (281021 => 281022)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-612.1.28-branch/Source/JavaScriptCore/dfg/DFGDoesGC.cpp  2021-08-13 16:39:44 UTC (rev 281021)
+++ branches/safari-612.1.28-branch/Source/JavaScriptCore/dfg/DFGDoesGC.cpp     2021-08-13 16:50:38 UTC (rev 281022)
</span><span class="lines">@@ -205,6 +205,7 @@
</span><span class="cx">     case PutStructure:
</span><span class="cx">     case GetByOffset:
</span><span class="cx">     case GetGetterSetterByOffset:
</span><ins>+    case GetEnumerableLength:
</ins><span class="cx">     case FiatInt52:
</span><span class="cx">     case BooleanToNumber:
</span><span class="cx">     case CheckBadValue:
</span><span class="lines">@@ -296,10 +297,16 @@
</span><span class="cx">     case GetByIdFlush:
</span><span class="cx">     case GetByIdWithThis:
</span><span class="cx">     case GetByValWithThis:
</span><ins>+    case GetDirectPname:
</ins><span class="cx">     case GetDynamicVar:
</span><span class="cx">     case GetMapBucket:
</span><span class="cx">     case HasIndexedProperty:
</span><ins>+    case HasEnumerableIndexedProperty:
+    case HasEnumerableStructureProperty:
+    case HasEnumerableProperty:
</ins><span class="cx">     case HasOwnProperty:
</span><ins>+    case HasOwnStructureProperty:
+    case InStructureProperty:
</ins><span class="cx">     case InById:
</span><span class="cx">     case InByVal:
</span><span class="cx">     case HasPrivateName:
</span><span class="lines">@@ -385,10 +392,9 @@
</span><span class="cx">     case NewTypedArray:
</span><span class="cx">     case ThrowStaticError:
</span><span class="cx">     case GetPropertyEnumerator:
</span><del>-    case EnumeratorInByVal:
-    case EnumeratorHasOwnProperty:
-    case EnumeratorNextUpdatePropertyName:
-    case EnumeratorNextUpdateIndexAndMode:
</del><ins>+    case GetEnumeratorStructurePname:
+    case GetEnumeratorGenericPname:
+    case ToIndexString:
</ins><span class="cx">     case MaterializeNewObject:
</span><span class="cx">     case MaterializeNewInternalFieldObject:
</span><span class="cx">     case MaterializeCreateActivation:
</span><span class="lines">@@ -498,15 +504,10 @@
</span><span class="cx"> 
</span><span class="cx">     case GetIndexedPropertyStorage:
</span><span class="cx">     case GetByVal:
</span><del>-    case EnumeratorGetByVal:
</del><span class="cx">         if (node->arrayMode().type() == Array::String)
</span><span class="cx">             return true;
</span><span class="cx">         return false;
</span><span class="cx"> 
</span><del>-    case EnumeratorNextExtractMode:
-    case EnumeratorNextExtractIndex:
-        return false;
-
</del><span class="cx">     case PutByValDirect:
</span><span class="cx">     case PutByVal:
</span><span class="cx">     case PutByValAlias:
</span></span></pre></div>
<a id="branchessafari612128branchSourceJavaScriptCoredfgDFGFixupPhasecpp"></a>
<div class="modfile"><h4>Modified: branches/safari-612.1.28-branch/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp (281021 => 281022)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-612.1.28-branch/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp      2021-08-13 16:39:44 UTC (rev 281021)
+++ branches/safari-612.1.28-branch/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp 2021-08-13 16:50:38 UTC (rev 281022)
</span><span class="lines">@@ -1024,13 +1024,6 @@
</span><span class="cx">             break;
</span><span class="cx">         }
</span><span class="cx"> 
</span><del>-        case EnumeratorGetByVal: {
-            fixEdge<KnownInt32Use>(m_graph.varArgChild(node, 3));
-            fixEdge<KnownInt32Use>(m_graph.varArgChild(node, 4));
-            fixEdge<KnownCellUse>(m_graph.varArgChild(node, 5));
-            FALLTHROUGH;
-        }
-
</del><span class="cx">         case GetByVal: {
</span><span class="cx">             if (!node->prediction()) {
</span><span class="cx">                 m_insertionSet.insertNode(
</span><span class="lines">@@ -1069,15 +1062,6 @@
</span><span class="cx">                 // https://bugs.webkit.org/show_bug.cgi?id=221172
</span><span class="cx">                 node->setArrayMode(ArrayMode(Array::Generic, node->arrayMode().action()));
</span><span class="cx">                 break;
</span><del>-
-
-            case Array::ForceExit: {
-                // Don't force OSR because we have only seen OwnStructureMode.
-                // FIXME: WE should have a better way to do this...
-                if (node->op() == EnumeratorGetByVal)
-                    node->setArrayMode(node->arrayMode().withType(Array::Generic));
-                break;
-            }
</del><span class="cx">             default:
</span><span class="cx">                 break;
</span><span class="cx">             }
</span><span class="lines">@@ -1089,7 +1073,63 @@
</span><span class="cx">             case Array::Contiguous:
</span><span class="cx">             case Array::Double:
</span><span class="cx">             case Array::Int32: {
</span><del>-                setJSArraySaneChainIfPossible(node);
</del><ins>+                std::optional<Array::Speculation> saneChainSpeculation;
+                if (arrayMode.isJSArrayWithOriginalStructure()) {
+                    // Check if InBoundsSaneChain will work on a per-type basis. Note that:
+                    //
+                    // 1) We don't want double arrays to sometimes return undefined, since
+                    // that would require a change to the return type and it would pessimise
+                    // things a lot. So, we'd only want to do that if we actually had
+                    // evidence that we could read from a hole. That's pretty annoying.
+                    // Likely the best way to handle that case is with an equivalent of
+                    // InBoundsSaneChain for OutOfBounds. For now we just detect when Undefined and
+                    // NaN are indistinguishable according to backwards propagation, and just
+                    // use InBoundsSaneChain in that case. This happens to catch a lot of cases.
+                    //
+                    // 2) We don't want int32 array loads to have to do a hole check just to
+                    // coerce to Undefined, since that would mean twice the checks. We want to
+                    // be able to say we always return Int32. FIXME: Maybe this should be profiling
+                    // based?
+                    //
+                    // This has two implications. First, we have to do more checks than we'd
+                    // like. It's unfortunate that we have to do the hole check. Second,
+                    // some accesses that hit a hole will now need to take the full-blown
+                    // out-of-bounds slow path. We can fix that with:
+                    // https://bugs.webkit.org/show_bug.cgi?id=144668
+                    
+                    switch (arrayMode.type()) {
+                    case Array::Int32:
+                        if (is64Bit() && arrayMode.speculation() == Array::OutOfBounds && !m_graph.hasExitSite(node->origin.semantic, NegativeIndex))
+                            saneChainSpeculation = Array::OutOfBoundsSaneChain;
+                        break;
+                    case Array::Contiguous:
+                        // This is happens to be entirely natural. We already would have
+                        // returned any JSValue, and now we'll return Undefined. We still do
+                        // the check but it doesn't require taking any kind of slow path.
+                        if (is64Bit() && arrayMode.speculation() == Array::OutOfBounds && !m_graph.hasExitSite(node->origin.semantic, NegativeIndex))
+                            saneChainSpeculation = Array::OutOfBoundsSaneChain;
+                        else if (arrayMode.speculation() == Array::InBounds)
+                            saneChainSpeculation = Array::InBoundsSaneChain;
+                        break;
+                        
+                    case Array::Double:
+                        if (!(node->flags() & NodeBytecodeUsesAsOther) && arrayMode.speculation() == Array::InBounds) {
+                            // Holes look like NaN already, so if the user doesn't care
+                            // about the difference between Undefined and NaN then we can
+                            // do this.
+                            saneChainSpeculation = Array::InBoundsSaneChain;
+                        } else if (is64Bit() && arrayMode.speculation() == Array::OutOfBounds && !m_graph.hasExitSite(node->origin.semantic, NegativeIndex))
+                            saneChainSpeculation = Array::OutOfBoundsSaneChain;
+                        break;
+                        
+                    default:
+                        break;
+                    }
+                }
+
+                if (saneChainSpeculation)
+                    setSaneChainIfPossible(node, *saneChainSpeculation);
+
</ins><span class="cx">                 break;
</span><span class="cx">             }
</span><span class="cx">                 
</span><span class="lines">@@ -1138,11 +1178,7 @@
</span><span class="cx">                 fixEdge<Int32Use>(m_graph.varArgChild(node, 1));
</span><span class="cx">                 break;
</span><span class="cx">             }
</span><del>-
-            // Don't set a non-JSValue result for EnumeratorGetByVal as the indexing mode doesn't tell us about the type of OwnStructure
-            // properties. This isn't an issue for IndexedMode only as BytecodeParsing will emit a normal GetByVal if we've profiled that.
-            if (node->op() == EnumeratorGetByVal)
-                break;
</del><ins>+            
</ins><span class="cx">             switch (arrayMode.type()) {
</span><span class="cx">             case Array::Double:
</span><span class="cx">                 if (!arrayMode.isOutOfBounds()
</span><span class="lines">@@ -2239,7 +2275,28 @@
</span><span class="cx">             break;
</span><span class="cx">         }
</span><span class="cx"> 
</span><del>-        case HasIndexedProperty: {
</del><ins>+        case GetEnumerableLength: {
+            fixEdge<CellUse>(node->child1());
+            break;
+        }
+        case HasEnumerableProperty: {
+            fixEdge<CellUse>(node->child2());
+            break;
+        }
+        case HasEnumerableStructureProperty: {
+            fixEdge<StringUse>(node->child2());
+            fixEdge<KnownCellUse>(node->child3());
+            break;
+        }
+        case HasOwnStructureProperty:
+        case InStructureProperty: {
+            fixEdge<CellUse>(node->child1());
+            fixEdge<KnownStringUse>(node->child2());
+            fixEdge<KnownCellUse>(node->child3());
+            break;
+        }
+        case HasIndexedProperty:
+        case HasEnumerableIndexedProperty: {
</ins><span class="cx">             node->setArrayMode(
</span><span class="cx">                 node->arrayMode().refine(
</span><span class="cx">                     m_graph, node,
</span><span class="lines">@@ -2258,64 +2315,36 @@
</span><span class="cx">                 setSaneChainIfPossible(node, Array::InBoundsSaneChain);
</span><span class="cx">             break;
</span><span class="cx">         }
</span><del>-
</del><ins>+        case GetDirectPname: {
+            Edge& base = m_graph.varArgChild(node, 0);
+            Edge& property = m_graph.varArgChild(node, 1);
+            Edge& index = m_graph.varArgChild(node, 2);
+            Edge& enumerator = m_graph.varArgChild(node, 3);
+            fixEdge<CellUse>(base);
+            fixEdge<KnownCellUse>(property);
+            fixEdge<Int32Use>(index);
+            fixEdge<KnownCellUse>(enumerator);
+            break;
+        }
</ins><span class="cx">         case GetPropertyEnumerator: {
</span><span class="cx">             if (node->child1()->shouldSpeculateCell())
</span><span class="cx">                 fixEdge<CellUse>(node->child1());
</span><span class="cx">             break;
</span><span class="cx">         }
</span><del>-
-        case EnumeratorNextUpdateIndexAndMode: {
-            Edge& base = m_graph.varArgChild(node, 0);
-            Edge& index = m_graph.varArgChild(node, 1);
-            Edge& storageEdge = m_graph.varArgChild(node, node->storageChildIndex());
-
-            if (node->enumeratorMetadata() == JSPropertyNameEnumerator::IndexedMode) {
-                node->setArrayMode(
-                    node->arrayMode().refine(
-                        m_graph, node,
-                        m_graph.varArgChild(node, 0)->prediction(),
-                        m_graph.varArgChild(node, 1)->prediction()));
-
-                fixEdge<CellUse>(base);
-                blessArrayOperation(base, index, storageEdge);
-
-                ArrayMode arrayMode = node->arrayMode();
-                if (arrayMode.benefitsFromOriginalArray())
-                    setSaneChainIfPossible(node, arrayMode.speculation() == Array::InBounds ? Array::InBoundsSaneChain : Array::OutOfBoundsSaneChain);
-            }
-
-            if (node->enumeratorMetadata() == JSPropertyNameEnumerator::OwnStructureMode && !m_graph.hasExitSite(node->origin.semantic, BadCache))
-                fixEdge<CellUse>(base);
-
-            fixEdge<KnownInt32Use>(index);
-            fixEdge<KnownInt32Use>(m_graph.varArgChild(node, 2));
-            fixEdge<KnownCellUse>(m_graph.varArgChild(node, 3));
</del><ins>+        case GetEnumeratorStructurePname: {
+            fixEdge<KnownCellUse>(node->child1());
+            fixEdge<Int32Use>(node->child2());
</ins><span class="cx">             break;
</span><span class="cx">         }
</span><del>-
-        case EnumeratorNextExtractIndex:
-        case EnumeratorNextExtractMode: {
</del><ins>+        case GetEnumeratorGenericPname: {
+            fixEdge<KnownCellUse>(node->child1());
+            fixEdge<Int32Use>(node->child2());
</ins><span class="cx">             break;
</span><span class="cx">         }
</span><del>-
-        case EnumeratorNextUpdatePropertyName: {
-            fixEdge<KnownInt32Use>(node->child1());
-            fixEdge<KnownInt32Use>(node->child2());
-            fixEdge<KnownCellUse>(node->child3());
</del><ins>+        case ToIndexString: {
+            fixEdge<Int32Use>(node->child1());
</ins><span class="cx">             break;
</span><span class="cx">         }
</span><del>-
-        case EnumeratorHasOwnProperty:
-        case EnumeratorInByVal: {
-            if (m_graph.varArgChild(node, 0)->shouldSpeculateCell())
-                fixEdge<CellUse>(m_graph.varArgChild(node, 0));
-            fixEdge<KnownInt32Use>(m_graph.varArgChild(node, 2));
-            fixEdge<KnownInt32Use>(m_graph.varArgChild(node, 3));
-            fixEdge<KnownCellUse>(m_graph.varArgChild(node, 4));
-            break;
-        }
-
</del><span class="cx">         case ProfileType: {
</span><span class="cx">             // We want to insert type checks based on the instructionTypeSet of the TypeLocation, not the globalTypeSet.
</span><span class="cx">             // Because the instructionTypeSet is contained in globalTypeSet, if we produce a type check for
</span><span class="lines">@@ -3661,67 +3690,6 @@
</span><span class="cx">             OpInfo(arrayMode.asWord()), Edge(array, KnownCellUse));
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    void setJSArraySaneChainIfPossible(Node* node)
-    {
-        ArrayMode arrayMode = node->arrayMode();
-        std::optional<Array::Speculation> saneChainSpeculation;
-        if (arrayMode.isJSArrayWithOriginalStructure()) {
-            // Check if InBoundsSaneChain will work on a per-type basis. Note that:
-            //
-            // 1) We don't want double arrays to sometimes return undefined, since
-            // that would require a change to the return type and it would pessimise
-            // things a lot. So, we'd only want to do that if we actually had
-            // evidence that we could read from a hole. That's pretty annoying.
-            // Likely the best way to handle that case is with an equivalent of
-            // InBoundsSaneChain for OutOfBounds. For now we just detect when Undefined and
-            // NaN are indistinguishable according to backwards propagation, and just
-            // use InBoundsSaneChain in that case. This happens to catch a lot of cases.
-            //
-            // 2) We don't want int32 array loads to have to do a hole check just to
-            // coerce to Undefined, since that would mean twice the checks. We want to
-            // be able to say we always return Int32. FIXME: Maybe this should be profiling
-            // based?
-            //
-            // This has two implications. First, we have to do more checks than we'd
-            // like. It's unfortunate that we have to do the hole check. Second,
-            // some accesses that hit a hole will now need to take the full-blown
-            // out-of-bounds slow path. We can fix that with:
-            // https://bugs.webkit.org/show_bug.cgi?id=144668
-
-            switch (arrayMode.type()) {
-            case Array::Int32:
-                if (is64Bit() && arrayMode.speculation() == Array::OutOfBounds && !m_graph.hasExitSite(node->origin.semantic, NegativeIndex))
-                    saneChainSpeculation = Array::OutOfBoundsSaneChain;
-                break;
-            case Array::Contiguous:
-                // This is happens to be entirely natural. We already would have
-                // returned any JSValue, and now we'll return Undefined. We still do
-                // the check but it doesn't require taking any kind of slow path.
-                if (is64Bit() && arrayMode.speculation() == Array::OutOfBounds && !m_graph.hasExitSite(node->origin.semantic, NegativeIndex))
-                    saneChainSpeculation = Array::OutOfBoundsSaneChain;
-                else if (arrayMode.speculation() == Array::InBounds)
-                    saneChainSpeculation = Array::InBoundsSaneChain;
-                break;
-
-            case Array::Double:
-                if (!(node->flags() & NodeBytecodeUsesAsOther) && arrayMode.speculation() == Array::InBounds) {
-                    // Holes look like NaN already, so if the user doesn't care
-                    // about the difference between Undefined and NaN then we can
-                    // do this.
-                    saneChainSpeculation = Array::InBoundsSaneChain;
-                } else if (is64Bit() && arrayMode.speculation() == Array::OutOfBounds && !m_graph.hasExitSite(node->origin.semantic, NegativeIndex))
-                    saneChainSpeculation = Array::OutOfBoundsSaneChain;
-                break;
-
-            default:
-                break;
-            }
-        }
-
-        if (saneChainSpeculation)
-            setSaneChainIfPossible(node, *saneChainSpeculation);
-    }
-
</del><span class="cx">     void setSaneChainIfPossible(Node* node, Array::Speculation speculation)
</span><span class="cx">     {
</span><span class="cx">         JSGlobalObject* globalObject = m_graph.globalObjectFor(node->origin.semantic);
</span></span></pre></div>
<a id="branchessafari612128branchSourceJavaScriptCoredfgDFGGraphcpp"></a>
<div class="modfile"><h4>Modified: branches/safari-612.1.28-branch/Source/JavaScriptCore/dfg/DFGGraph.cpp (281021 => 281022)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-612.1.28-branch/Source/JavaScriptCore/dfg/DFGGraph.cpp   2021-08-13 16:39:44 UTC (rev 281021)
+++ branches/safari-612.1.28-branch/Source/JavaScriptCore/dfg/DFGGraph.cpp      2021-08-13 16:50:38 UTC (rev 281022)
</span><span class="lines">@@ -387,8 +387,6 @@
</span><span class="cx">         out.print(comma, *node->inByStatus());
</span><span class="cx">     if (node->hasPutByIdStatus())
</span><span class="cx">         out.print(comma, *node->putByIdStatus());
</span><del>-    if (node->hasEnumeratorMetadata())
-        out.print(comma, "enumeratorModes = ", node->enumeratorMetadata().toRaw());
</del><span class="cx">     if (node->isJump())
</span><span class="cx">         out.print(comma, "T:", *node->targetBlock());
</span><span class="cx">     if (node->isBranch())
</span></span></pre></div>
<a id="branchessafari612128branchSourceJavaScriptCoredfgDFGIntegerRangeOptimizationPhasecpp"></a>
<div class="modfile"><h4>Modified: branches/safari-612.1.28-branch/Source/JavaScriptCore/dfg/DFGIntegerRangeOptimizationPhase.cpp (281021 => 281022)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-612.1.28-branch/Source/JavaScriptCore/dfg/DFGIntegerRangeOptimizationPhase.cpp   2021-08-13 16:39:44 UTC (rev 281021)
+++ branches/safari-612.1.28-branch/Source/JavaScriptCore/dfg/DFGIntegerRangeOptimizationPhase.cpp      2021-08-13 16:50:38 UTC (rev 281022)
</span><span class="lines">@@ -1344,7 +1344,6 @@
</span><span class="cx">                     break;
</span><span class="cx">                 }
</span><span class="cx"> 
</span><del>-                case EnumeratorGetByVal:
</del><span class="cx">                 case GetByVal: {
</span><span class="cx">                     if (node->arrayMode().type() != Array::Undecided)
</span><span class="cx">                         break;
</span><span class="lines">@@ -1381,7 +1380,6 @@
</span><span class="cx">     void executeNode(Node* node)
</span><span class="cx">     {
</span><span class="cx">         switch (node->op()) {
</span><del>-        // FIXME: Teach this about EnumeratorNextExtractIndex.
</del><span class="cx">         case CheckInBounds: {
</span><span class="cx">             setRelationship(Relationship::safeCreate(node->child1().node(), node->child2().node(), Relationship::LessThan));
</span><span class="cx">             setRelationship(Relationship::safeCreate(node->child1().node(), m_zero, Relationship::GreaterThan, -1));
</span></span></pre></div>
<a id="branchessafari612128branchSourceJavaScriptCoredfgDFGMayExitcpp"></a>
<div class="modfile"><h4>Modified: branches/safari-612.1.28-branch/Source/JavaScriptCore/dfg/DFGMayExit.cpp (281021 => 281022)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-612.1.28-branch/Source/JavaScriptCore/dfg/DFGMayExit.cpp 2021-08-13 16:39:44 UTC (rev 281021)
+++ branches/safari-612.1.28-branch/Source/JavaScriptCore/dfg/DFGMayExit.cpp    2021-08-13 16:50:38 UTC (rev 281022)
</span><span class="lines">@@ -111,11 +111,8 @@
</span><span class="cx">     case FilterDeleteByStatus:
</span><span class="cx">     case FilterCheckPrivateBrandStatus:
</span><span class="cx">     case FilterSetPrivateBrandStatus:
</span><del>-    case EnumeratorNextExtractMode:
-    case EnumeratorNextExtractIndex:
</del><span class="cx">         break;
</span><span class="cx"> 
</span><del>-    case EnumeratorNextUpdatePropertyName:
</del><span class="cx">     case StrCat:
</span><span class="cx">     case Call:
</span><span class="cx">     case Construct:
</span></span></pre></div>
<a id="branchessafari612128branchSourceJavaScriptCoredfgDFGNodeh"></a>
<div class="modfile"><h4>Modified: branches/safari-612.1.28-branch/Source/JavaScriptCore/dfg/DFGNode.h (281021 => 281022)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-612.1.28-branch/Source/JavaScriptCore/dfg/DFGNode.h      2021-08-13 16:39:44 UTC (rev 281021)
+++ branches/safari-612.1.28-branch/Source/JavaScriptCore/dfg/DFGNode.h 2021-08-13 16:50:38 UTC (rev 281022)
</span><span class="lines">@@ -52,7 +52,6 @@
</span><span class="cx"> #include "DeleteByVariant.h"
</span><span class="cx"> #include "GetByVariant.h"
</span><span class="cx"> #include "JSCJSValue.h"
</span><del>-#include "JSPropertyNameEnumerator.h"
</del><span class="cx"> #include "Operands.h"
</span><span class="cx"> #include "PrivateFieldPutKind.h"
</span><span class="cx"> #include "PutByIdVariant.h"
</span><span class="lines">@@ -1765,6 +1764,7 @@
</span><span class="cx">         case ArithFloor:
</span><span class="cx">         case ArithCeil:
</span><span class="cx">         case ArithTrunc:
</span><ins>+        case GetDirectPname:
</ins><span class="cx">         case GetById:
</span><span class="cx">         case GetByIdFlush:
</span><span class="cx">         case GetByIdWithThis:
</span><span class="lines">@@ -1772,7 +1772,6 @@
</span><span class="cx">         case GetByIdDirectFlush:
</span><span class="cx">         case GetPrototypeOf:
</span><span class="cx">         case TryGetById:
</span><del>-        case EnumeratorGetByVal:
</del><span class="cx">         case GetByVal:
</span><span class="cx">         case GetByValWithThis:
</span><span class="cx">         case GetPrivateName:
</span><span class="lines">@@ -1942,82 +1941,6 @@
</span><span class="cx">         return m_opInfo.as<void*>();
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    bool hasStorageChild() const
-    {
-        switch (op()) {
-        case StringCharAt:
-        case StringCharCodeAt:
-        case StringCodePointAt:
-        case EnumeratorGetByVal:
-        case GetByVal:
-        case PutByValDirect:
-        case PutByVal:
-        case PutByValAlias:
-        case AtomicsAdd:
-        case AtomicsAnd:
-        case AtomicsCompareExchange:
-        case AtomicsExchange:
-        case AtomicsLoad:
-        case AtomicsOr:
-        case AtomicsStore:
-        case AtomicsSub:
-        case AtomicsXor:
-        case ArrayPush:
-        case ArrayPop:
-        case GetArrayLength:
-        case HasIndexedProperty:
-        case EnumeratorNextUpdateIndexAndMode:
-        case ArrayIndexOf:
-            return true;
-        default:
-            break;
-        }
-        return false;
-    }
-
-    unsigned storageChildIndex()
-    {
-        ASSERT(hasStorageChild());
-        switch (op()) {
-        case StringCharAt:
-        case StringCharCodeAt:
-        case StringCodePointAt:
-        case EnumeratorGetByVal:
-        case GetByVal:
-            return 2;
-        case PutByValDirect:
-        case PutByVal:
-        case PutByValAlias:
-            return 3;
-        case AtomicsAdd:
-        case AtomicsAnd:
-        case AtomicsCompareExchange:
-        case AtomicsExchange:
-        case AtomicsLoad:
-        case AtomicsOr:
-        case AtomicsStore:
-        case AtomicsSub:
-        case AtomicsXor:
-            return 2 + numExtraAtomicsArgs(op());
-        case ArrayPush:
-            return 0;
-
-        case ArrayPop:
-        case GetArrayLength:
-            return 2;
-
-        case HasIndexedProperty:
-            return 2;
-
-        case EnumeratorNextUpdateIndexAndMode:
-            return 4;
-
-        default:
-            // FIXME: Add ArrayIndexOf but it does non-trivial things to determine storage edge.
-            RELEASE_ASSERT_NOT_REACHED();
-        }
-    }
-
</del><span class="cx">     bool hasUidOperand()
</span><span class="cx">     {
</span><span class="cx">         return op() == CheckIdent;
</span><span class="lines">@@ -2282,10 +2205,6 @@
</span><span class="cx">         case PutByVal:
</span><span class="cx">         case PutByValAlias:
</span><span class="cx">         case GetByVal:
</span><del>-        case EnumeratorNextUpdateIndexAndMode:
-        case EnumeratorGetByVal:
-        case EnumeratorInByVal:
-        case EnumeratorHasOwnProperty:
</del><span class="cx">         case StringCharAt:
</span><span class="cx">         case StringCharCodeAt:
</span><span class="cx">         case StringCodePointAt:
</span><span class="lines">@@ -2297,6 +2216,7 @@
</span><span class="cx">         case ArrayPop:
</span><span class="cx">         case ArrayIndexOf:
</span><span class="cx">         case HasIndexedProperty:
</span><ins>+        case HasEnumerableIndexedProperty:
</ins><span class="cx">         case AtomicsAdd:
</span><span class="cx">         case AtomicsAnd:
</span><span class="cx">         case AtomicsCompareExchange:
</span><span class="lines">@@ -3254,25 +3174,6 @@
</span><span class="cx">         return m_opInfo.as<SetPrivateBrandStatus*>();
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    bool hasEnumeratorMetadata() const
-    {
-        switch (op()) {
-        case EnumeratorNextUpdateIndexAndMode:
-        case EnumeratorNextUpdatePropertyName:
-        case EnumeratorHasOwnProperty:
-        case EnumeratorInByVal:
-            return true;
-        default:
-            return false;
-        }
-    }
-
-    OptionSet<JSPropertyNameEnumerator::Mode> enumeratorMetadata()
-    {
-        ASSERT(hasEnumeratorMetadata());
-        return OptionSet<JSPropertyNameEnumerator::Mode>::fromRaw(m_opInfo2.as<unsigned>());
-    }
-
</del><span class="cx">     void dumpChildren(PrintStream& out)
</span><span class="cx">     {
</span><span class="cx">         if (!child1())
</span></span></pre></div>
<a id="branchessafari612128branchSourceJavaScriptCoredfgDFGNodeTypeh"></a>
<div class="modfile"><h4>Modified: branches/safari-612.1.28-branch/Source/JavaScriptCore/dfg/DFGNodeType.h (281021 => 281022)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-612.1.28-branch/Source/JavaScriptCore/dfg/DFGNodeType.h  2021-08-13 16:39:44 UTC (rev 281021)
+++ branches/safari-612.1.28-branch/Source/JavaScriptCore/dfg/DFGNodeType.h     2021-08-13 16:50:38 UTC (rev 281022)
</span><span class="lines">@@ -501,17 +501,20 @@
</span><span class="cx">     macro(StoreBarrier, NodeMustGenerate) \
</span><span class="cx">     macro(FencedStoreBarrier, NodeMustGenerate) \
</span><span class="cx">     \
</span><ins>+    /* For-in enumeration opcodes */\
+    macro(GetEnumerableLength, NodeMustGenerate | NodeResultJS) \
</ins><span class="cx">     /* Must generate because of Proxies on the prototype chain */ \
</span><span class="cx">     macro(HasIndexedProperty, NodeMustGenerate | NodeResultBoolean | NodeHasVarArgs) \
</span><del>-    /* For-in enumeration opcodes */\
</del><ins>+    macro(HasEnumerableIndexedProperty, NodeMustGenerate | NodeResultBoolean | NodeHasVarArgs) \
+    macro(HasEnumerableStructureProperty, NodeResultBoolean) \
+    macro(HasEnumerableProperty, NodeResultBoolean) \
+    macro(HasOwnStructureProperty, NodeResultBoolean | NodeMustGenerate) \
+    macro(InStructureProperty, NodeMustGenerate | NodeResultBoolean) \
+    macro(GetDirectPname, NodeMustGenerate | NodeHasVarArgs | NodeResultJS) \
</ins><span class="cx">     macro(GetPropertyEnumerator, NodeMustGenerate | NodeResultJS) \
</span><del>-    macro(EnumeratorNextUpdateIndexAndMode, NodeResultJS | NodeHasVarArgs) \
-    macro(EnumeratorNextExtractMode, NodeResultInt32) \
-    macro(EnumeratorNextExtractIndex, NodeResultInt32) \
-    macro(EnumeratorNextUpdatePropertyName, NodeResultJS) \
-    macro(EnumeratorGetByVal, NodeResultJS | NodeHasVarArgs | NodeMustGenerate) \
-    macro(EnumeratorInByVal, NodeResultBoolean | NodeHasVarArgs | NodeMustGenerate) \
-    macro(EnumeratorHasOwnProperty, NodeResultBoolean | NodeHasVarArgs | NodeMustGenerate) \
</del><ins>+    macro(GetEnumeratorStructurePname, NodeMustGenerate | NodeResultJS) \
+    macro(GetEnumeratorGenericPname, NodeMustGenerate | NodeResultJS) \
+    macro(ToIndexString, NodeResultJS) \
</ins><span class="cx">     /* Nodes for JSMap and JSSet */ \
</span><span class="cx">     macro(MapHash, NodeResultInt32) \
</span><span class="cx">     macro(NormalizeMapKey, NodeResultJS) \
</span></span></pre></div>
<a id="branchessafari612128branchSourceJavaScriptCoredfgDFGOpInfoh"></a>
<div class="modfile"><h4>Modified: branches/safari-612.1.28-branch/Source/JavaScriptCore/dfg/DFGOpInfo.h (281021 => 281022)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-612.1.28-branch/Source/JavaScriptCore/dfg/DFGOpInfo.h    2021-08-13 16:39:44 UTC (rev 281021)
+++ branches/safari-612.1.28-branch/Source/JavaScriptCore/dfg/DFGOpInfo.h       2021-08-13 16:50:38 UTC (rev 281022)
</span><span class="lines">@@ -29,7 +29,6 @@
</span><span class="cx"> #include "DFGRegisteredStructure.h"
</span><span class="cx"> #include "HeapCell.h"
</span><span class="cx"> #include "PrivateFieldPutKind.h"
</span><del>-#include <wtf/OptionSet.h>
</del><span class="cx"> #include <wtf/StdLibExtras.h>
</span><span class="cx"> 
</span><span class="cx"> #if ENABLE(DFG_JIT)
</span><span class="lines">@@ -51,8 +50,6 @@
</span><span class="cx">     explicit OpInfo(CacheableIdentifier identifier) : m_value(static_cast<uint64_t>(identifier.rawBits())) { }
</span><span class="cx">     explicit OpInfo(ECMAMode ecmaMode) : m_value(ecmaMode.value()) { }
</span><span class="cx">     explicit OpInfo(PrivateFieldPutKind putKind) : m_value(putKind.value()) { }
</span><del>-    template<typename EnumType>
-    explicit OpInfo(OptionSet<EnumType> optionSet) : m_value(optionSet.toRaw()) { }
</del><span class="cx"> 
</span><span class="cx">     template <typename T>
</span><span class="cx">     explicit OpInfo(T* ptr)
</span></span></pre></div>
<a id="branchessafari612128branchSourceJavaScriptCoredfgDFGOperationscpp"></a>
<div class="modfile"><h4>Modified: branches/safari-612.1.28-branch/Source/JavaScriptCore/dfg/DFGOperations.cpp (281021 => 281022)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-612.1.28-branch/Source/JavaScriptCore/dfg/DFGOperations.cpp      2021-08-13 16:39:44 UTC (rev 281021)
+++ branches/safari-612.1.28-branch/Source/JavaScriptCore/dfg/DFGOperations.cpp 2021-08-13 16:50:38 UTC (rev 281022)
</span><span class="lines">@@ -2399,6 +2399,48 @@
</span><span class="cx">     return result;
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+JSC_DEFINE_JIT_OPERATION(operationHasEnumerableProperty, EncodedJSValue, (JSGlobalObject* globalObject, EncodedJSValue encodedBaseValue, JSCell* property))
+{
+    VM& vm = globalObject->vm();
+    CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
+    JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
+    auto scope = DECLARE_THROW_SCOPE(vm);
+
+    JSValue baseValue = JSValue::decode(encodedBaseValue);
+    if (baseValue.isUndefinedOrNull())
+        return JSValue::encode(jsBoolean(false));
+
+    JSObject* base = baseValue.toObject(globalObject);
+    EXCEPTION_ASSERT(!scope.exception() || !base);
+    if (!base)
+        return JSValue::encode(JSValue());
+    auto propertyName = asString(property)->toIdentifier(globalObject);
+    RETURN_IF_EXCEPTION(scope, { });
+    RELEASE_AND_RETURN(scope, JSValue::encode(jsBoolean(base->hasEnumerableProperty(globalObject, propertyName))));
+}
+
+JSC_DEFINE_JIT_OPERATION(operationInStructureProperty, EncodedJSValue, (JSGlobalObject* globalObject, JSCell* base, JSString* property))
+{
+    VM& vm = globalObject->vm();
+    CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
+    JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
+
+    return JSValue::encode(jsBoolean(CommonSlowPaths::opInByVal(globalObject, base, property)));
+}
+
+JSC_DEFINE_JIT_OPERATION(operationHasOwnStructureProperty, EncodedJSValue, (JSGlobalObject* globalObject, JSCell* base, JSString* property))
+{
+    VM& vm = globalObject->vm();
+    CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
+    JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
+
+    auto scope = DECLARE_THROW_SCOPE(vm);
+    auto propertyName = property->toIdentifier(globalObject);
+    RETURN_IF_EXCEPTION(scope, { });
+    scope.release();
+    return JSValue::encode(jsBoolean(objectPrototypeHasOwnProperty(globalObject, base, propertyName)));
+}
+
</ins><span class="cx"> JSC_DEFINE_JIT_OPERATION(operationHasIndexedProperty, size_t, (JSGlobalObject* globalObject, JSCell* baseCell, int32_t subscript))
</span><span class="cx"> {
</span><span class="cx">     VM& vm = globalObject->vm();
</span><span class="lines">@@ -2455,107 +2497,14 @@
</span><span class="cx">     RELEASE_AND_RETURN(scope, propertyNameEnumerator(globalObject, base));
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-JSC_DEFINE_JIT_OPERATION(operationEnumeratorNextUpdateIndexAndMode, EncodedJSValue, (JSGlobalObject* globalObject, EncodedJSValue baseValue, uint32_t index, int32_t modeNumber, JSPropertyNameEnumerator* enumerator))
</del><ins>+JSC_DEFINE_JIT_OPERATION(operationToIndexString, JSCell*, (JSGlobalObject* globalObject, int32_t index))
</ins><span class="cx"> {
</span><span class="cx">     VM& vm = globalObject->vm();
</span><span class="cx">     CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
</span><span class="cx">     JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
</span><del>-    auto scope = DECLARE_THROW_SCOPE(vm);
-
-    JSPropertyNameEnumerator::Mode mode = static_cast<JSPropertyNameEnumerator::Mode>(modeNumber);
-    if (JSValue::decode(baseValue).isUndefinedOrNull()) {
-        ASSERT(mode == JSPropertyNameEnumerator::InitMode);
-        ASSERT(!index);
-        ASSERT(!enumerator->sizeOfPropertyNames());
-        mode = JSPropertyNameEnumerator::GenericMode;
-    } else {
-        JSObject* base = JSValue::decode(baseValue).toObject(globalObject);
-        RETURN_IF_EXCEPTION(scope, { });
-
-        constexpr bool shouldAllocateIndexedNameString = false;
-        enumerator->computeNext(globalObject, base, index, mode, shouldAllocateIndexedNameString);
-        RETURN_IF_EXCEPTION(scope, { });
-    }
-
-#if USE(JSVALUE64)
-    JSValue result = bitwise_cast<JSValue>(static_cast<uint64_t>(mode) << 32 | index | JSValue::DoubleEncodeOffset);
-#else
-    JSValue result = JSValue(mode, index);
-#endif
-    ASSERT(result.isDouble());
-    return JSValue::encode(result);
</del><ins>+    return jsString(vm, Identifier::from(vm, index).string());
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-JSC_DEFINE_JIT_OPERATION(operationEnumeratorNextUpdatePropertyName, EncodedJSValue, (JSGlobalObject* globalObject, uint32_t index, int32_t modeNumber, JSPropertyNameEnumerator* enumerator))
-{
-    VM& vm = globalObject->vm();
-    CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
-    JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
-
-    if (modeNumber == JSPropertyNameEnumerator::IndexedMode) {
-        if (index < enumerator->indexedLength())
-            return JSValue::encode(jsString(vm, Identifier::from(vm, index).string()));
-        return JSValue::encode(jsNull());
-    }
-
-    JSString* result = enumerator->propertyNameAtIndex(index);
-    if (!result)
-        return JSValue::encode(jsNull());
-
-    return JSValue::encode(result);
-}
-
-JSC_DEFINE_JIT_OPERATION(operationEnumeratorRecoverNameAndGetByVal, EncodedJSValue, (JSGlobalObject* globalObject, JSCell* base, uint32_t index, JSPropertyNameEnumerator* enumerator))
-{
-    VM& vm = globalObject->vm();
-    CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
-    JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
-    auto scope = DECLARE_THROW_SCOPE(vm);
-
-    JSString* string = enumerator->propertyNameAtIndex(index);
-    PropertyName propertyName = string->toIdentifier(globalObject);
-    // This should only really return for TerminationException since we know string is backed by a UUID.
-    RETURN_IF_EXCEPTION(scope, { });
-    JSObject* object = base->toObject(globalObject);
-    RETURN_IF_EXCEPTION(scope, { });
-
-    RELEASE_AND_RETURN(scope, JSValue::encode(object->get(globalObject, propertyName)));
-}
-
-JSC_DEFINE_JIT_OPERATION(operationEnumeratorInByVal, EncodedJSValue, (JSGlobalObject* globalObject, EncodedJSValue baseValue, EncodedJSValue propertyNameValue, uint32_t index, int32_t modeNumber))
-{
-    VM& vm = globalObject->vm();
-    CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
-    JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
-    auto scope = DECLARE_THROW_SCOPE(vm);
-
-    JSValue base = JSValue::decode(baseValue);
-    RETURN_IF_EXCEPTION(scope, { });
-    if (modeNumber == JSPropertyNameEnumerator::IndexedMode && base.isObject())
-        return JSValue::encode(jsBoolean(jsCast<JSObject*>(base)->hasProperty(globalObject, index)));
-
-    JSString* propertyName = jsSecureCast<JSString*>(vm, JSValue::decode(propertyNameValue));
-    RELEASE_AND_RETURN(scope, JSValue::encode(jsBoolean(CommonSlowPaths::opInByVal(globalObject, base, propertyName))));
-}
-
-JSC_DEFINE_JIT_OPERATION(operationEnumeratorHasOwnProperty, EncodedJSValue, (JSGlobalObject* globalObject, EncodedJSValue baseValue, EncodedJSValue propertyNameValue, uint32_t index, int32_t modeNumber))
-{
-    VM& vm = globalObject->vm();
-    CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
-    JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
-    auto scope = DECLARE_THROW_SCOPE(vm);
-
-    JSValue base = JSValue::decode(baseValue);
-    RETURN_IF_EXCEPTION(scope, { });
-    if (modeNumber == JSPropertyNameEnumerator::IndexedMode && base.isObject())
-        return JSValue::encode(jsBoolean(jsCast<JSObject*>(base)->hasOwnProperty(globalObject, index)));
-
-    JSString* propertyName = jsSecureCast<JSString*>(vm, JSValue::decode(propertyNameValue));
-    auto identifier = propertyName->toIdentifier(globalObject);
-    RETURN_IF_EXCEPTION(scope, { });
-    RELEASE_AND_RETURN(scope, JSValue::encode(jsBoolean(objectPrototypeHasOwnProperty(globalObject, base, identifier))));
-}
-
</del><span class="cx"> JSC_DEFINE_JIT_OPERATION(operationNewRegexpWithLastIndex, JSCell*, (JSGlobalObject* globalObject, JSCell* regexpPtr, EncodedJSValue encodedLastIndex))
</span><span class="cx"> {
</span><span class="cx">     VM& vm = globalObject->vm();
</span></span></pre></div>
<a id="branchessafari612128branchSourceJavaScriptCoredfgDFGOperationsh"></a>
<div class="modfile"><h4>Modified: branches/safari-612.1.28-branch/Source/JavaScriptCore/dfg/DFGOperations.h (281021 => 281022)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-612.1.28-branch/Source/JavaScriptCore/dfg/DFGOperations.h        2021-08-13 16:39:44 UTC (rev 281021)
+++ branches/safari-612.1.28-branch/Source/JavaScriptCore/dfg/DFGOperations.h   2021-08-13 16:50:38 UTC (rev 281022)
</span><span class="lines">@@ -36,7 +36,6 @@
</span><span class="cx"> class DateInstance;
</span><span class="cx"> class JSBigInt;
</span><span class="cx"> struct UnlinkedStringJumpTable;
</span><del>-class JSPropertyNameEnumerator;
</del><span class="cx"> 
</span><span class="cx"> namespace DFG {
</span><span class="cx"> 
</span><span class="lines">@@ -105,14 +104,12 @@
</span><span class="cx"> JSC_DECLARE_JIT_OPERATION(operationGetPrototypeOfObject, EncodedJSValue, (JSGlobalObject*, JSObject*));
</span><span class="cx"> JSC_DECLARE_JIT_OPERATION(operationHasIndexedProperty, size_t, (JSGlobalObject*, JSCell*, int32_t));
</span><span class="cx"> JSC_DECLARE_JIT_OPERATION(operationHasEnumerableIndexedProperty, size_t, (JSGlobalObject*, JSCell*, int32_t));
</span><ins>+JSC_DECLARE_JIT_OPERATION(operationHasEnumerableProperty, EncodedJSValue, (JSGlobalObject*, EncodedJSValue, JSCell*));
+JSC_DECLARE_JIT_OPERATION(operationHasOwnStructureProperty, EncodedJSValue, (JSGlobalObject*, JSCell*, JSString*));
+JSC_DECLARE_JIT_OPERATION(operationInStructureProperty, EncodedJSValue, (JSGlobalObject*, JSCell*, JSString*));
</ins><span class="cx"> JSC_DECLARE_JIT_OPERATION(operationGetPropertyEnumerator, JSCell*, (JSGlobalObject*, EncodedJSValue));
</span><span class="cx"> JSC_DECLARE_JIT_OPERATION(operationGetPropertyEnumeratorCell, JSCell*, (JSGlobalObject*, JSCell*));
</span><del>-JSC_DECLARE_JIT_OPERATION(operationEnumeratorNextUpdateIndexAndMode, EncodedJSValue, (JSGlobalObject*, EncodedJSValue, uint32_t, int32_t, JSPropertyNameEnumerator*));
-JSC_DECLARE_JIT_OPERATION(operationEnumeratorNextUpdatePropertyName, EncodedJSValue, (JSGlobalObject*, uint32_t, int32_t, JSPropertyNameEnumerator*));
-JSC_DECLARE_JIT_OPERATION(operationEnumeratorInByVal, EncodedJSValue, (JSGlobalObject*, EncodedJSValue, EncodedJSValue, uint32_t, int32_t));
-JSC_DECLARE_JIT_OPERATION(operationEnumeratorHasOwnProperty, EncodedJSValue, (JSGlobalObject*, EncodedJSValue, EncodedJSValue, uint32_t, int32_t));
-JSC_DECLARE_JIT_OPERATION(operationEnumeratorRecoverNameAndGetByVal, EncodedJSValue, (JSGlobalObject*, JSCell*, uint32_t, JSPropertyNameEnumerator*));
-
</del><ins>+JSC_DECLARE_JIT_OPERATION(operationToIndexString, JSCell*, (JSGlobalObject*, int32_t));
</ins><span class="cx"> JSC_DECLARE_JIT_OPERATION(operationNewRegexpWithLastIndex, JSCell*, (JSGlobalObject*, JSCell*, EncodedJSValue));
</span><span class="cx"> JSC_DECLARE_JIT_OPERATION(operationNewArray, char*, (JSGlobalObject*, Structure*, void*, size_t));
</span><span class="cx"> JSC_DECLARE_JIT_OPERATION(operationNewEmptyArray, char*, (VM*, Structure*));
</span></span></pre></div>
<a id="branchessafari612128branchSourceJavaScriptCoredfgDFGPredictionPropagationPhasecpp"></a>
<div class="modfile"><h4>Modified: branches/safari-612.1.28-branch/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp (281021 => 281022)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-612.1.28-branch/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp      2021-08-13 16:39:44 UTC (rev 281021)
+++ branches/safari-612.1.28-branch/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp 2021-08-13 16:50:38 UTC (rev 281022)
</span><span class="lines">@@ -473,7 +473,7 @@
</span><span class="cx">             Edge child1 = m_graph.child(node, 0);
</span><span class="cx">             if (!child1->prediction())
</span><span class="cx">                 break;
</span><del>-
</del><ins>+            
</ins><span class="cx">             Edge child2 = m_graph.child(node, 1);
</span><span class="cx">             ArrayMode arrayMode = node->arrayMode().refine(
</span><span class="cx">                 m_graph, node,
</span><span class="lines">@@ -480,7 +480,7 @@
</span><span class="cx">                 child1->prediction(),
</span><span class="cx">                 child2->prediction(),
</span><span class="cx">                 SpecNone);
</span><del>-
</del><ins>+            
</ins><span class="cx">             switch (arrayMode.type()) {
</span><span class="cx">             case Array::Int32:
</span><span class="cx">                 if (arrayMode.isOutOfBounds())
</span><span class="lines">@@ -862,7 +862,6 @@
</span><span class="cx">             break;
</span><span class="cx">         }
</span><span class="cx"> 
</span><del>-        case EnumeratorGetByVal:
</del><span class="cx">         case ArrayPop:
</span><span class="cx">         case ArrayPush:
</span><span class="cx">         case RegExpExec:
</span><span class="lines">@@ -883,6 +882,7 @@
</span><span class="cx">         case GetPrivateName:
</span><span class="cx">         case GetPrivateNameById:
</span><span class="cx">         case MultiGetByOffset:
</span><ins>+        case GetDirectPname:
</ins><span class="cx">         case Call:
</span><span class="cx">         case DirectCall:
</span><span class="cx">         case TailCallInlinedCaller:
</span><span class="lines">@@ -1205,20 +1205,21 @@
</span><span class="cx">             setPrediction(SpecObjectOther);
</span><span class="cx">             break;
</span><span class="cx"> 
</span><del>-        case EnumeratorNextExtractMode:
-        case EnumeratorNextExtractIndex: {
</del><ins>+        case GetEnumerableLength: {
</ins><span class="cx">             setPrediction(SpecInt32Only);
</span><span class="cx">             break;
</span><span class="cx">         }
</span><del>-
-        case EnumeratorInByVal:
-        case EnumeratorHasOwnProperty:
</del><span class="cx">         case InByVal:
</span><span class="cx">         case InById:
</span><span class="cx">         case HasPrivateName:
</span><span class="cx">         case HasPrivateBrand:
</span><span class="cx">         case HasOwnProperty:
</span><del>-        case HasIndexedProperty: {
</del><ins>+        case HasOwnStructureProperty:
+        case InStructureProperty:
+        case HasIndexedProperty:
+        case HasEnumerableIndexedProperty:
+        case HasEnumerableStructureProperty:
+        case HasEnumerableProperty: {
</ins><span class="cx">             setPrediction(SpecBoolean);
</span><span class="cx">             break;
</span><span class="cx">         }
</span><span class="lines">@@ -1226,17 +1227,18 @@
</span><span class="cx">             setPrediction(SpecCell);
</span><span class="cx">             break;
</span><span class="cx">         }
</span><del>-
-        case EnumeratorNextUpdateIndexAndMode: {
-            setPrediction(SpecFullNumber);
</del><ins>+        case GetEnumeratorStructurePname: {
+            setPrediction(SpecCell | SpecOther);
</ins><span class="cx">             break;
</span><span class="cx">         }
</span><del>-
-        case EnumeratorNextUpdatePropertyName: {
-            setPrediction(SpecString | SpecOther);
</del><ins>+        case GetEnumeratorGenericPname: {
+            setPrediction(SpecCell | SpecOther);
</ins><span class="cx">             break;
</span><span class="cx">         }
</span><del>-
</del><ins>+        case ToIndexString: {
+            setPrediction(SpecString);
+            break;
+        }
</ins><span class="cx">         case ParseInt: {
</span><span class="cx">             // We expect this node to almost always produce an int32. However,
</span><span class="cx">             // it's possible it produces NaN or integers out of int32 range. We
</span></span></pre></div>
<a id="branchessafari612128branchSourceJavaScriptCoredfgDFGSSALoweringPhasecpp"></a>
<div class="modfile"><h4>Modified: branches/safari-612.1.28-branch/Source/JavaScriptCore/dfg/DFGSSALoweringPhase.cpp (281021 => 281022)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-612.1.28-branch/Source/JavaScriptCore/dfg/DFGSSALoweringPhase.cpp        2021-08-13 16:39:44 UTC (rev 281021)
+++ branches/safari-612.1.28-branch/Source/JavaScriptCore/dfg/DFGSSALoweringPhase.cpp   2021-08-13 16:50:38 UTC (rev 281022)
</span><span class="lines">@@ -82,10 +82,10 @@
</span><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         case HasIndexedProperty:
</span><ins>+        case HasEnumerableIndexedProperty:
</ins><span class="cx">             lowerBoundsCheck(m_graph.child(m_node, 0), m_graph.child(m_node, 1), m_graph.child(m_node, 2));
</span><span class="cx">             break;
</span><span class="cx"> 
</span><del>-        case EnumeratorGetByVal:
</del><span class="cx">         case GetByVal: {
</span><span class="cx">             lowerBoundsCheck(m_graph.varArgChild(m_node, 0), m_graph.varArgChild(m_node, 1), m_graph.varArgChild(m_node, 2));
</span><span class="cx">             break;
</span></span></pre></div>
<a id="branchessafari612128branchSourceJavaScriptCoredfgDFGSafeToExecuteh"></a>
<div class="modfile"><h4>Modified: branches/safari-612.1.28-branch/Source/JavaScriptCore/dfg/DFGSafeToExecute.h (281021 => 281022)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-612.1.28-branch/Source/JavaScriptCore/dfg/DFGSafeToExecute.h     2021-08-13 16:39:44 UTC (rev 281021)
+++ branches/safari-612.1.28-branch/Source/JavaScriptCore/dfg/DFGSafeToExecute.h        2021-08-13 16:50:38 UTC (rev 281022)
</span><span class="lines">@@ -296,6 +296,10 @@
</span><span class="cx">     case BooleanToNumber:
</span><span class="cx">     case FiatInt52:
</span><span class="cx">     case HasIndexedProperty:
</span><ins>+    case HasEnumerableIndexedProperty:
+    case GetEnumeratorStructurePname:
+    case GetEnumeratorGenericPname:
+    case ToIndexString:
</ins><span class="cx">     case CheckStructureImmediate:
</span><span class="cx">     case GetMyArgumentByVal:
</span><span class="cx">     case GetMyArgumentByValOutOfBounds:
</span><span class="lines">@@ -368,7 +372,6 @@
</span><span class="cx">         // to capture "profiling" at the point in control flow here the user put them.
</span><span class="cx">         return false;
</span><span class="cx"> 
</span><del>-    case EnumeratorGetByVal:
</del><span class="cx">     case GetByVal:
</span><span class="cx">     case GetIndexedPropertyStorage:
</span><span class="cx">     case GetArrayLength:
</span><span class="lines">@@ -493,11 +496,6 @@
</span><span class="cx">         return isSafe;
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    case EnumeratorNextUpdateIndexAndMode:
-    // These technically don't have effects but they'll only ever follow a EnumeratorNextUpdateIndexAndMode so we might as well return false.
-    case EnumeratorNextExtractMode:
-    case EnumeratorNextExtractIndex:
-    case EnumeratorNextUpdatePropertyName:
</del><span class="cx">     case ToThis:
</span><span class="cx">     case CreateThis:
</span><span class="cx">     case CreatePromise:
</span><span class="lines">@@ -597,8 +595,6 @@
</span><span class="cx">     case NewStringObject:
</span><span class="cx">     case InByVal:
</span><span class="cx">     case InById:
</span><del>-    case EnumeratorInByVal:
-    case EnumeratorHasOwnProperty:
</del><span class="cx">     case HasPrivateName:
</span><span class="cx">     case HasPrivateBrand:
</span><span class="cx">     case HasOwnProperty:
</span><span class="lines">@@ -643,6 +639,12 @@
</span><span class="cx">     case NotifyWrite:
</span><span class="cx">     case MultiPutByOffset:
</span><span class="cx">     case MultiDeleteByOffset:
</span><ins>+    case GetEnumerableLength:
+    case HasEnumerableStructureProperty:
+    case HasEnumerableProperty:
+    case HasOwnStructureProperty:
+    case InStructureProperty:
+    case GetDirectPname:
</ins><span class="cx">     case GetPropertyEnumerator:
</span><span class="cx">     case PhantomNewObject:
</span><span class="cx">     case PhantomNewFunction:
</span></span></pre></div>
<a id="branchessafari612128branchSourceJavaScriptCoredfgDFGSpeculativeJITcpp"></a>
<div class="modfile"><h4>Modified: branches/safari-612.1.28-branch/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp (281021 => 281022)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-612.1.28-branch/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp  2021-08-13 16:39:44 UTC (rev 281021)
+++ branches/safari-612.1.28-branch/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp     2021-08-13 16:50:38 UTC (rev 281022)
</span><span class="lines">@@ -1637,15 +1637,25 @@
</span><span class="cx"> {
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-JSValueRegsTemporary::JSValueRegsTemporary(SpeculativeJIT* jit, GPRReg specificPayload)
</del><span class="cx"> #if USE(JSVALUE64)
</span><del>-    : m_gpr(jit, specificPayload)
</del><ins>+template<typename T>
+JSValueRegsTemporary::JSValueRegsTemporary(SpeculativeJIT* jit, ReuseTag, T& operand, WhichValueWord)
+    : m_gpr(jit, Reuse, operand)
+{
+}
</ins><span class="cx"> #else
</span><del>-    : m_payloadGPR(jit, specificPayload)
-    , m_tagGPR(jit)
-#endif
</del><ins>+template<typename T>
+JSValueRegsTemporary::JSValueRegsTemporary(SpeculativeJIT* jit, ReuseTag, T& operand, WhichValueWord resultWord)
</ins><span class="cx"> {
</span><ins>+    if (resultWord == PayloadWord) {
+        m_payloadGPR = GPRTemporary(jit, Reuse, operand);
+        m_tagGPR = GPRTemporary(jit);
+    } else {
+        m_payloadGPR = GPRTemporary(jit);
+        m_tagGPR = GPRTemporary(jit, Reuse, operand);
+    }
</ins><span class="cx"> }
</span><ins>+#endif
</ins><span class="cx"> 
</span><span class="cx"> #if USE(JSVALUE64)
</span><span class="cx"> JSValueRegsTemporary::JSValueRegsTemporary(SpeculativeJIT* jit, ReuseTag, JSValueOperand& operand)
</span><span class="lines">@@ -2587,7 +2597,7 @@
</span><span class="cx">     strictInt32Result(scratchReg, m_currentNode);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void SpeculativeJIT::compileGetByValOnString(Node* node, const ScopedLambda<std::tuple<JSValueRegs, DataFormat>(DataFormat preferredFormat)>& prefix)
</del><ins>+void SpeculativeJIT::compileGetByValOnString(Node* node)
</ins><span class="cx"> {
</span><span class="cx">     SpeculateCellOperand base(this, m_graph.child(node, 0));
</span><span class="cx">     SpeculateStrictInt32Operand property(this, m_graph.child(node, 1));
</span><span class="lines">@@ -2596,10 +2606,17 @@
</span><span class="cx">     GPRReg propertyReg = property.gpr();
</span><span class="cx">     GPRReg storageReg = storage.gpr();
</span><span class="cx"> 
</span><del>-    JSValueRegs resultRegs;
-    DataFormat format;
-    std::tie(resultRegs, format) = prefix(node->arrayMode().isOutOfBounds() ? DataFormatJS : DataFormatCell);
-    GPRReg scratchReg = resultRegs.payloadGPR();
</del><ins>+    GPRTemporary scratch(this);
+    GPRReg scratchReg = scratch.gpr();
+#if USE(JSVALUE32_64)
+    GPRTemporary resultTag;
+    GPRReg resultTagReg = InvalidGPRReg;
+    if (node->arrayMode().isOutOfBounds()) {
+        GPRTemporary realResultTag(this);
+        resultTag.adopt(realResultTag);
+        resultTagReg = resultTag.gpr();
+    }
+#endif
</ins><span class="cx"> 
</span><span class="cx">     // unsigned comparison so we can filter out negative indices and indices that are too large
</span><span class="cx">     m_jit.loadPtr(MacroAssembler::Address(baseReg, JSString::offsetOfValue()), scratchReg);
</span><span class="lines">@@ -2635,9 +2652,8 @@
</span><span class="cx">             bigCharacter, this, operationSingleCharacterString, scratchReg, &vm, scratchReg));
</span><span class="cx"> 
</span><span class="cx">     if (node->arrayMode().isOutOfBounds()) {
</span><del>-        ASSERT(format == DataFormatJS);
</del><span class="cx"> #if USE(JSVALUE32_64)
</span><del>-        m_jit.move(TrustedImm32(JSValue::CellTag), resultRegs.tagGPR());
</del><ins>+        m_jit.move(TrustedImm32(JSValue::CellTag), resultTagReg);
</ins><span class="cx"> #endif
</span><span class="cx"> 
</span><span class="cx">         JSGlobalObject* globalObject = m_jit.globalObjectFor(node->origin.semantic);
</span><span class="lines">@@ -2655,24 +2671,34 @@
</span><span class="cx">             m_jit.graph().registerAndWatchStructureTransition(stringPrototypeStructure);
</span><span class="cx">             m_jit.graph().registerAndWatchStructureTransition(objectPrototypeStructure);
</span><span class="cx"> 
</span><ins>+#if USE(JSVALUE64)
</ins><span class="cx">             addSlowPathGenerator(makeUnique<SaneStringGetByValSlowPathGenerator>(
</span><del>-                outOfBounds, this, resultRegs, TrustedImmPtr::weakPointer(m_graph, globalObject), baseReg, propertyReg));
</del><ins>+                outOfBounds, this, JSValueRegs(scratchReg), TrustedImmPtr::weakPointer(m_graph, globalObject), baseReg, propertyReg));
+#else
+            addSlowPathGenerator(makeUnique<SaneStringGetByValSlowPathGenerator>(
+                outOfBounds, this, JSValueRegs(resultTagReg, scratchReg), TrustedImmPtr::weakPointer(m_graph, globalObject), baseReg, propertyReg));
+#endif
</ins><span class="cx">         } else {
</span><ins>+#if USE(JSVALUE64)
</ins><span class="cx">             addSlowPathGenerator(
</span><span class="cx">                 slowPathCall(
</span><span class="cx">                     outOfBounds, this, operationGetByValStringInt,
</span><del>-                    resultRegs, TrustedImmPtr::weakPointer(m_graph, globalObject), baseReg, propertyReg));
</del><ins>+                    scratchReg, TrustedImmPtr::weakPointer(m_graph, globalObject), baseReg, propertyReg));
+#else
+            addSlowPathGenerator(
+                slowPathCall(
+                    outOfBounds, this, operationGetByValStringInt,
+                    JSValueRegs(resultTagReg, scratchReg), TrustedImmPtr::weakPointer(m_graph, globalObject), baseReg, propertyReg));
+#endif
</ins><span class="cx">         }
</span><span class="cx">         
</span><del>-        jsValueResult(resultRegs, m_currentNode);
-    } else {
-        if (format == DataFormatJS)
-            jsValueResult(resultRegs, m_currentNode);
-        else {
-            ASSERT(format == DataFormatCell);
-            cellResult(resultRegs.payloadGPR(), m_currentNode);
-        }
-    }
</del><ins>+#if USE(JSVALUE64)
+        jsValueResult(scratchReg, m_currentNode);
+#else
+        jsValueResult(resultTagReg, scratchReg, m_currentNode);
+#endif
+    } else
+        cellResult(scratchReg, m_currentNode);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void SpeculativeJIT::compileFromCharCode(Node* node)
</span><span class="lines">@@ -3325,31 +3351,14 @@
</span><span class="cx">     }
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void SpeculativeJIT::setIntTypedArrayLoadResult(Node* node, JSValueRegs resultRegs, TypedArrayType type, bool canSpeculate, bool shouldBox)
</del><ins>+void SpeculativeJIT::setIntTypedArrayLoadResult(Node* node, GPRReg resultReg, TypedArrayType type, bool canSpeculate)
</ins><span class="cx"> {
</span><del>-    bool isUInt32 = elementSize(type) == 4 && !isSigned(type);
-    GPRReg resultReg = resultRegs.payloadGPR();
-
-    if (shouldBox) {
-        if (isUInt32) {
-            FPRTemporary fresult(this);
-            m_jit.convertInt32ToDouble(resultReg, fresult.fpr());
-            JITCompiler::Jump positive = m_jit.branch32(MacroAssembler::GreaterThanOrEqual, resultReg, TrustedImm32(0));
-            m_jit.addDouble(JITCompiler::AbsoluteAddress(&AssemblyHelpers::twoToThe32), fresult.fpr());
-            positive.link(&m_jit);
-            m_jit.boxDouble(fresult.fpr(), resultRegs);
-        } else
-            m_jit.boxInt32(resultRegs.payloadGPR(), resultRegs);
-        jsValueResult(resultRegs, node);
-        return;
-    }
-
-    if (!isUInt32) {
-        ASSERT(elementSize(type) < 4 || isSigned(type));
</del><ins>+    if (elementSize(type) < 4 || isSigned(type)) {
</ins><span class="cx">         strictInt32Result(resultReg, node);
</span><span class="cx">         return;
</span><span class="cx">     }
</span><del>-
</del><ins>+    
+    ASSERT(elementSize(type) == 4 && !isSigned(type));
</ins><span class="cx">     if (node->shouldSpeculateInt32() && canSpeculate) {
</span><span class="cx">         speculationCheck(Overflow, JSValueRegs(), nullptr, m_jit.branch32(MacroAssembler::LessThan, resultReg, TrustedImm32(0)));
</span><span class="cx">         strictInt32Result(resultReg, node);
</span><span class="lines">@@ -3373,7 +3382,7 @@
</span><span class="cx">     doubleResult(fresult.fpr(), node);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void SpeculativeJIT::compileGetByValOnIntTypedArray(Node* node, TypedArrayType type, const ScopedLambda<std::tuple<JSValueRegs, DataFormat>(DataFormat preferredFormat)>& prefix)
</del><ins>+void SpeculativeJIT::compileGetByValOnIntTypedArray(Node* node, TypedArrayType type)
</ins><span class="cx"> {
</span><span class="cx">     ASSERT(isInt(type));
</span><span class="cx">     
</span><span class="lines">@@ -3385,15 +3394,13 @@
</span><span class="cx">     GPRReg propertyReg = property.gpr();
</span><span class="cx">     GPRReg storageReg = storage.gpr();
</span><span class="cx"> 
</span><del>-    JSValueRegs resultRegs;
-    DataFormat format;
-    std::tie(resultRegs, format) = prefix(DataFormatInt32);
-    bool shouldBox = format == DataFormatJS;
</del><ins>+    GPRTemporary result(this);
+    GPRReg resultReg = result.gpr();
</ins><span class="cx"> 
</span><span class="cx">     emitTypedArrayBoundsCheck(node, baseReg, propertyReg);
</span><del>-    loadFromIntTypedArray(storageReg, propertyReg, resultRegs.payloadGPR(), type);
</del><ins>+    loadFromIntTypedArray(storageReg, propertyReg, resultReg, type);
</ins><span class="cx">     constexpr bool canSpeculate = true;
</span><del>-    setIntTypedArrayLoadResult(node, resultRegs, type, canSpeculate, shouldBox);
</del><ins>+    setIntTypedArrayLoadResult(node, resultReg, type, canSpeculate);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> bool SpeculativeJIT::getIntTypedArrayStoreOperand(
</span><span class="lines">@@ -3631,7 +3638,7 @@
</span><span class="cx">     noResult(node);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void SpeculativeJIT::compileGetByValOnFloatTypedArray(Node* node, TypedArrayType type, const ScopedLambda<std::tuple<JSValueRegs, DataFormat>(DataFormat preferredFormat)>& prefix)
</del><ins>+void SpeculativeJIT::compileGetByValOnFloatTypedArray(Node* node, TypedArrayType type)
</ins><span class="cx"> {
</span><span class="cx">     ASSERT(isFloat(type));
</span><span class="cx">     
</span><span class="lines">@@ -3643,10 +3650,6 @@
</span><span class="cx">     GPRReg propertyReg = property.gpr();
</span><span class="cx">     GPRReg storageReg = storage.gpr();
</span><span class="cx"> 
</span><del>-    JSValueRegs resultRegs;
-    DataFormat format;
-    std::tie(resultRegs, format) = prefix(DataFormatDouble);
-
</del><span class="cx">     FPRTemporary result(this);
</span><span class="cx">     FPRReg resultReg = result.fpr();
</span><span class="cx">     emitTypedArrayBoundsCheck(node, baseReg, propertyReg);
</span><span class="lines">@@ -3663,13 +3666,7 @@
</span><span class="cx">         RELEASE_ASSERT_NOT_REACHED();
</span><span class="cx">     }
</span><span class="cx">     
</span><del>-    if (format == DataFormatJS) {
-        m_jit.boxDouble(resultReg, resultRegs);
-        jsValueResult(resultRegs, node);
-    } else {
-        ASSERT(format == DataFormatDouble);
-        doubleResult(resultReg, node);
-    }
</del><ins>+    doubleResult(resultReg, node);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void SpeculativeJIT::compilePutByValForFloatTypedArray(GPRReg base, GPRReg property, Node* node, TypedArrayType type)
</span><span class="lines">@@ -3708,7 +3705,7 @@
</span><span class="cx">     noResult(node);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void SpeculativeJIT::compileGetByValForObjectWithString(Node* node, const ScopedLambda<std::tuple<JSValueRegs, DataFormat>(DataFormat preferredFormat)>& prefix)
</del><ins>+void SpeculativeJIT::compileGetByValForObjectWithString(Node* node)
</ins><span class="cx"> {
</span><span class="cx">     SpeculateCellOperand arg1(this, m_graph.varArgChild(node, 0));
</span><span class="cx">     SpeculateCellOperand arg2(this, m_graph.varArgChild(node, 1));
</span><span class="lines">@@ -3716,13 +3713,12 @@
</span><span class="cx">     GPRReg arg1GPR = arg1.gpr();
</span><span class="cx">     GPRReg arg2GPR = arg2.gpr();
</span><span class="cx"> 
</span><del>-    JSValueRegs resultRegs;
-    std::tie(resultRegs, std::ignore) = prefix(DataFormatJS);
-
</del><span class="cx">     speculateObject(m_graph.varArgChild(node, 0), arg1GPR);
</span><span class="cx">     speculateString(m_graph.varArgChild(node, 1), arg2GPR);
</span><span class="cx"> 
</span><span class="cx">     flushRegisters();
</span><ins>+    JSValueRegsFlushedCallResult result(this);
+    JSValueRegs resultRegs = result.regs();
</ins><span class="cx">     callOperation(operationGetByValObjectString, resultRegs, TrustedImmPtr::weakPointer(m_graph, m_graph.globalObjectFor(node->origin.semantic)), arg1GPR, arg2GPR);
</span><span class="cx">     m_jit.exceptionCheck();
</span><span class="cx"> 
</span><span class="lines">@@ -3729,7 +3725,7 @@
</span><span class="cx">     jsValueResult(resultRegs, node);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void SpeculativeJIT::compileGetByValForObjectWithSymbol(Node* node, const ScopedLambda<std::tuple<JSValueRegs, DataFormat>(DataFormat preferredFormat)>& prefix)
</del><ins>+void SpeculativeJIT::compileGetByValForObjectWithSymbol(Node* node)
</ins><span class="cx"> {
</span><span class="cx">     SpeculateCellOperand arg1(this, m_graph.varArgChild(node, 0));
</span><span class="cx">     SpeculateCellOperand arg2(this, m_graph.varArgChild(node, 1));
</span><span class="lines">@@ -3737,13 +3733,12 @@
</span><span class="cx">     GPRReg arg1GPR = arg1.gpr();
</span><span class="cx">     GPRReg arg2GPR = arg2.gpr();
</span><span class="cx"> 
</span><del>-    JSValueRegs resultRegs;
-    std::tie(resultRegs, std::ignore) = prefix(DataFormatJS);
-
</del><span class="cx">     speculateObject(m_graph.varArgChild(node, 0), arg1GPR);
</span><span class="cx">     speculateSymbol(m_graph.varArgChild(node, 1), arg2GPR);
</span><span class="cx"> 
</span><span class="cx">     flushRegisters();
</span><ins>+    JSValueRegsFlushedCallResult result(this);
+    JSValueRegs resultRegs = result.regs();
</ins><span class="cx">     callOperation(operationGetByValObjectSymbol, resultRegs, TrustedImmPtr::weakPointer(m_graph, m_graph.globalObjectFor(node->origin.semantic)), arg1GPR, arg2GPR);
</span><span class="cx">     m_jit.exceptionCheck();
</span><span class="cx"> 
</span><span class="lines">@@ -8045,17 +8040,17 @@
</span><span class="cx">     strictInt32Result(vectorGPR, node);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void SpeculativeJIT::compileGetByValOnDirectArguments(Node* node, const ScopedLambda<std::tuple<JSValueRegs, DataFormat>(DataFormat preferredFormat)>& prefix)
</del><ins>+void SpeculativeJIT::compileGetByValOnDirectArguments(Node* node)
</ins><span class="cx"> {
</span><span class="cx">     SpeculateCellOperand base(this, m_graph.varArgChild(node, 0));
</span><span class="cx">     SpeculateStrictInt32Operand property(this, m_graph.varArgChild(node, 1));
</span><ins>+    JSValueRegsTemporary result(this);
+    GPRTemporary scratch(this);
</ins><span class="cx">     
</span><span class="cx">     GPRReg baseReg = base.gpr();
</span><span class="cx">     GPRReg propertyReg = property.gpr();
</span><del>-
-    JSValueRegs resultRegs;
-    std::tie(resultRegs, std::ignore) = prefix(DataFormatJS);
-    GPRReg scratchReg = resultRegs.payloadGPR();
</del><ins>+    JSValueRegs resultRegs = result.regs();
+    GPRReg scratchReg = scratch.gpr();
</ins><span class="cx">     
</span><span class="cx">     if (!m_compileOkay)
</span><span class="cx">         return;
</span><span class="lines">@@ -8086,23 +8081,22 @@
</span><span class="cx">     jsValueResult(resultRegs, node);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void SpeculativeJIT::compileGetByValOnScopedArguments(Node* node, const ScopedLambda<std::tuple<JSValueRegs, DataFormat>(DataFormat preferredFormat)>& prefix)
</del><ins>+void SpeculativeJIT::compileGetByValOnScopedArguments(Node* node)
</ins><span class="cx"> {
</span><span class="cx">     SpeculateCellOperand base(this, m_graph.varArgChild(node, 0));
</span><span class="cx">     SpeculateStrictInt32Operand property(this, m_graph.varArgChild(node, 1));
</span><ins>+    JSValueRegsTemporary result(this);
</ins><span class="cx">     GPRTemporary scratch(this);
</span><span class="cx">     GPRTemporary scratch2(this);
</span><span class="cx">     
</span><span class="cx">     GPRReg baseReg = base.gpr();
</span><span class="cx">     GPRReg propertyReg = property.gpr();
</span><ins>+    JSValueRegs resultRegs = result.regs();
</ins><span class="cx">     GPRReg scratchReg = scratch.gpr();
</span><span class="cx">     GPRReg scratch2Reg = scratch2.gpr();
</span><span class="cx">     
</span><span class="cx">     if (!m_compileOkay)
</span><span class="cx">         return;
</span><del>-
-    JSValueRegs resultRegs;
-    std::tie(resultRegs, std::ignore) = prefix(DataFormatJS);
</del><span class="cx">     
</span><span class="cx">     m_jit.loadPtr(
</span><span class="cx">         MacroAssembler::Address(baseReg, ScopedArguments::offsetOfStorage()), resultRegs.payloadGPR());
</span><span class="lines">@@ -13450,360 +13444,46 @@
</span><span class="cx">     noResult(node);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void SpeculativeJIT::compileEnumeratorNextUpdateIndexAndMode(Node* node)
</del><ins>+void SpeculativeJIT::compileGetEnumerableLength(Node* node)
</ins><span class="cx"> {
</span><del>-    Edge baseEdge = m_graph.varArgChild(node, 0);
-    SpeculateStrictInt32Operand index(this, m_graph.varArgChild(node, 1));
-    SpeculateStrictInt32Operand mode(this, m_graph.varArgChild(node, 2));
-    SpeculateCellOperand enumerator(this, m_graph.varArgChild(node, 3));
-
-    GPRReg indexGPR = index.gpr();
-    GPRReg modeGPR = mode.gpr();
</del><ins>+    SpeculateCellOperand enumerator(this, node->child1());
+    GPRTemporary result(this, Reuse, enumerator);
</ins><span class="cx">     GPRReg enumeratorGPR = enumerator.gpr();
</span><ins>+    GPRReg resultGPR = result.gpr();
</ins><span class="cx"> 
</span><del>-    if (node->enumeratorMetadata() == JSPropertyNameEnumerator::IndexedMode) {
-        JSValueRegsTemporary result(this);
-        GPRTemporary scratch(this, Reuse, index);
-        JSValueRegs resultRegs = result.regs();
</del><ins>+    m_jit.load32(MacroAssembler::Address(enumeratorGPR, JSPropertyNameEnumerator::indexedLengthOffset()), resultGPR);
+    strictInt32Result(resultGPR, node);
+}
</ins><span class="cx"> 
</span><del>-        speculationCheck(BadCache, JSValueSource(), node, m_jit.branch32(MacroAssembler::NotEqual, MacroAssembler::Address(enumeratorGPR, JSPropertyNameEnumerator::endGenericPropertyIndexOffset()), TrustedImm32(0)));
</del><ins>+void SpeculativeJIT::compileHasEnumerableProperty(Node* node)
+{
+    JSValueOperand base(this, node->child1());
+    SpeculateCellOperand property(this, node->child2());
</ins><span class="cx"> 
</span><del>-        MacroAssembler::Label incrementLoop;
-        MacroAssembler::Jump done;
-        compileHasIndexedProperty(node, operationHasEnumerableIndexedProperty, scopedLambda<std::tuple<GPRReg, GPRReg>()>([&] {
</del><ins>+    JSValueRegs baseRegs = base.jsValueRegs();
+    GPRReg propertyGPR = property.gpr();
</ins><span class="cx"> 
</span><del>-            m_jit.move(indexGPR, scratch.gpr());
-            MacroAssembler::Jump initMode = m_jit.branchTest32(MacroAssembler::Zero, modeGPR);
-
-            incrementLoop = m_jit.label();
-            m_jit.add32(TrustedImm32(1), scratch.gpr());
-
-            initMode.link(&m_jit);
-            done = m_jit.branch32(MacroAssembler::AboveOrEqual, scratch.gpr(), MacroAssembler::Address(enumeratorGPR, JSPropertyNameEnumerator::indexedLengthOffset()));
-            return std::make_pair(scratch.gpr(), resultRegs.payloadGPR());
-        }));
-        m_jit.branchTest32(MacroAssembler::Zero, resultRegs.payloadGPR()).linkTo(incrementLoop, &m_jit);
-
-        done.link(&m_jit);
-
-#if USE(JSVALUE64)
-        m_jit.move(TrustedImm64(JSValue::DoubleEncodeOffset | static_cast<uint64_t>(JSPropertyNameEnumerator::IndexedMode) << 32), resultRegs.payloadGPR());
-        m_jit.or64(scratch.gpr(), resultRegs.payloadGPR());
-#else
-        m_jit.move(TrustedImm32(JSPropertyNameEnumerator::IndexedMode), resultRegs.tagGPR());
-#endif
-
-        jsValueResult(resultRegs, node);
-        return;
-    }
-
-    if (node->enumeratorMetadata() == JSPropertyNameEnumerator::OwnStructureMode && baseEdge.useKind() == CellUse) {
-        SpeculateCellOperand base(this, baseEdge);
-        JSValueRegsTemporary result(this);
-        GPRReg baseGPR = base.gpr();
-        JSValueRegs resultRegs = result.regs();
-
-        // Has the same structure as the enumerator.
-        m_jit.load32(MacroAssembler::Address(baseGPR, JSCell::structureIDOffset()), resultRegs.payloadGPR());
-        speculationCheck(BadCache, JSValueSource(), node, m_jit.branch32(MacroAssembler::NotEqual, resultRegs.payloadGPR(), MacroAssembler::Address(enumeratorGPR, JSPropertyNameEnumerator::cachedStructureIDOffset())));
-
-        m_jit.load32(MacroAssembler::Address(enumeratorGPR, JSPropertyNameEnumerator::modeSetOffset()), resultRegs.payloadGPR());
-        speculationCheck(BadCache, JSValueSource(), node, m_jit.branch32(MacroAssembler::NotEqual, TrustedImm32(JSPropertyNameEnumerator::OwnStructureMode), resultRegs.payloadGPR()));
-
-        m_jit.move(indexGPR, resultRegs.payloadGPR());
-        MacroAssembler::Jump initMode = m_jit.branchTest32(MacroAssembler::Zero, modeGPR);
-
-        m_jit.add32(MacroAssembler::TrustedImm32(1), resultRegs.payloadGPR());
-
-        initMode.link(&m_jit);
-#if USE(JSVALUE64)
-        m_jit.or64(TrustedImm64(JSValue::DoubleEncodeOffset | static_cast<uint64_t>(JSPropertyNameEnumerator::OwnStructureMode) << 32), resultRegs.payloadGPR());
-#else
-        m_jit.move(TrustedImm32(JSPropertyNameEnumerator::OwnStructureMode), resultRegs.tagGPR());
-#endif
-
-        jsValueResult(resultRegs, node);
-        return;
-    }
-
-    JSValueOperand base(this, baseEdge);
-    JSValueRegs baseRegs = base.regs();
-
</del><span class="cx">     flushRegisters();
</span><span class="cx">     JSValueRegsFlushedCallResult result(this);
</span><span class="cx">     JSValueRegs resultRegs = result.regs();
</span><del>-    callOperation(operationEnumeratorNextUpdateIndexAndMode, resultRegs, TrustedImmPtr::weakPointer(m_graph, m_graph.globalObjectFor(node->origin.semantic)), baseRegs, indexGPR, modeGPR, enumeratorGPR);
</del><ins>+    callOperation(operationHasEnumerableProperty, resultRegs, TrustedImmPtr::weakPointer(m_graph, m_graph.globalObjectFor(node->origin.semantic)), baseRegs, propertyGPR);
</ins><span class="cx">     m_jit.exceptionCheck();
</span><del>-    jsValueResult(resultRegs, node);
</del><ins>+    blessedBooleanResult(resultRegs.payloadGPR(), node);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-void SpeculativeJIT::compileEnumeratorNextExtractIndex(Node* node)
</del><ins>+void SpeculativeJIT::compileToIndexString(Node* node)
</ins><span class="cx"> {
</span><del>-    JSValueOperand updatedPair(this, node->child1());
-    JSValueRegs pairRegs = updatedPair.jsValueRegs();
-    GPRReg payloadGPR = pairRegs.payloadGPR();
</del><ins>+    SpeculateInt32Operand index(this, node->child1());
+    GPRReg indexGPR = index.gpr();
</ins><span class="cx"> 
</span><del>-    GPRTemporary result(this);
</del><ins>+    flushRegisters();
+    GPRFlushedCallResult result(this);
</ins><span class="cx">     GPRReg resultGPR = result.gpr();
</span><del>-
-    m_jit.and32(TrustedImm32(std::numeric_limits<uint32_t>::max()), payloadGPR, resultGPR);
-
-    strictInt32Result(resultGPR, node);
</del><ins>+    callOperation(operationToIndexString, resultGPR, TrustedImmPtr::weakPointer(m_graph, m_graph.globalObjectFor(node->origin.semantic)), indexGPR);
+    m_jit.exceptionCheck();
+    cellResult(resultGPR, node);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-void SpeculativeJIT::compileEnumeratorNextExtractMode(Node* node)
-{
-    JSValueOperand updatedPair(this, node->child1());
-    JSValueRegs pairRegs = updatedPair.jsValueRegs();
-    GPRReg pairGPR = is64Bit() ? pairRegs.payloadGPR() : pairRegs.tagGPR();
-
-    GPRTemporary result(this);
-    GPRReg resultGPR = result.gpr();
-
-#if CPU(ARM64) && USE(JSVALUE64)
-    m_jit.extractUnsignedBitfield64(pairGPR, TrustedImm32(32), TrustedImm32(WTF::fastLog2(static_cast<unsigned>(JSPropertyNameEnumerator::enumerationModeMask + 1))), resultGPR);
-#else
-#if USE(JSVALUE64)
-    m_jit.rshift64(pairGPR, TrustedImm32(32), resultGPR);
-#else
-    m_jit.move(pairGPR, resultGPR);
-#endif
-    m_jit.and32(TrustedImm32(JSPropertyNameEnumerator::enumerationModeMask), resultGPR);
-#endif
-
-    strictInt32Result(resultGPR, node);
-}
-
-void SpeculativeJIT::compileEnumeratorNextUpdatePropertyName(Node* node)
-{
-    SpeculateStrictInt32Operand indexOperand(this, node->child1());
-    SpeculateStrictInt32Operand modeOperand(this, node->child2());
-    SpeculateCellOperand enumeratorOperand(this, node->child3());
-    JSValueRegsTemporary resultTemp(this);
-
-    GPRReg index = indexOperand.gpr();
-    GPRReg mode = modeOperand.gpr();
-    GPRReg enumerator = enumeratorOperand.gpr();
-    JSValueRegs resultRegs = resultTemp.regs();
-
-    OptionSet seenModes = node->enumeratorMetadata();
-
-    MacroAssembler::JumpList doneCases;
-    MacroAssembler::Jump operationCall;
-
-    bool needsOperation = seenModes.contains(JSPropertyNameEnumerator::IndexedMode);
-
-    // Make sure we flush on all code paths if we could call the operation.
-    if (needsOperation)
-        flushRegisters();
-
-    if (seenModes.containsAny({ JSPropertyNameEnumerator::OwnStructureMode, JSPropertyNameEnumerator::GenericMode })) {
-
-        if (needsOperation)
-            operationCall = m_jit.branchTest32(MacroAssembler::NonZero, mode, TrustedImm32(JSPropertyNameEnumerator::IndexedMode));
-
-        auto outOfBounds = m_jit.branch32(MacroAssembler::AboveOrEqual, index, MacroAssembler::Address(enumerator, JSPropertyNameEnumerator::endGenericPropertyIndexOffset()));
-
-        m_jit.loadPtr(MacroAssembler::Address(enumerator, JSPropertyNameEnumerator::cachedPropertyNamesVectorOffset()), resultRegs.payloadGPR());
-        m_jit.loadPtr(MacroAssembler::BaseIndex(resultRegs.payloadGPR(), index, MacroAssembler::ScalePtr), resultRegs.payloadGPR());
-#if USE(JSVALUE32_64)
-        m_jit.move(TrustedImm32(JSValue::CellTag), resultRegs.tagGPR());
-#endif
-        doneCases.append(m_jit.jump());
-
-        outOfBounds.link(&m_jit);
-        m_jit.moveTrustedValue(jsNull(), resultRegs);
-    }
-
-    if (needsOperation) {
-        if (operationCall.isSet()) {
-            doneCases.append(m_jit.jump());
-            operationCall.link(&m_jit);
-        }
-        callOperation(operationEnumeratorNextUpdatePropertyName, resultRegs, TrustedImmPtr::weakPointer(m_graph, m_graph.globalObjectFor(node->origin.semantic)), index, mode, enumerator);
-        m_jit.exceptionCheck();
-    }
-
-    doneCases.link(&m_jit);
-    jsValueResult(resultRegs, node);
-}
-
-void SpeculativeJIT::compileEnumeratorGetByVal(Node* node)
-{
-    Edge baseEdge = m_graph.varArgChild(node, 0);
-    auto generate = [&] (GPRReg baseCellGPR) {
-        MacroAssembler::JumpList doneCases;
-        JSValueRegsTemporary result;
-        JSValueRegs resultRegs;
-        GPRReg indexGPR;
-        GPRReg enumeratorGPR;
-        MacroAssembler::Jump badStructureSlowPath;
-
-        compileGetByVal(node, scopedLambda<std::tuple<JSValueRegs, DataFormat>(DataFormat)>([&] (DataFormat) {
-            Edge storageEdge = m_graph.varArgChild(node, 2);
-            StorageOperand storage;
-            if (storageEdge)
-                storage.emplace(this, storageEdge);
-            SpeculateStrictInt32Operand index(this, m_graph.varArgChild(node, 3));
-            SpeculateStrictInt32Operand mode(this, m_graph.varArgChild(node, 4));
-            SpeculateCellOperand enumerator(this, m_graph.varArgChild(node, 5));
-
-            GPRReg modeGPR = mode.gpr();
-            indexGPR = index.gpr();
-            enumeratorGPR = enumerator.gpr();
-
-            result = JSValueRegsTemporary(this);
-            resultRegs = result.regs();
-            GPRReg scratchGPR = resultRegs.payloadGPR();
-
-            bool haveStorage = !!storageEdge;
-            GPRTemporary storageTemporary;
-            GPRReg storageGPR;
-            if (!haveStorage) {
-                storageTemporary = GPRTemporary(this, Reuse, enumerator);
-                storageGPR = storageTemporary.gpr();
-            } else
-                storageGPR = storage.gpr();
-
-            MacroAssembler::JumpList notFastNamedCases;
-
-            // FIXME: We shouldn't generate this code if we know base is not an object.
-            notFastNamedCases.append(m_jit.branchTest32(MacroAssembler::NonZero, modeGPR, TrustedImm32(JSPropertyNameEnumerator::IndexedMode | JSPropertyNameEnumerator::GenericMode)));
-            {
-                if (!m_state.forNode(baseEdge).isType(SpecCell))
-                    notFastNamedCases.append(m_jit.branchIfNotCell(baseCellGPR));
-
-                // Check the structure
-                // FIXME: If we know there's only one structure for base we can just embed it here.
-                m_jit.load32(MacroAssembler::Address(baseCellGPR, JSCell::structureIDOffset()), scratchGPR);
-
-                auto badStructure = m_jit.branch32(
-                    MacroAssembler::NotEqual,
-                    scratchGPR,
-                    MacroAssembler::Address(
-                        enumeratorGPR, JSPropertyNameEnumerator::cachedStructureIDOffset()));
-
-                // FIXME: Maybe we should have a better way to represent Indexed+Named?
-                if (m_graph.varArgChild(node, 1).node() == m_graph.varArgChild(node, 3).node())
-                    badStructureSlowPath = badStructure;
-                else
-                    notFastNamedCases.append(badStructure);
-
-                // Compute the offset
-                // If index is less than the enumerator's cached inline storage, then it's an inline access
-                MacroAssembler::Jump outOfLineAccess = m_jit.branch32(MacroAssembler::AboveOrEqual,
-                    indexGPR, MacroAssembler::Address(enumeratorGPR, JSPropertyNameEnumerator::cachedInlineCapacityOffset()));
-
-                m_jit.loadValue(MacroAssembler::BaseIndex(baseCellGPR, indexGPR, MacroAssembler::TimesEight, JSObject::offsetOfInlineStorage()), resultRegs);
-
-                doneCases.append(m_jit.jump());
-
-                // Otherwise it's out of line
-                outOfLineAccess.link(&m_jit);
-                m_jit.move(indexGPR, scratchGPR);
-                m_jit.sub32(MacroAssembler::Address(enumeratorGPR, JSPropertyNameEnumerator::cachedInlineCapacityOffset()), scratchGPR);
-                m_jit.neg32(scratchGPR);
-                m_jit.signExtend32ToPtr(scratchGPR, scratchGPR);
-                if (!haveStorage)
-                    m_jit.loadPtr(MacroAssembler::Address(baseCellGPR, JSObject::butterflyOffset()), storageGPR);
-                int32_t offsetOfFirstProperty = static_cast<int32_t>(offsetInButterfly(firstOutOfLineOffset)) * sizeof(EncodedJSValue);
-                m_jit.loadValue(MacroAssembler::BaseIndex(storageGPR, scratchGPR, MacroAssembler::TimesEight, offsetOfFirstProperty), resultRegs);
-                doneCases.append(m_jit.jump());
-            }
-
-            notFastNamedCases.link(&m_jit);
-            return std::make_pair(resultRegs, DataFormatJS);
-        }));
-
-        // We rely on compileGetByVal to call jsValueResult for us.
-        // FIXME: This is kinda hacky...
-        ASSERT(generationInfo(node).jsValueRegs() == resultRegs && generationInfo(node).registerFormat() == DataFormatJS);
-
-        if (badStructureSlowPath.isSet())
-            addSlowPathGenerator(slowPathCall(badStructureSlowPath, this, operationEnumeratorRecoverNameAndGetByVal, resultRegs, TrustedImmPtr::weakPointer(m_graph, m_graph.globalObjectFor(node->origin.semantic)), baseCellGPR, indexGPR, enumeratorGPR));
-
-        doneCases.link(&m_jit);
-    };
-
-    if (isCell(baseEdge.useKind())) {
-        // Use manual operand speculation since Fixup may have picked a UseKind more restrictive than CellUse.
-        speculate(node, baseEdge);
-        SpeculateCellOperand baseOperand(this, baseEdge, ManualOperandSpeculation);
-        generate(baseOperand.gpr());
-    } else {
-        JSValueOperand baseOperand(this, baseEdge);
-        generate(baseOperand.gpr());
-    }
-}
-
-template<typename SlowPathFunctionType>
-void SpeculativeJIT::compileEnumeratorHasProperty(Node* node, SlowPathFunctionType slowPathFunction)
-{
-    Edge baseEdge = m_graph.varArgChild(node, 0);
-    auto generate = [&] (auto base, GPRReg baseCellGPR) {
-        JSValueOperand propertyName(this, m_graph.varArgChild(node, 1));
-        SpeculateStrictInt32Operand index(this, m_graph.varArgChild(node, 2));
-        SpeculateStrictInt32Operand mode(this, m_graph.varArgChild(node, 3));
-        SpeculateCellOperand enumerator(this, m_graph.varArgChild(node, 4));
-
-        JSValueRegs propertyNameRegs = propertyName.regs();
-        GPRReg indexGPR = index.gpr();
-        GPRReg modeGPR = mode.gpr();
-        GPRReg enumeratorGPR = enumerator.gpr();
-
-        JSValueRegsTemporary result(this);
-        JSValueRegs resultRegs = result.regs();
-
-        MacroAssembler::JumpList operationCases;
-
-        if (m_state.forNode(baseEdge).m_type & ~SpecCell)
-            operationCases.append(m_jit.branchIfNotCell(base));
-
-        // FIXME: We shouldn't generate this code if we know base is not a cell.
-        operationCases.append(m_jit.branchTest32(MacroAssembler::Zero, modeGPR, TrustedImm32(JSPropertyNameEnumerator::OwnStructureMode)));
-
-        m_jit.load32(MacroAssembler::Address(baseCellGPR, JSCell::structureIDOffset()), resultRegs.payloadGPR());
-        operationCases.append(m_jit.branch32(MacroAssembler::NotEqual, resultRegs.payloadGPR(), MacroAssembler::Address(enumeratorGPR, JSPropertyNameEnumerator::cachedStructureIDOffset())));
-
-        moveTrueTo(resultRegs.payloadGPR());
-        MacroAssembler::Jump done = m_jit.jump();
-
-        operationCases.link(&m_jit);
-
-        flushRegisters();
-#if USE(JSVALUE32_64)
-        m_jit.move(TrustedImm32(JSValue::CellTag), resultRegs.tagGPR());
-        auto baseRegs = JSValueRegs(baseCellGPR, resultRegs.tagGPR());
-#else
-        auto baseRegs = base;
-#endif
-        callOperation(slowPathFunction, resultRegs, TrustedImmPtr::weakPointer(m_graph, m_graph.globalObjectFor(node->origin.semantic)), baseRegs, propertyNameRegs, indexGPR, modeGPR);
-        m_jit.exceptionCheck();
-
-        done.link(&m_jit);
-
-        blessedBooleanResult(resultRegs.payloadGPR(), node);
-    };
-
-    if (isCell(baseEdge.useKind())) {
-        SpeculateCellOperand base(this, baseEdge);
-        generate(base.gpr(), base.gpr());
-    } else {
-        JSValueOperand base(this, baseEdge);
-        generate(base.regs(), base.regs().payloadGPR());
-    }
-}
-
-void SpeculativeJIT::compileEnumeratorInByVal(Node* node)
-{
-    compileEnumeratorHasProperty(node, operationEnumeratorInByVal);
-}
-
-void SpeculativeJIT::compileEnumeratorHasOwnProperty(Node* node)
-{
-    compileEnumeratorHasProperty(node, operationEnumeratorHasOwnProperty);
-}
-
</del><span class="cx"> void SpeculativeJIT::compilePutByIdFlush(Node* node)
</span><span class="cx"> {
</span><span class="cx">     std::optional<GPRTemporary> stubInfo;
</span><span class="lines">@@ -13944,6 +13624,67 @@
</span><span class="cx">     blessedBooleanResult(tempGPR, node);
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void SpeculativeJIT::compileHasEnumerableStructureProperty(Node* node)
+{
+    JSValueOperand base(this, node->child1());
+    SpeculateCellOperand property(this, node->child2());
+    SpeculateCellOperand enumerator(this, node->child3());
+    JSValueRegsTemporary result(this);
+
+    JSValueRegs baseRegs = base.jsValueRegs();
+    GPRReg propertyGPR = property.gpr();
+    JSValueRegs resultRegs = result.regs();
+
+    CCallHelpers::JumpList wrongStructure;
+
+    wrongStructure.append(m_jit.branchIfNotCell(baseRegs));
+
+    m_jit.load32(MacroAssembler::Address(baseRegs.payloadGPR(), JSCell::structureIDOffset()), resultRegs.payloadGPR());
+    wrongStructure.append(m_jit.branch32(MacroAssembler::NotEqual,
+        resultRegs.payloadGPR(),
+        MacroAssembler::Address(enumerator.gpr(), JSPropertyNameEnumerator::cachedStructureIDOffset())));
+
+    moveTrueTo(resultRegs.payloadGPR());
+
+    addSlowPathGenerator(slowPathCall(wrongStructure, this, operationHasEnumerableProperty, resultRegs, TrustedImmPtr::weakPointer(m_graph, m_graph.globalObjectFor(node->origin.semantic)), baseRegs, propertyGPR));
+    blessedBooleanResult(resultRegs.payloadGPR(), node);
+}
+
+template <typename Function>
+void SpeculativeJIT::compileHasOwnStructurePropertyImpl(Node* node, Function slowPath)
+{
+    SpeculateCellOperand base(this, node->child1());
+    SpeculateCellOperand property(this, node->child2());
+    SpeculateCellOperand enumerator(this, node->child3());
+    JSValueRegsTemporary result(this);
+
+    GPRReg baseGPR = base.gpr();
+    GPRReg propertyGPR = property.gpr();
+    JSValueRegs resultRegs = result.regs();
+
+    CCallHelpers::JumpList wrongStructure;
+
+    m_jit.load32(MacroAssembler::Address(baseGPR, JSCell::structureIDOffset()), resultRegs.payloadGPR());
+    wrongStructure.append(m_jit.branch32(MacroAssembler::NotEqual,
+        resultRegs.payloadGPR(),
+        MacroAssembler::Address(enumerator.gpr(), JSPropertyNameEnumerator::cachedStructureIDOffset())));
+
+    moveTrueTo(resultRegs.payloadGPR());
+
+    addSlowPathGenerator(slowPathCall(wrongStructure, this, slowPath, resultRegs, TrustedImmPtr::weakPointer(m_graph, m_graph.globalObjectFor(node->origin.semantic)), baseGPR, propertyGPR));
+    blessedBooleanResult(resultRegs.payloadGPR(), node);
+}
+
+void SpeculativeJIT::compileHasOwnStructureProperty(Node* node)
+{
+    compileHasOwnStructurePropertyImpl(node, operationHasOwnStructureProperty);
+}
+
+void SpeculativeJIT::compileInStructureProperty(Node* node)
+{
+    compileHasOwnStructurePropertyImpl(node, operationInStructureProperty);
+}
+
</ins><span class="cx"> void SpeculativeJIT::compileGetPropertyEnumerator(Node* node)
</span><span class="cx"> {
</span><span class="cx">     if (node->child1().useKind() == CellUse) {
</span><span class="lines">@@ -13970,6 +13711,39 @@
</span><span class="cx">     cellResult(resultGPR, node);
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void SpeculativeJIT::compileGetEnumeratorPname(Node* node)
+{
+    ASSERT(node->op() == GetEnumeratorStructurePname || node->op() == GetEnumeratorGenericPname);
+    SpeculateCellOperand enumerator(this, node->child1());
+    SpeculateStrictInt32Operand index(this, node->child2());
+    GPRTemporary scratch(this);
+    JSValueRegsTemporary result(this);
+
+    GPRReg enumeratorGPR = enumerator.gpr();
+    GPRReg indexGPR = index.gpr();
+    GPRReg scratchGPR = scratch.gpr();
+    JSValueRegs resultRegs = result.regs();
+
+    MacroAssembler::Jump inBounds = m_jit.branch32(MacroAssembler::Below, indexGPR,
+        MacroAssembler::Address(enumeratorGPR, (node->op() == GetEnumeratorStructurePname)
+            ? JSPropertyNameEnumerator::endStructurePropertyIndexOffset()
+            : JSPropertyNameEnumerator::endGenericPropertyIndexOffset()));
+
+    m_jit.moveValue(jsNull(), resultRegs);
+
+    MacroAssembler::Jump done = m_jit.jump();
+    inBounds.link(&m_jit);
+
+    m_jit.loadPtr(MacroAssembler::Address(enumeratorGPR, JSPropertyNameEnumerator::cachedPropertyNamesVectorOffset()), scratchGPR);
+    m_jit.loadPtr(MacroAssembler::BaseIndex(scratchGPR, indexGPR, MacroAssembler::ScalePtr), resultRegs.payloadGPR());
+#if USE(JSVALUE32_64)
+    m_jit.move(MacroAssembler::TrustedImm32(JSValue::CellTag), resultRegs.tagGPR());
+#endif
+
+    done.link(&m_jit);
+    jsValueResult(resultRegs, node);
+}
+
</ins><span class="cx"> void SpeculativeJIT::compileGetExecutable(Node* node)
</span><span class="cx"> {
</span><span class="cx">     SpeculateCellOperand function(this, node->child1());
</span><span class="lines">@@ -15162,13 +14936,15 @@
</span><span class="cx">         sizeGPR, storageGPR));
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void SpeculativeJIT::compileHasIndexedProperty(Node* node, S_JITOperation_GCZ slowPathOperation, const ScopedLambda<std::tuple<GPRReg, GPRReg>()>& prefix)
</del><ins>+void SpeculativeJIT::compileHasIndexedProperty(Node* node, S_JITOperation_GCZ slowPathOperation)
</ins><span class="cx"> {
</span><span class="cx">     SpeculateCellOperand base(this, m_graph.varArgChild(node, 0));
</span><ins>+    SpeculateStrictInt32Operand index(this, m_graph.varArgChild(node, 1));
+    GPRTemporary result(this);
</ins><span class="cx"> 
</span><span class="cx">     GPRReg baseGPR = base.gpr();
</span><del>-    GPRReg indexGPR = InvalidGPRReg;
-    GPRReg resultGPR = InvalidGPRReg;
</del><ins>+    GPRReg indexGPR = index.gpr();
+    GPRReg resultGPR = result.gpr();
</ins><span class="cx"> 
</span><span class="cx">     MacroAssembler::JumpList slowCases;
</span><span class="cx">     ArrayMode mode = node->arrayMode();
</span><span class="lines">@@ -15175,15 +14951,13 @@
</span><span class="cx">     switch (mode.type()) {
</span><span class="cx">     case Array::Int32:
</span><span class="cx">     case Array::Contiguous: {
</span><del>-        ASSERT(!!m_graph.varArgChild(node, node->storageChildIndex()));
-        StorageOperand storage(this, m_graph.varArgChild(node, node->storageChildIndex()));
</del><ins>+        ASSERT(!!m_graph.varArgChild(node, 2));
+        StorageOperand storage(this, m_graph.varArgChild(node, 2));
</ins><span class="cx">         GPRTemporary scratch(this);
</span><span class="cx"> 
</span><span class="cx">         GPRReg storageGPR = storage.gpr();
</span><span class="cx">         GPRReg scratchGPR = scratch.gpr();
</span><span class="cx"> 
</span><del>-        std::tie(indexGPR, resultGPR) = prefix();
-
</del><span class="cx">         MacroAssembler::Jump outOfBounds = m_jit.branch32(MacroAssembler::AboveOrEqual, indexGPR, MacroAssembler::Address(storageGPR, Butterfly::offsetOfPublicLength()));
</span><span class="cx"> 
</span><span class="cx">         if (mode.isInBounds())
</span><span class="lines">@@ -15211,14 +14985,12 @@
</span><span class="cx">         break;
</span><span class="cx">     }
</span><span class="cx">     case Array::Double: {
</span><del>-        ASSERT(!!m_graph.varArgChild(node, node->storageChildIndex()));
-        StorageOperand storage(this, m_graph.varArgChild(node, node->storageChildIndex()));
</del><ins>+        ASSERT(!!m_graph.varArgChild(node, 2));
+        StorageOperand storage(this, m_graph.varArgChild(node, 2));
</ins><span class="cx">         FPRTemporary scratch(this);
</span><span class="cx">         FPRReg scratchFPR = scratch.fpr();
</span><span class="cx">         GPRReg storageGPR = storage.gpr();
</span><span class="cx"> 
</span><del>-        std::tie(indexGPR, resultGPR) = prefix();
-
</del><span class="cx">         MacroAssembler::Jump outOfBounds = m_jit.branch32(MacroAssembler::AboveOrEqual, indexGPR, MacroAssembler::Address(storageGPR, Butterfly::offsetOfPublicLength()));
</span><span class="cx"> 
</span><span class="cx">         if (mode.isInBounds())
</span><span class="lines">@@ -15242,15 +15014,13 @@
</span><span class="cx">         break;
</span><span class="cx">     }
</span><span class="cx">     case Array::ArrayStorage: {
</span><del>-        ASSERT(!!m_graph.varArgChild(node, node->storageChildIndex()));
-        StorageOperand storage(this, m_graph.varArgChild(node, node->storageChildIndex()));
</del><ins>+        ASSERT(!!m_graph.varArgChild(node, 2));
+        StorageOperand storage(this, m_graph.varArgChild(node, 2));
</ins><span class="cx">         GPRTemporary scratch(this);
</span><span class="cx"> 
</span><span class="cx">         GPRReg storageGPR = storage.gpr();
</span><span class="cx">         GPRReg scratchGPR = scratch.gpr();
</span><span class="cx"> 
</span><del>-        std::tie(indexGPR, resultGPR) = prefix();
-
</del><span class="cx">         MacroAssembler::Jump outOfBounds = m_jit.branch32(MacroAssembler::AboveOrEqual, indexGPR, MacroAssembler::Address(storageGPR, ArrayStorage::vectorLengthOffset()));
</span><span class="cx">         if (mode.isInBounds())
</span><span class="cx">             speculationCheck(OutOfBounds, JSValueRegs(), nullptr, outOfBounds);
</span><span class="lines">@@ -15279,7 +15049,6 @@
</span><span class="cx">     default: {
</span><span class="cx">         // FIXME: Optimize TypedArrays in HasIndexedProperty IC
</span><span class="cx">         // https://bugs.webkit.org/show_bug.cgi?id=221183
</span><del>-        std::tie(indexGPR, resultGPR) = prefix();
</del><span class="cx">         slowCases.append(m_jit.jump());
</span><span class="cx">         break;
</span><span class="cx">     }
</span><span class="lines">@@ -15286,8 +15055,69 @@
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     addSlowPathGenerator(slowPathCall(slowCases, this, slowPathOperation, resultGPR, TrustedImmPtr::weakPointer(m_graph, m_graph.globalObjectFor(node->origin.semantic)), baseGPR, indexGPR));
</span><ins>+
+    unblessedBooleanResult(resultGPR, node);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void SpeculativeJIT::compileGetDirectPname(Node* node)
+{
+    Edge& baseEdge = m_jit.graph().varArgChild(node, 0);
+    Edge& propertyEdge = m_jit.graph().varArgChild(node, 1);
+    Edge& indexEdge = m_jit.graph().varArgChild(node, 2);
+
+    SpeculateCellOperand base(this, baseEdge);
+    SpeculateCellOperand property(this, propertyEdge);
+    GPRReg baseGPR = base.gpr();
+    GPRReg propertyGPR = property.gpr();
+
+    Edge& enumeratorEdge = m_jit.graph().varArgChild(node, 3);
+    SpeculateStrictInt32Operand index(this, indexEdge);
+    SpeculateCellOperand enumerator(this, enumeratorEdge);
+    GPRTemporary scratch(this);
+    JSValueRegsTemporary result(this);
+
+    GPRReg indexGPR = index.gpr();
+    GPRReg enumeratorGPR = enumerator.gpr();
+    GPRReg scratchGPR = scratch.gpr();
+    JSValueRegs resultRegs = result.regs();
+
+    MacroAssembler::JumpList slowPath;
+
+    // Check the structure
+    m_jit.load32(MacroAssembler::Address(baseGPR, JSCell::structureIDOffset()), scratchGPR);
+    slowPath.append(
+        m_jit.branch32(
+            MacroAssembler::NotEqual,
+            scratchGPR,
+            MacroAssembler::Address(
+                enumeratorGPR, JSPropertyNameEnumerator::cachedStructureIDOffset())));
+
+    // Compute the offset
+    // If index is less than the enumerator's cached inline storage, then it's an inline access
+    MacroAssembler::Jump outOfLineAccess = m_jit.branch32(MacroAssembler::AboveOrEqual,
+        indexGPR, MacroAssembler::Address(enumeratorGPR, JSPropertyNameEnumerator::cachedInlineCapacityOffset()));
+
+    m_jit.loadValue(MacroAssembler::BaseIndex(baseGPR, indexGPR, MacroAssembler::TimesEight, JSObject::offsetOfInlineStorage()), resultRegs);
+
+    MacroAssembler::Jump done = m_jit.jump();
+
+    // Otherwise it's out of line
+    outOfLineAccess.link(&m_jit);
+    m_jit.loadPtr(MacroAssembler::Address(baseGPR, JSObject::butterflyOffset()), resultRegs.payloadGPR());
+    m_jit.move(indexGPR, scratchGPR);
+    m_jit.sub32(MacroAssembler::Address(enumeratorGPR, JSPropertyNameEnumerator::cachedInlineCapacityOffset()), scratchGPR);
+    m_jit.neg32(scratchGPR);
+    m_jit.signExtend32ToPtr(scratchGPR, scratchGPR);
+    int32_t offsetOfFirstProperty = static_cast<int32_t>(offsetInButterfly(firstOutOfLineOffset)) * sizeof(EncodedJSValue);
+    m_jit.loadValue(MacroAssembler::BaseIndex(resultRegs.payloadGPR(), scratchGPR, MacroAssembler::TimesEight, offsetOfFirstProperty), resultRegs);
+
+    done.link(&m_jit);
+
+    addSlowPathGenerator(slowPathCall(slowPath, this, operationGetByValCell, resultRegs, TrustedImmPtr::weakPointer(m_graph, m_graph.globalObjectFor(node->origin.semantic)), baseGPR, CCallHelpers::CellValue(propertyGPR)));
+
+    jsValueResult(resultRegs, node);
+}
+
</ins><span class="cx"> void SpeculativeJIT::compileExtractCatchLocal(Node* node)
</span><span class="cx"> {
</span><span class="cx">     JSValueRegsTemporary result(this);
</span></span></pre></div>
<a id="branchessafari612128branchSourceJavaScriptCoredfgDFGSpeculativeJITh"></a>
<div class="modfile"><h4>Modified: branches/safari-612.1.28-branch/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h (281021 => 281022)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-612.1.28-branch/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h    2021-08-13 16:39:44 UTC (rev 281021)
+++ branches/safari-612.1.28-branch/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h       2021-08-13 16:50:38 UTC (rev 281022)
</span><span class="lines">@@ -47,7 +47,6 @@
</span><span class="cx"> namespace JSC { namespace DFG {
</span><span class="cx"> 
</span><span class="cx"> class GPRTemporary;
</span><del>-class JSValueRegsTemporary;
</del><span class="cx"> class JSValueOperand;
</span><span class="cx"> class SlowPathGenerator;
</span><span class="cx"> class SpeculativeJIT;
</span><span class="lines">@@ -247,8 +246,6 @@
</span><span class="cx">     }
</span><span class="cx">     GPRReg allocate(GPRReg specific)
</span><span class="cx">     {
</span><del>-        if (specific == InvalidGPRReg)
-            allocate();
</del><span class="cx"> #if ENABLE(DFG_REGISTER_ALLOCATION_VALIDATION)
</span><span class="cx">         m_jit.addRegisterAllocationAtOffset(m_jit.debugOffset());
</span><span class="cx"> #endif
</span><span class="lines">@@ -1348,15 +1345,12 @@
</span><span class="cx">         return temporaryRegisterForPutByVal(temporary, node->arrayMode());
</span><span class="cx">     }
</span><span class="cx">     
</span><del>-    // We use a scopedLambda to placate register allocation validation.
-    void compileGetByVal(Node*, const ScopedLambda<std::tuple<JSValueRegs, DataFormat>(DataFormat preferredFormat)>& prefix);
-
</del><span class="cx">     void compileGetCharCodeAt(Node*);
</span><del>-    void compileGetByValOnString(Node*, const ScopedLambda<std::tuple<JSValueRegs, DataFormat>(DataFormat preferredFormat)>& prefix);
</del><ins>+    void compileGetByValOnString(Node*);
</ins><span class="cx">     void compileFromCharCode(Node*); 
</span><span class="cx"> 
</span><del>-    void compileGetByValOnDirectArguments(Node*, const ScopedLambda<std::tuple<JSValueRegs, DataFormat>(DataFormat preferredFormat)>& prefix);
-    void compileGetByValOnScopedArguments(Node*, const ScopedLambda<std::tuple<JSValueRegs, DataFormat>(DataFormat preferredFormat)>& prefix);
</del><ins>+    void compileGetByValOnDirectArguments(Node*);
+    void compileGetByValOnScopedArguments(Node*);
</ins><span class="cx"> 
</span><span class="cx">     void compileGetPrivateName(Node*);
</span><span class="cx">     void compileGetPrivateNameById(Node*);
</span><span class="lines">@@ -1430,12 +1424,12 @@
</span><span class="cx">     JITCompiler::Jump jumpForTypedArrayIsDetachedIfOutOfBounds(Node*, GPRReg baseGPR, JITCompiler::Jump outOfBounds);
</span><span class="cx">     void emitTypedArrayBoundsCheck(Node*, GPRReg baseGPR, GPRReg indexGPR);
</span><span class="cx">     void compileGetTypedArrayByteOffset(Node*);
</span><del>-    void compileGetByValOnIntTypedArray(Node*, TypedArrayType, const ScopedLambda<std::tuple<JSValueRegs, DataFormat>(DataFormat preferredFormat)>& prefix);
</del><ins>+    void compileGetByValOnIntTypedArray(Node*, TypedArrayType);
</ins><span class="cx">     void compilePutByValForIntTypedArray(GPRReg base, GPRReg property, Node*, TypedArrayType);
</span><del>-    void compileGetByValOnFloatTypedArray(Node*, TypedArrayType, const ScopedLambda<std::tuple<JSValueRegs, DataFormat>(DataFormat preferredFormat)>& prefix);
</del><ins>+    void compileGetByValOnFloatTypedArray(Node*, TypedArrayType);
</ins><span class="cx">     void compilePutByValForFloatTypedArray(GPRReg base, GPRReg property, Node*, TypedArrayType);
</span><del>-    void compileGetByValForObjectWithString(Node*, const ScopedLambda<std::tuple<JSValueRegs, DataFormat>(DataFormat preferredFormat)>& prefix);
-    void compileGetByValForObjectWithSymbol(Node*, const ScopedLambda<std::tuple<JSValueRegs, DataFormat>(DataFormat preferredFormat)>& prefix);
</del><ins>+    void compileGetByValForObjectWithString(Node*);
+    void compileGetByValForObjectWithSymbol(Node*);
</ins><span class="cx">     void compilePutByValForCellWithString(Node*, Edge& child1, Edge& child2, Edge& child3);
</span><span class="cx">     void compilePutByValForCellWithSymbol(Node*, Edge& child1, Edge& child2, Edge& child3);
</span><span class="cx">     void compileGetByValWithThis(Node*);
</span><span class="lines">@@ -1464,7 +1458,7 @@
</span><span class="cx"> #endif
</span><span class="cx">         Edge valueUse);
</span><span class="cx">     void loadFromIntTypedArray(GPRReg storageReg, GPRReg propertyReg, GPRReg resultReg, TypedArrayType);
</span><del>-    void setIntTypedArrayLoadResult(Node*, JSValueRegs resultRegs, TypedArrayType, bool canSpeculate, bool shouldBox);
</del><ins>+    void setIntTypedArrayLoadResult(Node*, GPRReg resultReg, TypedArrayType, bool canSpeculate);
</ins><span class="cx">     template <typename ClassType> void compileNewFunctionCommon(GPRReg, RegisteredStructure, GPRReg, GPRReg, GPRReg, MacroAssembler::JumpList&, size_t, FunctionExecutable*);
</span><span class="cx">     void compileNewFunction(Node*);
</span><span class="cx">     void compileSetFunctionName(Node*);
</span><span class="lines">@@ -1530,22 +1524,21 @@
</span><span class="cx">     void compileToLowerCase(Node*);
</span><span class="cx">     void compileThrow(Node*);
</span><span class="cx">     void compileThrowStaticError(Node*);
</span><del>-
-    void compileEnumeratorNextUpdateIndexAndMode(Node*);
-    void compileEnumeratorNextExtractMode(Node*);
-    void compileEnumeratorNextExtractIndex(Node*);
-    void compileEnumeratorNextUpdatePropertyName(Node*);
-    void compileEnumeratorGetByVal(Node*);
-    template<typename SlowPathFunctionType>
-    void compileEnumeratorHasProperty(Node*, SlowPathFunctionType);
-    void compileEnumeratorInByVal(Node*);
-    void compileEnumeratorHasOwnProperty(Node*);
-
</del><ins>+    void compileGetEnumerableLength(Node*);
+    void compileHasEnumerableStructureProperty(Node*);
+    void compileHasEnumerableProperty(Node*);
+    void compileToIndexString(Node*);
</ins><span class="cx">     void compilePutByIdFlush(Node*);
</span><span class="cx">     void compilePutById(Node*);
</span><span class="cx">     void compilePutByIdDirect(Node*);
</span><span class="cx">     void compilePutByIdWithThis(Node*);
</span><ins>+    template <typename Function>
+    void compileHasOwnStructurePropertyImpl(Node*, Function);
+    void compileHasOwnStructureProperty(Node*);
+    void compileInStructureProperty(Node*);
+    void compileGetDirectPname(Node*);
</ins><span class="cx">     void compileGetPropertyEnumerator(Node*);
</span><ins>+    void compileGetEnumeratorPname(Node*);
</ins><span class="cx">     void compileGetExecutable(Node*);
</span><span class="cx">     void compileGetGetter(Node*);
</span><span class="cx">     void compileGetSetter(Node*);
</span><span class="lines">@@ -1575,7 +1568,7 @@
</span><span class="cx">     void compileCallNumberConstructor(Node*);
</span><span class="cx">     void compileLogShadowChickenPrologue(Node*);
</span><span class="cx">     void compileLogShadowChickenTail(Node*);
</span><del>-    void compileHasIndexedProperty(Node*, S_JITOperation_GCZ, const ScopedLambda<std::tuple<GPRReg, GPRReg>()>& prefix);
</del><ins>+    void compileHasIndexedProperty(Node*, S_JITOperation_GCZ);
</ins><span class="cx">     void compileExtractCatchLocal(Node*);
</span><span class="cx">     void compileClearCatchLocals(Node*);
</span><span class="cx">     void compileProfileType(Node*);
</span><span class="lines">@@ -1933,8 +1926,6 @@
</span><span class="cx">         return edge().node();
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    JSValueRegs regs() { return jsValueRegs(); }
-
</del><span class="cx"> #if USE(JSVALUE64)
</span><span class="cx">     GPRReg gpr()
</span><span class="cx">     {
</span><span class="lines">@@ -1974,7 +1965,7 @@
</span><span class="cx">         return JSValueRegs(tagGPR(), payloadGPR());
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    GPRReg gpr(WhichValueWord which = PayloadWord)
</del><ins>+    GPRReg gpr(WhichValueWord which)
</ins><span class="cx">     {
</span><span class="cx">         return jsValueRegs().gpr(which);
</span><span class="cx">     }
</span><span class="lines">@@ -2012,20 +2003,21 @@
</span><span class="cx"> class StorageOperand {
</span><span class="cx">     WTF_MAKE_FAST_ALLOCATED;
</span><span class="cx"> public:
</span><del>-    StorageOperand() = default;
-
</del><span class="cx">     explicit StorageOperand(SpeculativeJIT* jit, Edge edge)
</span><span class="cx">         : m_jit(jit)
</span><span class="cx">         , m_edge(edge)
</span><span class="cx">         , m_gprOrInvalid(InvalidGPRReg)
</span><span class="cx">     {
</span><del>-        emplace(jit, edge);
</del><ins>+        ASSERT(m_jit);
+        ASSERT(edge.useKind() == UntypedUse || edge.useKind() == KnownCellUse);
+        if (jit->isFilled(node()))
+            gpr();
</ins><span class="cx">     }
</span><span class="cx">     
</span><span class="cx">     ~StorageOperand()
</span><span class="cx">     {
</span><del>-        if (m_gprOrInvalid != InvalidGPRReg)
-            m_jit->unlock(m_gprOrInvalid);
</del><ins>+        ASSERT(m_gprOrInvalid != InvalidGPRReg);
+        m_jit->unlock(m_gprOrInvalid);
</ins><span class="cx">     }
</span><span class="cx">     
</span><span class="cx">     Edge edge() const
</span><span class="lines">@@ -2044,17 +2036,6 @@
</span><span class="cx">             m_gprOrInvalid = m_jit->fillStorage(edge());
</span><span class="cx">         return m_gprOrInvalid;
</span><span class="cx">     }
</span><del>-
-    void emplace(SpeculativeJIT* jit, Edge edge)
-    {
-        m_jit = jit;
-        m_edge = edge;
-        ASSERT(m_gprOrInvalid == InvalidGPRReg);
-        ASSERT(m_jit);
-        ASSERT(edge.useKind() == UntypedUse || edge.useKind() == KnownCellUse);
-        if (jit->isFilled(node()))
-            gpr();
-    }
</del><span class="cx">     
</span><span class="cx">     void use()
</span><span class="cx">     {
</span><span class="lines">@@ -2062,9 +2043,9 @@
</span><span class="cx">     }
</span><span class="cx">     
</span><span class="cx"> private:
</span><del>-    SpeculativeJIT* m_jit { nullptr };
</del><ins>+    SpeculativeJIT* m_jit;
</ins><span class="cx">     Edge m_edge;
</span><del>-    GPRReg m_gprOrInvalid { InvalidGPRReg };
</del><ins>+    GPRReg m_gprOrInvalid;
</ins><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> 
</span><span class="lines">@@ -2153,19 +2134,11 @@
</span><span class="cx"> public:
</span><span class="cx">     JSValueRegsTemporary();
</span><span class="cx">     JSValueRegsTemporary(SpeculativeJIT*);
</span><del>-    JSValueRegsTemporary(SpeculativeJIT*, GPRReg specificPayload);
-#if USE(JSVALUE32_64)
-    JSValueRegsTemporary(SpeculativeJIT*, GPRReg specificPayload, GPRReg specificTag);
-#endif
</del><span class="cx">     template<typename T>
</span><span class="cx">     JSValueRegsTemporary(SpeculativeJIT*, ReuseTag, T& operand, WhichValueWord resultRegWord = PayloadWord);
</span><span class="cx">     JSValueRegsTemporary(SpeculativeJIT*, ReuseTag, JSValueOperand&);
</span><span class="cx">     ~JSValueRegsTemporary();
</span><span class="cx">     
</span><del>-    explicit operator bool() { return !!regs(); }
-
-    JSValueRegsTemporary& operator=(JSValueRegsTemporary&&) = default;
-
</del><span class="cx">     JSValueRegs regs();
</span><span class="cx"> 
</span><span class="cx"> private:
</span><span class="lines">@@ -2177,26 +2150,6 @@
</span><span class="cx"> #endif
</span><span class="cx"> };
</span><span class="cx"> 
</span><del>-#if USE(JSVALUE64)
-template<typename T>
-JSValueRegsTemporary::JSValueRegsTemporary(SpeculativeJIT* jit, ReuseTag, T& operand, WhichValueWord)
-    : m_gpr(jit, Reuse, operand)
-{
-}
-#else
-template<typename T>
-JSValueRegsTemporary::JSValueRegsTemporary(SpeculativeJIT* jit, ReuseTag, T& operand, WhichValueWord resultWord)
-{
-    if (resultWord == PayloadWord) {
-        m_payloadGPR = GPRTemporary(jit, Reuse, operand);
-        m_tagGPR = GPRTemporary(jit);
-    } else {
-        m_payloadGPR = GPRTemporary(jit);
-        m_tagGPR = GPRTemporary(jit, Reuse, operand);
-    }
-}
-#endif
-
</del><span class="cx"> class FPRTemporary {
</span><span class="cx">     WTF_MAKE_FAST_ALLOCATED;
</span><span class="cx"> public:
</span></span></pre></div>
<a id="branchessafari612128branchSourceJavaScriptCoredfgDFGSpeculativeJIT32_64cpp"></a>
<div class="modfile"><h4>Modified: branches/safari-612.1.28-branch/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp (281021 => 281022)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-612.1.28-branch/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp     2021-08-13 16:39:44 UTC (rev 281021)
+++ branches/safari-612.1.28-branch/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp        2021-08-13 16:50:38 UTC (rev 281022)
</span><span class="lines">@@ -1812,335 +1812,6 @@
</span><span class="cx">     noResult(node, UseChildrenCalledExplicitly);    
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void SpeculativeJIT::compileGetByVal(Node* node, const ScopedLambda<std::tuple<JSValueRegs, DataFormat>(DataFormat preferredFormat)>& prefix)
-{
-    switch (node->arrayMode().type()) {
-    case Array::SelectUsingPredictions:
-    case Array::ForceExit:
-        RELEASE_ASSERT_NOT_REACHED();
-#if COMPILER_QUIRK(CONSIDERS_UNREACHABLE_CODE)
-        terminateSpeculativeExecution(InadequateCoverage, JSValueRegs(), 0);
-#endif
-        break;
-    case Array::Undecided: {
-        SpeculateStrictInt32Operand index(this, m_graph.varArgChild(node, 1));
-
-        GPRReg indexGPR = index.gpr();
-
-        JSValueRegs resultRegs;
-        std::tie(resultRegs, std::ignore) = prefix(DataFormatJS);
-
-        speculationCheck(OutOfBounds, JSValueRegs(), node,
-            m_jit.branch32(MacroAssembler::LessThan, indexGPR, MacroAssembler::TrustedImm32(0)));
-
-        m_jit.move(MacroAssembler::TrustedImm32(JSValue::UndefinedTag), resultRegs.tagGPR());
-        m_jit.move(MacroAssembler::TrustedImm32(0), resultRegs.payloadGPR());
-        jsValueResult(resultRegs, node);
-        break;
-    }
-    case Array::Generic: {
-        if (m_graph.m_slowGetByVal.contains(node)) {
-            if (m_graph.varArgChild(node, 0).useKind() == ObjectUse) {
-                if (m_graph.varArgChild(node, 1).useKind() == StringUse) {
-                    compileGetByValForObjectWithString(node, prefix);
-                    break;
-                }
-
-                if (m_graph.varArgChild(node, 1).useKind() == SymbolUse) {
-                    compileGetByValForObjectWithSymbol(node, prefix);
-                    break;
-                }
-            }
-
-            SpeculateCellOperand base(this, m_graph.varArgChild(node, 0)); // Save a register, speculate cell. We'll probably be right.
-            JSValueOperand property(this, m_graph.varArgChild(node, 1));
-            GPRReg baseGPR = base.gpr();
-            JSValueRegs propertyRegs = property.jsValueRegs();
-
-            JSValueRegs resultRegs;
-            std::tie(resultRegs, std::ignore) = prefix(DataFormatJS);
-
-            flushRegisters();
-            callOperation(operationGetByValCell, resultRegs, TrustedImmPtr::weakPointer(m_graph, m_graph.globalObjectFor(node->origin.semantic)), baseGPR, propertyRegs);
-            m_jit.exceptionCheck();
-
-            jsValueResult(resultRegs, node);
-            break;
-        }
-
-        speculate(node, m_graph.varArgChild(node, 0));
-        speculate(node, m_graph.varArgChild(node, 1));
-
-        JSValueOperand base(this, m_graph.varArgChild(node, 0), ManualOperandSpeculation);
-        JSValueOperand property(this, m_graph.varArgChild(node, 1), ManualOperandSpeculation);
-
-        JSValueRegs baseRegs = base.jsValueRegs();
-        JSValueRegs propertyRegs = property.jsValueRegs();
-
-        JSValueRegs resultRegs;
-        std::tie(resultRegs, std::ignore) = prefix(DataFormatJS);
-
-        CodeOrigin codeOrigin = node->origin.semantic;
-        CallSiteIndex callSite = m_jit.recordCallSiteAndGenerateExceptionHandlingOSRExitIfNeeded(codeOrigin, m_stream->size());
-        RegisterSet usedRegisters = this->usedRegisters();
-
-        JITCompiler::JumpList slowCases;
-        if (!m_state.forNode(m_graph.varArgChild(node, 0)).isType(SpecCell))
-            slowCases.append(m_jit.branchIfNotCell(baseRegs.tagGPR()));
-
-        JITGetByValGenerator gen(
-            m_jit.codeBlock(), JITType::DFGJIT, codeOrigin, callSite, AccessType::GetByVal, usedRegisters,
-            baseRegs, propertyRegs, resultRegs, InvalidGPRReg);
-
-        if (m_state.forNode(m_graph.varArgChild(node, 1)).isType(SpecString))
-            gen.stubInfo()->propertyIsString = true;
-        else if (m_state.forNode(m_graph.varArgChild(node, 1)).isType(SpecInt32Only))
-            gen.stubInfo()->propertyIsInt32 = true;
-        else if (m_state.forNode(m_graph.varArgChild(node, 1)).isType(SpecSymbol))
-            gen.stubInfo()->propertyIsSymbol = true;
-
-        gen.generateFastPath(m_jit);
-
-        slowCases.append(gen.slowPathJump());
-
-        std::unique_ptr<SlowPathGenerator> slowPath = slowPathCall(
-            slowCases, this, operationGetByValOptimize,
-            resultRegs, TrustedImmPtr::weakPointer(m_graph, m_graph.globalObjectFor(codeOrigin)), gen.stubInfo(), nullptr, baseRegs, propertyRegs);
-
-        m_jit.addGetByVal(gen, slowPath.get());
-        addSlowPathGenerator(WTFMove(slowPath));
-
-        jsValueResult(resultRegs, node);
-        break;
-    }
-    case Array::Int32:
-    case Array::Contiguous: {
-        if (node->arrayMode().isInBounds()) {
-            SpeculateStrictInt32Operand property(this, m_graph.varArgChild(node, 1));
-            StorageOperand storage(this, m_graph.varArgChild(node, 2));
-
-            GPRReg propertyReg = property.gpr();
-            GPRReg storageReg = storage.gpr();
-
-            if (!m_compileOkay)
-                return;
-
-            JSValueRegs resultRegs;
-            DataFormat format;
-            std::tie(resultRegs, format) = prefix(node->arrayMode().type() == Array::Int32 ? DataFormatInt32 : DataFormatJS);
-
-            speculationCheck(OutOfBounds, JSValueRegs(), 0, m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfPublicLength())));
-
-            if (format == DataFormatInt32) {
-                ASSERT(!node->arrayMode().isInBoundsSaneChain());
-
-                speculationCheck(
-                    OutOfBounds, JSValueRegs(), 0,
-                    m_jit.branch32(
-                        MacroAssembler::Equal,
-                        MacroAssembler::BaseIndex(
-                            storageReg, propertyReg, MacroAssembler::TimesEight, TagOffset),
-                        TrustedImm32(JSValue::EmptyValueTag)));
-                m_jit.load32(
-                    MacroAssembler::BaseIndex(
-                        storageReg, propertyReg, MacroAssembler::TimesEight, PayloadOffset),
-                    resultRegs.payloadGPR());
-                strictInt32Result(resultRegs.payloadGPR(), node);
-                break;
-            }
-
-            ASSERT(format == DataFormatJS);
-            m_jit.load32(
-                MacroAssembler::BaseIndex(
-                    storageReg, propertyReg, MacroAssembler::TimesEight, TagOffset),
-                resultRegs.tagGPR());
-            m_jit.load32(
-                MacroAssembler::BaseIndex(
-                    storageReg, propertyReg, MacroAssembler::TimesEight, PayloadOffset),
-                resultRegs.payloadGPR());
-            if (node->arrayMode().isInBoundsSaneChain()) {
-                JITCompiler::Jump notHole = m_jit.branchIfNotEmpty(resultRegs.tagGPR());
-                m_jit.move(TrustedImm32(JSValue::UndefinedTag), resultRegs.tagGPR());
-                m_jit.move(TrustedImm32(0), resultRegs.payloadGPR());
-                notHole.link(&m_jit);
-            } else {
-                speculationCheck(
-                    LoadFromHole, JSValueRegs(), nullptr,
-                    m_jit.branchIfEmpty(resultRegs.tagGPR()));
-            }
-            jsValueResult(resultRegs, node);
-            break;
-        }
-
-        SpeculateCellOperand base(this, m_graph.varArgChild(node, 0));
-        SpeculateStrictInt32Operand property(this, m_graph.varArgChild(node, 1));
-        StorageOperand storage(this, m_graph.varArgChild(node, 2));
-
-        GPRReg baseReg = base.gpr();
-        GPRReg propertyReg = property.gpr();
-        GPRReg storageReg = storage.gpr();
-
-        if (!m_compileOkay)
-            return;
-
-        JSValueRegs resultRegs;
-        std::tie(resultRegs, std::ignore) = prefix(DataFormatJS);
-
-        MacroAssembler::JumpList slowCases;
-
-        slowCases.append(m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfPublicLength())));
-
-        m_jit.loadValue(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight), resultRegs);
-        slowCases.append(m_jit.branchIfEmpty(resultRegs.tagGPR()));
-
-        addSlowPathGenerator(
-            slowPathCall(
-                slowCases, this, operationGetByValObjectInt,
-                resultRegs, TrustedImmPtr::weakPointer(m_graph, m_graph.globalObjectFor(node->origin.semantic)), baseReg, propertyReg));
-
-        jsValueResult(resultRegs, node);
-        break;
-    }
-    case Array::Double: {
-        if (node->arrayMode().isInBounds()) {
-            SpeculateStrictInt32Operand property(this, m_graph.varArgChild(node, 1));
-            StorageOperand storage(this, m_graph.varArgChild(node, 2));
-
-            GPRReg propertyReg = property.gpr();
-            GPRReg storageReg = storage.gpr();
-
-            if (!m_compileOkay)
-                return;
-
-            FPRTemporary result(this);
-
-            JSValueRegs resultRegs;
-            DataFormat format;
-            std::tie(resultRegs, format) = prefix(DataFormatDouble);
-
-            speculationCheck(OutOfBounds, JSValueRegs(), 0, m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfPublicLength())));
-
-            m_jit.loadDouble(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight), result.fpr());
-            if (!node->arrayMode().isInBoundsSaneChain())
-                speculationCheck(LoadFromHole, JSValueRegs(), 0, m_jit.branchIfNaN(result.fpr()));
-            if (format == DataFormatJS) {
-                boxDouble(result.fpr(), resultRegs);
-                jsValueResult(resultRegs, node);
-            } else {
-                ASSERT(format == DataFormatDouble && !resultRegs);
-                doubleResult(result.fpr(), node);
-            }
-            break;
-        }
-
-        SpeculateCellOperand base(this, m_graph.varArgChild(node, 0));
-        SpeculateStrictInt32Operand property(this, m_graph.varArgChild(node, 1));
-        StorageOperand storage(this, m_graph.varArgChild(node, 2));
-
-        GPRReg baseReg = base.gpr();
-        GPRReg propertyReg = property.gpr();
-        GPRReg storageReg = storage.gpr();
-
-        if (!m_compileOkay)
-            return;
-
-        FPRTemporary temp(this);
-        FPRReg tempReg = temp.fpr();
-
-        JSValueRegs resultRegs;
-        std::tie(resultRegs, std::ignore) = prefix(DataFormatJS);
-
-        MacroAssembler::JumpList slowCases;
-
-        slowCases.append(m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfPublicLength())));
-
-        m_jit.loadDouble(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight), tempReg);
-        slowCases.append(m_jit.branchIfNaN(tempReg));
-        boxDouble(tempReg, resultRegs);
-
-        addSlowPathGenerator(
-            slowPathCall(
-                slowCases, this, operationGetByValObjectInt,
-                resultRegs, TrustedImmPtr::weakPointer(m_graph, m_graph.globalObjectFor(node->origin.semantic)), baseReg, propertyReg));
-
-        jsValueResult(resultRegs, node);
-        break;
-    }
-    case Array::ArrayStorage:
-    case Array::SlowPutArrayStorage: {
-        if (node->arrayMode().isInBounds()) {
-            SpeculateStrictInt32Operand property(this, m_graph.varArgChild(node, 1));
-            StorageOperand storage(this, m_graph.varArgChild(node, 2));
-            GPRReg propertyReg = property.gpr();
-            GPRReg storageReg = storage.gpr();
-
-            if (!m_compileOkay)
-                return;
-
-            JSValueRegs resultRegs;
-            std::tie(resultRegs, std::ignore) = prefix(DataFormatJS);
-
-            speculationCheck(OutOfBounds, JSValueRegs(), 0, m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, ArrayStorage::vectorLengthOffset())));
-
-            m_jit.load32(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, ArrayStorage::vectorOffset() + OBJECT_OFFSETOF(JSValue, u.asBits.tag)), resultRegs.tagGPR());
-            speculationCheck(LoadFromHole, JSValueRegs(), 0, m_jit.branchIfEmpty(resultRegs.tagGPR()));
-            m_jit.load32(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, ArrayStorage::vectorOffset() + OBJECT_OFFSETOF(JSValue, u.asBits.payload)), resultRegs.payloadGPR());
-
-            jsValueResult(resultRegs, node);
-            break;
-        }
-
-        SpeculateCellOperand base(this, m_graph.varArgChild(node, 0));
-        SpeculateStrictInt32Operand property(this, m_graph.varArgChild(node, 1));
-        StorageOperand storage(this, m_graph.varArgChild(node, 2));
-        GPRReg propertyReg = property.gpr();
-        GPRReg storageReg = storage.gpr();
-        GPRReg baseReg = base.gpr();
-
-        if (!m_compileOkay)
-            return;
-
-        JSValueRegs resultRegs;
-        std::tie(resultRegs, std::ignore) = prefix(DataFormatJS);
-
-        JITCompiler::Jump outOfBounds = m_jit.branch32(
-            MacroAssembler::AboveOrEqual, propertyReg,
-            MacroAssembler::Address(storageReg, ArrayStorage::vectorLengthOffset()));
-
-        m_jit.load32(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, ArrayStorage::vectorOffset() + OBJECT_OFFSETOF(JSValue, u.asBits.tag)), resultRegs.tagGPR());
-        JITCompiler::Jump hole = m_jit.branchIfEmpty(resultRegs.tagGPR());
-        m_jit.load32(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, ArrayStorage::vectorOffset() + OBJECT_OFFSETOF(JSValue, u.asBits.payload)), resultRegs.payloadGPR());
-
-        JITCompiler::JumpList slowCases;
-        slowCases.append(outOfBounds);
-        slowCases.append(hole);
-        addSlowPathGenerator(
-            slowPathCall(
-                slowCases, this, operationGetByValObjectInt,
-                resultRegs, TrustedImmPtr::weakPointer(m_graph, m_graph.globalObjectFor(node->origin.semantic)),
-                baseReg, propertyReg));
-
-        jsValueResult(resultRegs, node);
-        break;
-    }
-    case Array::String:
-        compileGetByValOnString(node, prefix);
-        break;
-    case Array::DirectArguments:
-        compileGetByValOnDirectArguments(node, prefix);
-        break;
-    case Array::ScopedArguments:
-        compileGetByValOnScopedArguments(node, prefix);
-        break;
-    default: {
-        TypedArrayType type = node->arrayMode().typedArrayType();
-        if (isInt(type))
-            compileGetByValOnIntTypedArray(node, type, prefix);
-        else
-            compileGetByValOnFloatTypedArray(node, type, prefix);
-    } }
-}
-
</del><span class="cx"> void SpeculativeJIT::compile(Node* node)
</span><span class="cx"> {
</span><span class="cx">     NodeType op = node->op();
</span><span class="lines">@@ -2562,12 +2233,7 @@
</span><span class="cx"> 
</span><span class="cx">     case StringCharAt: {
</span><span class="cx">         // Relies on StringCharAt node having same basic layout as GetByVal
</span><del>-        JSValueRegsTemporary result;
-        compileGetByValOnString(node, scopedLambda<std::tuple<JSValueRegs, DataFormat>(DataFormat preferredFormat)>([&] (DataFormat preferredFormat) {
-            result = JSValueRegsTemporary(this);
-            ASSERT(preferredFormat & DataFormatJS);
-            return std::make_pair(result.regs(), preferredFormat);
-        }));
</del><ins>+        compileGetByValOnString(node);
</ins><span class="cx">         break;
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="lines">@@ -2599,27 +2265,326 @@
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     case GetByVal: {
</span><del>-        JSValueRegsTemporary jsValueResult;
-        GPRTemporary oneRegResult;
-        compileGetByVal(node, scopedLambda<std::tuple<JSValueRegs, DataFormat>(DataFormat preferredFormat)>([&] (DataFormat preferredFormat) {
-            JSValueRegs resultRegs;
-            switch (preferredFormat) {
-            case DataFormatDouble:
</del><ins>+        switch (node->arrayMode().type()) {
+        case Array::SelectUsingPredictions:
+        case Array::ForceExit:
+            RELEASE_ASSERT_NOT_REACHED();
+#if COMPILER_QUIRK(CONSIDERS_UNREACHABLE_CODE)
+            terminateSpeculativeExecution(InadequateCoverage, JSValueRegs(), 0);
+#endif
+            break;
+        case Array::Undecided: {
+            SpeculateStrictInt32Operand index(this, m_graph.varArgChild(node, 1));
+            GPRTemporary resultTag(this, Reuse, index);
+            GPRTemporary resultPayload(this);
+
+            GPRReg indexGPR = index.gpr();
+            GPRReg resultTagGPR = resultTag.gpr();
+            GPRReg resultPayloadGPR = resultPayload.gpr();
+
+            speculationCheck(OutOfBounds, JSValueRegs(), node,
+                m_jit.branch32(MacroAssembler::LessThan, indexGPR, MacroAssembler::TrustedImm32(0)));
+
+            use(m_graph.varArgChild(node, 0));
+            index.use();
+
+            m_jit.move(MacroAssembler::TrustedImm32(JSValue::UndefinedTag), resultTagGPR);
+            m_jit.move(MacroAssembler::TrustedImm32(0), resultPayloadGPR);
+            jsValueResult(resultTagGPR, resultPayloadGPR, node, UseChildrenCalledExplicitly);
+            break;
+        }
+        case Array::Generic: {
+            if (m_graph.m_slowGetByVal.contains(node)) {
+                if (m_graph.varArgChild(node, 0).useKind() == ObjectUse) {
+                    if (m_graph.varArgChild(node, 1).useKind() == StringUse) {
+                        compileGetByValForObjectWithString(node);
+                        break;
+                    }
+
+                    if (m_graph.varArgChild(node, 1).useKind() == SymbolUse) {
+                        compileGetByValForObjectWithSymbol(node);
+                        break;
+                    }
+                }
+
+                SpeculateCellOperand base(this, m_graph.varArgChild(node, 0)); // Save a register, speculate cell. We'll probably be right.
+                JSValueOperand property(this, m_graph.varArgChild(node, 1));
+                GPRReg baseGPR = base.gpr();
+                JSValueRegs propertyRegs = property.jsValueRegs();
+                
+                flushRegisters();
+                JSValueRegsFlushedCallResult result(this);
+                JSValueRegs resultRegs = result.regs();
+                callOperation(operationGetByValCell, resultRegs, TrustedImmPtr::weakPointer(m_graph, m_graph.globalObjectFor(node->origin.semantic)), baseGPR, propertyRegs);
+                m_jit.exceptionCheck();
+                
+                jsValueResult(resultRegs, node);
</ins><span class="cx">                 break;
</span><del>-            case DataFormatInt32:
-            case DataFormatCell:
-                oneRegResult = GPRTemporary(this);
-                resultRegs = JSValueRegs::payloadOnly(oneRegResult.gpr());
</del><ins>+            }
+
+            speculate(node, m_graph.varArgChild(node, 0));
+            speculate(node, m_graph.varArgChild(node, 1));
+
+            JSValueOperand base(this, m_graph.varArgChild(node, 0), ManualOperandSpeculation);
+            JSValueOperand property(this, m_graph.varArgChild(node, 1), ManualOperandSpeculation);
+            GPRTemporary resultTag(this, Reuse, property, TagWord);
+            GPRTemporary resultPayload(this, Reuse, property, PayloadWord);
+
+            JSValueRegs baseRegs = base.jsValueRegs();
+            JSValueRegs propertyRegs = property.jsValueRegs();
+            JSValueRegs resultRegs(resultTag.gpr(), resultPayload.gpr());
+
+            CodeOrigin codeOrigin = node->origin.semantic;
+            CallSiteIndex callSite = m_jit.recordCallSiteAndGenerateExceptionHandlingOSRExitIfNeeded(codeOrigin, m_stream->size());
+            RegisterSet usedRegisters = this->usedRegisters();
+
+            JITCompiler::JumpList slowCases;
+            if (!m_state.forNode(m_graph.varArgChild(node, 0)).isType(SpecCell))
+                slowCases.append(m_jit.branchIfNotCell(baseRegs.tagGPR()));
+
+            JITGetByValGenerator gen(
+                m_jit.codeBlock(), JITType::DFGJIT, codeOrigin, callSite, AccessType::GetByVal, usedRegisters,
+                baseRegs, propertyRegs, resultRegs, InvalidGPRReg);
+
+            if (m_state.forNode(m_graph.varArgChild(node, 1)).isType(SpecString))
+                gen.stubInfo()->propertyIsString = true;
+            else if (m_state.forNode(m_graph.varArgChild(node, 1)).isType(SpecInt32Only))
+                gen.stubInfo()->propertyIsInt32 = true;
+            else if (m_state.forNode(m_graph.varArgChild(node, 1)).isType(SpecSymbol))
+                gen.stubInfo()->propertyIsSymbol = true;
+
+            gen.generateFastPath(m_jit);
+            
+            slowCases.append(gen.slowPathJump());
+
+            std::unique_ptr<SlowPathGenerator> slowPath = slowPathCall(
+                slowCases, this, operationGetByValOptimize,
+                resultRegs, TrustedImmPtr::weakPointer(m_graph, m_graph.globalObjectFor(codeOrigin)), gen.stubInfo(), nullptr, baseRegs, propertyRegs);
+            
+            m_jit.addGetByVal(gen, slowPath.get());
+            addSlowPathGenerator(WTFMove(slowPath));
+
+            jsValueResult(resultRegs, node);
+            break;
+        }
+        case Array::Int32:
+        case Array::Contiguous: {
+            if (node->arrayMode().isInBounds()) {
+                SpeculateStrictInt32Operand property(this, m_graph.varArgChild(node, 1));
+                StorageOperand storage(this, m_graph.varArgChild(node, 2));
+            
+                GPRReg propertyReg = property.gpr();
+                GPRReg storageReg = storage.gpr();
+            
+                if (!m_compileOkay)
+                    return;
+            
+                speculationCheck(OutOfBounds, JSValueRegs(), 0, m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfPublicLength())));
+            
+                GPRTemporary resultPayload(this);
+                if (node->arrayMode().type() == Array::Int32) {
+                    ASSERT(!node->arrayMode().isInBoundsSaneChain());
+                    
+                    speculationCheck(
+                        OutOfBounds, JSValueRegs(), 0,
+                        m_jit.branch32(
+                            MacroAssembler::Equal,
+                            MacroAssembler::BaseIndex(
+                                storageReg, propertyReg, MacroAssembler::TimesEight, TagOffset),
+                            TrustedImm32(JSValue::EmptyValueTag)));
+                    m_jit.load32(
+                        MacroAssembler::BaseIndex(
+                            storageReg, propertyReg, MacroAssembler::TimesEight, PayloadOffset),
+                        resultPayload.gpr());
+                    strictInt32Result(resultPayload.gpr(), node);
+                    break;
+                }
+                
+                GPRTemporary resultTag(this);
+                m_jit.load32(
+                    MacroAssembler::BaseIndex(
+                        storageReg, propertyReg, MacroAssembler::TimesEight, TagOffset),
+                    resultTag.gpr());
+                m_jit.load32(
+                    MacroAssembler::BaseIndex(
+                        storageReg, propertyReg, MacroAssembler::TimesEight, PayloadOffset),
+                    resultPayload.gpr());
+                if (node->arrayMode().isInBoundsSaneChain()) {
+                    JITCompiler::Jump notHole = m_jit.branchIfNotEmpty(resultTag.gpr());
+                    m_jit.move(TrustedImm32(JSValue::UndefinedTag), resultTag.gpr());
+                    m_jit.move(TrustedImm32(0), resultPayload.gpr());
+                    notHole.link(&m_jit);
+                } else {
+                    speculationCheck(
+                        LoadFromHole, JSValueRegs(), 0,
+                        m_jit.branchIfEmpty(resultTag.gpr()));
+                }
+                jsValueResult(resultTag.gpr(), resultPayload.gpr(), node);
</ins><span class="cx">                 break;
</span><del>-            default: {
-                ASSERT(preferredFormat == DataFormatJS);
-                jsValueResult = JSValueRegsTemporary(this);
-                resultRegs = jsValueResult.regs();
</del><ins>+            }
+
+            SpeculateCellOperand base(this, m_graph.varArgChild(node, 0));
+            SpeculateStrictInt32Operand property(this, m_graph.varArgChild(node, 1));
+            StorageOperand storage(this, m_graph.varArgChild(node, 2));
+            
+            GPRReg baseReg = base.gpr();
+            GPRReg propertyReg = property.gpr();
+            GPRReg storageReg = storage.gpr();
+            
+            if (!m_compileOkay)
+                return;
+            
+            GPRTemporary resultTag(this);
+            GPRTemporary resultPayload(this);
+            GPRReg resultTagReg = resultTag.gpr();
+            GPRReg resultPayloadReg = resultPayload.gpr();
+            
+            MacroAssembler::JumpList slowCases;
+
+            slowCases.append(m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfPublicLength())));
+            
+            m_jit.load32(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.tag)), resultTagReg);
+            m_jit.load32(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.payload)), resultPayloadReg);
+            slowCases.append(m_jit.branchIfEmpty(resultTagReg));
+            
+            addSlowPathGenerator(
+                slowPathCall(
+                    slowCases, this, operationGetByValObjectInt,
+                    JSValueRegs(resultTagReg, resultPayloadReg), TrustedImmPtr::weakPointer(m_graph, m_graph.globalObjectFor(node->origin.semantic)), baseReg, propertyReg));
+            
+            jsValueResult(resultTagReg, resultPayloadReg, node);
+            break;
+        }
+        case Array::Double: {
+            if (node->arrayMode().isInBounds()) {
+                SpeculateStrictInt32Operand property(this, m_graph.varArgChild(node, 1));
+                StorageOperand storage(this, m_graph.varArgChild(node, 2));
+            
+                GPRReg propertyReg = property.gpr();
+                GPRReg storageReg = storage.gpr();
+            
+                if (!m_compileOkay)
+                    return;
+            
+                speculationCheck(OutOfBounds, JSValueRegs(), 0, m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfPublicLength())));
+            
+                FPRTemporary result(this);
+                m_jit.loadDouble(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight), result.fpr());
+                if (!node->arrayMode().isInBoundsSaneChain())
+                    speculationCheck(LoadFromHole, JSValueRegs(), 0, m_jit.branchIfNaN(result.fpr()));
+                doubleResult(result.fpr(), node);
</ins><span class="cx">                 break;
</span><span class="cx">             }
</span><del>-            };
-            return std::make_pair(resultRegs, preferredFormat);
-        }));
</del><ins>+
+            SpeculateCellOperand base(this, m_graph.varArgChild(node, 0));
+            SpeculateStrictInt32Operand property(this, m_graph.varArgChild(node, 1));
+            StorageOperand storage(this, m_graph.varArgChild(node, 2));
+            
+            GPRReg baseReg = base.gpr();
+            GPRReg propertyReg = property.gpr();
+            GPRReg storageReg = storage.gpr();
+            
+            if (!m_compileOkay)
+                return;
+            
+            GPRTemporary resultTag(this);
+            GPRTemporary resultPayload(this);
+            FPRTemporary temp(this);
+            GPRReg resultTagReg = resultTag.gpr();
+            GPRReg resultPayloadReg = resultPayload.gpr();
+            FPRReg tempReg = temp.fpr();
+            
+            MacroAssembler::JumpList slowCases;
+            
+            slowCases.append(m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfPublicLength())));
+            
+            m_jit.loadDouble(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight), tempReg);
+            slowCases.append(m_jit.branchIfNaN(tempReg));
+            boxDouble(tempReg, resultTagReg, resultPayloadReg);
+
+            addSlowPathGenerator(
+                slowPathCall(
+                    slowCases, this, operationGetByValObjectInt,
+                    JSValueRegs(resultTagReg, resultPayloadReg), TrustedImmPtr::weakPointer(m_graph, m_graph.globalObjectFor(node->origin.semantic)), baseReg, propertyReg));
+            
+            jsValueResult(resultTagReg, resultPayloadReg, node);
+            break;
+        }
+        case Array::ArrayStorage:
+        case Array::SlowPutArrayStorage: {
+            if (node->arrayMode().isInBounds()) {
+                SpeculateStrictInt32Operand property(this, m_graph.varArgChild(node, 1));
+                StorageOperand storage(this, m_graph.varArgChild(node, 2));
+                GPRReg propertyReg = property.gpr();
+                GPRReg storageReg = storage.gpr();
+        
+                if (!m_compileOkay)
+                    return;
+
+                speculationCheck(OutOfBounds, JSValueRegs(), 0, m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, ArrayStorage::vectorLengthOffset())));
+
+                GPRTemporary resultTag(this);
+                GPRTemporary resultPayload(this);
+
+                m_jit.load32(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, ArrayStorage::vectorOffset() + OBJECT_OFFSETOF(JSValue, u.asBits.tag)), resultTag.gpr());
+                speculationCheck(LoadFromHole, JSValueRegs(), 0, m_jit.branchIfEmpty(resultTag.gpr()));
+                m_jit.load32(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, ArrayStorage::vectorOffset() + OBJECT_OFFSETOF(JSValue, u.asBits.payload)), resultPayload.gpr());
+            
+                jsValueResult(resultTag.gpr(), resultPayload.gpr(), node);
+                break;
+            }
+
+            SpeculateCellOperand base(this, m_graph.varArgChild(node, 0));
+            SpeculateStrictInt32Operand property(this, m_graph.varArgChild(node, 1));
+            StorageOperand storage(this, m_graph.varArgChild(node, 2));
+            GPRReg propertyReg = property.gpr();
+            GPRReg storageReg = storage.gpr();
+            GPRReg baseReg = base.gpr();
+
+            if (!m_compileOkay)
+                return;
+
+            GPRTemporary resultTag(this);
+            GPRTemporary resultPayload(this);
+            GPRReg resultTagReg = resultTag.gpr();
+            GPRReg resultPayloadReg = resultPayload.gpr();
+
+            JITCompiler::Jump outOfBounds = m_jit.branch32(
+                MacroAssembler::AboveOrEqual, propertyReg,
+                MacroAssembler::Address(storageReg, ArrayStorage::vectorLengthOffset()));
+
+            m_jit.load32(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, ArrayStorage::vectorOffset() + OBJECT_OFFSETOF(JSValue, u.asBits.tag)), resultTagReg);
+            JITCompiler::Jump hole = m_jit.branchIfEmpty(resultTag.gpr());
+            m_jit.load32(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, ArrayStorage::vectorOffset() + OBJECT_OFFSETOF(JSValue, u.asBits.payload)), resultPayloadReg);
+            
+            JITCompiler::JumpList slowCases;
+            slowCases.append(outOfBounds);
+            slowCases.append(hole);
+            addSlowPathGenerator(
+                slowPathCall(
+                    slowCases, this, operationGetByValObjectInt,
+                    JSValueRegs(resultTagReg, resultPayloadReg), TrustedImmPtr::weakPointer(m_graph, m_graph.globalObjectFor(node->origin.semantic)),
+                    baseReg, propertyReg));
+
+            jsValueResult(resultTagReg, resultPayloadReg, node);
+            break;
+        }
+        case Array::String:
+            compileGetByValOnString(node);
+            break;
+        case Array::DirectArguments:
+            compileGetByValOnDirectArguments(node);
+            break;
+        case Array::ScopedArguments:
+            compileGetByValOnScopedArguments(node);
+            break;
+        default: {
+            TypedArrayType type = node->arrayMode().typedArrayType();
+            if (isInt(type))
+                compileGetByValOnIntTypedArray(node, type);
+            else
+                compileGetByValOnFloatTypedArray(node, type);
+        } }
</ins><span class="cx">         break;
</span><span class="cx">     }
</span><span class="cx">     
</span><span class="lines">@@ -4147,55 +4112,51 @@
</span><span class="cx">         break;
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    case HasIndexedProperty: {
-        SpeculateStrictInt32Operand index(this, m_graph.varArgChild(node, 1));
-        GPRTemporary result(this, Reuse, index);
-
-        compileHasIndexedProperty(node, operationHasIndexedProperty, scopedLambda<std::tuple<GPRReg, GPRReg>()>([&] { return std::make_pair(index.gpr(), result.gpr()); }));
-        unblessedBooleanResult(result.gpr(), node);
</del><ins>+    case GetEnumerableLength: {
+        compileGetEnumerableLength(node);
</ins><span class="cx">         break;
</span><span class="cx">     }
</span><del>-
-    case GetPropertyEnumerator: {
-        compileGetPropertyEnumerator(node);
</del><ins>+    case HasEnumerableStructureProperty: {
+        compileHasEnumerableStructureProperty(node);
</ins><span class="cx">         break;
</span><span class="cx">     }
</span><del>-
-    case EnumeratorNextUpdateIndexAndMode: {
-        compileEnumeratorNextUpdateIndexAndMode(node);
</del><ins>+    case HasEnumerableProperty: {
+        compileHasEnumerableProperty(node);
</ins><span class="cx">         break;
</span><span class="cx">     }
</span><del>-
-    case EnumeratorNextExtractMode: {
-        compileEnumeratorNextExtractMode(node);
</del><ins>+    case HasOwnStructureProperty: {
+        compileHasOwnStructureProperty(node);
</ins><span class="cx">         break;
</span><span class="cx">     }
</span><del>-
-    case EnumeratorNextExtractIndex: {
-        compileEnumeratorNextExtractIndex(node);
</del><ins>+    case InStructureProperty: {
+        compileInStructureProperty(node);
</ins><span class="cx">         break;
</span><span class="cx">     }
</span><del>-
-    case EnumeratorNextUpdatePropertyName: {
-        compileEnumeratorNextUpdatePropertyName(node);
</del><ins>+    case HasIndexedProperty: {
+        compileHasIndexedProperty(node, operationHasIndexedProperty);
</ins><span class="cx">         break;
</span><span class="cx">     }
</span><del>-
-    case EnumeratorGetByVal: {
-        compileEnumeratorGetByVal(node);
</del><ins>+    case HasEnumerableIndexedProperty: {
+        compileHasIndexedProperty(node, operationHasEnumerableIndexedProperty);
</ins><span class="cx">         break;
</span><span class="cx">     }
</span><del>-
-    case EnumeratorInByVal: {
-        compileEnumeratorInByVal(node);
</del><ins>+    case GetDirectPname: {
+        compileGetDirectPname(node);
</ins><span class="cx">         break;
</span><span class="cx">     }
</span><del>-
-    case EnumeratorHasOwnProperty: {
-        compileEnumeratorHasOwnProperty(node);
</del><ins>+    case GetPropertyEnumerator: {
+        compileGetPropertyEnumerator(node);
</ins><span class="cx">         break;
</span><span class="cx">     }
</span><del>-
</del><ins>+    case GetEnumeratorStructurePname:
+    case GetEnumeratorGenericPname: {
+        compileGetEnumeratorPname(node);
+        break;
+    }
+    case ToIndexString: {
+        compileToIndexString(node);
+        break;
+    }
</ins><span class="cx">     case ProfileType: {
</span><span class="cx">         compileProfileType(node);
</span><span class="cx">         break;
</span></span></pre></div>
<a id="branchessafari612128branchSourceJavaScriptCoredfgDFGSpeculativeJIT64cpp"></a>
<div class="modfile"><h4>Modified: branches/safari-612.1.28-branch/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp (281021 => 281022)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-612.1.28-branch/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp        2021-08-13 16:39:44 UTC (rev 281021)
+++ branches/safari-612.1.28-branch/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp   2021-08-13 16:50:38 UTC (rev 281022)
</span><span class="lines">@@ -2246,370 +2246,6 @@
</span><span class="cx">     }
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void SpeculativeJIT::compileGetByVal(Node* node, const ScopedLambda<std::tuple<JSValueRegs, DataFormat>(DataFormat preferredFormat)>& prefix)
-{
-    switch (node->arrayMode().type()) {
-    case Array::AnyTypedArray:
-    case Array::ForceExit:
-    case Array::SelectUsingArguments:
-    case Array::SelectUsingPredictions:
-    case Array::Unprofiled:
-        DFG_CRASH(m_jit.graph(), node, "Bad array mode type");
-        break;
-    case Array::Undecided: {
-        SpeculateStrictInt32Operand index(this, m_graph.varArgChild(node, 1));
-        GPRReg indexGPR = index.gpr();
-
-        JSValueRegs resultRegs;
-        std::tie(resultRegs, std::ignore) = prefix(DataFormatJS);
-
-        speculationCheck(OutOfBounds, JSValueRegs(), node,
-            m_jit.branch32(MacroAssembler::LessThan, indexGPR, MacroAssembler::TrustedImm32(0)));
-
-        m_jit.move(MacroAssembler::TrustedImm64(JSValue::ValueUndefined), resultRegs.gpr());
-
-        jsValueResult(resultRegs, node);
-        break;
-    }
-    case Array::BigInt64Array:
-    case Array::BigUint64Array:
-    case Array::Generic: {
-        if (m_graph.m_slowGetByVal.contains(node)) {
-            if (m_graph.varArgChild(node, 0).useKind() == ObjectUse) {
-                if (m_graph.varArgChild(node, 1).useKind() == StringUse) {
-                    compileGetByValForObjectWithString(node, prefix);
-                    return;
-                }
-
-                if (m_graph.varArgChild(node, 1).useKind() == SymbolUse) {
-                    compileGetByValForObjectWithSymbol(node, prefix);
-                    return;
-                }
-            }
-
-            JSValueOperand base(this, m_graph.varArgChild(node, 0));
-            JSValueOperand property(this, m_graph.varArgChild(node, 1));
-            GPRReg baseGPR = base.gpr();
-            GPRReg propertyGPR = property.gpr();
-
-            JSValueRegs resultRegs;
-            std::tie(resultRegs, std::ignore) = prefix(DataFormatJS);
-
-            flushRegisters();
-            callOperation(operationGetByVal, resultRegs, TrustedImmPtr::weakPointer(m_graph, m_graph.globalObjectFor(node->origin.semantic)), baseGPR, propertyGPR);
-            m_jit.exceptionCheck();
-
-            jsValueResult(resultRegs, node);
-            return;
-        }
-
-        JSValueOperand base(this, m_graph.varArgChild(node, 0), ManualOperandSpeculation);
-        JSValueOperand property(this, m_graph.varArgChild(node, 1), ManualOperandSpeculation);
-        GPRReg baseGPR = base.gpr();
-        GPRReg propertyGPR = property.gpr();
-
-        GPRTemporary stubInfo;
-        GPRReg stubInfoGPR = InvalidGPRReg;
-        if (JITCode::useDataIC(JITType::DFGJIT)) {
-            stubInfo = GPRTemporary(this);
-            stubInfoGPR = stubInfo.gpr();
-        }
-
-        speculate(node, m_graph.varArgChild(node, 0));
-        speculate(node, m_graph.varArgChild(node, 1));
-
-        JSValueRegs resultRegs;
-        std::tie(resultRegs, std::ignore) = prefix(DataFormatJS);
-        GPRReg resultGPR = resultRegs.gpr();
-
-        CodeOrigin codeOrigin = node->origin.semantic;
-        CallSiteIndex callSite = m_jit.recordCallSiteAndGenerateExceptionHandlingOSRExitIfNeeded(codeOrigin, m_stream->size());
-        RegisterSet usedRegisters = this->usedRegisters();
-
-        JITCompiler::JumpList slowCases;
-        if (!m_state.forNode(m_graph.varArgChild(node, 0)).isType(SpecCell))
-            slowCases.append(m_jit.branchIfNotCell(baseGPR));
-
-        JITGetByValGenerator gen(
-            m_jit.codeBlock(), JITType::DFGJIT, codeOrigin, callSite, AccessType::GetByVal, usedRegisters,
-            JSValueRegs(baseGPR), JSValueRegs(propertyGPR), JSValueRegs(resultGPR), stubInfoGPR);
-
-        if (m_state.forNode(m_graph.varArgChild(node, 1)).isType(SpecString))
-            gen.stubInfo()->propertyIsString = true;
-        else if (m_state.forNode(m_graph.varArgChild(node, 1)).isType(SpecInt32Only))
-            gen.stubInfo()->propertyIsInt32 = true;
-        else if (m_state.forNode(m_graph.varArgChild(node, 1)).isType(SpecSymbol))
-            gen.stubInfo()->propertyIsSymbol = true;
-
-        gen.generateFastPath(m_jit);
-
-        if (!JITCode::useDataIC(JITType::DFGJIT))
-            slowCases.append(gen.slowPathJump());
-
-        std::unique_ptr<SlowPathGenerator> slowPath;
-        if (JITCode::useDataIC(JITType::DFGJIT)) {
-            slowPath = slowPathICCall(
-                slowCases, this, gen.stubInfo(), stubInfoGPR, CCallHelpers::Address(stubInfoGPR, StructureStubInfo::offsetOfSlowOperation()), operationGetByValOptimize,
-                resultGPR, TrustedImmPtr::weakPointer(m_graph, m_graph.globalObjectFor(codeOrigin)), stubInfoGPR, nullptr, baseGPR, propertyGPR);
-        } else {
-            slowPath = slowPathCall(
-                slowCases, this, operationGetByValOptimize,
-                resultGPR, TrustedImmPtr::weakPointer(m_graph, m_graph.globalObjectFor(codeOrigin)), gen.stubInfo(), nullptr, baseGPR, propertyGPR);
-        }
-
-        m_jit.addGetByVal(gen, slowPath.get());
-        addSlowPathGenerator(WTFMove(slowPath));
-
-        jsValueResult(resultGPR, node);
-        break;
-    }
-    case Array::Int32:
-    case Array::Contiguous: {
-        if (node->arrayMode().isInBounds()) {
-            SpeculateStrictInt32Operand property(this, m_graph.varArgChild(node, 1));
-            StorageOperand storage(this, m_graph.varArgChild(node, 2));
-
-            GPRReg propertyReg = property.gpr();
-            GPRReg storageReg = storage.gpr();
-
-            if (!m_compileOkay)
-                return;
-
-            JSValueRegs resultRegs;
-            DataFormat format;
-            std::tie(resultRegs, format) = prefix(node->arrayMode().type() == Array::Int32 ? DataFormatJSInt32 : DataFormatJS);
-            GPRReg result = resultRegs.gpr();
-
-            speculationCheck(OutOfBounds, JSValueRegs(), nullptr, m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfPublicLength())));
-
-            m_jit.load64(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight), result);
-            if (node->arrayMode().isInBoundsSaneChain()) {
-                ASSERT(node->arrayMode().type() == Array::Contiguous);
-                JITCompiler::Jump notHole = m_jit.branchIfNotEmpty(result);
-                m_jit.move(TrustedImm64(JSValue::encode(jsUndefined())), result);
-                notHole.link(&m_jit);
-            } else {
-                speculationCheck(
-                    LoadFromHole, JSValueRegs(), nullptr,
-                    m_jit.branchIfEmpty(result));
-            }
-            jsValueResult(result, node, format);
-            break;
-        }
-
-        SpeculateCellOperand base(this, m_graph.varArgChild(node, 0));
-        SpeculateStrictInt32Operand property(this, m_graph.varArgChild(node, 1));
-        StorageOperand storage(this, m_graph.varArgChild(node, 2));
-
-        GPRReg baseReg = base.gpr();
-        GPRReg propertyReg = property.gpr();
-        GPRReg storageReg = storage.gpr();
-
-        if (!m_compileOkay)
-            return;
-
-        JSValueRegs resultRegs;
-        std::tie(resultRegs, std::ignore) = prefix(DataFormatJS);
-        GPRReg resultReg = resultRegs.gpr();
-
-        MacroAssembler::JumpList slowCases;
-
-        slowCases.append(m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfPublicLength())));
-
-        m_jit.load64(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight), resultReg);
-
-        if (node->arrayMode().isOutOfBoundsSaneChain()) {
-            auto done = m_jit.branchIfNotEmpty(resultReg);
-            slowCases.link(&m_jit);
-            speculationCheck(NegativeIndex, JSValueRegs(), nullptr, m_jit.branch32(MacroAssembler::LessThan, propertyReg, CCallHelpers::TrustedImm32(0)));
-            m_jit.move(CCallHelpers::TrustedImm64(JSValue::encode(jsUndefined())), resultReg);
-            done.link(&m_jit);
-        } else {
-            slowCases.append(m_jit.branchIfEmpty(resultReg));
-            addSlowPathGenerator(
-                slowPathCall(
-                    slowCases, this, operationGetByValObjectInt,
-                    resultReg, TrustedImmPtr::weakPointer(m_graph, m_graph.globalObjectFor(node->origin.semantic)), baseReg, propertyReg));
-        }
-
-
-        jsValueResult(resultReg, node);
-        break;
-    }
-
-    case Array::Double: {
-        if (node->arrayMode().isInBounds()) {
-            SpeculateStrictInt32Operand property(this, m_graph.varArgChild(node, 1));
-            StorageOperand storage(this, m_graph.varArgChild(node, 2));
-
-            GPRReg propertyReg = property.gpr();
-            GPRReg storageReg = storage.gpr();
-
-            if (!m_compileOkay)
-                return;
-
-            FPRTemporary result(this);
-            FPRReg resultReg = result.fpr();
-
-            JSValueRegs resultRegs;
-            DataFormat format;
-            std::tie(resultRegs, format) = prefix(DataFormatDouble);
-
-            speculationCheck(OutOfBounds, JSValueRegs(), nullptr, m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfPublicLength())));
-
-            m_jit.loadDouble(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight), resultReg);
-            if (!node->arrayMode().isInBoundsSaneChain())
-                speculationCheck(LoadFromHole, JSValueRegs(), nullptr, m_jit.branchIfNaN(resultReg));
-            if (format == DataFormatJS) {
-                boxDouble(resultReg, resultRegs);
-                jsValueResult(resultRegs, node);
-            } else {
-                ASSERT(format == DataFormatDouble && !resultRegs);
-                doubleResult(resultReg, node);
-            }
-            break;
-        }
-
-        bool resultIsUnboxed = node->arrayMode().isOutOfBoundsSaneChain() && !(node->flags() & NodeBytecodeUsesAsOther);
-
-        SpeculateCellOperand base(this, m_graph.varArgChild(node, 0));
-        SpeculateStrictInt32Operand property(this, m_graph.varArgChild(node, 1));
-        StorageOperand storage(this, m_graph.varArgChild(node, 2));
-
-        GPRReg baseReg = base.gpr();
-        GPRReg propertyReg = property.gpr();
-        GPRReg storageReg = storage.gpr();
-
-        if (!m_compileOkay)
-            return;
-
-        FPRTemporary temp(this);
-        FPRReg tempReg = temp.fpr();
-
-        JSValueRegs resultRegs;
-        DataFormat format;
-        std::tie(resultRegs, format) = prefix(resultIsUnboxed ? DataFormatDouble : DataFormatJS);
-
-        MacroAssembler::JumpList slowCases;
-
-        slowCases.append(m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfPublicLength())));
-
-        m_jit.loadDouble(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight), tempReg);
-        if (node->arrayMode().isOutOfBoundsSaneChain()) {
-            if (format == DataFormatDouble) {
-                auto done = m_jit.jump();
-                slowCases.link(&m_jit);
-                speculationCheck(NegativeIndex, JSValueRegs(), nullptr, m_jit.branch32(MacroAssembler::LessThan, propertyReg, CCallHelpers::TrustedImm32(0)));
-                static const double NaN = PNaN;
-                m_jit.loadDouble(TrustedImmPtr(&NaN), tempReg);
-                done.link(&m_jit);
-                ASSERT(!resultRegs);
-                doubleResult(tempReg, node);
-            } else {
-                slowCases.append(m_jit.branchIfNaN(tempReg));
-                boxDouble(tempReg, resultRegs.gpr());
-                auto done = m_jit.jump();
-                slowCases.link(&m_jit);
-                speculationCheck(NegativeIndex, JSValueRegs(), nullptr, m_jit.branch32(MacroAssembler::LessThan, propertyReg, CCallHelpers::TrustedImm32(0)));
-                m_jit.move(CCallHelpers::TrustedImm64(JSValue::encode(jsUndefined())), resultRegs.gpr());
-                done.link(&m_jit);
-                jsValueResult(resultRegs.gpr(), node);
-            }
-        } else {
-            slowCases.append(m_jit.branchIfNaN(tempReg));
-            boxDouble(tempReg, resultRegs.gpr());
-            addSlowPathGenerator(
-                slowPathCall(
-                    slowCases, this, operationGetByValObjectInt,
-                    resultRegs.gpr(), TrustedImmPtr::weakPointer(m_graph, m_graph.globalObjectFor(node->origin.semantic)), baseReg, propertyReg));
-            jsValueResult(resultRegs.gpr(), node);
-        }
-
-        break;
-    }
-
-    case Array::ArrayStorage:
-    case Array::SlowPutArrayStorage: {
-        if (node->arrayMode().isInBounds()) {
-            SpeculateStrictInt32Operand property(this, m_graph.varArgChild(node, 1));
-            StorageOperand storage(this, m_graph.varArgChild(node, 2));
-
-            GPRReg propertyReg = property.gpr();
-            GPRReg storageReg = storage.gpr();
-
-            if (!m_compileOkay)
-                return;
-
-            JSValueRegs resultRegs;
-            std::tie(resultRegs, std::ignore) = prefix(DataFormatJS);
-            GPRReg resultGPR = resultRegs.gpr();
-
-            speculationCheck(OutOfBounds, JSValueRegs(), nullptr, m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, ArrayStorage::vectorLengthOffset())));
-
-
-            m_jit.load64(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, ArrayStorage::vectorOffset()), resultGPR);
-            speculationCheck(LoadFromHole, JSValueRegs(), nullptr, m_jit.branchIfEmpty(resultGPR));
-
-            jsValueResult(resultGPR, node);
-            break;
-        }
-
-        SpeculateCellOperand base(this, m_graph.varArgChild(node, 0));
-        SpeculateStrictInt32Operand property(this, m_graph.varArgChild(node, 1));
-        StorageOperand storage(this, m_graph.varArgChild(node, 2));
-
-        GPRReg baseReg = base.gpr();
-        GPRReg propertyReg = property.gpr();
-        GPRReg storageReg = storage.gpr();
-
-        if (!m_compileOkay)
-            return;
-
-        JSValueRegs resultRegs;
-        std::tie(resultRegs, std::ignore) = prefix(DataFormatJS);
-        GPRReg resultReg = resultRegs.gpr();
-
-        MacroAssembler::JumpList slowCases;
-
-        slowCases.append(m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, ArrayStorage::vectorLengthOffset())));
-
-        m_jit.load64(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, ArrayStorage::vectorOffset()), resultReg);
-        slowCases.append(m_jit.branchIfEmpty(resultReg));
-
-        addSlowPathGenerator(
-            slowPathCall(
-                slowCases, this, operationGetByValObjectInt,
-                resultReg, TrustedImmPtr::weakPointer(m_graph, m_graph.globalObjectFor(node->origin.semantic)), baseReg, propertyReg));
-
-        jsValueResult(resultReg, node);
-        break;
-    }
-    case Array::String:
-        compileGetByValOnString(node, prefix);
-        break;
-    case Array::DirectArguments:
-        compileGetByValOnDirectArguments(node, prefix);
-        break;
-    case Array::ScopedArguments:
-        compileGetByValOnScopedArguments(node, prefix);
-        break;
-    case Array::Int8Array:
-    case Array::Int16Array:
-    case Array::Int32Array:
-    case Array::Uint8Array:
-    case Array::Uint8ClampedArray:
-    case Array::Uint16Array:
-    case Array::Uint32Array:
-    case Array::Float32Array:
-    case Array::Float64Array: {
-        TypedArrayType type = node->arrayMode().typedArrayType();
-        if (isInt(type))
-            compileGetByValOnIntTypedArray(node, type, prefix);
-        else
-            compileGetByValOnFloatTypedArray(node, type, prefix);
-    } }
-}
-
</del><span class="cx"> void SpeculativeJIT::compile(Node* node)
</span><span class="cx"> {
</span><span class="cx">     NodeType op = node->op();
</span><span class="lines">@@ -3077,12 +2713,7 @@
</span><span class="cx"> 
</span><span class="cx">     case StringCharAt: {
</span><span class="cx">         // Relies on StringCharAt node having same basic layout as GetByVal
</span><del>-        JSValueRegsTemporary result;
-        compileGetByValOnString(node, scopedLambda<std::tuple<JSValueRegs, DataFormat>(DataFormat preferredFormat)>([&] (DataFormat preferredFormat) {
-            result = JSValueRegsTemporary(this);
-            ASSERT(preferredFormat == DataFormatJS || preferredFormat == DataFormatCell);
-            return std::make_pair(result.regs(), preferredFormat);
-        }));
</del><ins>+        compileGetByValOnString(node);
</ins><span class="cx">         break;
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="lines">@@ -3115,20 +2746,345 @@
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     case GetByVal: {
</span><del>-        JSValueRegsTemporary result;
-        compileGetByVal(node, scopedLambda<std::tuple<JSValueRegs, DataFormat>(DataFormat preferredFormat)>([&] (DataFormat preferredFormat) {
-            JSValueRegs resultRegs;
-            switch (preferredFormat) {
-            case DataFormatDouble:
</del><ins>+        switch (node->arrayMode().type()) {
+        case Array::AnyTypedArray:
+        case Array::ForceExit:
+        case Array::SelectUsingArguments:
+        case Array::SelectUsingPredictions:
+        case Array::Unprofiled:
+            DFG_CRASH(m_jit.graph(), node, "Bad array mode type");
+            break;
+        case Array::Undecided: {
+            SpeculateStrictInt32Operand index(this, m_graph.varArgChild(node, 1));
+            GPRTemporary result(this, Reuse, index);
+            GPRReg indexGPR = index.gpr();
+            GPRReg resultGPR = result.gpr();
+
+            speculationCheck(OutOfBounds, JSValueRegs(), node,
+                m_jit.branch32(MacroAssembler::LessThan, indexGPR, MacroAssembler::TrustedImm32(0)));
+
+            use(m_graph.varArgChild(node, 0));
+            index.use();
+
+            m_jit.move(MacroAssembler::TrustedImm64(JSValue::ValueUndefined), resultGPR);
+            jsValueResult(resultGPR, node, UseChildrenCalledExplicitly);
+            break;
+        }
+        case Array::BigInt64Array:
+        case Array::BigUint64Array:
+        case Array::Generic: {
+            if (m_graph.m_slowGetByVal.contains(node)) {
+                if (m_graph.varArgChild(node, 0).useKind() == ObjectUse) {
+                    if (m_graph.varArgChild(node, 1).useKind() == StringUse) {
+                        compileGetByValForObjectWithString(node);
+                        break;
+                    }
+
+                    if (m_graph.varArgChild(node, 1).useKind() == SymbolUse) {
+                        compileGetByValForObjectWithSymbol(node);
+                        break;
+                    }
+                }
+
+                JSValueOperand base(this, m_graph.varArgChild(node, 0));
+                JSValueOperand property(this, m_graph.varArgChild(node, 1));
+                GPRReg baseGPR = base.gpr();
+                GPRReg propertyGPR = property.gpr();
+                
+                flushRegisters();
+                GPRFlushedCallResult result(this);
+                callOperation(operationGetByVal, result.gpr(), TrustedImmPtr::weakPointer(m_graph, m_graph.globalObjectFor(node->origin.semantic)), baseGPR, propertyGPR);
+                m_jit.exceptionCheck();
+                
+                jsValueResult(result.gpr(), node);
</ins><span class="cx">                 break;
</span><del>-            default: {
-                result = JSValueRegsTemporary(this);
-                resultRegs = result.regs();
</del><ins>+            }
+
+            std::optional<GPRTemporary> stubInfo;
+            JSValueOperand base(this, m_graph.varArgChild(node, 0), ManualOperandSpeculation);
+            JSValueOperand property(this, m_graph.varArgChild(node, 1), ManualOperandSpeculation);
+            GPRTemporary result(this, Reuse, property);
+
+            GPRReg stubInfoGPR = InvalidGPRReg;
+            if (JITCode::useDataIC(JITType::DFGJIT)) {
+                stubInfo.emplace(this);
+                stubInfoGPR = stubInfo->gpr();
+            }
+            GPRReg baseGPR = base.gpr();
+            GPRReg propertyGPR = property.gpr();
+            GPRReg resultGPR = result.gpr();
+
+            speculate(node, m_graph.varArgChild(node, 0));
+            speculate(node, m_graph.varArgChild(node, 1));
+
+            CodeOrigin codeOrigin = node->origin.semantic;
+            CallSiteIndex callSite = m_jit.recordCallSiteAndGenerateExceptionHandlingOSRExitIfNeeded(codeOrigin, m_stream->size());
+            RegisterSet usedRegisters = this->usedRegisters();
+
+            JITCompiler::JumpList slowCases;
+            if (!m_state.forNode(m_graph.varArgChild(node, 0)).isType(SpecCell))
+                slowCases.append(m_jit.branchIfNotCell(baseGPR));
+
+            JITGetByValGenerator gen(
+                m_jit.codeBlock(), JITType::DFGJIT, codeOrigin, callSite, AccessType::GetByVal, usedRegisters,
+                JSValueRegs(baseGPR), JSValueRegs(propertyGPR), JSValueRegs(resultGPR), stubInfoGPR);
+
+            if (m_state.forNode(m_graph.varArgChild(node, 1)).isType(SpecString))
+                gen.stubInfo()->propertyIsString = true;
+            else if (m_state.forNode(m_graph.varArgChild(node, 1)).isType(SpecInt32Only))
+                gen.stubInfo()->propertyIsInt32 = true;
+            else if (m_state.forNode(m_graph.varArgChild(node, 1)).isType(SpecSymbol))
+                gen.stubInfo()->propertyIsSymbol = true;
+
+            gen.generateFastPath(m_jit);
+            
+            if (!JITCode::useDataIC(JITType::DFGJIT))
+                slowCases.append(gen.slowPathJump());
+
+            std::unique_ptr<SlowPathGenerator> slowPath;
+            if (JITCode::useDataIC(JITType::DFGJIT)) {
+                slowPath = slowPathICCall(
+                    slowCases, this, gen.stubInfo(), stubInfoGPR, CCallHelpers::Address(stubInfoGPR, StructureStubInfo::offsetOfSlowOperation()), operationGetByValOptimize,
+                    resultGPR, TrustedImmPtr::weakPointer(m_graph, m_graph.globalObjectFor(codeOrigin)), stubInfoGPR, nullptr, baseGPR, propertyGPR);
+            } else {
+                slowPath = slowPathCall(
+                    slowCases, this, operationGetByValOptimize,
+                    resultGPR, TrustedImmPtr::weakPointer(m_graph, m_graph.globalObjectFor(codeOrigin)), gen.stubInfo(), nullptr, baseGPR, propertyGPR);
+            }
+            
+            m_jit.addGetByVal(gen, slowPath.get());
+            addSlowPathGenerator(WTFMove(slowPath));
+
+            jsValueResult(resultGPR, node);
+            break;
+        }
+        case Array::Int32:
+        case Array::Contiguous: {
+            if (node->arrayMode().isInBounds()) {
+                SpeculateStrictInt32Operand property(this, m_graph.varArgChild(node, 1));
+                StorageOperand storage(this, m_graph.varArgChild(node, 2));
+
+                GPRReg propertyReg = property.gpr();
+                GPRReg storageReg = storage.gpr();
+
+                if (!m_compileOkay)
+                    return;
+                
+                speculationCheck(OutOfBounds, JSValueRegs(), nullptr, m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfPublicLength())));
+                
+                GPRTemporary result(this);
+
+                m_jit.load64(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight), result.gpr());
+                if (node->arrayMode().isInBoundsSaneChain()) {
+                    ASSERT(node->arrayMode().type() == Array::Contiguous);
+                    JITCompiler::Jump notHole = m_jit.branchIfNotEmpty(result.gpr());
+                    m_jit.move(TrustedImm64(JSValue::encode(jsUndefined())), result.gpr());
+                    notHole.link(&m_jit);
+                } else {
+                    speculationCheck(
+                        LoadFromHole, JSValueRegs(), nullptr,
+                        m_jit.branchIfEmpty(result.gpr()));
+                }
+                jsValueResult(result.gpr(), node, node->arrayMode().type() == Array::Int32 ? DataFormatJSInt32 : DataFormatJS);
</ins><span class="cx">                 break;
</span><span class="cx">             }
</span><del>-            };
-            return std::make_pair(resultRegs, preferredFormat);
-        }));
</del><ins>+            
+            SpeculateCellOperand base(this, m_graph.varArgChild(node, 0));
+            SpeculateStrictInt32Operand property(this, m_graph.varArgChild(node, 1));
+            StorageOperand storage(this, m_graph.varArgChild(node, 2));
+            
+            GPRReg baseReg = base.gpr();
+            GPRReg propertyReg = property.gpr();
+            GPRReg storageReg = storage.gpr();
+            
+            if (!m_compileOkay)
+                return;
+            
+            GPRTemporary result(this);
+            GPRReg resultReg = result.gpr();
+            
+            MacroAssembler::JumpList slowCases;
+            
+            slowCases.append(m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfPublicLength())));
+
+            m_jit.load64(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight), resultReg);
+
+            if (node->arrayMode().isOutOfBoundsSaneChain()) {
+                auto done = m_jit.branchIfNotEmpty(resultReg);
+                slowCases.link(&m_jit);
+                speculationCheck(NegativeIndex, JSValueRegs(), nullptr, m_jit.branch32(MacroAssembler::LessThan, propertyReg, CCallHelpers::TrustedImm32(0)));
+                m_jit.move(CCallHelpers::TrustedImm64(JSValue::encode(jsUndefined())), resultReg);
+                done.link(&m_jit);
+            } else {
+                slowCases.append(m_jit.branchIfEmpty(resultReg));
+                addSlowPathGenerator(
+                    slowPathCall(
+                        slowCases, this, operationGetByValObjectInt,
+                        result.gpr(), TrustedImmPtr::weakPointer(m_graph, m_graph.globalObjectFor(node->origin.semantic)), baseReg, propertyReg));
+            }
+            
+            
+            jsValueResult(resultReg, node);
+            break;
+        }
+
+        case Array::Double: {
+            if (node->arrayMode().isInBounds()) {
+                SpeculateStrictInt32Operand property(this, m_graph.varArgChild(node, 1));
+                StorageOperand storage(this, m_graph.varArgChild(node, 2));
+
+                GPRReg propertyReg = property.gpr();
+                GPRReg storageReg = storage.gpr();
+
+                if (!m_compileOkay)
+                    return;
+
+                FPRTemporary result(this);
+                FPRReg resultReg = result.fpr();
+
+                speculationCheck(OutOfBounds, JSValueRegs(), nullptr, m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfPublicLength())));
+
+                m_jit.loadDouble(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight), resultReg);
+                if (!node->arrayMode().isInBoundsSaneChain())
+                    speculationCheck(LoadFromHole, JSValueRegs(), nullptr, m_jit.branchIfNaN(resultReg));
+                doubleResult(resultReg, node);
+                break;
+            }
+
+            bool resultIsUnboxed = node->arrayMode().isOutOfBoundsSaneChain() && !(node->flags() & NodeBytecodeUsesAsOther);
+
+            SpeculateCellOperand base(this, m_graph.varArgChild(node, 0));
+            SpeculateStrictInt32Operand property(this, m_graph.varArgChild(node, 1));
+            StorageOperand storage(this, m_graph.varArgChild(node, 2));
+            
+            GPRReg baseReg = base.gpr();
+            GPRReg propertyReg = property.gpr();
+            GPRReg storageReg = storage.gpr();
+            
+            if (!m_compileOkay)
+                return;
+            
+            std::optional<GPRTemporary> result;
+            std::optional<GPRReg> resultReg;
+            if (!resultIsUnboxed) {
+                result.emplace(this);
+                resultReg = result->gpr();
+            }
+            FPRTemporary temp(this);
+            FPRReg tempReg = temp.fpr();
+            
+            MacroAssembler::JumpList slowCases;
+            
+            slowCases.append(m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfPublicLength())));
+
+            m_jit.loadDouble(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight), tempReg);
+            if (node->arrayMode().isOutOfBoundsSaneChain()) {
+                if (resultIsUnboxed) {
+                    auto done = m_jit.jump();
+                    slowCases.link(&m_jit);
+                    speculationCheck(NegativeIndex, JSValueRegs(), nullptr, m_jit.branch32(MacroAssembler::LessThan, propertyReg, CCallHelpers::TrustedImm32(0)));
+                    static const double NaN = PNaN;
+                    m_jit.loadDouble(TrustedImmPtr(&NaN), tempReg);
+                    done.link(&m_jit);
+                    doubleResult(tempReg, node);
+                } else {
+                    slowCases.append(m_jit.branchIfNaN(tempReg));
+                    boxDouble(tempReg, *resultReg);
+                    auto done = m_jit.jump();
+                    slowCases.link(&m_jit);
+                    speculationCheck(NegativeIndex, JSValueRegs(), nullptr, m_jit.branch32(MacroAssembler::LessThan, propertyReg, CCallHelpers::TrustedImm32(0)));
+                    m_jit.move(CCallHelpers::TrustedImm64(JSValue::encode(jsUndefined())), *resultReg);
+                    done.link(&m_jit);
+                    jsValueResult(*resultReg, node);
+                }
+            } else {
+                slowCases.append(m_jit.branchIfNaN(tempReg));
+                boxDouble(tempReg, *resultReg);
+                addSlowPathGenerator(
+                    slowPathCall(
+                        slowCases, this, operationGetByValObjectInt,
+                        *resultReg, TrustedImmPtr::weakPointer(m_graph, m_graph.globalObjectFor(node->origin.semantic)), baseReg, propertyReg));
+                jsValueResult(*resultReg, node);
+            }
+
+            break;
+        }
+
+        case Array::ArrayStorage:
+        case Array::SlowPutArrayStorage: {
+            if (node->arrayMode().isInBounds()) {
+                SpeculateStrictInt32Operand property(this, m_graph.varArgChild(node, 1));
+                StorageOperand storage(this, m_graph.varArgChild(node, 2));
+            
+                GPRReg propertyReg = property.gpr();
+                GPRReg storageReg = storage.gpr();
+            
+                if (!m_compileOkay)
+                    return;
+            
+                speculationCheck(OutOfBounds, JSValueRegs(), nullptr, m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, ArrayStorage::vectorLengthOffset())));
+            
+                GPRTemporary result(this);
+                m_jit.load64(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, ArrayStorage::vectorOffset()), result.gpr());
+                speculationCheck(LoadFromHole, JSValueRegs(), nullptr, m_jit.branchIfEmpty(result.gpr()));
+            
+                jsValueResult(result.gpr(), node);
+                break;
+            }
+
+            SpeculateCellOperand base(this, m_graph.varArgChild(node, 0));
+            SpeculateStrictInt32Operand property(this, m_graph.varArgChild(node, 1));
+            StorageOperand storage(this, m_graph.varArgChild(node, 2));
+            
+            GPRReg baseReg = base.gpr();
+            GPRReg propertyReg = property.gpr();
+            GPRReg storageReg = storage.gpr();
+            
+            if (!m_compileOkay)
+                return;
+            
+            GPRTemporary result(this);
+            GPRReg resultReg = result.gpr();
+            
+            MacroAssembler::JumpList slowCases;
+            
+            slowCases.append(m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, ArrayStorage::vectorLengthOffset())));
+    
+            m_jit.load64(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, ArrayStorage::vectorOffset()), resultReg);
+            slowCases.append(m_jit.branchIfEmpty(resultReg));
+    
+            addSlowPathGenerator(
+                slowPathCall(
+                    slowCases, this, operationGetByValObjectInt,
+                    result.gpr(), TrustedImmPtr::weakPointer(m_graph, m_graph.globalObjectFor(node->origin.semantic)), baseReg, propertyReg));
+            
+            jsValueResult(resultReg, node);
+            break;
+        }
+        case Array::String:
+            compileGetByValOnString(node);
+            break;
+        case Array::DirectArguments:
+            compileGetByValOnDirectArguments(node);
+            break;
+        case Array::ScopedArguments:
+            compileGetByValOnScopedArguments(node);
+            break;
+        case Array::Int8Array:
+        case Array::Int16Array:
+        case Array::Int32Array:
+        case Array::Uint8Array:
+        case Array::Uint8ClampedArray:
+        case Array::Uint16Array:
+        case Array::Uint32Array:
+        case Array::Float32Array:
+        case Array::Float64Array: {
+            TypedArrayType type = node->arrayMode().typedArrayType();
+            if (isInt(type))
+                compileGetByValOnIntTypedArray(node, type);
+            else
+                compileGetByValOnFloatTypedArray(node, type);
+        } }
</ins><span class="cx">         break;
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="lines">@@ -3625,8 +3581,7 @@
</span><span class="cx">             break;
</span><span class="cx">         }
</span><span class="cx">         constexpr bool canSpeculate = false;
</span><del>-        constexpr bool shouldBox = false;
-        setIntTypedArrayLoadResult(node, JSValueRegs(resultGPR), type, canSpeculate, shouldBox);
</del><ins>+        setIntTypedArrayLoadResult(node, resultGPR, type, canSpeculate);
</ins><span class="cx">         break;
</span><span class="cx">     }
</span><span class="cx">         
</span><span class="lines">@@ -5314,56 +5269,52 @@
</span><span class="cx">         compileStoreBarrier(node);
</span><span class="cx">         break;
</span><span class="cx">     }
</span><del>-
-    case HasIndexedProperty: {
-        SpeculateStrictInt32Operand index(this, m_graph.varArgChild(node, 1));
-        GPRTemporary result(this, Reuse, index);
-
-        compileHasIndexedProperty(node, operationHasIndexedProperty, scopedLambda<std::tuple<GPRReg, GPRReg>()>([&] { return std::make_pair(index.gpr(), result.gpr()); }));
-        unblessedBooleanResult(result.gpr(), node);
</del><ins>+        
+    case GetEnumerableLength: {
+        compileGetEnumerableLength(node);
</ins><span class="cx">         break;
</span><span class="cx">     }
</span><del>-
-    case GetPropertyEnumerator: {
-        compileGetPropertyEnumerator(node);
</del><ins>+    case HasEnumerableStructureProperty: {
+        compileHasEnumerableStructureProperty(node);
</ins><span class="cx">         break;
</span><span class="cx">     }
</span><del>-
-    case EnumeratorNextUpdateIndexAndMode: {
-        compileEnumeratorNextUpdateIndexAndMode(node);
</del><ins>+    case HasEnumerableProperty: {
+        compileHasEnumerableProperty(node);
</ins><span class="cx">         break;
</span><span class="cx">     }
</span><del>-
-    case EnumeratorNextExtractMode: {
-        compileEnumeratorNextExtractMode(node);
</del><ins>+    case HasOwnStructureProperty: {
+        compileHasOwnStructureProperty(node);
</ins><span class="cx">         break;
</span><span class="cx">     }
</span><del>-
-    case EnumeratorNextExtractIndex: {
-        compileEnumeratorNextExtractIndex(node);
</del><ins>+    case InStructureProperty: {
+        compileInStructureProperty(node);
</ins><span class="cx">         break;
</span><span class="cx">     }
</span><del>-
-    case EnumeratorNextUpdatePropertyName: {
-        compileEnumeratorNextUpdatePropertyName(node);
</del><ins>+    case HasIndexedProperty: {
+        compileHasIndexedProperty(node, operationHasIndexedProperty);
</ins><span class="cx">         break;
</span><span class="cx">     }
</span><del>-
-    case EnumeratorGetByVal: {
-        compileEnumeratorGetByVal(node);
</del><ins>+    case HasEnumerableIndexedProperty: {
+        compileHasIndexedProperty(node, operationHasEnumerableIndexedProperty);
</ins><span class="cx">         break;
</span><span class="cx">     }
</span><del>-
-    case EnumeratorInByVal: {
-        compileEnumeratorInByVal(node);
</del><ins>+    case GetDirectPname: {
+        compileGetDirectPname(node);
</ins><span class="cx">         break;
</span><span class="cx">     }
</span><del>-
-    case EnumeratorHasOwnProperty: {
-        compileEnumeratorHasOwnProperty(node);
</del><ins>+    case GetPropertyEnumerator: {
+        compileGetPropertyEnumerator(node);
</ins><span class="cx">         break;
</span><span class="cx">     }
</span><del>-
</del><ins>+    case GetEnumeratorStructurePname:
+    case GetEnumeratorGenericPname: {
+        compileGetEnumeratorPname(node);
+        break;
+    }
+    case ToIndexString: {
+        compileToIndexString(node);
+        break;
+    }
</ins><span class="cx">     case ProfileType: {
</span><span class="cx">         compileProfileType(node);
</span><span class="cx">         break;
</span></span></pre></div>
<a id="branchessafari612128branchSourceJavaScriptCoredfgDFGTypeCheckHoistingPhasecpp"></a>
<div class="modfile"><h4>Modified: branches/safari-612.1.28-branch/Source/JavaScriptCore/dfg/DFGTypeCheckHoistingPhase.cpp (281021 => 281022)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-612.1.28-branch/Source/JavaScriptCore/dfg/DFGTypeCheckHoistingPhase.cpp  2021-08-13 16:39:44 UTC (rev 281021)
+++ branches/safari-612.1.28-branch/Source/JavaScriptCore/dfg/DFGTypeCheckHoistingPhase.cpp     2021-08-13 16:50:38 UTC (rev 281022)
</span><span class="lines">@@ -273,7 +273,6 @@
</span><span class="cx">                 case ReallocatePropertyStorage:
</span><span class="cx">                 case NukeStructureAndSetButterfly:
</span><span class="cx">                 case GetButterfly:
</span><del>-                case EnumeratorGetByVal:
</del><span class="cx">                 case GetByVal:
</span><span class="cx">                 case PutByValDirect:
</span><span class="cx">                 case PutByVal:
</span><span class="lines">@@ -353,7 +352,6 @@
</span><span class="cx">                 case PutStructure:
</span><span class="cx">                 case ReallocatePropertyStorage:
</span><span class="cx">                 case GetButterfly:
</span><del>-                case EnumeratorGetByVal:
</del><span class="cx">                 case GetByVal:
</span><span class="cx">                 case PutByValDirect:
</span><span class="cx">                 case PutByVal:
</span></span></pre></div>
<a id="branchessafari612128branchSourceJavaScriptCoreftlFTLAbstractHeapRepositoryh"></a>
<div class="modfile"><h4>Modified: branches/safari-612.1.28-branch/Source/JavaScriptCore/ftl/FTLAbstractHeapRepository.h (281021 => 281022)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-612.1.28-branch/Source/JavaScriptCore/ftl/FTLAbstractHeapRepository.h    2021-08-13 16:39:44 UTC (rev 281021)
+++ branches/safari-612.1.28-branch/Source/JavaScriptCore/ftl/FTLAbstractHeapRepository.h       2021-08-13 16:50:38 UTC (rev 281022)
</span><span class="lines">@@ -114,7 +114,6 @@
</span><span class="cx">     macro(JSPropertyNameEnumerator_endGenericPropertyIndex, JSPropertyNameEnumerator::endGenericPropertyIndexOffset()) \
</span><span class="cx">     macro(JSPropertyNameEnumerator_endStructurePropertyIndex, JSPropertyNameEnumerator::endStructurePropertyIndexOffset()) \
</span><span class="cx">     macro(JSPropertyNameEnumerator_indexLength, JSPropertyNameEnumerator::indexedLengthOffset()) \
</span><del>-    macro(JSPropertyNameEnumerator_modeSet, JSPropertyNameEnumerator::modeSetOffset()) \
</del><span class="cx">     macro(JSRopeString_flags, JSRopeString::offsetOfFlags()) \
</span><span class="cx">     macro(JSRopeString_length, JSRopeString::offsetOfLength()) \
</span><span class="cx">     macro(JSRopeString_fiber0, JSRopeString::offsetOfFiber0()) \
</span></span></pre></div>
<a id="branchessafari612128branchSourceJavaScriptCoreftlFTLCapabilitiescpp"></a>
<div class="modfile"><h4>Modified: branches/safari-612.1.28-branch/Source/JavaScriptCore/ftl/FTLCapabilities.cpp (281021 => 281022)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-612.1.28-branch/Source/JavaScriptCore/ftl/FTLCapabilities.cpp    2021-08-13 16:39:44 UTC (rev 281021)
+++ branches/safari-612.1.28-branch/Source/JavaScriptCore/ftl/FTLCapabilities.cpp       2021-08-13 16:50:38 UTC (rev 281022)
</span><span class="lines">@@ -286,15 +286,18 @@
</span><span class="cx">     case Int52Constant:
</span><span class="cx">     case BooleanToNumber:
</span><span class="cx">     case HasIndexedProperty:
</span><ins>+    case HasEnumerableIndexedProperty:
+    case HasEnumerableStructureProperty:
+    case HasEnumerableProperty:
+    case HasOwnStructureProperty:
+    case InStructureProperty:
+    case GetDirectPname:
+    case GetEnumerableLength:
</ins><span class="cx">     case GetIndexedPropertyStorage:
</span><span class="cx">     case GetPropertyEnumerator:
</span><del>-    case EnumeratorNextUpdateIndexAndMode:
-    case EnumeratorNextExtractMode:
-    case EnumeratorNextExtractIndex:
-    case EnumeratorNextUpdatePropertyName:
-    case EnumeratorGetByVal:
-    case EnumeratorInByVal:
-    case EnumeratorHasOwnProperty:
</del><ins>+    case GetEnumeratorStructurePname:
+    case GetEnumeratorGenericPname:
+    case ToIndexString:
</ins><span class="cx">     case BottomValue:
</span><span class="cx">     case PhantomNewObject:
</span><span class="cx">     case PhantomNewFunction:
</span></span></pre></div>
<a id="branchessafari612128branchSourceJavaScriptCoreftlFTLLowerDFGToB3cpp"></a>
<div class="modfile"><h4>Modified: branches/safari-612.1.28-branch/Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp (281021 => 281022)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-612.1.28-branch/Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp    2021-08-13 16:39:44 UTC (rev 281021)
+++ branches/safari-612.1.28-branch/Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp       2021-08-13 16:50:38 UTC (rev 281022)
</span><span class="lines">@@ -1523,32 +1523,41 @@
</span><span class="cx">             compileStoreBarrier();
</span><span class="cx">             break;
</span><span class="cx">         case HasIndexedProperty:
</span><del>-            compileHasIndexedProperty();
</del><ins>+            compileHasIndexedProperty(operationHasIndexedProperty);
</ins><span class="cx">             break;
</span><del>-        case GetPropertyEnumerator:
-            compileGetPropertyEnumerator();
</del><ins>+        case HasEnumerableIndexedProperty:
+            compileHasIndexedProperty(operationHasEnumerableIndexedProperty);
</ins><span class="cx">             break;
</span><del>-        case EnumeratorNextUpdateIndexAndMode:
-            compileEnumeratorNextUpdateIndexAndMode();
</del><ins>+        case HasEnumerableStructureProperty:
+            compileHasEnumerableStructureProperty();
</ins><span class="cx">             break;
</span><del>-        case EnumeratorNextExtractIndex:
-            compileEnumeratorNextExtractIndex();
</del><ins>+        case HasEnumerableProperty:
+            compileHasEnumerableProperty();
</ins><span class="cx">             break;
</span><del>-        case EnumeratorNextExtractMode:
-            compileEnumeratorNextExtractMode();
</del><ins>+        case HasOwnStructureProperty:
+            compileHasOwnStructureProperty();
</ins><span class="cx">             break;
</span><del>-        case EnumeratorNextUpdatePropertyName:
-            compileEnumeratorNextUpdatePropertyName();
</del><ins>+        case InStructureProperty:
+            compileInStructureProperty();
</ins><span class="cx">             break;
</span><del>-        case EnumeratorGetByVal:
-            compileEnumeratorGetByVal();
</del><ins>+        case GetDirectPname:
+            compileGetDirectPname();
</ins><span class="cx">             break;
</span><del>-        case EnumeratorInByVal:
-            compileEnumeratorInByVal();
</del><ins>+        case GetEnumerableLength:
+            compileGetEnumerableLength();
</ins><span class="cx">             break;
</span><del>-        case EnumeratorHasOwnProperty:
-            compileEnumeratorHasOwnProperty();
</del><ins>+        case GetPropertyEnumerator:
+            compileGetPropertyEnumerator();
</ins><span class="cx">             break;
</span><ins>+        case GetEnumeratorStructurePname:
+            compileGetEnumeratorStructurePname();
+            break;
+        case GetEnumeratorGenericPname:
+            compileGetEnumeratorGenericPname();
+            break;
+        case ToIndexString:
+            compileToIndexString();
+            break;
</ins><span class="cx">         case CheckStructureImmediate:
</span><span class="cx">             compileCheckStructureImmediate();
</span><span class="cx">             break;
</span><span class="lines">@@ -5011,7 +5020,7 @@
</span><span class="cx">         // we dominate them.
</span><span class="cx">     }
</span><span class="cx">     
</span><del>-    LValue compileGetByValImpl()
</del><ins>+    void compileGetByVal()
</ins><span class="cx">     {
</span><span class="cx">         JSGlobalObject* globalObject = m_graph.globalObjectFor(m_origin.semantic);
</span><span class="cx">         switch (m_node->arrayMode().type()) {
</span><span class="lines">@@ -5038,7 +5047,8 @@
</span><span class="cx">                 // We have to keep base alive to keep content in storage alive.
</span><span class="cx">                 if (m_node->arrayMode().type() == Array::Contiguous)
</span><span class="cx">                     ensureStillAliveHere(base);
</span><del>-                return result;
</del><ins>+                setJSValue(result);
+                return;
</ins><span class="cx">             }
</span><span class="cx"> 
</span><span class="cx">             LBasicBlock fastCase = m_out.newBlock();
</span><span class="lines">@@ -5070,7 +5080,8 @@
</span><span class="cx">             // We have to keep base alive to keep content in storage alive.
</span><span class="cx">             if (m_node->arrayMode().type() == Array::Contiguous)
</span><span class="cx">                 ensureStillAliveHere(base);
</span><del>-            return m_out.phi(Int64, fastResult, slowResult);
</del><ins>+            setJSValue(m_out.phi(Int64, fastResult, slowResult));
+            return;
</ins><span class="cx">         }
</span><span class="cx">             
</span><span class="cx">         case Array::Double: {
</span><span class="lines">@@ -5089,8 +5100,8 @@
</span><span class="cx">                         LoadFromHole, noValue(), nullptr,
</span><span class="cx">                         m_out.doubleNotEqualOrUnordered(result, result));
</span><span class="cx">                 }
</span><del>-
-                return result;
</del><ins>+                setDouble(result);
+                break;
</ins><span class="cx">             }
</span><span class="cx"> 
</span><span class="cx">             bool resultIsUnboxed = m_node->arrayMode().isOutOfBoundsSaneChain() && !(m_node->flags() & NodeBytecodeUsesAsOther);
</span><span class="lines">@@ -5130,9 +5141,10 @@
</span><span class="cx">             
</span><span class="cx">             m_out.appendTo(continuation, lastNext);
</span><span class="cx">             if (resultIsUnboxed)
</span><del>-                return m_out.phi(Double, fastResult, slowResult);
-
-            return m_out.phi(Int64, fastResult, slowResult);
</del><ins>+                setDouble(m_out.phi(Double, fastResult, slowResult));
+            else
+                setJSValue(m_out.phi(Int64, fastResult, slowResult));
+            return;
</ins><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         case Array::Undecided: {
</span><span class="lines">@@ -5139,7 +5151,8 @@
</span><span class="cx">             LValue index = lowInt32(m_graph.varArgChild(m_node, 1));
</span><span class="cx"> 
</span><span class="cx">             speculate(OutOfBounds, noValue(), m_node, m_out.lessThan(index, m_out.int32Zero));
</span><del>-            return m_out.constInt64(JSValue::ValueUndefined);
</del><ins>+            setJSValue(m_out.constInt64(JSValue::ValueUndefined));
+            return;
</ins><span class="cx">         }
</span><span class="cx">             
</span><span class="cx">         case Array::DirectArguments: {
</span><span class="lines">@@ -5156,7 +5169,8 @@
</span><span class="cx">                 speculate(OutOfBounds, noValue(), nullptr, isOutOfBounds);
</span><span class="cx">                 TypedPointer address = m_out.baseIndex(
</span><span class="cx">                     m_heaps.DirectArguments_storage, base, m_out.zeroExtPtr(index));
</span><del>-                return m_out.load64(address);
</del><ins>+                setJSValue(m_out.load64(address));
+                return;
</ins><span class="cx">             }
</span><span class="cx"> 
</span><span class="cx">             LBasicBlock inBounds = m_out.newBlock();
</span><span class="lines">@@ -5178,7 +5192,8 @@
</span><span class="cx">             m_out.jump(continuation);
</span><span class="cx"> 
</span><span class="cx">             m_out.appendTo(continuation, lastNext);
</span><del>-            return m_out.phi(Int64, fastResult, slowResult);
</del><ins>+            setJSValue(m_out.phi(Int64, fastResult, slowResult));
+            return;
</ins><span class="cx">         }
</span><span class="cx">             
</span><span class="cx">         case Array::ScopedArguments: {
</span><span class="lines">@@ -5231,7 +5246,8 @@
</span><span class="cx">             m_out.jump(continuation);
</span><span class="cx">             
</span><span class="cx">             m_out.appendTo(continuation, lastNext);
</span><del>-            return m_out.phi(Int64, namedResult, overflowResult);
</del><ins>+            setJSValue(m_out.phi(Int64, namedResult, overflowResult));
+            return;
</ins><span class="cx">         }
</span><span class="cx">             
</span><span class="cx">         case Array::BigInt64Array:
</span><span class="lines">@@ -5240,21 +5256,24 @@
</span><span class="cx">             if (m_graph.m_slowGetByVal.contains(m_node)) {
</span><span class="cx">                 if (m_graph.varArgChild(m_node, 0).useKind() == ObjectUse) {
</span><span class="cx">                     if (m_graph.varArgChild(m_node, 1).useKind() == StringUse) {
</span><del>-                        return vmCall(
</del><ins>+                        setJSValue(vmCall(
</ins><span class="cx">                             Int64, operationGetByValObjectString, weakPointer(globalObject),
</span><del>-                            lowObject(m_graph.varArgChild(m_node, 0)), lowString(m_graph.varArgChild(m_node, 1)));
</del><ins>+                            lowObject(m_graph.varArgChild(m_node, 0)), lowString(m_graph.varArgChild(m_node, 1))));
+                        return;
</ins><span class="cx">                     }
</span><span class="cx"> 
</span><span class="cx">                     if (m_graph.varArgChild(m_node, 1).useKind() == SymbolUse) {
</span><del>-                        return vmCall(
</del><ins>+                        setJSValue(vmCall(
</ins><span class="cx">                             Int64, operationGetByValObjectSymbol, weakPointer(globalObject),
</span><del>-                            lowObject(m_graph.varArgChild(m_node, 0)), lowSymbol(m_graph.varArgChild(m_node, 1)));
</del><ins>+                            lowObject(m_graph.varArgChild(m_node, 0)), lowSymbol(m_graph.varArgChild(m_node, 1))));
+                        return;
</ins><span class="cx">                     }
</span><span class="cx">                 }
</span><span class="cx"> 
</span><del>-                return vmCall(
</del><ins>+                setJSValue(vmCall(
</ins><span class="cx">                     Int64, operationGetByVal, weakPointer(globalObject),
</span><del>-                    lowJSValue(m_graph.varArgChild(m_node, 0)), lowJSValue(m_graph.varArgChild(m_node, 1)));
</del><ins>+                    lowJSValue(m_graph.varArgChild(m_node, 0)), lowJSValue(m_graph.varArgChild(m_node, 1))));
+                return;
</ins><span class="cx">             }
</span><span class="cx"> 
</span><span class="cx">             Node* node = m_node;
</span><span class="lines">@@ -5354,7 +5373,8 @@
</span><span class="cx">                 });
</span><span class="cx">             });
</span><span class="cx"> 
</span><del>-            return patchpoint;
</del><ins>+            setJSValue(patchpoint);
+            return;
</ins><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         case Array::ArrayStorage:
</span><span class="lines">@@ -5370,7 +5390,8 @@
</span><span class="cx">                 speculate(LoadFromHole, noValue(), nullptr, m_out.isZero64(result));
</span><span class="cx">                 // We have to keep base alive to keep content in storage alive.
</span><span class="cx">                 ensureStillAliveHere(base);
</span><del>-                return result;
</del><ins>+                setJSValue(result);
+                return;
</ins><span class="cx">             }
</span><span class="cx"> 
</span><span class="cx">             LBasicBlock inBounds = m_out.newBlock();
</span><span class="lines">@@ -5396,11 +5417,13 @@
</span><span class="cx">             m_out.appendTo(continuation, lastNext);
</span><span class="cx">             // We have to keep base alive to keep content in storage alive.
</span><span class="cx">             ensureStillAliveHere(base);
</span><del>-            return m_out.phi(Int64, fastResult, slowResult);
</del><ins>+            setJSValue(m_out.phi(Int64, fastResult, slowResult));
+            return;
</ins><span class="cx">         }
</span><span class="cx">             
</span><span class="cx">         case Array::String: {
</span><del>-            return compileStringCharAtImpl();
</del><ins>+            compileStringCharAt();
+            return;
</ins><span class="cx">         }
</span><span class="cx">             
</span><span class="cx">         case Array::Int8Array:
</span><span class="lines">@@ -5425,7 +5448,9 @@
</span><span class="cx">                     LValue result = loadFromIntTypedArray(pointer, type);
</span><span class="cx">                     // We have to keep base alive since that keeps storage alive.
</span><span class="cx">                     ensureStillAliveHere(base);
</span><del>-                    return result;
</del><ins>+                    constexpr bool canSpeculate = true;
+                    setIntTypedArrayLoadResult(result, type, canSpeculate);
+                    return;
</ins><span class="cx">                 }
</span><span class="cx">             
</span><span class="cx">                 ASSERT(isFloat(type));
</span><span class="lines">@@ -5444,7 +5469,8 @@
</span><span class="cx">                 
</span><span class="cx">                 // We have to keep base alive since that keeps storage alive.
</span><span class="cx">                 ensureStillAliveHere(base);
</span><del>-                return result;
</del><ins>+                setDouble(result);
+                return;
</ins><span class="cx">             }
</span><span class="cx">         }
</span><span class="cx"> 
</span><span class="lines">@@ -5454,25 +5480,8 @@
</span><span class="cx">         case Array::SelectUsingPredictions:
</span><span class="cx">         case Array::Unprofiled:
</span><span class="cx">             DFG_CRASH(m_graph, m_node, "Bad array type");
</span><del>-            return nullptr;
-        }
-        RELEASE_ASSERT_NOT_REACHED();
-    }
-
-    void compileGetByVal()
-    {
-        LValue result = compileGetByValImpl();
-        TypedArrayType type = m_node->arrayMode().typedArrayType();
-        if (isInt(type)) {
-            constexpr bool canSpeculate = true;
-            setIntTypedArrayLoadResult(result, type, canSpeculate);
</del><span class="cx">             return;
</span><span class="cx">         }
</span><del>-
-        if (result->type() == Double)
-            setDouble(result);
-        else
-            setJSValue(result);
</del><span class="cx">     }
</span><span class="cx">     
</span><span class="cx">     void compileGetMyArgumentByVal()
</span><span class="lines">@@ -8562,7 +8571,7 @@
</span><span class="cx">         setJSValue(m_out.phi(Int64, fastResult, emptyResult, slowResult));
</span><span class="cx">     }
</span><span class="cx">     
</span><del>-    LValue compileStringCharAtImpl()
</del><ins>+    void compileStringCharAt()
</ins><span class="cx">     {
</span><span class="cx">         LValue base = lowString(m_graph.child(m_node, 0));
</span><span class="cx">         LValue index = lowInt32(m_graph.child(m_node, 1));
</span><span class="lines">@@ -8670,13 +8679,8 @@
</span><span class="cx">         m_out.appendTo(continuation, lastNext);
</span><span class="cx">         // We have to keep base alive since that keeps storage alive.
</span><span class="cx">         ensureStillAliveHere(base);
</span><del>-        return m_out.phi(Int64, results);
</del><ins>+        setJSValue(m_out.phi(Int64, results));
</ins><span class="cx">     }
</span><del>-
-    void compileStringCharAt()
-    {
-        setJSValue(compileStringCharAtImpl());
-    }
</del><span class="cx">     
</span><span class="cx">     void compileStringCharCodeAt()
</span><span class="cx">     {
</span><span class="lines">@@ -12902,16 +12906,17 @@
</span><span class="cx">         emitStoreBarrier(lowCell(m_node->child1()), m_node->op() == FencedStoreBarrier);
</span><span class="cx">     }
</span><span class="cx">     
</span><del>-    LValue compileHasIndexedPropertyImpl(LValue index, S_JITOperation_GCZ slowPathOperation)
</del><ins>+    void compileHasIndexedProperty(S_JITOperation_GCZ slowPathOperation)
</ins><span class="cx">     {
</span><span class="cx">         JSGlobalObject* globalObject = m_graph.globalObjectFor(m_origin.semantic);
</span><span class="cx">         LValue base = lowCell(m_graph.varArgChild(m_node, 0));
</span><ins>+        LValue index = lowInt32(m_graph.varArgChild(m_node, 1));
</ins><span class="cx">         ArrayMode mode = m_node->arrayMode();
</span><span class="cx"> 
</span><span class="cx">         switch (m_node->arrayMode().type()) {
</span><span class="cx">         case Array::Int32:
</span><span class="cx">         case Array::Contiguous: {
</span><del>-            LValue storage = lowStorage(m_graph.varArgChild(m_node, m_node->storageChildIndex()));
</del><ins>+            LValue storage = lowStorage(m_graph.varArgChild(m_node, 2));
</ins><span class="cx"> 
</span><span class="cx">             IndexedAbstractHeap& heap = mode.type() == Array::Int32 ?
</span><span class="cx">                 m_heaps.indexedInt32Properties : m_heaps.indexedContiguousProperties;
</span><span class="lines">@@ -12946,10 +12951,11 @@
</span><span class="cx">             m_out.jump(continuation);
</span><span class="cx"> 
</span><span class="cx">             m_out.appendTo(continuation, lastNext);
</span><del>-            return m_out.phi(Int32, checkHoleResult, slowResult);
</del><ins>+            setBoolean(m_out.phi(Int32, checkHoleResult, slowResult));
+            return;
</ins><span class="cx">         }
</span><span class="cx">         case Array::Double: {
</span><del>-            LValue storage = lowStorage(m_graph.varArgChild(m_node, m_node->storageChildIndex()));
</del><ins>+            LValue storage = lowStorage(m_graph.varArgChild(m_node, 2));
</ins><span class="cx">             
</span><span class="cx">             IndexedAbstractHeap& heap = m_heaps.indexedDoubleProperties;
</span><span class="cx">             
</span><span class="lines">@@ -12983,11 +12989,12 @@
</span><span class="cx">             m_out.jump(continuation);
</span><span class="cx">             
</span><span class="cx">             m_out.appendTo(continuation, lastNext);
</span><del>-            return m_out.phi(Int32, checkHoleResult, slowResult);
</del><ins>+            setBoolean(m_out.phi(Int32, checkHoleResult, slowResult));
+            return;
</ins><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         case Array::ArrayStorage: {
</span><del>-            LValue storage = lowStorage(m_graph.varArgChild(m_node, m_node->storageChildIndex()));
</del><ins>+            LValue storage = lowStorage(m_graph.varArgChild(m_node, 2));
</ins><span class="cx"> 
</span><span class="cx">             LBasicBlock slowCase = m_out.newBlock();
</span><span class="cx">             LBasicBlock continuation = m_out.newBlock();
</span><span class="lines">@@ -13019,325 +13026,197 @@
</span><span class="cx">             m_out.jump(continuation);
</span><span class="cx"> 
</span><span class="cx">             m_out.appendTo(continuation, lastNext);
</span><del>-            return m_out.phi(Int32, checkHoleResult, slowResult);
</del><ins>+            setBoolean(m_out.phi(Int32, checkHoleResult, slowResult));
+            break;
</ins><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         default: {
</span><del>-            return m_out.notZero64(vmCall(Int64, slowPathOperation, weakPointer(globalObject), base, index));
</del><ins>+            setBoolean(m_out.notZero64(vmCall(Int64, slowPathOperation, weakPointer(globalObject), base, index)));
+            break;
</ins><span class="cx">         }
</span><span class="cx">         }
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    void compileHasIndexedProperty()
</del><ins>+    void compileHasEnumerableProperty()
</ins><span class="cx">     {
</span><del>-        LValue index = lowInt32(m_graph.varArgChild(m_node, 1));
-        setBoolean(compileHasIndexedPropertyImpl(index, operationHasIndexedProperty));
-    }
-
-    void compileGetPropertyEnumerator()
-    {
</del><span class="cx">         JSGlobalObject* globalObject = m_graph.globalObjectFor(m_origin.semantic);
</span><del>-        if (m_node->child1().useKind() == CellUse)
-            setJSValue(vmCall(Int64, operationGetPropertyEnumeratorCell, weakPointer(globalObject), lowCell(m_node->child1())));
-        else
-            setJSValue(vmCall(Int64, operationGetPropertyEnumerator, weakPointer(globalObject), lowJSValue(m_node->child1())));
</del><ins>+        LValue base = lowJSValue(m_node->child1());
+        LValue property = lowCell(m_node->child2());
+        setJSValue(vmCall(Int64, operationHasEnumerableProperty, weakPointer(globalObject), base, property));
</ins><span class="cx">     }
</span><span class="cx"> 
</span><del>-    void compileEnumeratorNextUpdateIndexAndMode()
</del><ins>+    template <typename SlowPathCall>
+    void compileHasStructurePropertyImpl(LValue base, SlowPathCall slowPathCall)
</ins><span class="cx">     {
</span><span class="cx">         JSGlobalObject* globalObject = m_graph.globalObjectFor(m_origin.semantic);
</span><del>-        LValue index = lowInt32(m_graph.varArgChild(m_node, 1));
-        LValue mode = lowInt32(m_graph.varArgChild(m_node, 2));
-        LValue enumerator = lowCell(m_graph.varArgChild(m_node, 3));
</del><ins>+        LValue property = lowString(m_node->child2());
+        LValue enumerator = lowCell(m_node->child3());
</ins><span class="cx"> 
</span><del>-        if (m_node->enumeratorMetadata() == JSPropertyNameEnumerator::IndexedMode) {
-            speculate(BadCache, noValue(), m_node, m_out.notZero32(m_out.load32(enumerator, m_heaps.JSPropertyNameEnumerator_endGenericPropertyIndex)));
</del><ins>+        LBasicBlock isCellCase = m_out.newBlock();
+        LBasicBlock correctStructure = m_out.newBlock();
+        LBasicBlock slowPath = m_out.newBlock();
+        LBasicBlock continuation = m_out.newBlock();
</ins><span class="cx"> 
</span><del>-            LBasicBlock increment = m_out.newBlock();
-            LBasicBlock checkHasProperty = m_out.newBlock();
-            LBasicBlock continuation = m_out.newBlock();
</del><ins>+        m_out.branch(isCell(base, provenType(m_node->child1())),
+            usually(isCellCase), rarely(slowPath));
</ins><span class="cx"> 
</span><del>-            ValueFromBlock initialIndex = m_out.anchor(index);
-            ValueFromBlock initialIndexForHasProperty = m_out.anchor(index);
-            m_out.branch(m_out.isZero32(mode), unsure(checkHasProperty), unsure(increment));
</del><ins>+        LBasicBlock lastNext = m_out.appendTo(isCellCase, correctStructure);
</ins><span class="cx"> 
</span><del>-            m_out.appendTo(increment);
-            LValue indexPhi = m_out.phi(Int32, initialIndex);
-            LValue incrementedIndex = m_out.add(indexPhi, m_out.int32One);
-            ValueFromBlock incrementedIndexResult = m_out.anchor(incrementedIndex);
-            ValueFromBlock finalIncrementedIndex = m_out.anchor(incrementedIndex);
-            m_out.branch(m_out.lessThan(incrementedIndex, m_out.load32(enumerator, m_heaps.JSPropertyNameEnumerator_indexLength)), unsure(checkHasProperty), unsure(continuation));
</del><ins>+        m_out.branch(m_out.notEqual(
+            m_out.load32(base, m_heaps.JSCell_structureID),
+            m_out.load32(enumerator, m_heaps.JSPropertyNameEnumerator_cachedStructureID)),
+            rarely(slowPath), usually(correctStructure));
</ins><span class="cx"> 
</span><del>-            m_out.appendTo(checkHasProperty);
-            LValue propertyIndex = m_out.phi(Int32, initialIndexForHasProperty, incrementedIndexResult);
-            m_out.addIncomingToPhi(indexPhi, m_out.anchor(propertyIndex));
-            ValueFromBlock finalPropertyIndex = m_out.anchor(propertyIndex);
-            LValue hasProperty = compileHasIndexedPropertyImpl(propertyIndex, operationHasEnumerableIndexedProperty);
-            m_out.branch(hasProperty, unsure(continuation), unsure(increment));
</del><ins>+        m_out.appendTo(correctStructure, slowPath);
+        ValueFromBlock correctStructureResult = m_out.anchor(m_out.booleanTrue);
+        m_out.jump(continuation);
</ins><span class="cx"> 
</span><del>-            m_out.appendTo(continuation);
-            LValue finalIndex = m_out.phi(Int32, finalIncrementedIndex, finalPropertyIndex);
-            setJSValue(m_out.bitOr(m_out.zeroExt(finalIndex, Int64), m_out.constInt64(JSValue::NumberTag | static_cast<uint64_t>(JSPropertyNameEnumerator::IndexedMode) << 32)));
-            return;
-        }
</del><ins>+        m_out.appendTo(slowPath, continuation);
+        ValueFromBlock slowPathResult = m_out.anchor(
+            m_out.equal(
+                m_out.constInt64(JSValue::encode(jsBoolean(true))), 
+                vmCall(Int64, slowPathCall, weakPointer(globalObject), base, property)));
+        m_out.jump(continuation);
</ins><span class="cx"> 
</span><del>-        Edge& baseEdge = m_graph.varArgChild(m_node, 0);
-        if (m_node->enumeratorMetadata() == JSPropertyNameEnumerator::OwnStructureMode && baseEdge.useKind() == CellUse) {
-            LValue base = lowCell(baseEdge);
-            speculate(BadCache, noValue(), m_node, m_out.notEqual(m_out.load32(base, m_heaps.JSCell_structureID), m_out.load32(enumerator, m_heaps.JSPropertyNameEnumerator_cachedStructureID)));
</del><ins>+        m_out.appendTo(continuation, lastNext);
+        setBoolean(m_out.phi(Int32, correctStructureResult, slowPathResult));
+    }
</ins><span class="cx"> 
</span><del>-            speculate(BadCache, noValue(), m_node, m_out.notEqual(m_out.load32(enumerator, m_heaps.JSPropertyNameEnumerator_modeSet), m_out.constInt32(JSPropertyNameEnumerator::OwnStructureMode)));
-
-            LBasicBlock increment = m_out.newBlock();
-            LBasicBlock continuation = m_out.newBlock();
-
-            ValueFromBlock initialIndex = m_out.anchor(index);
-            m_out.branch(m_out.isZero32(mode), unsure(continuation), unsure(increment));
-
-            m_out.appendTo(increment);
-            ValueFromBlock incrementedIndex = m_out.anchor(m_out.add(index, m_out.int32One));
-            m_out.jump(continuation);
-
-            m_out.appendTo(continuation);
-            index = m_out.phi(Int32, initialIndex, incrementedIndex);
-            setJSValue(m_out.bitOr(m_out.zeroExt(index, Int64), m_out.constInt64(JSValue::DoubleEncodeOffset | static_cast<uint64_t>(JSPropertyNameEnumerator::OwnStructureMode) << 32)));
-            return;
-        }
-
-        LValue base = lowJSValue(baseEdge);
-        setJSValue(vmCall(Int64, operationEnumeratorNextUpdateIndexAndMode, weakPointer(globalObject), base, index, mode, enumerator));
</del><ins>+    void compileHasEnumerableStructureProperty()
+    {
+        compileHasStructurePropertyImpl(lowJSValue(m_node->child1()), operationHasEnumerableProperty);
</ins><span class="cx">     }
</span><span class="cx"> 
</span><del>-    void compileEnumeratorNextExtractIndex()
</del><ins>+    void compileHasOwnStructureProperty()
</ins><span class="cx">     {
</span><del>-        LValue boxedPair = lowJSValue(m_node->child1());
-
-        setInt32(m_out.castToInt32(boxedPair));
</del><ins>+        compileHasStructurePropertyImpl(lowCell(m_node->child1()), operationHasOwnStructureProperty);
</ins><span class="cx">     }
</span><span class="cx"> 
</span><del>-    void compileEnumeratorNextExtractMode()
</del><ins>+    void compileInStructureProperty()
</ins><span class="cx">     {
</span><del>-        LValue boxedPair = lowJSValue(m_node->child1());
-
-        LValue highBits = m_out.castToInt32(m_out.lShr(boxedPair, m_out.constInt32(32)));
-        setInt32(m_out.bitAnd(highBits, m_out.constInt32(JSPropertyNameEnumerator::enumerationModeMask)));
</del><ins>+        compileHasStructurePropertyImpl(lowCell(m_node->child1()), operationInStructureProperty);
</ins><span class="cx">     }
</span><span class="cx"> 
</span><del>-    // FIXME: We should probably have a method of value recovery for this node since it's "effect" free but always live in bytecode.
-    void compileEnumeratorNextUpdatePropertyName()
</del><ins>+    void compileGetDirectPname()
</ins><span class="cx">     {
</span><span class="cx">         JSGlobalObject* globalObject = m_graph.globalObjectFor(m_origin.semantic);
</span><del>-        LValue index = lowInt32(m_node->child1());
-        LValue mode = lowInt32(m_node->child2());
-        LValue enumerator = lowCell(m_node->child3());
</del><ins>+        LValue base = lowCell(m_graph.varArgChild(m_node, 0));
+        LValue property = lowCell(m_graph.varArgChild(m_node, 1));
+        LValue index = lowInt32(m_graph.varArgChild(m_node, 2));
+        LValue enumerator = lowCell(m_graph.varArgChild(m_node, 3));
</ins><span class="cx"> 
</span><del>-        LBasicBlock operationBlock = nullptr;
-        LBasicBlock continuation = nullptr;
</del><ins>+        LBasicBlock checkOffset = m_out.newBlock();
+        LBasicBlock inlineLoad = m_out.newBlock();
+        LBasicBlock outOfLineLoad = m_out.newBlock();
+        LBasicBlock slowCase = m_out.newBlock();
+        LBasicBlock continuation = m_out.newBlock();
</ins><span class="cx"> 
</span><del>-        Vector<ValueFromBlock, 3> results;
-        OptionSet seenModes = m_node->enumeratorMetadata();
</del><ins>+        m_out.branch(m_out.notEqual(
+            m_out.load32(base, m_heaps.JSCell_structureID),
+            m_out.load32(enumerator, m_heaps.JSPropertyNameEnumerator_cachedStructureID)),
+            rarely(slowCase), usually(checkOffset));
</ins><span class="cx"> 
</span><del>-        if (seenModes.containsAny({ JSPropertyNameEnumerator::OwnStructureMode, JSPropertyNameEnumerator::GenericMode })) {
-            LBasicBlock checkIndex = nullptr;
-            LBasicBlock outOfBoundsBlock = m_out.newBlock();
-            LBasicBlock loadPropertyNameBlock = m_out.newBlock();
-            continuation = m_out.newBlock();
</del><ins>+        LBasicBlock lastNext = m_out.appendTo(checkOffset, inlineLoad);
+        m_out.branch(m_out.aboveOrEqual(index, m_out.load32(enumerator, m_heaps.JSPropertyNameEnumerator_cachedInlineCapacity)),
+            unsure(outOfLineLoad), unsure(inlineLoad));
</ins><span class="cx"> 
</span><del>-            if (seenModes.contains(JSPropertyNameEnumerator::IndexedMode)) {
-                checkIndex = m_out.newBlock();
-                operationBlock = m_out.newBlock();
-                m_out.branch(m_out.testIsZero32(mode, m_out.constInt32(JSPropertyNameEnumerator::IndexedMode)), unsure(checkIndex), unsure(operationBlock));
-            }
</del><ins>+        m_out.appendTo(inlineLoad, outOfLineLoad);
+        ValueFromBlock inlineResult = m_out.anchor(
+            m_out.load64(m_out.baseIndex(m_heaps.properties.atAnyNumber(), 
+                base, m_out.zeroExt(index, Int64), ScaleEight, JSObject::offsetOfInlineStorage())));
+        m_out.jump(continuation);
</ins><span class="cx"> 
</span><del>-            {
-                if (checkIndex)
-                    m_out.appendTo(checkIndex);
-                LValue outOfBounds = m_out.aboveOrEqual(index, m_out.load32(enumerator, m_heaps.JSPropertyNameEnumerator_endGenericPropertyIndex));
-                m_out.branch(outOfBounds, unsure(outOfBoundsBlock), unsure(loadPropertyNameBlock));
-            }
</del><ins>+        m_out.appendTo(outOfLineLoad, slowCase);
+        LValue storage = m_out.loadPtr(base, m_heaps.JSObject_butterfly);
+        LValue realIndex = m_out.signExt32To64(
+            m_out.neg(m_out.sub(index, m_out.load32(enumerator, m_heaps.JSPropertyNameEnumerator_cachedInlineCapacity))));
+        int32_t offsetOfFirstProperty = static_cast<int32_t>(offsetInButterfly(firstOutOfLineOffset)) * sizeof(EncodedJSValue);
+        ValueFromBlock outOfLineResult = m_out.anchor(
+            m_out.load64(m_out.baseIndex(m_heaps.properties.atAnyNumber(), storage, realIndex, ScaleEight, offsetOfFirstProperty)));
+        m_out.jump(continuation);
</ins><span class="cx"> 
</span><del>-            {
-                m_out.appendTo(outOfBoundsBlock);
-                results.append(m_out.anchor(m_out.constInt64(JSValue::encode(jsNull()))));
-                m_out.jump(continuation);
-            }
</del><ins>+        m_out.appendTo(slowCase, continuation);
+        ValueFromBlock slowCaseResult = m_out.anchor(
+            vmCall(Int64, operationGetByVal, weakPointer(globalObject), base, property));
+        m_out.jump(continuation);
</ins><span class="cx"> 
</span><del>-            {
-                m_out.appendTo(loadPropertyNameBlock);
-                LValue namesVector = m_out.loadPtr(enumerator, m_heaps.JSPropertyNameEnumerator_cachedPropertyNamesVector);
-                results.append(m_out.anchor(m_out.zeroExtPtr(m_out.loadPtr(m_out.baseIndex(m_heaps.WriteBarrierBuffer_bufferContents.atAnyIndex(), namesVector, m_out.zeroExt(index, Int64), ScalePtr)))));
-                m_out.jump(continuation);
-            }
-        }
</del><ins>+        m_out.appendTo(continuation, lastNext);
+        setJSValue(m_out.phi(Int64, inlineResult, outOfLineResult, slowCaseResult));
+    }
</ins><span class="cx"> 
</span><del>-        if (seenModes.contains(JSPropertyNameEnumerator::IndexedMode)) {
-            if (operationBlock)
-                m_out.appendTo(operationBlock);
-            results.append(m_out.anchor(vmCall(Int64, operationEnumeratorNextUpdatePropertyName, weakPointer(globalObject), index, mode, enumerator)));
-            if (continuation)
-                m_out.jump(continuation);
-        }
</del><ins>+    void compileGetEnumerableLength()
+    {
+        LValue enumerator = lowCell(m_node->child1());
+        setInt32(m_out.load32(enumerator, m_heaps.JSPropertyNameEnumerator_indexLength));
+    }
</ins><span class="cx"> 
</span><del>-        if (continuation)
-            m_out.appendTo(continuation);
-
-        ASSERT(results.size());
-        LValue result = m_out.phi(Int64, results);
-        setJSValue(result);
</del><ins>+    void compileGetPropertyEnumerator()
+    {
+        JSGlobalObject* globalObject = m_graph.globalObjectFor(m_origin.semantic);
+        if (m_node->child1().useKind() == CellUse)
+            setJSValue(vmCall(Int64, operationGetPropertyEnumeratorCell, weakPointer(globalObject), lowCell(m_node->child1())));
+        else
+            setJSValue(vmCall(Int64, operationGetPropertyEnumerator, weakPointer(globalObject), lowJSValue(m_node->child1())));
</ins><span class="cx">     }
</span><span class="cx"> 
</span><del>-    void compileEnumeratorGetByVal()
</del><ins>+    void compileGetEnumeratorStructurePname()
</ins><span class="cx">     {
</span><del>-        Edge baseEdge = m_graph.varArgChild(m_node, 0);
-        Edge propertyNameEdge = m_graph.varArgChild(m_node, 1);
-        Edge storageEdge = m_graph.varArgChild(m_node, 2);
-        Edge indexEdge = m_graph.varArgChild(m_node, 3);
</del><ins>+        LValue enumerator = lowCell(m_node->child1());
+        LValue index = lowInt32(m_node->child2());
</ins><span class="cx"> 
</span><del>-        LValue base = DFG::isCell(baseEdge.useKind()) ? lowCell(baseEdge, ManualOperandSpeculation) : lowJSValue(baseEdge);
-
-        LValue storage = storageEdge ? lowStorage(storageEdge) : nullptr;
-        // We have to materialize the propertyName here in case it requires boxing since the IC path won't dominate subsequent uses in subsequent nodes.
-        // If it's an Int32 and we use it as such this boxing will be DCE'd by b3 later anyway.
-        lowJSValue(propertyNameEdge, ManualOperandSpeculation);
-
-
-        LValue index = lowInt32(indexEdge);
-        LValue mode = lowInt32(m_graph.varArgChild(m_node, 4));
-        LValue enumerator = lowCell(m_graph.varArgChild(m_node, 5));
-
-        LBasicBlock checkIsCellBlock = m_out.newBlock();
-        LBasicBlock checkStructureBlock = m_out.newBlock();
-        LBasicBlock checkInlineOrOutOfLineBlock = m_out.newBlock();
-        LBasicBlock inlineLoadBlock = m_out.newBlock();
-        LBasicBlock outOfLineLoadBlock = m_out.newBlock();
-        LBasicBlock genericICBlock = m_out.newBlock();
</del><ins>+        LBasicBlock inBounds = m_out.newBlock();
+        LBasicBlock outOfBounds = m_out.newBlock();
</ins><span class="cx">         LBasicBlock continuation = m_out.newBlock();
</span><span class="cx"> 
</span><del>-        Vector<ValueFromBlock, 4> results;
</del><ins>+        m_out.branch(m_out.below(index, m_out.load32(enumerator, m_heaps.JSPropertyNameEnumerator_endStructurePropertyIndex)),
+            usually(inBounds), rarely(outOfBounds));
</ins><span class="cx"> 
</span><del>-        LValue isNotNamed = m_out.testNonZero32(mode, m_out.constInt32(JSPropertyNameEnumerator::IndexedMode | JSPropertyNameEnumerator::GenericMode));
-        m_out.branch(isNotNamed, unsure(genericICBlock), unsure(checkIsCellBlock));
-
-        m_out.appendTo(checkIsCellBlock);
-        m_out.branch(isCell(base, provenType(baseEdge)), usually(checkStructureBlock), rarely(genericICBlock));
-
-        m_out.appendTo(checkStructureBlock);
-        LValue structureID;
-        auto structure = m_state.forNode(baseEdge.node()).m_structure.onlyStructure();
-        if (structure)
-            structureID = m_out.constInt32(structure->id());
-        else
-            structureID = m_out.load32(base, m_heaps.JSCell_structureID);
-
-        LValue hasEnumeratorStructure = m_out.equal(structureID, m_out.load32(enumerator, m_heaps.JSPropertyNameEnumerator_cachedStructureID));
-
-        if (indexEdge.node() == propertyNameEdge.node()) {
-            JSGlobalObject* globalObject = m_graph.globalObjectFor(m_origin.semantic);
-            LBasicBlock badStructureSlowPath = m_out.newBlock();
-            m_out.branch(hasEnumeratorStructure, usually(checkInlineOrOutOfLineBlock), rarely(genericICBlock));
-
-            m_out.appendTo(badStructureSlowPath);
-            results.append(m_out.anchor(vmCall(Int64, operationEnumeratorRecoverNameAndGetByVal, weakPointer(globalObject), base, index, enumerator)));
-        } else
-            m_out.branch(hasEnumeratorStructure, usually(checkInlineOrOutOfLineBlock), rarely(genericICBlock));
-
-        m_out.appendTo(checkInlineOrOutOfLineBlock);
-        LValue inlineCapacity = nullptr;
-        bool hasNoOutOfLineProperties = false;
-        if (structure) {
-            hasNoOutOfLineProperties = !structure->outOfLineCapacity();
-            inlineCapacity = m_out.constInt32(structure->inlineCapacity());
-        }
-        if (!inlineCapacity)
-            inlineCapacity = m_out.load32(enumerator, m_heaps.JSPropertyNameEnumerator_cachedInlineCapacity);
-        LValue isInline = hasNoOutOfLineProperties ? m_out.int32One : m_out.below(index, inlineCapacity);
-        m_out.branch(isInline, unsure(inlineLoadBlock), unsure(outOfLineLoadBlock));
-
-        m_out.appendTo(inlineLoadBlock);
-        results.append(m_out.anchor(
-            m_out.load64(m_out.baseIndex(m_heaps.properties.atAnyNumber(),
-                base, m_out.zeroExt(index, Int64), ScaleEight, JSObject::offsetOfInlineStorage()))));
</del><ins>+        LBasicBlock lastNext = m_out.appendTo(inBounds, outOfBounds);
+        LValue storage = m_out.loadPtr(enumerator, m_heaps.JSPropertyNameEnumerator_cachedPropertyNamesVector);
+        ValueFromBlock inBoundsResult = m_out.anchor(
+            m_out.loadPtr(m_out.baseIndex(m_heaps.JSPropertyNameEnumerator_cachedPropertyNamesVectorContents, storage, m_out.zeroExtPtr(index))));
</ins><span class="cx">         m_out.jump(continuation);
</span><span class="cx"> 
</span><del>-        m_out.appendTo(outOfLineLoadBlock);
-        if (!storage)
-            storage = m_out.loadPtr(base, m_heaps.JSObject_butterfly);
-
-        LValue realIndex = m_out.signExt32To64(
-            m_out.neg(m_out.sub(index, inlineCapacity)));
-        int32_t offsetOfFirstProperty = static_cast<int32_t>(offsetInButterfly(firstOutOfLineOffset)) * sizeof(EncodedJSValue);
-        results.append(m_out.anchor(
-            m_out.load64(m_out.baseIndex(m_heaps.properties.atAnyNumber(), storage, realIndex, ScaleEight, offsetOfFirstProperty))));
</del><ins>+        m_out.appendTo(outOfBounds, continuation);
+        ValueFromBlock outOfBoundsResult = m_out.anchor(m_out.constInt64(JSValue::ValueNull));
</ins><span class="cx">         m_out.jump(continuation);
</span><del>-
-        m_out.appendTo(genericICBlock);
-        LValue genericResult = compileGetByValImpl();
-        TypedArrayType type = m_node->arrayMode().typedArrayType();
-        if (isInt(type)) {
-            if (elementSize(type) < 4 || isSigned(type))
-                genericResult = boxInt32(genericResult);
-            else
-                genericResult = strictInt52ToJSValue(genericResult);
-        } else if (genericResult->type() == Double)
-            genericResult = boxDouble(genericResult);
-
-        results.append(m_out.anchor(genericResult));
-        m_out.jump(continuation);
-
-        m_out.appendTo(continuation);
-        ASSERT(results.size());
-        LValue result = m_out.phi(Int64, results);
-        setJSValue(result);
</del><ins>+        
+        m_out.appendTo(continuation, lastNext);
+        setJSValue(m_out.phi(Int64, inBoundsResult, outOfBoundsResult));
</ins><span class="cx">     }
</span><span class="cx"> 
</span><del>-    template<typename SlowPathFunctionType>
-    void compileEnumeratorHasProperty(SlowPathFunctionType slowPathFunction)
</del><ins>+    void compileGetEnumeratorGenericPname()
</ins><span class="cx">     {
</span><del>-        JSGlobalObject* globalObject = m_graph.globalObjectFor(m_origin.semantic);
-        Edge baseEdge = m_graph.varArgChild(m_node, 0);
-        LValue base = baseEdge.useKind() == CellUse ? lowCell(baseEdge) : lowJSValue(baseEdge);
-        LValue propertyName = lowJSValue(m_graph.varArgChild(m_node, 1));
-        LValue index = lowInt32(m_graph.varArgChild(m_node, 2));
-        LValue mode = lowInt32(m_graph.varArgChild(m_node, 3));
-        LValue enumerator = lowCell(m_graph.varArgChild(m_node, 4));
</del><ins>+        LValue enumerator = lowCell(m_node->child1());
+        LValue index = lowInt32(m_node->child2());
</ins><span class="cx"> 
</span><del>-        LBasicBlock isNamedBlock = m_out.newBlock();
-        LBasicBlock isCellBlock = m_out.newBlock();
-        LBasicBlock matchesStructureBlock = m_out.newBlock();
-        LBasicBlock operationBlock = m_out.newBlock();
</del><ins>+        LBasicBlock inBounds = m_out.newBlock();
+        LBasicBlock outOfBounds = m_out.newBlock();
</ins><span class="cx">         LBasicBlock continuation = m_out.newBlock();
</span><span class="cx"> 
</span><del>-        m_out.branch(m_out.testNonZero32(mode, m_out.constInt32(JSPropertyNameEnumerator::OwnStructureMode)), unsure(isNamedBlock), unsure(operationBlock));
-        m_out.appendTo(isNamedBlock);
</del><ins>+        m_out.branch(m_out.below(index, m_out.load32(enumerator, m_heaps.JSPropertyNameEnumerator_endGenericPropertyIndex)),
+            usually(inBounds), rarely(outOfBounds));
</ins><span class="cx"> 
</span><del>-        m_out.branch(isCell(base, provenType(baseEdge)), unsure(isCellBlock), unsure(operationBlock));
-
-        m_out.appendTo(isCellBlock);
-        LValue structureID = m_out.load32(base, m_heaps.JSCell_structureID);
-        m_out.branch(m_out.equal(structureID, m_out.load32(enumerator, m_heaps.JSPropertyNameEnumerator_cachedStructureID)),
-            usually(matchesStructureBlock), rarely(operationBlock));
-
-        m_out.appendTo(matchesStructureBlock);
-        ValueFromBlock namedResult = m_out.anchor(m_out.booleanTrue);
</del><ins>+        LBasicBlock lastNext = m_out.appendTo(inBounds, outOfBounds);
+        LValue storage = m_out.loadPtr(enumerator, m_heaps.JSPropertyNameEnumerator_cachedPropertyNamesVector);
+        ValueFromBlock inBoundsResult = m_out.anchor(
+            m_out.loadPtr(m_out.baseIndex(m_heaps.JSPropertyNameEnumerator_cachedPropertyNamesVectorContents, storage, m_out.zeroExtPtr(index))));
</ins><span class="cx">         m_out.jump(continuation);
</span><span class="cx"> 
</span><del>-        m_out.appendTo(operationBlock);
-        ValueFromBlock operationResult = m_out.anchor(unboxBoolean(vmCall(Int64, slowPathFunction, weakPointer(globalObject), base, propertyName, index, mode)));
</del><ins>+        m_out.appendTo(outOfBounds, continuation);
+        ValueFromBlock outOfBoundsResult = m_out.anchor(m_out.constInt64(JSValue::ValueNull));
</ins><span class="cx">         m_out.jump(continuation);
</span><del>-
-        m_out.appendTo(continuation);
-        setBoolean(m_out.phi(Int32, namedResult, operationResult));
</del><ins>+        
+        m_out.appendTo(continuation, lastNext);
+        setJSValue(m_out.phi(Int64, inBoundsResult, outOfBoundsResult));
</ins><span class="cx">     }
</span><del>-
-    void compileEnumeratorInByVal()
</del><ins>+    
+    void compileToIndexString()
</ins><span class="cx">     {
</span><del>-        compileEnumeratorHasProperty(operationEnumeratorInByVal);
</del><ins>+        JSGlobalObject* globalObject = m_graph.globalObjectFor(m_origin.semantic);
+        LValue index = lowInt32(m_node->child1());
+        setJSValue(vmCall(Int64, operationToIndexString, weakPointer(globalObject), index));
</ins><span class="cx">     }
</span><del>-
-    void compileEnumeratorHasOwnProperty()
-    {
-        compileEnumeratorHasProperty(operationEnumeratorHasOwnProperty);
-    }
</del><span class="cx">     
</span><span class="cx">     void compileCheckStructureImmediate()
</span><span class="cx">     {
</span><span class="lines">@@ -17465,7 +17344,7 @@
</span><span class="cx">             setInt32(result);
</span><span class="cx">             return;
</span><span class="cx">         }
</span><del>-
</del><ins>+        
</ins><span class="cx">         if (m_node->shouldSpeculateInt32() && canSpeculate) {
</span><span class="cx">             speculate(
</span><span class="cx">                 Overflow, noValue(), nullptr, m_out.lessThan(result, m_out.int32Zero));
</span><span class="lines">@@ -20417,27 +20296,6 @@
</span><span class="cx">         m_out.unreachable();
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    // This only works for ints right now.
-    PatchpointValue* dataLogForDebugging(const char* prefix, LValue value)
-    {
-        PatchpointValue* result = m_out.patchpoint(Void);
-        result->effects.writesLocalState = true;
-        result->append(value, ValueRep::reg(GPRInfo::regT0));
-        Type valueType = value->type();
-        result->setGenerator([=] (CCallHelpers& jit, const StackmapGenerationParams&) {
-            AllowMacroScratchRegisterUsage allowScratch(jit);
-
-            jit.probeDebug([=] (Probe::Context& context) {
-                if (valueType == Int32)
-                    dataLogLn(prefix, context.gpr<int32_t>(GPRInfo::regT0));
-                else
-                    dataLogLn(prefix, context.gpr<JSValue>(GPRInfo::regT0));
-            });
-        });
-
-        return result;
-    }
-
</del><span class="cx">     AvailabilityMap& availabilityMap() { return m_availabilityCalculator.m_availability; }
</span><span class="cx">     
</span><span class="cx">     VM& vm() { return m_graph.m_vm; }
</span></span></pre></div>
<a id="branchessafari612128branchSourceJavaScriptCoreftlFTLOutputh"></a>
<div class="modfile"><h4>Modified: branches/safari-612.1.28-branch/Source/JavaScriptCore/ftl/FTLOutput.h (281021 => 281022)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-612.1.28-branch/Source/JavaScriptCore/ftl/FTLOutput.h    2021-08-13 16:39:44 UTC (rev 281021)
+++ branches/safari-612.1.28-branch/Source/JavaScriptCore/ftl/FTLOutput.h       2021-08-13 16:50:38 UTC (rev 281022)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> /*
</span><del>- * Copyright (C) 2013-2021 Apple Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2013-2019 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">@@ -145,8 +145,6 @@
</span><span class="cx">     void addIncomingToPhi(LValue phi, ValueFromBlock);
</span><span class="cx">     template<typename... Params>
</span><span class="cx">     void addIncomingToPhi(LValue phi, ValueFromBlock, Params... theRest);
</span><del>-    template<typename... Params>
-    void addIncomingToPhiIfSet(LValue phi, Params... theRest);
</del><span class="cx">     
</span><span class="cx">     LValue opaque(LValue);
</span><span class="cx"> 
</span></span></pre></div>
<a id="branchessafari612128branchSourceJavaScriptCoregeneratorDSLrb"></a>
<div class="modfile"><h4>Modified: branches/safari-612.1.28-branch/Source/JavaScriptCore/generator/DSL.rb (281021 => 281022)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-612.1.28-branch/Source/JavaScriptCore/generator/DSL.rb   2021-08-13 16:39:44 UTC (rev 281021)
+++ branches/safari-612.1.28-branch/Source/JavaScriptCore/generator/DSL.rb      2021-08-13 16:50:38 UTC (rev 281022)
</span><span class="lines">@@ -138,7 +138,6 @@
</span><span class="cx"> #include "GetByValHistory.h"
</span><span class="cx"> #include "Instruction.h"
</span><span class="cx"> #include "IterationModeMetadata.h"
</span><del>-#include "JSPropertyNameEnumerator.h"
</del><span class="cx"> #include "Opcode.h"
</span><span class="cx"> #include "PrivateFieldPutKind.h"
</span><span class="cx"> #include "PutByIdStatus.h"
</span></span></pre></div>
<a id="branchessafari612128branchSourceJavaScriptCoreinterpreterRegisterh"></a>
<div class="modfile"><h4>Modified: branches/safari-612.1.28-branch/Source/JavaScriptCore/interpreter/Register.h (281021 => 281022)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-612.1.28-branch/Source/JavaScriptCore/interpreter/Register.h     2021-08-13 16:39:44 UTC (rev 281021)
+++ branches/safari-612.1.28-branch/Source/JavaScriptCore/interpreter/Register.h        2021-08-13 16:50:38 UTC (rev 281022)
</span><span class="lines">@@ -53,7 +53,7 @@
</span><span class="cx">         ALWAYS_INLINE Register& operator=(CallFrame*);
</span><span class="cx">         ALWAYS_INLINE Register& operator=(CodeBlock*);
</span><span class="cx">         ALWAYS_INLINE Register& operator=(JSScope*);
</span><del>-        ALWAYS_INLINE Register& operator=(JSCell*);
</del><ins>+        ALWAYS_INLINE Register& operator=(JSObject*);
</ins><span class="cx">         ALWAYS_INLINE Register& operator=(EncodedJSValue);
</span><span class="cx"> 
</span><span class="cx">         int32_t i() const;
</span></span></pre></div>
<a id="branchessafari612128branchSourceJavaScriptCoreinterpreterRegisterInlinesh"></a>
<div class="modfile"><h4>Modified: branches/safari-612.1.28-branch/Source/JavaScriptCore/interpreter/RegisterInlines.h (281021 => 281022)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-612.1.28-branch/Source/JavaScriptCore/interpreter/RegisterInlines.h      2021-08-13 16:39:44 UTC (rev 281021)
+++ branches/safari-612.1.28-branch/Source/JavaScriptCore/interpreter/RegisterInlines.h 2021-08-13 16:50:38 UTC (rev 281022)
</span><span class="lines">@@ -63,7 +63,7 @@
</span><span class="cx">     return *this;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-ALWAYS_INLINE Register& Register::operator=(JSCell* object)
</del><ins>+ALWAYS_INLINE Register& Register::operator=(JSObject* object)
</ins><span class="cx"> {
</span><span class="cx">     u.value = JSValue::encode(JSValue(object));
</span><span class="cx">     return *this;
</span></span></pre></div>
<a id="branchessafari612128branchSourceJavaScriptCorejitAssemblyHelpersh"></a>
<div class="modfile"><h4>Modified: branches/safari-612.1.28-branch/Source/JavaScriptCore/jit/AssemblyHelpers.h (281021 => 281022)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-612.1.28-branch/Source/JavaScriptCore/jit/AssemblyHelpers.h      2021-08-13 16:39:44 UTC (rev 281021)
+++ branches/safari-612.1.28-branch/Source/JavaScriptCore/jit/AssemblyHelpers.h 2021-08-13 16:50:38 UTC (rev 281022)
</span><span class="lines">@@ -188,7 +188,7 @@
</span><span class="cx">         store32(regs.tagGPR(), bitwise_cast<void*>(bitwise_cast<uintptr_t>(address) + TagOffset));
</span><span class="cx"> #endif
</span><span class="cx">     }
</span><del>-
</del><ins>+    
</ins><span class="cx">     void loadValue(Address address, JSValueRegs regs)
</span><span class="cx">     {
</span><span class="cx"> #if USE(JSVALUE64)
</span><span class="lines">@@ -889,7 +889,7 @@
</span><span class="cx">         return branch8(
</span><span class="cx">             Below, Address(cellGPR, JSCell::typeInfoTypeOffset()), TrustedImm32(ObjectType));
</span><span class="cx">     }
</span><del>-
</del><ins>+    
</ins><span class="cx">     // Note that first and last are inclusive.
</span><span class="cx">     Jump branchIfType(GPRReg cellGPR, JSTypeRange range)
</span><span class="cx">     {
</span></span></pre></div>
<a id="branchessafari612128branchSourceJavaScriptCorejitJITcpp"></a>
<div class="modfile"><h4>Modified: branches/safari-612.1.28-branch/Source/JavaScriptCore/jit/JIT.cpp (281021 => 281022)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-612.1.28-branch/Source/JavaScriptCore/jit/JIT.cpp        2021-08-13 16:39:44 UTC (rev 281021)
+++ branches/safari-612.1.28-branch/Source/JavaScriptCore/jit/JIT.cpp   2021-08-13 16:50:38 UTC (rev 281022)
</span><span class="lines">@@ -308,7 +308,10 @@
</span><span class="cx">         DEFINE_SLOW_OP(new_array_with_spread)
</span><span class="cx">         DEFINE_SLOW_OP(new_array_buffer)
</span><span class="cx">         DEFINE_SLOW_OP(spread)
</span><ins>+        DEFINE_SLOW_OP(get_enumerable_length)
+        DEFINE_SLOW_OP(has_enumerable_property)
</ins><span class="cx">         DEFINE_SLOW_OP(get_property_enumerator)
</span><ins>+        DEFINE_SLOW_OP(to_index_string)
</ins><span class="cx">         DEFINE_SLOW_OP(create_direct_arguments)
</span><span class="cx">         DEFINE_SLOW_OP(create_scoped_arguments)
</span><span class="cx">         DEFINE_SLOW_OP(create_cloned_arguments)
</span><span class="lines">@@ -362,10 +365,6 @@
</span><span class="cx">         DEFINE_OP(op_get_by_id_with_this)
</span><span class="cx">         DEFINE_OP(op_get_by_id_direct)
</span><span class="cx">         DEFINE_OP(op_get_by_val)
</span><del>-        DEFINE_OP(op_enumerator_next)
-        DEFINE_OP(op_enumerator_get_by_val)
-        DEFINE_OP(op_enumerator_in_by_val)
-        DEFINE_OP(op_enumerator_has_own_property)
</del><span class="cx">         DEFINE_OP(op_get_private_name)
</span><span class="cx">         DEFINE_OP(op_set_private_brand)
</span><span class="cx">         DEFINE_OP(op_check_private_brand)
</span><span class="lines">@@ -474,6 +473,14 @@
</span><span class="cx">         DEFINE_OP(op_get_from_arguments)
</span><span class="cx">         DEFINE_OP(op_put_to_arguments)
</span><span class="cx"> 
</span><ins>+        DEFINE_OP(op_has_enumerable_indexed_property)
+        DEFINE_OP(op_has_enumerable_structure_property)
+        DEFINE_OP(op_has_own_structure_property)
+        DEFINE_OP(op_in_structure_property)
+        DEFINE_OP(op_get_direct_pname)
+        DEFINE_OP(op_enumerator_structure_pname)
+        DEFINE_OP(op_enumerator_generic_pname)
+            
</ins><span class="cx">         DEFINE_OP(op_log_shadow_chicken_prologue)
</span><span class="cx">         DEFINE_OP(op_log_shadow_chicken_tail)
</span><span class="cx"> 
</span><span class="lines">@@ -571,7 +578,6 @@
</span><span class="cx">         DEFINE_SLOWCASE_OP(op_get_by_id_with_this)
</span><span class="cx">         DEFINE_SLOWCASE_OP(op_get_by_id_direct)
</span><span class="cx">         DEFINE_SLOWCASE_OP(op_get_by_val)
</span><del>-        DEFINE_SLOWCASE_OP(op_enumerator_get_by_val)
</del><span class="cx">         DEFINE_SLOWCASE_OP(op_get_private_name)
</span><span class="cx">         DEFINE_SLOWCASE_OP(op_set_private_brand)
</span><span class="cx">         DEFINE_SLOWCASE_OP(op_check_private_brand)
</span><span class="lines">@@ -603,6 +609,7 @@
</span><span class="cx">         DEFINE_SLOWCASE_OP(op_del_by_val)
</span><span class="cx">         DEFINE_SLOWCASE_OP(op_del_by_id)
</span><span class="cx">         DEFINE_SLOWCASE_OP(op_sub)
</span><ins>+        DEFINE_SLOWCASE_OP(op_has_enumerable_indexed_property)
</ins><span class="cx"> #if !ENABLE(EXTRA_CTI_THUNKS)
</span><span class="cx">         DEFINE_SLOWCASE_OP(op_get_from_scope)
</span><span class="cx"> #endif
</span><span class="lines">@@ -635,7 +642,11 @@
</span><span class="cx">         DEFINE_SLOWCASE_SLOW_OP(not)
</span><span class="cx">         DEFINE_SLOWCASE_SLOW_OP(stricteq)
</span><span class="cx">         DEFINE_SLOWCASE_SLOW_OP(nstricteq)
</span><ins>+        DEFINE_SLOWCASE_SLOW_OP(get_direct_pname)
</ins><span class="cx">         DEFINE_SLOWCASE_SLOW_OP(get_prototype_of)
</span><ins>+        DEFINE_SLOWCASE_SLOW_OP(has_enumerable_structure_property)
+        DEFINE_SLOWCASE_SLOW_OP(has_own_structure_property)
+        DEFINE_SLOWCASE_SLOW_OP(in_structure_property)
</ins><span class="cx"> #if !ENABLE(EXTRA_CTI_THUNKS)
</span><span class="cx">         DEFINE_SLOWCASE_SLOW_OP(resolve_scope)
</span><span class="cx"> #endif
</span></span></pre></div>
<a id="branchessafari612128branchSourceJavaScriptCorejitJITh"></a>
<div class="modfile"><h4>Modified: branches/safari-612.1.28-branch/Source/JavaScriptCore/jit/JIT.h (281021 => 281022)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-612.1.28-branch/Source/JavaScriptCore/jit/JIT.h  2021-08-13 16:39:44 UTC (rev 281021)
+++ branches/safari-612.1.28-branch/Source/JavaScriptCore/jit/JIT.h     2021-08-13 16:50:38 UTC (rev 281022)
</span><span class="lines">@@ -453,7 +453,6 @@
</span><span class="cx"> 
</span><span class="cx">         void emitGetVirtualRegister(VirtualRegister src, JSValueRegs dst);
</span><span class="cx">         void emitPutVirtualRegister(VirtualRegister dst, JSValueRegs src);
</span><del>-        void emitStore(VirtualRegister, const JSValue constant, RegisterID base = callFrameRegister);
</del><span class="cx"> 
</span><span class="cx">         int32_t getOperandConstantInt(VirtualRegister src);
</span><span class="cx">         double getOperandConstantDouble(VirtualRegister src);
</span><span class="lines">@@ -470,6 +469,7 @@
</span><span class="cx">         void emitLoad2(VirtualRegister, RegisterID tag1, RegisterID payload1, VirtualRegister, RegisterID tag2, RegisterID payload2);
</span><span class="cx"> 
</span><span class="cx">         void emitStore(VirtualRegister, RegisterID tag, RegisterID payload, RegisterID base = callFrameRegister);
</span><ins>+        void emitStore(VirtualRegister, const JSValue constant, RegisterID base = callFrameRegister);
</ins><span class="cx">         void emitStoreInt32(VirtualRegister, RegisterID payload, bool indexIsInt32 = false);
</span><span class="cx">         void emitStoreInt32(VirtualRegister, TrustedImm32 payload, bool indexIsInt32 = false);
</span><span class="cx">         void emitStoreCell(VirtualRegister, RegisterID payload, bool indexIsCell = false);
</span><span class="lines">@@ -670,6 +670,15 @@
</span><span class="cx">         void emit_op_unexpected_load(const Instruction*);
</span><span class="cx">         void emit_op_unsigned(const Instruction*);
</span><span class="cx">         void emit_op_urshift(const Instruction*);
</span><ins>+        template <typename OpCodeType>
+        void emit_op_has_structure_propertyImpl(const Instruction*);
+        void emit_op_has_enumerable_indexed_property(const Instruction*);
+        void emit_op_has_enumerable_structure_property(const Instruction*);
+        void emit_op_has_own_structure_property(const Instruction*);
+        void emit_op_in_structure_property(const Instruction*);
+        void emit_op_get_direct_pname(const Instruction*);
+        void emit_op_enumerator_structure_pname(const Instruction*);
+        void emit_op_enumerator_generic_pname(const Instruction*);
</ins><span class="cx">         void emit_op_get_internal_field(const Instruction*);
</span><span class="cx">         void emit_op_put_internal_field(const Instruction*);
</span><span class="cx">         void emit_op_log_shadow_chicken_prologue(const Instruction*);
</span><span class="lines">@@ -676,18 +685,6 @@
</span><span class="cx">         void emit_op_log_shadow_chicken_tail(const Instruction*);
</span><span class="cx">         void emit_op_to_property_key(const Instruction*);
</span><span class="cx"> 
</span><del>-        template<typename OpcodeType>
-        void generateGetByValSlowCase(const OpcodeType&, Vector<SlowCaseEntry>::iterator&);
-
-        void emit_op_enumerator_next(const Instruction*);
-        void emit_op_enumerator_get_by_val(const Instruction*);
-        void emitSlow_op_enumerator_get_by_val(const Instruction*, Vector<SlowCaseEntry>::iterator&);
-
-        template<typename OpcodeType, typename SlowPathFunctionType>
-        void emit_enumerator_has_propertyImpl(const Instruction*, const OpcodeType&, SlowPathFunctionType);
-        void emit_op_enumerator_in_by_val(const Instruction*);
-        void emit_op_enumerator_has_own_property(const Instruction*);
-
</del><span class="cx">         void emitSlow_op_add(const Instruction*, Vector<SlowCaseEntry>::iterator&);
</span><span class="cx">         void emitSlow_op_call(const Instruction*, Vector<SlowCaseEntry>::iterator&);
</span><span class="cx">         void emitSlow_op_tail_call(const Instruction*, Vector<SlowCaseEntry>::iterator&);
</span><span class="lines">@@ -738,6 +735,7 @@
</span><span class="cx">         void emitSlow_op_put_by_val(const Instruction*, Vector<SlowCaseEntry>::iterator&);
</span><span class="cx">         void emitSlow_op_put_private_name(const Instruction*, Vector<SlowCaseEntry>::iterator&);
</span><span class="cx">         void emitSlow_op_sub(const Instruction*, Vector<SlowCaseEntry>::iterator&);
</span><ins>+        void emitSlow_op_has_enumerable_indexed_property(const Instruction*, Vector<SlowCaseEntry>::iterator&);
</ins><span class="cx"> 
</span><span class="cx">         void emit_op_resolve_scope(const Instruction*);
</span><span class="cx">         void emit_op_get_from_scope(const Instruction*);
</span></span></pre></div>
<a id="branchessafari612128branchSourceJavaScriptCorejitJITOpcodescpp"></a>
<div class="modfile"><h4>Modified: branches/safari-612.1.28-branch/Source/JavaScriptCore/jit/JITOpcodes.cpp (281021 => 281022)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-612.1.28-branch/Source/JavaScriptCore/jit/JITOpcodes.cpp 2021-08-13 16:39:44 UTC (rev 281021)
+++ branches/safari-612.1.28-branch/Source/JavaScriptCore/jit/JITOpcodes.cpp    2021-08-13 16:50:38 UTC (rev 281022)
</span><span class="lines">@@ -1692,12 +1692,46 @@
</span><span class="cx"> 
</span><span class="cx"> #if USE(JSVALUE64)
</span><span class="cx"> 
</span><ins>+template <typename OpCodeType>
+void JIT::emit_op_has_structure_propertyImpl(const Instruction* currentInstruction)
+{
+    auto bytecode = currentInstruction->as<OpCodeType>();
+    VirtualRegister dst = bytecode.m_dst;
+    VirtualRegister base = bytecode.m_base;
+    VirtualRegister enumerator = bytecode.m_enumerator;
+
+    emitGetVirtualRegister(base, regT0);
+    emitGetVirtualRegister(enumerator, regT1);
+    emitJumpSlowCaseIfNotJSCell(regT0, base);
+
+    load32(Address(regT0, JSCell::structureIDOffset()), regT0);
+    addSlowCase(branch32(NotEqual, regT0, Address(regT1, JSPropertyNameEnumerator::cachedStructureIDOffset())));
+    
+    move(TrustedImm64(JSValue::encode(jsBoolean(true))), regT0);
+    emitPutVirtualRegister(dst);
+}
+
+void JIT::emit_op_has_enumerable_structure_property(const Instruction* currentInstruction)
+{
+    emit_op_has_structure_propertyImpl<OpHasEnumerableStructureProperty>(currentInstruction);
+}
+
+void JIT::emit_op_has_own_structure_property(const Instruction* currentInstruction)
+{
+    emit_op_has_structure_propertyImpl<OpHasOwnStructureProperty>(currentInstruction);
+}
+
+void JIT::emit_op_in_structure_property(const Instruction* currentInstruction)
+{
+    emit_op_has_structure_propertyImpl<OpInStructureProperty>(currentInstruction);
+}
+
</ins><span class="cx"> void JIT::privateCompileHasIndexedProperty(ByValInfo* byValInfo, ReturnAddressPtr returnAddress, JITArrayMode arrayMode)
</span><span class="cx"> {
</span><span class="cx">     const Instruction* currentInstruction = m_codeBlock->instructions().at(byValInfo->bytecodeIndex).ptr();
</span><del>-
</del><ins>+    
</ins><span class="cx">     PatchableJump badType;
</span><del>-
</del><ins>+    
</ins><span class="cx">     // FIXME: Add support for other types like TypedArrays and Arguments.
</span><span class="cx">     // See https://bugs.webkit.org/show_bug.cgi?id=135033 and https://bugs.webkit.org/show_bug.cgi?id=135034.
</span><span class="cx">     JumpList slowCases = emitLoadForArrayMode(currentInstruction, arrayMode, badType, nullptr);
</span><span class="lines">@@ -1705,7 +1739,7 @@
</span><span class="cx">     Jump done = jump();
</span><span class="cx"> 
</span><span class="cx">     LinkBuffer patchBuffer(*this, m_codeBlock, LinkBuffer::Profile::InlineCache);
</span><del>-
</del><ins>+    
</ins><span class="cx">     patchBuffer.link(badType, byValInfo->slowPathTarget);
</span><span class="cx">     patchBuffer.link(slowCases, byValInfo->slowPathTarget);
</span><span class="cx"> 
</span><span class="lines">@@ -1714,7 +1748,7 @@
</span><span class="cx">     byValInfo->stubRoutine = FINALIZE_CODE_FOR_STUB(
</span><span class="cx">         m_codeBlock, patchBuffer, JITStubRoutinePtrTag,
</span><span class="cx">         "Baseline has_indexed_property stub for %s, return point %p", toCString(*m_codeBlock).data(), returnAddress.untaggedValue());
</span><del>-
</del><ins>+    
</ins><span class="cx">     if (JITCode::useDataIC(JITType::BaselineJIT)) {
</span><span class="cx">         byValInfo->m_badTypeJumpTarget = CodeLocationLabel<JITStubRoutinePtrTag>(byValInfo->stubRoutine->code().code());
</span><span class="cx">         byValInfo->m_slowOperation = operationHasIndexedPropertyGeneric;
</span><span class="lines">@@ -1724,6 +1758,171 @@
</span><span class="cx">     }
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void JIT::emit_op_has_enumerable_indexed_property(const Instruction* currentInstruction)
+{
+    auto bytecode = currentInstruction->as<OpHasEnumerableIndexedProperty>();
+    auto& metadata = bytecode.metadata(m_codeBlock);
+    VirtualRegister dst = bytecode.m_dst;
+    VirtualRegister base = bytecode.m_base;
+    VirtualRegister property = bytecode.m_property;
+    ArrayProfile* profile = &metadata.m_arrayProfile;
+    ByValInfo* byValInfo = m_codeBlock->addByValInfo(m_bytecodeIndex);
+    
+    emitGetVirtualRegisters(base, regT0, property, regT1);
+
+    emitJumpSlowCaseIfNotInt(regT1);
+
+    // This is technically incorrect - we're zero-extending an int32. On the hot path this doesn't matter.
+    // We check the value as if it was a uint32 against the m_vectorLength - which will always fail if
+    // number was signed since m_vectorLength is always less than intmax (since the total allocation
+    // size is always less than 4Gb). As such zero extending will have been correct (and extending the value
+    // to 64-bits is necessary since it's used in the address calculation. We zero extend rather than sign
+    // extending since it makes it easier to re-tag the value in the slow case.
+    zeroExtend32ToWord(regT1, regT1);
+
+    emitJumpSlowCaseIfNotJSCell(regT0, base);
+    emitArrayProfilingSiteWithCell(regT0, regT2, profile);
+    and32(TrustedImm32(IndexingShapeMask), regT2);
+
+    JITArrayMode mode = chooseArrayMode(profile);
+    PatchableJump badType;
+
+    // FIXME: Add support for other types like TypedArrays and Arguments.
+    // See https://bugs.webkit.org/show_bug.cgi?id=135033 and https://bugs.webkit.org/show_bug.cgi?id=135034.
+    JumpList slowCases = emitLoadForArrayMode(currentInstruction, mode, badType, byValInfo);
+    
+    move(TrustedImm64(JSValue::encode(jsBoolean(true))), regT0);
+
+    if (!JITCode::useDataIC(JITType::BaselineJIT))
+        addSlowCase(badType);
+    addSlowCase(slowCases);
+    
+    Label done = label();
+    
+    emitPutVirtualRegister(dst);
+
+    Label nextHotPath = label();
+    
+    m_byValCompilationInfo.append(ByValCompilationInfo(byValInfo, m_bytecodeIndex, PatchableJump(), badType, mode, profile, done, nextHotPath));
+}
+
+void JIT::emitSlow_op_has_enumerable_indexed_property(const Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
+{
+    linkAllSlowCases(iter);
+
+    auto bytecode = currentInstruction->as<OpHasEnumerableIndexedProperty>();
+    VirtualRegister dst = bytecode.m_dst;
+    VirtualRegister base = bytecode.m_base;
+    VirtualRegister property = bytecode.m_property;
+    ByValInfo* byValInfo = m_byValCompilationInfo[m_byValInstructionIndex].byValInfo;
+
+    Label slowPath = label();
+    
+    emitGetVirtualRegister(base, regT0);
+    emitGetVirtualRegister(property, regT1);
+
+    Call call;
+    if (JITCode::useDataIC(JITType::BaselineJIT)) {
+        byValInfo->m_slowOperation = operationHasIndexedPropertyDefault;
+        move(TrustedImmPtr(byValInfo), GPRInfo::nonArgGPR0);
+        callOperation<decltype(operationHasIndexedPropertyDefault)>(Address(GPRInfo::nonArgGPR0, ByValInfo::offsetOfSlowOperation()), dst, TrustedImmPtr(m_codeBlock->globalObject()), regT0, regT1, GPRInfo::nonArgGPR0);
+    } else
+        call = callOperation(operationHasIndexedPropertyDefault, dst, TrustedImmPtr(m_codeBlock->globalObject()), regT0, regT1, byValInfo);
+
+    m_byValCompilationInfo[m_byValInstructionIndex].slowPathTarget = slowPath;
+    m_byValCompilationInfo[m_byValInstructionIndex].returnAddress = call;
+    m_byValInstructionIndex++;
+}
+
+void JIT::emit_op_get_direct_pname(const Instruction* currentInstruction)
+{
+    auto bytecode = currentInstruction->as<OpGetDirectPname>();
+    VirtualRegister dst = bytecode.m_dst;
+    VirtualRegister base = bytecode.m_base;
+    VirtualRegister index = bytecode.m_index;
+    VirtualRegister enumerator = bytecode.m_enumerator;
+
+    // Check that base is a cell
+    emitGetVirtualRegister(base, regT0);
+    emitJumpSlowCaseIfNotJSCell(regT0, base);
+
+    // Check the structure
+    emitGetVirtualRegister(enumerator, regT2);
+    load32(Address(regT0, JSCell::structureIDOffset()), regT1);
+    addSlowCase(branch32(NotEqual, regT1, Address(regT2, JSPropertyNameEnumerator::cachedStructureIDOffset())));
+
+    // Compute the offset
+    emitGetVirtualRegister(index, regT1);
+    // If index is less than the enumerator's cached inline storage, then it's an inline access
+    Jump outOfLineAccess = branch32(AboveOrEqual, regT1, Address(regT2, JSPropertyNameEnumerator::cachedInlineCapacityOffset()));
+    addPtr(TrustedImm32(JSObject::offsetOfInlineStorage()), regT0);
+    signExtend32ToPtr(regT1, regT1);
+    load64(BaseIndex(regT0, regT1, TimesEight), regT0);
+    
+    Jump done = jump();
+
+    // Otherwise it's out of line
+    outOfLineAccess.link(this);
+    loadPtr(Address(regT0, JSObject::butterflyOffset()), regT0);
+    sub32(Address(regT2, JSPropertyNameEnumerator::cachedInlineCapacityOffset()), regT1);
+    neg32(regT1);
+    signExtend32ToPtr(regT1, regT1);
+    int32_t offsetOfFirstProperty = static_cast<int32_t>(offsetInButterfly(firstOutOfLineOffset)) * sizeof(EncodedJSValue);
+    load64(BaseIndex(regT0, regT1, TimesEight, offsetOfFirstProperty), regT0);
+    
+    done.link(this);
+    emitValueProfilingSite(bytecode.metadata(m_codeBlock), regT0);
+    emitPutVirtualRegister(dst, regT0);
+}
+
+void JIT::emit_op_enumerator_structure_pname(const Instruction* currentInstruction)
+{
+    auto bytecode = currentInstruction->as<OpEnumeratorStructurePname>();
+    VirtualRegister dst = bytecode.m_dst;
+    VirtualRegister enumerator = bytecode.m_enumerator;
+    VirtualRegister index = bytecode.m_index;
+
+    emitGetVirtualRegister(index, regT0);
+    emitGetVirtualRegister(enumerator, regT1);
+    Jump inBounds = branch32(Below, regT0, Address(regT1, JSPropertyNameEnumerator::endStructurePropertyIndexOffset()));
+
+    move(TrustedImm64(JSValue::encode(jsNull())), regT0);
+
+    Jump done = jump();
+    inBounds.link(this);
+
+    loadPtr(Address(regT1, JSPropertyNameEnumerator::cachedPropertyNamesVectorOffset()), regT1);
+    signExtend32ToPtr(regT0, regT0);
+    load64(BaseIndex(regT1, regT0, TimesEight), regT0);
+
+    done.link(this);
+    emitPutVirtualRegister(dst);
+}
+
+void JIT::emit_op_enumerator_generic_pname(const Instruction* currentInstruction)
+{
+    auto bytecode = currentInstruction->as<OpEnumeratorGenericPname>();
+    VirtualRegister dst = bytecode.m_dst;
+    VirtualRegister enumerator = bytecode.m_enumerator;
+    VirtualRegister index = bytecode.m_index;
+
+    emitGetVirtualRegister(index, regT0);
+    emitGetVirtualRegister(enumerator, regT1);
+    Jump inBounds = branch32(Below, regT0, Address(regT1, JSPropertyNameEnumerator::endGenericPropertyIndexOffset()));
+
+    move(TrustedImm64(JSValue::encode(jsNull())), regT0);
+
+    Jump done = jump();
+    inBounds.link(this);
+
+    loadPtr(Address(regT1, JSPropertyNameEnumerator::cachedPropertyNamesVectorOffset()), regT1);
+    signExtend32ToPtr(regT0, regT0);
+    load64(BaseIndex(regT1, regT0, TimesEight), regT0);
+    
+    done.link(this);
+    emitPutVirtualRegister(dst);
+}
+
</ins><span class="cx"> void JIT::emit_op_profile_type(const Instruction* currentInstruction)
</span><span class="cx"> {
</span><span class="cx">     auto bytecode = currentInstruction->as<OpProfileType>();
</span></span></pre></div>
<a id="branchessafari612128branchSourceJavaScriptCorejitJITOpcodes32_64cpp"></a>
<div class="modfile"><h4>Modified: branches/safari-612.1.28-branch/Source/JavaScriptCore/jit/JITOpcodes32_64.cpp (281021 => 281022)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-612.1.28-branch/Source/JavaScriptCore/jit/JITOpcodes32_64.cpp    2021-08-13 16:39:44 UTC (rev 281021)
+++ branches/safari-612.1.28-branch/Source/JavaScriptCore/jit/JITOpcodes32_64.cpp       2021-08-13 16:50:38 UTC (rev 281022)
</span><span class="lines">@@ -1142,12 +1142,47 @@
</span><span class="cx">     addSlowCase(branchIfEmpty(regT0));
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+template <typename OpCodeType>
+void JIT::emit_op_has_structure_propertyImpl(const Instruction* currentInstruction)
+{
+    auto bytecode = currentInstruction->as<OpCodeType>();
+    VirtualRegister dst = bytecode.m_dst;
+    VirtualRegister base = bytecode.m_base;
+    VirtualRegister enumerator = bytecode.m_enumerator;
+
+    emitLoadPayload(base, regT0);
+    emitJumpSlowCaseIfNotJSCell(base);
+
+    emitLoadPayload(enumerator, regT1);
+
+    load32(Address(regT0, JSCell::structureIDOffset()), regT0);
+    addSlowCase(branch32(NotEqual, regT0, Address(regT1, JSPropertyNameEnumerator::cachedStructureIDOffset())));
+    
+    move(TrustedImm32(1), regT0);
+    emitStoreBool(dst, regT0);
+}
+
+void JIT::emit_op_has_enumerable_structure_property(const Instruction* currentInstruction)
+{
+    emit_op_has_structure_propertyImpl<OpHasEnumerableStructureProperty>(currentInstruction);
+}
+
+void JIT::emit_op_has_own_structure_property(const Instruction* currentInstruction)
+{
+    emit_op_has_structure_propertyImpl<OpHasOwnStructureProperty>(currentInstruction);
+}
+
+void JIT::emit_op_in_structure_property(const Instruction* currentInstruction)
+{
+    emit_op_has_structure_propertyImpl<OpInStructureProperty>(currentInstruction);
+}
+
</ins><span class="cx"> void JIT::privateCompileHasIndexedProperty(ByValInfo* byValInfo, ReturnAddressPtr returnAddress, JITArrayMode arrayMode)
</span><span class="cx"> {
</span><span class="cx">     const Instruction* currentInstruction = m_codeBlock->instructions().at(byValInfo->bytecodeIndex).ptr();
</span><del>-
</del><ins>+    
</ins><span class="cx">     PatchableJump badType;
</span><del>-
</del><ins>+    
</ins><span class="cx">     // FIXME: Add support for other types like TypedArrays and Arguments.
</span><span class="cx">     // See https://bugs.webkit.org/show_bug.cgi?id=135033 and https://bugs.webkit.org/show_bug.cgi?id=135034.
</span><span class="cx">     JumpList slowCases = emitLoadForArrayMode(currentInstruction, arrayMode, badType, nullptr);
</span><span class="lines">@@ -1155,7 +1190,7 @@
</span><span class="cx">     Jump done = jump();
</span><span class="cx"> 
</span><span class="cx">     LinkBuffer patchBuffer(*this, m_codeBlock, LinkBuffer::Profile::InlineCache);
</span><del>-
</del><ins>+    
</ins><span class="cx">     patchBuffer.link(badType, byValInfo->slowPathTarget);
</span><span class="cx">     patchBuffer.link(slowCases, byValInfo->slowPathTarget);
</span><span class="cx"> 
</span><span class="lines">@@ -1164,11 +1199,170 @@
</span><span class="cx">     byValInfo->stubRoutine = FINALIZE_CODE_FOR_STUB(
</span><span class="cx">         m_codeBlock, patchBuffer, JITStubRoutinePtrTag,
</span><span class="cx">         "Baseline has_indexed_property stub for %s, return point %p", toCString(*m_codeBlock).data(), returnAddress.untaggedValue());
</span><del>-
</del><ins>+    
</ins><span class="cx">     MacroAssembler::repatchJump(byValInfo->m_badTypeJump, CodeLocationLabel<JITStubRoutinePtrTag>(byValInfo->stubRoutine->code().code()));
</span><span class="cx">     MacroAssembler::repatchCall(CodeLocationCall<ReturnAddressPtrTag>(MacroAssemblerCodePtr<ReturnAddressPtrTag>(returnAddress)), FunctionPtr<OperationPtrTag>(operationHasIndexedPropertyGeneric));
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void JIT::emit_op_has_enumerable_indexed_property(const Instruction* currentInstruction)
+{
+    auto bytecode = currentInstruction->as<OpHasEnumerableIndexedProperty>();
+    auto& metadata = bytecode.metadata(m_codeBlock);
+    VirtualRegister dst = bytecode.m_dst;
+    VirtualRegister base = bytecode.m_base;
+    VirtualRegister property = bytecode.m_property;
+    ArrayProfile* profile = &metadata.m_arrayProfile;
+    ByValInfo* byValInfo = m_codeBlock->addByValInfo(m_bytecodeIndex);
+    
+    emitLoadPayload(base, regT0);
+    emitJumpSlowCaseIfNotJSCell(base);
+
+    emitLoad(property, regT3, regT1);
+    addSlowCase(branchIfNotInt32(regT3));
+
+    // This is technically incorrect - we're zero-extending an int32. On the hot path this doesn't matter.
+    // We check the value as if it was a uint32 against the m_vectorLength - which will always fail if
+    // number was signed since m_vectorLength is always less than intmax (since the total allocation
+    // size is always less than 4Gb). As such zero extending will have been correct (and extending the value
+    // to 64-bits is necessary since it's used in the address calculation. We zero extend rather than sign
+    // extending since it makes it easier to re-tag the value in the slow case.
+    zeroExtend32ToWord(regT1, regT1);
+
+    emitArrayProfilingSiteWithCell(regT0, regT2, profile);
+    and32(TrustedImm32(IndexingShapeMask), regT2);
+
+    JITArrayMode mode = chooseArrayMode(profile);
+    PatchableJump badType;
+
+    // FIXME: Add support for other types like TypedArrays and Arguments.
+    // See https://bugs.webkit.org/show_bug.cgi?id=135033 and https://bugs.webkit.org/show_bug.cgi?id=135034.
+    JumpList slowCases = emitLoadForArrayMode(currentInstruction, mode, badType, byValInfo);
+    move(TrustedImm32(1), regT0);
+
+    addSlowCase(badType);
+    addSlowCase(slowCases);
+    
+    Label done = label();
+    
+    emitStoreBool(dst, regT0);
+
+    Label nextHotPath = label();
+    
+    m_byValCompilationInfo.append(ByValCompilationInfo(byValInfo, m_bytecodeIndex, PatchableJump(), badType, mode, profile, done, nextHotPath));
+}
+
+void JIT::emitSlow_op_has_enumerable_indexed_property(const Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
+{
+    linkAllSlowCases(iter);
+
+    auto bytecode = currentInstruction->as<OpHasEnumerableIndexedProperty>();
+    VirtualRegister dst = bytecode.m_dst;
+    VirtualRegister base = bytecode.m_base;
+    VirtualRegister property = bytecode.m_property;
+    ByValInfo* byValInfo = m_byValCompilationInfo[m_byValInstructionIndex].byValInfo;
+
+    Label slowPath = label();
+    
+    emitLoad(base, regT1, regT0);
+    emitLoad(property, regT3, regT2);
+    Call call = callOperation(operationHasIndexedPropertyDefault, dst, m_codeBlock->globalObject(), JSValueRegs(regT1, regT0), JSValueRegs(regT3, regT2), byValInfo);
+
+    m_byValCompilationInfo[m_byValInstructionIndex].slowPathTarget = slowPath;
+    m_byValCompilationInfo[m_byValInstructionIndex].returnAddress = call;
+    m_byValInstructionIndex++;
+}
+
+void JIT::emit_op_get_direct_pname(const Instruction* currentInstruction)
+{
+    auto bytecode = currentInstruction->as<OpGetDirectPname>();
+    VirtualRegister dst = bytecode.m_dst;
+    VirtualRegister base = bytecode.m_base;
+    VirtualRegister index = bytecode.m_index;
+    VirtualRegister enumerator = bytecode.m_enumerator;
+
+    // Check that base is a cell
+    emitLoadPayload(base, regT0);
+    emitJumpSlowCaseIfNotJSCell(base);
+
+    // Check the structure
+    emitLoadPayload(enumerator, regT1);
+    load32(Address(regT0, JSCell::structureIDOffset()), regT2);
+    addSlowCase(branch32(NotEqual, regT2, Address(regT1, JSPropertyNameEnumerator::cachedStructureIDOffset())));
+
+    // Compute the offset
+    emitLoadPayload(index, regT2);
+    // If index is less than the enumerator's cached inline storage, then it's an inline access
+    Jump outOfLineAccess = branch32(AboveOrEqual, regT2, Address(regT1, JSPropertyNameEnumerator::cachedInlineCapacityOffset()));
+    addPtr(TrustedImm32(JSObject::offsetOfInlineStorage()), regT0);
+    load32(BaseIndex(regT0, regT2, TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.tag)), regT1);
+    load32(BaseIndex(regT0, regT2, TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.payload)), regT0);
+    
+    Jump done = jump();
+
+    // Otherwise it's out of line
+    outOfLineAccess.link(this);
+    loadPtr(Address(regT0, JSObject::butterflyOffset()), regT0);
+    sub32(Address(regT1, JSPropertyNameEnumerator::cachedInlineCapacityOffset()), regT2);
+    neg32(regT2);
+    int32_t offsetOfFirstProperty = static_cast<int32_t>(offsetInButterfly(firstOutOfLineOffset)) * sizeof(EncodedJSValue);
+    load32(BaseIndex(regT0, regT2, TimesEight, offsetOfFirstProperty + OBJECT_OFFSETOF(JSValue, u.asBits.tag)), regT1);
+    load32(BaseIndex(regT0, regT2, TimesEight, offsetOfFirstProperty + OBJECT_OFFSETOF(JSValue, u.asBits.payload)), regT0);
+    
+    done.link(this);
+    emitValueProfilingSite(bytecode.metadata(m_codeBlock), JSValueRegs(regT1, regT0));
+    emitStore(dst, regT1, regT0);
+}
+
+void JIT::emit_op_enumerator_structure_pname(const Instruction* currentInstruction)
+{
+    auto bytecode = currentInstruction->as<OpEnumeratorStructurePname>();
+    VirtualRegister dst = bytecode.m_dst;
+    VirtualRegister enumerator = bytecode.m_enumerator;
+    VirtualRegister index = bytecode.m_index;
+
+    emitLoadPayload(index, regT0);
+    emitLoadPayload(enumerator, regT1);
+    Jump inBounds = branch32(Below, regT0, Address(regT1, JSPropertyNameEnumerator::endStructurePropertyIndexOffset()));
+
+    move(TrustedImm32(JSValue::NullTag), regT2);
+    move(TrustedImm32(0), regT0);
+
+    Jump done = jump();
+    inBounds.link(this);
+
+    loadPtr(Address(regT1, JSPropertyNameEnumerator::cachedPropertyNamesVectorOffset()), regT1);
+    loadPtr(BaseIndex(regT1, regT0, ScalePtr), regT0);
+    move(TrustedImm32(JSValue::CellTag), regT2);
+
+    done.link(this);
+    emitStore(dst, regT2, regT0);
+}
+
+void JIT::emit_op_enumerator_generic_pname(const Instruction* currentInstruction)
+{
+    auto bytecode = currentInstruction->as<OpEnumeratorGenericPname>();
+    VirtualRegister dst = bytecode.m_dst;
+    VirtualRegister enumerator = bytecode.m_enumerator;
+    VirtualRegister index = bytecode.m_index;
+
+    emitLoadPayload(index, regT0);
+    emitLoadPayload(enumerator, regT1);
+    Jump inBounds = branch32(Below, regT0, Address(regT1, JSPropertyNameEnumerator::endGenericPropertyIndexOffset()));
+
+    move(TrustedImm32(JSValue::NullTag), regT2);
+    move(TrustedImm32(0), regT0);
+
+    Jump done = jump();
+    inBounds.link(this);
+
+    loadPtr(Address(regT1, JSPropertyNameEnumerator::cachedPropertyNamesVectorOffset()), regT1);
+    loadPtr(BaseIndex(regT1, regT0, ScalePtr), regT0);
+    move(TrustedImm32(JSValue::CellTag), regT2);
+    
+    done.link(this);
+    emitStore(dst, regT2, regT0);
+}
+
</ins><span class="cx"> void JIT::emit_op_profile_type(const Instruction* currentInstruction)
</span><span class="cx"> {
</span><span class="cx">     auto bytecode = currentInstruction->as<OpProfileType>();
</span></span></pre></div>
<a id="branchessafari612128branchSourceJavaScriptCorejitJITPropertyAccesscpp"></a>
<div class="modfile"><h4>Modified: branches/safari-612.1.28-branch/Source/JavaScriptCore/jit/JITPropertyAccess.cpp (281021 => 281022)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-612.1.28-branch/Source/JavaScriptCore/jit/JITPropertyAccess.cpp  2021-08-13 16:39:44 UTC (rev 281021)
+++ branches/safari-612.1.28-branch/Source/JavaScriptCore/jit/JITPropertyAccess.cpp     2021-08-13 16:50:38 UTC (rev 281022)
</span><span class="lines">@@ -36,7 +36,6 @@
</span><span class="cx"> #include "JSLexicalEnvironment.h"
</span><span class="cx"> #include "LinkBuffer.h"
</span><span class="cx"> #include "PrivateFieldPutKind.h"
</span><del>-#include "ProbeContext.h"
</del><span class="cx"> #include "SlowPathCall.h"
</span><span class="cx"> #include "StructureStubInfo.h"
</span><span class="cx"> #include "ThunkGenerators.h"
</span><span class="lines">@@ -87,10 +86,10 @@
</span><span class="cx"> 
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-template<typename OpcodeType>
-void JIT::generateGetByValSlowCase(const OpcodeType& bytecode, Vector<SlowCaseEntry>::iterator& iter)
</del><ins>+void JIT::emitSlow_op_get_by_val(const Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
</ins><span class="cx"> {
</span><span class="cx">     if (hasAnySlowCases(iter)) {
</span><ins>+        auto bytecode = currentInstruction->as<OpGetByVal>();
</ins><span class="cx">         VirtualRegister dst = bytecode.m_dst;
</span><span class="cx">         auto& metadata = bytecode.metadata(m_codeBlock);
</span><span class="cx">         ArrayProfile* profile = &metadata.m_arrayProfile;
</span><span class="lines">@@ -137,11 +136,6 @@
</span><span class="cx">     }
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void JIT::emitSlow_op_get_by_val(const Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
-{
-    generateGetByValSlowCase(currentInstruction->as<OpGetByVal>(), iter);
-}
-
</del><span class="cx"> #if ENABLE(EXTRA_CTI_THUNKS)
</span><span class="cx"> MacroAssemblerCodeRef<JITThunkPtrTag> JIT::slow_op_get_by_val_prepareCallGenerator(VM& vm)
</span><span class="cx"> {
</span><span class="lines">@@ -2983,193 +2977,6 @@
</span><span class="cx"> 
</span><span class="cx"> template void JIT::emit_op_put_by_val<OpPutByVal>(const Instruction*);
</span><span class="cx"> 
</span><del>-void JIT::emit_op_enumerator_next(const Instruction* currentInstruction)
-{
-    auto bytecode = currentInstruction->as<OpEnumeratorNext>();
-    auto& metadata = bytecode.metadata(m_codeBlock);
-
-    VirtualRegister base = bytecode.m_base;
-    VirtualRegister mode = bytecode.m_mode;
-    VirtualRegister index = bytecode.m_index;
-    VirtualRegister propertyName = bytecode.m_propertyName;
-    VirtualRegister enumerator = bytecode.m_enumerator;
-
-    JumpList done;
-    JumpList operationCases;
-
-    GPRReg modeGPR = regT0;
-    GPRReg indexGPR = regT1;
-    GPRReg baseGPR = regT2;
-
-    // This is the most common mode set we tend to see, so special case it if we profile it in the LLInt.
-    if (metadata.m_enumeratorMetadata == JSPropertyNameEnumerator::OwnStructureMode) {
-        GPRReg enumeratorGPR = regT3;
-        emitGetVirtualRegister(enumerator, enumeratorGPR);
-        operationCases.append(branchTest32(NonZero, Address(enumeratorGPR, JSPropertyNameEnumerator::modeSetOffset()), TrustedImm32(~JSPropertyNameEnumerator::OwnStructureMode)));
-        emitGetVirtualRegister(base, baseGPR);
-        load32(Address(enumeratorGPR, JSPropertyNameEnumerator::cachedStructureIDOffset()), indexGPR);
-        operationCases.append(branch32(NotEqual, indexGPR, Address(baseGPR, JSCell::structureIDOffset())));
-
-        emitGetVirtualRegister(mode, modeGPR);
-        emitGetVirtualRegister(index, indexGPR);
-        Jump notInit = branchTest32(Zero, modeGPR);
-        // Need to use add64 since this is a JSValue int32.
-        add64(TrustedImm32(1), indexGPR);
-        emitPutVirtualRegister(index, indexGPR);
-        notInit.link(this);
-        storeTrustedValue(jsNumber(static_cast<uint8_t>(JSPropertyNameEnumerator::OwnStructureMode)), addressFor(mode));
-
-        Jump outOfBounds = branch32(AboveOrEqual, indexGPR, Address(enumeratorGPR, JSPropertyNameEnumerator::endStructurePropertyIndexOffset()));
-        loadPtr(Address(enumeratorGPR, JSPropertyNameEnumerator::cachedPropertyNamesVectorOffset()), enumeratorGPR);
-        // We need to clear the high bits from the number encoding.
-        and32(TrustedImm32(-1), indexGPR);
-        loadPtr(BaseIndex(enumeratorGPR, indexGPR, ScalePtr), enumeratorGPR);
-
-        emitPutVirtualRegister(propertyName, enumeratorGPR);
-        done.append(jump());
-
-        outOfBounds.link(this);
-        storeTrustedValue(jsNull(), addressFor(propertyName));
-        done.append(jump());
-    }
-
-    operationCases.link(this);
-
-    JITSlowPathCall slowPathCall(this, currentInstruction, slow_path_enumerator_next);
-    slowPathCall.call();
-
-    done.link(this);
-}
-
-void JIT::emit_op_enumerator_get_by_val(const Instruction* currentInstruction)
-{
-    auto bytecode = currentInstruction->as<OpEnumeratorGetByVal>();
-    auto& metadata = bytecode.metadata(m_codeBlock);
-    VirtualRegister dst = bytecode.m_dst;
-    VirtualRegister mode = bytecode.m_mode;
-    VirtualRegister base = bytecode.m_base;
-    VirtualRegister index = bytecode.m_index;
-    VirtualRegister propertyName = bytecode.m_propertyName;
-    VirtualRegister enumerator = bytecode.m_enumerator;
-    ArrayProfile* profile = &metadata.m_arrayProfile;
-
-    JumpList doneCases;
-
-    auto resultGPR = regT0;
-
-    emitGetVirtualRegister(base, regT0);
-    emitGetVirtualRegister(mode, regT2);
-    emitGetVirtualRegister(propertyName, regT1);
-
-    or8(regT2, AbsoluteAddress(&metadata.m_enumeratorMetadata));
-
-    addSlowCase(branchIfNotCell(regT0));
-    // This is always an int32 encoded value.
-    Jump isNotOwnStructureMode = branchTest32(NonZero, regT2, TrustedImm32(JSPropertyNameEnumerator::IndexedMode | JSPropertyNameEnumerator::GenericMode));
-
-    // Check the structure
-    emitGetVirtualRegister(enumerator, regT2);
-    load32(Address(regT0, JSCell::structureIDOffset()), regT3);
-    Jump structureMismatch = branch32(NotEqual, regT3, Address(regT2, JSPropertyNameEnumerator::cachedStructureIDOffset()));
-
-    // Compute the offset.
-    emitGetVirtualRegister(index, regT3);
-    // If index is less than the enumerator's cached inline storage, then it's an inline access
-    Jump outOfLineAccess = branch32(AboveOrEqual, regT3, Address(regT2, JSPropertyNameEnumerator::cachedInlineCapacityOffset()));
-    addPtr(TrustedImm32(JSObject::offsetOfInlineStorage()), regT0);
-    signExtend32ToPtr(regT3, regT3);
-    load64(BaseIndex(regT0, regT3, TimesEight), resultGPR);
-
-    doneCases.append(jump());
-
-    // Otherwise it's out of line
-    outOfLineAccess.link(this);
-    loadPtr(Address(regT0, JSObject::butterflyOffset()), regT0);
-    sub32(Address(regT2, JSPropertyNameEnumerator::cachedInlineCapacityOffset()), regT3);
-    neg32(regT3);
-    signExtend32ToPtr(regT3, regT3);
-    int32_t offsetOfFirstProperty = static_cast<int32_t>(offsetInButterfly(firstOutOfLineOffset)) * sizeof(EncodedJSValue);
-    load64(BaseIndex(regT0, regT3, TimesEight, offsetOfFirstProperty), resultGPR);
-    doneCases.append(jump());
-
-    structureMismatch.link(this);
-    store8(TrustedImm32(JSPropertyNameEnumerator::HasSeenOwnStructureModeStructureMismatch), &metadata.m_enumeratorMetadata);
-
-    isNotOwnStructureMode.link(this);
-    Jump isNotIndexed = branchTest32(Zero, regT2, TrustedImm32(JSPropertyNameEnumerator::IndexedMode));
-    // Replace the string with the index.
-    emitGetVirtualRegister(index, regT1);
-
-    isNotIndexed.link(this);
-    emitArrayProfilingSiteWithCell(regT0, regT2, profile);
-
-    JITGetByValGenerator gen(
-        m_codeBlock, JITType::BaselineJIT, CodeOrigin(m_bytecodeIndex), CallSiteIndex(m_bytecodeIndex), AccessType::GetByVal, RegisterSet::stubUnavailableRegisters(),
-        JSValueRegs(regT0), JSValueRegs(regT1), JSValueRegs(resultGPR), regT2);
-    gen.generateFastPath(*this);
-    if (!JITCode::useDataIC(JITType::BaselineJIT))
-        addSlowCase(gen.slowPathJump());
-    else
-        addSlowCase();
-    m_getByVals.append(gen);
-
-    doneCases.link(this);
-
-    emitValueProfilingSite(metadata, JSValueRegs(resultGPR));
-    emitPutVirtualRegister(dst);
-}
-
-void JIT::emitSlow_op_enumerator_get_by_val(const Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
-{
-    generateGetByValSlowCase(currentInstruction->as<OpEnumeratorGetByVal>(), iter);
-}
-
-template <typename OpcodeType, typename SlowPathFunctionType>
-void JIT::emit_enumerator_has_propertyImpl(const Instruction* currentInstruction, const OpcodeType& bytecode, SlowPathFunctionType generalCase)
-{
-    auto& metadata = bytecode.metadata(m_codeBlock);
-    VirtualRegister dst = bytecode.m_dst;
-    VirtualRegister base = bytecode.m_base;
-    VirtualRegister enumerator = bytecode.m_enumerator;
-    VirtualRegister mode = bytecode.m_mode;
-
-    JumpList slowCases;
-
-    emitGetVirtualRegister(mode, regT0);
-    or8(regT0, AbsoluteAddress(&metadata.m_enumeratorMetadata));
-
-    slowCases.append(branchTest32(Zero, regT0, TrustedImm32(JSPropertyNameEnumerator::OwnStructureMode)));
-
-    emitGetVirtualRegister(base, regT0);
-
-    slowCases.append(branchIfNotCell(regT0));
-
-    emitGetVirtualRegister(enumerator, regT1);
-    load32(Address(regT0, JSCell::structureIDOffset()), regT0);
-    slowCases.append(branch32(NotEqual, regT0, Address(regT1, JSPropertyNameEnumerator::cachedStructureIDOffset())));
-
-    move(TrustedImm64(JSValue::encode(jsBoolean(true))), regT0);
-    emitPutVirtualRegister(dst);
-    Jump done = jump();
-
-    slowCases.link(this);
-
-    JITSlowPathCall slowPathCall(this, currentInstruction, generalCase);
-    slowPathCall.call();
-
-    done.link(this);
-}
-
-void JIT::emit_op_enumerator_in_by_val(const Instruction* currentInstruction)
-{
-    emit_enumerator_has_propertyImpl(currentInstruction, currentInstruction->as<OpEnumeratorInByVal>(), slow_path_enumerator_in_by_val);
-}
-
-void JIT::emit_op_enumerator_has_own_property(const Instruction* currentInstruction)
-{
-    emit_enumerator_has_propertyImpl(currentInstruction, currentInstruction->as<OpEnumeratorHasOwnProperty>(), slow_path_enumerator_has_own_property);
-}
-
</del><span class="cx"> #else // USE(JSVALUE64)
</span><span class="cx"> 
</span><span class="cx"> void JIT::emitWriteBarrier(VirtualRegister owner, VirtualRegister value, WriteBarrierMode mode)
</span></span></pre></div>
<a id="branchessafari612128branchSourceJavaScriptCorejitJITPropertyAccess32_64cpp"></a>
<div class="modfile"><h4>Modified: branches/safari-612.1.28-branch/Source/JavaScriptCore/jit/JITPropertyAccess32_64.cpp (281021 => 281022)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-612.1.28-branch/Source/JavaScriptCore/jit/JITPropertyAccess32_64.cpp     2021-08-13 16:39:44 UTC (rev 281021)
+++ branches/safari-612.1.28-branch/Source/JavaScriptCore/jit/JITPropertyAccess32_64.cpp        2021-08-13 16:50:38 UTC (rev 281022)
</span><span class="lines">@@ -1505,35 +1505,6 @@
</span><span class="cx"> 
</span><span class="cx"> template void JIT::emit_op_put_by_val<OpPutByVal>(const Instruction*);
</span><span class="cx"> 
</span><del>-void JIT::emit_op_enumerator_next(const Instruction* currentInstruction)
-{
-    JITSlowPathCall slowPathCall(this, currentInstruction, slow_path_enumerator_next);
-    slowPathCall.call();
-}
-
-void JIT::emit_op_enumerator_get_by_val(const Instruction* currentInstruction)
-{
-    JITSlowPathCall slowPathCall(this, currentInstruction, slow_path_enumerator_get_by_val);
-    slowPathCall.call();
-}
-
-void JIT::emitSlow_op_enumerator_get_by_val(const Instruction*, Vector<SlowCaseEntry>::iterator&)
-{
-    UNREACHABLE_FOR_PLATFORM();
-}
-
-void JIT::emit_op_enumerator_in_by_val(const Instruction* currentInstruction)
-{
-    JITSlowPathCall slowPathCall(this, currentInstruction, slow_path_enumerator_in_by_val);
-    slowPathCall.call();
-}
-
-void JIT::emit_op_enumerator_has_own_property(const Instruction* currentInstruction)
-{
-    JITSlowPathCall slowPathCall(this, currentInstruction, slow_path_enumerator_has_own_property);
-    slowPathCall.call();
-}
-
</del><span class="cx"> } // namespace JSC
</span><span class="cx"> 
</span><span class="cx"> #endif // USE(JSVALUE32_64)
</span></span></pre></div>
<a id="branchessafari612128branchSourceJavaScriptCorellintLowLevelInterpreterasm"></a>
<div class="modfile"><h4>Modified: branches/safari-612.1.28-branch/Source/JavaScriptCore/llint/LowLevelInterpreter.asm (281021 => 281022)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-612.1.28-branch/Source/JavaScriptCore/llint/LowLevelInterpreter.asm      2021-08-13 16:39:44 UTC (rev 281021)
+++ branches/safari-612.1.28-branch/Source/JavaScriptCore/llint/LowLevelInterpreter.asm 2021-08-13 16:50:38 UTC (rev 281022)
</span><span class="lines">@@ -1992,14 +1992,19 @@
</span><span class="cx"> slowPathOp(create_async_generator)
</span><span class="cx"> slowPathOp(define_accessor_property)
</span><span class="cx"> slowPathOp(define_data_property)
</span><ins>+slowPathOp(enumerator_generic_pname)
+slowPathOp(enumerator_structure_pname)
</ins><span class="cx"> slowPathOp(get_by_val_with_this)
</span><ins>+slowPathOp(get_direct_pname)
+slowPathOp(get_enumerable_length)
</ins><span class="cx"> slowPathOp(get_property_enumerator)
</span><del>-slowPathOp(enumerator_next)
-slowPathOp(enumerator_get_by_val)
-slowPathOp(enumerator_in_by_val)
-slowPathOp(enumerator_has_own_property)
</del><ins>+slowPathOp(has_enumerable_indexed_property)
+slowPathOp(has_enumerable_property)
</ins><span class="cx"> 
</span><span class="cx"> if not JSVALUE64
</span><ins>+    slowPathOp(has_enumerable_structure_property)
+    slowPathOp(has_own_structure_property)
+    slowPathOp(in_structure_property)
</ins><span class="cx">     slowPathOp(get_prototype_of)
</span><span class="cx"> end
</span><span class="cx"> 
</span><span class="lines">@@ -2016,6 +2021,7 @@
</span><span class="cx"> slowPathOp(spread)
</span><span class="cx"> slowPathOp(strcat)
</span><span class="cx"> slowPathOp(throw_static_error)
</span><ins>+slowPathOp(to_index_string)
</ins><span class="cx"> slowPathOp(typeof)
</span><span class="cx"> slowPathOp(typeof_is_object)
</span><span class="cx"> slowPathOp(typeof_is_function)
</span></span></pre></div>
<a id="branchessafari612128branchSourceJavaScriptCorellintLowLevelInterpreter64asm"></a>
<div class="modfile"><h4>Modified: branches/safari-612.1.28-branch/Source/JavaScriptCore/llint/LowLevelInterpreter64.asm (281021 => 281022)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-612.1.28-branch/Source/JavaScriptCore/llint/LowLevelInterpreter64.asm    2021-08-13 16:39:44 UTC (rev 281021)
+++ branches/safari-612.1.28-branch/Source/JavaScriptCore/llint/LowLevelInterpreter64.asm       2021-08-13 16:50:38 UTC (rev 281022)
</span><span class="lines">@@ -3141,6 +3141,34 @@
</span><span class="cx">     dispatch()
</span><span class="cx"> end)
</span><span class="cx"> 
</span><ins>+macro hasStructurePropertyImpl(size, get, dispatch, return, slowPathCall)
+    get(m_base, t0)
+    loadConstantOrVariable(size, t0, t1)
+    btqnz t1, notCellMask, .slowPath
+
+    loadVariable(get, m_enumerator, t0)
+    loadi JSCell::m_structureID[t1], t1
+    bineq t1, JSPropertyNameEnumerator::m_cachedStructureID[t0], .slowPath
+
+    return(ValueTrue)
+
+.slowPath:
+    callSlowPath(slowPathCall)
+    dispatch()
+end
+
+llintOpWithReturn(op_has_enumerable_structure_property, OpHasEnumerableStructureProperty, macro (size, get, dispatch, return)
+    hasStructurePropertyImpl(size, get, dispatch,  return, _slow_path_has_enumerable_structure_property)
+end)
+
+llintOpWithReturn(op_has_own_structure_property, OpHasOwnStructureProperty, macro (size, get, dispatch, return)
+    hasStructurePropertyImpl(size, get, dispatch,  return, _slow_path_has_own_structure_property)
+end)
+
+llintOpWithReturn(op_in_structure_property, OpInStructureProperty, macro (size, get, dispatch, return)
+    hasStructurePropertyImpl(size, get, dispatch,  return, _slow_path_in_structure_property)
+end)
+
</ins><span class="cx"> op(fuzzer_return_early_from_loop_hint, macro ()
</span><span class="cx">     loadp CodeBlock[cfr], t0
</span><span class="cx">     loadp CodeBlock::m_globalObject[t0], t0
</span></span></pre></div>
<a id="branchessafari612128branchSourceJavaScriptCoreruntimeCommonSlowPathscpp"></a>
<div class="modfile"><h4>Modified: branches/safari-612.1.28-branch/Source/JavaScriptCore/runtime/CommonSlowPaths.cpp (281021 => 281022)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-612.1.28-branch/Source/JavaScriptCore/runtime/CommonSlowPaths.cpp        2021-08-13 16:39:44 UTC (rev 281021)
+++ branches/safari-612.1.28-branch/Source/JavaScriptCore/runtime/CommonSlowPaths.cpp   2021-08-13 16:50:38 UTC (rev 281022)
</span><span class="lines">@@ -962,139 +962,163 @@
</span><span class="cx">     RETURN(GET_C(bytecode.m_src).jsValue().toPropertyKeyValue(globalObject));
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-JSC_DEFINE_COMMON_SLOW_PATH(slow_path_get_property_enumerator)
</del><ins>+JSC_DEFINE_COMMON_SLOW_PATH(slow_path_get_enumerable_length)
</ins><span class="cx"> {
</span><span class="cx">     BEGIN();
</span><del>-    auto bytecode = pc->as<OpGetPropertyEnumerator>();
-    JSValue baseValue = GET_C(bytecode.m_base).jsValue();
-    if (baseValue.isUndefinedOrNull())
-        RETURN(vm.emptyPropertyNameEnumerator());
</del><ins>+    auto bytecode = pc->as<OpGetEnumerableLength>();
+    JSValue enumeratorValue = GET_C(bytecode.m_base).jsValue();
+    if (enumeratorValue.isUndefinedOrNull())
+        RETURN(jsNumber(0));
</ins><span class="cx"> 
</span><del>-    JSObject* base = baseValue.toObject(globalObject);
-    CHECK_EXCEPTION();
</del><ins>+    JSPropertyNameEnumerator* enumerator = jsCast<JSPropertyNameEnumerator*>(enumeratorValue.asCell());
</ins><span class="cx"> 
</span><del>-    RETURN(propertyNameEnumerator(globalObject, base));
</del><ins>+    RETURN(jsNumber(enumerator->indexedLength()));
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-JSC_DEFINE_COMMON_SLOW_PATH(slow_path_enumerator_next)
</del><ins>+JSC_DEFINE_COMMON_SLOW_PATH(slow_path_has_enumerable_indexed_property)
</ins><span class="cx"> {
</span><span class="cx">     BEGIN();
</span><del>-    auto bytecode = pc->as<OpEnumeratorNext>();
</del><ins>+    auto bytecode = pc->as<OpHasEnumerableIndexedProperty>();
</ins><span class="cx">     auto& metadata = bytecode.metadata(codeBlock);
</span><del>-    Register& modeRegister = GET(bytecode.m_mode);
-    Register& indexRegister = GET(bytecode.m_index);
-    Register& nameRegister = GET(bytecode.m_propertyName);
</del><ins>+    JSObject* base = GET_C(bytecode.m_base).jsValue().toObject(globalObject);
+    CHECK_EXCEPTION();
+    JSValue property = GET(bytecode.m_property).jsValue();
+    metadata.m_arrayProfile.observeStructure(base->structure(vm));
+    ASSERT(property.isUInt32AsAnyInt());
+    RETURN(jsBoolean(base->hasEnumerableProperty(globalObject, property.asUInt32AsAnyInt())));
+}
</ins><span class="cx"> 
</span><del>-    auto mode = static_cast<JSPropertyNameEnumerator::Mode>(modeRegister.jsValue().asUInt32());
-    uint32_t index = indexRegister.jsValue().asUInt32();
-
-    JSPropertyNameEnumerator* enumerator = jsCast<JSPropertyNameEnumerator*>(GET(bytecode.m_enumerator).jsValue());
-    JSValue baseValue = GET(bytecode.m_base).jsValue();
-    ASSERT(!baseValue.isUndefinedOrNull());
-    JSObject* base = baseValue.toObject(globalObject);
</del><ins>+JSC_DEFINE_COMMON_SLOW_PATH(slow_path_has_enumerable_structure_property)
+{
+    BEGIN();
+    auto bytecode = pc->as<OpHasEnumerableStructureProperty>();
+    JSObject* base = GET_C(bytecode.m_base).jsValue().toObject(globalObject);
</ins><span class="cx">     CHECK_EXCEPTION();
</span><del>-    metadata.m_arrayProfile.observeStructureID(base->structureID());
</del><ins>+    JSValue property = GET(bytecode.m_property).jsValue();
+    RELEASE_ASSERT(property.isString());
+#if USE(JSVALUE32_64)
+    JSPropertyNameEnumerator* enumerator = jsCast<JSPropertyNameEnumerator*>(GET(bytecode.m_enumerator).jsValue().asCell());
+    if (base->structure(vm)->id() == enumerator->cachedStructureID())
+        RETURN(jsBoolean(true));
+#endif
+    JSString* string = asString(property);
+    auto propertyName = string->toIdentifier(globalObject);
+    CHECK_EXCEPTION();
+    RETURN(jsBoolean(base->hasEnumerableProperty(globalObject, propertyName)));
+}
</ins><span class="cx"> 
</span><del>-    JSString* name = enumerator->computeNext(globalObject, base, index, mode);
</del><ins>+JSC_DEFINE_COMMON_SLOW_PATH(slow_path_has_own_structure_property)
+{
+    BEGIN();
+    auto bytecode = pc->as<OpHasOwnStructureProperty>();
+    JSValue base = GET_C(bytecode.m_base).jsValue();
+
+#if USE(JSVALUE32_64)
+    JSPropertyNameEnumerator* enumerator = jsCast<JSPropertyNameEnumerator*>(GET(bytecode.m_enumerator).jsValue().asCell());
+    if (base.isCell() && base.asCell()->structure(vm)->id() == enumerator->cachedStructureID())
+        RETURN(jsBoolean(true));
+#endif
+
+    JSValue property = GET(bytecode.m_property).jsValue();
+    RELEASE_ASSERT(property.isString());
+    JSString* string = asString(property);
+    auto propertyName = string->toIdentifier(globalObject);
</ins><span class="cx">     CHECK_EXCEPTION();
</span><span class="cx"> 
</span><del>-    metadata.m_enumeratorMetadata |= static_cast<uint8_t>(mode);
-    modeRegister = jsNumber(static_cast<uint8_t>(mode));
-    indexRegister = jsNumber(index);
-    nameRegister = name ? name : jsNull();
-    END();
</del><ins>+    RETURN(jsBoolean(objectPrototypeHasOwnProperty(globalObject, base, propertyName)));
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-JSC_DEFINE_COMMON_SLOW_PATH(slow_path_enumerator_get_by_val)
</del><ins>+JSC_DEFINE_COMMON_SLOW_PATH(slow_path_in_structure_property)
</ins><span class="cx"> {
</span><span class="cx">     BEGIN();
</span><del>-    auto bytecode = pc->as<OpEnumeratorGetByVal>();
-    JSValue baseValue = GET_C(bytecode.m_base).jsValue();
-    auto& metadata = bytecode.metadata(codeBlock);
-    auto mode = static_cast<JSPropertyNameEnumerator::Mode>(GET(bytecode.m_mode).jsValue().asUInt32());
-    metadata.m_enumeratorMetadata |= static_cast<uint8_t>(mode);
</del><ins>+    auto bytecode = pc->as<OpInStructureProperty>();
+    JSValue base = GET_C(bytecode.m_base).jsValue();
+#if USE(JSVALUE32_64)
+    JSPropertyNameEnumerator* enumerator = jsCast<JSPropertyNameEnumerator*>(GET(bytecode.m_enumerator).jsValue().asCell());
+    if (base.isCell() && base.asCell()->structure(vm)->id() == enumerator->cachedStructureID())
+        RETURN(jsBoolean(true));
+#endif
+    JSValue property = GET(bytecode.m_property).jsValue();
+    RELEASE_ASSERT(property.isString());
+    RETURN(jsBoolean(CommonSlowPaths::opInByVal(globalObject, base, asString(property))));
+}
</ins><span class="cx"> 
</span><del>-    JSPropertyNameEnumerator* enumerator = jsCast<JSPropertyNameEnumerator*>(GET(bytecode.m_enumerator).jsValue());
-    unsigned index = GET(bytecode.m_index).jsValue().asInt32();
-    switch (mode) {
-    case JSPropertyNameEnumerator::IndexedMode: {
-        if (LIKELY(baseValue.isCell()))
-            metadata.m_arrayProfile.observeStructureID(baseValue.asCell()->structureID());
-        RETURN_PROFILED(baseValue.get(globalObject, static_cast<unsigned>(index)));
-    }
-    case JSPropertyNameEnumerator::OwnStructureMode: {
-        if (LIKELY(baseValue.isCell()) && baseValue.asCell()->structureID() == enumerator->cachedStructureID()) {
-            // We'll only match the structure ID if the base is an object.
-            ASSERT(index < enumerator->endStructurePropertyIndex());
-            RETURN_PROFILED(baseValue.getObject()->getDirect(index < enumerator->cachedInlineCapacity() ? index : index - enumerator->cachedInlineCapacity() + firstOutOfLineOffset));
-        } else
-            metadata.m_enumeratorMetadata |= static_cast<uint8_t>(JSPropertyNameEnumerator::HasSeenOwnStructureModeStructureMismatch);
-        FALLTHROUGH;
-    }
</del><ins>+JSC_DEFINE_COMMON_SLOW_PATH(slow_path_has_enumerable_property)
+{
+    BEGIN();
+    auto bytecode = pc->as<OpHasEnumerableProperty>();
+    JSObject* base = GET_C(bytecode.m_base).jsValue().toObject(globalObject);
+    CHECK_EXCEPTION();
+    JSValue property = GET(bytecode.m_property).jsValue();
+    ASSERT(property.isString());
+    JSString* string = asString(property);
+    auto propertyName = string->toIdentifier(globalObject);
+    CHECK_EXCEPTION();
+    RETURN(jsBoolean(base->hasEnumerableProperty(globalObject, propertyName)));
+}
</ins><span class="cx"> 
</span><del>-    case JSPropertyNameEnumerator::GenericMode: {
-        if (baseValue.isCell() && mode != JSPropertyNameEnumerator::OwnStructureMode)
-            metadata.m_arrayProfile.observeStructureID(baseValue.asCell()->structureID());
-        JSString* string = asString(GET(bytecode.m_propertyName).jsValue());
-        auto propertyName = string->toIdentifier(globalObject);
-        CHECK_EXCEPTION();
-        RETURN_PROFILED(baseValue.get(globalObject, propertyName));
-    }
-
-    default:
-        RELEASE_ASSERT_NOT_REACHED();
-        break;
-    };
-    RELEASE_ASSERT_NOT_REACHED();
</del><ins>+JSC_DEFINE_COMMON_SLOW_PATH(slow_path_get_direct_pname)
+{
+    BEGIN();
+    auto bytecode = pc->as<OpGetDirectPname>();
+    JSValue baseValue = GET_C(bytecode.m_base).jsValue();
+    JSValue property = GET(bytecode.m_property).jsValue();
+    ASSERT(property.isString());
+    JSString* string = asString(property);
+    auto propertyName = string->toIdentifier(globalObject);
+    CHECK_EXCEPTION();
+    RETURN(baseValue.get(globalObject, propertyName));
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-JSC_DEFINE_COMMON_SLOW_PATH(slow_path_enumerator_in_by_val)
</del><ins>+JSC_DEFINE_COMMON_SLOW_PATH(slow_path_get_property_enumerator)
</ins><span class="cx"> {
</span><span class="cx">     BEGIN();
</span><del>-    auto bytecode = pc->as<OpEnumeratorInByVal>();
</del><ins>+    auto bytecode = pc->as<OpGetPropertyEnumerator>();
</ins><span class="cx">     JSValue baseValue = GET_C(bytecode.m_base).jsValue();
</span><del>-    auto& metadata = bytecode.metadata(codeBlock);
-    auto mode = static_cast<JSPropertyNameEnumerator::Mode>(GET(bytecode.m_mode).jsValue().asUInt32());
-    metadata.m_enumeratorMetadata |= static_cast<uint8_t>(mode);
</del><ins>+    if (baseValue.isUndefinedOrNull())
+        RETURN(vm.emptyPropertyNameEnumerator());
</ins><span class="cx"> 
</span><ins>+    JSObject* base = baseValue.toObject(globalObject);
</ins><span class="cx">     CHECK_EXCEPTION();
</span><del>-    JSPropertyNameEnumerator* enumerator = jsCast<JSPropertyNameEnumerator*>(GET(bytecode.m_enumerator).jsValue());
-    if (auto* base = baseValue.getObject()) {
-        if (mode == JSPropertyNameEnumerator::OwnStructureMode && base->structureID() == enumerator->cachedStructureID())
-            RETURN(jsBoolean(true));
</del><span class="cx"> 
</span><del>-        if (mode == JSPropertyNameEnumerator::IndexedMode)
-            RETURN(jsBoolean(base->hasProperty(globalObject, GET(bytecode.m_index).jsValue().asUInt32())));
-    }
-
-    JSString* string = asString(GET(bytecode.m_propertyName).jsValue());
-    RETURN(jsBoolean(CommonSlowPaths::opInByVal(globalObject, baseValue, string, &metadata.m_arrayProfile)));
</del><ins>+    RETURN(propertyNameEnumerator(globalObject, base));
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-JSC_DEFINE_COMMON_SLOW_PATH(slow_path_enumerator_has_own_property)
</del><ins>+JSC_DEFINE_COMMON_SLOW_PATH(slow_path_enumerator_structure_pname)
</ins><span class="cx"> {
</span><span class="cx">     BEGIN();
</span><del>-    auto bytecode = pc->as<OpEnumeratorHasOwnProperty>();
-    JSValue baseValue = GET_C(bytecode.m_base).jsValue();
-    auto& metadata = bytecode.metadata(codeBlock);
-    auto mode = static_cast<JSPropertyNameEnumerator::Mode>(GET(bytecode.m_mode).jsValue().asUInt32());
-    metadata.m_enumeratorMetadata |= static_cast<uint8_t>(mode);
</del><ins>+    auto bytecode = pc->as<OpEnumeratorStructurePname>();
+    JSPropertyNameEnumerator* enumerator = jsCast<JSPropertyNameEnumerator*>(GET(bytecode.m_enumerator).jsValue().asCell());
+    uint32_t index = GET(bytecode.m_index).jsValue().asUInt32AsAnyInt();
</ins><span class="cx"> 
</span><del>-    JSPropertyNameEnumerator* enumerator = jsCast<JSPropertyNameEnumerator*>(GET(bytecode.m_enumerator).jsValue());
-    if (auto* base = baseValue.getObject()) {
-        if (mode == JSPropertyNameEnumerator::OwnStructureMode && base->structureID() == enumerator->cachedStructureID())
-            RETURN(jsBoolean(true));
</del><ins>+    JSString* propertyName = nullptr;
+    if (index < enumerator->endStructurePropertyIndex())
+        propertyName = enumerator->propertyNameAtIndex(index);
+    RETURN(propertyName ? propertyName : jsNull());
+}
</ins><span class="cx"> 
</span><del>-        if (mode == JSPropertyNameEnumerator::IndexedMode)
-            RETURN(jsBoolean(base->hasOwnProperty(globalObject, GET(bytecode.m_index).jsValue().asUInt32())));
-    }
</del><ins>+JSC_DEFINE_COMMON_SLOW_PATH(slow_path_enumerator_generic_pname)
+{
+    BEGIN();
+    auto bytecode = pc->as<OpEnumeratorGenericPname>();
+    JSPropertyNameEnumerator* enumerator = jsCast<JSPropertyNameEnumerator*>(GET(bytecode.m_enumerator).jsValue().asCell());
+    uint32_t index = GET(bytecode.m_index).jsValue().asUInt32AsAnyInt();
</ins><span class="cx"> 
</span><del>-    JSString* string = asString(GET(bytecode.m_propertyName).jsValue());
-    auto propertyName = string->toIdentifier(globalObject);
-    CHECK_EXCEPTION();
-    RETURN(jsBoolean(objectPrototypeHasOwnProperty(globalObject, baseValue, propertyName)));
</del><ins>+    JSString* propertyName = nullptr;
+    if (enumerator->endStructurePropertyIndex() <= index && index < enumerator->endGenericPropertyIndex())
+        propertyName = enumerator->propertyNameAtIndex(index);
+    RETURN(propertyName ? propertyName : jsNull());
</ins><span class="cx"> }
</span><span class="cx"> 
</span><ins>+JSC_DEFINE_COMMON_SLOW_PATH(slow_path_to_index_string)
+{
+    BEGIN();
+    auto bytecode = pc->as<OpToIndexString>();
+    JSValue indexValue = GET(bytecode.m_index).jsValue();
+    ASSERT(indexValue.isUInt32AsAnyInt());
+    RETURN(jsString(vm, Identifier::from(vm, indexValue.asUInt32AsAnyInt()).string()));
+}
+
</ins><span class="cx"> JSC_DEFINE_COMMON_SLOW_PATH(slow_path_profile_type_clear_log)
</span><span class="cx"> {
</span><span class="cx">     BEGIN();
</span></span></pre></div>
<a id="branchessafari612128branchSourceJavaScriptCoreruntimeCommonSlowPathsh"></a>
<div class="modfile"><h4>Modified: branches/safari-612.1.28-branch/Source/JavaScriptCore/runtime/CommonSlowPaths.h (281021 => 281022)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-612.1.28-branch/Source/JavaScriptCore/runtime/CommonSlowPaths.h  2021-08-13 16:39:44 UTC (rev 281021)
+++ branches/safari-612.1.28-branch/Source/JavaScriptCore/runtime/CommonSlowPaths.h     2021-08-13 16:50:38 UTC (rev 281022)
</span><span class="lines">@@ -254,11 +254,17 @@
</span><span class="cx"> JSC_DECLARE_COMMON_SLOW_PATH(slow_path_strcat);
</span><span class="cx"> JSC_DECLARE_COMMON_SLOW_PATH(slow_path_to_primitive);
</span><span class="cx"> JSC_DECLARE_COMMON_SLOW_PATH(slow_path_to_property_key);
</span><ins>+JSC_DECLARE_COMMON_SLOW_PATH(slow_path_get_enumerable_length);
+JSC_DECLARE_COMMON_SLOW_PATH(slow_path_has_enumerable_indexed_property);
+JSC_DECLARE_COMMON_SLOW_PATH(slow_path_has_enumerable_structure_property);
+JSC_DECLARE_COMMON_SLOW_PATH(slow_path_has_enumerable_property);
+JSC_DECLARE_COMMON_SLOW_PATH(slow_path_has_own_structure_property);
+JSC_DECLARE_COMMON_SLOW_PATH(slow_path_in_structure_property);
+JSC_DECLARE_COMMON_SLOW_PATH(slow_path_get_direct_pname);
</ins><span class="cx"> JSC_DECLARE_COMMON_SLOW_PATH(slow_path_get_property_enumerator);
</span><del>-JSC_DECLARE_COMMON_SLOW_PATH(slow_path_enumerator_next);
-JSC_DECLARE_COMMON_SLOW_PATH(slow_path_enumerator_get_by_val);
-JSC_DECLARE_COMMON_SLOW_PATH(slow_path_enumerator_in_by_val);
-JSC_DECLARE_COMMON_SLOW_PATH(slow_path_enumerator_has_own_property);
</del><ins>+JSC_DECLARE_COMMON_SLOW_PATH(slow_path_enumerator_structure_pname);
+JSC_DECLARE_COMMON_SLOW_PATH(slow_path_enumerator_generic_pname);
+JSC_DECLARE_COMMON_SLOW_PATH(slow_path_to_index_string);
</ins><span class="cx"> JSC_DECLARE_COMMON_SLOW_PATH(slow_path_profile_type_clear_log);
</span><span class="cx"> JSC_DECLARE_COMMON_SLOW_PATH(slow_path_unreachable);
</span><span class="cx"> JSC_DECLARE_COMMON_SLOW_PATH(slow_path_create_lexical_environment);
</span></span></pre></div>
<a id="branchessafari612128branchSourceJavaScriptCoreruntimeFileBasedFuzzerAgentcpp"></a>
<div class="modfile"><h4>Modified: branches/safari-612.1.28-branch/Source/JavaScriptCore/runtime/FileBasedFuzzerAgent.cpp (281021 => 281022)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-612.1.28-branch/Source/JavaScriptCore/runtime/FileBasedFuzzerAgent.cpp   2021-08-13 16:39:44 UTC (rev 281021)
+++ branches/safari-612.1.28-branch/Source/JavaScriptCore/runtime/FileBasedFuzzerAgent.cpp      2021-08-13 16:50:38 UTC (rev 281022)
</span><span class="lines">@@ -90,6 +90,7 @@
</span><span class="cx">         break;
</span><span class="cx"> 
</span><span class="cx">     case op_get_by_val_with_this:
</span><ins>+    case op_get_direct_pname:
</ins><span class="cx">     case op_construct:
</span><span class="cx">     case op_construct_varargs:
</span><span class="cx">     case op_call_varargs:
</span></span></pre></div>
<a id="branchessafari612128branchSourceJavaScriptCoreruntimeFileBasedFuzzerAgentBasecpp"></a>
<div class="modfile"><h4>Modified: branches/safari-612.1.28-branch/Source/JavaScriptCore/runtime/FileBasedFuzzerAgentBase.cpp (281021 => 281022)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-612.1.28-branch/Source/JavaScriptCore/runtime/FileBasedFuzzerAgentBase.cpp       2021-08-13 16:39:44 UTC (rev 281021)
+++ branches/safari-612.1.28-branch/Source/JavaScriptCore/runtime/FileBasedFuzzerAgentBase.cpp  2021-08-13 16:50:38 UTC (rev 281022)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> /*
</span><del>- * Copyright (C) 2019-2021 Apple Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2019 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">@@ -52,7 +52,7 @@
</span><span class="cx"> {
</span><span class="cx">     if (opcodeId == op_call_varargs || opcodeId == op_call_eval || opcodeId == op_tail_call || opcodeId == op_tail_call_varargs)
</span><span class="cx">         return op_call;
</span><del>-    if (opcodeId == op_enumerator_get_by_val || opcodeId == op_get_by_val_with_this)
</del><ins>+    if (opcodeId == op_get_direct_pname || opcodeId == op_get_by_val_with_this)
</ins><span class="cx">         return op_get_by_val;
</span><span class="cx">     if (opcodeId == op_construct_varargs)
</span><span class="cx">         return op_construct;
</span></span></pre></div>
<a id="branchessafari612128branchSourceJavaScriptCoreruntimeJSGlobalObjectcpp"></a>
<div class="modfile"><h4>Modified: branches/safari-612.1.28-branch/Source/JavaScriptCore/runtime/JSGlobalObject.cpp (281021 => 281022)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-612.1.28-branch/Source/JavaScriptCore/runtime/JSGlobalObject.cpp 2021-08-13 16:39:44 UTC (rev 281021)
+++ branches/safari-612.1.28-branch/Source/JavaScriptCore/runtime/JSGlobalObject.cpp    2021-08-13 16:50:38 UTC (rev 281022)
</span><span class="lines">@@ -1461,10 +1461,6 @@
</span><span class="cx">         });
</span><span class="cx"> #endif
</span><span class="cx"> 
</span><del>-    m_linkTimeConstants[static_cast<unsigned>(LinkTimeConstant::emptyPropertyNameEnumerator)].initLater([] (const Initializer<JSCell>& init) {
-        init.set(init.vm.emptyPropertyNameEnumerator());
-    });
-
</del><span class="cx">     if (Options::exposeProfilersOnGlobalObject()) {
</span><span class="cx"> #if ENABLE(SAMPLING_PROFILER)
</span><span class="cx">         putDirectWithoutTransition(vm, Identifier::fromString(vm, "__enableSamplingProfiler"), JSFunction::create(vm, this, 1, String(), enableSamplingProfiler), PropertyAttribute::DontEnum | PropertyAttribute::DontDelete | PropertyAttribute::ReadOnly);
</span></span></pre></div>
<a id="branchessafari612128branchSourceJavaScriptCoreruntimeJSPropertyNameEnumeratorcpp"></a>
<div class="modfile"><h4>Modified: branches/safari-612.1.28-branch/Source/JavaScriptCore/runtime/JSPropertyNameEnumerator.cpp (281021 => 281022)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-612.1.28-branch/Source/JavaScriptCore/runtime/JSPropertyNameEnumerator.cpp       2021-08-13 16:39:44 UTC (rev 281021)
+++ branches/safari-612.1.28-branch/Source/JavaScriptCore/runtime/JSPropertyNameEnumerator.cpp  2021-08-13 16:50:38 UTC (rev 281022)
</span><span class="lines">@@ -56,12 +56,6 @@
</span><span class="cx">     , m_endGenericPropertyIndex(propertyNamesSize)
</span><span class="cx">     , m_cachedInlineCapacity(structure ? structure->inlineCapacity() : 0)
</span><span class="cx"> {
</span><del>-    if (m_indexedLength)
-        m_modeSet |= JSPropertyNameEnumerator::IndexedMode;
-    if (m_endStructurePropertyIndex)
-        m_modeSet |= JSPropertyNameEnumerator::OwnStructureMode;
-    if (m_endGenericPropertyIndex - m_endStructurePropertyIndex)
-        m_modeSet |= JSPropertyNameEnumerator::GenericMode;
</del><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void JSPropertyNameEnumerator::finishCreation(VM& vm, RefPtr<PropertyNameArrayData>&& identifiers)
</span><span class="lines">@@ -154,70 +148,4 @@
</span><span class="cx">     }
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-JSString* JSPropertyNameEnumerator::computeNext(JSGlobalObject* globalObject, JSObject* base, uint32_t& index, Mode& mode, bool shouldAllocateIndexedNameString)
-{
-    VM& vm = globalObject->vm();
-    auto scope = DECLARE_THROW_SCOPE(vm);
-
-    ASSERT(indexedLength() || sizeOfPropertyNames());
-
-    index++;
-    switch (mode) {
-    case InitMode: {
-        mode = IndexedMode;
-        index = 0;
-        FALLTHROUGH;
-    }
-
-    case JSPropertyNameEnumerator::IndexedMode: {
-        while (index < indexedLength() && !base->hasEnumerableProperty(globalObject, index)) {
-            RETURN_IF_EXCEPTION(scope, nullptr);
-            index++;
-        }
-        scope.assertNoException();
-
-        if (index < indexedLength())
-            return shouldAllocateIndexedNameString ? jsString(vm, Identifier::from(vm, index).string()) : nullptr;
-
-        if (!sizeOfPropertyNames())
-            return nullptr;
-
-        mode = OwnStructureMode;
-        index = 0;
-        FALLTHROUGH;
-    }
-
-    case JSPropertyNameEnumerator::OwnStructureMode:
-    case JSPropertyNameEnumerator::GenericMode: {
-        JSString* name = nullptr;
-        while (true) {
-            if (index >= sizeOfPropertyNames())
-                break;
-            name = propertyNameAtIndex(index);
-            if (!name)
-                break;
-            if (index < endStructurePropertyIndex() && base->structureID() == cachedStructureID())
-                break;
-            auto id = Identifier::fromString(vm, name->value(globalObject));
-            RETURN_IF_EXCEPTION(scope, nullptr);
-            if (base->hasEnumerableProperty(globalObject, id))
-                break;
-            RETURN_IF_EXCEPTION(scope, nullptr);
-            name = nullptr;
-            index++;
-        }
-        scope.assertNoException();
-
-        if (index >= endStructurePropertyIndex() && index < sizeOfPropertyNames())
-            mode = GenericMode;
-        return name;
-    }
-
-    default:
-        break;
-    }
-    RELEASE_ASSERT_NOT_REACHED();
-    return nullptr;
-}
-
</del><span class="cx"> } // namespace JSC
</span></span></pre></div>
<a id="branchessafari612128branchSourceJavaScriptCoreruntimeJSPropertyNameEnumeratorh"></a>
<div class="modfile"><h4>Modified: branches/safari-612.1.28-branch/Source/JavaScriptCore/runtime/JSPropertyNameEnumerator.h (281021 => 281022)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-612.1.28-branch/Source/JavaScriptCore/runtime/JSPropertyNameEnumerator.h 2021-08-13 16:39:44 UTC (rev 281021)
+++ branches/safari-612.1.28-branch/Source/JavaScriptCore/runtime/JSPropertyNameEnumerator.h    2021-08-13 16:50:38 UTC (rev 281022)
</span><span class="lines">@@ -28,7 +28,7 @@
</span><span class="cx"> #include "JSCast.h"
</span><span class="cx"> #include "Operations.h"
</span><span class="cx"> #include "PropertyNameArray.h"
</span><del>-#include "StructureChain.h"
</del><ins>+#include "Structure.h"
</ins><span class="cx"> 
</span><span class="cx"> namespace JSC {
</span><span class="cx"> 
</span><span class="lines">@@ -37,17 +37,6 @@
</span><span class="cx">     using Base = JSCell;
</span><span class="cx">     static constexpr unsigned StructureFlags = Base::StructureFlags | StructureIsImmortal;
</span><span class="cx"> 
</span><del>-    enum Mode : uint8_t {
-        InitMode = 0,
-        IndexedMode = 1 << 0,
-        OwnStructureMode = 1 << 1,
-        GenericMode = 1 << 2,
-        // Profiling Only
-        HasSeenOwnStructureModeStructureMismatch = 1 << 3,
-    };
-
-    static constexpr uint8_t enumerationModeMask = (GenericMode << 1) - 1;
-
</del><span class="cx">     template<typename CellType, SubspaceAccess mode>
</span><span class="cx">     static IsoSubspace* subspaceFor(VM& vm)
</span><span class="cx">     {
</span><span class="lines">@@ -85,20 +74,16 @@
</span><span class="cx">     uint32_t endGenericPropertyIndex() const { return m_endGenericPropertyIndex; }
</span><span class="cx">     uint32_t cachedInlineCapacity() const { return m_cachedInlineCapacity; }
</span><span class="cx">     uint32_t sizeOfPropertyNames() const { return endGenericPropertyIndex(); }
</span><del>-    uint32_t modeSet() const { return m_modeSet; }
</del><span class="cx">     static ptrdiff_t cachedStructureIDOffset() { return OBJECT_OFFSETOF(JSPropertyNameEnumerator, m_cachedStructureID); }
</span><span class="cx">     static ptrdiff_t indexedLengthOffset() { return OBJECT_OFFSETOF(JSPropertyNameEnumerator, m_indexedLength); }
</span><span class="cx">     static ptrdiff_t endStructurePropertyIndexOffset() { return OBJECT_OFFSETOF(JSPropertyNameEnumerator, m_endStructurePropertyIndex); }
</span><span class="cx">     static ptrdiff_t endGenericPropertyIndexOffset() { return OBJECT_OFFSETOF(JSPropertyNameEnumerator, m_endGenericPropertyIndex); }
</span><span class="cx">     static ptrdiff_t cachedInlineCapacityOffset() { return OBJECT_OFFSETOF(JSPropertyNameEnumerator, m_cachedInlineCapacity); }
</span><del>-    static ptrdiff_t modeSetOffset() { return OBJECT_OFFSETOF(JSPropertyNameEnumerator, m_modeSet); }
</del><span class="cx">     static ptrdiff_t cachedPropertyNamesVectorOffset()
</span><span class="cx">     {
</span><span class="cx">         return OBJECT_OFFSETOF(JSPropertyNameEnumerator, m_propertyNames);
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    JSString* computeNext(JSGlobalObject*, JSObject* base, uint32_t& currentIndex, Mode&, bool shouldAllocateIndexedNameString = true);
-
</del><span class="cx">     DECLARE_VISIT_CHILDREN;
</span><span class="cx"> 
</span><span class="cx"> private:
</span><span class="lines">@@ -114,7 +99,6 @@
</span><span class="cx">     uint32_t m_endStructurePropertyIndex;
</span><span class="cx">     uint32_t m_endGenericPropertyIndex;
</span><span class="cx">     uint32_t m_cachedInlineCapacity;
</span><del>-    uint32_t m_modeSet { 0 };
</del><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> void getEnumerablePropertyNames(JSGlobalObject*, JSObject*, PropertyNameArray&, uint32_t& indexedLength, uint32_t& structurePropertyCount);
</span><span class="lines">@@ -150,10 +134,7 @@
</span><span class="cx">         numberStructureProperties = 0;
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    if (!indexedLength && !propertyNames.size())
-        enumerator = vm.emptyPropertyNameEnumerator();
-    else
-        enumerator = JSPropertyNameEnumerator::create(vm, structureAfterGettingPropertyNames, indexedLength, numberStructureProperties, WTFMove(propertyNames));
</del><ins>+    enumerator = JSPropertyNameEnumerator::create(vm, structureAfterGettingPropertyNames, indexedLength, numberStructureProperties, WTFMove(propertyNames));
</ins><span class="cx">     if (!indexedLength && successfullyNormalizedChain && structureAfterGettingPropertyNames == structure) {
</span><span class="cx">         enumerator->setCachedPrototypeChain(vm, structure->prototypeChain(globalObject, base));
</span><span class="cx">         if (structure->canCachePropertyNameEnumerator(vm))
</span><span class="lines">@@ -162,6 +143,4 @@
</span><span class="cx">     return enumerator;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-using EnumeratorMetadata = std::underlying_type_t<JSPropertyNameEnumerator::Mode>;
-
</del><span class="cx"> } // namespace JSC
</span></span></pre></div>
<a id="branchessafari612128branchSourceJavaScriptCoreruntimePredictionFileCreatingFuzzerAgentcpp"></a>
<div class="modfile"><h4>Modified: branches/safari-612.1.28-branch/Source/JavaScriptCore/runtime/PredictionFileCreatingFuzzerAgent.cpp (281021 => 281022)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-612.1.28-branch/Source/JavaScriptCore/runtime/PredictionFileCreatingFuzzerAgent.cpp      2021-08-13 16:39:44 UTC (rev 281021)
+++ branches/safari-612.1.28-branch/Source/JavaScriptCore/runtime/PredictionFileCreatingFuzzerAgent.cpp 2021-08-13 16:50:38 UTC (rev 281022)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> /*
</span><del>- * Copyright (C) 2019-2021 Apple Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2019 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">@@ -52,7 +52,7 @@
</span><span class="cx">     case op_get_by_id:
</span><span class="cx">     case op_get_by_id_with_this:
</span><span class="cx">     case op_get_by_val_with_this:
</span><del>-    case op_enumerator_get_by_val:
</del><ins>+    case op_get_direct_pname:
</ins><span class="cx">     case op_construct:
</span><span class="cx">     case op_construct_varargs:
</span><span class="cx">     case op_call:
</span></span></pre>
</div>
</div>

</body>
</html>