• 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 ConstReference = 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     ConstReference 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 internalAllocator, uintptr_t minAddress, 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 beginAddr, uintptr_t endAddr);
GetCardSize()110     static constexpr uint32_t GetCardSize()
111     {
112         return CARD_SIZE;
113     }
GetCardsCount()114     size_t GetCardsCount() const
115     {
116         return cardsCount_;
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 cardVisitor, uint32_t processedFlag);
125 
126     template <typename CardVisitor>
127     void VisitMarkedCompact(CardVisitor cardVisitor);
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_ + cardsCount_);
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_ + cardsCount_);
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         uint8_t GetCard() const;
177         void SetCard(uint8_t newVal);
178 
GetValueOffset()179         static constexpr uint32_t GetValueOffset()
180         {
181             return MEMBER_OFFSET(Card, value_);
182         }
183 
GetClearValue()184         static constexpr auto GetClearValue()
185         {
186             return CLEAR_VALUE;
187         }
188 
GetMarkedValue()189         static constexpr auto GetMarkedValue()
190         {
191             return MARKED_VALUE;
192         }
193 
194         ~Card() = default;
195 
196         NO_COPY_SEMANTIC(Card);
197         NO_MOVE_SEMANTIC(Card);
198 
199     private:
200         static constexpr uint8_t YOUNG_VALUE = 3;
201         static constexpr uint8_t PROCESSED_VALUE = 2;
202         static constexpr uint8_t MARKED_VALUE = 1;
203         static constexpr uint8_t CLEAR_VALUE = 0;
204 
205         std::atomic_uint8_t value_ = CLEAR_VALUE;
206     };
207 
208     CardPtr GetCardPtr(uintptr_t addr) const;  // returns card address for the addr
209 
GetMinAddress()210     ALWAYS_INLINE uintptr_t GetMinAddress() const
211     {
212         return minAddress_;
213     }
214 
215     void MarkCardsAsYoung(const MemRange &memRange);
216 
217 private:
218     void ClearCards(CardPtr start, size_t cardCount);
219     size_t GetSize() const;  // returns size of card table array
220     inline void FillRanges(PandaVector<MemRange> *ranges, const Card *startCard, const Card *endCard);
221 
222     static constexpr uint8_t LOG2_CARD_SIZE = 12;
223     static constexpr uint32_t CARD_SIZE = 1U << LOG2_CARD_SIZE;
224     static constexpr uint8_t DIRTY_CARD = 1U;
225 
226     CardPtr cards_ {nullptr};
227     uintptr_t minAddress_ {0};
228     size_t cardsCount_ {0};
229     InternalAllocatorPtr internalAllocator_ {nullptr};
230 };
231 
232 using CardVisitor = std::function<void(CardTable::CardPtr)>;
233 
234 }  // namespace panda::mem
235 
236 #endif  // ACCOUNTING_CARD_TABLE_H
237