• 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.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 internal_allocator,uintptr_t min_address,size_t size)24 CardTable::CardTable(InternalAllocatorPtr internal_allocator, uintptr_t min_address, size_t size)
25     : min_address_(min_address),
26       cards_count_((size / CARD_SIZE) + (size % CARD_SIZE != 0 ? 1 : 0)),
27       internal_allocator_(internal_allocator)
28 {
29 }
30 
~CardTable()31 CardTable::~CardTable()
32 {
33     ASSERT(cards_ != nullptr);
34     internal_allocator_->Free(cards_);
35 }
36 
Initialize()37 void CardTable::Initialize()
38 {
39     trace::ScopedTrace scoped_trace(__PRETTY_FUNCTION__);
40     if (cards_ != nullptr) {
41         LOG(FATAL, GC) << "try to initialize already initialized CardTable";
42     }
43     cards_ = static_cast<CardPtr>(internal_allocator_->Alloc(cards_count_));
44     ClearCards(cards_, cards_count_);
45     ASSERT(cards_ != nullptr);
46 }
47 
ClearCards(CardPtr start,size_t card_count)48 void CardTable::ClearCards(CardPtr start, size_t card_count)
49 {
50     // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
51     CardPtr end = start + card_count;
52     // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
53     for (auto *cur_card = start; cur_card < end; ++cur_card) {
54         cur_card->Clear();
55     }
56 }
57 
IsMarked(uintptr_t addr) const58 bool CardTable::IsMarked(uintptr_t addr) const
59 {
60     CardPtr card = GetCardPtr(addr);
61     return card->IsMarked();
62 }
63 
MarkCard(uintptr_t addr)64 void CardTable::MarkCard(uintptr_t addr)
65 {
66     CardPtr card = GetCardPtr(addr);
67     card->Mark();
68 }
69 
IsClear(uintptr_t addr) const70 bool CardTable::IsClear(uintptr_t addr) const
71 {
72     CardPtr card = GetCardPtr(addr);
73     return card->IsClear();
74 }
75 
ClearCard(uintptr_t addr)76 void CardTable::ClearCard(uintptr_t addr)
77 {
78     CardPtr card = GetCardPtr(addr);
79     card->Clear();
80 }
81 
ClearAll()82 void CardTable::ClearAll()
83 {
84     ClearCards(cards_, cards_count_);
85 }
86 
ClearCardRange(uintptr_t begin_addr,uintptr_t end_addr)87 void CardTable::ClearCardRange(uintptr_t begin_addr, uintptr_t end_addr)
88 {
89     ASSERT((begin_addr - min_address_) % CARD_SIZE == 0);
90     size_t cards_count = (end_addr - begin_addr) / CARD_SIZE;
91     CardPtr start = GetCardPtr(begin_addr);
92     ClearCards(start, cards_count);
93 }
94 
GetCardStartAddress(CardPtr card) const95 uintptr_t CardTable::GetCardStartAddress(CardPtr card) const
96 {
97     return min_address_ + (ToUintPtr(card) - ToUintPtr(cards_)) * CARD_SIZE;
98 }
99 
GetCardEndAddress(CardPtr card) const100 uintptr_t CardTable::GetCardEndAddress(CardPtr card) const
101 {
102     return min_address_ + (ToUintPtr(card + 1) - ToUintPtr(cards_)) * CARD_SIZE - 1;
103 }
104 
GetMemoryRange(CardPtr card) const105 MemRange CardTable::GetMemoryRange(CardPtr card) const
106 {
107     return MemRange(GetCardStartAddress(card), GetCardEndAddress(card));
108 }
109 
Card(uint8_t val)110 CardTable::Card::Card(uint8_t val)
111 {
112     SetCard(val);
113 }
114 
IsMarked() const115 bool CardTable::Card::IsMarked() const
116 {
117     return GetCard() == MARKED_VALUE;
118 }
119 
Mark()120 void CardTable::Card::Mark()
121 {
122     SetCard(MARKED_VALUE);
123 }
124 
IsClear() const125 bool CardTable::Card::IsClear() const
126 {
127     return GetCard() == CLEAR_VALUE;
128 }
129 
Clear()130 void CardTable::Card::Clear()
131 {
132     SetCard(CLEAR_VALUE);
133 }
134 
IsProcessed() const135 bool CardTable::Card::IsProcessed() const
136 {
137     return GetCard() == PROCESSED_VALUE;
138 }
139 
SetProcessed()140 void CardTable::Card::SetProcessed()
141 {
142     SetCard(PROCESSED_VALUE);
143 }
144 
IsYoung() const145 bool CardTable::Card::IsYoung() const
146 {
147     return GetCard() == YOUNG_VALUE;
148 }
149 
SetYoung()150 void CardTable::Card::SetYoung()
151 {
152     SetCard(YOUNG_VALUE);
153 }
154 
GetCard() const155 uint8_t CardTable::Card::GetCard() const
156 {
157     // Atomic with relaxed order reason: data race with value_ with no synchronization or ordering constraints imposed
158     // on other reads or writes
159     return value_.load(std::memory_order_relaxed);
160 }
161 
SetCard(uint8_t new_val)162 void CardTable::Card::SetCard(uint8_t new_val)
163 {
164     // Atomic with relaxed order reason: data race with value_ with no synchronization or ordering constraints imposed
165     // on other reads or writes
166     value_.store(new_val, std::memory_order_relaxed);
167 }
168 
GetCardPtr(uintptr_t addr) const169 CardTable::CardPtr CardTable::GetCardPtr(uintptr_t addr) const
170 {
171     ASSERT(addr >= min_address_);
172     ASSERT(addr < min_address_ + cards_count_ * CARD_SIZE);
173     auto card = static_cast<CardPtr>(ToVoidPtr(ToUintPtr(cards_) + ((addr - min_address_) >> LOG2_CARD_SIZE)));
174     return card;
175 }
176 
MarkCardsAsYoung(const MemRange & mem_range)177 void CardTable::MarkCardsAsYoung(const MemRange &mem_range)
178 {
179     CardPtrIterator cur_card = CardPtrIterator(GetCardPtr(mem_range.GetStartAddress()));
180     auto end_card = CardPtrIterator(GetCardPtr(mem_range.GetEndAddress() - 1));
181     while (cur_card != end_card) {
182         (*cur_card)->SetYoung();
183         ++cur_card;
184     }
185     (*cur_card)->SetYoung();
186 }
187 }  // namespace panda::mem
188