OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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 25 matching lines...) Expand all Loading... |
36 #include <sys/time.h> | 36 #include <sys/time.h> |
37 #include <sys/mman.h> // mmap & munmap | 37 #include <sys/mman.h> // mmap & munmap |
38 #include <unistd.h> // sysconf | 38 #include <unistd.h> // sysconf |
39 | 39 |
40 #undef MAP_TYPE | 40 #undef MAP_TYPE |
41 | 41 |
42 #include "v8.h" | 42 #include "v8.h" |
43 | 43 |
44 #include "platform-posix.h" | 44 #include "platform-posix.h" |
45 #include "platform.h" | 45 #include "platform.h" |
| 46 #include "simulator.h" |
46 #include "v8threads.h" | 47 #include "v8threads.h" |
47 #include "vm-state-inl.h" | 48 #include "vm-state-inl.h" |
48 #include "win32-headers.h" | 49 #include "win32-headers.h" |
49 | 50 |
50 namespace v8 { | 51 namespace v8 { |
51 namespace internal { | 52 namespace internal { |
52 | 53 |
53 // 0 is never a valid thread id | 54 // 0 is never a valid thread id |
54 static const pthread_t kNoThread = (pthread_t) 0; | 55 static const pthread_t kNoThread = (pthread_t) 0; |
55 | 56 |
(...skipping 541 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
597 // | 598 // |
598 // On Cygwin we use the same sampler implementation as on win32. | 599 // On Cygwin we use the same sampler implementation as on win32. |
599 | 600 |
600 class Sampler::PlatformData : public Malloced { | 601 class Sampler::PlatformData : public Malloced { |
601 public: | 602 public: |
602 // Get a handle to the calling thread. This is the thread that we are | 603 // Get a handle to the calling thread. This is the thread that we are |
603 // going to profile. We need to make a copy of the handle because we are | 604 // going to profile. We need to make a copy of the handle because we are |
604 // going to use it in the sampler thread. Using GetThreadHandle() will | 605 // going to use it in the sampler thread. Using GetThreadHandle() will |
605 // not work in this case. We're using OpenThread because DuplicateHandle | 606 // not work in this case. We're using OpenThread because DuplicateHandle |
606 // for some reason doesn't work in Chrome's sandbox. | 607 // for some reason doesn't work in Chrome's sandbox. |
607 PlatformData() : profiled_thread_(OpenThread(THREAD_GET_CONTEXT | | 608 PlatformData() |
608 THREAD_SUSPEND_RESUME | | 609 : profiled_thread_(OpenThread(THREAD_GET_CONTEXT | |
609 THREAD_QUERY_INFORMATION, | 610 THREAD_SUSPEND_RESUME | |
610 false, | 611 THREAD_QUERY_INFORMATION, |
611 GetCurrentThreadId())) {} | 612 false, |
| 613 GetCurrentThreadId())), |
| 614 profiled_thread_id_(ThreadId::Current()) {} |
612 | 615 |
613 ~PlatformData() { | 616 ~PlatformData() { |
614 if (profiled_thread_ != NULL) { | 617 if (profiled_thread_ != NULL) { |
615 CloseHandle(profiled_thread_); | 618 CloseHandle(profiled_thread_); |
616 profiled_thread_ = NULL; | 619 profiled_thread_ = NULL; |
617 } | 620 } |
618 } | 621 } |
619 | 622 |
620 HANDLE profiled_thread() { return profiled_thread_; } | 623 HANDLE profiled_thread() { return profiled_thread_; } |
| 624 ThreadId profiled_thread_id() { return profiled_thread_id_; } |
621 | 625 |
622 private: | 626 private: |
623 HANDLE profiled_thread_; | 627 HANDLE profiled_thread_; |
| 628 ThreadId profiled_thread_id_; |
624 }; | 629 }; |
625 | 630 |
626 | 631 |
627 class SamplerThread : public Thread { | 632 class SamplerThread : public Thread { |
628 public: | 633 public: |
629 static const int kSamplerThreadStackSize = 64 * KB; | 634 static const int kSamplerThreadStackSize = 64 * KB; |
630 | 635 |
631 explicit SamplerThread(int interval) | 636 explicit SamplerThread(int interval) |
632 : Thread(Thread::Options("SamplerThread", kSamplerThreadStackSize)), | 637 : Thread(Thread::Options("SamplerThread", kSamplerThreadStackSize)), |
633 interval_(interval) {} | 638 interval_(interval) {} |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
680 | 685 |
681 void SampleContext(Sampler* sampler) { | 686 void SampleContext(Sampler* sampler) { |
682 HANDLE profiled_thread = sampler->platform_data()->profiled_thread(); | 687 HANDLE profiled_thread = sampler->platform_data()->profiled_thread(); |
683 if (profiled_thread == NULL) return; | 688 if (profiled_thread == NULL) return; |
684 | 689 |
685 // Context used for sampling the register state of the profiled thread. | 690 // Context used for sampling the register state of the profiled thread. |
686 CONTEXT context; | 691 CONTEXT context; |
687 memset(&context, 0, sizeof(context)); | 692 memset(&context, 0, sizeof(context)); |
688 | 693 |
689 Isolate* isolate = sampler->isolate(); | 694 Isolate* isolate = sampler->isolate(); |
| 695 #if defined(USE_SIMULATOR) |
| 696 #if V8_TARGET_ARCH_ARM || V8_TARGET_ARCH_MIPS |
| 697 ThreadId thread_id = sampler->platform_data()->profiled_thread_id(); |
| 698 Isolate::PerIsolateThreadData* per_thread_data = isolate-> |
| 699 FindPerThreadDataForThread(thread_id); |
| 700 if (!per_thread_data) return; |
| 701 Simulator* sim = per_thread_data->simulator(); |
| 702 // Check if there is active simulator before allocating TickSample. |
| 703 if (!sim) return; |
| 704 #endif |
| 705 #endif // USE_SIMULATOR |
690 TickSample sample_obj; | 706 TickSample sample_obj; |
691 TickSample* sample = isolate->cpu_profiler()->TickSampleEvent(); | 707 TickSample* sample = isolate->cpu_profiler()->TickSampleEvent(); |
692 if (sample == NULL) sample = &sample_obj; | 708 if (sample == NULL) sample = &sample_obj; |
693 | 709 |
694 static const DWORD kSuspendFailed = static_cast<DWORD>(-1); | 710 static const DWORD kSuspendFailed = static_cast<DWORD>(-1); |
695 if (SuspendThread(profiled_thread) == kSuspendFailed) return; | 711 if (SuspendThread(profiled_thread) == kSuspendFailed) return; |
696 sample->state = isolate->current_vm_state(); | 712 sample->state = isolate->current_vm_state(); |
697 | 713 |
698 context.ContextFlags = CONTEXT_FULL; | 714 context.ContextFlags = CONTEXT_FULL; |
699 if (GetThreadContext(profiled_thread, &context) != 0) { | 715 if (GetThreadContext(profiled_thread, &context) != 0) { |
| 716 #if defined(USE_SIMULATOR) |
| 717 #if V8_TARGET_ARCH_ARM |
| 718 sample->pc = reinterpret_cast<Address>(sim->get_register(Simulator::pc)); |
| 719 sample->sp = reinterpret_cast<Address>(sim->get_register(Simulator::sp)); |
| 720 sample->fp = reinterpret_cast<Address>(sim->get_register(Simulator::r11)); |
| 721 #elif V8_TARGET_ARCH_MIPS |
| 722 sample->pc = reinterpret_cast<Address>(sim->get_register(Simulator::pc)); |
| 723 sample->sp = reinterpret_cast<Address>(sim->get_register(Simulator::sp)); |
| 724 sample->fp = reinterpret_cast<Address>(sim->get_register(Simulator::fp)); |
| 725 #endif |
| 726 #else |
700 #if V8_HOST_ARCH_X64 | 727 #if V8_HOST_ARCH_X64 |
701 sample->pc = reinterpret_cast<Address>(context.Rip); | 728 sample->pc = reinterpret_cast<Address>(context.Rip); |
702 sample->sp = reinterpret_cast<Address>(context.Rsp); | 729 sample->sp = reinterpret_cast<Address>(context.Rsp); |
703 sample->fp = reinterpret_cast<Address>(context.Rbp); | 730 sample->fp = reinterpret_cast<Address>(context.Rbp); |
704 #else | 731 #else |
705 sample->pc = reinterpret_cast<Address>(context.Eip); | 732 sample->pc = reinterpret_cast<Address>(context.Eip); |
706 sample->sp = reinterpret_cast<Address>(context.Esp); | 733 sample->sp = reinterpret_cast<Address>(context.Esp); |
707 sample->fp = reinterpret_cast<Address>(context.Ebp); | 734 sample->fp = reinterpret_cast<Address>(context.Ebp); |
708 #endif | 735 #endif |
| 736 #endif // USE_SIMULATOR |
709 sampler->SampleStack(sample); | 737 sampler->SampleStack(sample); |
710 sampler->Tick(sample); | 738 sampler->Tick(sample); |
711 } | 739 } |
712 ResumeThread(profiled_thread); | 740 ResumeThread(profiled_thread); |
713 } | 741 } |
714 | 742 |
715 const int interval_; | 743 const int interval_; |
716 | 744 |
717 // Protects the process wide state below. | 745 // Protects the process wide state below. |
718 static Mutex* mutex_; | 746 static Mutex* mutex_; |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
770 | 798 |
771 | 799 |
772 void Sampler::Stop() { | 800 void Sampler::Stop() { |
773 ASSERT(IsActive()); | 801 ASSERT(IsActive()); |
774 SamplerThread::RemoveActiveSampler(this); | 802 SamplerThread::RemoveActiveSampler(this); |
775 SetActive(false); | 803 SetActive(false); |
776 } | 804 } |
777 | 805 |
778 | 806 |
779 } } // namespace v8::internal | 807 } } // namespace v8::internal |
OLD | NEW |