diff --git a/Meta/gn/secondary/Userland/Libraries/LibJS/BUILD.gn b/Meta/gn/secondary/Userland/Libraries/LibJS/BUILD.gn index d8a595e9b7..bcb0ff0c18 100644 --- a/Meta/gn/secondary/Userland/Libraries/LibJS/BUILD.gn +++ b/Meta/gn/secondary/Userland/Libraries/LibJS/BUILD.gn @@ -44,6 +44,7 @@ shared_library("LibJS") { "Heap/BlockAllocator.cpp", "Heap/Cell.cpp", "Heap/CellAllocator.cpp", + "Heap/ConservativeVector.cpp", "Heap/Handle.cpp", "Heap/Heap.cpp", "Heap/HeapBlock.cpp", diff --git a/Userland/Libraries/LibJS/CMakeLists.txt b/Userland/Libraries/LibJS/CMakeLists.txt index a368643c5b..c9e29dcfae 100644 --- a/Userland/Libraries/LibJS/CMakeLists.txt +++ b/Userland/Libraries/LibJS/CMakeLists.txt @@ -20,6 +20,7 @@ set(SOURCES Heap/BlockAllocator.cpp Heap/Cell.cpp Heap/CellAllocator.cpp + Heap/ConservativeVector.cpp Heap/Handle.cpp Heap/Heap.cpp Heap/HeapBlock.cpp diff --git a/Userland/Libraries/LibJS/Forward.h b/Userland/Libraries/LibJS/Forward.h index 49c58be2ad..c1c070ed6e 100644 --- a/Userland/Libraries/LibJS/Forward.h +++ b/Userland/Libraries/LibJS/Forward.h @@ -302,6 +302,9 @@ class ThrowCompletionOr; template class Handle; +template +class ConservativeVector; + template class MarkedVector; diff --git a/Userland/Libraries/LibJS/Heap/ConservativeVector.cpp b/Userland/Libraries/LibJS/Heap/ConservativeVector.cpp new file mode 100644 index 0000000000..8c0fcf1b06 --- /dev/null +++ b/Userland/Libraries/LibJS/Heap/ConservativeVector.cpp @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2024, Andreas Kling + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include +#include + +namespace JS { + +ConservativeVectorBase::ConservativeVectorBase(Heap& heap) + : m_heap(&heap) +{ + m_heap->did_create_conservative_vector({}, *this); +} + +ConservativeVectorBase::~ConservativeVectorBase() +{ + m_heap->did_destroy_conservative_vector({}, *this); +} + +} diff --git a/Userland/Libraries/LibJS/Heap/ConservativeVector.h b/Userland/Libraries/LibJS/Heap/ConservativeVector.h new file mode 100644 index 0000000000..21b4e9c39f --- /dev/null +++ b/Userland/Libraries/LibJS/Heap/ConservativeVector.h @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2024, Andreas Kling + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#pragma once + +#include +#include +#include +#include +#include +#include + +namespace JS { + +class ConservativeVectorBase { +public: + virtual ReadonlySpan possible_values() const = 0; + +protected: + explicit ConservativeVectorBase(Heap&); + ~ConservativeVectorBase(); + + ConservativeVectorBase& operator=(ConservativeVectorBase const&); + + Heap* m_heap { nullptr }; + IntrusiveListNode m_list_node; + +public: + using List = IntrusiveList<&ConservativeVectorBase::m_list_node>; +}; + +template +class ConservativeVector final + : public ConservativeVectorBase + , public Vector { + +public: + explicit ConservativeVector(Heap& heap) + : ConservativeVectorBase(heap) + { + } + + virtual ~ConservativeVector() = default; + + ConservativeVector(ConservativeVector const& other) + : ConservativeVectorBase(*other.m_heap) + , Vector(other) + { + } + + ConservativeVector(ConservativeVector&& other) + : ConservativeVectorBase(*other.m_heap) + , Vector(move(static_cast&>(other))) + { + } + + ConservativeVector& operator=(ConservativeVector const& other) + { + Vector::operator=(other); + ConservativeVectorBase::operator=(other); + return *this; + } + + virtual ReadonlySpan possible_values() const override + { + return ReadonlySpan { reinterpret_cast(this->data()), this->size() }; + } +}; + +} diff --git a/Userland/Libraries/LibJS/Heap/Heap.cpp b/Userland/Libraries/LibJS/Heap/Heap.cpp index 4370032674..511724f8e4 100644 --- a/Userland/Libraries/LibJS/Heap/Heap.cpp +++ b/Userland/Libraries/LibJS/Heap/Heap.cpp @@ -369,6 +369,12 @@ __attribute__((no_sanitize("address"))) void Heap::gather_conservative_roots(Has } } + for (auto& vector : m_conservative_vectors) { + for (auto possible_value : vector.possible_values()) { + add_possible_value(possible_pointers, possible_value, HeapRoot { .type = HeapRoot::Type::ConservativeVector }, min_block_address, max_block_address); + } + } + HashTable all_live_heap_blocks; for_each_block([&](auto& block) { all_live_heap_blocks.set(&block); diff --git a/Userland/Libraries/LibJS/Heap/Heap.h b/Userland/Libraries/LibJS/Heap/Heap.h index 4002ca229f..87b7056a9e 100644 --- a/Userland/Libraries/LibJS/Heap/Heap.h +++ b/Userland/Libraries/LibJS/Heap/Heap.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020-2023, Andreas Kling + * Copyright (c) 2020-2024, Andreas Kling * * SPDX-License-Identifier: BSD-2-Clause */ @@ -17,6 +17,7 @@ #include #include #include +#include #include #include #include @@ -74,6 +75,9 @@ public: void did_create_marked_vector(Badge, MarkedVectorBase&); void did_destroy_marked_vector(Badge, MarkedVectorBase&); + void did_create_conservative_vector(Badge, ConservativeVectorBase&); + void did_destroy_conservative_vector(Badge, ConservativeVectorBase&); + void did_create_weak_container(Badge, WeakContainer&); void did_destroy_weak_container(Badge, WeakContainer&); @@ -147,6 +151,7 @@ private: HandleImpl::List m_handles; MarkedVectorBase::List m_marked_vectors; + ConservativeVectorBase::List m_conservative_vectors; WeakContainer::List m_weak_containers; Vector> m_uprooted_cells; @@ -181,6 +186,18 @@ inline void Heap::did_destroy_marked_vector(Badge, MarkedVecto m_marked_vectors.remove(vector); } +inline void Heap::did_create_conservative_vector(Badge, ConservativeVectorBase& vector) +{ + VERIFY(!m_conservative_vectors.contains(vector)); + m_conservative_vectors.append(vector); +} + +inline void Heap::did_destroy_conservative_vector(Badge, ConservativeVectorBase& vector) +{ + VERIFY(m_conservative_vectors.contains(vector)); + m_conservative_vectors.remove(vector); +} + inline void Heap::did_create_weak_container(Badge, WeakContainer& set) { VERIFY(!m_weak_containers.contains(set)); diff --git a/Userland/Libraries/LibJS/Heap/HeapRoot.h b/Userland/Libraries/LibJS/Heap/HeapRoot.h index 1d88a58097..1a9e4811b9 100644 --- a/Userland/Libraries/LibJS/Heap/HeapRoot.h +++ b/Userland/Libraries/LibJS/Heap/HeapRoot.h @@ -15,6 +15,7 @@ struct HeapRoot { HeapFunctionCapturedPointer, Handle, MarkedVector, + ConservativeVector, RegisterPointer, SafeFunction, StackPointer,