ladybird/Libraries/LibGC/RootVector.h
Timothy Flynn 8ec420bc28
Some checks are pending
CI / Lagom (arm64, Sanitizer_CI, false, macos-15, macOS, Clang) (push) Waiting to run
CI / Lagom (x86_64, Fuzzers_CI, false, ubuntu-24.04, Linux, Clang) (push) Waiting to run
CI / Lagom (x86_64, Sanitizer_CI, false, ubuntu-24.04, Linux, GNU) (push) Waiting to run
CI / Lagom (x86_64, Sanitizer_CI, true, ubuntu-24.04, Linux, Clang) (push) Waiting to run
Package the js repl as a binary artifact / build-and-package (arm64, macos-15, macOS, macOS-universal2) (push) Waiting to run
Package the js repl as a binary artifact / build-and-package (x86_64, ubuntu-24.04, Linux, Linux-x86_64) (push) Waiting to run
Run test262 and test-wasm / run_and_update_results (push) Waiting to run
Lint Code / lint (push) Waiting to run
Label PRs with merge conflicts / auto-labeler (push) Waiting to run
Push notes / build (push) Waiting to run
LibGC: Allow move-assigning RootVector instances
Rule of 5 - we were missing a move-assignment operator, thus all move
assignments resulted in a copy.
2025-04-19 02:03:43 +02:00

99 lines
2.3 KiB
C++

/*
* Copyright (c) 2021, Andreas Kling <andreas@ladybird.org>
* Copyright (c) 2022, Linus Groh <linusg@serenityos.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#pragma once
#include <AK/HashMap.h>
#include <AK/IntrusiveList.h>
#include <AK/Vector.h>
#include <LibGC/Cell.h>
#include <LibGC/Forward.h>
#include <LibGC/HeapRoot.h>
namespace GC {
class RootVectorBase {
public:
virtual void gather_roots(HashMap<Cell*, GC::HeapRoot>&) const = 0;
protected:
explicit RootVectorBase(Heap&);
~RootVectorBase();
void assign_heap(Heap*);
Heap* m_heap { nullptr };
IntrusiveListNode<RootVectorBase> m_list_node;
public:
using List = IntrusiveList<&RootVectorBase::m_list_node>;
};
template<typename T, size_t inline_capacity>
class RootVector final
: public RootVectorBase
, public Vector<T, inline_capacity> {
using VectorBase = Vector<T, inline_capacity>;
public:
explicit RootVector(Heap& heap)
: RootVectorBase(heap)
{
}
virtual ~RootVector() = default;
RootVector(Heap& heap, ReadonlySpan<T> other)
: RootVectorBase(heap)
, Vector<T, inline_capacity>(other)
{
}
RootVector(RootVector const& other)
: RootVectorBase(*other.m_heap)
, Vector<T, inline_capacity>(other)
{
}
RootVector(RootVector&& other)
: RootVectorBase(*other.m_heap)
, VectorBase(move(static_cast<VectorBase&>(other)))
{
}
RootVector& operator=(RootVector const& other)
{
if (&other == this)
return *this;
assign_heap(other.m_heap);
VectorBase::operator=(other);
return *this;
}
RootVector& operator=(RootVector&& other)
{
assign_heap(other.m_heap);
VectorBase::operator=(move(static_cast<VectorBase&>(other)));
return *this;
}
virtual void gather_roots(HashMap<Cell*, GC::HeapRoot>& roots) const override
{
for (auto& value : *this) {
if constexpr (IsBaseOf<NanBoxedValue, T>) {
if (value.is_cell())
roots.set(&const_cast<T&>(value).as_cell(), HeapRoot { .type = HeapRoot::Type::RootVector });
} else {
roots.set(value, HeapRoot { .type = HeapRoot::Type::RootVector });
}
}
}
};
}