[api] Remove APIs for resurrecting finalizers

Removes support for specifying weak handles with finalizers that allow
for object resurrection.

This CL removes the public facing APIs. Internal support will be
removed in a follow up.

Bug: v8:12672
Change-Id: Ia6ea269093aaa128caadb7508aca2e5a1254923c
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3596174
Auto-Submit: Michael Lippautz <mlippautz@chromium.org>
Reviewed-by: Dominik Inführ <dinfuehr@chromium.org>
Commit-Queue: Dominik Inführ <dinfuehr@chromium.org>
Cr-Commit-Position: refs/heads/main@{#80070}
This commit is contained in:
Michael Lippautz 2022-04-20 22:33:55 +02:00 committed by V8 LUCI CQ
parent b25adddb90
commit 2ae2aa92b1
4 changed files with 1 additions and 188 deletions

View File

@ -63,13 +63,6 @@ enum class WeakCallbackType {
* Passes the first two internal fields of the object back to the callback.
*/
kInternalFields,
/**
* Passes a user-defined void* parameter back to the callback. Will do so
* before the object is actually reclaimed, allowing it to be resurrected. In
* this case it is not possible to set a second-pass callback.
*/
kFinalizer V8_ENUM_DEPRECATED("Resurrecting finalizers are deprecated "
"and will not be supported going forward.")
};
template <class T>

View File

@ -15,7 +15,6 @@
#include "src/base/bits.h"
#include "src/base/compiler-specific.h"
#include "src/base/sanitizer/asan.h"
#include "src/common/allow-deprecated.h"
#include "src/common/globals.h"
#include "src/execution/vm-state-inl.h"
#include "src/heap/base/stack.h"
@ -544,11 +543,6 @@ class GlobalHandles::Node final : public NodeBase<GlobalHandles::Node> {
case v8::WeakCallbackType::kInternalFields:
set_weakness_type(PHANTOM_WEAK_2_EMBEDDER_FIELDS);
break;
START_ALLOW_USE_DEPRECATED()
case v8::WeakCallbackType::kFinalizer:
set_weakness_type(FINALIZER_WEAK);
break;
END_ALLOW_USE_DEPRECATED()
}
set_parameter(parameter);
weak_callback_ = phantom_callback;

View File

@ -28,7 +28,6 @@
#include "include/v8-function.h"
#include "include/v8-locker.h"
#include "src/api/api-inl.h"
#include "src/common/allow-deprecated.h"
#include "src/execution/isolate.h"
#include "src/handles/global-handles.h"
#include "src/heap/factory.h"
@ -37,8 +36,6 @@
#include "test/cctest/cctest.h"
#include "test/cctest/heap/heap-utils.h"
START_ALLOW_USE_DEPRECATED()
namespace v8 {
namespace internal {
@ -191,28 +188,8 @@ void TracedReferenceTestWithScavenge(v8::Isolate* isolate,
CHECK_IMPLIES(survives == SurvivalMode::kDies, fp->handle.IsEmpty());
}
void ResurrectingFinalizer(
const v8::WeakCallbackInfo<v8::Global<v8::Object>>& data) {
data.GetParameter()->ClearWeak();
}
void ResettingFinalizer(
const v8::WeakCallbackInfo<v8::Global<v8::Object>>& data) {
data.GetParameter()->Reset();
}
void EmptyWeakCallback(const v8::WeakCallbackInfo<void>& data) {}
void ResurrectingFinalizerSettingProperty(
const v8::WeakCallbackInfo<v8::Global<v8::Object>>& data) {
data.GetParameter()->ClearWeak();
v8::Local<v8::Object> o =
v8::Local<v8::Object>::New(data.GetIsolate(), *data.GetParameter());
o->Set(data.GetIsolate()->GetCurrentContext(), v8_str("finalizer"),
v8_str("was here"))
.FromJust();
}
} // namespace
TEST(EternalHandles) {
@ -309,32 +286,7 @@ TEST(WeakPersistentSmi) {
v8::WeakCallbackType::kParameter);
}
TEST(FinalizerWeakness) {
CcTest::InitializeVM();
v8::Isolate* isolate = CcTest::isolate();
v8::Global<v8::Object> g;
int identity;
{
v8::HandleScope scope(isolate);
v8::Local<v8::Object> o = v8::Object::New(isolate);
identity = o->GetIdentityHash();
g.Reset(isolate, o);
g.SetWeak(&g, &ResurrectingFinalizerSettingProperty,
v8::WeakCallbackType::kFinalizer);
}
CcTest::CollectAllAvailableGarbage();
CHECK(!g.IsEmpty());
v8::HandleScope scope(isolate);
v8::Local<v8::Object> o = v8::Local<v8::Object>::New(isolate, g);
CHECK_EQ(identity, o->GetIdentityHash());
CHECK(o->Has(isolate->GetCurrentContext(), v8_str("finalizer")).FromJust());
}
TEST(PhatomHandlesWithoutCallbacks) {
TEST(PhantomHandlesWithoutCallbacks) {
CcTest::InitializeVM();
v8::Isolate* isolate = CcTest::isolate();
@ -510,84 +462,6 @@ TEST(TracedReferenceTOJsApiObjectWithElementsSurvivesScavenge) {
CHECK(!handle.IsEmpty());
}
TEST(FinalizerOnUnmodifiedJSApiObjectDoesNotCrash) {
// See crbug.com/v8/8586.
CcTest::InitializeVM();
v8::Isolate* isolate = CcTest::isolate();
v8::HandleScope scope(isolate);
v8::Local<v8::Context> context = v8::Context::New(isolate);
v8::Context::Scope context_scope(context);
FlagAndGlobal fp;
ConstructJSApiObject(isolate, context, &fp);
fp.handle.SetWeak(&fp, &ResetHandleAndSetFlag,
v8::WeakCallbackType::kFinalizer);
fp.flag = false;
{
v8::HandleScope inner_scope(isolate);
v8::Local<v8::Object> tmp = v8::Local<v8::Object>::New(isolate, fp.handle);
USE(tmp);
InvokeScavenge();
}
}
namespace {
void ConstructFinalizerPointingPhantomHandle(
v8::Isolate* isolate, v8::Global<v8::Object>* g1,
v8::Global<v8::Object>* g2,
typename v8::WeakCallbackInfo<v8::Global<v8::Object>>::Callback
finalizer_for_g1) {
v8::HandleScope scope(isolate);
v8::Local<v8::Object> o1 =
v8::Local<v8::Object>::New(isolate, v8::Object::New(isolate));
v8::Local<v8::Object> o2 =
v8::Local<v8::Object>::New(isolate, v8::Object::New(isolate));
o1->Set(isolate->GetCurrentContext(), v8_str("link"), o2).FromJust();
g1->Reset(isolate, o1);
g2->Reset(isolate, o2);
// g1 will be finalized but resurrected.
g1->SetWeak(g1, finalizer_for_g1, v8::WeakCallbackType::kFinalizer);
// g2 will be a phantom handle that is dependent on the finalizer handle
// g1 as it is in its subgraph.
g2->SetWeak();
}
} // namespace
TEST(FinalizerResurrectsAndKeepsPhantomAliveOnMarkCompact) {
// See crbug.com/772299.
CcTest::InitializeVM();
v8::Global<v8::Object> g1, g2;
ConstructFinalizerPointingPhantomHandle(CcTest::isolate(), &g1, &g2,
ResurrectingFinalizer);
InvokeMarkSweep();
// Both, g1 and g2, should stay alive as the finalizer resurrects the root
// object that transitively keeps the other one alive.
CHECK(!g1.IsEmpty());
CHECK(!g2.IsEmpty());
InvokeMarkSweep();
// The finalizer handle is now strong, so it should keep the objects alive.
CHECK(!g1.IsEmpty());
CHECK(!g2.IsEmpty());
}
TEST(FinalizerDiesAndKeepsPhantomAliveOnMarkCompact) {
CcTest::InitializeVM();
v8::Global<v8::Object> g1, g2;
ConstructFinalizerPointingPhantomHandle(CcTest::isolate(), &g1, &g2,
ResettingFinalizer);
InvokeMarkSweep();
// Finalizer (g1) dies but the phantom handle (g2) is kept alive for one
// more round as the underlying object only dies on the next GC.
CHECK(g1.IsEmpty());
CHECK(!g2.IsEmpty());
InvokeMarkSweep();
// Phantom handle dies after one more round.
CHECK(g1.IsEmpty());
CHECK(g2.IsEmpty());
}
namespace {
void ForceScavenge2(const v8::WeakCallbackInfo<FlagAndGlobal>& data) {
@ -748,5 +622,3 @@ TEST(TotalSizeTracedNode) {
} // namespace internal
} // namespace v8
END_ALLOW_USE_DEPRECATED()

View File

@ -6,7 +6,6 @@
#include "include/v8-function.h"
#include "include/v8-template.h"
#include "src/common/allow-deprecated.h"
#include "src/handles/global-handles.h"
#include "src/heap/gc-tracer.h"
#include "src/heap/heap.h"
@ -263,8 +262,6 @@ v8::Local<v8::Object> ConstructTraceableJSApiObject(
return scope.Escape(instance);
}
START_ALLOW_USE_DEPRECATED()
enum class TracePrologueBehavior { kNoop, kCallV8WriteBarrier };
class TestEmbedderHeapTracer final : public v8::EmbedderHeapTracer {
@ -403,47 +400,6 @@ TEST_F(EmbedderTracingTest, EmbedderRegisteringV8Reference) {
EXPECT_FALSE(handle->IsEmpty());
}
namespace {
void ResurrectingFinalizer(
const v8::WeakCallbackInfo<v8::Global<v8::Object>>& data) {
data.GetParameter()->ClearWeak();
}
} // namespace
TEST_F(EmbedderTracingTest, TracingInRevivedSubgraph) {
// Tests that wrappers are traced when they are contained with in a subgraph
// that is revived by a finalizer.
ManualGCScope manual_gc(i_isolate());
TestEmbedderHeapTracer tracer;
heap::TemporaryEmbedderHeapTracerScope tracer_scope(v8_isolate(), &tracer);
v8::HandleScope scope(v8_isolate());
v8::Local<v8::Context> context = v8::Context::New(v8_isolate());
v8::Context::Scope context_scope(context);
v8::Global<v8::Object> g;
void* first_and_second_field = reinterpret_cast<void*>(0x4);
{
v8::HandleScope inner_scope(v8_isolate());
v8::Local<v8::Object> api_object = ConstructTraceableJSApiObject(
context, first_and_second_field, first_and_second_field);
EXPECT_FALSE(api_object.IsEmpty());
v8::Local<v8::Object> o =
v8::Local<v8::Object>::New(v8_isolate(), v8::Object::New(v8_isolate()));
o->Set(context,
v8::String::NewFromUtf8(v8::Isolate::GetCurrent(), "link")
.ToLocalChecked(),
api_object)
.FromJust();
g.Reset(v8_isolate(), o);
g.SetWeak(&g, ResurrectingFinalizer, v8::WeakCallbackType::kFinalizer);
}
i_isolate()->heap()->CollectGarbage(i::OLD_SPACE,
GarbageCollectionReason::kTesting);
EXPECT_TRUE(tracer.IsRegisteredFromV8(first_and_second_field));
}
TEST_F(EmbedderTracingTest, TracingInEphemerons) {
// Tests that wrappers that are part of ephemerons are traced.
ManualGCScope manual_gc(i_isolate());
@ -1231,8 +1187,6 @@ TEST_F(EmbedderTracingTest, NotifyEmptyStack) {
TracedReferenceNotifyEmptyStackTest(v8_isolate(), &tracer);
}
END_ALLOW_USE_DEPRECATED()
} // namespace heap
} // namespace internal
} // namespace v8