Revision: 3128 Author: [email protected] Date: Mon Oct 26 05:54:41 2009 Log: Allocate global handles in chunks.
Review URL: http://codereview.chromium.org/327008 http://code.google.com/p/v8/source/detail?r=3128 Modified: /branches/bleeding_edge/src/global-handles.cc /branches/bleeding_edge/src/global-handles.h ======================================= --- /branches/bleeding_edge/src/global-handles.cc Thu Oct 15 00:50:23 2009 +++ /branches/bleeding_edge/src/global-handles.cc Mon Oct 26 05:54:41 2009 @@ -43,6 +43,10 @@ parameter_or_next_free_.parameter = NULL; callback_ = NULL; } + + Node() { + state_ = DESTROYED; + } explicit Node(Object* object) { Initialize(object); @@ -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 << 12) - 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) { - // Allocate a new node. - result = new Node(value); - result->set_next(head()); - set_head(result); - } else { + if (first_free()) { // Take the first node in the free list. result = first_free(); set_first_free(result->next_free()); - result->Initialize(value); - } + } 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 = pool_.Allocate(); + result->set_next(head()); + set_head(result); + } + 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 ======================================= --- /branches/bleeding_edge/src/global-handles.h Thu Oct 15 00:50:23 2009 +++ /branches/bleeding_edge/src/global-handles.h Mon Oct 26 05:54:41 2009 @@ -127,6 +127,7 @@ static void PrintStats(); static void Print(); #endif + class Pool; private: // Internal node structure, one for each global handle. class Node; @@ -148,6 +149,23 @@ static Node* first_free_; static Node* first_free() { return first_free_; } static void set_first_free(Node* value) { first_free_ = value; } + + // List of deallocated nodes. + // Deallocated nodes form a prefix of all the nodes and + // |first_deallocated| points to last deallocated node before + // |head|. Those deallocated nodes are additionally linked + // by |next_free|: + // 1st deallocated head + // | | + // V V + // node node ... node node + // .next -> .next -> .next -> + // <- .next_free <- .next_free <- .next_free + static Node* first_deallocated_; + static Node* first_deallocated() { return first_deallocated_; } + static void set_first_deallocated(Node* value) { + first_deallocated_ = value; + } }; --~--~---------~--~----~------------~-------~--~----~ v8-dev mailing list [email protected] http://groups.google.com/group/v8-dev -~----------~----~----~----~------~----~------~--~---
