Title: [209696] trunk
Revision
209696
Author
[email protected]
Date
2016-12-11 19:11:18 -0800 (Sun, 11 Dec 2016)

Log Message

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/_javascript_Core:

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()):

Modified Paths

Added Paths

Diff

Modified: trunk/JSTests/ChangeLog (209695 => 209696)


--- trunk/JSTests/ChangeLog	2016-12-12 02:50:06 UTC (rev 209695)
+++ trunk/JSTests/ChangeLog	2016-12-12 03:11:18 UTC (rev 209696)
@@ -1,3 +1,23 @@
+2016-12-11  Saam Barati  <[email protected]>
+
+        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):
+
 2016-12-10  Commit Queue  <[email protected]>
 
         Unreviewed, rolling out r209653, r209654, r209663, and

Added: trunk/JSTests/wasm/function-tests/trap-load.js (0 => 209696)


--- 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)
@@ -0,0 +1,104 @@
+import Builder from '../Builder.js'
+
+const pageSize = 64 * 1024;
+const numPages = 10;
+
+const builder = (new Builder())
+    .Type().End()
+    .Import()
+        .Memory("a", "b", {initial: numPages})
+    .End()
+    .Function().End()
+    .Export().Function("foo").End()
+    .Code()
+        .Function("foo", {params: ["i32"], ret: "i32"})
+            .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("Bad")
+}
+
+function wasmFrameCountFromError(e) {
+    let stackFrames = e.stack.split("\n").filter((s) => s.indexOf("<wasm>@[wasm code]") !== -1);
+    return stackFrames.length;
+}
+
+for (let i = 0; i < 1000; i++) {
+    let threw = false;
+    try {
+        foo(numPages * pageSize + 1);
+    } catch(e) {
+        assert(e instanceof WebAssembly.RuntimeError);
+        assert(e.message === "Out of bounds memory access");
+        threw = true;
+        assert(wasmFrameCountFromError(e) === 2);
+    }
+    assert(threw);
+}
+
+{
+    const builder = (new Builder())
+        .Type().End()
+        .Import()
+            .Memory("imp", "mem", {initial: numPages})
+            .Function("imp", "func", { params: ["i32"] })
+        .End()
+        .Function().End()
+        .Export().Function("foo").End()
+        .Code()
+            .Function("foo", {params: ["i32", "i32"]})
+                .GetLocal(0)
+                .I32Const(0)
+                .I32Eq()
+                .If("void", b =>
+                    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 < 10000; i++) {
+        let threw = false;
+        try {
+            foo(25, address);
+        } catch(e) {
+            assert(e instanceof WebAssembly.RuntimeError);
+            assert(e.message === "Out of bounds memory access");
+            // 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);
+    }
+}

Added: trunk/JSTests/wasm/function-tests/trap-store.js (0 => 209696)


--- 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)
@@ -0,0 +1,97 @@
+import Builder from '../Builder.js'
+
+function assert(b) {
+    if (!b)
+        throw new Error("Bad")
+}
+
+const pageSize = 64 * 1024;
+const numPages = 10;
+
+{
+    const builder = (new Builder())
+        .Type().End()
+        .Import()
+            .Memory("a", "b", {initial: numPages})
+        .End()
+        .Function().End()
+        .Export().Function("foo").End()
+        .Code()
+            .Function("foo", {params: ["i32", "i32"]})
+                .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 < 10000; i++) {
+        let threw = false;
+        try {
+            foo(i, numPages * pageSize + 1);
+        } catch(e) {
+            assert(e instanceof WebAssembly.RuntimeError);
+            assert(e.message === "Out of bounds memory access");
+            threw = true;
+        }
+        assert(threw);
+    }
+}
+
+
+{
+    const builder = (new Builder())
+        .Type().End()
+        .Import()
+            .Memory("imp", "mem", {initial: numPages})
+            .Function("imp", "func", { params: ["i32"] })
+        .End()
+        .Function().End()
+        .Export().Function("foo").End()
+        .Code()
+            .Function("foo", {params: ["i32", "i32"]})
+                .GetLocal(0)
+                .I32Const(0)
+                .I32Eq()
+                .If("void", b =>
+                    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 < 10000; i++) {
+        let threw = false;
+        try {
+            foo(25, address);
+        } catch(e) {
+            assert(e instanceof WebAssembly.RuntimeError);
+            assert(e.message === "Out of bounds memory access");
+            threw = true;
+        }
+        assert(threw);
+    }
+}

Modified: trunk/JSTests/wasm/js-api/test_memory_constructor.js (209695 => 209696)


--- 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)
@@ -39,9 +39,12 @@
         testInvalidSize({initial: v}, "initial");
     }
 
-    // These should not throw.
-    new WebAssembly.Memory({initial: maxPageCount});
-    new WebAssembly.Memory({initial: maxPageCount, maximum: maxPageCount});
+    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.
+    }
 
     testInvalidInitial(2**31);
     testInvalidInitial(maxPageCount + 1);

Modified: trunk/Source/_javascript_Core/API/JSContextRef.cpp (209695 => 209696)


--- trunk/Source/_javascript_Core/API/JSContextRef.cpp	2016-12-12 02:50:06 UTC (rev 209695)
+++ trunk/Source/_javascript_Core/API/JSContextRef.cpp	2016-12-12 03:11:18 UTC (rev 209696)
@@ -260,7 +260,7 @@
         if (m_remainingCapacityForFrameCapture) {
             // If callee is unknown, but we've not added any frame yet, we should
             // still add the frame, because something called us, and gave us arguments.
-            JSObject* callee = visitor->callee();
+            JSCell* callee = visitor->callee();
             if (!callee && visitor->index())
                 return StackVisitor::Done;
 
@@ -273,7 +273,7 @@
             builder.append(visitor->functionName());
             builder.appendLiteral("() at ");
             builder.append(visitor->sourceURL());
-            if (visitor->isJSFrame()) {
+            if (visitor->hasLineAndColumnInfo()) {
                 builder.append(':');
                 unsigned lineNumber;
                 unsigned unusedColumn;

Modified: trunk/Source/_javascript_Core/ChangeLog (209695 => 209696)


--- trunk/Source/_javascript_Core/ChangeLog	2016-12-12 02:50:06 UTC (rev 209695)
+++ trunk/Source/_javascript_Core/ChangeLog	2016-12-12 03:11:18 UTC (rev 209696)
@@ -1,3 +1,137 @@
+2016-12-11  Saam Barati  <[email protected]>
+
+        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):
+
 2016-12-11  Filip Pizlo  <[email protected]>
 
         Re-enable concurrent GC.

Modified: trunk/Source/_javascript_Core/inspector/ScriptCallStackFactory.cpp (209695 => 209696)


--- trunk/Source/_javascript_Core/inspector/ScriptCallStackFactory.cpp	2016-12-12 02:50:06 UTC (rev 209695)
+++ trunk/Source/_javascript_Core/inspector/ScriptCallStackFactory.cpp	2016-12-12 03:11:18 UTC (rev 209696)
@@ -156,7 +156,7 @@
             extractSourceInformationFromException(exec, exceptionObject, &lineNumber, &columnNumber, &exceptionSourceURL);
             frames.append(ScriptCallFrame(String(), exceptionSourceURL, noSourceID, lineNumber, columnNumber));
         } else {
-            if (stackTrace[0].isNative() || stackTrace[0].sourceURL().isEmpty()) {
+            if (!stackTrace[0].hasLineAndColumnInfo() || stackTrace[0].sourceURL().isEmpty()) {
                 const ScriptCallFrame& firstCallFrame = frames.first();
                 extractSourceInformationFromException(exec, exceptionObject, &lineNumber, &columnNumber, &exceptionSourceURL);
                 frames[0] = ScriptCallFrame(firstCallFrame.functionName(), exceptionSourceURL, stackTrace[0].sourceID(), lineNumber, columnNumber);

Modified: trunk/Source/_javascript_Core/interpreter/CallFrame.cpp (209695 => 209696)


--- trunk/Source/_javascript_Core/interpreter/CallFrame.cpp	2016-12-12 02:50:06 UTC (rev 209695)
+++ trunk/Source/_javascript_Core/interpreter/CallFrame.cpp	2016-12-12 03:11:18 UTC (rev 209696)
@@ -185,8 +185,11 @@
 
 JSGlobalObject* CallFrame::vmEntryGlobalObject()
 {
-    if (this == lexicalGlobalObject()->globalExec())
-        return lexicalGlobalObject();
+    if (callee()->isObject()) { 
+        if (this == lexicalGlobalObject()->globalExec())
+            return lexicalGlobalObject();
+    }
+    // If we're not an object, we're wasm, and therefore we're executing code and the below is safe.
 
     // For any ExecState that's not a globalExec, the 
     // dynamic global object must be set since code is running

Modified: trunk/Source/_javascript_Core/interpreter/CallFrame.h (209695 => 209696)


--- trunk/Source/_javascript_Core/interpreter/CallFrame.h	2016-12-12 02:50:06 UTC (rev 209695)
+++ trunk/Source/_javascript_Core/interpreter/CallFrame.h	2016-12-12 03:11:18 UTC (rev 209696)
@@ -86,9 +86,9 @@
     public:
         static const int headerSizeInRegisters = CallFrameSlot::argumentCount + 1;
 
-        JSCell* callee() const { return this[CallFrameSlot::callee].unboxedCell(); }
         JSValue calleeAsValue() const { return this[CallFrameSlot::callee].jsValue(); }
         JSObject* jsCallee() const { return this[CallFrameSlot::callee].object(); }
+        JSCell* callee() const { return this[CallFrameSlot::callee].unboxedCell(); }
         SUPPRESS_ASAN JSValue unsafeCallee() const { return this[CallFrameSlot::callee].asanUnsafeJSValue(); }
         CodeBlock* codeBlock() const { return this[CallFrameSlot::codeBlock].Register::codeBlock(); }
         CodeBlock** addressOfCodeBlock() const { return bitwise_cast<CodeBlock**>(this + CallFrameSlot::codeBlock); }

Modified: trunk/Source/_javascript_Core/interpreter/Interpreter.cpp (209695 => 209696)


--- trunk/Source/_javascript_Core/interpreter/Interpreter.cpp	2016-12-12 02:50:06 UTC (rev 209695)
+++ trunk/Source/_javascript_Core/interpreter/Interpreter.cpp	2016-12-12 03:11:18 UTC (rev 209696)
@@ -63,6 +63,7 @@
 #include "Register.h"
 #include "ScopedArguments.h"
 #include "StackAlignment.h"
+#include "StackFrame.h"
 #include "StackVisitor.h"
 #include "StrictEvalActivation.h"
 #include "StrongInlines.h"
@@ -466,21 +467,14 @@
         }
 
         if (m_remainingCapacityForFrameCapture) {
-            if (visitor->isJSFrame()
+            if (!visitor->isWasmFrame()
+                && !!visitor->codeBlock()
                 && !visitor->codeBlock()->unlinkedCodeBlock()->isBuiltinFunction()) {
-                StackFrame s = {
-                    Strong<JSObject>(m_vm, visitor->callee()),
-                    Strong<CodeBlock>(m_vm, visitor->codeBlock()),
-                    visitor->bytecodeOffset()
-                };
-                m_results.append(s);
+                m_results.append(
+                    StackFrame(m_vm, visitor->callee(), visitor->codeBlock(), visitor->bytecodeOffset()));
             } else {
-                StackFrame s = {
-                    Strong<JSObject>(m_vm, visitor->callee()),
-                    Strong<CodeBlock>(),
-                    0 // unused value because codeBlock is null.
-                };
-                m_results.append(s);
+                m_results.append(
+                    StackFrame(m_vm,  visitor->callee()));
             }
     
             m_remainingCapacityForFrameCapture--;
@@ -608,24 +602,21 @@
 
         m_handler = nullptr;
         if (!m_isTermination) {
-            if (m_codeBlock)
+            if (m_codeBlock) {
                 m_handler = findExceptionHandler(visitor, m_codeBlock, RequiredHandler::AnyHandler);
+                if (m_handler)
+                    return StackVisitor::Done;
+            }
         }
 
-        if (m_handler)
-            return StackVisitor::Done;
-
         notifyDebuggerOfUnwinding(m_callFrame);
 
+        copyCalleeSavesToVMEntryFrameCalleeSavesBuffer(visitor);
+
         bool shouldStopUnwinding = visitor->callerIsVMEntryFrame();
-        if (shouldStopUnwinding) {
-            copyCalleeSavesToVMEntryFrameCalleeSavesBuffer(visitor);
-
+        if (shouldStopUnwinding)
             return StackVisitor::Done;
-        }
 
-        copyCalleeSavesToVMEntryFrameCalleeSavesBuffer(visitor);
-
         return StackVisitor::Continue;
     }
 
@@ -633,16 +624,8 @@
     void copyCalleeSavesToVMEntryFrameCalleeSavesBuffer(StackVisitor& visitor) const
     {
 #if ENABLE(JIT) && NUMBER_OF_CALLEE_SAVES_REGISTERS > 0
+        RegisterAtOffsetList* currentCalleeSaves = visitor->calleeSaveRegisters();
 
-        if (!visitor->isJSFrame())
-            return;
-
-#if ENABLE(DFG_JIT)
-        if (visitor->inlineCallFrame())
-            return;
-#endif
-        RegisterAtOffsetList* currentCalleeSaves = m_codeBlock ? m_codeBlock->calleeSaveRegisters() : nullptr;
-
         if (!currentCalleeSaves)
             return;
 

Modified: trunk/Source/_javascript_Core/interpreter/Interpreter.h (209695 => 209696)


--- trunk/Source/_javascript_Core/interpreter/Interpreter.h	2016-12-12 02:50:06 UTC (rev 209695)
+++ trunk/Source/_javascript_Core/interpreter/Interpreter.h	2016-12-12 03:11:18 UTC (rev 209696)
@@ -37,7 +37,6 @@
 #include "JSObject.h"
 #include "Opcode.h"
 #include "StackAlignment.h"
-#include "StackFrame.h"
 #include <wtf/HashMap.h>
 
 #if !ENABLE(JIT)
@@ -60,6 +59,7 @@
     class ModuleProgramExecutable;
     class Register;
     class JSScope;
+    class StackFrame;
     struct CallFrameClosure;
     struct HandlerInfo;
     struct Instruction;

Modified: trunk/Source/_javascript_Core/interpreter/ShadowChicken.cpp (209695 => 209696)


--- trunk/Source/_javascript_Core/interpreter/ShadowChicken.cpp	2016-12-12 02:50:06 UTC (rev 209695)
+++ trunk/Source/_javascript_Core/interpreter/ShadowChicken.cpp	2016-12-12 03:11:18 UTC (rev 209696)
@@ -155,8 +155,16 @@
             exec, [&] (StackVisitor& visitor) -> StackVisitor::Status {
                 if (visitor->isInlinedFrame())
                     return StackVisitor::Continue;
+                if (visitor->isWasmFrame()) {
+                    // FIXME: Make shadow chicken work with Wasm.
+                    // https://bugs.webkit.org/show_bug.cgi?id=165441
+                    return StackVisitor::Continue;
+                }
+
                 bool isTailDeleted = false;
-                stackRightNow.append(Frame(visitor->callee(), visitor->callFrame(), isTailDeleted));
+                // FIXME: Make shadow chicken work with Wasm.
+                // https://bugs.webkit.org/show_bug.cgi?id=165441
+                stackRightNow.append(Frame(jsCast<JSObject*>(visitor->callee()), visitor->callFrame(), isTailDeleted));
                 return StackVisitor::Continue;
             });
         stackRightNow.reverse();
@@ -272,6 +280,11 @@
                 return StackVisitor::Continue;
             }
 
+            if (visitor->isWasmFrame()) {
+                // FIXME: Make shadow chicken work with Wasm.
+                return StackVisitor::Continue;
+            }
+
             CallFrame* callFrame = visitor->callFrame();
             if (verbose)
                 dataLog("    Examining ", RawPointer(callFrame), "\n");
@@ -293,7 +306,7 @@
                 if (scope)
                     RELEASE_ASSERT(scope->inherits(JSScope::info()));
             }
-            toPush.append(Frame(visitor->callee(), callFrame, isTailDeleted, callFrame->thisValue(), scope, codeBlock, callFrame->callSiteIndex()));
+            toPush.append(Frame(jsCast<JSObject*>(visitor->callee()), callFrame, isTailDeleted, callFrame->thisValue(), scope, codeBlock, callFrame->callSiteIndex()));
 
             if (indexInLog < logCursorIndex
                 // This condition protects us from the case where advanceIndexInLogTo didn't find

Modified: trunk/Source/_javascript_Core/interpreter/StackVisitor.cpp (209695 => 209696)


--- trunk/Source/_javascript_Core/interpreter/StackVisitor.cpp	2016-12-12 02:50:06 UTC (rev 209695)
+++ trunk/Source/_javascript_Core/interpreter/StackVisitor.cpp	2016-12-12 03:11:18 UTC (rev 209696)
@@ -31,6 +31,7 @@
 #include "InlineCallFrame.h"
 #include "Interpreter.h"
 #include "JSCInlines.h"
+#include "JSWebAssemblyCallee.h"
 #include <wtf/text/StringBuilder.h>
 
 namespace JSC {
@@ -38,6 +39,7 @@
 StackVisitor::StackVisitor(CallFrame* startFrame)
 {
     m_frame.m_index = 0;
+    m_frame.m_isWasmFrame = false;
     CallFrame* topFrame;
     if (startFrame) {
         m_frame.m_VMEntryFrame = startFrame->vm().topVMEntryFrame;
@@ -101,6 +103,11 @@
         return;
     }
 
+    if (callFrame->callee()->isAnyWasmCallee()) {
+        readNonInlinedFrame(callFrame);
+        return;
+    }
+
 #if !ENABLE(DFG_JIT)
     readNonInlinedFrame(callFrame);
 
@@ -146,11 +153,23 @@
     m_frame.m_CallerVMEntryFrame = m_frame.m_VMEntryFrame;
     m_frame.m_callerFrame = callFrame->callerFrame(m_frame.m_CallerVMEntryFrame);
     m_frame.m_callerIsVMEntryFrame = m_frame.m_CallerVMEntryFrame != m_frame.m_VMEntryFrame;
-    m_frame.m_callee = callFrame->jsCallee();
-    m_frame.m_codeBlock = callFrame->codeBlock();
-    m_frame.m_bytecodeOffset = !m_frame.codeBlock() ? 0
-        : codeOrigin ? codeOrigin->bytecodeIndex
-        : callFrame->bytecodeOffset();
+    m_frame.m_isWasmFrame = false;
+
+    JSCell* callee = callFrame->callee();
+    m_frame.m_callee = callee;
+
+    if (callee->isAnyWasmCallee()) {
+        m_frame.m_isWasmFrame = true;
+        m_frame.m_codeBlock = nullptr;
+        m_frame.m_bytecodeOffset = 0;
+    } else {
+        m_frame.m_codeBlock = callFrame->codeBlock();
+        m_frame.m_bytecodeOffset = !m_frame.codeBlock() ? 0
+            : codeOrigin ? codeOrigin->bytecodeIndex
+            : callFrame->bytecodeOffset();
+
+    }
+
 #if ENABLE(DFG_JIT)
     m_frame.m_inlineCallFrame = 0;
 #endif
@@ -167,6 +186,7 @@
 void StackVisitor::readInlinedFrame(CallFrame* callFrame, CodeOrigin* codeOrigin)
 {
     ASSERT(codeOrigin);
+    m_frame.m_isWasmFrame = false;
 
     int frameOffset = inlinedFrameOffset(codeOrigin);
     bool isInlined = !!frameOffset;
@@ -198,9 +218,17 @@
 }
 #endif // ENABLE(DFG_JIT)
 
+bool StackVisitor::Frame::isWasmFrame() const
+{
+    return m_isWasmFrame;
+}
+
 StackVisitor::Frame::CodeType StackVisitor::Frame::codeType() const
 {
-    if (!isJSFrame())
+    if (isWasmFrame())
+        return CodeType::Wasm;
+
+    if (!codeBlock())
         return CodeType::Native;
 
     switch (codeBlock()->codeType()) {
@@ -217,12 +245,39 @@
     return CodeType::Global;
 }
 
+RegisterAtOffsetList* StackVisitor::Frame::calleeSaveRegisters()
+{
+    if (isInlinedFrame())
+        return nullptr;
+
+#if ENABLE(WEBASSEMBLY)
+    if (isWasmFrame()) {
+        if (JSCell* callee = this->callee()) {
+            if (JSWebAssemblyCallee* wasmCallee = jsDynamicCast<JSWebAssemblyCallee*>(callee))
+                return wasmCallee->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->codeBlock())
+        return codeBlock->calleeSaveRegisters();
+
+    return nullptr;
+}
+
 String StackVisitor::Frame::functionName() const
 {
     String traceLine;
-    JSObject* callee = this->callee();
+    JSCell* callee = this->callee();
 
     switch (codeType()) {
+    case CodeType::Wasm:
+        traceLine = ASCIILiteral("wasm code");
+        break;
     case CodeType::Eval:
         traceLine = ASCIILiteral("eval code");
         break;
@@ -231,10 +286,10 @@
         break;
     case CodeType::Native:
         if (callee)
-            traceLine = getCalculatedDisplayName(callFrame()->vm(), callee).impl();
+            traceLine = getCalculatedDisplayName(callFrame()->vm(), jsCast<JSObject*>(callee)).impl();
         break;
     case CodeType::Function:
-        traceLine = getCalculatedDisplayName(callFrame()->vm(), callee).impl();
+        traceLine = getCalculatedDisplayName(callFrame()->vm(), jsCast<JSObject*>(callee)).impl();
         break;
     case CodeType::Global:
         traceLine = ASCIILiteral("global code");
@@ -260,6 +315,9 @@
     case CodeType::Native:
         traceLine = ASCIILiteral("[native code]");
         break;
+    case CodeType::Wasm:
+        traceLine = ASCIILiteral("[wasm code]");
+        break;
     }
     return traceLine.isNull() ? emptyString() : traceLine;
 }
@@ -274,7 +332,7 @@
         if (!functionName.isEmpty())
             traceBuild.append('@');
         traceBuild.append(sourceURL);
-        if (isJSFrame()) {
+        if (hasLineAndColumnInfo()) {
             unsigned line = 0;
             unsigned column = 0;
             computeLineAndColumn(line, column);
@@ -314,6 +372,11 @@
     return arguments;
 }
 
+bool StackVisitor::Frame::hasLineAndColumnInfo() const
+{
+    return !!codeBlock();
+}
+
 void StackVisitor::Frame::computeLineAndColumn(unsigned& line, unsigned& column) const
 {
     CodeBlock* codeBlock = this->codeBlock();
@@ -350,6 +413,7 @@
 #if ENABLE(DFG_JIT)
     m_inlineCallFrame = 0;
 #endif
+    m_isWasmFrame = false;
 }
 
 void StackVisitor::Frame::dump(PrintStream& out, Indenter indent) const

Modified: trunk/Source/_javascript_Core/interpreter/StackVisitor.h (209695 => 209696)


--- trunk/Source/_javascript_Core/interpreter/StackVisitor.h	2016-12-12 02:50:06 UTC (rev 209695)
+++ trunk/Source/_javascript_Core/interpreter/StackVisitor.h	2016-12-12 03:11:18 UTC (rev 209696)
@@ -41,6 +41,7 @@
 class JSObject;
 class ClonedArguments;
 class Register;
+class RegisterAtOffsetList;
 
 typedef ExecState CallFrame;
 
@@ -53,7 +54,8 @@
             Eval,
             Function,
             Module,
-            Native
+            Native,
+            Wasm
         };
 
         size_t index() const { return m_index; }
@@ -60,7 +62,7 @@
         size_t argumentCountIncludingThis() const { return m_argumentCountIncludingThis; }
         bool callerIsVMEntryFrame() const { return m_callerIsVMEntryFrame; }
         CallFrame* callerFrame() const { return m_callerFrame; }
-        JSObject* callee() const { return m_callee; }
+        JSCell* callee() const { return m_callee; }
         CodeBlock* codeBlock() const { return m_codeBlock; }
         unsigned bytecodeOffset() const { return m_bytecodeOffset; }
         InlineCallFrame* inlineCallFrame() const {
@@ -71,8 +73,9 @@
 #endif
         }
 
-        bool isJSFrame() const { return !!codeBlock(); }
+        bool isNativeFrame() const { return !codeBlock() && !isWasmFrame(); }
         bool isInlinedFrame() const { return !!inlineCallFrame(); }
+        bool isWasmFrame() const;
 
         JS_EXPORT_PRIVATE String functionName() const;
         JS_EXPORT_PRIVATE String sourceURL() const;
@@ -81,8 +84,11 @@
         intptr_t sourceID();
 
         CodeType codeType() const;
+        bool hasLineAndColumnInfo() const;
         JS_EXPORT_PRIVATE void computeLineAndColumn(unsigned& line, unsigned& column) const;
 
+        RegisterAtOffsetList* calleeSaveRegisters();
+
         ClonedArguments* createArguments();
         VMEntryFrame* vmEntryFrame() const { return m_VMEntryFrame; }
         CallFrame* callFrame() const { return m_callFrame; }
@@ -97,19 +103,20 @@
         void retrieveExpressionInfo(int& divot, int& startOffset, int& endOffset, unsigned& line, unsigned& column) const;
         void setToEnd();
 
-        size_t m_index;
-        size_t m_argumentCountIncludingThis;
+#if ENABLE(DFG_JIT)
+        InlineCallFrame* m_inlineCallFrame;
+#endif
+        CallFrame* m_callFrame;
         VMEntryFrame* m_VMEntryFrame;
         VMEntryFrame* m_CallerVMEntryFrame;
         CallFrame* m_callerFrame;
-        JSObject* m_callee;
+        JSCell* m_callee;
         CodeBlock* m_codeBlock;
+        size_t m_index;
+        size_t m_argumentCountIncludingThis;
         unsigned m_bytecodeOffset;
-        bool m_callerIsVMEntryFrame;
-#if ENABLE(DFG_JIT)
-        InlineCallFrame* m_inlineCallFrame;
-#endif
-        CallFrame* m_callFrame;
+        bool m_callerIsVMEntryFrame : 1;
+        bool m_isWasmFrame : 1;
 
         friend class StackVisitor;
     };

Modified: trunk/Source/_javascript_Core/jsc.cpp (209695 => 209696)


--- trunk/Source/_javascript_Core/jsc.cpp	2016-12-12 02:50:06 UTC (rev 209695)
+++ trunk/Source/_javascript_Core/jsc.cpp	2016-12-12 03:11:18 UTC (rev 209696)
@@ -2593,7 +2593,7 @@
     ProtoCallFrame protoCallFrame;
     protoCallFrame.init(nullptr, globalObject->globalExec()->jsCallee(), firstArgument, argCount, remainingArgs);
 
-    return JSValue::decode(vmEntryToWasm(wasmCallee->jsToWasmEntryPoint(), vm, &protoCallFrame));
+    return JSValue::decode(vmEntryToWasm(wasmCallee->entrypoint(), vm, &protoCallFrame));
 }
 
 // testWasmModule(JSArrayBufferView source, number functionCount, ...[[WasmValue, [WasmValue]]]) where the ith copy of [[result, [args]]] is a list
@@ -2623,12 +2623,14 @@
         CRASH();
 
     MarkedArgumentBuffer callees;
+    MarkedArgumentBuffer keepAlive;
     {
         unsigned lastIndex = UINT_MAX;
         plan.initializeCallees(exec->lexicalGlobalObject(),
-            [&] (unsigned calleeIndex, JSWebAssemblyCallee* callee) {
+            [&] (unsigned calleeIndex, JSWebAssemblyCallee* jsEntrypointCallee, JSWebAssemblyCallee* wasmEntrypointCallee) {
                 RELEASE_ASSERT(!calleeIndex || (calleeIndex - 1 == lastIndex));
-                callees.append(callee);
+                callees.append(jsEntrypointCallee);
+                keepAlive.append(wasmEntrypointCallee);
                 lastIndex = calleeIndex;
             });
     }
@@ -2640,6 +2642,7 @@
 
     if (!!moduleInformation->memory) {
         memory = std::make_unique<Wasm::Memory>(moduleInformation->memory.initial(), moduleInformation->memory.maximum());
+        RELEASE_ASSERT(memory->isValid());
         memoryBytes = memory->memory();
         memorySize = memory->size();
     }
@@ -2657,7 +2660,12 @@
             for (unsigned argIndex = 0; argIndex < arguments->length(); ++argIndex)
                 boxedArgs.append(box(exec, vm, arguments->getIndexQuickly(argIndex)));
 
-            JSValue callResult = callWasmFunction(&vm, exec->lexicalGlobalObject(), jsCast<JSWebAssemblyCallee*>(callees.at(i)), boxedArgs);
+            JSValue callResult;
+            {
+                auto scope = DECLARE_THROW_SCOPE(vm);
+                callResult = callWasmFunction(&vm, exec->lexicalGlobalObject(), jsCast<JSWebAssemblyCallee*>(callees.at(i)), boxedArgs);
+                RETURN_IF_EXCEPTION(scope, { });
+            }
             JSValue expected = box(exec, vm, result);
             if (callResult != expected) {
                 dataLog("Arguments: ");

Modified: trunk/Source/_javascript_Core/runtime/Error.cpp (209695 => 209696)


--- trunk/Source/_javascript_Core/runtime/Error.cpp	2016-12-12 02:50:06 UTC (rev 209695)
+++ trunk/Source/_javascript_Core/runtime/Error.cpp	2016-12-12 03:11:18 UTC (rev 209696)
@@ -165,10 +165,10 @@
 
         ASSERT(exec == vm.topCallFrame || exec == exec->lexicalGlobalObject()->globalExec() || exec == exec->vmEntryGlobalObject()->globalExec());
 
-        StackFrame* firstNonNativeFrame = nullptr;
+        StackFrame* firstFrameWithLineAndColumnInfo = nullptr;
         for (unsigned i = 0 ; i < stackTrace.size(); ++i) {
-            firstNonNativeFrame = &stackTrace.at(i);
-            if (!firstNonNativeFrame->isNative())
+            firstFrameWithLineAndColumnInfo = &stackTrace.at(i);
+            if (firstFrameWithLineAndColumnInfo->hasLineAndColumnInfo())
                 break;
         }
 
@@ -177,16 +177,18 @@
             vm.topCallFrame->iterate(functor);
             callFrame = functor.foundCallFrame();
             unsigned stackIndex = functor.index();
-            *bytecodeOffset = stackTrace.at(stackIndex).bytecodeOffset;
+            *bytecodeOffset = 0;
+            if (stackTrace.at(stackIndex).hasBytecodeOffset())
+                *bytecodeOffset = stackTrace.at(stackIndex).bytecodeOffset();
         }
         
         unsigned line;
         unsigned column;
-        firstNonNativeFrame->computeLineAndColumn(line, column);
+        firstFrameWithLineAndColumnInfo->computeLineAndColumn(line, column);
         obj->putDirect(vm, vm.propertyNames->line, jsNumber(line));
         obj->putDirect(vm, vm.propertyNames->column, jsNumber(column));
 
-        String frameSourceURL = firstNonNativeFrame->sourceURL();
+        String frameSourceURL = firstFrameWithLineAndColumnInfo->sourceURL();
         if (!frameSourceURL.isEmpty())
             obj->putDirect(vm, vm.propertyNames->sourceURL, jsString(&vm, frameSourceURL));
 

Modified: trunk/Source/_javascript_Core/runtime/JSCell.cpp (209695 => 209696)


--- trunk/Source/_javascript_Core/runtime/JSCell.cpp	2016-12-12 02:50:06 UTC (rev 209695)
+++ trunk/Source/_javascript_Core/runtime/JSCell.cpp	2016-12-12 03:11:18 UTC (rev 209696)
@@ -24,11 +24,13 @@
 #include "JSCell.h"
 
 #include "ArrayBufferView.h"
+#include "JSCInlines.h"
 #include "JSFunction.h"
 #include "JSString.h"
 #include "JSObject.h"
+#include "JSWebAssemblyCallee.h"
 #include "NumberObject.h"
-#include "JSCInlines.h"
+#include "WebAssemblyToJSCallee.h"
 #include <wtf/MathExtras.h>
 
 namespace JSC {
@@ -293,4 +295,14 @@
     RELEASE_ASSERT_NOT_REACHED();
 }
 
+bool JSCell::isAnyWasmCallee() const
+{
+#if ENABLE(WEBASSEMBLY)
+    return inherits(JSWebAssemblyCallee::info()) || inherits(WebAssemblyToJSCallee::info());
+#else
+    return false;
+#endif
+
+}
+
 } // namespace JSC

Modified: trunk/Source/_javascript_Core/runtime/JSCell.h (209695 => 209696)


--- trunk/Source/_javascript_Core/runtime/JSCell.h	2016-12-12 02:50:06 UTC (rev 209695)
+++ trunk/Source/_javascript_Core/runtime/JSCell.h	2016-12-12 03:11:18 UTC (rev 209696)
@@ -95,6 +95,7 @@
     bool isString() const;
     bool isSymbol() const;
     bool isObject() const;
+    bool isAnyWasmCallee() const;
     bool isGetterSetter() const;
     bool isCustomGetterSetter() const;
     bool isProxy() const;

Modified: trunk/Source/_javascript_Core/runtime/JSFunction.cpp (209695 => 209696)


--- trunk/Source/_javascript_Core/runtime/JSFunction.cpp	2016-12-12 02:50:06 UTC (rev 209695)
+++ trunk/Source/_javascript_Core/runtime/JSFunction.cpp	2016-12-12 03:11:18 UTC (rev 209696)
@@ -235,7 +235,7 @@
 
     StackVisitor::Status operator()(StackVisitor& visitor) const
     {
-        JSObject* callee = visitor->callee();
+        JSCell* callee = visitor->callee();
         if (callee != m_targetCallee)
             return StackVisitor::Continue;
 
@@ -277,7 +277,7 @@
 
     StackVisitor::Status operator()(StackVisitor& visitor) const
     {
-        JSObject* callee = visitor->callee();
+        JSCell* callee = visitor->callee();
 
         if (callee && callee->inherits(JSBoundFunction::info()))
             return StackVisitor::Continue;

Modified: trunk/Source/_javascript_Core/runtime/StackFrame.cpp (209695 => 209696)


--- trunk/Source/_javascript_Core/runtime/StackFrame.cpp	2016-12-12 02:50:06 UTC (rev 209695)
+++ trunk/Source/_javascript_Core/runtime/StackFrame.cpp	2016-12-12 03:11:18 UTC (rev 209696)
@@ -35,17 +35,20 @@
 
 intptr_t StackFrame::sourceID() const
 {
-    if (!codeBlock)
+    if (!m_codeBlock)
         return noSourceID;
-    return codeBlock->ownerScriptExecutable()->sourceID();
+    return m_codeBlock->ownerScriptExecutable()->sourceID();
 }
 
 String StackFrame::sourceURL() const
 {
-    if (!codeBlock)
+    if (!m_codeBlock) {
+        if (m_callee && m_callee->isAnyWasmCallee())
+            return ASCIILiteral("[wasm code]");
         return ASCIILiteral("[native code]");
+    }
 
-    String sourceURL = codeBlock->ownerScriptExecutable()->sourceURL();
+    String sourceURL = m_codeBlock->ownerScriptExecutable()->sourceURL();
     if (!sourceURL.isNull())
         return sourceURL;
     return emptyString();
@@ -53,8 +56,8 @@
 
 String StackFrame::functionName(VM& vm) const
 {
-    if (codeBlock) {
-        switch (codeBlock->codeType()) {
+    if (m_codeBlock) {
+        switch (m_codeBlock->codeType()) {
         case EvalCode:
             return ASCIILiteral("eval code");
         case ModuleCode:
@@ -68,14 +71,18 @@
         }
     }
     String name;
-    if (callee)
-        name = getCalculatedDisplayName(vm, callee.get()).impl();
+    if (m_callee) {
+        if (m_callee->isObject())
+            name = getCalculatedDisplayName(vm, jsCast<JSObject*>(m_callee.get())).impl();
+        else if (m_callee->isAnyWasmCallee())
+            return ASCIILiteral("<wasm>");
+    }
     return name.isNull() ? emptyString() : name;
 }
 
 void StackFrame::computeLineAndColumn(unsigned& line, unsigned& column) const
 {
-    if (!codeBlock) {
+    if (!m_codeBlock) {
         line = 0;
         column = 0;
         return;
@@ -84,9 +91,9 @@
     int divot = 0;
     int unusedStartOffset = 0;
     int unusedEndOffset = 0;
-    codeBlock->expressionRangeForBytecodeOffset(bytecodeOffset, divot, unusedStartOffset, unusedEndOffset, line, column);
+    m_codeBlock->expressionRangeForBytecodeOffset(m_bytecodeOffset, divot, unusedStartOffset, unusedEndOffset, line, column);
 
-    ScriptExecutable* executable = codeBlock->ownerScriptExecutable();
+    ScriptExecutable* executable = m_codeBlock->ownerScriptExecutable();
     if (executable->hasOverrideLineNumber())
         line = executable->overrideLineNumber();
 }
@@ -101,7 +108,7 @@
         if (!functionName.isEmpty())
             traceBuild.append('@');
         traceBuild.append(sourceURL);
-        if (codeBlock) {
+        if (hasLineAndColumnInfo()) {
             unsigned line;
             unsigned column;
             computeLineAndColumn(line, column);

Modified: trunk/Source/_javascript_Core/runtime/StackFrame.h (209695 => 209696)


--- trunk/Source/_javascript_Core/runtime/StackFrame.h	2016-12-12 02:50:06 UTC (rev 209695)
+++ trunk/Source/_javascript_Core/runtime/StackFrame.h	2016-12-12 03:11:18 UTC (rev 209696)
@@ -32,18 +32,39 @@
 class CodeBlock;
 class JSObject;
 
-struct StackFrame {
-    Strong<JSObject> callee;
-    Strong<CodeBlock> codeBlock;
-    unsigned bytecodeOffset;
+class StackFrame {
+public:
+    StackFrame(VM& vm, JSCell* callee)
+        : m_callee(vm, callee)
+    { }
+
+    StackFrame(VM& vm, JSCell* callee, CodeBlock* codeBlock, unsigned bytecodeOffset)
+        : m_callee(vm, callee)
+        , m_codeBlock(vm, codeBlock)
+        , m_bytecodeOffset(bytecodeOffset)
+    { }
+
+    bool hasLineAndColumnInfo() const { return !!m_codeBlock; }
     
-    bool isNative() const { return !codeBlock; }
-    
     void computeLineAndColumn(unsigned& line, unsigned& column) const;
     String functionName(VM&) const;
     intptr_t sourceID() const;
     String sourceURL() const;
     String toString(VM&) const;
+
+    bool hasBytecodeOffset() const { return m_bytecodeOffset != UINT_MAX; }
+    unsigned bytecodeOffset()
+    {
+        ASSERT(m_bytecodeOffset != UINT_MAX);
+        return m_bytecodeOffset;
+    }
+
+
+private:
+    Strong<JSCell> m_callee { };
+    Strong<CodeBlock> m_codeBlock { };
+    unsigned m_bytecodeOffset { UINT_MAX };
+    
 };
 
 } // namespace JSC

Modified: trunk/Source/_javascript_Core/runtime/VM.h (209695 => 209696)


--- trunk/Source/_javascript_Core/runtime/VM.h	2016-12-12 02:50:06 UTC (rev 209695)
+++ trunk/Source/_javascript_Core/runtime/VM.h	2016-12-12 03:11:18 UTC (rev 209696)
@@ -110,7 +110,7 @@
 class ScriptExecutable;
 class SourceProvider;
 class SourceProviderCache;
-struct StackFrame;
+class StackFrame;
 class Structure;
 #if ENABLE(REGEXP_TRACING)
 class RegExp;

Modified: trunk/Source/_javascript_Core/wasm/WasmB3IRGenerator.cpp (209695 => 209696)


--- trunk/Source/_javascript_Core/wasm/WasmB3IRGenerator.cpp	2016-12-12 02:50:06 UTC (rev 209695)
+++ trunk/Source/_javascript_Core/wasm/WasmB3IRGenerator.cpp	2016-12-12 03:11:18 UTC (rev 209696)
@@ -40,8 +40,13 @@
 #include "B3VariableValue.h"
 #include "B3WasmAddressValue.h"
 #include "B3WasmBoundsCheckValue.h"
+#include "ExceptionScope.h"
+#include "FrameTracers.h"
+#include "JITExceptions.h"
+#include "JSCInlines.h"
 #include "JSWebAssemblyInstance.h"
 #include "JSWebAssemblyModule.h"
+#include "JSWebAssemblyRuntimeError.h"
 #include "VirtualRegister.h"
 #include "WasmCallingConvention.h"
 #include "WasmFunctionParser.h"
@@ -224,13 +229,45 @@
             m_proc.pinRegister(info.sizeRegister);
 
         m_proc.setWasmBoundsCheckGenerator([=] (CCallHelpers& jit, GPRReg pinnedGPR, unsigned) {
+            AllowMacroScratchRegisterUsage allowScratch(jit);
             ASSERT_UNUSED(pinnedGPR, m_memorySizeGPR == pinnedGPR);
-            // FIXME: This should unwind the stack and throw a JS exception. See: https://bugs.webkit.org/show_bug.cgi?id=163351
-            jit.breakpoint();
+            jit.copyCalleeSavesToVMEntryFrameCalleeSavesBuffer();
+
+            jit.move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
+
+            CCallHelpers::Call call = jit.call();
+            jit.jumpToExceptionHandler();
+
+            jit.addLinkTask([=] (LinkBuffer& linkBuffer) {
+                void (*throwMemoryException)(ExecState*) = [] (ExecState* exec) {
+                    VM* vm = &exec->vm();
+                    NativeCallFrameTracer tracer(vm, exec);
+
+                    {
+                        auto throwScope = DECLARE_THROW_SCOPE(*vm);
+                        JSGlobalObject* globalObject = vm->topJSWebAssemblyInstance->globalObject();
+
+                        JSWebAssemblyRuntimeError* error = JSWebAssemblyRuntimeError::create(
+                            exec, globalObject->WebAssemblyRuntimeErrorStructure(), "Out of bounds memory access");
+                        throwException(exec, throwScope, error);
+                    }
+
+                    genericUnwind(vm, exec);
+                    ASSERT(!!vm->callFrameForCatch);
+                };
+
+                linkBuffer.link(call, throwMemoryException);
+            });
         });
+
+        B3::PatchpointValue* foo = m_currentBlock->appendNew<B3::PatchpointValue>(m_proc, B3::Void, Origin());
+        foo->setGenerator(
+            [=] (CCallHelpers& jit, const B3::StackmapGenerationParams&) {
+                AllowMacroScratchRegisterUsage allowScratch(jit);
+            });
     }
 
-    wasmCallingConvention().setupFrameInPrologue(compilation, m_proc, Origin(), m_currentBlock);
+    wasmCallingConvention().setupFrameInPrologue(&compilation->wasmCalleeMoveLocation, m_proc, Origin(), m_currentBlock);
 
     m_functionIndexSpaceValue = m_currentBlock->appendNew<ConstPtrValue>(m_proc, Origin(), functionIndexSpace.buffer.get());
 }
@@ -718,21 +755,25 @@
     dataLogLn("\n");
 }
 
-static std::unique_ptr<Compilation> createJSToWasmWrapper(VM& vm, const Signature* signature, MacroAssemblerCodePtr mainFunction, const MemoryInformation& memory)
+static std::unique_ptr<Compilation> createJSToWasmWrapper(VM& vm, WasmInternalFunction& function, const Signature* signature, MacroAssemblerCodePtr mainFunction, const MemoryInformation& memory)
 {
     Procedure proc;
     BasicBlock* block = proc.addBlock();
 
-    // Check argument count is sane.
-    Value* framePointer = block->appendNew<B3::Value>(proc, B3::FramePointer, Origin());
-    Value* offSetOfArgumentCount = block->appendNew<Const64Value>(proc, Origin(), CallFrameSlot::argumentCount * sizeof(Register));
-    Value* argumentCount = block->appendNew<MemoryValue>(proc, Load, Int32, Origin(),
-        block->appendNew<Value>(proc, Add, Origin(), framePointer, offSetOfArgumentCount));
+    Origin origin;
 
-    Value* expectedArgumentCount = block->appendNew<Const32Value>(proc, Origin(), signature->arguments.size());
+    jscCallingConvention().setupFrameInPrologue(&function.jsToWasmCalleeMoveLocation, proc, origin, block);
 
-    CheckValue* argumentCountCheck = block->appendNew<CheckValue>(proc, Check, Origin(),
-        block->appendNew<Value>(proc, Above, Origin(), expectedArgumentCount, argumentCount));
+    Value* framePointer = block->appendNew<B3::Value>(proc, B3::FramePointer, origin);
+    Value* offSetOfArgumentCount = block->appendNew<Const64Value>(proc, origin, CallFrameSlot::argumentCount * sizeof(Register));
+    Value* argumentCount = block->appendNew<MemoryValue>(proc, Load, Int32, origin,
+        block->appendNew<Value>(proc, Add, origin, framePointer, offSetOfArgumentCount));
+
+    Value* expectedArgumentCount = block->appendNew<Const32Value>(proc, origin, signature->arguments.size());
+
+    CheckValue* argumentCountCheck = block->appendNew<CheckValue>(proc, Check, origin,
+        block->appendNew<Value>(proc, Above, origin, expectedArgumentCount, argumentCount));
+
     argumentCountCheck->setGenerator([] (CCallHelpers& jit, const StackmapGenerationParams&) {
         jit.breakpoint();
     });
@@ -747,19 +788,19 @@
             block->appendNew<ConstPtrValue>(proc, Origin(), &vm.topWasmMemorySize));
         sizes.reserveCapacity(memory.pinnedRegisters().sizeRegisters.size());
         for (auto info : memory.pinnedRegisters().sizeRegisters) {
-            sizes.append(block->appendNew<Value>(proc, Sub, Origin(), size,
-                block->appendNew<Const32Value>(proc, Origin(), info.sizeOffset)));
+            sizes.append(block->appendNew<Value>(proc, Sub, origin, size,
+                block->appendNew<Const32Value>(proc, origin, info.sizeOffset)));
         }
     }
 
     // Get our arguments.
     Vector<Value*> arguments;
-    jscCallingConvention().loadArguments(signature->arguments, proc, block, Origin(), [&] (Value* argument, unsigned) {
+    jscCallingConvention().loadArguments(signature->arguments, proc, block, origin, [&] (Value* argument, unsigned) {
         arguments.append(argument);
     });
 
     // Move the arguments into place.
-    Value* result = wasmCallingConvention().setupCall(proc, block, Origin(), arguments, toB3Type(signature->returnType), [&] (PatchpointValue* patchpoint) {
+    Value* result = wasmCallingConvention().setupCall(proc, block, origin, arguments, toB3Type(signature->returnType), [&] (PatchpointValue* patchpoint) {
         if (!!memory) {
             ASSERT(sizes.size() == memory.pinnedRegisters().sizeRegisters.size());
             patchpoint->append(ConstrainedValue(baseMemory, ValueRep::reg(memory.pinnedRegisters().baseMemoryPointer)));
@@ -780,15 +821,15 @@
     // Return the result, if needed.
     switch (signature->returnType) {
     case Wasm::Void:
-        block->appendNewControlValue(proc, B3::Return, Origin());
+        block->appendNewControlValue(proc, B3::Return, origin);
         break;
     case Wasm::F32:
     case Wasm::F64:
-        result = block->appendNew<Value>(proc, BitwiseCast, Origin(), result);
+        result = block->appendNew<Value>(proc, BitwiseCast, origin, result);
         FALLTHROUGH;
     case Wasm::I32:
     case Wasm::I64:
-        block->appendNewControlValue(proc, B3::Return, Origin(), result);
+        block->appendNewControlValue(proc, B3::Return, origin, result);
         break;
     case Wasm::Func:
     case Wasm::Anyfunc:
@@ -795,7 +836,9 @@
         RELEASE_ASSERT_NOT_REACHED();
     }
 
-    return std::make_unique<Compilation>(vm, proc);
+    auto jsEntrypoint = std::make_unique<Compilation>(vm, proc);
+    function.jsToWasmEntrypoint.calleeSaveRegisters = proc.calleeSaveRegisters();
+    return jsEntrypoint;
 }
 
 std::unique_ptr<WasmInternalFunction> parseAndCompile(VM& vm, const uint8_t* functionStart, size_t functionLength, const Signature* signature, Vector<UnlinkedWasmToWasmCall>& unlinkedWasmToWasmCalls, const ImmutableFunctionIndexSpace& functionIndexSpace, const ModuleInformation& info, unsigned optLevel)
@@ -817,8 +860,9 @@
     if (verbose)
         dataLog("Post SSA: ", procedure);
 
-    result->code = std::make_unique<Compilation>(vm, procedure, optLevel);
-    result->jsToWasmEntryPoint = createJSToWasmWrapper(vm, signature, result->code->code(), info.memory);
+    result->wasmEntrypoint.compilation = std::make_unique<Compilation>(vm, procedure, optLevel);
+    result->wasmEntrypoint.calleeSaveRegisters = procedure.calleeSaveRegisters();
+    result->jsToWasmEntrypoint.compilation = createJSToWasmWrapper(vm, *result, signature, result->wasmEntrypoint.compilation->code(), info.memory);
     return result;
 }
 

Modified: trunk/Source/_javascript_Core/wasm/WasmCallingConvention.h (209695 => 209696)


--- trunk/Source/_javascript_Core/wasm/WasmCallingConvention.h	2016-12-12 02:50:06 UTC (rev 209695)
+++ trunk/Source/_javascript_Core/wasm/WasmCallingConvention.h	2016-12-12 03:11:18 UTC (rev 209696)
@@ -83,7 +83,7 @@
     }
 
 public:
-    void setupFrameInPrologue(WasmInternalFunction* compilation, B3::Procedure& proc, B3::Origin origin, B3::BasicBlock* block) const
+    void setupFrameInPrologue(CodeLocationDataLabelPtr* calleeMoveLocation, B3::Procedure& proc, B3::Origin origin, B3::BasicBlock* block) const
     {
         static_assert(CallFrameSlot::callee * sizeof(Register) < headerSize, "We rely on this here for now.");
         static_assert(CallFrameSlot::codeBlock * sizeof(Register) < headerSize, "We rely on this here for now.");
@@ -96,7 +96,7 @@
                 GPRReg result = params[0].gpr();
                 MacroAssembler::DataLabelPtr moveLocation = jit.moveWithPatch(MacroAssembler::TrustedImmPtr(nullptr), result);
                 jit.addLinkTask([=] (LinkBuffer& linkBuffer) {
-                    compilation->calleeMoveLocation = linkBuffer.locationOf(moveLocation);
+                    *calleeMoveLocation = linkBuffer.locationOf(moveLocation);
                 });
             });
 

Modified: trunk/Source/_javascript_Core/wasm/WasmFormat.h (209695 => 209696)


--- trunk/Source/_javascript_Core/wasm/WasmFormat.h	2016-12-12 02:50:06 UTC (rev 209695)
+++ trunk/Source/_javascript_Core/wasm/WasmFormat.h	2016-12-12 03:11:18 UTC (rev 209696)
@@ -32,6 +32,7 @@
 #include "CodeLocation.h"
 #include "Identifier.h"
 #include "MacroAssemblerCodeRef.h"
+#include "RegisterAtOffsetList.h"
 #include "WasmMemoryInformation.h"
 #include "WasmOps.h"
 #include "WasmPageCount.h"
@@ -166,10 +167,17 @@
     size_t functionIndex;
 };
 
+struct Entrypoint {
+    std::unique_ptr<B3::Compilation> compilation;
+    RegisterAtOffsetList calleeSaveRegisters;
+};
+
 struct WasmInternalFunction {
-    CodeLocationDataLabelPtr calleeMoveLocation;
-    std::unique_ptr<B3::Compilation> code;
-    std::unique_ptr<B3::Compilation> jsToWasmEntryPoint;
+    CodeLocationDataLabelPtr wasmCalleeMoveLocation;
+    CodeLocationDataLabelPtr jsToWasmCalleeMoveLocation;
+
+    Entrypoint wasmEntrypoint;
+    Entrypoint jsToWasmEntrypoint;
 };
 
 typedef MacroAssemblerCodeRef WasmToJSStub;

Modified: trunk/Source/_javascript_Core/wasm/WasmMemory.cpp (209695 => 209696)


--- trunk/Source/_javascript_Core/wasm/WasmMemory.cpp	2016-12-12 02:50:06 UTC (rev 209695)
+++ trunk/Source/_javascript_Core/wasm/WasmMemory.cpp	2016-12-12 03:11:18 UTC (rev 209696)
@@ -38,15 +38,15 @@
     , m_maximum(maximum)
     // FIXME: If we add signal based bounds checking then we need extra space for overflow on load.
     // see: https://bugs.webkit.org/show_bug.cgi?id=162693
-    , m_mappedCapacity(PageCount::max().bytes())
 {
     RELEASE_ASSERT(!maximum || maximum >= initial); // This should be guaranteed by our caller.
 
+    m_mappedCapacity = m_capacity;
     // FIXME: It would be nice if we had a VM tag for wasm memory. https://bugs.webkit.org/show_bug.cgi?id=163600
     void* result = mmap(nullptr, m_mappedCapacity, PROT_NONE, MAP_PRIVATE | MAP_ANON, -1, 0);
     if (result == MAP_FAILED) {
         // Try again with a different number.
-        m_mappedCapacity = m_capacity;
+        m_mappedCapacity = m_size;
         result = mmap(nullptr, m_mappedCapacity, PROT_NONE, MAP_PRIVATE | MAP_ANON, -1, 0);
         if (result == MAP_FAILED)
             return;

Modified: trunk/Source/_javascript_Core/wasm/WasmMemory.h (209695 => 209696)


--- trunk/Source/_javascript_Core/wasm/WasmMemory.h	2016-12-12 02:50:06 UTC (rev 209695)
+++ trunk/Source/_javascript_Core/wasm/WasmMemory.h	2016-12-12 03:11:18 UTC (rev 209696)
@@ -52,6 +52,8 @@
             munmap(m_memory, m_mappedCapacity);
     }
 
+    bool isValid() const { return !!m_memory; }
+
     void* memory() const { return m_memory; }
     uint32_t size() const { return m_size; }
 

Modified: trunk/Source/_javascript_Core/wasm/WasmPlan.cpp (209695 => 209696)


--- trunk/Source/_javascript_Core/wasm/WasmPlan.cpp	2016-12-12 02:50:06 UTC (rev 209695)
+++ trunk/Source/_javascript_Core/wasm/WasmPlan.cpp	2016-12-12 03:11:18 UTC (rev 209696)
@@ -130,7 +130,7 @@
 
         unlinkedWasmToWasmCalls.uncheckedAppend(Vector<UnlinkedWasmToWasmCall>());
         m_wasmInternalFunctions.uncheckedAppend(parseAndCompile(*m_vm, functionStart, functionLength, signature, unlinkedWasmToWasmCalls.at(functionIndex), m_functionIndexSpace, *m_moduleInformation));
-        m_functionIndexSpace.buffer.get()[functionIndexSpace].code = m_wasmInternalFunctions[functionIndex]->code->code().executableAddress();
+        m_functionIndexSpace.buffer.get()[functionIndexSpace].code = m_wasmInternalFunctions[functionIndex]->wasmEntrypoint.compilation->code().executableAddress();
     }
 
     // Patch the call sites for each WebAssembly function.
@@ -142,20 +142,19 @@
     m_failed = false;
 }
 
-void Plan::initializeCallees(JSGlobalObject* globalObject, std::function<void(unsigned, JSWebAssemblyCallee*)> callback)
+void Plan::initializeCallees(JSGlobalObject* globalObject, std::function<void(unsigned, JSWebAssemblyCallee*, JSWebAssemblyCallee*)> callback)
 {
     ASSERT(!failed());
     for (unsigned internalFunctionIndex = 0; internalFunctionIndex < m_wasmInternalFunctions.size(); ++internalFunctionIndex) {
         WasmInternalFunction* function = m_wasmInternalFunctions[internalFunctionIndex].get();
-        CodeLocationDataLabelPtr calleeMoveLocation = function->calleeMoveLocation;
-        JSWebAssemblyCallee* callee = JSWebAssemblyCallee::create(globalObject->vm(), WTFMove(function->code), WTFMove(function->jsToWasmEntryPoint));
 
-        MacroAssembler::repatchPointer(calleeMoveLocation, callee);
+        JSWebAssemblyCallee* jsEntrypointCallee = JSWebAssemblyCallee::create(globalObject->vm(), WTFMove(function->jsToWasmEntrypoint));
+        MacroAssembler::repatchPointer(function->jsToWasmCalleeMoveLocation, jsEntrypointCallee);
 
-        if (verbose)
-            dataLogLn("Made Wasm callee: ", RawPointer(callee));
+        JSWebAssemblyCallee* wasmEntrypointCallee = JSWebAssemblyCallee::create(globalObject->vm(), WTFMove(function->wasmEntrypoint));
+        MacroAssembler::repatchPointer(function->wasmCalleeMoveLocation, wasmEntrypointCallee);
 
-        callback(internalFunctionIndex, callee);
+        callback(internalFunctionIndex, jsEntrypointCallee, wasmEntrypointCallee);
     }
 }
 

Modified: trunk/Source/_javascript_Core/wasm/WasmPlan.h (209695 => 209696)


--- trunk/Source/_javascript_Core/wasm/WasmPlan.h	2016-12-12 02:50:06 UTC (rev 209695)
+++ trunk/Source/_javascript_Core/wasm/WasmPlan.h	2016-12-12 03:11:18 UTC (rev 209696)
@@ -50,7 +50,7 @@
 
     JS_EXPORT_PRIVATE void run();
 
-    JS_EXPORT_PRIVATE void initializeCallees(JSGlobalObject*, std::function<void(unsigned, JSWebAssemblyCallee*)>);
+    JS_EXPORT_PRIVATE void initializeCallees(JSGlobalObject*, std::function<void(unsigned, JSWebAssemblyCallee*, JSWebAssemblyCallee*)>);
 
     bool WARN_UNUSED_RETURN failed() const { return m_failed; }
     const String& errorMessage() const
@@ -71,12 +71,6 @@
         return m_wasmInternalFunctions.size();
     }
 
-    B3::Compilation* jsToWasmEntryPointForFunction(size_t i) const
-    {
-        ASSERT(i > m_wasmToJSStubs.size());
-        return m_wasmInternalFunctions.at(i - m_wasmToJSStubs.size())->jsToWasmEntryPoint.get();
-    }
-
     std::unique_ptr<ModuleInformation>&& takeModuleInformation()
     {
         RELEASE_ASSERT(!failed());

Modified: trunk/Source/_javascript_Core/wasm/js/JSWebAssemblyCallee.cpp (209695 => 209696)


--- trunk/Source/_javascript_Core/wasm/js/JSWebAssemblyCallee.cpp	2016-12-12 02:50:06 UTC (rev 209695)
+++ trunk/Source/_javascript_Core/wasm/js/JSWebAssemblyCallee.cpp	2016-12-12 03:11:18 UTC (rev 209696)
@@ -38,12 +38,11 @@
     : Base(vm, vm.webAssemblyCalleeStructure.get())
 { }
 
-void JSWebAssemblyCallee::finishCreation(VM& vm, std::unique_ptr<B3::Compilation>&& code, std::unique_ptr<B3::Compilation>&& jsToWasmEntryPoint)
+void JSWebAssemblyCallee::finishCreation(VM& vm, Wasm::Entrypoint&& entrypoint)
 {
     Base::finishCreation(vm);
 
-    m_code = WTFMove(code);
-    m_jsToWasmEntryPoint = WTFMove(jsToWasmEntryPoint);
+    m_entrypoint = WTFMove(entrypoint);
 }
 
 void JSWebAssemblyCallee::destroy(JSCell* cell)

Modified: trunk/Source/_javascript_Core/wasm/js/JSWebAssemblyCallee.h (209695 => 209696)


--- trunk/Source/_javascript_Core/wasm/js/JSWebAssemblyCallee.h	2016-12-12 02:50:06 UTC (rev 209695)
+++ trunk/Source/_javascript_Core/wasm/js/JSWebAssemblyCallee.h	2016-12-12 03:11:18 UTC (rev 209696)
@@ -27,7 +27,9 @@
 
 #if ENABLE(WEBASSEMBLY)
 
-#include "JSCallee.h"
+#include "JSCell.h"
+#include "RegisterAtOffsetList.h"
+#include "Structure.h"
 #include "WasmFormat.h"
 
 namespace JSC {
@@ -37,10 +39,10 @@
     typedef JSCell Base;
     static const unsigned StructureFlags = Base::StructureFlags | StructureIsImmortal;
 
-    static JSWebAssemblyCallee* create(VM& vm, std::unique_ptr<B3::Compilation>&& code, std::unique_ptr<B3::Compilation>&& jsToWasmEntryPoint)
+    static JSWebAssemblyCallee* create(VM& vm, Wasm::Entrypoint&& entrypoint)
     {
         JSWebAssemblyCallee* callee = new (NotNull, allocateCell<JSWebAssemblyCallee>(vm.heap)) JSWebAssemblyCallee(vm);
-        callee->finishCreation(vm, std::forward<std::unique_ptr<B3::Compilation>>(code), std::forward<std::unique_ptr<B3::Compilation>>(jsToWasmEntryPoint));
+        callee->finishCreation(vm, WTFMove(entrypoint));
         return callee;
     }
 
@@ -53,14 +55,15 @@
     static const bool needsDestruction = true;
     static void destroy(JSCell*);
 
-    void* jsToWasmEntryPoint() { return m_jsToWasmEntryPoint->code().executableAddress(); }
+    void* entrypoint() { return m_entrypoint.compilation->code().executableAddress(); }
 
+    RegisterAtOffsetList* calleeSaveRegisters() { return &m_entrypoint.calleeSaveRegisters; }
+
 private:
-    void finishCreation(VM&, std::unique_ptr<B3::Compilation>&&, std::unique_ptr<B3::Compilation>&&);
+    void finishCreation(VM&, Wasm::Entrypoint&&);
     JSWebAssemblyCallee(VM&);
 
-    std::unique_ptr<B3::Compilation> m_code;
-    std::unique_ptr<B3::Compilation> m_jsToWasmEntryPoint;
+    Wasm::Entrypoint m_entrypoint;
 };
 
 } // namespace JSC

Modified: trunk/Source/_javascript_Core/wasm/js/JSWebAssemblyModule.cpp (209695 => 209696)


--- trunk/Source/_javascript_Core/wasm/js/JSWebAssemblyModule.cpp	2016-12-12 02:50:06 UTC (rev 209695)
+++ trunk/Source/_javascript_Core/wasm/js/JSWebAssemblyModule.cpp	2016-12-12 03:11:18 UTC (rev 209696)
@@ -58,7 +58,7 @@
     , m_functionIndexSpace(WTFMove(functionIndexSpace))
     , m_calleeCount(calleeCount)
 {
-    memset(callees(), 0, m_calleeCount * sizeof(WriteBarrier<JSWebAssemblyCallee>));
+    memset(callees(), 0, m_calleeCount * sizeof(WriteBarrier<JSWebAssemblyCallee>) * 2);
 }
 
 void JSWebAssemblyModule::finishCreation(VM& vm, SymbolTable* exportSymbolTable)
@@ -75,19 +75,27 @@
 
 void JSWebAssemblyModule::visitChildren(JSCell* cell, SlotVisitor& visitor)
 {
-    auto* thisObject = jsCast<JSWebAssemblyModule*>(cell);
+    JSWebAssemblyModule* thisObject = jsCast<JSWebAssemblyModule*>(cell);
     ASSERT_GC_OBJECT_INHERITS(thisObject, info());
 
     Base::visitChildren(thisObject, visitor);
     visitor.append(&thisObject->m_exportSymbolTable);
-    for (auto iter = thisObject->m_callLinkInfos.begin(); !!iter; ++iter)
-        (*iter)->visitWeak(*thisObject->vm());
-    for (unsigned i = 0; i < thisObject->m_calleeCount; i++) {
+    for (unsigned i = 0; i < thisObject->m_calleeCount * 2; i++) {
         WriteBarrier<JSWebAssemblyCallee>* callee = &thisObject->callees()[i];
         visitor.append(callee);
     }
+
+    visitor.addUnconditionalFinalizer(&thisObject->m_unconditionalFinalizer);
 }
 
+void JSWebAssemblyModule::UnconditionalFinalizer::finalizeUnconditionally()
+{
+    JSWebAssemblyModule* thisObject = bitwise_cast<JSWebAssemblyModule*>(
+        bitwise_cast<char*>(this) - OBJECT_OFFSETOF(JSWebAssemblyModule, m_unconditionalFinalizer));
+    for (auto iter = thisObject->m_callLinkInfos.begin(); !!iter; ++iter)
+        (*iter)->visitWeak(*thisObject->vm());
+}
+
 } // namespace JSC
 
 #endif // ENABLE(WEBASSEMBLY)

Modified: trunk/Source/_javascript_Core/wasm/js/JSWebAssemblyModule.h (209695 => 209696)


--- trunk/Source/_javascript_Core/wasm/js/JSWebAssemblyModule.h	2016-12-12 02:50:06 UTC (rev 209695)
+++ trunk/Source/_javascript_Core/wasm/js/JSWebAssemblyModule.h	2016-12-12 03:11:18 UTC (rev 209696)
@@ -29,6 +29,8 @@
 
 #include "JSDestructibleObject.h"
 #include "JSObject.h"
+#include "JSWebAssemblyCallee.h"
+#include "UnconditionalFinalizer.h"
 #include "WasmFormat.h"
 #include <wtf/Bag.h>
 #include <wtf/Vector.h>
@@ -35,7 +37,6 @@
 
 namespace JSC {
 
-class JSWebAssemblyCallee;
 class SymbolTable;
 
 class JSWebAssemblyModule : public JSDestructibleObject {
@@ -52,7 +53,7 @@
     Wasm::Signature* signatureForFunctionIndexSpace(unsigned functionIndexSpace) const { ASSERT(functionIndexSpace < m_functionIndexSpace.size); return m_functionIndexSpace.buffer.get()[functionIndexSpace].signature; }
     unsigned importCount() const { return m_wasmToJSStubs.size(); }
 
-    JSWebAssemblyCallee* calleeFromFunctionIndexSpace(unsigned functionIndexSpace)
+    JSWebAssemblyCallee* jsEntrypointCalleeFromFunctionIndexSpace(unsigned functionIndexSpace)
     {
         RELEASE_ASSERT(functionIndexSpace >= importCount());
         unsigned calleeIndex = functionIndexSpace - importCount();
@@ -60,6 +61,26 @@
         return callees()[calleeIndex].get();
     }
 
+    JSWebAssemblyCallee* wasmEntrypointCalleeFromFunctionIndexSpace(unsigned functionIndexSpace)
+    {
+        RELEASE_ASSERT(functionIndexSpace >= importCount());
+        unsigned calleeIndex = functionIndexSpace - importCount();
+        RELEASE_ASSERT(calleeIndex < m_calleeCount);
+        return callees()[calleeIndex + m_calleeCount].get();
+    }
+
+    void setJSEntrypointCallee(VM& vm, unsigned calleeIndex, JSWebAssemblyCallee* callee)
+    {
+        RELEASE_ASSERT(calleeIndex < m_calleeCount);
+        callees()[calleeIndex].set(vm, this, callee);
+    }
+
+    void setWasmEntrypointCallee(VM& vm, unsigned calleeIndex, JSWebAssemblyCallee* callee)
+    {
+        RELEASE_ASSERT(calleeIndex < m_calleeCount);
+        callees()[calleeIndex + m_calleeCount].set(vm, this, callee);
+    }
+
     WriteBarrier<JSWebAssemblyCallee>* callees()
     {
         return bitwise_cast<WriteBarrier<JSWebAssemblyCallee>*>(bitwise_cast<char*>(this) + offsetOfCallees());
@@ -81,9 +102,14 @@
 
     static size_t allocationSize(unsigned numCallees)
     {
-        return offsetOfCallees() + sizeof(WriteBarrier<JSWebAssemblyCallee>) * numCallees;
+        return offsetOfCallees() + sizeof(WriteBarrier<JSWebAssemblyCallee>) * numCallees * 2;
     }
 
+    class UnconditionalFinalizer : public JSC::UnconditionalFinalizer { 
+        void finalizeUnconditionally() override;
+    };
+
+    UnconditionalFinalizer m_unconditionalFinalizer;
     std::unique_ptr<Wasm::ModuleInformation> m_moduleInformation;
     Bag<CallLinkInfo> m_callLinkInfos;
     WriteBarrier<SymbolTable> m_exportSymbolTable;

Modified: trunk/Source/_javascript_Core/wasm/js/JSWebAssemblyRuntimeError.h (209695 => 209696)


--- trunk/Source/_javascript_Core/wasm/js/JSWebAssemblyRuntimeError.h	2016-12-12 02:50:06 UTC (rev 209695)
+++ trunk/Source/_javascript_Core/wasm/js/JSWebAssemblyRuntimeError.h	2016-12-12 03:11:18 UTC (rev 209696)
@@ -35,7 +35,7 @@
 public:
     typedef ErrorInstance Base;
 
-    static JSWebAssemblyRuntimeError* create(ExecState*, Structure*, const String&, bool);
+    static JSWebAssemblyRuntimeError* create(ExecState*, Structure*, const String&, bool useCurrentFrame = true);
     static JSWebAssemblyRuntimeError* create(ExecState* exec, Structure* structure, JSValue message, bool useCurrentFrame)
     {
         return create(exec, structure, message.isUndefined() ? String() : message.toString(exec)->value(exec), useCurrentFrame);

Modified: trunk/Source/_javascript_Core/wasm/js/WebAssemblyFunction.cpp (209695 => 209696)


--- trunk/Source/_javascript_Core/wasm/js/WebAssemblyFunction.cpp	2016-12-12 02:50:06 UTC (rev 209695)
+++ trunk/Source/_javascript_Core/wasm/js/WebAssemblyFunction.cpp	2016-12-12 03:11:18 UTC (rev 209696)
@@ -116,7 +116,8 @@
 
     JSWebAssemblyInstance* prevJSWebAssemblyInstance = vm.topJSWebAssemblyInstance;
     vm.topJSWebAssemblyInstance = instance();
-    EncodedJSValue rawResult = vmEntryToWasm(webAssemblyCallee()->jsToWasmEntryPoint(), &vm, protoCallFrame);
+    ASSERT(instance());
+    EncodedJSValue rawResult = vmEntryToWasm(webAssemblyCallee()->entrypoint(), &vm, protoCallFrame);
     vm.topJSWebAssemblyInstance = prevJSWebAssemblyInstance;
 
     // FIXME is this correct? https://bugs.webkit.org/show_bug.cgi?id=164876

Modified: trunk/Source/_javascript_Core/wasm/js/WebAssemblyInstanceConstructor.cpp (209695 => 209696)


--- trunk/Source/_javascript_Core/wasm/js/WebAssemblyInstanceConstructor.cpp	2016-12-12 02:50:06 UTC (rev 209695)
+++ trunk/Source/_javascript_Core/wasm/js/WebAssemblyInstanceConstructor.cpp	2016-12-12 03:11:18 UTC (rev 209696)
@@ -193,6 +193,8 @@
             RELEASE_ASSERT(!moduleInformation.memory.isImport());
             // We create a memory when it's a memory definition.
             std::unique_ptr<Wasm::Memory> memory = std::make_unique<Wasm::Memory>(moduleInformation.memory.initial(), moduleInformation.memory.maximum());
+            if (!memory->isValid())
+                return JSValue::encode(throwException(exec, throwScope, createOutOfMemoryError(exec)));
             instance->setMemory(vm,
                JSWebAssemblyMemory::create(vm, exec->lexicalGlobalObject()->WebAssemblyMemoryStructure(), WTFMove(memory)));
         }

Modified: trunk/Source/_javascript_Core/wasm/js/WebAssemblyMemoryConstructor.cpp (209695 => 209696)


--- trunk/Source/_javascript_Core/wasm/js/WebAssemblyMemoryConstructor.cpp	2016-12-12 02:50:06 UTC (rev 209695)
+++ trunk/Source/_javascript_Core/wasm/js/WebAssemblyMemoryConstructor.cpp	2016-12-12 03:11:18 UTC (rev 209696)
@@ -107,6 +107,8 @@
     }
 
     std::unique_ptr<Wasm::Memory> memory = std::make_unique<Wasm::Memory>(initialPageCount, maximumPageCount);
+    if (!memory->isValid())
+        return JSValue::encode(throwException(exec, throwScope, createOutOfMemoryError(exec)));
 
     return JSValue::encode(JSWebAssemblyMemory::create(vm, exec->lexicalGlobalObject()->WebAssemblyMemoryStructure(), WTFMove(memory)));
 }

Modified: trunk/Source/_javascript_Core/wasm/js/WebAssemblyModuleConstructor.cpp (209695 => 209696)


--- trunk/Source/_javascript_Core/wasm/js/WebAssemblyModuleConstructor.cpp	2016-12-12 02:50:06 UTC (rev 209695)
+++ trunk/Source/_javascript_Core/wasm/js/WebAssemblyModuleConstructor.cpp	2016-12-12 03:11:18 UTC (rev 209696)
@@ -92,8 +92,9 @@
     unsigned calleeCount = plan.internalFunctionCount();
     JSWebAssemblyModule* result = JSWebAssemblyModule::create(vm, structure, plan.takeModuleInformation(), plan.takeCallLinkInfos(), plan.takeWasmToJSStubs(), plan.takeFunctionIndexSpace(), exportSymbolTable, calleeCount);
     plan.initializeCallees(state->jsCallee()->globalObject(), 
-        [&] (unsigned calleeIndex, JSWebAssemblyCallee* callee) {
-            result->callees()[calleeIndex].set(vm, result, callee);
+        [&] (unsigned calleeIndex, JSWebAssemblyCallee* jsEntrypointCallee, JSWebAssemblyCallee* wasmEntrypointCallee) {
+            result->setJSEntrypointCallee(vm, calleeIndex, jsEntrypointCallee);
+            result->setWasmEntrypointCallee(vm, calleeIndex, wasmEntrypointCallee);
         });
     return JSValue::encode(result);
 }

Modified: trunk/Source/_javascript_Core/wasm/js/WebAssemblyModuleRecord.cpp (209695 => 209696)


--- trunk/Source/_javascript_Core/wasm/js/WebAssemblyModuleRecord.cpp	2016-12-12 02:50:06 UTC (rev 209695)
+++ trunk/Source/_javascript_Core/wasm/js/WebAssemblyModuleRecord.cpp	2016-12-12 03:11:18 UTC (rev 209696)
@@ -136,7 +136,7 @@
             //     a. Let func be an Exported Function Exotic Object created from c.
             //     b. Append func to funcs.
             //     c. Return func.
-            JSWebAssemblyCallee* wasmCallee = module->calleeFromFunctionIndexSpace(exp.functionIndex);
+            JSWebAssemblyCallee* wasmCallee = module->jsEntrypointCalleeFromFunctionIndexSpace(exp.functionIndex);
             Wasm::Signature* signature = module->signatureForFunctionIndexSpace(exp.functionIndex);
             WebAssemblyFunction* function = WebAssemblyFunction::create(vm, globalObject, signature->arguments.size(), exp.field.string(), instance, wasmCallee, signature);
             exportedValue = function;
@@ -174,7 +174,7 @@
         // FIXME can start call imports / tables? This assumes not. https://github.com/WebAssembly/design/issues/896
         if (!m_startFunction.get()) {
             // The start function wasn't added above. It must be a purely internal function.
-            JSWebAssemblyCallee* wasmCallee = module->calleeFromFunctionIndexSpace(startFunctionIndexSpace);
+            JSWebAssemblyCallee* wasmCallee = module->jsEntrypointCalleeFromFunctionIndexSpace(startFunctionIndexSpace);
             WebAssemblyFunction* function = WebAssemblyFunction::create(vm, globalObject, signature->arguments.size(), "start", instance, wasmCallee, signature);
             m_startFunction.set(vm, this, function);
         }

Modified: trunk/Source/WebCore/ChangeLog (209695 => 209696)


--- 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)
@@ -1,3 +1,13 @@
+2016-12-11  Saam Barati  <[email protected]>
+
+        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()):
+
 2016-12-11  Darin Adler  <[email protected]>
 
         Remove uses of Dictionary in WebRTC IDL files

Modified: trunk/Source/WebCore/bindings/js/JSDOMBinding.cpp (209695 => 209696)


--- 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)
@@ -759,7 +759,11 @@
             m_globalObject = codeBlock->globalObject();
         else {
             ASSERT(visitor->callee());
-            m_globalObject = visitor->callee()->globalObject();
+            // 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->callee()->isObject())
+                m_globalObject = jsCast<JSObject*>(visitor->callee())->globalObject();
         }
         return StackVisitor::Done;
     }
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to