• 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 #include "runtime/mem/gc/card_table-inl.h"
17 
18 #include "trace/trace.h"
19 #include "libpandabase/mem/mem.h"
20 #include "libpandabase/utils/logger.h"
21 
22 namespace panda::mem {
23 
CardTable(InternalAllocatorPtr internalAllocator,uintptr_t minAddress,size_t size)24 CardTable::CardTable(InternalAllocatorPtr internalAllocator, uintptr_t minAddress, size_t size)
25     : minAddress_(minAddress),
26       cardsCount_((size / CARD_SIZE) + (size % CARD_SIZE != 0 ? 1 : 0)),
27       internalAllocator_(internalAllocator)
28 {
29     /**
30      * We use this assumption in compiler's post barriers in case of store pair.
31      *
32      * The idea is to check whether two sequential slots of an object/array being
33      * written to belong to the same card or not.
34      *
35      * The only situation when they belong to different cards is when the second
36      * slot of the store is placed at the beggining of a card.
37      *
38      * This could be checked by `(2nd_store_ptr - min_address) % card_size == 0`
39      * condition, but if `min_address` is aligned at `card_size`, it may be simplified
40      * to `2nd_store_ptr % card_size == 0`.
41      */
42     ASSERT(IsAligned<GetCardSize()>(minAddress));
43 }
44 
~CardTable()45 CardTable::~CardTable()
46 {
47     ASSERT(cards_ != nullptr);
48     internalAllocator_->Free(cards_);
49 }
50 
Initialize()51 void CardTable::Initialize()
52 {
53     trace::ScopedTrace scopedTrace(__PRETTY_FUNCTION__);
54     if (cards_ != nullptr) {
55         LOG(FATAL, GC) << "try to initialize already initialized CardTable";
56     }
57     cards_ = static_cast<CardPtr>(internalAllocator_->Alloc(cardsCount_));
58     ClearCards(cards_, cardsCount_);
59     ASSERT(cards_ != nullptr);
60 }
61 
ClearCards(CardPtr start,size_t cardCount)62 void CardTable::ClearCards(CardPtr start, size_t cardCount)
63 {
64     // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
65     CardPtr end = start + cardCount;
66     // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
67     for (auto *curCard = start; curCard < end; ++curCard) {
68         curCard->Clear();
69     }
70 }
71 
IsMarked(uintptr_t addr) const72 bool CardTable::IsMarked(uintptr_t addr) const
73 {
74     CardPtr card = GetCardPtr(addr);
75     return card->IsMarked();
76 }
77 
MarkCard(uintptr_t addr)78 void CardTable::MarkCard(uintptr_t addr)
79 {
80     CardPtr card = GetCardPtr(addr);
81     card->Mark();
82 }
83 
IsClear(uintptr_t addr) const84 bool CardTable::IsClear(uintptr_t addr) const
85 {
86     CardPtr card = GetCardPtr(addr);
87     return card->IsClear();
88 }
89 
ClearCard(uintptr_t addr)90 void CardTable::ClearCard(uintptr_t addr)
91 {
92     CardPtr card = GetCardPtr(addr);
93     card->Clear();
94 }
95 
ClearAll()96 void CardTable::ClearAll()
97 {
98     ClearCards(cards_, cardsCount_);
99 }
100 
ClearCardRange(uintptr_t beginAddr,uintptr_t endAddr)101 void CardTable::ClearCardRange(uintptr_t beginAddr, uintptr_t endAddr)
102 {
103     ASSERT((beginAddr - minAddress_) % CARD_SIZE == 0);
104     size_t cardsCount = (endAddr - beginAddr) / CARD_SIZE;
105     CardPtr start = GetCardPtr(beginAddr);
106     ClearCards(start, cardsCount);
107 }
108 
GetCardStartAddress(CardPtr card) const109 uintptr_t CardTable::GetCardStartAddress(CardPtr card) const
110 {
111     return minAddress_ + (ToUintPtr(card) - ToUintPtr(cards_)) * CARD_SIZE;
112 }
113 
GetCardEndAddress(CardPtr card) const114 uintptr_t CardTable::GetCardEndAddress(CardPtr card) const
115 {
116     return minAddress_ + (ToUintPtr(card + 1) - ToUintPtr(cards_)) * CARD_SIZE - 1;
117 }
118 
GetMemoryRange(CardPtr card) const119 MemRange CardTable::GetMemoryRange(CardPtr card) const
120 {
121     return MemRange(GetCardStartAddress(card), GetCardEndAddress(card));
122 }
123 
Card(uint8_t val)124 CardTable::Card::Card(uint8_t val)
125 {
126     SetCard(val);
127 }
128 
IsMarked() const129 bool CardTable::Card::IsMarked() const
130 {
131     return GetCard() == MARKED_VALUE;
132 }
133 
Mark()134 void CardTable::Card::Mark()
135 {
136     SetCard(MARKED_VALUE);
137 }
138 
IsClear() const139 bool CardTable::Card::IsClear() const
140 {
141     return GetCard() == CLEAR_VALUE;
142 }
143 
Clear()144 void CardTable::Card::Clear()
145 {
146     SetCard(CLEAR_VALUE);
147 }
148 
IsProcessed() const149 bool CardTable::Card::IsProcessed() const
150 {
151     return GetCard() == PROCESSED_VALUE;
152 }
153 
SetProcessed()154 void CardTable::Card::SetProcessed()
155 {
156     SetCard(PROCESSED_VALUE);
157 }
158 
IsYoung() const159 bool CardTable::Card::IsYoung() const
160 {
161     return GetCard() == YOUNG_VALUE;
162 }
163 
SetYoung()164 void CardTable::Card::SetYoung()
165 {
166     SetCard(YOUNG_VALUE);
167 }
168 
GetCardPtr(uintptr_t addr) const169 CardTable::CardPtr CardTable::GetCardPtr(uintptr_t addr) const
170 {
171     ASSERT(addr >= minAddress_);
172     ASSERT(addr < minAddress_ + cardsCount_ * CARD_SIZE);
173     auto card = static_cast<CardPtr>(ToVoidPtr(ToUintPtr(cards_) + ((addr - minAddress_) >> LOG2_CARD_SIZE)));
174     return card;
175 }
176 
MarkCardsAsYoung(const MemRange & memRange)177 void CardTable::MarkCardsAsYoung(const MemRange &memRange)
178 {
179     CardPtrIterator curCard = CardPtrIterator(GetCardPtr(memRange.GetStartAddress()));
180     auto endCard = CardPtrIterator(GetCardPtr(memRange.GetEndAddress() - 1));
181     while (curCard != endCard) {
182         (*curCard)->SetYoung();
183         ++curCard;
184     }
185     (*curCard)->SetYoung();
186 }
187 }  // namespace panda::mem
188