diff --git a/Documentation/LibWebPatterns.md b/Documentation/LibWebPatterns.md index 673b4a60df8..b0734684817 100644 --- a/Documentation/LibWebPatterns.md +++ b/Documentation/LibWebPatterns.md @@ -36,7 +36,7 @@ This is the most common and at the same time most broad error type in LibWeb. In variant of supported errors: - `SimpleException` -- `JS::NonnullGCPtr` +- `GC::Ref` - `JS::Completion` (from `JS::ThrowCompletionOr`, assumed to be of `Type::Throw`) Use this error type for anything that needs to interact with the JS bindings, which will generally @@ -86,7 +86,7 @@ must have: ```cpp // https://fetch.spec.whatwg.org/#concept-fetch - WebIDL::ExceptionOr> fetch(JS::Realm& realm, Infrastructure::Request& request, Infrastructure::FetchAlgorithms const& algorithms, UseParallelQueue use_parallel_queue) + WebIDL::ExceptionOr> fetch(JS::Realm& realm, Infrastructure::Request& request, Infrastructure::FetchAlgorithms const& algorithms, UseParallelQueue use_parallel_queue) { // ... } @@ -99,7 +99,7 @@ must have: VERIFY(request.mode() == Infrastructure::Request::Mode::Navigate || !algorithms.process_early_hints_response().has_value()); // 2. Let taskDestination be null. - JS::GCPtr task_destination; + GC::Ptr task_destination; // ... ``` diff --git a/Libraries/LibJS/Heap/BlockAllocator.cpp b/Libraries/LibGC/BlockAllocator.cpp similarity index 96% rename from Libraries/LibJS/Heap/BlockAllocator.cpp rename to Libraries/LibGC/BlockAllocator.cpp index af0a0d27938..0c890619eae 100644 --- a/Libraries/LibJS/Heap/BlockAllocator.cpp +++ b/Libraries/LibGC/BlockAllocator.cpp @@ -7,8 +7,8 @@ #include #include #include -#include -#include +#include +#include #include #ifdef HAS_ADDRESS_SANITIZER @@ -20,7 +20,7 @@ # define USE_FALLBACK_BLOCK_DEALLOCATION #endif -namespace JS { +namespace GC { BlockAllocator::~BlockAllocator() { diff --git a/Libraries/LibJS/Heap/BlockAllocator.h b/Libraries/LibGC/BlockAllocator.h similarity index 89% rename from Libraries/LibJS/Heap/BlockAllocator.h rename to Libraries/LibGC/BlockAllocator.h index 7d4ab54700f..e3a5dfa28fb 100644 --- a/Libraries/LibJS/Heap/BlockAllocator.h +++ b/Libraries/LibGC/BlockAllocator.h @@ -7,9 +7,9 @@ #pragma once #include -#include +#include -namespace JS { +namespace GC { class BlockAllocator { public: diff --git a/Libraries/LibGC/CMakeLists.txt b/Libraries/LibGC/CMakeLists.txt new file mode 100644 index 00000000000..be7c1d07aa7 --- /dev/null +++ b/Libraries/LibGC/CMakeLists.txt @@ -0,0 +1,14 @@ +set(SOURCES + BlockAllocator.cpp + Cell.cpp + CellAllocator.cpp + ConservativeVector.cpp + Root.cpp + Heap.cpp + HeapBlock.cpp + MarkedVector.cpp + WeakContainer.cpp +) + +serenity_lib(LibGC gc) +target_link_libraries(LibGC PRIVATE LibCore) diff --git a/Libraries/LibJS/Heap/CellImpl.cpp b/Libraries/LibGC/Cell.cpp similarity index 55% rename from Libraries/LibJS/Heap/CellImpl.cpp rename to Libraries/LibGC/Cell.cpp index 13673de8f57..328200f5c80 100644 --- a/Libraries/LibJS/Heap/CellImpl.cpp +++ b/Libraries/LibGC/Cell.cpp @@ -4,12 +4,12 @@ * SPDX-License-Identifier: BSD-2-Clause */ -#include -#include +#include +#include -namespace JS { +namespace GC { -void JS::CellImpl::Visitor::visit(NanBoxedValue const& value) +void GC::Cell::Visitor::visit(NanBoxedValue const& value) { if (value.is_cell()) visit_impl(value.as_cell()); diff --git a/Libraries/LibJS/Heap/CellImpl.h b/Libraries/LibGC/Cell.h similarity index 85% rename from Libraries/LibJS/Heap/CellImpl.h rename to Libraries/LibGC/Cell.h index 14c42add160..85eadf0459e 100644 --- a/Libraries/LibJS/Heap/CellImpl.h +++ b/Libraries/LibGC/Cell.h @@ -13,11 +13,11 @@ #include #include #include -#include -#include -#include +#include +#include +#include -namespace JS { +namespace GC { // This instrumentation tells analysis tooling to ignore a potentially mis-wrapped GC-allocated member variable // It should only be used when the lifetime of the GC-allocated member is always longer than the object @@ -27,21 +27,21 @@ namespace JS { # define IGNORE_GC #endif -#define JS_CELL(class_, base_class) \ +#define GC_CELL(class_, base_class) \ public: \ using Base = base_class; \ virtual StringView class_name() const override \ { \ return #class_##sv; \ } \ - friend class JS::Heap; + friend class GC::Heap; -class CellImpl : public Weakable { - AK_MAKE_NONCOPYABLE(CellImpl); - AK_MAKE_NONMOVABLE(CellImpl); +class Cell : public Weakable { + AK_MAKE_NONCOPYABLE(Cell); + AK_MAKE_NONMOVABLE(Cell); public: - virtual ~CellImpl() = default; + virtual ~Cell() = default; bool is_marked() const { return m_mark; } void set_marked(bool b) { m_mark = b; } @@ -58,36 +58,36 @@ public: class Visitor { public: - void visit(CellImpl* cell) + void visit(Cell* cell) { if (cell) visit_impl(*cell); } - void visit(CellImpl& cell) + void visit(Cell& cell) { visit_impl(cell); } - void visit(CellImpl const* cell) + void visit(Cell const* cell) { - visit(const_cast(cell)); + visit(const_cast(cell)); } - void visit(CellImpl const& cell) + void visit(Cell const& cell) { - visit(const_cast(cell)); + visit(const_cast(cell)); } template - void visit(GCPtr cell) + void visit(Ptr cell) { if (cell) visit_impl(const_cast&>(*cell.ptr())); } template - void visit(NonnullGCPtr cell) + void visit(Ref cell) { visit_impl(const_cast&>(*cell.ptr())); } @@ -161,7 +161,7 @@ public: virtual void visit_possible_values(ReadonlyBytes) = 0; protected: - virtual void visit_impl(CellImpl&) = 0; + virtual void visit_impl(Cell&) = 0; virtual ~Visitor() = default; }; @@ -180,7 +180,7 @@ public: ALWAYS_INLINE Heap& heap() const { return HeapBlockBase::from_cell(this)->heap(); } protected: - CellImpl() = default; + Cell() = default; ALWAYS_INLINE void* private_data() const { return bit_cast(&heap())->private_data(); } @@ -195,8 +195,8 @@ private: } template<> -struct AK::Formatter : AK::Formatter { - ErrorOr format(FormatBuilder& builder, JS::CellImpl const* cell) +struct AK::Formatter : AK::Formatter { + ErrorOr format(FormatBuilder& builder, GC::Cell const* cell) { if (!cell) return builder.put_string("Cell{nullptr}"sv); diff --git a/Libraries/LibJS/Heap/CellAllocator.cpp b/Libraries/LibGC/CellAllocator.cpp similarity index 87% rename from Libraries/LibJS/Heap/CellAllocator.cpp rename to Libraries/LibGC/CellAllocator.cpp index fe8d00578dc..78433a2cc86 100644 --- a/Libraries/LibJS/Heap/CellAllocator.cpp +++ b/Libraries/LibGC/CellAllocator.cpp @@ -5,12 +5,12 @@ */ #include -#include -#include -#include -#include +#include +#include +#include +#include -namespace JS { +namespace GC { CellAllocator::CellAllocator(size_t cell_size, char const* class_name) : m_class_name(class_name) @@ -18,7 +18,7 @@ CellAllocator::CellAllocator(size_t cell_size, char const* class_name) { } -CellImpl* CellAllocator::allocate_cell(Heap& heap) +Cell* CellAllocator::allocate_cell(Heap& heap) { if (!m_list_node.is_in_list()) heap.register_cell_allocator({}, *this); diff --git a/Libraries/LibJS/Heap/CellAllocator.h b/Libraries/LibGC/CellAllocator.h similarity index 84% rename from Libraries/LibJS/Heap/CellAllocator.h rename to Libraries/LibGC/CellAllocator.h index beece07829f..8a73436901e 100644 --- a/Libraries/LibJS/Heap/CellAllocator.h +++ b/Libraries/LibGC/CellAllocator.h @@ -9,17 +9,17 @@ #include #include #include -#include -#include -#include +#include +#include +#include -#define JS_DECLARE_ALLOCATOR(ClassName) \ - static JS::TypeIsolatingCellAllocator cell_allocator +#define GC_DECLARE_ALLOCATOR(ClassName) \ + static GC::TypeIsolatingCellAllocator cell_allocator -#define JS_DEFINE_ALLOCATOR(ClassName) \ - JS::TypeIsolatingCellAllocator ClassName::cell_allocator { #ClassName } +#define GC_DEFINE_ALLOCATOR(ClassName) \ + GC::TypeIsolatingCellAllocator ClassName::cell_allocator { #ClassName } -namespace JS { +namespace GC { class CellAllocator { public: @@ -28,7 +28,7 @@ public: size_t cell_size() const { return m_cell_size; } - CellImpl* allocate_cell(Heap&); + Cell* allocate_cell(Heap&); template IterationDecision for_each_block(Callback callback) diff --git a/Libraries/LibJS/Heap/ConservativeVector.cpp b/Libraries/LibGC/ConservativeVector.cpp similarity index 80% rename from Libraries/LibJS/Heap/ConservativeVector.cpp rename to Libraries/LibGC/ConservativeVector.cpp index b9ef2f26b97..33e6f1a3aaa 100644 --- a/Libraries/LibJS/Heap/ConservativeVector.cpp +++ b/Libraries/LibGC/ConservativeVector.cpp @@ -4,10 +4,10 @@ * SPDX-License-Identifier: BSD-2-Clause */ -#include -#include +#include +#include -namespace JS { +namespace GC { ConservativeVectorBase::ConservativeVectorBase(Heap& heap) : m_heap(&heap) diff --git a/Libraries/LibJS/Heap/ConservativeVector.h b/Libraries/LibGC/ConservativeVector.h similarity index 94% rename from Libraries/LibJS/Heap/ConservativeVector.h rename to Libraries/LibGC/ConservativeVector.h index 066dcf37edd..150525a7cea 100644 --- a/Libraries/LibJS/Heap/ConservativeVector.h +++ b/Libraries/LibGC/ConservativeVector.h @@ -9,11 +9,11 @@ #include #include #include -#include -#include -#include +#include +#include +#include -namespace JS { +namespace GC { class ConservativeVectorBase { public: diff --git a/Libraries/LibJS/Heap/DeferGC.h b/Libraries/LibGC/DeferGC.h similarity index 88% rename from Libraries/LibJS/Heap/DeferGC.h rename to Libraries/LibGC/DeferGC.h index 3c2ab1ea11a..addeed7a53a 100644 --- a/Libraries/LibJS/Heap/DeferGC.h +++ b/Libraries/LibGC/DeferGC.h @@ -6,9 +6,9 @@ #pragma once -#include +#include -namespace JS { +namespace GC { class DeferGC { public: diff --git a/Libraries/LibGC/Forward.h b/Libraries/LibGC/Forward.h new file mode 100644 index 00000000000..98cf257c9cf --- /dev/null +++ b/Libraries/LibGC/Forward.h @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2024, Shannon Booth + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#pragma once + +namespace GC { + +class Cell; +class CellAllocator; +class DeferGC; +class RootImpl; +class Heap; +class HeapBlock; +class NanBoxedValue; +class WeakContainer; + +template +class Function; + +template +class Root; + +template +class ConservativeVector; + +template +class MarkedVector; + +} diff --git a/Libraries/LibGC/Function.h b/Libraries/LibGC/Function.h new file mode 100644 index 00000000000..047ea765cc5 --- /dev/null +++ b/Libraries/LibGC/Function.h @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2023, Andreas Kling + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#pragma once + +#include +#include +#include + +namespace GC { + +template +class Function final : public Cell { + GC_CELL(Function, Cell); + +public: + static Ref create(Heap& heap, AK::Function function) + { + return heap.allocate(move(function)); + } + + virtual ~Function() override = default; + + [[nodiscard]] AK::Function const& function() const { return m_function; } + +private: + Function(AK::Function function) + : m_function(move(function)) + { + } + + virtual void visit_edges(Visitor& visitor) override + { + Base::visit_edges(visitor); + visitor.visit_possible_values(m_function.raw_capture_range()); + } + + AK::Function m_function; +}; + +template> +static Ref> create_function(Heap& heap, Callable&& function) +{ + return Function::create(heap, AK::Function { forward(function) }); +} + +} diff --git a/Libraries/LibJS/Heap/Heap.cpp b/Libraries/LibGC/Heap.cpp similarity index 89% rename from Libraries/LibJS/Heap/Heap.cpp rename to Libraries/LibGC/Heap.cpp index e7d2698267e..f6be03c1bd3 100644 --- a/Libraries/LibJS/Heap/Heap.cpp +++ b/Libraries/LibGC/Heap.cpp @@ -15,20 +15,20 @@ #include #include #include -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include #include #ifdef HAS_ADDRESS_SANITIZER # include #endif -namespace JS { +namespace GC { -Heap::Heap(void* private_data, Function&)> gather_embedder_roots) +Heap::Heap(void* private_data, AK::Function&)> gather_embedder_roots) : HeapBase(private_data) , m_gather_embedder_roots(move(gather_embedder_roots)) { @@ -100,7 +100,7 @@ static void for_each_cell_among_possible_pointers(HashTable const& a for (auto possible_pointer : possible_pointers.keys()) { if (!possible_pointer) continue; - auto* possible_heap_block = HeapBlock::from_cell(reinterpret_cast(possible_pointer)); + auto* possible_heap_block = HeapBlock::from_cell(reinterpret_cast(possible_pointer)); if (!all_live_heap_blocks.contains(possible_heap_block)) continue; if (auto* cell = possible_heap_block->cell_from_possible_pointer(possible_pointer)) { @@ -109,9 +109,9 @@ static void for_each_cell_among_possible_pointers(HashTable const& a } } -class GraphConstructorVisitor final : public CellImpl::Visitor { +class GraphConstructorVisitor final : public Cell::Visitor { public: - explicit GraphConstructorVisitor(Heap& heap, HashMap const& roots) + explicit GraphConstructorVisitor(Heap& heap, HashMap const& roots) : m_heap(heap) { m_heap.find_min_and_max_block_addresses(m_min_block_address, m_max_block_address); @@ -129,7 +129,7 @@ public: } } - virtual void visit_impl(CellImpl& cell) override + virtual void visit_impl(Cell& cell) override { if (m_node_being_visited) m_node_being_visited->edges.set(reinterpret_cast(&cell)); @@ -148,7 +148,7 @@ public: for (size_t i = 0; i < (bytes.size() / sizeof(FlatPtr)); ++i) add_possible_value(possible_pointers, raw_pointer_sized_values[i], HeapRoot { .type = HeapRoot::Type::HeapFunctionCapturedPointer }, m_min_block_address, m_max_block_address); - for_each_cell_among_possible_pointers(m_all_live_heap_blocks, possible_pointers, [&](CellImpl* cell, FlatPtr) { + for_each_cell_among_possible_pointers(m_all_live_heap_blocks, possible_pointers, [&](Cell* cell, FlatPtr) { if (m_node_being_visited) m_node_being_visited->edges.set(reinterpret_cast(cell)); @@ -183,8 +183,8 @@ public: auto type = it.value.root_origin->type; auto location = it.value.root_origin->location; switch (type) { - case HeapRoot::Type::Handle: - node.set("root"sv, ByteString::formatted("Handle {} {}:{}", location->function_name(), location->filename(), location->line_number())); + case HeapRoot::Type::Root: + node.set("root"sv, ByteString::formatted("Root {} {}:{}", location->function_name(), location->filename(), location->line_number())); break; case HeapRoot::Type::MarkedVector: node.set("root"sv, "MarkedVector"); @@ -218,7 +218,7 @@ private: }; GraphNode* m_node_being_visited { nullptr }; - Vector> m_work_queue; + Vector> m_work_queue; HashMap m_graph; Heap& m_heap; @@ -229,7 +229,7 @@ private: AK::JsonObject Heap::dump_graph() { - HashMap roots; + HashMap roots; gather_roots(roots); GraphConstructorVisitor visitor(*this, roots); visitor.visit_all_cells(); @@ -250,7 +250,7 @@ void Heap::collect_garbage(CollectionType collection_type, bool print_report) m_should_gc_when_deferral_ends = true; return; } - HashMap roots; + HashMap roots; gather_roots(roots); mark_live_cells(roots); } @@ -258,13 +258,13 @@ void Heap::collect_garbage(CollectionType collection_type, bool print_report) sweep_dead_cells(print_report, collection_measurement_timer); } -void Heap::gather_roots(HashMap& roots) +void Heap::gather_roots(HashMap& roots) { m_gather_embedder_roots(roots); gather_conservative_roots(roots); - for (auto& handle : m_handles) - roots.set(handle.cell(), HeapRoot { .type = HeapRoot::Type::Handle, .location = &handle.source_location() }); + for (auto& root : m_roots) + roots.set(root.cell(), HeapRoot { .type = HeapRoot::Type::Root, .location = &root.source_location() }); for (auto& vector : m_marked_vectors) vector.gather_roots(roots); @@ -298,7 +298,7 @@ void Heap::gather_asan_fake_stack_roots(HashMap&, FlatPtr, Fl } #endif -NO_SANITIZE_ADDRESS void Heap::gather_conservative_roots(HashMap& roots) +NO_SANITIZE_ADDRESS void Heap::gather_conservative_roots(HashMap& roots) { FlatPtr dummy; @@ -337,8 +337,8 @@ NO_SANITIZE_ADDRESS void Heap::gather_conservative_roots(HashMapstate() == CellImpl::State::Live) { + for_each_cell_among_possible_pointers(all_live_heap_blocks, possible_pointers, [&](Cell* cell, FlatPtr possible_pointer) { + if (cell->state() == Cell::State::Live) { dbgln_if(HEAP_DEBUG, " ?-> {}", (void const*)cell); roots.set(cell, *possible_pointers.get(possible_pointer)); } else { @@ -347,9 +347,9 @@ NO_SANITIZE_ADDRESS void Heap::gather_conservative_roots(HashMap const& roots) + explicit MarkingVisitor(Heap& heap, HashMap const& roots) : m_heap(heap) { m_heap.find_min_and_max_block_addresses(m_min_block_address, m_max_block_address); @@ -363,7 +363,7 @@ public: } } - virtual void visit_impl(CellImpl& cell) override + virtual void visit_impl(Cell& cell) override { if (cell.is_marked()) return; @@ -381,10 +381,10 @@ public: for (size_t i = 0; i < (bytes.size() / sizeof(FlatPtr)); ++i) add_possible_value(possible_pointers, raw_pointer_sized_values[i], HeapRoot { .type = HeapRoot::Type::HeapFunctionCapturedPointer }, m_min_block_address, m_max_block_address); - for_each_cell_among_possible_pointers(m_all_live_heap_blocks, possible_pointers, [&](CellImpl* cell, FlatPtr) { + for_each_cell_among_possible_pointers(m_all_live_heap_blocks, possible_pointers, [&](Cell* cell, FlatPtr) { if (cell->is_marked()) return; - if (cell->state() != CellImpl::State::Live) + if (cell->state() != Cell::State::Live) return; cell->set_marked(true); m_work_queue.append(*cell); @@ -400,13 +400,13 @@ public: private: Heap& m_heap; - Vector> m_work_queue; + Vector> m_work_queue; HashTable m_all_live_heap_blocks; FlatPtr m_min_block_address; FlatPtr m_max_block_address; }; -void Heap::mark_live_cells(HashMap const& roots) +void Heap::mark_live_cells(HashMap const& roots) { dbgln_if(HEAP_DEBUG, "mark_live_cells:"); @@ -420,7 +420,7 @@ void Heap::mark_live_cells(HashMap const& roots) m_uprooted_cells.clear(); } -bool Heap::cell_must_survive_garbage_collection(CellImpl const& cell) +bool Heap::cell_must_survive_garbage_collection(Cell const& cell) { if (!cell.overrides_must_survive_garbage_collection({})) return false; @@ -430,7 +430,7 @@ bool Heap::cell_must_survive_garbage_collection(CellImpl const& cell) void Heap::finalize_unmarked_cells() { for_each_block([&](auto& block) { - block.template for_each_cell_in_state([](CellImpl* cell) { + block.template for_each_cell_in_state([](Cell* cell) { if (!cell->is_marked() && !cell_must_survive_garbage_collection(*cell)) cell->finalize(); }); @@ -452,7 +452,7 @@ void Heap::sweep_dead_cells(bool print_report, Core::ElapsedTimer const& measure for_each_block([&](auto& block) { bool block_has_live_cells = false; bool block_was_full = block.is_full(); - block.template for_each_cell_in_state([&](CellImpl* cell) { + block.template for_each_cell_in_state([&](Cell* cell) { if (!cell->is_marked() && !cell_must_survive_garbage_collection(*cell)) { dbgln_if(HEAP_DEBUG, " ~ {}", cell); block.deallocate(cell); @@ -530,7 +530,7 @@ void Heap::undefer_gc() } } -void Heap::uproot_cell(CellImpl* cell) +void Heap::uproot_cell(Cell* cell) { m_uprooted_cells.append(cell); } diff --git a/Libraries/LibJS/Heap/Heap.h b/Libraries/LibGC/Heap.h similarity index 79% rename from Libraries/LibJS/Heap/Heap.h rename to Libraries/LibGC/Heap.h index 79851307c45..89e31d998d2 100644 --- a/Libraries/LibJS/Heap/Heap.h +++ b/Libraries/LibGC/Heap.h @@ -16,28 +16,28 @@ #include #include #include -#include -#include -#include -#include -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include +#include +#include +#include +#include -namespace JS { +namespace GC { class Heap : public HeapBase { AK_MAKE_NONCOPYABLE(Heap); AK_MAKE_NONMOVABLE(Heap); public: - explicit Heap(void* private_data, Function&)> gather_embedder_roots); + explicit Heap(void* private_data, AK::Function&)> gather_embedder_roots); ~Heap(); template - NonnullGCPtr allocate(Args&&... args) + Ref allocate(Args&&... args) { auto* memory = allocate_cell(); defer_gc(); @@ -57,8 +57,8 @@ public: bool should_collect_on_every_allocation() const { return m_should_collect_on_every_allocation; } void set_should_collect_on_every_allocation(bool b) { m_should_collect_on_every_allocation = b; } - void did_create_handle(Badge, HandleImpl&); - void did_destroy_handle(Badge, HandleImpl&); + void did_create_root(Badge, RootImpl&); + void did_destroy_root(Badge, RootImpl&); void did_create_marked_vector(Badge, MarkedVectorBase&); void did_destroy_marked_vector(Badge, MarkedVectorBase&); @@ -71,7 +71,7 @@ public: void register_cell_allocator(Badge, CellAllocator&); - void uproot_cell(CellImpl* cell); + void uproot_cell(Cell* cell); private: friend class MarkingVisitor; @@ -81,10 +81,10 @@ private: void defer_gc(); void undefer_gc(); - static bool cell_must_survive_garbage_collection(CellImpl const&); + static bool cell_must_survive_garbage_collection(Cell const&); template - CellImpl* allocate_cell() + Cell* allocate_cell() { will_allocate(sizeof(T)); if constexpr (requires { T::cell_allocator.allocator.get().allocate_cell(*this); }) { @@ -98,10 +98,10 @@ private: void will_allocate(size_t); void find_min_and_max_block_addresses(FlatPtr& min_address, FlatPtr& max_address); - void gather_roots(HashMap&); - void gather_conservative_roots(HashMap&); + void gather_roots(HashMap&); + void gather_conservative_roots(HashMap&); void gather_asan_fake_stack_roots(HashMap&, FlatPtr, FlatPtr min_block_address, FlatPtr max_block_address); - void mark_live_cells(HashMap const& live_cells); + void mark_live_cells(HashMap const& live_cells); void finalize_unmarked_cells(); void sweep_dead_cells(bool print_report, Core::ElapsedTimer const&); @@ -134,31 +134,31 @@ private: Vector> m_size_based_cell_allocators; CellAllocator::List m_all_cell_allocators; - HandleImpl::List m_handles; + RootImpl::List m_roots; MarkedVectorBase::List m_marked_vectors; ConservativeVectorBase::List m_conservative_vectors; WeakContainer::List m_weak_containers; - Vector> m_uprooted_cells; + Vector> m_uprooted_cells; size_t m_gc_deferrals { 0 }; bool m_should_gc_when_deferral_ends { false }; bool m_collecting_garbage { false }; StackInfo m_stack_info; - Function&)> m_gather_embedder_roots; + AK::Function&)> m_gather_embedder_roots; }; -inline void Heap::did_create_handle(Badge, HandleImpl& impl) +inline void Heap::did_create_root(Badge, RootImpl& impl) { - VERIFY(!m_handles.contains(impl)); - m_handles.append(impl); + VERIFY(!m_roots.contains(impl)); + m_roots.append(impl); } -inline void Heap::did_destroy_handle(Badge, HandleImpl& impl) +inline void Heap::did_destroy_root(Badge, RootImpl& impl) { - VERIFY(m_handles.contains(impl)); - m_handles.remove(impl); + VERIFY(m_roots.contains(impl)); + m_roots.remove(impl); } inline void Heap::did_create_marked_vector(Badge, MarkedVectorBase& vector) diff --git a/Libraries/LibJS/Heap/HeapBlock.cpp b/Libraries/LibGC/HeapBlock.cpp similarity index 89% rename from Libraries/LibJS/Heap/HeapBlock.cpp rename to Libraries/LibGC/HeapBlock.cpp index f7587cc04ea..61373dc48ea 100644 --- a/Libraries/LibJS/Heap/HeapBlock.cpp +++ b/Libraries/LibGC/HeapBlock.cpp @@ -7,8 +7,8 @@ #include #include #include -#include -#include +#include +#include #include #include @@ -16,7 +16,7 @@ # include #endif -namespace JS { +namespace GC { size_t HeapBlockBase::block_size = PAGE_SIZE; @@ -37,16 +37,16 @@ HeapBlock::HeapBlock(Heap& heap, CellAllocator& cell_allocator, size_t cell_size ASAN_POISON_MEMORY_REGION(m_storage, block_size - sizeof(HeapBlock)); } -void HeapBlock::deallocate(CellImpl* cell) +void HeapBlock::deallocate(Cell* cell) { VERIFY(is_valid_cell_pointer(cell)); VERIFY(!m_freelist || is_valid_cell_pointer(m_freelist)); - VERIFY(cell->state() == CellImpl::State::Live); + VERIFY(cell->state() == Cell::State::Live); VERIFY(!cell->is_marked()); - cell->~CellImpl(); + cell->~Cell(); auto* freelist_entry = new (cell) FreelistEntry(); - freelist_entry->set_state(CellImpl::State::Dead); + freelist_entry->set_state(Cell::State::Dead); freelist_entry->next = m_freelist; m_freelist = freelist_entry; diff --git a/Libraries/LibJS/Heap/HeapBlock.h b/Libraries/LibGC/HeapBlock.h similarity index 79% rename from Libraries/LibJS/Heap/HeapBlock.h rename to Libraries/LibGC/HeapBlock.h index 44d1c89e682..17afadeb73b 100644 --- a/Libraries/LibJS/Heap/HeapBlock.h +++ b/Libraries/LibGC/HeapBlock.h @@ -10,15 +10,15 @@ #include #include #include -#include -#include -#include +#include +#include +#include #ifdef HAS_ADDRESS_SANITIZER # include #endif -namespace JS { +namespace GC { class HeapBlock : public HeapBlockBase { AK_MAKE_NONCOPYABLE(HeapBlock); @@ -32,9 +32,9 @@ public: size_t cell_count() const { return (block_size - sizeof(HeapBlock)) / m_cell_size; } bool is_full() const { return !has_lazy_freelist() && !m_freelist; } - ALWAYS_INLINE CellImpl* allocate() + ALWAYS_INLINE Cell* allocate() { - CellImpl* allocated_cell = nullptr; + Cell* allocated_cell = nullptr; if (m_freelist) { VERIFY(is_valid_cell_pointer(m_freelist)); allocated_cell = exchange(m_freelist, m_freelist->next); @@ -48,7 +48,7 @@ public: return allocated_cell; } - void deallocate(CellImpl*); + void deallocate(Cell*); template void for_each_cell(Callback callback) @@ -58,7 +58,7 @@ public: callback(cell(i)); } - template + template void for_each_cell_in_state(Callback callback) { for_each_cell([&](auto* cell) { @@ -67,12 +67,12 @@ public: }); } - static HeapBlock* from_cell(CellImpl const* cell) + static HeapBlock* from_cell(Cell const* cell) { return static_cast(HeapBlockBase::from_cell(cell)); } - CellImpl* cell_from_possible_pointer(FlatPtr pointer) + Cell* cell_from_possible_pointer(FlatPtr pointer) { if (pointer < reinterpret_cast(m_storage)) return nullptr; @@ -83,7 +83,7 @@ public: return cell(cell_index); } - bool is_valid_cell_pointer(CellImpl const* cell) + bool is_valid_cell_pointer(Cell const* cell) { return cell_from_possible_pointer((FlatPtr)cell); } @@ -97,21 +97,21 @@ private: bool has_lazy_freelist() const { return m_next_lazy_freelist_index < cell_count(); } - struct FreelistEntry final : public CellImpl { - JS_CELL(FreelistEntry, CellImpl); + struct FreelistEntry final : public Cell { + GC_CELL(FreelistEntry, Cell); - RawGCPtr next; + RawPtr next; }; - CellImpl* cell(size_t index) + Cell* cell(size_t index) { - return reinterpret_cast(&m_storage[index * cell_size()]); + return reinterpret_cast(&m_storage[index * cell_size()]); } CellAllocator& m_cell_allocator; size_t m_cell_size { 0 }; size_t m_next_lazy_freelist_index { 0 }; - GCPtr m_freelist; + Ptr m_freelist; alignas(__BIGGEST_ALIGNMENT__) u8 m_storage[]; public: diff --git a/Libraries/LibJS/Heap/HeapRoot.h b/Libraries/LibGC/HeapRoot.h similarity index 93% rename from Libraries/LibJS/Heap/HeapRoot.h rename to Libraries/LibGC/HeapRoot.h index 0309062bdbc..f4205185ab5 100644 --- a/Libraries/LibJS/Heap/HeapRoot.h +++ b/Libraries/LibGC/HeapRoot.h @@ -8,12 +8,12 @@ #include -namespace JS { +namespace GC { struct HeapRoot { enum class Type { HeapFunctionCapturedPointer, - Handle, + Root, MarkedVector, ConservativeVector, RegisterPointer, diff --git a/Libraries/LibJS/Heap/Internals.h b/Libraries/LibGC/Internals.h similarity index 89% rename from Libraries/LibJS/Heap/Internals.h rename to Libraries/LibGC/Internals.h index f3ec8a8ee55..234c33baf40 100644 --- a/Libraries/LibJS/Heap/Internals.h +++ b/Libraries/LibGC/Internals.h @@ -8,9 +8,9 @@ #pragma once #include -#include +#include -namespace JS { +namespace GC { class HeapBase { AK_MAKE_NONCOPYABLE(HeapBase); @@ -34,7 +34,7 @@ class HeapBlockBase { public: static size_t block_size; - static HeapBlockBase* from_cell(CellImpl const* cell) + static HeapBlockBase* from_cell(Cell const* cell) { return reinterpret_cast(bit_cast(cell) & ~(HeapBlockBase::block_size - 1)); } diff --git a/Libraries/LibJS/Heap/MarkedVector.cpp b/Libraries/LibGC/MarkedVector.cpp similarity index 89% rename from Libraries/LibJS/Heap/MarkedVector.cpp rename to Libraries/LibGC/MarkedVector.cpp index fe269181b32..e03960d3108 100644 --- a/Libraries/LibJS/Heap/MarkedVector.cpp +++ b/Libraries/LibGC/MarkedVector.cpp @@ -5,10 +5,10 @@ * SPDX-License-Identifier: BSD-2-Clause */ -#include -#include +#include +#include -namespace JS { +namespace GC { MarkedVectorBase::MarkedVectorBase(Heap& heap) : m_heap(&heap) diff --git a/Libraries/LibJS/Heap/MarkedVector.h b/Libraries/LibGC/MarkedVector.h similarity index 84% rename from Libraries/LibJS/Heap/MarkedVector.h rename to Libraries/LibGC/MarkedVector.h index 4be1bdeafe3..b1e191a28a1 100644 --- a/Libraries/LibJS/Heap/MarkedVector.h +++ b/Libraries/LibGC/MarkedVector.h @@ -10,15 +10,15 @@ #include #include #include -#include -#include -#include +#include +#include +#include -namespace JS { +namespace GC { class MarkedVectorBase { public: - virtual void gather_roots(HashMap&) const = 0; + virtual void gather_roots(HashMap&) const = 0; protected: explicit MarkedVectorBase(Heap&); @@ -65,10 +65,10 @@ public: return *this; } - virtual void gather_roots(HashMap& roots) const override + virtual void gather_roots(HashMap& roots) const override { for (auto& value : *this) { - if constexpr (IsSame) { + if constexpr (IsBaseOf) { if (value.is_cell()) roots.set(&const_cast(value).as_cell(), HeapRoot { .type = HeapRoot::Type::MarkedVector }); } else { diff --git a/Libraries/LibJS/Heap/NanBoxedValue.h b/Libraries/LibGC/NanBoxedValue.h similarity index 96% rename from Libraries/LibJS/Heap/NanBoxedValue.h rename to Libraries/LibGC/NanBoxedValue.h index 3bf95351158..989a87efbda 100644 --- a/Libraries/LibJS/Heap/NanBoxedValue.h +++ b/Libraries/LibGC/NanBoxedValue.h @@ -8,8 +8,9 @@ #include #include +#include -namespace JS { +namespace GC { static_assert(sizeof(double) == 8); static_assert(sizeof(void*) == sizeof(double) || sizeof(void*) == sizeof(u32)); @@ -72,7 +73,7 @@ public: // For AArch64 the top 16 bits of the pointer should be zero. // For PPC64: all 64 bits can be used for pointers, however on Linux only // the lower 43 bits are used for user-space addresses, so - // masking off the top 16 bits should match the rest of LibJS. + // masking off the top 16 bits should match the rest of LibGC. return static_cast(encoded & 0xffff'ffff'ffffULL); #else # error "Unknown architecture. Don't know whether pointers need to be sign-extended." @@ -86,16 +87,16 @@ public: return reinterpret_cast(extract_pointer_bits(m_value.encoded)); } - CellImpl& as_cell() + Cell& as_cell() { VERIFY(is_cell()); - return *extract_pointer(); + return *extract_pointer(); } - CellImpl& as_cell() const + Cell& as_cell() const { VERIFY(is_cell()); - return *extract_pointer(); + return *extract_pointer(); } bool is_nan() const diff --git a/Libraries/LibJS/Heap/GCPtr.h b/Libraries/LibGC/Ptr.h similarity index 68% rename from Libraries/LibJS/Heap/GCPtr.h rename to Libraries/LibGC/Ptr.h index ebe8753f096..fcbbb4b7586 100644 --- a/Libraries/LibJS/Heap/GCPtr.h +++ b/Libraries/LibGC/Ptr.h @@ -9,51 +9,51 @@ #include #include -namespace JS { +namespace GC { template -class GCPtr; +class Ptr; template -class NonnullGCPtr { +class Ref { public: - NonnullGCPtr() = delete; + Ref() = delete; - NonnullGCPtr(T& ptr) + Ref(T& ptr) : m_ptr(&ptr) { } template - NonnullGCPtr(U& ptr) + Ref(U& ptr) requires(IsConvertible) : m_ptr(&static_cast(ptr)) { } template - NonnullGCPtr(NonnullGCPtr const& other) + Ref(Ref const& other) requires(IsConvertible) : m_ptr(other.ptr()) { } template - NonnullGCPtr& operator=(NonnullGCPtr const& other) + Ref& operator=(Ref const& other) requires(IsConvertible) { m_ptr = static_cast(other.ptr()); return *this; } - NonnullGCPtr& operator=(T& other) + Ref& operator=(T& other) { m_ptr = &other; return *this; } template - NonnullGCPtr& operator=(U& other) + Ref& operator=(U& other) requires(IsConvertible) { m_ptr = &static_cast(other); @@ -75,88 +75,88 @@ private: }; template -class GCPtr { +class Ptr { public: - constexpr GCPtr() = default; + constexpr Ptr() = default; - GCPtr(T& ptr) + Ptr(T& ptr) : m_ptr(&ptr) { } - GCPtr(T* ptr) + Ptr(T* ptr) : m_ptr(ptr) { } template - GCPtr(GCPtr const& other) + Ptr(Ptr const& other) requires(IsConvertible) : m_ptr(other.ptr()) { } - GCPtr(NonnullGCPtr const& other) + Ptr(Ref const& other) : m_ptr(other.ptr()) { } template - GCPtr(NonnullGCPtr const& other) + Ptr(Ref const& other) requires(IsConvertible) : m_ptr(other.ptr()) { } - GCPtr(nullptr_t) + Ptr(nullptr_t) : m_ptr(nullptr) { } template - GCPtr& operator=(GCPtr const& other) + Ptr& operator=(Ptr const& other) requires(IsConvertible) { m_ptr = static_cast(other.ptr()); return *this; } - GCPtr& operator=(NonnullGCPtr const& other) + Ptr& operator=(Ref const& other) { m_ptr = other.ptr(); return *this; } template - GCPtr& operator=(NonnullGCPtr const& other) + Ptr& operator=(Ref const& other) requires(IsConvertible) { m_ptr = static_cast(other.ptr()); return *this; } - GCPtr& operator=(T& other) + Ptr& operator=(T& other) { m_ptr = &other; return *this; } template - GCPtr& operator=(U& other) + Ptr& operator=(U& other) requires(IsConvertible) { m_ptr = &static_cast(other); return *this; } - GCPtr& operator=(T* other) + Ptr& operator=(T* other) { m_ptr = other; return *this; } template - GCPtr& operator=(U* other) + Ptr& operator=(U* other) requires(IsConvertible) { m_ptr = static_cast(other); @@ -186,34 +186,34 @@ private: T* m_ptr { nullptr }; }; -// Non-Owning GCPtr +// Non-Owning GC::Ptr template -using RawGCPtr = GCPtr; +using RawPtr = Ptr; -// Non-Owning NonnullGCPtr +// Non-Owning Ref template -using RawNonnullGCPtr = NonnullGCPtr; +using RawRef = Ref; template -inline bool operator==(GCPtr const& a, GCPtr const& b) +inline bool operator==(Ptr const& a, Ptr const& b) { return a.ptr() == b.ptr(); } template -inline bool operator==(GCPtr const& a, NonnullGCPtr const& b) +inline bool operator==(Ptr const& a, Ref const& b) { return a.ptr() == b.ptr(); } template -inline bool operator==(NonnullGCPtr const& a, NonnullGCPtr const& b) +inline bool operator==(Ref const& a, Ref const& b) { return a.ptr() == b.ptr(); } template -inline bool operator==(NonnullGCPtr const& a, GCPtr const& b) +inline bool operator==(Ref const& a, Ptr const& b) { return a.ptr() == b.ptr(); } @@ -223,16 +223,16 @@ inline bool operator==(NonnullGCPtr const& a, GCPtr const& b) namespace AK { template -struct Traits> : public DefaultTraits> { - static unsigned hash(JS::GCPtr const& value) +struct Traits> : public DefaultTraits> { + static unsigned hash(GC::Ptr const& value) { return Traits::hash(value.ptr()); } }; template -struct Traits> : public DefaultTraits> { - static unsigned hash(JS::NonnullGCPtr const& value) +struct Traits> : public DefaultTraits> { + static unsigned hash(GC::Ref const& value) { return Traits::hash(value.ptr()); } diff --git a/Libraries/LibGC/Root.cpp b/Libraries/LibGC/Root.cpp new file mode 100644 index 00000000000..48890e80edb --- /dev/null +++ b/Libraries/LibGC/Root.cpp @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2020, Andreas Kling + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include +#include +#include + +namespace GC { + +RootImpl::RootImpl(Cell* cell, SourceLocation location) + : m_cell(cell) + , m_location(location) +{ + m_cell->heap().did_create_root({}, *this); +} + +RootImpl::~RootImpl() +{ + m_cell->heap().did_destroy_root({}, *this); +} + +} diff --git a/Libraries/LibGC/Root.h b/Libraries/LibGC/Root.h new file mode 100644 index 00000000000..e814ffe2910 --- /dev/null +++ b/Libraries/LibGC/Root.h @@ -0,0 +1,169 @@ +/* + * Copyright (c) 2020, Andreas Kling + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#pragma once + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace GC { + +class RootImpl : public RefCounted { + AK_MAKE_NONCOPYABLE(RootImpl); + AK_MAKE_NONMOVABLE(RootImpl); + +public: + ~RootImpl(); + + Cell* cell() { return m_cell; } + Cell const* cell() const { return m_cell; } + + SourceLocation const& source_location() const { return m_location; } + +private: + template + friend class Root; + + explicit RootImpl(Cell*, SourceLocation location); + Ptr m_cell; + SourceLocation m_location; + + IntrusiveListNode m_list_node; + +public: + using List = IntrusiveList<&RootImpl::m_list_node>; +}; + +template +class Root { +public: + Root() = default; + + static Root create(T* cell, SourceLocation location = SourceLocation::current()) + { + return Root(adopt_ref(*new RootImpl(const_cast*>(cell), location))); + } + + Root(T* cell, SourceLocation location = SourceLocation::current()) + { + if (cell) + m_impl = adopt_ref(*new RootImpl(cell, location)); + } + + Root(T& cell, SourceLocation location = SourceLocation::current()) + : m_impl(adopt_ref(*new RootImpl(&cell, location))) + { + } + + Root(Ptr cell, SourceLocation location = SourceLocation::current()) + : Root(cell.ptr(), location) + { + } + + Root(Ref cell, SourceLocation location = SourceLocation::current()) + : Root(*cell, location) + { + } + + T* cell() const + { + if (!m_impl) + return nullptr; + return static_cast(m_impl->cell()); + } + + T* ptr() const + { + return cell(); + } + + bool is_null() const + { + return m_impl.is_null(); + } + + T* operator->() const + { + return cell(); + } + + [[nodiscard]] T& operator*() const + { + return *cell(); + } + + bool operator!() const + { + return !cell(); + } + operator bool() const + { + return cell(); + } + + operator T*() const { return cell(); } + +private: + explicit Root(NonnullRefPtr impl) + : m_impl(move(impl)) + { + } + + RefPtr m_impl; +}; + +template +inline Root make_root(T* cell, SourceLocation location = SourceLocation::current()) +{ + if (!cell) + return Root {}; + return Root::create(cell, location); +} + +template +inline Root make_root(T& cell, SourceLocation location = SourceLocation::current()) +{ + return Root::create(&cell, location); +} + +template +inline Root make_root(Ptr cell, SourceLocation location = SourceLocation::current()) +{ + if (!cell) + return Root {}; + return Root::create(cell.ptr(), location); +} + +template +inline Root make_root(Ref cell, SourceLocation location = SourceLocation::current()) +{ + return Root::create(cell.ptr(), location); +} + +} + +namespace AK { + +template +struct Traits> : public DefaultTraits> { + static unsigned hash(GC::Root const& handle) { return Traits::hash(handle); } +}; + +namespace Detail { +template +inline constexpr bool IsHashCompatible, T> = true; + +template +inline constexpr bool IsHashCompatible> = true; + +} +} diff --git a/Libraries/LibJS/Heap/WeakContainer.cpp b/Libraries/LibGC/WeakContainer.cpp similarity index 84% rename from Libraries/LibJS/Heap/WeakContainer.cpp rename to Libraries/LibGC/WeakContainer.cpp index b84cdf39713..86f74ba8fe1 100644 --- a/Libraries/LibJS/Heap/WeakContainer.cpp +++ b/Libraries/LibGC/WeakContainer.cpp @@ -4,10 +4,10 @@ * SPDX-License-Identifier: BSD-2-Clause */ -#include -#include +#include +#include -namespace JS { +namespace GC { WeakContainer::WeakContainer(Heap& heap) : m_heap(heap) diff --git a/Libraries/LibJS/Heap/WeakContainer.h b/Libraries/LibGC/WeakContainer.h similarity index 92% rename from Libraries/LibJS/Heap/WeakContainer.h rename to Libraries/LibGC/WeakContainer.h index 81169984dc9..e2b47d50ec2 100644 --- a/Libraries/LibJS/Heap/WeakContainer.h +++ b/Libraries/LibGC/WeakContainer.h @@ -7,9 +7,9 @@ #pragma once #include -#include +#include -namespace JS { +namespace GC { class WeakContainer { public: diff --git a/Libraries/LibJS/AST.cpp b/Libraries/LibJS/AST.cpp index 9ed24d38bc4..6764b1ac872 100644 --- a/Libraries/LibJS/AST.cpp +++ b/Libraries/LibJS/AST.cpp @@ -14,9 +14,9 @@ #include #include #include +#include +#include #include -#include -#include #include #include #include @@ -97,7 +97,7 @@ Value FunctionExpression::instantiate_ordinary_function_expression(VM& vm, Depre auto has_own_name = !name().is_empty(); auto const used_name = has_own_name ? name() : given_name.view(); - auto environment = NonnullGCPtr { *vm.running_execution_context().lexical_environment }; + auto environment = GC::Ref { *vm.running_execution_context().lexical_environment }; if (has_own_name) { VERIFY(environment); environment = new_declarative_environment(*environment); @@ -227,7 +227,7 @@ ThrowCompletionOr ClassField::class_element_evaluation auto& realm = *vm.current_realm(); auto property_key_or_private_name = TRY(class_key_to_property_name(vm, *m_key, property_key)); - GCPtr initializer; + GC::Ptr initializer; if (m_initializer) { auto copy_initializer = m_initializer; auto name = property_key_or_private_name.visit( @@ -310,7 +310,7 @@ ThrowCompletionOr ClassExpression::create_class_const vm.running_execution_context().lexical_environment = class_environment; - auto proto_parent = GCPtr { realm.intrinsics().object_prototype() }; + auto proto_parent = GC::Ptr { realm.intrinsics().object_prototype() }; auto constructor_parent = realm.intrinsics().function_prototype(); if (!m_super_class.is_null()) { @@ -366,12 +366,12 @@ ThrowCompletionOr ClassExpression::create_class_const prototype->define_direct_property(vm.names.constructor, class_constructor, Attribute::Writable | Attribute::Configurable); - using StaticElement = Variant>; + using StaticElement = Variant>; - ConservativeVector static_private_methods(vm.heap()); - ConservativeVector instance_private_methods(vm.heap()); - ConservativeVector instance_fields(vm.heap()); - ConservativeVector static_elements(vm.heap()); + GC::ConservativeVector static_private_methods(vm.heap()); + GC::ConservativeVector instance_private_methods(vm.heap()); + GC::ConservativeVector instance_fields(vm.heap()); + GC::ConservativeVector static_elements(vm.heap()); for (size_t element_index = 0; element_index < m_elements.size(); element_index++) { auto const& element = m_elements[element_index]; @@ -411,7 +411,7 @@ ThrowCompletionOr ClassExpression::create_class_const VERIFY(element_value.has() && element_value.get().value().has_value()); auto& element_object = element_value.get().value()->as_object(); VERIFY(is(element_object)); - static_elements.append(NonnullGCPtr { static_cast(element_object) }); + static_elements.append(GC::Ref { static_cast(element_object) }); } } @@ -435,7 +435,7 @@ ThrowCompletionOr ClassExpression::create_class_const [&](ClassFieldDefinition& field) -> ThrowCompletionOr { return TRY(class_constructor->define_field(field)); }, - [&](Handle static_block_function) -> ThrowCompletionOr { + [&](GC::Root static_block_function) -> ThrowCompletionOr { VERIFY(!static_block_function.is_null()); // We discard any value returned here. TRY(call(vm, *static_block_function.cell(), class_constructor)); diff --git a/Libraries/LibJS/AST.h b/Libraries/LibJS/AST.h index 3c59145c922..dec69d2ec59 100644 --- a/Libraries/LibJS/AST.h +++ b/Libraries/LibJS/AST.h @@ -15,6 +15,7 @@ #include #include #include +#include #include #include #include @@ -22,7 +23,6 @@ #include #include #include -#include #include #include #include @@ -160,10 +160,10 @@ public: } Bytecode::Executable* bytecode_executable() const { return m_bytecode_executable; } - void set_bytecode_executable(Bytecode::Executable* bytecode_executable) { m_bytecode_executable = make_handle(bytecode_executable); } + void set_bytecode_executable(Bytecode::Executable* bytecode_executable) { m_bytecode_executable = make_root(bytecode_executable); } private: - Handle m_bytecode_executable; + GC::Root m_bytecode_executable; }; // 14.13 Labelled Statements, https://tc39.es/ecma262/#sec-labelled-statements @@ -690,7 +690,7 @@ struct FunctionParameter { Variant, NonnullRefPtr> binding; RefPtr default_value; bool is_rest { false }; - Handle bytecode_executable {}; + GC::Root bytecode_executable {}; }; struct FunctionParsingInsights { diff --git a/Libraries/LibJS/Bytecode/BasicBlock.h b/Libraries/LibJS/Bytecode/BasicBlock.h index d28f112aaa7..d9e0ff4bf87 100644 --- a/Libraries/LibJS/Bytecode/BasicBlock.h +++ b/Libraries/LibJS/Bytecode/BasicBlock.h @@ -8,16 +8,16 @@ #include #include +#include #include #include #include -#include namespace JS::Bytecode { struct UnwindInfo { - JS::GCPtr executable; - JS::GCPtr lexical_environment; + GC::Ptr executable; + GC::Ptr lexical_environment; bool handler_called { false }; }; diff --git a/Libraries/LibJS/Bytecode/Executable.cpp b/Libraries/LibJS/Bytecode/Executable.cpp index 959a5ffe240..e012256418f 100644 --- a/Libraries/LibJS/Bytecode/Executable.cpp +++ b/Libraries/LibJS/Bytecode/Executable.cpp @@ -13,7 +13,7 @@ namespace JS::Bytecode { -JS_DEFINE_ALLOCATOR(Executable); +GC_DEFINE_ALLOCATOR(Executable); Executable::Executable( Vector bytecode, diff --git a/Libraries/LibJS/Bytecode/Executable.h b/Libraries/LibJS/Bytecode/Executable.h index 7eb1b168bc4..499506809d8 100644 --- a/Libraries/LibJS/Bytecode/Executable.h +++ b/Libraries/LibJS/Bytecode/Executable.h @@ -11,12 +11,12 @@ #include #include #include +#include #include #include #include #include #include -#include #include #include @@ -40,8 +40,8 @@ struct SourceRecord { }; class Executable final : public Cell { - JS_CELL(Executable, Cell); - JS_DECLARE_ALLOCATOR(Executable); + GC_CELL(Executable, Cell); + GC_DECLARE_ALLOCATOR(Executable); public: Executable( diff --git a/Libraries/LibJS/Bytecode/Generator.cpp b/Libraries/LibJS/Bytecode/Generator.cpp index 7ae318c1e1d..f4c99673a1c 100644 --- a/Libraries/LibJS/Bytecode/Generator.cpp +++ b/Libraries/LibJS/Bytecode/Generator.cpp @@ -17,7 +17,7 @@ namespace JS::Bytecode { -Generator::Generator(VM& vm, GCPtr function, MustPropagateCompletion must_propagate_completion) +Generator::Generator(VM& vm, GC::Ptr function, MustPropagateCompletion must_propagate_completion) : m_vm(vm) , m_string_table(make()) , m_identifier_table(make()) @@ -199,7 +199,7 @@ CodeGenerationErrorOr Generator::emit_function_declaration_instantiation(E return {}; } -CodeGenerationErrorOr> Generator::compile(VM& vm, ASTNode const& node, FunctionKind enclosing_function_kind, GCPtr function, MustPropagateCompletion must_propagate_completion, Vector local_variable_names) +CodeGenerationErrorOr> Generator::compile(VM& vm, ASTNode const& node, FunctionKind enclosing_function_kind, GC::Ptr function, MustPropagateCompletion must_propagate_completion, Vector local_variable_names) { Generator generator(vm, function, must_propagate_completion); @@ -460,7 +460,7 @@ CodeGenerationErrorOr> Generator::compile(VM& vm, ASTNo return executable; } -CodeGenerationErrorOr> Generator::generate_from_ast_node(VM& vm, ASTNode const& node, FunctionKind enclosing_function_kind) +CodeGenerationErrorOr> Generator::generate_from_ast_node(VM& vm, ASTNode const& node, FunctionKind enclosing_function_kind) { Vector local_variable_names; if (is(node)) @@ -468,7 +468,7 @@ CodeGenerationErrorOr> Generator::generate_from_ast_nod return compile(vm, node, enclosing_function_kind, {}, MustPropagateCompletion::Yes, move(local_variable_names)); } -CodeGenerationErrorOr> Generator::generate_from_function(VM& vm, ECMAScriptFunctionObject const& function) +CodeGenerationErrorOr> Generator::generate_from_function(VM& vm, ECMAScriptFunctionObject const& function) { return compile(vm, function.ecmascript_code(), function.kind(), &function, MustPropagateCompletion::No, function.local_variables_names()); } diff --git a/Libraries/LibJS/Bytecode/Generator.h b/Libraries/LibJS/Bytecode/Generator.h index c934a42d364..bb496898914 100644 --- a/Libraries/LibJS/Bytecode/Generator.h +++ b/Libraries/LibJS/Bytecode/Generator.h @@ -38,8 +38,8 @@ public: Yes, }; - static CodeGenerationErrorOr> generate_from_ast_node(VM&, ASTNode const&, FunctionKind = FunctionKind::Normal); - static CodeGenerationErrorOr> generate_from_function(VM&, ECMAScriptFunctionObject const& function); + static CodeGenerationErrorOr> generate_from_ast_node(VM&, ASTNode const&, FunctionKind = FunctionKind::Normal); + static CodeGenerationErrorOr> generate_from_function(VM&, ECMAScriptFunctionObject const& function); CodeGenerationErrorOr emit_function_declaration_instantiation(ECMAScriptFunctionObject const& function); @@ -343,7 +343,7 @@ public: private: VM& m_vm; - static CodeGenerationErrorOr> compile(VM&, ASTNode const&, FunctionKind, GCPtr, MustPropagateCompletion, Vector local_variable_names); + static CodeGenerationErrorOr> compile(VM&, ASTNode const&, FunctionKind, GC::Ptr, MustPropagateCompletion, Vector local_variable_names); enum class JumpType { Continue, @@ -352,7 +352,7 @@ private: void generate_scoped_jump(JumpType); void generate_labelled_jump(JumpType, DeprecatedFlyString const& label); - Generator(VM&, GCPtr, MustPropagateCompletion); + Generator(VM&, GC::Ptr, MustPropagateCompletion); ~Generator() = default; void grow(size_t); @@ -373,7 +373,7 @@ private: NonnullOwnPtr m_string_table; NonnullOwnPtr m_identifier_table; NonnullOwnPtr m_regex_table; - MarkedVector m_constants; + GC::MarkedVector m_constants; mutable Optional m_true_constant; mutable Optional m_false_constant; @@ -401,7 +401,7 @@ private: bool m_finished { false }; bool m_must_propagate_completion { true }; - GCPtr m_function; + GC::Ptr m_function; Optional m_length_identifier; }; diff --git a/Libraries/LibJS/Bytecode/Instruction.h b/Libraries/LibJS/Bytecode/Instruction.h index 26a55d75247..2a557064d1f 100644 --- a/Libraries/LibJS/Bytecode/Instruction.h +++ b/Libraries/LibJS/Bytecode/Instruction.h @@ -213,7 +213,7 @@ private: u8 const* m_begin { nullptr }; u8 const* m_end { nullptr }; u8 const* m_ptr { nullptr }; - GCPtr m_executable; + GC::Ptr m_executable; }; } diff --git a/Libraries/LibJS/Bytecode/Interpreter.cpp b/Libraries/LibJS/Bytecode/Interpreter.cpp index ff3d2304f5e..b93a73dd387 100644 --- a/Libraries/LibJS/Bytecode/Interpreter.cpp +++ b/Libraries/LibJS/Bytecode/Interpreter.cpp @@ -182,7 +182,7 @@ ALWAYS_INLINE Value Interpreter::do_yield(Value value, Optional