<!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>[209850] 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/209850">209850</a></dd>
<dt>Author</dt> <dd>sbarati@apple.com</dd>
<dt>Date</dt> <dd>2016-12-14 19:30:44 -0800 (Wed, 14 Dec 2016)</dd>
</dl>

<h3>Log Message</h3>
<pre>WebAssembly: Add various low hanging fruit that will allow us to run the LLVM torture tests in Wasm
https://bugs.webkit.org/show_bug.cgi?id=165883

Reviewed by Keith Miller.

JSTests:

* wasm/Builder.js:
(export.default.Builder.prototype._registerSectionBuilders.switch.case.string_appeared_here.this.section):
* wasm/Builder_WebAssemblyBinary.js:
(const.emitters.Export):
* wasm/js-api/table.js:
(assertBadBinary):
(assertBadTable):
(assert.truthy):
* wasm/js-api/test_memory.js:
(binaryShouldNotParse):
(test):
(test.testMemImportError):
(assert.truthy):
(assert): Deleted.

Source/JavaScriptCore:

This patch implements some low hanging fruit:
- Exporting Table
- Exporting Memory
- Load16 with zero extension to both 32 and 64 bit values.
- Fixes Unreachable to emit code that will prevent B3 from having a validation error.

* wasm/WasmB3IRGenerator.cpp:
(JSC::Wasm::B3IRGenerator::addUnreachable):
(JSC::Wasm::sizeOfLoadOp):
(JSC::Wasm::B3IRGenerator::emitLoadOp):
* wasm/WasmFunctionParser.h:
(JSC::Wasm::FunctionParser&lt;Context&gt;::parseExpression):
* wasm/WasmModuleParser.cpp:
(JSC::Wasm::ModuleParser::parseExport):
* wasm/WasmValidate.cpp:
(JSC::Wasm::Validate::addUnreachable):
* wasm/js/WebAssemblyInstanceConstructor.cpp:
(JSC::constructJSWebAssemblyInstance):
* wasm/js/WebAssemblyModuleRecord.cpp:
(JSC::WebAssemblyModuleRecord::finishCreation):
(JSC::WebAssemblyModuleRecord::link):</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="#trunkJSTestswasmBuilder_WebAssemblyBinaryjs">trunk/JSTests/wasm/Builder_WebAssemblyBinary.js</a></li>
<li><a href="#trunkJSTestswasmjsapitablejs">trunk/JSTests/wasm/js-api/table.js</a></li>
<li><a href="#trunkJSTestswasmjsapitest_memoryjs">trunk/JSTests/wasm/js-api/test_memory.js</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="#trunkSourceJavaScriptCorewasmWasmFunctionParserh">trunk/Source/JavaScriptCore/wasm/WasmFunctionParser.h</a></li>
<li><a href="#trunkSourceJavaScriptCorewasmWasmModuleParsercpp">trunk/Source/JavaScriptCore/wasm/WasmModuleParser.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorewasmWasmValidatecpp">trunk/Source/JavaScriptCore/wasm/WasmValidate.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorewasmjsWebAssemblyInstanceConstructorcpp">trunk/Source/JavaScriptCore/wasm/js/WebAssemblyInstanceConstructor.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorewasmjsWebAssemblyModuleRecordcpp">trunk/Source/JavaScriptCore/wasm/js/WebAssemblyModuleRecord.cpp</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkJSTestsChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/JSTests/ChangeLog (209849 => 209850)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JSTests/ChangeLog        2016-12-15 02:31:37 UTC (rev 209849)
+++ trunk/JSTests/ChangeLog        2016-12-15 03:30:44 UTC (rev 209850)
</span><span class="lines">@@ -1,3 +1,25 @@
</span><ins>+2016-12-14  Saam Barati  &lt;sbarati@apple.com&gt;
+
+        WebAssembly: Add various low hanging fruit that will allow us to run the LLVM torture tests in Wasm
+        https://bugs.webkit.org/show_bug.cgi?id=165883
+
+        Reviewed by Keith Miller.
+
+        * wasm/Builder.js:
+        (export.default.Builder.prototype._registerSectionBuilders.switch.case.string_appeared_here.this.section):
+        * wasm/Builder_WebAssemblyBinary.js:
+        (const.emitters.Export):
+        * wasm/js-api/table.js:
+        (assertBadBinary):
+        (assertBadTable):
+        (assert.truthy):
+        * wasm/js-api/test_memory.js:
+        (binaryShouldNotParse):
+        (test):
+        (test.testMemImportError):
+        (assert.truthy):
+        (assert): Deleted.
+
</ins><span class="cx"> 2016-12-14  Filip Pizlo  &lt;fpizlo@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         DirectTailCall implementation needs to tell the shuffler what to put into the ArgumentCount explicitly
</span></span></pre></div>
<a id="trunkJSTestswasmBuilderjs"></a>
<div class="modfile"><h4>Modified: trunk/JSTests/wasm/Builder.js (209849 => 209850)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JSTests/wasm/Builder.js        2016-12-15 02:31:37 UTC (rev 209849)
+++ trunk/JSTests/wasm/Builder.js        2016-12-15 03:30:44 UTC (rev 209850)
</span><span class="lines">@@ -191,6 +191,22 @@
</span><span class="cx">     }
</span><span class="cx"> };
</span><span class="cx"> 
</span><ins>+const _exportMemoryContinuation = (builder, section, nextBuilder) =&gt; {
+    return (field, index) =&gt; {
+        assert.isNumber(index, `Memory exports only support number indices`);
+        section.data.push({field, kind: &quot;Memory&quot;, index});
+        return nextBuilder;
+    }
+};
+
+const _exportTableContinuation = (builder, section, nextBuilder) =&gt; {
+    return (field, index) =&gt; {
+        assert.isNumber(index, `Table exports only support number indices`);
+        section.data.push({field, kind: &quot;Table&quot;, index});
+        return nextBuilder;
+    }
+};
+
</ins><span class="cx"> const _importGlobalContinuation = (builder, section, nextBuilder) =&gt; {
</span><span class="cx">     return () =&gt; {
</span><span class="cx">         const globalBuilder = {
</span><span class="lines">@@ -516,11 +532,11 @@
</span><span class="cx">                     const s = this._addSection(section);
</span><span class="cx">                     const exportBuilder = {
</span><span class="cx">                         End: () =&gt; this,
</span><del>-                        Table: () =&gt; { throw new Error(`Unimplemented: export table`); },
-                        Memory: () =&gt; { throw new Error(`Unimplemented: export memory`); },
</del><span class="cx">                     };
</span><span class="cx">                     exportBuilder.Global = _exportGlobalContinuation(this, s, exportBuilder);
</span><span class="cx">                     exportBuilder.Function = _exportFunctionContinuation(this, s, exportBuilder);
</span><ins>+                    exportBuilder.Memory = _exportMemoryContinuation(this, s, exportBuilder);
+                    exportBuilder.Table = _exportTableContinuation(this, s, exportBuilder);
</ins><span class="cx">                     return exportBuilder;
</span><span class="cx">                 };
</span><span class="cx">                 break;
</span></span></pre></div>
<a id="trunkJSTestswasmBuilder_WebAssemblyBinaryjs"></a>
<div class="modfile"><h4>Modified: trunk/JSTests/wasm/Builder_WebAssemblyBinary.js (209849 => 209850)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JSTests/wasm/Builder_WebAssemblyBinary.js        2016-12-15 02:31:37 UTC (rev 209849)
+++ trunk/JSTests/wasm/Builder_WebAssemblyBinary.js        2016-12-15 03:30:44 UTC (rev 209850)
</span><span class="lines">@@ -167,14 +167,13 @@
</span><span class="cx">             put(bin, &quot;string&quot;, entry.field);
</span><span class="cx">             put(bin, &quot;uint8&quot;, WASM.externalKindValue[entry.kind]);
</span><span class="cx">             switch (entry.kind) {
</span><del>-            default: throw new Error(`Implementation problem: unexpected kind ${entry.kind}`);
</del><span class="cx">             case &quot;Global&quot;:
</span><span class="cx">             case &quot;Function&quot;:
</span><ins>+            case &quot;Memory&quot;:
+            case &quot;Table&quot;:
</ins><span class="cx">                 put(bin, &quot;varuint32&quot;, entry.index);
</span><span class="cx">                 break;
</span><del>-            case &quot;Table&quot;: throw new Error(`Not yet implemented`);
-            case &quot;Memory&quot;: throw new Error(`Not yet implemented`);
-
</del><ins>+            default: throw new Error(`Implementation problem: unexpected kind ${entry.kind}`);
</ins><span class="cx">             }
</span><span class="cx">         }
</span><span class="cx">     },
</span></span></pre></div>
<a id="trunkJSTestswasmjsapitablejs"></a>
<div class="modfile"><h4>Modified: trunk/JSTests/wasm/js-api/table.js (209849 => 209850)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JSTests/wasm/js-api/table.js        2016-12-15 02:31:37 UTC (rev 209849)
+++ trunk/JSTests/wasm/js-api/table.js        2016-12-15 03:30:44 UTC (rev 209850)
</span><span class="lines">@@ -1,19 +1,13 @@
</span><span class="cx"> import Builder from '../Builder.js';
</span><span class="cx"> import * as assert from '../assert.js';
</span><span class="cx"> 
</span><del>-const badTableString = &quot;couldn't parse section Table&quot;;
-const badImportString = &quot;couldn't parse section Import&quot;;
</del><ins>+const badTableString = &quot;couldn't parse section Table: Indirect function table and other tables (evaluating 'new WebAssembly.Module(bin)')&quot;;
+const badImportString = &quot;couldn't parse section Import: Import declarations (evaluating 'new WebAssembly.Module(bin)')&quot;;
+const badExportString = &quot;couldn't parse section Export: Exports (evaluating 'new WebAssembly.Module(bin)')&quot;;
+
</ins><span class="cx"> function assertBadBinary(builder, str) {
</span><span class="cx">     const bin = builder.WebAssembly().get();
</span><del>-    let threw = false;
-    try {
-        new WebAssembly.Module(bin);
-    } catch(e) {
-        threw = true;
-        assert.truthy(e.toString().indexOf(str) !== -1);
-        assert.truthy(e instanceof WebAssembly.CompileError);
-    }
-    assert.truthy(threw);
</del><ins>+    assert.throws(() =&gt; new WebAssembly.Module(bin), WebAssembly.CompileError, str);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> {
</span><span class="lines">@@ -57,7 +51,7 @@
</span><span class="cx">                 .CallIndirect(0, 0)
</span><span class="cx">             .End()
</span><span class="cx">         .End();
</span><del>-    assertBadBinary(builder, &quot;call_indirect is only valid when a table is defined or imported&quot;);
</del><ins>+    assertBadBinary(builder, &quot;call_indirect is only valid when a table is defined or imported (evaluating 'new WebAssembly.Module(bin)')&quot;);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> {
</span><span class="lines">@@ -76,9 +70,38 @@
</span><span class="cx">                 .CallIndirect(0, 1)
</span><span class="cx">             .End()
</span><span class="cx">         .End();
</span><del>-    assertBadBinary(builder, &quot;call_indirect 'reserved' varuint1 must be 0x0&quot;);
</del><ins>+    assertBadBinary(builder, &quot;call_indirect 'reserved' varuint1 must be 0x0 (evaluating 'new WebAssembly.Module(bin)')&quot;);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><ins>+{
+    // Can't export an undefined table
+    const builder = new Builder()
+        .Type().End()
+        .Function().End()
+        .Export()
+            .Table(&quot;foo&quot;, 0)
+        .End()
+        .Code()
+        .End();
+    assertBadBinary(builder, badExportString);
+}
+
+{
+    // Can't export a table at index 1.
+    const builder = new Builder()
+        .Type().End()
+        .Function().End()
+        .Table()
+            .Table({initial: 20, maximum: 30, element: &quot;anyfunc&quot;})
+        .End()
+        .Export()
+            .Table(&quot;foo&quot;, 1)
+        .End()
+        .Code()
+        .End();
+    assertBadBinary(builder, badExportString);
+}
+
</ins><span class="cx"> function assertBadTable(tableDescription) {
</span><span class="cx">     const builder = new Builder()
</span><span class="cx">         .Type().End()
</span><span class="lines">@@ -228,3 +251,43 @@
</span><span class="cx">     assertBadTable([]);
</span><span class="cx">     assertBadTable(new WebAssembly.Memory({initial:1}));
</span><span class="cx"> }
</span><ins>+
+{
+    const builder = new Builder()
+        .Type().End()
+        .Import()
+            .Table(&quot;imp&quot;, &quot;table&quot;, {initial: 25, element: &quot;anyfunc&quot;})
+        .End()
+        .Function().End()
+        .Export()
+            .Table(&quot;table&quot;, 0)
+            .Table(&quot;table2&quot;, 0)
+        .End()
+        .Code().End();
+
+    const module = new WebAssembly.Module(builder.WebAssembly().get());
+    const table = new WebAssembly.Table({element: &quot;anyfunc&quot;, initial: 25});
+    const instance = new WebAssembly.Instance(module, {imp: {table}});
+    assert.truthy(table === instance.exports.table);
+    assert.truthy(table === instance.exports.table2);
+}
+
+{
+    const builder = new Builder()
+        .Type().End()
+        .Function().End()
+        .Table()
+            .Table({initial: 20, maximum: 30, element: &quot;anyfunc&quot;})
+        .End()
+        .Export()
+            .Table(&quot;table&quot;, 0)
+            .Table(&quot;table2&quot;, 0)
+        .End()
+        .Code().End();
+
+    const module = new WebAssembly.Module(builder.WebAssembly().get());
+    const instance = new WebAssembly.Instance(module);
+    assert.eq(instance.exports.table, instance.exports.table2);
+    assert.eq(instance.exports.table.length, 20);
+    assert.truthy(instance.exports.table instanceof WebAssembly.Table);
+}
</ins></span></pre></div>
<a id="trunkJSTestswasmjsapitest_memoryjs"></a>
<div class="modfile"><h4>Modified: trunk/JSTests/wasm/js-api/test_memory.js (209849 => 209850)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JSTests/wasm/js-api/test_memory.js        2016-12-15 02:31:37 UTC (rev 209849)
+++ trunk/JSTests/wasm/js-api/test_memory.js        2016-12-15 03:30:44 UTC (rev 209850)
</span><span class="lines">@@ -1,12 +1,7 @@
</span><span class="cx"> // FIXME: use the assert library: https://bugs.webkit.org/show_bug.cgi?id=165684
</span><span class="cx"> import Builder from '../Builder.js';
</span><ins>+import * as assert from '../assert.js';
</ins><span class="cx"> 
</span><del>-function assert(b) {
-    if (!b) {
-        throw new Error(&quot;Bad assertion&quot;);
-    }
-}
-
</del><span class="cx"> const pageSize = 64 * 1024;
</span><span class="cx"> const maxPageCount = (2**32) / pageSize;
</span><span class="cx"> 
</span><span class="lines">@@ -18,7 +13,7 @@
</span><span class="cx">     } catch(e) {
</span><span class="cx">         threw = true;
</span><span class="cx">     }
</span><del>-    assert(threw);
</del><ins>+    assert.truthy(threw);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> {
</span><span class="lines">@@ -102,29 +97,37 @@
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> {
</span><del>-    let threw = false;
-    try {
-        new WebAssembly.Memory(20);
-    } catch(e) {
-        assert(e instanceof TypeError);
-        assert(e.message === &quot;WebAssembly.Memory expects its first argument to be an object&quot;);
-        threw = true;
-    }
-    assert(threw);
</del><ins>+    // Can't export an undefined memory.
+    const builder = (new Builder())
+        .Type().End()
+        .Function().End()
+        .Export()
+            .Memory(&quot;memory&quot;, 0)
+        .End()
+        .Code()
+        .End();
+    binaryShouldNotParse(builder);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> {
</span><del>-    let threw = false;
-    try {
-        new WebAssembly.Memory({}, {});
-    } catch(e) {
-        assert(e instanceof TypeError);
-        assert(e.message === &quot;WebAssembly.Memory expects exactly one argument&quot;);
-        threw = true;
-    }
-    assert(threw);
</del><ins>+    // Can't export a non-zero memory index.
+    const builder = (new Builder())
+        .Type().End()
+        .Import().Memory(&quot;imp&quot;, &quot;memory&quot;, {initial: 20}).End()
+        .Function().End()
+        .Export()
+            .Memory(&quot;memory&quot;, 1)
+        .End()
+        .Code()
+        .End();
+    binaryShouldNotParse(builder);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><ins>+{
+    assert.throws(() =&gt; new WebAssembly.Memory(20), TypeError, &quot;WebAssembly.Memory expects its first argument to be an object&quot;); 
+    assert.throws(() =&gt; new WebAssembly.Memory({}, {}), TypeError,  &quot;WebAssembly.Memory expects exactly one argument&quot;);
+}
+
</ins><span class="cx"> function test(f) {
</span><span class="cx">     noInline(f);
</span><span class="cx">     for (let i = 0; i &lt; 2; i++) {
</span><span class="lines">@@ -164,10 +167,10 @@
</span><span class="cx">         let value = i + 1;
</span><span class="cx">         let address = i * 4;
</span><span class="cx">         let result = foo(value, address);
</span><del>-        assert(result === value);
</del><ins>+        assert.truthy(result === value);
</ins><span class="cx">         let arrayBuffer = memory.buffer;
</span><span class="cx">         let buffer = new Uint32Array(arrayBuffer);
</span><del>-        assert(buffer[i] === value);
</del><ins>+        assert.truthy(buffer[i] === value);
</ins><span class="cx">     }
</span><span class="cx"> });
</span><span class="cx"> 
</span><span class="lines">@@ -204,10 +207,10 @@
</span><span class="cx">         let address = i;
</span><span class="cx">         let result = foo(value, address);
</span><span class="cx">         let expectedValue = (value &amp; ((2**8) - 1)); 
</span><del>-        assert(result === expectedValue);
</del><ins>+        assert.truthy(result === expectedValue);
</ins><span class="cx">         let arrayBuffer = memory.buffer;
</span><span class="cx">         let buffer = new Uint8Array(arrayBuffer);
</span><del>-        assert(buffer[i] === expectedValue);
</del><ins>+        assert.truthy(buffer[i] === expectedValue);
</ins><span class="cx">     }
</span><span class="cx"> });
</span><span class="cx"> 
</span><span class="lines">@@ -241,14 +244,14 @@
</span><span class="cx">     const bytes = memoryDescription.initial * pageSize;
</span><span class="cx">     for (let i = 0; i &lt; (bytes/4); i++) {
</span><span class="cx">         let value = i + 1 + .0128213781289;
</span><del>-        assert(value !== Math.fround(value));
</del><ins>+        assert.truthy(value !== Math.fround(value));
</ins><span class="cx">         let address = i * 4;
</span><span class="cx">         let result = foo(value, address);
</span><span class="cx">         let expectedValue = Math.fround(result);
</span><del>-        assert(result === expectedValue);
</del><ins>+        assert.truthy(result === expectedValue);
</ins><span class="cx">         let arrayBuffer = memory.buffer;
</span><span class="cx">         let buffer = new Float32Array(arrayBuffer);
</span><del>-        assert(buffer[i] === expectedValue);
</del><ins>+        assert.truthy(buffer[i] === expectedValue);
</ins><span class="cx">     }
</span><span class="cx"> });
</span><span class="cx"> 
</span><span class="lines">@@ -285,10 +288,10 @@
</span><span class="cx">         let address = i * 8;
</span><span class="cx">         let result = foo(value, address);
</span><span class="cx">         let expectedValue = result;
</span><del>-        assert(result === expectedValue);
</del><ins>+        assert.truthy(result === expectedValue);
</ins><span class="cx">         let arrayBuffer = memory.buffer;
</span><span class="cx">         let buffer = new Float64Array(arrayBuffer);
</span><del>-        assert(buffer[i] === expectedValue);
</del><ins>+        assert.truthy(buffer[i] === expectedValue);
</ins><span class="cx">     }
</span><span class="cx"> });
</span><span class="cx"> 
</span><span class="lines">@@ -320,13 +323,13 @@
</span><span class="cx">         try {
</span><span class="cx">             new WebAssembly.Instance(module, instanceObj);
</span><span class="cx">         } catch(e) {
</span><del>-            assert(e instanceof TypeError);
</del><ins>+            assert.truthy(e instanceof TypeError);
</ins><span class="cx">             threw = true;
</span><span class="cx">             if (expectedError) {
</span><del>-                assert(e.message === expectedError);
</del><ins>+                assert.truthy(e.message === expectedError);
</ins><span class="cx">             }
</span><span class="cx">         }
</span><del>-        assert(threw);
</del><ins>+        assert.truthy(threw);
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     testMemImportError(20);
</span><span class="lines">@@ -363,17 +366,7 @@
</span><span class="cx">     const module = new WebAssembly.Module(bin);
</span><span class="cx"> 
</span><span class="cx">     function testMemImportError(instanceObj, expectedError) {
</span><del>-        let threw = false;
-        try {
-            new WebAssembly.Instance(module, instanceObj);
-        } catch(e) {
-            assert(e instanceof TypeError);
-            threw = true;
-            if (expectedError) {
-                assert(e.message === expectedError);
-            }
-        }
-        assert(threw);
</del><ins>+        assert.throws(() =&gt; new WebAssembly.Instance(module, instanceObj), TypeError, expectedError);
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     testMemImportError({imp: { memory: new WebAssembly.Memory({initial: 19, maximum: 25}) } }, &quot;Memory import provided an 'initial' that is too small&quot;);
</span><span class="lines">@@ -383,3 +376,41 @@
</span><span class="cx">     new WebAssembly.Instance(module, {imp: {memory: new WebAssembly.Memory({initial:20})}});
</span><span class="cx">     new WebAssembly.Instance(module, {imp: {memory: new WebAssembly.Memory({initial:20, maximum:20})}});
</span><span class="cx"> });
</span><ins>+
+{
+    const builder = (new Builder())
+        .Type().End()
+        .Import().Memory(&quot;imp&quot;, &quot;memory&quot;, {initial: 20}).End()
+        .Function().End()
+        .Export()
+            .Memory(&quot;memory&quot;, 0)
+            .Memory(&quot;memory2&quot;, 0)
+        .End()
+        .Code()
+        .End();
+    const bin = builder.WebAssembly().get();
+    const module = new WebAssembly.Module(bin);
+    const memory = new WebAssembly.Memory({initial: 20});
+    const instance = new WebAssembly.Instance(module, {imp: {memory}});
+    assert.truthy(memory === instance.exports.memory);
+    assert.truthy(memory === instance.exports.memory2);
+}
+
+{
+    const builder = (new Builder())
+        .Type().End()
+        .Function().End()
+        .Memory().InitialMaxPages(20, 25).End()
+        .Export()
+            .Memory(&quot;memory&quot;, 0)
+            .Memory(&quot;memory2&quot;, 0)
+        .End()
+        .Code()
+        .End();
+    const bin = builder.WebAssembly().get();
+    const module = new WebAssembly.Module(bin);
+    const instance = new WebAssembly.Instance(module);
+    assert.eq(instance.exports.memory, instance.exports.memory2);
+    assert.eq(instance.exports.memory.buffer.byteLength, 20 * pageSize);
+    assert.truthy(instance.exports.memory instanceof WebAssembly.Memory);
+}
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ChangeLog (209849 => 209850)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ChangeLog        2016-12-15 02:31:37 UTC (rev 209849)
+++ trunk/Source/JavaScriptCore/ChangeLog        2016-12-15 03:30:44 UTC (rev 209850)
</span><span class="lines">@@ -1,3 +1,32 @@
</span><ins>+2016-12-14  Saam Barati  &lt;sbarati@apple.com&gt;
+
+        WebAssembly: Add various low hanging fruit that will allow us to run the LLVM torture tests in Wasm
+        https://bugs.webkit.org/show_bug.cgi?id=165883
+
+        Reviewed by Keith Miller.
+
+        This patch implements some low hanging fruit:
+        - Exporting Table
+        - Exporting Memory
+        - Load16 with zero extension to both 32 and 64 bit values.
+        - Fixes Unreachable to emit code that will prevent B3 from having a validation error.
+
+        * wasm/WasmB3IRGenerator.cpp:
+        (JSC::Wasm::B3IRGenerator::addUnreachable):
+        (JSC::Wasm::sizeOfLoadOp):
+        (JSC::Wasm::B3IRGenerator::emitLoadOp):
+        * wasm/WasmFunctionParser.h:
+        (JSC::Wasm::FunctionParser&lt;Context&gt;::parseExpression):
+        * wasm/WasmModuleParser.cpp:
+        (JSC::Wasm::ModuleParser::parseExport):
+        * wasm/WasmValidate.cpp:
+        (JSC::Wasm::Validate::addUnreachable):
+        * wasm/js/WebAssemblyInstanceConstructor.cpp:
+        (JSC::constructJSWebAssemblyInstance):
+        * wasm/js/WebAssemblyModuleRecord.cpp:
+        (JSC::WebAssemblyModuleRecord::finishCreation):
+        (JSC::WebAssemblyModuleRecord::link):
+
</ins><span class="cx"> 2016-12-14  Yusuke Suzuki  &lt;utatane.tea@gmail.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Update ModuleLoader code by using the latest builtin primitives
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorewasmWasmB3IRGeneratorcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/wasm/WasmB3IRGenerator.cpp (209849 => 209850)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/wasm/WasmB3IRGenerator.cpp        2016-12-15 02:31:37 UTC (rev 209849)
+++ trunk/Source/JavaScriptCore/wasm/WasmB3IRGenerator.cpp        2016-12-15 03:30:44 UTC (rev 209850)
</span><span class="lines">@@ -178,6 +178,7 @@
</span><span class="cx">     // Calls
</span><span class="cx">     bool WARN_UNUSED_RETURN addCall(uint32_t calleeIndex, const Signature*, Vector&lt;ExpressionType&gt;&amp; args, ExpressionType&amp; result);
</span><span class="cx">     bool WARN_UNUSED_RETURN addCallIndirect(const Signature*, Vector&lt;ExpressionType&gt;&amp; args, ExpressionType&amp; result);
</span><ins>+    void addUnreachable();
</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">@@ -326,6 +327,15 @@
</span><span class="cx">     return true;
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void B3IRGenerator::addUnreachable()
+{
+    B3::PatchpointValue* unreachable = m_currentBlock-&gt;appendNew&lt;B3::PatchpointValue&gt;(m_proc, B3::Void, Origin());
+    unreachable-&gt;setGenerator([=] (CCallHelpers&amp; jit, const B3::StackmapGenerationParams&amp;) {
+        jit.breakpoint();
+    });
+    unreachable-&gt;effects.terminal = true;
+}
+
</ins><span class="cx"> bool B3IRGenerator::setLocal(uint32_t index, ExpressionType value)
</span><span class="cx"> {
</span><span class="cx">     ASSERT(m_locals[index]);
</span><span class="lines">@@ -367,6 +377,8 @@
</span><span class="cx">         return 1;
</span><span class="cx">     case LoadOpType::I32Load16S:
</span><span class="cx">     case LoadOpType::I64Load16S:
</span><ins>+    case LoadOpType::I32Load16U:
+    case LoadOpType::I64Load16U:
</ins><span class="cx">         return 2;
</span><span class="cx">     case LoadOpType::I32Load:
</span><span class="cx">     case LoadOpType::I64Load32S:
</span><span class="lines">@@ -376,9 +388,6 @@
</span><span class="cx">     case LoadOpType::I64Load:
</span><span class="cx">     case LoadOpType::F64Load:
</span><span class="cx">         return 8;
</span><del>-    case LoadOpType::I32Load16U:
-    case LoadOpType::I64Load16U:
-        break;
</del><span class="cx">     }
</span><span class="cx">     RELEASE_ASSERT_NOT_REACHED();
</span><span class="cx"> }
</span><span class="lines">@@ -438,11 +447,21 @@
</span><span class="cx">         return m_currentBlock-&gt;appendNew&lt;MemoryValue&gt;(m_proc, Load, Double, origin, pointer);
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    // B3 doesn't support Load16Z yet.
-    case LoadOpType::I32Load16U:
-    case LoadOpType::I64Load16U:
-        break;
</del><ins>+    // FIXME: B3 doesn't support Load16Z yet. We should lower to that value when
+    // it's added. https://bugs.webkit.org/show_bug.cgi?id=165884
+    case LoadOpType::I32Load16U: {
+        Value* value = m_currentBlock-&gt;appendNew&lt;MemoryValue&gt;(m_proc, Load16S, origin, pointer, offset);
+        return m_currentBlock-&gt;appendNew&lt;Value&gt;(m_proc, BitAnd, Origin(), value,
+                m_currentBlock-&gt;appendNew&lt;Const32Value&gt;(m_proc, Origin(), 0x0000ffff));
</ins><span class="cx">     }
</span><ins>+    case LoadOpType::I64Load16U: {
+        Value* value = m_currentBlock-&gt;appendNew&lt;MemoryValue&gt;(m_proc, Load16S, origin, pointer, offset);
+        Value* partialResult = m_currentBlock-&gt;appendNew&lt;Value&gt;(m_proc, BitAnd, Origin(), value,
+                m_currentBlock-&gt;appendNew&lt;Const32Value&gt;(m_proc, Origin(), 0x0000ffff));
+
+        return m_currentBlock-&gt;appendNew&lt;Value&gt;(m_proc, ZExt32, Origin(), partialResult);
+    }
+    }
</ins><span class="cx">     RELEASE_ASSERT_NOT_REACHED();
</span><span class="cx"> }
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorewasmWasmFunctionParserh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/wasm/WasmFunctionParser.h (209849 => 209850)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/wasm/WasmFunctionParser.h        2016-12-15 02:31:37 UTC (rev 209849)
+++ trunk/Source/JavaScriptCore/wasm/WasmFunctionParser.h        2016-12-15 03:30:44 UTC (rev 209850)
</span><span class="lines">@@ -566,6 +566,7 @@
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     case OpType::Unreachable: {
</span><ins>+        m_context.addUnreachable();
</ins><span class="cx">         m_unreachableBlocks = 1;
</span><span class="cx">         return true;
</span><span class="cx">     }
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorewasmWasmModuleParsercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/wasm/WasmModuleParser.cpp (209849 => 209850)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/wasm/WasmModuleParser.cpp        2016-12-15 02:31:37 UTC (rev 209849)
+++ trunk/Source/JavaScriptCore/wasm/WasmModuleParser.cpp        2016-12-15 03:30:44 UTC (rev 209850)
</span><span class="lines">@@ -511,11 +511,17 @@
</span><span class="cx">             break;
</span><span class="cx">         }
</span><span class="cx">         case External::Table: {
</span><del>-            // FIXME https://bugs.webkit.org/show_bug.cgi?id=165782
</del><ins>+            if (!m_hasTable)
+                return false;
+            if (exp.kindIndex != 0)
+                return false;
</ins><span class="cx">             break;
</span><span class="cx">         }
</span><span class="cx">         case External::Memory: {
</span><del>-            // FIXME: https://bugs.webkit.org/show_bug.cgi?id=165671
</del><ins>+            if (!m_module-&gt;memory)
+                return false;
+            if (exp.kindIndex != 0)
+                return false;
</ins><span class="cx">             break;
</span><span class="cx">         }
</span><span class="cx">         case External::Global: {
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorewasmWasmValidatecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/wasm/WasmValidate.cpp (209849 => 209850)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/wasm/WasmValidate.cpp        2016-12-15 02:31:37 UTC (rev 209849)
+++ trunk/Source/JavaScriptCore/wasm/WasmValidate.cpp        2016-12-15 03:30:44 UTC (rev 209850)
</span><span class="lines">@@ -114,6 +114,8 @@
</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><ins>+    void addUnreachable() { }
+
</ins><span class="cx">     // Calls
</span><span class="cx">     bool WARN_UNUSED_RETURN addCall(unsigned calleeIndex, const Signature*, const Vector&lt;ExpressionType&gt;&amp; args, ExpressionType&amp; result);
</span><span class="cx">     bool WARN_UNUSED_RETURN addCallIndirect(const Signature*, const Vector&lt;ExpressionType&gt;&amp; args, ExpressionType&amp; result);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorewasmjsWebAssemblyInstanceConstructorcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/wasm/js/WebAssemblyInstanceConstructor.cpp (209849 => 209850)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/wasm/js/WebAssemblyInstanceConstructor.cpp        2016-12-15 02:31:37 UTC (rev 209849)
+++ trunk/Source/JavaScriptCore/wasm/js/WebAssemblyInstanceConstructor.cpp        2016-12-15 03:30:44 UTC (rev 209850)
</span><span class="lines">@@ -245,7 +245,7 @@
</span><span class="cx">         if (!!moduleInformation.tableInformation &amp;&amp; !hasTableImport) {
</span><span class="cx">             RELEASE_ASSERT(!moduleInformation.tableInformation.isImport());
</span><span class="cx">             // We create a Table when it's a Table definition.
</span><del>-            JSWebAssemblyTable* table = JSWebAssemblyTable::create(exec, vm, exec-&gt;lexicalGlobalObject()-&gt;WebAssemblyMemoryStructure(),
</del><ins>+            JSWebAssemblyTable* table = JSWebAssemblyTable::create(exec, vm, exec-&gt;lexicalGlobalObject()-&gt;WebAssemblyTableStructure(),
</ins><span class="cx">                 moduleInformation.tableInformation.initial(), moduleInformation.tableInformation.maximum());
</span><span class="cx">             // We should always be able to allocate a JSWebAssemblyTable we've defined.
</span><span class="cx">             // If it's defined to be too large, we should have thrown a validation error.
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorewasmjsWebAssemblyModuleRecordcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/wasm/js/WebAssemblyModuleRecord.cpp (209849 => 209850)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/wasm/js/WebAssemblyModuleRecord.cpp        2016-12-15 02:31:37 UTC (rev 209849)
+++ trunk/Source/JavaScriptCore/wasm/js/WebAssemblyModuleRecord.cpp        2016-12-15 03:30:44 UTC (rev 209850)
</span><span class="lines">@@ -70,27 +70,8 @@
</span><span class="cx"> {
</span><span class="cx">     Base::finishCreation(exec, vm);
</span><span class="cx">     ASSERT(inherits(info()));
</span><del>-    for (const auto&amp; exp : moduleInformation.exports) {
-        switch (exp.kind) {
-        case Wasm::External::Function: {
-            addExportEntry(ExportEntry::createLocal(exp.field, exp.field));
-            break;
-        }
-        case Wasm::External::Table: {
-            // FIXME https://bugs.webkit.org/show_bug.cgi?id=165782
-            break;
-        }
-        case Wasm::External::Memory: {
-            // FIXME: https://bugs.webkit.org/show_bug.cgi?id=165671
-            break;
-        }
-        case Wasm::External::Global: {
-            // In the MVP, only immutable global variables can be exported.
-            addExportEntry(ExportEntry::createLocal(exp.field, exp.field));
-            break;
-        }
-        }
-    }
</del><ins>+    for (const auto&amp; exp : moduleInformation.exports)
+        addExportEntry(ExportEntry::createLocal(exp.field, exp.field));
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void WebAssemblyModuleRecord::visitChildren(JSCell* cell, SlotVisitor&amp; visitor)
</span><span class="lines">@@ -146,14 +127,21 @@
</span><span class="cx">             break;
</span><span class="cx">         }
</span><span class="cx">         case Wasm::External::Table: {
</span><del>-            // FIXME https://bugs.webkit.org/show_bug.cgi?id=165782
</del><ins>+            // This should be guaranteed by module verification.
+            RELEASE_ASSERT(instance-&gt;table()); 
+            ASSERT(exp.kindIndex == 0);
+
+            exportedValue = instance-&gt;table();
</ins><span class="cx">             break;
</span><span class="cx">         }
</span><span class="cx">         case Wasm::External::Memory: {
</span><del>-            // FIXME: https://bugs.webkit.org/show_bug.cgi?id=165671
</del><ins>+            // This should be guaranteed by module verification.
+            RELEASE_ASSERT(instance-&gt;memory()); 
+            ASSERT(exp.kindIndex == 0);
+
+            exportedValue = instance-&gt;memory();
</ins><span class="cx">             break;
</span><span class="cx">         }
</span><del>-
</del><span class="cx">         case Wasm::External::Global: {
</span><span class="cx">             // Assert: the global is immutable by MVP validation constraint.
</span><span class="cx">             const Wasm::Global&amp; global = moduleInformation.globals[exp.kindIndex];
</span></span></pre>
</div>
</div>

</body>
</html>