diff --git a/Userland/Libraries/LibJS/Forward.h b/Userland/Libraries/LibJS/Forward.h index 9a35729af8..560a07db2a 100644 --- a/Userland/Libraries/LibJS/Forward.h +++ b/Userland/Libraries/LibJS/Forward.h @@ -6,6 +6,8 @@ #pragma once +#include + #define JS_DECLARE_NATIVE_FUNCTION(name) \ static JS::ThrowCompletionOr name(JS::VM&, JS::GlobalObject&) @@ -241,7 +243,7 @@ class ThrowCompletionOr; template class Handle; -template +template class MarkedVector; namespace Bytecode { diff --git a/Userland/Libraries/LibJS/Heap/Heap.cpp b/Userland/Libraries/LibJS/Heap/Heap.cpp index 3fd89637c5..4b0ed04c04 100644 --- a/Userland/Libraries/LibJS/Heap/Heap.cpp +++ b/Userland/Libraries/LibJS/Heap/Heap.cpp @@ -120,10 +120,8 @@ void Heap::gather_roots(HashTable& roots) } } - for (auto& vector : m_marked_vectors) { - for (auto* cell : vector.cells()) - roots.set(cell); - } + for (auto& vector : m_marked_vectors) + vector.gather_roots(roots); if constexpr (HEAP_DEBUG) { dbgln("gather_roots:"); diff --git a/Userland/Libraries/LibJS/Heap/MarkedVector.cpp b/Userland/Libraries/LibJS/Heap/MarkedVector.cpp index 8400704cca..5fa3915dd7 100644 --- a/Userland/Libraries/LibJS/Heap/MarkedVector.cpp +++ b/Userland/Libraries/LibJS/Heap/MarkedVector.cpp @@ -1,5 +1,6 @@ /* * Copyright (c) 2021, Andreas Kling + * Copyright (c) 2022, Linus Groh * * SPDX-License-Identifier: BSD-2-Clause */ @@ -10,21 +11,26 @@ namespace JS { MarkedVectorBase::MarkedVectorBase(Heap& heap) - : m_heap(heap) + : m_heap(&heap) { - m_heap.did_create_marked_vector({}, *this); -} - -MarkedVectorBase::MarkedVectorBase(MarkedVectorBase&& other) - : m_heap(other.m_heap) - , m_cells(move(other.m_cells)) -{ - m_heap.did_create_marked_vector({}, *this); + m_heap->did_create_marked_vector({}, *this); } MarkedVectorBase::~MarkedVectorBase() { - m_heap.did_destroy_marked_vector({}, *this); + m_heap->did_destroy_marked_vector({}, *this); +} + +MarkedVectorBase& MarkedVectorBase::operator=(MarkedVectorBase const& other) +{ + if (m_heap != other.m_heap) { + m_heap = other.m_heap; + + // NOTE: IntrusiveList will remove this MarkedVectorBase from the old heap it was part of. + m_heap->did_create_marked_vector({}, *this); + } + + return *this; } } diff --git a/Userland/Libraries/LibJS/Heap/MarkedVector.h b/Userland/Libraries/LibJS/Heap/MarkedVector.h index f0367b3cdb..153de0aec4 100644 --- a/Userland/Libraries/LibJS/Heap/MarkedVector.h +++ b/Userland/Libraries/LibJS/Heap/MarkedVector.h @@ -1,13 +1,14 @@ /* * Copyright (c) 2021, Andreas Kling + * Copyright (c) 2022, Linus Groh * * SPDX-License-Identifier: BSD-2-Clause */ #pragma once +#include #include -#include #include #include #include @@ -15,56 +16,65 @@ namespace JS { class MarkedVectorBase { - AK_MAKE_NONCOPYABLE(MarkedVectorBase); - public: - void append(Cell* cell) { m_cells.append(cell); } - void prepend(Cell* cell) { m_cells.prepend(cell); } - size_t size() const { return m_cells.size(); } - - Span cells() { return m_cells.span(); } + virtual void gather_roots(HashTable&) const = 0; protected: explicit MarkedVectorBase(Heap&); - - MarkedVectorBase(MarkedVectorBase&&); - MarkedVectorBase& operator=(MarkedVectorBase&& other) - { - m_cells = move(other.m_cells); - return *this; - } - ~MarkedVectorBase(); - Heap& m_heap; + MarkedVectorBase& operator=(MarkedVectorBase const&); + Heap* m_heap { nullptr }; IntrusiveListNode m_list_node; - Vector m_cells; public: using List = IntrusiveList<&MarkedVectorBase::m_list_node>; }; -template -class MarkedVector : public MarkedVectorBase { +template +class MarkedVector + : public MarkedVectorBase + , public Vector { + public: explicit MarkedVector(Heap& heap) : MarkedVectorBase(heap) { } - ~MarkedVector() = default; + virtual ~MarkedVector() = default; - MarkedVector(MarkedVector&&) = default; - MarkedVector& operator=(MarkedVector&&) = default; + MarkedVector(MarkedVector const& other) + : MarkedVectorBase(*other.m_heap) + , Vector(other) + { + } - Span span() { return Span { bit_cast(m_cells.data()), m_cells.size() }; } + MarkedVector(MarkedVector&& other) + : MarkedVectorBase(*other.m_heap) + , Vector(move(static_cast&>(other))) + { + } - auto begin() { return span().begin(); } - auto begin() const { return span().begin(); } + MarkedVector& operator=(MarkedVector const& other) + { + Vector::operator=(other); + MarkedVectorBase::operator=(other); + return *this; + } - auto end() { return span().end(); } - auto end() const { return span().end(); } + virtual void gather_roots(HashTable& roots) const override + { + for (auto& value : *this) { + if constexpr (IsSame) { + if (value.is_cell()) + roots.set(&const_cast(value).as_cell()); + } else { + roots.set(value); + } + } + }; }; }