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

Unified Diff: runtime/vm/profiler.cc

Issue 397163002: Profiler cleanup (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 6 years, 5 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 | « no previous file | no next file » | 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 1018cf4bc4184a95a4409f82ee1992551d7f7740..2bed0b0eb89e91b95b9482203eb8148d918b6ccb 100644
--- a/runtime/vm/profiler.cc
+++ b/runtime/vm/profiler.cc
@@ -34,8 +34,6 @@ DEFINE_FLAG(int, profile_period, 1000,
"Time between profiler samples in microseconds. Minimum 50.");
DEFINE_FLAG(int, profile_depth, 8,
"Maximum number stack frames walked. Minimum 1. Maximum 255.");
-DEFINE_FLAG(bool, profile_verify_stack_walk, false,
- "Verify instruction addresses while walking the stack.");
DEFINE_FLAG(bool, profile_vm, false,
"Always collect native stack traces.");
@@ -1663,6 +1661,29 @@ Sample* SampleBuffer::ReserveSample() {
}
+static void SetPCMarkerIfSafe(Sample* sample) {
+ ASSERT(sample != NULL);
+
+ uword* fp = reinterpret_cast<uword*>(sample->fp());
+ uword* sp = reinterpret_cast<uword*>(sample->sp());
+
+ // If FP == SP, the pc marker hasn't been pushed.
+ if (fp > sp) {
+#if defined(TARGET_OS_WINDOWS)
+ // If the fp is at the beginning of a page, it may be unsafe to access
+ // the pc marker, because we are reading it from a different thread on
+ // Windows. The next page may be a guard page.
+ const intptr_t kPageMask = VirtualMemory::PageSize() - 1;
+ if ((sample->fp() & kPageMask) == 0) {
+ return;
+ }
+#endif
+ const uword pc_marker = *(fp + kPcMarkerSlotFromFp);
+ sample->set_pc_marker(pc_marker);
+ }
+}
+
+
class ProfilerDartStackWalker : public ValueObject {
public:
ProfilerDartStackWalker(Isolate* isolate, Sample* sample)
@@ -1722,98 +1743,57 @@ class ProfilerNativeStackWalker : public ValueObject {
ASSERT(sample_ != NULL);
}
- int walk(Heap* heap) {
- const intptr_t kMaxStep = 0x1000; // 4K.
- const bool kWalkStack = true; // Walk the stack.
- // Always store the exclusive PC.
+ void walk(Heap* heap) {
+ const intptr_t kMaxStep = VirtualMemory::PageSize();
+
sample_->SetAt(0, original_pc_);
- if (!kWalkStack) {
- // Not walking the stack, only took exclusive sample.
- return 1;
- }
+
uword* pc = reinterpret_cast<uword*>(original_pc_);
uword* fp = reinterpret_cast<uword*>(original_fp_);
uword* previous_fp = fp;
- if (original_sp_ > original_fp_) {
- // Stack pointer should not be above frame pointer.
- return 1;
- }
- const intptr_t gap = original_fp_ - original_sp_;
- if (gap >= kMaxStep) {
+
+ if ((original_fp_ - original_sp_) >= kMaxStep) {
// Gap between frame pointer and stack pointer is
// too large.
- return 1;
+ return;
}
- if (original_sp_ < lower_bound_) {
- // The stack pointer gives us a better lower bound than
- // the isolates stack limit.
- lower_bound_ = original_sp_;
+
+ if (!ValidFramePointer(fp)) {
+ return;
}
-#if defined(TARGET_OS_WINDOWS)
- // If the original_fp_ is at the beginning of a page, it may be unsafe
- // to access the pc marker, because we are reading it from a different
- // thread on Windows. The next page may be a guard page.
- const intptr_t kPageMask = kMaxStep - 1;
- bool safe_to_read_pc_marker = (original_fp_ & kPageMask) != 0;
-#else
- bool safe_to_read_pc_marker = true;
-#endif
- if (safe_to_read_pc_marker && (gap > 0)) {
- // Store the PC marker for the top frame.
- sample_->set_pc_marker(GetCurrentFramePcMarker(fp));
- }
- int i = 0;
- for (; i < FLAG_profile_depth; i++) {
- if (FLAG_profile_verify_stack_walk) {
- VerifyCodeAddress(heap, i, reinterpret_cast<uword>(pc));
- }
+
+ for (int i = 0; i < FLAG_profile_depth; i++) {
sample_->SetAt(i, reinterpret_cast<uword>(pc));
- if (fp == NULL) {
- return i + 1;
- }
- if (!ValidFramePointer(fp)) {
- return i + 1;
- }
+
pc = CallerPC(fp);
previous_fp = fp;
fp = CallerFP(fp);
- intptr_t step = fp - previous_fp;
+
if (fp == NULL) {
- return i + 1;
- }
- if ((step >= kMaxStep)) {
- // Frame pointer step is too large.
- return i + 1;
+ return;
}
- if ((fp <= previous_fp)) {
+
+ if (fp <= previous_fp) {
// Frame pointer did not move to a higher address.
- return i + 1;
+ return;
+ }
+
+ if ((fp - previous_fp) >= kMaxStep) {
+ // Frame pointer step is too large.
+ return;
}
+
if (!ValidFramePointer(fp)) {
- // Frame pointer is outside of isolate stack bounds.
- return i + 1;
+ // Frame pointer is outside of isolate stack boundary.
+ return;
}
+
// Move the lower bound up.
lower_bound_ = reinterpret_cast<uword>(fp);
}
- return i;
}
private:
- void VerifyCodeAddress(Heap* heap, int i, uword pc) {
- if (heap != NULL) {
- if (heap->Contains(pc) && !heap->CodeContains(pc)) {
- for (int j = 0; j < i; j++) {
- OS::Print("%d %" Px "\n", j, sample_->At(j));
- }
- OS::Print("%d %" Px " <--\n", i, pc);
- OS::Print("---ASSERT-FAILED---\n");
- OS::Print("%" Px " %" Px "\n", original_pc_, original_fp_);
- UNREACHABLE();
- }
- }
- }
-
uword* CallerPC(uword* fp) const {
ASSERT(fp != NULL);
return reinterpret_cast<uword*>(*(fp + kSavedCallerPcSlotFromFp));
@@ -1824,20 +1804,13 @@ class ProfilerNativeStackWalker : public ValueObject {
return reinterpret_cast<uword*>(*(fp + kSavedCallerFpSlotFromFp));
}
- uword GetCurrentFramePcMarker(uword* fp) const {
- if (!ValidFramePointer(fp)) {
- return 0;
- }
- return *(fp + kPcMarkerSlotFromFp);
- }
-
bool ValidFramePointer(uword* fp) const {
if (fp == NULL) {
return false;
}
uword cursor = reinterpret_cast<uword>(fp);
cursor += sizeof(fp);
- bool r = cursor >= lower_bound_ && cursor < stack_upper_;
+ bool r = (cursor >= lower_bound_) && (cursor < stack_upper_);
return r;
}
@@ -1855,46 +1828,96 @@ void Profiler::RecordSampleInterruptCallback(
void* data) {
Isolate* isolate = reinterpret_cast<Isolate*>(data);
if ((isolate == NULL) || (Dart::vm_isolate() == NULL)) {
+ // No isolate.
return;
}
+
ASSERT(isolate != Dart::vm_isolate());
+
+ IsolateProfilerData* profiler_data = isolate->profiler_data();
+ if (profiler_data == NULL) {
+ // Profiler not initialized.
+ return;
+ }
+
+ SampleBuffer* sample_buffer = profiler_data->sample_buffer();
+ if (sample_buffer == NULL) {
+ // Profiler not initialized.
+ return;
+ }
+
+ if ((state.sp == 0) || (state.fp == 0) || (state.pc == 0)) {
+ // None of these registers should be zero.
+ return;
+ }
+
+ if (state.sp > state.fp) {
+ // Assuming the stack grows down, we should never have a stack pointer above
+ // the frame pointer.
+ return;
+ }
+
if (StubCode::InJumpToExceptionHandlerStub(state.pc)) {
// The JumpToExceptionHandler stub manually adjusts the stack pointer,
// frame pointer, and some isolate state before jumping to a catch entry.
// It is not safe to walk the stack when executing this stub.
return;
}
- VMTagCounters* counters = isolate->vm_tag_counters();
- ASSERT(counters != NULL);
- counters->Increment(isolate->vm_tag());
- IsolateProfilerData* profiler_data = isolate->profiler_data();
- if (profiler_data == NULL) {
+
+ uword stack_lower = 0;
+ uword stack_upper = 0;
+ isolate->GetStackBounds(&stack_lower, &stack_upper);
+ if ((stack_lower == 0) || (stack_upper == 0)) {
+ // Could not get stack boundary.
return;
}
- SampleBuffer* sample_buffer = profiler_data->sample_buffer();
- if (sample_buffer == NULL) {
+
+ if (state.sp > stack_lower) {
+ // The stack pointer gives us a tighter lower bound.
+ stack_lower = state.sp;
+ }
+
+ if (stack_lower >= stack_upper) {
+ // Stack boundary is invalid.
+ return;
+ }
+
+ if ((state.sp < stack_lower) || (state.sp >= stack_upper)) {
+ // Stack pointer is outside isolate stack boundary.
return;
}
+
+ if ((state.fp < stack_lower) || (state.fp >= stack_upper)) {
+ // Frame pointer is outside isolate stack boundary.
+ return;
+ }
+
+ // At this point we have a valid stack boundary for this isolate and
+ // know that our initial stack and frame pointers are within the boundary.
+
+ // Increment counter for vm tag.
+ VMTagCounters* counters = isolate->vm_tag_counters();
+ ASSERT(counters != NULL);
+ counters->Increment(isolate->vm_tag());
+
+ // Setup sample.
Sample* sample = sample_buffer->ReserveSample();
sample->Init(isolate, OS::GetCurrentTimeMicros(), state.tid);
sample->set_vm_tag(isolate->vm_tag());
sample->set_user_tag(isolate->user_tag());
sample->set_sp(state.sp);
sample->set_fp(state.fp);
+ SetPCMarkerIfSafe(sample);
- uword stack_lower = 0;
- uword stack_upper = 0;
- isolate->GetStackBounds(&stack_lower, &stack_upper);
- if ((stack_lower == 0) || (stack_upper == 0)) {
- stack_lower = 0;
- stack_upper = 0;
- }
+ // Walk the call stack.
if (FLAG_profile_vm) {
- // Collect native and Dart frames.
+ // Always walk the native stack collecting both native and Dart frames.
ProfilerNativeStackWalker stackWalker(sample, stack_lower, stack_upper,
state.pc, state.fp, state.sp);
stackWalker.walk(isolate->heap());
} else {
+ // Attempt to walk only the Dart call stack, falling back to walking
+ // the native stack.
if ((isolate->stub_code() != NULL) &&
(isolate->top_exit_frame_info() != 0) &&
(isolate->vm_tag() != VMTag::kScriptTagId)) {
@@ -1902,7 +1925,6 @@ void Profiler::RecordSampleInterruptCallback(
ProfilerDartStackWalker stackWalker(isolate, sample);
stackWalker.walk();
} else {
- // Collect native and Dart frames.
ProfilerNativeStackWalker stackWalker(sample, stack_lower, stack_upper,
state.pc, state.fp, state.sp);
stackWalker.walk(isolate->heap());
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698