LibGC: Share root container value gathering
Add a small helper for turning root container values into Cell pointers, and use it from RootVector, RootHashTable, and RootHashMap.
This commit is contained in:
parent
45f1b18263
commit
47bd8388c5
4 changed files with 53 additions and 33 deletions
|
|
@ -11,6 +11,7 @@
|
|||
#include <LibGC/Cell.h>
|
||||
#include <LibGC/Forward.h>
|
||||
#include <LibGC/HeapRoot.h>
|
||||
#include <LibGC/Rootable.h>
|
||||
|
||||
namespace GC {
|
||||
|
||||
|
|
@ -49,24 +50,15 @@ public:
|
|||
|
||||
virtual void gather_roots(HashMap<Cell*, GC::HeapRoot>& roots) const override
|
||||
{
|
||||
static constexpr bool KeyIsGCType = IsBaseOf<NanBoxedValue, K> || IsConvertible<K, Cell const*>;
|
||||
static constexpr bool ValueIsGCType = IsBaseOf<NanBoxedValue, V> || IsConvertible<V, Cell const*>;
|
||||
static constexpr bool KeyIsGCType = Detail::RootableValueTraits<K>::is_rootable;
|
||||
static constexpr bool ValueIsGCType = Detail::RootableValueTraits<V>::is_rootable;
|
||||
static_assert(KeyIsGCType || ValueIsGCType,
|
||||
"RootHashMap requires at least one of key or value types to be convertible to Cell const* or derive from NanBoxedValue");
|
||||
for (auto& [key, value] : *this) {
|
||||
if constexpr (IsBaseOf<NanBoxedValue, K>) {
|
||||
if (key.is_cell())
|
||||
roots.set(&const_cast<K&>(key).as_cell(), HeapRoot { .type = HeapRoot::Type::RootHashMap });
|
||||
} else if constexpr (IsConvertible<K, Cell const*>) {
|
||||
roots.set(const_cast<Cell*>(static_cast<Cell const*>(key)), HeapRoot { .type = HeapRoot::Type::RootHashMap });
|
||||
}
|
||||
|
||||
if constexpr (IsBaseOf<NanBoxedValue, V>) {
|
||||
if (value.is_cell())
|
||||
roots.set(&const_cast<V&>(value).as_cell(), HeapRoot { .type = HeapRoot::Type::RootHashMap });
|
||||
} else if constexpr (IsConvertible<V, Cell const*>) {
|
||||
roots.set(const_cast<Cell*>(static_cast<Cell const*>(value)), HeapRoot { .type = HeapRoot::Type::RootHashMap });
|
||||
}
|
||||
if constexpr (KeyIsGCType)
|
||||
Detail::gather_root(roots, key, HeapRoot::Type::RootHashMap);
|
||||
if constexpr (ValueIsGCType)
|
||||
Detail::gather_root(roots, value, HeapRoot::Type::RootHashMap);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@
|
|||
#include <LibGC/Cell.h>
|
||||
#include <LibGC/Forward.h>
|
||||
#include <LibGC/HeapRoot.h>
|
||||
#include <LibGC/Rootable.h>
|
||||
|
||||
namespace GC {
|
||||
|
||||
|
|
@ -48,16 +49,10 @@ public:
|
|||
|
||||
virtual void gather_roots(HashMap<Cell*, GC::HeapRoot>& roots) const override
|
||||
{
|
||||
static_assert(IsBaseOf<NanBoxedValue, T> || IsConvertible<T, Cell const*>,
|
||||
static_assert(Detail::RootableValueTraits<T>::is_rootable,
|
||||
"RootHashTable element type must be convertible to Cell const* or derive from NanBoxedValue");
|
||||
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::RootHashTable });
|
||||
} else if constexpr (IsConvertible<T, Cell const*>) {
|
||||
roots.set(const_cast<Cell*>(static_cast<Cell const*>(value)), HeapRoot { .type = HeapRoot::Type::RootHashTable });
|
||||
}
|
||||
}
|
||||
for (auto& value : *this)
|
||||
Detail::gather_root(roots, value, HeapRoot::Type::RootHashTable);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@
|
|||
#include <LibGC/Cell.h>
|
||||
#include <LibGC/Forward.h>
|
||||
#include <LibGC/HeapRoot.h>
|
||||
#include <LibGC/Rootable.h>
|
||||
|
||||
namespace GC {
|
||||
|
||||
|
|
@ -86,16 +87,10 @@ public:
|
|||
|
||||
virtual void gather_roots(HashMap<Cell*, GC::HeapRoot>& roots) const override
|
||||
{
|
||||
static_assert(IsBaseOf<NanBoxedValue, T> || IsConvertible<T, Cell const*>,
|
||||
static_assert(Detail::RootableValueTraits<T>::is_rootable,
|
||||
"RootVector element type must be convertible to Cell const* or derive from NanBoxedValue");
|
||||
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 if constexpr (IsConvertible<T, Cell const*>) {
|
||||
roots.set(const_cast<Cell*>(static_cast<Cell const*>(value)), HeapRoot { .type = HeapRoot::Type::RootVector });
|
||||
}
|
||||
}
|
||||
for (auto& value : *this)
|
||||
Detail::gather_root(roots, value, HeapRoot::Type::RootVector);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
38
Libraries/LibGC/Rootable.h
Normal file
38
Libraries/LibGC/Rootable.h
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
/*
|
||||
* Copyright (c) 2026, the Ladybird developers.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <LibGC/Cell.h>
|
||||
#include <LibGC/HeapRoot.h>
|
||||
|
||||
namespace GC::Detail {
|
||||
|
||||
template<typename T>
|
||||
struct RootableValueTraits {
|
||||
static constexpr bool is_rootable = IsBaseOf<NanBoxedValue, T> || IsConvertible<T, Cell const*>;
|
||||
|
||||
static Cell* cell(T const& value)
|
||||
{
|
||||
if constexpr (IsBaseOf<NanBoxedValue, T>) {
|
||||
if (value.is_cell())
|
||||
return &const_cast<T&>(value).as_cell();
|
||||
} else if constexpr (IsConvertible<T, Cell const*>) {
|
||||
return const_cast<Cell*>(static_cast<Cell const*>(value));
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
static void gather_root(HashMap<Cell*, GC::HeapRoot>& roots, T const& value, HeapRoot::Type root_type)
|
||||
{
|
||||
if (auto* cell = RootableValueTraits<T>::cell(value))
|
||||
roots.set(cell, HeapRoot { .type = root_type });
|
||||
}
|
||||
|
||||
}
|
||||
Loading…
Reference in a new issue