<!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>[189303] trunk/Source/JavaScriptCore</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/189303">189303</a></dd>
<dt>Author</dt> <dd>commit-queue@webkit.org</dd>
<dt>Date</dt> <dd>2015-09-03 15:45:03 -0700 (Thu, 03 Sep 2015)</dd>
</dl>

<h3>Log Message</h3>
<pre>Implement some arithmetic instructions in WebAssembly
https://bugs.webkit.org/show_bug.cgi?id=148737

Patch by Sukolsak Sakshuwong &lt;sukolsak@gmail.com&gt; on 2015-09-03
Reviewed by Geoffrey Garen.

This patch implements the addition and subtraction instructions in
WebAssembly using a stack-based approach: each instruction reads its
operands from the top of the 'temporary' stack, pops them, and
optionally pushes a return value to the stack. Since operands are passed
on the stack, we don't use the arguments that are passed to the methods
of WASMFunctionCompiler, and we don't use the return values from these
methods. (We will use them when we implement LLVM IR generation for
WebAssembly, where each expression is an LLVMValueRef.)

* tests/stress/wasm-arithmetic.js: Added.
* tests/stress/wasm-arithmetic.wasm: Added.
* wasm/WASMFunctionCompiler.h:
(JSC::WASMFunctionCompiler::endFunction):
(JSC::WASMFunctionCompiler::buildReturn):
(JSC::WASMFunctionCompiler::buildImmediateI32):
(JSC::WASMFunctionCompiler::buildBinaryI32):
(JSC::WASMFunctionCompiler::temporaryAddress):
* wasm/WASMFunctionParser.cpp:
(JSC::WASMFunctionParser::parseReturnStatement):
(JSC::WASMFunctionParser::parseExpressionI32):
(JSC::WASMFunctionParser::parseImmediateExpressionI32):
(JSC::WASMFunctionParser::parseBinaryExpressionI32):
* wasm/WASMFunctionParser.h:
* wasm/WASMFunctionSyntaxChecker.h:
(JSC::WASMFunctionSyntaxChecker::startFunction):
(JSC::WASMFunctionSyntaxChecker::endFunction):
(JSC::WASMFunctionSyntaxChecker::buildReturn):
(JSC::WASMFunctionSyntaxChecker::buildImmediateI32):
(JSC::WASMFunctionSyntaxChecker::buildBinaryI32):
(JSC::WASMFunctionSyntaxChecker::stackHeight):
(JSC::WASMFunctionSyntaxChecker::updateTempStackHeight):</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkSourceJavaScriptCoreChangeLog">trunk/Source/JavaScriptCore/ChangeLog</a></li>
<li><a href="#trunkSourceJavaScriptCorewasmWASMFunctionCompilerh">trunk/Source/JavaScriptCore/wasm/WASMFunctionCompiler.h</a></li>
<li><a href="#trunkSourceJavaScriptCorewasmWASMFunctionParsercpp">trunk/Source/JavaScriptCore/wasm/WASMFunctionParser.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorewasmWASMFunctionParserh">trunk/Source/JavaScriptCore/wasm/WASMFunctionParser.h</a></li>
<li><a href="#trunkSourceJavaScriptCorewasmWASMFunctionSyntaxCheckerh">trunk/Source/JavaScriptCore/wasm/WASMFunctionSyntaxChecker.h</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#trunkSourceJavaScriptCoretestsstresswasmarithmeticjs">trunk/Source/JavaScriptCore/tests/stress/wasm-arithmetic.js</a></li>
<li><a href="#trunkSourceJavaScriptCoretestsstresswasmarithmeticwasm">trunk/Source/JavaScriptCore/tests/stress/wasm-arithmetic.wasm</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceJavaScriptCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ChangeLog (189302 => 189303)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ChangeLog        2015-09-03 22:39:38 UTC (rev 189302)
+++ trunk/Source/JavaScriptCore/ChangeLog        2015-09-03 22:45:03 UTC (rev 189303)
</span><span class="lines">@@ -1,3 +1,42 @@
</span><ins>+2015-09-03  Sukolsak Sakshuwong  &lt;sukolsak@gmail.com&gt;
+
+        Implement some arithmetic instructions in WebAssembly
+        https://bugs.webkit.org/show_bug.cgi?id=148737
+
+        Reviewed by Geoffrey Garen.
+
+        This patch implements the addition and subtraction instructions in
+        WebAssembly using a stack-based approach: each instruction reads its
+        operands from the top of the 'temporary' stack, pops them, and
+        optionally pushes a return value to the stack. Since operands are passed
+        on the stack, we don't use the arguments that are passed to the methods
+        of WASMFunctionCompiler, and we don't use the return values from these
+        methods. (We will use them when we implement LLVM IR generation for
+        WebAssembly, where each expression is an LLVMValueRef.)
+
+        * tests/stress/wasm-arithmetic.js: Added.
+        * tests/stress/wasm-arithmetic.wasm: Added.
+        * wasm/WASMFunctionCompiler.h:
+        (JSC::WASMFunctionCompiler::endFunction):
+        (JSC::WASMFunctionCompiler::buildReturn):
+        (JSC::WASMFunctionCompiler::buildImmediateI32):
+        (JSC::WASMFunctionCompiler::buildBinaryI32):
+        (JSC::WASMFunctionCompiler::temporaryAddress):
+        * wasm/WASMFunctionParser.cpp:
+        (JSC::WASMFunctionParser::parseReturnStatement):
+        (JSC::WASMFunctionParser::parseExpressionI32):
+        (JSC::WASMFunctionParser::parseImmediateExpressionI32):
+        (JSC::WASMFunctionParser::parseBinaryExpressionI32):
+        * wasm/WASMFunctionParser.h:
+        * wasm/WASMFunctionSyntaxChecker.h:
+        (JSC::WASMFunctionSyntaxChecker::startFunction):
+        (JSC::WASMFunctionSyntaxChecker::endFunction):
+        (JSC::WASMFunctionSyntaxChecker::buildReturn):
+        (JSC::WASMFunctionSyntaxChecker::buildImmediateI32):
+        (JSC::WASMFunctionSyntaxChecker::buildBinaryI32):
+        (JSC::WASMFunctionSyntaxChecker::stackHeight):
+        (JSC::WASMFunctionSyntaxChecker::updateTempStackHeight):
+
</ins><span class="cx"> 2015-09-03  Brian Burg  &lt;bburg@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Web Inspector: should crash on purpose if InjectedScriptSource.js is unparseable
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoretestsstresswasmarithmeticjs"></a>
<div class="addfile"><h4>Added: trunk/Source/JavaScriptCore/tests/stress/wasm-arithmetic.js (0 => 189303)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/tests/stress/wasm-arithmetic.js                                (rev 0)
+++ trunk/Source/JavaScriptCore/tests/stress/wasm-arithmetic.js        2015-09-03 22:45:03 UTC (rev 189303)
</span><span class="lines">@@ -0,0 +1,22 @@
</span><ins>+//@ skip
+
+/*
+wasm-arithmetic.wasm is generated by pack-asmjs &lt;https://github.com/WebAssembly/polyfill-prototype-1&gt; from the following script:
+
+function asmModule(global, env, buffer) {
+    &quot;use asm&quot;;
+
+    function main() {
+        return (10 + 40) - 8;
+    }
+
+    return {
+        main: main
+    };
+}
+*/
+
+var module = loadWebAssembly(&quot;wasm-arithmetic.wasm&quot;);
+var result = module.main();
+if (result != 42)
+    throw &quot;Error: bad result: &quot; + result;
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCoretestsstresswasmarithmeticwasm"></a>
<div class="addfile"><h4>Added: trunk/Source/JavaScriptCore/tests/stress/wasm-arithmetic.wasm (0 => 189303)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/tests/stress/wasm-arithmetic.wasm                                (rev 0)
+++ trunk/Source/JavaScriptCore/tests/stress/wasm-arithmetic.wasm        2015-09-03 22:45:03 UTC (rev 189303)
</span><span class="lines">@@ -0,0 +1 @@
</span><ins>+wasm\xF8\x80\xAA(\xA8main
</ins><span class="cx">\ No newline at end of file
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorewasmWASMFunctionCompilerh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/wasm/WASMFunctionCompiler.h (189302 => 189303)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/wasm/WASMFunctionCompiler.h        2015-09-03 22:39:38 UTC (rev 189302)
+++ trunk/Source/JavaScriptCore/wasm/WASMFunctionCompiler.h        2015-09-03 22:45:03 UTC (rev 189303)
</span><span class="lines">@@ -33,6 +33,8 @@
</span><span class="cx"> #include &quot;LinkBuffer.h&quot;
</span><span class="cx"> #include &quot;MaxFrameExtentForSlowPathCall.h&quot;
</span><span class="cx"> 
</span><ins>+#define UNUSED 0
+
</ins><span class="cx"> namespace JSC {
</span><span class="cx"> 
</span><span class="cx"> class WASMFunctionCompiler : private CCallHelpers {
</span><span class="lines">@@ -40,12 +42,6 @@
</span><span class="cx">     typedef int Expression;
</span><span class="cx">     typedef int Statement;
</span><span class="cx"> 
</span><del>-    union StackSlot {
-        int32_t intValue;
-        float floatValue;
-        double doubleValue;
-    };
-
</del><span class="cx">     WASMFunctionCompiler(VM&amp; vm, CodeBlock* codeBlock, unsigned stackHeight)
</span><span class="cx">         : CCallHelpers(&amp;vm, codeBlock)
</span><span class="cx">         , m_stackHeight(stackHeight)
</span><span class="lines">@@ -102,6 +98,8 @@
</span><span class="cx"> 
</span><span class="cx">     void endFunction()
</span><span class="cx">     {
</span><ins>+        ASSERT(!m_tempStackTop);
+
</ins><span class="cx">         // FIXME: Remove these if the last statement is a return statement.
</span><span class="cx">         move(TrustedImm64(JSValue::encode(jsUndefined())), GPRInfo::returnValueGPR);
</span><span class="cx">         emitFunctionEpilogue();
</span><span class="lines">@@ -129,13 +127,68 @@
</span><span class="cx">         m_codeBlock-&gt;capabilityLevel();
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    void buildReturn(int, WASMExpressionType returnType)
+    {
+        switch (returnType) {
+        case WASMExpressionType::I32:
+            load32(temporaryAddress(m_tempStackTop - 1), GPRInfo::returnValueGPR);
+            or64(GPRInfo::tagTypeNumberRegister, GPRInfo::returnValueGPR);
+            m_tempStackTop--;
+            break;
+        case WASMExpressionType::Void:
+            move(TrustedImm64(JSValue::encode(jsUndefined())), GPRInfo::returnValueGPR);
+            break;
+        default:
+            ASSERT_NOT_REACHED();
+        }
+        emitFunctionEpilogue();
+        ret();
+    }
+
+    int buildImmediateI32(uint32_t immediate)
+    {
+        store32(TrustedImm32(immediate), temporaryAddress(m_tempStackTop++));
+        return UNUSED;
+    }
+
+    int buildBinaryI32(int, int, WASMOpExpressionI32 op)
+    {
+        load32(temporaryAddress(m_tempStackTop - 2), GPRInfo::regT0);
+        load32(temporaryAddress(m_tempStackTop - 1), GPRInfo::regT1);
+        switch (op) {
+        case WASMOpExpressionI32::Add:
+            add32(GPRInfo::regT1, GPRInfo::regT0);
+            break;
+        case WASMOpExpressionI32::Sub:
+            sub32(GPRInfo::regT1, GPRInfo::regT0);
+            break;
+        default:
+            ASSERT_NOT_REACHED();
+        }
+        m_tempStackTop--;
+        store32(GPRInfo::regT0, temporaryAddress(m_tempStackTop - 1));
+        return UNUSED;
+    }
+
</ins><span class="cx"> private:
</span><ins>+    union StackSlot {
+        int32_t intValue;
+        float floatValue;
+        double doubleValue;
+    };
+
</ins><span class="cx">     Address localAddress(unsigned localIndex) const
</span><span class="cx">     {
</span><span class="cx">         ASSERT(localIndex &lt; m_numberOfLocals);
</span><span class="cx">         return Address(GPRInfo::callFrameRegister, -(localIndex + 1) * sizeof(StackSlot));
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    Address temporaryAddress(unsigned temporaryIndex) const
+    {
+        ASSERT(m_numberOfLocals + temporaryIndex &lt; m_stackHeight);
+        return Address(GPRInfo::callFrameRegister, -(m_numberOfLocals + temporaryIndex + 1) * sizeof(StackSlot));
+    }
+
</ins><span class="cx">     void throwStackOverflowError()
</span><span class="cx">     {
</span><span class="cx">         setupArgumentsWithExecState(TrustedImmPtr(m_codeBlock));
</span><span class="lines">@@ -156,6 +209,7 @@
</span><span class="cx"> 
</span><span class="cx">     unsigned m_stackHeight;
</span><span class="cx">     unsigned m_numberOfLocals;
</span><ins>+    unsigned m_tempStackTop { 0 };
</ins><span class="cx"> 
</span><span class="cx">     Label m_beginLabel;
</span><span class="cx">     Jump m_stackOverflow;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorewasmWASMFunctionParsercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/wasm/WASMFunctionParser.cpp (189302 => 189303)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/wasm/WASMFunctionParser.cpp        2015-09-03 22:39:38 UTC (rev 189302)
+++ trunk/Source/JavaScriptCore/wasm/WASMFunctionParser.cpp        2015-09-03 22:45:03 UTC (rev 189303)
</span><span class="lines">@@ -226,9 +226,12 @@
</span><span class="cx"> template &lt;class Context&gt;
</span><span class="cx"> ContextStatement WASMFunctionParser::parseReturnStatement(Context&amp; context)
</span><span class="cx"> {
</span><del>-    if (m_returnType != WASMExpressionType::Void)
-        parseExpression(context, m_returnType);
-    // FIXME: Implement this instruction.
</del><ins>+    ContextExpression expression = 0;
+    if (m_returnType != WASMExpressionType::Void) {
+        expression = parseExpression(context, m_returnType);
+        PROPAGATE_ERROR();
+    }
+    context.buildReturn(expression, m_returnType);
</ins><span class="cx">     return UNUSED;
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -422,6 +425,9 @@
</span><span class="cx">         switch (op) {
</span><span class="cx">         case WASMOpExpressionI32::Immediate:
</span><span class="cx">             return parseImmediateExpressionI32(context);
</span><ins>+        case WASMOpExpressionI32::Add:
+        case WASMOpExpressionI32::Sub:
+            return parseBinaryExpressionI32(context, op);
</ins><span class="cx">         case WASMOpExpressionI32::ConstantPoolIndex:
</span><span class="cx">         case WASMOpExpressionI32::GetLocal:
</span><span class="cx">         case WASMOpExpressionI32::GetGlobal:
</span><span class="lines">@@ -451,8 +457,6 @@
</span><span class="cx">         case WASMOpExpressionI32::FromF32:
</span><span class="cx">         case WASMOpExpressionI32::FromF64:
</span><span class="cx">         case WASMOpExpressionI32::Negate:
</span><del>-        case WASMOpExpressionI32::Add:
-        case WASMOpExpressionI32::Sub:
</del><span class="cx">         case WASMOpExpressionI32::Mul:
</span><span class="cx">         case WASMOpExpressionI32::SDiv:
</span><span class="cx">         case WASMOpExpressionI32::UDiv:
</span><span class="lines">@@ -515,10 +519,9 @@
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> template &lt;class Context&gt;
</span><del>-ContextExpression WASMFunctionParser::parseImmediateExpressionI32(Context&amp;, uint32_t)
</del><ins>+ContextExpression WASMFunctionParser::parseImmediateExpressionI32(Context&amp; context, uint32_t immediate)
</ins><span class="cx"> {
</span><del>-    // FIXME: Implement this instruction.
-    return UNUSED;
</del><ins>+    return context.buildImmediateI32(immediate);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> template &lt;class Context&gt;
</span><span class="lines">@@ -529,6 +532,16 @@
</span><span class="cx">     return parseImmediateExpressionI32(context, immediate);
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+template &lt;class Context&gt;
+ContextExpression WASMFunctionParser::parseBinaryExpressionI32(Context&amp; context, WASMOpExpressionI32 op)
+{
+    ContextExpression left = parseExpressionI32(context);
+    PROPAGATE_ERROR();
+    ContextExpression right = parseExpressionI32(context);
+    PROPAGATE_ERROR();
+    return context.buildBinaryI32(left, right, op);
+}
+
</ins><span class="cx"> } // namespace JSC
</span><span class="cx"> 
</span><span class="cx"> #endif // ENABLE(WEBASSEMBLY)
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorewasmWASMFunctionParserh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/wasm/WASMFunctionParser.h (189302 => 189303)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/wasm/WASMFunctionParser.h        2015-09-03 22:39:38 UTC (rev 189302)
+++ trunk/Source/JavaScriptCore/wasm/WASMFunctionParser.h        2015-09-03 22:45:03 UTC (rev 189303)
</span><span class="lines">@@ -80,6 +80,7 @@
</span><span class="cx">     template &lt;class Context&gt; ContextExpression parseExpressionI32(Context&amp;);
</span><span class="cx">     template &lt;class Context&gt; ContextExpression parseImmediateExpressionI32(Context&amp;, uint32_t immediate);
</span><span class="cx">     template &lt;class Context&gt; ContextExpression parseImmediateExpressionI32(Context&amp;);
</span><ins>+    template &lt;class Context&gt; ContextExpression parseBinaryExpressionI32(Context&amp;, WASMOpExpressionI32);
</ins><span class="cx"> 
</span><span class="cx">     JSWASMModule* m_module;
</span><span class="cx">     WASMReader m_reader;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorewasmWASMFunctionSyntaxCheckerh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/wasm/WASMFunctionSyntaxChecker.h (189302 => 189303)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/wasm/WASMFunctionSyntaxChecker.h        2015-09-03 22:39:38 UTC (rev 189302)
+++ trunk/Source/JavaScriptCore/wasm/WASMFunctionSyntaxChecker.h        2015-09-03 22:45:03 UTC (rev 189303)
</span><span class="lines">@@ -28,6 +28,8 @@
</span><span class="cx"> 
</span><span class="cx"> #if ENABLE(WEBASSEMBLY)
</span><span class="cx"> 
</span><ins>+#define UNUSED 0
+
</ins><span class="cx"> namespace JSC {
</span><span class="cx"> 
</span><span class="cx"> class WASMFunctionSyntaxChecker {
</span><span class="lines">@@ -37,16 +39,48 @@
</span><span class="cx"> 
</span><span class="cx">     void startFunction(const Vector&lt;WASMType&gt;&amp; arguments, uint32_t numberOfI32LocalVariables, uint32_t numberOfF32LocalVariables, uint32_t numberOfF64LocalVariables)
</span><span class="cx">     {
</span><del>-        // FIXME: Need to include the number of temporaries used.
-        m_stackHeight = arguments.size() + numberOfI32LocalVariables + numberOfF32LocalVariables + numberOfF64LocalVariables;
</del><ins>+        m_numberOfLocals = arguments.size() + numberOfI32LocalVariables + numberOfF32LocalVariables + numberOfF64LocalVariables;
</ins><span class="cx">     }
</span><span class="cx"> 
</span><del>-    void endFunction() { }
</del><ins>+    void endFunction()
+    {
+        ASSERT(!m_tempStackTop);
+    }
</ins><span class="cx"> 
</span><del>-    unsigned stackHeight() { return m_stackHeight; }
</del><ins>+    void buildReturn(int, WASMExpressionType returnType)
+    {
+        if (returnType != WASMExpressionType::Void)
+            m_tempStackTop--;
+    }
</ins><span class="cx"> 
</span><ins>+    int buildImmediateI32(uint32_t)
+    {
+        m_tempStackTop++;
+        updateTempStackHeight();
+        return UNUSED;
+    }
+
+    int buildBinaryI32(int, int, WASMOpExpressionI32)
+    {
+        m_tempStackTop--;
+        return UNUSED;
+    }
+
+    unsigned stackHeight()
+    {
+        return m_numberOfLocals + m_tempStackHeight;
+    }
+
</ins><span class="cx"> private:
</span><del>-    unsigned m_stackHeight;
</del><ins>+    void updateTempStackHeight()
+    {
+        if (m_tempStackTop &gt; m_tempStackHeight)
+            m_tempStackHeight = m_tempStackTop;
+    }
+
+    unsigned m_numberOfLocals;
+    unsigned m_tempStackTop { 0 };
+    unsigned m_tempStackHeight { 0 };
</ins><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> } // namespace JSC
</span></span></pre>
</div>
</div>

</body>
</html>