Index: src/global-handles.cc |
diff --git a/src/global-handles.cc b/src/global-handles.cc |
index aa6542baee922f8f4e517cd6764f8b8ed71290ee..4cd0a18ff8ece0cd658f744d19161269d5053de6 100644 |
--- a/src/global-handles.cc |
+++ b/src/global-handles.cc |
@@ -495,6 +495,29 @@ class GlobalHandles::NodeIterator { |
DISALLOW_COPY_AND_ASSIGN(NodeIterator); |
}; |
+class GlobalHandles::PendingPhantomCallbacksSecondPassTask : public v8::Task { |
+ public: |
+ // Takes ownership of the contents of pending_phantom_callbacks, leaving it in |
+ // the same state it would be after a call to Clear(). |
+ PendingPhantomCallbacksSecondPassTask( |
+ List<PendingPhantomCallback>* pending_phantom_callbacks, Isolate* isolate) |
+ : isolate_(isolate) { |
+ pending_phantom_callbacks_.Swap(pending_phantom_callbacks); |
+ } |
+ |
+ ~PendingPhantomCallbacksSecondPassTask() override {} |
+ |
+ void Run() override { |
+ InvokeSecondPassPhantomCallbacks(&pending_phantom_callbacks_, isolate_); |
+ } |
+ |
+ private: |
+ List<PendingPhantomCallback> pending_phantom_callbacks_; |
+ Isolate* isolate_; |
+ |
+ DISALLOW_COPY_AND_ASSIGN(PendingPhantomCallbacksSecondPassTask); |
+}; |
+ |
GlobalHandles::GlobalHandles(Isolate* isolate) |
: isolate_(isolate), |
@@ -709,6 +732,19 @@ bool GlobalHandles::IterateObjectGroups(ObjectVisitor* v, |
} |
+void GlobalHandles::InvokeSecondPassPhantomCallbacks( |
+ List<PendingPhantomCallback>* callbacks, Isolate* isolate) { |
+ while (callbacks->length() != 0) { |
+ auto callback = callbacks->RemoveLast(); |
+ DCHECK(callback.node() == nullptr); |
+ // No second pass callback required. |
+ if (callback.callback() == nullptr) continue; |
+ // Fire second pass callback |
+ callback.Invoke(isolate); |
+ } |
+} |
+ |
+ |
int GlobalHandles::PostScavengeProcessing( |
const int initial_post_gc_processing_count) { |
int freed_nodes = 0; |
@@ -791,7 +827,8 @@ void GlobalHandles::UpdateListOfNewSpaceNodes() { |
} |
-int GlobalHandles::DispatchPendingPhantomCallbacks() { |
+int GlobalHandles::DispatchPendingPhantomCallbacks( |
+ bool synchronous_second_pass) { |
int freed_nodes = 0; |
{ |
// The initial pass callbacks must simply clear the nodes. |
@@ -804,14 +841,15 @@ int GlobalHandles::DispatchPendingPhantomCallbacks() { |
freed_nodes++; |
} |
} |
- // The second pass empties the list. |
- while (pending_phantom_callbacks_.length() != 0) { |
- auto callback = pending_phantom_callbacks_.RemoveLast(); |
- DCHECK(callback.node() == nullptr); |
- // No second pass callback required. |
- if (callback.callback() == nullptr) continue; |
- // Fire second pass callback. |
- callback.Invoke(isolate()); |
+ if (pending_phantom_callbacks_.length() > 0) { |
+ if (synchronous_second_pass) { |
+ InvokeSecondPassPhantomCallbacks(&pending_phantom_callbacks_, isolate()); |
+ } else { |
+ auto* task = new PendingPhantomCallbacksSecondPassTask( |
+ &pending_phantom_callbacks_, isolate()); |
+ V8::GetCurrentPlatform()->CallOnForegroundThread( |
+ reinterpret_cast<v8::Isolate*>(isolate()), task); |
+ } |
} |
pending_phantom_callbacks_.Clear(); |
return freed_nodes; |
@@ -838,14 +876,17 @@ void GlobalHandles::PendingPhantomCallback::Invoke(Isolate* isolate) { |
} |
-int GlobalHandles::PostGarbageCollectionProcessing(GarbageCollector collector) { |
+int GlobalHandles::PostGarbageCollectionProcessing( |
+ GarbageCollector collector, const v8::GCCallbackFlags gc_callback_flags) { |
// Process weak global handle callbacks. This must be done after the |
// GC is completely done, because the callbacks may invoke arbitrary |
// API functions. |
DCHECK(isolate_->heap()->gc_state() == Heap::NOT_IN_GC); |
const int initial_post_gc_processing_count = ++post_gc_processing_count_; |
int freed_nodes = 0; |
- freed_nodes += DispatchPendingPhantomCallbacks(); |
+ bool synchronous_second_pass = |
+ (gc_callback_flags & kGCCallbackFlagForced) != 0; |
+ freed_nodes += DispatchPendingPhantomCallbacks(synchronous_second_pass); |
if (initial_post_gc_processing_count != post_gc_processing_count_) { |
// If the callbacks caused a nested GC, then return. See comment in |
// PostScavengeProcessing. |