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

Side by Side Diff: src/platform-cygwin.cc

Issue 6794050: Revert "[Arguments] Merge (7442,7496] from bleeding_edge." (Closed) Base URL: https://v8.googlecode.com/svn/branches/experimental/arguments
Patch Set: Created 9 years, 8 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/platform.h ('k') | src/platform-macos.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 2006-2011 the V8 project authors. All rights reserved. 1 // Copyright 2006-2011 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 24 matching lines...) Expand all
35 #include <strings.h> // index 35 #include <strings.h> // index
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.h" 44 #include "platform.h"
45 #include "top.h"
45 #include "v8threads.h" 46 #include "v8threads.h"
46 #include "vm-state-inl.h" 47 #include "vm-state-inl.h"
47 #include "win32-headers.h" 48 #include "win32-headers.h"
48 49
49 namespace v8 { 50 namespace v8 {
50 namespace internal { 51 namespace internal {
51 52
52 // 0 is never a valid thread id 53 // 0 is never a valid thread id
53 static const pthread_t kNoThread = (pthread_t) 0; 54 static const pthread_t kNoThread = (pthread_t) 0;
54 55
55 56
56 double ceiling(double x) { 57 double ceiling(double x) {
57 return ceil(x); 58 return ceil(x);
58 } 59 }
59 60
60 61
61 static Mutex* limit_mutex = NULL;
62
63
64 void OS::Setup() { 62 void OS::Setup() {
65 // Seed the random number generator. 63 // Seed the random number generator.
66 // Convert the current time to a 64-bit integer first, before converting it 64 // Convert the current time to a 64-bit integer first, before converting it
67 // to an unsigned. Going directly can cause an overflow and the seed to be 65 // to an unsigned. Going directly can cause an overflow and the seed to be
68 // set to all ones. The seed will be identical for different instances that 66 // set to all ones. The seed will be identical for different instances that
69 // call this setup code within the same millisecond. 67 // call this setup code within the same millisecond.
70 uint64_t seed = static_cast<uint64_t>(TimeCurrentMillis()); 68 uint64_t seed = static_cast<uint64_t>(TimeCurrentMillis());
71 srandom(static_cast<unsigned int>(seed)); 69 srandom(static_cast<unsigned int>(seed));
72 limit_mutex = CreateMutex();
73 } 70 }
74 71
75 72
76 uint64_t OS::CpuFeaturesImpliedByPlatform() { 73 uint64_t OS::CpuFeaturesImpliedByPlatform() {
77 return 0; // Nothing special about Cygwin. 74 return 0; // Nothing special about Cygwin.
78 } 75 }
79 76
80 77
81 int OS::ActivationFrameAlignment() { 78 int OS::ActivationFrameAlignment() {
82 // With gcc 4.4 the tree vectorization optimizer can generate code 79 // With gcc 4.4 the tree vectorization optimizer can generate code
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
115 // We keep the lowest and highest addresses mapped as a quick way of 112 // We keep the lowest and highest addresses mapped as a quick way of
116 // determining that pointers are outside the heap (used mostly in assertions 113 // determining that pointers are outside the heap (used mostly in assertions
117 // and verification). The estimate is conservative, ie, not all addresses in 114 // and verification). The estimate is conservative, ie, not all addresses in
118 // 'allocated' space are actually allocated to our heap. The range is 115 // 'allocated' space are actually allocated to our heap. The range is
119 // [lowest, highest), inclusive on the low and and exclusive on the high end. 116 // [lowest, highest), inclusive on the low and and exclusive on the high end.
120 static void* lowest_ever_allocated = reinterpret_cast<void*>(-1); 117 static void* lowest_ever_allocated = reinterpret_cast<void*>(-1);
121 static void* highest_ever_allocated = reinterpret_cast<void*>(0); 118 static void* highest_ever_allocated = reinterpret_cast<void*>(0);
122 119
123 120
124 static void UpdateAllocatedSpaceLimits(void* address, int size) { 121 static void UpdateAllocatedSpaceLimits(void* address, int size) {
125 ASSERT(limit_mutex != NULL);
126 ScopedLock lock(limit_mutex);
127
128 lowest_ever_allocated = Min(lowest_ever_allocated, address); 122 lowest_ever_allocated = Min(lowest_ever_allocated, address);
129 highest_ever_allocated = 123 highest_ever_allocated =
130 Max(highest_ever_allocated, 124 Max(highest_ever_allocated,
131 reinterpret_cast<void*>(reinterpret_cast<char*>(address) + size)); 125 reinterpret_cast<void*>(reinterpret_cast<char*>(address) + size));
132 } 126 }
133 127
134 128
135 bool OS::IsOutsideAllocatedSpace(void* address) { 129 bool OS::IsOutsideAllocatedSpace(void* address) {
136 return address < lowest_ever_allocated || address >= highest_ever_allocated; 130 return address < lowest_ever_allocated || address >= highest_ever_allocated;
137 } 131 }
(...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after
253 // This function assumes that the layout of the file is as follows: 247 // This function assumes that the layout of the file is as follows:
254 // hex_start_addr-hex_end_addr rwxp <unused data> [binary_file_name] 248 // hex_start_addr-hex_end_addr rwxp <unused data> [binary_file_name]
255 // If we encounter an unexpected situation we abort scanning further entries. 249 // If we encounter an unexpected situation we abort scanning further entries.
256 FILE* fp = fopen("/proc/self/maps", "r"); 250 FILE* fp = fopen("/proc/self/maps", "r");
257 if (fp == NULL) return; 251 if (fp == NULL) return;
258 252
259 // Allocate enough room to be able to store a full file name. 253 // Allocate enough room to be able to store a full file name.
260 const int kLibNameLen = FILENAME_MAX + 1; 254 const int kLibNameLen = FILENAME_MAX + 1;
261 char* lib_name = reinterpret_cast<char*>(malloc(kLibNameLen)); 255 char* lib_name = reinterpret_cast<char*>(malloc(kLibNameLen));
262 256
263 i::Isolate* isolate = ISOLATE;
264 // This loop will terminate once the scanning hits an EOF. 257 // This loop will terminate once the scanning hits an EOF.
265 while (true) { 258 while (true) {
266 uintptr_t start, end; 259 uintptr_t start, end;
267 char attr_r, attr_w, attr_x, attr_p; 260 char attr_r, attr_w, attr_x, attr_p;
268 // Parse the addresses and permission bits at the beginning of the line. 261 // Parse the addresses and permission bits at the beginning of the line.
269 if (fscanf(fp, "%" V8PRIxPTR "-%" V8PRIxPTR, &start, &end) != 2) break; 262 if (fscanf(fp, "%" V8PRIxPTR "-%" V8PRIxPTR, &start, &end) != 2) break;
270 if (fscanf(fp, " %c%c%c%c", &attr_r, &attr_w, &attr_x, &attr_p) != 4) break; 263 if (fscanf(fp, " %c%c%c%c", &attr_r, &attr_w, &attr_x, &attr_p) != 4) break;
271 264
272 int c; 265 int c;
273 if (attr_r == 'r' && attr_w != 'w' && attr_x == 'x') { 266 if (attr_r == 'r' && attr_w != 'w' && attr_x == 'x') {
(...skipping 13 matching lines...) Expand all
287 280
288 // Drop the newline character read by fgets. We do not need to check 281 // Drop the newline character read by fgets. We do not need to check
289 // for a zero-length string because we know that we at least read the 282 // for a zero-length string because we know that we at least read the
290 // '/' character. 283 // '/' character.
291 lib_name[strlen(lib_name) - 1] = '\0'; 284 lib_name[strlen(lib_name) - 1] = '\0';
292 } else { 285 } else {
293 // No library name found, just record the raw address range. 286 // No library name found, just record the raw address range.
294 snprintf(lib_name, kLibNameLen, 287 snprintf(lib_name, kLibNameLen,
295 "%08" V8PRIxPTR "-%08" V8PRIxPTR, start, end); 288 "%08" V8PRIxPTR "-%08" V8PRIxPTR, start, end);
296 } 289 }
297 LOG(isolate, SharedLibraryEvent(lib_name, start, end)); 290 LOG(SharedLibraryEvent(lib_name, start, end));
298 } else { 291 } else {
299 // Entry not describing executable data. Skip to end of line to setup 292 // Entry not describing executable data. Skip to end of line to setup
300 // reading the next entry. 293 // reading the next entry.
301 do { 294 do {
302 c = getc(fp); 295 c = getc(fp);
303 } while ((c != EOF) && (c != '\n')); 296 } while ((c != EOF) && (c != '\n'));
304 if (c == EOF) break; 297 if (c == EOF) break;
305 } 298 }
306 } 299 }
307 free(lib_name); 300 free(lib_name);
308 fclose(fp); 301 fclose(fp);
309 #endif 302 #endif
310 } 303 }
311 304
312 305
313 void OS::SignalCodeMovingGC() { 306 void OS::SignalCodeMovingGC() {
314 // Nothing to do on Cygwin. 307 // Nothing to do on Cygwin.
315 } 308 }
316 309
317 310
318 int OS::StackWalk(Vector<OS::StackFrame> frames) { 311 int OS::StackWalk(Vector<OS::StackFrame> frames) {
319 // Not supported on Cygwin. 312 // Not supported on Cygwin.
320 return 0; 313 return 0;
321 } 314 }
322 315
323 316
324 // The VirtualMemory implementation is taken from platform-win32.cc. 317 // Constants used for mmap.
325 // The mmap-based virtual memory implementation as it is used on most posix 318 static const int kMmapFd = -1;
326 // platforms does not work well because Cygwin does not support MAP_FIXED. 319 static const int kMmapFdOffset = 0;
327 // This causes VirtualMemory::Commit to not always commit the memory region
328 // specified.
329
330 bool VirtualMemory::IsReserved() {
331 return address_ != NULL;
332 }
333 320
334 321
335 VirtualMemory::VirtualMemory(size_t size) { 322 VirtualMemory::VirtualMemory(size_t size) {
336 address_ = VirtualAlloc(NULL, size, MEM_RESERVE, PAGE_NOACCESS); 323 address_ = mmap(NULL, size, PROT_NONE,
324 MAP_PRIVATE | MAP_ANONYMOUS | MAP_NORESERVE,
325 kMmapFd, kMmapFdOffset);
337 size_ = size; 326 size_ = size;
338 } 327 }
339 328
340 329
341 VirtualMemory::~VirtualMemory() { 330 VirtualMemory::~VirtualMemory() {
342 if (IsReserved()) { 331 if (IsReserved()) {
343 if (0 == VirtualFree(address(), 0, MEM_RELEASE)) address_ = NULL; 332 if (0 == munmap(address(), size())) address_ = MAP_FAILED;
344 } 333 }
345 } 334 }
346 335
347 336
337 bool VirtualMemory::IsReserved() {
338 return address_ != MAP_FAILED;
339 }
340
341
348 bool VirtualMemory::Commit(void* address, size_t size, bool is_executable) { 342 bool VirtualMemory::Commit(void* address, size_t size, bool is_executable) {
349 int prot = is_executable ? PAGE_EXECUTE_READWRITE : PAGE_READWRITE; 343 int prot = PROT_READ | PROT_WRITE | (is_executable ? PROT_EXEC : 0);
350 if (NULL == VirtualAlloc(address, size, MEM_COMMIT, prot)) { 344
345 if (mprotect(address, size, prot) != 0) {
351 return false; 346 return false;
352 } 347 }
353 348
354 UpdateAllocatedSpaceLimits(address, static_cast<int>(size)); 349 UpdateAllocatedSpaceLimits(address, size);
355 return true; 350 return true;
356 } 351 }
357 352
358 353
359 bool VirtualMemory::Uncommit(void* address, size_t size) { 354 bool VirtualMemory::Uncommit(void* address, size_t size) {
360 ASSERT(IsReserved()); 355 return mmap(address, size, PROT_NONE,
361 return VirtualFree(address, size, MEM_DECOMMIT) != false; 356 MAP_PRIVATE | MAP_ANONYMOUS | MAP_NORESERVE,
357 kMmapFd, kMmapFdOffset) != MAP_FAILED;
362 } 358 }
363 359
364 360
365 class ThreadHandle::PlatformData : public Malloced { 361 class ThreadHandle::PlatformData : public Malloced {
366 public: 362 public:
367 explicit PlatformData(ThreadHandle::Kind kind) { 363 explicit PlatformData(ThreadHandle::Kind kind) {
368 Initialize(kind); 364 Initialize(kind);
369 } 365 }
370 366
371 void Initialize(ThreadHandle::Kind kind) { 367 void Initialize(ThreadHandle::Kind kind) {
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
424 } 420 }
425 421
426 422
427 static void* ThreadEntry(void* arg) { 423 static void* ThreadEntry(void* arg) {
428 Thread* thread = reinterpret_cast<Thread*>(arg); 424 Thread* thread = reinterpret_cast<Thread*>(arg);
429 // This is also initialized by the first argument to pthread_create() but we 425 // This is also initialized by the first argument to pthread_create() but we
430 // don't know which thread will run first (the original thread or the new 426 // don't know which thread will run first (the original thread or the new
431 // one) so we initialize it here too. 427 // one) so we initialize it here too.
432 thread->thread_handle_data()->thread_ = pthread_self(); 428 thread->thread_handle_data()->thread_ = pthread_self();
433 ASSERT(thread->IsValid()); 429 ASSERT(thread->IsValid());
434 Thread::SetThreadLocal(Isolate::isolate_key(), thread->isolate());
435 thread->Run(); 430 thread->Run();
436 return NULL; 431 return NULL;
437 } 432 }
438 433
439 434
440 void Thread::set_name(const char* name) { 435 void Thread::set_name(const char* name) {
441 strncpy(name_, name, sizeof(name_)); 436 strncpy(name_, name, sizeof(name_));
442 name_[sizeof(name_) - 1] = '\0'; 437 name_[sizeof(name_) - 1] = '\0';
443 } 438 }
444 439
445 440
446 void Thread::Start() { 441 void Thread::Start() {
447 pthread_attr_t* attr_ptr = NULL; 442 pthread_create(&thread_handle_data()->thread_, NULL, ThreadEntry, this);
448 pthread_attr_t attr;
449 if (stack_size_ > 0) {
450 pthread_attr_init(&attr);
451 pthread_attr_setstacksize(&attr, static_cast<size_t>(stack_size_));
452 attr_ptr = &attr;
453 }
454 pthread_create(&thread_handle_data()->thread_, attr_ptr, ThreadEntry, this);
455 ASSERT(IsValid()); 443 ASSERT(IsValid());
456 } 444 }
457 445
458 446
459 void Thread::Join() { 447 void Thread::Join() {
460 pthread_join(thread_handle_data()->thread_, NULL); 448 pthread_join(thread_handle_data()->thread_, NULL);
461 } 449 }
462 450
463 451
464 static inline Thread::LocalStorageKey PthreadKeyToLocalKey( 452 static inline Thread::LocalStorageKey PthreadKeyToLocalKey(
(...skipping 163 matching lines...) Expand 10 before | Expand all | Expand 10 after
628 616
629 #ifdef ENABLE_LOGGING_AND_PROFILING 617 #ifdef ENABLE_LOGGING_AND_PROFILING
630 618
631 // ---------------------------------------------------------------------------- 619 // ----------------------------------------------------------------------------
632 // Cygwin profiler support. 620 // Cygwin profiler support.
633 // 621 //
634 // On Cygwin we use the same sampler implementation as on win32. 622 // On Cygwin we use the same sampler implementation as on win32.
635 623
636 class Sampler::PlatformData : public Malloced { 624 class Sampler::PlatformData : public Malloced {
637 public: 625 public:
626 explicit PlatformData(Sampler* sampler) {
627 sampler_ = sampler;
628 sampler_thread_ = INVALID_HANDLE_VALUE;
629 profiled_thread_ = INVALID_HANDLE_VALUE;
630 }
631
632 Sampler* sampler_;
633 HANDLE sampler_thread_;
634 HANDLE profiled_thread_;
635 RuntimeProfilerRateLimiter rate_limiter_;
636
637 // Sampler thread handler.
638 void Runner() {
639 while (sampler_->IsActive()) {
640 if (rate_limiter_.SuspendIfNecessary()) continue;
641 Sample();
642 Sleep(sampler_->interval_);
643 }
644 }
645
646 void Sample() {
647 if (sampler_->IsProfiling()) {
648 // Context used for sampling the register state of the profiled thread.
649 CONTEXT context;
650 memset(&context, 0, sizeof(context));
651
652 TickSample sample_obj;
653 TickSample* sample = CpuProfiler::TickSampleEvent();
654 if (sample == NULL) sample = &sample_obj;
655
656 static const DWORD kSuspendFailed = static_cast<DWORD>(-1);
657 if (SuspendThread(profiled_thread_) == kSuspendFailed) return;
658 sample->state = Top::current_vm_state();
659
660 context.ContextFlags = CONTEXT_FULL;
661 if (GetThreadContext(profiled_thread_, &context) != 0) {
662 #if V8_HOST_ARCH_X64
663 sample->pc = reinterpret_cast<Address>(context.Rip);
664 sample->sp = reinterpret_cast<Address>(context.Rsp);
665 sample->fp = reinterpret_cast<Address>(context.Rbp);
666 #else
667 sample->pc = reinterpret_cast<Address>(context.Eip);
668 sample->sp = reinterpret_cast<Address>(context.Esp);
669 sample->fp = reinterpret_cast<Address>(context.Ebp);
670 #endif
671 sampler_->SampleStack(sample);
672 sampler_->Tick(sample);
673 }
674 ResumeThread(profiled_thread_);
675 }
676 if (RuntimeProfiler::IsEnabled()) RuntimeProfiler::NotifyTick();
677 }
678 };
679
680
681 // Entry point for sampler thread.
682 static DWORD __stdcall SamplerEntry(void* arg) {
683 Sampler::PlatformData* data =
684 reinterpret_cast<Sampler::PlatformData*>(arg);
685 data->Runner();
686 return 0;
687 }
688
689
690 // Initialize a profile sampler.
691 Sampler::Sampler(int interval)
692 : interval_(interval),
693 profiling_(false),
694 active_(false),
695 samples_taken_(0) {
696 data_ = new PlatformData(this);
697 }
698
699
700 Sampler::~Sampler() {
701 delete data_;
702 }
703
704
705 // Start profiling.
706 void Sampler::Start() {
707 // Do not start multiple threads for the same sampler.
708 ASSERT(!IsActive());
709
638 // Get a handle to the calling thread. This is the thread that we are 710 // Get a handle to the calling thread. This is the thread that we are
639 // going to profile. We need to make a copy of the handle because we are 711 // going to profile. We need to make a copy of the handle because we are
640 // going to use it in the sampler thread. Using GetThreadHandle() will 712 // going to use it in the sampler thread. Using GetThreadHandle() will
641 // not work in this case. We're using OpenThread because DuplicateHandle 713 // not work in this case. We're using OpenThread because DuplicateHandle
642 // for some reason doesn't work in Chrome's sandbox. 714 // for some reason doesn't work in Chrome's sandbox.
643 PlatformData() : profiled_thread_(OpenThread(THREAD_GET_CONTEXT | 715 data_->profiled_thread_ = OpenThread(THREAD_GET_CONTEXT |
644 THREAD_SUSPEND_RESUME | 716 THREAD_SUSPEND_RESUME |
645 THREAD_QUERY_INFORMATION, 717 THREAD_QUERY_INFORMATION,
646 false, 718 false,
647 GetCurrentThreadId())) {} 719 GetCurrentThreadId());
720 BOOL ok = data_->profiled_thread_ != NULL;
721 if (!ok) return;
648 722
649 ~PlatformData() { 723 // Start sampler thread.
650 if (profiled_thread_ != NULL) { 724 DWORD tid;
651 CloseHandle(profiled_thread_); 725 SetActive(true);
652 profiled_thread_ = NULL; 726 data_->sampler_thread_ = CreateThread(NULL, 0, SamplerEntry, data_, 0, &tid);
653 } 727 // Set thread to high priority to increase sampling accuracy.
654 } 728 SetThreadPriority(data_->sampler_thread_, THREAD_PRIORITY_TIME_CRITICAL);
655
656 HANDLE profiled_thread() { return profiled_thread_; }
657
658 private:
659 HANDLE profiled_thread_;
660 };
661
662
663 class SamplerThread : public Thread {
664 public:
665 explicit SamplerThread(int interval)
666 : Thread(NULL, "SamplerThread"),
667 interval_(interval) {}
668
669 static void AddActiveSampler(Sampler* sampler) {
670 ScopedLock lock(mutex_);
671 SamplerRegistry::AddActiveSampler(sampler);
672 if (instance_ == NULL) {
673 instance_ = new SamplerThread(sampler->interval());
674 instance_->Start();
675 } else {
676 ASSERT(instance_->interval_ == sampler->interval());
677 }
678 }
679
680 static void RemoveActiveSampler(Sampler* sampler) {
681 ScopedLock lock(mutex_);
682 SamplerRegistry::RemoveActiveSampler(sampler);
683 if (SamplerRegistry::GetState() == SamplerRegistry::HAS_NO_SAMPLERS) {
684 RuntimeProfiler::WakeUpRuntimeProfilerThreadBeforeShutdown();
685 instance_->Join();
686 delete instance_;
687 instance_ = NULL;
688 }
689 }
690
691 // Implement Thread::Run().
692 virtual void Run() {
693 SamplerRegistry::State state;
694 while ((state = SamplerRegistry::GetState()) !=
695 SamplerRegistry::HAS_NO_SAMPLERS) {
696 bool cpu_profiling_enabled =
697 (state == SamplerRegistry::HAS_CPU_PROFILING_SAMPLERS);
698 bool runtime_profiler_enabled = RuntimeProfiler::IsEnabled();
699 // When CPU profiling is enabled both JavaScript and C++ code is
700 // profiled. We must not suspend.
701 if (!cpu_profiling_enabled) {
702 if (rate_limiter_.SuspendIfNecessary()) continue;
703 }
704 if (cpu_profiling_enabled) {
705 if (!SamplerRegistry::IterateActiveSamplers(&DoCpuProfile, this)) {
706 return;
707 }
708 }
709 if (runtime_profiler_enabled) {
710 if (!SamplerRegistry::IterateActiveSamplers(&DoRuntimeProfile, NULL)) {
711 return;
712 }
713 }
714 OS::Sleep(interval_);
715 }
716 }
717
718 static void DoCpuProfile(Sampler* sampler, void* raw_sampler_thread) {
719 if (!sampler->isolate()->IsInitialized()) return;
720 if (!sampler->IsProfiling()) return;
721 SamplerThread* sampler_thread =
722 reinterpret_cast<SamplerThread*>(raw_sampler_thread);
723 sampler_thread->SampleContext(sampler);
724 }
725
726 static void DoRuntimeProfile(Sampler* sampler, void* ignored) {
727 if (!sampler->isolate()->IsInitialized()) return;
728 sampler->isolate()->runtime_profiler()->NotifyTick();
729 }
730
731 void SampleContext(Sampler* sampler) {
732 HANDLE profiled_thread = sampler->platform_data()->profiled_thread();
733 if (profiled_thread == NULL) return;
734
735 // Context used for sampling the register state of the profiled thread.
736 CONTEXT context;
737 memset(&context, 0, sizeof(context));
738
739 TickSample sample_obj;
740 TickSample* sample = CpuProfiler::TickSampleEvent(sampler->isolate());
741 if (sample == NULL) sample = &sample_obj;
742
743 static const DWORD kSuspendFailed = static_cast<DWORD>(-1);
744 if (SuspendThread(profiled_thread) == kSuspendFailed) return;
745 sample->state = sampler->isolate()->current_vm_state();
746
747 context.ContextFlags = CONTEXT_FULL;
748 if (GetThreadContext(profiled_thread, &context) != 0) {
749 #if V8_HOST_ARCH_X64
750 sample->pc = reinterpret_cast<Address>(context.Rip);
751 sample->sp = reinterpret_cast<Address>(context.Rsp);
752 sample->fp = reinterpret_cast<Address>(context.Rbp);
753 #else
754 sample->pc = reinterpret_cast<Address>(context.Eip);
755 sample->sp = reinterpret_cast<Address>(context.Esp);
756 sample->fp = reinterpret_cast<Address>(context.Ebp);
757 #endif
758 sampler->SampleStack(sample);
759 sampler->Tick(sample);
760 }
761 ResumeThread(profiled_thread);
762 }
763
764 const int interval_;
765 RuntimeProfilerRateLimiter rate_limiter_;
766
767 // Protects the process wide state below.
768 static Mutex* mutex_;
769 static SamplerThread* instance_;
770
771 DISALLOW_COPY_AND_ASSIGN(SamplerThread);
772 };
773
774
775 Mutex* SamplerThread::mutex_ = OS::CreateMutex();
776 SamplerThread* SamplerThread::instance_ = NULL;
777
778
779 Sampler::Sampler(Isolate* isolate, int interval)
780 : isolate_(isolate),
781 interval_(interval),
782 profiling_(false),
783 active_(false),
784 samples_taken_(0) {
785 data_ = new PlatformData;
786 } 729 }
787 730
788 731
789 Sampler::~Sampler() { 732 // Stop profiling.
790 ASSERT(!IsActive()); 733 void Sampler::Stop() {
791 delete data_; 734 // Seting active to false triggers termination of the sampler
735 // thread.
736 SetActive(false);
737
738 // Wait for sampler thread to terminate.
739 Top::WakeUpRuntimeProfilerThreadBeforeShutdown();
740 WaitForSingleObject(data_->sampler_thread_, INFINITE);
741
742 // Release the thread handles
743 CloseHandle(data_->sampler_thread_);
744 CloseHandle(data_->profiled_thread_);
792 } 745 }
793 746
794 747
795 void Sampler::Start() {
796 ASSERT(!IsActive());
797 SetActive(true);
798 SamplerThread::AddActiveSampler(this);
799 }
800
801
802 void Sampler::Stop() {
803 ASSERT(IsActive());
804 SamplerThread::RemoveActiveSampler(this);
805 SetActive(false);
806 }
807
808 #endif // ENABLE_LOGGING_AND_PROFILING 748 #endif // ENABLE_LOGGING_AND_PROFILING
809 749
810 } } // namespace v8::internal 750 } } // namespace v8::internal
811 751
OLDNEW
« no previous file with comments | « src/platform.h ('k') | src/platform-macos.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698