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

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

Issue 6529055: [Isolates] Merge crankshaft (r5922 from bleeding_edge). (Closed)
Patch Set: Win32 port Created 9 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
« no previous file with comments | « src/platform-linux.cc ('k') | src/platform-nullos.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-2008 the V8 project authors. All rights reserved. 1 // Copyright 2006-2008 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 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
50 #include <stdarg.h> 50 #include <stdarg.h>
51 #include <stdlib.h> 51 #include <stdlib.h>
52 52
53 #include <errno.h> 53 #include <errno.h>
54 54
55 #undef MAP_TYPE 55 #undef MAP_TYPE
56 56
57 #include "v8.h" 57 #include "v8.h"
58 58
59 #include "platform.h" 59 #include "platform.h"
60 #include "vm-state-inl.h"
60 61
61 // Manually define these here as weak imports, rather than including execinfo.h. 62 // Manually define these here as weak imports, rather than including execinfo.h.
62 // This lets us launch on 10.4 which does not have these calls. 63 // This lets us launch on 10.4 which does not have these calls.
63 extern "C" { 64 extern "C" {
64 extern int backtrace(void**, int) __attribute__((weak_import)); 65 extern int backtrace(void**, int) __attribute__((weak_import));
65 extern char** backtrace_symbols(void* const*, int) 66 extern char** backtrace_symbols(void* const*, int)
66 __attribute__((weak_import)); 67 __attribute__((weak_import));
67 extern void backtrace_symbols_fd(void* const*, int, int) 68 extern void backtrace_symbols_fd(void* const*, int, int)
68 __attribute__((weak_import)); 69 __attribute__((weak_import));
69 } 70 }
(...skipping 416 matching lines...) Expand 10 before | Expand all | Expand 10 after
486 class MacOSMutex : public Mutex { 487 class MacOSMutex : public Mutex {
487 public: 488 public:
488 489
489 MacOSMutex() { 490 MacOSMutex() {
490 pthread_mutexattr_t attr; 491 pthread_mutexattr_t attr;
491 pthread_mutexattr_init(&attr); 492 pthread_mutexattr_init(&attr);
492 pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE); 493 pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
493 pthread_mutex_init(&mutex_, &attr); 494 pthread_mutex_init(&mutex_, &attr);
494 } 495 }
495 496
496 ~MacOSMutex() { pthread_mutex_destroy(&mutex_); } 497 virtual ~MacOSMutex() { pthread_mutex_destroy(&mutex_); }
497 498
498 int Lock() { return pthread_mutex_lock(&mutex_); } 499 virtual int Lock() { return pthread_mutex_lock(&mutex_); }
500 virtual int Unlock() { return pthread_mutex_unlock(&mutex_); }
499 501
500 int Unlock() { return pthread_mutex_unlock(&mutex_); } 502 virtual bool TryLock() {
503 int result = pthread_mutex_trylock(&mutex_);
504 // Return false if the lock is busy and locking failed.
505 if (result == EBUSY) {
506 return false;
507 }
508 ASSERT(result == 0); // Verify no other errors.
509 return true;
510 }
501 511
502 private: 512 private:
503 pthread_mutex_t mutex_; 513 pthread_mutex_t mutex_;
504 }; 514 };
505 515
506 516
507 Mutex* OS::CreateMutex() { 517 Mutex* OS::CreateMutex() {
508 return new MacOSMutex(); 518 return new MacOSMutex();
509 } 519 }
510 520
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
543 553
544 Semaphore* OS::CreateSemaphore(int count) { 554 Semaphore* OS::CreateSemaphore(int count) {
545 return new MacOSSemaphore(count); 555 return new MacOSSemaphore(count);
546 } 556 }
547 557
548 558
549 #ifdef ENABLE_LOGGING_AND_PROFILING 559 #ifdef ENABLE_LOGGING_AND_PROFILING
550 560
551 class Sampler::PlatformData : public Malloced { 561 class Sampler::PlatformData : public Malloced {
552 public: 562 public:
553 explicit PlatformData(Sampler* sampler) 563 PlatformData() : profiled_thread_(mach_thread_self()) {}
554 : sampler_(sampler), 564
555 task_self_(mach_task_self()), 565 ~PlatformData() {
556 profiled_thread_(0), 566 // Deallocate Mach port for thread.
557 sampler_thread_(0) { 567 mach_port_deallocate(mach_task_self(), profiled_thread_);
558 } 568 }
559 569
560 Sampler* sampler_; 570 thread_act_t profiled_thread() { return profiled_thread_; }
571
572 private:
561 // Note: for profiled_thread_ Mach primitives are used instead of PThread's 573 // Note: for profiled_thread_ Mach primitives are used instead of PThread's
562 // because the latter doesn't provide thread manipulation primitives required. 574 // because the latter doesn't provide thread manipulation primitives required.
563 // For details, consult "Mac OS X Internals" book, Section 7.3. 575 // For details, consult "Mac OS X Internals" book, Section 7.3.
564 mach_port_t task_self_;
565 thread_act_t profiled_thread_; 576 thread_act_t profiled_thread_;
566 pthread_t sampler_thread_; 577 };
567 578
568 // Sampler thread handler. 579 class SamplerThread : public Thread {
569 void Runner() { 580 public:
570 // Loop until the sampler is disengaged, keeping the specified 581 explicit SamplerThread(int interval) : Thread(NULL), interval_(interval) {}
571 // sampling frequency.
572 for ( ; sampler_->IsActive(); OS::Sleep(sampler_->interval_)) {
573 TickSample sample_obj;
574 TickSample* sample = CpuProfiler::TickSampleEvent();
575 if (sample == NULL) sample = &sample_obj;
576 582
577 // If the sampler runs in sync with the JS thread, we try to 583 static void AddActiveSampler(Sampler* sampler) {
578 // suspend it. If we fail, we skip the current sample. 584 ScopedLock lock(mutex_);
579 if (sampler_->IsSynchronous()) { 585 SamplerRegistry::AddActiveSampler(sampler);
580 if (KERN_SUCCESS != thread_suspend(profiled_thread_)) continue; 586 if (instance_ == NULL) {
587 instance_ = new SamplerThread(sampler->interval());
588 instance_->Start();
589 } else {
590 ASSERT(instance_->interval_ == sampler->interval());
591 }
592 }
593
594 static void RemoveActiveSampler(Sampler* sampler) {
595 ScopedLock lock(mutex_);
596 SamplerRegistry::RemoveActiveSampler(sampler);
597 if (SamplerRegistry::GetState() == SamplerRegistry::HAS_NO_SAMPLERS) {
598 RuntimeProfiler::WakeUpRuntimeProfilerThreadBeforeShutdown();
599 instance_->Join();
600 delete instance_;
601 instance_ = NULL;
602 }
603 }
604
605 // Implement Thread::Run().
606 virtual void Run() {
607 SamplerRegistry::State state = SamplerRegistry::GetState();
608 while (state != SamplerRegistry::HAS_NO_SAMPLERS) {
609 bool cpu_profiling_enabled =
610 (state == SamplerRegistry::HAS_CPU_PROFILING_SAMPLERS);
611 bool runtime_profiler_enabled = RuntimeProfiler::IsEnabled();
612 // When CPU profiling is enabled both JavaScript and C++ code is
613 // profiled. We must not suspend.
614 if (!cpu_profiling_enabled) {
615 if (rate_limiter_.SuspendIfNecessary()) continue;
581 } 616 }
617 if (cpu_profiling_enabled) {
618 if (!SamplerRegistry::IterateActiveSamplers(&DoCpuProfile, this)) {
619 return;
620 }
621 }
622 if (runtime_profiler_enabled) {
623 if (!SamplerRegistry::IterateActiveSamplers(&DoRuntimeProfile, NULL)) {
624 return;
625 }
626 }
627 OS::Sleep(interval_);
628 }
629 }
582 630
583 // We always sample the VM state. 631 static void DoCpuProfile(Sampler* sampler, void* raw_sampler_thread) {
584 sample->state = VMState::current_state(); 632 if (!sampler->IsProfiling()) return;
633 SamplerThread* sampler_thread =
634 reinterpret_cast<SamplerThread*>(raw_sampler_thread);
635 sampler_thread->SampleContext(sampler);
636 }
585 637
586 // If profiling, we record the pc and sp of the profiled thread. 638 static void DoRuntimeProfile(Sampler* sampler, void* ignored) {
587 if (sampler_->IsProfiling()) { 639 if (!sampler->isolate()->IsInitialized()) return;
640 sampler->isolate()->runtime_profiler()->NotifyTick();
641 }
642
643 void SampleContext(Sampler* sampler) {
644 thread_act_t profiled_thread = sampler->platform_data()->profiled_thread();
645 TickSample sample_obj;
646 TickSample* sample = CpuProfiler::TickSampleEvent(sampler->isolate());
647 if (sample == NULL) sample = &sample_obj;
648
649 if (KERN_SUCCESS != thread_suspend(profiled_thread)) return;
650
588 #if V8_HOST_ARCH_X64 651 #if V8_HOST_ARCH_X64
589 thread_state_flavor_t flavor = x86_THREAD_STATE64; 652 thread_state_flavor_t flavor = x86_THREAD_STATE64;
590 x86_thread_state64_t state; 653 x86_thread_state64_t state;
591 mach_msg_type_number_t count = x86_THREAD_STATE64_COUNT; 654 mach_msg_type_number_t count = x86_THREAD_STATE64_COUNT;
592 #if __DARWIN_UNIX03 655 #if __DARWIN_UNIX03
593 #define REGISTER_FIELD(name) __r ## name 656 #define REGISTER_FIELD(name) __r ## name
594 #else 657 #else
595 #define REGISTER_FIELD(name) r ## name 658 #define REGISTER_FIELD(name) r ## name
596 #endif // __DARWIN_UNIX03 659 #endif // __DARWIN_UNIX03
597 #elif V8_HOST_ARCH_IA32 660 #elif V8_HOST_ARCH_IA32
598 thread_state_flavor_t flavor = i386_THREAD_STATE; 661 thread_state_flavor_t flavor = i386_THREAD_STATE;
599 i386_thread_state_t state; 662 i386_thread_state_t state;
600 mach_msg_type_number_t count = i386_THREAD_STATE_COUNT; 663 mach_msg_type_number_t count = i386_THREAD_STATE_COUNT;
601 #if __DARWIN_UNIX03 664 #if __DARWIN_UNIX03
602 #define REGISTER_FIELD(name) __e ## name 665 #define REGISTER_FIELD(name) __e ## name
603 #else 666 #else
604 #define REGISTER_FIELD(name) e ## name 667 #define REGISTER_FIELD(name) e ## name
605 #endif // __DARWIN_UNIX03 668 #endif // __DARWIN_UNIX03
606 #else 669 #else
607 #error Unsupported Mac OS X host architecture. 670 #error Unsupported Mac OS X host architecture.
608 #endif // V8_HOST_ARCH 671 #endif // V8_HOST_ARCH
609 672
610 if (thread_get_state(profiled_thread_, 673 if (thread_get_state(profiled_thread,
611 flavor, 674 flavor,
612 reinterpret_cast<natural_t*>(&state), 675 reinterpret_cast<natural_t*>(&state),
613 &count) == KERN_SUCCESS) { 676 &count) == KERN_SUCCESS) {
614 sample->pc = reinterpret_cast<Address>(state.REGISTER_FIELD(ip)); 677 sample->state = sampler->isolate()->current_vm_state();
615 sample->sp = reinterpret_cast<Address>(state.REGISTER_FIELD(sp)); 678 sample->pc = reinterpret_cast<Address>(state.REGISTER_FIELD(ip));
616 sample->fp = reinterpret_cast<Address>(state.REGISTER_FIELD(bp)); 679 sample->sp = reinterpret_cast<Address>(state.REGISTER_FIELD(sp));
617 sampler_->SampleStack(sample); 680 sample->fp = reinterpret_cast<Address>(state.REGISTER_FIELD(bp));
618 } 681 sampler->SampleStack(sample);
619 } 682 sampler->Tick(sample);
683 }
684 thread_resume(profiled_thread);
685 }
620 686
621 // Invoke tick handler with program counter and stack pointer. 687 const int interval_;
622 sampler_->Tick(sample); 688 RuntimeProfilerRateLimiter rate_limiter_;
623 689
624 // If the sampler runs in sync with the JS thread, we have to 690 // Protects the process wide state below.
625 // remember to resume it. 691 static Mutex* mutex_;
626 if (sampler_->IsSynchronous()) thread_resume(profiled_thread_); 692 static SamplerThread* instance_;
627 } 693
628 } 694 DISALLOW_COPY_AND_ASSIGN(SamplerThread);
629 }; 695 };
630 696
631 #undef REGISTER_FIELD 697 #undef REGISTER_FIELD
632 698
633 699
634 // Entry point for sampler thread. 700 Mutex* SamplerThread::mutex_ = OS::CreateMutex();
635 static void* SamplerEntry(void* arg) { 701 SamplerThread* SamplerThread::instance_ = NULL;
636 Sampler::PlatformData* data =
637 reinterpret_cast<Sampler::PlatformData*>(arg);
638 Thread::SetThreadLocal(Isolate::isolate_key(), data->sampler_->isolate());
639 data->Runner();
640 return 0;
641 }
642 702
643 703
644 Sampler::Sampler(Isolate* isolate, int interval, bool profiling) 704 Sampler::Sampler(Isolate* isolate, int interval)
645 : isolate_(isolate), 705 : isolate_(isolate),
646 interval_(interval), 706 interval_(interval),
647 synchronous_(profiling), 707 profiling_(false),
648 profiling_(profiling),
649 active_(false), 708 active_(false),
650 samples_taken_(0) { 709 samples_taken_(0) {
651 data_ = new PlatformData(this); 710 data_ = new PlatformData;
652 } 711 }
653 712
654 713
655 Sampler::~Sampler() { 714 Sampler::~Sampler() {
715 ASSERT(!IsActive());
656 delete data_; 716 delete data_;
657 } 717 }
658 718
659 719
660 void Sampler::Start() { 720 void Sampler::Start() {
661 // If we are starting a synchronous sampler, we need to be able to 721 ASSERT(!IsActive());
662 // access the calling thread. 722 SetActive(true);
663 if (IsSynchronous()) { 723 SamplerThread::AddActiveSampler(this);
664 data_->profiled_thread_ = mach_thread_self();
665 }
666
667 // Create sampler thread with high priority.
668 // According to POSIX spec, when SCHED_FIFO policy is used, a thread
669 // runs until it exits or blocks.
670 pthread_attr_t sched_attr;
671 sched_param fifo_param;
672 pthread_attr_init(&sched_attr);
673 pthread_attr_setinheritsched(&sched_attr, PTHREAD_EXPLICIT_SCHED);
674 pthread_attr_setschedpolicy(&sched_attr, SCHED_FIFO);
675 fifo_param.sched_priority = sched_get_priority_max(SCHED_FIFO);
676 pthread_attr_setschedparam(&sched_attr, &fifo_param);
677
678 active_ = true;
679 pthread_create(&data_->sampler_thread_, &sched_attr, SamplerEntry, data_);
680 } 724 }
681 725
682 726
683 void Sampler::Stop() { 727 void Sampler::Stop() {
684 // Seting active to false triggers termination of the sampler 728 ASSERT(IsActive());
685 // thread. 729 SamplerThread::RemoveActiveSampler(this);
686 active_ = false; 730 SetActive(false);
687
688 // Wait for sampler thread to terminate.
689 pthread_join(data_->sampler_thread_, NULL);
690
691 // Deallocate Mach port for thread.
692 if (IsSynchronous()) {
693 mach_port_deallocate(data_->task_self_, data_->profiled_thread_);
694 }
695 } 731 }
696 732
697 #endif // ENABLE_LOGGING_AND_PROFILING 733 #endif // ENABLE_LOGGING_AND_PROFILING
698 734
699 } } // namespace v8::internal 735 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/platform-linux.cc ('k') | src/platform-nullos.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698