diff --git a/Userland/Libraries/LibJS/CMakeLists.txt b/Userland/Libraries/LibJS/CMakeLists.txt index 1f8b0684dab..e59cc737fa1 100644 --- a/Userland/Libraries/LibJS/CMakeLists.txt +++ b/Userland/Libraries/LibJS/CMakeLists.txt @@ -20,6 +20,7 @@ set(SOURCES Heap/Handle.cpp Heap/Heap.cpp Heap/HeapBlock.cpp + Heap/MarkedVector.cpp Interpreter.cpp Lexer.cpp MarkupGenerator.cpp diff --git a/Userland/Libraries/LibJS/Forward.h b/Userland/Libraries/LibJS/Forward.h index 9ed9134cb80..e67045445c6 100644 --- a/Userland/Libraries/LibJS/Forward.h +++ b/Userland/Libraries/LibJS/Forward.h @@ -228,6 +228,9 @@ class ThrowCompletionOr; template class Handle; +template +class MarkedVector; + namespace Bytecode { class BasicBlock; struct Executable; diff --git a/Userland/Libraries/LibJS/Heap/Heap.cpp b/Userland/Libraries/LibJS/Heap/Heap.cpp index e616ecbb986..3e075cb2e46 100644 --- a/Userland/Libraries/LibJS/Heap/Heap.cpp +++ b/Userland/Libraries/LibJS/Heap/Heap.cpp @@ -119,6 +119,11 @@ void Heap::gather_roots(HashTable& roots) } } + for (auto& vector : m_marked_vectors) { + for (auto* cell : vector.cells()) + roots.set(cell); + } + if constexpr (HEAP_DEBUG) { dbgln("gather_roots:"); for (auto* root : roots) @@ -318,6 +323,18 @@ void Heap::did_destroy_marked_value_list(Badge, MarkedValueList m_marked_value_lists.remove(list); } +void Heap::did_create_marked_vector(Badge, MarkedVectorBase& vector) +{ + VERIFY(!m_marked_vectors.contains(vector)); + m_marked_vectors.append(vector); +} + +void Heap::did_destroy_marked_vector(Badge, MarkedVectorBase& vector) +{ + VERIFY(m_marked_vectors.contains(vector)); + m_marked_vectors.remove(vector); +} + void Heap::did_create_weak_container(Badge, WeakContainer& set) { VERIFY(!m_weak_containers.contains(set)); diff --git a/Userland/Libraries/LibJS/Heap/Heap.h b/Userland/Libraries/LibJS/Heap/Heap.h index a68e3ffc5bd..6b2deb7335d 100644 --- a/Userland/Libraries/LibJS/Heap/Heap.h +++ b/Userland/Libraries/LibJS/Heap/Heap.h @@ -19,6 +19,7 @@ #include #include #include +#include #include #include @@ -75,6 +76,9 @@ public: void did_create_marked_value_list(Badge, MarkedValueList&); void did_destroy_marked_value_list(Badge, MarkedValueList&); + void did_create_marked_vector(Badge, MarkedVectorBase&); + void did_destroy_marked_vector(Badge, MarkedVectorBase&); + void did_create_weak_container(Badge, WeakContainer&); void did_destroy_weak_container(Badge, WeakContainer&); @@ -115,6 +119,7 @@ private: HandleImpl::List m_handles; + MarkedVectorBase::List m_marked_vectors; MarkedValueList::List m_marked_value_lists; WeakContainer::List m_weak_containers; diff --git a/Userland/Libraries/LibJS/Heap/MarkedVector.cpp b/Userland/Libraries/LibJS/Heap/MarkedVector.cpp new file mode 100644 index 00000000000..8400704cca0 --- /dev/null +++ b/Userland/Libraries/LibJS/Heap/MarkedVector.cpp @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2021, Andreas Kling + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include +#include + +namespace JS { + +MarkedVectorBase::MarkedVectorBase(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); +} + +MarkedVectorBase::~MarkedVectorBase() +{ + m_heap.did_destroy_marked_vector({}, *this); +} + +} diff --git a/Userland/Libraries/LibJS/Heap/MarkedVector.h b/Userland/Libraries/LibJS/Heap/MarkedVector.h new file mode 100644 index 00000000000..0b353763146 --- /dev/null +++ b/Userland/Libraries/LibJS/Heap/MarkedVector.h @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2021, Andreas Kling + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#pragma once + +#include +#include +#include +#include +#include + +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(); } + +protected: + explicit MarkedVectorBase(Heap&); + + MarkedVectorBase(MarkedVectorBase&&); + MarkedVectorBase& operator=(MarkedVectorBase&& other) + { + m_cells = move(other.m_cells); + return *this; + } + + ~MarkedVectorBase(); + + Heap& m_heap; + + IntrusiveListNode m_list_node; + Vector m_cells; + +public: + using List = IntrusiveList<&MarkedVectorBase::m_list_node>; +}; + +template +class MarkedVector : public MarkedVectorBase { +public: + explicit MarkedVector(Heap& heap) + : MarkedVectorBase(heap) + { + } + + ~MarkedVector() = default; + + MarkedVector(MarkedVector&&) = default; + MarkedVector& operator=(MarkedVector&&) = default; + + Span span() { return Span { bit_cast(m_cells.data()), m_cells.size() }; } + + auto begin() { return span().begin(); } + auto begin() const { return span().begin(); } + + auto end() { return span().begin(); } + auto end() const { return span().begin(); } +}; + +}