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

Unified Diff: runtime/vm/profiler.cc

Issue 2680213002: Updated MallocHooks to collect stack traces when memory is allocated. (Closed)
Patch Set: Added tests and modified stack walker to allow for skipping an arbitrary number of frames before co… Created 3 years, 10 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
Index: runtime/vm/profiler.cc
diff --git a/runtime/vm/profiler.cc b/runtime/vm/profiler.cc
index 2e99b34d7ee646d2eb9d364f4c66f09feb469a78..73f2e41a5c8e9285542dec404276fd34f438d97e 100644
--- a/runtime/vm/profiler.cc
+++ b/runtime/vm/profiler.cc
@@ -168,7 +168,7 @@ Sample* SampleBuffer::ReserveSampleAndLink(Sample* previous) {
ASSERT(previous != NULL);
intptr_t next_index = ReserveSampleSlot();
Sample* next = At(next_index);
- next->Init(previous->isolate(), previous->timestamp(), previous->tid());
+ next->Init(previous->port(), previous->timestamp(), previous->tid());
next->set_head_sample(false);
// Mark that previous continues at next.
previous->SetContinuationIndex(next_index);
@@ -321,7 +321,7 @@ bool SampleFilter::TaskFilterSample(Sample* sample) {
ClearProfileVisitor::ClearProfileVisitor(Isolate* isolate)
- : SampleVisitor(isolate) {}
+ : SampleVisitor(isolate->main_port()) {}
void ClearProfileVisitor::VisitSample(Sample* sample) {
@@ -357,15 +357,14 @@ static void DumpStackFrame(intptr_t frame_index, uword pc) {
class ProfilerStackWalker : public ValueObject {
public:
- ProfilerStackWalker(Isolate* isolate,
+ ProfilerStackWalker(Dart_Port port_id,
Sample* head_sample,
SampleBuffer* sample_buffer)
- : isolate_(isolate),
+ : port_id_(port_id),
sample_(head_sample),
sample_buffer_(sample_buffer),
frame_index_(0),
total_frames_(0) {
- ASSERT(isolate_ != NULL);
if (sample_ == NULL) {
ASSERT(sample_buffer_ == NULL);
} else {
@@ -404,7 +403,7 @@ class ProfilerStackWalker : public ValueObject {
}
protected:
- Isolate* isolate_;
+ Dart_Port port_id_;
Sample* sample_;
SampleBuffer* sample_buffer_;
intptr_t frame_index_;
@@ -425,7 +424,11 @@ class ProfilerDartStackWalker : public ProfilerStackWalker {
uword sp,
bool exited_dart_code,
bool allocation_sample)
- : ProfilerStackWalker(thread->isolate(), sample, sample_buffer),
+ : ProfilerStackWalker((thread->isolate() != NULL)
+ ? thread->isolate()->main_port()
+ : ILLEGAL_PORT,
+ sample,
+ sample_buffer),
pc_(reinterpret_cast<uword*>(pc)),
fp_(reinterpret_cast<uword*>(fp)),
sp_(reinterpret_cast<uword*>(sp)),
@@ -597,24 +600,31 @@ class ProfilerDartStackWalker : public ProfilerStackWalker {
//
class ProfilerNativeStackWalker : public ProfilerStackWalker {
public:
- ProfilerNativeStackWalker(Isolate* isolate,
+ ProfilerNativeStackWalker(Dart_Port port_id,
Sample* sample,
SampleBuffer* sample_buffer,
uword stack_lower,
uword stack_upper,
uword pc,
uword fp,
- uword sp)
- : ProfilerStackWalker(isolate, sample, sample_buffer),
+ uword sp,
+ intptr_t skip_count = 0)
Cutch 2017/02/15 08:21:00 Support for skip count should be generalized and p
bkonyi 2017/02/16 00:28:28 Done.
+ : ProfilerStackWalker(port_id, sample, sample_buffer),
stack_upper_(stack_upper),
original_pc_(pc),
original_fp_(fp),
original_sp_(sp),
- lower_bound_(stack_lower) {}
+ lower_bound_(stack_lower),
+ skip_count_(skip_count) {}
void walk() {
const uword kMaxStep = VirtualMemory::PageSize();
- Append(original_pc_);
+ intptr_t frame_count = 0;
+
+ if (frame_count >= skip_count_) {
+ Append(original_pc_);
+ }
+ ++frame_count;
uword* pc = reinterpret_cast<uword*>(original_pc_);
uword* fp = reinterpret_cast<uword*>(original_fp_);
@@ -632,7 +642,7 @@ class ProfilerNativeStackWalker : public ProfilerStackWalker {
}
while (true) {
- if (!Append(reinterpret_cast<uword>(pc))) {
+ if (frame_count >= skip_count_ && !Append(reinterpret_cast<uword>(pc))) {
Cutch 2017/02/15 08:21:00 wrap in parens: (frame_count >= skip_count_) Also
bkonyi 2017/02/16 00:28:29 Acknowledged.
return;
}
@@ -662,6 +672,7 @@ class ProfilerNativeStackWalker : public ProfilerStackWalker {
// Move the lower bound up.
lower_bound_ = reinterpret_cast<uword>(fp);
+ ++frame_count;
Cutch 2017/02/15 08:21:00 You should bump frame_count immediately after the
bkonyi 2017/02/16 00:28:29 Acknowledged.
}
}
@@ -699,6 +710,7 @@ class ProfilerNativeStackWalker : public ProfilerStackWalker {
const uword original_fp_;
const uword original_sp_;
uword lower_bound_;
+ intptr_t skip_count_;
};
@@ -798,18 +810,23 @@ static void CollectSample(Isolate* isolate,
// Get |isolate|'s stack boundary and verify that |sp| and |fp| are within
// it. Return |false| if anything looks suspicious.
-static bool GetAndValidateIsolateStackBounds(Thread* thread,
- uintptr_t fp,
- uintptr_t sp,
- uword* stack_lower,
- uword* stack_upper) {
- ASSERT(thread != NULL);
- OSThread* os_thread = thread->os_thread();
+static bool GetAndValidateStackBounds(Thread* thread,
Cutch 2017/02/15 08:21:00 Seems like a bad merge here. Please see this CL:
bkonyi 2017/02/16 00:28:29 Not a bad merge, just haven't rebased in awhile. D
+ uintptr_t fp,
+ uintptr_t sp,
+ uword* stack_lower,
+ uword* stack_upper) {
+ OSThread* os_thread = NULL;
+ if (thread != NULL) {
+ os_thread = thread->os_thread();
+ } else {
+ os_thread = OSThread::Current();
+ }
ASSERT(os_thread != NULL);
ASSERT(stack_lower != NULL);
ASSERT(stack_upper != NULL);
#if defined(USING_SIMULATOR)
- const bool in_dart_code = thread->IsExecutingDartCode();
+ const bool in_dart_code =
+ (thread == NULL) ? false : thread->IsExecutingDartCode();
if (in_dart_code) {
Isolate* isolate = thread->isolate();
ASSERT(isolate != NULL);
@@ -886,7 +903,7 @@ static Sample* SetupSample(Thread* thread,
Isolate* isolate = thread->isolate();
ASSERT(sample_buffer != NULL);
Sample* sample = sample_buffer->ReserveSample();
- sample->Init(isolate, OS::GetCurrentMonotonicMicros(), tid);
+ sample->Init(isolate->main_port(), OS::GetCurrentMonotonicMicros(), tid);
uword vm_tag = thread->vm_tag();
#if defined(USING_SIMULATOR) && !defined(TARGET_ARCH_DBC)
// When running in the simulator, the runtime entry function address
@@ -904,6 +921,23 @@ static Sample* SetupSample(Thread* thread,
}
+static Sample* SetupSampleNative(SampleBuffer* sample_buffer, ThreadId tid) {
+ Sample* sample = sample_buffer->ReserveSample();
+ sample->Init(ILLEGAL_PORT, OS::GetCurrentMonotonicMicros(), tid);
+ sample->set_is_native_allocation_sample(true);
+
+ Thread* thread = Thread::Current();
+
+ // TODO(bkonyi) Any samples created while a current thread doesn't exist are
+ // ignored by the NativeAllocationSampleFilter since the default task is
+ // kUnknownTask. Is this what we want to do?
+ if (thread != NULL) {
+ sample->set_thread_task(thread->task_kind());
+ }
+ return sample;
+}
+
+
static bool CheckIsolate(Isolate* isolate) {
if ((isolate == NULL) || (Dart::vm_isolate() == NULL)) {
// No isolate.
@@ -982,15 +1016,14 @@ void Profiler::DumpStackTrace(uword sp, uword fp, uword pc) {
return;
}
- if (!GetAndValidateIsolateStackBounds(thread, fp, sp, &stack_lower,
- &stack_upper)) {
- OS::PrintErr(
- "Stack dump aborted because GetAndValidateIsolateStackBounds.\n");
+ if (!GetAndValidateStackBounds(thread, fp, sp, &stack_lower, &stack_upper)) {
+ OS::PrintErr("Stack dump aborted because GetAndValidateStackBounds.\n");
return;
}
ProfilerNativeStackWalker native_stack_walker(
- isolate, NULL, NULL, stack_lower, stack_upper, pc, fp, sp);
+ (isolate != NULL) ? isolate->main_port() : ILLEGAL_PORT, NULL, NULL,
+ stack_lower, stack_upper, pc, fp, sp);
native_stack_walker.walk();
OS::PrintErr("-- End of DumpStackTrace\n");
}
@@ -1026,8 +1059,7 @@ void Profiler::SampleAllocation(Thread* thread, intptr_t cid) {
return;
}
- if (!GetAndValidateIsolateStackBounds(thread, fp, sp, &stack_lower,
- &stack_upper)) {
+ if (!GetAndValidateStackBounds(thread, fp, sp, &stack_lower, &stack_upper)) {
// Could not get stack boundary.
return;
}
@@ -1037,7 +1069,8 @@ void Profiler::SampleAllocation(Thread* thread, intptr_t cid) {
if (FLAG_profile_vm) {
ProfilerNativeStackWalker native_stack_walker(
- isolate, sample, sample_buffer, stack_lower, stack_upper, pc, fp, sp);
+ (isolate != NULL) ? isolate->main_port() : ILLEGAL_PORT, sample,
+ sample_buffer, stack_lower, stack_upper, pc, fp, sp);
native_stack_walker.walk();
} else if (exited_dart_code) {
ProfilerDartStackWalker dart_exit_stack_walker(
@@ -1054,6 +1087,43 @@ void Profiler::SampleAllocation(Thread* thread, intptr_t cid) {
}
+Sample* Profiler::SampleNativeAllocation(intptr_t skip_count) {
+ SampleBuffer* sample_buffer = Profiler::sample_buffer();
+ if (sample_buffer == NULL) {
+ return NULL;
+ }
+
+ uintptr_t sp = Thread::GetCurrentStackPointer();
+ uintptr_t fp = 0;
+ uintptr_t pc = GetProgramCounter();
+
+ COPY_FP_REGISTER(fp);
+
+ uword stack_lower = 0;
+ uword stack_upper = 0;
+ if (!InitialRegisterCheck(pc, fp, sp)) {
+ return NULL;
+ }
+
+ OSThread* os_thread = OSThread::Current();
+ if (os_thread->stack_base() == 0) {
+ stack_lower = sp;
+ stack_upper = ~static_cast<uintptr_t>(0x0);
+ } else {
+ if (!GetAndValidateStackBounds(NULL, fp, sp, &stack_lower, &stack_upper)) {
+ // Could not get stack boundary.
+ return NULL;
+ }
+ }
+ Sample* sample = SetupSampleNative(sample_buffer, os_thread->trace_id());
+ ProfilerNativeStackWalker native_stack_walker(
+ ILLEGAL_PORT, sample, sample_buffer, stack_lower, stack_upper, pc, fp, sp,
+ skip_count);
+ native_stack_walker.walk();
+ return sample;
+}
+
+
void Profiler::SampleThreadSingleFrame(Thread* thread, uintptr_t pc) {
ASSERT(thread != NULL);
OSThread* os_thread = thread->os_thread();
@@ -1152,8 +1222,7 @@ void Profiler::SampleThread(Thread* thread,
uword stack_lower = 0;
uword stack_upper = 0;
- if (!GetAndValidateIsolateStackBounds(thread, fp, sp, &stack_lower,
- &stack_upper)) {
+ if (!GetAndValidateStackBounds(thread, fp, sp, &stack_lower, &stack_upper)) {
AtomicOperations::IncrementInt64By(
&counters_.single_frame_sample_get_and_validate_stack_bounds, 1);
// Could not get stack boundary.
@@ -1179,7 +1248,8 @@ void Profiler::SampleThread(Thread* thread,
}
ProfilerNativeStackWalker native_stack_walker(
- isolate, sample, sample_buffer, stack_lower, stack_upper, pc, fp, sp);
+ (isolate != NULL) ? isolate->main_port() : ILLEGAL_PORT, sample,
+ sample_buffer, stack_lower, stack_upper, pc, fp, sp);
const bool exited_dart_code = thread->HasExitedDartCode();
ProfilerDartStackWalker dart_stack_walker(thread, sample, sample_buffer,
stack_lower, stack_upper, pc, fp,
@@ -1339,7 +1409,10 @@ ProcessedSampleBuffer* SampleBuffer::BuildProcessedSampleBuffer(
// An inner sample in a chain of samples.
continue;
}
- if (sample->isolate() != filter->isolate()) {
+ // If we're requesting all the native allocation samples, we don't care
+ // whether or not we're in the same isolate as the sample.
+ if (sample->port() != filter->port() &&
Cutch 2017/02/15 08:21:00 wrap in parens: (sample->port() != filter->port())
bkonyi 2017/02/16 00:28:29 Done.
+ !sample->is_native_allocation_sample()) {
// Another isolate.
continue;
}
@@ -1418,7 +1491,7 @@ Sample* SampleBuffer::Next(Sample* sample) {
// Sanity check.
ASSERT(sample != next_sample);
// Detect invalid chaining.
- if (sample->isolate() != next_sample->isolate()) {
+ if (sample->port() != next_sample->port()) {
return NULL;
}
if (sample->timestamp() != next_sample->timestamp()) {

Powered by Google App Engine
This is Rietveld 408576698