1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-05-14 21:44:59 +00:00
serenity/Userland/Libraries/LibJS/Heap/ConservativeVector.h
Andreas Kling 4bbb0a5c35 LibJS: Add ConservativeVector<T>
This works very similarly to MarkedVector<T>, but instead of expecting
T to be Value or a GC-allocated pointer type, T can be anything.
Every pointer-sized value in the vector's storage will be checked during
conservative root scanning.

In other words, this allows you to put something like this in a
ConservativeVector<Foo> and it will be protected from GC:

    struct Foo {
        i64 number;
        Value some_value;
        GCPtr<Object> some_object;
    };
2024-02-22 16:44:54 +01:00

73 lines
1.8 KiB
C++

/*
* Copyright (c) 2024, Andreas Kling <kling@serenityos.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#pragma once
#include <AK/HashMap.h>
#include <AK/IntrusiveList.h>
#include <AK/Vector.h>
#include <LibJS/Forward.h>
#include <LibJS/Heap/Cell.h>
#include <LibJS/Heap/HeapRoot.h>
namespace JS {
class ConservativeVectorBase {
public:
virtual ReadonlySpan<FlatPtr> possible_values() const = 0;
protected:
explicit ConservativeVectorBase(Heap&);
~ConservativeVectorBase();
ConservativeVectorBase& operator=(ConservativeVectorBase const&);
Heap* m_heap { nullptr };
IntrusiveListNode<ConservativeVectorBase> m_list_node;
public:
using List = IntrusiveList<&ConservativeVectorBase::m_list_node>;
};
template<typename T, size_t inline_capacity>
class ConservativeVector final
: public ConservativeVectorBase
, public Vector<T, inline_capacity> {
public:
explicit ConservativeVector(Heap& heap)
: ConservativeVectorBase(heap)
{
}
virtual ~ConservativeVector() = default;
ConservativeVector(ConservativeVector const& other)
: ConservativeVectorBase(*other.m_heap)
, Vector<T, inline_capacity>(other)
{
}
ConservativeVector(ConservativeVector&& other)
: ConservativeVectorBase(*other.m_heap)
, Vector<T, inline_capacity>(move(static_cast<Vector<T, inline_capacity>&>(other)))
{
}
ConservativeVector& operator=(ConservativeVector const& other)
{
Vector<T, inline_capacity>::operator=(other);
ConservativeVectorBase::operator=(other);
return *this;
}
virtual ReadonlySpan<FlatPtr> possible_values() const override
{
return ReadonlySpan<FlatPtr> { reinterpret_cast<FlatPtr const*>(this->data()), this->size() };
}
};
}