From 8bb9fe63b7ed63cda4654d449aa87b1756daaa40 Mon Sep 17 00:00:00 2001 From: Andreas Kling Date: Thu, 16 Dec 2021 18:54:06 +0100 Subject: [PATCH] LibJS: Add MarkedVector This abstracts a vector of Cell* with a strongly typed span() accessor that gives you Span instead of Span. It is intended to replace MarkedValueList in situations where you only need to store pointers to Cell (or an even more specific type of Cell). The API can definitely be improved, it's just the bare basics for now. --- Userland/Libraries/LibJS/CMakeLists.txt | 1 + Userland/Libraries/LibJS/Forward.h | 3 + Userland/Libraries/LibJS/Heap/Heap.cpp | 17 +++++ Userland/Libraries/LibJS/Heap/Heap.h | 5 ++ .../Libraries/LibJS/Heap/MarkedVector.cpp | 30 ++++++++ Userland/Libraries/LibJS/Heap/MarkedVector.h | 70 +++++++++++++++++++ 6 files changed, 126 insertions(+) create mode 100644 Userland/Libraries/LibJS/Heap/MarkedVector.cpp create mode 100644 Userland/Libraries/LibJS/Heap/MarkedVector.h diff --git a/Userland/Libraries/LibJS/CMakeLists.txt b/Userland/Libraries/LibJS/CMakeLists.txt index 1f8b0684da..e59cc737fa 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 9ed9134cb8..e67045445c 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 e616ecbb98..3e075cb2e4 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 a68e3ffc5b..6b2deb7335 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 0000000000..8400704cca --- /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 0000000000..0b35376314 --- /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(); } +}; + +}