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;
}