<!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>[207671] 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/207671">207671</a></dd>
<dt>Author</dt> <dd>keith_miller@apple.com</dd>
<dt>Date</dt> <dd>2016-10-21 09:02:39 -0700 (Fri, 21 Oct 2016)</dd>
</dl>

<h3>Log Message</h3>
<pre>Add support for WASM calls
https://bugs.webkit.org/show_bug.cgi?id=161727

Reviewed by Filip Pizlo and Michael Saboff.

JSTests:

Add members of the Call category to the WASMOps special group.

* wasm/generate-wasmops-header.js:

Source/JavaScriptCore:

Add support for WASM calls. Since most of the work for this was already done when we added
WASM Memory, this is mostly just cleanup work.  The main interesting part of this patch is
how we link calls to other WASM functions in the same module. Since a WASM callee may not
have been compiled by the time the current function has started compilation we don't know
what address we need to call to.  For each callsite in the compiling function, WASM
remembers the CodeLocationCall and the target function index. Once all WASM functions are
compiled, each callsite is linked to the appropriate entrypoint.

* testWASM.cpp:
(runWASMTests):
* wasm/WASMB3IRGenerator.cpp:
(JSC::WASM::createJSWrapper):
(JSC::WASM::parseAndCompile):
* wasm/WASMB3IRGenerator.h:
* wasm/WASMCallingConvention.cpp:
(JSC::WASM::jscCallingConvention):
(JSC::WASM::wasmCallingConvention):
* wasm/WASMCallingConvention.h:
(JSC::WASM::CallingConvention::CallingConvention):
(JSC::WASM::CallingConvention::marshallArgumentImpl):
(JSC::WASM::CallingConvention::marshallArgument):
(JSC::WASM::CallingConvention::loadArguments):
(JSC::WASM::CallingConvention::setupCall):
(JSC::WASM::CallingConvention::iterate): Deleted.
* wasm/WASMFormat.h:
* wasm/WASMFunctionParser.h:
(JSC::WASM::FunctionParser&lt;Context&gt;::FunctionParser):
(JSC::WASM::FunctionParser&lt;Context&gt;::parseBlock):
(JSC::WASM::FunctionParser&lt;Context&gt;::parseExpression):
* wasm/WASMModuleParser.cpp:
(JSC::WASM::ModuleParser::parse):
* wasm/WASMOps.h:
* wasm/WASMParser.h:
(JSC::WASM::Parser::parseVarUInt32):
(JSC::WASM::Parser::parseVarUInt64):
* wasm/WASMPlan.cpp:
(JSC::WASM::Plan::Plan):

Source/WTF:

Added a new decodeUInt64. Also, added WTF::LEBDecoder namespace.

* wtf/LEBDecoder.h:
(WTF::LEBDecoder::decodeUInt):
(WTF::LEBDecoder::decodeUInt32):
(WTF::LEBDecoder::decodeUInt64):
(WTF::LEBDecoder::decodeInt32):
(decodeUInt32): Deleted.
(decodeInt32): Deleted.</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkJSTestsChangeLog">trunk/JSTests/ChangeLog</a></li>
<li><a href="#trunkJSTestswasmgeneratewasmopsheaderjs">trunk/JSTests/wasm/generate-wasmops-header.js</a></li>
<li><a href="#trunkSourceJavaScriptCoreChangeLog">trunk/Source/JavaScriptCore/ChangeLog</a></li>
<li><a href="#trunkSourceJavaScriptCoretestWASMcpp">trunk/Source/JavaScriptCore/testWASM.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorewasmWASMB3IRGeneratorcpp">trunk/Source/JavaScriptCore/wasm/WASMB3IRGenerator.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorewasmWASMB3IRGeneratorh">trunk/Source/JavaScriptCore/wasm/WASMB3IRGenerator.h</a></li>
<li><a href="#trunkSourceJavaScriptCorewasmWASMCallingConventioncpp">trunk/Source/JavaScriptCore/wasm/WASMCallingConvention.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorewasmWASMCallingConventionh">trunk/Source/JavaScriptCore/wasm/WASMCallingConvention.h</a></li>
<li><a href="#trunkSourceJavaScriptCorewasmWASMFormath">trunk/Source/JavaScriptCore/wasm/WASMFormat.h</a></li>
<li><a href="#trunkSourceJavaScriptCorewasmWASMFunctionParserh">trunk/Source/JavaScriptCore/wasm/WASMFunctionParser.h</a></li>
<li><a href="#trunkSourceJavaScriptCorewasmWASMModuleParsercpp">trunk/Source/JavaScriptCore/wasm/WASMModuleParser.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorewasmWASMOpsh">trunk/Source/JavaScriptCore/wasm/WASMOps.h</a></li>
<li><a href="#trunkSourceJavaScriptCorewasmWASMParserh">trunk/Source/JavaScriptCore/wasm/WASMParser.h</a></li>
<li><a href="#trunkSourceJavaScriptCorewasmWASMPlancpp">trunk/Source/JavaScriptCore/wasm/WASMPlan.cpp</a></li>
<li><a href="#trunkSourceWTFChangeLog">trunk/Source/WTF/ChangeLog</a></li>
<li><a href="#trunkSourceWTFwtfLEBDecoderh">trunk/Source/WTF/wtf/LEBDecoder.h</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkJSTestsChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/JSTests/ChangeLog (207670 => 207671)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JSTests/ChangeLog        2016-10-21 15:51:28 UTC (rev 207670)
+++ trunk/JSTests/ChangeLog        2016-10-21 16:02:39 UTC (rev 207671)
</span><span class="lines">@@ -1,3 +1,14 @@
</span><ins>+2016-10-20  Keith Miller  &lt;keith_miller@apple.com&gt;
+
+        Add support for WASM calls
+        https://bugs.webkit.org/show_bug.cgi?id=161727
+
+        Reviewed by Filip Pizlo and Michael Saboff.
+
+        Add members of the Call category to the WASMOps special group.
+
+        * wasm/generate-wasmops-header.js:
+
</ins><span class="cx"> 2016-10-20  Yusuke Suzuki  &lt;utatane.tea@gmail.com&gt;
</span><span class="cx"> 
</span><span class="cx">         [JSC] Drop isEnvironmentRecord type info flag and use JSType information instead
</span></span></pre></div>
<a id="trunkJSTestswasmgeneratewasmopsheaderjs"></a>
<div class="modfile"><h4>Modified: trunk/JSTests/wasm/generate-wasmops-header.js (207670 => 207671)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JSTests/wasm/generate-wasmops-header.js        2016-10-21 15:51:28 UTC (rev 207670)
+++ trunk/JSTests/wasm/generate-wasmops-header.js        2016-10-21 16:02:39 UTC (rev 207671)
</span><span class="lines">@@ -29,7 +29,7 @@
</span><span class="cx"> 
</span><span class="cx"> const defines = [
</span><span class="cx">     &quot;#define FOR_EACH_WASM_SPECIAL_OP(macro)&quot;,
</span><del>-    ...opcodeMacroizer(op =&gt; op.category === &quot;special&quot;),
</del><ins>+    ...opcodeMacroizer(op =&gt; op.category === &quot;special&quot; || op.category === &quot;call&quot;),
</ins><span class="cx">     &quot;\n\n#define FOR_EACH_WASM_CONTROL_FLOW_OP(macro)&quot;,
</span><span class="cx">     ...opcodeMacroizer(op =&gt; op.category === &quot;control&quot;),
</span><span class="cx">     &quot;\n\n#define FOR_EACH_WASM_UNARY_OP(macro)&quot;,
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ChangeLog (207670 => 207671)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ChangeLog        2016-10-21 15:51:28 UTC (rev 207670)
+++ trunk/Source/JavaScriptCore/ChangeLog        2016-10-21 16:02:39 UTC (rev 207671)
</span><span class="lines">@@ -1,3 +1,48 @@
</span><ins>+2016-10-20  Keith Miller  &lt;keith_miller@apple.com&gt;
+
+        Add support for WASM calls
+        https://bugs.webkit.org/show_bug.cgi?id=161727
+
+        Reviewed by Filip Pizlo and Michael Saboff.
+
+        Add support for WASM calls. Since most of the work for this was already done when we added
+        WASM Memory, this is mostly just cleanup work.  The main interesting part of this patch is
+        how we link calls to other WASM functions in the same module. Since a WASM callee may not
+        have been compiled by the time the current function has started compilation we don't know
+        what address we need to call to.  For each callsite in the compiling function, WASM
+        remembers the CodeLocationCall and the target function index. Once all WASM functions are
+        compiled, each callsite is linked to the appropriate entrypoint.
+
+        * testWASM.cpp:
+        (runWASMTests):
+        * wasm/WASMB3IRGenerator.cpp:
+        (JSC::WASM::createJSWrapper):
+        (JSC::WASM::parseAndCompile):
+        * wasm/WASMB3IRGenerator.h:
+        * wasm/WASMCallingConvention.cpp:
+        (JSC::WASM::jscCallingConvention):
+        (JSC::WASM::wasmCallingConvention):
+        * wasm/WASMCallingConvention.h:
+        (JSC::WASM::CallingConvention::CallingConvention):
+        (JSC::WASM::CallingConvention::marshallArgumentImpl):
+        (JSC::WASM::CallingConvention::marshallArgument):
+        (JSC::WASM::CallingConvention::loadArguments):
+        (JSC::WASM::CallingConvention::setupCall):
+        (JSC::WASM::CallingConvention::iterate): Deleted.
+        * wasm/WASMFormat.h:
+        * wasm/WASMFunctionParser.h:
+        (JSC::WASM::FunctionParser&lt;Context&gt;::FunctionParser):
+        (JSC::WASM::FunctionParser&lt;Context&gt;::parseBlock):
+        (JSC::WASM::FunctionParser&lt;Context&gt;::parseExpression):
+        * wasm/WASMModuleParser.cpp:
+        (JSC::WASM::ModuleParser::parse):
+        * wasm/WASMOps.h:
+        * wasm/WASMParser.h:
+        (JSC::WASM::Parser::parseVarUInt32):
+        (JSC::WASM::Parser::parseVarUInt64):
+        * wasm/WASMPlan.cpp:
+        (JSC::WASM::Plan::Plan):
+
</ins><span class="cx"> 2016-10-21  Wenson Hsieh  &lt;wenson_hsieh@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Implement InputEvent.getTargetRanges() for the input events spec
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoretestWASMcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/testWASM.cpp (207670 => 207671)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/testWASM.cpp        2016-10-21 15:51:28 UTC (rev 207670)
+++ trunk/Source/JavaScriptCore/testWASM.cpp        2016-10-21 16:02:39 UTC (rev 207671)
</span><span class="lines">@@ -135,7 +135,7 @@
</span><span class="cx">         Vector&lt;uint8_t&gt; vector = Vector&lt;uint8_t&gt; init; \
</span><span class="cx">         size_t offset = startOffset; \
</span><span class="cx">         uint32_t result; \
</span><del>-        bool status = decodeUInt32(vector.data(), vector.size(), offset, result); \
</del><ins>+        bool status = WTF::LEBDecoder::decodeUInt32(vector.data(), vector.size(), offset, result); \
</ins><span class="cx">         CHECK_EQ(status, expectedStatus); \
</span><span class="cx">         if (expectedStatus) { \
</span><span class="cx">             CHECK_EQ(result, expectedResult); \
</span><span class="lines">@@ -183,7 +183,7 @@
</span><span class="cx">         Vector&lt;uint8_t&gt; vector = Vector&lt;uint8_t&gt; init; \
</span><span class="cx">         size_t offset = startOffset; \
</span><span class="cx">         int32_t result; \
</span><del>-        bool status = decodeInt32(vector.data(), vector.size(), offset, result); \
</del><ins>+        bool status = WTF::LEBDecoder::decodeInt32(vector.data(), vector.size(), offset, result); \
</ins><span class="cx">         CHECK_EQ(status, expectedStatus); \
</span><span class="cx">         if (expectedStatus) { \
</span><span class="cx">             int32_t expected = expectedResult; \
</span><span class="lines">@@ -244,6 +244,136 @@
</span><span class="cx"> {
</span><span class="cx">     {
</span><span class="cx">         // Generated from:
</span><ins>+        //    (module
+        //     (memory 1)
+        //     (func $sum12 (param i32) (param i32) (param i32) (param i32) (param i32) (param i32) (param i32) (param i32) (param i32) (param i32) (param i32) (param i32) (result i32) (return (i32.add (get_local 0) (i32.add (get_local 1) (i32.add (get_local 2) (i32.add (get_local 3) (i32.add (get_local 4) (i32.add (get_local 5) (i32.add (get_local 6) (i32.add (get_local 7) (i32.add (get_local 8) (i32.add (get_local 9) (i32.add (get_local 10) (get_local 11))))))))))))))
+        //     (func (export &quot;mult12&quot;) (param i32) (result i32) (return (call $sum12 (get_local 0) (get_local 0) (get_local 0) (get_local 0) (get_local 0) (get_local 0) (get_local 0) (get_local 0) (get_local 0) (get_local 0) (get_local 0) (get_local 0))))
+        //     )
+
+        Vector&lt;uint8_t&gt; vector = {
+            0x00, 0x61, 0x73, 0x6d, 0x0c, 0x00, 0x00, 0x00, 0x01, 0x96, 0x80, 0x80, 0x80, 0x00, 0x02, 0x40,
+            0x0c, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x40,
+            0x01, 0x01, 0x01, 0x01, 0x03, 0x83, 0x80, 0x80, 0x80, 0x00, 0x02, 0x00, 0x01, 0x05, 0x83, 0x80,
+            0x80, 0x80, 0x00, 0x01, 0x00, 0x01, 0x07, 0x8a, 0x80, 0x80, 0x80, 0x00, 0x01, 0x06, 0x6d, 0x75,
+            0x6c, 0x74, 0x31, 0x32, 0x00, 0x01, 0x0a, 0xce, 0x80, 0x80, 0x80, 0x00, 0x02, 0xa6, 0x80, 0x80,
+            0x80, 0x00, 0x00, 0x14, 0x00, 0x14, 0x01, 0x14, 0x02, 0x14, 0x03, 0x14, 0x04, 0x14, 0x05, 0x14,
+            0x06, 0x14, 0x07, 0x14, 0x08, 0x14, 0x09, 0x14, 0x0a, 0x14, 0x0b, 0x40, 0x40, 0x40, 0x40, 0x40,
+            0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x09, 0x0f, 0x9d, 0x80, 0x80, 0x80, 0x00, 0x00, 0x14, 0x00,
+            0x14, 0x00, 0x14, 0x00, 0x14, 0x00, 0x14, 0x00, 0x14, 0x00, 0x14, 0x00, 0x14, 0x00, 0x14, 0x00,
+            0x14, 0x00, 0x14, 0x00, 0x14, 0x00, 0x16, 0x00, 0x09, 0x0f
+        };
+
+        Plan plan(*vm, vector);
+        if (plan.result.size() != 2 || !plan.result[0] || !plan.result[1]) {
+            dataLogLn(&quot;Module failed to compile correctly.&quot;);
+            CRASH();
+        }
+
+        // Test this doesn't crash.
+        CHECK_EQ(invoke&lt;int&gt;(*plan.result[1]-&gt;jsEntryPoint, { box(0) }), 0);
+        CHECK_EQ(invoke&lt;int&gt;(*plan.result[1]-&gt;jsEntryPoint, { box(100) }), 1200);
+        CHECK_EQ(invoke&lt;int&gt;(*plan.result[1]-&gt;jsEntryPoint, { box(1) }), 12);
+        CHECK_EQ(invoke&lt;int&gt;(*plan.result[0]-&gt;jsEntryPoint, { box(1), box(2), box(3), box(4), box(5), box(6), box(7), box(8), box(9), box(10), box(11), box(12) }), 78);
+        CHECK_EQ(invoke&lt;int&gt;(*plan.result[0]-&gt;jsEntryPoint, { box(1), box(2), box(3), box(4), box(5), box(6), box(7), box(8), box(9), box(10), box(11), box(100) }), 166);
+    }
+
+    {
+        // Generated from:
+        //    (module
+        //     (memory 1)
+        //     (func $fac (export &quot;fac&quot;) (param i64) (result i64)
+        //      (if (i64.eqz (get_local 0))
+        //       (return (i64.const 1))
+        //       )
+        //      (return (i64.mul (get_local 0) (call $fac (i64.sub (get_local 0) (i64.const 1)))))
+        //      )
+        //     )
+        Vector&lt;uint8_t&gt; vector = {
+            0x00, 0x61, 0x73, 0x6d, 0x0c, 0x00, 0x00, 0x00, 0x01, 0x86, 0x80, 0x80, 0x80, 0x00, 0x01, 0x40,
+            0x01, 0x02, 0x01, 0x02, 0x03, 0x82, 0x80, 0x80, 0x80, 0x00, 0x01, 0x00, 0x05, 0x83, 0x80, 0x80,
+            0x80, 0x00, 0x01, 0x00, 0x01, 0x07, 0x87, 0x80, 0x80, 0x80, 0x00, 0x01, 0x03, 0x66, 0x61, 0x63,
+            0x00, 0x00, 0x0a, 0x9e, 0x80, 0x80, 0x80, 0x00, 0x01, 0x98, 0x80, 0x80, 0x80, 0x00, 0x00, 0x14,
+            0x00, 0x11, 0x00, 0x68, 0x03, 0x00, 0x11, 0x01, 0x09, 0x0f, 0x14, 0x00, 0x14, 0x00, 0x11, 0x01,
+            0x5c, 0x16, 0x00, 0x5d, 0x09, 0x0f
+        };
+
+        Plan plan(*vm, vector);
+        if (plan.result.size() != 1 || !plan.result[0]) {
+            dataLogLn(&quot;Module failed to compile correctly.&quot;);
+            CRASH();
+        }
+
+        // Test this doesn't crash.
+        CHECK_EQ(invoke&lt;int&gt;(*plan.result[0]-&gt;jsEntryPoint, { box(0) }), 1);
+        CHECK_EQ(invoke&lt;int&gt;(*plan.result[0]-&gt;jsEntryPoint, { box(1) }), 1);
+        CHECK_EQ(invoke&lt;int&gt;(*plan.result[0]-&gt;jsEntryPoint, { box(2) }), 2);
+        CHECK_EQ(invoke&lt;int&gt;(*plan.result[0]-&gt;jsEntryPoint, { box(4) }), 24);
+    }
+
+    {
+        // Generated from:
+        //    (module
+        //     (memory 1)
+        //     (func (export &quot;double&quot;) (param i64) (result i64) (return (call 1 (get_local 0) (get_local 0))))
+        //     (func $sum (param i64) (param i64) (result i64) (return (i64.add (get_local 0) (get_local 1))))
+        //     )
+        Vector&lt;uint8_t&gt; vector = {
+            0x00, 0x61, 0x73, 0x6d, 0x0c, 0x00, 0x00, 0x00, 0x01, 0x8c, 0x80, 0x80, 0x80, 0x00, 0x02, 0x40,
+            0x01, 0x02, 0x01, 0x02, 0x40, 0x02, 0x02, 0x02, 0x01, 0x02, 0x03, 0x83, 0x80, 0x80, 0x80, 0x00,
+            0x02, 0x00, 0x01, 0x05, 0x83, 0x80, 0x80, 0x80, 0x00, 0x01, 0x00, 0x01, 0x07, 0x8a, 0x80, 0x80,
+            0x80, 0x00, 0x01, 0x06, 0x64, 0x6f, 0x75, 0x62, 0x6c, 0x65, 0x00, 0x00, 0x0a, 0x9c, 0x80, 0x80,
+            0x80, 0x00, 0x02, 0x89, 0x80, 0x80, 0x80, 0x00, 0x00, 0x14, 0x00, 0x14, 0x00, 0x16, 0x01, 0x09,
+            0x0f, 0x88, 0x80, 0x80, 0x80, 0x00, 0x00, 0x14, 0x00, 0x14, 0x01, 0x5b, 0x09, 0x0f
+        };
+
+        Plan plan(*vm, vector);
+        if (plan.result.size() != 2 || !plan.result[0] || !plan.result[1]) {
+            dataLogLn(&quot;Module failed to compile correctly.&quot;);
+            CRASH();
+        }
+
+        // Test this doesn't crash.
+        CHECK_EQ(invoke&lt;int&gt;(*plan.result[1]-&gt;jsEntryPoint, { box(0), box(0) }), 0);
+        CHECK_EQ(invoke&lt;int&gt;(*plan.result[1]-&gt;jsEntryPoint, { box(100), box(0) }), 100);
+        CHECK_EQ(invoke&lt;int&gt;(*plan.result[1]-&gt;jsEntryPoint, { box(1), box(15) }), 16);
+        CHECK_EQ(invoke&lt;int&gt;(*plan.result[0]-&gt;jsEntryPoint, { box(0) }), 0);
+        CHECK_EQ(invoke&lt;int&gt;(*plan.result[0]-&gt;jsEntryPoint, { box(100) }), 200);
+        CHECK_EQ(invoke&lt;int&gt;(*plan.result[0]-&gt;jsEntryPoint, { box(1) }), 2);
+    }
+
+    {
+        // Generated from:
+        //    (module
+        //     (memory 1)
+        //     (func $id (param $value i32) (result i32) (return (get_local $value)))
+        //     (func (export &quot;id-call&quot;) (param $value i32) (result i32) (return (call $id (get_local $value))))
+        //     )
+        Vector&lt;uint8_t&gt; vector = {
+            0x00, 0x61, 0x73, 0x6d, 0x0c, 0x00, 0x00, 0x00, 0x01, 0x86, 0x80, 0x80, 0x80, 0x00, 0x01, 0x40,
+            0x01, 0x01, 0x01, 0x01, 0x03, 0x83, 0x80, 0x80, 0x80, 0x00, 0x02, 0x00, 0x00, 0x05, 0x83, 0x80,
+            0x80, 0x80, 0x00, 0x01, 0x01, 0x01, 0x07, 0x8b, 0x80, 0x80, 0x80, 0x00, 0x01, 0x07, 0x69, 0x64,
+            0x2d, 0x63, 0x61, 0x6c, 0x6c, 0x00, 0x01, 0x0a, 0x97, 0x80, 0x80, 0x80, 0x00, 0x02, 0x85, 0x80,
+            0x80, 0x80, 0x00, 0x00, 0x14, 0x00, 0x09, 0x0f, 0x87, 0x80, 0x80, 0x80, 0x00, 0x00, 0x14, 0x00,
+            0x16, 0x00, 0x09, 0x0f
+        };
+
+        Plan plan(*vm, vector);
+        if (plan.result.size() != 2 || !plan.result[0] || !plan.result[1]) {
+            dataLogLn(&quot;Module failed to compile correctly.&quot;);
+            CRASH();
+        }
+
+        // Test this doesn't crash.
+        CHECK_EQ(invoke&lt;int&gt;(*plan.result[1]-&gt;jsEntryPoint, { box(0) }), 0);
+        CHECK_EQ(invoke&lt;int&gt;(*plan.result[1]-&gt;jsEntryPoint, { box(100) }), 100);
+        CHECK_EQ(invoke&lt;int&gt;(*plan.result[1]-&gt;jsEntryPoint, { box(1) }), 1);
+        CHECK_EQ(invoke&lt;int&gt;(*plan.result[0]-&gt;jsEntryPoint, { box(0) }), 0);
+        CHECK_EQ(invoke&lt;int&gt;(*plan.result[0]-&gt;jsEntryPoint, { box(100) }), 100);
+        CHECK_EQ(invoke&lt;int&gt;(*plan.result[0]-&gt;jsEntryPoint, { box(1) }), 1);
+    }
+
+    {
+        // Generated from:
</ins><span class="cx">         // (module
</span><span class="cx">         //  (memory 1)
</span><span class="cx">         //  (func (export &quot;i32_load8_s&quot;) (param $i i32) (param $ptr i32) (result i32)
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorewasmWASMB3IRGeneratorcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/wasm/WASMB3IRGenerator.cpp (207670 => 207671)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/wasm/WASMB3IRGenerator.cpp        2016-10-21 15:51:28 UTC (rev 207670)
+++ trunk/Source/JavaScriptCore/wasm/WASMB3IRGenerator.cpp        2016-10-21 16:02:39 UTC (rev 207671)
</span><span class="lines">@@ -170,7 +170,7 @@
</span><span class="cx">     typedef Vector&lt;Variable*, 1&gt; ResultList;
</span><span class="cx">     static constexpr ExpressionType emptyExpression = nullptr;
</span><span class="cx"> 
</span><del>-    B3IRGenerator(Memory*, Procedure&amp;);
</del><ins>+    B3IRGenerator(Memory*, Procedure&amp;, Vector&lt;UnlinkedCall&gt;&amp; unlinkedCalls);
</ins><span class="cx"> 
</span><span class="cx">     void addArguments(const Vector&lt;Type&gt;&amp;);
</span><span class="cx">     void addLocal(Type, uint32_t);
</span><span class="lines">@@ -198,6 +198,8 @@
</span><span class="cx">     bool WARN_UNUSED_RETURN addBranch(ControlData&amp;, ExpressionType condition, const ExpressionList&amp; returnValues);
</span><span class="cx">     bool WARN_UNUSED_RETURN endBlock(ControlData&amp;, ExpressionList&amp; expressionStack);
</span><span class="cx"> 
</span><ins>+    bool WARN_UNUSED_RETURN addCall(unsigned calleeIndex, const FunctionInformation&amp;, Vector&lt;ExpressionType&gt;&amp; args, ExpressionType&amp; result);
+
</ins><span class="cx">     bool isContinuationReachable(ControlData&amp;);
</span><span class="cx"> 
</span><span class="cx">     void dump(const Vector&lt;ControlType&gt;&amp; controlStack, const ExpressionList&amp; expressionStack);
</span><span class="lines">@@ -214,13 +216,16 @@
</span><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><ins>+    // m_unlikedCalls is list of each call site and the function index whose address it should be patched with.
+    Vector&lt;UnlinkedCall&gt;&amp; m_unlinkedCalls;
</ins><span class="cx">     GPRReg m_memoryBaseGPR;
</span><span class="cx">     GPRReg m_memorySizeGPR;
</span><span class="cx"> };
</span><span class="cx"> 
</span><del>-B3IRGenerator::B3IRGenerator(Memory* memory, Procedure&amp; procedure)
</del><ins>+B3IRGenerator::B3IRGenerator(Memory* memory, Procedure&amp; procedure, Vector&lt;UnlinkedCall&gt;&amp; unlinkedCalls)
</ins><span class="cx">     : m_memory(memory)
</span><span class="cx">     , m_proc(procedure)
</span><ins>+    , m_unlinkedCalls(unlinkedCalls)
</ins><span class="cx"> {
</span><span class="cx">     m_currentBlock = m_proc.addBlock();
</span><span class="cx"> 
</span><span class="lines">@@ -231,13 +236,13 @@
</span><span class="cx">         m_memorySizeGPR = m_memory-&gt;pinnedRegisters().sizeRegisters[0].sizeRegister;
</span><span class="cx">         for (const PinnedSizeRegisterInfo&amp; info : m_memory-&gt;pinnedRegisters().sizeRegisters)
</span><span class="cx">             m_proc.pinRegister(info.sizeRegister);
</span><ins>+
+        m_proc.setWasmBoundsCheckGenerator([=] (CCallHelpers&amp; jit, GPRReg pinnedGPR, unsigned) {
+            ASSERT_UNUSED(pinnedGPR, m_memorySizeGPR == pinnedGPR);
+            // FIXME: This should unwind the stack and throw a JS exception. See: https://bugs.webkit.org/show_bug.cgi?id=163351
+            jit.breakpoint();
+        });
</ins><span class="cx">     }
</span><del>-
-    m_proc.setWasmBoundsCheckGenerator([=] (CCallHelpers&amp; jit, GPRReg pinnedGPR, unsigned) {
-        ASSERT_UNUSED(pinnedGPR, m_memorySizeGPR == pinnedGPR);
-        // FIXME: This should unwind the stack and throw a JS exception. See: https://bugs.webkit.org/show_bug.cgi?id=163351
-        jit.breakpoint();
-    });
</del><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void B3IRGenerator::addLocal(Type type, uint32_t count)
</span><span class="lines">@@ -251,7 +256,7 @@
</span><span class="cx"> {
</span><span class="cx">     ASSERT(!m_locals.size());
</span><span class="cx">     m_locals.grow(types.size());
</span><del>-    jscCallingConvention().iterate(types, m_proc, m_currentBlock, Origin(),
</del><ins>+    wasmCallingConvention().loadArguments(types, m_proc, m_currentBlock, Origin(),
</ins><span class="cx">         [&amp;] (ExpressionType argument, unsigned i) {
</span><span class="cx">             Variable* argumentVariable = m_proc.addVariable(argument-&gt;type());
</span><span class="cx">             m_locals[i] = argumentVariable;
</span><span class="lines">@@ -561,6 +566,32 @@
</span><span class="cx">     return true;
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+bool B3IRGenerator::addCall(unsigned functionIndex, const FunctionInformation&amp; info, Vector&lt;ExpressionType&gt;&amp; args, ExpressionType&amp; result)
+{
+    ASSERT(info.signature-&gt;arguments.size() == args.size());
+
+    Type returnType = info.signature-&gt;returnType;
+
+    size_t callIndex = m_unlinkedCalls.size();
+    m_unlinkedCalls.grow(callIndex + 1);
+    result = wasmCallingConvention().setupCall(m_proc, m_currentBlock, Origin(), args, toB3Type(returnType),
+        [&amp;] (PatchpointValue* patchpoint) {
+            patchpoint-&gt;effects.writesPinned = true;
+            patchpoint-&gt;effects.readsPinned = true;
+
+            patchpoint-&gt;setGenerator([=] (CCallHelpers&amp; jit, const B3::StackmapGenerationParams&amp;) {
+                AllowMacroScratchRegisterUsage allowScratch(jit);
+
+                CCallHelpers::Call call = jit.call();
+
+                jit.addLinkTask([=] (LinkBuffer&amp; linkBuffer) {
+                    m_unlinkedCalls[callIndex] = { linkBuffer.locationOf(call), functionIndex };
+                });
+            });
+        });
+    return true;
+}
+
</ins><span class="cx"> bool B3IRGenerator::isContinuationReachable(ControlData&amp; data)
</span><span class="cx"> {
</span><span class="cx">     // If nothing targets the continuation of the current block then we don't want to create
</span><span class="lines">@@ -642,12 +673,12 @@
</span><span class="cx"> 
</span><span class="cx">     // Get our arguments.
</span><span class="cx">     Vector&lt;Value*&gt; arguments;
</span><del>-    jscCallingConvention().iterate(signature-&gt;arguments, proc, block, Origin(), [&amp;] (Value* argument, unsigned) {
</del><ins>+    jscCallingConvention().loadArguments(signature-&gt;arguments, proc, block, Origin(), [&amp;] (Value* argument, unsigned) {
</ins><span class="cx">         arguments.append(argument);
</span><span class="cx">     });
</span><span class="cx"> 
</span><span class="cx">     // Move the arguments into place.
</span><del>-    Value* result = jscCallingConvention().setupCall(proc, block, Origin(), mainFunction, arguments, toB3Type(signature-&gt;returnType), [&amp;] (PatchpointValue* patchpoint) {
</del><ins>+    Value* result = wasmCallingConvention().setupCall(proc, block, Origin(), arguments, toB3Type(signature-&gt;returnType), [&amp;] (PatchpointValue* patchpoint) {
</ins><span class="cx">         if (memory) {
</span><span class="cx">             ASSERT(sizes.size() == memory-&gt;pinnedRegisters().sizeRegisters.size());
</span><span class="cx">             patchpoint-&gt;append(ConstrainedValue(baseMemory, ValueRep::reg(memory-&gt;pinnedRegisters().baseMemoryPointer)));
</span><span class="lines">@@ -654,6 +685,15 @@
</span><span class="cx">             for (unsigned i = 0; i &lt; sizes.size(); ++i)
</span><span class="cx">                 patchpoint-&gt;append(ConstrainedValue(sizes[i], ValueRep::reg(memory-&gt;pinnedRegisters().sizeRegisters[i].sizeRegister)));
</span><span class="cx">         }
</span><ins>+
+        patchpoint-&gt;setGenerator([=] (CCallHelpers&amp; jit, const B3::StackmapGenerationParams&amp;) {
+            AllowMacroScratchRegisterUsage allowScratch(jit);
+
+            CCallHelpers::Call call = jit.call();
+            jit.addLinkTask([=] (LinkBuffer&amp; linkBuffer) {
+                linkBuffer.link(call, FunctionPtr(mainFunction.executableAddress()));
+            });
+        });
</ins><span class="cx">     });
</span><span class="cx"> 
</span><span class="cx">     // Return the result, if needed.
</span><span class="lines">@@ -665,11 +705,13 @@
</span><span class="cx">     return std::make_unique&lt;Compilation&gt;(vm, proc);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-std::unique_ptr&lt;FunctionCompilation&gt; parseAndCompile(VM&amp; vm, Vector&lt;uint8_t&gt;&amp; source, Memory* memory, FunctionInformation info, unsigned optLevel)
</del><ins>+std::unique_ptr&lt;FunctionCompilation&gt; parseAndCompile(VM&amp; vm, Vector&lt;uint8_t&gt;&amp; source, Memory* memory, FunctionInformation info, const Vector&lt;FunctionInformation&gt;&amp; functions, unsigned optLevel)
</ins><span class="cx"> {
</span><ins>+    auto result = std::make_unique&lt;FunctionCompilation&gt;();
+
</ins><span class="cx">     Procedure procedure;
</span><del>-    B3IRGenerator context(memory, procedure);
-    FunctionParser&lt;B3IRGenerator&gt; parser(context, source, info);
</del><ins>+    B3IRGenerator context(memory, procedure, result-&gt;unlinkedCalls);
+    FunctionParser&lt;B3IRGenerator&gt; parser(context, source, info, functions);
</ins><span class="cx">     if (!parser.parse())
</span><span class="cx">         RELEASE_ASSERT_NOT_REACHED();
</span><span class="cx"> 
</span><span class="lines">@@ -679,7 +721,6 @@
</span><span class="cx">     fixSSA(procedure);
</span><span class="cx">     if (verbose)
</span><span class="cx">         dataLog(&quot;Post SSA: &quot;, procedure);
</span><del>-    auto result = std::make_unique&lt;FunctionCompilation&gt;();
</del><span class="cx"> 
</span><span class="cx">     result-&gt;code = std::make_unique&lt;Compilation&gt;(vm, procedure, optLevel);
</span><span class="cx">     result-&gt;jsEntryPoint = createJSWrapper(vm, info.signature, result-&gt;code-&gt;code(), memory);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorewasmWASMB3IRGeneratorh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/wasm/WASMB3IRGenerator.h (207670 => 207671)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/wasm/WASMB3IRGenerator.h        2016-10-21 15:51:28 UTC (rev 207670)
+++ trunk/Source/JavaScriptCore/wasm/WASMB3IRGenerator.h        2016-10-21 16:02:39 UTC (rev 207671)
</span><span class="lines">@@ -37,7 +37,7 @@
</span><span class="cx"> 
</span><span class="cx"> class Memory;
</span><span class="cx"> 
</span><del>-std::unique_ptr&lt;FunctionCompilation&gt; parseAndCompile(VM&amp;, Vector&lt;uint8_t&gt;&amp;, Memory*, FunctionInformation, unsigned optLevel = 1);
</del><ins>+std::unique_ptr&lt;FunctionCompilation&gt; parseAndCompile(VM&amp;, Vector&lt;uint8_t&gt;&amp;, Memory*, FunctionInformation, const Vector&lt;FunctionInformation&gt;&amp;, unsigned optLevel = 1);
</ins><span class="cx"> 
</span><span class="cx"> } } // namespace JSC::WASM
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorewasmWASMCallingConventioncpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/wasm/WASMCallingConvention.cpp (207670 => 207671)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/wasm/WASMCallingConvention.cpp        2016-10-21 15:51:28 UTC (rev 207670)
+++ trunk/Source/JavaScriptCore/wasm/WASMCallingConvention.cpp        2016-10-21 16:02:39 UTC (rev 207671)
</span><span class="lines">@@ -37,12 +37,31 @@
</span><span class="cx">     static LazyNeverDestroyed&lt;JSCCallingConvention&gt; staticJSCCallingConvention;
</span><span class="cx">     static std::once_flag staticJSCCallingConventionFlag;
</span><span class="cx">     std::call_once(staticJSCCallingConventionFlag, [] () {
</span><del>-        staticJSCCallingConvention.construct(Vector&lt;GPRReg&gt;(), RegisterSet::calleeSaveRegisters());
</del><ins>+        staticJSCCallingConvention.construct(Vector&lt;Reg&gt;(), Vector&lt;Reg&gt;(), RegisterSet::calleeSaveRegisters());
</ins><span class="cx">     });
</span><span class="cx"> 
</span><span class="cx">     return staticJSCCallingConvention;
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+const WASMCallingConvention&amp; wasmCallingConvention()
+{
+    static LazyNeverDestroyed&lt;JSCCallingConvention&gt; staticWASMCallingConvention;
+    static std::once_flag staticWASMCallingConventionFlag;
+    std::call_once(staticWASMCallingConventionFlag, [] () {
+        Vector&lt;Reg&gt; gprArgumentRegisters(GPRInfo::numberOfArgumentRegisters);
+        for (unsigned i = 0; i &lt; GPRInfo::numberOfArgumentRegisters; ++i)
+            gprArgumentRegisters[i] = GPRInfo::toArgumentRegister(i);
+
+        Vector&lt;Reg&gt; fprArgumentRegisters(FPRInfo::numberOfArgumentRegisters);
+        for (unsigned i = 0; i &lt; FPRInfo::numberOfArgumentRegisters; ++i)
+            fprArgumentRegisters[i] = FPRInfo::toArgumentRegister(i);
+
+        staticWASMCallingConvention.construct(WTFMove(gprArgumentRegisters), WTFMove(fprArgumentRegisters), RegisterSet::calleeSaveRegisters());
+    });
+
+    return staticWASMCallingConvention;
+}
+
</ins><span class="cx"> } } // namespace JSC::WASM
</span><span class="cx"> 
</span><span class="cx"> #endif // ENABLE(B3_JIT)
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorewasmWASMCallingConventionh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/wasm/WASMCallingConvention.h (207670 => 207671)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/wasm/WASMCallingConvention.h        2016-10-21 15:51:28 UTC (rev 207670)
+++ trunk/Source/JavaScriptCore/wasm/WASMCallingConvention.h        2016-10-21 16:02:39 UTC (rev 207671)
</span><span class="lines">@@ -48,62 +48,92 @@
</span><span class="cx"> template&lt;unsigned headerSize, NextOffset updateOffset&gt;
</span><span class="cx"> class CallingConvention {
</span><span class="cx"> public:
</span><del>-    CallingConvention(Vector&lt;GPRReg&gt;&amp;&amp; registerArguments, RegisterSet&amp;&amp; calleeSaveRegisters)
-        : m_registerArguments(registerArguments)
</del><ins>+    CallingConvention(Vector&lt;Reg&gt;&amp;&amp; gprArgs, Vector&lt;Reg&gt;&amp;&amp; fprArgs, RegisterSet&amp;&amp; calleeSaveRegisters)
+        : m_gprArgs(gprArgs)
+        , m_fprArgs(fprArgs)
</ins><span class="cx">         , m_calleeSaveRegisters(calleeSaveRegisters)
</span><span class="cx">     {
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+private:
+    B3::ValueRep marshallArgumentImpl(Vector&lt;Reg&gt; regArgs, B3::Type type, size_t&amp; count, size_t&amp; stackOffset) const
+    {
+        if (count &lt; regArgs.size())
+            return B3::ValueRep::reg(regArgs[count++]);
+
+        count++;
+        B3::ValueRep result = B3::ValueRep::stackArgument(stackOffset);
+        stackOffset = updateOffset(stackOffset, type);
+        return result;
+    }
+
+    B3::ValueRep marshallArgument(B3::Type type, size_t&amp; gpArgumentCount, size_t&amp; fpArgumentCount, size_t&amp; stackOffset) const
+    {
+        switch (type) {
+        case B3::Int32:
+        case B3::Int64:
+            return marshallArgumentImpl(m_gprArgs, type, gpArgumentCount, stackOffset);
+        case B3::Float:
+        case B3::Double:
+            return marshallArgumentImpl(m_fprArgs, type, fpArgumentCount, stackOffset);
+        case Void:
+            break;
+        }
+        RELEASE_ASSERT_NOT_REACHED();
+    }
+
+public:
</ins><span class="cx">     template&lt;typename Functor&gt;
</span><del>-    void iterate(const Vector&lt;Type&gt;&amp; argumentTypes, B3::Procedure&amp; proc, B3::BasicBlock* block, B3::Origin origin, const Functor&amp; functor) const
</del><ins>+    void loadArguments(const Vector&lt;Type&gt;&amp; argumentTypes, B3::Procedure&amp; proc, B3::BasicBlock* block, B3::Origin origin, const Functor&amp; functor) const
</ins><span class="cx">     {
</span><del>-        unsigned currentOffset = headerSize;
</del><span class="cx">         B3::Value* framePointer = block-&gt;appendNew&lt;B3::Value&gt;(proc, B3::FramePointer, origin);
</span><span class="cx"> 
</span><del>-        for (unsigned i = 0; i &lt; argumentTypes.size(); ++i) {
</del><ins>+        size_t gpArgumentCount = 0;
+        size_t fpArgumentCount = 0;
+        size_t stackOffset = headerSize;
+
+        for (size_t i = 0; i &lt; argumentTypes.size(); ++i) {
+            B3::Type type = toB3Type(argumentTypes[i]);
</ins><span class="cx">             B3::Value* argument;
</span><del>-            if (i &lt; m_registerArguments.size())
-                argument = block-&gt;appendNew&lt;B3::ArgumentRegValue&gt;(proc, origin, m_registerArguments[i]);
-            else {
</del><ins>+            B3::ValueRep rep = marshallArgument(type, gpArgumentCount, fpArgumentCount, stackOffset);
+            if (rep.isReg()) {
+                argument = block-&gt;appendNew&lt;B3::ArgumentRegValue&gt;(proc, origin, rep.reg());
+                if (type == B3::Int32)
+                    argument = block-&gt;appendNew&lt;B3::Value&gt;(proc, B3::Trunc, origin, argument);
+                // FIXME: How do I get a float from a FPR? We don't support floating points yet so it's not a big deal... yet.
+                // see: https://bugs.webkit.org/show_bug.cgi?id=163770
+            } else {
+                ASSERT(rep.isStackArgument());
</ins><span class="cx">                 B3::Value* address = block-&gt;appendNew&lt;B3::Value&gt;(proc, B3::Add, origin, framePointer,
</span><del>-                    block-&gt;appendNew&lt;B3::Const64Value&gt;(proc, origin, currentOffset));
-                argument = block-&gt;appendNew&lt;B3::MemoryValue&gt;(proc, B3::Load, toB3Type(argumentTypes[i]), origin, address);
-                currentOffset = updateOffset(currentOffset, toB3Type(argumentTypes[i]));
</del><ins>+                    block-&gt;appendNew&lt;B3::Const64Value&gt;(proc, origin, rep.offsetFromSP()));
+                argument = block-&gt;appendNew&lt;B3::MemoryValue&gt;(proc, B3::Load, type, origin, address);
</ins><span class="cx">             }
</span><span class="cx">             functor(argument, i);
</span><span class="cx">         }
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    // It's expected that the pachpointFunctor sets the generator for the call operation.
</ins><span class="cx">     template&lt;typename Functor&gt;
</span><del>-    B3::Value* setupCall(B3::Procedure&amp; proc, B3::BasicBlock* block, B3::Origin origin, MacroAssemblerCodePtr target, const Vector&lt;B3::Value*&gt;&amp; arguments, B3::Type returnType, const Functor&amp; patchpointFunctor) const
</del><ins>+    B3::Value* setupCall(B3::Procedure&amp; proc, B3::BasicBlock* block, B3::Origin origin, const Vector&lt;B3::Value*&gt;&amp; arguments, B3::Type returnType, const Functor&amp; patchpointFunctor) const
</ins><span class="cx">     {
</span><del>-        size_t stackArgumentCount = arguments.size() &lt; m_registerArguments.size() ? 0 : arguments.size() - m_registerArguments.size();
-        unsigned offset = headerSize - sizeof(CallerFrameAndPC);
</del><ins>+        size_t gpArgumentCount = 0;
+        size_t fpArgumentCount = 0;
+        size_t stackOffset = headerSize - sizeof(CallerFrameAndPC);
</ins><span class="cx"> 
</span><del>-        proc.requestCallArgAreaSizeInBytes(WTF::roundUpToMultipleOf(stackAlignmentBytes(), headerSize + (stackArgumentCount * sizeof(Register))));
</del><span class="cx">         Vector&lt;B3::ConstrainedValue&gt; constrainedArguments;
</span><del>-        for (unsigned i = 0; i &lt; arguments.size(); ++i) {
-            B3::ValueRep rep;
-            if (i &lt; m_registerArguments.size())
-                rep = B3::ValueRep::reg(m_registerArguments[i]);
-            else
-                rep = B3::ValueRep::stackArgument(offset);
-            constrainedArguments.append(B3::ConstrainedValue(arguments[i], rep));
-            offset = updateOffset(offset, arguments[i]-&gt;type());
</del><ins>+        for (B3::Value* argument : arguments) {
+            B3::ValueRep rep = marshallArgument(argument-&gt;type(), gpArgumentCount, fpArgumentCount, stackOffset);
+            constrainedArguments.append(B3::ConstrainedValue(argument, rep));
</ins><span class="cx">         }
</span><span class="cx"> 
</span><ins>+        proc.requestCallArgAreaSizeInBytes(WTF::roundUpToMultipleOf(stackAlignmentBytes(), stackOffset));
+
</ins><span class="cx">         B3::PatchpointValue* patchpoint = block-&gt;appendNew&lt;B3::PatchpointValue&gt;(proc, returnType, origin);
</span><ins>+        patchpoint-&gt;clobberEarly(RegisterSet::macroScratchRegisters());
+        patchpoint-&gt;clobberLate(RegisterSet::volatileRegistersForJSCall());
</ins><span class="cx">         patchpoint-&gt;appendVector(constrainedArguments);
</span><span class="cx">         patchpointFunctor(patchpoint);
</span><del>-        patchpoint-&gt;setGenerator([=] (CCallHelpers&amp; jit, const B3::StackmapGenerationParams&amp;) {
-            AllowMacroScratchRegisterUsage allowScratch(jit);
</del><span class="cx"> 
</span><del>-            CCallHelpers::Call call = jit.call();
-            jit.addLinkTask([=] (LinkBuffer&amp; linkBuffer) {
-                linkBuffer.link(call, FunctionPtr(target.executableAddress()));
-            });
-        });
-
</del><span class="cx">         if (returnType == B3::Void)
</span><span class="cx">             return nullptr;
</span><span class="cx"> 
</span><span class="lines">@@ -111,7 +141,8 @@
</span><span class="cx">         return patchpoint;
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    const Vector&lt;GPRReg&gt; m_registerArguments;
</del><ins>+    const Vector&lt;Reg&gt; m_gprArgs;
+    const Vector&lt;Reg&gt; m_fprArgs;
</ins><span class="cx">     const RegisterSet m_calleeSaveRegisters;
</span><span class="cx">     const RegisterSet m_callerSaveRegisters;
</span><span class="cx"> };
</span><span class="lines">@@ -124,7 +155,10 @@
</span><span class="cx"> constexpr unsigned jscHeaderSize = ExecState::headerSizeInRegisters * sizeof(Register);
</span><span class="cx"> typedef CallingConvention&lt;jscHeaderSize, nextJSCOffset&gt; JSCCallingConvention;
</span><span class="cx"> 
</span><ins>+typedef JSCCallingConvention WASMCallingConvention;
+
</ins><span class="cx"> const JSCCallingConvention&amp; jscCallingConvention();
</span><ins>+const WASMCallingConvention&amp; wasmCallingConvention();
</ins><span class="cx"> 
</span><span class="cx"> } } // namespace JSC::WASM
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorewasmWASMFormath"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/wasm/WASMFormat.h (207670 => 207671)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/wasm/WASMFormat.h        2016-10-21 15:51:28 UTC (rev 207670)
+++ trunk/Source/JavaScriptCore/wasm/WASMFormat.h        2016-10-21 16:02:39 UTC (rev 207671)
</span><span class="lines">@@ -46,6 +46,7 @@
</span><span class="cx"> 
</span><span class="cx"> #include &quot;B3Compilation.h&quot;
</span><span class="cx"> #include &quot;B3Type.h&quot;
</span><ins>+#include &quot;CodeLocation.h&quot;
</ins><span class="cx"> #include &lt;wtf/Vector.h&gt;
</span><span class="cx"> #include &lt;wtf/text/WTFString.h&gt;
</span><span class="cx"> 
</span><span class="lines">@@ -127,7 +128,13 @@
</span><span class="cx">     size_t end;
</span><span class="cx"> };
</span><span class="cx"> 
</span><ins>+struct UnlinkedCall {
+    CodeLocationCall callLocation;
+    size_t functionIndex;
+};
+
</ins><span class="cx"> struct FunctionCompilation {
</span><ins>+    Vector&lt;UnlinkedCall&gt; unlinkedCalls;
</ins><span class="cx">     std::unique_ptr&lt;B3::Compilation&gt; code;
</span><span class="cx">     std::unique_ptr&lt;B3::Compilation&gt; jsEntryPoint;
</span><span class="cx"> };
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorewasmWASMFunctionParserh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/wasm/WASMFunctionParser.h (207670 => 207671)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/wasm/WASMFunctionParser.h        2016-10-21 15:51:28 UTC (rev 207670)
+++ trunk/Source/JavaScriptCore/wasm/WASMFunctionParser.h        2016-10-21 16:02:39 UTC (rev 207671)
</span><span class="lines">@@ -44,7 +44,7 @@
</span><span class="cx">     typedef typename Context::ExpressionType ExpressionType;
</span><span class="cx">     typedef typename Context::ControlType ControlType;
</span><span class="cx"> 
</span><del>-    FunctionParser(Context&amp;, const Vector&lt;uint8_t&gt;&amp; sourceBuffer, const FunctionInformation&amp;);
</del><ins>+    FunctionParser(Context&amp;, const Vector&lt;uint8_t&gt;&amp; sourceBuffer, const FunctionInformation&amp;, const Vector&lt;FunctionInformation&gt;&amp; functions);
</ins><span class="cx"> 
</span><span class="cx">     bool WARN_UNUSED_RETURN parse();
</span><span class="cx"> 
</span><span class="lines">@@ -60,14 +60,16 @@
</span><span class="cx">     Vector&lt;ExpressionType, 1&gt; m_expressionStack;
</span><span class="cx">     Vector&lt;ControlType&gt; m_controlStack;
</span><span class="cx">     const Signature&amp; m_signature;
</span><ins>+    const Vector&lt;FunctionInformation&gt;&amp; m_functions;
</ins><span class="cx">     unsigned m_unreachableBlocks { 0 };
</span><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> template&lt;typename Context&gt;
</span><del>-FunctionParser&lt;Context&gt;::FunctionParser(Context&amp; context, const Vector&lt;uint8_t&gt;&amp; sourceBuffer, const FunctionInformation&amp; info)
</del><ins>+FunctionParser&lt;Context&gt;::FunctionParser(Context&amp; context, const Vector&lt;uint8_t&gt;&amp; sourceBuffer, const FunctionInformation&amp; info, const Vector&lt;FunctionInformation&gt;&amp; functions)
</ins><span class="cx">     : Parser(sourceBuffer, info.start, info.end)
</span><span class="cx">     , m_context(context)
</span><span class="cx">     , m_signature(*info.signature)
</span><ins>+    , m_functions(functions)
</ins><span class="cx"> {
</span><span class="cx">     if (verbose)
</span><span class="cx">         dataLogLn(&quot;Parsing function starting at: &quot;, info.start, &quot; ending at: &quot;, info.end);
</span><span class="lines">@@ -101,8 +103,11 @@
</span><span class="cx"> {
</span><span class="cx">     while (true) {
</span><span class="cx">         uint8_t op;
</span><del>-        if (!parseUInt7(op) || !isValidOpType(op))
</del><ins>+        if (!parseUInt7(op) || !isValidOpType(op)) {
+            if (verbose)
+                WTF::dataLogLn(&quot;attempted to decode invalid op: &quot;, RawPointer(reinterpret_cast&lt;void*&gt;(op)), &quot; at offset: &quot;, RawPointer(reinterpret_cast&lt;void*&gt;(m_offset)));
</ins><span class="cx">             return false;
</span><ins>+        }
</ins><span class="cx"> 
</span><span class="cx">         if (verbose) {
</span><span class="cx">             dataLogLn(&quot;processing op (&quot;, m_unreachableBlocks, &quot;): &quot;,  RawPointer(reinterpret_cast&lt;void*&gt;(op)), &quot; at offset: &quot;, RawPointer(reinterpret_cast&lt;void*&gt;(m_offset)));
</span><span class="lines">@@ -193,6 +198,14 @@
</span><span class="cx">         return true;
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    case OpType::I64Const: {
+        uint64_t constant;
+        if (!parseVarUInt64(constant))
+            return false;
+        m_expressionStack.append(m_context.addConstant(I64, constant));
+        return true;
+    }
+
</ins><span class="cx">     case OpType::GetLocal: {
</span><span class="cx">         uint32_t index;
</span><span class="cx">         if (!parseVarUInt32(index))
</span><span class="lines">@@ -213,6 +226,30 @@
</span><span class="cx">         return m_context.setLocal(index, value);
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    case OpType::Call: {
+        uint32_t functionIndex;
+        if (!parseVarUInt32(functionIndex))
+            return false;
+
+        if (functionIndex &gt;= m_functions.size())
+            return false;
+
+        const FunctionInformation&amp; info = m_functions[functionIndex];
+
+        Vector&lt;ExpressionType&gt; args;
+        for (unsigned i = 0; i &lt; info.signature-&gt;arguments.size(); ++i)
+            args.append(m_expressionStack.takeLast());
+
+        ExpressionType result = Context::emptyExpression;
+        if (!m_context.addCall(functionIndex, info, args, result))
+            return false;
+
+        if (result != Context::emptyExpression)
+            m_expressionStack.append(result);
+
+        return true;
+    }
+
</ins><span class="cx">     case OpType::Block: {
</span><span class="cx">         Type inlineSignature;
</span><span class="cx">         if (!parseValueType(inlineSignature))
</span><span class="lines">@@ -281,12 +318,12 @@
</span><span class="cx">     case OpType::BrTable:
</span><span class="cx">     case OpType::Nop:
</span><span class="cx">     case OpType::Drop:
</span><del>-    case OpType::I64Const:
</del><span class="cx">     case OpType::F32Const:
</span><span class="cx">     case OpType::F64Const:
</span><span class="cx">     case OpType::TeeLocal:
</span><span class="cx">     case OpType::GetGlobal:
</span><span class="cx">     case OpType::SetGlobal:
</span><ins>+    case OpType::CallIndirect:
</ins><span class="cx">         // FIXME: Not yet implemented.
</span><span class="cx">         return false;
</span><span class="cx">     }
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorewasmWASMModuleParsercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/wasm/WASMModuleParser.cpp (207670 => 207671)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/wasm/WASMModuleParser.cpp        2016-10-21 15:51:28 UTC (rev 207670)
+++ trunk/Source/JavaScriptCore/wasm/WASMModuleParser.cpp        2016-10-21 16:02:39 UTC (rev 207671)
</span><span class="lines">@@ -82,7 +82,7 @@
</span><span class="cx">                 return false;
</span><span class="cx"> 
</span><span class="cx">             // Make sure we can read up to the section's size.
</span><del>-            if (m_offset + sectionNameLength + maxLEBByteLength &gt;= m_sourceLength)
</del><ins>+            if (m_offset + sectionNameLength + WTF::LEBDecoder::max32BitLEBByteLength &gt;= m_sourceLength)
</ins><span class="cx">                 return false;
</span><span class="cx"> 
</span><span class="cx">             // We don't support any custom sections yet.
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorewasmWASMOpsh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/wasm/WASMOps.h (207670 => 207671)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/wasm/WASMOps.h        2016-10-21 15:51:28 UTC (rev 207670)
+++ trunk/Source/JavaScriptCore/wasm/WASMOps.h        2016-10-21 16:02:39 UTC (rev 207671)
</span><span class="lines">@@ -42,7 +42,9 @@
</span><span class="cx">     macro(SetLocal, 0x15, Oops) \
</span><span class="cx">     macro(TeeLocal, 0x19, Oops) \
</span><span class="cx">     macro(GetGlobal, 0xbb, Oops) \
</span><del>-    macro(SetGlobal, 0xbc, Oops)
</del><ins>+    macro(SetGlobal, 0xbc, Oops) \
+    macro(Call, 0x16, Oops) \
+    macro(CallIndirect, 0x17, Oops)
</ins><span class="cx"> 
</span><span class="cx"> #define FOR_EACH_WASM_CONTROL_FLOW_OP(macro) \
</span><span class="cx">     macro(Unreachable, 0x0, Oops) \
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorewasmWASMParserh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/wasm/WASMParser.h (207670 => 207671)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/wasm/WASMParser.h        2016-10-21 15:51:28 UTC (rev 207670)
+++ trunk/Source/JavaScriptCore/wasm/WASMParser.h        2016-10-21 16:02:39 UTC (rev 207671)
</span><span class="lines">@@ -46,7 +46,8 @@
</span><span class="cx">     bool WARN_UNUSED_RETURN parseVarUInt1(uint8_t&amp; result);
</span><span class="cx">     bool WARN_UNUSED_RETURN parseUInt7(uint8_t&amp; result);
</span><span class="cx">     bool WARN_UNUSED_RETURN parseUInt32(uint32_t&amp; result);
</span><del>-    bool WARN_UNUSED_RETURN parseVarUInt32(uint32_t&amp; result) { return decodeUInt32(m_source.data(), m_sourceLength, m_offset, result); }
</del><ins>+    bool WARN_UNUSED_RETURN parseVarUInt32(uint32_t&amp; result) { return WTF::LEBDecoder::decodeUInt32(m_source.data(), m_sourceLength, m_offset, result); }
+    bool WARN_UNUSED_RETURN parseVarUInt64(uint64_t&amp; result) { return WTF::LEBDecoder::decodeUInt64(m_source.data(), m_sourceLength, m_offset, result); }
</ins><span class="cx"> 
</span><span class="cx"> 
</span><span class="cx">     bool WARN_UNUSED_RETURN parseValueType(Type&amp; result);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorewasmWASMPlancpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/wasm/WASMPlan.cpp (207670 => 207671)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/wasm/WASMPlan.cpp        2016-10-21 15:51:28 UTC (rev 207670)
+++ trunk/Source/JavaScriptCore/wasm/WASMPlan.cpp        2016-10-21 16:02:39 UTC (rev 207671)
</span><span class="lines">@@ -54,8 +54,16 @@
</span><span class="cx">     for (const FunctionInformation&amp; info : moduleParser.functionInformation()) {
</span><span class="cx">         if (verbose)
</span><span class="cx">             dataLogLn(&quot;Processing funcion starting at: &quot;, info.start, &quot; and ending at: &quot;, info.end);
</span><del>-        result.append(parseAndCompile(vm, source, moduleParser.memory().get(), info));
</del><ins>+        result.append(parseAndCompile(vm, source, moduleParser.memory().get(), info, moduleParser.functionInformation()));
</ins><span class="cx">     }
</span><ins>+
+    // Patch the call sites for each function.
+    for (std::unique_ptr&lt;FunctionCompilation&gt;&amp; functionPtr : result) {
+        FunctionCompilation* function = functionPtr.get();
+        for (auto&amp; call : function-&gt;unlinkedCalls)
+            MacroAssembler::repatchCall(call.callLocation, CodeLocationLabel(result[call.functionIndex]-&gt;code-&gt;code()));
+    }
+
</ins><span class="cx">     memory = WTFMove(moduleParser.memory());
</span><span class="cx"> }
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWTFChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WTF/ChangeLog (207670 => 207671)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WTF/ChangeLog        2016-10-21 15:51:28 UTC (rev 207670)
+++ trunk/Source/WTF/ChangeLog        2016-10-21 16:02:39 UTC (rev 207671)
</span><span class="lines">@@ -1,3 +1,20 @@
</span><ins>+2016-10-20  Keith Miller  &lt;keith_miller@apple.com&gt;
+
+        Add support for WASM calls
+        https://bugs.webkit.org/show_bug.cgi?id=161727
+
+        Reviewed by Filip Pizlo and Michael Saboff.
+
+        Added a new decodeUInt64. Also, added WTF::LEBDecoder namespace.
+
+        * wtf/LEBDecoder.h:
+        (WTF::LEBDecoder::decodeUInt):
+        (WTF::LEBDecoder::decodeUInt32):
+        (WTF::LEBDecoder::decodeUInt64):
+        (WTF::LEBDecoder::decodeInt32):
+        (decodeUInt32): Deleted.
+        (decodeInt32): Deleted.
+
</ins><span class="cx"> 2016-10-20  Filip Pizlo  &lt;fpizlo@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         The tracking of the coarse-grain Heap state (allocating or not, collector or not, eden vs full) should respect the orthogonality between allocating and collecting
</span></span></pre></div>
<a id="trunkSourceWTFwtfLEBDecoderh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WTF/wtf/LEBDecoder.h (207670 => 207671)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WTF/wtf/LEBDecoder.h        2016-10-21 15:51:28 UTC (rev 207670)
+++ trunk/Source/WTF/wtf/LEBDecoder.h        2016-10-21 16:02:39 UTC (rev 207671)
</span><span class="lines">@@ -32,14 +32,15 @@
</span><span class="cx"> // See https://en.wikipedia.org/wiki/LEB128 for more information about the
</span><span class="cx"> // LEB format.
</span><span class="cx"> 
</span><del>-const size_t maxLEBByteLength = 5;
</del><ins>+namespace WTF { namespace LEBDecoder {
</ins><span class="cx"> 
</span><del>-inline bool WARN_UNUSED_RETURN decodeUInt32(const uint8_t* bytes, size_t length, size_t&amp; offset, uint32_t&amp; result)
</del><ins>+template&lt;size_t maxByteLength, typename T&gt;
+inline bool WARN_UNUSED_RETURN decodeUInt(const uint8_t* bytes, size_t length, size_t&amp; offset, T&amp; result)
</ins><span class="cx"> {
</span><span class="cx">     ASSERT(length &gt; offset);
</span><span class="cx">     result = 0;
</span><span class="cx">     unsigned shift = 0;
</span><del>-    size_t last = std::min(maxLEBByteLength, length - offset - 1);
</del><ins>+    size_t last = std::min(maxByteLength, length - offset - 1);
</ins><span class="cx">     for (unsigned i = 0; true; ++i) {
</span><span class="cx">         uint8_t byte = bytes[offset++];
</span><span class="cx">         result |= (byte &amp; 0x7f) &lt;&lt; shift;
</span><span class="lines">@@ -53,12 +54,25 @@
</span><span class="cx">     return true;
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+const size_t max32BitLEBByteLength = 5;
+const size_t max64BitLEBByteLength = 10;
+
+inline bool WARN_UNUSED_RETURN decodeUInt32(const uint8_t* bytes, size_t length, size_t&amp; offset, uint32_t&amp; result)
+{
+    return decodeUInt&lt;max32BitLEBByteLength, uint32_t&gt;(bytes, length, offset, result);
+}
+
+inline bool WARN_UNUSED_RETURN decodeUInt64(const uint8_t* bytes, size_t length, size_t&amp; offset, uint64_t&amp; result)
+{
+    return decodeUInt&lt;max64BitLEBByteLength, uint64_t&gt;(bytes, length, offset, result);
+}
+
</ins><span class="cx"> inline bool WARN_UNUSED_RETURN decodeInt32(const uint8_t* bytes, size_t length, size_t&amp; offset, int32_t&amp; result)
</span><span class="cx"> {
</span><span class="cx">     ASSERT(length &gt; offset);
</span><span class="cx">     result = 0;
</span><span class="cx">     unsigned shift = 0;
</span><del>-    size_t last = std::min(maxLEBByteLength, length - offset - 1);
</del><ins>+    size_t last = std::min(max32BitLEBByteLength, length - offset - 1);
</ins><span class="cx">     uint8_t byte;
</span><span class="cx">     for (unsigned i = 0; true; ++i) {
</span><span class="cx">         byte = bytes[offset++];
</span><span class="lines">@@ -74,3 +88,5 @@
</span><span class="cx">         result |= ((-1u) &lt;&lt; shift);
</span><span class="cx">     return true;
</span><span class="cx"> }
</span><ins>+
+} } // WTF::LEBDecoder
</ins></span></pre>
</div>
</div>

</body>
</html>