<!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>[210201] 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/210201">210201</a></dd>
<dt>Author</dt> <dd>sbarati@apple.com</dd>
<dt>Date</dt> <dd>2016-12-28 16:06:52 -0800 (Wed, 28 Dec 2016)</dd>
</dl>

<h3>Log Message</h3>
<pre>WebAssembly: Implement grow_memory and current_memory
https://bugs.webkit.org/show_bug.cgi?id=166448
&lt;rdar://problem/29803676&gt;

Reviewed by Keith Miller.

JSTests:

I rewrote some of the testWasmModuleFunctions that used Memory to use
the JS API since the jsc.cpp version can no longer use memory.

* wasm.yaml:
* wasm/function-tests/add-12.js:
(testWasmModuleFunctions):
* wasm/function-tests/br-if-loop-less-than.js:
(testWasmModuleFunctions):
* wasm/function-tests/brTableAsIf.js:
(testWasmModuleFunctions):
* wasm/function-tests/brTableManyValues.js:
(testWasmModuleFunctions):
* wasm/function-tests/brTableWithLoop.js:
(testWasmModuleFunctions):
* wasm/function-tests/dumb-eq-if-then-else.js:
* wasm/function-tests/eqz.js:
* wasm/function-tests/grow-memory-2.js: Added.
(const.func):
(assert.eq.instance.exports.foo):
* wasm/function-tests/grow-memory-3.js: Added.
* wasm/function-tests/grow-memory-4.js: Added.
(const.func):
* wasm/function-tests/grow-memory.js: Added.
(binaryShouldNotParse):
(assert.truthy):
(assert.eq):
(memory.grow):
* wasm/function-tests/i32-load.js:
(testWasmModuleFunctions):
* wasm/function-tests/i32-load8-s.js:
* wasm/function-tests/max.js:
* wasm/function-tests/min.js:
* wasm/js-api/memory-grow.js: Added.
(i.i):
(assertEq):
* wasm/js-api/test_memory.js:
* wasm/wasm.json:

Source/JavaScriptCore:

This patch implements grow_memory, current_memory, and WebAssembly.prototype.grow.
See relevant spec texts here:
        
https://github.com/WebAssembly/design/blob/master/Semantics.md#linear-memory-accesses
https://github.com/WebAssembly/design/blob/master/JS.md#webassemblymemoryprototypegrow
        
I also fix a couple miscellaneous bugs:
        
1. Data section now understands full init_exprs. 
2. parseVarUint1 no longer has a bug where we allow values larger than 1 if
their bottom 8 bits are zero.
        
Since the JS API can now grow memory, we need to make calling an import
and call_indirect refresh the base memory register and the size registers.

* jsc.cpp:
(functionTestWasmModuleFunctions):
* runtime/Options.h:
* runtime/VM.h:
* wasm/WasmB3IRGenerator.cpp:
(JSC::Wasm::B3IRGenerator::B3IRGenerator):
(JSC::Wasm::reloadPinnedRegisters):
(JSC::Wasm::B3IRGenerator::emitReloadPinnedRegisters):
(JSC::Wasm::createJSToWasmWrapper):
(JSC::Wasm::parseAndCompile):
* wasm/WasmFormat.cpp:
(JSC::Wasm::Segment::create):
* wasm/WasmFormat.h:
(JSC::Wasm::I32InitExpr::I32InitExpr):
(JSC::Wasm::I32InitExpr::globalImport):
(JSC::Wasm::I32InitExpr::constValue):
(JSC::Wasm::I32InitExpr::isConst):
(JSC::Wasm::I32InitExpr::isGlobalImport):
(JSC::Wasm::I32InitExpr::globalImportIndex):
(JSC::Wasm::Segment::byte):
(JSC::Wasm::ModuleInformation::importFunctionCount):
(JSC::Wasm::ModuleInformation::hasMemory):
* wasm/WasmFunctionParser.h:
* wasm/WasmMemory.cpp:
(JSC::Wasm::Memory::Memory):
(JSC::Wasm::Memory::grow):
* wasm/WasmMemory.h:
(JSC::Wasm::Memory::size):
(JSC::Wasm::Memory::sizeInPages):
(JSC::Wasm::Memory::offsetOfMemory):
(JSC::Wasm::Memory::isValid): Deleted.
(JSC::Wasm::Memory::grow): Deleted.
* wasm/WasmModuleParser.cpp:
(JSC::Wasm::makeI32InitExpr):
* wasm/WasmModuleParser.h:
* wasm/WasmPageCount.h:
(JSC::Wasm::PageCount::bytes):
(JSC::Wasm::PageCount::pageCount):
(JSC::Wasm::PageCount::fromBytes):
(JSC::Wasm::PageCount::operator+):
* wasm/WasmParser.h:
(JSC::Wasm::Parser&lt;SuccessType&gt;::parseVarUInt1):
* wasm/WasmValidate.cpp:
* wasm/js/JSWebAssemblyInstance.h:
(JSC::JSWebAssemblyInstance::offsetOfMemory):
* wasm/js/JSWebAssemblyMemory.cpp:
(JSC::JSWebAssemblyMemory::~JSWebAssemblyMemory):
(JSC::JSWebAssemblyMemory::grow):
* wasm/js/JSWebAssemblyMemory.h:
(JSC::JSWebAssemblyMemory::offsetOfMemory):
* wasm/js/JSWebAssemblyModule.h:
(JSC::JSWebAssemblyModule::functionImportCount):
(JSC::JSWebAssemblyModule::jsEntrypointCalleeFromFunctionIndexSpace):
(JSC::JSWebAssemblyModule::wasmEntrypointCalleeFromFunctionIndexSpace):
(JSC::JSWebAssemblyModule::importCount): Deleted.
* wasm/js/WebAssemblyFunction.cpp:
(JSC::callWebAssemblyFunction):
* wasm/js/WebAssemblyInstanceConstructor.cpp:
(JSC::constructJSWebAssemblyInstance):
* wasm/js/WebAssemblyMemoryConstructor.cpp:
(JSC::constructJSWebAssemblyMemory):
* wasm/js/WebAssemblyMemoryPrototype.cpp:
(JSC::getMemory):
(JSC::webAssemblyMemoryProtoFuncBuffer):
(JSC::webAssemblyMemoryProtoFuncGrow):
* wasm/js/WebAssemblyModuleRecord.cpp:
(JSC::WebAssemblyModuleRecord::link):
(JSC::dataSegmentFail):
(JSC::WebAssemblyModuleRecord::evaluate):
* wasm/wasm.json:</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkJSTestsChangeLog">trunk/JSTests/ChangeLog</a></li>
<li><a href="#trunkJSTestswasmfunctiontestsadd12js">trunk/JSTests/wasm/function-tests/add-12.js</a></li>
<li><a href="#trunkJSTestswasmfunctiontestsbriflooplessthanjs">trunk/JSTests/wasm/function-tests/br-if-loop-less-than.js</a></li>
<li><a href="#trunkJSTestswasmfunctiontestsbrTableAsIfjs">trunk/JSTests/wasm/function-tests/brTableAsIf.js</a></li>
<li><a href="#trunkJSTestswasmfunctiontestsbrTableManyValuesjs">trunk/JSTests/wasm/function-tests/brTableManyValues.js</a></li>
<li><a href="#trunkJSTestswasmfunctiontestsbrTableWithLoopjs">trunk/JSTests/wasm/function-tests/brTableWithLoop.js</a></li>
<li><a href="#trunkJSTestswasmfunctiontestsdumbeqifthenelsejs">trunk/JSTests/wasm/function-tests/dumb-eq-if-then-else.js</a></li>
<li><a href="#trunkJSTestswasmfunctiontestseqzjs">trunk/JSTests/wasm/function-tests/eqz.js</a></li>
<li><a href="#trunkJSTestswasmfunctiontestsi32loadjs">trunk/JSTests/wasm/function-tests/i32-load.js</a></li>
<li><a href="#trunkJSTestswasmfunctiontestsi32load8sjs">trunk/JSTests/wasm/function-tests/i32-load8-s.js</a></li>
<li><a href="#trunkJSTestswasmfunctiontestsmaxjs">trunk/JSTests/wasm/function-tests/max.js</a></li>
<li><a href="#trunkJSTestswasmfunctiontestsminjs">trunk/JSTests/wasm/function-tests/min.js</a></li>
<li><a href="#trunkJSTestswasmjsapitest_memoryjs">trunk/JSTests/wasm/js-api/test_memory.js</a></li>
<li><a href="#trunkJSTestswasmwasmjson">trunk/JSTests/wasm/wasm.json</a></li>
<li><a href="#trunkJSTestswasmyaml">trunk/JSTests/wasm.yaml</a></li>
<li><a href="#trunkSourceJavaScriptCoreChangeLog">trunk/Source/JavaScriptCore/ChangeLog</a></li>
<li><a href="#trunkSourceJavaScriptCorejsccpp">trunk/Source/JavaScriptCore/jsc.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeOptionsh">trunk/Source/JavaScriptCore/runtime/Options.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeVMh">trunk/Source/JavaScriptCore/runtime/VM.h</a></li>
<li><a href="#trunkSourceJavaScriptCorewasmWasmB3IRGeneratorcpp">trunk/Source/JavaScriptCore/wasm/WasmB3IRGenerator.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorewasmWasmFormatcpp">trunk/Source/JavaScriptCore/wasm/WasmFormat.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorewasmWasmFormath">trunk/Source/JavaScriptCore/wasm/WasmFormat.h</a></li>
<li><a href="#trunkSourceJavaScriptCorewasmWasmFunctionParserh">trunk/Source/JavaScriptCore/wasm/WasmFunctionParser.h</a></li>
<li><a href="#trunkSourceJavaScriptCorewasmWasmMemorycpp">trunk/Source/JavaScriptCore/wasm/WasmMemory.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorewasmWasmMemoryh">trunk/Source/JavaScriptCore/wasm/WasmMemory.h</a></li>
<li><a href="#trunkSourceJavaScriptCorewasmWasmModuleParsercpp">trunk/Source/JavaScriptCore/wasm/WasmModuleParser.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorewasmWasmModuleParserh">trunk/Source/JavaScriptCore/wasm/WasmModuleParser.h</a></li>
<li><a href="#trunkSourceJavaScriptCorewasmWasmPageCounth">trunk/Source/JavaScriptCore/wasm/WasmPageCount.h</a></li>
<li><a href="#trunkSourceJavaScriptCorewasmWasmParserh">trunk/Source/JavaScriptCore/wasm/WasmParser.h</a></li>
<li><a href="#trunkSourceJavaScriptCorewasmWasmValidatecpp">trunk/Source/JavaScriptCore/wasm/WasmValidate.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorewasmjsJSWebAssemblyInstanceh">trunk/Source/JavaScriptCore/wasm/js/JSWebAssemblyInstance.h</a></li>
<li><a href="#trunkSourceJavaScriptCorewasmjsJSWebAssemblyMemorycpp">trunk/Source/JavaScriptCore/wasm/js/JSWebAssemblyMemory.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorewasmjsJSWebAssemblyMemoryh">trunk/Source/JavaScriptCore/wasm/js/JSWebAssemblyMemory.h</a></li>
<li><a href="#trunkSourceJavaScriptCorewasmjsJSWebAssemblyModuleh">trunk/Source/JavaScriptCore/wasm/js/JSWebAssemblyModule.h</a></li>
<li><a href="#trunkSourceJavaScriptCorewasmjsWebAssemblyFunctioncpp">trunk/Source/JavaScriptCore/wasm/js/WebAssemblyFunction.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorewasmjsWebAssemblyInstanceConstructorcpp">trunk/Source/JavaScriptCore/wasm/js/WebAssemblyInstanceConstructor.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorewasmjsWebAssemblyMemoryConstructorcpp">trunk/Source/JavaScriptCore/wasm/js/WebAssemblyMemoryConstructor.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorewasmjsWebAssemblyMemoryPrototypecpp">trunk/Source/JavaScriptCore/wasm/js/WebAssemblyMemoryPrototype.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorewasmjsWebAssemblyModuleRecordcpp">trunk/Source/JavaScriptCore/wasm/js/WebAssemblyModuleRecord.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorewasmwasmjson">trunk/Source/JavaScriptCore/wasm/wasm.json</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#trunkJSTestswasmfunctiontestsgrowmemory2js">trunk/JSTests/wasm/function-tests/grow-memory-2.js</a></li>
<li><a href="#trunkJSTestswasmfunctiontestsgrowmemory3js">trunk/JSTests/wasm/function-tests/grow-memory-3.js</a></li>
<li><a href="#trunkJSTestswasmfunctiontestsgrowmemory4js">trunk/JSTests/wasm/function-tests/grow-memory-4.js</a></li>
<li><a href="#trunkJSTestswasmfunctiontestsgrowmemoryjs">trunk/JSTests/wasm/function-tests/grow-memory.js</a></li>
<li><a href="#trunkJSTestswasmjsapimemorygrowjs">trunk/JSTests/wasm/js-api/memory-grow.js</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkJSTestsChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/JSTests/ChangeLog (210200 => 210201)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JSTests/ChangeLog        2016-12-28 14:36:15 UTC (rev 210200)
+++ trunk/JSTests/ChangeLog        2016-12-29 00:06:52 UTC (rev 210201)
</span><span class="lines">@@ -1,3 +1,49 @@
</span><ins>+2016-12-28  Saam Barati  &lt;sbarati@apple.com&gt;
+
+        WebAssembly: Implement grow_memory and current_memory
+        https://bugs.webkit.org/show_bug.cgi?id=166448
+        &lt;rdar://problem/29803676&gt;
+
+        Reviewed by Keith Miller.
+
+        I rewrote some of the testWasmModuleFunctions that used Memory to use
+        the JS API since the jsc.cpp version can no longer use memory.
+
+        * wasm.yaml:
+        * wasm/function-tests/add-12.js:
+        (testWasmModuleFunctions):
+        * wasm/function-tests/br-if-loop-less-than.js:
+        (testWasmModuleFunctions):
+        * wasm/function-tests/brTableAsIf.js:
+        (testWasmModuleFunctions):
+        * wasm/function-tests/brTableManyValues.js:
+        (testWasmModuleFunctions):
+        * wasm/function-tests/brTableWithLoop.js:
+        (testWasmModuleFunctions):
+        * wasm/function-tests/dumb-eq-if-then-else.js:
+        * wasm/function-tests/eqz.js:
+        * wasm/function-tests/grow-memory-2.js: Added.
+        (const.func):
+        (assert.eq.instance.exports.foo):
+        * wasm/function-tests/grow-memory-3.js: Added.
+        * wasm/function-tests/grow-memory-4.js: Added.
+        (const.func):
+        * wasm/function-tests/grow-memory.js: Added.
+        (binaryShouldNotParse):
+        (assert.truthy):
+        (assert.eq):
+        (memory.grow):
+        * wasm/function-tests/i32-load.js:
+        (testWasmModuleFunctions):
+        * wasm/function-tests/i32-load8-s.js:
+        * wasm/function-tests/max.js:
+        * wasm/function-tests/min.js:
+        * wasm/js-api/memory-grow.js: Added.
+        (i.i):
+        (assertEq):
+        * wasm/js-api/test_memory.js:
+        * wasm/wasm.json:
+
</ins><span class="cx"> 2016-12-25  Yusuke Suzuki  &lt;utatane.tea@gmail.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Propagate the source origin as much as possible
</span></span></pre></div>
<a id="trunkJSTestswasmfunctiontestsadd12js"></a>
<div class="modfile"><h4>Modified: trunk/JSTests/wasm/function-tests/add-12.js (210200 => 210201)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JSTests/wasm/function-tests/add-12.js        2016-12-28 14:36:15 UTC (rev 210200)
+++ trunk/JSTests/wasm/function-tests/add-12.js        2016-12-29 00:06:52 UTC (rev 210201)
</span><span class="lines">@@ -1,60 +1,72 @@
</span><span class="cx"> import Builder from '../Builder.js'
</span><ins>+import * as assert from '../assert.js'
</ins><span class="cx"> 
</span><span class="cx"> const b = new Builder();
</span><span class="cx"> b.Type().End()
</span><span class="cx">     .Function().End()
</span><ins>+    .Export().Function(&quot;f0&quot;).Function(&quot;f1&quot;).End()
</ins><span class="cx">     .Code()
</span><del>-    .Function({ params: [&quot;i32&quot;, &quot;i32&quot;, &quot;i32&quot;, &quot;i32&quot;, &quot;i32&quot;, &quot;i32&quot;, &quot;i32&quot;, &quot;i32&quot;, &quot;i32&quot;, &quot;i32&quot;, &quot;i32&quot;, &quot;i32&quot;], ret: &quot;i32&quot; }, [])
-    .GetLocal(0)
-    .GetLocal(1)
-    .I32Add()
-    .GetLocal(2)
-    .I32Add()
-    .GetLocal(3)
-    .I32Add()
-    .GetLocal(4)
-    .I32Add()
-    .GetLocal(5)
-    .I32Add()
-    .GetLocal(6)
-    .I32Add()
-    .GetLocal(7)
-    .I32Add()
-    .GetLocal(8)
-    .I32Add()
-    .GetLocal(9)
-    .I32Add()
-    .GetLocal(10)
-    .I32Add()
-    .GetLocal(11)
-    .I32Add()
-    .Return()
</del><ins>+        .Function(&quot;f0&quot;, { params: [&quot;i32&quot;, &quot;i32&quot;, &quot;i32&quot;, &quot;i32&quot;, &quot;i32&quot;, &quot;i32&quot;, &quot;i32&quot;, &quot;i32&quot;, &quot;i32&quot;, &quot;i32&quot;, &quot;i32&quot;, &quot;i32&quot;], ret: &quot;i32&quot; })
+            .GetLocal(0)
+            .GetLocal(1)
+            .I32Add()
+            .GetLocal(2)
+            .I32Add()
+            .GetLocal(3)
+            .I32Add()
+            .GetLocal(4)
+            .I32Add()
+            .GetLocal(5)
+            .I32Add()
+            .GetLocal(6)
+            .I32Add()
+            .GetLocal(7)
+            .I32Add()
+            .GetLocal(8)
+            .I32Add()
+            .GetLocal(9)
+            .I32Add()
+            .GetLocal(10)
+            .I32Add()
+            .GetLocal(11)
+            .I32Add()
+            .Return()
+        .End()
+        .Function(&quot;f1&quot;, { params: [&quot;i32&quot;], ret: &quot;i32&quot; })
+            .GetLocal(0)
+            .GetLocal(0)
+            .GetLocal(0)
+            .GetLocal(0)
+            .GetLocal(0)
+            .GetLocal(0)
+            .GetLocal(0)
+            .GetLocal(0)
+            .GetLocal(0)
+            .GetLocal(0)
+            .GetLocal(0)
+            .GetLocal(0)
+            .Call(0)
+            .Return()
+        .End()
</ins><span class="cx">     .End()
</span><span class="cx"> 
</span><del>-    .Function({ params: [&quot;i32&quot;], ret: &quot;i32&quot; })
-    .GetLocal(0)
-    .GetLocal(0)
-    .GetLocal(0)
-    .GetLocal(0)
-    .GetLocal(0)
-    .GetLocal(0)
-    .GetLocal(0)
-    .GetLocal(0)
-    .GetLocal(0)
-    .GetLocal(0)
-    .GetLocal(0)
-    .GetLocal(0)
-    .Call(0)
-    .End()
</del><ins>+const bin = b.WebAssembly().get();
+const instance = new WebAssembly.Instance(new WebAssembly.Module(bin));
+function testWasmModuleFunctions(...tests) {
+    for (let i = 0; i &lt; tests.length; i++) {
+        const func = instance.exports['f' + i];
+        for (let test of tests[i]) {
+            let result = test[0].value;
+            let args = test[1].map(x =&gt; x.value);
+            assert.eq(result, func(...args));
+        }
+    }
+}
</ins><span class="cx"> 
</span><del>-const bin = b.WebAssembly()
-bin.trim();
-testWasmModuleFunctions(bin.get(), 2,
-                        [[{ type: &quot;i32&quot;, value: 78 }, [{ type: &quot;i32&quot;, value: 1 }, { type: &quot;i32&quot;, value: 2 }, { type: &quot;i32&quot;, value: 3 }, { type: &quot;i32&quot;, value: 4 }, { type: &quot;i32&quot;, value: 5 }, { type: &quot;i32&quot;, value: 6 }, { type: &quot;i32&quot;, value: 7 }, { type: &quot;i32&quot;, value: 8 }, { type: &quot;i32&quot;, value: 9 }, { type: &quot;i32&quot;, value: 10 }, { type: &quot;i32&quot;, value: 11 }, { type: &quot;i32&quot;, value: 12 }]],
</del><ins>+testWasmModuleFunctions([[{ type: &quot;i32&quot;, value: 78 }, [{ type: &quot;i32&quot;, value: 1 }, { type: &quot;i32&quot;, value: 2 }, { type: &quot;i32&quot;, value: 3 }, { type: &quot;i32&quot;, value: 4 }, { type: &quot;i32&quot;, value: 5 }, { type: &quot;i32&quot;, value: 6 }, { type: &quot;i32&quot;, value: 7 }, { type: &quot;i32&quot;, value: 8 }, { type: &quot;i32&quot;, value: 9 }, { type: &quot;i32&quot;, value: 10 }, { type: &quot;i32&quot;, value: 11 }, { type: &quot;i32&quot;, value: 12 }]],
</ins><span class="cx">                          [{ type: &quot;i32&quot;, value: 166 }, [{ type: &quot;i32&quot;, value: 1 }, { type: &quot;i32&quot;, value: 2 }, { type: &quot;i32&quot;, value: 3 }, { type: &quot;i32&quot;, value: 4 }, { type: &quot;i32&quot;, value: 5 }, { type: &quot;i32&quot;, value: 6 }, { type: &quot;i32&quot;, value: 7 }, { type: &quot;i32&quot;, value: 8 }, { type: &quot;i32&quot;, value: 9 }, { type: &quot;i32&quot;, value: 10 }, { type: &quot;i32&quot;, value: 11 }, { type: &quot;i32&quot;, value: 100 }]]
</span><span class="cx">                         ],
</span><span class="cx">                         [[{ type: &quot;i32&quot;, value: 12 }, [{ type: &quot;i32&quot;, value: 1 }]],
</span><span class="cx">                          [{ type: &quot;i32&quot;, value: 1200 }, [{ type: &quot;i32&quot;, value: 100 }]],
</span><span class="cx">                          [{ type: &quot;i32&quot;, value: 0 }, [{ type: &quot;i32&quot;, value: 0 }]],
</span><del>-                        ]
-                       );
</del><ins>+                        ]);
</ins></span></pre></div>
<a id="trunkJSTestswasmfunctiontestsbriflooplessthanjs"></a>
<div class="modfile"><h4>Modified: trunk/JSTests/wasm/function-tests/br-if-loop-less-than.js (210200 => 210201)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JSTests/wasm/function-tests/br-if-loop-less-than.js        2016-12-28 14:36:15 UTC (rev 210200)
+++ trunk/JSTests/wasm/function-tests/br-if-loop-less-than.js        2016-12-29 00:06:52 UTC (rev 210201)
</span><span class="lines">@@ -1,10 +1,12 @@
</span><span class="cx"> import Builder from '../Builder.js'
</span><ins>+import * as assert from '../assert.js'
</ins><span class="cx"> 
</span><span class="cx"> const b = new Builder();
</span><span class="cx"> b.Type().End()
</span><span class="cx">     .Function().End()
</span><ins>+    .Export().Function(&quot;f0&quot;).End()
</ins><span class="cx">     .Code()
</span><del>-    .Function({ params: [&quot;i32&quot;, &quot;i32&quot;], ret: &quot;i32&quot; }, [])
</del><ins>+    .Function(&quot;f0&quot;, { params: [&quot;i32&quot;, &quot;i32&quot;], ret: &quot;i32&quot; })
</ins><span class="cx">     .Loop(&quot;void&quot;)
</span><span class="cx">     .Block(&quot;void&quot;, b =&gt;
</span><span class="cx">            b.Block(&quot;void&quot;, b =&gt;
</span><span class="lines">@@ -36,10 +38,23 @@
</span><span class="cx">     .End()
</span><span class="cx">     .Unreachable()
</span><span class="cx">     .End()
</span><ins>+    .End()
</ins><span class="cx"> 
</span><del>-const bin = b.WebAssembly()
-bin.trim();
-testWasmModuleFunctions(bin.get(), 1, [[{type: &quot;i32&quot;, value: 1 }, [{ type: &quot;i32&quot;, value: 0 }, { type: &quot;i32&quot;, value: 1 }]],
</del><ins>+const bin = b.WebAssembly().get();
+const instance = new WebAssembly.Instance(new WebAssembly.Module(bin));
+
+function testWasmModuleFunctions(...tests) {
+    for (let i = 0; i &lt; tests.length; i++) {
+        const func = instance.exports['f' + i];
+        for (let test of tests[i]) {
+            let result = test[0].value;
+            let args = test[1].map(x =&gt; x.value);
+            assert.eq(result, func(...args));
+        }
+    }
+}
+
+testWasmModuleFunctions([[{type: &quot;i32&quot;, value: 1 }, [{ type: &quot;i32&quot;, value: 0 }, { type: &quot;i32&quot;, value: 1 }]],
</ins><span class="cx">                                        [{type: &quot;i32&quot;, value: 0 }, [{ type: &quot;i32&quot;, value: 1 }, { type: &quot;i32&quot;, value: 0 }]],
</span><span class="cx">                                        [{type: &quot;i32&quot;, value: 0 }, [{ type: &quot;i32&quot;, value: 2 }, { type: &quot;i32&quot;, value: 1 }]],
</span><span class="cx">                                        [{type: &quot;i32&quot;, value: 1 }, [{ type: &quot;i32&quot;, value: 1 }, { type: &quot;i32&quot;, value: 2 }]],
</span></span></pre></div>
<a id="trunkJSTestswasmfunctiontestsbrTableAsIfjs"></a>
<div class="modfile"><h4>Modified: trunk/JSTests/wasm/function-tests/brTableAsIf.js (210200 => 210201)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JSTests/wasm/function-tests/brTableAsIf.js        2016-12-28 14:36:15 UTC (rev 210200)
+++ trunk/JSTests/wasm/function-tests/brTableAsIf.js        2016-12-29 00:06:52 UTC (rev 210201)
</span><span class="lines">@@ -1,24 +1,37 @@
</span><span class="cx"> import Builder from '../Builder.js'
</span><ins>+import * as assert from '../assert.js'
</ins><span class="cx"> 
</span><span class="cx"> const b = new Builder();
</span><span class="cx"> b.Type().End()
</span><span class="cx">     .Function().End()
</span><ins>+    .Export().Function('f0').End()
</ins><span class="cx">     .Code()
</span><del>-    .Function({ params: [&quot;i32&quot;], ret: &quot;i32&quot; }, [&quot;i32&quot;])
-    .Block(&quot;void&quot;, (b) =&gt;
-           b.Block(&quot;void&quot;, (b) =&gt;
-                   b.GetLocal(0)
-                   .BrTable(1, 0)
-                   .I32Const(21)
-                   .Return()
-                  ).I32Const(20)
-           .Return()
-          ).I32Const(22)
</del><ins>+        .Function('f0', { params: [&quot;i32&quot;], ret: &quot;i32&quot; }, [&quot;i32&quot;])
+        .Block(&quot;void&quot;, (b) =&gt;
+               b.Block(&quot;void&quot;, (b) =&gt;
+                       b.GetLocal(0)
+                       .BrTable(1, 0)
+                       .I32Const(21)
+                       .Return()
+                      ).I32Const(20)
+               .Return()
+              ).I32Const(22)
+        .End()
</ins><span class="cx">     .End()
</span><span class="cx"> 
</span><del>-const bin = b.WebAssembly()
-bin.trim();
-testWasmModuleFunctions(bin.get(), 1, [[{type: &quot;i32&quot;, value: 22 }, [{ type: &quot;i32&quot;, value: 0 }]],
</del><ins>+const bin = b.WebAssembly().get();
+const instance = new WebAssembly.Instance(new WebAssembly.Module(bin));
+function testWasmModuleFunctions(...tests) {
+    for (let i = 0; i &lt; tests.length; i++) {
+        const func = instance.exports['f' + i];
+        for (let test of tests[i]) {
+            let result = test[0].value;
+            let args = test[1].map(x =&gt; x.value);
+            assert.eq(result, func(...args));
+        }
+    }
+}
+testWasmModuleFunctions([[{type: &quot;i32&quot;, value: 22 }, [{ type: &quot;i32&quot;, value: 0 }]],
</ins><span class="cx">                                        [{type: &quot;i32&quot;, value: 20 }, [{ type: &quot;i32&quot;, value: 1 }]],
</span><span class="cx">                                        [{type: &quot;i32&quot;, value: 20 }, [{ type: &quot;i32&quot;, value: 11 }]],
</span><span class="cx">                                        [{type: &quot;i32&quot;, value: 20 }, [{ type: &quot;i32&quot;, value: -100 }]]
</span></span></pre></div>
<a id="trunkJSTestswasmfunctiontestsbrTableManyValuesjs"></a>
<div class="modfile"><h4>Modified: trunk/JSTests/wasm/function-tests/brTableManyValues.js (210200 => 210201)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JSTests/wasm/function-tests/brTableManyValues.js        2016-12-28 14:36:15 UTC (rev 210200)
+++ trunk/JSTests/wasm/function-tests/brTableManyValues.js        2016-12-29 00:06:52 UTC (rev 210201)
</span><span class="lines">@@ -1,10 +1,12 @@
</span><span class="cx"> import Builder from '../Builder.js'
</span><ins>+import * as assert from '../assert.js'
</ins><span class="cx"> 
</span><span class="cx"> const b = new Builder();
</span><span class="cx"> b.Type().End()
</span><span class="cx">     .Function().End()
</span><ins>+    .Export().Function('f0').End()
</ins><span class="cx">     .Code()
</span><del>-    .Function({ params: [&quot;i32&quot;], ret: &quot;i32&quot; }, [&quot;i32&quot;])
</del><ins>+    .Function('f0', { params: [&quot;i32&quot;], ret: &quot;i32&quot; }, [&quot;i32&quot;])
</ins><span class="cx">     .Block(&quot;i32&quot;, (b) =&gt;
</span><span class="cx">            b.Block(&quot;i32&quot;, (b) =&gt;
</span><span class="cx">                    b.Block(&quot;i32&quot;, (b) =&gt;
</span><span class="lines">@@ -29,9 +31,21 @@
</span><span class="cx">     .I32Add()
</span><span class="cx">     .Return()
</span><span class="cx">     .End()
</span><del>-const bin = b.WebAssembly()
-bin.trim();
-testWasmModuleFunctions(bin.get(), 1, [[{type: &quot;i32&quot;, value: 213 }, [{ type: &quot;i32&quot;, value: 0 }]],
</del><ins>+    .End()
+
+const bin = b.WebAssembly().get();
+const instance = new WebAssembly.Instance(new WebAssembly.Module(bin));
+function testWasmModuleFunctions(...tests) {
+    for (let i = 0; i &lt; tests.length; i++) {
+        const func = instance.exports['f' + i];
+        for (let test of tests[i]) {
+            let result = test[0].value;
+            let args = test[1].map(x =&gt; x.value);
+            assert.eq(result, func(...args));
+        }
+    }
+}
+testWasmModuleFunctions([[{type: &quot;i32&quot;, value: 213 }, [{ type: &quot;i32&quot;, value: 0 }]],
</ins><span class="cx">                                        [{type: &quot;i32&quot;, value: 212 }, [{ type: &quot;i32&quot;, value: 1 }]],
</span><span class="cx">                                        [{type: &quot;i32&quot;, value: 211 }, [{ type: &quot;i32&quot;, value: 2 }]],
</span><span class="cx">                                        [{type: &quot;i32&quot;, value: 210 }, [{ type: &quot;i32&quot;, value: 3 }]],
</span></span></pre></div>
<a id="trunkJSTestswasmfunctiontestsbrTableWithLoopjs"></a>
<div class="modfile"><h4>Modified: trunk/JSTests/wasm/function-tests/brTableWithLoop.js (210200 => 210201)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JSTests/wasm/function-tests/brTableWithLoop.js        2016-12-28 14:36:15 UTC (rev 210200)
+++ trunk/JSTests/wasm/function-tests/brTableWithLoop.js        2016-12-29 00:06:52 UTC (rev 210201)
</span><span class="lines">@@ -1,10 +1,12 @@
</span><span class="cx"> import Builder from '../Builder.js'
</span><ins>+import * as assert from '../assert.js'
</ins><span class="cx"> 
</span><span class="cx"> const b = new Builder();
</span><span class="cx"> b.Type().End()
</span><span class="cx">     .Function().End()
</span><ins>+    .Export().Function('f0').End()
</ins><span class="cx">     .Code()
</span><del>-    .Function({ params: [&quot;i32&quot;], ret: &quot;i32&quot; }, [&quot;i32&quot;])
</del><ins>+    .Function('f0', { params: [&quot;i32&quot;], ret: &quot;i32&quot; }, [&quot;i32&quot;])
</ins><span class="cx">     .Loop(&quot;void&quot;)
</span><span class="cx">     .Block(&quot;void&quot;, (b) =&gt;
</span><span class="cx"> 
</span><span class="lines">@@ -18,12 +20,23 @@
</span><span class="cx">            .I32Sub()
</span><span class="cx">            .SetLocal(0)
</span><span class="cx">            .BrTable(0, 1))
</span><del>-
</del><span class="cx">     .End()
</span><span class="cx">     .GetLocal(1)
</span><span class="cx">     .End()
</span><del>-const bin = b.WebAssembly()
-bin.trim();
-testWasmModuleFunctions(bin.get(), 1, [[{type: &quot;i32&quot;, value: 1 }, [{ type: &quot;i32&quot;, value: 0 }]],
</del><ins>+    .End()
+
+const bin = b.WebAssembly().get();
+const instance = new WebAssembly.Instance(new WebAssembly.Module(bin));
+function testWasmModuleFunctions(...tests) {
+    for (let i = 0; i &lt; tests.length; i++) {
+        const func = instance.exports['f' + i];
+        for (let test of tests[i]) {
+            let result = test[0].value;
+            let args = test[1].map(x =&gt; x.value);
+            assert.eq(result, func(...args));
+        }
+    }
+}
+testWasmModuleFunctions([[{type: &quot;i32&quot;, value: 1 }, [{ type: &quot;i32&quot;, value: 0 }]],
</ins><span class="cx">                                        [{type: &quot;i32&quot;, value: 2 }, [{ type: &quot;i32&quot;, value: 1 }]]
</span><span class="cx">                                       ]);
</span></span></pre></div>
<a id="trunkJSTestswasmfunctiontestsdumbeqifthenelsejs"></a>
<div class="modfile"><h4>Modified: trunk/JSTests/wasm/function-tests/dumb-eq-if-then-else.js (210200 => 210201)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JSTests/wasm/function-tests/dumb-eq-if-then-else.js        2016-12-28 14:36:15 UTC (rev 210200)
+++ trunk/JSTests/wasm/function-tests/dumb-eq-if-then-else.js        2016-12-29 00:06:52 UTC (rev 210201)
</span><span class="lines">@@ -3,7 +3,6 @@
</span><span class="cx"> const b = new Builder();
</span><span class="cx"> b.Type().End()
</span><span class="cx">     .Function().End()
</span><del>-    .Memory().InitialMaxPages(1, 1).End()
</del><span class="cx">     .Code()
</span><span class="cx">     .Function({ params: [&quot;i32&quot;, &quot;i32&quot;], ret: &quot;i32&quot; }, [])
</span><span class="cx">     .GetLocal(0)
</span></span></pre></div>
<a id="trunkJSTestswasmfunctiontestseqzjs"></a>
<div class="modfile"><h4>Modified: trunk/JSTests/wasm/function-tests/eqz.js (210200 => 210201)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JSTests/wasm/function-tests/eqz.js        2016-12-28 14:36:15 UTC (rev 210200)
+++ trunk/JSTests/wasm/function-tests/eqz.js        2016-12-29 00:06:52 UTC (rev 210201)
</span><span class="lines">@@ -3,7 +3,6 @@
</span><span class="cx"> const b = new Builder();
</span><span class="cx"> b.Type().End()
</span><span class="cx">     .Function().End()
</span><del>-    .Memory().InitialMaxPages(1, 1).End()
</del><span class="cx">     .Code()
</span><span class="cx">     .Function({ params: [&quot;i32&quot;], ret: &quot;i32&quot; }, [])
</span><span class="cx">     .GetLocal(0)
</span></span></pre></div>
<a id="trunkJSTestswasmfunctiontestsgrowmemory2js"></a>
<div class="addfile"><h4>Added: trunk/JSTests/wasm/function-tests/grow-memory-2.js (0 => 210201)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JSTests/wasm/function-tests/grow-memory-2.js                                (rev 0)
+++ trunk/JSTests/wasm/function-tests/grow-memory-2.js        2016-12-29 00:06:52 UTC (rev 210201)
</span><span class="lines">@@ -0,0 +1,82 @@
</span><ins>+import Builder from '../Builder.js';
+import * as assert from '../assert.js';
+
+{
+    const memoryDescription = {initial: 0, maximum: 2};
+    const builder = (new Builder())
+        .Type().End()
+        .Import()
+            .Memory(&quot;imp&quot;, &quot;memory&quot;, memoryDescription)
+            .Function(&quot;imp&quot;, &quot;func&quot;, {params: [], ret: &quot;void&quot;})
+        .End()
+        .Function().End()
+        .Export()
+            .Function(&quot;foo&quot;)
+        .End()
+        .Code()
+            .Function(&quot;foo&quot;, {params: [&quot;i32&quot;], ret: &quot;i32&quot;})
+                .Call(0)
+                .GetLocal(0)
+                .I32Load(0, 0)
+                .Return()
+            .End()
+        .End();
+
+    const bin = builder.WebAssembly().get();
+    const module = new WebAssembly.Module(bin);
+    const memory = new WebAssembly.Memory(memoryDescription);
+
+    const func = () =&gt; {
+        memory.grow(1);
+        (new Uint32Array(memory.buffer))[0] = 42;
+    };
+
+    const instance = new WebAssembly.Instance(module, {imp: {memory, func}});
+    assert.eq(instance.exports.foo(0), 42);
+}
+
+{
+    const memoryDescription = {initial: 0, maximum: 2};
+    const tableDescription = {initial: 1, maximum: 1, element: &quot;anyfunc&quot;};
+    const builder = (new Builder())
+        .Type()
+            .Func([], &quot;void&quot;)
+        .End()
+        .Import()
+            .Memory(&quot;imp&quot;, &quot;memory&quot;, memoryDescription)
+            .Function(&quot;imp&quot;, &quot;func&quot;, {params: [], ret: &quot;void&quot;})
+            .Table(&quot;imp&quot;, &quot;table&quot;, tableDescription)
+        .End()
+        .Function().End()
+        .Export()
+            .Function(&quot;foo&quot;)
+            .Function(&quot;bar&quot;)
+        .End()
+        .Code()
+            .Function(&quot;foo&quot;, {params: [&quot;i32&quot;], ret: &quot;i32&quot;})
+                .I32Const(0)
+                .CallIndirect(0, 0) // call [] =&gt; void
+                .GetLocal(0)
+                .I32Load(0, 0)
+                .Return()
+            .End()
+            .Function(&quot;bar&quot;, {params: [], ret: &quot;void&quot;})
+                .Call(0)
+                .Return()
+            .End()
+        .End();
+
+    const bin = builder.WebAssembly().get();
+    const module = new WebAssembly.Module(bin);
+    const memory = new WebAssembly.Memory(memoryDescription);
+    const table = new WebAssembly.Table(tableDescription);
+
+    const func = () =&gt; {
+        memory.grow(1);
+        (new Uint32Array(memory.buffer))[0] = 0xbadbeef;
+    };
+
+    const instance = new WebAssembly.Instance(module, {imp: {memory, func, table}});
+    table.set(0, instance.exports.bar);
+    assert.eq(instance.exports.foo(0), 0xbadbeef);
+}
</ins></span></pre></div>
<a id="trunkJSTestswasmfunctiontestsgrowmemory3js"></a>
<div class="addfile"><h4>Added: trunk/JSTests/wasm/function-tests/grow-memory-3.js (0 => 210201)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JSTests/wasm/function-tests/grow-memory-3.js                                (rev 0)
+++ trunk/JSTests/wasm/function-tests/grow-memory-3.js        2016-12-29 00:06:52 UTC (rev 210201)
</span><span class="lines">@@ -0,0 +1,34 @@
</span><ins>+import Builder from '../Builder.js';
+import * as assert from '../assert.js';
+
+{
+    const memoryDescription = {initial: 0, maximum: 2};
+    const builder = (new Builder())
+        .Type().End()
+        .Import()
+            .Memory(&quot;imp&quot;, &quot;memory&quot;, memoryDescription)
+        .End()
+        .Function().End()
+        .Export()
+            .Function(&quot;foo&quot;)
+            .Function(&quot;bar&quot;)
+        .End()
+        .Code()
+            .Function(&quot;foo&quot;, {params: [], ret: &quot;void&quot;})
+                .Unreachable()
+                .GrowMemory(0)
+            .End()
+            .Function(&quot;bar&quot;, {params: [], ret: &quot;void&quot;})
+                .Unreachable()
+                .CurrentMemory(0)
+            .End()
+        .End();
+
+    const bin = builder.WebAssembly().get();
+    const module = new WebAssembly.Module(bin); // Just make sure it parses.
+    const memory = new WebAssembly.Memory(memoryDescription);
+    const instance = new WebAssembly.Instance(module, {imp: {memory}});
+
+    assert.throws(() =&gt; instance.exports.foo(), WebAssembly.RuntimeError, &quot;Unreachable code should not be executed&quot;)
+    assert.throws(() =&gt; instance.exports.bar(), WebAssembly.RuntimeError, &quot;Unreachable code should not be executed&quot;)
+}
</ins></span></pre></div>
<a id="trunkJSTestswasmfunctiontestsgrowmemory4js"></a>
<div class="addfile"><h4>Added: trunk/JSTests/wasm/function-tests/grow-memory-4.js (0 => 210201)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JSTests/wasm/function-tests/grow-memory-4.js                                (rev 0)
+++ trunk/JSTests/wasm/function-tests/grow-memory-4.js        2016-12-29 00:06:52 UTC (rev 210201)
</span><span class="lines">@@ -0,0 +1,34 @@
</span><ins>+import Builder from '../Builder.js';
+import * as assert from '../assert.js';
+
+{
+    const memoryDescription = {initial: 0, maximum: 50};
+    const builder = (new Builder())
+        .Type().End()
+        .Import()
+            .Memory(&quot;imp&quot;, &quot;memory&quot;, memoryDescription)
+            .Function(&quot;imp&quot;, &quot;func&quot;, {params: [], ret: &quot;void&quot;})
+        .End()
+        .Function().End()
+        .Export()
+            .Function(&quot;foo&quot;)
+        .End()
+        .Code()
+            .Function(&quot;foo&quot;, {params: [], ret: &quot;i32&quot;})
+                .Call(0)
+                .CurrentMemory(0)
+                .Return()
+            .End()
+        .End();
+
+    const bin = builder.WebAssembly().get();
+    const module = new WebAssembly.Module(bin);
+    const memory = new WebAssembly.Memory(memoryDescription);
+
+    const func = () =&gt; {
+        memory.grow(42);
+    };
+
+    const instance = new WebAssembly.Instance(module, {imp: {memory, func}});
+    assert.eq(instance.exports.foo(), 42);
+}
</ins></span></pre></div>
<a id="trunkJSTestswasmfunctiontestsgrowmemoryjs"></a>
<div class="addfile"><h4>Added: trunk/JSTests/wasm/function-tests/grow-memory.js (0 => 210201)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JSTests/wasm/function-tests/grow-memory.js                                (rev 0)
+++ trunk/JSTests/wasm/function-tests/grow-memory.js        2016-12-29 00:06:52 UTC (rev 210201)
</span><span class="lines">@@ -0,0 +1,207 @@
</span><ins>+import Builder from '../Builder.js';
+import * as assert from '../assert.js';
+
+const pageSize = 64 * 1024;
+const maxPageCount = (2**32) / pageSize;
+
+function binaryShouldNotParse(builder, msg = &quot;&quot;) {
+    const bin = builder.WebAssembly().get();
+    let threw = false;
+    try {
+        const module = new WebAssembly.Module(bin);
+    } catch(e) {
+        assert.truthy(e instanceof WebAssembly.CompileError);
+        if (msg)
+            assert.truthy(e.message.indexOf(msg) !== -1);
+        threw = true;
+    }
+    assert.truthy(threw);
+}
+
+{
+    // Can't grow_memory if no memory is defined.
+    const builder = (new Builder())
+        .Type().End()
+        .Function().End()
+        .Export().End()
+        .Code()
+            .Function({ret: &quot;void&quot;, params: []})
+                .I32Const(25)
+                .GrowMemory(0)
+                .Drop()
+            .End()
+        .End();
+
+    binaryShouldNotParse(builder, &quot;grow_memory is only valid if a memory is defined or imported&quot;);
+}
+
+{
+    // Can't current_memory if no memory is defined.
+    const builder = (new Builder())
+        .Type().End()
+        .Function().End()
+        .Export().End()
+        .Code()
+            .Function({ret: &quot;void&quot;, params: []})
+                .I32Const(25)
+                .CurrentMemory(0)
+                .Drop()
+            .End()
+        .End();
+
+    binaryShouldNotParse(builder, &quot;current_memory is only valid if a memory is defined or imported&quot;);
+}
+
+{
+    const builder = (new Builder())
+        .Type().End()
+        .Function().End()
+        .Memory().InitialMaxPages(1, 1).End()
+        .Export().End()
+        .Code()
+            .Function({ret: &quot;void&quot;, params: []})
+                .I32Const(25)
+                .GrowMemory(1)
+                .Drop()
+            .End()
+        .End();
+
+    binaryShouldNotParse(builder, &quot;reserved varUint1 for grow_memory must be zero&quot;);
+}
+
+{
+    const builder = (new Builder())
+        .Type().End()
+        .Function().End()
+        .Memory().InitialMaxPages(1, 1).End()
+        .Export().End()
+        .Code()
+            .Function({ret: &quot;void&quot;, params: []})
+                .I32Const(25)
+                .CurrentMemory(1)
+                .Drop()
+            .End()
+        .End();
+
+    binaryShouldNotParse(builder, &quot;reserved varUint1 for current_memory must be zero&quot;);
+}
+
+{
+    const builder = (new Builder())
+        .Type().End()
+        .Function().End()
+        .Memory().InitialMaxPages(1, 1).End()
+        .Export().End()
+        .Code()
+            .Function({ret: &quot;void&quot;, params: []})
+                .I32Const(25)
+                .CurrentMemory(0xffffff00)
+                .Drop()
+            .End()
+        .End();
+
+    binaryShouldNotParse(builder, &quot;can't parse reserved varUint1 for current_memory&quot;);
+}
+
+{
+    const builder = (new Builder())
+        .Type().End()
+        .Function().End()
+        .Memory().InitialMaxPages(1, 1).End()
+        .Export().End()
+        .Code()
+            .Function({ret: &quot;void&quot;, params: []})
+                .I32Const(25)
+                .GrowMemory(0xffffff00)
+                .Drop()
+            .End()
+        .End();
+
+    binaryShouldNotParse(builder, &quot;can't parse reserved varUint1 for grow_memory&quot;);
+}
+
+{
+    const memoryDescription = {initial: 20, maximum: 50};
+    const builder = (new Builder())
+        .Type().End()
+        .Import().Memory(&quot;imp&quot;, &quot;memory&quot;, memoryDescription).End()
+        .Function().End()
+        .Export()
+            .Function(&quot;foo&quot;)
+        .End()
+        .Code()
+            .Function(&quot;foo&quot;, { params: [&quot;i32&quot;], ret: &quot;i32&quot;})
+                .GetLocal(0)
+                .GrowMemory(0)
+                .Return()
+            .End()
+        .End();
+
+    const bin = builder.WebAssembly().get();
+    const module = new WebAssembly.Module(bin);
+    const instance = new WebAssembly.Instance(module, {imp: {memory: new WebAssembly.Memory(memoryDescription)}});
+    let currentPageSize = memoryDescription.initial;
+    for (let i = 0; i &lt; memoryDescription.maximum - memoryDescription.initial; i++) {
+        assert.eq(instance.exports.foo(1), currentPageSize);
+        ++currentPageSize;
+    }
+
+    for (let i = 0; i &lt; 1000; i++) {
+        assert.eq(instance.exports.foo(1), -1);
+        assert.eq(instance.exports.foo(0), currentPageSize);
+    }
+}
+
+{
+    const memoryDescription = {initial: 20, maximum: 100};
+    const builder = (new Builder())
+        .Type().End()
+        .Import().Memory(&quot;imp&quot;, &quot;memory&quot;, memoryDescription).End()
+        .Function().End()
+        .Export()
+            .Function(&quot;foo&quot;)
+        .End()
+        .Code()
+            .Function(&quot;foo&quot;, { params: [], ret: &quot;i32&quot;})
+                .CurrentMemory(0)
+                .Return()
+            .End()
+        .End();
+
+    const bin = builder.WebAssembly().get();
+    const module = new WebAssembly.Module(bin);
+    const memory = new WebAssembly.Memory(memoryDescription);
+    const instance = new WebAssembly.Instance(module, {imp: {memory}});
+    let currentPageSize = memoryDescription.initial;
+    for (let i = 0; i &lt; memoryDescription.maximum - memoryDescription.initial; i++) {
+        assert.eq(instance.exports.foo(), currentPageSize);
+        ++currentPageSize;
+        memory.grow(1);
+    }
+}
+
+{
+    const memoryDescription = {initial: 20, maximum: 100};
+    const builder = (new Builder())
+        .Type().End()
+        .Import().Memory(&quot;imp&quot;, &quot;memory&quot;, memoryDescription).End()
+        .Function().End()
+        .Export()
+            .Function(&quot;foo&quot;)
+        .End()
+        .Code()
+            .Function(&quot;foo&quot;, { params: [], ret: &quot;i32&quot;})
+                .I32Const(-1)
+                .GrowMemory(0)
+                .Return()
+            .End()
+        .End();
+
+    const bin = builder.WebAssembly().get();
+    const module = new WebAssembly.Module(bin);
+    const memory = new WebAssembly.Memory(memoryDescription);
+    const instance = new WebAssembly.Instance(module, {imp: {memory}});
+    for (let i = 0; i &lt; 20; i++) {
+        assert.eq(instance.exports.foo(), -1);
+    }
+}
</ins></span></pre></div>
<a id="trunkJSTestswasmfunctiontestsi32loadjs"></a>
<div class="modfile"><h4>Modified: trunk/JSTests/wasm/function-tests/i32-load.js (210200 => 210201)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JSTests/wasm/function-tests/i32-load.js        2016-12-28 14:36:15 UTC (rev 210200)
+++ trunk/JSTests/wasm/function-tests/i32-load.js        2016-12-29 00:06:52 UTC (rev 210201)
</span><span class="lines">@@ -1,11 +1,13 @@
</span><span class="cx"> import Builder from '../Builder.js'
</span><ins>+import * as assert from '../assert.js'
</ins><span class="cx"> 
</span><span class="cx"> const b = new Builder();
</span><span class="cx"> b.Type().End()
</span><span class="cx">     .Function().End()
</span><span class="cx">     .Memory().InitialMaxPages(1, 1).End()
</span><ins>+    .Export().Function('f0').End()
</ins><span class="cx">     .Code()
</span><del>-    .Function({ params: [&quot;i32&quot;, &quot;i32&quot;], ret: &quot;i32&quot; }, [])
</del><ins>+    .Function('f0', { params: [&quot;i32&quot;, &quot;i32&quot;], ret: &quot;i32&quot; })
</ins><span class="cx">     .GetLocal(1)
</span><span class="cx">     .GetLocal(0)
</span><span class="cx">     .I32Store(2, 0)
</span><span class="lines">@@ -13,10 +15,21 @@
</span><span class="cx">     .I32Load(2, 0)
</span><span class="cx">     .Return()
</span><span class="cx">     .End()
</span><ins>+    .End();
</ins><span class="cx"> 
</span><del>-const bin = b.WebAssembly()
-bin.trim();
-testWasmModuleFunctions(bin.get(), 1, [[{type: &quot;i32&quot;, value: 0 }, [{ type: &quot;i32&quot;, value: 0 }, { type: &quot;i32&quot;, value: 10 }]],
</del><ins>+const bin = b.WebAssembly().get();
+const instance = new WebAssembly.Instance(new WebAssembly.Module(bin));
+function testWasmModuleFunctions(...tests) {
+    for (let i = 0; i &lt; tests.length; i++) {
+        const func = instance.exports['f' + i];
+        for (let test of tests[i]) {
+            let result = test[0].value;
+            let args = test[1].map(x =&gt; x.value);
+            assert.eq(result, func(...args));
+        }
+    }
+}
+testWasmModuleFunctions([[{type: &quot;i32&quot;, value: 0 }, [{ type: &quot;i32&quot;, value: 0 }, { type: &quot;i32&quot;, value: 10 }]],
</ins><span class="cx">                                        [{type: &quot;i32&quot;, value: 100 }, [{ type: &quot;i32&quot;, value: 100 }, { type: &quot;i32&quot;, value: 112 }]],
</span><span class="cx">                                        [{type: &quot;i32&quot;, value: 1000000 }, [{ type: &quot;i32&quot;, value: 1000000 }, { type: &quot;i32&quot;, value: 10 }]]
</span><span class="cx">                                       ]);
</span></span></pre></div>
<a id="trunkJSTestswasmfunctiontestsi32load8sjs"></a>
<div class="modfile"><h4>Modified: trunk/JSTests/wasm/function-tests/i32-load8-s.js (210200 => 210201)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JSTests/wasm/function-tests/i32-load8-s.js        2016-12-28 14:36:15 UTC (rev 210200)
+++ trunk/JSTests/wasm/function-tests/i32-load8-s.js        2016-12-29 00:06:52 UTC (rev 210201)
</span><span class="lines">@@ -1,22 +1,24 @@
</span><span class="cx"> import Builder from '../Builder.js'
</span><ins>+import * as assert from '../assert.js'
</ins><span class="cx"> 
</span><span class="cx"> const b = new Builder();
</span><span class="cx"> b.Type().End()
</span><span class="cx">     .Function().End()
</span><span class="cx">     .Memory().InitialMaxPages(1, 1).End()
</span><ins>+    .Export().Function(&quot;foo&quot;).End()
</ins><span class="cx">     .Code()
</span><del>-    .Function({ params: [&quot;i32&quot;, &quot;i32&quot;], ret: &quot;i32&quot; }, [])
-    .GetLocal(1)
-    .GetLocal(0)
-    .I32Store(2, 0)
-    .GetLocal(1)
-    .I32Load8S(2, 0)
-    .Return()
</del><ins>+        .Function(&quot;foo&quot;, { params: [&quot;i32&quot;, &quot;i32&quot;], ret: &quot;i32&quot; })
+            .GetLocal(1)
+            .GetLocal(0)
+            .I32Store(2, 0)
+            .GetLocal(1)
+            .I32Load8S(2, 0)
+            .Return()
+        .End()
</ins><span class="cx">     .End()
</span><span class="cx"> 
</span><del>-const bin = b.WebAssembly()
-bin.trim();
-testWasmModuleFunctions(bin.get(), 1, [[{type: &quot;i32&quot;, value: 0 }, [{ type: &quot;i32&quot;, value: 0 }, { type: &quot;i32&quot;, value: 10 }]],
-                                       [{type: &quot;i32&quot;, value: 100 }, [{ type: &quot;i32&quot;, value: 100 }, { type: &quot;i32&quot;, value: 112 }]],
-                                       [{type: &quot;i32&quot;, value: 0x40 }, [{ type: &quot;i32&quot;, value: 1000000 }, { type: &quot;i32&quot;, value: 10 }]]
-                                      ]);
</del><ins>+const bin = b.WebAssembly().get();
+const foo = (new WebAssembly.Instance(new WebAssembly.Module(bin))).exports.foo;
+assert.eq(foo(0, 10), 0);
+assert.eq(foo(100, 112), 100);
+assert.eq(foo(1000000, 10), 0x40);
</ins></span></pre></div>
<a id="trunkJSTestswasmfunctiontestsmaxjs"></a>
<div class="modfile"><h4>Modified: trunk/JSTests/wasm/function-tests/max.js (210200 => 210201)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JSTests/wasm/function-tests/max.js        2016-12-28 14:36:15 UTC (rev 210200)
+++ trunk/JSTests/wasm/function-tests/max.js        2016-12-29 00:06:52 UTC (rev 210201)
</span><span class="lines">@@ -3,7 +3,6 @@
</span><span class="cx"> const b = new Builder();
</span><span class="cx"> b.Type().End()
</span><span class="cx">     .Function().End()
</span><del>-    .Memory().InitialMaxPages(1, 1).End()
</del><span class="cx">     .Code()
</span><span class="cx">     .Function({ params: [&quot;f32&quot;, &quot;f32&quot;], ret: &quot;f32&quot; }, [])
</span><span class="cx">     .GetLocal(0)
</span></span></pre></div>
<a id="trunkJSTestswasmfunctiontestsminjs"></a>
<div class="modfile"><h4>Modified: trunk/JSTests/wasm/function-tests/min.js (210200 => 210201)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JSTests/wasm/function-tests/min.js        2016-12-28 14:36:15 UTC (rev 210200)
+++ trunk/JSTests/wasm/function-tests/min.js        2016-12-29 00:06:52 UTC (rev 210201)
</span><span class="lines">@@ -3,7 +3,6 @@
</span><span class="cx"> const b = new Builder();
</span><span class="cx"> b.Type().End()
</span><span class="cx">     .Function().End()
</span><del>-    .Memory().InitialMaxPages(1, 1).End()
</del><span class="cx">     .Code()
</span><span class="cx">     .Function({ params: [&quot;f32&quot;, &quot;f32&quot;], ret: &quot;f32&quot; }, [])
</span><span class="cx">     .GetLocal(0)
</span></span></pre></div>
<a id="trunkJSTestswasmjsapimemorygrowjs"></a>
<div class="addfile"><h4>Added: trunk/JSTests/wasm/js-api/memory-grow.js (0 => 210201)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JSTests/wasm/js-api/memory-grow.js                                (rev 0)
+++ trunk/JSTests/wasm/js-api/memory-grow.js        2016-12-29 00:06:52 UTC (rev 210201)
</span><span class="lines">@@ -0,0 +1,51 @@
</span><ins>+import { eq as assertEq, throws as assertThrows } from &quot;../assert.js&quot;;
+const pageSize = 64*1024;
+
+let buffers = [];
+for (let i = 0; i &lt; 100; i++) {
+    const max = 5;
+    let pageCount = 1;
+    let x = new WebAssembly.Memory({initial: 1, maximum: max});
+    for (let i = 0; i &lt; (max - 1); i++) {
+        let int8Array = new Uint8Array(x.buffer);
+
+        for (let i = 0; i &lt; pageSize; i++) {
+            assertEq(int8Array[pageSize*(pageCount - 1) + i], 0);
+            int8Array[pageSize*(pageCount - 1) + i] = pageCount;
+        }
+
+        for (let i = 0; i &lt; pageCount; i++) {
+            for (let j = 0; j &lt; pageSize; j++) {
+                assertEq(int8Array[i * pageSize + j], i + 1);
+            }
+        }
+
+        let buffer = x.buffer;
+        assertEq(buffer.byteLength, pageCount * pageSize);
+        buffers.push(buffer);
+        let previousPageSize = x.grow(1);
+        assertEq(buffer.byteLength, 0);
+        assertEq(previousPageSize, pageCount);
+        ++pageCount;
+    }
+}
+
+for (let buffer of buffers) {
+    assertEq(buffer.byteLength, 0);
+}
+
+{
+    const memory = new WebAssembly.Memory({initial: 1, maximum: 5});
+    let buffer = memory.buffer;
+    assertEq(buffer.byteLength, 1*64*1024);
+    memory.grow(1);
+    assertEq(buffer.byteLength, 0);
+
+    buffer = memory.buffer;
+    assertEq(buffer.byteLength, 2*64*1024);
+
+    // This shouldn't neuter the buffer since it fails.
+    assertThrows(() =&gt; memory.grow(1000), Error, &quot;Out of memory&quot;); 
+    assertEq(buffer.byteLength, 2*64*1024);
+    assertEq(memory.buffer, buffer);
+}
</ins></span></pre></div>
<a id="trunkJSTestswasmjsapitest_memoryjs"></a>
<div class="modfile"><h4>Modified: trunk/JSTests/wasm/js-api/test_memory.js (210200 => 210201)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JSTests/wasm/js-api/test_memory.js        2016-12-28 14:36:15 UTC (rev 210200)
+++ trunk/JSTests/wasm/js-api/test_memory.js        2016-12-29 00:06:52 UTC (rev 210201)
</span><span class="lines">@@ -1,4 +1,3 @@
</span><del>-// FIXME: use the assert library: https://bugs.webkit.org/show_bug.cgi?id=165684
</del><span class="cx"> import Builder from '../Builder.js';
</span><span class="cx"> import * as assert from '../assert.js';
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkJSTestswasmwasmjson"></a>
<div class="modfile"><h4>Modified: trunk/JSTests/wasm/wasm.json (210200 => 210201)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JSTests/wasm/wasm.json        2016-12-28 14:36:15 UTC (rev 210200)
+++ trunk/JSTests/wasm/wasm.json        2016-12-29 00:06:52 UTC (rev 210201)
</span><span class="lines">@@ -88,8 +88,8 @@
</span><span class="cx">         &quot;i64.store&quot;:           { &quot;category&quot;: &quot;memory&quot;,     &quot;value&quot;:  55, &quot;return&quot;: [],           &quot;parameter&quot;: [&quot;addr&quot;, &quot;i64&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;store to memory&quot; },
</span><span class="cx">         &quot;f32.store&quot;:           { &quot;category&quot;: &quot;memory&quot;,     &quot;value&quot;:  56, &quot;return&quot;: [],           &quot;parameter&quot;: [&quot;addr&quot;, &quot;f32&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;store to memory&quot; },
</span><span class="cx">         &quot;f64.store&quot;:           { &quot;category&quot;: &quot;memory&quot;,     &quot;value&quot;:  57, &quot;return&quot;: [],           &quot;parameter&quot;: [&quot;addr&quot;, &quot;f64&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;store to memory&quot; },
</span><del>-        &quot;current_memory&quot;:      { &quot;category&quot;: &quot;operation&quot;,  &quot;value&quot;:  63, &quot;return&quot;: [&quot;size&quot;],     &quot;parameter&quot;: [],                       &quot;immediate&quot;: [],                                                                                         &quot;description&quot;: &quot;query the size of memory&quot; },
-        &quot;grow_memory&quot;:         { &quot;category&quot;: &quot;operation&quot;,  &quot;value&quot;:  64, &quot;return&quot;: [&quot;size&quot;],     &quot;parameter&quot;: [&quot;size&quot;],                 &quot;immediate&quot;: [],                                                                                         &quot;description&quot;: &quot;grow the size of memory&quot; },
</del><ins>+        &quot;current_memory&quot;:      { &quot;category&quot;: &quot;operation&quot;,  &quot;value&quot;:  63, &quot;return&quot;: [&quot;size&quot;],     &quot;parameter&quot;: [],                       &quot;immediate&quot;: [{&quot;name&quot;: &quot;flags&quot;, &quot;type&quot;: &quot;varuint32&quot;}],                                                                                         &quot;description&quot;: &quot;query the size of memory&quot; },
+        &quot;grow_memory&quot;:         { &quot;category&quot;: &quot;operation&quot;,  &quot;value&quot;:  64, &quot;return&quot;: [&quot;size&quot;],     &quot;parameter&quot;: [&quot;size&quot;],                 &quot;immediate&quot;: [{&quot;name&quot;: &quot;flags&quot;, &quot;type&quot;: &quot;varuint32&quot;}],                                                                                         &quot;description&quot;: &quot;grow the size of memory&quot; },
</ins><span class="cx">         &quot;i32.add&quot;:             { &quot;category&quot;: &quot;arithmetic&quot;, &quot;value&quot;: 106, &quot;return&quot;: [&quot;i32&quot;],      &quot;parameter&quot;: [&quot;i32&quot;, &quot;i32&quot;],           &quot;immediate&quot;: [], &quot;b3op&quot;: &quot;Add&quot;          },
</span><span class="cx">         &quot;i32.sub&quot;:             { &quot;category&quot;: &quot;arithmetic&quot;, &quot;value&quot;: 107, &quot;return&quot;: [&quot;i32&quot;],      &quot;parameter&quot;: [&quot;i32&quot;, &quot;i32&quot;],           &quot;immediate&quot;: [], &quot;b3op&quot;: &quot;Sub&quot;          },
</span><span class="cx">         &quot;i32.mul&quot;:             { &quot;category&quot;: &quot;arithmetic&quot;, &quot;value&quot;: 108, &quot;return&quot;: [&quot;i32&quot;],      &quot;parameter&quot;: [&quot;i32&quot;, &quot;i32&quot;],           &quot;immediate&quot;: [], &quot;b3op&quot;: &quot;Mul&quot;          },
</span></span></pre></div>
<a id="trunkJSTestswasmyaml"></a>
<div class="modfile"><h4>Modified: trunk/JSTests/wasm.yaml (210200 => 210201)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JSTests/wasm.yaml        2016-12-28 14:36:15 UTC (rev 210200)
+++ trunk/JSTests/wasm.yaml        2016-12-29 00:06:52 UTC (rev 210201)
</span><span class="lines">@@ -143,7 +143,7 @@
</span><span class="cx">   cmd: runWebAssemblySpecTest :normal
</span><span class="cx"> 
</span><span class="cx"> - path: wasm/spec-tests/memory_trap.wast.js
</span><del>-  cmd: runWebAssemblySpecTest :skip
</del><ins>+  cmd: runWebAssemblySpecTest :normal
</ins><span class="cx"> 
</span><span class="cx"> - path: wasm/spec-tests/names.wast.js
</span><span class="cx">   cmd: runWebAssemblySpecTest :skip
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ChangeLog (210200 => 210201)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ChangeLog        2016-12-28 14:36:15 UTC (rev 210200)
+++ trunk/Source/JavaScriptCore/ChangeLog        2016-12-29 00:06:52 UTC (rev 210201)
</span><span class="lines">@@ -1,3 +1,97 @@
</span><ins>+2016-12-28  Saam Barati  &lt;sbarati@apple.com&gt;
+
+        WebAssembly: Implement grow_memory and current_memory
+        https://bugs.webkit.org/show_bug.cgi?id=166448
+        &lt;rdar://problem/29803676&gt;
+
+        Reviewed by Keith Miller.
+
+        This patch implements grow_memory, current_memory, and WebAssembly.prototype.grow.
+        See relevant spec texts here:
+        
+        https://github.com/WebAssembly/design/blob/master/Semantics.md#linear-memory-accesses
+        https://github.com/WebAssembly/design/blob/master/JS.md#webassemblymemoryprototypegrow
+        
+        I also fix a couple miscellaneous bugs:
+        
+        1. Data section now understands full init_exprs. 
+        2. parseVarUint1 no longer has a bug where we allow values larger than 1 if
+        their bottom 8 bits are zero.
+        
+        Since the JS API can now grow memory, we need to make calling an import
+        and call_indirect refresh the base memory register and the size registers.
+
+        * jsc.cpp:
+        (functionTestWasmModuleFunctions):
+        * runtime/Options.h:
+        * runtime/VM.h:
+        * wasm/WasmB3IRGenerator.cpp:
+        (JSC::Wasm::B3IRGenerator::B3IRGenerator):
+        (JSC::Wasm::reloadPinnedRegisters):
+        (JSC::Wasm::B3IRGenerator::emitReloadPinnedRegisters):
+        (JSC::Wasm::createJSToWasmWrapper):
+        (JSC::Wasm::parseAndCompile):
+        * wasm/WasmFormat.cpp:
+        (JSC::Wasm::Segment::create):
+        * wasm/WasmFormat.h:
+        (JSC::Wasm::I32InitExpr::I32InitExpr):
+        (JSC::Wasm::I32InitExpr::globalImport):
+        (JSC::Wasm::I32InitExpr::constValue):
+        (JSC::Wasm::I32InitExpr::isConst):
+        (JSC::Wasm::I32InitExpr::isGlobalImport):
+        (JSC::Wasm::I32InitExpr::globalImportIndex):
+        (JSC::Wasm::Segment::byte):
+        (JSC::Wasm::ModuleInformation::importFunctionCount):
+        (JSC::Wasm::ModuleInformation::hasMemory):
+        * wasm/WasmFunctionParser.h:
+        * wasm/WasmMemory.cpp:
+        (JSC::Wasm::Memory::Memory):
+        (JSC::Wasm::Memory::grow):
+        * wasm/WasmMemory.h:
+        (JSC::Wasm::Memory::size):
+        (JSC::Wasm::Memory::sizeInPages):
+        (JSC::Wasm::Memory::offsetOfMemory):
+        (JSC::Wasm::Memory::isValid): Deleted.
+        (JSC::Wasm::Memory::grow): Deleted.
+        * wasm/WasmModuleParser.cpp:
+        (JSC::Wasm::makeI32InitExpr):
+        * wasm/WasmModuleParser.h:
+        * wasm/WasmPageCount.h:
+        (JSC::Wasm::PageCount::bytes):
+        (JSC::Wasm::PageCount::pageCount):
+        (JSC::Wasm::PageCount::fromBytes):
+        (JSC::Wasm::PageCount::operator+):
+        * wasm/WasmParser.h:
+        (JSC::Wasm::Parser&lt;SuccessType&gt;::parseVarUInt1):
+        * wasm/WasmValidate.cpp:
+        * wasm/js/JSWebAssemblyInstance.h:
+        (JSC::JSWebAssemblyInstance::offsetOfMemory):
+        * wasm/js/JSWebAssemblyMemory.cpp:
+        (JSC::JSWebAssemblyMemory::~JSWebAssemblyMemory):
+        (JSC::JSWebAssemblyMemory::grow):
+        * wasm/js/JSWebAssemblyMemory.h:
+        (JSC::JSWebAssemblyMemory::offsetOfMemory):
+        * wasm/js/JSWebAssemblyModule.h:
+        (JSC::JSWebAssemblyModule::functionImportCount):
+        (JSC::JSWebAssemblyModule::jsEntrypointCalleeFromFunctionIndexSpace):
+        (JSC::JSWebAssemblyModule::wasmEntrypointCalleeFromFunctionIndexSpace):
+        (JSC::JSWebAssemblyModule::importCount): Deleted.
+        * wasm/js/WebAssemblyFunction.cpp:
+        (JSC::callWebAssemblyFunction):
+        * wasm/js/WebAssemblyInstanceConstructor.cpp:
+        (JSC::constructJSWebAssemblyInstance):
+        * wasm/js/WebAssemblyMemoryConstructor.cpp:
+        (JSC::constructJSWebAssemblyMemory):
+        * wasm/js/WebAssemblyMemoryPrototype.cpp:
+        (JSC::getMemory):
+        (JSC::webAssemblyMemoryProtoFuncBuffer):
+        (JSC::webAssemblyMemoryProtoFuncGrow):
+        * wasm/js/WebAssemblyModuleRecord.cpp:
+        (JSC::WebAssemblyModuleRecord::link):
+        (JSC::dataSegmentFail):
+        (JSC::WebAssemblyModuleRecord::evaluate):
+        * wasm/wasm.json:
+
</ins><span class="cx"> 2016-12-26  Yusuke Suzuki  &lt;utatane.tea@gmail.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Use variadic templates in JSC Parser to clean up
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejsccpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jsc.cpp (210200 => 210201)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jsc.cpp        2016-12-28 14:36:15 UTC (rev 210200)
+++ trunk/Source/JavaScriptCore/jsc.cpp        2016-12-29 00:06:52 UTC (rev 210201)
</span><span class="lines">@@ -2654,8 +2654,9 @@
</span><span class="cx">     std::unique_ptr&lt;Wasm::ModuleInformation&gt; moduleInformation = plan.takeModuleInformation();
</span><span class="cx"> 
</span><span class="cx">     if (!!moduleInformation-&gt;memory) {
</span><del>-        memory = std::make_unique&lt;Wasm::Memory&gt;(moduleInformation-&gt;memory.initial(), moduleInformation-&gt;memory.maximum());
-        RELEASE_ASSERT(memory-&gt;isValid());
</del><ins>+        bool failed;
+        memory = std::make_unique&lt;Wasm::Memory&gt;(moduleInformation-&gt;memory.initial(), moduleInformation-&gt;memory.maximum(), failed);
+        RELEASE_ASSERT(!failed);
</ins><span class="cx">         memoryBytes = memory-&gt;memory();
</span><span class="cx">         memorySize = memory-&gt;size();
</span><span class="cx">     }
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeOptionsh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/Options.h (210200 => 210201)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/Options.h        2016-12-28 14:36:15 UTC (rev 210200)
+++ trunk/Source/JavaScriptCore/runtime/Options.h        2016-12-29 00:06:52 UTC (rev 210201)
</span><span class="lines">@@ -417,6 +417,7 @@
</span><span class="cx">     v(bool, useCodeCache, true, Normal, &quot;If false, the unlinked byte code cache will not be used.&quot;) \
</span><span class="cx">     \
</span><span class="cx">     v(bool, useWebAssembly, true, Normal, &quot;Expose the WebAssembly global object.&quot;) \
</span><ins>+    v(bool, simulateWebAssemblyLowMemory, false, Normal, &quot;If true, the Memory object won't mmap the full 'maximum' range and instead will allocate the minimum required amount.&quot;) \
</ins><span class="cx"> 
</span><span class="cx"> enum OptionEquivalence {
</span><span class="cx">     SameOption,
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeVMh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/VM.h (210200 => 210201)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/VM.h        2016-12-28 14:36:15 UTC (rev 210200)
+++ trunk/Source/JavaScriptCore/runtime/VM.h        2016-12-29 00:06:52 UTC (rev 210201)
</span><span class="lines">@@ -301,8 +301,6 @@
</span><span class="cx">     // https://bugs.webkit.org/show_bug.cgi?id=160441
</span><span class="cx">     ExecState* topCallFrame;
</span><span class="cx">     JSWebAssemblyInstance* topJSWebAssemblyInstance;
</span><del>-    void* topWasmMemoryPointer;
-    uint32_t topWasmMemorySize;
</del><span class="cx">     Strong&lt;Structure&gt; structureStructure;
</span><span class="cx">     Strong&lt;Structure&gt; structureRareDataStructure;
</span><span class="cx">     Strong&lt;Structure&gt; terminatedExecutionErrorStructure;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorewasmWasmB3IRGeneratorcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/wasm/WasmB3IRGenerator.cpp (210200 => 210201)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/wasm/WasmB3IRGenerator.cpp        2016-12-28 14:36:15 UTC (rev 210200)
+++ trunk/Source/JavaScriptCore/wasm/WasmB3IRGenerator.cpp        2016-12-29 00:06:52 UTC (rev 210201)
</span><span class="lines">@@ -172,6 +172,8 @@
</span><span class="cx">     // Memory
</span><span class="cx">     PartialResult WARN_UNUSED_RETURN load(LoadOpType, ExpressionType pointer, ExpressionType&amp; result, uint32_t offset);
</span><span class="cx">     PartialResult WARN_UNUSED_RETURN store(StoreOpType, ExpressionType pointer, ExpressionType value, uint32_t offset);
</span><ins>+    PartialResult WARN_UNUSED_RETURN addGrowMemory(ExpressionType delta, ExpressionType&amp; result);
+    PartialResult WARN_UNUSED_RETURN addCurrentMemory(ExpressionType&amp; result);
</ins><span class="cx"> 
</span><span class="cx">     // Basic operators
</span><span class="cx">     template&lt;OpType&gt;
</span><span class="lines">@@ -203,6 +205,8 @@
</span><span class="cx"> 
</span><span class="cx">     void emitExceptionCheck(CCallHelpers&amp;, ExceptionType);
</span><span class="cx"> 
</span><ins>+    void emitReloadPinnedRegisters();
+
</ins><span class="cx"> private:
</span><span class="cx">     ExpressionType emitCheckAndPreparePointer(ExpressionType pointer, uint32_t offset, uint32_t sizeOfOp);
</span><span class="cx">     ExpressionType emitLoadOp(LoadOpType, Origin, ExpressionType pointer, uint32_t offset);
</span><span class="lines">@@ -250,7 +254,7 @@
</span><span class="cx">         }
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    if (!!info.memory) {
</del><ins>+    if (info.hasMemory()) {
</ins><span class="cx">         m_memoryBaseGPR = info.memory.pinnedRegisters().baseMemoryPointer;
</span><span class="cx">         m_proc.pinRegister(m_memoryBaseGPR);
</span><span class="cx">         ASSERT(!info.memory.pinnedRegisters().sizeRegisters[0].sizeOffset);
</span><span class="lines">@@ -334,6 +338,96 @@
</span><span class="cx">     return { };
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+static void reloadPinnedRegisters(Procedure&amp; proc, BasicBlock* block, const ModuleInformation&amp; info, Value* instance)
+{
+    if (!info.hasMemory())
+        return;
+
+    const MemoryInformation* memory = &amp;info.memory;
+
+    RegisterSet clobbers;
+    clobbers.set(memory-&gt;pinnedRegisters().baseMemoryPointer);
+    for (auto info : memory-&gt;pinnedRegisters().sizeRegisters)
+        clobbers.set(info.sizeRegister);
+
+    B3::PatchpointValue* patchpoint = block-&gt;appendNew&lt;B3::PatchpointValue&gt;(proc, B3::Void, Origin());
+    patchpoint-&gt;effects = Effects::none();
+    patchpoint-&gt;effects.writesPinned = true;
+    patchpoint-&gt;clobber(clobbers);
+    patchpoint-&gt;numGPScratchRegisters = 1;
+
+    patchpoint-&gt;append(instance, ValueRep::SomeRegister);
+
+    patchpoint-&gt;setGenerator([memory] (CCallHelpers&amp; jit, const B3::StackmapGenerationParams&amp; params) {
+        AllowMacroScratchRegisterUsage allowScratch(jit);
+
+        GPRReg scratch = params.gpScratch(0);
+        jit.loadPtr(CCallHelpers::Address(params[0].gpr(), JSWebAssemblyInstance::offsetOfMemory()), scratch);
+        jit.loadPtr(CCallHelpers::Address(scratch, JSWebAssemblyMemory::offsetOfMemory()), scratch);
+        jit.loadPtr(CCallHelpers::Address(scratch, Memory::offsetOfMemory()), memory-&gt;pinnedRegisters().baseMemoryPointer);
+
+        jit.load64(CCallHelpers::Address(scratch, Memory::offsetOfSize()), scratch);
+        for (unsigned i = 0; i &lt; memory-&gt;pinnedRegisters().sizeRegisters.size(); i++) {
+            GPRReg sizeReg = memory-&gt;pinnedRegisters().sizeRegisters[i].sizeRegister;
+            jit.move(scratch, sizeReg);
+            jit.sub64(CCallHelpers::TrustedImm32(memory-&gt;pinnedRegisters().sizeRegisters[i].sizeOffset), sizeReg);
+        }
+    });
+}
+
+void B3IRGenerator::emitReloadPinnedRegisters()
+{
+    reloadPinnedRegisters(m_proc, m_currentBlock, m_info, m_instanceValue);
+}
+
+
+auto B3IRGenerator::addGrowMemory(ExpressionType delta, ExpressionType&amp; result) -&gt; PartialResult
+{
+    int32_t (*growMemory) (ExecState*, int32_t) = [] (ExecState* exec, int32_t delta) -&gt; int32_t {
+        VM&amp; vm = exec-&gt;vm();
+        auto scope = DECLARE_THROW_SCOPE(vm);
+
+        JSWebAssemblyInstance* instance = vm.topJSWebAssemblyInstance;
+        JSWebAssemblyMemory* wasmMemory = instance-&gt;memory();
+        RELEASE_ASSERT(wasmMemory); // This would fail validation otherwise.
+
+        if (delta &lt; 0)
+            return -1;
+
+        bool shouldThrowExceptionsOnFailure = false;
+        PageCount result = wasmMemory-&gt;grow(exec, static_cast&lt;uint32_t&gt;(delta), shouldThrowExceptionsOnFailure);
+        RELEASE_ASSERT(!scope.exception());
+        if (!result)
+            return -1;
+
+        return result.pageCount();
+    };
+
+    result = m_currentBlock-&gt;appendNew&lt;CCallValue&gt;(m_proc, Int32, Origin(),
+        m_currentBlock-&gt;appendNew&lt;ConstPtrValue&gt;(m_proc, Origin(), bitwise_cast&lt;void*&gt;(growMemory)),
+        m_currentBlock-&gt;appendNew&lt;B3::Value&gt;(m_proc, B3::FramePointer, Origin()), delta);
+
+    emitReloadPinnedRegisters();
+
+    return { };
+}
+
+auto B3IRGenerator::addCurrentMemory(ExpressionType&amp; result) -&gt; PartialResult
+{
+    Value* jsMemory = m_currentBlock-&gt;appendNew&lt;MemoryValue&gt;(m_proc, Load, pointerType(), Origin(), m_instanceValue, JSWebAssemblyInstance::offsetOfMemory());
+    Value* wasmMemory = m_currentBlock-&gt;appendNew&lt;MemoryValue&gt;(m_proc, Load, pointerType(), Origin(), jsMemory, JSWebAssemblyMemory::offsetOfMemory());
+    Value* size = m_currentBlock-&gt;appendNew&lt;MemoryValue&gt;(m_proc, Load, B3::Int64, Origin(), wasmMemory, Memory::offsetOfSize());
+
+    constexpr uint32_t shiftValue = 16;
+    static_assert(PageCount::pageSize == 1 &lt;&lt; shiftValue, &quot;This must hold for the code below to be correct.&quot;);
+    Value* numPages = m_currentBlock-&gt;appendNew&lt;Value&gt;(m_proc, ZShr, Origin(),
+        size, m_currentBlock-&gt;appendNew&lt;Const32Value&gt;(m_proc, Origin(), shiftValue));
+
+    result = m_currentBlock-&gt;appendNew&lt;Value&gt;(m_proc, Trunc, Origin(), numPages);
+
+    return { };
+}
+
</ins><span class="cx"> auto B3IRGenerator::setLocal(uint32_t index, ExpressionType value) -&gt; PartialResult
</span><span class="cx"> {
</span><span class="cx">     ASSERT(m_locals[index]);
</span><span class="lines">@@ -755,6 +849,10 @@
</span><span class="cx">                 });
</span><span class="cx">             });
</span><span class="cx">         });
</span><ins>+
+    if (functionIndex &lt; m_info.importFunctionCount())
+        emitReloadPinnedRegisters();
+
</ins><span class="cx">     return { };
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -831,6 +929,8 @@
</span><span class="cx">             });
</span><span class="cx">         });
</span><span class="cx"> 
</span><ins>+    emitReloadPinnedRegisters();
+
</ins><span class="cx">     return { };
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -871,7 +971,7 @@
</span><span class="cx">     dataLogLn();
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-static void createJSToWasmWrapper(VM&amp; vm, CompilationContext&amp; compilationContext, WasmInternalFunction&amp; function, const Signature* signature, const MemoryInformation&amp; memory)
</del><ins>+static void createJSToWasmWrapper(VM&amp; vm, CompilationContext&amp; compilationContext, WasmInternalFunction&amp; function, const Signature* signature, const ModuleInformation&amp; info)
</ins><span class="cx"> {
</span><span class="cx">     Procedure proc;
</span><span class="cx">     BasicBlock* block = proc.addBlock();
</span><span class="lines">@@ -899,18 +999,10 @@
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     // Move memory values to the approriate places, if needed.
</span><del>-    Value* baseMemory = nullptr;
-    Vector&lt;Value*&gt; sizes;
-    if (!!memory) {
-        baseMemory = block-&gt;appendNew&lt;MemoryValue&gt;(proc, Load, Int64, Origin(),
-            block-&gt;appendNew&lt;ConstPtrValue&gt;(proc, Origin(), &amp;vm.topWasmMemoryPointer));
-        Value* size = block-&gt;appendNew&lt;MemoryValue&gt;(proc, Load, Int32, Origin(),
-            block-&gt;appendNew&lt;ConstPtrValue&gt;(proc, Origin(), &amp;vm.topWasmMemorySize));
-        sizes.reserveCapacity(memory.pinnedRegisters().sizeRegisters.size());
-        for (auto info : memory.pinnedRegisters().sizeRegisters) {
-            sizes.append(block-&gt;appendNew&lt;Value&gt;(proc, Sub, origin, size,
-                block-&gt;appendNew&lt;Const32Value&gt;(proc, origin, info.sizeOffset)));
-        }
</del><ins>+    {
+        Value* instance = block-&gt;appendNew&lt;MemoryValue&gt;(proc, Load, pointerType(), Origin(),
+            block-&gt;appendNew&lt;ConstPtrValue&gt;(proc, Origin(), &amp;vm.topJSWebAssemblyInstance));
+        reloadPinnedRegisters(proc, block, info, instance);
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     // Get our arguments.
</span><span class="lines">@@ -921,13 +1013,6 @@
</span><span class="cx"> 
</span><span class="cx">     // Move the arguments into place.
</span><span class="cx">     Value* result = wasmCallingConvention().setupCall(proc, block, origin, arguments, toB3Type(signature-&gt;returnType()), [&amp;] (PatchpointValue* patchpoint) {
</span><del>-        if (!!memory) {
-            ASSERT(sizes.size() == memory.pinnedRegisters().sizeRegisters.size());
-            patchpoint-&gt;append(ConstrainedValue(baseMemory, ValueRep::reg(memory.pinnedRegisters().baseMemoryPointer)));
-            for (unsigned i = 0; i &lt; sizes.size(); ++i)
-                patchpoint-&gt;append(ConstrainedValue(sizes[i], ValueRep::reg(memory.pinnedRegisters().sizeRegisters[i].sizeRegister)));
-        }
-
</del><span class="cx">         CompilationContext* context = &amp;compilationContext;
</span><span class="cx">         patchpoint-&gt;setGenerator([context] (CCallHelpers&amp; jit, const B3::StackmapGenerationParams&amp;) {
</span><span class="cx">             AllowMacroScratchRegisterUsage allowScratch(jit);
</span><span class="lines">@@ -989,7 +1074,7 @@
</span><span class="cx">         result-&gt;wasmEntrypoint.calleeSaveRegisters = procedure.calleeSaveRegisters();
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    createJSToWasmWrapper(vm, compilationContext, *result, signature, info.memory);
</del><ins>+    createJSToWasmWrapper(vm, compilationContext, *result, signature, info);
</ins><span class="cx">     return WTFMove(result);
</span><span class="cx"> }
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorewasmWasmFormatcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/wasm/WasmFormat.cpp (210200 => 210201)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/wasm/WasmFormat.cpp        2016-12-28 14:36:15 UTC (rev 210200)
+++ trunk/Source/JavaScriptCore/wasm/WasmFormat.cpp        2016-12-29 00:06:52 UTC (rev 210201)
</span><span class="lines">@@ -34,7 +34,7 @@
</span><span class="cx"> 
</span><span class="cx"> namespace JSC { namespace Wasm {
</span><span class="cx"> 
</span><del>-Segment* Segment::create(uint32_t offset, uint32_t sizeInBytes)
</del><ins>+Segment* Segment::create(I32InitExpr offset, uint32_t sizeInBytes)
</ins><span class="cx"> {
</span><span class="cx">     auto allocated = tryFastCalloc(sizeof(Segment) + sizeInBytes, 1);
</span><span class="cx">     Segment* segment;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorewasmWasmFormath"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/wasm/WasmFormat.h (210200 => 210201)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/wasm/WasmFormat.h        2016-12-28 14:36:15 UTC (rev 210200)
+++ trunk/Source/JavaScriptCore/wasm/WasmFormat.h        2016-12-29 00:06:52 UTC (rev 210201)
</span><span class="lines">@@ -138,16 +138,51 @@
</span><span class="cx">     size_t end;
</span><span class="cx"> };
</span><span class="cx"> 
</span><ins>+class I32InitExpr {
+    enum Type : uint8_t {
+        Global,
+        Const
+    };
+
+    I32InitExpr(Type type, uint32_t bits)
+        : m_bits(bits)
+        , m_type(type)
+    { }
+
+public:
+    I32InitExpr() = delete;
+
+    static I32InitExpr globalImport(uint32_t globalImportNumber) { return I32InitExpr(Global, globalImportNumber); }
+    static I32InitExpr constValue(uint32_t constValue) { return I32InitExpr(Const, constValue); }
+
+    bool isConst() const { return m_type == Const; }
+    bool isGlobalImport() const { return m_type == Global; }
+    uint32_t constValue() const
+    {
+        RELEASE_ASSERT(isConst());
+        return m_bits;
+    }
+    uint32_t globalImportIndex() const
+    {
+        RELEASE_ASSERT(isGlobalImport());
+        return m_bits;
+    }
+
+private:
+    uint32_t m_bits;
+    Type m_type;
+};
+
</ins><span class="cx"> struct Segment {
</span><del>-    uint32_t offset;
</del><span class="cx">     uint32_t sizeInBytes;
</span><ins>+    I32InitExpr offset;
</ins><span class="cx">     // Bytes are allocated at the end.
</span><span class="cx">     uint8_t&amp; byte(uint32_t pos)
</span><span class="cx">     {
</span><span class="cx">         ASSERT(pos &lt; sizeInBytes);
</span><del>-        return *reinterpret_cast&lt;uint8_t*&gt;(reinterpret_cast&lt;char*&gt;(this) + sizeof(offset) + sizeof(sizeInBytes) + pos);
</del><ins>+        return *reinterpret_cast&lt;uint8_t*&gt;(reinterpret_cast&lt;char*&gt;(this) + sizeof(Segment) + pos);
</ins><span class="cx">     }
</span><del>-    static Segment* create(uint32_t, uint32_t);
</del><ins>+    static Segment* create(I32InitExpr, uint32_t);
</ins><span class="cx">     static void destroy(Segment*);
</span><span class="cx">     typedef std::unique_ptr&lt;Segment, decltype(&amp;Segment::destroy)&gt; Ptr;
</span><span class="cx">     static Ptr adoptPtr(Segment*);
</span><span class="lines">@@ -191,7 +226,9 @@
</span><span class="cx">     Vector&lt;Import&gt; imports;
</span><span class="cx">     Vector&lt;SignatureIndex&gt; importFunctionSignatureIndices;
</span><span class="cx">     Vector&lt;SignatureIndex&gt; internalFunctionSignatureIndices;
</span><ins>+
</ins><span class="cx">     MemoryInformation memory;
</span><ins>+
</ins><span class="cx">     Vector&lt;Export&gt; exports;
</span><span class="cx">     std::optional&lt;uint32_t&gt; startFunctionIndexSpace;
</span><span class="cx">     Vector&lt;Segment::Ptr&gt; data;
</span><span class="lines">@@ -200,6 +237,9 @@
</span><span class="cx">     Vector&lt;Global&gt; globals;
</span><span class="cx">     unsigned firstInternalGlobal { 0 };
</span><span class="cx"> 
</span><ins>+    uint32_t importFunctionCount() const { return importFunctionSignatureIndices.size(); }
+    bool hasMemory() const { return !!memory; }
+
</ins><span class="cx">     ~ModuleInformation();
</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 (210200 => 210201)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/wasm/WasmFunctionParser.h        2016-12-28 14:36:15 UTC (rev 210200)
+++ trunk/Source/JavaScriptCore/wasm/WasmFunctionParser.h        2016-12-29 00:06:52 UTC (rev 210201)
</span><span class="lines">@@ -478,14 +478,38 @@
</span><span class="cx">         return { };
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    case GrowMemory:
-        return fail(&quot;not yet implemented: grow_memory&quot;); // FIXME: Not yet implemented.
</del><ins>+    case GrowMemory: {
+        WASM_PARSER_FAIL_IF(!m_info.memory, &quot;grow_memory is only valid if a memory is defined or imported&quot;);
</ins><span class="cx"> 
</span><del>-    case CurrentMemory:
-        return fail(&quot;not yet implemented: current_memory&quot;); // FIXME: Not yet implemented.
</del><ins>+        uint8_t reserved;
+        WASM_PARSER_FAIL_IF(!parseVarUInt1(reserved), &quot;can't parse reserved varUint1 for grow_memory&quot;);
+        WASM_PARSER_FAIL_IF(reserved != 0, &quot;reserved varUint1 for grow_memory must be zero&quot;);
</ins><span class="cx"> 
</span><ins>+        ExpressionType delta;
+        WASM_TRY_POP_EXPRESSION_STACK_INTO(delta, &quot;expect an i32 argument to grow_memory on the stack&quot;);
+
+        ExpressionType result;
+        WASM_TRY_ADD_TO_CONTEXT(addGrowMemory(delta, result));
+        m_expressionStack.append(result);
+
+        return { };
</ins><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    case CurrentMemory: {
+        WASM_PARSER_FAIL_IF(!m_info.memory, &quot;current_memory is only valid if a memory is defined or imported&quot;);
+
+        uint8_t reserved;
+        WASM_PARSER_FAIL_IF(!parseVarUInt1(reserved), &quot;can't parse reserved varUint1 for current_memory&quot;);
+        WASM_PARSER_FAIL_IF(reserved != 0, &quot;reserved varUint1 for current_memory must be zero&quot;);
+
+        ExpressionType result;
+        WASM_TRY_ADD_TO_CONTEXT(addCurrentMemory(result));
+        m_expressionStack.append(result);
+
+        return { };
+    }
+    }
+
</ins><span class="cx">     ASSERT_NOT_REACHED();
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -584,6 +608,13 @@
</span><span class="cx">         return { };
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    case GrowMemory:
+    case CurrentMemory: {
+        uint8_t reserved;
+        WASM_PARSER_FAIL_IF(!parseVarUInt1(reserved), &quot;can't parse reserved varUint1 for grow_memory/current_memory&quot;);
+        return { };
+    }
+
</ins><span class="cx">     // no immediate cases
</span><span class="cx">     FOR_EACH_WASM_BINARY_OP(CREATE_CASE)
</span><span class="cx">     FOR_EACH_WASM_UNARY_OP(CREATE_CASE)
</span><span class="lines">@@ -591,9 +622,7 @@
</span><span class="cx">     case Nop:
</span><span class="cx">     case Return:
</span><span class="cx">     case Select:
</span><del>-    case Drop:
-    case GrowMemory:
-    case CurrentMemory: {
</del><ins>+    case Drop: {
</ins><span class="cx">         return { };
</span><span class="cx">     }
</span><span class="cx">     }
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorewasmWasmMemorycpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/wasm/WasmMemory.cpp (210200 => 210201)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/wasm/WasmMemory.cpp        2016-12-28 14:36:15 UTC (rev 210200)
+++ trunk/Source/JavaScriptCore/wasm/WasmMemory.cpp        2016-12-29 00:06:52 UTC (rev 210201)
</span><span class="lines">@@ -30,37 +30,89 @@
</span><span class="cx"> 
</span><span class="cx"> namespace JSC { namespace Wasm {
</span><span class="cx"> 
</span><del>-Memory::Memory(PageCount initial, PageCount maximum)
</del><ins>+static_assert(sizeof(uint64_t) == sizeof(size_t), &quot;We rely on allowing the maximum size of Memory we map to be 2^32 which is larger than fits in a 32-bit integer that we'd pass to mprotect if this didn't hold.&quot;);
+
+Memory::Memory(PageCount initial, PageCount maximum, bool&amp; failed)
</ins><span class="cx">     : m_mode(Mode::BoundsChecking)
</span><del>-    , m_size(initial.bytes())
-    , m_capacity(maximum ? maximum.bytes() : PageCount::max().bytes())
</del><span class="cx">     , m_initial(initial)
</span><span class="cx">     , m_maximum(maximum)
</span><ins>+    , m_size(initial.bytes())
</ins><span class="cx">     // FIXME: If we add signal based bounds checking then we need extra space for overflow on load.
</span><span class="cx">     // see: https://bugs.webkit.org/show_bug.cgi?id=162693
</span><span class="cx"> {
</span><span class="cx">     RELEASE_ASSERT(!maximum || maximum &gt;= initial); // This should be guaranteed by our caller.
</span><span class="cx"> 
</span><del>-    m_mappedCapacity = m_capacity;
</del><ins>+    m_mappedCapacity = maximum ? maximum.bytes() : PageCount::max().bytes();
+    if (!m_mappedCapacity) {
+        // This means we specified a zero as maximum (which means we also have zero as initial size).
+        RELEASE_ASSERT(m_size == 0);
+        m_mappedCapacity = 0;
+        m_memory = nullptr;
+        failed = false;
+        return;
+    }
+
</ins><span class="cx">     // FIXME: It would be nice if we had a VM tag for wasm memory. https://bugs.webkit.org/show_bug.cgi?id=163600
</span><del>-    void* result = mmap(nullptr, m_mappedCapacity, PROT_NONE, MAP_PRIVATE | MAP_ANON, -1, 0);
</del><ins>+    void* result = Options::simulateWebAssemblyLowMemory() ? MAP_FAILED : mmap(nullptr, m_mappedCapacity, PROT_NONE, MAP_PRIVATE | MAP_ANON, -1, 0);
</ins><span class="cx">     if (result == MAP_FAILED) {
</span><span class="cx">         // Try again with a different number.
</span><span class="cx">         m_mappedCapacity = m_size;
</span><ins>+        if (!m_mappedCapacity) {
+            m_memory = nullptr;
+            failed = false;
+            return;
+        }
+
</ins><span class="cx">         result = mmap(nullptr, m_mappedCapacity, PROT_NONE, MAP_PRIVATE | MAP_ANON, -1, 0);
</span><del>-        if (result == MAP_FAILED)
</del><ins>+        if (result == MAP_FAILED) {
+            failed = true;
</ins><span class="cx">             return;
</span><ins>+        }
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     ASSERT(m_size &lt;= m_mappedCapacity);
</span><del>-    if (mprotect(result, m_size, PROT_READ | PROT_WRITE)) {
-        munmap(result, m_mappedCapacity);
-        return;
</del><ins>+    {
+        bool success = !mprotect(result, static_cast&lt;size_t&gt;(m_size), PROT_READ | PROT_WRITE);
+        RELEASE_ASSERT(success);
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     m_memory = result;
</span><ins>+    failed = false;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><ins>+bool Memory::grow(PageCount newSize)
+{
+    RELEASE_ASSERT(newSize &gt; PageCount::fromBytes(m_size));
+
+    if (maximum() &amp;&amp; newSize &gt; maximum())
+        return false;
+
+    uint64_t desiredSize = newSize.bytes();
+
+    if (m_memory &amp;&amp; desiredSize &lt;= m_mappedCapacity) {
+        bool success = !mprotect(static_cast&lt;uint8_t*&gt;(m_memory) + m_size, static_cast&lt;size_t&gt;(desiredSize - m_size), PROT_READ | PROT_WRITE);
+        RELEASE_ASSERT(success);
+        m_size = desiredSize;
+        return true;
+    }
+
+    // Otherwise, let's try to make some new memory.
+    void* newMemory = mmap(nullptr, desiredSize, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0);
+    if (newMemory == MAP_FAILED)
+        return false;
+
+    if (m_memory) {
+        memcpy(newMemory, m_memory, m_size);
+        bool success = !munmap(m_memory, m_mappedCapacity);
+        RELEASE_ASSERT(success);
+    }
+    m_memory = newMemory;
+    m_mappedCapacity = desiredSize;
+    m_size = desiredSize;
+
+    return true;
+}
+
</ins><span class="cx"> } // namespace JSC
</span><span class="cx"> 
</span><span class="cx"> } // namespace Wasm
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorewasmWasmMemoryh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/wasm/WasmMemory.h (210200 => 210201)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/wasm/WasmMemory.h        2016-12-28 14:36:15 UTC (rev 210200)
+++ trunk/Source/JavaScriptCore/wasm/WasmMemory.h        2016-12-29 00:06:52 UTC (rev 210201)
</span><span class="lines">@@ -44,7 +44,7 @@
</span><span class="cx">         BoundsChecking
</span><span class="cx">     };
</span><span class="cx"> 
</span><del>-    JS_EXPORT_PRIVATE Memory(PageCount initial, PageCount maximum);
</del><ins>+    JS_EXPORT_PRIVATE Memory(PageCount initial, PageCount maximum, bool&amp; failed);
</ins><span class="cx"> 
</span><span class="cx">     ~Memory()
</span><span class="cx">     {
</span><span class="lines">@@ -52,10 +52,9 @@
</span><span class="cx">             munmap(m_memory, m_mappedCapacity);
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    bool isValid() const { return !!m_memory; }
-
</del><span class="cx">     void* memory() const { return m_memory; }
</span><del>-    uint32_t size() const { return m_size; }
</del><ins>+    uint64_t size() const { return m_size; }
+    PageCount sizeInPages() const { return PageCount::fromBytes(m_size); }
</ins><span class="cx"> 
</span><span class="cx">     Mode mode() const { return m_mode; }
</span><span class="cx"> 
</span><span class="lines">@@ -62,25 +61,17 @@
</span><span class="cx">     PageCount initial() const { return m_initial; }
</span><span class="cx">     PageCount maximum() const { return m_maximum; }
</span><span class="cx"> 
</span><del>-    bool grow(uint32_t newSize)
-    {
-        ASSERT(m_memory);
-        if (newSize &gt; m_capacity)
-            return false;
</del><ins>+    bool grow(PageCount);
</ins><span class="cx"> 
</span><del>-        return !mprotect(m_memory, newSize, PROT_READ | PROT_WRITE);
-    }
-
</del><span class="cx">     static ptrdiff_t offsetOfSize() { return OBJECT_OFFSETOF(Memory, m_size); }
</span><del>-
</del><ins>+    static ptrdiff_t offsetOfMemory() { return OBJECT_OFFSETOF(Memory, m_memory); }
</ins><span class="cx">     
</span><span class="cx"> private:
</span><span class="cx">     void* m_memory { nullptr };
</span><span class="cx">     Mode m_mode;
</span><del>-    uint32_t m_size { 0 };
-    uint32_t m_capacity { 0 };
</del><span class="cx">     PageCount m_initial;
</span><span class="cx">     PageCount m_maximum;
</span><ins>+    uint64_t m_size { 0 };
</ins><span class="cx">     uint64_t m_mappedCapacity { 0 };
</span><span class="cx"> };
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorewasmWasmModuleParsercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/wasm/WasmModuleParser.cpp (210200 => 210201)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/wasm/WasmModuleParser.cpp        2016-12-28 14:36:15 UTC (rev 210200)
+++ trunk/Source/JavaScriptCore/wasm/WasmModuleParser.cpp        2016-12-29 00:06:52 UTC (rev 210201)
</span><span class="lines">@@ -39,6 +39,14 @@
</span><span class="cx"> 
</span><span class="cx"> namespace JSC { namespace Wasm {
</span><span class="cx"> 
</span><ins>+ALWAYS_INLINE I32InitExpr makeI32InitExpr(uint8_t opcode, uint32_t bits)
+{
+    RELEASE_ASSERT(opcode == I32Const || opcode == GetGlobal);
+    if (opcode == I32Const)
+        return I32InitExpr::constValue(bits);
+    return I32InitExpr::globalImport(bits);
+}
+
</ins><span class="cx"> auto ModuleParser::parse() -&gt; Result
</span><span class="cx"> {
</span><span class="cx">     m_result.module = std::make_unique&lt;ModuleInformation&gt;();
</span><span class="lines">@@ -289,7 +297,7 @@
</span><span class="cx"> 
</span><span class="cx"> auto ModuleParser::parseMemoryHelper(bool isImport) -&gt; PartialResult
</span><span class="cx"> {
</span><del>-    WASM_PARSER_FAIL_IF(m_result.module-&gt;memory, &quot;Memory section cannot exist if an Import has a memory&quot;);
</del><ins>+    WASM_PARSER_FAIL_IF(!!m_result.module-&gt;memory, &quot;Memory section cannot exist if an Import has a memory&quot;);
</ins><span class="cx"> 
</span><span class="cx">     PageCount initialPageCount;
</span><span class="cx">     PageCount maximumPageCount;
</span><span class="lines">@@ -342,32 +350,12 @@
</span><span class="cx">         uint8_t initOpcode;
</span><span class="cx"> 
</span><span class="cx">         WASM_FAIL_IF_HELPER_FAILS(parseGlobalType(global));
</span><del>-        WASM_FAIL_IF_HELPER_FAILS(parseInitExpr(initOpcode, global.initialBitsOrImportNumber));
-
-        global.initializationType = Global::FromExpression;
</del><span class="cx">         Type typeForInitOpcode;
</span><del>-        switch (initOpcode) {
-        case I32Const:
-            typeForInitOpcode = I32;
-            break;
-        case I64Const:
-            typeForInitOpcode = I64;
-            break;
-        case F32Const:
-            typeForInitOpcode = F32;
-            break;
-        case F64Const:
-            typeForInitOpcode = F64;
-            break;
-        case GetGlobal:
-            WASM_PARSER_FAIL_IF(global.initialBitsOrImportNumber &gt;= m_result.module-&gt;firstInternalGlobal, globalIndex, &quot;th Global uses get_global &quot;, global.initialBitsOrImportNumber, &quot; which exceeds the first internal global &quot;, m_result.module-&gt;firstInternalGlobal);
-            typeForInitOpcode = m_result.module-&gt;globals[global.initialBitsOrImportNumber].type;
</del><ins>+        WASM_FAIL_IF_HELPER_FAILS(parseInitExpr(initOpcode, global.initialBitsOrImportNumber, typeForInitOpcode));
+        if (initOpcode == GetGlobal)
</ins><span class="cx">             global.initializationType = Global::FromGlobalImport;
</span><del>-            break;
-        default:
-            RELEASE_ASSERT_NOT_REACHED();
-        }
-
</del><ins>+        else
+            global.initializationType = Global::FromExpression;
</ins><span class="cx">         WASM_PARSER_FAIL_IF(typeForInitOpcode != global.type, &quot;Global init_expr opcode of type &quot;, typeForInitOpcode, &quot; doesn't match global's type &quot;, global.type);
</span><span class="cx"> 
</span><span class="cx">         m_result.module-&gt;globals.uncheckedAppend(WTFMove(global));
</span><span class="lines">@@ -451,7 +439,8 @@
</span><span class="cx"> 
</span><span class="cx">         WASM_PARSER_FAIL_IF(!parseVarUInt32(tableIndex), &quot;can't get &quot;, elementNum, &quot;th Element table index&quot;);
</span><span class="cx">         WASM_PARSER_FAIL_IF(tableIndex, &quot;Element section can only have one Table for now&quot;);
</span><del>-        WASM_FAIL_IF_HELPER_FAILS(parseInitExpr(initOpcode, offset));
</del><ins>+        Type initExprType;
+        WASM_FAIL_IF_HELPER_FAILS(parseInitExpr(initOpcode, offset, initExprType));
</ins><span class="cx">         WASM_PARSER_FAIL_IF(initOpcode != OpType::I32Const, &quot;Element section doesn't support non-i32 init_expr opcode for now, got &quot;, initOpcode);
</span><span class="cx">         WASM_PARSER_FAIL_IF(!parseVarUInt32(indexCount), &quot;can't get &quot;, elementNum, &quot;th index count for Element section&quot;);
</span><span class="cx">         WASM_PARSER_FAIL_IF(indexCount == std::numeric_limits&lt;uint32_t&gt;::max(), &quot;Element section's &quot;, elementNum, &quot;th index count is too big &quot;, indexCount);
</span><span class="lines">@@ -509,7 +498,7 @@
</span><span class="cx">     return { };
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-auto ModuleParser::parseInitExpr(uint8_t&amp; opcode, uint64_t&amp; bitsOrImportNumber) -&gt; PartialResult
</del><ins>+auto ModuleParser::parseInitExpr(uint8_t&amp; opcode, uint64_t&amp; bitsOrImportNumber, Type&amp; resultType) -&gt; PartialResult
</ins><span class="cx"> {
</span><span class="cx">     WASM_PARSER_FAIL_IF(!parseUInt8(opcode), &quot;can't get init_expr's opcode&quot;);
</span><span class="cx"> 
</span><span class="lines">@@ -518,6 +507,7 @@
</span><span class="cx">         int32_t constant;
</span><span class="cx">         WASM_PARSER_FAIL_IF(!parseVarInt32(constant), &quot;can't get constant value for init_expr's i32.const&quot;);
</span><span class="cx">         bitsOrImportNumber = static_cast&lt;uint64_t&gt;(constant);
</span><ins>+        resultType = I32;
</ins><span class="cx">         break;
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="lines">@@ -525,6 +515,7 @@
</span><span class="cx">         int64_t constant;
</span><span class="cx">         WASM_PARSER_FAIL_IF(!parseVarInt64(constant), &quot;can't get constant value for init_expr's i64.const&quot;);
</span><span class="cx">         bitsOrImportNumber = constant;
</span><ins>+        resultType = I64;
</ins><span class="cx">         break;
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="lines">@@ -532,6 +523,7 @@
</span><span class="cx">         uint32_t constant;
</span><span class="cx">         WASM_PARSER_FAIL_IF(!parseUInt32(constant), &quot;can't get constant value for init_expr's f32.const&quot;);
</span><span class="cx">         bitsOrImportNumber = constant;
</span><ins>+        resultType = F32;
</ins><span class="cx">         break;
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="lines">@@ -539,6 +531,7 @@
</span><span class="cx">         uint64_t constant;
</span><span class="cx">         WASM_PARSER_FAIL_IF(!parseUInt64(constant), &quot;can't get constant value for init_expr's f64.const&quot;);
</span><span class="cx">         bitsOrImportNumber = constant;
</span><ins>+        resultType = F64;
</ins><span class="cx">         break;
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="lines">@@ -551,7 +544,7 @@
</span><span class="cx">         WASM_PARSER_FAIL_IF(import.kindIndex &gt;= m_result.module-&gt;firstInternalGlobal, &quot;get_global import kind index &quot;, import.kindIndex, &quot; exceeds the first internal global &quot;, m_result.module-&gt;firstInternalGlobal);
</span><span class="cx"> 
</span><span class="cx">         ASSERT(m_result.module-&gt;globals[import.kindIndex].mutability == Global::Immutable);
</span><del>-
</del><ins>+        resultType = m_result.module-&gt;globals[index].type;
</ins><span class="cx">         bitsOrImportNumber = index;
</span><span class="cx">         break;
</span><span class="cx">     }
</span><span class="lines">@@ -586,18 +579,19 @@
</span><span class="cx"> 
</span><span class="cx">     for (uint32_t segmentNumber = 0; segmentNumber &lt; segmentCount; ++segmentNumber) {
</span><span class="cx">         uint32_t index;
</span><del>-        uint64_t offset;
</del><ins>+        uint64_t initExprBits;
</ins><span class="cx">         uint8_t initOpcode;
</span><span class="cx">         uint32_t dataByteLength;
</span><span class="cx"> 
</span><span class="cx">         WASM_PARSER_FAIL_IF(!parseVarUInt32(index), &quot;can't get &quot;, segmentNumber, &quot;th Data segment's index&quot;);
</span><span class="cx">         WASM_PARSER_FAIL_IF(index, segmentNumber, &quot;th Data segment has non-zero index &quot;, index);
</span><del>-        WASM_FAIL_IF_HELPER_FAILS(parseInitExpr(initOpcode, offset));
-        WASM_PARSER_FAIL_IF(initOpcode != OpType::I32Const, segmentNumber, &quot;th Data segment has opcode &quot;, initOpcode, &quot; expected i32.const&quot;);
</del><ins>+        Type initExprType;
+        WASM_FAIL_IF_HELPER_FAILS(parseInitExpr(initOpcode, initExprBits, initExprType));
+        WASM_PARSER_FAIL_IF(initExprType != I32, segmentNumber, &quot;th Data segment's init_expr must produce an i32&quot;);
</ins><span class="cx">         WASM_PARSER_FAIL_IF(!parseVarUInt32(dataByteLength), &quot;can't get &quot;, segmentNumber, &quot;th Data segment's data byte length&quot;);
</span><span class="cx">         WASM_PARSER_FAIL_IF(dataByteLength == std::numeric_limits&lt;uint32_t&gt;::max(), segmentNumber, &quot;th Data segment's data byte length is too big &quot;, dataByteLength);
</span><span class="cx"> 
</span><del>-        Segment* segment = Segment::create(offset, dataByteLength);
</del><ins>+        Segment* segment = Segment::create(makeI32InitExpr(initOpcode, initExprBits), dataByteLength);
</ins><span class="cx">         WASM_PARSER_FAIL_IF(!segment, &quot;can't allocate enough memory for &quot;, segmentNumber, &quot;th Data segment of size &quot;, dataByteLength);
</span><span class="cx">         m_result.module-&gt;data.uncheckedAppend(Segment::adoptPtr(segment));
</span><span class="cx">         for (uint32_t dataByte = 0; dataByte &lt; dataByteLength; ++dataByte) {
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorewasmWasmModuleParserh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/wasm/WasmModuleParser.h (210200 => 210201)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/wasm/WasmModuleParser.h        2016-12-28 14:36:15 UTC (rev 210200)
+++ trunk/Source/JavaScriptCore/wasm/WasmModuleParser.h        2016-12-29 00:06:52 UTC (rev 210201)
</span><span class="lines">@@ -64,7 +64,7 @@
</span><span class="cx">     PartialResult WARN_UNUSED_RETURN parseMemoryHelper(bool isImport);
</span><span class="cx">     PartialResult WARN_UNUSED_RETURN parseTableHelper(bool isImport);
</span><span class="cx">     PartialResult WARN_UNUSED_RETURN parseResizableLimits(uint32_t&amp; initial, std::optional&lt;uint32_t&gt;&amp; maximum);
</span><del>-    PartialResult WARN_UNUSED_RETURN parseInitExpr(uint8_t&amp;, uint64_t&amp;);
</del><ins>+    PartialResult WARN_UNUSED_RETURN parseInitExpr(uint8_t&amp;, uint64_t&amp;, Type&amp; initExprType);
</ins><span class="cx"> 
</span><span class="cx">     ModuleParserResult m_result;
</span><span class="cx">     bool m_hasTable { false };
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorewasmWasmPageCounth"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/wasm/WasmPageCount.h (210200 => 210201)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/wasm/WasmPageCount.h        2016-12-28 14:36:15 UTC (rev 210200)
+++ trunk/Source/JavaScriptCore/wasm/WasmPageCount.h        2016-12-29 00:06:52 UTC (rev 210201)
</span><span class="lines">@@ -42,7 +42,8 @@
</span><span class="cx">         : m_pageCount(pageCount)
</span><span class="cx">     { }
</span><span class="cx"> 
</span><del>-    size_t bytes() { return m_pageCount * pageSize; }
</del><ins>+    uint64_t bytes() const { return static_cast&lt;uint64_t&gt;(m_pageCount) * static_cast&lt;uint64_t&gt;(pageSize); }
+    uint32_t pageCount() const { return m_pageCount; }
</ins><span class="cx"> 
</span><span class="cx">     static bool isValid(uint32_t pageCount)
</span><span class="cx">     {
</span><span class="lines">@@ -49,6 +50,14 @@
</span><span class="cx">         return pageCount &lt;= maxPageCount;
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    static PageCount fromBytes(uint64_t bytes)
+    {
+        RELEASE_ASSERT(bytes % pageSize == 0);
+        uint32_t numPages = bytes / pageSize;
+        RELEASE_ASSERT(PageCount::isValid(numPages));
+        return PageCount(numPages);
+    }
+
</ins><span class="cx">     static PageCount max()
</span><span class="cx">     {
</span><span class="cx">         return PageCount(maxPageCount);
</span><span class="lines">@@ -62,9 +71,18 @@
</span><span class="cx">     bool operator&lt;(const PageCount&amp; other) const { return m_pageCount &lt; other.m_pageCount; }
</span><span class="cx">     bool operator&gt;(const PageCount&amp; other) const { return m_pageCount &gt; other.m_pageCount; }
</span><span class="cx">     bool operator&gt;=(const PageCount&amp; other) const { return m_pageCount &gt;= other.m_pageCount; }
</span><ins>+    PageCount operator+(const PageCount&amp; other) const
+    {
+        if (sumOverflows&lt;uint32_t&gt;(m_pageCount, other.m_pageCount))
+            return PageCount();
+        uint32_t newCount = m_pageCount + other.m_pageCount;
+        if (!PageCount::isValid(newCount))
+            return PageCount();
+        return PageCount(newCount);
+    }
</ins><span class="cx"> 
</span><ins>+    static constexpr uint32_t pageSize = 64 * KB;
</ins><span class="cx"> private:
</span><del>-    static constexpr uint32_t pageSize = 64 * KB;
</del><span class="cx">     static constexpr uint32_t maxPageCount = static_cast&lt;uint32_t&gt;((1ull &lt;&lt; 32) / pageSize);
</span><span class="cx"> 
</span><span class="cx">     uint32_t m_pageCount;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorewasmWasmParserh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/wasm/WasmParser.h (210200 => 210201)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/wasm/WasmParser.h        2016-12-28 14:36:15 UTC (rev 210200)
+++ trunk/Source/JavaScriptCore/wasm/WasmParser.h        2016-12-29 00:06:52 UTC (rev 210201)
</span><span class="lines">@@ -235,8 +235,10 @@
</span><span class="cx">     uint32_t temp;
</span><span class="cx">     if (!parseVarUInt32(temp))
</span><span class="cx">         return false;
</span><ins>+    if (temp &gt; 1)
+        return false;
</ins><span class="cx">     result = static_cast&lt;uint8_t&gt;(temp);
</span><del>-    return temp &lt;= 1;
</del><ins>+    return true;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> template&lt;typename SuccessType&gt;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorewasmWasmValidatecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/wasm/WasmValidate.cpp (210200 => 210201)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/wasm/WasmValidate.cpp        2016-12-28 14:36:15 UTC (rev 210200)
+++ trunk/Source/JavaScriptCore/wasm/WasmValidate.cpp        2016-12-29 00:06:52 UTC (rev 210201)
</span><span class="lines">@@ -132,6 +132,8 @@
</span><span class="cx">     Result WARN_UNUSED_RETURN addSwitch(ExpressionType condition, const Vector&lt;ControlData*&gt;&amp; targets, ControlData&amp; defaultTarget, const ExpressionList&amp; expressionStack);
</span><span class="cx">     Result WARN_UNUSED_RETURN endBlock(ControlEntry&amp;, ExpressionList&amp; expressionStack);
</span><span class="cx">     Result WARN_UNUSED_RETURN addEndToUnreachable(ControlEntry&amp;);
</span><ins>+    Result WARN_UNUSED_RETURN addGrowMemory(ExpressionType delta, ExpressionType&amp; result);
+    Result WARN_UNUSED_RETURN addCurrentMemory(ExpressionType&amp; result);
</ins><span class="cx"> 
</span><span class="cx">     Result WARN_UNUSED_RETURN addUnreachable() { return { }; }
</span><span class="cx"> 
</span><span class="lines">@@ -292,6 +294,19 @@
</span><span class="cx">     return checkBranchTarget(defaultTarget, expressionStack);
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+auto Validate::addGrowMemory(ExpressionType delta, ExpressionType&amp; result) -&gt; Result
+{
+    WASM_VALIDATOR_FAIL_IF(delta != I32, &quot;grow_memory with non-i32 delta&quot;);
+    result = I32;
+    return { };
+}
+
+auto Validate::addCurrentMemory(ExpressionType&amp; result) -&gt; Result
+{
+    result = I32;
+    return { };
+}
+
</ins><span class="cx"> auto Validate::endBlock(ControlEntry&amp; entry, ExpressionList&amp; stack) -&gt; Result
</span><span class="cx"> {
</span><span class="cx">     WASM_FAIL_IF_HELPER_FAILS(unify(stack, entry.controlData));
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorewasmjsJSWebAssemblyInstanceh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/wasm/js/JSWebAssemblyInstance.h (210200 => 210201)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/wasm/js/JSWebAssemblyInstance.h        2016-12-28 14:36:15 UTC (rev 210200)
+++ trunk/Source/JavaScriptCore/wasm/js/JSWebAssemblyInstance.h        2016-12-29 00:06:52 UTC (rev 210201)
</span><span class="lines">@@ -87,6 +87,7 @@
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     static ptrdiff_t offsetOfTable() { return OBJECT_OFFSETOF(JSWebAssemblyInstance, m_table); }
</span><ins>+    static ptrdiff_t offsetOfMemory() { return OBJECT_OFFSETOF(JSWebAssemblyInstance, m_memory); }
</ins><span class="cx">     static ptrdiff_t offsetOfGlobals() { return OBJECT_OFFSETOF(JSWebAssemblyInstance, m_globals); }
</span><span class="cx"> 
</span><span class="cx"> protected:
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorewasmjsJSWebAssemblyMemorycpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/wasm/js/JSWebAssemblyMemory.cpp (210200 => 210201)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/wasm/js/JSWebAssemblyMemory.cpp        2016-12-28 14:36:15 UTC (rev 210200)
+++ trunk/Source/JavaScriptCore/wasm/js/JSWebAssemblyMemory.cpp        2016-12-29 00:06:52 UTC (rev 210201)
</span><span class="lines">@@ -30,8 +30,8 @@
</span><span class="cx"> 
</span><span class="cx"> #include &quot;JSCInlines.h&quot;
</span><span class="cx"> 
</span><ins>+#include &quot;ArrayBuffer.h&quot;
</ins><span class="cx"> #include &quot;JSArrayBuffer.h&quot;
</span><del>-#include &quot;ArrayBuffer.h&quot;
</del><span class="cx"> 
</span><span class="cx"> namespace JSC {
</span><span class="cx"> 
</span><span class="lines">@@ -55,6 +55,15 @@
</span><span class="cx"> {
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+JSWebAssemblyMemory::~JSWebAssemblyMemory()
+{
+    if (m_buffer) {
+        ArrayBufferContents dummyContents;
+        m_buffer-&gt;transferTo(dummyContents);
+        m_buffer = nullptr;
+    }
+}
+
</ins><span class="cx"> JSArrayBuffer* JSWebAssemblyMemory::buffer(VM&amp; vm, JSGlobalObject* globalObject)
</span><span class="cx"> {
</span><span class="cx">     if (m_bufferWrapper)
</span><span class="lines">@@ -71,6 +80,48 @@
</span><span class="cx">     return m_bufferWrapper.get();
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+Wasm::PageCount JSWebAssemblyMemory::grow(ExecState* exec, uint32_t delta, bool shouldThrowExceptionsOnFailure)
+{
+    VM&amp; vm = exec-&gt;vm();
+    auto throwScope = DECLARE_THROW_SCOPE(vm);
+
+    Wasm::PageCount oldPageCount = m_memory-&gt;sizeInPages();
+
+    if (!Wasm::PageCount::isValid(delta)) {
+        if (shouldThrowExceptionsOnFailure)
+            throwException(exec, throwScope, createRangeError(exec, ASCIILiteral(&quot;WebAssembly.Memory.grow expects the delta to be a valid page count&quot;)));
+        return Wasm::PageCount();
+    }
+
+    Wasm::PageCount newSize = oldPageCount + Wasm::PageCount(delta);
+    if (!newSize) {
+        if (shouldThrowExceptionsOnFailure)
+            throwException(exec, throwScope, createRangeError(exec, ASCIILiteral(&quot;WebAssembly.Memory.grow expects the grown size to be a valid page count&quot;)));
+        return Wasm::PageCount();
+    }
+
+    if (delta) {
+        bool success = m_memory-&gt;grow(newSize);
+        if (!success) {
+            if (shouldThrowExceptionsOnFailure)
+                throwException(exec, throwScope, createOutOfMemoryError(exec));
+            return Wasm::PageCount();
+        }
+    }
+
+    // We need to clear out the old array buffer because it might now be pointing
+    // to stale memory.
+    // Neuter the old array.
+    if (m_buffer) {
+        ArrayBufferContents dummyContents;
+        m_buffer-&gt;transferTo(dummyContents);
+        m_buffer = nullptr;
+        m_bufferWrapper.clear();
+    }
+
+    return oldPageCount;
+}
+
</ins><span class="cx"> void JSWebAssemblyMemory::finishCreation(VM&amp; vm)
</span><span class="cx"> {
</span><span class="cx">     Base::finishCreation(vm);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorewasmjsJSWebAssemblyMemoryh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/wasm/js/JSWebAssemblyMemory.h (210200 => 210201)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/wasm/js/JSWebAssemblyMemory.h        2016-12-28 14:36:15 UTC (rev 210200)
+++ trunk/Source/JavaScriptCore/wasm/js/JSWebAssemblyMemory.h        2016-12-29 00:06:52 UTC (rev 210201)
</span><span class="lines">@@ -48,9 +48,13 @@
</span><span class="cx"> 
</span><span class="cx">     Wasm::Memory* memory() { return m_memory.get(); }
</span><span class="cx">     JSArrayBuffer* buffer(VM&amp; vm, JSGlobalObject*);
</span><ins>+    Wasm::PageCount grow(ExecState*, uint32_t delta, bool shouldThrowExceptionsOnFailure);
</ins><span class="cx"> 
</span><ins>+    static ptrdiff_t offsetOfMemory() { return OBJECT_OFFSETOF(JSWebAssemblyMemory, m_memory); }
+
</ins><span class="cx"> protected:
</span><span class="cx">     JSWebAssemblyMemory(VM&amp;, Structure*, std::unique_ptr&lt;Wasm::Memory&gt;&amp;&amp;);
</span><ins>+    ~JSWebAssemblyMemory();
</ins><span class="cx">     void finishCreation(VM&amp;);
</span><span class="cx">     static void destroy(JSCell*);
</span><span class="cx">     static void visitChildren(JSCell*, SlotVisitor&amp;);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorewasmjsJSWebAssemblyModuleh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/wasm/js/JSWebAssemblyModule.h (210200 => 210201)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/wasm/js/JSWebAssemblyModule.h        2016-12-28 14:36:15 UTC (rev 210200)
+++ trunk/Source/JavaScriptCore/wasm/js/JSWebAssemblyModule.h        2016-12-29 00:06:52 UTC (rev 210201)
</span><span class="lines">@@ -55,12 +55,12 @@
</span><span class="cx">         ASSERT(functionIndexSpace &lt; m_functionIndexSpace.size);
</span><span class="cx">         return m_functionIndexSpace.buffer.get()[functionIndexSpace].signatureIndex;
</span><span class="cx">     }
</span><del>-    unsigned importCount() const { return m_wasmToJSStubs.size(); }
</del><ins>+    unsigned functionImportCount() const { return m_wasmToJSStubs.size(); }
</ins><span class="cx"> 
</span><span class="cx">     JSWebAssemblyCallee* jsEntrypointCalleeFromFunctionIndexSpace(unsigned functionIndexSpace)
</span><span class="cx">     {
</span><del>-        RELEASE_ASSERT(functionIndexSpace &gt;= importCount());
-        unsigned calleeIndex = functionIndexSpace - importCount();
</del><ins>+        RELEASE_ASSERT(functionIndexSpace &gt;= functionImportCount());
+        unsigned calleeIndex = functionIndexSpace - functionImportCount();
</ins><span class="cx">         RELEASE_ASSERT(calleeIndex &lt; m_calleeCount);
</span><span class="cx">         return callees()[calleeIndex].get();
</span><span class="cx">     }
</span><span class="lines">@@ -67,8 +67,8 @@
</span><span class="cx"> 
</span><span class="cx">     JSWebAssemblyCallee* wasmEntrypointCalleeFromFunctionIndexSpace(unsigned functionIndexSpace)
</span><span class="cx">     {
</span><del>-        RELEASE_ASSERT(functionIndexSpace &gt;= importCount());
-        unsigned calleeIndex = functionIndexSpace - importCount();
</del><ins>+        RELEASE_ASSERT(functionIndexSpace &gt;= functionImportCount());
+        unsigned calleeIndex = functionIndexSpace - functionImportCount();
</ins><span class="cx">         RELEASE_ASSERT(calleeIndex &lt; m_calleeCount);
</span><span class="cx">         return callees()[calleeIndex + m_calleeCount].get();
</span><span class="cx">     }
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorewasmjsWebAssemblyFunctioncpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/wasm/js/WebAssemblyFunction.cpp (210200 => 210201)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/wasm/js/WebAssemblyFunction.cpp        2016-12-28 14:36:15 UTC (rev 210200)
+++ trunk/Source/JavaScriptCore/wasm/js/WebAssemblyFunction.cpp        2016-12-29 00:06:52 UTC (rev 210201)
</span><span class="lines">@@ -119,15 +119,6 @@
</span><span class="cx">     ProtoCallFrame protoCallFrame;
</span><span class="cx">     protoCallFrame.init(nullptr, wasmFunction, firstArgument, argCount, remainingArgs);
</span><span class="cx"> 
</span><del>-    if (JSWebAssemblyMemory* memory = wasmFunction-&gt;instance()-&gt;memory()) {
-        Wasm::Memory* wasmMemory = memory-&gt;memory();
-        vm.topWasmMemoryPointer = wasmMemory-&gt;memory();
-        vm.topWasmMemorySize = wasmMemory-&gt;size();
-    } else {
-        vm.topWasmMemoryPointer = nullptr;
-        vm.topWasmMemorySize = 0;
-    }
-
</del><span class="cx">     JSWebAssemblyInstance* prevJSWebAssemblyInstance = vm.topJSWebAssemblyInstance;
</span><span class="cx">     vm.topJSWebAssemblyInstance = wasmFunction-&gt;instance();
</span><span class="cx">     ASSERT(wasmFunction-&gt;instance());
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorewasmjsWebAssemblyInstanceConstructorcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/wasm/js/WebAssemblyInstanceConstructor.cpp (210200 => 210201)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/wasm/js/WebAssemblyInstanceConstructor.cpp        2016-12-28 14:36:15 UTC (rev 210200)
+++ trunk/Source/JavaScriptCore/wasm/js/WebAssemblyInstanceConstructor.cpp        2016-12-29 00:06:52 UTC (rev 210201)
</span><span class="lines">@@ -229,8 +229,9 @@
</span><span class="cx">         if (moduleInformation.memory &amp;&amp; !hasMemoryImport) {
</span><span class="cx">             RELEASE_ASSERT(!moduleInformation.memory.isImport());
</span><span class="cx">             // We create a memory when it's a memory definition.
</span><del>-            std::unique_ptr&lt;Wasm::Memory&gt; memory = std::make_unique&lt;Wasm::Memory&gt;(moduleInformation.memory.initial(), moduleInformation.memory.maximum());
-            if (!memory-&gt;isValid())
</del><ins>+            bool failed;
+            std::unique_ptr&lt;Wasm::Memory&gt; memory = std::make_unique&lt;Wasm::Memory&gt;(moduleInformation.memory.initial(), moduleInformation.memory.maximum(), failed);
+            if (failed)
</ins><span class="cx">                 return JSValue::encode(throwException(exec, throwScope, createOutOfMemoryError(exec)));
</span><span class="cx">             instance-&gt;setMemory(vm,
</span><span class="cx">                JSWebAssemblyMemory::create(vm, exec-&gt;lexicalGlobalObject()-&gt;WebAssemblyMemoryStructure(), WTFMove(memory)));
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorewasmjsWebAssemblyMemoryConstructorcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/wasm/js/WebAssemblyMemoryConstructor.cpp (210200 => 210201)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/wasm/js/WebAssemblyMemoryConstructor.cpp        2016-12-28 14:36:15 UTC (rev 210200)
+++ trunk/Source/JavaScriptCore/wasm/js/WebAssemblyMemoryConstructor.cpp        2016-12-29 00:06:52 UTC (rev 210201)
</span><span class="lines">@@ -96,8 +96,9 @@
</span><span class="cx">         }
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    std::unique_ptr&lt;Wasm::Memory&gt; memory = std::make_unique&lt;Wasm::Memory&gt;(initialPageCount, maximumPageCount);
-    if (!memory-&gt;isValid())
</del><ins>+    bool failed;
+    std::unique_ptr&lt;Wasm::Memory&gt; memory = std::make_unique&lt;Wasm::Memory&gt;(initialPageCount, maximumPageCount, failed);
+    if (failed)
</ins><span class="cx">         return JSValue::encode(throwException(exec, throwScope, createOutOfMemoryError(exec)));
</span><span class="cx"> 
</span><span class="cx">     return JSValue::encode(JSWebAssemblyMemory::create(vm, exec-&gt;lexicalGlobalObject()-&gt;WebAssemblyMemoryStructure(), WTFMove(memory)));
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorewasmjsWebAssemblyMemoryPrototypecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/wasm/js/WebAssemblyMemoryPrototype.cpp (210200 => 210201)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/wasm/js/WebAssemblyMemoryPrototype.cpp        2016-12-28 14:36:15 UTC (rev 210200)
+++ trunk/Source/JavaScriptCore/wasm/js/WebAssemblyMemoryPrototype.cpp        2016-12-29 00:06:52 UTC (rev 210201)
</span><span class="lines">@@ -32,33 +32,69 @@
</span><span class="cx"> #include &quot;JSArrayBuffer.h&quot;
</span><span class="cx"> #include &quot;JSCInlines.h&quot;
</span><span class="cx"> #include &quot;JSWebAssemblyMemory.h&quot;
</span><ins>+#include &quot;JSWebAssemblyHelpers.h&quot;
</ins><span class="cx"> 
</span><ins>+namespace JSC {
+static EncodedJSValue JSC_HOST_CALL webAssemblyMemoryProtoFuncGrow(ExecState*);
+}
+
</ins><span class="cx"> #include &quot;WebAssemblyMemoryPrototype.lut.h&quot;
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx"> namespace JSC {
</span><span class="cx"> 
</span><span class="cx"> const ClassInfo WebAssemblyMemoryPrototype::s_info = { &quot;WebAssembly.Memory.prototype&quot;, &amp;Base::s_info, &amp;prototypeTableWebAssemblyMemory, CREATE_METHOD_TABLE(WebAssemblyMemoryPrototype) };
</span><span class="cx"> 
</span><span class="cx"> /* Source for WebAssemblyMemoryPrototype.lut.h
</span><del>- @begin prototypeTableWebAssemblyMemory
- @end
- */
</del><ins>+@begin prototypeTableWebAssemblyMemory
+  grow     webAssemblyMemoryProtoFuncGrow   DontEnum|Function 1
+@end
+*/
</ins><span class="cx"> 
</span><del>-static EncodedJSValue JSC_HOST_CALL webAssemblyMemoryProtoFuncBuffer(ExecState*);
</del><ins>+EncodedJSValue JSC_HOST_CALL webAssemblyMemoryProtoFuncBuffer(ExecState*);
</ins><span class="cx"> 
</span><del>-EncodedJSValue JSC_HOST_CALL webAssemblyMemoryProtoFuncBuffer(ExecState* exec)
</del><ins>+ALWAYS_INLINE JSWebAssemblyMemory* getMemory(ExecState* exec, JSValue value)
</ins><span class="cx"> {
</span><span class="cx">     VM&amp; vm = exec-&gt;vm();
</span><span class="cx">     auto throwScope = DECLARE_THROW_SCOPE(vm);
</span><span class="cx"> 
</span><del>-    JSWebAssemblyMemory* memory = jsDynamicCast&lt;JSWebAssemblyMemory*&gt;(exec-&gt;thisValue()); 
</del><ins>+    JSWebAssemblyMemory* memory = jsDynamicCast&lt;JSWebAssemblyMemory*&gt;(value); 
</ins><span class="cx">     if (!memory) {
</span><del>-        return JSValue::encode(throwException(exec, throwScope, 
-                    createTypeError(exec, ASCIILiteral(&quot;WebAssembly.Memory.prototype.buffer getter called with non WebAssembly.Memory |this| value&quot;))));
</del><ins>+        throwException(exec, throwScope, 
+            createTypeError(exec, ASCIILiteral(&quot;WebAssembly.Memory.prototype.buffer getter called with non WebAssembly.Memory |this| value&quot;)));
+        return nullptr;
</ins><span class="cx">     }
</span><ins>+    return memory;
+}
+
+EncodedJSValue JSC_HOST_CALL webAssemblyMemoryProtoFuncBuffer(ExecState* exec)
+{
+    VM&amp; vm = exec-&gt;vm();
+    auto throwScope = DECLARE_THROW_SCOPE(vm);
+
+    JSWebAssemblyMemory* memory = getMemory(exec, exec-&gt;thisValue()); 
+    RETURN_IF_EXCEPTION(throwScope, { });
</ins><span class="cx">     return JSValue::encode(memory-&gt;buffer(exec-&gt;vm(), exec-&gt;lexicalGlobalObject()));
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+EncodedJSValue JSC_HOST_CALL webAssemblyMemoryProtoFuncGrow(ExecState* exec)
+{
+    VM&amp; vm = exec-&gt;vm();
+    auto throwScope = DECLARE_THROW_SCOPE(vm);
+
+    JSWebAssemblyMemory* memory = getMemory(exec, exec-&gt;thisValue()); 
+    RETURN_IF_EXCEPTION(throwScope, { });
+    
+    uint32_t delta = toNonWrappingUint32(exec, exec-&gt;argument(0));
+    RETURN_IF_EXCEPTION(throwScope, { });
+
+    bool shouldThrowExceptionsOnFailure = true;
+    Wasm::PageCount result = memory-&gt;grow(exec, delta, shouldThrowExceptionsOnFailure);
+    RETURN_IF_EXCEPTION(throwScope, { });
+
+    return JSValue::encode(jsNumber(result.pageCount()));
+}
+
</ins><span class="cx"> WebAssemblyMemoryPrototype* WebAssemblyMemoryPrototype::create(VM&amp; vm, JSGlobalObject* globalObject, Structure* structure)
</span><span class="cx"> {
</span><span class="cx">     auto* object = new (NotNull, allocateCell&lt;WebAssemblyMemoryPrototype&gt;(vm.heap)) WebAssemblyMemoryPrototype(vm, structure);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorewasmjsWebAssemblyModuleRecordcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/wasm/js/WebAssemblyModuleRecord.cpp (210200 => 210201)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/wasm/js/WebAssemblyModuleRecord.cpp        2016-12-28 14:36:15 UTC (rev 210200)
+++ trunk/Source/JavaScriptCore/wasm/js/WebAssemblyModuleRecord.cpp        2016-12-29 00:06:52 UTC (rev 210201)
</span><span class="lines">@@ -95,7 +95,7 @@
</span><span class="cx">     const Wasm::ModuleInformation&amp; moduleInformation = module-&gt;moduleInformation();
</span><span class="cx"> 
</span><span class="cx">     SymbolTable* exportSymbolTable = module-&gt;exportSymbolTable();
</span><del>-    unsigned importCount = module-&gt;importCount();
</del><ins>+    unsigned functionImportCount = module-&gt;functionImportCount();
</ins><span class="cx"> 
</span><span class="cx">     // FIXME wire up the imports. https://bugs.webkit.org/show_bug.cgi?id=165118
</span><span class="cx"> 
</span><span class="lines">@@ -108,7 +108,7 @@
</span><span class="cx">             // 1. If e is a closure c:
</span><span class="cx">             //   i. If there is an Exported Function Exotic Object func in funcs whose func.[[Closure]] equals c, then return func.
</span><span class="cx">             //   ii. (Note: At most one wrapper is created for any closure, so func is unique, even if there are multiple occurrances in the list. Moreover, if the item was an import that is already an Exported Function Exotic Object, then the original function object will be found. For imports that are regular JS functions, a new wrapper will be created.)
</span><del>-            if (exp.kindIndex &lt; importCount) {
</del><ins>+            if (exp.kindIndex &lt; functionImportCount) {
</ins><span class="cx">                 // FIXME Implement re-exporting an import. https://bugs.webkit.org/show_bug.cgi?id=165510
</span><span class="cx">                 RELEASE_ASSERT_NOT_REACHED();
</span><span class="cx">             }
</span><span class="lines">@@ -180,7 +180,7 @@
</span><span class="cx">         // The start function must not take any arguments or return anything. This is enforced by the parser.
</span><span class="cx">         ASSERT(!signature-&gt;argumentCount());
</span><span class="cx">         ASSERT(signature-&gt;returnType() == Wasm::Void);
</span><del>-        if (startFunctionIndexSpace &lt; module-&gt;importCount()) {
</del><ins>+        if (startFunctionIndexSpace &lt; module-&gt;functionImportCount()) {
</ins><span class="cx">             JSCell* startFunction = instance-&gt;importFunction(startFunctionIndexSpace)-&gt;get();
</span><span class="cx">             m_startFunction.set(vm, this, startFunction);
</span><span class="cx">         } else {
</span><span class="lines">@@ -196,8 +196,8 @@
</span><span class="cx">     m_moduleEnvironment.set(vm, this, moduleEnvironment);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-template &lt;typename Scope, typename N, typename ...Args&gt;
-NEVER_INLINE static JSValue dataSegmentFail(ExecState* state, VM&amp; vm, Scope&amp; scope, N memorySize, N segmentSize, N offset, Args... args)
</del><ins>+template &lt;typename Scope, typename M, typename N, typename ...Args&gt;
+NEVER_INLINE static JSValue dataSegmentFail(ExecState* state, VM&amp; vm, Scope&amp; scope, M memorySize, N segmentSize, N offset, Args... args)
</ins><span class="cx"> {
</span><span class="cx">     return throwException(state, scope, createJSWebAssemblyLinkError(state, vm, makeString(ASCIILiteral(&quot;Invalid data segment initialization: segment of &quot;), String::number(segmentSize), ASCIILiteral(&quot; bytes memory of &quot;), String::number(memorySize), ASCIILiteral(&quot; bytes, at offset &quot;), String::number(offset), args...)));
</span><span class="cx"> }
</span><span class="lines">@@ -231,7 +231,7 @@
</span><span class="cx">                 // for the import.
</span><span class="cx">                 // https://bugs.webkit.org/show_bug.cgi?id=165510
</span><span class="cx">                 uint32_t functionIndex = element.functionIndices[i];
</span><del>-                if (functionIndex &lt; module-&gt;importCount()) {
</del><ins>+                if (functionIndex &lt; module-&gt;functionImportCount()) {
</ins><span class="cx">                     return JSValue::decode(
</span><span class="cx">                         throwVMRangeError(state, scope, ASCIILiteral(&quot;Element is setting the table value with an import. This is not yet implemented. FIXME.&quot;)));
</span><span class="cx">                 }
</span><span class="lines">@@ -259,15 +259,21 @@
</span><span class="cx">         if (!data.isEmpty()) {
</span><span class="cx">             RELEASE_ASSERT(jsMemory); // It is a validation error for a Data section to exist without a Memory section or import.
</span><span class="cx">             uint8_t* memory = reinterpret_cast&lt;uint8_t*&gt;(jsMemory-&gt;memory()-&gt;memory());
</span><del>-            RELEASE_ASSERT(memory);
-            auto sizeInBytes = jsMemory-&gt;memory()-&gt;size();
</del><ins>+            uint64_t sizeInBytes = jsMemory-&gt;memory()-&gt;size();
</ins><span class="cx">             for (auto&amp; segment : data) {
</span><span class="cx">                 if (segment-&gt;sizeInBytes) {
</span><ins>+                    uint32_t offset;
+                    if (segment-&gt;offset.isGlobalImport())
+                        offset = static_cast&lt;uint32_t&gt;(m_instance-&gt;loadI32Global(segment-&gt;offset.globalImportIndex()));
+                    else
+                        offset = segment-&gt;offset.constValue();
+
</ins><span class="cx">                     if (UNLIKELY(sizeInBytes &lt; segment-&gt;sizeInBytes))
</span><del>-                        return dataSegmentFail(state, vm, scope, sizeInBytes, segment-&gt;sizeInBytes, segment-&gt;offset, ASCIILiteral(&quot;, segment is too big&quot;));
-                    if (UNLIKELY(segment-&gt;offset &gt; sizeInBytes - segment-&gt;sizeInBytes))
-                        return dataSegmentFail(state, vm, scope, sizeInBytes, segment-&gt;sizeInBytes, segment-&gt;offset, ASCIILiteral(&quot;, segment writes outside of memory&quot;));
-                    memcpy(memory + segment-&gt;offset, &amp;segment-&gt;byte(0), segment-&gt;sizeInBytes);
</del><ins>+                        return dataSegmentFail(state, vm, scope, sizeInBytes, segment-&gt;sizeInBytes, offset, ASCIILiteral(&quot;, segment is too big&quot;));
+                    if (UNLIKELY(offset &gt; sizeInBytes - segment-&gt;sizeInBytes))
+                        return dataSegmentFail(state, vm, scope, sizeInBytes, segment-&gt;sizeInBytes, offset, ASCIILiteral(&quot;, segment writes outside of memory&quot;));
+                    RELEASE_ASSERT(memory);
+                    memcpy(memory + offset, &amp;segment-&gt;byte(0), segment-&gt;sizeInBytes);
</ins><span class="cx">                 }
</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 (210200 => 210201)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/wasm/wasm.json        2016-12-28 14:36:15 UTC (rev 210200)
+++ trunk/Source/JavaScriptCore/wasm/wasm.json        2016-12-29 00:06:52 UTC (rev 210201)
</span><span class="lines">@@ -88,8 +88,8 @@
</span><span class="cx">         &quot;i64.store&quot;:           { &quot;category&quot;: &quot;memory&quot;,     &quot;value&quot;:  55, &quot;return&quot;: [],           &quot;parameter&quot;: [&quot;addr&quot;, &quot;i64&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;store to memory&quot; },
</span><span class="cx">         &quot;f32.store&quot;:           { &quot;category&quot;: &quot;memory&quot;,     &quot;value&quot;:  56, &quot;return&quot;: [],           &quot;parameter&quot;: [&quot;addr&quot;, &quot;f32&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;store to memory&quot; },
</span><span class="cx">         &quot;f64.store&quot;:           { &quot;category&quot;: &quot;memory&quot;,     &quot;value&quot;:  57, &quot;return&quot;: [],           &quot;parameter&quot;: [&quot;addr&quot;, &quot;f64&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;store to memory&quot; },
</span><del>-        &quot;current_memory&quot;:      { &quot;category&quot;: &quot;operation&quot;,  &quot;value&quot;:  63, &quot;return&quot;: [&quot;size&quot;],     &quot;parameter&quot;: [],                       &quot;immediate&quot;: [],                                                                                         &quot;description&quot;: &quot;query the size of memory&quot; },
-        &quot;grow_memory&quot;:         { &quot;category&quot;: &quot;operation&quot;,  &quot;value&quot;:  64, &quot;return&quot;: [&quot;size&quot;],     &quot;parameter&quot;: [&quot;size&quot;],                 &quot;immediate&quot;: [],                                                                                         &quot;description&quot;: &quot;grow the size of memory&quot; },
</del><ins>+        &quot;current_memory&quot;:      { &quot;category&quot;: &quot;operation&quot;,  &quot;value&quot;:  63, &quot;return&quot;: [&quot;size&quot;],     &quot;parameter&quot;: [],                       &quot;immediate&quot;: [{&quot;name&quot;: &quot;flags&quot;, &quot;type&quot;: &quot;varuint32&quot;}],                                                                                         &quot;description&quot;: &quot;query the size of memory&quot; },
+        &quot;grow_memory&quot;:         { &quot;category&quot;: &quot;operation&quot;,  &quot;value&quot;:  64, &quot;return&quot;: [&quot;size&quot;],     &quot;parameter&quot;: [&quot;size&quot;],                 &quot;immediate&quot;: [{&quot;name&quot;: &quot;flags&quot;, &quot;type&quot;: &quot;varuint32&quot;}],                                                                                         &quot;description&quot;: &quot;grow the size of memory&quot; },
</ins><span class="cx">         &quot;i32.add&quot;:             { &quot;category&quot;: &quot;arithmetic&quot;, &quot;value&quot;: 106, &quot;return&quot;: [&quot;i32&quot;],      &quot;parameter&quot;: [&quot;i32&quot;, &quot;i32&quot;],           &quot;immediate&quot;: [], &quot;b3op&quot;: &quot;Add&quot;          },
</span><span class="cx">         &quot;i32.sub&quot;:             { &quot;category&quot;: &quot;arithmetic&quot;, &quot;value&quot;: 107, &quot;return&quot;: [&quot;i32&quot;],      &quot;parameter&quot;: [&quot;i32&quot;, &quot;i32&quot;],           &quot;immediate&quot;: [], &quot;b3op&quot;: &quot;Sub&quot;          },
</span><span class="cx">         &quot;i32.mul&quot;:             { &quot;category&quot;: &quot;arithmetic&quot;, &quot;value&quot;: 108, &quot;return&quot;: [&quot;i32&quot;],      &quot;parameter&quot;: [&quot;i32&quot;, &quot;i32&quot;],           &quot;immediate&quot;: [], &quot;b3op&quot;: &quot;Mul&quot;          },
</span></span></pre>
</div>
</div>

</body>
</html>