<!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>[259582] trunk</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/259582">259582</a></dd>
<dt>Author</dt> <dd>sbarati@apple.com</dd>
<dt>Date</dt> <dd>2020-04-06 11:19:52 -0700 (Mon, 06 Apr 2020)</dd>
</dl>

<h3>Log Message</h3>
<pre>Implement 1GB of executable memory on arm64
https://bugs.webkit.org/show_bug.cgi?id=208490
<rdar://problem/60797127>

Reviewed by Keith Miller.

JSTests:

Run JetStream2 wasm tests.

* wasm.yaml:
* wasm/lowExecutableMemory/executable-memory-oom.js:

PerformanceTests:

* JetStream2/JetStreamDriver.js:
(Driver.prototype.dumpJSONResultsIfNeeded):
(DefaultBenchmark.prototype.updateUIAfterRun):
(DefaultBenchmark):
(WSLBenchmark.prototype.updateUIAfterRun):
(WSLBenchmark):
(WasmBenchmark.prototype.updateUIAfterRun):
(WasmBenchmark):
(Driver.async fetchResources.statusElement.innerHTML.a.href.string_appeared_here):
(Driver.prototype.async fetchResources):

Source/JavaScriptCore:

This patch implements the 1GB executable memory space on arm64. To make this
work, we implement jumps larger than +/-128MB to use jump islands. Jump islands
work by splitting up the ~1GB region into 9 112MB chunks (1008 MB total). Each
chunk is split into two: 96MB of executable region, and 16MB of jump island region.
With this split, any jump inside a jump island region can get to the adjacent
island (forwards or backwards) in a single +/-128MB jump. When linking a jump
from A to B, where |A - B| > 128MB, we instead point the jump to an island,
where this island has a potential series of jumps that finally lands at B.

To allocate executable memory, use a MetaAllocator for each 96MB chunk. To
allocate islands, we have a bit vector we use to track used and freed islands.
We only grow this bit vector as islands are allocated, so it frequently
remains empty or very small.

The goal of this patch is to have minimal perf impact when not using islands,
so the data structures are designed to only incur overhead when actually using
islands. We expect the use of islands to be minimal. We use a red black tree
to track all island locations. This allows us to deallocate all islands when
an executable memory handle is freed. Typically, this red black tree is empty,
so freeing an executable memory handle incurs no extra overhead.

To make islands work for Wasm, we now have to link tier up code in two phases.
Previously, we would just patch jumps concurrently to Wasm threads running after
resetting the icache, knowing that we would be able to atomically update the jump
instruction to point to the new destination. However, now when repatching these
jumps in a world with jump islands, we might need to allocate islands depending
on the jump location and its target. So we now allocate and collect the set of islands,
then reset the icache, then atomically update the branch to point to the destination
(or an island that jumps to the destination). One important implementation detail
here is that for normal island repatching, if we have a jump from A to B, and it
allocates a set if islands X, we usually can deallocate X when repatching A to go to B'.
This is because the typical repatch scenario in JS happens when that code is not being
executed. For Wasm though, those islands X might be running while we want to repatch
A to go to B'. So instead of deallocating X, we just append to X in this scenario, and
we free the new set X' when the code itself is freed.

(This patch also fixes a bug in the Wasm LLInt to BBQ tier up that I spotted,
where we would publish a LLInt callee's BBQ replacement before we finished
linking the outgoing calls of the BBQ replacement.)

This patch also removes the old "CodeProfiling" code that has been unused for
a long time.

* JavaScriptCore.xcodeproj/project.pbxproj:
* Sources.txt:
* assembler/ARM64Assembler.h:
(JSC::ARM64Assembler::b):
(JSC::ARM64Assembler::bl):
(JSC::ARM64Assembler::replaceWithJump):
(JSC::ARM64Assembler::prepareForAtomicRelinkJumpConcurrently):
(JSC::ARM64Assembler::prepareForAtomicRelinkCallConcurrently):
(JSC::ARM64Assembler::computeJumpType):
(JSC::ARM64Assembler::canEmitJump):
(JSC::ARM64Assembler::linkJumpOrCall):
(JSC::ARM64Assembler::linkCompareAndBranch):
(JSC::ARM64Assembler::linkConditionalBranch):
(JSC::ARM64Assembler::linkTestAndBranch):
* assembler/AbstractMacroAssembler.h:
(JSC::AbstractMacroAssembler::prepareForAtomicRepatchNearCallConcurrently):
* assembler/LinkBuffer.cpp:
(JSC::LinkBuffer::copyCompactAndLinkCode):
(JSC::LinkBuffer::linkCode):
(JSC::LinkBuffer::allocate):
(JSC::LinkBuffer::performFinalization):
* assembler/LinkBuffer.h:
(JSC::LinkBuffer::LinkBuffer):
(JSC::LinkBuffer::setIsJumpIsland):
* assembler/MacroAssemblerCodeRef.h:
(JSC::MacroAssemblerCodeRef::MacroAssemblerCodeRef):
* jit/ExecutableAllocator.cpp:
(JSC::initializeJITPageReservation):
(JSC::ExecutableAllocator::initializeUnderlyingAllocator):
(JSC::ExecutableAllocator::isValid const):
(JSC::ExecutableAllocator::allocate):
(JSC::ExecutableAllocator::getJumpIslandTo):
(JSC::ExecutableAllocator::getJumpIslandToConcurrently):
(JSC::FixedVMPoolExecutableAllocator::~FixedVMPoolExecutableAllocator): Deleted.
* jit/ExecutableAllocator.h:
(JSC::ExecutableAllocatorBase::allocate):
* runtime/CommonSlowPaths.cpp:
* runtime/Completion.cpp:
(JSC::evaluate):
* runtime/JSModuleLoader.cpp:
(JSC::moduleLoaderParseModule):
* runtime/OptionsList.h:
* tools/CodeProfile.cpp:
(JSC::truncateTrace): Deleted.
(JSC::CodeProfile::sample): Deleted.
(JSC::CodeProfile::report): Deleted.
* tools/CodeProfile.h:
(JSC::CodeProfile::CodeProfile): Deleted.
(JSC::CodeProfile::parent): Deleted.
(JSC::CodeProfile::addChild): Deleted.
(): Deleted.
(JSC::CodeProfile::CodeRecord::CodeRecord): Deleted.
* tools/CodeProfiling.cpp:
(JSC::setProfileTimer): Deleted.
(JSC::profilingTimer): Deleted.
(JSC::CodeProfiling::sample): Deleted.
(JSC::CodeProfiling::notifyAllocator): Deleted.
(JSC::CodeProfiling::getOwnerUIDForPC): Deleted.
(JSC::CodeProfiling::begin): Deleted.
(JSC::CodeProfiling::end): Deleted.
* tools/CodeProfiling.h:
(): Deleted.
(JSC::CodeProfiling::CodeProfiling): Deleted.
(JSC::CodeProfiling::~CodeProfiling): Deleted.
(JSC::CodeProfiling::enabled): Deleted.
(JSC::CodeProfiling::beVerbose): Deleted.
(JSC::CodeProfiling::beVeryVerbose): Deleted.
* wasm/WasmBBQPlan.cpp:
(JSC::Wasm::BBQPlan::work):
* wasm/WasmCodeBlock.h:
* wasm/WasmOMGForOSREntryPlan.cpp:
(JSC::Wasm::OMGForOSREntryPlan::work):
* wasm/WasmOMGPlan.cpp:
(JSC::Wasm::OMGPlan::work):
* wasm/WasmPlan.cpp:
(JSC::Wasm::Plan::updateCallSitesToCallUs):
* wasm/WasmPlan.h:

Source/WTF:

* wtf/MetaAllocator.cpp:
(WTF::MetaAllocatorTracker::notify):
(WTF::MetaAllocatorTracker::release):
(WTF::MetaAllocator::release):
(WTF::MetaAllocatorHandle::MetaAllocatorHandle):
(WTF::MetaAllocatorHandle::~MetaAllocatorHandle):
(WTF::MetaAllocatorHandle::shrink):
(WTF::MetaAllocator::MetaAllocator):
(WTF::MetaAllocator::allocate):
(WTF::MetaAllocator::currentStatistics):
* wtf/MetaAllocator.h:
(WTF::MetaAllocatorTracker::find):
(WTF::MetaAllocator::allocate):
(WTF::MetaAllocator::currentStatistics):
(WTF::MetaAllocator::getLock): Deleted.
* wtf/MetaAllocatorHandle.h:
(WTF::MetaAllocatorHandle::allocator):
(WTF::MetaAllocatorHandle::isManaged): Deleted.
(WTF::MetaAllocatorHandle::ownerUID): Deleted.
* wtf/PlatformEnable.h:
* wtf/RedBlackTree.h:
* wtf/StdLibExtras.h:
(WTF::constructFixedSizeArrayWithArgumentsImpl):
(WTF::constructFixedSizeArrayWithArguments):

Tools:

* Scripts/run-jsc-stress-tests:
* TestWebKitAPI/Tests/WTF/MetaAllocator.cpp:
(TestWebKitAPI::TEST_F):
* TestWebKitAPI/Tests/WTF/RedBlackTree.cpp:
(TestWebKitAPI::TEST_F):</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkJSTestsChangeLog">trunk/JSTests/ChangeLog</a></li>
<li><a href="#trunkJSTestswasmlowExecutableMemoryexecutablememoryoomjs">trunk/JSTests/wasm/lowExecutableMemory/executable-memory-oom.js</a></li>
<li><a href="#trunkJSTestswasmyaml">trunk/JSTests/wasm.yaml</a></li>
<li><a href="#trunkPerformanceTestsChangeLog">trunk/PerformanceTests/ChangeLog</a></li>
<li><a href="#trunkPerformanceTestsJetStream2JetStreamDriverjs">trunk/PerformanceTests/JetStream2/JetStreamDriver.js</a></li>
<li><a href="#trunkSourceJavaScriptCoreChangeLog">trunk/Source/JavaScriptCore/ChangeLog</a></li>
<li><a href="#trunkSourceJavaScriptCoreJavaScriptCorexcodeprojprojectpbxproj">trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj</a></li>
<li><a href="#trunkSourceJavaScriptCoreSourcestxt">trunk/Source/JavaScriptCore/Sources.txt</a></li>
<li><a href="#trunkSourceJavaScriptCoreassemblerARM64Assemblerh">trunk/Source/JavaScriptCore/assembler/ARM64Assembler.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreassemblerAbstractMacroAssemblerh">trunk/Source/JavaScriptCore/assembler/AbstractMacroAssembler.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreassemblerLinkBuffercpp">trunk/Source/JavaScriptCore/assembler/LinkBuffer.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreassemblerLinkBufferh">trunk/Source/JavaScriptCore/assembler/LinkBuffer.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreassemblerMacroAssemblerCodeRefh">trunk/Source/JavaScriptCore/assembler/MacroAssemblerCodeRef.h</a></li>
<li><a href="#trunkSourceJavaScriptCorejitExecutableAllocatorcpp">trunk/Source/JavaScriptCore/jit/ExecutableAllocator.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorejitExecutableAllocatorh">trunk/Source/JavaScriptCore/jit/ExecutableAllocator.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeCommonSlowPathscpp">trunk/Source/JavaScriptCore/runtime/CommonSlowPaths.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeCompletioncpp">trunk/Source/JavaScriptCore/runtime/Completion.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeJSModuleLoadercpp">trunk/Source/JavaScriptCore/runtime/JSModuleLoader.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeOptionsListh">trunk/Source/JavaScriptCore/runtime/OptionsList.h</a></li>
<li><a href="#trunkSourceJavaScriptCorewasmWasmBBQPlancpp">trunk/Source/JavaScriptCore/wasm/WasmBBQPlan.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorewasmWasmCodeBlockh">trunk/Source/JavaScriptCore/wasm/WasmCodeBlock.h</a></li>
<li><a href="#trunkSourceJavaScriptCorewasmWasmOMGForOSREntryPlancpp">trunk/Source/JavaScriptCore/wasm/WasmOMGForOSREntryPlan.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorewasmWasmOMGPlancpp">trunk/Source/JavaScriptCore/wasm/WasmOMGPlan.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorewasmWasmPlancpp">trunk/Source/JavaScriptCore/wasm/WasmPlan.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorewasmWasmPlanh">trunk/Source/JavaScriptCore/wasm/WasmPlan.h</a></li>
<li><a href="#trunkSourceWTFChangeLog">trunk/Source/WTF/ChangeLog</a></li>
<li><a href="#trunkSourceWTFwtfMetaAllocatorcpp">trunk/Source/WTF/wtf/MetaAllocator.cpp</a></li>
<li><a href="#trunkSourceWTFwtfMetaAllocatorh">trunk/Source/WTF/wtf/MetaAllocator.h</a></li>
<li><a href="#trunkSourceWTFwtfMetaAllocatorHandleh">trunk/Source/WTF/wtf/MetaAllocatorHandle.h</a></li>
<li><a href="#trunkSourceWTFwtfPlatformEnableh">trunk/Source/WTF/wtf/PlatformEnable.h</a></li>
<li><a href="#trunkSourceWTFwtfRedBlackTreeh">trunk/Source/WTF/wtf/RedBlackTree.h</a></li>
<li><a href="#trunkSourceWTFwtfStdLibExtrash">trunk/Source/WTF/wtf/StdLibExtras.h</a></li>
<li><a href="#trunkToolsChangeLog">trunk/Tools/ChangeLog</a></li>
<li><a href="#trunkToolsScriptsrunjscstresstests">trunk/Tools/Scripts/run-jsc-stress-tests</a></li>
<li><a href="#trunkToolsTestWebKitAPITestsWTFMetaAllocatorcpp">trunk/Tools/TestWebKitAPI/Tests/WTF/MetaAllocator.cpp</a></li>
<li><a href="#trunkToolsTestWebKitAPITestsWTFRedBlackTreecpp">trunk/Tools/TestWebKitAPI/Tests/WTF/RedBlackTree.cpp</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#trunkPerformanceTestsJetStream2wasmclijs">trunk/PerformanceTests/JetStream2/wasm-cli.js</a></li>
</ul>

<h3>Removed Paths</h3>
<ul>
<li><a href="#trunkSourceJavaScriptCoretoolsCodeProfilecpp">trunk/Source/JavaScriptCore/tools/CodeProfile.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoretoolsCodeProfileh">trunk/Source/JavaScriptCore/tools/CodeProfile.h</a></li>
<li><a href="#trunkSourceJavaScriptCoretoolsCodeProfilingcpp">trunk/Source/JavaScriptCore/tools/CodeProfiling.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoretoolsCodeProfilingh">trunk/Source/JavaScriptCore/tools/CodeProfiling.h</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkJSTestsChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/JSTests/ChangeLog (259581 => 259582)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JSTests/ChangeLog  2020-04-06 18:09:10 UTC (rev 259581)
+++ trunk/JSTests/ChangeLog     2020-04-06 18:19:52 UTC (rev 259582)
</span><span class="lines">@@ -1,3 +1,16 @@
</span><ins>+2020-04-06  Saam Barati  <sbarati@apple.com>
+
+        Implement 1GB of executable memory on arm64
+        https://bugs.webkit.org/show_bug.cgi?id=208490
+        <rdar://problem/60797127>
+
+        Reviewed by Keith Miller.
+
+        Run JetStream2 wasm tests.
+
+        * wasm.yaml:
+        * wasm/lowExecutableMemory/executable-memory-oom.js:
+
</ins><span class="cx"> 2020-04-06  Yusuke Suzuki  <ysuzuki@apple.com>
</span><span class="cx"> 
</span><span class="cx">         [JSC] Since ArrayBufferViewWatchpointAdaptor::add can fire watchpoints, DFG::Plan should check validity of CodeBlock after executing reallyAdd
</span></span></pre></div>
<a id="trunkJSTestswasmlowExecutableMemoryexecutablememoryoomjs"></a>
<div class="modfile"><h4>Modified: trunk/JSTests/wasm/lowExecutableMemory/executable-memory-oom.js (259581 => 259582)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JSTests/wasm/lowExecutableMemory/executable-memory-oom.js  2020-04-06 18:09:10 UTC (rev 259581)
+++ trunk/JSTests/wasm/lowExecutableMemory/executable-memory-oom.js     2020-04-06 18:19:52 UTC (rev 259582)
</span><span class="lines">@@ -1,3 +1,7 @@
</span><ins>+// FIXME: Consider making jump islands work with Options::jitMemoryReservationSize
+// https://bugs.webkit.org/show_bug.cgi?id=209037
+//@ skip if $architecture == "arm64"
+
</ins><span class="cx"> import * as assert from '../assert.js'
</span><span class="cx"> import Builder from '../Builder.js'
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkJSTestswasmyaml"></a>
<div class="modfile"><h4>Modified: trunk/JSTests/wasm.yaml (259581 => 259582)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JSTests/wasm.yaml  2020-04-06 18:09:10 UTC (rev 259581)
+++ trunk/JSTests/wasm.yaml     2020-04-06 18:19:52 UTC (rev 259582)
</span><span class="lines">@@ -231,3 +231,6 @@
</span><span class="cx"> - path: wasm/modules/run-from-wasm.wasm
</span><span class="cx">   cmd: runWebAssembly
</span><span class="cx"> 
</span><ins>+- path: ../PerformanceTests/JetStream2/wasm-cli.js
+  cmd: runWebAssemblyJetStream2 unless parseRunCommands
+
</ins></span></pre></div>
<a id="trunkPerformanceTestsChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/PerformanceTests/ChangeLog (259581 => 259582)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/PerformanceTests/ChangeLog 2020-04-06 18:09:10 UTC (rev 259581)
+++ trunk/PerformanceTests/ChangeLog    2020-04-06 18:19:52 UTC (rev 259582)
</span><span class="lines">@@ -1,3 +1,22 @@
</span><ins>+2020-04-06  Saam Barati  <sbarati@apple.com>
+
+        Implement 1GB of executable memory on arm64
+        https://bugs.webkit.org/show_bug.cgi?id=208490
+        <rdar://problem/60797127>
+
+        Reviewed by Keith Miller.
+
+        * JetStream2/JetStreamDriver.js:
+        (Driver.prototype.dumpJSONResultsIfNeeded):
+        (DefaultBenchmark.prototype.updateUIAfterRun):
+        (DefaultBenchmark):
+        (WSLBenchmark.prototype.updateUIAfterRun):
+        (WSLBenchmark):
+        (WasmBenchmark.prototype.updateUIAfterRun):
+        (WasmBenchmark):
+        (Driver.async fetchResources.statusElement.innerHTML.a.href.string_appeared_here):
+        (Driver.prototype.async fetchResources):
+
</ins><span class="cx"> 2020-03-26  Saam Barati  <sbarati@apple.com>
</span><span class="cx"> 
</span><span class="cx">         Make it so RAMification can be run with python 3 and 2 and that it recognizes the new JavaScriptCore.framework directory structure
</span></span></pre></div>
<a id="trunkPerformanceTestsJetStream2JetStreamDriverjs"></a>
<div class="modfile"><h4>Modified: trunk/PerformanceTests/JetStream2/JetStreamDriver.js (259581 => 259582)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/PerformanceTests/JetStream2/JetStreamDriver.js     2020-04-06 18:09:10 UTC (rev 259581)
+++ trunk/PerformanceTests/JetStream2/JetStreamDriver.js        2020-04-06 18:19:52 UTC (rev 259582)
</span><span class="lines">@@ -409,9 +409,9 @@
</span><span class="cx">     dumpJSONResultsIfNeeded()
</span><span class="cx">     {
</span><span class="cx">         if (dumpJSONResults) {
</span><del>-            print("\n");
-            print(this.resultsJSON());
-            print("\n");
</del><ins>+            console.log("\n");
+            console.log(this.resultsJSON());
+            console.log("\n");
</ins><span class="cx">         }
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="lines">@@ -725,15 +725,15 @@
</span><span class="cx">             return;
</span><span class="cx">         }
</span><span class="cx"> 
</span><del>-        print("    Startup:", uiFriendlyNumber(this.firstIteration));
-        print("    Worst Case:", uiFriendlyNumber(this.worst4));
-        print("    Average:", uiFriendlyNumber(this.average));
-        print("    Score:", uiFriendlyNumber(this.score));
</del><ins>+        console.log("    Startup:", uiFriendlyNumber(this.firstIteration));
+        console.log("    Worst Case:", uiFriendlyNumber(this.worst4));
+        console.log("    Average:", uiFriendlyNumber(this.average));
+        console.log("    Score:", uiFriendlyNumber(this.score));
</ins><span class="cx">         if (RAMification) {
</span><del>-            print("    Current Footprint:", uiFriendlyNumber(this.currentFootprint));
-            print("    Peak Footprint:", uiFriendlyNumber(this.peakFootprint));
</del><ins>+            console.log("    Current Footprint:", uiFriendlyNumber(this.currentFootprint));
+            console.log("    Peak Footprint:", uiFriendlyNumber(this.peakFootprint));
</ins><span class="cx">         }
</span><del>-        print("    Wall time:", uiFriendlyDuration(new Date(this.endTime - this.startTime)));
</del><ins>+        console.log("    Wall time:", uiFriendlyDuration(new Date(this.endTime - this.startTime)));
</ins><span class="cx">     }
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -819,14 +819,14 @@
</span><span class="cx">             return;
</span><span class="cx">         }
</span><span class="cx"> 
</span><del>-        print("    Stdlib:", uiFriendlyNumber(this.stdlib));
-        print("    Tests:", uiFriendlyNumber(this.mainRun));
-        print("    Score:", uiFriendlyNumber(this.score));
</del><ins>+        console.log("    Stdlib:", uiFriendlyNumber(this.stdlib));
+        console.log("    Tests:", uiFriendlyNumber(this.mainRun));
+        console.log("    Score:", uiFriendlyNumber(this.score));
</ins><span class="cx">         if (RAMification) {
</span><del>-            print("    Current Footprint:", uiFriendlyNumber(this.currentFootprint));
-            print("    Peak Footprint:", uiFriendlyNumber(this.peakFootprint));
</del><ins>+            console.log("    Current Footprint:", uiFriendlyNumber(this.currentFootprint));
+            console.log("    Peak Footprint:", uiFriendlyNumber(this.peakFootprint));
</ins><span class="cx">         }
</span><del>-        print("    Wall time:", uiFriendlyDuration(new Date(this.endTime - this.startTime)));
</del><ins>+        console.log("    Wall time:", uiFriendlyDuration(new Date(this.endTime - this.startTime)));
</ins><span class="cx">     }
</span><span class="cx"> };
</span><span class="cx"> 
</span><span class="lines">@@ -975,13 +975,13 @@
</span><span class="cx">             document.getElementById(this.scoreID).innerHTML = uiFriendlyNumber(this.score);
</span><span class="cx">             return;
</span><span class="cx">         }
</span><del>-        print("    Startup:", uiFriendlyNumber(this.startupTime));
-        print("    Run time:", uiFriendlyNumber(this.runTime));
</del><ins>+        console.log("    Startup:", uiFriendlyNumber(this.startupTime));
+        console.log("    Run time:", uiFriendlyNumber(this.runTime));
</ins><span class="cx">         if (RAMification) {
</span><del>-            print("    Current Footprint:", uiFriendlyNumber(this.currentFootprint));
-            print("    Peak Footprint:", uiFriendlyNumber(this.peakFootprint));
</del><ins>+            console.log("    Current Footprint:", uiFriendlyNumber(this.currentFootprint));
+            console.log("    Peak Footprint:", uiFriendlyNumber(this.peakFootprint));
</ins><span class="cx">         }
</span><del>-        print("    Score:", uiFriendlyNumber(this.score));
</del><ins>+        console.log("    Score:", uiFriendlyNumber(this.score));
</ins><span class="cx">     }
</span><span class="cx"> };
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkPerformanceTestsJetStream2wasmclijs"></a>
<div class="addfile"><h4>Added: trunk/PerformanceTests/JetStream2/wasm-cli.js (0 => 259582)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/PerformanceTests/JetStream2/wasm-cli.js                            (rev 0)
+++ trunk/PerformanceTests/JetStream2/wasm-cli.js       2020-04-06 18:19:52 UTC (rev 259582)
</span><span class="lines">@@ -0,0 +1,45 @@
</span><ins>+/*
+ * Copyright (C) 2020 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+const isInBrowser = false;
+console = {
+    log: () => { }
+}
+
+testList = ["HashSet-wasm", "tsf-wasm", "quicksort-wasm", "gcc-loops-wasm", "richards-wasm"];
+
+RAMification = false;
+
+load("./JetStreamDriver.js");
+
+async function runJetStream() {
+    try {
+        await JetStream.initialize();
+        JetStream.start();
+    } catch (e) {
+        throw e;
+    }
+}
+runJetStream();
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ChangeLog (259581 => 259582)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ChangeLog    2020-04-06 18:09:10 UTC (rev 259581)
+++ trunk/Source/JavaScriptCore/ChangeLog       2020-04-06 18:19:52 UTC (rev 259582)
</span><span class="lines">@@ -1,3 +1,132 @@
</span><ins>+2020-04-06  Saam Barati  <sbarati@apple.com>
+
+        Implement 1GB of executable memory on arm64
+        https://bugs.webkit.org/show_bug.cgi?id=208490
+        <rdar://problem/60797127>
+
+        Reviewed by Keith Miller.
+
+        This patch implements the 1GB executable memory space on arm64. To make this
+        work, we implement jumps larger than +/-128MB to use jump islands. Jump islands
+        work by splitting up the ~1GB region into 9 112MB chunks (1008 MB total). Each
+        chunk is split into two: 96MB of executable region, and 16MB of jump island region.
+        With this split, any jump inside a jump island region can get to the adjacent
+        island (forwards or backwards) in a single +/-128MB jump. When linking a jump
+        from A to B, where |A - B| > 128MB, we instead point the jump to an island,
+        where this island has a potential series of jumps that finally lands at B.
+        
+        To allocate executable memory, use a MetaAllocator for each 96MB chunk. To
+        allocate islands, we have a bit vector we use to track used and freed islands.
+        We only grow this bit vector as islands are allocated, so it frequently
+        remains empty or very small.
+        
+        The goal of this patch is to have minimal perf impact when not using islands,
+        so the data structures are designed to only incur overhead when actually using
+        islands. We expect the use of islands to be minimal. We use a red black tree
+        to track all island locations. This allows us to deallocate all islands when
+        an executable memory handle is freed. Typically, this red black tree is empty,
+        so freeing an executable memory handle incurs no extra overhead.
+        
+        To make islands work for Wasm, we now have to link tier up code in two phases.
+        Previously, we would just patch jumps concurrently to Wasm threads running after
+        resetting the icache, knowing that we would be able to atomically update the jump
+        instruction to point to the new destination. However, now when repatching these
+        jumps in a world with jump islands, we might need to allocate islands depending
+        on the jump location and its target. So we now allocate and collect the set of islands,
+        then reset the icache, then atomically update the branch to point to the destination
+        (or an island that jumps to the destination). One important implementation detail
+        here is that for normal island repatching, if we have a jump from A to B, and it
+        allocates a set if islands X, we usually can deallocate X when repatching A to go to B'.
+        This is because the typical repatch scenario in JS happens when that code is not being
+        executed. For Wasm though, those islands X might be running while we want to repatch
+        A to go to B'. So instead of deallocating X, we just append to X in this scenario, and
+        we free the new set X' when the code itself is freed.
+        
+        (This patch also fixes a bug in the Wasm LLInt to BBQ tier up that I spotted,
+        where we would publish a LLInt callee's BBQ replacement before we finished
+        linking the outgoing calls of the BBQ replacement.)
+        
+        This patch also removes the old "CodeProfiling" code that has been unused for
+        a long time.
+
+        * JavaScriptCore.xcodeproj/project.pbxproj:
+        * Sources.txt:
+        * assembler/ARM64Assembler.h:
+        (JSC::ARM64Assembler::b):
+        (JSC::ARM64Assembler::bl):
+        (JSC::ARM64Assembler::replaceWithJump):
+        (JSC::ARM64Assembler::prepareForAtomicRelinkJumpConcurrently):
+        (JSC::ARM64Assembler::prepareForAtomicRelinkCallConcurrently):
+        (JSC::ARM64Assembler::computeJumpType):
+        (JSC::ARM64Assembler::canEmitJump):
+        (JSC::ARM64Assembler::linkJumpOrCall):
+        (JSC::ARM64Assembler::linkCompareAndBranch):
+        (JSC::ARM64Assembler::linkConditionalBranch):
+        (JSC::ARM64Assembler::linkTestAndBranch):
+        * assembler/AbstractMacroAssembler.h:
+        (JSC::AbstractMacroAssembler::prepareForAtomicRepatchNearCallConcurrently):
+        * assembler/LinkBuffer.cpp:
+        (JSC::LinkBuffer::copyCompactAndLinkCode):
+        (JSC::LinkBuffer::linkCode):
+        (JSC::LinkBuffer::allocate):
+        (JSC::LinkBuffer::performFinalization):
+        * assembler/LinkBuffer.h:
+        (JSC::LinkBuffer::LinkBuffer):
+        (JSC::LinkBuffer::setIsJumpIsland):
+        * assembler/MacroAssemblerCodeRef.h:
+        (JSC::MacroAssemblerCodeRef::MacroAssemblerCodeRef):
+        * jit/ExecutableAllocator.cpp:
+        (JSC::initializeJITPageReservation):
+        (JSC::ExecutableAllocator::initializeUnderlyingAllocator):
+        (JSC::ExecutableAllocator::isValid const):
+        (JSC::ExecutableAllocator::allocate):
+        (JSC::ExecutableAllocator::getJumpIslandTo):
+        (JSC::ExecutableAllocator::getJumpIslandToConcurrently):
+        (JSC::FixedVMPoolExecutableAllocator::~FixedVMPoolExecutableAllocator): Deleted.
+        * jit/ExecutableAllocator.h:
+        (JSC::ExecutableAllocatorBase::allocate):
+        * runtime/CommonSlowPaths.cpp:
+        * runtime/Completion.cpp:
+        (JSC::evaluate):
+        * runtime/JSModuleLoader.cpp:
+        (JSC::moduleLoaderParseModule):
+        * runtime/OptionsList.h:
+        * tools/CodeProfile.cpp:
+        (JSC::truncateTrace): Deleted.
+        (JSC::CodeProfile::sample): Deleted.
+        (JSC::CodeProfile::report): Deleted.
+        * tools/CodeProfile.h:
+        (JSC::CodeProfile::CodeProfile): Deleted.
+        (JSC::CodeProfile::parent): Deleted.
+        (JSC::CodeProfile::addChild): Deleted.
+        (): Deleted.
+        (JSC::CodeProfile::CodeRecord::CodeRecord): Deleted.
+        * tools/CodeProfiling.cpp:
+        (JSC::setProfileTimer): Deleted.
+        (JSC::profilingTimer): Deleted.
+        (JSC::CodeProfiling::sample): Deleted.
+        (JSC::CodeProfiling::notifyAllocator): Deleted.
+        (JSC::CodeProfiling::getOwnerUIDForPC): Deleted.
+        (JSC::CodeProfiling::begin): Deleted.
+        (JSC::CodeProfiling::end): Deleted.
+        * tools/CodeProfiling.h:
+        (): Deleted.
+        (JSC::CodeProfiling::CodeProfiling): Deleted.
+        (JSC::CodeProfiling::~CodeProfiling): Deleted.
+        (JSC::CodeProfiling::enabled): Deleted.
+        (JSC::CodeProfiling::beVerbose): Deleted.
+        (JSC::CodeProfiling::beVeryVerbose): Deleted.
+        * wasm/WasmBBQPlan.cpp:
+        (JSC::Wasm::BBQPlan::work):
+        * wasm/WasmCodeBlock.h:
+        * wasm/WasmOMGForOSREntryPlan.cpp:
+        (JSC::Wasm::OMGForOSREntryPlan::work):
+        * wasm/WasmOMGPlan.cpp:
+        (JSC::Wasm::OMGPlan::work):
+        * wasm/WasmPlan.cpp:
+        (JSC::Wasm::Plan::updateCallSitesToCallUs):
+        * wasm/WasmPlan.h:
+
</ins><span class="cx"> 2020-04-06  Yusuke Suzuki  <ysuzuki@apple.com>
</span><span class="cx"> 
</span><span class="cx">         [JSC] Since ArrayBufferViewWatchpointAdaptor::add can fire watchpoints, DFG::Plan should check validity of CodeBlock after executing reallyAdd
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreJavaScriptCorexcodeprojprojectpbxproj"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj (259581 => 259582)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj     2020-04-06 18:09:10 UTC (rev 259581)
+++ trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj        2020-04-06 18:19:52 UTC (rev 259582)
</span><span class="lines">@@ -4073,8 +4073,6 @@
</span><span class="cx">          860161E00F3A83C100F84710 /* MacroAssemblerX86.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MacroAssemblerX86.h; sourceTree = "<group>"; };
</span><span class="cx">          860161E10F3A83C100F84710 /* MacroAssemblerX86_64.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MacroAssemblerX86_64.h; sourceTree = "<group>"; };
</span><span class="cx">          860161E20F3A83C100F84710 /* MacroAssemblerX86Common.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MacroAssemblerX86Common.h; sourceTree = "<group>"; };
</span><del>-               8603CEF214C7546400AE59E3 /* CodeProfiling.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CodeProfiling.cpp; sourceTree = "<group>"; };
-               8603CEF314C7546400AE59E3 /* CodeProfiling.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CodeProfiling.h; sourceTree = "<group>"; };
</del><span class="cx">           8604F4F2143A6C4400B295F5 /* ChangeLog */ = {isa = PBXFileReference; lastKnownFileType = text; lineEnding = 0; path = ChangeLog; sourceTree = "<group>"; };
</span><span class="cx">          8606DDE918DA44AB00A383D0 /* IdentifierInlines.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IdentifierInlines.h; sourceTree = "<group>"; };
</span><span class="cx">          8612E4CB1522918400C836BE /* MatchResult.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MatchResult.h; sourceTree = "<group>"; };
</span><span class="lines">@@ -4120,8 +4118,6 @@
</span><span class="cx">          86ADD1430FDDEA980006FFCC /* ARMv7Registers.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ARMv7Registers.h; sourceTree = "<group>"; };
</span><span class="cx">          86ADD1440FDDEA980006EEC2 /* MacroAssemblerARMv7.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MacroAssemblerARMv7.h; sourceTree = "<group>"; };
</span><span class="cx">          86B5822C14D22F5F00A9C306 /* ProfileTreeNode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ProfileTreeNode.h; sourceTree = "<group>"; };
</span><del>-               86B5822E14D2373B00A9C306 /* CodeProfile.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CodeProfile.cpp; sourceTree = "<group>"; };
-               86B5822F14D2373B00A9C306 /* CodeProfile.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CodeProfile.h; sourceTree = "<group>"; };
</del><span class="cx">           86B5826A14D35D5100A9C306 /* TieredMMapArray.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TieredMMapArray.h; sourceTree = "<group>"; };
</span><span class="cx">          86BF642A148DB2B5004DE36A /* Intrinsic.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Intrinsic.h; sourceTree = "<group>"; };
</span><span class="cx">          86C36EE90EE1289D00B3DF59 /* MacroAssembler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MacroAssembler.h; sourceTree = "<group>"; };
</span><span class="lines">@@ -7687,10 +7683,6 @@
</span><span class="cx">                          FE1BD01B1E72002100134BC9 /* CellList.cpp */,
</span><span class="cx">                          FE1BD01C1E72002100134BC9 /* CellList.h */,
</span><span class="cx">                          FE1BD0201E72027000134BC9 /* CellProfile.h */,
</span><del>-                               86B5822E14D2373B00A9C306 /* CodeProfile.cpp */,
-                               86B5822F14D2373B00A9C306 /* CodeProfile.h */,
-                               8603CEF214C7546400AE59E3 /* CodeProfiling.cpp */,
-                               8603CEF314C7546400AE59E3 /* CodeProfiling.h */,
</del><span class="cx">                           0F4F11E7209BCDA100709654 /* CompilerTimingScope.cpp */,
</span><span class="cx">                          0F4F11E6209BCDA100709654 /* CompilerTimingScope.h */,
</span><span class="cx">                          FE4BFF291AD476E700088F87 /* FunctionOverrides.cpp */,
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreSourcestxt"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/Sources.txt (259581 => 259582)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/Sources.txt  2020-04-06 18:09:10 UTC (rev 259581)
+++ trunk/Source/JavaScriptCore/Sources.txt     2020-04-06 18:19:52 UTC (rev 259582)
</span><span class="lines">@@ -997,8 +997,6 @@
</span><span class="cx"> JSCBuiltins.cpp
</span><span class="cx"> 
</span><span class="cx"> tools/CellList.cpp
</span><del>-tools/CodeProfile.cpp
-tools/CodeProfiling.cpp
</del><span class="cx"> tools/CompilerTimingScope.cpp
</span><span class="cx"> tools/FunctionOverrides.cpp
</span><span class="cx"> tools/FunctionWhitelist.cpp
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreassemblerARM64Assemblerh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/assembler/ARM64Assembler.h (259581 => 259582)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/assembler/ARM64Assembler.h   2020-04-06 18:09:10 UTC (rev 259581)
+++ trunk/Source/JavaScriptCore/assembler/ARM64Assembler.h      2020-04-06 18:19:52 UTC (rev 259582)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> /*
</span><del>- * Copyright (C) 2012-2019 Apple Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2012-2020 Apple Inc. All rights reserved.
</ins><span class="cx">  *
</span><span class="cx">  * Redistribution and use in source and binary forms, with or without
</span><span class="cx">  * modification, are permitted provided that the following conditions
</span><span class="lines">@@ -783,12 +783,9 @@
</span><span class="cx">         insn(dataProcessing2Source(DATASIZE, rm, DataOp_ASRV, rn, rd));
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    ALWAYS_INLINE void b(int32_t offset = 0)
</del><ins>+    ALWAYS_INLINE void b()
</ins><span class="cx">     {
</span><del>-        ASSERT(!(offset & 3));
-        offset >>= 2;
-        ASSERT(offset == (offset << 6) >> 6);
-        insn(unconditionalBranchImmediate(false, offset));
</del><ins>+        insn(unconditionalBranchImmediate(false, 0));
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     ALWAYS_INLINE void b_cond(Condition cond, int32_t offset = 0)
</span><span class="lines">@@ -831,11 +828,9 @@
</span><span class="cx">         insn(logicalShiftedRegister(DATASIZE, setFlags ? LogicalOp_ANDS : LogicalOp_AND, shift, true, rm, amount, rn, rd));
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    ALWAYS_INLINE void bl(int32_t offset = 0)
</del><ins>+    ALWAYS_INLINE void bl()
</ins><span class="cx">     {
</span><del>-        ASSERT(!(offset & 3));
-        offset >>= 2;
-        insn(unconditionalBranchImmediate(true, offset));
</del><ins>+        insn(unconditionalBranchImmediate(true, 0));
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     ALWAYS_INLINE void blr(RegisterID rn)
</span><span class="lines">@@ -2582,6 +2577,15 @@
</span><span class="cx">     {
</span><span class="cx">         intptr_t offset = (reinterpret_cast<intptr_t>(to) - reinterpret_cast<intptr_t>(where)) >> 2;
</span><span class="cx">         ASSERT(static_cast<int>(offset) == offset);
</span><ins>+
+#if USE(JUMP_ISLANDS)
+        if (!isInt<26>(offset)) {
+            to = ExecutableAllocator::singleton().getJumpIslandTo(where, to);
+            offset = (bitwise_cast<intptr_t>(to) - bitwise_cast<intptr_t>(where)) >> 2;
+            RELEASE_ASSERT(isInt<26>(offset));
+        }
+#endif
+
</ins><span class="cx">         int insn = unconditionalBranchImmediate(false, static_cast<int>(offset));
</span><span class="cx">         RELEASE_ASSERT(roundUpToMultipleOf<instructionSize>(where) == where);
</span><span class="cx">         performJITMemcpy(where, &insn, sizeof(int));
</span><span class="lines">@@ -2771,6 +2775,25 @@
</span><span class="cx">         relinkJumpOrCall<BranchType_CALL>(reinterpret_cast<int*>(from) - 1, reinterpret_cast<const int*>(from) - 1, to);
</span><span class="cx">         cacheFlush(reinterpret_cast<int*>(from) - 1, sizeof(int));
</span><span class="cx">     }
</span><ins>+
+#if USE(JUMP_ISLANDS)
+    static void* prepareForAtomicRelinkJumpConcurrently(void* from, void* to)
+    {
+        intptr_t offset = (bitwise_cast<intptr_t>(to) - bitwise_cast<intptr_t>(from)) >> 2;
+        ASSERT(static_cast<int>(offset) == offset);
+
+        if (isInt<26>(offset))
+            return to;
+
+        return ExecutableAllocator::singleton().getJumpIslandToConcurrently(from, to);
+    }
+
+    static void* prepareForAtomicRelinkCallConcurrently(void* from, void* to)
+    {
+        from = static_cast<void*>(bitwise_cast<int*>(from) - 1);
+        return prepareForAtomicRelinkJumpConcurrently(from, to);
+    }
+#endif
</ins><span class="cx">     
</span><span class="cx">     static void repatchCompact(void* where, int32_t value)
</span><span class="cx">     {
</span><span class="lines">@@ -2872,7 +2895,7 @@
</span><span class="cx">                 return LinkJumpConditionDirect;
</span><span class="cx"> 
</span><span class="cx">             return LinkJumpCondition;
</span><del>-            }
</del><ins>+        }
</ins><span class="cx">         case JumpCompareAndBranch:  {
</span><span class="cx">             ASSERT(is4ByteAligned(from));
</span><span class="cx">             ASSERT(is4ByteAligned(to));
</span><span class="lines">@@ -2945,6 +2968,12 @@
</span><span class="cx">         }
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    static ALWAYS_INLINE bool canEmitJump(void* from, void* to)
+    {
+        intptr_t diff = (bitwise_cast<intptr_t>(from) - bitwise_cast<intptr_t>(to)) >> 2;
+        return isInt<26>(diff);
+    }
+
</ins><span class="cx"> protected:
</span><span class="cx">     template<Datasize size>
</span><span class="cx">     static bool checkMovk(int insn, int _hw, RegisterID _rd)
</span><span class="lines">@@ -2994,9 +3023,17 @@
</span><span class="cx">         ASSERT(!(reinterpret_cast<intptr_t>(to) & 3));
</span><span class="cx">         assertIsNotTagged(to);
</span><span class="cx">         assertIsNotTagged(fromInstruction);
</span><del>-        intptr_t offset = (reinterpret_cast<intptr_t>(to) - reinterpret_cast<intptr_t>(fromInstruction)) >> 2;
</del><ins>+        intptr_t offset = (bitwise_cast<intptr_t>(to) - bitwise_cast<intptr_t>(fromInstruction)) >> 2;
</ins><span class="cx">         ASSERT(static_cast<int>(offset) == offset);
</span><span class="cx"> 
</span><ins>+#if USE(JUMP_ISLANDS)
+        if (!isInt<26>(offset)) {
+            to = ExecutableAllocator::singleton().getJumpIslandTo(bitwise_cast<void*>(fromInstruction), to);
+            offset = (bitwise_cast<intptr_t>(to) - bitwise_cast<intptr_t>(fromInstruction)) >> 2;
+            RELEASE_ASSERT(isInt<26>(offset));
+        }
+#endif
+
</ins><span class="cx">         int insn = unconditionalBranchImmediate(isCall, static_cast<int>(offset));
</span><span class="cx">         RELEASE_ASSERT(roundUpToMultipleOf<instructionSize>(from) == from);
</span><span class="cx">         copy(from, &insn, sizeof(int));
</span><span class="lines">@@ -3008,12 +3045,12 @@
</span><span class="cx">         ASSERT(!(reinterpret_cast<intptr_t>(from) & 3));
</span><span class="cx">         ASSERT(!(reinterpret_cast<intptr_t>(to) & 3));
</span><span class="cx">         intptr_t offset = (reinterpret_cast<intptr_t>(to) - reinterpret_cast<intptr_t>(fromInstruction)) >> 2;
</span><del>-        ASSERT(isInt<26>(offset));
</del><span class="cx"> 
</span><span class="cx">         bool useDirect = isInt<19>(offset);
</span><span class="cx">         ASSERT(type == IndirectBranch || useDirect);
</span><span class="cx"> 
</span><span class="cx">         if (useDirect || type == DirectBranch) {
</span><ins>+            ASSERT(isInt<19>(offset));
</ins><span class="cx">             int insn = compareAndBranchImmediate(is64Bit ? Datasize_64 : Datasize_32, condition == ConditionNE, static_cast<int>(offset), rt);
</span><span class="cx">             RELEASE_ASSERT(roundUpToMultipleOf<instructionSize>(from) == from);
</span><span class="cx">             copy(from, &insn, sizeof(int));
</span><span class="lines">@@ -3036,12 +3073,12 @@
</span><span class="cx">         ASSERT(!(reinterpret_cast<intptr_t>(from) & 3));
</span><span class="cx">         ASSERT(!(reinterpret_cast<intptr_t>(to) & 3));
</span><span class="cx">         intptr_t offset = (reinterpret_cast<intptr_t>(to) - reinterpret_cast<intptr_t>(fromInstruction)) >> 2;
</span><del>-        ASSERT(isInt<26>(offset));
</del><span class="cx"> 
</span><span class="cx">         bool useDirect = isInt<19>(offset);
</span><span class="cx">         ASSERT(type == IndirectBranch || useDirect);
</span><span class="cx"> 
</span><span class="cx">         if (useDirect || type == DirectBranch) {
</span><ins>+            ASSERT(isInt<19>(offset));
</ins><span class="cx">             int insn = conditionalBranchImmediate(static_cast<int>(offset), condition);
</span><span class="cx">             RELEASE_ASSERT(roundUpToMultipleOf<instructionSize>(from) == from);
</span><span class="cx">             copy(from, &insn, sizeof(int));
</span><span class="lines">@@ -3065,12 +3102,12 @@
</span><span class="cx">         ASSERT(!(reinterpret_cast<intptr_t>(to) & 3));
</span><span class="cx">         intptr_t offset = (reinterpret_cast<intptr_t>(to) - reinterpret_cast<intptr_t>(fromInstruction)) >> 2;
</span><span class="cx">         ASSERT(static_cast<int>(offset) == offset);
</span><del>-        ASSERT(isInt<26>(offset));
</del><span class="cx"> 
</span><span class="cx">         bool useDirect = isInt<14>(offset);
</span><span class="cx">         ASSERT(type == IndirectBranch || useDirect);
</span><span class="cx"> 
</span><span class="cx">         if (useDirect || type == DirectBranch) {
</span><ins>+            ASSERT(isInt<14>(offset));
</ins><span class="cx">             int insn = testAndBranchImmediate(condition == ConditionNE, static_cast<int>(bitNumber), static_cast<int>(offset), rt);
</span><span class="cx">             RELEASE_ASSERT(roundUpToMultipleOf<instructionSize>(from) == from);
</span><span class="cx">             copy(from, &insn, sizeof(int));
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreassemblerAbstractMacroAssemblerh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/assembler/AbstractMacroAssembler.h (259581 => 259582)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/assembler/AbstractMacroAssembler.h   2020-04-06 18:09:10 UTC (rev 259581)
+++ trunk/Source/JavaScriptCore/assembler/AbstractMacroAssembler.h      2020-04-06 18:19:52 UTC (rev 259582)
</span><span class="lines">@@ -919,6 +919,22 @@
</span><span class="cx">         RELEASE_ASSERT_NOT_REACHED();
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    template<PtrTag callTag, PtrTag destTag>
+    static CodeLocationLabel<destTag> prepareForAtomicRepatchNearCallConcurrently(CodeLocationNearCall<callTag> nearCall, CodeLocationLabel<destTag> destination)
+    {
+#if USE(JUMP_ISLANDS)
+        switch (nearCall.callMode()) {
+        case NearCallMode::Tail:
+            return CodeLocationLabel<destTag>(tagCodePtr<destTag>(AssemblerType::prepareForAtomicRelinkJumpConcurrently(nearCall.dataLocation(), destination.dataLocation())));
+        case NearCallMode::Regular:
+            return CodeLocationLabel<destTag>(tagCodePtr<destTag>(AssemblerType::prepareForAtomicRelinkCallConcurrently(nearCall.dataLocation(), destination.untaggedExecutableAddress())));
+        }
+#else
+        UNUSED_PARAM(nearCall);
+        return destination;
+#endif
+    }
+
</ins><span class="cx">     template<PtrTag tag>
</span><span class="cx">     static void repatchCompact(CodeLocationDataLabelCompact<tag> dataLabelCompact, int32_t value)
</span><span class="cx">     {
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreassemblerLinkBuffercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/assembler/LinkBuffer.cpp (259581 => 259582)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/assembler/LinkBuffer.cpp     2020-04-06 18:09:10 UTC (rev 259581)
+++ trunk/Source/JavaScriptCore/assembler/LinkBuffer.cpp        2020-04-06 18:19:52 UTC (rev 259582)
</span><span class="lines">@@ -131,9 +131,9 @@
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> template <typename InstructionType>
</span><del>-void LinkBuffer::copyCompactAndLinkCode(MacroAssembler& macroAssembler, void* ownerUID, JITCompilationEffort effort)
</del><ins>+void LinkBuffer::copyCompactAndLinkCode(MacroAssembler& macroAssembler, JITCompilationEffort effort)
</ins><span class="cx"> {
</span><del>-    allocate(macroAssembler, ownerUID, effort);
</del><ins>+    allocate(macroAssembler, effort);
</ins><span class="cx">     const size_t initialSize = macroAssembler.m_assembler.codeSize();
</span><span class="cx">     if (didFailToAllocate())
</span><span class="cx">         return;
</span><span class="lines">@@ -295,7 +295,7 @@
</span><span class="cx"> #endif // ENABLE(BRANCH_COMPACTION)
</span><span class="cx"> 
</span><span class="cx"> 
</span><del>-void LinkBuffer::linkCode(MacroAssembler& macroAssembler, void* ownerUID, JITCompilationEffort effort)
</del><ins>+void LinkBuffer::linkCode(MacroAssembler& macroAssembler, JITCompilationEffort effort)
</ins><span class="cx"> {
</span><span class="cx">     // Ensure that the end of the last invalidation point does not extend beyond the end of the buffer.
</span><span class="cx">     macroAssembler.label();
</span><span class="lines">@@ -304,7 +304,7 @@
</span><span class="cx"> #if defined(ASSEMBLER_HAS_CONSTANT_POOL) && ASSEMBLER_HAS_CONSTANT_POOL
</span><span class="cx">     macroAssembler.m_assembler.buffer().flushConstantPool(false);
</span><span class="cx"> #endif
</span><del>-    allocate(macroAssembler, ownerUID, effort);
</del><ins>+    allocate(macroAssembler, effort);
</ins><span class="cx">     if (!m_didAllocate)
</span><span class="cx">         return;
</span><span class="cx">     ASSERT(m_code);
</span><span class="lines">@@ -318,15 +318,15 @@
</span><span class="cx">     macroAssembler.m_assembler.relocateJumps(buffer.data(), code);
</span><span class="cx"> #endif
</span><span class="cx"> #elif CPU(ARM_THUMB2)
</span><del>-    copyCompactAndLinkCode<uint16_t>(macroAssembler, ownerUID, effort);
</del><ins>+    copyCompactAndLinkCode<uint16_t>(macroAssembler, effort);
</ins><span class="cx"> #elif CPU(ARM64)
</span><del>-    copyCompactAndLinkCode<uint32_t>(macroAssembler, ownerUID, effort);
</del><ins>+    copyCompactAndLinkCode<uint32_t>(macroAssembler, effort);
</ins><span class="cx"> #endif // !ENABLE(BRANCH_COMPACTION)
</span><span class="cx"> 
</span><span class="cx">     m_linkTasks = WTFMove(macroAssembler.m_linkTasks);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void LinkBuffer::allocate(MacroAssembler& macroAssembler, void* ownerUID, JITCompilationEffort effort)
</del><ins>+void LinkBuffer::allocate(MacroAssembler& macroAssembler, JITCompilationEffort effort)
</ins><span class="cx"> {
</span><span class="cx">     size_t initialSize = macroAssembler.m_assembler.codeSize();
</span><span class="cx">     if (m_code) {
</span><span class="lines">@@ -344,7 +344,7 @@
</span><span class="cx">         initialSize = macroAssembler.m_assembler.codeSize();
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    m_executableMemory = ExecutableAllocator::singleton().allocate(initialSize, ownerUID, effort);
</del><ins>+    m_executableMemory = ExecutableAllocator::singleton().allocate(initialSize, effort);
</ins><span class="cx">     if (!m_executableMemory)
</span><span class="cx">         return;
</span><span class="cx">     m_code = MacroAssemblerCodePtr<LinkBufferPtrTag>(m_executableMemory->start().retaggedPtr<LinkBufferPtrTag>());
</span><span class="lines">@@ -358,7 +358,7 @@
</span><span class="cx">         task->run(*this);
</span><span class="cx"> 
</span><span class="cx"> #ifndef NDEBUG
</span><del>-    ASSERT(!isCompilationThread());
</del><ins>+    ASSERT(m_isJumpIsland || !isCompilationThread());
</ins><span class="cx">     ASSERT(!m_completed);
</span><span class="cx">     ASSERT(isValid());
</span><span class="cx">     m_completed = true;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreassemblerLinkBufferh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/assembler/LinkBuffer.h (259581 => 259582)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/assembler/LinkBuffer.h       2020-04-06 18:09:10 UTC (rev 259581)
+++ trunk/Source/JavaScriptCore/assembler/LinkBuffer.h  2020-04-06 18:19:52 UTC (rev 259582)
</span><span class="lines">@@ -90,7 +90,8 @@
</span><span class="cx">         , m_completed(false)
</span><span class="cx"> #endif
</span><span class="cx">     {
</span><del>-        linkCode(macroAssembler, ownerUID, effort);
</del><ins>+        UNUSED_PARAM(ownerUID);
+        linkCode(macroAssembler, effort);
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     template<PtrTag tag>
</span><span class="lines">@@ -107,7 +108,7 @@
</span><span class="cx"> #else
</span><span class="cx">         UNUSED_PARAM(shouldPerformBranchCompaction);
</span><span class="cx"> #endif
</span><del>-        linkCode(macroAssembler, 0, effort);
</del><ins>+        linkCode(macroAssembler, effort);
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     ~LinkBuffer()
</span><span class="lines">@@ -123,6 +124,13 @@
</span><span class="cx">     {
</span><span class="cx">         return !didFailToAllocate();
</span><span class="cx">     }
</span><ins>+
+    void setIsJumpIsland()
+    {
+#if ASSERT_ENABLED
+        m_isJumpIsland = true;
+#endif
+    }
</ins><span class="cx">     
</span><span class="cx">     // These methods are used to link or set values at code generation time.
</span><span class="cx"> 
</span><span class="lines">@@ -321,12 +329,12 @@
</span><span class="cx">         return m_code.dataLocation();
</span><span class="cx">     }
</span><span class="cx">     
</span><del>-    void allocate(MacroAssembler&, void* ownerUID, JITCompilationEffort);
</del><ins>+    void allocate(MacroAssembler&, JITCompilationEffort);
</ins><span class="cx"> 
</span><del>-    JS_EXPORT_PRIVATE void linkCode(MacroAssembler&, void* ownerUID, JITCompilationEffort);
</del><ins>+    JS_EXPORT_PRIVATE void linkCode(MacroAssembler&, JITCompilationEffort);
</ins><span class="cx"> #if ENABLE(BRANCH_COMPACTION)
</span><span class="cx">     template <typename InstructionType>
</span><del>-    void copyCompactAndLinkCode(MacroAssembler&, void* ownerUID, JITCompilationEffort);
</del><ins>+    void copyCompactAndLinkCode(MacroAssembler&, JITCompilationEffort);
</ins><span class="cx"> #endif
</span><span class="cx"> 
</span><span class="cx">     void performFinalization();
</span><span class="lines">@@ -349,6 +357,9 @@
</span><span class="cx"> #ifndef NDEBUG
</span><span class="cx">     bool m_completed;
</span><span class="cx"> #endif
</span><ins>+#if ASSERT_ENABLED
+    bool m_isJumpIsland { false };
+#endif
</ins><span class="cx">     bool m_alreadyDisassembled { false };
</span><span class="cx">     MacroAssemblerCodePtr<LinkBufferPtrTag> m_code;
</span><span class="cx">     Vector<RefPtr<SharedTask<void(LinkBuffer&)>>> m_linkTasks;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreassemblerMacroAssemblerCodeRefh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/assembler/MacroAssemblerCodeRef.h (259581 => 259582)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/assembler/MacroAssemblerCodeRef.h    2020-04-06 18:09:10 UTC (rev 259581)
+++ trunk/Source/JavaScriptCore/assembler/MacroAssemblerCodeRef.h       2020-04-06 18:19:52 UTC (rev 259582)
</span><span class="lines">@@ -434,7 +434,6 @@
</span><span class="cx">         : m_codePtr(executableMemory->start().retaggedPtr<tag>())
</span><span class="cx">         , m_executableMemory(WTFMove(executableMemory))
</span><span class="cx">     {
</span><del>-        ASSERT(m_executableMemory->isManaged());
</del><span class="cx">         ASSERT(m_executableMemory->start());
</span><span class="cx">         ASSERT(m_codePtr);
</span><span class="cx">     }
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitExecutableAllocatorcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/ExecutableAllocator.cpp (259581 => 259582)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/ExecutableAllocator.cpp  2020-04-06 18:09:10 UTC (rev 259581)
+++ trunk/Source/JavaScriptCore/jit/ExecutableAllocator.cpp     2020-04-06 18:19:52 UTC (rev 259582)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> /*
</span><del>- * Copyright (C) 2008-2019 Apple Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2008-2020 Apple Inc. All rights reserved.
</ins><span class="cx">  *
</span><span class="cx">  * Redistribution and use in source and binary forms, with or without
</span><span class="cx">  * modification, are permitted provided that the following conditions
</span><span class="lines">@@ -28,9 +28,10 @@
</span><span class="cx"> 
</span><span class="cx"> #if ENABLE(JIT)
</span><span class="cx"> 
</span><del>-#include "CodeProfiling.h"
</del><span class="cx"> #include "ExecutableAllocationFuzz.h"
</span><ins>+#include "IterationStatus.h"
</ins><span class="cx"> #include "JSCInlines.h"
</span><ins>+#include <type_traits>
</ins><span class="cx"> #include <wtf/FileSystem.h>
</span><span class="cx"> #include <wtf/MetaAllocator.h>
</span><span class="cx"> #include <wtf/PageReservation.h>
</span><span class="lines">@@ -92,15 +93,26 @@
</span><span class="cx"> using namespace WTF;
</span><span class="cx"> 
</span><span class="cx"> #if defined(FIXED_EXECUTABLE_MEMORY_POOL_SIZE_IN_MB) && FIXED_EXECUTABLE_MEMORY_POOL_SIZE_IN_MB > 0
</span><del>-static constexpr size_t fixedExecutableMemoryPoolSize = FIXED_EXECUTABLE_MEMORY_POOL_SIZE_IN_MB * 1024 * 1024;
</del><ins>+static constexpr size_t fixedExecutableMemoryPoolSize = FIXED_EXECUTABLE_MEMORY_POOL_SIZE_IN_MB * MB;
</ins><span class="cx"> #elif CPU(ARM)
</span><del>-static constexpr size_t fixedExecutableMemoryPoolSize = 16 * 1024 * 1024;
</del><ins>+static constexpr size_t fixedExecutableMemoryPoolSize = 16 * MB;
</ins><span class="cx"> #elif CPU(ARM64)
</span><del>-static constexpr size_t fixedExecutableMemoryPoolSize = 128 * 1024 * 1024;
</del><ins>+#if USE(JUMP_ISLANDS)
+static constexpr size_t fixedExecutableMemoryPoolSize = 1 * GB;
+// These sizes guarantee that any jump within an island can jump forwards or backwards
+// to the adjacent island in a single instruction.
+static constexpr size_t regionSize = 112 * MB;
+static constexpr size_t islandRegionSize = 16 * MB;
+static constexpr size_t numberOfRegions = fixedExecutableMemoryPoolSize / regionSize;
+static constexpr size_t islandSizeInBytes = 4;
+static constexpr size_t maxIslandsPerRegion = islandRegionSize / islandSizeInBytes;
+#else
+static constexpr size_t fixedExecutableMemoryPoolSize = 128 * MB;
+#endif
</ins><span class="cx"> #elif CPU(X86_64)
</span><del>-static constexpr size_t fixedExecutableMemoryPoolSize = 1024 * 1024 * 1024;
</del><ins>+static constexpr size_t fixedExecutableMemoryPoolSize = 1 * GB;
</ins><span class="cx"> #else
</span><del>-static constexpr size_t fixedExecutableMemoryPoolSize = 32 * 1024 * 1024;
</del><ins>+static constexpr size_t fixedExecutableMemoryPoolSize = 32 * MB;
</ins><span class="cx"> #endif
</span><span class="cx"> 
</span><span class="cx"> #if CPU(ARM)
</span><span class="lines">@@ -313,10 +325,13 @@
</span><span class="cx">     if (!isJITEnabled())
</span><span class="cx">         return reservation;
</span><span class="cx"> 
</span><ins>+    reservation.size = fixedExecutableMemoryPoolSize;
+#if !USE(JUMP_ISLANDS)
+    // FIXME: Consider making jump islands work with Options::jitMemoryReservationSize
+    // https://bugs.webkit.org/show_bug.cgi?id=209037
</ins><span class="cx">     if (Options::jitMemoryReservationSize())
</span><span class="cx">         reservation.size = Options::jitMemoryReservationSize();
</span><del>-    else
-        reservation.size = fixedExecutableMemoryPoolSize;
</del><ins>+#endif
</ins><span class="cx">     reservation.size = std::max(roundUpToMultipleOf(pageSize(), reservation.size), pageSize() * 2);
</span><span class="cx"> 
</span><span class="cx">     auto tryCreatePageReservation = [] (size_t reservationSize) {
</span><span class="lines">@@ -363,52 +378,459 @@
</span><span class="cx">     return reservation;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-class FixedVMPoolExecutableAllocator final : public MetaAllocator {
</del><ins>+class FixedVMPoolExecutableAllocator final {
</ins><span class="cx">     WTF_MAKE_FAST_ALLOCATED;
</span><ins>+
+#if USE(JUMP_ISLANDS)
+    class Islands;
+    class RegionAllocator;
+#endif
+
</ins><span class="cx"> public:
</span><span class="cx">     FixedVMPoolExecutableAllocator()
</span><del>-        : MetaAllocator(jitAllocationGranule) // round up all allocations to 32 bytes
</del><ins>+#if USE(JUMP_ISLANDS)
+        : m_allocators(constructFixedSizeArrayWithArguments<RegionAllocator, numberOfRegions>(*this))
+#else
+        : m_allocator(*this)
+#endif
</ins><span class="cx">     {
</span><span class="cx">         JITReservation reservation = initializeJITPageReservation();
</span><span class="cx">         m_reservation = WTFMove(reservation.pageReservation);
</span><span class="cx">         if (m_reservation) {
</span><del>-            addFreshFreeSpace(reservation.base, reservation.size);
</del><ins>+#if USE(JUMP_ISLANDS)
+            uintptr_t start = bitwise_cast<uintptr_t>(memoryStart());
+            uintptr_t reservationEnd = bitwise_cast<uintptr_t>(memoryEnd());
+            for (size_t i = 0; i < numberOfRegions; ++i) {
+                RELEASE_ASSERT(start < reservationEnd);
+                m_allocators[i].m_start = tagCodePtr<ExecutableMemoryPtrTag>(bitwise_cast<void*>(start));
+                m_allocators[i].m_end = tagCodePtr<ExecutableMemoryPtrTag>(bitwise_cast<void*>(start + regionSize));
+                if (m_allocators[i].end() > reservationEnd) {
+                    // We may have taken a page for the executable only copy thunk.
+                    RELEASE_ASSERT(i == numberOfRegions - 1);
+                    m_allocators[i].m_end = tagCodePtr<ExecutableMemoryPtrTag>(bitwise_cast<void*>(reservationEnd));
+                }
+
+                m_allocators[i].addFreshFreeSpace(bitwise_cast<void*>(m_allocators[i].start()), m_allocators[i].allocatorSize());
+
+                RELEASE_ASSERT(m_allocators[i].allocatorSize() < regionSize);
+                RELEASE_ASSERT(m_allocators[i].islandBegin() > m_allocators[i].start());
+                RELEASE_ASSERT(m_allocators[i].islandBegin() < m_allocators[i].end());
+
+                start += regionSize;
+            }
+#else
+            m_allocator.addFreshFreeSpace(reservation.base, reservation.size);
</ins><span class="cx">             ASSERT(bytesReserved() == reservation.size); // Since our executable memory is fixed-sized, bytesReserved is never changed after initialization.
</span><ins>+#endif
</ins><span class="cx">         }
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    virtual ~FixedVMPoolExecutableAllocator();
</del><ins>+    ~FixedVMPoolExecutableAllocator()
+    {
+        m_reservation.deallocate();
+    }
</ins><span class="cx"> 
</span><span class="cx">     void* memoryStart() { return untagCodePtr<ExecutableMemoryPtrTag>(g_jscConfig.startExecutableMemory); }
</span><span class="cx">     void* memoryEnd() { return untagCodePtr<ExecutableMemoryPtrTag>(g_jscConfig.endExecutableMemory); }
</span><span class="cx">     bool isJITPC(void* pc) { return memoryStart() <= pc && pc < memoryEnd(); }
</span><ins>+    bool isValid() { return !!m_reservation; }
</ins><span class="cx"> 
</span><del>-protected:
-    FreeSpacePtr allocateNewSpace(size_t&) override
</del><ins>+    RefPtr<ExecutableMemoryHandle> allocate(size_t sizeInBytes)
</ins><span class="cx">     {
</span><del>-        // We're operating in a fixed pool, so new allocation is always prohibited.
</del><ins>+#if USE(JUMP_ISLANDS)
+        auto locker = holdLock(getLock());
+
+        unsigned start = 0;
+        if (Options::useRandomizingExecutableIslandAllocation())
+            start = cryptographicallyRandomNumber() % m_allocators.size();
+
+        unsigned i = start;
+        while (true) {
+            RegionAllocator& allocator = m_allocators[i];
+            if (RefPtr<ExecutableMemoryHandle> result = allocator.allocate(locker, sizeInBytes))
+                return result;
+            i = (i + 1) % m_allocators.size();
+            if (i == start)
+                break;
+        }
</ins><span class="cx">         return nullptr;
</span><ins>+#else
+        return m_allocator.allocate(sizeInBytes);
+#endif // USE(JUMP_ISLANDS)
</ins><span class="cx">     }
</span><span class="cx"> 
</span><del>-    void notifyNeedPage(void* page, size_t count) override
</del><ins>+    Lock& getLock() { return m_lock; }
+
+    // Non atomic
+    size_t bytesAllocated() 
</ins><span class="cx">     {
</span><del>-        m_reservation.commit(page, pageSize() * count);
</del><ins>+        size_t result = 0;
+        forEachAllocator([&] (Allocator& allocator) {
+            result += allocator.bytesAllocated();
+        });
+        return result;
</ins><span class="cx">     }
</span><ins>+    size_t bytesReserved() 
+    {
+        size_t result = 0;
+        forEachAllocator([&] (Allocator& allocator) {
+            result += allocator.bytesReserved();
+        });
+        return result;
+    }
+    size_t bytesCommitted()
+    {
+        size_t result = 0;
+        forEachAllocator([&] (Allocator& allocator) {
+            result += allocator.bytesCommitted();
+        });
+        return result;
+    }
</ins><span class="cx"> 
</span><del>-    void notifyPageIsFree(void* page, size_t count) override
</del><ins>+    bool isInAllocatedMemory(const AbstractLocker& locker, void* address)
</ins><span class="cx">     {
</span><del>-        m_reservation.decommit(page, pageSize() * count);
</del><ins>+#if USE(JUMP_ISLANDS)
+        if (RegionAllocator* allocator = findRegion(bitwise_cast<uintptr_t>(address)))
+            return allocator->isInAllocatedMemory(locker, address);
+        return false;
+#else
+        return m_allocator.isInAllocatedMemory(locker, address);
+#endif
</ins><span class="cx">     }
</span><span class="cx"> 
</span><ins>+#if ENABLE(META_ALLOCATOR_PROFILE)
+    void dumpProfile()
+    {
+        forEachAllocator([&] (Allocator& allocator) {
+            allocator.dumpProfile();
+        });
+    }
+#endif
+
+    MetaAllocator::Statistics currentStatistics()
+    {
+        auto locker = holdLock(getLock());
+        MetaAllocator::Statistics result { 0, 0, 0 };
+        forEachAllocator([&] (Allocator& allocator) {
+            auto allocatorStats = allocator.currentStatistics(locker);
+            result.bytesAllocated += allocatorStats.bytesAllocated;
+            result.bytesReserved += allocatorStats.bytesReserved;
+            result.bytesCommitted += allocatorStats.bytesCommitted;
+        });
+        return result;
+    }
+
+#if USE(JUMP_ISLANDS)
+    void handleWillBeReleased(const LockHolder& locker, MetaAllocatorHandle& handle)
+    {
+        if (m_islandsForJumpSourceLocation.isEmpty())
+            return;
+
+        Vector<Islands*, 16> toRemove;
+        void* start = handle.start().untaggedPtr();
+        void* end = handle.end().untaggedPtr();
+        m_islandsForJumpSourceLocation.iterate([&] (Islands& islands, bool& visitLeft, bool& visitRight) {
+            if (start <= islands.key() && islands.key() < end)
+                toRemove.append(&islands);
+            if (islands.key() > start)
+                visitLeft = true;
+            if (islands.key() < end)
+                visitRight = true;
+        });
+
+        for (Islands* islands : toRemove)
+            freeIslands(locker, islands);
+
+        if (ASSERT_ENABLED) {
+            m_islandsForJumpSourceLocation.iterate([&] (Islands& islands, bool& visitLeft, bool& visitRight) {
+                if (start <= islands.key() && islands.key() < end) {
+                    dataLogLn("did not remove everything!");
+                    RELEASE_ASSERT_NOT_REACHED();
+                }
+                visitLeft = true;
+                visitRight = true;
+            });
+        }
+    }
+
+    void* makeIsland(uintptr_t jumpLocation, uintptr_t newTarget, bool concurrently)
+    {
+        auto locker = holdLock(getLock());
+        return islandForJumpLocation(locker, jumpLocation, newTarget, concurrently);
+    }
+
</ins><span class="cx"> private:
</span><ins>+    RegionAllocator* findRegion(uintptr_t ptr)
+    {
+        RegionAllocator* result = nullptr;
+        forEachAllocator([&] (RegionAllocator& allocator) {
+            if (allocator.start() <= ptr && ptr < allocator.end()) {
+                result = &allocator;
+                return IterationStatus::Done;
+            }
+            return IterationStatus::Continue;
+        });
+        return result;
+    }
+
+    void freeJumpIslands(const LockHolder&, Islands* islands)
+    {
+        for (CodeLocationLabel<ExecutableMemoryPtrTag> jumpIsland : islands->jumpIslands) {
+            uintptr_t untaggedJumpIsland = bitwise_cast<uintptr_t>(jumpIsland.dataLocation());
+            RegionAllocator* allocator = findRegion(untaggedJumpIsland);
+            RELEASE_ASSERT(allocator);
+            allocator->freeIsland(untaggedJumpIsland);
+        }
+        islands->jumpIslands.clear();
+    }
+
+    void freeIslands(const LockHolder& locker, Islands* islands)
+    {
+        freeJumpIslands(locker, islands);
+        m_islandsForJumpSourceLocation.remove(islands);
+        delete islands;
+    }
+
+    void* islandForJumpLocation(const LockHolder& locker, uintptr_t jumpLocation, uintptr_t target, bool concurrently)
+    {
+        Islands* islands = m_islandsForJumpSourceLocation.findExact(bitwise_cast<void*>(jumpLocation));
+        if (islands) {
+            // FIXME: We could create some method of reusing already allocated islands here, but it's
+            // unlikely to matter in practice.
+            if (!concurrently)
+                freeJumpIslands(locker, islands);
+        } else {
+            islands = new Islands;
+            islands->jumpSourceLocation = CodeLocationLabel<ExecutableMemoryPtrTag>(tagCodePtr<ExecutableMemoryPtrTag>(bitwise_cast<void*>(jumpLocation)));
+            m_islandsForJumpSourceLocation.insert(islands);
+        }
+
+        RegionAllocator* allocator = findRegion(jumpLocation > target ? jumpLocation - regionSize : jumpLocation);
+        RELEASE_ASSERT(allocator);
+        void* result = allocator->allocateIsland();
+        void* currentIsland = result;
+        jumpLocation = bitwise_cast<uintptr_t>(currentIsland);
+        while (true) {
+            islands->jumpIslands.append(CodeLocationLabel<ExecutableMemoryPtrTag>(tagCodePtr<ExecutableMemoryPtrTag>(currentIsland)));
+
+            auto emitJumpTo = [&] (void* target) {
+                RELEASE_ASSERT(ARM64Assembler::canEmitJump(bitwise_cast<void*>(jumpLocation), target));
+
+                MacroAssembler jit;
+                auto jump = jit.jump();
+                LinkBuffer linkBuffer(jit, MacroAssemblerCodePtr<NoPtrTag>(currentIsland), islandSizeInBytes, JITCompilationMustSucceed, false);
+                RELEASE_ASSERT(linkBuffer.isValid());
+
+                // We use this to appease the assertion that we're not finalizing on a compiler thread. In this situation, it's
+                // ok to do this on a compiler thread, since the compiler thread is linking a jump to this code (and no other live
+                // code can jump to these islands). It's ok because the CPU protocol for exposing code to other CPUs is:
+                // - Self modifying code fence (what FINALIZE_CODE does below). This does various memory flushes + instruction sync barrier (isb).
+                // - Any CPU that will run the code must run a crossModifyingCodeFence (isb) before running it. Since the code that
+                // has a jump linked to this island hasn't finalized yet, they're guaranteed to finalize there code and run an isb.
+                linkBuffer.setIsJumpIsland();
+
+                linkBuffer.link(jump, CodeLocationLabel<NoPtrTag>(target));
+                FINALIZE_CODE(linkBuffer, NoPtrTag, "Jump Island: %lu", jumpLocation);
+            };
+
+            if (ARM64Assembler::canEmitJump(bitwise_cast<void*>(jumpLocation), bitwise_cast<void*>(target))) {
+                emitJumpTo(bitwise_cast<void*>(target));
+                break;
+            }
+
+            uintptr_t nextIslandRegion;
+            if (jumpLocation > target)
+                nextIslandRegion = jumpLocation - regionSize;
+            else
+                nextIslandRegion = jumpLocation + regionSize;
+
+            RegionAllocator* allocator = findRegion(nextIslandRegion);
+            RELEASE_ASSERT(allocator);
+            void* nextIsland = allocator->allocateIsland();
+            emitJumpTo(nextIsland);
+            jumpLocation = bitwise_cast<uintptr_t>(nextIsland);
+            currentIsland = nextIsland;
+        }
+
+        return result;
+    }
+#endif // USE(JUMP_ISLANDS)
+
+private:
+    class Allocator : public MetaAllocator {
+        using Base = MetaAllocator;
+    public:
+        Allocator(FixedVMPoolExecutableAllocator& allocator)
+            : Base(allocator.getLock(), jitAllocationGranule, pageSize()) // round up all allocations to 32 bytes
+            , m_fixedAllocator(allocator)
+        {
+        }
+
+        FreeSpacePtr allocateNewSpace(size_t&) override
+        {
+            // We're operating in a fixed pool, so new allocation is always prohibited.
+            return nullptr;
+        }
+
+        void notifyNeedPage(void* page, size_t count) override
+        {
+            m_fixedAllocator.m_reservation.commit(page, pageSize() * count);
+        }
+
+        void notifyPageIsFree(void* page, size_t count) override
+        {
+            m_fixedAllocator.m_reservation.decommit(page, pageSize() * count);
+        }
+
+        FixedVMPoolExecutableAllocator& m_fixedAllocator;
+    };
+
+#if USE(JUMP_ISLANDS)
+    class RegionAllocator final : public Allocator {
+        using Base = Allocator;
+    public:
+        RegionAllocator(FixedVMPoolExecutableAllocator& allocator)
+            : Base(allocator)
+        {
+        }
+
+        //  ------------------------------------
+        //  | jit allocations -->   <-- islands |
+        //  -------------------------------------
+
+        uintptr_t start() { return bitwise_cast<uintptr_t>(untagCodePtr<ExecutableMemoryPtrTag>(m_start)); }
+        uintptr_t end() { return bitwise_cast<uintptr_t>(untagCodePtr<ExecutableMemoryPtrTag>(m_end)); }
+
+        uintptr_t islandBegin()
+        {
+            // [start, allocatorEnd)
+            return end() - islandRegionSize;
+        }
+
+        uintptr_t allocatorSize()
+        {
+            return islandBegin() - start();
+        }
+
+        size_t islandsPerPage()
+        {
+            size_t islandsPerPage = pageSize() / islandSizeInBytes;
+            ASSERT(islandsPerPage * islandSizeInBytes == pageSize());
+            ASSERT(isPowerOfTwo(islandsPerPage));
+            return islandsPerPage;
+        }
+
+        void release(const LockHolder& locker, MetaAllocatorHandle& handle) final
+        {
+            m_fixedAllocator.handleWillBeReleased(locker, handle);
+            Base::release(locker, handle);
+        }
+
+        void* allocateIsland()
+        {
+            uintptr_t end = this->end();
+            auto findResult = [&] () -> void* {
+                size_t resultBit = islandBits.findClearBit(0);
+                if (resultBit == islandBits.size())
+                    return nullptr;
+                islandBits[resultBit] = true;
+                uintptr_t result = end - ((resultBit + 1) * islandSizeInBytes); 
+                return bitwise_cast<void*>(result);
+            };
+
+            if (void* result = findResult())
+                return result;
+
+            islandBits.resize(islandBits.size() + islandsPerPage());
+            if (UNLIKELY(islandBits.size() > maxIslandsPerRegion))
+                crashOnJumpIslandExhaustion();
+
+            uintptr_t pageBegin = end - (islandBits.size() * islandSizeInBytes); // [islandBegin, end)
+            m_fixedAllocator.m_reservation.commit(bitwise_cast<void*>(pageBegin), pageSize());
+
+            void* result = findResult();
+            RELEASE_ASSERT(result);
+            return result;
+        }
+
+        NEVER_INLINE NO_RETURN_DUE_TO_CRASH void crashOnJumpIslandExhaustion()
+        {
+            CRASH();
+        }
+
+        Optional<size_t> islandBit(uintptr_t island)
+        {
+            uintptr_t end = this->end();
+            if (islandBegin() <= island && island < end)
+                return ((end - island) / islandSizeInBytes) - 1;
+            return WTF::nullopt;
+        }
+
+        void freeIsland(uintptr_t island)
+        {
+            RELEASE_ASSERT(islandBegin() <= island && island < end());
+            size_t bit = islandBit(island).value();
+            RELEASE_ASSERT(!!islandBits[bit]);
+            islandBits[bit] = false;
+        }
+
+        bool isInAllocatedMemory(const AbstractLocker& locker, void* address)
+        {
+            if (Base::isInAllocatedMemory(locker, address))
+                return true;
+            if (Optional<size_t> bit = islandBit(bitwise_cast<uintptr_t>(address))) {
+                if (bit.value() < islandBits.size())
+                    return !!islandBits[bit.value()];
+            }
+            return false;
+        }
+
+        // Range: [start, end)
+        void* m_start;
+        void* m_end;
+        FastBitVector islandBits;
+    };
+#endif // USE(JUMP_ISLANDS)
+
+    template <typename Function>
+    void forEachAllocator(Function function)
+    {
+#if USE(JUMP_ISLANDS)
+        for (RegionAllocator& allocator : m_allocators) {
+            using FunctionResultType = decltype(function(allocator));
+            if constexpr (std::is_same<IterationStatus, FunctionResultType>::value) {
+                if (function(allocator) == IterationStatus::Done)
+                    break;
+            } else {
+                static_assert(std::is_same<void, FunctionResultType>::value);
+                function(allocator);
+            }
+        }
+#else
+        function(m_allocator);
+#endif // USE(JUMP_ISLANDS)
+    }
+
+#if USE(JUMP_ISLANDS)
+    class Islands : public RedBlackTree<Islands, void*>::Node {
+        WTF_MAKE_FAST_ALLOCATED;
+    public:
+        void* key() { return jumpSourceLocation.dataLocation(); }
+        CodeLocationLabel<ExecutableMemoryPtrTag> jumpSourceLocation;
+        Vector<CodeLocationLabel<ExecutableMemoryPtrTag>> jumpIslands;
+    };
+#endif // USE(JUMP_ISLANDS)
+
+    Lock m_lock;
</ins><span class="cx">     PageReservation m_reservation;
</span><ins>+#if USE(JUMP_ISLANDS)
+    std::array<RegionAllocator, numberOfRegions> m_allocators;
+    RedBlackTree<Islands, void*> m_islandsForJumpSourceLocation;
+#else
+    Allocator m_allocator;
+#endif // USE(JUMP_ISLANDS)
</ins><span class="cx"> };
</span><span class="cx"> 
</span><del>-FixedVMPoolExecutableAllocator::~FixedVMPoolExecutableAllocator()
-{
-    m_reservation.deallocate();
-}
-
</del><span class="cx"> // Keep this pointer in a mutable global variable to help Leaks find it.
</span><span class="cx"> // But we do not use this pointer.
</span><span class="cx"> static FixedVMPoolExecutableAllocator* globalFixedVMPoolExecutableAllocatorToWorkAroundLeaks = nullptr;
</span><span class="lines">@@ -417,7 +839,6 @@
</span><span class="cx">     RELEASE_ASSERT(!g_jscConfig.fixedVMPoolExecutableAllocator);
</span><span class="cx">     g_jscConfig.fixedVMPoolExecutableAllocator = new FixedVMPoolExecutableAllocator();
</span><span class="cx">     globalFixedVMPoolExecutableAllocatorToWorkAroundLeaks = g_jscConfig.fixedVMPoolExecutableAllocator;
</span><del>-    CodeProfiling::notifyAllocator(g_jscConfig.fixedVMPoolExecutableAllocator);
</del><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> bool ExecutableAllocator::isValid() const
</span><span class="lines">@@ -425,7 +846,7 @@
</span><span class="cx">     FixedVMPoolExecutableAllocator* allocator = g_jscConfig.fixedVMPoolExecutableAllocator;
</span><span class="cx">     if (!allocator)
</span><span class="cx">         return Base::isValid();
</span><del>-    return !!allocator->bytesReserved();
</del><ins>+    return allocator->isValid();
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> bool ExecutableAllocator::underMemoryPressure()
</span><span class="lines">@@ -456,11 +877,11 @@
</span><span class="cx">     return result;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-RefPtr<ExecutableMemoryHandle> ExecutableAllocator::allocate(size_t sizeInBytes, void* ownerUID, JITCompilationEffort effort)
</del><ins>+RefPtr<ExecutableMemoryHandle> ExecutableAllocator::allocate(size_t sizeInBytes, JITCompilationEffort effort)
</ins><span class="cx"> {
</span><span class="cx">     FixedVMPoolExecutableAllocator* allocator = g_jscConfig.fixedVMPoolExecutableAllocator;
</span><span class="cx">     if (!allocator)
</span><del>-        return Base::allocate(sizeInBytes, ownerUID, effort);
</del><ins>+        return Base::allocate(sizeInBytes, effort);
</ins><span class="cx">     if (Options::logExecutableAllocation()) {
</span><span class="cx">         MetaAllocator::Statistics stats = allocator->currentStatistics();
</span><span class="cx">         dataLog("Allocating ", sizeInBytes, " bytes of executable memory with ", stats.bytesAllocated, " bytes allocated, ", stats.bytesReserved, " bytes reserved, and ", stats.bytesCommitted, " committed.\n");
</span><span class="lines">@@ -487,7 +908,7 @@
</span><span class="cx">         }
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    RefPtr<ExecutableMemoryHandle> result = allocator->allocate(sizeInBytes, ownerUID);
</del><ins>+    RefPtr<ExecutableMemoryHandle> result = allocator->allocate(sizeInBytes);
</ins><span class="cx">     if (!result) {
</span><span class="cx">         if (effort != JITCompilationCanFail) {
</span><span class="cx">             dataLog("Ran out of executable memory while allocating ", sizeInBytes, " bytes.\n");
</span><span class="lines">@@ -539,6 +960,26 @@
</span><span class="cx"> }
</span><span class="cx"> #endif
</span><span class="cx"> 
</span><ins>+#if USE(JUMP_ISLANDS)
+void* ExecutableAllocator::getJumpIslandTo(void* from, void* newDestination)
+{
+    FixedVMPoolExecutableAllocator* allocator = g_jscConfig.fixedVMPoolExecutableAllocator;
+    if (!allocator)
+        RELEASE_ASSERT_NOT_REACHED();
+
+    return allocator->makeIsland(bitwise_cast<uintptr_t>(from), bitwise_cast<uintptr_t>(newDestination), false);
+}
+
+void* ExecutableAllocator::getJumpIslandToConcurrently(void* from, void* newDestination)
+{
+    FixedVMPoolExecutableAllocator* allocator = g_jscConfig.fixedVMPoolExecutableAllocator;
+    if (!allocator)
+        RELEASE_ASSERT_NOT_REACHED();
+
+    return allocator->makeIsland(bitwise_cast<uintptr_t>(from), bitwise_cast<uintptr_t>(newDestination), true);
+}
+#endif
+
</ins><span class="cx"> void* startOfFixedExecutableMemoryPoolImpl()
</span><span class="cx"> {
</span><span class="cx">     FixedVMPoolExecutableAllocator* allocator = g_jscConfig.fixedVMPoolExecutableAllocator;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitExecutableAllocatorh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/ExecutableAllocator.h (259581 => 259582)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/ExecutableAllocator.h    2020-04-06 18:09:10 UTC (rev 259581)
+++ trunk/Source/JavaScriptCore/jit/ExecutableAllocator.h       2020-04-06 18:19:52 UTC (rev 259582)
</span><span class="lines">@@ -71,7 +71,7 @@
</span><span class="cx"> 
</span><span class="cx">     static void dumpProfile() { }
</span><span class="cx"> 
</span><del>-    RefPtr<ExecutableMemoryHandle> allocate(size_t, void*, JITCompilationEffort) { return nullptr; }
</del><ins>+    RefPtr<ExecutableMemoryHandle> allocate(size_t, JITCompilationEffort) { return nullptr; }
</ins><span class="cx"> 
</span><span class="cx">     static void setJITEnabled(bool) { };
</span><span class="cx">     
</span><span class="lines">@@ -158,7 +158,7 @@
</span><span class="cx"> public:
</span><span class="cx">     using Base = ExecutableAllocatorBase;
</span><span class="cx"> 
</span><del>-    static ExecutableAllocator& singleton();
</del><ins>+    JS_EXPORT_PRIVATE static ExecutableAllocator& singleton();
</ins><span class="cx">     static void initialize();
</span><span class="cx">     static void initializeUnderlyingAllocator();
</span><span class="cx"> 
</span><span class="lines">@@ -176,7 +176,7 @@
</span><span class="cx">     
</span><span class="cx">     JS_EXPORT_PRIVATE static void setJITEnabled(bool);
</span><span class="cx"> 
</span><del>-    RefPtr<ExecutableMemoryHandle> allocate(size_t sizeInBytes, void* ownerUID, JITCompilationEffort);
</del><ins>+    RefPtr<ExecutableMemoryHandle> allocate(size_t sizeInBytes, JITCompilationEffort);
</ins><span class="cx"> 
</span><span class="cx">     bool isValidExecutableMemory(const AbstractLocker&, void* address);
</span><span class="cx"> 
</span><span class="lines">@@ -184,6 +184,11 @@
</span><span class="cx"> 
</span><span class="cx">     Lock& getLock() const;
</span><span class="cx"> 
</span><ins>+#if USE(JUMP_ISLANDS)
+    JS_EXPORT_PRIVATE void* getJumpIslandTo(void* from, void* newDestination);
+    JS_EXPORT_PRIVATE void* getJumpIslandToConcurrently(void* from, void* newDestination);
+#endif
+
</ins><span class="cx"> private:
</span><span class="cx">     ExecutableAllocator() = default;
</span><span class="cx">     ~ExecutableAllocator() = default;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeCommonSlowPathscpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/CommonSlowPaths.cpp (259581 => 259582)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/CommonSlowPaths.cpp  2020-04-06 18:09:10 UTC (rev 259581)
+++ trunk/Source/JavaScriptCore/runtime/CommonSlowPaths.cpp     2020-04-06 18:19:52 UTC (rev 259582)
</span><span class="lines">@@ -32,7 +32,6 @@
</span><span class="cx"> #include "BytecodeStructs.h"
</span><span class="cx"> #include "CallFrame.h"
</span><span class="cx"> #include "ClonedArguments.h"
</span><del>-#include "CodeProfiling.h"
</del><span class="cx"> #include "DefinePropertyAttributes.h"
</span><span class="cx"> #include "DirectArguments.h"
</span><span class="cx"> #include "Error.h"
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeCompletioncpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/Completion.cpp (259581 => 259582)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/Completion.cpp       2020-04-06 18:09:10 UTC (rev 259581)
+++ trunk/Source/JavaScriptCore/runtime/Completion.cpp  2020-04-06 18:19:52 UTC (rev 259582)
</span><span class="lines">@@ -27,7 +27,6 @@
</span><span class="cx"> #include "CallFrame.h"
</span><span class="cx"> #include "CatchScope.h"
</span><span class="cx"> #include "CodeCache.h"
</span><del>-#include "CodeProfiling.h"
</del><span class="cx"> #include "Exception.h"
</span><span class="cx"> #include "IdentifierInlines.h"
</span><span class="cx"> #include "Interpreter.h"
</span><span class="lines">@@ -138,8 +137,6 @@
</span><span class="cx">     RELEASE_ASSERT(vm.atomStringTable() == Thread::current().atomStringTable());
</span><span class="cx">     RELEASE_ASSERT(!vm.isCollectorBusyOnCurrentThread());
</span><span class="cx"> 
</span><del>-    CodeProfiling profile(source);
-
</del><span class="cx">     if (!thisValue || thisValue.isUndefinedOrNull())
</span><span class="cx">         thisValue = globalObject;
</span><span class="cx">     JSObject* thisObj = jsCast<JSObject*>(thisValue.toThis(globalObject, NotStrictMode));
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeJSModuleLoadercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/JSModuleLoader.cpp (259581 => 259582)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/JSModuleLoader.cpp   2020-04-06 18:09:10 UTC (rev 259581)
+++ trunk/Source/JavaScriptCore/runtime/JSModuleLoader.cpp      2020-04-06 18:19:52 UTC (rev 259582)
</span><span class="lines">@@ -29,7 +29,6 @@
</span><span class="cx"> 
</span><span class="cx"> #include "BuiltinNames.h"
</span><span class="cx"> #include "CatchScope.h"
</span><del>-#include "CodeProfiling.h"
</del><span class="cx"> #include "Error.h"
</span><span class="cx"> #include "Exception.h"
</span><span class="cx"> #include "JSCInlines.h"
</span><span class="lines">@@ -400,8 +399,6 @@
</span><span class="cx">         return JSValue::encode(JSWebAssembly::instantiate(globalObject, promise, moduleKey, jsSourceCode));
</span><span class="cx"> #endif
</span><span class="cx"> 
</span><del>-    CodeProfiling profile(sourceCode);
-
</del><span class="cx">     ParserError error;
</span><span class="cx">     std::unique_ptr<ModuleProgramNode> moduleProgramNode = parse<ModuleProgramNode>(
</span><span class="cx">         vm, sourceCode, Identifier(), JSParserBuiltinMode::NotBuiltin,
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeOptionsListh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/OptionsList.h (259581 => 259582)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/OptionsList.h        2020-04-06 18:09:10 UTC (rev 259581)
+++ trunk/Source/JavaScriptCore/runtime/OptionsList.h   2020-04-06 18:19:52 UTC (rev 259582)
</span><span class="lines">@@ -500,6 +500,7 @@
</span><span class="cx">     v(Bool, forceOSRExitToLLInt, false, Normal, "If true, we always exit to the LLInt. If false, we exit to whatever is most convenient.") \
</span><span class="cx">     v(Unsigned, getByValICMaxNumberOfIdentifiers, 4, Normal, "Number of identifiers we see in the LLInt that could cause us to bail on generating an IC for get_by_val.") \
</span><span class="cx">     v(Bool, usePublicClassFields, true, Normal, "If true, the parser will understand public data fields inside classes.") \
</span><ins>+    v(Bool, useRandomizingExecutableIslandAllocation, false, Normal, "For the arm64 ExecutableAllocator, if true, select which region to use randomly. This is useful for testing that jump islands work.") \
</ins><span class="cx"> 
</span><span class="cx"> enum OptionEquivalence {
</span><span class="cx">     SameOption,
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoretoolsCodeProfilecpp"></a>
<div class="delfile"><h4>Deleted: trunk/Source/JavaScriptCore/tools/CodeProfile.cpp (259581 => 259582)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/tools/CodeProfile.cpp        2020-04-06 18:09:10 UTC (rev 259581)
+++ trunk/Source/JavaScriptCore/tools/CodeProfile.cpp   2020-04-06 18:19:52 UTC (rev 259582)
</span><span class="lines">@@ -1,172 +0,0 @@
</span><del>-/*
- * Copyright (C) 2012 Apple Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
- */
-
-#include "config.h"
-#include "CodeProfile.h"
-
-#include "CodeBlock.h"
-#include "CodeProfiling.h"
-#include "LinkBuffer.h"
-#include "ProfileTreeNode.h"
-#include <wtf/StackTrace.h>
-#include <wtf/text/WTFString.h>
-
-namespace JSC {
-
-// Map from CodeType enum to a corresponding name.
-static const char* const s_codeTypeNames[CodeProfile::NumberOfCodeTypes] = {
-    "[[EngineCode]]",
-    "[[GlobalThunk]]",
-    "[[RegExpCode]]",
-    "[[DFGJIT]]",
-    "[[BaselineOnly]]",
-    "[[BaselineProfile]]",
-    "[[BaselineOSR]]",
-    "[[EngineFrame]]"
-};
-
-// Helper function, truncate traces to prune the output & make very verbose mode a little more readable.
-static bool truncateTrace(const char* symbolName)
-{
-    return !strcmp(symbolName, "JSC::BytecodeGenerator::generate()")
-        || !strcmp(symbolName, "JSC::Parser<JSC::Lexer<unsigned char>>::parseInner()")
-        || !strcmp(symbolName, "WTF::fastMalloc(unsigned long)")
-        || !strcmp(symbolName, "WTF::calculateUTCOffset()")
-        || !strcmp(symbolName, "JSC::DFG::ByteCodeParser::parseCodeBlock()");
-        
-}
-
-// Each trace consists of a sequence of zero or more 'EngineFrame' entries,
-// followed by a sample in JIT code, or one or more 'EngineFrame' entries,
-// followed by a 'EngineCode' terminator.
-void CodeProfile::sample(void* pc, void** framePointer)
-{
-    // Disallow traces containing only a 'EngineCode' terminator, without any 'EngineFrame' frames.
-    if (!framePointer)
-        return;
-
-    while (framePointer) {
-        CodeType type;
-
-#if ENABLE(JIT)
-        // Determine if this sample fell in JIT code, and if so, from which JIT & why.
-        void* ownerUID = CodeProfiling::getOwnerUIDForPC(pc);
-
-        if (!ownerUID)
-            type = EngineFrame;
-        else if (ownerUID == GLOBAL_THUNK_ID)
-            type = GlobalThunk;
-        else if (ownerUID == REGEXP_CODE_ID)
-            type = RegExpCode;
-        else {
-            CodeBlock* codeBlock = static_cast<CodeBlock*>(ownerUID);
-            if (codeBlock->jitType() == JITType::DFGJIT)
-                type = DFGJIT;
-            else if (!canCompile(codeBlock->capabilityLevelState()))
-                type = BaselineOnly;
-            else if (codeBlock->replacement())
-                type = BaselineOSR;
-            else
-                type = BaselineProfile;
-        }
-#else
-        type = EngineFrame;
-#endif
-
-        // A sample in JIT code terminates the trace.
-        m_samples.append(CodeRecord(pc, type));
-        if (type != EngineFrame)
-            return;
-
-#if OS(DARWIN) && CPU(X86_64)
-        // Walk up the stack.
-        pc = framePointer[1];
-        framePointer = reinterpret_cast<void**>(*framePointer);
-#elif OS(LINUX) && CPU(X86)
-        // Don't unwind the stack as some dependent third party libraries
-        // may be compiled with -fomit-frame-pointer.
-        framePointer = 0;
-#else
-        // This platform is not yet supported!
-        RELEASE_ASSERT_NOT_REACHED();
-#endif
-    }
-
-    // If we get here, we walked the entire stack without finding any frames of JIT code.
-    m_samples.append(CodeRecord(0, EngineCode));
-}
-
-void CodeProfile::report()
-{
-    dataLogF("<CodeProfiling %s:%d>\n", m_file.data(), m_lineNumber);
-
-    // How many frames of C-code to print - 0, if not verbose, 1 if verbose, up to 1024 if very verbose.
-    unsigned recursionLimit = CodeProfiling::beVeryVerbose() ? 1024 : CodeProfiling::beVerbose();
-
-    ProfileTreeNode profile;
-
-    // Walk through the sample buffer.
-    size_t trace = 0;
-    while (trace < m_samples.size()) {
-
-        // All traces are zero or more 'EngineFrame's, followed by a non-'EngineFrame'.
-        // Scan to find the last sample in the trace.
-        size_t lastInTrace = trace;
-        while (m_samples[lastInTrace].type == EngineFrame)
-            ++lastInTrace;
-
-        // We use the last sample type to look up a name (used as a bucket in the profiler).
-        ProfileTreeNode* callbacks = profile.sampleChild(s_codeTypeNames[m_samples[lastInTrace].type]);
-
-        // If there are any samples in C-code, add up to recursionLimit of them into the profile tree.
-        size_t lastEngineFrame = lastInTrace;
-        for (unsigned count = 0; lastEngineFrame > trace && count < recursionLimit; ++count) {
-            --lastEngineFrame;
-            ASSERT(m_samples[lastEngineFrame].type == EngineFrame);
-            const char* name = "<unknown>";
-            auto demangled = StackTrace::demangle(m_samples[lastEngineFrame].pc);
-            if (demangled)
-                name = demangled->demangledName() ? demangled->demangledName() : demangled->mangledName();
-            callbacks = callbacks->sampleChild(name);
-            if (truncateTrace(name))
-                break;
-        }
-
-        // Move on to the next trace.
-        trace = lastInTrace + 1;
-        ASSERT(trace <= m_samples.size());
-    }
-
-    // Output the profile tree.
-    dataLogF("Total samples: %lld\n", static_cast<long long>(profile.childCount()));
-    profile.dump();
-    
-    for (size_t i = 0 ; i < m_children.size(); ++i)
-        m_children[i]->report();
-
-    dataLogF("</CodeProfiling %s:%d>\n", m_file.data(), m_lineNumber);
-}
-
-}
</del></span></pre></div>
<a id="trunkSourceJavaScriptCoretoolsCodeProfileh"></a>
<div class="delfile"><h4>Deleted: trunk/Source/JavaScriptCore/tools/CodeProfile.h (259581 => 259582)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/tools/CodeProfile.h  2020-04-06 18:09:10 UTC (rev 259581)
+++ trunk/Source/JavaScriptCore/tools/CodeProfile.h     2020-04-06 18:19:52 UTC (rev 259582)
</span><span class="lines">@@ -1,89 +0,0 @@
</span><del>-/*
- * Copyright (C) 2012 Apple Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
- */
-
-#pragma once
-
-#include "SourceCode.h"
-#include "TieredMMapArray.h"
-#include <wtf/text/CString.h>
-
-namespace JSC {
-
-class CodeProfile {
-    WTF_MAKE_FAST_ALLOCATED;
-public:
-    CodeProfile(const SourceCode& source, CodeProfile* parent)
-        : m_file(String(source.provider()->url()).utf8())
-        , m_lineNumber(source.firstLine().oneBasedInt())
-        , m_parent(parent)
-    {
-        if (parent)
-            parent->addChild(std::unique_ptr<CodeProfile>(this));
-    }
-
-    void sample(void* pc, void** framePointer);
-    void report();
-
-    CodeProfile* parent()
-    {
-        return m_parent;
-    }
-    
-    void addChild(std::unique_ptr<CodeProfile> child)
-    {
-        m_children.append(WTFMove(child));
-    }
-
-    enum CodeType {
-        EngineCode,
-        GlobalThunk,
-        RegExpCode,
-        DFGJIT,
-        BaselineOnly,
-        BaselineProfile,
-        BaselineOSR,
-        EngineFrame,
-        NumberOfCodeTypes
-    };
-
-private:
-    struct CodeRecord {
-        CodeRecord(void* pc, CodeType type)
-            : pc(pc)
-            , type(type)
-        {
-        }
-        void* pc;
-        CodeType type;
-    };
-
-    CString m_file;
-    unsigned m_lineNumber;
-    CodeProfile* m_parent;
-    Vector<std::unique_ptr<CodeProfile>> m_children;
-    TieredMMapArray<CodeRecord> m_samples;
-};
-
-} // namespace JSC
</del></span></pre></div>
<a id="trunkSourceJavaScriptCoretoolsCodeProfilingcpp"></a>
<div class="delfile"><h4>Deleted: trunk/Source/JavaScriptCore/tools/CodeProfiling.cpp (259581 => 259582)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/tools/CodeProfiling.cpp      2020-04-06 18:09:10 UTC (rev 259581)
+++ trunk/Source/JavaScriptCore/tools/CodeProfiling.cpp 2020-04-06 18:19:52 UTC (rev 259582)
</span><span class="lines">@@ -1,169 +0,0 @@
</span><del>-/*
- * Copyright (C) 2012-2018 Apple Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
- */
-
-#include "config.h"
-#include "CodeProfiling.h"
-
-#include "CodeProfile.h"
-#include "MachineContext.h"
-#include <wtf/MetaAllocator.h>
-
-#if HAVE(SIGNAL_H)
-#include <signal.h>
-#endif
-
-#if HAVE(MACHINE_CONTEXT)
-#include <sys/time.h>
-#endif
-
-namespace JSC {
-
-volatile CodeProfile* CodeProfiling::s_profileStack = 0;
-CodeProfiling::Mode CodeProfiling::s_mode = CodeProfiling::Disabled;
-WTF::MetaAllocatorTracker* CodeProfiling::s_tracker = 0;
-
-IGNORE_WARNINGS_BEGIN("missing-noreturn")
-
-#if HAVE(MACHINE_CONTEXT)
-// Helper function to start & stop the timer.
-// Presently we're using the wall-clock timer, since this seems to give the best results.
-static void setProfileTimer(unsigned usec)
-{
-    itimerval timer;
-    timer.it_value.tv_sec = 0;
-    timer.it_value.tv_usec = usec;
-    timer.it_interval.tv_sec = 0;
-    timer.it_interval.tv_usec = usec;
-    setitimer(ITIMER_REAL, &timer, 0);
-}
-#endif
-
-IGNORE_WARNINGS_END
-
-#if HAVE(MACHINE_CONTEXT)
-static void profilingTimer(int, siginfo_t*, void* uap)
-{
-    PlatformRegisters& platformRegisters = WTF::registersFromUContext(static_cast<ucontext_t*>(uap));
-    if (auto instructionPointer = MachineContext::instructionPointer(platformRegisters)) {
-        CodeProfiling::sample(
-            instructionPointer->untaggedExecutableAddress(),
-            reinterpret_cast<void**>(MachineContext::framePointer(platformRegisters)));
-    }
-}
-#endif
-
-// Callback triggered when the timer is fired.
-void CodeProfiling::sample(void* pc, void** framePointer)
-{
-    CodeProfile* profileStack = const_cast<CodeProfile*>(s_profileStack);
-    if (profileStack)
-        profileStack->sample(pc, framePointer);
-}
-
-void CodeProfiling::notifyAllocator(WTF::MetaAllocator* allocator)
-{
-    // Check for JSC_CODE_PROFILING.
-    const char* codeProfilingMode = getenv("JSC_CODE_PROFILING");
-    if (!codeProfilingMode)
-        return;
-
-    // Check for a valid mode, currently "1", "2", or "3".
-    if (!codeProfilingMode[0] || codeProfilingMode[1])
-        return;
-    switch (*codeProfilingMode) {
-    case '1':
-        s_mode = Enabled;
-        break;
-    case '2':
-        s_mode = Verbose;
-        break;
-    case '3':
-        s_mode = VeryVerbose;
-        break;
-    default:
-        return;
-    }
-
-    ASSERT(enabled());
-    ASSERT(!s_tracker);
-    s_tracker = new WTF::MetaAllocatorTracker();
-    allocator->trackAllocations(s_tracker);
-}
-
-void* CodeProfiling::getOwnerUIDForPC(void* address)
-{
-    if (!s_tracker)
-        return 0;
-    WTF::MetaAllocatorHandle* handle = s_tracker->find(address);
-    if (!handle)
-        return 0;
-    return handle->ownerUID();
-}
-
-void CodeProfiling::begin(const SourceCode& source)
-{
-    // Push a new CodeProfile onto the stack for each script encountered.
-    CodeProfile* profileStack = const_cast<CodeProfile*>(s_profileStack);
-    bool alreadyProfiling = profileStack;
-    s_profileStack = profileStack = new CodeProfile(source, profileStack);
-
-    // Is the profiler already running - if so, the timer will already be set up.
-    if (alreadyProfiling)
-        return;
-
-#if HAVE(MACHINE_CONTEXT)
-    // Regsiter a signal handler & itimer.
-    struct sigaction action;
-    action.sa_sigaction = reinterpret_cast<void (*)(int, siginfo_t *, void *)>(profilingTimer);
-    sigfillset(&action.sa_mask);
-    action.sa_flags = SA_SIGINFO;
-    sigaction(SIGALRM, &action, 0);
-    setProfileTimer(100);
-#endif
-}
-
-void CodeProfiling::end()
-{
-    // Pop the current profiler off the stack.
-    CodeProfile* current = const_cast<CodeProfile*>(s_profileStack);
-    ASSERT(current);
-    s_profileStack = current->parent();
-
-    // Is this the outermost script being profiled? - if not, just return.
-    // We perform all output of profiles recursively from the outermost script,
-    // to minimize profiling overhead from skewing results.
-    if (s_profileStack)
-        return;
-
-#if HAVE(MACHINE_CONTEXT)
-    // Stop profiling
-    setProfileTimer(0);
-#endif
-
-    current->report();
-    delete current;
-}
-
-}
</del></span></pre></div>
<a id="trunkSourceJavaScriptCoretoolsCodeProfilingh"></a>
<div class="delfile"><h4>Deleted: trunk/Source/JavaScriptCore/tools/CodeProfiling.h (259581 => 259582)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/tools/CodeProfiling.h        2020-04-06 18:09:10 UTC (rev 259581)
+++ trunk/Source/JavaScriptCore/tools/CodeProfiling.h   2020-04-06 18:19:52 UTC (rev 259582)
</span><span class="lines">@@ -1,81 +0,0 @@
</span><del>-/*
- * Copyright (C) 2012 Apple Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
- */
-
-#pragma once
-
-namespace WTF {
-
-class MetaAllocator;
-class MetaAllocatorTracker;
-
-}
-
-namespace JSC {
-
-class CodeProfile;
-class SourceCode;
-
-class CodeProfiling {
-    enum Mode {
-        Disabled,
-        Enabled,
-        Verbose,
-        VeryVerbose
-    };
-
-public:
-    CodeProfiling(const SourceCode& source)
-        : m_active(enabled())
-    {
-        if (m_active)
-            begin(source);
-    }
-
-    ~CodeProfiling()
-    {
-        if (m_active)
-            end();
-    }
-
-    static bool enabled() { return s_mode != Disabled; }
-    static bool beVerbose() { return s_mode >= Verbose; }
-    static bool beVeryVerbose() { return s_mode >= VeryVerbose; }
-
-    static void notifyAllocator(WTF::MetaAllocator*);
-    static void* getOwnerUIDForPC(void*);
-    static void sample(void* pc, void** framePointer);
-
-private:
-    void begin(const SourceCode&);
-    void end();
-
-    bool m_active;
-
-    static Mode s_mode;
-    static WTF::MetaAllocatorTracker* s_tracker;
-    static volatile CodeProfile* s_profileStack;
-};
-
-} // namespace JSC
</del></span></pre></div>
<a id="trunkSourceJavaScriptCorewasmWasmBBQPlancpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/wasm/WasmBBQPlan.cpp (259581 => 259582)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/wasm/WasmBBQPlan.cpp 2020-04-06 18:09:10 UTC (rev 259581)
+++ trunk/Source/JavaScriptCore/wasm/WasmBBQPlan.cpp    2020-04-06 18:19:52 UTC (rev 259582)
</span><span class="lines">@@ -132,13 +132,9 @@
</span><span class="cx">         // will update. It's also ok if they publish their code before we reset the instruction caches because after we release
</span><span class="cx">         // the lock our code is ready to be published too.
</span><span class="cx">         LockHolder holder(m_codeBlock->m_lock);
</span><ins>+
</ins><span class="cx">         m_codeBlock->m_bbqCallees[m_functionIndex] = callee.copyRef();
</span><del>-        {
-            LLIntCallee& llintCallee = m_codeBlock->m_llintCallees->at(m_functionIndex).get();
-            auto locker = holdLock(llintCallee.tierUpCounter().m_lock);
-            llintCallee.setReplacement(callee.copyRef());
-            llintCallee.tierUpCounter().m_compilationStatus = LLIntTierUpCounter::CompilationStatus::Compiled;
-        }
</del><ins>+
</ins><span class="cx">         for (auto& call : callee->wasmToWasmCallsites()) {
</span><span class="cx">             MacroAssemblerCodePtr<WasmEntryPtrTag> entrypoint;
</span><span class="cx">             if (call.functionIndexSpace < m_moduleInformation->importFunctionCount())
</span><span class="lines">@@ -148,49 +144,19 @@
</span><span class="cx"> 
</span><span class="cx">             MacroAssembler::repatchNearCall(call.callLocation, CodeLocationLabel<WasmEntryPtrTag>(entrypoint));
</span><span class="cx">         }
</span><del>-    }
</del><span class="cx"> 
</span><del>-    // It's important to make sure we do this before we make any of the code we just compiled visible. If we didn't, we could end up
-    // where we are tiering up some function A to A' and we repatch some function B to call A' instead of A. Another CPU could see
-    // the updates to B but still not have reset its cache of A', which would lead to all kinds of badness.
-    resetInstructionCacheOnAllThreads();
-    WTF::storeStoreFence(); // This probably isn't necessary but it's good to be paranoid.
</del><ins>+        Plan::updateCallSitesToCallUs(*m_codeBlock, CodeLocationLabel<WasmEntryPtrTag>(entrypoint), m_functionIndex, functionIndexSpace);
</ins><span class="cx"> 
</span><del>-    m_codeBlock->m_wasmIndirectCallEntryPoints[m_functionIndex] = entrypoint;
-    {
-        LockHolder holder(m_codeBlock->m_lock);
-
-        auto repatchCalls = [&] (const Vector<UnlinkedWasmToWasmCall>& callsites) {
-            for (auto& call : callsites) {
-                dataLogLnIf(WasmBBQPlanInternal::verbose, "Considering repatching call at: ", RawPointer(call.callLocation.dataLocation()), " that targets ", call.functionIndexSpace);
-                if (call.functionIndexSpace == functionIndexSpace) {
-                    dataLogLnIf(WasmBBQPlanInternal::verbose, "Repatching call at: ", RawPointer(call.callLocation.dataLocation()), " to ", RawPointer(entrypoint.executableAddress()));
-                    MacroAssembler::repatchNearCall(call.callLocation, CodeLocationLabel<WasmEntryPtrTag>(entrypoint));
-                }
-            }
-        };
-
-        for (unsigned i = 0; i < m_codeBlock->m_wasmToWasmCallsites.size(); ++i) {
-            repatchCalls(m_codeBlock->m_wasmToWasmCallsites[i]);
-            if (m_codeBlock->m_llintCallees) {
-                LLIntCallee& llintCallee = m_codeBlock->m_llintCallees->at(i).get();
-                if (JITCallee* replacementCallee = llintCallee.replacement())
-                    repatchCalls(replacementCallee->wasmToWasmCallsites());
-                if (OMGForOSREntryCallee* osrEntryCallee = llintCallee.osrEntryCallee())
-                    repatchCalls(osrEntryCallee->wasmToWasmCallsites());
-            }
-            if (BBQCallee* bbqCallee = m_codeBlock->m_bbqCallees[i].get()) {
-                if (OMGCallee* replacementCallee = bbqCallee->replacement())
-                    repatchCalls(replacementCallee->wasmToWasmCallsites());
-                if (OMGForOSREntryCallee* osrEntryCallee = bbqCallee->osrEntryCallee())
-                    repatchCalls(osrEntryCallee->wasmToWasmCallsites());
-            }
</del><ins>+        {
+            LLIntCallee& llintCallee = m_codeBlock->m_llintCallees->at(m_functionIndex).get();
+            auto locker = holdLock(llintCallee.tierUpCounter().m_lock);
+            llintCallee.setReplacement(callee.copyRef());
+            llintCallee.tierUpCounter().m_compilationStatus = LLIntTierUpCounter::CompilationStatus::Compiled;
</ins><span class="cx">         }
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     dataLogLnIf(WasmBBQPlanInternal::verbose, "Finished BBQ ", m_functionIndex);
</span><span class="cx"> 
</span><del>-
</del><span class="cx">     auto locker = holdLock(m_lock);
</span><span class="cx">     moveToState(State::Completed);
</span><span class="cx">     runCompletionTasks(locker);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorewasmWasmCodeBlockh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/wasm/WasmCodeBlock.h (259581 => 259582)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/wasm/WasmCodeBlock.h 2020-04-06 18:09:10 UTC (rev 259581)
+++ trunk/Source/JavaScriptCore/wasm/WasmCodeBlock.h    2020-04-06 18:19:52 UTC (rev 259582)
</span><span class="lines">@@ -124,6 +124,7 @@
</span><span class="cx"> 
</span><span class="cx">     ~CodeBlock();
</span><span class="cx"> private:
</span><ins>+    friend class Plan;
</ins><span class="cx">     friend class BBQPlan;
</span><span class="cx">     friend class OMGPlan;
</span><span class="cx">     friend class OMGForOSREntryPlan;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorewasmWasmOMGForOSREntryPlancpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/wasm/WasmOMGForOSREntryPlan.cpp (259581 => 259582)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/wasm/WasmOMGForOSREntryPlan.cpp      2020-04-06 18:09:10 UTC (rev 259581)
+++ trunk/Source/JavaScriptCore/wasm/WasmOMGForOSREntryPlan.cpp 2020-04-06 18:19:52 UTC (rev 259582)
</span><span class="lines">@@ -103,12 +103,10 @@
</span><span class="cx"> 
</span><span class="cx">     omgEntrypoint.calleeSaveRegisters = WTFMove(parseAndCompileResult.value()->entrypoint.calleeSaveRegisters);
</span><span class="cx"> 
</span><del>-    MacroAssemblerCodePtr<WasmEntryPtrTag> entrypoint;
</del><span class="cx">     ASSERT(m_codeBlock.ptr() == m_module->codeBlockFor(mode()));
</span><span class="cx">     Ref<OMGForOSREntryCallee> callee = OMGForOSREntryCallee::create(WTFMove(omgEntrypoint), functionIndexSpace, m_moduleInformation->nameSection->get(functionIndexSpace), osrEntryScratchBufferSize, m_loopIndex, WTFMove(unlinkedCalls));
</span><span class="cx">     {
</span><span class="cx">         MacroAssembler::repatchPointer(parseAndCompileResult.value()->calleeMoveLocation, CalleeBits::boxWasm(callee.ptr()));
</span><del>-        entrypoint = callee->entrypoint();
</del><span class="cx"> 
</span><span class="cx">         auto locker = holdLock(m_codeBlock->m_lock);
</span><span class="cx">         for (auto& call : callee->wasmToWasmCallsites()) {
</span><span class="lines">@@ -120,11 +118,10 @@
</span><span class="cx"> 
</span><span class="cx">             MacroAssembler::repatchNearCall(call.callLocation, CodeLocationLabel<WasmEntryPtrTag>(entrypoint));
</span><span class="cx">         }
</span><del>-    }
-    resetInstructionCacheOnAllThreads();
-    WTF::storeStoreFence();
-    {
-        auto locker = holdLock(m_codeBlock->m_lock);
</del><ins>+
+        resetInstructionCacheOnAllThreads();
+        WTF::storeStoreFence();
+
</ins><span class="cx">         {
</span><span class="cx">             switch (m_callee->compilationMode()) {
</span><span class="cx">             case CompilationMode::LLIntMode: {
</span><span class="lines">@@ -146,19 +143,6 @@
</span><span class="cx">                 RELEASE_ASSERT_NOT_REACHED();
</span><span class="cx">             }
</span><span class="cx">         }
</span><del>-        WTF::storeStoreFence();
-        // It is possible that a new OMG callee is added while we release m_codeBlock->lock.
-        // Until we add OMGForOSREntry callee to BBQCallee's m_osrEntryCallee, this new OMG function linking does not happen for this OMGForOSREntry callee.
-        // We re-link this OMGForOSREntry callee again not to miss that chance.
-        for (auto& call : callee->wasmToWasmCallsites()) {
-            MacroAssemblerCodePtr<WasmEntryPtrTag> entrypoint;
-            if (call.functionIndexSpace < m_module->moduleInformation().importFunctionCount())
-                entrypoint = m_codeBlock->m_wasmToWasmExitStubs[call.functionIndexSpace].code();
-            else
-                entrypoint = m_codeBlock->wasmEntrypointCalleeFromFunctionIndexSpace(call.functionIndexSpace).entrypoint().retagged<WasmEntryPtrTag>();
-
-            MacroAssembler::repatchNearCall(call.callLocation, CodeLocationLabel<WasmEntryPtrTag>(entrypoint));
-        }
</del><span class="cx">     }
</span><span class="cx">     dataLogLnIf(WasmOMGForOSREntryPlanInternal::verbose, "Finished OMGForOSREntry ", m_functionIndex);
</span><span class="cx">     complete(holdLock(m_lock));
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorewasmWasmOMGPlancpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/wasm/WasmOMGPlan.cpp (259581 => 259582)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/wasm/WasmOMGPlan.cpp 2020-04-06 18:09:10 UTC (rev 259581)
+++ trunk/Source/JavaScriptCore/wasm/WasmOMGPlan.cpp    2020-04-06 18:19:52 UTC (rev 259582)
</span><span class="lines">@@ -114,20 +114,9 @@
</span><span class="cx">         // will update. It's also ok if they publish their code before we reset the instruction caches because after we release
</span><span class="cx">         // the lock our code is ready to be published too.
</span><span class="cx">         LockHolder holder(m_codeBlock->m_lock);
</span><ins>+
</ins><span class="cx">         m_codeBlock->m_omgCallees[m_functionIndex] = callee.copyRef();
</span><del>-        {
-            if (BBQCallee* bbqCallee = m_codeBlock->m_bbqCallees[m_functionIndex].get()) {
-                auto locker = holdLock(bbqCallee->tierUpCount()->getLock());
-                bbqCallee->setReplacement(callee.copyRef());
-                bbqCallee->tierUpCount()->m_compilationStatusForOMG = TierUpCount::CompilationStatus::Compiled;
-            }
-            if (m_codeBlock->m_llintCallees) {
-                LLIntCallee& llintCallee = m_codeBlock->m_llintCallees->at(m_functionIndex).get();
-                auto locker = holdLock(llintCallee.tierUpCounter().m_lock);
-                llintCallee.setReplacement(callee.copyRef());
-                llintCallee.tierUpCounter().m_compilationStatus = LLIntTierUpCounter::CompilationStatus::Compiled;
-            }
-        }
</del><ins>+
</ins><span class="cx">         for (auto& call : callee->wasmToWasmCallsites()) {
</span><span class="cx">             MacroAssemblerCodePtr<WasmEntryPtrTag> entrypoint;
</span><span class="cx">             if (call.functionIndexSpace < m_module->moduleInformation().importFunctionCount())
</span><span class="lines">@@ -137,43 +126,21 @@
</span><span class="cx"> 
</span><span class="cx">             MacroAssembler::repatchNearCall(call.callLocation, CodeLocationLabel<WasmEntryPtrTag>(entrypoint));
</span><span class="cx">         }
</span><del>-    }
</del><span class="cx"> 
</span><del>-    // It's important to make sure we do this before we make any of the code we just compiled visible. If we didn't, we could end up
-    // where we are tiering up some function A to A' and we repatch some function B to call A' instead of A. Another CPU could see
-    // the updates to B but still not have reset its cache of A', which would lead to all kinds of badness.
-    resetInstructionCacheOnAllThreads();
-    WTF::storeStoreFence(); // This probably isn't necessary but it's good to be paranoid.
</del><ins>+        Plan::updateCallSitesToCallUs(m_codeBlock, CodeLocationLabel<WasmEntryPtrTag>(entrypoint), m_functionIndex, functionIndexSpace);
</ins><span class="cx"> 
</span><del>-    m_codeBlock->m_wasmIndirectCallEntryPoints[m_functionIndex] = entrypoint;
-    {
-        LockHolder holder(m_codeBlock->m_lock);
-
-        auto repatchCalls = [&] (const Vector<UnlinkedWasmToWasmCall>& callsites) {
-            for (auto& call : callsites) {
-                dataLogLnIf(WasmOMGPlanInternal::verbose, "Considering repatching call at: ", RawPointer(call.callLocation.dataLocation()), " that targets ", call.functionIndexSpace);
-                if (call.functionIndexSpace == functionIndexSpace) {
-                    dataLogLnIf(WasmOMGPlanInternal::verbose, "Repatching call at: ", RawPointer(call.callLocation.dataLocation()), " to ", RawPointer(entrypoint.executableAddress()));
-                    MacroAssembler::repatchNearCall(call.callLocation, CodeLocationLabel<WasmEntryPtrTag>(entrypoint));
-                }
</del><ins>+        {
+            if (BBQCallee* bbqCallee = m_codeBlock->m_bbqCallees[m_functionIndex].get()) {
+                auto locker = holdLock(bbqCallee->tierUpCount()->getLock());
+                bbqCallee->setReplacement(callee.copyRef());
+                bbqCallee->tierUpCount()->m_compilationStatusForOMG = TierUpCount::CompilationStatus::Compiled;
</ins><span class="cx">             }
</span><del>-        };
-
-        for (unsigned i = 0; i < m_codeBlock->m_wasmToWasmCallsites.size(); ++i) {
-            repatchCalls(m_codeBlock->m_wasmToWasmCallsites[i]);
</del><span class="cx">             if (m_codeBlock->m_llintCallees) {
</span><del>-                LLIntCallee& llintCallee = m_codeBlock->m_llintCallees->at(i).get();
-                if (JITCallee* replacementCallee = llintCallee.replacement())
-                    repatchCalls(replacementCallee->wasmToWasmCallsites());
-                if (OMGForOSREntryCallee* osrEntryCallee = llintCallee.osrEntryCallee())
-                    repatchCalls(osrEntryCallee->wasmToWasmCallsites());
</del><ins>+                LLIntCallee& llintCallee = m_codeBlock->m_llintCallees->at(m_functionIndex).get();
+                auto locker = holdLock(llintCallee.tierUpCounter().m_lock);
+                llintCallee.setReplacement(callee.copyRef());
+                llintCallee.tierUpCounter().m_compilationStatus = LLIntTierUpCounter::CompilationStatus::Compiled;
</ins><span class="cx">             }
</span><del>-            if (BBQCallee* bbqCallee = m_codeBlock->m_bbqCallees[i].get()) {
-                if (OMGCallee* replacementCallee = bbqCallee->replacement())
-                    repatchCalls(replacementCallee->wasmToWasmCallsites());
-                if (OMGForOSREntryCallee* osrEntryCallee = bbqCallee->osrEntryCallee())
-                    repatchCalls(osrEntryCallee->wasmToWasmCallsites());
-            }
</del><span class="cx">         }
</span><span class="cx">     }
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorewasmWasmPlancpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/wasm/WasmPlan.cpp (259581 => 259582)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/wasm/WasmPlan.cpp    2020-04-06 18:09:10 UTC (rev 259581)
+++ trunk/Source/JavaScriptCore/wasm/WasmPlan.cpp       2020-04-06 18:19:52 UTC (rev 259582)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> /*
</span><del>- * Copyright (C) 2016-2019 Apple Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2016-2020 Apple Inc. All rights reserved.
</ins><span class="cx">  *
</span><span class="cx">  * Redistribution and use in source and binary forms, with or without
</span><span class="cx">  * modification, are permitted provided that the following conditions
</span><span class="lines">@@ -129,6 +129,71 @@
</span><span class="cx">     complete(locker);
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void Plan::updateCallSitesToCallUs(CodeBlock& codeBlock, CodeLocationLabel<WasmEntryPtrTag> entrypoint, uint32_t functionIndex, uint32_t functionIndexSpace)
+{
+    HashMap<void*, CodeLocationLabel<WasmEntryPtrTag>> stagedCalls;
+    auto stageRepatch = [&] (const Vector<UnlinkedWasmToWasmCall>& callsites) {
+        for (auto& call : callsites) {
+            if (call.functionIndexSpace == functionIndexSpace) {
+                CodeLocationLabel<WasmEntryPtrTag> target = MacroAssembler::prepareForAtomicRepatchNearCallConcurrently(call.callLocation, entrypoint);
+                stagedCalls.add(call.callLocation.dataLocation(), target);
+            }
+        }
+    };
+    for (unsigned i = 0; i < codeBlock.m_wasmToWasmCallsites.size(); ++i) {
+        stageRepatch(codeBlock.m_wasmToWasmCallsites[i]);
+        if (codeBlock.m_llintCallees) {
+            LLIntCallee& llintCallee = codeBlock.m_llintCallees->at(i).get();
+            if (JITCallee* replacementCallee = llintCallee.replacement())
+                stageRepatch(replacementCallee->wasmToWasmCallsites());
+            if (OMGForOSREntryCallee* osrEntryCallee = llintCallee.osrEntryCallee())
+                stageRepatch(osrEntryCallee->wasmToWasmCallsites());
+        }
+        if (BBQCallee* bbqCallee = codeBlock.m_bbqCallees[i].get()) {
+            if (OMGCallee* replacementCallee = bbqCallee->replacement())
+                stageRepatch(replacementCallee->wasmToWasmCallsites());
+            if (OMGForOSREntryCallee* osrEntryCallee = bbqCallee->osrEntryCallee())
+                stageRepatch(osrEntryCallee->wasmToWasmCallsites());
+        }
+    }
+
+    // It's important to make sure we do this before we make any of the code we just compiled visible. If we didn't, we could end up
+    // where we are tiering up some function A to A' and we repatch some function B to call A' instead of A. Another CPU could see
+    // the updates to B but still not have reset its cache of A', which would lead to all kinds of badness.
+    resetInstructionCacheOnAllThreads();
+    WTF::storeStoreFence(); // This probably isn't necessary but it's good to be paranoid.
+
+    codeBlock.m_wasmIndirectCallEntryPoints[functionIndex] = entrypoint;
+
+    auto repatchCalls = [&] (const Vector<UnlinkedWasmToWasmCall>& callsites) {
+        for (auto& call : callsites) {
+            dataLogLnIf(WasmPlanInternal::verbose, "Considering repatching call at: ", RawPointer(call.callLocation.dataLocation()), " that targets ", call.functionIndexSpace);
+            if (call.functionIndexSpace == functionIndexSpace) {
+                dataLogLnIf(WasmPlanInternal::verbose, "Repatching call at: ", RawPointer(call.callLocation.dataLocation()), " to ", RawPointer(entrypoint.executableAddress()));
+                MacroAssembler::repatchNearCall(call.callLocation, stagedCalls.get(call.callLocation.dataLocation()));
+            }
+        }
+    };
+
+    for (unsigned i = 0; i < codeBlock.m_wasmToWasmCallsites.size(); ++i) {
+        repatchCalls(codeBlock.m_wasmToWasmCallsites[i]);
+        if (codeBlock.m_llintCallees) {
+            LLIntCallee& llintCallee = codeBlock.m_llintCallees->at(i).get();
+            if (JITCallee* replacementCallee = llintCallee.replacement())
+                repatchCalls(replacementCallee->wasmToWasmCallsites());
+            if (OMGForOSREntryCallee* osrEntryCallee = llintCallee.osrEntryCallee())
+                repatchCalls(osrEntryCallee->wasmToWasmCallsites());
+        }
+        if (BBQCallee* bbqCallee = codeBlock.m_bbqCallees[i].get()) {
+            if (OMGCallee* replacementCallee = bbqCallee->replacement())
+                repatchCalls(replacementCallee->wasmToWasmCallsites());
+            if (OMGForOSREntryCallee* osrEntryCallee = bbqCallee->osrEntryCallee())
+                repatchCalls(osrEntryCallee->wasmToWasmCallsites());
+        }
+    }
+
+}
+
</ins><span class="cx"> Plan::~Plan() { }
</span><span class="cx"> 
</span><span class="cx"> } } // namespace JSC::Wasm
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorewasmWasmPlanh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/wasm/WasmPlan.h (259581 => 259582)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/wasm/WasmPlan.h      2020-04-06 18:09:10 UTC (rev 259581)
+++ trunk/Source/JavaScriptCore/wasm/WasmPlan.h 2020-04-06 18:19:52 UTC (rev 259582)
</span><span class="lines">@@ -83,6 +83,8 @@
</span><span class="cx">     virtual bool isComplete() const = 0;
</span><span class="cx">     virtual void complete(const AbstractLocker&) = 0;
</span><span class="cx"> 
</span><ins>+    static void updateCallSitesToCallUs(CodeBlock&, CodeLocationLabel<WasmEntryPtrTag> entrypoint, uint32_t functionIndex, uint32_t functionIndexSpace);
+
</ins><span class="cx">     Ref<ModuleInformation> m_moduleInformation;
</span><span class="cx"> 
</span><span class="cx">     Vector<std::pair<Context*, CompletionTask>, 1> m_completionTasks;
</span></span></pre></div>
<a id="trunkSourceWTFChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WTF/ChangeLog (259581 => 259582)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WTF/ChangeLog       2020-04-06 18:09:10 UTC (rev 259581)
+++ trunk/Source/WTF/ChangeLog  2020-04-06 18:19:52 UTC (rev 259582)
</span><span class="lines">@@ -1,3 +1,36 @@
</span><ins>+2020-04-06  Saam Barati  <sbarati@apple.com>
+
+        Implement 1GB of executable memory on arm64
+        https://bugs.webkit.org/show_bug.cgi?id=208490
+        <rdar://problem/60797127>
+
+        Reviewed by Keith Miller.
+
+        * wtf/MetaAllocator.cpp:
+        (WTF::MetaAllocatorTracker::notify):
+        (WTF::MetaAllocatorTracker::release):
+        (WTF::MetaAllocator::release):
+        (WTF::MetaAllocatorHandle::MetaAllocatorHandle):
+        (WTF::MetaAllocatorHandle::~MetaAllocatorHandle):
+        (WTF::MetaAllocatorHandle::shrink):
+        (WTF::MetaAllocator::MetaAllocator):
+        (WTF::MetaAllocator::allocate):
+        (WTF::MetaAllocator::currentStatistics):
+        * wtf/MetaAllocator.h:
+        (WTF::MetaAllocatorTracker::find):
+        (WTF::MetaAllocator::allocate):
+        (WTF::MetaAllocator::currentStatistics):
+        (WTF::MetaAllocator::getLock): Deleted.
+        * wtf/MetaAllocatorHandle.h:
+        (WTF::MetaAllocatorHandle::allocator):
+        (WTF::MetaAllocatorHandle::isManaged): Deleted.
+        (WTF::MetaAllocatorHandle::ownerUID): Deleted.
+        * wtf/PlatformEnable.h:
+        * wtf/RedBlackTree.h:
+        * wtf/StdLibExtras.h:
+        (WTF::constructFixedSizeArrayWithArgumentsImpl):
+        (WTF::constructFixedSizeArrayWithArguments):
+
</ins><span class="cx"> 2020-04-04  Darin Adler  <darin@apple.com>
</span><span class="cx"> 
</span><span class="cx">         Stop using live ranges in DocumentMarkerController
</span></span></pre></div>
<a id="trunkSourceWTFwtfMetaAllocatorcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WTF/wtf/MetaAllocator.cpp (259581 => 259582)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WTF/wtf/MetaAllocator.cpp   2020-04-06 18:09:10 UTC (rev 259581)
+++ trunk/Source/WTF/wtf/MetaAllocator.cpp      2020-04-06 18:19:52 UTC (rev 259582)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> /*
</span><del>- * Copyright (C) 2011-2018 Apple Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2011-2020 Apple Inc. All rights reserved.
</ins><span class="cx">  *
</span><span class="cx">  * Redistribution and use in source and binary forms, with or without
</span><span class="cx">  * modification, are permitted provided that the following conditions
</span><span class="lines">@@ -54,22 +54,21 @@
</span><span class="cx"> #endif
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void MetaAllocatorTracker::notify(MetaAllocatorHandle* handle)
</del><ins>+void MetaAllocatorTracker::notify(MetaAllocatorHandle& handle)
</ins><span class="cx"> {
</span><del>-    m_allocations.insert(handle);
</del><ins>+    m_allocations.insert(&handle);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-void MetaAllocatorTracker::release(MetaAllocatorHandle* handle)
</del><ins>+void MetaAllocatorTracker::release(MetaAllocatorHandle& handle)
</ins><span class="cx"> {
</span><del>-    m_allocations.remove(handle);
</del><ins>+    m_allocations.remove(&handle);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-ALWAYS_INLINE void MetaAllocator::release(MetaAllocatorHandle* handle)
</del><ins>+void MetaAllocator::release(const LockHolder&, MetaAllocatorHandle& handle)
</ins><span class="cx"> {
</span><del>-    LockHolder locker(&m_lock);
-    if (handle->sizeInBytes()) {
-        void* start = handle->start().untaggedPtr();
-        size_t sizeInBytes = handle->sizeInBytes();
</del><ins>+    if (handle.sizeInBytes()) {
+        void* start = handle.start().untaggedPtr();
+        size_t sizeInBytes = handle.sizeInBytes();
</ins><span class="cx">         decrementPageOccupancy(start, sizeInBytes);
</span><span class="cx">         addFreeSpaceFromReleasedHandle(FreeSpacePtr(start), sizeInBytes);
</span><span class="cx">     }
</span><span class="lines">@@ -78,13 +77,11 @@
</span><span class="cx">         m_tracker->release(handle);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-MetaAllocatorHandle::MetaAllocatorHandle(MetaAllocator* allocator, void* start, size_t sizeInBytes, void* ownerUID)
</del><ins>+MetaAllocatorHandle::MetaAllocatorHandle(MetaAllocator& allocator, void* start, size_t sizeInBytes)
</ins><span class="cx">     : m_allocator(allocator)
</span><span class="cx">     , m_start(start)
</span><span class="cx">     , m_end(reinterpret_cast<char*>(start) + sizeInBytes)
</span><del>-    , m_ownerUID(ownerUID)
</del><span class="cx"> {
</span><del>-    ASSERT(allocator);
</del><span class="cx">     ASSERT(start);
</span><span class="cx">     ASSERT(sizeInBytes);
</span><span class="cx"> }
</span><span class="lines">@@ -91,8 +88,8 @@
</span><span class="cx"> 
</span><span class="cx"> MetaAllocatorHandle::~MetaAllocatorHandle()
</span><span class="cx"> {
</span><del>-    ASSERT(m_allocator);
-    m_allocator->release(this);
</del><ins>+    auto locker = holdLock(allocator().m_lock);
+    allocator().release(locker, *this);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void MetaAllocatorHandle::shrink(size_t newSizeInBytes)
</span><span class="lines">@@ -100,9 +97,10 @@
</span><span class="cx">     size_t sizeInBytes = this->sizeInBytes();
</span><span class="cx">     ASSERT(newSizeInBytes <= sizeInBytes);
</span><span class="cx"> 
</span><del>-    LockHolder locker(&m_allocator->m_lock);
</del><ins>+    MetaAllocator& allocator = this->allocator();
+    LockHolder locker(&allocator.m_lock);
</ins><span class="cx"> 
</span><del>-    newSizeInBytes = m_allocator->roundUp(newSizeInBytes);
</del><ins>+    newSizeInBytes = allocator.roundUp(newSizeInBytes);
</ins><span class="cx">     
</span><span class="cx">     ASSERT(newSizeInBytes <= sizeInBytes);
</span><span class="cx"> 
</span><span class="lines">@@ -113,11 +111,11 @@
</span><span class="cx">     size_t freeSize = sizeInBytes - newSizeInBytes;
</span><span class="cx">     uintptr_t freeEnd = freeStart + freeSize;
</span><span class="cx">     
</span><del>-    uintptr_t firstCompletelyFreePage = (freeStart + m_allocator->m_pageSize - 1) & ~(m_allocator->m_pageSize - 1);
</del><ins>+    uintptr_t firstCompletelyFreePage = (freeStart + allocator.m_pageSize - 1) & ~(allocator.m_pageSize - 1);
</ins><span class="cx">     if (firstCompletelyFreePage < freeEnd)
</span><del>-        m_allocator->decrementPageOccupancy(reinterpret_cast<void*>(firstCompletelyFreePage), freeSize - (firstCompletelyFreePage - freeStart));
</del><ins>+        allocator.decrementPageOccupancy(reinterpret_cast<void*>(firstCompletelyFreePage), freeSize - (firstCompletelyFreePage - freeStart));
</ins><span class="cx"> 
</span><del>-    m_allocator->addFreeSpaceFromReleasedHandle(MetaAllocator::FreeSpacePtr(freeStart), freeSize);
</del><ins>+    allocator.addFreeSpaceFromReleasedHandle(MetaAllocator::FreeSpacePtr(freeStart), freeSize);
</ins><span class="cx"> 
</span><span class="cx">     m_end = m_start + newSizeInBytes;
</span><span class="cx"> }
</span><span class="lines">@@ -127,13 +125,13 @@
</span><span class="cx">     out.print(RawPointer(start().untaggedPtr()), "...", RawPointer(end().untaggedPtr()));
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-MetaAllocator::MetaAllocator(size_t allocationGranule, size_t pageSize)
</del><ins>+MetaAllocator::MetaAllocator(Lock& lock, size_t allocationGranule, size_t pageSize)
</ins><span class="cx">     : m_allocationGranule(allocationGranule)
</span><span class="cx">     , m_pageSize(pageSize)
</span><span class="cx">     , m_bytesAllocated(0)
</span><span class="cx">     , m_bytesReserved(0)
</span><span class="cx">     , m_bytesCommitted(0)
</span><del>-    , m_tracker(0)
</del><ins>+    , m_lock(lock)
</ins><span class="cx"> #ifndef NDEBUG
</span><span class="cx">     , m_mallocBalance(0)
</span><span class="cx"> #endif
</span><span class="lines">@@ -157,10 +155,8 @@
</span><span class="cx">     ASSERT(static_cast<size_t>(1) << m_logAllocationGranule == m_allocationGranule);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-RefPtr<MetaAllocatorHandle> MetaAllocator::allocate(size_t sizeInBytes, void* ownerUID)
</del><ins>+RefPtr<MetaAllocatorHandle> MetaAllocator::allocate(const LockHolder&, size_t sizeInBytes)
</ins><span class="cx"> {
</span><del>-    LockHolder locker(&m_lock);
-
</del><span class="cx">     if (!sizeInBytes)
</span><span class="cx">         return nullptr;
</span><span class="cx">     
</span><span class="lines">@@ -195,17 +191,16 @@
</span><span class="cx">     m_numAllocations++;
</span><span class="cx"> #endif
</span><span class="cx"> 
</span><del>-    auto handle = adoptRef(*new MetaAllocatorHandle(this, start.untaggedPtr(), sizeInBytes, ownerUID));
</del><ins>+    auto handle = adoptRef(*new MetaAllocatorHandle(*this, start.untaggedPtr(), sizeInBytes));
</ins><span class="cx"> 
</span><span class="cx">     if (UNLIKELY(!!m_tracker))
</span><del>-        m_tracker->notify(handle.ptr());
</del><ins>+        m_tracker->notify(*handle.ptr());
</ins><span class="cx"> 
</span><span class="cx">     return handle;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-MetaAllocator::Statistics MetaAllocator::currentStatistics()
</del><ins>+MetaAllocator::Statistics MetaAllocator::currentStatistics(const LockHolder&)
</ins><span class="cx"> {
</span><del>-    LockHolder locker(&m_lock);
</del><span class="cx">     Statistics result;
</span><span class="cx">     result.bytesAllocated = m_bytesAllocated;
</span><span class="cx">     result.bytesReserved = m_bytesReserved;
</span></span></pre></div>
<a id="trunkSourceWTFwtfMetaAllocatorh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WTF/wtf/MetaAllocator.h (259581 => 259582)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WTF/wtf/MetaAllocator.h     2020-04-06 18:09:10 UTC (rev 259581)
+++ trunk/Source/WTF/wtf/MetaAllocator.h        2020-04-06 18:19:52 UTC (rev 259582)
</span><span class="lines">@@ -44,15 +44,15 @@
</span><span class="cx"> class MetaAllocatorTracker {
</span><span class="cx">     WTF_MAKE_FAST_ALLOCATED;
</span><span class="cx"> public:
</span><del>-    void notify(MetaAllocatorHandle*);
-    void release(MetaAllocatorHandle*);
</del><ins>+    void notify(MetaAllocatorHandle&);
+    void release(MetaAllocatorHandle&);
</ins><span class="cx"> 
</span><span class="cx">     MetaAllocatorHandle* find(void* address)
</span><span class="cx">     {
</span><span class="cx">         MetaAllocatorHandle* handle = m_allocations.findGreatestLessThanOrEqual(address);
</span><del>-        if (handle && address < handle->end().untaggedPtr())
</del><ins>+        if (handle && handle->start().untaggedPtr() <= address && address < handle->end().untaggedPtr())
</ins><span class="cx">             return handle;
</span><del>-        return 0;
</del><ins>+        return nullptr;
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     RedBlackTree<MetaAllocatorHandle, void*> m_allocations;
</span><span class="lines">@@ -64,17 +64,22 @@
</span><span class="cx"> public:
</span><span class="cx">     using FreeSpacePtr = MetaAllocatorPtr<FreeSpacePtrTag>;
</span><span class="cx"> 
</span><del>-    WTF_EXPORT_PRIVATE MetaAllocator(size_t allocationGranule, size_t pageSize = WTF::pageSize());
</del><ins>+    WTF_EXPORT_PRIVATE MetaAllocator(Lock&, size_t allocationGranule, size_t pageSize = WTF::pageSize());
</ins><span class="cx">     
</span><span class="cx">     WTF_EXPORT_PRIVATE virtual ~MetaAllocator();
</span><span class="cx">     
</span><del>-    WTF_EXPORT_PRIVATE RefPtr<MetaAllocatorHandle> allocate(size_t sizeInBytes, void* ownerUID);
</del><ins>+    ALWAYS_INLINE RefPtr<MetaAllocatorHandle> allocate(size_t sizeInBytes)
+    {
+        auto locker = holdLock(m_lock);
+        return allocate(locker, sizeInBytes);
+    }
+    WTF_EXPORT_PRIVATE RefPtr<MetaAllocatorHandle> allocate(const LockHolder&, size_t sizeInBytes);
</ins><span class="cx"> 
</span><span class="cx">     void trackAllocations(MetaAllocatorTracker* tracker)
</span><span class="cx">     {
</span><span class="cx">         m_tracker = tracker;
</span><span class="cx">     }
</span><del>-    
</del><ins>+
</ins><span class="cx">     // Non-atomic methods for getting allocator statistics.
</span><span class="cx">     size_t bytesAllocated() { return m_bytesAllocated; }
</span><span class="cx">     size_t bytesReserved() { return m_bytesReserved; }
</span><span class="lines">@@ -87,7 +92,12 @@
</span><span class="cx">         size_t bytesReserved;
</span><span class="cx">         size_t bytesCommitted;
</span><span class="cx">     };
</span><del>-    WTF_EXPORT_PRIVATE Statistics currentStatistics();
</del><ins>+    Statistics currentStatistics()
+    {
+        auto locker = holdLock(m_lock);
+        return currentStatistics(locker);
+    }
+    WTF_EXPORT_PRIVATE Statistics currentStatistics(const LockHolder&);
</ins><span class="cx"> 
</span><span class="cx">     // Add more free space to the allocator. Call this directly from
</span><span class="cx">     // the constructor if you wish to operate the allocator within a
</span><span class="lines">@@ -98,7 +108,6 @@
</span><span class="cx">     // builds.
</span><span class="cx">     WTF_EXPORT_PRIVATE size_t debugFreeSpaceSize();
</span><span class="cx"> 
</span><del>-    Lock& getLock() { return m_lock; }
</del><span class="cx">     WTF_EXPORT_PRIVATE bool isInAllocatedMemory(const AbstractLocker&, void* address);
</span><span class="cx">     
</span><span class="cx"> #if ENABLE(META_ALLOCATOR_PROFILE)
</span><span class="lines">@@ -123,6 +132,8 @@
</span><span class="cx">     // destruction, in part because a MetaAllocator cannot die so long
</span><span class="cx">     // as there are Handles that refer to it.
</span><span class="cx"> 
</span><ins>+    // Release a MetaAllocatorHandle.
+    WTF_EXPORT_PRIVATE virtual void release(const LockHolder&, MetaAllocatorHandle&);
</ins><span class="cx"> private:
</span><span class="cx">     
</span><span class="cx">     friend class MetaAllocatorHandle;
</span><span class="lines">@@ -150,9 +161,6 @@
</span><span class="cx">         FreeSpacePtr m_end;
</span><span class="cx">     };
</span><span class="cx">     typedef RedBlackTree<FreeSpaceNode, size_t> Tree;
</span><del>-
-    // Release a MetaAllocatorHandle.
-    void release(MetaAllocatorHandle*);
</del><span class="cx">     
</span><span class="cx">     // Remove free space from the allocator. This is effectively
</span><span class="cx">     // the allocate() function, except that it does not mark the
</span><span class="lines">@@ -193,9 +201,9 @@
</span><span class="cx">     size_t m_bytesReserved;
</span><span class="cx">     size_t m_bytesCommitted;
</span><span class="cx">     
</span><del>-    Lock m_lock;
</del><ins>+    Lock& m_lock;
</ins><span class="cx"> 
</span><del>-    MetaAllocatorTracker* m_tracker;
</del><ins>+    MetaAllocatorTracker* m_tracker { nullptr };
</ins><span class="cx"> 
</span><span class="cx"> #ifndef NDEBUG
</span><span class="cx">     size_t m_mallocBalance;
</span></span></pre></div>
<a id="trunkSourceWTFwtfMetaAllocatorHandleh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WTF/wtf/MetaAllocatorHandle.h (259581 => 259582)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WTF/wtf/MetaAllocatorHandle.h       2020-04-06 18:09:10 UTC (rev 259581)
+++ trunk/Source/WTF/wtf/MetaAllocatorHandle.h  2020-04-06 18:19:52 UTC (rev 259582)
</span><span class="lines">@@ -42,7 +42,7 @@
</span><span class="cx"> class MetaAllocatorHandle : public ThreadSafeRefCounted<MetaAllocatorHandle>, public RedBlackTree<MetaAllocatorHandle, void*>::Node {
</span><span class="cx">     WTF_MAKE_FAST_ALLOCATED_WITH_HEAP_IDENTIFIER(MetaAllocatorHandle);
</span><span class="cx"> private:
</span><del>-    MetaAllocatorHandle(MetaAllocator*, void* start, size_t sizeInBytes, void* ownerUID);
</del><ins>+    MetaAllocatorHandle(MetaAllocator&, void* start, size_t sizeInBytes);
</ins><span class="cx"> 
</span><span class="cx"> public:
</span><span class="cx">     using MemoryPtr = MetaAllocatorPtr<HandleMemoryPtrTag>;
</span><span class="lines">@@ -86,22 +86,11 @@
</span><span class="cx">         
</span><span class="cx">     WTF_EXPORT_PRIVATE void shrink(size_t newSizeInBytes);
</span><span class="cx">     
</span><del>-    bool isManaged()
</del><ins>+    MetaAllocator& allocator()
</ins><span class="cx">     {
</span><del>-        return !!m_allocator;
-    }
-        
-    MetaAllocator* allocator()
-    {
-        ASSERT(m_allocator);
</del><span class="cx">         return m_allocator;
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    void* ownerUID()
-    {
-        return m_ownerUID;
-    }
-
</del><span class="cx">     void* key()
</span><span class="cx">     {
</span><span class="cx">         return m_start.untaggedPtr();
</span><span class="lines">@@ -112,10 +101,9 @@
</span><span class="cx"> private:
</span><span class="cx">     friend class MetaAllocator;
</span><span class="cx">     
</span><del>-    MetaAllocator* m_allocator;
</del><ins>+    MetaAllocator& m_allocator;
</ins><span class="cx">     MemoryPtr m_start;
</span><span class="cx">     MemoryPtr m_end;
</span><del>-    void* m_ownerUID;
</del><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> }
</span></span></pre></div>
<a id="trunkSourceWTFwtfPlatformEnableh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WTF/wtf/PlatformEnable.h (259581 => 259582)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WTF/wtf/PlatformEnable.h    2020-04-06 18:09:10 UTC (rev 259581)
+++ trunk/Source/WTF/wtf/PlatformEnable.h       2020-04-06 18:19:52 UTC (rev 259582)
</span><span class="lines">@@ -878,3 +878,7 @@
</span><span class="cx"> #if ENABLE(WEBGL2) && !ENABLE(WEBGL)
</span><span class="cx"> #error "ENABLE(WEBGL2) requires ENABLE(WEBGL)"
</span><span class="cx"> #endif
</span><ins>+
+#if CPU(ARM64) && CPU(ADDRESS64)
+#define USE_JUMP_ISLANDS 1
+#endif
</ins></span></pre></div>
<a id="trunkSourceWTFwtfRedBlackTreeh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WTF/wtf/RedBlackTree.h (259581 => 259582)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WTF/wtf/RedBlackTree.h      2020-04-06 18:09:10 UTC (rev 259581)
+++ trunk/Source/WTF/wtf/RedBlackTree.h 2020-04-06 18:19:52 UTC (rev 259582)
</span><span class="lines">@@ -30,6 +30,7 @@
</span><span class="cx"> 
</span><span class="cx"> #include <wtf/Assertions.h>
</span><span class="cx"> #include <wtf/Noncopyable.h>
</span><ins>+#include <wtf/Vector.h>
</ins><span class="cx"> 
</span><span class="cx"> namespace WTF {
</span><span class="cx"> 
</span><span class="lines">@@ -324,6 +325,26 @@
</span><span class="cx">         }
</span><span class="cx">         return best;
</span><span class="cx">     }
</span><ins>+
+    template <typename Function>
+    void iterate(Function function)
+    {
+        if (!m_root)
+            return;
+
+        Vector<NodeType*, 16> toIterate;
+        toIterate.append(m_root);
+        while (toIterate.size()) {
+            NodeType& current = *toIterate.takeLast();
+            bool iterateLeft = false;
+            bool iterateRight = false;
+            function(current, iterateLeft, iterateRight);
+            if (iterateLeft && current.left())
+                toIterate.append(current.left());
+            if (iterateRight && current.right())
+                toIterate.append(current.right());
+        }
+    }
</ins><span class="cx">     
</span><span class="cx">     NodeType* first() const
</span><span class="cx">     {
</span></span></pre></div>
<a id="trunkSourceWTFwtfStdLibExtrash"></a>
<div class="modfile"><h4>Modified: trunk/Source/WTF/wtf/StdLibExtras.h (259581 => 259582)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WTF/wtf/StdLibExtras.h      2020-04-06 18:09:10 UTC (rev 259581)
+++ trunk/Source/WTF/wtf/StdLibExtras.h 2020-04-06 18:19:52 UTC (rev 259582)
</span><span class="lines">@@ -489,7 +489,20 @@
</span><span class="cx">     return std::make_unique<T>(std::forward<Args>(args)...);
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+template <typename ResultType, size_t... Is, typename ...Args>
+constexpr auto constructFixedSizeArrayWithArgumentsImpl(std::index_sequence<Is...>, Args&&... args) -> std::array<ResultType, sizeof...(Is)>
+{
+    return { ((void)Is, ResultType { std::forward<Args>(args)... })... };
+}
</ins><span class="cx"> 
</span><ins>+// Construct an std::array with N elements of ResultType, passing Args to each of the N constructors.
+template<typename ResultType, size_t N, typename ...Args>
+constexpr auto constructFixedSizeArrayWithArguments(Args&&... args) -> decltype(auto)
+{
+    auto tuple = std::make_index_sequence<N>();
+    return constructFixedSizeArrayWithArgumentsImpl<ResultType>(tuple, std::forward<Args>(args)...);
+}
+
</ins><span class="cx"> } // namespace WTF
</span><span class="cx"> 
</span><span class="cx"> #define WTFMove(value) std::move<WTF::CheckMoveParameter>(value)
</span><span class="lines">@@ -514,3 +527,4 @@
</span><span class="cx"> using WTF::tryBinarySearch;
</span><span class="cx"> using WTF::makeUnique;
</span><span class="cx"> using WTF::makeUniqueWithoutFastMallocCheck;
</span><ins>+using WTF::constructFixedSizeArrayWithArguments;
</ins></span></pre></div>
<a id="trunkToolsChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Tools/ChangeLog (259581 => 259582)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Tools/ChangeLog    2020-04-06 18:09:10 UTC (rev 259581)
+++ trunk/Tools/ChangeLog       2020-04-06 18:19:52 UTC (rev 259582)
</span><span class="lines">@@ -1,3 +1,17 @@
</span><ins>+2020-04-06  Saam Barati  <sbarati@apple.com>
+
+        Implement 1GB of executable memory on arm64
+        https://bugs.webkit.org/show_bug.cgi?id=208490
+        <rdar://problem/60797127>
+
+        Reviewed by Keith Miller.
+
+        * Scripts/run-jsc-stress-tests:
+        * TestWebKitAPI/Tests/WTF/MetaAllocator.cpp:
+        (TestWebKitAPI::TEST_F):
+        * TestWebKitAPI/Tests/WTF/RedBlackTree.cpp:
+        (TestWebKitAPI::TEST_F):
+
</ins><span class="cx"> 2020-04-04  Darin Adler  <darin@apple.com>
</span><span class="cx"> 
</span><span class="cx">         Stop using live ranges in DocumentMarkerController
</span></span></pre></div>
<a id="trunkToolsScriptsrunjscstresstests"></a>
<div class="modfile"><h4>Modified: trunk/Tools/Scripts/run-jsc-stress-tests (259581 => 259582)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Tools/Scripts/run-jsc-stress-tests 2020-04-06 18:09:10 UTC (rev 259581)
+++ trunk/Tools/Scripts/run-jsc-stress-tests    2020-04-06 18:19:52 UTC (rev 259582)
</span><span class="lines">@@ -50,6 +50,7 @@
</span><span class="cx"> WEBKIT_PATH = SCRIPTS_PATH.dirname.dirname
</span><span class="cx"> LAYOUTTESTS_PATH = WEBKIT_PATH + "LayoutTests"
</span><span class="cx"> WASMTESTS_PATH = WEBKIT_PATH + "JSTests/wasm"
</span><ins>+JETSTREAM2_PATH = WEBKIT_PATH + "PerformanceTests/JetStream2"
</ins><span class="cx"> CHAKRATESTS_PATH = WEBKIT_PATH + "JSTests/ChakraCore/test"
</span><span class="cx"> raise unless SCRIPTS_PATH.basename.to_s == "Scripts"
</span><span class="cx"> raise unless SCRIPTS_PATH.dirname.basename.to_s == "Tools"
</span><span class="lines">@@ -669,7 +670,7 @@
</span><span class="cx"> end
</span><span class="cx"> 
</span><span class="cx"> def runNoCJITValidatePhases(*optionalTestSpecificOptions)
</span><del>-    run("no-cjit-validate-phases", "--validateBytecode=true", "--validateGraphAtEachPhase=true", "--useSourceProviderCache=false", *(NO_CJIT_OPTIONS + optionalTestSpecificOptions))
</del><ins>+    run("no-cjit-validate-phases", "--validateBytecode=true", "--validateGraphAtEachPhase=true", "--useSourceProviderCache=false", "--useRandomizingExecutableIslandAllocation=true", *(NO_CJIT_OPTIONS + optionalTestSpecificOptions))
</ins><span class="cx"> end
</span><span class="cx"> 
</span><span class="cx"> def runNoCJITCollectContinuously(*optionalTestSpecificOptions)
</span><span class="lines">@@ -706,7 +707,7 @@
</span><span class="cx"> end
</span><span class="cx"> 
</span><span class="cx"> def runFTLNoCJITB3O0(*optionalTestSpecificOptions)
</span><del>-    run("ftl-no-cjit-b3o0", "--useArrayAllocationProfiling=false", "--forcePolyProto=true", *(FTL_OPTIONS + NO_CJIT_OPTIONS + B3O0_OPTIONS + FORCE_LLINT_EXIT_OPTIONS + optionalTestSpecificOptions))
</del><ins>+    run("ftl-no-cjit-b3o0", "--useArrayAllocationProfiling=false", "--forcePolyProto=true", "--useRandomizingExecutableIslandAllocation=true", *(FTL_OPTIONS + NO_CJIT_OPTIONS + B3O0_OPTIONS + FORCE_LLINT_EXIT_OPTIONS + optionalTestSpecificOptions))
</ins><span class="cx"> end
</span><span class="cx"> 
</span><span class="cx"> def runFTLNoCJITValidate(*optionalTestSpecificOptions)
</span><span class="lines">@@ -734,7 +735,7 @@
</span><span class="cx"> end
</span><span class="cx"> 
</span><span class="cx"> def runFTLEager(*optionalTestSpecificOptions)
</span><del>-    run("ftl-eager", "--airForceBriggsAllocator=true", "--forcePolyProto=true", *(FTL_OPTIONS + EAGER_OPTIONS + COLLECT_CONTINUOUSLY_OPTIONS + optionalTestSpecificOptions))
</del><ins>+    run("ftl-eager", "--airForceBriggsAllocator=true", "--useRandomizingExecutableIslandAllocation=true", "--forcePolyProto=true", *(FTL_OPTIONS + EAGER_OPTIONS + COLLECT_CONTINUOUSLY_OPTIONS + optionalTestSpecificOptions))
</ins><span class="cx"> end
</span><span class="cx"> 
</span><span class="cx"> def runFTLEagerWatchdog(*optionalTestSpecificOptions)
</span><span class="lines">@@ -775,7 +776,7 @@
</span><span class="cx"> end
</span><span class="cx"> 
</span><span class="cx"> def runEagerJettisonNoCJIT(*optionalTestSpecificOptions)
</span><del>-    run("eager-jettison-no-cjit", "--forceCodeBlockToJettisonDueToOldAge=true", *(NO_CJIT_OPTIONS + optionalTestSpecificOptions))
</del><ins>+    run("eager-jettison-no-cjit", "--useRandomizingExecutableIslandAllocation=true", "--forceCodeBlockToJettisonDueToOldAge=true", *(NO_CJIT_OPTIONS + optionalTestSpecificOptions))
</ins><span class="cx"> end
</span><span class="cx"> 
</span><span class="cx"> def runShadowChicken(*optionalTestSpecificOptions)
</span><span class="lines">@@ -1083,16 +1084,37 @@
</span><span class="cx">     run("default-wasm", "-m", *FTL_OPTIONS)
</span><span class="cx">     if $mode != "quick"
</span><span class="cx">         run("wasm-no-cjit-yes-tls-context", "-m", "--useFastTLSForWasmContext=true", *(FTL_OPTIONS + NO_CJIT_OPTIONS))
</span><del>-        run("wasm-eager", "-m", *(FTL_OPTIONS + EAGER_OPTIONS))
-        run("wasm-eager-jettison", "-m", "--forceCodeBlockToJettisonDueToOldAge=true", *FTL_OPTIONS)
</del><ins>+        run("wasm-eager", "-m", "--useRandomizingExecutableIslandAllocation=true", *(FTL_OPTIONS + EAGER_OPTIONS))
+        run("wasm-eager-jettison", "-m", "--forceCodeBlockToJettisonDueToOldAge=true", "--useRandomizingExecutableIslandAllocation=true", *FTL_OPTIONS)
</ins><span class="cx">         run("wasm-no-tls-context", "-m", "--useFastTLSForWasmContext=false", *FTL_OPTIONS)
</span><span class="cx">         run("wasm-slow-memory", "-m", "--useWebAssemblyFastMemory=false", *FTL_OPTIONS)
</span><span class="cx">         run("wasm-b3", "-m", "--useWasmLLInt=false", "--wasmBBQUsesAir=false", *FTL_OPTIONS)
</span><del>-        run("wasm-air", "-m", "--useWasmLLInt=false", *FTL_OPTIONS)
</del><ins>+        run("wasm-air", "-m", "--useWasmLLInt=false", "--useRandomizingExecutableIslandAllocation=true", *FTL_OPTIONS)
</ins><span class="cx">         run("wasm-collect-continuously", "-m", "--collectContinuously=true", *FTL_OPTIONS) if shouldCollectContinuously?
</span><span class="cx">     end
</span><span class="cx"> end
</span><span class="cx"> 
</span><ins>+def runWebAssemblyJetStream2
+    return if !$jitTests
+    return if !$isFTLPlatform
+
+    prepareExtraAbsoluteFiles(JETSTREAM2_PATH, ["JetStreamDriver.js"])
+    prepareExtraRelativeFilesWithBaseDirectory(Dir[JETSTREAM2_PATH + "wasm" + "*.js"].map { |f| "wasm/" + File.basename(f) }, $collection.dirname, $extraFilesBaseDir.dirname)
+    prepareExtraRelativeFilesWithBaseDirectory(Dir[JETSTREAM2_PATH + "wasm" + "*.wasm"].map { |f| "wasm/" + File.basename(f) }, $collection.dirname, $extraFilesBaseDir.dirname)
+
+    run("default-wasm", *FTL_OPTIONS)
+    if $mode != "quick"
+        run("wasm-no-cjit-yes-tls-context", "--useFastTLSForWasmContext=true", *(FTL_OPTIONS + NO_CJIT_OPTIONS))
+        run("wasm-eager", "--useRandomizingExecutableIslandAllocation=true", *(FTL_OPTIONS + EAGER_OPTIONS))
+        run("wasm-eager-jettison", "--forceCodeBlockToJettisonDueToOldAge=true", *FTL_OPTIONS)
+        run("wasm-no-tls-context", "--useFastTLSForWasmContext=false", *FTL_OPTIONS)
+        run("wasm-slow-memory", "--useWebAssemblyFastMemory=false", *FTL_OPTIONS)
+        run("wasm-b3", "--useWasmLLInt=false", "--wasmBBQUsesAir=false", *FTL_OPTIONS)
+        run("wasm-air", "--useWasmLLInt=false", "--useRandomizingExecutableIslandAllocation=true", *FTL_OPTIONS)
+        run("wasm-collect-continuously", "--collectContinuously=true", *FTL_OPTIONS) if shouldCollectContinuously?
+    end
+end
+
</ins><span class="cx"> def runWebAssemblySuite(*optionalTestSpecificOptions)
</span><span class="cx">     return if !$jitTests
</span><span class="cx">     return if !$isFTLPlatform
</span><span class="lines">@@ -1103,11 +1125,11 @@
</span><span class="cx">     if $mode != "quick"
</span><span class="cx">         run("wasm-no-cjit-yes-tls-context", "-m", "--useFastTLSForWasmContext=true", *(FTL_OPTIONS + NO_CJIT_OPTIONS + optionalTestSpecificOptions))
</span><span class="cx">         run("wasm-eager", "-m", *(FTL_OPTIONS + EAGER_OPTIONS + optionalTestSpecificOptions))
</span><del>-        run("wasm-eager-jettison", "-m", "--forceCodeBlockToJettisonDueToOldAge=true", *(FTL_OPTIONS + optionalTestSpecificOptions))
</del><ins>+        run("wasm-eager-jettison", "-m", "--forceCodeBlockToJettisonDueToOldAge=true", "--useRandomizingExecutableIslandAllocation=true", *(FTL_OPTIONS + optionalTestSpecificOptions))
</ins><span class="cx">         run("wasm-no-tls-context", "-m", "--useFastTLSForWasmContext=false", *(FTL_OPTIONS + optionalTestSpecificOptions))
</span><span class="cx">         run("wasm-slow-memory", "-m", "--useWebAssemblyFastMemory=false", *(FTL_OPTIONS + optionalTestSpecificOptions))
</span><span class="cx">         run("wasm-b3", "-m", "--useWasmLLInt=false", "--wasmBBQUsesAir=false", *(FTL_OPTIONS + optionalTestSpecificOptions))
</span><del>-        run("wasm-air", "-m", "--useWasmLLInt=false", *(FTL_OPTIONS + optionalTestSpecificOptions))
</del><ins>+        run("wasm-air", "-m", "--useWasmLLInt=false", "--useRandomizingExecutableIslandAllocation=true", *(FTL_OPTIONS + optionalTestSpecificOptions))
</ins><span class="cx">         run("wasm-collect-continuously", "-m", "--collectContinuously=true", *(FTL_OPTIONS + optionalTestSpecificOptions)) if shouldCollectContinuously?
</span><span class="cx">     end
</span><span class="cx"> end
</span><span class="lines">@@ -1133,11 +1155,11 @@
</span><span class="cx">     if $mode != "quick"
</span><span class="cx">         runHarnessTest("wasm-no-cjit-yes-tls-context", "--useFastTLSForWasmContext=true", *(FTL_OPTIONS + NO_CJIT_OPTIONS + optionalTestSpecificOptions))
</span><span class="cx">         runHarnessTest("wasm-eager", *(FTL_OPTIONS + EAGER_OPTIONS + optionalTestSpecificOptions))
</span><del>-        runHarnessTest("wasm-eager-jettison", "--forceCodeBlockToJettisonDueToOldAge=true", *(FTL_OPTIONS + optionalTestSpecificOptions))
</del><ins>+        runHarnessTest("wasm-eager-jettison", "--forceCodeBlockToJettisonDueToOldAge=true", "--useRandomizingExecutableIslandAllocation=true", *(FTL_OPTIONS + optionalTestSpecificOptions))
</ins><span class="cx">         runHarnessTest("wasm-no-tls-context", "--useFastTLSForWasmContext=false", *(FTL_OPTIONS + optionalTestSpecificOptions))
</span><span class="cx">         runHarnessTest("wasm-slow-memory", "--useWebAssemblyFastMemory=false", *(FTL_OPTIONS + optionalTestSpecificOptions))
</span><span class="cx">         runHarnessTest("wasm-b3", "--useWasmLLInt=false", "--wasmBBQUsesAir=false", *(FTL_OPTIONS + optionalTestSpecificOptions))
</span><del>-        runHarnessTest("wasm-no-air", "--useWasmLLInt=false", *(FTL_OPTIONS + optionalTestSpecificOptions))
</del><ins>+        runHarnessTest("wasm-no-air", "--useWasmLLInt=false", "--useRandomizingExecutableIslandAllocation=true", *(FTL_OPTIONS + optionalTestSpecificOptions))
</ins><span class="cx">         runHarnessTest("wasm-collect-continuously", "--collectContinuously=true", *(FTL_OPTIONS + optionalTestSpecificOptions)) if shouldCollectContinuously?
</span><span class="cx">     end
</span><span class="cx"> end
</span><span class="lines">@@ -1154,10 +1176,10 @@
</span><span class="cx">     run("default-wasm", *FTL_OPTIONS)
</span><span class="cx">     if $mode != "quick"
</span><span class="cx">         run("wasm-no-cjit-yes-tls-context", "--useFastTLSForWasmContext=true", *(FTL_OPTIONS + NO_CJIT_OPTIONS))
</span><del>-        run("wasm-eager-jettison", "--forceCodeBlockToJettisonDueToOldAge=true", *FTL_OPTIONS)
</del><ins>+        run("wasm-eager-jettison", "--forceCodeBlockToJettisonDueToOldAge=true", "--useRandomizingExecutableIslandAllocation=true", *FTL_OPTIONS)
</ins><span class="cx">         run("wasm-no-tls-context", "--useFastTLSForWasmContext=false", *FTL_OPTIONS)
</span><span class="cx">         run("wasm-b3", "--useWasmLLInt=false", "--wasmBBQUsesAir=false", *FTL_OPTIONS)
</span><del>-        run("wasm-air", "--useWasmLLInt=false", *FTL_OPTIONS)
</del><ins>+        run("wasm-air", "--useWasmLLInt=false", "--useRandomizingExecutableIslandAllocation=true", *FTL_OPTIONS)
</ins><span class="cx">         run("wasm-collect-continuously", "--collectContinuously=true", *FTL_OPTIONS) if shouldCollectContinuously?
</span><span class="cx">     end
</span><span class="cx"> end
</span><span class="lines">@@ -1180,10 +1202,10 @@
</span><span class="cx">     runWithOutputHandler("default-wasm", noisyOutputHandler, "../spec-harness.js", *FTL_OPTIONS)
</span><span class="cx">     if $mode != "quick"
</span><span class="cx">       runWithOutputHandler("wasm-no-cjit-yes-tls-context", noisyOutputHandler, "../spec-harness.js",  "--useFastTLSForWasmContext=true", *(FTL_OPTIONS + NO_CJIT_OPTIONS))
</span><del>-      runWithOutputHandler("wasm-eager-jettison", noisyOutputHandler, "../spec-harness.js", "--forceCodeBlockToJettisonDueToOldAge=true", *FTL_OPTIONS)
</del><ins>+      runWithOutputHandler("wasm-eager-jettison", noisyOutputHandler, "../spec-harness.js", "--forceCodeBlockToJettisonDueToOldAge=true", "--useRandomizingExecutableIslandAllocation=true", *FTL_OPTIONS)
</ins><span class="cx">       runWithOutputHandler("wasm-no-tls-context", noisyOutputHandler, "../spec-harness.js", "--useFastTLSForWasmContext=false", *FTL_OPTIONS)
</span><span class="cx">       runWithOutputHandler("wasm-b3", noisyOutputHandler, "../spec-harness.js", "--useWasmLLInt=false", "--wasmBBQUsesAir=false", *FTL_OPTIONS)
</span><del>-      runWithOutputHandler("wasm-air", noisyOutputHandler, "../spec-harness.js", "--useWasmLLInt=false", *FTL_OPTIONS)
</del><ins>+      runWithOutputHandler("wasm-air", noisyOutputHandler, "../spec-harness.js", "--useWasmLLInt=false", "--useRandomizingExecutableIslandAllocation=true", *FTL_OPTIONS)
</ins><span class="cx">       runWithOutputHandler("wasm-collect-continuously", noisyOutputHandler, "../spec-harness.js", "--collectContinuously=true", *FTL_OPTIONS) if shouldCollectContinuously?
</span><span class="cx">     end
</span><span class="cx"> end
</span><span class="lines">@@ -1352,17 +1374,21 @@
</span><span class="cx">     end
</span><span class="cx"> end
</span><span class="cx"> 
</span><del>-def prepareExtraRelativeFiles(extraFiles, destination)
</del><ins>+def prepareExtraRelativeFilesWithBaseDirectory(extraFiles, destination, baseDirectory)
</ins><span class="cx">     Dir.chdir($outputDir) {
</span><span class="cx">         extraFiles.each {
</span><span class="cx">             | file |
</span><span class="cx">             dest = destination + file
</span><span class="cx">             FileUtils.mkdir_p(dest.dirname)
</span><del>-            FileUtils.cp $extraFilesBaseDir + file, dest
</del><ins>+            FileUtils.cp baseDirectory + file, dest
</ins><span class="cx">         }
</span><span class="cx">     }
</span><span class="cx"> end
</span><span class="cx"> 
</span><ins>+def prepareExtraRelativeFiles(extraFiles, destination)
+    prepareExtraRelativeFilesWithBaseDirectory(extraFiles, destination, $extraFilesBaseDir)
+end
+
</ins><span class="cx"> def baseDirForCollection(collectionName)
</span><span class="cx">     Pathname(".tests") + collectionName
</span><span class="cx"> end
</span></span></pre></div>
<a id="trunkToolsTestWebKitAPITestsWTFMetaAllocatorcpp"></a>
<div class="modfile"><h4>Modified: trunk/Tools/TestWebKitAPI/Tests/WTF/MetaAllocator.cpp (259581 => 259582)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Tools/TestWebKitAPI/Tests/WTF/MetaAllocator.cpp    2020-04-06 18:09:10 UTC (rev 259581)
+++ trunk/Tools/TestWebKitAPI/Tests/WTF/MetaAllocator.cpp       2020-04-06 18:19:52 UTC (rev 259582)
</span><span class="lines">@@ -52,7 +52,7 @@
</span><span class="cx">     class SimpleTestAllocator: public MetaAllocator {
</span><span class="cx">     public:
</span><span class="cx">         SimpleTestAllocator(MetaAllocatorTest* parent)
</span><del>-            : MetaAllocator(32)
</del><ins>+            : MetaAllocator(m_lock, 32)
</ins><span class="cx">             , m_parent(parent)
</span><span class="cx">         {
</span><span class="cx">             addFreshFreeSpace(reinterpret_cast<void*>(basePage * pageSize()), defaultPagesInHeap * pageSize());
</span><span class="lines">@@ -129,6 +129,7 @@
</span><span class="cx">         }
</span><span class="cx">         
</span><span class="cx">     private:
</span><ins>+        Lock m_lock;
</ins><span class="cx">         MetaAllocatorTest* m_parent;
</span><span class="cx">     };
</span><span class="cx"> 
</span><span class="lines">@@ -190,7 +191,7 @@
</span><span class="cx">     
</span><span class="cx">     MetaAllocatorHandle* allocate(size_t sizeInBytes, SanityCheckMode sanityCheckMode = RunSanityCheck)
</span><span class="cx">     {
</span><del>-        MetaAllocatorHandle* handle = allocator->allocate(sizeInBytes, 0).leakRef();
</del><ins>+        MetaAllocatorHandle* handle = allocator->allocate(sizeInBytes).leakRef();
</ins><span class="cx">         EXPECT_TRUE(handle);
</span><span class="cx">         EXPECT_EQ(handle->sizeInBytes(), sizeInBytes);
</span><span class="cx">         
</span><span class="lines">@@ -472,7 +473,7 @@
</span><span class="cx">         
</span><span class="cx">         sanityCheck();
</span><span class="cx">         
</span><del>-        EXPECT_TRUE(!allocator->allocate(sizeInBytes, 0));
</del><ins>+        EXPECT_TRUE(!allocator->allocate(sizeInBytes));
</ins><span class="cx">         
</span><span class="cx">         for (size_t index = 0; index < numAllocations; ++index)
</span><span class="cx">             free(handles.at(index), DontRunSanityCheck);
</span><span class="lines">@@ -579,7 +580,7 @@
</span><span class="cx">         sanityCheck();
</span><span class="cx">         
</span><span class="cx">         // Assert that the heap is not empty.
</span><del>-        EXPECT_TRUE(!allocator->allocate(defaultPagesInHeap * pageSize(), 0));
</del><ins>+        EXPECT_TRUE(!allocator->allocate(defaultPagesInHeap * pageSize()));
</ins><span class="cx">         
</span><span class="cx">         // Allocate the remainder of the heap.
</span><span class="cx">         MetaAllocatorHandle* remainder = allocate(defaultPagesInHeap * pageSize() - secondSize);
</span><span class="lines">@@ -597,12 +598,12 @@
</span><span class="cx">     
</span><span class="cx">     void testDemandAllocCoalesce(size_t firstSize, size_t numPages, size_t secondSize)
</span><span class="cx">     {
</span><del>-        EXPECT_TRUE(!allocator->allocate((defaultPagesInHeap + numPages) * pageSize(), 0));
</del><ins>+        EXPECT_TRUE(!allocator->allocate((defaultPagesInHeap + numPages) * pageSize()));
</ins><span class="cx">         
</span><span class="cx">         MetaAllocatorHandle* firstHandle = allocate(firstSize);
</span><span class="cx">         
</span><del>-        EXPECT_TRUE(!allocator->allocate(secondSize, 0));
-        EXPECT_TRUE(!allocator->allocate((defaultPagesInHeap + numPages) * pageSize(), 0));
</del><ins>+        EXPECT_TRUE(!allocator->allocate(secondSize));
+        EXPECT_TRUE(!allocator->allocate((defaultPagesInHeap + numPages) * pageSize()));
</ins><span class="cx">         
</span><span class="cx">         currentHeapGrowthMode = ForTestDemandAllocCoalesce;
</span><span class="cx">         allowAllocatePages = numPages;
</span><span class="lines">@@ -626,12 +627,12 @@
</span><span class="cx">     {
</span><span class="cx">         free(allocate(firstSize));
</span><span class="cx">         free(allocate(defaultPagesInHeap * pageSize()));
</span><del>-        EXPECT_TRUE(!allocator->allocate((defaultPagesInHeap + numPages) * pageSize(), 0));
</del><ins>+        EXPECT_TRUE(!allocator->allocate((defaultPagesInHeap + numPages) * pageSize()));
</ins><span class="cx">         
</span><span class="cx">         MetaAllocatorHandle* firstHandle = allocate(firstSize);
</span><span class="cx">         
</span><del>-        EXPECT_TRUE(!allocator->allocate(secondSize, 0));
-        EXPECT_TRUE(!allocator->allocate((defaultPagesInHeap + numPages) * pageSize(), 0));
</del><ins>+        EXPECT_TRUE(!allocator->allocate(secondSize));
+        EXPECT_TRUE(!allocator->allocate((defaultPagesInHeap + numPages) * pageSize()));
</ins><span class="cx">         
</span><span class="cx">         currentHeapGrowthMode = ForTestDemandAllocDontCoalesce;
</span><span class="cx">         allowAllocatePages = numPages;
</span><span class="lines">@@ -645,12 +646,12 @@
</span><span class="cx">         
</span><span class="cx">         requestedNumPages = 0;
</span><span class="cx">         
</span><del>-        EXPECT_TRUE(!allocator->allocate((defaultPagesInHeap + numPages) * pageSize(), 0));
</del><ins>+        EXPECT_TRUE(!allocator->allocate((defaultPagesInHeap + numPages) * pageSize()));
</ins><span class="cx"> 
</span><span class="cx">         free(firstHandle);
</span><span class="cx">         free(secondHandle);
</span><span class="cx">         
</span><del>-        EXPECT_TRUE(!allocator->allocate((defaultPagesInHeap + numPages) * pageSize(), 0));
</del><ins>+        EXPECT_TRUE(!allocator->allocate((defaultPagesInHeap + numPages) * pageSize()));
</ins><span class="cx">         
</span><span class="cx">         firstHandle = allocate(firstSize);
</span><span class="cx">         secondHandle = allocate(secondSize);
</span><span class="lines">@@ -671,7 +672,7 @@
</span><span class="cx">     // Tests that allocating a zero-length block returns 0 and
</span><span class="cx">     // does not change anything in memory.
</span><span class="cx">     
</span><del>-    ASSERT(!allocator->allocate(0, 0));
</del><ins>+    ASSERT(!allocator->allocate(0));
</ins><span class="cx">     
</span><span class="cx">     MetaAllocatorHandle* final = allocate(defaultPagesInHeap * pageSize());
</span><span class="cx">     EXPECT_EQ(final->start().untaggedPtr(), reinterpret_cast<void*>(basePage * pageSize()));
</span></span></pre></div>
<a id="trunkToolsTestWebKitAPITestsWTFRedBlackTreecpp"></a>
<div class="modfile"><h4>Modified: trunk/Tools/TestWebKitAPI/Tests/WTF/RedBlackTree.cpp (259581 => 259582)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Tools/TestWebKitAPI/Tests/WTF/RedBlackTree.cpp     2020-04-06 18:09:10 UTC (rev 259581)
+++ trunk/Tools/TestWebKitAPI/Tests/WTF/RedBlackTree.cpp        2020-04-06 18:19:52 UTC (rev 259582)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> /*
</span><del>- * Copyright (C) 2011 Apple Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2011, 2020 Apple Inc. All rights reserved.
</ins><span class="cx">  *
</span><span class="cx">  * Redistribution and use in source and binary forms, with or without
</span><span class="cx">  * modification, are permitted provided that the following conditions
</span><span class="lines">@@ -27,6 +27,7 @@
</span><span class="cx">  */
</span><span class="cx"> 
</span><span class="cx"> #include "config.h"
</span><ins>+#include <wtf/HashSet.h>
</ins><span class="cx"> #include <wtf/RedBlackTree.h>
</span><span class="cx"> #include <wtf/Vector.h>
</span><span class="cx"> 
</span><span class="lines">@@ -319,4 +320,85 @@
</span><span class="cx">     testDriver("+d+d+d+d+d+d+d+d+d+d+f+f+f+f+f+f+f+h+h+i+j+k+l+m+o+p+q+r+z@a@b@c@d@e@f@g@h@i@j@k@l@m@n@o@p@q@r@s@t@u@v@w@x@y@z");
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+TEST_F(RedBlackTreeTest, Iterate)
+{
+    class Node : public RedBlackTree<Node, unsigned>::Node {
+    public:
+        unsigned value;
+        unsigned key() { return value; }
+    };
+
+    HashSet<unsigned> items;
+    items.add(2);
+    items.add(42);
+    items.add(48);
+    items.add(55);
+    items.add(73);
+    items.add(105);
+    items.add(200);
+    items.add(250);
+    items.add(300);
+
+    RedBlackTree<Node, unsigned> tree;
+    for (unsigned value : items) {
+        Node* node = new Node;
+        node->value = value;
+        tree.insert(node);
+    }
+
+    {
+        HashSet<unsigned> testItems;
+        tree.iterate([&] (Node& node, bool& iterateLeft, bool& iterateRight) {
+            testItems.add(node.value);
+            iterateLeft = true;
+            iterateRight = true;
+        });
+
+        EXPECT_EQ(items, testItems);
+    }
+
+    {
+        HashSet<unsigned> lessThanOrEqual73;
+        tree.iterate([&] (Node& node, bool& iterateLeft, bool& iterateRight) {
+            if (node.value < 73) {
+                iterateRight = true;
+                iterateLeft = true;
+            } else
+                iterateLeft = true;
+
+            if (node.value <= 73)
+                lessThanOrEqual73.add(node.value);
+        });
+
+        EXPECT_EQ(lessThanOrEqual73.size(), static_cast<size_t>(5));
+        EXPECT_TRUE(lessThanOrEqual73.contains(2));
+        EXPECT_TRUE(lessThanOrEqual73.contains(42));
+        EXPECT_TRUE(lessThanOrEqual73.contains(48));
+        EXPECT_TRUE(lessThanOrEqual73.contains(55));
+        EXPECT_TRUE(lessThanOrEqual73.contains(73));
+    }
+
+    {
+        HashSet<unsigned> greaterThan55;
+        tree.iterate([&] (Node& node, bool& iterateLeft, bool& iterateRight) {
+            if (node.value <= 55)
+                iterateRight = true;
+            else {
+                iterateLeft = true;
+                iterateRight = true;
+            }
+
+            if (node.value > 55)
+                greaterThan55.add(node.value);
+        });
+
+        EXPECT_EQ(greaterThan55.size(), static_cast<size_t>(5));
+        EXPECT_TRUE(greaterThan55.contains(73));
+        EXPECT_TRUE(greaterThan55.contains(105));
+        EXPECT_TRUE(greaterThan55.contains(200));
+        EXPECT_TRUE(greaterThan55.contains(250));
+        EXPECT_TRUE(greaterThan55.contains(300));
+    }
+}
+
</ins><span class="cx"> } // namespace TestWebKitAPI
</span></span></pre>
</div>
</div>

</body>
</html>