| Index: src/global-handles.cc
|
| diff --git a/src/global-handles.cc b/src/global-handles.cc
|
| index 650999f394c5cc7c2e5397afff53c74e3c186d20..cf2a94e5cf45abb801ace506af4d364c3c56694a 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>(IsInactive::kShift) ==
|
| + Internals::kNodeIsInactiveShift);
|
| }
|
|
|
| #ifdef ENABLE_HANDLE_ZAPPING
|
| @@ -64,7 +66,12 @@ class GlobalHandles::Node {
|
| class_id_ = v8::HeapProfiler::kPersistentHandleNoClassId;
|
| index_ = 0;
|
| set_independent(false);
|
| - set_partially_dependent(false);
|
| + if (FLAG_scavenge_reclaim_unmodified_objects) {
|
| + set_unmodified(false);
|
| + set_inactive(false);
|
| + } else {
|
| + set_partially_dependent(false);
|
| + }
|
| set_in_new_space_list(false);
|
| parameter_or_next_free_.next_free = NULL;
|
| weak_callback_ = NULL;
|
| @@ -77,6 +84,10 @@ class GlobalHandles::Node {
|
| set_state(FREE);
|
| set_weakness_type(NORMAL_WEAK);
|
| set_in_new_space_list(false);
|
| + if (FLAG_scavenge_reclaim_unmodified_objects) {
|
| + set_unmodified(false);
|
| + set_inactive(false);
|
| + }
|
| parameter_or_next_free_.next_free = *first_free;
|
| *first_free = this;
|
| }
|
| @@ -86,7 +97,14 @@ class GlobalHandles::Node {
|
| object_ = object;
|
| class_id_ = v8::HeapProfiler::kPersistentHandleNoClassId;
|
| set_independent(false);
|
| - set_partially_dependent(false);
|
| + if (FLAG_scavenge_reclaim_unmodified_objects) {
|
| + set_unmodified(false);
|
| + set_inactive(false);
|
| + // set_inactive(false);
|
| + // set_partially_dependent(false);
|
| + } else {
|
| + set_partially_dependent(false);
|
| + }
|
| set_state(NORMAL);
|
| parameter_or_next_free_.parameter = NULL;
|
| weak_callback_ = NULL;
|
| @@ -106,7 +124,14 @@ 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_unmodified(false);
|
| + set_inactive(false);
|
| + // set_inactive(false);
|
| + // set_partially_dependent(false);
|
| + } else {
|
| + set_partially_dependent(false);
|
| + }
|
| weak_callback_ = NULL;
|
| DecreaseBlockUses();
|
| }
|
| @@ -140,12 +165,26 @@ 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_inactive() { return IsInactive::decode(flags_); }
|
| + void set_inactive(bool v) { IsInactive::update(flags_, v); }
|
| +
|
| + bool is_unmodified() {
|
| + CHECK(FLAG_scavenge_reclaim_unmodified_objects);
|
| + return unmodified_flag;
|
| + }
|
| + void set_unmodified(bool v) {
|
| + CHECK(FLAG_scavenge_reclaim_unmodified_objects);
|
| + unmodified_flag = v;
|
| + }
|
| +
|
| bool is_in_new_space_list() {
|
| return IsInNewSpaceList::decode(flags_);
|
| }
|
| @@ -349,11 +388,14 @@ 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 IsInactive : 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> {};
|
|
|
| uint8_t flags_;
|
| + bool unmodified_flag;
|
|
|
| // Handle specific callback - might be a weak reference in disguise.
|
| WeakCallback weak_callback_;
|
| @@ -646,10 +688,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_unmodified())) {
|
| + v->VisitPointer(node->location());
|
| + }
|
| + } else {
|
| + if (node->IsStrongRetainer() ||
|
| + (node->IsWeakRetainer() && !node->is_independent() &&
|
| + !node->is_partially_dependent())) {
|
| v->VisitPointer(node->location());
|
| + }
|
| }
|
| }
|
| }
|
| @@ -687,6 +737,52 @@ 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->is_inactive()) {
|
| + node->set_inactive(false);
|
| + if (node->IsWeak() && is_unmodified(node->location())) {
|
| + node->set_unmodified(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_unmodified()) && 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_unmodified()) &&
|
| + 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 +853,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) {
|
| + node->set_inactive(false);
|
| + if (!node->is_independent() && !node->is_unmodified()) {
|
| + continue;
|
| + }
|
| + node->set_unmodified(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 +896,12 @@ int GlobalHandles::PostMarkSweepProcessing(
|
| // the freed_nodes.
|
| continue;
|
| }
|
| - it.node()->clear_partially_dependent();
|
| + if (FLAG_scavenge_reclaim_unmodified_objects) {
|
| + it.node()->set_unmodified(false);
|
| + it.node()->set_inactive(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 +1066,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()) {
|
|
|