[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:
parent
d95b754319
commit
6fa76d461b
@ -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(
|
||||
|
@ -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);
|
||||
|
||||
|
21
src/ic/ic.cc
21
src/ic/ic.cc
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user