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

[profiler] Fix attribution for the top-most interpreted frame.

Before this change, we attributed samples for the top-most interpreter frame to the second-topmost frame if we were in a bytecode handler with elided frame. With this change we try to detect that we are in a handler without a frame. If we are, we do not drop the topmost frame.

For example, consider the program

function inner() {
  var s = 0;
  for (var i = 0; i < 100000; i++) {
    s += i * i;
  }
  return s;
}

function trivial() {
  return inner();
}

for (var i = 0; i < 2000; i++) {
  trivial();
}

Before this change, d8 --prof --ignition --nocrankshaft and linux-tick-processor would produce:

  [JavaScript]:
   ticks  total  nonlib   name
   4885   83.4%   83.5%  Function: ~trivial a.js:15:17
    759   13.0%   13.0%  Function: ~inner a.js:7:15

After this change, we get

 [JavaScript]:
   ticks  total  nonlib   name
   5486   95.9%   96.2%  Function: ~inner a.js:7:15
      4    0.1%    0.1%  Function: ~trivial a.js:15:17

Review-Url: https://codereview.chromium.org/2667253004
Cr-Original-Commit-Position: refs/heads/master@{#42894}
Committed: https://chromium.googlesource.com/v8/v8/+/d07f6540c1f9628ed2ba1fa6507c90db07ccc5f5
Review-Url: https://codereview.chromium.org/2667253004
Cr-Commit-Position: refs/heads/master@{#42924}
parent bff24112
...@@ -182,6 +182,29 @@ void StackTraceFrameIterator::AdvanceToArgumentsFrame() { ...@@ -182,6 +182,29 @@ void StackTraceFrameIterator::AdvanceToArgumentsFrame() {
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
namespace {
bool IsInterpreterFramePc(Isolate* isolate, Address pc) {
Code* interpreter_entry_trampoline =
isolate->builtins()->builtin(Builtins::kInterpreterEntryTrampoline);
Code* interpreter_bytecode_advance =
isolate->builtins()->builtin(Builtins::kInterpreterEnterBytecodeAdvance);
Code* interpreter_bytecode_dispatch =
isolate->builtins()->builtin(Builtins::kInterpreterEnterBytecodeDispatch);
return (pc >= interpreter_entry_trampoline->instruction_start() &&
pc < interpreter_entry_trampoline->instruction_end()) ||
(pc >= interpreter_bytecode_advance->instruction_start() &&
pc < interpreter_bytecode_advance->instruction_end()) ||
(pc >= interpreter_bytecode_dispatch->instruction_start() &&
pc < interpreter_bytecode_dispatch->instruction_end());
}
DISABLE_ASAN Address ReadMemoryAt(Address address) {
return Memory::Address_at(address);
}
} // namespace
SafeStackFrameIterator::SafeStackFrameIterator( SafeStackFrameIterator::SafeStackFrameIterator(
Isolate* isolate, Isolate* isolate,
...@@ -194,6 +217,7 @@ SafeStackFrameIterator::SafeStackFrameIterator( ...@@ -194,6 +217,7 @@ SafeStackFrameIterator::SafeStackFrameIterator(
StackFrame::State state; StackFrame::State state;
StackFrame::Type type; StackFrame::Type type;
ThreadLocalTop* top = isolate->thread_local_top(); ThreadLocalTop* top = isolate->thread_local_top();
bool advance_frame = true;
if (IsValidTop(top)) { if (IsValidTop(top)) {
type = ExitFrame::GetStateForFramePointer(Isolate::c_entry_fp(top), &state); type = ExitFrame::GetStateForFramePointer(Isolate::c_entry_fp(top), &state);
top_frame_type_ = type; top_frame_type_ = type;
...@@ -203,6 +227,19 @@ SafeStackFrameIterator::SafeStackFrameIterator( ...@@ -203,6 +227,19 @@ SafeStackFrameIterator::SafeStackFrameIterator(
state.sp = sp; state.sp = sp;
state.pc_address = StackFrame::ResolveReturnAddressLocation( state.pc_address = StackFrame::ResolveReturnAddressLocation(
reinterpret_cast<Address*>(StandardFrame::ComputePCAddress(fp))); reinterpret_cast<Address*>(StandardFrame::ComputePCAddress(fp)));
// If the top of stack is a return address to the interpreter trampoline,
// then we are likely in a bytecode handler with elided frame. In that
// case, set the PC properly and make sure we do not drop the frame.
if (IsValidStackAddress(sp)) {
MSAN_MEMORY_IS_INITIALIZED(sp, kPointerSize);
Address tos = ReadMemoryAt(reinterpret_cast<Address>(sp));
if (IsInterpreterFramePc(isolate, tos)) {
state.pc_address = reinterpret_cast<Address*>(sp);
advance_frame = false;
}
}
// StackFrame::ComputeType will read both kContextOffset and kMarkerOffset, // StackFrame::ComputeType will read both kContextOffset and kMarkerOffset,
// we check only that kMarkerOffset is within the stack bounds and do // we check only that kMarkerOffset is within the stack bounds and do
// compile time check that kContextOffset slot is pushed on the stack before // compile time check that kContextOffset slot is pushed on the stack before
...@@ -213,6 +250,10 @@ SafeStackFrameIterator::SafeStackFrameIterator( ...@@ -213,6 +250,10 @@ SafeStackFrameIterator::SafeStackFrameIterator(
if (IsValidStackAddress(frame_marker)) { if (IsValidStackAddress(frame_marker)) {
type = StackFrame::ComputeType(this, &state); type = StackFrame::ComputeType(this, &state);
top_frame_type_ = type; top_frame_type_ = type;
// We only keep the top frame if we believe it to be interpreted frame.
if (type != StackFrame::INTERPRETED) {
advance_frame = true;
}
} else { } else {
// Mark the frame as JAVA_SCRIPT if we cannot determine its type. // Mark the frame as JAVA_SCRIPT if we cannot determine its type.
// The frame anyways will be skipped. // The frame anyways will be skipped.
...@@ -224,7 +265,7 @@ SafeStackFrameIterator::SafeStackFrameIterator( ...@@ -224,7 +265,7 @@ SafeStackFrameIterator::SafeStackFrameIterator(
return; return;
} }
frame_ = SingletonFor(type, &state); frame_ = SingletonFor(type, &state);
if (frame_) Advance(); if (advance_frame && frame_) Advance();
} }
...@@ -389,22 +430,6 @@ void StackFrame::SetReturnAddressLocationResolver( ...@@ -389,22 +430,6 @@ void StackFrame::SetReturnAddressLocationResolver(
return_address_location_resolver_ = resolver; return_address_location_resolver_ = resolver;
} }
static bool IsInterpreterFramePc(Isolate* isolate, Address pc) {
Code* interpreter_entry_trampoline =
isolate->builtins()->builtin(Builtins::kInterpreterEntryTrampoline);
Code* interpreter_bytecode_advance =
isolate->builtins()->builtin(Builtins::kInterpreterEnterBytecodeAdvance);
Code* interpreter_bytecode_dispatch =
isolate->builtins()->builtin(Builtins::kInterpreterEnterBytecodeDispatch);
return (pc >= interpreter_entry_trampoline->instruction_start() &&
pc < interpreter_entry_trampoline->instruction_end()) ||
(pc >= interpreter_bytecode_advance->instruction_start() &&
pc < interpreter_bytecode_advance->instruction_end()) ||
(pc >= interpreter_bytecode_dispatch->instruction_start() &&
pc < interpreter_bytecode_dispatch->instruction_end());
}
StackFrame::Type StackFrame::ComputeType(const StackFrameIteratorBase* iterator, StackFrame::Type StackFrame::ComputeType(const StackFrameIteratorBase* iterator,
State* state) { State* state) {
DCHECK(state->fp != NULL); DCHECK(state->fp != NULL);
......
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