| Index: src/global-handles.cc | 
| =================================================================== | 
| --- src/global-handles.cc	(revision 3093) | 
| +++ src/global-handles.cc	(working copy) | 
| @@ -44,6 +44,10 @@ | 
| callback_ = NULL; | 
| } | 
|  | 
| +  Node() { | 
| +    state_ = DESTROYED; | 
| +  } | 
| + | 
| explicit Node(Object* object) { | 
| Initialize(object); | 
| // Initialize link structure. | 
| @@ -200,20 +204,80 @@ | 
| }; | 
|  | 
|  | 
| +class GlobalHandles::Pool BASE_EMBEDDED { | 
| +  public: | 
| +    Pool() { | 
| +      current_ = new Chunk(); | 
| +      current_->previous = NULL; | 
| +      next_ = current_->nodes; | 
| +      limit_ = current_->nodes + kNodesPerChunk; | 
| +    } | 
| + | 
| +    Node* Allocate() { | 
| +      if (next_ < limit_) { | 
| +        return next_++; | 
| +      } | 
| +      return SlowAllocate(); | 
| +    } | 
| + | 
| +    void Release() { | 
| +      Chunk* current = current_; | 
| +      ASSERT(current != NULL);  // At least a single block must by allocated | 
| +      do { | 
| +        Chunk* previous = current->previous; | 
| +        delete current; | 
| +        current = previous; | 
| +      } while (current != NULL); | 
| +      current_ = NULL; | 
| +      next_ = limit_ = NULL; | 
| +    } | 
| + | 
| +  private: | 
| +    static const int kNodesPerChunk = (1 << 13) - 1; | 
| +    struct Chunk : public Malloced { | 
| +      Chunk* previous; | 
| +      Node nodes[kNodesPerChunk]; | 
| +    }; | 
| + | 
| +    Node* SlowAllocate() { | 
| +      Chunk* chunk = new Chunk(); | 
| +      chunk->previous = current_; | 
| +      current_ = chunk; | 
| + | 
| +      Node* new_nodes = current_->nodes; | 
| +      next_ = new_nodes + 1; | 
| +      limit_ = new_nodes + kNodesPerChunk; | 
| +      return new_nodes; | 
| +    } | 
| + | 
| +    Chunk* current_; | 
| +    Node* next_; | 
| +    Node* limit_; | 
| +}; | 
| + | 
| + | 
| +static GlobalHandles::Pool pool_; | 
| + | 
| + | 
| Handle<Object> GlobalHandles::Create(Object* value) { | 
| Counters::global_handles.Increment(); | 
| Node* result; | 
| -  if (first_free() == NULL) { | 
| +  if (first_free()) { | 
| +    // Take the first node in the free list. | 
| +    result = first_free(); | 
| +    set_first_free(result->next_free()); | 
| +  } else if (first_deallocated()) { | 
| +    // Next try deallocated list | 
| +    result = first_deallocated(); | 
| +    set_first_deallocated(result->next_free()); | 
| +    set_head(result); | 
| +  } else { | 
| // Allocate a new node. | 
| -    result = new Node(value); | 
| +    result = pool_.Allocate(); | 
| result->set_next(head()); | 
| set_head(result); | 
| -  } else { | 
| -    // Take the first node in the free list. | 
| -    result = first_free(); | 
| -    set_first_free(result->next_free()); | 
| -    result->Initialize(value); | 
| } | 
| +  result->Initialize(value); | 
| return result->handle(); | 
| } | 
|  | 
| @@ -292,7 +356,7 @@ | 
| // Process weak global handle callbacks. This must be done after the | 
| // GC is completely done, because the callbacks may invoke arbitrary | 
| // API functions. | 
| -  // At the same time deallocate all DESTROYED nodes | 
| +  // At the same time deallocate all DESTROYED nodes. | 
| ASSERT(Heap::gc_state() == Heap::NOT_IN_GC); | 
| const int initial_post_gc_processing_count = ++post_gc_processing_count; | 
| Node** p = &head_; | 
| @@ -310,12 +374,19 @@ | 
| // Delete the link. | 
| Node* node = *p; | 
| *p = node->next();  // Update the link. | 
| -      delete node; | 
| +      if (first_deallocated()) { | 
| +        first_deallocated()->set_next(node); | 
| +      } | 
| +      node->set_next_free(first_deallocated()); | 
| +      set_first_deallocated(node); | 
| } else { | 
| p = (*p)->next_addr(); | 
| } | 
| } | 
| set_first_free(NULL); | 
| +  if (first_deallocated()) { | 
| +    first_deallocated()->set_next(head()); | 
| +  } | 
| } | 
|  | 
|  | 
| @@ -329,16 +400,11 @@ | 
| } | 
|  | 
| void GlobalHandles::TearDown() { | 
| -  // Delete all the nodes in the linked list. | 
| -  Node* current = head_; | 
| -  while (current != NULL) { | 
| -    Node* n = current; | 
| -    current = current->next(); | 
| -    delete n; | 
| -  } | 
| -  // Reset the head and free_list. | 
| +  // Reset all the lists. | 
| set_head(NULL); | 
| set_first_free(NULL); | 
| +  set_first_deallocated(NULL); | 
| +  pool_.Release(); | 
| } | 
|  | 
|  | 
| @@ -347,6 +413,7 @@ | 
|  | 
| GlobalHandles::Node* GlobalHandles::head_ = NULL; | 
| GlobalHandles::Node* GlobalHandles::first_free_ = NULL; | 
| +GlobalHandles::Node* GlobalHandles::first_deallocated_ = NULL; | 
|  | 
| #ifdef DEBUG | 
|  | 
|  |