Commit 6fa76d46 authored by mythria's avatar mythria Committed by Commit bot

[Interpreter] Print information about interpreted functions when tracing ics.

With --trace-ic flag, the function names and the source positions are
not shown for interpreted functions. Interpreted functions have an extra
frame built by bytecode handlers which has to be skipped to get the
interpreted function's frame. Also the code offsets are computed differently
for interpreted functions.

BUG=v8:4280

Review-Url: https://codereview.chromium.org/2405173007
Cr-Commit-Position: refs/heads/master@{#40274}
parent d95b7543
...@@ -991,16 +991,16 @@ int JavaScriptFrame::LookupExceptionHandlerInTable( ...@@ -991,16 +991,16 @@ int JavaScriptFrame::LookupExceptionHandlerInTable(
return code->LookupRangeInHandlerTable(pc_offset, stack_depth, prediction); return code->LookupRangeInHandlerTable(pc_offset, stack_depth, prediction);
} }
void JavaScriptFrame::PrintFunctionAndOffset(JSFunction* function, Code* code, void JavaScriptFrame::PrintFunctionAndOffset(JSFunction* function,
Address pc, FILE* file, AbstractCode* code,
int code_offset, FILE* file,
bool print_line_number) { bool print_line_number) {
PrintF(file, "%s", function->IsOptimized() ? "*" : "~"); PrintF(file, "%s", function->IsOptimized() ? "*" : "~");
function->PrintName(file); function->PrintName(file);
int code_offset = static_cast<int>(pc - code->instruction_start());
PrintF(file, "+%d", code_offset); PrintF(file, "+%d", code_offset);
if (print_line_number) { if (print_line_number) {
SharedFunctionInfo* shared = function->shared(); SharedFunctionInfo* shared = function->shared();
int source_pos = AbstractCode::cast(code)->SourcePosition(code_offset); int source_pos = code->SourcePosition(code_offset);
Object* maybe_script = shared->script(); Object* maybe_script = shared->script();
if (maybe_script->IsScript()) { if (maybe_script->IsScript()) {
Script* script = Script::cast(maybe_script); Script* script = Script::cast(maybe_script);
...@@ -1030,8 +1030,17 @@ void JavaScriptFrame::PrintTop(Isolate* isolate, FILE* file, bool print_args, ...@@ -1030,8 +1030,17 @@ void JavaScriptFrame::PrintTop(Isolate* isolate, FILE* file, bool print_args,
if (it.frame()->is_java_script()) { if (it.frame()->is_java_script()) {
JavaScriptFrame* frame = it.frame(); JavaScriptFrame* frame = it.frame();
if (frame->IsConstructor()) PrintF(file, "new "); if (frame->IsConstructor()) PrintF(file, "new ");
PrintFunctionAndOffset(frame->function(), frame->unchecked_code(), JSFunction* function = frame->function();
frame->pc(), file, print_line_number); int code_offset = 0;
if (frame->is_interpreted()) {
InterpretedFrame* iframe = reinterpret_cast<InterpretedFrame*>(frame);
code_offset = iframe->GetBytecodeOffset();
} else {
Code* code = frame->unchecked_code();
code_offset = static_cast<int>(frame->pc() - code->instruction_start());
}
PrintFunctionAndOffset(function, function->abstract_code(), code_offset,
file, print_line_number);
if (print_args) { if (print_args) {
// function arguments // function arguments
// (we are intentionally only printing the actually // (we are intentionally only printing the actually
...@@ -1363,6 +1372,17 @@ int InterpretedFrame::GetBytecodeOffset() const { ...@@ -1363,6 +1372,17 @@ int InterpretedFrame::GetBytecodeOffset() const {
return raw_offset - BytecodeArray::kHeaderSize + kHeapObjectTag; return raw_offset - BytecodeArray::kHeaderSize + kHeapObjectTag;
} }
int InterpretedFrame::GetBytecodeOffset(Address fp) {
const int offset = InterpreterFrameConstants::kExpressionsOffset;
const int index = InterpreterFrameConstants::kBytecodeOffsetExpressionIndex;
DCHECK_EQ(
InterpreterFrameConstants::kBytecodeOffsetFromFp,
InterpreterFrameConstants::kExpressionsOffset - index * kPointerSize);
Address expression_offset = fp + offset - index * kPointerSize;
int raw_offset = Smi::cast(Memory::Object_at(expression_offset))->value();
return raw_offset - BytecodeArray::kHeaderSize + kHeapObjectTag;
}
void InterpretedFrame::PatchBytecodeOffset(int new_offset) { void InterpretedFrame::PatchBytecodeOffset(int new_offset) {
const int index = InterpreterFrameConstants::kBytecodeOffsetExpressionIndex; const int index = InterpreterFrameConstants::kBytecodeOffsetExpressionIndex;
DCHECK_EQ( DCHECK_EQ(
......
...@@ -872,8 +872,8 @@ class JavaScriptFrame : public StandardFrame { ...@@ -872,8 +872,8 @@ class JavaScriptFrame : public StandardFrame {
return static_cast<JavaScriptFrame*>(frame); return static_cast<JavaScriptFrame*>(frame);
} }
static void PrintFunctionAndOffset(JSFunction* function, Code* code, static void PrintFunctionAndOffset(JSFunction* function, AbstractCode* code,
Address pc, FILE* file, int code_offset, FILE* file,
bool print_line_number); bool print_line_number);
static void PrintTop(Isolate* isolate, FILE* file, bool print_args, static void PrintTop(Isolate* isolate, FILE* file, bool print_args,
...@@ -988,6 +988,8 @@ class InterpretedFrame : public JavaScriptFrame { ...@@ -988,6 +988,8 @@ class InterpretedFrame : public JavaScriptFrame {
List<FrameSummary>* frames, List<FrameSummary>* frames,
FrameSummary::Mode mode = FrameSummary::kExactSummary) const override; FrameSummary::Mode mode = FrameSummary::kExactSummary) const override;
static int GetBytecodeOffset(Address fp);
protected: protected:
inline explicit InterpretedFrame(StackFrameIteratorBase* iterator); inline explicit InterpretedFrame(StackFrameIteratorBase* iterator);
......
...@@ -111,8 +111,15 @@ void IC::TraceIC(const char* type, Handle<Object> name, State old_state, ...@@ -111,8 +111,15 @@ void IC::TraceIC(const char* type, Handle<Object> name, State old_state,
Memory::Object_at(fp_ + JavaScriptFrameConstants::kFunctionOffset); Memory::Object_at(fp_ + JavaScriptFrameConstants::kFunctionOffset);
if (maybe_function->IsJSFunction()) { if (maybe_function->IsJSFunction()) {
JSFunction* function = JSFunction::cast(maybe_function); JSFunction* function = JSFunction::cast(maybe_function);
JavaScriptFrame::PrintFunctionAndOffset(function, function->code(), pc(), int code_offset = 0;
stdout, true); if (function->code()->is_interpreter_trampoline_builtin()) {
code_offset = InterpretedFrame::GetBytecodeOffset(fp());
} else {
code_offset =
static_cast<int>(pc() - function->code()->instruction_start());
}
JavaScriptFrame::PrintFunctionAndOffset(
function, function->abstract_code(), code_offset, stdout, true);
} }
const char* modifier = ""; const char* modifier = "";
...@@ -171,6 +178,16 @@ IC::IC(FrameDepth depth, Isolate* isolate, FeedbackNexus* nexus) ...@@ -171,6 +178,16 @@ IC::IC(FrameDepth depth, Isolate* isolate, FeedbackNexus* nexus)
StackFrame* frame = it.frame(); StackFrame* frame = it.frame();
DCHECK(fp == frame->fp() && pc_address == frame->pc_address()); DCHECK(fp == frame->fp() && pc_address == frame->pc_address());
#endif #endif
// For interpreted functions, some bytecode handlers construct a
// frame. We have to skip the constructed frame to find the interpreted
// function's frame. Check if the there is an additional frame, and if there
// is skip this frame. However, the pc should not be updated. The call to
// ICs happen from bytecode handlers.
Object* frame_type =
Memory::Object_at(fp + TypedFrameConstants::kFrameTypeOffset);
if (frame_type == Smi::FromInt(StackFrame::STUB)) {
fp = Memory::Address_at(fp + TypedFrameConstants::kCallerFPOffset);
}
fp_ = fp; fp_ = fp;
if (FLAG_enable_embedded_constant_pool) { if (FLAG_enable_embedded_constant_pool) {
constant_pool_address_ = constant_pool; constant_pool_address_ = constant_pool;
......
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