• 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 PANDA_MEM_GC_G1_REM_SET_INL_H
17 #define PANDA_MEM_GC_G1_REM_SET_INL_H
18 
19 #include "runtime/mem/rem_set.h"
20 #include "runtime/mem/region_space-inl.h"
21 #include "runtime/mem/region_allocator.h"
22 
23 namespace panda::mem {
24 
25 template <typename LockConfigT>
RemSet(Region * region,CardTable * card_table)26 RemSet<LockConfigT>::RemSet(Region *region, CardTable *card_table)
27     : region_(region), allocator_(region->GetInternalAllocator()), card_table_(card_table)
28 {
29 }
30 
31 template <typename LockConfigT>
~RemSet()32 RemSet<LockConfigT>::~RemSet()
33 {
34     Clear();
35 }
36 
37 template <typename LockConfigT>
38 template <bool need_lock>
AddRef(const ObjectHeader * from_obj_addr)39 void RemSet<LockConfigT>::AddRef(const ObjectHeader *from_obj_addr)
40 {
41     ASSERT(from_obj_addr != nullptr);
42     auto from_region = ObjectToRegion(from_obj_addr);
43     ASSERT(from_region != nullptr);
44     auto card_ptr = GetCardPtr(from_obj_addr);
45     auto list = GetCardList<need_lock>(from_region);
46     os::memory::LockHolder<LockConfigT, need_lock> lock(rem_set_lock_);
47     if (list == nullptr) {
48         list = allocator_->New<CardList>();
49         // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
50         regions_[from_region] = list;
51     }
52     if (find(list->begin(), list->end(), card_ptr) == list->end()) {
53         list->push_back(card_ptr);
54     }
55 }
56 
57 template <typename LockConfigT>
Clear()58 void RemSet<LockConfigT>::Clear()
59 {
60     os::memory::LockHolder lock(rem_set_lock_);
61     for (auto region_iter : regions_) {
62         auto list = region_iter.second;
63         allocator_->Delete(list);
64     }
65     regions_.clear();
66     ref_regions_.clear();
67 }
68 
69 template <typename LockConfigT>
70 template <bool need_lock>
GetCardList(Region * region)71 CardList *RemSet<LockConfigT>::GetCardList(Region *region)
72 {
73     os::memory::LockHolder<LockConfigT, need_lock> lock(rem_set_lock_);
74     auto card_list = regions_.find(region);
75     if (card_list == regions_.end()) {
76         return nullptr;
77     }
78     return card_list->second;
79 }
80 
81 template <typename LockConfigT>
GetCardPtr(const void * addr)82 CardPtr RemSet<LockConfigT>::GetCardPtr(const void *addr)
83 {
84     return card_table_ != nullptr ? card_table_->GetCardPtr(ToUintPtr(addr)) : nullptr;
85 }
86 
87 template <typename LockConfigT>
GetMemoryRange(CardPtr card)88 MemRange RemSet<LockConfigT>::GetMemoryRange(CardPtr card)
89 {
90     return card_table_->GetMemoryRange(card);
91 }
92 
93 /* static */
94 template <typename LockConfigT>
95 template <bool need_lock>
InvalidateRegion(Region * invalid_region)96 void RemSet<LockConfigT>::InvalidateRegion(Region *invalid_region)
97 {
98     RemSet<> *invalid_remset = invalid_region->GetRemSet();
99     os::memory::LockHolder<LockConfigT, need_lock> lock(invalid_remset->rem_set_lock_);
100     for (Region *ref_reg : invalid_remset->ref_regions_) {
101         ref_reg->GetRemSet()->RemoveFromRegion<need_lock>(invalid_region);
102     }
103 
104     for (auto entry : invalid_remset->regions_) {
105         Region *from_region = entry.first;
106         from_region->GetRemSet()->RemoveRefRegion<need_lock>(invalid_region);
107     }
108 }
109 
110 /* static */
111 template <typename LockConfigT>
112 template <bool need_lock>
AddRefWithAddr(const ObjectHeader * obj_addr,const ObjectHeader * value_addr)113 void RemSet<LockConfigT>::AddRefWithAddr(const ObjectHeader *obj_addr, const ObjectHeader *value_addr)
114 {
115     auto *from_region = ObjectToRegion(obj_addr);
116     auto *to_region = ObjectToRegion(value_addr);
117     // TSAN thinks that we can have a data race here when we get region or getRemSet from region, because we don't have
118     // synchronization between these events. In reality it's impossible, because if we get write from/to region it
119     // should be created already by allocator in mutator thread, and only then writes happens.
120     TSAN_ANNOTATE_IGNORE_WRITES_BEGIN();
121     ASSERT(from_region != nullptr);
122     ASSERT(from_region->GetRemSet() != nullptr);
123     ASSERT(to_region != nullptr);
124     ASSERT(to_region->GetRemSet() != nullptr);
125 
126     to_region->GetRemSet()->AddRef<need_lock>(obj_addr);
127     from_region->GetRemSet()->AddRefRegion<need_lock>(to_region);
128     TSAN_ANNOTATE_IGNORE_WRITES_END();
129 }
130 
131 /* static */
132 template <typename LockConfigT>
TraverseObjectToAddRef(const void * addr)133 void RemSet<LockConfigT>::TraverseObjectToAddRef(const void *addr)
134 {
135     // TODO(xucheng) : need a special thread to add ref.
136     auto traverse_object_visitor = [](ObjectHeader *from_object, ObjectHeader *object_to_traverse) {
137         AddRefWithAddr(from_object, object_to_traverse);
138     };
139     auto obj = static_cast<ObjectHeader *>(const_cast<void *>(addr));
140     GCStaticObjectHelpers::TraverseAllObjects(obj, traverse_object_visitor);
141 }
142 
143 template <typename LockConfigT>
144 template <bool need_lock, typename ObjectVisitor>
VisitMarkedCards(const ObjectVisitor & object_visitor)145 inline void RemSet<LockConfigT>::VisitMarkedCards(const ObjectVisitor &object_visitor)
146 {
147     os::memory::LockHolder<LockConfigT, need_lock> lock(rem_set_lock_);
148     auto visitor = [&object_visitor](void *mem) { object_visitor(static_cast<ObjectHeader *>(mem)); };
149     for (auto region_iter : regions_) {
150         auto *region = region_iter.first;
151         auto *card_list = region_iter.second;
152         if (region == nullptr) {
153             // process humongous
154             continue;
155         } else {  // NOLINT(readability-else-after-return)
156             for (auto card_ptr : *card_list) {
157                 // visit live objects in old region
158                 auto mem_range = GetMemoryRange(card_ptr);
159                 region->GetLiveBitmap()->IterateOverMarkedChunkInRange(ToVoidPtr(mem_range.GetStartAddress()),
160                                                                        ToVoidPtr(mem_range.GetEndAddress()), visitor);
161             }
162         }
163     }
164 }
165 
166 template <typename LockConfigT>
167 template <bool need_lock, typename CardVisitor>
ProceedMarkedCards(const CardVisitor & card_visitor)168 inline void RemSet<LockConfigT>::ProceedMarkedCards(const CardVisitor &card_visitor)
169 {
170     os::memory::LockHolder<LockConfigT, need_lock> lock(rem_set_lock_);
171     for (auto region_iter : regions_) {
172         auto *region = region_iter.first;
173         auto *card_list = region_iter.second;
174         if (region == nullptr) {
175             // process humongous
176             continue;
177         } else {  // NOLINT(readability-else-after-return)
178             for (auto card_ptr : *card_list) {
179                 // visit live objects in old region
180                 card_visitor(card_ptr, region);
181             }
182         }
183     }
184 }
185 
186 template <typename LockConfigT>
187 template <bool need_lock>
GetRefRegions()188 PandaUnorderedSet<Region *> *RemSet<LockConfigT>::GetRefRegions()
189 {
190     os::memory::LockHolder lock(rem_set_lock_);
191     return &ref_regions_;
192 }
193 
194 template <typename LockConfigT>
195 template <bool need_lock>
AddRefRegion(Region * region)196 void RemSet<LockConfigT>::AddRefRegion(Region *region)
197 {
198     os::memory::LockHolder<LockConfigT, need_lock> lock(rem_set_lock_);
199     ref_regions_.insert(region);
200 }
201 
202 template <typename LockConfigT>
203 template <bool need_lock>
RemoveFromRegion(Region * region)204 void RemSet<LockConfigT>::RemoveFromRegion(Region *region)
205 {
206     os::memory::LockHolder<LockConfigT, need_lock> lock(rem_set_lock_);
207     auto it = regions_.find(region);
208     if (it == regions_.end()) {
209         return;
210     }
211     allocator_->Delete(it->second);
212     regions_.erase(it);
213 }
214 
215 template <typename LockConfigT>
216 template <bool need_lock>
RemoveRefRegion(Region * region)217 void RemSet<LockConfigT>::RemoveRefRegion(Region *region)
218 {
219     os::memory::LockHolder<LockConfigT, need_lock> lock(rem_set_lock_);
220     ref_regions_.erase(region);
221 }
222 
223 template <typename LockConfigT>
Dump(std::ostream & out)224 void RemSet<LockConfigT>::Dump(std::ostream &out)
225 {
226     os::memory::LockHolder lock(rem_set_lock_);
227     out << *region_ << ": From";
228     for (auto entry : regions_) {
229         CardList *cards = entry.second;
230         if (cards != nullptr) {
231             for (CardPtr card : *cards) {
232                 if (entry.first->HasFlag(RegionFlag::IS_LARGE_OBJECT)) {
233                     out << " H-";
234                 } else if (entry.first->HasFlag(RegionFlag::IS_NONMOVABLE)) {
235                     out << " NM-";
236                 } else if (entry.first->HasFlag(RegionFlag::IS_OLD)) {
237                     out << " T-";
238                 } else {
239                     out << " Y-";
240                 }
241                 out << std::hex << "[" << card_table_->GetCardStartAddress(card) << "-"
242                     << card_table_->GetCardEndAddress(card) << "]";
243             }
244         }
245     }
246     out << " To:";
247     for (auto reg : ref_regions_) {
248         out << " " << *reg;
249     }
250     out << std::dec;
251 }
252 
253 }  // namespace panda::mem
254 
255 #endif  // PANDA_MEM_GC_G1_REM_SET_INL_H
256