Commit 5043ab26 authored by Michael Lippautz's avatar Michael Lippautz Committed by Commit Bot

Revert "[global-handles] Restructure GC post processing"

This reverts commit 2b77aaf4.

Reason for revert: https://ci.chromium.org/p/v8/builders/luci.v8.ci/V8%20Linux64%20-%20cfi/18836

Original change's description:
> [global-handles] Restructure GC post processing
> 
> Bug: chromium:923361
> Change-Id: I97a0314b6d5af543e0574f27892c73637739844d
> Reviewed-on: https://chromium-review.googlesource.com/c/1426124
> Commit-Queue: Michael Lippautz <mlippautz@chromium.org>
> Reviewed-by: Ulan Degenbaev <ulan@chromium.org>
> Cr-Commit-Position: refs/heads/master@{#58984}

TBR=ulan@chromium.org,mlippautz@chromium.org

Change-Id: I8220c60573cf7f4a1ced99bcd18628933c45f41e
No-Presubmit: true
No-Tree-Checks: true
No-Try: true
Bug: chromium:923361
Reviewed-on: https://chromium-review.googlesource.com/c/1425901Reviewed-by: 's avatarMichael Lippautz <mlippautz@chromium.org>
Commit-Queue: Michael Lippautz <mlippautz@chromium.org>
Cr-Commit-Position: refs/heads/master@{#58985}
parent 2b77aaf4
...@@ -373,12 +373,6 @@ class GlobalHandles::Node final { ...@@ -373,12 +373,6 @@ class GlobalHandles::Node final {
return state() == PENDING && IsPhantomResetHandle(); return state() == PENDING && IsPhantomResetHandle();
} }
bool IsPendingFinalizer() const {
return state() == PENDING && weakness_type() == FINALIZER_WEAK;
}
bool IsPending() const { return state() == PENDING; }
bool IsRetainer() const { bool IsRetainer() const {
return state() != FREE && return state() != FREE &&
!(state() == NEAR_DEATH && weakness_type() != FINALIZER_WEAK); !(state() == NEAR_DEATH && weakness_type() != FINALIZER_WEAK);
...@@ -406,8 +400,6 @@ class GlobalHandles::Node final { ...@@ -406,8 +400,6 @@ class GlobalHandles::Node final {
return data_.parameter; return data_.parameter;
} }
bool has_callback() const { return weak_callback_ != nullptr; }
// Accessors for next free node in the free list. // Accessors for next free node in the free list.
Node* next_free() { Node* next_free() {
DCHECK_EQ(FREE, state()); DCHECK_EQ(FREE, state());
...@@ -498,16 +490,25 @@ class GlobalHandles::Node final { ...@@ -498,16 +490,25 @@ class GlobalHandles::Node final {
NodeSpace<Node>::Release(this); NodeSpace<Node>::Release(this);
} }
void InvokeFinalizer(Isolate* isolate) { bool PostGarbageCollectionProcessing(Isolate* isolate) {
CHECK(IsPendingFinalizer()); // Handles only weak handles (not phantom) that are dying.
CHECK(!is_active()); if (state() != Node::PENDING) return false;
if (weak_callback_ == nullptr) {
NodeSpace<Node>::Release(this);
return false;
}
set_state(NEAR_DEATH); set_state(NEAR_DEATH);
// Check that we are not passing a finalized external string to // Check that we are not passing a finalized external string to
// the callback. // the callback.
DCHECK(!object()->IsExternalOneByteString() || DCHECK(!object()->IsExternalOneByteString() ||
ExternalOneByteString::cast(object())->resource() != nullptr); ExternalOneByteString::cast(object())->resource() != nullptr);
DCHECK(!object()->IsExternalTwoByteString() || DCHECK(!object()->IsExternalTwoByteString() ||
ExternalTwoByteString::cast(object())->resource() != nullptr); ExternalTwoByteString::cast(object())->resource() != nullptr);
if (weakness_type() != FINALIZER_WEAK) {
return false;
}
// Leaving V8. // Leaving V8.
VMState<EXTERNAL> vmstate(isolate); VMState<EXTERNAL> vmstate(isolate);
HandleScope handle_scope(isolate); HandleScope handle_scope(isolate);
...@@ -516,9 +517,11 @@ class GlobalHandles::Node final { ...@@ -516,9 +517,11 @@ class GlobalHandles::Node final {
v8::WeakCallbackInfo<void> data(reinterpret_cast<v8::Isolate*>(isolate), v8::WeakCallbackInfo<void> data(reinterpret_cast<v8::Isolate*>(isolate),
parameter(), embedder_fields, nullptr); parameter(), embedder_fields, nullptr);
weak_callback_(data); weak_callback_(data);
// For finalizers the handle must have either been reset or made strong.
// Both cases reset the state. // Absence of explicit cleanup or revival of weak handle
CHECK_NE(NEAR_DEATH, state()); // in most of the cases would lead to memory leak.
CHECK(state() != NEAR_DEATH);
return true;
} }
inline GlobalHandles* GetGlobalHandles(); inline GlobalHandles* GetGlobalHandles();
...@@ -816,44 +819,61 @@ void GlobalHandles::InvokeSecondPassPhantomCallbacks() { ...@@ -816,44 +819,61 @@ void GlobalHandles::InvokeSecondPassPhantomCallbacks() {
} }
} }
size_t GlobalHandles::PostScavengeProcessing(unsigned post_processing_count) { int GlobalHandles::PostScavengeProcessing(
size_t freed_nodes = 0; unsigned initial_post_gc_processing_count) {
int freed_nodes = 0;
for (Node* node : new_space_nodes_) { for (Node* node : new_space_nodes_) {
// Filter free nodes. DCHECK(node->is_in_new_space_list());
if (!node->IsRetainer()) continue; if (!node->IsRetainer()) {
// Free nodes do not have weak callbacks. Do not use them to compute
// Reset active state for all affected nodes. // the freed_nodes.
continue;
}
// 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_active())) {
node->set_active(false);
continue;
}
node->set_active(false); node->set_active(false);
if (node->IsPending()) { if (node->PostGarbageCollectionProcessing(isolate_)) {
DCHECK(node->has_callback()); if (initial_post_gc_processing_count != post_gc_processing_count_) {
DCHECK(node->IsPendingFinalizer()); // Weak callback triggered another GC and another round of
node->InvokeFinalizer(isolate_); // PostGarbageCollection processing. The current node might
// have been deleted in that round, so we need to bail out (or
// restart the processing).
return freed_nodes;
}
}
if (!node->IsRetainer()) {
freed_nodes++;
} }
if (InRecursiveGC(post_processing_count)) return freed_nodes;
if (!node->IsRetainer()) freed_nodes++;
} }
return freed_nodes; return freed_nodes;
} }
size_t GlobalHandles::PostMarkSweepProcessing(unsigned post_processing_count) { int GlobalHandles::PostMarkSweepProcessing(
size_t freed_nodes = 0; unsigned initial_post_gc_processing_count) {
int freed_nodes = 0;
for (Node* node : *regular_nodes_) { for (Node* node : *regular_nodes_) {
// Filter free nodes. if (!node->IsRetainer()) {
if (!node->IsRetainer()) continue; // Free nodes do not have weak callbacks. Do not use them to compute
// the freed_nodes.
// Reset active state for all affected nodes. continue;
}
node->set_active(false); node->set_active(false);
if (node->PostGarbageCollectionProcessing(isolate_)) {
if (node->IsPending()) { if (initial_post_gc_processing_count != post_gc_processing_count_) {
DCHECK(node->has_callback()); // See the comment above.
DCHECK(node->IsPendingFinalizer()); return freed_nodes;
node->InvokeFinalizer(isolate_); }
}
if (!node->IsRetainer()) {
freed_nodes++;
} }
if (InRecursiveGC(post_processing_count)) return freed_nodes;
if (!node->IsRetainer()) freed_nodes++;
} }
return freed_nodes; return freed_nodes;
} }
...@@ -880,8 +900,8 @@ void GlobalHandles::UpdateListOfNewSpaceNodes() { ...@@ -880,8 +900,8 @@ void GlobalHandles::UpdateListOfNewSpaceNodes() {
new_space_nodes_.shrink_to_fit(); new_space_nodes_.shrink_to_fit();
} }
size_t GlobalHandles::InvokeFirstPassWeakCallbacks() { int GlobalHandles::InvokeFirstPassWeakCallbacks() {
size_t freed_nodes = 0; int freed_nodes = 0;
std::vector<PendingPhantomCallback> pending_phantom_callbacks; std::vector<PendingPhantomCallback> pending_phantom_callbacks;
pending_phantom_callbacks.swap(pending_phantom_callbacks_); pending_phantom_callbacks.swap(pending_phantom_callbacks_);
{ {
...@@ -939,32 +959,38 @@ void GlobalHandles::PendingPhantomCallback::Invoke(Isolate* isolate) { ...@@ -939,32 +959,38 @@ void GlobalHandles::PendingPhantomCallback::Invoke(Isolate* isolate) {
} }
} }
bool GlobalHandles::InRecursiveGC(unsigned gc_processing_counter) { int GlobalHandles::PostGarbageCollectionProcessing(
return gc_processing_counter != post_gc_processing_count_;
}
size_t GlobalHandles::PostGarbageCollectionProcessing(
GarbageCollector collector, const v8::GCCallbackFlags gc_callback_flags) { GarbageCollector collector, const v8::GCCallbackFlags gc_callback_flags) {
// Process weak global handle callbacks. This must be done after the // Process weak global handle callbacks. This must be done after the
// GC is completely done, because the callbacks may invoke arbitrary // GC is completely done, because the callbacks may invoke arbitrary
// API functions. // API functions.
DCHECK_EQ(Heap::NOT_IN_GC, isolate_->heap()->gc_state()); DCHECK(isolate_->heap()->gc_state() == Heap::NOT_IN_GC);
const unsigned post_processing_count = ++post_gc_processing_count_; const unsigned initial_post_gc_processing_count = ++post_gc_processing_count_;
size_t freed_nodes = 0; int freed_nodes = 0;
bool synchronous_second_pass = bool synchronous_second_pass =
isolate_->heap()->IsTearingDown() || isolate_->heap()->IsTearingDown() ||
(gc_callback_flags & (gc_callback_flags &
(kGCCallbackFlagForced | kGCCallbackFlagCollectAllAvailableGarbage | (kGCCallbackFlagForced | kGCCallbackFlagCollectAllAvailableGarbage |
kGCCallbackFlagSynchronousPhantomCallbackProcessing)) != 0; kGCCallbackFlagSynchronousPhantomCallbackProcessing)) != 0;
InvokeOrScheduleSecondPassPhantomCallbacks(synchronous_second_pass); InvokeOrScheduleSecondPassPhantomCallbacks(synchronous_second_pass);
if (InRecursiveGC(post_processing_count)) return freed_nodes; if (initial_post_gc_processing_count != post_gc_processing_count_) {
// If the callbacks caused a nested GC, then return. See comment in
freed_nodes += Heap::IsYoungGenerationCollector(collector) // PostScavengeProcessing.
? PostScavengeProcessing(post_processing_count) return freed_nodes;
: PostMarkSweepProcessing(post_processing_count); }
if (InRecursiveGC(post_processing_count)) return freed_nodes; if (Heap::IsYoungGenerationCollector(collector)) {
freed_nodes += PostScavengeProcessing(initial_post_gc_processing_count);
UpdateListOfNewSpaceNodes(); } else {
freed_nodes += PostMarkSweepProcessing(initial_post_gc_processing_count);
}
if (initial_post_gc_processing_count != post_gc_processing_count_) {
// If the callbacks caused a nested GC, then return. See comment in
// PostScavengeProcessing.
return freed_nodes;
}
if (initial_post_gc_processing_count == post_gc_processing_count_) {
UpdateListOfNewSpaceNodes();
}
return freed_nodes; return freed_nodes;
} }
......
...@@ -89,12 +89,12 @@ class GlobalHandles final { ...@@ -89,12 +89,12 @@ class GlobalHandles final {
void RecordStats(HeapStats* stats); void RecordStats(HeapStats* stats);
size_t InvokeFirstPassWeakCallbacks(); int InvokeFirstPassWeakCallbacks();
void InvokeSecondPassPhantomCallbacks(); void InvokeSecondPassPhantomCallbacks();
// Process pending weak handles. // Process pending weak handles.
// Returns the number of freed nodes. // Returns the number of freed nodes.
size_t PostGarbageCollectionProcessing( int PostGarbageCollectionProcessing(
GarbageCollector collector, const v8::GCCallbackFlags gc_callback_flags); GarbageCollector collector, const v8::GCCallbackFlags gc_callback_flags);
void IterateStrongRoots(RootVisitor* v); void IterateStrongRoots(RootVisitor* v);
...@@ -179,15 +179,11 @@ class GlobalHandles final { ...@@ -179,15 +179,11 @@ class GlobalHandles final {
class NodeSpace; class NodeSpace;
class PendingPhantomCallback; class PendingPhantomCallback;
bool InRecursiveGC(unsigned gc_processing_counter);
void InvokeSecondPassPhantomCallbacksFromTask(); void InvokeSecondPassPhantomCallbacksFromTask();
int PostScavengeProcessing(unsigned initial_post_gc_processing_count);
int PostMarkSweepProcessing(unsigned initial_post_gc_processing_count);
void InvokeOrScheduleSecondPassPhantomCallbacks(bool synchronous_second_pass); void InvokeOrScheduleSecondPassPhantomCallbacks(bool synchronous_second_pass);
size_t PostScavengeProcessing(unsigned post_processing_count);
size_t PostMarkSweepProcessing(unsigned post_processing_count);
void UpdateListOfNewSpaceNodes(); void UpdateListOfNewSpaceNodes();
void ApplyPersistentHandleVisitor(v8::PersistentHandleVisitor* visitor, void ApplyPersistentHandleVisitor(v8::PersistentHandleVisitor* visitor,
Node* node); Node* node);
......
...@@ -1644,7 +1644,7 @@ void Heap::UpdateSurvivalStatistics(int start_new_space_size) { ...@@ -1644,7 +1644,7 @@ void Heap::UpdateSurvivalStatistics(int start_new_space_size) {
bool Heap::PerformGarbageCollection( bool Heap::PerformGarbageCollection(
GarbageCollector collector, const v8::GCCallbackFlags gc_callback_flags) { GarbageCollector collector, const v8::GCCallbackFlags gc_callback_flags) {
size_t freed_global_handles = 0; int freed_global_handles = 0;
if (!IsYoungGenerationCollector(collector)) { if (!IsYoungGenerationCollector(collector)) {
PROFILE(isolate_, CodeMovingGCEvent()); PROFILE(isolate_, CodeMovingGCEvent());
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment