Index: src/global-handles.cc |
diff --git a/src/global-handles.cc b/src/global-handles.cc |
index 650999f394c5cc7c2e5397afff53c74e3c186d20..3608fe81b684df8894e106169d82b71d01340c58 100644 |
--- a/src/global-handles.cc |
+++ b/src/global-handles.cc |
@@ -54,6 +54,8 @@ class GlobalHandles::Node { |
Internals::kNodeIsIndependentShift); |
STATIC_ASSERT(static_cast<int>(IsPartiallyDependent::kShift) == |
Internals::kNodeIsPartiallyDependentShift); |
+ STATIC_ASSERT(static_cast<int>(IsActive::kShift) == |
+ Internals::kNodeIsActiveShift); |
} |
#ifdef ENABLE_HANDLE_ZAPPING |
@@ -64,7 +66,11 @@ class GlobalHandles::Node { |
class_id_ = v8::HeapProfiler::kPersistentHandleNoClassId; |
index_ = 0; |
set_independent(false); |
- set_partially_dependent(false); |
+ if (FLAG_scavenge_reclaim_unmodified_objects) { |
+ set_active(false); |
+ } else { |
+ set_partially_dependent(false); |
+ } |
set_in_new_space_list(false); |
parameter_or_next_free_.next_free = NULL; |
weak_callback_ = NULL; |
@@ -86,7 +92,11 @@ class GlobalHandles::Node { |
object_ = object; |
class_id_ = v8::HeapProfiler::kPersistentHandleNoClassId; |
set_independent(false); |
- set_partially_dependent(false); |
+ if (FLAG_scavenge_reclaim_unmodified_objects) { |
+ set_active(false); |
+ } else { |
+ set_partially_dependent(false); |
+ } |
set_state(NORMAL); |
parameter_or_next_free_.parameter = NULL; |
weak_callback_ = NULL; |
@@ -106,7 +116,11 @@ class GlobalHandles::Node { |
object_ = reinterpret_cast<Object*>(kGlobalHandleZapValue); |
class_id_ = v8::HeapProfiler::kPersistentHandleNoClassId; |
set_independent(false); |
- set_partially_dependent(false); |
+ if (FLAG_scavenge_reclaim_unmodified_objects) { |
+ set_active(false); |
+ } else { |
+ set_partially_dependent(false); |
+ } |
weak_callback_ = NULL; |
DecreaseBlockUses(); |
} |
@@ -140,12 +154,23 @@ class GlobalHandles::Node { |
} |
bool is_partially_dependent() { |
+ CHECK(!FLAG_scavenge_reclaim_unmodified_objects); |
return IsPartiallyDependent::decode(flags_); |
} |
void set_partially_dependent(bool v) { |
+ CHECK(!FLAG_scavenge_reclaim_unmodified_objects); |
flags_ = IsPartiallyDependent::update(flags_, v); |
} |
+ bool is_active() { |
+ CHECK(FLAG_scavenge_reclaim_unmodified_objects); |
+ return IsActive::decode(flags_); |
+ } |
+ void set_active(bool v) { |
+ CHECK(FLAG_scavenge_reclaim_unmodified_objects); |
+ flags_ = IsActive::update(flags_, v); |
+ } |
+ |
bool is_in_new_space_list() { |
return IsInNewSpaceList::decode(flags_); |
} |
@@ -349,6 +374,8 @@ class GlobalHandles::Node { |
// in_new_space_list) and a State. |
class NodeState : public BitField<State, 0, 3> {}; |
class IsIndependent : public BitField<bool, 3, 1> {}; |
+ // The following two fields are mutually exclusive |
+ class IsActive : public BitField<bool, 4, 1> {}; |
class IsPartiallyDependent : public BitField<bool, 4, 1> {}; |
class IsInNewSpaceList : public BitField<bool, 5, 1> {}; |
class NodeWeaknessType : public BitField<WeaknessType, 6, 2> {}; |
@@ -646,10 +673,18 @@ void GlobalHandles::IdentifyWeakHandles(WeakSlotCallback f) { |
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() && |
- !node->is_partially_dependent())) { |
+ if (FLAG_scavenge_reclaim_unmodified_objects) { |
+ if (node->IsStrongRetainer() || |
+ (node->IsWeakRetainer() && !node->is_independent() && |
+ node->is_active())) { |
+ v->VisitPointer(node->location()); |
+ } |
+ } else { |
+ if (node->IsStrongRetainer() || |
+ (node->IsWeakRetainer() && !node->is_independent() && |
+ !node->is_partially_dependent())) { |
v->VisitPointer(node->location()); |
+ } |
} |
} |
} |
@@ -687,6 +722,49 @@ void GlobalHandles::IterateNewSpaceWeakIndependentRoots(ObjectVisitor* v) { |
} |
+void GlobalHandles::IdentifyWeakUnmodifiedObjects( |
+ WeakSlotCallback is_unmodified) { |
+ for (int i = 0; i < new_space_nodes_.length(); ++i) { |
+ Node* node = new_space_nodes_[i]; |
+ if (node->IsWeak() && !is_unmodified(node->location())) { |
+ node->set_active(true); |
+ } |
+ } |
+} |
+ |
+ |
+void GlobalHandles::MarkNewSpaceWeakUnmodifiedObjectsPending( |
+ WeakSlotCallbackWithHeap is_unscavenged) { |
+ for (int i = 0; i < new_space_nodes_.length(); ++i) { |
+ Node* node = new_space_nodes_[i]; |
+ DCHECK(node->is_in_new_space_list()); |
+ if ((node->is_independent() || !node->is_active()) && node->IsWeak() && |
+ is_unscavenged(isolate_->heap(), node->location())) { |
+ node->MarkPending(); |
+ } |
+ } |
+} |
+ |
+ |
+void GlobalHandles::IterateNewSpaceWeakUnmodifiedRoots(ObjectVisitor* v) { |
+ for (int i = 0; i < new_space_nodes_.length(); ++i) { |
+ Node* node = new_space_nodes_[i]; |
+ DCHECK(node->is_in_new_space_list()); |
+ if ((node->is_independent() || !node->is_active()) && |
+ node->IsWeakRetainer()) { |
+ // Pending weak phantom handles die immediately. Everything else survives. |
+ if (node->state() == Node::PENDING && |
+ node->weakness_type() != NORMAL_WEAK) { |
+ node->CollectPhantomCallbackData(isolate(), |
+ &pending_phantom_callbacks_); |
+ } else { |
+ v->VisitPointer(node->location()); |
+ } |
+ } |
+ } |
+} |
+ |
+ |
bool GlobalHandles::IterateObjectGroups(ObjectVisitor* v, |
WeakSlotCallbackWithHeap can_skip) { |
ComputeObjectGroupsAndImplicitReferences(); |
@@ -757,13 +835,23 @@ int GlobalHandles::PostScavengeProcessing( |
// the freed_nodes. |
continue; |
} |
- // Skip dependent handles. Their weak callbacks might expect to be |
+ // Skip dependent or unmodified 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() && !node->is_partially_dependent()) { |
- continue; |
+ if (FLAG_scavenge_reclaim_unmodified_objects) { |
+ if (!node->is_independent() && (node->is_active())) { |
+ node->set_active(false); |
+ continue; |
+ } |
+ node->set_active(false); |
+ } else { |
+ if (!node->is_independent() && !node->is_partially_dependent()) { |
+ continue; |
+ } |
+ node->clear_partially_dependent(); |
} |
- node->clear_partially_dependent(); |
+ |
if (node->PostGarbageCollectionProcessing(isolate_)) { |
if (initial_post_gc_processing_count != post_gc_processing_count_) { |
// Weak callback triggered another GC and another round of |
@@ -790,7 +878,11 @@ int GlobalHandles::PostMarkSweepProcessing( |
// the freed_nodes. |
continue; |
} |
- it.node()->clear_partially_dependent(); |
+ if (FLAG_scavenge_reclaim_unmodified_objects) { |
+ it.node()->set_active(false); |
+ } else { |
+ it.node()->clear_partially_dependent(); |
+ } |
if (it.node()->PostGarbageCollectionProcessing(isolate_)) { |
if (initial_post_gc_processing_count != post_gc_processing_count_) { |
// See the comment above. |
@@ -955,6 +1047,16 @@ void GlobalHandles::IterateAllRootsInNewSpaceWithClassIds(ObjectVisitor* v) { |
} |
+void GlobalHandles::IterateWeakRootsInNewSpaceWithClassIds(ObjectVisitor* v) { |
+ for (int i = 0; i < new_space_nodes_.length(); ++i) { |
+ Node* node = new_space_nodes_[i]; |
+ if (node->has_wrapper_class_id() && node->IsWeak()) { |
+ v->VisitEmbedderReference(node->location(), node->wrapper_class_id()); |
+ } |
+ } |
+} |
+ |
+ |
int GlobalHandles::NumberOfWeakHandles() { |
int count = 0; |
for (NodeIterator it(this); !it.done(); it.Advance()) { |