Commit df5417ae authored by clemensh's avatar clemensh Committed by Commit bot

Refactor FrameSummary for JS and Wasm frames

Wasm frames can be either compiled or interpreted. For interpreted wasm
frames, there is only one physical stack frame representing an
arbitrary stack of interpreted functions. Hence the physical stack
frame needs to provide a summary of the underlying functions.
Summaries were tailored for JavaScript frames before. Now they are
universal.

The refactored FrameSummaries are now also used in the FrameInspector,
and from the StackFrame objects themselves, to avoid code duplication.

All dispatch is implemented "manually", making the FrameSummary still
stack-allocatable.

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

Review-Url: https://codereview.chromium.org/2619353006
Cr-Commit-Position: refs/heads/master@{#42279}
parent 53137df8
...@@ -5,22 +5,28 @@ ...@@ -5,22 +5,28 @@
#include "src/debug/debug-frames.h" #include "src/debug/debug-frames.h"
#include "src/frames-inl.h" #include "src/frames-inl.h"
#include "src/wasm/wasm-interpreter.h"
#include "src/wasm/wasm-objects.h"
namespace v8 { namespace v8 {
namespace internal { namespace internal {
FrameInspector::FrameInspector(StandardFrame* frame, int inlined_jsframe_index, FrameInspector::FrameInspector(StandardFrame* frame, int inlined_frame_index,
Isolate* isolate) Isolate* isolate)
: frame_(frame), deoptimized_frame_(NULL), isolate_(isolate) { : frame_(frame),
frame_summary_(FrameSummary::Get(frame, inlined_frame_index)),
deoptimized_frame_(nullptr),
isolate_(isolate) {
JavaScriptFrame* js_frame = JavaScriptFrame* js_frame =
frame->is_java_script() ? javascript_frame() : nullptr; frame->is_java_script() ? javascript_frame() : nullptr;
DCHECK(js_frame || frame->is_wasm()); DCHECK(js_frame || frame->is_wasm());
has_adapted_arguments_ = js_frame && js_frame->has_adapted_arguments(); has_adapted_arguments_ = js_frame && js_frame->has_adapted_arguments();
is_bottommost_ = inlined_jsframe_index == 0; is_bottommost_ = inlined_frame_index == 0;
is_optimized_ = frame_->is_optimized(); is_optimized_ = frame_->is_optimized();
is_interpreted_ = frame_->is_interpreted(); is_interpreted_ = frame_->is_interpreted();
// Calculate the deoptimized frame. // Calculate the deoptimized frame.
if (frame->is_optimized()) { if (is_optimized_) {
DCHECK(js_frame != nullptr); DCHECK(js_frame != nullptr);
// TODO(turbofan): Revisit once we support deoptimization. // TODO(turbofan): Revisit once we support deoptimization.
if (js_frame->LookupCode()->is_turbofanned() && if (js_frame->LookupCode()->is_turbofanned() &&
...@@ -30,7 +36,7 @@ FrameInspector::FrameInspector(StandardFrame* frame, int inlined_jsframe_index, ...@@ -30,7 +36,7 @@ FrameInspector::FrameInspector(StandardFrame* frame, int inlined_jsframe_index,
} }
deoptimized_frame_ = Deoptimizer::DebuggerInspectableFrame( deoptimized_frame_ = Deoptimizer::DebuggerInspectableFrame(
js_frame, inlined_jsframe_index, isolate); js_frame, inlined_frame_index, isolate);
} }
} }
...@@ -47,16 +53,11 @@ int FrameInspector::GetParametersCount() { ...@@ -47,16 +53,11 @@ int FrameInspector::GetParametersCount() {
} }
Handle<Script> FrameInspector::GetScript() { Handle<Script> FrameInspector::GetScript() {
Object* script = is_optimized_ return Handle<Script>::cast(frame_summary_.script());
? deoptimized_frame_->GetFunction()->shared()->script()
: frame_->script();
return handle(Script::cast(script), isolate_);
} }
Handle<JSFunction> FrameInspector::GetFunction() { Handle<JSFunction> FrameInspector::GetFunction() {
DCHECK(!frame_->is_wasm()); return frame_summary_.AsJavaScript().function();
return is_optimized_ ? deoptimized_frame_->GetFunction()
: handle(javascript_frame()->function(), isolate_);
} }
Handle<Object> FrameInspector::GetParameter(int index) { Handle<Object> FrameInspector::GetParameter(int index) {
...@@ -76,22 +77,16 @@ Handle<Object> FrameInspector::GetExpression(int index) { ...@@ -76,22 +77,16 @@ Handle<Object> FrameInspector::GetExpression(int index) {
} }
int FrameInspector::GetSourcePosition() { int FrameInspector::GetSourcePosition() {
return is_optimized_ ? deoptimized_frame_->GetSourcePosition() return frame_summary_.SourcePosition();
: frame_->position();
} }
bool FrameInspector::IsConstructor() { bool FrameInspector::IsConstructor() { return frame_summary_.is_constructor(); }
return is_optimized_ && !is_bottommost_
? deoptimized_frame_->HasConstructStub()
: frame_->IsConstructor();
}
Handle<Object> FrameInspector::GetContext() { Handle<Object> FrameInspector::GetContext() {
return is_optimized_ ? deoptimized_frame_->GetContext() return is_optimized_ ? deoptimized_frame_->GetContext()
: handle(frame_->context(), isolate_); : handle(frame_->context(), isolate_);
} }
// To inspect all the provided arguments the frame might need to be // To inspect all the provided arguments the frame might need to be
// replaced with the arguments frame. // replaced with the arguments frame.
void FrameInspector::SetArgumentsFrame(StandardFrame* frame) { void FrameInspector::SetArgumentsFrame(StandardFrame* frame) {
...@@ -209,15 +204,11 @@ int DebugFrameHelper::FindIndexedNonNativeFrame(StackTraceFrameIterator* it, ...@@ -209,15 +204,11 @@ int DebugFrameHelper::FindIndexedNonNativeFrame(StackTraceFrameIterator* it,
int index) { int index) {
int count = -1; int count = -1;
for (; !it->done(); it->Advance()) { for (; !it->done(); it->Advance()) {
if (it->is_wasm()) {
if (++count == index) return 0;
continue;
}
List<FrameSummary> frames(FLAG_max_inlining_levels + 1); List<FrameSummary> frames(FLAG_max_inlining_levels + 1);
it->javascript_frame()->Summarize(&frames); it->frame()->Summarize(&frames);
for (int i = frames.length() - 1; i >= 0; i--) { for (int i = frames.length() - 1; i >= 0; i--) {
// Omit functions from native and extension scripts. // Omit functions from native and extension scripts.
if (!frames[i].function()->shared()->IsSubjectToDebugging()) continue; if (!frames[i].is_subject_to_debugging()) continue;
if (++count == index) return i; if (++count == index) return i;
} }
} }
......
...@@ -15,11 +15,13 @@ namespace internal { ...@@ -15,11 +15,13 @@ namespace internal {
class FrameInspector { class FrameInspector {
public: public:
FrameInspector(StandardFrame* frame, int inlined_jsframe_index, FrameInspector(StandardFrame* frame, int inlined_frame_index,
Isolate* isolate); Isolate* isolate);
~FrameInspector(); ~FrameInspector();
FrameSummary& summary() { return frame_summary_; }
int GetParametersCount(); int GetParametersCount();
Handle<JSFunction> GetFunction(); Handle<JSFunction> GetFunction();
Handle<Script> GetScript(); Handle<Script> GetScript();
...@@ -33,9 +35,6 @@ class FrameInspector { ...@@ -33,9 +35,6 @@ class FrameInspector {
return frame_->is_arguments_adaptor() ? ArgumentsAdaptorFrame::cast(frame_) return frame_->is_arguments_adaptor() ? ArgumentsAdaptorFrame::cast(frame_)
: JavaScriptFrame::cast(frame_); : JavaScriptFrame::cast(frame_);
} }
inline WasmCompiledFrame* wasm_frame() {
return WasmCompiledFrame::cast(frame_);
}
JavaScriptFrame* GetArgumentsFrame() { return javascript_frame(); } JavaScriptFrame* GetArgumentsFrame() { return javascript_frame(); }
void SetArgumentsFrame(StandardFrame* frame); void SetArgumentsFrame(StandardFrame* frame);
...@@ -54,6 +53,7 @@ class FrameInspector { ...@@ -54,6 +53,7 @@ class FrameInspector {
Handle<String> parameter_name); Handle<String> parameter_name);
StandardFrame* frame_; StandardFrame* frame_;
FrameSummary frame_summary_;
DeoptimizedFrameInfo* deoptimized_frame_; DeoptimizedFrameInfo* deoptimized_frame_;
Isolate* isolate_; Isolate* isolate_;
bool is_optimized_; bool is_optimized_;
......
...@@ -62,7 +62,7 @@ BreakLocation BreakLocation::FromFrame(Handle<DebugInfo> debug_info, ...@@ -62,7 +62,7 @@ BreakLocation BreakLocation::FromFrame(Handle<DebugInfo> debug_info,
JavaScriptFrame* frame) { JavaScriptFrame* frame) {
FrameSummary summary = FrameSummary::GetFirst(frame); FrameSummary summary = FrameSummary::GetFirst(frame);
int offset = summary.code_offset(); int offset = summary.code_offset();
Handle<AbstractCode> abstract_code = summary.abstract_code(); Handle<AbstractCode> abstract_code = summary.AsJavaScript().abstract_code();
if (abstract_code->IsCode()) offset = offset - 1; if (abstract_code->IsCode()) offset = offset - 1;
auto it = BreakIterator::GetIterator(debug_info, abstract_code); auto it = BreakIterator::GetIterator(debug_info, abstract_code);
it->SkipTo(BreakIndexFromCodeOffset(debug_info, abstract_code, offset)); it->SkipTo(BreakIndexFromCodeOffset(debug_info, abstract_code, offset));
...@@ -72,7 +72,7 @@ BreakLocation BreakLocation::FromFrame(Handle<DebugInfo> debug_info, ...@@ -72,7 +72,7 @@ BreakLocation BreakLocation::FromFrame(Handle<DebugInfo> debug_info,
void BreakLocation::AllAtCurrentStatement(Handle<DebugInfo> debug_info, void BreakLocation::AllAtCurrentStatement(Handle<DebugInfo> debug_info,
JavaScriptFrame* frame, JavaScriptFrame* frame,
List<BreakLocation>* result_out) { List<BreakLocation>* result_out) {
FrameSummary summary = FrameSummary::GetFirst(frame); auto summary = FrameSummary::GetFirst(frame).AsJavaScript();
int offset = summary.code_offset(); int offset = summary.code_offset();
Handle<AbstractCode> abstract_code = summary.abstract_code(); Handle<AbstractCode> abstract_code = summary.abstract_code();
if (abstract_code->IsCode()) offset = offset - 1; if (abstract_code->IsCode()) offset = offset - 1;
...@@ -558,11 +558,9 @@ void Debug::Break(JavaScriptFrame* frame) { ...@@ -558,11 +558,9 @@ void Debug::Break(JavaScriptFrame* frame) {
// Fall through. // Fall through.
case StepIn: { case StepIn: {
FrameSummary summary = FrameSummary::GetFirst(frame); FrameSummary summary = FrameSummary::GetFirst(frame);
int offset = summary.code_offset(); step_break = step_break || location.IsReturn() || current_fp != last_fp ||
step_break = step_break || location.IsReturn() || thread_local_.last_statement_position_ !=
(current_fp != last_fp) || summary.SourceStatementPosition();
(thread_local_.last_statement_position_ !=
summary.abstract_code()->SourceStatementPosition(offset));
break; break;
} }
case StepFrame: case StepFrame:
...@@ -1000,7 +998,7 @@ void Debug::PrepareStep(StepAction step_action) { ...@@ -1000,7 +998,7 @@ void Debug::PrepareStep(StepAction step_action) {
} }
// Get the debug info (create it if it does not exist). // Get the debug info (create it if it does not exist).
FrameSummary summary = FrameSummary::GetFirst(frame); auto summary = FrameSummary::GetFirst(frame).AsJavaScript();
Handle<JSFunction> function(summary.function()); Handle<JSFunction> function(summary.function());
Handle<SharedFunctionInfo> shared(function->shared()); Handle<SharedFunctionInfo> shared(function->shared());
if (!EnsureDebugInfo(shared, function)) { if (!EnsureDebugInfo(shared, function)) {
...@@ -2259,11 +2257,10 @@ void Debug::PrintBreakLocation() { ...@@ -2259,11 +2257,10 @@ void Debug::PrintBreakLocation() {
if (iterator.done()) return; if (iterator.done()) return;
JavaScriptFrame* frame = iterator.frame(); JavaScriptFrame* frame = iterator.frame();
FrameSummary summary = FrameSummary::GetFirst(frame); FrameSummary summary = FrameSummary::GetFirst(frame);
int source_position = int source_position = summary.SourcePosition();
summary.abstract_code()->SourcePosition(summary.code_offset()); Handle<Object> script_obj = summary.script();
Handle<Object> script_obj(summary.function()->shared()->script(), isolate_);
PrintF("[debug] break in function '"); PrintF("[debug] break in function '");
summary.function()->PrintName(); summary.FunctionName()->PrintOn(stdout);
PrintF("'.\n"); PrintF("'.\n");
if (script_obj->IsScript()) { if (script_obj->IsScript()) {
Handle<Script> script = Handle<Script>::cast(script_obj); Handle<Script> script = Handle<Script>::cast(script_obj);
......
...@@ -318,10 +318,6 @@ JavaScriptFrame* StackTraceFrameIterator::javascript_frame() const { ...@@ -318,10 +318,6 @@ JavaScriptFrame* StackTraceFrameIterator::javascript_frame() const {
return JavaScriptFrame::cast(frame()); return JavaScriptFrame::cast(frame());
} }
WasmCompiledFrame* StackTraceFrameIterator::wasm_compiled_frame() const {
return WasmCompiledFrame::cast(frame());
}
inline StackFrame* SafeStackFrameIterator::frame() const { inline StackFrame* SafeStackFrameIterator::frame() const {
DCHECK(!done()); DCHECK(!done());
DCHECK(frame_->is_java_script() || frame_->is_exit() || DCHECK(frame_->is_java_script() || frame_->is_exit() ||
......
This diff is collapsed.
...@@ -748,26 +748,154 @@ class FrameSummary BASE_EMBEDDED { ...@@ -748,26 +748,154 @@ class FrameSummary BASE_EMBEDDED {
// information, but it might miss frames. // information, but it might miss frames.
enum Mode { kExactSummary, kApproximateSummary }; enum Mode { kExactSummary, kApproximateSummary };
FrameSummary(Object* receiver, JSFunction* function, // Subclasses for the different summary kinds:
AbstractCode* abstract_code, int code_offset, #define FRAME_SUMMARY_VARIANTS(F) \
bool is_constructor, Mode mode = kExactSummary); F(JAVA_SCRIPT, JavaScriptFrameSummary, java_script_summary_, JavaScript) \
F(WASM_COMPILED, WasmCompiledFrameSummary, wasm_compiled_summary_, \
WasmCompiled) \
F(WASM_INTERPRETED, WasmInterpretedFrameSummary, wasm_interpreted_summary_, \
WasmInterpreted)
#define FRAME_SUMMARY_KIND(kind, type, field, desc) kind,
enum Kind { FRAME_SUMMARY_VARIANTS(FRAME_SUMMARY_KIND) };
#undef FRAME_SUMMARY_KIND
class FrameSummaryBase {
public:
FrameSummaryBase(Isolate* isolate, Kind kind)
: isolate_(isolate), kind_(kind) {}
Isolate* isolate() const { return isolate_; }
Kind kind() const { return kind_; }
private:
Isolate* isolate_;
Kind kind_;
};
class JavaScriptFrameSummary : public FrameSummaryBase {
public:
JavaScriptFrameSummary(Isolate* isolate, Object* receiver,
JSFunction* function, AbstractCode* abstract_code,
int code_offset, bool is_constructor,
Mode mode = kExactSummary);
Handle<Object> receiver() const { return receiver_; }
Handle<JSFunction> function() const { return function_; }
Handle<AbstractCode> abstract_code() const { return abstract_code_; }
int code_offset() const { return code_offset_; }
bool is_constructor() const { return is_constructor_; }
bool is_subject_to_debugging() const;
int SourcePosition() const;
int SourceStatementPosition() const;
Handle<Object> script() const;
Handle<String> FunctionName() const;
Handle<Context> native_context() const;
private:
Handle<Object> receiver_;
Handle<JSFunction> function_;
Handle<AbstractCode> abstract_code_;
int code_offset_;
bool is_constructor_;
};
class WasmFrameSummary : public FrameSummaryBase {
protected:
WasmFrameSummary(Isolate*, Kind, Handle<WasmInstanceObject>,
bool at_to_number_conversion);
public:
Handle<Object> receiver() const;
uint32_t function_index() const;
int byte_offset() const;
bool is_constructor() const { return false; }
bool is_subject_to_debugging() const { return true; }
int SourcePosition() const;
int SourceStatementPosition() const { return SourcePosition(); }
Handle<Script> script() const;
Handle<WasmInstanceObject> wasm_instance() const { return wasm_instance_; }
Handle<String> FunctionName() const;
Handle<Context> native_context() const;
bool at_to_number_conversion() const { return at_to_number_conversion_; }
private:
Handle<WasmInstanceObject> wasm_instance_;
bool at_to_number_conversion_;
};
class WasmCompiledFrameSummary : public WasmFrameSummary {
public:
WasmCompiledFrameSummary(Isolate*, Handle<WasmInstanceObject>, Handle<Code>,
int code_offset, bool at_to_number_conversion);
uint32_t function_index() const;
Handle<Code> code() const { return code_; }
int code_offset() const { return code_offset_; }
int byte_offset() const;
private:
Handle<Code> code_;
int code_offset_;
};
static FrameSummary GetFirst(StandardFrame* frame); class WasmInterpretedFrameSummary : public WasmFrameSummary {
public:
WasmInterpretedFrameSummary(Isolate*, Handle<WasmInstanceObject>,
uint32_t function_index, int byte_offset);
uint32_t function_index() const { return function_index_; }
int code_offset() const { return byte_offset_; }
int byte_offset() const { return byte_offset_; }
private:
uint32_t function_index_;
int byte_offset_;
};
#undef FRAME_SUMMARY_FIELD
#define FRAME_SUMMARY_CONS(kind, type, field, desc) \
FrameSummary(type summ) : field(summ) {} // NOLINT
FRAME_SUMMARY_VARIANTS(FRAME_SUMMARY_CONS)
#undef FRAME_SUMMARY_CONS
Handle<Object> receiver() const { return receiver_; } ~FrameSummary();
Handle<JSFunction> function() const { return function_; }
Handle<AbstractCode> abstract_code() const { return abstract_code_; }
int code_offset() const { return code_offset_; }
bool is_constructor() const { return is_constructor_; }
void Print(); static inline FrameSummary GetFirst(const StandardFrame* frame) {
return Get(frame, 0);
}
static FrameSummary Get(const StandardFrame* frame, int index);
static FrameSummary GetSingle(const StandardFrame* frame);
// Dispatched accessors.
Handle<Object> receiver() const;
int code_offset() const;
bool is_constructor() const;
bool is_subject_to_debugging() const;
Handle<Object> script() const;
int SourcePosition() const;
int SourceStatementPosition() const;
Handle<String> FunctionName() const;
Handle<Context> native_context() const;
#define FRAME_SUMMARY_CAST(kind_, type, field, desc) \
bool Is##desc() const { return base_.kind() == kind_; } \
const type& As##desc() const { \
DCHECK_EQ(base_.kind(), kind_); \
return field; \
}
FRAME_SUMMARY_VARIANTS(FRAME_SUMMARY_CAST)
#undef FRAME_SUMMARY_CAST
bool IsWasm() const { return IsWasmCompiled() || IsWasmInterpreted(); }
const WasmFrameSummary& AsWasm() const {
if (IsWasmCompiled()) return AsWasmCompiled();
return AsWasmInterpreted();
}
private: private:
Handle<Object> receiver_; #define FRAME_SUMMARY_FIELD(kind, type, field, desc) type field;
Handle<JSFunction> function_; union {
Handle<AbstractCode> abstract_code_; FrameSummaryBase base_;
int code_offset_; FRAME_SUMMARY_VARIANTS(FRAME_SUMMARY_FIELD)
bool is_constructor_; };
}; };
class StandardFrame : public StackFrame { class StandardFrame : public StackFrame {
...@@ -1365,9 +1493,6 @@ class StackTraceFrameIterator BASE_EMBEDDED { ...@@ -1365,9 +1493,6 @@ class StackTraceFrameIterator BASE_EMBEDDED {
inline bool is_javascript() const; inline bool is_javascript() const;
inline bool is_wasm() const; inline bool is_wasm() const;
inline JavaScriptFrame* javascript_frame() const; inline JavaScriptFrame* javascript_frame() const;
// TODO(clemensh): Remove / refactor this for general wasm frames
// (compiled/interpreted).
inline WasmCompiledFrame* wasm_compiled_frame() const;
// Advance to the frame holding the arguments for the current // Advance to the frame holding the arguments for the current
// frame. This only affects the current frame if it is a javascript frame and // frame. This only affects the current frame if it is a javascript frame and
......
...@@ -461,13 +461,14 @@ Handle<Object> Isolate::CaptureSimpleStackTrace(Handle<JSReceiver> error_object, ...@@ -461,13 +461,14 @@ Handle<Object> Isolate::CaptureSimpleStackTrace(Handle<JSReceiver> error_object,
List<FrameSummary> frames(FLAG_max_inlining_levels + 1); List<FrameSummary> frames(FLAG_max_inlining_levels + 1);
js_frame->Summarize(&frames); js_frame->Summarize(&frames);
for (int i = frames.length() - 1; i >= 0; i--) { for (int i = frames.length() - 1; i >= 0; i--) {
Handle<JSFunction> fun = frames[i].function(); const auto& summ = frames[i].AsJavaScript();
Handle<JSFunction> fun = summ.function();
// Filter out internal frames that we do not want to show. // Filter out internal frames that we do not want to show.
if (!helper.IsVisibleInStackTrace(*fun)) continue; if (!helper.IsVisibleInStackTrace(*fun)) continue;
Handle<Object> recv = frames[i].receiver(); Handle<Object> recv = frames[i].receiver();
Handle<AbstractCode> abstract_code = frames[i].abstract_code(); Handle<AbstractCode> abstract_code = summ.abstract_code();
const int offset = frames[i].code_offset(); const int offset = frames[i].code_offset();
bool force_constructor = false; bool force_constructor = false;
...@@ -627,21 +628,22 @@ class CaptureStackTraceHelper { ...@@ -627,21 +628,22 @@ class CaptureStackTraceHelper {
} }
Handle<JSObject> NewStackFrameObject(FrameSummary& summ) { Handle<JSObject> NewStackFrameObject(FrameSummary& summ) {
int position = summ.abstract_code()->SourcePosition(summ.code_offset()); if (summ.IsJavaScript()) return NewStackFrameObject(summ.AsJavaScript());
return NewStackFrameObject(summ.function(), position, if (summ.IsWasm()) return NewStackFrameObject(summ.AsWasm());
summ.is_constructor()); UNREACHABLE();
return Handle<JSObject>::null();
} }
Handle<JSObject> NewStackFrameObject(Handle<JSFunction> fun, int position, Handle<JSObject> NewStackFrameObject(
bool is_constructor) { const FrameSummary::JavaScriptFrameSummary& summ) {
Handle<JSObject> stack_frame = Handle<JSObject> stack_frame =
factory()->NewJSObject(isolate_->object_function()); factory()->NewJSObject(isolate_->object_function());
Handle<Script> script(Script::cast(fun->shared()->script()), isolate_); Handle<Script> script = Handle<Script>::cast(summ.script());
if (!line_key_.is_null()) { if (!line_key_.is_null()) {
Script::PositionInfo info; Script::PositionInfo info;
bool valid_pos = bool valid_pos = Script::GetPositionInfo(script, summ.SourcePosition(),
Script::GetPositionInfo(script, position, &info, Script::WITH_OFFSET); &info, Script::WITH_OFFSET);
if (!column_key_.is_null() && valid_pos) { if (!column_key_.is_null() && valid_pos) {
JSObject::AddProperty(stack_frame, column_key_, JSObject::AddProperty(stack_frame, column_key_,
...@@ -676,12 +678,13 @@ class CaptureStackTraceHelper { ...@@ -676,12 +678,13 @@ class CaptureStackTraceHelper {
} }
if (!function_key_.is_null()) { if (!function_key_.is_null()) {
Handle<Object> fun_name = JSFunction::GetDebugName(fun); Handle<String> fun_name = summ.FunctionName();
JSObject::AddProperty(stack_frame, function_key_, fun_name, NONE); JSObject::AddProperty(stack_frame, function_key_, fun_name, NONE);
} }
if (!constructor_key_.is_null()) { if (!constructor_key_.is_null()) {
Handle<Object> is_constructor_obj = factory()->ToBoolean(is_constructor); Handle<Object> is_constructor_obj =
factory()->ToBoolean(summ.is_constructor());
JSObject::AddProperty(stack_frame, constructor_key_, is_constructor_obj, JSObject::AddProperty(stack_frame, constructor_key_, is_constructor_obj,
NONE); NONE);
} }
...@@ -703,29 +706,28 @@ class CaptureStackTraceHelper { ...@@ -703,29 +706,28 @@ class CaptureStackTraceHelper {
return stack_frame; return stack_frame;
} }
Handle<JSObject> NewStackFrameObject(WasmCompiledFrame* frame) { Handle<JSObject> NewStackFrameObject(
const FrameSummary::WasmFrameSummary& summ) {
Handle<JSObject> stack_frame = Handle<JSObject> stack_frame =
factory()->NewJSObject(isolate_->object_function()); factory()->NewJSObject(isolate_->object_function());
if (!function_key_.is_null()) { if (!function_key_.is_null()) {
Handle<WasmCompiledModule> compiled_module( Handle<WasmCompiledModule> compiled_module(
frame->wasm_instance()->compiled_module(), isolate_); summ.wasm_instance()->compiled_module(), isolate_);
Handle<String> name = WasmCompiledModule::GetFunctionName( Handle<String> name = WasmCompiledModule::GetFunctionName(
isolate_, compiled_module, frame->function_index()); isolate_, compiled_module, summ.function_index());
JSObject::AddProperty(stack_frame, function_key_, name, NONE); JSObject::AddProperty(stack_frame, function_key_, name, NONE);
} }
// Encode the function index as line number (1-based). // Encode the function index as line number (1-based).
if (!line_key_.is_null()) { if (!line_key_.is_null()) {
JSObject::AddProperty( JSObject::AddProperty(
stack_frame, line_key_, stack_frame, line_key_,
isolate_->factory()->NewNumberFromInt(frame->function_index() + 1), isolate_->factory()->NewNumberFromInt(summ.function_index() + 1),
NONE); NONE);
} }
// Encode the byte offset as column (1-based). // Encode the byte offset as column (1-based).
if (!column_key_.is_null()) { if (!column_key_.is_null()) {
Code* code = frame->LookupCode(); int position = summ.byte_offset();
int offset = static_cast<int>(frame->pc() - code->instruction_start());
int position = AbstractCode::cast(code)->SourcePosition(offset);
// Make position 1-based. // Make position 1-based.
if (position >= 0) ++position; if (position >= 0) ++position;
JSObject::AddProperty(stack_frame, column_key_, JSObject::AddProperty(stack_frame, column_key_,
...@@ -733,7 +735,7 @@ class CaptureStackTraceHelper { ...@@ -733,7 +735,7 @@ class CaptureStackTraceHelper {
NONE); NONE);
} }
if (!script_id_key_.is_null()) { if (!script_id_key_.is_null()) {
int script_id = frame->script()->id(); int script_id = summ.script()->id();
JSObject::AddProperty(stack_frame, script_id_key_, JSObject::AddProperty(stack_frame, script_id_key_,
handle(Smi::FromInt(script_id), isolate_), NONE); handle(Smi::FromInt(script_id), isolate_), NONE);
} }
...@@ -770,25 +772,16 @@ Handle<JSArray> Isolate::CaptureCurrentStackTrace( ...@@ -770,25 +772,16 @@ Handle<JSArray> Isolate::CaptureCurrentStackTrace(
for (StackTraceFrameIterator it(this); !it.done() && (frames_seen < limit); for (StackTraceFrameIterator it(this); !it.done() && (frames_seen < limit);
it.Advance()) { it.Advance()) {
StandardFrame* frame = it.frame(); StandardFrame* frame = it.frame();
if (frame->is_java_script()) { // Set initial size to the maximum inlining level + 1 for the outermost
// Set initial size to the maximum inlining level + 1 for the outermost // function.
// function. List<FrameSummary> frames(FLAG_max_inlining_levels + 1);
List<FrameSummary> frames(FLAG_max_inlining_levels + 1); frame->Summarize(&frames);
JavaScriptFrame::cast(frame)->Summarize(&frames); for (int i = frames.length() - 1; i >= 0 && frames_seen < limit; i--) {
for (int i = frames.length() - 1; i >= 0 && frames_seen < limit; i--) { // Filter frames from other security contexts.
Handle<JSFunction> fun = frames[i].function(); if (!(options & StackTrace::kExposeFramesAcrossSecurityOrigins) &&
// Filter frames from other security contexts. !this->context()->HasSameSecurityTokenAs(*frames[i].native_context()))
if (!(options & StackTrace::kExposeFramesAcrossSecurityOrigins) && continue;
!this->context()->HasSameSecurityTokenAs(fun->context())) Handle<JSObject> new_frame_obj = helper.NewStackFrameObject(frames[i]);
continue;
Handle<JSObject> new_frame_obj = helper.NewStackFrameObject(frames[i]);
stack_trace_elems->set(frames_seen, *new_frame_obj);
frames_seen++;
}
} else {
DCHECK(frame->is_wasm());
WasmCompiledFrame* wasm_frame = WasmCompiledFrame::cast(frame);
Handle<JSObject> new_frame_obj = helper.NewStackFrameObject(wasm_frame);
stack_trace_elems->set(frames_seen, *new_frame_obj); stack_trace_elems->set(frames_seen, *new_frame_obj);
frames_seen++; frames_seen++;
} }
...@@ -1345,7 +1338,7 @@ HandlerTable::CatchPrediction PredictException(JavaScriptFrame* frame) { ...@@ -1345,7 +1338,7 @@ HandlerTable::CatchPrediction PredictException(JavaScriptFrame* frame) {
List<FrameSummary> summaries; List<FrameSummary> summaries;
frame->Summarize(&summaries); frame->Summarize(&summaries);
for (const FrameSummary& summary : summaries) { for (const FrameSummary& summary : summaries) {
Handle<AbstractCode> code = summary.abstract_code(); Handle<AbstractCode> code = summary.AsJavaScript().abstract_code();
if (code->IsCode() && code->kind() == AbstractCode::BUILTIN) { if (code->IsCode() && code->kind() == AbstractCode::BUILTIN) {
if (code->GetCode()->is_promise_rejection()) { if (code->GetCode()->is_promise_rejection()) {
return HandlerTable::PROMISE; return HandlerTable::PROMISE;
...@@ -1359,7 +1352,7 @@ HandlerTable::CatchPrediction PredictException(JavaScriptFrame* frame) { ...@@ -1359,7 +1352,7 @@ HandlerTable::CatchPrediction PredictException(JavaScriptFrame* frame) {
} }
if (code->kind() == AbstractCode::OPTIMIZED_FUNCTION) { if (code->kind() == AbstractCode::OPTIMIZED_FUNCTION) {
DCHECK(summary.function()->shared()->asm_function()); DCHECK(summary.AsJavaScript().function()->shared()->asm_function());
// asm code cannot contain try-catch. // asm code cannot contain try-catch.
continue; continue;
} }
...@@ -1503,23 +1496,27 @@ bool Isolate::ComputeLocation(MessageLocation* target) { ...@@ -1503,23 +1496,27 @@ bool Isolate::ComputeLocation(MessageLocation* target) {
StackTraceFrameIterator it(this); StackTraceFrameIterator it(this);
if (it.done()) return false; if (it.done()) return false;
StandardFrame* frame = it.frame(); StandardFrame* frame = it.frame();
// TODO(clemensh): handle wasm frames
if (!frame->is_java_script()) return false;
JSFunction* fun = JavaScriptFrame::cast(frame)->function();
Object* script = fun->shared()->script();
if (!script->IsScript() ||
(Script::cast(script)->source()->IsUndefined(this))) {
return false;
}
Handle<Script> casted_script(Script::cast(script), this);
// Compute the location from the function and the relocation info of the // Compute the location from the function and the relocation info of the
// baseline code. For optimized code this will use the deoptimization // baseline code. For optimized code this will use the deoptimization
// information to get canonical location information. // information to get canonical location information.
List<FrameSummary> frames(FLAG_max_inlining_levels + 1); List<FrameSummary> frames(FLAG_max_inlining_levels + 1);
JavaScriptFrame::cast(frame)->Summarize(&frames); frame->Summarize(&frames);
FrameSummary& summary = frames.last(); FrameSummary& summary = frames.last();
int pos = summary.abstract_code()->SourcePosition(summary.code_offset()); int pos = summary.SourcePosition();
*target = MessageLocation(casted_script, pos, pos + 1, handle(fun, this)); Handle<JSFunction> fun;
Handle<Object> script = summary.script();
if (!script->IsScript() ||
(Script::cast(*script)->source()->IsUndefined(this))) {
return false;
}
// TODO(wasm): Remove this once trap-if is always on.
// Background: Without trap-if, the information on the stack trace is
// incomplete (see bug v8:5007).
if (summary.IsWasmCompiled() && !FLAG_wasm_trap_if) return false;
if (summary.IsJavaScript()) fun = summary.AsJavaScript().function();
*target = MessageLocation(Handle<Script>::cast(script), pos, pos + 1, fun);
return true; return true;
} }
......
...@@ -64,8 +64,8 @@ class List { ...@@ -64,8 +64,8 @@ class List {
// not safe to use after operations that can change the list's // not safe to use after operations that can change the list's
// backing store (e.g. Add). // backing store (e.g. Add).
inline T& operator[](int i) const { inline T& operator[](int i) const {
DCHECK(0 <= i); DCHECK_LE(0, i);
SLOW_DCHECK(static_cast<unsigned>(i) < static_cast<unsigned>(length_)); DCHECK_GT(length_, i);
return data_[i]; return data_[i];
} }
inline T& at(int i) const { return operator[](i); } inline T& at(int i) const { return operator[](i); }
......
...@@ -12983,7 +12983,7 @@ void Script::SetEvalOrigin(Handle<Script> script, ...@@ -12983,7 +12983,7 @@ void Script::SetEvalOrigin(Handle<Script> script,
StackTraceFrameIterator it(script->GetIsolate()); StackTraceFrameIterator it(script->GetIsolate());
if (!it.done() && it.is_javascript()) { if (!it.done() && it.is_javascript()) {
FrameSummary summary = FrameSummary::GetFirst(it.javascript_frame()); FrameSummary summary = FrameSummary::GetFirst(it.javascript_frame());
script->set_eval_from_shared(summary.function()->shared()); script->set_eval_from_shared(summary.AsJavaScript().function()->shared());
script->set_eval_from_position(-summary.code_offset()); script->set_eval_from_position(-summary.code_offset());
return; return;
} }
......
...@@ -435,22 +435,18 @@ RUNTIME_FUNCTION(Runtime_GetFrameCount) { ...@@ -435,22 +435,18 @@ RUNTIME_FUNCTION(Runtime_GetFrameCount) {
return Smi::kZero; return Smi::kZero;
} }
List<FrameSummary> frames(FLAG_max_inlining_levels + 1);
for (StackTraceFrameIterator it(isolate, id); !it.done(); it.Advance()) { for (StackTraceFrameIterator it(isolate, id); !it.done(); it.Advance()) {
List<FrameSummary> frames(FLAG_max_inlining_levels + 1); frames.Clear();
if (it.is_wasm()) { it.frame()->Summarize(&frames);
n++; for (int i = frames.length() - 1; i >= 0; i--) {
} else { // Omit functions from native and extension scripts.
it.javascript_frame()->Summarize(&frames); if (frames[i].is_subject_to_debugging()) n++;
for (int i = frames.length() - 1; i >= 0; i--) {
// Omit functions from native and extension scripts.
if (frames[i].function()->shared()->IsSubjectToDebugging()) n++;
}
} }
} }
return Smi::FromInt(n); return Smi::FromInt(n);
} }
static const int kFrameDetailsFrameIdIndex = 0; static const int kFrameDetailsFrameIdIndex = 0;
static const int kFrameDetailsReceiverIndex = 1; static const int kFrameDetailsReceiverIndex = 1;
static const int kFrameDetailsFunctionIndex = 2; static const int kFrameDetailsFunctionIndex = 2;
...@@ -499,11 +495,11 @@ RUNTIME_FUNCTION(Runtime_GetFrameDetails) { ...@@ -499,11 +495,11 @@ RUNTIME_FUNCTION(Runtime_GetFrameDetails) {
StackTraceFrameIterator it(isolate, id); StackTraceFrameIterator it(isolate, id);
// Inlined frame index in optimized frame, starting from outer function. // Inlined frame index in optimized frame, starting from outer function.
int inlined_jsframe_index = int inlined_frame_index =
DebugFrameHelper::FindIndexedNonNativeFrame(&it, index); DebugFrameHelper::FindIndexedNonNativeFrame(&it, index);
if (inlined_jsframe_index == -1) return heap->undefined_value(); if (inlined_frame_index == -1) return heap->undefined_value();
FrameInspector frame_inspector(it.frame(), inlined_jsframe_index, isolate); FrameInspector frame_inspector(it.frame(), inlined_frame_index, isolate);
// Traverse the saved contexts chain to find the active context for the // Traverse the saved contexts chain to find the active context for the
// selected frame. // selected frame.
...@@ -514,10 +510,7 @@ RUNTIME_FUNCTION(Runtime_GetFrameDetails) { ...@@ -514,10 +510,7 @@ RUNTIME_FUNCTION(Runtime_GetFrameDetails) {
Handle<Object> frame_id(DebugFrameHelper::WrapFrameId(it.frame()->id()), Handle<Object> frame_id(DebugFrameHelper::WrapFrameId(it.frame()->id()),
isolate); isolate);
// Find source position in unoptimized code. if (frame_inspector.summary().IsWasm()) {
int position = frame_inspector.GetSourcePosition();
if (it.is_wasm()) {
// Create the details array (no dynamic information for wasm). // Create the details array (no dynamic information for wasm).
Handle<FixedArray> details = Handle<FixedArray> details =
isolate->factory()->NewFixedArray(kFrameDetailsFirstDynamicIndex); isolate->factory()->NewFixedArray(kFrameDetailsFirstDynamicIndex);
...@@ -526,11 +519,7 @@ RUNTIME_FUNCTION(Runtime_GetFrameDetails) { ...@@ -526,11 +519,7 @@ RUNTIME_FUNCTION(Runtime_GetFrameDetails) {
details->set(kFrameDetailsFrameIdIndex, *frame_id); details->set(kFrameDetailsFrameIdIndex, *frame_id);
// Add the function name. // Add the function name.
Handle<WasmCompiledModule> compiled_module( Handle<String> func_name = frame_inspector.summary().FunctionName();
it.wasm_compiled_frame()->wasm_instance()->compiled_module(), isolate);
int func_index = it.wasm_compiled_frame()->function_index();
Handle<String> func_name = WasmCompiledModule::GetFunctionName(
isolate, compiled_module, func_index);
details->set(kFrameDetailsFunctionIndex, *func_name); details->set(kFrameDetailsFunctionIndex, *func_name);
// Add the script wrapper // Add the script wrapper
...@@ -545,20 +534,8 @@ RUNTIME_FUNCTION(Runtime_GetFrameDetails) { ...@@ -545,20 +534,8 @@ RUNTIME_FUNCTION(Runtime_GetFrameDetails) {
details->set(kFrameDetailsLocalCountIndex, Smi::kZero); details->set(kFrameDetailsLocalCountIndex, Smi::kZero);
// Add the source position. // Add the source position.
// For wasm, it is function-local, so translate it to a module-relative int position = frame_inspector.summary().SourcePosition();
// position, such that together with the script it uniquely identifies the details->set(kFrameDetailsSourcePositionIndex, Smi::FromInt(position));
// position.
Handle<Object> positionValue;
if (position != kNoSourcePosition) {
int translated_position = position;
// No further translation needed for asm.js modules.
if (!compiled_module->is_asm_js()) {
translated_position +=
wasm::GetFunctionCodeOffset(compiled_module, func_index);
}
details->set(kFrameDetailsSourcePositionIndex,
Smi::FromInt(translated_position));
}
// Add the constructor information. // Add the constructor information.
details->set(kFrameDetailsConstructCallIndex, heap->ToBoolean(false)); details->set(kFrameDetailsConstructCallIndex, heap->ToBoolean(false));
...@@ -579,6 +556,9 @@ RUNTIME_FUNCTION(Runtime_GetFrameDetails) { ...@@ -579,6 +556,9 @@ RUNTIME_FUNCTION(Runtime_GetFrameDetails) {
return *isolate->factory()->NewJSArrayWithElements(details); return *isolate->factory()->NewJSArrayWithElements(details);
} }
// Find source position in unoptimized code.
int position = frame_inspector.GetSourcePosition();
// Handle JavaScript frames. // Handle JavaScript frames.
bool is_optimized = it.frame()->is_optimized(); bool is_optimized = it.frame()->is_optimized();
...@@ -660,7 +640,7 @@ RUNTIME_FUNCTION(Runtime_GetFrameDetails) { ...@@ -660,7 +640,7 @@ RUNTIME_FUNCTION(Runtime_GetFrameDetails) {
// the provided parameters whereas the function frame always have the number // the provided parameters whereas the function frame always have the number
// of arguments matching the functions parameters. The rest of the // of arguments matching the functions parameters. The rest of the
// information (except for what is collected above) is the same. // information (except for what is collected above) is the same.
if ((inlined_jsframe_index == 0) && if ((inlined_frame_index == 0) &&
it.javascript_frame()->has_adapted_arguments()) { it.javascript_frame()->has_adapted_arguments()) {
it.AdvanceToArgumentsFrame(); it.AdvanceToArgumentsFrame();
frame_inspector.SetArgumentsFrame(it.frame()); frame_inspector.SetArgumentsFrame(it.frame());
...@@ -718,7 +698,7 @@ RUNTIME_FUNCTION(Runtime_GetFrameDetails) { ...@@ -718,7 +698,7 @@ RUNTIME_FUNCTION(Runtime_GetFrameDetails) {
} }
if (is_optimized) { if (is_optimized) {
flags |= 1 << 1; flags |= 1 << 1;
flags |= inlined_jsframe_index << 2; flags |= inlined_frame_index << 2;
} }
details->set(kFrameDetailsFlagsIndex, Smi::FromInt(flags)); details->set(kFrameDetailsFlagsIndex, Smi::FromInt(flags));
......
...@@ -332,7 +332,7 @@ bool ComputeLocation(Isolate* isolate, MessageLocation* target) { ...@@ -332,7 +332,7 @@ bool ComputeLocation(Isolate* isolate, MessageLocation* target) {
// information to get canonical location information. // information to get canonical location information.
List<FrameSummary> frames(FLAG_max_inlining_levels + 1); List<FrameSummary> frames(FLAG_max_inlining_levels + 1);
it.frame()->Summarize(&frames); it.frame()->Summarize(&frames);
FrameSummary& summary = frames.last(); auto& summary = frames.last().AsJavaScript();
Handle<JSFunction> function = summary.function(); Handle<JSFunction> function = summary.function();
Handle<Object> script(function->shared()->script(), isolate); Handle<Object> script(function->shared()->script(), isolate);
int pos = summary.abstract_code()->SourcePosition(summary.code_offset()); int pos = summary.abstract_code()->SourcePosition(summary.code_offset());
......
...@@ -450,6 +450,7 @@ Handle<WasmCompiledModule> WasmCompiledModule::New( ...@@ -450,6 +450,7 @@ Handle<WasmCompiledModule> WasmCompiledModule::New(
reinterpret_cast<WasmCompiledModule*>(*ret), isolate); reinterpret_cast<WasmCompiledModule*>(*ret), isolate);
compiled_module->InitId(); compiled_module->InitId();
compiled_module->set_shared(shared); compiled_module->set_shared(shared);
compiled_module->set_native_context(isolate->native_context());
return compiled_module; return compiled_module;
} }
......
...@@ -237,6 +237,7 @@ class WasmCompiledModule : public FixedArray { ...@@ -237,6 +237,7 @@ class WasmCompiledModule : public FixedArray {
#define CORE_WCM_PROPERTY_TABLE(MACRO) \ #define CORE_WCM_PROPERTY_TABLE(MACRO) \
MACRO(WASM_OBJECT, WasmSharedModuleData, shared) \ MACRO(WASM_OBJECT, WasmSharedModuleData, shared) \
MACRO(OBJECT, Context, native_context) \
MACRO(OBJECT, FixedArray, code_table) \ MACRO(OBJECT, FixedArray, code_table) \
MACRO(OBJECT, FixedArray, function_tables) \ MACRO(OBJECT, FixedArray, function_tables) \
MACRO(OBJECT, FixedArray, signature_tables) \ MACRO(OBJECT, FixedArray, signature_tables) \
......
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