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

Side by Side Diff: src/sampler.cc

Issue 151163005: A64: Synchronize with r16356. (Closed) Base URL: https://v8.googlecode.com/svn/branches/experimental/a64
Patch Set: Created 6 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 unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/sampler.h ('k') | src/scopes.cc » ('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 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
(...skipping 11 matching lines...) Expand all
22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 27
28 #include "sampler.h" 28 #include "sampler.h"
29 29
30 #if defined(__linux__) || defined(__FreeBSD__) || defined(__OpenBSD__) \ 30 #if defined(__linux__) || defined(__FreeBSD__) || defined(__OpenBSD__) \
31 || defined(__NetBSD__) || defined(__sun) || defined(__ANDROID__) \ 31 || defined(__NetBSD__) || defined(__sun) || defined(__ANDROID__) \
32 || defined(__native_client__) 32 || defined(__native_client__) || defined(__MACH__)
33 33
34 #define USE_SIGNALS 34 #define USE_SIGNALS
35 35
36 #include <errno.h> 36 #include <errno.h>
37 #include <pthread.h> 37 #include <pthread.h>
38 #include <signal.h> 38 #include <signal.h>
39 #include <sys/time.h> 39 #include <sys/time.h>
40 #include <sys/syscall.h> 40 #include <sys/syscall.h>
41
42 #if defined(__MACH__)
43 #include <mach/mach.h>
41 // OpenBSD doesn't have <ucontext.h>. ucontext_t lives in <signal.h> 44 // OpenBSD doesn't have <ucontext.h>. ucontext_t lives in <signal.h>
42 // and is a typedef for struct sigcontext. There is no uc_mcontext. 45 // and is a typedef for struct sigcontext. There is no uc_mcontext.
43 #if (!defined(__ANDROID__) || defined(__BIONIC_HAVE_UCONTEXT_T)) \ 46 #elif(!defined(__ANDROID__) || defined(__BIONIC_HAVE_UCONTEXT_T)) \
44 && !defined(__OpenBSD__) 47 && !defined(__OpenBSD__)
45 #include <ucontext.h> 48 #include <ucontext.h>
46 #endif 49 #endif
47 #include <unistd.h> 50 #include <unistd.h>
48 51
49 // GLibc on ARM defines mcontext_t has a typedef for 'struct sigcontext'. 52 // GLibc on ARM defines mcontext_t has a typedef for 'struct sigcontext'.
50 // Old versions of the C library <signal.h> didn't define the type. 53 // Old versions of the C library <signal.h> didn't define the type.
51 #if defined(__ANDROID__) && !defined(__BIONIC_HAVE_UCONTEXT_T) && \ 54 #if defined(__ANDROID__) && !defined(__BIONIC_HAVE_UCONTEXT_T) && \
52 (defined(__arm__) || defined(__aarch64__)) && \ 55 (defined(__arm__) || defined(__aarch64__)) && \
53 !defined(__BIONIC_HAVE_STRUCT_SIGCONTEXT) 56 !defined(__BIONIC_HAVE_STRUCT_SIGCONTEXT)
54 #include <asm/sigcontext.h> 57 #include <asm/sigcontext.h>
55 #endif 58 #endif
56 59
57 #elif defined(__MACH__)
58
59 #include <mach/mach.h>
60
61 #elif defined(_WIN32) || defined(_WIN64) || defined(__CYGWIN__) 60 #elif defined(_WIN32) || defined(_WIN64) || defined(__CYGWIN__)
62 61
63 #include "win32-headers.h" 62 #include "win32-headers.h"
64 63
65 #endif 64 #endif
66 65
67 #include "v8.h" 66 #include "v8.h"
68 67
69 #include "cpu-profiler.h" 68 #include "cpu-profiler-inl.h"
70 #include "flags.h" 69 #include "flags.h"
71 #include "frames-inl.h" 70 #include "frames-inl.h"
72 #include "log.h" 71 #include "log.h"
73 #include "platform.h" 72 #include "platform.h"
74 #include "simulator.h" 73 #include "simulator.h"
75 #include "v8threads.h" 74 #include "v8threads.h"
76 #include "vm-state-inl.h" 75 #include "vm-state-inl.h"
77 76
78 77
79 #if defined(__ANDROID__) && !defined(__BIONIC_HAVE_UCONTEXT_T) 78 #if defined(__ANDROID__) && !defined(__BIONIC_HAVE_UCONTEXT_T)
(...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after
186 185
187 class Sampler::PlatformData : public PlatformDataCommon { 186 class Sampler::PlatformData : public PlatformDataCommon {
188 public: 187 public:
189 PlatformData() : vm_tid_(pthread_self()) {} 188 PlatformData() : vm_tid_(pthread_self()) {}
190 pthread_t vm_tid() const { return vm_tid_; } 189 pthread_t vm_tid() const { return vm_tid_; }
191 190
192 private: 191 private:
193 pthread_t vm_tid_; 192 pthread_t vm_tid_;
194 }; 193 };
195 194
196 #elif defined(__MACH__)
197
198 class Sampler::PlatformData : public PlatformDataCommon {
199 public:
200 PlatformData() : profiled_thread_(mach_thread_self()) {}
201
202 ~PlatformData() {
203 // Deallocate Mach port for thread.
204 mach_port_deallocate(mach_task_self(), profiled_thread_);
205 }
206
207 thread_act_t profiled_thread() { return profiled_thread_; }
208
209 private:
210 // Note: for profiled_thread_ Mach primitives are used instead of PThread's
211 // because the latter doesn't provide thread manipulation primitives required.
212 // For details, consult "Mac OS X Internals" book, Section 7.3.
213 thread_act_t profiled_thread_;
214 };
215
216 #elif defined(_WIN32) || defined(_WIN64) || defined(__CYGWIN__) 195 #elif defined(_WIN32) || defined(_WIN64) || defined(__CYGWIN__)
217 196
218 // ---------------------------------------------------------------------------- 197 // ----------------------------------------------------------------------------
219 // Win32 profiler support. On Cygwin we use the same sampler implementation as 198 // Win32 profiler support. On Cygwin we use the same sampler implementation as
220 // on Win32. 199 // on Win32.
221 200
222 class Sampler::PlatformData : public PlatformDataCommon { 201 class Sampler::PlatformData : public PlatformDataCommon {
223 public: 202 public:
224 // Get a handle to the calling thread. This is the thread that we are 203 // Get a handle to the calling thread. This is the thread that we are
225 // going to profile. We need to make a copy of the handle because we are 204 // going to profile. We need to make a copy of the handle because we are
(...skipping 168 matching lines...) Expand 10 before | Expand all | Expand 10 after
394 #elif V8_HOST_ARCH_A64 373 #elif V8_HOST_ARCH_A64
395 state.pc = reinterpret_cast<Address>(mcontext.pc); 374 state.pc = reinterpret_cast<Address>(mcontext.pc);
396 state.sp = reinterpret_cast<Address>(mcontext.sp); 375 state.sp = reinterpret_cast<Address>(mcontext.sp);
397 // FP is an alias for x29. 376 // FP is an alias for x29.
398 state.fp = reinterpret_cast<Address>(mcontext.regs[29]); 377 state.fp = reinterpret_cast<Address>(mcontext.regs[29]);
399 #elif V8_HOST_ARCH_MIPS 378 #elif V8_HOST_ARCH_MIPS
400 state.pc = reinterpret_cast<Address>(mcontext.pc); 379 state.pc = reinterpret_cast<Address>(mcontext.pc);
401 state.sp = reinterpret_cast<Address>(mcontext.gregs[29]); 380 state.sp = reinterpret_cast<Address>(mcontext.gregs[29]);
402 state.fp = reinterpret_cast<Address>(mcontext.gregs[30]); 381 state.fp = reinterpret_cast<Address>(mcontext.gregs[30]);
403 #endif // V8_HOST_ARCH_* 382 #endif // V8_HOST_ARCH_*
383 #elif defined(__MACH__)
384 #if V8_HOST_ARCH_X64
385 #if __DARWIN_UNIX03
386 state.pc = reinterpret_cast<Address>(mcontext->__ss.__rip);
387 state.sp = reinterpret_cast<Address>(mcontext->__ss.__rsp);
388 state.fp = reinterpret_cast<Address>(mcontext->__ss.__rbp);
389 #else // !__DARWIN_UNIX03
390 state.pc = reinterpret_cast<Address>(mcontext->ss.rip);
391 state.sp = reinterpret_cast<Address>(mcontext->ss.rsp);
392 state.fp = reinterpret_cast<Address>(mcontext->ss.rbp);
393 #endif // __DARWIN_UNIX03
394 #elif V8_HOST_ARCH_IA32
395 #if __DARWIN_UNIX03
396 state.pc = reinterpret_cast<Address>(mcontext->__ss.__eip);
397 state.sp = reinterpret_cast<Address>(mcontext->__ss.__esp);
398 state.fp = reinterpret_cast<Address>(mcontext->__ss.__ebp);
399 #else // !__DARWIN_UNIX03
400 state.pc = reinterpret_cast<Address>(mcontext->ss.eip);
401 state.sp = reinterpret_cast<Address>(mcontext->ss.esp);
402 state.fp = reinterpret_cast<Address>(mcontext->ss.ebp);
403 #endif // __DARWIN_UNIX03
404 #endif // V8_HOST_ARCH_IA32
404 #elif defined(__FreeBSD__) 405 #elif defined(__FreeBSD__)
405 #if V8_HOST_ARCH_IA32 406 #if V8_HOST_ARCH_IA32
406 state.pc = reinterpret_cast<Address>(mcontext.mc_eip); 407 state.pc = reinterpret_cast<Address>(mcontext.mc_eip);
407 state.sp = reinterpret_cast<Address>(mcontext.mc_esp); 408 state.sp = reinterpret_cast<Address>(mcontext.mc_esp);
408 state.fp = reinterpret_cast<Address>(mcontext.mc_ebp); 409 state.fp = reinterpret_cast<Address>(mcontext.mc_ebp);
409 #elif V8_HOST_ARCH_X64 410 #elif V8_HOST_ARCH_X64
410 state.pc = reinterpret_cast<Address>(mcontext.mc_rip); 411 state.pc = reinterpret_cast<Address>(mcontext.mc_rip);
411 state.sp = reinterpret_cast<Address>(mcontext.mc_rsp); 412 state.sp = reinterpret_cast<Address>(mcontext.mc_rsp);
412 state.fp = reinterpret_cast<Address>(mcontext.mc_rbp); 413 state.fp = reinterpret_cast<Address>(mcontext.mc_rbp);
413 #elif V8_HOST_ARCH_ARM 414 #elif V8_HOST_ARCH_ARM
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after
511 while (true) { 512 while (true) {
512 { 513 {
513 ScopedLock lock(mutex_); 514 ScopedLock lock(mutex_);
514 if (active_samplers_.is_empty()) break; 515 if (active_samplers_.is_empty()) break;
515 // When CPU profiling is enabled both JavaScript and C++ code is 516 // When CPU profiling is enabled both JavaScript and C++ code is
516 // profiled. We must not suspend. 517 // profiled. We must not suspend.
517 for (int i = 0; i < active_samplers_.length(); ++i) { 518 for (int i = 0; i < active_samplers_.length(); ++i) {
518 Sampler* sampler = active_samplers_.at(i); 519 Sampler* sampler = active_samplers_.at(i);
519 if (!sampler->isolate()->IsInitialized()) continue; 520 if (!sampler->isolate()->IsInitialized()) continue;
520 if (!sampler->IsProfiling()) continue; 521 if (!sampler->IsProfiling()) continue;
521 SampleContext(sampler); 522 sampler->DoSample();
522 } 523 }
523 } 524 }
524 OS::Sleep(interval_); 525 OS::Sleep(interval_);
525 } 526 }
526 } 527 }
527 528
528 private: 529 private:
529 #if defined(USE_SIGNALS)
530
531 void SampleContext(Sampler* sampler) {
532 if (!SignalHandler::Installed()) return;
533 pthread_t tid = sampler->platform_data()->vm_tid();
534 pthread_kill(tid, SIGPROF);
535 }
536
537 #elif defined(__MACH__)
538
539 void SampleContext(Sampler* sampler) {
540 thread_act_t profiled_thread = sampler->platform_data()->profiled_thread();
541
542 #if defined(USE_SIMULATOR)
543 SimulatorHelper helper;
544 Isolate* isolate = sampler->isolate();
545 if (!helper.Init(sampler, isolate)) return;
546 #endif
547
548 if (KERN_SUCCESS != thread_suspend(profiled_thread)) return;
549
550 #if V8_HOST_ARCH_X64
551 thread_state_flavor_t flavor = x86_THREAD_STATE64;
552 x86_thread_state64_t thread_state;
553 mach_msg_type_number_t count = x86_THREAD_STATE64_COUNT;
554 #if __DARWIN_UNIX03
555 #define REGISTER_FIELD(name) __r ## name
556 #else
557 #define REGISTER_FIELD(name) r ## name
558 #endif // __DARWIN_UNIX03
559 #elif V8_HOST_ARCH_IA32
560 thread_state_flavor_t flavor = i386_THREAD_STATE;
561 i386_thread_state_t thread_state;
562 mach_msg_type_number_t count = i386_THREAD_STATE_COUNT;
563 #if __DARWIN_UNIX03
564 #define REGISTER_FIELD(name) __e ## name
565 #else
566 #define REGISTER_FIELD(name) e ## name
567 #endif // __DARWIN_UNIX03
568 #else
569 #error Unsupported Mac OS X host architecture.
570 #endif // V8_HOST_ARCH
571
572 if (thread_get_state(profiled_thread,
573 flavor,
574 reinterpret_cast<natural_t*>(&thread_state),
575 &count) == KERN_SUCCESS) {
576 RegisterState state;
577 #if defined(USE_SIMULATOR)
578 helper.FillRegisters(&state);
579 #else
580 state.pc = reinterpret_cast<Address>(thread_state.REGISTER_FIELD(ip));
581 state.sp = reinterpret_cast<Address>(thread_state.REGISTER_FIELD(sp));
582 state.fp = reinterpret_cast<Address>(thread_state.REGISTER_FIELD(bp));
583 #endif // USE_SIMULATOR
584 #undef REGISTER_FIELD
585 sampler->SampleStack(state);
586 }
587 thread_resume(profiled_thread);
588 }
589
590 #elif defined(_WIN32) || defined(_WIN64) || defined(__CYGWIN__)
591
592 void SampleContext(Sampler* sampler) {
593 HANDLE profiled_thread = sampler->platform_data()->profiled_thread();
594 if (profiled_thread == NULL) return;
595
596 Isolate* isolate = sampler->isolate();
597 #if defined(USE_SIMULATOR)
598 SimulatorHelper helper;
599 if (!helper.Init(sampler, isolate)) return;
600 #endif
601
602 const DWORD kSuspendFailed = static_cast<DWORD>(-1);
603 if (SuspendThread(profiled_thread) == kSuspendFailed) return;
604
605 // Context used for sampling the register state of the profiled thread.
606 CONTEXT context;
607 memset(&context, 0, sizeof(context));
608 context.ContextFlags = CONTEXT_FULL;
609 if (GetThreadContext(profiled_thread, &context) != 0) {
610 RegisterState state;
611 #if defined(USE_SIMULATOR)
612 helper.FillRegisters(&state);
613 #else
614 #if V8_HOST_ARCH_X64
615 state.pc = reinterpret_cast<Address>(context.Rip);
616 state.sp = reinterpret_cast<Address>(context.Rsp);
617 state.fp = reinterpret_cast<Address>(context.Rbp);
618 #else
619 state.pc = reinterpret_cast<Address>(context.Eip);
620 state.sp = reinterpret_cast<Address>(context.Esp);
621 state.fp = reinterpret_cast<Address>(context.Ebp);
622 #endif
623 #endif // USE_SIMULATOR
624 sampler->SampleStack(state);
625 }
626 ResumeThread(profiled_thread);
627 }
628
629 #endif // USE_SIGNALS
630
631
632 // Protects the process wide state below. 530 // Protects the process wide state below.
633 static Mutex* mutex_; 531 static Mutex* mutex_;
634 static SamplerThread* instance_; 532 static SamplerThread* instance_;
635 533
636 const int interval_; 534 const int interval_;
637 List<Sampler*> active_samplers_; 535 List<Sampler*> active_samplers_;
638 536
639 DISALLOW_COPY_AND_ASSIGN(SamplerThread); 537 DISALLOW_COPY_AND_ASSIGN(SamplerThread);
640 }; 538 };
641 539
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
695 593
696 void Sampler::TearDown() { 594 void Sampler::TearDown() {
697 SamplerThread::TearDown(); 595 SamplerThread::TearDown();
698 } 596 }
699 597
700 598
701 Sampler::Sampler(Isolate* isolate, int interval) 599 Sampler::Sampler(Isolate* isolate, int interval)
702 : isolate_(isolate), 600 : isolate_(isolate),
703 interval_(interval), 601 interval_(interval),
704 profiling_(false), 602 profiling_(false),
603 has_processing_thread_(false),
705 active_(false), 604 active_(false),
706 is_counting_samples_(false), 605 is_counting_samples_(false),
707 js_and_external_sample_count_(0) { 606 js_and_external_sample_count_(0) {
708 data_ = new PlatformData; 607 data_ = new PlatformData;
709 } 608 }
710 609
711 610
712 Sampler::~Sampler() { 611 Sampler::~Sampler() {
713 ASSERT(!IsActive()); 612 ASSERT(!IsActive());
714 delete data_; 613 delete data_;
715 } 614 }
716 615
717 616
718 void Sampler::Start() { 617 void Sampler::Start() {
719 ASSERT(!IsActive()); 618 ASSERT(!IsActive());
720 SetActive(true); 619 SetActive(true);
721 SamplerThread::AddActiveSampler(this); 620 SamplerThread::AddActiveSampler(this);
722 } 621 }
723 622
724 623
725 void Sampler::Stop() { 624 void Sampler::Stop() {
726 ASSERT(IsActive()); 625 ASSERT(IsActive());
727 SamplerThread::RemoveActiveSampler(this); 626 SamplerThread::RemoveActiveSampler(this);
728 SetActive(false); 627 SetActive(false);
729 } 628 }
730 629
731 630
732 void Sampler::SampleStack(const RegisterState& state) { 631 void Sampler::SampleStack(const RegisterState& state) {
733 TickSample* sample = isolate_->cpu_profiler()->TickSampleEvent(); 632 TickSample* sample = isolate_->cpu_profiler()->StartTickSample();
734 TickSample sample_obj; 633 TickSample sample_obj;
735 if (sample == NULL) sample = &sample_obj; 634 if (sample == NULL) sample = &sample_obj;
736 sample->Init(isolate_, state); 635 sample->Init(isolate_, state);
737 if (is_counting_samples_) { 636 if (is_counting_samples_) {
738 if (sample->state == JS || sample->state == EXTERNAL) { 637 if (sample->state == JS || sample->state == EXTERNAL) {
739 ++js_and_external_sample_count_; 638 ++js_and_external_sample_count_;
740 } 639 }
741 } 640 }
742 Tick(sample); 641 Tick(sample);
642 if (sample != &sample_obj) {
643 isolate_->cpu_profiler()->FinishTickSample();
644 }
743 } 645 }
744 646
647
648 bool Sampler::CanSampleOnProfilerEventsProcessorThread() {
649 #if defined(USE_SIGNALS)
650 return true;
651 #else
652 return false;
653 #endif
654 }
655
656
657 #if defined(USE_SIGNALS)
658
659 void Sampler::DoSample() {
660 if (!SignalHandler::Installed()) return;
661 pthread_kill(platform_data()->vm_tid(), SIGPROF);
662 }
663
664 #elif defined(_WIN32) || defined(_WIN64) || defined(__CYGWIN__)
665
666 void Sampler::DoSample() {
667 HANDLE profiled_thread = platform_data()->profiled_thread();
668 if (profiled_thread == NULL) return;
669
670 #if defined(USE_SIMULATOR)
671 SimulatorHelper helper;
672 if (!helper.Init(this, isolate())) return;
673 #endif
674
675 const DWORD kSuspendFailed = static_cast<DWORD>(-1);
676 if (SuspendThread(profiled_thread) == kSuspendFailed) return;
677
678 // Context used for sampling the register state of the profiled thread.
679 CONTEXT context;
680 memset(&context, 0, sizeof(context));
681 context.ContextFlags = CONTEXT_FULL;
682 if (GetThreadContext(profiled_thread, &context) != 0) {
683 RegisterState state;
684 #if defined(USE_SIMULATOR)
685 helper.FillRegisters(&state);
686 #else
687 #if V8_HOST_ARCH_X64
688 state.pc = reinterpret_cast<Address>(context.Rip);
689 state.sp = reinterpret_cast<Address>(context.Rsp);
690 state.fp = reinterpret_cast<Address>(context.Rbp);
691 #else
692 state.pc = reinterpret_cast<Address>(context.Eip);
693 state.sp = reinterpret_cast<Address>(context.Esp);
694 state.fp = reinterpret_cast<Address>(context.Ebp);
695 #endif
696 #endif // USE_SIMULATOR
697 SampleStack(state);
698 }
699 ResumeThread(profiled_thread);
700 }
701
702 #endif // USE_SIGNALS
703
704
745 } } // namespace v8::internal 705 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/sampler.h ('k') | src/scopes.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698