@@ -379,6 +379,10 @@ class GlobalHandles::Node final : public NodeBase<GlobalHandles::Node> {
379379 Internals::kNodeStateMask );
380380 STATIC_ASSERT (WEAK == Internals::kNodeStateIsWeakValue );
381381 STATIC_ASSERT (PENDING == Internals::kNodeStateIsPendingValue );
382+ STATIC_ASSERT (static_cast <int >(IsIndependent::kShift ) ==
383+ Internals::kNodeIsIndependentShift );
384+ STATIC_ASSERT (static_cast <int >(IsActive::kShift ) ==
385+ Internals::kNodeIsActiveShift );
382386 set_in_young_list (false );
383387 }
384388
@@ -402,6 +406,16 @@ class GlobalHandles::Node final : public NodeBase<GlobalHandles::Node> {
402406 flags_ = NodeState::update (flags_, state);
403407 }
404408
409+ bool is_independent () { return IsIndependent::decode (flags_); }
410+ void set_independent (bool v) { flags_ = IsIndependent::update (flags_, v); }
411+
412+ bool is_active () {
413+ return IsActive::decode (flags_);
414+ }
415+ void set_active (bool v) {
416+ flags_ = IsActive::update (flags_, v);
417+ }
418+
405419 bool is_in_young_list () const { return IsInYoungList::decode (flags_); }
406420 void set_in_young_list (bool v) { flags_ = IsInYoungList::update (flags_, v); }
407421
@@ -548,6 +562,7 @@ class GlobalHandles::Node final : public NodeBase<GlobalHandles::Node> {
548562 // This method invokes a finalizer. Updating the method name would require
549563 // adjusting CFI blacklist as weak_callback_ is invoked on the wrong type.
550564 CHECK (IsPendingFinalizer ());
565+ CHECK (!is_active ());
551566 set_state (NEAR_DEATH);
552567 // Check that we are not passing a finalized external string to
553568 // the callback.
@@ -578,17 +593,24 @@ class GlobalHandles::Node final : public NodeBase<GlobalHandles::Node> {
578593 private:
579594 // Fields that are not used for managing node memory.
580595 void ClearImplFields () {
596+ set_independent (false );
597+ set_active (false );
581598 weak_callback_ = nullptr ;
582599 }
583600
584601 void CheckImplFieldsAreCleared () {
602+ DCHECK (!is_independent ());
603+ DCHECK (!is_active ());
585604 DCHECK_EQ (nullptr , weak_callback_);
586605 }
587606
588607 // This stores three flags (independent, partially_dependent and
589608 // in_young_list) and a State.
590609 class NodeState : public BitField8 <State, 0 , 3 > {};
591- class IsInYoungList : public BitField8 <bool , NodeState::kNext , 1 > {};
610+ class IsIndependent : public BitField8 <bool , NodeState::kNext , 1 > {};
611+ // The following two fields are mutually exclusive
612+ class IsActive : public BitField8 <bool , IsIndependent::kNext , 1 > {};
613+ class IsInYoungList : public BitField8 <bool , IsActive::kNext , 1 > {};
592614 class NodeWeaknessType
593615 : public BitField8<WeaknessType, IsInYoungList::kNext , 2 > {};
594616
@@ -851,6 +873,12 @@ void GlobalHandles::IterateWeakRootsIdentifyFinalizers(
851873
852874void GlobalHandles::IdentifyWeakUnmodifiedObjects (
853875 WeakSlotCallback is_unmodified) {
876+ for (Node* node : young_nodes_) {
877+ if (node->IsWeak () && !is_unmodified (node->location ())) {
878+ node->set_active (true );
879+ }
880+ }
881+
854882 LocalEmbedderHeapTracer* const tracer =
855883 isolate ()->heap ()->local_embedder_heap_tracer ();
856884 for (TracedNode* node : traced_young_nodes_) {
@@ -867,7 +895,9 @@ void GlobalHandles::IdentifyWeakUnmodifiedObjects(
867895
868896void GlobalHandles::IterateYoungStrongAndDependentRoots (RootVisitor* v) {
869897 for (Node* node : young_nodes_) {
870- if (node->IsStrongRetainer ()) {
898+ if (node->IsStrongRetainer () ||
899+ (node->IsWeakRetainer () && !node->is_independent () &&
900+ node->is_active ())) {
871901 v->VisitRootPointer (Root::kGlobalHandles , node->label (),
872902 node->location ());
873903 }
@@ -883,7 +913,8 @@ void GlobalHandles::MarkYoungWeakUnmodifiedObjectsPending(
883913 WeakSlotCallbackWithHeap is_dead) {
884914 for (Node* node : young_nodes_) {
885915 DCHECK (node->is_in_young_list ());
886- if (node->IsWeak () && is_dead (isolate_->heap (), node->location ())) {
916+ if ((node->is_independent () || !node->is_active ()) && node->IsWeak () &&
917+ is_dead (isolate_->heap (), node->location ())) {
887918 if (!node->IsPhantomCallback () && !node->IsPhantomResetHandle ()) {
888919 node->MarkPending ();
889920 }
@@ -895,7 +926,8 @@ void GlobalHandles::IterateYoungWeakUnmodifiedRootsForFinalizers(
895926 RootVisitor* v) {
896927 for (Node* node : young_nodes_) {
897928 DCHECK (node->is_in_young_list ());
898- if (node->IsWeakRetainer () && (node->state () == Node::PENDING)) {
929+ if ((node->is_independent () || !node->is_active ()) &&
930+ node->IsWeakRetainer () && (node->state () == Node::PENDING)) {
899931 DCHECK (!node->IsPhantomCallback ());
900932 DCHECK (!node->IsPhantomResetHandle ());
901933 // Finalizers need to survive.
@@ -909,7 +941,8 @@ void GlobalHandles::IterateYoungWeakUnmodifiedRootsForPhantomHandles(
909941 RootVisitor* v, WeakSlotCallbackWithHeap should_reset_handle) {
910942 for (Node* node : young_nodes_) {
911943 DCHECK (node->is_in_young_list ());
912- if (node->IsWeakRetainer () && (node->state () != Node::PENDING)) {
944+ if ((node->is_independent () || !node->is_active ()) &&
945+ node->IsWeakRetainer () && (node->state () != Node::PENDING)) {
913946 if (should_reset_handle (isolate_->heap (), node->location ())) {
914947 DCHECK (node->IsPhantomResetHandle () || node->IsPhantomCallback ());
915948 if (node->IsPhantomResetHandle ()) {
@@ -975,6 +1008,9 @@ size_t GlobalHandles::PostScavengeProcessing(unsigned post_processing_count) {
9751008 // Filter free nodes.
9761009 if (!node->IsRetainer ()) continue ;
9771010
1011+ // Reset active state for all affected nodes.
1012+ node->set_active (false );
1013+
9781014 if (node->IsPending ()) {
9791015 DCHECK (node->has_callback ());
9801016 DCHECK (node->IsPendingFinalizer ());
@@ -993,6 +1029,9 @@ size_t GlobalHandles::PostMarkSweepProcessing(unsigned post_processing_count) {
9931029 // Filter free nodes.
9941030 if (!node->IsRetainer ()) continue ;
9951031
1032+ // Reset active state for all affected nodes.
1033+ node->set_active (false );
1034+
9961035 if (node->IsPending ()) {
9971036 DCHECK (node->has_callback ());
9981037 DCHECK (node->IsPendingFinalizer ());
0 commit comments