@@ -495,6 +495,29 @@ class GlobalHandles::NodeIterator {
495495 DISALLOW_COPY_AND_ASSIGN (NodeIterator);
496496};
497497
498+ class GlobalHandles ::PendingPhantomCallbacksSecondPassTask : public v8::Task {
499+ public:
500+ // Takes ownership of the contents of pending_phantom_callbacks, leaving it in
501+ // the same state it would be after a call to Clear().
502+ PendingPhantomCallbacksSecondPassTask (
503+ List<PendingPhantomCallback>* pending_phantom_callbacks, Isolate* isolate)
504+ : isolate_(isolate) {
505+ pending_phantom_callbacks_.Swap (pending_phantom_callbacks);
506+ }
507+
508+ ~PendingPhantomCallbacksSecondPassTask () override {}
509+
510+ void Run () override {
511+ InvokeSecondPassPhantomCallbacks (&pending_phantom_callbacks_, isolate_);
512+ }
513+
514+ private:
515+ List<PendingPhantomCallback> pending_phantom_callbacks_;
516+ Isolate* isolate_;
517+
518+ DISALLOW_COPY_AND_ASSIGN (PendingPhantomCallbacksSecondPassTask);
519+ };
520+
498521
499522GlobalHandles::GlobalHandles (Isolate* isolate)
500523 : isolate_(isolate),
@@ -709,6 +732,19 @@ bool GlobalHandles::IterateObjectGroups(ObjectVisitor* v,
709732}
710733
711734
735+ void GlobalHandles::InvokeSecondPassPhantomCallbacks (
736+ List<PendingPhantomCallback>* callbacks, Isolate* isolate) {
737+ while (callbacks->length () != 0 ) {
738+ auto callback = callbacks->RemoveLast ();
739+ DCHECK (callback.node () == nullptr );
740+ // No second pass callback required.
741+ if (callback.callback () == nullptr ) continue ;
742+ // Fire second pass callback
743+ callback.Invoke (isolate);
744+ }
745+ }
746+
747+
712748int GlobalHandles::PostScavengeProcessing (
713749 const int initial_post_gc_processing_count) {
714750 int freed_nodes = 0 ;
@@ -791,7 +827,8 @@ void GlobalHandles::UpdateListOfNewSpaceNodes() {
791827}
792828
793829
794- int GlobalHandles::DispatchPendingPhantomCallbacks () {
830+ int GlobalHandles::DispatchPendingPhantomCallbacks (
831+ bool synchronous_second_pass) {
795832 int freed_nodes = 0 ;
796833 {
797834 // The initial pass callbacks must simply clear the nodes.
@@ -804,14 +841,15 @@ int GlobalHandles::DispatchPendingPhantomCallbacks() {
804841 freed_nodes++;
805842 }
806843 }
807- // The second pass empties the list.
808- while (pending_phantom_callbacks_.length () != 0 ) {
809- auto callback = pending_phantom_callbacks_.RemoveLast ();
810- DCHECK (callback.node () == nullptr );
811- // No second pass callback required.
812- if (callback.callback () == nullptr ) continue ;
813- // Fire second pass callback.
814- callback.Invoke (isolate ());
844+ if (pending_phantom_callbacks_.length () > 0 ) {
845+ if (synchronous_second_pass) {
846+ InvokeSecondPassPhantomCallbacks (&pending_phantom_callbacks_, isolate ());
847+ } else {
848+ auto * task = new PendingPhantomCallbacksSecondPassTask (
849+ &pending_phantom_callbacks_, isolate ());
850+ V8::GetCurrentPlatform ()->CallOnForegroundThread (
851+ reinterpret_cast <v8::Isolate*>(isolate ()), task);
852+ }
815853 }
816854 pending_phantom_callbacks_.Clear ();
817855 return freed_nodes;
@@ -838,14 +876,17 @@ void GlobalHandles::PendingPhantomCallback::Invoke(Isolate* isolate) {
838876}
839877
840878
841- int GlobalHandles::PostGarbageCollectionProcessing (GarbageCollector collector) {
879+ int GlobalHandles::PostGarbageCollectionProcessing (
880+ GarbageCollector collector, const v8::GCCallbackFlags gc_callback_flags) {
842881 // Process weak global handle callbacks. This must be done after the
843882 // GC is completely done, because the callbacks may invoke arbitrary
844883 // API functions.
845884 DCHECK (isolate_->heap ()->gc_state () == Heap::NOT_IN_GC );
846885 const int initial_post_gc_processing_count = ++post_gc_processing_count_;
847886 int freed_nodes = 0 ;
848- freed_nodes += DispatchPendingPhantomCallbacks ();
887+ bool synchronous_second_pass =
888+ (gc_callback_flags & kGCCallbackFlagForced ) != 0 ;
889+ freed_nodes += DispatchPendingPhantomCallbacks (synchronous_second_pass);
849890 if (initial_post_gc_processing_count != post_gc_processing_count_) {
850891 // If the callbacks caused a nested GC, then return. See comment in
851892 // PostScavengeProcessing.
0 commit comments