| Index: runtime/vm/thread_registry.cc
 | 
| diff --git a/runtime/vm/thread_registry.cc b/runtime/vm/thread_registry.cc
 | 
| index 2d2dee3f0357aa008b12f2beee6adf33ec663029..111ae57596f7cd3ddceca27cd9eb9cf1e0cf242d 100644
 | 
| --- a/runtime/vm/thread_registry.cc
 | 
| +++ b/runtime/vm/thread_registry.cc
 | 
| @@ -12,7 +12,7 @@ namespace dart {
 | 
|  ThreadRegistry::~ThreadRegistry() {
 | 
|    // Go over the free thread list and delete the thread objects.
 | 
|    {
 | 
| -    MonitorLocker ml(monitor_);
 | 
| +    MonitorLocker ml(threads_lock());
 | 
|      // At this point the active list should be empty.
 | 
|      ASSERT(active_list_ == NULL);
 | 
|      // We have cached the mutator thread, delete it.
 | 
| @@ -27,114 +27,44 @@ ThreadRegistry::~ThreadRegistry() {
 | 
|    }
 | 
|  
 | 
|    // Delete monitor.
 | 
| -  delete monitor_;
 | 
| +  delete threads_lock_;
 | 
|  }
 | 
|  
 | 
|  
 | 
| -void ThreadRegistry::SafepointThreads() {
 | 
| -  MonitorLocker ml(monitor_);
 | 
| -  // First wait for any older rounds that are still in progress.
 | 
| -  while (in_rendezvous_) {
 | 
| -    // Assert we are not the organizer trying to nest calls to SafepointThreads.
 | 
| -    ASSERT(remaining_ > 0);
 | 
| -    CheckSafepointLocked();
 | 
| -  }
 | 
| -  // Start a new round.
 | 
| -  in_rendezvous_ = true;
 | 
| -  ++round_;  // Overflows after 240+ years @ 10^9 safepoints per second.
 | 
| -  remaining_ = CountScheduledLocked();
 | 
| -  Isolate* isolate = Isolate::Current();
 | 
| -  // We only expect this method to be called from within the isolate itself.
 | 
| -  ASSERT(isolate->thread_registry() == this);
 | 
| -  --remaining_;  // Exclude this thread from the count.
 | 
| -  // Ensure the main mutator will reach a safepoint (could be running Dart).
 | 
| -  if (!Thread::Current()->IsMutatorThread()) {
 | 
| -    isolate->ScheduleInterrupts(Isolate::kVMInterrupt);
 | 
| -  }
 | 
| -  while (remaining_ > 0) {
 | 
| -    ml.Wait(Monitor::kNoTimeout);
 | 
| -  }
 | 
| -}
 | 
| -
 | 
| -
 | 
| -void ThreadRegistry::ResumeAllThreads() {
 | 
| -  MonitorLocker ml(monitor_);
 | 
| -  ASSERT(in_rendezvous_);
 | 
| -  in_rendezvous_ = false;
 | 
| -  ml.NotifyAll();
 | 
| -}
 | 
| -
 | 
| -
 | 
| -Thread* ThreadRegistry::Schedule(Isolate* isolate,
 | 
| -                                 bool is_mutator,
 | 
| -                                 bool bypass_safepoint) {
 | 
| -  MonitorLocker ml(monitor_);
 | 
| -  // Wait for any rendezvous in progress.
 | 
| -  while (!bypass_safepoint && in_rendezvous_) {
 | 
| -    ml.Wait(Monitor::kNoTimeout);
 | 
| -  }
 | 
| -  Thread* thread = NULL;
 | 
| -  OSThread* os_thread = OSThread::Current();
 | 
| -  if (os_thread != NULL) {
 | 
| -    ASSERT(isolate->heap() != NULL);
 | 
| -    // First get a Thread structure. (we special case the mutator thread
 | 
| -    // by reusing the cached structure, see comment in 'thread_registry.h').
 | 
| -    if (is_mutator) {
 | 
| -      if (mutator_thread_ == NULL) {
 | 
| -        mutator_thread_ = GetThreadFromFreelist(isolate);
 | 
| -      }
 | 
| -      thread = mutator_thread_;
 | 
| -    } else {
 | 
| -      thread = GetThreadFromFreelist(isolate);
 | 
| -      ASSERT(thread->api_top_scope() == NULL);
 | 
| +// Gets a free Thread structure, we special case the mutator thread
 | 
| +// by reusing the cached structure, see comment in 'thread_registry.h'.
 | 
| +Thread* ThreadRegistry::GetFreeThreadLocked(Isolate* isolate, bool is_mutator) {
 | 
| +  ASSERT(threads_lock()->IsOwnedByCurrentThread());
 | 
| +  Thread* thread;
 | 
| +  if (is_mutator) {
 | 
| +    if (mutator_thread_ == NULL) {
 | 
| +      mutator_thread_ = GetFromFreelistLocked(isolate);
 | 
|      }
 | 
| -    // Now add this Thread to the active list for the isolate.
 | 
| -    AddThreadToActiveList(thread);
 | 
| -    // Set up other values and set the TLS value.
 | 
| -    thread->isolate_ = isolate;
 | 
| -    thread->heap_ = isolate->heap();
 | 
| -    thread->set_os_thread(os_thread);
 | 
| -    os_thread->set_thread(thread);
 | 
| -    Thread::SetCurrent(thread);
 | 
| -    os_thread->EnableThreadInterrupts();
 | 
| +    thread = mutator_thread_;
 | 
| +  } else {
 | 
| +    thread = GetFromFreelistLocked(isolate);
 | 
| +    ASSERT(thread->api_top_scope() == NULL);
 | 
|    }
 | 
| +  // Now add this Thread to the active list for the isolate.
 | 
| +  AddToActiveListLocked(thread);
 | 
|    return thread;
 | 
|  }
 | 
|  
 | 
|  
 | 
| -void ThreadRegistry::Unschedule(Thread* thread,
 | 
| -                                bool is_mutator,
 | 
| -                                bool bypass_safepoint) {
 | 
| -  MonitorLocker ml(monitor_);
 | 
| -  OSThread* os_thread = thread->os_thread();
 | 
| -  ASSERT(os_thread != NULL);
 | 
| -  os_thread->DisableThreadInterrupts();
 | 
| -  os_thread->set_thread(NULL);
 | 
| -  OSThread::SetCurrent(os_thread);
 | 
| -  thread->isolate_ = NULL;
 | 
| -  thread->heap_ = NULL;
 | 
| -  thread->set_os_thread(NULL);
 | 
| +void ThreadRegistry::ReturnThreadLocked(bool is_mutator, Thread* thread) {
 | 
| +  ASSERT(threads_lock()->IsOwnedByCurrentThread());
 | 
|    // Remove thread from the active list for the isolate.
 | 
| -  RemoveThreadFromActiveList(thread);
 | 
| -  // Return thread to the free list (we special case the mutator
 | 
| -  // thread by holding on to it, see comment in 'thread_registry.h').
 | 
| +  RemoveFromActiveListLocked(thread);
 | 
|    if (!is_mutator) {
 | 
|      ASSERT(thread->api_top_scope() == NULL);
 | 
| -    ReturnThreadToFreelist(thread);
 | 
| -  }
 | 
| -  if (!bypass_safepoint && in_rendezvous_) {
 | 
| -    // Don't wait for this thread.
 | 
| -    ASSERT(remaining_ > 0);
 | 
| -    if (--remaining_ == 0) {
 | 
| -      ml.NotifyAll();
 | 
| -    }
 | 
| +    ReturnToFreelistLocked(thread);
 | 
|    }
 | 
|  }
 | 
|  
 | 
|  
 | 
|  void ThreadRegistry::VisitObjectPointers(ObjectPointerVisitor* visitor,
 | 
|                                           bool validate_frames) {
 | 
| -  MonitorLocker ml(monitor_);
 | 
| +  MonitorLocker ml(threads_lock());
 | 
|    Thread* thread = active_list_;
 | 
|    while (thread != NULL) {
 | 
|      if (thread->zone() != NULL) {
 | 
| @@ -155,7 +85,7 @@ void ThreadRegistry::VisitObjectPointers(ObjectPointerVisitor* visitor,
 | 
|  
 | 
|  
 | 
|  void ThreadRegistry::PrepareForGC() {
 | 
| -  MonitorLocker ml(monitor_);
 | 
| +  MonitorLocker ml(threads_lock());
 | 
|    Thread* thread = active_list_;
 | 
|    while (thread != NULL) {
 | 
|      thread->PrepareForGC();
 | 
| @@ -164,17 +94,17 @@ void ThreadRegistry::PrepareForGC() {
 | 
|  }
 | 
|  
 | 
|  
 | 
| -void ThreadRegistry::AddThreadToActiveList(Thread* thread) {
 | 
| +void ThreadRegistry::AddToActiveListLocked(Thread* thread) {
 | 
|    ASSERT(thread != NULL);
 | 
| -  ASSERT(monitor_->IsOwnedByCurrentThread());
 | 
| +  ASSERT(threads_lock()->IsOwnedByCurrentThread());
 | 
|    thread->next_ = active_list_;
 | 
|    active_list_ = thread;
 | 
|  }
 | 
|  
 | 
|  
 | 
| -void ThreadRegistry::RemoveThreadFromActiveList(Thread* thread) {
 | 
| +void ThreadRegistry::RemoveFromActiveListLocked(Thread* thread) {
 | 
|    ASSERT(thread != NULL);
 | 
| -  ASSERT(monitor_->IsOwnedByCurrentThread());
 | 
| +  ASSERT(threads_lock()->IsOwnedByCurrentThread());
 | 
|    Thread* prev = NULL;
 | 
|    Thread* current = active_list_;
 | 
|    while (current != NULL) {
 | 
| @@ -192,8 +122,8 @@ void ThreadRegistry::RemoveThreadFromActiveList(Thread* thread) {
 | 
|  }
 | 
|  
 | 
|  
 | 
| -Thread* ThreadRegistry::GetThreadFromFreelist(Isolate* isolate) {
 | 
| -  ASSERT(monitor_->IsOwnedByCurrentThread());
 | 
| +Thread* ThreadRegistry::GetFromFreelistLocked(Isolate* isolate) {
 | 
| +  ASSERT(threads_lock()->IsOwnedByCurrentThread());
 | 
|    Thread* thread = NULL;
 | 
|    // Get thread structure from free list or create a new one.
 | 
|    if (free_list_ == NULL) {
 | 
| @@ -205,51 +135,15 @@ Thread* ThreadRegistry::GetThreadFromFreelist(Isolate* isolate) {
 | 
|    return thread;
 | 
|  }
 | 
|  
 | 
| -void ThreadRegistry::ReturnThreadToFreelist(Thread* thread) {
 | 
| +void ThreadRegistry::ReturnToFreelistLocked(Thread* thread) {
 | 
|    ASSERT(thread != NULL);
 | 
|    ASSERT(thread->os_thread_ == NULL);
 | 
|    ASSERT(thread->isolate_ == NULL);
 | 
|    ASSERT(thread->heap_ == NULL);
 | 
| -  ASSERT(monitor_->IsOwnedByCurrentThread());
 | 
| +  ASSERT(threads_lock()->IsOwnedByCurrentThread());
 | 
|    // Add thread to the free list.
 | 
|    thread->next_ = free_list_;
 | 
|    free_list_ = thread;
 | 
|  }
 | 
|  
 | 
| -
 | 
| -void ThreadRegistry::CheckSafepointLocked() {
 | 
| -  int64_t last_round = -1;
 | 
| -  while (in_rendezvous_) {
 | 
| -    ASSERT(round_ >= last_round);
 | 
| -    if (round_ != last_round) {
 | 
| -      ASSERT((last_round == -1) || (round_ == (last_round + 1)));
 | 
| -      last_round = round_;
 | 
| -      // Participate in this round.
 | 
| -      if (--remaining_ == 0) {
 | 
| -        // Ensure the organizing thread is notified.
 | 
| -        // TODO(koda): Use separate condition variables and plain 'Notify'.
 | 
| -        monitor_->NotifyAll();
 | 
| -      }
 | 
| -    }
 | 
| -    monitor_->Wait(Monitor::kNoTimeout);
 | 
| -    // Note: Here, round_ is needed to detect and distinguish two cases:
 | 
| -    // a) The old rendezvous is still in progress, so just keep waiting, or
 | 
| -    // b) after ResumeAllThreads, another call to SafepointThreads was
 | 
| -    // made before this thread got a chance to reaquire monitor_, thus this
 | 
| -    // thread should (again) decrease remaining_ to indicate cooperation in
 | 
| -    // this new round.
 | 
| -  }
 | 
| -}
 | 
| -
 | 
| -
 | 
| -intptr_t ThreadRegistry::CountScheduledLocked() {
 | 
| -  intptr_t count = 0;
 | 
| -  Thread* current = active_list_;
 | 
| -  while (current != NULL) {
 | 
| -    ++count;
 | 
| -    current = current->next_;
 | 
| -  }
 | 
| -  return count;
 | 
| -}
 | 
| -
 | 
|  }  // namespace dart
 | 
| 
 |