Diff
Modified: trunk/JSTests/ChangeLog (215853 => 215854)
--- trunk/JSTests/ChangeLog 2017-04-27 02:57:09 UTC (rev 215853)
+++ trunk/JSTests/ChangeLog 2017-04-27 03:38:12 UTC (rev 215854)
@@ -1,5 +1,22 @@
2017-04-26 Saam Barati <[email protected]>
+ Print Wasm function index in stack trace
+ https://bugs.webkit.org/show_bug.cgi?id=171349
+
+ Reviewed by JF Bastien.
+
+ * wasm/function-tests/stack-trace.js: Added.
+ (import.Builder.from.string_appeared_here.assert):
+ (let.imp):
+ * wasm/function-tests/trap-after-cross-instance-call.js:
+ (wasmFrameCountFromError):
+ * wasm/function-tests/trap-load-2.js:
+ (wasmFrameCountFromError):
+ * wasm/function-tests/trap-load.js:
+ (wasmFrameCountFromError):
+
+2017-04-26 Saam Barati <[email protected]>
+
ASSERTION FAILED: inIndex != notFound in JSC::invalidParameterInSourceAppender()
https://bugs.webkit.org/show_bug.cgi?id=170924
<rdar://problem/31721052>
Added: trunk/JSTests/wasm/function-tests/stack-trace.js (0 => 215854)
--- trunk/JSTests/wasm/function-tests/stack-trace.js (rev 0)
+++ trunk/JSTests/wasm/function-tests/stack-trace.js 2017-04-27 03:38:12 UTC (rev 215854)
@@ -0,0 +1,57 @@
+import Builder from '../Builder.js'
+
+function assert(b) {
+ if (!b)
+ throw new Error("Bad");
+}
+
+const builder = (new Builder())
+ .Type().End()
+ .Import()
+ .Function("imp", "f", { params: [], ret: "void" })
+ .End()
+ .Function().End()
+ .Export().Function("entry").End()
+ .Code()
+ // idx 1
+ .Function("entry", {params: []})
+ .Call(3)
+ .End()
+ // idx 2
+ .Function({params: []})
+ .Call(4)
+ .End()
+ // idx 3
+ .Function({params: []})
+ .Call(2)
+ .End()
+ // idx 4
+ .Function({params: []})
+ .Call(0)
+ .End()
+ .End();
+
+let stacktrace;
+let imp = () => {
+ stacktrace = (new Error).stack;
+}
+
+
+const bin = builder.WebAssembly().get();
+const module = new WebAssembly.Module(bin);
+let instance = new WebAssembly.Instance(module, {imp: {f: imp}});
+assert(!stacktrace);
+for (let i = 0; i < 10000; ++i) {
+ instance.exports.entry();
+ assert(stacktrace);
+ stacktrace = stacktrace.split("\n");
+ assert(stacktrace[0].indexOf("imp") !== -1); // the arrow function import named "imp".
+ assert(stacktrace[1] === "wasm function@[wasm code]"); // the wasm->js stub
+ assert(stacktrace[2] === "wasm function index: 4@[wasm code]");
+ assert(stacktrace[3] === "wasm function index: 2@[wasm code]");
+ assert(stacktrace[4] === "wasm function index: 3@[wasm code]");
+ assert(stacktrace[5] === "wasm function index: 1@[wasm code]");
+ assert(stacktrace[6] === "wasm function@[wasm code]"); // wasm entry
+
+ stacktrace = null;
+}
Modified: trunk/JSTests/wasm/function-tests/trap-after-cross-instance-call.js (215853 => 215854)
--- trunk/JSTests/wasm/function-tests/trap-after-cross-instance-call.js 2017-04-27 02:57:09 UTC (rev 215853)
+++ trunk/JSTests/wasm/function-tests/trap-after-cross-instance-call.js 2017-04-27 03:38:12 UTC (rev 215854)
@@ -52,7 +52,7 @@
function wasmFrameCountFromError(e) {
- let stackFrames = e.stack.split("\n").filter((s) => s.indexOf("<wasm>@[wasm code]") !== -1);
+ let stackFrames = e.stack.split("\n").filter((s) => s.indexOf("wasm function") !== -1);
return stackFrames.length;
}
Modified: trunk/JSTests/wasm/function-tests/trap-load-2.js (215853 => 215854)
--- trunk/JSTests/wasm/function-tests/trap-load-2.js 2017-04-27 02:57:09 UTC (rev 215853)
+++ trunk/JSTests/wasm/function-tests/trap-load-2.js 2017-04-27 03:38:12 UTC (rev 215854)
@@ -20,7 +20,7 @@
.End();
function wasmFrameCountFromError(e) {
- let stackFrames = e.stack.split("\n").filter((s) => s.indexOf("<wasm>@[wasm code]") !== -1);
+ let stackFrames = e.stack.split("\n").filter((s) => s.indexOf("wasm function") !== -1);
return stackFrames.length;
}
Modified: trunk/JSTests/wasm/function-tests/trap-load.js (215853 => 215854)
--- trunk/JSTests/wasm/function-tests/trap-load.js 2017-04-27 02:57:09 UTC (rev 215853)
+++ trunk/JSTests/wasm/function-tests/trap-load.js 2017-04-27 03:38:12 UTC (rev 215854)
@@ -24,7 +24,7 @@
const foo = new WebAssembly.Instance(module, {a: {b: new WebAssembly.Memory({initial: numPages})}}).exports.foo;
function wasmFrameCountFromError(e) {
- let stackFrames = e.stack.split("\n").filter((s) => s.indexOf("<wasm>@[wasm code]") !== -1);
+ let stackFrames = e.stack.split("\n").filter((s) => s.indexOf("wasm function") !== -1);
return stackFrames.length;
}
Modified: trunk/Source/_javascript_Core/ChangeLog (215853 => 215854)
--- trunk/Source/_javascript_Core/ChangeLog 2017-04-27 02:57:09 UTC (rev 215853)
+++ trunk/Source/_javascript_Core/ChangeLog 2017-04-27 03:38:12 UTC (rev 215854)
@@ -1,3 +1,44 @@
+2017-04-26 Saam Barati <[email protected]>
+
+ Print Wasm function index in stack trace
+ https://bugs.webkit.org/show_bug.cgi?id=171349
+
+ Reviewed by JF Bastien.
+
+ This patch prints a Callee's index in the function index
+ space in Error.stack.
+
+ This will lead to stack traces that have lines of text like:
+ wasm function index: 4@[wasm code]
+
+ We don't ascribe indices to everything in wasm. Specifically, the
+ Wasm->JS call stub callee does not get a name, and neither does
+ the JS -> Wasm entrypoint.
+
+ * interpreter/Interpreter.cpp:
+ (JSC::GetStackTraceFunctor::operator()):
+ * interpreter/StackVisitor.cpp:
+ (JSC::StackVisitor::readNonInlinedFrame):
+ (JSC::StackVisitor::Frame::functionName):
+ * interpreter/StackVisitor.h:
+ (JSC::StackVisitor::Frame::wasmFunctionIndex):
+ * runtime/StackFrame.cpp:
+ (JSC::StackFrame::functionName):
+ * runtime/StackFrame.h:
+ (JSC::StackFrame::StackFrame):
+ (JSC::StackFrame::wasm):
+ (JSC::StackFrame::hasBytecodeOffset):
+ (JSC::StackFrame::bytecodeOffset):
+ * wasm/WasmBBQPlanInlines.h:
+ (JSC::Wasm::BBQPlan::initializeCallees):
+ * wasm/WasmCallee.cpp:
+ (JSC::Wasm::Callee::Callee):
+ * wasm/WasmCallee.h:
+ (JSC::Wasm::Callee::create):
+ (JSC::Wasm::Callee::index):
+ * wasm/WasmOMGPlan.cpp:
+ (JSC::Wasm::OMGPlan::work):
+
2017-04-26 Keith Miller <[email protected]>
Follow up to r215843
Modified: trunk/Source/_javascript_Core/interpreter/Interpreter.cpp (215853 => 215854)
--- trunk/Source/_javascript_Core/interpreter/Interpreter.cpp 2017-04-27 02:57:09 UTC (rev 215853)
+++ trunk/Source/_javascript_Core/interpreter/Interpreter.cpp 2017-04-27 03:38:12 UTC (rev 215854)
@@ -479,9 +479,10 @@
}
if (m_remainingCapacityForFrameCapture) {
- if (visitor->isWasmFrame())
- m_results.append(StackFrame::wasm());
- else if (!!visitor->codeBlock() && !visitor->codeBlock()->unlinkedCodeBlock()->isBuiltinFunction()) {
+ if (visitor->isWasmFrame()) {
+ std::optional<unsigned> wasmFunctionIndex = visitor->wasmFunctionIndex();
+ m_results.append(StackFrame::wasm(wasmFunctionIndex ? *wasmFunctionIndex : StackFrame::invalidWasmIndex));
+ } else if (!!visitor->codeBlock() && !visitor->codeBlock()->unlinkedCodeBlock()->isBuiltinFunction()) {
m_results.append(
StackFrame(m_vm, visitor->callee().asCell(), visitor->codeBlock(), visitor->bytecodeOffset()));
} else {
Modified: trunk/Source/_javascript_Core/interpreter/StackVisitor.cpp (215853 => 215854)
--- trunk/Source/_javascript_Core/interpreter/StackVisitor.cpp 2017-04-27 02:57:09 UTC (rev 215853)
+++ trunk/Source/_javascript_Core/interpreter/StackVisitor.cpp 2017-04-27 03:38:12 UTC (rev 215854)
@@ -163,6 +163,11 @@
m_frame.m_isWasmFrame = true;
m_frame.m_codeBlock = nullptr;
m_frame.m_bytecodeOffset = 0;
+#if ENABLE(WEBASSEMBLY)
+ CalleeBits bits = callFrame->callee();
+ if (bits.isWasm())
+ m_frame.m_wasmFunctionIndex = bits.asWasmCallee()->index();
+#endif
} else {
m_frame.m_codeBlock = callFrame->codeBlock();
m_frame.m_bytecodeOffset = !m_frame.codeBlock() ? 0
@@ -278,7 +283,10 @@
switch (codeType()) {
case CodeType::Wasm:
- traceLine = ASCIILiteral("wasm code");
+ if (m_wasmFunctionIndex)
+ traceLine = makeString("wasm function index: ", String::number(*m_wasmFunctionIndex));
+ else
+ traceLine = ASCIILiteral("wasm function");
break;
case CodeType::Eval:
traceLine = ASCIILiteral("eval code");
Modified: trunk/Source/_javascript_Core/interpreter/StackVisitor.h (215853 => 215854)
--- trunk/Source/_javascript_Core/interpreter/StackVisitor.h 2017-04-27 02:57:09 UTC (rev 215853)
+++ trunk/Source/_javascript_Core/interpreter/StackVisitor.h 2017-04-27 03:38:12 UTC (rev 215854)
@@ -77,6 +77,11 @@
bool isNativeFrame() const { return !codeBlock() && !isWasmFrame(); }
bool isInlinedFrame() const { return !!inlineCallFrame(); }
bool isWasmFrame() const;
+ std::optional<unsigned> const wasmFunctionIndex()
+ {
+ ASSERT(isWasmFrame());
+ return m_wasmFunctionIndex;
+ }
JS_EXPORT_PRIVATE String functionName() const;
JS_EXPORT_PRIVATE String sourceURL() const;
@@ -116,6 +121,7 @@
size_t m_index;
size_t m_argumentCountIncludingThis;
unsigned m_bytecodeOffset;
+ std::optional<unsigned> m_wasmFunctionIndex;
bool m_callerIsVMEntryFrame : 1;
bool m_isWasmFrame : 1;
Modified: trunk/Source/_javascript_Core/runtime/StackFrame.cpp (215853 => 215854)
--- trunk/Source/_javascript_Core/runtime/StackFrame.cpp 2017-04-27 02:57:09 UTC (rev 215853)
+++ trunk/Source/_javascript_Core/runtime/StackFrame.cpp 2017-04-27 03:38:12 UTC (rev 215854)
@@ -57,8 +57,11 @@
String StackFrame::functionName(VM& vm) const
{
- if (m_isWasmFrame)
- return ASCIILiteral("<wasm>");
+ if (m_isWasmFrame) {
+ if (m_wasmFunctionIndex == invalidWasmIndex)
+ return ASCIILiteral("wasm function");
+ return makeString("wasm function index: ", String::number(m_wasmFunctionIndex));
+ }
if (m_codeBlock) {
switch (m_codeBlock->codeType()) {
Modified: trunk/Source/_javascript_Core/runtime/StackFrame.h (215853 => 215854)
--- trunk/Source/_javascript_Core/runtime/StackFrame.h 2017-04-27 02:57:09 UTC (rev 215853)
+++ trunk/Source/_javascript_Core/runtime/StackFrame.h 2017-04-27 03:38:12 UTC (rev 215854)
@@ -39,6 +39,7 @@
StackFrame(VM& vm, JSCell* callee)
: m_callee(vm, callee)
+ , m_bytecodeOffset(UINT_MAX)
{ }
StackFrame(VM& vm, JSCell* callee, CodeBlock* codeBlock, unsigned bytecodeOffset)
@@ -47,10 +48,12 @@
, m_bytecodeOffset(bytecodeOffset)
{ }
- static StackFrame wasm()
+ static constexpr unsigned invalidWasmIndex = UINT_MAX;
+ static StackFrame wasm(unsigned index)
{
StackFrame result;
result.m_isWasmFrame = true;
+ result.m_wasmFunctionIndex = index;
return result;
}
@@ -62,10 +65,10 @@
String sourceURL() const;
String toString(VM&) const;
- bool hasBytecodeOffset() const { return m_bytecodeOffset != UINT_MAX; }
+ bool hasBytecodeOffset() const { return m_bytecodeOffset != UINT_MAX && !m_isWasmFrame; }
unsigned bytecodeOffset()
{
- ASSERT(m_bytecodeOffset != UINT_MAX);
+ ASSERT(hasBytecodeOffset());
return m_bytecodeOffset;
}
@@ -73,7 +76,10 @@
private:
Strong<JSCell> m_callee { };
Strong<CodeBlock> m_codeBlock { };
- unsigned m_bytecodeOffset { UINT_MAX };
+ union {
+ unsigned m_bytecodeOffset;
+ unsigned m_wasmFunctionIndex;
+ };
bool m_isWasmFrame { false };
};
Modified: trunk/Source/_javascript_Core/wasm/WasmBBQPlanInlines.h (215853 => 215854)
--- trunk/Source/_javascript_Core/wasm/WasmBBQPlanInlines.h 2017-04-27 02:57:09 UTC (rev 215853)
+++ trunk/Source/_javascript_Core/wasm/WasmBBQPlanInlines.h 2017-04-27 03:38:12 UTC (rev 215854)
@@ -43,7 +43,7 @@
Ref<Wasm::Callee> jsEntrypointCallee = Wasm::Callee::create(WTFMove(function->jsToWasmEntrypoint));
MacroAssembler::repatchPointer(function->jsToWasmCalleeMoveLocation, CalleeBits::boxWasm(jsEntrypointCallee.ptr()));
- Ref<Wasm::Callee> wasmEntrypointCallee = Wasm::Callee::create(WTFMove(function->wasmEntrypoint));
+ Ref<Wasm::Callee> wasmEntrypointCallee = Wasm::Callee::create(WTFMove(function->wasmEntrypoint), internalFunctionIndex + m_moduleInformation->importFunctionCount());
MacroAssembler::repatchPointer(function->wasmCalleeMoveLocation, CalleeBits::boxWasm(wasmEntrypointCallee.ptr()));
callback(internalFunctionIndex, WTFMove(jsEntrypointCallee), WTFMove(wasmEntrypointCallee));
Modified: trunk/Source/_javascript_Core/wasm/WasmCallee.cpp (215853 => 215854)
--- trunk/Source/_javascript_Core/wasm/WasmCallee.cpp 2017-04-27 02:57:09 UTC (rev 215853)
+++ trunk/Source/_javascript_Core/wasm/WasmCallee.cpp 2017-04-27 03:38:12 UTC (rev 215854)
@@ -32,8 +32,9 @@
namespace JSC { namespace Wasm {
-Callee::Callee(Entrypoint&& entrypoint)
+Callee::Callee(Entrypoint&& entrypoint, unsigned index)
: m_entrypoint(WTFMove(entrypoint))
+ , m_index(index)
{
registerCode(m_entrypoint.compilation->codeRef().executableMemory()->start(), m_entrypoint.compilation->codeRef().executableMemory()->end());
}
Modified: trunk/Source/_javascript_Core/wasm/WasmCallee.h (215853 => 215854)
--- trunk/Source/_javascript_Core/wasm/WasmCallee.h 2017-04-27 02:57:09 UTC (rev 215853)
+++ trunk/Source/_javascript_Core/wasm/WasmCallee.h 2017-04-27 03:38:12 UTC (rev 215854)
@@ -38,9 +38,12 @@
WTF_MAKE_FAST_ALLOCATED;
public:
- static Ref<Callee> create(Wasm::Entrypoint&& entrypoint)
+ // We use this when we're the JS entrypoint, we don't ascribe an index to those.
+ static constexpr unsigned invalidCalleeIndex = UINT_MAX;
+
+ static Ref<Callee> create(Wasm::Entrypoint&& entrypoint, unsigned index = invalidCalleeIndex)
{
- Callee* callee = new Callee(WTFMove(entrypoint));
+ Callee* callee = new Callee(WTFMove(entrypoint), index);
return adoptRef(*callee);
}
@@ -47,11 +50,18 @@
void* entrypoint() const { return m_entrypoint.compilation->code().executableAddress(); }
RegisterAtOffsetList* calleeSaveRegisters() { return &m_entrypoint.calleeSaveRegisters; }
+ std::optional<unsigned> index() const
+ {
+ if (m_index == invalidCalleeIndex)
+ return std::nullopt;
+ return m_index;
+ }
private:
- JS_EXPORT_PRIVATE Callee(Wasm::Entrypoint&&);
+ JS_EXPORT_PRIVATE Callee(Wasm::Entrypoint&&, unsigned index);
Wasm::Entrypoint m_entrypoint;
+ unsigned m_index;
};
} } // namespace JSC::Wasm
Modified: trunk/Source/_javascript_Core/wasm/WasmOMGPlan.cpp (215853 => 215854)
--- trunk/Source/_javascript_Core/wasm/WasmOMGPlan.cpp 2017-04-27 02:57:09 UTC (rev 215853)
+++ trunk/Source/_javascript_Core/wasm/WasmOMGPlan.cpp 2017-04-27 03:38:12 UTC (rev 215854)
@@ -98,7 +98,7 @@
void* entrypoint;
{
ASSERT(m_codeBlock.ptr() == m_module->codeBlockFor(mode()));
- Ref<Callee> callee = Callee::create(WTFMove(omgEntrypoint));
+ Ref<Callee> callee = Callee::create(WTFMove(omgEntrypoint), functionIndexSpace);
MacroAssembler::repatchPointer(parseAndCompileResult.value()->wasmCalleeMoveLocation, CalleeBits::boxWasm(callee.ptr()));
ASSERT(!m_codeBlock->m_optimizedCallees[m_functionIndex]);
entrypoint = callee->entrypoint();