| Index: runtime/vm/profiler.cc
|
| diff --git a/runtime/vm/profiler.cc b/runtime/vm/profiler.cc
|
| index 2e99b34d7ee646d2eb9d364f4c66f09feb469a78..b9010432f15c0885f398f531459139e31c4ab5fa 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,7 +600,7 @@ 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,
|
| @@ -605,7 +608,7 @@ class ProfilerNativeStackWalker : public ProfilerStackWalker {
|
| uword pc,
|
| uword fp,
|
| uword sp)
|
| - : ProfilerStackWalker(isolate, sample, sample_buffer),
|
| + : ProfilerStackWalker(port_id, sample, sample_buffer),
|
| stack_upper_(stack_upper),
|
| original_pc_(pc),
|
| original_fp_(fp),
|
| @@ -862,6 +865,43 @@ static bool GetAndValidateIsolateStackBounds(Thread* thread,
|
| }
|
|
|
|
|
| +static bool GetAndValidateThreadStackBounds(OSThread* os_thread,
|
| + uintptr_t fp,
|
| + uintptr_t sp,
|
| + uword* stack_lower,
|
| + uword* stack_upper) {
|
| + ASSERT(os_thread != NULL);
|
| + ASSERT(stack_lower != NULL);
|
| + ASSERT(stack_upper != NULL);
|
| + if (!os_thread->GetProfilerStackBounds(stack_lower, stack_upper) ||
|
| + (*stack_lower == 0) || (*stack_upper == 0)) {
|
| + // Could not get stack boundary.
|
| + }
|
| +
|
| + if (sp > *stack_lower) {
|
| + // The stack pointer gives us a tighter lower bound.
|
| + *stack_lower = sp;
|
| + }
|
| +
|
| + if (*stack_lower >= *stack_upper) {
|
| + // Stack boundary is invalid.
|
| + return false;
|
| + }
|
| +
|
| + if ((sp < *stack_lower) || (sp >= *stack_upper)) {
|
| + // Stack pointer is outside thread's stack boundary.
|
| + return false;
|
| + }
|
| +
|
| + if ((fp < *stack_lower) || (fp >= *stack_upper)) {
|
| + // Frame pointer is outside threads's stack boundary.
|
| + return false;
|
| + }
|
| +
|
| + return true;
|
| +}
|
| +
|
| +
|
| // Some simple sanity checking of |pc|, |fp|, and |sp|.
|
| static bool InitialRegisterCheck(uintptr_t pc, uintptr_t fp, uintptr_t sp) {
|
| if ((sp == 0) || (fp == 0) || (pc == 0)) {
|
| @@ -886,7 +926,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 +944,14 @@ static Sample* SetupSample(Thread* thread,
|
| }
|
|
|
|
|
| +static Sample* SetupNativeSample(SampleBuffer* sample_buffer, ThreadId tid) {
|
| + Sample* sample = sample_buffer->ReserveSample();
|
| + sample->Init(ILLEGAL_PORT, OS::GetCurrentMonotonicMicros(), tid);
|
| + sample->set_is_native_allocation_sample(true);
|
| + return sample;
|
| +}
|
| +
|
| +
|
| static bool CheckIsolate(Isolate* isolate) {
|
| if ((isolate == NULL) || (Dart::vm_isolate() == NULL)) {
|
| // No isolate.
|
| @@ -990,7 +1038,8 @@ void Profiler::DumpStackTrace(uword sp, uword fp, uword pc) {
|
| }
|
|
|
| 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");
|
| }
|
| @@ -1037,7 +1086,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 +1104,44 @@ void Profiler::SampleAllocation(Thread* thread, intptr_t cid) {
|
| }
|
|
|
|
|
| +Sample* Profiler::SampleNativeAllocation() {
|
| + 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 (!GetAndValidateThreadStackBounds(os_thread, fp, sp, &stack_lower,
|
| + &stack_upper)) {
|
| + // Could not get stack boundary.
|
| + return NULL;
|
| + }
|
| + }
|
| + Sample* sample = SetupNativeSample(sample_buffer, os_thread->trace_id());
|
| + ProfilerNativeStackWalker native_stack_walker(ILLEGAL_PORT, sample,
|
| + sample_buffer, stack_lower,
|
| + stack_upper, pc, fp, sp);
|
| + native_stack_walker.walk();
|
| + return sample;
|
| +}
|
| +
|
| +
|
| void Profiler::SampleThreadSingleFrame(Thread* thread, uintptr_t pc) {
|
| ASSERT(thread != NULL);
|
| OSThread* os_thread = thread->os_thread();
|
| @@ -1179,7 +1267,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 +1428,7 @@ ProcessedSampleBuffer* SampleBuffer::BuildProcessedSampleBuffer(
|
| // An inner sample in a chain of samples.
|
| continue;
|
| }
|
| - if (sample->isolate() != filter->isolate()) {
|
| + if (sample->port() != filter->port()) {
|
| // Another isolate.
|
| continue;
|
| }
|
| @@ -1418,7 +1507,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()) {
|
|
|