<!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>[209830] 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/209830">209830</a></dd>
<dt>Author</dt> <dd>keith_miller@apple.com</dd>
<dt>Date</dt> <dd>2016-12-14 13:29:14 -0800 (Wed, 14 Dec 2016)</dd>
</dl>

<h3>Log Message</h3>
<pre>WebAssembly JS API: implement Global
https://bugs.webkit.org/show_bug.cgi?id=164133

Reviewed by Saam Barati.

JSTests:

* wasm/Builder.js:
(export.default.Builder.prototype._registerSectionBuilders.switch.case.string_appeared_here.this.section):
* wasm/Builder_WebAssemblyBinary.js:
(const.valueType.WASM.description.type.i32.type.const.putGlobalType):
(const.putOp):
(const.putInitExpr):
(const.emitters.Import):
(const.emitters.Global):
(const.emitters.Export):
(const.emitters.Code):
* wasm/LowLevelBinary.js:
(export.default.LowLevelBinary.prototype.varuint32):
(export.default.LowLevelBinary.prototype.varint32):
* wasm/js-api/global-error.js: Added.
(catch):
(assert.truthy):
* wasm/js-api/global-external-init-from-import.js: Added.
* wasm/js-api/global-internal-init-from-import.js: Added.
* wasm/js-api/global-mutate.js: Added.
(createInternalGlobalModule):
* wasm/js-api/globals-export.js: Added.
* wasm/js-api/globals-import.js: Added.
* wasm/wasm.json:

Source/JavaScriptCore:

This patch adds support for globals. It handles imports, exports
and internal globals. In the MVP only internal globals are allowed
to be mutable. This means we can store a C-array of 64-bit slots
off the instance holding them. When globals are exported to JS
they are done so as numbers. This means that i64 globals cannot be
imported or exported.

* wasm/WasmB3IRGenerator.cpp:
(JSC::Wasm::B3IRGenerator::B3IRGenerator):
(JSC::Wasm::B3IRGenerator::getGlobal):
(JSC::Wasm::B3IRGenerator::setGlobal):
(JSC::Wasm::B3IRGenerator::addCallIndirect):
(JSC::Wasm::parseAndCompile):
* wasm/WasmFormat.h:
* wasm/WasmFunctionParser.h:
(JSC::Wasm::FunctionParser&lt;Context&gt;::parseExpression):
* wasm/WasmModuleParser.cpp:
(JSC::Wasm::ModuleParser::parseImport):
(JSC::Wasm::ModuleParser::parseGlobal):
(JSC::Wasm::ModuleParser::parseExport):
(JSC::Wasm::ModuleParser::parseElement):
(JSC::Wasm::ModuleParser::parseInitExpr):
(JSC::Wasm::ModuleParser::parseGlobalType):
(JSC::Wasm::ModuleParser::parseData):
* wasm/WasmModuleParser.h:
* wasm/WasmParser.h:
(JSC::Wasm::Parser::parseVarInt32):
(JSC::Wasm::Parser::parseVarInt64):
(JSC::Wasm::Parser::parseUInt64):
* wasm/WasmValidate.cpp:
(JSC::Wasm::Validate::hasMemory):
(JSC::Wasm::Validate::Validate):
(JSC::Wasm::Validate::getGlobal):
(JSC::Wasm::Validate::setGlobal):
(JSC::Wasm::validateFunction):
* wasm/generateWasmOpsHeader.py:
* wasm/js/JSWebAssemblyInstance.cpp:
(JSC::JSWebAssemblyInstance::create):
(JSC::JSWebAssemblyInstance::finishCreation):
(JSC::JSWebAssemblyInstance::visitChildren):
* wasm/js/JSWebAssemblyInstance.h:
(JSC::JSWebAssemblyInstance::loadI32Global):
(JSC::JSWebAssemblyInstance::loadI64Global):
(JSC::JSWebAssemblyInstance::loadF32Global):
(JSC::JSWebAssemblyInstance::loadF64Global):
(JSC::JSWebAssemblyInstance::setGlobal):
(JSC::JSWebAssemblyInstance::offsetOfGlobals):
* wasm/js/WebAssemblyInstanceConstructor.cpp:
(JSC::constructJSWebAssemblyInstance):
* wasm/js/WebAssemblyModuleRecord.cpp:
(JSC::WebAssemblyModuleRecord::finishCreation):
(JSC::WebAssemblyModuleRecord::link):</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkJSTestsChangeLog">trunk/JSTests/ChangeLog</a></li>
<li><a href="#trunkJSTestswasmBuilderjs">trunk/JSTests/wasm/Builder.js</a></li>
<li><a href="#trunkJSTestswasmBuilder_WebAssemblyBinaryjs">trunk/JSTests/wasm/Builder_WebAssemblyBinary.js</a></li>
<li><a href="#trunkJSTestswasmLowLevelBinaryjs">trunk/JSTests/wasm/LowLevelBinary.js</a></li>
<li><a href="#trunkJSTestswasmwasmjson">trunk/JSTests/wasm/wasm.json</a></li>
<li><a href="#trunkSourceJavaScriptCoreChangeLog">trunk/Source/JavaScriptCore/ChangeLog</a></li>
<li><a href="#trunkSourceJavaScriptCorewasmWasmB3IRGeneratorcpp">trunk/Source/JavaScriptCore/wasm/WasmB3IRGenerator.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorewasmWasmFormath">trunk/Source/JavaScriptCore/wasm/WasmFormat.h</a></li>
<li><a href="#trunkSourceJavaScriptCorewasmWasmFunctionParserh">trunk/Source/JavaScriptCore/wasm/WasmFunctionParser.h</a></li>
<li><a href="#trunkSourceJavaScriptCorewasmWasmModuleParsercpp">trunk/Source/JavaScriptCore/wasm/WasmModuleParser.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorewasmWasmModuleParserh">trunk/Source/JavaScriptCore/wasm/WasmModuleParser.h</a></li>
<li><a href="#trunkSourceJavaScriptCorewasmWasmParserh">trunk/Source/JavaScriptCore/wasm/WasmParser.h</a></li>
<li><a href="#trunkSourceJavaScriptCorewasmWasmValidatecpp">trunk/Source/JavaScriptCore/wasm/WasmValidate.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorewasmgenerateWasmOpsHeaderpy">trunk/Source/JavaScriptCore/wasm/generateWasmOpsHeader.py</a></li>
<li><a href="#trunkSourceJavaScriptCorewasmjsJSWebAssemblyInstancecpp">trunk/Source/JavaScriptCore/wasm/js/JSWebAssemblyInstance.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorewasmjsJSWebAssemblyInstanceh">trunk/Source/JavaScriptCore/wasm/js/JSWebAssemblyInstance.h</a></li>
<li><a href="#trunkSourceJavaScriptCorewasmjsWebAssemblyInstanceConstructorcpp">trunk/Source/JavaScriptCore/wasm/js/WebAssemblyInstanceConstructor.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorewasmjsWebAssemblyModuleRecordcpp">trunk/Source/JavaScriptCore/wasm/js/WebAssemblyModuleRecord.cpp</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#trunkJSTestswasmjsapiglobalerrorjs">trunk/JSTests/wasm/js-api/global-error.js</a></li>
<li><a href="#trunkJSTestswasmjsapiglobalexternalinitfromimportjs">trunk/JSTests/wasm/js-api/global-external-init-from-import.js</a></li>
<li><a href="#trunkJSTestswasmjsapiglobalinternalinitfromimportjs">trunk/JSTests/wasm/js-api/global-internal-init-from-import.js</a></li>
<li><a href="#trunkJSTestswasmjsapiglobalmutatejs">trunk/JSTests/wasm/js-api/global-mutate.js</a></li>
<li><a href="#trunkJSTestswasmjsapiglobalsexportjs">trunk/JSTests/wasm/js-api/globals-export.js</a></li>
<li><a href="#trunkJSTestswasmjsapiglobalsimportjs">trunk/JSTests/wasm/js-api/globals-import.js</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkJSTestsChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/JSTests/ChangeLog (209829 => 209830)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JSTests/ChangeLog        2016-12-14 21:18:02 UTC (rev 209829)
+++ trunk/JSTests/ChangeLog        2016-12-14 21:29:14 UTC (rev 209830)
</span><span class="lines">@@ -1,3 +1,34 @@
</span><ins>+2016-12-14  Keith Miller  &lt;keith_miller@apple.com&gt;
+
+        WebAssembly JS API: implement Global
+        https://bugs.webkit.org/show_bug.cgi?id=164133
+
+        Reviewed by Saam Barati.
+
+        * wasm/Builder.js:
+        (export.default.Builder.prototype._registerSectionBuilders.switch.case.string_appeared_here.this.section):
+        * wasm/Builder_WebAssemblyBinary.js:
+        (const.valueType.WASM.description.type.i32.type.const.putGlobalType):
+        (const.putOp):
+        (const.putInitExpr):
+        (const.emitters.Import):
+        (const.emitters.Global):
+        (const.emitters.Export):
+        (const.emitters.Code):
+        * wasm/LowLevelBinary.js:
+        (export.default.LowLevelBinary.prototype.varuint32):
+        (export.default.LowLevelBinary.prototype.varint32):
+        * wasm/js-api/global-error.js: Added.
+        (catch):
+        (assert.truthy):
+        * wasm/js-api/global-external-init-from-import.js: Added.
+        * wasm/js-api/global-internal-init-from-import.js: Added.
+        * wasm/js-api/global-mutate.js: Added.
+        (createInternalGlobalModule):
+        * wasm/js-api/globals-export.js: Added.
+        * wasm/js-api/globals-import.js: Added.
+        * wasm/wasm.json:
+
</ins><span class="cx"> 2016-12-13  Saam Barati  &lt;sbarati@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         WebAssembly: implement the elements section
</span></span></pre></div>
<a id="trunkJSTestswasmBuilderjs"></a>
<div class="modfile"><h4>Modified: trunk/JSTests/wasm/Builder.js (209829 => 209830)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JSTests/wasm/Builder.js        2016-12-14 21:18:02 UTC (rev 209829)
+++ trunk/JSTests/wasm/Builder.js        2016-12-14 21:29:14 UTC (rev 209830)
</span><span class="lines">@@ -174,6 +174,41 @@
</span><span class="cx">     };
</span><span class="cx"> };
</span><span class="cx"> 
</span><ins>+const _normalizeMutability = (mutability) =&gt; {
+    if (mutability === &quot;mutable&quot;)
+        return 1;
+    else if (mutability === &quot;immutable&quot;)
+        return 0;
+    else
+        throw new Error(`mutability should be either &quot;mutable&quot; or &quot;immutable&quot;, but got ${global.mutablity}`);
+};
+
+const _exportGlobalContinuation = (builder, section, nextBuilder) =&gt; {
+    return (field, index) =&gt; {
+        assert.isNumber(index, `Global exports only support number indices right now`);
+        section.data.push({ field, kind: &quot;Global&quot;, index });
+        return nextBuilder;
+    }
+};
+
+const _importGlobalContinuation = (builder, section, nextBuilder) =&gt; {
+    return () =&gt; {
+        const globalBuilder = {
+            End: () =&gt; nextBuilder
+        };
+        for (let op of WASM.description.value_type) {
+            globalBuilder[_toJavaScriptName(op)] = (module, field, mutability) =&gt; {
+                assert.isString(module, `Import global module should be a string, got &quot;${module}&quot;`);
+                assert.isString(field, `Import global field should be a string, got &quot;${field}&quot;`);
+                assert.isString(mutability, `Import global mutability should be a string, got &quot;${mutability}&quot;`);
+                section.data.push({ globalDescription: { type: op, mutability: _normalizeMutability(mutability) }, module, field, kind: &quot;Global&quot; });
+                return globalBuilder;
+            };
+        }
+        return globalBuilder;
+    };
+};
+
</ins><span class="cx"> const _checkStackArgs = (op, param) =&gt; {
</span><span class="cx">     for (let expect of param) {
</span><span class="cx">         if (WASM.isValidType(expect)) {
</span><span class="lines">@@ -202,6 +237,7 @@
</span><span class="cx">         } else {
</span><span class="cx">             // Handle our own meta-types.
</span><span class="cx">             switch (expect) {
</span><ins>+            case &quot;any&quot;: break;
</ins><span class="cx">             case &quot;bool&quot;: break; // FIXME implement bool. https://bugs.webkit.org/show_bug.cgi?id=163421
</span><span class="cx">             case &quot;call&quot;: break; // FIXME implement call stack return check based on function signature. https://bugs.webkit.org/show_bug.cgi?id=163421
</span><span class="cx">             case &quot;control&quot;: break; // FIXME implement control. https://bugs.webkit.org/show_bug.cgi?id=163421
</span><span class="lines">@@ -407,8 +443,8 @@
</span><span class="cx">                     const s = this._addSection(section);
</span><span class="cx">                     const importBuilder = {
</span><span class="cx">                         End: () =&gt; this,
</span><del>-                        Global: () =&gt; { throw new Error(`Unimplemented: import global`); },
</del><span class="cx">                     };
</span><ins>+                    importBuilder.Global = _importGlobalContinuation(this, s, importBuilder);
</ins><span class="cx">                     importBuilder.Function = _importFunctionContinuation(this, s, importBuilder);
</span><span class="cx">                     importBuilder.Memory = _importMemoryContinuation(this, s, importBuilder);
</span><span class="cx">                     importBuilder.Table = _importTableContinuation(this, s, importBuilder);
</span><span class="lines">@@ -456,8 +492,23 @@
</span><span class="cx">                 break;
</span><span class="cx"> 
</span><span class="cx">             case &quot;Global&quot;:
</span><del>-                // FIXME implement global https://bugs.webkit.org/show_bug.cgi?id=164133
-                this[section] = () =&gt; { throw new Error(`Unimplemented: section type &quot;${section}&quot;`); };
</del><ins>+                this[section] = function() {
+                    const s = this._addSection(section);
+                    const globalBuilder = {
+                        End: () =&gt; this,
+                        GetGlobal: (type, initValue, mutability) =&gt; {
+                            s.data.push({ type, op: &quot;get_global&quot;, mutability: _normalizeMutability(mutability), initValue });
+                            return globalBuilder;
+                        }
+                    };
+                    for (let op of WASM.description.value_type) {
+                        globalBuilder[_toJavaScriptName(op)] = (initValue, mutability) =&gt; {
+                            s.data.push({ type: op, op: op + &quot;.const&quot;, mutability: _normalizeMutability(mutability), initValue });
+                            return globalBuilder;
+                        };
+                    }
+                    return globalBuilder;
+                };
</ins><span class="cx">                 break;
</span><span class="cx"> 
</span><span class="cx">             case &quot;Export&quot;:
</span><span class="lines">@@ -467,8 +518,8 @@
</span><span class="cx">                         End: () =&gt; this,
</span><span class="cx">                         Table: () =&gt; { throw new Error(`Unimplemented: export table`); },
</span><span class="cx">                         Memory: () =&gt; { throw new Error(`Unimplemented: export memory`); },
</span><del>-                        Global: () =&gt; { throw new Error(`Unimplemented: export global`); },
</del><span class="cx">                     };
</span><ins>+                    exportBuilder.Global = _exportGlobalContinuation(this, s, exportBuilder);
</ins><span class="cx">                     exportBuilder.Function = _exportFunctionContinuation(this, s, exportBuilder);
</span><span class="cx">                     return exportBuilder;
</span><span class="cx">                 };
</span><span class="lines">@@ -508,7 +559,7 @@
</span><span class="cx">                     const builder = this;
</span><span class="cx">                     const codeBuilder =  {
</span><span class="cx">                         End: () =&gt; {
</span><del>-                            // We now have enough information to remap the export section's &quot;type&quot; and &quot;index&quot; according to the Code section we're currently ending.
</del><ins>+                            // We now have enough information to remap the export section's &quot;type&quot; and &quot;index&quot; according to the Code section we are currently ending.
</ins><span class="cx">                             const typeSection = builder._getSection(&quot;Type&quot;);
</span><span class="cx">                             const importSection = builder._getSection(&quot;Import&quot;);
</span><span class="cx">                             const exportSection = builder._getSection(&quot;Export&quot;);
</span><span class="lines">@@ -516,6 +567,8 @@
</span><span class="cx">                             const codeSection = s;
</span><span class="cx">                             if (exportSection) {
</span><span class="cx">                                 for (const e of exportSection.data) {
</span><ins>+                                    if (e.kind !== &quot;Function&quot; || typeof(e.type) !== &quot;undefined&quot;)
+                                        continue;
</ins><span class="cx">                                     switch (typeof(e.index)) {
</span><span class="cx">                                     default: throw new Error(`Unexpected export index &quot;${e.index}&quot;`);
</span><span class="cx">                                     case &quot;string&quot;: {
</span></span></pre></div>
<a id="trunkJSTestswasmBuilder_WebAssemblyBinaryjs"></a>
<div class="modfile"><h4>Modified: trunk/JSTests/wasm/Builder_WebAssemblyBinary.js (209829 => 209830)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JSTests/wasm/Builder_WebAssemblyBinary.js        2016-12-14 21:18:02 UTC (rev 209829)
+++ trunk/JSTests/wasm/Builder_WebAssemblyBinary.js        2016-12-14 21:29:14 UTC (rev 209830)
</span><span class="lines">@@ -51,6 +51,40 @@
</span><span class="cx">     putResizableLimits(bin, initial, maximum);
</span><span class="cx"> };
</span><span class="cx"> 
</span><ins>+const valueType = WASM.description.type.i32.type
+
+const putGlobalType = (bin, global) =&gt; {
+    put(bin, valueType, WASM.typeValue[global.type]);
+    put(bin, &quot;varuint1&quot;, global.mutability);
+};
+
+const putOp = (bin, op) =&gt; {
+    put(bin, &quot;uint8&quot;, op.value);
+    if (op.arguments.length !== 0)
+        throw new Error(`Unimplemented: arguments`); // FIXME https://bugs.webkit.org/show_bug.cgi?id=162706
+
+    switch (op.name) {
+    default:
+        for (let i = 0; i &lt; op.immediates.length; ++i) {
+            const type = WASM.description.opcode[op.name].immediate[i].type
+            if (!bin[type])
+                throw new TypeError(`Unknown type: ${type} in op: ${op.name}`);
+            put(bin, type, op.immediates[i]);
+        }
+        break;
+    case &quot;br_table&quot;:
+        put(bin, &quot;varuint32&quot;, op.immediates.length - 1);
+        for (let imm of op.immediates)
+            put(bin, &quot;varuint32&quot;, imm);
+        break;
+    }
+};
+
+const putInitExpr = (bin, expr) =&gt; {
+    putOp(bin, { value: WASM.description.opcode[expr.op].value, name: expr.op, immediates: [expr.initValue], arguments: [] });
+    putOp(bin, { value: WASM.description.opcode.end.value, name: &quot;end&quot;, immediates: [], arguments: [] });
+};
+
</ins><span class="cx"> const emitters = {
</span><span class="cx">     Type: (section, bin) =&gt; {
</span><span class="cx">         put(bin, &quot;varuint32&quot;, section.data.length);
</span><span class="lines">@@ -88,7 +122,9 @@
</span><span class="cx">                 putResizableLimits(bin, initial, maximum);
</span><span class="cx">                 break;
</span><span class="cx">             };
</span><del>-            case &quot;Global&quot;: throw new Error(`Not yet implemented`);
</del><ins>+            case &quot;Global&quot;:
+                putGlobalType(bin, entry.globalDescription);
+                break;
</ins><span class="cx">             }
</span><span class="cx">         }
</span><span class="cx">     },
</span><span class="lines">@@ -117,7 +153,14 @@
</span><span class="cx">         }
</span><span class="cx">     },
</span><span class="cx"> 
</span><del>-    Global: (section, bin) =&gt; { throw new Error(`Not yet implemented`); },
</del><ins>+    Global: (section, bin) =&gt; {
+        put(bin, &quot;varuint32&quot;, section.data.length);
+        for (const global of section.data) {
+            putGlobalType(bin, global);
+            putInitExpr(bin, global)
+        }
+    },
+
</ins><span class="cx">     Export: (section, bin) =&gt; {
</span><span class="cx">         put(bin, &quot;varuint32&quot;, section.data.length);
</span><span class="cx">         for (const entry of section.data) {
</span><span class="lines">@@ -125,10 +168,13 @@
</span><span class="cx">             put(bin, &quot;uint8&quot;, WASM.externalKindValue[entry.kind]);
</span><span class="cx">             switch (entry.kind) {
</span><span class="cx">             default: throw new Error(`Implementation problem: unexpected kind ${entry.kind}`);
</span><del>-            case &quot;Function&quot;: put(bin, &quot;varuint32&quot;, entry.index); break;
</del><ins>+            case &quot;Global&quot;:
+            case &quot;Function&quot;:
+                put(bin, &quot;varuint32&quot;, entry.index);
+                break;
</ins><span class="cx">             case &quot;Table&quot;: throw new Error(`Not yet implemented`);
</span><span class="cx">             case &quot;Memory&quot;: throw new Error(`Not yet implemented`);
</span><del>-            case &quot;Global&quot;: throw new Error(`Not yet implemented`);
</del><ins>+
</ins><span class="cx">             }
</span><span class="cx">         }
</span><span class="cx">     },
</span><span class="lines">@@ -164,27 +210,9 @@
</span><span class="cx">                 put(funcBin, &quot;varint7&quot;, WASM.typeValue[func.locals[i]]);
</span><span class="cx">             }
</span><span class="cx"> 
</span><del>-            for (const op of func.code) {
-                put(funcBin, &quot;uint8&quot;, op.value);
-                if (op.arguments.length !== 0)
-                    throw new Error(`Unimplemented: arguments`); // FIXME https://bugs.webkit.org/show_bug.cgi?id=162706
</del><ins>+            for (const op of func.code)
+                putOp(funcBin, op);
</ins><span class="cx"> 
</span><del>-                switch (op.name) {
-                default:
-                    for (let i = 0; i &lt; op.immediates.length; ++i) {
-                        const type = WASM.description.opcode[op.name].immediate[i].type
-                        if (!funcBin[type])
-                            throw new TypeError(`Unknown type: ${type} in op: ${op.name}`);
-                        put(funcBin, type, op.immediates[i]);
-                    }
-                    break;
-                case &quot;br_table&quot;:
-                    put(funcBin, &quot;varuint32&quot;, op.immediates.length - 1);
-                    for (let imm of op.immediates)
-                        put(funcBin, &quot;varuint32&quot;, imm);
-                    break;
-                }
-            }
</del><span class="cx">             funcBin.apply();
</span><span class="cx">         }
</span><span class="cx">     },
</span></span></pre></div>
<a id="trunkJSTestswasmLowLevelBinaryjs"></a>
<div class="modfile"><h4>Modified: trunk/JSTests/wasm/LowLevelBinary.js (209829 => 209830)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JSTests/wasm/LowLevelBinary.js        2016-12-14 21:18:02 UTC (rev 209829)
+++ trunk/JSTests/wasm/LowLevelBinary.js        2016-12-14 21:29:14 UTC (rev 209830)
</span><span class="lines">@@ -123,6 +123,7 @@
</span><span class="cx">         this._push8(v &gt;&gt;&gt; 24);
</span><span class="cx">     }
</span><span class="cx">     varuint32(v) {
</span><ins>+        assert.isNumber(v);
</ins><span class="cx">         if (v &lt; varuint32Min || varuint32Max &lt; v)
</span><span class="cx">             throw new RangeError(`Invalid varuint32 ${v} range is [${varuint32Min}, ${varuint32Max}]`);
</span><span class="cx">         while (v &gt;= 0x80) {
</span><span class="lines">@@ -132,6 +133,7 @@
</span><span class="cx">         this.uint8(v);
</span><span class="cx">     }
</span><span class="cx">     varint32(v) {
</span><ins>+        assert.isNumber(v);
</ins><span class="cx">         if (v &lt; varint32Min || varint32Max &lt; v)
</span><span class="cx">             throw new RangeError(`Invalid varint32 ${v} range is [${varint32Min}, ${varint32Max}]`);
</span><span class="cx">         do {
</span></span></pre></div>
<a id="trunkJSTestswasmjsapiglobalerrorjs"></a>
<div class="addfile"><h4>Added: trunk/JSTests/wasm/js-api/global-error.js (0 => 209830)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JSTests/wasm/js-api/global-error.js                                (rev 0)
+++ trunk/JSTests/wasm/js-api/global-error.js        2016-12-14 21:29:14 UTC (rev 209830)
</span><span class="lines">@@ -0,0 +1,238 @@
</span><ins>+import * as assert from '../assert.js';
+import Builder from '../Builder.js';
+
+{
+    // Test init from non-import.
+    const builder = new Builder();
+
+    builder.Type().End()
+        .Function().End()
+        .Global().GetGlobal(&quot;i32&quot;, 0, &quot;immutable&quot;).End()
+        .Export()
+            .Function(&quot;getGlobal&quot;)
+            .Global(&quot;global&quot;, 1)
+        .End()
+        .Code()
+
+        .Function(&quot;getGlobal&quot;, { params: [], ret: &quot;i32&quot; })
+        .GetGlobal(1)
+        .End()
+
+        .End()
+
+    const bin = builder.WebAssembly();
+    bin.trim();
+
+    let passed = false;
+    try {
+        const module = new WebAssembly.Module(bin.get());
+    } catch (e) {
+        if (e.message === &quot;couldn't parse section Global: Global declarations (evaluating 'new WebAssembly.Module(bin.get())')&quot;)
+            passed = true;
+    }
+    assert.truthy(passed);
+}
+
+
+{
+    // Test import mutable.
+    const builder = new Builder();
+
+    builder.Type().End()
+        .Import()
+            .Global().I32(&quot;imp&quot;, &quot;global&quot;, &quot;mutable&quot;).End()
+        .End()
+        .Function().End()
+        .Global().GetGlobal(&quot;i32&quot;, 0, &quot;immutable&quot;).End()
+        .Export()
+            .Function(&quot;getGlobal&quot;)
+            .Global(&quot;global&quot;, 1)
+        .End()
+        .Code()
+
+        .Function(&quot;getGlobal&quot;, { params: [], ret: &quot;i32&quot; })
+        .GetGlobal(1)
+        .End()
+
+        .End()
+
+    const bin = builder.WebAssembly();
+    bin.trim();
+
+    let passed = false;
+    try {
+        const module = new WebAssembly.Module(bin.get());
+    } catch (e) {
+        if (e.message === &quot;couldn't parse section Import: Import declarations (evaluating 'new WebAssembly.Module(bin.get())')&quot;)
+            passed = true;
+    }
+    assert.truthy(passed);
+}
+
+{
+    // Test export mutable.
+    const builder = new Builder();
+
+    builder.Type().End()
+        .Function().End()
+        .Global().I32(0, &quot;mutable&quot;).End()
+        .Export()
+            .Function(&quot;setGlobal&quot;)
+            .Global(&quot;global&quot;, 0)
+        .End()
+        .Code()
+
+        .Function(&quot;setGlobal&quot;, { params: [], ret: &quot;i32&quot; })
+        .GetGlobal(1)
+        .End()
+
+        .End()
+
+    const bin = builder.WebAssembly();
+    bin.trim();
+
+    let passed = false;
+    try {
+        const module = new WebAssembly.Module(bin.get());
+    } catch (e) {
+        if (e.message === &quot;couldn't parse section Export: Exports (evaluating 'new WebAssembly.Module(bin.get())')&quot;)
+            passed = true;
+    }
+    assert.truthy(passed);
+}
+
+{
+    // Test set immutable.
+    const builder = new Builder();
+
+    builder.Type().End()
+        .Function().End()
+        .Global().I32(0, &quot;immutable&quot;).End()
+        .Export()
+            .Function(&quot;setGlobal&quot;)
+            .Global(&quot;global&quot;, 0)
+        .End()
+        .Code()
+
+        .Function(&quot;setGlobal&quot;, { params: [], ret: &quot;i32&quot; })
+        .I32Const(0)
+        .SetGlobal(0)
+        .End()
+
+        .End()
+
+    const bin = builder.WebAssembly();
+    bin.trim();
+
+    let passed = false;
+    try {
+        const module = new WebAssembly.Module(bin.get());
+    } catch (e) {
+        if (e.message === &quot;Attempt to store to immutable global. (evaluating 'new WebAssembly.Module(bin.get())')&quot;)
+            passed = true;
+    }
+    assert.truthy(passed);
+}
+
+
+{
+    // Test set non-existant global.
+    const builder = new Builder();
+
+    builder.Type().End()
+        .Function().End()
+        .Global().I32(0, &quot;immutable&quot;).End()
+        .Export()
+            .Function(&quot;setGlobal&quot;)
+            .Global(&quot;global&quot;, 0)
+        .End()
+        .Code()
+
+        .Function(&quot;setGlobal&quot;, { params: [], ret: &quot;i32&quot; })
+        .I32Const(0)
+        .SetGlobal(1)
+        .End()
+
+        .End()
+
+    const bin = builder.WebAssembly();
+    bin.trim();
+
+    let passed = false;
+    try {
+        const module = new WebAssembly.Module(bin.get());
+    } catch (e) {
+        if (e.message === &quot;Attempt to use unknown global. (evaluating 'new WebAssembly.Module(bin.get())')&quot;)
+            passed = true;
+    }
+    assert.truthy(passed);
+}
+
+
+{
+    // Test set to incorrect type
+    const builder = new Builder();
+
+    builder.Type().End()
+        .Function().End()
+        .Global().F32(0, &quot;mutable&quot;).End()
+        .Export()
+            .Function(&quot;setGlobal&quot;)
+        .End()
+        .Code()
+
+        .Function(&quot;setGlobal&quot;, { params: [], ret: &quot;i32&quot; })
+        .I32Const(0)
+        .SetGlobal(0)
+        .End()
+
+        .End()
+
+    const bin = builder.WebAssembly();
+    bin.trim();
+
+    let passed = false;
+    try {
+        const module = new WebAssembly.Module(bin.get());
+    } catch (e) {
+        if (e.message === &quot;Attempt to set global with type: F32 with a variable of type: I32 (evaluating 'new WebAssembly.Module(bin.get())')&quot;)
+            passed = true;
+    }
+    assert.truthy(passed);
+}
+
+for ( let imp of [undefined, null, {}, () =&gt; {}, &quot;number&quot;, new Number(4)]) {
+    // Test import non-number.
+    const builder = new Builder();
+
+    builder.Type().End()
+        .Import()
+            .Global().I32(&quot;imp&quot;, &quot;global&quot;, &quot;immutable&quot;).End()
+        .End()
+        .Function().End()
+        .Global().GetGlobal(&quot;i32&quot;, 0, &quot;immutable&quot;).End()
+        .Export()
+            .Function(&quot;getGlobal&quot;)
+            .Global(&quot;global&quot;, 1)
+        .End()
+        .Code()
+
+        .Function(&quot;getGlobal&quot;, { params: [], ret: &quot;i32&quot; })
+        .GetGlobal(1)
+        .End()
+
+        .End()
+
+    const bin = builder.WebAssembly();
+    bin.trim();
+
+    let passed = false;
+    const module = new WebAssembly.Module(bin.get());
+    try {
+        new WebAssembly.Instance(module, { imp: { global: imp } });
+    } catch (e) {
+        if (e.message === &quot;imported global must be a number (evaluating 'new WebAssembly.Instance(module, { imp: { global: imp } })')&quot;)
+            passed = true;
+    }
+    assert.truthy(passed);
+}
</ins></span></pre></div>
<a id="trunkJSTestswasmjsapiglobalexternalinitfromimportjs"></a>
<div class="addfile"><h4>Added: trunk/JSTests/wasm/js-api/global-external-init-from-import.js (0 => 209830)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JSTests/wasm/js-api/global-external-init-from-import.js                                (rev 0)
+++ trunk/JSTests/wasm/js-api/global-external-init-from-import.js        2016-12-14 21:29:14 UTC (rev 209830)
</span><span class="lines">@@ -0,0 +1,30 @@
</span><ins>+import * as assert from '../assert.js';
+import Builder from '../Builder.js';
+
+const builder = new Builder();
+
+builder.Type().End()
+    .Import()
+        .Global().I32(&quot;imp&quot;, &quot;global&quot;, &quot;immutable&quot;).End()
+    .End()
+    .Function().End()
+    .Global().GetGlobal(&quot;i32&quot;, 0, &quot;immutable&quot;).End()
+    .Export()
+        .Function(&quot;getGlobal&quot;)
+    .Global(&quot;global&quot;, 1)
+    .End()
+    .Code()
+
+    .Function(&quot;getGlobal&quot;, { params: [], ret: &quot;i32&quot; })
+        .GetGlobal(1)
+    .End()
+
+    .End()
+
+const bin = builder.WebAssembly();
+bin.trim();
+
+const module = new WebAssembly.Module(bin.get());
+const instance = new WebAssembly.Instance(module, { imp: { global: 5 } });
+assert.eq(instance.exports.getGlobal(), 5);
+assert.eq(instance.exports.global, 5);
</ins></span></pre></div>
<a id="trunkJSTestswasmjsapiglobalinternalinitfromimportjs"></a>
<div class="addfile"><h4>Added: trunk/JSTests/wasm/js-api/global-internal-init-from-import.js (0 => 209830)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JSTests/wasm/js-api/global-internal-init-from-import.js                                (rev 0)
+++ trunk/JSTests/wasm/js-api/global-internal-init-from-import.js        2016-12-14 21:29:14 UTC (rev 209830)
</span><span class="lines">@@ -0,0 +1,26 @@
</span><ins>+import * as assert from '../assert.js';
+import Builder from '../Builder.js';
+
+const builder = new Builder();
+
+builder.Type().End()
+    .Import()
+        .Global().I32(&quot;imp&quot;, &quot;global&quot;, &quot;immutable&quot;).End()
+    .End()
+    .Function().End()
+    .Global().GetGlobal(&quot;i32&quot;, 0, &quot;mutable&quot;).End()
+    .Export().Function(&quot;getGlobal&quot;).End()
+    .Code()
+
+    .Function(&quot;getGlobal&quot;, { params: [], ret: &quot;i32&quot; })
+        .GetGlobal(1)
+    .End()
+
+    .End()
+
+const bin = builder.WebAssembly();
+bin.trim();
+
+const module = new WebAssembly.Module(bin.get());
+const instance = new WebAssembly.Instance(module, { imp: { global: 5 } });
+assert.eq(instance.exports.getGlobal(), 5);
</ins></span></pre></div>
<a id="trunkJSTestswasmjsapiglobalmutatejs"></a>
<div class="addfile"><h4>Added: trunk/JSTests/wasm/js-api/global-mutate.js (0 => 209830)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JSTests/wasm/js-api/global-mutate.js                                (rev 0)
+++ trunk/JSTests/wasm/js-api/global-mutate.js        2016-12-14 21:29:14 UTC (rev 209830)
</span><span class="lines">@@ -0,0 +1,39 @@
</span><ins>+import * as assert from '../assert.js';
+import Builder from '../Builder.js';
+
+function createInternalGlobalModule() {
+    const builder = new Builder();
+
+    builder.Type().End()
+        .Function().End()
+        .Global().I32(5, &quot;mutable&quot;).End()
+        .Export()
+            .Function(&quot;getGlobal&quot;)
+            .Function(&quot;setGlobal&quot;)
+        .End()
+        .Code()
+
+        // GetGlobal
+        .Function(&quot;getGlobal&quot;, { params: [], ret: &quot;i32&quot; })
+            .GetGlobal(0)
+        .End()
+
+        // SetGlobal
+        .Function(&quot;setGlobal&quot;, { params: [&quot;i32&quot;] })
+            .GetLocal(0)
+            .SetGlobal(0)
+        .End()
+
+        .End()
+
+    const bin = builder.WebAssembly();
+    bin.trim();
+
+    const module = new WebAssembly.Module(bin.get());
+    const instance = new WebAssembly.Instance(module);
+    assert.eq(instance.exports.getGlobal(), 5);
+    instance.exports.setGlobal(3);
+    assert.eq(instance.exports.getGlobal(), 3);
+}
+
+createInternalGlobalModule();
</ins></span></pre></div>
<a id="trunkJSTestswasmjsapiglobalsexportjs"></a>
<div class="addfile"><h4>Added: trunk/JSTests/wasm/js-api/globals-export.js (0 => 209830)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JSTests/wasm/js-api/globals-export.js                                (rev 0)
+++ trunk/JSTests/wasm/js-api/globals-export.js        2016-12-14 21:29:14 UTC (rev 209830)
</span><span class="lines">@@ -0,0 +1,28 @@
</span><ins>+import * as assert from '../assert.js';
+import Builder from '../Builder.js';
+
+const builder = new Builder();
+
+builder.Type().End()
+    .Import()
+        .Global().I32(&quot;imp&quot;, &quot;global&quot;, &quot;immutable&quot;).End()
+    .End()
+    .Function().End()
+    .Export()
+        .Function(&quot;getGlobal&quot;)
+        .Global(&quot;global&quot;, 0)
+    .End()
+    .Code()
+
+    .Function(&quot;getGlobal&quot;, { params: [], ret: &quot;i32&quot; })
+        .GetGlobal(0)
+    .End()
+
+    .End()
+
+const bin = builder.WebAssembly();
+bin.trim();
+
+const module = new WebAssembly.Module(bin.get());
+const instance = new WebAssembly.Instance(module, { imp: { global: 5 } });
+assert.eq(instance.exports.global, 5);
</ins></span></pre></div>
<a id="trunkJSTestswasmjsapiglobalsimportjs"></a>
<div class="addfile"><h4>Added: trunk/JSTests/wasm/js-api/globals-import.js (0 => 209830)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JSTests/wasm/js-api/globals-import.js                                (rev 0)
+++ trunk/JSTests/wasm/js-api/globals-import.js        2016-12-14 21:29:14 UTC (rev 209830)
</span><span class="lines">@@ -0,0 +1,29 @@
</span><ins>+import * as assert from '../assert.js';
+import Builder from '../Builder.js';
+
+const builder = new Builder();
+
+builder.Type().End()
+    .Import()
+        .Global().I32(&quot;imp&quot;, &quot;global&quot;, &quot;immutable&quot;).End()
+    .End()
+    .Function().End()
+    .Global().I32(5, &quot;mutable&quot;).End()
+    .Export()
+        .Function(&quot;getGlobal&quot;)
+    .End()
+    .Code()
+
+    // GetGlobal
+    .Function(&quot;getGlobal&quot;, { params: [], ret: &quot;i32&quot; })
+        .GetGlobal(0)
+    .End()
+
+    .End()
+
+const bin = builder.WebAssembly();
+bin.trim();
+
+const module = new WebAssembly.Module(bin.get());
+const instance = new WebAssembly.Instance(module, { imp: { global: 5 } });
+assert.eq(instance.exports.getGlobal(), 5);
</ins></span></pre></div>
<a id="trunkJSTestswasmwasmjson"></a>
<div class="modfile"><h4>Modified: trunk/JSTests/wasm/wasm.json (209829 => 209830)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JSTests/wasm/wasm.json        2016-12-14 21:18:02 UTC (rev 209829)
+++ trunk/JSTests/wasm/wasm.json        2016-12-14 21:29:14 UTC (rev 209830)
</span><span class="lines">@@ -58,11 +58,11 @@
</span><span class="cx">         &quot;i64.const&quot;:           { &quot;category&quot;: &quot;special&quot;,    &quot;value&quot;:  66, &quot;return&quot;: [&quot;i64&quot;],      &quot;parameter&quot;: [],                       &quot;immediate&quot;: [{&quot;name&quot;: &quot;value&quot;,          &quot;type&quot;: &quot;varint64&quot;}],                                           &quot;description&quot;: &quot;a constant value interpreted as i64&quot; },
</span><span class="cx">         &quot;f64.const&quot;:           { &quot;category&quot;: &quot;special&quot;,    &quot;value&quot;:  68, &quot;return&quot;: [&quot;f64&quot;],      &quot;parameter&quot;: [],                       &quot;immediate&quot;: [{&quot;name&quot;: &quot;value&quot;,          &quot;type&quot;: &quot;uint64&quot;}],                                             &quot;description&quot;: &quot;a constant value interpreted as f64&quot; },
</span><span class="cx">         &quot;f32.const&quot;:           { &quot;category&quot;: &quot;special&quot;,    &quot;value&quot;:  67, &quot;return&quot;: [&quot;f32&quot;],      &quot;parameter&quot;: [],                       &quot;immediate&quot;: [{&quot;name&quot;: &quot;value&quot;,          &quot;type&quot;: &quot;uint32&quot;}],                                             &quot;description&quot;: &quot;a constant value interpreted as f32&quot; },
</span><del>-        &quot;get_local&quot;:           { &quot;category&quot;: &quot;special&quot;,    &quot;value&quot;:  32, &quot;return&quot;: [&quot;local&quot;],    &quot;parameter&quot;: [],                       &quot;immediate&quot;: [{&quot;name&quot;: &quot;local_index&quot;,    &quot;type&quot;: &quot;varuint32&quot;}],                                          &quot;description&quot;: &quot;read a local variable or parameter&quot; },
-        &quot;set_local&quot;:           { &quot;category&quot;: &quot;special&quot;,    &quot;value&quot;:  33, &quot;return&quot;: [],           &quot;parameter&quot;: [&quot;local&quot;],                &quot;immediate&quot;: [{&quot;name&quot;: &quot;local_index&quot;,    &quot;type&quot;: &quot;varuint32&quot;}],                                          &quot;description&quot;: &quot;write a local variable or parameter&quot; },
-        &quot;tee_local&quot;:           { &quot;category&quot;: &quot;special&quot;,    &quot;value&quot;:  34, &quot;return&quot;: [&quot;prev&quot;],     &quot;parameter&quot;: [&quot;any&quot;],                  &quot;immediate&quot;: [{&quot;name&quot;: &quot;local_index&quot;,    &quot;type&quot;: &quot;varuint32&quot;}],                                          &quot;description&quot;: &quot;write a local variable or parameter and return the same value&quot; },
-        &quot;get_global&quot;:          { &quot;category&quot;: &quot;special&quot;,    &quot;value&quot;:  35, &quot;return&quot;: [&quot;global&quot;],   &quot;parameter&quot;: [],                       &quot;immediate&quot;: [{&quot;name&quot;: &quot;global_index&quot;,   &quot;type&quot;: &quot;varuint32&quot;}],                                          &quot;description&quot;: &quot;read a global variable&quot; },
-        &quot;set_global&quot;:          { &quot;category&quot;: &quot;special&quot;,    &quot;value&quot;:  36, &quot;return&quot;: [&quot;&quot;],         &quot;parameter&quot;: [&quot;global&quot;],               &quot;immediate&quot;: [{&quot;name&quot;: &quot;global_index&quot;,   &quot;type&quot;: &quot;varuint32&quot;}],                                          &quot;description&quot;: &quot;write a global variable&quot; },
</del><ins>+        &quot;get_local&quot;:           { &quot;category&quot;: &quot;special&quot;,    &quot;value&quot;:  32, &quot;return&quot;: [&quot;any&quot;],    &quot;parameter&quot;: [],                       &quot;immediate&quot;: [{&quot;name&quot;: &quot;local_index&quot;,    &quot;type&quot;: &quot;varuint32&quot;}],                                          &quot;description&quot;: &quot;read a local variable or parameter&quot; },
+        &quot;set_local&quot;:           { &quot;category&quot;: &quot;special&quot;,    &quot;value&quot;:  33, &quot;return&quot;: [],           &quot;parameter&quot;: [&quot;any&quot;],                &quot;immediate&quot;: [{&quot;name&quot;: &quot;local_index&quot;,    &quot;type&quot;: &quot;varuint32&quot;}],                                          &quot;description&quot;: &quot;write a local variable or parameter&quot; },
+        &quot;tee_local&quot;:           { &quot;category&quot;: &quot;special&quot;,    &quot;value&quot;:  34, &quot;return&quot;: [&quot;any&quot;],     &quot;parameter&quot;: [&quot;any&quot;],                  &quot;immediate&quot;: [{&quot;name&quot;: &quot;local_index&quot;,    &quot;type&quot;: &quot;varuint32&quot;}],                                          &quot;description&quot;: &quot;write a local variable or parameter and return the same value&quot; },
+        &quot;get_global&quot;:          { &quot;category&quot;: &quot;special&quot;,    &quot;value&quot;:  35, &quot;return&quot;: [&quot;any&quot;],   &quot;parameter&quot;: [],                       &quot;immediate&quot;: [{&quot;name&quot;: &quot;global_index&quot;,   &quot;type&quot;: &quot;varuint32&quot;}],                                          &quot;description&quot;: &quot;read a global variable&quot; },
+        &quot;set_global&quot;:          { &quot;category&quot;: &quot;special&quot;,    &quot;value&quot;:  36, &quot;return&quot;: [],         &quot;parameter&quot;: [&quot;any&quot;],               &quot;immediate&quot;: [{&quot;name&quot;: &quot;global_index&quot;,   &quot;type&quot;: &quot;varuint32&quot;}],                                          &quot;description&quot;: &quot;write a global variable&quot; },
</ins><span class="cx">         &quot;call&quot;:                { &quot;category&quot;: &quot;call&quot;,       &quot;value&quot;:  16, &quot;return&quot;: [&quot;call&quot;],     &quot;parameter&quot;: [&quot;call&quot;],                 &quot;immediate&quot;: [{&quot;name&quot;: &quot;function_index&quot;, &quot;type&quot;: &quot;varuint32&quot;}],                                          &quot;description&quot;: &quot;call a function by its index&quot; },
</span><span class="cx">         &quot;call_indirect&quot;:       { &quot;category&quot;: &quot;call&quot;,       &quot;value&quot;:  17, &quot;return&quot;: [&quot;call&quot;],     &quot;parameter&quot;: [&quot;call&quot;],                 &quot;immediate&quot;: [{&quot;name&quot;: &quot;type_index&quot;,     &quot;type&quot;: &quot;varuint32&quot;}, {&quot;name&quot;: &quot;reserved&quot;,     &quot;type&quot;: &quot;varuint1&quot;}], &quot;description&quot;: &quot;call a function indirect with an expected signature&quot; },
</span><span class="cx">         &quot;i32.load8_s&quot;:         { &quot;category&quot;: &quot;memory&quot;,     &quot;value&quot;:  44, &quot;return&quot;: [&quot;i32&quot;],      &quot;parameter&quot;: [&quot;addr&quot;],                 &quot;immediate&quot;: [{&quot;name&quot;: &quot;flags&quot;,          &quot;type&quot;: &quot;varuint32&quot;}, {&quot;name&quot;: &quot;offset&quot;, &quot;type&quot;: &quot;varuint32&quot;}], &quot;description&quot;: &quot;load from memory&quot; },
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ChangeLog (209829 => 209830)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ChangeLog        2016-12-14 21:18:02 UTC (rev 209829)
+++ trunk/Source/JavaScriptCore/ChangeLog        2016-12-14 21:29:14 UTC (rev 209830)
</span><span class="lines">@@ -1,3 +1,63 @@
</span><ins>+2016-12-14  Keith Miller  &lt;keith_miller@apple.com&gt;
+
+        WebAssembly JS API: implement Global
+        https://bugs.webkit.org/show_bug.cgi?id=164133
+
+        Reviewed by Saam Barati.
+
+        This patch adds support for globals. It handles imports, exports
+        and internal globals. In the MVP only internal globals are allowed
+        to be mutable. This means we can store a C-array of 64-bit slots
+        off the instance holding them. When globals are exported to JS
+        they are done so as numbers. This means that i64 globals cannot be
+        imported or exported.
+
+        * wasm/WasmB3IRGenerator.cpp:
+        (JSC::Wasm::B3IRGenerator::B3IRGenerator):
+        (JSC::Wasm::B3IRGenerator::getGlobal):
+        (JSC::Wasm::B3IRGenerator::setGlobal):
+        (JSC::Wasm::B3IRGenerator::addCallIndirect):
+        (JSC::Wasm::parseAndCompile):
+        * wasm/WasmFormat.h:
+        * wasm/WasmFunctionParser.h:
+        (JSC::Wasm::FunctionParser&lt;Context&gt;::parseExpression):
+        * wasm/WasmModuleParser.cpp:
+        (JSC::Wasm::ModuleParser::parseImport):
+        (JSC::Wasm::ModuleParser::parseGlobal):
+        (JSC::Wasm::ModuleParser::parseExport):
+        (JSC::Wasm::ModuleParser::parseElement):
+        (JSC::Wasm::ModuleParser::parseInitExpr):
+        (JSC::Wasm::ModuleParser::parseGlobalType):
+        (JSC::Wasm::ModuleParser::parseData):
+        * wasm/WasmModuleParser.h:
+        * wasm/WasmParser.h:
+        (JSC::Wasm::Parser::parseVarInt32):
+        (JSC::Wasm::Parser::parseVarInt64):
+        (JSC::Wasm::Parser::parseUInt64):
+        * wasm/WasmValidate.cpp:
+        (JSC::Wasm::Validate::hasMemory):
+        (JSC::Wasm::Validate::Validate):
+        (JSC::Wasm::Validate::getGlobal):
+        (JSC::Wasm::Validate::setGlobal):
+        (JSC::Wasm::validateFunction):
+        * wasm/generateWasmOpsHeader.py:
+        * wasm/js/JSWebAssemblyInstance.cpp:
+        (JSC::JSWebAssemblyInstance::create):
+        (JSC::JSWebAssemblyInstance::finishCreation):
+        (JSC::JSWebAssemblyInstance::visitChildren):
+        * wasm/js/JSWebAssemblyInstance.h:
+        (JSC::JSWebAssemblyInstance::loadI32Global):
+        (JSC::JSWebAssemblyInstance::loadI64Global):
+        (JSC::JSWebAssemblyInstance::loadF32Global):
+        (JSC::JSWebAssemblyInstance::loadF64Global):
+        (JSC::JSWebAssemblyInstance::setGlobal):
+        (JSC::JSWebAssemblyInstance::offsetOfGlobals):
+        * wasm/js/WebAssemblyInstanceConstructor.cpp:
+        (JSC::constructJSWebAssemblyInstance):
+        * wasm/js/WebAssemblyModuleRecord.cpp:
+        (JSC::WebAssemblyModuleRecord::finishCreation):
+        (JSC::WebAssemblyModuleRecord::link):
+
</ins><span class="cx"> 2016-12-14  Filip Pizlo  &lt;fpizlo@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Unreviewed, re-enable concurrent GC on ARM64 now that the most likely culprit of the memory
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorewasmWasmB3IRGeneratorcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/wasm/WasmB3IRGenerator.cpp (209829 => 209830)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/wasm/WasmB3IRGenerator.cpp        2016-12-14 21:18:02 UTC (rev 209829)
+++ trunk/Source/JavaScriptCore/wasm/WasmB3IRGenerator.cpp        2016-12-14 21:29:14 UTC (rev 209830)
</span><span class="lines">@@ -137,7 +137,7 @@
</span><span class="cx"> 
</span><span class="cx">     static constexpr ExpressionType emptyExpression = nullptr;
</span><span class="cx"> 
</span><del>-    B3IRGenerator(VM&amp;, const MemoryInformation&amp;, Procedure&amp;, WasmInternalFunction*, Vector&lt;UnlinkedWasmToWasmCall&gt;&amp;, const ImmutableFunctionIndexSpace&amp;);
</del><ins>+    B3IRGenerator(VM&amp;, const ModuleInformation&amp;, Procedure&amp;, WasmInternalFunction*, Vector&lt;UnlinkedWasmToWasmCall&gt;&amp;, const ImmutableFunctionIndexSpace&amp;);
</ins><span class="cx"> 
</span><span class="cx">     bool WARN_UNUSED_RETURN addArguments(const Vector&lt;Type&gt;&amp;);
</span><span class="cx">     bool WARN_UNUSED_RETURN addLocal(Type, uint32_t);
</span><span class="lines">@@ -147,6 +147,10 @@
</span><span class="cx">     bool WARN_UNUSED_RETURN getLocal(uint32_t index, ExpressionType&amp; result);
</span><span class="cx">     bool WARN_UNUSED_RETURN setLocal(uint32_t index, ExpressionType value);
</span><span class="cx"> 
</span><ins>+    // Globals
+    bool WARN_UNUSED_RETURN getGlobal(uint32_t index, ExpressionType&amp; result);
+    bool WARN_UNUSED_RETURN setGlobal(uint32_t index, ExpressionType value);
+
</ins><span class="cx">     // Memory
</span><span class="cx">     bool WARN_UNUSED_RETURN load(LoadOpType, ExpressionType pointer, ExpressionType&amp; result, uint32_t offset);
</span><span class="cx">     bool WARN_UNUSED_RETURN store(StoreOpType, ExpressionType pointer, ExpressionType value, uint32_t offset);
</span><span class="lines">@@ -190,6 +194,7 @@
</span><span class="cx"> 
</span><span class="cx">     VM&amp; m_vm;
</span><span class="cx">     const ImmutableFunctionIndexSpace&amp; m_functionIndexSpace;
</span><ins>+    const ModuleInformation&amp; m_info;
</ins><span class="cx">     Procedure&amp; m_proc;
</span><span class="cx">     BasicBlock* m_currentBlock;
</span><span class="cx">     Vector&lt;Variable*&gt; m_locals;
</span><span class="lines">@@ -197,12 +202,14 @@
</span><span class="cx">     GPRReg m_memoryBaseGPR;
</span><span class="cx">     GPRReg m_memorySizeGPR;
</span><span class="cx">     Value* m_zeroValues[numTypes];
</span><del>-    Value* m_functionIndexSpaceValue;
</del><ins>+    Value* m_instanceValue;
+
</ins><span class="cx"> };
</span><span class="cx"> 
</span><del>-B3IRGenerator::B3IRGenerator(VM&amp; vm, const MemoryInformation&amp; memory, Procedure&amp; procedure, WasmInternalFunction* compilation, Vector&lt;UnlinkedWasmToWasmCall&gt;&amp; unlinkedWasmToWasmCalls, const ImmutableFunctionIndexSpace&amp; functionIndexSpace)
</del><ins>+B3IRGenerator::B3IRGenerator(VM&amp; vm, const ModuleInformation&amp; info, Procedure&amp; procedure, WasmInternalFunction* compilation, Vector&lt;UnlinkedWasmToWasmCall&gt;&amp; unlinkedWasmToWasmCalls, const ImmutableFunctionIndexSpace&amp; functionIndexSpace)
</ins><span class="cx">     : m_vm(vm)
</span><span class="cx">     , m_functionIndexSpace(functionIndexSpace)
</span><ins>+    , m_info(info)
</ins><span class="cx">     , m_proc(procedure)
</span><span class="cx">     , m_unlinkedWasmToWasmCalls(unlinkedWasmToWasmCalls)
</span><span class="cx"> {
</span><span class="lines">@@ -222,13 +229,13 @@
</span><span class="cx">         }
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    if (!!memory) {
-        m_memoryBaseGPR = memory.pinnedRegisters().baseMemoryPointer;
</del><ins>+    if (!!info.memory) {
+        m_memoryBaseGPR = info.memory.pinnedRegisters().baseMemoryPointer;
</ins><span class="cx">         m_proc.pinRegister(m_memoryBaseGPR);
</span><del>-        ASSERT(!memory.pinnedRegisters().sizeRegisters[0].sizeOffset);
-        m_memorySizeGPR = memory.pinnedRegisters().sizeRegisters[0].sizeRegister;
-        for (const PinnedSizeRegisterInfo&amp; info : memory.pinnedRegisters().sizeRegisters)
-            m_proc.pinRegister(info.sizeRegister);
</del><ins>+        ASSERT(!info.memory.pinnedRegisters().sizeRegisters[0].sizeOffset);
+        m_memorySizeGPR = info.memory.pinnedRegisters().sizeRegisters[0].sizeRegister;
+        for (const PinnedSizeRegisterInfo&amp; regInfo : info.memory.pinnedRegisters().sizeRegisters)
+            m_proc.pinRegister(regInfo.sizeRegister);
</ins><span class="cx"> 
</span><span class="cx">         m_proc.setWasmBoundsCheckGenerator([=] (CCallHelpers&amp; jit, GPRReg pinnedGPR, unsigned) {
</span><span class="cx">             AllowMacroScratchRegisterUsage allowScratch(jit);
</span><span class="lines">@@ -271,7 +278,8 @@
</span><span class="cx"> 
</span><span class="cx">     wasmCallingConvention().setupFrameInPrologue(&amp;compilation-&gt;wasmCalleeMoveLocation, m_proc, Origin(), m_currentBlock);
</span><span class="cx"> 
</span><del>-    m_functionIndexSpaceValue = m_currentBlock-&gt;appendNew&lt;ConstPtrValue&gt;(m_proc, Origin(), functionIndexSpace.buffer.get());
</del><ins>+    m_instanceValue = m_currentBlock-&gt;appendNew&lt;MemoryValue&gt;(m_proc, Load, pointerType(), Origin(),
+        m_currentBlock-&gt;appendNew&lt;ConstPtrValue&gt;(m_proc, Origin(), &amp;m_vm.topJSWebAssemblyInstance));
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> Value* B3IRGenerator::zeroForType(Type type)
</span><span class="lines">@@ -325,6 +333,21 @@
</span><span class="cx">     return true;
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+bool B3IRGenerator::getGlobal(uint32_t index, ExpressionType&amp; result)
+{
+    Value* globalsArray = m_currentBlock-&gt;appendNew&lt;MemoryValue&gt;(m_proc, Load, pointerType(), Origin(), m_instanceValue, JSWebAssemblyInstance::offsetOfGlobals());
+    result = m_currentBlock-&gt;appendNew&lt;MemoryValue&gt;(m_proc, Load, toB3Type(m_info.globals[index].type), Origin(), globalsArray, index * sizeof(Register));
+    return true;
+}
+
+bool B3IRGenerator::setGlobal(uint32_t index, ExpressionType value)
+{
+    ASSERT(toB3Type(m_info.globals[index].type) == value-&gt;type());
+    Value* globalsArray = m_currentBlock-&gt;appendNew&lt;MemoryValue&gt;(m_proc, Load, pointerType(), Origin(), m_instanceValue, JSWebAssemblyInstance::offsetOfGlobals());
+    m_currentBlock-&gt;appendNew&lt;MemoryValue&gt;(m_proc, Store, Origin(), value, globalsArray, index * sizeof(Register));
+    return true;
+}
+
</ins><span class="cx"> inline Value* B3IRGenerator::emitCheckAndPreparePointer(ExpressionType pointer, uint32_t offset, uint32_t sizeOfOperation)
</span><span class="cx"> {
</span><span class="cx">     ASSERT(m_memoryBaseGPR &amp;&amp; m_memorySizeGPR);
</span><span class="lines">@@ -674,10 +697,8 @@
</span><span class="cx">     ExpressionType callableFunctionBuffer;
</span><span class="cx">     ExpressionType callableFunctionBufferSize;
</span><span class="cx">     {
</span><del>-        ExpressionType topInstance = m_currentBlock-&gt;appendNew&lt;MemoryValue&gt;(m_proc, Load, pointerType(), Origin(),
-            m_currentBlock-&gt;appendNew&lt;ConstPtrValue&gt;(m_proc, Origin(), &amp;m_vm.topJSWebAssemblyInstance));
</del><span class="cx">         ExpressionType table = m_currentBlock-&gt;appendNew&lt;MemoryValue&gt;(m_proc, Load, pointerType(), Origin(),
</span><del>-            topInstance, JSWebAssemblyInstance::offsetOfTable());
</del><ins>+            m_instanceValue, JSWebAssemblyInstance::offsetOfTable());
</ins><span class="cx">         callableFunctionBuffer = m_currentBlock-&gt;appendNew&lt;MemoryValue&gt;(m_proc, Load, pointerType(), Origin(),
</span><span class="cx">             table, JSWebAssemblyTable::offsetOfFunctions());
</span><span class="cx">         callableFunctionBufferSize = m_currentBlock-&gt;appendNew&lt;MemoryValue&gt;(m_proc, Load, Int32, Origin(),
</span><span class="lines">@@ -872,7 +893,7 @@
</span><span class="cx">     auto result = std::make_unique&lt;WasmInternalFunction&gt;();
</span><span class="cx"> 
</span><span class="cx">     Procedure procedure;
</span><del>-    B3IRGenerator context(vm, info.memory, procedure, result.get(), unlinkedWasmToWasmCalls, functionIndexSpace);
</del><ins>+    B3IRGenerator context(vm, info, procedure, result.get(), unlinkedWasmToWasmCalls, functionIndexSpace);
</ins><span class="cx">     FunctionParser&lt;B3IRGenerator&gt; parser(context, functionStart, functionLength, signature, functionIndexSpace, info);
</span><span class="cx">     if (!parser.parse())
</span><span class="cx">         RELEASE_ASSERT_NOT_REACHED();
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorewasmWasmFormath"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/wasm/WasmFormat.h (209829 => 209830)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/wasm/WasmFormat.h        2016-12-14 21:18:02 UTC (rev 209829)
+++ trunk/Source/JavaScriptCore/wasm/WasmFormat.h        2016-12-14 21:29:14 UTC (rev 209830)
</span><span class="lines">@@ -93,7 +93,7 @@
</span><span class="cx">     Type returnType;
</span><span class="cx">     Vector&lt;Type&gt; arguments;
</span><span class="cx"> };
</span><del>-    
</del><ins>+
</ins><span class="cx"> struct Import {
</span><span class="cx">     Identifier module;
</span><span class="cx">     Identifier field;
</span><span class="lines">@@ -104,12 +104,26 @@
</span><span class="cx"> struct Export {
</span><span class="cx">     Identifier field;
</span><span class="cx">     External::Kind kind;
</span><del>-    union {
-        uint32_t functionIndex;
-        // FIXME implement Table https://bugs.webkit.org/show_bug.cgi?id=165782
-        // FIXME implement Memory https://bugs.webkit.org/show_bug.cgi?id=165671
-        // FIXME implement Global https://bugs.webkit.org/show_bug.cgi?id=164133
</del><ins>+    unsigned kindIndex; // Index in the vector of the corresponding kind.
+};
+
+struct Global {
+    enum Mutability : uint8_t {
+        // FIXME auto-generate this. https://bugs.webkit.org/show_bug.cgi?id=165231
+        Mutable = 1,
+        Immutable = 0
</ins><span class="cx">     };
</span><ins>+
+    enum InitializationType {
+        IsImport,
+        FromGlobalImport,
+        FromExpression
+    };
+
+    Mutability mutability;
+    Type type;
+    InitializationType initializationType { IsImport };
+    uint64_t initialBitsOrImportNumber { 0 };
</ins><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> struct FunctionLocationInBinary {
</span><span class="lines">@@ -184,7 +198,6 @@
</span><span class="cx">     Vector&lt;Signature&gt; signatures;
</span><span class="cx">     Vector&lt;Import&gt; imports;
</span><span class="cx">     Vector&lt;Signature*&gt; importFunctions;
</span><del>-    // FIXME implement import Global https://bugs.webkit.org/show_bug.cgi?id=164133
</del><span class="cx">     Vector&lt;Signature*&gt; internalFunctionSignatures;
</span><span class="cx">     MemoryInformation memory;
</span><span class="cx">     Vector&lt;Export&gt; exports;
</span><span class="lines">@@ -192,6 +205,8 @@
</span><span class="cx">     Vector&lt;Segment::Ptr&gt; data;
</span><span class="cx">     Vector&lt;Element&gt; elements;
</span><span class="cx">     TableInformation tableInformation;
</span><ins>+    Vector&lt;Global&gt; globals;
+    unsigned firstInternalGlobal { 0 };
</ins><span class="cx"> 
</span><span class="cx">     ~ModuleInformation();
</span><span class="cx"> };
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorewasmWasmFunctionParserh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/wasm/WasmFunctionParser.h (209829 => 209830)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/wasm/WasmFunctionParser.h        2016-12-14 21:18:02 UTC (rev 209829)
+++ trunk/Source/JavaScriptCore/wasm/WasmFunctionParser.h        2016-12-14 21:29:14 UTC (rev 209830)
</span><span class="lines">@@ -351,6 +351,28 @@
</span><span class="cx">         return m_context.setLocal(index, m_expressionStack.last());
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    case OpType::GetGlobal: {
+        uint32_t index;
+        if (!parseVarUInt32(index))
+            return false;
+        ExpressionType result;
+        if (!m_context.getGlobal(index, result))
+            return false;
+
+        m_expressionStack.append(result);
+        return true;
+    }
+
+    case OpType::SetGlobal: {
+        uint32_t index;
+        if (!parseVarUInt32(index))
+            return false;
+        ExpressionType value;
+        if (!popExpressionStack(value))
+            return false;
+        return m_context.setGlobal(index, value);
+    }
+
</ins><span class="cx">     case OpType::Call: {
</span><span class="cx">         uint32_t functionIndex;
</span><span class="cx">         if (!parseVarUInt32(functionIndex))
</span><span class="lines">@@ -563,12 +585,9 @@
</span><span class="cx"> 
</span><span class="cx">     case OpType::GrowMemory:
</span><span class="cx">     case OpType::CurrentMemory:
</span><del>-    case OpType::GetGlobal:
-    case OpType::SetGlobal: {
</del><span class="cx">         // FIXME: Not yet implemented.
</span><span class="cx">         return false;
</span><span class="cx">     }
</span><del>-    }
</del><span class="cx"> 
</span><span class="cx">     ASSERT_NOT_REACHED();
</span><span class="cx"> }
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorewasmWasmModuleParsercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/wasm/WasmModuleParser.cpp (209829 => 209830)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/wasm/WasmModuleParser.cpp        2016-12-14 21:18:02 UTC (rev 209829)
+++ trunk/Source/JavaScriptCore/wasm/WasmModuleParser.cpp        2016-12-14 21:29:14 UTC (rev 209830)
</span><span class="lines">@@ -217,6 +217,7 @@
</span><span class="cx">     uint32_t importCount;
</span><span class="cx">     if (!parseVarUInt32(importCount)
</span><span class="cx">         || importCount == std::numeric_limits&lt;uint32_t&gt;::max()
</span><ins>+        || !m_module-&gt;globals.tryReserveCapacity(importCount) // FIXME this over-allocates when we fix the FIXMEs below.
</ins><span class="cx">         || !m_module-&gt;imports.tryReserveCapacity(importCount) // FIXME this over-allocates when we fix the FIXMEs below.
</span><span class="cx">         || !m_module-&gt;importFunctions.tryReserveCapacity(importCount) // FIXME this over-allocates when we fix the FIXMEs below.
</span><span class="cx">         || !m_functionIndexSpace.tryReserveCapacity(importCount)) // FIXME this over-allocates when we fix the FIXMEs below. We'll allocate some more here when we know how many functions to expect.
</span><span class="lines">@@ -263,8 +264,15 @@
</span><span class="cx">             break;
</span><span class="cx">         }
</span><span class="cx">         case External::Global: {
</span><del>-            // FIXME https://bugs.webkit.org/show_bug.cgi?id=164133
-            // In the MVP, only immutable global variables can be imported.
</del><ins>+            Global global;
+            if (!parseGlobalType(global))
+                return false;
+
+            if (global.mutability == Global::Mutable)
+                return false;
+
+            imp.kindIndex = m_module-&gt;globals.size();
+            m_module-&gt;globals.uncheckedAppend(WTFMove(global));
</ins><span class="cx">             break;
</span><span class="cx">         }
</span><span class="cx">         }
</span><span class="lines">@@ -272,6 +280,7 @@
</span><span class="cx">         m_module-&gt;imports.uncheckedAppend(imp);
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    m_module-&gt;firstInternalGlobal = m_module-&gt;globals.size();
</ins><span class="cx">     return true;
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -423,8 +432,52 @@
</span><span class="cx"> 
</span><span class="cx"> bool ModuleParser::parseGlobal()
</span><span class="cx"> {
</span><del>-    // FIXME https://bugs.webkit.org/show_bug.cgi?id=164133
-    RELEASE_ASSERT_NOT_REACHED();
</del><ins>+    uint32_t globalCount;
+    if (!parseVarUInt32(globalCount))
+        return false;
+    if (!m_module-&gt;globals.tryReserveCapacity(globalCount + m_module-&gt;firstInternalGlobal))
+        return false;
+
+    for (uint32_t globalIndex = 0; globalIndex &lt; globalCount; ++globalIndex) {
+        Global global;
+        if (!parseGlobalType(global))
+            return false;
+
+        uint8_t initOpcode;
+        if (!parseInitExpr(initOpcode, global.initialBitsOrImportNumber))
+            return false;
+
+        global.initializationType = Global::FromExpression;
+        Type typeForInitOpcode;
+        switch (initOpcode) {
+        case I32Const:
+            typeForInitOpcode = I32;
+            break;
+        case I64Const:
+            typeForInitOpcode = I64;
+            break;
+        case F32Const:
+            typeForInitOpcode = F32;
+            break;
+        case F64Const:
+            typeForInitOpcode = F64;
+            break;
+        case GetGlobal:
+            if (global.initialBitsOrImportNumber &gt;= m_module-&gt;firstInternalGlobal)
+                return false;
+            typeForInitOpcode = m_module-&gt;globals[global.initialBitsOrImportNumber].type;
+            global.initializationType = Global::FromGlobalImport;
+            break;
+        default:
+            RELEASE_ASSERT_NOT_REACHED();
+        }
+
+        if (typeForInitOpcode != global.type)
+            return false;
+
+        m_module-&gt;globals.uncheckedAppend(WTFMove(global));
+    }
+
</ins><span class="cx">     return true;
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -448,10 +501,12 @@
</span><span class="cx">         if (!parseExternalKind(exp.kind))
</span><span class="cx">             return false;
</span><span class="cx"> 
</span><ins>+        if (!parseVarUInt32(exp.kindIndex))
+            return false;
+
</ins><span class="cx">         switch (exp.kind) {
</span><span class="cx">         case External::Function: {
</span><del>-            if (!parseVarUInt32(exp.functionIndex)
-                || exp.functionIndex &gt;= m_functionIndexSpace.size())
</del><ins>+            if (exp.kindIndex &gt;= m_functionIndexSpace.size())
</ins><span class="cx">                 return false;
</span><span class="cx">             break;
</span><span class="cx">         }
</span><span class="lines">@@ -464,8 +519,11 @@
</span><span class="cx">             break;
</span><span class="cx">         }
</span><span class="cx">         case External::Global: {
</span><del>-            // FIXME https://bugs.webkit.org/show_bug.cgi?id=164133
-            // In the MVP, only immutable global variables can be exported.
</del><ins>+            if (exp.kindIndex &gt;= m_module-&gt;globals.size())
+                return false;
+
+            if (m_module-&gt;globals[exp.kindIndex].mutability != Global::Immutable)
+                return false;
</ins><span class="cx">             break;
</span><span class="cx">         }
</span><span class="cx">         }
</span><span class="lines">@@ -509,10 +567,14 @@
</span><span class="cx">         if (tableIndex != 0)
</span><span class="cx">             return false;
</span><span class="cx"> 
</span><del>-        uint32_t offset;
-        if (!parseInitExpr(offset))
</del><ins>+        uint64_t offset;
+        uint8_t initOpcode;
+        if (!parseInitExpr(initOpcode, offset))
</ins><span class="cx">             return false;
</span><span class="cx"> 
</span><ins>+        if (initOpcode != OpType::I32Const)
+            return false;
+
</ins><span class="cx">         uint32_t indexCount;
</span><span class="cx">         if (!parseVarUInt32(indexCount))
</span><span class="cx">             return false;
</span><span class="lines">@@ -577,22 +639,82 @@
</span><span class="cx">     return true;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-bool ModuleParser::parseInitExpr(uint32_t&amp; value)
</del><ins>+bool ModuleParser::parseInitExpr(uint8_t&amp; opcode, uint64_t&amp; bitsOrImportNumber)
</ins><span class="cx"> {
</span><del>-    // FIXME allow complex init_expr here. https://bugs.webkit.org/show_bug.cgi?id=165700
-    // For now we only handle i32.const as offset.
</del><ins>+    if (!parseUInt8(opcode))
+        return false;
</ins><span class="cx"> 
</span><del>-    uint8_t opcode;
</del><ins>+    switch (opcode) {
+    case I32Const: {
+        int32_t constant;
+        if (!parseVarInt32(constant))
+            return false;
+        bitsOrImportNumber = static_cast&lt;uint64_t&gt;(constant);
+        break;
+    }
+
+    case I64Const: {
+        int64_t constant;
+        if (!parseVarInt64(constant))
+            return false;
+        bitsOrImportNumber = constant;
+        break;
+    }
+
+    case F32Const: {
+        uint32_t constant;
+        if (!parseUInt32(constant))
+            return false;
+        bitsOrImportNumber = constant;
+        break;
+    }
+
+    case F64Const: {
+        uint64_t constant;
+        if (!parseUInt64(constant))
+            return false;
+        bitsOrImportNumber = constant;
+        break;
+    }
+
+    case GetGlobal: {
+        uint32_t index;
+        if (!parseVarUInt32(index))
+            return false;
+
+        if (index &gt;= m_module-&gt;imports.size())
+            return false;
+        const Import&amp; import = m_module-&gt;imports[index];
+        if (m_module-&gt;imports[index].kind != External::Global
+            || import.kindIndex &gt;= m_module-&gt;firstInternalGlobal)
+            return false;
+
+        ASSERT(m_module-&gt;globals[import.kindIndex].mutability == Global::Immutable);
+
+        bitsOrImportNumber = index;
+        break;
+    }
+
+    default:
+        return false;
+    }
+
</ins><span class="cx">     uint8_t endOpcode;
</span><del>-    if (!parseUInt8(opcode)
-        || opcode != Wasm::I32Const
-        || !parseVarUInt32(value)
-        || !parseUInt8(endOpcode)
-        || endOpcode != Wasm::End)
</del><ins>+    if (!parseUInt8(endOpcode) || endOpcode != OpType::End)
</ins><span class="cx">         return false;
</span><ins>+
</ins><span class="cx">     return true;
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+bool ModuleParser::parseGlobalType(Global&amp; global)
+{
+    uint8_t mutability;
+    if (!parseValueType(global.type) || !parseVarUInt1(mutability))
+        return false;
+    global.mutability = static_cast&lt;Global::Mutability&gt;(mutability);
+    return true;
+}
+
</ins><span class="cx"> bool ModuleParser::parseData()
</span><span class="cx"> {
</span><span class="cx">     uint32_t segmentCount;
</span><span class="lines">@@ -607,14 +729,19 @@
</span><span class="cx">         if (verbose)
</span><span class="cx">             dataLogLn(&quot;  segment #&quot;, segmentNumber);
</span><span class="cx">         uint32_t index;
</span><del>-        uint32_t offset;
</del><ins>+        uint64_t offset;
+        uint8_t initOpcode;
</ins><span class="cx">         uint32_t dataByteLength;
</span><span class="cx">         if (!parseVarUInt32(index)
</span><span class="cx">             || index)
</span><span class="cx">             return false;
</span><span class="cx"> 
</span><del>-        if (!parseInitExpr(offset))
</del><ins>+        if (!parseInitExpr(initOpcode, offset))
</ins><span class="cx">             return false;
</span><ins>+
+        if (initOpcode != OpType::I32Const)
+            return false;
+
</ins><span class="cx">         if (verbose)
</span><span class="cx">             dataLogLn(&quot;    offset: &quot;, offset);
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorewasmWasmModuleParserh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/wasm/WasmModuleParser.h (209829 => 209830)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/wasm/WasmModuleParser.h        2016-12-14 21:18:02 UTC (rev 209829)
+++ trunk/Source/JavaScriptCore/wasm/WasmModuleParser.h        2016-12-14 21:29:14 UTC (rev 209830)
</span><span class="lines">@@ -74,6 +74,8 @@
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx"> private:
</span><ins>+    bool parseGlobalType(Global&amp;);
+
</ins><span class="cx"> #define WASM_SECTION_DECLARE_PARSER(NAME, ID, DESCRIPTION) bool WARN_UNUSED_RETURN parse ## NAME();
</span><span class="cx">     FOR_EACH_WASM_SECTION(WASM_SECTION_DECLARE_PARSER)
</span><span class="cx"> #undef WASM_SECTION_DECLARE_PARSER
</span><span class="lines">@@ -81,7 +83,7 @@
</span><span class="cx">     bool WARN_UNUSED_RETURN parseMemoryHelper(bool isImport);
</span><span class="cx">     bool WARN_UNUSED_RETURN parseTableHelper(bool isImport);
</span><span class="cx">     bool WARN_UNUSED_RETURN parseResizableLimits(uint32_t&amp; initial, std::optional&lt;uint32_t&gt;&amp; maximum);
</span><del>-    bool WARN_UNUSED_RETURN parseInitExpr(uint32_t&amp;);
</del><ins>+    bool WARN_UNUSED_RETURN parseInitExpr(uint8_t&amp;, uint64_t&amp;);
</ins><span class="cx"> 
</span><span class="cx">     VM* m_vm;
</span><span class="cx">     std::unique_ptr&lt;ModuleInformation&gt; m_module;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorewasmWasmParserh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/wasm/WasmParser.h (209829 => 209830)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/wasm/WasmParser.h        2016-12-14 21:18:02 UTC (rev 209829)
+++ trunk/Source/JavaScriptCore/wasm/WasmParser.h        2016-12-14 21:29:14 UTC (rev 209830)
</span><span class="lines">@@ -51,9 +51,13 @@
</span><span class="cx">     bool WARN_UNUSED_RETURN parseUInt7(uint8_t&amp;);
</span><span class="cx">     bool WARN_UNUSED_RETURN parseUInt8(uint8_t&amp;);
</span><span class="cx">     bool WARN_UNUSED_RETURN parseUInt32(uint32_t&amp;);
</span><ins>+    bool WARN_UNUSED_RETURN parseUInt64(uint64_t&amp;);
</ins><span class="cx">     bool WARN_UNUSED_RETURN parseVarUInt32(uint32_t&amp;);
</span><span class="cx">     bool WARN_UNUSED_RETURN parseVarUInt64(uint64_t&amp;);
</span><span class="cx"> 
</span><ins>+    bool WARN_UNUSED_RETURN parseVarInt32(int32_t&amp;);
+    bool WARN_UNUSED_RETURN parseVarInt64(int64_t&amp;);
+
</ins><span class="cx">     bool WARN_UNUSED_RETURN parseResultType(Type&amp;);
</span><span class="cx">     bool WARN_UNUSED_RETURN parseValueType(Type&amp;);
</span><span class="cx">     bool WARN_UNUSED_RETURN parseExternalKind(External::Kind&amp;);
</span><span class="lines">@@ -124,6 +128,16 @@
</span><span class="cx">     return WTF::LEBDecoder::decodeUInt64(m_source, m_sourceLength, m_offset, result);
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+ALWAYS_INLINE bool Parser::parseVarInt32(int32_t&amp; result)
+{
+    return WTF::LEBDecoder::decodeInt32(m_source, m_sourceLength, m_offset, result);
+}
+
+ALWAYS_INLINE bool Parser::parseVarInt64(int64_t&amp; result)
+{
+    return WTF::LEBDecoder::decodeInt64(m_source, m_sourceLength, m_offset, result);
+}
+
</ins><span class="cx"> ALWAYS_INLINE bool Parser::parseUInt32(uint32_t&amp; result)
</span><span class="cx"> {
</span><span class="cx">     if (length() &lt; 4 || m_offset &gt; length() - 4)
</span><span class="lines">@@ -133,6 +147,15 @@
</span><span class="cx">     return true;
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+ALWAYS_INLINE bool Parser::parseUInt64(uint64_t&amp; result)
+{
+    if (length() &lt; 8 || m_offset &gt; length() - 8)
+        return false;
+    result = *reinterpret_cast&lt;const uint64_t*&gt;(source() + m_offset);
+    m_offset += 8;
+    return true;
+}
+
</ins><span class="cx"> ALWAYS_INLINE bool Parser::parseUInt8(uint8_t&amp; result)
</span><span class="cx"> {
</span><span class="cx">     if (m_offset &gt;= length())
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorewasmWasmValidatecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/wasm/WasmValidate.cpp (209829 => 209830)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/wasm/WasmValidate.cpp        2016-12-14 21:18:02 UTC (rev 209829)
+++ trunk/Source/JavaScriptCore/wasm/WasmValidate.cpp        2016-12-14 21:29:14 UTC (rev 209830)
</span><span class="lines">@@ -86,6 +86,10 @@
</span><span class="cx">     bool WARN_UNUSED_RETURN getLocal(uint32_t index, ExpressionType&amp; result);
</span><span class="cx">     bool WARN_UNUSED_RETURN setLocal(uint32_t index, ExpressionType value);
</span><span class="cx"> 
</span><ins>+    // Globals
+    bool WARN_UNUSED_RETURN getGlobal(uint32_t index, ExpressionType&amp; result);
+    bool WARN_UNUSED_RETURN setGlobal(uint32_t index, ExpressionType value);
+
</ins><span class="cx">     // Memory
</span><span class="cx">     bool WARN_UNUSED_RETURN load(LoadOpType, ExpressionType pointer, ExpressionType&amp; result, uint32_t offset);
</span><span class="cx">     bool WARN_UNUSED_RETURN store(StoreOpType, ExpressionType pointer, ExpressionType value, uint32_t offset);
</span><span class="lines">@@ -116,13 +120,13 @@
</span><span class="cx"> 
</span><span class="cx">     void dump(const Vector&lt;ControlEntry&gt;&amp; controlStack, const ExpressionList&amp; expressionStack);
</span><span class="cx"> 
</span><del>-    bool hasMemory() const { return !!m_memory; }
</del><ins>+    bool hasMemory() const { return !!m_module.memory; }
</ins><span class="cx"> 
</span><span class="cx">     void setErrorMessage(String&amp;&amp; message) { ASSERT(m_errorMessage.isNull()); m_errorMessage = WTFMove(message); }
</span><span class="cx">     String errorMessage() const { return m_errorMessage; }
</span><del>-    Validate(ExpressionType returnType, const MemoryInformation&amp; memory)
</del><ins>+    Validate(ExpressionType returnType, const ModuleInformation&amp; module)
</ins><span class="cx">         : m_returnType(returnType)
</span><del>-        , m_memory(memory)
</del><ins>+        , m_module(module)
</ins><span class="cx">     {
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="lines">@@ -135,7 +139,7 @@
</span><span class="cx">     ExpressionType m_returnType;
</span><span class="cx">     Vector&lt;Type&gt; m_locals;
</span><span class="cx">     String m_errorMessage;
</span><del>-    const MemoryInformation&amp; m_memory;
</del><ins>+    const ModuleInformation&amp; m_module;
</ins><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> bool Validate::addArguments(const Vector&lt;Type&gt;&amp; args)
</span><span class="lines">@@ -180,6 +184,38 @@
</span><span class="cx">     return false;
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+bool Validate::getGlobal(uint32_t index, ExpressionType&amp; result)
+{
+    if (index &lt; m_module.globals.size()) {
+        result = m_module.globals[index].type;
+        ASSERT(isValueType(result));
+        return true;
+    }
+    m_errorMessage = ASCIILiteral(&quot;Attempt to use unknown global.&quot;);
+    return false;
+}
+
+bool Validate::setGlobal(uint32_t index, ExpressionType value)
+{
+    if (index &gt;= m_module.globals.size()) {
+        m_errorMessage = ASCIILiteral(&quot;Attempt to use unknown global.&quot;);
+        return false;
+    }
+
+    if (m_module.globals[index].mutability == Global::Immutable) {
+        m_errorMessage = ASCIILiteral(&quot;Attempt to store to immutable global.&quot;);
+        return false;
+    }
+
+    ExpressionType globalType = m_module.globals[index].type;
+    ASSERT(isValueType(globalType));
+    if (globalType == value)
+        return true;
+
+    m_errorMessage = makeString(&quot;Attempt to set global with type: &quot;, toString(globalType), &quot; with a variable of type: &quot;, toString(value));
+    return false;
+}
+
</ins><span class="cx"> Validate::ControlType Validate::addBlock(Type signature)
</span><span class="cx"> {
</span><span class="cx">     return ControlData(BlockType::Block, signature);
</span><span class="lines">@@ -401,10 +437,10 @@
</span><span class="cx">     // Think of this as penance for the sin of bad error messages.
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-String validateFunction(const uint8_t* source, size_t length, const Signature* signature, const ImmutableFunctionIndexSpace&amp; functionIndexSpace, const ModuleInformation&amp; info)
</del><ins>+String validateFunction(const uint8_t* source, size_t length, const Signature* signature, const ImmutableFunctionIndexSpace&amp; functionIndexSpace, const ModuleInformation&amp; module)
</ins><span class="cx"> {
</span><del>-    Validate context(signature-&gt;returnType, info.memory);
-    FunctionParser&lt;Validate&gt; validator(context, source, length, signature, functionIndexSpace, info);
</del><ins>+    Validate context(signature-&gt;returnType, module);
+    FunctionParser&lt;Validate&gt; validator(context, source, length, signature, functionIndexSpace, module);
</ins><span class="cx"> 
</span><span class="cx">     if (!validator.parse()) {
</span><span class="cx">         // FIXME: add better location information here. see: https://bugs.webkit.org/show_bug.cgi?id=164288
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorewasmgenerateWasmOpsHeaderpy"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/wasm/generateWasmOpsHeader.py (209829 => 209830)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/wasm/generateWasmOpsHeader.py        2016-12-14 21:18:02 UTC (rev 209829)
+++ trunk/Source/JavaScriptCore/wasm/generateWasmOpsHeader.py        2016-12-14 21:29:14 UTC (rev 209830)
</span><span class="lines">@@ -150,7 +150,7 @@
</span><span class="cx"> }
</span><span class="cx"> #undef CREATE_CASE
</span><span class="cx"> 
</span><del>-#define CREATE_CASE(name, id, b3type, inc) case name: return &quot;name&quot;;
</del><ins>+#define CREATE_CASE(name, id, b3type, inc) case name: return #name;
</ins><span class="cx"> inline const char* toString(Type type)
</span><span class="cx"> {
</span><span class="cx">     switch (type) {
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorewasmjsJSWebAssemblyInstancecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/wasm/js/JSWebAssemblyInstance.cpp (209829 => 209830)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/wasm/js/JSWebAssemblyInstance.cpp        2016-12-14 21:18:02 UTC (rev 209829)
+++ trunk/Source/JavaScriptCore/wasm/js/JSWebAssemblyInstance.cpp        2016-12-14 21:29:14 UTC (rev 209830)
</span><span class="lines">@@ -38,9 +38,10 @@
</span><span class="cx"> 
</span><span class="cx"> namespace JSC {
</span><span class="cx"> 
</span><del>-JSWebAssemblyInstance* JSWebAssemblyInstance::create(VM&amp; vm, Structure* structure, JSWebAssemblyModule* module, JSModuleNamespaceObject* moduleNamespaceObject, unsigned numImportFunctions)
</del><ins>+JSWebAssemblyInstance* JSWebAssemblyInstance::create(VM&amp; vm, Structure* structure, JSWebAssemblyModule* module, JSModuleNamespaceObject* moduleNamespaceObject)
</ins><span class="cx"> {
</span><del>-    auto* instance = new (NotNull, allocateCell&lt;JSWebAssemblyInstance&gt;(vm.heap, allocationSize(numImportFunctions))) JSWebAssemblyInstance(vm, structure, numImportFunctions);
</del><ins>+    // FIXME: These objects could be pretty big we should try to throw OOM here.
+    auto* instance = new (NotNull, allocateCell&lt;JSWebAssemblyInstance&gt;(vm.heap, allocationSize(module-&gt;moduleInformation().importFunctions.size()))) JSWebAssemblyInstance(vm, structure, module-&gt;moduleInformation().importFunctions.size());
</ins><span class="cx">     instance-&gt;finishCreation(vm, module, moduleNamespaceObject);
</span><span class="cx">     return instance;
</span><span class="cx"> }
</span><span class="lines">@@ -61,6 +62,11 @@
</span><span class="cx"> {
</span><span class="cx">     Base::finishCreation(vm);
</span><span class="cx">     ASSERT(inherits(info()));
</span><ins>+
+    const size_t extraMemorySize = module-&gt;moduleInformation().globals.size() * sizeof(Register);
+    m_globals = MallocPtr&lt;uint64_t&gt;::malloc(extraMemorySize);
+    heap()-&gt;reportExtraMemoryAllocated(extraMemorySize);
+
</ins><span class="cx">     m_module.set(vm, this, module);
</span><span class="cx">     m_moduleNamespaceObject.set(vm, this, moduleNamespaceObject);
</span><span class="cx">     putDirect(vm, Identifier::fromString(&amp;vm, &quot;exports&quot;), moduleNamespaceObject, None);
</span><span class="lines">@@ -81,6 +87,7 @@
</span><span class="cx">     visitor.append(&amp;thisObject-&gt;m_moduleNamespaceObject);
</span><span class="cx">     visitor.append(&amp;thisObject-&gt;m_memory);
</span><span class="cx">     visitor.append(&amp;thisObject-&gt;m_table);
</span><ins>+    visitor.reportExtraMemoryVisited(thisObject-&gt;module()-&gt;moduleInformation().globals.size());
</ins><span class="cx">     for (unsigned i = 0; i &lt; thisObject-&gt;m_numImportFunctions; ++i)
</span><span class="cx">         visitor.append(thisObject-&gt;importFunction(i));
</span><span class="cx"> }
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorewasmjsJSWebAssemblyInstanceh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/wasm/js/JSWebAssemblyInstance.h (209829 => 209830)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/wasm/js/JSWebAssemblyInstance.h        2016-12-14 21:18:02 UTC (rev 209829)
+++ trunk/Source/JavaScriptCore/wasm/js/JSWebAssemblyInstance.h        2016-12-14 21:29:14 UTC (rev 209830)
</span><span class="lines">@@ -42,7 +42,7 @@
</span><span class="cx">     typedef JSDestructibleObject Base;
</span><span class="cx"> 
</span><span class="cx"> 
</span><del>-    static JSWebAssemblyInstance* create(VM&amp;, Structure*, JSWebAssemblyModule*, JSModuleNamespaceObject*, unsigned);
</del><ins>+    static JSWebAssemblyInstance* create(VM&amp;, Structure*, JSWebAssemblyModule*, JSModuleNamespaceObject*);
</ins><span class="cx">     static Structure* createStructure(VM&amp;, JSGlobalObject*, JSValue);
</span><span class="cx"> 
</span><span class="cx">     DECLARE_INFO;
</span><span class="lines">@@ -75,6 +75,12 @@
</span><span class="cx">     JSWebAssemblyTable* table() { return m_table.get(); }
</span><span class="cx">     void setTable(VM&amp; vm, JSWebAssemblyTable* table) { m_table.set(vm, this, table); }
</span><span class="cx"> 
</span><ins>+    int32_t loadI32Global(unsigned i) const { return m_globals.get()[i]; }
+    int64_t loadI64Global(unsigned i) const { return m_globals.get()[i]; }
+    float loadF32Global(unsigned i) const { return bitwise_cast&lt;float&gt;(loadI32Global(i)); }
+    double loadF64Global(unsigned i) const { return bitwise_cast&lt;double&gt;(loadI64Global(i)); }
+    void setGlobal(unsigned i, int64_t bits) { m_globals.get()[i] = bits; }
+
</ins><span class="cx">     static size_t offsetOfImportFunction(unsigned idx)
</span><span class="cx">     {
</span><span class="cx">         return offsetOfImportFunctions() + sizeof(WriteBarrier&lt;JSCell&gt;) * idx;
</span><span class="lines">@@ -81,9 +87,10 @@
</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 offsetOfGlobals() { return OBJECT_OFFSETOF(JSWebAssemblyInstance, m_globals); }
</ins><span class="cx"> 
</span><span class="cx"> protected:
</span><del>-    JSWebAssemblyInstance(VM&amp;, Structure*, unsigned);
</del><ins>+    JSWebAssemblyInstance(VM&amp;, Structure*, unsigned numImportFunctions);
</ins><span class="cx">     void finishCreation(VM&amp;, JSWebAssemblyModule*, JSModuleNamespaceObject*);
</span><span class="cx">     static void destroy(JSCell*);
</span><span class="cx">     static void visitChildren(JSCell*, SlotVisitor&amp;);
</span><span class="lines">@@ -103,6 +110,7 @@
</span><span class="cx">     WriteBarrier&lt;JSModuleNamespaceObject&gt; m_moduleNamespaceObject;
</span><span class="cx">     WriteBarrier&lt;JSWebAssemblyMemory&gt; m_memory;
</span><span class="cx">     WriteBarrier&lt;JSWebAssemblyTable&gt; m_table;
</span><ins>+    MallocPtr&lt;uint64_t&gt; m_globals;
</ins><span class="cx">     unsigned m_numImportFunctions;
</span><span class="cx"> };
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorewasmjsWebAssemblyInstanceConstructorcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/wasm/js/WebAssemblyInstanceConstructor.cpp (209829 => 209830)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/wasm/js/WebAssemblyInstanceConstructor.cpp        2016-12-14 21:18:02 UTC (rev 209829)
+++ trunk/Source/JavaScriptCore/wasm/js/WebAssemblyInstanceConstructor.cpp        2016-12-14 21:29:14 UTC (rev 209830)
</span><span class="lines">@@ -81,15 +81,14 @@
</span><span class="cx">     Structure* instanceStructure = InternalFunction::createSubclassStructure(exec, exec-&gt;newTarget(), globalObject-&gt;WebAssemblyInstanceStructure());
</span><span class="cx">     RETURN_IF_EXCEPTION(throwScope, { });
</span><span class="cx"> 
</span><del>-    JSWebAssemblyInstance* instance = JSWebAssemblyInstance::create(vm, instanceStructure, jsModule, moduleRecord-&gt;getModuleNamespace(exec), moduleInformation.imports.size());
</del><ins>+    JSWebAssemblyInstance* instance = JSWebAssemblyInstance::create(vm, instanceStructure, jsModule, moduleRecord-&gt;getModuleNamespace(exec));
</ins><span class="cx">     RETURN_IF_EXCEPTION(throwScope, { });
</span><span class="cx"> 
</span><span class="cx">     // Let funcs, memories and tables be initially-empty lists of callable JavaScript objects, WebAssembly.Memory objects and WebAssembly.Table objects, respectively.
</span><span class="cx">     // Let imports be an initially-empty list of external values.
</span><span class="cx">     unsigned numImportFunctions = 0;
</span><ins>+    unsigned numImportGlobals = 0;
</ins><span class="cx"> 
</span><del>-    // FIXME implement Global https://bugs.webkit.org/show_bug.cgi?id=164133
-
</del><span class="cx">     bool hasMemoryImport = false;
</span><span class="cx">     bool hasTableImport = false;
</span><span class="cx">     // For each import i in module.imports:
</span><span class="lines">@@ -195,11 +194,26 @@
</span><span class="cx">         }
</span><span class="cx">         case Wasm::External::Global: {
</span><span class="cx">             // 5. If i is a global import:
</span><del>-            // FIXME implement Global https://bugs.webkit.org/show_bug.cgi?id=164133
</del><span class="cx">             // i. If i is not an immutable global, throw a TypeError.
</span><ins>+            ASSERT(moduleInformation.globals[import.kindIndex].mutability == Wasm::Global::Immutable);
</ins><span class="cx">             // ii. If Type(v) is not Number, throw a TypeError.
</span><ins>+            if (!value.isNumber())
+                return JSValue::encode(throwException(exec, throwScope, createTypeError(exec, ASCIILiteral(&quot;imported global must be a number&quot;), defaultSourceAppender, runtimeTypeForValue(value))));
</ins><span class="cx">             // iii. Append ToWebAssemblyValue(v) to imports.
</span><del>-            RELEASE_ASSERT_NOT_REACHED();
</del><ins>+            switch (moduleInformation.globals[import.kindIndex].type) {
+            case Wasm::I32:
+                instance-&gt;setGlobal(numImportGlobals++, value.toInt32(exec));
+                break;
+            case Wasm::F32:
+                instance-&gt;setGlobal(numImportGlobals++, bitwise_cast&lt;uint32_t&gt;(value.toFloat(exec)));
+                break;
+            case Wasm::F64:
+                instance-&gt;setGlobal(numImportGlobals++, bitwise_cast&lt;uint64_t&gt;(value.asNumber()));
+                break;
+            default:
+                RELEASE_ASSERT_NOT_REACHED();
+            }
+            ASSERT(!throwScope.exception());
</ins><span class="cx">             break;
</span><span class="cx">         }
</span><span class="cx">         }
</span><span class="lines">@@ -241,8 +255,23 @@
</span><span class="cx">         }
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    // Globals
+    {
+        ASSERT(numImportGlobals == moduleInformation.firstInternalGlobal);
+        for (size_t globalIndex = numImportGlobals; globalIndex &lt; moduleInformation.globals.size(); ++globalIndex) {
+            const auto&amp; global = moduleInformation.globals[globalIndex];
+            ASSERT(global.initializationType != Wasm::Global::IsImport);
+            if (global.initializationType == Wasm::Global::FromGlobalImport) {
+                ASSERT(global.initialBitsOrImportNumber &lt; numImportGlobals);
+                instance-&gt;setGlobal(globalIndex, instance-&gt;loadI64Global(global.initialBitsOrImportNumber));
+            } else
+                instance-&gt;setGlobal(globalIndex, global.initialBitsOrImportNumber);
+        }
+    }
+
</ins><span class="cx">     moduleRecord-&gt;link(exec, instance);
</span><span class="cx">     RETURN_IF_EXCEPTION(throwScope, { });
</span><ins>+
</ins><span class="cx">     if (verbose)
</span><span class="cx">         moduleRecord-&gt;dump();
</span><span class="cx">     JSValue startResult = moduleRecord-&gt;evaluate(exec);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorewasmjsWebAssemblyModuleRecordcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/wasm/js/WebAssemblyModuleRecord.cpp (209829 => 209830)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/wasm/js/WebAssemblyModuleRecord.cpp        2016-12-14 21:18:02 UTC (rev 209829)
+++ trunk/Source/JavaScriptCore/wasm/js/WebAssemblyModuleRecord.cpp        2016-12-14 21:29:14 UTC (rev 209830)
</span><span class="lines">@@ -85,8 +85,8 @@
</span><span class="cx">             break;
</span><span class="cx">         }
</span><span class="cx">         case Wasm::External::Global: {
</span><del>-            // FIXME https://bugs.webkit.org/show_bug.cgi?id=164133
</del><span class="cx">             // In the MVP, only immutable global variables can be exported.
</span><ins>+            addExportEntry(ExportEntry::createLocal(exp.field, exp.field));
</ins><span class="cx">             break;
</span><span class="cx">         }
</span><span class="cx">         }
</span><span class="lines">@@ -128,7 +128,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.functionIndex &lt; importCount) {
</del><ins>+            if (exp.kindIndex &lt; importCount) {
</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">@@ -136,12 +136,12 @@
</span><span class="cx">             //     a. Let func be an Exported Function Exotic Object created from c.
</span><span class="cx">             //     b. Append func to funcs.
</span><span class="cx">             //     c. Return func.
</span><del>-            JSWebAssemblyCallee* jsEntrypointCallee = module-&gt;jsEntrypointCalleeFromFunctionIndexSpace(exp.functionIndex);
-            JSWebAssemblyCallee* wasmEntrypointCallee = module-&gt;wasmEntrypointCalleeFromFunctionIndexSpace(exp.functionIndex);
-            Wasm::Signature* signature = module-&gt;signatureForFunctionIndexSpace(exp.functionIndex);
</del><ins>+            JSWebAssemblyCallee* jsEntrypointCallee = module-&gt;jsEntrypointCalleeFromFunctionIndexSpace(exp.kindIndex);
+            JSWebAssemblyCallee* wasmEntrypointCallee = module-&gt;wasmEntrypointCalleeFromFunctionIndexSpace(exp.kindIndex);
+            Wasm::Signature* signature = module-&gt;signatureForFunctionIndexSpace(exp.kindIndex);
</ins><span class="cx">             WebAssemblyFunction* function = WebAssemblyFunction::create(vm, globalObject, signature-&gt;arguments.size(), exp.field.string(), instance, jsEntrypointCallee, wasmEntrypointCallee, signature);
</span><span class="cx">             exportedValue = function;
</span><del>-            if (hasStart &amp;&amp; startFunctionIndexSpace == exp.functionIndex)
</del><ins>+            if (hasStart &amp;&amp; startFunctionIndexSpace == exp.kindIndex)
</ins><span class="cx">                 m_startFunction.set(vm, this, function);
</span><span class="cx">             break;
</span><span class="cx">         }
</span><span class="lines">@@ -153,9 +153,28 @@
</span><span class="cx">             // FIXME: https://bugs.webkit.org/show_bug.cgi?id=165671
</span><span class="cx">             break;
</span><span class="cx">         }
</span><ins>+
</ins><span class="cx">         case Wasm::External::Global: {
</span><del>-            // FIXME https://bugs.webkit.org/show_bug.cgi?id=164133
-            // In the MVP, only immutable global variables can be exported.
</del><ins>+            // Assert: the global is immutable by MVP validation constraint.
+            const Wasm::Global&amp; global = moduleInformation.globals[exp.kindIndex];
+            ASSERT(global.mutability == Wasm::Global::Immutable);
+            // Return ToJSValue(v).
+            switch (global.type) {
+            case Wasm::I32:
+                exportedValue = JSValue(instance-&gt;loadI32Global(exp.kindIndex));
+                break;
+
+            case Wasm::F32:
+                exportedValue = JSValue(instance-&gt;loadF32Global(exp.kindIndex));
+                break;
+
+            case Wasm::F64:
+                exportedValue = JSValue(instance-&gt;loadF64Global(exp.kindIndex));
+                break;
+
+            default:
+                RELEASE_ASSERT_NOT_REACHED();
+            }
</ins><span class="cx">             break;
</span><span class="cx">         }
</span><span class="cx">         }
</span></span></pre>
</div>
</div>

</body>
</html>