[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}
This commit is contained in:
mythria 2016-10-13 07:47:44 -07:00 committed by Commit bot
parent d95b754319
commit 6fa76d461b
3 changed files with 49 additions and 10 deletions

View File

@ -991,16 +991,16 @@ int JavaScriptFrame::LookupExceptionHandlerInTable(
return code->LookupRangeInHandlerTable(pc_offset, stack_depth, prediction);
}
void JavaScriptFrame::PrintFunctionAndOffset(JSFunction* function, Code* code,
Address pc, FILE* file,
void JavaScriptFrame::PrintFunctionAndOffset(JSFunction* function,
AbstractCode* code,
int code_offset, FILE* file,
bool print_line_number) {
PrintF(file, "%s", function->IsOptimized() ? "*" : "~");
function->PrintName(file);
int code_offset = static_cast<int>(pc - code->instruction_start());
PrintF(file, "+%d", code_offset);
if (print_line_number) {
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();
if (maybe_script->IsScript()) {
Script* script = Script::cast(maybe_script);
@ -1030,8 +1030,17 @@ void JavaScriptFrame::PrintTop(Isolate* isolate, FILE* file, bool print_args,
if (it.frame()->is_java_script()) {
JavaScriptFrame* frame = it.frame();
if (frame->IsConstructor()) PrintF(file, "new ");
PrintFunctionAndOffset(frame->function(), frame->unchecked_code(),
frame->pc(), file, print_line_number);
JSFunction* function = frame->function();
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) {
// function arguments
// (we are intentionally only printing the actually
@ -1363,6 +1372,17 @@ int InterpretedFrame::GetBytecodeOffset() const {
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) {
const int index = InterpreterFrameConstants::kBytecodeOffsetExpressionIndex;
DCHECK_EQ(

View File

@ -872,8 +872,8 @@ class JavaScriptFrame : public StandardFrame {
return static_cast<JavaScriptFrame*>(frame);
}
static void PrintFunctionAndOffset(JSFunction* function, Code* code,
Address pc, FILE* file,
static void PrintFunctionAndOffset(JSFunction* function, AbstractCode* code,
int code_offset, FILE* file,
bool print_line_number);
static void PrintTop(Isolate* isolate, FILE* file, bool print_args,
@ -988,6 +988,8 @@ class InterpretedFrame : public JavaScriptFrame {
List<FrameSummary>* frames,
FrameSummary::Mode mode = FrameSummary::kExactSummary) const override;
static int GetBytecodeOffset(Address fp);
protected:
inline explicit InterpretedFrame(StackFrameIteratorBase* iterator);

View File

@ -111,8 +111,15 @@ void IC::TraceIC(const char* type, Handle<Object> name, State old_state,
Memory::Object_at(fp_ + JavaScriptFrameConstants::kFunctionOffset);
if (maybe_function->IsJSFunction()) {
JSFunction* function = JSFunction::cast(maybe_function);
JavaScriptFrame::PrintFunctionAndOffset(function, function->code(), pc(),
stdout, true);
int code_offset = 0;
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 = "";
@ -171,6 +178,16 @@ IC::IC(FrameDepth depth, Isolate* isolate, FeedbackNexus* nexus)
StackFrame* frame = it.frame();
DCHECK(fp == frame->fp() && pc_address == frame->pc_address());
#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;
if (FLAG_enable_embedded_constant_pool) {
constant_pool_address_ = constant_pool;