Index: src/global-handles.cc |
diff --git a/src/global-handles.cc b/src/global-handles.cc |
index c4e8f131afa8e1d1c590c2f8643f662449ac1e7f..250f1276494c532d6f8834cb867ffeeed10b2bc5 100644 |
--- a/src/global-handles.cc |
+++ b/src/global-handles.cc |
@@ -48,6 +48,7 @@ class GlobalHandles::Node : public Malloced { |
// Set the initial value of the handle. |
object_ = object; |
class_id_ = v8::HeapProfiler::kPersistentHandleNoClassId; |
+ independent_ = false; |
state_ = NORMAL; |
parameter_or_next_free_.parameter = NULL; |
callback_ = NULL; |
@@ -138,6 +139,13 @@ class GlobalHandles::Node : public Malloced { |
set_parameter(NULL); |
} |
+ void MarkIndependent(GlobalHandles* global_handles) { |
+ LOG(global_handles->isolate(), |
+ HandleEvent("GlobalHandle::MarkIndependent", handle().location())); |
+ ASSERT(state_ != DESTROYED); |
+ independent_ = true; |
+ } |
+ |
bool IsNearDeath() { |
// Check for PENDING to ensure correct answer when processing callbacks. |
return state_ == PENDING || state_ == NEAR_DEATH; |
@@ -222,6 +230,8 @@ class GlobalHandles::Node : public Malloced { |
}; |
State state_ : 4; // Need one more bit for MSVC as it treats enums as signed. |
+ bool independent_ : 1; |
+ |
private: |
// Handle specific callback. |
WeakReferenceCallback callback_; |
@@ -364,6 +374,11 @@ void GlobalHandles::ClearWeakness(Object** location) { |
} |
+void GlobalHandles::MarkIndependent(Object** location) { |
+ Node::FromLocation(location)->MarkIndependent(this); |
+} |
+ |
+ |
bool GlobalHandles::IsNearDeath(Object** location) { |
return Node::FromLocation(location)->IsNearDeath(); |
} |
@@ -381,7 +396,7 @@ void GlobalHandles::SetWrapperClassId(Object** location, uint16_t class_id) { |
void GlobalHandles::IterateWeakRoots(ObjectVisitor* v) { |
// Traversal of GC roots in the global handle list that are marked as |
- // WEAK or PENDING. |
+ // WEAK, PENDING or NEAR_DEATH. |
for (Node* current = head_; current != NULL; current = current->next()) { |
if (current->state_ == Node::WEAK |
|| current->state_ == Node::PENDING |
@@ -392,6 +407,20 @@ void GlobalHandles::IterateWeakRoots(ObjectVisitor* v) { |
} |
+void GlobalHandles::IterateWeakIndependentRoots(ObjectVisitor* v) { |
+ // Traversal of GC roots in the global handle list that are independent |
+ // and marked as WEAK, PENDING or NEAR_DEATH. |
+ for (Node* current = head_; current != NULL; current = current->next()) { |
+ if (!current->independent_) continue; |
+ if (current->state_ == Node::WEAK |
+ || current->state_ == Node::PENDING |
+ || current->state_ == Node::NEAR_DEATH) { |
+ v->VisitPointer(¤t->object_); |
+ } |
+ } |
+} |
+ |
+ |
void GlobalHandles::IterateWeakRoots(WeakReferenceGuest f, |
WeakReferenceCallback callback) { |
for (Node* current = head_; current != NULL; current = current->next()) { |
@@ -415,7 +444,21 @@ void GlobalHandles::IdentifyWeakHandles(WeakSlotCallback f) { |
} |
-bool GlobalHandles::PostGarbageCollectionProcessing() { |
+void GlobalHandles::IdentifyWeakIndependentHandles(WeakSlotCallbackWithHeap f) { |
+ for (Node* current = head_; current != NULL; current = current->next()) { |
+ if (current->state_ == Node::WEAK && current->independent_) { |
+ if (f(isolate_->heap(), ¤t->object_)) { |
+ current->state_ = Node::PENDING; |
+ LOG(isolate_, |
+ HandleEvent("GlobalHandle::Pending", current->handle().location())); |
+ } |
+ } |
+ } |
+} |
+ |
+ |
+bool GlobalHandles::PostGarbageCollectionProcessing( |
+ GarbageCollector collector) { |
// Process weak global handle callbacks. This must be done after the |
// GC is completely done, because the callbacks may invoke arbitrary |
// API functions. |
@@ -425,6 +468,14 @@ bool GlobalHandles::PostGarbageCollectionProcessing() { |
bool next_gc_likely_to_collect_more = false; |
Node** p = &head_; |
while (*p != NULL) { |
+ // Skip dependent handles. Their weak callbacks might expect to be |
+ // called between two global garbage collection callbacks which |
+ // are not called for minor collections. |
+ if (collector == SCAVENGER && !(*p)->independent_) { |
+ p = (*p)->next_addr(); |
+ continue; |
+ } |
+ |
if ((*p)->PostGarbageCollectionProcessing(isolate_, this)) { |
if (initial_post_gc_processing_count != post_gc_processing_count_) { |
// Weak callback triggered another GC and another round of |
@@ -476,6 +527,16 @@ void GlobalHandles::IterateAllRoots(ObjectVisitor* v) { |
} |
+void GlobalHandles::IterateStrongAndDependentRoots(ObjectVisitor* v) { |
+ for (Node* current = head_; current != NULL; current = current->next()) { |
+ if ((current->independent_ && current->state_ == Node::NORMAL) || |
+ (!current->independent_ && current->state_ != Node::DESTROYED)) { |
+ v->VisitPointer(¤t->object_); |
+ } |
+ } |
+} |
+ |
+ |
void GlobalHandles::IterateAllRootsWithClassIds(ObjectVisitor* v) { |
for (Node* current = head_; current != NULL; current = current->next()) { |
if (current->class_id_ != v8::HeapProfiler::kPersistentHandleNoClassId && |