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, ...@@ -537,9 +537,26 @@ Handle<Object> Isolate::CaptureSimpleStackTrace(Handle<JSReceiver> error_object,
abstract_code, offset, flags); abstract_code, offset, flags);
} break; } break;
case StackFrame::WASM_INTERPRETER_ENTRY: case StackFrame::WASM_INTERPRETER_ENTRY: {
// TODO(clemensh): Add frames. WasmInterpreterEntryFrame* interpreter_frame =
break; 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: default:
break; break;
......
...@@ -639,12 +639,19 @@ WasmStackFrame::WasmStackFrame() {} ...@@ -639,12 +639,19 @@ WasmStackFrame::WasmStackFrame() {}
void WasmStackFrame::FromFrameArray(Isolate* isolate, Handle<FrameArray> array, void WasmStackFrame::FromFrameArray(Isolate* isolate, Handle<FrameArray> array,
int frame_ix) { int frame_ix) {
// This function is called for both wasm and asm.js->wasm frames. // This function is called for compiled and interpreted wasm frames, and for
DCHECK(array->IsWasmFrame(frame_ix) || array->IsAsmJsWasmFrame(frame_ix)); // asm.js->wasm frames.
DCHECK(array->IsWasmFrame(frame_ix) ||
array->IsWasmInterpretedFrame(frame_ix) ||
array->IsAsmJsWasmFrame(frame_ix));
isolate_ = isolate; isolate_ = isolate;
wasm_instance_ = handle(array->WasmInstance(frame_ix), isolate); wasm_instance_ = handle(array->WasmInstance(frame_ix), isolate);
wasm_func_index_ = array->WasmFunctionIndex(frame_ix)->value(); 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(); offset_ = array->Offset(frame_ix)->value();
} }
...@@ -692,6 +699,7 @@ MaybeHandle<String> WasmStackFrame::ToString() { ...@@ -692,6 +699,7 @@ MaybeHandle<String> WasmStackFrame::ToString() {
} }
int WasmStackFrame::GetPosition() const { int WasmStackFrame::GetPosition() const {
if (IsInterpreted()) return offset_;
// TODO(wasm): Clean this up (bug 5007). // TODO(wasm): Clean this up (bug 5007).
return (offset_ < 0) ? (-1 - offset_) : code_->SourcePosition(offset_); return (offset_ < 0) ? (-1 - offset_) : code_->SourcePosition(offset_);
} }
...@@ -802,13 +810,17 @@ void FrameArrayIterator::Next() { next_frame_ix_++; } ...@@ -802,13 +810,17 @@ void FrameArrayIterator::Next() { next_frame_ix_++; }
StackFrameBase* FrameArrayIterator::Frame() { StackFrameBase* FrameArrayIterator::Frame() {
DCHECK(HasNext()); DCHECK(HasNext());
const int flags = array_->Flags(next_frame_ix_)->value(); 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: case 0:
// JavaScript Frame. // JavaScript Frame.
js_frame_.FromFrameArray(isolate_, array_, next_frame_ix_); js_frame_.FromFrameArray(isolate_, array_, next_frame_ix_);
return &js_frame_; return &js_frame_;
case FrameArray::kIsWasmFrame: case FrameArray::kIsWasmFrame:
// Wasm Frame; case FrameArray::kIsWasmInterpretedFrame:
// Wasm Frame:
wasm_frame_.FromFrameArray(isolate_, array_, next_frame_ix_); wasm_frame_.FromFrameArray(isolate_, array_, next_frame_ix_);
return &wasm_frame_; return &wasm_frame_;
case FrameArray::kIsAsmJsWasmFrame: case FrameArray::kIsAsmJsWasmFrame:
......
...@@ -149,6 +149,7 @@ class WasmStackFrame : public StackFrameBase { ...@@ -149,6 +149,7 @@ class WasmStackFrame : public StackFrameBase {
bool IsToplevel() override { return false; } bool IsToplevel() override { return false; }
bool IsConstructor() override { return false; } bool IsConstructor() override { return false; }
bool IsStrict() const override { return false; } bool IsStrict() const override { return false; }
bool IsInterpreted() const { return code_.is_null(); }
MaybeHandle<String> ToString() override; MaybeHandle<String> ToString() override;
...@@ -161,7 +162,7 @@ class WasmStackFrame : public StackFrameBase { ...@@ -161,7 +162,7 @@ class WasmStackFrame : public StackFrameBase {
// TODO(wasm): Use proper typing. // TODO(wasm): Use proper typing.
Handle<Object> wasm_instance_; Handle<Object> wasm_instance_;
uint32_t wasm_func_index_; uint32_t wasm_func_index_;
Handle<AbstractCode> code_; Handle<AbstractCode> code_; // null handle for interpreted frames.
int offset_; int offset_;
private: private:
......
...@@ -2690,6 +2690,11 @@ bool FrameArray::IsWasmFrame(int frame_ix) const { ...@@ -2690,6 +2690,11 @@ bool FrameArray::IsWasmFrame(int frame_ix) const {
return (flags & kIsWasmFrame) != 0; 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 { bool FrameArray::IsAsmJsWasmFrame(int frame_ix) const {
const int flags = Flags(frame_ix)->value(); const int flags = Flags(frame_ix)->value();
return (flags & kIsAsmJsWasmFrame) != 0; return (flags & kIsAsmJsWasmFrame) != 0;
......
...@@ -10010,8 +10010,7 @@ Handle<FixedArray> EnsureSpaceInFixedArray(Handle<FixedArray> array, ...@@ -10010,8 +10010,7 @@ Handle<FixedArray> EnsureSpaceInFixedArray(Handle<FixedArray> array,
int new_capacity = length; int new_capacity = length;
new_capacity = new_capacity + Max(new_capacity / 2, 2); new_capacity = new_capacity + Max(new_capacity / 2, 2);
int grow_by = new_capacity - capacity; int grow_by = new_capacity - capacity;
array = Handle<ArrayList>::cast( array = isolate->factory()->CopyFixedArrayAndGrow(array, grow_by);
isolate->factory()->CopyFixedArrayAndGrow(array, grow_by));
} }
return array; return array;
} }
...@@ -10064,7 +10063,8 @@ Handle<FrameArray> FrameArray::AppendWasmFrame(Handle<FrameArray> in, ...@@ -10064,7 +10063,8 @@ Handle<FrameArray> FrameArray::AppendWasmFrame(Handle<FrameArray> in,
Handle<FrameArray> array = EnsureSpace(in, new_length); Handle<FrameArray> array = EnsureSpace(in, new_length);
array->SetWasmInstance(frame_count, *wasm_instance); array->SetWasmInstance(frame_count, *wasm_instance);
array->SetWasmFunctionIndex(frame_count, Smi::FromInt(wasm_function_index)); 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->SetOffset(frame_count, Smi::FromInt(offset));
array->SetFlags(frame_count, Smi::FromInt(flags)); array->SetFlags(frame_count, Smi::FromInt(flags));
array->set(kFrameCountIndex, Smi::FromInt(frame_count + 1)); array->set(kFrameCountIndex, Smi::FromInt(frame_count + 1));
......
...@@ -2984,17 +2984,21 @@ class FrameArray : public FixedArray { ...@@ -2984,17 +2984,21 @@ class FrameArray : public FixedArray {
#undef DECLARE_FRAME_ARRAY_ACCESSORS #undef DECLARE_FRAME_ARRAY_ACCESSORS
inline bool IsWasmFrame(int frame_ix) const; inline bool IsWasmFrame(int frame_ix) const;
inline bool IsWasmInterpretedFrame(int frame_ix) const;
inline bool IsAsmJsWasmFrame(int frame_ix) const; inline bool IsAsmJsWasmFrame(int frame_ix) const;
inline int FrameCount() const; inline int FrameCount() const;
void ShrinkToFit(); void ShrinkToFit();
// Flags. // Flags.
static const int kIsWasmFrame = 1 << 0; enum Flag {
static const int kIsAsmJsWasmFrame = 1 << 1; kIsWasmFrame = 1 << 0,
static const int kIsStrict = 1 << 2; kIsWasmInterpretedFrame = 1 << 1,
static const int kForceConstructor = 1 << 3; kIsAsmJsWasmFrame = 1 << 2,
static const int kAsmJsAtNumberConversion = 1 << 4; kIsStrict = 1 << 3,
kForceConstructor = 1 << 4,
kAsmJsAtNumberConversion = 1 << 5
};
static Handle<FrameArray> AppendJSFrame(Handle<FrameArray> in, static Handle<FrameArray> AppendJSFrame(Handle<FrameArray> in,
Handle<Object> receiver, Handle<Object> receiver,
......
...@@ -17,6 +17,7 @@ end ...@@ -17,6 +17,7 @@ end
Getting current stack trace via "new Error().stack". Getting current stack trace via "new Error().stack".
Error Error
at v8://test/getStack:1:1 at v8://test/getStack:1:1
at func (<WASM>[0]+1)
at main (<WASM>[1]+1) at main (<WASM>[1]+1)
at v8://test/runWasm:1:22 at v8://test/runWasm:1:22
exports.main returned. 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