Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(686)

Unified Diff: runtime/vm/profiler.cc

Issue 1150633002: Track prologue offset of Code and use for more precise return addresses (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Created 5 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « runtime/vm/object.cc ('k') | runtime/vm/raw_object.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: runtime/vm/profiler.cc
diff --git a/runtime/vm/profiler.cc b/runtime/vm/profiler.cc
index c4e27e3e37494afc06ee2469ca584b8f248a1e5f..620d8c0f1718da98ae9c0972f49adfbc62c86989 100644
--- a/runtime/vm/profiler.cc
+++ b/runtime/vm/profiler.cc
@@ -25,8 +25,11 @@
namespace dart {
+DECLARE_FLAG(bool, trace_profiler);
+
DEFINE_FLAG(bool, profile, true, "Enable Sampling Profiler");
DEFINE_FLAG(bool, trace_profiled_isolates, false, "Trace profiled isolates.");
+
#if defined(TARGET_OS_ANDROID) || defined(TARGET_ARCH_ARM64) || \
defined(TARGET_ARCH_ARM) || defined(TARGET_ARCH_MIPS)
DEFINE_FLAG(int, profile_period, 10000,
@@ -41,7 +44,7 @@ DEFINE_FLAG(int, profile_depth, 8,
DEFINE_FLAG(bool, profile_vm, true,
"Always collect native stack traces.");
#else
-DEFINE_FLAG(bool, profile_vm, true,
+DEFINE_FLAG(bool, profile_vm, false,
"Always collect native stack traces.");
#endif
@@ -240,6 +243,12 @@ SampleBuffer::SampleBuffer(intptr_t capacity) {
ASSERT(Sample::instance_size() > 0);
samples_ = reinterpret_cast<Sample*>(
calloc(capacity, Sample::instance_size()));
+ if (FLAG_trace_profiler) {
+ OS::Print("Profiler holds %" Pd " samples\n", capacity);
+ OS::Print("Profiler sample is %" Pd " bytes\n", Sample::instance_size());
+ OS::Print("Profiler memory usage = %" Pd " bytes\n",
+ capacity * Sample::instance_size());
+ }
capacity_ = capacity;
cursor_ = 0;
}
@@ -262,7 +271,6 @@ Sample* SampleBuffer::ReserveSample() {
return At(cursor);
}
-
// Attempts to find the true return address when a Dart frame is being setup
// or torn down.
// NOTE: Architecture specific implementations below.
@@ -270,16 +278,11 @@ class ReturnAddressLocator : public ValueObject {
public:
ReturnAddressLocator(Sample* sample, const Code& code)
: sample_(sample),
- code_(Code::ZoneHandle(code.raw())),
- is_optimized_(code.is_optimized()) {
+ code_(Code::ZoneHandle(code.raw())) {
ASSERT(!code_.IsNull());
ASSERT(code_.ContainsInstructionAt(pc()));
}
- bool is_code_optimized() {
- return is_optimized_;
- }
-
uword pc() {
return sample_->pc();
}
@@ -288,12 +291,13 @@ class ReturnAddressLocator : public ValueObject {
bool LocateReturnAddress(uword* return_address);
// Returns offset into code object.
- uword RelativePC() {
- return pc() - code_.EntryPoint();
+ intptr_t RelativePC() {
+ ASSERT(pc() >= code_.EntryPoint());
+ return static_cast<intptr_t>(pc() - code_.EntryPoint());
}
- uint8_t* CodePointer(uword offset) {
- const uword size = code_.Size();
+ uint8_t* CodePointer(intptr_t offset) {
+ const intptr_t size = code_.Size();
ASSERT(offset < size);
uint8_t* code_pointer = reinterpret_cast<uint8_t*>(code_.EntryPoint());
code_pointer += offset;
@@ -309,152 +313,56 @@ class ReturnAddressLocator : public ValueObject {
private:
Sample* sample_;
const Code& code_;
- const bool is_optimized_;
};
-#if defined(TARGET_ARCH_IA32)
+#if defined(TARGET_ARCH_IA32) || defined(TARGET_ARCH_X64)
bool ReturnAddressLocator::LocateReturnAddress(uword* return_address) {
ASSERT(return_address != NULL);
- const uword offset = RelativePC();
- const uword size = code_.Size();
- if (is_optimized_) {
- // 0: push ebp
- // 1: mov ebp, esp
- // 3: ...
- if (offset == 0x0) {
- // Stack layout:
- // 0 RETURN ADDRESS.
- *return_address = StackAt(0);
- return true;
- }
- if (offset == 0x1) {
- // Stack layout:
- // 0 CALLER FRAME POINTER
- // 1 RETURN ADDRESS
- *return_address = StackAt(1);
- return true;
- }
- ReturnPattern rp(pc());
- if (rp.IsValid()) {
- // Stack layout:
- // 0 RETURN ADDRESS.
- *return_address = StackAt(0);
- return true;
- }
- return false;
- } else {
- // 0x00: mov edi, function
- // 0x05: incl (inc usage count) <-- this is optional.
- // 0x08: cmpl (compare usage count)
- // 0x0f: jump to optimize function
- // 0x15: push ebp
- // 0x16: mov ebp, esp
- // 0x18: ...
- ASSERT(size >= 0x08);
- const uword incl_offset = 0x05;
- const uword incl_length = 0x03;
- const uint8_t incl_op_code = 0xFF;
- const bool has_incl = (*CodePointer(incl_offset) == incl_op_code);
- const uword push_fp_offset = has_incl ? 0x15 : 0x15 - incl_length;
- if (offset <= push_fp_offset) {
- // Stack layout:
- // 0 RETURN ADDRESS.
- *return_address = StackAt(0);
- return true;
- }
- if (offset == (push_fp_offset + 1)) {
- // Stack layout:
- // 0 CALLER FRAME POINTER
- // 1 RETURN ADDRESS
- *return_address = StackAt(1);
- return true;
- }
- ReturnPattern rp(pc());
- if (rp.IsValid()) {
- // Stack layout:
- // 0 RETURN ADDRESS.
- *return_address = StackAt(0);
- return true;
- }
- return false;
+ const intptr_t offset = RelativePC();
+ ASSERT(offset >= 0);
+ const intptr_t size = code_.Size();
+ ASSERT(offset < size);
+ const intptr_t prologue_offset = code_.GetPrologueOffset();
+ if (offset < prologue_offset) {
+ // Before the prologue, return address is at the top of the stack.
+ // TODO(johnmccutchan): Some intrinsics and stubs do not conform to the
+ // expected stack layout. Use a more robust solution for those code objects.
+ *return_address = StackAt(0);
+ return true;
}
- UNREACHABLE();
- return false;
-}
-#elif defined(TARGET_ARCH_X64)
-bool ReturnAddressLocator::LocateReturnAddress(uword* return_address) {
- ASSERT(return_address != NULL);
- const uword offset = RelativePC();
- const uword size = code_.Size();
- if (is_optimized_) {
- // 0x00: leaq (load pc marker)
- // 0x07: movq (load pool pointer)
- // 0x0c: push rpb
- // 0x0d: movq rbp, rsp
- // 0x10: ...
- const uword push_fp_offset = 0x0c;
- if (offset <= push_fp_offset) {
- // Stack layout:
- // 0 RETURN ADDRESS.
- *return_address = StackAt(0);
- return true;
- }
- if (offset == (push_fp_offset + 1)) {
- // Stack layout:
- // 0 CALLER FRAME POINTER
- // 1 RETURN ADDRESS
- *return_address = StackAt(1);
- return true;
- }
- ReturnPattern rp(pc());
- if (rp.IsValid()) {
- // Stack layout:
- // 0 RETURN ADDRESS.
- *return_address = StackAt(0);
- return true;
- }
- return false;
- } else {
- // 0x00: leaq (load pc marker)
- // 0x07: movq (load pool pointer)
- // 0x0c: movq (load function)
- // 0x13: incl (inc usage count) <-- this is optional.
- // 0x16: cmpl (compare usage count)
- // 0x1d: jl + 0x
- // 0x23: jmp [pool pointer]
- // 0x27: push rbp
- // 0x28: movq rbp, rsp
- // 0x2b: ...
- ASSERT(size >= 0x16);
- const uword incl_offset = 0x13;
- const uword incl_length = 0x03;
- const uint8_t incl_op_code = 0xFF;
- const bool has_incl = (*CodePointer(incl_offset) == incl_op_code);
- const uword push_fp_offset = has_incl ? 0x27 : 0x27 - incl_length;
- if (offset <= push_fp_offset) {
- // Stack layout:
- // 0 RETURN ADDRESS.
- *return_address = StackAt(0);
- return true;
- }
- if (offset == (push_fp_offset + 1)) {
- // Stack layout:
- // 0 CALLER FRAME POINTER
- // 1 RETURN ADDRESS
- *return_address = StackAt(1);
- return true;
- }
- ReturnPattern rp(pc());
- if (rp.IsValid()) {
- // Stack layout:
- // 0 RETURN ADDRESS.
- *return_address = StackAt(0);
- return true;
- }
- return false;
+ // Detect if we are:
+ // push ebp <--- here
+ // mov ebp, esp
+ // on X64 the register names are different but the sequence is the same.
+ ProloguePattern pp(pc());
+ if (pp.IsValid()) {
+ // Stack layout:
+ // 0 RETURN ADDRESS.
+ *return_address = StackAt(0);
+ return true;
+ }
+ // Detect if we are:
+ // push ebp
+ // mov ebp, esp <--- here
+ // on X64 the register names are different but the sequence is the same.
+ SetFramePointerPattern sfpp(pc());
+ if (sfpp.IsValid()) {
+ // Stack layout:
+ // 0 CALLER FRAME POINTER
+ // 1 RETURN ADDRESS
+ *return_address = StackAt(1);
+ return true;
+ }
+ // Detect if we are:
+ // ret <--- here
+ ReturnPattern rp(pc());
+ if (rp.IsValid()) {
+ // Stack layout:
+ // 0 RETURN ADDRESS.
+ *return_address = StackAt(0);
+ return true;
}
- UNREACHABLE();
return false;
}
#elif defined(TARGET_ARCH_ARM)
@@ -538,6 +446,11 @@ void PreprocessVisitor::CheckForMissingDartFrame(const Code& code,
if (!ral.LocateReturnAddress(&return_address)) {
ASSERT(return_address == sample->pc_marker());
+ if (code.GetPrologueOffset() == 0) {
+ // Code has the prologue at offset 0. The frame is already setup and
+ // can be trusted.
+ return;
+ }
// Could not find a better return address than the pc_marker.
if (code.ContainsInstructionAt(return_address)) {
// PC marker is in the same code as pc, no missing frame.
@@ -592,11 +505,11 @@ class ProfilerDartExitStackWalker : public ValueObject {
: sample_(sample),
frame_iterator_(isolate) {
ASSERT(sample_ != NULL);
- // Mark that this sample was collected from an exit frame.
- sample_->set_exit_frame_sample(true);
}
void walk() {
+ // Mark that this sample was collected from an exit frame.
+ sample_->set_exit_frame_sample(true);
intptr_t frame_index = 0;
StackFrame* frame = frame_iterator_.NextFrame();
while (frame != NULL) {
@@ -637,6 +550,7 @@ class ProfilerDartStackWalker : public ValueObject {
}
void walk() {
+ sample_->set_exit_frame_sample(false);
if (!ValidFramePointer()) {
sample_->set_ignore_sample(true);
return;
« no previous file with comments | « runtime/vm/object.cc ('k') | runtime/vm/raw_object.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698