<!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>[213386] trunk/Source</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/213386">213386</a></dd>
<dt>Author</dt> <dd>keith_miller@apple.com</dd>
<dt>Date</dt> <dd>2017-03-03 14:24:21 -0800 (Fri, 03 Mar 2017)</dd>
</dl>

<h3>Log Message</h3>
<pre>WASM should support faster loads.
https://bugs.webkit.org/show_bug.cgi?id=162693

Reviewed by Saam Barati.

Source/JavaScriptCore:

This patch adds support for WebAssembly using a 32-bit address
space for memory (along with some extra space for offset
overflow). With a 32-bit address space (we call them
Signaling/fast memories), we reserve the virtual address space for
2^32 + offset bytes of memory and only mark the usable section as
read/write. If wasm code would read/write out of bounds we use a
custom signal handler to catch the SIGBUS. The signal handler then
checks if the faulting instruction is wasm code and tells the
thread to resume executing from the wasm exception
handler. Otherwise, the signal handler crashes the process, as
usual.

All of the allocations of these memories are managed by the
Wasm::Memory class. In order to avoid TLB churn in the OS we cache
old Signaling memories that are no longer in use. Since getting
the wrong memory can cause recompiles, we try to reserve a memory
for modules that do not import a memory. If a module does import a
memory, we try to guess the type of memory we are going to get
based on the last one allocated.

This patch also changes how the wasm JS-api manages objects. Since
we can compile different versions of code, this patch adds a new
JSWebAssemblyCodeBlock class that holds all the information
specific to running a module in a particular bounds checking
mode. Additionally, the Wasm::Memory object is now a reference
counted class that is shared between the JSWebAssemblyMemory
object and the ArrayBuffer that also views it.

* JavaScriptCore.xcodeproj/project.pbxproj:
* jit/JITThunks.cpp:
(JSC::JITThunks::existingCTIStub):
* jit/JITThunks.h:
* jsc.cpp:
(jscmain):
* runtime/Options.h:
* runtime/VM.cpp:
(JSC::VM::VM):
* runtime/VM.h:
* wasm/JSWebAssemblyCodeBlock.h: Copied from Source/JavaScriptCore/wasm/js/JSWebAssemblyModule.h.
(JSC::JSWebAssemblyCodeBlock::create):
(JSC::JSWebAssemblyCodeBlock::createStructure):
(JSC::JSWebAssemblyCodeBlock::functionImportCount):
(JSC::JSWebAssemblyCodeBlock::mode):
(JSC::JSWebAssemblyCodeBlock::module):
(JSC::JSWebAssemblyCodeBlock::jsEntrypointCalleeFromFunctionIndexSpace):
(JSC::JSWebAssemblyCodeBlock::wasmEntrypointCalleeFromFunctionIndexSpace):
(JSC::JSWebAssemblyCodeBlock::setJSEntrypointCallee):
(JSC::JSWebAssemblyCodeBlock::setWasmEntrypointCallee):
(JSC::JSWebAssemblyCodeBlock::callees):
(JSC::JSWebAssemblyCodeBlock::offsetOfCallees):
(JSC::JSWebAssemblyCodeBlock::allocationSize):
* wasm/WasmB3IRGenerator.cpp:
(JSC::Wasm::B3IRGenerator::B3IRGenerator):
(JSC::Wasm::getMemoryBaseAndSize):
(JSC::Wasm::B3IRGenerator::emitCheckAndPreparePointer):
(JSC::Wasm::B3IRGenerator::emitLoadOp):
(JSC::Wasm::B3IRGenerator::emitStoreOp):
* wasm/WasmCallingConvention.h:
* wasm/WasmFaultSignalHandler.cpp: Added.
(JSC::Wasm::trapHandler):
(JSC::Wasm::registerCode):
(JSC::Wasm::unregisterCode):
(JSC::Wasm::fastMemoryEnabled):
(JSC::Wasm::enableFastMemory):
* wasm/WasmFaultSignalHandler.h: Copied from Source/JavaScriptCore/wasm/js/JSWebAssemblyCallee.cpp.
* wasm/WasmFormat.h:
(JSC::Wasm::ModuleInformation::importFunctionCount):
(JSC::Wasm::ModuleInformation::hasMemory): Deleted.
* wasm/WasmMemory.cpp:
(JSC::Wasm::mmapBytes):
(JSC::Wasm::Memory::lastAllocatedMode):
(JSC::Wasm::availableFastMemories):
(JSC::Wasm::tryGetFastMemory):
(JSC::Wasm::releaseFastMemory):
(JSC::Wasm::Memory::Memory):
(JSC::Wasm::Memory::createImpl):
(JSC::Wasm::Memory::create):
(JSC::Wasm::Memory::~Memory):
(JSC::Wasm::Memory::grow):
(JSC::Wasm::Memory::dump):
(JSC::Wasm::Memory::makeString):
* wasm/WasmMemory.h:
(JSC::Wasm::Memory::operator bool):
(JSC::Wasm::Memory::size):
(JSC::Wasm::Memory::check):
(JSC::Wasm::Memory::Memory): Deleted.
(JSC::Wasm::Memory::offsetOfMemory): Deleted.
(JSC::Wasm::Memory::offsetOfSize): Deleted.
* wasm/WasmMemoryInformation.cpp:
(JSC::Wasm::MemoryInformation::MemoryInformation):
* wasm/WasmMemoryInformation.h:
(JSC::Wasm::MemoryInformation::hasReservedMemory):
(JSC::Wasm::MemoryInformation::takeReservedMemory):
(JSC::Wasm::MemoryInformation::mode):
* wasm/WasmModuleParser.cpp:
* wasm/WasmModuleParser.h:
(JSC::Wasm::ModuleParser::ModuleParser):
* wasm/WasmPlan.cpp:
(JSC::Wasm::Plan::parseAndValidateModule):
(JSC::Wasm::Plan::run):
* wasm/WasmPlan.h:
(JSC::Wasm::Plan::mode):
* wasm/js/JSWebAssemblyCallee.cpp:
(JSC::JSWebAssemblyCallee::finishCreation):
(JSC::JSWebAssemblyCallee::destroy):
* wasm/js/JSWebAssemblyCodeBlock.cpp: Added.
(JSC::JSWebAssemblyCodeBlock::JSWebAssemblyCodeBlock):
(JSC::JSWebAssemblyCodeBlock::destroy):
(JSC::JSWebAssemblyCodeBlock::isSafeToRun):
(JSC::JSWebAssemblyCodeBlock::visitChildren):
(JSC::JSWebAssemblyCodeBlock::UnconditionalFinalizer::finalizeUnconditionally):
* wasm/js/JSWebAssemblyInstance.cpp:
(JSC::JSWebAssemblyInstance::setMemory):
(JSC::JSWebAssemblyInstance::finishCreation):
(JSC::JSWebAssemblyInstance::visitChildren):
* wasm/js/JSWebAssemblyInstance.h:
(JSC::JSWebAssemblyInstance::module):
(JSC::JSWebAssemblyInstance::codeBlock):
(JSC::JSWebAssemblyInstance::memoryMode):
(JSC::JSWebAssemblyInstance::setMemory): Deleted.
* wasm/js/JSWebAssemblyMemory.cpp:
(JSC::JSWebAssemblyMemory::create):
(JSC::JSWebAssemblyMemory::JSWebAssemblyMemory):
(JSC::JSWebAssemblyMemory::buffer):
(JSC::JSWebAssemblyMemory::grow):
(JSC::JSWebAssemblyMemory::destroy):
* wasm/js/JSWebAssemblyMemory.h:
(JSC::JSWebAssemblyMemory::memory):
(JSC::JSWebAssemblyMemory::offsetOfMemory):
(JSC::JSWebAssemblyMemory::offsetOfSize):
* wasm/js/JSWebAssemblyModule.cpp:
(JSC::JSWebAssemblyModule::buildCodeBlock):
(JSC::JSWebAssemblyModule::create):
(JSC::JSWebAssemblyModule::JSWebAssemblyModule):
(JSC::JSWebAssemblyModule::codeBlock):
(JSC::JSWebAssemblyModule::finishCreation):
(JSC::JSWebAssemblyModule::visitChildren):
(JSC::JSWebAssemblyModule::UnconditionalFinalizer::finalizeUnconditionally): Deleted.
* wasm/js/JSWebAssemblyModule.h:
(JSC::JSWebAssemblyModule::takeReservedMemory):
(JSC::JSWebAssemblyModule::signatureIndexFromFunctionIndexSpace):
(JSC::JSWebAssemblyModule::codeBlock):
(JSC::JSWebAssemblyModule::functionImportCount): Deleted.
(JSC::JSWebAssemblyModule::jsEntrypointCalleeFromFunctionIndexSpace): Deleted.
(JSC::JSWebAssemblyModule::wasmEntrypointCalleeFromFunctionIndexSpace): Deleted.
(JSC::JSWebAssemblyModule::setJSEntrypointCallee): Deleted.
(JSC::JSWebAssemblyModule::setWasmEntrypointCallee): Deleted.
(JSC::JSWebAssemblyModule::callees): Deleted.
(JSC::JSWebAssemblyModule::offsetOfCallees): Deleted.
(JSC::JSWebAssemblyModule::allocationSize): Deleted.
* wasm/js/WebAssemblyFunction.cpp:
(JSC::callWebAssemblyFunction):
* wasm/js/WebAssemblyInstanceConstructor.cpp:
(JSC::constructJSWebAssemblyInstance):
* wasm/js/WebAssemblyMemoryConstructor.cpp:
(JSC::constructJSWebAssemblyMemory):
* wasm/js/WebAssemblyModuleConstructor.cpp:
(JSC::WebAssemblyModuleConstructor::createModule):
* wasm/js/WebAssemblyModuleRecord.cpp:
(JSC::WebAssemblyModuleRecord::link):
(JSC::WebAssemblyModuleRecord::evaluate):

Source/WTF:

Add new forms of dataLog that take a boolean which describes if the log should happen. This makes cases where we have a static const bool for printing nicer since you can do:

dataLogIf(verbose, things, to, print);

instead of:

if (verbose)
    dataLog(things, to, print);

Also, add a operator! to Ref that has the same semantics as C++ refs.

* wtf/DataLog.h:
(WTF::dataLogLn):
(WTF::dataLogIf):
(WTF::dataLogLnIf):
* wtf/Ref.h:
(WTF::Ref::operator!):</pre>

<h3>Modified Paths</h3>
<ul>
<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="#trunkSourceJavaScriptCorejitJITThunkscpp">trunk/Source/JavaScriptCore/jit/JITThunks.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorejitJITThunksh">trunk/Source/JavaScriptCore/jit/JITThunks.h</a></li>
<li><a href="#trunkSourceJavaScriptCorejsccpp">trunk/Source/JavaScriptCore/jsc.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeOptionsh">trunk/Source/JavaScriptCore/runtime/Options.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeVMcpp">trunk/Source/JavaScriptCore/runtime/VM.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeVMh">trunk/Source/JavaScriptCore/runtime/VM.h</a></li>
<li><a href="#trunkSourceJavaScriptCorewasmWasmB3IRGeneratorcpp">trunk/Source/JavaScriptCore/wasm/WasmB3IRGenerator.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorewasmWasmCallingConventionh">trunk/Source/JavaScriptCore/wasm/WasmCallingConvention.h</a></li>
<li><a href="#trunkSourceJavaScriptCorewasmWasmFormath">trunk/Source/JavaScriptCore/wasm/WasmFormat.h</a></li>
<li><a href="#trunkSourceJavaScriptCorewasmWasmMemorycpp">trunk/Source/JavaScriptCore/wasm/WasmMemory.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorewasmWasmMemoryh">trunk/Source/JavaScriptCore/wasm/WasmMemory.h</a></li>
<li><a href="#trunkSourceJavaScriptCorewasmWasmMemoryInformationcpp">trunk/Source/JavaScriptCore/wasm/WasmMemoryInformation.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorewasmWasmMemoryInformationh">trunk/Source/JavaScriptCore/wasm/WasmMemoryInformation.h</a></li>
<li><a href="#trunkSourceJavaScriptCorewasmWasmModuleParsercpp">trunk/Source/JavaScriptCore/wasm/WasmModuleParser.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorewasmWasmModuleParserh">trunk/Source/JavaScriptCore/wasm/WasmModuleParser.h</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="#trunkSourceJavaScriptCorewasmjsJSWebAssemblyCalleecpp">trunk/Source/JavaScriptCore/wasm/js/JSWebAssemblyCallee.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorewasmjsJSWebAssemblyInstancecpp">trunk/Source/JavaScriptCore/wasm/js/JSWebAssemblyInstance.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorewasmjsJSWebAssemblyInstanceh">trunk/Source/JavaScriptCore/wasm/js/JSWebAssemblyInstance.h</a></li>
<li><a href="#trunkSourceJavaScriptCorewasmjsJSWebAssemblyMemorycpp">trunk/Source/JavaScriptCore/wasm/js/JSWebAssemblyMemory.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorewasmjsJSWebAssemblyMemoryh">trunk/Source/JavaScriptCore/wasm/js/JSWebAssemblyMemory.h</a></li>
<li><a href="#trunkSourceJavaScriptCorewasmjsJSWebAssemblyModulecpp">trunk/Source/JavaScriptCore/wasm/js/JSWebAssemblyModule.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorewasmjsJSWebAssemblyModuleh">trunk/Source/JavaScriptCore/wasm/js/JSWebAssemblyModule.h</a></li>
<li><a href="#trunkSourceJavaScriptCorewasmjsWebAssemblyFunctioncpp">trunk/Source/JavaScriptCore/wasm/js/WebAssemblyFunction.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorewasmjsWebAssemblyInstanceConstructorcpp">trunk/Source/JavaScriptCore/wasm/js/WebAssemblyInstanceConstructor.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorewasmjsWebAssemblyMemoryConstructorcpp">trunk/Source/JavaScriptCore/wasm/js/WebAssemblyMemoryConstructor.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorewasmjsWebAssemblyModuleConstructorcpp">trunk/Source/JavaScriptCore/wasm/js/WebAssemblyModuleConstructor.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorewasmjsWebAssemblyModuleRecordcpp">trunk/Source/JavaScriptCore/wasm/js/WebAssemblyModuleRecord.cpp</a></li>
<li><a href="#trunkSourceWTFChangeLog">trunk/Source/WTF/ChangeLog</a></li>
<li><a href="#trunkSourceWTFwtfDataLogh">trunk/Source/WTF/wtf/DataLog.h</a></li>
<li><a href="#trunkSourceWTFwtfRefh">trunk/Source/WTF/wtf/Ref.h</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#trunkSourceJavaScriptCorewasmJSWebAssemblyCodeBlockh">trunk/Source/JavaScriptCore/wasm/JSWebAssemblyCodeBlock.h</a></li>
<li><a href="#trunkSourceJavaScriptCorewasmWasmFaultSignalHandlercpp">trunk/Source/JavaScriptCore/wasm/WasmFaultSignalHandler.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorewasmWasmFaultSignalHandlerh">trunk/Source/JavaScriptCore/wasm/WasmFaultSignalHandler.h</a></li>
<li><a href="#trunkSourceJavaScriptCorewasmjsJSWebAssemblyCodeBlockcpp">trunk/Source/JavaScriptCore/wasm/js/JSWebAssemblyCodeBlock.cpp</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceJavaScriptCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ChangeLog (213385 => 213386)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ChangeLog        2017-03-03 22:19:06 UTC (rev 213385)
+++ trunk/Source/JavaScriptCore/ChangeLog        2017-03-03 22:24:21 UTC (rev 213386)
</span><span class="lines">@@ -1,3 +1,172 @@
</span><ins>+2017-03-03  Keith Miller  &lt;keith_miller@apple.com&gt;
+
+        WASM should support faster loads.
+        https://bugs.webkit.org/show_bug.cgi?id=162693
+
+        Reviewed by Saam Barati.
+
+        This patch adds support for WebAssembly using a 32-bit address
+        space for memory (along with some extra space for offset
+        overflow). With a 32-bit address space (we call them
+        Signaling/fast memories), we reserve the virtual address space for
+        2^32 + offset bytes of memory and only mark the usable section as
+        read/write. If wasm code would read/write out of bounds we use a
+        custom signal handler to catch the SIGBUS. The signal handler then
+        checks if the faulting instruction is wasm code and tells the
+        thread to resume executing from the wasm exception
+        handler. Otherwise, the signal handler crashes the process, as
+        usual.
+
+        All of the allocations of these memories are managed by the
+        Wasm::Memory class. In order to avoid TLB churn in the OS we cache
+        old Signaling memories that are no longer in use. Since getting
+        the wrong memory can cause recompiles, we try to reserve a memory
+        for modules that do not import a memory. If a module does import a
+        memory, we try to guess the type of memory we are going to get
+        based on the last one allocated.
+
+        This patch also changes how the wasm JS-api manages objects. Since
+        we can compile different versions of code, this patch adds a new
+        JSWebAssemblyCodeBlock class that holds all the information
+        specific to running a module in a particular bounds checking
+        mode. Additionally, the Wasm::Memory object is now a reference
+        counted class that is shared between the JSWebAssemblyMemory
+        object and the ArrayBuffer that also views it.
+
+        * JavaScriptCore.xcodeproj/project.pbxproj:
+        * jit/JITThunks.cpp:
+        (JSC::JITThunks::existingCTIStub):
+        * jit/JITThunks.h:
+        * jsc.cpp:
+        (jscmain):
+        * runtime/Options.h:
+        * runtime/VM.cpp:
+        (JSC::VM::VM):
+        * runtime/VM.h:
+        * wasm/JSWebAssemblyCodeBlock.h: Copied from Source/JavaScriptCore/wasm/js/JSWebAssemblyModule.h.
+        (JSC::JSWebAssemblyCodeBlock::create):
+        (JSC::JSWebAssemblyCodeBlock::createStructure):
+        (JSC::JSWebAssemblyCodeBlock::functionImportCount):
+        (JSC::JSWebAssemblyCodeBlock::mode):
+        (JSC::JSWebAssemblyCodeBlock::module):
+        (JSC::JSWebAssemblyCodeBlock::jsEntrypointCalleeFromFunctionIndexSpace):
+        (JSC::JSWebAssemblyCodeBlock::wasmEntrypointCalleeFromFunctionIndexSpace):
+        (JSC::JSWebAssemblyCodeBlock::setJSEntrypointCallee):
+        (JSC::JSWebAssemblyCodeBlock::setWasmEntrypointCallee):
+        (JSC::JSWebAssemblyCodeBlock::callees):
+        (JSC::JSWebAssemblyCodeBlock::offsetOfCallees):
+        (JSC::JSWebAssemblyCodeBlock::allocationSize):
+        * wasm/WasmB3IRGenerator.cpp:
+        (JSC::Wasm::B3IRGenerator::B3IRGenerator):
+        (JSC::Wasm::getMemoryBaseAndSize):
+        (JSC::Wasm::B3IRGenerator::emitCheckAndPreparePointer):
+        (JSC::Wasm::B3IRGenerator::emitLoadOp):
+        (JSC::Wasm::B3IRGenerator::emitStoreOp):
+        * wasm/WasmCallingConvention.h:
+        * wasm/WasmFaultSignalHandler.cpp: Added.
+        (JSC::Wasm::trapHandler):
+        (JSC::Wasm::registerCode):
+        (JSC::Wasm::unregisterCode):
+        (JSC::Wasm::fastMemoryEnabled):
+        (JSC::Wasm::enableFastMemory):
+        * wasm/WasmFaultSignalHandler.h: Copied from Source/JavaScriptCore/wasm/js/JSWebAssemblyCallee.cpp.
+        * wasm/WasmFormat.h:
+        (JSC::Wasm::ModuleInformation::importFunctionCount):
+        (JSC::Wasm::ModuleInformation::hasMemory): Deleted.
+        * wasm/WasmMemory.cpp:
+        (JSC::Wasm::mmapBytes):
+        (JSC::Wasm::Memory::lastAllocatedMode):
+        (JSC::Wasm::availableFastMemories):
+        (JSC::Wasm::tryGetFastMemory):
+        (JSC::Wasm::releaseFastMemory):
+        (JSC::Wasm::Memory::Memory):
+        (JSC::Wasm::Memory::createImpl):
+        (JSC::Wasm::Memory::create):
+        (JSC::Wasm::Memory::~Memory):
+        (JSC::Wasm::Memory::grow):
+        (JSC::Wasm::Memory::dump):
+        (JSC::Wasm::Memory::makeString):
+        * wasm/WasmMemory.h:
+        (JSC::Wasm::Memory::operator bool):
+        (JSC::Wasm::Memory::size):
+        (JSC::Wasm::Memory::check):
+        (JSC::Wasm::Memory::Memory): Deleted.
+        (JSC::Wasm::Memory::offsetOfMemory): Deleted.
+        (JSC::Wasm::Memory::offsetOfSize): Deleted.
+        * wasm/WasmMemoryInformation.cpp:
+        (JSC::Wasm::MemoryInformation::MemoryInformation):
+        * wasm/WasmMemoryInformation.h:
+        (JSC::Wasm::MemoryInformation::hasReservedMemory):
+        (JSC::Wasm::MemoryInformation::takeReservedMemory):
+        (JSC::Wasm::MemoryInformation::mode):
+        * wasm/WasmModuleParser.cpp:
+        * wasm/WasmModuleParser.h:
+        (JSC::Wasm::ModuleParser::ModuleParser):
+        * wasm/WasmPlan.cpp:
+        (JSC::Wasm::Plan::parseAndValidateModule):
+        (JSC::Wasm::Plan::run):
+        * wasm/WasmPlan.h:
+        (JSC::Wasm::Plan::mode):
+        * wasm/js/JSWebAssemblyCallee.cpp:
+        (JSC::JSWebAssemblyCallee::finishCreation):
+        (JSC::JSWebAssemblyCallee::destroy):
+        * wasm/js/JSWebAssemblyCodeBlock.cpp: Added.
+        (JSC::JSWebAssemblyCodeBlock::JSWebAssemblyCodeBlock):
+        (JSC::JSWebAssemblyCodeBlock::destroy):
+        (JSC::JSWebAssemblyCodeBlock::isSafeToRun):
+        (JSC::JSWebAssemblyCodeBlock::visitChildren):
+        (JSC::JSWebAssemblyCodeBlock::UnconditionalFinalizer::finalizeUnconditionally):
+        * wasm/js/JSWebAssemblyInstance.cpp:
+        (JSC::JSWebAssemblyInstance::setMemory):
+        (JSC::JSWebAssemblyInstance::finishCreation):
+        (JSC::JSWebAssemblyInstance::visitChildren):
+        * wasm/js/JSWebAssemblyInstance.h:
+        (JSC::JSWebAssemblyInstance::module):
+        (JSC::JSWebAssemblyInstance::codeBlock):
+        (JSC::JSWebAssemblyInstance::memoryMode):
+        (JSC::JSWebAssemblyInstance::setMemory): Deleted.
+        * wasm/js/JSWebAssemblyMemory.cpp:
+        (JSC::JSWebAssemblyMemory::create):
+        (JSC::JSWebAssemblyMemory::JSWebAssemblyMemory):
+        (JSC::JSWebAssemblyMemory::buffer):
+        (JSC::JSWebAssemblyMemory::grow):
+        (JSC::JSWebAssemblyMemory::destroy):
+        * wasm/js/JSWebAssemblyMemory.h:
+        (JSC::JSWebAssemblyMemory::memory):
+        (JSC::JSWebAssemblyMemory::offsetOfMemory):
+        (JSC::JSWebAssemblyMemory::offsetOfSize):
+        * wasm/js/JSWebAssemblyModule.cpp:
+        (JSC::JSWebAssemblyModule::buildCodeBlock):
+        (JSC::JSWebAssemblyModule::create):
+        (JSC::JSWebAssemblyModule::JSWebAssemblyModule):
+        (JSC::JSWebAssemblyModule::codeBlock):
+        (JSC::JSWebAssemblyModule::finishCreation):
+        (JSC::JSWebAssemblyModule::visitChildren):
+        (JSC::JSWebAssemblyModule::UnconditionalFinalizer::finalizeUnconditionally): Deleted.
+        * wasm/js/JSWebAssemblyModule.h:
+        (JSC::JSWebAssemblyModule::takeReservedMemory):
+        (JSC::JSWebAssemblyModule::signatureIndexFromFunctionIndexSpace):
+        (JSC::JSWebAssemblyModule::codeBlock):
+        (JSC::JSWebAssemblyModule::functionImportCount): Deleted.
+        (JSC::JSWebAssemblyModule::jsEntrypointCalleeFromFunctionIndexSpace): Deleted.
+        (JSC::JSWebAssemblyModule::wasmEntrypointCalleeFromFunctionIndexSpace): Deleted.
+        (JSC::JSWebAssemblyModule::setJSEntrypointCallee): Deleted.
+        (JSC::JSWebAssemblyModule::setWasmEntrypointCallee): Deleted.
+        (JSC::JSWebAssemblyModule::callees): Deleted.
+        (JSC::JSWebAssemblyModule::offsetOfCallees): Deleted.
+        (JSC::JSWebAssemblyModule::allocationSize): Deleted.
+        * wasm/js/WebAssemblyFunction.cpp:
+        (JSC::callWebAssemblyFunction):
+        * wasm/js/WebAssemblyInstanceConstructor.cpp:
+        (JSC::constructJSWebAssemblyInstance):
+        * wasm/js/WebAssemblyMemoryConstructor.cpp:
+        (JSC::constructJSWebAssemblyMemory):
+        * wasm/js/WebAssemblyModuleConstructor.cpp:
+        (JSC::WebAssemblyModuleConstructor::createModule):
+        * wasm/js/WebAssemblyModuleRecord.cpp:
+        (JSC::WebAssemblyModuleRecord::link):
+        (JSC::WebAssemblyModuleRecord::evaluate):
+
</ins><span class="cx"> 2017-03-03  Mark Lam  &lt;mark.lam@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Gardening: fix broken ARM64 build.
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreJavaScriptCorexcodeprojprojectpbxproj"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj (213385 => 213386)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj        2017-03-03 22:19:06 UTC (rev 213385)
+++ trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj        2017-03-03 22:24:21 UTC (rev 213386)
</span><span class="lines">@@ -1324,6 +1324,10 @@
</span><span class="cx">                 535557161D9DFA32006D583B /* WasmMemory.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 535557151D9DFA32006D583B /* WasmMemory.cpp */; };
</span><span class="cx">                 5370B4F51BF26202005C40FC /* AdaptiveInferredPropertyValueWatchpointBase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5370B4F31BF25EA2005C40FC /* AdaptiveInferredPropertyValueWatchpointBase.cpp */; };
</span><span class="cx">                 5370B4F61BF26205005C40FC /* AdaptiveInferredPropertyValueWatchpointBase.h in Headers */ = {isa = PBXBuildFile; fileRef = 5370B4F41BF25EA2005C40FC /* AdaptiveInferredPropertyValueWatchpointBase.h */; };
</span><ins>+                5381B9371E60E9660090F794 /* WasmFaultSignalHandler.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5381B9361E60E9660090F794 /* WasmFaultSignalHandler.cpp */; };
+                5381B9391E60E97D0090F794 /* WasmFaultSignalHandler.h in Headers */ = {isa = PBXBuildFile; fileRef = 5381B9381E60E97D0090F794 /* WasmFaultSignalHandler.h */; };
+                5381B9401E65DFEB0090F794 /* JSWebAssemblyCodeBlock.h in Headers */ = {isa = PBXBuildFile; fileRef = 5381B93F1E65DFEB0090F794 /* JSWebAssemblyCodeBlock.h */; };
+                5383AA301E65E8A100A532FC /* JSWebAssemblyCodeBlock.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5383AA2F1E65E8A100A532FC /* JSWebAssemblyCodeBlock.cpp */; };
</ins><span class="cx">                 53917E7B1B7906FA000EBD33 /* JSGenericTypedArrayViewPrototypeFunctions.h in Headers */ = {isa = PBXBuildFile; fileRef = 53917E7A1B7906E4000EBD33 /* JSGenericTypedArrayViewPrototypeFunctions.h */; };
</span><span class="cx">                 539FB8BA1C99DA7C00940FA1 /* JSArrayInlines.h in Headers */ = {isa = PBXBuildFile; fileRef = 539FB8B91C99DA7C00940FA1 /* JSArrayInlines.h */; };
</span><span class="cx">                 53B0BE341E561AC900A8FC29 /* GetterSetterAccessCase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 53B0BE331E561AC900A8FC29 /* GetterSetterAccessCase.cpp */; };
</span><span class="lines">@@ -3791,6 +3795,10 @@
</span><span class="cx">                 535557151D9DFA32006D583B /* WasmMemory.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WasmMemory.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 5370B4F31BF25EA2005C40FC /* AdaptiveInferredPropertyValueWatchpointBase.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = AdaptiveInferredPropertyValueWatchpointBase.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 5370B4F41BF25EA2005C40FC /* AdaptiveInferredPropertyValueWatchpointBase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AdaptiveInferredPropertyValueWatchpointBase.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><ins>+                5381B9361E60E9660090F794 /* WasmFaultSignalHandler.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WasmFaultSignalHandler.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
+                5381B9381E60E97D0090F794 /* WasmFaultSignalHandler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WasmFaultSignalHandler.h; sourceTree = &quot;&lt;group&gt;&quot;; };
+                5381B93F1E65DFEB0090F794 /* JSWebAssemblyCodeBlock.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSWebAssemblyCodeBlock.h; sourceTree = &quot;&lt;group&gt;&quot;; };
+                5383AA2F1E65E8A100A532FC /* JSWebAssemblyCodeBlock.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = JSWebAssemblyCodeBlock.cpp; path = js/JSWebAssemblyCodeBlock.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</ins><span class="cx">                 53917E7A1B7906E4000EBD33 /* JSGenericTypedArrayViewPrototypeFunctions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSGenericTypedArrayViewPrototypeFunctions.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 53917E7C1B791106000EBD33 /* JSTypedArrayViewPrototype.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSTypedArrayViewPrototype.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 53917E831B791CB8000EBD33 /* TypedArrayPrototype.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; name = TypedArrayPrototype.js; path = builtins/TypedArrayPrototype.js; sourceTree = SOURCE_ROOT; };
</span><span class="lines">@@ -6227,6 +6235,8 @@
</span><span class="cx">                                 53F40E961D5A7BEC0099A1B6 /* WasmModuleParser.cpp */,
</span><span class="cx">                                 53F40E941D5A7AEF0099A1B6 /* WasmModuleParser.h */,
</span><span class="cx">                                 ADB6F67C1E15D7500082F384 /* WasmPageCount.cpp */,
</span><ins>+                                5381B9361E60E9660090F794 /* WasmFaultSignalHandler.cpp */,
+                                5381B9381E60E97D0090F794 /* WasmFaultSignalHandler.h */,
</ins><span class="cx">                                 79B759731DFA4C600052174C /* WasmPageCount.h */,
</span><span class="cx">                                 53F40E8C1D5901F20099A1B6 /* WasmParser.h */,
</span><span class="cx">                                 531374BE1D5CE95000AF7A0B /* WasmPlan.cpp */,
</span><span class="lines">@@ -7821,6 +7831,8 @@
</span><span class="cx">                         children = (
</span><span class="cx">                                 79E423E01DEE65320078D355 /* JSWebAssemblyCallee.cpp */,
</span><span class="cx">                                 79E423E11DEE65320078D355 /* JSWebAssemblyCallee.h */,
</span><ins>+                                5383AA2F1E65E8A100A532FC /* JSWebAssemblyCodeBlock.cpp */,
+                                5381B93F1E65DFEB0090F794 /* JSWebAssemblyCodeBlock.h */,
</ins><span class="cx">                                 AD2FCBA61DB58DA400B3E736 /* JSWebAssemblyCompileError.cpp */,
</span><span class="cx">                                 AD2FCBA71DB58DA400B3E736 /* JSWebAssemblyCompileError.h */,
</span><span class="cx">                                 796FB4391DFF8C3F0039C95D /* JSWebAssemblyHelpers.h */,
</span><span class="lines">@@ -7961,6 +7973,7 @@
</span><span class="cx">                                 0FEC85721BDACDC70080FF74 /* AirBasicBlock.h in Headers */,
</span><span class="cx">                                 0FB3878E1BFBC44D00E3AB1E /* AirBlockWorklist.h in Headers */,
</span><span class="cx">                                 0F61832A1C45BF070072450B /* AirCCallingConvention.h in Headers */,
</span><ins>+                                5381B9401E65DFEB0090F794 /* JSWebAssemblyCodeBlock.h in Headers */,
</ins><span class="cx">                                 0FEC85741BDACDC70080FF74 /* AirCCallSpecial.h in Headers */,
</span><span class="cx">                                 0FEC85761BDACDC70080FF74 /* AirCode.h in Headers */,
</span><span class="cx">                                 0F10F1A31C420BF0001C07D2 /* AirCustom.h in Headers */,
</span><span class="lines">@@ -8280,6 +8293,7 @@
</span><span class="cx">                                 A7D89CF417A0B8CC00773AD8 /* DFGBlockInsertionSet.h in Headers */,
</span><span class="cx">                                 0FC3CCFC19ADA410006AC72A /* DFGBlockMap.h in Headers */,
</span><span class="cx">                                 0FC3CCFD19ADA410006AC72A /* DFGBlockMapInlines.h in Headers */,
</span><ins>+                                5381B9391E60E97D0090F794 /* WasmFaultSignalHandler.h in Headers */,
</ins><span class="cx">                                 0FC3CCFE19ADA410006AC72A /* DFGBlockSet.h in Headers */,
</span><span class="cx">                                 0FBF158D19B7A53100695DD0 /* DFGBlockSetInlines.h in Headers */,
</span><span class="cx">                                 0FC3CD0019ADA410006AC72A /* DFGBlockWorklist.h in Headers */,
</span><span class="lines">@@ -10077,6 +10091,7 @@
</span><span class="cx">                                 0FC841681BA8C3210061837D /* DFGInferredTypeCheck.cpp in Sources */,
</span><span class="cx">                                 A704D90517A0BAA8006BA554 /* DFGInPlaceAbstractState.cpp in Sources */,
</span><span class="cx">                                 0F3BD1B71B896A0700598AA6 /* DFGInsertionSet.cpp in Sources */,
</span><ins>+                                5381B9371E60E9660090F794 /* WasmFaultSignalHandler.cpp in Sources */,
</ins><span class="cx">                                 0F300B7B18AB1B1400A6D72E /* DFGIntegerCheckCombiningPhase.cpp in Sources */,
</span><span class="cx">                                 0F898F311B27689F0083A33C /* DFGIntegerRangeOptimizationPhase.cpp in Sources */,
</span><span class="cx">                                 0FC97F3D18202119002C9B26 /* DFGInvalidationPointInjectionPhase.cpp in Sources */,
</span><span class="lines">@@ -10480,6 +10495,7 @@
</span><span class="cx">                                 86C568E011A213EE0007F7F0 /* MacroAssemblerARM.cpp in Sources */,
</span><span class="cx">                                 FEB137571BB11EF900CD5100 /* MacroAssemblerARM64.cpp in Sources */,
</span><span class="cx">                                 A729009C17976C6000317298 /* MacroAssemblerARMv7.cpp in Sources */,
</span><ins>+                                5383AA301E65E8A100A532FC /* JSWebAssemblyCodeBlock.cpp in Sources */,
</ins><span class="cx">                                 0F6DB7EC1D617D1100CDBF8E /* MacroAssemblerCodeRef.cpp in Sources */,
</span><span class="cx">                                 FE68C6381B90DE0B0042BCB3 /* MacroAssemblerPrinter.cpp in Sources */,
</span><span class="cx">                                 A7A4AE0817973B26005612B1 /* MacroAssemblerX86Common.cpp in Sources */,
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitJITThunkscpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/JITThunks.cpp (213385 => 213386)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/JITThunks.cpp        2017-03-03 22:19:06 UTC (rev 213385)
+++ trunk/Source/JavaScriptCore/jit/JITThunks.cpp        2017-03-03 22:24:21 UTC (rev 213386)
</span><span class="lines">@@ -82,6 +82,15 @@
</span><span class="cx">     return entry.iterator-&gt;value;
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+MacroAssemblerCodeRef JITThunks::existingCTIStub(ThunkGenerator generator)
+{
+    LockHolder locker(m_lock);
+    CTIStubMap::iterator entry = m_ctiStubMap.find(generator);
+    if (entry == m_ctiStubMap.end())
+        return MacroAssemblerCodeRef();
+    return entry-&gt;value;
+}
+
</ins><span class="cx"> void JITThunks::finalize(Handle&lt;Unknown&gt; handle, void*)
</span><span class="cx"> {
</span><span class="cx">     auto* nativeExecutable = static_cast&lt;NativeExecutable*&gt;(handle.get().asCell());
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitJITThunksh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/JITThunks.h (213385 => 213386)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/JITThunks.h        2017-03-03 22:19:06 UTC (rev 213385)
+++ trunk/Source/JavaScriptCore/jit/JITThunks.h        2017-03-03 22:24:21 UTC (rev 213386)
</span><span class="lines">@@ -58,6 +58,7 @@
</span><span class="cx">     MacroAssemblerCodePtr ctiNativeTailCallWithoutSavedTags(VM*);    
</span><span class="cx"> 
</span><span class="cx">     MacroAssemblerCodeRef ctiStub(VM*, ThunkGenerator);
</span><ins>+    MacroAssemblerCodeRef existingCTIStub(ThunkGenerator);
</ins><span class="cx"> 
</span><span class="cx">     NativeExecutable* hostFunctionStub(VM*, NativeFunction, NativeFunction constructor, const String&amp; name);
</span><span class="cx">     NativeExecutable* hostFunctionStub(VM*, NativeFunction, NativeFunction constructor, ThunkGenerator, Intrinsic, const DOMJIT::Signature*, const String&amp; name);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejsccpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jsc.cpp (213385 => 213386)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jsc.cpp        2017-03-03 22:19:06 UTC (rev 213385)
+++ trunk/Source/JavaScriptCore/jsc.cpp        2017-03-03 22:24:21 UTC (rev 213386)
</span><span class="lines">@@ -72,6 +72,7 @@
</span><span class="cx"> #include &quot;SuperSampler.h&quot;
</span><span class="cx"> #include &quot;TestRunnerUtils.h&quot;
</span><span class="cx"> #include &quot;TypeProfilerLog.h&quot;
</span><ins>+#include &quot;WasmFaultSignalHandler.h&quot;
</ins><span class="cx"> #include &quot;WasmPlan.h&quot;
</span><span class="cx"> #include &quot;WasmMemory.h&quot;
</span><span class="cx"> #include &lt;locale.h&gt;
</span><span class="lines">@@ -3773,6 +3774,9 @@
</span><span class="cx">     WTF::initializeMainThread();
</span><span class="cx">     JSC::initializeThreading();
</span><span class="cx">     startTimeoutThreadIfNeeded();
</span><ins>+#if ENABLE(WEBASSEMBLY)
+    JSC::Wasm::enableFastMemory();
+#endif
</ins><span class="cx"> 
</span><span class="cx">     int result;
</span><span class="cx">     result = runJSC(
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeOptionsh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/Options.h (213385 => 213386)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/Options.h        2017-03-03 22:19:06 UTC (rev 213385)
+++ trunk/Source/JavaScriptCore/runtime/Options.h        2017-03-03 22:24:21 UTC (rev 213386)
</span><span class="lines">@@ -430,7 +430,9 @@
</span><span class="cx">     \
</span><span class="cx">     v(bool, useWebAssembly, true, Normal, &quot;Expose the WebAssembly global object.&quot;) \
</span><span class="cx">     v(bool, simulateWebAssemblyLowMemory, false, Normal, &quot;If true, the Memory object won't mmap the full 'maximum' range and instead will allocate the minimum required amount.&quot;) \
</span><ins>+    v(bool, useWebAssemblyFastMemory, true, Normal, &quot;If true, we will try to use a 32-bit address space with a signal handler to bounds check wasm memory.&quot;)
</ins><span class="cx"> 
</span><ins>+
</ins><span class="cx"> enum OptionEquivalence {
</span><span class="cx">     SameOption,
</span><span class="cx">     InvertedOption,
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeVMcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/VM.cpp (213385 => 213386)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/VM.cpp        2017-03-03 22:19:06 UTC (rev 213385)
+++ trunk/Source/JavaScriptCore/runtime/VM.cpp        2017-03-03 22:24:21 UTC (rev 213386)
</span><span class="lines">@@ -241,6 +241,7 @@
</span><span class="cx"> #if ENABLE(WEBASSEMBLY)
</span><span class="cx">     webAssemblyCalleeStructure.set(*this, JSWebAssemblyCallee::createStructure(*this, 0, jsNull()));
</span><span class="cx">     webAssemblyToJSCalleeStructure.set(*this, WebAssemblyToJSCallee::createStructure(*this, 0, jsNull()));
</span><ins>+    webAssemblyCodeBlockStructure.set(*this, JSWebAssemblyCodeBlock::createStructure(*this, 0, jsNull()));
</ins><span class="cx">     webAssemblyToJSCallee.set(*this, WebAssemblyToJSCallee::create(*this, webAssemblyToJSCalleeStructure.get()));
</span><span class="cx"> #endif
</span><span class="cx">     moduleProgramExecutableStructure.set(*this, ModuleProgramExecutable::createStructure(*this, 0, jsNull()));
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeVMh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/VM.h (213385 => 213386)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/VM.h        2017-03-03 22:19:06 UTC (rev 213385)
+++ trunk/Source/JavaScriptCore/runtime/VM.h        2017-03-03 22:24:21 UTC (rev 213386)
</span><span class="lines">@@ -334,6 +334,7 @@
</span><span class="cx"> #if ENABLE(WEBASSEMBLY)
</span><span class="cx">     Strong&lt;Structure&gt; webAssemblyCalleeStructure;
</span><span class="cx">     Strong&lt;Structure&gt; webAssemblyToJSCalleeStructure;
</span><ins>+    Strong&lt;Structure&gt; webAssemblyCodeBlockStructure;
</ins><span class="cx">     Strong&lt;JSCell&gt; webAssemblyToJSCallee;
</span><span class="cx"> #endif
</span><span class="cx">     Strong&lt;Structure&gt; moduleProgramExecutableStructure;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorewasmJSWebAssemblyCodeBlockhfromrev213385trunkSourceJavaScriptCorewasmjsJSWebAssemblyModuleh"></a>
<div class="copfile"><h4>Copied: trunk/Source/JavaScriptCore/wasm/JSWebAssemblyCodeBlock.h (from rev 213385, trunk/Source/JavaScriptCore/wasm/js/JSWebAssemblyModule.h) (0 => 213386)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/wasm/JSWebAssemblyCodeBlock.h                                (rev 0)
+++ trunk/Source/JavaScriptCore/wasm/JSWebAssemblyCodeBlock.h        2017-03-03 22:24:21 UTC (rev 213386)
</span><span class="lines">@@ -0,0 +1,128 @@
</span><ins>+/*
+ * Copyright (C) 2017 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
+
+#if ENABLE(WEBASSEMBLY)
+
+#include &quot;JSCell.h&quot;
+#include &quot;JSWebAssemblyCallee.h&quot;
+#include &quot;UnconditionalFinalizer.h&quot;
+#include &quot;WasmFormat.h&quot;
+#include &lt;wtf/Bag.h&gt;
+#include &lt;wtf/Vector.h&gt;
+
+namespace JSC {
+
+class JSWebAssemblyModule;
+class JSWebAssemblyMemory;
+
+class JSWebAssemblyCodeBlock : public JSCell {
+public:
+    typedef JSCell Base;
+    static const unsigned StructureFlags = Base::StructureFlags | StructureIsImmortal;
+
+    static JSWebAssemblyCodeBlock* create(VM&amp; vm, JSWebAssemblyModule* owner, Bag&lt;CallLinkInfo&gt;&amp;&amp; callLinkInfos, Vector&lt;Wasm::WasmExitStubs&gt;&amp;&amp; exitStubs, Wasm::Memory::Mode mode, unsigned calleeCount)
+    {
+        auto* result = new (NotNull, allocateCell&lt;JSWebAssemblyCodeBlock&gt;(vm.heap, allocationSize(calleeCount))) JSWebAssemblyCodeBlock(vm, owner, std::forward&lt;Bag&lt;CallLinkInfo&gt;&gt;(callLinkInfos), std::forward&lt;Vector&lt;Wasm::WasmExitStubs&gt;&gt;(exitStubs), mode, calleeCount);
+        result-&gt;finishCreation(vm);
+        return result;
+    }
+
+    static Structure* createStructure(VM&amp; vm, JSGlobalObject* globalObject, JSValue prototype)
+    {
+        return Structure::create(vm, globalObject, prototype, TypeInfo(CellType, StructureFlags), info());
+    }
+
+    unsigned functionImportCount() const { return m_wasmExitStubs.size(); }
+    Wasm::Memory::Mode mode() const { return m_mode; }
+    JSWebAssemblyModule* module() const { return m_module.get(); }
+    bool isSafeToRun(JSWebAssemblyMemory*);
+
+    JSWebAssemblyCallee* jsEntrypointCalleeFromFunctionIndexSpace(unsigned functionIndexSpace)
+    {
+        RELEASE_ASSERT(functionIndexSpace &gt;= functionImportCount());
+        unsigned calleeIndex = functionIndexSpace - functionImportCount();
+        RELEASE_ASSERT(calleeIndex &lt; m_calleeCount);
+        return callees()[calleeIndex].get();
+    }
+
+    JSWebAssemblyCallee* wasmEntrypointCalleeFromFunctionIndexSpace(unsigned functionIndexSpace)
+    {
+        RELEASE_ASSERT(functionIndexSpace &gt;= functionImportCount());
+        unsigned calleeIndex = functionIndexSpace - functionImportCount();
+        RELEASE_ASSERT(calleeIndex &lt; m_calleeCount);
+        return callees()[calleeIndex + m_calleeCount].get();
+    }
+
+    void setJSEntrypointCallee(VM&amp; vm, unsigned calleeIndex, JSWebAssemblyCallee* callee)
+    {
+        RELEASE_ASSERT(calleeIndex &lt; m_calleeCount);
+        callees()[calleeIndex].set(vm, this, callee);
+    }
+
+    void setWasmEntrypointCallee(VM&amp; vm, unsigned calleeIndex, JSWebAssemblyCallee* callee)
+    {
+        RELEASE_ASSERT(calleeIndex &lt; m_calleeCount);
+        callees()[calleeIndex + m_calleeCount].set(vm, this, callee);
+    }
+
+    WriteBarrier&lt;JSWebAssemblyCallee&gt;* callees()
+    {
+        return bitwise_cast&lt;WriteBarrier&lt;JSWebAssemblyCallee&gt;*&gt;(bitwise_cast&lt;char*&gt;(this) + offsetOfCallees());
+    }
+
+private:
+    JSWebAssemblyCodeBlock(VM&amp;, JSWebAssemblyModule*, Bag&lt;CallLinkInfo&gt;&amp;&amp;, Vector&lt;Wasm::WasmExitStubs&gt;&amp;&amp;, Wasm::Memory::Mode, unsigned calleeCount);
+    DECLARE_EXPORT_INFO;
+    static const bool needsDestruction = true;
+    static void destroy(JSCell*);
+    static void visitChildren(JSCell*, SlotVisitor&amp;);
+
+    static size_t offsetOfCallees()
+    {
+        return WTF::roundUpToMultipleOf&lt;sizeof(WriteBarrier&lt;JSWebAssemblyCallee&gt;)&gt;(sizeof(JSWebAssemblyCodeBlock));
+    }
+
+    static size_t allocationSize(unsigned numCallees)
+    {
+        return offsetOfCallees() + sizeof(WriteBarrier&lt;JSWebAssemblyCallee&gt;) * numCallees * 2;
+    }
+
+    class UnconditionalFinalizer : public JSC::UnconditionalFinalizer {
+        void finalizeUnconditionally() override;
+    };
+
+    WriteBarrier&lt;JSWebAssemblyModule&gt; m_module;
+    UnconditionalFinalizer m_unconditionalFinalizer;
+    Bag&lt;CallLinkInfo&gt; m_callLinkInfos;
+    Vector&lt;Wasm::WasmExitStubs&gt; m_wasmExitStubs;
+    Wasm::Memory::Mode m_mode;
+    unsigned m_calleeCount;
+};
+
+} // namespace JSC
+
+#endif // ENABLE(WEBASSEMBLY)
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCorewasmWasmB3IRGeneratorcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/wasm/WasmB3IRGenerator.cpp (213385 => 213386)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/wasm/WasmB3IRGenerator.cpp        2017-03-03 22:19:06 UTC (rev 213385)
+++ trunk/Source/JavaScriptCore/wasm/WasmB3IRGenerator.cpp        2017-03-03 22:24:21 UTC (rev 213386)
</span><span class="lines">@@ -207,6 +207,7 @@
</span><span class="cx"> 
</span><span class="cx"> private:
</span><span class="cx">     ExpressionType emitCheckAndPreparePointer(ExpressionType pointer, uint32_t offset, uint32_t sizeOfOp);
</span><ins>+    B3::Kind memoryKind(B3::Opcode memoryOp);
</ins><span class="cx">     ExpressionType emitLoadOp(LoadOpType, Origin, ExpressionType pointer, uint32_t offset);
</span><span class="cx">     void emitStoreOp(StoreOpType, Origin, ExpressionType pointer, ExpressionType value, uint32_t offset);
</span><span class="cx"> 
</span><span class="lines">@@ -259,7 +260,7 @@
</span><span class="cx">     for (const PinnedSizeRegisterInfo&amp; regInfo : pinnedRegs.sizeRegisters)
</span><span class="cx">         m_proc.pinRegister(regInfo.sizeRegister);
</span><span class="cx"> 
</span><del>-    if (info.hasMemory()) {
</del><ins>+    if (info.memory) {
</ins><span class="cx">         m_proc.setWasmBoundsCheckGenerator([=] (CCallHelpers&amp; jit, GPRReg pinnedGPR, unsigned) {
</span><span class="cx">             AllowMacroScratchRegisterUsage allowScratch(jit);
</span><span class="cx">             ASSERT_UNUSED(pinnedGPR, m_memorySizeGPR == pinnedGPR);
</span><span class="lines">@@ -282,8 +283,8 @@
</span><span class="cx"> {
</span><span class="cx">     Value* memoryObject = block-&gt;appendNew&lt;MemoryValue&gt;(proc, Load, pointerType(), Origin(), instance, JSWebAssemblyInstance::offsetOfMemory());
</span><span class="cx"> 
</span><del>-    static_assert(sizeof(decltype(vm.topJSWebAssemblyInstance-&gt;memory()-&gt;memory()-&gt;memory())) == sizeof(void*), &quot;codegen relies on this size&quot;);
-    static_assert(sizeof(decltype(vm.topJSWebAssemblyInstance-&gt;memory()-&gt;memory()-&gt;size())) == sizeof(uint64_t), &quot;codegen relies on this size&quot;);
</del><ins>+    static_assert(sizeof(decltype(vm.topJSWebAssemblyInstance-&gt;memory()-&gt;memory().memory())) == sizeof(void*), &quot;codegen relies on this size&quot;);
+    static_assert(sizeof(decltype(vm.topJSWebAssemblyInstance-&gt;memory()-&gt;memory().size())) == sizeof(uint64_t), &quot;codegen relies on this size&quot;);
</ins><span class="cx">     MemoryBaseAndSize result;
</span><span class="cx">     result.base = block-&gt;appendNew&lt;MemoryValue&gt;(proc, Load, pointerType(), Origin(), memoryObject, JSWebAssemblyMemory::offsetOfMemory());
</span><span class="cx">     result.size = block-&gt;appendNew&lt;MemoryValue&gt;(proc, Load, Int64, Origin(), memoryObject, JSWebAssemblyMemory::offsetOfSize());
</span><span class="lines">@@ -454,9 +455,12 @@
</span><span class="cx"> 
</span><span class="cx"> inline Value* B3IRGenerator::emitCheckAndPreparePointer(ExpressionType pointer, uint32_t offset, uint32_t sizeOfOperation)
</span><span class="cx"> {
</span><del>-    ASSERT(m_memoryBaseGPR &amp;&amp; m_memorySizeGPR);
-    ASSERT(sizeOfOperation + offset &gt; offset);
-    m_currentBlock-&gt;appendNew&lt;WasmBoundsCheckValue&gt;(m_proc, Origin(), pointer, m_memorySizeGPR, sizeOfOperation + offset - 1);
</del><ins>+    ASSERT(m_memoryBaseGPR);
+    if (m_info.memory.mode() == Memory::Mode::BoundsChecking) {
+        ASSERT(m_memorySizeGPR);
+        ASSERT(sizeOfOperation + offset &gt; offset);
+        m_currentBlock-&gt;appendNew&lt;WasmBoundsCheckValue&gt;(m_proc, Origin(), pointer, m_memorySizeGPR, sizeOfOperation + offset - 1);
+    }
</ins><span class="cx">     pointer = m_currentBlock-&gt;appendNew&lt;Value&gt;(m_proc, ZExt32, Origin(), pointer);
</span><span class="cx">     return m_currentBlock-&gt;appendNew&lt;WasmAddressValue&gt;(m_proc, Origin(), pointer, m_memoryBaseGPR);
</span><span class="cx"> }
</span><span class="lines">@@ -486,70 +490,77 @@
</span><span class="cx">     RELEASE_ASSERT_NOT_REACHED();
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+inline B3::Kind B3IRGenerator::memoryKind(B3::Opcode memoryOp)
+{
+    if (m_info.memory.mode() == Memory::Signaling)
+        return trapping(memoryOp);
+    return memoryOp;
+}
+
</ins><span class="cx"> inline Value* B3IRGenerator::emitLoadOp(LoadOpType op, Origin origin, ExpressionType pointer, uint32_t offset)
</span><span class="cx"> {
</span><span class="cx">     switch (op) {
</span><span class="cx">     case LoadOpType::I32Load8S: {
</span><del>-        return m_currentBlock-&gt;appendNew&lt;MemoryValue&gt;(m_proc, Load8S, origin, pointer, offset);
</del><ins>+        return m_currentBlock-&gt;appendNew&lt;MemoryValue&gt;(m_proc, memoryKind(Load8S), origin, pointer, offset);
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     case LoadOpType::I64Load8S: {
</span><del>-        Value* value = m_currentBlock-&gt;appendNew&lt;MemoryValue&gt;(m_proc, Load8S, origin, pointer, offset);
</del><ins>+        Value* value = m_currentBlock-&gt;appendNew&lt;MemoryValue&gt;(m_proc, memoryKind(Load8S), origin, pointer, offset);
</ins><span class="cx">         return m_currentBlock-&gt;appendNew&lt;Value&gt;(m_proc, SExt32, origin, value);
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     case LoadOpType::I32Load8U: {
</span><del>-        return m_currentBlock-&gt;appendNew&lt;MemoryValue&gt;(m_proc, Load8Z, origin, pointer, offset);
</del><ins>+        return m_currentBlock-&gt;appendNew&lt;MemoryValue&gt;(m_proc, memoryKind(Load8Z), origin, pointer, offset);
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     case LoadOpType::I64Load8U: {
</span><del>-        Value* value = m_currentBlock-&gt;appendNew&lt;MemoryValue&gt;(m_proc, Load8Z, origin, pointer, offset);
</del><ins>+        Value* value = m_currentBlock-&gt;appendNew&lt;MemoryValue&gt;(m_proc, memoryKind(Load8Z), origin, pointer, offset);
</ins><span class="cx">         return m_currentBlock-&gt;appendNew&lt;Value&gt;(m_proc, ZExt32, origin, value);
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     case LoadOpType::I32Load16S: {
</span><del>-        return m_currentBlock-&gt;appendNew&lt;MemoryValue&gt;(m_proc, Load16S, origin, pointer, offset);
</del><ins>+        return m_currentBlock-&gt;appendNew&lt;MemoryValue&gt;(m_proc, memoryKind(Load16S), origin, pointer, offset);
</ins><span class="cx">     }
</span><span class="cx">     case LoadOpType::I64Load16S: {
</span><del>-        Value* value = m_currentBlock-&gt;appendNew&lt;MemoryValue&gt;(m_proc, Load16S, origin, pointer, offset);
</del><ins>+        Value* value = m_currentBlock-&gt;appendNew&lt;MemoryValue&gt;(m_proc, memoryKind(Load16S), origin, pointer, offset);
</ins><span class="cx">         return m_currentBlock-&gt;appendNew&lt;Value&gt;(m_proc, SExt32, origin, value);
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     case LoadOpType::I32Load: {
</span><del>-        return m_currentBlock-&gt;appendNew&lt;MemoryValue&gt;(m_proc, Load, Int32, origin, pointer, offset);
</del><ins>+        return m_currentBlock-&gt;appendNew&lt;MemoryValue&gt;(m_proc, memoryKind(Load), Int32, origin, pointer, offset);
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     case LoadOpType::I64Load32U: {
</span><del>-        Value* value = m_currentBlock-&gt;appendNew&lt;MemoryValue&gt;(m_proc, Load, Int32, origin, pointer, offset);
</del><ins>+        Value* value = m_currentBlock-&gt;appendNew&lt;MemoryValue&gt;(m_proc, memoryKind(Load), Int32, origin, pointer, offset);
</ins><span class="cx">         return m_currentBlock-&gt;appendNew&lt;Value&gt;(m_proc, ZExt32, origin, value);
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     case LoadOpType::I64Load32S: {
</span><del>-        Value* value = m_currentBlock-&gt;appendNew&lt;MemoryValue&gt;(m_proc, Load, Int32, origin, pointer, offset);
</del><ins>+        Value* value = m_currentBlock-&gt;appendNew&lt;MemoryValue&gt;(m_proc, memoryKind(Load), Int32, origin, pointer, offset);
</ins><span class="cx">         return m_currentBlock-&gt;appendNew&lt;Value&gt;(m_proc, SExt32, origin, value);
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     case LoadOpType::I64Load: {
</span><del>-        return m_currentBlock-&gt;appendNew&lt;MemoryValue&gt;(m_proc, Load, Int64, origin, pointer, offset);
</del><ins>+        return m_currentBlock-&gt;appendNew&lt;MemoryValue&gt;(m_proc, memoryKind(Load), Int64, origin, pointer, offset);
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     case LoadOpType::F32Load: {
</span><del>-        return m_currentBlock-&gt;appendNew&lt;MemoryValue&gt;(m_proc, Load, Float, origin, pointer, offset);
</del><ins>+        return m_currentBlock-&gt;appendNew&lt;MemoryValue&gt;(m_proc, memoryKind(Load), Float, origin, pointer, offset);
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     case LoadOpType::F64Load: {
</span><del>-        return m_currentBlock-&gt;appendNew&lt;MemoryValue&gt;(m_proc, Load, Double, origin, pointer, offset);
</del><ins>+        return m_currentBlock-&gt;appendNew&lt;MemoryValue&gt;(m_proc, memoryKind(Load), Double, origin, pointer, offset);
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     // FIXME: B3 doesn't support Load16Z yet. We should lower to that value when
</span><span class="cx">     // it's added. https://bugs.webkit.org/show_bug.cgi?id=165884
</span><span class="cx">     case LoadOpType::I32Load16U: {
</span><del>-        Value* value = m_currentBlock-&gt;appendNew&lt;MemoryValue&gt;(m_proc, Load16S, origin, pointer, offset);
</del><ins>+        Value* value = m_currentBlock-&gt;appendNew&lt;MemoryValue&gt;(m_proc, memoryKind(Load16S), origin, pointer, offset);
</ins><span class="cx">         return m_currentBlock-&gt;appendNew&lt;Value&gt;(m_proc, BitAnd, Origin(), value,
</span><span class="cx">                 m_currentBlock-&gt;appendNew&lt;Const32Value&gt;(m_proc, Origin(), 0x0000ffff));
</span><span class="cx">     }
</span><span class="cx">     case LoadOpType::I64Load16U: {
</span><del>-        Value* value = m_currentBlock-&gt;appendNew&lt;MemoryValue&gt;(m_proc, Load16S, origin, pointer, offset);
</del><ins>+        Value* value = m_currentBlock-&gt;appendNew&lt;MemoryValue&gt;(m_proc, memoryKind(Load16S), origin, pointer, offset);
</ins><span class="cx">         Value* partialResult = m_currentBlock-&gt;appendNew&lt;Value&gt;(m_proc, BitAnd, Origin(), value,
</span><span class="cx">                 m_currentBlock-&gt;appendNew&lt;Const32Value&gt;(m_proc, Origin(), 0x0000ffff));
</span><span class="cx"> 
</span><span class="lines">@@ -631,7 +642,7 @@
</span><span class="cx">         FALLTHROUGH;
</span><span class="cx"> 
</span><span class="cx">     case StoreOpType::I32Store8:
</span><del>-        m_currentBlock-&gt;appendNew&lt;MemoryValue&gt;(m_proc, Store8, origin, value, pointer, offset);
</del><ins>+        m_currentBlock-&gt;appendNew&lt;MemoryValue&gt;(m_proc, memoryKind(Store8), origin, value, pointer, offset);
</ins><span class="cx">         return;
</span><span class="cx"> 
</span><span class="cx">     case StoreOpType::I64Store16:
</span><span class="lines">@@ -639,7 +650,7 @@
</span><span class="cx">         FALLTHROUGH;
</span><span class="cx"> 
</span><span class="cx">     case StoreOpType::I32Store16:
</span><del>-        m_currentBlock-&gt;appendNew&lt;MemoryValue&gt;(m_proc, Store16, origin, value, pointer, offset);
</del><ins>+        m_currentBlock-&gt;appendNew&lt;MemoryValue&gt;(m_proc, memoryKind(Store16), origin, value, pointer, offset);
</ins><span class="cx">         return;
</span><span class="cx"> 
</span><span class="cx">     case StoreOpType::I64Store32:
</span><span class="lines">@@ -650,7 +661,7 @@
</span><span class="cx">     case StoreOpType::I32Store:
</span><span class="cx">     case StoreOpType::F32Store:
</span><span class="cx">     case StoreOpType::F64Store:
</span><del>-        m_currentBlock-&gt;appendNew&lt;MemoryValue&gt;(m_proc, Store, origin, value, pointer, offset);
</del><ins>+        m_currentBlock-&gt;appendNew&lt;MemoryValue&gt;(m_proc, memoryKind(Store), origin, value, pointer, offset);
</ins><span class="cx">         return;
</span><span class="cx">     }
</span><span class="cx">     RELEASE_ASSERT_NOT_REACHED();
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorewasmWasmCallingConventionh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/wasm/WasmCallingConvention.h (213385 => 213386)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/wasm/WasmCallingConvention.h        2017-03-03 22:19:06 UTC (rev 213385)
+++ trunk/Source/JavaScriptCore/wasm/WasmCallingConvention.h        2017-03-03 22:24:21 UTC (rev 213386)
</span><span class="lines">@@ -40,6 +40,7 @@
</span><span class="cx"> #include &quot;LinkBuffer.h&quot;
</span><span class="cx"> #include &quot;RegisterSet.h&quot;
</span><span class="cx"> #include &quot;WasmFormat.h&quot;
</span><ins>+#include &quot;WasmSignature.h&quot;
</ins><span class="cx"> 
</span><span class="cx"> namespace JSC { namespace Wasm {
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorewasmWasmFaultSignalHandlercpp"></a>
<div class="addfile"><h4>Added: trunk/Source/JavaScriptCore/wasm/WasmFaultSignalHandler.cpp (0 => 213386)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/wasm/WasmFaultSignalHandler.cpp                                (rev 0)
+++ trunk/Source/JavaScriptCore/wasm/WasmFaultSignalHandler.cpp        2017-03-03 22:24:21 UTC (rev 213386)
</span><span class="lines">@@ -0,0 +1,140 @@
</span><ins>+/*
+ * Copyright (C) 2017 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 &quot;config.h&quot;
+#include &quot;WasmFaultSignalHandler.h&quot;
+
+#if ENABLE(WEBASSEMBLY)
+
+#include &quot;ExecutableAllocator.h&quot;
+#include &quot;VM.h&quot;
+#include &quot;WasmExceptionType.h&quot;
+
+#include &lt;wtf/Lock.h&gt;
+#include &lt;wtf/NeverDestroyed.h&gt;
+
+namespace JSC { namespace Wasm {
+
+
+namespace {
+static const bool verbose = false;
+}
+
+static struct sigaction oldSigBusHandler;
+static bool fastHandlerInstalled { false };
+static StaticLock codeLocationsLock;
+static LazyNeverDestroyed&lt;HashSet&lt;std::tuple&lt;VM*, void*, void*&gt;&gt;&gt; codeLocations; // (vm, start, end)
+
+#if CPU(X86_64)
+#define InstructionPointerGPR context-&gt;__ss.__rip
+#define FirstArgumentGPR context-&gt;__ss.__rsi
+#else
+#define InstructionPointerGPR context-&gt;__ss.__pc
+#define FirstArgumentGPR context-&gt;__ss.__x[1]
+#endif
+
+static void trapHandler(int signal, siginfo_t*, void* ucontext)
+{
+    mcontext_t context = static_cast&lt;ucontext_t*&gt;(ucontext)-&gt;uc_mcontext;
+    void* faultingInstruction = reinterpret_cast&lt;void*&gt;(InstructionPointerGPR);
+    dataLogLnIf(verbose, &quot;starting handler for fault at: &quot;, RawPointer(faultingInstruction));
+
+    dataLogLnIf(verbose, &quot;JIT memory start: &quot;, RawPointer(reinterpret_cast&lt;void*&gt;(startOfFixedExecutableMemoryPool)), &quot; end: &quot;, RawPointer(reinterpret_cast&lt;void*&gt;(endOfFixedExecutableMemoryPool)));
+    // First we need to make sure we are in JIT code before we can aquire any locks. Otherwise,
+    // we might have crashed in code that is already holding one of the locks we want to aquire.
+    if (reinterpret_cast&lt;void*&gt;(startOfFixedExecutableMemoryPool) &lt;= faultingInstruction
+        &amp;&amp; faultingInstruction &lt; reinterpret_cast&lt;void*&gt;(endOfFixedExecutableMemoryPool)) {
+
+        LockHolder locker(codeLocationsLock);
+        for (auto range : codeLocations.get()) {
+            VM* vm;
+            void* start;
+            void* end;
+            std::tie(vm, start, end) = range;
+            dataLogLnIf(verbose, &quot;function start: &quot;, RawPointer(start), &quot; end: &quot;, RawPointer(end));
+            if (start &lt;= faultingInstruction &amp;&amp; faultingInstruction &lt; end) {
+                dataLogLnIf(verbose, &quot;found match&quot;);
+                MacroAssemblerCodeRef exceptionStub = vm-&gt;jitStubs-&gt;existingCTIStub(throwExceptionFromWasmThunkGenerator);
+                // If for whatever reason we don't have a stub then we should just treat this like a regular crash.
+                if (!exceptionStub)
+                    break;
+                dataLogLnIf(verbose, &quot;found stub: &quot;, RawPointer(exceptionStub.code().executableAddress()));
+                FirstArgumentGPR = static_cast&lt;uint64_t&gt;(ExceptionType::OutOfBoundsMemoryAccess);
+                InstructionPointerGPR = reinterpret_cast&lt;uint64_t&gt;(exceptionStub.code().executableAddress());
+                return;
+            }
+        }
+    }
+
+    // Since we only use fast memory in processes we control, if we restore we will just fall back to the default handler.
+    sigaction(signal, &amp;oldSigBusHandler, nullptr);
+}
+
+void registerCode(VM&amp; vm, void* start, void* end)
+{
+    if (!fastMemoryEnabled())
+        return;
+    LockHolder locker(codeLocationsLock);
+    codeLocations-&gt;add(std::make_tuple(&amp;vm, start, end));
+}
+
+void unregisterCode(VM&amp; vm, void* start, void* end)
+{
+    if (!fastMemoryEnabled())
+        return;
+    LockHolder locker(codeLocationsLock);
+    codeLocations-&gt;remove(std::make_tuple(&amp;vm, start, end));
+}
+
+bool fastMemoryEnabled()
+{
+    return fastHandlerInstalled;
+}
+
+void enableFastMemory()
+{
+    static std::once_flag once;
+    std::call_once(once, [] {
+        if (!Options::useWebAssemblyFastMemory())
+            return;
+
+        struct sigaction action;
+
+        action.sa_sigaction = trapHandler;
+        sigfillset(&amp;action.sa_mask);
+        action.sa_flags = SA_SIGINFO;
+        
+        if (!sigaction(SIGBUS, &amp;action, &amp;oldSigBusHandler)) {
+            fastHandlerInstalled = true;
+            codeLocations.construct();
+        }
+
+    });
+}
+    
+} } // namespace JSC::Wasm
+
+#endif // ENABLE(WEBASSEMBLY)
+
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCorewasmWasmFaultSignalHandlerhfromrev213385trunkSourceJavaScriptCorewasmjsJSWebAssemblyCalleecpp"></a>
<div class="copfile"><h4>Copied: trunk/Source/JavaScriptCore/wasm/WasmFaultSignalHandler.h (from rev 213385, trunk/Source/JavaScriptCore/wasm/js/JSWebAssemblyCallee.cpp) (0 => 213386)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/wasm/WasmFaultSignalHandler.h                                (rev 0)
+++ trunk/Source/JavaScriptCore/wasm/WasmFaultSignalHandler.h        2017-03-03 22:24:21 UTC (rev 213386)
</span><span class="lines">@@ -0,0 +1,42 @@
</span><ins>+/*
+ * Copyright (C) 2017 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.
+ */
+
+#if ENABLE(WEBASSEMBLY)
+
+namespace JSC {
+
+class VM;
+
+namespace Wasm {
+
+void registerCode(VM&amp;, void* start, void* end);
+void unregisterCode(VM&amp;, void* start, void* end);
+
+bool fastMemoryEnabled();
+JS_EXPORT_PRIVATE void enableFastMemory();
+
+} } // namespace JSC::Wasm
+
+#endif // ENABLE(WEBASSEMBLY)
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCorewasmWasmFormath"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/wasm/WasmFormat.h (213385 => 213386)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/wasm/WasmFormat.h        2017-03-03 22:19:06 UTC (rev 213385)
+++ trunk/Source/JavaScriptCore/wasm/WasmFormat.h        2017-03-03 22:24:21 UTC (rev 213386)
</span><span class="lines">@@ -256,7 +256,6 @@
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     uint32_t importFunctionCount() const { return importFunctionSignatureIndices.size(); }
</span><del>-    bool hasMemory() const { return !!memory; }
</del><span class="cx"> 
</span><span class="cx">     ~ModuleInformation();
</span><span class="cx"> };
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorewasmWasmMemorycpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/wasm/WasmMemory.cpp (213385 => 213386)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/wasm/WasmMemory.cpp        2017-03-03 22:19:06 UTC (rev 213385)
+++ trunk/Source/JavaScriptCore/wasm/WasmMemory.cpp        2017-03-03 22:24:21 UTC (rev 213386)
</span><span class="lines">@@ -28,7 +28,11 @@
</span><span class="cx"> 
</span><span class="cx"> #if ENABLE(WEBASSEMBLY)
</span><span class="cx"> 
</span><ins>+#include &quot;VM.h&quot;
+#include &quot;WasmFaultSignalHandler.h&quot;
+
</ins><span class="cx"> #include &lt;wtf/HexNumber.h&gt;
</span><ins>+#include &lt;wtf/NeverDestroyed.h&gt;
</ins><span class="cx"> #include &lt;wtf/PrintStream.h&gt;
</span><span class="cx"> #include &lt;wtf/text/WTFString.h&gt;
</span><span class="cx"> 
</span><span class="lines">@@ -38,86 +42,200 @@
</span><span class="cx"> const bool verbose = false;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void Memory::dump(PrintStream&amp; out) const
</del><ins>+inline bool mmapBytes(size_t bytes, void*&amp; memory)
</ins><span class="cx"> {
</span><del>-    String memoryHex;
-    WTF::appendUnsigned64AsHex((uint64_t)(uintptr_t)m_memory, memoryHex);
-    out.print(&quot;Memory at 0x&quot;, memoryHex, &quot;, size &quot;, m_size, &quot;B capacity &quot;, m_mappedCapacity, &quot;B, initial &quot;, m_initial, &quot; maximum &quot;, m_maximum, &quot; mode &quot;, makeString(m_mode));
</del><ins>+    dataLogIf(verbose, &quot;Attempting to mmap &quot;, bytes, &quot; bytes: &quot;);
+    // FIXME: It would be nice if we had a VM tag for wasm memory. https://bugs.webkit.org/show_bug.cgi?id=163600
+    void* result = mmap(nullptr, bytes, PROT_NONE, MAP_PRIVATE | MAP_ANON, -1, 0);
+    if (result == MAP_FAILED) {
+        dataLogLnIf(verbose, &quot;failed&quot;);
+        return false;
+    }
+    dataLogLnIf(verbose, &quot;succeeded&quot;);
+    memory = result;
+    return true;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-const char* Memory::makeString(Mode mode) const
</del><ins>+// We use this as a heuristic to guess what mode a memory import will be. Most of the time we expect users to
+// allocate the memory they are going to pass to all their modules right before compilation.
+static Memory::Mode lastAllocatedMemoryMode { Memory::Mode::Signaling };
+
+Memory::Mode Memory::lastAllocatedMode()
</ins><span class="cx"> {
</span><del>-    switch (mode) {
-    case Mode::BoundsChecking: return &quot;BoundsChecking&quot;;
</del><ins>+    return lastAllocatedMemoryMode;
+}
+
+static_assert(sizeof(uint64_t) == sizeof(size_t), &quot;We rely on allowing the maximum size of Memory we map to be 2^33 which is larger than fits in a 32-bit integer that we'd pass to mprotect if this didn't hold.&quot;);
+
+static const size_t fastMemoryMappedBytes = (static_cast&lt;size_t&gt;(std::numeric_limits&lt;uint32_t&gt;::max()) + 1) * 2; // pointer max + offset max. This is all we need since a load straddling readable memory will trap.
+static const unsigned maxFastMemories = 4;
+static unsigned allocatedFastMemories { 0 };
+static StaticLock memoryLock;
+inline Deque&lt;void*, maxFastMemories&gt;&amp; availableFastMemories(const LockHolder&amp;)
+{
+    static NeverDestroyed&lt;Deque&lt;void*, maxFastMemories&gt;&gt; availableFastMemories;
+    return availableFastMemories;
+}
+
+inline bool tryGetFastMemory(VM&amp; vm, void*&amp; memory, size_t&amp; mappedCapacity, Memory::Mode&amp; mode)
+{
+    // We might GC here so we should be holding the API lock.
+    // FIXME: We should be able to syncronously trigger the GC from another thread.
+    ASSERT(vm.currentThreadIsHoldingAPILock());
+    if (!fastMemoryEnabled())
+        return false;
+
+    // We need to be sure we have a stub prior to running code.
+    if (!vm.getCTIStub(throwExceptionFromWasmThunkGenerator).size())
+        return false;
+
+    auto dequeFastMemory = [&amp;] () -&gt; bool {
+        // FIXME: We should eventually return these to the OS if we go some number of GCs
+        // without using them.
+        LockHolder locker(memoryLock);
+        if (!availableFastMemories(locker).isEmpty()) {
+            memory = availableFastMemories(locker).takeFirst();
+            mappedCapacity = fastMemoryMappedBytes;
+            mode = Memory::Signaling;
+            return true;
+        }
+        return false;
+    };
+
+    ASSERT(allocatedFastMemories &lt;= maxFastMemories);
+    if (dequeFastMemory())
+        return true;
+
+    // If we have allocated all the fast memories... too bad.
+    if (allocatedFastMemories == maxFastMemories) {
+        // There is a reasonable chance that another module has died but has not been collected yet. Don't lose hope yet!
+        vm.heap.collectSync();
+        return dequeFastMemory();
</ins><span class="cx">     }
</span><del>-    RELEASE_ASSERT_NOT_REACHED();
-    return &quot;&quot;;
</del><ins>+
+    if (mmapBytes(fastMemoryMappedBytes, memory)) {
+        mappedCapacity = fastMemoryMappedBytes;
+        mode = Memory::Signaling;
+        allocatedFastMemories++;
+    }
+    return memory;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-static_assert(sizeof(uint64_t) == sizeof(size_t), &quot;We rely on allowing the maximum size of Memory we map to be 2^32 which is larger than fits in a 32-bit integer that we'd pass to mprotect if this didn't hold.&quot;);
</del><ins>+inline void releaseFastMemory(void*&amp; memory, size_t writableSize, size_t mappedCapacity, Memory::Mode mode)
+{
+    if (mode != Memory::Signaling || !memory)
+        return;
</ins><span class="cx"> 
</span><del>-Memory::Memory(PageCount initial, PageCount maximum, bool&amp; failed)
-    : m_size(initial.bytes())
</del><ins>+    RELEASE_ASSERT(memory &amp;&amp; mappedCapacity == fastMemoryMappedBytes);
+    ASSERT(fastMemoryEnabled());
+
+    memset(memory, 0, writableSize);
+    if (mprotect(memory, writableSize, PROT_NONE))
+        CRASH();
+
+    LockHolder locker(memoryLock);
+    ASSERT(availableFastMemories(locker).size() &lt; allocatedFastMemories);
+    availableFastMemories(locker).append(memory);
+    memory = nullptr;
+}
+
+Memory::Memory(PageCount initial, PageCount maximum)
+    : m_initial(initial)
+    , m_maximum(maximum)
+{
+    ASSERT(!initial.bytes());
+}
+
+Memory::Memory(void* memory, PageCount initial, PageCount maximum, size_t mappedCapacity, Mode mode)
+    : m_memory(memory)
+    , m_size(initial.bytes())
</ins><span class="cx">     , m_initial(initial)
</span><span class="cx">     , m_maximum(maximum)
</span><del>-    , m_mode(Mode::BoundsChecking)
-    // FIXME: If we add signal based bounds checking then we need extra space for overflow on load.
-    // see: https://bugs.webkit.org/show_bug.cgi?id=162693
</del><ins>+    , m_mappedCapacity(mappedCapacity)
+    , m_mode(mode)
</ins><span class="cx"> {
</span><ins>+    dataLogLnIf(verbose, &quot;Memory::Memory allocating &quot;, *this);
+}
+
+RefPtr&lt;Memory&gt; Memory::createImpl(VM&amp; vm, PageCount initial, PageCount maximum, std::optional&lt;Mode&gt; requiredMode)
+{
</ins><span class="cx">     RELEASE_ASSERT(!maximum || maximum &gt;= initial); // This should be guaranteed by our caller.
</span><span class="cx"> 
</span><del>-    m_mappedCapacity = maximum ? maximum.bytes() : PageCount::max().bytes();
-    if (!m_mappedCapacity) {
</del><ins>+    Mode mode = requiredMode ? *requiredMode : BoundsChecking;
+    const size_t size = initial.bytes();
+    size_t mappedCapacity = maximum ? maximum.bytes() : PageCount::max().bytes();
+    void* memory = nullptr;
+
+    auto makeEmptyMemory = [&amp;] () -&gt; RefPtr&lt;Memory&gt; {
+        if (mode == Signaling)
+            return nullptr;
+
+        lastAllocatedMemoryMode = BoundsChecking;
+        return adoptRef(new Memory(initial, maximum));
+    };
+
+    if (!mappedCapacity) {
</ins><span class="cx">         // This means we specified a zero as maximum (which means we also have zero as initial size).
</span><del>-        RELEASE_ASSERT(m_size == 0);
-        m_memory = nullptr;
-        m_mappedCapacity = 0;
-        failed = false;
-        if (verbose)
-            dataLogLn(&quot;Memory::Memory allocating nothing &quot;, *this);
-        return;
</del><ins>+        RELEASE_ASSERT(!size);
+        dataLogLnIf(verbose, &quot;Memory::create allocating nothing&quot;);
+        return makeEmptyMemory();
</ins><span class="cx">     }
</span><span class="cx"> 
</span><del>-    // FIXME: It would be nice if we had a VM tag for wasm memory. https://bugs.webkit.org/show_bug.cgi?id=163600
-    void* result = Options::simulateWebAssemblyLowMemory() ? MAP_FAILED : mmap(nullptr, m_mappedCapacity, PROT_NONE, MAP_PRIVATE | MAP_ANON, -1, 0);
-    if (result == MAP_FAILED) {
-        // Try again with a different number.
-        if (verbose)
-            dataLogLn(&quot;Memory::Memory mmap failed once for capacity, trying again&quot;, *this);
-        m_mappedCapacity = m_size;
-        if (!m_mappedCapacity) {
-            m_memory = nullptr;
-            failed = false;
-            if (verbose)
-                dataLogLn(&quot;Memory::Memory mmap not trying again because size is zero &quot;, *this);
-            return;
</del><ins>+    bool canUseFastMemory = !requiredMode || requiredMode == Signaling;
+    if (!canUseFastMemory || !tryGetFastMemory(vm, memory, mappedCapacity, mode)) {
+        if (mode == Signaling)
+            return nullptr;
+
+        if (Options::simulateWebAssemblyLowMemory() ? true : !mmapBytes(mappedCapacity, memory)) {
+            // Try again with a different number.
+            dataLogLnIf(verbose, &quot;Memory::create mmap failed once for capacity, trying again&quot;);
+            mappedCapacity = size;
+            if (!mappedCapacity) {
+                dataLogLnIf(verbose, &quot;Memory::create mmap not trying again because size is zero&quot;);
+                return makeEmptyMemory();
+            }
+
+            if (!mmapBytes(mappedCapacity, memory)) {
+                dataLogLnIf(verbose, &quot;Memory::create mmap failed twice&quot;);
+                return nullptr;
+            }
</ins><span class="cx">         }
</span><ins>+    }
</ins><span class="cx"> 
</span><del>-        result = mmap(nullptr, m_mappedCapacity, PROT_NONE, MAP_PRIVATE | MAP_ANON, -1, 0);
-        if (result == MAP_FAILED) {
-            if (verbose)
-                dataLogLn(&quot;Memory::Memory mmap failed twice &quot;, *this);
-            failed = true;
-            return;
</del><ins>+    ASSERT(memory &amp;&amp; size &lt;= mappedCapacity);
+    if (mprotect(memory, size, PROT_READ | PROT_WRITE)) {
+        dataLogLnIf(verbose, &quot;Memory::create mprotect failed&quot;);
+        releaseFastMemory(memory, 0, mappedCapacity, mode);
+        if (memory) {
+            if (munmap(memory, mappedCapacity))
+                CRASH();
</ins><span class="cx">         }
</span><ins>+        return nullptr;
</ins><span class="cx">     }
</span><ins>+    
+    lastAllocatedMemoryMode = mode;
+    dataLogLnIf(verbose, &quot;Memory::create mmap succeeded&quot;);
+    return adoptRef(new Memory(memory, initial, maximum, mappedCapacity, mode));
+}
</ins><span class="cx"> 
</span><del>-    ASSERT(m_size &lt;= m_mappedCapacity);
-    {
-        bool success = !mprotect(result, static_cast&lt;size_t&gt;(m_size), PROT_READ | PROT_WRITE);
-        RELEASE_ASSERT(success);
</del><ins>+RefPtr&lt;Memory&gt; Memory::create(VM&amp; vm, PageCount initial, PageCount maximum, std::optional&lt;Mode&gt; mode)
+{
+    RELEASE_ASSERT(!maximum || maximum &gt;= initial); // This should be guaranteed by our caller.
+    RefPtr&lt;Memory&gt; result = createImpl(vm, initial, maximum, mode);
+    if (result) {
+        if (result-&gt;mode() == Signaling)
+            RELEASE_ASSERT(result-&gt;m_mappedCapacity == fastMemoryMappedBytes);
+        if (mode)
+            ASSERT(*mode == result-&gt;mode());
+        ASSERT(lastAllocatedMemoryMode == result-&gt;mode());
</ins><span class="cx">     }
</span><del>-
-    m_memory = result;
-    failed = false;
-    if (verbose)
-        dataLogLn(&quot;Memory::Memory mmap succeeded &quot;, *this);
</del><ins>+    return result;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> Memory::~Memory()
</span><span class="cx"> {
</span><del>-    if (verbose)
-        dataLogLn(&quot;Memory::~Memory &quot;, *this);
</del><ins>+    dataLogLnIf(verbose, &quot;Memory::~Memory &quot;, *this);
+    releaseFastMemory(m_memory, m_size, m_mappedCapacity, m_mode);
</ins><span class="cx">     if (m_memory) {
</span><span class="cx">         if (munmap(m_memory, m_mappedCapacity))
</span><span class="cx">             CRASH();
</span><span class="lines">@@ -128,23 +246,25 @@
</span><span class="cx"> {
</span><span class="cx">     RELEASE_ASSERT(newSize &gt; PageCount::fromBytes(m_size));
</span><span class="cx"> 
</span><del>-    if (verbose)
-        dataLogLn(&quot;Memory::grow to &quot;, newSize, &quot; from &quot;, *this);
</del><ins>+    dataLogLnIf(verbose, &quot;Memory::grow to &quot;, newSize, &quot; from &quot;, *this);
</ins><span class="cx"> 
</span><span class="cx">     if (maximum() &amp;&amp; newSize &gt; maximum())
</span><span class="cx">         return false;
</span><span class="cx"> 
</span><del>-    uint64_t desiredSize = newSize.bytes();
</del><ins>+    size_t desiredSize = newSize.bytes();
</ins><span class="cx"> 
</span><span class="cx">     if (m_memory &amp;&amp; desiredSize &lt;= m_mappedCapacity) {
</span><del>-        bool success = !mprotect(static_cast&lt;uint8_t*&gt;(m_memory) + m_size, static_cast&lt;size_t&gt;(desiredSize - m_size), PROT_READ | PROT_WRITE);
-        RELEASE_ASSERT(success);
</del><ins>+        if (mprotect(static_cast&lt;uint8_t*&gt;(m_memory) + m_size, static_cast&lt;size_t&gt;(desiredSize - m_size), PROT_READ | PROT_WRITE)) {
+            dataLogLnIf(verbose, &quot;Memory::grow in-place failed &quot;, *this);
+            return false;
+        }
+
</ins><span class="cx">         m_size = desiredSize;
</span><del>-        if (verbose)
-            dataLogLn(&quot;Memory::grow in-place &quot;, *this);
</del><ins>+        dataLogLnIf(verbose, &quot;Memory::grow in-place &quot;, *this);
</ins><span class="cx">         return true;
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    ASSERT(mode() != Signaling);
</ins><span class="cx">     // Otherwise, let's try to make some new memory.
</span><span class="cx">     void* newMemory = mmap(nullptr, desiredSize, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0);
</span><span class="cx">     if (newMemory == MAP_FAILED)
</span><span class="lines">@@ -159,11 +279,26 @@
</span><span class="cx">     m_mappedCapacity = desiredSize;
</span><span class="cx">     m_size = desiredSize;
</span><span class="cx"> 
</span><del>-    if (verbose)
-        dataLogLn(&quot;Memory::grow &quot;, *this);
</del><ins>+    dataLogLnIf(verbose, &quot;Memory::grow &quot;, *this);
</ins><span class="cx">     return true;
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void Memory::dump(PrintStream&amp; out) const
+{
+    out.print(&quot;Memory at &quot;, RawPointer(m_memory), &quot;, size &quot;, m_size, &quot;B capacity &quot;, m_mappedCapacity, &quot;B, initial &quot;, m_initial, &quot; maximum &quot;, m_maximum, &quot; mode &quot;, makeString(m_mode));
+}
+
+const char* Memory::makeString(Mode mode) const
+{
+    switch (mode) {
+    case Mode::BoundsChecking: return &quot;BoundsChecking&quot;;
+    case Mode::Signaling: return &quot;Signaling&quot;;
+    case Mode::NumberOfModes: break;
+    }
+    RELEASE_ASSERT_NOT_REACHED();
+    return &quot;&quot;;
+}
+
</ins><span class="cx"> } // namespace JSC
</span><span class="cx"> 
</span><span class="cx"> } // namespace Wasm
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorewasmWasmMemoryh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/wasm/WasmMemory.h (213385 => 213386)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/wasm/WasmMemory.h        2017-03-03 22:19:06 UTC (rev 213385)
+++ trunk/Source/JavaScriptCore/wasm/WasmMemory.h        2017-03-03 22:24:21 UTC (rev 213386)
</span><span class="lines">@@ -27,16 +27,23 @@
</span><span class="cx"> 
</span><span class="cx"> #if ENABLE(WEBASSEMBLY)
</span><span class="cx"> 
</span><del>-#include &quot;WasmCallingConvention.h&quot;
</del><span class="cx"> #include &quot;WasmPageCount.h&quot;
</span><span class="cx"> 
</span><ins>+#include &lt;wtf/Optional.h&gt;
+#include &lt;wtf/RefCounted.h&gt;
+#include &lt;wtf/RefPtr.h&gt;
+
</ins><span class="cx"> namespace WTF {
</span><span class="cx"> class PrintStream;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-namespace JSC { namespace Wasm {
</del><ins>+namespace JSC {
</ins><span class="cx"> 
</span><del>-class Memory {
</del><ins>+class VM;
+
+namespace Wasm {
+
+class Memory : public RefCounted&lt;Memory&gt; {
</ins><span class="cx">     WTF_MAKE_NONCOPYABLE(Memory);
</span><span class="cx">     WTF_MAKE_FAST_ALLOCATED;
</span><span class="cx"> public:
</span><span class="lines">@@ -43,46 +50,46 @@
</span><span class="cx">     void dump(WTF::PrintStream&amp;) const;
</span><span class="cx"> 
</span><span class="cx">     // FIXME: We should support other modes. see: https://bugs.webkit.org/show_bug.cgi?id=162693
</span><del>-    enum class Mode {
-        BoundsChecking
</del><ins>+    enum Mode {
+        BoundsChecking,
+        Signaling,
+        NumberOfModes
</ins><span class="cx">     };
</span><span class="cx">     const char* makeString(Mode) const;
</span><span class="cx"> 
</span><ins>+    explicit operator bool() const { return !!m_memory; }
+
+    static RefPtr&lt;Memory&gt; create(VM&amp;, PageCount initial, PageCount maximum, std::optional&lt;Mode&gt; requiredMode = std::nullopt);
+
</ins><span class="cx">     Memory() = default;
</span><del>-    JS_EXPORT_PRIVATE Memory(PageCount initial, PageCount maximum, bool&amp; failed);
-    Memory(Memory&amp;&amp; other)
-        : m_memory(other.m_memory)
-        , m_size(other.m_size)
-        , m_initial(other.m_initial)
-        , m_maximum(other.m_maximum)
-        , m_mappedCapacity(other.m_mappedCapacity)
-        , m_mode(other.m_mode)
-    {
-        // Moving transfers ownership of the allocated memory.
-        other.m_memory = nullptr;
-    }
</del><span class="cx">     ~Memory();
</span><span class="cx"> 
</span><span class="cx">     void* memory() const { return m_memory; }
</span><del>-    uint64_t size() const { return m_size; }
</del><ins>+    size_t size() const { return m_size; }
</ins><span class="cx">     PageCount sizeInPages() const { return PageCount::fromBytes(m_size); }
</span><span class="cx"> 
</span><span class="cx">     PageCount initial() const { return m_initial; }
</span><span class="cx">     PageCount maximum() const { return m_maximum; }
</span><span class="cx"> 
</span><ins>+    static Mode lastAllocatedMode();
</ins><span class="cx">     Mode mode() const { return m_mode; }
</span><span class="cx"> 
</span><ins>+    // grow() should only be called from the JSWebAssemblyMemory object since that object needs to update internal
+    // pointers with the current base and size.
</ins><span class="cx">     bool grow(PageCount);
</span><span class="cx"> 
</span><del>-    static ptrdiff_t offsetOfMemory() { return OBJECT_OFFSETOF(Memory, m_memory); }
-    static ptrdiff_t offsetOfSize() { return OBJECT_OFFSETOF(Memory, m_size); }
-    
</del><ins>+    void check() {  ASSERT(!deletionHasBegun()); }
</ins><span class="cx"> private:
</span><ins>+    static RefPtr&lt;Memory&gt; createImpl(VM&amp;, PageCount initial, PageCount maximum, std::optional&lt;Mode&gt; requiredMode = std::nullopt);
+    Memory(void* memory, PageCount initial, PageCount maximum, size_t mappedCapacity, Mode);
+    Memory(PageCount initial, PageCount maximum);
+
+    // FIXME: we should move these to the instance to avoid a load on instance-&gt;instance calls.
</ins><span class="cx">     void* m_memory { nullptr };
</span><del>-    uint64_t m_size { 0 };
</del><ins>+    size_t m_size { 0 };
</ins><span class="cx">     PageCount m_initial;
</span><span class="cx">     PageCount m_maximum;
</span><del>-    uint64_t m_mappedCapacity { 0 };
</del><ins>+    size_t m_mappedCapacity { 0 };
</ins><span class="cx">     Mode m_mode { Mode::BoundsChecking };
</span><span class="cx"> };
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorewasmWasmMemoryInformationcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/wasm/WasmMemoryInformation.cpp (213385 => 213386)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/wasm/WasmMemoryInformation.cpp        2017-03-03 22:19:06 UTC (rev 213385)
+++ trunk/Source/JavaScriptCore/wasm/WasmMemoryInformation.cpp        2017-03-03 22:24:21 UTC (rev 213386)
</span><span class="lines">@@ -29,6 +29,7 @@
</span><span class="cx"> #if ENABLE(WEBASSEMBLY)
</span><span class="cx"> 
</span><span class="cx"> #include &quot;WasmCallingConvention.h&quot;
</span><ins>+#include &quot;WasmMemory.h&quot;
</ins><span class="cx"> #include &lt;wtf/NeverDestroyed.h&gt;
</span><span class="cx"> 
</span><span class="cx"> namespace JSC { namespace Wasm {
</span><span class="lines">@@ -48,6 +49,8 @@
</span><span class="cx">         Vector&lt;unsigned&gt; pinnedSizes = { 0 };
</span><span class="cx">         unsigned remainingPinnedRegisters = pinnedSizes.size() + 1;
</span><span class="cx">         jscCallingConvention().m_calleeSaveRegisters.forEach([&amp;] (Reg reg) {
</span><ins>+            if (!reg.isGPR())
+                return;
</ins><span class="cx">             GPRReg gpr = reg.gpr();
</span><span class="cx">             if (!remainingPinnedRegisters || RegisterSet::stackRegisters().get(reg))
</span><span class="cx">                 return;
</span><span class="lines">@@ -71,7 +74,7 @@
</span><span class="cx"> {
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-MemoryInformation::MemoryInformation(PageCount initial, PageCount maximum,  bool isImport)
</del><ins>+MemoryInformation::MemoryInformation(VM&amp; vm, PageCount initial, PageCount maximum, std::optional&lt;Memory::Mode&gt; recompileMode, bool isImport)
</ins><span class="cx">     : m_initial(initial)
</span><span class="cx">     , m_maximum(maximum)
</span><span class="cx">     , m_isImport(isImport)
</span><span class="lines">@@ -79,6 +82,19 @@
</span><span class="cx">     RELEASE_ASSERT(!!m_initial);
</span><span class="cx">     RELEASE_ASSERT(!m_maximum || m_maximum &gt;= m_initial);
</span><span class="cx">     ASSERT(!!*this);
</span><ins>+
+    if (!recompileMode) {
+        if (!isImport) {
+            m_reservedMemory = Memory::create(vm, initial, maximum, Memory::Signaling);
+            if (m_reservedMemory) {
+                ASSERT(!!*m_reservedMemory);
+                m_mode = m_reservedMemory-&gt;mode();
+                return;
+            }
+        }
+        m_mode = Memory::lastAllocatedMode();
+    } else
+        m_mode = *recompileMode;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> } } // namespace JSC::Wasm
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorewasmWasmMemoryInformationh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/wasm/WasmMemoryInformation.h (213385 => 213386)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/wasm/WasmMemoryInformation.h        2017-03-03 22:19:06 UTC (rev 213385)
+++ trunk/Source/JavaScriptCore/wasm/WasmMemoryInformation.h        2017-03-03 22:24:21 UTC (rev 213386)
</span><span class="lines">@@ -28,7 +28,9 @@
</span><span class="cx"> #if ENABLE(WEBASSEMBLY)
</span><span class="cx"> 
</span><span class="cx"> #include &quot;GPRInfo.h&quot;
</span><ins>+#include &quot;WasmMemory.h&quot;
</ins><span class="cx"> #include &quot;WasmPageCount.h&quot;
</span><ins>+#include &lt;wtf/Ref.h&gt;
</ins><span class="cx"> #include &lt;wtf/Vector.h&gt;
</span><span class="cx"> 
</span><span class="cx"> namespace JSC { namespace Wasm {
</span><span class="lines">@@ -52,17 +54,22 @@
</span><span class="cx">         ASSERT(!*this);
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    MemoryInformation(PageCount initial, PageCount maximum, bool isImport);
</del><ins>+    MemoryInformation(VM&amp;, PageCount initial, PageCount maximum, std::optional&lt;Memory::Mode&gt;, bool isImport);
</ins><span class="cx"> 
</span><span class="cx">     PageCount initial() const { return m_initial; }
</span><span class="cx">     PageCount maximum() const { return m_maximum; }
</span><ins>+    bool hasReservedMemory() const { return m_reservedMemory; }
+    RefPtr&lt;Memory&gt; takeReservedMemory() { ASSERT(hasReservedMemory()); return m_reservedMemory.release(); }
+    Memory::Mode mode() const { return m_mode; }
</ins><span class="cx">     bool isImport() const { return m_isImport; }
</span><span class="cx"> 
</span><span class="cx">     explicit operator bool() const { return !!m_initial; }
</span><span class="cx"> 
</span><span class="cx"> private:
</span><ins>+    RefPtr&lt;Memory&gt; m_reservedMemory;
</ins><span class="cx">     PageCount m_initial { };
</span><span class="cx">     PageCount m_maximum { };
</span><ins>+    Memory::Mode m_mode { Memory::Mode::BoundsChecking };
</ins><span class="cx">     bool m_isImport { false };
</span><span class="cx"> };
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorewasmWasmModuleParsercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/wasm/WasmModuleParser.cpp (213385 => 213386)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/wasm/WasmModuleParser.cpp        2017-03-03 22:19:06 UTC (rev 213385)
+++ trunk/Source/JavaScriptCore/wasm/WasmModuleParser.cpp        2017-03-03 22:24:21 UTC (rev 213386)
</span><span class="lines">@@ -316,7 +316,7 @@
</span><span class="cx">     ASSERT(initialPageCount);
</span><span class="cx">     ASSERT(!maximumPageCount || maximumPageCount &gt;= initialPageCount);
</span><span class="cx"> 
</span><del>-    m_result.module-&gt;memory = MemoryInformation(initialPageCount, maximumPageCount, isImport);
</del><ins>+    m_result.module-&gt;memory = MemoryInformation(*m_vm, initialPageCount, maximumPageCount, m_mode, isImport);
</ins><span class="cx">     return { };
</span><span class="cx"> }
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorewasmWasmModuleParserh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/wasm/WasmModuleParser.h (213385 => 213386)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/wasm/WasmModuleParser.h        2017-03-03 22:19:06 UTC (rev 213385)
+++ trunk/Source/JavaScriptCore/wasm/WasmModuleParser.h        2017-03-03 22:24:21 UTC (rev 213386)
</span><span class="lines">@@ -30,6 +30,7 @@
</span><span class="cx"> #include &quot;WasmFormat.h&quot;
</span><span class="cx"> #include &quot;WasmOps.h&quot;
</span><span class="cx"> #include &quot;WasmParser.h&quot;
</span><ins>+#include &lt;wtf/Optional.h&gt;
</ins><span class="cx"> #include &lt;wtf/Vector.h&gt;
</span><span class="cx"> 
</span><span class="cx"> namespace JSC { namespace Wasm {
</span><span class="lines">@@ -43,14 +44,11 @@
</span><span class="cx"> class ModuleParser : public Parser&lt;ModuleParserResult&gt; {
</span><span class="cx"> public:
</span><span class="cx"> 
</span><del>-    ModuleParser(VM* vm, const uint8_t* sourceBuffer, size_t sourceLength)
</del><ins>+    ModuleParser(VM* vm, const uint8_t* sourceBuffer, size_t sourceLength, std::optional&lt;Memory::Mode&gt; mode)
</ins><span class="cx">         : Parser(vm, sourceBuffer, sourceLength)
</span><ins>+        , m_mode(mode)
</ins><span class="cx">     {
</span><span class="cx">     }
</span><del>-    ModuleParser(VM* vm, const Vector&lt;uint8_t&gt;&amp; sourceBuffer)
-        : ModuleParser(vm, sourceBuffer.data(), sourceBuffer.size())
-    {
-    }
</del><span class="cx"> 
</span><span class="cx">     Result WARN_UNUSED_RETURN parse();
</span><span class="cx"> 
</span><span class="lines">@@ -68,6 +66,7 @@
</span><span class="cx">     PartialResult WARN_UNUSED_RETURN parseInitExpr(uint8_t&amp;, uint64_t&amp;, Type&amp; initExprType);
</span><span class="cx"> 
</span><span class="cx">     ModuleParserResult m_result;
</span><ins>+    std::optional&lt;Memory::Mode&gt; m_mode { std::nullopt };
</ins><span class="cx">     bool m_hasTable { false };
</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 (213385 => 213386)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/wasm/WasmPlan.cpp        2017-03-03 22:19:06 UTC (rev 213385)
+++ trunk/Source/JavaScriptCore/wasm/WasmPlan.cpp        2017-03-03 22:24:21 UTC (rev 213386)
</span><span class="lines">@@ -35,6 +35,7 @@
</span><span class="cx"> #include &quot;WasmB3IRGenerator.h&quot;
</span><span class="cx"> #include &quot;WasmBinding.h&quot;
</span><span class="cx"> #include &quot;WasmCallingConvention.h&quot;
</span><ins>+#include &quot;WasmFaultSignalHandler.h&quot;
</ins><span class="cx"> #include &quot;WasmMemory.h&quot;
</span><span class="cx"> #include &quot;WasmModuleParser.h&quot;
</span><span class="cx"> #include &quot;WasmValidate.h&quot;
</span><span class="lines">@@ -61,7 +62,7 @@
</span><span class="cx"> {
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-bool Plan::parseAndValidateModule()
</del><ins>+bool Plan::parseAndValidateModule(std::optional&lt;Memory::Mode&gt; recompileMode)
</ins><span class="cx"> {
</span><span class="cx">     MonotonicTime startTime;
</span><span class="cx">     if (verbose || Options::reportCompileTimes())
</span><span class="lines">@@ -68,7 +69,7 @@
</span><span class="cx">         startTime = MonotonicTime::now();
</span><span class="cx"> 
</span><span class="cx">     {
</span><del>-        ModuleParser moduleParser(m_vm, m_source, m_sourceLength);
</del><ins>+        ModuleParser moduleParser(m_vm, m_source, m_sourceLength, recompileMode);
</ins><span class="cx">         auto parseResult = moduleParser.parse();
</span><span class="cx">         if (!parseResult) {
</span><span class="cx">             m_errorMessage = parseResult.error();
</span><span class="lines">@@ -109,10 +110,12 @@
</span><span class="cx"> // The reason this is OK is that we guarantee that the main thread doesn't continue until all threads
</span><span class="cx"> // that could touch its stack are done executing.
</span><span class="cx"> SUPPRESS_ASAN 
</span><del>-void Plan::run()
</del><ins>+void Plan::run(std::optional&lt;Memory::Mode&gt; recompileMode)
</ins><span class="cx"> {
</span><del>-    if (!parseAndValidateModule())
</del><ins>+    if (!parseAndValidateModule(recompileMode))
</ins><span class="cx">         return;
</span><ins>+    if (recompileMode)
+        ASSERT(m_moduleInformation-&gt;memory.mode() == recompileMode);
</ins><span class="cx"> 
</span><span class="cx">     auto tryReserveCapacity = [this] (auto&amp; vector, size_t size, const char* what) {
</span><span class="cx">         if (UNLIKELY(!vector.tryReserveCapacity(size))) {
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorewasmWasmPlanh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/wasm/WasmPlan.h (213385 => 213386)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/wasm/WasmPlan.h        2017-03-03 22:19:06 UTC (rev 213385)
+++ trunk/Source/JavaScriptCore/wasm/WasmPlan.h        2017-03-03 22:24:21 UTC (rev 213386)
</span><span class="lines">@@ -49,9 +49,9 @@
</span><span class="cx">     JS_EXPORT_PRIVATE Plan(VM*, const uint8_t*, size_t);
</span><span class="cx">     JS_EXPORT_PRIVATE ~Plan();
</span><span class="cx"> 
</span><del>-    bool parseAndValidateModule();
</del><ins>+    bool parseAndValidateModule(std::optional&lt;Memory::Mode&gt; = std::nullopt);
</ins><span class="cx"> 
</span><del>-    JS_EXPORT_PRIVATE void run();
</del><ins>+    JS_EXPORT_PRIVATE void run(std::optional&lt;Memory::Mode&gt; = std::nullopt);
</ins><span class="cx"> 
</span><span class="cx">     JS_EXPORT_PRIVATE void initializeCallees(JSGlobalObject*, std::function&lt;void(unsigned, JSWebAssemblyCallee*, JSWebAssemblyCallee*)&gt;);
</span><span class="cx"> 
</span><span class="lines">@@ -92,6 +92,8 @@
</span><span class="cx">         return WTFMove(m_wasmExitStubs);
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    Memory::Mode mode() const { return m_moduleInformation-&gt;memory.mode(); }
+
</ins><span class="cx"> private:
</span><span class="cx">     std::unique_ptr&lt;ModuleInformation&gt; m_moduleInformation;
</span><span class="cx">     Vector&lt;FunctionLocationInBinary&gt; m_functionLocationInBinary;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorewasmjsJSWebAssemblyCalleecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/wasm/js/JSWebAssemblyCallee.cpp (213385 => 213386)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/wasm/js/JSWebAssemblyCallee.cpp        2017-03-03 22:19:06 UTC (rev 213385)
+++ trunk/Source/JavaScriptCore/wasm/js/JSWebAssemblyCallee.cpp        2017-03-03 22:24:21 UTC (rev 213386)
</span><span class="lines">@@ -29,6 +29,7 @@
</span><span class="cx"> #if ENABLE(WEBASSEMBLY)
</span><span class="cx"> 
</span><span class="cx"> #include &quot;JSCInlines.h&quot;
</span><ins>+#include &quot;WasmFaultSignalHandler.h&quot;
</ins><span class="cx"> 
</span><span class="cx"> namespace JSC {
</span><span class="cx"> 
</span><span class="lines">@@ -43,11 +44,13 @@
</span><span class="cx">     Base::finishCreation(vm);
</span><span class="cx"> 
</span><span class="cx">     m_entrypoint = WTFMove(entrypoint);
</span><ins>+    Wasm::registerCode(vm, m_entrypoint.compilation-&gt;codeRef().executableMemory()-&gt;start(), m_entrypoint.compilation-&gt;codeRef().executableMemory()-&gt;end());
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void JSWebAssemblyCallee::destroy(JSCell* cell)
</span><span class="cx"> {
</span><span class="cx">     JSWebAssemblyCallee* thisObject = static_cast&lt;JSWebAssemblyCallee*&gt;(cell);
</span><ins>+    Wasm::unregisterCode(*cell-&gt;vm(), thisObject-&gt;m_entrypoint.compilation-&gt;codeRef().executableMemory()-&gt;start(), thisObject-&gt;m_entrypoint.compilation-&gt;codeRef().executableMemory()-&gt;end());
</ins><span class="cx">     thisObject-&gt;JSWebAssemblyCallee::~JSWebAssemblyCallee();
</span><span class="cx"> }
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorewasmjsJSWebAssemblyCodeBlockcpp"></a>
<div class="addfile"><h4>Added: trunk/Source/JavaScriptCore/wasm/js/JSWebAssemblyCodeBlock.cpp (0 => 213386)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/wasm/js/JSWebAssemblyCodeBlock.cpp                                (rev 0)
+++ trunk/Source/JavaScriptCore/wasm/js/JSWebAssemblyCodeBlock.cpp        2017-03-03 22:24:21 UTC (rev 213386)
</span><span class="lines">@@ -0,0 +1,85 @@
</span><ins>+/*
+ * Copyright (C) 2017 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 &quot;config.h&quot;
+#include &quot;JSWebAssemblyCodeBlock.h&quot;
+
+#if ENABLE(WEBASSEMBLY)
+
+#include &quot;JSCInlines.h&quot;
+#include &quot;JSWebAssemblyMemory.h&quot;
+#include &quot;JSWebAssemblyModule.h&quot;
+
+namespace JSC {
+
+const ClassInfo JSWebAssemblyCodeBlock::s_info = { &quot;WebAssemblyCodeBlock&quot;, nullptr, 0, CREATE_METHOD_TABLE(JSWebAssemblyCodeBlock) };
+
+JSWebAssemblyCodeBlock::JSWebAssemblyCodeBlock(VM&amp; vm, JSWebAssemblyModule* owner, Bag&lt;CallLinkInfo&gt;&amp;&amp; callLinkInfos, Vector&lt;Wasm::WasmExitStubs&gt;&amp;&amp; wasmExitStubs, Wasm::Memory::Mode mode, unsigned calleeCount)
+    : Base(vm, vm.webAssemblyCodeBlockStructure.get())
+    , m_callLinkInfos(WTFMove(callLinkInfos))
+    , m_wasmExitStubs(WTFMove(wasmExitStubs))
+    , m_mode(mode)
+    , m_calleeCount(calleeCount)
+{
+    m_module.set(vm, this, owner);
+    memset(callees(), 0, m_calleeCount * sizeof(WriteBarrier&lt;JSWebAssemblyCallee&gt;) * 2);
+}
+
+void JSWebAssemblyCodeBlock::destroy(JSCell* cell)
+{
+    static_cast&lt;JSWebAssemblyCodeBlock*&gt;(cell)-&gt;JSWebAssemblyCodeBlock::~JSWebAssemblyCodeBlock();
+}
+
+bool JSWebAssemblyCodeBlock::isSafeToRun(JSWebAssemblyMemory* memory)
+{
+    if (mode() == Wasm::Memory::Signaling)
+        return memory-&gt;memory().mode() == mode();
+    return true;
+}
+
+void JSWebAssemblyCodeBlock::visitChildren(JSCell* cell, SlotVisitor&amp; visitor)
+{
+    JSWebAssemblyCodeBlock* thisObject = jsCast&lt;JSWebAssemblyCodeBlock*&gt;(cell);
+    ASSERT_GC_OBJECT_INHERITS(thisObject, info());
+
+    Base::visitChildren(thisObject, visitor);
+    visitor.append(thisObject-&gt;m_module);
+    for (unsigned i = 0; i &lt; thisObject-&gt;m_calleeCount * 2; i++)
+        visitor.append(thisObject-&gt;callees()[i]);
+
+    visitor.addUnconditionalFinalizer(&amp;thisObject-&gt;m_unconditionalFinalizer);
+}
+
+void JSWebAssemblyCodeBlock::UnconditionalFinalizer::finalizeUnconditionally()
+{
+    JSWebAssemblyCodeBlock* thisObject = bitwise_cast&lt;JSWebAssemblyCodeBlock*&gt;(
+        bitwise_cast&lt;char*&gt;(this) - OBJECT_OFFSETOF(JSWebAssemblyCodeBlock, m_unconditionalFinalizer));
+    for (auto iter = thisObject-&gt;m_callLinkInfos.begin(); !!iter; ++iter)
+        (*iter)-&gt;visitWeak(*thisObject-&gt;vm());
+}
+
+} // namespace JSC
+
+#endif // ENABLE(WEBASSEMBLY)
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCorewasmjsJSWebAssemblyInstancecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/wasm/js/JSWebAssemblyInstance.cpp (213385 => 213386)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/wasm/js/JSWebAssemblyInstance.cpp        2017-03-03 22:19:06 UTC (rev 213385)
+++ trunk/Source/JavaScriptCore/wasm/js/JSWebAssemblyInstance.cpp        2017-03-03 22:24:21 UTC (rev 213386)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> /*
</span><del>- * Copyright (C) 2016 Apple Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2016-2017 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">@@ -38,6 +38,18 @@
</span><span class="cx"> 
</span><span class="cx"> namespace JSC {
</span><span class="cx"> 
</span><ins>+void JSWebAssemblyInstance::setMemory(VM&amp; vm, ExecState* exec, JSWebAssemblyMemory* memory)
+{
+    auto scope = DECLARE_THROW_SCOPE(vm);
+    // We create stub memories even for modules that should eventually get a memory so we want to avoid recompling there.
+    if (memory-&gt;memory()) {
+        auto codeBlock = m_codeBlock-&gt;module()-&gt;codeBlock(vm, exec, memory);
+        RETURN_IF_EXCEPTION(scope,);
+        m_codeBlock.set(vm, this, codeBlock);
+    }
+    m_memory.set(vm, this, memory);
+}
+
</ins><span class="cx"> JSWebAssemblyInstance* JSWebAssemblyInstance::create(VM&amp; vm, Structure* structure, JSWebAssemblyModule* module, JSModuleNamespaceObject* moduleNamespaceObject)
</span><span class="cx"> {
</span><span class="cx">     // FIXME: These objects could be pretty big we should try to throw OOM here.
</span><span class="lines">@@ -67,7 +79,7 @@
</span><span class="cx">     m_globals = MallocPtr&lt;uint64_t&gt;::malloc(extraMemorySize);
</span><span class="cx">     heap()-&gt;reportExtraMemoryAllocated(extraMemorySize);
</span><span class="cx"> 
</span><del>-    m_module.set(vm, this, module);
</del><ins>+    m_codeBlock.set(vm, this, module-&gt;codeBlock());
</ins><span class="cx">     m_moduleNamespaceObject.set(vm, this, moduleNamespaceObject);
</span><span class="cx">     putDirect(vm, Identifier::fromString(&amp;vm, &quot;exports&quot;), moduleNamespaceObject, None);
</span><span class="cx"> }
</span><span class="lines">@@ -83,7 +95,7 @@
</span><span class="cx">     ASSERT_GC_OBJECT_INHERITS(thisObject, info());
</span><span class="cx"> 
</span><span class="cx">     Base::visitChildren(thisObject, visitor);
</span><del>-    visitor.append(thisObject-&gt;m_module);
</del><ins>+    visitor.append(thisObject-&gt;m_codeBlock);
</ins><span class="cx">     visitor.append(thisObject-&gt;m_moduleNamespaceObject);
</span><span class="cx">     visitor.append(thisObject-&gt;m_memory);
</span><span class="cx">     visitor.append(thisObject-&gt;m_table);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorewasmjsJSWebAssemblyInstanceh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/wasm/js/JSWebAssemblyInstance.h (213385 => 213386)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/wasm/js/JSWebAssemblyInstance.h        2017-03-03 22:19:06 UTC (rev 213385)
+++ trunk/Source/JavaScriptCore/wasm/js/JSWebAssemblyInstance.h        2017-03-03 22:24:21 UTC (rev 213386)
</span><span class="lines">@@ -29,6 +29,7 @@
</span><span class="cx"> 
</span><span class="cx"> #include &quot;JSDestructibleObject.h&quot;
</span><span class="cx"> #include &quot;JSObject.h&quot;
</span><ins>+#include &quot;JSWebAssemblyCodeBlock.h&quot;
</ins><span class="cx"> #include &quot;JSWebAssemblyMemory.h&quot;
</span><span class="cx"> #include &quot;JSWebAssemblyTable.h&quot;
</span><span class="cx"> 
</span><span class="lines">@@ -47,12 +48,18 @@
</span><span class="cx"> 
</span><span class="cx">     DECLARE_INFO;
</span><span class="cx"> 
</span><del>-    JSWebAssemblyModule* module()
</del><ins>+    JSWebAssemblyModule* module() const
</ins><span class="cx">     {
</span><del>-        ASSERT(m_module);
-        return m_module.get();
</del><ins>+        ASSERT(m_codeBlock);
+        return m_codeBlock-&gt;module();
</ins><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    JSWebAssemblyCodeBlock* codeBlock() const
+    {
+        ASSERT(m_codeBlock);
+        return m_codeBlock.get();
+    }
+
</ins><span class="cx">     WriteBarrier&lt;JSCell&gt;* importFunction(unsigned idx)
</span><span class="cx">     {
</span><span class="cx">         RELEASE_ASSERT(idx &lt; m_numImportFunctions);
</span><span class="lines">@@ -70,7 +77,9 @@
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     JSWebAssemblyMemory* memory() { return m_memory.get(); }
</span><del>-    void setMemory(VM&amp; vm, JSWebAssemblyMemory* memory) { m_memory.set(vm, this, memory); }
</del><ins>+    // Calling this might trigger a recompile.
+    void setMemory(VM&amp;, ExecState*, JSWebAssemblyMemory*);
+    Wasm::Memory::Mode memoryMode() { return memory()-&gt;memory().mode(); }
</ins><span class="cx"> 
</span><span class="cx">     JSWebAssemblyTable* table() { return m_table.get(); }
</span><span class="cx">     void setTable(VM&amp; vm, JSWebAssemblyTable* table) { m_table.set(vm, this, table); }
</span><span class="lines">@@ -104,7 +113,7 @@
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx"> private:
</span><del>-    WriteBarrier&lt;JSWebAssemblyModule&gt; m_module;
</del><ins>+    WriteBarrier&lt;JSWebAssemblyCodeBlock&gt; m_codeBlock;
</ins><span class="cx">     WriteBarrier&lt;JSModuleNamespaceObject&gt; m_moduleNamespaceObject;
</span><span class="cx">     WriteBarrier&lt;JSWebAssemblyMemory&gt; m_memory;
</span><span class="cx">     WriteBarrier&lt;JSWebAssemblyTable&gt; m_table;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorewasmjsJSWebAssemblyMemorycpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/wasm/js/JSWebAssemblyMemory.cpp (213385 => 213386)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/wasm/js/JSWebAssemblyMemory.cpp        2017-03-03 22:19:06 UTC (rev 213385)
+++ trunk/Source/JavaScriptCore/wasm/js/JSWebAssemblyMemory.cpp        2017-03-03 22:24:21 UTC (rev 213386)
</span><span class="lines">@@ -37,9 +37,10 @@
</span><span class="cx"> 
</span><span class="cx"> const ClassInfo JSWebAssemblyMemory::s_info = { &quot;WebAssembly.Memory&quot;, &amp;Base::s_info, 0, CREATE_METHOD_TABLE(JSWebAssemblyMemory) };
</span><span class="cx"> 
</span><del>-JSWebAssemblyMemory* JSWebAssemblyMemory::create(VM&amp; vm, Structure* structure, Wasm::Memory&amp;&amp; memory)
</del><ins>+JSWebAssemblyMemory* JSWebAssemblyMemory::create(VM&amp; vm, Structure* structure, Ref&lt;Wasm::Memory&gt;&amp;&amp; memory)
</ins><span class="cx"> {
</span><del>-    auto* instance = new (NotNull, allocateCell&lt;JSWebAssemblyMemory&gt;(vm.heap)) JSWebAssemblyMemory(vm, structure, std::forward&lt;Wasm::Memory&gt;(memory));
</del><ins>+    auto* instance = new (NotNull, allocateCell&lt;JSWebAssemblyMemory&gt;(vm.heap)) JSWebAssemblyMemory(vm, structure, WTFMove(memory));
+    instance-&gt;m_memory-&gt;check();
</ins><span class="cx">     instance-&gt;finishCreation(vm);
</span><span class="cx">     return instance;
</span><span class="cx"> }
</span><span class="lines">@@ -49,10 +50,13 @@
</span><span class="cx">     return Structure::create(vm, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), info());
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-JSWebAssemblyMemory::JSWebAssemblyMemory(VM&amp; vm, Structure* structure, Wasm::Memory&amp;&amp; memory)
</del><ins>+JSWebAssemblyMemory::JSWebAssemblyMemory(VM&amp; vm, Structure* structure, Ref&lt;Wasm::Memory&gt;&amp;&amp; memory)
</ins><span class="cx">     : Base(vm, structure)
</span><span class="cx">     , m_memory(WTFMove(memory))
</span><span class="cx"> {
</span><ins>+    ASSERT(m_memory-&gt;refCount() == 1);
+    m_memoryBase = m_memory-&gt;memory();
+    m_memorySize = m_memory-&gt;size();
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> JSArrayBuffer* JSWebAssemblyMemory::buffer(VM&amp; vm, JSGlobalObject* globalObject)
</span><span class="lines">@@ -60,12 +64,10 @@
</span><span class="cx">     if (m_bufferWrapper)
</span><span class="cx">         return m_bufferWrapper.get();
</span><span class="cx"> 
</span><del>-    auto destructor = [] (void*) {
-        // We don't need to do anything here to destroy the memory.
-        // The ArrayBuffer backing the JSArrayBuffer is only owned by us,
-        // so we guarantee its lifecycle.
-    };
-    m_buffer = ArrayBuffer::createFromBytes(memory()-&gt;memory(), memory()-&gt;size(), WTFMove(destructor));
</del><ins>+    // We can't use a ref here since it doesn't have a copy constructor...
+    Ref&lt;Wasm::Memory&gt; protectedMemory = m_memory.get();
+    auto destructor = [protectedMemory = WTFMove(protectedMemory)] (void*) { };
+    m_buffer = ArrayBuffer::createFromBytes(memory().memory(), memory().size(), WTFMove(destructor));
</ins><span class="cx">     m_bufferWrapper.set(vm, this, JSArrayBuffer::create(vm, globalObject-&gt;m_arrayBufferStructure.get(), m_buffer.get()));
</span><span class="cx">     RELEASE_ASSERT(m_bufferWrapper);
</span><span class="cx">     return m_bufferWrapper.get();
</span><span class="lines">@@ -76,7 +78,7 @@
</span><span class="cx">     VM&amp; vm = exec-&gt;vm();
</span><span class="cx">     auto throwScope = DECLARE_THROW_SCOPE(vm);
</span><span class="cx"> 
</span><del>-    Wasm::PageCount oldPageCount = memory()-&gt;sizeInPages();
</del><ins>+    Wasm::PageCount oldPageCount = memory().sizeInPages();
</ins><span class="cx"> 
</span><span class="cx">     if (!Wasm::PageCount::isValid(delta)) {
</span><span class="cx">         if (shouldThrowExceptionsOnFailure)
</span><span class="lines">@@ -92,12 +94,16 @@
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     if (delta) {
</span><del>-        bool success = memory()-&gt;grow(newSize);
</del><ins>+        bool success = memory().grow(newSize);
</ins><span class="cx">         if (!success) {
</span><ins>+            ASSERT(m_memoryBase == memory().memory());
+            ASSERT(m_memorySize == memory().size());
</ins><span class="cx">             if (shouldThrowExceptionsOnFailure)
</span><span class="cx">                 throwException(exec, throwScope, createOutOfMemoryError(exec));
</span><span class="cx">             return Wasm::PageCount();
</span><span class="cx">         }
</span><ins>+        m_memoryBase = memory().memory();
+        m_memorySize = memory().size();
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     // We need to clear out the old array buffer because it might now be pointing
</span><span class="lines">@@ -110,6 +116,7 @@
</span><span class="cx">         m_bufferWrapper.clear();
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    memory().check();
</ins><span class="cx">     return oldPageCount;
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -123,14 +130,7 @@
</span><span class="cx"> {
</span><span class="cx">     auto memory = static_cast&lt;JSWebAssemblyMemory*&gt;(cell);
</span><span class="cx">     ASSERT(memory-&gt;classInfo() == info());
</span><del>-    VM&amp; vm = *memory-&gt;vm();
</del><span class="cx"> 
</span><del>-    if (memory-&gt;m_buffer) {
-        ArrayBufferContents dummyContents;
-        memory-&gt;m_buffer-&gt;transferTo(vm, dummyContents);
-        memory-&gt;m_buffer = nullptr;
-    }
-
</del><span class="cx">     memory-&gt;JSWebAssemblyMemory::~JSWebAssemblyMemory();
</span><span class="cx"> }
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorewasmjsJSWebAssemblyMemoryh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/wasm/js/JSWebAssemblyMemory.h (213385 => 213386)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/wasm/js/JSWebAssemblyMemory.h        2017-03-03 22:19:06 UTC (rev 213385)
+++ trunk/Source/JavaScriptCore/wasm/js/JSWebAssemblyMemory.h        2017-03-03 22:24:21 UTC (rev 213386)
</span><span class="lines">@@ -41,25 +41,27 @@
</span><span class="cx"> public:
</span><span class="cx">     typedef JSDestructibleObject Base;
</span><span class="cx"> 
</span><del>-    static JSWebAssemblyMemory* create(VM&amp;, Structure*, Wasm::Memory&amp;&amp;);
</del><ins>+    static JSWebAssemblyMemory* create(VM&amp;, Structure*, Ref&lt;Wasm::Memory&gt;&amp;&amp;);
</ins><span class="cx">     static Structure* createStructure(VM&amp;, JSGlobalObject*, JSValue);
</span><span class="cx"> 
</span><span class="cx">     DECLARE_INFO;
</span><span class="cx"> 
</span><del>-    Wasm::Memory* memory() { return &amp;m_memory; }
</del><ins>+    Wasm::Memory&amp; memory() { return m_memory.get(); }
</ins><span class="cx">     JSArrayBuffer* buffer(VM&amp; vm, JSGlobalObject*);
</span><span class="cx">     Wasm::PageCount grow(ExecState*, uint32_t delta, bool shouldThrowExceptionsOnFailure);
</span><span class="cx"> 
</span><del>-    static ptrdiff_t offsetOfMemory() { return OBJECT_OFFSETOF(JSWebAssemblyMemory, m_memory) + Wasm::Memory::offsetOfMemory(); }
-    static ptrdiff_t offsetOfSize() { return OBJECT_OFFSETOF(JSWebAssemblyMemory, m_memory) + Wasm::Memory::offsetOfSize(); }
</del><ins>+    static ptrdiff_t offsetOfMemory() { return OBJECT_OFFSETOF(JSWebAssemblyMemory, m_memoryBase); }
+    static ptrdiff_t offsetOfSize() { return OBJECT_OFFSETOF(JSWebAssemblyMemory, m_memorySize); }
</ins><span class="cx"> 
</span><del>-protected:
-    JSWebAssemblyMemory(VM&amp;, Structure*, Wasm::Memory&amp;&amp;);
</del><ins>+private:
+    JSWebAssemblyMemory(VM&amp;, Structure*, Ref&lt;Wasm::Memory&gt;&amp;&amp;);
</ins><span class="cx">     void finishCreation(VM&amp;);
</span><span class="cx">     static void destroy(JSCell*);
</span><span class="cx">     static void visitChildren(JSCell*, SlotVisitor&amp;);
</span><span class="cx"> 
</span><del>-    Wasm::Memory m_memory;
</del><ins>+    void* m_memoryBase;
+    size_t m_memorySize;
+    Ref&lt;Wasm::Memory&gt; m_memory;
</ins><span class="cx">     WriteBarrier&lt;JSArrayBuffer&gt; m_bufferWrapper;
</span><span class="cx">     RefPtr&lt;ArrayBuffer&gt; m_buffer;
</span><span class="cx"> };
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorewasmjsJSWebAssemblyModulecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/wasm/js/JSWebAssemblyModule.cpp (213385 => 213386)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/wasm/js/JSWebAssemblyModule.cpp        2017-03-03 22:19:06 UTC (rev 213385)
+++ trunk/Source/JavaScriptCore/wasm/js/JSWebAssemblyModule.cpp        2017-03-03 22:24:21 UTC (rev 213386)
</span><span class="lines">@@ -30,8 +30,12 @@
</span><span class="cx"> 
</span><span class="cx"> #include &quot;JSCInlines.h&quot;
</span><span class="cx"> #include &quot;JSWebAssemblyCallee.h&quot;
</span><ins>+#include &quot;JSWebAssemblyCodeBlock.h&quot;
+#include &quot;JSWebAssemblyCompileError.h&quot;
+#include &quot;JSWebAssemblyMemory.h&quot;
</ins><span class="cx"> #include &quot;WasmFormat.h&quot;
</span><span class="cx"> #include &quot;WasmMemory.h&quot;
</span><ins>+#include &quot;WasmPlan.h&quot;
</ins><span class="cx"> #include &lt;wtf/StdLibExtras.h&gt;
</span><span class="cx"> 
</span><span class="cx"> namespace JSC {
</span><span class="lines">@@ -38,10 +42,34 @@
</span><span class="cx"> 
</span><span class="cx"> const ClassInfo JSWebAssemblyModule::s_info = { &quot;WebAssembly.Module&quot;, &amp;Base::s_info, nullptr, CREATE_METHOD_TABLE(JSWebAssemblyModule) };
</span><span class="cx"> 
</span><del>-JSWebAssemblyModule* JSWebAssemblyModule::create(VM&amp; vm, Structure* structure, std::unique_ptr&lt;Wasm::ModuleInformation&gt;&amp;&amp; moduleInformation, Bag&lt;CallLinkInfo&gt;&amp;&amp; callLinkInfos, Vector&lt;Wasm::WasmExitStubs&gt;&amp;&amp; wasmExitStubs, SymbolTable* exportSymbolTable, unsigned calleeCount)
</del><ins>+JSWebAssemblyCodeBlock* JSWebAssemblyModule::buildCodeBlock(VM&amp; vm, ExecState* exec, Wasm::Plan&amp; plan, std::optional&lt;Wasm::Memory::Mode&gt; mode)
</ins><span class="cx"> {
</span><del>-    auto* instance = new (NotNull, allocateCell&lt;JSWebAssemblyModule&gt;(vm.heap, allocationSize(calleeCount))) JSWebAssemblyModule(vm, structure, std::forward&lt;std::unique_ptr&lt;Wasm::ModuleInformation&gt;&gt;(moduleInformation), std::forward&lt;Bag&lt;CallLinkInfo&gt;&gt;(callLinkInfos), std::forward&lt;Vector&lt;Wasm::WasmExitStubs&gt;&gt;(wasmExitStubs), calleeCount);
-    instance-&gt;finishCreation(vm, exportSymbolTable);
</del><ins>+    auto scope = DECLARE_THROW_SCOPE(vm);
+    // On failure, a new WebAssembly.CompileError is thrown.
+    plan.run(mode);
+    if (plan.failed()) {
+        throwException(exec, scope, createJSWebAssemblyCompileError(exec, vm, plan.errorMessage()));
+        return nullptr;
+    }
+    if (mode)
+        ASSERT(*mode == plan.mode());
+
+    unsigned calleeCount = plan.internalFunctionCount();
+    auto* codeBlock = JSWebAssemblyCodeBlock::create(vm, this, plan.takeCallLinkInfos(), plan.takeWasmExitStubs(), plan.mode(), calleeCount);
+
+    plan.initializeCallees(exec-&gt;jsCallee()-&gt;globalObject(),
+        [&amp;] (unsigned calleeIndex, JSWebAssemblyCallee* jsEntrypointCallee, JSWebAssemblyCallee* wasmEntrypointCallee) {
+            codeBlock-&gt;setJSEntrypointCallee(vm, calleeIndex, jsEntrypointCallee);
+            codeBlock-&gt;setWasmEntrypointCallee(vm, calleeIndex, wasmEntrypointCallee);
+        });
+    return codeBlock;
+}
+
+JSWebAssemblyModule* JSWebAssemblyModule::create(VM&amp; vm, ExecState* exec, Structure* structure, uint8_t* source, size_t byteSize)
+{
+    auto* instance = new (NotNull, allocateCell&lt;JSWebAssemblyModule&gt;(vm.heap)) JSWebAssemblyModule(vm, structure);
+
+    instance-&gt;finishCreation(vm, exec, source, byteSize);
</ins><span class="cx">     return instance;
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -50,21 +78,61 @@
</span><span class="cx">     return Structure::create(vm, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), info());
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-JSWebAssemblyModule::JSWebAssemblyModule(VM&amp; vm, Structure* structure, std::unique_ptr&lt;Wasm::ModuleInformation&gt;&amp;&amp; moduleInformation, Bag&lt;CallLinkInfo&gt;&amp;&amp; callLinkInfos, Vector&lt;Wasm::WasmExitStubs&gt;&amp;&amp; wasmExitStubs, unsigned calleeCount)
</del><ins>+JSWebAssemblyModule::JSWebAssemblyModule(VM&amp; vm, Structure* structure)
</ins><span class="cx">     : Base(vm, structure)
</span><del>-    , m_moduleInformation(WTFMove(moduleInformation))
-    , m_callLinkInfos(WTFMove(callLinkInfos))
-    , m_wasmExitStubs(WTFMove(wasmExitStubs))
-    , m_calleeCount(calleeCount)
</del><span class="cx"> {
</span><del>-    memset(callees(), 0, m_calleeCount * sizeof(WriteBarrier&lt;JSWebAssemblyCallee&gt;) * 2);
</del><span class="cx"> }
</span><span class="cx"> 
</span><del>-void JSWebAssemblyModule::finishCreation(VM&amp; vm, SymbolTable* exportSymbolTable)
</del><ins>+JSWebAssemblyCodeBlock* JSWebAssemblyModule::codeBlock(VM&amp; vm, ExecState* exec, JSWebAssemblyMemory* memory)
</ins><span class="cx"> {
</span><ins>+    Wasm::Memory::Mode mode = memory-&gt;memory().mode();
+
+    for (unsigned i = 0; i &lt; Wasm::Memory::NumberOfModes; ++i) {
+        if (m_codeBlocks[i] &amp;&amp; m_codeBlocks[i]-&gt;isSafeToRun(memory))
+            return m_codeBlocks[i].get();
+    }
+
+    ASSERT(!m_codeBlocks[mode]);
+    auto scope = DECLARE_THROW_SCOPE(vm);
+    // We don't have a code block for this mode, we need to recompile...
+    Wasm::Plan plan(&amp;vm, static_cast&lt;uint8_t*&gt;(m_sourceBuffer-&gt;data()), m_sourceBuffer-&gt;byteLength());
+
+    auto* codeBlock = buildCodeBlock(vm, exec, plan, mode);
+    RETURN_IF_EXCEPTION(scope, nullptr);
+
+    ASSERT(plan.exports().size() == m_exportSymbolTable-&gt;size());
+    if (!ASSERT_DISABLED) {
+        for (auto&amp; exp : plan.exports())
+            ASSERT_UNUSED(exp, m_exportSymbolTable-&gt;contains(exp.field.impl()));
+    }
+
+    ASSERT(mode == codeBlock-&gt;mode());
+    m_codeBlocks[mode].set(vm, this, codeBlock);
+    return codeBlock;
+}
+
+void JSWebAssemblyModule::finishCreation(VM&amp; vm, ExecState* exec, uint8_t* source, size_t byteSize)
+{
</ins><span class="cx">     Base::finishCreation(vm);
</span><span class="cx">     ASSERT(inherits(vm, info()));
</span><ins>+
+    auto scope = DECLARE_THROW_SCOPE(vm);
+    Wasm::Plan plan(&amp;vm, source, byteSize);
+
+    auto* codeBlock = buildCodeBlock(vm, exec, plan);
+    RETURN_IF_EXCEPTION(scope,);
+
+    // On success, a new WebAssembly.Module object is returned with [[Module]] set to the validated Ast.module.
+    SymbolTable* exportSymbolTable = SymbolTable::create(vm);
+    for (auto&amp; exp : plan.exports()) {
+        auto offset = exportSymbolTable-&gt;takeNextScopeOffset(NoLockingNecessary);
+        exportSymbolTable-&gt;set(NoLockingNecessary, exp.field.impl(), SymbolTableEntry(VarOffset(offset)));
+    }
+
+    m_sourceBuffer = ArrayBuffer::create(source, byteSize);
+    m_moduleInformation = plan.takeModuleInformation();
</ins><span class="cx">     m_exportSymbolTable.set(vm, this, exportSymbolTable);
</span><ins>+    m_codeBlocks[codeBlock-&gt;mode()].set(vm, this, codeBlock);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void JSWebAssemblyModule::destroy(JSCell* cell)
</span><span class="lines">@@ -79,20 +147,10 @@
</span><span class="cx"> 
</span><span class="cx">     Base::visitChildren(thisObject, visitor);
</span><span class="cx">     visitor.append(thisObject-&gt;m_exportSymbolTable);
</span><del>-    for (unsigned i = 0; i &lt; thisObject-&gt;m_calleeCount * 2; i++)
-        visitor.append(thisObject-&gt;callees()[i]);
-
-    visitor.addUnconditionalFinalizer(&amp;thisObject-&gt;m_unconditionalFinalizer);
</del><ins>+    for (unsigned i = 0; i &lt; Wasm::Memory::NumberOfModes; ++i)
+        visitor.append(thisObject-&gt;m_codeBlocks[i]);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-void JSWebAssemblyModule::UnconditionalFinalizer::finalizeUnconditionally()
-{
-    JSWebAssemblyModule* thisObject = bitwise_cast&lt;JSWebAssemblyModule*&gt;(
-        bitwise_cast&lt;char*&gt;(this) - OBJECT_OFFSETOF(JSWebAssemblyModule, m_unconditionalFinalizer));
-    for (auto iter = thisObject-&gt;m_callLinkInfos.begin(); !!iter; ++iter)
-        (*iter)-&gt;visitWeak(*thisObject-&gt;vm());
-}
-
</del><span class="cx"> } // namespace JSC
</span><span class="cx"> 
</span><span class="cx"> #endif // ENABLE(WEBASSEMBLY)
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorewasmjsJSWebAssemblyModuleh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/wasm/js/JSWebAssemblyModule.h (213385 => 213386)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/wasm/js/JSWebAssemblyModule.h        2017-03-03 22:19:06 UTC (rev 213385)
+++ trunk/Source/JavaScriptCore/wasm/js/JSWebAssemblyModule.h        2017-03-03 22:24:21 UTC (rev 213386)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> /*
</span><del>- * Copyright (C) 2016 Apple Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2016-2017 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">@@ -29,7 +29,7 @@
</span><span class="cx"> 
</span><span class="cx"> #include &quot;JSDestructibleObject.h&quot;
</span><span class="cx"> #include &quot;JSObject.h&quot;
</span><del>-#include &quot;JSWebAssemblyCallee.h&quot;
</del><ins>+#include &quot;JSWebAssemblyCodeBlock.h&quot;
</ins><span class="cx"> #include &quot;UnconditionalFinalizer.h&quot;
</span><span class="cx"> #include &quot;WasmFormat.h&quot;
</span><span class="cx"> #include &lt;wtf/Bag.h&gt;
</span><span class="lines">@@ -37,85 +37,47 @@
</span><span class="cx"> 
</span><span class="cx"> namespace JSC {
</span><span class="cx"> 
</span><ins>+namespace Wasm {
+class Plan;
+}
+
</ins><span class="cx"> class SymbolTable;
</span><ins>+class JSWebAssemblyMemory;
</ins><span class="cx"> 
</span><span class="cx"> class JSWebAssemblyModule : public JSDestructibleObject {
</span><span class="cx"> public:
</span><span class="cx">     typedef JSDestructibleObject Base;
</span><span class="cx"> 
</span><del>-    static JSWebAssemblyModule* create(VM&amp;, Structure*, std::unique_ptr&lt;Wasm::ModuleInformation&gt;&amp;&amp;, Bag&lt;CallLinkInfo&gt;&amp;&amp;, Vector&lt;Wasm::WasmExitStubs&gt;&amp;&amp;, SymbolTable*, unsigned);
</del><ins>+    static JSWebAssemblyModule* create(VM&amp;, ExecState*, Structure*, uint8_t* source, size_t byteSize);
</ins><span class="cx">     static Structure* createStructure(VM&amp;, JSGlobalObject*, JSValue);
</span><span class="cx"> 
</span><span class="cx">     DECLARE_INFO;
</span><span class="cx"> 
</span><span class="cx">     const Wasm::ModuleInformation&amp; moduleInformation() const { return *m_moduleInformation.get(); }
</span><ins>+    RefPtr&lt;Wasm::Memory&gt; takeReservedMemory() { return m_moduleInformation-&gt;memory.takeReservedMemory(); }
</ins><span class="cx">     SymbolTable* exportSymbolTable() const { return m_exportSymbolTable.get(); }
</span><span class="cx">     Wasm::SignatureIndex signatureIndexFromFunctionIndexSpace(unsigned functionIndexSpace) const
</span><span class="cx">     {
</span><span class="cx">         return m_moduleInformation-&gt;signatureIndexFromFunctionIndexSpace(functionIndexSpace);
</span><span class="cx">     }
</span><del>-    unsigned functionImportCount() const { return m_wasmExitStubs.size(); }
</del><span class="cx"> 
</span><del>-    JSWebAssemblyCallee* jsEntrypointCalleeFromFunctionIndexSpace(unsigned functionIndexSpace)
-    {
-        RELEASE_ASSERT(functionIndexSpace &gt;= functionImportCount());
-        unsigned calleeIndex = functionIndexSpace - functionImportCount();
-        RELEASE_ASSERT(calleeIndex &lt; m_calleeCount);
-        return callees()[calleeIndex].get();
-    }
</del><ins>+    // Returns the code block that this module was originally compiled expecting to use. This won't need to recompile.
+    JSWebAssemblyCodeBlock* codeBlock() { return m_codeBlocks[m_moduleInformation-&gt;memory.mode()].get(); }
+    // Returns the appropriate code block for the given memory, possibly triggering a recompile.
+    JSWebAssemblyCodeBlock* codeBlock(VM&amp;, ExecState*, JSWebAssemblyMemory*);
</ins><span class="cx"> 
</span><del>-    JSWebAssemblyCallee* wasmEntrypointCalleeFromFunctionIndexSpace(unsigned functionIndexSpace)
-    {
-        RELEASE_ASSERT(functionIndexSpace &gt;= functionImportCount());
-        unsigned calleeIndex = functionIndexSpace - functionImportCount();
-        RELEASE_ASSERT(calleeIndex &lt; m_calleeCount);
-        return callees()[calleeIndex + m_calleeCount].get();
-    }
</del><ins>+private:
+    JSWebAssemblyCodeBlock* buildCodeBlock(VM&amp;, ExecState*, Wasm::Plan&amp;, std::optional&lt;Wasm::Memory::Mode&gt; mode = std::nullopt);
</ins><span class="cx"> 
</span><del>-    void setJSEntrypointCallee(VM&amp; vm, unsigned calleeIndex, JSWebAssemblyCallee* callee)
-    {
-        RELEASE_ASSERT(calleeIndex &lt; m_calleeCount);
-        callees()[calleeIndex].set(vm, this, callee);
-    }
-
-    void setWasmEntrypointCallee(VM&amp; vm, unsigned calleeIndex, JSWebAssemblyCallee* callee)
-    {
-        RELEASE_ASSERT(calleeIndex &lt; m_calleeCount);
-        callees()[calleeIndex + m_calleeCount].set(vm, this, callee);
-    }
-
-    WriteBarrier&lt;JSWebAssemblyCallee&gt;* callees()
-    {
-        return bitwise_cast&lt;WriteBarrier&lt;JSWebAssemblyCallee&gt;*&gt;(bitwise_cast&lt;char*&gt;(this) + offsetOfCallees());
-    }
-
-protected:
-    JSWebAssemblyModule(VM&amp;, Structure*, std::unique_ptr&lt;Wasm::ModuleInformation&gt;&amp;&amp;, Bag&lt;CallLinkInfo&gt;&amp;&amp;, Vector&lt;Wasm::WasmExitStubs&gt;&amp;&amp;, unsigned calleeCount);
-    void finishCreation(VM&amp;, SymbolTable*);
</del><ins>+    JSWebAssemblyModule(VM&amp;, Structure*);
+    void finishCreation(VM&amp;, ExecState*, uint8_t* source, size_t byteSize);
</ins><span class="cx">     static void destroy(JSCell*);
</span><span class="cx">     static void visitChildren(JSCell*, SlotVisitor&amp;);
</span><span class="cx"> 
</span><del>-private:
-    static size_t offsetOfCallees()
-    {
-        return WTF::roundUpToMultipleOf&lt;sizeof(WriteBarrier&lt;JSWebAssemblyCallee&gt;)&gt;(sizeof(JSWebAssemblyModule));
-    }
-
-    static size_t allocationSize(unsigned numCallees)
-    {
-        return offsetOfCallees() + sizeof(WriteBarrier&lt;JSWebAssemblyCallee&gt;) * numCallees * 2;
-    }
-
-    class UnconditionalFinalizer : public JSC::UnconditionalFinalizer { 
-        void finalizeUnconditionally() override;
-    };
-
-    UnconditionalFinalizer m_unconditionalFinalizer;
</del><ins>+    RefPtr&lt;ArrayBuffer&gt; m_sourceBuffer;
</ins><span class="cx">     std::unique_ptr&lt;Wasm::ModuleInformation&gt; m_moduleInformation;
</span><del>-    Bag&lt;CallLinkInfo&gt; m_callLinkInfos;
</del><span class="cx">     WriteBarrier&lt;SymbolTable&gt; m_exportSymbolTable;
</span><del>-    Vector&lt;Wasm::WasmExitStubs&gt; m_wasmExitStubs;
-    unsigned m_calleeCount;
</del><ins>+    WriteBarrier&lt;JSWebAssemblyCodeBlock&gt; m_codeBlocks[Wasm::Memory::NumberOfModes];
</ins><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> } // namespace JSC
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorewasmjsWebAssemblyFunctioncpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/wasm/js/WebAssemblyFunction.cpp (213385 => 213386)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/wasm/js/WebAssemblyFunction.cpp        2017-03-03 22:19:06 UTC (rev 213385)
+++ trunk/Source/JavaScriptCore/wasm/js/WebAssemblyFunction.cpp        2017-03-03 22:24:21 UTC (rev 213386)
</span><span class="lines">@@ -56,6 +56,8 @@
</span><span class="cx">     Wasm::SignatureIndex signatureIndex = wasmFunction-&gt;signatureIndex();
</span><span class="cx">     const Wasm::Signature* signature = Wasm::SignatureInformation::get(&amp;vm, signatureIndex);
</span><span class="cx"> 
</span><ins>+    // Make sure that the memory we think we are going to run with matches the one we expect.
+    ASSERT(wasmFunction-&gt;instance()-&gt;codeBlock()-&gt;isSafeToRun(wasmFunction-&gt;instance()-&gt;memory()));
</ins><span class="cx">     {
</span><span class="cx">         // Check if we have a disallowed I64 use.
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorewasmjsWebAssemblyInstanceConstructorcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/wasm/js/WebAssemblyInstanceConstructor.cpp (213385 => 213386)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/wasm/js/WebAssemblyInstanceConstructor.cpp        2017-03-03 22:19:06 UTC (rev 213385)
+++ trunk/Source/JavaScriptCore/wasm/js/WebAssemblyInstanceConstructor.cpp        2017-03-03 22:24:21 UTC (rev 213386)
</span><span class="lines">@@ -84,12 +84,8 @@
</span><span class="cx"> 
</span><span class="cx">     JSWebAssemblyInstance* instance = JSWebAssemblyInstance::create(vm, instanceStructure, jsModule, moduleRecord-&gt;getModuleNamespace(exec));
</span><span class="cx">     RETURN_IF_EXCEPTION(throwScope, encodedJSValue());
</span><del>-    {
-        // Always start with a dummy Memory, so that wasm -&gt; wasm thunks avoid checking for a nullptr Memory when trying to set pinned registers.
-        Wasm::Memory memory;
-        instance-&gt;setMemory(vm, JSWebAssemblyMemory::create(vm, exec-&gt;lexicalGlobalObject()-&gt;WebAssemblyMemoryStructure(), WTFMove(memory)));
-    }
</del><span class="cx"> 
</span><ins>+
</ins><span class="cx">     // Let funcs, memories and tables be initially-empty lists of callable JavaScript objects, WebAssembly.Memory objects and WebAssembly.Table objects, respectively.
</span><span class="cx">     // Let imports be an initially-empty list of external values.
</span><span class="cx">     unsigned numImportFunctions = 0;
</span><span class="lines">@@ -178,12 +174,12 @@
</span><span class="cx">                 return JSValue::encode(throwException(exec, throwScope, createJSWebAssemblyLinkError(exec, vm, ASCIILiteral(&quot;Memory import is not an instance of WebAssembly.Memory&quot;))));
</span><span class="cx"> 
</span><span class="cx">             Wasm::PageCount expectedInitial = moduleInformation.memory.initial();
</span><del>-            Wasm::PageCount actualInitial = memory-&gt;memory()-&gt;initial();
</del><ins>+            Wasm::PageCount actualInitial = memory-&gt;memory().initial();
</ins><span class="cx">             if (actualInitial &lt; expectedInitial)
</span><span class="cx">                 return JSValue::encode(throwException(exec, throwScope, createJSWebAssemblyLinkError(exec, vm, ASCIILiteral(&quot;Memory import provided an 'initial' that is too small&quot;))));
</span><span class="cx"> 
</span><span class="cx">             if (Wasm::PageCount expectedMaximum = moduleInformation.memory.maximum()) {
</span><del>-                Wasm::PageCount actualMaximum = memory-&gt;memory()-&gt;maximum();
</del><ins>+                Wasm::PageCount actualMaximum = memory-&gt;memory().maximum();
</ins><span class="cx">                 if (!actualMaximum) {
</span><span class="cx">                     return JSValue::encode(
</span><span class="cx">                         throwException(exec, throwScope, createJSWebAssemblyLinkError(exec, vm, ASCIILiteral(&quot;Memory import did not have a 'maximum' but the module requires that it does&quot;))));
</span><span class="lines">@@ -194,9 +190,11 @@
</span><span class="cx">                         throwException(exec, throwScope, createJSWebAssemblyLinkError(exec, vm, ASCIILiteral(&quot;Memory imports 'maximum' is larger than the module's expected 'maximum'&quot;))));
</span><span class="cx">                 }
</span><span class="cx">             }
</span><ins>+
</ins><span class="cx">             // ii. Append v to memories.
</span><span class="cx">             // iii. Append v.[[Memory]] to imports.
</span><del>-            instance-&gt;setMemory(vm, memory);
</del><ins>+            instance-&gt;setMemory(vm, exec, memory);
+            RETURN_IF_EXCEPTION(throwScope, encodedJSValue());
</ins><span class="cx">             break;
</span><span class="cx">         }
</span><span class="cx">         case Wasm::ExternalKind::Global: {
</span><span class="lines">@@ -237,12 +235,17 @@
</span><span class="cx">         if (moduleInformation.memory &amp;&amp; !hasMemoryImport) {
</span><span class="cx">             RELEASE_ASSERT(!moduleInformation.memory.isImport());
</span><span class="cx">             // We create a memory when it's a memory definition.
</span><del>-            bool failed;
-            Wasm::Memory memory(moduleInformation.memory.initial(), moduleInformation.memory.maximum(), failed);
-            if (failed)
-                return JSValue::encode(throwException(exec, throwScope, createOutOfMemoryError(exec)));
-            instance-&gt;setMemory(vm,
-               JSWebAssemblyMemory::create(vm, exec-&gt;lexicalGlobalObject()-&gt;WebAssemblyMemoryStructure(), WTFMove(memory)));
</del><ins>+            RefPtr&lt;Wasm::Memory&gt; memory;
+            if (moduleInformation.memory.hasReservedMemory())
+                memory = jsModule-&gt;takeReservedMemory();
+            else {
+                memory = Wasm::Memory::create(vm, moduleInformation.memory.initial(), moduleInformation.memory.maximum());
+                if (!memory)
+                    return JSValue::encode(throwException(exec, throwScope, createOutOfMemoryError(exec)));
+            }
+            instance-&gt;setMemory(vm, exec,
+                JSWebAssemblyMemory::create(vm, exec-&gt;lexicalGlobalObject()-&gt;WebAssemblyMemoryStructure(), memory.releaseNonNull()));
+            RETURN_IF_EXCEPTION(throwScope, encodedJSValue());
</ins><span class="cx">         }
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="lines">@@ -265,6 +268,11 @@
</span><span class="cx">         }
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    if (!instance-&gt;memory()) {
+        // Make sure we have a dummy memory, so that wasm -&gt; wasm thunks avoid checking for a nullptr Memory when trying to set pinned registers.
+        instance-&gt;setMemory(vm, exec, JSWebAssemblyMemory::create(vm, exec-&gt;lexicalGlobalObject()-&gt;WebAssemblyMemoryStructure(), adoptRef(*(new Wasm::Memory()))));
+    }
+
</ins><span class="cx">     // Globals
</span><span class="cx">     {
</span><span class="cx">         ASSERT(numImportGlobals == moduleInformation.firstInternalGlobal);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorewasmjsWebAssemblyMemoryConstructorcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/wasm/js/WebAssemblyMemoryConstructor.cpp (213385 => 213386)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/wasm/js/WebAssemblyMemoryConstructor.cpp        2017-03-03 22:19:06 UTC (rev 213385)
+++ trunk/Source/JavaScriptCore/wasm/js/WebAssemblyMemoryConstructor.cpp        2017-03-03 22:24:21 UTC (rev 213386)
</span><span class="lines">@@ -96,12 +96,11 @@
</span><span class="cx">         }
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    bool failed;
-    Wasm::Memory memory(initialPageCount, maximumPageCount, failed);
-    if (failed)
</del><ins>+    RefPtr&lt;Wasm::Memory&gt; memory = Wasm::Memory::create(vm, initialPageCount, maximumPageCount);
+    if (!memory)
</ins><span class="cx">         return JSValue::encode(throwException(exec, throwScope, createOutOfMemoryError(exec)));
</span><span class="cx"> 
</span><del>-    return JSValue::encode(JSWebAssemblyMemory::create(vm, exec-&gt;lexicalGlobalObject()-&gt;WebAssemblyMemoryStructure(), WTFMove(memory)));
</del><ins>+    return JSValue::encode(JSWebAssemblyMemory::create(vm, exec-&gt;lexicalGlobalObject()-&gt;WebAssemblyMemoryStructure(), adoptRef(*memory.leakRef())));
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> static EncodedJSValue JSC_HOST_CALL callJSWebAssemblyMemory(ExecState* state)
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorewasmjsWebAssemblyModuleConstructorcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/wasm/js/WebAssemblyModuleConstructor.cpp (213385 => 213386)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/wasm/js/WebAssemblyModuleConstructor.cpp        2017-03-03 22:19:06 UTC (rev 213385)
+++ trunk/Source/JavaScriptCore/wasm/js/WebAssemblyModuleConstructor.cpp        2017-03-03 22:24:21 UTC (rev 213386)
</span><span class="lines">@@ -80,31 +80,8 @@
</span><span class="cx">     uint8_t* base = getWasmBufferFromValue(state, state-&gt;argument(0), byteOffset, byteSize);
</span><span class="cx">     RETURN_IF_EXCEPTION(scope, { });
</span><span class="cx"> 
</span><del>-    Wasm::Plan plan(&amp;vm, base + byteOffset, byteSize);
-    // On failure, a new WebAssembly.CompileError is thrown.
-    plan.run();
-    if (plan.failed())
-        return throwException(state, scope, createJSWebAssemblyCompileError(state, vm, plan.errorMessage()));
-
-    // On success, a new WebAssembly.Module object is returned with [[Module]] set to the validated Ast.module.
-
-    // The export symbol table is the same for all Instances of a Module.
-    SymbolTable* exportSymbolTable = SymbolTable::create(vm);
-    for (auto&amp; exp : plan.exports()) {
-        auto offset = exportSymbolTable-&gt;takeNextScopeOffset(NoLockingNecessary);
-        exportSymbolTable-&gt;set(NoLockingNecessary, exp.field.impl(), SymbolTableEntry(VarOffset(offset)));
-    }
-
-    // Only wasm-internal functions have a callee, stubs to JS do not.
-    unsigned calleeCount = plan.internalFunctionCount();
-    JSWebAssemblyModule* result = JSWebAssemblyModule::create(vm, structure, plan.takeModuleInformation(), plan.takeCallLinkInfos(), plan.takeWasmExitStubs(), exportSymbolTable, calleeCount);
-    plan.initializeCallees(state-&gt;jsCallee()-&gt;globalObject(), 
-        [&amp;] (unsigned calleeIndex, JSWebAssemblyCallee* jsEntrypointCallee, JSWebAssemblyCallee* wasmEntrypointCallee) {
-            result-&gt;setJSEntrypointCallee(vm, calleeIndex, jsEntrypointCallee);
-            result-&gt;setWasmEntrypointCallee(vm, calleeIndex, wasmEntrypointCallee);
-        });
-
-    return result;
</del><ins>+    scope.release();
+    return JSWebAssemblyModule::create(vm, state, structure, base + byteOffset, byteSize);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> WebAssemblyModuleConstructor* WebAssemblyModuleConstructor::create(VM&amp; vm, Structure* structure, WebAssemblyModulePrototype* thisPrototype)
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorewasmjsWebAssemblyModuleRecordcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/wasm/js/WebAssemblyModuleRecord.cpp (213385 => 213386)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/wasm/js/WebAssemblyModuleRecord.cpp        2017-03-03 22:19:06 UTC (rev 213385)
+++ trunk/Source/JavaScriptCore/wasm/js/WebAssemblyModuleRecord.cpp        2017-03-03 22:24:21 UTC (rev 213386)
</span><span class="lines">@@ -92,10 +92,11 @@
</span><span class="cx">     auto* globalObject = state-&gt;lexicalGlobalObject();
</span><span class="cx"> 
</span><span class="cx">     JSWebAssemblyModule* module = instance-&gt;module();
</span><ins>+    JSWebAssemblyCodeBlock* codeBlock = instance-&gt;codeBlock();
</ins><span class="cx">     const Wasm::ModuleInformation&amp; moduleInformation = module-&gt;moduleInformation();
</span><span class="cx"> 
</span><span class="cx">     SymbolTable* exportSymbolTable = module-&gt;exportSymbolTable();
</span><del>-    unsigned functionImportCount = module-&gt;functionImportCount();
</del><ins>+    unsigned functionImportCount = codeBlock-&gt;functionImportCount();
</ins><span class="cx"> 
</span><span class="cx">     // FIXME wire up the imports. https://bugs.webkit.org/show_bug.cgi?id=165118
</span><span class="cx"> 
</span><span class="lines">@@ -116,8 +117,8 @@
</span><span class="cx">             //     a. Let func be an Exported Function Exotic Object created from c.
</span><span class="cx">             //     b. Append func to funcs.
</span><span class="cx">             //     c. Return func.
</span><del>-            JSWebAssemblyCallee* jsEntrypointCallee = module-&gt;jsEntrypointCalleeFromFunctionIndexSpace(exp.kindIndex);
-            JSWebAssemblyCallee* wasmEntrypointCallee = module-&gt;wasmEntrypointCalleeFromFunctionIndexSpace(exp.kindIndex);
</del><ins>+            JSWebAssemblyCallee* jsEntrypointCallee = codeBlock-&gt;jsEntrypointCalleeFromFunctionIndexSpace(exp.kindIndex);
+            JSWebAssemblyCallee* wasmEntrypointCallee = codeBlock-&gt;wasmEntrypointCalleeFromFunctionIndexSpace(exp.kindIndex);
</ins><span class="cx">             Wasm::SignatureIndex signatureIndex = module-&gt;signatureIndexFromFunctionIndexSpace(exp.kindIndex);
</span><span class="cx">             const Wasm::Signature* signature = Wasm::SignatureInformation::get(&amp;vm, signatureIndex);
</span><span class="cx">             WebAssemblyFunction* function = WebAssemblyFunction::create(vm, globalObject, signature-&gt;argumentCount(), exp.field.string(), instance, jsEntrypointCallee, wasmEntrypointCallee, signatureIndex);
</span><span class="lines">@@ -182,12 +183,12 @@
</span><span class="cx">         // The start function must not take any arguments or return anything. This is enforced by the parser.
</span><span class="cx">         ASSERT(!signature-&gt;argumentCount());
</span><span class="cx">         ASSERT(signature-&gt;returnType() == Wasm::Void);
</span><del>-        if (startFunctionIndexSpace &lt; module-&gt;functionImportCount()) {
</del><ins>+        if (startFunctionIndexSpace &lt; codeBlock-&gt;functionImportCount()) {
</ins><span class="cx">             JSCell* startFunction = instance-&gt;importFunction(startFunctionIndexSpace)-&gt;get();
</span><span class="cx">             m_startFunction.set(vm, this, startFunction);
</span><span class="cx">         } else {
</span><del>-            JSWebAssemblyCallee* jsEntrypointCallee = module-&gt;jsEntrypointCalleeFromFunctionIndexSpace(startFunctionIndexSpace);
-            JSWebAssemblyCallee* wasmEntrypointCallee = module-&gt;wasmEntrypointCalleeFromFunctionIndexSpace(startFunctionIndexSpace);
</del><ins>+            JSWebAssemblyCallee* jsEntrypointCallee = codeBlock-&gt;jsEntrypointCalleeFromFunctionIndexSpace(startFunctionIndexSpace);
+            JSWebAssemblyCallee* wasmEntrypointCallee = codeBlock-&gt;wasmEntrypointCalleeFromFunctionIndexSpace(startFunctionIndexSpace);
</ins><span class="cx">             WebAssemblyFunction* function = WebAssemblyFunction::create(vm, globalObject, signature-&gt;argumentCount(), &quot;start&quot;, instance, jsEntrypointCallee, wasmEntrypointCallee, signatureIndex);
</span><span class="cx">             m_startFunction.set(vm, this, function);
</span><span class="cx">         }
</span><span class="lines">@@ -211,6 +212,7 @@
</span><span class="cx"> 
</span><span class="cx">     {
</span><span class="cx">         JSWebAssemblyModule* module = m_instance-&gt;module();
</span><ins>+        JSWebAssemblyCodeBlock* codeBlock = m_instance-&gt;codeBlock();
</ins><span class="cx">         const Wasm::ModuleInformation&amp; moduleInformation = module-&gt;moduleInformation();
</span><span class="cx">         JSWebAssemblyTable* table = m_instance-&gt;table();
</span><span class="cx">         for (const Wasm::Element&amp; element : moduleInformation.elements) {
</span><span class="lines">@@ -233,13 +235,13 @@
</span><span class="cx">                 // for the import.
</span><span class="cx">                 // https://bugs.webkit.org/show_bug.cgi?id=165510
</span><span class="cx">                 uint32_t functionIndex = element.functionIndices[i];
</span><del>-                if (functionIndex &lt; module-&gt;functionImportCount()) {
</del><ins>+                if (functionIndex &lt; codeBlock-&gt;functionImportCount()) {
</ins><span class="cx">                     return JSValue::decode(
</span><span class="cx">                         throwVMRangeError(state, scope, ASCIILiteral(&quot;Element is setting the table value with an import. This is not yet implemented. FIXME.&quot;)));
</span><span class="cx">                 }
</span><span class="cx"> 
</span><del>-                JSWebAssemblyCallee* jsEntrypointCallee = module-&gt;jsEntrypointCalleeFromFunctionIndexSpace(functionIndex);
-                JSWebAssemblyCallee* wasmEntrypointCallee = module-&gt;wasmEntrypointCalleeFromFunctionIndexSpace(functionIndex);
</del><ins>+                JSWebAssemblyCallee* jsEntrypointCallee = codeBlock-&gt;jsEntrypointCalleeFromFunctionIndexSpace(functionIndex);
+                JSWebAssemblyCallee* wasmEntrypointCallee = codeBlock-&gt;wasmEntrypointCalleeFromFunctionIndexSpace(functionIndex);
</ins><span class="cx">                 Wasm::SignatureIndex signatureIndex = module-&gt;signatureIndexFromFunctionIndexSpace(functionIndex);
</span><span class="cx">                 const Wasm::Signature* signature = Wasm::SignatureInformation::get(&amp;vm, signatureIndex);
</span><span class="cx">                 // FIXME: Say we export local function &quot;foo&quot; at function index 0.
</span><span class="lines">@@ -259,8 +261,8 @@
</span><span class="cx">         const Vector&lt;Wasm::Segment::Ptr&gt;&amp; data = m_instance-&gt;module()-&gt;moduleInformation().data;
</span><span class="cx">         JSWebAssemblyMemory* jsMemory = m_instance-&gt;memory();
</span><span class="cx">         if (!data.isEmpty()) {
</span><del>-            uint8_t* memory = reinterpret_cast&lt;uint8_t*&gt;(jsMemory-&gt;memory()-&gt;memory());
-            uint64_t sizeInBytes = jsMemory-&gt;memory()-&gt;size();
</del><ins>+            uint8_t* memory = reinterpret_cast&lt;uint8_t*&gt;(jsMemory-&gt;memory().memory());
+            uint64_t sizeInBytes = jsMemory-&gt;memory().size();
</ins><span class="cx">             for (auto&amp; segment : data) {
</span><span class="cx">                 if (segment-&gt;sizeInBytes) {
</span><span class="cx">                     uint32_t offset;
</span></span></pre></div>
<a id="trunkSourceWTFChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WTF/ChangeLog (213385 => 213386)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WTF/ChangeLog        2017-03-03 22:19:06 UTC (rev 213385)
+++ trunk/Source/WTF/ChangeLog        2017-03-03 22:24:21 UTC (rev 213386)
</span><span class="lines">@@ -1,3 +1,28 @@
</span><ins>+2017-03-03  Keith Miller  &lt;keith_miller@apple.com&gt;
+
+        WASM should support faster loads.
+        https://bugs.webkit.org/show_bug.cgi?id=162693
+
+        Reviewed by Saam Barati.
+
+        Add new forms of dataLog that take a boolean which describes if the log should happen. This makes cases where we have a static const bool for printing nicer since you can do:
+
+        dataLogIf(verbose, things, to, print);
+
+        instead of:
+
+        if (verbose)
+            dataLog(things, to, print);
+
+        Also, add a operator! to Ref that has the same semantics as C++ refs.
+
+        * wtf/DataLog.h:
+        (WTF::dataLogLn):
+        (WTF::dataLogIf):
+        (WTF::dataLogLnIf):
+        * wtf/Ref.h:
+        (WTF::Ref::operator!):
+
</ins><span class="cx"> 2017-03-02  Jer Noble  &lt;jer.noble@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Sufficently large timeValue and timeScale arguments to MediaTime will cause wrapping in toTimeScale().
</span></span></pre></div>
<a id="trunkSourceWTFwtfDataLogh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WTF/wtf/DataLog.h (213385 => 213386)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WTF/wtf/DataLog.h        2017-03-03 22:19:06 UTC (rev 213385)
+++ trunk/Source/WTF/wtf/DataLog.h        2017-03-03 22:24:21 UTC (rev 213386)
</span><span class="lines">@@ -49,13 +49,29 @@
</span><span class="cx"> template&lt;typename... Types&gt;
</span><span class="cx"> void dataLogLn(const Types&amp;... values)
</span><span class="cx"> {
</span><del>-    dataFile().print(values..., &quot;\n&quot;);
</del><ins>+    dataLog(values..., &quot;\n&quot;);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><ins>+template&lt;typename... Types&gt;
+void dataLogIf(bool shouldLog, const Types&amp;... values)
+{
+    if (shouldLog)
+        dataLog(values...);
+}
+
+template&lt;typename... Types&gt;
+void dataLogLnIf(bool shouldLog, const Types&amp;... values)
+{
+    if (shouldLog)
+        dataLogLn(values...);
+}
+
</ins><span class="cx"> } // namespace WTF
</span><span class="cx"> 
</span><span class="cx"> using WTF::dataLog;
</span><span class="cx"> using WTF::dataLogLn;
</span><ins>+using WTF::dataLogIf;
+using WTF::dataLogLnIf;
</ins><span class="cx"> using WTF::dataLogF;
</span><span class="cx"> using WTF::dataLogFString;
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWTFwtfRefh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WTF/wtf/Ref.h (213385 => 213386)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WTF/wtf/Ref.h        2017-03-03 22:19:06 UTC (rev 213385)
+++ trunk/Source/WTF/wtf/Ref.h        2017-03-03 22:24:21 UTC (rev 213386)
</span><span class="lines">@@ -137,6 +137,7 @@
</span><span class="cx">     T* ptr() const { ASSERT(m_ptr); return m_ptr; }
</span><span class="cx">     T&amp; get() const { ASSERT(m_ptr); return *m_ptr; }
</span><span class="cx">     operator T&amp;() const { ASSERT(m_ptr); return *m_ptr; }
</span><ins>+    bool operator!() const { ASSERT(m_ptr); return !*m_ptr; }
</ins><span class="cx"> 
</span><span class="cx">     template&lt;typename U&gt; Ref&lt;T&gt; replace(Ref&lt;U&gt;&amp;&amp;) WARN_UNUSED_RETURN;
</span><span class="cx"> 
</span></span></pre>
</div>
</div>

</body>
</html>