<!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>[210229] 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/210229">210229</a></dd>
<dt>Author</dt> <dd>jfbastien@apple.com</dd>
<dt>Date</dt> <dd>2017-01-02 17:57:40 -0800 (Mon, 02 Jan 2017)</dd>
</dl>

<h3>Log Message</h3>
<pre>WebAssembly: handle and optimize wasm export → wasm import calls
https://bugs.webkit.org/show_bug.cgi?id=165282

Reviewed by Saam Barati.

JSTests:

* wasm/Builder.js: Add a Proxy to Builder.js, which intercepts
unknown property lookups. This creates way better error messages
on typos than 'undefined is not a function', which happens
semi-frequently as I typo opcode names (and which one is a typo is
hard to find because we chain builders).
(const._isValidValue):
(get target):
(const._importFunctionContinuation):
(const._importMemoryContinuation):
(const._importTableContinuation):
(const._exportFunctionContinuation):
(export.default.Builder.prototype._registerSectionBuilders.const.section.in.WASM.description.section.switch.section.case.string_appeared_here.this.section):
(export.default.Builder.prototype._registerSectionBuilders.this.Unknown):
* wasm/LowLevelBinary.js: Add limited support for var{u}int64 (only the 32-bit values)
(export.default.LowLevelBinary.prototype.varint32):
(export.default.LowLevelBinary.prototype.varuint64):
(export.default.LowLevelBinary.prototype.varint64):
* wasm/function-tests/exceptions.js: update error message
* wasm/function-tests/trap-load.js: update error message
* wasm/function-tests/trap-store.js: update error message
* wasm/js-api/wasm-to-wasm-bad-signature.js: Added. Test a bunch of bad wasm-&gt;wasm import signatures
(const.makeImportee.signature.switch):
(BadSignatureDropStartParams):
* wasm/js-api/wasm-to-wasm.js: Added. Test 64-bit wasm-&gt;wasm import calls
(const.callerModule):
(const.calleeModule):
(WasmToWasm):

Source/JavaScriptCore:

  - Add a new JSType for WebAssemblyFunction, and use it when creating its
    structure. This will is used to quickly detect from wasm whether the import
    call is to another wasm module, or whether it's to JS.
  - Generate two stubs from the import stub generator: one for wasm-&gt;JS and one
    for wasm -&gt; wasm. This is done at Module time. Which is called will only be
    known at Instance time, once we've received the import object. We want to
    avoid codegen at Instance time, so having both around is great.
  - Restore the WebAssembly global state (VM top Instance, and pinned registers)
    after call / call_indirect, and in the JS-&gt;wasm entry stub.
  - Pinned registers are now a global thing, not per-Memory, because the wasm -&gt;
    wasm stubs are generated at Module time where we don't really have enough
    information to do the right thing (doing so would generate too much code).

* CMakeLists.txt:
* JavaScriptCore.xcodeproj/project.pbxproj:
* runtime/JSType.h: add WebAssemblyFunctionType as a JSType
* wasm/WasmB3IRGenerator.cpp: significantly rework how calls which
could be external work, and how we save / restore global state:
VM's top Instance, and pinned registers
(JSC::Wasm::B3IRGenerator::B3IRGenerator):
(JSC::Wasm::getMemoryBaseAndSize):
(JSC::Wasm::restoreWebAssemblyGlobalState):
(JSC::Wasm::createJSToWasmWrapper):
(JSC::Wasm::parseAndCompile):
* wasm/WasmB3IRGenerator.h:
* wasm/WasmBinding.cpp:
(JSC::Wasm::materializeImportJSCell):
(JSC::Wasm::wasmToJS):
(JSC::Wasm::wasmToWasm): the main goal of this patch was adding this function
(JSC::Wasm::exitStubGenerator):
* wasm/WasmBinding.h:
* wasm/WasmFormat.h: Get rid of much of the function index space:
we already have all of its information elsewhere, and as-is it
provides no extra efficiency.
(JSC::Wasm::ModuleInformation::functionIndexSpaceSize):
(JSC::Wasm::ModuleInformation::isImportedFunctionFromFunctionIndexSpace):
(JSC::Wasm::ModuleInformation::signatureIndexFromFunctionIndexSpace):
* wasm/WasmFunctionParser.h:
(JSC::Wasm::FunctionParser&lt;Context&gt;::FunctionParser):
* wasm/WasmMemory.cpp: Add some logging.
(JSC::Wasm::Memory::dump): this was nice when debugging
(JSC::Wasm::Memory::makeString):
(JSC::Wasm::Memory::Memory):
(JSC::Wasm::Memory::~Memory):
(JSC::Wasm::Memory::grow):
* wasm/WasmMemory.h: don't use extra indirection, it wasn't
needed. Reorder some of the fields which are looked up at runtime
so they're more cache-friendly.
(JSC::Wasm::Memory::Memory):
(JSC::Wasm::Memory::mode):
(JSC::Wasm::Memory::offsetOfSize):
* wasm/WasmMemoryInformation.cpp: Pinned registers are now a
global thing for all of JSC, not a per-Memory thing
anymore. wasm-&gt;wasm calls are more complex otherwise: they have to
figure out how to bridge between the caller and callee's
special-snowflake pinning.
(JSC::Wasm::PinnedRegisterInfo::get):
(JSC::Wasm::PinnedRegisterInfo::PinnedRegisterInfo):
(JSC::Wasm::MemoryInformation::MemoryInformation):
* wasm/WasmMemoryInformation.h:
* wasm/WasmModuleParser.cpp:
* wasm/WasmModuleParser.h:
* wasm/WasmPageCount.cpp: Copied from Source/JavaScriptCore/wasm/WasmBinding.h.
(JSC::Wasm::PageCount::dump): nice for debugging
* wasm/WasmPageCount.h:
* wasm/WasmPlan.cpp:
(JSC::Wasm::Plan::parseAndValidateModule):
(JSC::Wasm::Plan::run):
* wasm/WasmPlan.h:
(JSC::Wasm::Plan::takeWasmExitStubs):
* wasm/WasmSignature.cpp:
(JSC::Wasm::Signature::toString):
(JSC::Wasm::Signature::dump):
* wasm/WasmSignature.h:
* wasm/WasmValidate.cpp:
(JSC::Wasm::validateFunction):
* wasm/WasmValidate.h:
* wasm/js/JSWebAssemblyInstance.h:
(JSC::JSWebAssemblyInstance::offsetOfTable):
(JSC::JSWebAssemblyInstance::offsetOfImportFunctions):
(JSC::JSWebAssemblyInstance::offsetOfImportFunction):
* wasm/js/JSWebAssemblyMemory.cpp:
(JSC::JSWebAssemblyMemory::create):
(JSC::JSWebAssemblyMemory::JSWebAssemblyMemory):
(JSC::JSWebAssemblyMemory::buffer):
(JSC::JSWebAssemblyMemory::grow):
* wasm/js/JSWebAssemblyMemory.h:
(JSC::JSWebAssemblyMemory::memory):
(JSC::JSWebAssemblyMemory::offsetOfMemory):
(JSC::JSWebAssemblyMemory::offsetOfSize):
* wasm/js/JSWebAssemblyModule.cpp:
(JSC::JSWebAssemblyModule::create):
(JSC::JSWebAssemblyModule::JSWebAssemblyModule):
* wasm/js/JSWebAssemblyModule.h:
(JSC::JSWebAssemblyModule::signatureIndexFromFunctionIndexSpace):
(JSC::JSWebAssemblyModule::functionImportCount):
* wasm/js/WebAssemblyFunction.cpp:
(JSC::callWebAssemblyFunction):
(JSC::WebAssemblyFunction::create):
(JSC::WebAssemblyFunction::createStructure):
(JSC::WebAssemblyFunction::WebAssemblyFunction):
(JSC::WebAssemblyFunction::finishCreation):
* wasm/js/WebAssemblyFunction.h:
(JSC::WebAssemblyFunction::wasmEntrypoint):
(JSC::WebAssemblyFunction::offsetOfInstance):
(JSC::WebAssemblyFunction::offsetOfWasmEntryPointCode):
* wasm/js/WebAssemblyInstanceConstructor.cpp:
(JSC::constructJSWebAssemblyInstance): always start with a dummy
memory, so wasm-&gt;wasm calls don't need to null-check
* wasm/js/WebAssemblyMemoryConstructor.cpp:
(JSC::constructJSWebAssemblyMemory):
* wasm/js/WebAssemblyModuleConstructor.cpp:
(JSC::WebAssemblyModuleConstructor::createModule):
* wasm/js/WebAssemblyModuleRecord.cpp:
(JSC::WebAssemblyModuleRecord::link):
(JSC::WebAssemblyModuleRecord::evaluate):
* wasm/js/WebAssemblyModuleRecord.h:</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkJSTestsChangeLog">trunk/JSTests/ChangeLog</a></li>
<li><a href="#trunkJSTestswasmBuilderjs">trunk/JSTests/wasm/Builder.js</a></li>
<li><a href="#trunkJSTestswasmLowLevelBinaryjs">trunk/JSTests/wasm/LowLevelBinary.js</a></li>
<li><a href="#trunkJSTestswasmfunctiontestsexceptionsjs">trunk/JSTests/wasm/function-tests/exceptions.js</a></li>
<li><a href="#trunkJSTestswasmfunctionteststraploadjs">trunk/JSTests/wasm/function-tests/trap-load.js</a></li>
<li><a href="#trunkJSTestswasmfunctionteststrapstorejs">trunk/JSTests/wasm/function-tests/trap-store.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="#trunkSourceJavaScriptCoreJavaScriptCorexcodeprojprojectpbxproj">trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj</a></li>
<li><a href="#trunkSourceJavaScriptCorejsccpp">trunk/Source/JavaScriptCore/jsc.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeJSTypeh">trunk/Source/JavaScriptCore/runtime/JSType.h</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="#trunkSourceJavaScriptCorewasmWasmBindingcpp">trunk/Source/JavaScriptCore/wasm/WasmBinding.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorewasmWasmBindingh">trunk/Source/JavaScriptCore/wasm/WasmBinding.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="#trunkSourceJavaScriptCorewasmWasmMemorycpp">trunk/Source/JavaScriptCore/wasm/WasmMemory.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorewasmWasmMemoryh">trunk/Source/JavaScriptCore/wasm/WasmMemory.h</a></li>
<li><a href="#trunkSourceJavaScriptCorewasmWasmMemoryInformationcpp">trunk/Source/JavaScriptCore/wasm/WasmMemoryInformation.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorewasmWasmMemoryInformationh">trunk/Source/JavaScriptCore/wasm/WasmMemoryInformation.h</a></li>
<li><a href="#trunkSourceJavaScriptCorewasmWasmModuleParsercpp">trunk/Source/JavaScriptCore/wasm/WasmModuleParser.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorewasmWasmModuleParserh">trunk/Source/JavaScriptCore/wasm/WasmModuleParser.h</a></li>
<li><a href="#trunkSourceJavaScriptCorewasmWasmPageCounth">trunk/Source/JavaScriptCore/wasm/WasmPageCount.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="#trunkSourceJavaScriptCorewasmWasmSignaturecpp">trunk/Source/JavaScriptCore/wasm/WasmSignature.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorewasmWasmSignatureh">trunk/Source/JavaScriptCore/wasm/WasmSignature.h</a></li>
<li><a href="#trunkSourceJavaScriptCorewasmWasmValidatecpp">trunk/Source/JavaScriptCore/wasm/WasmValidate.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorewasmWasmValidateh">trunk/Source/JavaScriptCore/wasm/WasmValidate.h</a></li>
<li><a href="#trunkSourceJavaScriptCorewasmjsJSWebAssemblyInstanceh">trunk/Source/JavaScriptCore/wasm/js/JSWebAssemblyInstance.h</a></li>
<li><a href="#trunkSourceJavaScriptCorewasmjsJSWebAssemblyMemorycpp">trunk/Source/JavaScriptCore/wasm/js/JSWebAssemblyMemory.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorewasmjsJSWebAssemblyMemoryh">trunk/Source/JavaScriptCore/wasm/js/JSWebAssemblyMemory.h</a></li>
<li><a href="#trunkSourceJavaScriptCorewasmjsJSWebAssemblyModulecpp">trunk/Source/JavaScriptCore/wasm/js/JSWebAssemblyModule.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorewasmjsJSWebAssemblyModuleh">trunk/Source/JavaScriptCore/wasm/js/JSWebAssemblyModule.h</a></li>
<li><a href="#trunkSourceJavaScriptCorewasmjsWebAssemblyFunctioncpp">trunk/Source/JavaScriptCore/wasm/js/WebAssemblyFunction.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorewasmjsWebAssemblyFunctionh">trunk/Source/JavaScriptCore/wasm/js/WebAssemblyFunction.h</a></li>
<li><a href="#trunkSourceJavaScriptCorewasmjsWebAssemblyInstanceConstructorcpp">trunk/Source/JavaScriptCore/wasm/js/WebAssemblyInstanceConstructor.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorewasmjsWebAssemblyMemoryConstructorcpp">trunk/Source/JavaScriptCore/wasm/js/WebAssemblyMemoryConstructor.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorewasmjsWebAssemblyModuleConstructorcpp">trunk/Source/JavaScriptCore/wasm/js/WebAssemblyModuleConstructor.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorewasmjsWebAssemblyModuleRecordcpp">trunk/Source/JavaScriptCore/wasm/js/WebAssemblyModuleRecord.cpp</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#trunkJSTestswasmjsapiwasmtowasmbadsignaturejs">trunk/JSTests/wasm/js-api/wasm-to-wasm-bad-signature.js</a></li>
<li><a href="#trunkJSTestswasmjsapiwasmtowasmjs">trunk/JSTests/wasm/js-api/wasm-to-wasm.js</a></li>
<li><a href="#trunkSourceJavaScriptCorewasmWasmPageCountcpp">trunk/Source/JavaScriptCore/wasm/WasmPageCount.cpp</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkJSTestsChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/JSTests/ChangeLog (210228 => 210229)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JSTests/ChangeLog        2017-01-03 00:32:05 UTC (rev 210228)
+++ trunk/JSTests/ChangeLog        2017-01-03 01:57:40 UTC (rev 210229)
</span><span class="lines">@@ -1,3 +1,38 @@
</span><ins>+2017-01-02  JF Bastien  &lt;jfbastien@apple.com&gt;
+
+        WebAssembly: handle and optimize wasm export → wasm import calls
+        https://bugs.webkit.org/show_bug.cgi?id=165282
+
+        Reviewed by Saam Barati.
+
+        * wasm/Builder.js: Add a Proxy to Builder.js, which intercepts
+        unknown property lookups. This creates way better error messages
+        on typos than 'undefined is not a function', which happens
+        semi-frequently as I typo opcode names (and which one is a typo is
+        hard to find because we chain builders).
+        (const._isValidValue):
+        (get target):
+        (const._importFunctionContinuation):
+        (const._importMemoryContinuation):
+        (const._importTableContinuation):
+        (const._exportFunctionContinuation):
+        (export.default.Builder.prototype._registerSectionBuilders.const.section.in.WASM.description.section.switch.section.case.string_appeared_here.this.section):
+        (export.default.Builder.prototype._registerSectionBuilders.this.Unknown):
+        * wasm/LowLevelBinary.js: Add limited support for var{u}int64 (only the 32-bit values)
+        (export.default.LowLevelBinary.prototype.varint32):
+        (export.default.LowLevelBinary.prototype.varuint64):
+        (export.default.LowLevelBinary.prototype.varint64):
+        * wasm/function-tests/exceptions.js: update error message
+        * wasm/function-tests/trap-load.js: update error message
+        * wasm/function-tests/trap-store.js: update error message
+        * wasm/js-api/wasm-to-wasm-bad-signature.js: Added. Test a bunch of bad wasm-&gt;wasm import signatures
+        (const.makeImportee.signature.switch):
+        (BadSignatureDropStartParams):
+        * wasm/js-api/wasm-to-wasm.js: Added. Test 64-bit wasm-&gt;wasm import calls
+        (const.callerModule):
+        (const.calleeModule):
+        (WasmToWasm):
+
</ins><span class="cx"> 2017-01-02  Saam Barati  &lt;sbarati@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         WebAssembly: Some loads don't take into account the offset
</span></span></pre></div>
<a id="trunkJSTestswasmBuilderjs"></a>
<div class="modfile"><h4>Modified: trunk/JSTests/wasm/Builder.js (210228 => 210229)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JSTests/wasm/Builder.js        2017-01-03 00:32:05 UTC (rev 210228)
+++ trunk/JSTests/wasm/Builder.js        2017-01-03 01:57:40 UTC (rev 210229)
</span><span class="lines">@@ -38,7 +38,7 @@
</span><span class="cx">     switch (type) {
</span><span class="cx">     // We allow both signed and unsigned numbers.
</span><span class="cx">     case &quot;i32&quot;: return Math.round(value) === value &amp;&amp; LLB.varint32Min &lt;= value &amp;&amp; value &lt;= LLB.varuint32Max;
</span><del>-    case &quot;i64&quot;: throw new Error(`Unimplemented: value check for ${type}`); // FIXME https://bugs.webkit.org/show_bug.cgi?id=163420 64-bit values
</del><ins>+    case &quot;i64&quot;: return true; // FIXME https://bugs.webkit.org/show_bug.cgi?id=163420 64-bit values
</ins><span class="cx">     case &quot;f32&quot;: return typeof(value) === &quot;number&quot; &amp;&amp; isFinite(value);
</span><span class="cx">     case &quot;f64&quot;: return typeof(value) === &quot;number&quot; &amp;&amp; isFinite(value);
</span><span class="cx">     default: throw new Error(`Implementation problem: unknown type ${type}`);
</span><span class="lines">@@ -57,6 +57,16 @@
</span><span class="cx">     return [params, ret];
</span><span class="cx"> };
</span><span class="cx"> 
</span><ins>+const _errorHandlingProxyFor = builder =&gt; builder[&quot;__isProxy&quot;] ? builder : new Proxy(builder, {
+    get: (target, property, receiver) =&gt; {
+        if (property === &quot;__isProxy&quot;)
+            return true;
+        if (target[property] === undefined)
+            throw new Error(`WebAssembly builder received unknown property '${property}'`);
+        return target[property];
+    }
+});
+
</ins><span class="cx"> const _maybeRegisterType = (builder, type) =&gt; {
</span><span class="cx">     const typeSection = builder._getSection(&quot;Type&quot;);
</span><span class="cx">     if (typeof(type) === &quot;number&quot;) {
</span><span class="lines">@@ -100,7 +110,7 @@
</span><span class="cx">         section.data.push({ field: field, type: type, kind: &quot;Function&quot;, module: module });
</span><span class="cx">         // Imports also count in the function index space. Map them as objects to avoid clashing with Code functions' names.
</span><span class="cx">         builder._registerFunctionToIndexSpace({ module: module, field: field });
</span><del>-        return nextBuilder;
</del><ins>+        return _errorHandlingProxyFor(nextBuilder);
</ins><span class="cx">     };
</span><span class="cx"> };
</span><span class="cx"> 
</span><span class="lines">@@ -109,7 +119,7 @@
</span><span class="cx">         assert.isString(module, `Import Memory module should be a string, got &quot;${module}&quot;`);
</span><span class="cx">         assert.isString(field, `Import Memory field should be a string, got &quot;${field}&quot;`);
</span><span class="cx">         section.data.push({module, field, kind: &quot;Memory&quot;, memoryDescription: {initial, maximum}});
</span><del>-        return nextBuilder;
</del><ins>+        return _errorHandlingProxyFor(nextBuilder);
</ins><span class="cx">     };
</span><span class="cx"> };
</span><span class="cx"> 
</span><span class="lines">@@ -118,7 +128,7 @@
</span><span class="cx">         assert.isString(module, `Import Table module should be a string, got &quot;${module}&quot;`);
</span><span class="cx">         assert.isString(field, `Import Table field should be a string, got &quot;${field}&quot;`);
</span><span class="cx">         section.data.push({module, field, kind: &quot;Table&quot;, tableDescription: {initial, maximum, element}});
</span><del>-        return nextBuilder;
</del><ins>+        return _errorHandlingProxyFor(nextBuilder);
</ins><span class="cx">     };
</span><span class="cx"> };
</span><span class="cx"> 
</span><span class="lines">@@ -172,7 +182,7 @@
</span><span class="cx">                 assert.eq(type, exportedImport.type, `Re-exporting import &quot;${exportedImport.field}&quot; as &quot;${field}&quot; has mismatching type`);
</span><span class="cx">         }
</span><span class="cx">         section.data.push({ field: field, type: type, kind: &quot;Function&quot;, index: index });
</span><del>-        return nextBuilder;
</del><ins>+        return _errorHandlingProxyFor(nextBuilder);
</ins><span class="cx">     };
</span><span class="cx"> };
</span><span class="cx"> 
</span><span class="lines">@@ -189,7 +199,7 @@
</span><span class="cx">     return (field, index) =&gt; {
</span><span class="cx">         assert.isNumber(index, `Global exports only support number indices right now`);
</span><span class="cx">         section.data.push({ field, kind: &quot;Global&quot;, index });
</span><del>-        return nextBuilder;
</del><ins>+        return _errorHandlingProxyFor(nextBuilder);
</ins><span class="cx">     }
</span><span class="cx"> };
</span><span class="cx"> 
</span><span class="lines">@@ -197,7 +207,7 @@
</span><span class="cx">     return (field, index) =&gt; {
</span><span class="cx">         assert.isNumber(index, `Memory exports only support number indices`);
</span><span class="cx">         section.data.push({field, kind: &quot;Memory&quot;, index});
</span><del>-        return nextBuilder;
</del><ins>+        return _errorHandlingProxyFor(nextBuilder);
</ins><span class="cx">     }
</span><span class="cx"> };
</span><span class="cx"> 
</span><span class="lines">@@ -205,7 +215,7 @@
</span><span class="cx">     return (field, index) =&gt; {
</span><span class="cx">         assert.isNumber(index, `Table exports only support number indices`);
</span><span class="cx">         section.data.push({field, kind: &quot;Table&quot;, index});
</span><del>-        return nextBuilder;
</del><ins>+        return _errorHandlingProxyFor(nextBuilder);
</ins><span class="cx">     }
</span><span class="cx"> };
</span><span class="cx"> 
</span><span class="lines">@@ -220,10 +230,10 @@
</span><span class="cx">                 assert.isString(field, `Import global field should be a string, got &quot;${field}&quot;`);
</span><span class="cx">                 assert.isString(mutability, `Import global mutability should be a string, got &quot;${mutability}&quot;`);
</span><span class="cx">                 section.data.push({ globalDescription: { type: op, mutability: _normalizeMutability(mutability) }, module, field, kind: &quot;Global&quot; });
</span><del>-                return globalBuilder;
</del><ins>+                return _errorHandlingProxyFor(globalBuilder);
</ins><span class="cx">             };
</span><span class="cx">         }
</span><del>-        return globalBuilder;
</del><ins>+        return _errorHandlingProxyFor(globalBuilder);
</ins><span class="cx">     };
</span><span class="cx"> };
</span><span class="cx"> 
</span><span class="lines">@@ -324,11 +334,11 @@
</span><span class="cx">             default:
</span><span class="cx">                 nextBuilder = functionBuilder;
</span><span class="cx">                 break;
</span><del>-                case &quot;End&quot;:
</del><ins>+            case &quot;End&quot;:
</ins><span class="cx">                 nextBuilder = previousBuilder;
</span><del>-                    break;
</del><ins>+                break;
</ins><span class="cx">             case &quot;Block&quot;:
</span><del>-                case &quot;Loop&quot;:
</del><ins>+            case &quot;Loop&quot;:
</ins><span class="cx">             case &quot;If&quot;:
</span><span class="cx">                 nextBuilder = _createFunctionBuilder(func, builder, functionBuilder);
</span><span class="cx">                 break;
</span><span class="lines">@@ -344,11 +354,12 @@
</span><span class="cx">             const stackArgs = []; // FIXME https://bugs.webkit.org/show_bug.cgi?id=162706
</span><span class="cx">             func.code.push({ name: op, value: value, arguments: stackArgs, immediates: imms });
</span><span class="cx">             if (hasContinuation)
</span><del>-                return continuation(nextBuilder).End();
-            return nextBuilder;
</del><ins>+                return _errorHandlingProxyFor(continuation(nextBuilder).End());
+            return _errorHandlingProxyFor(nextBuilder);
</ins><span class="cx">         };
</span><del>-    }
-    return functionBuilder;
</del><ins>+    };
+
+    return _errorHandlingProxyFor(functionBuilder);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> const _createFunction = (section, builder, previousBuilder) =&gt; {
</span><span class="lines">@@ -449,10 +460,10 @@
</span><span class="cx">                         Func: (params, ret) =&gt; {
</span><span class="cx">                             [params, ret] = _normalizeFunctionSignature(params, ret);
</span><span class="cx">                             s.data.push({ params: params, ret: ret });
</span><del>-                            return typeBuilder;
</del><ins>+                            return _errorHandlingProxyFor(typeBuilder);
</ins><span class="cx">                         },
</span><span class="cx">                     };
</span><del>-                    return typeBuilder;
</del><ins>+                    return _errorHandlingProxyFor(typeBuilder);
</ins><span class="cx">                 };
</span><span class="cx">                 break;
</span><span class="cx"> 
</span><span class="lines">@@ -466,7 +477,7 @@
</span><span class="cx">                     importBuilder.Function = _importFunctionContinuation(this, s, importBuilder);
</span><span class="cx">                     importBuilder.Memory = _importMemoryContinuation(this, s, importBuilder);
</span><span class="cx">                     importBuilder.Table = _importTableContinuation(this, s, importBuilder);
</span><del>-                    return importBuilder;
</del><ins>+                    return _errorHandlingProxyFor(importBuilder);
</ins><span class="cx">                 };
</span><span class="cx">                 break;
</span><span class="cx"> 
</span><span class="lines">@@ -477,7 +488,7 @@
</span><span class="cx">                         End: () =&gt; this
</span><span class="cx">                         // FIXME: add ability to add this with whatever.
</span><span class="cx">                     };
</span><del>-                    return functionBuilder;
</del><ins>+                    return _errorHandlingProxyFor(functionBuilder);
</ins><span class="cx">                 };
</span><span class="cx">                 break;
</span><span class="cx"> 
</span><span class="lines">@@ -488,10 +499,10 @@
</span><span class="cx">                         End: () =&gt; this,
</span><span class="cx">                         Table: ({initial, maximum, element}) =&gt; {
</span><span class="cx">                             s.data.push({tableDescription: {initial, maximum, element}});
</span><del>-                            return tableBuilder;
</del><ins>+                            return _errorHandlingProxyFor(tableBuilder);
</ins><span class="cx">                         }
</span><span class="cx">                     };
</span><del>-                    return tableBuilder;
</del><ins>+                    return _errorHandlingProxyFor(tableBuilder);
</ins><span class="cx">                 };
</span><span class="cx">                 break;
</span><span class="cx"> 
</span><span class="lines">@@ -502,10 +513,10 @@
</span><span class="cx">                         End: () =&gt; this,
</span><span class="cx">                         InitialMaxPages: (initial, max) =&gt; {
</span><span class="cx">                             s.data.push({ initial, max });
</span><del>-                            return memoryBuilder;
</del><ins>+                            return _errorHandlingProxyFor(memoryBuilder);
</ins><span class="cx">                         }
</span><span class="cx">                     };
</span><del>-                    return memoryBuilder;
</del><ins>+                    return _errorHandlingProxyFor(memoryBuilder);
</ins><span class="cx">                 };
</span><span class="cx">                 break;
</span><span class="cx"> 
</span><span class="lines">@@ -516,16 +527,16 @@
</span><span class="cx">                         End: () =&gt; this,
</span><span class="cx">                         GetGlobal: (type, initValue, mutability) =&gt; {
</span><span class="cx">                             s.data.push({ type, op: &quot;get_global&quot;, mutability: _normalizeMutability(mutability), initValue });
</span><del>-                            return globalBuilder;
</del><ins>+                            return _errorHandlingProxyFor(globalBuilder);
</ins><span class="cx">                         }
</span><span class="cx">                     };
</span><span class="cx">                     for (let op of WASM.description.value_type) {
</span><span class="cx">                         globalBuilder[_toJavaScriptName(op)] = (initValue, mutability) =&gt; {
</span><span class="cx">                             s.data.push({ type: op, op: op + &quot;.const&quot;, mutability: _normalizeMutability(mutability), initValue });
</span><del>-                            return globalBuilder;
</del><ins>+                            return _errorHandlingProxyFor(globalBuilder);
</ins><span class="cx">                         };
</span><span class="cx">                     }
</span><del>-                    return globalBuilder;
</del><ins>+                    return _errorHandlingProxyFor(globalBuilder);
</ins><span class="cx">                 };
</span><span class="cx">                 break;
</span><span class="cx"> 
</span><span class="lines">@@ -539,7 +550,7 @@
</span><span class="cx">                     exportBuilder.Function = _exportFunctionContinuation(this, s, exportBuilder);
</span><span class="cx">                     exportBuilder.Memory = _exportMemoryContinuation(this, s, exportBuilder);
</span><span class="cx">                     exportBuilder.Table = _exportTableContinuation(this, s, exportBuilder);
</span><del>-                    return exportBuilder;
</del><ins>+                    return _errorHandlingProxyFor(exportBuilder);
</ins><span class="cx">                 };
</span><span class="cx">                 break;
</span><span class="cx"> 
</span><span class="lines">@@ -552,7 +563,7 @@
</span><span class="cx">                     if (typeof(functionIndexOrName) !== &quot;number&quot; &amp;&amp; typeof(functionIndexOrName) !== &quot;string&quot;)
</span><span class="cx">                         throw new Error(`Start section's function index  must either be a number or a string`);
</span><span class="cx">                     s.data.push(functionIndexOrName);
</span><del>-                    return startBuilder;
</del><ins>+                    return _errorHandlingProxyFor(startBuilder);
</ins><span class="cx">                 };
</span><span class="cx">                 break;
</span><span class="cx"> 
</span><span class="lines">@@ -563,11 +574,11 @@
</span><span class="cx">                         End: () =&gt; this,
</span><span class="cx">                         Element: ({tableIndex = 0, offset, functionIndices}) =&gt; {
</span><span class="cx">                             s.data.push({tableIndex, offset, functionIndices});
</span><del>-                            return elementBuilder;
</del><ins>+                            return _errorHandlingProxyFor(elementBuilder);
</ins><span class="cx">                         }
</span><span class="cx">                     };
</span><span class="cx"> 
</span><del>-                    return elementBuilder;
</del><ins>+                    return _errorHandlingProxyFor(elementBuilder);
</ins><span class="cx">                 };
</span><span class="cx">                 break;
</span><span class="cx"> 
</span><span class="lines">@@ -632,12 +643,12 @@
</span><span class="cx">                                     // FIXME in checked mode, test that the type is acceptable for start function. We probably want _registerFunctionToIndexSpace to also register types per index. https://bugs.webkit.org/show_bug.cgi?id=165658
</span><span class="cx">                                 }
</span><span class="cx">                             }
</span><del>-                            return builder;
</del><ins>+                            return _errorHandlingProxyFor(builder);
</ins><span class="cx">                         },
</span><span class="cx"> 
</span><span class="cx">                     };
</span><span class="cx">                     codeBuilder.Function = _createFunction(s, builder, codeBuilder);
</span><del>-                    return codeBuilder;
</del><ins>+                    return _errorHandlingProxyFor(codeBuilder);
</ins><span class="cx">                 };
</span><span class="cx">                 break;
</span><span class="cx"> 
</span><span class="lines">@@ -660,19 +671,19 @@
</span><span class="cx">                                 Index: index =&gt; {
</span><span class="cx">                                     assert.eq(index, 0); // Linear memory index must be zero in MVP.
</span><span class="cx">                                     thisSegment.index = index;
</span><del>-                                    return segmentBuilder;
</del><ins>+                                    return _errorHandlingProxyFor(segmentBuilder);
</ins><span class="cx">                                 },
</span><span class="cx">                                 Offset: offset =&gt; {
</span><span class="cx">                                     // FIXME allow complex init_expr here. https://bugs.webkit.org/show_bug.cgi?id=165700
</span><span class="cx">                                     assert.isNumber(offset);
</span><span class="cx">                                     thisSegment.offset = offset;
</span><del>-                                    return segmentBuilder;
</del><ins>+                                    return _errorHandlingProxyFor(segmentBuilder);
</ins><span class="cx">                                 },
</span><span class="cx">                             };
</span><del>-                            return segmentBuilder;
</del><ins>+                            return _errorHandlingProxyFor(segmentBuilder);
</ins><span class="cx">                         },
</span><span class="cx">                     };
</span><del>-                    return dataBuilder;
</del><ins>+                    return _errorHandlingProxyFor(dataBuilder);
</ins><span class="cx">                 };
</span><span class="cx">                 break;
</span><span class="cx"> 
</span><span class="lines">@@ -690,10 +701,10 @@
</span><span class="cx">                 Byte: b =&gt; {
</span><span class="cx">                     assert.eq(b &amp; 0xFF, b, `Unknown section expected byte, got: &quot;${b}&quot;`);
</span><span class="cx">                     s.data.push(b);
</span><del>-                    return unknownBuilder;
</del><ins>+                    return _errorHandlingProxyFor(unknownBuilder);
</ins><span class="cx">                 }
</span><span class="cx">             };
</span><del>-            return unknownBuilder;
</del><ins>+            return _errorHandlingProxyFor(unknownBuilder);
</ins><span class="cx">         };
</span><span class="cx">     }
</span><span class="cx">     _addSection(nameOrNumber, extraObject) {
</span></span></pre></div>
<a id="trunkJSTestswasmLowLevelBinaryjs"></a>
<div class="modfile"><h4>Modified: trunk/JSTests/wasm/LowLevelBinary.js (210228 => 210229)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JSTests/wasm/LowLevelBinary.js        2017-01-03 00:32:05 UTC (rev 210228)
+++ trunk/JSTests/wasm/LowLevelBinary.js        2017-01-03 01:57:40 UTC (rev 210229)
</span><span class="lines">@@ -170,6 +170,18 @@
</span><span class="cx">             this.uint8(0x80 | b);
</span><span class="cx">         } while (true);
</span><span class="cx">     }
</span><ins>+    varuint64(v) {
+        assert.isNumber(v);
+        if (v &lt; varuint32Min || varuint32Max &lt; v)
+            throw new RangeError(`unimplemented: varuint64 larger than 32-bit`);
+        this.varuint32(v); // FIXME implement 64-bit var{u}int https://bugs.webkit.org/show_bug.cgi?id=163420
+    }
+    varint64(v) {
+        assert.isNumber(v);
+        if (v &lt; varint32Min || varint32Max &lt; v)
+            throw new RangeError(`unimplemented: varint64 larger than 32-bit`);
+        this.varint32(v); // FIXME implement 64-bit var{u}int https://bugs.webkit.org/show_bug.cgi?id=163420
+    }
</ins><span class="cx">     varuint1(v) {
</span><span class="cx">         if (v !== 0 &amp;&amp; v !== 1)
</span><span class="cx">             throw new RangeError(`Invalid varuint1 ${v} range is [0, 1]`);
</span></span></pre></div>
<a id="trunkJSTestswasmfunctiontestsexceptionsjs"></a>
<div class="modfile"><h4>Modified: trunk/JSTests/wasm/function-tests/exceptions.js (210228 => 210229)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JSTests/wasm/function-tests/exceptions.js        2017-01-03 00:32:05 UTC (rev 210228)
+++ trunk/JSTests/wasm/function-tests/exceptions.js        2017-01-03 01:57:40 UTC (rev 210229)
</span><span class="lines">@@ -45,7 +45,7 @@
</span><span class="cx">     assert.eq(table.get(0), null);
</span><span class="cx"> 
</span><span class="cx">     for (let i = 0; i &lt; 1000; i++) {
</span><del>-        assert.throws(() =&gt; foo(0, i), WebAssembly.RuntimeError, &quot;call_indirect to a null table entry (evaluating 'func(...args)')&quot;);
</del><ins>+        assert.throws(() =&gt; foo(0, i), WebAssembly.RuntimeError, &quot;call_indirect to a null table entry&quot;);
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     table.set(0, foo);
</span><span class="lines">@@ -52,11 +52,11 @@
</span><span class="cx">     assert.eq(table.get(0), foo);
</span><span class="cx"> 
</span><span class="cx">     for (let i = 0; i &lt; 1000; i++) {
</span><del>-        assert.throws(() =&gt; foo(1 + i, i), WebAssembly.RuntimeError, &quot;Out of bounds call_indirect (evaluating 'func(...args)')&quot;);
</del><ins>+        assert.throws(() =&gt; foo(1 + i, i), WebAssembly.RuntimeError, &quot;Out of bounds call_indirect&quot;);
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     for (let i = 0; i &lt; 1000; i++) {
</span><del>-        assert.throws(() =&gt; foo(0, i), WebAssembly.RuntimeError, &quot;call_indirect to a signature that does not match (evaluating 'func(...args)')&quot;);
</del><ins>+        assert.throws(() =&gt; foo(0, i), WebAssembly.RuntimeError, &quot;call_indirect to a signature that does not match&quot;);
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     table.set(0, bar);
</span></span></pre></div>
<a id="trunkJSTestswasmfunctionteststraploadjs"></a>
<div class="modfile"><h4>Modified: trunk/JSTests/wasm/function-tests/trap-load.js (210228 => 210229)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JSTests/wasm/function-tests/trap-load.js        2017-01-03 00:32:05 UTC (rev 210228)
+++ trunk/JSTests/wasm/function-tests/trap-load.js        2017-01-03 01:57:40 UTC (rev 210229)
</span><span class="lines">@@ -29,6 +29,6 @@
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> for (let i = 0; i &lt; 1000; i++) {
</span><del>-    const e = assert.throws(() =&gt; foo(numPages * pageSize + 1), WebAssembly.RuntimeError, &quot;Out of bounds memory access (evaluating 'func(...args)')&quot;);
</del><ins>+    const e = assert.throws(() =&gt; foo(numPages * pageSize + 1), WebAssembly.RuntimeError, &quot;Out of bounds memory access&quot;);
</ins><span class="cx">     assert.eq(wasmFrameCountFromError(e), 2);
</span><span class="cx"> }
</span></span></pre></div>
<a id="trunkJSTestswasmfunctionteststrapstorejs"></a>
<div class="modfile"><h4>Modified: trunk/JSTests/wasm/function-tests/trap-store.js (210228 => 210229)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JSTests/wasm/function-tests/trap-store.js        2017-01-03 00:32:05 UTC (rev 210228)
+++ trunk/JSTests/wasm/function-tests/trap-store.js        2017-01-03 01:57:40 UTC (rev 210229)
</span><span class="lines">@@ -25,5 +25,5 @@
</span><span class="cx">     const foo = new WebAssembly.Instance(module, {a: {b: new WebAssembly.Memory({initial: numPages})}}).exports.foo;
</span><span class="cx"> 
</span><span class="cx">     for (let i = 0; i &lt; 10000; i++)
</span><del>-        assert.throws(() =&gt; foo(i, numPages * pageSize + 1), WebAssembly.RuntimeError, &quot;Out of bounds memory access (evaluating 'func(...args)')&quot;);
</del><ins>+        assert.throws(() =&gt; foo(i, numPages * pageSize + 1), WebAssembly.RuntimeError, &quot;Out of bounds memory access&quot;);
</ins><span class="cx"> }
</span></span></pre></div>
<a id="trunkJSTestswasmjsapiwasmtowasmbadsignaturejs"></a>
<div class="addfile"><h4>Added: trunk/JSTests/wasm/js-api/wasm-to-wasm-bad-signature.js (0 => 210229)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JSTests/wasm/js-api/wasm-to-wasm-bad-signature.js                                (rev 0)
+++ trunk/JSTests/wasm/js-api/wasm-to-wasm-bad-signature.js        2017-01-03 01:57:40 UTC (rev 210229)
</span><span class="lines">@@ -0,0 +1,105 @@
</span><ins>+import * as assert from '../assert.js';
+import Builder from '../Builder.js';
+
+const importName = &quot;pierOne&quot;;
+const types = [&quot;i32&quot;, &quot;i64&quot;, &quot;f32&quot;, &quot;f64&quot;, &quot;void&quot;];
+const typesNonVoid = [&quot;i32&quot;, &quot;i64&quot;, &quot;f32&quot;, &quot;f64&quot;];
+const swapType = (type, index) =&gt; types[(types.indexOf(type) + index) % types.length];
+const swapTypeNonVoid = (type, index) =&gt; typesNonVoid[(typesNonVoid.indexOf(type) + index) % typesNonVoid.length];
+
+const signatures = [
+    { params: [&quot;i32&quot;], ret: &quot;void&quot; },
+    { params: [&quot;i64&quot;], ret: &quot;void&quot; },
+    { params: [&quot;f32&quot;], ret: &quot;void&quot; },
+    { params: [&quot;f64&quot;], ret: &quot;void&quot; },
+    { params: [&quot;i32&quot;], ret: &quot;i32&quot; },
+    { params: [&quot;i64&quot;], ret: &quot;i64&quot; },
+    { params: [&quot;f32&quot;], ret: &quot;f32&quot; },
+    { params: [&quot;f64&quot;], ret: &quot;f64&quot; },
+    { params: [&quot;i32&quot;, &quot;f32&quot;], ret: &quot;i32&quot; },
+    { params: [&quot;f32&quot;, &quot;i32&quot;], ret: &quot;i32&quot; },
+    { params: [&quot;i64&quot;, &quot;f64&quot;], ret: &quot;i64&quot; },
+    { params: [&quot;f64&quot;, &quot;i64&quot;], ret: &quot;i64&quot; },
+    { params: [&quot;i32&quot;, &quot;f32&quot;, &quot;i32&quot;], ret: &quot;i32&quot; },
+    { params: [&quot;i32&quot;, &quot;f32&quot;, &quot;i32&quot;], ret: &quot;i32&quot; },
+    { params: [&quot;i64&quot;, &quot;f64&quot;, &quot;i64&quot;], ret: &quot;i64&quot; },
+    { params: [&quot;i64&quot;, &quot;f64&quot;, &quot;i64&quot;], ret: &quot;i64&quot; },
+    { params: Array(32).fill(&quot;i32&quot;), ret: &quot;i64&quot; },
+    { params: Array(32).fill(&quot;i64&quot;), ret: &quot;i64&quot; },
+    { params: Array(32).fill(&quot;f32&quot;), ret: &quot;i64&quot; },
+    { params: Array(32).fill(&quot;f64&quot;), ret: &quot;i64&quot; },
+];
+
+const makeImporter = signature =&gt; {
+    const builder = (new Builder())
+        .Type().End()
+        .Import().Function(&quot;exports&quot;, importName, signature).End();
+    return new WebAssembly.Module(builder.WebAssembly().get());
+};
+
+const makeImportee = signature =&gt; {
+    const builder = (new Builder())
+        .Type().End()
+        .Function().End()
+        .Export()
+            .Function(importName)
+        .End()
+        .Code()
+            .Function(importName, signature);
+    switch (signature.ret) {
+    case &quot;i32&quot;: builder.I32Const(0); break;
+    case &quot;i64&quot;: builder.I64Const(0); break;
+    case &quot;f32&quot;: builder.F32Const(0); break;
+    case &quot;f64&quot;: builder.F64Const(0); break;
+    case &quot;void&quot;: break;
+    }
+    return new WebAssembly.Instance(new WebAssembly.Module(builder.Return().End().End().WebAssembly().get()));
+};
+
+(function BadSignatureDropStartParams() {
+    for (let signature of signatures) {
+        const importee = makeImportee(signature);
+        for (let i = 1; i &lt;= signature.params.length; ++i) {
+            const badParamSignature = { params: signature.params.slice(i, signature.params.length), ret: signature.ret };
+            const importer = makeImporter(badParamSignature);
+            assert.throws(() =&gt; new WebAssembly.Instance(importer, importee), WebAssembly.LinkError, `imported function's signature doesn't match the provided WebAssembly function's signature (evaluating 'new WebAssembly.Instance(importer, importee)')`);
+        }
+    }
+})();
+
+(function BadSignatureDropEndParams() {
+    for (let signature of signatures) {
+        const importee = makeImportee(signature);
+        for (let i = 1; i &lt; signature.params.length; ++i) {
+            const badParamSignature = { params: signature.params.slice(0, i), ret: signature.ret };
+            const importer = makeImporter(badParamSignature);
+            assert.throws(() =&gt; new WebAssembly.Instance(importer, importee), WebAssembly.LinkError, `imported function's signature doesn't match the provided WebAssembly function's signature (evaluating 'new WebAssembly.Instance(importer, importee)')`);
+        }
+    }
+})();
+
+(function BadSignatureSwapParam() {
+    for (let signature of signatures) {
+        const importee = makeImportee(signature);
+        for (let signatureIndex = 0; signatureIndex &lt; signature.length; ++signatureIndex) {
+            for (let typeIndex = 1; typeIndex &lt; typesNonVoid.length; ++typeIndex) {
+                let badParams = signature.params.slice();
+                badParams[signatureIndex] = swapTypeNonVoid(badParams[signatureIndex], typeIndex);
+                const badParamSignature = { params: badParams, ret: signature.ret };
+                const importer = makeImporter(badParamSignature);
+                assert.throws(() =&gt; new WebAssembly.Instance(importer, importee), WebAssembly.LinkError, `imported function's signature doesn't match the provided WebAssembly function's signature (evaluating 'new WebAssembly.Instance(importer, importee)')`);
+            }
+        }
+    }
+})();
+
+(function BadSignatureRet() {
+    for (let signature of signatures) {
+        const importee = makeImportee(signature);
+        for (let typeIndex = 1; typeIndex &lt; types.length; ++typeIndex) {
+            const badParamSignature = { params: signature.params, ret: swapType(signature.ret, typeIndex) };
+            const importer = makeImporter(badParamSignature);
+            assert.throws(() =&gt; new WebAssembly.Instance(importer, importee), WebAssembly.LinkError, `imported function's signature doesn't match the provided WebAssembly function's signature (evaluating 'new WebAssembly.Instance(importer, importee)')`);
+        }
+    }
+})();
</ins></span></pre></div>
<a id="trunkJSTestswasmjsapiwasmtowasmjs"></a>
<div class="addfile"><h4>Added: trunk/JSTests/wasm/js-api/wasm-to-wasm.js (0 => 210229)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JSTests/wasm/js-api/wasm-to-wasm.js                                (rev 0)
+++ trunk/JSTests/wasm/js-api/wasm-to-wasm.js        2017-01-03 01:57:40 UTC (rev 210229)
</span><span class="lines">@@ -0,0 +1,72 @@
</span><ins>+import * as assert from '../assert.js';
+import Builder from '../Builder.js';
+
+const callerTopBits = 0xC0FEBEEF;
+const innerReturnHi = 0xDEADFACE;
+const innerReturnLo = 0xC0FEC0FE;
+
+const callerModule = () =&gt; {
+    const builder = (new Builder())
+        .Type().End()
+        .Import()
+            .Function(&quot;exports&quot;, &quot;callMe&quot;, { params: [&quot;i64&quot;], ret: &quot;i64&quot; })
+        .End()
+        .Function().End()
+        .Export()
+            .Function(&quot;entry&quot;)
+        .End()
+        .Code()
+            .Function(&quot;entry&quot;, { params: [&quot;i32&quot;], ret: &quot;i32&quot; }, [&quot;i64&quot;])
+                .I32Const(callerTopBits).I64ExtendUI32().I32Const(32).I64ExtendUI32().I64Shl() // ((i64)callerTopBits) &lt;&lt; 32
+                .GetLocal(0).I64ExtendUI32()
+                .I64Or() // value: param | (((i64)callerTopBits &lt;&lt; 32))
+                .Call(0) // Calls exports.callMe(param | (((i64)callerTopBits) &lt;&lt; 32)).
+                .TeeLocal(1).I32WrapI64() // lo: (i32)callResult
+                .GetLocal(1).I32Const(32).I64ExtendUI32().I64ShrU().I32WrapI64() // hi: (i32)(callResult &gt;&gt; 32)
+                .I32Xor()
+                .Return()
+            .End()
+        .End();
+    return new WebAssembly.Module(builder.WebAssembly().get());
+};
+
+const calleeModule = () =&gt; {
+    const builder = (new Builder())
+        .Type().End()
+        .Import()
+            .Function(&quot;imp&quot;, &quot;func&quot;, { params: [&quot;i32&quot;, &quot;i32&quot;], ret: &quot;i32&quot; })
+        .End()
+        .Function().End()
+        .Export()
+            .Function(&quot;callMe&quot;)
+        .End()
+        .Code()
+            .Function(&quot;callMe&quot;, { params: [&quot;i64&quot;], ret: &quot;i64&quot; })
+                .GetLocal(0).I32WrapI64() // lo: (i32)param
+                .GetLocal(0).I32Const(32).I64ExtendUI32().I64ShrU().I32WrapI64() // hi: (i32)(param &gt;&gt; 32)
+                .Call(0) // Calls imp.func with the 64-bit value as i32 { hi, lo }.
+                .Drop()
+                .I32Const(innerReturnHi).I64ExtendUI32().I32Const(32).I64ExtendUI32().I64Shl().I32Const(innerReturnLo).I64ExtendUI32().I64Or() // ((i64)hi &lt;&lt; 32) | (i64)lo
+                .Return()
+            .End()
+        .End();
+    return new WebAssembly.Module(builder.WebAssembly().get());
+};
+
+(function WasmToWasm() {
+    let value;
+    const func = (hi, lo) =&gt; { value = { hi: hi, lo: lo }; return hi ^ lo; };
+    const callee = new WebAssembly.Instance(calleeModule(), { imp: { func: func } });
+    const caller = new WebAssembly.Instance(callerModule(), callee);
+    for (let i = 0; i &lt; 4096; ++i) {
+        assert.eq(caller.exports.entry(i), innerReturnHi ^ innerReturnLo);
+        assert.eq(value.lo &gt;&gt;&gt; 0, callerTopBits);
+        assert.eq(value.hi &gt;&gt;&gt; 0, i);
+    }
+})();
+
+// FIXME test the following https://bugs.webkit.org/show_bug.cgi?id=166625
+// - wasm-&gt;wasm using 32-bit things (including float), as well as 64-bit NaNs that don't get canonicalized
+// - Do a throw two-deep
+// - Check that the first wasm's instance is back in OK state (with table or global?)
+// - Test calling through a Table
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCoreCMakeListstxt"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/CMakeLists.txt (210228 => 210229)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/CMakeLists.txt        2017-01-03 00:32:05 UTC (rev 210228)
+++ trunk/Source/JavaScriptCore/CMakeLists.txt        2017-01-03 01:57:40 UTC (rev 210229)
</span><span class="lines">@@ -905,6 +905,7 @@
</span><span class="cx">     wasm/WasmMemory.cpp
</span><span class="cx">     wasm/WasmMemoryInformation.cpp
</span><span class="cx">     wasm/WasmModuleParser.cpp
</span><ins>+    wasm/WasmPageCount.cpp
</ins><span class="cx">     wasm/WasmPlan.cpp
</span><span class="cx">     wasm/WasmSignature.cpp
</span><span class="cx">     wasm/WasmValidate.cpp
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ChangeLog (210228 => 210229)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ChangeLog        2017-01-03 00:32:05 UTC (rev 210228)
+++ trunk/Source/JavaScriptCore/ChangeLog        2017-01-03 01:57:40 UTC (rev 210229)
</span><span class="lines">@@ -1,3 +1,128 @@
</span><ins>+2017-01-02  JF Bastien  &lt;jfbastien@apple.com&gt;
+
+        WebAssembly: handle and optimize wasm export → wasm import calls
+        https://bugs.webkit.org/show_bug.cgi?id=165282
+
+        Reviewed by Saam Barati.
+
+          - Add a new JSType for WebAssemblyFunction, and use it when creating its
+            structure. This will is used to quickly detect from wasm whether the import
+            call is to another wasm module, or whether it's to JS.
+          - Generate two stubs from the import stub generator: one for wasm-&gt;JS and one
+            for wasm -&gt; wasm. This is done at Module time. Which is called will only be
+            known at Instance time, once we've received the import object. We want to
+            avoid codegen at Instance time, so having both around is great.
+          - Restore the WebAssembly global state (VM top Instance, and pinned registers)
+            after call / call_indirect, and in the JS-&gt;wasm entry stub.
+          - Pinned registers are now a global thing, not per-Memory, because the wasm -&gt;
+            wasm stubs are generated at Module time where we don't really have enough
+            information to do the right thing (doing so would generate too much code).
+
+        * CMakeLists.txt:
+        * JavaScriptCore.xcodeproj/project.pbxproj:
+        * runtime/JSType.h: add WebAssemblyFunctionType as a JSType
+        * wasm/WasmB3IRGenerator.cpp: significantly rework how calls which
+        could be external work, and how we save / restore global state:
+        VM's top Instance, and pinned registers
+        (JSC::Wasm::B3IRGenerator::B3IRGenerator):
+        (JSC::Wasm::getMemoryBaseAndSize):
+        (JSC::Wasm::restoreWebAssemblyGlobalState):
+        (JSC::Wasm::createJSToWasmWrapper):
+        (JSC::Wasm::parseAndCompile):
+        * wasm/WasmB3IRGenerator.h:
+        * wasm/WasmBinding.cpp:
+        (JSC::Wasm::materializeImportJSCell):
+        (JSC::Wasm::wasmToJS):
+        (JSC::Wasm::wasmToWasm): the main goal of this patch was adding this function
+        (JSC::Wasm::exitStubGenerator):
+        * wasm/WasmBinding.h:
+        * wasm/WasmFormat.h: Get rid of much of the function index space:
+        we already have all of its information elsewhere, and as-is it
+        provides no extra efficiency.
+        (JSC::Wasm::ModuleInformation::functionIndexSpaceSize):
+        (JSC::Wasm::ModuleInformation::isImportedFunctionFromFunctionIndexSpace):
+        (JSC::Wasm::ModuleInformation::signatureIndexFromFunctionIndexSpace):
+        * wasm/WasmFunctionParser.h:
+        (JSC::Wasm::FunctionParser&lt;Context&gt;::FunctionParser):
+        * wasm/WasmMemory.cpp: Add some logging.
+        (JSC::Wasm::Memory::dump): this was nice when debugging
+        (JSC::Wasm::Memory::makeString):
+        (JSC::Wasm::Memory::Memory):
+        (JSC::Wasm::Memory::~Memory):
+        (JSC::Wasm::Memory::grow):
+        * wasm/WasmMemory.h: don't use extra indirection, it wasn't
+        needed. Reorder some of the fields which are looked up at runtime
+        so they're more cache-friendly.
+        (JSC::Wasm::Memory::Memory):
+        (JSC::Wasm::Memory::mode):
+        (JSC::Wasm::Memory::offsetOfSize):
+        * wasm/WasmMemoryInformation.cpp: Pinned registers are now a
+        global thing for all of JSC, not a per-Memory thing
+        anymore. wasm-&gt;wasm calls are more complex otherwise: they have to
+        figure out how to bridge between the caller and callee's
+        special-snowflake pinning.
+        (JSC::Wasm::PinnedRegisterInfo::get):
+        (JSC::Wasm::PinnedRegisterInfo::PinnedRegisterInfo):
+        (JSC::Wasm::MemoryInformation::MemoryInformation):
+        * wasm/WasmMemoryInformation.h:
+        * wasm/WasmModuleParser.cpp:
+        * wasm/WasmModuleParser.h:
+        * wasm/WasmPageCount.cpp: Copied from Source/JavaScriptCore/wasm/WasmBinding.h.
+        (JSC::Wasm::PageCount::dump): nice for debugging
+        * wasm/WasmPageCount.h:
+        * wasm/WasmPlan.cpp:
+        (JSC::Wasm::Plan::parseAndValidateModule):
+        (JSC::Wasm::Plan::run):
+        * wasm/WasmPlan.h:
+        (JSC::Wasm::Plan::takeWasmExitStubs):
+        * wasm/WasmSignature.cpp:
+        (JSC::Wasm::Signature::toString):
+        (JSC::Wasm::Signature::dump):
+        * wasm/WasmSignature.h:
+        * wasm/WasmValidate.cpp:
+        (JSC::Wasm::validateFunction):
+        * wasm/WasmValidate.h:
+        * wasm/js/JSWebAssemblyInstance.h:
+        (JSC::JSWebAssemblyInstance::offsetOfTable):
+        (JSC::JSWebAssemblyInstance::offsetOfImportFunctions):
+        (JSC::JSWebAssemblyInstance::offsetOfImportFunction):
+        * wasm/js/JSWebAssemblyMemory.cpp:
+        (JSC::JSWebAssemblyMemory::create):
+        (JSC::JSWebAssemblyMemory::JSWebAssemblyMemory):
+        (JSC::JSWebAssemblyMemory::buffer):
+        (JSC::JSWebAssemblyMemory::grow):
+        * wasm/js/JSWebAssemblyMemory.h:
+        (JSC::JSWebAssemblyMemory::memory):
+        (JSC::JSWebAssemblyMemory::offsetOfMemory):
+        (JSC::JSWebAssemblyMemory::offsetOfSize):
+        * wasm/js/JSWebAssemblyModule.cpp:
+        (JSC::JSWebAssemblyModule::create):
+        (JSC::JSWebAssemblyModule::JSWebAssemblyModule):
+        * wasm/js/JSWebAssemblyModule.h:
+        (JSC::JSWebAssemblyModule::signatureIndexFromFunctionIndexSpace):
+        (JSC::JSWebAssemblyModule::functionImportCount):
+        * wasm/js/WebAssemblyFunction.cpp:
+        (JSC::callWebAssemblyFunction):
+        (JSC::WebAssemblyFunction::create):
+        (JSC::WebAssemblyFunction::createStructure):
+        (JSC::WebAssemblyFunction::WebAssemblyFunction):
+        (JSC::WebAssemblyFunction::finishCreation):
+        * wasm/js/WebAssemblyFunction.h:
+        (JSC::WebAssemblyFunction::wasmEntrypoint):
+        (JSC::WebAssemblyFunction::offsetOfInstance):
+        (JSC::WebAssemblyFunction::offsetOfWasmEntryPointCode):
+        * wasm/js/WebAssemblyInstanceConstructor.cpp:
+        (JSC::constructJSWebAssemblyInstance): always start with a dummy
+        memory, so wasm-&gt;wasm calls don't need to null-check
+        * wasm/js/WebAssemblyMemoryConstructor.cpp:
+        (JSC::constructJSWebAssemblyMemory):
+        * wasm/js/WebAssemblyModuleConstructor.cpp:
+        (JSC::WebAssemblyModuleConstructor::createModule):
+        * wasm/js/WebAssemblyModuleRecord.cpp:
+        (JSC::WebAssemblyModuleRecord::link):
+        (JSC::WebAssemblyModuleRecord::evaluate):
+        * wasm/js/WebAssemblyModuleRecord.h:
+
</ins><span class="cx"> 2017-01-02  Saam Barati  &lt;sbarati@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         WebAssembly: Some loads don't take into account the offset
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreJavaScriptCorexcodeprojprojectpbxproj"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj (210228 => 210229)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj        2017-01-03 00:32:05 UTC (rev 210228)
+++ trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj        2017-01-03 01:57:40 UTC (rev 210229)
</span><span class="lines">@@ -1235,6 +1235,7 @@
</span><span class="cx">                 2ADFA26318EF3540004F9FCC /* GCLogging.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2ADFA26218EF3540004F9FCC /* GCLogging.cpp */; };
</span><span class="cx">                 2AF7382C18BBBF92008A5A37 /* StructureIDTable.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2AF7382A18BBBF92008A5A37 /* StructureIDTable.cpp */; };
</span><span class="cx">                 2AF7382D18BBBF92008A5A37 /* StructureIDTable.h in Headers */ = {isa = PBXBuildFile; fileRef = 2AF7382B18BBBF92008A5A37 /* StructureIDTable.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><ins>+                2D342F36F7244096804ADB24 /* SourceOrigin.h in Headers */ = {isa = PBXBuildFile; fileRef = 425BA1337E4344E1B269A671 /* SourceOrigin.h */; settings = {ATTRIBUTES = (Private, ); }; };
</ins><span class="cx">                 371D842D17C98B6E00ECF994 /* libz.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 371D842C17C98B6E00ECF994 /* libz.dylib */; };
</span><span class="cx">                 412952771D2CF6BC00E78B89 /* builtins_generate_internals_wrapper_header.py in Headers */ = {isa = PBXBuildFile; fileRef = 412952731D2CF6AC00E78B89 /* builtins_generate_internals_wrapper_header.py */; settings = {ATTRIBUTES = (Private, ); }; };
</span><span class="cx">                 412952781D2CF6BC00E78B89 /* builtins_generate_internals_wrapper_implementation.py in Headers */ = {isa = PBXBuildFile; fileRef = 412952741D2CF6AC00E78B89 /* builtins_generate_internals_wrapper_implementation.py */; settings = {ATTRIBUTES = (Private, ); }; };
</span><span class="lines">@@ -2025,6 +2026,7 @@
</span><span class="cx">                 AD7438C01E0457A400FD0C2A /* WasmSignature.h in Headers */ = {isa = PBXBuildFile; fileRef = AD7438BF1E04579200FD0C2A /* WasmSignature.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><span class="cx">                 AD7438C11E0457AA00FD0C2A /* WasmSignature.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AD7438BE1E04579200FD0C2A /* WasmSignature.cpp */; };
</span><span class="cx">                 AD86A93E1AA4D88D002FE77F /* WeakGCMapInlines.h in Headers */ = {isa = PBXBuildFile; fileRef = AD86A93D1AA4D87C002FE77F /* WeakGCMapInlines.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><ins>+                ADB6F67D1E15D7600082F384 /* WasmPageCount.cpp in Sources */ = {isa = PBXBuildFile; fileRef = ADB6F67C1E15D7500082F384 /* WasmPageCount.cpp */; };
</ins><span class="cx">                 ADBC54D41DF8EA2B005BF738 /* WebAssemblyToJSCallee.cpp in Sources */ = {isa = PBXBuildFile; fileRef = ADBC54D21DF8EA00005BF738 /* WebAssemblyToJSCallee.cpp */; };
</span><span class="cx">                 ADBC54D51DF8EA2B005BF738 /* WebAssemblyToJSCallee.h in Headers */ = {isa = PBXBuildFile; fileRef = ADBC54D31DF8EA00005BF738 /* WebAssemblyToJSCallee.h */; };
</span><span class="cx">                 ADDB1F6318D77DBE009B58A8 /* OpaqueRootSet.h in Headers */ = {isa = PBXBuildFile; fileRef = ADDB1F6218D77DB7009B58A8 /* OpaqueRootSet.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><span class="lines">@@ -2361,7 +2363,6 @@
</span><span class="cx">                 FED94F2F171E3E2300BE77A4 /* Watchdog.h in Headers */ = {isa = PBXBuildFile; fileRef = FED94F2C171E3E2300BE77A4 /* Watchdog.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><span class="cx">                 FEF040511AAE662D00BD28B0 /* CompareAndSwapTest.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FEF040501AAE662D00BD28B0 /* CompareAndSwapTest.cpp */; };
</span><span class="cx">                 FEFD6FC61D5E7992008F2F0B /* JSStringInlines.h in Headers */ = {isa = PBXBuildFile; fileRef = FEFD6FC51D5E7970008F2F0B /* JSStringInlines.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><del>-                2D342F36F7244096804ADB24 /* SourceOrigin.h in Headers */ = {isa = PBXBuildFile; fileRef = 425BA1337E4344E1B269A671 /* SourceOrigin.h */; settings = {ATTRIBUTES = (Private, ); }; };
</del><span class="cx"> /* End PBXBuildFile section */
</span><span class="cx"> 
</span><span class="cx"> /* Begin PBXContainerItemProxy section */
</span><span class="lines">@@ -3638,6 +3639,7 @@
</span><span class="cx">                 412952751D2CF6AC00E78B89 /* builtins_generate_wrapper_header.py */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.python; path = builtins_generate_wrapper_header.py; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 412952761D2CF6AC00E78B89 /* builtins_generate_wrapper_implementation.py */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.python; path = builtins_generate_wrapper_implementation.py; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 41DEA1311B9F3154006D65DD /* BuiltinUtils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BuiltinUtils.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><ins>+                425BA1337E4344E1B269A671 /* SourceOrigin.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SourceOrigin.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</ins><span class="cx">                 4319DA011C1BE3C1001D260B /* B3LowerMacrosAfterOptimizations.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = B3LowerMacrosAfterOptimizations.cpp; path = b3/B3LowerMacrosAfterOptimizations.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 4319DA021C1BE3C1001D260B /* B3LowerMacrosAfterOptimizations.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = B3LowerMacrosAfterOptimizations.h; path = b3/B3LowerMacrosAfterOptimizations.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 4340A4821A9051AF00D73CCA /* MathCommon.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MathCommon.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="lines">@@ -4510,6 +4512,7 @@
</span><span class="cx">                 AD7438BE1E04579200FD0C2A /* WasmSignature.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WasmSignature.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 AD7438BF1E04579200FD0C2A /* WasmSignature.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WasmSignature.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 AD86A93D1AA4D87C002FE77F /* WeakGCMapInlines.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WeakGCMapInlines.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><ins>+                ADB6F67C1E15D7500082F384 /* WasmPageCount.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WasmPageCount.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</ins><span class="cx">                 ADBC54D21DF8EA00005BF738 /* WebAssemblyToJSCallee.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = WebAssemblyToJSCallee.cpp; path = js/WebAssemblyToJSCallee.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 ADBC54D31DF8EA00005BF738 /* WebAssemblyToJSCallee.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = WebAssemblyToJSCallee.h; path = js/WebAssemblyToJSCallee.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 ADDB1F6218D77DB7009B58A8 /* OpaqueRootSet.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OpaqueRootSet.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="lines">@@ -4879,7 +4882,6 @@
</span><span class="cx">                 FEF040501AAE662D00BD28B0 /* CompareAndSwapTest.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = CompareAndSwapTest.cpp; path = API/tests/CompareAndSwapTest.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 FEF040521AAEC4ED00BD28B0 /* CompareAndSwapTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CompareAndSwapTest.h; path = API/tests/CompareAndSwapTest.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 FEFD6FC51D5E7970008F2F0B /* JSStringInlines.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSStringInlines.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><del>-                425BA1337E4344E1B269A671 /* SourceOrigin.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SourceOrigin.h; path = SourceOrigin.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</del><span class="cx"> /* End PBXFileReference section */
</span><span class="cx"> 
</span><span class="cx"> /* Begin PBXFrameworksBuildPhase section */
</span><span class="lines">@@ -6047,6 +6049,7 @@
</span><span class="cx">                                 79B759721DFA4C600052174C /* WasmMemoryInformation.h */,
</span><span class="cx">                                 53F40E961D5A7BEC0099A1B6 /* WasmModuleParser.cpp */,
</span><span class="cx">                                 53F40E941D5A7AEF0099A1B6 /* WasmModuleParser.h */,
</span><ins>+                                ADB6F67C1E15D7500082F384 /* WasmPageCount.cpp */,
</ins><span class="cx">                                 79B759731DFA4C600052174C /* WasmPageCount.h */,
</span><span class="cx">                                 53F40E8C1D5901F20099A1B6 /* WasmParser.h */,
</span><span class="cx">                                 531374BE1D5CE95000AF7A0B /* WasmPlan.cpp */,
</span><span class="lines">@@ -9703,6 +9706,7 @@
</span><span class="cx">                                 0F64B2711A784BAF006E4E66 /* BinarySwitch.cpp in Sources */,
</span><span class="cx">                                 14280863107EC11A0013E7B2 /* BooleanConstructor.cpp in Sources */,
</span><span class="cx">                                 14280864107EC11A0013E7B2 /* BooleanObject.cpp in Sources */,
</span><ins>+                                ADB6F67D1E15D7600082F384 /* WasmPageCount.cpp in Sources */,
</ins><span class="cx">                                 14280865107EC11A0013E7B2 /* BooleanPrototype.cpp in Sources */,
</span><span class="cx">                                 DE26E9071CB5DEFB00D2BE82 /* BuiltinExecutableCreator.cpp in Sources */,
</span><span class="cx">                                 A7D801A41880D66E0026C39B /* BuiltinExecutables.cpp in Sources */,
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejsccpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jsc.cpp (210228 => 210229)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jsc.cpp        2017-01-03 00:32:05 UTC (rev 210228)
+++ trunk/Source/JavaScriptCore/jsc.cpp        2017-01-03 01:57:40 UTC (rev 210229)
</span><span class="lines">@@ -2647,7 +2647,6 @@
</span><span class="cx">                 lastIndex = calleeIndex;
</span><span class="cx">             });
</span><span class="cx">     }
</span><del>-
</del><span class="cx">     std::unique_ptr&lt;Wasm::ModuleInformation&gt; moduleInformation = plan.takeModuleInformation();
</span><span class="cx">     RELEASE_ASSERT(!moduleInformation-&gt;memory);
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeJSTypeh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/JSType.h (210228 => 210229)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/JSType.h        2017-01-03 00:32:05 UTC (rev 210228)
+++ trunk/Source/JavaScriptCore/runtime/JSType.h        2017-01-03 01:57:40 UTC (rev 210229)
</span><span class="lines">@@ -93,6 +93,8 @@
</span><span class="cx">     JSMapType,
</span><span class="cx">     JSSetType,
</span><span class="cx"> 
</span><ins>+    WebAssemblyFunctionType,
+
</ins><span class="cx">     LastJSCObjectType = JSSetType,
</span><span class="cx">     MaxJSType = 0b11111111,
</span><span class="cx"> };
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorewasmWasmB3IRGeneratorcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/wasm/WasmB3IRGenerator.cpp (210228 => 210229)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/wasm/WasmB3IRGenerator.cpp        2017-01-03 00:32:05 UTC (rev 210228)
+++ trunk/Source/JavaScriptCore/wasm/WasmB3IRGenerator.cpp        2017-01-03 01:57:40 UTC (rev 210229)
</span><span class="lines">@@ -155,7 +155,7 @@
</span><span class="cx">             return fail(__VA_ARGS__);             \
</span><span class="cx">     } while (0)
</span><span class="cx"> 
</span><del>-    B3IRGenerator(VM&amp;, const ModuleInformation&amp;, Procedure&amp;, WasmInternalFunction*, Vector&lt;UnlinkedWasmToWasmCall&gt;&amp;, const ImmutableFunctionIndexSpace&amp;);
</del><ins>+    B3IRGenerator(VM&amp;, const ModuleInformation&amp;, Procedure&amp;, WasmInternalFunction*, Vector&lt;UnlinkedWasmToWasmCall&gt;&amp;);
</ins><span class="cx"> 
</span><span class="cx">     PartialResult WARN_UNUSED_RETURN addArguments(const Signature*);
</span><span class="cx">     PartialResult WARN_UNUSED_RETURN addLocal(Type, uint32_t);
</span><span class="lines">@@ -205,8 +205,6 @@
</span><span class="cx"> 
</span><span class="cx">     void emitExceptionCheck(CCallHelpers&amp;, ExceptionType);
</span><span class="cx"> 
</span><del>-    void emitReloadPinnedRegisters();
-
</del><span class="cx"> private:
</span><span class="cx">     ExpressionType emitCheckAndPreparePointer(ExpressionType pointer, uint32_t offset, uint32_t sizeOfOp);
</span><span class="cx">     ExpressionType emitLoadOp(LoadOpType, Origin, ExpressionType pointer, uint32_t offset);
</span><span class="lines">@@ -219,7 +217,6 @@
</span><span class="cx">     void emitChecksForModOrDiv(B3::Opcode, ExpressionType left, ExpressionType right);
</span><span class="cx"> 
</span><span class="cx">     VM&amp; m_vm;
</span><del>-    const ImmutableFunctionIndexSpace&amp; m_functionIndexSpace;
</del><span class="cx">     const ModuleInformation&amp; m_info;
</span><span class="cx">     Procedure&amp; m_proc;
</span><span class="cx">     BasicBlock* m_currentBlock;
</span><span class="lines">@@ -231,9 +228,8 @@
</span><span class="cx">     Value* m_instanceValue;
</span><span class="cx"> };
</span><span class="cx"> 
</span><del>-B3IRGenerator::B3IRGenerator(VM&amp; vm, const ModuleInformation&amp; info, Procedure&amp; procedure, WasmInternalFunction* compilation, Vector&lt;UnlinkedWasmToWasmCall&gt;&amp; unlinkedWasmToWasmCalls, const ImmutableFunctionIndexSpace&amp; functionIndexSpace)
</del><ins>+B3IRGenerator::B3IRGenerator(VM&amp; vm, const ModuleInformation&amp; info, Procedure&amp; procedure, WasmInternalFunction* compilation, Vector&lt;UnlinkedWasmToWasmCall&gt;&amp; unlinkedWasmToWasmCalls)
</ins><span class="cx">     : m_vm(vm)
</span><del>-    , m_functionIndexSpace(functionIndexSpace)
</del><span class="cx">     , m_info(info)
</span><span class="cx">     , m_proc(procedure)
</span><span class="cx">     , m_unlinkedWasmToWasmCalls(unlinkedWasmToWasmCalls)
</span><span class="lines">@@ -254,14 +250,16 @@
</span><span class="cx">         }
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    // FIXME we don't really need to pin registers here if there's no memory. It makes wasm -&gt; wasm thunks simpler for now. https://bugs.webkit.org/show_bug.cgi?id=166623
+    const PinnedRegisterInfo&amp; pinnedRegs = PinnedRegisterInfo::get();
+    m_memoryBaseGPR = pinnedRegs.baseMemoryPointer;
+    m_proc.pinRegister(m_memoryBaseGPR);
+    ASSERT(!pinnedRegs.sizeRegisters[0].sizeOffset);
+    m_memorySizeGPR = pinnedRegs.sizeRegisters[0].sizeRegister;
+    for (const PinnedSizeRegisterInfo&amp; regInfo : pinnedRegs.sizeRegisters)
+        m_proc.pinRegister(regInfo.sizeRegister);
+
</ins><span class="cx">     if (info.hasMemory()) {
</span><del>-        m_memoryBaseGPR = info.memory.pinnedRegisters().baseMemoryPointer;
-        m_proc.pinRegister(m_memoryBaseGPR);
-        ASSERT(!info.memory.pinnedRegisters().sizeRegisters[0].sizeOffset);
-        m_memorySizeGPR = info.memory.pinnedRegisters().sizeRegisters[0].sizeRegister;
-        for (const PinnedSizeRegisterInfo&amp; regInfo : info.memory.pinnedRegisters().sizeRegisters)
-            m_proc.pinRegister(regInfo.sizeRegister);
-
</del><span class="cx">         m_proc.setWasmBoundsCheckGenerator([=] (CCallHelpers&amp; jit, GPRReg pinnedGPR, unsigned) {
</span><span class="cx">             AllowMacroScratchRegisterUsage allowScratch(jit);
</span><span class="cx">             ASSERT_UNUSED(pinnedGPR, m_memorySizeGPR == pinnedGPR);
</span><span class="lines">@@ -275,6 +273,56 @@
</span><span class="cx">         m_currentBlock-&gt;appendNew&lt;ConstPtrValue&gt;(m_proc, Origin(), &amp;m_vm.topJSWebAssemblyInstance));
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+struct MemoryBaseAndSize {
+    Value* base;
+    Value* size;
+};
+
+static MemoryBaseAndSize getMemoryBaseAndSize(VM&amp; vm, Value* instance, Procedure&amp; proc, BasicBlock* block)
+{
+    Value* memoryObject = block-&gt;appendNew&lt;MemoryValue&gt;(proc, Load, pointerType(), Origin(), instance, JSWebAssemblyInstance::offsetOfMemory());
+
+    static_assert(sizeof(decltype(vm.topJSWebAssemblyInstance-&gt;memory()-&gt;memory()-&gt;memory())) == sizeof(void*), &quot;codegen relies on this size&quot;);
+    static_assert(sizeof(decltype(vm.topJSWebAssemblyInstance-&gt;memory()-&gt;memory()-&gt;size())) == sizeof(uint64_t), &quot;codegen relies on this size&quot;);
+    MemoryBaseAndSize result;
+    result.base = block-&gt;appendNew&lt;MemoryValue&gt;(proc, Load, pointerType(), Origin(), memoryObject, JSWebAssemblyMemory::offsetOfMemory());
+    result.size = block-&gt;appendNew&lt;MemoryValue&gt;(proc, Load, Int64, Origin(), memoryObject, JSWebAssemblyMemory::offsetOfSize());
+
+    return result;
+}
+
+static void restoreWebAssemblyGlobalState(VM&amp; vm, const MemoryInformation&amp; memory, Value* instance, Procedure&amp; proc, BasicBlock* block)
+{
+    block-&gt;appendNew&lt;MemoryValue&gt;(proc, Store, Origin(), instance, block-&gt;appendNew&lt;ConstPtrValue&gt;(proc, Origin(), &amp;vm.topJSWebAssemblyInstance));
+
+    if (!!memory) {
+        const PinnedRegisterInfo* pinnedRegs = &amp;PinnedRegisterInfo::get();
+        RegisterSet clobbers;
+        clobbers.set(pinnedRegs-&gt;baseMemoryPointer);
+        for (auto info : pinnedRegs-&gt;sizeRegisters)
+            clobbers.set(info.sizeRegister);
+
+        B3::PatchpointValue* patchpoint = block-&gt;appendNew&lt;B3::PatchpointValue&gt;(proc, B3::Void, Origin());
+        patchpoint-&gt;effects = Effects::none();
+        patchpoint-&gt;effects.writesPinned = true;
+        patchpoint-&gt;clobber(clobbers);
+
+        patchpoint-&gt;append(instance, ValueRep::SomeRegister);
+
+        patchpoint-&gt;setGenerator([pinnedRegs] (CCallHelpers&amp; jit, const B3::StackmapGenerationParams&amp; params) {
+            GPRReg baseMemory = pinnedRegs-&gt;baseMemoryPointer;
+            jit.loadPtr(CCallHelpers::Address(params[0].gpr(), JSWebAssemblyInstance::offsetOfMemory()), baseMemory);
+            const auto&amp; sizeRegs = pinnedRegs-&gt;sizeRegisters;
+            ASSERT(sizeRegs.size() &gt;= 1);
+            ASSERT(!sizeRegs[0].sizeOffset); // The following code assumes we start at 0, and calculates subsequent size registers relative to 0.
+            jit.loadPtr(CCallHelpers::Address(baseMemory, JSWebAssemblyMemory::offsetOfSize()), sizeRegs[0].sizeRegister);
+            jit.loadPtr(CCallHelpers::Address(baseMemory, JSWebAssemblyMemory::offsetOfMemory()), baseMemory);
+            for (unsigned i = 1; i &lt; sizeRegs.size(); ++i)
+                jit.add64(CCallHelpers::TrustedImm32(-sizeRegs[i].sizeOffset), sizeRegs[0].sizeRegister, sizeRegs[i].sizeRegister);
+        });
+    }
+}
+
</ins><span class="cx"> void B3IRGenerator::emitExceptionCheck(CCallHelpers&amp; jit, ExceptionType type)
</span><span class="cx"> {
</span><span class="cx">     jit.move(CCallHelpers::TrustedImm32(static_cast&lt;uint32_t&gt;(type)), GPRInfo::argumentGPR1);
</span><span class="lines">@@ -338,49 +386,6 @@
</span><span class="cx">     return { };
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-static void reloadPinnedRegisters(Procedure&amp; proc, BasicBlock* block, const ModuleInformation&amp; info, Value* instance)
-{
-    if (!info.hasMemory())
-        return;
-
-    const MemoryInformation* memory = &amp;info.memory;
-
-    RegisterSet clobbers;
-    clobbers.set(memory-&gt;pinnedRegisters().baseMemoryPointer);
-    for (auto info : memory-&gt;pinnedRegisters().sizeRegisters)
-        clobbers.set(info.sizeRegister);
-
-    B3::PatchpointValue* patchpoint = block-&gt;appendNew&lt;B3::PatchpointValue&gt;(proc, B3::Void, Origin());
-    patchpoint-&gt;effects = Effects::none();
-    patchpoint-&gt;effects.writesPinned = true;
-    patchpoint-&gt;clobber(clobbers);
-    patchpoint-&gt;numGPScratchRegisters = 1;
-
-    patchpoint-&gt;append(instance, ValueRep::SomeRegister);
-
-    patchpoint-&gt;setGenerator([memory] (CCallHelpers&amp; jit, const B3::StackmapGenerationParams&amp; params) {
-        AllowMacroScratchRegisterUsage allowScratch(jit);
-
-        GPRReg scratch = params.gpScratch(0);
-        jit.loadPtr(CCallHelpers::Address(params[0].gpr(), JSWebAssemblyInstance::offsetOfMemory()), scratch);
-        jit.loadPtr(CCallHelpers::Address(scratch, JSWebAssemblyMemory::offsetOfMemory()), scratch);
-        jit.loadPtr(CCallHelpers::Address(scratch, Memory::offsetOfMemory()), memory-&gt;pinnedRegisters().baseMemoryPointer);
-
-        jit.load64(CCallHelpers::Address(scratch, Memory::offsetOfSize()), scratch);
-        for (unsigned i = 0; i &lt; memory-&gt;pinnedRegisters().sizeRegisters.size(); i++) {
-            GPRReg sizeReg = memory-&gt;pinnedRegisters().sizeRegisters[i].sizeRegister;
-            jit.move(scratch, sizeReg);
-            jit.sub64(CCallHelpers::TrustedImm32(memory-&gt;pinnedRegisters().sizeRegisters[i].sizeOffset), sizeReg);
-        }
-    });
-}
-
-void B3IRGenerator::emitReloadPinnedRegisters()
-{
-    reloadPinnedRegisters(m_proc, m_currentBlock, m_info, m_instanceValue);
-}
-
-
</del><span class="cx"> auto B3IRGenerator::addGrowMemory(ExpressionType delta, ExpressionType&amp; result) -&gt; PartialResult
</span><span class="cx"> {
</span><span class="cx">     int32_t (*growMemory) (ExecState*, int32_t) = [] (ExecState* exec, int32_t delta) -&gt; int32_t {
</span><span class="lines">@@ -389,7 +394,6 @@
</span><span class="cx"> 
</span><span class="cx">         JSWebAssemblyInstance* instance = vm.topJSWebAssemblyInstance;
</span><span class="cx">         JSWebAssemblyMemory* wasmMemory = instance-&gt;memory();
</span><del>-        RELEASE_ASSERT(wasmMemory); // This would fail validation otherwise.
</del><span class="cx"> 
</span><span class="cx">         if (delta &lt; 0)
</span><span class="cx">             return -1;
</span><span class="lines">@@ -407,7 +411,7 @@
</span><span class="cx">         m_currentBlock-&gt;appendNew&lt;ConstPtrValue&gt;(m_proc, Origin(), bitwise_cast&lt;void*&gt;(growMemory)),
</span><span class="cx">         m_currentBlock-&gt;appendNew&lt;B3::Value&gt;(m_proc, B3::FramePointer, Origin()), delta);
</span><span class="cx"> 
</span><del>-    emitReloadPinnedRegisters();
</del><ins>+    restoreWebAssemblyGlobalState(m_vm, m_info.memory, m_instanceValue, m_proc, m_currentBlock);
</ins><span class="cx"> 
</span><span class="cx">     return { };
</span><span class="cx"> }
</span><span class="lines">@@ -414,14 +418,12 @@
</span><span class="cx"> 
</span><span class="cx"> auto B3IRGenerator::addCurrentMemory(ExpressionType&amp; result) -&gt; PartialResult
</span><span class="cx"> {
</span><del>-    Value* jsMemory = m_currentBlock-&gt;appendNew&lt;MemoryValue&gt;(m_proc, Load, pointerType(), Origin(), m_instanceValue, JSWebAssemblyInstance::offsetOfMemory());
-    Value* wasmMemory = m_currentBlock-&gt;appendNew&lt;MemoryValue&gt;(m_proc, Load, pointerType(), Origin(), jsMemory, JSWebAssemblyMemory::offsetOfMemory());
-    Value* size = m_currentBlock-&gt;appendNew&lt;MemoryValue&gt;(m_proc, Load, B3::Int64, Origin(), wasmMemory, Memory::offsetOfSize());
</del><ins>+    auto memoryValue = getMemoryBaseAndSize(m_vm, m_instanceValue, m_proc, m_currentBlock);
</ins><span class="cx"> 
</span><span class="cx">     constexpr uint32_t shiftValue = 16;
</span><span class="cx">     static_assert(PageCount::pageSize == 1 &lt;&lt; shiftValue, &quot;This must hold for the code below to be correct.&quot;);
</span><span class="cx">     Value* numPages = m_currentBlock-&gt;appendNew&lt;Value&gt;(m_proc, ZShr, Origin(),
</span><del>-        size, m_currentBlock-&gt;appendNew&lt;Const32Value&gt;(m_proc, Origin(), shiftValue));
</del><ins>+        memoryValue.size, m_currentBlock-&gt;appendNew&lt;Const32Value&gt;(m_proc, Origin(), shiftValue));
</ins><span class="cx"> 
</span><span class="cx">     result = m_currentBlock-&gt;appendNew&lt;Value&gt;(m_proc, Trunc, Origin(), numPages);
</span><span class="cx"> 
</span><span class="lines">@@ -832,27 +834,76 @@
</span><span class="cx">     ASSERT(signature-&gt;argumentCount() == args.size());
</span><span class="cx"> 
</span><span class="cx">     Type returnType = signature-&gt;returnType();
</span><ins>+    Vector&lt;UnlinkedWasmToWasmCall&gt;* unlinkedWasmToWasmCalls = &amp;m_unlinkedWasmToWasmCalls;
</ins><span class="cx"> 
</span><del>-    result = wasmCallingConvention().setupCall(m_proc, m_currentBlock, Origin(), args, toB3Type(returnType),
-        [&amp;] (PatchpointValue* patchpoint) {
-            patchpoint-&gt;effects.writesPinned = true;
-            patchpoint-&gt;effects.readsPinned = true;
</del><ins>+    if (m_info.isImportedFunctionFromFunctionIndexSpace(functionIndex)) {
+        // FIXME imports can be linked here, instead of generating a patchpoint, because all import stubs are generated before B3 compilation starts. https://bugs.webkit.org/show_bug.cgi?id=166462
+        Value* functionImport = m_currentBlock-&gt;appendNew&lt;MemoryValue&gt;(m_proc, Load, pointerType(), Origin(), m_instanceValue, JSWebAssemblyInstance::offsetOfImportFunction(functionIndex));
+        Value* jsTypeOfImport = m_currentBlock-&gt;appendNew&lt;MemoryValue&gt;(m_proc, Load8Z, Origin(), functionImport, JSCell::typeInfoTypeOffset());
+        Value* isWasmCall = m_currentBlock-&gt;appendNew&lt;Value&gt;(m_proc, Equal, Origin(), jsTypeOfImport, m_currentBlock-&gt;appendNew&lt;Const32Value&gt;(m_proc, Origin(), WebAssemblyFunctionType));
</ins><span class="cx"> 
</span><del>-            Vector&lt;UnlinkedWasmToWasmCall&gt;* unlinkedWasmToWasmCalls = &amp;m_unlinkedWasmToWasmCalls;
-            patchpoint-&gt;setGenerator([unlinkedWasmToWasmCalls, functionIndex] (CCallHelpers&amp; jit, const B3::StackmapGenerationParams&amp;) {
-                AllowMacroScratchRegisterUsage allowScratch(jit);
</del><ins>+        BasicBlock* isWasmBlock = m_proc.addBlock();
+        BasicBlock* isJSBlock = m_proc.addBlock();
+        BasicBlock* continuation = m_proc.addBlock();
+        m_currentBlock-&gt;appendNewControlValue(m_proc, B3::Branch, Origin(), isWasmCall, FrequentedBlock(isWasmBlock), FrequentedBlock(isJSBlock));
</ins><span class="cx"> 
</span><del>-                CCallHelpers::Call call = jit.call();
</del><ins>+        Value* wasmCallResult = wasmCallingConvention().setupCall(m_proc, isWasmBlock, Origin(), args, toB3Type(returnType),
+            [&amp;] (PatchpointValue* patchpoint) {
+                patchpoint-&gt;effects.writesPinned = true;
+                patchpoint-&gt;effects.readsPinned = true;
+                patchpoint-&gt;setGenerator([unlinkedWasmToWasmCalls, functionIndex] (CCallHelpers&amp; jit, const B3::StackmapGenerationParams&amp;) {
+                    AllowMacroScratchRegisterUsage allowScratch(jit);
+                    CCallHelpers::Call call = jit.call();
+                    jit.addLinkTask([unlinkedWasmToWasmCalls, call, functionIndex] (LinkBuffer&amp; linkBuffer) {
+                        unlinkedWasmToWasmCalls-&gt;append({ linkBuffer.locationOf(call), functionIndex, UnlinkedWasmToWasmCall::Target::ToWasm });
+                    });
+                });
+            });
+        UpsilonValue* wasmCallResultUpsilon = returnType == Void ? nullptr : isWasmBlock-&gt;appendNew&lt;UpsilonValue&gt;(m_proc, Origin(), wasmCallResult);
+        isWasmBlock-&gt;appendNewControlValue(m_proc, Jump, Origin(), continuation);
</ins><span class="cx"> 
</span><del>-                jit.addLinkTask([unlinkedWasmToWasmCalls, call, functionIndex] (LinkBuffer&amp; linkBuffer) {
-                    unlinkedWasmToWasmCalls-&gt;append({ linkBuffer.locationOf(call), functionIndex });
</del><ins>+        Value* jsCallResult = wasmCallingConvention().setupCall(m_proc, isJSBlock, Origin(), args, toB3Type(returnType),
+            [&amp;] (PatchpointValue* patchpoint) {
+                patchpoint-&gt;effects.writesPinned = true;
+                patchpoint-&gt;effects.readsPinned = true;
+                patchpoint-&gt;setGenerator([unlinkedWasmToWasmCalls, functionIndex] (CCallHelpers&amp; jit, const B3::StackmapGenerationParams&amp;) {
+                    AllowMacroScratchRegisterUsage allowScratch(jit);
+                    CCallHelpers::Call call = jit.call();
+                    jit.addLinkTask([unlinkedWasmToWasmCalls, call, functionIndex] (LinkBuffer&amp; linkBuffer) {
+                        unlinkedWasmToWasmCalls-&gt;append({ linkBuffer.locationOf(call), functionIndex, UnlinkedWasmToWasmCall::Target::ToJs });
+                    });
</ins><span class="cx">                 });
</span><span class="cx">             });
</span><del>-        });
</del><ins>+        UpsilonValue* jsCallResultUpsilon = returnType == Void ? nullptr : isJSBlock-&gt;appendNew&lt;UpsilonValue&gt;(m_proc, Origin(), jsCallResult);
+        isJSBlock-&gt;appendNewControlValue(m_proc, Jump, Origin(), continuation);
</ins><span class="cx"> 
</span><del>-    if (functionIndex &lt; m_info.importFunctionCount())
-        emitReloadPinnedRegisters();
</del><ins>+        m_currentBlock = continuation;
</ins><span class="cx"> 
</span><ins>+        if (returnType == Void)
+            result = nullptr;
+        else {
+            result = continuation-&gt;appendNew&lt;Value&gt;(m_proc, Phi, toB3Type(returnType), Origin());
+            wasmCallResultUpsilon-&gt;setPhi(result);
+            jsCallResultUpsilon-&gt;setPhi(result);
+        }
+
+        // The call could have been to another WebAssembly instance, and / or could have modified our Memory.
+        restoreWebAssemblyGlobalState(m_vm, m_info.memory, m_instanceValue, m_proc, continuation);
+    } else {
+        result = wasmCallingConvention().setupCall(m_proc, m_currentBlock, Origin(), args, toB3Type(returnType),
+            [&amp;] (PatchpointValue* patchpoint) {
+                patchpoint-&gt;effects.writesPinned = true;
+                patchpoint-&gt;effects.readsPinned = true;
+                patchpoint-&gt;setGenerator([unlinkedWasmToWasmCalls, functionIndex] (CCallHelpers&amp; jit, const B3::StackmapGenerationParams&amp;) {
+                    AllowMacroScratchRegisterUsage allowScratch(jit);
+                    CCallHelpers::Call call = jit.call();
+                    jit.addLinkTask([unlinkedWasmToWasmCalls, call, functionIndex] (LinkBuffer&amp; linkBuffer) {
+                        unlinkedWasmToWasmCalls-&gt;append({ linkBuffer.locationOf(call), functionIndex, UnlinkedWasmToWasmCall::Target::ToWasm });
+                    });
+                });
+            });
+    }
+
</ins><span class="cx">     return { };
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -929,7 +980,8 @@
</span><span class="cx">             });
</span><span class="cx">         });
</span><span class="cx"> 
</span><del>-    emitReloadPinnedRegisters();
</del><ins>+    // The call could have been to another WebAssembly instance, and / or could have modified our Memory.
+    restoreWebAssemblyGlobalState(m_vm, m_info.memory, m_instanceValue, m_proc, m_currentBlock);
</ins><span class="cx"> 
</span><span class="cx">     return { };
</span><span class="cx"> }
</span><span class="lines">@@ -998,12 +1050,10 @@
</span><span class="cx">         });
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    // Move memory values to the approriate places, if needed.
-    {
-        Value* instance = block-&gt;appendNew&lt;MemoryValue&gt;(proc, Load, pointerType(), Origin(),
-            block-&gt;appendNew&lt;ConstPtrValue&gt;(proc, Origin(), &amp;vm.topJSWebAssemblyInstance));
-        reloadPinnedRegisters(proc, block, info, instance);
-    }
</del><ins>+    // FIXME The instance is currently set by the C++ code in WebAssemblyFunction::call. We shouldn't go through the extra C++ hoop. https://bugs.webkit.org/show_bug.cgi?id=166486
+    Value* instance = block-&gt;appendNew&lt;MemoryValue&gt;(proc, Load, pointerType(), Origin(),
+        block-&gt;appendNew&lt;ConstPtrValue&gt;(proc, Origin(), &amp;vm.topJSWebAssemblyInstance));
+    restoreWebAssemblyGlobalState(vm, info.memory, instance, proc, block);
</ins><span class="cx"> 
</span><span class="cx">     // Get our arguments.
</span><span class="cx">     Vector&lt;Value*&gt; arguments;
</span><span class="lines">@@ -1046,7 +1096,7 @@
</span><span class="cx">     function.jsToWasmEntrypoint.calleeSaveRegisters = proc.calleeSaveRegisters();
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-Expected&lt;std::unique_ptr&lt;WasmInternalFunction&gt;, String&gt; parseAndCompile(VM&amp; vm, CompilationContext&amp; compilationContext, const uint8_t* functionStart, size_t functionLength, const Signature* signature, Vector&lt;UnlinkedWasmToWasmCall&gt;&amp; unlinkedWasmToWasmCalls, const ImmutableFunctionIndexSpace&amp; functionIndexSpace, const ModuleInformation&amp; info, unsigned optLevel)
</del><ins>+Expected&lt;std::unique_ptr&lt;WasmInternalFunction&gt;, String&gt; parseAndCompile(VM&amp; vm, CompilationContext&amp; compilationContext, const uint8_t* functionStart, size_t functionLength, const Signature* signature, Vector&lt;UnlinkedWasmToWasmCall&gt;&amp; unlinkedWasmToWasmCalls, const ModuleInformation&amp; info, const Vector&lt;SignatureIndex&gt;&amp; moduleSignatureIndicesToUniquedSignatureIndices, unsigned optLevel)
</ins><span class="cx"> {
</span><span class="cx">     auto result = std::make_unique&lt;WasmInternalFunction&gt;();
</span><span class="cx"> 
</span><span class="lines">@@ -1054,8 +1104,8 @@
</span><span class="cx">     compilationContext.wasmEntrypointJIT = std::make_unique&lt;CCallHelpers&gt;(&amp;vm);
</span><span class="cx"> 
</span><span class="cx">     Procedure procedure;
</span><del>-    B3IRGenerator context(vm, info, procedure, result.get(), unlinkedWasmToWasmCalls, functionIndexSpace);
-    FunctionParser&lt;B3IRGenerator&gt; parser(&amp;vm, context, functionStart, functionLength, signature, functionIndexSpace, info);
</del><ins>+    B3IRGenerator context(vm, info, procedure, result.get(), unlinkedWasmToWasmCalls);
+    FunctionParser&lt;B3IRGenerator&gt; parser(&amp;vm, context, functionStart, functionLength, signature, info, moduleSignatureIndicesToUniquedSignatureIndices);
</ins><span class="cx">     WASM_FAIL_IF_HELPER_FAILS(parser.parse());
</span><span class="cx"> 
</span><span class="cx">     procedure.resetReachability();
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorewasmWasmB3IRGeneratorh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/wasm/WasmB3IRGenerator.h (210228 => 210229)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/wasm/WasmB3IRGenerator.h        2017-01-03 00:32:05 UTC (rev 210228)
+++ trunk/Source/JavaScriptCore/wasm/WasmB3IRGenerator.h        2017-01-03 01:57:40 UTC (rev 210229)
</span><span class="lines">@@ -47,7 +47,7 @@
</span><span class="cx">     CCallHelpers::Call jsEntrypointToWasmEntrypointCall;
</span><span class="cx"> };
</span><span class="cx"> 
</span><del>-Expected&lt;std::unique_ptr&lt;WasmInternalFunction&gt;, String&gt; parseAndCompile(VM&amp;, CompilationContext&amp;, const uint8_t*, size_t, const Signature*, Vector&lt;UnlinkedWasmToWasmCall&gt;&amp;, const ImmutableFunctionIndexSpace&amp;, const ModuleInformation&amp;, unsigned optLevel = 1);
</del><ins>+Expected&lt;std::unique_ptr&lt;WasmInternalFunction&gt;, String&gt; parseAndCompile(VM&amp;, CompilationContext&amp;, const uint8_t*, size_t, const Signature*, Vector&lt;UnlinkedWasmToWasmCall&gt;&amp;, const ModuleInformation&amp;, const Vector&lt;SignatureIndex&gt;&amp;, unsigned optLevel = 1);
</ins><span class="cx"> 
</span><span class="cx"> } } // namespace JSC::Wasm
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorewasmWasmBindingcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/wasm/WasmBinding.cpp (210228 => 210229)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/wasm/WasmBinding.cpp        2017-01-03 00:32:05 UTC (rev 210228)
+++ trunk/Source/JavaScriptCore/wasm/WasmBinding.cpp        2017-01-03 01:57:40 UTC (rev 210229)
</span><span class="lines">@@ -36,13 +36,21 @@
</span><span class="cx"> 
</span><span class="cx"> namespace JSC { namespace Wasm {
</span><span class="cx"> 
</span><del>-WasmToJSStub importStubGenerator(VM* vm, Bag&lt;CallLinkInfo&gt;&amp; callLinkInfos, SignatureIndex signatureIndex, unsigned importIndex)
</del><ins>+typedef AssemblyHelpers JIT;
+
+static void materializeImportJSCell(VM* vm, JIT&amp; jit, unsigned importIndex, GPRReg result)
</ins><span class="cx"> {
</span><ins>+    // We're calling out of the current WebAssembly.Instance, which is identified on VM. That Instance has a list of all its import functions.
+    jit.loadPtr(&amp;vm-&gt;topJSWebAssemblyInstance, result);
+    jit.loadPtr(JIT::Address(result, JSWebAssemblyInstance::offsetOfImportFunction(importIndex)), result);
+}
+
+static MacroAssemblerCodeRef wasmToJs(VM* vm, Bag&lt;CallLinkInfo&gt;&amp; callLinkInfos, SignatureIndex signatureIndex, unsigned importIndex)
+{
</ins><span class="cx">     const WasmCallingConvention&amp; wasmCC = wasmCallingConvention();
</span><span class="cx">     const JSCCallingConvention&amp; jsCC = jscCallingConvention();
</span><span class="cx">     const Signature* signature = SignatureInformation::get(vm, signatureIndex);
</span><span class="cx">     unsigned argCount = signature-&gt;argumentCount();
</span><del>-    typedef AssemblyHelpers JIT;
</del><span class="cx">     JIT jit(vm, nullptr);
</span><span class="cx"> 
</span><span class="cx">     // Below, we assume that the JS calling convention is always on the stack.
</span><span class="lines">@@ -138,9 +146,7 @@
</span><span class="cx">     GPRReg importJSCellGPRReg = GPRInfo::regT0; // Callee needs to be in regT0 for slow path below.
</span><span class="cx">     ASSERT(!wasmCC.m_calleeSaveRegisters.get(importJSCellGPRReg));
</span><span class="cx"> 
</span><del>-    // Each JS -&gt; wasm entry sets the WebAssembly.Instance whose export is being called. We're calling out of this Instance, and can therefore figure out the import being called.
-    jit.loadPtr(&amp;vm-&gt;topJSWebAssemblyInstance, importJSCellGPRReg);
-    jit.loadPtr(JIT::Address(importJSCellGPRReg, JSWebAssemblyInstance::offsetOfImportFunction(importIndex)), importJSCellGPRReg);
</del><ins>+    materializeImportJSCell(vm, jit, importIndex, importJSCellGPRReg);
</ins><span class="cx"> 
</span><span class="cx">     uint64_t thisArgument = ValueUndefined; // FIXME what does the WebAssembly spec say this should be? https://bugs.webkit.org/show_bug.cgi?id=165471
</span><span class="cx">     jit.store64(importJSCellGPRReg, calleeFrame.withOffset(CallFrameSlot::callee * static_cast&lt;int&gt;(sizeof(Register))));
</span><span class="lines">@@ -231,9 +237,58 @@
</span><span class="cx">     CodeLocationLabel hotPathBegin(patchBuffer.locationOf(targetToCheck));
</span><span class="cx">     CodeLocationNearCall hotPathOther = patchBuffer.locationOfNearCall(fastCall);
</span><span class="cx">     callLinkInfo-&gt;setCallLocations(callReturnLocation, hotPathBegin, hotPathOther);
</span><del>-    return FINALIZE_CODE(patchBuffer, (&quot;WebAssembly import[%i] stub for signature %i&quot;, importIndex, signatureIndex));
</del><ins>+    String signatureDescription = SignatureInformation::get(vm, signatureIndex)-&gt;toString();
+    return FINALIZE_CODE(patchBuffer, (&quot;WebAssembly-&gt;JavaScript import[%i] %s&quot;, importIndex, signatureDescription.ascii().data()));
</ins><span class="cx"> }
</span><span class="cx"> 
</span><ins>+static MacroAssemblerCodeRef wasmToWasm(VM* vm, unsigned importIndex)
+{
+    const PinnedRegisterInfo&amp; pinnedRegs = PinnedRegisterInfo::get();
+    JIT jit(vm, nullptr);
+
+    GPRReg scratch = GPRInfo::nonPreservedNonArgumentGPR;
+
+    // B3's call codegen ensures that the JSCell is a WebAssemblyFunction.
+    materializeImportJSCell(vm, jit, importIndex, scratch);
+
+    // Get the callee's WebAssembly.Instance and set it as vm.topJSWebAssemblyInstance. The caller will take care of restoring its own Instance.
+    GPRReg baseMemory = pinnedRegs.baseMemoryPointer;
+    ASSERT(baseMemory != scratch);
+    jit.loadPtr(JIT::Address(scratch, WebAssemblyFunction::offsetOfInstance()), baseMemory); // Instance*.
+    jit.storePtr(baseMemory, &amp;vm-&gt;topJSWebAssemblyInstance);
+
+    // FIXME the following code assumes that all WebAssembly.Instance have the same pinned registers. https://bugs.webkit.org/show_bug.cgi?id=162952
+    // Set up the callee's baseMemory register as well as the memory size registers.
+    jit.loadPtr(JIT::Address(baseMemory, JSWebAssemblyInstance::offsetOfMemory()), baseMemory); // JSWebAssemblyMemory*.
+    const auto&amp; sizeRegs = pinnedRegs.sizeRegisters;
+    ASSERT(sizeRegs.size() &gt;= 1);
+    ASSERT(sizeRegs[0].sizeRegister != baseMemory);
+    ASSERT(sizeRegs[0].sizeRegister != scratch);
+    ASSERT(!sizeRegs[0].sizeOffset); // The following code assumes we start at 0, and calculates subsequent size registers relative to 0.
+    jit.loadPtr(JIT::Address(baseMemory, JSWebAssemblyMemory::offsetOfSize()), sizeRegs[0].sizeRegister); // Memory size.
+    jit.loadPtr(JIT::Address(baseMemory, JSWebAssemblyMemory::offsetOfMemory()), baseMemory); // WasmMemory::void*.
+    for (unsigned i = 1; i &lt; sizeRegs.size(); ++i) {
+        ASSERT(sizeRegs[i].sizeRegister != baseMemory);
+        ASSERT(sizeRegs[i].sizeRegister != scratch);
+        jit.add64(JIT::TrustedImm32(-sizeRegs[i].sizeOffset), sizeRegs[0].sizeRegister, sizeRegs[i].sizeRegister);
+    }
+
+    // Tail call into the callee WebAssembly function.
+    jit.loadPtr(JIT::Address(scratch, WebAssemblyFunction::offsetOfWasmEntryPointCode()), scratch);
+    jit.jump(scratch);
+
+    LinkBuffer patchBuffer(*vm, jit, GLOBAL_THUNK_ID);
+    return FINALIZE_CODE(patchBuffer, (&quot;WebAssembly-&gt;WebAssembly import[%i]&quot;, importIndex));
+}
+
+WasmExitStubs exitStubGenerator(VM* vm, Bag&lt;CallLinkInfo&gt;&amp; callLinkInfos, SignatureIndex signatureIndex, unsigned importIndex)
+{
+    WasmExitStubs stubs;
+    stubs.wasmToJs = wasmToJs(vm, callLinkInfos, signatureIndex, importIndex);
+    stubs.wasmToWasm = wasmToWasm(vm, importIndex);
+    return stubs;
+}
+
</ins><span class="cx"> } } // namespace JSC::Wasm
</span><span class="cx"> 
</span><span class="cx"> #endif // ENABLE(WEBASSEMBLY)
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorewasmWasmBindingh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/wasm/WasmBinding.h (210228 => 210229)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/wasm/WasmBinding.h        2017-01-03 00:32:05 UTC (rev 210228)
+++ trunk/Source/JavaScriptCore/wasm/WasmBinding.h        2017-01-03 01:57:40 UTC (rev 210229)
</span><span class="lines">@@ -38,7 +38,7 @@
</span><span class="cx"> 
</span><span class="cx"> namespace Wasm {
</span><span class="cx"> 
</span><del>-WasmToJSStub importStubGenerator(VM*, Bag&lt;CallLinkInfo&gt;&amp;, SignatureIndex, unsigned);
</del><ins>+WasmExitStubs exitStubGenerator(VM*, Bag&lt;CallLinkInfo&gt;&amp;, SignatureIndex, unsigned);
</ins><span class="cx"> 
</span><span class="cx"> } } // namespace JSC::Wasm
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorewasmWasmFormath"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/wasm/WasmFormat.h (210228 => 210229)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/wasm/WasmFormat.h        2017-01-03 00:32:05 UTC (rev 210228)
+++ trunk/Source/JavaScriptCore/wasm/WasmFormat.h        2017-01-03 01:57:40 UTC (rev 210229)
</span><span class="lines">@@ -222,7 +222,6 @@
</span><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> struct ModuleInformation {
</span><del>-    Vector&lt;SignatureIndex&gt; signatureIndices;
</del><span class="cx">     Vector&lt;Import&gt; imports;
</span><span class="cx">     Vector&lt;SignatureIndex&gt; importFunctionSignatureIndices;
</span><span class="cx">     Vector&lt;SignatureIndex&gt; internalFunctionSignatureIndices;
</span><span class="lines">@@ -236,6 +235,18 @@
</span><span class="cx">     TableInformation tableInformation;
</span><span class="cx">     Vector&lt;Global&gt; globals;
</span><span class="cx">     unsigned firstInternalGlobal { 0 };
</span><ins>+    size_t functionIndexSpaceSize() const { return importFunctionSignatureIndices.size() + internalFunctionSignatureIndices.size(); }
+    bool isImportedFunctionFromFunctionIndexSpace(size_t functionIndex) const
+    {
+        ASSERT(functionIndex &lt; functionIndexSpaceSize());
+        return functionIndex &lt; importFunctionSignatureIndices.size();
+    }
+    SignatureIndex signatureIndexFromFunctionIndexSpace(size_t functionIndex) const
+    {
+        return isImportedFunctionFromFunctionIndexSpace(functionIndex)
+            ? importFunctionSignatureIndices[functionIndex]
+            : internalFunctionSignatureIndices[functionIndex - importFunctionSignatureIndices.size()];
+    }
</ins><span class="cx"> 
</span><span class="cx">     uint32_t importFunctionCount() const { return importFunctionSignatureIndices.size(); }
</span><span class="cx">     bool hasMemory() const { return !!memory; }
</span><span class="lines">@@ -246,6 +257,10 @@
</span><span class="cx"> struct UnlinkedWasmToWasmCall {
</span><span class="cx">     CodeLocationCall callLocation;
</span><span class="cx">     size_t functionIndex;
</span><ins>+    enum class Target : uint8_t {
+        ToJs,
+        ToWasm,
+    } target;
</ins><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> struct Entrypoint {
</span><span class="lines">@@ -261,7 +276,10 @@
</span><span class="cx">     Entrypoint jsToWasmEntrypoint;
</span><span class="cx"> };
</span><span class="cx"> 
</span><del>-typedef MacroAssemblerCodeRef WasmToJSStub;
</del><ins>+struct WasmExitStubs {
+    MacroAssemblerCodeRef wasmToJs;
+    MacroAssemblerCodeRef wasmToWasm;
+};
</ins><span class="cx"> 
</span><span class="cx"> // WebAssembly direct calls and call_indirect use indices into &quot;function index space&quot;. This space starts with all imports, and then all internal functions.
</span><span class="cx"> // CallableFunction and FunctionIndexSpace are only meant as fast lookup tables for these opcodes, and do not own code.
</span><span class="lines">@@ -280,12 +298,6 @@
</span><span class="cx"> };
</span><span class="cx"> typedef Vector&lt;CallableFunction&gt; FunctionIndexSpace;
</span><span class="cx"> 
</span><del>-
-struct ImmutableFunctionIndexSpace {
-    MallocPtr&lt;CallableFunction&gt; buffer;
-    size_t size;
-};
-
</del><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 (210228 => 210229)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/wasm/WasmFunctionParser.h        2017-01-03 00:32:05 UTC (rev 210228)
+++ trunk/Source/JavaScriptCore/wasm/WasmFunctionParser.h        2017-01-03 01:57:40 UTC (rev 210229)
</span><span class="lines">@@ -46,7 +46,7 @@
</span><span class="cx">     typedef typename Context::ControlType ControlType;
</span><span class="cx">     typedef typename Context::ExpressionList ExpressionList;
</span><span class="cx"> 
</span><del>-    FunctionParser(VM*, Context&amp;, const uint8_t* functionStart, size_t functionLength, const Signature*, const ImmutableFunctionIndexSpace&amp;, const ModuleInformation&amp;);
</del><ins>+    FunctionParser(VM*, Context&amp;, const uint8_t* functionStart, size_t functionLength, const Signature*, const ModuleInformation&amp;, const Vector&lt;SignatureIndex&gt;&amp;);
</ins><span class="cx"> 
</span><span class="cx">     Result WARN_UNUSED_RETURN parse();
</span><span class="cx"> 
</span><span class="lines">@@ -82,18 +82,18 @@
</span><span class="cx">     ExpressionList m_expressionStack;
</span><span class="cx">     Vector&lt;ControlEntry&gt; m_controlStack;
</span><span class="cx">     const Signature* m_signature;
</span><del>-    const ImmutableFunctionIndexSpace&amp; m_functionIndexSpace;
</del><span class="cx">     const ModuleInformation&amp; m_info;
</span><ins>+    const Vector&lt;SignatureIndex&gt;&amp; m_moduleSignatureIndicesToUniquedSignatureIndices;
</ins><span class="cx">     unsigned m_unreachableBlocks { 0 };
</span><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> template&lt;typename Context&gt;
</span><del>-FunctionParser&lt;Context&gt;::FunctionParser(VM* vm, Context&amp; context, const uint8_t* functionStart, size_t functionLength, const Signature* signature, const ImmutableFunctionIndexSpace&amp; functionIndexSpace, const ModuleInformation&amp; info)
</del><ins>+FunctionParser&lt;Context&gt;::FunctionParser(VM* vm, Context&amp; context, const uint8_t* functionStart, size_t functionLength, const Signature* signature, const ModuleInformation&amp; info, const Vector&lt;SignatureIndex&gt;&amp; moduleSignatureIndicesToUniquedSignatureIndices)
</ins><span class="cx">     : Parser(vm, functionStart, functionLength)
</span><span class="cx">     , m_context(context)
</span><span class="cx">     , m_signature(signature)
</span><del>-    , m_functionIndexSpace(functionIndexSpace)
</del><span class="cx">     , m_info(info)
</span><ins>+    , m_moduleSignatureIndicesToUniquedSignatureIndices(moduleSignatureIndicesToUniquedSignatureIndices)
</ins><span class="cx"> {
</span><span class="cx">     if (verbose)
</span><span class="cx">         dataLogLn(&quot;Parsing function starting at: &quot;, (uintptr_t)functionStart, &quot; of length: &quot;, functionLength);
</span><span class="lines">@@ -308,9 +308,9 @@
</span><span class="cx">     case Call: {
</span><span class="cx">         uint32_t functionIndex;
</span><span class="cx">         WASM_PARSER_FAIL_IF(!parseVarUInt32(functionIndex), &quot;can't parse call's function index&quot;);
</span><del>-        WASM_PARSER_FAIL_IF(functionIndex &gt;= m_functionIndexSpace.size, &quot;call function index &quot;, functionIndex, &quot; exceeds function index space &quot;, m_functionIndexSpace.size);
</del><ins>+        WASM_PARSER_FAIL_IF(functionIndex &gt;= m_info.functionIndexSpaceSize(), &quot;call function index &quot;, functionIndex, &quot; exceeds function index space &quot;, m_info.functionIndexSpaceSize());
</ins><span class="cx"> 
</span><del>-        SignatureIndex calleeSignatureIndex = m_functionIndexSpace.buffer.get()[functionIndex].signatureIndex;
</del><ins>+        SignatureIndex calleeSignatureIndex = m_info.signatureIndexFromFunctionIndexSpace(functionIndex);
</ins><span class="cx">         const Signature* calleeSignature = SignatureInformation::get(m_vm, calleeSignatureIndex);
</span><span class="cx">         WASM_PARSER_FAIL_IF(calleeSignature-&gt;argumentCount() &gt; m_expressionStack.size(), &quot;call function index &quot;, functionIndex, &quot; has &quot;, calleeSignature-&gt;argumentCount(), &quot; arguments, but the expression stack currently holds &quot;, m_expressionStack.size(), &quot; values&quot;);
</span><span class="cx"> 
</span><span class="lines">@@ -337,9 +337,9 @@
</span><span class="cx">         WASM_PARSER_FAIL_IF(!parseVarUInt32(signatureIndex), &quot;can't get call_indirect's signature index&quot;);
</span><span class="cx">         WASM_PARSER_FAIL_IF(!parseVarUInt1(reserved), &quot;can't get call_indirect's reserved byte&quot;);
</span><span class="cx">         WASM_PARSER_FAIL_IF(reserved, &quot;call_indirect's 'reserved' varuint1 must be 0x0&quot;);
</span><del>-        WASM_PARSER_FAIL_IF(m_info.signatureIndices.size() &lt;= signatureIndex, &quot;call_indirect's signature index &quot;, signatureIndex, &quot; exceeds known signatures &quot;, m_info.signatureIndices.size());
</del><ins>+        WASM_PARSER_FAIL_IF(m_moduleSignatureIndicesToUniquedSignatureIndices.size() &lt;= signatureIndex, &quot;call_indirect's signature index &quot;, signatureIndex, &quot; exceeds known signatures &quot;, m_moduleSignatureIndicesToUniquedSignatureIndices.size());
</ins><span class="cx"> 
</span><del>-        SignatureIndex calleeSignatureIndex = m_info.signatureIndices[signatureIndex];
</del><ins>+        SignatureIndex calleeSignatureIndex = m_moduleSignatureIndicesToUniquedSignatureIndices[signatureIndex];
</ins><span class="cx">         const Signature* calleeSignature = SignatureInformation::get(m_vm, calleeSignatureIndex);
</span><span class="cx">         size_t argumentCount = calleeSignature-&gt;argumentCount() + 1; // Add the callee's index.
</span><span class="cx">         WASM_PARSER_FAIL_IF(argumentCount &gt; m_expressionStack.size(), &quot;call_indirect expects &quot;, argumentCount, &quot; arguments, but the expression stack currently holds &quot;, m_expressionStack.size(), &quot; values&quot;);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorewasmWasmMemorycpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/wasm/WasmMemory.cpp (210228 => 210229)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/wasm/WasmMemory.cpp        2017-01-03 00:32:05 UTC (rev 210228)
+++ trunk/Source/JavaScriptCore/wasm/WasmMemory.cpp        2017-01-03 01:57:40 UTC (rev 210229)
</span><span class="lines">@@ -28,15 +28,39 @@
</span><span class="cx"> 
</span><span class="cx"> #if ENABLE(WEBASSEMBLY)
</span><span class="cx"> 
</span><ins>+#include &lt;wtf/HexNumber.h&gt;
+#include &lt;wtf/PrintStream.h&gt;
+#include &lt;wtf/text/WTFString.h&gt;
+
</ins><span class="cx"> namespace JSC { namespace Wasm {
</span><span class="cx"> 
</span><ins>+namespace {
+const bool verbose = false;
+}
+
+void Memory::dump(PrintStream&amp; out) const
+{
+    String memoryHex;
+    WTF::appendUnsigned64AsHex((uint64_t)(uintptr_t)m_memory, memoryHex);
+    out.print(&quot;Memory at 0x&quot;, memoryHex, &quot;, size &quot;, m_size, &quot;B capacity &quot;, m_mappedCapacity, &quot;B, initial &quot;, m_initial, &quot; maximum &quot;, m_maximum, &quot; mode &quot;, makeString(m_mode));
+}
+
+const char* Memory::makeString(Mode mode) const
+{
+    switch (mode) {
+    case Mode::BoundsChecking: return &quot;BoundsChecking&quot;;
+    }
+    RELEASE_ASSERT_NOT_REACHED();
+    return &quot;&quot;;
+}
+
</ins><span class="cx"> static_assert(sizeof(uint64_t) == sizeof(size_t), &quot;We rely on allowing the maximum size of Memory we map to be 2^32 which is larger than fits in a 32-bit integer that we'd pass to mprotect if this didn't hold.&quot;);
</span><span class="cx"> 
</span><span class="cx"> Memory::Memory(PageCount initial, PageCount maximum, bool&amp; failed)
</span><del>-    : m_mode(Mode::BoundsChecking)
</del><ins>+    : m_size(initial.bytes())
</ins><span class="cx">     , m_initial(initial)
</span><span class="cx">     , m_maximum(maximum)
</span><del>-    , m_size(initial.bytes())
</del><ins>+    , m_mode(Mode::BoundsChecking)
</ins><span class="cx">     // FIXME: If we add signal based bounds checking then we need extra space for overflow on load.
</span><span class="cx">     // see: https://bugs.webkit.org/show_bug.cgi?id=162693
</span><span class="cx"> {
</span><span class="lines">@@ -46,9 +70,11 @@
</span><span class="cx">     if (!m_mappedCapacity) {
</span><span class="cx">         // This means we specified a zero as maximum (which means we also have zero as initial size).
</span><span class="cx">         RELEASE_ASSERT(m_size == 0);
</span><ins>+        m_memory = nullptr;
</ins><span class="cx">         m_mappedCapacity = 0;
</span><del>-        m_memory = nullptr;
</del><span class="cx">         failed = false;
</span><ins>+        if (verbose)
+            dataLogLn(&quot;Memory::Memory allocating nothing &quot;, *this);
</ins><span class="cx">         return;
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="lines">@@ -56,15 +82,21 @@
</span><span class="cx">     void* result = Options::simulateWebAssemblyLowMemory() ? MAP_FAILED : mmap(nullptr, m_mappedCapacity, PROT_NONE, MAP_PRIVATE | MAP_ANON, -1, 0);
</span><span class="cx">     if (result == MAP_FAILED) {
</span><span class="cx">         // Try again with a different number.
</span><ins>+        if (verbose)
+            dataLogLn(&quot;Memory::Memory mmap failed once for capacity, trying again&quot;, *this);
</ins><span class="cx">         m_mappedCapacity = m_size;
</span><span class="cx">         if (!m_mappedCapacity) {
</span><span class="cx">             m_memory = nullptr;
</span><span class="cx">             failed = false;
</span><ins>+            if (verbose)
+                dataLogLn(&quot;Memory::Memory mmap not trying again because size is zero &quot;, *this);
</ins><span class="cx">             return;
</span><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         result = mmap(nullptr, m_mappedCapacity, PROT_NONE, MAP_PRIVATE | MAP_ANON, -1, 0);
</span><span class="cx">         if (result == MAP_FAILED) {
</span><ins>+            if (verbose)
+                dataLogLn(&quot;Memory::Memory mmap failed twice &quot;, *this);
</ins><span class="cx">             failed = true;
</span><span class="cx">             return;
</span><span class="cx">         }
</span><span class="lines">@@ -78,12 +110,27 @@
</span><span class="cx"> 
</span><span class="cx">     m_memory = result;
</span><span class="cx">     failed = false;
</span><ins>+    if (verbose)
+        dataLogLn(&quot;Memory::Memory mmap succeeded &quot;, *this);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><ins>+Memory::~Memory()
+{
+    if (verbose)
+        dataLogLn(&quot;Memory::~Memory &quot;, *this);
+    if (m_memory) {
+        if (munmap(m_memory, m_mappedCapacity))
+            CRASH();
+    }
+}
+
</ins><span class="cx"> bool Memory::grow(PageCount newSize)
</span><span class="cx"> {
</span><span class="cx">     RELEASE_ASSERT(newSize &gt; PageCount::fromBytes(m_size));
</span><span class="cx"> 
</span><ins>+    if (verbose)
+        dataLogLn(&quot;Memory::grow to &quot;, newSize, &quot; from &quot;, *this);
+
</ins><span class="cx">     if (maximum() &amp;&amp; newSize &gt; maximum())
</span><span class="cx">         return false;
</span><span class="cx"> 
</span><span class="lines">@@ -93,6 +140,8 @@
</span><span class="cx">         bool success = !mprotect(static_cast&lt;uint8_t*&gt;(m_memory) + m_size, static_cast&lt;size_t&gt;(desiredSize - m_size), PROT_READ | PROT_WRITE);
</span><span class="cx">         RELEASE_ASSERT(success);
</span><span class="cx">         m_size = desiredSize;
</span><ins>+        if (verbose)
+            dataLogLn(&quot;Memory::grow in-place &quot;, *this);
</ins><span class="cx">         return true;
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="lines">@@ -110,6 +159,8 @@
</span><span class="cx">     m_mappedCapacity = desiredSize;
</span><span class="cx">     m_size = desiredSize;
</span><span class="cx"> 
</span><ins>+    if (verbose)
+        dataLogLn(&quot;Memory::grow &quot;, *this);
</ins><span class="cx">     return true;
</span><span class="cx"> }
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorewasmWasmMemoryh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/wasm/WasmMemory.h (210228 => 210229)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/wasm/WasmMemory.h        2017-01-03 00:32:05 UTC (rev 210228)
+++ trunk/Source/JavaScriptCore/wasm/WasmMemory.h        2017-01-03 01:57:40 UTC (rev 210229)
</span><span class="lines">@@ -30,7 +30,9 @@
</span><span class="cx"> #include &quot;WasmCallingConvention.h&quot;
</span><span class="cx"> #include &quot;WasmPageCount.h&quot;
</span><span class="cx"> 
</span><del>-#include &lt;wtf/Vector.h&gt;
</del><ins>+namespace WTF {
+class PrintStream;
+}
</ins><span class="cx"> 
</span><span class="cx"> namespace JSC { namespace Wasm {
</span><span class="cx"> 
</span><span class="lines">@@ -38,41 +40,50 @@
</span><span class="cx">     WTF_MAKE_NONCOPYABLE(Memory);
</span><span class="cx">     WTF_MAKE_FAST_ALLOCATED;
</span><span class="cx"> public:
</span><ins>+    void dump(WTF::PrintStream&amp;) const;
</ins><span class="cx"> 
</span><span class="cx">     // FIXME: We should support other modes. see: https://bugs.webkit.org/show_bug.cgi?id=162693
</span><span class="cx">     enum class Mode {
</span><span class="cx">         BoundsChecking
</span><span class="cx">     };
</span><ins>+    const char* makeString(Mode) const;
</ins><span class="cx"> 
</span><ins>+    Memory() = default;
</ins><span class="cx">     JS_EXPORT_PRIVATE Memory(PageCount initial, PageCount maximum, bool&amp; failed);
</span><del>-
-    ~Memory()
</del><ins>+    Memory(Memory&amp;&amp; other)
+        : m_memory(other.m_memory)
+        , m_size(other.m_size)
+        , m_initial(other.m_initial)
+        , m_maximum(other.m_maximum)
+        , m_mappedCapacity(other.m_mappedCapacity)
+        , m_mode(other.m_mode)
</ins><span class="cx">     {
</span><del>-        if (m_memory)
-            munmap(m_memory, m_mappedCapacity);
</del><ins>+        // Moving transfers ownership of the allocated memory.
+        other.m_memory = nullptr;
</ins><span class="cx">     }
</span><ins>+    ~Memory();
</ins><span class="cx"> 
</span><span class="cx">     void* memory() const { return m_memory; }
</span><span class="cx">     uint64_t size() const { return m_size; }
</span><span class="cx">     PageCount sizeInPages() const { return PageCount::fromBytes(m_size); }
</span><span class="cx"> 
</span><del>-    Mode mode() const { return m_mode; }
-
</del><span class="cx">     PageCount initial() const { return m_initial; }
</span><span class="cx">     PageCount maximum() const { return m_maximum; }
</span><span class="cx"> 
</span><ins>+    Mode mode() const { return m_mode; }
+
</ins><span class="cx">     bool grow(PageCount);
</span><span class="cx"> 
</span><ins>+    static ptrdiff_t offsetOfMemory() { return OBJECT_OFFSETOF(Memory, m_memory); }
</ins><span class="cx">     static ptrdiff_t offsetOfSize() { return OBJECT_OFFSETOF(Memory, m_size); }
</span><del>-    static ptrdiff_t offsetOfMemory() { return OBJECT_OFFSETOF(Memory, m_memory); }
</del><span class="cx">     
</span><span class="cx"> private:
</span><span class="cx">     void* m_memory { nullptr };
</span><del>-    Mode m_mode;
</del><ins>+    uint64_t m_size { 0 };
</ins><span class="cx">     PageCount m_initial;
</span><span class="cx">     PageCount m_maximum;
</span><del>-    uint64_t m_size { 0 };
</del><span class="cx">     uint64_t m_mappedCapacity { 0 };
</span><ins>+    Mode m_mode { Mode::BoundsChecking };
</ins><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> } } // namespace JSC::Wasm
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorewasmWasmMemoryInformationcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/wasm/WasmMemoryInformation.cpp (210228 => 210229)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/wasm/WasmMemoryInformation.cpp        2017-01-03 00:32:05 UTC (rev 210228)
+++ trunk/Source/JavaScriptCore/wasm/WasmMemoryInformation.cpp        2017-01-03 01:57:40 UTC (rev 210229)
</span><span class="lines">@@ -26,13 +26,52 @@
</span><span class="cx"> #include &quot;config.h&quot;
</span><span class="cx"> #include &quot;WasmMemoryInformation.h&quot;
</span><span class="cx"> 
</span><ins>+#if ENABLE(WEBASSEMBLY)
+
</ins><span class="cx"> #include &quot;WasmCallingConvention.h&quot;
</span><ins>+#include &lt;wtf/NeverDestroyed.h&gt;
</ins><span class="cx"> 
</span><del>-#if ENABLE(WEBASSEMBLY)
-
</del><span class="cx"> namespace JSC { namespace Wasm {
</span><span class="cx"> 
</span><del>-MemoryInformation::MemoryInformation(PageCount initial, PageCount maximum,  const Vector&lt;unsigned&gt;&amp; pinnedSizeRegisters, bool isImport)
</del><ins>+const PinnedRegisterInfo&amp; PinnedRegisterInfo::get()
+{
+    static LazyNeverDestroyed&lt;PinnedRegisterInfo&gt; staticPinnedRegisterInfo;
+    static std::once_flag staticPinnedRegisterInfoFlag;
+    std::call_once(staticPinnedRegisterInfoFlag, [] () {
+        Vector&lt;PinnedSizeRegisterInfo&gt; sizeRegisters;
+        GPRReg baseMemoryPointer;
+
+        // FIXME: We should support more than one memory size register, and we should allow different
+        //        WebAssembly.Instance to have different pins. Right now we take a vector with only one entry.
+        //        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
+        Vector&lt;unsigned&gt; pinnedSizes = { 0 };
+        unsigned remainingPinnedRegisters = pinnedSizes.size() + 1;
+        jscCallingConvention().m_calleeSaveRegisters.forEach([&amp;] (Reg reg) {
+            GPRReg gpr = reg.gpr();
+            if (!remainingPinnedRegisters || RegisterSet::stackRegisters().get(reg))
+                return;
+            if (remainingPinnedRegisters == 1) {
+                baseMemoryPointer = gpr;
+                remainingPinnedRegisters--;
+            } else
+                sizeRegisters.append({ gpr, pinnedSizes[--remainingPinnedRegisters - 1] });
+        });
+
+        ASSERT(!remainingPinnedRegisters);
+        staticPinnedRegisterInfo.construct(WTFMove(sizeRegisters), baseMemoryPointer);
+    });
+
+    return staticPinnedRegisterInfo.get();
+}
+
+PinnedRegisterInfo::PinnedRegisterInfo(Vector&lt;PinnedSizeRegisterInfo&gt;&amp;&amp; sizeRegisters, GPRReg baseMemoryPointer)
+    : sizeRegisters(WTFMove(sizeRegisters))
+    , baseMemoryPointer(baseMemoryPointer)
+{
+}
+
+MemoryInformation::MemoryInformation(PageCount initial, PageCount maximum,  bool isImport)
</ins><span class="cx">     : m_initial(initial)
</span><span class="cx">     , m_maximum(maximum)
</span><span class="cx">     , m_isImport(isImport)
</span><span class="lines">@@ -40,20 +79,6 @@
</span><span class="cx">     RELEASE_ASSERT(!!m_initial);
</span><span class="cx">     RELEASE_ASSERT(!m_maximum || m_maximum &gt;= m_initial);
</span><span class="cx">     ASSERT(!!*this);
</span><del>-
-    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);
</del><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> } } // namespace JSC::Wasm
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorewasmWasmMemoryInformationh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/wasm/WasmMemoryInformation.h (210228 => 210229)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/wasm/WasmMemoryInformation.h        2017-01-03 00:32:05 UTC (rev 210228)
+++ trunk/Source/JavaScriptCore/wasm/WasmMemoryInformation.h        2017-01-03 01:57:40 UTC (rev 210229)
</span><span class="lines">@@ -38,12 +38,11 @@
</span><span class="cx">     unsigned sizeOffset;
</span><span class="cx"> };
</span><span class="cx"> 
</span><del>-// FIXME: We should support more than one memory size register. Right now we take a vector with only one
-// entry. Specifically an entry 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
</del><span class="cx"> struct PinnedRegisterInfo {
</span><span class="cx">     Vector&lt;PinnedSizeRegisterInfo&gt; sizeRegisters;
</span><span class="cx">     GPRReg baseMemoryPointer;
</span><ins>+    static const PinnedRegisterInfo&amp; get();
+    PinnedRegisterInfo(Vector&lt;PinnedSizeRegisterInfo&gt;&amp;&amp;, GPRReg);
</ins><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> class MemoryInformation {
</span><span class="lines">@@ -53,9 +52,8 @@
</span><span class="cx">         ASSERT(!*this);
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    MemoryInformation(PageCount initial, PageCount maximum, const Vector&lt;unsigned&gt;&amp; pinnedSizeRegisters, bool isImport);
</del><ins>+    MemoryInformation(PageCount initial, PageCount maximum, bool isImport);
</ins><span class="cx"> 
</span><del>-    const PinnedRegisterInfo&amp; pinnedRegisters() const { return m_pinnedRegisters; }
</del><span class="cx">     PageCount initial() const { return m_initial; }
</span><span class="cx">     PageCount maximum() const { return m_maximum; }
</span><span class="cx">     bool isImport() const { return m_isImport; }
</span><span class="lines">@@ -65,7 +63,6 @@
</span><span class="cx"> private:
</span><span class="cx">     PageCount m_initial { };
</span><span class="cx">     PageCount m_maximum { };
</span><del>-    PinnedRegisterInfo m_pinnedRegisters { };
</del><span class="cx">     bool m_isImport { false };
</span><span class="cx"> };
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorewasmWasmModuleParsercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/wasm/WasmModuleParser.cpp (210228 => 210229)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/wasm/WasmModuleParser.cpp        2017-01-03 00:32:05 UTC (rev 210228)
+++ trunk/Source/JavaScriptCore/wasm/WasmModuleParser.cpp        2017-01-03 01:57:40 UTC (rev 210229)
</span><span class="lines">@@ -107,7 +107,7 @@
</span><span class="cx"> 
</span><span class="cx">     WASM_PARSER_FAIL_IF(!parseVarUInt32(count), &quot;can't get Type section's count&quot;);
</span><span class="cx">     WASM_PARSER_FAIL_IF(count == std::numeric_limits&lt;uint32_t&gt;::max(), &quot;Type section's count is too big &quot;, count);
</span><del>-    WASM_PARSER_FAIL_IF(!m_result.module-&gt;signatureIndices.tryReserveCapacity(count), &quot;can't allocate enough memory for Type section's &quot;, count, &quot; entries&quot;);
</del><ins>+    WASM_PARSER_FAIL_IF(!m_result.moduleSignatureIndicesToUniquedSignatureIndices.tryReserveCapacity(count), &quot;can't allocate enough memory for Type section's &quot;, count, &quot; entries&quot;);
</ins><span class="cx"> 
</span><span class="cx">     for (uint32_t i = 0; i &lt; count; ++i) {
</span><span class="cx">         int8_t type;
</span><span class="lines">@@ -139,7 +139,7 @@
</span><span class="cx">         signature-&gt;returnType() = returnType;
</span><span class="cx"> 
</span><span class="cx">         SignatureIndex signatureIndex = SignatureInformation::adopt(m_vm, signature.release());
</span><del>-        m_result.module-&gt;signatureIndices.uncheckedAppend(signatureIndex);
</del><ins>+        m_result.moduleSignatureIndicesToUniquedSignatureIndices.uncheckedAppend(signatureIndex);
</ins><span class="cx">     }
</span><span class="cx">     return { };
</span><span class="cx"> }
</span><span class="lines">@@ -152,7 +152,6 @@
</span><span class="cx">     WASM_PARSER_FAIL_IF(!m_result.module-&gt;globals.tryReserveCapacity(importCount), &quot;can't allocate enough memory for &quot;, importCount, &quot; globals&quot;); // FIXME this over-allocates when we fix the FIXMEs below.
</span><span class="cx">     WASM_PARSER_FAIL_IF(!m_result.module-&gt;imports.tryReserveCapacity(importCount), &quot;can't allocate enough memory for &quot;, importCount, &quot; imports&quot;); // FIXME this over-allocates when we fix the FIXMEs below.
</span><span class="cx">     WASM_PARSER_FAIL_IF(!m_result.module-&gt;importFunctionSignatureIndices.tryReserveCapacity(importCount), &quot;can't allocate enough memory for &quot;, importCount, &quot; import function signatures&quot;); // FIXME this over-allocates when we fix the FIXMEs below.
</span><del>-    WASM_PARSER_FAIL_IF(!m_result.functionIndexSpace.tryReserveCapacity(importCount), &quot;can't allocate enough memory for &quot;, importCount, &quot; functions in the index space&quot;); // FIXME this over-allocates when we fix the FIXMEs below. We'll allocate some more here when we know how many functions to expect.
</del><span class="cx"> 
</span><span class="cx">     for (uint32_t importNumber = 0; importNumber &lt; importCount; ++importNumber) {
</span><span class="cx">         Import imp;
</span><span class="lines">@@ -174,11 +173,10 @@
</span><span class="cx">         case ExternalKind::Function: {
</span><span class="cx">             uint32_t functionSignatureIndex;
</span><span class="cx">             WASM_PARSER_FAIL_IF(!parseVarUInt32(functionSignatureIndex), &quot;can't get &quot;, importNumber, &quot;th Import's function signature in module '&quot;, moduleString, &quot;' field '&quot;, fieldString, &quot;'&quot;);
</span><del>-            WASM_PARSER_FAIL_IF(functionSignatureIndex &gt;= m_result.module-&gt;signatureIndices.size(), &quot;invalid function signature for &quot;, importNumber, &quot;th Import, &quot;, functionSignatureIndex, &quot; is out of range of &quot;, m_result.module-&gt;signatureIndices.size(), &quot; in module '&quot;, moduleString, &quot;' field '&quot;, fieldString, &quot;'&quot;);
</del><ins>+            WASM_PARSER_FAIL_IF(functionSignatureIndex &gt;= m_result.moduleSignatureIndicesToUniquedSignatureIndices.size(), &quot;invalid function signature for &quot;, importNumber, &quot;th Import, &quot;, functionSignatureIndex, &quot; is out of range of &quot;, m_result.moduleSignatureIndicesToUniquedSignatureIndices.size(), &quot; in module '&quot;, moduleString, &quot;' field '&quot;, fieldString, &quot;'&quot;);
</ins><span class="cx">             imp.kindIndex = m_result.module-&gt;importFunctionSignatureIndices.size();
</span><del>-            SignatureIndex signatureIndex = m_result.module-&gt;signatureIndices[functionSignatureIndex];
</del><ins>+            SignatureIndex signatureIndex = m_result.moduleSignatureIndicesToUniquedSignatureIndices[functionSignatureIndex];
</ins><span class="cx">             m_result.module-&gt;importFunctionSignatureIndices.uncheckedAppend(signatureIndex);
</span><del>-            m_result.functionIndexSpace.uncheckedAppend(signatureIndex);
</del><span class="cx">             break;
</span><span class="cx">         }
</span><span class="cx">         case ExternalKind::Table: {
</span><span class="lines">@@ -220,20 +218,18 @@
</span><span class="cx">     WASM_PARSER_FAIL_IF(count == std::numeric_limits&lt;uint32_t&gt;::max(), &quot;Function section's count is too big &quot;, count);
</span><span class="cx">     WASM_PARSER_FAIL_IF(!m_result.module-&gt;internalFunctionSignatureIndices.tryReserveCapacity(count), &quot;can't allocate enough memory for &quot;, count, &quot; Function signatures&quot;);
</span><span class="cx">     WASM_PARSER_FAIL_IF(!m_result.functionLocationInBinary.tryReserveCapacity(count), &quot;can't allocate enough memory for &quot;, count, &quot;Function locations&quot;);
</span><del>-    WASM_PARSER_FAIL_IF(!m_result.functionIndexSpace.tryReserveCapacity(m_result.functionIndexSpace.size() + count), &quot;can't allocate enough memory for &quot;, count, &quot; more functions in the function index space&quot;);
</del><span class="cx"> 
</span><span class="cx">     for (uint32_t i = 0; i &lt; count; ++i) {
</span><span class="cx">         uint32_t typeNumber;
</span><span class="cx">         WASM_PARSER_FAIL_IF(!parseVarUInt32(typeNumber), &quot;can't get &quot;, i, &quot;th Function's type number&quot;);
</span><del>-        WASM_PARSER_FAIL_IF(typeNumber &gt;= m_result.module-&gt;signatureIndices.size(), i, &quot;th Function type number is invalid &quot;, typeNumber);
</del><ins>+        WASM_PARSER_FAIL_IF(typeNumber &gt;= m_result.moduleSignatureIndicesToUniquedSignatureIndices.size(), i, &quot;th Function type number is invalid &quot;, typeNumber);
</ins><span class="cx"> 
</span><del>-        SignatureIndex signatureIndex = m_result.module-&gt;signatureIndices[typeNumber];
</del><ins>+        SignatureIndex signatureIndex = m_result.moduleSignatureIndicesToUniquedSignatureIndices[typeNumber];
</ins><span class="cx">         // The Code section fixes up start and end.
</span><span class="cx">         size_t start = 0;
</span><span class="cx">         size_t end = 0;
</span><span class="cx">         m_result.module-&gt;internalFunctionSignatureIndices.uncheckedAppend(signatureIndex);
</span><span class="cx">         m_result.functionLocationInBinary.uncheckedAppend({ start, end });
</span><del>-        m_result.functionIndexSpace.uncheckedAppend(signatureIndex);
</del><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     return { };
</span><span class="lines">@@ -320,8 +316,7 @@
</span><span class="cx">     ASSERT(initialPageCount);
</span><span class="cx">     ASSERT(!maximumPageCount || maximumPageCount &gt;= initialPageCount);
</span><span class="cx"> 
</span><del>-    Vector&lt;unsigned&gt; pinnedSizes = { 0 };
-    m_result.module-&gt;memory = MemoryInformation(initialPageCount, maximumPageCount, pinnedSizes, isImport);
</del><ins>+    m_result.module-&gt;memory = MemoryInformation(initialPageCount, maximumPageCount, isImport);
</ins><span class="cx">     return { };
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -387,7 +382,7 @@
</span><span class="cx">         WASM_PARSER_FAIL_IF(!parseVarUInt32(exp.kindIndex), &quot;can't get &quot;, exportNumber, &quot;th Export's kind index, named '&quot;, fieldString, &quot;'&quot;);
</span><span class="cx">         switch (exp.kind) {
</span><span class="cx">         case ExternalKind::Function: {
</span><del>-            WASM_PARSER_FAIL_IF(exp.kindIndex &gt;= m_result.functionIndexSpace.size(), exportNumber, &quot;th Export has invalid function number &quot;, exp.kindIndex, &quot; it exceeds the function index space &quot;, m_result.functionIndexSpace.size(), &quot;, named '&quot;, fieldString, &quot;'&quot;);
</del><ins>+            WASM_PARSER_FAIL_IF(exp.kindIndex &gt;= m_result.module-&gt;functionIndexSpaceSize(), exportNumber, &quot;th Export has invalid function number &quot;, exp.kindIndex, &quot; it exceeds the function index space &quot;, m_result.module-&gt;functionIndexSpaceSize(), &quot;, named '&quot;, fieldString, &quot;'&quot;);
</ins><span class="cx">             break;
</span><span class="cx">         }
</span><span class="cx">         case ExternalKind::Table: {
</span><span class="lines">@@ -417,8 +412,8 @@
</span><span class="cx"> {
</span><span class="cx">     uint32_t startFunctionIndex;
</span><span class="cx">     WASM_PARSER_FAIL_IF(!parseVarUInt32(startFunctionIndex), &quot;can't get Start index&quot;);
</span><del>-    WASM_PARSER_FAIL_IF(startFunctionIndex &gt;= m_result.functionIndexSpace.size(), &quot;Start index &quot;, startFunctionIndex, &quot; exceeds function index space &quot;, m_result.functionIndexSpace.size());
-    SignatureIndex signatureIndex = m_result.functionIndexSpace[startFunctionIndex].signatureIndex;
</del><ins>+    WASM_PARSER_FAIL_IF(startFunctionIndex &gt;= m_result.module-&gt;functionIndexSpaceSize(), &quot;Start index &quot;, startFunctionIndex, &quot; exceeds function index space &quot;, m_result.module-&gt;functionIndexSpaceSize());
+    SignatureIndex signatureIndex = m_result.module-&gt;signatureIndexFromFunctionIndexSpace(startFunctionIndex);
</ins><span class="cx">     const Signature* signature = SignatureInformation::get(m_vm, signatureIndex);
</span><span class="cx">     WASM_PARSER_FAIL_IF(signature-&gt;argumentCount(), &quot;Start function can't have arguments&quot;);
</span><span class="cx">     WASM_PARSER_FAIL_IF(signature-&gt;returnType() != Void, &quot;Start function can't return a value&quot;);
</span><span class="lines">@@ -469,7 +464,7 @@
</span><span class="cx">         for (unsigned index = 0; index &lt; indexCount; ++index) {
</span><span class="cx">             uint32_t functionIndex;
</span><span class="cx">             WASM_PARSER_FAIL_IF(!parseVarUInt32(functionIndex), &quot;can't get Element section's &quot;, elementNum, &quot;th element's &quot;, index, &quot;th index&quot;);
</span><del>-            WASM_PARSER_FAIL_IF(functionIndex &gt;= m_result.functionIndexSpace.size(), &quot;Element section's &quot;, elementNum, &quot;th element's &quot;, index, &quot;th index is &quot;, functionIndex, &quot; which exceeds the function index space size of &quot;, m_result.functionIndexSpace.size());
</del><ins>+            WASM_PARSER_FAIL_IF(functionIndex &gt;= m_result.module-&gt;functionIndexSpaceSize(), &quot;Element section's &quot;, elementNum, &quot;th element's &quot;, index, &quot;th index is &quot;, functionIndex, &quot; which exceeds the function index space size of &quot;, m_result.module-&gt;functionIndexSpaceSize());
</ins><span class="cx"> 
</span><span class="cx">             element.functionIndices.uncheckedAppend(functionIndex);
</span><span class="cx">         }
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorewasmWasmModuleParserh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/wasm/WasmModuleParser.h (210228 => 210229)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/wasm/WasmModuleParser.h        2017-01-03 00:32:05 UTC (rev 210228)
+++ trunk/Source/JavaScriptCore/wasm/WasmModuleParser.h        2017-01-03 01:57:40 UTC (rev 210229)
</span><span class="lines">@@ -36,8 +36,8 @@
</span><span class="cx"> 
</span><span class="cx"> struct ModuleParserResult {
</span><span class="cx">     std::unique_ptr&lt;ModuleInformation&gt; module;
</span><del>-    FunctionIndexSpace functionIndexSpace;
</del><span class="cx">     Vector&lt;FunctionLocationInBinary&gt; functionLocationInBinary;
</span><ins>+    Vector&lt;SignatureIndex&gt; moduleSignatureIndicesToUniquedSignatureIndices;
</ins><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> class ModuleParser : public Parser&lt;ModuleParserResult&gt; {
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorewasmWasmPageCountcppfromrev210228trunkSourceJavaScriptCorewasmWasmBindingh"></a>
<div class="copfile"><h4>Copied: trunk/Source/JavaScriptCore/wasm/WasmPageCount.cpp (from rev 210228, trunk/Source/JavaScriptCore/wasm/WasmBinding.h) (0 => 210229)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/wasm/WasmPageCount.cpp                                (rev 0)
+++ trunk/Source/JavaScriptCore/wasm/WasmPageCount.cpp        2017-01-03 01:57:40 UTC (rev 210229)
</span><span class="lines">@@ -0,0 +1,45 @@
</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;WasmPageCount.h&quot;
+
+#if ENABLE(WEBASSEMBLY)
+
+#include &lt;wtf/PrintStream.h&gt;
+#include &lt;wtf/text/WTFString.h&gt;
+
+namespace JSC { namespace Wasm {
+
+void PageCount::dump(PrintStream&amp; out) const
+{
+    out.print(String::number(bytes()), &quot;B&quot;);
+}
+
+} // namespace JSC
+
+} // namespace Wasm
+
+#endif // ENABLE(WEBASSEMBLY)
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCorewasmWasmPageCounth"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/wasm/WasmPageCount.h (210228 => 210229)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/wasm/WasmPageCount.h        2017-01-03 00:32:05 UTC (rev 210228)
+++ trunk/Source/JavaScriptCore/wasm/WasmPageCount.h        2017-01-03 01:57:40 UTC (rev 210229)
</span><span class="lines">@@ -27,6 +27,10 @@
</span><span class="cx"> 
</span><span class="cx"> #if ENABLE(WEBASSEMBLY)
</span><span class="cx"> 
</span><ins>+namespace WTF {
+class PrintStream;
+}
+
</ins><span class="cx"> namespace JSC { namespace Wasm {
</span><span class="cx"> 
</span><span class="cx"> class PageCount {
</span><span class="lines">@@ -42,6 +46,8 @@
</span><span class="cx">         : m_pageCount(pageCount)
</span><span class="cx">     { }
</span><span class="cx"> 
</span><ins>+    void dump(WTF::PrintStream&amp;) const;
+
</ins><span class="cx">     uint64_t bytes() const { return static_cast&lt;uint64_t&gt;(m_pageCount) * static_cast&lt;uint64_t&gt;(pageSize); }
</span><span class="cx">     uint32_t pageCount() const { return m_pageCount; }
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorewasmWasmPlancpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/wasm/WasmPlan.cpp (210228 => 210229)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/wasm/WasmPlan.cpp        2017-01-03 00:32:05 UTC (rev 210228)
+++ trunk/Source/JavaScriptCore/wasm/WasmPlan.cpp        2017-01-03 01:57:40 UTC (rev 210229)
</span><span class="lines">@@ -76,8 +76,7 @@
</span><span class="cx">         }
</span><span class="cx">         m_moduleInformation = WTFMove(parseResult-&gt;module);
</span><span class="cx">         m_functionLocationInBinary = WTFMove(parseResult-&gt;functionLocationInBinary);
</span><del>-        m_functionIndexSpace.size = parseResult-&gt;functionIndexSpace.size();
-        m_functionIndexSpace.buffer = parseResult-&gt;functionIndexSpace.releaseBuffer();
</del><ins>+        m_moduleSignatureIndicesToUniquedSignatureIndices = WTFMove(parseResult-&gt;moduleSignatureIndicesToUniquedSignatureIndices);
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     for (unsigned functionIndex = 0; functionIndex &lt; m_functionLocationInBinary.size(); ++functionIndex) {
</span><span class="lines">@@ -89,7 +88,7 @@
</span><span class="cx">         SignatureIndex signatureIndex = m_moduleInformation-&gt;internalFunctionSignatureIndices[functionIndex];
</span><span class="cx">         const Signature* signature = SignatureInformation::get(m_vm, signatureIndex);
</span><span class="cx"> 
</span><del>-        auto validationResult = validateFunction(m_vm, functionStart, functionLength, signature, m_functionIndexSpace, *m_moduleInformation);
</del><ins>+        auto validationResult = validateFunction(m_vm, functionStart, functionLength, signature, *m_moduleInformation, m_moduleSignatureIndicesToUniquedSignatureIndices);
</ins><span class="cx">         if (!validationResult) {
</span><span class="cx">             if (verbose) {
</span><span class="cx">                 for (unsigned i = 0; i &lt; functionLength; ++i)
</span><span class="lines">@@ -127,7 +126,7 @@
</span><span class="cx">         return true;
</span><span class="cx">     };
</span><span class="cx"> 
</span><del>-    if (!tryReserveCapacity(m_wasmToJSStubs, m_moduleInformation-&gt;importFunctionSignatureIndices.size(), &quot; WebAssembly to JavaScript stubs&quot;)
</del><ins>+    if (!tryReserveCapacity(m_wasmExitStubs, m_moduleInformation-&gt;importFunctionSignatureIndices.size(), &quot; WebAssembly to JavaScript stubs&quot;)
</ins><span class="cx">         || !tryReserveCapacity(m_unlinkedWasmToWasmCalls, m_functionLocationInBinary.size(), &quot; unlinked WebAssembly to WebAssembly calls&quot;)
</span><span class="cx">         || !tryReserveCapacity(m_wasmInternalFunctions, m_functionLocationInBinary.size(), &quot; WebAssembly functions&quot;)
</span><span class="cx">         || !tryReserveCapacity(m_compilationContexts, m_functionLocationInBinary.size(), &quot; compilation contexts&quot;))
</span><span class="lines">@@ -141,12 +140,11 @@
</span><span class="cx">         Import* import = &amp;m_moduleInformation-&gt;imports[importIndex];
</span><span class="cx">         if (import-&gt;kind != ExternalKind::Function)
</span><span class="cx">             continue;
</span><del>-        unsigned importFunctionIndex = m_wasmToJSStubs.size();
</del><ins>+        unsigned importFunctionIndex = m_wasmExitStubs.size();
</ins><span class="cx">         if (verbose)
</span><span class="cx">             dataLogLn(&quot;Processing import function number &quot;, importFunctionIndex, &quot;: &quot;, import-&gt;module, &quot;: &quot;, import-&gt;field);
</span><span class="cx">         SignatureIndex signatureIndex = m_moduleInformation-&gt;importFunctionSignatureIndices.at(import-&gt;kindIndex);
</span><del>-        m_wasmToJSStubs.uncheckedAppend(importStubGenerator(m_vm, m_callLinkInfos, signatureIndex, importFunctionIndex));
-        m_functionIndexSpace.buffer.get()[importFunctionIndex].code = m_wasmToJSStubs[importFunctionIndex].code().executableAddress();
</del><ins>+        m_wasmExitStubs.uncheckedAppend(exitStubGenerator(m_vm, m_callLinkInfos, signatureIndex, importFunctionIndex));
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     m_currentIndex = 0;
</span><span class="lines">@@ -167,12 +165,12 @@
</span><span class="cx">             ASSERT(functionLength &lt;= m_sourceLength);
</span><span class="cx">             SignatureIndex signatureIndex = m_moduleInformation-&gt;internalFunctionSignatureIndices[functionIndex];
</span><span class="cx">             const Signature* signature = SignatureInformation::get(m_vm, signatureIndex);
</span><del>-            unsigned functionIndexSpace = m_wasmToJSStubs.size() + functionIndex;
-            ASSERT_UNUSED(functionIndexSpace, m_functionIndexSpace.buffer.get()[functionIndexSpace].signatureIndex == signatureIndex);
-            ASSERT(validateFunction(m_vm, functionStart, functionLength, signature, m_functionIndexSpace, *m_moduleInformation));
</del><ins>+            unsigned functionIndexSpace = m_wasmExitStubs.size() + functionIndex;
+            ASSERT_UNUSED(functionIndexSpace, m_moduleInformation-&gt;signatureIndexFromFunctionIndexSpace(functionIndexSpace) == signatureIndex);
+            ASSERT(validateFunction(m_vm, functionStart, functionLength, signature, *m_moduleInformation, m_moduleSignatureIndicesToUniquedSignatureIndices));
</ins><span class="cx"> 
</span><span class="cx">             m_unlinkedWasmToWasmCalls[functionIndex] = Vector&lt;UnlinkedWasmToWasmCall&gt;();
</span><del>-            auto parseAndCompileResult = parseAndCompile(*m_vm, m_compilationContexts[functionIndex], functionStart, functionLength, signature, m_unlinkedWasmToWasmCalls[functionIndex], m_functionIndexSpace, *m_moduleInformation);
</del><ins>+            auto parseAndCompileResult = parseAndCompile(*m_vm, m_compilationContexts[functionIndex], functionStart, functionLength, signature, m_unlinkedWasmToWasmCalls[functionIndex], *m_moduleInformation, m_moduleSignatureIndicesToUniquedSignatureIndices);
</ins><span class="cx"> 
</span><span class="cx">             if (UNLIKELY(!parseAndCompileResult)) {
</span><span class="cx">                 auto locker = holdLock(m_lock);
</span><span class="lines">@@ -209,10 +207,12 @@
</span><span class="cx">     for (uint32_t functionIndex = 0; functionIndex &lt; m_functionLocationInBinary.size(); functionIndex++) {
</span><span class="cx">         {
</span><span class="cx">             CompilationContext&amp; context = m_compilationContexts[functionIndex];
</span><ins>+            SignatureIndex signatureIndex = m_moduleInformation-&gt;internalFunctionSignatureIndices[functionIndex];
+            String signatureDescription = SignatureInformation::get(m_vm, signatureIndex)-&gt;toString();
</ins><span class="cx">             {
</span><span class="cx">                 LinkBuffer linkBuffer(*m_vm, *context.wasmEntrypointJIT, nullptr);
</span><span class="cx">                 m_wasmInternalFunctions[functionIndex]-&gt;wasmEntrypoint.compilation =
</span><del>-                    std::make_unique&lt;B3::Compilation&gt;(FINALIZE_CODE(linkBuffer, (&quot;Wasm function&quot;)), WTFMove(context.wasmEntrypointByproducts));
</del><ins>+                    std::make_unique&lt;B3::Compilation&gt;(FINALIZE_CODE(linkBuffer, (&quot;WebAssembly function[%i] %s&quot;, functionIndex, signatureDescription.ascii().data())), WTFMove(context.wasmEntrypointByproducts));
</ins><span class="cx">             }
</span><span class="cx"> 
</span><span class="cx">             {
</span><span class="lines">@@ -220,12 +220,9 @@
</span><span class="cx">                 linkBuffer.link(context.jsEntrypointToWasmEntrypointCall, FunctionPtr(m_wasmInternalFunctions[functionIndex]-&gt;wasmEntrypoint.compilation-&gt;code().executableAddress()));
</span><span class="cx"> 
</span><span class="cx">                 m_wasmInternalFunctions[functionIndex]-&gt;jsToWasmEntrypoint.compilation =
</span><del>-                    std::make_unique&lt;B3::Compilation&gt;(FINALIZE_CODE(linkBuffer, (&quot;Wasm JS entrypoint&quot;)), WTFMove(context.jsEntrypointByproducts));
</del><ins>+                    std::make_unique&lt;B3::Compilation&gt;(FINALIZE_CODE(linkBuffer, (&quot;JavaScript-&gt;WebAssembly entrypoint[%i] %s&quot;, functionIndex, signatureDescription.ascii().data())), WTFMove(context.jsEntrypointByproducts));
</ins><span class="cx">             }
</span><span class="cx">         }
</span><del>-
-        unsigned functionIndexSpace = m_wasmToJSStubs.size() + functionIndex;
-        m_functionIndexSpace.buffer.get()[functionIndexSpace].code = m_wasmInternalFunctions[functionIndex]-&gt;wasmEntrypoint.compilation-&gt;code().executableAddress();
</del><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     if (verbose || Options::reportCompileTimes()) {
</span><span class="lines">@@ -235,8 +232,19 @@
</span><span class="cx"> 
</span><span class="cx">     // Patch the call sites for each WebAssembly function.
</span><span class="cx">     for (auto&amp; unlinked : m_unlinkedWasmToWasmCalls) {
</span><del>-        for (auto&amp; call : unlinked)
-            MacroAssembler::repatchCall(call.callLocation, CodeLocationLabel(m_functionIndexSpace.buffer.get()[call.functionIndex].code));
</del><ins>+        for (auto&amp; call : unlinked) {
+            void* executableAddress;
+            if (m_moduleInformation-&gt;isImportedFunctionFromFunctionIndexSpace(call.functionIndex)) {
+                // FIXME imports could have been linked in B3, instead of generating a patchpoint. This condition should be replaced by a RELEASE_ASSERT. https://bugs.webkit.org/show_bug.cgi?id=166462
+                executableAddress = call.target == UnlinkedWasmToWasmCall::Target::ToJs
+                    ? m_wasmExitStubs.at(call.functionIndex).wasmToJs.code().executableAddress()
+                    : m_wasmExitStubs.at(call.functionIndex).wasmToWasm.code().executableAddress();
+            } else {
+                ASSERT(call.target != UnlinkedWasmToWasmCall::Target::ToJs);
+                executableAddress = m_wasmInternalFunctions.at(call.functionIndex - m_wasmExitStubs.size())-&gt;wasmEntrypoint.compilation-&gt;code().executableAddress();
+            }
+            MacroAssembler::repatchCall(call.callLocation, CodeLocationLabel(executableAddress));
+        }
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     m_failed = false;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorewasmWasmPlanh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/wasm/WasmPlan.h (210228 => 210229)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/wasm/WasmPlan.h        2017-01-03 00:32:05 UTC (rev 210228)
+++ trunk/Source/JavaScriptCore/wasm/WasmPlan.h        2017-01-03 01:57:40 UTC (rev 210229)
</span><span class="lines">@@ -86,26 +86,20 @@
</span><span class="cx">         return WTFMove(m_callLinkInfos);
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    Vector&lt;WasmToJSStub&gt;&amp;&amp; takeWasmToJSStubs()
</del><ins>+    Vector&lt;WasmExitStubs&gt;&amp;&amp; takeWasmExitStubs()
</ins><span class="cx">     {
</span><span class="cx">         RELEASE_ASSERT(!failed());
</span><del>-        return WTFMove(m_wasmToJSStubs);
</del><ins>+        return WTFMove(m_wasmExitStubs);
</ins><span class="cx">     }
</span><span class="cx"> 
</span><del>-    ImmutableFunctionIndexSpace&amp;&amp; takeFunctionIndexSpace()
-    {
-        RELEASE_ASSERT(!failed());
-        return WTFMove(m_functionIndexSpace);
-    }
-
</del><span class="cx"> private:
</span><span class="cx">     std::unique_ptr&lt;ModuleInformation&gt; m_moduleInformation;
</span><span class="cx">     Vector&lt;FunctionLocationInBinary&gt; m_functionLocationInBinary;
</span><ins>+    Vector&lt;SignatureIndex&gt; m_moduleSignatureIndicesToUniquedSignatureIndices;
</ins><span class="cx">     Bag&lt;CallLinkInfo&gt; m_callLinkInfos;
</span><del>-    Vector&lt;WasmToJSStub&gt; m_wasmToJSStubs;
</del><ins>+    Vector&lt;WasmExitStubs&gt; m_wasmExitStubs;
</ins><span class="cx">     Vector&lt;std::unique_ptr&lt;WasmInternalFunction&gt;&gt; m_wasmInternalFunctions;
</span><span class="cx">     Vector&lt;CompilationContext&gt; m_compilationContexts;
</span><del>-    ImmutableFunctionIndexSpace m_functionIndexSpace;
</del><span class="cx"> 
</span><span class="cx">     VM* m_vm;
</span><span class="cx">     Vector&lt;Vector&lt;UnlinkedWasmToWasmCall&gt;&gt; m_unlinkedWasmToWasmCalls;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorewasmWasmSignaturecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/wasm/WasmSignature.cpp (210228 => 210229)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/wasm/WasmSignature.cpp        2017-01-03 00:32:05 UTC (rev 210228)
+++ trunk/Source/JavaScriptCore/wasm/WasmSignature.cpp        2017-01-03 01:57:40 UTC (rev 210229)
</span><span class="lines">@@ -41,12 +41,22 @@
</span><span class="cx"> 
</span><span class="cx"> const constexpr SignatureIndex Signature::invalidIndex;
</span><span class="cx"> 
</span><ins>+String Signature::toString() const
+{
+    String result(makeString(returnType()));
+    result.append(&quot; (&quot;);
+    for (SignatureArgCount arg = 0; arg &lt; argumentCount(); ++arg) {
+        if (arg)
+            result.append(&quot;, &quot;);
+        result.append(makeString(argument(arg)));
+    }
+    result.append(')');
+    return result;
+}
+
</ins><span class="cx"> void Signature::dump(PrintStream&amp; out) const
</span><span class="cx"> {
</span><del>-    out.print(makeString(returnType()), &quot; (&quot;);
-    for (SignatureArgCount arg = 0; arg &lt; argumentCount(); ++arg)
-        out.print((arg ? &quot;, &quot; : &quot;&quot;), makeString(argument(arg)));
-    out.print(&quot;)&quot;);
</del><ins>+    out.print(toString());
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> unsigned Signature::hash() const
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorewasmWasmSignatureh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/wasm/WasmSignature.h (210228 => 210229)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/wasm/WasmSignature.h        2017-01-03 00:32:05 UTC (rev 210228)
+++ trunk/Source/JavaScriptCore/wasm/WasmSignature.h        2017-01-03 01:57:40 UTC (rev 210229)
</span><span class="lines">@@ -82,6 +82,7 @@
</span><span class="cx">     }
</span><span class="cx">     Type argument(SignatureArgCount i) const { return const_cast&lt;Signature*&gt;(this)-&gt;argument(i); }
</span><span class="cx"> 
</span><ins>+    WTF::String toString() const;
</ins><span class="cx">     void dump(WTF::PrintStream&amp; out) const;
</span><span class="cx">     bool operator==(const Signature&amp; rhs) const
</span><span class="cx">     {
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorewasmWasmValidatecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/wasm/WasmValidate.cpp (210228 => 210229)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/wasm/WasmValidate.cpp        2017-01-03 00:32:05 UTC (rev 210228)
+++ trunk/Source/JavaScriptCore/wasm/WasmValidate.cpp        2017-01-03 01:57:40 UTC (rev 210229)
</span><span class="lines">@@ -381,10 +381,10 @@
</span><span class="cx">     dataLogLn();
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-Expected&lt;void, String&gt; validateFunction(VM* vm, const uint8_t* source, size_t length, const Signature* signature, const ImmutableFunctionIndexSpace&amp; functionIndexSpace, const ModuleInformation&amp; module)
</del><ins>+Expected&lt;void, String&gt; validateFunction(VM* vm, const uint8_t* source, size_t length, const Signature* signature, const ModuleInformation&amp; module, const Vector&lt;SignatureIndex&gt;&amp; moduleSignatureIndicesToUniquedSignatureIndices)
</ins><span class="cx"> {
</span><span class="cx">     Validate context(module);
</span><del>-    FunctionParser&lt;Validate&gt; validator(vm, context, source, length, signature, functionIndexSpace, module);
</del><ins>+    FunctionParser&lt;Validate&gt; validator(vm, context, source, length, signature, module, moduleSignatureIndicesToUniquedSignatureIndices);
</ins><span class="cx">     WASM_FAIL_IF_HELPER_FAILS(validator.parse());
</span><span class="cx">     return { };
</span><span class="cx"> }
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorewasmWasmValidateh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/wasm/WasmValidate.h (210228 => 210229)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/wasm/WasmValidate.h        2017-01-03 00:32:05 UTC (rev 210228)
+++ trunk/Source/JavaScriptCore/wasm/WasmValidate.h        2017-01-03 01:57:40 UTC (rev 210229)
</span><span class="lines">@@ -36,7 +36,7 @@
</span><span class="cx"> 
</span><span class="cx"> namespace Wasm {
</span><span class="cx"> 
</span><del>-Expected&lt;void, String&gt; validateFunction(VM*, const uint8_t*, size_t, const Signature*, const ImmutableFunctionIndexSpace&amp;, const ModuleInformation&amp;);
</del><ins>+Expected&lt;void, String&gt; validateFunction(VM*, const uint8_t*, size_t, const Signature*, const ModuleInformation&amp;, const Vector&lt;SignatureIndex&gt;&amp;);
</ins><span class="cx"> 
</span><span class="cx"> } } // namespace JSC::Wasm
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorewasmjsJSWebAssemblyInstanceh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/wasm/js/JSWebAssemblyInstance.h (210228 => 210229)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/wasm/js/JSWebAssemblyInstance.h        2017-01-03 00:32:05 UTC (rev 210228)
+++ trunk/Source/JavaScriptCore/wasm/js/JSWebAssemblyInstance.h        2017-01-03 01:57:40 UTC (rev 210229)
</span><span class="lines">@@ -86,9 +86,11 @@
</span><span class="cx">         return offsetOfImportFunctions() + sizeof(WriteBarrier&lt;JSCell&gt;) * idx;
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    static ptrdiff_t offsetOfMemory() { return OBJECT_OFFSETOF(JSWebAssemblyInstance, m_memory); }
</ins><span class="cx">     static ptrdiff_t offsetOfTable() { return OBJECT_OFFSETOF(JSWebAssemblyInstance, m_table); }
</span><del>-    static ptrdiff_t offsetOfMemory() { return OBJECT_OFFSETOF(JSWebAssemblyInstance, m_memory); }
</del><span class="cx">     static ptrdiff_t offsetOfGlobals() { return OBJECT_OFFSETOF(JSWebAssemblyInstance, m_globals); }
</span><ins>+    static size_t offsetOfImportFunctions() { return WTF::roundUpToMultipleOf&lt;sizeof(WriteBarrier&lt;JSCell&gt;)&gt;(sizeof(JSWebAssemblyInstance)); }
+    static size_t offsetOfImportFunction(size_t importFunctionNum) { return offsetOfImportFunctions() + importFunctionNum * sizeof(sizeof(WriteBarrier&lt;JSCell&gt;)); }
</ins><span class="cx"> 
</span><span class="cx"> protected:
</span><span class="cx">     JSWebAssemblyInstance(VM&amp;, Structure*, unsigned numImportFunctions);
</span><span class="lines">@@ -96,11 +98,6 @@
</span><span class="cx">     static void destroy(JSCell*);
</span><span class="cx">     static void visitChildren(JSCell*, SlotVisitor&amp;);
</span><span class="cx"> 
</span><del>-    static size_t offsetOfImportFunctions()
-    {
-        return WTF::roundUpToMultipleOf&lt;sizeof(WriteBarrier&lt;JSCell&gt;)&gt;(sizeof(JSWebAssemblyInstance));
-    }
-
</del><span class="cx">     static size_t allocationSize(unsigned numImportFunctions)
</span><span class="cx">     {
</span><span class="cx">         return offsetOfImportFunctions() + sizeof(WriteBarrier&lt;JSCell&gt;) * numImportFunctions;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorewasmjsJSWebAssemblyMemorycpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/wasm/js/JSWebAssemblyMemory.cpp (210228 => 210229)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/wasm/js/JSWebAssemblyMemory.cpp        2017-01-03 00:32:05 UTC (rev 210228)
+++ trunk/Source/JavaScriptCore/wasm/js/JSWebAssemblyMemory.cpp        2017-01-03 01:57:40 UTC (rev 210229)
</span><span class="lines">@@ -37,9 +37,9 @@
</span><span class="cx"> 
</span><span class="cx"> const ClassInfo JSWebAssemblyMemory::s_info = { &quot;WebAssembly.Memory&quot;, &amp;Base::s_info, 0, CREATE_METHOD_TABLE(JSWebAssemblyMemory) };
</span><span class="cx"> 
</span><del>-JSWebAssemblyMemory* JSWebAssemblyMemory::create(VM&amp; vm, Structure* structure, std::unique_ptr&lt;Wasm::Memory&gt;&amp;&amp; memory)
</del><ins>+JSWebAssemblyMemory* JSWebAssemblyMemory::create(VM&amp; vm, Structure* structure, Wasm::Memory&amp;&amp; memory)
</ins><span class="cx"> {
</span><del>-    auto* instance = new (NotNull, allocateCell&lt;JSWebAssemblyMemory&gt;(vm.heap)) JSWebAssemblyMemory(vm, structure, WTFMove(memory));
</del><ins>+    auto* instance = new (NotNull, allocateCell&lt;JSWebAssemblyMemory&gt;(vm.heap)) JSWebAssemblyMemory(vm, structure, std::forward&lt;Wasm::Memory&gt;(memory));
</ins><span class="cx">     instance-&gt;finishCreation(vm);
</span><span class="cx">     return instance;
</span><span class="cx"> }
</span><span class="lines">@@ -49,7 +49,7 @@
</span><span class="cx">     return Structure::create(vm, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), info());
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-JSWebAssemblyMemory::JSWebAssemblyMemory(VM&amp; vm, Structure* structure, std::unique_ptr&lt;Wasm::Memory&gt;&amp;&amp; memory)
</del><ins>+JSWebAssemblyMemory::JSWebAssemblyMemory(VM&amp; vm, Structure* structure, Wasm::Memory&amp;&amp; memory)
</ins><span class="cx">     : Base(vm, structure)
</span><span class="cx">     , m_memory(WTFMove(memory))
</span><span class="cx"> {
</span><span class="lines">@@ -72,7 +72,7 @@
</span><span class="cx">     auto destructor = [] (void*) {
</span><span class="cx">         // We don't need to do anything here to destroy the memory.
</span><span class="cx">         // The ArrayBuffer backing the JSArrayBuffer is only owned by us,
</span><del>-        // so we guarantee its lifecylce.
</del><ins>+        // so we guarantee its lifecycle.
</ins><span class="cx">     };
</span><span class="cx">     m_buffer = ArrayBuffer::createFromBytes(memory()-&gt;memory(), memory()-&gt;size(), WTFMove(destructor));
</span><span class="cx">     m_bufferWrapper.set(vm, this, JSArrayBuffer::create(vm, globalObject-&gt;m_arrayBufferStructure.get(), m_buffer.get()));
</span><span class="lines">@@ -85,7 +85,7 @@
</span><span class="cx">     VM&amp; vm = exec-&gt;vm();
</span><span class="cx">     auto throwScope = DECLARE_THROW_SCOPE(vm);
</span><span class="cx"> 
</span><del>-    Wasm::PageCount oldPageCount = m_memory-&gt;sizeInPages();
</del><ins>+    Wasm::PageCount oldPageCount = memory()-&gt;sizeInPages();
</ins><span class="cx"> 
</span><span class="cx">     if (!Wasm::PageCount::isValid(delta)) {
</span><span class="cx">         if (shouldThrowExceptionsOnFailure)
</span><span class="lines">@@ -101,7 +101,7 @@
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     if (delta) {
</span><del>-        bool success = m_memory-&gt;grow(newSize);
</del><ins>+        bool success = memory()-&gt;grow(newSize);
</ins><span class="cx">         if (!success) {
</span><span class="cx">             if (shouldThrowExceptionsOnFailure)
</span><span class="cx">                 throwException(exec, throwScope, createOutOfMemoryError(exec));
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorewasmjsJSWebAssemblyMemoryh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/wasm/js/JSWebAssemblyMemory.h (210228 => 210229)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/wasm/js/JSWebAssemblyMemory.h        2017-01-03 00:32:05 UTC (rev 210228)
+++ trunk/Source/JavaScriptCore/wasm/js/JSWebAssemblyMemory.h        2017-01-03 01:57:40 UTC (rev 210229)
</span><span class="lines">@@ -41,25 +41,26 @@
</span><span class="cx"> public:
</span><span class="cx">     typedef JSDestructibleObject Base;
</span><span class="cx"> 
</span><del>-    static JSWebAssemblyMemory* create(VM&amp;, Structure*, std::unique_ptr&lt;Wasm::Memory&gt;&amp;&amp;);
</del><ins>+    static JSWebAssemblyMemory* create(VM&amp;, Structure*, Wasm::Memory&amp;&amp;);
</ins><span class="cx">     static Structure* createStructure(VM&amp;, JSGlobalObject*, JSValue);
</span><span class="cx"> 
</span><span class="cx">     DECLARE_INFO;
</span><span class="cx"> 
</span><del>-    Wasm::Memory* memory() { return m_memory.get(); }
</del><ins>+    Wasm::Memory* memory() { return &amp;m_memory; }
</ins><span class="cx">     JSArrayBuffer* buffer(VM&amp; vm, JSGlobalObject*);
</span><span class="cx">     Wasm::PageCount grow(ExecState*, uint32_t delta, bool shouldThrowExceptionsOnFailure);
</span><span class="cx"> 
</span><del>-    static ptrdiff_t offsetOfMemory() { return OBJECT_OFFSETOF(JSWebAssemblyMemory, m_memory); }
</del><ins>+    static ptrdiff_t offsetOfMemory() { return OBJECT_OFFSETOF(JSWebAssemblyMemory, m_memory) + Wasm::Memory::offsetOfMemory(); }
+    static ptrdiff_t offsetOfSize() { return OBJECT_OFFSETOF(JSWebAssemblyMemory, m_memory) + Wasm::Memory::offsetOfSize(); }
</ins><span class="cx"> 
</span><span class="cx"> protected:
</span><del>-    JSWebAssemblyMemory(VM&amp;, Structure*, std::unique_ptr&lt;Wasm::Memory&gt;&amp;&amp;);
</del><ins>+    JSWebAssemblyMemory(VM&amp;, Structure*, Wasm::Memory&amp;&amp;);
</ins><span class="cx">     ~JSWebAssemblyMemory();
</span><span class="cx">     void finishCreation(VM&amp;);
</span><span class="cx">     static void destroy(JSCell*);
</span><span class="cx">     static void visitChildren(JSCell*, SlotVisitor&amp;);
</span><span class="cx"> 
</span><del>-    std::unique_ptr&lt;Wasm::Memory&gt; m_memory;
</del><ins>+    Wasm::Memory m_memory;
</ins><span class="cx">     WriteBarrier&lt;JSArrayBuffer&gt; m_bufferWrapper;
</span><span class="cx">     RefPtr&lt;ArrayBuffer&gt; m_buffer;
</span><span class="cx"> };
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorewasmjsJSWebAssemblyModulecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/wasm/js/JSWebAssemblyModule.cpp (210228 => 210229)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/wasm/js/JSWebAssemblyModule.cpp        2017-01-03 00:32:05 UTC (rev 210228)
+++ trunk/Source/JavaScriptCore/wasm/js/JSWebAssemblyModule.cpp        2017-01-03 01:57:40 UTC (rev 210229)
</span><span class="lines">@@ -38,9 +38,9 @@
</span><span class="cx"> 
</span><span class="cx"> const ClassInfo JSWebAssemblyModule::s_info = { &quot;WebAssembly.Module&quot;, &amp;Base::s_info, nullptr, CREATE_METHOD_TABLE(JSWebAssemblyModule) };
</span><span class="cx"> 
</span><del>-JSWebAssemblyModule* JSWebAssemblyModule::create(VM&amp; vm, Structure* structure, std::unique_ptr&lt;Wasm::ModuleInformation&gt;&amp;&amp; moduleInformation, Bag&lt;CallLinkInfo&gt;&amp;&amp; callLinkInfos, Vector&lt;Wasm::WasmToJSStub&gt;&amp;&amp; wasmToJSStubs, Wasm::ImmutableFunctionIndexSpace&amp;&amp; functionIndexSpace, SymbolTable* exportSymbolTable, unsigned calleeCount)
</del><ins>+JSWebAssemblyModule* JSWebAssemblyModule::create(VM&amp; vm, Structure* structure, std::unique_ptr&lt;Wasm::ModuleInformation&gt;&amp;&amp; moduleInformation, Bag&lt;CallLinkInfo&gt;&amp;&amp; callLinkInfos, Vector&lt;Wasm::WasmExitStubs&gt;&amp;&amp; wasmExitStubs, SymbolTable* exportSymbolTable, unsigned calleeCount)
</ins><span class="cx"> {
</span><del>-    auto* instance = new (NotNull, allocateCell&lt;JSWebAssemblyModule&gt;(vm.heap, allocationSize(calleeCount))) JSWebAssemblyModule(vm, structure, std::forward&lt;std::unique_ptr&lt;Wasm::ModuleInformation&gt;&gt;(moduleInformation), std::forward&lt;Bag&lt;CallLinkInfo&gt;&gt;(callLinkInfos), std::forward&lt;Vector&lt;Wasm::WasmToJSStub&gt;&gt;(wasmToJSStubs), std::forward&lt;Wasm::ImmutableFunctionIndexSpace&gt;(functionIndexSpace), calleeCount);
</del><ins>+    auto* instance = new (NotNull, allocateCell&lt;JSWebAssemblyModule&gt;(vm.heap, allocationSize(calleeCount))) JSWebAssemblyModule(vm, structure, std::forward&lt;std::unique_ptr&lt;Wasm::ModuleInformation&gt;&gt;(moduleInformation), std::forward&lt;Bag&lt;CallLinkInfo&gt;&gt;(callLinkInfos), std::forward&lt;Vector&lt;Wasm::WasmExitStubs&gt;&gt;(wasmExitStubs), calleeCount);
</ins><span class="cx">     instance-&gt;finishCreation(vm, exportSymbolTable);
</span><span class="cx">     return instance;
</span><span class="cx"> }
</span><span class="lines">@@ -50,12 +50,11 @@
</span><span class="cx">     return Structure::create(vm, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), info());
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-JSWebAssemblyModule::JSWebAssemblyModule(VM&amp; vm, Structure* structure, std::unique_ptr&lt;Wasm::ModuleInformation&gt;&amp;&amp; moduleInformation, Bag&lt;CallLinkInfo&gt;&amp;&amp; callLinkInfos, Vector&lt;Wasm::WasmToJSStub&gt;&amp;&amp; wasmToJSStubs, Wasm::ImmutableFunctionIndexSpace&amp;&amp; functionIndexSpace, unsigned calleeCount)
</del><ins>+JSWebAssemblyModule::JSWebAssemblyModule(VM&amp; vm, Structure* structure, std::unique_ptr&lt;Wasm::ModuleInformation&gt;&amp;&amp; moduleInformation, Bag&lt;CallLinkInfo&gt;&amp;&amp; callLinkInfos, Vector&lt;Wasm::WasmExitStubs&gt;&amp;&amp; wasmExitStubs, unsigned calleeCount)
</ins><span class="cx">     : Base(vm, structure)
</span><span class="cx">     , m_moduleInformation(WTFMove(moduleInformation))
</span><span class="cx">     , m_callLinkInfos(WTFMove(callLinkInfos))
</span><del>-    , m_wasmToJSStubs(WTFMove(wasmToJSStubs))
-    , m_functionIndexSpace(WTFMove(functionIndexSpace))
</del><ins>+    , m_wasmExitStubs(WTFMove(wasmExitStubs))
</ins><span class="cx">     , m_calleeCount(calleeCount)
</span><span class="cx"> {
</span><span class="cx">     memset(callees(), 0, m_calleeCount * sizeof(WriteBarrier&lt;JSWebAssemblyCallee&gt;) * 2);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorewasmjsJSWebAssemblyModuleh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/wasm/js/JSWebAssemblyModule.h (210228 => 210229)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/wasm/js/JSWebAssemblyModule.h        2017-01-03 00:32:05 UTC (rev 210228)
+++ trunk/Source/JavaScriptCore/wasm/js/JSWebAssemblyModule.h        2017-01-03 01:57:40 UTC (rev 210229)
</span><span class="lines">@@ -43,7 +43,7 @@
</span><span class="cx"> public:
</span><span class="cx">     typedef JSDestructibleObject Base;
</span><span class="cx"> 
</span><del>-    static JSWebAssemblyModule* create(VM&amp;, Structure*, std::unique_ptr&lt;Wasm::ModuleInformation&gt;&amp;&amp;, Bag&lt;CallLinkInfo&gt;&amp;&amp;, Vector&lt;Wasm::WasmToJSStub&gt;&amp;&amp;, Wasm::ImmutableFunctionIndexSpace&amp;&amp;, SymbolTable*, unsigned);
</del><ins>+    static JSWebAssemblyModule* create(VM&amp;, Structure*, std::unique_ptr&lt;Wasm::ModuleInformation&gt;&amp;&amp;, Bag&lt;CallLinkInfo&gt;&amp;&amp;, Vector&lt;Wasm::WasmExitStubs&gt;&amp;&amp;, SymbolTable*, unsigned);
</ins><span class="cx">     static Structure* createStructure(VM&amp;, JSGlobalObject*, JSValue);
</span><span class="cx"> 
</span><span class="cx">     DECLARE_INFO;
</span><span class="lines">@@ -50,12 +50,11 @@
</span><span class="cx"> 
</span><span class="cx">     const Wasm::ModuleInformation&amp; moduleInformation() const { return *m_moduleInformation.get(); }
</span><span class="cx">     SymbolTable* exportSymbolTable() const { return m_exportSymbolTable.get(); }
</span><del>-    Wasm::SignatureIndex signatureForFunctionIndexSpace(unsigned functionIndexSpace) const
</del><ins>+    Wasm::SignatureIndex signatureIndexFromFunctionIndexSpace(unsigned functionIndexSpace) const
</ins><span class="cx">     {
</span><del>-        ASSERT(functionIndexSpace &lt; m_functionIndexSpace.size);
-        return m_functionIndexSpace.buffer.get()[functionIndexSpace].signatureIndex;
</del><ins>+        return m_moduleInformation-&gt;signatureIndexFromFunctionIndexSpace(functionIndexSpace);
</ins><span class="cx">     }
</span><del>-    unsigned functionImportCount() const { return m_wasmToJSStubs.size(); }
</del><ins>+    unsigned functionImportCount() const { return m_wasmExitStubs.size(); }
</ins><span class="cx"> 
</span><span class="cx">     JSWebAssemblyCallee* jsEntrypointCalleeFromFunctionIndexSpace(unsigned functionIndexSpace)
</span><span class="cx">     {
</span><span class="lines">@@ -90,10 +89,8 @@
</span><span class="cx">         return bitwise_cast&lt;WriteBarrier&lt;JSWebAssemblyCallee&gt;*&gt;(bitwise_cast&lt;char*&gt;(this) + offsetOfCallees());
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    static ptrdiff_t offsetOfFunctionIndexSpace() { return OBJECT_OFFSETOF(JSWebAssemblyModule, m_functionIndexSpace); }
-
</del><span class="cx"> protected:
</span><del>-    JSWebAssemblyModule(VM&amp;, Structure*, std::unique_ptr&lt;Wasm::ModuleInformation&gt;&amp;&amp;, Bag&lt;CallLinkInfo&gt;&amp;&amp;, Vector&lt;Wasm::WasmToJSStub&gt;&amp;&amp;, Wasm::ImmutableFunctionIndexSpace&amp;&amp;, unsigned calleeCount);
</del><ins>+    JSWebAssemblyModule(VM&amp;, Structure*, std::unique_ptr&lt;Wasm::ModuleInformation&gt;&amp;&amp;, Bag&lt;CallLinkInfo&gt;&amp;&amp;, Vector&lt;Wasm::WasmExitStubs&gt;&amp;&amp;, unsigned calleeCount);
</ins><span class="cx">     void finishCreation(VM&amp;, SymbolTable*);
</span><span class="cx">     static void destroy(JSCell*);
</span><span class="cx">     static void visitChildren(JSCell*, SlotVisitor&amp;);
</span><span class="lines">@@ -117,8 +114,7 @@
</span><span class="cx">     std::unique_ptr&lt;Wasm::ModuleInformation&gt; m_moduleInformation;
</span><span class="cx">     Bag&lt;CallLinkInfo&gt; m_callLinkInfos;
</span><span class="cx">     WriteBarrier&lt;SymbolTable&gt; m_exportSymbolTable;
</span><del>-    Vector&lt;Wasm::WasmToJSStub&gt; m_wasmToJSStubs;
-    const Wasm::ImmutableFunctionIndexSpace m_functionIndexSpace;
</del><ins>+    Vector&lt;Wasm::WasmExitStubs&gt; m_wasmExitStubs;
</ins><span class="cx">     unsigned m_calleeCount;
</span><span class="cx"> };
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorewasmjsWebAssemblyFunctioncpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/wasm/js/WebAssemblyFunction.cpp (210228 => 210229)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/wasm/js/WebAssemblyFunction.cpp        2017-01-03 00:32:05 UTC (rev 210228)
+++ trunk/Source/JavaScriptCore/wasm/js/WebAssemblyFunction.cpp        2017-01-03 01:57:40 UTC (rev 210229)
</span><span class="lines">@@ -119,6 +119,7 @@
</span><span class="cx">     ProtoCallFrame protoCallFrame;
</span><span class="cx">     protoCallFrame.init(nullptr, wasmFunction, firstArgument, argCount, remainingArgs);
</span><span class="cx"> 
</span><ins>+    // FIXME Do away with this entire function, and only use the entrypoint generated by B3. https://bugs.webkit.org/show_bug.cgi?id=166486
</ins><span class="cx">     JSWebAssemblyInstance* prevJSWebAssemblyInstance = vm.topJSWebAssemblyInstance;
</span><span class="cx">     vm.topJSWebAssemblyInstance = wasmFunction-&gt;instance();
</span><span class="cx">     ASSERT(wasmFunction-&gt;instance());
</span><span class="lines">@@ -149,7 +150,7 @@
</span><span class="cx"> {
</span><span class="cx">     NativeExecutable* executable = vm.getHostFunction(callWebAssemblyFunction, NoIntrinsic, callHostFunctionAsConstructor, nullptr, name);
</span><span class="cx">     Structure* structure = globalObject-&gt;webAssemblyFunctionStructure();
</span><del>-    WebAssemblyFunction* function = new (NotNull, allocateCell&lt;WebAssemblyFunction&gt;(vm.heap)) WebAssemblyFunction(vm, globalObject, structure, signatureIndex);
</del><ins>+    WebAssemblyFunction* function = new (NotNull, allocateCell&lt;WebAssemblyFunction&gt;(vm.heap)) WebAssemblyFunction(vm, globalObject, structure, wasmEntrypoint, signatureIndex);
</ins><span class="cx">     function-&gt;finishCreation(vm, executable, length, name, instance, jsEntrypoint, wasmEntrypoint);
</span><span class="cx">     return function;
</span><span class="cx"> }
</span><span class="lines">@@ -157,11 +158,12 @@
</span><span class="cx"> Structure* WebAssemblyFunction::createStructure(VM&amp; vm, JSGlobalObject* globalObject, JSValue prototype)
</span><span class="cx"> {
</span><span class="cx">     ASSERT(globalObject);
</span><del>-    return Structure::create(vm, globalObject, prototype, TypeInfo(JSFunctionType, StructureFlags), info());
</del><ins>+    return Structure::create(vm, globalObject, prototype, TypeInfo(WebAssemblyFunctionType, StructureFlags), info());
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-WebAssemblyFunction::WebAssemblyFunction(VM&amp; vm, JSGlobalObject* globalObject, Structure* structure, Wasm::SignatureIndex signatureIndex)
</del><ins>+WebAssemblyFunction::WebAssemblyFunction(VM&amp; vm, JSGlobalObject* globalObject, Structure* structure, JSWebAssemblyCallee* wasmEntrypoint, Wasm::SignatureIndex signatureIndex)
</ins><span class="cx">     : Base(vm, globalObject, structure)
</span><ins>+    , m_wasmEntryPointCode(wasmEntrypoint-&gt;entrypoint())
</ins><span class="cx">     , m_signatureIndex(signatureIndex)
</span><span class="cx"> { }
</span><span class="cx"> 
</span><span class="lines">@@ -183,6 +185,7 @@
</span><span class="cx">     ASSERT(jsEntrypoint != wasmEntrypoint);
</span><span class="cx">     m_jsEntrypoint.set(vm, this, jsEntrypoint);
</span><span class="cx">     m_wasmEntrypoint.set(vm, this, wasmEntrypoint);
</span><ins>+    ASSERT(m_wasmEntrypoint-&gt;entrypoint() == m_wasmEntryPointCode);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> } // namespace JSC
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorewasmjsWebAssemblyFunctionh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/wasm/js/WebAssemblyFunction.h (210228 => 210229)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/wasm/js/WebAssemblyFunction.h        2017-01-03 00:32:05 UTC (rev 210228)
+++ trunk/Source/JavaScriptCore/wasm/js/WebAssemblyFunction.h        2017-01-03 01:57:40 UTC (rev 210229)
</span><span class="lines">@@ -54,9 +54,12 @@
</span><span class="cx"> 
</span><span class="cx">     JSWebAssemblyInstance* instance() const { return m_instance.get(); }
</span><span class="cx">     Wasm::SignatureIndex signatureIndex() const { return m_signatureIndex; }
</span><del>-    void* wasmEntrypoint() { return m_wasmEntrypoint-&gt;entrypoint(); }
</del><ins>+    void* wasmEntrypoint() { return m_wasmEntryPointCode; }
</ins><span class="cx">     void* jsEntrypoint() { return m_jsEntrypoint-&gt;entrypoint(); }
</span><span class="cx"> 
</span><ins>+    static ptrdiff_t offsetOfInstance() { return OBJECT_OFFSETOF(WebAssemblyFunction, m_instance); }
+    static ptrdiff_t offsetOfWasmEntryPointCode() { return OBJECT_OFFSETOF(WebAssemblyFunction, m_wasmEntryPointCode); }
+
</ins><span class="cx"> protected:
</span><span class="cx">     static void visitChildren(JSCell*, SlotVisitor&amp;);
</span><span class="cx"> 
</span><span class="lines">@@ -63,9 +66,10 @@
</span><span class="cx">     void finishCreation(VM&amp;, NativeExecutable*, unsigned length, const String&amp; name, JSWebAssemblyInstance*, JSWebAssemblyCallee* jsEntrypoint, JSWebAssemblyCallee* wasmEntrypoint);
</span><span class="cx"> 
</span><span class="cx"> private:
</span><del>-    WebAssemblyFunction(VM&amp;, JSGlobalObject*, Structure*, Wasm::SignatureIndex);
</del><ins>+    WebAssemblyFunction(VM&amp;, JSGlobalObject*, Structure*, JSWebAssemblyCallee*, Wasm::SignatureIndex);
</ins><span class="cx"> 
</span><span class="cx">     WriteBarrier&lt;JSWebAssemblyInstance&gt; m_instance;
</span><ins>+    void* m_wasmEntryPointCode; // Cache code pointer: allows the wasm -&gt; wasm stub to do a single load and jump instead of having dependent loads.
</ins><span class="cx">     WriteBarrier&lt;JSWebAssemblyCallee&gt; m_jsEntrypoint;
</span><span class="cx">     WriteBarrier&lt;JSWebAssemblyCallee&gt; m_wasmEntrypoint;
</span><span class="cx">     Wasm::SignatureIndex m_signatureIndex;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorewasmjsWebAssemblyInstanceConstructorcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/wasm/js/WebAssemblyInstanceConstructor.cpp (210228 => 210229)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/wasm/js/WebAssemblyInstanceConstructor.cpp        2017-01-03 00:32:05 UTC (rev 210228)
+++ trunk/Source/JavaScriptCore/wasm/js/WebAssemblyInstanceConstructor.cpp        2017-01-03 01:57:40 UTC (rev 210229)
</span><span class="lines">@@ -84,6 +84,11 @@
</span><span class="cx"> 
</span><span class="cx">     JSWebAssemblyInstance* instance = JSWebAssemblyInstance::create(vm, instanceStructure, jsModule, moduleRecord-&gt;getModuleNamespace(exec));
</span><span class="cx">     RETURN_IF_EXCEPTION(throwScope, encodedJSValue());
</span><ins>+    {
+        // Always start with a dummy Memory, so that wasm -&gt; wasm thunks avoid checking for a nullptr Memory when trying to set pinned registers.
+        Wasm::Memory memory;
+        instance-&gt;setMemory(vm, JSWebAssemblyMemory::create(vm, exec-&gt;lexicalGlobalObject()-&gt;WebAssemblyMemoryStructure(), WTFMove(memory)));
+    }
</ins><span class="cx"> 
</span><span class="cx">     // Let funcs, memories and tables be initially-empty lists of callable JavaScript objects, WebAssembly.Memory objects and WebAssembly.Table objects, respectively.
</span><span class="cx">     // Let imports be an initially-empty list of external values.
</span><span class="lines">@@ -114,18 +119,19 @@
</span><span class="cx">                 return JSValue::encode(throwException(exec, throwScope, createJSWebAssemblyLinkError(exec, vm, ASCIILiteral(&quot;import function must be callable&quot;))));
</span><span class="cx">             JSCell* cell = value.asCell();
</span><span class="cx">             // ii. If v is an Exported Function Exotic Object:
</span><del>-            if (WebAssemblyFunction* importedExports = jsDynamicCast&lt;WebAssemblyFunction*&gt;(object)) {
-                // FIXME handle Function Exotic Object properly. https://bugs.webkit.org/show_bug.cgi?id=165282
-                // a. If the signature of v does not match the signature of i, throw a TypeError.
</del><ins>+            if (WebAssemblyFunction* importedExport = jsDynamicCast&lt;WebAssemblyFunction*&gt;(cell)) {
+                // a. If the signature of v does not match the signature of i, throw a WebAssembly.LinkError.
+                Wasm::SignatureIndex importedSignatureIndex = importedExport-&gt;signatureIndex();
+                Wasm::SignatureIndex expectedSignatureIndex = moduleInformation.importFunctionSignatureIndices[import.kindIndex];
+                if (importedSignatureIndex != expectedSignatureIndex)
+                    return JSValue::encode(throwException(exec, throwScope, createJSWebAssemblyLinkError(exec, vm, ASCIILiteral(&quot;imported function's signature doesn't match the provided WebAssembly function's signature&quot;))));
</ins><span class="cx">                 // b. Let closure be v.[[Closure]].
</span><del>-                RELEASE_ASSERT_NOT_REACHED();
-                UNUSED_PARAM(importedExports);
-                break;
</del><span class="cx">             }
</span><span class="cx">             // iii. Otherwise:
</span><span class="cx">             // a. Let closure be a new host function of the given signature which calls v by coercing WebAssembly arguments to JavaScript arguments via ToJSValue and returns the result, if any, by coercing via ToWebAssemblyValue.
</span><span class="cx">             // Note: done as part of Plan compilation.
</span><span class="cx">             // iv. Append v to funcs.
</span><ins>+            // Note: adding the JSCell to the instance list fulfills closure requirements b. above (the WebAssembly.Instance wil be kept alive) and v. below (the JSFunction).
</ins><span class="cx">             instance-&gt;setImportFunction(vm, cell, numImportFunctions++);
</span><span class="cx">             // v. Append closure to imports.
</span><span class="cx">             break;
</span><span class="lines">@@ -230,7 +236,7 @@
</span><span class="cx">             RELEASE_ASSERT(!moduleInformation.memory.isImport());
</span><span class="cx">             // We create a memory when it's a memory definition.
</span><span class="cx">             bool failed;
</span><del>-            std::unique_ptr&lt;Wasm::Memory&gt; memory = std::make_unique&lt;Wasm::Memory&gt;(moduleInformation.memory.initial(), moduleInformation.memory.maximum(), failed);
</del><ins>+            Wasm::Memory memory(moduleInformation.memory.initial(), moduleInformation.memory.maximum(), failed);
</ins><span class="cx">             if (failed)
</span><span class="cx">                 return JSValue::encode(throwException(exec, throwScope, createOutOfMemoryError(exec)));
</span><span class="cx">             instance-&gt;setMemory(vm,
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorewasmjsWebAssemblyMemoryConstructorcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/wasm/js/WebAssemblyMemoryConstructor.cpp (210228 => 210229)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/wasm/js/WebAssemblyMemoryConstructor.cpp        2017-01-03 00:32:05 UTC (rev 210228)
+++ trunk/Source/JavaScriptCore/wasm/js/WebAssemblyMemoryConstructor.cpp        2017-01-03 01:57:40 UTC (rev 210229)
</span><span class="lines">@@ -97,7 +97,7 @@
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     bool failed;
</span><del>-    std::unique_ptr&lt;Wasm::Memory&gt; memory = std::make_unique&lt;Wasm::Memory&gt;(initialPageCount, maximumPageCount, failed);
</del><ins>+    Wasm::Memory memory(initialPageCount, maximumPageCount, failed);
</ins><span class="cx">     if (failed)
</span><span class="cx">         return JSValue::encode(throwException(exec, throwScope, createOutOfMemoryError(exec)));
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorewasmjsWebAssemblyModuleConstructorcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/wasm/js/WebAssemblyModuleConstructor.cpp (210228 => 210229)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/wasm/js/WebAssemblyModuleConstructor.cpp        2017-01-03 00:32:05 UTC (rev 210228)
+++ trunk/Source/JavaScriptCore/wasm/js/WebAssemblyModuleConstructor.cpp        2017-01-03 01:57:40 UTC (rev 210229)
</span><span class="lines">@@ -97,7 +97,7 @@
</span><span class="cx"> 
</span><span class="cx">     // Only wasm-internal functions have a callee, stubs to JS do not.
</span><span class="cx">     unsigned calleeCount = plan.internalFunctionCount();
</span><del>-    JSWebAssemblyModule* result = JSWebAssemblyModule::create(vm, structure, plan.takeModuleInformation(), plan.takeCallLinkInfos(), plan.takeWasmToJSStubs(), plan.takeFunctionIndexSpace(), exportSymbolTable, calleeCount);
</del><ins>+    JSWebAssemblyModule* result = JSWebAssemblyModule::create(vm, structure, plan.takeModuleInformation(), plan.takeCallLinkInfos(), plan.takeWasmExitStubs(), exportSymbolTable, calleeCount);
</ins><span class="cx">     plan.initializeCallees(state-&gt;jsCallee()-&gt;globalObject(), 
</span><span class="cx">         [&amp;] (unsigned calleeIndex, JSWebAssemblyCallee* jsEntrypointCallee, JSWebAssemblyCallee* wasmEntrypointCallee) {
</span><span class="cx">             result-&gt;setJSEntrypointCallee(vm, calleeIndex, jsEntrypointCallee);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorewasmjsWebAssemblyModuleRecordcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/wasm/js/WebAssemblyModuleRecord.cpp (210228 => 210229)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/wasm/js/WebAssemblyModuleRecord.cpp        2017-01-03 00:32:05 UTC (rev 210228)
+++ trunk/Source/JavaScriptCore/wasm/js/WebAssemblyModuleRecord.cpp        2017-01-03 01:57:40 UTC (rev 210229)
</span><span class="lines">@@ -118,7 +118,7 @@
</span><span class="cx">             //     c. Return func.
</span><span class="cx">             JSWebAssemblyCallee* jsEntrypointCallee = module-&gt;jsEntrypointCalleeFromFunctionIndexSpace(exp.kindIndex);
</span><span class="cx">             JSWebAssemblyCallee* wasmEntrypointCallee = module-&gt;wasmEntrypointCalleeFromFunctionIndexSpace(exp.kindIndex);
</span><del>-            Wasm::SignatureIndex signatureIndex = module-&gt;signatureForFunctionIndexSpace(exp.kindIndex);
</del><ins>+            Wasm::SignatureIndex signatureIndex = module-&gt;signatureIndexFromFunctionIndexSpace(exp.kindIndex);
</ins><span class="cx">             const Wasm::Signature* signature = Wasm::SignatureInformation::get(&amp;vm, signatureIndex);
</span><span class="cx">             WebAssemblyFunction* function = WebAssemblyFunction::create(vm, globalObject, signature-&gt;argumentCount(), exp.field.string(), instance, jsEntrypointCallee, wasmEntrypointCallee, signatureIndex);
</span><span class="cx">             exportedValue = function;
</span><span class="lines">@@ -133,8 +133,6 @@
</span><span class="cx">             break;
</span><span class="cx">         }
</span><span class="cx">         case Wasm::ExternalKind::Memory: {
</span><del>-            // This should be guaranteed by module verification.
-            RELEASE_ASSERT(instance-&gt;memory()); 
</del><span class="cx">             ASSERT(exp.kindIndex == 0);
</span><span class="cx"> 
</span><span class="cx">             exportedValue = instance-&gt;memory();
</span><span class="lines">@@ -175,7 +173,7 @@
</span><span class="cx">     bool hasStart = !!moduleInformation.startFunctionIndexSpace;
</span><span class="cx">     if (hasStart) {
</span><span class="cx">         auto startFunctionIndexSpace = moduleInformation.startFunctionIndexSpace.value_or(0);
</span><del>-        Wasm::SignatureIndex signatureIndex = module-&gt;signatureForFunctionIndexSpace(startFunctionIndexSpace);
</del><ins>+        Wasm::SignatureIndex signatureIndex = module-&gt;signatureIndexFromFunctionIndexSpace(startFunctionIndexSpace);
</ins><span class="cx">         const Wasm::Signature* signature = Wasm::SignatureInformation::get(&amp;vm, signatureIndex);
</span><span class="cx">         // The start function must not take any arguments or return anything. This is enforced by the parser.
</span><span class="cx">         ASSERT(!signature-&gt;argumentCount());
</span><span class="lines">@@ -238,7 +236,7 @@
</span><span class="cx"> 
</span><span class="cx">                 JSWebAssemblyCallee* jsEntrypointCallee = module-&gt;jsEntrypointCalleeFromFunctionIndexSpace(functionIndex);
</span><span class="cx">                 JSWebAssemblyCallee* wasmEntrypointCallee = module-&gt;wasmEntrypointCalleeFromFunctionIndexSpace(functionIndex);
</span><del>-                Wasm::SignatureIndex signatureIndex = module-&gt;signatureForFunctionIndexSpace(functionIndex);
</del><ins>+                Wasm::SignatureIndex signatureIndex = module-&gt;signatureIndexFromFunctionIndexSpace(functionIndex);
</ins><span class="cx">                 const Wasm::Signature* signature = Wasm::SignatureInformation::get(&amp;vm, signatureIndex);
</span><span class="cx">                 // FIXME: Say we export local function &quot;foo&quot; at funciton index 0.
</span><span class="cx">                 // What if we also set it to the table an Element w/ index 0.
</span><span class="lines">@@ -257,7 +255,6 @@
</span><span class="cx">         const Vector&lt;Wasm::Segment::Ptr&gt;&amp; data = m_instance-&gt;module()-&gt;moduleInformation().data;
</span><span class="cx">         JSWebAssemblyMemory* jsMemory = m_instance-&gt;memory();
</span><span class="cx">         if (!data.isEmpty()) {
</span><del>-            RELEASE_ASSERT(jsMemory); // It is a validation error for a Data section to exist without a Memory section or import.
</del><span class="cx">             uint8_t* memory = reinterpret_cast&lt;uint8_t*&gt;(jsMemory-&gt;memory()-&gt;memory());
</span><span class="cx">             uint64_t sizeInBytes = jsMemory-&gt;memory()-&gt;size();
</span><span class="cx">             for (auto&amp; segment : data) {
</span></span></pre>
</div>
</div>

</body>
</html>