summaryrefslogtreecommitdiff
path: root/Userland/Libraries/LibJS/Heap/MarkedVector.h
blob: 153de0aec433b1e54a31751e849a7141975c9e99 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
/*
 * Copyright (c) 2021, Andreas Kling <kling@serenityos.org>
 * Copyright (c) 2022, Linus Groh <linusg@serenityos.org>
 *
 * SPDX-License-Identifier: BSD-2-Clause
 */

#pragma once

#include <AK/HashTable.h>
#include <AK/IntrusiveList.h>
#include <AK/Vector.h>
#include <LibJS/Forward.h>
#include <LibJS/Heap/Cell.h>

namespace JS {

class MarkedVectorBase {
public:
    virtual void gather_roots(HashTable<Cell*>&) const = 0;

protected:
    explicit MarkedVectorBase(Heap&);
    ~MarkedVectorBase();

    MarkedVectorBase& operator=(MarkedVectorBase const&);

    Heap* m_heap { nullptr };
    IntrusiveListNode<MarkedVectorBase> m_list_node;

public:
    using List = IntrusiveList<&MarkedVectorBase::m_list_node>;
};

template<typename T, size_t inline_capacity>
class MarkedVector
    : public MarkedVectorBase
    , public Vector<T, inline_capacity> {

public:
    explicit MarkedVector(Heap& heap)
        : MarkedVectorBase(heap)
    {
    }

    virtual ~MarkedVector() = default;

    MarkedVector(MarkedVector const& other)
        : MarkedVectorBase(*other.m_heap)
        , Vector<T, inline_capacity>(other)
    {
    }

    MarkedVector(MarkedVector&& other)
        : MarkedVectorBase(*other.m_heap)
        , Vector<T, inline_capacity>(move(static_cast<Vector<T, inline_capacity>&>(other)))
    {
    }

    MarkedVector& operator=(MarkedVector const& other)
    {
        Vector<T, inline_capacity>::operator=(other);
        MarkedVectorBase::operator=(other);
        return *this;
    }

    virtual void gather_roots(HashTable<Cell*>& roots) const override
    {
        for (auto& value : *this) {
            if constexpr (IsSame<Value, T>) {
                if (value.is_cell())
                    roots.set(&const_cast<T&>(value).as_cell());
            } else {
                roots.set(value);
            }
        }
    };
};

}