Commit fcbe95c8 authored by jarin's avatar jarin Committed by Commit bot

Introduce approximate mode for StandardFrame::Summarize.

The approximate mode enables taking an approximate stack trace from GC,
where the top frames might be missing if inlined. Note that in that case,
the frame summary will refer to optimized code, so it will not be possible
to take source position. (The user of the summary will have to handle the
case frame_summary.abstract_code()->kind() == AbstractCode::OPTIMIZED_CODE
specially.)

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

Cr-Commit-Position: refs/heads/master@{#35728}
parent 530cf26b
......@@ -3383,6 +3383,7 @@ TranslatedState::TranslatedState(JavaScriptFrame* frame)
int deopt_index = Safepoint::kNoDeoptimizationIndex;
DeoptimizationInputData* data =
static_cast<OptimizedFrame*>(frame)->GetDeoptimizationData(&deopt_index);
DCHECK(data != nullptr && deopt_index != Safepoint::kNoDeoptimizationIndex);
TranslationIterator it(data->TranslationByteArray(),
data->TranslationIndex(deopt_index)->value());
Init(frame->fp(), &it, data->LiteralArray(), nullptr /* registers */,
......
......@@ -617,7 +617,8 @@ void ExitFrame::FillState(Address fp, Address sp, State* state) {
state->constant_pool_address = NULL;
}
void StandardFrame::Summarize(List<FrameSummary>* functions) const {
void StandardFrame::Summarize(List<FrameSummary>* functions,
FrameSummary::Mode mode) const {
DCHECK(functions->length() == 0);
// default implementation: no summary added
}
......@@ -860,13 +861,14 @@ void JavaScriptFrame::GetFunctions(List<JSFunction*>* functions) const {
functions->Add(function());
}
void JavaScriptFrame::Summarize(List<FrameSummary>* functions) const {
void JavaScriptFrame::Summarize(List<FrameSummary>* functions,
FrameSummary::Mode mode) const {
DCHECK(functions->length() == 0);
Code* code = LookupCode();
int offset = static_cast<int>(pc() - code->instruction_start());
AbstractCode* abstract_code = AbstractCode::cast(code);
FrameSummary summary(receiver(), function(), abstract_code, offset,
IsConstructor());
IsConstructor(), mode);
functions->Add(summary);
}
......@@ -966,7 +968,7 @@ bool CannotDeoptFromAsmCode(Code* code, JSFunction* function) {
FrameSummary::FrameSummary(Object* receiver, JSFunction* function,
AbstractCode* abstract_code, int code_offset,
bool is_constructor)
bool is_constructor, Mode mode)
: receiver_(receiver, function->GetIsolate()),
function_(function),
abstract_code_(abstract_code),
......@@ -974,7 +976,8 @@ FrameSummary::FrameSummary(Object* receiver, JSFunction* function,
is_constructor_(is_constructor) {
DCHECK(abstract_code->IsBytecodeArray() ||
Code::cast(abstract_code)->kind() != Code::OPTIMIZED_FUNCTION ||
CannotDeoptFromAsmCode(Code::cast(abstract_code), function));
CannotDeoptFromAsmCode(Code::cast(abstract_code), function) ||
mode == kApproximateSummary);
}
FrameSummary FrameSummary::GetFirst(JavaScriptFrame* frame) {
......@@ -994,8 +997,12 @@ void FrameSummary::Print() {
Code* code = abstract_code_->GetCode();
if (code->kind() == Code::FUNCTION) PrintF(" UNOPT ");
if (code->kind() == Code::OPTIMIZED_FUNCTION) {
DCHECK(CannotDeoptFromAsmCode(code, *function()));
PrintF(" ASM ");
if (function()->shared()->asm_function()) {
DCHECK(CannotDeoptFromAsmCode(code, *function()));
PrintF(" ASM ");
} else {
PrintF(" OPT (approximate)");
}
}
} else {
PrintF(" BYTECODE ");
......@@ -1003,7 +1010,8 @@ void FrameSummary::Print() {
PrintF("\npc: %d\n", code_offset_);
}
void OptimizedFrame::Summarize(List<FrameSummary>* frames) const {
void OptimizedFrame::Summarize(List<FrameSummary>* frames,
FrameSummary::Mode mode) const {
DCHECK(frames->length() == 0);
DCHECK(is_optimized());
......@@ -1018,6 +1026,13 @@ void OptimizedFrame::Summarize(List<FrameSummary>* frames) const {
DisallowHeapAllocation no_gc;
int deopt_index = Safepoint::kNoDeoptimizationIndex;
DeoptimizationInputData* const data = GetDeoptimizationData(&deopt_index);
if (deopt_index == Safepoint::kNoDeoptimizationIndex) {
DCHECK(data == nullptr);
if (mode == FrameSummary::kApproximateSummary) {
return JavaScriptFrame::Summarize(frames, mode);
}
FATAL("Missing deoptimization information for OptimizedFrame::Summarize.");
}
FixedArray* const literal_array = data->LiteralArray();
TranslationIterator it(data->TranslationByteArray(),
......@@ -1140,9 +1155,10 @@ DeoptimizationInputData* OptimizedFrame::GetDeoptimizationData(
SafepointEntry safepoint_entry = code->GetSafepointEntry(pc());
*deopt_index = safepoint_entry.deoptimization_index();
DCHECK(*deopt_index != Safepoint::kNoDeoptimizationIndex);
return DeoptimizationInputData::cast(code->deoptimization_data());
if (*deopt_index != Safepoint::kNoDeoptimizationIndex) {
return DeoptimizationInputData::cast(code->deoptimization_data());
}
return nullptr;
}
......@@ -1161,6 +1177,7 @@ void OptimizedFrame::GetFunctions(List<JSFunction*>* functions) const {
DisallowHeapAllocation no_gc;
int deopt_index = Safepoint::kNoDeoptimizationIndex;
DeoptimizationInputData* const data = GetDeoptimizationData(&deopt_index);
DCHECK(data != nullptr && deopt_index != Safepoint::kNoDeoptimizationIndex);
FixedArray* const literal_array = data->LiteralArray();
TranslationIterator it(data->TranslationByteArray(),
......@@ -1267,7 +1284,8 @@ void InterpretedFrame::WriteInterpreterRegister(int register_index,
return SetExpression(index + register_index, value);
}
void InterpretedFrame::Summarize(List<FrameSummary>* functions) const {
void InterpretedFrame::Summarize(List<FrameSummary>* functions,
FrameSummary::Mode mode) const {
DCHECK(functions->length() == 0);
AbstractCode* abstract_code =
AbstractCode::cast(function()->shared()->bytecode_array());
......@@ -1333,7 +1351,8 @@ JSFunction* WasmFrame::function() const {
return *fun;
}
void WasmFrame::Summarize(List<FrameSummary>* functions) const {
void WasmFrame::Summarize(List<FrameSummary>* functions,
FrameSummary::Mode mode) const {
DCHECK(functions->length() == 0);
Code* code = LookupCode();
int offset = static_cast<int>(pc() - code->instruction_start());
......
......@@ -635,9 +635,16 @@ class JavaScriptFrame;
class FrameSummary BASE_EMBEDDED {
public:
// Mode for StandardFrame::Summarize. Exact summary is required to produce an
// exact stack trace. It will trigger an assertion failure if that is not
// possible, e.g., because of missing deoptimization information. The
// approximate mode should produce a summary even without deoptimization
// information, but it might miss frames.
enum Mode { kExactSummary, kApproximateSummary };
FrameSummary(Object* receiver, JSFunction* function,
AbstractCode* abstract_code, int code_offset,
bool is_constructor);
bool is_constructor, Mode mode = kExactSummary);
static FrameSummary GetFirst(JavaScriptFrame* frame);
......@@ -678,7 +685,9 @@ class StandardFrame : public StackFrame {
}
// Build a list with summaries for this frame including all inlined frames.
virtual void Summarize(List<FrameSummary>* frames) const;
virtual void Summarize(
List<FrameSummary>* frames,
FrameSummary::Mode mode = FrameSummary::kExactSummary) const;
// Accessors.
virtual JSFunction* function() const;
......@@ -777,7 +786,9 @@ class JavaScriptFrame : public StandardFrame {
// Return a list with JSFunctions of this frame.
virtual void GetFunctions(List<JSFunction*>* functions) const;
void Summarize(List<FrameSummary>* frames) const override;
void Summarize(
List<FrameSummary>* frames,
FrameSummary::Mode mode = FrameSummary::kExactSummary) const override;
// Lookup exception handler for current {pc}, returns -1 if none found. Also
// returns data associated with the handler site specific to the frame type:
......@@ -855,7 +866,9 @@ class OptimizedFrame : public JavaScriptFrame {
// is the top-most activation)
void GetFunctions(List<JSFunction*>* functions) const override;
void Summarize(List<FrameSummary>* frames) const override;
void Summarize(
List<FrameSummary>* frames,
FrameSummary::Mode mode = FrameSummary::kExactSummary) const override;
// Lookup exception handler for current {pc}, returns -1 if none found.
int LookupExceptionHandlerInTable(
......@@ -902,7 +915,9 @@ class InterpretedFrame : public JavaScriptFrame {
void WriteInterpreterRegister(int register_index, Object* value);
// Build a list with summaries for this frame including all inlined frames.
void Summarize(List<FrameSummary>* frames) const override;
void Summarize(
List<FrameSummary>* frames,
FrameSummary::Mode mode = FrameSummary::kExactSummary) const override;
protected:
inline explicit InterpretedFrame(StackFrameIteratorBase* iterator);
......@@ -967,7 +982,9 @@ class WasmFrame : public StandardFrame {
JSFunction* function() const override;
void Summarize(List<FrameSummary>* frames) const override;
void Summarize(
List<FrameSummary>* frames,
FrameSummary::Mode mode = FrameSummary::kExactSummary) const override;
protected:
inline explicit WasmFrame(StackFrameIteratorBase* iterator);
......
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