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

Side by Side Diff: src/sampler.cc

Issue 588623002: Implemented GetSample like POSIX backtrace() Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Printing return value of GetSample (for ARM try server) Created 6 years, 3 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 unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/sampler.h ('k') | test/cctest/cctest.gyp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2013 the V8 project authors. All rights reserved. 1 // Copyright 2013 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "src/sampler.h" 5 #include "src/sampler.h"
6 6
7 #if V8_OS_POSIX && !V8_OS_CYGWIN
8
9 #define USE_SIGNALS
10
11 #include <errno.h>
12 #include <pthread.h>
13 #include <signal.h>
14 #include <sys/time.h>
15
16 #if !V8_OS_QNX && !V8_OS_NACL
17 #include <sys/syscall.h> // NOLINT
18 #endif
19
20 #if V8_OS_MACOSX
21 #include <mach/mach.h>
22 // OpenBSD doesn't have <ucontext.h>. ucontext_t lives in <signal.h>
23 // and is a typedef for struct sigcontext. There is no uc_mcontext.
24 #elif(!V8_OS_ANDROID || defined(__BIONIC_HAVE_UCONTEXT_T)) && \
25 !V8_OS_OPENBSD && !V8_OS_NACL
26 #include <ucontext.h>
27 #endif
28
29 #include <unistd.h>
30
31 // GLibc on ARM defines mcontext_t has a typedef for 'struct sigcontext'.
32 // Old versions of the C library <signal.h> didn't define the type.
33 #if V8_OS_ANDROID && !defined(__BIONIC_HAVE_UCONTEXT_T) && \
34 (defined(__arm__) || defined(__aarch64__)) && \
35 !defined(__BIONIC_HAVE_STRUCT_SIGCONTEXT)
36 #include <asm/sigcontext.h> // NOLINT
37 #endif
38
39 #elif V8_OS_WIN || V8_OS_CYGWIN
40
41 #include "src/base/win32-headers.h"
42
43 #endif
44
45 #include "src/v8.h" 7 #include "src/v8.h"
46 8
47 #include "src/base/platform/platform.h" 9 #include "src/base/platform/platform.h"
48 #include "src/cpu-profiler-inl.h" 10 #include "src/cpu-profiler-inl.h"
49 #include "src/flags.h" 11 #include "src/flags.h"
50 #include "src/frames-inl.h" 12 #include "src/frames-inl.h"
51 #include "src/log.h" 13 #include "src/log.h"
52 #include "src/simulator.h" 14 #include "src/simulator.h"
53 #include "src/v8threads.h" 15 #include "src/v8threads.h"
54 #include "src/vm-state-inl.h" 16 #include "src/vm-state-inl.h"
55 17
56
57 #if V8_OS_ANDROID && !defined(__BIONIC_HAVE_UCONTEXT_T)
58
59 // Not all versions of Android's C library provide ucontext_t.
60 // Detect this and provide custom but compatible definitions. Note that these
61 // follow the GLibc naming convention to access register values from
62 // mcontext_t.
63 //
64 // See http://code.google.com/p/android/issues/detail?id=34784
65
66 #if defined(__arm__)
67
68 typedef struct sigcontext mcontext_t;
69
70 typedef struct ucontext {
71 uint32_t uc_flags;
72 struct ucontext* uc_link;
73 stack_t uc_stack;
74 mcontext_t uc_mcontext;
75 // Other fields are not used by V8, don't define them here.
76 } ucontext_t;
77
78 #elif defined(__aarch64__)
79
80 typedef struct sigcontext mcontext_t;
81
82 typedef struct ucontext {
83 uint64_t uc_flags;
84 struct ucontext *uc_link;
85 stack_t uc_stack;
86 mcontext_t uc_mcontext;
87 // Other fields are not used by V8, don't define them here.
88 } ucontext_t;
89
90 #elif defined(__mips__)
91 // MIPS version of sigcontext, for Android bionic.
92 typedef struct {
93 uint32_t regmask;
94 uint32_t status;
95 uint64_t pc;
96 uint64_t gregs[32];
97 uint64_t fpregs[32];
98 uint32_t acx;
99 uint32_t fpc_csr;
100 uint32_t fpc_eir;
101 uint32_t used_math;
102 uint32_t dsp;
103 uint64_t mdhi;
104 uint64_t mdlo;
105 uint32_t hi1;
106 uint32_t lo1;
107 uint32_t hi2;
108 uint32_t lo2;
109 uint32_t hi3;
110 uint32_t lo3;
111 } mcontext_t;
112
113 typedef struct ucontext {
114 uint32_t uc_flags;
115 struct ucontext* uc_link;
116 stack_t uc_stack;
117 mcontext_t uc_mcontext;
118 // Other fields are not used by V8, don't define them here.
119 } ucontext_t;
120
121 #elif defined(__i386__)
122 // x86 version for Android.
123 typedef struct {
124 uint32_t gregs[19];
125 void* fpregs;
126 uint32_t oldmask;
127 uint32_t cr2;
128 } mcontext_t;
129
130 typedef uint32_t kernel_sigset_t[2]; // x86 kernel uses 64-bit signal masks
131 typedef struct ucontext {
132 uint32_t uc_flags;
133 struct ucontext* uc_link;
134 stack_t uc_stack;
135 mcontext_t uc_mcontext;
136 // Other fields are not used by V8, don't define them here.
137 } ucontext_t;
138 enum { REG_EBP = 6, REG_ESP = 7, REG_EIP = 14 };
139
140 #elif defined(__x86_64__)
141 // x64 version for Android.
142 typedef struct {
143 uint64_t gregs[23];
144 void* fpregs;
145 uint64_t __reserved1[8];
146 } mcontext_t;
147
148 typedef struct ucontext {
149 uint64_t uc_flags;
150 struct ucontext *uc_link;
151 stack_t uc_stack;
152 mcontext_t uc_mcontext;
153 // Other fields are not used by V8, don't define them here.
154 } ucontext_t;
155 enum { REG_RBP = 10, REG_RSP = 15, REG_RIP = 16 };
156 #endif
157
158 #endif // V8_OS_ANDROID && !defined(__BIONIC_HAVE_UCONTEXT_T)
159
160
161 namespace v8 { 18 namespace v8 {
162 namespace internal { 19 namespace internal {
163 20
164 namespace { 21 namespace {
165 22
166 class PlatformDataCommon : public Malloced { 23 class PlatformDataCommon : public Malloced {
167 public: 24 public:
168 PlatformDataCommon() : profiled_thread_id_(ThreadId::Current()) {} 25 PlatformDataCommon() : profiled_thread_id_(ThreadId::Current()) {}
169 ThreadId profiled_thread_id() { return profiled_thread_id_; } 26 ThreadId profiled_thread_id() { return profiled_thread_id_; }
170 27
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
225 82
226 #if defined(USE_SIMULATOR) 83 #if defined(USE_SIMULATOR)
227 class SimulatorHelper { 84 class SimulatorHelper {
228 public: 85 public:
229 inline bool Init(Sampler* sampler, Isolate* isolate) { 86 inline bool Init(Sampler* sampler, Isolate* isolate) {
230 simulator_ = isolate->thread_local_top()->simulator_; 87 simulator_ = isolate->thread_local_top()->simulator_;
231 // Check if there is active simulator. 88 // Check if there is active simulator.
232 return simulator_ != NULL; 89 return simulator_ != NULL;
233 } 90 }
234 91
235 inline void FillRegisters(RegisterState* state) { 92 inline void FillRegisters(v8::RegisterState* state) {
236 #if V8_TARGET_ARCH_ARM 93 #if V8_TARGET_ARCH_ARM
237 state->pc = reinterpret_cast<Address>(simulator_->get_pc()); 94 state->pc = reinterpret_cast<Address>(simulator_->get_pc());
238 state->sp = reinterpret_cast<Address>(simulator_->get_register( 95 state->sp = reinterpret_cast<Address>(simulator_->get_register(
239 Simulator::sp)); 96 Simulator::sp));
240 state->fp = reinterpret_cast<Address>(simulator_->get_register( 97 state->fp = reinterpret_cast<Address>(simulator_->get_register(
241 Simulator::r11)); 98 Simulator::r11));
242 #elif V8_TARGET_ARCH_ARM64 99 #elif V8_TARGET_ARCH_ARM64
243 if (simulator_->sp() == 0 || simulator_->fp() == 0) { 100 if (simulator_->sp() == 0 || simulator_->fp() == 0) {
244 // It possible that the simulator is interrupted while it is updating 101 // It possible that the simulator is interrupted while it is updating
245 // the sp or fp register. ARM64 simulator does this in two steps: 102 // the sp or fp register. ARM64 simulator does this in two steps:
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after
346 return; 203 return;
347 } 204 }
348 if (v8::Locker::IsActive() && 205 if (v8::Locker::IsActive() &&
349 !isolate->thread_manager()->IsLockedByCurrentThread()) { 206 !isolate->thread_manager()->IsLockedByCurrentThread()) {
350 return; 207 return;
351 } 208 }
352 209
353 Sampler* sampler = isolate->logger()->sampler(); 210 Sampler* sampler = isolate->logger()->sampler();
354 if (sampler == NULL) return; 211 if (sampler == NULL) return;
355 212
356 RegisterState state; 213 v8::RegisterState state;
357 214
358 #if defined(USE_SIMULATOR) 215 #if defined(USE_SIMULATOR)
359 SimulatorHelper helper; 216 SimulatorHelper helper;
360 if (!helper.Init(sampler, isolate)) return; 217 if (!helper.Init(sampler, isolate)) return;
361 helper.FillRegisters(&state); 218 helper.FillRegisters(&state);
362 // It possible that the simulator is interrupted while it is updating 219 // It possible that the simulator is interrupted while it is updating
363 // the sp or fp register. ARM64 simulator does this in two steps: 220 // the sp or fp register. ARM64 simulator does this in two steps:
364 // first setting it to zero and then setting it to the new value. 221 // first setting it to zero and then setting it to the new value.
365 // Bailout if sp/fp doesn't contain the new value. 222 // Bailout if sp/fp doesn't contain the new value.
366 if (state.sp == 0 || state.fp == 0) return; 223 if (state.sp == 0 || state.fp == 0) return;
(...skipping 203 matching lines...) Expand 10 before | Expand all | Expand 10 after
570 427
571 428
572 base::Mutex* SamplerThread::mutex_ = NULL; 429 base::Mutex* SamplerThread::mutex_ = NULL;
573 SamplerThread* SamplerThread::instance_ = NULL; 430 SamplerThread* SamplerThread::instance_ = NULL;
574 431
575 432
576 // 433 //
577 // StackTracer implementation 434 // StackTracer implementation
578 // 435 //
579 DISABLE_ASAN void TickSample::Init(Isolate* isolate, 436 DISABLE_ASAN void TickSample::Init(Isolate* isolate,
580 const RegisterState& regs) { 437 const v8::RegisterState& regs) {
581 DCHECK(isolate->IsInitialized()); 438 DCHECK(isolate->IsInitialized());
582 timestamp = base::TimeTicks::HighResolutionNow(); 439 timestamp = base::TimeTicks::HighResolutionNow();
583 pc = regs.pc; 440 pc = reinterpret_cast<Address>(regs.pc);
584 state = isolate->current_vm_state(); 441 state = isolate->current_vm_state();
585 442
586 // Avoid collecting traces while doing GC. 443 // Avoid collecting traces while doing GC.
587 if (state == GC) return; 444 if (state == GC) return;
588 445
589 Address js_entry_sp = isolate->js_entry_sp(); 446 Address js_entry_sp = isolate->js_entry_sp();
590 if (js_entry_sp == 0) { 447 if (js_entry_sp == 0) {
591 // Not executing JS now. 448 // Not executing JS now.
592 return; 449 return;
593 } 450 }
594 451
595 ExternalCallbackScope* scope = isolate->external_callback_scope(); 452 ExternalCallbackScope* scope = isolate->external_callback_scope();
596 Address handler = Isolate::handler(isolate->thread_local_top()); 453 Address handler = Isolate::handler(isolate->thread_local_top());
597 // If there is a handler on top of the external callback scope then 454 // If there is a handler on top of the external callback scope then
598 // we have already entrered JavaScript again and the external callback 455 // we have already entrered JavaScript again and the external callback
599 // is not the top function. 456 // is not the top function.
600 if (scope && scope->scope_address() < handler) { 457 if (scope && scope->scope_address() < handler) {
601 external_callback = scope->callback(); 458 external_callback = scope->callback();
602 has_external_callback = true; 459 has_external_callback = true;
603 } else { 460 } else {
604 // Sample potential return address value for frameless invocation of 461 // Sample potential return address value for frameless invocation of
605 // stubs (we'll figure out later, if this value makes sense). 462 // stubs (we'll figure out later, if this value makes sense).
606 tos = Memory::Address_at(regs.sp); 463 tos = Memory::Address_at(reinterpret_cast<Address>(regs.sp));
607 has_external_callback = false; 464 has_external_callback = false;
608 } 465 }
609 466
610 SafeStackFrameIterator it(isolate, regs.fp, regs.sp, js_entry_sp); 467 SafeStackFrameIterator it(isolate,
468 reinterpret_cast<Address>(regs.fp),
469 reinterpret_cast<Address>(regs.sp),
470 js_entry_sp);
611 top_frame_type = it.top_frame_type(); 471 top_frame_type = it.top_frame_type();
612 unsigned i = 0; 472 unsigned i = 0;
613 while (!it.done() && i < TickSample::kMaxFramesCount) { 473 while (!it.done() && i < TickSample::kMaxFramesCount) {
614 stack[i++] = it.frame()->pc(); 474 stack[i++] = it.frame()->pc();
615 it.Advance(); 475 it.Advance();
616 } 476 }
617 frames_count = i; 477 frames_count = i;
618 } 478 }
619 479
620 480
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
675 535
676 536
677 void Sampler::DecreaseProfilingDepth() { 537 void Sampler::DecreaseProfilingDepth() {
678 #if defined(USE_SIGNALS) 538 #if defined(USE_SIGNALS)
679 SignalHandler::DecreaseSamplerCount(); 539 SignalHandler::DecreaseSamplerCount();
680 #endif 540 #endif
681 base::NoBarrier_AtomicIncrement(&profiling_, -1); 541 base::NoBarrier_AtomicIncrement(&profiling_, -1);
682 } 542 }
683 543
684 544
685 void Sampler::SampleStack(const RegisterState& state) { 545 void Sampler::SampleStack(const v8::RegisterState& state) {
686 TickSample* sample = isolate_->cpu_profiler()->StartTickSample(); 546 TickSample* sample = isolate_->cpu_profiler()->StartTickSample();
687 TickSample sample_obj; 547 TickSample sample_obj;
688 if (sample == NULL) sample = &sample_obj; 548 if (sample == NULL) sample = &sample_obj;
689 sample->Init(isolate_, state); 549 sample->Init(isolate_, state);
690 if (is_counting_samples_) { 550 if (is_counting_samples_) {
691 if (sample->state == JS || sample->state == EXTERNAL) { 551 if (sample->state == JS || sample->state == EXTERNAL) {
692 ++js_and_external_sample_count_; 552 ++js_and_external_sample_count_;
693 } 553 }
694 } 554 }
695 Tick(sample); 555 Tick(sample);
696 if (sample != &sample_obj) { 556 if (sample != &sample_obj) {
697 isolate_->cpu_profiler()->FinishTickSample(); 557 isolate_->cpu_profiler()->FinishTickSample();
698 } 558 }
699 } 559 }
700 560
701 561
562 int Sampler::GetSample(Isolate* isolate,
563 const v8::RegisterState& state,
564 void** buffer,
565 unsigned int depth) {
566 DCHECK(isolate->IsInitialized());
567
568 // Avoid collecting traces while doing GC.
569 if (isolate->current_vm_state() == GC) return -1;
570
571 fprintf(stderr, "sp:%p\nfp:%p\npc:%p\ndepth:%d\n",
572 state.sp,
573 state.fp,
574 state.pc,
575 depth);
576 Address js_entry_sp = isolate->js_entry_sp();
577 if (js_entry_sp == 0) {
578 fprintf(stderr, "js_entry_sp is zero.\n");
579 return 0; // Not executing JS now.
580 }
581
582
583 SafeStackFrameIterator it(isolate,
584 reinterpret_cast<Address>(state.fp),
585 reinterpret_cast<Address>(state.sp),
586 js_entry_sp);
587 unsigned i = 0;
588 while (!it.done() && i < depth) {
589 buffer[i++] = it.frame()->pc();
590 it.Advance();
591 }
592 fprintf(stderr, "GetSample returning %d\n", i);
593 return i;
594 }
595
596
702 #if defined(USE_SIGNALS) 597 #if defined(USE_SIGNALS)
703 598
704 void Sampler::DoSample() { 599 void Sampler::DoSample() {
705 if (!SignalHandler::Installed()) return; 600 if (!SignalHandler::Installed()) return;
706 pthread_kill(platform_data()->vm_tid(), SIGPROF); 601 pthread_kill(platform_data()->vm_tid(), SIGPROF);
707 } 602 }
708 603
709 #elif V8_OS_WIN || V8_OS_CYGWIN 604 #elif V8_OS_WIN || V8_OS_CYGWIN
710 605
711 void Sampler::DoSample() { 606 void Sampler::DoSample() {
712 HANDLE profiled_thread = platform_data()->profiled_thread(); 607 HANDLE profiled_thread = platform_data()->profiled_thread();
713 if (profiled_thread == NULL) return; 608 if (profiled_thread == NULL) return;
714 609
715 #if defined(USE_SIMULATOR) 610 #if defined(USE_SIMULATOR)
716 SimulatorHelper helper; 611 SimulatorHelper helper;
717 if (!helper.Init(this, isolate())) return; 612 if (!helper.Init(this, isolate())) return;
718 #endif 613 #endif
719 614
720 const DWORD kSuspendFailed = static_cast<DWORD>(-1); 615 const DWORD kSuspendFailed = static_cast<DWORD>(-1);
721 if (SuspendThread(profiled_thread) == kSuspendFailed) return; 616 if (SuspendThread(profiled_thread) == kSuspendFailed) return;
722 617
723 // Context used for sampling the register state of the profiled thread. 618 // Context used for sampling the register state of the profiled thread.
724 CONTEXT context; 619 CONTEXT context;
725 memset(&context, 0, sizeof(context)); 620 memset(&context, 0, sizeof(context));
726 context.ContextFlags = CONTEXT_FULL; 621 context.ContextFlags = CONTEXT_FULL;
727 if (GetThreadContext(profiled_thread, &context) != 0) { 622 if (GetThreadContext(profiled_thread, &context) != 0) {
728 RegisterState state; 623 v8::RegisterState state;
729 #if defined(USE_SIMULATOR) 624 #if defined(USE_SIMULATOR)
730 helper.FillRegisters(&state); 625 helper.FillRegisters(&state);
731 #else 626 #else
732 #if V8_HOST_ARCH_X64 627 #if V8_HOST_ARCH_X64
733 state.pc = reinterpret_cast<Address>(context.Rip); 628 state.pc = reinterpret_cast<Address>(context.Rip);
734 state.sp = reinterpret_cast<Address>(context.Rsp); 629 state.sp = reinterpret_cast<Address>(context.Rsp);
735 state.fp = reinterpret_cast<Address>(context.Rbp); 630 state.fp = reinterpret_cast<Address>(context.Rbp);
736 #else 631 #else
737 state.pc = reinterpret_cast<Address>(context.Eip); 632 state.pc = reinterpret_cast<Address>(context.Eip);
738 state.sp = reinterpret_cast<Address>(context.Esp); 633 state.sp = reinterpret_cast<Address>(context.Esp);
739 state.fp = reinterpret_cast<Address>(context.Ebp); 634 state.fp = reinterpret_cast<Address>(context.Ebp);
740 #endif 635 #endif
741 #endif // USE_SIMULATOR 636 #endif // USE_SIMULATOR
742 SampleStack(state); 637 SampleStack(state);
743 } 638 }
744 ResumeThread(profiled_thread); 639 ResumeThread(profiled_thread);
745 } 640 }
746 641
747 #endif // USE_SIGNALS 642 #endif // USE_SIGNALS
748 643
749 644
750 } } // namespace v8::internal 645 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/sampler.h ('k') | test/cctest/cctest.gyp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698