| Index: runtime/vm/profiler.cc
|
| diff --git a/runtime/vm/profiler.cc b/runtime/vm/profiler.cc
|
| index 05f830292c76c03c54568a4fac18debcebb55717..2b0a7247c5a08038d2a7bdc80b98aa87e06d74a0 100644
|
| --- a/runtime/vm/profiler.cc
|
| +++ b/runtime/vm/profiler.cc
|
| @@ -418,67 +418,54 @@ class ProfilerStackWalker : public ValueObject {
|
| };
|
|
|
|
|
| -// Given an exit frame, walk the Dart stack.
|
| -class ProfilerDartExitStackWalker : public ProfilerStackWalker {
|
| - public:
|
| - ProfilerDartExitStackWalker(Thread* thread,
|
| - Isolate* isolate,
|
| - Sample* sample,
|
| - SampleBuffer* sample_buffer)
|
| - : ProfilerStackWalker(isolate, sample, sample_buffer),
|
| - frame_iterator_(thread) {}
|
| -
|
| - void walk() {
|
| - // Mark that this sample was collected from an exit frame.
|
| - sample_->set_exit_frame_sample(true);
|
| -
|
| - StackFrame* frame = frame_iterator_.NextFrame();
|
| - if (sample_ == NULL) {
|
| - // Only when we are dumping the stack trace for debug purposes.
|
| - Code& code = Code::Handle();
|
| - while (frame != NULL) {
|
| - code ^= frame->LookupDartCode();
|
| - if (!Append(frame->pc(), code)) {
|
| - return;
|
| - }
|
| - frame = frame_iterator_.NextFrame();
|
| - }
|
| - } else {
|
| - while (frame != NULL) {
|
| - if (!Append(frame->pc())) {
|
| - return;
|
| - }
|
| - frame = frame_iterator_.NextFrame();
|
| - }
|
| - }
|
| - }
|
| -
|
| - private:
|
| - DartFrameIterator frame_iterator_;
|
| -};
|
| -
|
| -
|
| // Executing Dart code, walk the stack.
|
| class ProfilerDartStackWalker : public ProfilerStackWalker {
|
| public:
|
| - ProfilerDartStackWalker(Isolate* isolate,
|
| + ProfilerDartStackWalker(Thread* thread,
|
| Sample* sample,
|
| SampleBuffer* sample_buffer,
|
| uword stack_lower,
|
| uword stack_upper,
|
| uword pc,
|
| uword fp,
|
| - uword sp)
|
| - : ProfilerStackWalker(isolate, sample, sample_buffer),
|
| + uword sp,
|
| + bool exited_dart_code,
|
| + bool allocation_sample)
|
| + : ProfilerStackWalker(thread->isolate(), sample, sample_buffer),
|
| + pc_(reinterpret_cast<uword*>(pc)),
|
| + fp_(reinterpret_cast<uword*>(fp)),
|
| + sp_(reinterpret_cast<uword*>(sp)),
|
| stack_upper_(stack_upper),
|
| - stack_lower_(stack_lower) {
|
| - pc_ = reinterpret_cast<uword*>(pc);
|
| - fp_ = reinterpret_cast<uword*>(fp);
|
| - sp_ = reinterpret_cast<uword*>(sp);
|
| + stack_lower_(stack_lower),
|
| + has_exit_frame_(exited_dart_code) {
|
| + if (exited_dart_code) {
|
| + StackFrameIterator iterator(StackFrameIterator::kDontValidateFrames,
|
| + thread);
|
| + pc_ = NULL;
|
| + fp_ = NULL;
|
| + sp_ = NULL;
|
| + if (!iterator.HasNextFrame()) {
|
| + return;
|
| + }
|
| + // Ensure we are able to get to the exit frame.
|
| + StackFrame* frame = iterator.NextFrame();
|
| + if (!frame->IsExitFrame()) {
|
| + return;
|
| + }
|
| + // Skip the exit frame.
|
| + if (!iterator.HasNextFrame()) {
|
| + return;
|
| + }
|
| + frame = iterator.NextFrame();
|
| + // Record frame details of the first frame from which we start walking.
|
| + pc_ = reinterpret_cast<uword*>(frame->pc());
|
| + fp_ = reinterpret_cast<uword*>(frame->fp());
|
| + sp_ = reinterpret_cast<uword*>(frame->sp());
|
| + }
|
| }
|
|
|
| void walk() {
|
| - sample_->set_exit_frame_sample(false);
|
| + sample_->set_exit_frame_sample(has_exit_frame_);
|
| if (!ValidFramePointer()) {
|
| sample_->set_ignore_sample(true);
|
| return;
|
| @@ -605,7 +592,8 @@ class ProfilerDartStackWalker : public ProfilerStackWalker {
|
| uword* fp_;
|
| uword* sp_;
|
| const uword stack_upper_;
|
| - uword stack_lower_;
|
| + const uword stack_lower_;
|
| + bool has_exit_frame_;
|
| };
|
|
|
|
|
| @@ -758,7 +746,6 @@ static void CollectSample(Isolate* isolate,
|
| bool in_dart_code,
|
| Sample* sample,
|
| ProfilerNativeStackWalker* native_stack_walker,
|
| - ProfilerDartExitStackWalker* dart_exit_stack_walker,
|
| ProfilerDartStackWalker* dart_stack_walker,
|
| uword pc,
|
| uword fp,
|
| @@ -783,7 +770,7 @@ static void CollectSample(Isolate* isolate,
|
| } else if (StubCode::HasBeenInitialized() && exited_dart_code) {
|
| AtomicOperations::IncrementInt64By(&counters->stack_walker_dart_exit, 1);
|
| // We have a valid exit frame info, use the Dart stack walker.
|
| - dart_exit_stack_walker->walk();
|
| + dart_stack_walker->walk();
|
| } else if (StubCode::HasBeenInitialized() && in_dart_code) {
|
| AtomicOperations::IncrementInt64By(&counters->stack_walker_dart, 1);
|
| // We are executing Dart code. We have frame pointers.
|
| @@ -944,7 +931,7 @@ static uintptr_t __attribute__((noinline)) GetProgramCounter() {
|
| #endif
|
|
|
|
|
| -void Profiler::DumpStackTrace(bool native_stack_trace) {
|
| +void Profiler::DumpStackTrace() {
|
| // Allow only one stack trace to prevent recursively printing stack traces if
|
| // we hit an assert while printing the stack.
|
| static uintptr_t started_dump = 0;
|
| @@ -964,10 +951,7 @@ void Profiler::DumpStackTrace(bool native_stack_trace) {
|
| return;
|
| }
|
|
|
| - const bool exited_dart_code = thread->HasExitedDartCode();
|
| -
|
| - OS::PrintErr("Dumping %s stack trace for thread %" Px "\n",
|
| - native_stack_trace ? "native" : "dart-only",
|
| + OS::PrintErr("Dumping native stack trace for thread %" Px "\n",
|
| OSThread::ThreadIdToIntPtr(os_thread->trace_id()));
|
|
|
| uintptr_t sp = Thread::GetCurrentStackPointer();
|
| @@ -991,18 +975,9 @@ void Profiler::DumpStackTrace(bool native_stack_trace) {
|
| return;
|
| }
|
|
|
| - if (native_stack_trace) {
|
| - ProfilerNativeStackWalker native_stack_walker(
|
| - isolate, NULL, NULL, stack_lower, stack_upper, pc, fp, sp);
|
| - native_stack_walker.walk();
|
| - } else if (exited_dart_code) {
|
| - ProfilerDartExitStackWalker dart_exit_stack_walker(thread, isolate, NULL,
|
| - NULL);
|
| - dart_exit_stack_walker.walk();
|
| - } else {
|
| - ProfilerDartStackWalker dart_stack_walker(isolate, NULL, NULL, stack_lower,
|
| - stack_upper, pc, fp, sp);
|
| - }
|
| + ProfilerNativeStackWalker native_stack_walker(
|
| + isolate, NULL, NULL, stack_lower, stack_upper, pc, fp, sp);
|
| + native_stack_walker.walk();
|
| OS::PrintErr("-- End of DumpStackTrace\n");
|
| }
|
|
|
| @@ -1024,36 +999,36 @@ void Profiler::SampleAllocation(Thread* thread, intptr_t cid) {
|
| return;
|
| }
|
|
|
| - if (FLAG_profile_vm) {
|
| - uintptr_t sp = Thread::GetCurrentStackPointer();
|
| - uintptr_t fp = 0;
|
| - uintptr_t pc = GetProgramCounter();
|
| + uintptr_t sp = Thread::GetCurrentStackPointer();
|
| + uintptr_t fp = 0;
|
| + uintptr_t pc = GetProgramCounter();
|
|
|
| - COPY_FP_REGISTER(fp);
|
| + COPY_FP_REGISTER(fp);
|
|
|
| - uword stack_lower = 0;
|
| - uword stack_upper = 0;
|
| + uword stack_lower = 0;
|
| + uword stack_upper = 0;
|
|
|
| - if (!InitialRegisterCheck(pc, fp, sp)) {
|
| - return;
|
| - }
|
| + if (!InitialRegisterCheck(pc, fp, sp)) {
|
| + return;
|
| + }
|
|
|
| - if (!GetAndValidateIsolateStackBounds(thread, fp, sp, &stack_lower,
|
| - &stack_upper)) {
|
| - // Could not get stack boundary.
|
| - return;
|
| - }
|
| + if (!GetAndValidateIsolateStackBounds(thread, fp, sp, &stack_lower,
|
| + &stack_upper)) {
|
| + // Could not get stack boundary.
|
| + return;
|
| + }
|
|
|
| - Sample* sample = SetupSample(thread, sample_buffer, os_thread->trace_id());
|
| - sample->SetAllocationCid(cid);
|
| + Sample* sample = SetupSample(thread, sample_buffer, os_thread->trace_id());
|
| + sample->SetAllocationCid(cid);
|
| +
|
| + if (FLAG_profile_vm) {
|
| ProfilerNativeStackWalker native_stack_walker(
|
| isolate, sample, sample_buffer, stack_lower, stack_upper, pc, fp, sp);
|
| native_stack_walker.walk();
|
| } else if (exited_dart_code) {
|
| - Sample* sample = SetupSample(thread, sample_buffer, os_thread->trace_id());
|
| - sample->SetAllocationCid(cid);
|
| - ProfilerDartExitStackWalker dart_exit_stack_walker(thread, isolate, sample,
|
| - sample_buffer);
|
| + ProfilerDartStackWalker dart_exit_stack_walker(
|
| + thread, sample, sample_buffer, stack_lower, stack_upper, pc, fp, sp,
|
| + exited_dart_code, true);
|
| dart_exit_stack_walker.walk();
|
| } else {
|
| // Fall back.
|
| @@ -1192,19 +1167,15 @@ void Profiler::SampleThread(Thread* thread,
|
|
|
| ProfilerNativeStackWalker native_stack_walker(
|
| isolate, sample, sample_buffer, stack_lower, stack_upper, pc, fp, sp);
|
| -
|
| - ProfilerDartExitStackWalker dart_exit_stack_walker(thread, isolate, sample,
|
| - sample_buffer);
|
| -
|
| - ProfilerDartStackWalker dart_stack_walker(
|
| - isolate, 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,
|
| + sp, exited_dart_code, false);
|
|
|
| // All memory access is done inside CollectSample.
|
| CollectSample(isolate, exited_dart_code, in_dart_code, sample,
|
| - &native_stack_walker, &dart_exit_stack_walker,
|
| - &dart_stack_walker, pc, fp, sp, &counters_);
|
| + &native_stack_walker, &dart_stack_walker, pc, fp, sp,
|
| + &counters_);
|
| }
|
|
|
|
|
|
|