<!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>[209652] 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/209652">209652</a></dd>
<dt>Author</dt> <dd>keith_miller@apple.com</dd>
<dt>Date</dt> <dd>2016-12-09 23:12:53 -0800 (Fri, 09 Dec 2016)</dd>
</dl>

<h3>Log Message</h3>
<pre>Wasm should support call_indirect
https://bugs.webkit.org/show_bug.cgi?id=165718

Reviewed by Filip Pizlo.

JSTests:

* wasm/Builder.js:
* wasm/function-tests/call-indirect-params.js: Added.
* wasm/function-tests/call-indirect.js: Added.
* wasm/js-api/call-indirect.js: Added.
(const.wasmModuleWhichImportJS):
(MonomorphicImport):
(Polyphic2Import):
(VirtualImport):
* wasm/wasm.json:

Source/JavaScriptCore:

This patch adds support for call_indirect. The basic framework for
an indirect call is that the module holds a buffer containing a
stub for each function in the index space. Whenever a function
needs to do an indirect call it gets a index into that table. In
order to ensure call_indirect is calling a valid function the
functionIndexSpace also needs a pointer to a canonicalized
signature. When making an indirect call, we first check the index
is in range, then check the signature matches the value we were given.

This patch also differentiates between FunctionIndexSpaces and
ImmutableFunctionIndexSpaces. Since we don't know the size of the
FunctionIndexSpace when we start parsing we need to be able to
resize the IndexSpace. However, once we have finished parsing all
the sections we want to prevent an relocation of the function
index space pointer.

* wasm/WasmB3IRGenerator.cpp:
(JSC::Wasm::B3IRGenerator::B3IRGenerator):
(JSC::Wasm::B3IRGenerator::addCall):
(JSC::Wasm::B3IRGenerator::addCallIndirect):
(JSC::Wasm::createJSToWasmWrapper):
(JSC::Wasm::parseAndCompile):
* wasm/WasmB3IRGenerator.h:
* wasm/WasmCallingConvention.h:
(JSC::Wasm::CallingConvention::setupCall):
* wasm/WasmFormat.h:
* wasm/WasmFunctionParser.h:
(JSC::Wasm::FunctionParser::setErrorMessage):
(JSC::Wasm::FunctionParser&lt;Context&gt;::FunctionParser):
(JSC::Wasm::FunctionParser&lt;Context&gt;::parseExpression):
* wasm/WasmPlan.cpp:
(JSC::Wasm::Plan::run):
* wasm/WasmPlan.h:
(JSC::Wasm::Plan::takeFunctionIndexSpace):
* wasm/WasmValidate.cpp:
(JSC::Wasm::Validate::addCallIndirect):
(JSC::Wasm::validateFunction):
* wasm/WasmValidate.h:
* wasm/js/JSWebAssemblyModule.cpp:
(JSC::JSWebAssemblyModule::create):
(JSC::JSWebAssemblyModule::JSWebAssemblyModule):
* wasm/js/JSWebAssemblyModule.h:
(JSC::JSWebAssemblyModule::signatureForFunctionIndexSpace):
(JSC::JSWebAssemblyModule::offsetOfFunctionIndexSpace):</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="#trunkJSTestswasmwasmjson">trunk/JSTests/wasm/wasm.json</a></li>
<li><a href="#trunkSourceJavaScriptCoreChangeLog">trunk/Source/JavaScriptCore/ChangeLog</a></li>
<li><a href="#trunkSourceJavaScriptCorewasmWasmB3IRGeneratorcpp">trunk/Source/JavaScriptCore/wasm/WasmB3IRGenerator.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorewasmWasmB3IRGeneratorh">trunk/Source/JavaScriptCore/wasm/WasmB3IRGenerator.h</a></li>
<li><a href="#trunkSourceJavaScriptCorewasmWasmCallingConventionh">trunk/Source/JavaScriptCore/wasm/WasmCallingConvention.h</a></li>
<li><a href="#trunkSourceJavaScriptCorewasmWasmFormath">trunk/Source/JavaScriptCore/wasm/WasmFormat.h</a></li>
<li><a href="#trunkSourceJavaScriptCorewasmWasmFunctionParserh">trunk/Source/JavaScriptCore/wasm/WasmFunctionParser.h</a></li>
<li><a href="#trunkSourceJavaScriptCorewasmWasmPlancpp">trunk/Source/JavaScriptCore/wasm/WasmPlan.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorewasmWasmPlanh">trunk/Source/JavaScriptCore/wasm/WasmPlan.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="#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="#trunkSourceJavaScriptCorewasmwasmjson">trunk/Source/JavaScriptCore/wasm/wasm.json</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#trunkJSTestswasmfunctiontestscallindirectparamsjs">trunk/JSTests/wasm/function-tests/call-indirect-params.js</a></li>
<li><a href="#trunkJSTestswasmfunctiontestscallindirectjs">trunk/JSTests/wasm/function-tests/call-indirect.js</a></li>
<li><a href="#trunkJSTestswasmjsapicallindirectjs">trunk/JSTests/wasm/js-api/call-indirect.js</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkJSTestsChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/JSTests/ChangeLog (209651 => 209652)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JSTests/ChangeLog        2016-12-10 07:08:31 UTC (rev 209651)
+++ trunk/JSTests/ChangeLog        2016-12-10 07:12:53 UTC (rev 209652)
</span><span class="lines">@@ -1,3 +1,20 @@
</span><ins>+2016-12-09  Keith Miller  &lt;keith_miller@apple.com&gt;
+
+        Wasm should support call_indirect
+        https://bugs.webkit.org/show_bug.cgi?id=165718
+
+        Reviewed by Filip Pizlo.
+
+        * wasm/Builder.js:
+        * wasm/function-tests/call-indirect-params.js: Added.
+        * wasm/function-tests/call-indirect.js: Added.
+        * wasm/js-api/call-indirect.js: Added.
+        (const.wasmModuleWhichImportJS):
+        (MonomorphicImport):
+        (Polyphic2Import):
+        (VirtualImport):
+        * wasm/wasm.json:
+
</ins><span class="cx"> 2016-12-09  JF Bastien  &lt;jfbastien@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         WebAssembly: implement data section
</span></span></pre></div>
<a id="trunkJSTestswasmBuilderjs"></a>
<div class="modfile"><h4>Modified: trunk/JSTests/wasm/Builder.js (209651 => 209652)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JSTests/wasm/Builder.js        2016-12-10 07:08:31 UTC (rev 209651)
+++ trunk/JSTests/wasm/Builder.js        2016-12-10 07:12:53 UTC (rev 209652)
</span><span class="lines">@@ -236,6 +236,7 @@
</span><span class="cx">             break;
</span><span class="cx">         case &quot;target_count&quot;: break; // improve checking https://bugs.webkit.org/show_bug.cgi?id=163421
</span><span class="cx">         case &quot;target_table&quot;: break; // improve checking https://bugs.webkit.org/show_bug.cgi?id=163421
</span><ins>+        case &quot;reserved&quot;: break; // improve checking https://bugs.webkit.org/show_bug.cgi?id=163421
</ins><span class="cx">         default: throw new Error(`Implementation problem: unhandled immediate &quot;${expect.name}&quot; on &quot;${op}&quot;`);
</span><span class="cx">         }
</span><span class="cx">     }
</span></span></pre></div>
<a id="trunkJSTestswasmfunctiontestscallindirectparamsjs"></a>
<div class="addfile"><h4>Added: trunk/JSTests/wasm/function-tests/call-indirect-params.js (0 => 209652)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JSTests/wasm/function-tests/call-indirect-params.js                                (rev 0)
+++ trunk/JSTests/wasm/function-tests/call-indirect-params.js        2016-12-10 07:12:53 UTC (rev 209652)
</span><span class="lines">@@ -0,0 +1,28 @@
</span><ins>+import Builder from '../Builder.js'
+
+const b = new Builder();
+b.Type().End()
+    .Function().End()
+    .Code()
+
+    .Function({ params: [&quot;i32&quot;], ret: &quot;i32&quot; })
+    .I32Const(1)
+    .End()
+
+    .Function({ params: [&quot;i32&quot;], ret: &quot;i32&quot; })
+    .GetLocal(0)
+    .End()
+
+    .Function({ params: [&quot;i32&quot;, &quot;i32&quot;], ret: &quot;i32&quot; })
+    .GetLocal(1)
+    .GetLocal(0)
+    .CallIndirect(0, 0)
+    .End()
+
+
+const bin = b.WebAssembly()
+bin.trim();
+testWasmModuleFunctions(bin.get(), 3, [], [],
+                        [[{ type: &quot;i32&quot;, value: 1 }, [{ type: &quot;i32&quot;, value: 0 }, { type: &quot;i32&quot;, value: 4 }]],
+                         [{ type: &quot;i32&quot;, value: 4 }, [{ type: &quot;i32&quot;, value: 1 }, { type: &quot;i32&quot;, value: 4 }]],
+                        ]);
</ins></span></pre></div>
<a id="trunkJSTestswasmfunctiontestscallindirectjs"></a>
<div class="addfile"><h4>Added: trunk/JSTests/wasm/function-tests/call-indirect.js (0 => 209652)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JSTests/wasm/function-tests/call-indirect.js                                (rev 0)
+++ trunk/JSTests/wasm/function-tests/call-indirect.js        2016-12-10 07:12:53 UTC (rev 209652)
</span><span class="lines">@@ -0,0 +1,27 @@
</span><ins>+import Builder from '../Builder.js'
+
+const b = new Builder();
+b.Type().End()
+    .Function().End()
+    .Code()
+
+    .Function({ params: [], ret: &quot;i32&quot; })
+    .I32Const(1)
+    .End()
+
+    .Function({ params: [], ret: &quot;i32&quot; })
+    .I32Const(2)
+    .End()
+
+    .Function({ params: [&quot;i32&quot;], ret: &quot;i32&quot; })
+    .GetLocal(0)
+    .CallIndirect(0, 0)
+    .End()
+
+
+const bin = b.WebAssembly()
+bin.trim();
+testWasmModuleFunctions(bin.get(), 3, [], [],
+                        [[{ type: &quot;i32&quot;, value: 1 }, [{ type: &quot;i32&quot;, value: 0 }]],
+                         [{ type: &quot;i32&quot;, value: 1 }, [{ type: &quot;i32&quot;, value: 0 }]],
+                        ]);
</ins></span></pre></div>
<a id="trunkJSTestswasmjsapicallindirectjs"></a>
<div class="addfile"><h4>Added: trunk/JSTests/wasm/js-api/call-indirect.js (0 => 209652)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JSTests/wasm/js-api/call-indirect.js                                (rev 0)
+++ trunk/JSTests/wasm/js-api/call-indirect.js        2016-12-10 07:12:53 UTC (rev 209652)
</span><span class="lines">@@ -0,0 +1,87 @@
</span><ins>+import * as assert from '../assert.js';
+import Builder from '../Builder.js';
+
+const wasmModuleWhichImportJS = () =&gt; {
+    const builder = (new Builder())
+        .Type().End()
+        .Import()
+            .Function(&quot;imp&quot;, &quot;func&quot;, { params: [&quot;i32&quot;] })
+        .End()
+        .Function().End()
+        .Export()
+            .Function(&quot;changeCounter&quot;)
+        .End()
+        .Code()
+            .Function(&quot;changeCounter&quot;, { params: [&quot;i32&quot;, &quot;i32&quot;] })
+                .I32Const(42)
+                .GetLocal(0)
+                .I32Add()
+                .GetLocal(1)
+                .CallIndirect(0, 0) // Calls func(param[0] + 42).
+            .End()
+        .End();
+    const bin = builder.WebAssembly().get();
+    const module = new WebAssembly.Module(bin);
+    return module;
+};
+
+
+(function MonomorphicImport() {
+    let counter = 0;
+    const counterSetter = v =&gt; counter = v;
+    const module = wasmModuleWhichImportJS();
+    const instance = new WebAssembly.Instance(module, { imp: { func: counterSetter } });
+    for (let i = 0; i &lt; 4096; ++i) {
+        // Invoke this a bunch of times to make sure the IC in the wasm -&gt; JS stub works correctly.
+        instance.exports.changeCounter(i, 0);
+        assert.eq(counter, i + 42);
+    }
+})();
+
+(function Polyphic2Import() {
+    let counterA = 0;
+    let counterB = undefined;
+    const counterASetter = v =&gt; counterA = v;
+    const counterBSetter = v =&gt; counterB = { valueB: v };
+    const module = wasmModuleWhichImportJS();
+    const instanceA = new WebAssembly.Instance(module, { imp: { func: counterASetter } });
+    const instanceB = new WebAssembly.Instance(module, { imp: { func: counterBSetter } });
+    for (let i = 0; i &lt; 2048; ++i) {
+        instanceA.exports.changeCounter(i, 0);
+        assert.isA(counterA, &quot;number&quot;);
+        assert.eq(counterA, i + 42);
+        instanceB.exports.changeCounter(i, 0);
+        assert.isA(counterB, &quot;object&quot;);
+        assert.eq(counterB.valueB, i + 42);
+    }
+})();
+
+(function VirtualImport() {
+    const num = 10; // It's definitely going virtual at 10!
+    let counters = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
+    const counterSetters = [
+        v =&gt; counters[0] = v,
+        v =&gt; counters[1] = v + 1,
+        v =&gt; counters[2] = v + 2,
+        v =&gt; counters[3] = v + 3,
+        v =&gt; counters[4] = v + 4,
+        v =&gt; counters[5] = v + 5,
+        v =&gt; counters[6] = v + 6,
+        v =&gt; counters[7] = v + 7,
+        v =&gt; counters[8] = v + 8,
+        v =&gt; counters[9] = v + 9,
+    ];
+    assert.eq(counters.length, num);
+    assert.eq(counterSetters.length, num);
+    const module = wasmModuleWhichImportJS();
+    let instances = [];
+    for (let i = 0; i &lt; num; ++i)
+        instances[i] = new WebAssembly.Instance(module, { imp: { func: counterSetters[i] } });
+    for (let i = 0; i &lt; 2048; ++i) {
+        for (let j = 0; j &lt; num; ++j) {
+            instances[j].exports.changeCounter(i, 0);
+            assert.isA(counters[j], &quot;number&quot;);
+            assert.eq(counters[j], i + 42 + j);
+        }
+    }
+})();
</ins></span></pre></div>
<a id="trunkJSTestswasmwasmjson"></a>
<div class="modfile"><h4>Modified: trunk/JSTests/wasm/wasm.json (209651 => 209652)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JSTests/wasm/wasm.json        2016-12-10 07:08:31 UTC (rev 209651)
+++ trunk/JSTests/wasm/wasm.json        2016-12-10 07:12:53 UTC (rev 209652)
</span><span class="lines">@@ -64,7 +64,7 @@
</span><span class="cx">         &quot;get_global&quot;:          { &quot;category&quot;: &quot;special&quot;,    &quot;value&quot;:  35, &quot;return&quot;: [&quot;global&quot;],   &quot;parameter&quot;: [],                       &quot;immediate&quot;: [{&quot;name&quot;: &quot;global_index&quot;,   &quot;type&quot;: &quot;varuint32&quot;}],                                          &quot;description&quot;: &quot;read a global variable&quot; },
</span><span class="cx">         &quot;set_global&quot;:          { &quot;category&quot;: &quot;special&quot;,    &quot;value&quot;:  36, &quot;return&quot;: [&quot;&quot;],         &quot;parameter&quot;: [&quot;global&quot;],               &quot;immediate&quot;: [{&quot;name&quot;: &quot;global_index&quot;,   &quot;type&quot;: &quot;varuint32&quot;}],                                          &quot;description&quot;: &quot;write a global variable&quot; },
</span><span class="cx">         &quot;call&quot;:                { &quot;category&quot;: &quot;call&quot;,       &quot;value&quot;:  16, &quot;return&quot;: [&quot;call&quot;],     &quot;parameter&quot;: [&quot;call&quot;],                 &quot;immediate&quot;: [{&quot;name&quot;: &quot;function_index&quot;, &quot;type&quot;: &quot;varuint32&quot;}],                                          &quot;description&quot;: &quot;call a function by its index&quot; },
</span><del>-        &quot;call_indirect&quot;:       { &quot;category&quot;: &quot;call&quot;,       &quot;value&quot;:  17, &quot;return&quot;: [&quot;call&quot;],     &quot;parameter&quot;: [&quot;call&quot;],                 &quot;immediate&quot;: [{&quot;name&quot;: &quot;type_index&quot;,     &quot;type&quot;: &quot;varuint32&quot;}],                                          &quot;description&quot;: &quot;call a function indirect with an expected signature&quot; },
</del><ins>+        &quot;call_indirect&quot;:       { &quot;category&quot;: &quot;call&quot;,       &quot;value&quot;:  17, &quot;return&quot;: [&quot;call&quot;],     &quot;parameter&quot;: [&quot;call&quot;],                 &quot;immediate&quot;: [{&quot;name&quot;: &quot;type_index&quot;,     &quot;type&quot;: &quot;varuint32&quot;}, {&quot;name&quot;: &quot;reserved&quot;,     &quot;type&quot;: &quot;varuint1&quot;}], &quot;description&quot;: &quot;call a function indirect with an expected signature&quot; },
</ins><span class="cx">         &quot;i32.load8_s&quot;:         { &quot;category&quot;: &quot;memory&quot;,     &quot;value&quot;:  44, &quot;return&quot;: [&quot;i32&quot;],      &quot;parameter&quot;: [&quot;addr&quot;],                 &quot;immediate&quot;: [{&quot;name&quot;: &quot;flags&quot;,          &quot;type&quot;: &quot;varuint32&quot;}, {&quot;name&quot;: &quot;offset&quot;, &quot;type&quot;: &quot;varuint32&quot;}], &quot;description&quot;: &quot;load from memory&quot; },
</span><span class="cx">         &quot;i32.load8_u&quot;:         { &quot;category&quot;: &quot;memory&quot;,     &quot;value&quot;:  45, &quot;return&quot;: [&quot;i32&quot;],      &quot;parameter&quot;: [&quot;addr&quot;],                 &quot;immediate&quot;: [{&quot;name&quot;: &quot;flags&quot;,          &quot;type&quot;: &quot;varuint32&quot;}, {&quot;name&quot;: &quot;offset&quot;, &quot;type&quot;: &quot;varuint32&quot;}], &quot;description&quot;: &quot;load from memory&quot; },
</span><span class="cx">         &quot;i32.load16_s&quot;:        { &quot;category&quot;: &quot;memory&quot;,     &quot;value&quot;:  46, &quot;return&quot;: [&quot;i32&quot;],      &quot;parameter&quot;: [&quot;addr&quot;],                 &quot;immediate&quot;: [{&quot;name&quot;: &quot;flags&quot;,          &quot;type&quot;: &quot;varuint32&quot;}, {&quot;name&quot;: &quot;offset&quot;, &quot;type&quot;: &quot;varuint32&quot;}], &quot;description&quot;: &quot;load from memory&quot; },
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ChangeLog (209651 => 209652)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ChangeLog        2016-12-10 07:08:31 UTC (rev 209651)
+++ trunk/Source/JavaScriptCore/ChangeLog        2016-12-10 07:12:53 UTC (rev 209652)
</span><span class="lines">@@ -1,3 +1,55 @@
</span><ins>+2016-12-09  Keith Miller  &lt;keith_miller@apple.com&gt;
+
+        Wasm should support call_indirect
+        https://bugs.webkit.org/show_bug.cgi?id=165718
+
+        Reviewed by Filip Pizlo.
+
+        This patch adds support for call_indirect. The basic framework for
+        an indirect call is that the module holds a buffer containing a
+        stub for each function in the index space. Whenever a function
+        needs to do an indirect call it gets a index into that table. In
+        order to ensure call_indirect is calling a valid function the
+        functionIndexSpace also needs a pointer to a canonicalized
+        signature. When making an indirect call, we first check the index
+        is in range, then check the signature matches the value we were given.
+
+        This patch also differentiates between FunctionIndexSpaces and
+        ImmutableFunctionIndexSpaces. Since we don't know the size of the
+        FunctionIndexSpace when we start parsing we need to be able to
+        resize the IndexSpace. However, once we have finished parsing all
+        the sections we want to prevent an relocation of the function
+        index space pointer.
+
+        * wasm/WasmB3IRGenerator.cpp:
+        (JSC::Wasm::B3IRGenerator::B3IRGenerator):
+        (JSC::Wasm::B3IRGenerator::addCall):
+        (JSC::Wasm::B3IRGenerator::addCallIndirect):
+        (JSC::Wasm::createJSToWasmWrapper):
+        (JSC::Wasm::parseAndCompile):
+        * wasm/WasmB3IRGenerator.h:
+        * wasm/WasmCallingConvention.h:
+        (JSC::Wasm::CallingConvention::setupCall):
+        * wasm/WasmFormat.h:
+        * wasm/WasmFunctionParser.h:
+        (JSC::Wasm::FunctionParser::setErrorMessage):
+        (JSC::Wasm::FunctionParser&lt;Context&gt;::FunctionParser):
+        (JSC::Wasm::FunctionParser&lt;Context&gt;::parseExpression):
+        * wasm/WasmPlan.cpp:
+        (JSC::Wasm::Plan::run):
+        * wasm/WasmPlan.h:
+        (JSC::Wasm::Plan::takeFunctionIndexSpace):
+        * wasm/WasmValidate.cpp:
+        (JSC::Wasm::Validate::addCallIndirect):
+        (JSC::Wasm::validateFunction):
+        * wasm/WasmValidate.h:
+        * wasm/js/JSWebAssemblyModule.cpp:
+        (JSC::JSWebAssemblyModule::create):
+        (JSC::JSWebAssemblyModule::JSWebAssemblyModule):
+        * wasm/js/JSWebAssemblyModule.h:
+        (JSC::JSWebAssemblyModule::signatureForFunctionIndexSpace):
+        (JSC::JSWebAssemblyModule::offsetOfFunctionIndexSpace):
+
</ins><span class="cx"> 2016-12-09  JF Bastien  &lt;jfbastien@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         WebAssembly: implement data section
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorewasmWasmB3IRGeneratorcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/wasm/WasmB3IRGenerator.cpp (209651 => 209652)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/wasm/WasmB3IRGenerator.cpp        2016-12-10 07:08:31 UTC (rev 209651)
+++ trunk/Source/JavaScriptCore/wasm/WasmB3IRGenerator.cpp        2016-12-10 07:12:53 UTC (rev 209652)
</span><span class="lines">@@ -40,6 +40,8 @@
</span><span class="cx"> #include &quot;B3VariableValue.h&quot;
</span><span class="cx"> #include &quot;B3WasmAddressValue.h&quot;
</span><span class="cx"> #include &quot;B3WasmBoundsCheckValue.h&quot;
</span><ins>+#include &quot;JSWebAssemblyInstance.h&quot;
+#include &quot;JSWebAssemblyModule.h&quot;
</ins><span class="cx"> #include &quot;VirtualRegister.h&quot;
</span><span class="cx"> #include &quot;WasmCallingConvention.h&quot;
</span><span class="cx"> #include &quot;WasmFunctionParser.h&quot;
</span><span class="lines">@@ -130,7 +132,7 @@
</span><span class="cx"> 
</span><span class="cx">     static constexpr ExpressionType emptyExpression = nullptr;
</span><span class="cx"> 
</span><del>-    B3IRGenerator(MemoryInformation&amp;, Procedure&amp;, WasmInternalFunction*, Vector&lt;UnlinkedWasmToWasmCall&gt;&amp;);
</del><ins>+    B3IRGenerator(const MemoryInformation&amp;, Procedure&amp;, WasmInternalFunction*, Vector&lt;UnlinkedWasmToWasmCall&gt;&amp;, const ImmutableFunctionIndexSpace&amp;);
</ins><span class="cx"> 
</span><span class="cx">     bool WARN_UNUSED_RETURN addArguments(const Vector&lt;Type&gt;&amp;);
</span><span class="cx">     bool WARN_UNUSED_RETURN addLocal(Type, uint32_t);
</span><span class="lines">@@ -164,7 +166,9 @@
</span><span class="cx">     bool WARN_UNUSED_RETURN endBlock(ControlEntry&amp;, ExpressionList&amp; expressionStack);
</span><span class="cx">     bool WARN_UNUSED_RETURN addEndToUnreachable(ControlEntry&amp;);
</span><span class="cx"> 
</span><del>-    bool WARN_UNUSED_RETURN addCall(unsigned calleeIndex, const Signature*, Vector&lt;ExpressionType&gt;&amp; args, ExpressionType&amp; result);
</del><ins>+    // Calls
+    bool WARN_UNUSED_RETURN addCall(uint32_t calleeIndex, const Signature*, Vector&lt;ExpressionType&gt;&amp; args, ExpressionType&amp; result);
+    bool WARN_UNUSED_RETURN addCallIndirect(const Signature*, Vector&lt;ExpressionType&gt;&amp; args, ExpressionType&amp; result);
</ins><span class="cx"> 
</span><span class="cx">     void dump(const Vector&lt;ControlEntry&gt;&amp; controlStack, const ExpressionList&amp; expressionStack);
</span><span class="cx"> 
</span><span class="lines">@@ -179,6 +183,7 @@
</span><span class="cx">     void unifyValuesWithBlock(const ExpressionList&amp; resultStack, ResultList&amp; stack);
</span><span class="cx">     Value* zeroForType(Type);
</span><span class="cx"> 
</span><ins>+    const ImmutableFunctionIndexSpace&amp; m_functionIndexSpace;
</ins><span class="cx">     Procedure&amp; m_proc;
</span><span class="cx">     BasicBlock* m_currentBlock;
</span><span class="cx">     Vector&lt;Variable*&gt; m_locals;
</span><span class="lines">@@ -186,10 +191,12 @@
</span><span class="cx">     GPRReg m_memoryBaseGPR;
</span><span class="cx">     GPRReg m_memorySizeGPR;
</span><span class="cx">     Value* m_zeroValues[numTypes];
</span><ins>+    Value* m_functionIndexSpaceValue;
</ins><span class="cx"> };
</span><span class="cx"> 
</span><del>-B3IRGenerator::B3IRGenerator(MemoryInformation&amp; memory, Procedure&amp; procedure, WasmInternalFunction* compilation, Vector&lt;UnlinkedWasmToWasmCall&gt;&amp; unlinkedWasmToWasmCalls)
-    : m_proc(procedure)
</del><ins>+B3IRGenerator::B3IRGenerator(const MemoryInformation&amp; memory, Procedure&amp; procedure, WasmInternalFunction* compilation, Vector&lt;UnlinkedWasmToWasmCall&gt;&amp; unlinkedWasmToWasmCalls, const ImmutableFunctionIndexSpace&amp; functionIndexSpace)
+    : m_functionIndexSpace(functionIndexSpace)
+    , m_proc(procedure)
</ins><span class="cx">     , m_unlinkedWasmToWasmCalls(unlinkedWasmToWasmCalls)
</span><span class="cx"> {
</span><span class="cx">     m_currentBlock = m_proc.addBlock();
</span><span class="lines">@@ -224,6 +231,8 @@
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     wasmCallingConvention().setupFrameInPrologue(compilation, m_proc, Origin(), m_currentBlock);
</span><ins>+
+    m_functionIndexSpaceValue = m_currentBlock-&gt;appendNew&lt;ConstPtrValue&gt;(m_proc, Origin(), functionIndexSpace.buffer.get());
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> Value* B3IRGenerator::zeroForType(Type type)
</span><span class="lines">@@ -592,7 +601,7 @@
</span><span class="cx">     return true;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-bool B3IRGenerator::addCall(unsigned functionIndex, const Signature* signature, Vector&lt;ExpressionType&gt;&amp; args, ExpressionType&amp; result)
</del><ins>+bool B3IRGenerator::addCall(uint32_t functionIndex, const Signature* signature, Vector&lt;ExpressionType&gt;&amp; args, ExpressionType&amp; result)
</ins><span class="cx"> {
</span><span class="cx">     ASSERT(signature-&gt;arguments.size() == args.size());
</span><span class="cx"> 
</span><span class="lines">@@ -618,6 +627,57 @@
</span><span class="cx">     return true;
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+bool B3IRGenerator::addCallIndirect(const Signature* signature, Vector&lt;ExpressionType&gt;&amp; args, ExpressionType&amp; result)
+{
+    ExpressionType calleeIndex = args.takeLast();
+    ASSERT(signature-&gt;arguments.size() == args.size());
+
+    // Check the index we are looking for is valid.
+    {
+        ExpressionType maxValidIndex = m_currentBlock-&gt;appendIntConstant(m_proc, Origin(), Int32, m_functionIndexSpace.size);
+        CheckValue* check = m_currentBlock-&gt;appendNew&lt;CheckValue&gt;(m_proc, Check, Origin(),
+            m_currentBlock-&gt;appendNew&lt;Value&gt;(m_proc, Equal, Origin(), m_zeroValues[linearizeType(I32)],
+                m_currentBlock-&gt;appendNew&lt;Value&gt;(m_proc, LessThan, Origin(), calleeIndex, maxValidIndex)));
+
+        check-&gt;setGenerator([] (CCallHelpers&amp; jit, const B3::StackmapGenerationParams&amp;) {
+            jit.breakpoint();
+        });
+    }
+
+    // Compute the offset in the function index space we are looking for.
+    ExpressionType offset = m_currentBlock-&gt;appendNew&lt;Value&gt;(m_proc, Mul, Origin(),
+        m_currentBlock-&gt;appendNew&lt;Value&gt;(m_proc, ZExt32, Origin(), calleeIndex),
+        m_currentBlock-&gt;appendIntConstant(m_proc, Origin(), pointerType(), sizeof(CallableFunction)));
+    ExpressionType callableFunction = m_currentBlock-&gt;appendNew&lt;Value&gt;(m_proc, Add, Origin(), m_functionIndexSpaceValue, offset);
+
+    // Check the signature matches the value we expect.
+    {
+        ExpressionType calleeSignature = m_currentBlock-&gt;appendNew&lt;MemoryValue&gt;(m_proc, Load, pointerType(), Origin(), callableFunction, OBJECT_OFFSETOF(CallableFunction, signature));
+        ExpressionType expectedSignature = m_currentBlock-&gt;appendNew&lt;ConstPtrValue&gt;(m_proc, Origin(), signature);
+        CheckValue* check = m_currentBlock-&gt;appendNew&lt;CheckValue&gt;(m_proc, Check, Origin(),
+            m_currentBlock-&gt;appendNew&lt;Value&gt;(m_proc, NotEqual, Origin(), calleeSignature, expectedSignature));
+
+        check-&gt;setGenerator([] (CCallHelpers&amp; jit, const B3::StackmapGenerationParams&amp;) {
+            jit.breakpoint();
+        });
+    }
+
+    ExpressionType calleeCode = m_currentBlock-&gt;appendNew&lt;MemoryValue&gt;(m_proc, Load, pointerType(), Origin(), callableFunction, OBJECT_OFFSETOF(CallableFunction, code));
+
+    result = wasmCallingConvention().setupCall(m_proc, m_currentBlock, Origin(), args, toB3Type(signature-&gt;returnType),
+        [&amp;] (PatchpointValue* patchpoint) {
+            patchpoint-&gt;effects.writesPinned = true;
+            patchpoint-&gt;effects.readsPinned = true;
+
+            patchpoint-&gt;append(calleeCode, ValueRep::SomeRegister);
+
+            patchpoint-&gt;setGenerator([=] (CCallHelpers&amp; jit, const B3::StackmapGenerationParams&amp; params) {
+                jit.call(params[0].gpr());
+            });
+        });
+    return true;
+}
+
</ins><span class="cx"> void B3IRGenerator::unify(Variable* variable, ExpressionType source)
</span><span class="cx"> {
</span><span class="cx">     m_currentBlock-&gt;appendNew&lt;VariableValue&gt;(m_proc, Set, Origin(), variable, source);
</span><span class="lines">@@ -657,7 +717,7 @@
</span><span class="cx">     dataLogLn(&quot;\n&quot;);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-static std::unique_ptr&lt;Compilation&gt; createJSToWasmWrapper(VM&amp; vm, const Signature* signature, MacroAssemblerCodePtr mainFunction, MemoryInformation&amp; memory)
</del><ins>+static std::unique_ptr&lt;Compilation&gt; createJSToWasmWrapper(VM&amp; vm, const Signature* signature, MacroAssemblerCodePtr mainFunction, const MemoryInformation&amp; memory)
</ins><span class="cx"> {
</span><span class="cx">     Procedure proc;
</span><span class="cx">     BasicBlock* block = proc.addBlock();
</span><span class="lines">@@ -737,13 +797,13 @@
</span><span class="cx">     return std::make_unique&lt;Compilation&gt;(vm, proc);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-std::unique_ptr&lt;WasmInternalFunction&gt; parseAndCompile(VM&amp; vm, const uint8_t* functionStart, size_t functionLength, MemoryInformation&amp; memory, const Signature* signature, Vector&lt;UnlinkedWasmToWasmCall&gt;&amp; unlinkedWasmToWasmCalls, const FunctionIndexSpace&amp; functionIndexSpace, unsigned optLevel)
</del><ins>+std::unique_ptr&lt;WasmInternalFunction&gt; parseAndCompile(VM&amp; vm, 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)
</ins><span class="cx"> {
</span><span class="cx">     auto result = std::make_unique&lt;WasmInternalFunction&gt;();
</span><span class="cx"> 
</span><span class="cx">     Procedure procedure;
</span><del>-    B3IRGenerator context(memory, procedure, result.get(), unlinkedWasmToWasmCalls);
-    FunctionParser&lt;B3IRGenerator&gt; parser(context, functionStart, functionLength, signature, functionIndexSpace);
</del><ins>+    B3IRGenerator context(info.memory, procedure, result.get(), unlinkedWasmToWasmCalls, functionIndexSpace);
+    FunctionParser&lt;B3IRGenerator&gt; parser(context, functionStart, functionLength, signature, functionIndexSpace, info);
</ins><span class="cx">     if (!parser.parse())
</span><span class="cx">         RELEASE_ASSERT_NOT_REACHED();
</span><span class="cx"> 
</span><span class="lines">@@ -757,7 +817,7 @@
</span><span class="cx">         dataLog(&quot;Post SSA: &quot;, procedure);
</span><span class="cx"> 
</span><span class="cx">     result-&gt;code = std::make_unique&lt;Compilation&gt;(vm, procedure, optLevel);
</span><del>-    result-&gt;jsToWasmEntryPoint = createJSToWasmWrapper(vm, signature, result-&gt;code-&gt;code(), memory);
</del><ins>+    result-&gt;jsToWasmEntryPoint = createJSToWasmWrapper(vm, signature, result-&gt;code-&gt;code(), info.memory);
</ins><span class="cx">     return result;
</span><span class="cx"> }
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorewasmWasmB3IRGeneratorh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/wasm/WasmB3IRGenerator.h (209651 => 209652)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/wasm/WasmB3IRGenerator.h        2016-12-10 07:08:31 UTC (rev 209651)
+++ trunk/Source/JavaScriptCore/wasm/WasmB3IRGenerator.h        2016-12-10 07:12:53 UTC (rev 209652)
</span><span class="lines">@@ -37,7 +37,7 @@
</span><span class="cx"> 
</span><span class="cx"> class MemoryInformation;
</span><span class="cx"> 
</span><del>-std::unique_ptr&lt;WasmInternalFunction&gt; parseAndCompile(VM&amp;, const uint8_t*, size_t, MemoryInformation&amp;, const Signature*, Vector&lt;UnlinkedWasmToWasmCall&gt;&amp;, const FunctionIndexSpace&amp;, unsigned optLevel = 1);
</del><ins>+std::unique_ptr&lt;WasmInternalFunction&gt; parseAndCompile(VM&amp;, const uint8_t*, size_t, const Signature*, Vector&lt;UnlinkedWasmToWasmCall&gt;&amp;, const ImmutableFunctionIndexSpace&amp;, const ModuleInformation&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="trunkSourceJavaScriptCorewasmWasmCallingConventionh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/wasm/WasmCallingConvention.h (209651 => 209652)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/wasm/WasmCallingConvention.h        2016-12-10 07:08:31 UTC (rev 209651)
+++ trunk/Source/JavaScriptCore/wasm/WasmCallingConvention.h        2016-12-10 07:12:53 UTC (rev 209652)
</span><span class="lines">@@ -163,8 +163,8 @@
</span><span class="cx">         B3::PatchpointValue* patchpoint = block-&gt;appendNew&lt;B3::PatchpointValue&gt;(proc, returnType, origin);
</span><span class="cx">         patchpoint-&gt;clobberEarly(RegisterSet::macroScratchRegisters());
</span><span class="cx">         patchpoint-&gt;clobberLate(RegisterSet::volatileRegistersForJSCall());
</span><ins>+        patchpointFunctor(patchpoint);
</ins><span class="cx">         patchpoint-&gt;appendVector(constrainedArguments);
</span><del>-        patchpointFunctor(patchpoint);
</del><span class="cx"> 
</span><span class="cx">         switch (returnType) {
</span><span class="cx">         case B3::Void:
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorewasmWasmFormath"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/wasm/WasmFormat.h (209651 => 209652)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/wasm/WasmFormat.h        2016-12-10 07:08:31 UTC (rev 209651)
+++ trunk/Source/JavaScriptCore/wasm/WasmFormat.h        2016-12-10 07:12:53 UTC (rev 209652)
</span><span class="lines">@@ -187,6 +187,12 @@
</span><span class="cx"> };
</span><span class="cx"> typedef Vector&lt;CallableFunction&gt; FunctionIndexSpace;
</span><span class="cx"> 
</span><ins>+
+struct ImmutableFunctionIndexSpace {
+    MallocPtr&lt;CallableFunction&gt; buffer;
+    size_t size;
+};
+
</ins><span class="cx"> } } // namespace JSC::Wasm
</span><span class="cx"> 
</span><span class="cx"> #endif // ENABLE(WEBASSEMBLY)
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorewasmWasmFunctionParserh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/wasm/WasmFunctionParser.h (209651 => 209652)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/wasm/WasmFunctionParser.h        2016-12-10 07:08:31 UTC (rev 209651)
+++ trunk/Source/JavaScriptCore/wasm/WasmFunctionParser.h        2016-12-10 07:12:53 UTC (rev 209652)
</span><span class="lines">@@ -45,7 +45,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(Context&amp;, const uint8_t* functionStart, size_t functionLength, const Signature*, const FunctionIndexSpace&amp;);
</del><ins>+    FunctionParser(Context&amp;, const uint8_t* functionStart, size_t functionLength, const Signature*, const ImmutableFunctionIndexSpace&amp;, const ModuleInformation&amp;);
</ins><span class="cx"> 
</span><span class="cx">     bool WARN_UNUSED_RETURN parse();
</span><span class="cx"> 
</span><span class="lines">@@ -71,22 +71,28 @@
</span><span class="cx">     template&lt;OpType&gt;
</span><span class="cx">     bool WARN_UNUSED_RETURN binaryCase();
</span><span class="cx"> 
</span><del>-    void setErrorMessage(String&amp;&amp; message) { m_context.setErrorMessage(WTFMove(message)); }
</del><ins>+    bool setErrorMessage(String&amp;&amp; message)
+    {
+        m_context.setErrorMessage(WTFMove(message));
+        return false;
+    }
</ins><span class="cx"> 
</span><span class="cx">     Context&amp; m_context;
</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 FunctionIndexSpace&amp; m_functionIndexSpace;
</del><ins>+    const ImmutableFunctionIndexSpace&amp; m_functionIndexSpace;
+    const ModuleInformation&amp; m_info;
</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(Context&amp; context, const uint8_t* functionStart, size_t functionLength, const Signature* signature, const FunctionIndexSpace&amp; functionIndexSpace)
</del><ins>+FunctionParser&lt;Context&gt;::FunctionParser(Context&amp; context, const uint8_t* functionStart, size_t functionLength, const Signature* signature, const ImmutableFunctionIndexSpace&amp; functionIndexSpace, const ModuleInformation&amp; info)
</ins><span class="cx">     : Parser(functionStart, functionLength)
</span><span class="cx">     , m_context(context)
</span><span class="cx">     , m_signature(signature)
</span><span class="cx">     , m_functionIndexSpace(functionIndexSpace)
</span><ins>+    , m_info(info)
</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">@@ -350,10 +356,10 @@
</span><span class="cx">         if (!parseVarUInt32(functionIndex))
</span><span class="cx">             return false;
</span><span class="cx"> 
</span><del>-        if (functionIndex &gt;= m_functionIndexSpace.size())
</del><ins>+        if (functionIndex &gt;= m_functionIndexSpace.size)
</ins><span class="cx">             return false;
</span><span class="cx"> 
</span><del>-        const Signature* calleeSignature = m_functionIndexSpace[functionIndex].signature;
</del><ins>+        const Signature* calleeSignature = m_functionIndexSpace.buffer.get()[functionIndex].signature;
</ins><span class="cx"> 
</span><span class="cx">         if (calleeSignature-&gt;arguments.size() &gt; m_expressionStack.size())
</span><span class="cx">             return false;
</span><span class="lines">@@ -375,6 +381,42 @@
</span><span class="cx">         return true;
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    case OpType::CallIndirect: {
+        uint32_t signatureIndex;
+        if (!parseVarUInt32(signatureIndex))
+            return false;
+
+        uint8_t reserved;
+        if (!parseVarUInt1(reserved))
+            return false;
+
+        if (m_info.signatures.size() &lt;= signatureIndex)
+            return setErrorMessage(&quot;Tried to use a signature outside the range of valid signatures&quot;);
+
+        const Signature* calleeSignature = &amp;m_info.signatures[signatureIndex];
+        size_t argumentCount = calleeSignature-&gt;arguments.size() + 1; // Add the callee's index.
+        if (argumentCount &gt; m_expressionStack.size())
+            return setErrorMessage(&quot;Not enough values on the stack for call_indirect&quot;);
+
+        Vector&lt;ExpressionType&gt; args;
+        if (!args.tryReserveCapacity(argumentCount))
+            return setErrorMessage(&quot;Out of memory&quot;);
+
+        size_t firstArgumentIndex = m_expressionStack.size() - argumentCount;
+        for (unsigned i = firstArgumentIndex; i &lt; m_expressionStack.size(); ++i)
+            args.uncheckedAppend(m_expressionStack[i]);
+        m_expressionStack.shrink(firstArgumentIndex);
+
+        ExpressionType result = Context::emptyExpression;
+        if (!m_context.addCallIndirect(calleeSignature, args, result))
+            return false;
+
+        if (result != Context::emptyExpression)
+            m_expressionStack.append(result);
+
+        return true;
+    }
+
</ins><span class="cx">     case OpType::Block: {
</span><span class="cx">         Type inlineSignature;
</span><span class="cx">         if (!parseResultType(inlineSignature))
</span><span class="lines">@@ -517,8 +559,7 @@
</span><span class="cx">     case OpType::GrowMemory:
</span><span class="cx">     case OpType::CurrentMemory:
</span><span class="cx">     case OpType::GetGlobal:
</span><del>-    case OpType::SetGlobal:
-    case OpType::CallIndirect: {
</del><ins>+    case OpType::SetGlobal: {
</ins><span class="cx">         // FIXME: Not yet implemented.
</span><span class="cx">         return false;
</span><span class="cx">     }
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorewasmWasmPlancpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/wasm/WasmPlan.cpp (209651 => 209652)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/wasm/WasmPlan.cpp        2016-12-10 07:08:31 UTC (rev 209651)
+++ trunk/Source/JavaScriptCore/wasm/WasmPlan.cpp        2016-12-10 07:12:53 UTC (rev 209652)
</span><span class="lines">@@ -72,7 +72,8 @@
</span><span class="cx">         }
</span><span class="cx">         m_moduleInformation = WTFMove(moduleParser.moduleInformation());
</span><span class="cx">         m_functionLocationInBinary = WTFMove(moduleParser.functionLocationInBinary());
</span><del>-        m_functionIndexSpace = WTFMove(moduleParser.functionIndexSpace());
</del><ins>+        m_functionIndexSpace.size = moduleParser.functionIndexSpace().size();
+        m_functionIndexSpace.buffer = moduleParser.functionIndexSpace().releaseBuffer();
</ins><span class="cx">     }
</span><span class="cx">     if (verbose)
</span><span class="cx">         dataLogLn(&quot;Parsed module.&quot;);
</span><span class="lines">@@ -103,7 +104,7 @@
</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">         Signature* signature = m_moduleInformation-&gt;importFunctions.at(import-&gt;kindIndex);
</span><span class="cx">         m_wasmToJSStubs.uncheckedAppend(importStubGenerator(m_vm, m_callLinkInfos, signature, importFunctionIndex));
</span><del>-        m_functionIndexSpace[importFunctionIndex].code = m_wasmToJSStubs[importFunctionIndex].code().executableAddress();
</del><ins>+        m_functionIndexSpace.buffer.get()[importFunctionIndex].code = m_wasmToJSStubs[importFunctionIndex].code().executableAddress();
</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">@@ -114,9 +115,9 @@
</span><span class="cx">         ASSERT(functionLength &lt;= m_sourceLength);
</span><span class="cx">         Signature* signature = m_moduleInformation-&gt;internalFunctionSignatures[functionIndex];
</span><span class="cx">         unsigned functionIndexSpace = m_wasmToJSStubs.size() + functionIndex;
</span><del>-        ASSERT(m_functionIndexSpace[functionIndexSpace].signature == signature);
</del><ins>+        ASSERT(m_functionIndexSpace.buffer.get()[functionIndexSpace].signature == signature);
</ins><span class="cx"> 
</span><del>-        String error = validateFunction(functionStart, functionLength, signature, m_functionIndexSpace, m_moduleInformation-&gt;memory);
</del><ins>+        String error = validateFunction(functionStart, functionLength, signature, m_functionIndexSpace, *m_moduleInformation);
</ins><span class="cx">         if (!error.isNull()) {
</span><span class="cx">             if (verbose) {
</span><span class="cx">                 for (unsigned i = 0; i &lt; functionLength; ++i)
</span><span class="lines">@@ -128,14 +129,14 @@
</span><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         unlinkedWasmToWasmCalls.uncheckedAppend(Vector&lt;UnlinkedWasmToWasmCall&gt;());
</span><del>-        m_wasmInternalFunctions.uncheckedAppend(parseAndCompile(*m_vm, functionStart, functionLength, m_moduleInformation-&gt;memory, signature, unlinkedWasmToWasmCalls.at(functionIndex), m_functionIndexSpace));
-        m_functionIndexSpace[functionIndexSpace].code = m_wasmInternalFunctions[functionIndex]-&gt;code-&gt;code().executableAddress();
</del><ins>+        m_wasmInternalFunctions.uncheckedAppend(parseAndCompile(*m_vm, functionStart, functionLength, signature, unlinkedWasmToWasmCalls.at(functionIndex), m_functionIndexSpace, *m_moduleInformation));
+        m_functionIndexSpace.buffer.get()[functionIndexSpace].code = m_wasmInternalFunctions[functionIndex]-&gt;code-&gt;code().executableAddress();
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     // Patch the call sites for each WebAssembly function.
</span><span class="cx">     for (auto&amp; unlinked : unlinkedWasmToWasmCalls) {
</span><span class="cx">         for (auto&amp; call : unlinked)
</span><del>-            MacroAssembler::repatchCall(call.callLocation, CodeLocationLabel(m_functionIndexSpace[call.functionIndex].code));
</del><ins>+            MacroAssembler::repatchCall(call.callLocation, CodeLocationLabel(m_functionIndexSpace.buffer.get()[call.functionIndex].code));
</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 (209651 => 209652)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/wasm/WasmPlan.h        2016-12-10 07:08:31 UTC (rev 209651)
+++ trunk/Source/JavaScriptCore/wasm/WasmPlan.h        2016-12-10 07:12:53 UTC (rev 209652)
</span><span class="lines">@@ -95,7 +95,7 @@
</span><span class="cx">         return WTFMove(m_wasmToJSStubs);
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    FunctionIndexSpace&amp;&amp; takeFunctionIndexSpace()
</del><ins>+    ImmutableFunctionIndexSpace&amp;&amp; takeFunctionIndexSpace()
</ins><span class="cx">     {
</span><span class="cx">         RELEASE_ASSERT(!failed());
</span><span class="cx">         return WTFMove(m_functionIndexSpace);
</span><span class="lines">@@ -107,7 +107,7 @@
</span><span class="cx">     Bag&lt;CallLinkInfo&gt; m_callLinkInfos;
</span><span class="cx">     Vector&lt;WasmToJSStub&gt; m_wasmToJSStubs;
</span><span class="cx">     Vector&lt;std::unique_ptr&lt;WasmInternalFunction&gt;&gt; m_wasmInternalFunctions;
</span><del>-    FunctionIndexSpace m_functionIndexSpace;
</del><ins>+    ImmutableFunctionIndexSpace m_functionIndexSpace;
</ins><span class="cx"> 
</span><span class="cx">     VM* m_vm;
</span><span class="cx">     const uint8_t* m_source;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorewasmWasmValidatecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/wasm/WasmValidate.cpp (209651 => 209652)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/wasm/WasmValidate.cpp        2016-12-10 07:08:31 UTC (rev 209651)
+++ trunk/Source/JavaScriptCore/wasm/WasmValidate.cpp        2016-12-10 07:12:53 UTC (rev 209652)
</span><span class="lines">@@ -110,8 +110,9 @@
</span><span class="cx">     bool WARN_UNUSED_RETURN endBlock(ControlEntry&amp;, ExpressionList&amp; expressionStack);
</span><span class="cx">     bool WARN_UNUSED_RETURN addEndToUnreachable(ControlEntry&amp;);
</span><span class="cx"> 
</span><del>-
</del><ins>+    // Calls
</ins><span class="cx">     bool WARN_UNUSED_RETURN addCall(unsigned calleeIndex, const Signature*, const Vector&lt;ExpressionType&gt;&amp; args, ExpressionType&amp; result);
</span><ins>+    bool WARN_UNUSED_RETURN addCallIndirect(const Signature*, const Vector&lt;ExpressionType&gt;&amp; args, ExpressionType&amp; result);
</ins><span class="cx"> 
</span><span class="cx">     void dump(const Vector&lt;ControlEntry&gt;&amp; controlStack, const ExpressionList&amp; expressionStack);
</span><span class="cx"> 
</span><span class="lines">@@ -347,6 +348,35 @@
</span><span class="cx">     return true;
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+bool Validate::addCallIndirect(const Signature* signature, const Vector&lt;ExpressionType&gt;&amp; args, ExpressionType&amp; result)
+{
+    const auto argumentCount = signature-&gt;arguments.size();
+    if (argumentCount != args.size() - 1) {
+        StringBuilder builder;
+        builder.append(&quot;Arity mismatch in call_indirect, expected: &quot;);
+        builder.appendNumber(signature-&gt;arguments.size());
+        builder.append(&quot; but got: &quot;);
+        builder.appendNumber(args.size());
+        m_errorMessage = builder.toString();
+        return false;
+    }
+
+    for (unsigned i = 0; i &lt; argumentCount; ++i) {
+        if (args[i] != signature-&gt;arguments[i]) {
+            m_errorMessage = makeString(&quot;Expected argument type: &quot;, toString(signature-&gt;arguments[i]), &quot; does not match passed argument type: &quot;, toString(args[i]));
+            return false;
+        }
+    }
+
+    if (args.last() != I32) {
+        m_errorMessage = makeString(&quot;Expected call_indirect target index to have type: i32 but got type: &quot;, toString(args.last()));
+        return false;
+    }
+    
+    result = signature-&gt;returnType;
+    return true;
+}
+
</ins><span class="cx"> bool Validate::unify(const ExpressionList&amp; values, const ControlType&amp; block)
</span><span class="cx"> {
</span><span class="cx">     ASSERT(values.size() &lt;= 1);
</span><span class="lines">@@ -371,10 +401,11 @@
</span><span class="cx">     // Think of this as penance for the sin of bad error messages.
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-String validateFunction(const uint8_t* source, size_t length, const Signature* signature, const FunctionIndexSpace&amp; functionIndexSpace, const MemoryInformation&amp; memory)
</del><ins>+String validateFunction(const uint8_t* source, size_t length, const Signature* signature, const ImmutableFunctionIndexSpace&amp; functionIndexSpace, const ModuleInformation&amp; info)
</ins><span class="cx"> {
</span><del>-    Validate context(signature-&gt;returnType, memory);
-    FunctionParser&lt;Validate&gt; validator(context, source, length, signature, functionIndexSpace);
</del><ins>+    Validate context(signature-&gt;returnType, info.memory);
+    FunctionParser&lt;Validate&gt; validator(context, source, length, signature, functionIndexSpace, info);
+
</ins><span class="cx">     if (!validator.parse()) {
</span><span class="cx">         // FIXME: add better location information here. see: https://bugs.webkit.org/show_bug.cgi?id=164288
</span><span class="cx">         // FIXME: We should never not have an error message if we return false.
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorewasmWasmValidateh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/wasm/WasmValidate.h (209651 => 209652)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/wasm/WasmValidate.h        2016-12-10 07:08:31 UTC (rev 209651)
+++ trunk/Source/JavaScriptCore/wasm/WasmValidate.h        2016-12-10 07:12:53 UTC (rev 209652)
</span><span class="lines">@@ -31,7 +31,7 @@
</span><span class="cx"> 
</span><span class="cx"> namespace JSC { namespace Wasm {
</span><span class="cx"> 
</span><del>-String validateFunction(const uint8_t*, size_t, const Signature*, const FunctionIndexSpace&amp;, const MemoryInformation&amp;);
</del><ins>+String validateFunction(const uint8_t*, size_t, const Signature*, const ImmutableFunctionIndexSpace&amp;, const ModuleInformation&amp;);
</ins><span class="cx"> 
</span><span class="cx"> } } // namespace JSC::Wasm
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorewasmjsJSWebAssemblyModulecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/wasm/js/JSWebAssemblyModule.cpp (209651 => 209652)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/wasm/js/JSWebAssemblyModule.cpp        2016-12-10 07:08:31 UTC (rev 209651)
+++ trunk/Source/JavaScriptCore/wasm/js/JSWebAssemblyModule.cpp        2016-12-10 07:12:53 UTC (rev 209652)
</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::FunctionIndexSpace&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::WasmToJSStub&gt;&amp;&amp; wasmToJSStubs, Wasm::ImmutableFunctionIndexSpace&amp;&amp; functionIndexSpace, 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::FunctionIndexSpace&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::WasmToJSStub&gt;&gt;(wasmToJSStubs), std::forward&lt;Wasm::ImmutableFunctionIndexSpace&gt;(functionIndexSpace), 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,7 +50,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>-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::FunctionIndexSpace&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::WasmToJSStub&gt;&amp;&amp; wasmToJSStubs, Wasm::ImmutableFunctionIndexSpace&amp;&amp; functionIndexSpace, 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></span></pre></div>
<a id="trunkSourceJavaScriptCorewasmjsJSWebAssemblyModuleh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/wasm/js/JSWebAssemblyModule.h (209651 => 209652)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/wasm/js/JSWebAssemblyModule.h        2016-12-10 07:08:31 UTC (rev 209651)
+++ trunk/Source/JavaScriptCore/wasm/js/JSWebAssemblyModule.h        2016-12-10 07:12:53 UTC (rev 209652)
</span><span class="lines">@@ -42,7 +42,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::FunctionIndexSpace&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::WasmToJSStub&gt;&amp;&amp;, Wasm::ImmutableFunctionIndexSpace&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">@@ -49,7 +49,7 @@
</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::Signature* signatureForFunctionIndexSpace(unsigned functionIndexSpace) const { return m_functionIndexSpace.at(functionIndexSpace).signature; }
</del><ins>+    Wasm::Signature* signatureForFunctionIndexSpace(unsigned functionIndexSpace) const { ASSERT(functionIndexSpace &lt; m_functionIndexSpace.size); return m_functionIndexSpace.buffer.get()[functionIndexSpace].signature; }
</ins><span class="cx">     unsigned importCount() const { return m_wasmToJSStubs.size(); }
</span><span class="cx"> 
</span><span class="cx">     JSWebAssemblyCallee* calleeFromFunctionIndexSpace(unsigned functionIndexSpace)
</span><span class="lines">@@ -65,8 +65,10 @@
</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><ins>+    static ptrdiff_t offsetOfFunctionIndexSpace() { return OBJECT_OFFSETOF(JSWebAssemblyModule, m_functionIndexSpace); }
+
</ins><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::FunctionIndexSpace&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::WasmToJSStub&gt;&amp;&amp;, Wasm::ImmutableFunctionIndexSpace&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">@@ -86,7 +88,7 @@
</span><span class="cx">     Bag&lt;CallLinkInfo&gt; m_callLinkInfos;
</span><span class="cx">     WriteBarrier&lt;SymbolTable&gt; m_exportSymbolTable;
</span><span class="cx">     Vector&lt;Wasm::WasmToJSStub&gt; m_wasmToJSStubs;
</span><del>-    Wasm::FunctionIndexSpace m_functionIndexSpace;
</del><ins>+    const Wasm::ImmutableFunctionIndexSpace m_functionIndexSpace;
</ins><span class="cx">     unsigned m_calleeCount;
</span><span class="cx"> };
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorewasmwasmjson"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/wasm/wasm.json (209651 => 209652)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/wasm/wasm.json        2016-12-10 07:08:31 UTC (rev 209651)
+++ trunk/Source/JavaScriptCore/wasm/wasm.json        2016-12-10 07:12:53 UTC (rev 209652)
</span><span class="lines">@@ -64,7 +64,7 @@
</span><span class="cx">         &quot;get_global&quot;:          { &quot;category&quot;: &quot;special&quot;,    &quot;value&quot;:  35, &quot;return&quot;: [&quot;global&quot;],   &quot;parameter&quot;: [],                       &quot;immediate&quot;: [{&quot;name&quot;: &quot;global_index&quot;,   &quot;type&quot;: &quot;varuint32&quot;}],                                          &quot;description&quot;: &quot;read a global variable&quot; },
</span><span class="cx">         &quot;set_global&quot;:          { &quot;category&quot;: &quot;special&quot;,    &quot;value&quot;:  36, &quot;return&quot;: [&quot;&quot;],         &quot;parameter&quot;: [&quot;global&quot;],               &quot;immediate&quot;: [{&quot;name&quot;: &quot;global_index&quot;,   &quot;type&quot;: &quot;varuint32&quot;}],                                          &quot;description&quot;: &quot;write a global variable&quot; },
</span><span class="cx">         &quot;call&quot;:                { &quot;category&quot;: &quot;call&quot;,       &quot;value&quot;:  16, &quot;return&quot;: [&quot;call&quot;],     &quot;parameter&quot;: [&quot;call&quot;],                 &quot;immediate&quot;: [{&quot;name&quot;: &quot;function_index&quot;, &quot;type&quot;: &quot;varuint32&quot;}],                                          &quot;description&quot;: &quot;call a function by its index&quot; },
</span><del>-        &quot;call_indirect&quot;:       { &quot;category&quot;: &quot;call&quot;,       &quot;value&quot;:  17, &quot;return&quot;: [&quot;call&quot;],     &quot;parameter&quot;: [&quot;call&quot;],                 &quot;immediate&quot;: [{&quot;name&quot;: &quot;type_index&quot;,     &quot;type&quot;: &quot;varuint32&quot;}],                                          &quot;description&quot;: &quot;call a function indirect with an expected signature&quot; },
</del><ins>+        &quot;call_indirect&quot;:       { &quot;category&quot;: &quot;call&quot;,       &quot;value&quot;:  17, &quot;return&quot;: [&quot;call&quot;],     &quot;parameter&quot;: [&quot;call&quot;],                 &quot;immediate&quot;: [{&quot;name&quot;: &quot;type_index&quot;,     &quot;type&quot;: &quot;varuint32&quot;}, {&quot;name&quot;: &quot;reserved&quot;,     &quot;type&quot;: &quot;varuint1&quot;}], &quot;description&quot;: &quot;call a function indirect with an expected signature&quot; },
</ins><span class="cx">         &quot;i32.load8_s&quot;:         { &quot;category&quot;: &quot;memory&quot;,     &quot;value&quot;:  44, &quot;return&quot;: [&quot;i32&quot;],      &quot;parameter&quot;: [&quot;addr&quot;],                 &quot;immediate&quot;: [{&quot;name&quot;: &quot;flags&quot;,          &quot;type&quot;: &quot;varuint32&quot;}, {&quot;name&quot;: &quot;offset&quot;, &quot;type&quot;: &quot;varuint32&quot;}], &quot;description&quot;: &quot;load from memory&quot; },
</span><span class="cx">         &quot;i32.load8_u&quot;:         { &quot;category&quot;: &quot;memory&quot;,     &quot;value&quot;:  45, &quot;return&quot;: [&quot;i32&quot;],      &quot;parameter&quot;: [&quot;addr&quot;],                 &quot;immediate&quot;: [{&quot;name&quot;: &quot;flags&quot;,          &quot;type&quot;: &quot;varuint32&quot;}, {&quot;name&quot;: &quot;offset&quot;, &quot;type&quot;: &quot;varuint32&quot;}], &quot;description&quot;: &quot;load from memory&quot; },
</span><span class="cx">         &quot;i32.load16_s&quot;:        { &quot;category&quot;: &quot;memory&quot;,     &quot;value&quot;:  46, &quot;return&quot;: [&quot;i32&quot;],      &quot;parameter&quot;: [&quot;addr&quot;],                 &quot;immediate&quot;: [{&quot;name&quot;: &quot;flags&quot;,          &quot;type&quot;: &quot;varuint32&quot;}, {&quot;name&quot;: &quot;offset&quot;, &quot;type&quot;: &quot;varuint32&quot;}], &quot;description&quot;: &quot;load from memory&quot; },
</span></span></pre>
</div>
</div>

</body>
</html>