Index: src/global-handles.cc |
diff --git a/src/global-handles.cc b/src/global-handles.cc |
index c09ba4b476b97e8fc524bc4180c8017d72814167..59af2381dc5249c7d9678293c6e2ef63527c1007 100644 |
--- a/src/global-handles.cc |
+++ b/src/global-handles.cc |
@@ -154,6 +154,14 @@ class GlobalHandles::Node { |
} |
bool is_independent() const { return independent_; } |
+ void MarkExternallyUnreachable(GlobalHandles* global_handles) { |
+ ASSERT(state_ != FREE); |
+ if (global_handles->isolate()->heap()->InNewSpace(object_)) |
+ externally_unreachable_ = true; |
+ } |
+ bool is_externally_unreachable() const { return externally_unreachable_; } |
+ bool clear_externally_unreachable() { externally_unreachable_ = false; } |
+ |
// In-new-space-list flag accessors. |
void set_in_new_space_list(bool v) { in_new_space_list_ = v; } |
bool is_in_new_space_list() const { return in_new_space_list_; } |
@@ -260,6 +268,7 @@ class GlobalHandles::Node { |
State state_ : 4; |
bool independent_ : 1; |
+ bool externally_unreachable_ : 1; |
bool in_new_space_list_ : 1; |
// Handle specific callback. |
@@ -448,6 +457,11 @@ void GlobalHandles::MarkIndependent(Object** location) { |
} |
+void GlobalHandles::MarkExternallyUnreachable(Object** location) { |
+ Node::FromLocation(location)->MarkExternallyUnreachable(this); |
+} |
+ |
+ |
bool GlobalHandles::IsIndependent(Object** location) { |
return Node::FromLocation(location)->is_independent(); |
} |
@@ -501,8 +515,9 @@ void GlobalHandles::IterateNewSpaceStrongAndDependentRoots(ObjectVisitor* v) { |
for (int i = 0; i < new_space_nodes_.length(); ++i) { |
Node* node = new_space_nodes_[i]; |
if (node->IsStrongRetainer() || |
- (node->IsWeakRetainer() && !node->is_independent())) { |
- v->VisitPointer(node->location()); |
+ (node->IsWeakRetainer() && !node->is_independent() && |
+ !node->is_externally_unreachable())) { |
+ v->VisitPointer(node->location()); |
} |
} |
} |
@@ -513,8 +528,8 @@ void GlobalHandles::IdentifyNewSpaceWeakIndependentHandles( |
for (int i = 0; i < new_space_nodes_.length(); ++i) { |
Node* node = new_space_nodes_[i]; |
ASSERT(node->is_in_new_space_list()); |
- if (node->is_independent() && node->IsWeak() && |
- f(isolate_->heap(), node->location())) { |
+ if ((node->is_independent() || node->is_externally_unreachable()) && |
+ node->IsWeak() && f(isolate_->heap(), node->location())) { |
node->MarkPending(); |
} |
} |
@@ -525,7 +540,8 @@ void GlobalHandles::IterateNewSpaceWeakIndependentRoots(ObjectVisitor* v) { |
for (int i = 0; i < new_space_nodes_.length(); ++i) { |
Node* node = new_space_nodes_[i]; |
ASSERT(node->is_in_new_space_list()); |
- if (node->is_independent() && node->IsWeakRetainer()) { |
+ if ((node->is_independent() || node->is_externally_unreachable()) && |
+ node->IsWeakRetainer()) { |
v->VisitPointer(node->location()); |
} |
} |
@@ -547,7 +563,8 @@ bool GlobalHandles::PostGarbageCollectionProcessing( |
// 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 (!node->is_independent()) continue; |
+ if (!node->is_independent() && !node->is_externally_unreachable()) continue; |
Michael Starzinger
2012/10/26 14:16:48
More than 80 characters, move the continue into th
haraken
2012/10/30 08:51:17
Done.
|
+ node->clear_externally_unreachable(); |
if (node->PostGarbageCollectionProcessing(isolate_, this)) { |
if (initial_post_gc_processing_count != post_gc_processing_count_) { |
// Weak callback triggered another GC and another round of |
@@ -563,6 +580,7 @@ bool GlobalHandles::PostGarbageCollectionProcessing( |
} |
} else { |
for (NodeIterator it(this); !it.done(); it.Advance()) { |
+ it.node()->clear_externally_unreachable(); |
if (it.node()->PostGarbageCollectionProcessing(isolate_, this)) { |
if (initial_post_gc_processing_count != post_gc_processing_count_) { |
// See the comment above. |