LibGC: Only call finalize() on types that override finalize()
This dramatically cuts down on time spent in the GC's finalizer pass, since most types don't override finalize().
This commit is contained in:
parent
75ad452099
commit
2ac363dcba
44 changed files with 105 additions and 22 deletions
|
|
@ -43,6 +43,7 @@ class GC_API Cell {
|
|||
|
||||
public:
|
||||
static constexpr bool OVERRIDES_MUST_SURVIVE_GARBAGE_COLLECTION = false;
|
||||
static constexpr bool OVERRIDES_FINALIZE = false;
|
||||
|
||||
virtual ~Cell() = default;
|
||||
|
||||
|
|
|
|||
|
|
@ -12,10 +12,11 @@
|
|||
|
||||
namespace GC {
|
||||
|
||||
CellAllocator::CellAllocator(size_t cell_size, StringView class_name, bool overrides_must_survive_garbage_collection)
|
||||
CellAllocator::CellAllocator(size_t cell_size, StringView class_name, bool overrides_must_survive_garbage_collection, bool overrides_finalize)
|
||||
: m_class_name(class_name)
|
||||
, m_cell_size(cell_size)
|
||||
, m_overrides_must_survive_garbage_collection(overrides_must_survive_garbage_collection)
|
||||
, m_overrides_finalize(overrides_finalize)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
@ -25,7 +26,7 @@ Cell* CellAllocator::allocate_cell(Heap& heap)
|
|||
heap.register_cell_allocator({}, *this);
|
||||
|
||||
if (m_usable_blocks.is_empty()) {
|
||||
auto block = HeapBlock::create_with_cell_size(heap, *this, m_cell_size, m_class_name, m_overrides_must_survive_garbage_collection);
|
||||
auto block = HeapBlock::create_with_cell_size(heap, *this, m_cell_size, m_class_name, m_overrides_must_survive_garbage_collection, m_overrides_finalize);
|
||||
auto block_ptr = reinterpret_cast<FlatPtr>(block.ptr());
|
||||
if (m_min_block_address > block_ptr)
|
||||
m_min_block_address = block_ptr;
|
||||
|
|
|
|||
|
|
@ -17,13 +17,13 @@
|
|||
static GC::TypeIsolatingCellAllocator<ClassName> cell_allocator
|
||||
|
||||
#define GC_DEFINE_ALLOCATOR(ClassName) \
|
||||
GC::TypeIsolatingCellAllocator<ClassName> ClassName::cell_allocator { #ClassName##sv, ClassName::OVERRIDES_MUST_SURVIVE_GARBAGE_COLLECTION }
|
||||
GC::TypeIsolatingCellAllocator<ClassName> ClassName::cell_allocator { #ClassName##sv, ClassName::OVERRIDES_MUST_SURVIVE_GARBAGE_COLLECTION, ClassName::OVERRIDES_FINALIZE }
|
||||
|
||||
namespace GC {
|
||||
|
||||
class GC_API CellAllocator {
|
||||
public:
|
||||
CellAllocator(size_t cell_size, StringView = {}, bool overrides_must_survive_garbage_collection = false);
|
||||
CellAllocator(size_t cell_size, StringView = {}, bool overrides_must_survive_garbage_collection = false, bool overrides_finalize = false);
|
||||
~CellAllocator() = default;
|
||||
|
||||
StringView class_name() const { return m_class_name; }
|
||||
|
|
@ -67,6 +67,7 @@ private:
|
|||
FlatPtr m_min_block_address { explode_byte(0xff) };
|
||||
FlatPtr m_max_block_address { 0 };
|
||||
bool m_overrides_must_survive_garbage_collection { false };
|
||||
bool m_overrides_finalize { false };
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
|
|
@ -74,8 +75,8 @@ class GC_API TypeIsolatingCellAllocator {
|
|||
public:
|
||||
using CellType = T;
|
||||
|
||||
TypeIsolatingCellAllocator(StringView class_name, bool overrides_must_survive_garbage_collection)
|
||||
: allocator(sizeof(T), class_name, overrides_must_survive_garbage_collection)
|
||||
TypeIsolatingCellAllocator(StringView class_name, bool overrides_must_survive_garbage_collection, bool overrides_finalize)
|
||||
: allocator(sizeof(T), class_name, overrides_must_survive_garbage_collection, overrides_finalize)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -28,6 +28,8 @@ class GC_API ForeignCell : public Cell {
|
|||
FOREIGN_CELL(ForeignCell, Cell);
|
||||
|
||||
public:
|
||||
static constexpr bool OVERRIDES_FINALIZE = true;
|
||||
|
||||
struct Vtable {
|
||||
// Holds a pointer to the foreign vtable information such as
|
||||
// a jclass in Java, or a Swift type metadata pointer
|
||||
|
|
|
|||
|
|
@ -372,6 +372,15 @@ void Heap::gather_roots(HashMap<Cell*, HeapRoot>& roots, HashTable<HeapBlock*>&
|
|||
{
|
||||
for_each_block([&](auto& block) {
|
||||
all_live_heap_blocks.set(&block);
|
||||
|
||||
if (block.overrides_must_survive_garbage_collection()) {
|
||||
block.template for_each_cell_in_state<Cell::State::Live>([&](Cell* cell) {
|
||||
if (cell->must_survive_garbage_collection()) {
|
||||
roots.set(cell, HeapRoot { .type = HeapRoot::Type::MustSurviveGC });
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return IterationDecision::Continue;
|
||||
});
|
||||
|
||||
|
|
@ -387,17 +396,6 @@ void Heap::gather_roots(HashMap<Cell*, HeapRoot>& roots, HashTable<HeapBlock*>&
|
|||
for (auto& hash_map : m_root_hash_maps)
|
||||
hash_map.gather_roots(roots);
|
||||
|
||||
for_each_block([&](HeapBlock& block) {
|
||||
if (!block.overrides_must_survive_garbage_collection())
|
||||
return IterationDecision::Continue;
|
||||
block.template for_each_cell_in_state<Cell::State::Live>([&](Cell* cell) {
|
||||
if (cell->must_survive_garbage_collection()) {
|
||||
roots.set(cell, HeapRoot { .type = HeapRoot::Type::MustSurviveGC });
|
||||
}
|
||||
});
|
||||
return IterationDecision::Continue;
|
||||
});
|
||||
|
||||
if constexpr (HEAP_DEBUG) {
|
||||
dbgln("gather_roots:");
|
||||
for (auto* root : roots.keys())
|
||||
|
|
@ -541,6 +539,8 @@ void Heap::mark_live_cells(HashMap<Cell*, HeapRoot> const& roots, HashTable<Heap
|
|||
void Heap::finalize_unmarked_cells()
|
||||
{
|
||||
for_each_block([&](auto& block) {
|
||||
if (!block.overrides_finalize())
|
||||
return IterationDecision::Continue;
|
||||
block.template for_each_cell_in_state<Cell::State::Live>([](Cell* cell) {
|
||||
if (!cell->is_marked())
|
||||
cell->finalize();
|
||||
|
|
|
|||
|
|
@ -18,19 +18,20 @@
|
|||
|
||||
namespace GC {
|
||||
|
||||
NonnullOwnPtr<HeapBlock> HeapBlock::create_with_cell_size(Heap& heap, CellAllocator& cell_allocator, size_t cell_size, [[maybe_unused]] StringView class_name, bool overrides_must_survive_garbage_collection)
|
||||
NonnullOwnPtr<HeapBlock> HeapBlock::create_with_cell_size(Heap& heap, CellAllocator& cell_allocator, size_t cell_size, [[maybe_unused]] StringView class_name, bool overrides_must_survive_garbage_collection, bool overrides_finalize)
|
||||
{
|
||||
char const* name = nullptr;
|
||||
auto* block = static_cast<HeapBlock*>(cell_allocator.block_allocator().allocate_block(name));
|
||||
new (block) HeapBlock(heap, cell_allocator, cell_size, overrides_must_survive_garbage_collection);
|
||||
new (block) HeapBlock(heap, cell_allocator, cell_size, overrides_must_survive_garbage_collection, overrides_finalize);
|
||||
return NonnullOwnPtr<HeapBlock>(NonnullOwnPtr<HeapBlock>::Adopt, *block);
|
||||
}
|
||||
|
||||
HeapBlock::HeapBlock(Heap& heap, CellAllocator& cell_allocator, size_t cell_size, bool overrides_must_survive_garbage_collection)
|
||||
HeapBlock::HeapBlock(Heap& heap, CellAllocator& cell_allocator, size_t cell_size, bool overrides_must_survive_garbage_collection, bool overrides_finalize)
|
||||
: HeapBlockBase(heap)
|
||||
, m_cell_allocator(cell_allocator)
|
||||
, m_cell_size(cell_size)
|
||||
, m_overrides_must_survive_garbage_collection(overrides_must_survive_garbage_collection)
|
||||
, m_overrides_finalize(overrides_finalize)
|
||||
{
|
||||
VERIFY(cell_size >= sizeof(FreelistEntry));
|
||||
ASAN_POISON_MEMORY_REGION(m_storage, BLOCK_SIZE - sizeof(HeapBlock));
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ class GC_API HeapBlock : public HeapBlockBase {
|
|||
|
||||
public:
|
||||
using HeapBlockBase::BLOCK_SIZE;
|
||||
static NonnullOwnPtr<HeapBlock> create_with_cell_size(Heap&, CellAllocator&, size_t cell_size, StringView class_name, bool overrides_must_survive_garbage_collection);
|
||||
static NonnullOwnPtr<HeapBlock> create_with_cell_size(Heap&, CellAllocator&, size_t cell_size, StringView class_name, bool overrides_must_survive_garbage_collection, bool overrides_finalize);
|
||||
|
||||
size_t cell_size() const { return m_cell_size; }
|
||||
size_t cell_count() const { return (HeapBlock::BLOCK_SIZE - sizeof(HeapBlock)) / m_cell_size; }
|
||||
|
|
@ -93,9 +93,10 @@ public:
|
|||
CellAllocator& cell_allocator() { return m_cell_allocator; }
|
||||
|
||||
bool overrides_must_survive_garbage_collection() const { return m_overrides_must_survive_garbage_collection; }
|
||||
bool overrides_finalize() const { return m_overrides_finalize; }
|
||||
|
||||
private:
|
||||
HeapBlock(Heap&, CellAllocator&, size_t cell_size, bool overrides_must_survive_garbage_collection);
|
||||
HeapBlock(Heap&, CellAllocator&, size_t cell_size, bool overrides_must_survive_garbage_collection, bool overrides_finalize);
|
||||
|
||||
bool has_lazy_freelist() const { return m_next_lazy_freelist_index < cell_count(); }
|
||||
|
||||
|
|
@ -115,6 +116,7 @@ private:
|
|||
u32 m_next_lazy_freelist_index { 0 };
|
||||
|
||||
bool m_overrides_must_survive_garbage_collection { false };
|
||||
bool m_overrides_finalize { false };
|
||||
|
||||
Ptr<FreelistEntry> m_freelist;
|
||||
alignas(__BIGGEST_ALIGNMENT__) u8 m_storage[];
|
||||
|
|
|
|||
|
|
@ -29,6 +29,8 @@ class Animation : public DOM::EventTarget {
|
|||
GC_DECLARE_ALLOCATOR(Animation);
|
||||
|
||||
public:
|
||||
static constexpr bool OVERRIDES_FINALIZE = true;
|
||||
|
||||
static GC::Ref<Animation> create(JS::Realm&, GC::Ptr<AnimationEffect>, Optional<GC::Ptr<AnimationTimeline>>);
|
||||
static WebIDL::ExceptionOr<GC::Ref<Animation>> construct_impl(JS::Realm&, GC::Ptr<AnimationEffect>, Optional<GC::Ptr<AnimationTimeline>>);
|
||||
|
||||
|
|
|
|||
|
|
@ -18,6 +18,8 @@ class AnimationTimeline : public Bindings::PlatformObject {
|
|||
GC_DECLARE_ALLOCATOR(AnimationTimeline);
|
||||
|
||||
public:
|
||||
static constexpr bool OVERRIDES_FINALIZE = true;
|
||||
|
||||
NullableCSSNumberish current_time_for_bindings() const
|
||||
{
|
||||
return NullableCSSNumberish::from_optional_css_numberish_time(current_time());
|
||||
|
|
|
|||
|
|
@ -181,6 +181,8 @@ class WEB_API Document
|
|||
GC_DECLARE_ALLOCATOR(Document);
|
||||
|
||||
public:
|
||||
static constexpr bool OVERRIDES_FINALIZE = true;
|
||||
|
||||
enum class Type {
|
||||
XML,
|
||||
HTML
|
||||
|
|
|
|||
|
|
@ -21,6 +21,8 @@ class WEB_API DocumentObserver final : public Bindings::PlatformObject {
|
|||
GC_DECLARE_ALLOCATOR(DocumentObserver);
|
||||
|
||||
public:
|
||||
static constexpr bool OVERRIDES_FINALIZE = true;
|
||||
|
||||
[[nodiscard]] GC::Ptr<GC::Function<void()>> document_became_active() const { return m_document_became_active; }
|
||||
void set_document_became_active(Function<void()>);
|
||||
|
||||
|
|
|
|||
|
|
@ -148,6 +148,8 @@ class WEB_API Node : public EventTarget
|
|||
WEB_PLATFORM_OBJECT(Node, EventTarget);
|
||||
|
||||
public:
|
||||
static constexpr bool OVERRIDES_FINALIZE = true;
|
||||
|
||||
ParentNode* parent_or_shadow_host();
|
||||
ParentNode const* parent_or_shadow_host() const { return const_cast<Node*>(this)->parent_or_shadow_host(); }
|
||||
|
||||
|
|
|
|||
|
|
@ -17,6 +17,8 @@ class NodeIterator final : public Bindings::PlatformObject {
|
|||
GC_DECLARE_ALLOCATOR(NodeIterator);
|
||||
|
||||
public:
|
||||
static constexpr bool OVERRIDES_FINALIZE = true;
|
||||
|
||||
static GC::Ref<NodeIterator> create(JS::Realm& realm, Node& root, unsigned what_to_show, GC::Ptr<NodeFilter>);
|
||||
|
||||
virtual ~NodeIterator() override;
|
||||
|
|
|
|||
|
|
@ -20,6 +20,8 @@ class WEB_API ShadowRoot final : public DocumentFragment {
|
|||
GC_DECLARE_ALLOCATOR(ShadowRoot);
|
||||
|
||||
public:
|
||||
static constexpr bool OVERRIDES_FINALIZE = true;
|
||||
|
||||
Bindings::ShadowRootMode mode() const { return m_mode; }
|
||||
|
||||
Bindings::SlotAssignmentMode slot_assignment() const { return m_slot_assignment; }
|
||||
|
|
|
|||
|
|
@ -17,6 +17,8 @@ class WEB_API FetchRecord final : public JS::Cell {
|
|||
GC_DECLARE_ALLOCATOR(FetchRecord);
|
||||
|
||||
public:
|
||||
static constexpr bool OVERRIDES_FINALIZE = true;
|
||||
|
||||
[[nodiscard]] static GC::Ref<FetchRecord> create(JS::VM&, GC::Ref<Infrastructure::Request>);
|
||||
[[nodiscard]] static GC::Ref<FetchRecord> create(JS::VM&, GC::Ref<Infrastructure::Request>, GC::Ptr<FetchController>);
|
||||
|
||||
|
|
|
|||
|
|
@ -20,6 +20,8 @@ class Gamepad final : public Bindings::PlatformObject {
|
|||
GC_DECLARE_ALLOCATOR(Gamepad);
|
||||
|
||||
public:
|
||||
static constexpr bool OVERRIDES_FINALIZE = true;
|
||||
|
||||
static GC::Ref<Gamepad> create(JS::Realm&, SDL_JoystickID);
|
||||
|
||||
SDL_JoystickID sdl_joystick_id() const { return m_sdl_joystick_id; }
|
||||
|
|
|
|||
|
|
@ -16,6 +16,8 @@ class BroadcastChannel final : public DOM::EventTarget {
|
|||
GC_DECLARE_ALLOCATOR(BroadcastChannel);
|
||||
|
||||
public:
|
||||
static constexpr bool OVERRIDES_FINALIZE = true;
|
||||
|
||||
[[nodiscard]] static GC::Ref<BroadcastChannel> construct_impl(JS::Realm&, FlyString const& name);
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/web-messaging.html#dom-broadcastchannel-name
|
||||
|
|
|
|||
|
|
@ -20,6 +20,8 @@ class WEB_API DedicatedWorkerGlobalScope
|
|||
GC_DECLARE_ALLOCATOR(DedicatedWorkerGlobalScope);
|
||||
|
||||
public:
|
||||
static constexpr bool OVERRIDES_FINALIZE = true;
|
||||
|
||||
virtual ~DedicatedWorkerGlobalScope() override;
|
||||
|
||||
WebIDL::ExceptionOr<void> post_message(JS::Value message, StructuredSerializeOptions const&);
|
||||
|
|
|
|||
|
|
@ -29,6 +29,8 @@ class EventSource : public DOM::EventTarget {
|
|||
GC_DECLARE_ALLOCATOR(EventSource);
|
||||
|
||||
public:
|
||||
static constexpr bool OVERRIDES_FINALIZE = true;
|
||||
|
||||
virtual ~EventSource() override;
|
||||
|
||||
static WebIDL::ExceptionOr<GC::Ref<EventSource>> construct_impl(JS::Realm&, StringView url, EventSourceInit event_source_init_dict = {});
|
||||
|
|
|
|||
|
|
@ -35,6 +35,8 @@ class HTMLImageElement final
|
|||
LAZY_LOADING_ELEMENT(HTMLImageElement);
|
||||
|
||||
public:
|
||||
static constexpr bool OVERRIDES_FINALIZE = true;
|
||||
|
||||
virtual ~HTMLImageElement() override;
|
||||
|
||||
virtual void form_associated_element_attribute_changed(FlyString const& name, Optional<String> const& old_value, Optional<String> const& value, Optional<FlyString> const& namespace_) override;
|
||||
|
|
|
|||
|
|
@ -37,6 +37,8 @@ class HTMLMediaElement : public HTMLElement {
|
|||
WEB_PLATFORM_OBJECT(HTMLMediaElement, HTMLElement);
|
||||
|
||||
public:
|
||||
static constexpr bool OVERRIDES_FINALIZE = true;
|
||||
|
||||
virtual ~HTMLMediaElement() override;
|
||||
|
||||
virtual bool is_focusable() const override { return true; }
|
||||
|
|
|
|||
|
|
@ -25,6 +25,8 @@ class HTMLVideoElement final : public HTMLMediaElement {
|
|||
GC_DECLARE_ALLOCATOR(HTMLVideoElement);
|
||||
|
||||
public:
|
||||
static constexpr bool OVERRIDES_FINALIZE = true;
|
||||
|
||||
virtual ~HTMLVideoElement() override;
|
||||
|
||||
Layout::VideoBox* layout_node();
|
||||
|
|
|
|||
|
|
@ -28,6 +28,8 @@ class WEB_API MessagePort final
|
|||
GC_DECLARE_ALLOCATOR(MessagePort);
|
||||
|
||||
public:
|
||||
static constexpr bool OVERRIDES_FINALIZE = true;
|
||||
|
||||
[[nodiscard]] static GC::Ref<MessagePort> create(JS::Realm&);
|
||||
|
||||
static void for_each_message_port(Function<void(MessagePort&)>);
|
||||
|
|
|
|||
|
|
@ -46,6 +46,8 @@ class WEB_API Navigable : public JS::Cell {
|
|||
GC_DECLARE_ALLOCATOR(Navigable);
|
||||
|
||||
public:
|
||||
static constexpr bool OVERRIDES_FINALIZE = true;
|
||||
|
||||
virtual ~Navigable() override;
|
||||
|
||||
using NullOrError = Optional<String>;
|
||||
|
|
|
|||
|
|
@ -19,6 +19,8 @@ class WEB_API NavigationObserver final : public Bindings::PlatformObject {
|
|||
GC_DECLARE_ALLOCATOR(NavigationObserver);
|
||||
|
||||
public:
|
||||
static constexpr bool OVERRIDES_FINALIZE = true;
|
||||
|
||||
[[nodiscard]] GC::Ptr<GC::Function<void()>> navigation_complete() const { return m_navigation_complete; }
|
||||
void set_navigation_complete(Function<void()>);
|
||||
|
||||
|
|
|
|||
|
|
@ -78,6 +78,8 @@ struct WEB_API EnvironmentSettingsObject : public Environment {
|
|||
GC_CELL(EnvironmentSettingsObject, Environment);
|
||||
|
||||
public:
|
||||
static constexpr bool OVERRIDES_FINALIZE = true;
|
||||
|
||||
virtual void finalize() override;
|
||||
virtual void initialize(JS::Realm&) override;
|
||||
|
||||
|
|
|
|||
|
|
@ -19,6 +19,8 @@ class SharedResourceRequest final : public JS::Cell {
|
|||
GC_DECLARE_ALLOCATOR(SharedResourceRequest);
|
||||
|
||||
public:
|
||||
static constexpr bool OVERRIDES_FINALIZE = true;
|
||||
|
||||
[[nodiscard]] static GC::Ref<SharedResourceRequest> get_or_create(JS::Realm&, GC::Ref<Page>, URL::URL const&);
|
||||
|
||||
virtual ~SharedResourceRequest() override;
|
||||
|
|
|
|||
|
|
@ -24,6 +24,8 @@ class WEB_API SharedWorkerGlobalScope
|
|||
GC_DECLARE_ALLOCATOR(SharedWorkerGlobalScope);
|
||||
|
||||
public:
|
||||
static constexpr bool OVERRIDES_FINALIZE = true;
|
||||
|
||||
virtual ~SharedWorkerGlobalScope() override;
|
||||
|
||||
void set_constructor_origin(URL::Origin origin) { m_constructor_origin = move(origin); }
|
||||
|
|
|
|||
|
|
@ -21,6 +21,8 @@ class WEB_API Storage : public Bindings::PlatformObject {
|
|||
GC_DECLARE_ALLOCATOR(Storage);
|
||||
|
||||
public:
|
||||
static constexpr bool OVERRIDES_FINALIZE = true;
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/webstorage.html#concept-storage-type
|
||||
enum class Type {
|
||||
Local,
|
||||
|
|
|
|||
|
|
@ -19,6 +19,8 @@ class TextTrackObserver final : public Bindings::PlatformObject {
|
|||
GC_DECLARE_ALLOCATOR(TextTrackObserver);
|
||||
|
||||
public:
|
||||
static constexpr bool OVERRIDES_FINALIZE = true;
|
||||
|
||||
[[nodiscard]] GC::Ptr<GC::Function<void(TextTrack::ReadinessState)>> track_readiness_observer() const { return m_track_readiness_observer; }
|
||||
void set_track_readiness_observer(Function<void(TextTrack::ReadinessState)>);
|
||||
|
||||
|
|
|
|||
|
|
@ -74,6 +74,8 @@ class WEB_API Window final
|
|||
GC_DECLARE_ALLOCATOR(Window);
|
||||
|
||||
public:
|
||||
static constexpr bool OVERRIDES_FINALIZE = true;
|
||||
|
||||
[[nodiscard]] static GC::Ref<Window> create(JS::Realm&);
|
||||
|
||||
~Window();
|
||||
|
|
|
|||
|
|
@ -42,6 +42,8 @@ class WEB_API WorkerGlobalScope
|
|||
GC_DECLARE_ALLOCATOR(WorkerGlobalScope);
|
||||
|
||||
public:
|
||||
static constexpr bool OVERRIDES_FINALIZE = true;
|
||||
|
||||
virtual ~WorkerGlobalScope() override;
|
||||
|
||||
// ^WindowOrWorkerGlobalScopeMixin
|
||||
|
|
|
|||
|
|
@ -18,6 +18,8 @@ class IDBDatabaseObserver final : public GC::Cell {
|
|||
GC_DECLARE_ALLOCATOR(IDBDatabaseObserver);
|
||||
|
||||
public:
|
||||
static constexpr bool OVERRIDES_FINALIZE = true;
|
||||
|
||||
virtual ~IDBDatabaseObserver();
|
||||
|
||||
[[nodiscard]] GC::Ptr<GC::Function<void()>> connection_state_changed_observer() const { return m_connection_state_changed_observer; }
|
||||
|
|
|
|||
|
|
@ -17,6 +17,8 @@ class IDBRequestObserver final : public GC::Cell {
|
|||
GC_DECLARE_ALLOCATOR(IDBRequestObserver);
|
||||
|
||||
public:
|
||||
static constexpr bool OVERRIDES_FINALIZE = true;
|
||||
|
||||
virtual ~IDBRequestObserver();
|
||||
|
||||
[[nodiscard]] GC::Ptr<GC::Function<void()>> request_processed_changed_observer() const { return m_request_processed_changed_observer; }
|
||||
|
|
|
|||
|
|
@ -17,6 +17,8 @@ class IDBTransactionObserver final : public GC::Cell {
|
|||
GC_DECLARE_ALLOCATOR(IDBTransactionObserver);
|
||||
|
||||
public:
|
||||
static constexpr bool OVERRIDES_FINALIZE = true;
|
||||
|
||||
virtual ~IDBTransactionObserver();
|
||||
|
||||
[[nodiscard]] GC::Ptr<GC::Function<void()>> transaction_finished_observer() const { return m_transaction_finished_observer; }
|
||||
|
|
|
|||
|
|
@ -16,6 +16,8 @@ class InternalGamepad : public Bindings::PlatformObject {
|
|||
GC_DECLARE_ALLOCATOR(InternalGamepad);
|
||||
|
||||
public:
|
||||
static constexpr bool OVERRIDES_FINALIZE = true;
|
||||
|
||||
static GC::Ref<InternalGamepad> create(JS::Realm&);
|
||||
|
||||
virtual ~InternalGamepad() override;
|
||||
|
|
|
|||
|
|
@ -44,6 +44,8 @@ class IntersectionObserver final : public Bindings::PlatformObject {
|
|||
GC_DECLARE_ALLOCATOR(IntersectionObserver);
|
||||
|
||||
public:
|
||||
static constexpr bool OVERRIDES_FINALIZE = true;
|
||||
|
||||
static WebIDL::ExceptionOr<GC::Ref<IntersectionObserver>> construct_impl(JS::Realm&, GC::Ptr<WebIDL::CallbackType> callback, IntersectionObserverInit const& options = {});
|
||||
|
||||
virtual ~IntersectionObserver() override;
|
||||
|
|
|
|||
|
|
@ -199,6 +199,8 @@ class GeneratedContentImageProvider final
|
|||
GC_DECLARE_ALLOCATOR(GeneratedContentImageProvider);
|
||||
|
||||
public:
|
||||
static constexpr bool OVERRIDES_FINALIZE = true;
|
||||
|
||||
virtual ~GeneratedContentImageProvider() override = default;
|
||||
|
||||
virtual void finalize() override
|
||||
|
|
|
|||
|
|
@ -19,6 +19,8 @@ class VideoBox final
|
|||
GC_DECLARE_ALLOCATOR(VideoBox);
|
||||
|
||||
public:
|
||||
static constexpr bool OVERRIDES_FINALIZE = true;
|
||||
|
||||
virtual void prepare_for_replaced_layout() override;
|
||||
|
||||
HTML::HTMLVideoElement& dom_node();
|
||||
|
|
|
|||
|
|
@ -19,6 +19,8 @@ class ImagePaintable final
|
|||
GC_DECLARE_ALLOCATOR(ImagePaintable);
|
||||
|
||||
public:
|
||||
static constexpr bool OVERRIDES_FINALIZE = true;
|
||||
|
||||
static GC::Ref<ImagePaintable> create(Layout::ImageBox const& layout_box);
|
||||
static GC::Ref<ImagePaintable> create(Layout::SVGImageBox const& layout_box);
|
||||
|
||||
|
|
|
|||
|
|
@ -55,6 +55,8 @@ class WEB_API Paintable
|
|||
GC_CELL(Paintable, JS::Cell);
|
||||
|
||||
public:
|
||||
static constexpr bool OVERRIDES_FINALIZE = true;
|
||||
|
||||
virtual ~Paintable();
|
||||
|
||||
void detach_from_layout_node();
|
||||
|
|
|
|||
|
|
@ -23,6 +23,8 @@ class ResizeObserver : public Bindings::PlatformObject {
|
|||
GC_DECLARE_ALLOCATOR(ResizeObserver);
|
||||
|
||||
public:
|
||||
static constexpr bool OVERRIDES_FINALIZE = true;
|
||||
|
||||
static WebIDL::ExceptionOr<GC::Ref<ResizeObserver>> construct_impl(JS::Realm&, WebIDL::CallbackType* callback);
|
||||
|
||||
virtual ~ResizeObserver() override;
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@ class WebSocket final : public DOM::EventTarget {
|
|||
GC_DECLARE_ALLOCATOR(WebSocket);
|
||||
|
||||
public:
|
||||
static constexpr bool OVERRIDES_FINALIZE = true;
|
||||
static constexpr bool OVERRIDES_MUST_SURVIVE_GARBAGE_COLLECTION = true;
|
||||
|
||||
static WebIDL::ExceptionOr<GC::Ref<WebSocket>> construct_impl(JS::Realm&, String const& url, Optional<Variant<String, Vector<String>>> const& protocols);
|
||||
|
|
|
|||
|
|
@ -4904,6 +4904,10 @@ private:
|
|||
|
||||
if (interface.extended_attributes.contains("WithFinalizer"sv)) {
|
||||
generator.append(R"~~~(
|
||||
public:
|
||||
static constexpr bool OVERRIDES_FINALIZE = true;
|
||||
|
||||
private:
|
||||
virtual void finalize() override;
|
||||
)~~~");
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue