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/platform-cygwin.cc

Issue 6776011: Fix the Cygwin build (Closed)
Patch Set: foobar 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
« no previous file with comments | « no previous file | test/cctest/test-alloc.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"
46 #include "v8threads.h" 45 #include "v8threads.h"
47 #include "vm-state-inl.h" 46 #include "vm-state-inl.h"
48 #include "win32-headers.h" 47 #include "win32-headers.h"
49 48
50 namespace v8 { 49 namespace v8 {
51 namespace internal { 50 namespace internal {
52 51
53 // 0 is never a valid thread id 52 // 0 is never a valid thread id
54 static const pthread_t kNoThread = (pthread_t) 0; 53 static const pthread_t kNoThread = (pthread_t) 0;
55 54
56 55
57 double ceiling(double x) { 56 double ceiling(double x) {
58 return ceil(x); 57 return ceil(x);
59 } 58 }
60 59
61 60
61 static Mutex* limit_mutex = NULL;
62
63
62 void OS::Setup() { 64 void OS::Setup() {
63 // Seed the random number generator. 65 // Seed the random number generator.
64 // Convert the current time to a 64-bit integer first, before converting it 66 // Convert the current time to a 64-bit integer first, before converting it
65 // to an unsigned. Going directly can cause an overflow and the seed to be 67 // to an unsigned. Going directly can cause an overflow and the seed to be
66 // set to all ones. The seed will be identical for different instances that 68 // set to all ones. The seed will be identical for different instances that
67 // call this setup code within the same millisecond. 69 // call this setup code within the same millisecond.
68 uint64_t seed = static_cast<uint64_t>(TimeCurrentMillis()); 70 uint64_t seed = static_cast<uint64_t>(TimeCurrentMillis());
69 srandom(static_cast<unsigned int>(seed)); 71 srandom(static_cast<unsigned int>(seed));
72 limit_mutex = CreateMutex();
70 } 73 }
71 74
72 75
73 uint64_t OS::CpuFeaturesImpliedByPlatform() { 76 uint64_t OS::CpuFeaturesImpliedByPlatform() {
74 return 0; // Nothing special about Cygwin. 77 return 0; // Nothing special about Cygwin.
75 } 78 }
76 79
77 80
78 int OS::ActivationFrameAlignment() { 81 int OS::ActivationFrameAlignment() {
79 // With gcc 4.4 the tree vectorization optimizer can generate code 82 // With gcc 4.4 the tree vectorization optimizer can generate code
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
112 // We keep the lowest and highest addresses mapped as a quick way of 115 // We keep the lowest and highest addresses mapped as a quick way of
113 // determining that pointers are outside the heap (used mostly in assertions 116 // determining that pointers are outside the heap (used mostly in assertions
114 // and verification). The estimate is conservative, ie, not all addresses in 117 // and verification). The estimate is conservative, ie, not all addresses in
115 // 'allocated' space are actually allocated to our heap. The range is 118 // 'allocated' space are actually allocated to our heap. The range is
116 // [lowest, highest), inclusive on the low and and exclusive on the high end. 119 // [lowest, highest), inclusive on the low and and exclusive on the high end.
117 static void* lowest_ever_allocated = reinterpret_cast<void*>(-1); 120 static void* lowest_ever_allocated = reinterpret_cast<void*>(-1);
118 static void* highest_ever_allocated = reinterpret_cast<void*>(0); 121 static void* highest_ever_allocated = reinterpret_cast<void*>(0);
119 122
120 123
121 static void UpdateAllocatedSpaceLimits(void* address, int size) { 124 static void UpdateAllocatedSpaceLimits(void* address, int size) {
125 ASSERT(limit_mutex != NULL);
126 ScopedLock lock(limit_mutex);
127
122 lowest_ever_allocated = Min(lowest_ever_allocated, address); 128 lowest_ever_allocated = Min(lowest_ever_allocated, address);
123 highest_ever_allocated = 129 highest_ever_allocated =
124 Max(highest_ever_allocated, 130 Max(highest_ever_allocated,
125 reinterpret_cast<void*>(reinterpret_cast<char*>(address) + size)); 131 reinterpret_cast<void*>(reinterpret_cast<char*>(address) + size));
126 } 132 }
127 133
128 134
129 bool OS::IsOutsideAllocatedSpace(void* address) { 135 bool OS::IsOutsideAllocatedSpace(void* address) {
130 return address < lowest_ever_allocated || address >= highest_ever_allocated; 136 return address < lowest_ever_allocated || address >= highest_ever_allocated;
131 } 137 }
(...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after
247 // This function assumes that the layout of the file is as follows: 253 // This function assumes that the layout of the file is as follows:
248 // hex_start_addr-hex_end_addr rwxp <unused data> [binary_file_name] 254 // hex_start_addr-hex_end_addr rwxp <unused data> [binary_file_name]
249 // If we encounter an unexpected situation we abort scanning further entries. 255 // If we encounter an unexpected situation we abort scanning further entries.
250 FILE* fp = fopen("/proc/self/maps", "r"); 256 FILE* fp = fopen("/proc/self/maps", "r");
251 if (fp == NULL) return; 257 if (fp == NULL) return;
252 258
253 // Allocate enough room to be able to store a full file name. 259 // Allocate enough room to be able to store a full file name.
254 const int kLibNameLen = FILENAME_MAX + 1; 260 const int kLibNameLen = FILENAME_MAX + 1;
255 char* lib_name = reinterpret_cast<char*>(malloc(kLibNameLen)); 261 char* lib_name = reinterpret_cast<char*>(malloc(kLibNameLen));
256 262
263 i::Isolate* isolate = ISOLATE;
257 // This loop will terminate once the scanning hits an EOF. 264 // This loop will terminate once the scanning hits an EOF.
258 while (true) { 265 while (true) {
259 uintptr_t start, end; 266 uintptr_t start, end;
260 char attr_r, attr_w, attr_x, attr_p; 267 char attr_r, attr_w, attr_x, attr_p;
261 // Parse the addresses and permission bits at the beginning of the line. 268 // Parse the addresses and permission bits at the beginning of the line.
262 if (fscanf(fp, "%" V8PRIxPTR "-%" V8PRIxPTR, &start, &end) != 2) break; 269 if (fscanf(fp, "%" V8PRIxPTR "-%" V8PRIxPTR, &start, &end) != 2) break;
263 if (fscanf(fp, " %c%c%c%c", &attr_r, &attr_w, &attr_x, &attr_p) != 4) break; 270 if (fscanf(fp, " %c%c%c%c", &attr_r, &attr_w, &attr_x, &attr_p) != 4) break;
264 271
265 int c; 272 int c;
266 if (attr_r == 'r' && attr_w != 'w' && attr_x == 'x') { 273 if (attr_r == 'r' && attr_w != 'w' && attr_x == 'x') {
(...skipping 13 matching lines...) Expand all
280 287
281 // Drop the newline character read by fgets. We do not need to check 288 // Drop the newline character read by fgets. We do not need to check
282 // for a zero-length string because we know that we at least read the 289 // for a zero-length string because we know that we at least read the
283 // '/' character. 290 // '/' character.
284 lib_name[strlen(lib_name) - 1] = '\0'; 291 lib_name[strlen(lib_name) - 1] = '\0';
285 } else { 292 } else {
286 // No library name found, just record the raw address range. 293 // No library name found, just record the raw address range.
287 snprintf(lib_name, kLibNameLen, 294 snprintf(lib_name, kLibNameLen,
288 "%08" V8PRIxPTR "-%08" V8PRIxPTR, start, end); 295 "%08" V8PRIxPTR "-%08" V8PRIxPTR, start, end);
289 } 296 }
290 LOG(SharedLibraryEvent(lib_name, start, end)); 297 LOG(isolate, SharedLibraryEvent(lib_name, start, end));
291 } else { 298 } else {
292 // Entry not describing executable data. Skip to end of line to setup 299 // Entry not describing executable data. Skip to end of line to setup
293 // reading the next entry. 300 // reading the next entry.
294 do { 301 do {
295 c = getc(fp); 302 c = getc(fp);
296 } while ((c != EOF) && (c != '\n')); 303 } while ((c != EOF) && (c != '\n'));
297 if (c == EOF) break; 304 if (c == EOF) break;
298 } 305 }
299 } 306 }
300 free(lib_name); 307 free(lib_name);
301 fclose(fp); 308 fclose(fp);
302 #endif 309 #endif
303 } 310 }
304 311
305 312
306 void OS::SignalCodeMovingGC() { 313 void OS::SignalCodeMovingGC() {
307 // Nothing to do on Cygwin. 314 // Nothing to do on Cygwin.
308 } 315 }
309 316
310 317
311 int OS::StackWalk(Vector<OS::StackFrame> frames) { 318 int OS::StackWalk(Vector<OS::StackFrame> frames) {
312 // Not supported on Cygwin. 319 // Not supported on Cygwin.
313 return 0; 320 return 0;
314 } 321 }
315 322
316 323
317 // Constants used for mmap. 324 // The VirtualMemory implementation is taken from platform-win32.cc.
318 static const int kMmapFd = -1; 325 // The mmap-based virtual memory implementation as it is used on most posix
319 static const int kMmapFdOffset = 0; 326 // platforms does not work well because Cygwin does not support MAP_FIXED.
327 // This causes VirtualMemory::Commit to not always commit the memory region
328 // specified.
329
330 bool VirtualMemory::IsReserved() {
331 return address_ != NULL;
332 }
320 333
321 334
322 VirtualMemory::VirtualMemory(size_t size) { 335 VirtualMemory::VirtualMemory(size_t size) {
323 address_ = mmap(NULL, size, PROT_NONE, 336 address_ = VirtualAlloc(NULL, size, MEM_RESERVE, PAGE_NOACCESS);
324 MAP_PRIVATE | MAP_ANONYMOUS | MAP_NORESERVE,
325 kMmapFd, kMmapFdOffset);
326 size_ = size; 337 size_ = size;
327 } 338 }
328 339
329 340
330 VirtualMemory::~VirtualMemory() { 341 VirtualMemory::~VirtualMemory() {
331 if (IsReserved()) { 342 if (IsReserved()) {
332 if (0 == munmap(address(), size())) address_ = MAP_FAILED; 343 if (0 == VirtualFree(address(), 0, MEM_RELEASE)) address_ = NULL;
333 } 344 }
334 } 345 }
335 346
336 347
337 bool VirtualMemory::IsReserved() {
338 return address_ != MAP_FAILED;
339 }
340
341
342 bool VirtualMemory::Commit(void* address, size_t size, bool is_executable) { 348 bool VirtualMemory::Commit(void* address, size_t size, bool is_executable) {
343 int prot = PROT_READ | PROT_WRITE | (is_executable ? PROT_EXEC : 0); 349 int prot = is_executable ? PAGE_EXECUTE_READWRITE : PAGE_READWRITE;
344 350 if (NULL == VirtualAlloc(address, size, MEM_COMMIT, prot)) {
345 if (mprotect(address, size, prot) != 0) {
346 return false; 351 return false;
347 } 352 }
348 353
349 UpdateAllocatedSpaceLimits(address, size); 354 UpdateAllocatedSpaceLimits(address, static_cast<int>(size));
350 return true; 355 return true;
351 } 356 }
352 357
353 358
354 bool VirtualMemory::Uncommit(void* address, size_t size) { 359 bool VirtualMemory::Uncommit(void* address, size_t size) {
355 return mmap(address, size, PROT_NONE, 360 ASSERT(IsReserved());
356 MAP_PRIVATE | MAP_ANONYMOUS | MAP_NORESERVE, 361 return VirtualFree(address, size, MEM_DECOMMIT) != false;
357 kMmapFd, kMmapFdOffset) != MAP_FAILED;
358 } 362 }
359 363
360 364
361 class ThreadHandle::PlatformData : public Malloced { 365 class ThreadHandle::PlatformData : public Malloced {
362 public: 366 public:
363 explicit PlatformData(ThreadHandle::Kind kind) { 367 explicit PlatformData(ThreadHandle::Kind kind) {
364 Initialize(kind); 368 Initialize(kind);
365 } 369 }
366 370
367 void Initialize(ThreadHandle::Kind kind) { 371 void Initialize(ThreadHandle::Kind kind) {
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
420 } 424 }
421 425
422 426
423 static void* ThreadEntry(void* arg) { 427 static void* ThreadEntry(void* arg) {
424 Thread* thread = reinterpret_cast<Thread*>(arg); 428 Thread* thread = reinterpret_cast<Thread*>(arg);
425 // This is also initialized by the first argument to pthread_create() but we 429 // This is also initialized by the first argument to pthread_create() but we
426 // don't know which thread will run first (the original thread or the new 430 // don't know which thread will run first (the original thread or the new
427 // one) so we initialize it here too. 431 // one) so we initialize it here too.
428 thread->thread_handle_data()->thread_ = pthread_self(); 432 thread->thread_handle_data()->thread_ = pthread_self();
429 ASSERT(thread->IsValid()); 433 ASSERT(thread->IsValid());
434 Thread::SetThreadLocal(Isolate::isolate_key(), thread->isolate());
430 thread->Run(); 435 thread->Run();
431 return NULL; 436 return NULL;
432 } 437 }
433 438
434 439
435 void Thread::set_name(const char* name) { 440 void Thread::set_name(const char* name) {
436 strncpy(name_, name, sizeof(name_)); 441 strncpy(name_, name, sizeof(name_));
437 name_[sizeof(name_) - 1] = '\0'; 442 name_[sizeof(name_) - 1] = '\0';
438 } 443 }
439 444
440 445
441 void Thread::Start() { 446 void Thread::Start() {
442 pthread_create(&thread_handle_data()->thread_, NULL, ThreadEntry, this); 447 pthread_attr_t* attr_ptr = NULL;
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);
443 ASSERT(IsValid()); 455 ASSERT(IsValid());
444 } 456 }
445 457
446 458
447 void Thread::Join() { 459 void Thread::Join() {
448 pthread_join(thread_handle_data()->thread_, NULL); 460 pthread_join(thread_handle_data()->thread_, NULL);
449 } 461 }
450 462
451 463
452 static inline Thread::LocalStorageKey PthreadKeyToLocalKey( 464 static inline Thread::LocalStorageKey PthreadKeyToLocalKey(
(...skipping 163 matching lines...) Expand 10 before | Expand all | Expand 10 after
616 628
617 #ifdef ENABLE_LOGGING_AND_PROFILING 629 #ifdef ENABLE_LOGGING_AND_PROFILING
618 630
619 // ---------------------------------------------------------------------------- 631 // ----------------------------------------------------------------------------
620 // Cygwin profiler support. 632 // Cygwin profiler support.
621 // 633 //
622 // On Cygwin we use the same sampler implementation as on win32. 634 // On Cygwin we use the same sampler implementation as on win32.
623 635
624 class Sampler::PlatformData : public Malloced { 636 class Sampler::PlatformData : public Malloced {
625 public: 637 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
710 // Get a handle to the calling thread. This is the thread that we are 638 // Get a handle to the calling thread. This is the thread that we are
711 // going to profile. We need to make a copy of the handle because we are 639 // going to profile. We need to make a copy of the handle because we are
712 // going to use it in the sampler thread. Using GetThreadHandle() will 640 // going to use it in the sampler thread. Using GetThreadHandle() will
713 // not work in this case. We're using OpenThread because DuplicateHandle 641 // not work in this case. We're using OpenThread because DuplicateHandle
714 // for some reason doesn't work in Chrome's sandbox. 642 // for some reason doesn't work in Chrome's sandbox.
715 data_->profiled_thread_ = OpenThread(THREAD_GET_CONTEXT | 643 PlatformData() : profiled_thread_(OpenThread(THREAD_GET_CONTEXT |
716 THREAD_SUSPEND_RESUME | 644 THREAD_SUSPEND_RESUME |
717 THREAD_QUERY_INFORMATION, 645 THREAD_QUERY_INFORMATION,
718 false, 646 false,
719 GetCurrentThreadId()); 647 GetCurrentThreadId())) {}
720 BOOL ok = data_->profiled_thread_ != NULL;
721 if (!ok) return;
722 648
723 // Start sampler thread. 649 ~PlatformData() {
724 DWORD tid; 650 if (profiled_thread_ != NULL) {
725 SetActive(true); 651 CloseHandle(profiled_thread_);
726 data_->sampler_thread_ = CreateThread(NULL, 0, SamplerEntry, data_, 0, &tid); 652 profiled_thread_ = NULL;
727 // Set thread to high priority to increase sampling accuracy. 653 }
728 SetThreadPriority(data_->sampler_thread_, THREAD_PRIORITY_TIME_CRITICAL); 654 }
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;
729 } 786 }
730 787
731 788
732 // Stop profiling. 789 Sampler::~Sampler() {
733 void Sampler::Stop() { 790 ASSERT(!IsActive());
734 // Seting active to false triggers termination of the sampler 791 delete data_;
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_);
745 } 792 }
746 793
747 794
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
748 #endif // ENABLE_LOGGING_AND_PROFILING 808 #endif // ENABLE_LOGGING_AND_PROFILING
749 809
750 } } // namespace v8::internal 810 } } // namespace v8::internal
751 811
OLDNEW
« no previous file with comments | « no previous file | test/cctest/test-alloc.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698