| 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
|
|
|
|
|