| 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 |