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(¤t->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(¤t->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