Commit 7f460012 authored by Clemens Hammacher's avatar Clemens Hammacher Committed by Commit Bot

[wasm] Show interpreted frames on captured stack traces

In Isolate::CaptureSimpleStackTrace, we were ignoring interpreter entry
frames so far. This CLs changes this to gets the interpreted stack from
the wasm interpreter and add the frames to the FrameArray.

R=ahaas@chromium.org, titzer@chromium.org
BUG=v8:5822

Change-Id: I705909532ff28af412ff809da94522866eaa1c0d
Reviewed-on: https://chromium-review.googlesource.com/452378
Commit-Queue: Clemens Hammacher <clemensh@chromium.org>
Reviewed-by: 's avatarBen Titzer <titzer@chromium.org>
Reviewed-by: 's avatarAndreas Haas <ahaas@chromium.org>
Cr-Commit-Position: refs/heads/master@{#43772}
parent 9f4188c2
......@@ -537,9 +537,26 @@ Handle<Object> Isolate::CaptureSimpleStackTrace(Handle<JSReceiver> error_object,
abstract_code, offset, flags);
} break;
case StackFrame::WASM_INTERPRETER_ENTRY:
// TODO(clemensh): Add frames.
break;
case StackFrame::WASM_INTERPRETER_ENTRY: {
WasmInterpreterEntryFrame* interpreter_frame =
WasmInterpreterEntryFrame::cast(frame);
Handle<WasmInstanceObject> instance(interpreter_frame->wasm_instance(),
this);
// Get the interpreted stack (<func_index, offset> pairs).
std::vector<std::pair<uint32_t, int>> interpreted_stack =
instance->debug_info()->GetInterpretedStack(
interpreter_frame->fp());
// interpreted_stack is bottom-up, i.e. caller before callee. We need it
// the other way around.
for (auto it = interpreted_stack.rbegin(),
end = interpreted_stack.rend();
it != end; ++it) {
elements = FrameArray::AppendWasmFrame(
elements, instance, it->first, Handle<AbstractCode>::null(),
it->second, FrameArray::kIsWasmInterpretedFrame);
}
} break;
default:
break;
......
......@@ -639,12 +639,19 @@ WasmStackFrame::WasmStackFrame() {}
void WasmStackFrame::FromFrameArray(Isolate* isolate, Handle<FrameArray> array,
int frame_ix) {
// This function is called for both wasm and asm.js->wasm frames.
DCHECK(array->IsWasmFrame(frame_ix) || array->IsAsmJsWasmFrame(frame_ix));
// This function is called for compiled and interpreted wasm frames, and for
// asm.js->wasm frames.
DCHECK(array->IsWasmFrame(frame_ix) ||
array->IsWasmInterpretedFrame(frame_ix) ||
array->IsAsmJsWasmFrame(frame_ix));
isolate_ = isolate;
wasm_instance_ = handle(array->WasmInstance(frame_ix), isolate);
wasm_func_index_ = array->WasmFunctionIndex(frame_ix)->value();
code_ = handle(array->Code(frame_ix), isolate);
if (array->IsWasmInterpretedFrame(frame_ix)) {
code_ = Handle<AbstractCode>::null();
} else {
code_ = handle(array->Code(frame_ix), isolate);
}
offset_ = array->Offset(frame_ix)->value();
}
......@@ -692,6 +699,7 @@ MaybeHandle<String> WasmStackFrame::ToString() {
}
int WasmStackFrame::GetPosition() const {
if (IsInterpreted()) return offset_;
// TODO(wasm): Clean this up (bug 5007).
return (offset_ < 0) ? (-1 - offset_) : code_->SourcePosition(offset_);
}
......@@ -802,13 +810,17 @@ void FrameArrayIterator::Next() { next_frame_ix_++; }
StackFrameBase* FrameArrayIterator::Frame() {
DCHECK(HasNext());
const int flags = array_->Flags(next_frame_ix_)->value();
switch (flags & (FrameArray::kIsWasmFrame | FrameArray::kIsAsmJsWasmFrame)) {
int flag_mask = FrameArray::kIsWasmFrame |
FrameArray::kIsWasmInterpretedFrame |
FrameArray::kIsAsmJsWasmFrame;
switch (flags & flag_mask) {
case 0:
// JavaScript Frame.
js_frame_.FromFrameArray(isolate_, array_, next_frame_ix_);
return &js_frame_;
case FrameArray::kIsWasmFrame:
// Wasm Frame;
case FrameArray::kIsWasmInterpretedFrame:
// Wasm Frame:
wasm_frame_.FromFrameArray(isolate_, array_, next_frame_ix_);
return &wasm_frame_;
case FrameArray::kIsAsmJsWasmFrame:
......
......@@ -149,6 +149,7 @@ class WasmStackFrame : public StackFrameBase {
bool IsToplevel() override { return false; }
bool IsConstructor() override { return false; }
bool IsStrict() const override { return false; }
bool IsInterpreted() const { return code_.is_null(); }
MaybeHandle<String> ToString() override;
......@@ -161,7 +162,7 @@ class WasmStackFrame : public StackFrameBase {
// TODO(wasm): Use proper typing.
Handle<Object> wasm_instance_;
uint32_t wasm_func_index_;
Handle<AbstractCode> code_;
Handle<AbstractCode> code_; // null handle for interpreted frames.
int offset_;
private:
......
......@@ -2690,6 +2690,11 @@ bool FrameArray::IsWasmFrame(int frame_ix) const {
return (flags & kIsWasmFrame) != 0;
}
bool FrameArray::IsWasmInterpretedFrame(int frame_ix) const {
const int flags = Flags(frame_ix)->value();
return (flags & kIsWasmInterpretedFrame) != 0;
}
bool FrameArray::IsAsmJsWasmFrame(int frame_ix) const {
const int flags = Flags(frame_ix)->value();
return (flags & kIsAsmJsWasmFrame) != 0;
......
......@@ -10010,8 +10010,7 @@ Handle<FixedArray> EnsureSpaceInFixedArray(Handle<FixedArray> array,
int new_capacity = length;
new_capacity = new_capacity + Max(new_capacity / 2, 2);
int grow_by = new_capacity - capacity;
array = Handle<ArrayList>::cast(
isolate->factory()->CopyFixedArrayAndGrow(array, grow_by));
array = isolate->factory()->CopyFixedArrayAndGrow(array, grow_by);
}
return array;
}
......@@ -10064,7 +10063,8 @@ Handle<FrameArray> FrameArray::AppendWasmFrame(Handle<FrameArray> in,
Handle<FrameArray> array = EnsureSpace(in, new_length);
array->SetWasmInstance(frame_count, *wasm_instance);
array->SetWasmFunctionIndex(frame_count, Smi::FromInt(wasm_function_index));
array->SetCode(frame_count, *code);
// code will be a null handle for interpreted wasm frames.
if (!code.is_null()) array->SetCode(frame_count, *code);
array->SetOffset(frame_count, Smi::FromInt(offset));
array->SetFlags(frame_count, Smi::FromInt(flags));
array->set(kFrameCountIndex, Smi::FromInt(frame_count + 1));
......
......@@ -2984,17 +2984,21 @@ class FrameArray : public FixedArray {
#undef DECLARE_FRAME_ARRAY_ACCESSORS
inline bool IsWasmFrame(int frame_ix) const;
inline bool IsWasmInterpretedFrame(int frame_ix) const;
inline bool IsAsmJsWasmFrame(int frame_ix) const;
inline int FrameCount() const;
void ShrinkToFit();
// Flags.
static const int kIsWasmFrame = 1 << 0;
static const int kIsAsmJsWasmFrame = 1 << 1;
static const int kIsStrict = 1 << 2;
static const int kForceConstructor = 1 << 3;
static const int kAsmJsAtNumberConversion = 1 << 4;
enum Flag {
kIsWasmFrame = 1 << 0,
kIsWasmInterpretedFrame = 1 << 1,
kIsAsmJsWasmFrame = 1 << 2,
kIsStrict = 1 << 3,
kForceConstructor = 1 << 4,
kAsmJsAtNumberConversion = 1 << 5
};
static Handle<FrameArray> AppendJSFrame(Handle<FrameArray> in,
Handle<Object> receiver,
......
......@@ -17,6 +17,7 @@ end
Getting current stack trace via "new Error().stack".
Error
at v8://test/getStack:1:1
at func (<WASM>[0]+1)
at main (<WASM>[1]+1)
at v8://test/runWasm:1:22
exports.main returned.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment