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

Prepare StackFrame hierarchy & iterators for WASM

This particularly changes the StackTraceFrameIterator such that is not
only returs JavaScriptFrames, but also WasmFrames. Because of that,
some methods (Summarize, function, receiver) were pulled up to the
StandardFrame, with specializations in JavaScriptFrame and WasmFrame.

R=jfb@chromium.org, titzer@chromium.org
BUG=

Review URL: https://codereview.chromium.org/1861283002

Cr-Commit-Position: refs/heads/master@{#35293}
parent 141324cf
...@@ -199,11 +199,6 @@ inline int JavaScriptFrame::ComputeOperandsCount() const { ...@@ -199,11 +199,6 @@ inline int JavaScriptFrame::ComputeOperandsCount() const {
} }
inline Object* JavaScriptFrame::receiver() const {
return GetParameter(-1);
}
inline void JavaScriptFrame::set_receiver(Object* value) { inline void JavaScriptFrame::set_receiver(Object* value) {
Memory::Object_at(GetParameterSlot(-1)) = value; Memory::Object_at(GetParameterSlot(-1)) = value;
} }
...@@ -214,11 +209,6 @@ inline bool JavaScriptFrame::has_adapted_arguments() const { ...@@ -214,11 +209,6 @@ inline bool JavaScriptFrame::has_adapted_arguments() const {
} }
inline JSFunction* JavaScriptFrame::function() const {
return JSFunction::cast(function_slot_object());
}
inline Object* JavaScriptFrame::function_slot_object() const { inline Object* JavaScriptFrame::function_slot_object() const {
const int offset = JavaScriptFrameConstants::kFunctionOffset; const int offset = JavaScriptFrameConstants::kFunctionOffset;
return Memory::Object_at(fp() + offset); return Memory::Object_at(fp() + offset);
...@@ -288,6 +278,28 @@ inline JavaScriptFrame* JavaScriptFrameIterator::frame() const { ...@@ -288,6 +278,28 @@ inline JavaScriptFrame* JavaScriptFrameIterator::frame() const {
return static_cast<JavaScriptFrame*>(frame); return static_cast<JavaScriptFrame*>(frame);
} }
inline StandardFrame* StackTraceFrameIterator::frame() const {
StackFrame* frame = iterator_.frame();
DCHECK(frame->is_java_script() || frame->is_arguments_adaptor() ||
frame->is_wasm());
return static_cast<StandardFrame*>(frame);
}
bool StackTraceFrameIterator::is_javascript() const {
return frame()->is_java_script();
}
bool StackTraceFrameIterator::is_wasm() const { return frame()->is_wasm(); }
JavaScriptFrame* StackTraceFrameIterator::javascript_frame() const {
DCHECK(is_javascript());
return static_cast<JavaScriptFrame*>(frame());
}
WasmFrame* StackTraceFrameIterator::wasm_frame() const {
DCHECK(is_wasm());
return static_cast<WasmFrame*>(frame());
}
inline StackFrame* SafeStackFrameIterator::frame() const { inline StackFrame* SafeStackFrameIterator::frame() const {
DCHECK(!done()); DCHECK(!done());
......
...@@ -160,28 +160,29 @@ void JavaScriptFrameIterator::AdvanceToArgumentsFrame() { ...@@ -160,28 +160,29 @@ void JavaScriptFrameIterator::AdvanceToArgumentsFrame() {
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
StackTraceFrameIterator::StackTraceFrameIterator(Isolate* isolate) StackTraceFrameIterator::StackTraceFrameIterator(Isolate* isolate)
: JavaScriptFrameIterator(isolate) { : iterator_(isolate) {
if (!done() && !IsValidFrame()) Advance(); if (!done() && !IsValidFrame(iterator_.frame())) Advance();
} }
void StackTraceFrameIterator::Advance() { void StackTraceFrameIterator::Advance() {
while (true) { do {
JavaScriptFrameIterator::Advance(); iterator_.Advance();
if (done()) return; } while (!done() && !IsValidFrame(iterator_.frame()));
if (IsValidFrame()) return;
}
} }
bool StackTraceFrameIterator::IsValidFrame(StackFrame* frame) const {
bool StackTraceFrameIterator::IsValidFrame() { if (frame->is_java_script()) {
if (!frame()->function()->IsJSFunction()) return false; JavaScriptFrame* jsFrame = static_cast<JavaScriptFrame*>(frame);
Object* script = frame()->function()->shared()->script(); if (!jsFrame->function()->IsJSFunction()) return false;
Object* script = jsFrame->function()->shared()->script();
// Don't show functions from native scripts to user. // Don't show functions from native scripts to user.
return (script->IsScript() && return (script->IsScript() &&
Script::TYPE_NATIVE != Script::cast(script)->type()); Script::TYPE_NATIVE != Script::cast(script)->type());
}
// apart from javascript, only wasm is valid
return frame->is_wasm();
} }
...@@ -616,6 +617,19 @@ void ExitFrame::FillState(Address fp, Address sp, State* state) { ...@@ -616,6 +617,19 @@ void ExitFrame::FillState(Address fp, Address sp, State* state) {
state->constant_pool_address = NULL; state->constant_pool_address = NULL;
} }
void StandardFrame::Summarize(List<FrameSummary>* functions) const {
DCHECK(functions->length() == 0);
// default implementation: no summary added
}
JSFunction* StandardFrame::function() const {
// this default implementation is overridden by JS and WASM frames
return nullptr;
}
Object* StandardFrame::receiver() const {
return isolate()->heap()->undefined_value();
}
Address StandardFrame::GetExpressionAddress(int n) const { Address StandardFrame::GetExpressionAddress(int n) const {
const int offset = StandardFrameConstants::kExpressionsOffset; const int offset = StandardFrameConstants::kExpressionsOffset;
...@@ -846,8 +860,7 @@ void JavaScriptFrame::GetFunctions(List<JSFunction*>* functions) const { ...@@ -846,8 +860,7 @@ void JavaScriptFrame::GetFunctions(List<JSFunction*>* functions) const {
functions->Add(function()); functions->Add(function());
} }
void JavaScriptFrame::Summarize(List<FrameSummary>* functions) const {
void JavaScriptFrame::Summarize(List<FrameSummary>* functions) {
DCHECK(functions->length() == 0); DCHECK(functions->length() == 0);
Code* code = LookupCode(); Code* code = LookupCode();
int offset = static_cast<int>(pc() - code->instruction_start()); int offset = static_cast<int>(pc() - code->instruction_start());
...@@ -857,6 +870,12 @@ void JavaScriptFrame::Summarize(List<FrameSummary>* functions) { ...@@ -857,6 +870,12 @@ void JavaScriptFrame::Summarize(List<FrameSummary>* functions) {
functions->Add(summary); functions->Add(summary);
} }
JSFunction* JavaScriptFrame::function() const {
return JSFunction::cast(function_slot_object());
}
Object* JavaScriptFrame::receiver() const { return GetParameter(-1); }
int JavaScriptFrame::LookupExceptionHandlerInTable( int JavaScriptFrame::LookupExceptionHandlerInTable(
int* stack_depth, HandlerTable::CatchPrediction* prediction) { int* stack_depth, HandlerTable::CatchPrediction* prediction) {
Code* code = LookupCode(); Code* code = LookupCode();
...@@ -978,8 +997,7 @@ void FrameSummary::Print() { ...@@ -978,8 +997,7 @@ void FrameSummary::Print() {
PrintF("\npc: %d\n", code_offset_); PrintF("\npc: %d\n", code_offset_);
} }
void OptimizedFrame::Summarize(List<FrameSummary>* frames) const {
void OptimizedFrame::Summarize(List<FrameSummary>* frames) {
DCHECK(frames->length() == 0); DCHECK(frames->length() == 0);
DCHECK(is_optimized()); DCHECK(is_optimized());
...@@ -1234,7 +1252,7 @@ Object* InterpretedFrame::GetInterpreterRegister(int register_index) const { ...@@ -1234,7 +1252,7 @@ Object* InterpretedFrame::GetInterpreterRegister(int register_index) const {
return GetExpression(index + register_index); return GetExpression(index + register_index);
} }
void InterpretedFrame::Summarize(List<FrameSummary>* functions) { void InterpretedFrame::Summarize(List<FrameSummary>* functions) const {
DCHECK(functions->length() == 0); DCHECK(functions->length() == 0);
AbstractCode* abstract_code = AbstractCode* abstract_code =
AbstractCode::cast(function()->shared()->bytecode_array()); AbstractCode::cast(function()->shared()->bytecode_array());
...@@ -1291,6 +1309,15 @@ Code* WasmFrame::unchecked_code() const { ...@@ -1291,6 +1309,15 @@ Code* WasmFrame::unchecked_code() const {
return static_cast<Code*>(isolate()->FindCodeObject(pc())); return static_cast<Code*>(isolate()->FindCodeObject(pc()));
} }
JSFunction* WasmFrame::function() const {
// TODO(clemensh): generate the right JSFunctions once per wasm function and
// cache them
Factory* factory = isolate()->factory();
Handle<JSFunction> fun =
factory->NewFunction(factory->NewStringFromAsciiChecked("<WASM>"));
return *fun;
}
void WasmFrame::Iterate(ObjectVisitor* v) const { IterateCompiledFrame(v); } void WasmFrame::Iterate(ObjectVisitor* v) const { IterateCompiledFrame(v); }
Address WasmFrame::GetCallerStackPointer() const { Address WasmFrame::GetCallerStackPointer() const {
......
...@@ -640,8 +640,29 @@ class ExitFrame: public StackFrame { ...@@ -640,8 +640,29 @@ class ExitFrame: public StackFrame {
friend class StackFrameIteratorBase; friend class StackFrameIteratorBase;
}; };
class FrameSummary BASE_EMBEDDED {
public:
FrameSummary(Object* receiver, JSFunction* function,
AbstractCode* abstract_code, int code_offset,
bool is_constructor);
Handle<Object> receiver() { return receiver_; }
Handle<JSFunction> function() { return function_; }
Handle<AbstractCode> abstract_code() { return abstract_code_; }
int code_offset() { return code_offset_; }
bool is_constructor() { return is_constructor_; }
void Print();
private:
Handle<Object> receiver_;
Handle<JSFunction> function_;
Handle<AbstractCode> abstract_code_;
int code_offset_;
bool is_constructor_;
};
class StandardFrame: public StackFrame { class StandardFrame : public StackFrame {
public: public:
// Testers. // Testers.
bool is_standard() const override { return true; } bool is_standard() const override { return true; }
...@@ -661,6 +682,13 @@ class StandardFrame: public StackFrame { ...@@ -661,6 +682,13 @@ class StandardFrame: public StackFrame {
return static_cast<StandardFrame*>(frame); return static_cast<StandardFrame*>(frame);
} }
// Build a list with summaries for this frame including all inlined frames.
virtual void Summarize(List<FrameSummary>* frames) const;
// Accessors.
virtual JSFunction* function() const;
virtual Object* receiver() const;
protected: protected:
inline explicit StandardFrame(StackFrameIteratorBase* iterator); inline explicit StandardFrame(StackFrameIteratorBase* iterator);
...@@ -702,35 +730,13 @@ class StandardFrame: public StackFrame { ...@@ -702,35 +730,13 @@ class StandardFrame: public StackFrame {
}; };
class FrameSummary BASE_EMBEDDED {
public:
FrameSummary(Object* receiver, JSFunction* function,
AbstractCode* abstract_code, int code_offset,
bool is_constructor);
Handle<Object> receiver() { return receiver_; }
Handle<JSFunction> function() { return function_; }
Handle<AbstractCode> abstract_code() { return abstract_code_; }
int code_offset() { return code_offset_; }
bool is_constructor() { return is_constructor_; }
void Print();
private:
Handle<Object> receiver_;
Handle<JSFunction> function_;
Handle<AbstractCode> abstract_code_;
int code_offset_;
bool is_constructor_;
};
class JavaScriptFrame : public StandardFrame { class JavaScriptFrame : public StandardFrame {
public: public:
Type type() const override { return JAVA_SCRIPT; } Type type() const override { return JAVA_SCRIPT; }
// Accessors. JSFunction* function() const override;
inline JSFunction* function() const; Object* receiver() const override;
inline Object* receiver() const;
inline void set_receiver(Object* value); inline void set_receiver(Object* value);
// Access the parameters. // Access the parameters.
...@@ -777,8 +783,7 @@ class JavaScriptFrame : public StandardFrame { ...@@ -777,8 +783,7 @@ class JavaScriptFrame : public StandardFrame {
// Return a list with JSFunctions of this frame. // Return a list with JSFunctions of this frame.
virtual void GetFunctions(List<JSFunction*>* functions) const; virtual void GetFunctions(List<JSFunction*>* functions) const;
// Build a list with summaries for this frame including all inlined frames. void Summarize(List<FrameSummary>* frames) const override;
virtual void Summarize(List<FrameSummary>* frames);
// Lookup exception handler for current {pc}, returns -1 if none found. Also // Lookup exception handler for current {pc}, returns -1 if none found. Also
// returns data associated with the handler site specific to the frame type: // returns data associated with the handler site specific to the frame type:
...@@ -856,7 +861,7 @@ class OptimizedFrame : public JavaScriptFrame { ...@@ -856,7 +861,7 @@ class OptimizedFrame : public JavaScriptFrame {
// is the top-most activation) // is the top-most activation)
void GetFunctions(List<JSFunction*>* functions) const override; void GetFunctions(List<JSFunction*>* functions) const override;
void Summarize(List<FrameSummary>* frames) override; void Summarize(List<FrameSummary>* frames) const override;
// Lookup exception handler for current {pc}, returns -1 if none found. // Lookup exception handler for current {pc}, returns -1 if none found.
int LookupExceptionHandlerInTable( int LookupExceptionHandlerInTable(
...@@ -902,7 +907,7 @@ class InterpretedFrame : public JavaScriptFrame { ...@@ -902,7 +907,7 @@ class InterpretedFrame : public JavaScriptFrame {
Object* GetInterpreterRegister(int register_index) const; Object* GetInterpreterRegister(int register_index) const;
// Build a list with summaries for this frame including all inlined frames. // Build a list with summaries for this frame including all inlined frames.
void Summarize(List<FrameSummary>* frames) override; void Summarize(List<FrameSummary>* frames) const override;
protected: protected:
inline explicit InterpretedFrame(StackFrameIteratorBase* iterator); inline explicit InterpretedFrame(StackFrameIteratorBase* iterator);
...@@ -965,6 +970,8 @@ class WasmFrame : public StandardFrame { ...@@ -965,6 +970,8 @@ class WasmFrame : public StandardFrame {
return static_cast<WasmFrame*>(frame); return static_cast<WasmFrame*>(frame);
} }
JSFunction* function() const override;
protected: protected:
inline explicit WasmFrame(StackFrameIteratorBase* iterator); inline explicit WasmFrame(StackFrameIteratorBase* iterator);
...@@ -1142,17 +1149,25 @@ class JavaScriptFrameIterator BASE_EMBEDDED { ...@@ -1142,17 +1149,25 @@ class JavaScriptFrameIterator BASE_EMBEDDED {
StackFrameIterator iterator_; StackFrameIterator iterator_;
}; };
// NOTE: The stack trace frame iterator is an iterator that only // NOTE: The stack trace frame iterator is an iterator that only traverse proper
// traverse proper JavaScript frames; that is JavaScript frames that // JavaScript frames that have proper JavaScript functions and WASM frames.
// have proper JavaScript functions. This excludes the problematic // This excludes the problematic functions in runtime.js.
// functions in runtime.js. class StackTraceFrameIterator BASE_EMBEDDED {
class StackTraceFrameIterator: public JavaScriptFrameIterator {
public: public:
explicit StackTraceFrameIterator(Isolate* isolate); explicit StackTraceFrameIterator(Isolate* isolate);
bool done() const { return iterator_.done(); }
void Advance(); void Advance();
inline StandardFrame* frame() const;
inline bool is_javascript() const;
inline bool is_wasm() const;
inline JavaScriptFrame* javascript_frame() const;
inline WasmFrame* wasm_frame() const;
private: private:
bool IsValidFrame(); StackFrameIterator iterator_;
bool IsValidFrame(StackFrame* frame) const;
}; };
......
...@@ -687,7 +687,7 @@ Handle<JSArray> Isolate::CaptureCurrentStackTrace( ...@@ -687,7 +687,7 @@ Handle<JSArray> Isolate::CaptureCurrentStackTrace(
StackTraceFrameIterator it(this); StackTraceFrameIterator it(this);
int frames_seen = 0; int frames_seen = 0;
while (!it.done() && (frames_seen < limit)) { while (!it.done() && (frames_seen < limit)) {
JavaScriptFrame* frame = it.frame(); StandardFrame* frame = it.frame();
// 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);
...@@ -1318,7 +1318,7 @@ void Isolate::PrintCurrentStackTrace(FILE* out) { ...@@ -1318,7 +1318,7 @@ void Isolate::PrintCurrentStackTrace(FILE* out) {
while (!it.done()) { while (!it.done()) {
HandleScope scope(this); HandleScope scope(this);
// Find code position if recorded in relocation info. // Find code position if recorded in relocation info.
JavaScriptFrame* frame = it.frame(); StandardFrame* frame = it.frame();
Code* code = frame->LookupCode(); Code* code = frame->LookupCode();
int offset = static_cast<int>(frame->pc() - code->instruction_start()); int offset = static_cast<int>(frame->pc() - code->instruction_start());
int pos = frame->LookupCode()->SourcePosition(offset); int pos = frame->LookupCode()->SourcePosition(offset);
...@@ -1344,7 +1344,7 @@ void Isolate::PrintCurrentStackTrace(FILE* out) { ...@@ -1344,7 +1344,7 @@ void Isolate::PrintCurrentStackTrace(FILE* out) {
bool Isolate::ComputeLocation(MessageLocation* target) { bool Isolate::ComputeLocation(MessageLocation* target) {
StackTraceFrameIterator it(this); StackTraceFrameIterator it(this);
if (!it.done()) { if (!it.done()) {
JavaScriptFrame* frame = it.frame(); StandardFrame* frame = it.frame();
JSFunction* fun = frame->function(); JSFunction* fun = frame->function();
Object* script = fun->shared()->script(); Object* script = fun->shared()->script();
if (script->IsScript() && if (script->IsScript() &&
...@@ -1354,7 +1354,7 @@ bool Isolate::ComputeLocation(MessageLocation* target) { ...@@ -1354,7 +1354,7 @@ bool Isolate::ComputeLocation(MessageLocation* target) {
// 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);
it.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.abstract_code()->SourcePosition(summary.code_offset());
*target = MessageLocation(casted_script, pos, pos + 1, handle(fun)); *target = MessageLocation(casted_script, pos, pos + 1, handle(fun));
......
...@@ -233,7 +233,7 @@ void AllocationTracker::AllocationEvent(Address addr, int size) { ...@@ -233,7 +233,7 @@ void AllocationTracker::AllocationEvent(Address addr, int size) {
int length = 0; int length = 0;
StackTraceFrameIterator it(isolate); StackTraceFrameIterator it(isolate);
while (!it.done() && length < kMaxAllocationTraceLength) { while (!it.done() && length < kMaxAllocationTraceLength) {
JavaScriptFrame* frame = it.frame(); StandardFrame* frame = it.frame();
SharedFunctionInfo* shared = frame->function()->shared(); SharedFunctionInfo* shared = frame->function()->shared();
SnapshotObjectId id = ids_->FindOrAddEntry( SnapshotObjectId id = ids_->FindOrAddEntry(
shared->address(), shared->Size(), false); shared->address(), shared->Size(), false);
......
...@@ -143,7 +143,7 @@ SamplingHeapProfiler::AllocationNode* SamplingHeapProfiler::AddStack() { ...@@ -143,7 +143,7 @@ SamplingHeapProfiler::AllocationNode* SamplingHeapProfiler::AddStack() {
StackTraceFrameIterator it(isolate_); StackTraceFrameIterator it(isolate_);
int frames_captured = 0; int frames_captured = 0;
while (!it.done() && frames_captured < stack_depth_) { while (!it.done() && frames_captured < stack_depth_) {
JavaScriptFrame* frame = it.frame(); StandardFrame* frame = it.frame();
SharedFunctionInfo* shared = frame->function()->shared(); SharedFunctionInfo* shared = frame->function()->shared();
stack.push_back(shared); stack.push_back(shared);
......
...@@ -16,9 +16,9 @@ namespace { ...@@ -16,9 +16,9 @@ namespace {
void AssertInlineCount(const v8::FunctionCallbackInfo<v8::Value>& args) { void AssertInlineCount(const v8::FunctionCallbackInfo<v8::Value>& args) {
StackTraceFrameIterator it(CcTest::i_isolate()); StackTraceFrameIterator it(CcTest::i_isolate());
int frames_seen = 0; int frames_seen = 0;
JavaScriptFrame* topmost = it.frame(); JavaScriptFrame* topmost = it.javascript_frame();
while (!it.done()) { while (!it.done()) {
JavaScriptFrame* frame = it.frame(); JavaScriptFrame* frame = it.javascript_frame();
List<JSFunction*> functions(2); List<JSFunction*> functions(2);
frame->GetFunctions(&functions); frame->GetFunctions(&functions);
PrintF("%d %s, inline count: %d\n", frames_seen, PrintF("%d %s, inline count: %d\n", frames_seen,
......
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