<!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>[282478] trunk/Source/JavaScriptCore</title>
</head>
<body>

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

<h3>Log Message</h3>
<pre>Move some profiling to UnlinkedCodeBlock
https://bugs.webkit.org/show_bug.cgi?id=230078
<rdar://problem/82947571>

Reviewed by Yusuke Suzuki.

This patch moves ValueProfiles and ArrayProfiles for non-call opcodes into
UnlinkedCodeBlock. This way, the data is shared between the linked CodeBlocks
of the same UnlinkedCodeBlock. The profiling bet here is that when the same code
runs in a different global object, it largely runs in the same way. We've made
this same bet in other ways with our profiling, and it largely makes sense
to do for ValueProfile and ArrayProfile since they both hold global object
independent data.

Because ArrayProfiles are now shared between CodeBlocks, the existing m_usesOriginalArrayStructures
bit is slightly harder to track now, since the ArrayProfile may see inputs from a different
global object, an array may be an original array in one lexical global object,
but not another. So we now track when an ArrayProfile sees a different global
object than the lexical global object, and when we observe exits in the DFG,
we propagate that bit to the m_usesOriginalArrayStructures bit.

This patch also makes it so we no longer hold the CodeBlock lock when
processing ValueProfiles and ArrayProfiles. We now allow multiple compiler
threads to race against each other when updating these profiles. This is fine.
It may end up with incomplete data in the profiles, but it won't corrupt them.

This patch also makes it so we finalized visited UnlinkedCodeBlocks to finalize
their value profiles. We no longer do that work inside CodeBlock for the
ValueProfiles that UnlinkedCodeBlock owns. This also means that we have to
WriteBarrier UnlinkedCodeBlock when executing in the LLInt, Baseline, and
other areas, such as OSR exit, and in the GC when a CodeBlock was executing.
That way we're guaranteed to visit the UnlinkedCodeBlock, add it to the
visited set, and then finalize it at the end of GC.

This patch also makes it so that inside CodeBlock::finishCreation, we finish
linking before we do anything that can throw an exception. It's not valid to
finalize a CodeBlock that isn't linked.

This was measured as a 0.5-1% speedup on Speedometer2.

* bytecode/ArrayProfile.cpp:
(JSC::ArrayProfile::computeUpdatedPrediction):
(JSC::ArrayProfile::briefDescription):
(JSC::ArrayProfile::briefDescriptionWithoutUpdating):
* bytecode/ArrayProfile.h:
(JSC::ArrayProfile::ArrayProfile):
(JSC::ArrayProfile::observedArrayModes const):
(JSC::ArrayProfile::mayInterceptIndexedAccesses const):
(JSC::ArrayProfile::mayStoreToHole const):
(JSC::ArrayProfile::outOfBounds const):
(JSC::ArrayProfile::usesOriginalArrayStructures const):
(JSC::ArrayProfile::setDoesNotUseOriginalArrayStructures):
(JSC::ArrayProfile::observedDifferentGlobalObject const):
* bytecode/BytecodeList.rb:
* bytecode/BytecodeOperandsForCheckpoint.h:
(JSC::valueProfileForImpl):
* bytecode/CodeBlock.cpp:
(JSC::CodeBlock::finishCreation):
(JSC::CodeBlock::setConstantRegisters):
(JSC::CodeBlock::initializeTemplateObjects):
(JSC::CodeBlock::setNumParameters):
(JSC::CodeBlock::visitChildren):
(JSC::CodeBlock::finalizeUnconditionally):
(JSC::CodeBlock::getArrayProfile):
(JSC::CodeBlock::updateAllValueProfilePredictionsAndCountLiveness):
(JSC::CodeBlock::updateAllArrayPredictions):
(JSC::CodeBlock::tryGetValueProfileForBytecodeIndex):
(JSC::CodeBlock::valueProfilePredictionForBytecodeIndex):
* bytecode/CodeBlock.h:
(JSC::CodeBlock::offsetOfUnlinkedCodeBlock):
(JSC::CodeBlock::numberOfArgumentValueProfiles):
(JSC::CodeBlock::valueProfileForArgument):
(JSC::CodeBlock::metadata):
* bytecode/CodeBlockInlines.h:
(JSC::CodeBlock::forEachValueProfile):
(JSC::CodeBlock::forEachArrayProfile):
* bytecode/DFGExitProfile.cpp:
(JSC::DFG::ExitProfile::hasAnyExitsAt const):
* bytecode/DFGExitProfile.h:
* bytecode/GetByIdMetadata.h:
(JSC::GetByIdModeMetadata::setArrayLengthMode):
* bytecode/LazyOperandValueProfile.cpp:
(JSC::CompressedLazyOperandValueProfileHolder::computeUpdatedPredictions):
(JSC::LazyOperandValueProfileParser::prediction const):
* bytecode/MetadataTable.cpp:
(JSC::DeallocTable::withOpcodeType):
* bytecode/MetadataTable.h:
(JSC::MetadataTable::get):
(JSC::MetadataTable::forEach):
(JSC::MetadataTable::getWithoutAligning):
(JSC::MetadataTable::getImpl): Deleted.
* bytecode/Opcode.h:
* bytecode/UnlinkedCodeBlock.cpp:
(JSC::UnlinkedCodeBlock::visitChildrenImpl):
(JSC::UnlinkedCodeBlock::allocateSharedProfiles):
(JSC::UnlinkedCodeBlock::finalizeUnconditionally):
* bytecode/UnlinkedCodeBlock.h:
(JSC::UnlinkedCodeBlock::hasAnyExitsAt const):
(JSC::UnlinkedCodeBlock::hasAnyExitsAt):
(JSC::UnlinkedCodeBlock::valueProfile):
(JSC::UnlinkedCodeBlock::arrayProfile):
(JSC::UnlinkedCodeBlock::numValueProfiles const):
(JSC::UnlinkedCodeBlock::numArrayProfiles const):
* bytecode/UnlinkedCodeBlockGenerator.cpp:
(JSC::UnlinkedCodeBlockGenerator::finalize):
* bytecode/UnlinkedMetadataTable.cpp:
(JSC::UnlinkedMetadataTable::finalize):
* bytecode/UnlinkedMetadataTable.h:
(JSC::UnlinkedMetadataTable::isFinalized):
(JSC::UnlinkedMetadataTable::hasMetadata):
* bytecode/UnlinkedMetadataTableInlines.h:
(JSC::UnlinkedMetadataTable::numEntries):
* bytecode/ValueProfile.h:
(JSC::ValueProfileBase::ValueProfileBase):
(JSC::ValueProfileBase::clearBuckets):
(JSC::ValueProfileBase::briefDescription):
(JSC::ValueProfileBase::computeUpdatedPrediction):
(JSC::ValueProfile::offsetOfFirstBucket):
(JSC::ValueProfileBase::classInfo const): Deleted.
* dfg/DFGArrayMode.cpp:
(JSC::DFG::ArrayMode::fromObserved):
* dfg/DFGArrayMode.h:
(JSC::DFG::ArrayMode::withSpeculationFromProfile const):
(JSC::DFG::ArrayMode::withProfile const):
* dfg/DFGByteCodeParser.cpp:
(JSC::DFG::ByteCodeParser::getPredictionWithoutOSRExit):
(JSC::DFG::ByteCodeParser::getArrayMode):
(JSC::DFG::ByteCodeParser::handleVarargsInlining):
(JSC::DFG::ByteCodeParser::parseBlock):
(JSC::DFG::ByteCodeParser::handlePutByVal):
* dfg/DFGFixupPhase.cpp:
(JSC::DFG::FixupPhase::attemptToMakeGetArrayLength):
* dfg/DFGGraph.h:
* dfg/DFGOSRExitCompilerCommon.cpp:
(JSC::DFG::osrWriteBarrier):
(JSC::DFG::adjustAndJumpToTarget):
* dfg/DFGPredictionInjectionPhase.cpp:
(JSC::DFG::PredictionInjectionPhase::run):
* heap/CodeBlockSetInlines.h:
(JSC::CodeBlockSet::iterateViaSubspaces):
* heap/Heap.cpp:
(JSC::Heap::finalizeMarkedUnconditionalFinalizers):
(JSC::Heap::finalizeUnconditionalFinalizers):
(JSC::Heap::deleteUnmarkedCompiledCode):
(JSC::Heap::runEndPhase):
(JSC::Heap::addCoreConstraints):
* jit/JIT.h:
* jit/JITInlines.h:
(JSC::JIT::emitValueProfilingSiteIfProfiledOpcode):
* jit/JITOpcodes.cpp:
(JSC::JIT::emit_op_enter):
(JSC::JIT::op_enter_handlerGenerator):
* jit/JITOperations.cpp:
(JSC::putByValOptimize):
(JSC::directPutByValOptimize):
(JSC::JSC_DEFINE_JIT_OPERATION):
* jit/JITPropertyAccess.cpp:
(JSC::JIT::emit_op_get_by_val):
(JSC::JIT::generateGetByValSlowCase):
(JSC::JIT::emit_op_put_by_val):
(JSC::JIT::emitSlow_op_put_by_val):
(JSC::JIT::emit_op_get_by_id):
(JSC::JIT::emit_op_in_by_val):
(JSC::JIT::emitSlow_op_in_by_val):
(JSC::JIT::generateOpGetFromScopeThunk):
(JSC::JIT::slow_op_get_from_scopeGenerator):
(JSC::JIT::emit_op_enumerator_get_by_val):
* jit/JITPropertyAccess32_64.cpp:
(JSC::JIT::emit_op_get_by_val):
(JSC::JIT::emitSlow_op_get_by_val):
(JSC::JIT::emit_op_put_by_val):
(JSC::JIT::emitSlow_op_put_by_val):
(JSC::JIT::emit_op_get_by_id):
(JSC::JIT::emit_op_in_by_val):
(JSC::JIT::emitSlow_op_in_by_val):
* llint/LLIntSlowPaths.cpp:
(JSC::LLInt::performLLIntGetByID):
(JSC::LLInt::LLINT_SLOW_PATH_DECL):
(JSC::LLInt::getByVal):
* llint/LowLevelInterpreter.asm:
* llint/LowLevelInterpreter32_64.asm:
* llint/LowLevelInterpreter64.asm:
* profiler/ProfilerBytecodeSequence.cpp:
(JSC::Profiler::BytecodeSequence::BytecodeSequence):
* runtime/CachedTypes.cpp:
(JSC::CachedCodeBlock::numValueProfiles const):
(JSC::CachedCodeBlock::numArrayProfiles const):
(JSC::UnlinkedCodeBlock::UnlinkedCodeBlock):
(JSC::CachedCodeBlock<CodeBlockType>::encode):
* runtime/CommonSlowPaths.cpp:
(JSC::iteratorNextTryFastImpl):
(JSC::JSC_DEFINE_COMMON_SLOW_PATH):
* runtime/JSScope.cpp:
(JSC::abstractAccess):
(JSC::JSScope::abstractResolve):
* runtime/VM.cpp:
* runtime/VM.h:
(JSC::VM::forEachUnlinkedCodeBlockSpace):
(JSC::VM::forEachCodeBlockSpace): Deleted.</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkSourceJavaScriptCoreChangeLog">trunk/Source/JavaScriptCore/ChangeLog</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecodeArrayProfilecpp">trunk/Source/JavaScriptCore/bytecode/ArrayProfile.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecodeArrayProfileh">trunk/Source/JavaScriptCore/bytecode/ArrayProfile.h</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecodeBytecodeListrb">trunk/Source/JavaScriptCore/bytecode/BytecodeList.rb</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecodeBytecodeOperandsForCheckpointh">trunk/Source/JavaScriptCore/bytecode/BytecodeOperandsForCheckpoint.h</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecodeCodeBlockcpp">trunk/Source/JavaScriptCore/bytecode/CodeBlock.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecodeCodeBlockh">trunk/Source/JavaScriptCore/bytecode/CodeBlock.h</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecodeCodeBlockInlinesh">trunk/Source/JavaScriptCore/bytecode/CodeBlockInlines.h</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecodeDFGExitProfilecpp">trunk/Source/JavaScriptCore/bytecode/DFGExitProfile.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecodeDFGExitProfileh">trunk/Source/JavaScriptCore/bytecode/DFGExitProfile.h</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecodeGetByIdMetadatah">trunk/Source/JavaScriptCore/bytecode/GetByIdMetadata.h</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecodeLazyOperandValueProfilecpp">trunk/Source/JavaScriptCore/bytecode/LazyOperandValueProfile.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecodeMetadataTablecpp">trunk/Source/JavaScriptCore/bytecode/MetadataTable.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecodeMetadataTableh">trunk/Source/JavaScriptCore/bytecode/MetadataTable.h</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecodeOpcodeh">trunk/Source/JavaScriptCore/bytecode/Opcode.h</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecodeUnlinkedCodeBlockcpp">trunk/Source/JavaScriptCore/bytecode/UnlinkedCodeBlock.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecodeUnlinkedCodeBlockh">trunk/Source/JavaScriptCore/bytecode/UnlinkedCodeBlock.h</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecodeUnlinkedCodeBlockGeneratorcpp">trunk/Source/JavaScriptCore/bytecode/UnlinkedCodeBlockGenerator.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecodeUnlinkedMetadataTablecpp">trunk/Source/JavaScriptCore/bytecode/UnlinkedMetadataTable.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecodeUnlinkedMetadataTableh">trunk/Source/JavaScriptCore/bytecode/UnlinkedMetadataTable.h</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecodeUnlinkedMetadataTableInlinesh">trunk/Source/JavaScriptCore/bytecode/UnlinkedMetadataTableInlines.h</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecodeValueProfileh">trunk/Source/JavaScriptCore/bytecode/ValueProfile.h</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGArrayModecpp">trunk/Source/JavaScriptCore/dfg/DFGArrayMode.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGArrayModeh">trunk/Source/JavaScriptCore/dfg/DFGArrayMode.h</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGByteCodeParsercpp">trunk/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGFixupPhasecpp">trunk/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGGraphh">trunk/Source/JavaScriptCore/dfg/DFGGraph.h</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGOSRExitCompilerCommoncpp">trunk/Source/JavaScriptCore/dfg/DFGOSRExitCompilerCommon.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGPredictionInjectionPhasecpp">trunk/Source/JavaScriptCore/dfg/DFGPredictionInjectionPhase.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreheapCodeBlockSetInlinesh">trunk/Source/JavaScriptCore/heap/CodeBlockSetInlines.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreheapHeapcpp">trunk/Source/JavaScriptCore/heap/Heap.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorejitJITh">trunk/Source/JavaScriptCore/jit/JIT.h</a></li>
<li><a href="#trunkSourceJavaScriptCorejitJITInlinesh">trunk/Source/JavaScriptCore/jit/JITInlines.h</a></li>
<li><a href="#trunkSourceJavaScriptCorejitJITOpcodescpp">trunk/Source/JavaScriptCore/jit/JITOpcodes.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorejitJITOperationscpp">trunk/Source/JavaScriptCore/jit/JITOperations.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorejitJITPropertyAccesscpp">trunk/Source/JavaScriptCore/jit/JITPropertyAccess.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorejitJITPropertyAccess32_64cpp">trunk/Source/JavaScriptCore/jit/JITPropertyAccess32_64.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorellintLLIntSlowPathscpp">trunk/Source/JavaScriptCore/llint/LLIntSlowPaths.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorellintLowLevelInterpreterasm">trunk/Source/JavaScriptCore/llint/LowLevelInterpreter.asm</a></li>
<li><a href="#trunkSourceJavaScriptCorellintLowLevelInterpreter32_64asm">trunk/Source/JavaScriptCore/llint/LowLevelInterpreter32_64.asm</a></li>
<li><a href="#trunkSourceJavaScriptCorellintLowLevelInterpreter64asm">trunk/Source/JavaScriptCore/llint/LowLevelInterpreter64.asm</a></li>
<li><a href="#trunkSourceJavaScriptCoreprofilerProfilerBytecodeSequencecpp">trunk/Source/JavaScriptCore/profiler/ProfilerBytecodeSequence.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeCachedTypescpp">trunk/Source/JavaScriptCore/runtime/CachedTypes.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeCommonSlowPathscpp">trunk/Source/JavaScriptCore/runtime/CommonSlowPaths.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeJSScopecpp">trunk/Source/JavaScriptCore/runtime/JSScope.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeVMcpp">trunk/Source/JavaScriptCore/runtime/VM.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeVMh">trunk/Source/JavaScriptCore/runtime/VM.h</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceJavaScriptCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ChangeLog (282477 => 282478)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ChangeLog    2021-09-15 22:12:01 UTC (rev 282477)
+++ trunk/Source/JavaScriptCore/ChangeLog       2021-09-15 22:18:52 UTC (rev 282478)
</span><span class="lines">@@ -1,3 +1,205 @@
</span><ins>+2021-09-15  Saam Barati  <sbarati@apple.com>
+
+        Move some profiling to UnlinkedCodeBlock
+        https://bugs.webkit.org/show_bug.cgi?id=230078
+        <rdar://problem/82947571>
+
+        Reviewed by Yusuke Suzuki.
+
+        This patch moves ValueProfiles and ArrayProfiles for non-call opcodes into
+        UnlinkedCodeBlock. This way, the data is shared between the linked CodeBlocks
+        of the same UnlinkedCodeBlock. The profiling bet here is that when the same code
+        runs in a different global object, it largely runs in the same way. We've made
+        this same bet in other ways with our profiling, and it largely makes sense
+        to do for ValueProfile and ArrayProfile since they both hold global object
+        independent data.
+        
+        Because ArrayProfiles are now shared between CodeBlocks, the existing m_usesOriginalArrayStructures
+        bit is slightly harder to track now, since the ArrayProfile may see inputs from a different
+        global object, an array may be an original array in one lexical global object,
+        but not another. So we now track when an ArrayProfile sees a different global
+        object than the lexical global object, and when we observe exits in the DFG,
+        we propagate that bit to the m_usesOriginalArrayStructures bit.
+        
+        This patch also makes it so we no longer hold the CodeBlock lock when
+        processing ValueProfiles and ArrayProfiles. We now allow multiple compiler
+        threads to race against each other when updating these profiles. This is fine.
+        It may end up with incomplete data in the profiles, but it won't corrupt them.
+        
+        This patch also makes it so we finalized visited UnlinkedCodeBlocks to finalize
+        their value profiles. We no longer do that work inside CodeBlock for the
+        ValueProfiles that UnlinkedCodeBlock owns. This also means that we have to
+        WriteBarrier UnlinkedCodeBlock when executing in the LLInt, Baseline, and
+        other areas, such as OSR exit, and in the GC when a CodeBlock was executing.
+        That way we're guaranteed to visit the UnlinkedCodeBlock, add it to the
+        visited set, and then finalize it at the end of GC.
+        
+        This patch also makes it so that inside CodeBlock::finishCreation, we finish
+        linking before we do anything that can throw an exception. It's not valid to
+        finalize a CodeBlock that isn't linked.
+        
+        This was measured as a 0.5-1% speedup on Speedometer2.
+
+        * bytecode/ArrayProfile.cpp:
+        (JSC::ArrayProfile::computeUpdatedPrediction):
+        (JSC::ArrayProfile::briefDescription):
+        (JSC::ArrayProfile::briefDescriptionWithoutUpdating):
+        * bytecode/ArrayProfile.h:
+        (JSC::ArrayProfile::ArrayProfile):
+        (JSC::ArrayProfile::observedArrayModes const):
+        (JSC::ArrayProfile::mayInterceptIndexedAccesses const):
+        (JSC::ArrayProfile::mayStoreToHole const):
+        (JSC::ArrayProfile::outOfBounds const):
+        (JSC::ArrayProfile::usesOriginalArrayStructures const):
+        (JSC::ArrayProfile::setDoesNotUseOriginalArrayStructures):
+        (JSC::ArrayProfile::observedDifferentGlobalObject const):
+        * bytecode/BytecodeList.rb:
+        * bytecode/BytecodeOperandsForCheckpoint.h:
+        (JSC::valueProfileForImpl):
+        * bytecode/CodeBlock.cpp:
+        (JSC::CodeBlock::finishCreation):
+        (JSC::CodeBlock::setConstantRegisters):
+        (JSC::CodeBlock::initializeTemplateObjects):
+        (JSC::CodeBlock::setNumParameters):
+        (JSC::CodeBlock::visitChildren):
+        (JSC::CodeBlock::finalizeUnconditionally):
+        (JSC::CodeBlock::getArrayProfile):
+        (JSC::CodeBlock::updateAllValueProfilePredictionsAndCountLiveness):
+        (JSC::CodeBlock::updateAllArrayPredictions):
+        (JSC::CodeBlock::tryGetValueProfileForBytecodeIndex):
+        (JSC::CodeBlock::valueProfilePredictionForBytecodeIndex):
+        * bytecode/CodeBlock.h:
+        (JSC::CodeBlock::offsetOfUnlinkedCodeBlock):
+        (JSC::CodeBlock::numberOfArgumentValueProfiles):
+        (JSC::CodeBlock::valueProfileForArgument):
+        (JSC::CodeBlock::metadata):
+        * bytecode/CodeBlockInlines.h:
+        (JSC::CodeBlock::forEachValueProfile):
+        (JSC::CodeBlock::forEachArrayProfile):
+        * bytecode/DFGExitProfile.cpp:
+        (JSC::DFG::ExitProfile::hasAnyExitsAt const):
+        * bytecode/DFGExitProfile.h:
+        * bytecode/GetByIdMetadata.h:
+        (JSC::GetByIdModeMetadata::setArrayLengthMode):
+        * bytecode/LazyOperandValueProfile.cpp:
+        (JSC::CompressedLazyOperandValueProfileHolder::computeUpdatedPredictions):
+        (JSC::LazyOperandValueProfileParser::prediction const):
+        * bytecode/MetadataTable.cpp:
+        (JSC::DeallocTable::withOpcodeType):
+        * bytecode/MetadataTable.h:
+        (JSC::MetadataTable::get):
+        (JSC::MetadataTable::forEach):
+        (JSC::MetadataTable::getWithoutAligning):
+        (JSC::MetadataTable::getImpl): Deleted.
+        * bytecode/Opcode.h:
+        * bytecode/UnlinkedCodeBlock.cpp:
+        (JSC::UnlinkedCodeBlock::visitChildrenImpl):
+        (JSC::UnlinkedCodeBlock::allocateSharedProfiles):
+        (JSC::UnlinkedCodeBlock::finalizeUnconditionally):
+        * bytecode/UnlinkedCodeBlock.h:
+        (JSC::UnlinkedCodeBlock::hasAnyExitsAt const):
+        (JSC::UnlinkedCodeBlock::hasAnyExitsAt):
+        (JSC::UnlinkedCodeBlock::valueProfile):
+        (JSC::UnlinkedCodeBlock::arrayProfile):
+        (JSC::UnlinkedCodeBlock::numValueProfiles const):
+        (JSC::UnlinkedCodeBlock::numArrayProfiles const):
+        * bytecode/UnlinkedCodeBlockGenerator.cpp:
+        (JSC::UnlinkedCodeBlockGenerator::finalize):
+        * bytecode/UnlinkedMetadataTable.cpp:
+        (JSC::UnlinkedMetadataTable::finalize):
+        * bytecode/UnlinkedMetadataTable.h:
+        (JSC::UnlinkedMetadataTable::isFinalized):
+        (JSC::UnlinkedMetadataTable::hasMetadata):
+        * bytecode/UnlinkedMetadataTableInlines.h:
+        (JSC::UnlinkedMetadataTable::numEntries):
+        * bytecode/ValueProfile.h:
+        (JSC::ValueProfileBase::ValueProfileBase):
+        (JSC::ValueProfileBase::clearBuckets):
+        (JSC::ValueProfileBase::briefDescription):
+        (JSC::ValueProfileBase::computeUpdatedPrediction):
+        (JSC::ValueProfile::offsetOfFirstBucket):
+        (JSC::ValueProfileBase::classInfo const): Deleted.
+        * dfg/DFGArrayMode.cpp:
+        (JSC::DFG::ArrayMode::fromObserved):
+        * dfg/DFGArrayMode.h:
+        (JSC::DFG::ArrayMode::withSpeculationFromProfile const):
+        (JSC::DFG::ArrayMode::withProfile const):
+        * dfg/DFGByteCodeParser.cpp:
+        (JSC::DFG::ByteCodeParser::getPredictionWithoutOSRExit):
+        (JSC::DFG::ByteCodeParser::getArrayMode):
+        (JSC::DFG::ByteCodeParser::handleVarargsInlining):
+        (JSC::DFG::ByteCodeParser::parseBlock):
+        (JSC::DFG::ByteCodeParser::handlePutByVal):
+        * dfg/DFGFixupPhase.cpp:
+        (JSC::DFG::FixupPhase::attemptToMakeGetArrayLength):
+        * dfg/DFGGraph.h:
+        * dfg/DFGOSRExitCompilerCommon.cpp:
+        (JSC::DFG::osrWriteBarrier):
+        (JSC::DFG::adjustAndJumpToTarget):
+        * dfg/DFGPredictionInjectionPhase.cpp:
+        (JSC::DFG::PredictionInjectionPhase::run):
+        * heap/CodeBlockSetInlines.h:
+        (JSC::CodeBlockSet::iterateViaSubspaces):
+        * heap/Heap.cpp:
+        (JSC::Heap::finalizeMarkedUnconditionalFinalizers):
+        (JSC::Heap::finalizeUnconditionalFinalizers):
+        (JSC::Heap::deleteUnmarkedCompiledCode):
+        (JSC::Heap::runEndPhase):
+        (JSC::Heap::addCoreConstraints):
+        * jit/JIT.h:
+        * jit/JITInlines.h:
+        (JSC::JIT::emitValueProfilingSiteIfProfiledOpcode):
+        * jit/JITOpcodes.cpp:
+        (JSC::JIT::emit_op_enter):
+        (JSC::JIT::op_enter_handlerGenerator):
+        * jit/JITOperations.cpp:
+        (JSC::putByValOptimize):
+        (JSC::directPutByValOptimize):
+        (JSC::JSC_DEFINE_JIT_OPERATION):
+        * jit/JITPropertyAccess.cpp:
+        (JSC::JIT::emit_op_get_by_val):
+        (JSC::JIT::generateGetByValSlowCase):
+        (JSC::JIT::emit_op_put_by_val):
+        (JSC::JIT::emitSlow_op_put_by_val):
+        (JSC::JIT::emit_op_get_by_id):
+        (JSC::JIT::emit_op_in_by_val):
+        (JSC::JIT::emitSlow_op_in_by_val):
+        (JSC::JIT::generateOpGetFromScopeThunk):
+        (JSC::JIT::slow_op_get_from_scopeGenerator):
+        (JSC::JIT::emit_op_enumerator_get_by_val):
+        * jit/JITPropertyAccess32_64.cpp:
+        (JSC::JIT::emit_op_get_by_val):
+        (JSC::JIT::emitSlow_op_get_by_val):
+        (JSC::JIT::emit_op_put_by_val):
+        (JSC::JIT::emitSlow_op_put_by_val):
+        (JSC::JIT::emit_op_get_by_id):
+        (JSC::JIT::emit_op_in_by_val):
+        (JSC::JIT::emitSlow_op_in_by_val):
+        * llint/LLIntSlowPaths.cpp:
+        (JSC::LLInt::performLLIntGetByID):
+        (JSC::LLInt::LLINT_SLOW_PATH_DECL):
+        (JSC::LLInt::getByVal):
+        * llint/LowLevelInterpreter.asm:
+        * llint/LowLevelInterpreter32_64.asm:
+        * llint/LowLevelInterpreter64.asm:
+        * profiler/ProfilerBytecodeSequence.cpp:
+        (JSC::Profiler::BytecodeSequence::BytecodeSequence):
+        * runtime/CachedTypes.cpp:
+        (JSC::CachedCodeBlock::numValueProfiles const):
+        (JSC::CachedCodeBlock::numArrayProfiles const):
+        (JSC::UnlinkedCodeBlock::UnlinkedCodeBlock):
+        (JSC::CachedCodeBlock<CodeBlockType>::encode):
+        * runtime/CommonSlowPaths.cpp:
+        (JSC::iteratorNextTryFastImpl):
+        (JSC::JSC_DEFINE_COMMON_SLOW_PATH):
+        * runtime/JSScope.cpp:
+        (JSC::abstractAccess):
+        (JSC::JSScope::abstractResolve):
+        * runtime/VM.cpp:
+        * runtime/VM.h:
+        (JSC::VM::forEachUnlinkedCodeBlockSpace):
+        (JSC::VM::forEachCodeBlockSpace): Deleted.
+
</ins><span class="cx"> 2021-09-15  Michael Catanzaro  <mcatanzaro@gnome.org>
</span><span class="cx"> 
</span><span class="cx">         Avoid GCC warnings introduced in r282125
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecodeArrayProfilecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecode/ArrayProfile.cpp (282477 => 282478)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/ArrayProfile.cpp    2021-09-15 22:12:01 UTC (rev 282477)
+++ trunk/Source/JavaScriptCore/bytecode/ArrayProfile.cpp       2021-09-15 22:18:52 UTC (rev 282478)
</span><span class="lines">@@ -118,18 +118,41 @@
</span><span class="cx">         out.print(comma, "BigUint64ArrayMode");
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void ArrayProfile::computeUpdatedPrediction(const ConcurrentJSLocker& locker, CodeBlock* codeBlock)
</del><ins>+void ArrayProfile::computeUpdatedPrediction(CodeBlock* codeBlock)
</ins><span class="cx"> {
</span><del>-    if (!m_lastSeenStructureID)
</del><ins>+    // Multiple threads could be calling into this at the same time.
+    StructureID id = m_lastSeenStructureID;
+    if (!id)
</ins><span class="cx">         return;
</span><span class="cx">     
</span><del>-    Structure* lastSeenStructure = codeBlock->heap()->structureIDTable().get(m_lastSeenStructureID);
-    computeUpdatedPrediction(locker, codeBlock, lastSeenStructure);
</del><ins>+    Structure* lastSeenStructure = codeBlock->heap()->structureIDTable().get(id);
+    computeUpdatedPrediction(codeBlock, lastSeenStructure);
</ins><span class="cx">     m_lastSeenStructureID = 0;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void ArrayProfile::computeUpdatedPrediction(const ConcurrentJSLocker&, CodeBlock* codeBlock, Structure* lastSeenStructure)
</del><ins>+void ArrayProfile::computeUpdatedPrediction(UnlinkedCodeBlock* unlinkedCodeBlock)
</ins><span class="cx"> {
</span><ins>+    // Multiple threads could be calling into this at the same time.
+    StructureID id = m_lastSeenStructureID;
+    if (!id)
+        return;
+
+    Structure* lastSeenStructure = unlinkedCodeBlock->heap()->structureIDTable().get(id);
+    computeUpdatedPrediction(lastSeenStructure, nullptr);
+    
+    m_lastSeenStructureID = 0;
+}
+
+void ArrayProfile::computeUpdatedPrediction(CodeBlock* codeBlock, Structure* lastSeenStructure)
+{
+    computeUpdatedPrediction(lastSeenStructure, codeBlock->globalObject());
+}
+
+void ArrayProfile::computeUpdatedPrediction(Structure* lastSeenStructure, JSGlobalObject* lexicalGlobalObject)
+{
+    // Multiple threads could be calling into this at the same time. That won't lead
+    // to any form of corruption, but could cause us to go down !m_didPerformFirstRunPruning
+    // path simultaneously.
</ins><span class="cx">     m_observedArrayModes |= arrayModesFromStructure(lastSeenStructure);
</span><span class="cx">     
</span><span class="cx">     if (!m_didPerformFirstRunPruning
</span><span class="lines">@@ -140,8 +163,11 @@
</span><span class="cx">     
</span><span class="cx">     m_mayInterceptIndexedAccesses |=
</span><span class="cx">         lastSeenStructure->typeInfo().interceptsGetOwnPropertySlotByIndexEvenWhenLengthIsNotZero();
</span><del>-    JSGlobalObject* globalObject = codeBlock->globalObject();
-    if (!globalObject->isOriginalArrayStructure(lastSeenStructure)
</del><ins>+    JSGlobalObject* globalObject = lastSeenStructure->globalObject();
+    if (lexicalGlobalObject && globalObject && globalObject != lexicalGlobalObject)
+        m_observedDifferentGlobalObject = true;
+    if (globalObject
+        && !globalObject->isOriginalArrayStructure(lastSeenStructure)
</ins><span class="cx">         && !globalObject->isOriginalTypedArrayStructure(lastSeenStructure))
</span><span class="cx">         m_usesOriginalArrayStructures = false;
</span><span class="cx"> }
</span><span class="lines">@@ -163,13 +189,13 @@
</span><span class="cx">     }
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-CString ArrayProfile::briefDescription(const ConcurrentJSLocker& locker, CodeBlock* codeBlock)
</del><ins>+CString ArrayProfile::briefDescription(CodeBlock* codeBlock)
</ins><span class="cx"> {
</span><del>-    computeUpdatedPrediction(locker, codeBlock);
-    return briefDescriptionWithoutUpdating(locker);
</del><ins>+    computeUpdatedPrediction(codeBlock);
+    return briefDescriptionWithoutUpdating();
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-CString ArrayProfile::briefDescriptionWithoutUpdating(const ConcurrentJSLocker&)
</del><ins>+CString ArrayProfile::briefDescriptionWithoutUpdating()
</ins><span class="cx"> {
</span><span class="cx">     StringPrintStream out;
</span><span class="cx">     CommaPrinter comma;
</span><span class="lines">@@ -184,6 +210,8 @@
</span><span class="cx">         out.print(comma, "Intercept");
</span><span class="cx">     if (m_usesOriginalArrayStructures)
</span><span class="cx">         out.print(comma, "Original");
</span><ins>+    if (m_observedDifferentGlobalObject)
+        out.print(comma, "DifferentGlobal");
</ins><span class="cx"> 
</span><span class="cx">     return out.toCString();
</span><span class="cx"> }
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecodeArrayProfileh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecode/ArrayProfile.h (282477 => 282478)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/ArrayProfile.h      2021-09-15 22:12:01 UTC (rev 282477)
+++ trunk/Source/JavaScriptCore/bytecode/ArrayProfile.h 2021-09-15 22:18:52 UTC (rev 282478)
</span><span class="lines">@@ -32,6 +32,7 @@
</span><span class="cx"> 
</span><span class="cx"> class CodeBlock;
</span><span class="cx"> class LLIntOffsetsExtractor;
</span><ins>+class UnlinkedCodeBlock;
</ins><span class="cx"> 
</span><span class="cx"> // This is a bitfield where each bit represents an type of array access that we have seen.
</span><span class="cx"> // There are 19 indexing types that use the lower bits.
</span><span class="lines">@@ -201,6 +202,7 @@
</span><span class="cx">         : m_mayInterceptIndexedAccesses(false)
</span><span class="cx">         , m_usesOriginalArrayStructures(true)
</span><span class="cx">         , m_didPerformFirstRunPruning(false)
</span><ins>+        , m_observedDifferentGlobalObject(false)
</ins><span class="cx">     {
</span><span class="cx">     }
</span><span class="cx">     
</span><span class="lines">@@ -217,22 +219,27 @@
</span><span class="cx">     void observeStructureID(StructureID structureID) { m_lastSeenStructureID = structureID; }
</span><span class="cx">     void observeStructure(Structure* structure) { m_lastSeenStructureID = structure->id(); }
</span><span class="cx"> 
</span><del>-    void computeUpdatedPrediction(const ConcurrentJSLocker&, CodeBlock*);
-    void computeUpdatedPrediction(const ConcurrentJSLocker&, CodeBlock*, Structure* lastSeenStructure);
</del><ins>+    void computeUpdatedPrediction(UnlinkedCodeBlock*);
+    void computeUpdatedPrediction(CodeBlock*);
+    void computeUpdatedPrediction(CodeBlock*, Structure* lastSeenStructure);
+    void computeUpdatedPrediction(Structure* lastSeenStructure, JSGlobalObject* lexicalGlobalObject);
</ins><span class="cx">     
</span><span class="cx">     void observeArrayMode(ArrayModes mode) { m_observedArrayModes |= mode; }
</span><span class="cx">     void observeIndexedRead(VM&, JSCell*, unsigned index);
</span><span class="cx"> 
</span><del>-    ArrayModes observedArrayModes(const ConcurrentJSLocker&) const { return m_observedArrayModes; }
-    bool mayInterceptIndexedAccesses(const ConcurrentJSLocker&) const { return m_mayInterceptIndexedAccesses; }
</del><ins>+    ArrayModes observedArrayModes() const { return m_observedArrayModes; }
+    bool mayInterceptIndexedAccesses() const { return m_mayInterceptIndexedAccesses; }
</ins><span class="cx">     
</span><del>-    bool mayStoreToHole(const ConcurrentJSLocker&) const { return m_mayStoreToHole; }
-    bool outOfBounds(const ConcurrentJSLocker&) const { return m_outOfBounds; }
</del><ins>+    bool mayStoreToHole() const { return m_mayStoreToHole; }
+    bool outOfBounds() const { return m_outOfBounds; }
</ins><span class="cx">     
</span><del>-    bool usesOriginalArrayStructures(const ConcurrentJSLocker&) const { return m_usesOriginalArrayStructures; }
</del><ins>+    bool usesOriginalArrayStructures() const { return m_usesOriginalArrayStructures; }
+    void setDoesNotUseOriginalArrayStructures() { m_usesOriginalArrayStructures = false; }
</ins><span class="cx"> 
</span><del>-    CString briefDescription(const ConcurrentJSLocker&, CodeBlock*);
-    CString briefDescriptionWithoutUpdating(const ConcurrentJSLocker&);
</del><ins>+    bool observedDifferentGlobalObject() const { return m_observedDifferentGlobalObject; }
+
+    CString briefDescription(CodeBlock*);
+    CString briefDescriptionWithoutUpdating();
</ins><span class="cx">     
</span><span class="cx"> private:
</span><span class="cx">     friend class LLIntOffsetsExtractor;
</span><span class="lines">@@ -245,6 +252,7 @@
</span><span class="cx">     bool m_mayInterceptIndexedAccesses : 1;
</span><span class="cx">     bool m_usesOriginalArrayStructures : 1;
</span><span class="cx">     bool m_didPerformFirstRunPruning : 1;
</span><ins>+    bool m_observedDifferentGlobalObject : 1;
</ins><span class="cx">     ArrayModes m_observedArrayModes { 0 };
</span><span class="cx"> };
</span><span class="cx"> static_assert(sizeof(ArrayProfile) == 12);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecodeBytecodeListrb"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecode/BytecodeList.rb (282477 => 282478)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/BytecodeList.rb     2021-09-15 22:12:01 UTC (rev 282477)
+++ trunk/Source/JavaScriptCore/bytecode/BytecodeList.rb        2021-09-15 22:18:52 UTC (rev 282478)
</span><span class="lines">@@ -167,7 +167,7 @@
</span><span class="cx">         index: int,
</span><span class="cx">     },
</span><span class="cx">     metadata: {
</span><del>-        profile: ValueProfile,
</del><ins>+        profile: ValueProfile.*,
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx"> op :argument_count,
</span><span class="lines">@@ -183,7 +183,7 @@
</span><span class="cx">     metadata: {
</span><span class="cx">         cachedStructureID: StructureID,
</span><span class="cx">         toThisStatus: ToThisStatus,
</span><del>-        profile: ValueProfile,
</del><ins>+        profile: ValueProfile.*,
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx"> op :check_tdz,
</span><span class="lines">@@ -309,7 +309,7 @@
</span><span class="cx">         rhs: VirtualRegister,
</span><span class="cx">     },
</span><span class="cx">     metadata: {
</span><del>-        profile: ValueProfile
</del><ins>+        profile: ValueProfile.*
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx"> op :bitnot,
</span><span class="lines">@@ -318,7 +318,7 @@
</span><span class="cx">         operand: VirtualRegister,
</span><span class="cx">     },
</span><span class="cx">     metadata: {
</span><del>-        profile: ValueProfile
</del><ins>+        profile: ValueProfile.*
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx"> op_group :UnaryOp,
</span><span class="lines">@@ -363,7 +363,7 @@
</span><span class="cx">         message: unsigned,
</span><span class="cx">     },
</span><span class="cx">     metadata: {
</span><del>-        profile: ValueProfile,
</del><ins>+        profile: ValueProfile.*,
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx"> op_group :ValueProfiledUnaryOp,
</span><span class="lines">@@ -376,7 +376,7 @@
</span><span class="cx">         operand: VirtualRegister,
</span><span class="cx">     },
</span><span class="cx">     metadata: {
</span><del>-        profile: ValueProfile,
</del><ins>+        profile: ValueProfile.*,
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx"> op :negate,
</span><span class="lines">@@ -445,7 +445,7 @@
</span><span class="cx">         property: VirtualRegister,
</span><span class="cx">     },
</span><span class="cx">     metadata: {
</span><del>-        arrayProfile: ArrayProfile,
</del><ins>+        arrayProfile: ArrayProfile.*,
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx"> op :in_by_id,
</span><span class="lines">@@ -476,8 +476,9 @@
</span><span class="cx">         property: unsigned,
</span><span class="cx">     },
</span><span class="cx">     metadata: {
</span><ins>+        profile: ValueProfile.*,
+        arrayProfile: ArrayProfile.*,
</ins><span class="cx">         modeMetadata: GetByIdModeMetadata,
</span><del>-        profile: ValueProfile,
</del><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx"> op :get_by_id_with_this,
</span><span class="lines">@@ -488,7 +489,7 @@
</span><span class="cx">         property: unsigned,
</span><span class="cx">     },
</span><span class="cx">     metadata: {
</span><del>-        profile: ValueProfile,
</del><ins>+        profile: ValueProfile.*,
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx"> op :get_by_val_with_this,
</span><span class="lines">@@ -499,7 +500,7 @@
</span><span class="cx">         property: VirtualRegister,
</span><span class="cx">     },
</span><span class="cx">     metadata: {
</span><del>-        profile: ValueProfile,
</del><ins>+        profile: ValueProfile.*,
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx"> op :get_by_id_direct,
</span><span class="lines">@@ -509,7 +510,7 @@
</span><span class="cx">         property: unsigned,
</span><span class="cx">     },
</span><span class="cx">     metadata: {
</span><del>-        profile: ValueProfile, # not used in llint
</del><ins>+        profile: ValueProfile.*, # not used in llint
</ins><span class="cx">         structureID: StructureID,
</span><span class="cx">         offset: unsigned,
</span><span class="cx">     }
</span><span class="lines">@@ -520,7 +521,7 @@
</span><span class="cx">         value: VirtualRegister,
</span><span class="cx">     },
</span><span class="cx">     metadata: {
</span><del>-        profile: ValueProfile,
</del><ins>+        profile: ValueProfile.*,
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx"> op :try_get_by_id,
</span><span class="lines">@@ -530,7 +531,7 @@
</span><span class="cx">         property: unsigned,
</span><span class="cx">     },
</span><span class="cx">     metadata: {
</span><del>-        profile: ValueProfile,
</del><ins>+        profile: ValueProfile.*,
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx"> op :put_by_id,
</span><span class="lines">@@ -571,8 +572,8 @@
</span><span class="cx">         property: VirtualRegister,
</span><span class="cx">     },
</span><span class="cx">     metadata: {
</span><del>-        profile: ValueProfile,
-        arrayProfile: ArrayProfile,
</del><ins>+        profile: ValueProfile.*,
+        arrayProfile: ArrayProfile.*,
</ins><span class="cx">         seenIdentifiers: GetByValHistory,
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="lines">@@ -583,7 +584,7 @@
</span><span class="cx">         property: VirtualRegister,
</span><span class="cx">     },
</span><span class="cx">     metadata: {
</span><del>-        profile: ValueProfile,
</del><ins>+        profile: ValueProfile.*,
</ins><span class="cx">         structureID: StructureID,
</span><span class="cx">         offset: unsigned,
</span><span class="cx">         property: WriteBarrier[JSCell],
</span><span class="lines">@@ -632,7 +633,7 @@
</span><span class="cx">         ecmaMode: ECMAMode,
</span><span class="cx">     },
</span><span class="cx">     metadata: {
</span><del>-        arrayProfile: ArrayProfile,
</del><ins>+        arrayProfile: ArrayProfile.*,
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx"> op :put_by_val_with_this,
</span><span class="lines">@@ -652,7 +653,7 @@
</span><span class="cx">         ecmaMode: ECMAMode,
</span><span class="cx">     },
</span><span class="cx">     metadata: {
</span><del>-        arrayProfile: ArrayProfile,
</del><ins>+        arrayProfile: ArrayProfile.*,
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx"> op :del_by_val,
</span><span class="lines">@@ -842,7 +843,7 @@
</span><span class="cx">     },
</span><span class="cx">     metadata: {
</span><span class="cx">         callLinkInfo: LLIntCallLinkInfo,
</span><del>-        profile: ValueProfile,
</del><ins>+        profile: ValueProfile.*,
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx"> op :tail_call,
</span><span class="lines">@@ -854,7 +855,7 @@
</span><span class="cx">     },
</span><span class="cx">     metadata: {
</span><span class="cx">         callLinkInfo: LLIntCallLinkInfo,
</span><del>-        profile: ValueProfile,
</del><ins>+        profile: ValueProfile.*,
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx"> op :call_eval,
</span><span class="lines">@@ -867,7 +868,7 @@
</span><span class="cx">     },
</span><span class="cx">     metadata: {
</span><span class="cx">         callLinkInfo: LLIntCallLinkInfo,
</span><del>-        profile: ValueProfile,
</del><ins>+        profile: ValueProfile.*,
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx"> op :call_varargs,
</span><span class="lines">@@ -880,8 +881,8 @@
</span><span class="cx">         firstVarArg: int,
</span><span class="cx">     },
</span><span class="cx">     metadata: {
</span><del>-        arrayProfile: ArrayProfile,
-        profile: ValueProfile,
</del><ins>+        arrayProfile: ArrayProfile.*,
+        profile: ValueProfile.*,
</ins><span class="cx">     },
</span><span class="cx">     tmps: {
</span><span class="cx">         argCountIncludingThis: unsigned,
</span><span class="lines">@@ -901,8 +902,8 @@
</span><span class="cx">         firstVarArg: int,
</span><span class="cx">     },
</span><span class="cx">     metadata: {
</span><del>-        arrayProfile: ArrayProfile,
-        profile: ValueProfile,
</del><ins>+        arrayProfile: ArrayProfile.*,
+        profile: ValueProfile.*,
</ins><span class="cx">     },
</span><span class="cx">     tmps: {
</span><span class="cx">         argCountIncludingThis: unsigned
</span><span class="lines">@@ -922,8 +923,8 @@
</span><span class="cx">         firstVarArg: int,
</span><span class="cx">     },
</span><span class="cx">     metadata: {
</span><del>-        arrayProfile: ArrayProfile,
-        profile: ValueProfile,
</del><ins>+        arrayProfile: ArrayProfile.*,
+        profile: ValueProfile.*,
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx"> op :construct,
</span><span class="lines">@@ -934,8 +935,8 @@
</span><span class="cx">         argv: unsigned,
</span><span class="cx">     },
</span><span class="cx">     metadata: {
</span><ins>+        profile: ValueProfile.*,
</ins><span class="cx">         callLinkInfo: LLIntCallLinkInfo,
</span><del>-        profile: ValueProfile,
</del><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx"> op :construct_varargs,
</span><span class="lines">@@ -948,8 +949,8 @@
</span><span class="cx">         firstVarArg: int,
</span><span class="cx">     },
</span><span class="cx">     metadata: {
</span><del>-        arrayProfile: ArrayProfile,
-        profile: ValueProfile,
</del><ins>+        arrayProfile: ArrayProfile.*,
+        profile: ValueProfile.*,
</ins><span class="cx">     },
</span><span class="cx">     tmps: {
</span><span class="cx">         argCountIncludingThis: unsigned
</span><span class="lines">@@ -1028,7 +1029,7 @@
</span><span class="cx">             structure: WriteBarrierBase[Structure],
</span><span class="cx">         },
</span><span class="cx">         operand: uintptr_t, #offset 6
</span><del>-        profile: ValueProfile, # offset 7
</del><ins>+        profile: ValueProfile.*, # offset 7
</ins><span class="cx">     },
</span><span class="cx">     metadata_initializers: {
</span><span class="cx">         getPutInfo: :getPutInfo,
</span><span class="lines">@@ -1065,7 +1066,7 @@
</span><span class="cx">         index: unsigned,
</span><span class="cx">     },
</span><span class="cx">     metadata: {
</span><del>-        profile: ValueProfile,
</del><ins>+        profile: ValueProfile.*,
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx"> op :put_to_arguments,
</span><span class="lines">@@ -1173,7 +1174,7 @@
</span><span class="cx">         enumerator: VirtualRegister,
</span><span class="cx">     },
</span><span class="cx">     metadata: {
</span><del>-        arrayProfile: ArrayProfile,
</del><ins>+        arrayProfile: ArrayProfile.*,
</ins><span class="cx">         enumeratorMetadata: EnumeratorMetadata,
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="lines">@@ -1187,8 +1188,8 @@
</span><span class="cx">         enumerator: VirtualRegister,
</span><span class="cx">     },
</span><span class="cx">     metadata: {
</span><del>-        profile: ValueProfile,
-        arrayProfile: ArrayProfile,
</del><ins>+        profile: ValueProfile.*,
+        arrayProfile: ArrayProfile.*,
</ins><span class="cx">         enumeratorMetadata: EnumeratorMetadata,
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="lines">@@ -1202,7 +1203,7 @@
</span><span class="cx">         enumerator: VirtualRegister,
</span><span class="cx">     },
</span><span class="cx">     metadata: {
</span><del>-        arrayProfile: ArrayProfile,
</del><ins>+        arrayProfile: ArrayProfile.*,
</ins><span class="cx">         enumeratorMetadata: EnumeratorMetadata,
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="lines">@@ -1216,7 +1217,7 @@
</span><span class="cx">         enumerator: VirtualRegister,
</span><span class="cx">     },
</span><span class="cx">     metadata: {
</span><del>-        arrayProfile: ArrayProfile,
</del><ins>+        arrayProfile: ArrayProfile.*,
</ins><span class="cx">         enumeratorMetadata: EnumeratorMetadata,
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="lines">@@ -1248,12 +1249,12 @@
</span><span class="cx">         stackOffset: unsigned,
</span><span class="cx">     },
</span><span class="cx">     metadata: {
</span><ins>+        iterableProfile: ValueProfile.*,
+        iteratorProfile: ValueProfile.*,
+        nextProfile: ValueProfile.*,
</ins><span class="cx">         iterationMetadata: IterationModeMetadata,
</span><del>-        iterableProfile: ValueProfile,
</del><span class="cx">         callLinkInfo: LLIntCallLinkInfo,
</span><del>-        iteratorProfile: ValueProfile,
</del><span class="cx">         modeMetadata: GetByIdModeMetadata,
</span><del>-        nextProfile: ValueProfile,
</del><span class="cx">     },
</span><span class="cx">     checkpoints: {
</span><span class="cx">         symbolCall: nil,
</span><span class="lines">@@ -1271,14 +1272,14 @@
</span><span class="cx">         stackOffset: unsigned,
</span><span class="cx">     },
</span><span class="cx">     metadata: {
</span><ins>+        nextResultProfile: ValueProfile.*,
+        doneProfile: ValueProfile.*,
+        valueProfile: ValueProfile.*,
+        iterableProfile: ArrayProfile.*,
</ins><span class="cx">         iterationMetadata: IterationModeMetadata,
</span><del>-        iterableProfile: ArrayProfile,
</del><span class="cx">         callLinkInfo: LLIntCallLinkInfo,
</span><del>-        nextResultProfile: ValueProfile,
</del><span class="cx">         doneModeMetadata: GetByIdModeMetadata,
</span><del>-        doneProfile: ValueProfile,
</del><span class="cx">         valueModeMetadata: GetByIdModeMetadata,
</span><del>-        valueProfile: ValueProfile,
</del><span class="cx">     },
</span><span class="cx">     tmps: {
</span><span class="cx">         nextResult: JSValue,
</span><span class="lines">@@ -1322,7 +1323,7 @@
</span><span class="cx">         index: unsigned,
</span><span class="cx">     },
</span><span class="cx">     metadata: {
</span><del>-        profile: ValueProfile,
</del><ins>+        profile: ValueProfile.*,
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx"> op :put_internal_field,
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecodeBytecodeOperandsForCheckpointh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecode/BytecodeOperandsForCheckpoint.h (282477 => 282478)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/BytecodeOperandsForCheckpoint.h     2021-09-15 22:12:01 UTC (rev 282477)
+++ trunk/Source/JavaScriptCore/bytecode/BytecodeOperandsForCheckpoint.h        2021-09-15 22:18:52 UTC (rev 282478)
</span><span class="lines">@@ -57,20 +57,20 @@
</span><span class="cx">     UNUSED_PARAM(checkpointIndex);
</span><span class="cx">     if constexpr (BytecodeMetadata::opcodeID == op_iterator_open) {
</span><span class="cx">         switch (checkpointIndex) {
</span><del>-        case OpIteratorOpen::symbolCall: return &metadata.m_iteratorProfile;
-        case OpIteratorOpen::getNext: return &metadata.m_nextProfile;
</del><ins>+        case OpIteratorOpen::symbolCall: return metadata.m_iteratorProfile;
+        case OpIteratorOpen::getNext: return metadata.m_nextProfile;
</ins><span class="cx">         default: RELEASE_ASSERT_NOT_REACHED();
</span><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">     } else if constexpr (BytecodeMetadata::opcodeID == op_iterator_next) {
</span><span class="cx">         switch (checkpointIndex) {
</span><del>-        case OpIteratorNext::computeNext: return &metadata.m_nextResultProfile;
-        case OpIteratorNext::getDone: return &metadata.m_doneProfile;
-        case OpIteratorNext::getValue: return &metadata.m_valueProfile;
</del><ins>+        case OpIteratorNext::computeNext: return metadata.m_nextResultProfile;
+        case OpIteratorNext::getDone: return metadata.m_doneProfile;
+        case OpIteratorNext::getValue: return metadata.m_valueProfile;
</ins><span class="cx">         default: RELEASE_ASSERT_NOT_REACHED();
</span><span class="cx">         }
</span><span class="cx">     } else 
</span><del>-        return &metadata.m_profile;
</del><ins>+        return metadata.m_profile;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> template<typename BytecodeMetadata>
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecodeCodeBlockcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecode/CodeBlock.cpp (282477 => 282478)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/CodeBlock.cpp       2021-09-15 22:12:01 UTC (rev 282477)
+++ trunk/Source/JavaScriptCore/bytecode/CodeBlock.cpp  2021-09-15 22:18:52 UTC (rev 282478)
</span><span class="lines">@@ -374,6 +374,10 @@
</span><span class="cx"> bool CodeBlock::finishCreation(VM& vm, ScriptExecutable* ownerExecutable, UnlinkedCodeBlock* unlinkedCodeBlock,
</span><span class="cx">     JSScope* scope)
</span><span class="cx"> {
</span><ins>+    // We can't finalize a GC while in here since we need to make sure to
+    // make sure our ValueProfiles and ArrayProfiles all point to proper locations.
+    RELEASE_ASSERT(vm.heap.isDeferred()); 
+
</ins><span class="cx">     Base::finishCreation(vm);
</span><span class="cx">     finishCreationCommon(vm);
</span><span class="cx"> 
</span><span class="lines">@@ -383,9 +387,12 @@
</span><span class="cx">         vm.functionHasExecutedCache()->removeUnexecutedRange(ownerExecutable->sourceID(), ownerExecutable->typeProfilingStartOffset(vm), ownerExecutable->typeProfilingEndOffset(vm));
</span><span class="cx"> 
</span><span class="cx">     ScriptExecutable* topLevelExecutable = ownerExecutable->topLevelExecutable();
</span><del>-    setConstantRegisters(unlinkedCodeBlock->constantRegisters(), unlinkedCodeBlock->constantsSourceCodeRepresentation(), topLevelExecutable);
-    RETURN_IF_EXCEPTION(throwScope, false);
</del><span class="cx"> 
</span><ins>+    // We wait to initialize template objects until the end of finishCreation beecause it can
+    // throw. We rely on linking to put the CodeBlock into a coherent state, so we can't throw
+    // until we're all done linking.
+    Vector<unsigned> templateObjectIndices = setConstantRegisters(unlinkedCodeBlock->constantRegisters(), unlinkedCodeBlock->constantsSourceCodeRepresentation());
+
</ins><span class="cx">     // We already have the cloned symbol table for the module environment since we need to instantiate
</span><span class="cx">     // the module environments before linking the code block. We replace the stored symbol table with the already cloned one.
</span><span class="cx">     if (UnlinkedModuleProgramCodeBlock* unlinkedModuleProgramCodeBlock = jsDynamicCast<UnlinkedModuleProgramCodeBlock*>(vm, unlinkedCodeBlock)) {
</span><span class="lines">@@ -435,7 +442,8 @@
</span><span class="cx">     // Bookkeep the strongly referenced module environments.
</span><span class="cx">     HashSet<JSModuleEnvironment*> stronglyReferencedModuleEnvironments;
</span><span class="cx"> 
</span><del>-    auto link_profile = [&](const auto& /*instruction*/, auto /*bytecode*/, auto& /*metadata*/) {
</del><ins>+    auto link_profile = [&](const auto& /*instruction*/, auto /*bytecode*/, auto& metadata) {
+        static_assert(std::is_same_v<ValueProfile*, decltype(metadata.m_profile)>);
</ins><span class="cx">         m_numberOfNonArgumentValueProfiles++;
</span><span class="cx">     };
</span><span class="cx"> 
</span><span class="lines">@@ -499,9 +507,9 @@
</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)
</del><ins>+        LINK(OpEnumeratorNext)
+        LINK(OpEnumeratorInByVal)
+        LINK(OpEnumeratorHasOwnProperty)
</ins><span class="cx">         LINK(OpEnumeratorGetByVal, profile)
</span><span class="cx"> 
</span><span class="cx">         LINK(OpCall, profile)
</span><span class="lines">@@ -563,7 +571,6 @@
</span><span class="cx">             RELEASE_ASSERT(bytecode.m_resolveType != ResolvedClosureVar);
</span><span class="cx"> 
</span><span class="cx">             ResolveOp op = JSScope::abstractResolve(m_globalObject.get(), bytecode.m_localScopeDepth, scope, ident, Get, bytecode.m_resolveType, InitializationMode::NotInitialization);
</span><del>-            RETURN_IF_EXCEPTION(throwScope, false);
</del><span class="cx"> 
</span><span class="cx">             metadata.m_resolveType = op.type;
</span><span class="cx">             metadata.m_localScopeDepth = op.depth;
</span><span class="lines">@@ -598,7 +605,6 @@
</span><span class="cx"> 
</span><span class="cx">             const Identifier& ident = identifier(bytecode.m_var);
</span><span class="cx">             ResolveOp op = JSScope::abstractResolve(m_globalObject.get(), bytecode.m_localScopeDepth, scope, ident, Get, bytecode.m_getPutInfo.resolveType(), InitializationMode::NotInitialization);
</span><del>-            RETURN_IF_EXCEPTION(throwScope, false);
</del><span class="cx"> 
</span><span class="cx">             metadata.m_getPutInfo = GetPutInfo(bytecode.m_getPutInfo.resolveMode(), op.type, bytecode.m_getPutInfo.initializationMode(), bytecode.m_getPutInfo.ecmaMode());
</span><span class="cx">             if (op.type == ModuleVar)
</span><span class="lines">@@ -632,7 +638,6 @@
</span><span class="cx">             const Identifier& ident = identifier(bytecode.m_var);
</span><span class="cx">             metadata.m_watchpointSet = nullptr;
</span><span class="cx">             ResolveOp op = JSScope::abstractResolve(m_globalObject.get(), bytecode.m_symbolTableOrScopeDepth.scopeDepth(), scope, ident, Put, bytecode.m_getPutInfo.resolveType(), bytecode.m_getPutInfo.initializationMode());
</span><del>-            RETURN_IF_EXCEPTION(throwScope, false);
</del><span class="cx"> 
</span><span class="cx">             metadata.m_getPutInfo = GetPutInfo(bytecode.m_getPutInfo.resolveMode(), op.type, bytecode.m_getPutInfo.initializationMode(), bytecode.m_getPutInfo.ecmaMode());
</span><span class="cx">             if (op.type == GlobalVar || op.type == GlobalVarWithVarInjectionChecks || op.type == GlobalLexicalVar || op.type == GlobalLexicalVarWithVarInjectionChecks)
</span><span class="lines">@@ -665,7 +670,6 @@
</span><span class="cx">                 // Even though type profiling may be profiling either a Get or a Put, we can always claim a Get because
</span><span class="cx">                 // we're abstractly "read"ing from a JSScope.
</span><span class="cx">                 ResolveOp op = JSScope::abstractResolve(m_globalObject.get(), localScopeDepth, scope, ident, Get, bytecode.m_resolveType, InitializationMode::NotInitialization);
</span><del>-                RETURN_IF_EXCEPTION(throwScope, false);
</del><span class="cx"> 
</span><span class="cx">                 if (op.type == ClosureVar || op.type == ModuleVar)
</span><span class="cx">                     symbolTable = op.lexicalEnvironment->symbolTable();
</span><span class="lines">@@ -761,6 +765,56 @@
</span><span class="cx"> #undef LINK_FIELD
</span><span class="cx"> #undef LINK
</span><span class="cx"> 
</span><ins>+    {
+        unsigned index = numberOfArgumentValueProfiles(); // The first numberOfArgumentValueProfiles() profiles are argument value profiles
+
+        if (m_metadata) {
+            auto assign = [&] (ValueProfile*& profile) {
+                profile = &unlinkedCodeBlock->valueProfile(index++);
+            };
+
+#define VISIT(__op) \
+            m_metadata->forEach<__op>([&] (auto& metadata) { assign(metadata.m_profile); });
+            FOR_EACH_OPCODE_WITH_VALUE_PROFILE(VISIT)
+#undef VISIT
+
+            m_metadata->forEach<OpIteratorOpen>([&] (auto& metadata) { 
+                assign(metadata.m_iterableProfile);
+                assign(metadata.m_iteratorProfile);
+                assign(metadata.m_nextProfile);
+            });
+
+            m_metadata->forEach<OpIteratorNext>([&] (auto& metadata) {
+                assign(metadata.m_nextResultProfile);
+                assign(metadata.m_doneProfile);
+                assign(metadata.m_valueProfile);
+            });
+        }
+
+        RELEASE_ASSERT(index == unlinkedCodeBlock->numValueProfiles());
+    }
+
+    if (m_metadata) {
+        unsigned index = 0;
+
+        auto assign = [&] (ArrayProfile*& profile) {
+            profile = &unlinkedCodeBlock->arrayProfile(index++);
+        };
+
+        // We only share array profiles for the opcodes in FOR_EACH_OPCODE_WITH_ARRAY_PROFILE.
+        // We don't yet share array profiles for things with LLInt CallLinkInfos.
+#define VISIT(__op) \
+        m_metadata->forEach<__op>([&] (auto& metadata) { assign(metadata.m_arrayProfile); });
+        FOR_EACH_OPCODE_WITH_ARRAY_PROFILE(VISIT)
+#undef VISIT
+
+        m_metadata->forEach<OpIteratorNext>([&] (auto& metadata) {
+            assign(metadata.m_iterableProfile);
+        });
+
+        RELEASE_ASSERT(index == unlinkedCodeBlock->numArrayProfiles());
+    }
+
</ins><span class="cx">     if (m_unlinkedCode->wasCompiledWithControlFlowProfilerOpcodes())
</span><span class="cx">         insertBasicBlockBoundariesForControlFlowProfiler();
</span><span class="cx"> 
</span><span class="lines">@@ -781,6 +835,9 @@
</span><span class="cx">     if (m_metadata)
</span><span class="cx">         vm.heap.reportExtraMemoryAllocated(m_metadata->sizeInBytes());
</span><span class="cx"> 
</span><ins>+    initializeTemplateObjects(topLevelExecutable, templateObjectIndices);
+    RETURN_IF_EXCEPTION(throwScope, false);
+
</ins><span class="cx">     return true;
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -869,19 +926,20 @@
</span><span class="cx"> #endif // ENABLE(JIT)
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void CodeBlock::setConstantRegisters(const FixedVector<WriteBarrier<Unknown>>& constants, const FixedVector<SourceCodeRepresentation>& constantsSourceCodeRepresentation, ScriptExecutable* topLevelExecutable)
</del><ins>+Vector<unsigned> CodeBlock::setConstantRegisters(const FixedVector<WriteBarrier<Unknown>>& constants, const FixedVector<SourceCodeRepresentation>& constantsSourceCodeRepresentation)
</ins><span class="cx"> {
</span><span class="cx">     VM& vm = *m_vm;
</span><del>-    auto scope = DECLARE_THROW_SCOPE(vm);
</del><span class="cx">     JSGlobalObject* globalObject = m_globalObject.get();
</span><span class="cx"> 
</span><ins>+    Vector<unsigned> templateObjectIndices;
+
</ins><span class="cx">     ASSERT(constants.size() == constantsSourceCodeRepresentation.size());
</span><del>-    size_t count = constants.size();
</del><ins>+    unsigned count = constants.size();
</ins><span class="cx">     {
</span><span class="cx">         ConcurrentJSLocker locker(m_lock);
</span><span class="cx">         m_constantRegisters.resizeToFit(count);
</span><span class="cx">     }
</span><del>-    for (size_t i = 0; i < count; i++) {
</del><ins>+    for (unsigned i = 0; i < count; i++) {
</ins><span class="cx">         JSValue constant = constants[i].get();
</span><span class="cx">         SourceCodeRepresentation representation = constantsSourceCodeRepresentation[i];
</span><span class="cx">         switch (representation) {
</span><span class="lines">@@ -905,11 +963,8 @@
</span><span class="cx">                             clone->setRareDataCodeBlock(this);
</span><span class="cx"> 
</span><span class="cx">                         constant = clone;
</span><del>-                    } else if (auto* descriptor = jsDynamicCast<JSTemplateObjectDescriptor*>(vm, cell)) {
-                        auto* templateObject = topLevelExecutable->createTemplateObject(globalObject, descriptor);
-                        RETURN_IF_EXCEPTION(scope, void());
-                        constant = templateObject;
-                    }
</del><ins>+                    } else if (jsDynamicCast<JSTemplateObjectDescriptor*>(vm, cell))
+                        templateObjectIndices.append(i);
</ins><span class="cx">                 }
</span><span class="cx">             }
</span><span class="cx">             break;
</span><span class="lines">@@ -916,8 +971,21 @@
</span><span class="cx">         }
</span><span class="cx">         m_constantRegisters[i].set(vm, this, constant);
</span><span class="cx">     }
</span><ins>+
+    return templateObjectIndices;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void CodeBlock::initializeTemplateObjects(ScriptExecutable* topLevelExecutable, const Vector<unsigned>& templateObjectIndices)
+{
+    auto scope = DECLARE_THROW_SCOPE(vm());
+    for (unsigned i : templateObjectIndices) {
+        auto* descriptor = jsCast<JSTemplateObjectDescriptor*>(m_constantRegisters[i].get());
+        auto* templateObject = topLevelExecutable->createTemplateObject(globalObject(), descriptor);
+        RETURN_IF_EXCEPTION(scope, void());
+        m_constantRegisters[i].set(vm(), this, templateObject);
+    }
+}
+
</ins><span class="cx"> void CodeBlock::setAlternative(VM& vm, CodeBlock* alternative)
</span><span class="cx"> {
</span><span class="cx">     RELEASE_ASSERT(alternative);
</span><span class="lines">@@ -928,8 +996,6 @@
</span><span class="cx"> void CodeBlock::setNumParameters(unsigned newValue)
</span><span class="cx"> {
</span><span class="cx">     m_numParameters = newValue;
</span><del>-
-    m_argumentValueProfiles = FixedVector<ValueProfile>(Options::useJIT() ? newValue : 0);
</del><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> CodeBlock* CodeBlock::specialOSREntryBlockOrNull()
</span><span class="lines">@@ -990,7 +1056,7 @@
</span><span class="cx">     stronglyVisitStrongReferences(locker, visitor);
</span><span class="cx">     stronglyVisitWeakReferences(locker, visitor);
</span><span class="cx">     
</span><del>-    VM::SpaceAndSet::setFor(*subspace()).add(this);
</del><ins>+    vm().codeBlockSpace.set.add(this);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> template<typename Visitor>
</span><span class="lines">@@ -1517,8 +1583,36 @@
</span><span class="cx"> {
</span><span class="cx">     UNUSED_PARAM(vm);
</span><span class="cx"> 
</span><del>-    updateAllPredictions();
</del><ins>+    {
+        // We only update the profiles that the UnlinkedCodeBlock doesn't own.
</ins><span class="cx"> 
</span><ins>+        if (m_metadata) {
+#define UPDATE(__op) \
+            m_metadata->forEach<__op>([&] (auto& metadata) { metadata.m_callLinkInfo.m_arrayProfile.computeUpdatedPrediction(this); });
+            FOR_EACH_OPCODE_WITH_LLINT_CALL_LINK_INFO(UPDATE)
+#undef UPDATE
+
+            m_metadata->forEach<OpCatch>([&](auto& metadata) {
+                if (metadata.m_buffer) {
+                    metadata.m_buffer->forEach([&](ValueProfileAndVirtualRegister& profile) {
+                        profile.computeUpdatedPrediction();
+                    });
+                }
+            });
+        }
+
+        {
+            ConcurrentJSLocker locker(m_lock);
+#if ENABLE(DFG_JIT)
+            lazyOperandValueProfiles(locker).computeUpdatedPredictions(locker);
+#endif
+        }
+
+        forEachArrayAllocationProfile([&](ArrayAllocationProfile& profile) {
+            profile.updateProfile();
+        });
+    }
+
</ins><span class="cx"> #if ENABLE(JIT)
</span><span class="cx">     bool isEligibleForLLIntDowngrade = m_isEligibleForLLIntDowngrade;
</span><span class="cx">     m_isEligibleForLLIntDowngrade = false;
</span><span class="lines">@@ -1603,7 +1697,7 @@
</span><span class="cx">     };
</span><span class="cx">     updateActivity();
</span><span class="cx"> 
</span><del>-    VM::SpaceAndSet::setFor(*subspace()).remove(this);
</del><ins>+    vm.codeBlockSpace.set.remove(this);
</ins><span class="cx"> 
</span><span class="cx">     // In CodeBlock::shouldVisitStrongly() we may have decided to skip visiting this
</span><span class="cx">     // codeBlock. By the time we get here, we're done with the verifier GC. So, let's
</span><span class="lines">@@ -2773,7 +2867,7 @@
</span><span class="cx">     switch (instruction->opcodeID()) {
</span><span class="cx"> #define CASE1(Op) \
</span><span class="cx">     case Op::opcodeID: \
</span><del>-        return &instruction->as<Op>().metadata(this).m_arrayProfile;
</del><ins>+        return instruction->as<Op>().metadata(this).m_arrayProfile;
</ins><span class="cx"> 
</span><span class="cx"> #define CASE2(Op) \
</span><span class="cx">     case Op::opcodeID: \
</span><span class="lines">@@ -2785,13 +2879,6 @@
</span><span class="cx"> #undef CASE1
</span><span class="cx"> #undef CASE2
</span><span class="cx"> 
</span><del>-    case OpGetById::opcodeID: {
-        auto bytecode = instruction->as<OpGetById>();
-        auto& metadata = bytecode.metadata(this);
-        if (metadata.m_modeMetadata.mode == GetByIdMode::ArrayLength)
-            return &metadata.m_modeMetadata.arrayLengthMode.arrayProfile;
-        break;
-    }
</del><span class="cx">     default:
</span><span class="cx">         break;
</span><span class="cx">     }
</span><span class="lines">@@ -2900,12 +2987,12 @@
</span><span class="cx">             numSamples = ValueProfile::numberOfBuckets; // We don't want profiles that are extremely hot to be given more weight.
</span><span class="cx">         numberOfSamplesInProfiles += numSamples;
</span><span class="cx">         if (isArgument) {
</span><del>-            profile.computeUpdatedPrediction(locker);
</del><ins>+            profile.computeUpdatedPrediction();
</ins><span class="cx">             return;
</span><span class="cx">         }
</span><span class="cx">         if (profile.numberOfSamples() || profile.isSampledBefore())
</span><span class="cx">             numberOfLiveNonArgumentValueProfiles++;
</span><del>-        profile.computeUpdatedPrediction(locker);
</del><ins>+        profile.computeUpdatedPrediction();
</ins><span class="cx">     });
</span><span class="cx"> 
</span><span class="cx">     if (m_metadata) {
</span><span class="lines">@@ -2912,7 +2999,7 @@
</span><span class="cx">         m_metadata->forEach<OpCatch>([&](auto& metadata) {
</span><span class="cx">             if (metadata.m_buffer) {
</span><span class="cx">                 metadata.m_buffer->forEach([&](ValueProfileAndVirtualRegister& profile) {
</span><del>-                    profile.computeUpdatedPrediction(locker);
</del><ins>+                    profile.computeUpdatedPrediction();
</ins><span class="cx">                 });
</span><span class="cx">             }
</span><span class="cx">         });
</span><span class="lines">@@ -2931,10 +3018,8 @@
</span><span class="cx"> 
</span><span class="cx"> void CodeBlock::updateAllArrayPredictions()
</span><span class="cx"> {
</span><del>-    ConcurrentJSLocker locker(m_lock);
-    
</del><span class="cx">     forEachArrayProfile([&](ArrayProfile& profile) {
</span><del>-        profile.computeUpdatedPrediction(locker, this);
</del><ins>+        profile.computeUpdatedPrediction(this);
</ins><span class="cx">     });
</span><span class="cx">     
</span><span class="cx">     forEachArrayAllocationProfile([&](ArrayAllocationProfile& profile) {
</span><span class="lines">@@ -3164,7 +3249,7 @@
</span><span class="cx"> 
</span><span class="cx"> #define CASE(Op) \
</span><span class="cx">     case Op::opcodeID: \
</span><del>-        return &instruction->as<Op>().metadata(this).m_profile;
</del><ins>+        return instruction->as<Op>().metadata(this).m_profile;
</ins><span class="cx"> 
</span><span class="cx">         FOR_EACH_OPCODE_WITH_VALUE_PROFILE(CASE)
</span><span class="cx"> 
</span><span class="lines">@@ -3181,10 +3266,10 @@
</span><span class="cx">     }
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-SpeculatedType CodeBlock::valueProfilePredictionForBytecodeIndex(const ConcurrentJSLocker& locker, BytecodeIndex bytecodeIndex)
</del><ins>+SpeculatedType CodeBlock::valueProfilePredictionForBytecodeIndex(BytecodeIndex bytecodeIndex)
</ins><span class="cx"> {
</span><span class="cx">     if (ValueProfile* valueProfile = tryGetValueProfileForBytecodeIndex(bytecodeIndex))
</span><del>-        return valueProfile->computeUpdatedPrediction(locker);
</del><ins>+        return valueProfile->computeUpdatedPrediction();
</ins><span class="cx">     return SpecNone;
</span><span class="cx"> }
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecodeCodeBlockh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecode/CodeBlock.h (282477 => 282478)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/CodeBlock.h 2021-09-15 22:12:01 UTC (rev 282477)
+++ trunk/Source/JavaScriptCore/bytecode/CodeBlock.h    2021-09-15 22:18:52 UTC (rev 282478)
</span><span class="lines">@@ -144,6 +144,7 @@
</span><span class="cx">     JS_EXPORT_PRIVATE ~CodeBlock();
</span><span class="cx"> 
</span><span class="cx">     UnlinkedCodeBlock* unlinkedCodeBlock() const { return m_unlinkedCode.get(); }
</span><ins>+    static ptrdiff_t offsetOfUnlinkedCodeBlock() { return OBJECT_OFFSETOF(CodeBlock, m_unlinkedCode); }
</ins><span class="cx"> 
</span><span class="cx">     CString inferredName() const;
</span><span class="cx">     CodeBlockHash hash() const;
</span><span class="lines">@@ -474,19 +475,16 @@
</span><span class="cx"> 
</span><span class="cx">     unsigned numberOfArgumentValueProfiles()
</span><span class="cx">     {
</span><del>-        ASSERT(m_argumentValueProfiles.size() == static_cast<unsigned>(m_numParameters) || !Options::useJIT());
-        return m_argumentValueProfiles.size();
</del><ins>+        return numParameters();
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     ValueProfile& valueProfileForArgument(unsigned argumentIndex)
</span><span class="cx">     {
</span><del>-        ASSERT(Options::useJIT()); // This is only called from the various JIT compilers or places that first check numberOfArgumentValueProfiles before calling this.
-        ValueProfile& result = m_argumentValueProfiles[argumentIndex];
-        return result;
</del><ins>+        return unlinkedCodeBlock()->valueProfile(argumentIndex);
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     ValueProfile& valueProfileForBytecodeIndex(BytecodeIndex);
</span><del>-    SpeculatedType valueProfilePredictionForBytecodeIndex(const ConcurrentJSLocker&, BytecodeIndex);
</del><ins>+    SpeculatedType valueProfilePredictionForBytecodeIndex(BytecodeIndex);
</ins><span class="cx"> 
</span><span class="cx">     template<typename Functor> void forEachValueProfile(const Functor&);
</span><span class="cx">     template<typename Functor> void forEachArrayProfile(const Functor&);
</span><span class="lines">@@ -886,7 +884,8 @@
</span><span class="cx">     Metadata& metadata(OpcodeID opcodeID, unsigned metadataID)
</span><span class="cx">     {
</span><span class="cx">         ASSERT(m_metadata);
</span><del>-        return bitwise_cast<Metadata*>(m_metadata->get(opcodeID))[metadataID];
</del><ins>+        ASSERT_UNUSED(opcodeID, opcodeID == Metadata::opcodeID);
+        return m_metadata->get<Metadata>()[metadataID];
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     template<typename Metadata>
</span><span class="lines">@@ -939,7 +938,8 @@
</span><span class="cx"> 
</span><span class="cx">     void updateAllValueProfilePredictionsAndCountLiveness(unsigned& numberOfLiveNonArgumentValueProfiles, unsigned& numberOfSamplesInProfiles);
</span><span class="cx"> 
</span><del>-    void setConstantRegisters(const FixedVector<WriteBarrier<Unknown>>& constants, const FixedVector<SourceCodeRepresentation>& constantsSourceCodeRepresentation, ScriptExecutable* topLevelExecutable);
</del><ins>+    Vector<unsigned> setConstantRegisters(const FixedVector<WriteBarrier<Unknown>>& constants, const FixedVector<SourceCodeRepresentation>& constantsSourceCodeRepresentation);
+    void initializeTemplateObjects(ScriptExecutable* topLevelExecutable, const Vector<unsigned>&);
</ins><span class="cx"> 
</span><span class="cx">     void replaceConstant(VirtualRegister reg, JSValue value)
</span><span class="cx">     {
</span><span class="lines">@@ -1015,7 +1015,6 @@
</span><span class="cx">     // for DFG code blocks.
</span><span class="cx">     CompressedLazyOperandValueProfileHolder m_lazyOperandValueProfiles;
</span><span class="cx"> #endif
</span><del>-    FixedVector<ValueProfile> m_argumentValueProfiles;
</del><span class="cx"> 
</span><span class="cx">     // Constant Pool
</span><span class="cx">     COMPILE_ASSERT(sizeof(Register) == sizeof(WriteBarrier<Unknown>), Register_must_be_same_size_as_WriteBarrier_Unknown);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecodeCodeBlockInlinesh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecode/CodeBlockInlines.h (282477 => 282478)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/CodeBlockInlines.h  2021-09-15 22:12:01 UTC (rev 282477)
+++ trunk/Source/JavaScriptCore/bytecode/CodeBlockInlines.h     2021-09-15 22:18:52 UTC (rev 282478)
</span><span class="lines">@@ -39,7 +39,7 @@
</span><span class="cx"> 
</span><span class="cx">     if (m_metadata) {
</span><span class="cx"> #define VISIT(__op) \
</span><del>-        m_metadata->forEach<__op>([&] (auto& metadata) { func(metadata.m_profile, false); });
</del><ins>+        m_metadata->forEach<__op>([&] (auto& metadata) { func(*metadata.m_profile, false); });
</ins><span class="cx"> 
</span><span class="cx">         FOR_EACH_OPCODE_WITH_VALUE_PROFILE(VISIT)
</span><span class="cx"> 
</span><span class="lines">@@ -46,15 +46,15 @@
</span><span class="cx"> #undef VISIT
</span><span class="cx"> 
</span><span class="cx">         m_metadata->forEach<OpIteratorOpen>([&] (auto& metadata) { 
</span><del>-            func(metadata.m_iterableProfile, false);
-            func(metadata.m_iteratorProfile, false);
-            func(metadata.m_nextProfile, false);
</del><ins>+            func(*metadata.m_iterableProfile, false);
+            func(*metadata.m_iteratorProfile, false);
+            func(*metadata.m_nextProfile, false);
</ins><span class="cx">         });
</span><span class="cx"> 
</span><span class="cx">         m_metadata->forEach<OpIteratorNext>([&] (auto& metadata) {
</span><del>-            func(metadata.m_nextResultProfile, false);
-            func(metadata.m_doneProfile, false);
-            func(metadata.m_valueProfile, false);
</del><ins>+            func(*metadata.m_nextResultProfile, false);
+            func(*metadata.m_doneProfile, false);
+            func(*metadata.m_valueProfile, false);
</ins><span class="cx">         });
</span><span class="cx">     }   
</span><span class="cx"> 
</span><span class="lines">@@ -64,13 +64,8 @@
</span><span class="cx"> void CodeBlock::forEachArrayProfile(const Functor& func)
</span><span class="cx"> {
</span><span class="cx">     if (m_metadata) {
</span><del>-        m_metadata->forEach<OpGetById>([&] (auto& metadata) {
-            if (metadata.m_modeMetadata.mode == GetByIdMode::ArrayLength)
-                func(metadata.m_modeMetadata.arrayLengthMode.arrayProfile);
-        });
-
</del><span class="cx"> #define VISIT1(__op) \
</span><del>-    m_metadata->forEach<__op>([&] (auto& metadata) { func(metadata.m_arrayProfile); });
</del><ins>+    m_metadata->forEach<__op>([&] (auto& metadata) { func(*metadata.m_arrayProfile); });
</ins><span class="cx"> 
</span><span class="cx"> #define VISIT2(__op) \
</span><span class="cx">     m_metadata->forEach<__op>([&] (auto& metadata) { func(metadata.m_callLinkInfo.m_arrayProfile); });
</span><span class="lines">@@ -82,7 +77,7 @@
</span><span class="cx"> #undef VISIT2
</span><span class="cx"> 
</span><span class="cx">         m_metadata->forEach<OpIteratorNext>([&] (auto& metadata) {
</span><del>-            func(metadata.m_iterableProfile);
</del><ins>+            func(*metadata.m_iterableProfile);
</ins><span class="cx">         });
</span><span class="cx">     }
</span><span class="cx"> }
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecodeDFGExitProfilecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecode/DFGExitProfile.cpp (282477 => 282478)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/DFGExitProfile.cpp  2021-09-15 22:12:01 UTC (rev 282477)
+++ trunk/Source/JavaScriptCore/bytecode/DFGExitProfile.cpp     2021-09-15 22:18:52 UTC (rev 282478)
</span><span class="lines">@@ -89,6 +89,19 @@
</span><span class="cx">     return result;
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+bool ExitProfile::hasAnyExitsAt(const ConcurrentJSLocker&, BytecodeIndex bytecodeIndex) const
+{
+    if (!m_frequentExitSites)
+        return false;
+
+    for (unsigned i = 0; i < m_frequentExitSites->size(); ++i) {
+        if (m_frequentExitSites->at(i).bytecodeIndex() == bytecodeIndex)
+            return true;
+    }
+
+    return false;
+}
+
</ins><span class="cx"> bool ExitProfile::hasExitSite(const ConcurrentJSLocker&, const FrequentExitSite& site) const
</span><span class="cx"> {
</span><span class="cx">     if (!m_frequentExitSites)
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecodeDFGExitProfileh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecode/DFGExitProfile.h (282477 => 282478)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/DFGExitProfile.h    2021-09-15 22:12:01 UTC (rev 282477)
+++ trunk/Source/JavaScriptCore/bytecode/DFGExitProfile.h       2021-09-15 22:18:52 UTC (rev 282478)
</span><span class="lines">@@ -182,6 +182,8 @@
</span><span class="cx">     // Get the frequent exit sites for a bytecode index. This is O(n), and is
</span><span class="cx">     // meant to only be used from debugging/profiling code.
</span><span class="cx">     Vector<FrequentExitSite> exitSitesFor(BytecodeIndex);
</span><ins>+
+    bool hasAnyExitsAt(const ConcurrentJSLocker&, BytecodeIndex) const;
</ins><span class="cx">     
</span><span class="cx">     // This is O(n) and should be called on less-frequently executed code paths
</span><span class="cx">     // in the compiler. It should be strictly cheaper than building a
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecodeGetByIdMetadatah"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecode/GetByIdMetadata.h (282477 => 282478)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/GetByIdMetadata.h   2021-09-15 22:12:01 UTC (rev 282477)
+++ trunk/Source/JavaScriptCore/bytecode/GetByIdMetadata.h      2021-09-15 22:18:52 UTC (rev 282478)
</span><span class="lines">@@ -48,11 +48,6 @@
</span><span class="cx"> };
</span><span class="cx"> static_assert(sizeof(GetByIdModeMetadataUnset) == 12);
</span><span class="cx"> 
</span><del>-struct GetByIdModeMetadataArrayLength {
-    ArrayProfile arrayProfile;
-};
-static_assert(sizeof(GetByIdModeMetadataArrayLength) == 12);
-
</del><span class="cx"> struct GetByIdModeMetadataProtoLoad {
</span><span class="cx">     StructureID structureID;
</span><span class="cx">     PropertyOffset cachedOffset;
</span><span class="lines">@@ -90,7 +85,6 @@
</span><span class="cx">     };
</span><span class="cx">     GetByIdModeMetadataDefault defaultMode;
</span><span class="cx">     GetByIdModeMetadataUnset unsetMode;
</span><del>-    GetByIdModeMetadataArrayLength arrayLengthMode;
</del><span class="cx">     GetByIdModeMetadataProtoLoad protoLoadMode;
</span><span class="cx"> };
</span><span class="cx"> static_assert(sizeof(GetByIdModeMetadata) == 16);
</span><span class="lines">@@ -113,7 +107,6 @@
</span><span class="cx">     union {
</span><span class="cx">         GetByIdModeMetadataDefault defaultMode;
</span><span class="cx">         GetByIdModeMetadataUnset unsetMode;
</span><del>-        GetByIdModeMetadataArrayLength arrayLengthMode;
</del><span class="cx">         GetByIdModeMetadataProtoLoad protoLoadMode;
</span><span class="cx">     };
</span><span class="cx">     GetByIdMode mode;
</span><span class="lines">@@ -137,7 +130,6 @@
</span><span class="cx"> inline void GetByIdModeMetadata::setArrayLengthMode()
</span><span class="cx"> {
</span><span class="cx">     mode = GetByIdMode::ArrayLength;
</span><del>-    new (&arrayLengthMode.arrayProfile) ArrayProfile;
</del><span class="cx">     // Prevent the prototype cache from ever happening.
</span><span class="cx">     hitCountForLLIntCaching = 0;
</span><span class="cx"> }
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecodeLazyOperandValueProfilecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecode/LazyOperandValueProfile.cpp (282477 => 282478)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/LazyOperandValueProfile.cpp 2021-09-15 22:12:01 UTC (rev 282477)
+++ trunk/Source/JavaScriptCore/bytecode/LazyOperandValueProfile.cpp    2021-09-15 22:18:52 UTC (rev 282478)
</span><span class="lines">@@ -33,13 +33,13 @@
</span><span class="cx"> CompressedLazyOperandValueProfileHolder::CompressedLazyOperandValueProfileHolder() { }
</span><span class="cx"> CompressedLazyOperandValueProfileHolder::~CompressedLazyOperandValueProfileHolder() { }
</span><span class="cx"> 
</span><del>-void CompressedLazyOperandValueProfileHolder::computeUpdatedPredictions(const ConcurrentJSLocker& locker)
</del><ins>+void CompressedLazyOperandValueProfileHolder::computeUpdatedPredictions(const ConcurrentJSLocker&)
</ins><span class="cx"> {
</span><span class="cx">     if (!m_data)
</span><span class="cx">         return;
</span><span class="cx">     
</span><span class="cx">     for (unsigned i = 0; i < m_data->size(); ++i)
</span><del>-        m_data->at(i).computeUpdatedPrediction(locker);
</del><ins>+        m_data->at(i).computeUpdatedPrediction();
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> LazyOperandValueProfile* CompressedLazyOperandValueProfileHolder::add(
</span><span class="lines">@@ -87,13 +87,13 @@
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> SpeculatedType LazyOperandValueProfileParser::prediction(
</span><del>-    const ConcurrentJSLocker& locker, const LazyOperandValueProfileKey& key) const
</del><ins>+    const ConcurrentJSLocker&, const LazyOperandValueProfileKey& key) const
</ins><span class="cx"> {
</span><span class="cx">     LazyOperandValueProfile* profile = getIfPresent(key);
</span><span class="cx">     if (!profile)
</span><span class="cx">         return SpecNone;
</span><span class="cx">     
</span><del>-    return profile->computeUpdatedPrediction(locker);
</del><ins>+    return profile->computeUpdatedPrediction();
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> } // namespace JSC
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecodeMetadataTablecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecode/MetadataTable.cpp (282477 => 282478)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/MetadataTable.cpp   2021-09-15 22:12:01 UTC (rev 282477)
+++ trunk/Source/JavaScriptCore/bytecode/MetadataTable.cpp      2021-09-15 22:18:52 UTC (rev 282478)
</span><span class="lines">@@ -44,9 +44,11 @@
</span><span class="cx">     template<typename Op>
</span><span class="cx">     static void withOpcodeType(MetadataTable* table)
</span><span class="cx">     {
</span><del>-        table->forEach<Op>([](auto& entry) {
-            entry.~Metadata();
-        });
</del><ins>+        if constexpr (static_cast<unsigned>(Op::opcodeID) < NUMBER_OF_BYTECODE_WITH_METADATA) {
+            table->forEach<Op>([](auto& entry) {
+                entry.~Metadata();
+            });
+        }
</ins><span class="cx">     }
</span><span class="cx"> };
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecodeMetadataTableh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecode/MetadataTable.h (282477 => 282478)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/MetadataTable.h     2021-09-15 22:12:01 UTC (rev 282477)
+++ trunk/Source/JavaScriptCore/bytecode/MetadataTable.h        2021-09-15 22:18:52 UTC (rev 282478)
</span><span class="lines">@@ -46,18 +46,22 @@
</span><span class="cx"> public:
</span><span class="cx">     ~MetadataTable();
</span><span class="cx"> 
</span><del>-    ALWAYS_INLINE Instruction::Metadata* get(OpcodeID opcodeID)
</del><ins>+    template<typename Metadata>
+    ALWAYS_INLINE Metadata* get()
</ins><span class="cx">     {
</span><ins>+        auto opcodeID = Metadata::opcodeID;
</ins><span class="cx">         ASSERT(opcodeID < NUMBER_OF_BYTECODE_WITH_METADATA);
</span><del>-        return reinterpret_cast<Instruction::Metadata*>(getImpl(opcodeID));
</del><ins>+        uintptr_t ptr = bitwise_cast<uintptr_t>(getWithoutAligning(opcodeID));
+        ptr = roundUpToMultipleOf(alignof(Metadata), ptr);
+        return bitwise_cast<Metadata*>(ptr);
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     template<typename Op, typename Functor>
</span><span class="cx">     ALWAYS_INLINE void forEach(const Functor& func)
</span><span class="cx">     {
</span><del>-        auto* metadata = bitwise_cast<typename Op::Metadata*>(get(Op::opcodeID));
-        auto* end = bitwise_cast<typename Op::Metadata*>(getImpl(Op::opcodeID + 1));
-        for (; metadata + 1 <= end; ++metadata)
</del><ins>+        auto* metadata = get<typename Op::Metadata>();
+        auto* end = bitwise_cast<typename Op::Metadata*>(getWithoutAligning(Op::opcodeID + 1));
+        for (; metadata < end; ++metadata)
</ins><span class="cx">             func(*metadata);
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="lines">@@ -116,7 +120,7 @@
</span><span class="cx">         return offsetTable32()[i];
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    ALWAYS_INLINE uint8_t* getImpl(unsigned i)
</del><ins>+    ALWAYS_INLINE uint8_t* getWithoutAligning(unsigned i)
</ins><span class="cx">     {
</span><span class="cx">         return bitwise_cast<uint8_t*>(this) + getOffset(i);
</span><span class="cx">     }
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecodeOpcodeh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecode/Opcode.h (282477 => 282478)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/Opcode.h    2021-09-15 22:12:01 UTC (rev 282477)
+++ trunk/Source/JavaScriptCore/bytecode/Opcode.h       2021-09-15 22:18:52 UTC (rev 282478)
</span><span class="lines">@@ -139,6 +139,7 @@
</span><span class="cx">     macro(OpEnumeratorGetByVal) \
</span><span class="cx">     macro(OpEnumeratorInByVal) \
</span><span class="cx">     macro(OpEnumeratorHasOwnProperty) \
</span><ins>+    macro(OpGetById) \
</ins><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="trunkSourceJavaScriptCorebytecodeUnlinkedCodeBlockcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecode/UnlinkedCodeBlock.cpp (282477 => 282478)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/UnlinkedCodeBlock.cpp       2021-09-15 22:12:01 UTC (rev 282477)
+++ trunk/Source/JavaScriptCore/bytecode/UnlinkedCodeBlock.cpp  2021-09-15 22:18:52 UTC (rev 282478)
</span><span class="lines">@@ -108,6 +108,8 @@
</span><span class="cx">     extraMemory += thisObject->m_functionExprs.byteSize();
</span><span class="cx"> 
</span><span class="cx">     visitor.reportExtraMemoryVisited(extraMemory);
</span><ins>+
+    VM::SpaceAndSet::setFor(*thisObject->subspace()).add(thisObject);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> DEFINE_VISIT_CHILDREN(UnlinkedCodeBlock);
</span><span class="lines">@@ -316,4 +318,45 @@
</span><span class="cx">     return m_outOfLineJumpTargets.get(bytecodeOffset);
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void UnlinkedCodeBlock::allocateSharedProfiles()
+{
+    RELEASE_ASSERT(!m_metadata->isFinalized());
+
+    {
+        unsigned numberOfValueProfiles = numParameters();
+        if (m_metadata->hasMetadata()) {
+#define COUNT(__op) \
+            numberOfValueProfiles += m_metadata->numEntries<__op>();
+            FOR_EACH_OPCODE_WITH_VALUE_PROFILE(COUNT)
+#undef COUNT
+            numberOfValueProfiles += m_metadata->numEntries<OpIteratorOpen>() * 3;
+            numberOfValueProfiles += m_metadata->numEntries<OpIteratorNext>() * 3;
+        }
+
+        m_valueProfiles = FixedVector<ValueProfile>(numberOfValueProfiles);
+    }
+
+    if (m_metadata->hasMetadata()) {
+        unsigned numberOfArrayProfiles = 0;
+
+#define COUNT(__op) \
+        numberOfArrayProfiles += m_metadata->numEntries<__op>();
+        FOR_EACH_OPCODE_WITH_ARRAY_PROFILE(COUNT)
+#undef COUNT
+        numberOfArrayProfiles += m_metadata->numEntries<OpIteratorNext>();
+
+        m_arrayProfiles = FixedVector<ArrayProfile>(numberOfArrayProfiles);
+    }
+}
+
+void UnlinkedCodeBlock::finalizeUnconditionally(VM&)
+{
+    for (auto& profile : m_valueProfiles)
+        profile.computeUpdatedPrediction();
+    for (auto& profile : m_arrayProfiles)
+        profile.computeUpdatedPrediction(this);
+
+    VM::SpaceAndSet::setFor(*subspace()).remove(this);
+}
+
</ins><span class="cx"> } // namespace JSC
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecodeUnlinkedCodeBlockh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecode/UnlinkedCodeBlock.h (282477 => 282478)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/UnlinkedCodeBlock.h 2021-09-15 22:12:01 UTC (rev 282477)
+++ trunk/Source/JavaScriptCore/bytecode/UnlinkedCodeBlock.h    2021-09-15 22:18:52 UTC (rev 282478)
</span><span class="lines">@@ -25,6 +25,7 @@
</span><span class="cx"> 
</span><span class="cx"> #pragma once
</span><span class="cx"> 
</span><ins>+#include "ArrayProfile.h"
</ins><span class="cx"> #include "BytecodeConventions.h"
</span><span class="cx"> #include "CodeType.h"
</span><span class="cx"> #include "DFGExitProfile.h"
</span><span class="lines">@@ -38,6 +39,7 @@
</span><span class="cx"> #include "RegExp.h"
</span><span class="cx"> #include "UnlinkedFunctionExecutable.h"
</span><span class="cx"> #include "UnlinkedMetadataTable.h"
</span><ins>+#include "ValueProfile.h"
</ins><span class="cx"> #include "VirtualRegister.h"
</span><span class="cx"> #include <algorithm>
</span><span class="cx"> #include <wtf/BitVector.h>
</span><span class="lines">@@ -324,6 +326,17 @@
</span><span class="cx">         return hasExitSite(locker, site);
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    bool hasAnyExitsAt(const ConcurrentJSLocker& locker, BytecodeIndex bytecodeIndex) const
+    {
+        return m_exitProfile.hasAnyExitsAt(locker, bytecodeIndex);
+    }
+
+    bool hasAnyExitsAt(BytecodeIndex bytecodeIndex)
+    {
+        ConcurrentJSLocker locker(m_lock);
+        return hasAnyExitsAt(locker, bytecodeIndex);
+    }
+
</ins><span class="cx">     DFG::ExitProfile& exitProfile() { return m_exitProfile; }
</span><span class="cx"> #endif
</span><span class="cx"> 
</span><span class="lines">@@ -334,7 +347,10 @@
</span><span class="cx">         return m_metadata->sizeInBytes();
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    void allocateSharedProfiles();
</ins><span class="cx"> 
</span><ins>+    void finalizeUnconditionally(VM&);
+
</ins><span class="cx"> protected:
</span><span class="cx">     UnlinkedCodeBlock(VM&, Structure*, CodeType, const ExecutableInfo&, OptionSet<CodeGenerationMode>);
</span><span class="cx"> 
</span><span class="lines">@@ -419,6 +435,8 @@
</span><span class="cx">     FixedVector<Identifier> m_identifiers;
</span><span class="cx">     FixedVector<WriteBarrier<Unknown>> m_constantRegisters;
</span><span class="cx">     FixedVector<SourceCodeRepresentation> m_constantsSourceCodeRepresentation;
</span><ins>+    FixedVector<ValueProfile> m_valueProfiles; // The first numParameters() are argument profiles.
+    FixedVector<ArrayProfile> m_arrayProfiles;
</ins><span class="cx">     using FunctionExpressionVector = FixedVector<WriteBarrier<UnlinkedFunctionExecutable>>;
</span><span class="cx">     FunctionExpressionVector m_functionDecls;
</span><span class="cx">     FunctionExpressionVector m_functionExprs;
</span><span class="lines">@@ -456,6 +474,11 @@
</span><span class="cx">         return outOfLineJumpOffset(instruction.offset());
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    ValueProfile& valueProfile(unsigned i) { return m_valueProfiles[i]; }
+    ArrayProfile& arrayProfile(unsigned i) { return m_arrayProfiles[i]; }
+    unsigned numValueProfiles() const { return m_valueProfiles.size(); }
+    unsigned numArrayProfiles() const { return m_arrayProfiles.size(); }
+
</ins><span class="cx"> private:
</span><span class="cx">     using OutOfLineJumpTargets = HashMap<InstructionStream::Offset, int>;
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecodeUnlinkedCodeBlockGeneratorcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecode/UnlinkedCodeBlockGenerator.cpp (282477 => 282478)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/UnlinkedCodeBlockGenerator.cpp      2021-09-15 22:12:01 UTC (rev 282477)
+++ trunk/Source/JavaScriptCore/bytecode/UnlinkedCodeBlockGenerator.cpp 2021-09-15 22:18:52 UTC (rev 282478)
</span><span class="lines">@@ -119,6 +119,7 @@
</span><span class="cx">     {
</span><span class="cx">         Locker locker { m_codeBlock->cellLock() };
</span><span class="cx">         m_codeBlock->m_instructions = WTFMove(instructions);
</span><ins>+        m_codeBlock->allocateSharedProfiles();
</ins><span class="cx">         m_codeBlock->m_metadata->finalize();
</span><span class="cx"> 
</span><span class="cx">         m_codeBlock->m_jumpTargets = WTFMove(m_jumpTargets);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecodeUnlinkedMetadataTablecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecode/UnlinkedMetadataTable.cpp (282477 => 282478)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/UnlinkedMetadataTable.cpp   2021-09-15 22:12:01 UTC (rev 282477)
+++ trunk/Source/JavaScriptCore/bytecode/UnlinkedMetadataTable.cpp      2021-09-15 22:18:52 UTC (rev 282478)
</span><span class="lines">@@ -55,10 +55,10 @@
</span><span class="cx">                 buffer[i] = offset;
</span><span class="cx">                 continue;
</span><span class="cx">             }
</span><ins>+            buffer[i] = offset; // We align when we access this.
</ins><span class="cx">             unsigned alignment = metadataAlignment(static_cast<OpcodeID>(i));
</span><span class="cx">             offset = roundUpToMultipleOf(alignment, offset);
</span><span class="cx">             ASSERT(alignment <= s_maxMetadataAlignment);
</span><del>-            buffer[i] = offset;
</del><span class="cx">             offset += numberOfEntries * metadataSize(static_cast<OpcodeID>(i));
</span><span class="cx">         }
</span><span class="cx">         buffer[s_offsetTableEntries - 1] = offset;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecodeUnlinkedMetadataTableh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecode/UnlinkedMetadataTable.h (282477 => 282478)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/UnlinkedMetadataTable.h     2021-09-15 22:12:01 UTC (rev 282477)
+++ trunk/Source/JavaScriptCore/bytecode/UnlinkedMetadataTable.h        2021-09-15 22:18:52 UTC (rev 282478)
</span><span class="lines">@@ -52,6 +52,8 @@
</span><span class="cx">     ~UnlinkedMetadataTable();
</span><span class="cx"> 
</span><span class="cx">     unsigned addEntry(OpcodeID);
</span><ins>+    template <typename Bytecode>
+    unsigned numEntries();
</ins><span class="cx"> 
</span><span class="cx">     size_t sizeInBytes();
</span><span class="cx"> 
</span><span class="lines">@@ -64,6 +66,9 @@
</span><span class="cx">         return adoptRef(*new UnlinkedMetadataTable);
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    bool isFinalized() { return m_isFinalized; }
+    bool hasMetadata() { return m_hasMetadata; }
+
</ins><span class="cx"> private:
</span><span class="cx">     enum EmptyTag { Empty };
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecodeUnlinkedMetadataTableInlinesh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecode/UnlinkedMetadataTableInlines.h (282477 => 282478)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/UnlinkedMetadataTableInlines.h      2021-09-15 22:12:01 UTC (rev 282477)
+++ trunk/Source/JavaScriptCore/bytecode/UnlinkedMetadataTableInlines.h 2021-09-15 22:18:52 UTC (rev 282478)
</span><span class="lines">@@ -73,6 +73,14 @@
</span><span class="cx">     return preprocessBuffer()[opcodeID]++;
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+template <typename Bytecode>
+ALWAYS_INLINE unsigned UnlinkedMetadataTable::numEntries()
+{
+    constexpr auto opcodeID = Bytecode::opcodeID;
+    ASSERT(!m_isFinalized && opcodeID < s_offsetTableEntries - 1);
+    return preprocessBuffer()[opcodeID];
+}
+
</ins><span class="cx"> ALWAYS_INLINE size_t UnlinkedMetadataTable::sizeInBytes()
</span><span class="cx"> {
</span><span class="cx">     if (m_isFinalized && !m_hasMetadata)
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecodeValueProfileh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecode/ValueProfile.h (282477 => 282478)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/ValueProfile.h      2021-09-15 22:12:01 UTC (rev 282477)
+++ trunk/Source/JavaScriptCore/bytecode/ValueProfile.h 2021-09-15 22:18:52 UTC (rev 282478)
</span><span class="lines">@@ -31,6 +31,7 @@
</span><span class="cx"> #include "ConcurrentJSLock.h"
</span><span class="cx"> #include "SpeculatedType.h"
</span><span class="cx"> #include "Structure.h"
</span><ins>+#include "VirtualRegister.h"
</ins><span class="cx"> #include <wtf/PrintStream.h>
</span><span class="cx"> #include <wtf/StringPrintStream.h>
</span><span class="cx"> 
</span><span class="lines">@@ -45,6 +46,11 @@
</span><span class="cx">     
</span><span class="cx">     ValueProfileBase()
</span><span class="cx">     {
</span><ins>+        clearBuckets();
+    }
+
+    void clearBuckets()
+    {
</ins><span class="cx">         for (unsigned i = 0; i < totalNumberOfBuckets; ++i)
</span><span class="cx">             m_buckets[i] = JSValue::encode(JSValue());
</span><span class="cx">     }
</span><span class="lines">@@ -55,17 +61,6 @@
</span><span class="cx">         return m_buckets + numberOfBuckets + i;
</span><span class="cx">     }
</span><span class="cx">     
</span><del>-    const ClassInfo* classInfo(unsigned bucket) const
-    {
-        JSValue value = JSValue::decode(m_buckets[bucket]);
-        if (!!value) {
-            if (!value.isCell())
-                return nullptr;
-            return value.asCell()->structure()->classInfo();
-        }
-        return nullptr;
-    }
-    
</del><span class="cx">     unsigned numberOfSamples() const
</span><span class="cx">     {
</span><span class="cx">         unsigned result = 0;
</span><span class="lines">@@ -92,9 +87,9 @@
</span><span class="cx">         return false;
</span><span class="cx">     }
</span><span class="cx">     
</span><del>-    CString briefDescription(const ConcurrentJSLocker& locker)
</del><ins>+    CString briefDescription()
</ins><span class="cx">     {
</span><del>-        computeUpdatedPrediction(locker);
</del><ins>+        computeUpdatedPrediction();
</ins><span class="cx">         
</span><span class="cx">         StringPrintStream out;
</span><span class="cx">         out.print("predicting ", SpeculationDump(m_prediction));
</span><span class="lines">@@ -118,10 +113,10 @@
</span><span class="cx">         }
</span><span class="cx">     }
</span><span class="cx">     
</span><del>-    // Updates the prediction and returns the new one. Never call this from any thread
-    // that isn't executing the code.
-    SpeculatedType computeUpdatedPrediction(const ConcurrentJSLocker&)
</del><ins>+    SpeculatedType computeUpdatedPrediction()
</ins><span class="cx">     {
</span><ins>+        // Multiple threads could be calling into this at the same time.
+        // The import part is that we don't end up corrupting any values.
</ins><span class="cx">         for (unsigned i = 0; i < totalNumberOfBuckets; ++i) {
</span><span class="cx">             JSValue value = JSValue::decode(m_buckets[i]);
</span><span class="cx">             if (!value)
</span><span class="lines">@@ -156,6 +151,7 @@
</span><span class="cx"> 
</span><span class="cx"> struct ValueProfile : public ValueProfileWithLogNumberOfBuckets<0> {
</span><span class="cx">     ValueProfile() : ValueProfileWithLogNumberOfBuckets<0>() { }
</span><ins>+    static ptrdiff_t offsetOfFirstBucket() { return OBJECT_OFFSETOF(ValueProfile, m_buckets[0]); }
</ins><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> struct ValueProfileAndVirtualRegister : public ValueProfile {
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGArrayModecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGArrayMode.cpp (282477 => 282478)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGArrayMode.cpp 2021-09-15 22:12:01 UTC (rev 282477)
+++ trunk/Source/JavaScriptCore/dfg/DFGArrayMode.cpp    2021-09-15 22:18:52 UTC (rev 282478)
</span><span class="lines">@@ -36,10 +36,17 @@
</span><span class="cx"> 
</span><span class="cx"> namespace JSC { namespace DFG {
</span><span class="cx"> 
</span><del>-ArrayMode ArrayMode::fromObserved(const ConcurrentJSLocker& locker, ArrayProfile* profile, Array::Action action, bool makeSafe)
</del><ins>+ArrayMode ArrayMode::fromObserved(Graph& graph, const CodeOrigin& origin, ArrayProfile* profile, Array::Action action, bool makeSafe)
</ins><span class="cx"> {
</span><ins>+    if (profile->observedDifferentGlobalObject() && graph.hasAnyExitsAt(origin)) {
+        // This could be an original array structure, but from a different
+        // global object than the lexical global object. So we conservatively
+        // say it is not an original array structure.
+        profile->setDoesNotUseOriginalArrayStructures();
+    }
+
</ins><span class="cx">     Array::Class nonArray;
</span><del>-    if (profile->usesOriginalArrayStructures(locker))
</del><ins>+    if (profile->usesOriginalArrayStructures())
</ins><span class="cx">         nonArray = Array::OriginalNonArray;
</span><span class="cx">     else
</span><span class="cx">         nonArray = Array::NonArray;
</span><span class="lines">@@ -63,27 +70,27 @@
</span><span class="cx">         else
</span><span class="cx">             converts = Array::AsIs;
</span><span class="cx"> 
</span><del>-        return ArrayMode(type, isArray, converts, action).withProfile(locker, profile, makeSafe);
</del><ins>+        return ArrayMode(type, isArray, converts, action).withProfile(profile, makeSafe);
</ins><span class="cx">     };
</span><span class="cx"> 
</span><del>-    ArrayModes observed = profile->observedArrayModes(locker);
</del><ins>+    ArrayModes observed = profile->observedArrayModes();
</ins><span class="cx">     switch (observed) {
</span><span class="cx">     case 0:
</span><span class="cx">         return ArrayMode(Array::Unprofiled);
</span><span class="cx">     case asArrayModesIgnoringTypedArrays(NonArray):
</span><del>-        if (action == Array::Write && !profile->mayInterceptIndexedAccesses(locker))
</del><ins>+        if (action == Array::Write && !profile->mayInterceptIndexedAccesses())
</ins><span class="cx">             return ArrayMode(Array::SelectUsingArguments, nonArray, Array::OutOfBounds, Array::Convert, action);
</span><del>-        return ArrayMode(Array::SelectUsingPredictions, nonArray, action).withSpeculationFromProfile(locker, profile, makeSafe);
</del><ins>+        return ArrayMode(Array::SelectUsingPredictions, nonArray, action).withSpeculationFromProfile(profile, makeSafe);
</ins><span class="cx"> 
</span><span class="cx">     case asArrayModesIgnoringTypedArrays(ArrayWithUndecided):
</span><span class="cx">         if (action == Array::Write)
</span><span class="cx">             return ArrayMode(Array::SelectUsingArguments, Array::Array, Array::OutOfBounds, Array::Convert, action);
</span><del>-        return ArrayMode(Array::Undecided, Array::Array, Array::OutOfBounds, Array::AsIs, action).withProfile(locker, profile, makeSafe);
</del><ins>+        return ArrayMode(Array::Undecided, Array::Array, Array::OutOfBounds, Array::AsIs, action).withProfile(profile, makeSafe);
</ins><span class="cx">         
</span><span class="cx">     case asArrayModesIgnoringTypedArrays(NonArray) | asArrayModesIgnoringTypedArrays(ArrayWithUndecided):
</span><del>-        if (action == Array::Write && !profile->mayInterceptIndexedAccesses(locker))
</del><ins>+        if (action == Array::Write && !profile->mayInterceptIndexedAccesses())
</ins><span class="cx">             return ArrayMode(Array::SelectUsingArguments, Array::PossiblyArray, Array::OutOfBounds, Array::Convert, action);
</span><del>-        return ArrayMode(Array::SelectUsingPredictions, action).withSpeculationFromProfile(locker, profile, makeSafe);
</del><ins>+        return ArrayMode(Array::SelectUsingPredictions, action).withSpeculationFromProfile(profile, makeSafe);
</ins><span class="cx"> 
</span><span class="cx">     case asArrayModesIgnoringTypedArrays(NonArrayWithInt32):
</span><span class="cx">     case asArrayModesIgnoringTypedArrays(ArrayWithInt32):
</span><span class="lines">@@ -113,50 +120,50 @@
</span><span class="cx">         return handleContiguousModes(Array::Contiguous, observed);
</span><span class="cx"> 
</span><span class="cx">     case asArrayModesIgnoringTypedArrays(NonArrayWithArrayStorage):
</span><del>-        return ArrayMode(Array::ArrayStorage, nonArray, Array::AsIs, action).withProfile(locker, profile, makeSafe);
</del><ins>+        return ArrayMode(Array::ArrayStorage, nonArray, Array::AsIs, action).withProfile(profile, makeSafe);
</ins><span class="cx">     case asArrayModesIgnoringTypedArrays(NonArrayWithSlowPutArrayStorage):
</span><span class="cx">     case asArrayModesIgnoringTypedArrays(NonArrayWithArrayStorage) | asArrayModesIgnoringTypedArrays(NonArrayWithSlowPutArrayStorage):
</span><del>-        return ArrayMode(Array::SlowPutArrayStorage, nonArray, Array::AsIs, action).withProfile(locker, profile, makeSafe);
</del><ins>+        return ArrayMode(Array::SlowPutArrayStorage, nonArray, Array::AsIs, action).withProfile(profile, makeSafe);
</ins><span class="cx">     case asArrayModesIgnoringTypedArrays(ArrayWithArrayStorage):
</span><del>-        return ArrayMode(Array::ArrayStorage, Array::Array, Array::AsIs, action).withProfile(locker, profile, makeSafe);
</del><ins>+        return ArrayMode(Array::ArrayStorage, Array::Array, Array::AsIs, action).withProfile(profile, makeSafe);
</ins><span class="cx">     case asArrayModesIgnoringTypedArrays(ArrayWithSlowPutArrayStorage):
</span><span class="cx">     case asArrayModesIgnoringTypedArrays(ArrayWithArrayStorage) | asArrayModesIgnoringTypedArrays(ArrayWithSlowPutArrayStorage):
</span><del>-        return ArrayMode(Array::SlowPutArrayStorage, Array::Array, Array::AsIs, action).withProfile(locker, profile, makeSafe);
</del><ins>+        return ArrayMode(Array::SlowPutArrayStorage, Array::Array, Array::AsIs, action).withProfile(profile, makeSafe);
</ins><span class="cx">     case asArrayModesIgnoringTypedArrays(NonArrayWithArrayStorage) | asArrayModesIgnoringTypedArrays(ArrayWithArrayStorage):
</span><del>-        return ArrayMode(Array::ArrayStorage, Array::PossiblyArray, Array::AsIs, action).withProfile(locker, profile, makeSafe);
</del><ins>+        return ArrayMode(Array::ArrayStorage, Array::PossiblyArray, Array::AsIs, action).withProfile(profile, makeSafe);
</ins><span class="cx">     case asArrayModesIgnoringTypedArrays(NonArrayWithSlowPutArrayStorage) | asArrayModesIgnoringTypedArrays(ArrayWithSlowPutArrayStorage):
</span><span class="cx">     case asArrayModesIgnoringTypedArrays(NonArrayWithArrayStorage) | asArrayModesIgnoringTypedArrays(ArrayWithArrayStorage) | asArrayModesIgnoringTypedArrays(NonArrayWithSlowPutArrayStorage) | asArrayModesIgnoringTypedArrays(ArrayWithSlowPutArrayStorage):
</span><del>-        return ArrayMode(Array::SlowPutArrayStorage, Array::PossiblyArray, Array::AsIs, action).withProfile(locker, profile, makeSafe);
</del><ins>+        return ArrayMode(Array::SlowPutArrayStorage, Array::PossiblyArray, Array::AsIs, action).withProfile(profile, makeSafe);
</ins><span class="cx">     case Int8ArrayMode:
</span><del>-        return ArrayMode(Array::Int8Array, nonArray, Array::AsIs, action).withProfile(locker, profile, makeSafe);
</del><ins>+        return ArrayMode(Array::Int8Array, nonArray, Array::AsIs, action).withProfile(profile, makeSafe);
</ins><span class="cx">     case Int16ArrayMode:
</span><del>-        return ArrayMode(Array::Int16Array, nonArray, Array::AsIs, action).withProfile(locker, profile, makeSafe);
</del><ins>+        return ArrayMode(Array::Int16Array, nonArray, Array::AsIs, action).withProfile(profile, makeSafe);
</ins><span class="cx">     case Int32ArrayMode:
</span><del>-        return ArrayMode(Array::Int32Array, nonArray, Array::AsIs, action).withProfile(locker, profile, makeSafe);
</del><ins>+        return ArrayMode(Array::Int32Array, nonArray, Array::AsIs, action).withProfile(profile, makeSafe);
</ins><span class="cx">     case Uint8ArrayMode:
</span><del>-        return ArrayMode(Array::Uint8Array, nonArray, Array::AsIs, action).withProfile(locker, profile, makeSafe);
</del><ins>+        return ArrayMode(Array::Uint8Array, nonArray, Array::AsIs, action).withProfile(profile, makeSafe);
</ins><span class="cx">     case Uint8ClampedArrayMode:
</span><del>-        return ArrayMode(Array::Uint8ClampedArray, nonArray, Array::AsIs, action).withProfile(locker, profile, makeSafe);
</del><ins>+        return ArrayMode(Array::Uint8ClampedArray, nonArray, Array::AsIs, action).withProfile(profile, makeSafe);
</ins><span class="cx">     case Uint16ArrayMode:
</span><del>-        return ArrayMode(Array::Uint16Array, nonArray, Array::AsIs, action).withProfile(locker, profile, makeSafe);
</del><ins>+        return ArrayMode(Array::Uint16Array, nonArray, Array::AsIs, action).withProfile(profile, makeSafe);
</ins><span class="cx">     case Uint32ArrayMode:
</span><del>-        return ArrayMode(Array::Uint32Array, nonArray, Array::AsIs, action).withProfile(locker, profile, makeSafe);
</del><ins>+        return ArrayMode(Array::Uint32Array, nonArray, Array::AsIs, action).withProfile(profile, makeSafe);
</ins><span class="cx">     case Float32ArrayMode:
</span><del>-        return ArrayMode(Array::Float32Array, nonArray, Array::AsIs, action).withProfile(locker, profile, makeSafe);
</del><ins>+        return ArrayMode(Array::Float32Array, nonArray, Array::AsIs, action).withProfile(profile, makeSafe);
</ins><span class="cx">     case Float64ArrayMode:
</span><del>-        return ArrayMode(Array::Float64Array, nonArray, Array::AsIs, action).withProfile(locker, profile, makeSafe);
</del><ins>+        return ArrayMode(Array::Float64Array, nonArray, Array::AsIs, action).withProfile(profile, makeSafe);
</ins><span class="cx">     case BigInt64ArrayMode:
</span><del>-        return ArrayMode(Array::BigInt64Array, nonArray, Array::AsIs, action).withProfile(locker, profile, makeSafe);
</del><ins>+        return ArrayMode(Array::BigInt64Array, nonArray, Array::AsIs, action).withProfile(profile, makeSafe);
</ins><span class="cx">     case BigUint64ArrayMode:
</span><del>-        return ArrayMode(Array::BigUint64Array, nonArray, Array::AsIs, action).withProfile(locker, profile, makeSafe);
</del><ins>+        return ArrayMode(Array::BigUint64Array, nonArray, Array::AsIs, action).withProfile(profile, makeSafe);
</ins><span class="cx"> 
</span><span class="cx">     default:
</span><span class="cx">         // If we have seen multiple TypedArray types, or a TypedArray and non-typed array, it doesn't make sense to try to convert the object since you can't convert typed arrays.
</span><span class="cx">         if (observed & ALL_TYPED_ARRAY_MODES)
</span><del>-            return ArrayMode(Array::Generic, nonArray, Array::AsIs, action).withProfile(locker, profile, makeSafe);
</del><ins>+            return ArrayMode(Array::Generic, nonArray, Array::AsIs, action).withProfile(profile, makeSafe);
</ins><span class="cx"> 
</span><del>-        if ((observed & asArrayModesIgnoringTypedArrays(NonArray)) && profile->mayInterceptIndexedAccesses(locker))
-            return ArrayMode(Array::SelectUsingPredictions).withSpeculationFromProfile(locker, profile, makeSafe);
</del><ins>+        if ((observed & asArrayModesIgnoringTypedArrays(NonArray)) && profile->mayInterceptIndexedAccesses())
+            return ArrayMode(Array::SelectUsingPredictions).withSpeculationFromProfile(profile, makeSafe);
</ins><span class="cx">         
</span><span class="cx">         Array::Type type;
</span><span class="cx">         Array::Class arrayClass;
</span><span class="lines">@@ -183,7 +190,7 @@
</span><span class="cx">         else
</span><span class="cx">             arrayClass = Array::PossiblyArray;
</span><span class="cx">         
</span><del>-        return ArrayMode(type, arrayClass, Array::Convert, action).withProfile(locker, profile, makeSafe);
</del><ins>+        return ArrayMode(type, arrayClass, Array::Convert, action).withProfile(profile, makeSafe);
</ins><span class="cx">     }
</span><span class="cx"> }
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGArrayModeh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGArrayMode.h (282477 => 282478)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGArrayMode.h   2021-09-15 22:12:01 UTC (rev 282477)
+++ trunk/Source/JavaScriptCore/dfg/DFGArrayMode.h      2021-09-15 22:18:52 UTC (rev 282478)
</span><span class="lines">@@ -178,7 +178,7 @@
</span><span class="cx">         return ArrayMode(word);
</span><span class="cx">     }
</span><span class="cx">     
</span><del>-    static ArrayMode fromObserved(const ConcurrentJSLocker&, ArrayProfile*, Array::Action, bool makeSafe);
</del><ins>+    static ArrayMode fromObserved(Graph&, const CodeOrigin&, ArrayProfile*, Array::Action, bool makeSafe);
</ins><span class="cx">     
</span><span class="cx">     ArrayMode withSpeculation(Array::Speculation speculation) const
</span><span class="cx">     {
</span><span class="lines">@@ -190,13 +190,13 @@
</span><span class="cx">         return ArrayMode(type(), arrayClass, speculation(), conversion(), action());
</span><span class="cx">     }
</span><span class="cx">     
</span><del>-    ArrayMode withSpeculationFromProfile(const ConcurrentJSLocker& locker, ArrayProfile* profile, bool makeSafe) const
</del><ins>+    ArrayMode withSpeculationFromProfile(ArrayProfile* profile, bool makeSafe) const
</ins><span class="cx">     {
</span><span class="cx">         Array::Speculation mySpeculation;
</span><span class="cx"> 
</span><span class="cx">         if (makeSafe)
</span><span class="cx">             mySpeculation = Array::OutOfBounds;
</span><del>-        else if (profile->mayStoreToHole(locker))
</del><ins>+        else if (profile->mayStoreToHole())
</ins><span class="cx">             mySpeculation = Array::ToHole;
</span><span class="cx">         else
</span><span class="cx">             mySpeculation = Array::InBounds;
</span><span class="lines">@@ -204,27 +204,6 @@
</span><span class="cx">         return withSpeculation(mySpeculation);
</span><span class="cx">     }
</span><span class="cx">     
</span><del>-    ArrayMode withProfile(const ConcurrentJSLocker& locker, ArrayProfile* profile, bool makeSafe) const
-    {
-        Array::Class myArrayClass;
-
-        if (isJSArray()) {
-            if (profile->usesOriginalArrayStructures(locker) && benefitsFromOriginalArray()) {
-                ArrayModes arrayModes = profile->observedArrayModes(locker);
-                if (hasSeenCopyOnWriteArray(arrayModes) && !hasSeenWritableArray(arrayModes))
-                    myArrayClass = Array::OriginalCopyOnWriteArray;
-                else if (!hasSeenCopyOnWriteArray(arrayModes) && hasSeenWritableArray(arrayModes))
-                    myArrayClass = Array::OriginalArray;
-                else
-                    myArrayClass = Array::Array;
-            } else
-                myArrayClass = Array::Array;
-        } else
-            myArrayClass = arrayClass();
-        
-        return withArrayClass(myArrayClass).withSpeculationFromProfile(locker, profile, makeSafe);
-    }
-    
</del><span class="cx">     ArrayMode withType(Array::Type type) const
</span><span class="cx">     {
</span><span class="cx">         return ArrayMode(type, arrayClass(), speculation(), conversion(), action());
</span><span class="lines">@@ -538,7 +517,29 @@
</span><span class="cx">     {
</span><span class="cx">         u.asWord = word;
</span><span class="cx">     }
</span><ins>+
+    ArrayMode withProfile(ArrayProfile* profile, bool makeSafe) const
+    {
+        Array::Class myArrayClass;
+
+        if (isJSArray()) {
+            if (profile->usesOriginalArrayStructures() && benefitsFromOriginalArray()) {
+                ArrayModes arrayModes = profile->observedArrayModes();
+                if (hasSeenCopyOnWriteArray(arrayModes) && !hasSeenWritableArray(arrayModes))
+                    myArrayClass = Array::OriginalCopyOnWriteArray;
+                else if (!hasSeenCopyOnWriteArray(arrayModes) && hasSeenWritableArray(arrayModes))
+                    myArrayClass = Array::OriginalArray;
+                else
+                    myArrayClass = Array::Array;
+            } else
+                myArrayClass = Array::Array;
+        } else
+            myArrayClass = arrayClass();
+        
+        return withArrayClass(myArrayClass).withSpeculationFromProfile(profile, makeSafe);
+    }
</ins><span class="cx">     
</span><ins>+    
</ins><span class="cx">     ArrayModes arrayModesWithIndexingShapes(IndexingType shape) const
</span><span class="cx">     {
</span><span class="cx">         switch (arrayClass()) {
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGByteCodeParsercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp (282477 => 282478)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp    2021-09-15 22:12:01 UTC (rev 282477)
+++ trunk/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp       2021-09-15 22:18:52 UTC (rev 282478)
</span><span class="lines">@@ -895,11 +895,7 @@
</span><span class="cx">     {
</span><span class="cx">         auto getValueProfilePredictionFromForCodeBlockAndBytecodeOffset = [&] (CodeBlock* codeBlock, const CodeOrigin& codeOrigin)
</span><span class="cx">         {
</span><del>-            SpeculatedType prediction;
-            {
-                ConcurrentJSLocker locker(codeBlock->m_lock);
-                prediction = codeBlock->valueProfilePredictionForBytecodeIndex(locker, codeOrigin.bytecodeIndex());
-            }
</del><ins>+            SpeculatedType prediction = codeBlock->valueProfilePredictionForBytecodeIndex(codeOrigin.bytecodeIndex());
</ins><span class="cx">             auto* fuzzerAgent = m_vm->fuzzerAgent();
</span><span class="cx">             if (UNLIKELY(fuzzerAgent))
</span><span class="cx">                 return fuzzerAgent->getPrediction(codeBlock, codeOrigin, prediction) & SpecBytecodeTop;
</span><span class="lines">@@ -983,10 +979,9 @@
</span><span class="cx"> 
</span><span class="cx">     ArrayMode getArrayMode(ArrayProfile& profile, Array::Action action)
</span><span class="cx">     {
</span><del>-        ConcurrentJSLocker locker(m_inlineStackTop->m_profiledBlock->m_lock);
-        profile.computeUpdatedPrediction(locker, m_inlineStackTop->m_profiledBlock);
-        bool makeSafe = profile.outOfBounds(locker);
-        return ArrayMode::fromObserved(locker, &profile, action, makeSafe);
</del><ins>+        profile.computeUpdatedPrediction(m_inlineStackTop->m_profiledBlock);
+        bool makeSafe = profile.outOfBounds();
+        return ArrayMode::fromObserved(m_graph, currentCodeOrigin(), &profile, action, makeSafe);
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     Node* makeSafe(Node* node)
</span><span class="lines">@@ -2058,9 +2053,8 @@
</span><span class="cx">             // arguments received inside the callee. But that probably won't matter for most
</span><span class="cx">             // calls.
</span><span class="cx">             if (codeBlock && argument < static_cast<unsigned>(codeBlock->numParameters())) {
</span><del>-                ConcurrentJSLocker locker(codeBlock->m_lock);
</del><span class="cx">                 ValueProfile& profile = codeBlock->valueProfileForArgument(argument);
</span><del>-                variable->predict(profile.computeUpdatedPrediction(locker));
</del><ins>+                variable->predict(profile.computeUpdatedPrediction());
</ins><span class="cx">             }
</span><span class="cx">             
</span><span class="cx">             Node* setArgument = addToGraph(numSetArguments >= mandatoryMinimum ? SetArgumentMaybe : SetArgumentDefinitely, OpInfo(variable));
</span><span class="lines">@@ -6305,7 +6299,7 @@
</span><span class="cx">             if (shouldCompileAsGetById)
</span><span class="cx">                 handleGetById(bytecode.m_dst, prediction, base, identifier, identifierNumber, getByStatus, AccessType::GetById, nextOpcodeIndex());
</span><span class="cx">             else {
</span><del>-                ArrayMode arrayMode = getArrayMode(bytecode.metadata(codeBlock).m_arrayProfile, Array::Read);
</del><ins>+                ArrayMode arrayMode = getArrayMode(*bytecode.metadata(codeBlock).m_arrayProfile, Array::Read);
</ins><span class="cx">                 // FIXME: We could consider making this not vararg, since it only uses three child
</span><span class="cx">                 // slots.
</span><span class="cx">                 // https://bugs.webkit.org/show_bug.cgi?id=184192
</span><span class="lines">@@ -7075,11 +7069,9 @@
</span><span class="cx">             HashSet<unsigned, WTF::IntHash<unsigned>, WTF::UnsignedWithZeroKeyHashTraits<unsigned>> seenArguments;
</span><span class="cx"> 
</span><span class="cx">             {
</span><del>-                ConcurrentJSLocker locker(m_inlineStackTop->m_profiledBlock->m_lock);
-
</del><span class="cx">                 buffer->forEach([&] (ValueProfileAndVirtualRegister& profile) {
</span><span class="cx">                     VirtualRegister operand(profile.m_operand);
</span><del>-                    SpeculatedType prediction = profile.computeUpdatedPrediction(locker);
</del><ins>+                    SpeculatedType prediction = profile.computeUpdatedPrediction();
</ins><span class="cx">                     if (operand.isLocal())
</span><span class="cx">                         localPredictions.append(prediction);
</span><span class="cx">                     else {
</span><span class="lines">@@ -7431,7 +7423,7 @@
</span><span class="cx">                 BasicBlock* isDoneBlock = allocateUntargetableBlock();
</span><span class="cx">                 BasicBlock* doLoadBlock = allocateUntargetableBlock();
</span><span class="cx"> 
</span><del>-                ArrayMode arrayMode = getArrayMode(metadata.m_iterableProfile, Array::Read);
</del><ins>+                ArrayMode arrayMode = getArrayMode(*metadata.m_iterableProfile, Array::Read);
</ins><span class="cx">                 auto prediction = getPredictionWithoutOSRExit(BytecodeIndex(m_currentIndex.offset(), OpIteratorNext::getValue));
</span><span class="cx"> 
</span><span class="cx">                 {
</span><span class="lines">@@ -8326,7 +8318,7 @@
</span><span class="cx">             }
</span><span class="cx"> 
</span><span class="cx">             if (!compiledAsInById) {
</span><del>-                ArrayMode arrayMode = getArrayMode(bytecode.metadata(codeBlock).m_arrayProfile, Array::Read);
</del><ins>+                ArrayMode arrayMode = getArrayMode(*bytecode.metadata(codeBlock).m_arrayProfile, Array::Read);
</ins><span class="cx">                 set(bytecode.m_dst, addToGraph(InByVal, OpInfo(arrayMode.asWord()), base, property));
</span><span class="cx">             }
</span><span class="cx">             NEXT_OPCODE(op_in_by_val);
</span><span class="lines">@@ -8410,7 +8402,7 @@
</span><span class="cx">         case op_enumerator_next: {
</span><span class="cx">             auto bytecode = currentInstruction->as<OpEnumeratorNext>();
</span><span class="cx">             auto& metadata = bytecode.metadata(codeBlock);
</span><del>-            ArrayMode arrayMode = getArrayMode(metadata.m_arrayProfile, Array::Read);
</del><ins>+            ArrayMode arrayMode = getArrayMode(*metadata.m_arrayProfile, Array::Read);
</ins><span class="cx">             Node* base = get(bytecode.m_base);
</span><span class="cx">             Node* index = get(bytecode.m_index);
</span><span class="cx">             Node* enumerator = get(bytecode.m_enumerator);
</span><span class="lines">@@ -8442,7 +8434,7 @@
</span><span class="cx">         case op_enumerator_get_by_val: {
</span><span class="cx">             auto bytecode = currentInstruction->as<OpEnumeratorGetByVal>();
</span><span class="cx">             auto& metadata = bytecode.metadata(codeBlock);
</span><del>-            ArrayMode arrayMode = getArrayMode(metadata.m_arrayProfile, Array::Read);
</del><ins>+            ArrayMode arrayMode = getArrayMode(*metadata.m_arrayProfile, Array::Read);
</ins><span class="cx">             SpeculatedType speculation = getPredictionWithoutOSRExit();
</span><span class="cx"> 
</span><span class="cx">             Node* base = get(bytecode.m_base);
</span><span class="lines">@@ -8506,7 +8498,7 @@
</span><span class="cx">         case op_enumerator_in_by_val: {
</span><span class="cx">             auto bytecode = currentInstruction->as<OpEnumeratorInByVal>();
</span><span class="cx">             auto& metadata = bytecode.metadata(codeBlock);
</span><del>-            ArrayMode arrayMode = getArrayMode(metadata.m_arrayProfile, Array::Read);
</del><ins>+            ArrayMode arrayMode = getArrayMode(*metadata.m_arrayProfile, Array::Read);
</ins><span class="cx"> 
</span><span class="cx">             addVarArgChild(get(bytecode.m_base));
</span><span class="cx">             addVarArgChild(get(bytecode.m_propertyName));
</span><span class="lines">@@ -8521,7 +8513,7 @@
</span><span class="cx">         case op_enumerator_has_own_property: {
</span><span class="cx">             auto bytecode = currentInstruction->as<OpEnumeratorHasOwnProperty>();
</span><span class="cx">             auto& metadata = bytecode.metadata(codeBlock);
</span><del>-            ArrayMode arrayMode = getArrayMode(metadata.m_arrayProfile, Array::Read);
</del><ins>+            ArrayMode arrayMode = getArrayMode(*metadata.m_arrayProfile, Array::Read);
</ins><span class="cx"> 
</span><span class="cx">             addVarArgChild(get(bytecode.m_base));
</span><span class="cx">             addVarArgChild(get(bytecode.m_propertyName));
</span><span class="lines">@@ -8881,7 +8873,7 @@
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     if (!compiledAsPutById) {
</span><del>-        ArrayMode arrayMode = getArrayMode(bytecode.metadata(codeBlock).m_arrayProfile, Array::Write);
</del><ins>+        ArrayMode arrayMode = getArrayMode(*bytecode.metadata(codeBlock).m_arrayProfile, Array::Write);
</ins><span class="cx"> 
</span><span class="cx">         addVarArgChild(base);
</span><span class="cx">         addVarArgChild(property);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGFixupPhasecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp (282477 => 282478)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp        2021-09-15 22:12:01 UTC (rev 282477)
+++ trunk/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp   2021-09-15 22:18:52 UTC (rev 282478)
</span><span class="lines">@@ -4047,9 +4047,8 @@
</span><span class="cx">             profiledBlock->getArrayProfile(node->origin.semantic.bytecodeIndex());
</span><span class="cx">         ArrayMode arrayMode = ArrayMode(Array::SelectUsingPredictions, Array::Read);
</span><span class="cx">         if (arrayProfile) {
</span><del>-            ConcurrentJSLocker locker(profiledBlock->m_lock);
-            arrayProfile->computeUpdatedPrediction(locker, profiledBlock);
-            arrayMode = ArrayMode::fromObserved(locker, arrayProfile, Array::Read, false);
</del><ins>+            arrayProfile->computeUpdatedPrediction(profiledBlock);
+            arrayMode = ArrayMode::fromObserved(m_graph, node->origin.semantic, arrayProfile, Array::Read, false);
</ins><span class="cx">             if (arrayMode.type() == Array::Unprofiled) {
</span><span class="cx">                 // For normal array operations, it makes sense to treat Unprofiled
</span><span class="cx">                 // accesses as ForceExit and get more data rather than using
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGGraphh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGGraph.h (282477 => 282478)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGGraph.h       2021-09-15 22:12:01 UTC (rev 282477)
+++ trunk/Source/JavaScriptCore/dfg/DFGGraph.h  2021-09-15 22:18:52 UTC (rev 282478)
</span><span class="lines">@@ -520,7 +520,12 @@
</span><span class="cx">     {
</span><span class="cx">         return hasExitSite(node->origin.semantic, exitKind);
</span><span class="cx">     }
</span><del>-    
</del><ins>+
+    bool hasAnyExitsAt(const CodeOrigin& codeOrigin)
+    {
+        return baselineCodeBlockFor(codeOrigin)->unlinkedCodeBlock()->hasAnyExitsAt(codeOrigin.bytecodeIndex());
+    }
+
</ins><span class="cx">     MethodOfGettingAValueProfile methodOfGettingAValueProfileFor(Node* currentNode, Node* operandNode);
</span><span class="cx">     
</span><span class="cx">     BlockIndex numBlocks() const { return m_blocks.size(); }
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGOSRExitCompilerCommoncpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGOSRExitCompilerCommon.cpp (282477 => 282478)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGOSRExitCompilerCommon.cpp     2021-09-15 22:12:01 UTC (rev 282477)
+++ trunk/Source/JavaScriptCore/dfg/DFGOSRExitCompilerCommon.cpp        2021-09-15 22:18:52 UTC (rev 282478)
</span><span class="lines">@@ -337,16 +337,22 @@
</span><span class="cx">     }
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-static void osrWriteBarrier(VM& vm, CCallHelpers& jit, GPRReg owner, GPRReg scratch)
</del><ins>+static void osrWriteBarrier(VM& vm, CCallHelpers& jit, CodeBlock* codeBlock, GPRReg owner, GPRReg scratch)
</ins><span class="cx"> {
</span><del>-    AssemblyHelpers::Jump ownerIsRememberedOrInEden = jit.barrierBranchWithoutFence(owner);
</del><ins>+    auto emitBarrier = [&] (auto* cell) {
+        jit.move(AssemblyHelpers::TrustedImmPtr(cell), owner);
+        AssemblyHelpers::Jump ownerIsRememberedOrInEden = jit.barrierBranchWithoutFence(owner);
</ins><span class="cx"> 
</span><del>-    jit.setupArguments<decltype(operationOSRWriteBarrier)>(&vm, owner);
-    jit.prepareCallOperation(vm);
-    jit.move(MacroAssembler::TrustedImmPtr(tagCFunction<OperationPtrTag>(operationOSRWriteBarrier)), scratch);
-    jit.call(scratch, OperationPtrTag);
</del><ins>+        jit.setupArguments<decltype(operationOSRWriteBarrier)>(&vm, owner);
+        jit.prepareCallOperation(vm);
+        jit.move(MacroAssembler::TrustedImmPtr(tagCFunction<OperationPtrTag>(operationOSRWriteBarrier)), scratch);
+        jit.call(scratch, OperationPtrTag);
</ins><span class="cx"> 
</span><del>-    ownerIsRememberedOrInEden.link(&jit);
</del><ins>+        ownerIsRememberedOrInEden.link(&jit);
+    };
+
+    emitBarrier(codeBlock);
+    emitBarrier(codeBlock->unlinkedCodeBlock());
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void adjustAndJumpToTarget(VM& vm, CCallHelpers& jit, const OSRExitBase& exit)
</span><span class="lines">@@ -353,10 +359,7 @@
</span><span class="cx"> {
</span><span class="cx">     jit.memoryFence();
</span><span class="cx">     
</span><del>-    jit.move(
-        AssemblyHelpers::TrustedImmPtr(
-            jit.codeBlock()->baselineAlternative()), GPRInfo::argumentGPR1);
-    osrWriteBarrier(vm, jit, GPRInfo::argumentGPR1, GPRInfo::nonArgGPR0);
</del><ins>+    osrWriteBarrier(vm, jit, jit.codeBlock()->baselineAlternative(), GPRInfo::argumentGPR1, GPRInfo::nonArgGPR0);
</ins><span class="cx"> 
</span><span class="cx">     // We barrier all inlined frames -- and not just the current inline stack --
</span><span class="cx">     // because we don't know which inlined function owns the value profile that
</span><span class="lines">@@ -367,12 +370,8 @@
</span><span class="cx">     // the value profile.
</span><span class="cx">     InlineCallFrameSet* inlineCallFrames = jit.codeBlock()->jitCode()->dfgCommon()->inlineCallFrames.get();
</span><span class="cx">     if (inlineCallFrames) {
</span><del>-        for (InlineCallFrame* inlineCallFrame : *inlineCallFrames) {
-            jit.move(
-                AssemblyHelpers::TrustedImmPtr(
-                    inlineCallFrame->baselineCodeBlock.get()), GPRInfo::argumentGPR1);
-            osrWriteBarrier(vm, jit, GPRInfo::argumentGPR1, GPRInfo::nonArgGPR0);
-        }
</del><ins>+        for (InlineCallFrame* inlineCallFrame : *inlineCallFrames)
+            osrWriteBarrier(vm, jit, inlineCallFrame->baselineCodeBlock.get(), GPRInfo::argumentGPR1, GPRInfo::nonArgGPR0);
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     auto* exitInlineCallFrame = exit.m_codeOrigin.inlineCallFrame();
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGPredictionInjectionPhasecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGPredictionInjectionPhase.cpp (282477 => 282478)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGPredictionInjectionPhase.cpp  2021-09-15 22:12:01 UTC (rev 282477)
+++ trunk/Source/JavaScriptCore/dfg/DFGPredictionInjectionPhase.cpp     2021-09-15 22:18:52 UTC (rev 282478)
</span><span class="lines">@@ -48,8 +48,6 @@
</span><span class="cx">         
</span><span class="cx">         ASSERT(codeBlock()->numParameters() >= 1);
</span><span class="cx">         {
</span><del>-            ConcurrentJSLocker locker(profiledBlock()->m_lock);
-            
</del><span class="cx">             // We only do this for the arguments at the first block. The arguments from
</span><span class="cx">             // other entrypoints have already been populated with their predictions.
</span><span class="cx">             auto& arguments = m_graph.m_rootToArguments.find(m_graph.block(0))->value;
</span><span class="lines">@@ -56,8 +54,7 @@
</span><span class="cx"> 
</span><span class="cx">             for (size_t arg = 0; arg < static_cast<size_t>(codeBlock()->numParameters()); ++arg) {
</span><span class="cx">                 ValueProfile& profile = profiledBlock()->valueProfileForArgument(arg);
</span><del>-                arguments[arg]->variableAccessData()->predict(
-                    profile.computeUpdatedPrediction(locker));
</del><ins>+                arguments[arg]->variableAccessData()->predict(profile.computeUpdatedPrediction());
</ins><span class="cx">             }
</span><span class="cx">         }
</span><span class="cx">         
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreheapCodeBlockSetInlinesh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/heap/CodeBlockSetInlines.h (282477 => 282478)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/heap/CodeBlockSetInlines.h   2021-09-15 22:12:01 UTC (rev 282477)
+++ trunk/Source/JavaScriptCore/heap/CodeBlockSetInlines.h      2021-09-15 22:18:52 UTC (rev 282478)
</span><span class="lines">@@ -62,12 +62,9 @@
</span><span class="cx"> template<typename Functor>
</span><span class="cx"> void CodeBlockSet::iterateViaSubspaces(VM& vm, const Functor& functor)
</span><span class="cx"> {
</span><del>-    vm.forEachCodeBlockSpace(
-        [&] (auto& spaceAndSet) {
-            spaceAndSet.space.forEachLiveCell(
-                [&] (HeapCell* cell, HeapCell::Kind) {
-                    functor(jsCast<CodeBlock*>(static_cast<JSCell*>(cell)));
-                });
</del><ins>+    vm.codeBlockSpace.space.forEachLiveCell(
+        [&] (HeapCell* cell, HeapCell::Kind) {
+            functor(jsCast<CodeBlock*>(static_cast<JSCell*>(cell)));
</ins><span class="cx">         });
</span><span class="cx"> }
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreheapHeapcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/heap/Heap.cpp (282477 => 282478)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/heap/Heap.cpp        2021-09-15 22:12:01 UTC (rev 282477)
+++ trunk/Source/JavaScriptCore/heap/Heap.cpp   2021-09-15 22:18:52 UTC (rev 282478)
</span><span class="lines">@@ -583,10 +583,10 @@
</span><span class="cx">     }
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-template<typename CellType, typename CellSet>
-void Heap::finalizeMarkedUnconditionalFinalizers(CellSet& cellSet)
</del><ins>+template<typename CellType, typename CellSetOrIsoSubspace>
+void Heap::finalizeMarkedUnconditionalFinalizers(CellSetOrIsoSubspace& setOrSubspace)
</ins><span class="cx"> {
</span><del>-    cellSet.forEachMarkedCell(
</del><ins>+    setOrSubspace.forEachMarkedCell(
</ins><span class="cx">         [&] (HeapCell* cell, HeapCell::Kind) {
</span><span class="cx">             static_cast<CellType*>(cell)->finalizeUnconditionally(vm());
</span><span class="cx">         });
</span><span class="lines">@@ -598,10 +598,12 @@
</span><span class="cx">     finalizeMarkedUnconditionalFinalizers<FunctionExecutable>(vm().functionExecutableSpace.space);
</span><span class="cx">     finalizeMarkedUnconditionalFinalizers<SymbolTable>(vm().symbolTableSpace);
</span><span class="cx">     finalizeMarkedUnconditionalFinalizers<ExecutableToCodeBlockEdge>(vm().executableToCodeBlockEdgesWithFinalizers); // We run this before CodeBlock's unconditional finalizer since CodeBlock looks at the owner executable's installed CodeBlock in its finalizeUnconditionally.
</span><del>-    vm().forEachCodeBlockSpace(
-        [&] (auto& space) {
-            this->finalizeMarkedUnconditionalFinalizers<CodeBlock>(space.set);
-        });
</del><ins>+    finalizeMarkedUnconditionalFinalizers<CodeBlock>(vm().codeBlockSpace.set);
+    vm().forEachUnlinkedCodeBlockSpace([&] (VM::SpaceAndSet* spaceAndSet) {
+        if (!spaceAndSet)
+            return;
+        finalizeMarkedUnconditionalFinalizers<UnlinkedCodeBlock>(spaceAndSet->set);
+    });
</ins><span class="cx">     finalizeMarkedUnconditionalFinalizers<StructureRareData>(vm().structureRareDataSpace);
</span><span class="cx">     finalizeMarkedUnconditionalFinalizers<UnlinkedFunctionExecutable>(vm().unlinkedFunctionExecutableSpace.set);
</span><span class="cx">     if (vm().m_weakSetSpace)
</span><span class="lines">@@ -973,7 +975,7 @@
</span><span class="cx">     vm().forEachScriptExecutableSpace([] (auto& space) { space.space.sweep(); });
</span><span class="cx">     // Sweeping must occur before deleting stubs, otherwise the stubs might still think they're alive as they get deleted.
</span><span class="cx">     // And CodeBlock destructor is assuming that CodeBlock gets destroyed before UnlinkedCodeBlock gets destroyed.
</span><del>-    vm().forEachCodeBlockSpace([] (auto& space) { space.space.sweep(); });
</del><ins>+    vm().codeBlockSpace.space.sweep();
</ins><span class="cx">     m_jitStubRoutines->deleteUnmarkedJettisonedStubRoutines();
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -1486,6 +1488,7 @@
</span><span class="cx">     iterateExecutingAndCompilingCodeBlocks(visitor,
</span><span class="cx">         [&] (CodeBlock* codeBlock) {
</span><span class="cx">             writeBarrier(codeBlock);
</span><ins>+            writeBarrier(codeBlock->unlinkedCodeBlock());
</ins><span class="cx">         });
</span><span class="cx"> 
</span><span class="cx">     updateObjectCounts();
</span><span class="lines">@@ -1523,6 +1526,7 @@
</span><span class="cx">     m_codeBlocks->iterateCurrentlyExecuting(
</span><span class="cx">         [&] (CodeBlock* codeBlock) {
</span><span class="cx">             writeBarrier(codeBlock);
</span><ins>+            writeBarrier(codeBlock->unlinkedCodeBlock());
</ins><span class="cx">         });
</span><span class="cx">     m_codeBlocks->clearCurrentlyExecuting();
</span><span class="cx">         
</span><span class="lines">@@ -2886,10 +2890,14 @@
</span><span class="cx">             SetRootMarkReasonScope rootScope(visitor, RootMarkReason::CodeBlocks);
</span><span class="cx">             iterateExecutingAndCompilingCodeBlocksWithoutHoldingLocks(visitor,
</span><span class="cx">                 [&] (CodeBlock* codeBlock) {
</span><ins>+                    auto handle = [&] (auto* cell) {
+                        if (visitor.isMarked(cell)
+                            && cell->cellState() == CellState::PossiblyBlack)
+                            visitor.visitAsConstraint(cell);
+                    };
</ins><span class="cx">                     // Visit the CodeBlock as a constraint only if it's black.
</span><del>-                    if (visitor.isMarked(codeBlock)
-                        && codeBlock->cellState() == CellState::PossiblyBlack)
-                        visitor.visitAsConstraint(codeBlock);
</del><ins>+                    handle(codeBlock);
+                    handle(codeBlock->unlinkedCodeBlock());
</ins><span class="cx">                 });
</span><span class="cx">         })),
</span><span class="cx">         ConstraintVolatility::SeldomGreyed);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitJITh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/JIT.h (282477 => 282478)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/JIT.h    2021-09-15 22:12:01 UTC (rev 282477)
+++ trunk/Source/JavaScriptCore/jit/JIT.h       2021-09-15 22:18:52 UTC (rev 282478)
</span><span class="lines">@@ -302,7 +302,7 @@
</span><span class="cx"> 
</span><span class="cx">         void emitValueProfilingSiteIfProfiledOpcode(...);
</span><span class="cx">         template<typename Op>
</span><del>-        std::enable_if_t<std::is_same<decltype(Op::Metadata::m_profile), ValueProfile>::value, void>
</del><ins>+        std::enable_if_t<std::is_same<decltype(Op::Metadata::m_profile), ValueProfile*>::value, void>
</ins><span class="cx">         emitValueProfilingSiteIfProfiledOpcode(Op bytecode);
</span><span class="cx"> 
</span><span class="cx">         void emitArrayProfilingSiteWithCell(RegisterID cellGPR, ArrayProfile*, RegisterID scratchGPR);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitJITInlinesh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/JITInlines.h (282477 => 282478)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/JITInlines.h     2021-09-15 22:12:01 UTC (rev 282477)
+++ trunk/Source/JavaScriptCore/jit/JITInlines.h        2021-09-15 22:18:52 UTC (rev 282478)
</span><span class="lines">@@ -312,7 +312,7 @@
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> template<typename Op>
</span><del>-inline std::enable_if_t<std::is_same<decltype(Op::Metadata::m_profile), ValueProfile>::value, void> JIT::emitValueProfilingSiteIfProfiledOpcode(Op bytecode)
</del><ins>+inline std::enable_if_t<std::is_same<decltype(Op::Metadata::m_profile), ValueProfile*>::value, void> JIT::emitValueProfilingSiteIfProfiledOpcode(Op bytecode)
</ins><span class="cx"> {
</span><span class="cx"> #if USE(JSVALUE64)
</span><span class="cx">     emitValueProfilingSite(bytecode.metadata(m_codeBlock), regT0);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitJITOpcodescpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/JITOpcodes.cpp (282477 => 282478)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/JITOpcodes.cpp   2021-09-15 22:12:01 UTC (rev 282477)
+++ trunk/Source/JavaScriptCore/jit/JITOpcodes.cpp      2021-09-15 22:18:52 UTC (rev 282478)
</span><span class="lines">@@ -1194,6 +1194,7 @@
</span><span class="cx">         emitInitRegister(virtualRegisterForLocal(j));
</span><span class="cx"> 
</span><span class="cx">     emitWriteBarrier(m_codeBlock);
</span><ins>+    emitWriteBarrier(m_codeBlock->unlinkedCodeBlock());
</ins><span class="cx"> 
</span><span class="cx">     emitEnterOptimizationCheck();
</span><span class="cx"> #else
</span><span class="lines">@@ -1245,17 +1246,29 @@
</span><span class="cx">     initDone.link(&jit);
</span><span class="cx"> 
</span><span class="cx">     // emitWriteBarrier(m_codeBlock).
</span><ins>+    // emitWriteBarrier(m_codeBlock->unlinkedCodeBlock()).
</ins><span class="cx">     jit.loadPtr(addressFor(CallFrameSlot::codeBlock), argumentGPR1);
</span><del>-    Jump ownerIsRememberedOrInEden = jit.barrierBranch(vm, argumentGPR1, argumentGPR2);
-
</del><span class="cx">     jit.move(canBeOptimizedGPR, GPRInfo::numberTagRegister); // save.
</span><del>-    jit.setupArguments<decltype(operationWriteBarrierSlowPath)>(&vm, argumentGPR1);
-    jit.prepareCallOperation(vm);
-    Call operationWriteBarrierCall = jit.call(OperationPtrTag);
-
</del><ins>+    Call operationWriteBarrierCall1;
+    Call operationWriteBarrierCall2;
+    {
+        Jump ownerIsRememberedOrInEden = jit.barrierBranch(vm, argumentGPR1, argumentGPR2);
+        jit.setupArguments<decltype(operationWriteBarrierSlowPath)>(&vm, argumentGPR1);
+        jit.prepareCallOperation(vm);
+        operationWriteBarrierCall1 = jit.call(OperationPtrTag);
+        jit.loadPtr(addressFor(CallFrameSlot::codeBlock), argumentGPR1);
+        ownerIsRememberedOrInEden.link(&jit);
+    }
+    {
+        jit.loadPtr(Address(argumentGPR1, CodeBlock::offsetOfUnlinkedCodeBlock()), argumentGPR1);
+        Jump ownerIsRememberedOrInEden = jit.barrierBranch(vm, argumentGPR1, argumentGPR2);
+        jit.setupArguments<decltype(operationWriteBarrierSlowPath)>(&vm, argumentGPR1);
+        jit.prepareCallOperation(vm);
+        operationWriteBarrierCall2 = jit.call(OperationPtrTag);
+        ownerIsRememberedOrInEden.link(&jit);
+    }
</ins><span class="cx">     jit.move(GPRInfo::numberTagRegister, canBeOptimizedGPR); // restore.
</span><span class="cx">     jit.move(TrustedImm64(JSValue::NumberTag), GPRInfo::numberTagRegister);
</span><del>-    ownerIsRememberedOrInEden.link(&jit);
</del><span class="cx"> 
</span><span class="cx"> #if ENABLE(DFG_JIT)
</span><span class="cx">     Call operationOptimizeCall;
</span><span class="lines">@@ -1289,7 +1302,8 @@
</span><span class="cx">     jit.ret();
</span><span class="cx"> 
</span><span class="cx">     LinkBuffer patchBuffer(jit, GLOBAL_THUNK_ID, LinkBuffer::Profile::ExtraCTIThunk);
</span><del>-    patchBuffer.link(operationWriteBarrierCall, FunctionPtr<OperationPtrTag>(operationWriteBarrierSlowPath));
</del><ins>+    patchBuffer.link(operationWriteBarrierCall1, FunctionPtr<OperationPtrTag>(operationWriteBarrierSlowPath));
+    patchBuffer.link(operationWriteBarrierCall2, FunctionPtr<OperationPtrTag>(operationWriteBarrierSlowPath));
</ins><span class="cx"> #if ENABLE(DFG_JIT)
</span><span class="cx">     if (Options::useDFGJIT())
</span><span class="cx">         patchBuffer.link(operationOptimizeCall, FunctionPtr<OperationPtrTag>(operationOptimize));
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitJITOperationscpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/JITOperations.cpp (282477 => 282478)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/JITOperations.cpp        2021-09-15 22:12:01 UTC (rev 282477)
+++ trunk/Source/JavaScriptCore/jit/JITOperations.cpp   2021-09-15 22:18:52 UTC (rev 282478)
</span><span class="lines">@@ -1028,10 +1028,8 @@
</span><span class="cx">         if (!isCopyOnWrite(baseObject->indexingMode()) && subscript.isInt32()) {
</span><span class="cx">             Structure* structure = baseObject->structure(vm);
</span><span class="cx">             if (stubInfo->considerCachingGeneric(vm, codeBlock, structure)) {
</span><del>-                if (profile) {
-                    ConcurrentJSLocker locker(codeBlock->m_lock);
-                    profile->computeUpdatedPrediction(locker, codeBlock, structure);
-                }
</del><ins>+                if (profile)
+                    profile->computeUpdatedPrediction(codeBlock, structure);
</ins><span class="cx">                 repatchArrayPutByVal(globalObject, codeBlock, baseValue, subscript, *stubInfo, PutKind::NotDirect, ecmaMode);
</span><span class="cx">             }
</span><span class="cx">         }
</span><span class="lines">@@ -1098,10 +1096,8 @@
</span><span class="cx">     if (!isCopyOnWrite(baseObject->indexingMode()) && subscript.isInt32()) {
</span><span class="cx">         Structure* structure = baseObject->structure(vm);
</span><span class="cx">         if (stubInfo->considerCachingGeneric(vm, codeBlock, structure)) {
</span><del>-            if (profile) {
-                ConcurrentJSLocker locker(codeBlock->m_lock);
-                profile->computeUpdatedPrediction(locker, codeBlock, structure);
-            }
</del><ins>+            if (profile)
+                profile->computeUpdatedPrediction(codeBlock, structure);
</ins><span class="cx">             repatchArrayPutByVal(globalObject, codeBlock, baseValue, subscript, *stubInfo, PutKind::Direct, ecmaMode);
</span><span class="cx">         }
</span><span class="cx">     }
</span><span class="lines">@@ -2412,10 +2408,8 @@
</span><span class="cx">     if (baseValue.isCell() && subscript.isInt32()) {
</span><span class="cx">         Structure* structure = baseValue.asCell()->structure(vm);
</span><span class="cx">         if (stubInfo->considerCachingGeneric(vm, codeBlock, structure)) {
</span><del>-            if (profile) {
-                ConcurrentJSLocker locker(codeBlock->m_lock);
-                profile->computeUpdatedPrediction(locker, codeBlock, structure);
-            }
</del><ins>+            if (profile)
+                profile->computeUpdatedPrediction(codeBlock, structure);
</ins><span class="cx">             repatchArrayGetByVal(globalObject, codeBlock, baseValue, subscript, *stubInfo);
</span><span class="cx">         }
</span><span class="cx">     }
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitJITPropertyAccesscpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/JITPropertyAccess.cpp (282477 => 282478)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/JITPropertyAccess.cpp    2021-09-15 22:12:01 UTC (rev 282477)
+++ trunk/Source/JavaScriptCore/jit/JITPropertyAccess.cpp       2021-09-15 22:18:52 UTC (rev 282478)
</span><span class="lines">@@ -53,7 +53,7 @@
</span><span class="cx">     VirtualRegister dst = bytecode.m_dst;
</span><span class="cx">     VirtualRegister base = bytecode.m_base;
</span><span class="cx">     VirtualRegister property = bytecode.m_property;
</span><del>-    ArrayProfile* profile = &metadata.m_arrayProfile;
</del><ins>+    ArrayProfile* profile = metadata.m_arrayProfile;
</ins><span class="cx"> 
</span><span class="cx">     emitGetVirtualRegister(base, regT0);
</span><span class="cx">     emitGetVirtualRegister(property, regT1);
</span><span class="lines">@@ -93,7 +93,7 @@
</span><span class="cx">     if (hasAnySlowCases(iter)) {
</span><span class="cx">         VirtualRegister dst = bytecode.m_dst;
</span><span class="cx">         auto& metadata = bytecode.metadata(m_codeBlock);
</span><del>-        ArrayProfile* profile = &metadata.m_arrayProfile;
</del><ins>+        ArrayProfile* profile = metadata.m_arrayProfile;
</ins><span class="cx"> 
</span><span class="cx">         linkAllSlowCases(iter);
</span><span class="cx"> 
</span><span class="lines">@@ -439,7 +439,7 @@
</span><span class="cx">     VirtualRegister base = bytecode.m_base;
</span><span class="cx">     VirtualRegister property = bytecode.m_property;
</span><span class="cx">     VirtualRegister value = bytecode.m_value;
</span><del>-    ArrayProfile* profile = &metadata.m_arrayProfile;
</del><ins>+    ArrayProfile* profile = metadata.m_arrayProfile;
</ins><span class="cx"> 
</span><span class="cx">     emitGetVirtualRegister(base, regT0);
</span><span class="cx">     emitGetVirtualRegister(property, regT1);
</span><span class="lines">@@ -482,7 +482,7 @@
</span><span class="cx">         value = bytecode.m_value;
</span><span class="cx">         ecmaMode = bytecode.m_ecmaMode;
</span><span class="cx">         auto& metadata = bytecode.metadata(m_codeBlock);
</span><del>-        profile = &metadata.m_arrayProfile;
</del><ins>+        profile = metadata.m_arrayProfile;
</ins><span class="cx">     };
</span><span class="cx"> 
</span><span class="cx">     if (isDirect)
</span><span class="lines">@@ -1108,11 +1108,8 @@
</span><span class="cx">     
</span><span class="cx">     emitJumpSlowCaseIfNotJSCell(regT0, baseVReg);
</span><span class="cx">     
</span><del>-    if (*ident == m_vm->propertyNames->length && shouldEmitProfiling()) {
-        Jump notArrayLengthMode = branch8(NotEqual, AbsoluteAddress(&metadata.m_modeMetadata.mode), TrustedImm32(static_cast<uint8_t>(GetByIdMode::ArrayLength)));
-        emitArrayProfilingSiteWithCell(regT0, &metadata.m_modeMetadata.arrayLengthMode.arrayProfile, regT1);
-        notArrayLengthMode.link(this);
-    }
</del><ins>+    if (*ident == m_vm->propertyNames->length && shouldEmitProfiling())
+        emitArrayProfilingSiteWithCell(regT0, metadata.m_arrayProfile, regT1);
</ins><span class="cx"> 
</span><span class="cx">     JSValueRegs resultRegs = JSValueRegs(regT0);
</span><span class="cx"> 
</span><span class="lines">@@ -1511,7 +1508,7 @@
</span><span class="cx">     VirtualRegister base = bytecode.m_base;
</span><span class="cx">     VirtualRegister property = bytecode.m_property;
</span><span class="cx">     auto& metadata = bytecode.metadata(m_codeBlock);
</span><del>-    ArrayProfile* profile = &metadata.m_arrayProfile;
</del><ins>+    ArrayProfile* profile = metadata.m_arrayProfile;
</ins><span class="cx"> 
</span><span class="cx">     emitGetVirtualRegister(base, regT0);
</span><span class="cx">     emitGetVirtualRegister(property, regT1);
</span><span class="lines">@@ -1538,7 +1535,7 @@
</span><span class="cx">     auto bytecode = currentInstruction->as<OpInByVal>();
</span><span class="cx">     VirtualRegister dst = bytecode.m_dst;
</span><span class="cx">     auto& metadata = bytecode.metadata(m_codeBlock);
</span><del>-    ArrayProfile* profile = &metadata.m_arrayProfile;
</del><ins>+    ArrayProfile* profile = metadata.m_arrayProfile;
</ins><span class="cx"> 
</span><span class="cx">     JITInByValGenerator& gen = m_inByVals[m_inByValIndex++];
</span><span class="cx"> 
</span><span class="lines">@@ -2393,7 +2390,8 @@
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     static_assert(ValueProfile::numberOfBuckets == 1);
</span><del>-    store64(regT0, Address(metadataGPR, OBJECT_OFFSETOF(Metadata, m_profile)));
</del><ins>+    loadPtr(Address(metadataGPR, OBJECT_OFFSETOF(Metadata, m_profile)), regT1);
+    store64(regT0, Address(regT1, ValueProfile::offsetOfFirstBucket()));
</ins><span class="cx"> 
</span><span class="cx">     ret();
</span><span class="cx"> 
</span><span class="lines">@@ -2449,7 +2447,8 @@
</span><span class="cx">     Call operation = jit.call(OperationPtrTag);
</span><span class="cx">     Jump exceptionCheck = jit.emitNonPatchableExceptionCheck(vm);
</span><span class="cx"> 
</span><del>-    jit.store64(regT0, Address(GPRInfo::numberTagRegister, OBJECT_OFFSETOF(Metadata, m_profile)));
</del><ins>+    jit.loadPtr(Address(GPRInfo::numberTagRegister, OBJECT_OFFSETOF(Metadata, m_profile)), GPRInfo::numberTagRegister);
+    jit.store64(regT0, Address(GPRInfo::numberTagRegister, ValueProfile::offsetOfFirstBucket()));
</ins><span class="cx">     jit.move(TrustedImm64(JSValue::NumberTag), GPRInfo::numberTagRegister);
</span><span class="cx"> 
</span><span class="cx"> #if CPU(X86_64)
</span><span class="lines">@@ -2888,7 +2887,7 @@
</span><span class="cx">     VirtualRegister index = bytecode.m_index;
</span><span class="cx">     VirtualRegister propertyName = bytecode.m_propertyName;
</span><span class="cx">     VirtualRegister enumerator = bytecode.m_enumerator;
</span><del>-    ArrayProfile* profile = &metadata.m_arrayProfile;
</del><ins>+    ArrayProfile* profile = metadata.m_arrayProfile;
</ins><span class="cx"> 
</span><span class="cx">     JumpList doneCases;
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitJITPropertyAccess32_64cpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/JITPropertyAccess32_64.cpp (282477 => 282478)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/JITPropertyAccess32_64.cpp       2021-09-15 22:12:01 UTC (rev 282477)
+++ trunk/Source/JavaScriptCore/jit/JITPropertyAccess32_64.cpp  2021-09-15 22:18:52 UTC (rev 282478)
</span><span class="lines">@@ -241,7 +241,7 @@
</span><span class="cx">     VirtualRegister dst = bytecode.m_dst;
</span><span class="cx">     VirtualRegister base = bytecode.m_base;
</span><span class="cx">     VirtualRegister property = bytecode.m_property;
</span><del>-    ArrayProfile* profile = &metadata.m_arrayProfile;
</del><ins>+    ArrayProfile* profile = metadata.m_arrayProfile;
</ins><span class="cx"> 
</span><span class="cx">     emitLoad2(base, regT1, regT0, property, regT3, regT2);
</span><span class="cx"> 
</span><span class="lines">@@ -276,7 +276,7 @@
</span><span class="cx">         auto bytecode = currentInstruction->as<OpGetByVal>();
</span><span class="cx">         VirtualRegister dst = bytecode.m_dst;
</span><span class="cx">         auto& metadata = bytecode.metadata(m_codeBlock);
</span><del>-        ArrayProfile* profile = &metadata.m_arrayProfile;
</del><ins>+        ArrayProfile* profile = metadata.m_arrayProfile;
</ins><span class="cx"> 
</span><span class="cx">         JITGetByValGenerator& gen = m_getByVals[m_getByValIndex];
</span><span class="cx">         ++m_getByValIndex;
</span><span class="lines">@@ -469,7 +469,7 @@
</span><span class="cx">     VirtualRegister base = bytecode.m_base;
</span><span class="cx">     VirtualRegister property = bytecode.m_property;
</span><span class="cx">     VirtualRegister value = bytecode.m_value;
</span><del>-    ArrayProfile* profile = &metadata.m_arrayProfile;
</del><ins>+    ArrayProfile* profile = metadata.m_arrayProfile;
</ins><span class="cx"> 
</span><span class="cx">     emitLoad2(base, regT1, regT0, property, regT3, regT2);
</span><span class="cx">     emitLoad(value, regT5, regT4);
</span><span class="lines">@@ -505,7 +505,7 @@
</span><span class="cx">         value = bytecode.m_value;
</span><span class="cx">         ecmaMode = JIT::ecmaMode(bytecode);
</span><span class="cx">         auto& metadata = bytecode.metadata(m_codeBlock);
</span><del>-        profile = &metadata.m_arrayProfile;
</del><ins>+        profile = metadata.m_arrayProfile;
</ins><span class="cx">     };
</span><span class="cx"> 
</span><span class="cx">     if (isDirect)
</span><span class="lines">@@ -622,11 +622,8 @@
</span><span class="cx">     emitLoad(base, regT1, regT0);
</span><span class="cx">     emitJumpSlowCaseIfNotJSCell(base, regT1);
</span><span class="cx"> 
</span><del>-    if (*ident == m_vm->propertyNames->length && shouldEmitProfiling()) {
-        Jump notArrayLengthMode = branch8(NotEqual, AbsoluteAddress(&metadata.m_modeMetadata.mode), TrustedImm32(static_cast<uint8_t>(GetByIdMode::ArrayLength)));
-        emitArrayProfilingSiteWithCell(regT0, &metadata.m_modeMetadata.arrayLengthMode.arrayProfile, regT2);
-        notArrayLengthMode.link(this);
-    }
</del><ins>+    if (*ident == m_vm->propertyNames->length && shouldEmitProfiling())
+        emitArrayProfilingSiteWithCell(regT0, metadata.m_arrayProfile, regT2);
</ins><span class="cx"> 
</span><span class="cx">     JSValueRegs resultRegs = JSValueRegs(regT1, regT0);
</span><span class="cx">     JITGetByIdGenerator gen(
</span><span class="lines">@@ -797,7 +794,7 @@
</span><span class="cx">     VirtualRegister base = bytecode.m_base;
</span><span class="cx">     VirtualRegister property = bytecode.m_property;
</span><span class="cx">     auto& metadata = bytecode.metadata(m_codeBlock);
</span><del>-    ArrayProfile* profile = &metadata.m_arrayProfile;
</del><ins>+    ArrayProfile* profile = metadata.m_arrayProfile;
</ins><span class="cx"> 
</span><span class="cx">     emitLoad2(base, regT1, regT0, property, regT3, regT2);
</span><span class="cx">     emitJumpSlowCaseIfNotJSCell(base, regT1);
</span><span class="lines">@@ -820,7 +817,7 @@
</span><span class="cx">     auto bytecode = currentInstruction->as<OpInByVal>();
</span><span class="cx">     VirtualRegister dst = bytecode.m_dst;
</span><span class="cx">     auto& metadata = bytecode.metadata(m_codeBlock);
</span><del>-    ArrayProfile* profile = &metadata.m_arrayProfile;
</del><ins>+    ArrayProfile* profile = metadata.m_arrayProfile;
</ins><span class="cx"> 
</span><span class="cx">     JITInByValGenerator& gen = m_inByVals[m_inByValIndex++];
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorellintLLIntSlowPathscpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/llint/LLIntSlowPaths.cpp (282477 => 282478)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/llint/LLIntSlowPaths.cpp     2021-09-15 22:12:01 UTC (rev 282477)
+++ trunk/Source/JavaScriptCore/llint/LLIntSlowPaths.cpp        2021-09-15 22:18:52 UTC (rev 282478)
</span><span class="lines">@@ -153,7 +153,7 @@
</span><span class="cx">     } while (false)
</span><span class="cx"> 
</span><span class="cx"> #define LLINT_PROFILE_VALUE(value) do { \
</span><del>-        bytecode.metadata(codeBlock).m_profile.m_buckets[0] = JSValue::encode(value); \
</del><ins>+        bytecode.metadata(codeBlock).m_profile->m_buckets[0] = JSValue::encode(value); \
</ins><span class="cx">     } while (false)
</span><span class="cx"> 
</span><span class="cx"> #define LLINT_CALL_END_IMPL(callFrame, callTarget, callTargetTag) \
</span><span class="lines">@@ -761,7 +761,7 @@
</span><span class="cx">     vm.heap.writeBarrier(codeBlock);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-static JSValue performLLIntGetByID(const Instruction* pc, CodeBlock* codeBlock, JSGlobalObject* globalObject, JSValue baseValue, const Identifier& ident, GetByIdModeMetadata& metadata)
</del><ins>+static JSValue performLLIntGetByID(const Instruction* pc, CodeBlock* codeBlock, JSGlobalObject* globalObject, JSValue baseValue, const Identifier& ident, GetByIdModeMetadata& metadata, ArrayProfile* arrayProfile)
</ins><span class="cx"> {
</span><span class="cx">     VM& vm = globalObject->vm();
</span><span class="cx">     auto throwScope = DECLARE_THROW_SCOPE(vm);
</span><span class="lines">@@ -824,8 +824,9 @@
</span><span class="cx">     } else if (!LLINT_ALWAYS_ACCESS_SLOW && isJSArray(baseValue) && ident == vm.propertyNames->length) {
</span><span class="cx">         {
</span><span class="cx">             ConcurrentJSLocker locker(codeBlock->m_lock);
</span><ins>+            RELEASE_ASSERT(arrayProfile);
</ins><span class="cx">             metadata.setArrayLengthMode();
</span><del>-            metadata.arrayLengthMode.arrayProfile.observeStructure(baseValue.asCell()->structure(vm));
</del><ins>+            arrayProfile->observeStructure(baseValue.asCell()->structure(vm));
</ins><span class="cx">         }
</span><span class="cx">         vm.heap.writeBarrier(codeBlock);
</span><span class="cx">     }
</span><span class="lines">@@ -841,7 +842,7 @@
</span><span class="cx">     const Identifier& ident = codeBlock->identifier(bytecode.m_property);
</span><span class="cx">     JSValue baseValue = getOperand(callFrame, bytecode.m_base);
</span><span class="cx"> 
</span><del>-    JSValue result = performLLIntGetByID(pc, codeBlock, globalObject, baseValue, ident, metadata.m_modeMetadata);
</del><ins>+    JSValue result = performLLIntGetByID(pc, codeBlock, globalObject, baseValue, ident, metadata.m_modeMetadata, metadata.m_arrayProfile);
</ins><span class="cx">     LLINT_RETURN_PROFILED(result);
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -857,10 +858,10 @@
</span><span class="cx">     if (!iterator.isObject())
</span><span class="cx">         LLINT_THROW(createTypeError(globalObject, "Iterator result interface is not an object."_s));
</span><span class="cx"> 
</span><del>-    JSValue result = performLLIntGetByID(pc, codeBlock, globalObject, iterator, vm.propertyNames->next, metadata.m_modeMetadata);
</del><ins>+    JSValue result = performLLIntGetByID(pc, codeBlock, globalObject, iterator, vm.propertyNames->next, metadata.m_modeMetadata, nullptr);
</ins><span class="cx">     LLINT_CHECK_EXCEPTION();
</span><span class="cx">     nextRegister = result;
</span><del>-    bytecode.metadata(codeBlock).m_nextProfile.m_buckets[0] = JSValue::encode(result);
</del><ins>+    bytecode.metadata(codeBlock).m_nextProfile->m_buckets[0] = JSValue::encode(result);
</ins><span class="cx">     LLINT_END();
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -877,10 +878,10 @@
</span><span class="cx">     if (!iteratorReturn.isObject())
</span><span class="cx">         LLINT_THROW(createTypeError(globalObject, "Iterator result interface is not an object."_s));
</span><span class="cx"> 
</span><del>-    JSValue result = performLLIntGetByID(pc, codeBlock, globalObject, iteratorReturn, vm.propertyNames->done, metadata.m_doneModeMetadata);
</del><ins>+    JSValue result = performLLIntGetByID(pc, codeBlock, globalObject, iteratorReturn, vm.propertyNames->done, metadata.m_doneModeMetadata, nullptr);
</ins><span class="cx">     LLINT_CHECK_EXCEPTION();
</span><span class="cx">     doneRegister = result;
</span><del>-    bytecode.metadata(codeBlock).m_doneProfile.m_buckets[0] = JSValue::encode(result);
</del><ins>+    bytecode.metadata(codeBlock).m_doneProfile->m_buckets[0] = JSValue::encode(result);
</ins><span class="cx">     LLINT_END();
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -894,10 +895,10 @@
</span><span class="cx">     Register& valueRegister = callFrame->uncheckedR(bytecode.m_value);
</span><span class="cx">     JSValue iteratorReturn = valueRegister.jsValue();
</span><span class="cx"> 
</span><del>-    JSValue result = performLLIntGetByID(pc, codeBlock, globalObject, iteratorReturn, vm.propertyNames->value, metadata.m_valueModeMetadata);
</del><ins>+    JSValue result = performLLIntGetByID(pc, codeBlock, globalObject, iteratorReturn, vm.propertyNames->value, metadata.m_valueModeMetadata, nullptr);
</ins><span class="cx">     LLINT_CHECK_EXCEPTION();
</span><span class="cx">     valueRegister = result;
</span><del>-    bytecode.metadata(codeBlock).m_valueProfile.m_buckets[0] = JSValue::encode(result);
</del><ins>+    bytecode.metadata(codeBlock).m_valueProfile->m_buckets[0] = JSValue::encode(result);
</ins><span class="cx">     LLINT_END();
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -1024,7 +1025,7 @@
</span><span class="cx">     if (std::optional<uint32_t> index = subscript.tryGetAsUint32Index()) {
</span><span class="cx">         uint32_t i = *index;
</span><span class="cx">         auto& metadata = bytecode.metadata(codeBlock);
</span><del>-        ArrayProfile* arrayProfile = &metadata.m_arrayProfile;
</del><ins>+        ArrayProfile* arrayProfile = metadata.m_arrayProfile;
</ins><span class="cx"> 
</span><span class="cx">         if (isJSString(baseValue)) {
</span><span class="cx">             if (asString(baseValue)->canGetIndex(i)) {
</span><span class="lines">@@ -1429,7 +1430,7 @@
</span><span class="cx">     LLINT_BEGIN();
</span><span class="cx">     auto bytecode = pc->as<OpInByVal>();
</span><span class="cx">     auto& metadata = bytecode.metadata(codeBlock);
</span><del>-    LLINT_RETURN(jsBoolean(CommonSlowPaths::opInByVal(globalObject, getOperand(callFrame, bytecode.m_base), getOperand(callFrame, bytecode.m_property), &metadata.m_arrayProfile)));
</del><ins>+    LLINT_RETURN(jsBoolean(CommonSlowPaths::opInByVal(globalObject, getOperand(callFrame, bytecode.m_base), getOperand(callFrame, bytecode.m_property), metadata.m_arrayProfile)));
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> LLINT_SLOW_PATH_DECL(slow_path_has_private_name)
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorellintLowLevelInterpreterasm"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/llint/LowLevelInterpreter.asm (282477 => 282478)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/llint/LowLevelInterpreter.asm        2021-09-15 22:12:01 UTC (rev 282477)
+++ trunk/Source/JavaScriptCore/llint/LowLevelInterpreter.asm   2021-09-15 22:18:52 UTC (rev 282478)
</span><span class="lines">@@ -413,6 +413,11 @@
</span><span class="cx">     muli sizeof %opcode%::Metadata, scratch # scratch *= sizeof(Op::Metadata)
</span><span class="cx">     addi scratch, dst # offset += scratch
</span><span class="cx">     addp metadataTable, dst # return &metadataTable[offset]
</span><ins>+    # roundUpToMultipleOf(alignof(Metadata), dst)
+    const adder = (constexpr (alignof(%opcode%::Metadata))) - 1
+    const mask = ~adder
+    addp adder, dst
+    andp mask, dst
</ins><span class="cx"> end
</span><span class="cx"> 
</span><span class="cx"> macro jumpImpl(dispatchIndirect, targetOffsetReg)
</span><span class="lines">@@ -1287,11 +1292,12 @@
</span><span class="cx">     loadi LLIntReturnPC[cfr], PC
</span><span class="cx"> end
</span><span class="cx"> 
</span><del>-macro arrayProfile(offset, cellAndIndexingType, metadata, scratch)
</del><ins>+macro arrayProfile(offset, cellAndIndexingType, metadata, scratch1, scratch2)
</ins><span class="cx">     const cell = cellAndIndexingType
</span><span class="cx">     const indexingType = cellAndIndexingType 
</span><del>-    loadi JSCell::m_structureID[cell], scratch
-    storei scratch, offset + ArrayProfile::m_lastSeenStructureID[metadata]
</del><ins>+    loadp offset[metadata], scratch2
+    loadi JSCell::m_structureID[cell], scratch1
+    storei scratch1, ArrayProfile::m_lastSeenStructureID[scratch2]
</ins><span class="cx">     loadb JSCell::m_indexingTypeAndMisc[cell], indexingType
</span><span class="cx"> end
</span><span class="cx"> 
</span><span class="lines">@@ -1615,8 +1621,8 @@
</span><span class="cx">     addp -profileArgSkip, t0 # Use addi because that's what has the peephole
</span><span class="cx">     assert(macro (ok) bpgteq t0, 0, ok end)
</span><span class="cx">     btpz t0, .argumentProfileDone
</span><del>-    loadp CodeBlock::m_argumentValueProfiles + FixedVector::m_storage + RefCountedArray::m_data[t1], t3
-    btpz t3, .argumentProfileDone # When we can't JIT, we don't allocate any argument value profiles.
</del><ins>+    loadp CodeBlock::m_unlinkedCode[t1], t3
+    loadp UnlinkedCodeBlock::m_valueProfiles + FixedVector::m_storage + RefCountedArray::m_data[t3], t3
</ins><span class="cx">     mulp sizeof ValueProfile, t0, t2 # Aaaaahhhh! Need strength reduction!
</span><span class="cx">     lshiftp 3, t0 # offset of last JSValue arguments on the stack.
</span><span class="cx">     addp t2, t3 # pointer to end of ValueProfile array in CodeBlock::m_argumentValueProfiles.
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorellintLowLevelInterpreter32_64asm"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/llint/LowLevelInterpreter32_64.asm (282477 => 282478)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/llint/LowLevelInterpreter32_64.asm   2021-09-15 22:12:01 UTC (rev 282477)
+++ trunk/Source/JavaScriptCore/llint/LowLevelInterpreter32_64.asm      2021-09-15 22:18:52 UTC (rev 282478)
</span><span class="lines">@@ -67,7 +67,7 @@
</span><span class="cx">         move payload, t0
</span><span class="cx"> 
</span><span class="cx">         metadata(t5, t2)
</span><del>-        valueProfile(opcodeStruct, m_profile, t5, t1, t0)
</del><ins>+        valueProfile(opcodeStruct, m_profile, t5, t1, t0, t2)
</ins><span class="cx">         get(m_dst, t2)
</span><span class="cx">         storei t1, TagOffset[cfr, t2, 8]
</span><span class="cx">         storei t0, PayloadOffset[cfr, t2, 8]
</span><span class="lines">@@ -85,7 +85,7 @@
</span><span class="cx">     storei r1, TagOffset[cfr, t3, 8]
</span><span class="cx">     storei r0, PayloadOffset[cfr, t3, 8]
</span><span class="cx">     metadata(size, opcodeStruct, t2, t3)
</span><del>-    valueProfile(opcodeStruct, valueProfileName, t2, r1, r0)
</del><ins>+    valueProfile(opcodeStruct, valueProfileName, t2, r1, r0, t3)
</ins><span class="cx">     dispatch()
</span><span class="cx"> 
</span><span class="cx"> end
</span><span class="lines">@@ -677,9 +677,10 @@
</span><span class="cx">         end)
</span><span class="cx"> end
</span><span class="cx"> 
</span><del>-macro valueProfile(opcodeStruct, profileName, metadata, tag, payload)
-    storei tag, %opcodeStruct%::Metadata::%profileName%.m_buckets + TagOffset[metadata]
-    storei payload, %opcodeStruct%::Metadata::%profileName%.m_buckets + PayloadOffset[metadata]
</del><ins>+macro valueProfile(opcodeStruct, profileName, metadata, tag, payload, scratch)
+    loadp %opcodeStruct%::Metadata::%profileName%[metadata], scratch
+    storei tag, ValueProfile::m_buckets + TagOffset[scratch]
+    storei payload, ValueProfile::m_buckets + PayloadOffset[scratch]
</ins><span class="cx"> end
</span><span class="cx"> 
</span><span class="cx"> 
</span><span class="lines">@@ -1437,7 +1438,7 @@
</span><span class="cx">     loadi OpGetByIdDirect::Metadata::m_offset[t5], t2
</span><span class="cx">     bineq JSCell::m_structureID[t3], t1, .opGetByIdDirectSlow
</span><span class="cx">     loadPropertyAtVariableOffset(t2, t3, t0, t1)
</span><del>-    valueProfile(OpGetByIdDirect, m_profile, t5, t0, t1)
</del><ins>+    valueProfile(OpGetByIdDirect, m_profile, t5, t0, t1, t3)
</ins><span class="cx">     return(t0, t1)
</span><span class="cx"> 
</span><span class="cx"> .opGetByIdDirectSlow:
</span><span class="lines">@@ -1458,11 +1459,11 @@
</span><span class="cx">     bineq t0, t1, slowLabel
</span><span class="cx">     loadis %opcodeStruct%::Metadata::%modeMetadataName%.defaultMode.cachedOffset[t2], t1
</span><span class="cx">     loadPropertyAtVariableOffset(t1, t3, t0, t1)
</span><del>-    valueProfile(opcodeStruct, valueProfileName, t2, t0, t1)
</del><ins>+    valueProfile(opcodeStruct, valueProfileName, t2, t0, t1, t3)
</ins><span class="cx">     return(t0, t1)
</span><span class="cx"> 
</span><span class="cx"> .opGetByIdProtoLoad:
</span><del>-    bbneq t1, constexpr GetByIdMode::ProtoLoad, .opGetByIdArrayLength
</del><ins>+    bbneq t1, constexpr GetByIdMode::ProtoLoad, .opGetByIdUnset
</ins><span class="cx">     loadi JSCell::m_structureID[t3], t1
</span><span class="cx">     loadi %opcodeStruct%::Metadata::%modeMetadataName%.protoLoadMode.structureID[t2], t3
</span><span class="cx">     bineq t3, t1, slowLabel
</span><span class="lines">@@ -1469,26 +1470,18 @@
</span><span class="cx">     loadis %opcodeStruct%::Metadata::%modeMetadataName%.protoLoadMode.cachedOffset[t2], t1
</span><span class="cx">     loadp %opcodeStruct%::Metadata::%modeMetadataName%.protoLoadMode.cachedSlot[t2], t3
</span><span class="cx">     loadPropertyAtVariableOffset(t1, t3, t0, t1)
</span><del>-    valueProfile(opcodeStruct, valueProfileName, t2, t0, t1)
</del><ins>+    valueProfile(opcodeStruct, valueProfileName, t2, t0, t1, t3)
</ins><span class="cx">     return(t0, t1)
</span><span class="cx"> 
</span><del>-.opGetByIdArrayLength:
-    bbneq t1, constexpr GetByIdMode::ArrayLength, .opGetByIdUnset
-    move t3, t0
-    arrayProfile(%opcodeStruct%::Metadata::%modeMetadataName%.arrayLengthMode.arrayProfile, t0, t2, t5)
-    btiz t0, IsArray, slowLabel
-    btiz t0, IndexingShapeMask, slowLabel
-    loadp JSObject::m_butterfly[t3], t0
-    loadi -sizeof IndexingHeader + IndexingHeader::u.lengths.publicLength[t0], t0
-    bilt t0, 0, slowLabel
-    valueProfile(opcodeStruct, valueProfileName, t2, Int32Tag, t0)
-    return(Int32Tag, t0)
</del><ins>+# It can't be array length since we don't use this for arbitrary get_by_id's that could
+# access "length". We only use it for iterator opcodes which aren't using "length" as an
+# identifier.
</ins><span class="cx">     
</span><span class="cx"> .opGetByIdUnset:
</span><span class="cx">     loadi JSCell::m_structureID[t3], t1
</span><span class="cx">     loadi %opcodeStruct%::Metadata::%modeMetadataName%.unsetMode.structureID[t2], t0
</span><span class="cx">     bineq t0, t1, slowLabel
</span><del>-    valueProfile(opcodeStruct, valueProfileName, t2, UndefinedTag, 0)
</del><ins>+    valueProfile(opcodeStruct, valueProfileName, t2, UndefinedTag, 0, t3)
</ins><span class="cx">     return(UndefinedTag, 0)
</span><span class="cx"> 
</span><span class="cx"> end
</span><span class="lines">@@ -1506,7 +1499,7 @@
</span><span class="cx">     bineq JSCell::m_structureID[t3], t1, .opGetByIdSlow
</span><span class="cx">     loadp OpGetById::Metadata::m_modeMetadata.protoLoadMode.cachedSlot[t5], t3
</span><span class="cx">     loadPropertyAtVariableOffset(t2, t3, t0, t1)
</span><del>-    valueProfile(OpGetById, m_profile, t5, t0, t1)
</del><ins>+    valueProfile(OpGetById, m_profile, t5, t0, t1, t3)
</ins><span class="cx">     return(t0, t1)
</span><span class="cx"> 
</span><span class="cx"> .opGetByIdArrayLength:
</span><span class="lines">@@ -1513,13 +1506,13 @@
</span><span class="cx">     bbneq t1, constexpr GetByIdMode::ArrayLength, .opGetByIdUnset
</span><span class="cx">     loadConstantOrVariablePayload(size, t0, CellTag, t3, .opGetByIdSlow)
</span><span class="cx">     move t3, t2
</span><del>-    arrayProfile(OpGetById::Metadata::m_modeMetadata.arrayLengthMode.arrayProfile, t2, t5, t0)
</del><ins>+    arrayProfile(OpGetById::Metadata::m_arrayProfile, t2, t5, t0, t1)
</ins><span class="cx">     btiz t2, IsArray, .opGetByIdSlow
</span><span class="cx">     btiz t2, IndexingShapeMask, .opGetByIdSlow
</span><span class="cx">     loadp JSObject::m_butterfly[t3], t0
</span><span class="cx">     loadi -sizeof IndexingHeader + IndexingHeader::u.lengths.publicLength[t0], t0
</span><span class="cx">     bilt t0, 0, .opGetByIdSlow
</span><del>-    valueProfile(OpGetById, m_profile, t5, Int32Tag, t0)
</del><ins>+    valueProfile(OpGetById, m_profile, t5, Int32Tag, t0, t3)
</ins><span class="cx">     return(Int32Tag, t0)
</span><span class="cx"> 
</span><span class="cx"> .opGetByIdUnset:
</span><span class="lines">@@ -1527,7 +1520,7 @@
</span><span class="cx">     loadi OpGetById::Metadata::m_modeMetadata.unsetMode.structureID[t5], t1
</span><span class="cx">     loadConstantOrVariablePayload(size, t0, CellTag, t3, .opGetByIdSlow)
</span><span class="cx">     bineq JSCell::m_structureID[t3], t1, .opGetByIdSlow
</span><del>-    valueProfile(OpGetById, m_profile, t5, UndefinedTag, 0)
</del><ins>+    valueProfile(OpGetById, m_profile, t5, UndefinedTag, 0, t3)
</ins><span class="cx">     return(UndefinedTag, 0)
</span><span class="cx"> 
</span><span class="cx"> .opGetByIdDefault:
</span><span class="lines">@@ -1536,7 +1529,7 @@
</span><span class="cx">     loadis OpGetById::Metadata::m_modeMetadata.defaultMode.cachedOffset[t5], t2
</span><span class="cx">     bineq JSCell::m_structureID[t3], t1, .opGetByIdSlow
</span><span class="cx">     loadPropertyAtVariableOffset(t2, t3, t0, t1)
</span><del>-    valueProfile(OpGetById, m_profile, t5, t0, t1)
</del><ins>+    valueProfile(OpGetById, m_profile, t5, t0, t1, t3)
</ins><span class="cx">     return(t0, t1)
</span><span class="cx"> 
</span><span class="cx"> .opGetByIdSlow:
</span><span class="lines">@@ -1546,7 +1539,7 @@
</span><span class="cx"> .osrReturnPoint:
</span><span class="cx">     getterSetterOSRExitReturnPoint(op_get_by_id, size)
</span><span class="cx">     metadata(t2, t3)
</span><del>-    valueProfile(OpGetById, m_profile, t2, r1, r0)
</del><ins>+    valueProfile(OpGetById, m_profile, t2, r1, r0, t3)
</ins><span class="cx">     return(r1, r0)
</span><span class="cx"> 
</span><span class="cx"> end)
</span><span class="lines">@@ -1624,7 +1617,7 @@
</span><span class="cx">         get(m_dst, scratch)
</span><span class="cx">         storei Int32Tag, TagOffset[cfr, scratch, 8]
</span><span class="cx">         storei resultPayload, PayloadOffset[cfr, scratch, 8]
</span><del>-        valueProfile(OpGetByVal, m_profile, t5, Int32Tag, resultPayload)
</del><ins>+        valueProfile(OpGetByVal, m_profile, t5, Int32Tag, resultPayload, scratch)
</ins><span class="cx">         dispatch()
</span><span class="cx">     end
</span><span class="cx"> 
</span><span class="lines">@@ -1633,7 +1626,7 @@
</span><span class="cx">         fd2ii result, scratch2, scratch3
</span><span class="cx">         storei scratch3, TagOffset[cfr, scratch1, 8]
</span><span class="cx">         storei scratch2, PayloadOffset[cfr, scratch1, 8]
</span><del>-        valueProfile(OpGetByVal, m_profile, t5, scratch3, scratch2)
</del><ins>+        valueProfile(OpGetByVal, m_profile, t5, scratch3, scratch2, scratch1)
</ins><span class="cx">         dispatch()
</span><span class="cx">     end
</span><span class="cx"> 
</span><span class="lines">@@ -1641,7 +1634,7 @@
</span><span class="cx">     get(m_base, t2)
</span><span class="cx">     loadConstantOrVariablePayload(size, t2, CellTag, t0, .opGetByValSlow)
</span><span class="cx">     move t0, t2
</span><del>-    arrayProfile(OpGetByVal::Metadata::m_arrayProfile, t2, t5, t1)
</del><ins>+    arrayProfile(OpGetByVal::Metadata::m_arrayProfile, t2, t5, t1, t3)
</ins><span class="cx">     get(m_property, t3)
</span><span class="cx">     loadConstantOrVariablePayload(size, t3, Int32Tag, t1, .opGetByValSlow)
</span><span class="cx">     loadp JSObject::m_butterfly[t0], t3
</span><span class="lines">@@ -1678,7 +1671,7 @@
</span><span class="cx"> .opGetByValNotEmpty:
</span><span class="cx">     storei t2, TagOffset[cfr, t0, 8]
</span><span class="cx">     storei t1, PayloadOffset[cfr, t0, 8]
</span><del>-    valueProfile(OpGetByVal, m_profile, t5, t2, t1)
</del><ins>+    valueProfile(OpGetByVal, m_profile, t5, t2, t1, t3)
</ins><span class="cx">     dispatch()
</span><span class="cx"> 
</span><span class="cx"> .opGetByValNotIndexedStorage:
</span><span class="lines">@@ -1691,7 +1684,7 @@
</span><span class="cx"> .osrReturnPoint:
</span><span class="cx">     getterSetterOSRExitReturnPoint(op_get_by_val, size)
</span><span class="cx">     metadata(t2, t3)
</span><del>-    valueProfile(OpGetByVal, m_profile, t2, r1, r0)
</del><ins>+    valueProfile(OpGetByVal, m_profile, t2, r1, r0, t3)
</ins><span class="cx">     return(r1, r0)
</span><span class="cx"> 
</span><span class="cx"> end)
</span><span class="lines">@@ -1712,7 +1705,7 @@
</span><span class="cx">     bineq JSCell::m_structureID[t3], t1, .opGetPrivateNameSlow
</span><span class="cx"> 
</span><span class="cx">     loadPropertyAtVariableOffset(t2, t3, t0, t1)
</span><del>-    valueProfile(OpGetPrivateName, m_profile, t5, t0, t1)
</del><ins>+    valueProfile(OpGetPrivateName, m_profile, t5, t0, t1, t3)
</ins><span class="cx">     return(t0, t1)
</span><span class="cx"> 
</span><span class="cx"> .opGetPrivateNameSlow:
</span><span class="lines">@@ -1774,7 +1767,8 @@
</span><span class="cx"> 
</span><span class="cx">         .outOfBounds:
</span><span class="cx">             biaeq t3, -sizeof IndexingHeader + IndexingHeader::u.lengths.vectorLength[t0], .opPutByValOutOfBounds
</span><del>-            storeb 1, %opcodeStruct%::Metadata::m_arrayProfile.m_mayStoreToHole[t5]
</del><ins>+            loadp %opcodeStruct%::Metadata::m_arrayProfile[t5], t2
+            storeb 1, ArrayProfile::m_mayStoreToHole[t2]
</ins><span class="cx">             addi 1, t3, t2
</span><span class="cx">             storei t2, -sizeof IndexingHeader + IndexingHeader::u.lengths.publicLength[t0]
</span><span class="cx">             jmp .storeResult
</span><span class="lines">@@ -1785,7 +1779,7 @@
</span><span class="cx">         get(m_base, t0)
</span><span class="cx">         loadConstantOrVariablePayload(size, t0, CellTag, t1, .opPutByValSlow)
</span><span class="cx">         move t1, t2
</span><del>-        arrayProfile(%opcodeStruct%::Metadata::m_arrayProfile, t2, t5, t0)
</del><ins>+        arrayProfile(%opcodeStruct%::Metadata::m_arrayProfile, t2, t5, t0, t3)
</ins><span class="cx">         get(m_property, t0)
</span><span class="cx">         loadConstantOrVariablePayload(size, t0, Int32Tag, t3, .opPutByValSlow)
</span><span class="cx">         loadp JSObject::m_butterfly[t1], t0
</span><span class="lines">@@ -1839,7 +1833,8 @@
</span><span class="cx">         dispatch()
</span><span class="cx"> 
</span><span class="cx">     .opPutByValArrayStorageEmpty:
</span><del>-        storeb 1, %opcodeStruct%::Metadata::m_arrayProfile.m_mayStoreToHole[t5]
</del><ins>+        loadp %opcodeStruct%::Metadata::m_arrayProfile[t5], t1
+        storeb 1, ArrayProfile::m_mayStoreToHole[t1]
</ins><span class="cx">         addi 1, ArrayStorage::m_numValuesInVector[t0]
</span><span class="cx">         bib t3, -sizeof IndexingHeader + IndexingHeader::u.lengths.publicLength[t0], .opPutByValArrayStorageStoreResult
</span><span class="cx">         addi 1, t3, t1
</span><span class="lines">@@ -1847,7 +1842,8 @@
</span><span class="cx">         jmp .opPutByValArrayStorageStoreResult
</span><span class="cx"> 
</span><span class="cx">     .opPutByValOutOfBounds:
</span><del>-        storeb 1, %opcodeStruct%::Metadata::m_arrayProfile.m_outOfBounds[t5]
</del><ins>+        loadp %opcodeStruct%::Metadata::m_arrayProfile[t5], t1
+        storeb 1, ArrayProfile::m_outOfBounds[t1]
</ins><span class="cx">     .opPutByValSlow:
</span><span class="cx">         callSlowPath(_llint_slow_path_%opcodeName%)
</span><span class="cx">         dispatch()
</span><span class="lines">@@ -2515,7 +2511,7 @@
</span><span class="cx">     macro getProperty()
</span><span class="cx">         loadp OpGetFromScope::Metadata::m_operand[t5], t3
</span><span class="cx">         loadPropertyAtVariableOffset(t3, t0, t1, t2)
</span><del>-        valueProfile(OpGetFromScope, m_profile, t5, t1, t2)
</del><ins>+        valueProfile(OpGetFromScope, m_profile, t5, t1, t2, t3)
</ins><span class="cx">         return(t1, t2)
</span><span class="cx">     end
</span><span class="cx"> 
</span><span class="lines">@@ -2524,7 +2520,7 @@
</span><span class="cx">         loadp TagOffset[t0], t1
</span><span class="cx">         loadp PayloadOffset[t0], t2
</span><span class="cx">         tdzCheckIfNecessary(t1)
</span><del>-        valueProfile(OpGetFromScope, m_profile, t5, t1, t2)
</del><ins>+        valueProfile(OpGetFromScope, m_profile, t5, t1, t2, t3)
</ins><span class="cx">         return(t1, t2)
</span><span class="cx">     end
</span><span class="cx"> 
</span><span class="lines">@@ -2532,7 +2528,7 @@
</span><span class="cx">         loadp OpGetFromScope::Metadata::m_operand[t5], t3
</span><span class="cx">         loadp JSLexicalEnvironment_variables + TagOffset[t0, t3, 8], t1
</span><span class="cx">         loadp JSLexicalEnvironment_variables + PayloadOffset[t0, t3, 8], t2
</span><del>-        valueProfile(OpGetFromScope, m_profile, t5, t1, t2)
</del><ins>+        valueProfile(OpGetFromScope, m_profile, t5, t1, t2, t3)
</ins><span class="cx">         return(t1, t2)
</span><span class="cx">     end
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorellintLowLevelInterpreter64asm"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/llint/LowLevelInterpreter64.asm (282477 => 282478)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/llint/LowLevelInterpreter64.asm      2021-09-15 22:12:01 UTC (rev 282477)
+++ trunk/Source/JavaScriptCore/llint/LowLevelInterpreter64.asm 2021-09-15 22:18:52 UTC (rev 282478)
</span><span class="lines">@@ -68,7 +68,7 @@
</span><span class="cx">     fn(macro (value)
</span><span class="cx">         move value, t3
</span><span class="cx">         metadata(t1, t2)
</span><del>-        valueProfile(opcodeStruct, m_profile, t1, t3)
</del><ins>+        valueProfile(opcodeStruct, m_profile, t1, t3, t2)
</ins><span class="cx">         get(m_dst, t1)
</span><span class="cx">         storeq t3, [cfr, t1, 8]
</span><span class="cx">         dispatch()
</span><span class="lines">@@ -75,8 +75,9 @@
</span><span class="cx">     end)
</span><span class="cx"> end
</span><span class="cx"> 
</span><del>-macro valueProfile(opcodeStruct, profileName, metadata, value)
-    storeq value, %opcodeStruct%::Metadata::%profileName%.m_buckets[metadata]
</del><ins>+macro valueProfile(opcodeStruct, profileName, metadata, value, scratch)
+    loadp %opcodeStruct%::Metadata::%profileName%[metadata], scratch
+    storeq value, ValueProfile::m_buckets[scratch]
</ins><span class="cx"> end
</span><span class="cx"> 
</span><span class="cx"> # After calling, calling bytecode is claiming input registers are not used.
</span><span class="lines">@@ -87,7 +88,7 @@
</span><span class="cx">     get(size, opcodeStruct, dstVirtualRegister, t1)
</span><span class="cx">     storeq r0, [cfr, t1, 8]
</span><span class="cx">     metadata(size, opcodeStruct, t2, t1)
</span><del>-    valueProfile(opcodeStruct, valueProfileName, t2, r0)
</del><ins>+    valueProfile(opcodeStruct, valueProfileName, t2, r0, t3)
</ins><span class="cx">     dispatch()
</span><span class="cx"> end
</span><span class="cx"> 
</span><span class="lines">@@ -1509,7 +1510,7 @@
</span><span class="cx">     bineq t0, t1, .opGetByIdDirectSlow
</span><span class="cx">     loadi OpGetByIdDirect::Metadata::m_offset[t2], t1
</span><span class="cx">     loadPropertyAtVariableOffset(t1, t3, t0)
</span><del>-    valueProfile(OpGetByIdDirect, m_profile, t2, t0)
</del><ins>+    valueProfile(OpGetByIdDirect, m_profile, t2, t0, t1)
</ins><span class="cx">     return(t0)
</span><span class="cx"> 
</span><span class="cx"> .opGetByIdDirectSlow:
</span><span class="lines">@@ -1518,7 +1519,7 @@
</span><span class="cx"> end)
</span><span class="cx"> 
</span><span class="cx"> # The base object is expected in t3
</span><del>-macro performGetByIDHelper(opcodeStruct, modeMetadataName, valueProfileName, slowLabel, size, metadata, return)
</del><ins>+macro performGetByIDHelper(opcodeStruct, modeMetadataName, valueProfileName, slowLabel, size, metadata, return, doArrayProfile)
</ins><span class="cx">     metadata(t2, t1)
</span><span class="cx">     loadb %opcodeStruct%::Metadata::%modeMetadataName%.mode[t2], t1
</span><span class="cx"> 
</span><span class="lines">@@ -1529,7 +1530,7 @@
</span><span class="cx">     bineq t0, t1, slowLabel
</span><span class="cx">     loadis %opcodeStruct%::Metadata::%modeMetadataName%.defaultMode.cachedOffset[t2], t1
</span><span class="cx">     loadPropertyAtVariableOffset(t1, t3, t0)
</span><del>-    valueProfile(opcodeStruct, valueProfileName, t2, t0)
</del><ins>+    valueProfile(opcodeStruct, valueProfileName, t2, t0, t1)
</ins><span class="cx">     return(t0)
</span><span class="cx"> 
</span><span class="cx"> .opGetByIdProtoLoad:
</span><span class="lines">@@ -1540,13 +1541,13 @@
</span><span class="cx">     loadis %opcodeStruct%::Metadata::%modeMetadataName%.protoLoadMode.cachedOffset[t2], t1
</span><span class="cx">     loadp %opcodeStruct%::Metadata::%modeMetadataName%.protoLoadMode.cachedSlot[t2], t3
</span><span class="cx">     loadPropertyAtVariableOffset(t1, t3, t0)
</span><del>-    valueProfile(opcodeStruct, valueProfileName, t2, t0)
</del><ins>+    valueProfile(opcodeStruct, valueProfileName, t2, t0, t1)
</ins><span class="cx">     return(t0)
</span><span class="cx"> 
</span><span class="cx"> .opGetByIdArrayLength:
</span><span class="cx">     bbneq t1, constexpr GetByIdMode::ArrayLength, .opGetByIdUnset
</span><span class="cx">     move t3, t0
</span><del>-    arrayProfile(%opcodeStruct%::Metadata::%modeMetadataName%.arrayLengthMode.arrayProfile, t0, t2, t5)
</del><ins>+    doArrayProfile(t0, t2, t5, t1)
</ins><span class="cx">     btiz t0, IsArray, slowLabel
</span><span class="cx">     btiz t0, IndexingShapeMask, slowLabel
</span><span class="cx">     loadCagedJSValue(JSObject::m_butterfly[t3], t0, t1)
</span><span class="lines">@@ -1553,7 +1554,7 @@
</span><span class="cx">     loadi -sizeof IndexingHeader + IndexingHeader::u.lengths.publicLength[t0], t0
</span><span class="cx">     bilt t0, 0, slowLabel
</span><span class="cx">     orq numberTag, t0
</span><del>-    valueProfile(opcodeStruct, valueProfileName, t2, t0)
</del><ins>+    valueProfile(opcodeStruct, valueProfileName, t2, t0, t1)
</ins><span class="cx">     return(t0)
</span><span class="cx"> 
</span><span class="cx"> .opGetByIdUnset:
</span><span class="lines">@@ -1560,7 +1561,7 @@
</span><span class="cx">     loadi JSCell::m_structureID[t3], t1
</span><span class="cx">     loadi %opcodeStruct%::Metadata::%modeMetadataName%.unsetMode.structureID[t2], t0
</span><span class="cx">     bineq t0, t1, slowLabel
</span><del>-    valueProfile(opcodeStruct, valueProfileName, t2, ValueUndefined)
</del><ins>+    valueProfile(opcodeStruct, valueProfileName, t2, ValueUndefined, t1)
</ins><span class="cx">     return(ValueUndefined)
</span><span class="cx"> 
</span><span class="cx"> end
</span><span class="lines">@@ -1568,7 +1569,10 @@
</span><span class="cx"> llintOpWithMetadata(op_get_by_id, OpGetById, macro (size, get, dispatch, metadata, return)
</span><span class="cx">     get(m_base, t0)
</span><span class="cx">     loadConstantOrVariableCell(size, t0, t3, .opGetByIdSlow)
</span><del>-    performGetByIDHelper(OpGetById, m_modeMetadata, m_profile, .opGetByIdSlow, size, metadata, return)
</del><ins>+    performGetByIDHelper(OpGetById, m_modeMetadata, m_profile, .opGetByIdSlow, size, metadata, return,
+        macro (cellAndIndexingType, metadata, scratch1, scratch2)
+            arrayProfile(OpGetById::Metadata::m_arrayProfile, cellAndIndexingType, metadata, scratch1, scratch2)
+        end)
</ins><span class="cx"> 
</span><span class="cx"> .opGetByIdSlow:
</span><span class="cx">     callSlowPath(_llint_slow_path_get_by_id)
</span><span class="lines">@@ -1577,7 +1581,7 @@
</span><span class="cx"> .osrReturnPoint:
</span><span class="cx">     getterSetterOSRExitReturnPoint(op_get_by_id, size)
</span><span class="cx">     metadata(t2, t3)
</span><del>-    valueProfile(OpGetById, m_profile, t2, r0)
</del><ins>+    valueProfile(OpGetById, m_profile, t2, r0, t3)
</ins><span class="cx">     return(r0)
</span><span class="cx"> 
</span><span class="cx"> end)
</span><span class="lines">@@ -1698,7 +1702,7 @@
</span><span class="cx">     macro finishGetByVal(result, scratch)
</span><span class="cx">         get(m_dst, scratch)
</span><span class="cx">         storeq result, [cfr, scratch, 8]
</span><del>-        valueProfile(OpGetByVal, m_profile, t5, result)
</del><ins>+        valueProfile(OpGetByVal, m_profile, t5, result, scratch)
</ins><span class="cx">         dispatch()
</span><span class="cx">     end
</span><span class="cx"> 
</span><span class="lines">@@ -1719,7 +1723,7 @@
</span><span class="cx">     loadConstantOrVariableCell(size, t2, t0, .opGetByValSlow)
</span><span class="cx"> 
</span><span class="cx">     move t0, t2
</span><del>-    arrayProfile(OpGetByVal::Metadata::m_arrayProfile, t2, t5, t1)
</del><ins>+    arrayProfile(OpGetByVal::Metadata::m_arrayProfile, t2, t5, t1, t3)
</ins><span class="cx"> 
</span><span class="cx">     get(m_property, t3)
</span><span class="cx">     loadConstantOrVariableInt32(size, t3, t1, .opGetByValSlow)
</span><span class="lines">@@ -1759,7 +1763,7 @@
</span><span class="cx"> 
</span><span class="cx"> .opGetByValDone:
</span><span class="cx">     storeq t2, [cfr, t0, 8]
</span><del>-    valueProfile(OpGetByVal, m_profile, t5, t2)
</del><ins>+    valueProfile(OpGetByVal, m_profile, t5, t2, t3)
</ins><span class="cx">     dispatch()
</span><span class="cx"> 
</span><span class="cx"> .opGetByValNotIndexedStorage:
</span><span class="lines">@@ -1772,7 +1776,7 @@
</span><span class="cx"> .osrReturnPoint:
</span><span class="cx">     getterSetterOSRExitReturnPoint(op_get_by_val, size)
</span><span class="cx">     metadata(t5, t2)
</span><del>-    valueProfile(OpGetByVal, m_profile, t5, r0)
</del><ins>+    valueProfile(OpGetByVal, m_profile, t5, r0, t3)
</ins><span class="cx">     return(r0)
</span><span class="cx"> 
</span><span class="cx"> end)
</span><span class="lines">@@ -1794,7 +1798,7 @@
</span><span class="cx"> 
</span><span class="cx">     loadi OpGetPrivateName::Metadata::m_offset[t2], t1
</span><span class="cx">     loadPropertyAtVariableOffset(t1, t3, t0)
</span><del>-    valueProfile(OpGetPrivateName, m_profile, t2, t0)
</del><ins>+    valueProfile(OpGetPrivateName, m_profile, t2, t0, t3)
</ins><span class="cx">     return(t0)
</span><span class="cx"> 
</span><span class="cx"> .opGetPrivateNameSlow:
</span><span class="lines">@@ -1897,7 +1901,8 @@
</span><span class="cx"> 
</span><span class="cx">         .outOfBounds:
</span><span class="cx">             biaeq t3, -sizeof IndexingHeader + IndexingHeader::u.lengths.vectorLength[t0], .opPutByValOutOfBounds
</span><del>-            storeb 1, %opcodeStruct%::Metadata::m_arrayProfile.m_mayStoreToHole[t5]
</del><ins>+            loadp %opcodeStruct%::Metadata::m_arrayProfile[t5], t2
+            storeb 1, ArrayProfile::m_mayStoreToHole[t2]
</ins><span class="cx">             addi 1, t3, t2
</span><span class="cx">             storei t2, -sizeof IndexingHeader + IndexingHeader::u.lengths.publicLength[t0]
</span><span class="cx">             jmp .storeResult
</span><span class="lines">@@ -1907,7 +1912,7 @@
</span><span class="cx">         loadConstantOrVariableCell(size, t0, t1, .opPutByValSlow)
</span><span class="cx">         move t1, t2
</span><span class="cx">         metadata(t5, t0)
</span><del>-        arrayProfile(%opcodeStruct%::Metadata::m_arrayProfile, t2, t5, t0)
</del><ins>+        arrayProfile(%opcodeStruct%::Metadata::m_arrayProfile, t2, t5, t0, t3)
</ins><span class="cx">         get(m_property, t0)
</span><span class="cx">         loadConstantOrVariableInt32(size, t0, t3, .opPutByValSlow)
</span><span class="cx">         sxi2q t3, t3
</span><span class="lines">@@ -1962,7 +1967,8 @@
</span><span class="cx">         dispatch()
</span><span class="cx"> 
</span><span class="cx">     .opPutByValArrayStorageEmpty:
</span><del>-        storeb 1, %opcodeStruct%::Metadata::m_arrayProfile.m_mayStoreToHole[t5]
</del><ins>+        loadp %opcodeStruct%::Metadata::m_arrayProfile[t5], t1
+        storeb 1, ArrayProfile::m_mayStoreToHole[t1]
</ins><span class="cx">         addi 1, ArrayStorage::m_numValuesInVector[t0]
</span><span class="cx">         bib t3, -sizeof IndexingHeader + IndexingHeader::u.lengths.publicLength[t0], .opPutByValArrayStorageStoreResult
</span><span class="cx">         addi 1, t3, t1
</span><span class="lines">@@ -1970,7 +1976,8 @@
</span><span class="cx">         jmp .opPutByValArrayStorageStoreResult
</span><span class="cx"> 
</span><span class="cx">     .opPutByValOutOfBounds:
</span><del>-        storeb 1, %opcodeStruct%::Metadata::m_arrayProfile.m_outOfBounds[t5]
</del><ins>+        loadp %opcodeStruct%::Metadata::m_arrayProfile[t5], t1
+        storeb 1, ArrayProfile::m_outOfBounds[t1]
</ins><span class="cx">     .opPutByValSlow:
</span><span class="cx">         callSlowPath(_llint_slow_path_%opcodeName%)
</span><span class="cx">         dispatch()
</span><span class="lines">@@ -2662,7 +2669,7 @@
</span><span class="cx">     macro getProperty()
</span><span class="cx">         loadp OpGetFromScope::Metadata::m_operand[t5], t1
</span><span class="cx">         loadPropertyAtVariableOffset(t1, t0, t2)
</span><del>-        valueProfile(OpGetFromScope, m_profile, t5, t2)
</del><ins>+        valueProfile(OpGetFromScope, m_profile, t5, t2, t3)
</ins><span class="cx">         return(t2)
</span><span class="cx">     end
</span><span class="cx"> 
</span><span class="lines">@@ -2670,7 +2677,7 @@
</span><span class="cx">         loadp OpGetFromScope::Metadata::m_operand[t5], t0
</span><span class="cx">         loadq [t0], t0
</span><span class="cx">         tdzCheckIfNecessary(t0)
</span><del>-        valueProfile(OpGetFromScope, m_profile, t5, t0)
</del><ins>+        valueProfile(OpGetFromScope, m_profile, t5, t0, t3)
</ins><span class="cx">         return(t0)
</span><span class="cx">     end
</span><span class="cx"> 
</span><span class="lines">@@ -2677,7 +2684,7 @@
</span><span class="cx">     macro getClosureVar()
</span><span class="cx">         loadp OpGetFromScope::Metadata::m_operand[t5], t1
</span><span class="cx">         loadq JSLexicalEnvironment_variables[t0, t1, 8], t0
</span><del>-        valueProfile(OpGetFromScope, m_profile, t5, t0)
</del><ins>+        valueProfile(OpGetFromScope, m_profile, t5, t0, t3)
</ins><span class="cx">         return(t0)
</span><span class="cx">     end
</span><span class="cx"> 
</span><span class="lines">@@ -3002,7 +3009,7 @@
</span><span class="cx"> 
</span><span class="cx">     loadVariable(get, m_iterator, t3)
</span><span class="cx">     btqnz t3, notCellMask, .iteratorOpenGenericGetNextSlow
</span><del>-    performGetByIDHelper(OpIteratorOpen, m_modeMetadata, m_nextProfile, .iteratorOpenGenericGetNextSlow, size, metadata, storeNextAndDispatch)
</del><ins>+    performGetByIDHelper(OpIteratorOpen, m_modeMetadata, m_nextProfile, .iteratorOpenGenericGetNextSlow, size, metadata, storeNextAndDispatch, macro(a, b, c, d) end)
</ins><span class="cx"> 
</span><span class="cx"> .iteratorOpenGenericGetNextSlow:
</span><span class="cx">     callSlowPath(_llint_slow_path_iterator_open_get_next)
</span><span class="lines">@@ -3061,7 +3068,7 @@
</span><span class="cx"> 
</span><span class="cx">     loadVariable(get, m_value, t3)
</span><span class="cx">     btqnz t3, notCellMask, .getDoneSlow
</span><del>-    performGetByIDHelper(OpIteratorNext, m_doneModeMetadata, m_doneProfile, .getDoneSlow, size, metadata, storeDoneAndJmpToGetValue)
</del><ins>+    performGetByIDHelper(OpIteratorNext, m_doneModeMetadata, m_doneProfile, .getDoneSlow, size, metadata, storeDoneAndJmpToGetValue, macro(a, b, c, d) end)
</ins><span class="cx"> 
</span><span class="cx"> .getDoneSlow:
</span><span class="cx">     callSlowPath(_llint_slow_path_iterator_next_get_done)
</span><span class="lines">@@ -3086,7 +3093,7 @@
</span><span class="cx">     # Reload the next result tmp since the get_by_id above may have clobbered t3.
</span><span class="cx">     loadVariable(get, m_value, t3)
</span><span class="cx">     # We don't need to check if the iterator result is a cell here since we will have thrown an error before.
</span><del>-    performGetByIDHelper(OpIteratorNext, m_valueModeMetadata, m_valueProfile, .getValueSlow, size, metadata, storeValueAndDispatch)
</del><ins>+    performGetByIDHelper(OpIteratorNext, m_valueModeMetadata, m_valueProfile, .getValueSlow, size, metadata, storeValueAndDispatch, macro(a, b, c, d) end)
</ins><span class="cx"> 
</span><span class="cx"> .getValueSlow:
</span><span class="cx">     callSlowPath(_llint_slow_path_iterator_next_get_value)
</span><span class="lines">@@ -3183,7 +3190,7 @@
</span><span class="cx">     loadq constexpr ((offsetInButterfly(firstOutOfLineOffset)) * sizeof(EncodedJSValue))[t0, t2, 8], t2
</span><span class="cx"> 
</span><span class="cx"> .done:
</span><del>-    valueProfile(OpEnumeratorGetByVal, m_profile, t5, t2)
</del><ins>+    valueProfile(OpEnumeratorGetByVal, m_profile, t5, t2, t3)
</ins><span class="cx">     return(t2)
</span><span class="cx"> 
</span><span class="cx"> .getSlowPath:
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreprofilerProfilerBytecodeSequencecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/profiler/ProfilerBytecodeSequence.cpp (282477 => 282478)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/profiler/ProfilerBytecodeSequence.cpp        2021-09-15 22:12:01 UTC (rev 282477)
+++ trunk/Source/JavaScriptCore/profiler/ProfilerBytecodeSequence.cpp   2021-09-15 22:18:52 UTC (rev 282478)
</span><span class="lines">@@ -37,8 +37,7 @@
</span><span class="cx">     StringPrintStream out;
</span><span class="cx">     
</span><span class="cx">     for (unsigned i = 0; i < codeBlock->numberOfArgumentValueProfiles(); ++i) {
</span><del>-        ConcurrentJSLocker locker(codeBlock->m_lock);
-        CString description = codeBlock->valueProfileForArgument(i).briefDescription(locker);
</del><ins>+        CString description = codeBlock->valueProfileForArgument(i).briefDescription();
</ins><span class="cx">         if (!description.length())
</span><span class="cx">             continue;
</span><span class="cx">         out.reset();
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeCachedTypescpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/CachedTypes.cpp (282477 => 282478)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/CachedTypes.cpp      2021-09-15 22:12:01 UTC (rev 282477)
+++ trunk/Source/JavaScriptCore/runtime/CachedTypes.cpp 2021-09-15 22:18:52 UTC (rev 282478)
</span><span class="lines">@@ -1916,6 +1916,9 @@
</span><span class="cx"> 
</span><span class="cx">     UnlinkedCodeBlock::RareData* rareData(Decoder& decoder) const { return m_rareData.decode(decoder); }
</span><span class="cx"> 
</span><ins>+    unsigned numValueProfiles() const { return m_numValueProfiles; }
+    unsigned numArrayProfiles() const { return m_numArrayProfiles; }
+
</ins><span class="cx"> private:
</span><span class="cx">     VirtualRegister m_thisRegister;
</span><span class="cx">     VirtualRegister m_scopeRegister;
</span><span class="lines">@@ -1947,6 +1950,9 @@
</span><span class="cx">     int m_numCalleeLocals;
</span><span class="cx">     int m_numParameters;
</span><span class="cx"> 
</span><ins>+    unsigned m_numValueProfiles;
+    unsigned m_numArrayProfiles;
+
</ins><span class="cx">     CachedMetadataTable m_metadata;
</span><span class="cx"> 
</span><span class="cx">     CachedPtr<CachedCodeBlockRareData> m_rareData;
</span><span class="lines">@@ -2152,6 +2158,8 @@
</span><span class="cx">     , m_metadata(cachedCodeBlock.metadata(decoder))
</span><span class="cx">     , m_instructions(cachedCodeBlock.instructions(decoder))
</span><span class="cx"> 
</span><ins>+    , m_valueProfiles(cachedCodeBlock.numValueProfiles())
+    , m_arrayProfiles(cachedCodeBlock.numArrayProfiles())
</ins><span class="cx">     , m_rareData(cachedCodeBlock.rareData(decoder))
</span><span class="cx"> {
</span><span class="cx"> }
</span><span class="lines">@@ -2322,6 +2330,8 @@
</span><span class="cx">     m_numVars = codeBlock.m_numVars;
</span><span class="cx">     m_numCalleeLocals = codeBlock.m_numCalleeLocals;
</span><span class="cx">     m_numParameters = codeBlock.m_numParameters;
</span><ins>+    m_numValueProfiles = codeBlock.m_valueProfiles.size();
+    m_numArrayProfiles = codeBlock.m_arrayProfiles.size();
</ins><span class="cx">     m_features = codeBlock.m_features;
</span><span class="cx">     m_lexicalScopeFeatures = codeBlock.m_lexicalScopeFeatures;
</span><span class="cx">     m_parseMode = codeBlock.m_parseMode;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeCommonSlowPathscpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/CommonSlowPaths.cpp (282477 => 282478)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/CommonSlowPaths.cpp  2021-09-15 22:12:01 UTC (rev 282477)
+++ trunk/Source/JavaScriptCore/runtime/CommonSlowPaths.cpp     2021-09-15 22:18:52 UTC (rev 282478)
</span><span class="lines">@@ -139,7 +139,7 @@
</span><span class="cx">     PROFILE_VALUE_IN(value__, m_profile)
</span><span class="cx"> 
</span><span class="cx"> #define PROFILE_VALUE_IN(value, profileName) do { \
</span><del>-        bytecode.metadata(codeBlock).profileName.m_buckets[0] = JSValue::encode(value); \
</del><ins>+        bytecode.metadata(codeBlock).profileName->m_buckets[0] = JSValue::encode(value); \
</ins><span class="cx">     } while (false)
</span><span class="cx"> 
</span><span class="cx"> static void throwArityCheckStackOverflowError(JSGlobalObject* globalObject, ThrowScope& scope)
</span><span class="lines">@@ -887,7 +887,7 @@
</span><span class="cx">     JSCell* iterable = GET(bytecode.m_iterable).jsValue().asCell();
</span><span class="cx">     if (auto arrayIterator = jsDynamicCast<JSArrayIterator*>(vm, iterator)) {
</span><span class="cx">         if (auto array = jsDynamicCast<JSArray*>(vm, iterable)) {
</span><del>-            metadata.m_iterableProfile.observeStructureID(array->structureID());
</del><ins>+            metadata.m_iterableProfile->observeStructureID(array->structureID());
</ins><span class="cx"> 
</span><span class="cx">             metadata.m_iterationMetadata.seenModes = metadata.m_iterationMetadata.seenModes | IterationMode::FastArray;
</span><span class="cx">             auto& indexSlot = arrayIterator->internalField(JSArrayIterator::Field::Index);
</span><span class="lines">@@ -951,7 +951,9 @@
</span><span class="cx"> JSC_DEFINE_COMMON_SLOW_PATH(slow_path_enter)
</span><span class="cx"> {
</span><span class="cx">     BEGIN();
</span><del>-    Heap::heap(codeBlock)->writeBarrier(codeBlock);
</del><ins>+    Heap& heap = *Heap::heap(codeBlock);
+    heap.writeBarrier(codeBlock);
+    heap.writeBarrier(codeBlock->unlinkedCodeBlock());
</ins><span class="cx">     END();
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -993,7 +995,7 @@
</span><span class="cx">     ASSERT(!baseValue.isUndefinedOrNull());
</span><span class="cx">     JSObject* base = baseValue.toObject(globalObject);
</span><span class="cx">     CHECK_EXCEPTION();
</span><del>-    metadata.m_arrayProfile.observeStructureID(base->structureID());
</del><ins>+    metadata.m_arrayProfile->observeStructureID(base->structureID());
</ins><span class="cx"> 
</span><span class="cx">     JSString* name = enumerator->computeNext(globalObject, base, index, mode);
</span><span class="cx">     CHECK_EXCEPTION();
</span><span class="lines">@@ -1017,7 +1019,7 @@
</span><span class="cx">     JSPropertyNameEnumerator* enumerator = jsCast<JSPropertyNameEnumerator*>(GET(bytecode.m_enumerator).jsValue());
</span><span class="cx">     unsigned index = GET(bytecode.m_index).jsValue().asInt32();
</span><span class="cx"> 
</span><del>-    RETURN_PROFILED(CommonSlowPaths::opEnumeratorGetByVal(globalObject, baseValue, propertyName, index, mode, enumerator, &metadata.m_arrayProfile, &metadata.m_enumeratorMetadata));
</del><ins>+    RETURN_PROFILED(CommonSlowPaths::opEnumeratorGetByVal(globalObject, baseValue, propertyName, index, mode, enumerator, metadata.m_arrayProfile, &metadata.m_enumeratorMetadata));
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> JSC_DEFINE_COMMON_SLOW_PATH(slow_path_enumerator_in_by_val)
</span><span class="lines">@@ -1040,7 +1042,7 @@
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     JSString* string = asString(GET(bytecode.m_propertyName).jsValue());
</span><del>-    RETURN(jsBoolean(CommonSlowPaths::opInByVal(globalObject, baseValue, string, &metadata.m_arrayProfile)));
</del><ins>+    RETURN(jsBoolean(CommonSlowPaths::opInByVal(globalObject, baseValue, string, metadata.m_arrayProfile)));
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> JSC_DEFINE_COMMON_SLOW_PATH(slow_path_enumerator_has_own_property)
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeJSScopecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/JSScope.cpp (282477 => 282478)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/JSScope.cpp  2021-09-15 22:12:01 UTC (rev 282477)
+++ trunk/Source/JavaScriptCore/runtime/JSScope.cpp     2021-09-15 22:18:52 UTC (rev 282478)
</span><span class="lines">@@ -27,10 +27,12 @@
</span><span class="cx"> #include "JSScope.h"
</span><span class="cx"> 
</span><span class="cx"> #include "AbstractModuleRecord.h"
</span><ins>+#include "DeferTermination.h"
</ins><span class="cx"> #include "JSCInlines.h"
</span><span class="cx"> #include "JSLexicalEnvironment.h"
</span><span class="cx"> #include "JSModuleEnvironment.h"
</span><span class="cx"> #include "JSWithScope.h"
</span><ins>+#include "VMTrapsInlines.h"
</ins><span class="cx"> #include "VariableEnvironment.h"
</span><span class="cx"> 
</span><span class="cx"> namespace JSC {
</span><span class="lines">@@ -54,7 +56,7 @@
</span><span class="cx"> static inline bool abstractAccess(JSGlobalObject* globalObject, JSScope* scope, const Identifier& ident, GetOrPut getOrPut, size_t depth, bool& needsVarInjectionChecks, ResolveOp& op, InitializationMode initializationMode)
</span><span class="cx"> {
</span><span class="cx">     VM& vm = globalObject->vm();
</span><del>-    auto throwScope = DECLARE_THROW_SCOPE(vm);
</del><ins>+    DeferTerminationForAWhile deferScope(vm);
</ins><span class="cx"> 
</span><span class="cx">     if (scope->isJSLexicalEnvironment()) {
</span><span class="cx">         JSLexicalEnvironment* lexicalEnvironment = jsCast<JSLexicalEnvironment*>(scope);
</span><span class="lines">@@ -80,8 +82,9 @@
</span><span class="cx">         if (scope->type() == ModuleEnvironmentType) {
</span><span class="cx">             JSModuleEnvironment* moduleEnvironment = jsCast<JSModuleEnvironment*>(scope);
</span><span class="cx">             AbstractModuleRecord* moduleRecord = moduleEnvironment->moduleRecord();
</span><ins>+            auto catchScope = DECLARE_CATCH_SCOPE(vm);
</ins><span class="cx">             AbstractModuleRecord::Resolution resolution = moduleRecord->resolveImport(globalObject, ident);
</span><del>-            RETURN_IF_EXCEPTION(throwScope, false);
</del><ins>+            catchScope.releaseAssertNoException();
</ins><span class="cx">             if (resolution.type == AbstractModuleRecord::Resolution::Type::Resolved) {
</span><span class="cx">                 AbstractModuleRecord* importedRecord = resolution.moduleRecord;
</span><span class="cx">                 JSModuleEnvironment* importedEnvironment = importedRecord->moduleEnvironment();
</span><span class="lines">@@ -304,9 +307,6 @@
</span><span class="cx"> 
</span><span class="cx"> ResolveOp JSScope::abstractResolve(JSGlobalObject* globalObject, size_t depthOffset, JSScope* scope, const Identifier& ident, GetOrPut getOrPut, ResolveType unlinkedType, InitializationMode initializationMode)
</span><span class="cx"> {
</span><del>-    VM& vm = globalObject->vm();
-    auto throwScope = DECLARE_THROW_SCOPE(vm);
-
</del><span class="cx">     ResolveOp op(Dynamic, 0, nullptr, nullptr, nullptr, 0);
</span><span class="cx">     if (unlinkedType == Dynamic)
</span><span class="cx">         return op;
</span><span class="lines">@@ -315,7 +315,6 @@
</span><span class="cx">     size_t depth = depthOffset;
</span><span class="cx">     for (; scope; scope = scope->next()) {
</span><span class="cx">         bool success = abstractAccess(globalObject, scope, ident, getOrPut, depth, needsVarInjectionChecks, op, initializationMode);
</span><del>-        RETURN_IF_EXCEPTION(throwScope, ResolveOp(Dynamic, 0, nullptr, nullptr, nullptr, 0));
</del><span class="cx">         if (success)
</span><span class="cx">             break;
</span><span class="cx">         ++depth;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeVMcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/VM.cpp (282477 => 282478)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/VM.cpp       2021-09-15 22:12:01 UTC (rev 282477)
+++ trunk/Source/JavaScriptCore/runtime/VM.cpp  2021-09-15 22:18:52 UTC (rev 282478)
</span><span class="lines">@@ -1597,10 +1597,6 @@
</span><span class="cx"> DYNAMIC_ISO_SUBSPACE_DEFINE_MEMBER_SLOW(uint8ClampedArraySpace, cellHeapCellType.get(), JSUint8ClampedArray)
</span><span class="cx"> DYNAMIC_ISO_SUBSPACE_DEFINE_MEMBER_SLOW(uint16ArraySpace, cellHeapCellType.get(), JSUint16Array)
</span><span class="cx"> DYNAMIC_ISO_SUBSPACE_DEFINE_MEMBER_SLOW(uint32ArraySpace, cellHeapCellType.get(), JSUint32Array)
</span><del>-DYNAMIC_ISO_SUBSPACE_DEFINE_MEMBER_SLOW(unlinkedEvalCodeBlockSpace, destructibleCellHeapCellType.get(), UnlinkedEvalCodeBlock)
-DYNAMIC_ISO_SUBSPACE_DEFINE_MEMBER_SLOW(unlinkedFunctionCodeBlockSpace, destructibleCellHeapCellType.get(), UnlinkedFunctionCodeBlock)
-DYNAMIC_ISO_SUBSPACE_DEFINE_MEMBER_SLOW(unlinkedModuleProgramCodeBlockSpace, destructibleCellHeapCellType.get(), UnlinkedModuleProgramCodeBlock)
-DYNAMIC_ISO_SUBSPACE_DEFINE_MEMBER_SLOW(unlinkedProgramCodeBlockSpace, destructibleCellHeapCellType.get(), UnlinkedProgramCodeBlock)
</del><span class="cx"> DYNAMIC_ISO_SUBSPACE_DEFINE_MEMBER_SLOW(weakMapSpace, weakMapHeapCellType.get(), JSWeakMap) // Hash:0x662b12a3
</span><span class="cx"> DYNAMIC_ISO_SUBSPACE_DEFINE_MEMBER_SLOW(weakSetSpace, weakSetHeapCellType.get(), JSWeakSet) // Hash:0x4c781b30
</span><span class="cx"> DYNAMIC_ISO_SUBSPACE_DEFINE_MEMBER_SLOW(weakObjectRefSpace, cellHeapCellType.get(), JSWeakObjectRef) // Hash:0x8ec68f1f
</span><span class="lines">@@ -1654,6 +1650,11 @@
</span><span class="cx"> DYNAMIC_SPACE_AND_SET_DEFINE_MEMBER_SLOW(evalExecutableSpace, destructibleCellHeapCellType.get(), EvalExecutable) // Hash:0x958e3e9d
</span><span class="cx"> DYNAMIC_SPACE_AND_SET_DEFINE_MEMBER_SLOW(moduleProgramExecutableSpace, destructibleCellHeapCellType.get(), ModuleProgramExecutable) // Hash:0x6506fa3c
</span><span class="cx"> 
</span><ins>+DYNAMIC_SPACE_AND_SET_DEFINE_MEMBER_SLOW(unlinkedEvalCodeBlockSpace, destructibleCellHeapCellType.get(), UnlinkedEvalCodeBlock)
+DYNAMIC_SPACE_AND_SET_DEFINE_MEMBER_SLOW(unlinkedFunctionCodeBlockSpace, destructibleCellHeapCellType.get(), UnlinkedFunctionCodeBlock)
+DYNAMIC_SPACE_AND_SET_DEFINE_MEMBER_SLOW(unlinkedModuleProgramCodeBlockSpace, destructibleCellHeapCellType.get(), UnlinkedModuleProgramCodeBlock)
+DYNAMIC_SPACE_AND_SET_DEFINE_MEMBER_SLOW(unlinkedProgramCodeBlockSpace, destructibleCellHeapCellType.get(), UnlinkedProgramCodeBlock)
+
</ins><span class="cx"> #undef DYNAMIC_SPACE_AND_SET_DEFINE_MEMBER_SLOW
</span><span class="cx"> 
</span><span class="cx"> JSCell* VM::sentinelSetBucketSlow()
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeVMh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/VM.h (282477 => 282478)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/VM.h 2021-09-15 22:12:01 UTC (rev 282477)
+++ trunk/Source/JavaScriptCore/runtime/VM.h    2021-09-15 22:18:52 UTC (rev 282478)
</span><span class="lines">@@ -603,10 +603,6 @@
</span><span class="cx">     DYNAMIC_ISO_SUBSPACE_DEFINE_MEMBER(uint8ClampedArraySpace)
</span><span class="cx">     DYNAMIC_ISO_SUBSPACE_DEFINE_MEMBER(uint16ArraySpace)
</span><span class="cx">     DYNAMIC_ISO_SUBSPACE_DEFINE_MEMBER(uint32ArraySpace)
</span><del>-    DYNAMIC_ISO_SUBSPACE_DEFINE_MEMBER(unlinkedEvalCodeBlockSpace)
-    DYNAMIC_ISO_SUBSPACE_DEFINE_MEMBER(unlinkedFunctionCodeBlockSpace)
-    DYNAMIC_ISO_SUBSPACE_DEFINE_MEMBER(unlinkedModuleProgramCodeBlockSpace)
-    DYNAMIC_ISO_SUBSPACE_DEFINE_MEMBER(unlinkedProgramCodeBlockSpace)
</del><span class="cx">     DYNAMIC_ISO_SUBSPACE_DEFINE_MEMBER(finalizationRegistrySpace)
</span><span class="cx">     DYNAMIC_ISO_SUBSPACE_DEFINE_MEMBER(weakObjectRefSpace)
</span><span class="cx">     DYNAMIC_ISO_SUBSPACE_DEFINE_MEMBER(weakSetSpace)
</span><span class="lines">@@ -678,20 +674,26 @@
</span><span class="cx">     
</span><span class="cx">     SpaceAndSet codeBlockSpace;
</span><span class="cx"> 
</span><del>-    template<typename Func>
-    void forEachCodeBlockSpace(const Func& func)
-    {
-        // This should not include webAssemblyCodeBlockSpace because this is about subsclasses of
-        // JSC::CodeBlock.
-        func(codeBlockSpace);
-    }
-
</del><span class="cx">     DYNAMIC_SPACE_AND_SET_DEFINE_MEMBER(evalExecutableSpace)
</span><span class="cx">     DYNAMIC_SPACE_AND_SET_DEFINE_MEMBER(moduleProgramExecutableSpace)
</span><span class="cx">     SpaceAndSet functionExecutableSpace;
</span><span class="cx">     SpaceAndSet programExecutableSpace;
</span><span class="cx"> 
</span><ins>+    DYNAMIC_SPACE_AND_SET_DEFINE_MEMBER(unlinkedEvalCodeBlockSpace)
+    DYNAMIC_SPACE_AND_SET_DEFINE_MEMBER(unlinkedFunctionCodeBlockSpace)
+    DYNAMIC_SPACE_AND_SET_DEFINE_MEMBER(unlinkedModuleProgramCodeBlockSpace)
+    DYNAMIC_SPACE_AND_SET_DEFINE_MEMBER(unlinkedProgramCodeBlockSpace)
+
</ins><span class="cx">     template<typename Func>
</span><ins>+    void forEachUnlinkedCodeBlockSpace(const Func& func)
+    {
+        func(m_unlinkedEvalCodeBlockSpace.get());
+        func(m_unlinkedFunctionCodeBlockSpace.get());
+        func(m_unlinkedModuleProgramCodeBlockSpace.get());
+        func(m_unlinkedProgramCodeBlockSpace.get());
+    }
+
+    template<typename Func>
</ins><span class="cx">     void forEachScriptExecutableSpace(const Func& func)
</span><span class="cx">     {
</span><span class="cx">         if (m_evalExecutableSpace)
</span></span></pre>
</div>
</div>

</body>
</html>