[weakrefs] Rename FinalizationGroup to FinalizationRegistry in C++

Renaming the JS-visible identifiers and strings is left for a future CL.

FinalizationGroup was renamed at Feb 2020 TC39, to better signal that if
a FinalizationRegistry dies, the finalization actions registered with it
may no longer be performed.

Bug: v8:8179
Change-Id: I0d676a71a4a67d2b7175994a67458a6158065844
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2055381
Reviewed-by: Adam Klein <adamk@chromium.org>
Reviewed-by: Ulan Degenbaev <ulan@chromium.org>
Commit-Queue: Shu-yu Guo <syg@chromium.org>
Cr-Commit-Position: refs/heads/master@{#66416}
This commit is contained in:
Shu-yu Guo 2020-02-24 11:47:48 -08:00 committed by Commit Bot
parent aa9849470e
commit 5e797bf82a
40 changed files with 652 additions and 622 deletions

View File

@ -2334,8 +2334,8 @@ v8_source_set("v8_base_without_compiler") {
"src/heap/factory-inl.h",
"src/heap/factory.cc",
"src/heap/factory.h",
"src/heap/finalization-group-cleanup-task.cc",
"src/heap/finalization-group-cleanup-task.h",
"src/heap/finalization-registry-cleanup-task.cc",
"src/heap/finalization-registry-cleanup-task.h",
"src/heap/gc-idle-time-handler.cc",
"src/heap/gc-idle-time-handler.h",
"src/heap/gc-tracer.cc",

View File

@ -86,7 +86,7 @@ MAKE_TO_LOCAL(ToLocal, JSArrayBufferView, ArrayBufferView)
MAKE_TO_LOCAL(ToLocal, JSDataView, DataView)
MAKE_TO_LOCAL(ToLocal, JSTypedArray, TypedArray)
MAKE_TO_LOCAL(ToLocalShared, JSArrayBuffer, SharedArrayBuffer)
MAKE_TO_LOCAL(ToLocal, JSFinalizationGroup, FinalizationGroup)
MAKE_TO_LOCAL(ToLocal, JSFinalizationRegistry, FinalizationGroup)
TYPED_ARRAYS(MAKE_TO_LOCAL_TYPED_ARRAY)

View File

@ -895,7 +895,7 @@ StartupData SnapshotCreator::CreateBlob(
startup_serializer.SerializeWeakReferencesAndDeferred();
can_be_rehashed = can_be_rehashed && startup_serializer.can_be_rehashed();
startup_serializer.CheckNoDirtyFinalizationGroups();
startup_serializer.CheckNoDirtyFinalizationRegistries();
read_only_serializer.FinalizeSerialization();
can_be_rehashed = can_be_rehashed && read_only_serializer.can_be_rehashed();
@ -8356,16 +8356,17 @@ void Isolate::SetHostCleanupFinalizationGroupCallback(
Maybe<bool> FinalizationGroup::Cleanup(
Local<FinalizationGroup> finalization_group) {
i::Handle<i::JSFinalizationGroup> fg = Utils::OpenHandle(*finalization_group);
i::Isolate* isolate = fg->native_context().GetIsolate();
i::Handle<i::Context> i_context(fg->native_context(), isolate);
i::Handle<i::JSFinalizationRegistry> fr =
Utils::OpenHandle(*finalization_group);
i::Isolate* isolate = fr->native_context().GetIsolate();
i::Handle<i::Context> i_context(fr->native_context(), isolate);
Local<Context> context = Utils::ToLocal(i_context);
ENTER_V8(isolate, context, FinalizationGroup, Cleanup, Nothing<bool>(),
i::HandleScope);
i::Handle<i::Object> callback(fg->cleanup(), isolate);
fg->set_scheduled_for_cleanup(false);
i::Handle<i::Object> callback(fr->cleanup(), isolate);
fr->set_scheduled_for_cleanup(false);
has_pending_exception =
i::JSFinalizationGroup::Cleanup(isolate, fg, callback).IsNothing();
i::JSFinalizationRegistry::Cleanup(isolate, fr, callback).IsNothing();
RETURN_ON_FAILED_EXECUTION_PRIMITIVE(bool);
return Just(true);
}
@ -11074,21 +11075,22 @@ void InvokeFunctionCallback(const v8::FunctionCallbackInfo<v8::Value>& info,
callback(info);
}
void InvokeFinalizationGroupCleanupFromTask(
Handle<Context> context, Handle<JSFinalizationGroup> finalization_group,
void InvokeFinalizationRegistryCleanupFromTask(
Handle<Context> context,
Handle<JSFinalizationRegistry> finalization_registry,
Handle<Object> callback) {
Isolate* isolate = finalization_group->native_context().GetIsolate();
Isolate* isolate = finalization_registry->native_context().GetIsolate();
RuntimeCallTimerScope timer(
isolate, RuntimeCallCounterId::kFinalizationGroupCleanupFromTask);
isolate, RuntimeCallCounterId::kFinalizationRegistryCleanupFromTask);
// Do not use ENTER_V8 because this is always called from a running
// FinalizationGroupCleanupTask within V8 and we should not log it as an API
// call. This method is implemented here to avoid duplication of the exception
// handling and microtask running logic in CallDepthScope.
// FinalizationRegistryCleanupTask within V8 and we should not log it as an
// API call. This method is implemented here to avoid duplication of the
// exception handling and microtask running logic in CallDepthScope.
if (IsExecutionTerminatingCheck(isolate)) return;
Local<v8::Context> api_context = Utils::ToLocal(context);
CallDepthScope<true> call_depth_scope(isolate, api_context);
VMState<OTHER> state(isolate);
if (JSFinalizationGroup::Cleanup(isolate, finalization_group, callback)
if (JSFinalizationRegistry::Cleanup(isolate, finalization_registry, callback)
.IsNothing()) {
call_depth_scope.Escape();
}

View File

@ -26,7 +26,7 @@ namespace v8 {
namespace internal {
class JSArrayBufferView;
class JSFinalizationGroup;
class JSFinalizationRegistry;
} // namespace internal
namespace debug {
@ -93,7 +93,7 @@ class RegisteredExtension {
V(Data, Object) \
V(RegExp, JSRegExp) \
V(Object, JSReceiver) \
V(FinalizationGroup, JSFinalizationGroup) \
V(FinalizationGroup, JSFinalizationRegistry) \
V(Array, JSArray) \
V(Map, JSMap) \
V(Set, JSSet) \
@ -206,7 +206,7 @@ class Utils {
static inline Local<BigUint64Array> ToLocalBigUint64Array(
v8::internal::Handle<v8::internal::JSTypedArray> obj);
static inline Local<FinalizationGroup> ToLocal(
v8::internal::Handle<v8::internal::JSFinalizationGroup> obj);
v8::internal::Handle<v8::internal::JSFinalizationRegistry> obj);
static inline Local<SharedArrayBuffer> ToLocalShared(
v8::internal::Handle<v8::internal::JSArrayBuffer> obj);
@ -562,8 +562,9 @@ void InvokeAccessorGetterCallback(
void InvokeFunctionCallback(const v8::FunctionCallbackInfo<v8::Value>& info,
v8::FunctionCallback callback);
void InvokeFinalizationGroupCleanupFromTask(
Handle<Context> context, Handle<JSFinalizationGroup> finalization_group,
void InvokeFinalizationRegistryCleanupFromTask(
Handle<Context> context,
Handle<JSFinalizationRegistry> finalization_registry,
Handle<Object> callback);
} // namespace internal

View File

@ -979,11 +979,11 @@ namespace internal {
CPP(Trace) \
\
/* Weak refs */ \
CPP(FinalizationGroupCleanupIteratorNext) \
CPP(FinalizationGroupCleanupSome) \
CPP(FinalizationGroupConstructor) \
CPP(FinalizationGroupRegister) \
CPP(FinalizationGroupUnregister) \
CPP(FinalizationRegistryCleanupIteratorNext) \
CPP(FinalizationRegistryCleanupSome) \
CPP(FinalizationRegistryConstructor) \
CPP(FinalizationRegistryRegister) \
CPP(FinalizationRegistryUnregister) \
CPP(WeakRefConstructor) \
CPP(WeakRefDeref) \
\

View File

@ -9,7 +9,7 @@
namespace v8 {
namespace internal {
BUILTIN(FinalizationGroupConstructor) {
BUILTIN(FinalizationRegistryConstructor) {
HandleScope scope(isolate);
Handle<JSFunction> target = args.target();
if (args.new_target()->IsUndefined(isolate)) { // [[Call]]
@ -31,22 +31,22 @@ BUILTIN(FinalizationGroupConstructor) {
isolate, result,
JSObject::New(target, new_target, Handle<AllocationSite>::null()));
Handle<JSFinalizationGroup> finalization_group =
Handle<JSFinalizationGroup>::cast(result);
finalization_group->set_native_context(*isolate->native_context());
finalization_group->set_cleanup(*cleanup);
finalization_group->set_flags(
JSFinalizationGroup::ScheduledForCleanupField::encode(false));
Handle<JSFinalizationRegistry> finalization_registry =
Handle<JSFinalizationRegistry>::cast(result);
finalization_registry->set_native_context(*isolate->native_context());
finalization_registry->set_cleanup(*cleanup);
finalization_registry->set_flags(
JSFinalizationRegistry::ScheduledForCleanupField::encode(false));
DCHECK(finalization_group->active_cells().IsUndefined(isolate));
DCHECK(finalization_group->cleared_cells().IsUndefined(isolate));
DCHECK(finalization_group->key_map().IsUndefined(isolate));
return *finalization_group;
DCHECK(finalization_registry->active_cells().IsUndefined(isolate));
DCHECK(finalization_registry->cleared_cells().IsUndefined(isolate));
DCHECK(finalization_registry->key_map().IsUndefined(isolate));
return *finalization_registry;
}
BUILTIN(FinalizationGroupRegister) {
BUILTIN(FinalizationRegistryRegister) {
HandleScope scope(isolate);
const char* method_name = "FinalizationGroup.prototype.register";
const char* method_name = "FinalizationRegistry.prototype.register";
// 1. Let finalizationGroup be the this value.
//
@ -55,7 +55,7 @@ BUILTIN(FinalizationGroupRegister) {
//
// 4. If finalizationGroup does not have a [[Cells]] internal slot,
// throw a TypeError exception.
CHECK_RECEIVER(JSFinalizationGroup, finalization_group, method_name);
CHECK_RECEIVER(JSFinalizationRegistry, finalization_registry, method_name);
Handle<Object> target = args.atOrUndefined(isolate, 1);
@ -86,15 +86,15 @@ BUILTIN(FinalizationGroupRegister) {
}
// TODO(marja): Realms.
JSFinalizationGroup::Register(finalization_group,
Handle<JSReceiver>::cast(target), holdings,
unregister_token, isolate);
JSFinalizationRegistry::Register(finalization_registry,
Handle<JSReceiver>::cast(target), holdings,
unregister_token, isolate);
return ReadOnlyRoots(isolate).undefined_value();
}
BUILTIN(FinalizationGroupUnregister) {
BUILTIN(FinalizationRegistryUnregister) {
HandleScope scope(isolate);
const char* method_name = "FinalizationGroup.prototype.unregister";
const char* method_name = "FinalizationRegistry.prototype.unregister";
// 1. Let finalizationGroup be the this value.
//
@ -103,7 +103,7 @@ BUILTIN(FinalizationGroupUnregister) {
//
// 3. If finalizationGroup does not have a [[Cells]] internal slot,
// throw a TypeError exception.
CHECK_RECEIVER(JSFinalizationGroup, finalization_group, method_name);
CHECK_RECEIVER(JSFinalizationRegistry, finalization_registry, method_name);
Handle<Object> unregister_token = args.atOrUndefined(isolate, 1);
@ -115,15 +115,16 @@ BUILTIN(FinalizationGroupUnregister) {
unregister_token));
}
bool success = JSFinalizationGroup::Unregister(
finalization_group, Handle<JSReceiver>::cast(unregister_token), isolate);
bool success = JSFinalizationRegistry::Unregister(
finalization_registry, Handle<JSReceiver>::cast(unregister_token),
isolate);
return *isolate->factory()->ToBoolean(success);
}
BUILTIN(FinalizationGroupCleanupSome) {
BUILTIN(FinalizationRegistryCleanupSome) {
HandleScope scope(isolate);
const char* method_name = "FinalizationGroup.prototype.cleanupSome";
const char* method_name = "FinalizationRegistry.prototype.cleanupSome";
// 1. Let finalizationGroup be the this value.
//
@ -132,9 +133,9 @@ BUILTIN(FinalizationGroupCleanupSome) {
//
// 3. If finalizationGroup does not have a [[Cells]] internal slot,
// throw a TypeError exception.
CHECK_RECEIVER(JSFinalizationGroup, finalization_group, method_name);
CHECK_RECEIVER(JSFinalizationRegistry, finalization_registry, method_name);
Handle<Object> callback(finalization_group->cleanup(), isolate);
Handle<Object> callback(finalization_registry->cleanup(), isolate);
Handle<Object> callback_obj = args.atOrUndefined(isolate, 1);
// 4. If callback is not undefined and IsCallable(callback) is
@ -150,7 +151,7 @@ BUILTIN(FinalizationGroupCleanupSome) {
// Don't do set_scheduled_for_cleanup(false); we still have the task
// scheduled.
if (JSFinalizationGroup::Cleanup(isolate, finalization_group, callback)
if (JSFinalizationRegistry::Cleanup(isolate, finalization_registry, callback)
.IsNothing()) {
DCHECK(isolate->has_pending_exception());
return ReadOnlyRoots(isolate).exception();
@ -158,19 +159,20 @@ BUILTIN(FinalizationGroupCleanupSome) {
return ReadOnlyRoots(isolate).undefined_value();
}
BUILTIN(FinalizationGroupCleanupIteratorNext) {
BUILTIN(FinalizationRegistryCleanupIteratorNext) {
HandleScope scope(isolate);
CHECK_RECEIVER(JSFinalizationGroupCleanupIterator, iterator, "next");
CHECK_RECEIVER(JSFinalizationRegistryCleanupIterator, iterator, "next");
Handle<JSFinalizationGroup> finalization_group(iterator->finalization_group(),
isolate);
if (!finalization_group->NeedsCleanup()) {
Handle<JSFinalizationRegistry> finalization_registry(
iterator->finalization_registry(), isolate);
if (!finalization_registry->NeedsCleanup()) {
return *isolate->factory()->NewJSIteratorResult(
handle(ReadOnlyRoots(isolate).undefined_value(), isolate), true);
}
Handle<Object> holdings = handle(
JSFinalizationGroup::PopClearedCellHoldings(finalization_group, isolate),
isolate);
Handle<Object> holdings =
handle(JSFinalizationRegistry::PopClearedCellHoldings(
finalization_registry, isolate),
isolate);
return *isolate->factory()->NewJSIteratorResult(holdings, false);
}

View File

@ -582,8 +582,8 @@ namespace internal {
T(WeakRefsRegisterTargetMustBeObject, \
"FinalizationGroup.prototype.register: target must be an object") \
T(WeakRefsRegisterTargetAndHoldingsMustNotBeSame, \
"FinalizationGroup.prototype.register: target and holdings must not be " \
"same") \
"FinalizationGroup.prototype.register: target and holdings must not " \
"be same") \
T(WeakRefsWeakRefConstructorTargetMustBeObject, \
"WeakRef: target must be an object") \
T(OptionalChainingNoNew, "Invalid optional chain from new expression") \

View File

@ -64,8 +64,8 @@ class JSSegmentIterator;
class JSSegmenter;
class JSV8BreakIterator;
class JSWeakCollection;
class JSFinalizationGroup;
class JSFinalizationGroupCleanupIterator;
class JSFinalizationRegistry;
class JSFinalizationRegistryCleanupIterator;
class JSWeakMap;
class JSWeakRef;
class JSWeakSet;

View File

@ -239,8 +239,8 @@ Type::bitset BitsetType::Lub(const MapRefLike& map) {
case JS_MAP_VALUE_ITERATOR_TYPE:
case JS_STRING_ITERATOR_TYPE:
case JS_ASYNC_FROM_SYNC_ITERATOR_TYPE:
case JS_FINALIZATION_GROUP_TYPE:
case JS_FINALIZATION_GROUP_CLEANUP_ITERATOR_TYPE:
case JS_FINALIZATION_REGISTRY_TYPE:
case JS_FINALIZATION_REGISTRY_CLEANUP_ITERATOR_TYPE:
case JS_WEAK_MAP_TYPE:
case JS_WEAK_REF_TYPE:
case JS_WEAK_SET_TYPE:

View File

@ -637,7 +637,7 @@ bool Shell::ExecuteString(Isolate* isolate, Local<String> source,
DCHECK(try_catch.HasCaught());
return false;
}
// It's possible that a FinalizationGroup cleanup task threw an error.
// It's possible that a FinalizationRegistry cleanup task threw an error.
if (try_catch.HasCaught()) success = false;
if (print_result) {
if (options.test_shell) {

View File

@ -1070,8 +1070,8 @@ void WeakCell::WeakCellVerify(Isolate* isolate) {
CHECK(key_list_next().IsWeakCell() || key_list_next().IsUndefined(isolate));
CHECK(finalization_group().IsUndefined(isolate) ||
finalization_group().IsJSFinalizationGroup());
CHECK(finalization_registry().IsUndefined(isolate) ||
finalization_registry().IsJSFinalizationRegistry());
}
void JSWeakRef::JSWeakRefVerify(Isolate* isolate) {
@ -1080,8 +1080,8 @@ void JSWeakRef::JSWeakRefVerify(Isolate* isolate) {
CHECK(target().IsUndefined(isolate) || target().IsJSReceiver());
}
void JSFinalizationGroup::JSFinalizationGroupVerify(Isolate* isolate) {
CHECK(IsJSFinalizationGroup());
void JSFinalizationRegistry::JSFinalizationRegistryVerify(Isolate* isolate) {
CHECK(IsJSFinalizationRegistry());
JSObjectVerify(isolate);
VerifyHeapPointer(isolate, cleanup());
CHECK(active_cells().IsUndefined(isolate) || active_cells().IsWeakCell());
@ -1093,14 +1093,14 @@ void JSFinalizationGroup::JSFinalizationGroupVerify(Isolate* isolate) {
CHECK(WeakCell::cast(cleared_cells()).prev().IsUndefined(isolate));
}
CHECK(next_dirty().IsUndefined(isolate) ||
next_dirty().IsJSFinalizationGroup());
next_dirty().IsJSFinalizationRegistry());
}
void JSFinalizationGroupCleanupIterator::
JSFinalizationGroupCleanupIteratorVerify(Isolate* isolate) {
CHECK(IsJSFinalizationGroupCleanupIterator());
void JSFinalizationRegistryCleanupIterator::
JSFinalizationRegistryCleanupIteratorVerify(Isolate* isolate) {
CHECK(IsJSFinalizationRegistryCleanupIterator());
JSObjectVerify(isolate);
VerifyHeapPointer(isolate, finalization_group());
VerifyHeapPointer(isolate, finalization_registry());
}
void JSWeakMap::JSWeakMapVerify(Isolate* isolate) {

View File

@ -1150,7 +1150,7 @@ void JSMapIterator::JSMapIteratorPrint(std::ostream& os) { // NOLINT
void WeakCell::WeakCellPrint(std::ostream& os) {
PrintHeader(os, "WeakCell");
os << "\n - finalization_group: " << Brief(finalization_group());
os << "\n - finalization_registry: " << Brief(finalization_registry());
os << "\n - target: " << Brief(target());
os << "\n - holdings: " << Brief(holdings());
os << "\n - prev: " << Brief(prev());
@ -1166,8 +1166,8 @@ void JSWeakRef::JSWeakRefPrint(std::ostream& os) {
JSObjectPrintBody(os, *this);
}
void JSFinalizationGroup::JSFinalizationGroupPrint(std::ostream& os) {
JSObjectPrintHeader(os, *this, "JSFinalizationGroup");
void JSFinalizationRegistry::JSFinalizationRegistryPrint(std::ostream& os) {
JSObjectPrintHeader(os, *this, "JSFinalizationRegistry");
os << "\n - native_context: " << Brief(native_context());
os << "\n - cleanup: " << Brief(cleanup());
os << "\n - active_cells: " << Brief(active_cells());
@ -1186,10 +1186,10 @@ void JSFinalizationGroup::JSFinalizationGroupPrint(std::ostream& os) {
JSObjectPrintBody(os, *this);
}
void JSFinalizationGroupCleanupIterator::
JSFinalizationGroupCleanupIteratorPrint(std::ostream& os) {
JSObjectPrintHeader(os, *this, "JSFinalizationGroupCleanupIterator");
os << "\n - finalization_group: " << Brief(finalization_group());
void JSFinalizationRegistryCleanupIterator::
JSFinalizationRegistryCleanupIteratorPrint(std::ostream& os) {
JSObjectPrintHeader(os, *this, "JSFinalizationRegistryCleanupIterator");
os << "\n - finalization_registry: " << Brief(finalization_registry());
JSObjectPrintBody(os, *this);
}

View File

@ -4017,12 +4017,12 @@ void Isolate::SetHostCleanupFinalizationGroupCallback(
}
void Isolate::RunHostCleanupFinalizationGroupCallback(
Handle<JSFinalizationGroup> fg) {
Handle<JSFinalizationRegistry> fr) {
if (host_cleanup_finalization_group_callback_ != nullptr) {
v8::Local<v8::Context> api_context =
v8::Utils::ToLocal(handle(Context::cast(fg->native_context()), this));
v8::Utils::ToLocal(handle(Context::cast(fr->native_context()), this));
host_cleanup_finalization_group_callback_(api_context,
v8::Utils::ToLocal(fg));
v8::Utils::ToLocal(fr));
}
}

View File

@ -1424,7 +1424,8 @@ class V8_EXPORT_PRIVATE Isolate final : private HiddenFactory {
host_cleanup_finalization_group_callback() const {
return host_cleanup_finalization_group_callback_;
}
void RunHostCleanupFinalizationGroupCallback(Handle<JSFinalizationGroup> fg);
void RunHostCleanupFinalizationGroupCallback(
Handle<JSFinalizationRegistry> fr);
void SetHostImportModuleDynamicallyCallback(
HostImportModuleDynamicallyCallback callback);

View File

@ -1,35 +0,0 @@
// Copyright 2020 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef V8_HEAP_FINALIZATION_GROUP_CLEANUP_TASK_H_
#define V8_HEAP_FINALIZATION_GROUP_CLEANUP_TASK_H_
#include "src/objects/js-weak-refs.h"
#include "src/tasks/cancelable-task.h"
namespace v8 {
namespace internal {
// The GC schedules a cleanup task when the dirty FinalizationGroup list is
// non-empty. The task processes a single FinalizationGroup and posts another
// cleanup task if there are remaining dirty FinalizationGroups on the list.
class FinalizationGroupCleanupTask : public CancelableTask {
public:
explicit FinalizationGroupCleanupTask(Heap* heap);
~FinalizationGroupCleanupTask() override = default;
private:
FinalizationGroupCleanupTask(const FinalizationGroupCleanupTask&) = delete;
void operator=(const FinalizationGroupCleanupTask&) = delete;
void RunInternal() override;
void SlowAssertNoActiveJavaScript();
Heap* heap_;
};
} // namespace internal
} // namespace v8
#endif // V8_HEAP_FINALIZATION_GROUP_CLEANUP_TASK_H_

View File

@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "src/heap/finalization-group-cleanup-task.h"
#include "src/heap/finalization-registry-cleanup-task.h"
#include "src/execution/frames.h"
#include "src/execution/interrupts-scope.h"
@ -15,10 +15,10 @@
namespace v8 {
namespace internal {
FinalizationGroupCleanupTask::FinalizationGroupCleanupTask(Heap* heap)
FinalizationRegistryCleanupTask::FinalizationRegistryCleanupTask(Heap* heap)
: CancelableTask(heap->isolate()), heap_(heap) {}
void FinalizationGroupCleanupTask::SlowAssertNoActiveJavaScript() {
void FinalizationRegistryCleanupTask::SlowAssertNoActiveJavaScript() {
#ifdef ENABLE_SLOW_DCHECKS
class NoActiveJavaScript : public ThreadVisitor {
public:
@ -35,39 +35,42 @@ void FinalizationGroupCleanupTask::SlowAssertNoActiveJavaScript() {
#endif // ENABLE_SLOW_DCHECKS
}
void FinalizationGroupCleanupTask::RunInternal() {
void FinalizationRegistryCleanupTask::RunInternal() {
Isolate* isolate = heap_->isolate();
DCHECK(!isolate->host_cleanup_finalization_group_callback());
SlowAssertNoActiveJavaScript();
TRACE_EVENT_CALL_STATS_SCOPED(isolate, "v8",
"V8.FinalizationGroupCleanupTask");
"V8.FinalizationRegistryCleanupTask");
HandleScope handle_scope(isolate);
Handle<JSFinalizationGroup> finalization_group;
// There could be no dirty FinalizationGroups. When a context is disposed by
// the embedder, its FinalizationGroups are removed from the dirty list.
if (!heap_->DequeueDirtyJSFinalizationGroup().ToHandle(&finalization_group)) {
Handle<JSFinalizationRegistry> finalization_registry;
// There could be no dirty FinalizationRegistries. When a context is disposed
// by the embedder, its FinalizationRegistries are removed from the dirty
// list.
if (!heap_->DequeueDirtyJSFinalizationRegistry().ToHandle(
&finalization_registry)) {
return;
}
finalization_group->set_scheduled_for_cleanup(false);
finalization_registry->set_scheduled_for_cleanup(false);
// Since FinalizationGroup cleanup callbacks are scheduled by V8, enter the
// FinalizationGroup's context.
Handle<Context> context(Context::cast(finalization_group->native_context()),
isolate);
Handle<Object> callback(finalization_group->cleanup(), isolate);
// Since FinalizationRegistry cleanup callbacks are scheduled by V8, enter the
// FinalizationRegistry's context.
Handle<Context> context(
Context::cast(finalization_registry->native_context()), isolate);
Handle<Object> callback(finalization_registry->cleanup(), isolate);
v8::Context::Scope context_scope(v8::Utils::ToLocal(context));
v8::TryCatch catcher(reinterpret_cast<v8::Isolate*>(isolate));
catcher.SetVerbose(true);
// Exceptions are reported via the message handler. This is ensured by the
// verbose TryCatch.
InvokeFinalizationGroupCleanupFromTask(context, finalization_group, callback);
InvokeFinalizationRegistryCleanupFromTask(context, finalization_registry,
callback);
// Repost if there are remaining dirty FinalizationGroups.
heap_->set_is_finalization_group_cleanup_task_posted(false);
heap_->PostFinalizationGroupCleanupTaskIfNeeded();
// Repost if there are remaining dirty FinalizationRegistries.
heap_->set_is_finalization_registry_cleanup_task_posted(false);
heap_->PostFinalizationRegistryCleanupTaskIfNeeded();
}
} // namespace internal

View File

@ -0,0 +1,36 @@
// Copyright 2020 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef V8_HEAP_FINALIZATION_REGISTRY_CLEANUP_TASK_H_
#define V8_HEAP_FINALIZATION_REGISTRY_CLEANUP_TASK_H_
#include "src/objects/js-weak-refs.h"
#include "src/tasks/cancelable-task.h"
namespace v8 {
namespace internal {
// The GC schedules a cleanup task when the dirty FinalizationRegistry list is
// non-empty. The task processes a single FinalizationRegistry and posts another
// cleanup task if there are remaining dirty FinalizationRegistries on the list.
class FinalizationRegistryCleanupTask : public CancelableTask {
public:
explicit FinalizationRegistryCleanupTask(Heap* heap);
~FinalizationRegistryCleanupTask() override = default;
private:
FinalizationRegistryCleanupTask(const FinalizationRegistryCleanupTask&) =
delete;
void operator=(const FinalizationRegistryCleanupTask&) = delete;
void RunInternal() override;
void SlowAssertNoActiveJavaScript();
Heap* heap_;
};
} // namespace internal
} // namespace v8
#endif // V8_HEAP_FINALIZATION_REGISTRY_CLEANUP_TASK_H_

View File

@ -640,8 +640,8 @@ void Heap::DecrementExternalBackingStoreBytes(ExternalBackingStoreType type,
base::CheckedDecrement(&backing_store_bytes_, amount);
}
bool Heap::HasDirtyJSFinalizationGroups() {
return !dirty_js_finalization_groups_list().IsUndefined(isolate());
bool Heap::HasDirtyJSFinalizationRegistries() {
return !dirty_js_finalization_registries_list().IsUndefined(isolate());
}
AlwaysAllocateScope::AlwaysAllocateScope(Heap* heap) : heap_(heap) {

View File

@ -33,7 +33,7 @@
#include "src/heap/combined-heap.h"
#include "src/heap/concurrent-marking.h"
#include "src/heap/embedder-tracing.h"
#include "src/heap/finalization-group-cleanup-task.h"
#include "src/heap/finalization-registry-cleanup-task.h"
#include "src/heap/gc-idle-time-handler.h"
#include "src/heap/gc-tracer.h"
#include "src/heap/heap-controller.h"
@ -206,8 +206,8 @@ Heap::Heap()
set_native_contexts_list(Smi::zero());
set_allocation_sites_list(Smi::zero());
set_dirty_js_finalization_groups_list(Smi::zero());
set_dirty_js_finalization_groups_list_tail(Smi::zero());
set_dirty_js_finalization_registries_list(Smi::zero());
set_dirty_js_finalization_registries_list_tail(Smi::zero());
// Put a dummy entry in the remembered pages so we can find the list the
// minidump even if there are no real unmapped pages.
RememberUnmappedPage(kNullAddress, false);
@ -1202,9 +1202,10 @@ void Heap::GarbageCollectionEpilogue() {
if (FLAG_harmony_weak_refs &&
isolate()->host_cleanup_finalization_group_callback()) {
HandleScope handle_scope(isolate());
Handle<JSFinalizationGroup> finalization_group;
while (DequeueDirtyJSFinalizationGroup().ToHandle(&finalization_group)) {
isolate()->RunHostCleanupFinalizationGroupCallback(finalization_group);
Handle<JSFinalizationRegistry> finalization_registry;
while (
DequeueDirtyJSFinalizationRegistry().ToHandle(&finalization_registry)) {
isolate()->RunHostCleanupFinalizationGroupCallback(finalization_registry);
}
}
}
@ -1659,7 +1660,7 @@ int Heap::NotifyContextDisposed(bool dependant_context) {
}
isolate()->AbortConcurrentOptimization(BlockingBehavior::kDontBlock);
if (!isolate()->context().is_null()) {
RemoveDirtyFinalizationGroupsOnContext(isolate()->raw_native_context());
RemoveDirtyFinalizationRegistriesOnContext(isolate()->raw_native_context());
}
number_of_disposed_maps_ = retained_maps().length();
@ -2652,7 +2653,7 @@ void Heap::UpdateReferencesInExternalStringTable(
void Heap::ProcessAllWeakReferences(WeakObjectRetainer* retainer) {
ProcessNativeContexts(retainer);
ProcessAllocationSites(retainer);
ProcessDirtyJSFinalizationGroups(retainer);
ProcessDirtyJSFinalizationRegistries(retainer);
}
@ -2674,24 +2675,24 @@ void Heap::ProcessAllocationSites(WeakObjectRetainer* retainer) {
set_allocation_sites_list(allocation_site_obj);
}
void Heap::ProcessDirtyJSFinalizationGroups(WeakObjectRetainer* retainer) {
Object head = VisitWeakList<JSFinalizationGroup>(
this, dirty_js_finalization_groups_list(), retainer);
set_dirty_js_finalization_groups_list(head);
void Heap::ProcessDirtyJSFinalizationRegistries(WeakObjectRetainer* retainer) {
Object head = VisitWeakList<JSFinalizationRegistry>(
this, dirty_js_finalization_registries_list(), retainer);
set_dirty_js_finalization_registries_list(head);
// If the list is empty, set the tail to undefined. Otherwise the tail is set
// by WeakListVisitor<JSFinalizationGroup>::VisitLiveObject.
if (head.IsUndefined(isolate())) {
set_dirty_js_finalization_groups_list_tail(head);
set_dirty_js_finalization_registries_list_tail(head);
}
}
void Heap::ProcessWeakListRoots(WeakObjectRetainer* retainer) {
set_native_contexts_list(retainer->RetainAs(native_contexts_list()));
set_allocation_sites_list(retainer->RetainAs(allocation_sites_list()));
set_dirty_js_finalization_groups_list(
retainer->RetainAs(dirty_js_finalization_groups_list()));
set_dirty_js_finalization_groups_list_tail(
retainer->RetainAs(dirty_js_finalization_groups_list_tail()));
set_dirty_js_finalization_registries_list(
retainer->RetainAs(dirty_js_finalization_registries_list()));
set_dirty_js_finalization_registries_list_tail(
retainer->RetainAs(dirty_js_finalization_registries_list_tail()));
}
void Heap::ForeachAllocationSite(
@ -6069,58 +6070,59 @@ void Heap::SetInterpreterEntryTrampolineForProfiling(Code code) {
set_interpreter_entry_trampoline_for_profiling(code);
}
void Heap::PostFinalizationGroupCleanupTaskIfNeeded() {
void Heap::PostFinalizationRegistryCleanupTaskIfNeeded() {
DCHECK(!isolate()->host_cleanup_finalization_group_callback());
// Only one cleanup task is posted at a time.
if (!HasDirtyJSFinalizationGroups() ||
is_finalization_group_cleanup_task_posted_) {
if (!HasDirtyJSFinalizationRegistries() ||
is_finalization_registry_cleanup_task_posted_) {
return;
}
auto taskrunner = V8::GetCurrentPlatform()->GetForegroundTaskRunner(
reinterpret_cast<v8::Isolate*>(isolate()));
auto task = std::make_unique<FinalizationGroupCleanupTask>(this);
auto task = std::make_unique<FinalizationRegistryCleanupTask>(this);
taskrunner->PostNonNestableTask(std::move(task));
is_finalization_group_cleanup_task_posted_ = true;
is_finalization_registry_cleanup_task_posted_ = true;
}
void Heap::EnqueueDirtyJSFinalizationGroup(
JSFinalizationGroup finalization_group,
void Heap::EnqueueDirtyJSFinalizationRegistry(
JSFinalizationRegistry finalization_registry,
std::function<void(HeapObject object, ObjectSlot slot, Object target)>
gc_notify_updated_slot) {
// Add a FinalizationGroup to the tail of the dirty list.
DCHECK(!HasDirtyJSFinalizationGroups() ||
dirty_js_finalization_groups_list().IsJSFinalizationGroup());
DCHECK(finalization_group.next_dirty().IsUndefined(isolate()));
DCHECK(!finalization_group.scheduled_for_cleanup());
finalization_group.set_scheduled_for_cleanup(true);
if (dirty_js_finalization_groups_list_tail().IsUndefined(isolate())) {
DCHECK(dirty_js_finalization_groups_list().IsUndefined(isolate()));
set_dirty_js_finalization_groups_list(finalization_group);
// dirty_js_finalization_groups_list_ is rescanned by ProcessWeakListRoots.
// Add a FinalizationRegistry to the tail of the dirty list.
DCHECK(!HasDirtyJSFinalizationRegistries() ||
dirty_js_finalization_registries_list().IsJSFinalizationRegistry());
DCHECK(finalization_registry.next_dirty().IsUndefined(isolate()));
DCHECK(!finalization_registry.scheduled_for_cleanup());
finalization_registry.set_scheduled_for_cleanup(true);
if (dirty_js_finalization_registries_list_tail().IsUndefined(isolate())) {
DCHECK(dirty_js_finalization_registries_list().IsUndefined(isolate()));
set_dirty_js_finalization_registries_list(finalization_registry);
// dirty_js_finalization_registries_list_ is rescanned by
// ProcessWeakListRoots.
} else {
JSFinalizationGroup tail =
JSFinalizationGroup::cast(dirty_js_finalization_groups_list_tail());
tail.set_next_dirty(finalization_group);
gc_notify_updated_slot(
tail,
finalization_group.RawField(JSFinalizationGroup::kNextDirtyOffset),
finalization_group);
JSFinalizationRegistry tail = JSFinalizationRegistry::cast(
dirty_js_finalization_registries_list_tail());
tail.set_next_dirty(finalization_registry);
gc_notify_updated_slot(tail,
finalization_registry.RawField(
JSFinalizationRegistry::kNextDirtyOffset),
finalization_registry);
}
set_dirty_js_finalization_groups_list_tail(finalization_group);
// dirty_js_finalization_groups_list_tail_ is rescanned by
set_dirty_js_finalization_registries_list_tail(finalization_registry);
// dirty_js_finalization_registries_list_tail_ is rescanned by
// ProcessWeakListRoots.
}
MaybeHandle<JSFinalizationGroup> Heap::DequeueDirtyJSFinalizationGroup() {
// Take a FinalizationGroup from the head of the dirty list for fairness.
if (HasDirtyJSFinalizationGroups()) {
Handle<JSFinalizationGroup> head(
JSFinalizationGroup::cast(dirty_js_finalization_groups_list()),
MaybeHandle<JSFinalizationRegistry> Heap::DequeueDirtyJSFinalizationRegistry() {
// Take a FinalizationRegistry from the head of the dirty list for fairness.
if (HasDirtyJSFinalizationRegistries()) {
Handle<JSFinalizationRegistry> head(
JSFinalizationRegistry::cast(dirty_js_finalization_registries_list()),
isolate());
set_dirty_js_finalization_groups_list(head->next_dirty());
set_dirty_js_finalization_registries_list(head->next_dirty());
head->set_next_dirty(ReadOnlyRoots(this).undefined_value());
if (*head == dirty_js_finalization_groups_list_tail()) {
set_dirty_js_finalization_groups_list_tail(
if (*head == dirty_js_finalization_registries_list_tail()) {
set_dirty_js_finalization_registries_list_tail(
ReadOnlyRoots(this).undefined_value());
}
return head;
@ -6128,7 +6130,7 @@ MaybeHandle<JSFinalizationGroup> Heap::DequeueDirtyJSFinalizationGroup() {
return {};
}
void Heap::RemoveDirtyFinalizationGroupsOnContext(NativeContext context) {
void Heap::RemoveDirtyFinalizationRegistriesOnContext(NativeContext context) {
if (!FLAG_harmony_weak_refs) return;
if (isolate()->host_cleanup_finalization_group_callback()) return;
@ -6136,26 +6138,28 @@ void Heap::RemoveDirtyFinalizationGroupsOnContext(NativeContext context) {
Isolate* isolate = this->isolate();
Object prev = ReadOnlyRoots(isolate).undefined_value();
Object current = dirty_js_finalization_groups_list();
Object current = dirty_js_finalization_registries_list();
while (!current.IsUndefined(isolate)) {
JSFinalizationGroup finalization_group = JSFinalizationGroup::cast(current);
if (finalization_group.native_context() == context) {
JSFinalizationRegistry finalization_registry =
JSFinalizationRegistry::cast(current);
if (finalization_registry.native_context() == context) {
if (prev.IsUndefined(isolate)) {
set_dirty_js_finalization_groups_list(finalization_group.next_dirty());
set_dirty_js_finalization_registries_list(
finalization_registry.next_dirty());
} else {
JSFinalizationGroup::cast(prev).set_next_dirty(
finalization_group.next_dirty());
JSFinalizationRegistry::cast(prev).set_next_dirty(
finalization_registry.next_dirty());
}
finalization_group.set_scheduled_for_cleanup(false);
current = finalization_group.next_dirty();
finalization_group.set_next_dirty(
finalization_registry.set_scheduled_for_cleanup(false);
current = finalization_registry.next_dirty();
finalization_registry.set_next_dirty(
ReadOnlyRoots(isolate).undefined_value());
} else {
prev = current;
current = finalization_group.next_dirty();
current = finalization_registry.next_dirty();
}
}
set_dirty_js_finalization_groups_list_tail(prev);
set_dirty_js_finalization_registries_list_tail(prev);
}
void Heap::KeepDuringJob(Handle<JSReceiver> target) {

View File

@ -70,7 +70,7 @@ class HeapObjectAllocationTracker;
class HeapObjectsFilter;
class HeapStats;
class Isolate;
class JSFinalizationGroup;
class JSFinalizationRegistry;
class LocalEmbedderHeapTracer;
class MemoryAllocator;
class MemoryMeasurement;
@ -502,17 +502,17 @@ class Heap {
}
Object allocation_sites_list() { return allocation_sites_list_; }
void set_dirty_js_finalization_groups_list(Object object) {
dirty_js_finalization_groups_list_ = object;
void set_dirty_js_finalization_registries_list(Object object) {
dirty_js_finalization_registries_list_ = object;
}
Object dirty_js_finalization_groups_list() {
return dirty_js_finalization_groups_list_;
Object dirty_js_finalization_registries_list() {
return dirty_js_finalization_registries_list_;
}
void set_dirty_js_finalization_groups_list_tail(Object object) {
dirty_js_finalization_groups_list_tail_ = object;
void set_dirty_js_finalization_registries_list_tail(Object object) {
dirty_js_finalization_registries_list_tail_ = object;
}
Object dirty_js_finalization_groups_list_tail() {
return dirty_js_finalization_groups_list_tail_;
Object dirty_js_finalization_registries_list_tail() {
return dirty_js_finalization_registries_list_tail_;
}
// Used in CreateAllocationSiteStub and the (de)serializer.
@ -813,29 +813,29 @@ class Heap {
// See also: FLAG_interpreted_frames_native_stack.
void SetInterpreterEntryTrampolineForProfiling(Code code);
void EnqueueDirtyJSFinalizationGroup(
JSFinalizationGroup finalization_group,
void EnqueueDirtyJSFinalizationRegistry(
JSFinalizationRegistry finalization_registry,
std::function<void(HeapObject object, ObjectSlot slot, Object target)>
gc_notify_updated_slot);
MaybeHandle<JSFinalizationGroup> DequeueDirtyJSFinalizationGroup();
MaybeHandle<JSFinalizationRegistry> DequeueDirtyJSFinalizationRegistry();
// Called from Heap::NotifyContextDisposed to remove all FinalizationGroups
// with {context} from the dirty list when the context e.g. navigates away or
// is detached. If the dirty list is empty afterwards, the cleanup task is
// aborted if needed.
void RemoveDirtyFinalizationGroupsOnContext(NativeContext context);
// Called from Heap::NotifyContextDisposed to remove all
// FinalizationRegistries with {context} from the dirty list when the context
// e.g. navigates away or is detached. If the dirty list is empty afterwards,
// the cleanup task is aborted if needed.
void RemoveDirtyFinalizationRegistriesOnContext(NativeContext context);
inline bool HasDirtyJSFinalizationGroups();
inline bool HasDirtyJSFinalizationRegistries();
void PostFinalizationGroupCleanupTaskIfNeeded();
void PostFinalizationRegistryCleanupTaskIfNeeded();
void set_is_finalization_group_cleanup_task_posted(bool posted) {
is_finalization_group_cleanup_task_posted_ = posted;
void set_is_finalization_registry_cleanup_task_posted(bool posted) {
is_finalization_registry_cleanup_task_posted_ = posted;
}
bool is_finalization_group_cleanup_task_posted() {
return is_finalization_group_cleanup_task_posted_;
bool is_finalization_registry_cleanup_task_posted() {
return is_finalization_registry_cleanup_task_posted_;
}
V8_EXPORT_PRIVATE void KeepDuringJob(Handle<JSReceiver> target);
@ -1748,7 +1748,7 @@ class Heap {
void ProcessYoungWeakReferences(WeakObjectRetainer* retainer);
void ProcessNativeContexts(WeakObjectRetainer* retainer);
void ProcessAllocationSites(WeakObjectRetainer* retainer);
void ProcessDirtyJSFinalizationGroups(WeakObjectRetainer* retainer);
void ProcessDirtyJSFinalizationRegistries(WeakObjectRetainer* retainer);
void ProcessWeakListRoots(WeakObjectRetainer* retainer);
// ===========================================================================
@ -2053,9 +2053,9 @@ class Heap {
// List heads are initialized lazily and contain the undefined_value at start.
Object native_contexts_list_;
Object allocation_sites_list_;
Object dirty_js_finalization_groups_list_;
Object dirty_js_finalization_registries_list_;
// Weak list tails.
Object dirty_js_finalization_groups_list_tail_;
Object dirty_js_finalization_registries_list_tail_;
std::vector<GCCallbackTuple> gc_epilogue_callbacks_;
std::vector<GCCallbackTuple> gc_prologue_callbacks_;
@ -2192,7 +2192,7 @@ class Heap {
std::vector<HeapObjectAllocationTracker*> allocation_trackers_;
bool is_finalization_group_cleanup_task_posted_ = false;
bool is_finalization_registry_cleanup_task_posted_ = false;
std::unique_ptr<third_party_heap::Heap> tp_heap_;

View File

@ -2494,18 +2494,18 @@ void MarkCompactCollector::ClearJSWeakRefs() {
if (!non_atomic_marking_state()->IsBlackOrGrey(target)) {
DCHECK(!target.IsUndefined());
// The value of the WeakCell is dead.
JSFinalizationGroup finalization_group =
JSFinalizationGroup::cast(weak_cell.finalization_group());
if (!finalization_group.scheduled_for_cleanup()) {
heap()->EnqueueDirtyJSFinalizationGroup(finalization_group,
gc_notify_updated_slot);
JSFinalizationRegistry finalization_registry =
JSFinalizationRegistry::cast(weak_cell.finalization_registry());
if (!finalization_registry.scheduled_for_cleanup()) {
heap()->EnqueueDirtyJSFinalizationRegistry(finalization_registry,
gc_notify_updated_slot);
}
// We're modifying the pointers in WeakCell and JSFinalizationGroup during
// GC; thus we need to record the slots it writes. The normal write
// We're modifying the pointers in WeakCell and JSFinalizationRegistry
// during GC; thus we need to record the slots it writes. The normal write
// barrier is not enough, since it's disabled before GC.
weak_cell.Nullify(isolate(), gc_notify_updated_slot);
DCHECK(finalization_group.NeedsCleanup());
DCHECK(finalization_group.scheduled_for_cleanup());
DCHECK(finalization_registry.NeedsCleanup());
DCHECK(finalization_registry.scheduled_for_cleanup());
} else {
// The value of the WeakCell is alive.
ObjectSlot slot = weak_cell.RawField(WeakCell::kTargetOffset);
@ -2521,9 +2521,9 @@ void MarkCompactCollector::ClearJSWeakRefs() {
// WeakCell. Like above, we're modifying pointers during GC, so record the
// slots.
HeapObject undefined = ReadOnlyRoots(isolate()).undefined_value();
JSFinalizationGroup finalization_group =
JSFinalizationGroup::cast(weak_cell.finalization_group());
finalization_group.RemoveUnregisterToken(
JSFinalizationRegistry finalization_registry =
JSFinalizationRegistry::cast(weak_cell.finalization_registry());
finalization_registry.RemoveUnregisterToken(
JSReceiver::cast(unregister_token), isolate(),
[undefined](WeakCell matched_cell) {
matched_cell.set_unregister_token(undefined);
@ -2536,7 +2536,7 @@ void MarkCompactCollector::ClearJSWeakRefs() {
}
}
if (!isolate()->host_cleanup_finalization_group_callback()) {
heap()->PostFinalizationGroupCleanupTaskIfNeeded();
heap()->PostFinalizationRegistryCleanupTaskIfNeeded();
}
}

View File

@ -186,23 +186,27 @@ struct WeakListVisitor<AllocationSite> {
};
template <>
struct WeakListVisitor<JSFinalizationGroup> {
static void SetWeakNext(JSFinalizationGroup obj, Object next) {
struct WeakListVisitor<JSFinalizationRegistry> {
static void SetWeakNext(JSFinalizationRegistry obj, Object next) {
obj.set_next_dirty(next, UPDATE_WEAK_WRITE_BARRIER);
}
static Object WeakNext(JSFinalizationGroup obj) { return obj.next_dirty(); }
static HeapObject WeakNextHolder(JSFinalizationGroup obj) { return obj; }
static int WeakNextOffset() { return JSFinalizationGroup::kNextDirtyOffset; }
static void VisitLiveObject(Heap* heap, JSFinalizationGroup obj,
WeakObjectRetainer*) {
heap->set_dirty_js_finalization_groups_list_tail(obj);
static Object WeakNext(JSFinalizationRegistry obj) {
return obj.next_dirty();
}
static void VisitPhantomObject(Heap*, JSFinalizationGroup) {}
static HeapObject WeakNextHolder(JSFinalizationRegistry obj) { return obj; }
static int WeakNextOffset() {
return JSFinalizationRegistry::kNextDirtyOffset;
}
static void VisitLiveObject(Heap* heap, JSFinalizationRegistry obj,
WeakObjectRetainer*) {
heap->set_dirty_js_finalization_registries_list_tail(obj);
}
static void VisitPhantomObject(Heap*, JSFinalizationRegistry) {}
};
template Object VisitWeakList<Context>(Heap* heap, Object list,
@ -211,7 +215,7 @@ template Object VisitWeakList<Context>(Heap* heap, Object list,
template Object VisitWeakList<AllocationSite>(Heap* heap, Object list,
WeakObjectRetainer* retainer);
template Object VisitWeakList<JSFinalizationGroup>(
template Object VisitWeakList<JSFinalizationRegistry>(
Heap* heap, Object list, WeakObjectRetainer* retainer);
} // namespace internal
} // namespace v8

View File

@ -67,8 +67,9 @@ bool Heap::CreateHeapObjects() {
set_native_contexts_list(ReadOnlyRoots(this).undefined_value());
set_allocation_sites_list(ReadOnlyRoots(this).undefined_value());
set_dirty_js_finalization_groups_list(ReadOnlyRoots(this).undefined_value());
set_dirty_js_finalization_groups_list_tail(
set_dirty_js_finalization_registries_list(
ReadOnlyRoots(this).undefined_value());
set_dirty_js_finalization_registries_list_tail(
ReadOnlyRoots(this).undefined_value());
return true;

View File

@ -4307,44 +4307,46 @@ void Genesis::InitializeGlobal_harmony_weak_refs() {
Handle<JSGlobalObject> global(native_context()->global_object(), isolate());
{
// Create %FinalizationGroupPrototype%
Handle<String> finalization_group_name =
// Create %FinalizationRegistryPrototype%
Handle<String> finalization_registry_name =
factory->NewStringFromStaticChars("FinalizationGroup");
Handle<JSObject> finalization_group_prototype = factory->NewJSObject(
Handle<JSObject> finalization_registry_prototype = factory->NewJSObject(
isolate()->object_function(), AllocationType::kOld);
// Create %FinalizationGroup%
Handle<JSFunction> finalization_group_fun = CreateFunction(
isolate(), finalization_group_name, JS_FINALIZATION_GROUP_TYPE,
JSFinalizationGroup::kHeaderSize, 0, finalization_group_prototype,
Builtins::kFinalizationGroupConstructor);
// Create %FinalizationRegistry%
Handle<JSFunction> finalization_registry_fun = CreateFunction(
isolate(), finalization_registry_name, JS_FINALIZATION_REGISTRY_TYPE,
JSFinalizationRegistry::kHeaderSize, 0, finalization_registry_prototype,
Builtins::kFinalizationRegistryConstructor);
InstallWithIntrinsicDefaultProto(
isolate(), finalization_group_fun,
Context::JS_FINALIZATION_GROUP_FUNCTION_INDEX);
isolate(), finalization_registry_fun,
Context::JS_FINALIZATION_REGISTRY_FUNCTION_INDEX);
finalization_group_fun->shared().DontAdaptArguments();
finalization_group_fun->shared().set_length(1);
finalization_registry_fun->shared().DontAdaptArguments();
finalization_registry_fun->shared().set_length(1);
// Install the "constructor" property on the prototype.
JSObject::AddProperty(isolate(), finalization_group_prototype,
factory->constructor_string(), finalization_group_fun,
DONT_ENUM);
JSObject::AddProperty(isolate(), finalization_registry_prototype,
factory->constructor_string(),
finalization_registry_fun, DONT_ENUM);
InstallToStringTag(isolate(), finalization_group_prototype,
finalization_group_name);
InstallToStringTag(isolate(), finalization_registry_prototype,
finalization_registry_name);
JSObject::AddProperty(isolate(), global, finalization_group_name,
finalization_group_fun, DONT_ENUM);
JSObject::AddProperty(isolate(), global, finalization_registry_name,
finalization_registry_fun, DONT_ENUM);
SimpleInstallFunction(isolate(), finalization_group_prototype, "register",
Builtins::kFinalizationGroupRegister, 2, false);
SimpleInstallFunction(isolate(), finalization_registry_prototype,
"register", Builtins::kFinalizationRegistryRegister,
2, false);
SimpleInstallFunction(isolate(), finalization_group_prototype, "unregister",
Builtins::kFinalizationGroupUnregister, 1, false);
SimpleInstallFunction(isolate(), finalization_registry_prototype,
"unregister",
Builtins::kFinalizationRegistryUnregister, 1, false);
SimpleInstallFunction(isolate(), finalization_group_prototype,
SimpleInstallFunction(isolate(), finalization_registry_prototype,
"cleanupSome",
Builtins::kFinalizationGroupCleanupSome, 0, false);
Builtins::kFinalizationRegistryCleanupSome, 0, false);
}
{
// Create %WeakRefPrototype%
@ -4383,7 +4385,7 @@ void Genesis::InitializeGlobal_harmony_weak_refs() {
}
{
// Create cleanup iterator for JSFinalizationGroup.
// Create cleanup iterator for JSFinalizationRegistry.
Handle<JSObject> iterator_prototype(
native_context()->initial_iterator_prototype(), isolate());
@ -4395,14 +4397,14 @@ void Genesis::InitializeGlobal_harmony_weak_refs() {
"FinalizationGroup Cleanup Iterator");
SimpleInstallFunction(isolate(), cleanup_iterator_prototype, "next",
Builtins::kFinalizationGroupCleanupIteratorNext, 0,
Builtins::kFinalizationRegistryCleanupIteratorNext, 0,
true);
Handle<Map> cleanup_iterator_map =
factory->NewMap(JS_FINALIZATION_GROUP_CLEANUP_ITERATOR_TYPE,
JSFinalizationGroupCleanupIterator::kHeaderSize);
factory->NewMap(JS_FINALIZATION_REGISTRY_CLEANUP_ITERATOR_TYPE,
JSFinalizationRegistryCleanupIterator::kHeaderSize);
Map::SetPrototype(isolate(), cleanup_iterator_map,
cleanup_iterator_prototype);
native_context()->set_js_finalization_group_cleanup_iterator_map(
native_context()->set_js_finalization_registry_cleanup_iterator_map(
*cleanup_iterator_map);
}
}

View File

@ -989,7 +989,7 @@ class RuntimeCallTimer final {
V(DeoptimizeCode) \
V(DeserializeContext) \
V(DeserializeIsolate) \
V(FinalizationGroupCleanupFromTask) \
V(FinalizationRegistryCleanupFromTask) \
V(FunctionCallback) \
V(FunctionLengthGetter) \
V(FunctionPrototypeGetter) \

View File

@ -188,13 +188,13 @@ enum ContextLookupFlags {
V(JS_SET_FUN_INDEX, JSFunction, js_set_fun) \
V(JS_SET_MAP_INDEX, Map, js_set_map) \
V(WEAK_CELL_MAP_INDEX, Map, weak_cell_map) \
V(JS_FINALIZATION_GROUP_CLEANUP_ITERATOR_MAP_INDEX, Map, \
js_finalization_group_cleanup_iterator_map) \
V(JS_FINALIZATION_REGISTRY_CLEANUP_ITERATOR_MAP_INDEX, Map, \
js_finalization_registry_cleanup_iterator_map) \
V(JS_WEAK_MAP_FUN_INDEX, JSFunction, js_weak_map_fun) \
V(JS_WEAK_SET_FUN_INDEX, JSFunction, js_weak_set_fun) \
V(JS_WEAK_REF_FUNCTION_INDEX, JSFunction, js_weak_ref_fun) \
V(JS_FINALIZATION_GROUP_FUNCTION_INDEX, JSFunction, \
js_finalization_group_fun) \
V(JS_FINALIZATION_REGISTRY_FUNCTION_INDEX, JSFunction, \
js_finalization_registry_fun) \
/* Context maps */ \
V(NATIVE_CONTEXT_MAP_INDEX, Map, native_context_map) \
V(FUNCTION_CONTEXT_MAP_INDEX, Map, function_context_map) \

View File

@ -2138,10 +2138,10 @@ int JSObject::GetHeaderSize(InstanceType type,
return JSMapIterator::kHeaderSize;
case JS_WEAK_REF_TYPE:
return JSWeakRef::kHeaderSize;
case JS_FINALIZATION_GROUP_TYPE:
return JSFinalizationGroup::kHeaderSize;
case JS_FINALIZATION_GROUP_CLEANUP_ITERATOR_TYPE:
return JSFinalizationGroupCleanupIterator::kHeaderSize;
case JS_FINALIZATION_REGISTRY_TYPE:
return JSFinalizationRegistry::kHeaderSize;
case JS_FINALIZATION_REGISTRY_CLEANUP_ITERATOR_TYPE:
return JSFinalizationRegistryCleanupIterator::kHeaderSize;
case JS_WEAK_MAP_TYPE:
return JSWeakMap::kHeaderSize;
case JS_WEAK_SET_TYPE:
@ -5252,7 +5252,7 @@ bool CanSubclassHaveInobjectProperties(InstanceType instance_type) {
case JS_MESSAGE_OBJECT_TYPE:
case JS_OBJECT_TYPE:
case JS_ERROR_TYPE:
case JS_FINALIZATION_GROUP_TYPE:
case JS_FINALIZATION_REGISTRY_TYPE:
case JS_ARGUMENTS_OBJECT_TYPE:
case JS_PROMISE_TYPE:
case JS_REG_EXP_TYPE:

View File

@ -19,25 +19,26 @@ namespace internal {
TQ_OBJECT_CONSTRUCTORS_IMPL(WeakCell)
TQ_OBJECT_CONSTRUCTORS_IMPL(JSWeakRef)
OBJECT_CONSTRUCTORS_IMPL(JSFinalizationGroup, JSObject)
TQ_OBJECT_CONSTRUCTORS_IMPL(JSFinalizationGroupCleanupIterator)
OBJECT_CONSTRUCTORS_IMPL(JSFinalizationRegistry, JSObject)
TQ_OBJECT_CONSTRUCTORS_IMPL(JSFinalizationRegistryCleanupIterator)
ACCESSORS(JSFinalizationGroup, native_context, NativeContext,
ACCESSORS(JSFinalizationRegistry, native_context, NativeContext,
kNativeContextOffset)
ACCESSORS(JSFinalizationGroup, cleanup, Object, kCleanupOffset)
ACCESSORS(JSFinalizationGroup, active_cells, HeapObject, kActiveCellsOffset)
ACCESSORS(JSFinalizationGroup, cleared_cells, HeapObject, kClearedCellsOffset)
ACCESSORS(JSFinalizationGroup, key_map, Object, kKeyMapOffset)
SMI_ACCESSORS(JSFinalizationGroup, flags, kFlagsOffset)
ACCESSORS(JSFinalizationGroup, next_dirty, Object, kNextDirtyOffset)
CAST_ACCESSOR(JSFinalizationGroup)
ACCESSORS(JSFinalizationRegistry, cleanup, Object, kCleanupOffset)
ACCESSORS(JSFinalizationRegistry, active_cells, HeapObject, kActiveCellsOffset)
ACCESSORS(JSFinalizationRegistry, cleared_cells, HeapObject,
kClearedCellsOffset)
ACCESSORS(JSFinalizationRegistry, key_map, Object, kKeyMapOffset)
SMI_ACCESSORS(JSFinalizationRegistry, flags, kFlagsOffset)
ACCESSORS(JSFinalizationRegistry, next_dirty, Object, kNextDirtyOffset)
CAST_ACCESSOR(JSFinalizationRegistry)
void JSFinalizationGroup::Register(
Handle<JSFinalizationGroup> finalization_group, Handle<JSReceiver> target,
Handle<Object> holdings, Handle<Object> unregister_token,
Isolate* isolate) {
void JSFinalizationRegistry::Register(
Handle<JSFinalizationRegistry> finalization_registry,
Handle<JSReceiver> target, Handle<Object> holdings,
Handle<Object> unregister_token, Isolate* isolate) {
Handle<WeakCell> weak_cell = isolate->factory()->NewWeakCell();
weak_cell->set_finalization_group(*finalization_group);
weak_cell->set_finalization_registry(*finalization_registry);
weak_cell->set_target(*target);
weak_cell->set_holdings(*holdings);
weak_cell->set_prev(ReadOnlyRoots(isolate).undefined_value());
@ -47,19 +48,20 @@ void JSFinalizationGroup::Register(
weak_cell->set_key_list_next(ReadOnlyRoots(isolate).undefined_value());
// Add to active_cells.
weak_cell->set_next(finalization_group->active_cells());
if (finalization_group->active_cells().IsWeakCell()) {
WeakCell::cast(finalization_group->active_cells()).set_prev(*weak_cell);
weak_cell->set_next(finalization_registry->active_cells());
if (finalization_registry->active_cells().IsWeakCell()) {
WeakCell::cast(finalization_registry->active_cells()).set_prev(*weak_cell);
}
finalization_group->set_active_cells(*weak_cell);
finalization_registry->set_active_cells(*weak_cell);
if (!unregister_token->IsUndefined(isolate)) {
Handle<SimpleNumberDictionary> key_map;
if (finalization_group->key_map().IsUndefined(isolate)) {
if (finalization_registry->key_map().IsUndefined(isolate)) {
key_map = SimpleNumberDictionary::New(isolate, 1);
} else {
key_map = handle(
SimpleNumberDictionary::cast(finalization_group->key_map()), isolate);
key_map =
handle(SimpleNumberDictionary::cast(finalization_registry->key_map()),
isolate);
}
// Unregister tokens are held weakly as objects are often their own
@ -74,29 +76,29 @@ void JSFinalizationGroup::Register(
weak_cell->set_key_list_next(existing_weak_cell);
}
key_map = SimpleNumberDictionary::Set(isolate, key_map, key, weak_cell);
finalization_group->set_key_map(*key_map);
finalization_registry->set_key_map(*key_map);
}
}
bool JSFinalizationGroup::Unregister(
Handle<JSFinalizationGroup> finalization_group,
bool JSFinalizationRegistry::Unregister(
Handle<JSFinalizationRegistry> finalization_registry,
Handle<JSReceiver> unregister_token, Isolate* isolate) {
// Iterate through the doubly linked list of WeakCells associated with the
// key. Each WeakCell will be in the "active_cells" or "cleared_cells" list of
// its FinalizationGroup; remove it from there.
return finalization_group->RemoveUnregisterToken(
// its FinalizationRegistry; remove it from there.
return finalization_registry->RemoveUnregisterToken(
*unregister_token, isolate,
[isolate](WeakCell matched_cell) {
matched_cell.RemoveFromFinalizationGroupCells(isolate);
matched_cell.RemoveFromFinalizationRegistryCells(isolate);
},
[](HeapObject, ObjectSlot, Object) {});
}
template <typename MatchCallback, typename GCNotifyUpdatedSlotCallback>
bool JSFinalizationGroup::RemoveUnregisterToken(
bool JSFinalizationRegistry::RemoveUnregisterToken(
JSReceiver unregister_token, Isolate* isolate, MatchCallback match_callback,
GCNotifyUpdatedSlotCallback gc_notify_updated_slot) {
// This method is called from both FinalizationGroup#unregister and for
// This method is called from both FinalizationRegistry#unregister and for
// removing weakly-held dead unregister tokens. The latter is during GC so
// this function cannot GC.
DisallowHeapAllocation no_gc;
@ -169,41 +171,42 @@ bool JSFinalizationGroup::RemoveUnregisterToken(
return was_present;
}
bool JSFinalizationGroup::NeedsCleanup() const {
bool JSFinalizationRegistry::NeedsCleanup() const {
return cleared_cells().IsWeakCell();
}
bool JSFinalizationGroup::scheduled_for_cleanup() const {
bool JSFinalizationRegistry::scheduled_for_cleanup() const {
return ScheduledForCleanupField::decode(flags());
}
void JSFinalizationGroup::set_scheduled_for_cleanup(
void JSFinalizationRegistry::set_scheduled_for_cleanup(
bool scheduled_for_cleanup) {
set_flags(ScheduledForCleanupField::update(flags(), scheduled_for_cleanup));
}
Object JSFinalizationGroup::PopClearedCellHoldings(
Handle<JSFinalizationGroup> finalization_group, Isolate* isolate) {
Object JSFinalizationRegistry::PopClearedCellHoldings(
Handle<JSFinalizationRegistry> finalization_registry, Isolate* isolate) {
Handle<WeakCell> weak_cell =
handle(WeakCell::cast(finalization_group->cleared_cells()), isolate);
handle(WeakCell::cast(finalization_registry->cleared_cells()), isolate);
DCHECK(weak_cell->prev().IsUndefined(isolate));
finalization_group->set_cleared_cells(weak_cell->next());
finalization_registry->set_cleared_cells(weak_cell->next());
weak_cell->set_next(ReadOnlyRoots(isolate).undefined_value());
if (finalization_group->cleared_cells().IsWeakCell()) {
if (finalization_registry->cleared_cells().IsWeakCell()) {
WeakCell cleared_cells_head =
WeakCell::cast(finalization_group->cleared_cells());
WeakCell::cast(finalization_registry->cleared_cells());
DCHECK_EQ(cleared_cells_head.prev(), *weak_cell);
cleared_cells_head.set_prev(ReadOnlyRoots(isolate).undefined_value());
} else {
DCHECK(finalization_group->cleared_cells().IsUndefined(isolate));
DCHECK(finalization_registry->cleared_cells().IsUndefined(isolate));
}
// Also remove the WeakCell from the key_map (if it's there).
if (!weak_cell->unregister_token().IsUndefined(isolate)) {
if (weak_cell->key_list_prev().IsUndefined(isolate)) {
Handle<SimpleNumberDictionary> key_map = handle(
SimpleNumberDictionary::cast(finalization_group->key_map()), isolate);
Handle<SimpleNumberDictionary> key_map =
handle(SimpleNumberDictionary::cast(finalization_registry->key_map()),
isolate);
Handle<Object> unregister_token =
handle(weak_cell->unregister_token(), isolate);
uint32_t key = Smi::ToInt(unregister_token->GetHash());
@ -214,7 +217,7 @@ Object JSFinalizationGroup::PopClearedCellHoldings(
// from the hash table.
DCHECK(entry.is_found());
key_map = SimpleNumberDictionary::DeleteEntry(isolate, key_map, entry);
finalization_group->set_key_map(*key_map);
finalization_registry->set_key_map(*key_map);
} else {
// weak_cell is the list head for its key; we need to change the value
// of the key in the hash table.
@ -224,7 +227,7 @@ Object JSFinalizationGroup::PopClearedCellHoldings(
next->set_key_list_prev(ReadOnlyRoots(isolate).undefined_value());
weak_cell->set_key_list_next(ReadOnlyRoots(isolate).undefined_value());
key_map = SimpleNumberDictionary::Set(isolate, key_map, key, next);
finalization_group->set_key_map(*key_map);
finalization_registry->set_key_map(*key_map);
}
} else {
// weak_cell is somewhere in the middle of its key list.
@ -244,25 +247,26 @@ template <typename GCNotifyUpdatedSlotCallback>
void WeakCell::Nullify(Isolate* isolate,
GCNotifyUpdatedSlotCallback gc_notify_updated_slot) {
// Remove from the WeakCell from the "active_cells" list of its
// JSFinalizationGroup and insert it into the "cleared_cells" list. This is
// JSFinalizationRegistry and insert it into the "cleared_cells" list. This is
// only called for WeakCells which haven't been unregistered yet, so they will
// be in the active_cells list. (The caller must guard against calling this
// for unregistered WeakCells by checking that the target is not undefined.)
DCHECK(target().IsJSReceiver());
set_target(ReadOnlyRoots(isolate).undefined_value());
JSFinalizationGroup fg = JSFinalizationGroup::cast(finalization_group());
JSFinalizationRegistry fr =
JSFinalizationRegistry::cast(finalization_registry());
if (prev().IsWeakCell()) {
DCHECK_NE(fg.active_cells(), *this);
DCHECK_NE(fr.active_cells(), *this);
WeakCell prev_cell = WeakCell::cast(prev());
prev_cell.set_next(next());
gc_notify_updated_slot(prev_cell, prev_cell.RawField(WeakCell::kNextOffset),
next());
} else {
DCHECK_EQ(fg.active_cells(), *this);
fg.set_active_cells(next());
DCHECK_EQ(fr.active_cells(), *this);
fr.set_active_cells(next());
gc_notify_updated_slot(
fg, fg.RawField(JSFinalizationGroup::kActiveCellsOffset), next());
fr, fr.RawField(JSFinalizationRegistry::kActiveCellsOffset), next());
}
if (next().IsWeakCell()) {
WeakCell next_cell = WeakCell::cast(next());
@ -272,7 +276,7 @@ void WeakCell::Nullify(Isolate* isolate,
}
set_prev(ReadOnlyRoots(isolate).undefined_value());
Object cleared_head = fg.cleared_cells();
Object cleared_head = fr.cleared_cells();
if (cleared_head.IsWeakCell()) {
WeakCell cleared_head_cell = WeakCell::cast(cleared_head);
cleared_head_cell.set_prev(*this);
@ -280,29 +284,30 @@ void WeakCell::Nullify(Isolate* isolate,
cleared_head_cell.RawField(WeakCell::kPrevOffset),
*this);
}
set_next(fg.cleared_cells());
set_next(fr.cleared_cells());
gc_notify_updated_slot(*this, RawField(WeakCell::kNextOffset), next());
fg.set_cleared_cells(*this);
fr.set_cleared_cells(*this);
gc_notify_updated_slot(
fg, fg.RawField(JSFinalizationGroup::kClearedCellsOffset), *this);
fr, fr.RawField(JSFinalizationRegistry::kClearedCellsOffset), *this);
}
void WeakCell::RemoveFromFinalizationGroupCells(Isolate* isolate) {
void WeakCell::RemoveFromFinalizationRegistryCells(Isolate* isolate) {
// Remove the WeakCell from the list it's in (either "active_cells" or
// "cleared_cells" of its JSFinalizationGroup).
// "cleared_cells" of its JSFinalizationRegistry).
// It's important to set_target to undefined here. This guards that we won't
// call Nullify (which assumes that the WeakCell is in active_cells).
DCHECK(target().IsUndefined() || target().IsJSReceiver());
set_target(ReadOnlyRoots(isolate).undefined_value());
JSFinalizationGroup fg = JSFinalizationGroup::cast(finalization_group());
if (fg.active_cells() == *this) {
JSFinalizationRegistry fr =
JSFinalizationRegistry::cast(finalization_registry());
if (fr.active_cells() == *this) {
DCHECK(prev().IsUndefined(isolate));
fg.set_active_cells(next());
} else if (fg.cleared_cells() == *this) {
fr.set_active_cells(next());
} else if (fr.cleared_cells() == *this) {
DCHECK(!prev().IsWeakCell());
fg.set_cleared_cells(next());
fr.set_cleared_cells(next());
} else {
DCHECK(prev().IsWeakCell());
WeakCell prev_cell = WeakCell::cast(prev());

View File

@ -16,13 +16,13 @@ namespace internal {
class NativeContext;
class WeakCell;
// FinalizationGroup object from the JS Weak Refs spec proposal:
// FinalizationRegistry object from the JS Weak Refs spec proposal:
// https://github.com/tc39/proposal-weakrefs
class JSFinalizationGroup : public JSObject {
class JSFinalizationRegistry : public JSObject {
public:
DECL_PRINTER(JSFinalizationGroup)
EXPORT_DECL_VERIFIER(JSFinalizationGroup)
DECL_CAST(JSFinalizationGroup)
DECL_PRINTER(JSFinalizationRegistry)
EXPORT_DECL_VERIFIER(JSFinalizationRegistry)
DECL_CAST(JSFinalizationRegistry)
DECL_ACCESSORS(native_context, NativeContext)
DECL_ACCESSORS(cleanup, Object)
@ -37,13 +37,13 @@ class JSFinalizationGroup : public JSObject {
class BodyDescriptor;
inline static void Register(Handle<JSFinalizationGroup> finalization_group,
Handle<JSReceiver> target,
Handle<Object> holdings, Handle<Object> key,
Isolate* isolate);
inline static bool Unregister(Handle<JSFinalizationGroup> finalization_group,
Handle<JSReceiver> unregister_token,
Isolate* isolate);
inline static void Register(
Handle<JSFinalizationRegistry> finalization_registry,
Handle<JSReceiver> target, Handle<Object> holdings, Handle<Object> key,
Isolate* isolate);
inline static bool Unregister(
Handle<JSFinalizationRegistry> finalization_registry,
Handle<JSReceiver> unregister_token, Isolate* isolate);
// RemoveUnregisterToken is called from both Unregister and during GC. Since
// it modifies slots in key_map and WeakCells and the normal write barrier is
@ -64,27 +64,27 @@ class JSFinalizationGroup : public JSObject {
// Remove the first cleared WeakCell from the cleared_cells
// list (assumes there is one) and return its holdings.
inline static Object PopClearedCellHoldings(
Handle<JSFinalizationGroup> finalization_group, Isolate* isolate);
Handle<JSFinalizationRegistry> finalization_registry, Isolate* isolate);
// Constructs an iterator for the WeakCells in the cleared_cells list and
// calls the user's cleanup function.
//
// Returns Nothing<bool> if exception occurs, otherwise returns Just(true).
static V8_WARN_UNUSED_RESULT Maybe<bool> Cleanup(
Isolate* isolate, Handle<JSFinalizationGroup> finalization_group,
Isolate* isolate, Handle<JSFinalizationRegistry> finalization_registry,
Handle<Object> callback);
// Layout description.
DEFINE_FIELD_OFFSET_CONSTANTS(JSObject::kHeaderSize,
TORQUE_GENERATED_JS_FINALIZATION_GROUP_FIELDS)
DEFINE_FIELD_OFFSET_CONSTANTS(
JSObject::kHeaderSize, TORQUE_GENERATED_JS_FINALIZATION_REGISTRY_FIELDS)
// Bitfields in flags.
using ScheduledForCleanupField = base::BitField<bool, 0, 1>;
OBJECT_CONSTRUCTORS(JSFinalizationGroup, JSObject);
OBJECT_CONSTRUCTORS(JSFinalizationRegistry, JSObject);
};
// Internal object for storing weak references in JSFinalizationGroup.
// Internal object for storing weak references in JSFinalizationRegistry.
class WeakCell : public TorqueGeneratedWeakCell<WeakCell, HeapObject> {
public:
DECL_PRINTER(WeakCell)
@ -93,14 +93,14 @@ class WeakCell : public TorqueGeneratedWeakCell<WeakCell, HeapObject> {
class BodyDescriptor;
// Nullify is called during GC and it modifies the pointers in WeakCell and
// JSFinalizationGroup. Thus we need to tell the GC about the modified slots
// via the gc_notify_updated_slot function. The normal write barrier is not
// enough, since it's disabled before GC.
// JSFinalizationRegistry. Thus we need to tell the GC about the modified
// slots via the gc_notify_updated_slot function. The normal write barrier is
// not enough, since it's disabled before GC.
template <typename GCNotifyUpdatedSlotCallback>
inline void Nullify(Isolate* isolate,
GCNotifyUpdatedSlotCallback gc_notify_updated_slot);
inline void RemoveFromFinalizationGroupCells(Isolate* isolate);
inline void RemoveFromFinalizationRegistryCells(Isolate* isolate);
TQ_OBJECT_CONSTRUCTORS(WeakCell)
};
@ -115,14 +115,14 @@ class JSWeakRef : public TorqueGeneratedJSWeakRef<JSWeakRef, JSObject> {
TQ_OBJECT_CONSTRUCTORS(JSWeakRef)
};
class JSFinalizationGroupCleanupIterator
: public TorqueGeneratedJSFinalizationGroupCleanupIterator<
JSFinalizationGroupCleanupIterator, JSObject> {
class JSFinalizationRegistryCleanupIterator
: public TorqueGeneratedJSFinalizationRegistryCleanupIterator<
JSFinalizationRegistryCleanupIterator, JSObject> {
public:
DECL_PRINTER(JSFinalizationGroupCleanupIterator)
DECL_VERIFIER(JSFinalizationGroupCleanupIterator)
DECL_PRINTER(JSFinalizationRegistryCleanupIterator)
DECL_VERIFIER(JSFinalizationRegistryCleanupIterator)
TQ_OBJECT_CONSTRUCTORS(JSFinalizationGroupCleanupIterator)
TQ_OBJECT_CONSTRUCTORS(JSFinalizationRegistryCleanupIterator)
};
} // namespace internal

View File

@ -2,39 +2,39 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
extern class JSFinalizationGroup extends JSObject {
extern class JSFinalizationRegistry extends JSObject {
native_context: NativeContext;
cleanup: Object;
active_cells: Undefined|WeakCell;
cleared_cells: Undefined|WeakCell;
key_map: Object;
// For the linked list of FinalizationGroups that need cleanup. This link
// is weak.
next_dirty: Undefined|JSFinalizationGroup;
// For the linked list of FinalizationRegistries that need cleanup. This
// link is weak.
next_dirty: Undefined|JSFinalizationRegistry;
flags: Smi;
}
@generateCppClass
extern class JSFinalizationGroupCleanupIterator extends JSObject {
finalization_group: JSFinalizationGroup;
extern class JSFinalizationRegistryCleanupIterator extends JSObject {
finalization_registry: JSFinalizationRegistry;
}
@generateCppClass
extern class WeakCell extends HeapObject {
finalization_group: Undefined|JSFinalizationGroup;
finalization_registry: Undefined|JSFinalizationRegistry;
target: Undefined|JSReceiver;
unregister_token: Object;
holdings: Object;
// For storing doubly linked lists of WeakCells in JSFinalizationGroup's
// For storing doubly linked lists of WeakCells in JSFinalizationRegistry's
// "active_cells" and "cleared_cells" lists.
prev: Undefined|WeakCell;
next: Undefined|WeakCell;
// For storing doubly linked lists of WeakCells per key in
// JSFinalizationGroup's key-based hashmap. The key is the identity hash of
// unregister_token. WeakCell also needs to know its token, so that we can
// remove its corresponding key from the key_map when we remove the last
// JSFinalizationRegistry's key-based hashmap. The key is the identity hash
// of unregister_token. WeakCell also needs to know its token, so that we
// can remove its corresponding key from the key_map when we remove the last
// WeakCell associated with it or when the unregister_token dies. The
// unregister token is stored above, after target, as both are weak.
key_list_prev: Undefined|WeakCell;

View File

@ -288,8 +288,8 @@ VisitorId Map::GetVisitorId(Map map) {
case JS_PROMISE_TYPE:
case JS_REG_EXP_TYPE:
case JS_REG_EXP_STRING_ITERATOR_TYPE:
case JS_FINALIZATION_GROUP_CLEANUP_ITERATOR_TYPE:
case JS_FINALIZATION_GROUP_TYPE:
case JS_FINALIZATION_REGISTRY_CLEANUP_ITERATOR_TYPE:
case JS_FINALIZATION_REGISTRY_TYPE:
#ifdef V8_INTL_SUPPORT
case JS_V8_BREAK_ITERATOR_TYPE:
case JS_COLLATOR_TYPE:

View File

@ -140,8 +140,8 @@ class ZoneForwardList;
V(JSDataView) \
V(JSDate) \
V(JSError) \
V(JSFinalizationGroup) \
V(JSFinalizationGroupCleanupIterator) \
V(JSFinalizationRegistry) \
V(JSFinalizationRegistryCleanupIterator) \
V(JSFunction) \
V(JSFunctionOrBoundFunction) \
V(JSGeneratorObject) \

View File

@ -248,7 +248,7 @@ class JSWeakRef::BodyDescriptor final : public BodyDescriptorBase {
}
};
class JSFinalizationGroup::BodyDescriptor final : public BodyDescriptorBase {
class JSFinalizationRegistry::BodyDescriptor final : public BodyDescriptorBase {
public:
static bool IsValidSlot(Map map, HeapObject obj, int offset) {
return IsValidJSObjectSlotImpl(map, obj, offset);
@ -979,8 +979,8 @@ ReturnType BodyDescriptorApply(InstanceType type, T1 p1, T2 p2, T3 p3, T4 p4) {
case JS_SPECIAL_API_OBJECT_TYPE:
case JS_MESSAGE_OBJECT_TYPE:
case JS_BOUND_FUNCTION_TYPE:
case JS_FINALIZATION_GROUP_CLEANUP_ITERATOR_TYPE:
case JS_FINALIZATION_GROUP_TYPE:
case JS_FINALIZATION_REGISTRY_CLEANUP_ITERATOR_TYPE:
case JS_FINALIZATION_REGISTRY_TYPE:
#ifdef V8_INTL_SUPPORT
case JS_V8_BREAK_ITERATOR_TYPE:
case JS_COLLATOR_TYPE:

View File

@ -8194,35 +8194,36 @@ HashTable<NameDictionary, NameDictionaryShape>::Shrink(Isolate* isolate,
template void HashTable<GlobalDictionary, GlobalDictionaryShape>::Rehash(
ReadOnlyRoots roots);
Maybe<bool> JSFinalizationGroup::Cleanup(
Isolate* isolate, Handle<JSFinalizationGroup> finalization_group,
Maybe<bool> JSFinalizationRegistry::Cleanup(
Isolate* isolate, Handle<JSFinalizationRegistry> finalization_registry,
Handle<Object> cleanup) {
DCHECK(cleanup->IsCallable());
// Attempt to shrink key_map now, as unregister tokens are held weakly and the
// map is not shrinkable when sweeping dead tokens during GC itself.
if (!finalization_group->key_map().IsUndefined(isolate)) {
Handle<SimpleNumberDictionary> key_map = handle(
SimpleNumberDictionary::cast(finalization_group->key_map()), isolate);
if (!finalization_registry->key_map().IsUndefined(isolate)) {
Handle<SimpleNumberDictionary> key_map =
handle(SimpleNumberDictionary::cast(finalization_registry->key_map()),
isolate);
key_map = SimpleNumberDictionary::Shrink(isolate, key_map);
finalization_group->set_key_map(*key_map);
finalization_registry->set_key_map(*key_map);
}
// It's possible that the cleared_cells list is empty, since
// FinalizationGroup.unregister() removed all its elements before this task
// FinalizationRegistry.unregister() removed all its elements before this task
// ran. In that case, don't call the cleanup function.
if (!finalization_group->cleared_cells().IsUndefined(isolate)) {
if (!finalization_registry->cleared_cells().IsUndefined(isolate)) {
// Construct the iterator.
Handle<JSFinalizationGroupCleanupIterator> iterator;
Handle<JSFinalizationRegistryCleanupIterator> iterator;
{
Handle<Map> cleanup_iterator_map(
isolate->native_context()
->js_finalization_group_cleanup_iterator_map(),
->js_finalization_registry_cleanup_iterator_map(),
isolate);
iterator = Handle<JSFinalizationGroupCleanupIterator>::cast(
iterator = Handle<JSFinalizationRegistryCleanupIterator>::cast(
isolate->factory()->NewJSObjectFromMap(
cleanup_iterator_map, AllocationType::kYoung,
Handle<AllocationSite>::null()));
iterator->set_finalization_group(*finalization_group);
iterator->set_finalization_registry(*finalization_registry);
}
Handle<Object> args[] = {iterator};
if (Execution::Call(

View File

@ -54,9 +54,9 @@ void StartupDeserializer::DeserializeInto(Isolate* isolate) {
isolate->heap()->set_allocation_sites_list(
ReadOnlyRoots(isolate).undefined_value());
}
isolate->heap()->set_dirty_js_finalization_groups_list(
isolate->heap()->set_dirty_js_finalization_registries_list(
ReadOnlyRoots(isolate).undefined_value());
isolate->heap()->set_dirty_js_finalization_groups_list_tail(
isolate->heap()->set_dirty_js_finalization_registries_list_tail(
ReadOnlyRoots(isolate).undefined_value());
isolate->builtins()->MarkInitialized();

View File

@ -169,12 +169,13 @@ void StartupSerializer::SerializeUsingPartialSnapshotCache(
sink->PutInt(cache_index, "partial_snapshot_cache_index");
}
void StartupSerializer::CheckNoDirtyFinalizationGroups() {
void StartupSerializer::CheckNoDirtyFinalizationRegistries() {
Isolate* isolate = this->isolate();
CHECK(isolate->heap()->dirty_js_finalization_groups_list().IsUndefined(
isolate));
CHECK(isolate->heap()->dirty_js_finalization_groups_list_tail().IsUndefined(
CHECK(isolate->heap()->dirty_js_finalization_registries_list().IsUndefined(
isolate));
CHECK(
isolate->heap()->dirty_js_finalization_registries_list_tail().IsUndefined(
isolate));
}
void SerializedHandleChecker::AddToSet(FixedArray serialized) {

View File

@ -41,9 +41,9 @@ class V8_EXPORT_PRIVATE StartupSerializer : public RootsSerializer {
void SerializeUsingPartialSnapshotCache(SnapshotByteSink* sink,
HeapObject obj);
// The per-heap dirty FinalizationGroup list is weak and not serialized. No
// JSFinalizationGroups should be used during startup.
void CheckNoDirtyFinalizationGroups();
// The per-heap dirty FinalizationRegistry list is weak and not serialized. No
// JSFinalizationRegistries should be used during startup.
void CheckNoDirtyFinalizationRegistries();
private:
void SerializeObject(HeapObject o) override;

View File

@ -16,23 +16,24 @@ namespace internal {
namespace {
Handle<JSFinalizationGroup> ConstructJSFinalizationGroup(Isolate* isolate) {
Handle<JSFinalizationRegistry> ConstructJSFinalizationRegistry(
Isolate* isolate) {
Factory* factory = isolate->factory();
Handle<String> finalization_group_name =
Handle<String> finalization_registry_name =
factory->NewStringFromStaticChars("FinalizationGroup");
Handle<Object> global =
handle(isolate->native_context()->global_object(), isolate);
Handle<JSFunction> finalization_group_fun = Handle<JSFunction>::cast(
Object::GetProperty(isolate, global, finalization_group_name)
Handle<JSFunction> finalization_registry_fun = Handle<JSFunction>::cast(
Object::GetProperty(isolate, global, finalization_registry_name)
.ToHandleChecked());
auto finalization_group = Handle<JSFinalizationGroup>::cast(
JSObject::New(finalization_group_fun, finalization_group_fun,
auto finalization_registry = Handle<JSFinalizationRegistry>::cast(
JSObject::New(finalization_registry_fun, finalization_registry_fun,
Handle<AllocationSite>::null())
.ToHandleChecked());
#ifdef VERIFY_HEAP
finalization_group->JSFinalizationGroupVerify(isolate);
finalization_registry->JSFinalizationRegistryVerify(isolate);
#endif // VERIFY_HEAP
return finalization_group;
return finalization_registry;
}
Handle<JSWeakRef> ConstructJSWeakRef(Handle<JSReceiver> target,
@ -64,27 +65,28 @@ Handle<JSObject> CreateKey(const char* key_prop_value, Isolate* isolate) {
return key;
}
Handle<WeakCell> FinalizationGroupRegister(
Handle<JSFinalizationGroup> finalization_group, Handle<JSObject> target,
Handle<Object> holdings, Handle<Object> key, Isolate* isolate) {
JSFinalizationGroup::Register(finalization_group, target, holdings, key,
isolate);
CHECK(finalization_group->active_cells().IsWeakCell());
Handle<WeakCell> FinalizationRegistryRegister(
Handle<JSFinalizationRegistry> finalization_registry,
Handle<JSObject> target, Handle<Object> holdings, Handle<Object> key,
Isolate* isolate) {
JSFinalizationRegistry::Register(finalization_registry, target, holdings, key,
isolate);
CHECK(finalization_registry->active_cells().IsWeakCell());
Handle<WeakCell> weak_cell =
handle(WeakCell::cast(finalization_group->active_cells()), isolate);
handle(WeakCell::cast(finalization_registry->active_cells()), isolate);
#ifdef VERIFY_HEAP
weak_cell->WeakCellVerify(isolate);
#endif // VERIFY_HEAP
return weak_cell;
}
Handle<WeakCell> FinalizationGroupRegister(
Handle<JSFinalizationGroup> finalization_group, Handle<JSObject> target,
Isolate* isolate) {
Handle<WeakCell> FinalizationRegistryRegister(
Handle<JSFinalizationRegistry> finalization_registry,
Handle<JSObject> target, Isolate* isolate) {
Handle<Object> undefined =
handle(ReadOnlyRoots(isolate).undefined_value(), isolate);
return FinalizationGroupRegister(finalization_group, target, undefined,
undefined, isolate);
return FinalizationRegistryRegister(finalization_registry, target, undefined,
undefined, isolate);
}
void NullifyWeakCell(Handle<WeakCell> weak_cell, Isolate* isolate) {
@ -177,36 +179,36 @@ TEST(TestRegister) {
LocalContext context;
Isolate* isolate = CcTest::i_isolate();
HandleScope outer_scope(isolate);
Handle<JSFinalizationGroup> finalization_group =
ConstructJSFinalizationGroup(isolate);
Handle<JSFinalizationRegistry> finalization_registry =
ConstructJSFinalizationRegistry(isolate);
Handle<JSObject> js_object =
isolate->factory()->NewJSObject(isolate->object_function());
// Register a weak reference and verify internal data structures.
Handle<WeakCell> weak_cell1 =
FinalizationGroupRegister(finalization_group, js_object, isolate);
FinalizationRegistryRegister(finalization_registry, js_object, isolate);
VerifyWeakCellChain(isolate, finalization_group->active_cells(), 1,
VerifyWeakCellChain(isolate, finalization_registry->active_cells(), 1,
*weak_cell1);
CHECK(weak_cell1->key_list_prev().IsUndefined(isolate));
CHECK(weak_cell1->key_list_next().IsUndefined(isolate));
CHECK(finalization_group->cleared_cells().IsUndefined(isolate));
CHECK(finalization_registry->cleared_cells().IsUndefined(isolate));
// No key was used during registration, key-based map stays uninitialized.
CHECK(finalization_group->key_map().IsUndefined(isolate));
CHECK(finalization_registry->key_map().IsUndefined(isolate));
// Register another weak reference and verify internal data structures.
Handle<WeakCell> weak_cell2 =
FinalizationGroupRegister(finalization_group, js_object, isolate);
FinalizationRegistryRegister(finalization_registry, js_object, isolate);
VerifyWeakCellChain(isolate, finalization_group->active_cells(), 2,
VerifyWeakCellChain(isolate, finalization_registry->active_cells(), 2,
*weak_cell2, *weak_cell1);
CHECK(weak_cell2->key_list_prev().IsUndefined(isolate));
CHECK(weak_cell2->key_list_next().IsUndefined(isolate));
CHECK(finalization_group->cleared_cells().IsUndefined(isolate));
CHECK(finalization_group->key_map().IsUndefined(isolate));
CHECK(finalization_registry->cleared_cells().IsUndefined(isolate));
CHECK(finalization_registry->key_map().IsUndefined(isolate));
}
TEST(TestRegisterWithKey) {
@ -215,8 +217,8 @@ TEST(TestRegisterWithKey) {
LocalContext context;
Isolate* isolate = CcTest::i_isolate();
HandleScope outer_scope(isolate);
Handle<JSFinalizationGroup> finalization_group =
ConstructJSFinalizationGroup(isolate);
Handle<JSFinalizationRegistry> finalization_registry =
ConstructJSFinalizationRegistry(isolate);
Handle<JSObject> js_object =
isolate->factory()->NewJSObject(isolate->object_function());
@ -226,36 +228,36 @@ TEST(TestRegisterWithKey) {
handle(ReadOnlyRoots(isolate).undefined_value(), isolate);
// Register a weak reference with a key and verify internal data structures.
Handle<WeakCell> weak_cell1 = FinalizationGroupRegister(
finalization_group, js_object, undefined, token1, isolate);
Handle<WeakCell> weak_cell1 = FinalizationRegistryRegister(
finalization_registry, js_object, undefined, token1, isolate);
{
SimpleNumberDictionary key_map =
SimpleNumberDictionary::cast(finalization_group->key_map());
SimpleNumberDictionary::cast(finalization_registry->key_map());
VerifyWeakCellKeyChain(isolate, key_map, *token1, 1, *weak_cell1);
VerifyWeakCellKeyChain(isolate, key_map, *token2, 0);
}
// Register another weak reference with a different key and verify internal
// data structures.
Handle<WeakCell> weak_cell2 = FinalizationGroupRegister(
finalization_group, js_object, undefined, token2, isolate);
Handle<WeakCell> weak_cell2 = FinalizationRegistryRegister(
finalization_registry, js_object, undefined, token2, isolate);
{
SimpleNumberDictionary key_map =
SimpleNumberDictionary::cast(finalization_group->key_map());
SimpleNumberDictionary::cast(finalization_registry->key_map());
VerifyWeakCellKeyChain(isolate, key_map, *token1, 1, *weak_cell1);
VerifyWeakCellKeyChain(isolate, key_map, *token2, 1, *weak_cell2);
}
// Register another weak reference with token1 and verify internal data
// structures.
Handle<WeakCell> weak_cell3 = FinalizationGroupRegister(
finalization_group, js_object, undefined, token1, isolate);
Handle<WeakCell> weak_cell3 = FinalizationRegistryRegister(
finalization_registry, js_object, undefined, token1, isolate);
{
SimpleNumberDictionary key_map =
SimpleNumberDictionary::cast(finalization_group->key_map());
SimpleNumberDictionary::cast(finalization_registry->key_map());
VerifyWeakCellKeyChain(isolate, key_map, *token1, 2, *weak_cell3,
*weak_cell1);
VerifyWeakCellKeyChain(isolate, key_map, *token2, 1, *weak_cell2);
@ -268,29 +270,29 @@ TEST(TestWeakCellNullify1) {
LocalContext context;
Isolate* isolate = CcTest::i_isolate();
HandleScope outer_scope(isolate);
Handle<JSFinalizationGroup> finalization_group =
ConstructJSFinalizationGroup(isolate);
Handle<JSFinalizationRegistry> finalization_registry =
ConstructJSFinalizationRegistry(isolate);
Handle<JSObject> js_object =
isolate->factory()->NewJSObject(isolate->object_function());
Handle<WeakCell> weak_cell1 =
FinalizationGroupRegister(finalization_group, js_object, isolate);
FinalizationRegistryRegister(finalization_registry, js_object, isolate);
Handle<WeakCell> weak_cell2 =
FinalizationGroupRegister(finalization_group, js_object, isolate);
FinalizationRegistryRegister(finalization_registry, js_object, isolate);
// Nullify the first WeakCell and verify internal data structures.
NullifyWeakCell(weak_cell1, isolate);
CHECK_EQ(finalization_group->active_cells(), *weak_cell2);
CHECK_EQ(finalization_registry->active_cells(), *weak_cell2);
CHECK(weak_cell2->prev().IsUndefined(isolate));
CHECK(weak_cell2->next().IsUndefined(isolate));
CHECK_EQ(finalization_group->cleared_cells(), *weak_cell1);
CHECK_EQ(finalization_registry->cleared_cells(), *weak_cell1);
CHECK(weak_cell1->prev().IsUndefined(isolate));
CHECK(weak_cell1->next().IsUndefined(isolate));
// Nullify the second WeakCell and verify internal data structures.
NullifyWeakCell(weak_cell2, isolate);
CHECK(finalization_group->active_cells().IsUndefined(isolate));
CHECK_EQ(finalization_group->cleared_cells(), *weak_cell2);
CHECK(finalization_registry->active_cells().IsUndefined(isolate));
CHECK_EQ(finalization_registry->cleared_cells(), *weak_cell2);
CHECK_EQ(weak_cell2->next(), *weak_cell1);
CHECK(weak_cell2->prev().IsUndefined(isolate));
CHECK_EQ(weak_cell1->prev(), *weak_cell2);
@ -303,92 +305,92 @@ TEST(TestWeakCellNullify2) {
LocalContext context;
Isolate* isolate = CcTest::i_isolate();
HandleScope outer_scope(isolate);
Handle<JSFinalizationGroup> finalization_group =
ConstructJSFinalizationGroup(isolate);
Handle<JSFinalizationRegistry> finalization_registry =
ConstructJSFinalizationRegistry(isolate);
Handle<JSObject> js_object =
isolate->factory()->NewJSObject(isolate->object_function());
Handle<WeakCell> weak_cell1 =
FinalizationGroupRegister(finalization_group, js_object, isolate);
FinalizationRegistryRegister(finalization_registry, js_object, isolate);
Handle<WeakCell> weak_cell2 =
FinalizationGroupRegister(finalization_group, js_object, isolate);
FinalizationRegistryRegister(finalization_registry, js_object, isolate);
// Like TestWeakCellNullify1 but nullify the WeakCells in opposite order.
NullifyWeakCell(weak_cell2, isolate);
CHECK_EQ(finalization_group->active_cells(), *weak_cell1);
CHECK_EQ(finalization_registry->active_cells(), *weak_cell1);
CHECK(weak_cell1->prev().IsUndefined(isolate));
CHECK(weak_cell1->next().IsUndefined(isolate));
CHECK_EQ(finalization_group->cleared_cells(), *weak_cell2);
CHECK_EQ(finalization_registry->cleared_cells(), *weak_cell2);
CHECK(weak_cell2->prev().IsUndefined(isolate));
CHECK(weak_cell2->next().IsUndefined(isolate));
NullifyWeakCell(weak_cell1, isolate);
CHECK(finalization_group->active_cells().IsUndefined(isolate));
CHECK_EQ(finalization_group->cleared_cells(), *weak_cell1);
CHECK(finalization_registry->active_cells().IsUndefined(isolate));
CHECK_EQ(finalization_registry->cleared_cells(), *weak_cell1);
CHECK_EQ(weak_cell1->next(), *weak_cell2);
CHECK(weak_cell1->prev().IsUndefined(isolate));
CHECK_EQ(weak_cell2->prev(), *weak_cell1);
CHECK(weak_cell2->next().IsUndefined(isolate));
}
TEST(TestJSFinalizationGroupPopClearedCellHoldings1) {
TEST(TestJSFinalizationRegistryPopClearedCellHoldings1) {
FLAG_harmony_weak_refs = true;
CcTest::InitializeVM();
LocalContext context;
Isolate* isolate = CcTest::i_isolate();
Factory* factory = isolate->factory();
HandleScope outer_scope(isolate);
Handle<JSFinalizationGroup> finalization_group =
ConstructJSFinalizationGroup(isolate);
Handle<JSFinalizationRegistry> finalization_registry =
ConstructJSFinalizationRegistry(isolate);
Handle<JSObject> js_object =
isolate->factory()->NewJSObject(isolate->object_function());
Handle<Object> undefined =
handle(ReadOnlyRoots(isolate).undefined_value(), isolate);
Handle<Object> holdings1 = factory->NewStringFromAsciiChecked("holdings1");
Handle<WeakCell> weak_cell1 = FinalizationGroupRegister(
finalization_group, js_object, holdings1, undefined, isolate);
Handle<WeakCell> weak_cell1 = FinalizationRegistryRegister(
finalization_registry, js_object, holdings1, undefined, isolate);
Handle<Object> holdings2 = factory->NewStringFromAsciiChecked("holdings2");
Handle<WeakCell> weak_cell2 = FinalizationGroupRegister(
finalization_group, js_object, holdings2, undefined, isolate);
Handle<WeakCell> weak_cell2 = FinalizationRegistryRegister(
finalization_registry, js_object, holdings2, undefined, isolate);
Handle<Object> holdings3 = factory->NewStringFromAsciiChecked("holdings3");
Handle<WeakCell> weak_cell3 = FinalizationGroupRegister(
finalization_group, js_object, holdings3, undefined, isolate);
Handle<WeakCell> weak_cell3 = FinalizationRegistryRegister(
finalization_registry, js_object, holdings3, undefined, isolate);
NullifyWeakCell(weak_cell2, isolate);
NullifyWeakCell(weak_cell3, isolate);
CHECK(finalization_group->NeedsCleanup());
Object cleared1 =
JSFinalizationGroup::PopClearedCellHoldings(finalization_group, isolate);
CHECK(finalization_registry->NeedsCleanup());
Object cleared1 = JSFinalizationRegistry::PopClearedCellHoldings(
finalization_registry, isolate);
CHECK_EQ(cleared1, *holdings3);
CHECK(weak_cell3->prev().IsUndefined(isolate));
CHECK(weak_cell3->next().IsUndefined(isolate));
CHECK(finalization_group->NeedsCleanup());
Object cleared2 =
JSFinalizationGroup::PopClearedCellHoldings(finalization_group, isolate);
CHECK(finalization_registry->NeedsCleanup());
Object cleared2 = JSFinalizationRegistry::PopClearedCellHoldings(
finalization_registry, isolate);
CHECK_EQ(cleared2, *holdings2);
CHECK(weak_cell2->prev().IsUndefined(isolate));
CHECK(weak_cell2->next().IsUndefined(isolate));
CHECK(!finalization_group->NeedsCleanup());
CHECK(!finalization_registry->NeedsCleanup());
NullifyWeakCell(weak_cell1, isolate);
CHECK(finalization_group->NeedsCleanup());
Object cleared3 =
JSFinalizationGroup::PopClearedCellHoldings(finalization_group, isolate);
CHECK(finalization_registry->NeedsCleanup());
Object cleared3 = JSFinalizationRegistry::PopClearedCellHoldings(
finalization_registry, isolate);
CHECK_EQ(cleared3, *holdings1);
CHECK(weak_cell1->prev().IsUndefined(isolate));
CHECK(weak_cell1->next().IsUndefined(isolate));
CHECK(!finalization_group->NeedsCleanup());
CHECK(finalization_group->active_cells().IsUndefined(isolate));
CHECK(finalization_group->cleared_cells().IsUndefined(isolate));
CHECK(!finalization_registry->NeedsCleanup());
CHECK(finalization_registry->active_cells().IsUndefined(isolate));
CHECK(finalization_registry->cleared_cells().IsUndefined(isolate));
}
TEST(TestJSFinalizationGroupPopClearedCellHoldings2) {
TEST(TestJSFinalizationRegistryPopClearedCellHoldings2) {
// Test that when all WeakCells for a key are popped, the key is removed from
// the key map.
FLAG_harmony_weak_refs = true;
@ -397,18 +399,18 @@ TEST(TestJSFinalizationGroupPopClearedCellHoldings2) {
Isolate* isolate = CcTest::i_isolate();
Factory* factory = isolate->factory();
HandleScope outer_scope(isolate);
Handle<JSFinalizationGroup> finalization_group =
ConstructJSFinalizationGroup(isolate);
Handle<JSFinalizationRegistry> finalization_registry =
ConstructJSFinalizationRegistry(isolate);
Handle<JSObject> js_object =
isolate->factory()->NewJSObject(isolate->object_function());
Handle<JSObject> token1 = CreateKey("token1", isolate);
Handle<Object> holdings1 = factory->NewStringFromAsciiChecked("holdings1");
Handle<WeakCell> weak_cell1 = FinalizationGroupRegister(
finalization_group, js_object, holdings1, token1, isolate);
Handle<WeakCell> weak_cell1 = FinalizationRegistryRegister(
finalization_registry, js_object, holdings1, token1, isolate);
Handle<Object> holdings2 = factory->NewStringFromAsciiChecked("holdings2");
Handle<WeakCell> weak_cell2 = FinalizationGroupRegister(
finalization_group, js_object, holdings2, token1, isolate);
Handle<WeakCell> weak_cell2 = FinalizationRegistryRegister(
finalization_registry, js_object, holdings2, token1, isolate);
NullifyWeakCell(weak_cell1, isolate);
NullifyWeakCell(weak_cell2, isolate);
@ -417,28 +419,28 @@ TEST(TestJSFinalizationGroupPopClearedCellHoldings2) {
// active_cells to cleared_cells).
{
SimpleNumberDictionary key_map =
SimpleNumberDictionary::cast(finalization_group->key_map());
SimpleNumberDictionary::cast(finalization_registry->key_map());
VerifyWeakCellKeyChain(isolate, key_map, *token1, 2, *weak_cell2,
*weak_cell1);
}
Object cleared1 =
JSFinalizationGroup::PopClearedCellHoldings(finalization_group, isolate);
Object cleared1 = JSFinalizationRegistry::PopClearedCellHoldings(
finalization_registry, isolate);
CHECK_EQ(cleared1, *holdings2);
{
SimpleNumberDictionary key_map =
SimpleNumberDictionary::cast(finalization_group->key_map());
SimpleNumberDictionary::cast(finalization_registry->key_map());
VerifyWeakCellKeyChain(isolate, key_map, *token1, 1, *weak_cell1);
}
Object cleared2 =
JSFinalizationGroup::PopClearedCellHoldings(finalization_group, isolate);
Object cleared2 = JSFinalizationRegistry::PopClearedCellHoldings(
finalization_registry, isolate);
CHECK_EQ(cleared2, *holdings1);
{
SimpleNumberDictionary key_map =
SimpleNumberDictionary::cast(finalization_group->key_map());
SimpleNumberDictionary::cast(finalization_registry->key_map());
VerifyWeakCellKeyChain(isolate, key_map, *token1, 0);
}
}
@ -449,8 +451,8 @@ TEST(TestUnregisterActiveCells) {
LocalContext context;
Isolate* isolate = CcTest::i_isolate();
HandleScope outer_scope(isolate);
Handle<JSFinalizationGroup> finalization_group =
ConstructJSFinalizationGroup(isolate);
Handle<JSFinalizationRegistry> finalization_registry =
ConstructJSFinalizationRegistry(isolate);
Handle<JSObject> js_object =
isolate->factory()->NewJSObject(isolate->object_function());
@ -459,41 +461,41 @@ TEST(TestUnregisterActiveCells) {
Handle<Object> undefined =
handle(ReadOnlyRoots(isolate).undefined_value(), isolate);
Handle<WeakCell> weak_cell1a = FinalizationGroupRegister(
finalization_group, js_object, undefined, token1, isolate);
Handle<WeakCell> weak_cell1b = FinalizationGroupRegister(
finalization_group, js_object, undefined, token1, isolate);
Handle<WeakCell> weak_cell1a = FinalizationRegistryRegister(
finalization_registry, js_object, undefined, token1, isolate);
Handle<WeakCell> weak_cell1b = FinalizationRegistryRegister(
finalization_registry, js_object, undefined, token1, isolate);
Handle<WeakCell> weak_cell2a = FinalizationGroupRegister(
finalization_group, js_object, undefined, token2, isolate);
Handle<WeakCell> weak_cell2b = FinalizationGroupRegister(
finalization_group, js_object, undefined, token2, isolate);
Handle<WeakCell> weak_cell2a = FinalizationRegistryRegister(
finalization_registry, js_object, undefined, token2, isolate);
Handle<WeakCell> weak_cell2b = FinalizationRegistryRegister(
finalization_registry, js_object, undefined, token2, isolate);
VerifyWeakCellChain(isolate, finalization_group->active_cells(), 4,
VerifyWeakCellChain(isolate, finalization_registry->active_cells(), 4,
*weak_cell2b, *weak_cell2a, *weak_cell1b, *weak_cell1a);
VerifyWeakCellChain(isolate, finalization_group->cleared_cells(), 0);
VerifyWeakCellChain(isolate, finalization_registry->cleared_cells(), 0);
{
SimpleNumberDictionary key_map =
SimpleNumberDictionary::cast(finalization_group->key_map());
SimpleNumberDictionary::cast(finalization_registry->key_map());
VerifyWeakCellKeyChain(isolate, key_map, *token1, 2, *weak_cell1b,
*weak_cell1a);
VerifyWeakCellKeyChain(isolate, key_map, *token2, 2, *weak_cell2b,
*weak_cell2a);
}
JSFinalizationGroup::Unregister(finalization_group, token1, isolate);
JSFinalizationRegistry::Unregister(finalization_registry, token1, isolate);
{
SimpleNumberDictionary key_map =
SimpleNumberDictionary::cast(finalization_group->key_map());
SimpleNumberDictionary::cast(finalization_registry->key_map());
VerifyWeakCellKeyChain(isolate, key_map, *token1, 0);
VerifyWeakCellKeyChain(isolate, key_map, *token2, 2, *weak_cell2b,
*weak_cell2a);
}
// Both weak_cell1a and weak_cell1b removed from active_cells.
VerifyWeakCellChain(isolate, finalization_group->active_cells(), 2,
VerifyWeakCellChain(isolate, finalization_registry->active_cells(), 2,
*weak_cell2b, *weak_cell2a);
VerifyWeakCellChain(isolate, finalization_group->cleared_cells(), 0);
VerifyWeakCellChain(isolate, finalization_registry->cleared_cells(), 0);
}
TEST(TestUnregisterActiveAndClearedCells) {
@ -502,8 +504,8 @@ TEST(TestUnregisterActiveAndClearedCells) {
LocalContext context;
Isolate* isolate = CcTest::i_isolate();
HandleScope outer_scope(isolate);
Handle<JSFinalizationGroup> finalization_group =
ConstructJSFinalizationGroup(isolate);
Handle<JSFinalizationRegistry> finalization_registry =
ConstructJSFinalizationRegistry(isolate);
Handle<JSObject> js_object =
isolate->factory()->NewJSObject(isolate->object_function());
@ -512,40 +514,40 @@ TEST(TestUnregisterActiveAndClearedCells) {
Handle<Object> undefined =
handle(ReadOnlyRoots(isolate).undefined_value(), isolate);
Handle<WeakCell> weak_cell1a = FinalizationGroupRegister(
finalization_group, js_object, undefined, token1, isolate);
Handle<WeakCell> weak_cell1b = FinalizationGroupRegister(
finalization_group, js_object, undefined, token1, isolate);
Handle<WeakCell> weak_cell1a = FinalizationRegistryRegister(
finalization_registry, js_object, undefined, token1, isolate);
Handle<WeakCell> weak_cell1b = FinalizationRegistryRegister(
finalization_registry, js_object, undefined, token1, isolate);
Handle<WeakCell> weak_cell2a = FinalizationGroupRegister(
finalization_group, js_object, undefined, token2, isolate);
Handle<WeakCell> weak_cell2b = FinalizationGroupRegister(
finalization_group, js_object, undefined, token2, isolate);
Handle<WeakCell> weak_cell2a = FinalizationRegistryRegister(
finalization_registry, js_object, undefined, token2, isolate);
Handle<WeakCell> weak_cell2b = FinalizationRegistryRegister(
finalization_registry, js_object, undefined, token2, isolate);
NullifyWeakCell(weak_cell2a, isolate);
VerifyWeakCellChain(isolate, finalization_group->active_cells(), 3,
VerifyWeakCellChain(isolate, finalization_registry->active_cells(), 3,
*weak_cell2b, *weak_cell1b, *weak_cell1a);
VerifyWeakCellChain(isolate, finalization_group->cleared_cells(), 1,
VerifyWeakCellChain(isolate, finalization_registry->cleared_cells(), 1,
*weak_cell2a);
{
SimpleNumberDictionary key_map =
SimpleNumberDictionary::cast(finalization_group->key_map());
SimpleNumberDictionary::cast(finalization_registry->key_map());
VerifyWeakCellKeyChain(isolate, key_map, *token1, 2, *weak_cell1b,
*weak_cell1a);
VerifyWeakCellKeyChain(isolate, key_map, *token2, 2, *weak_cell2b,
*weak_cell2a);
}
JSFinalizationGroup::Unregister(finalization_group, token2, isolate);
JSFinalizationRegistry::Unregister(finalization_registry, token2, isolate);
// Both weak_cell2a and weak_cell2b removed.
VerifyWeakCellChain(isolate, finalization_group->active_cells(), 2,
VerifyWeakCellChain(isolate, finalization_registry->active_cells(), 2,
*weak_cell1b, *weak_cell1a);
VerifyWeakCellChain(isolate, finalization_group->cleared_cells(), 0);
VerifyWeakCellChain(isolate, finalization_registry->cleared_cells(), 0);
{
SimpleNumberDictionary key_map =
SimpleNumberDictionary::cast(finalization_group->key_map());
SimpleNumberDictionary::cast(finalization_registry->key_map());
VerifyWeakCellKeyChain(isolate, key_map, *token1, 2, *weak_cell1b,
*weak_cell1a);
VerifyWeakCellKeyChain(isolate, key_map, *token2, 0);
@ -558,8 +560,8 @@ TEST(TestWeakCellUnregisterTwice) {
LocalContext context;
Isolate* isolate = CcTest::i_isolate();
HandleScope outer_scope(isolate);
Handle<JSFinalizationGroup> finalization_group =
ConstructJSFinalizationGroup(isolate);
Handle<JSFinalizationRegistry> finalization_registry =
ConstructJSFinalizationRegistry(isolate);
Handle<JSObject> js_object =
isolate->factory()->NewJSObject(isolate->object_function());
@ -567,35 +569,35 @@ TEST(TestWeakCellUnregisterTwice) {
Handle<Object> undefined =
handle(ReadOnlyRoots(isolate).undefined_value(), isolate);
Handle<WeakCell> weak_cell1 = FinalizationGroupRegister(
finalization_group, js_object, undefined, token1, isolate);
Handle<WeakCell> weak_cell1 = FinalizationRegistryRegister(
finalization_registry, js_object, undefined, token1, isolate);
VerifyWeakCellChain(isolate, finalization_group->active_cells(), 1,
VerifyWeakCellChain(isolate, finalization_registry->active_cells(), 1,
*weak_cell1);
VerifyWeakCellChain(isolate, finalization_group->cleared_cells(), 0);
VerifyWeakCellChain(isolate, finalization_registry->cleared_cells(), 0);
{
SimpleNumberDictionary key_map =
SimpleNumberDictionary::cast(finalization_group->key_map());
SimpleNumberDictionary::cast(finalization_registry->key_map());
VerifyWeakCellKeyChain(isolate, key_map, *token1, 1, *weak_cell1);
}
JSFinalizationGroup::Unregister(finalization_group, token1, isolate);
JSFinalizationRegistry::Unregister(finalization_registry, token1, isolate);
VerifyWeakCellChain(isolate, finalization_group->active_cells(), 0);
VerifyWeakCellChain(isolate, finalization_group->cleared_cells(), 0);
VerifyWeakCellChain(isolate, finalization_registry->active_cells(), 0);
VerifyWeakCellChain(isolate, finalization_registry->cleared_cells(), 0);
{
SimpleNumberDictionary key_map =
SimpleNumberDictionary::cast(finalization_group->key_map());
SimpleNumberDictionary::cast(finalization_registry->key_map());
VerifyWeakCellKeyChain(isolate, key_map, *token1, 0);
}
JSFinalizationGroup::Unregister(finalization_group, token1, isolate);
JSFinalizationRegistry::Unregister(finalization_registry, token1, isolate);
VerifyWeakCellChain(isolate, finalization_group->active_cells(), 0);
VerifyWeakCellChain(isolate, finalization_group->cleared_cells(), 0);
VerifyWeakCellChain(isolate, finalization_registry->active_cells(), 0);
VerifyWeakCellChain(isolate, finalization_registry->cleared_cells(), 0);
{
SimpleNumberDictionary key_map =
SimpleNumberDictionary::cast(finalization_group->key_map());
SimpleNumberDictionary::cast(finalization_registry->key_map());
VerifyWeakCellKeyChain(isolate, key_map, *token1, 0);
}
}
@ -607,37 +609,37 @@ TEST(TestWeakCellUnregisterPopped) {
Isolate* isolate = CcTest::i_isolate();
Factory* factory = isolate->factory();
HandleScope outer_scope(isolate);
Handle<JSFinalizationGroup> finalization_group =
ConstructJSFinalizationGroup(isolate);
Handle<JSFinalizationRegistry> finalization_registry =
ConstructJSFinalizationRegistry(isolate);
Handle<JSObject> js_object =
isolate->factory()->NewJSObject(isolate->object_function());
Handle<JSObject> token1 = CreateKey("token1", isolate);
Handle<Object> holdings1 = factory->NewStringFromAsciiChecked("holdings1");
Handle<WeakCell> weak_cell1 = FinalizationGroupRegister(
finalization_group, js_object, holdings1, token1, isolate);
Handle<WeakCell> weak_cell1 = FinalizationRegistryRegister(
finalization_registry, js_object, holdings1, token1, isolate);
NullifyWeakCell(weak_cell1, isolate);
CHECK(finalization_group->NeedsCleanup());
Object cleared1 =
JSFinalizationGroup::PopClearedCellHoldings(finalization_group, isolate);
CHECK(finalization_registry->NeedsCleanup());
Object cleared1 = JSFinalizationRegistry::PopClearedCellHoldings(
finalization_registry, isolate);
CHECK_EQ(cleared1, *holdings1);
VerifyWeakCellChain(isolate, finalization_group->active_cells(), 0);
VerifyWeakCellChain(isolate, finalization_group->cleared_cells(), 0);
VerifyWeakCellChain(isolate, finalization_registry->active_cells(), 0);
VerifyWeakCellChain(isolate, finalization_registry->cleared_cells(), 0);
{
SimpleNumberDictionary key_map =
SimpleNumberDictionary::cast(finalization_group->key_map());
SimpleNumberDictionary::cast(finalization_registry->key_map());
VerifyWeakCellKeyChain(isolate, key_map, *token1, 0);
}
JSFinalizationGroup::Unregister(finalization_group, token1, isolate);
JSFinalizationRegistry::Unregister(finalization_registry, token1, isolate);
VerifyWeakCellChain(isolate, finalization_group->active_cells(), 0);
VerifyWeakCellChain(isolate, finalization_group->cleared_cells(), 0);
VerifyWeakCellChain(isolate, finalization_registry->active_cells(), 0);
VerifyWeakCellChain(isolate, finalization_registry->cleared_cells(), 0);
{
SimpleNumberDictionary key_map =
SimpleNumberDictionary::cast(finalization_group->key_map());
SimpleNumberDictionary::cast(finalization_registry->key_map());
VerifyWeakCellKeyChain(isolate, key_map, *token1, 0);
}
}
@ -648,11 +650,11 @@ TEST(TestWeakCellUnregisterNonexistentKey) {
LocalContext context;
Isolate* isolate = CcTest::i_isolate();
HandleScope outer_scope(isolate);
Handle<JSFinalizationGroup> finalization_group =
ConstructJSFinalizationGroup(isolate);
Handle<JSFinalizationRegistry> finalization_registry =
ConstructJSFinalizationRegistry(isolate);
Handle<JSObject> token1 = CreateKey("token1", isolate);
JSFinalizationGroup::Unregister(finalization_group, token1, isolate);
JSFinalizationRegistry::Unregister(finalization_registry, token1, isolate);
}
TEST(TestJSWeakRef) {
@ -793,8 +795,8 @@ TEST(TestRemoveUnregisterToken) {
LocalContext context;
Isolate* isolate = CcTest::i_isolate();
HandleScope outer_scope(isolate);
Handle<JSFinalizationGroup> finalization_group =
ConstructJSFinalizationGroup(isolate);
Handle<JSFinalizationRegistry> finalization_registry =
ConstructJSFinalizationRegistry(isolate);
Handle<JSObject> js_object =
isolate->factory()->NewJSObject(isolate->object_function());
@ -803,32 +805,32 @@ TEST(TestRemoveUnregisterToken) {
Handle<Object> undefined =
handle(ReadOnlyRoots(isolate).undefined_value(), isolate);
Handle<WeakCell> weak_cell1a = FinalizationGroupRegister(
finalization_group, js_object, undefined, token1, isolate);
Handle<WeakCell> weak_cell1b = FinalizationGroupRegister(
finalization_group, js_object, undefined, token1, isolate);
Handle<WeakCell> weak_cell1a = FinalizationRegistryRegister(
finalization_registry, js_object, undefined, token1, isolate);
Handle<WeakCell> weak_cell1b = FinalizationRegistryRegister(
finalization_registry, js_object, undefined, token1, isolate);
Handle<WeakCell> weak_cell2a = FinalizationGroupRegister(
finalization_group, js_object, undefined, token2, isolate);
Handle<WeakCell> weak_cell2b = FinalizationGroupRegister(
finalization_group, js_object, undefined, token2, isolate);
Handle<WeakCell> weak_cell2a = FinalizationRegistryRegister(
finalization_registry, js_object, undefined, token2, isolate);
Handle<WeakCell> weak_cell2b = FinalizationRegistryRegister(
finalization_registry, js_object, undefined, token2, isolate);
NullifyWeakCell(weak_cell2a, isolate);
VerifyWeakCellChain(isolate, finalization_group->active_cells(), 3,
VerifyWeakCellChain(isolate, finalization_registry->active_cells(), 3,
*weak_cell2b, *weak_cell1b, *weak_cell1a);
VerifyWeakCellChain(isolate, finalization_group->cleared_cells(), 1,
VerifyWeakCellChain(isolate, finalization_registry->cleared_cells(), 1,
*weak_cell2a);
{
SimpleNumberDictionary key_map =
SimpleNumberDictionary::cast(finalization_group->key_map());
SimpleNumberDictionary::cast(finalization_registry->key_map());
VerifyWeakCellKeyChain(isolate, key_map, *token1, 2, *weak_cell1b,
*weak_cell1a);
VerifyWeakCellKeyChain(isolate, key_map, *token2, 2, *weak_cell2b,
*weak_cell2a);
}
finalization_group->RemoveUnregisterToken(
finalization_registry->RemoveUnregisterToken(
JSReceiver::cast(*token2), isolate,
[undefined](WeakCell matched_cell) {
matched_cell.set_unregister_token(*undefined);
@ -836,15 +838,15 @@ TEST(TestRemoveUnregisterToken) {
[](HeapObject, ObjectSlot, Object) {});
// Both weak_cell2a and weak_cell2b remain on the weak cell chains.
VerifyWeakCellChain(isolate, finalization_group->active_cells(), 3,
VerifyWeakCellChain(isolate, finalization_registry->active_cells(), 3,
*weak_cell2b, *weak_cell1b, *weak_cell1a);
VerifyWeakCellChain(isolate, finalization_group->cleared_cells(), 1,
VerifyWeakCellChain(isolate, finalization_registry->cleared_cells(), 1,
*weak_cell2a);
// But both weak_cell2a and weak_cell2b are removed from the key chain.
{
SimpleNumberDictionary key_map =
SimpleNumberDictionary::cast(finalization_group->key_map());
SimpleNumberDictionary::cast(finalization_registry->key_map());
VerifyWeakCellKeyChain(isolate, key_map, *token1, 2, *weak_cell1b,
*weak_cell1a);
VerifyWeakCellKeyChain(isolate, key_map, *token2, 0);

View File

@ -30,10 +30,10 @@ void RunStdFunction(void* data) {
}
template <typename TMixin>
class WithFinalizationGroupMixin : public TMixin {
class WithFinalizationRegistryMixin : public TMixin {
public:
WithFinalizationGroupMixin() = default;
~WithFinalizationGroupMixin() override = default;
WithFinalizationRegistryMixin() = default;
~WithFinalizationRegistryMixin() override = default;
static void SetUpTestCase() {
CHECK_NULL(save_flags_);
@ -54,21 +54,21 @@ class WithFinalizationGroupMixin : public TMixin {
private:
static SaveFlags* save_flags_;
DISALLOW_COPY_AND_ASSIGN(WithFinalizationGroupMixin);
DISALLOW_COPY_AND_ASSIGN(WithFinalizationRegistryMixin);
};
template <typename TMixin>
SaveFlags* WithFinalizationGroupMixin<TMixin>::save_flags_ = nullptr;
SaveFlags* WithFinalizationRegistryMixin<TMixin>::save_flags_ = nullptr;
using TestWithNativeContextAndFinalizationGroup = //
WithInternalIsolateMixin< //
WithContextMixin< //
WithFinalizationGroupMixin< //
WithIsolateScopeMixin< //
WithSharedIsolateMixin< //
using TestWithNativeContextAndFinalizationRegistry = //
WithInternalIsolateMixin< //
WithContextMixin< //
WithFinalizationRegistryMixin< //
WithIsolateScopeMixin< //
WithSharedIsolateMixin< //
::testing::Test>>>>>;
class MicrotaskQueueTest : public TestWithNativeContextAndFinalizationGroup {
class MicrotaskQueueTest : public TestWithNativeContextAndFinalizationRegistry {
public:
template <typename F>
Handle<Microtask> NewMicrotask(F&& f) {

View File

@ -166,8 +166,8 @@ INSTANCE_TYPES = {
1066: "JS_DATE_TIME_FORMAT_TYPE",
1067: "JS_DISPLAY_NAMES_TYPE",
1068: "JS_ERROR_TYPE",
1069: "JS_FINALIZATION_GROUP_TYPE",
1070: "JS_FINALIZATION_GROUP_CLEANUP_ITERATOR_TYPE",
1069: "JS_FINALIZATION_REGISTRY_TYPE",
1070: "JS_FINALIZATION_REGISTRY_CLEANUP_ITERATOR_TYPE",
1071: "JS_LIST_FORMAT_TYPE",
1072: "JS_LOCALE_TYPE",
1073: "JS_MESSAGE_OBJECT_TYPE",