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

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

<h3>Log Message</h3>
<pre>Add support for WASM Memory.
https://bugs.webkit.org/show_bug.cgi?id=161710

Reviewed by Geoffrey Garen.

JSTests:

Add store and load opcodes to wasm.json. Additionally, add new
enums for those opcodes in the generator.

* stress/wasm/generate-wasmops-header.js:
(const.template.pragma.once.ENABLE.WEBASSEMBLY.include.cstdint.namespace.JSC.namespace.WASM.enum.LoadOpType):
(const.template.pragma.once.ENABLE.WEBASSEMBLY.include.cstdint.namespace.JSC.namespace.WASM.enum.StoreOpType):

Source/JavaScriptCore:

This patch add initial support for WASM memory operations. First,
it adds the concept of a WASM Module memory management object.
This object currently mmaps a 32-bit address space for WASM use,
although it marks all the memory outside the current breakpoint as
PROT_NONE. For now, we do a range check on each store and load. In
the future, we should change this to be an signal handler that
checks what module the program trapped in.

Additionally, this patch changes the way that our temporary tests
call into WASM code. There is now a true &quot;thunk&quot; that relocates
arguments and calls into WASM. This thunk does not tail call
because we use pinned values to memory base-pointer and
size. We use the new B3 pinned register api to pin the values.

* CMakeLists.txt:
* Configurations/ToolExecutable.xcconfig:
* JavaScriptCore.xcodeproj/project.pbxproj:
* testWASM.cpp:
(runWASMTests):
(main):
* wasm/WASMB3IRGenerator.cpp:
(JSC::WASM::createJSWrapper):
(JSC::WASM::parseAndCompile):
* wasm/WASMB3IRGenerator.h:
* wasm/WASMCallingConvention.h:
(JSC::WASM::CallingConvention::iterate):
(JSC::WASM::CallingConvention::setupCall):
(JSC::WASM::nextJSCOffset):
* wasm/WASMFormat.h:
* wasm/WASMFunctionParser.h:
(JSC::WASM::FunctionParser&lt;Context&gt;::parseExpression):
* wasm/WASMMemory.cpp: Copied from Source/JavaScriptCore/wasm/WASMPlan.cpp.
(JSC::WASM::Memory::Memory):
* wasm/WASMMemory.h: Copied from Source/JavaScriptCore/wasm/WASMModuleParser.h.
(JSC::WASM::Memory::~Memory):
(JSC::WASM::Memory::memory):
(JSC::WASM::Memory::size):
(JSC::WASM::Memory::pinnedRegisters):
(JSC::WASM::Memory::mode):
(JSC::WASM::Memory::growMemory):
(JSC::WASM::Memory::offsetOfSize):
* wasm/WASMModuleParser.cpp:
(JSC::WASM::ModuleParser::parse):
(JSC::WASM::ModuleParser::parseMemory):
* wasm/WASMModuleParser.h:
(JSC::WASM::ModuleParser::functionInformation):
(JSC::WASM::ModuleParser::memory):
* wasm/WASMOps.h:
* wasm/WASMPlan.cpp:
(JSC::WASM::Plan::Plan):
* wasm/WASMPlan.h:
* wasm/WASMSections.h:</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkJSTestsChangeLog">trunk/JSTests/ChangeLog</a></li>
<li><a href="#trunkJSTestswasmgeneratewasmopsheaderjs">trunk/JSTests/wasm/generate-wasmops-header.js</a></li>
<li><a href="#trunkSourceJavaScriptCoreCMakeListstxt">trunk/Source/JavaScriptCore/CMakeLists.txt</a></li>
<li><a href="#trunkSourceJavaScriptCoreChangeLog">trunk/Source/JavaScriptCore/ChangeLog</a></li>
<li><a href="#trunkSourceJavaScriptCoreConfigurationsToolExecutablexcconfig">trunk/Source/JavaScriptCore/Configurations/ToolExecutable.xcconfig</a></li>
<li><a href="#trunkSourceJavaScriptCoreJavaScriptCorexcodeprojprojectpbxproj">trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj</a></li>
<li><a href="#trunkSourceJavaScriptCoretestWASMcpp">trunk/Source/JavaScriptCore/testWASM.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorewasmWASMB3IRGeneratorcpp">trunk/Source/JavaScriptCore/wasm/WASMB3IRGenerator.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorewasmWASMB3IRGeneratorh">trunk/Source/JavaScriptCore/wasm/WASMB3IRGenerator.h</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="#trunkSourceJavaScriptCorewasmWASMFunctionParserh">trunk/Source/JavaScriptCore/wasm/WASMFunctionParser.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="#trunkSourceJavaScriptCorewasmWASMOpsh">trunk/Source/JavaScriptCore/wasm/WASMOps.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="#trunkSourceJavaScriptCorewasmWASMSectionsh">trunk/Source/JavaScriptCore/wasm/WASMSections.h</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#trunkSourceJavaScriptCorewasmWASMMemorycpp">trunk/Source/JavaScriptCore/wasm/WASMMemory.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorewasmWASMMemoryh">trunk/Source/JavaScriptCore/wasm/WASMMemory.h</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkJSTestsChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/JSTests/ChangeLog (207452 => 207453)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JSTests/ChangeLog        2016-10-18 01:25:54 UTC (rev 207452)
+++ trunk/JSTests/ChangeLog        2016-10-18 02:02:48 UTC (rev 207453)
</span><span class="lines">@@ -1,3 +1,17 @@
</span><ins>+2016-10-17  Keith Miller  &lt;keith_miller@apple.com&gt;
+
+        Add support for WASM Memory.
+        https://bugs.webkit.org/show_bug.cgi?id=161710
+
+        Reviewed by Geoffrey Garen.
+
+        Add store and load opcodes to wasm.json. Additionally, add new
+        enums for those opcodes in the generator.
+
+        * stress/wasm/generate-wasmops-header.js:
+        (const.template.pragma.once.ENABLE.WEBASSEMBLY.include.cstdint.namespace.JSC.namespace.WASM.enum.LoadOpType):
+        (const.template.pragma.once.ENABLE.WEBASSEMBLY.include.cstdint.namespace.JSC.namespace.WASM.enum.StoreOpType):
+
</ins><span class="cx"> 2016-10-17  Saam Barati  &lt;sbarati@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Add more tests for the double-&gt;String conversion in ValueAdd constant folding
</span></span></pre></div>
<a id="trunkJSTestswasmgeneratewasmopsheaderjs"></a>
<div class="modfile"><h4>Modified: trunk/JSTests/wasm/generate-wasmops-header.js (207452 => 207453)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JSTests/wasm/generate-wasmops-header.js        2016-10-18 01:25:54 UTC (rev 207452)
+++ trunk/JSTests/wasm/generate-wasmops-header.js        2016-10-18 02:02:48 UTC (rev 207453)
</span><span class="lines">@@ -36,6 +36,10 @@
</span><span class="cx">     ...opcodeMacroizer(op =&gt; op.category === &quot;arithmetic&quot; &amp;&amp; op.parameter.length === 1),
</span><span class="cx">     &quot;\n\n#define FOR_EACH_WASM_BINARY_OP(macro)&quot;,
</span><span class="cx">     ...opcodeMacroizer(op =&gt; (op.category === &quot;arithmetic&quot; || op.category === &quot;comparison&quot;) &amp;&amp; op.parameter.length === 2),
</span><ins>+    &quot;\n\n#define FOR_EACH_WASM_MEMORY_LOAD_OP(macro)&quot;,
+    ...opcodeMacroizer(op =&gt; (op.category === &quot;memory&quot; &amp;&amp; op.return.length === 1)),
+    &quot;\n\n#define FOR_EACH_WASM_MEMORY_STORE_OP(macro)&quot;,
+    ...opcodeMacroizer(op =&gt; (op.category === &quot;memory&quot; &amp;&amp; op.return.length === 0)),
</ins><span class="cx">     &quot;\n\n&quot;].join(&quot;&quot;);
</span><span class="cx"> 
</span><span class="cx"> const opValueSet = new Set(opcodeIterator(op =&gt; true, op =&gt; opcodes[op].value)());
</span><span class="lines">@@ -94,7 +98,9 @@
</span><span class="cx">     FOR_EACH_WASM_SPECIAL_OP(macro) \\
</span><span class="cx">     FOR_EACH_WASM_CONTROL_FLOW_OP(macro) \\
</span><span class="cx">     FOR_EACH_WASM_UNARY_OP(macro) \\
</span><del>-    FOR_EACH_WASM_BINARY_OP(macro)
</del><ins>+    FOR_EACH_WASM_BINARY_OP(macro) \\
+    FOR_EACH_WASM_MEMORY_LOAD_OP(macro) \\
+    FOR_EACH_WASM_MEMORY_STORE_OP(macro)
</ins><span class="cx"> 
</span><span class="cx"> #define CREATE_ENUM_VALUE(name, id, b3op) name = id,
</span><span class="cx"> 
</span><span class="lines">@@ -118,6 +124,14 @@
</span><span class="cx">     FOR_EACH_WASM_UNARY_OP(CREATE_ENUM_VALUE)
</span><span class="cx"> };
</span><span class="cx"> 
</span><ins>+enum class LoadOpType : uint8_t {
+    FOR_EACH_WASM_MEMORY_LOAD_OP(CREATE_ENUM_VALUE)
+};
+
+enum class StoreOpType : uint8_t {
+    FOR_EACH_WASM_MEMORY_STORE_OP(CREATE_ENUM_VALUE)
+};
+
</ins><span class="cx"> #undef CREATE_ENUM_VALUE
</span><span class="cx"> 
</span><span class="cx"> inline bool isControlOp(OpType op)
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreCMakeListstxt"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/CMakeLists.txt (207452 => 207453)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/CMakeLists.txt        2016-10-18 01:25:54 UTC (rev 207452)
+++ trunk/Source/JavaScriptCore/CMakeLists.txt        2016-10-18 02:02:48 UTC (rev 207453)
</span><span class="lines">@@ -863,6 +863,7 @@
</span><span class="cx">     wasm/JSWASMModule.cpp
</span><span class="cx">     wasm/WASMB3IRGenerator.cpp
</span><span class="cx">     wasm/WASMCallingConvention.cpp
</span><ins>+    wasm/WASMMemory.cpp
</ins><span class="cx">     wasm/WASMModuleParser.cpp
</span><span class="cx">     wasm/WASMPlan.cpp
</span><span class="cx">     wasm/WebAssemblyObject.cpp
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ChangeLog (207452 => 207453)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ChangeLog        2016-10-18 01:25:54 UTC (rev 207452)
+++ trunk/Source/JavaScriptCore/ChangeLog        2016-10-18 02:02:48 UTC (rev 207453)
</span><span class="lines">@@ -1,3 +1,63 @@
</span><ins>+2016-10-17  Keith Miller  &lt;keith_miller@apple.com&gt;
+
+        Add support for WASM Memory.
+        https://bugs.webkit.org/show_bug.cgi?id=161710
+
+        Reviewed by Geoffrey Garen.
+
+        This patch add initial support for WASM memory operations. First,
+        it adds the concept of a WASM Module memory management object.
+        This object currently mmaps a 32-bit address space for WASM use,
+        although it marks all the memory outside the current breakpoint as
+        PROT_NONE. For now, we do a range check on each store and load. In
+        the future, we should change this to be an signal handler that
+        checks what module the program trapped in.
+
+        Additionally, this patch changes the way that our temporary tests
+        call into WASM code. There is now a true &quot;thunk&quot; that relocates
+        arguments and calls into WASM. This thunk does not tail call
+        because we use pinned values to memory base-pointer and
+        size. We use the new B3 pinned register api to pin the values.
+
+        * CMakeLists.txt:
+        * Configurations/ToolExecutable.xcconfig:
+        * JavaScriptCore.xcodeproj/project.pbxproj:
+        * testWASM.cpp:
+        (runWASMTests):
+        (main):
+        * wasm/WASMB3IRGenerator.cpp:
+        (JSC::WASM::createJSWrapper):
+        (JSC::WASM::parseAndCompile):
+        * wasm/WASMB3IRGenerator.h:
+        * wasm/WASMCallingConvention.h:
+        (JSC::WASM::CallingConvention::iterate):
+        (JSC::WASM::CallingConvention::setupCall):
+        (JSC::WASM::nextJSCOffset):
+        * wasm/WASMFormat.h:
+        * wasm/WASMFunctionParser.h:
+        (JSC::WASM::FunctionParser&lt;Context&gt;::parseExpression):
+        * wasm/WASMMemory.cpp: Copied from Source/JavaScriptCore/wasm/WASMPlan.cpp.
+        (JSC::WASM::Memory::Memory):
+        * wasm/WASMMemory.h: Copied from Source/JavaScriptCore/wasm/WASMModuleParser.h.
+        (JSC::WASM::Memory::~Memory):
+        (JSC::WASM::Memory::memory):
+        (JSC::WASM::Memory::size):
+        (JSC::WASM::Memory::pinnedRegisters):
+        (JSC::WASM::Memory::mode):
+        (JSC::WASM::Memory::growMemory):
+        (JSC::WASM::Memory::offsetOfSize):
+        * wasm/WASMModuleParser.cpp:
+        (JSC::WASM::ModuleParser::parse):
+        (JSC::WASM::ModuleParser::parseMemory):
+        * wasm/WASMModuleParser.h:
+        (JSC::WASM::ModuleParser::functionInformation):
+        (JSC::WASM::ModuleParser::memory):
+        * wasm/WASMOps.h:
+        * wasm/WASMPlan.cpp:
+        (JSC::WASM::Plan::Plan):
+        * wasm/WASMPlan.h:
+        * wasm/WASMSections.h:
+
</ins><span class="cx"> 2016-10-17  Joseph Pecoraro  &lt;pecoraro@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Web Inspector: Add toggles for debugger pauses at console.assert failures
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreConfigurationsToolExecutablexcconfig"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/Configurations/ToolExecutable.xcconfig (207452 => 207453)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/Configurations/ToolExecutable.xcconfig        2016-10-18 01:25:54 UTC (rev 207452)
+++ trunk/Source/JavaScriptCore/Configurations/ToolExecutable.xcconfig        2016-10-18 02:02:48 UTC (rev 207453)
</span><span class="lines">@@ -31,6 +31,7 @@
</span><span class="cx"> CODE_SIGN_ENTITLEMENTS_ios_testair = entitlements.plist;
</span><span class="cx"> CODE_SIGN_ENTITLEMENTS_ios_testapi = entitlements.plist;
</span><span class="cx"> CODE_SIGN_ENTITLEMENTS_ios_testb3 = entitlements.plist;
</span><ins>+CODE_SIGN_ENTITLEMENTS_ios_testWASM = entitlements.plist;
</ins><span class="cx"> CODE_SIGN_ENTITLEMENTS_ios_testRegExp = entitlements.plist;
</span><span class="cx"> 
</span><span class="cx"> SKIP_INSTALL = $(SKIP_INSTALL_$(FORCE_TOOL_INSTALL));
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreJavaScriptCorexcodeprojprojectpbxproj"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj (207452 => 207453)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj        2016-10-18 01:25:54 UTC (rev 207452)
+++ trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj        2016-10-18 02:02:48 UTC (rev 207453)
</span><span class="lines">@@ -1216,6 +1216,8 @@
</span><span class="cx">                 534C457C1BC72411007476A7 /* JSTypedArrayViewConstructor.h in Headers */ = {isa = PBXBuildFile; fileRef = 534C457B1BC72411007476A7 /* JSTypedArrayViewConstructor.h */; };
</span><span class="cx">                 534C457E1BC72549007476A7 /* JSTypedArrayViewConstructor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 534C457D1BC72549007476A7 /* JSTypedArrayViewConstructor.cpp */; };
</span><span class="cx">                 53529A4C1C457B75000B49C6 /* APIUtils.h in Headers */ = {isa = PBXBuildFile; fileRef = 53529A4B1C457B75000B49C6 /* APIUtils.h */; };
</span><ins>+                535557141D9D9EA5006D583B /* WASMMemory.h in Headers */ = {isa = PBXBuildFile; fileRef = 535557131D9D9EA5006D583B /* WASMMemory.h */; };
+                535557161D9DFA32006D583B /* WASMMemory.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 535557151D9DFA32006D583B /* WASMMemory.cpp */; };
</ins><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><span class="cx">                 53917E7B1B7906FA000EBD33 /* JSGenericTypedArrayViewPrototypeFunctions.h in Headers */ = {isa = PBXBuildFile; fileRef = 53917E7A1B7906E4000EBD33 /* JSGenericTypedArrayViewPrototypeFunctions.h */; };
</span><span class="lines">@@ -3463,6 +3465,8 @@
</span><span class="cx">                 534C457B1BC72411007476A7 /* JSTypedArrayViewConstructor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSTypedArrayViewConstructor.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 534C457D1BC72549007476A7 /* JSTypedArrayViewConstructor.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSTypedArrayViewConstructor.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 53529A4B1C457B75000B49C6 /* APIUtils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = APIUtils.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><ins>+                535557131D9D9EA5006D583B /* WASMMemory.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WASMMemory.h; sourceTree = &quot;&lt;group&gt;&quot;; };
+                535557151D9DFA32006D583B /* WASMMemory.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WASMMemory.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</ins><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><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="lines">@@ -5699,6 +5703,8 @@
</span><span class="cx">                                 53F40E901D5903020099A1B6 /* WASMOps.h */,
</span><span class="cx">                                 7BC547D21B69599B00959B58 /* WASMFormat.h */,
</span><span class="cx">                                 53F40E8A1D5901BB0099A1B6 /* WASMFunctionParser.h */,
</span><ins>+                                535557151D9DFA32006D583B /* WASMMemory.cpp */,
+                                535557131D9D9EA5006D583B /* WASMMemory.h */,
</ins><span class="cx">                                 53F40E961D5A7BEC0099A1B6 /* WASMModuleParser.cpp */,
</span><span class="cx">                                 53F40E941D5A7AEF0099A1B6 /* WASMModuleParser.h */,
</span><span class="cx">                                 531374BE1D5CE95000AF7A0B /* WASMPlan.cpp */,
</span><span class="lines">@@ -7871,6 +7877,7 @@
</span><span class="cx">                                 142E3138134FF0A600AFADB5 /* HandleStack.h in Headers */,
</span><span class="cx">                                 1478297B1379E8A800A7C2A3 /* HandleTypes.h in Headers */,
</span><span class="cx">                                 0F10F1A31C420BF0001C07D2 /* AirCustom.h in Headers */,
</span><ins>+                                535557141D9D9EA5006D583B /* WASMMemory.h in Headers */,
</ins><span class="cx">                                 14BA7A9813AADFF8005B7C2C /* Heap.h in Headers */,
</span><span class="cx">                                 0F32BD111BB34F190093A57F /* HeapHelperPool.h in Headers */,
</span><span class="cx">                                 C2DA778318E259990066FCB6 /* HeapInlines.h in Headers */,
</span><span class="lines">@@ -9213,6 +9220,7 @@
</span><span class="cx">                                 0F5A1273192D9FDF008764A3 /* DFGDoesGC.cpp in Sources */,
</span><span class="cx">                                 0FD3C82614115D4000FD81CB /* DFGDriver.cpp in Sources */,
</span><span class="cx">                                 0FF0F19E16B72A0B005DF95B /* DFGEdge.cpp in Sources */,
</span><ins>+                                535557161D9DFA32006D583B /* WASMMemory.cpp in Sources */,
</ins><span class="cx">                                 0F8F14331ADF090100ED792C /* DFGEpoch.cpp in Sources */,
</span><span class="cx">                                 0FBC0AE71496C7C400D4FBDD /* DFGExitProfile.cpp in Sources */,
</span><span class="cx">                                 A78A9774179738B8009DF744 /* DFGFailedFinalizer.cpp in Sources */,
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoretestWASMcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/testWASM.cpp (207452 => 207453)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/testWASM.cpp        2016-10-18 01:25:54 UTC (rev 207452)
+++ trunk/Source/JavaScriptCore/testWASM.cpp        2016-10-18 02:02:48 UTC (rev 207453)
</span><span class="lines">@@ -32,7 +32,9 @@
</span><span class="cx"> #include &quot;LLIntThunks.h&quot;
</span><span class="cx"> #include &quot;ProtoCallFrame.h&quot;
</span><span class="cx"> #include &quot;VM.h&quot;
</span><ins>+#include &quot;WASMMemory.h&quot;
</ins><span class="cx"> #include &quot;WASMPlan.h&quot;
</span><ins>+
</ins><span class="cx"> #include &lt;wtf/DataLog.h&gt;
</span><span class="cx"> #include &lt;wtf/LEBDecoder.h&gt;
</span><span class="cx"> 
</span><span class="lines">@@ -242,8 +244,469 @@
</span><span class="cx"> {
</span><span class="cx">     {
</span><span class="cx">         // Generated from:
</span><ins>+        // (module
+        //  (memory 1)
+        //  (func (export &quot;i32_load8_s&quot;) (param $i i32) (param $ptr i32) (result i32)
+        //   (i64.store (get_local $ptr) (get_local $i))
+        //   (return (i64.load (get_local $ptr)))
+        //   )
+        //  )
+        Vector&lt;uint8_t&gt; vector = {
+            0x00, 0x61, 0x73, 0x6d, 0x0c, 0x00, 0x00, 0x00, 0x01, 0x87, 0x80, 0x80, 0x80, 0x00, 0x01, 0x40,
+            0x02, 0x02, 0x01, 0x01, 0x02, 0x03, 0x82, 0x80, 0x80, 0x80, 0x00, 0x01, 0x00, 0x05, 0x83, 0x80,
+            0x80, 0x80, 0x00, 0x01, 0x01, 0x01, 0x07, 0x8f, 0x80, 0x80, 0x80, 0x00, 0x01, 0x0b, 0x69, 0x33,
+            0x32, 0x5f, 0x6c, 0x6f, 0x61, 0x64, 0x38, 0x5f, 0x73, 0x00, 0x00, 0x0a, 0x95, 0x80, 0x80, 0x80,
+            0x00, 0x01, 0x8f, 0x80, 0x80, 0x80, 0x00, 0x00, 0x14, 0x01, 0x14, 0x00, 0x34, 0x03, 0x00, 0x14,
+            0x01, 0x2b, 0x03, 0x00, 0x09, 0x0f
+        };
+
+        Plan plan(*vm, vector);
+        if (plan.result.size() != 1 || !plan.result[0]) {
+            dataLogLn(&quot;Module failed to compile correctly.&quot;);
+            CRASH();
+        }
+
+        // Test this doesn't crash.
+        CHECK_EQ(invoke&lt;int&gt;(*plan.result[0]-&gt;jsEntryPoint, { box(0), box(10) }), 0);
+        CHECK_EQ(invoke&lt;int&gt;(*plan.result[0]-&gt;jsEntryPoint, { box(100), box(2) }), 100);
+        CHECK_EQ(invoke&lt;int&gt;(*plan.result[0]-&gt;jsEntryPoint, { box(1), box(100) }), 1);
+    }
+
+    {
+        // Generated from:
+        // (module
+        //  (memory 1)
+        //  (func (export &quot;i32_load8_s&quot;) (param $i i32) (param $ptr i32) (result i32)
+        //   (i32.store (get_local $ptr) (get_local $i))
+        //   (return (i32.load (get_local $ptr)))
+        //   )
+        //  )
+        Vector&lt;uint8_t&gt; vector = {
+            0x00, 0x61, 0x73, 0x6d, 0x0c, 0x00, 0x00, 0x00, 0x01, 0x87, 0x80, 0x80, 0x80, 0x00, 0x01, 0x40,
+            0x02, 0x01, 0x01, 0x01, 0x01, 0x03, 0x82, 0x80, 0x80, 0x80, 0x00, 0x01, 0x00, 0x05, 0x83, 0x80,
+            0x80, 0x80, 0x00, 0x01, 0x01, 0x01, 0x07, 0x8f, 0x80, 0x80, 0x80, 0x00, 0x01, 0x0b, 0x69, 0x33,
+            0x32, 0x5f, 0x6c, 0x6f, 0x61, 0x64, 0x38, 0x5f, 0x73, 0x00, 0x00, 0x0a, 0x95, 0x80, 0x80, 0x80,
+            0x00, 0x01, 0x8f, 0x80, 0x80, 0x80, 0x00, 0x00, 0x14, 0x01, 0x14, 0x00, 0x33, 0x02, 0x00, 0x14,
+            0x01, 0x2a, 0x02, 0x00, 0x09, 0x0f
+        };
+
+        Plan plan(*vm, vector);
+        if (plan.result.size() != 1 || !plan.result[0]) {
+            dataLogLn(&quot;Module failed to compile correctly.&quot;);
+            CRASH();
+        }
+
+        // Test this doesn't crash.
+        CHECK_EQ(invoke&lt;int&gt;(*plan.result[0]-&gt;jsEntryPoint, { box(0), box(10) }), 0);
+        CHECK_EQ(invoke&lt;int&gt;(*plan.result[0]-&gt;jsEntryPoint, { box(100), box(2) }), 100);
+        CHECK_EQ(invoke&lt;int&gt;(*plan.result[0]-&gt;jsEntryPoint, { box(1), box(100) }), 1);
+    }
+
+    {
+        // Generated from:
</ins><span class="cx">         //    (module
</span><del>-        //     (func (export &quot;dumb-eq&quot;) (param $x i32) (param $y i32) (result i32)
</del><ins>+        //     (memory 1)
+        //     (func (export &quot;write_array&quot;) (param $x i32) (param $p i32) (param $length i32) (local $i i32)
+        //      (set_local $i (i32.const 0))
+        //      (block
+        //       (loop
+        //        (br_if 1 (i32.ge_u (get_local $i) (get_local $length)))
+        //        (i32.store (i32.add (get_local $p) (i32.mul (get_local $i) (i32.const 4))) (get_local $x))
+        //        (set_local $i (i32.add (i32.const 1) (get_local $i)))
+        //        (br 0)
+        //        )
+        //       )
+        //      (return)
+        //      )
+        //     )
+        Vector&lt;uint8_t&gt; vector = {
+            0x00, 0x61, 0x73, 0x6d, 0x0c, 0x00, 0x00, 0x00, 0x01, 0x87, 0x80, 0x80, 0x80, 0x00, 0x01, 0x40,
+            0x03, 0x01, 0x01, 0x01, 0x00, 0x03, 0x82, 0x80, 0x80, 0x80, 0x00, 0x01, 0x00, 0x05, 0x83, 0x80,
+            0x80, 0x80, 0x00, 0x01, 0x01, 0x01, 0x07, 0x8f, 0x80, 0x80, 0x80, 0x00, 0x01, 0x0b, 0x77, 0x72,
+            0x69, 0x74, 0x65, 0x5f, 0x61, 0x72, 0x72, 0x61, 0x79, 0x00, 0x00, 0x0a, 0xb2, 0x80, 0x80, 0x80,
+            0x00, 0x01, 0xac, 0x80, 0x80, 0x80, 0x00, 0x01, 0x01, 0x01, 0x10, 0x00, 0x15, 0x03, 0x01, 0x00,
+            0x02, 0x00, 0x14, 0x03, 0x14, 0x02, 0x56, 0x07, 0x01, 0x14, 0x01, 0x14, 0x03, 0x10, 0x04, 0x42,
+            0x40, 0x14, 0x00, 0x33, 0x02, 0x00, 0x10, 0x01, 0x14, 0x03, 0x40, 0x15, 0x03, 0x06, 0x00, 0x0f,
+            0x0f, 0x09, 0x0f
+        };
+
+        Plan plan(*vm, vector);
+        if (plan.result.size() != 1 || !plan.result[0]) {
+            dataLogLn(&quot;Module failed to compile correctly.&quot;);
+            CRASH();
+        }
+        ASSERT(plan.memory-&gt;size());
+
+        // Test this doesn't crash.
+        unsigned length = 5;
+        unsigned offset = sizeof(uint32_t);
+        uint32_t* memory = static_cast&lt;uint32_t*&gt;(plan.memory-&gt;memory());
+        invoke&lt;void&gt;(*plan.result[0]-&gt;jsEntryPoint, { box(100), box(offset), box(length) });
+        offset /= sizeof(uint32_t);
+        CHECK_EQ(memory[offset - 1], 0u);
+        CHECK_EQ(memory[offset + length], 0u);
+        for (unsigned i = 0; i &lt; length; ++i)
+            CHECK_EQ(memory[i + offset], 100u);
+
+        length = 10;
+        offset = 5 * sizeof(uint32_t);
+        invoke&lt;void&gt;(*plan.result[0]-&gt;jsEntryPoint, { box(5), box(offset), box(length) });
+        offset /= sizeof(uint32_t);
+        CHECK_EQ(memory[offset - 1], 100u);
+        CHECK_EQ(memory[offset + length], 0u);
+        for (unsigned i = 0; i &lt; length; ++i)
+            CHECK_EQ(memory[i + offset], 5u);
+    }
+
+    {
+        // Generated from:
+        //    (module
+        //     (memory 1)
+        //     (func (export &quot;write_array&quot;) (param $x i32) (param $p i32) (param $length i32) (local $i i32)
+        //      (set_local $i (i32.const 0))
+        //      (block
+        //       (loop
+        //        (br_if 1 (i32.ge_u (get_local $i) (get_local $length)))
+        //        (i32.store8 (i32.add (get_local $p) (get_local $i)) (get_local $x))
+        //        (set_local $i (i32.add (i32.const 1) (get_local $i)))
+        //        (br 0)
+        //        )
+        //       )
+        //      (return)
+        //      )
+        //     )
+        Vector&lt;uint8_t&gt; vector = {
+            0x00, 0x61, 0x73, 0x6d, 0x0c, 0x00, 0x00, 0x00, 0x01, 0x87, 0x80, 0x80, 0x80, 0x00, 0x01, 0x40,
+            0x03, 0x01, 0x01, 0x01, 0x00, 0x03, 0x82, 0x80, 0x80, 0x80, 0x00, 0x01, 0x00, 0x05, 0x83, 0x80,
+            0x80, 0x80, 0x00, 0x01, 0x01, 0x01, 0x07, 0x8f, 0x80, 0x80, 0x80, 0x00, 0x01, 0x0b, 0x77, 0x72,
+            0x69, 0x74, 0x65, 0x5f, 0x61, 0x72, 0x72, 0x61, 0x79, 0x00, 0x00, 0x0a, 0xaf, 0x80, 0x80, 0x80,
+            0x00, 0x01, 0xa9, 0x80, 0x80, 0x80, 0x00, 0x01, 0x01, 0x01, 0x10, 0x00, 0x15, 0x03, 0x01, 0x00,
+            0x02, 0x00, 0x14, 0x03, 0x14, 0x02, 0x56, 0x07, 0x01, 0x14, 0x01, 0x14, 0x03, 0x40, 0x14, 0x00,
+            0x2e, 0x00, 0x00, 0x10, 0x01, 0x14, 0x03, 0x40, 0x15, 0x03, 0x06, 0x00, 0x0f, 0x0f, 0x09, 0x0f
+        };
+
+        Plan plan(*vm, vector);
+        if (plan.result.size() != 1 || !plan.result[0]) {
+            dataLogLn(&quot;Module failed to compile correctly.&quot;);
+            CRASH();
+        }
+        ASSERT(plan.memory-&gt;size());
+
+        // Test this doesn't crash.
+        unsigned length = 5;
+        unsigned offset = 1;
+        uint8_t* memory = static_cast&lt;uint8_t*&gt;(plan.memory-&gt;memory());
+        invoke&lt;void&gt;(*plan.result[0]-&gt;jsEntryPoint, { box(100), box(offset), box(length) });
+        CHECK_EQ(memory[offset - 1], 0u);
+        CHECK_EQ(memory[offset + length], 0u);
+        for (unsigned i = 0; i &lt; length; ++i)
+            CHECK_EQ(memory[i + offset], 100u);
+
+        length = 10;
+        offset = 5;
+        invoke&lt;void&gt;(*plan.result[0]-&gt;jsEntryPoint, { box(5), box(offset), box(length) });
+        CHECK_EQ(memory[offset - 1], 100u);
+        CHECK_EQ(memory[offset + length], 0u);
+        for (unsigned i = 0; i &lt; length; ++i)
+            CHECK_EQ(memory[i + offset], 5u);
+    }
+
+    {
+        // Generated from:
+        //    (module
+        //     (memory 1)
+        //     (func (export &quot;i32_load8_s&quot;) (param $i i32) (param $ptr i32) (result i32)
+        //      (i32.store8 (get_local $ptr) (get_local $i))
+        //      (return (i32.load8_s (get_local $ptr)))
+        //      )
+        //     )
+        Vector&lt;uint8_t&gt; vector = {
+            0x00, 0x61, 0x73, 0x6d, 0x0c, 0x00, 0x00, 0x00, 0x01, 0x87, 0x80, 0x80, 0x80, 0x00, 0x01, 0x40,
+            0x02, 0x01, 0x01, 0x01, 0x01, 0x03, 0x82, 0x80, 0x80, 0x80, 0x00, 0x01, 0x00, 0x05, 0x83, 0x80,
+            0x80, 0x80, 0x00, 0x01, 0x01, 0x01, 0x07, 0x8f, 0x80, 0x80, 0x80, 0x00, 0x01, 0x0b, 0x69, 0x33,
+            0x32, 0x5f, 0x6c, 0x6f, 0x61, 0x64, 0x38, 0x5f, 0x73, 0x00, 0x00, 0x0a, 0x95, 0x80, 0x80, 0x80,
+            0x00, 0x01, 0x8f, 0x80, 0x80, 0x80, 0x00, 0x00, 0x14, 0x01, 0x14, 0x00, 0x2e, 0x00, 0x00, 0x14,
+            0x01, 0x20, 0x00, 0x00, 0x09, 0x0f
+        };
+
+        Plan plan(*vm, vector);
+        if (plan.result.size() != 1 || !plan.result[0]) {
+            dataLogLn(&quot;Module failed to compile correctly.&quot;);
+            CRASH();
+        }
+        ASSERT(plan.memory-&gt;size());
+
+        // Test this doesn't crash.
+        CHECK_EQ(invoke&lt;int&gt;(*plan.result[0]-&gt;jsEntryPoint, { box(0), box(10) }), 0);
+        CHECK_EQ(invoke&lt;int&gt;(*plan.result[0]-&gt;jsEntryPoint, { box(100), box(2) }), 100);
+        CHECK_EQ(invoke&lt;int&gt;(*plan.result[0]-&gt;jsEntryPoint, { box(1), box(100) }), 1);
+    }
+
+    {
+        // Generated from:
+        //    (module
+        //     (memory 1)
+        //     (func (export &quot;i32_load8_s&quot;) (param $i i32) (result i32)
+        //      (i32.store8 (i32.const 8) (get_local $i))
+        //      (return (i32.load8_s (i32.const 8)))
+        //      )
+        //     )
+        Vector&lt;uint8_t&gt; vector = {
+            0x00, 0x61, 0x73, 0x6d, 0x0c, 0x00, 0x00, 0x00, 0x01, 0x86, 0x80, 0x80, 0x80, 0x00, 0x01, 0x40,
+            0x01, 0x01, 0x01, 0x01, 0x03, 0x82, 0x80, 0x80, 0x80, 0x00, 0x01, 0x00, 0x05, 0x83, 0x80, 0x80,
+            0x80, 0x00, 0x01, 0x01, 0x01, 0x07, 0x8f, 0x80, 0x80, 0x80, 0x00, 0x01, 0x0b, 0x69, 0x33, 0x32,
+            0x5f, 0x6c, 0x6f, 0x61, 0x64, 0x38, 0x5f, 0x73, 0x00, 0x00, 0x0a, 0x95, 0x80, 0x80, 0x80, 0x00,
+            0x01, 0x8f, 0x80, 0x80, 0x80, 0x00, 0x00, 0x10, 0x08, 0x14, 0x00, 0x2e, 0x00, 0x00, 0x10, 0x08,
+            0x20, 0x00, 0x00, 0x09, 0x0f
+        };
+
+        Plan plan(*vm, vector);
+        if (plan.result.size() != 1 || !plan.result[0]) {
+            dataLogLn(&quot;Module failed to compile correctly.&quot;);
+            CRASH();
+        }
+
+        // Test this doesn't crash.
+        CHECK_EQ(invoke&lt;int&gt;(*plan.result[0]-&gt;jsEntryPoint, { box(0) }), 0);
+        CHECK_EQ(invoke&lt;int&gt;(*plan.result[0]-&gt;jsEntryPoint, { box(100) }), 100);
+        CHECK_EQ(invoke&lt;int&gt;(*plan.result[0]-&gt;jsEntryPoint, { box(1) }), 1);
+    }
+
+    {
+        // Generated from:
+        // (module
+        //  (memory 1)
+        //  (func (export &quot;i32_load8_s&quot;) (param $i i32) (param $ptr i32) (result i32)
+        //   (i32.store (get_local $ptr) (get_local $i))
+        //   (return (i32.load (get_local $ptr)))
+        //   )
+        //  )
+        Vector&lt;uint8_t&gt; vector = {
+            0x00, 0x61, 0x73, 0x6d, 0x0c, 0x00, 0x00, 0x00, 0x01, 0x87, 0x80, 0x80, 0x80, 0x00, 0x01, 0x40,
+            0x02, 0x02, 0x01, 0x01, 0x02, 0x03, 0x82, 0x80, 0x80, 0x80, 0x00, 0x01, 0x00, 0x05, 0x83, 0x80,
+            0x80, 0x80, 0x00, 0x01, 0x01, 0x01, 0x07, 0x8f, 0x80, 0x80, 0x80, 0x00, 0x01, 0x0b, 0x69, 0x33,
+            0x32, 0x5f, 0x6c, 0x6f, 0x61, 0x64, 0x38, 0x5f, 0x73, 0x00, 0x00, 0x0a, 0x95, 0x80, 0x80, 0x80,
+            0x00, 0x01, 0x8f, 0x80, 0x80, 0x80, 0x00, 0x00, 0x14, 0x01, 0x14, 0x00, 0x34, 0x03, 0x00, 0x14,
+            0x01, 0x2b, 0x03, 0x00, 0x09, 0x0f
+        };
+
+        Plan plan(*vm, vector);
+        if (plan.result.size() != 1 || !plan.result[0]) {
+            dataLogLn(&quot;Module failed to compile correctly.&quot;);
+            CRASH();
+        }
+
+        // Test this doesn't crash.
+        CHECK_EQ(invoke&lt;int&gt;(*plan.result[0]-&gt;jsEntryPoint, { box(0), box(10) }), 0);
+        CHECK_EQ(invoke&lt;int&gt;(*plan.result[0]-&gt;jsEntryPoint, { box(100), box(2) }), 100);
+        CHECK_EQ(invoke&lt;int&gt;(*plan.result[0]-&gt;jsEntryPoint, { box(1), box(100) }), 1);
+        CHECK_EQ(invoke&lt;int&gt;(*plan.result[0]-&gt;jsEntryPoint, { box(-12), box(plan.memory-&gt;size() - sizeof(uint64_t)) }), -12);
+    }
+
+    {
+        // Generated from:
+        // (module
+        //  (memory 1)
+        //  (func (export &quot;i32_load8_s&quot;) (param $i i32) (param $ptr i32) (result i32)
+        //   (i32.store (get_local $ptr) (get_local $i))
+        //   (return (i32.load (get_local $ptr)))
+        //   )
+        //  )
+        Vector&lt;uint8_t&gt; vector = {
+            0x00, 0x61, 0x73, 0x6d, 0x0c, 0x00, 0x00, 0x00, 0x01, 0x87, 0x80, 0x80, 0x80, 0x00, 0x01, 0x40,
+            0x02, 0x01, 0x01, 0x01, 0x01, 0x03, 0x82, 0x80, 0x80, 0x80, 0x00, 0x01, 0x00, 0x05, 0x83, 0x80,
+            0x80, 0x80, 0x00, 0x01, 0x01, 0x01, 0x07, 0x8f, 0x80, 0x80, 0x80, 0x00, 0x01, 0x0b, 0x69, 0x33,
+            0x32, 0x5f, 0x6c, 0x6f, 0x61, 0x64, 0x38, 0x5f, 0x73, 0x00, 0x00, 0x0a, 0x95, 0x80, 0x80, 0x80,
+            0x00, 0x01, 0x8f, 0x80, 0x80, 0x80, 0x00, 0x00, 0x14, 0x01, 0x14, 0x00, 0x33, 0x02, 0x00, 0x14,
+            0x01, 0x2a, 0x02, 0x00, 0x09, 0x0f
+        };
+
+        Plan plan(*vm, vector);
+        if (plan.result.size() != 1 || !plan.result[0]) {
+            dataLogLn(&quot;Module failed to compile correctly.&quot;);
+            CRASH();
+        }
+
+        // Test this doesn't crash.
+        CHECK_EQ(invoke&lt;int&gt;(*plan.result[0]-&gt;jsEntryPoint, { box(0), box(10) }), 0);
+        CHECK_EQ(invoke&lt;int&gt;(*plan.result[0]-&gt;jsEntryPoint, { box(100), box(2) }), 100);
+        CHECK_EQ(invoke&lt;int&gt;(*plan.result[0]-&gt;jsEntryPoint, { box(1), box(100) }), 1);
+    }
+
+    {
+        // Generated from:
+        //    (module
+        //     (memory 1)
+        //     (func (export &quot;write_array&quot;) (param $x i32) (param $p i32) (param $length i32) (local $i i32)
+        //      (set_local $i (i32.const 0))
+        //      (block
+        //       (loop
+        //        (br_if 1 (i32.ge_u (get_local $i) (get_local $length)))
+        //        (i32.store (i32.add (get_local $p) (i32.mul (get_local $i) (i32.const 4))) (get_local $x))
+        //        (set_local $i (i32.add (i32.const 1) (get_local $i)))
+        //        (br 0)
+        //        )
+        //       )
+        //      (return)
+        //      )
+        //     )
+        Vector&lt;uint8_t&gt; vector = {
+            0x00, 0x61, 0x73, 0x6d, 0x0c, 0x00, 0x00, 0x00, 0x01, 0x87, 0x80, 0x80, 0x80, 0x00, 0x01, 0x40,
+            0x03, 0x01, 0x01, 0x01, 0x00, 0x03, 0x82, 0x80, 0x80, 0x80, 0x00, 0x01, 0x00, 0x05, 0x83, 0x80,
+            0x80, 0x80, 0x00, 0x01, 0x01, 0x01, 0x07, 0x8f, 0x80, 0x80, 0x80, 0x00, 0x01, 0x0b, 0x77, 0x72,
+            0x69, 0x74, 0x65, 0x5f, 0x61, 0x72, 0x72, 0x61, 0x79, 0x00, 0x00, 0x0a, 0xb2, 0x80, 0x80, 0x80,
+            0x00, 0x01, 0xac, 0x80, 0x80, 0x80, 0x00, 0x01, 0x01, 0x01, 0x10, 0x00, 0x15, 0x03, 0x01, 0x00,
+            0x02, 0x00, 0x14, 0x03, 0x14, 0x02, 0x56, 0x07, 0x01, 0x14, 0x01, 0x14, 0x03, 0x10, 0x04, 0x42,
+            0x40, 0x14, 0x00, 0x33, 0x02, 0x00, 0x10, 0x01, 0x14, 0x03, 0x40, 0x15, 0x03, 0x06, 0x00, 0x0f,
+            0x0f, 0x09, 0x0f
+        };
+
+        Plan plan(*vm, vector);
+        if (plan.result.size() != 1 || !plan.result[0]) {
+            dataLogLn(&quot;Module failed to compile correctly.&quot;);
+            CRASH();
+        }
+        ASSERT(plan.memory-&gt;size());
+
+        // Test this doesn't crash.
+        unsigned length = 5;
+        unsigned offset = sizeof(uint32_t);
+        uint32_t* memory = static_cast&lt;uint32_t*&gt;(plan.memory-&gt;memory());
+        invoke&lt;void&gt;(*plan.result[0]-&gt;jsEntryPoint, { box(100), box(offset), box(length) });
+        offset /= sizeof(uint32_t);
+        CHECK_EQ(memory[offset - 1], 0u);
+        CHECK_EQ(memory[offset + length], 0u);
+        for (unsigned i = 0; i &lt; length; ++i)
+            CHECK_EQ(memory[i + offset], 100u);
+
+        length = 10;
+        offset = 5 * sizeof(uint32_t);
+        invoke&lt;void&gt;(*plan.result[0]-&gt;jsEntryPoint, { box(5), box(offset), box(length) });
+        offset /= sizeof(uint32_t);
+        CHECK_EQ(memory[offset - 1], 100u);
+        CHECK_EQ(memory[offset + length], 0u);
+        for (unsigned i = 0; i &lt; length; ++i)
+            CHECK_EQ(memory[i + offset], 5u);
+    }
+
+    {
+        // Generated from:
+        //    (module
+        //     (memory 1)
+        //     (func (export &quot;write_array&quot;) (param $x i32) (param $p i32) (param $length i32) (local $i i32)
+        //      (set_local $i (i32.const 0))
+        //      (block
+        //       (loop
+        //        (br_if 1 (i32.ge_u (get_local $i) (get_local $length)))
+        //        (i32.store8 (i32.add (get_local $p) (get_local $i)) (get_local $x))
+        //        (set_local $i (i32.add (i32.const 1) (get_local $i)))
+        //        (br 0)
+        //        )
+        //       )
+        //      (return)
+        //      )
+        //     )
+        Vector&lt;uint8_t&gt; vector = {
+            0x00, 0x61, 0x73, 0x6d, 0x0c, 0x00, 0x00, 0x00, 0x01, 0x87, 0x80, 0x80, 0x80, 0x00, 0x01, 0x40,
+            0x03, 0x01, 0x01, 0x01, 0x00, 0x03, 0x82, 0x80, 0x80, 0x80, 0x00, 0x01, 0x00, 0x05, 0x83, 0x80,
+            0x80, 0x80, 0x00, 0x01, 0x01, 0x01, 0x07, 0x8f, 0x80, 0x80, 0x80, 0x00, 0x01, 0x0b, 0x77, 0x72,
+            0x69, 0x74, 0x65, 0x5f, 0x61, 0x72, 0x72, 0x61, 0x79, 0x00, 0x00, 0x0a, 0xaf, 0x80, 0x80, 0x80,
+            0x00, 0x01, 0xa9, 0x80, 0x80, 0x80, 0x00, 0x01, 0x01, 0x01, 0x10, 0x00, 0x15, 0x03, 0x01, 0x00,
+            0x02, 0x00, 0x14, 0x03, 0x14, 0x02, 0x56, 0x07, 0x01, 0x14, 0x01, 0x14, 0x03, 0x40, 0x14, 0x00,
+            0x2e, 0x00, 0x00, 0x10, 0x01, 0x14, 0x03, 0x40, 0x15, 0x03, 0x06, 0x00, 0x0f, 0x0f, 0x09, 0x0f
+        };
+
+        Plan plan(*vm, vector);
+        if (plan.result.size() != 1 || !plan.result[0]) {
+            dataLogLn(&quot;Module failed to compile correctly.&quot;);
+            CRASH();
+        }
+        ASSERT(plan.memory-&gt;size());
+
+        // Test this doesn't crash.
+        unsigned length = 5;
+        unsigned offset = 1;
+        uint8_t* memory = static_cast&lt;uint8_t*&gt;(plan.memory-&gt;memory());
+        invoke&lt;void&gt;(*plan.result[0]-&gt;jsEntryPoint, { box(100), box(offset), box(length) });
+        CHECK_EQ(memory[offset - 1], 0u);
+        CHECK_EQ(memory[offset + length], 0u);
+        for (unsigned i = 0; i &lt; length; ++i)
+            CHECK_EQ(memory[i + offset], 100u);
+
+        length = 10;
+        offset = 5;
+        invoke&lt;void&gt;(*plan.result[0]-&gt;jsEntryPoint, { box(5), box(offset), box(length) });
+        CHECK_EQ(memory[offset - 1], 100u);
+        CHECK_EQ(memory[offset + length], 0u);
+        for (unsigned i = 0; i &lt; length; ++i)
+            CHECK_EQ(memory[i + offset], 5u);
+    }
+
+    {
+        // Generated from:
+        //    (module
+        //     (memory 1)
+        //     (func (export &quot;i32_load8_s&quot;) (param $i i32) (param $ptr i32) (result i32)
+        //      (i32.store8 (get_local $ptr) (get_local $i))
+        //      (return (i32.load8_s (get_local $ptr)))
+        //      )
+        //     )
+        Vector&lt;uint8_t&gt; vector = {
+            0x00, 0x61, 0x73, 0x6d, 0x0c, 0x00, 0x00, 0x00, 0x01, 0x87, 0x80, 0x80, 0x80, 0x00, 0x01, 0x40,
+            0x02, 0x01, 0x01, 0x01, 0x01, 0x03, 0x82, 0x80, 0x80, 0x80, 0x00, 0x01, 0x00, 0x05, 0x83, 0x80,
+            0x80, 0x80, 0x00, 0x01, 0x01, 0x01, 0x07, 0x8f, 0x80, 0x80, 0x80, 0x00, 0x01, 0x0b, 0x69, 0x33,
+            0x32, 0x5f, 0x6c, 0x6f, 0x61, 0x64, 0x38, 0x5f, 0x73, 0x00, 0x00, 0x0a, 0x95, 0x80, 0x80, 0x80,
+            0x00, 0x01, 0x8f, 0x80, 0x80, 0x80, 0x00, 0x00, 0x14, 0x01, 0x14, 0x00, 0x2e, 0x00, 0x00, 0x14,
+            0x01, 0x20, 0x00, 0x00, 0x09, 0x0f
+        };
+
+        Plan plan(*vm, vector);
+        if (plan.result.size() != 1 || !plan.result[0]) {
+            dataLogLn(&quot;Module failed to compile correctly.&quot;);
+            CRASH();
+        }
+        ASSERT(plan.memory-&gt;size());
+
+        // Test this doesn't crash.
+        CHECK_EQ(invoke&lt;int&gt;(*plan.result[0]-&gt;jsEntryPoint, { box(0), box(10) }), 0);
+        CHECK_EQ(invoke&lt;int&gt;(*plan.result[0]-&gt;jsEntryPoint, { box(100), box(2) }), 100);
+        CHECK_EQ(invoke&lt;int&gt;(*plan.result[0]-&gt;jsEntryPoint, { box(1), box(100) }), 1);
+    }
+
+    {
+        // Generated from:
+        //    (module
+        //     (memory 1)
+        //     (func (export &quot;i32_load8_s&quot;) (param $i i32) (result i32)
+        //      (i32.store8 (i32.const 8) (get_local $i))
+        //      (return (i32.load8_s (i32.const 8)))
+        //      )
+        //     )
+        Vector&lt;uint8_t&gt; vector = {
+            0x00, 0x61, 0x73, 0x6d, 0x0c, 0x00, 0x00, 0x00, 0x01, 0x86, 0x80, 0x80, 0x80, 0x00, 0x01, 0x40,
+            0x01, 0x01, 0x01, 0x01, 0x03, 0x82, 0x80, 0x80, 0x80, 0x00, 0x01, 0x00, 0x05, 0x83, 0x80, 0x80,
+            0x80, 0x00, 0x01, 0x01, 0x01, 0x07, 0x8f, 0x80, 0x80, 0x80, 0x00, 0x01, 0x0b, 0x69, 0x33, 0x32,
+            0x5f, 0x6c, 0x6f, 0x61, 0x64, 0x38, 0x5f, 0x73, 0x00, 0x00, 0x0a, 0x95, 0x80, 0x80, 0x80, 0x00,
+            0x01, 0x8f, 0x80, 0x80, 0x80, 0x00, 0x00, 0x10, 0x08, 0x14, 0x00, 0x2e, 0x00, 0x00, 0x10, 0x08,
+            0x20, 0x00, 0x00, 0x09, 0x0f
+        };
+
+        Plan plan(*vm, vector);
+        if (plan.result.size() != 1 || !plan.result[0]) {
+            dataLogLn(&quot;Module failed to compile correctly.&quot;);
+            CRASH();
+        }
+
+        // Test this doesn't crash.
+        CHECK_EQ(invoke&lt;int&gt;(*plan.result[0]-&gt;jsEntryPoint, { box(0) }), 0);
+        CHECK_EQ(invoke&lt;int&gt;(*plan.result[0]-&gt;jsEntryPoint, { box(100) }), 100);
+        CHECK_EQ(invoke&lt;int&gt;(*plan.result[0]-&gt;jsEntryPoint, { box(1) }), 1);
+    }
+
+    {
+        // Generated from:
+        //    (module
+        //     (func &quot;dumb-eq&quot; (param $x i32) (param $y i32) (result i32)
</ins><span class="cx">         //      (if (i32.eq (get_local $x) (get_local $y))
</span><span class="cx">         //       (then (br 0))
</span><span class="cx">         //       (else (return (i32.const 1))))
</span><span class="lines">@@ -265,14 +728,14 @@
</span><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         // Test this doesn't crash.
</span><del>-        CHECK_EQ(invoke&lt;int&gt;(*plan.result[0], { box(0), box(1) }), 1);
-        CHECK_EQ(invoke&lt;int&gt;(*plan.result[0], { box(1), box(0) }), 1);
-        CHECK_EQ(invoke&lt;int&gt;(*plan.result[0], { box(2), box(1) }), 1);
-        CHECK_EQ(invoke&lt;int&gt;(*plan.result[0], { box(1), box(2) }), 1);
-        CHECK_EQ(invoke&lt;int&gt;(*plan.result[0], { box(2), box(2) }), 0);
-        CHECK_EQ(invoke&lt;int&gt;(*plan.result[0], { box(1), box(1) }), 0);
-        CHECK_EQ(invoke&lt;int&gt;(*plan.result[0], { box(2), box(6) }), 1);
-        CHECK_EQ(invoke&lt;int&gt;(*plan.result[0], { box(100), box(6) }), 1);
</del><ins>+        CHECK_EQ(invoke&lt;int&gt;(*plan.result[0]-&gt;jsEntryPoint, { box(0), box(1) }), 1);
+        CHECK_EQ(invoke&lt;int&gt;(*plan.result[0]-&gt;jsEntryPoint, { box(1), box(0) }), 1);
+        CHECK_EQ(invoke&lt;int&gt;(*plan.result[0]-&gt;jsEntryPoint, { box(2), box(1) }), 1);
+        CHECK_EQ(invoke&lt;int&gt;(*plan.result[0]-&gt;jsEntryPoint, { box(1), box(2) }), 1);
+        CHECK_EQ(invoke&lt;int&gt;(*plan.result[0]-&gt;jsEntryPoint, { box(2), box(2) }), 0);
+        CHECK_EQ(invoke&lt;int&gt;(*plan.result[0]-&gt;jsEntryPoint, { box(1), box(1) }), 0);
+        CHECK_EQ(invoke&lt;int&gt;(*plan.result[0]-&gt;jsEntryPoint, { box(2), box(6) }), 1);
+        CHECK_EQ(invoke&lt;int&gt;(*plan.result[0]-&gt;jsEntryPoint, { box(100), box(6) }), 1);
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     {
</span><span class="lines">@@ -306,14 +769,14 @@
</span><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         // Test this doesn't crash.
</span><del>-        CHECK_EQ(invoke&lt;int&gt;(*plan.result[0], { box(0), box(1) }), 1);
-        CHECK_EQ(invoke&lt;int&gt;(*plan.result[0], { box(1), box(0) }), 0);
-        CHECK_EQ(invoke&lt;int&gt;(*plan.result[0], { box(2), box(1) }), 0);
-        CHECK_EQ(invoke&lt;int&gt;(*plan.result[0], { box(1), box(2) }), 1);
-        CHECK_EQ(invoke&lt;int&gt;(*plan.result[0], { box(2), box(2) }), 0);
-        CHECK_EQ(invoke&lt;int&gt;(*plan.result[0], { box(1), box(1) }), 0);
-        CHECK_EQ(invoke&lt;int&gt;(*plan.result[0], { box(2), box(6) }), 1);
-        CHECK_EQ(invoke&lt;int&gt;(*plan.result[0], { box(100), box(6) }), 0);
</del><ins>+        CHECK_EQ(invoke&lt;int&gt;(*plan.result[0]-&gt;jsEntryPoint, { box(0), box(1) }), 1);
+        CHECK_EQ(invoke&lt;int&gt;(*plan.result[0]-&gt;jsEntryPoint, { box(1), box(0) }), 0);
+        CHECK_EQ(invoke&lt;int&gt;(*plan.result[0]-&gt;jsEntryPoint, { box(2), box(1) }), 0);
+        CHECK_EQ(invoke&lt;int&gt;(*plan.result[0]-&gt;jsEntryPoint, { box(1), box(2) }), 1);
+        CHECK_EQ(invoke&lt;int&gt;(*plan.result[0]-&gt;jsEntryPoint, { box(2), box(2) }), 0);
+        CHECK_EQ(invoke&lt;int&gt;(*plan.result[0]-&gt;jsEntryPoint, { box(1), box(1) }), 0);
+        CHECK_EQ(invoke&lt;int&gt;(*plan.result[0]-&gt;jsEntryPoint, { box(2), box(6) }), 1);
+        CHECK_EQ(invoke&lt;int&gt;(*plan.result[0]-&gt;jsEntryPoint, { box(100), box(6) }), 0);
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx"> 
</span><span class="lines">@@ -333,7 +796,7 @@
</span><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         // Test this doesn't crash.
</span><del>-        CHECK_EQ(invoke&lt;int&gt;(*plan.result[0], { }), 5);
</del><ins>+        CHECK_EQ(invoke&lt;int&gt;(*plan.result[0]-&gt;jsEntryPoint, { }), 5);
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx"> 
</span><span class="lines">@@ -354,7 +817,7 @@
</span><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         // Test this doesn't crash.
</span><del>-        CHECK_EQ(invoke&lt;int&gt;(*plan.result[0], { }), 11);
</del><ins>+        CHECK_EQ(invoke&lt;int&gt;(*plan.result[0]-&gt;jsEntryPoint, { }), 11);
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     {
</span><span class="lines">@@ -374,7 +837,7 @@
</span><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         // Test this doesn't crash.
</span><del>-        CHECK_EQ(invoke&lt;int&gt;(*plan.result[0], { }), 11);
</del><ins>+        CHECK_EQ(invoke&lt;int&gt;(*plan.result[0]-&gt;jsEntryPoint, { }), 11);
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     {
</span><span class="lines">@@ -394,7 +857,7 @@
</span><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         // Test this doesn't crash.
</span><del>-        CHECK_EQ(invoke&lt;int&gt;(*plan.result[0], { }), 11);
</del><ins>+        CHECK_EQ(invoke&lt;int&gt;(*plan.result[0]-&gt;jsEntryPoint, { }), 11);
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     {
</span><span class="lines">@@ -413,10 +876,10 @@
</span><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         // Test this doesn't crash.
</span><del>-        CHECK_EQ(invoke&lt;int&gt;(*plan.result[0], { box(0), box(1) }), 1);
-        CHECK_EQ(invoke&lt;int&gt;(*plan.result[0], { box(100), box(1) }), 101);
-        CHECK_EQ(invoke&lt;int&gt;(*plan.result[0], { box(-1), box(1)}), 0);
-        CHECK_EQ(invoke&lt;int&gt;(*plan.result[0], { box(std::numeric_limits&lt;int&gt;::max()), box(1) }), std::numeric_limits&lt;int&gt;::min());
</del><ins>+        CHECK_EQ(invoke&lt;int&gt;(*plan.result[0]-&gt;jsEntryPoint, { box(0), box(1) }), 1);
+        CHECK_EQ(invoke&lt;int&gt;(*plan.result[0]-&gt;jsEntryPoint, { box(100), box(1) }), 101);
+        CHECK_EQ(invoke&lt;int&gt;(*plan.result[0]-&gt;jsEntryPoint, { box(-1), box(1)}), 0);
+        CHECK_EQ(invoke&lt;int&gt;(*plan.result[0]-&gt;jsEntryPoint, { box(std::numeric_limits&lt;int&gt;::max()), box(1) }), std::numeric_limits&lt;int&gt;::min());
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     {
</span><span class="lines">@@ -442,8 +905,8 @@
</span><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         // Test this doesn't crash.
</span><del>-        CHECK_EQ(invoke&lt;int&gt;(*plan.result[0], { box(0) }), 0);
-        CHECK_EQ(invoke&lt;int&gt;(*plan.result[0], { box(10) }), 10);
</del><ins>+        CHECK_EQ(invoke&lt;int&gt;(*plan.result[0]-&gt;jsEntryPoint, { box(0) }), 0);
+        CHECK_EQ(invoke&lt;int&gt;(*plan.result[0]-&gt;jsEntryPoint, { box(10) }), 10);
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     {
</span><span class="lines">@@ -478,10 +941,10 @@
</span><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         // Test this doesn't crash.
</span><del>-        CHECK_EQ(invoke&lt;int&gt;(*plan.result[0], { box(0) }), 0);
-        CHECK_EQ(invoke&lt;int&gt;(*plan.result[0], { box(1) }), 1);
-        CHECK_EQ(invoke&lt;int&gt;(*plan.result[0], { box(2)}), 3);
-        CHECK_EQ(invoke&lt;int&gt;(*plan.result[0], { box(100) }), 5050);
</del><ins>+        CHECK_EQ(invoke&lt;int&gt;(*plan.result[0]-&gt;jsEntryPoint, { box(0) }), 0);
+        CHECK_EQ(invoke&lt;int&gt;(*plan.result[0]-&gt;jsEntryPoint, { box(1) }), 1);
+        CHECK_EQ(invoke&lt;int&gt;(*plan.result[0]-&gt;jsEntryPoint, { box(2)}), 3);
+        CHECK_EQ(invoke&lt;int&gt;(*plan.result[0]-&gt;jsEntryPoint, { box(100) }), 5050);
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     {
</span><span class="lines">@@ -522,14 +985,14 @@
</span><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         // Test this doesn't crash.
</span><del>-        CHECK_EQ(invoke&lt;int&gt;(*plan.result[0], { box(0), box(1) }), 0);
-        CHECK_EQ(invoke&lt;int&gt;(*plan.result[0], { box(1), box(0) }), 0);
-        CHECK_EQ(invoke&lt;int&gt;(*plan.result[0], { box(2), box(1) }), 2);
-        CHECK_EQ(invoke&lt;int&gt;(*plan.result[0], { box(1), box(2) }), 2);
-        CHECK_EQ(invoke&lt;int&gt;(*plan.result[0], { box(2), box(2) }), 4);
-        CHECK_EQ(invoke&lt;int&gt;(*plan.result[0], { box(2), box(6) }), 12);
-        CHECK_EQ(invoke&lt;int&gt;(*plan.result[0], { box(100), box(6) }), 600);
-        CHECK_EQ(invoke&lt;int&gt;(*plan.result[0], { box(100), box(100) }), 10000);
</del><ins>+        CHECK_EQ(invoke&lt;int&gt;(*plan.result[0]-&gt;jsEntryPoint, { box(0), box(1) }), 0);
+        CHECK_EQ(invoke&lt;int&gt;(*plan.result[0]-&gt;jsEntryPoint, { box(1), box(0) }), 0);
+        CHECK_EQ(invoke&lt;int&gt;(*plan.result[0]-&gt;jsEntryPoint, { box(2), box(1) }), 2);
+        CHECK_EQ(invoke&lt;int&gt;(*plan.result[0]-&gt;jsEntryPoint, { box(1), box(2) }), 2);
+        CHECK_EQ(invoke&lt;int&gt;(*plan.result[0]-&gt;jsEntryPoint, { box(2), box(2) }), 4);
+        CHECK_EQ(invoke&lt;int&gt;(*plan.result[0]-&gt;jsEntryPoint, { box(2), box(6) }), 12);
+        CHECK_EQ(invoke&lt;int&gt;(*plan.result[0]-&gt;jsEntryPoint, { box(100), box(6) }), 600);
+        CHECK_EQ(invoke&lt;int&gt;(*plan.result[0]-&gt;jsEntryPoint, { box(100), box(100) }), 10000);
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     {
</span><span class="lines">@@ -575,14 +1038,14 @@
</span><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         // Test this doesn't crash.
</span><del>-        CHECK_EQ(invoke&lt;int&gt;(*plan.result[0], { box(0), box(1) }), 1);
-        CHECK_EQ(invoke&lt;int&gt;(*plan.result[0], { box(1), box(0) }), 0);
-        CHECK_EQ(invoke&lt;int&gt;(*plan.result[0], { box(2), box(1) }), 0);
-        CHECK_EQ(invoke&lt;int&gt;(*plan.result[0], { box(1), box(2) }), 1);
-        CHECK_EQ(invoke&lt;int&gt;(*plan.result[0], { box(2), box(2) }), 0);
-        CHECK_EQ(invoke&lt;int&gt;(*plan.result[0], { box(1), box(1) }), 0);
-        CHECK_EQ(invoke&lt;int&gt;(*plan.result[0], { box(2), box(6) }), 1);
-        CHECK_EQ(invoke&lt;int&gt;(*plan.result[0], { box(100), box(6) }), 0);
</del><ins>+        CHECK_EQ(invoke&lt;int&gt;(*plan.result[0]-&gt;jsEntryPoint, { box(0), box(1) }), 1);
+        CHECK_EQ(invoke&lt;int&gt;(*plan.result[0]-&gt;jsEntryPoint, { box(1), box(0) }), 0);
+        CHECK_EQ(invoke&lt;int&gt;(*plan.result[0]-&gt;jsEntryPoint, { box(2), box(1) }), 0);
+        CHECK_EQ(invoke&lt;int&gt;(*plan.result[0]-&gt;jsEntryPoint, { box(1), box(2) }), 1);
+        CHECK_EQ(invoke&lt;int&gt;(*plan.result[0]-&gt;jsEntryPoint, { box(2), box(2) }), 0);
+        CHECK_EQ(invoke&lt;int&gt;(*plan.result[0]-&gt;jsEntryPoint, { box(1), box(1) }), 0);
+        CHECK_EQ(invoke&lt;int&gt;(*plan.result[0]-&gt;jsEntryPoint, { box(2), box(6) }), 1);
+        CHECK_EQ(invoke&lt;int&gt;(*plan.result[0]-&gt;jsEntryPoint, { box(100), box(6) }), 0);
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx"> }
</span><span class="lines">@@ -596,7 +1059,6 @@
</span><span class="cx">     if (options.m_runLEBTests)
</span><span class="cx">         runLEBTests();
</span><span class="cx"> 
</span><del>-
</del><span class="cx">     if (options.m_runWASMTests) {
</span><span class="cx"> #if ENABLE(WEBASSEMBLY)
</span><span class="cx">         JSC::initializeThreading();
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorewasmWASMB3IRGeneratorcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/wasm/WASMB3IRGenerator.cpp (207452 => 207453)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/wasm/WASMB3IRGenerator.cpp        2016-10-18 01:25:54 UTC (rev 207452)
+++ trunk/Source/JavaScriptCore/wasm/WASMB3IRGenerator.cpp        2016-10-18 02:02:48 UTC (rev 207453)
</span><span class="lines">@@ -29,14 +29,19 @@
</span><span class="cx"> #if ENABLE(WEBASSEMBLY)
</span><span class="cx"> 
</span><span class="cx"> #include &quot;B3BasicBlockInlines.h&quot;
</span><ins>+#include &quot;B3ConstPtrValue.h&quot;
</ins><span class="cx"> #include &quot;B3FixSSA.h&quot;
</span><ins>+#include &quot;B3StackmapGenerationParams.h&quot;
</ins><span class="cx"> #include &quot;B3Validate.h&quot;
</span><span class="cx"> #include &quot;B3ValueInlines.h&quot;
</span><span class="cx"> #include &quot;B3Variable.h&quot;
</span><span class="cx"> #include &quot;B3VariableValue.h&quot;
</span><ins>+#include &quot;B3WasmAddressValue.h&quot;
+#include &quot;B3WasmBoundsCheckValue.h&quot;
</ins><span class="cx"> #include &quot;VirtualRegister.h&quot;
</span><span class="cx"> #include &quot;WASMCallingConvention.h&quot;
</span><span class="cx"> #include &quot;WASMFunctionParser.h&quot;
</span><ins>+#include &quot;WASMMemory.h&quot;
</ins><span class="cx"> #include &lt;wtf/Optional.h&gt;
</span><span class="cx"> 
</span><span class="cx"> void dumpProcedure(void* ptr)
</span><span class="lines">@@ -165,18 +170,25 @@
</span><span class="cx">     typedef Vector&lt;Variable*, 1&gt; ResultList;
</span><span class="cx">     static constexpr ExpressionType emptyExpression = nullptr;
</span><span class="cx"> 
</span><del>-    B3IRGenerator(Procedure&amp;);
</del><ins>+    B3IRGenerator(Memory*, Procedure&amp;);
</ins><span class="cx"> 
</span><span class="cx">     void addArguments(const Vector&lt;Type&gt;&amp;);
</span><span class="cx">     void addLocal(Type, uint32_t);
</span><span class="cx">     ExpressionType addConstant(Type, uint64_t);
</span><span class="cx"> 
</span><ins>+    // Locals
</ins><span class="cx">     bool WARN_UNUSED_RETURN getLocal(uint32_t index, ExpressionType&amp; result);
</span><span class="cx">     bool WARN_UNUSED_RETURN setLocal(uint32_t index, ExpressionType value);
</span><span class="cx"> 
</span><ins>+    // Memory
+    bool WARN_UNUSED_RETURN load(LoadOpType, ExpressionType pointer, ExpressionType&amp; result, uint32_t offset);
+    bool WARN_UNUSED_RETURN store(StoreOpType, ExpressionType pointer, ExpressionType value, uint32_t offset);
+
+    // Basic operators
</ins><span class="cx">     bool WARN_UNUSED_RETURN binaryOp(BinaryOpType, ExpressionType left, ExpressionType right, ExpressionType&amp; result);
</span><span class="cx">     bool WARN_UNUSED_RETURN unaryOp(UnaryOpType, ExpressionType arg, ExpressionType&amp; result);
</span><span class="cx"> 
</span><ins>+    // Control flow
</ins><span class="cx">     ControlData WARN_UNUSED_RETURN addBlock(Type signature);
</span><span class="cx">     ControlData WARN_UNUSED_RETURN addLoop(Type signature);
</span><span class="cx">     ControlData WARN_UNUSED_RETURN addIf(ExpressionType condition, Type signature);
</span><span class="lines">@@ -191,18 +203,41 @@
</span><span class="cx">     void dump(const Vector&lt;ControlType&gt;&amp; controlStack, const ExpressionList&amp; expressionStack);
</span><span class="cx"> 
</span><span class="cx"> private:
</span><ins>+    ExpressionType emitCheckAndPreparePointer(ExpressionType pointer, uint32_t offset, uint32_t sizeOfOp);
+    ExpressionType emitLoadOp(LoadOpType, Origin, ExpressionType pointer, uint32_t offset);
+    void emitStoreOp(StoreOpType, Origin, ExpressionType pointer, ExpressionType value, uint32_t offset);
+
</ins><span class="cx">     void unify(Variable* target, const ExpressionType source);
</span><span class="cx">     void unifyValuesWithBlock(const ExpressionList&amp; resultStack, ResultList&amp; stack);
</span><span class="cx"> 
</span><ins>+    Memory* m_memory;
</ins><span class="cx">     Procedure&amp; m_proc;
</span><span class="cx">     BasicBlock* m_currentBlock;
</span><span class="cx">     Vector&lt;Variable*&gt; m_locals;
</span><ins>+    GPRReg m_memoryBaseGPR;
+    GPRReg m_memorySizeGPR;
</ins><span class="cx"> };
</span><span class="cx"> 
</span><del>-B3IRGenerator::B3IRGenerator(Procedure&amp; procedure)
-    : m_proc(procedure)
</del><ins>+B3IRGenerator::B3IRGenerator(Memory* memory, Procedure&amp; procedure)
+    : m_memory(memory)
+    , m_proc(procedure)
</ins><span class="cx"> {
</span><span class="cx">     m_currentBlock = m_proc.addBlock();
</span><ins>+
+    if (m_memory) {
+        m_memoryBaseGPR = m_memory-&gt;pinnedRegisters().baseMemoryPointer;
+        m_proc.pinRegister(m_memoryBaseGPR);
+        ASSERT(!m_memory-&gt;pinnedRegisters().sizeRegisters[0].sizeOffset);
+        m_memorySizeGPR = m_memory-&gt;pinnedRegisters().sizeRegisters[0].sizeRegister;
+        for (const PinnedSizeRegisterInfo&amp; info : m_memory-&gt;pinnedRegisters().sizeRegisters)
+            m_proc.pinRegister(info.sizeRegister);
+    }
+
+    m_proc.setWasmBoundsCheckGenerator([=] (CCallHelpers&amp; jit, GPRReg pinnedGPR, unsigned) {
+        ASSERT_UNUSED(pinnedGPR, m_memorySizeGPR == pinnedGPR);
+        // FIXME: This should unwind the stack and throw a JS exception. See: https://bugs.webkit.org/show_bug.cgi?id=163351
+        jit.breakpoint();
+    });
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void B3IRGenerator::addLocal(Type type, uint32_t count)
</span><span class="lines">@@ -224,7 +259,7 @@
</span><span class="cx">         });
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-bool WARN_UNUSED_RETURN B3IRGenerator::getLocal(uint32_t index, ExpressionType&amp; result)
</del><ins>+bool B3IRGenerator::getLocal(uint32_t index, ExpressionType&amp; result)
</ins><span class="cx"> {
</span><span class="cx">     ASSERT(m_locals[index]);
</span><span class="cx">     result = m_currentBlock-&gt;appendNew&lt;VariableValue&gt;(m_proc, B3::Get, Origin(), m_locals[index]);
</span><span class="lines">@@ -231,7 +266,7 @@
</span><span class="cx">     return true;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-bool WARN_UNUSED_RETURN B3IRGenerator::setLocal(uint32_t index, ExpressionType value)
</del><ins>+bool B3IRGenerator::setLocal(uint32_t index, ExpressionType value)
</ins><span class="cx"> {
</span><span class="cx">     ASSERT(m_locals[index]);
</span><span class="cx">     m_currentBlock-&gt;appendNew&lt;VariableValue&gt;(m_proc, B3::Set, Origin(), m_locals[index], value);
</span><span class="lines">@@ -238,6 +273,174 @@
</span><span class="cx">     return true;
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+inline Value* B3IRGenerator::emitCheckAndPreparePointer(ExpressionType pointer, uint32_t offset, uint32_t sizeOfOperation)
+{
+    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);
+    pointer = m_currentBlock-&gt;appendNew&lt;Value&gt;(m_proc, ZExt32, Origin(), pointer);
+    return m_currentBlock-&gt;appendNew&lt;WasmAddressValue&gt;(m_proc, Origin(), pointer, m_memoryBaseGPR);
+}
+
+inline uint32_t sizeOfLoadOp(LoadOpType op)
+{
+    switch (op) {
+    case LoadOpType::I32Load8S:
+    case LoadOpType::I32Load8U:
+    case LoadOpType::I64Load8S:
+    case LoadOpType::I64Load8U:
+        return 1;
+    case LoadOpType::I32Load16S:
+    case LoadOpType::I64Load16S:
+        return 2;
+    case LoadOpType::I32Load:
+    case LoadOpType::I64Load32S:
+    case LoadOpType::I64Load32U:
+        return 4;
+    case LoadOpType::I64Load:
+        return 8;
+    case LoadOpType::I32Load16U:
+    case LoadOpType::I64Load16U:
+    case LoadOpType::F32Load:
+    case LoadOpType::F64Load:
+        break;
+    }
+    RELEASE_ASSERT_NOT_REACHED();
+}
+
+inline Value* B3IRGenerator::emitLoadOp(LoadOpType op, Origin origin, ExpressionType pointer, uint32_t offset)
+{
+    switch (op) {
+    case LoadOpType::I32Load8S: {
+        return m_currentBlock-&gt;appendNew&lt;MemoryValue&gt;(m_proc, Load8S, origin, pointer, offset);
+    }
+
+    case LoadOpType::I64Load8S: {
+        Value* value = m_currentBlock-&gt;appendNew&lt;MemoryValue&gt;(m_proc, Load8S, origin, pointer, offset);
+        return m_currentBlock-&gt;appendNew&lt;Value&gt;(m_proc, SExt32, origin, value);
+    }
+
+    case LoadOpType::I32Load8U: {
+        return m_currentBlock-&gt;appendNew&lt;MemoryValue&gt;(m_proc, Load8Z, origin, pointer, offset);
+    }
+
+    case LoadOpType::I64Load8U: {
+        Value* value = m_currentBlock-&gt;appendNew&lt;MemoryValue&gt;(m_proc, Load8Z, origin, pointer, offset);
+        return m_currentBlock-&gt;appendNew&lt;Value&gt;(m_proc, ZExt32, origin, value);
+    }
+
+    case LoadOpType::I32Load16S: {
+        return m_currentBlock-&gt;appendNew&lt;MemoryValue&gt;(m_proc, Load16S, origin, pointer, offset);
+    }
+    case LoadOpType::I64Load16S: {
+        Value* value = m_currentBlock-&gt;appendNew&lt;MemoryValue&gt;(m_proc, Load16S, origin, pointer, offset);
+        return m_currentBlock-&gt;appendNew&lt;Value&gt;(m_proc, SExt32, origin, value);
+    }
+
+    case LoadOpType::I32Load: {
+        return m_currentBlock-&gt;appendNew&lt;MemoryValue&gt;(m_proc, Load, Int32, origin, pointer);
+    }
+
+    case LoadOpType::I64Load32U: {
+        Value* value = m_currentBlock-&gt;appendNew&lt;MemoryValue&gt;(m_proc, Load, Int32, origin, pointer);
+        return m_currentBlock-&gt;appendNew&lt;Value&gt;(m_proc, ZExt32, origin, value);
+    }
+
+    case LoadOpType::I64Load32S: {
+        Value* value = m_currentBlock-&gt;appendNew&lt;MemoryValue&gt;(m_proc, Load, Int32, origin, pointer);
+        return m_currentBlock-&gt;appendNew&lt;Value&gt;(m_proc, SExt32, origin, value);
+    }
+
+    case LoadOpType::I64Load: {
+        return m_currentBlock-&gt;appendNew&lt;MemoryValue&gt;(m_proc, Load, Int64, origin, pointer);
+    }
+
+    case LoadOpType::F32Load: {
+        return m_currentBlock-&gt;appendNew&lt;MemoryValue&gt;(m_proc, Load, Float, origin, pointer);
+    }
+
+    case LoadOpType::F64Load: {
+        return m_currentBlock-&gt;appendNew&lt;MemoryValue&gt;(m_proc, Load, Double, origin, pointer);
+    }
+
+    // B3 doesn't support Load16Z yet.
+    case LoadOpType::I32Load16U:
+    case LoadOpType::I64Load16U:
+        break;
+    }
+    RELEASE_ASSERT_NOT_REACHED();
+}
+
+bool B3IRGenerator::load(LoadOpType op, ExpressionType pointer, ExpressionType&amp; result, uint32_t offset)
+{
+    ASSERT(pointer-&gt;type() == Int32);
+
+    result = emitLoadOp(op, Origin(), emitCheckAndPreparePointer(pointer, offset, sizeOfLoadOp(op)), offset);
+    return true;
+}
+
+inline uint32_t sizeOfStoreOp(StoreOpType op)
+{
+    switch (op) {
+    case StoreOpType::I32Store8:
+    case StoreOpType::I64Store8:
+        return 1;
+    case StoreOpType::I32Store16:
+    case StoreOpType::I64Store16:
+        return 2;
+    case StoreOpType::I32Store:
+    case StoreOpType::I64Store32:
+    case StoreOpType::F32Store:
+        return 4;
+    case StoreOpType::I64Store:
+    case StoreOpType::F64Store:
+        return 8;
+    }
+    RELEASE_ASSERT_NOT_REACHED();
+}
+
+
+inline void B3IRGenerator::emitStoreOp(StoreOpType op, Origin origin, ExpressionType pointer, ExpressionType value, uint32_t offset)
+{
+    switch (op) {
+    case StoreOpType::I64Store8:
+        value = m_currentBlock-&gt;appendNew&lt;Value&gt;(m_proc, Trunc, origin, value);
+        FALLTHROUGH;
+
+    case StoreOpType::I32Store8:
+        m_currentBlock-&gt;appendNew&lt;MemoryValue&gt;(m_proc, Store8, origin, value, pointer, offset);
+        return;
+
+    case StoreOpType::I64Store16:
+        value = m_currentBlock-&gt;appendNew&lt;Value&gt;(m_proc, Trunc, origin, value);
+        FALLTHROUGH;
+
+    case StoreOpType::I32Store16:
+        m_currentBlock-&gt;appendNew&lt;MemoryValue&gt;(m_proc, Store16, origin, value, pointer, offset);
+        return;
+
+    case StoreOpType::I64Store32:
+        value = m_currentBlock-&gt;appendNew&lt;Value&gt;(m_proc, Trunc, origin, value);
+        FALLTHROUGH;
+
+    case StoreOpType::I64Store:
+    case StoreOpType::I32Store:
+    case StoreOpType::F32Store:
+    case StoreOpType::F64Store:
+        m_currentBlock-&gt;appendNew&lt;MemoryValue&gt;(m_proc, Store, origin, value, pointer, offset);
+        return;
+    }
+    RELEASE_ASSERT_NOT_REACHED();
+}
+
+bool B3IRGenerator::store(StoreOpType op, ExpressionType pointer, ExpressionType value, uint32_t offset)
+{
+    ASSERT(pointer-&gt;type() == Int32);
+
+    emitStoreOp(op, Origin(), emitCheckAndPreparePointer(pointer, offset, sizeOfStoreOp(op)), value, offset);
+    return true;
+}
+
</ins><span class="cx"> bool B3IRGenerator::unaryOp(UnaryOpType op, ExpressionType arg, ExpressionType&amp; result)
</span><span class="cx"> {
</span><span class="cx">     result = m_currentBlock-&gt;appendNew&lt;Value&gt;(m_proc, toB3Op(op), Origin(), arg);
</span><span class="lines">@@ -403,10 +606,69 @@
</span><span class="cx"> 
</span><span class="cx"> } // anonymous namespace
</span><span class="cx"> 
</span><del>-std::unique_ptr&lt;Compilation&gt; parseAndCompile(VM&amp; vm, Vector&lt;uint8_t&gt;&amp; source, FunctionInformation info, unsigned optLevel)
</del><ins>+
+static std::unique_ptr&lt;Compilation&gt; createJSWrapper(VM&amp; vm, const Signature* signature, MacroAssemblerCodePtr mainFunction, Memory* memory)
</ins><span class="cx"> {
</span><ins>+    Procedure proc;
+    BasicBlock* block = proc.addBlock();
+
+    // Check argument count is sane.
+    Value* framePointer = block-&gt;appendNew&lt;B3::Value&gt;(proc, B3::FramePointer, Origin());
+    Value* offSetOfArgumentCount = block-&gt;appendNew&lt;Const64Value&gt;(proc, Origin(), CallFrameSlot::argumentCount * sizeof(Register));
+    Value* argumentCount = block-&gt;appendNew&lt;MemoryValue&gt;(proc, Load, Int32, Origin(),
+        block-&gt;appendNew&lt;Value&gt;(proc, Add, Origin(), framePointer, offSetOfArgumentCount));
+
+    Value* expectedArgumentCount = block-&gt;appendNew&lt;Const32Value&gt;(proc, Origin(), signature-&gt;arguments.size());
+
+    CheckValue* argumentCountCheck = block-&gt;appendNew&lt;CheckValue&gt;(proc, Check, Origin(),
+        block-&gt;appendNew&lt;Value&gt;(proc, Above, Origin(), expectedArgumentCount, argumentCount));
+    argumentCountCheck-&gt;setGenerator([] (CCallHelpers&amp; jit, const StackmapGenerationParams&amp;) {
+        jit.breakpoint();
+    });
+
+    // Move memory values to the approriate places, if needed.
+    Value* baseMemory = nullptr;
+    Vector&lt;Value*&gt; sizes;
+    if (memory) {
+        baseMemory = block-&gt;appendNew&lt;ConstPtrValue&gt;(proc, Origin(), memory-&gt;memory());
+        Value* size = block-&gt;appendNew&lt;MemoryValue&gt;(proc, Load, Int32, Origin(),
+            block-&gt;appendNew&lt;ConstPtrValue&gt;(proc, Origin(), bitwise_cast&lt;char*&gt;(memory) + Memory::offsetOfSize()));
+        sizes.reserveCapacity(memory-&gt;pinnedRegisters().sizeRegisters.size());
+        for (auto info : memory-&gt;pinnedRegisters().sizeRegisters) {
+            sizes.append(block-&gt;appendNew&lt;Value&gt;(proc, Sub, Origin(), size,
+                block-&gt;appendNew&lt;Const32Value&gt;(proc, Origin(), info.sizeOffset)));
+        }
+    }
+
+    // Get our arguments.
+    Vector&lt;Value*&gt; arguments;
+    jscCallingConvention().iterate(signature-&gt;arguments, proc, block, Origin(), [&amp;] (Value* argument, unsigned) {
+        arguments.append(argument);
+    });
+
+    // Move the arguments into place.
+    Value* result = jscCallingConvention().setupCall(proc, block, Origin(), mainFunction, arguments, toB3Type(signature-&gt;returnType), [&amp;] (PatchpointValue* patchpoint) {
+        if (memory) {
+            ASSERT(sizes.size() == memory-&gt;pinnedRegisters().sizeRegisters.size());
+            patchpoint-&gt;append(ConstrainedValue(baseMemory, ValueRep::reg(memory-&gt;pinnedRegisters().baseMemoryPointer)));
+            for (unsigned i = 0; i &lt; sizes.size(); ++i)
+                patchpoint-&gt;append(ConstrainedValue(sizes[i], ValueRep::reg(memory-&gt;pinnedRegisters().sizeRegisters[i].sizeRegister)));
+        }
+    });
+
+    // Return the result, if needed.
+    if (signature-&gt;returnType != Void)
+        block-&gt;appendNewControlValue(proc, B3::Return, Origin(), result);
+    else
+        block-&gt;appendNewControlValue(proc, B3::Return, Origin());
+
+    return std::make_unique&lt;Compilation&gt;(vm, proc);
+}
+
+std::unique_ptr&lt;FunctionCompilation&gt; parseAndCompile(VM&amp; vm, Vector&lt;uint8_t&gt;&amp; source, Memory* memory, FunctionInformation info, unsigned optLevel)
+{
</ins><span class="cx">     Procedure procedure;
</span><del>-    B3IRGenerator context(procedure);
</del><ins>+    B3IRGenerator context(memory, procedure);
</ins><span class="cx">     FunctionParser&lt;B3IRGenerator&gt; parser(context, source, info);
</span><span class="cx">     if (!parser.parse())
</span><span class="cx">         RELEASE_ASSERT_NOT_REACHED();
</span><span class="lines">@@ -417,7 +679,11 @@
</span><span class="cx">     fixSSA(procedure);
</span><span class="cx">     if (verbose)
</span><span class="cx">         dataLog(&quot;Post SSA: &quot;, procedure);
</span><del>-    return std::make_unique&lt;Compilation&gt;(vm, procedure, optLevel);
</del><ins>+    auto result = std::make_unique&lt;FunctionCompilation&gt;();
+
+    result-&gt;code = std::make_unique&lt;Compilation&gt;(vm, procedure, optLevel);
+    result-&gt;jsEntryPoint = createJSWrapper(vm, info.signature, result-&gt;code-&gt;code(), memory);
+    return result;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> } } // namespace JSC::WASM
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorewasmWASMB3IRGeneratorh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/wasm/WASMB3IRGenerator.h (207452 => 207453)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/wasm/WASMB3IRGenerator.h        2016-10-18 01:25:54 UTC (rev 207452)
+++ trunk/Source/JavaScriptCore/wasm/WASMB3IRGenerator.h        2016-10-18 02:02:48 UTC (rev 207453)
</span><span class="lines">@@ -35,8 +35,10 @@
</span><span class="cx"> 
</span><span class="cx"> namespace JSC { namespace WASM {
</span><span class="cx"> 
</span><del>-std::unique_ptr&lt;B3::Compilation&gt; parseAndCompile(VM&amp;, Vector&lt;uint8_t&gt;&amp;, FunctionInformation, unsigned optLevel = 1);
</del><ins>+class Memory;
</ins><span class="cx"> 
</span><ins>+std::unique_ptr&lt;FunctionCompilation&gt; parseAndCompile(VM&amp;, Vector&lt;uint8_t&gt;&amp;, Memory*, FunctionInformation, unsigned optLevel = 1);
+
</ins><span class="cx"> } } // namespace JSC::WASM
</span><span class="cx"> 
</span><span class="cx"> #endif // ENABLE(WEBASSEMBLY)
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorewasmWASMCallingConventionh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/wasm/WASMCallingConvention.h (207452 => 207453)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/wasm/WASMCallingConvention.h        2016-10-18 01:25:54 UTC (rev 207452)
+++ trunk/Source/JavaScriptCore/wasm/WASMCallingConvention.h        2016-10-18 02:02:48 UTC (rev 207453)
</span><span class="lines">@@ -27,23 +27,27 @@
</span><span class="cx"> 
</span><span class="cx"> #if ENABLE(WEBASSEMBLY)
</span><span class="cx"> 
</span><ins>+#include &quot;AllowMacroScratchRegisterUsage.h&quot;
</ins><span class="cx"> #include &quot;B3ArgumentRegValue.h&quot;
</span><span class="cx"> #include &quot;B3BasicBlock.h&quot;
</span><span class="cx"> #include &quot;B3Const64Value.h&quot;
</span><ins>+#include &quot;B3ConstrainedValue.h&quot;
</ins><span class="cx"> #include &quot;B3MemoryValue.h&quot;
</span><ins>+#include &quot;B3PatchpointValue.h&quot;
+#include &quot;B3Procedure.h&quot;
+#include &quot;B3StackmapGenerationParams.h&quot;
</ins><span class="cx"> #include &quot;CallFrame.h&quot;
</span><ins>+#include &quot;LinkBuffer.h&quot;
</ins><span class="cx"> #include &quot;RegisterSet.h&quot;
</span><span class="cx"> #include &quot;WASMFormat.h&quot;
</span><span class="cx"> 
</span><span class="cx"> namespace JSC { namespace WASM {
</span><span class="cx"> 
</span><del>-typedef unsigned (*NextOffset)(unsigned currentOffset, Type type);
</del><ins>+typedef unsigned (*NextOffset)(unsigned currentOffset, B3::Type type);
</ins><span class="cx"> 
</span><del>-template&lt;unsigned offset, NextOffset updateOffset&gt;
</del><ins>+template&lt;unsigned headerSize, NextOffset updateOffset&gt;
</ins><span class="cx"> class CallingConvention {
</span><span class="cx"> public:
</span><del>-    static const unsigned headerSize = offset;
-
</del><span class="cx">     CallingConvention(Vector&lt;GPRReg&gt;&amp;&amp; registerArguments, RegisterSet&amp;&amp; calleeSaveRegisters)
</span><span class="cx">         : m_registerArguments(registerArguments)
</span><span class="cx">         , m_calleeSaveRegisters(calleeSaveRegisters)
</span><span class="lines">@@ -64,18 +68,55 @@
</span><span class="cx">                 B3::Value* address = block-&gt;appendNew&lt;B3::Value&gt;(proc, B3::Add, origin, framePointer,
</span><span class="cx">                     block-&gt;appendNew&lt;B3::Const64Value&gt;(proc, origin, currentOffset));
</span><span class="cx">                 argument = block-&gt;appendNew&lt;B3::MemoryValue&gt;(proc, B3::Load, toB3Type(argumentTypes[i]), origin, address);
</span><del>-                currentOffset = updateOffset(currentOffset, argumentTypes[i]);
</del><ins>+                currentOffset = updateOffset(currentOffset, toB3Type(argumentTypes[i]));
</ins><span class="cx">             }
</span><span class="cx">             functor(argument, i);
</span><span class="cx">         }
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    template&lt;typename Functor&gt;
+    B3::Value* setupCall(B3::Procedure&amp; proc, B3::BasicBlock* block, B3::Origin origin, MacroAssemblerCodePtr target, const Vector&lt;B3::Value*&gt;&amp; arguments, B3::Type returnType, const Functor&amp; patchpointFunctor) const
+    {
+        size_t stackArgumentCount = arguments.size() &lt; m_registerArguments.size() ? 0 : arguments.size() - m_registerArguments.size();
+        unsigned offset = headerSize - sizeof(CallerFrameAndPC);
+
+        proc.requestCallArgAreaSizeInBytes(WTF::roundUpToMultipleOf(stackAlignmentBytes(), headerSize + (stackArgumentCount * sizeof(Register))));
+        Vector&lt;B3::ConstrainedValue&gt; constrainedArguments;
+        for (unsigned i = 0; i &lt; arguments.size(); ++i) {
+            B3::ValueRep rep;
+            if (i &lt; m_registerArguments.size())
+                rep = B3::ValueRep::reg(m_registerArguments[i]);
+            else
+                rep = B3::ValueRep::stackArgument(offset);
+            constrainedArguments.append(B3::ConstrainedValue(arguments[i], rep));
+            offset = updateOffset(offset, arguments[i]-&gt;type());
+        }
+
+        B3::PatchpointValue* patchpoint = block-&gt;appendNew&lt;B3::PatchpointValue&gt;(proc, returnType, origin);
+        patchpoint-&gt;appendVector(constrainedArguments);
+        patchpointFunctor(patchpoint);
+        patchpoint-&gt;setGenerator([=] (CCallHelpers&amp; jit, const B3::StackmapGenerationParams&amp;) {
+            AllowMacroScratchRegisterUsage allowScratch(jit);
+
+            CCallHelpers::Call call = jit.call();
+            jit.addLinkTask([=] (LinkBuffer&amp; linkBuffer) {
+                linkBuffer.link(call, FunctionPtr(target.executableAddress()));
+            });
+        });
+
+        if (returnType == B3::Void)
+            return nullptr;
+
+        patchpoint-&gt;resultConstraint = B3::ValueRep::reg(GPRInfo::returnValueGPR);
+        return patchpoint;
+    }
+
</ins><span class="cx">     const Vector&lt;GPRReg&gt; m_registerArguments;
</span><span class="cx">     const RegisterSet m_calleeSaveRegisters;
</span><span class="cx">     const RegisterSet m_callerSaveRegisters;
</span><span class="cx"> };
</span><span class="cx"> 
</span><del>-inline unsigned nextJSCOffset(unsigned currentOffset, Type)
</del><ins>+inline unsigned nextJSCOffset(unsigned currentOffset, B3::Type)
</ins><span class="cx"> {
</span><span class="cx">     return currentOffset + sizeof(Register);
</span><span class="cx"> }
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorewasmWASMFormath"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/wasm/WASMFormat.h (207452 => 207453)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/wasm/WASMFormat.h        2016-10-18 01:25:54 UTC (rev 207452)
+++ trunk/Source/JavaScriptCore/wasm/WASMFormat.h        2016-10-18 02:02:48 UTC (rev 207453)
</span><span class="lines">@@ -44,6 +44,7 @@
</span><span class="cx"> 
</span><span class="cx"> #if ENABLE(WEBASSEMBLY)
</span><span class="cx"> 
</span><ins>+#include &quot;B3Compilation.h&quot;
</ins><span class="cx"> #include &quot;B3Type.h&quot;
</span><span class="cx"> #include &lt;wtf/Vector.h&gt;
</span><span class="cx"> #include &lt;wtf/text/WTFString.h&gt;
</span><span class="lines">@@ -126,6 +127,11 @@
</span><span class="cx">     size_t end;
</span><span class="cx"> };
</span><span class="cx"> 
</span><ins>+struct FunctionCompilation {
+    std::unique_ptr&lt;B3::Compilation&gt; code;
+    std::unique_ptr&lt;B3::Compilation&gt; jsEntryPoint;
+};
+
</ins><span class="cx"> } } // namespace JSC::WASM
</span><span class="cx"> 
</span><span class="cx"> #endif // ENABLE(WEBASSEMBLY)
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorewasmWASMFunctionParserh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/wasm/WASMFunctionParser.h (207452 => 207453)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/wasm/WASMFunctionParser.h        2016-10-18 01:25:54 UTC (rev 207452)
+++ trunk/Source/JavaScriptCore/wasm/WASMFunctionParser.h        2016-10-18 02:02:48 UTC (rev 207453)
</span><span class="lines">@@ -154,6 +154,37 @@
</span><span class="cx">         return true;
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    FOR_EACH_WASM_MEMORY_LOAD_OP(CREATE_CASE) {
+        uint32_t alignment;
+        if (!parseVarUInt32(alignment))
+            return false;
+
+        uint32_t offset;
+        if (!parseVarUInt32(offset))
+            return false;
+
+        ExpressionType pointer = m_expressionStack.takeLast();
+        ExpressionType result;
+        if (!m_context.load(static_cast&lt;LoadOpType&gt;(op), pointer, result, offset))
+            return false;
+        m_expressionStack.append(result);
+        return true;
+    }
+
+    FOR_EACH_WASM_MEMORY_STORE_OP(CREATE_CASE) {
+        uint32_t alignment;
+        if (!parseVarUInt32(alignment))
+            return false;
+
+        uint32_t offset;
+        if (!parseVarUInt32(offset))
+            return false;
+
+        ExpressionType value = m_expressionStack.takeLast();
+        ExpressionType pointer = m_expressionStack.takeLast();
+        return m_context.store(static_cast&lt;StoreOpType&gt;(op), pointer, value, offset);
+    }
+
</ins><span class="cx">     case OpType::I32Const: {
</span><span class="cx">         uint32_t constant;
</span><span class="cx">         if (!parseVarUInt32(constant))
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorewasmWASMMemorycpp"></a>
<div class="addfile"><h4>Added: trunk/Source/JavaScriptCore/wasm/WASMMemory.cpp (0 => 207453)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/wasm/WASMMemory.cpp                                (rev 0)
+++ trunk/Source/JavaScriptCore/wasm/WASMMemory.cpp        2016-10-18 02:02:48 UTC (rev 207453)
</span><span class="lines">@@ -0,0 +1,77 @@
</span><ins>+/*
+ * Copyright (C) 2016 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;WASMMemory.h&quot;
+
+#if ENABLE(WEBASSEMBLY)
+
+namespace JSC { namespace WASM {
+
+Memory::Memory(uint32_t startingSize, uint32_t capacity, const Vector&lt;unsigned&gt;&amp; pinnedSizeRegisters)
+    : m_mode(Mode::BoundsChecking)
+    , m_size(startingSize)
+    , m_capacity(capacity)
+    // 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
+    , m_mappedCapacity(static_cast&lt;uint64_t&gt;(maxPageCount) * static_cast&lt;uint64_t&gt;(pageSize))
+{
+    ASSERT(pinnedSizeRegisters.size() &gt; 0);
+
+    void* result = mmap(nullptr, m_mappedCapacity, PROT_NONE, MAP_PRIVATE | MAP_ANON, 0, 0);
+    if (result == MAP_FAILED) {
+        // Try again with a different number.
+        m_mappedCapacity = m_capacity;
+        result = mmap(nullptr, m_mappedCapacity, PROT_NONE, MAP_PRIVATE | MAP_ANON, 0, 0);
+        if (result == MAP_FAILED)
+            return;
+    }
+
+    if (mprotect(result, startingSize, PROT_READ | PROT_WRITE)) {
+        munmap(result, m_mappedCapacity);
+        return;
+    }
+
+    unsigned remainingPinnedRegisters = pinnedSizeRegisters.size() + 1;
+    jscCallingConvention().m_calleeSaveRegisters.forEach([&amp;] (Reg reg) {
+        GPRReg gpr = reg.gpr();
+        if (!remainingPinnedRegisters || RegisterSet::stackRegisters().get(reg))
+            return;
+        if (remainingPinnedRegisters == 1) {
+            m_pinnedRegisters.baseMemoryPointer = gpr;
+            remainingPinnedRegisters--;
+        } else
+            m_pinnedRegisters.sizeRegisters.append({ gpr, pinnedSizeRegisters[--remainingPinnedRegisters - 1] });
+    });
+
+    ASSERT(!remainingPinnedRegisters);
+    m_memory = result;
+}
+
+} // namespace JSC
+
+} // namespace WASM
+
+#endif // ENABLE(WEBASSEMBLY)
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCorewasmWASMMemoryh"></a>
<div class="addfile"><h4>Added: trunk/Source/JavaScriptCore/wasm/WASMMemory.h (0 => 207453)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/wasm/WASMMemory.h                                (rev 0)
+++ trunk/Source/JavaScriptCore/wasm/WASMMemory.h        2016-10-18 02:02:48 UTC (rev 207453)
</span><span class="lines">@@ -0,0 +1,99 @@
</span><ins>+/*
+ * Copyright (C) 2016 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;WASMCallingConvention.h&quot;
+
+#include &lt;wtf/Vector.h&gt;
+
+namespace JSC { namespace WASM {
+
+struct PinnedSizeRegisterInfo {
+    GPRReg sizeRegister;
+    unsigned sizeOffset;
+};
+
+// FIXME: We should support more than one memory size register. Right now we take a vector with only one
+// entry. Specifically an extry where the sizeOffset == 0. If we have more than one size register,
+// we can have one for each load size class. see: https://bugs.webkit.org/show_bug.cgi?id=162952
+struct PinnedRegisterInfo {
+    Vector&lt;PinnedSizeRegisterInfo&gt; sizeRegisters;
+    GPRReg baseMemoryPointer;
+};
+
+constexpr uint32_t pageSize = 64 * KB;
+constexpr uint32_t maxPageCount = static_cast&lt;uint32_t&gt;((1ull &lt;&lt; 32) / pageSize);
+
+class Memory {
+    WTF_MAKE_NONCOPYABLE(Memory);
+    WTF_MAKE_FAST_ALLOCATED;
+public:
+
+    // FIXME: We should support other modes. see: https://bugs.webkit.org/show_bug.cgi?id=162693
+    enum class Mode {
+        BoundsChecking
+    };
+
+    Memory() = default;
+    Memory(uint32_t startingSize, uint32_t capacity, const Vector&lt;unsigned&gt;&amp; pinnedSizeRegisters);
+
+    ~Memory()
+    {
+        if (m_memory)
+            munmap(m_memory, m_mappedCapacity);
+    }
+
+    void* memory() const { return m_memory; }
+    uint32_t size() const { return m_size; }
+    const PinnedRegisterInfo&amp; pinnedRegisters() const { return m_pinnedRegisters; }
+
+    Mode mode() const { return m_mode; }
+
+    bool grow(uint32_t newSize)
+    {
+        ASSERT(m_memory);
+        if (newSize &gt; m_capacity)
+            return false;
+
+        return !mprotect(m_memory, newSize, PROT_READ | PROT_WRITE);
+    }
+
+    static ptrdiff_t offsetOfSize() { return OBJECT_OFFSETOF(Memory, m_size); }
+    
+private:
+    void* m_memory { nullptr };
+    PinnedRegisterInfo m_pinnedRegisters;
+    Mode m_mode;
+    uint32_t m_size { 0 };
+    uint32_t m_capacity { 0 };
+    uint64_t m_mappedCapacity { 0 };
+};
+
+} } // namespace JSC::WASM
+
+#endif // ENABLE(WEBASSEMLY)
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCorewasmWASMModuleParsercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/wasm/WASMModuleParser.cpp (207452 => 207453)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/wasm/WASMModuleParser.cpp        2016-10-18 01:25:54 UTC (rev 207452)
+++ trunk/Source/JavaScriptCore/wasm/WASMModuleParser.cpp        2016-10-18 02:02:48 UTC (rev 207453)
</span><span class="lines">@@ -28,10 +28,13 @@
</span><span class="cx"> 
</span><span class="cx"> #if ENABLE(WEBASSEMBLY)
</span><span class="cx"> 
</span><ins>+#include &quot;JSWASMModule.h&quot;
</ins><span class="cx"> #include &quot;WASMFormat.h&quot;
</span><span class="cx"> #include &quot;WASMOps.h&quot;
</span><span class="cx"> #include &quot;WASMSections.h&quot;
</span><span class="cx"> 
</span><ins>+#include &lt;sys/mman.h&gt;
+
</ins><span class="cx"> namespace JSC { namespace WASM {
</span><span class="cx"> 
</span><span class="cx"> static const bool verbose = false;
</span><span class="lines">@@ -62,15 +65,16 @@
</span><span class="cx">         if (verbose)
</span><span class="cx">             dataLogLn(&quot;Starting to parse next section at offset: &quot;, m_offset);
</span><span class="cx"> 
</span><del>-        Sections::Section section = Sections::Unknown;
</del><span class="cx">         uint8_t sectionByte;
</span><span class="cx">         if (!parseUInt7(sectionByte))
</span><span class="cx">             return false;
</span><span class="cx"> 
</span><ins>+        if (verbose)
+            dataLogLn(&quot;Section byte: &quot;, sectionByte);
+
+        Sections::Section section = Sections::Unknown;
</ins><span class="cx">         if (sectionByte) {
</span><del>-            if (sectionByte &gt;= Sections::Unknown)
-                section = Sections::Unknown;
-            else
</del><ins>+            if (sectionByte &lt; Sections::Unknown)
</ins><span class="cx">                 section = static_cast&lt;Sections::Section&gt;(sectionByte);
</span><span class="cx">         } else {
</span><span class="cx">             uint32_t sectionNameLength;
</span><span class="lines">@@ -96,6 +100,15 @@
</span><span class="cx">         unsigned end = m_offset + sectionLength;
</span><span class="cx"> 
</span><span class="cx">         switch (section) {
</span><ins>+
+        case Sections::Memory: {
+            if (verbose)
+                dataLogLn(&quot;Parsing Memory.&quot;);
+            if (!parseMemory())
+                return false;
+            break;
+        }
+
</ins><span class="cx">         case Sections::FunctionTypes: {
</span><span class="cx">             if (verbose)
</span><span class="cx">                 dataLogLn(&quot;Parsing types.&quot;);
</span><span class="lines">@@ -143,6 +156,34 @@
</span><span class="cx">     return true;
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+bool ModuleParser::parseMemory()
+{
+    uint8_t flags;
+    if (!parseVarUInt1(flags))
+        return false;
+
+    uint32_t size;
+    if (!parseVarUInt32(size))
+        return false;
+    if (size &gt; maxPageCount)
+        return false;
+
+    uint32_t capacity = maxPageCount;
+    if (flags) {
+        if (!parseVarUInt32(capacity))
+            return false;
+        if (size &gt; capacity || capacity &gt; maxPageCount)
+            return false;
+    }
+
+    capacity *= pageSize;
+    size *= pageSize;
+
+    Vector&lt;unsigned&gt; pinnedSizes = { 0 };
+    m_memory = std::make_unique&lt;Memory&gt;(size, capacity, pinnedSizes);
+    return m_memory-&gt;memory();
+}
+
</ins><span class="cx"> bool ModuleParser::parseFunctionTypes()
</span><span class="cx"> {
</span><span class="cx">     uint32_t count;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorewasmWASMModuleParserh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/wasm/WASMModuleParser.h (207452 => 207453)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/wasm/WASMModuleParser.h        2016-10-18 01:25:54 UTC (rev 207452)
+++ trunk/Source/JavaScriptCore/wasm/WASMModuleParser.h        2016-10-18 02:02:48 UTC (rev 207453)
</span><span class="lines">@@ -27,6 +27,7 @@
</span><span class="cx"> 
</span><span class="cx"> #if ENABLE(WEBASSEMBLY)
</span><span class="cx"> 
</span><ins>+#include &quot;WASMMemory.h&quot;
</ins><span class="cx"> #include &quot;WASMOps.h&quot;
</span><span class="cx"> #include &quot;WASMParser.h&quot;
</span><span class="cx"> #include &lt;wtf/Vector.h&gt;
</span><span class="lines">@@ -45,18 +46,19 @@
</span><span class="cx"> 
</span><span class="cx">     bool WARN_UNUSED_RETURN parse();
</span><span class="cx"> 
</span><del>-    const Vector&lt;FunctionInformation&gt;&amp; functionInformation() { return m_functions; }
</del><ins>+    const Vector&lt;FunctionInformation&gt;&amp; functionInformation() const { return m_functions; }
+    std::unique_ptr&lt;Memory&gt;&amp; memory() { return m_memory; }
</ins><span class="cx"> 
</span><span class="cx"> private:
</span><ins>+    bool WARN_UNUSED_RETURN parseMemory();
</ins><span class="cx">     bool WARN_UNUSED_RETURN parseFunctionTypes();
</span><span class="cx">     bool WARN_UNUSED_RETURN parseFunctionSignatures();
</span><span class="cx">     bool WARN_UNUSED_RETURN parseFunctionDefinitions();
</span><span class="cx">     bool WARN_UNUSED_RETURN parseFunctionDefinition(uint32_t number);
</span><del>-    bool WARN_UNUSED_RETURN parseBlock();
-    bool WARN_UNUSED_RETURN parseExpression(OpType);
</del><span class="cx"> 
</span><span class="cx">     Vector&lt;FunctionInformation&gt; m_functions;
</span><span class="cx">     Vector&lt;Signature&gt; m_signatures;
</span><ins>+    std::unique_ptr&lt;Memory&gt; m_memory;
</ins><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> } } // namespace JSC::WASM
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorewasmWASMOpsh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/wasm/WASMOps.h (207452 => 207453)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/wasm/WASMOps.h        2016-10-18 01:25:54 UTC (rev 207452)
+++ trunk/Source/JavaScriptCore/wasm/WASMOps.h        2016-10-18 02:02:48 UTC (rev 207453)
</span><span class="lines">@@ -159,13 +159,42 @@
</span><span class="cx">     macro(F64Gt, 0x9b, Oops) \
</span><span class="cx">     macro(F64Ge, 0x9c, Oops)
</span><span class="cx"> 
</span><ins>+#define FOR_EACH_WASM_MEMORY_LOAD_OP(macro) \
+    macro(I32Load8S, 0x20, Oops) \
+    macro(I32Load8U, 0x21, Oops) \
+    macro(I32Load16S, 0x22, Oops) \
+    macro(I32Load16U, 0x23, Oops) \
+    macro(I64Load8S, 0x24, Oops) \
+    macro(I64Load8U, 0x25, Oops) \
+    macro(I64Load16S, 0x26, Oops) \
+    macro(I64Load16U, 0x27, Oops) \
+    macro(I64Load32S, 0x28, Oops) \
+    macro(I64Load32U, 0x29, Oops) \
+    macro(I32Load, 0x2a, Oops) \
+    macro(I64Load, 0x2b, Oops) \
+    macro(F32Load, 0x2c, Oops) \
+    macro(F64Load, 0x2d, Oops)
</ins><span class="cx"> 
</span><ins>+#define FOR_EACH_WASM_MEMORY_STORE_OP(macro) \
+    macro(I32Store8, 0x2e, Oops) \
+    macro(I32Store16, 0x2f, Oops) \
+    macro(I64Store8, 0x30, Oops) \
+    macro(I64Store16, 0x31, Oops) \
+    macro(I64Store32, 0x32, Oops) \
+    macro(I32Store, 0x33, Oops) \
+    macro(I64Store, 0x34, Oops) \
+    macro(F32Store, 0x35, Oops) \
+    macro(F64Store, 0x36, Oops)
</ins><span class="cx"> 
</span><ins>+
+
</ins><span class="cx"> #define FOR_EACH_WASM_OP(macro) \
</span><span class="cx">     FOR_EACH_WASM_SPECIAL_OP(macro) \
</span><span class="cx">     FOR_EACH_WASM_CONTROL_FLOW_OP(macro) \
</span><span class="cx">     FOR_EACH_WASM_UNARY_OP(macro) \
</span><del>-    FOR_EACH_WASM_BINARY_OP(macro)
</del><ins>+    FOR_EACH_WASM_BINARY_OP(macro) \
+    FOR_EACH_WASM_MEMORY_LOAD_OP(macro) \
+    FOR_EACH_WASM_MEMORY_STORE_OP(macro)
</ins><span class="cx"> 
</span><span class="cx"> #define CREATE_ENUM_VALUE(name, id, b3op) name = id,
</span><span class="cx"> 
</span><span class="lines">@@ -189,6 +218,14 @@
</span><span class="cx">     FOR_EACH_WASM_UNARY_OP(CREATE_ENUM_VALUE)
</span><span class="cx"> };
</span><span class="cx"> 
</span><ins>+enum class LoadOpType : uint8_t {
+    FOR_EACH_WASM_MEMORY_LOAD_OP(CREATE_ENUM_VALUE)
+};
+
+enum class StoreOpType : uint8_t {
+    FOR_EACH_WASM_MEMORY_STORE_OP(CREATE_ENUM_VALUE)
+};
+
</ins><span class="cx"> #undef CREATE_ENUM_VALUE
</span><span class="cx"> 
</span><span class="cx"> inline bool isControlOp(OpType op)
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorewasmWASMPlancpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/wasm/WASMPlan.cpp (207452 => 207453)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/wasm/WASMPlan.cpp        2016-10-18 01:25:54 UTC (rev 207452)
+++ trunk/Source/JavaScriptCore/wasm/WASMPlan.cpp        2016-10-18 02:02:48 UTC (rev 207453)
</span><span class="lines">@@ -30,6 +30,7 @@
</span><span class="cx"> 
</span><span class="cx"> #include &quot;B3Compilation.h&quot;
</span><span class="cx"> #include &quot;WASMB3IRGenerator.h&quot;
</span><ins>+#include &quot;WASMCallingConvention.h&quot;
</ins><span class="cx"> #include &quot;WASMModuleParser.h&quot;
</span><span class="cx"> #include &lt;wtf/DataLog.h&gt;
</span><span class="cx"> 
</span><span class="lines">@@ -53,8 +54,9 @@
</span><span class="cx">     for (const FunctionInformation&amp; info : moduleParser.functionInformation()) {
</span><span class="cx">         if (verbose)
</span><span class="cx">             dataLogLn(&quot;Processing funcion starting at: &quot;, info.start, &quot; and ending at: &quot;, info.end);
</span><del>-        result.append(parseAndCompile(vm, source, info));
</del><ins>+        result.append(parseAndCompile(vm, source, moduleParser.memory().get(), info));
</ins><span class="cx">     }
</span><ins>+    memory = WTFMove(moduleParser.memory());
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> } } // namespace JSC::WASM
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorewasmWASMPlanh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/wasm/WASMPlan.h (207452 => 207453)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/wasm/WASMPlan.h        2016-10-18 01:25:54 UTC (rev 207452)
+++ trunk/Source/JavaScriptCore/wasm/WASMPlan.h        2016-10-18 02:02:48 UTC (rev 207453)
</span><span class="lines">@@ -29,23 +29,20 @@
</span><span class="cx"> 
</span><span class="cx"> #include &quot;CompilationResult.h&quot;
</span><span class="cx"> #include &quot;VM.h&quot;
</span><ins>+#include &quot;WASMFormat.h&quot;
</ins><span class="cx"> #include &lt;wtf/ThreadSafeRefCounted.h&gt;
</span><span class="cx"> #include &lt;wtf/Vector.h&gt;
</span><span class="cx"> 
</span><del>-namespace JSC {
</del><ins>+namespace JSC { namespace WASM {
+class Memory;
</ins><span class="cx"> 
</span><del>-namespace B3 {
-class Compilation;
-} // namespace B3
-
-namespace WASM {
-
</del><span class="cx"> // TODO: This should create a WASM Module not a list of functions.
</span><span class="cx"> class Plan {
</span><span class="cx"> public:
</span><span class="cx">     JS_EXPORT_PRIVATE Plan(VM&amp;, Vector&lt;uint8_t&gt; source);
</span><span class="cx"> 
</span><del>-    Vector&lt;std::unique_ptr&lt;B3::Compilation&gt;&gt; result;
</del><ins>+    Vector&lt;std::unique_ptr&lt;FunctionCompilation&gt;&gt; result;
+    std::unique_ptr&lt;Memory&gt; memory;
</ins><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> } } // namespace JSC::WASM
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorewasmWASMSectionsh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/wasm/WASMSections.h (207452 => 207453)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/wasm/WASMSections.h        2016-10-18 01:25:54 UTC (rev 207452)
+++ trunk/Source/JavaScriptCore/wasm/WASMSections.h        2016-10-18 02:02:48 UTC (rev 207453)
</span><span class="lines">@@ -33,6 +33,7 @@
</span><span class="cx">     enum Section : uint8_t {
</span><span class="cx">         FunctionTypes = 1,
</span><span class="cx">         Signatures = 3,
</span><ins>+        Memory = 5,
</ins><span class="cx">         Definitions = 10,
</span><span class="cx">         Unknown
</span><span class="cx">     };
</span></span></pre>
</div>
</div>

</body>
</html>