• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**
2  * Copyright (c) 2021-2022 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  * http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #ifndef ACCOUNTING_CARD_TABLE_H
17 #define ACCOUNTING_CARD_TABLE_H
18 
19 #include <atomic>
20 #include <cstddef>
21 #include <cstdint>
22 #include <type_traits>
23 
24 #include "runtime/include/mem/panda_containers.h"
25 
26 namespace panda::mem {
27 
28 template <typename PtrType>
29 class CardPtrIterator {
30 public:
31     using reference = PtrType &;
32     using const_reference = typename std::add_const<PtrType &>::type;
33     using pointer = PtrType *;
34 
35     // NOLINTNEXTLINE(readability-identifier-naming)
CardPtrIterator(PtrType c)36     explicit CardPtrIterator(PtrType c) : card_(c) {}
37 
38     CardPtrIterator &operator++()
39     {
40         card_ += 1;
41         return *this;
42     }
43 
44     // NOLINTNEXTLINE(cert-dcl21-cpp)
45     CardPtrIterator operator++(int)
46     {
47         CardPtrIterator retval = *this;
48         ++(*this);
49         return retval;
50     }
51 
52     bool operator==(CardPtrIterator other) const
53     {
54         return card_ == other.card_;
55     }
56 
57     bool operator!=(CardPtrIterator other) const
58     {
59         return !(*this == other);
60     }
61 
62     const_reference operator*() const
63     {
64         return card_;
65     }
66 
67     reference operator*()
68     {
69         return card_;
70     }
71 
72     virtual ~CardPtrIterator() = default;
73 
74     DEFAULT_COPY_SEMANTIC(CardPtrIterator);
75     NO_MOVE_SEMANTIC(CardPtrIterator);
76 
77 private:
78     // NOLINTNEXTLINE(readability-identifier-naming)
79     PtrType card_;
80 };
81 
82 enum CardTableProcessedFlag : uint32_t {
83     VISIT_MARKED = 1U,           // visit marked cards
84     VISIT_PROCESSED = 1U << 1U,  // visit parocessed cards
85     SET_PROCESSED = 1U << 2U,    // set the visited cards processed
86 };
87 
88 class CardTable {
89 public:
90     class Card;
91     using CardPtr = Card *;
92     using CardAddress = uintptr_t;
93     using Iterator = CardPtrIterator<CardPtr>;
94     using ConstIterator = CardPtrIterator<const CardPtr>;
95 
96     explicit CardTable(InternalAllocatorPtr internal_allocator, uintptr_t min_address, size_t size);
97     ~CardTable();
98     CardTable(const CardTable &other) = delete;
99     CardTable &operator=(const CardTable &other) = delete;
100     CardTable(CardTable &&other) = delete;
101     CardTable &operator=(CardTable &&other) = delete;
102 
103     void Initialize();
104     bool IsMarked(uintptr_t addr) const;  // returns true if the card(for the addr) state is marked
105     void MarkCard(uintptr_t addr);        // set card state to the marked
106     bool IsClear(uintptr_t addr) const;   // returns true if the card(for the addr) state is clear
107     void ClearCard(uintptr_t addr);       // set card state to the cleared
108     void ClearAll();                      // set card state to the cleared for the all cards
109     void ClearCardRange(uintptr_t begin_addr, uintptr_t end_addr);
GetCardSize()110     static constexpr uint32_t GetCardSize()
111     {
112         return CARD_SIZE;
113     }
GetCardsCount()114     size_t GetCardsCount() const
115     {
116         return cards_count_;
117     }
118 
119     uintptr_t GetCardStartAddress(CardPtr card) const;  // returns address of the first byte in the card
120     uintptr_t GetCardEndAddress(CardPtr card) const;    // returns address of the last byte in the card
121     MemRange GetMemoryRange(CardPtr card) const;        // returns memory range for the card
122 
123     template <typename CardVisitor>
124     void VisitMarked(CardVisitor card_visitor, uint32_t processed_flag);
125 
126     template <typename CardVisitor>
127     void VisitMarkedCompact(CardVisitor card_visitor);
128 
129     // NOLINTNEXTLINE(readability-identifier-naming)
begin()130     Iterator begin()
131     {
132         return Iterator(cards_);
133     }
134 
135     // NOLINTNEXTLINE(readability-identifier-naming)
end()136     Iterator end()
137     {
138         return Iterator(cards_ + cards_count_);
139     }
140 
141     // NOLINTNEXTLINE(readability-identifier-naming)
begin()142     ConstIterator begin() const
143     {
144         return ConstIterator(cards_);
145     }
146 
147     // NOLINTNEXTLINE(readability-identifier-naming)
end()148     ConstIterator end() const
149     {
150         return ConstIterator(cards_ + cards_count_);
151     }
152 
GetCardBits()153     static constexpr uint8_t GetCardBits()
154     {
155         return LOG2_CARD_SIZE;
156     }
157 
GetCardDirtyValue()158     static constexpr uint8_t GetCardDirtyValue()
159     {
160         return DIRTY_CARD;
161     }
162 
163     class Card {
164     public:
165         Card() = default;
166         explicit Card(uint8_t val);
167 
168         bool IsMarked() const;
169         void Mark();
170         bool IsClear() const;
171         void Clear();
172         bool IsProcessed() const;
173         void SetProcessed();
174         bool IsYoung() const;
175         void SetYoung();
176 
177         ~Card() = default;
178 
179         NO_COPY_SEMANTIC(Card);
180         NO_MOVE_SEMANTIC(Card);
181 
182     private:
183         uint8_t GetCard() const;
184         void SetCard(uint8_t new_val);
185 
186         static constexpr uint8_t YOUNG_VALUE = 3;
187         static constexpr uint8_t PROCESSED_VALUE = 2;
188         static constexpr uint8_t MARKED_VALUE = 1;
189         static constexpr uint8_t CLEAR_VALUE = 0;
190 
191         std::atomic_uint8_t value_ = CLEAR_VALUE;
192     };
193 
194     CardPtr GetCardPtr(uintptr_t addr) const;  // returns card address for the addr
195 
GetMinAddress()196     ALWAYS_INLINE uintptr_t GetMinAddress() const
197     {
198         return min_address_;
199     }
200 
201     void MarkCardsAsYoung(const MemRange &mem_range);
202 
203 private:
204     void ClearCards(CardPtr start, size_t card_count);
205     size_t GetSize() const;  // returns size of card table array
206     inline void FillRanges(PandaVector<MemRange> *ranges, const Card *start_card, const Card *end_card);
207 
208     static constexpr uint8_t LOG2_CARD_SIZE = 12;
209     static constexpr uint32_t CARD_SIZE = 1U << LOG2_CARD_SIZE;
210     static constexpr uint8_t DIRTY_CARD = 1U;
211 
212     CardPtr cards_ {nullptr};
213     uintptr_t min_address_ {0};
214     size_t cards_count_ {0};
215     InternalAllocatorPtr internal_allocator_ {nullptr};
216 };
217 
218 using CardVisitor = std::function<void(CardTable::CardPtr)>;
219 
220 }  // namespace panda::mem
221 
222 #endif  // ACCOUNTING_CARD_TABLE_H
223