LibGC+Everywhere: Factor out a LibGC from LibJS

Resulting in a massive rename across almost everywhere! Alongside the
namespace change, we now have the following names:

 * JS::NonnullGCPtr -> GC::Ref
 * JS::GCPtr -> GC::Ptr
 * JS::HeapFunction -> GC::Function
 * JS::CellImpl -> GC::Cell
 * JS::Handle -> GC::Root
This commit is contained in:
Shannon Booth 2024-11-15 04:01:23 +13:00 committed by Andreas Kling
parent ce23efc5f6
commit f87041bf3a
Notes: github-actions[bot] 2024-11-15 13:50:17 +00:00
1722 changed files with 9939 additions and 9906 deletions

View file

@ -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: variant of supported errors:
- `SimpleException` - `SimpleException`
- `JS::NonnullGCPtr<DOMException>` - `GC::Ref<DOMException>`
- `JS::Completion` (from `JS::ThrowCompletionOr<T>`, assumed to be of `Type::Throw`) - `JS::Completion` (from `JS::ThrowCompletionOr<T>`, assumed to be of `Type::Throw`)
Use this error type for anything that needs to interact with the JS bindings, which will generally Use this error type for anything that needs to interact with the JS bindings, which will generally
@ -86,7 +86,7 @@ must have:
```cpp ```cpp
// https://fetch.spec.whatwg.org/#concept-fetch // https://fetch.spec.whatwg.org/#concept-fetch
WebIDL::ExceptionOr<JS::NonnullGCPtr<Infrastructure::FetchController>> fetch(JS::Realm& realm, Infrastructure::Request& request, Infrastructure::FetchAlgorithms const& algorithms, UseParallelQueue use_parallel_queue) WebIDL::ExceptionOr<GC::Ref<Infrastructure::FetchController>> 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()); VERIFY(request.mode() == Infrastructure::Request::Mode::Navigate || !algorithms.process_early_hints_response().has_value());
// 2. Let taskDestination be null. // 2. Let taskDestination be null.
JS::GCPtr<JS::Object> task_destination; GC::Ptr<JS::Object> task_destination;
// ... // ...
``` ```

View file

@ -7,8 +7,8 @@
#include <AK/Platform.h> #include <AK/Platform.h>
#include <AK/Random.h> #include <AK/Random.h>
#include <AK/Vector.h> #include <AK/Vector.h>
#include <LibJS/Heap/BlockAllocator.h> #include <LibGC/BlockAllocator.h>
#include <LibJS/Heap/HeapBlock.h> #include <LibGC/HeapBlock.h>
#include <sys/mman.h> #include <sys/mman.h>
#ifdef HAS_ADDRESS_SANITIZER #ifdef HAS_ADDRESS_SANITIZER
@ -20,7 +20,7 @@
# define USE_FALLBACK_BLOCK_DEALLOCATION # define USE_FALLBACK_BLOCK_DEALLOCATION
#endif #endif
namespace JS { namespace GC {
BlockAllocator::~BlockAllocator() BlockAllocator::~BlockAllocator()
{ {

View file

@ -7,9 +7,9 @@
#pragma once #pragma once
#include <AK/Vector.h> #include <AK/Vector.h>
#include <LibJS/Forward.h> #include <LibGC/Forward.h>
namespace JS { namespace GC {
class BlockAllocator { class BlockAllocator {
public: public:

View file

@ -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)

View file

@ -4,12 +4,12 @@
* SPDX-License-Identifier: BSD-2-Clause * SPDX-License-Identifier: BSD-2-Clause
*/ */
#include <LibJS/Heap/CellImpl.h> #include <LibGC/Cell.h>
#include <LibJS/Heap/NanBoxedValue.h> #include <LibGC/NanBoxedValue.h>
namespace JS { namespace GC {
void JS::CellImpl::Visitor::visit(NanBoxedValue const& value) void GC::Cell::Visitor::visit(NanBoxedValue const& value)
{ {
if (value.is_cell()) if (value.is_cell())
visit_impl(value.as_cell()); visit_impl(value.as_cell());

View file

@ -13,11 +13,11 @@
#include <AK/Noncopyable.h> #include <AK/Noncopyable.h>
#include <AK/StringView.h> #include <AK/StringView.h>
#include <AK/Weakable.h> #include <AK/Weakable.h>
#include <LibJS/Forward.h> #include <LibGC/Forward.h>
#include <LibJS/Heap/GCPtr.h> #include <LibGC/Internals.h>
#include <LibJS/Heap/Internals.h> #include <LibGC/Ptr.h>
namespace JS { namespace GC {
// This instrumentation tells analysis tooling to ignore a potentially mis-wrapped GC-allocated member variable // 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 // 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 # define IGNORE_GC
#endif #endif
#define JS_CELL(class_, base_class) \ #define GC_CELL(class_, base_class) \
public: \ public: \
using Base = base_class; \ using Base = base_class; \
virtual StringView class_name() const override \ virtual StringView class_name() const override \
{ \ { \
return #class_##sv; \ return #class_##sv; \
} \ } \
friend class JS::Heap; friend class GC::Heap;
class CellImpl : public Weakable<CellImpl> { class Cell : public Weakable<Cell> {
AK_MAKE_NONCOPYABLE(CellImpl); AK_MAKE_NONCOPYABLE(Cell);
AK_MAKE_NONMOVABLE(CellImpl); AK_MAKE_NONMOVABLE(Cell);
public: public:
virtual ~CellImpl() = default; virtual ~Cell() = default;
bool is_marked() const { return m_mark; } bool is_marked() const { return m_mark; }
void set_marked(bool b) { m_mark = b; } void set_marked(bool b) { m_mark = b; }
@ -58,36 +58,36 @@ public:
class Visitor { class Visitor {
public: public:
void visit(CellImpl* cell) void visit(Cell* cell)
{ {
if (cell) if (cell)
visit_impl(*cell); visit_impl(*cell);
} }
void visit(CellImpl& cell) void visit(Cell& cell)
{ {
visit_impl(cell); visit_impl(cell);
} }
void visit(CellImpl const* cell) void visit(Cell const* cell)
{ {
visit(const_cast<CellImpl*>(cell)); visit(const_cast<Cell*>(cell));
} }
void visit(CellImpl const& cell) void visit(Cell const& cell)
{ {
visit(const_cast<CellImpl&>(cell)); visit(const_cast<Cell&>(cell));
} }
template<typename T> template<typename T>
void visit(GCPtr<T> cell) void visit(Ptr<T> cell)
{ {
if (cell) if (cell)
visit_impl(const_cast<RemoveConst<T>&>(*cell.ptr())); visit_impl(const_cast<RemoveConst<T>&>(*cell.ptr()));
} }
template<typename T> template<typename T>
void visit(NonnullGCPtr<T> cell) void visit(Ref<T> cell)
{ {
visit_impl(const_cast<RemoveConst<T>&>(*cell.ptr())); visit_impl(const_cast<RemoveConst<T>&>(*cell.ptr()));
} }
@ -161,7 +161,7 @@ public:
virtual void visit_possible_values(ReadonlyBytes) = 0; virtual void visit_possible_values(ReadonlyBytes) = 0;
protected: protected:
virtual void visit_impl(CellImpl&) = 0; virtual void visit_impl(Cell&) = 0;
virtual ~Visitor() = default; virtual ~Visitor() = default;
}; };
@ -180,7 +180,7 @@ public:
ALWAYS_INLINE Heap& heap() const { return HeapBlockBase::from_cell(this)->heap(); } ALWAYS_INLINE Heap& heap() const { return HeapBlockBase::from_cell(this)->heap(); }
protected: protected:
CellImpl() = default; Cell() = default;
ALWAYS_INLINE void* private_data() const { return bit_cast<HeapBase*>(&heap())->private_data(); } ALWAYS_INLINE void* private_data() const { return bit_cast<HeapBase*>(&heap())->private_data(); }
@ -195,8 +195,8 @@ private:
} }
template<> template<>
struct AK::Formatter<JS::CellImpl> : AK::Formatter<FormatString> { struct AK::Formatter<GC::Cell> : AK::Formatter<FormatString> {
ErrorOr<void> format(FormatBuilder& builder, JS::CellImpl const* cell) ErrorOr<void> format(FormatBuilder& builder, GC::Cell const* cell)
{ {
if (!cell) if (!cell)
return builder.put_string("Cell{nullptr}"sv); return builder.put_string("Cell{nullptr}"sv);

View file

@ -5,12 +5,12 @@
*/ */
#include <AK/Badge.h> #include <AK/Badge.h>
#include <LibJS/Heap/BlockAllocator.h> #include <LibGC/BlockAllocator.h>
#include <LibJS/Heap/CellAllocator.h> #include <LibGC/CellAllocator.h>
#include <LibJS/Heap/Heap.h> #include <LibGC/Heap.h>
#include <LibJS/Heap/HeapBlock.h> #include <LibGC/HeapBlock.h>
namespace JS { namespace GC {
CellAllocator::CellAllocator(size_t cell_size, char const* class_name) CellAllocator::CellAllocator(size_t cell_size, char const* class_name)
: m_class_name(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()) if (!m_list_node.is_in_list())
heap.register_cell_allocator({}, *this); heap.register_cell_allocator({}, *this);

View file

@ -9,17 +9,17 @@
#include <AK/IntrusiveList.h> #include <AK/IntrusiveList.h>
#include <AK/NeverDestroyed.h> #include <AK/NeverDestroyed.h>
#include <AK/NonnullOwnPtr.h> #include <AK/NonnullOwnPtr.h>
#include <LibJS/Forward.h> #include <LibGC/BlockAllocator.h>
#include <LibJS/Heap/BlockAllocator.h> #include <LibGC/Forward.h>
#include <LibJS/Heap/HeapBlock.h> #include <LibGC/HeapBlock.h>
#define JS_DECLARE_ALLOCATOR(ClassName) \ #define GC_DECLARE_ALLOCATOR(ClassName) \
static JS::TypeIsolatingCellAllocator<ClassName> cell_allocator static GC::TypeIsolatingCellAllocator<ClassName> cell_allocator
#define JS_DEFINE_ALLOCATOR(ClassName) \ #define GC_DEFINE_ALLOCATOR(ClassName) \
JS::TypeIsolatingCellAllocator<ClassName> ClassName::cell_allocator { #ClassName } GC::TypeIsolatingCellAllocator<ClassName> ClassName::cell_allocator { #ClassName }
namespace JS { namespace GC {
class CellAllocator { class CellAllocator {
public: public:
@ -28,7 +28,7 @@ public:
size_t cell_size() const { return m_cell_size; } size_t cell_size() const { return m_cell_size; }
CellImpl* allocate_cell(Heap&); Cell* allocate_cell(Heap&);
template<typename Callback> template<typename Callback>
IterationDecision for_each_block(Callback callback) IterationDecision for_each_block(Callback callback)

View file

@ -4,10 +4,10 @@
* SPDX-License-Identifier: BSD-2-Clause * SPDX-License-Identifier: BSD-2-Clause
*/ */
#include <LibJS/Heap/ConservativeVector.h> #include <LibGC/ConservativeVector.h>
#include <LibJS/Heap/Heap.h> #include <LibGC/Heap.h>
namespace JS { namespace GC {
ConservativeVectorBase::ConservativeVectorBase(Heap& heap) ConservativeVectorBase::ConservativeVectorBase(Heap& heap)
: m_heap(&heap) : m_heap(&heap)

View file

@ -9,11 +9,11 @@
#include <AK/HashMap.h> #include <AK/HashMap.h>
#include <AK/IntrusiveList.h> #include <AK/IntrusiveList.h>
#include <AK/Vector.h> #include <AK/Vector.h>
#include <LibJS/Forward.h> #include <LibGC/Cell.h>
#include <LibJS/Heap/CellImpl.h> #include <LibGC/Forward.h>
#include <LibJS/Heap/HeapRoot.h> #include <LibGC/HeapRoot.h>
namespace JS { namespace GC {
class ConservativeVectorBase { class ConservativeVectorBase {
public: public:

View file

@ -6,9 +6,9 @@
#pragma once #pragma once
#include <LibJS/Heap/Heap.h> #include <LibGC/Heap.h>
namespace JS { namespace GC {
class DeferGC { class DeferGC {
public: public:

32
Libraries/LibGC/Forward.h Normal file
View file

@ -0,0 +1,32 @@
/*
* Copyright (c) 2024, Shannon Booth <shannon@serenityos.org>
*
* 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<typename T>
class Function;
template<class T>
class Root;
template<class T, size_t inline_capacity = 0>
class ConservativeVector;
template<class T, size_t inline_capacity = 0>
class MarkedVector;
}

View file

@ -0,0 +1,50 @@
/*
* Copyright (c) 2023, Andreas Kling <andreas@ladybird.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#pragma once
#include <AK/Function.h>
#include <LibGC/Cell.h>
#include <LibGC/Heap.h>
namespace GC {
template<typename T>
class Function final : public Cell {
GC_CELL(Function, Cell);
public:
static Ref<Function> create(Heap& heap, AK::Function<T> function)
{
return heap.allocate<Function>(move(function));
}
virtual ~Function() override = default;
[[nodiscard]] AK::Function<T> const& function() const { return m_function; }
private:
Function(AK::Function<T> 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<T> m_function;
};
template<typename Callable, typename T = EquivalentFunctionType<Callable>>
static Ref<Function<T>> create_function(Heap& heap, Callable&& function)
{
return Function<T>::create(heap, AK::Function<T> { forward<Callable>(function) });
}
}

View file

@ -15,20 +15,20 @@
#include <AK/StackInfo.h> #include <AK/StackInfo.h>
#include <AK/TemporaryChange.h> #include <AK/TemporaryChange.h>
#include <LibCore/ElapsedTimer.h> #include <LibCore/ElapsedTimer.h>
#include <LibJS/Heap/CellAllocator.h> #include <LibGC/CellAllocator.h>
#include <LibJS/Heap/Handle.h> #include <LibGC/Heap.h>
#include <LibJS/Heap/Heap.h> #include <LibGC/HeapBlock.h>
#include <LibJS/Heap/HeapBlock.h> #include <LibGC/NanBoxedValue.h>
#include <LibJS/Heap/NanBoxedValue.h> #include <LibGC/Root.h>
#include <setjmp.h> #include <setjmp.h>
#ifdef HAS_ADDRESS_SANITIZER #ifdef HAS_ADDRESS_SANITIZER
# include <sanitizer/asan_interface.h> # include <sanitizer/asan_interface.h>
#endif #endif
namespace JS { namespace GC {
Heap::Heap(void* private_data, Function<void(HashMap<CellImpl*, JS::HeapRoot>&)> gather_embedder_roots) Heap::Heap(void* private_data, AK::Function<void(HashMap<Cell*, GC::HeapRoot>&)> gather_embedder_roots)
: HeapBase(private_data) : HeapBase(private_data)
, m_gather_embedder_roots(move(gather_embedder_roots)) , m_gather_embedder_roots(move(gather_embedder_roots))
{ {
@ -100,7 +100,7 @@ static void for_each_cell_among_possible_pointers(HashTable<HeapBlock*> const& a
for (auto possible_pointer : possible_pointers.keys()) { for (auto possible_pointer : possible_pointers.keys()) {
if (!possible_pointer) if (!possible_pointer)
continue; continue;
auto* possible_heap_block = HeapBlock::from_cell(reinterpret_cast<CellImpl const*>(possible_pointer)); auto* possible_heap_block = HeapBlock::from_cell(reinterpret_cast<Cell const*>(possible_pointer));
if (!all_live_heap_blocks.contains(possible_heap_block)) if (!all_live_heap_blocks.contains(possible_heap_block))
continue; continue;
if (auto* cell = possible_heap_block->cell_from_possible_pointer(possible_pointer)) { 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<HeapBlock*> const& a
} }
} }
class GraphConstructorVisitor final : public CellImpl::Visitor { class GraphConstructorVisitor final : public Cell::Visitor {
public: public:
explicit GraphConstructorVisitor(Heap& heap, HashMap<CellImpl*, HeapRoot> const& roots) explicit GraphConstructorVisitor(Heap& heap, HashMap<Cell*, HeapRoot> const& roots)
: m_heap(heap) : m_heap(heap)
{ {
m_heap.find_min_and_max_block_addresses(m_min_block_address, m_max_block_address); 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) if (m_node_being_visited)
m_node_being_visited->edges.set(reinterpret_cast<FlatPtr>(&cell)); m_node_being_visited->edges.set(reinterpret_cast<FlatPtr>(&cell));
@ -148,7 +148,7 @@ public:
for (size_t i = 0; i < (bytes.size() / sizeof(FlatPtr)); ++i) 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); 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) if (m_node_being_visited)
m_node_being_visited->edges.set(reinterpret_cast<FlatPtr>(cell)); m_node_being_visited->edges.set(reinterpret_cast<FlatPtr>(cell));
@ -183,8 +183,8 @@ public:
auto type = it.value.root_origin->type; auto type = it.value.root_origin->type;
auto location = it.value.root_origin->location; auto location = it.value.root_origin->location;
switch (type) { switch (type) {
case HeapRoot::Type::Handle: case HeapRoot::Type::Root:
node.set("root"sv, ByteString::formatted("Handle {} {}:{}", location->function_name(), location->filename(), location->line_number())); node.set("root"sv, ByteString::formatted("Root {} {}:{}", location->function_name(), location->filename(), location->line_number()));
break; break;
case HeapRoot::Type::MarkedVector: case HeapRoot::Type::MarkedVector:
node.set("root"sv, "MarkedVector"); node.set("root"sv, "MarkedVector");
@ -218,7 +218,7 @@ private:
}; };
GraphNode* m_node_being_visited { nullptr }; GraphNode* m_node_being_visited { nullptr };
Vector<NonnullGCPtr<CellImpl>> m_work_queue; Vector<Ref<Cell>> m_work_queue;
HashMap<FlatPtr, GraphNode> m_graph; HashMap<FlatPtr, GraphNode> m_graph;
Heap& m_heap; Heap& m_heap;
@ -229,7 +229,7 @@ private:
AK::JsonObject Heap::dump_graph() AK::JsonObject Heap::dump_graph()
{ {
HashMap<CellImpl*, HeapRoot> roots; HashMap<Cell*, HeapRoot> roots;
gather_roots(roots); gather_roots(roots);
GraphConstructorVisitor visitor(*this, roots); GraphConstructorVisitor visitor(*this, roots);
visitor.visit_all_cells(); 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; m_should_gc_when_deferral_ends = true;
return; return;
} }
HashMap<CellImpl*, HeapRoot> roots; HashMap<Cell*, HeapRoot> roots;
gather_roots(roots); gather_roots(roots);
mark_live_cells(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); sweep_dead_cells(print_report, collection_measurement_timer);
} }
void Heap::gather_roots(HashMap<CellImpl*, HeapRoot>& roots) void Heap::gather_roots(HashMap<Cell*, HeapRoot>& roots)
{ {
m_gather_embedder_roots(roots); m_gather_embedder_roots(roots);
gather_conservative_roots(roots); gather_conservative_roots(roots);
for (auto& handle : m_handles) for (auto& root : m_roots)
roots.set(handle.cell(), HeapRoot { .type = HeapRoot::Type::Handle, .location = &handle.source_location() }); roots.set(root.cell(), HeapRoot { .type = HeapRoot::Type::Root, .location = &root.source_location() });
for (auto& vector : m_marked_vectors) for (auto& vector : m_marked_vectors)
vector.gather_roots(roots); vector.gather_roots(roots);
@ -298,7 +298,7 @@ void Heap::gather_asan_fake_stack_roots(HashMap<FlatPtr, HeapRoot>&, FlatPtr, Fl
} }
#endif #endif
NO_SANITIZE_ADDRESS void Heap::gather_conservative_roots(HashMap<CellImpl*, HeapRoot>& roots) NO_SANITIZE_ADDRESS void Heap::gather_conservative_roots(HashMap<Cell*, HeapRoot>& roots)
{ {
FlatPtr dummy; FlatPtr dummy;
@ -337,8 +337,8 @@ NO_SANITIZE_ADDRESS void Heap::gather_conservative_roots(HashMap<CellImpl*, Heap
return IterationDecision::Continue; return IterationDecision::Continue;
}); });
for_each_cell_among_possible_pointers(all_live_heap_blocks, possible_pointers, [&](CellImpl* cell, FlatPtr possible_pointer) { for_each_cell_among_possible_pointers(all_live_heap_blocks, possible_pointers, [&](Cell* cell, FlatPtr possible_pointer) {
if (cell->state() == CellImpl::State::Live) { if (cell->state() == Cell::State::Live) {
dbgln_if(HEAP_DEBUG, " ?-> {}", (void const*)cell); dbgln_if(HEAP_DEBUG, " ?-> {}", (void const*)cell);
roots.set(cell, *possible_pointers.get(possible_pointer)); roots.set(cell, *possible_pointers.get(possible_pointer));
} else { } else {
@ -347,9 +347,9 @@ NO_SANITIZE_ADDRESS void Heap::gather_conservative_roots(HashMap<CellImpl*, Heap
}); });
} }
class MarkingVisitor final : public CellImpl::Visitor { class MarkingVisitor final : public Cell::Visitor {
public: public:
explicit MarkingVisitor(Heap& heap, HashMap<CellImpl*, HeapRoot> const& roots) explicit MarkingVisitor(Heap& heap, HashMap<Cell*, HeapRoot> const& roots)
: m_heap(heap) : m_heap(heap)
{ {
m_heap.find_min_and_max_block_addresses(m_min_block_address, m_max_block_address); 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()) if (cell.is_marked())
return; return;
@ -381,10 +381,10 @@ public:
for (size_t i = 0; i < (bytes.size() / sizeof(FlatPtr)); ++i) 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); 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()) if (cell->is_marked())
return; return;
if (cell->state() != CellImpl::State::Live) if (cell->state() != Cell::State::Live)
return; return;
cell->set_marked(true); cell->set_marked(true);
m_work_queue.append(*cell); m_work_queue.append(*cell);
@ -400,13 +400,13 @@ public:
private: private:
Heap& m_heap; Heap& m_heap;
Vector<NonnullGCPtr<CellImpl>> m_work_queue; Vector<Ref<Cell>> m_work_queue;
HashTable<HeapBlock*> m_all_live_heap_blocks; HashTable<HeapBlock*> m_all_live_heap_blocks;
FlatPtr m_min_block_address; FlatPtr m_min_block_address;
FlatPtr m_max_block_address; FlatPtr m_max_block_address;
}; };
void Heap::mark_live_cells(HashMap<CellImpl*, HeapRoot> const& roots) void Heap::mark_live_cells(HashMap<Cell*, HeapRoot> const& roots)
{ {
dbgln_if(HEAP_DEBUG, "mark_live_cells:"); dbgln_if(HEAP_DEBUG, "mark_live_cells:");
@ -420,7 +420,7 @@ void Heap::mark_live_cells(HashMap<CellImpl*, HeapRoot> const& roots)
m_uprooted_cells.clear(); 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({})) if (!cell.overrides_must_survive_garbage_collection({}))
return false; return false;
@ -430,7 +430,7 @@ bool Heap::cell_must_survive_garbage_collection(CellImpl const& cell)
void Heap::finalize_unmarked_cells() void Heap::finalize_unmarked_cells()
{ {
for_each_block([&](auto& block) { for_each_block([&](auto& block) {
block.template for_each_cell_in_state<CellImpl::State::Live>([](CellImpl* cell) { block.template for_each_cell_in_state<Cell::State::Live>([](Cell* cell) {
if (!cell->is_marked() && !cell_must_survive_garbage_collection(*cell)) if (!cell->is_marked() && !cell_must_survive_garbage_collection(*cell))
cell->finalize(); cell->finalize();
}); });
@ -452,7 +452,7 @@ void Heap::sweep_dead_cells(bool print_report, Core::ElapsedTimer const& measure
for_each_block([&](auto& block) { for_each_block([&](auto& block) {
bool block_has_live_cells = false; bool block_has_live_cells = false;
bool block_was_full = block.is_full(); bool block_was_full = block.is_full();
block.template for_each_cell_in_state<CellImpl::State::Live>([&](CellImpl* cell) { block.template for_each_cell_in_state<Cell::State::Live>([&](Cell* cell) {
if (!cell->is_marked() && !cell_must_survive_garbage_collection(*cell)) { if (!cell->is_marked() && !cell_must_survive_garbage_collection(*cell)) {
dbgln_if(HEAP_DEBUG, " ~ {}", cell); dbgln_if(HEAP_DEBUG, " ~ {}", cell);
block.deallocate(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); m_uprooted_cells.append(cell);
} }

View file

@ -16,28 +16,28 @@
#include <AK/Types.h> #include <AK/Types.h>
#include <AK/Vector.h> #include <AK/Vector.h>
#include <LibCore/Forward.h> #include <LibCore/Forward.h>
#include <LibJS/Forward.h> #include <LibGC/Cell.h>
#include <LibJS/Heap/CellAllocator.h> #include <LibGC/CellAllocator.h>
#include <LibJS/Heap/CellImpl.h> #include <LibGC/ConservativeVector.h>
#include <LibJS/Heap/ConservativeVector.h> #include <LibGC/Forward.h>
#include <LibJS/Heap/Handle.h> #include <LibGC/HeapRoot.h>
#include <LibJS/Heap/HeapRoot.h> #include <LibGC/Internals.h>
#include <LibJS/Heap/Internals.h> #include <LibGC/MarkedVector.h>
#include <LibJS/Heap/MarkedVector.h> #include <LibGC/Root.h>
#include <LibJS/Heap/WeakContainer.h> #include <LibGC/WeakContainer.h>
namespace JS { namespace GC {
class Heap : public HeapBase { class Heap : public HeapBase {
AK_MAKE_NONCOPYABLE(Heap); AK_MAKE_NONCOPYABLE(Heap);
AK_MAKE_NONMOVABLE(Heap); AK_MAKE_NONMOVABLE(Heap);
public: public:
explicit Heap(void* private_data, Function<void(HashMap<CellImpl*, JS::HeapRoot>&)> gather_embedder_roots); explicit Heap(void* private_data, AK::Function<void(HashMap<Cell*, GC::HeapRoot>&)> gather_embedder_roots);
~Heap(); ~Heap();
template<typename T, typename... Args> template<typename T, typename... Args>
NonnullGCPtr<T> allocate(Args&&... args) Ref<T> allocate(Args&&... args)
{ {
auto* memory = allocate_cell<T>(); auto* memory = allocate_cell<T>();
defer_gc(); defer_gc();
@ -57,8 +57,8 @@ public:
bool should_collect_on_every_allocation() const { return m_should_collect_on_every_allocation; } 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 set_should_collect_on_every_allocation(bool b) { m_should_collect_on_every_allocation = b; }
void did_create_handle(Badge<HandleImpl>, HandleImpl&); void did_create_root(Badge<RootImpl>, RootImpl&);
void did_destroy_handle(Badge<HandleImpl>, HandleImpl&); void did_destroy_root(Badge<RootImpl>, RootImpl&);
void did_create_marked_vector(Badge<MarkedVectorBase>, MarkedVectorBase&); void did_create_marked_vector(Badge<MarkedVectorBase>, MarkedVectorBase&);
void did_destroy_marked_vector(Badge<MarkedVectorBase>, MarkedVectorBase&); void did_destroy_marked_vector(Badge<MarkedVectorBase>, MarkedVectorBase&);
@ -71,7 +71,7 @@ public:
void register_cell_allocator(Badge<CellAllocator>, CellAllocator&); void register_cell_allocator(Badge<CellAllocator>, CellAllocator&);
void uproot_cell(CellImpl* cell); void uproot_cell(Cell* cell);
private: private:
friend class MarkingVisitor; friend class MarkingVisitor;
@ -81,10 +81,10 @@ private:
void defer_gc(); void defer_gc();
void undefer_gc(); void undefer_gc();
static bool cell_must_survive_garbage_collection(CellImpl const&); static bool cell_must_survive_garbage_collection(Cell const&);
template<typename T> template<typename T>
CellImpl* allocate_cell() Cell* allocate_cell()
{ {
will_allocate(sizeof(T)); will_allocate(sizeof(T));
if constexpr (requires { T::cell_allocator.allocator.get().allocate_cell(*this); }) { if constexpr (requires { T::cell_allocator.allocator.get().allocate_cell(*this); }) {
@ -98,10 +98,10 @@ private:
void will_allocate(size_t); void will_allocate(size_t);
void find_min_and_max_block_addresses(FlatPtr& min_address, FlatPtr& max_address); void find_min_and_max_block_addresses(FlatPtr& min_address, FlatPtr& max_address);
void gather_roots(HashMap<CellImpl*, HeapRoot>&); void gather_roots(HashMap<Cell*, HeapRoot>&);
void gather_conservative_roots(HashMap<CellImpl*, HeapRoot>&); void gather_conservative_roots(HashMap<Cell*, HeapRoot>&);
void gather_asan_fake_stack_roots(HashMap<FlatPtr, HeapRoot>&, FlatPtr, FlatPtr min_block_address, FlatPtr max_block_address); void gather_asan_fake_stack_roots(HashMap<FlatPtr, HeapRoot>&, FlatPtr, FlatPtr min_block_address, FlatPtr max_block_address);
void mark_live_cells(HashMap<CellImpl*, HeapRoot> const& live_cells); void mark_live_cells(HashMap<Cell*, HeapRoot> const& live_cells);
void finalize_unmarked_cells(); void finalize_unmarked_cells();
void sweep_dead_cells(bool print_report, Core::ElapsedTimer const&); void sweep_dead_cells(bool print_report, Core::ElapsedTimer const&);
@ -134,31 +134,31 @@ private:
Vector<NonnullOwnPtr<CellAllocator>> m_size_based_cell_allocators; Vector<NonnullOwnPtr<CellAllocator>> m_size_based_cell_allocators;
CellAllocator::List m_all_cell_allocators; CellAllocator::List m_all_cell_allocators;
HandleImpl::List m_handles; RootImpl::List m_roots;
MarkedVectorBase::List m_marked_vectors; MarkedVectorBase::List m_marked_vectors;
ConservativeVectorBase::List m_conservative_vectors; ConservativeVectorBase::List m_conservative_vectors;
WeakContainer::List m_weak_containers; WeakContainer::List m_weak_containers;
Vector<GCPtr<CellImpl>> m_uprooted_cells; Vector<Ptr<Cell>> m_uprooted_cells;
size_t m_gc_deferrals { 0 }; size_t m_gc_deferrals { 0 };
bool m_should_gc_when_deferral_ends { false }; bool m_should_gc_when_deferral_ends { false };
bool m_collecting_garbage { false }; bool m_collecting_garbage { false };
StackInfo m_stack_info; StackInfo m_stack_info;
Function<void(HashMap<CellImpl*, JS::HeapRoot>&)> m_gather_embedder_roots; AK::Function<void(HashMap<Cell*, GC::HeapRoot>&)> m_gather_embedder_roots;
}; };
inline void Heap::did_create_handle(Badge<HandleImpl>, HandleImpl& impl) inline void Heap::did_create_root(Badge<RootImpl>, RootImpl& impl)
{ {
VERIFY(!m_handles.contains(impl)); VERIFY(!m_roots.contains(impl));
m_handles.append(impl); m_roots.append(impl);
} }
inline void Heap::did_destroy_handle(Badge<HandleImpl>, HandleImpl& impl) inline void Heap::did_destroy_root(Badge<RootImpl>, RootImpl& impl)
{ {
VERIFY(m_handles.contains(impl)); VERIFY(m_roots.contains(impl));
m_handles.remove(impl); m_roots.remove(impl);
} }
inline void Heap::did_create_marked_vector(Badge<MarkedVectorBase>, MarkedVectorBase& vector) inline void Heap::did_create_marked_vector(Badge<MarkedVectorBase>, MarkedVectorBase& vector)

View file

@ -7,8 +7,8 @@
#include <AK/Assertions.h> #include <AK/Assertions.h>
#include <AK/NonnullOwnPtr.h> #include <AK/NonnullOwnPtr.h>
#include <AK/Platform.h> #include <AK/Platform.h>
#include <LibJS/Heap/Heap.h> #include <LibGC/Heap.h>
#include <LibJS/Heap/HeapBlock.h> #include <LibGC/HeapBlock.h>
#include <stdio.h> #include <stdio.h>
#include <sys/mman.h> #include <sys/mman.h>
@ -16,7 +16,7 @@
# include <sanitizer/asan_interface.h> # include <sanitizer/asan_interface.h>
#endif #endif
namespace JS { namespace GC {
size_t HeapBlockBase::block_size = PAGE_SIZE; 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)); 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(is_valid_cell_pointer(cell));
VERIFY(!m_freelist || is_valid_cell_pointer(m_freelist)); 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()); VERIFY(!cell->is_marked());
cell->~CellImpl(); cell->~Cell();
auto* freelist_entry = new (cell) FreelistEntry(); 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; freelist_entry->next = m_freelist;
m_freelist = freelist_entry; m_freelist = freelist_entry;

View file

@ -10,15 +10,15 @@
#include <AK/Platform.h> #include <AK/Platform.h>
#include <AK/StringView.h> #include <AK/StringView.h>
#include <AK/Types.h> #include <AK/Types.h>
#include <LibJS/Forward.h> #include <LibGC/Cell.h>
#include <LibJS/Heap/CellImpl.h> #include <LibGC/Forward.h>
#include <LibJS/Heap/Internals.h> #include <LibGC/Internals.h>
#ifdef HAS_ADDRESS_SANITIZER #ifdef HAS_ADDRESS_SANITIZER
# include <sanitizer/asan_interface.h> # include <sanitizer/asan_interface.h>
#endif #endif
namespace JS { namespace GC {
class HeapBlock : public HeapBlockBase { class HeapBlock : public HeapBlockBase {
AK_MAKE_NONCOPYABLE(HeapBlock); AK_MAKE_NONCOPYABLE(HeapBlock);
@ -32,9 +32,9 @@ public:
size_t cell_count() const { return (block_size - sizeof(HeapBlock)) / m_cell_size; } size_t cell_count() const { return (block_size - sizeof(HeapBlock)) / m_cell_size; }
bool is_full() const { return !has_lazy_freelist() && !m_freelist; } 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) { if (m_freelist) {
VERIFY(is_valid_cell_pointer(m_freelist)); VERIFY(is_valid_cell_pointer(m_freelist));
allocated_cell = exchange(m_freelist, m_freelist->next); allocated_cell = exchange(m_freelist, m_freelist->next);
@ -48,7 +48,7 @@ public:
return allocated_cell; return allocated_cell;
} }
void deallocate(CellImpl*); void deallocate(Cell*);
template<typename Callback> template<typename Callback>
void for_each_cell(Callback callback) void for_each_cell(Callback callback)
@ -58,7 +58,7 @@ public:
callback(cell(i)); callback(cell(i));
} }
template<CellImpl::State state, typename Callback> template<Cell::State state, typename Callback>
void for_each_cell_in_state(Callback callback) void for_each_cell_in_state(Callback callback)
{ {
for_each_cell([&](auto* cell) { 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<HeapBlock*>(HeapBlockBase::from_cell(cell)); return static_cast<HeapBlock*>(HeapBlockBase::from_cell(cell));
} }
CellImpl* cell_from_possible_pointer(FlatPtr pointer) Cell* cell_from_possible_pointer(FlatPtr pointer)
{ {
if (pointer < reinterpret_cast<FlatPtr>(m_storage)) if (pointer < reinterpret_cast<FlatPtr>(m_storage))
return nullptr; return nullptr;
@ -83,7 +83,7 @@ public:
return cell(cell_index); 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); 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(); } bool has_lazy_freelist() const { return m_next_lazy_freelist_index < cell_count(); }
struct FreelistEntry final : public CellImpl { struct FreelistEntry final : public Cell {
JS_CELL(FreelistEntry, CellImpl); GC_CELL(FreelistEntry, Cell);
RawGCPtr<FreelistEntry> next; RawPtr<FreelistEntry> next;
}; };
CellImpl* cell(size_t index) Cell* cell(size_t index)
{ {
return reinterpret_cast<CellImpl*>(&m_storage[index * cell_size()]); return reinterpret_cast<Cell*>(&m_storage[index * cell_size()]);
} }
CellAllocator& m_cell_allocator; CellAllocator& m_cell_allocator;
size_t m_cell_size { 0 }; size_t m_cell_size { 0 };
size_t m_next_lazy_freelist_index { 0 }; size_t m_next_lazy_freelist_index { 0 };
GCPtr<FreelistEntry> m_freelist; Ptr<FreelistEntry> m_freelist;
alignas(__BIGGEST_ALIGNMENT__) u8 m_storage[]; alignas(__BIGGEST_ALIGNMENT__) u8 m_storage[];
public: public:

View file

@ -8,12 +8,12 @@
#include <AK/SourceLocation.h> #include <AK/SourceLocation.h>
namespace JS { namespace GC {
struct HeapRoot { struct HeapRoot {
enum class Type { enum class Type {
HeapFunctionCapturedPointer, HeapFunctionCapturedPointer,
Handle, Root,
MarkedVector, MarkedVector,
ConservativeVector, ConservativeVector,
RegisterPointer, RegisterPointer,

View file

@ -8,9 +8,9 @@
#pragma once #pragma once
#include <AK/Types.h> #include <AK/Types.h>
#include <LibJS/Forward.h> #include <LibGC/Forward.h>
namespace JS { namespace GC {
class HeapBase { class HeapBase {
AK_MAKE_NONCOPYABLE(HeapBase); AK_MAKE_NONCOPYABLE(HeapBase);
@ -34,7 +34,7 @@ class HeapBlockBase {
public: public:
static size_t block_size; static size_t block_size;
static HeapBlockBase* from_cell(CellImpl const* cell) static HeapBlockBase* from_cell(Cell const* cell)
{ {
return reinterpret_cast<HeapBlockBase*>(bit_cast<FlatPtr>(cell) & ~(HeapBlockBase::block_size - 1)); return reinterpret_cast<HeapBlockBase*>(bit_cast<FlatPtr>(cell) & ~(HeapBlockBase::block_size - 1));
} }

View file

@ -5,10 +5,10 @@
* SPDX-License-Identifier: BSD-2-Clause * SPDX-License-Identifier: BSD-2-Clause
*/ */
#include <LibJS/Heap/Heap.h> #include <LibGC/Heap.h>
#include <LibJS/Heap/MarkedVector.h> #include <LibGC/MarkedVector.h>
namespace JS { namespace GC {
MarkedVectorBase::MarkedVectorBase(Heap& heap) MarkedVectorBase::MarkedVectorBase(Heap& heap)
: m_heap(&heap) : m_heap(&heap)

View file

@ -10,15 +10,15 @@
#include <AK/HashMap.h> #include <AK/HashMap.h>
#include <AK/IntrusiveList.h> #include <AK/IntrusiveList.h>
#include <AK/Vector.h> #include <AK/Vector.h>
#include <LibJS/Forward.h> #include <LibGC/Cell.h>
#include <LibJS/Heap/CellImpl.h> #include <LibGC/Forward.h>
#include <LibJS/Heap/HeapRoot.h> #include <LibGC/HeapRoot.h>
namespace JS { namespace GC {
class MarkedVectorBase { class MarkedVectorBase {
public: public:
virtual void gather_roots(HashMap<CellImpl*, JS::HeapRoot>&) const = 0; virtual void gather_roots(HashMap<Cell*, GC::HeapRoot>&) const = 0;
protected: protected:
explicit MarkedVectorBase(Heap&); explicit MarkedVectorBase(Heap&);
@ -65,10 +65,10 @@ public:
return *this; return *this;
} }
virtual void gather_roots(HashMap<CellImpl*, JS::HeapRoot>& roots) const override virtual void gather_roots(HashMap<Cell*, GC::HeapRoot>& roots) const override
{ {
for (auto& value : *this) { for (auto& value : *this) {
if constexpr (IsSame<Value, T>) { if constexpr (IsBaseOf<NanBoxedValue, T>) {
if (value.is_cell()) if (value.is_cell())
roots.set(&const_cast<T&>(value).as_cell(), HeapRoot { .type = HeapRoot::Type::MarkedVector }); roots.set(&const_cast<T&>(value).as_cell(), HeapRoot { .type = HeapRoot::Type::MarkedVector });
} else { } else {

View file

@ -8,8 +8,9 @@
#include <AK/BitCast.h> #include <AK/BitCast.h>
#include <AK/Types.h> #include <AK/Types.h>
#include <LibGC/Cell.h>
namespace JS { namespace GC {
static_assert(sizeof(double) == 8); static_assert(sizeof(double) == 8);
static_assert(sizeof(void*) == sizeof(double) || sizeof(void*) == sizeof(u32)); 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 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 // 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 // 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<FlatPtr>(encoded & 0xffff'ffff'ffffULL); return static_cast<FlatPtr>(encoded & 0xffff'ffff'ffffULL);
#else #else
# error "Unknown architecture. Don't know whether pointers need to be sign-extended." # error "Unknown architecture. Don't know whether pointers need to be sign-extended."
@ -86,16 +87,16 @@ public:
return reinterpret_cast<PointerType*>(extract_pointer_bits(m_value.encoded)); return reinterpret_cast<PointerType*>(extract_pointer_bits(m_value.encoded));
} }
CellImpl& as_cell() Cell& as_cell()
{ {
VERIFY(is_cell()); VERIFY(is_cell());
return *extract_pointer<CellImpl>(); return *extract_pointer<Cell>();
} }
CellImpl& as_cell() const Cell& as_cell() const
{ {
VERIFY(is_cell()); VERIFY(is_cell());
return *extract_pointer<CellImpl>(); return *extract_pointer<Cell>();
} }
bool is_nan() const bool is_nan() const

View file

@ -9,51 +9,51 @@
#include <AK/Traits.h> #include <AK/Traits.h>
#include <AK/Types.h> #include <AK/Types.h>
namespace JS { namespace GC {
template<typename T> template<typename T>
class GCPtr; class Ptr;
template<typename T> template<typename T>
class NonnullGCPtr { class Ref {
public: public:
NonnullGCPtr() = delete; Ref() = delete;
NonnullGCPtr(T& ptr) Ref(T& ptr)
: m_ptr(&ptr) : m_ptr(&ptr)
{ {
} }
template<typename U> template<typename U>
NonnullGCPtr(U& ptr) Ref(U& ptr)
requires(IsConvertible<U*, T*>) requires(IsConvertible<U*, T*>)
: m_ptr(&static_cast<T&>(ptr)) : m_ptr(&static_cast<T&>(ptr))
{ {
} }
template<typename U> template<typename U>
NonnullGCPtr(NonnullGCPtr<U> const& other) Ref(Ref<U> const& other)
requires(IsConvertible<U*, T*>) requires(IsConvertible<U*, T*>)
: m_ptr(other.ptr()) : m_ptr(other.ptr())
{ {
} }
template<typename U> template<typename U>
NonnullGCPtr& operator=(NonnullGCPtr<U> const& other) Ref& operator=(Ref<U> const& other)
requires(IsConvertible<U*, T*>) requires(IsConvertible<U*, T*>)
{ {
m_ptr = static_cast<T*>(other.ptr()); m_ptr = static_cast<T*>(other.ptr());
return *this; return *this;
} }
NonnullGCPtr& operator=(T& other) Ref& operator=(T& other)
{ {
m_ptr = &other; m_ptr = &other;
return *this; return *this;
} }
template<typename U> template<typename U>
NonnullGCPtr& operator=(U& other) Ref& operator=(U& other)
requires(IsConvertible<U*, T*>) requires(IsConvertible<U*, T*>)
{ {
m_ptr = &static_cast<T&>(other); m_ptr = &static_cast<T&>(other);
@ -75,88 +75,88 @@ private:
}; };
template<typename T> template<typename T>
class GCPtr { class Ptr {
public: public:
constexpr GCPtr() = default; constexpr Ptr() = default;
GCPtr(T& ptr) Ptr(T& ptr)
: m_ptr(&ptr) : m_ptr(&ptr)
{ {
} }
GCPtr(T* ptr) Ptr(T* ptr)
: m_ptr(ptr) : m_ptr(ptr)
{ {
} }
template<typename U> template<typename U>
GCPtr(GCPtr<U> const& other) Ptr(Ptr<U> const& other)
requires(IsConvertible<U*, T*>) requires(IsConvertible<U*, T*>)
: m_ptr(other.ptr()) : m_ptr(other.ptr())
{ {
} }
GCPtr(NonnullGCPtr<T> const& other) Ptr(Ref<T> const& other)
: m_ptr(other.ptr()) : m_ptr(other.ptr())
{ {
} }
template<typename U> template<typename U>
GCPtr(NonnullGCPtr<U> const& other) Ptr(Ref<U> const& other)
requires(IsConvertible<U*, T*>) requires(IsConvertible<U*, T*>)
: m_ptr(other.ptr()) : m_ptr(other.ptr())
{ {
} }
GCPtr(nullptr_t) Ptr(nullptr_t)
: m_ptr(nullptr) : m_ptr(nullptr)
{ {
} }
template<typename U> template<typename U>
GCPtr& operator=(GCPtr<U> const& other) Ptr& operator=(Ptr<U> const& other)
requires(IsConvertible<U*, T*>) requires(IsConvertible<U*, T*>)
{ {
m_ptr = static_cast<T*>(other.ptr()); m_ptr = static_cast<T*>(other.ptr());
return *this; return *this;
} }
GCPtr& operator=(NonnullGCPtr<T> const& other) Ptr& operator=(Ref<T> const& other)
{ {
m_ptr = other.ptr(); m_ptr = other.ptr();
return *this; return *this;
} }
template<typename U> template<typename U>
GCPtr& operator=(NonnullGCPtr<U> const& other) Ptr& operator=(Ref<U> const& other)
requires(IsConvertible<U*, T*>) requires(IsConvertible<U*, T*>)
{ {
m_ptr = static_cast<T*>(other.ptr()); m_ptr = static_cast<T*>(other.ptr());
return *this; return *this;
} }
GCPtr& operator=(T& other) Ptr& operator=(T& other)
{ {
m_ptr = &other; m_ptr = &other;
return *this; return *this;
} }
template<typename U> template<typename U>
GCPtr& operator=(U& other) Ptr& operator=(U& other)
requires(IsConvertible<U*, T*>) requires(IsConvertible<U*, T*>)
{ {
m_ptr = &static_cast<T&>(other); m_ptr = &static_cast<T&>(other);
return *this; return *this;
} }
GCPtr& operator=(T* other) Ptr& operator=(T* other)
{ {
m_ptr = other; m_ptr = other;
return *this; return *this;
} }
template<typename U> template<typename U>
GCPtr& operator=(U* other) Ptr& operator=(U* other)
requires(IsConvertible<U*, T*>) requires(IsConvertible<U*, T*>)
{ {
m_ptr = static_cast<T*>(other); m_ptr = static_cast<T*>(other);
@ -186,34 +186,34 @@ private:
T* m_ptr { nullptr }; T* m_ptr { nullptr };
}; };
// Non-Owning GCPtr // Non-Owning GC::Ptr
template<typename T> template<typename T>
using RawGCPtr = GCPtr<T>; using RawPtr = Ptr<T>;
// Non-Owning NonnullGCPtr // Non-Owning Ref
template<typename T> template<typename T>
using RawNonnullGCPtr = NonnullGCPtr<T>; using RawRef = Ref<T>;
template<typename T, typename U> template<typename T, typename U>
inline bool operator==(GCPtr<T> const& a, GCPtr<U> const& b) inline bool operator==(Ptr<T> const& a, Ptr<U> const& b)
{ {
return a.ptr() == b.ptr(); return a.ptr() == b.ptr();
} }
template<typename T, typename U> template<typename T, typename U>
inline bool operator==(GCPtr<T> const& a, NonnullGCPtr<U> const& b) inline bool operator==(Ptr<T> const& a, Ref<U> const& b)
{ {
return a.ptr() == b.ptr(); return a.ptr() == b.ptr();
} }
template<typename T, typename U> template<typename T, typename U>
inline bool operator==(NonnullGCPtr<T> const& a, NonnullGCPtr<U> const& b) inline bool operator==(Ref<T> const& a, Ref<U> const& b)
{ {
return a.ptr() == b.ptr(); return a.ptr() == b.ptr();
} }
template<typename T, typename U> template<typename T, typename U>
inline bool operator==(NonnullGCPtr<T> const& a, GCPtr<U> const& b) inline bool operator==(Ref<T> const& a, Ptr<U> const& b)
{ {
return a.ptr() == b.ptr(); return a.ptr() == b.ptr();
} }
@ -223,16 +223,16 @@ inline bool operator==(NonnullGCPtr<T> const& a, GCPtr<U> const& b)
namespace AK { namespace AK {
template<typename T> template<typename T>
struct Traits<JS::GCPtr<T>> : public DefaultTraits<JS::GCPtr<T>> { struct Traits<GC::Ptr<T>> : public DefaultTraits<GC::Ptr<T>> {
static unsigned hash(JS::GCPtr<T> const& value) static unsigned hash(GC::Ptr<T> const& value)
{ {
return Traits<T*>::hash(value.ptr()); return Traits<T*>::hash(value.ptr());
} }
}; };
template<typename T> template<typename T>
struct Traits<JS::NonnullGCPtr<T>> : public DefaultTraits<JS::NonnullGCPtr<T>> { struct Traits<GC::Ref<T>> : public DefaultTraits<GC::Ref<T>> {
static unsigned hash(JS::NonnullGCPtr<T> const& value) static unsigned hash(GC::Ref<T> const& value)
{ {
return Traits<T*>::hash(value.ptr()); return Traits<T*>::hash(value.ptr());
} }

25
Libraries/LibGC/Root.cpp Normal file
View file

@ -0,0 +1,25 @@
/*
* Copyright (c) 2020, Andreas Kling <andreas@ladybird.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#include <LibGC/Cell.h>
#include <LibGC/Heap.h>
#include <LibGC/Root.h>
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);
}
}

169
Libraries/LibGC/Root.h Normal file
View file

@ -0,0 +1,169 @@
/*
* Copyright (c) 2020, Andreas Kling <andreas@ladybird.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#pragma once
#include <AK/Badge.h>
#include <AK/IntrusiveList.h>
#include <AK/Noncopyable.h>
#include <AK/RefCounted.h>
#include <AK/RefPtr.h>
#include <AK/SourceLocation.h>
#include <LibGC/Forward.h>
#include <LibGC/Ptr.h>
namespace GC {
class RootImpl : public RefCounted<RootImpl> {
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<class T>
friend class Root;
explicit RootImpl(Cell*, SourceLocation location);
Ptr<Cell> m_cell;
SourceLocation m_location;
IntrusiveListNode<RootImpl> m_list_node;
public:
using List = IntrusiveList<&RootImpl::m_list_node>;
};
template<class T>
class Root {
public:
Root() = default;
static Root create(T* cell, SourceLocation location = SourceLocation::current())
{
return Root(adopt_ref(*new RootImpl(const_cast<RemoveConst<T>*>(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<T> cell, SourceLocation location = SourceLocation::current())
: Root(cell.ptr(), location)
{
}
Root(Ref<T> cell, SourceLocation location = SourceLocation::current())
: Root(*cell, location)
{
}
T* cell() const
{
if (!m_impl)
return nullptr;
return static_cast<T*>(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<RootImpl> impl)
: m_impl(move(impl))
{
}
RefPtr<RootImpl> m_impl;
};
template<class T>
inline Root<T> make_root(T* cell, SourceLocation location = SourceLocation::current())
{
if (!cell)
return Root<T> {};
return Root<T>::create(cell, location);
}
template<class T>
inline Root<T> make_root(T& cell, SourceLocation location = SourceLocation::current())
{
return Root<T>::create(&cell, location);
}
template<class T>
inline Root<T> make_root(Ptr<T> cell, SourceLocation location = SourceLocation::current())
{
if (!cell)
return Root<T> {};
return Root<T>::create(cell.ptr(), location);
}
template<class T>
inline Root<T> make_root(Ref<T> cell, SourceLocation location = SourceLocation::current())
{
return Root<T>::create(cell.ptr(), location);
}
}
namespace AK {
template<typename T>
struct Traits<GC::Root<T>> : public DefaultTraits<GC::Root<T>> {
static unsigned hash(GC::Root<T> const& handle) { return Traits<T>::hash(handle); }
};
namespace Detail {
template<typename T>
inline constexpr bool IsHashCompatible<GC::Root<T>, T> = true;
template<typename T>
inline constexpr bool IsHashCompatible<T, GC::Root<T>> = true;
}
}

View file

@ -4,10 +4,10 @@
* SPDX-License-Identifier: BSD-2-Clause * SPDX-License-Identifier: BSD-2-Clause
*/ */
#include <LibJS/Heap/Heap.h> #include <LibGC/Heap.h>
#include <LibJS/Heap/WeakContainer.h> #include <LibGC/WeakContainer.h>
namespace JS { namespace GC {
WeakContainer::WeakContainer(Heap& heap) WeakContainer::WeakContainer(Heap& heap)
: m_heap(heap) : m_heap(heap)

View file

@ -7,9 +7,9 @@
#pragma once #pragma once
#include <AK/IntrusiveList.h> #include <AK/IntrusiveList.h>
#include <LibJS/Forward.h> #include <LibGC/Forward.h>
namespace JS { namespace GC {
class WeakContainer { class WeakContainer {
public: public:

View file

@ -14,9 +14,9 @@
#include <AK/StringBuilder.h> #include <AK/StringBuilder.h>
#include <AK/TemporaryChange.h> #include <AK/TemporaryChange.h>
#include <LibCrypto/BigInt/SignedBigInteger.h> #include <LibCrypto/BigInt/SignedBigInteger.h>
#include <LibGC/ConservativeVector.h>
#include <LibGC/MarkedVector.h>
#include <LibJS/AST.h> #include <LibJS/AST.h>
#include <LibJS/Heap/ConservativeVector.h>
#include <LibJS/Heap/MarkedVector.h>
#include <LibJS/Runtime/AbstractOperations.h> #include <LibJS/Runtime/AbstractOperations.h>
#include <LibJS/Runtime/Accessor.h> #include <LibJS/Runtime/Accessor.h>
#include <LibJS/Runtime/Array.h> #include <LibJS/Runtime/Array.h>
@ -97,7 +97,7 @@ Value FunctionExpression::instantiate_ordinary_function_expression(VM& vm, Depre
auto has_own_name = !name().is_empty(); auto has_own_name = !name().is_empty();
auto const used_name = has_own_name ? name() : given_name.view(); 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) { if (has_own_name) {
VERIFY(environment); VERIFY(environment);
environment = new_declarative_environment(*environment); environment = new_declarative_environment(*environment);
@ -227,7 +227,7 @@ ThrowCompletionOr<ClassElement::ClassValue> ClassField::class_element_evaluation
auto& realm = *vm.current_realm(); auto& realm = *vm.current_realm();
auto property_key_or_private_name = TRY(class_key_to_property_name(vm, *m_key, property_key)); auto property_key_or_private_name = TRY(class_key_to_property_name(vm, *m_key, property_key));
GCPtr<ECMAScriptFunctionObject> initializer; GC::Ptr<ECMAScriptFunctionObject> initializer;
if (m_initializer) { if (m_initializer) {
auto copy_initializer = m_initializer; auto copy_initializer = m_initializer;
auto name = property_key_or_private_name.visit( auto name = property_key_or_private_name.visit(
@ -310,7 +310,7 @@ ThrowCompletionOr<ECMAScriptFunctionObject*> ClassExpression::create_class_const
vm.running_execution_context().lexical_environment = class_environment; 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(); auto constructor_parent = realm.intrinsics().function_prototype();
if (!m_super_class.is_null()) { if (!m_super_class.is_null()) {
@ -366,12 +366,12 @@ ThrowCompletionOr<ECMAScriptFunctionObject*> ClassExpression::create_class_const
prototype->define_direct_property(vm.names.constructor, class_constructor, Attribute::Writable | Attribute::Configurable); prototype->define_direct_property(vm.names.constructor, class_constructor, Attribute::Writable | Attribute::Configurable);
using StaticElement = Variant<ClassFieldDefinition, JS::NonnullGCPtr<ECMAScriptFunctionObject>>; using StaticElement = Variant<ClassFieldDefinition, GC::Ref<ECMAScriptFunctionObject>>;
ConservativeVector<PrivateElement> static_private_methods(vm.heap()); GC::ConservativeVector<PrivateElement> static_private_methods(vm.heap());
ConservativeVector<PrivateElement> instance_private_methods(vm.heap()); GC::ConservativeVector<PrivateElement> instance_private_methods(vm.heap());
ConservativeVector<ClassFieldDefinition> instance_fields(vm.heap()); GC::ConservativeVector<ClassFieldDefinition> instance_fields(vm.heap());
ConservativeVector<StaticElement> static_elements(vm.heap()); GC::ConservativeVector<StaticElement> static_elements(vm.heap());
for (size_t element_index = 0; element_index < m_elements.size(); element_index++) { for (size_t element_index = 0; element_index < m_elements.size(); element_index++) {
auto const& element = m_elements[element_index]; auto const& element = m_elements[element_index];
@ -411,7 +411,7 @@ ThrowCompletionOr<ECMAScriptFunctionObject*> ClassExpression::create_class_const
VERIFY(element_value.has<Completion>() && element_value.get<Completion>().value().has_value()); VERIFY(element_value.has<Completion>() && element_value.get<Completion>().value().has_value());
auto& element_object = element_value.get<Completion>().value()->as_object(); auto& element_object = element_value.get<Completion>().value()->as_object();
VERIFY(is<ECMAScriptFunctionObject>(element_object)); VERIFY(is<ECMAScriptFunctionObject>(element_object));
static_elements.append(NonnullGCPtr { static_cast<ECMAScriptFunctionObject&>(element_object) }); static_elements.append(GC::Ref { static_cast<ECMAScriptFunctionObject&>(element_object) });
} }
} }
@ -435,7 +435,7 @@ ThrowCompletionOr<ECMAScriptFunctionObject*> ClassExpression::create_class_const
[&](ClassFieldDefinition& field) -> ThrowCompletionOr<void> { [&](ClassFieldDefinition& field) -> ThrowCompletionOr<void> {
return TRY(class_constructor->define_field(field)); return TRY(class_constructor->define_field(field));
}, },
[&](Handle<ECMAScriptFunctionObject> static_block_function) -> ThrowCompletionOr<void> { [&](GC::Root<ECMAScriptFunctionObject> static_block_function) -> ThrowCompletionOr<void> {
VERIFY(!static_block_function.is_null()); VERIFY(!static_block_function.is_null());
// We discard any value returned here. // We discard any value returned here.
TRY(call(vm, *static_block_function.cell(), class_constructor)); TRY(call(vm, *static_block_function.cell(), class_constructor));

View file

@ -15,6 +15,7 @@
#include <AK/RefPtr.h> #include <AK/RefPtr.h>
#include <AK/Variant.h> #include <AK/Variant.h>
#include <AK/Vector.h> #include <AK/Vector.h>
#include <LibGC/Root.h>
#include <LibJS/Bytecode/CodeGenerationError.h> #include <LibJS/Bytecode/CodeGenerationError.h>
#include <LibJS/Bytecode/Executable.h> #include <LibJS/Bytecode/Executable.h>
#include <LibJS/Bytecode/IdentifierTable.h> #include <LibJS/Bytecode/IdentifierTable.h>
@ -22,7 +23,6 @@
#include <LibJS/Bytecode/Operand.h> #include <LibJS/Bytecode/Operand.h>
#include <LibJS/Bytecode/ScopedOperand.h> #include <LibJS/Bytecode/ScopedOperand.h>
#include <LibJS/Forward.h> #include <LibJS/Forward.h>
#include <LibJS/Heap/Handle.h>
#include <LibJS/Runtime/ClassFieldDefinition.h> #include <LibJS/Runtime/ClassFieldDefinition.h>
#include <LibJS/Runtime/Completion.h> #include <LibJS/Runtime/Completion.h>
#include <LibJS/Runtime/EnvironmentCoordinate.h> #include <LibJS/Runtime/EnvironmentCoordinate.h>
@ -160,10 +160,10 @@ public:
} }
Bytecode::Executable* bytecode_executable() const { return m_bytecode_executable; } 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: private:
Handle<Bytecode::Executable> m_bytecode_executable; GC::Root<Bytecode::Executable> m_bytecode_executable;
}; };
// 14.13 Labelled Statements, https://tc39.es/ecma262/#sec-labelled-statements // 14.13 Labelled Statements, https://tc39.es/ecma262/#sec-labelled-statements
@ -690,7 +690,7 @@ struct FunctionParameter {
Variant<NonnullRefPtr<Identifier const>, NonnullRefPtr<BindingPattern const>> binding; Variant<NonnullRefPtr<Identifier const>, NonnullRefPtr<BindingPattern const>> binding;
RefPtr<Expression const> default_value; RefPtr<Expression const> default_value;
bool is_rest { false }; bool is_rest { false };
Handle<Bytecode::Executable> bytecode_executable {}; GC::Root<Bytecode::Executable> bytecode_executable {};
}; };
struct FunctionParsingInsights { struct FunctionParsingInsights {

View file

@ -8,16 +8,16 @@
#include <AK/Badge.h> #include <AK/Badge.h>
#include <AK/String.h> #include <AK/String.h>
#include <LibGC/Root.h>
#include <LibJS/Bytecode/Executable.h> #include <LibJS/Bytecode/Executable.h>
#include <LibJS/Bytecode/ScopedOperand.h> #include <LibJS/Bytecode/ScopedOperand.h>
#include <LibJS/Forward.h> #include <LibJS/Forward.h>
#include <LibJS/Heap/Handle.h>
namespace JS::Bytecode { namespace JS::Bytecode {
struct UnwindInfo { struct UnwindInfo {
JS::GCPtr<Executable const> executable; GC::Ptr<Executable const> executable;
JS::GCPtr<Environment> lexical_environment; GC::Ptr<Environment> lexical_environment;
bool handler_called { false }; bool handler_called { false };
}; };

View file

@ -13,7 +13,7 @@
namespace JS::Bytecode { namespace JS::Bytecode {
JS_DEFINE_ALLOCATOR(Executable); GC_DEFINE_ALLOCATOR(Executable);
Executable::Executable( Executable::Executable(
Vector<u8> bytecode, Vector<u8> bytecode,

View file

@ -11,12 +11,12 @@
#include <AK/NonnullOwnPtr.h> #include <AK/NonnullOwnPtr.h>
#include <AK/OwnPtr.h> #include <AK/OwnPtr.h>
#include <AK/WeakPtr.h> #include <AK/WeakPtr.h>
#include <LibGC/CellAllocator.h>
#include <LibJS/Bytecode/IdentifierTable.h> #include <LibJS/Bytecode/IdentifierTable.h>
#include <LibJS/Bytecode/Label.h> #include <LibJS/Bytecode/Label.h>
#include <LibJS/Bytecode/StringTable.h> #include <LibJS/Bytecode/StringTable.h>
#include <LibJS/Forward.h> #include <LibJS/Forward.h>
#include <LibJS/Heap/Cell.h> #include <LibJS/Heap/Cell.h>
#include <LibJS/Heap/CellAllocator.h>
#include <LibJS/Runtime/EnvironmentCoordinate.h> #include <LibJS/Runtime/EnvironmentCoordinate.h>
#include <LibJS/SourceRange.h> #include <LibJS/SourceRange.h>
@ -40,8 +40,8 @@ struct SourceRecord {
}; };
class Executable final : public Cell { class Executable final : public Cell {
JS_CELL(Executable, Cell); GC_CELL(Executable, Cell);
JS_DECLARE_ALLOCATOR(Executable); GC_DECLARE_ALLOCATOR(Executable);
public: public:
Executable( Executable(

View file

@ -17,7 +17,7 @@
namespace JS::Bytecode { namespace JS::Bytecode {
Generator::Generator(VM& vm, GCPtr<ECMAScriptFunctionObject const> function, MustPropagateCompletion must_propagate_completion) Generator::Generator(VM& vm, GC::Ptr<ECMAScriptFunctionObject const> function, MustPropagateCompletion must_propagate_completion)
: m_vm(vm) : m_vm(vm)
, m_string_table(make<StringTable>()) , m_string_table(make<StringTable>())
, m_identifier_table(make<IdentifierTable>()) , m_identifier_table(make<IdentifierTable>())
@ -199,7 +199,7 @@ CodeGenerationErrorOr<void> Generator::emit_function_declaration_instantiation(E
return {}; return {};
} }
CodeGenerationErrorOr<NonnullGCPtr<Executable>> Generator::compile(VM& vm, ASTNode const& node, FunctionKind enclosing_function_kind, GCPtr<ECMAScriptFunctionObject const> function, MustPropagateCompletion must_propagate_completion, Vector<DeprecatedFlyString> local_variable_names) CodeGenerationErrorOr<GC::Ref<Executable>> Generator::compile(VM& vm, ASTNode const& node, FunctionKind enclosing_function_kind, GC::Ptr<ECMAScriptFunctionObject const> function, MustPropagateCompletion must_propagate_completion, Vector<DeprecatedFlyString> local_variable_names)
{ {
Generator generator(vm, function, must_propagate_completion); Generator generator(vm, function, must_propagate_completion);
@ -460,7 +460,7 @@ CodeGenerationErrorOr<NonnullGCPtr<Executable>> Generator::compile(VM& vm, ASTNo
return executable; return executable;
} }
CodeGenerationErrorOr<NonnullGCPtr<Executable>> Generator::generate_from_ast_node(VM& vm, ASTNode const& node, FunctionKind enclosing_function_kind) CodeGenerationErrorOr<GC::Ref<Executable>> Generator::generate_from_ast_node(VM& vm, ASTNode const& node, FunctionKind enclosing_function_kind)
{ {
Vector<DeprecatedFlyString> local_variable_names; Vector<DeprecatedFlyString> local_variable_names;
if (is<ScopeNode>(node)) if (is<ScopeNode>(node))
@ -468,7 +468,7 @@ CodeGenerationErrorOr<NonnullGCPtr<Executable>> Generator::generate_from_ast_nod
return compile(vm, node, enclosing_function_kind, {}, MustPropagateCompletion::Yes, move(local_variable_names)); return compile(vm, node, enclosing_function_kind, {}, MustPropagateCompletion::Yes, move(local_variable_names));
} }
CodeGenerationErrorOr<NonnullGCPtr<Executable>> Generator::generate_from_function(VM& vm, ECMAScriptFunctionObject const& function) CodeGenerationErrorOr<GC::Ref<Executable>> Generator::generate_from_function(VM& vm, ECMAScriptFunctionObject const& function)
{ {
return compile(vm, function.ecmascript_code(), function.kind(), &function, MustPropagateCompletion::No, function.local_variables_names()); return compile(vm, function.ecmascript_code(), function.kind(), &function, MustPropagateCompletion::No, function.local_variables_names());
} }

View file

@ -38,8 +38,8 @@ public:
Yes, Yes,
}; };
static CodeGenerationErrorOr<NonnullGCPtr<Executable>> generate_from_ast_node(VM&, ASTNode const&, FunctionKind = FunctionKind::Normal); static CodeGenerationErrorOr<GC::Ref<Executable>> generate_from_ast_node(VM&, ASTNode const&, FunctionKind = FunctionKind::Normal);
static CodeGenerationErrorOr<NonnullGCPtr<Executable>> generate_from_function(VM&, ECMAScriptFunctionObject const& function); static CodeGenerationErrorOr<GC::Ref<Executable>> generate_from_function(VM&, ECMAScriptFunctionObject const& function);
CodeGenerationErrorOr<void> emit_function_declaration_instantiation(ECMAScriptFunctionObject const& function); CodeGenerationErrorOr<void> emit_function_declaration_instantiation(ECMAScriptFunctionObject const& function);
@ -343,7 +343,7 @@ public:
private: private:
VM& m_vm; VM& m_vm;
static CodeGenerationErrorOr<NonnullGCPtr<Executable>> compile(VM&, ASTNode const&, FunctionKind, GCPtr<ECMAScriptFunctionObject const>, MustPropagateCompletion, Vector<DeprecatedFlyString> local_variable_names); static CodeGenerationErrorOr<GC::Ref<Executable>> compile(VM&, ASTNode const&, FunctionKind, GC::Ptr<ECMAScriptFunctionObject const>, MustPropagateCompletion, Vector<DeprecatedFlyString> local_variable_names);
enum class JumpType { enum class JumpType {
Continue, Continue,
@ -352,7 +352,7 @@ private:
void generate_scoped_jump(JumpType); void generate_scoped_jump(JumpType);
void generate_labelled_jump(JumpType, DeprecatedFlyString const& label); void generate_labelled_jump(JumpType, DeprecatedFlyString const& label);
Generator(VM&, GCPtr<ECMAScriptFunctionObject const>, MustPropagateCompletion); Generator(VM&, GC::Ptr<ECMAScriptFunctionObject const>, MustPropagateCompletion);
~Generator() = default; ~Generator() = default;
void grow(size_t); void grow(size_t);
@ -373,7 +373,7 @@ private:
NonnullOwnPtr<StringTable> m_string_table; NonnullOwnPtr<StringTable> m_string_table;
NonnullOwnPtr<IdentifierTable> m_identifier_table; NonnullOwnPtr<IdentifierTable> m_identifier_table;
NonnullOwnPtr<RegexTable> m_regex_table; NonnullOwnPtr<RegexTable> m_regex_table;
MarkedVector<Value> m_constants; GC::MarkedVector<Value> m_constants;
mutable Optional<ScopedOperand> m_true_constant; mutable Optional<ScopedOperand> m_true_constant;
mutable Optional<ScopedOperand> m_false_constant; mutable Optional<ScopedOperand> m_false_constant;
@ -401,7 +401,7 @@ private:
bool m_finished { false }; bool m_finished { false };
bool m_must_propagate_completion { true }; bool m_must_propagate_completion { true };
GCPtr<ECMAScriptFunctionObject const> m_function; GC::Ptr<ECMAScriptFunctionObject const> m_function;
Optional<IdentifierTableIndex> m_length_identifier; Optional<IdentifierTableIndex> m_length_identifier;
}; };

View file

@ -213,7 +213,7 @@ private:
u8 const* m_begin { nullptr }; u8 const* m_begin { nullptr };
u8 const* m_end { nullptr }; u8 const* m_end { nullptr };
u8 const* m_ptr { nullptr }; u8 const* m_ptr { nullptr };
GCPtr<Executable const> m_executable; GC::Ptr<Executable const> m_executable;
}; };
} }

View file

@ -182,7 +182,7 @@ ALWAYS_INLINE Value Interpreter::do_yield(Value value, Optional<Label> continuat
} }
// 16.1.6 ScriptEvaluation ( scriptRecord ), https://tc39.es/ecma262/#sec-runtime-semantics-scriptevaluation // 16.1.6 ScriptEvaluation ( scriptRecord ), https://tc39.es/ecma262/#sec-runtime-semantics-scriptevaluation
ThrowCompletionOr<Value> Interpreter::run(Script& script_record, JS::GCPtr<Environment> lexical_environment_override) ThrowCompletionOr<Value> Interpreter::run(Script& script_record, GC::Ptr<Environment> lexical_environment_override)
{ {
auto& vm = this->vm(); auto& vm = this->vm();
@ -199,7 +199,7 @@ ThrowCompletionOr<Value> Interpreter::run(Script& script_record, JS::GCPtr<Envir
script_context->realm = &script_record.realm(); script_context->realm = &script_record.realm();
// 5. Set the ScriptOrModule of scriptContext to scriptRecord. // 5. Set the ScriptOrModule of scriptContext to scriptRecord.
script_context->script_or_module = NonnullGCPtr<Script>(script_record); script_context->script_or_module = GC::Ref<Script>(script_record);
// 6. Set the VariableEnvironment of scriptContext to globalEnv. // 6. Set the VariableEnvironment of scriptContext to globalEnv.
script_context->variable_environment = &global_environment; script_context->variable_environment = &global_environment;
@ -703,11 +703,11 @@ Interpreter::ResultAndReturnRegister Interpreter::run_executable(Executable& exe
{ {
dbgln_if(JS_BYTECODE_DEBUG, "Bytecode::Interpreter will run unit {:p}", &executable); dbgln_if(JS_BYTECODE_DEBUG, "Bytecode::Interpreter will run unit {:p}", &executable);
TemporaryChange restore_executable { m_current_executable, GCPtr { executable } }; TemporaryChange restore_executable { m_current_executable, GC::Ptr { executable } };
TemporaryChange restore_saved_jump { m_scheduled_jump, Optional<size_t> {} }; TemporaryChange restore_saved_jump { m_scheduled_jump, Optional<size_t> {} };
TemporaryChange restore_realm { m_realm, GCPtr { vm().current_realm() } }; TemporaryChange restore_realm { m_realm, GC::Ptr { vm().current_realm() } };
TemporaryChange restore_global_object { m_global_object, GCPtr { m_realm->global_object() } }; TemporaryChange restore_global_object { m_global_object, GC::Ptr { m_realm->global_object() } };
TemporaryChange restore_global_declarative_environment { m_global_declarative_environment, GCPtr { m_realm->global_environment().declarative_record() } }; TemporaryChange restore_global_declarative_environment { m_global_declarative_environment, GC::Ptr { m_realm->global_environment().declarative_record() } };
VERIFY(!vm().execution_context_stack().is_empty()); VERIFY(!vm().execution_context_stack().is_empty());
@ -813,7 +813,7 @@ void Interpreter::enter_object_environment(Object& object)
running_execution_context().lexical_environment = new_object_environment(object, true, old_environment); running_execution_context().lexical_environment = new_object_environment(object, true, old_environment);
} }
ThrowCompletionOr<NonnullGCPtr<Bytecode::Executable>> compile(VM& vm, ASTNode const& node, FunctionKind kind, DeprecatedFlyString const& name) ThrowCompletionOr<GC::Ref<Bytecode::Executable>> compile(VM& vm, ASTNode const& node, FunctionKind kind, DeprecatedFlyString const& name)
{ {
auto executable_result = Bytecode::Generator::generate_from_ast_node(vm, node, kind); auto executable_result = Bytecode::Generator::generate_from_ast_node(vm, node, kind);
if (executable_result.is_error()) if (executable_result.is_error())
@ -828,7 +828,7 @@ ThrowCompletionOr<NonnullGCPtr<Bytecode::Executable>> compile(VM& vm, ASTNode co
return bytecode_executable; return bytecode_executable;
} }
ThrowCompletionOr<NonnullGCPtr<Bytecode::Executable>> compile(VM& vm, ECMAScriptFunctionObject const& function) ThrowCompletionOr<GC::Ref<Bytecode::Executable>> compile(VM& vm, ECMAScriptFunctionObject const& function)
{ {
auto const& name = function.name(); auto const& name = function.name();
@ -921,7 +921,7 @@ ALWAYS_INLINE Completion throw_null_or_undefined_property_access(VM& vm, Value b
return vm.throw_completion<TypeError>(ErrorType::ToObjectNullOrUndefined); return vm.throw_completion<TypeError>(ErrorType::ToObjectNullOrUndefined);
} }
ALWAYS_INLINE GCPtr<Object> base_object_for_get_impl(VM& vm, Value base_value) ALWAYS_INLINE GC::Ptr<Object> base_object_for_get_impl(VM& vm, Value base_value)
{ {
if (base_value.is_object()) [[likely]] if (base_value.is_object()) [[likely]]
return base_value.as_object(); return base_value.as_object();
@ -942,19 +942,19 @@ ALWAYS_INLINE GCPtr<Object> base_object_for_get_impl(VM& vm, Value base_value)
return nullptr; return nullptr;
} }
ALWAYS_INLINE ThrowCompletionOr<NonnullGCPtr<Object>> base_object_for_get(VM& vm, Value base_value, Optional<IdentifierTableIndex> base_identifier, IdentifierTableIndex property_identifier, Executable const& executable) ALWAYS_INLINE ThrowCompletionOr<GC::Ref<Object>> base_object_for_get(VM& vm, Value base_value, Optional<IdentifierTableIndex> base_identifier, IdentifierTableIndex property_identifier, Executable const& executable)
{ {
if (auto base_object = base_object_for_get_impl(vm, base_value)) if (auto base_object = base_object_for_get_impl(vm, base_value))
return NonnullGCPtr { *base_object }; return GC::Ref { *base_object };
// NOTE: At this point this is guaranteed to throw (null or undefined). // NOTE: At this point this is guaranteed to throw (null or undefined).
return throw_null_or_undefined_property_get(vm, base_value, base_identifier, property_identifier, executable); return throw_null_or_undefined_property_get(vm, base_value, base_identifier, property_identifier, executable);
} }
ALWAYS_INLINE ThrowCompletionOr<NonnullGCPtr<Object>> base_object_for_get(VM& vm, Value base_value, Optional<IdentifierTableIndex> base_identifier, Value property, Executable const& executable) ALWAYS_INLINE ThrowCompletionOr<GC::Ref<Object>> base_object_for_get(VM& vm, Value base_value, Optional<IdentifierTableIndex> base_identifier, Value property, Executable const& executable)
{ {
if (auto base_object = base_object_for_get_impl(vm, base_value)) if (auto base_object = base_object_for_get_impl(vm, base_value))
return NonnullGCPtr { *base_object }; return GC::Ref { *base_object };
// NOTE: At this point this is guaranteed to throw (null or undefined). // NOTE: At this point this is guaranteed to throw (null or undefined).
return throw_null_or_undefined_property_get(vm, base_value, base_identifier, property, executable); return throw_null_or_undefined_property_get(vm, base_value, base_identifier, property, executable);
@ -1131,10 +1131,10 @@ inline ThrowCompletionOr<Value> get_global(Interpreter& interpreter, IdentifierT
auto& identifier = interpreter.current_executable().get_identifier(identifier_index); auto& identifier = interpreter.current_executable().get_identifier(identifier_index);
if (vm.running_execution_context().script_or_module.has<NonnullGCPtr<Module>>()) { if (vm.running_execution_context().script_or_module.has<GC::Ref<Module>>()) {
// NOTE: GetGlobal is used to access variables stored in the module environment and global environment. // NOTE: GetGlobal is used to access variables stored in the module environment and global environment.
// The module environment is checked first since it precedes the global environment in the environment chain. // The module environment is checked first since it precedes the global environment in the environment chain.
auto& module_environment = *vm.running_execution_context().script_or_module.get<NonnullGCPtr<Module>>()->environment(); auto& module_environment = *vm.running_execution_context().script_or_module.get<GC::Ref<Module>>()->environment();
if (TRY(module_environment.has_binding(identifier))) { if (TRY(module_environment.has_binding(identifier))) {
// TODO: Cache offset of binding value // TODO: Cache offset of binding value
return TRY(module_environment.get_binding_value(vm, identifier, vm.in_strict_mode())); return TRY(module_environment.get_binding_value(vm, identifier, vm.in_strict_mode()));
@ -1436,13 +1436,13 @@ inline Value new_regexp(VM& vm, ParsedRegex const& parsed_regex, ByteString cons
} }
// 13.3.8.1 https://tc39.es/ecma262/#sec-runtime-semantics-argumentlistevaluation // 13.3.8.1 https://tc39.es/ecma262/#sec-runtime-semantics-argumentlistevaluation
inline MarkedVector<Value> argument_list_evaluation(VM& vm, Value arguments) inline GC::MarkedVector<Value> argument_list_evaluation(VM& vm, Value arguments)
{ {
// Note: Any spreading and actual evaluation is handled in preceding opcodes // Note: Any spreading and actual evaluation is handled in preceding opcodes
// Note: The spec uses the concept of a list, while we create a temporary array // Note: The spec uses the concept of a list, while we create a temporary array
// in the preceding opcodes, so we have to convert in a manner that is not // in the preceding opcodes, so we have to convert in a manner that is not
// visible to the user // visible to the user
MarkedVector<Value> argument_values { vm.heap() }; GC::MarkedVector<Value> argument_values { vm.heap() };
auto& argument_array = arguments.as_array(); auto& argument_array = arguments.as_array();
auto array_length = argument_array.indexed_properties().array_like_size(); auto array_length = argument_array.indexed_properties().array_like_size();
@ -1507,7 +1507,7 @@ inline ThrowCompletionOr<ECMAScriptFunctionObject*> new_class(VM& vm, Value supe
} }
// 13.3.7.1 Runtime Semantics: Evaluation, https://tc39.es/ecma262/#sec-super-keyword-runtime-semantics-evaluation // 13.3.7.1 Runtime Semantics: Evaluation, https://tc39.es/ecma262/#sec-super-keyword-runtime-semantics-evaluation
inline ThrowCompletionOr<NonnullGCPtr<Object>> super_call_with_argument_array(VM& vm, Value argument_array, bool is_synthetic) inline ThrowCompletionOr<GC::Ref<Object>> super_call_with_argument_array(VM& vm, Value argument_array, bool is_synthetic)
{ {
// 1. Let newTarget be GetNewTarget(). // 1. Let newTarget be GetNewTarget().
auto new_target = vm.get_new_target(); auto new_target = vm.get_new_target();
@ -1519,7 +1519,7 @@ inline ThrowCompletionOr<NonnullGCPtr<Object>> super_call_with_argument_array(VM
auto* func = get_super_constructor(vm); auto* func = get_super_constructor(vm);
// 4. Let argList be ? ArgumentListEvaluation of Arguments. // 4. Let argList be ? ArgumentListEvaluation of Arguments.
MarkedVector<Value> arg_list { vm.heap() }; GC::MarkedVector<Value> arg_list { vm.heap() };
if (is_synthetic) { if (is_synthetic) {
VERIFY(argument_array.is_object() && is<Array>(argument_array.as_object())); VERIFY(argument_array.is_object() && is<Array>(argument_array.as_object()));
auto const& array_value = static_cast<Array const&>(argument_array.as_object()); auto const& array_value = static_cast<Array const&>(argument_array.as_object());
@ -1556,7 +1556,7 @@ inline ThrowCompletionOr<NonnullGCPtr<Object>> super_call_with_argument_array(VM
return result; return result;
} }
inline ThrowCompletionOr<NonnullGCPtr<Array>> iterator_to_array(VM& vm, Value iterator) inline ThrowCompletionOr<GC::Ref<Array>> iterator_to_array(VM& vm, Value iterator)
{ {
auto& iterator_record = verify_cast<IteratorRecord>(iterator.as_object()); auto& iterator_record = verify_cast<IteratorRecord>(iterator.as_object());
@ -1684,9 +1684,9 @@ inline ThrowCompletionOr<Object*> get_object_property_iterator(VM& vm, Value val
// so we just keep the order consistent anyway. // so we just keep the order consistent anyway.
OrderedHashTable<PropertyKey> properties; OrderedHashTable<PropertyKey> properties;
OrderedHashTable<PropertyKey> non_enumerable_properties; OrderedHashTable<PropertyKey> non_enumerable_properties;
HashTable<NonnullGCPtr<Object>> seen_objects; HashTable<GC::Ref<Object>> seen_objects;
// Collect all keys immediately (invariant no. 5) // Collect all keys immediately (invariant no. 5)
for (auto object_to_check = GCPtr { object.ptr() }; object_to_check && !seen_objects.contains(*object_to_check); object_to_check = TRY(object_to_check->internal_get_prototype_of())) { for (auto object_to_check = GC::Ptr { object.ptr() }; object_to_check && !seen_objects.contains(*object_to_check); object_to_check = TRY(object_to_check->internal_get_prototype_of())) {
seen_objects.set(*object_to_check); seen_objects.set(*object_to_check);
for (auto& key : TRY(object_to_check->internal_own_property_keys())) { for (auto& key : TRY(object_to_check->internal_own_property_keys())) {
if (key.is_symbol()) if (key.is_symbol())
@ -2207,7 +2207,7 @@ void CreateLexicalEnvironment::execute_impl(Bytecode::Interpreter& interpreter)
auto make_and_swap_envs = [&](auto& old_environment) { auto make_and_swap_envs = [&](auto& old_environment) {
auto declarative_environment = new_declarative_environment(*old_environment).ptr(); auto declarative_environment = new_declarative_environment(*old_environment).ptr();
declarative_environment->ensure_capacity(m_capacity); declarative_environment->ensure_capacity(m_capacity);
GCPtr<Environment> environment = declarative_environment; GC::Ptr<Environment> environment = declarative_environment;
swap(old_environment, environment); swap(old_environment, environment);
return environment; return environment;
}; };

View file

@ -30,7 +30,7 @@ public:
VM& vm() { return m_vm; } VM& vm() { return m_vm; }
VM const& vm() const { return m_vm; } VM const& vm() const { return m_vm; }
ThrowCompletionOr<Value> run(Script&, JS::GCPtr<Environment> lexical_environment_override = nullptr); ThrowCompletionOr<Value> run(Script&, GC::Ptr<Environment> lexical_environment_override = nullptr);
ThrowCompletionOr<Value> run(SourceTextModule&); ThrowCompletionOr<Value> run(SourceTextModule&);
ThrowCompletionOr<Value> run(Bytecode::Executable& executable, Optional<size_t> entry_point = {}, Value initial_accumulator_value = {}) ThrowCompletionOr<Value> run(Bytecode::Executable& executable, Optional<size_t> entry_point = {}, Value initial_accumulator_value = {})
@ -96,10 +96,10 @@ private:
VM& m_vm; VM& m_vm;
Optional<size_t> m_scheduled_jump; Optional<size_t> m_scheduled_jump;
GCPtr<Executable> m_current_executable { nullptr }; GC::Ptr<Executable> m_current_executable { nullptr };
GCPtr<Realm> m_realm { nullptr }; GC::Ptr<Realm> m_realm { nullptr };
GCPtr<Object> m_global_object { nullptr }; GC::Ptr<Object> m_global_object { nullptr };
GCPtr<DeclarativeEnvironment> m_global_declarative_environment { nullptr }; GC::Ptr<DeclarativeEnvironment> m_global_declarative_environment { nullptr };
Optional<size_t&> m_program_counter; Optional<size_t&> m_program_counter;
Span<Value> m_arguments; Span<Value> m_arguments;
Span<Value> m_registers_and_constants_and_locals; Span<Value> m_registers_and_constants_and_locals;
@ -109,7 +109,7 @@ private:
extern bool g_dump_bytecode; extern bool g_dump_bytecode;
ThrowCompletionOr<NonnullGCPtr<Bytecode::Executable>> compile(VM&, ASTNode const&, JS::FunctionKind kind, DeprecatedFlyString const& name); ThrowCompletionOr<GC::Ref<Bytecode::Executable>> compile(VM&, ASTNode const&, JS::FunctionKind kind, DeprecatedFlyString const& name);
ThrowCompletionOr<NonnullGCPtr<Bytecode::Executable>> compile(VM&, ECMAScriptFunctionObject const&); ThrowCompletionOr<GC::Ref<Bytecode::Executable>> compile(VM&, ECMAScriptFunctionObject const&);
} }

View file

@ -19,16 +19,7 @@ set(SOURCES
Contrib/Test262/GlobalObject.cpp Contrib/Test262/GlobalObject.cpp
Contrib/Test262/IsHTMLDDA.cpp Contrib/Test262/IsHTMLDDA.cpp
CyclicModule.cpp CyclicModule.cpp
Heap/BlockAllocator.cpp
Heap/Cell.cpp Heap/Cell.cpp
Heap/CellImpl.cpp
Heap/CellAllocator.cpp
Heap/ConservativeVector.cpp
Heap/Handle.cpp
Heap/Heap.cpp
Heap/HeapBlock.cpp
Heap/MarkedVector.cpp
Heap/WeakContainer.cpp
Lexer.cpp Lexer.cpp
MarkupGenerator.cpp MarkupGenerator.cpp
Module.cpp Module.cpp
@ -275,7 +266,7 @@ set(SOURCES
) )
serenity_lib(LibJS js) serenity_lib(LibJS js)
target_link_libraries(LibJS PRIVATE LibCore LibCrypto LibFileSystem LibRegex LibSyntax) target_link_libraries(LibJS PRIVATE LibCore LibCrypto LibFileSystem LibRegex LibSyntax LibGC)
# Link LibUnicode publicly to ensure ICU data (which is in libicudata.a) is available in any process using LibJS. # Link LibUnicode publicly to ensure ICU data (which is in libicudata.a) is available in any process using LibJS.
target_link_libraries(LibJS PUBLIC LibUnicode) target_link_libraries(LibJS PUBLIC LibUnicode)

View file

@ -20,8 +20,8 @@
namespace JS { namespace JS {
JS_DEFINE_ALLOCATOR(Console); GC_DEFINE_ALLOCATOR(Console);
JS_DEFINE_ALLOCATOR(ConsoleClient); GC_DEFINE_ALLOCATOR(ConsoleClient);
Console::Console(Realm& realm) Console::Console(Realm& realm)
: m_realm(realm) : m_realm(realm)
@ -51,7 +51,7 @@ ThrowCompletionOr<Value> Console::assert_()
auto message = PrimitiveString::create(vm, "Assertion failed"_string); auto message = PrimitiveString::create(vm, "Assertion failed"_string);
// NOTE: Assemble `data` from the function arguments. // NOTE: Assemble `data` from the function arguments.
MarkedVector<Value> data { vm.heap() }; GC::MarkedVector<Value> data { vm.heap() };
if (vm.argument_count() > 1) { if (vm.argument_count() > 1) {
data.ensure_capacity(vm.argument_count() - 1); data.ensure_capacity(vm.argument_count() - 1);
for (size_t i = 1; i < vm.argument_count(); ++i) { for (size_t i = 1; i < vm.argument_count(); ++i) {
@ -143,7 +143,7 @@ ThrowCompletionOr<Value> Console::log()
} }
// To [create table row] given tabularDataItem, rowIndex, list finalColumns, and optional list properties, perform the following steps: // To [create table row] given tabularDataItem, rowIndex, list finalColumns, and optional list properties, perform the following steps:
static ThrowCompletionOr<NonnullGCPtr<Object>> create_table_row(Realm& realm, Value row_index, Value tabular_data_item, MarkedVector<Value>& final_columns, HashMap<PropertyKey, bool>& visited_columns, HashMap<PropertyKey, bool>& properties) static ThrowCompletionOr<GC::Ref<Object>> create_table_row(Realm& realm, Value row_index, Value tabular_data_item, GC::MarkedVector<Value>& final_columns, HashMap<PropertyKey, bool>& visited_columns, HashMap<PropertyKey, bool>& properties)
{ {
auto& vm = realm.vm(); auto& vm = realm.vm();
@ -265,10 +265,10 @@ ThrowCompletionOr<Value> Console::table()
} }
// 1. Let `finalRows` be the new list, initially empty // 1. Let `finalRows` be the new list, initially empty
MarkedVector<Value> final_rows(vm.heap()); GC::MarkedVector<Value> final_rows(vm.heap());
// 2. Let `finalColumns` be the new list, initially empty // 2. Let `finalColumns` be the new list, initially empty
MarkedVector<Value> final_columns(vm.heap()); GC::MarkedVector<Value> final_columns(vm.heap());
HashMap<PropertyKey, bool> visited_columns; HashMap<PropertyKey, bool> visited_columns;
@ -328,7 +328,7 @@ ThrowCompletionOr<Value> Console::table()
TRY(final_data->set(PropertyKey("columns"), table_cols, Object::ShouldThrowExceptions::No)); TRY(final_data->set(PropertyKey("columns"), table_cols, Object::ShouldThrowExceptions::No));
// 5.4. Perform `Printer("table", finalData)` // 5.4. Perform `Printer("table", finalData)`
MarkedVector<Value> args(vm.heap()); GC::MarkedVector<Value> args(vm.heap());
args.append(Value(final_data)); args.append(Value(final_data));
return m_client->printer(LogLevel::Table, args); return m_client->printer(LogLevel::Table, args);
} }
@ -390,7 +390,7 @@ ThrowCompletionOr<Value> Console::dir()
// 2. Perform Printer("dir", « object », options). // 2. Perform Printer("dir", « object », options).
if (m_client) { if (m_client) {
MarkedVector<Value> printer_arguments { vm.heap() }; GC::MarkedVector<Value> printer_arguments { vm.heap() };
TRY_OR_THROW_OOM(vm, printer_arguments.try_append(object)); TRY_OR_THROW_OOM(vm, printer_arguments.try_append(object));
return m_client->printer(LogLevel::Dir, move(printer_arguments)); return m_client->printer(LogLevel::Dir, move(printer_arguments));
@ -430,7 +430,7 @@ ThrowCompletionOr<Value> Console::count()
auto concat = TRY_OR_THROW_OOM(vm, String::formatted("{}: {}", label, map.get(label).value())); auto concat = TRY_OR_THROW_OOM(vm, String::formatted("{}: {}", label, map.get(label).value()));
// 5. Perform Logger("count", « concat »). // 5. Perform Logger("count", « concat »).
MarkedVector<Value> concat_as_vector { vm.heap() }; GC::MarkedVector<Value> concat_as_vector { vm.heap() };
concat_as_vector.append(PrimitiveString::create(vm, move(concat))); concat_as_vector.append(PrimitiveString::create(vm, move(concat)));
if (m_client) if (m_client)
TRY(m_client->logger(LogLevel::Count, concat_as_vector)); TRY(m_client->logger(LogLevel::Count, concat_as_vector));
@ -458,7 +458,7 @@ ThrowCompletionOr<Value> Console::count_reset()
// that the given label does not have an associated count. // that the given label does not have an associated count.
auto message = TRY_OR_THROW_OOM(vm, String::formatted("\"{}\" doesn't have a count", label)); auto message = TRY_OR_THROW_OOM(vm, String::formatted("\"{}\" doesn't have a count", label));
// 2. Perform Logger("countReset", « message »); // 2. Perform Logger("countReset", « message »);
MarkedVector<Value> message_as_vector { vm.heap() }; GC::MarkedVector<Value> message_as_vector { vm.heap() };
message_as_vector.append(PrimitiveString::create(vm, move(message))); message_as_vector.append(PrimitiveString::create(vm, move(message)));
if (m_client) if (m_client)
TRY(m_client->logger(LogLevel::CountReset, message_as_vector)); TRY(m_client->logger(LogLevel::CountReset, message_as_vector));
@ -561,7 +561,7 @@ ThrowCompletionOr<Value> Console::time()
// a warning to the console indicating that a timer with label `label` has already been started. // a warning to the console indicating that a timer with label `label` has already been started.
if (m_timer_table.contains(label)) { if (m_timer_table.contains(label)) {
if (m_client) { if (m_client) {
MarkedVector<Value> timer_already_exists_warning_message_as_vector { vm.heap() }; GC::MarkedVector<Value> timer_already_exists_warning_message_as_vector { vm.heap() };
auto message = TRY_OR_THROW_OOM(vm, String::formatted("Timer '{}' already exists.", label)); auto message = TRY_OR_THROW_OOM(vm, String::formatted("Timer '{}' already exists.", label));
timer_already_exists_warning_message_as_vector.append(PrimitiveString::create(vm, move(message))); timer_already_exists_warning_message_as_vector.append(PrimitiveString::create(vm, move(message)));
@ -592,7 +592,7 @@ ThrowCompletionOr<Value> Console::time_log()
// NOTE: Warn if the timer doesn't exist. Not part of the spec yet, but discussed here: https://github.com/whatwg/console/issues/134 // NOTE: Warn if the timer doesn't exist. Not part of the spec yet, but discussed here: https://github.com/whatwg/console/issues/134
if (maybe_start_time == m_timer_table.end()) { if (maybe_start_time == m_timer_table.end()) {
if (m_client) { if (m_client) {
MarkedVector<Value> timer_does_not_exist_warning_message_as_vector { vm.heap() }; GC::MarkedVector<Value> timer_does_not_exist_warning_message_as_vector { vm.heap() };
auto message = TRY_OR_THROW_OOM(vm, String::formatted("Timer '{}' does not exist.", label)); auto message = TRY_OR_THROW_OOM(vm, String::formatted("Timer '{}' does not exist.", label));
timer_does_not_exist_warning_message_as_vector.append(PrimitiveString::create(vm, move(message))); timer_does_not_exist_warning_message_as_vector.append(PrimitiveString::create(vm, move(message)));
@ -610,7 +610,7 @@ ThrowCompletionOr<Value> Console::time_log()
auto concat = TRY_OR_THROW_OOM(vm, String::formatted("{}: {}", label, duration)); auto concat = TRY_OR_THROW_OOM(vm, String::formatted("{}: {}", label, duration));
// 5. Prepend concat to data. // 5. Prepend concat to data.
MarkedVector<Value> data { vm.heap() }; GC::MarkedVector<Value> data { vm.heap() };
data.ensure_capacity(vm.argument_count()); data.ensure_capacity(vm.argument_count());
data.append(PrimitiveString::create(vm, move(concat))); data.append(PrimitiveString::create(vm, move(concat)));
for (size_t i = 1; i < vm.argument_count(); ++i) for (size_t i = 1; i < vm.argument_count(); ++i)
@ -638,7 +638,7 @@ ThrowCompletionOr<Value> Console::time_end()
// NOTE: Warn if the timer doesn't exist. Not part of the spec yet, but discussed here: https://github.com/whatwg/console/issues/134 // NOTE: Warn if the timer doesn't exist. Not part of the spec yet, but discussed here: https://github.com/whatwg/console/issues/134
if (maybe_start_time == m_timer_table.end()) { if (maybe_start_time == m_timer_table.end()) {
if (m_client) { if (m_client) {
MarkedVector<Value> timer_does_not_exist_warning_message_as_vector { vm.heap() }; GC::MarkedVector<Value> timer_does_not_exist_warning_message_as_vector { vm.heap() };
auto message = TRY_OR_THROW_OOM(vm, String::formatted("Timer '{}' does not exist.", label)); auto message = TRY_OR_THROW_OOM(vm, String::formatted("Timer '{}' does not exist.", label));
timer_does_not_exist_warning_message_as_vector.append(PrimitiveString::create(vm, move(message))); timer_does_not_exist_warning_message_as_vector.append(PrimitiveString::create(vm, move(message)));
@ -660,18 +660,18 @@ ThrowCompletionOr<Value> Console::time_end()
// 6. Perform Printer("timeEnd", « concat »). // 6. Perform Printer("timeEnd", « concat »).
if (m_client) { if (m_client) {
MarkedVector<Value> concat_as_vector { vm.heap() }; GC::MarkedVector<Value> concat_as_vector { vm.heap() };
concat_as_vector.append(PrimitiveString::create(vm, move(concat))); concat_as_vector.append(PrimitiveString::create(vm, move(concat)));
TRY(m_client->printer(LogLevel::TimeEnd, move(concat_as_vector))); TRY(m_client->printer(LogLevel::TimeEnd, move(concat_as_vector)));
} }
return js_undefined(); return js_undefined();
} }
MarkedVector<Value> Console::vm_arguments() GC::MarkedVector<Value> Console::vm_arguments()
{ {
auto& vm = realm().vm(); auto& vm = realm().vm();
MarkedVector<Value> arguments { vm.heap() }; GC::MarkedVector<Value> arguments { vm.heap() };
arguments.ensure_capacity(vm.argument_count()); arguments.ensure_capacity(vm.argument_count());
for (size_t i = 0; i < vm.argument_count(); ++i) { for (size_t i = 0; i < vm.argument_count(); ++i) {
arguments.append(vm.argument(i)); arguments.append(vm.argument(i));
@ -709,7 +709,7 @@ void Console::report_exception(JS::Error const& exception, bool in_promise) cons
m_client->report_exception(exception, in_promise); m_client->report_exception(exception, in_promise);
} }
ThrowCompletionOr<String> Console::value_vector_to_string(MarkedVector<Value> const& values) ThrowCompletionOr<String> Console::value_vector_to_string(GC::MarkedVector<Value> const& values)
{ {
auto& vm = realm().vm(); auto& vm = realm().vm();
StringBuilder builder; StringBuilder builder;
@ -767,7 +767,7 @@ void ConsoleClient::visit_edges(Visitor& visitor)
} }
// 2.1. Logger(logLevel, args), https://console.spec.whatwg.org/#logger // 2.1. Logger(logLevel, args), https://console.spec.whatwg.org/#logger
ThrowCompletionOr<Value> ConsoleClient::logger(Console::LogLevel log_level, MarkedVector<Value> const& args) ThrowCompletionOr<Value> ConsoleClient::logger(Console::LogLevel log_level, GC::MarkedVector<Value> const& args)
{ {
auto& vm = m_console->realm().vm(); auto& vm = m_console->realm().vm();
@ -783,7 +783,7 @@ ThrowCompletionOr<Value> ConsoleClient::logger(Console::LogLevel log_level, Mark
// 4. If rest is empty, perform Printer(logLevel, « first ») and return. // 4. If rest is empty, perform Printer(logLevel, « first ») and return.
if (rest_size == 0) { if (rest_size == 0) {
MarkedVector<Value> first_as_vector { vm.heap() }; GC::MarkedVector<Value> first_as_vector { vm.heap() };
first_as_vector.append(first); first_as_vector.append(first);
return printer(log_level, move(first_as_vector)); return printer(log_level, move(first_as_vector));
} }
@ -799,7 +799,7 @@ ThrowCompletionOr<Value> ConsoleClient::logger(Console::LogLevel log_level, Mark
} }
// 2.2. Formatter(args), https://console.spec.whatwg.org/#formatter // 2.2. Formatter(args), https://console.spec.whatwg.org/#formatter
ThrowCompletionOr<MarkedVector<Value>> ConsoleClient::formatter(MarkedVector<Value> const& args) ThrowCompletionOr<GC::MarkedVector<Value>> ConsoleClient::formatter(GC::MarkedVector<Value> const& args)
{ {
auto& realm = m_console->realm(); auto& realm = m_console->realm();
auto& vm = realm.vm(); auto& vm = realm.vm();
@ -901,7 +901,7 @@ ThrowCompletionOr<MarkedVector<Value>> ConsoleClient::formatter(MarkedVector<Val
} }
// 7. Let result be a list containing target together with the elements of args starting from the third onward. // 7. Let result be a list containing target together with the elements of args starting from the third onward.
MarkedVector<Value> result { vm.heap() }; GC::MarkedVector<Value> result { vm.heap() };
result.ensure_capacity(args.size() - 1); result.ensure_capacity(args.size() - 1);
result.empend(PrimitiveString::create(vm, move(target))); result.empend(PrimitiveString::create(vm, move(target)));
for (size_t i = 2; i < args.size(); ++i) for (size_t i = 2; i < args.size(); ++i)
@ -911,7 +911,7 @@ ThrowCompletionOr<MarkedVector<Value>> ConsoleClient::formatter(MarkedVector<Val
return formatter(result); return formatter(result);
} }
ThrowCompletionOr<String> ConsoleClient::generically_format_values(MarkedVector<Value> const& values) ThrowCompletionOr<String> ConsoleClient::generically_format_values(GC::MarkedVector<Value> const& values)
{ {
AllocatingMemoryStream stream; AllocatingMemoryStream stream;
auto& vm = m_console->realm().vm(); auto& vm = m_console->realm().vm();

View file

@ -13,9 +13,9 @@
#include <AK/String.h> #include <AK/String.h>
#include <AK/Vector.h> #include <AK/Vector.h>
#include <LibCore/ElapsedTimer.h> #include <LibCore/ElapsedTimer.h>
#include <LibGC/CellAllocator.h>
#include <LibJS/Forward.h> #include <LibJS/Forward.h>
#include <LibJS/Heap/Cell.h> #include <LibJS/Heap/Cell.h>
#include <LibJS/Heap/CellAllocator.h>
#include <LibJS/Runtime/Value.h> #include <LibJS/Runtime/Value.h>
namespace JS { namespace JS {
@ -24,8 +24,8 @@ class ConsoleClient;
// https://console.spec.whatwg.org // https://console.spec.whatwg.org
class Console : public Cell { class Console : public Cell {
JS_CELL(Console, Cell); GC_CELL(Console, Cell);
JS_DECLARE_ALLOCATOR(Console); GC_DECLARE_ALLOCATOR(Console);
public: public:
virtual ~Console() override; virtual ~Console() override;
@ -63,7 +63,7 @@ public:
Realm& realm() const { return m_realm; } Realm& realm() const { return m_realm; }
MarkedVector<Value> vm_arguments(); GC::MarkedVector<Value> vm_arguments();
HashMap<String, unsigned>& counters() { return m_counters; } HashMap<String, unsigned>& counters() { return m_counters; }
HashMap<String, unsigned> const& counters() const { return m_counters; } HashMap<String, unsigned> const& counters() const { return m_counters; }
@ -95,11 +95,11 @@ private:
virtual void visit_edges(Visitor&) override; virtual void visit_edges(Visitor&) override;
ThrowCompletionOr<String> value_vector_to_string(MarkedVector<Value> const&); ThrowCompletionOr<String> value_vector_to_string(GC::MarkedVector<Value> const&);
ThrowCompletionOr<String> format_time_since(Core::ElapsedTimer timer); ThrowCompletionOr<String> format_time_since(Core::ElapsedTimer timer);
NonnullGCPtr<Realm> m_realm; GC::Ref<Realm> m_realm;
GCPtr<ConsoleClient> m_client; GC::Ptr<ConsoleClient> m_client;
HashMap<String, unsigned> m_counters; HashMap<String, unsigned> m_counters;
HashMap<String, Core::ElapsedTimer> m_timer_table; HashMap<String, Core::ElapsedTimer> m_timer_table;
@ -107,14 +107,14 @@ private:
}; };
class ConsoleClient : public Cell { class ConsoleClient : public Cell {
JS_CELL(ConsoleClient, Cell); GC_CELL(ConsoleClient, Cell);
JS_DECLARE_ALLOCATOR(ConsoleClient); GC_DECLARE_ALLOCATOR(ConsoleClient);
public: public:
using PrinterArguments = Variant<Console::Group, Console::Trace, MarkedVector<Value>>; using PrinterArguments = Variant<Console::Group, Console::Trace, GC::MarkedVector<Value>>;
ThrowCompletionOr<Value> logger(Console::LogLevel log_level, MarkedVector<Value> const& args); ThrowCompletionOr<Value> logger(Console::LogLevel log_level, GC::MarkedVector<Value> const& args);
ThrowCompletionOr<MarkedVector<Value>> formatter(MarkedVector<Value> const& args); ThrowCompletionOr<GC::MarkedVector<Value>> formatter(GC::MarkedVector<Value> const& args);
virtual ThrowCompletionOr<Value> printer(Console::LogLevel log_level, PrinterArguments) = 0; virtual ThrowCompletionOr<Value> printer(Console::LogLevel log_level, PrinterArguments) = 0;
virtual void add_css_style_to_current_message(StringView) { } virtual void add_css_style_to_current_message(StringView) { }
@ -123,14 +123,14 @@ public:
virtual void clear() = 0; virtual void clear() = 0;
virtual void end_group() = 0; virtual void end_group() = 0;
ThrowCompletionOr<String> generically_format_values(MarkedVector<Value> const&); ThrowCompletionOr<String> generically_format_values(GC::MarkedVector<Value> const&);
protected: protected:
explicit ConsoleClient(Console&); explicit ConsoleClient(Console&);
virtual ~ConsoleClient() override; virtual ~ConsoleClient() override;
virtual void visit_edges(Visitor& visitor) override; virtual void visit_edges(Visitor& visitor) override;
NonnullGCPtr<Console> m_console; GC::Ref<Console> m_console;
}; };
} }

View file

@ -21,7 +21,7 @@
namespace JS::Test262 { namespace JS::Test262 {
JS_DEFINE_ALLOCATOR($262Object); GC_DEFINE_ALLOCATOR($262Object);
$262Object::$262Object(Realm& realm) $262Object::$262Object(Realm& realm)
: Object(Object::ConstructWithoutPrototypeTag::Tag, realm) : Object(Object::ConstructWithoutPrototypeTag::Tag, realm)
@ -62,7 +62,7 @@ JS_DEFINE_NATIVE_FUNCTION($262Object::clear_kept_objects)
JS_DEFINE_NATIVE_FUNCTION($262Object::create_realm) JS_DEFINE_NATIVE_FUNCTION($262Object::create_realm)
{ {
JS::GCPtr<JS::Test262::GlobalObject> global_object; GC::Ptr<JS::Test262::GlobalObject> global_object;
auto root_execution_context = MUST(JS::Realm::initialize_host_defined_realm( auto root_execution_context = MUST(JS::Realm::initialize_host_defined_realm(
vm, vm,
[&](JS::Realm& realm) -> JS::GlobalObject* { [&](JS::Realm& realm) -> JS::GlobalObject* {

View file

@ -15,7 +15,7 @@ namespace JS::Test262 {
class $262Object final : public Object { class $262Object final : public Object {
JS_OBJECT($262Object, Object); JS_OBJECT($262Object, Object);
JS_DECLARE_ALLOCATOR($262Object); GC_DECLARE_ALLOCATOR($262Object);
public: public:
virtual void initialize(Realm&) override; virtual void initialize(Realm&) override;
@ -26,8 +26,8 @@ private:
virtual void visit_edges(Visitor&) override; virtual void visit_edges(Visitor&) override;
GCPtr<AgentObject> m_agent; GC::Ptr<AgentObject> m_agent;
GCPtr<IsHTMLDDA> m_is_htmldda; GC::Ptr<IsHTMLDDA> m_is_htmldda;
JS_DECLARE_NATIVE_FUNCTION(clear_kept_objects); JS_DECLARE_NATIVE_FUNCTION(clear_kept_objects);
JS_DECLARE_NATIVE_FUNCTION(create_realm); JS_DECLARE_NATIVE_FUNCTION(create_realm);

View file

@ -12,7 +12,7 @@
namespace JS::Test262 { namespace JS::Test262 {
JS_DEFINE_ALLOCATOR(AgentObject); GC_DEFINE_ALLOCATOR(AgentObject);
AgentObject::AgentObject(Realm& realm) AgentObject::AgentObject(Realm& realm)
: Object(Object::ConstructWithoutPrototypeTag::Tag, realm) : Object(Object::ConstructWithoutPrototypeTag::Tag, realm)

View file

@ -13,7 +13,7 @@ namespace JS::Test262 {
class AgentObject final : public Object { class AgentObject final : public Object {
JS_OBJECT(AgentObject, Object); JS_OBJECT(AgentObject, Object);
JS_DECLARE_ALLOCATOR(AgentObject); GC_DECLARE_ALLOCATOR(AgentObject);
public: public:
virtual void initialize(Realm&) override; virtual void initialize(Realm&) override;

View file

@ -14,7 +14,7 @@
namespace JS::Test262 { namespace JS::Test262 {
JS_DEFINE_ALLOCATOR(GlobalObject); GC_DEFINE_ALLOCATOR(GlobalObject);
void GlobalObject::initialize(Realm& realm) void GlobalObject::initialize(Realm& realm)
{ {

View file

@ -13,7 +13,7 @@ namespace JS::Test262 {
class GlobalObject final : public JS::GlobalObject { class GlobalObject final : public JS::GlobalObject {
JS_OBJECT(GlobalObject, JS::GlobalObject); JS_OBJECT(GlobalObject, JS::GlobalObject);
JS_DECLARE_ALLOCATOR(GlobalObject); GC_DECLARE_ALLOCATOR(GlobalObject);
public: public:
virtual void initialize(Realm&) override; virtual void initialize(Realm&) override;
@ -29,7 +29,7 @@ private:
virtual void visit_edges(Visitor&) override; virtual void visit_edges(Visitor&) override;
GCPtr<$262Object> m_$262; GC::Ptr<$262Object> m_$262;
JS_DECLARE_NATIVE_FUNCTION(print); JS_DECLARE_NATIVE_FUNCTION(print);
}; };

View file

@ -9,7 +9,7 @@
namespace JS::Test262 { namespace JS::Test262 {
JS_DEFINE_ALLOCATOR(IsHTMLDDA); GC_DEFINE_ALLOCATOR(IsHTMLDDA);
IsHTMLDDA::IsHTMLDDA(Realm& realm) IsHTMLDDA::IsHTMLDDA(Realm& realm)
// NativeFunction without prototype is currently not possible (only due to the lack of a ctor that supports it) // NativeFunction without prototype is currently not possible (only due to the lack of a ctor that supports it)

View file

@ -12,7 +12,7 @@ namespace JS::Test262 {
class IsHTMLDDA final : public NativeFunction { class IsHTMLDDA final : public NativeFunction {
JS_OBJECT(IsHTMLDDA, NativeFunction); JS_OBJECT(IsHTMLDDA, NativeFunction);
JS_DECLARE_ALLOCATOR(IsHTMLDDA); GC_DECLARE_ALLOCATOR(IsHTMLDDA);
public: public:
virtual ~IsHTMLDDA() override = default; virtual ~IsHTMLDDA() override = default;

View file

@ -15,7 +15,7 @@
namespace JS { namespace JS {
JS_DEFINE_ALLOCATOR(CyclicModule); GC_DEFINE_ALLOCATOR(CyclicModule);
CyclicModule::CyclicModule(Realm& realm, StringView filename, bool has_top_level_await, Vector<ModuleRequest> requested_modules, Script::HostDefined* host_defined) CyclicModule::CyclicModule(Realm& realm, StringView filename, bool has_top_level_await, Vector<ModuleRequest> requested_modules, Script::HostDefined* host_defined)
: Module(realm, filename, host_defined) : Module(realm, filename, host_defined)
@ -45,7 +45,7 @@ void GraphLoadingState::visit_edges(Cell::Visitor& visitor)
} }
// 16.2.1.5.1 LoadRequestedModules ( [ hostDefined ] ), https://tc39.es/ecma262/#sec-LoadRequestedModules // 16.2.1.5.1 LoadRequestedModules ( [ hostDefined ] ), https://tc39.es/ecma262/#sec-LoadRequestedModules
PromiseCapability& CyclicModule::load_requested_modules(GCPtr<GraphLoadingState::HostDefined> host_defined) PromiseCapability& CyclicModule::load_requested_modules(GC::Ptr<GraphLoadingState::HostDefined> host_defined)
{ {
// 1. If hostDefined is not present, let hostDefined be EMPTY. // 1. If hostDefined is not present, let hostDefined be EMPTY.
// NOTE: The empty state is handled by hostDefined being an optional without value. // NOTE: The empty state is handled by hostDefined being an optional without value.
@ -54,7 +54,7 @@ PromiseCapability& CyclicModule::load_requested_modules(GCPtr<GraphLoadingState:
auto promise_capability = MUST(new_promise_capability(vm(), vm().current_realm()->intrinsics().promise_constructor())); auto promise_capability = MUST(new_promise_capability(vm(), vm().current_realm()->intrinsics().promise_constructor()));
// 3. Let state be the GraphLoadingState Record { [[IsLoading]]: true, [[PendingModulesCount]]: 1, [[Visited]]: « », [[PromiseCapability]]: pc, [[HostDefined]]: hostDefined }. // 3. Let state be the GraphLoadingState Record { [[IsLoading]]: true, [[PendingModulesCount]]: 1, [[Visited]]: « », [[PromiseCapability]]: pc, [[HostDefined]]: hostDefined }.
auto state = heap().allocate<GraphLoadingState>(promise_capability, true, 1, HashTable<JS::GCPtr<CyclicModule>> {}, move(host_defined)); auto state = heap().allocate<GraphLoadingState>(promise_capability, true, 1, HashTable<GC::Ptr<CyclicModule>> {}, move(host_defined));
// 4. Perform InnerModuleLoading(state, module). // 4. Perform InnerModuleLoading(state, module).
inner_module_loading(state); inner_module_loading(state);
@ -101,7 +101,7 @@ void CyclicModule::inner_module_loading(JS::GraphLoadingState& state)
// ii. Else, // ii. Else,
if (!found_record_in_loaded_modules) { if (!found_record_in_loaded_modules) {
// 1. Perform HostLoadImportedModule(module, required, state.[[HostDefined]], state). // 1. Perform HostLoadImportedModule(module, required, state.[[HostDefined]], state).
vm().host_load_imported_module(NonnullGCPtr<CyclicModule> { *this }, required, state.host_defined, NonnullGCPtr<GraphLoadingState> { state }); vm().host_load_imported_module(GC::Ref<CyclicModule> { *this }, required, state.host_defined, GC::Ref<GraphLoadingState> { state });
// 2. NOTE: HostLoadImportedModule will call FinishLoadingImportedModule, which re-enters the graph loading process through ContinueModuleLoading. // 2. NOTE: HostLoadImportedModule will call FinishLoadingImportedModule, which re-enters the graph loading process through ContinueModuleLoading.
} }
@ -138,7 +138,7 @@ void CyclicModule::inner_module_loading(JS::GraphLoadingState& state)
} }
// 16.2.1.5.1.2 ContinueModuleLoading ( state, moduleCompletion ), https://tc39.es/ecma262/#sec-ContinueModuleLoading // 16.2.1.5.1.2 ContinueModuleLoading ( state, moduleCompletion ), https://tc39.es/ecma262/#sec-ContinueModuleLoading
void continue_module_loading(GraphLoadingState& state, ThrowCompletionOr<NonnullGCPtr<Module>> const& module_completion) void continue_module_loading(GraphLoadingState& state, ThrowCompletionOr<GC::Ref<Module>> const& module_completion)
{ {
// 1. If state.[[IsLoading]] is false, return UNUSED. // 1. If state.[[IsLoading]] is false, return UNUSED.
if (!state.is_loading) if (!state.is_loading)
@ -469,7 +469,7 @@ ThrowCompletionOr<u32> CyclicModule::inner_module_evaluation(VM& vm, Vector<Modu
if (!is<CyclicModule>(*required_module)) if (!is<CyclicModule>(*required_module))
continue; continue;
JS::NonnullGCPtr<CyclicModule> cyclic_module = verify_cast<CyclicModule>(*required_module); GC::Ref<CyclicModule> cyclic_module = verify_cast<CyclicModule>(*required_module);
// i. Assert: requiredModule.[[Status]] is either evaluating, evaluating-async, or evaluated. // i. Assert: requiredModule.[[Status]] is either evaluating, evaluating-async, or evaluated.
VERIFY(cyclic_module->m_status == ModuleStatus::Evaluating || cyclic_module->m_status == ModuleStatus::EvaluatingAsync || cyclic_module->m_status == ModuleStatus::Evaluated); VERIFY(cyclic_module->m_status == ModuleStatus::Evaluating || cyclic_module->m_status == ModuleStatus::EvaluatingAsync || cyclic_module->m_status == ModuleStatus::Evaluated);
@ -578,7 +578,7 @@ ThrowCompletionOr<void> CyclicModule::initialize_environment(VM&)
VERIFY_NOT_REACHED(); VERIFY_NOT_REACHED();
} }
ThrowCompletionOr<void> CyclicModule::execute_module(VM&, GCPtr<PromiseCapability>) ThrowCompletionOr<void> CyclicModule::execute_module(VM&, GC::Ptr<PromiseCapability>)
{ {
// Note: In ecma262 this is never called on a cyclic module only on SourceTextModules. // Note: In ecma262 this is never called on a cyclic module only on SourceTextModules.
// So this check is to make sure we don't accidentally call this. // So this check is to make sure we don't accidentally call this.
@ -807,7 +807,7 @@ void CyclicModule::async_module_execution_rejected(VM& vm, Value error)
} }
// 16.2.1.7 GetImportedModule ( referrer, specifier ), https://tc39.es/ecma262/#sec-GetImportedModule // 16.2.1.7 GetImportedModule ( referrer, specifier ), https://tc39.es/ecma262/#sec-GetImportedModule
NonnullGCPtr<Module> CyclicModule::get_imported_module(ModuleRequest const& request) GC::Ref<Module> CyclicModule::get_imported_module(ModuleRequest const& request)
{ {
// 1. Assert: Exactly one element of referrer.[[LoadedModules]] is a Record whose [[Specifier]] is specifier, // 1. Assert: Exactly one element of referrer.[[LoadedModules]] is a Record whose [[Specifier]] is specifier,
// since LoadRequestedModules has completed successfully on referrer prior to invoking this abstract operation. // since LoadRequestedModules has completed successfully on referrer prior to invoking this abstract operation.
@ -829,7 +829,7 @@ NonnullGCPtr<Module> CyclicModule::get_imported_module(ModuleRequest const& requ
} }
// 13.3.10.1.1 ContinueDynamicImport ( promiseCapability, moduleCompletion ), https://tc39.es/ecma262/#sec-ContinueDynamicImport // 13.3.10.1.1 ContinueDynamicImport ( promiseCapability, moduleCompletion ), https://tc39.es/ecma262/#sec-ContinueDynamicImport
void continue_dynamic_import(NonnullGCPtr<PromiseCapability> promise_capability, ThrowCompletionOr<NonnullGCPtr<Module>> const& module_completion) void continue_dynamic_import(GC::Ref<PromiseCapability> promise_capability, ThrowCompletionOr<GC::Ref<Module>> const& module_completion)
{ {
auto& vm = promise_capability->vm(); auto& vm = promise_capability->vm();

View file

@ -24,8 +24,8 @@ enum class ModuleStatus {
// 16.2.1.5 Cyclic Module Records, https://tc39.es/ecma262/#cyclic-module-record // 16.2.1.5 Cyclic Module Records, https://tc39.es/ecma262/#cyclic-module-record
class CyclicModule : public Module { class CyclicModule : public Module {
JS_CELL(CyclicModule, Module); GC_CELL(CyclicModule, Module);
JS_DECLARE_ALLOCATOR(CyclicModule); GC_DECLARE_ALLOCATOR(CyclicModule);
public: public:
virtual ~CyclicModule() override; virtual ~CyclicModule() override;
@ -35,7 +35,7 @@ public:
virtual ThrowCompletionOr<void> link(VM& vm) override final; virtual ThrowCompletionOr<void> link(VM& vm) override final;
virtual ThrowCompletionOr<Promise*> evaluate(VM& vm) override final; virtual ThrowCompletionOr<Promise*> evaluate(VM& vm) override final;
virtual PromiseCapability& load_requested_modules(GCPtr<GraphLoadingState::HostDefined>) override; virtual PromiseCapability& load_requested_modules(GC::Ptr<GraphLoadingState::HostDefined>) override;
virtual void inner_module_loading(GraphLoadingState& state); virtual void inner_module_loading(GraphLoadingState& state);
Vector<ModuleRequest> const& requested_modules() const { return m_requested_modules; } Vector<ModuleRequest> const& requested_modules() const { return m_requested_modules; }
@ -51,30 +51,30 @@ protected:
virtual ThrowCompletionOr<u32> inner_module_evaluation(VM& vm, Vector<Module*>& stack, u32 index) override final; virtual ThrowCompletionOr<u32> inner_module_evaluation(VM& vm, Vector<Module*>& stack, u32 index) override final;
virtual ThrowCompletionOr<void> initialize_environment(VM& vm); virtual ThrowCompletionOr<void> initialize_environment(VM& vm);
virtual ThrowCompletionOr<void> execute_module(VM& vm, GCPtr<PromiseCapability> capability = {}); virtual ThrowCompletionOr<void> execute_module(VM& vm, GC::Ptr<PromiseCapability> capability = {});
[[nodiscard]] NonnullGCPtr<Module> get_imported_module(ModuleRequest const&); [[nodiscard]] GC::Ref<Module> get_imported_module(ModuleRequest const&);
void execute_async_module(VM& vm); void execute_async_module(VM& vm);
void gather_available_ancestors(Vector<CyclicModule*>& exec_list); void gather_available_ancestors(Vector<CyclicModule*>& exec_list);
void async_module_execution_fulfilled(VM& vm); void async_module_execution_fulfilled(VM& vm);
void async_module_execution_rejected(VM& vm, Value error); void async_module_execution_rejected(VM& vm, Value error);
ModuleStatus m_status { ModuleStatus::New }; // [[Status]] ModuleStatus m_status { ModuleStatus::New }; // [[Status]]
ThrowCompletionOr<void> m_evaluation_error; // [[EvaluationError]] ThrowCompletionOr<void> m_evaluation_error; // [[EvaluationError]]
Optional<u32> m_dfs_index; // [[DFSIndex]] Optional<u32> m_dfs_index; // [[DFSIndex]]
Optional<u32> m_dfs_ancestor_index; // [[DFSAncestorIndex]] Optional<u32> m_dfs_ancestor_index; // [[DFSAncestorIndex]]
Vector<ModuleRequest> m_requested_modules; // [[RequestedModules]] Vector<ModuleRequest> m_requested_modules; // [[RequestedModules]]
Vector<ModuleWithSpecifier> m_loaded_modules; // [[LoadedModules]] Vector<ModuleWithSpecifier> m_loaded_modules; // [[LoadedModules]]
GCPtr<CyclicModule> m_cycle_root; // [[CycleRoot]] GC::Ptr<CyclicModule> m_cycle_root; // [[CycleRoot]]
bool m_has_top_level_await { false }; // [[HasTLA]] bool m_has_top_level_await { false }; // [[HasTLA]]
bool m_async_evaluation { false }; // [[AsyncEvaluation]] bool m_async_evaluation { false }; // [[AsyncEvaluation]]
GCPtr<PromiseCapability> m_top_level_capability; // [[TopLevelCapability]] GC::Ptr<PromiseCapability> m_top_level_capability; // [[TopLevelCapability]]
Vector<GCPtr<CyclicModule>> m_async_parent_modules; // [[AsyncParentModules]] Vector<GC::Ptr<CyclicModule>> m_async_parent_modules; // [[AsyncParentModules]]
Optional<u32> m_pending_async_dependencies; // [[PendingAsyncDependencies]] Optional<u32> m_pending_async_dependencies; // [[PendingAsyncDependencies]]
}; };
void continue_module_loading(GraphLoadingState&, ThrowCompletionOr<NonnullGCPtr<Module>> const&); void continue_module_loading(GraphLoadingState&, ThrowCompletionOr<GC::Ref<Module>> const&);
void continue_dynamic_import(NonnullGCPtr<PromiseCapability>, ThrowCompletionOr<NonnullGCPtr<Module>> const& module_completion); void continue_dynamic_import(GC::Ref<PromiseCapability>, ThrowCompletionOr<GC::Ref<Module>> const& module_completion);
} }

View file

@ -159,15 +159,12 @@ class BigInt;
class BoundFunction; class BoundFunction;
struct CachedSourceRange; struct CachedSourceRange;
class Cell; class Cell;
class CellImpl;
class CellAllocator;
class ClassExpression; class ClassExpression;
struct ClassFieldDefinition; struct ClassFieldDefinition;
class Completion; class Completion;
class Console; class Console;
class CyclicModule; class CyclicModule;
class DeclarativeEnvironment; class DeclarativeEnvironment;
class DeferGC;
class ECMAScriptFunctionObject; class ECMAScriptFunctionObject;
class Environment; class Environment;
class Error; class Error;
@ -183,9 +180,6 @@ struct FunctionParameter;
class GlobalEnvironment; class GlobalEnvironment;
class GlobalObject; class GlobalObject;
struct GraphLoadingState; struct GraphLoadingState;
class HandleImpl;
class Heap;
class HeapBlock;
struct ImportEntry; struct ImportEntry;
class ImportStatement; class ImportStatement;
class Identifier; class Identifier;
@ -195,7 +189,6 @@ class MemberExpression;
class MetaProperty; class MetaProperty;
class Module; class Module;
struct ModuleRequest; struct ModuleRequest;
class NanBoxedValue;
class NativeFunction; class NativeFunction;
class ObjectEnvironment; class ObjectEnvironment;
class Parser; class Parser;
@ -223,7 +216,6 @@ class Utf16String;
class VM; class VM;
class PrototypeChainValidity; class PrototypeChainValidity;
class Value; class Value;
class WeakContainer;
class WrappedFunction; class WrappedFunction;
enum class DeclarationKind; enum class DeclarationKind;
struct AlreadyResolved; struct AlreadyResolved;
@ -301,22 +293,10 @@ struct TimeZoneMethods;
struct PartialDurationRecord; struct PartialDurationRecord;
}; };
template<typename T>
class HeapFunction;
template<typename T> template<typename T>
requires(!IsLvalueReference<T>) requires(!IsLvalueReference<T>)
class ThrowCompletionOr; class ThrowCompletionOr;
template<class T>
class Handle;
template<class T, size_t inline_capacity = 0>
class ConservativeVector;
template<class T, size_t inline_capacity = 0>
class MarkedVector;
namespace Bytecode { namespace Bytecode {
class BasicBlock; class BasicBlock;
enum class Builtin : u8; enum class Builtin : u8;

View file

@ -6,12 +6,13 @@
#pragma once #pragma once
#include <LibJS/Heap/CellImpl.h> #include <LibGC/Cell.h>
#include <LibJS/Forward.h>
namespace JS { namespace JS {
class Cell : public CellImpl { class Cell : public GC::Cell {
JS_CELL(Cell, CellImpl); GC_CELL(Cell, GC::Cell);
public: public:
virtual void initialize(Realm&); virtual void initialize(Realm&);

View file

@ -1,25 +0,0 @@
/*
* Copyright (c) 2020, Andreas Kling <andreas@ladybird.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#include <LibJS/Heap/CellImpl.h>
#include <LibJS/Heap/Handle.h>
#include <LibJS/Heap/Heap.h>
namespace JS {
HandleImpl::HandleImpl(CellImpl* cell, SourceLocation location)
: m_cell(cell)
, m_location(location)
{
m_cell->heap().did_create_handle({}, *this);
}
HandleImpl::~HandleImpl()
{
m_cell->heap().did_destroy_handle({}, *this);
}
}

View file

@ -1,169 +0,0 @@
/*
* Copyright (c) 2020, Andreas Kling <andreas@ladybird.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#pragma once
#include <AK/Badge.h>
#include <AK/IntrusiveList.h>
#include <AK/Noncopyable.h>
#include <AK/RefCounted.h>
#include <AK/RefPtr.h>
#include <AK/SourceLocation.h>
#include <LibJS/Forward.h>
#include <LibJS/Heap/GCPtr.h>
namespace JS {
class HandleImpl : public RefCounted<HandleImpl> {
AK_MAKE_NONCOPYABLE(HandleImpl);
AK_MAKE_NONMOVABLE(HandleImpl);
public:
~HandleImpl();
CellImpl* cell() { return m_cell; }
CellImpl const* cell() const { return m_cell; }
SourceLocation const& source_location() const { return m_location; }
private:
template<class T>
friend class Handle;
explicit HandleImpl(CellImpl*, SourceLocation location);
GCPtr<CellImpl> m_cell;
SourceLocation m_location;
IntrusiveListNode<HandleImpl> m_list_node;
public:
using List = IntrusiveList<&HandleImpl::m_list_node>;
};
template<class T>
class Handle {
public:
Handle() = default;
static Handle create(T* cell, SourceLocation location = SourceLocation::current())
{
return Handle(adopt_ref(*new HandleImpl(const_cast<RemoveConst<T>*>(cell), location)));
}
Handle(T* cell, SourceLocation location = SourceLocation::current())
{
if (cell)
m_impl = adopt_ref(*new HandleImpl(cell, location));
}
Handle(T& cell, SourceLocation location = SourceLocation::current())
: m_impl(adopt_ref(*new HandleImpl(&cell, location)))
{
}
Handle(GCPtr<T> cell, SourceLocation location = SourceLocation::current())
: Handle(cell.ptr(), location)
{
}
Handle(NonnullGCPtr<T> cell, SourceLocation location = SourceLocation::current())
: Handle(*cell, location)
{
}
T* cell() const
{
if (!m_impl)
return nullptr;
return static_cast<T*>(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 Handle(NonnullRefPtr<HandleImpl> impl)
: m_impl(move(impl))
{
}
RefPtr<HandleImpl> m_impl;
};
template<class T>
inline Handle<T> make_handle(T* cell, SourceLocation location = SourceLocation::current())
{
if (!cell)
return Handle<T> {};
return Handle<T>::create(cell, location);
}
template<class T>
inline Handle<T> make_handle(T& cell, SourceLocation location = SourceLocation::current())
{
return Handle<T>::create(&cell, location);
}
template<class T>
inline Handle<T> make_handle(GCPtr<T> cell, SourceLocation location = SourceLocation::current())
{
if (!cell)
return Handle<T> {};
return Handle<T>::create(cell.ptr(), location);
}
template<class T>
inline Handle<T> make_handle(NonnullGCPtr<T> cell, SourceLocation location = SourceLocation::current())
{
return Handle<T>::create(cell.ptr(), location);
}
}
namespace AK {
template<typename T>
struct Traits<JS::Handle<T>> : public DefaultTraits<JS::Handle<T>> {
static unsigned hash(JS::Handle<T> const& handle) { return Traits<T>::hash(handle); }
};
namespace Detail {
template<typename T>
inline constexpr bool IsHashCompatible<JS::Handle<T>, T> = true;
template<typename T>
inline constexpr bool IsHashCompatible<T, JS::Handle<T>> = true;
}
}

View file

@ -1,50 +0,0 @@
/*
* Copyright (c) 2023, Andreas Kling <andreas@ladybird.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#pragma once
#include <AK/Function.h>
#include <LibJS/Heap/CellImpl.h>
#include <LibJS/Heap/Heap.h>
namespace JS {
template<typename T>
class HeapFunction final : public CellImpl {
JS_CELL(HeapFunction, CellImpl);
public:
static NonnullGCPtr<HeapFunction> create(Heap& heap, Function<T> function)
{
return heap.allocate<HeapFunction>(move(function));
}
virtual ~HeapFunction() override = default;
[[nodiscard]] Function<T> const& function() const { return m_function; }
private:
HeapFunction(Function<T> 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());
}
Function<T> m_function;
};
template<typename Callable, typename T = EquivalentFunctionType<Callable>>
static NonnullGCPtr<HeapFunction<T>> create_heap_function(Heap& heap, Callable&& function)
{
return HeapFunction<T>::create(heap, Function<T> { forward<Callable>(function) });
}
}

View file

@ -15,8 +15,8 @@
namespace JS { namespace JS {
JS_DEFINE_ALLOCATOR(Module); GC_DEFINE_ALLOCATOR(Module);
JS_DEFINE_ALLOCATOR(GraphLoadingState); GC_DEFINE_ALLOCATOR(GraphLoadingState);
Module::Module(Realm& realm, ByteString filename, Script::HostDefined* host_defined) Module::Module(Realm& realm, ByteString filename, Script::HostDefined* host_defined)
: m_realm(realm) : m_realm(realm)
@ -68,14 +68,14 @@ ThrowCompletionOr<u32> Module::inner_module_evaluation(VM& vm, Vector<Module*>&,
} }
// 16.2.1.9 FinishLoadingImportedModule ( referrer, specifier, payload, result ), https://tc39.es/ecma262/#sec-FinishLoadingImportedModule // 16.2.1.9 FinishLoadingImportedModule ( referrer, specifier, payload, result ), https://tc39.es/ecma262/#sec-FinishLoadingImportedModule
void finish_loading_imported_module(ImportedModuleReferrer referrer, ModuleRequest const& module_request, ImportedModulePayload payload, ThrowCompletionOr<NonnullGCPtr<Module>> const& result) void finish_loading_imported_module(ImportedModuleReferrer referrer, ModuleRequest const& module_request, ImportedModulePayload payload, ThrowCompletionOr<GC::Ref<Module>> const& result)
{ {
// 1. If result is a normal completion, then // 1. If result is a normal completion, then
if (!result.is_error()) { if (!result.is_error()) {
// NOTE: Only Script and CyclicModule referrers have the [[LoadedModules]] internal slot. // NOTE: Only Script and CyclicModule referrers have the [[LoadedModules]] internal slot.
if (referrer.has<NonnullGCPtr<Script>>() || referrer.has<NonnullGCPtr<CyclicModule>>()) { if (referrer.has<GC::Ref<Script>>() || referrer.has<GC::Ref<CyclicModule>>()) {
auto& loaded_modules = referrer.visit( auto& loaded_modules = referrer.visit(
[](JS::NonnullGCPtr<JS::Realm>&) -> Vector<ModuleWithSpecifier>& { [](GC::Ref<JS::Realm>&) -> Vector<ModuleWithSpecifier>& {
VERIFY_NOT_REACHED(); VERIFY_NOT_REACHED();
__builtin_unreachable(); __builtin_unreachable();
}, },
@ -101,19 +101,19 @@ void finish_loading_imported_module(ImportedModuleReferrer referrer, ModuleReque
// i. Append the Record { [[Specifier]]: specifier, [[Module]]: result.[[Value]] } to referrer.[[LoadedModules]]. // i. Append the Record { [[Specifier]]: specifier, [[Module]]: result.[[Value]] } to referrer.[[LoadedModules]].
loaded_modules.append(ModuleWithSpecifier { loaded_modules.append(ModuleWithSpecifier {
.specifier = module_request.module_specifier, .specifier = module_request.module_specifier,
.module = NonnullGCPtr<Module>(*module) }); .module = GC::Ref<Module>(*module) });
} }
} }
} }
if (payload.has<NonnullGCPtr<GraphLoadingState>>()) { if (payload.has<GC::Ref<GraphLoadingState>>()) {
// a. Perform ContinueModuleLoading(payload, result) // a. Perform ContinueModuleLoading(payload, result)
continue_module_loading(payload.get<NonnullGCPtr<GraphLoadingState>>(), result); continue_module_loading(payload.get<GC::Ref<GraphLoadingState>>(), result);
} }
// Else, // Else,
else { else {
// a. Perform ContinueDynamicImport(payload, result). // a. Perform ContinueDynamicImport(payload, result).
continue_dynamic_import(payload.get<NonnullGCPtr<PromiseCapability>>(), result); continue_dynamic_import(payload.get<GC::Ref<PromiseCapability>>(), result);
} }
// 4. Return unused. // 4. Return unused.
@ -174,7 +174,7 @@ Object* Module::module_namespace_create(Vector<DeprecatedFlyString> unambiguous_
auto module_namespace = realm.create<ModuleNamespaceObject>(realm, this, move(unambiguous_names)); auto module_namespace = realm.create<ModuleNamespaceObject>(realm, this, move(unambiguous_names));
// 9. Set module.[[Namespace]] to M. // 9. Set module.[[Namespace]] to M.
m_namespace = make_handle(module_namespace); m_namespace = make_root(module_namespace);
// 10. Return M. // 10. Return M.
return module_namespace; return module_namespace;

View file

@ -8,7 +8,7 @@
#pragma once #pragma once
#include <AK/DeprecatedFlyString.h> #include <AK/DeprecatedFlyString.h>
#include <LibJS/Heap/GCPtr.h> #include <LibGC/Ptr.h>
#include <LibJS/ModuleLoading.h> #include <LibJS/ModuleLoading.h>
#include <LibJS/Runtime/Environment.h> #include <LibJS/Runtime/Environment.h>
#include <LibJS/Runtime/Realm.h> #include <LibJS/Runtime/Realm.h>
@ -37,7 +37,7 @@ struct ResolvedBinding {
} }
Type type { Null }; Type type { Null };
GCPtr<Module> module; GC::Ptr<Module> module;
DeprecatedFlyString export_name; DeprecatedFlyString export_name;
bool is_valid() const bool is_valid() const
@ -58,25 +58,25 @@ struct ResolvedBinding {
// https://tc39.es/ecma262/#graphloadingstate-record // https://tc39.es/ecma262/#graphloadingstate-record
struct GraphLoadingState : public Cell { struct GraphLoadingState : public Cell {
JS_CELL(GraphLoadingState, Cell); GC_CELL(GraphLoadingState, Cell);
JS_DECLARE_ALLOCATOR(GraphLoadingState); GC_DECLARE_ALLOCATOR(GraphLoadingState);
public: public:
struct HostDefined : Cell { struct HostDefined : Cell {
JS_CELL(HostDefined, Cell); GC_CELL(HostDefined, Cell);
public: public:
virtual ~HostDefined() = default; virtual ~HostDefined() = default;
}; };
GCPtr<PromiseCapability> promise_capability; // [[PromiseCapability]] GC::Ptr<PromiseCapability> promise_capability; // [[PromiseCapability]]
bool is_loading { false }; // [[IsLoading]] bool is_loading { false }; // [[IsLoading]]
size_t pending_module_count { 0 }; // [[PendingModulesCount]] size_t pending_module_count { 0 }; // [[PendingModulesCount]]
HashTable<JS::GCPtr<CyclicModule>> visited; // [[Visited]] HashTable<GC::Ptr<CyclicModule>> visited; // [[Visited]]
GCPtr<HostDefined> host_defined; // [[HostDefined]] GC::Ptr<HostDefined> host_defined; // [[HostDefined]]
private: private:
GraphLoadingState(GCPtr<PromiseCapability> promise_capability, bool is_loading, size_t pending_module_count, HashTable<JS::GCPtr<CyclicModule>> visited, GCPtr<HostDefined> host_defined) GraphLoadingState(GC::Ptr<PromiseCapability> promise_capability, bool is_loading, size_t pending_module_count, HashTable<GC::Ptr<CyclicModule>> visited, GC::Ptr<HostDefined> host_defined)
: promise_capability(move(promise_capability)) : promise_capability(move(promise_capability))
, is_loading(is_loading) , is_loading(is_loading)
, pending_module_count(pending_module_count) , pending_module_count(pending_module_count)
@ -89,8 +89,8 @@ private:
// 16.2.1.4 Abstract Module Records, https://tc39.es/ecma262/#sec-abstract-module-records // 16.2.1.4 Abstract Module Records, https://tc39.es/ecma262/#sec-abstract-module-records
class Module : public Cell { class Module : public Cell {
JS_CELL(Module, Cell); GC_CELL(Module, Cell);
JS_DECLARE_ALLOCATOR(Module); GC_DECLARE_ALLOCATOR(Module);
public: public:
virtual ~Module() override; virtual ~Module() override;
@ -115,7 +115,7 @@ public:
virtual ThrowCompletionOr<u32> inner_module_linking(VM& vm, Vector<Module*>& stack, u32 index); virtual ThrowCompletionOr<u32> inner_module_linking(VM& vm, Vector<Module*>& stack, u32 index);
virtual ThrowCompletionOr<u32> inner_module_evaluation(VM& vm, Vector<Module*>& stack, u32 index); virtual ThrowCompletionOr<u32> inner_module_evaluation(VM& vm, Vector<Module*>& stack, u32 index);
virtual PromiseCapability& load_requested_modules(GCPtr<GraphLoadingState::HostDefined>) = 0; virtual PromiseCapability& load_requested_modules(GC::Ptr<GraphLoadingState::HostDefined>) = 0;
protected: protected:
Module(Realm&, ByteString filename, Script::HostDefined* host_defined = nullptr); Module(Realm&, ByteString filename, Script::HostDefined* host_defined = nullptr);
@ -135,9 +135,9 @@ private:
// destroy the VM but keep the modules this should not happen. Because VM // destroy the VM but keep the modules this should not happen. Because VM
// stores modules with a RefPtr we cannot just store the VM as that leads to // stores modules with a RefPtr we cannot just store the VM as that leads to
// cycles. // cycles.
GCPtr<Realm> m_realm; // [[Realm]] GC::Ptr<Realm> m_realm; // [[Realm]]
GCPtr<Environment> m_environment; // [[Environment]] GC::Ptr<Environment> m_environment; // [[Environment]]
GCPtr<Object> m_namespace; // [[Namespace]] GC::Ptr<Object> m_namespace; // [[Namespace]]
Script::HostDefined* m_host_defined { nullptr }; // [[HostDefined]] Script::HostDefined* m_host_defined { nullptr }; // [[HostDefined]]
// Needed for potential lookups of modules. // Needed for potential lookups of modules.
@ -147,6 +147,6 @@ private:
class CyclicModule; class CyclicModule;
struct GraphLoadingState; struct GraphLoadingState;
void finish_loading_imported_module(ImportedModuleReferrer, ModuleRequest const&, ImportedModulePayload, ThrowCompletionOr<NonnullGCPtr<Module>> const&); void finish_loading_imported_module(ImportedModuleReferrer, ModuleRequest const&, ImportedModulePayload, ThrowCompletionOr<GC::Ref<Module>> const&);
} }

View file

@ -7,12 +7,12 @@
#pragma once #pragma once
#include <AK/Variant.h> #include <AK/Variant.h>
#include <LibGC/Ptr.h>
#include <LibJS/Forward.h> #include <LibJS/Forward.h>
#include <LibJS/Heap/GCPtr.h>
namespace JS { namespace JS {
using ImportedModuleReferrer = Variant<NonnullGCPtr<Script>, NonnullGCPtr<CyclicModule>, NonnullGCPtr<Realm>>; using ImportedModuleReferrer = Variant<GC::Ref<Script>, GC::Ref<CyclicModule>, GC::Ref<Realm>>;
using ImportedModulePayload = Variant<NonnullGCPtr<GraphLoadingState>, NonnullGCPtr<PromiseCapability>>; using ImportedModulePayload = Variant<GC::Ref<GraphLoadingState>, GC::Ref<PromiseCapability>>;
} }

View file

@ -209,7 +209,7 @@ public:
}; };
// Needs to mess with m_state, and we're not going to expose a non-const getter for that :^) // Needs to mess with m_state, and we're not going to expose a non-const getter for that :^)
friend ThrowCompletionOr<NonnullGCPtr<ECMAScriptFunctionObject>> FunctionConstructor::create_dynamic_function(VM&, FunctionObject&, FunctionObject*, FunctionKind, ReadonlySpan<String> parameter_args, String const& body_arg); friend ThrowCompletionOr<GC::Ref<ECMAScriptFunctionObject>> FunctionConstructor::create_dynamic_function(VM&, FunctionObject&, FunctionObject*, FunctionKind, ReadonlySpan<String> parameter_args, String const& body_arg);
static Parser parse_function_body_from_string(ByteString const& body_string, u16 parse_options, Vector<FunctionParameter> const& parameters, FunctionKind kind, FunctionParsingInsights&); static Parser parse_function_body_from_string(ByteString const& body_string, u16 parse_options, Vector<FunctionParameter> const& parameters, FunctionKind kind, FunctionParsingInsights&);

View file

@ -73,7 +73,7 @@ ThrowCompletionOr<Value> call_impl(VM&, FunctionObject& function, Value this_val
} }
// 7.3.15 Construct ( F [ , argumentsList [ , newTarget ] ] ), https://tc39.es/ecma262/#sec-construct // 7.3.15 Construct ( F [ , argumentsList [ , newTarget ] ] ), https://tc39.es/ecma262/#sec-construct
ThrowCompletionOr<NonnullGCPtr<Object>> construct_impl(VM&, FunctionObject& function, ReadonlySpan<Value> arguments_list, FunctionObject* new_target) ThrowCompletionOr<GC::Ref<Object>> construct_impl(VM&, FunctionObject& function, ReadonlySpan<Value> arguments_list, FunctionObject* new_target)
{ {
// 1. If newTarget is not present, set newTarget to F. // 1. If newTarget is not present, set newTarget to F.
if (!new_target) if (!new_target)
@ -97,7 +97,7 @@ ThrowCompletionOr<size_t> length_of_array_like(VM& vm, Object const& object)
} }
// 7.3.20 CreateListFromArrayLike ( obj [ , elementTypes ] ), https://tc39.es/ecma262/#sec-createlistfromarraylike // 7.3.20 CreateListFromArrayLike ( obj [ , elementTypes ] ), https://tc39.es/ecma262/#sec-createlistfromarraylike
ThrowCompletionOr<MarkedVector<Value>> create_list_from_array_like(VM& vm, Value value, Function<ThrowCompletionOr<void>(Value)> check_value) ThrowCompletionOr<GC::MarkedVector<Value>> create_list_from_array_like(VM& vm, Value value, Function<ThrowCompletionOr<void>(Value)> check_value)
{ {
// 1. If elementTypes is not present, set elementTypes to « Undefined, Null, Boolean, String, Symbol, Number, BigInt, Object ». // 1. If elementTypes is not present, set elementTypes to « Undefined, Null, Boolean, String, Symbol, Number, BigInt, Object ».
@ -111,7 +111,7 @@ ThrowCompletionOr<MarkedVector<Value>> create_list_from_array_like(VM& vm, Value
auto length = TRY(length_of_array_like(vm, array_like)); auto length = TRY(length_of_array_like(vm, array_like));
// 4. Let list be a new empty List. // 4. Let list be a new empty List.
auto list = MarkedVector<Value> { vm.heap() }; auto list = GC::MarkedVector<Value> { vm.heap() };
list.ensure_capacity(length); list.ensure_capacity(length);
// 5. Let index be 0. // 5. Let index be 0.
@ -366,7 +366,7 @@ bool validate_and_apply_property_descriptor(Object* object, PropertyKey const& p
} }
// 10.1.14 GetPrototypeFromConstructor ( constructor, intrinsicDefaultProto ), https://tc39.es/ecma262/#sec-getprototypefromconstructor // 10.1.14 GetPrototypeFromConstructor ( constructor, intrinsicDefaultProto ), https://tc39.es/ecma262/#sec-getprototypefromconstructor
ThrowCompletionOr<Object*> get_prototype_from_constructor(VM& vm, FunctionObject const& constructor, NonnullGCPtr<Object> (Intrinsics::*intrinsic_default_prototype)()) ThrowCompletionOr<Object*> get_prototype_from_constructor(VM& vm, FunctionObject const& constructor, GC::Ref<Object> (Intrinsics::*intrinsic_default_prototype)())
{ {
// 1. Assert: intrinsicDefaultProto is this specification's name of an intrinsic object. The corresponding object must be an intrinsic that is intended to be used as the [[Prototype]] value of an object. // 1. Assert: intrinsicDefaultProto is this specification's name of an intrinsic object. The corresponding object must be an intrinsic that is intended to be used as the [[Prototype]] value of an object.
@ -387,7 +387,7 @@ ThrowCompletionOr<Object*> get_prototype_from_constructor(VM& vm, FunctionObject
} }
// 9.1.2.2 NewDeclarativeEnvironment ( E ), https://tc39.es/ecma262/#sec-newdeclarativeenvironment // 9.1.2.2 NewDeclarativeEnvironment ( E ), https://tc39.es/ecma262/#sec-newdeclarativeenvironment
NonnullGCPtr<DeclarativeEnvironment> new_declarative_environment(Environment& environment) GC::Ref<DeclarativeEnvironment> new_declarative_environment(Environment& environment)
{ {
auto& heap = environment.heap(); auto& heap = environment.heap();
@ -398,7 +398,7 @@ NonnullGCPtr<DeclarativeEnvironment> new_declarative_environment(Environment& en
} }
// 9.1.2.3 NewObjectEnvironment ( O, W, E ), https://tc39.es/ecma262/#sec-newobjectenvironment // 9.1.2.3 NewObjectEnvironment ( O, W, E ), https://tc39.es/ecma262/#sec-newobjectenvironment
NonnullGCPtr<ObjectEnvironment> new_object_environment(Object& object, bool is_with_environment, Environment* environment) GC::Ref<ObjectEnvironment> new_object_environment(Object& object, bool is_with_environment, Environment* environment)
{ {
auto& heap = object.heap(); auto& heap = object.heap();
@ -411,7 +411,7 @@ NonnullGCPtr<ObjectEnvironment> new_object_environment(Object& object, bool is_w
} }
// 9.1.2.4 NewFunctionEnvironment ( F, newTarget ), https://tc39.es/ecma262/#sec-newfunctionenvironment // 9.1.2.4 NewFunctionEnvironment ( F, newTarget ), https://tc39.es/ecma262/#sec-newfunctionenvironment
NonnullGCPtr<FunctionEnvironment> new_function_environment(ECMAScriptFunctionObject& function, Object* new_target) GC::Ref<FunctionEnvironment> new_function_environment(ECMAScriptFunctionObject& function, Object* new_target)
{ {
auto& heap = function.heap(); auto& heap = function.heap();
@ -439,7 +439,7 @@ NonnullGCPtr<FunctionEnvironment> new_function_environment(ECMAScriptFunctionObj
} }
// 9.2.1.1 NewPrivateEnvironment ( outerPrivEnv ), https://tc39.es/ecma262/#sec-newprivateenvironment // 9.2.1.1 NewPrivateEnvironment ( outerPrivEnv ), https://tc39.es/ecma262/#sec-newprivateenvironment
NonnullGCPtr<PrivateEnvironment> new_private_environment(VM& vm, PrivateEnvironment* outer) GC::Ref<PrivateEnvironment> new_private_environment(VM& vm, PrivateEnvironment* outer)
{ {
// 1. Let names be a new empty List. // 1. Let names be a new empty List.
// 2. Return the PrivateEnvironment Record { [[OuterPrivateEnvironment]]: outerPrivEnv, [[Names]]: names }. // 2. Return the PrivateEnvironment Record { [[OuterPrivateEnvironment]]: outerPrivEnv, [[Names]]: names }.
@ -447,7 +447,7 @@ NonnullGCPtr<PrivateEnvironment> new_private_environment(VM& vm, PrivateEnvironm
} }
// 9.4.3 GetThisEnvironment ( ), https://tc39.es/ecma262/#sec-getthisenvironment // 9.4.3 GetThisEnvironment ( ), https://tc39.es/ecma262/#sec-getthisenvironment
NonnullGCPtr<Environment> get_this_environment(VM& vm) GC::Ref<Environment> get_this_environment(VM& vm)
{ {
// 1. Let env be the running execution context's LexicalEnvironment. // 1. Let env be the running execution context's LexicalEnvironment.
// 2. Repeat, // 2. Repeat,
@ -1482,7 +1482,7 @@ ThrowCompletionOr<DisposableResource> create_disposable_resource(VM& vm, Value v
} }
// 2.1.4 GetDisposeMethod ( V, hint ), https://tc39.es/proposal-explicit-resource-management/#sec-getdisposemethod // 2.1.4 GetDisposeMethod ( V, hint ), https://tc39.es/proposal-explicit-resource-management/#sec-getdisposemethod
ThrowCompletionOr<GCPtr<FunctionObject>> get_dispose_method(VM& vm, Value value, Environment::InitializeBindingHint hint) ThrowCompletionOr<GC::Ptr<FunctionObject>> get_dispose_method(VM& vm, Value value, Environment::InitializeBindingHint hint)
{ {
// NOTE: We only have sync dispose for now which means we ignore step 1. // NOTE: We only have sync dispose for now which means we ignore step 1.
VERIFY(hint == Environment::InitializeBindingHint::SyncDispose); VERIFY(hint == Environment::InitializeBindingHint::SyncDispose);
@ -1493,7 +1493,7 @@ ThrowCompletionOr<GCPtr<FunctionObject>> get_dispose_method(VM& vm, Value value,
} }
// 2.1.5 Dispose ( V, hint, method ), https://tc39.es/proposal-explicit-resource-management/#sec-dispose // 2.1.5 Dispose ( V, hint, method ), https://tc39.es/proposal-explicit-resource-management/#sec-dispose
Completion dispose(VM& vm, Value value, NonnullGCPtr<FunctionObject> method) Completion dispose(VM& vm, Value value, GC::Ref<FunctionObject> method)
{ {
// 1. Let result be ? Call(method, V). // 1. Let result be ? Call(method, V).
[[maybe_unused]] auto result = TRY(call(vm, *method, value)); [[maybe_unused]] auto result = TRY(call(vm, *method, value));
@ -1550,7 +1550,7 @@ Completion dispose_resources(VM& vm, Vector<DisposableResource> const& disposabl
return completion; return completion;
} }
Completion dispose_resources(VM& vm, GCPtr<DeclarativeEnvironment> disposable, Completion completion) Completion dispose_resources(VM& vm, GC::Ptr<DeclarativeEnvironment> disposable, Completion completion)
{ {
// 1. If disposable is not undefined, then // 1. If disposable is not undefined, then
if (disposable) if (disposable)
@ -1588,12 +1588,12 @@ ThrowCompletionOr<Value> perform_import_call(VM& vm, Value specifier, Value opti
// 2. If referrer is null, set referrer to the current Realm Record. // 2. If referrer is null, set referrer to the current Realm Record.
if (active_script_or_module.has<Empty>()) if (active_script_or_module.has<Empty>())
return NonnullGCPtr<Realm> { realm }; return GC::Ref<Realm> { realm };
if (active_script_or_module.has<NonnullGCPtr<Script>>()) if (active_script_or_module.has<GC::Ref<Script>>())
return active_script_or_module.get<NonnullGCPtr<Script>>(); return active_script_or_module.get<GC::Ref<Script>>();
return NonnullGCPtr<CyclicModule> { verify_cast<CyclicModule>(*active_script_or_module.get<NonnullGCPtr<Module>>()) }; return GC::Ref<CyclicModule> { verify_cast<CyclicModule>(*active_script_or_module.get<GC::Ref<Module>>()) };
}(); }();
// 7. Let promiseCapability be ! NewPromiseCapability(%Promise%). // 7. Let promiseCapability be ! NewPromiseCapability(%Promise%).

View file

@ -9,8 +9,8 @@
#include <AK/Concepts.h> #include <AK/Concepts.h>
#include <AK/Forward.h> #include <AK/Forward.h>
#include <LibCrypto/Forward.h> #include <LibCrypto/Forward.h>
#include <LibGC/MarkedVector.h>
#include <LibJS/Forward.h> #include <LibJS/Forward.h>
#include <LibJS/Heap/MarkedVector.h>
#include <LibJS/Runtime/CanonicalIndex.h> #include <LibJS/Runtime/CanonicalIndex.h>
#include <LibJS/Runtime/FunctionObject.h> #include <LibJS/Runtime/FunctionObject.h>
#include <LibJS/Runtime/GlobalObject.h> #include <LibJS/Runtime/GlobalObject.h>
@ -22,38 +22,38 @@
namespace JS { namespace JS {
NonnullGCPtr<DeclarativeEnvironment> new_declarative_environment(Environment&); GC::Ref<DeclarativeEnvironment> new_declarative_environment(Environment&);
NonnullGCPtr<ObjectEnvironment> new_object_environment(Object&, bool is_with_environment, Environment*); GC::Ref<ObjectEnvironment> new_object_environment(Object&, bool is_with_environment, Environment*);
NonnullGCPtr<FunctionEnvironment> new_function_environment(ECMAScriptFunctionObject&, Object* new_target); GC::Ref<FunctionEnvironment> new_function_environment(ECMAScriptFunctionObject&, Object* new_target);
NonnullGCPtr<PrivateEnvironment> new_private_environment(VM& vm, PrivateEnvironment* outer); GC::Ref<PrivateEnvironment> new_private_environment(VM& vm, PrivateEnvironment* outer);
NonnullGCPtr<Environment> get_this_environment(VM&); GC::Ref<Environment> get_this_environment(VM&);
bool can_be_held_weakly(Value); bool can_be_held_weakly(Value);
Object* get_super_constructor(VM&); Object* get_super_constructor(VM&);
ThrowCompletionOr<Value> require_object_coercible(VM&, Value); ThrowCompletionOr<Value> require_object_coercible(VM&, Value);
ThrowCompletionOr<Value> call_impl(VM&, Value function, Value this_value, ReadonlySpan<Value> arguments = {}); ThrowCompletionOr<Value> call_impl(VM&, Value function, Value this_value, ReadonlySpan<Value> arguments = {});
ThrowCompletionOr<Value> call_impl(VM&, FunctionObject& function, Value this_value, ReadonlySpan<Value> arguments = {}); ThrowCompletionOr<Value> call_impl(VM&, FunctionObject& function, Value this_value, ReadonlySpan<Value> arguments = {});
ThrowCompletionOr<NonnullGCPtr<Object>> construct_impl(VM&, FunctionObject&, ReadonlySpan<Value> arguments = {}, FunctionObject* new_target = nullptr); ThrowCompletionOr<GC::Ref<Object>> construct_impl(VM&, FunctionObject&, ReadonlySpan<Value> arguments = {}, FunctionObject* new_target = nullptr);
ThrowCompletionOr<size_t> length_of_array_like(VM&, Object const&); ThrowCompletionOr<size_t> length_of_array_like(VM&, Object const&);
ThrowCompletionOr<MarkedVector<Value>> create_list_from_array_like(VM&, Value, Function<ThrowCompletionOr<void>(Value)> = {}); ThrowCompletionOr<GC::MarkedVector<Value>> create_list_from_array_like(VM&, Value, Function<ThrowCompletionOr<void>(Value)> = {});
ThrowCompletionOr<FunctionObject*> species_constructor(VM&, Object const&, FunctionObject& default_constructor); ThrowCompletionOr<FunctionObject*> species_constructor(VM&, Object const&, FunctionObject& default_constructor);
ThrowCompletionOr<Realm*> get_function_realm(VM&, FunctionObject const&); ThrowCompletionOr<Realm*> get_function_realm(VM&, FunctionObject const&);
ThrowCompletionOr<void> initialize_bound_name(VM&, DeprecatedFlyString const&, Value, Environment*); ThrowCompletionOr<void> initialize_bound_name(VM&, DeprecatedFlyString const&, Value, Environment*);
bool is_compatible_property_descriptor(bool extensible, PropertyDescriptor const&, Optional<PropertyDescriptor> const& current); bool is_compatible_property_descriptor(bool extensible, PropertyDescriptor const&, Optional<PropertyDescriptor> const& current);
bool validate_and_apply_property_descriptor(Object*, PropertyKey const&, bool extensible, PropertyDescriptor const&, Optional<PropertyDescriptor> const& current); bool validate_and_apply_property_descriptor(Object*, PropertyKey const&, bool extensible, PropertyDescriptor const&, Optional<PropertyDescriptor> const& current);
ThrowCompletionOr<Object*> get_prototype_from_constructor(VM&, FunctionObject const& constructor, NonnullGCPtr<Object> (Intrinsics::*intrinsic_default_prototype)()); ThrowCompletionOr<Object*> get_prototype_from_constructor(VM&, FunctionObject const& constructor, GC::Ref<Object> (Intrinsics::*intrinsic_default_prototype)());
Object* create_unmapped_arguments_object(VM&, ReadonlySpan<Value> arguments); Object* create_unmapped_arguments_object(VM&, ReadonlySpan<Value> arguments);
Object* create_mapped_arguments_object(VM&, FunctionObject&, Vector<FunctionParameter> const&, ReadonlySpan<Value> arguments, Environment&); Object* create_mapped_arguments_object(VM&, FunctionObject&, Vector<FunctionParameter> const&, ReadonlySpan<Value> arguments, Environment&);
struct DisposableResource { struct DisposableResource {
Value resource_value; Value resource_value;
NonnullGCPtr<FunctionObject> dispose_method; GC::Ref<FunctionObject> dispose_method;
}; };
ThrowCompletionOr<void> add_disposable_resource(VM&, Vector<DisposableResource>& disposable, Value, Environment::InitializeBindingHint, FunctionObject* = nullptr); ThrowCompletionOr<void> add_disposable_resource(VM&, Vector<DisposableResource>& disposable, Value, Environment::InitializeBindingHint, FunctionObject* = nullptr);
ThrowCompletionOr<DisposableResource> create_disposable_resource(VM&, Value, Environment::InitializeBindingHint, FunctionObject* method = nullptr); ThrowCompletionOr<DisposableResource> create_disposable_resource(VM&, Value, Environment::InitializeBindingHint, FunctionObject* method = nullptr);
ThrowCompletionOr<GCPtr<FunctionObject>> get_dispose_method(VM&, Value, Environment::InitializeBindingHint); ThrowCompletionOr<GC::Ptr<FunctionObject>> get_dispose_method(VM&, Value, Environment::InitializeBindingHint);
Completion dispose(VM& vm, Value, NonnullGCPtr<FunctionObject> method); Completion dispose(VM& vm, Value, GC::Ref<FunctionObject> method);
Completion dispose_resources(VM& vm, Vector<DisposableResource> const& disposable, Completion completion); Completion dispose_resources(VM& vm, Vector<DisposableResource> const& disposable, Completion completion);
Completion dispose_resources(VM& vm, GCPtr<DeclarativeEnvironment> disposable, Completion completion); Completion dispose_resources(VM& vm, GC::Ptr<DeclarativeEnvironment> disposable, Completion completion);
ThrowCompletionOr<Value> perform_import_call(VM&, Value specifier, Value options_value); ThrowCompletionOr<Value> perform_import_call(VM&, Value specifier, Value options_value);
@ -120,7 +120,7 @@ ALWAYS_INLINE ThrowCompletionOr<Value> call(VM& vm, FunctionObject& function, Va
// 7.3.15 Construct ( F [ , argumentsList [ , newTarget ] ] ), https://tc39.es/ecma262/#sec-construct // 7.3.15 Construct ( F [ , argumentsList [ , newTarget ] ] ), https://tc39.es/ecma262/#sec-construct
template<typename... Args> template<typename... Args>
ALWAYS_INLINE ThrowCompletionOr<NonnullGCPtr<Object>> construct(VM& vm, FunctionObject& function, Args&&... args) ALWAYS_INLINE ThrowCompletionOr<GC::Ref<Object>> construct(VM& vm, FunctionObject& function, Args&&... args)
{ {
constexpr auto argument_count = sizeof...(Args); constexpr auto argument_count = sizeof...(Args);
if constexpr (argument_count > 0) { if constexpr (argument_count > 0) {
@ -131,19 +131,19 @@ ALWAYS_INLINE ThrowCompletionOr<NonnullGCPtr<Object>> construct(VM& vm, Function
return construct_impl(vm, function); return construct_impl(vm, function);
} }
ALWAYS_INLINE ThrowCompletionOr<NonnullGCPtr<Object>> construct(VM& vm, FunctionObject& function, ReadonlySpan<Value> arguments_list, FunctionObject* new_target = nullptr) ALWAYS_INLINE ThrowCompletionOr<GC::Ref<Object>> construct(VM& vm, FunctionObject& function, ReadonlySpan<Value> arguments_list, FunctionObject* new_target = nullptr)
{ {
return construct_impl(vm, function, arguments_list, new_target); return construct_impl(vm, function, arguments_list, new_target);
} }
ALWAYS_INLINE ThrowCompletionOr<NonnullGCPtr<Object>> construct(VM& vm, FunctionObject& function, Span<Value> arguments_list, FunctionObject* new_target = nullptr) ALWAYS_INLINE ThrowCompletionOr<GC::Ref<Object>> construct(VM& vm, FunctionObject& function, Span<Value> arguments_list, FunctionObject* new_target = nullptr)
{ {
return construct_impl(vm, function, static_cast<ReadonlySpan<Value>>(arguments_list), new_target); return construct_impl(vm, function, static_cast<ReadonlySpan<Value>>(arguments_list), new_target);
} }
// 10.1.13 OrdinaryCreateFromConstructor ( constructor, intrinsicDefaultProto [ , internalSlotsList ] ), https://tc39.es/ecma262/#sec-ordinarycreatefromconstructor // 10.1.13 OrdinaryCreateFromConstructor ( constructor, intrinsicDefaultProto [ , internalSlotsList ] ), https://tc39.es/ecma262/#sec-ordinarycreatefromconstructor
template<typename T, typename... Args> template<typename T, typename... Args>
ThrowCompletionOr<NonnullGCPtr<T>> ordinary_create_from_constructor(VM& vm, FunctionObject const& constructor, NonnullGCPtr<Object> (Intrinsics::*intrinsic_default_prototype)(), Args&&... args) ThrowCompletionOr<GC::Ref<T>> ordinary_create_from_constructor(VM& vm, FunctionObject const& constructor, GC::Ref<Object> (Intrinsics::*intrinsic_default_prototype)(), Args&&... args)
{ {
auto& realm = *vm.current_realm(); auto& realm = *vm.current_realm();
auto* prototype = TRY(get_prototype_from_constructor(vm, constructor, intrinsic_default_prototype)); auto* prototype = TRY(get_prototype_from_constructor(vm, constructor, intrinsic_default_prototype));
@ -199,7 +199,7 @@ void add_value_to_keyed_group(VM& vm, GroupsType& groups, KeyType key, Value val
} }
// 2. Let group be the Record { [[Key]]: key, [[Elements]]: « value » }. // 2. Let group be the Record { [[Key]]: key, [[Elements]]: « value » }.
MarkedVector<Value> new_elements { vm.heap() }; GC::MarkedVector<Value> new_elements { vm.heap() };
new_elements.append(value); new_elements.append(value);
// 3. Append group as the last element of groups. // 3. Append group as the last element of groups.
@ -278,7 +278,7 @@ ThrowCompletionOr<GroupsType> group_by(VM& vm, Value items, Value callback_funct
// ii. Set key to CanonicalizeKeyedCollectionKey(key). // ii. Set key to CanonicalizeKeyedCollectionKey(key).
key = canonicalize_keyed_collection_key(key.value()); key = canonicalize_keyed_collection_key(key.value());
add_value_to_keyed_group(vm, groups, make_handle(key.release_value()), value); add_value_to_keyed_group(vm, groups, make_root(key.release_value()), value);
} }
// i. Perform AddValueToKeyedGroup(groups, key, value). // i. Perform AddValueToKeyedGroup(groups, key, value).

View file

@ -8,6 +8,6 @@
namespace JS { namespace JS {
JS_DEFINE_ALLOCATOR(Accessor); GC_DEFINE_ALLOCATOR(Accessor);
} }

View file

@ -14,11 +14,11 @@
namespace JS { namespace JS {
class Accessor final : public Cell { class Accessor final : public Cell {
JS_CELL(Accessor, Cell); GC_CELL(Accessor, Cell);
JS_DECLARE_ALLOCATOR(Accessor); GC_DECLARE_ALLOCATOR(Accessor);
public: public:
static NonnullGCPtr<Accessor> create(VM& vm, FunctionObject* getter, FunctionObject* setter) static GC::Ref<Accessor> create(VM& vm, FunctionObject* getter, FunctionObject* setter)
{ {
return vm.heap().allocate<Accessor>(getter, setter); return vm.heap().allocate<Accessor>(getter, setter);
} }
@ -43,8 +43,8 @@ private:
{ {
} }
GCPtr<FunctionObject> m_getter; GC::Ptr<FunctionObject> m_getter;
GCPtr<FunctionObject> m_setter; GC::Ptr<FunctionObject> m_setter;
}; };
} }

View file

@ -10,9 +10,9 @@
namespace JS { namespace JS {
JS_DEFINE_ALLOCATOR(AggregateError); GC_DEFINE_ALLOCATOR(AggregateError);
NonnullGCPtr<AggregateError> AggregateError::create(Realm& realm) GC::Ref<AggregateError> AggregateError::create(Realm& realm)
{ {
return realm.create<AggregateError>(realm.intrinsics().aggregate_error_prototype()); return realm.create<AggregateError>(realm.intrinsics().aggregate_error_prototype());
} }

View file

@ -13,10 +13,10 @@ namespace JS {
class AggregateError : public Error { class AggregateError : public Error {
JS_OBJECT(AggregateError, Error); JS_OBJECT(AggregateError, Error);
JS_DECLARE_ALLOCATOR(AggregateError); GC_DECLARE_ALLOCATOR(AggregateError);
public: public:
static NonnullGCPtr<AggregateError> create(Realm&); static GC::Ref<AggregateError> create(Realm&);
virtual ~AggregateError() override = default; virtual ~AggregateError() override = default;
private: private:

View file

@ -14,7 +14,7 @@
namespace JS { namespace JS {
JS_DEFINE_ALLOCATOR(AggregateErrorConstructor); GC_DEFINE_ALLOCATOR(AggregateErrorConstructor);
AggregateErrorConstructor::AggregateErrorConstructor(Realm& realm) AggregateErrorConstructor::AggregateErrorConstructor(Realm& realm)
: NativeFunction(static_cast<Object&>(*realm.intrinsics().error_constructor())) : NativeFunction(static_cast<Object&>(*realm.intrinsics().error_constructor()))
@ -40,7 +40,7 @@ ThrowCompletionOr<Value> AggregateErrorConstructor::call()
} }
// 20.5.7.1.1 AggregateError ( errors, message [ , options ] ), https://tc39.es/ecma262/#sec-aggregate-error // 20.5.7.1.1 AggregateError ( errors, message [ , options ] ), https://tc39.es/ecma262/#sec-aggregate-error
ThrowCompletionOr<NonnullGCPtr<Object>> AggregateErrorConstructor::construct(FunctionObject& new_target) ThrowCompletionOr<GC::Ref<Object>> AggregateErrorConstructor::construct(FunctionObject& new_target)
{ {
auto& vm = this->vm(); auto& vm = this->vm();
auto& realm = *vm.current_realm(); auto& realm = *vm.current_realm();

View file

@ -12,14 +12,14 @@ namespace JS {
class AggregateErrorConstructor final : public NativeFunction { class AggregateErrorConstructor final : public NativeFunction {
JS_OBJECT(AggregateErrorConstructor, NativeFunction); JS_OBJECT(AggregateErrorConstructor, NativeFunction);
JS_DECLARE_ALLOCATOR(AggregateErrorConstructor); GC_DECLARE_ALLOCATOR(AggregateErrorConstructor);
public: public:
virtual void initialize(Realm&) override; virtual void initialize(Realm&) override;
virtual ~AggregateErrorConstructor() override = default; virtual ~AggregateErrorConstructor() override = default;
virtual ThrowCompletionOr<Value> call() override; virtual ThrowCompletionOr<Value> call() override;
virtual ThrowCompletionOr<NonnullGCPtr<Object>> construct(FunctionObject& new_target) override; virtual ThrowCompletionOr<GC::Ref<Object>> construct(FunctionObject& new_target) override;
private: private:
explicit AggregateErrorConstructor(Realm&); explicit AggregateErrorConstructor(Realm&);

View file

@ -10,7 +10,7 @@
namespace JS { namespace JS {
JS_DEFINE_ALLOCATOR(AggregateErrorPrototype); GC_DEFINE_ALLOCATOR(AggregateErrorPrototype);
AggregateErrorPrototype::AggregateErrorPrototype(Realm& realm) AggregateErrorPrototype::AggregateErrorPrototype(Realm& realm)
: Object(ConstructWithPrototypeTag::Tag, realm.intrinsics().error_prototype()) : Object(ConstructWithPrototypeTag::Tag, realm.intrinsics().error_prototype())

View file

@ -12,7 +12,7 @@ namespace JS {
class AggregateErrorPrototype final : public Object { class AggregateErrorPrototype final : public Object {
JS_OBJECT(AggregateErrorPrototype, Object); JS_OBJECT(AggregateErrorPrototype, Object);
JS_DECLARE_ALLOCATOR(AggregateErrorPrototype); GC_DECLARE_ALLOCATOR(AggregateErrorPrototype);
public: public:
virtual void initialize(Realm&) override; virtual void initialize(Realm&) override;

View file

@ -10,7 +10,7 @@
namespace JS { namespace JS {
JS_DEFINE_ALLOCATOR(ArgumentsObject); GC_DEFINE_ALLOCATOR(ArgumentsObject);
ArgumentsObject::ArgumentsObject(Realm& realm, Environment& environment) ArgumentsObject::ArgumentsObject(Realm& realm, Environment& environment)
: Object(ConstructWithPrototypeTag::Tag, realm.intrinsics().object_prototype(), MayInterfereWithIndexedPropertyAccess::Yes) : Object(ConstructWithPrototypeTag::Tag, realm.intrinsics().object_prototype(), MayInterfereWithIndexedPropertyAccess::Yes)

View file

@ -14,7 +14,7 @@ namespace JS {
class ArgumentsObject final : public Object { class ArgumentsObject final : public Object {
JS_OBJECT(ArgumentsObject, Object); JS_OBJECT(ArgumentsObject, Object);
JS_DECLARE_ALLOCATOR(ArgumentsObject); GC_DECLARE_ALLOCATOR(ArgumentsObject);
public: public:
virtual void initialize(Realm&) override; virtual void initialize(Realm&) override;
@ -36,8 +36,8 @@ private:
virtual void visit_edges(Cell::Visitor&) override; virtual void visit_edges(Cell::Visitor&) override;
NonnullGCPtr<Environment> m_environment; GC::Ref<Environment> m_environment;
GCPtr<Object> m_parameter_map; GC::Ptr<Object> m_parameter_map;
}; };
} }

View file

@ -17,10 +17,10 @@
namespace JS { namespace JS {
JS_DEFINE_ALLOCATOR(Array); GC_DEFINE_ALLOCATOR(Array);
// 10.4.2.2 ArrayCreate ( length [ , proto ] ), https://tc39.es/ecma262/#sec-arraycreate // 10.4.2.2 ArrayCreate ( length [ , proto ] ), https://tc39.es/ecma262/#sec-arraycreate
ThrowCompletionOr<NonnullGCPtr<Array>> Array::create(Realm& realm, u64 length, Object* prototype) ThrowCompletionOr<GC::Ref<Array>> Array::create(Realm& realm, u64 length, Object* prototype)
{ {
auto& vm = realm.vm(); auto& vm = realm.vm();
@ -45,7 +45,7 @@ ThrowCompletionOr<NonnullGCPtr<Array>> Array::create(Realm& realm, u64 length, O
} }
// 7.3.18 CreateArrayFromList ( elements ), https://tc39.es/ecma262/#sec-createarrayfromlist // 7.3.18 CreateArrayFromList ( elements ), https://tc39.es/ecma262/#sec-createarrayfromlist
NonnullGCPtr<Array> Array::create_from(Realm& realm, ReadonlySpan<Value> elements) GC::Ref<Array> Array::create_from(Realm& realm, ReadonlySpan<Value> elements)
{ {
// 1. Let array be ! ArrayCreate(0). // 1. Let array be ! ArrayCreate(0).
auto array = MUST(Array::create(realm, 0)); auto array = MUST(Array::create(realm, 0));
@ -161,10 +161,10 @@ ThrowCompletionOr<bool> Array::set_length(PropertyDescriptor const& property_des
} }
// 23.1.3.30.1 SortIndexedProperties ( obj, len, SortCompare, holes ), https://tc39.es/ecma262/#sec-sortindexedproperties // 23.1.3.30.1 SortIndexedProperties ( obj, len, SortCompare, holes ), https://tc39.es/ecma262/#sec-sortindexedproperties
ThrowCompletionOr<MarkedVector<Value>> sort_indexed_properties(VM& vm, Object const& object, size_t length, Function<ThrowCompletionOr<double>(Value, Value)> const& sort_compare, Holes holes) ThrowCompletionOr<GC::MarkedVector<Value>> sort_indexed_properties(VM& vm, Object const& object, size_t length, Function<ThrowCompletionOr<double>(Value, Value)> const& sort_compare, Holes holes)
{ {
// 1. Let items be a new empty List. // 1. Let items be a new empty List.
auto items = MarkedVector<Value> { vm.heap() }; auto items = GC::MarkedVector<Value> { vm.heap() };
// 2. Let k be 0. // 2. Let k be 0.
// 3. Repeat, while k < len, // 3. Repeat, while k < len,
@ -330,7 +330,7 @@ ThrowCompletionOr<bool> Array::internal_delete(PropertyKey const& property_key)
} }
// NON-STANDARD: Used to inject the ephemeral length property's key // NON-STANDARD: Used to inject the ephemeral length property's key
ThrowCompletionOr<MarkedVector<Value>> Array::internal_own_property_keys() const ThrowCompletionOr<GC::MarkedVector<Value>> Array::internal_own_property_keys() const
{ {
auto& vm = this->vm(); auto& vm = this->vm();
auto keys = TRY(Object::internal_own_property_keys()); auto keys = TRY(Object::internal_own_property_keys());

View file

@ -21,23 +21,23 @@ namespace JS {
class Array : public Object { class Array : public Object {
JS_OBJECT(Array, Object); JS_OBJECT(Array, Object);
JS_DECLARE_ALLOCATOR(Array); GC_DECLARE_ALLOCATOR(Array);
public: public:
static ThrowCompletionOr<NonnullGCPtr<Array>> create(Realm&, u64 length, Object* prototype = nullptr); static ThrowCompletionOr<GC::Ref<Array>> create(Realm&, u64 length, Object* prototype = nullptr);
static NonnullGCPtr<Array> create_from(Realm&, ReadonlySpan<Value>); static GC::Ref<Array> create_from(Realm&, ReadonlySpan<Value>);
template<size_t N> template<size_t N>
static NonnullGCPtr<Array> create_from(Realm& realm, Value const (&values)[N]) static GC::Ref<Array> create_from(Realm& realm, Value const (&values)[N])
{ {
return create_from(realm, ReadonlySpan<Value> { values, N }); return create_from(realm, ReadonlySpan<Value> { values, N });
} }
// Non-standard but equivalent to CreateArrayFromList. // Non-standard but equivalent to CreateArrayFromList.
template<typename T> template<typename T>
static NonnullGCPtr<Array> create_from(Realm& realm, ReadonlySpan<T> elements, Function<Value(T const&)> map_fn) static GC::Ref<Array> create_from(Realm& realm, ReadonlySpan<T> elements, Function<Value(T const&)> map_fn)
{ {
auto values = MarkedVector<Value> { realm.heap() }; auto values = GC::MarkedVector<Value> { realm.heap() };
values.ensure_capacity(elements.size()); values.ensure_capacity(elements.size());
for (auto const& element : elements) for (auto const& element : elements)
values.append(map_fn(element)); values.append(map_fn(element));
@ -50,7 +50,7 @@ public:
virtual ThrowCompletionOr<Optional<PropertyDescriptor>> internal_get_own_property(PropertyKey const&) const override final; virtual ThrowCompletionOr<Optional<PropertyDescriptor>> internal_get_own_property(PropertyKey const&) const override final;
virtual ThrowCompletionOr<bool> internal_define_own_property(PropertyKey const&, PropertyDescriptor const&, Optional<PropertyDescriptor>* precomputed_get_own_property = nullptr) override final; virtual ThrowCompletionOr<bool> internal_define_own_property(PropertyKey const&, PropertyDescriptor const&, Optional<PropertyDescriptor>* precomputed_get_own_property = nullptr) override final;
virtual ThrowCompletionOr<bool> internal_delete(PropertyKey const&) override; virtual ThrowCompletionOr<bool> internal_delete(PropertyKey const&) override;
virtual ThrowCompletionOr<MarkedVector<Value>> internal_own_property_keys() const override final; virtual ThrowCompletionOr<GC::MarkedVector<Value>> internal_own_property_keys() const override final;
[[nodiscard]] bool length_is_writable() const { return m_length_writable; } [[nodiscard]] bool length_is_writable() const { return m_length_writable; }
@ -68,7 +68,7 @@ enum class Holes {
ReadThroughHoles, ReadThroughHoles,
}; };
ThrowCompletionOr<MarkedVector<Value>> sort_indexed_properties(VM&, Object const&, size_t length, Function<ThrowCompletionOr<double>(Value, Value)> const& sort_compare, Holes holes); ThrowCompletionOr<GC::MarkedVector<Value>> sort_indexed_properties(VM&, Object const&, size_t length, Function<ThrowCompletionOr<double>(Value, Value)> const& sort_compare, Holes holes);
ThrowCompletionOr<double> compare_array_elements(VM&, Value x, Value y, FunctionObject* comparefn); ThrowCompletionOr<double> compare_array_elements(VM&, Value x, Value y, FunctionObject* comparefn);
} }

View file

@ -11,9 +11,9 @@
namespace JS { namespace JS {
JS_DEFINE_ALLOCATOR(ArrayBuffer); GC_DEFINE_ALLOCATOR(ArrayBuffer);
ThrowCompletionOr<NonnullGCPtr<ArrayBuffer>> ArrayBuffer::create(Realm& realm, size_t byte_length) ThrowCompletionOr<GC::Ref<ArrayBuffer>> ArrayBuffer::create(Realm& realm, size_t byte_length)
{ {
auto buffer = ByteBuffer::create_zeroed(byte_length); auto buffer = ByteBuffer::create_zeroed(byte_length);
if (buffer.is_error()) if (buffer.is_error())
@ -22,12 +22,12 @@ ThrowCompletionOr<NonnullGCPtr<ArrayBuffer>> ArrayBuffer::create(Realm& realm, s
return realm.create<ArrayBuffer>(buffer.release_value(), realm.intrinsics().array_buffer_prototype()); return realm.create<ArrayBuffer>(buffer.release_value(), realm.intrinsics().array_buffer_prototype());
} }
NonnullGCPtr<ArrayBuffer> ArrayBuffer::create(Realm& realm, ByteBuffer buffer) GC::Ref<ArrayBuffer> ArrayBuffer::create(Realm& realm, ByteBuffer buffer)
{ {
return realm.create<ArrayBuffer>(move(buffer), realm.intrinsics().array_buffer_prototype()); return realm.create<ArrayBuffer>(move(buffer), realm.intrinsics().array_buffer_prototype());
} }
NonnullGCPtr<ArrayBuffer> ArrayBuffer::create(Realm& realm, ByteBuffer* buffer) GC::Ref<ArrayBuffer> ArrayBuffer::create(Realm& realm, ByteBuffer* buffer)
{ {
return realm.create<ArrayBuffer>(buffer, realm.intrinsics().array_buffer_prototype()); return realm.create<ArrayBuffer>(buffer, realm.intrinsics().array_buffer_prototype());
} }
@ -302,7 +302,7 @@ ThrowCompletionOr<Optional<size_t>> get_array_buffer_max_byte_length_option(VM&
} }
// 25.2.2.1 AllocateSharedArrayBuffer ( constructor, byteLength [ , maxByteLength ] ), https://tc39.es/ecma262/#sec-allocatesharedarraybuffer // 25.2.2.1 AllocateSharedArrayBuffer ( constructor, byteLength [ , maxByteLength ] ), https://tc39.es/ecma262/#sec-allocatesharedarraybuffer
ThrowCompletionOr<NonnullGCPtr<ArrayBuffer>> allocate_shared_array_buffer(VM& vm, FunctionObject& constructor, size_t byte_length) ThrowCompletionOr<GC::Ref<ArrayBuffer>> allocate_shared_array_buffer(VM& vm, FunctionObject& constructor, size_t byte_length)
{ {
// 1. Let obj be ? OrdinaryCreateFromConstructor(constructor, "%SharedArrayBuffer.prototype%", « [[ArrayBufferData]], [[ArrayBufferByteLength]] »). // 1. Let obj be ? OrdinaryCreateFromConstructor(constructor, "%SharedArrayBuffer.prototype%", « [[ArrayBufferData]], [[ArrayBufferByteLength]] »).
auto obj = TRY(ordinary_create_from_constructor<ArrayBuffer>(vm, constructor, &Intrinsics::shared_array_buffer_prototype, nullptr)); auto obj = TRY(ordinary_create_from_constructor<ArrayBuffer>(vm, constructor, &Intrinsics::shared_array_buffer_prototype, nullptr));

View file

@ -56,12 +56,12 @@ struct DataBlock {
class ArrayBuffer : public Object { class ArrayBuffer : public Object {
JS_OBJECT(ArrayBuffer, Object); JS_OBJECT(ArrayBuffer, Object);
JS_DECLARE_ALLOCATOR(ArrayBuffer); GC_DECLARE_ALLOCATOR(ArrayBuffer);
public: public:
static ThrowCompletionOr<NonnullGCPtr<ArrayBuffer>> create(Realm&, size_t); static ThrowCompletionOr<GC::Ref<ArrayBuffer>> create(Realm&, size_t);
static NonnullGCPtr<ArrayBuffer> create(Realm&, ByteBuffer); static GC::Ref<ArrayBuffer> create(Realm&, ByteBuffer);
static NonnullGCPtr<ArrayBuffer> create(Realm&, ByteBuffer*); static GC::Ref<ArrayBuffer> create(Realm&, ByteBuffer*);
virtual ~ArrayBuffer() override = default; virtual ~ArrayBuffer() override = default;
@ -152,7 +152,7 @@ ThrowCompletionOr<ArrayBuffer*> array_buffer_copy_and_detach(VM&, ArrayBuffer& a
ThrowCompletionOr<void> detach_array_buffer(VM&, ArrayBuffer& array_buffer, Optional<Value> key = {}); ThrowCompletionOr<void> detach_array_buffer(VM&, ArrayBuffer& array_buffer, Optional<Value> key = {});
ThrowCompletionOr<Optional<size_t>> get_array_buffer_max_byte_length_option(VM&, Value options); ThrowCompletionOr<Optional<size_t>> get_array_buffer_max_byte_length_option(VM&, Value options);
ThrowCompletionOr<ArrayBuffer*> clone_array_buffer(VM&, ArrayBuffer& source_buffer, size_t source_byte_offset, size_t source_length); ThrowCompletionOr<ArrayBuffer*> clone_array_buffer(VM&, ArrayBuffer& source_buffer, size_t source_byte_offset, size_t source_length);
ThrowCompletionOr<NonnullGCPtr<ArrayBuffer>> allocate_shared_array_buffer(VM&, FunctionObject& constructor, size_t byte_length); ThrowCompletionOr<GC::Ref<ArrayBuffer>> allocate_shared_array_buffer(VM&, FunctionObject& constructor, size_t byte_length);
// 25.1.3.2 ArrayBufferByteLength ( arrayBuffer, order ), https://tc39.es/ecma262/#sec-arraybufferbytelength // 25.1.3.2 ArrayBufferByteLength ( arrayBuffer, order ), https://tc39.es/ecma262/#sec-arraybufferbytelength
inline size_t array_buffer_byte_length(ArrayBuffer const& array_buffer, ArrayBuffer::Order) inline size_t array_buffer_byte_length(ArrayBuffer const& array_buffer, ArrayBuffer::Order)

View file

@ -14,7 +14,7 @@
namespace JS { namespace JS {
JS_DEFINE_ALLOCATOR(ArrayBufferConstructor); GC_DEFINE_ALLOCATOR(ArrayBufferConstructor);
ArrayBufferConstructor::ArrayBufferConstructor(Realm& realm) ArrayBufferConstructor::ArrayBufferConstructor(Realm& realm)
: NativeFunction(realm.vm().names.ArrayBuffer.as_string(), realm.intrinsics().function_prototype()) : NativeFunction(realm.vm().names.ArrayBuffer.as_string(), realm.intrinsics().function_prototype())
@ -48,7 +48,7 @@ ThrowCompletionOr<Value> ArrayBufferConstructor::call()
} }
// 25.1.4.1 ArrayBuffer ( length [ , options ] ), https://tc39.es/ecma262/#sec-arraybuffer-length // 25.1.4.1 ArrayBuffer ( length [ , options ] ), https://tc39.es/ecma262/#sec-arraybuffer-length
ThrowCompletionOr<NonnullGCPtr<Object>> ArrayBufferConstructor::construct(FunctionObject& new_target) ThrowCompletionOr<GC::Ref<Object>> ArrayBufferConstructor::construct(FunctionObject& new_target)
{ {
auto& vm = this->vm(); auto& vm = this->vm();

View file

@ -12,14 +12,14 @@ namespace JS {
class ArrayBufferConstructor final : public NativeFunction { class ArrayBufferConstructor final : public NativeFunction {
JS_OBJECT(ArrayBufferConstructor, NativeFunction); JS_OBJECT(ArrayBufferConstructor, NativeFunction);
JS_DECLARE_ALLOCATOR(ArrayBufferConstructor); GC_DECLARE_ALLOCATOR(ArrayBufferConstructor);
public: public:
virtual void initialize(Realm&) override; virtual void initialize(Realm&) override;
virtual ~ArrayBufferConstructor() override = default; virtual ~ArrayBufferConstructor() override = default;
virtual ThrowCompletionOr<Value> call() override; virtual ThrowCompletionOr<Value> call() override;
virtual ThrowCompletionOr<NonnullGCPtr<Object>> construct(FunctionObject& new_target) override; virtual ThrowCompletionOr<GC::Ref<Object>> construct(FunctionObject& new_target) override;
private: private:
explicit ArrayBufferConstructor(Realm&); explicit ArrayBufferConstructor(Realm&);

View file

@ -14,7 +14,7 @@
namespace JS { namespace JS {
JS_DEFINE_ALLOCATOR(ArrayBufferPrototype); GC_DEFINE_ALLOCATOR(ArrayBufferPrototype);
ArrayBufferPrototype::ArrayBufferPrototype(Realm& realm) ArrayBufferPrototype::ArrayBufferPrototype(Realm& realm)
: PrototypeObject(realm.intrinsics().object_prototype()) : PrototypeObject(realm.intrinsics().object_prototype())

View file

@ -13,7 +13,7 @@ namespace JS {
class ArrayBufferPrototype final : public PrototypeObject<ArrayBufferPrototype, ArrayBuffer> { class ArrayBufferPrototype final : public PrototypeObject<ArrayBufferPrototype, ArrayBuffer> {
JS_PROTOTYPE_OBJECT(ArrayBufferPrototype, ArrayBuffer, ArrayBuffer); JS_PROTOTYPE_OBJECT(ArrayBufferPrototype, ArrayBuffer, ArrayBuffer);
JS_DECLARE_ALLOCATOR(ArrayBufferPrototype); GC_DECLARE_ALLOCATOR(ArrayBufferPrototype);
public: public:
virtual void initialize(Realm&) override; virtual void initialize(Realm&) override;

View file

@ -22,7 +22,7 @@
namespace JS { namespace JS {
JS_DEFINE_ALLOCATOR(ArrayConstructor); GC_DEFINE_ALLOCATOR(ArrayConstructor);
ArrayConstructor::ArrayConstructor(Realm& realm) ArrayConstructor::ArrayConstructor(Realm& realm)
: NativeFunction(realm.vm().names.Array.as_string(), realm.intrinsics().function_prototype()) : NativeFunction(realm.vm().names.Array.as_string(), realm.intrinsics().function_prototype())
@ -57,7 +57,7 @@ ThrowCompletionOr<Value> ArrayConstructor::call()
} }
// 23.1.1.1 Array ( ...values ), https://tc39.es/ecma262/#sec-array // 23.1.1.1 Array ( ...values ), https://tc39.es/ecma262/#sec-array
ThrowCompletionOr<NonnullGCPtr<Object>> ArrayConstructor::construct(FunctionObject& new_target) ThrowCompletionOr<GC::Ref<Object>> ArrayConstructor::construct(FunctionObject& new_target)
{ {
auto& vm = this->vm(); auto& vm = this->vm();
auto& realm = *vm.current_realm(); auto& realm = *vm.current_realm();
@ -149,7 +149,7 @@ JS_DEFINE_NATIVE_FUNCTION(ArrayConstructor::from)
auto constructor = vm.this_value(); auto constructor = vm.this_value();
// 2. If mapfn is undefined, let mapping be false. // 2. If mapfn is undefined, let mapping be false.
GCPtr<FunctionObject> mapfn; GC::Ptr<FunctionObject> mapfn;
// 3. Else, // 3. Else,
if (!mapfn_value.is_undefined()) { if (!mapfn_value.is_undefined()) {
@ -166,7 +166,7 @@ JS_DEFINE_NATIVE_FUNCTION(ArrayConstructor::from)
// 5. If usingIterator is not undefined, then // 5. If usingIterator is not undefined, then
if (using_iterator) { if (using_iterator) {
GCPtr<Object> array; GC::Ptr<Object> array;
// a. If IsConstructor(C) is true, then // a. If IsConstructor(C) is true, then
if (constructor.is_constructor()) { if (constructor.is_constructor()) {
@ -245,7 +245,7 @@ JS_DEFINE_NATIVE_FUNCTION(ArrayConstructor::from)
// 8. Let len be ? LengthOfArrayLike(arrayLike). // 8. Let len be ? LengthOfArrayLike(arrayLike).
auto length = TRY(length_of_array_like(vm, array_like)); auto length = TRY(length_of_array_like(vm, array_like));
GCPtr<Object> array; GC::Ptr<Object> array;
// 9. If IsConstructor(C) is true, then // 9. If IsConstructor(C) is true, then
if (constructor.is_constructor()) { if (constructor.is_constructor()) {
@ -306,7 +306,7 @@ JS_DEFINE_NATIVE_FUNCTION(ArrayConstructor::from_async)
auto promise_capability = MUST(new_promise_capability(vm, realm.intrinsics().promise_constructor())); auto promise_capability = MUST(new_promise_capability(vm, realm.intrinsics().promise_constructor()));
// 3. Let fromAsyncClosure be a new Abstract Closure with no parameters that captures C, mapfn, and thisArg and performs the following steps when called: // 3. Let fromAsyncClosure be a new Abstract Closure with no parameters that captures C, mapfn, and thisArg and performs the following steps when called:
auto from_async_closure = create_heap_function(realm.heap(), [constructor, mapfn, this_arg, &vm, &realm, async_items]() mutable -> Completion { auto from_async_closure = GC::create_function(realm.heap(), [constructor, mapfn, this_arg, &vm, &realm, async_items]() mutable -> Completion {
bool mapping; bool mapping;
// a. If mapfn is undefined, let mapping be false. // a. If mapfn is undefined, let mapping be false.
@ -326,7 +326,7 @@ JS_DEFINE_NATIVE_FUNCTION(ArrayConstructor::from_async)
// c. Let usingAsyncIterator be ? GetMethod(asyncItems, @@asyncIterator). // c. Let usingAsyncIterator be ? GetMethod(asyncItems, @@asyncIterator).
auto using_async_iterator = TRY(async_items.get_method(vm, vm.well_known_symbol_async_iterator())); auto using_async_iterator = TRY(async_items.get_method(vm, vm.well_known_symbol_async_iterator()));
GCPtr<FunctionObject> using_sync_iterator; GC::Ptr<FunctionObject> using_sync_iterator;
// d. If usingAsyncIterator is undefined, then // d. If usingAsyncIterator is undefined, then
if (!using_async_iterator) { if (!using_async_iterator) {
@ -335,7 +335,7 @@ JS_DEFINE_NATIVE_FUNCTION(ArrayConstructor::from_async)
} }
// e. Let iteratorRecord be undefined. // e. Let iteratorRecord be undefined.
GCPtr<IteratorRecord> iterator_record; GC::Ptr<IteratorRecord> iterator_record;
// f. If usingAsyncIterator is not undefined, then // f. If usingAsyncIterator is not undefined, then
if (using_async_iterator) { if (using_async_iterator) {
@ -352,7 +352,7 @@ JS_DEFINE_NATIVE_FUNCTION(ArrayConstructor::from_async)
// h. If iteratorRecord is not undefined, then // h. If iteratorRecord is not undefined, then
if (iterator_record) { if (iterator_record) {
GCPtr<Object> array; GC::Ptr<Object> array;
// i. If IsConstructor(C) is true, then // i. If IsConstructor(C) is true, then
if (constructor.is_constructor()) { if (constructor.is_constructor()) {
@ -458,7 +458,7 @@ JS_DEFINE_NATIVE_FUNCTION(ArrayConstructor::from_async)
// iii. Let len be ? LengthOfArrayLike(arrayLike). // iii. Let len be ? LengthOfArrayLike(arrayLike).
auto length = TRY(length_of_array_like(vm, array_like)); auto length = TRY(length_of_array_like(vm, array_like));
GCPtr<Object> array; GC::Ptr<Object> array;
// iv. If IsConstructor(C) is true, then // iv. If IsConstructor(C) is true, then
if (constructor.is_constructor()) { if (constructor.is_constructor()) {
@ -542,7 +542,7 @@ JS_DEFINE_NATIVE_FUNCTION(ArrayConstructor::of)
// 3. Let C be the this value. // 3. Let C be the this value.
auto constructor = vm.this_value(); auto constructor = vm.this_value();
GCPtr<Object> array; GC::Ptr<Object> array;
// 4. If IsConstructor(C) is true, then // 4. If IsConstructor(C) is true, then
if (constructor.is_constructor()) { if (constructor.is_constructor()) {

View file

@ -12,14 +12,14 @@ namespace JS {
class ArrayConstructor final : public NativeFunction { class ArrayConstructor final : public NativeFunction {
JS_OBJECT(ArrayConstructor, NativeFunction); JS_OBJECT(ArrayConstructor, NativeFunction);
JS_DECLARE_ALLOCATOR(ArrayConstructor); GC_DECLARE_ALLOCATOR(ArrayConstructor);
public: public:
virtual void initialize(Realm&) override; virtual void initialize(Realm&) override;
virtual ~ArrayConstructor() override = default; virtual ~ArrayConstructor() override = default;
virtual ThrowCompletionOr<Value> call() override; virtual ThrowCompletionOr<Value> call() override;
virtual ThrowCompletionOr<NonnullGCPtr<Object>> construct(FunctionObject& new_target) override; virtual ThrowCompletionOr<GC::Ref<Object>> construct(FunctionObject& new_target) override;
private: private:
explicit ArrayConstructor(Realm&); explicit ArrayConstructor(Realm&);

View file

@ -9,9 +9,9 @@
namespace JS { namespace JS {
JS_DEFINE_ALLOCATOR(ArrayIterator); GC_DEFINE_ALLOCATOR(ArrayIterator);
NonnullGCPtr<ArrayIterator> ArrayIterator::create(Realm& realm, Value array, Object::PropertyKind iteration_kind) GC::Ref<ArrayIterator> ArrayIterator::create(Realm& realm, Value array, Object::PropertyKind iteration_kind)
{ {
return realm.create<ArrayIterator>(array, iteration_kind, realm.intrinsics().array_iterator_prototype()); return realm.create<ArrayIterator>(array, iteration_kind, realm.intrinsics().array_iterator_prototype());
} }

View file

@ -12,10 +12,10 @@ namespace JS {
class ArrayIterator final : public Object { class ArrayIterator final : public Object {
JS_OBJECT(ArrayIterator, Object); JS_OBJECT(ArrayIterator, Object);
JS_DECLARE_ALLOCATOR(ArrayIterator); GC_DECLARE_ALLOCATOR(ArrayIterator);
public: public:
static NonnullGCPtr<ArrayIterator> create(Realm&, Value array, Object::PropertyKind iteration_kind); static GC::Ref<ArrayIterator> create(Realm&, Value array, Object::PropertyKind iteration_kind);
virtual ~ArrayIterator() override = default; virtual ~ArrayIterator() override = default;

View file

@ -14,7 +14,7 @@
namespace JS { namespace JS {
JS_DEFINE_ALLOCATOR(ArrayIteratorPrototype); GC_DEFINE_ALLOCATOR(ArrayIteratorPrototype);
ArrayIteratorPrototype::ArrayIteratorPrototype(Realm& realm) ArrayIteratorPrototype::ArrayIteratorPrototype(Realm& realm)
: PrototypeObject(realm.intrinsics().iterator_prototype()) : PrototypeObject(realm.intrinsics().iterator_prototype())

View file

@ -13,7 +13,7 @@ namespace JS {
class ArrayIteratorPrototype final : public PrototypeObject<ArrayIteratorPrototype, ArrayIterator> { class ArrayIteratorPrototype final : public PrototypeObject<ArrayIteratorPrototype, ArrayIterator> {
JS_PROTOTYPE_OBJECT(ArrayIteratorPrototype, ArrayIterator, ArrayIterator); JS_PROTOTYPE_OBJECT(ArrayIteratorPrototype, ArrayIterator, ArrayIterator);
JS_DECLARE_ALLOCATOR(ArrayIteratorPrototype); GC_DECLARE_ALLOCATOR(ArrayIteratorPrototype);
public: public:
virtual void initialize(Realm&) override; virtual void initialize(Realm&) override;

View file

@ -27,9 +27,9 @@
namespace JS { namespace JS {
JS_DEFINE_ALLOCATOR(ArrayPrototype); GC_DEFINE_ALLOCATOR(ArrayPrototype);
static HashTable<NonnullGCPtr<Object>> s_array_join_seen_objects; static HashTable<GC::Ref<Object>> s_array_join_seen_objects;
ArrayPrototype::ArrayPrototype(Realm& realm) ArrayPrototype::ArrayPrototype(Realm& realm)
: Array(realm.intrinsics().object_prototype()) : Array(realm.intrinsics().object_prototype())
@ -1339,15 +1339,15 @@ JS_DEFINE_NATIVE_FUNCTION(ArrayPrototype::some)
return Value(false); return Value(false);
} }
ThrowCompletionOr<void> array_merge_sort(VM& vm, Function<ThrowCompletionOr<double>(Value, Value)> const& compare_func, MarkedVector<Value>& arr_to_sort) ThrowCompletionOr<void> array_merge_sort(VM& vm, Function<ThrowCompletionOr<double>(Value, Value)> const& compare_func, GC::MarkedVector<Value>& arr_to_sort)
{ {
// FIXME: it would probably be better to switch to insertion sort for small arrays for // FIXME: it would probably be better to switch to insertion sort for small arrays for
// better performance // better performance
if (arr_to_sort.size() <= 1) if (arr_to_sort.size() <= 1)
return {}; return {};
MarkedVector<Value> left(vm.heap()); GC::MarkedVector<Value> left(vm.heap());
MarkedVector<Value> right(vm.heap()); GC::MarkedVector<Value> right(vm.heap());
left.ensure_capacity(arr_to_sort.size() / 2); left.ensure_capacity(arr_to_sort.size() / 2);
right.ensure_capacity(arr_to_sort.size() / 2 + (arr_to_sort.size() & 1)); right.ensure_capacity(arr_to_sort.size() / 2 + (arr_to_sort.size() & 1));

View file

@ -13,7 +13,7 @@ namespace JS {
class ArrayPrototype final : public Array { class ArrayPrototype final : public Array {
JS_OBJECT(ArrayPrototype, Array); JS_OBJECT(ArrayPrototype, Array);
JS_DECLARE_ALLOCATOR(ArrayPrototype); GC_DECLARE_ALLOCATOR(ArrayPrototype);
public: public:
virtual void initialize(Realm&) override; virtual void initialize(Realm&) override;
@ -64,6 +64,6 @@ private:
JS_DECLARE_NATIVE_FUNCTION(with); JS_DECLARE_NATIVE_FUNCTION(with);
}; };
ThrowCompletionOr<void> array_merge_sort(VM&, Function<ThrowCompletionOr<double>(Value, Value)> const& compare_func, MarkedVector<Value>& arr_to_sort); ThrowCompletionOr<void> array_merge_sort(VM&, Function<ThrowCompletionOr<double>(Value, Value)> const& compare_func, GC::MarkedVector<Value>& arr_to_sort);
} }

View file

@ -11,14 +11,14 @@
namespace JS { namespace JS {
JS_DEFINE_ALLOCATOR(AsyncFromSyncIterator); GC_DEFINE_ALLOCATOR(AsyncFromSyncIterator);
NonnullGCPtr<AsyncFromSyncIterator> AsyncFromSyncIterator::create(Realm& realm, NonnullGCPtr<IteratorRecord> sync_iterator_record) GC::Ref<AsyncFromSyncIterator> AsyncFromSyncIterator::create(Realm& realm, GC::Ref<IteratorRecord> sync_iterator_record)
{ {
return realm.create<AsyncFromSyncIterator>(realm, sync_iterator_record); return realm.create<AsyncFromSyncIterator>(realm, sync_iterator_record);
} }
AsyncFromSyncIterator::AsyncFromSyncIterator(Realm& realm, NonnullGCPtr<IteratorRecord> sync_iterator_record) AsyncFromSyncIterator::AsyncFromSyncIterator(Realm& realm, GC::Ref<IteratorRecord> sync_iterator_record)
: Object(ConstructWithPrototypeTag::Tag, realm.intrinsics().async_from_sync_iterator_prototype()) : Object(ConstructWithPrototypeTag::Tag, realm.intrinsics().async_from_sync_iterator_prototype())
, m_sync_iterator_record(sync_iterator_record) , m_sync_iterator_record(sync_iterator_record)
{ {

View file

@ -15,10 +15,10 @@ namespace JS {
// 27.1.4.3 Properties of Async-from-Sync Iterator Instances, https://tc39.es/ecma262/#sec-properties-of-async-from-sync-iterator-instances // 27.1.4.3 Properties of Async-from-Sync Iterator Instances, https://tc39.es/ecma262/#sec-properties-of-async-from-sync-iterator-instances
class AsyncFromSyncIterator final : public Object { class AsyncFromSyncIterator final : public Object {
JS_OBJECT(AsyncFromSyncIterator, Object); JS_OBJECT(AsyncFromSyncIterator, Object);
JS_DECLARE_ALLOCATOR(AsyncFromSyncIterator); GC_DECLARE_ALLOCATOR(AsyncFromSyncIterator);
public: public:
static NonnullGCPtr<AsyncFromSyncIterator> create(Realm&, NonnullGCPtr<IteratorRecord> sync_iterator_record); static GC::Ref<AsyncFromSyncIterator> create(Realm&, GC::Ref<IteratorRecord> sync_iterator_record);
virtual ~AsyncFromSyncIterator() override = default; virtual ~AsyncFromSyncIterator() override = default;
@ -28,9 +28,9 @@ public:
IteratorRecord const& sync_iterator_record() const { return m_sync_iterator_record; } IteratorRecord const& sync_iterator_record() const { return m_sync_iterator_record; }
private: private:
AsyncFromSyncIterator(Realm&, NonnullGCPtr<IteratorRecord> sync_iterator_record); AsyncFromSyncIterator(Realm&, GC::Ref<IteratorRecord> sync_iterator_record);
NonnullGCPtr<IteratorRecord> m_sync_iterator_record; // [[SyncIteratorRecord]] GC::Ref<IteratorRecord> m_sync_iterator_record; // [[SyncIteratorRecord]]
}; };
} }

View file

@ -14,7 +14,7 @@
namespace JS { namespace JS {
JS_DEFINE_ALLOCATOR(AsyncFromSyncIteratorPrototype); GC_DEFINE_ALLOCATOR(AsyncFromSyncIteratorPrototype);
AsyncFromSyncIteratorPrototype::AsyncFromSyncIteratorPrototype(Realm& realm) AsyncFromSyncIteratorPrototype::AsyncFromSyncIteratorPrototype(Realm& realm)
: PrototypeObject(realm.intrinsics().async_iterator_prototype()) : PrototypeObject(realm.intrinsics().async_iterator_prototype())
@ -199,7 +199,7 @@ JS_DEFINE_NATIVE_FUNCTION(AsyncFromSyncIteratorPrototype::throw_)
} }
// 27.1.4.1 CreateAsyncFromSyncIterator ( syncIteratorRecord ), https://tc39.es/ecma262/#sec-createasyncfromsynciterator // 27.1.4.1 CreateAsyncFromSyncIterator ( syncIteratorRecord ), https://tc39.es/ecma262/#sec-createasyncfromsynciterator
NonnullGCPtr<IteratorRecord> create_async_from_sync_iterator(VM& vm, NonnullGCPtr<IteratorRecord> sync_iterator_record) GC::Ref<IteratorRecord> create_async_from_sync_iterator(VM& vm, GC::Ref<IteratorRecord> sync_iterator_record)
{ {
auto& realm = *vm.current_realm(); auto& realm = *vm.current_realm();

View file

@ -17,7 +17,7 @@ namespace JS {
// 27.1.4.2 The %AsyncFromSyncIteratorPrototype% Object, https://tc39.es/ecma262/#sec-%asyncfromsynciteratorprototype%-object // 27.1.4.2 The %AsyncFromSyncIteratorPrototype% Object, https://tc39.es/ecma262/#sec-%asyncfromsynciteratorprototype%-object
class AsyncFromSyncIteratorPrototype final : public PrototypeObject<AsyncFromSyncIteratorPrototype, AsyncFromSyncIterator> { class AsyncFromSyncIteratorPrototype final : public PrototypeObject<AsyncFromSyncIteratorPrototype, AsyncFromSyncIterator> {
JS_PROTOTYPE_OBJECT(AsyncFromSyncIteratorPrototype, AsyncFromSyncIterator, AsyncFromSyncIterator); JS_PROTOTYPE_OBJECT(AsyncFromSyncIteratorPrototype, AsyncFromSyncIterator, AsyncFromSyncIterator);
JS_DECLARE_ALLOCATOR(AsyncFromSyncIteratorPrototype); GC_DECLARE_ALLOCATOR(AsyncFromSyncIteratorPrototype);
public: public:
virtual void initialize(Realm&) override; virtual void initialize(Realm&) override;
@ -31,6 +31,6 @@ private:
JS_DECLARE_NATIVE_FUNCTION(throw_); JS_DECLARE_NATIVE_FUNCTION(throw_);
}; };
NonnullGCPtr<IteratorRecord> create_async_from_sync_iterator(VM&, NonnullGCPtr<IteratorRecord> sync_iterator); GC::Ref<IteratorRecord> create_async_from_sync_iterator(VM&, GC::Ref<IteratorRecord> sync_iterator);
} }

View file

@ -12,7 +12,7 @@
namespace JS { namespace JS {
JS_DEFINE_ALLOCATOR(AsyncFunctionConstructor); GC_DEFINE_ALLOCATOR(AsyncFunctionConstructor);
AsyncFunctionConstructor::AsyncFunctionConstructor(Realm& realm) AsyncFunctionConstructor::AsyncFunctionConstructor(Realm& realm)
: NativeFunction(realm.vm().names.AsyncFunction.as_string(), realm.intrinsics().function_constructor()) : NativeFunction(realm.vm().names.AsyncFunction.as_string(), realm.intrinsics().function_constructor())
@ -37,7 +37,7 @@ ThrowCompletionOr<Value> AsyncFunctionConstructor::call()
} }
// 27.7.1.1 AsyncFunction ( ...parameterArgs, bodyArg ), https://tc39.es/ecma262/#sec-async-function-constructor-arguments // 27.7.1.1 AsyncFunction ( ...parameterArgs, bodyArg ), https://tc39.es/ecma262/#sec-async-function-constructor-arguments
ThrowCompletionOr<NonnullGCPtr<Object>> AsyncFunctionConstructor::construct(FunctionObject& new_target) ThrowCompletionOr<GC::Ref<Object>> AsyncFunctionConstructor::construct(FunctionObject& new_target)
{ {
auto& vm = this->vm(); auto& vm = this->vm();

View file

@ -12,14 +12,14 @@ namespace JS {
class AsyncFunctionConstructor final : public NativeFunction { class AsyncFunctionConstructor final : public NativeFunction {
JS_OBJECT(AsyncFunctionConstructor, NativeFunction); JS_OBJECT(AsyncFunctionConstructor, NativeFunction);
JS_DECLARE_ALLOCATOR(AsyncFunctionConstructor); GC_DECLARE_ALLOCATOR(AsyncFunctionConstructor);
public: public:
virtual void initialize(Realm&) override; virtual void initialize(Realm&) override;
virtual ~AsyncFunctionConstructor() override = default; virtual ~AsyncFunctionConstructor() override = default;
virtual ThrowCompletionOr<Value> call() override; virtual ThrowCompletionOr<Value> call() override;
virtual ThrowCompletionOr<NonnullGCPtr<Object>> construct(FunctionObject& new_target) override; virtual ThrowCompletionOr<GC::Ref<Object>> construct(FunctionObject& new_target) override;
private: private:
explicit AsyncFunctionConstructor(Realm&); explicit AsyncFunctionConstructor(Realm&);

View file

@ -15,9 +15,9 @@
namespace JS { namespace JS {
JS_DEFINE_ALLOCATOR(AsyncFunctionDriverWrapper); GC_DEFINE_ALLOCATOR(AsyncFunctionDriverWrapper);
NonnullGCPtr<Promise> AsyncFunctionDriverWrapper::create(Realm& realm, GeneratorObject* generator_object) GC::Ref<Promise> AsyncFunctionDriverWrapper::create(Realm& realm, GeneratorObject* generator_object)
{ {
auto top_level_promise = Promise::create(realm); auto top_level_promise = Promise::create(realm);
// Note: The top_level_promise is also kept alive by this Wrapper // Note: The top_level_promise is also kept alive by this Wrapper
@ -29,7 +29,7 @@ NonnullGCPtr<Promise> AsyncFunctionDriverWrapper::create(Realm& realm, Generator
return top_level_promise; return top_level_promise;
} }
AsyncFunctionDriverWrapper::AsyncFunctionDriverWrapper(Realm& realm, NonnullGCPtr<GeneratorObject> generator_object, NonnullGCPtr<Promise> top_level_promise) AsyncFunctionDriverWrapper::AsyncFunctionDriverWrapper(Realm& realm, GC::Ref<GeneratorObject> generator_object, GC::Ref<Promise> top_level_promise)
: Promise(realm.intrinsics().promise_prototype()) : Promise(realm.intrinsics().promise_prototype())
, m_generator_object(generator_object) , m_generator_object(generator_object)
, m_top_level_promise(top_level_promise) , m_top_level_promise(top_level_promise)

View file

@ -16,7 +16,7 @@ namespace JS {
class AsyncFunctionDriverWrapper final : public Promise { class AsyncFunctionDriverWrapper final : public Promise {
JS_OBJECT(AsyncFunctionDriverWrapper, Promise); JS_OBJECT(AsyncFunctionDriverWrapper, Promise);
JS_DECLARE_ALLOCATOR(AsyncFunctionDriverWrapper); GC_DECLARE_ALLOCATOR(AsyncFunctionDriverWrapper);
public: public:
enum class IsInitialExecution { enum class IsInitialExecution {
@ -24,7 +24,7 @@ public:
Yes, Yes,
}; };
[[nodiscard]] static NonnullGCPtr<Promise> create(Realm&, GeneratorObject*); [[nodiscard]] static GC::Ref<Promise> create(Realm&, GeneratorObject*);
virtual ~AsyncFunctionDriverWrapper() override = default; virtual ~AsyncFunctionDriverWrapper() override = default;
void visit_edges(Cell::Visitor&) override; void visit_edges(Cell::Visitor&) override;
@ -32,12 +32,12 @@ public:
void continue_async_execution(VM&, Value, bool is_successful, IsInitialExecution is_initial_execution = IsInitialExecution::No); void continue_async_execution(VM&, Value, bool is_successful, IsInitialExecution is_initial_execution = IsInitialExecution::No);
private: private:
AsyncFunctionDriverWrapper(Realm&, NonnullGCPtr<GeneratorObject>, NonnullGCPtr<Promise> top_level_promise); AsyncFunctionDriverWrapper(Realm&, GC::Ref<GeneratorObject>, GC::Ref<Promise> top_level_promise);
ThrowCompletionOr<void> await(Value); ThrowCompletionOr<void> await(Value);
NonnullGCPtr<GeneratorObject> m_generator_object; GC::Ref<GeneratorObject> m_generator_object;
NonnullGCPtr<Promise> m_top_level_promise; GC::Ref<Promise> m_top_level_promise;
GCPtr<Promise> m_current_promise { nullptr }; GC::Ptr<Promise> m_current_promise { nullptr };
OwnPtr<ExecutionContext> m_suspended_execution_context; OwnPtr<ExecutionContext> m_suspended_execution_context;
}; };

View file

@ -9,7 +9,7 @@
namespace JS { namespace JS {
JS_DEFINE_ALLOCATOR(AsyncFunctionPrototype); GC_DEFINE_ALLOCATOR(AsyncFunctionPrototype);
AsyncFunctionPrototype::AsyncFunctionPrototype(Realm& realm) AsyncFunctionPrototype::AsyncFunctionPrototype(Realm& realm)
: Object(ConstructWithPrototypeTag::Tag, realm.intrinsics().function_prototype()) : Object(ConstructWithPrototypeTag::Tag, realm.intrinsics().function_prototype())

View file

@ -12,7 +12,7 @@ namespace JS {
class AsyncFunctionPrototype final : public Object { class AsyncFunctionPrototype final : public Object {
JS_OBJECT(AsyncFunctionPrototype, Object); JS_OBJECT(AsyncFunctionPrototype, Object);
JS_DECLARE_ALLOCATOR(AsyncFunctionPrototype); GC_DECLARE_ALLOCATOR(AsyncFunctionPrototype);
public: public:
virtual void initialize(Realm&) override; virtual void initialize(Realm&) override;

View file

@ -14,9 +14,9 @@
namespace JS { namespace JS {
JS_DEFINE_ALLOCATOR(AsyncGenerator); GC_DEFINE_ALLOCATOR(AsyncGenerator);
ThrowCompletionOr<NonnullGCPtr<AsyncGenerator>> AsyncGenerator::create(Realm& realm, Value initial_value, ECMAScriptFunctionObject* generating_function, NonnullOwnPtr<ExecutionContext> execution_context) ThrowCompletionOr<GC::Ref<AsyncGenerator>> AsyncGenerator::create(Realm& realm, Value initial_value, ECMAScriptFunctionObject* generating_function, NonnullOwnPtr<ExecutionContext> execution_context)
{ {
auto& vm = realm.vm(); auto& vm = realm.vm();
// This is "g1.prototype" in figure-2 (https://tc39.es/ecma262/img/figure-2.png) // This is "g1.prototype" in figure-2 (https://tc39.es/ecma262/img/figure-2.png)
@ -51,7 +51,7 @@ void AsyncGenerator::visit_edges(Cell::Visitor& visitor)
} }
// 27.6.3.4 AsyncGeneratorEnqueue ( generator, completion, promiseCapability ), https://tc39.es/ecma262/#sec-asyncgeneratorenqueue // 27.6.3.4 AsyncGeneratorEnqueue ( generator, completion, promiseCapability ), https://tc39.es/ecma262/#sec-asyncgeneratorenqueue
void AsyncGenerator::async_generator_enqueue(Completion completion, NonnullGCPtr<PromiseCapability> promise_capability) void AsyncGenerator::async_generator_enqueue(Completion completion, GC::Ref<PromiseCapability> promise_capability)
{ {
// 1. Let request be AsyncGeneratorRequest { [[Completion]]: completion, [[Capability]]: promiseCapability }. // 1. Let request be AsyncGeneratorRequest { [[Completion]]: completion, [[Capability]]: promiseCapability }.
auto request = AsyncGeneratorRequest { .completion = move(completion), .capability = promise_capability }; auto request = AsyncGeneratorRequest { .completion = move(completion), .capability = promise_capability };
@ -458,7 +458,7 @@ void AsyncGenerator::complete_step(Completion completion, bool done, Realm* real
// a. Assert: completion.[[Type]] is normal. // a. Assert: completion.[[Type]] is normal.
VERIFY(completion.type() == Completion::Type::Normal); VERIFY(completion.type() == Completion::Type::Normal);
GCPtr<Object> iterator_result; GC::Ptr<Object> iterator_result;
// b. If realm is present, then // b. If realm is present, then
if (realm) { if (realm) {

View file

@ -17,7 +17,7 @@ namespace JS {
// 27.6.2 Properties of AsyncGenerator Instances, https://tc39.es/ecma262/#sec-properties-of-asyncgenerator-intances // 27.6.2 Properties of AsyncGenerator Instances, https://tc39.es/ecma262/#sec-properties-of-asyncgenerator-intances
class AsyncGenerator final : public Object { class AsyncGenerator final : public Object {
JS_OBJECT(AsyncGenerator, Object); JS_OBJECT(AsyncGenerator, Object);
JS_DECLARE_ALLOCATOR(AsyncGenerator); GC_DECLARE_ALLOCATOR(AsyncGenerator);
public: public:
enum class State { enum class State {
@ -28,11 +28,11 @@ public:
Completed, Completed,
}; };
static ThrowCompletionOr<NonnullGCPtr<AsyncGenerator>> create(Realm&, Value, ECMAScriptFunctionObject*, NonnullOwnPtr<ExecutionContext>); static ThrowCompletionOr<GC::Ref<AsyncGenerator>> create(Realm&, Value, ECMAScriptFunctionObject*, NonnullOwnPtr<ExecutionContext>);
virtual ~AsyncGenerator() override; virtual ~AsyncGenerator() override;
void async_generator_enqueue(Completion, NonnullGCPtr<PromiseCapability>); void async_generator_enqueue(Completion, GC::Ref<PromiseCapability>);
ThrowCompletionOr<void> resume(VM&, Completion completion); ThrowCompletionOr<void> resume(VM&, Completion completion);
void await_return(); void await_return();
void complete_step(Completion, bool done, Realm* realm = nullptr); void complete_step(Completion, bool done, Realm* realm = nullptr);
@ -58,9 +58,9 @@ private:
Vector<AsyncGeneratorRequest> m_async_generator_queue; // [[AsyncGeneratorQueue]] Vector<AsyncGeneratorRequest> m_async_generator_queue; // [[AsyncGeneratorQueue]]
Optional<String> m_generator_brand; // [[GeneratorBrand]] Optional<String> m_generator_brand; // [[GeneratorBrand]]
GCPtr<ECMAScriptFunctionObject> m_generating_function; GC::Ptr<ECMAScriptFunctionObject> m_generating_function;
Value m_previous_value; Value m_previous_value;
GCPtr<Promise> m_current_promise; GC::Ptr<Promise> m_current_promise;
}; };
} }

View file

@ -12,7 +12,7 @@
namespace JS { namespace JS {
JS_DEFINE_ALLOCATOR(AsyncGeneratorFunctionConstructor); GC_DEFINE_ALLOCATOR(AsyncGeneratorFunctionConstructor);
AsyncGeneratorFunctionConstructor::AsyncGeneratorFunctionConstructor(Realm& realm) AsyncGeneratorFunctionConstructor::AsyncGeneratorFunctionConstructor(Realm& realm)
: NativeFunction(realm.vm().names.AsyncGeneratorFunction.as_string(), realm.intrinsics().function_prototype()) : NativeFunction(realm.vm().names.AsyncGeneratorFunction.as_string(), realm.intrinsics().function_prototype())
@ -38,7 +38,7 @@ ThrowCompletionOr<Value> AsyncGeneratorFunctionConstructor::call()
} }
// 27.4.1.1 AsyncGeneratorFunction ( ...parameterArgs, bodyArg ), https://tc39.es/ecma262/#sec-asyncgeneratorfunction // 27.4.1.1 AsyncGeneratorFunction ( ...parameterArgs, bodyArg ), https://tc39.es/ecma262/#sec-asyncgeneratorfunction
ThrowCompletionOr<NonnullGCPtr<Object>> AsyncGeneratorFunctionConstructor::construct(FunctionObject& new_target) ThrowCompletionOr<GC::Ref<Object>> AsyncGeneratorFunctionConstructor::construct(FunctionObject& new_target)
{ {
auto& vm = this->vm(); auto& vm = this->vm();

Some files were not shown because too many files have changed in this diff Show more