<!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>[209696] 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/209696">209696</a></dd>
<dt>Author</dt> <dd>sbarati@apple.com</dd>
<dt>Date</dt> <dd>2016-12-11 19:11:18 -0800 (Sun, 11 Dec 2016)</dd>
</dl>

<h3>Log Message</h3>
<pre>We should be able to throw exceptions from Wasm code and when Wasm frames are on the stack
https://bugs.webkit.org/show_bug.cgi?id=165429

Reviewed by Keith Miller.

JSTests:

* wasm/function-tests/trap-load.js: Added.
(assert):
(wasmFrameCountFromError):
(i.catch):
(assert.continuation):
* wasm/function-tests/trap-store.js: Added.
(import.Builder.from.string_appeared_here.assert):
(i.catch):
(assert.continuation):
(assert):
* wasm/js-api/test_memory_constructor.js:
(assert):

Source/JavaScriptCore:

This patch teaches the stack walking runtime about wasm.
To do this, I taught StackVisitor that a callee is not
always an object.

To be able to unwind callee save registers properly, I've given
JSWebAssemblyCallee a list of RegisterAtOffsetList for the callee
saves that B3 saved in the prologue. Also, because we have two
B3Compilations per wasm function, one for wasm entrypoint, and
one for the JS entrypoint, I needed to create a callee for each
because they each might spill callee save registers.

I also fixed a bug inside the Wasm::Memory constructor where we
were trying to mmap the same number of bytes even after the first
mmap failed. We should start by trying to mmap the maximum bytes,
and if that fails, fall back to the specified initial bytes. However,
the code was just mmapping the maximum twice. I've fixed that and
also added a RELEASE_ASSERT_NOT_REACHED() for when the second mmap
fails along with a FIXME to throw an OOM error.

There was a second bug I fixed where JSModuleRecord was calling
visitWeak on its CallLinkInfos inside ::visitChldren(). It needs
to do this after marking. I changed JSModuleRecord to do what
CodeBlock does and call visitWeak on its CallLinkInfos inside
an UnconditionalFinalizer.

* API/JSContextRef.cpp:
(BacktraceFunctor::operator()):
* inspector/ScriptCallStackFactory.cpp:
(Inspector::createScriptCallStackFromException):
* interpreter/CallFrame.cpp:
(JSC::CallFrame::vmEntryGlobalObject):
* interpreter/CallFrame.h:
(JSC::ExecState::callee):
* interpreter/Interpreter.cpp:
(JSC::GetStackTraceFunctor::operator()):
(JSC::UnwindFunctor::operator()):
(JSC::UnwindFunctor::copyCalleeSavesToVMEntryFrameCalleeSavesBuffer):
* interpreter/Interpreter.h:
* interpreter/ShadowChicken.cpp:
(JSC::ShadowChicken::update):
* interpreter/StackVisitor.cpp:
(JSC::StackVisitor::StackVisitor):
(JSC::StackVisitor::readFrame):
(JSC::StackVisitor::readNonInlinedFrame):
(JSC::StackVisitor::readInlinedFrame):
(JSC::StackVisitor::Frame::isWasmFrame):
(JSC::StackVisitor::Frame::codeType):
(JSC::StackVisitor::Frame::calleeSaveRegisters):
(JSC::StackVisitor::Frame::functionName):
(JSC::StackVisitor::Frame::sourceURL):
(JSC::StackVisitor::Frame::toString):
(JSC::StackVisitor::Frame::hasLineAndColumnInfo):
(JSC::StackVisitor::Frame::setToEnd):
* interpreter/StackVisitor.h:
(JSC::StackVisitor::Frame::callee):
(JSC::StackVisitor::Frame::isNativeFrame):
(JSC::StackVisitor::Frame::isJSFrame): Deleted.
* jsc.cpp:
(callWasmFunction):
(functionTestWasmModuleFunctions):
* runtime/Error.cpp:
(JSC::addErrorInfoAndGetBytecodeOffset):
* runtime/JSCell.cpp:
(JSC::JSCell::isAnyWasmCallee):
* runtime/JSCell.h:
* runtime/JSFunction.cpp:
(JSC::RetrieveArgumentsFunctor::operator()):
(JSC::RetrieveCallerFunctionFunctor::operator()):
* runtime/StackFrame.cpp:
(JSC::StackFrame::sourceID):
(JSC::StackFrame::sourceURL):
(JSC::StackFrame::functionName):
(JSC::StackFrame::computeLineAndColumn):
(JSC::StackFrame::toString):
* runtime/StackFrame.h:
(JSC::StackFrame::StackFrame):
(JSC::StackFrame::hasLineAndColumnInfo):
(JSC::StackFrame::hasBytecodeOffset):
(JSC::StackFrame::bytecodeOffset):
(JSC::StackFrame::isNative): Deleted.
* runtime/VM.h:
* wasm/WasmB3IRGenerator.cpp:
(JSC::Wasm::B3IRGenerator::B3IRGenerator):
(JSC::Wasm::createJSToWasmWrapper):
(JSC::Wasm::parseAndCompile):
* wasm/WasmCallingConvention.h:
(JSC::Wasm::CallingConvention::setupFrameInPrologue):
* wasm/WasmFormat.h:
* wasm/WasmMemory.cpp:
(JSC::Wasm::Memory::Memory):
* wasm/WasmMemory.h:
(JSC::Wasm::Memory::isValid):
* wasm/WasmPlan.cpp:
(JSC::Wasm::Plan::run):
(JSC::Wasm::Plan::initializeCallees):
* wasm/WasmPlan.h:
(JSC::Wasm::Plan::jsToWasmEntryPointForFunction): Deleted.
* wasm/js/JSWebAssemblyCallee.cpp:
(JSC::JSWebAssemblyCallee::finishCreation):
* wasm/js/JSWebAssemblyCallee.h:
(JSC::JSWebAssemblyCallee::create):
(JSC::JSWebAssemblyCallee::entrypoint):
(JSC::JSWebAssemblyCallee::calleeSaveRegisters):
(JSC::JSWebAssemblyCallee::jsToWasmEntryPoint): Deleted.
* wasm/js/JSWebAssemblyModule.cpp:
(JSC::JSWebAssemblyModule::JSWebAssemblyModule):
(JSC::JSWebAssemblyModule::visitChildren):
(JSC::JSWebAssemblyModule::UnconditionalFinalizer::finalizeUnconditionally):
* wasm/js/JSWebAssemblyModule.h:
(JSC::JSWebAssemblyModule::jsEntrypointCalleeFromFunctionIndexSpace):
(JSC::JSWebAssemblyModule::wasmEntrypointCalleeFromFunctionIndexSpace):
(JSC::JSWebAssemblyModule::setJSEntrypointCallee):
(JSC::JSWebAssemblyModule::setWasmEntrypointCallee):
(JSC::JSWebAssemblyModule::allocationSize):
(JSC::JSWebAssemblyModule::calleeFromFunctionIndexSpace): Deleted.
* wasm/js/JSWebAssemblyRuntimeError.h:
* wasm/js/WebAssemblyFunction.cpp:
(JSC::WebAssemblyFunction::call):
* wasm/js/WebAssemblyInstanceConstructor.cpp:
(JSC::constructJSWebAssemblyInstance):
* wasm/js/WebAssemblyMemoryConstructor.cpp:
(JSC::constructJSWebAssemblyMemory):
* wasm/js/WebAssemblyModuleConstructor.cpp:
(JSC::constructJSWebAssemblyModule):
* wasm/js/WebAssemblyModuleRecord.cpp:
(JSC::WebAssemblyModuleRecord::link):

Source/WebCore:

* bindings/js/JSDOMBinding.cpp:
(WebCore::GetCallerGlobalObjectFunctor::operator()):</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkJSTestsChangeLog">trunk/JSTests/ChangeLog</a></li>
<li><a href="#trunkJSTestswasmjsapitest_memory_constructorjs">trunk/JSTests/wasm/js-api/test_memory_constructor.js</a></li>
<li><a href="#trunkSourceJavaScriptCoreAPIJSContextRefcpp">trunk/Source/JavaScriptCore/API/JSContextRef.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreChangeLog">trunk/Source/JavaScriptCore/ChangeLog</a></li>
<li><a href="#trunkSourceJavaScriptCoreinspectorScriptCallStackFactorycpp">trunk/Source/JavaScriptCore/inspector/ScriptCallStackFactory.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreinterpreterCallFramecpp">trunk/Source/JavaScriptCore/interpreter/CallFrame.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreinterpreterCallFrameh">trunk/Source/JavaScriptCore/interpreter/CallFrame.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreinterpreterInterpretercpp">trunk/Source/JavaScriptCore/interpreter/Interpreter.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreinterpreterInterpreterh">trunk/Source/JavaScriptCore/interpreter/Interpreter.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreinterpreterShadowChickencpp">trunk/Source/JavaScriptCore/interpreter/ShadowChicken.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreinterpreterStackVisitorcpp">trunk/Source/JavaScriptCore/interpreter/StackVisitor.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreinterpreterStackVisitorh">trunk/Source/JavaScriptCore/interpreter/StackVisitor.h</a></li>
<li><a href="#trunkSourceJavaScriptCorejsccpp">trunk/Source/JavaScriptCore/jsc.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeErrorcpp">trunk/Source/JavaScriptCore/runtime/Error.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeJSCellcpp">trunk/Source/JavaScriptCore/runtime/JSCell.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeJSCellh">trunk/Source/JavaScriptCore/runtime/JSCell.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeJSFunctioncpp">trunk/Source/JavaScriptCore/runtime/JSFunction.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeStackFramecpp">trunk/Source/JavaScriptCore/runtime/StackFrame.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeStackFrameh">trunk/Source/JavaScriptCore/runtime/StackFrame.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeVMh">trunk/Source/JavaScriptCore/runtime/VM.h</a></li>
<li><a href="#trunkSourceJavaScriptCorewasmWasmB3IRGeneratorcpp">trunk/Source/JavaScriptCore/wasm/WasmB3IRGenerator.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorewasmWasmCallingConventionh">trunk/Source/JavaScriptCore/wasm/WasmCallingConvention.h</a></li>
<li><a href="#trunkSourceJavaScriptCorewasmWasmFormath">trunk/Source/JavaScriptCore/wasm/WasmFormat.h</a></li>
<li><a href="#trunkSourceJavaScriptCorewasmWasmMemorycpp">trunk/Source/JavaScriptCore/wasm/WasmMemory.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorewasmWasmMemoryh">trunk/Source/JavaScriptCore/wasm/WasmMemory.h</a></li>
<li><a href="#trunkSourceJavaScriptCorewasmWasmPlancpp">trunk/Source/JavaScriptCore/wasm/WasmPlan.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorewasmWasmPlanh">trunk/Source/JavaScriptCore/wasm/WasmPlan.h</a></li>
<li><a href="#trunkSourceJavaScriptCorewasmjsJSWebAssemblyCalleecpp">trunk/Source/JavaScriptCore/wasm/js/JSWebAssemblyCallee.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorewasmjsJSWebAssemblyCalleeh">trunk/Source/JavaScriptCore/wasm/js/JSWebAssemblyCallee.h</a></li>
<li><a href="#trunkSourceJavaScriptCorewasmjsJSWebAssemblyModulecpp">trunk/Source/JavaScriptCore/wasm/js/JSWebAssemblyModule.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorewasmjsJSWebAssemblyModuleh">trunk/Source/JavaScriptCore/wasm/js/JSWebAssemblyModule.h</a></li>
<li><a href="#trunkSourceJavaScriptCorewasmjsJSWebAssemblyRuntimeErrorh">trunk/Source/JavaScriptCore/wasm/js/JSWebAssemblyRuntimeError.h</a></li>
<li><a href="#trunkSourceJavaScriptCorewasmjsWebAssemblyFunctioncpp">trunk/Source/JavaScriptCore/wasm/js/WebAssemblyFunction.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorewasmjsWebAssemblyInstanceConstructorcpp">trunk/Source/JavaScriptCore/wasm/js/WebAssemblyInstanceConstructor.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorewasmjsWebAssemblyMemoryConstructorcpp">trunk/Source/JavaScriptCore/wasm/js/WebAssemblyMemoryConstructor.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorewasmjsWebAssemblyModuleConstructorcpp">trunk/Source/JavaScriptCore/wasm/js/WebAssemblyModuleConstructor.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorewasmjsWebAssemblyModuleRecordcpp">trunk/Source/JavaScriptCore/wasm/js/WebAssemblyModuleRecord.cpp</a></li>
<li><a href="#trunkSourceWebCoreChangeLog">trunk/Source/WebCore/ChangeLog</a></li>
<li><a href="#trunkSourceWebCorebindingsjsJSDOMBindingcpp">trunk/Source/WebCore/bindings/js/JSDOMBinding.cpp</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#trunkJSTestswasmfunctionteststraploadjs">trunk/JSTests/wasm/function-tests/trap-load.js</a></li>
<li><a href="#trunkJSTestswasmfunctionteststrapstorejs">trunk/JSTests/wasm/function-tests/trap-store.js</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkJSTestsChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/JSTests/ChangeLog (209695 => 209696)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JSTests/ChangeLog        2016-12-12 02:50:06 UTC (rev 209695)
+++ trunk/JSTests/ChangeLog        2016-12-12 03:11:18 UTC (rev 209696)
</span><span class="lines">@@ -1,3 +1,23 @@
</span><ins>+2016-12-11  Saam Barati  &lt;sbarati@apple.com&gt;
+
+        We should be able to throw exceptions from Wasm code and when Wasm frames are on the stack
+        https://bugs.webkit.org/show_bug.cgi?id=165429
+
+        Reviewed by Keith Miller.
+
+        * wasm/function-tests/trap-load.js: Added.
+        (assert):
+        (wasmFrameCountFromError):
+        (i.catch):
+        (assert.continuation):
+        * wasm/function-tests/trap-store.js: Added.
+        (import.Builder.from.string_appeared_here.assert):
+        (i.catch):
+        (assert.continuation):
+        (assert):
+        * wasm/js-api/test_memory_constructor.js:
+        (assert):
+
</ins><span class="cx"> 2016-12-10  Commit Queue  &lt;commit-queue@webkit.org&gt;
</span><span class="cx"> 
</span><span class="cx">         Unreviewed, rolling out r209653, r209654, r209663, and
</span></span></pre></div>
<a id="trunkJSTestswasmfunctionteststraploadjs"></a>
<div class="addfile"><h4>Added: trunk/JSTests/wasm/function-tests/trap-load.js (0 => 209696)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JSTests/wasm/function-tests/trap-load.js                                (rev 0)
+++ trunk/JSTests/wasm/function-tests/trap-load.js        2016-12-12 03:11:18 UTC (rev 209696)
</span><span class="lines">@@ -0,0 +1,104 @@
</span><ins>+import Builder from '../Builder.js'
+
+const pageSize = 64 * 1024;
+const numPages = 10;
+
+const builder = (new Builder())
+    .Type().End()
+    .Import()
+        .Memory(&quot;a&quot;, &quot;b&quot;, {initial: numPages})
+    .End()
+    .Function().End()
+    .Export().Function(&quot;foo&quot;).End()
+    .Code()
+        .Function(&quot;foo&quot;, {params: [&quot;i32&quot;], ret: &quot;i32&quot;})
+            .GetLocal(0)
+            .I32Load(2, 0)
+            .Return()
+        .End()
+    .End();
+
+const bin = builder.WebAssembly().get();
+const module = new WebAssembly.Module(bin);
+const foo = new WebAssembly.Instance(module, {a: {b: new WebAssembly.Memory({initial: numPages})}}).exports.foo;
+
+function assert(b) {
+    if (!b)
+        throw new Error(&quot;Bad&quot;)
+}
+
+function wasmFrameCountFromError(e) {
+    let stackFrames = e.stack.split(&quot;\n&quot;).filter((s) =&gt; s.indexOf(&quot;&lt;wasm&gt;@[wasm code]&quot;) !== -1);
+    return stackFrames.length;
+}
+
+for (let i = 0; i &lt; 1000; i++) {
+    let threw = false;
+    try {
+        foo(numPages * pageSize + 1);
+    } catch(e) {
+        assert(e instanceof WebAssembly.RuntimeError);
+        assert(e.message === &quot;Out of bounds memory access&quot;);
+        threw = true;
+        assert(wasmFrameCountFromError(e) === 2);
+    }
+    assert(threw);
+}
+
+{
+    const builder = (new Builder())
+        .Type().End()
+        .Import()
+            .Memory(&quot;imp&quot;, &quot;mem&quot;, {initial: numPages})
+            .Function(&quot;imp&quot;, &quot;func&quot;, { params: [&quot;i32&quot;] })
+        .End()
+        .Function().End()
+        .Export().Function(&quot;foo&quot;).End()
+        .Code()
+            .Function(&quot;foo&quot;, {params: [&quot;i32&quot;, &quot;i32&quot;]})
+                .GetLocal(0)
+                .I32Const(0)
+                .I32Eq()
+                .If(&quot;void&quot;, b =&gt;
+                    b.GetLocal(1)
+                    .GetLocal(1)
+                    .I32Load(2, 0)
+                    .Br(0)
+                    .Else()
+                        .GetLocal(0)
+                        .Call(0)
+                    .Br(0)
+                   )
+            .End()
+        .End();
+
+    const bin = builder.WebAssembly().get();
+    const module = new WebAssembly.Module(bin);
+    const imp = {
+        imp: {
+            mem: new WebAssembly.Memory({initial: numPages}),
+            func: continuation
+        }
+    };
+    const foo = new WebAssembly.Instance(module, imp).exports.foo;
+    const address = numPages*pageSize + 1;
+    function continuation(x) {
+        foo(x - 1, address);
+    }
+
+    for (let i = 0; i &lt; 10000; i++) {
+        let threw = false;
+        try {
+            foo(25, address);
+        } catch(e) {
+            assert(e instanceof WebAssembly.RuntimeError);
+            assert(e.message === &quot;Out of bounds memory access&quot;);
+            // There are 25 total calls, and each call does:
+            // JS entry, wasm entry, js call stub.
+            // The last call that traps just has JS entry and wasm entry.
+            assert(wasmFrameCountFromError(e) === 25 * 3 + 2);
+            threw = true;
+        }
+        assert(threw);
+    }
+}
</ins></span></pre></div>
<a id="trunkJSTestswasmfunctionteststrapstorejs"></a>
<div class="addfile"><h4>Added: trunk/JSTests/wasm/function-tests/trap-store.js (0 => 209696)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JSTests/wasm/function-tests/trap-store.js                                (rev 0)
+++ trunk/JSTests/wasm/function-tests/trap-store.js        2016-12-12 03:11:18 UTC (rev 209696)
</span><span class="lines">@@ -0,0 +1,97 @@
</span><ins>+import Builder from '../Builder.js'
+
+function assert(b) {
+    if (!b)
+        throw new Error(&quot;Bad&quot;)
+}
+
+const pageSize = 64 * 1024;
+const numPages = 10;
+
+{
+    const builder = (new Builder())
+        .Type().End()
+        .Import()
+            .Memory(&quot;a&quot;, &quot;b&quot;, {initial: numPages})
+        .End()
+        .Function().End()
+        .Export().Function(&quot;foo&quot;).End()
+        .Code()
+            .Function(&quot;foo&quot;, {params: [&quot;i32&quot;, &quot;i32&quot;]})
+                .GetLocal(1)
+                .GetLocal(0)
+                .I32Store(2, 0)
+            .End()
+        .End();
+
+    const bin = builder.WebAssembly().get();
+    const module = new WebAssembly.Module(bin);
+    const foo = new WebAssembly.Instance(module, {a: {b: new WebAssembly.Memory({initial: numPages})}}).exports.foo;
+
+    for (let i = 0; i &lt; 10000; i++) {
+        let threw = false;
+        try {
+            foo(i, numPages * pageSize + 1);
+        } catch(e) {
+            assert(e instanceof WebAssembly.RuntimeError);
+            assert(e.message === &quot;Out of bounds memory access&quot;);
+            threw = true;
+        }
+        assert(threw);
+    }
+}
+
+
+{
+    const builder = (new Builder())
+        .Type().End()
+        .Import()
+            .Memory(&quot;imp&quot;, &quot;mem&quot;, {initial: numPages})
+            .Function(&quot;imp&quot;, &quot;func&quot;, { params: [&quot;i32&quot;] })
+        .End()
+        .Function().End()
+        .Export().Function(&quot;foo&quot;).End()
+        .Code()
+            .Function(&quot;foo&quot;, {params: [&quot;i32&quot;, &quot;i32&quot;]})
+                .GetLocal(0)
+                .I32Const(0)
+                .I32Eq()
+                .If(&quot;void&quot;, b =&gt;
+                    b.GetLocal(1)
+                    .GetLocal(0)
+                    .I32Store(2, 0)
+                    .Br(0)
+                    .Else()
+                        .GetLocal(0)
+                        .Call(0)
+                    .Br(0)
+                   )
+            .End()
+        .End();
+
+    const bin = builder.WebAssembly().get();
+    const module = new WebAssembly.Module(bin);
+    const imp = {
+        imp: {
+            mem: new WebAssembly.Memory({initial: numPages}),
+            func: continuation
+        }
+    };
+    const foo = new WebAssembly.Instance(module, imp).exports.foo;
+    const address = numPages*pageSize + 1;
+    function continuation(x) {
+        foo(x - 1, address);
+    }
+
+    for (let i = 0; i &lt; 10000; i++) {
+        let threw = false;
+        try {
+            foo(25, address);
+        } catch(e) {
+            assert(e instanceof WebAssembly.RuntimeError);
+            assert(e.message === &quot;Out of bounds memory access&quot;);
+            threw = true;
+        }
+        assert(threw);
+    }
+}
</ins></span></pre></div>
<a id="trunkJSTestswasmjsapitest_memory_constructorjs"></a>
<div class="modfile"><h4>Modified: trunk/JSTests/wasm/js-api/test_memory_constructor.js (209695 => 209696)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JSTests/wasm/js-api/test_memory_constructor.js        2016-12-12 02:50:06 UTC (rev 209695)
+++ trunk/JSTests/wasm/js-api/test_memory_constructor.js        2016-12-12 03:11:18 UTC (rev 209696)
</span><span class="lines">@@ -39,9 +39,12 @@
</span><span class="cx">         testInvalidSize({initial: v}, &quot;initial&quot;);
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    // These should not throw.
-    new WebAssembly.Memory({initial: maxPageCount});
-    new WebAssembly.Memory({initial: maxPageCount, maximum: maxPageCount});
</del><ins>+    try {
+        new WebAssembly.Memory({initial: maxPageCount});
+        new WebAssembly.Memory({initial: maxPageCount, maximum: maxPageCount});
+    } catch(e) {
+        // These might throw, since we're asking for a lot of memory.
+    }
</ins><span class="cx"> 
</span><span class="cx">     testInvalidInitial(2**31);
</span><span class="cx">     testInvalidInitial(maxPageCount + 1);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreAPIJSContextRefcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/API/JSContextRef.cpp (209695 => 209696)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/API/JSContextRef.cpp        2016-12-12 02:50:06 UTC (rev 209695)
+++ trunk/Source/JavaScriptCore/API/JSContextRef.cpp        2016-12-12 03:11:18 UTC (rev 209696)
</span><span class="lines">@@ -260,7 +260,7 @@
</span><span class="cx">         if (m_remainingCapacityForFrameCapture) {
</span><span class="cx">             // If callee is unknown, but we've not added any frame yet, we should
</span><span class="cx">             // still add the frame, because something called us, and gave us arguments.
</span><del>-            JSObject* callee = visitor-&gt;callee();
</del><ins>+            JSCell* callee = visitor-&gt;callee();
</ins><span class="cx">             if (!callee &amp;&amp; visitor-&gt;index())
</span><span class="cx">                 return StackVisitor::Done;
</span><span class="cx"> 
</span><span class="lines">@@ -273,7 +273,7 @@
</span><span class="cx">             builder.append(visitor-&gt;functionName());
</span><span class="cx">             builder.appendLiteral(&quot;() at &quot;);
</span><span class="cx">             builder.append(visitor-&gt;sourceURL());
</span><del>-            if (visitor-&gt;isJSFrame()) {
</del><ins>+            if (visitor-&gt;hasLineAndColumnInfo()) {
</ins><span class="cx">                 builder.append(':');
</span><span class="cx">                 unsigned lineNumber;
</span><span class="cx">                 unsigned unusedColumn;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ChangeLog (209695 => 209696)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ChangeLog        2016-12-12 02:50:06 UTC (rev 209695)
+++ trunk/Source/JavaScriptCore/ChangeLog        2016-12-12 03:11:18 UTC (rev 209696)
</span><span class="lines">@@ -1,3 +1,137 @@
</span><ins>+2016-12-11  Saam Barati  &lt;sbarati@apple.com&gt;
+
+        We should be able to throw exceptions from Wasm code and when Wasm frames are on the stack
+        https://bugs.webkit.org/show_bug.cgi?id=165429
+
+        Reviewed by Keith Miller.
+
+        This patch teaches the stack walking runtime about wasm.
+        To do this, I taught StackVisitor that a callee is not
+        always an object.
+
+        To be able to unwind callee save registers properly, I've given
+        JSWebAssemblyCallee a list of RegisterAtOffsetList for the callee
+        saves that B3 saved in the prologue. Also, because we have two
+        B3Compilations per wasm function, one for wasm entrypoint, and
+        one for the JS entrypoint, I needed to create a callee for each
+        because they each might spill callee save registers.
+
+        I also fixed a bug inside the Wasm::Memory constructor where we
+        were trying to mmap the same number of bytes even after the first
+        mmap failed. We should start by trying to mmap the maximum bytes,
+        and if that fails, fall back to the specified initial bytes. However,
+        the code was just mmapping the maximum twice. I've fixed that and
+        also added a RELEASE_ASSERT_NOT_REACHED() for when the second mmap
+        fails along with a FIXME to throw an OOM error.
+
+        There was a second bug I fixed where JSModuleRecord was calling
+        visitWeak on its CallLinkInfos inside ::visitChldren(). It needs
+        to do this after marking. I changed JSModuleRecord to do what
+        CodeBlock does and call visitWeak on its CallLinkInfos inside
+        an UnconditionalFinalizer.
+
+        * API/JSContextRef.cpp:
+        (BacktraceFunctor::operator()):
+        * inspector/ScriptCallStackFactory.cpp:
+        (Inspector::createScriptCallStackFromException):
+        * interpreter/CallFrame.cpp:
+        (JSC::CallFrame::vmEntryGlobalObject):
+        * interpreter/CallFrame.h:
+        (JSC::ExecState::callee):
+        * interpreter/Interpreter.cpp:
+        (JSC::GetStackTraceFunctor::operator()):
+        (JSC::UnwindFunctor::operator()):
+        (JSC::UnwindFunctor::copyCalleeSavesToVMEntryFrameCalleeSavesBuffer):
+        * interpreter/Interpreter.h:
+        * interpreter/ShadowChicken.cpp:
+        (JSC::ShadowChicken::update):
+        * interpreter/StackVisitor.cpp:
+        (JSC::StackVisitor::StackVisitor):
+        (JSC::StackVisitor::readFrame):
+        (JSC::StackVisitor::readNonInlinedFrame):
+        (JSC::StackVisitor::readInlinedFrame):
+        (JSC::StackVisitor::Frame::isWasmFrame):
+        (JSC::StackVisitor::Frame::codeType):
+        (JSC::StackVisitor::Frame::calleeSaveRegisters):
+        (JSC::StackVisitor::Frame::functionName):
+        (JSC::StackVisitor::Frame::sourceURL):
+        (JSC::StackVisitor::Frame::toString):
+        (JSC::StackVisitor::Frame::hasLineAndColumnInfo):
+        (JSC::StackVisitor::Frame::setToEnd):
+        * interpreter/StackVisitor.h:
+        (JSC::StackVisitor::Frame::callee):
+        (JSC::StackVisitor::Frame::isNativeFrame):
+        (JSC::StackVisitor::Frame::isJSFrame): Deleted.
+        * jsc.cpp:
+        (callWasmFunction):
+        (functionTestWasmModuleFunctions):
+        * runtime/Error.cpp:
+        (JSC::addErrorInfoAndGetBytecodeOffset):
+        * runtime/JSCell.cpp:
+        (JSC::JSCell::isAnyWasmCallee):
+        * runtime/JSCell.h:
+        * runtime/JSFunction.cpp:
+        (JSC::RetrieveArgumentsFunctor::operator()):
+        (JSC::RetrieveCallerFunctionFunctor::operator()):
+        * runtime/StackFrame.cpp:
+        (JSC::StackFrame::sourceID):
+        (JSC::StackFrame::sourceURL):
+        (JSC::StackFrame::functionName):
+        (JSC::StackFrame::computeLineAndColumn):
+        (JSC::StackFrame::toString):
+        * runtime/StackFrame.h:
+        (JSC::StackFrame::StackFrame):
+        (JSC::StackFrame::hasLineAndColumnInfo):
+        (JSC::StackFrame::hasBytecodeOffset):
+        (JSC::StackFrame::bytecodeOffset):
+        (JSC::StackFrame::isNative): Deleted.
+        * runtime/VM.h:
+        * wasm/WasmB3IRGenerator.cpp:
+        (JSC::Wasm::B3IRGenerator::B3IRGenerator):
+        (JSC::Wasm::createJSToWasmWrapper):
+        (JSC::Wasm::parseAndCompile):
+        * wasm/WasmCallingConvention.h:
+        (JSC::Wasm::CallingConvention::setupFrameInPrologue):
+        * wasm/WasmFormat.h:
+        * wasm/WasmMemory.cpp:
+        (JSC::Wasm::Memory::Memory):
+        * wasm/WasmMemory.h:
+        (JSC::Wasm::Memory::isValid):
+        * wasm/WasmPlan.cpp:
+        (JSC::Wasm::Plan::run):
+        (JSC::Wasm::Plan::initializeCallees):
+        * wasm/WasmPlan.h:
+        (JSC::Wasm::Plan::jsToWasmEntryPointForFunction): Deleted.
+        * wasm/js/JSWebAssemblyCallee.cpp:
+        (JSC::JSWebAssemblyCallee::finishCreation):
+        * wasm/js/JSWebAssemblyCallee.h:
+        (JSC::JSWebAssemblyCallee::create):
+        (JSC::JSWebAssemblyCallee::entrypoint):
+        (JSC::JSWebAssemblyCallee::calleeSaveRegisters):
+        (JSC::JSWebAssemblyCallee::jsToWasmEntryPoint): Deleted.
+        * wasm/js/JSWebAssemblyModule.cpp:
+        (JSC::JSWebAssemblyModule::JSWebAssemblyModule):
+        (JSC::JSWebAssemblyModule::visitChildren):
+        (JSC::JSWebAssemblyModule::UnconditionalFinalizer::finalizeUnconditionally):
+        * wasm/js/JSWebAssemblyModule.h:
+        (JSC::JSWebAssemblyModule::jsEntrypointCalleeFromFunctionIndexSpace):
+        (JSC::JSWebAssemblyModule::wasmEntrypointCalleeFromFunctionIndexSpace):
+        (JSC::JSWebAssemblyModule::setJSEntrypointCallee):
+        (JSC::JSWebAssemblyModule::setWasmEntrypointCallee):
+        (JSC::JSWebAssemblyModule::allocationSize):
+        (JSC::JSWebAssemblyModule::calleeFromFunctionIndexSpace): Deleted.
+        * wasm/js/JSWebAssemblyRuntimeError.h:
+        * wasm/js/WebAssemblyFunction.cpp:
+        (JSC::WebAssemblyFunction::call):
+        * wasm/js/WebAssemblyInstanceConstructor.cpp:
+        (JSC::constructJSWebAssemblyInstance):
+        * wasm/js/WebAssemblyMemoryConstructor.cpp:
+        (JSC::constructJSWebAssemblyMemory):
+        * wasm/js/WebAssemblyModuleConstructor.cpp:
+        (JSC::constructJSWebAssemblyModule):
+        * wasm/js/WebAssemblyModuleRecord.cpp:
+        (JSC::WebAssemblyModuleRecord::link):
+
</ins><span class="cx"> 2016-12-11  Filip Pizlo  &lt;fpizlo@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Re-enable concurrent GC.
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreinspectorScriptCallStackFactorycpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/inspector/ScriptCallStackFactory.cpp (209695 => 209696)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/inspector/ScriptCallStackFactory.cpp        2016-12-12 02:50:06 UTC (rev 209695)
+++ trunk/Source/JavaScriptCore/inspector/ScriptCallStackFactory.cpp        2016-12-12 03:11:18 UTC (rev 209696)
</span><span class="lines">@@ -156,7 +156,7 @@
</span><span class="cx">             extractSourceInformationFromException(exec, exceptionObject, &amp;lineNumber, &amp;columnNumber, &amp;exceptionSourceURL);
</span><span class="cx">             frames.append(ScriptCallFrame(String(), exceptionSourceURL, noSourceID, lineNumber, columnNumber));
</span><span class="cx">         } else {
</span><del>-            if (stackTrace[0].isNative() || stackTrace[0].sourceURL().isEmpty()) {
</del><ins>+            if (!stackTrace[0].hasLineAndColumnInfo() || stackTrace[0].sourceURL().isEmpty()) {
</ins><span class="cx">                 const ScriptCallFrame&amp; firstCallFrame = frames.first();
</span><span class="cx">                 extractSourceInformationFromException(exec, exceptionObject, &amp;lineNumber, &amp;columnNumber, &amp;exceptionSourceURL);
</span><span class="cx">                 frames[0] = ScriptCallFrame(firstCallFrame.functionName(), exceptionSourceURL, stackTrace[0].sourceID(), lineNumber, columnNumber);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreinterpreterCallFramecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/interpreter/CallFrame.cpp (209695 => 209696)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/interpreter/CallFrame.cpp        2016-12-12 02:50:06 UTC (rev 209695)
+++ trunk/Source/JavaScriptCore/interpreter/CallFrame.cpp        2016-12-12 03:11:18 UTC (rev 209696)
</span><span class="lines">@@ -185,8 +185,11 @@
</span><span class="cx"> 
</span><span class="cx"> JSGlobalObject* CallFrame::vmEntryGlobalObject()
</span><span class="cx"> {
</span><del>-    if (this == lexicalGlobalObject()-&gt;globalExec())
-        return lexicalGlobalObject();
</del><ins>+    if (callee()-&gt;isObject()) { 
+        if (this == lexicalGlobalObject()-&gt;globalExec())
+            return lexicalGlobalObject();
+    }
+    // If we're not an object, we're wasm, and therefore we're executing code and the below is safe.
</ins><span class="cx"> 
</span><span class="cx">     // For any ExecState that's not a globalExec, the 
</span><span class="cx">     // dynamic global object must be set since code is running
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreinterpreterCallFrameh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/interpreter/CallFrame.h (209695 => 209696)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/interpreter/CallFrame.h        2016-12-12 02:50:06 UTC (rev 209695)
+++ trunk/Source/JavaScriptCore/interpreter/CallFrame.h        2016-12-12 03:11:18 UTC (rev 209696)
</span><span class="lines">@@ -86,9 +86,9 @@
</span><span class="cx">     public:
</span><span class="cx">         static const int headerSizeInRegisters = CallFrameSlot::argumentCount + 1;
</span><span class="cx"> 
</span><del>-        JSCell* callee() const { return this[CallFrameSlot::callee].unboxedCell(); }
</del><span class="cx">         JSValue calleeAsValue() const { return this[CallFrameSlot::callee].jsValue(); }
</span><span class="cx">         JSObject* jsCallee() const { return this[CallFrameSlot::callee].object(); }
</span><ins>+        JSCell* callee() const { return this[CallFrameSlot::callee].unboxedCell(); }
</ins><span class="cx">         SUPPRESS_ASAN JSValue unsafeCallee() const { return this[CallFrameSlot::callee].asanUnsafeJSValue(); }
</span><span class="cx">         CodeBlock* codeBlock() const { return this[CallFrameSlot::codeBlock].Register::codeBlock(); }
</span><span class="cx">         CodeBlock** addressOfCodeBlock() const { return bitwise_cast&lt;CodeBlock**&gt;(this + CallFrameSlot::codeBlock); }
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreinterpreterInterpretercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/interpreter/Interpreter.cpp (209695 => 209696)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/interpreter/Interpreter.cpp        2016-12-12 02:50:06 UTC (rev 209695)
+++ trunk/Source/JavaScriptCore/interpreter/Interpreter.cpp        2016-12-12 03:11:18 UTC (rev 209696)
</span><span class="lines">@@ -63,6 +63,7 @@
</span><span class="cx"> #include &quot;Register.h&quot;
</span><span class="cx"> #include &quot;ScopedArguments.h&quot;
</span><span class="cx"> #include &quot;StackAlignment.h&quot;
</span><ins>+#include &quot;StackFrame.h&quot;
</ins><span class="cx"> #include &quot;StackVisitor.h&quot;
</span><span class="cx"> #include &quot;StrictEvalActivation.h&quot;
</span><span class="cx"> #include &quot;StrongInlines.h&quot;
</span><span class="lines">@@ -466,21 +467,14 @@
</span><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         if (m_remainingCapacityForFrameCapture) {
</span><del>-            if (visitor-&gt;isJSFrame()
</del><ins>+            if (!visitor-&gt;isWasmFrame()
+                &amp;&amp; !!visitor-&gt;codeBlock()
</ins><span class="cx">                 &amp;&amp; !visitor-&gt;codeBlock()-&gt;unlinkedCodeBlock()-&gt;isBuiltinFunction()) {
</span><del>-                StackFrame s = {
-                    Strong&lt;JSObject&gt;(m_vm, visitor-&gt;callee()),
-                    Strong&lt;CodeBlock&gt;(m_vm, visitor-&gt;codeBlock()),
-                    visitor-&gt;bytecodeOffset()
-                };
-                m_results.append(s);
</del><ins>+                m_results.append(
+                    StackFrame(m_vm, visitor-&gt;callee(), visitor-&gt;codeBlock(), visitor-&gt;bytecodeOffset()));
</ins><span class="cx">             } else {
</span><del>-                StackFrame s = {
-                    Strong&lt;JSObject&gt;(m_vm, visitor-&gt;callee()),
-                    Strong&lt;CodeBlock&gt;(),
-                    0 // unused value because codeBlock is null.
-                };
-                m_results.append(s);
</del><ins>+                m_results.append(
+                    StackFrame(m_vm,  visitor-&gt;callee()));
</ins><span class="cx">             }
</span><span class="cx">     
</span><span class="cx">             m_remainingCapacityForFrameCapture--;
</span><span class="lines">@@ -608,24 +602,21 @@
</span><span class="cx"> 
</span><span class="cx">         m_handler = nullptr;
</span><span class="cx">         if (!m_isTermination) {
</span><del>-            if (m_codeBlock)
</del><ins>+            if (m_codeBlock) {
</ins><span class="cx">                 m_handler = findExceptionHandler(visitor, m_codeBlock, RequiredHandler::AnyHandler);
</span><ins>+                if (m_handler)
+                    return StackVisitor::Done;
+            }
</ins><span class="cx">         }
</span><span class="cx"> 
</span><del>-        if (m_handler)
-            return StackVisitor::Done;
-
</del><span class="cx">         notifyDebuggerOfUnwinding(m_callFrame);
</span><span class="cx"> 
</span><ins>+        copyCalleeSavesToVMEntryFrameCalleeSavesBuffer(visitor);
+
</ins><span class="cx">         bool shouldStopUnwinding = visitor-&gt;callerIsVMEntryFrame();
</span><del>-        if (shouldStopUnwinding) {
-            copyCalleeSavesToVMEntryFrameCalleeSavesBuffer(visitor);
-
</del><ins>+        if (shouldStopUnwinding)
</ins><span class="cx">             return StackVisitor::Done;
</span><del>-        }
</del><span class="cx"> 
</span><del>-        copyCalleeSavesToVMEntryFrameCalleeSavesBuffer(visitor);
-
</del><span class="cx">         return StackVisitor::Continue;
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="lines">@@ -633,16 +624,8 @@
</span><span class="cx">     void copyCalleeSavesToVMEntryFrameCalleeSavesBuffer(StackVisitor&amp; visitor) const
</span><span class="cx">     {
</span><span class="cx"> #if ENABLE(JIT) &amp;&amp; NUMBER_OF_CALLEE_SAVES_REGISTERS &gt; 0
</span><ins>+        RegisterAtOffsetList* currentCalleeSaves = visitor-&gt;calleeSaveRegisters();
</ins><span class="cx"> 
</span><del>-        if (!visitor-&gt;isJSFrame())
-            return;
-
-#if ENABLE(DFG_JIT)
-        if (visitor-&gt;inlineCallFrame())
-            return;
-#endif
-        RegisterAtOffsetList* currentCalleeSaves = m_codeBlock ? m_codeBlock-&gt;calleeSaveRegisters() : nullptr;
-
</del><span class="cx">         if (!currentCalleeSaves)
</span><span class="cx">             return;
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreinterpreterInterpreterh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/interpreter/Interpreter.h (209695 => 209696)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/interpreter/Interpreter.h        2016-12-12 02:50:06 UTC (rev 209695)
+++ trunk/Source/JavaScriptCore/interpreter/Interpreter.h        2016-12-12 03:11:18 UTC (rev 209696)
</span><span class="lines">@@ -37,7 +37,6 @@
</span><span class="cx"> #include &quot;JSObject.h&quot;
</span><span class="cx"> #include &quot;Opcode.h&quot;
</span><span class="cx"> #include &quot;StackAlignment.h&quot;
</span><del>-#include &quot;StackFrame.h&quot;
</del><span class="cx"> #include &lt;wtf/HashMap.h&gt;
</span><span class="cx"> 
</span><span class="cx"> #if !ENABLE(JIT)
</span><span class="lines">@@ -60,6 +59,7 @@
</span><span class="cx">     class ModuleProgramExecutable;
</span><span class="cx">     class Register;
</span><span class="cx">     class JSScope;
</span><ins>+    class StackFrame;
</ins><span class="cx">     struct CallFrameClosure;
</span><span class="cx">     struct HandlerInfo;
</span><span class="cx">     struct Instruction;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreinterpreterShadowChickencpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/interpreter/ShadowChicken.cpp (209695 => 209696)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/interpreter/ShadowChicken.cpp        2016-12-12 02:50:06 UTC (rev 209695)
+++ trunk/Source/JavaScriptCore/interpreter/ShadowChicken.cpp        2016-12-12 03:11:18 UTC (rev 209696)
</span><span class="lines">@@ -155,8 +155,16 @@
</span><span class="cx">             exec, [&amp;] (StackVisitor&amp; visitor) -&gt; StackVisitor::Status {
</span><span class="cx">                 if (visitor-&gt;isInlinedFrame())
</span><span class="cx">                     return StackVisitor::Continue;
</span><ins>+                if (visitor-&gt;isWasmFrame()) {
+                    // FIXME: Make shadow chicken work with Wasm.
+                    // https://bugs.webkit.org/show_bug.cgi?id=165441
+                    return StackVisitor::Continue;
+                }
+
</ins><span class="cx">                 bool isTailDeleted = false;
</span><del>-                stackRightNow.append(Frame(visitor-&gt;callee(), visitor-&gt;callFrame(), isTailDeleted));
</del><ins>+                // FIXME: Make shadow chicken work with Wasm.
+                // https://bugs.webkit.org/show_bug.cgi?id=165441
+                stackRightNow.append(Frame(jsCast&lt;JSObject*&gt;(visitor-&gt;callee()), visitor-&gt;callFrame(), isTailDeleted));
</ins><span class="cx">                 return StackVisitor::Continue;
</span><span class="cx">             });
</span><span class="cx">         stackRightNow.reverse();
</span><span class="lines">@@ -272,6 +280,11 @@
</span><span class="cx">                 return StackVisitor::Continue;
</span><span class="cx">             }
</span><span class="cx"> 
</span><ins>+            if (visitor-&gt;isWasmFrame()) {
+                // FIXME: Make shadow chicken work with Wasm.
+                return StackVisitor::Continue;
+            }
+
</ins><span class="cx">             CallFrame* callFrame = visitor-&gt;callFrame();
</span><span class="cx">             if (verbose)
</span><span class="cx">                 dataLog(&quot;    Examining &quot;, RawPointer(callFrame), &quot;\n&quot;);
</span><span class="lines">@@ -293,7 +306,7 @@
</span><span class="cx">                 if (scope)
</span><span class="cx">                     RELEASE_ASSERT(scope-&gt;inherits(JSScope::info()));
</span><span class="cx">             }
</span><del>-            toPush.append(Frame(visitor-&gt;callee(), callFrame, isTailDeleted, callFrame-&gt;thisValue(), scope, codeBlock, callFrame-&gt;callSiteIndex()));
</del><ins>+            toPush.append(Frame(jsCast&lt;JSObject*&gt;(visitor-&gt;callee()), callFrame, isTailDeleted, callFrame-&gt;thisValue(), scope, codeBlock, callFrame-&gt;callSiteIndex()));
</ins><span class="cx"> 
</span><span class="cx">             if (indexInLog &lt; logCursorIndex
</span><span class="cx">                 // This condition protects us from the case where advanceIndexInLogTo didn't find
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreinterpreterStackVisitorcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/interpreter/StackVisitor.cpp (209695 => 209696)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/interpreter/StackVisitor.cpp        2016-12-12 02:50:06 UTC (rev 209695)
+++ trunk/Source/JavaScriptCore/interpreter/StackVisitor.cpp        2016-12-12 03:11:18 UTC (rev 209696)
</span><span class="lines">@@ -31,6 +31,7 @@
</span><span class="cx"> #include &quot;InlineCallFrame.h&quot;
</span><span class="cx"> #include &quot;Interpreter.h&quot;
</span><span class="cx"> #include &quot;JSCInlines.h&quot;
</span><ins>+#include &quot;JSWebAssemblyCallee.h&quot;
</ins><span class="cx"> #include &lt;wtf/text/StringBuilder.h&gt;
</span><span class="cx"> 
</span><span class="cx"> namespace JSC {
</span><span class="lines">@@ -38,6 +39,7 @@
</span><span class="cx"> StackVisitor::StackVisitor(CallFrame* startFrame)
</span><span class="cx"> {
</span><span class="cx">     m_frame.m_index = 0;
</span><ins>+    m_frame.m_isWasmFrame = false;
</ins><span class="cx">     CallFrame* topFrame;
</span><span class="cx">     if (startFrame) {
</span><span class="cx">         m_frame.m_VMEntryFrame = startFrame-&gt;vm().topVMEntryFrame;
</span><span class="lines">@@ -101,6 +103,11 @@
</span><span class="cx">         return;
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    if (callFrame-&gt;callee()-&gt;isAnyWasmCallee()) {
+        readNonInlinedFrame(callFrame);
+        return;
+    }
+
</ins><span class="cx"> #if !ENABLE(DFG_JIT)
</span><span class="cx">     readNonInlinedFrame(callFrame);
</span><span class="cx"> 
</span><span class="lines">@@ -146,11 +153,23 @@
</span><span class="cx">     m_frame.m_CallerVMEntryFrame = m_frame.m_VMEntryFrame;
</span><span class="cx">     m_frame.m_callerFrame = callFrame-&gt;callerFrame(m_frame.m_CallerVMEntryFrame);
</span><span class="cx">     m_frame.m_callerIsVMEntryFrame = m_frame.m_CallerVMEntryFrame != m_frame.m_VMEntryFrame;
</span><del>-    m_frame.m_callee = callFrame-&gt;jsCallee();
-    m_frame.m_codeBlock = callFrame-&gt;codeBlock();
-    m_frame.m_bytecodeOffset = !m_frame.codeBlock() ? 0
-        : codeOrigin ? codeOrigin-&gt;bytecodeIndex
-        : callFrame-&gt;bytecodeOffset();
</del><ins>+    m_frame.m_isWasmFrame = false;
+
+    JSCell* callee = callFrame-&gt;callee();
+    m_frame.m_callee = callee;
+
+    if (callee-&gt;isAnyWasmCallee()) {
+        m_frame.m_isWasmFrame = true;
+        m_frame.m_codeBlock = nullptr;
+        m_frame.m_bytecodeOffset = 0;
+    } else {
+        m_frame.m_codeBlock = callFrame-&gt;codeBlock();
+        m_frame.m_bytecodeOffset = !m_frame.codeBlock() ? 0
+            : codeOrigin ? codeOrigin-&gt;bytecodeIndex
+            : callFrame-&gt;bytecodeOffset();
+
+    }
+
</ins><span class="cx"> #if ENABLE(DFG_JIT)
</span><span class="cx">     m_frame.m_inlineCallFrame = 0;
</span><span class="cx"> #endif
</span><span class="lines">@@ -167,6 +186,7 @@
</span><span class="cx"> void StackVisitor::readInlinedFrame(CallFrame* callFrame, CodeOrigin* codeOrigin)
</span><span class="cx"> {
</span><span class="cx">     ASSERT(codeOrigin);
</span><ins>+    m_frame.m_isWasmFrame = false;
</ins><span class="cx"> 
</span><span class="cx">     int frameOffset = inlinedFrameOffset(codeOrigin);
</span><span class="cx">     bool isInlined = !!frameOffset;
</span><span class="lines">@@ -198,9 +218,17 @@
</span><span class="cx"> }
</span><span class="cx"> #endif // ENABLE(DFG_JIT)
</span><span class="cx"> 
</span><ins>+bool StackVisitor::Frame::isWasmFrame() const
+{
+    return m_isWasmFrame;
+}
+
</ins><span class="cx"> StackVisitor::Frame::CodeType StackVisitor::Frame::codeType() const
</span><span class="cx"> {
</span><del>-    if (!isJSFrame())
</del><ins>+    if (isWasmFrame())
+        return CodeType::Wasm;
+
+    if (!codeBlock())
</ins><span class="cx">         return CodeType::Native;
</span><span class="cx"> 
</span><span class="cx">     switch (codeBlock()-&gt;codeType()) {
</span><span class="lines">@@ -217,12 +245,39 @@
</span><span class="cx">     return CodeType::Global;
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+RegisterAtOffsetList* StackVisitor::Frame::calleeSaveRegisters()
+{
+    if (isInlinedFrame())
+        return nullptr;
+
+#if ENABLE(WEBASSEMBLY)
+    if (isWasmFrame()) {
+        if (JSCell* callee = this-&gt;callee()) {
+            if (JSWebAssemblyCallee* wasmCallee = jsDynamicCast&lt;JSWebAssemblyCallee*&gt;(callee))
+                return wasmCallee-&gt;calleeSaveRegisters();
+            // Other wasm callees (e.g, stubs) don't use callee save registers, so nothing needs
+            // to be restored for them.
+        }
+
+        return nullptr;
+    }
+#endif
+
+    if (CodeBlock* codeBlock = this-&gt;codeBlock())
+        return codeBlock-&gt;calleeSaveRegisters();
+
+    return nullptr;
+}
+
</ins><span class="cx"> String StackVisitor::Frame::functionName() const
</span><span class="cx"> {
</span><span class="cx">     String traceLine;
</span><del>-    JSObject* callee = this-&gt;callee();
</del><ins>+    JSCell* callee = this-&gt;callee();
</ins><span class="cx"> 
</span><span class="cx">     switch (codeType()) {
</span><ins>+    case CodeType::Wasm:
+        traceLine = ASCIILiteral(&quot;wasm code&quot;);
+        break;
</ins><span class="cx">     case CodeType::Eval:
</span><span class="cx">         traceLine = ASCIILiteral(&quot;eval code&quot;);
</span><span class="cx">         break;
</span><span class="lines">@@ -231,10 +286,10 @@
</span><span class="cx">         break;
</span><span class="cx">     case CodeType::Native:
</span><span class="cx">         if (callee)
</span><del>-            traceLine = getCalculatedDisplayName(callFrame()-&gt;vm(), callee).impl();
</del><ins>+            traceLine = getCalculatedDisplayName(callFrame()-&gt;vm(), jsCast&lt;JSObject*&gt;(callee)).impl();
</ins><span class="cx">         break;
</span><span class="cx">     case CodeType::Function:
</span><del>-        traceLine = getCalculatedDisplayName(callFrame()-&gt;vm(), callee).impl();
</del><ins>+        traceLine = getCalculatedDisplayName(callFrame()-&gt;vm(), jsCast&lt;JSObject*&gt;(callee)).impl();
</ins><span class="cx">         break;
</span><span class="cx">     case CodeType::Global:
</span><span class="cx">         traceLine = ASCIILiteral(&quot;global code&quot;);
</span><span class="lines">@@ -260,6 +315,9 @@
</span><span class="cx">     case CodeType::Native:
</span><span class="cx">         traceLine = ASCIILiteral(&quot;[native code]&quot;);
</span><span class="cx">         break;
</span><ins>+    case CodeType::Wasm:
+        traceLine = ASCIILiteral(&quot;[wasm code]&quot;);
+        break;
</ins><span class="cx">     }
</span><span class="cx">     return traceLine.isNull() ? emptyString() : traceLine;
</span><span class="cx"> }
</span><span class="lines">@@ -274,7 +332,7 @@
</span><span class="cx">         if (!functionName.isEmpty())
</span><span class="cx">             traceBuild.append('@');
</span><span class="cx">         traceBuild.append(sourceURL);
</span><del>-        if (isJSFrame()) {
</del><ins>+        if (hasLineAndColumnInfo()) {
</ins><span class="cx">             unsigned line = 0;
</span><span class="cx">             unsigned column = 0;
</span><span class="cx">             computeLineAndColumn(line, column);
</span><span class="lines">@@ -314,6 +372,11 @@
</span><span class="cx">     return arguments;
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+bool StackVisitor::Frame::hasLineAndColumnInfo() const
+{
+    return !!codeBlock();
+}
+
</ins><span class="cx"> void StackVisitor::Frame::computeLineAndColumn(unsigned&amp; line, unsigned&amp; column) const
</span><span class="cx"> {
</span><span class="cx">     CodeBlock* codeBlock = this-&gt;codeBlock();
</span><span class="lines">@@ -350,6 +413,7 @@
</span><span class="cx"> #if ENABLE(DFG_JIT)
</span><span class="cx">     m_inlineCallFrame = 0;
</span><span class="cx"> #endif
</span><ins>+    m_isWasmFrame = false;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void StackVisitor::Frame::dump(PrintStream&amp; out, Indenter indent) const
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreinterpreterStackVisitorh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/interpreter/StackVisitor.h (209695 => 209696)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/interpreter/StackVisitor.h        2016-12-12 02:50:06 UTC (rev 209695)
+++ trunk/Source/JavaScriptCore/interpreter/StackVisitor.h        2016-12-12 03:11:18 UTC (rev 209696)
</span><span class="lines">@@ -41,6 +41,7 @@
</span><span class="cx"> class JSObject;
</span><span class="cx"> class ClonedArguments;
</span><span class="cx"> class Register;
</span><ins>+class RegisterAtOffsetList;
</ins><span class="cx"> 
</span><span class="cx"> typedef ExecState CallFrame;
</span><span class="cx"> 
</span><span class="lines">@@ -53,7 +54,8 @@
</span><span class="cx">             Eval,
</span><span class="cx">             Function,
</span><span class="cx">             Module,
</span><del>-            Native
</del><ins>+            Native,
+            Wasm
</ins><span class="cx">         };
</span><span class="cx"> 
</span><span class="cx">         size_t index() const { return m_index; }
</span><span class="lines">@@ -60,7 +62,7 @@
</span><span class="cx">         size_t argumentCountIncludingThis() const { return m_argumentCountIncludingThis; }
</span><span class="cx">         bool callerIsVMEntryFrame() const { return m_callerIsVMEntryFrame; }
</span><span class="cx">         CallFrame* callerFrame() const { return m_callerFrame; }
</span><del>-        JSObject* callee() const { return m_callee; }
</del><ins>+        JSCell* callee() const { return m_callee; }
</ins><span class="cx">         CodeBlock* codeBlock() const { return m_codeBlock; }
</span><span class="cx">         unsigned bytecodeOffset() const { return m_bytecodeOffset; }
</span><span class="cx">         InlineCallFrame* inlineCallFrame() const {
</span><span class="lines">@@ -71,8 +73,9 @@
</span><span class="cx"> #endif
</span><span class="cx">         }
</span><span class="cx"> 
</span><del>-        bool isJSFrame() const { return !!codeBlock(); }
</del><ins>+        bool isNativeFrame() const { return !codeBlock() &amp;&amp; !isWasmFrame(); }
</ins><span class="cx">         bool isInlinedFrame() const { return !!inlineCallFrame(); }
</span><ins>+        bool isWasmFrame() const;
</ins><span class="cx"> 
</span><span class="cx">         JS_EXPORT_PRIVATE String functionName() const;
</span><span class="cx">         JS_EXPORT_PRIVATE String sourceURL() const;
</span><span class="lines">@@ -81,8 +84,11 @@
</span><span class="cx">         intptr_t sourceID();
</span><span class="cx"> 
</span><span class="cx">         CodeType codeType() const;
</span><ins>+        bool hasLineAndColumnInfo() const;
</ins><span class="cx">         JS_EXPORT_PRIVATE void computeLineAndColumn(unsigned&amp; line, unsigned&amp; column) const;
</span><span class="cx"> 
</span><ins>+        RegisterAtOffsetList* calleeSaveRegisters();
+
</ins><span class="cx">         ClonedArguments* createArguments();
</span><span class="cx">         VMEntryFrame* vmEntryFrame() const { return m_VMEntryFrame; }
</span><span class="cx">         CallFrame* callFrame() const { return m_callFrame; }
</span><span class="lines">@@ -97,19 +103,20 @@
</span><span class="cx">         void retrieveExpressionInfo(int&amp; divot, int&amp; startOffset, int&amp; endOffset, unsigned&amp; line, unsigned&amp; column) const;
</span><span class="cx">         void setToEnd();
</span><span class="cx"> 
</span><del>-        size_t m_index;
-        size_t m_argumentCountIncludingThis;
</del><ins>+#if ENABLE(DFG_JIT)
+        InlineCallFrame* m_inlineCallFrame;
+#endif
+        CallFrame* m_callFrame;
</ins><span class="cx">         VMEntryFrame* m_VMEntryFrame;
</span><span class="cx">         VMEntryFrame* m_CallerVMEntryFrame;
</span><span class="cx">         CallFrame* m_callerFrame;
</span><del>-        JSObject* m_callee;
</del><ins>+        JSCell* m_callee;
</ins><span class="cx">         CodeBlock* m_codeBlock;
</span><ins>+        size_t m_index;
+        size_t m_argumentCountIncludingThis;
</ins><span class="cx">         unsigned m_bytecodeOffset;
</span><del>-        bool m_callerIsVMEntryFrame;
-#if ENABLE(DFG_JIT)
-        InlineCallFrame* m_inlineCallFrame;
-#endif
-        CallFrame* m_callFrame;
</del><ins>+        bool m_callerIsVMEntryFrame : 1;
+        bool m_isWasmFrame : 1;
</ins><span class="cx"> 
</span><span class="cx">         friend class StackVisitor;
</span><span class="cx">     };
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejsccpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jsc.cpp (209695 => 209696)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jsc.cpp        2016-12-12 02:50:06 UTC (rev 209695)
+++ trunk/Source/JavaScriptCore/jsc.cpp        2016-12-12 03:11:18 UTC (rev 209696)
</span><span class="lines">@@ -2593,7 +2593,7 @@
</span><span class="cx">     ProtoCallFrame protoCallFrame;
</span><span class="cx">     protoCallFrame.init(nullptr, globalObject-&gt;globalExec()-&gt;jsCallee(), firstArgument, argCount, remainingArgs);
</span><span class="cx"> 
</span><del>-    return JSValue::decode(vmEntryToWasm(wasmCallee-&gt;jsToWasmEntryPoint(), vm, &amp;protoCallFrame));
</del><ins>+    return JSValue::decode(vmEntryToWasm(wasmCallee-&gt;entrypoint(), vm, &amp;protoCallFrame));
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> // testWasmModule(JSArrayBufferView source, number functionCount, ...[[WasmValue, [WasmValue]]]) where the ith copy of [[result, [args]]] is a list
</span><span class="lines">@@ -2623,12 +2623,14 @@
</span><span class="cx">         CRASH();
</span><span class="cx"> 
</span><span class="cx">     MarkedArgumentBuffer callees;
</span><ins>+    MarkedArgumentBuffer keepAlive;
</ins><span class="cx">     {
</span><span class="cx">         unsigned lastIndex = UINT_MAX;
</span><span class="cx">         plan.initializeCallees(exec-&gt;lexicalGlobalObject(),
</span><del>-            [&amp;] (unsigned calleeIndex, JSWebAssemblyCallee* callee) {
</del><ins>+            [&amp;] (unsigned calleeIndex, JSWebAssemblyCallee* jsEntrypointCallee, JSWebAssemblyCallee* wasmEntrypointCallee) {
</ins><span class="cx">                 RELEASE_ASSERT(!calleeIndex || (calleeIndex - 1 == lastIndex));
</span><del>-                callees.append(callee);
</del><ins>+                callees.append(jsEntrypointCallee);
+                keepAlive.append(wasmEntrypointCallee);
</ins><span class="cx">                 lastIndex = calleeIndex;
</span><span class="cx">             });
</span><span class="cx">     }
</span><span class="lines">@@ -2640,6 +2642,7 @@
</span><span class="cx"> 
</span><span class="cx">     if (!!moduleInformation-&gt;memory) {
</span><span class="cx">         memory = std::make_unique&lt;Wasm::Memory&gt;(moduleInformation-&gt;memory.initial(), moduleInformation-&gt;memory.maximum());
</span><ins>+        RELEASE_ASSERT(memory-&gt;isValid());
</ins><span class="cx">         memoryBytes = memory-&gt;memory();
</span><span class="cx">         memorySize = memory-&gt;size();
</span><span class="cx">     }
</span><span class="lines">@@ -2657,7 +2660,12 @@
</span><span class="cx">             for (unsigned argIndex = 0; argIndex &lt; arguments-&gt;length(); ++argIndex)
</span><span class="cx">                 boxedArgs.append(box(exec, vm, arguments-&gt;getIndexQuickly(argIndex)));
</span><span class="cx"> 
</span><del>-            JSValue callResult = callWasmFunction(&amp;vm, exec-&gt;lexicalGlobalObject(), jsCast&lt;JSWebAssemblyCallee*&gt;(callees.at(i)), boxedArgs);
</del><ins>+            JSValue callResult;
+            {
+                auto scope = DECLARE_THROW_SCOPE(vm);
+                callResult = callWasmFunction(&amp;vm, exec-&gt;lexicalGlobalObject(), jsCast&lt;JSWebAssemblyCallee*&gt;(callees.at(i)), boxedArgs);
+                RETURN_IF_EXCEPTION(scope, { });
+            }
</ins><span class="cx">             JSValue expected = box(exec, vm, result);
</span><span class="cx">             if (callResult != expected) {
</span><span class="cx">                 dataLog(&quot;Arguments: &quot;);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeErrorcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/Error.cpp (209695 => 209696)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/Error.cpp        2016-12-12 02:50:06 UTC (rev 209695)
+++ trunk/Source/JavaScriptCore/runtime/Error.cpp        2016-12-12 03:11:18 UTC (rev 209696)
</span><span class="lines">@@ -165,10 +165,10 @@
</span><span class="cx"> 
</span><span class="cx">         ASSERT(exec == vm.topCallFrame || exec == exec-&gt;lexicalGlobalObject()-&gt;globalExec() || exec == exec-&gt;vmEntryGlobalObject()-&gt;globalExec());
</span><span class="cx"> 
</span><del>-        StackFrame* firstNonNativeFrame = nullptr;
</del><ins>+        StackFrame* firstFrameWithLineAndColumnInfo = nullptr;
</ins><span class="cx">         for (unsigned i = 0 ; i &lt; stackTrace.size(); ++i) {
</span><del>-            firstNonNativeFrame = &amp;stackTrace.at(i);
-            if (!firstNonNativeFrame-&gt;isNative())
</del><ins>+            firstFrameWithLineAndColumnInfo = &amp;stackTrace.at(i);
+            if (firstFrameWithLineAndColumnInfo-&gt;hasLineAndColumnInfo())
</ins><span class="cx">                 break;
</span><span class="cx">         }
</span><span class="cx"> 
</span><span class="lines">@@ -177,16 +177,18 @@
</span><span class="cx">             vm.topCallFrame-&gt;iterate(functor);
</span><span class="cx">             callFrame = functor.foundCallFrame();
</span><span class="cx">             unsigned stackIndex = functor.index();
</span><del>-            *bytecodeOffset = stackTrace.at(stackIndex).bytecodeOffset;
</del><ins>+            *bytecodeOffset = 0;
+            if (stackTrace.at(stackIndex).hasBytecodeOffset())
+                *bytecodeOffset = stackTrace.at(stackIndex).bytecodeOffset();
</ins><span class="cx">         }
</span><span class="cx">         
</span><span class="cx">         unsigned line;
</span><span class="cx">         unsigned column;
</span><del>-        firstNonNativeFrame-&gt;computeLineAndColumn(line, column);
</del><ins>+        firstFrameWithLineAndColumnInfo-&gt;computeLineAndColumn(line, column);
</ins><span class="cx">         obj-&gt;putDirect(vm, vm.propertyNames-&gt;line, jsNumber(line));
</span><span class="cx">         obj-&gt;putDirect(vm, vm.propertyNames-&gt;column, jsNumber(column));
</span><span class="cx"> 
</span><del>-        String frameSourceURL = firstNonNativeFrame-&gt;sourceURL();
</del><ins>+        String frameSourceURL = firstFrameWithLineAndColumnInfo-&gt;sourceURL();
</ins><span class="cx">         if (!frameSourceURL.isEmpty())
</span><span class="cx">             obj-&gt;putDirect(vm, vm.propertyNames-&gt;sourceURL, jsString(&amp;vm, frameSourceURL));
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeJSCellcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/JSCell.cpp (209695 => 209696)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/JSCell.cpp        2016-12-12 02:50:06 UTC (rev 209695)
+++ trunk/Source/JavaScriptCore/runtime/JSCell.cpp        2016-12-12 03:11:18 UTC (rev 209696)
</span><span class="lines">@@ -24,11 +24,13 @@
</span><span class="cx"> #include &quot;JSCell.h&quot;
</span><span class="cx"> 
</span><span class="cx"> #include &quot;ArrayBufferView.h&quot;
</span><ins>+#include &quot;JSCInlines.h&quot;
</ins><span class="cx"> #include &quot;JSFunction.h&quot;
</span><span class="cx"> #include &quot;JSString.h&quot;
</span><span class="cx"> #include &quot;JSObject.h&quot;
</span><ins>+#include &quot;JSWebAssemblyCallee.h&quot;
</ins><span class="cx"> #include &quot;NumberObject.h&quot;
</span><del>-#include &quot;JSCInlines.h&quot;
</del><ins>+#include &quot;WebAssemblyToJSCallee.h&quot;
</ins><span class="cx"> #include &lt;wtf/MathExtras.h&gt;
</span><span class="cx"> 
</span><span class="cx"> namespace JSC {
</span><span class="lines">@@ -293,4 +295,14 @@
</span><span class="cx">     RELEASE_ASSERT_NOT_REACHED();
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+bool JSCell::isAnyWasmCallee() const
+{
+#if ENABLE(WEBASSEMBLY)
+    return inherits(JSWebAssemblyCallee::info()) || inherits(WebAssemblyToJSCallee::info());
+#else
+    return false;
+#endif
+
+}
+
</ins><span class="cx"> } // namespace JSC
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeJSCellh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/JSCell.h (209695 => 209696)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/JSCell.h        2016-12-12 02:50:06 UTC (rev 209695)
+++ trunk/Source/JavaScriptCore/runtime/JSCell.h        2016-12-12 03:11:18 UTC (rev 209696)
</span><span class="lines">@@ -95,6 +95,7 @@
</span><span class="cx">     bool isString() const;
</span><span class="cx">     bool isSymbol() const;
</span><span class="cx">     bool isObject() const;
</span><ins>+    bool isAnyWasmCallee() const;
</ins><span class="cx">     bool isGetterSetter() const;
</span><span class="cx">     bool isCustomGetterSetter() const;
</span><span class="cx">     bool isProxy() const;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeJSFunctioncpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/JSFunction.cpp (209695 => 209696)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/JSFunction.cpp        2016-12-12 02:50:06 UTC (rev 209695)
+++ trunk/Source/JavaScriptCore/runtime/JSFunction.cpp        2016-12-12 03:11:18 UTC (rev 209696)
</span><span class="lines">@@ -235,7 +235,7 @@
</span><span class="cx"> 
</span><span class="cx">     StackVisitor::Status operator()(StackVisitor&amp; visitor) const
</span><span class="cx">     {
</span><del>-        JSObject* callee = visitor-&gt;callee();
</del><ins>+        JSCell* callee = visitor-&gt;callee();
</ins><span class="cx">         if (callee != m_targetCallee)
</span><span class="cx">             return StackVisitor::Continue;
</span><span class="cx"> 
</span><span class="lines">@@ -277,7 +277,7 @@
</span><span class="cx"> 
</span><span class="cx">     StackVisitor::Status operator()(StackVisitor&amp; visitor) const
</span><span class="cx">     {
</span><del>-        JSObject* callee = visitor-&gt;callee();
</del><ins>+        JSCell* callee = visitor-&gt;callee();
</ins><span class="cx"> 
</span><span class="cx">         if (callee &amp;&amp; callee-&gt;inherits(JSBoundFunction::info()))
</span><span class="cx">             return StackVisitor::Continue;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeStackFramecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/StackFrame.cpp (209695 => 209696)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/StackFrame.cpp        2016-12-12 02:50:06 UTC (rev 209695)
+++ trunk/Source/JavaScriptCore/runtime/StackFrame.cpp        2016-12-12 03:11:18 UTC (rev 209696)
</span><span class="lines">@@ -35,17 +35,20 @@
</span><span class="cx"> 
</span><span class="cx"> intptr_t StackFrame::sourceID() const
</span><span class="cx"> {
</span><del>-    if (!codeBlock)
</del><ins>+    if (!m_codeBlock)
</ins><span class="cx">         return noSourceID;
</span><del>-    return codeBlock-&gt;ownerScriptExecutable()-&gt;sourceID();
</del><ins>+    return m_codeBlock-&gt;ownerScriptExecutable()-&gt;sourceID();
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> String StackFrame::sourceURL() const
</span><span class="cx"> {
</span><del>-    if (!codeBlock)
</del><ins>+    if (!m_codeBlock) {
+        if (m_callee &amp;&amp; m_callee-&gt;isAnyWasmCallee())
+            return ASCIILiteral(&quot;[wasm code]&quot;);
</ins><span class="cx">         return ASCIILiteral(&quot;[native code]&quot;);
</span><ins>+    }
</ins><span class="cx"> 
</span><del>-    String sourceURL = codeBlock-&gt;ownerScriptExecutable()-&gt;sourceURL();
</del><ins>+    String sourceURL = m_codeBlock-&gt;ownerScriptExecutable()-&gt;sourceURL();
</ins><span class="cx">     if (!sourceURL.isNull())
</span><span class="cx">         return sourceURL;
</span><span class="cx">     return emptyString();
</span><span class="lines">@@ -53,8 +56,8 @@
</span><span class="cx"> 
</span><span class="cx"> String StackFrame::functionName(VM&amp; vm) const
</span><span class="cx"> {
</span><del>-    if (codeBlock) {
-        switch (codeBlock-&gt;codeType()) {
</del><ins>+    if (m_codeBlock) {
+        switch (m_codeBlock-&gt;codeType()) {
</ins><span class="cx">         case EvalCode:
</span><span class="cx">             return ASCIILiteral(&quot;eval code&quot;);
</span><span class="cx">         case ModuleCode:
</span><span class="lines">@@ -68,14 +71,18 @@
</span><span class="cx">         }
</span><span class="cx">     }
</span><span class="cx">     String name;
</span><del>-    if (callee)
-        name = getCalculatedDisplayName(vm, callee.get()).impl();
</del><ins>+    if (m_callee) {
+        if (m_callee-&gt;isObject())
+            name = getCalculatedDisplayName(vm, jsCast&lt;JSObject*&gt;(m_callee.get())).impl();
+        else if (m_callee-&gt;isAnyWasmCallee())
+            return ASCIILiteral(&quot;&lt;wasm&gt;&quot;);
+    }
</ins><span class="cx">     return name.isNull() ? emptyString() : name;
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void StackFrame::computeLineAndColumn(unsigned&amp; line, unsigned&amp; column) const
</span><span class="cx"> {
</span><del>-    if (!codeBlock) {
</del><ins>+    if (!m_codeBlock) {
</ins><span class="cx">         line = 0;
</span><span class="cx">         column = 0;
</span><span class="cx">         return;
</span><span class="lines">@@ -84,9 +91,9 @@
</span><span class="cx">     int divot = 0;
</span><span class="cx">     int unusedStartOffset = 0;
</span><span class="cx">     int unusedEndOffset = 0;
</span><del>-    codeBlock-&gt;expressionRangeForBytecodeOffset(bytecodeOffset, divot, unusedStartOffset, unusedEndOffset, line, column);
</del><ins>+    m_codeBlock-&gt;expressionRangeForBytecodeOffset(m_bytecodeOffset, divot, unusedStartOffset, unusedEndOffset, line, column);
</ins><span class="cx"> 
</span><del>-    ScriptExecutable* executable = codeBlock-&gt;ownerScriptExecutable();
</del><ins>+    ScriptExecutable* executable = m_codeBlock-&gt;ownerScriptExecutable();
</ins><span class="cx">     if (executable-&gt;hasOverrideLineNumber())
</span><span class="cx">         line = executable-&gt;overrideLineNumber();
</span><span class="cx"> }
</span><span class="lines">@@ -101,7 +108,7 @@
</span><span class="cx">         if (!functionName.isEmpty())
</span><span class="cx">             traceBuild.append('@');
</span><span class="cx">         traceBuild.append(sourceURL);
</span><del>-        if (codeBlock) {
</del><ins>+        if (hasLineAndColumnInfo()) {
</ins><span class="cx">             unsigned line;
</span><span class="cx">             unsigned column;
</span><span class="cx">             computeLineAndColumn(line, column);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeStackFrameh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/StackFrame.h (209695 => 209696)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/StackFrame.h        2016-12-12 02:50:06 UTC (rev 209695)
+++ trunk/Source/JavaScriptCore/runtime/StackFrame.h        2016-12-12 03:11:18 UTC (rev 209696)
</span><span class="lines">@@ -32,18 +32,39 @@
</span><span class="cx"> class CodeBlock;
</span><span class="cx"> class JSObject;
</span><span class="cx"> 
</span><del>-struct StackFrame {
-    Strong&lt;JSObject&gt; callee;
-    Strong&lt;CodeBlock&gt; codeBlock;
-    unsigned bytecodeOffset;
</del><ins>+class StackFrame {
+public:
+    StackFrame(VM&amp; vm, JSCell* callee)
+        : m_callee(vm, callee)
+    { }
+
+    StackFrame(VM&amp; vm, JSCell* callee, CodeBlock* codeBlock, unsigned bytecodeOffset)
+        : m_callee(vm, callee)
+        , m_codeBlock(vm, codeBlock)
+        , m_bytecodeOffset(bytecodeOffset)
+    { }
+
+    bool hasLineAndColumnInfo() const { return !!m_codeBlock; }
</ins><span class="cx">     
</span><del>-    bool isNative() const { return !codeBlock; }
-    
</del><span class="cx">     void computeLineAndColumn(unsigned&amp; line, unsigned&amp; column) const;
</span><span class="cx">     String functionName(VM&amp;) const;
</span><span class="cx">     intptr_t sourceID() const;
</span><span class="cx">     String sourceURL() const;
</span><span class="cx">     String toString(VM&amp;) const;
</span><ins>+
+    bool hasBytecodeOffset() const { return m_bytecodeOffset != UINT_MAX; }
+    unsigned bytecodeOffset()
+    {
+        ASSERT(m_bytecodeOffset != UINT_MAX);
+        return m_bytecodeOffset;
+    }
+
+
+private:
+    Strong&lt;JSCell&gt; m_callee { };
+    Strong&lt;CodeBlock&gt; m_codeBlock { };
+    unsigned m_bytecodeOffset { UINT_MAX };
+    
</ins><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> } // namespace JSC
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeVMh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/VM.h (209695 => 209696)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/VM.h        2016-12-12 02:50:06 UTC (rev 209695)
+++ trunk/Source/JavaScriptCore/runtime/VM.h        2016-12-12 03:11:18 UTC (rev 209696)
</span><span class="lines">@@ -110,7 +110,7 @@
</span><span class="cx"> class ScriptExecutable;
</span><span class="cx"> class SourceProvider;
</span><span class="cx"> class SourceProviderCache;
</span><del>-struct StackFrame;
</del><ins>+class StackFrame;
</ins><span class="cx"> class Structure;
</span><span class="cx"> #if ENABLE(REGEXP_TRACING)
</span><span class="cx"> class RegExp;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorewasmWasmB3IRGeneratorcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/wasm/WasmB3IRGenerator.cpp (209695 => 209696)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/wasm/WasmB3IRGenerator.cpp        2016-12-12 02:50:06 UTC (rev 209695)
+++ trunk/Source/JavaScriptCore/wasm/WasmB3IRGenerator.cpp        2016-12-12 03:11:18 UTC (rev 209696)
</span><span class="lines">@@ -40,8 +40,13 @@
</span><span class="cx"> #include &quot;B3VariableValue.h&quot;
</span><span class="cx"> #include &quot;B3WasmAddressValue.h&quot;
</span><span class="cx"> #include &quot;B3WasmBoundsCheckValue.h&quot;
</span><ins>+#include &quot;ExceptionScope.h&quot;
+#include &quot;FrameTracers.h&quot;
+#include &quot;JITExceptions.h&quot;
+#include &quot;JSCInlines.h&quot;
</ins><span class="cx"> #include &quot;JSWebAssemblyInstance.h&quot;
</span><span class="cx"> #include &quot;JSWebAssemblyModule.h&quot;
</span><ins>+#include &quot;JSWebAssemblyRuntimeError.h&quot;
</ins><span class="cx"> #include &quot;VirtualRegister.h&quot;
</span><span class="cx"> #include &quot;WasmCallingConvention.h&quot;
</span><span class="cx"> #include &quot;WasmFunctionParser.h&quot;
</span><span class="lines">@@ -224,13 +229,45 @@
</span><span class="cx">             m_proc.pinRegister(info.sizeRegister);
</span><span class="cx"> 
</span><span class="cx">         m_proc.setWasmBoundsCheckGenerator([=] (CCallHelpers&amp; jit, GPRReg pinnedGPR, unsigned) {
</span><ins>+            AllowMacroScratchRegisterUsage allowScratch(jit);
</ins><span class="cx">             ASSERT_UNUSED(pinnedGPR, m_memorySizeGPR == pinnedGPR);
</span><del>-            // FIXME: This should unwind the stack and throw a JS exception. See: https://bugs.webkit.org/show_bug.cgi?id=163351
-            jit.breakpoint();
</del><ins>+            jit.copyCalleeSavesToVMEntryFrameCalleeSavesBuffer();
+
+            jit.move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
+
+            CCallHelpers::Call call = jit.call();
+            jit.jumpToExceptionHandler();
+
+            jit.addLinkTask([=] (LinkBuffer&amp; linkBuffer) {
+                void (*throwMemoryException)(ExecState*) = [] (ExecState* exec) {
+                    VM* vm = &amp;exec-&gt;vm();
+                    NativeCallFrameTracer tracer(vm, exec);
+
+                    {
+                        auto throwScope = DECLARE_THROW_SCOPE(*vm);
+                        JSGlobalObject* globalObject = vm-&gt;topJSWebAssemblyInstance-&gt;globalObject();
+
+                        JSWebAssemblyRuntimeError* error = JSWebAssemblyRuntimeError::create(
+                            exec, globalObject-&gt;WebAssemblyRuntimeErrorStructure(), &quot;Out of bounds memory access&quot;);
+                        throwException(exec, throwScope, error);
+                    }
+
+                    genericUnwind(vm, exec);
+                    ASSERT(!!vm-&gt;callFrameForCatch);
+                };
+
+                linkBuffer.link(call, throwMemoryException);
+            });
</ins><span class="cx">         });
</span><ins>+
+        B3::PatchpointValue* foo = m_currentBlock-&gt;appendNew&lt;B3::PatchpointValue&gt;(m_proc, B3::Void, Origin());
+        foo-&gt;setGenerator(
+            [=] (CCallHelpers&amp; jit, const B3::StackmapGenerationParams&amp;) {
+                AllowMacroScratchRegisterUsage allowScratch(jit);
+            });
</ins><span class="cx">     }
</span><span class="cx"> 
</span><del>-    wasmCallingConvention().setupFrameInPrologue(compilation, m_proc, Origin(), m_currentBlock);
</del><ins>+    wasmCallingConvention().setupFrameInPrologue(&amp;compilation-&gt;wasmCalleeMoveLocation, m_proc, Origin(), m_currentBlock);
</ins><span class="cx"> 
</span><span class="cx">     m_functionIndexSpaceValue = m_currentBlock-&gt;appendNew&lt;ConstPtrValue&gt;(m_proc, Origin(), functionIndexSpace.buffer.get());
</span><span class="cx"> }
</span><span class="lines">@@ -718,21 +755,25 @@
</span><span class="cx">     dataLogLn(&quot;\n&quot;);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-static std::unique_ptr&lt;Compilation&gt; createJSToWasmWrapper(VM&amp; vm, const Signature* signature, MacroAssemblerCodePtr mainFunction, const MemoryInformation&amp; memory)
</del><ins>+static std::unique_ptr&lt;Compilation&gt; createJSToWasmWrapper(VM&amp; vm, WasmInternalFunction&amp; function, const Signature* signature, MacroAssemblerCodePtr mainFunction, const MemoryInformation&amp; memory)
</ins><span class="cx"> {
</span><span class="cx">     Procedure proc;
</span><span class="cx">     BasicBlock* block = proc.addBlock();
</span><span class="cx"> 
</span><del>-    // Check argument count is sane.
-    Value* framePointer = block-&gt;appendNew&lt;B3::Value&gt;(proc, B3::FramePointer, Origin());
-    Value* offSetOfArgumentCount = block-&gt;appendNew&lt;Const64Value&gt;(proc, Origin(), CallFrameSlot::argumentCount * sizeof(Register));
-    Value* argumentCount = block-&gt;appendNew&lt;MemoryValue&gt;(proc, Load, Int32, Origin(),
-        block-&gt;appendNew&lt;Value&gt;(proc, Add, Origin(), framePointer, offSetOfArgumentCount));
</del><ins>+    Origin origin;
</ins><span class="cx"> 
</span><del>-    Value* expectedArgumentCount = block-&gt;appendNew&lt;Const32Value&gt;(proc, Origin(), signature-&gt;arguments.size());
</del><ins>+    jscCallingConvention().setupFrameInPrologue(&amp;function.jsToWasmCalleeMoveLocation, proc, origin, block);
</ins><span class="cx"> 
</span><del>-    CheckValue* argumentCountCheck = block-&gt;appendNew&lt;CheckValue&gt;(proc, Check, Origin(),
-        block-&gt;appendNew&lt;Value&gt;(proc, Above, Origin(), expectedArgumentCount, argumentCount));
</del><ins>+    Value* framePointer = block-&gt;appendNew&lt;B3::Value&gt;(proc, B3::FramePointer, origin);
+    Value* offSetOfArgumentCount = block-&gt;appendNew&lt;Const64Value&gt;(proc, origin, CallFrameSlot::argumentCount * sizeof(Register));
+    Value* argumentCount = block-&gt;appendNew&lt;MemoryValue&gt;(proc, Load, Int32, origin,
+        block-&gt;appendNew&lt;Value&gt;(proc, Add, origin, framePointer, offSetOfArgumentCount));
+
+    Value* expectedArgumentCount = block-&gt;appendNew&lt;Const32Value&gt;(proc, origin, signature-&gt;arguments.size());
+
+    CheckValue* argumentCountCheck = block-&gt;appendNew&lt;CheckValue&gt;(proc, Check, origin,
+        block-&gt;appendNew&lt;Value&gt;(proc, Above, origin, expectedArgumentCount, argumentCount));
+
</ins><span class="cx">     argumentCountCheck-&gt;setGenerator([] (CCallHelpers&amp; jit, const StackmapGenerationParams&amp;) {
</span><span class="cx">         jit.breakpoint();
</span><span class="cx">     });
</span><span class="lines">@@ -747,19 +788,19 @@
</span><span class="cx">             block-&gt;appendNew&lt;ConstPtrValue&gt;(proc, Origin(), &amp;vm.topWasmMemorySize));
</span><span class="cx">         sizes.reserveCapacity(memory.pinnedRegisters().sizeRegisters.size());
</span><span class="cx">         for (auto info : memory.pinnedRegisters().sizeRegisters) {
</span><del>-            sizes.append(block-&gt;appendNew&lt;Value&gt;(proc, Sub, Origin(), size,
-                block-&gt;appendNew&lt;Const32Value&gt;(proc, Origin(), info.sizeOffset)));
</del><ins>+            sizes.append(block-&gt;appendNew&lt;Value&gt;(proc, Sub, origin, size,
+                block-&gt;appendNew&lt;Const32Value&gt;(proc, origin, info.sizeOffset)));
</ins><span class="cx">         }
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     // Get our arguments.
</span><span class="cx">     Vector&lt;Value*&gt; arguments;
</span><del>-    jscCallingConvention().loadArguments(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 = wasmCallingConvention().setupCall(proc, block, Origin(), 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.pinnedRegisters().sizeRegisters.size());
</span><span class="cx">             patchpoint-&gt;append(ConstrainedValue(baseMemory, ValueRep::reg(memory.pinnedRegisters().baseMemoryPointer)));
</span><span class="lines">@@ -780,15 +821,15 @@
</span><span class="cx">     // Return the result, if needed.
</span><span class="cx">     switch (signature-&gt;returnType) {
</span><span class="cx">     case Wasm::Void:
</span><del>-        block-&gt;appendNewControlValue(proc, B3::Return, Origin());
</del><ins>+        block-&gt;appendNewControlValue(proc, B3::Return, origin);
</ins><span class="cx">         break;
</span><span class="cx">     case Wasm::F32:
</span><span class="cx">     case Wasm::F64:
</span><del>-        result = block-&gt;appendNew&lt;Value&gt;(proc, BitwiseCast, Origin(), result);
</del><ins>+        result = block-&gt;appendNew&lt;Value&gt;(proc, BitwiseCast, origin, result);
</ins><span class="cx">         FALLTHROUGH;
</span><span class="cx">     case Wasm::I32:
</span><span class="cx">     case Wasm::I64:
</span><del>-        block-&gt;appendNewControlValue(proc, B3::Return, Origin(), result);
</del><ins>+        block-&gt;appendNewControlValue(proc, B3::Return, origin, result);
</ins><span class="cx">         break;
</span><span class="cx">     case Wasm::Func:
</span><span class="cx">     case Wasm::Anyfunc:
</span><span class="lines">@@ -795,7 +836,9 @@
</span><span class="cx">         RELEASE_ASSERT_NOT_REACHED();
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    return std::make_unique&lt;Compilation&gt;(vm, proc);
</del><ins>+    auto jsEntrypoint = std::make_unique&lt;Compilation&gt;(vm, proc);
+    function.jsToWasmEntrypoint.calleeSaveRegisters = proc.calleeSaveRegisters();
+    return jsEntrypoint;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> std::unique_ptr&lt;WasmInternalFunction&gt; parseAndCompile(VM&amp; vm, const uint8_t* functionStart, size_t functionLength, const Signature* signature, Vector&lt;UnlinkedWasmToWasmCall&gt;&amp; unlinkedWasmToWasmCalls, const ImmutableFunctionIndexSpace&amp; functionIndexSpace, const ModuleInformation&amp; info, unsigned optLevel)
</span><span class="lines">@@ -817,8 +860,9 @@
</span><span class="cx">     if (verbose)
</span><span class="cx">         dataLog(&quot;Post SSA: &quot;, procedure);
</span><span class="cx"> 
</span><del>-    result-&gt;code = std::make_unique&lt;Compilation&gt;(vm, procedure, optLevel);
-    result-&gt;jsToWasmEntryPoint = createJSToWasmWrapper(vm, signature, result-&gt;code-&gt;code(), info.memory);
</del><ins>+    result-&gt;wasmEntrypoint.compilation = std::make_unique&lt;Compilation&gt;(vm, procedure, optLevel);
+    result-&gt;wasmEntrypoint.calleeSaveRegisters = procedure.calleeSaveRegisters();
+    result-&gt;jsToWasmEntrypoint.compilation = createJSToWasmWrapper(vm, *result, signature, result-&gt;wasmEntrypoint.compilation-&gt;code(), info.memory);
</ins><span class="cx">     return result;
</span><span class="cx"> }
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorewasmWasmCallingConventionh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/wasm/WasmCallingConvention.h (209695 => 209696)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/wasm/WasmCallingConvention.h        2016-12-12 02:50:06 UTC (rev 209695)
+++ trunk/Source/JavaScriptCore/wasm/WasmCallingConvention.h        2016-12-12 03:11:18 UTC (rev 209696)
</span><span class="lines">@@ -83,7 +83,7 @@
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx"> public:
</span><del>-    void setupFrameInPrologue(WasmInternalFunction* compilation, B3::Procedure&amp; proc, B3::Origin origin, B3::BasicBlock* block) const
</del><ins>+    void setupFrameInPrologue(CodeLocationDataLabelPtr* calleeMoveLocation, B3::Procedure&amp; proc, B3::Origin origin, B3::BasicBlock* block) const
</ins><span class="cx">     {
</span><span class="cx">         static_assert(CallFrameSlot::callee * sizeof(Register) &lt; headerSize, &quot;We rely on this here for now.&quot;);
</span><span class="cx">         static_assert(CallFrameSlot::codeBlock * sizeof(Register) &lt; headerSize, &quot;We rely on this here for now.&quot;);
</span><span class="lines">@@ -96,7 +96,7 @@
</span><span class="cx">                 GPRReg result = params[0].gpr();
</span><span class="cx">                 MacroAssembler::DataLabelPtr moveLocation = jit.moveWithPatch(MacroAssembler::TrustedImmPtr(nullptr), result);
</span><span class="cx">                 jit.addLinkTask([=] (LinkBuffer&amp; linkBuffer) {
</span><del>-                    compilation-&gt;calleeMoveLocation = linkBuffer.locationOf(moveLocation);
</del><ins>+                    *calleeMoveLocation = linkBuffer.locationOf(moveLocation);
</ins><span class="cx">                 });
</span><span class="cx">             });
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorewasmWasmFormath"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/wasm/WasmFormat.h (209695 => 209696)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/wasm/WasmFormat.h        2016-12-12 02:50:06 UTC (rev 209695)
+++ trunk/Source/JavaScriptCore/wasm/WasmFormat.h        2016-12-12 03:11:18 UTC (rev 209696)
</span><span class="lines">@@ -32,6 +32,7 @@
</span><span class="cx"> #include &quot;CodeLocation.h&quot;
</span><span class="cx"> #include &quot;Identifier.h&quot;
</span><span class="cx"> #include &quot;MacroAssemblerCodeRef.h&quot;
</span><ins>+#include &quot;RegisterAtOffsetList.h&quot;
</ins><span class="cx"> #include &quot;WasmMemoryInformation.h&quot;
</span><span class="cx"> #include &quot;WasmOps.h&quot;
</span><span class="cx"> #include &quot;WasmPageCount.h&quot;
</span><span class="lines">@@ -166,10 +167,17 @@
</span><span class="cx">     size_t functionIndex;
</span><span class="cx"> };
</span><span class="cx"> 
</span><ins>+struct Entrypoint {
+    std::unique_ptr&lt;B3::Compilation&gt; compilation;
+    RegisterAtOffsetList calleeSaveRegisters;
+};
+
</ins><span class="cx"> struct WasmInternalFunction {
</span><del>-    CodeLocationDataLabelPtr calleeMoveLocation;
-    std::unique_ptr&lt;B3::Compilation&gt; code;
-    std::unique_ptr&lt;B3::Compilation&gt; jsToWasmEntryPoint;
</del><ins>+    CodeLocationDataLabelPtr wasmCalleeMoveLocation;
+    CodeLocationDataLabelPtr jsToWasmCalleeMoveLocation;
+
+    Entrypoint wasmEntrypoint;
+    Entrypoint jsToWasmEntrypoint;
</ins><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> typedef MacroAssemblerCodeRef WasmToJSStub;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorewasmWasmMemorycpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/wasm/WasmMemory.cpp (209695 => 209696)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/wasm/WasmMemory.cpp        2016-12-12 02:50:06 UTC (rev 209695)
+++ trunk/Source/JavaScriptCore/wasm/WasmMemory.cpp        2016-12-12 03:11:18 UTC (rev 209696)
</span><span class="lines">@@ -38,15 +38,15 @@
</span><span class="cx">     , m_maximum(maximum)
</span><span class="cx">     // FIXME: If we add signal based bounds checking then we need extra space for overflow on load.
</span><span class="cx">     // see: https://bugs.webkit.org/show_bug.cgi?id=162693
</span><del>-    , m_mappedCapacity(PageCount::max().bytes())
</del><span class="cx"> {
</span><span class="cx">     RELEASE_ASSERT(!maximum || maximum &gt;= initial); // This should be guaranteed by our caller.
</span><span class="cx"> 
</span><ins>+    m_mappedCapacity = m_capacity;
</ins><span class="cx">     // FIXME: It would be nice if we had a VM tag for wasm memory. https://bugs.webkit.org/show_bug.cgi?id=163600
</span><span class="cx">     void* result = mmap(nullptr, m_mappedCapacity, PROT_NONE, MAP_PRIVATE | MAP_ANON, -1, 0);
</span><span class="cx">     if (result == MAP_FAILED) {
</span><span class="cx">         // Try again with a different number.
</span><del>-        m_mappedCapacity = m_capacity;
</del><ins>+        m_mappedCapacity = m_size;
</ins><span class="cx">         result = mmap(nullptr, m_mappedCapacity, PROT_NONE, MAP_PRIVATE | MAP_ANON, -1, 0);
</span><span class="cx">         if (result == MAP_FAILED)
</span><span class="cx">             return;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorewasmWasmMemoryh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/wasm/WasmMemory.h (209695 => 209696)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/wasm/WasmMemory.h        2016-12-12 02:50:06 UTC (rev 209695)
+++ trunk/Source/JavaScriptCore/wasm/WasmMemory.h        2016-12-12 03:11:18 UTC (rev 209696)
</span><span class="lines">@@ -52,6 +52,8 @@
</span><span class="cx">             munmap(m_memory, m_mappedCapacity);
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    bool isValid() const { return !!m_memory; }
+
</ins><span class="cx">     void* memory() const { return m_memory; }
</span><span class="cx">     uint32_t size() const { return m_size; }
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorewasmWasmPlancpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/wasm/WasmPlan.cpp (209695 => 209696)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/wasm/WasmPlan.cpp        2016-12-12 02:50:06 UTC (rev 209695)
+++ trunk/Source/JavaScriptCore/wasm/WasmPlan.cpp        2016-12-12 03:11:18 UTC (rev 209696)
</span><span class="lines">@@ -130,7 +130,7 @@
</span><span class="cx"> 
</span><span class="cx">         unlinkedWasmToWasmCalls.uncheckedAppend(Vector&lt;UnlinkedWasmToWasmCall&gt;());
</span><span class="cx">         m_wasmInternalFunctions.uncheckedAppend(parseAndCompile(*m_vm, functionStart, functionLength, signature, unlinkedWasmToWasmCalls.at(functionIndex), m_functionIndexSpace, *m_moduleInformation));
</span><del>-        m_functionIndexSpace.buffer.get()[functionIndexSpace].code = m_wasmInternalFunctions[functionIndex]-&gt;code-&gt;code().executableAddress();
</del><ins>+        m_functionIndexSpace.buffer.get()[functionIndexSpace].code = m_wasmInternalFunctions[functionIndex]-&gt;wasmEntrypoint.compilation-&gt;code().executableAddress();
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     // Patch the call sites for each WebAssembly function.
</span><span class="lines">@@ -142,20 +142,19 @@
</span><span class="cx">     m_failed = false;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void Plan::initializeCallees(JSGlobalObject* globalObject, std::function&lt;void(unsigned, JSWebAssemblyCallee*)&gt; callback)
</del><ins>+void Plan::initializeCallees(JSGlobalObject* globalObject, std::function&lt;void(unsigned, JSWebAssemblyCallee*, JSWebAssemblyCallee*)&gt; callback)
</ins><span class="cx"> {
</span><span class="cx">     ASSERT(!failed());
</span><span class="cx">     for (unsigned internalFunctionIndex = 0; internalFunctionIndex &lt; m_wasmInternalFunctions.size(); ++internalFunctionIndex) {
</span><span class="cx">         WasmInternalFunction* function = m_wasmInternalFunctions[internalFunctionIndex].get();
</span><del>-        CodeLocationDataLabelPtr calleeMoveLocation = function-&gt;calleeMoveLocation;
-        JSWebAssemblyCallee* callee = JSWebAssemblyCallee::create(globalObject-&gt;vm(), WTFMove(function-&gt;code), WTFMove(function-&gt;jsToWasmEntryPoint));
</del><span class="cx"> 
</span><del>-        MacroAssembler::repatchPointer(calleeMoveLocation, callee);
</del><ins>+        JSWebAssemblyCallee* jsEntrypointCallee = JSWebAssemblyCallee::create(globalObject-&gt;vm(), WTFMove(function-&gt;jsToWasmEntrypoint));
+        MacroAssembler::repatchPointer(function-&gt;jsToWasmCalleeMoveLocation, jsEntrypointCallee);
</ins><span class="cx"> 
</span><del>-        if (verbose)
-            dataLogLn(&quot;Made Wasm callee: &quot;, RawPointer(callee));
</del><ins>+        JSWebAssemblyCallee* wasmEntrypointCallee = JSWebAssemblyCallee::create(globalObject-&gt;vm(), WTFMove(function-&gt;wasmEntrypoint));
+        MacroAssembler::repatchPointer(function-&gt;wasmCalleeMoveLocation, wasmEntrypointCallee);
</ins><span class="cx"> 
</span><del>-        callback(internalFunctionIndex, callee);
</del><ins>+        callback(internalFunctionIndex, jsEntrypointCallee, wasmEntrypointCallee);
</ins><span class="cx">     }
</span><span class="cx"> }
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorewasmWasmPlanh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/wasm/WasmPlan.h (209695 => 209696)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/wasm/WasmPlan.h        2016-12-12 02:50:06 UTC (rev 209695)
+++ trunk/Source/JavaScriptCore/wasm/WasmPlan.h        2016-12-12 03:11:18 UTC (rev 209696)
</span><span class="lines">@@ -50,7 +50,7 @@
</span><span class="cx"> 
</span><span class="cx">     JS_EXPORT_PRIVATE void run();
</span><span class="cx"> 
</span><del>-    JS_EXPORT_PRIVATE void initializeCallees(JSGlobalObject*, std::function&lt;void(unsigned, JSWebAssemblyCallee*)&gt;);
</del><ins>+    JS_EXPORT_PRIVATE void initializeCallees(JSGlobalObject*, std::function&lt;void(unsigned, JSWebAssemblyCallee*, JSWebAssemblyCallee*)&gt;);
</ins><span class="cx"> 
</span><span class="cx">     bool WARN_UNUSED_RETURN failed() const { return m_failed; }
</span><span class="cx">     const String&amp; errorMessage() const
</span><span class="lines">@@ -71,12 +71,6 @@
</span><span class="cx">         return m_wasmInternalFunctions.size();
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    B3::Compilation* jsToWasmEntryPointForFunction(size_t i) const
-    {
-        ASSERT(i &gt; m_wasmToJSStubs.size());
-        return m_wasmInternalFunctions.at(i - m_wasmToJSStubs.size())-&gt;jsToWasmEntryPoint.get();
-    }
-
</del><span class="cx">     std::unique_ptr&lt;ModuleInformation&gt;&amp;&amp; takeModuleInformation()
</span><span class="cx">     {
</span><span class="cx">         RELEASE_ASSERT(!failed());
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorewasmjsJSWebAssemblyCalleecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/wasm/js/JSWebAssemblyCallee.cpp (209695 => 209696)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/wasm/js/JSWebAssemblyCallee.cpp        2016-12-12 02:50:06 UTC (rev 209695)
+++ trunk/Source/JavaScriptCore/wasm/js/JSWebAssemblyCallee.cpp        2016-12-12 03:11:18 UTC (rev 209696)
</span><span class="lines">@@ -38,12 +38,11 @@
</span><span class="cx">     : Base(vm, vm.webAssemblyCalleeStructure.get())
</span><span class="cx"> { }
</span><span class="cx"> 
</span><del>-void JSWebAssemblyCallee::finishCreation(VM&amp; vm, std::unique_ptr&lt;B3::Compilation&gt;&amp;&amp; code, std::unique_ptr&lt;B3::Compilation&gt;&amp;&amp; jsToWasmEntryPoint)
</del><ins>+void JSWebAssemblyCallee::finishCreation(VM&amp; vm, Wasm::Entrypoint&amp;&amp; entrypoint)
</ins><span class="cx"> {
</span><span class="cx">     Base::finishCreation(vm);
</span><span class="cx"> 
</span><del>-    m_code = WTFMove(code);
-    m_jsToWasmEntryPoint = WTFMove(jsToWasmEntryPoint);
</del><ins>+    m_entrypoint = WTFMove(entrypoint);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void JSWebAssemblyCallee::destroy(JSCell* cell)
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorewasmjsJSWebAssemblyCalleeh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/wasm/js/JSWebAssemblyCallee.h (209695 => 209696)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/wasm/js/JSWebAssemblyCallee.h        2016-12-12 02:50:06 UTC (rev 209695)
+++ trunk/Source/JavaScriptCore/wasm/js/JSWebAssemblyCallee.h        2016-12-12 03:11:18 UTC (rev 209696)
</span><span class="lines">@@ -27,7 +27,9 @@
</span><span class="cx"> 
</span><span class="cx"> #if ENABLE(WEBASSEMBLY)
</span><span class="cx"> 
</span><del>-#include &quot;JSCallee.h&quot;
</del><ins>+#include &quot;JSCell.h&quot;
+#include &quot;RegisterAtOffsetList.h&quot;
+#include &quot;Structure.h&quot;
</ins><span class="cx"> #include &quot;WasmFormat.h&quot;
</span><span class="cx"> 
</span><span class="cx"> namespace JSC {
</span><span class="lines">@@ -37,10 +39,10 @@
</span><span class="cx">     typedef JSCell Base;
</span><span class="cx">     static const unsigned StructureFlags = Base::StructureFlags | StructureIsImmortal;
</span><span class="cx"> 
</span><del>-    static JSWebAssemblyCallee* create(VM&amp; vm, std::unique_ptr&lt;B3::Compilation&gt;&amp;&amp; code, std::unique_ptr&lt;B3::Compilation&gt;&amp;&amp; jsToWasmEntryPoint)
</del><ins>+    static JSWebAssemblyCallee* create(VM&amp; vm, Wasm::Entrypoint&amp;&amp; entrypoint)
</ins><span class="cx">     {
</span><span class="cx">         JSWebAssemblyCallee* callee = new (NotNull, allocateCell&lt;JSWebAssemblyCallee&gt;(vm.heap)) JSWebAssemblyCallee(vm);
</span><del>-        callee-&gt;finishCreation(vm, std::forward&lt;std::unique_ptr&lt;B3::Compilation&gt;&gt;(code), std::forward&lt;std::unique_ptr&lt;B3::Compilation&gt;&gt;(jsToWasmEntryPoint));
</del><ins>+        callee-&gt;finishCreation(vm, WTFMove(entrypoint));
</ins><span class="cx">         return callee;
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="lines">@@ -53,14 +55,15 @@
</span><span class="cx">     static const bool needsDestruction = true;
</span><span class="cx">     static void destroy(JSCell*);
</span><span class="cx"> 
</span><del>-    void* jsToWasmEntryPoint() { return m_jsToWasmEntryPoint-&gt;code().executableAddress(); }
</del><ins>+    void* entrypoint() { return m_entrypoint.compilation-&gt;code().executableAddress(); }
</ins><span class="cx"> 
</span><ins>+    RegisterAtOffsetList* calleeSaveRegisters() { return &amp;m_entrypoint.calleeSaveRegisters; }
+
</ins><span class="cx"> private:
</span><del>-    void finishCreation(VM&amp;, std::unique_ptr&lt;B3::Compilation&gt;&amp;&amp;, std::unique_ptr&lt;B3::Compilation&gt;&amp;&amp;);
</del><ins>+    void finishCreation(VM&amp;, Wasm::Entrypoint&amp;&amp;);
</ins><span class="cx">     JSWebAssemblyCallee(VM&amp;);
</span><span class="cx"> 
</span><del>-    std::unique_ptr&lt;B3::Compilation&gt; m_code;
-    std::unique_ptr&lt;B3::Compilation&gt; m_jsToWasmEntryPoint;
</del><ins>+    Wasm::Entrypoint m_entrypoint;
</ins><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> } // namespace JSC
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorewasmjsJSWebAssemblyModulecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/wasm/js/JSWebAssemblyModule.cpp (209695 => 209696)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/wasm/js/JSWebAssemblyModule.cpp        2016-12-12 02:50:06 UTC (rev 209695)
+++ trunk/Source/JavaScriptCore/wasm/js/JSWebAssemblyModule.cpp        2016-12-12 03:11:18 UTC (rev 209696)
</span><span class="lines">@@ -58,7 +58,7 @@
</span><span class="cx">     , m_functionIndexSpace(WTFMove(functionIndexSpace))
</span><span class="cx">     , m_calleeCount(calleeCount)
</span><span class="cx"> {
</span><del>-    memset(callees(), 0, m_calleeCount * sizeof(WriteBarrier&lt;JSWebAssemblyCallee&gt;));
</del><ins>+    memset(callees(), 0, m_calleeCount * sizeof(WriteBarrier&lt;JSWebAssemblyCallee&gt;) * 2);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void JSWebAssemblyModule::finishCreation(VM&amp; vm, SymbolTable* exportSymbolTable)
</span><span class="lines">@@ -75,19 +75,27 @@
</span><span class="cx"> 
</span><span class="cx"> void JSWebAssemblyModule::visitChildren(JSCell* cell, SlotVisitor&amp; visitor)
</span><span class="cx"> {
</span><del>-    auto* thisObject = jsCast&lt;JSWebAssemblyModule*&gt;(cell);
</del><ins>+    JSWebAssemblyModule* thisObject = jsCast&lt;JSWebAssemblyModule*&gt;(cell);
</ins><span class="cx">     ASSERT_GC_OBJECT_INHERITS(thisObject, info());
</span><span class="cx"> 
</span><span class="cx">     Base::visitChildren(thisObject, visitor);
</span><span class="cx">     visitor.append(&amp;thisObject-&gt;m_exportSymbolTable);
</span><del>-    for (auto iter = thisObject-&gt;m_callLinkInfos.begin(); !!iter; ++iter)
-        (*iter)-&gt;visitWeak(*thisObject-&gt;vm());
-    for (unsigned i = 0; i &lt; thisObject-&gt;m_calleeCount; i++) {
</del><ins>+    for (unsigned i = 0; i &lt; thisObject-&gt;m_calleeCount * 2; i++) {
</ins><span class="cx">         WriteBarrier&lt;JSWebAssemblyCallee&gt;* callee = &amp;thisObject-&gt;callees()[i];
</span><span class="cx">         visitor.append(callee);
</span><span class="cx">     }
</span><ins>+
+    visitor.addUnconditionalFinalizer(&amp;thisObject-&gt;m_unconditionalFinalizer);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void JSWebAssemblyModule::UnconditionalFinalizer::finalizeUnconditionally()
+{
+    JSWebAssemblyModule* thisObject = bitwise_cast&lt;JSWebAssemblyModule*&gt;(
+        bitwise_cast&lt;char*&gt;(this) - OBJECT_OFFSETOF(JSWebAssemblyModule, m_unconditionalFinalizer));
+    for (auto iter = thisObject-&gt;m_callLinkInfos.begin(); !!iter; ++iter)
+        (*iter)-&gt;visitWeak(*thisObject-&gt;vm());
+}
+
</ins><span class="cx"> } // namespace JSC
</span><span class="cx"> 
</span><span class="cx"> #endif // ENABLE(WEBASSEMBLY)
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorewasmjsJSWebAssemblyModuleh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/wasm/js/JSWebAssemblyModule.h (209695 => 209696)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/wasm/js/JSWebAssemblyModule.h        2016-12-12 02:50:06 UTC (rev 209695)
+++ trunk/Source/JavaScriptCore/wasm/js/JSWebAssemblyModule.h        2016-12-12 03:11:18 UTC (rev 209696)
</span><span class="lines">@@ -29,6 +29,8 @@
</span><span class="cx"> 
</span><span class="cx"> #include &quot;JSDestructibleObject.h&quot;
</span><span class="cx"> #include &quot;JSObject.h&quot;
</span><ins>+#include &quot;JSWebAssemblyCallee.h&quot;
+#include &quot;UnconditionalFinalizer.h&quot;
</ins><span class="cx"> #include &quot;WasmFormat.h&quot;
</span><span class="cx"> #include &lt;wtf/Bag.h&gt;
</span><span class="cx"> #include &lt;wtf/Vector.h&gt;
</span><span class="lines">@@ -35,7 +37,6 @@
</span><span class="cx"> 
</span><span class="cx"> namespace JSC {
</span><span class="cx"> 
</span><del>-class JSWebAssemblyCallee;
</del><span class="cx"> class SymbolTable;
</span><span class="cx"> 
</span><span class="cx"> class JSWebAssemblyModule : public JSDestructibleObject {
</span><span class="lines">@@ -52,7 +53,7 @@
</span><span class="cx">     Wasm::Signature* signatureForFunctionIndexSpace(unsigned functionIndexSpace) const { ASSERT(functionIndexSpace &lt; m_functionIndexSpace.size); return m_functionIndexSpace.buffer.get()[functionIndexSpace].signature; }
</span><span class="cx">     unsigned importCount() const { return m_wasmToJSStubs.size(); }
</span><span class="cx"> 
</span><del>-    JSWebAssemblyCallee* calleeFromFunctionIndexSpace(unsigned functionIndexSpace)
</del><ins>+    JSWebAssemblyCallee* jsEntrypointCalleeFromFunctionIndexSpace(unsigned functionIndexSpace)
</ins><span class="cx">     {
</span><span class="cx">         RELEASE_ASSERT(functionIndexSpace &gt;= importCount());
</span><span class="cx">         unsigned calleeIndex = functionIndexSpace - importCount();
</span><span class="lines">@@ -60,6 +61,26 @@
</span><span class="cx">         return callees()[calleeIndex].get();
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    JSWebAssemblyCallee* wasmEntrypointCalleeFromFunctionIndexSpace(unsigned functionIndexSpace)
+    {
+        RELEASE_ASSERT(functionIndexSpace &gt;= importCount());
+        unsigned calleeIndex = functionIndexSpace - importCount();
+        RELEASE_ASSERT(calleeIndex &lt; m_calleeCount);
+        return callees()[calleeIndex + m_calleeCount].get();
+    }
+
+    void setJSEntrypointCallee(VM&amp; vm, unsigned calleeIndex, JSWebAssemblyCallee* callee)
+    {
+        RELEASE_ASSERT(calleeIndex &lt; m_calleeCount);
+        callees()[calleeIndex].set(vm, this, callee);
+    }
+
+    void setWasmEntrypointCallee(VM&amp; vm, unsigned calleeIndex, JSWebAssemblyCallee* callee)
+    {
+        RELEASE_ASSERT(calleeIndex &lt; m_calleeCount);
+        callees()[calleeIndex + m_calleeCount].set(vm, this, callee);
+    }
+
</ins><span class="cx">     WriteBarrier&lt;JSWebAssemblyCallee&gt;* callees()
</span><span class="cx">     {
</span><span class="cx">         return bitwise_cast&lt;WriteBarrier&lt;JSWebAssemblyCallee&gt;*&gt;(bitwise_cast&lt;char*&gt;(this) + offsetOfCallees());
</span><span class="lines">@@ -81,9 +102,14 @@
</span><span class="cx"> 
</span><span class="cx">     static size_t allocationSize(unsigned numCallees)
</span><span class="cx">     {
</span><del>-        return offsetOfCallees() + sizeof(WriteBarrier&lt;JSWebAssemblyCallee&gt;) * numCallees;
</del><ins>+        return offsetOfCallees() + sizeof(WriteBarrier&lt;JSWebAssemblyCallee&gt;) * numCallees * 2;
</ins><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    class UnconditionalFinalizer : public JSC::UnconditionalFinalizer { 
+        void finalizeUnconditionally() override;
+    };
+
+    UnconditionalFinalizer m_unconditionalFinalizer;
</ins><span class="cx">     std::unique_ptr&lt;Wasm::ModuleInformation&gt; m_moduleInformation;
</span><span class="cx">     Bag&lt;CallLinkInfo&gt; m_callLinkInfos;
</span><span class="cx">     WriteBarrier&lt;SymbolTable&gt; m_exportSymbolTable;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorewasmjsJSWebAssemblyRuntimeErrorh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/wasm/js/JSWebAssemblyRuntimeError.h (209695 => 209696)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/wasm/js/JSWebAssemblyRuntimeError.h        2016-12-12 02:50:06 UTC (rev 209695)
+++ trunk/Source/JavaScriptCore/wasm/js/JSWebAssemblyRuntimeError.h        2016-12-12 03:11:18 UTC (rev 209696)
</span><span class="lines">@@ -35,7 +35,7 @@
</span><span class="cx"> public:
</span><span class="cx">     typedef ErrorInstance Base;
</span><span class="cx"> 
</span><del>-    static JSWebAssemblyRuntimeError* create(ExecState*, Structure*, const String&amp;, bool);
</del><ins>+    static JSWebAssemblyRuntimeError* create(ExecState*, Structure*, const String&amp;, bool useCurrentFrame = true);
</ins><span class="cx">     static JSWebAssemblyRuntimeError* create(ExecState* exec, Structure* structure, JSValue message, bool useCurrentFrame)
</span><span class="cx">     {
</span><span class="cx">         return create(exec, structure, message.isUndefined() ? String() : message.toString(exec)-&gt;value(exec), useCurrentFrame);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorewasmjsWebAssemblyFunctioncpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/wasm/js/WebAssemblyFunction.cpp (209695 => 209696)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/wasm/js/WebAssemblyFunction.cpp        2016-12-12 02:50:06 UTC (rev 209695)
+++ trunk/Source/JavaScriptCore/wasm/js/WebAssemblyFunction.cpp        2016-12-12 03:11:18 UTC (rev 209696)
</span><span class="lines">@@ -116,7 +116,8 @@
</span><span class="cx"> 
</span><span class="cx">     JSWebAssemblyInstance* prevJSWebAssemblyInstance = vm.topJSWebAssemblyInstance;
</span><span class="cx">     vm.topJSWebAssemblyInstance = instance();
</span><del>-    EncodedJSValue rawResult = vmEntryToWasm(webAssemblyCallee()-&gt;jsToWasmEntryPoint(), &amp;vm, protoCallFrame);
</del><ins>+    ASSERT(instance());
+    EncodedJSValue rawResult = vmEntryToWasm(webAssemblyCallee()-&gt;entrypoint(), &amp;vm, protoCallFrame);
</ins><span class="cx">     vm.topJSWebAssemblyInstance = prevJSWebAssemblyInstance;
</span><span class="cx"> 
</span><span class="cx">     // FIXME is this correct? https://bugs.webkit.org/show_bug.cgi?id=164876
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorewasmjsWebAssemblyInstanceConstructorcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/wasm/js/WebAssemblyInstanceConstructor.cpp (209695 => 209696)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/wasm/js/WebAssemblyInstanceConstructor.cpp        2016-12-12 02:50:06 UTC (rev 209695)
+++ trunk/Source/JavaScriptCore/wasm/js/WebAssemblyInstanceConstructor.cpp        2016-12-12 03:11:18 UTC (rev 209696)
</span><span class="lines">@@ -193,6 +193,8 @@
</span><span class="cx">             RELEASE_ASSERT(!moduleInformation.memory.isImport());
</span><span class="cx">             // We create a memory when it's a memory definition.
</span><span class="cx">             std::unique_ptr&lt;Wasm::Memory&gt; memory = std::make_unique&lt;Wasm::Memory&gt;(moduleInformation.memory.initial(), moduleInformation.memory.maximum());
</span><ins>+            if (!memory-&gt;isValid())
+                return JSValue::encode(throwException(exec, throwScope, createOutOfMemoryError(exec)));
</ins><span class="cx">             instance-&gt;setMemory(vm,
</span><span class="cx">                JSWebAssemblyMemory::create(vm, exec-&gt;lexicalGlobalObject()-&gt;WebAssemblyMemoryStructure(), WTFMove(memory)));
</span><span class="cx">         }
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorewasmjsWebAssemblyMemoryConstructorcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/wasm/js/WebAssemblyMemoryConstructor.cpp (209695 => 209696)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/wasm/js/WebAssemblyMemoryConstructor.cpp        2016-12-12 02:50:06 UTC (rev 209695)
+++ trunk/Source/JavaScriptCore/wasm/js/WebAssemblyMemoryConstructor.cpp        2016-12-12 03:11:18 UTC (rev 209696)
</span><span class="lines">@@ -107,6 +107,8 @@
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     std::unique_ptr&lt;Wasm::Memory&gt; memory = std::make_unique&lt;Wasm::Memory&gt;(initialPageCount, maximumPageCount);
</span><ins>+    if (!memory-&gt;isValid())
+        return JSValue::encode(throwException(exec, throwScope, createOutOfMemoryError(exec)));
</ins><span class="cx"> 
</span><span class="cx">     return JSValue::encode(JSWebAssemblyMemory::create(vm, exec-&gt;lexicalGlobalObject()-&gt;WebAssemblyMemoryStructure(), WTFMove(memory)));
</span><span class="cx"> }
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorewasmjsWebAssemblyModuleConstructorcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/wasm/js/WebAssemblyModuleConstructor.cpp (209695 => 209696)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/wasm/js/WebAssemblyModuleConstructor.cpp        2016-12-12 02:50:06 UTC (rev 209695)
+++ trunk/Source/JavaScriptCore/wasm/js/WebAssemblyModuleConstructor.cpp        2016-12-12 03:11:18 UTC (rev 209696)
</span><span class="lines">@@ -92,8 +92,9 @@
</span><span class="cx">     unsigned calleeCount = plan.internalFunctionCount();
</span><span class="cx">     JSWebAssemblyModule* result = JSWebAssemblyModule::create(vm, structure, plan.takeModuleInformation(), plan.takeCallLinkInfos(), plan.takeWasmToJSStubs(), plan.takeFunctionIndexSpace(), exportSymbolTable, calleeCount);
</span><span class="cx">     plan.initializeCallees(state-&gt;jsCallee()-&gt;globalObject(), 
</span><del>-        [&amp;] (unsigned calleeIndex, JSWebAssemblyCallee* callee) {
-            result-&gt;callees()[calleeIndex].set(vm, result, callee);
</del><ins>+        [&amp;] (unsigned calleeIndex, JSWebAssemblyCallee* jsEntrypointCallee, JSWebAssemblyCallee* wasmEntrypointCallee) {
+            result-&gt;setJSEntrypointCallee(vm, calleeIndex, jsEntrypointCallee);
+            result-&gt;setWasmEntrypointCallee(vm, calleeIndex, wasmEntrypointCallee);
</ins><span class="cx">         });
</span><span class="cx">     return JSValue::encode(result);
</span><span class="cx"> }
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorewasmjsWebAssemblyModuleRecordcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/wasm/js/WebAssemblyModuleRecord.cpp (209695 => 209696)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/wasm/js/WebAssemblyModuleRecord.cpp        2016-12-12 02:50:06 UTC (rev 209695)
+++ trunk/Source/JavaScriptCore/wasm/js/WebAssemblyModuleRecord.cpp        2016-12-12 03:11:18 UTC (rev 209696)
</span><span class="lines">@@ -136,7 +136,7 @@
</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* wasmCallee = module-&gt;calleeFromFunctionIndexSpace(exp.functionIndex);
</del><ins>+            JSWebAssemblyCallee* wasmCallee = module-&gt;jsEntrypointCalleeFromFunctionIndexSpace(exp.functionIndex);
</ins><span class="cx">             Wasm::Signature* signature = module-&gt;signatureForFunctionIndexSpace(exp.functionIndex);
</span><span class="cx">             WebAssemblyFunction* function = WebAssemblyFunction::create(vm, globalObject, signature-&gt;arguments.size(), exp.field.string(), instance, wasmCallee, signature);
</span><span class="cx">             exportedValue = function;
</span><span class="lines">@@ -174,7 +174,7 @@
</span><span class="cx">         // FIXME can start call imports / tables? This assumes not. https://github.com/WebAssembly/design/issues/896
</span><span class="cx">         if (!m_startFunction.get()) {
</span><span class="cx">             // The start function wasn't added above. It must be a purely internal function.
</span><del>-            JSWebAssemblyCallee* wasmCallee = module-&gt;calleeFromFunctionIndexSpace(startFunctionIndexSpace);
</del><ins>+            JSWebAssemblyCallee* wasmCallee = module-&gt;jsEntrypointCalleeFromFunctionIndexSpace(startFunctionIndexSpace);
</ins><span class="cx">             WebAssemblyFunction* function = WebAssemblyFunction::create(vm, globalObject, signature-&gt;arguments.size(), &quot;start&quot;, instance, wasmCallee, signature);
</span><span class="cx">             m_startFunction.set(vm, this, function);
</span><span class="cx">         }
</span></span></pre></div>
<a id="trunkSourceWebCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/ChangeLog (209695 => 209696)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/ChangeLog        2016-12-12 02:50:06 UTC (rev 209695)
+++ trunk/Source/WebCore/ChangeLog        2016-12-12 03:11:18 UTC (rev 209696)
</span><span class="lines">@@ -1,3 +1,13 @@
</span><ins>+2016-12-11  Saam Barati  &lt;sbarati@apple.com&gt;
+
+        We should be able to throw exceptions from Wasm code and when Wasm frames are on the stack
+        https://bugs.webkit.org/show_bug.cgi?id=165429
+
+        Reviewed by Keith Miller.
+
+        * bindings/js/JSDOMBinding.cpp:
+        (WebCore::GetCallerGlobalObjectFunctor::operator()):
+
</ins><span class="cx"> 2016-12-11  Darin Adler  &lt;darin@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Remove uses of Dictionary in WebRTC IDL files
</span></span></pre></div>
<a id="trunkSourceWebCorebindingsjsJSDOMBindingcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/bindings/js/JSDOMBinding.cpp (209695 => 209696)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/bindings/js/JSDOMBinding.cpp        2016-12-12 02:50:06 UTC (rev 209695)
+++ trunk/Source/WebCore/bindings/js/JSDOMBinding.cpp        2016-12-12 03:11:18 UTC (rev 209696)
</span><span class="lines">@@ -759,7 +759,11 @@
</span><span class="cx">             m_globalObject = codeBlock-&gt;globalObject();
</span><span class="cx">         else {
</span><span class="cx">             ASSERT(visitor-&gt;callee());
</span><del>-            m_globalObject = visitor-&gt;callee()-&gt;globalObject();
</del><ins>+            // FIXME: Callee is not an object if the caller is Web Assembly.
+            // Figure out what to do here. We can probably get the global object
+            // from the top-most Wasm Instance. https://bugs.webkit.org/show_bug.cgi?id=165721
+            if (visitor-&gt;callee()-&gt;isObject())
+                m_globalObject = jsCast&lt;JSObject*&gt;(visitor-&gt;callee())-&gt;globalObject();
</ins><span class="cx">         }
</span><span class="cx">         return StackVisitor::Done;
</span><span class="cx">     }
</span></span></pre>
</div>
</div>

</body>
</html>