Update V8 to r3431 as required by WebKit r51976.

Change-Id: I567392c3f8c0a0d5201a4249611ac4ccf468cd5b
diff --git a/src/global-handles.cc b/src/global-handles.cc
index f4b69fc..1a0c982 100644
--- a/src/global-handles.cc
+++ b/src/global-handles.cc
@@ -44,6 +44,10 @@
     callback_ = NULL;
   }
 
+  Node() {
+    state_ = DESTROYED;
+  }
+
   explicit Node(Object* object) {
     Initialize(object);
     // Initialize link structure.
@@ -161,6 +165,9 @@
       // It's fine though to reuse nodes that were destroyed in weak callback
       // as those cannot be deallocated until we are back from the callback.
       set_first_free(NULL);
+      if (first_deallocated()) {
+        first_deallocated()->set_next(head());
+      }
       // Leaving V8.
       VMState state(EXTERNAL);
       func(object, par);
@@ -200,20 +207,81 @@
 };
 
 
+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());
+    ASSERT(result->next() == head());
+    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 +360,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,17 +378,24 @@
       // 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());
+  }
 }
 
 
-void GlobalHandles::IterateRoots(ObjectVisitor* v) {
-  // Traversal of global handles marked as NORMAL or NEAR_DEATH.
+void GlobalHandles::IterateStrongRoots(ObjectVisitor* v) {
+  // Traversal of global handles marked as NORMAL.
   for (Node* current = head_; current != NULL; current = current->next()) {
     if (current->state_ == Node::NORMAL) {
       v->VisitPointer(&current->object_);
@@ -328,17 +403,22 @@
   }
 }
 
-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;
+
+void GlobalHandles::IterateAllRoots(ObjectVisitor* v) {
+  for (Node* current = head_; current != NULL; current = current->next()) {
+    if (current->state_ != Node::DESTROYED) {
+      v->VisitPointer(&current->object_);
+    }
   }
-  // Reset the head and free_list.
+}
+
+
+void GlobalHandles::TearDown() {
+  // Reset all the lists.
   set_head(NULL);
   set_first_free(NULL);
+  set_first_deallocated(NULL);
+  pool_.Release();
 }
 
 
@@ -347,6 +427,27 @@
 
 GlobalHandles::Node* GlobalHandles::head_ = NULL;
 GlobalHandles::Node* GlobalHandles::first_free_ = NULL;
+GlobalHandles::Node* GlobalHandles::first_deallocated_ = NULL;
+
+void GlobalHandles::RecordStats(HeapStats* stats) {
+  *stats->global_handle_count = 0;
+  *stats->weak_global_handle_count = 0;
+  *stats->pending_global_handle_count = 0;
+  *stats->near_death_global_handle_count = 0;
+  *stats->destroyed_global_handle_count = 0;
+  for (Node* current = head_; current != NULL; current = current->next()) {
+    *stats->global_handle_count += 1;
+    if (current->state_ == Node::WEAK) {
+      *stats->weak_global_handle_count += 1;
+    } else if (current->state_ == Node::PENDING) {
+      *stats->pending_global_handle_count += 1;
+    } else if (current->state_ == Node::NEAR_DEATH) {
+      *stats->near_death_global_handle_count += 1;
+    } else if (current->state_ == Node::DESTROYED) {
+      *stats->destroyed_global_handle_count += 1;
+    }
+  }
+}
 
 #ifdef DEBUG