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

Reply via email to