| Index: runtime/vm/thread_registry.h | 
| diff --git a/runtime/vm/thread_registry.h b/runtime/vm/thread_registry.h | 
| index 20f4d95d55da3a53a40d95ba0fc4afce8405145c..51ebceb46dbefed785cc0123941ed45b0e7ba6bc 100644 | 
| --- a/runtime/vm/thread_registry.h | 
| +++ b/runtime/vm/thread_registry.h | 
| @@ -19,13 +19,17 @@ class ThreadRegistry { | 
| public: | 
| ThreadRegistry() | 
| : monitor_(new Monitor()), | 
| -        entries_(), | 
| +        active_list_(NULL), | 
| +        free_list_(NULL), | 
| +        mutator_thread_(NULL), | 
| in_rendezvous_(false), | 
| remaining_(0), | 
| round_(0) {} | 
|  | 
| ~ThreadRegistry(); | 
|  | 
| +  Thread* active_list() const { return active_list_; } | 
| + | 
| // Bring all threads in this isolate to a safepoint. The caller is | 
| // expected to be implicitly at a safepoint. The threads will wait | 
| // until ResumeAllThreads is called. First participates in any | 
| @@ -48,145 +52,13 @@ class ThreadRegistry { | 
| CheckSafepointLocked(); | 
| } | 
|  | 
| -  bool RestoreStateTo(Thread* thread, Thread::State* state, | 
| -                      bool bypass_safepoint) { | 
| -    MonitorLocker ml(monitor_); | 
| -    // Wait for any rendezvous in progress. | 
| -    while (!bypass_safepoint && in_rendezvous_) { | 
| -      ml.Wait(Monitor::kNoTimeout); | 
| -    } | 
| -    Entry* entry = FindEntry(thread); | 
| -    if (entry != NULL) { | 
| -      Thread::State st = entry->state; | 
| -      // TODO(koda): Support same thread re-entering same isolate with | 
| -      // Dart frames in between. For now, just assert it doesn't happen. | 
| -      if (st.top_exit_frame_info != thread->top_exit_frame_info()) { | 
| -        ASSERT(thread->top_exit_frame_info() == 0 || | 
| -               thread->top_exit_frame_info() > st.top_exit_frame_info); | 
| -      } | 
| -      ASSERT(!entry->scheduled); | 
| -      entry->scheduled = true; | 
| -#if defined(DEBUG) | 
| -      // State field is not in use, so zap it. | 
| -      memset(&entry->state, 0xda, sizeof(entry->state)); | 
| -#endif | 
| -      *state = st; | 
| -      return true; | 
| -    } | 
| -    Entry new_entry; | 
| -    new_entry.thread = thread; | 
| -    new_entry.scheduled = true; | 
| -#if defined(DEBUG) | 
| -    // State field is not in use, so zap it. | 
| -    memset(&new_entry.state, 0xda, sizeof(new_entry.state)); | 
| -#endif | 
| -    entries_.Add(new_entry); | 
| -    return false; | 
| -  } | 
| - | 
| -  void SaveStateFrom(Thread* thread, const Thread::State& state, | 
| -                     bool bypass_safepoint) { | 
| -    MonitorLocker ml(monitor_); | 
| -    Entry* entry = FindEntry(thread); | 
| -    ASSERT(entry != NULL); | 
| -    ASSERT(entry->scheduled); | 
| -    entry->scheduled = false; | 
| -    entry->state = state; | 
| -    if (!bypass_safepoint && in_rendezvous_) { | 
| -      // Don't wait for this thread. | 
| -      ASSERT(remaining_ > 0); | 
| -      if (--remaining_ == 0) { | 
| -        ml.NotifyAll(); | 
| -      } | 
| -    } | 
| -  } | 
| - | 
| -  bool Contains(Thread* thread) { | 
| -    MonitorLocker ml(monitor_); | 
| -    return (FindEntry(thread) != NULL); | 
| -  } | 
| - | 
| -  void CheckNotScheduled(Isolate* isolate) { | 
| -    MonitorLocker ml(monitor_); | 
| -    for (int i = 0; i < entries_.length(); ++i) { | 
| -      const Entry& entry = entries_[i]; | 
| -      if (entry.scheduled) { | 
| -        FATAL3("Isolate %p still scheduled on %p (whose isolate_ is %p)\n", | 
| -               isolate, | 
| -               entry.thread, | 
| -               entry.thread->isolate()); | 
| -      } | 
| -    } | 
| -  } | 
| - | 
| -  void VisitObjectPointers(ObjectPointerVisitor* visitor, | 
| -                           bool validate_frames) { | 
| -    MonitorLocker ml(monitor_); | 
| -    for (int i = 0; i < entries_.length(); ++i) { | 
| -      const Entry& entry = entries_[i]; | 
| -      const Thread::State& state = | 
| -          entry.scheduled ? entry.thread->state_ : entry.state; | 
| -      if (state.zone != NULL) { | 
| -        state.zone->VisitObjectPointers(visitor); | 
| -      } | 
| -      if (entry.scheduled) { | 
| -        ASSERT(entry.thread != NULL); | 
| -        entry.thread->VisitObjectPointers(visitor); | 
| -      } | 
| -      // Iterate over all the stack frames and visit objects on the stack. | 
| -      StackFrameIterator frames_iterator(state.top_exit_frame_info, | 
| -                                         validate_frames); | 
| -      StackFrame* frame = frames_iterator.NextFrame(); | 
| -      while (frame != NULL) { | 
| -        frame->VisitObjectPointers(visitor); | 
| -        frame = frames_iterator.NextFrame(); | 
| -      } | 
| -    } | 
| -  } | 
| - | 
| -  void PruneThread(Thread* thread); | 
| - | 
| -  void ReclaimTimelineBlocks(); | 
| - | 
| -  struct Entry { | 
| -    // NOTE: |thread| is deleted automatically when the thread exits. | 
| -    // In other words, it is not safe to dereference |thread| unless you are on | 
| -    // the thread itself. | 
| -    Thread* thread; | 
| -    bool scheduled; | 
| -    Thread::State state; | 
| -  }; | 
| - | 
| -  class EntryIterator { | 
| -   public: | 
| -    explicit EntryIterator(ThreadRegistry* registry); | 
| -    ~EntryIterator(); | 
| - | 
| -    // Returns false when there are no more entries. | 
| -    bool HasNext() const; | 
| - | 
| -    // Returns the next entry and moves forward. | 
| -    const Entry& Next(); | 
| - | 
| -   private: | 
| -    void Reset(ThreadRegistry* registry); | 
| - | 
| -    intptr_t index_; | 
| -    ThreadRegistry* registry_; | 
| -  }; | 
| +  Thread* Schedule(Isolate* isolate, bool is_mutator, bool bypass_safepoint); | 
| +  void Unschedule(Thread* thread, bool is_mutator, bool bypass_safepoint); | 
| +  void VisitObjectPointers(ObjectPointerVisitor* visitor, bool validate_frames); | 
|  | 
| private: | 
| -  // Returns Entry corresponding to thread in registry or NULL. | 
| -  // Note: Lock should be taken before this function is called. | 
| -  // TODO(koda): Add method Monitor::IsOwnedByCurrentThread. | 
| -  Entry* FindEntry(Thread* thread) { | 
| -    for (int i = 0; i < entries_.length(); ++i) { | 
| -      if (entries_[i].thread == thread) { | 
| -        return &entries_[i]; | 
| -      } | 
| -    } | 
| -    return NULL; | 
| -  } | 
| +  Thread* GetThreadFromFreelist(Isolate* isolate); | 
| +  void ReturnThreadToFreelist(Thread* thread); | 
|  | 
| // Note: Lock should be taken before this function is called. | 
| void CheckSafepointLocked(); | 
| @@ -196,7 +68,16 @@ class ThreadRegistry { | 
| intptr_t CountScheduledLocked(); | 
|  | 
| Monitor* monitor_;  // All access is synchronized through this monitor. | 
| -  MallocGrowableArray<Entry> entries_; | 
| +  Thread* active_list_;  // List of active threads in the isolate. | 
| +  Thread* free_list_;  // Free list of Thread objects that can be reused. | 
| +  // TODO(asiva): Currently we treat a mutator thread as a special thread | 
| +  // and always schedule execution of Dart code on the same mutator thread | 
| +  // object. This is because ApiState is still an object associated with | 
| +  // the isolate and switching execution to another thread causes problems. | 
| +  // Once ApiState is made a per Thread object it should be possible to | 
| +  // free a mutator thread like all other threads and continue running on | 
| +  // a different thread. | 
| +  Thread* mutator_thread_; | 
|  | 
| // Safepoint rendezvous state. | 
| bool in_rendezvous_;    // A safepoint rendezvous request is in progress. | 
|  |