1
0
Fork 0
mirror of https://github.com/LadybirdBrowser/ladybird.git synced 2025-06-08 05:27:14 +09:00

LibGC: Add GC::RootHashMap<...> template container

This is a GC-aware wrapper around AK::HashMap. Entry values are treated
as GC roots, much like the GC::RootVector we already had.

We also provide GC::OrderedRootHashMap as a convenience.
This commit is contained in:
Andreas Kling 2025-05-03 11:59:17 +02:00 committed by Andreas Kling
parent a453da2906
commit 11ece7de10
Notes: github-actions[bot] 2025-05-03 15:34:58 +00:00
6 changed files with 122 additions and 0 deletions

View file

@ -5,6 +5,7 @@ set(SOURCES
ConservativeVector.cpp
ForeignCell.cpp
Root.cpp
RootHashMap.cpp
RootVector.cpp
Heap.cpp
HeapBlock.cpp

View file

@ -282,6 +282,9 @@ void Heap::gather_roots(HashMap<Cell*, HeapRoot>& roots)
for (auto& vector : m_root_vectors)
vector.gather_roots(roots);
for (auto& hash_map : m_root_hash_maps)
hash_map.gather_roots(roots);
if constexpr (HEAP_DEBUG) {
dbgln("gather_roots:");
for (auto* root : roots.keys())

View file

@ -24,6 +24,7 @@
#include <LibGC/HeapRoot.h>
#include <LibGC/Internals.h>
#include <LibGC/Root.h>
#include <LibGC/RootHashMap.h>
#include <LibGC/RootVector.h>
#include <LibGC/WeakContainer.h>
@ -64,6 +65,9 @@ public:
void did_create_root_vector(Badge<RootVectorBase>, RootVectorBase&);
void did_destroy_root_vector(Badge<RootVectorBase>, RootVectorBase&);
void did_create_root_hash_map(Badge<RootHashMapBase>, RootHashMapBase&);
void did_destroy_root_hash_map(Badge<RootHashMapBase>, RootHashMapBase&);
void did_create_conservative_vector(Badge<ConservativeVectorBase>, ConservativeVectorBase&);
void did_destroy_conservative_vector(Badge<ConservativeVectorBase>, ConservativeVectorBase&);
@ -142,6 +146,7 @@ private:
RootImpl::List m_roots;
RootVectorBase::List m_root_vectors;
RootHashMapBase::List m_root_hash_maps;
ConservativeVectorBase::List m_conservative_vectors;
WeakContainer::List m_weak_containers;
@ -181,6 +186,18 @@ inline void Heap::did_destroy_root_vector(Badge<RootVectorBase>, RootVectorBase&
m_root_vectors.remove(vector);
}
inline void Heap::did_create_root_hash_map(Badge<RootHashMapBase>, RootHashMapBase& hash_map)
{
VERIFY(!m_root_hash_maps.contains(hash_map));
m_root_hash_maps.append(hash_map);
}
inline void Heap::did_destroy_root_hash_map(Badge<RootHashMapBase>, RootHashMapBase& hash_map)
{
VERIFY(m_root_hash_maps.contains(hash_map));
m_root_hash_maps.remove(hash_map);
}
inline void Heap::did_create_conservative_vector(Badge<ConservativeVectorBase>, ConservativeVectorBase& vector)
{
VERIFY(!m_conservative_vectors.contains(vector));

View file

@ -15,6 +15,7 @@ struct HeapRoot {
HeapFunctionCapturedPointer,
Root,
RootVector,
RootHashMap,
ConservativeVector,
RegisterPointer,
StackPointer,

View file

@ -0,0 +1,34 @@
/*
* Copyright (c) 2025, Andreas Kling <andreas@ladybird.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#include <LibGC/Heap.h>
#include <LibGC/RootHashMap.h>
namespace GC {
RootHashMapBase::RootHashMapBase(Heap& heap)
: m_heap(&heap)
{
m_heap->did_create_root_hash_map({}, *this);
}
RootHashMapBase::~RootHashMapBase()
{
m_heap->did_destroy_root_hash_map({}, *this);
}
void RootHashMapBase::assign_heap(Heap* heap)
{
if (m_heap == heap)
return;
m_heap = heap;
// NOTE: IntrusiveList will remove this RootHashMap from the old heap it was part of.
m_heap->did_create_root_hash_map({}, *this);
}
}

View file

@ -0,0 +1,66 @@
/*
* Copyright (c) 2025, Andreas Kling <andreas@ladybird.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 RootHashMapBase {
public:
virtual void gather_roots(HashMap<Cell*, GC::HeapRoot>&) const = 0;
protected:
explicit RootHashMapBase(Heap&);
~RootHashMapBase();
void assign_heap(Heap*);
Heap* m_heap { nullptr };
IntrusiveListNode<RootHashMapBase> m_list_node;
public:
using List = IntrusiveList<&RootHashMapBase::m_list_node>;
};
template<typename K, typename V, typename KeyTraits = Traits<K>, typename ValueTraits = Traits<V>, bool IsOrdered = false>
class RootHashMap final
: public RootHashMapBase
, public HashMap<K, V, KeyTraits, ValueTraits, IsOrdered> {
using HashMapBase = HashMap<K, V, KeyTraits, ValueTraits, IsOrdered>;
public:
explicit RootHashMap(Heap& heap)
: RootHashMapBase(heap)
{
}
virtual ~RootHashMap() = default;
virtual void gather_roots(HashMap<Cell*, GC::HeapRoot>& roots) const override
{
for (auto& [key, value] : *this) {
if constexpr (IsBaseOf<NanBoxedValue, V>) {
if (value.is_cell())
roots.set(&const_cast<V&>(value).as_cell(), HeapRoot { .type = HeapRoot::Type::RootHashMap });
} else {
roots.set(value, HeapRoot { .type = HeapRoot::Type::RootHashMap });
}
}
}
};
template<typename K, typename V, typename KeyTraits = Traits<K>, typename ValueTraits = Traits<V>>
using OrderedRootHashMap = RootHashMap<K, V, KeyTraits, ValueTraits, true>;
}