1 /*
2 * Copyright (c) 2021 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_RUNTIME_MEM_REM_SET_INL_H_
17 #define PANDA_RUNTIME_MEM_REM_SET_INL_H_
18
19 #include "runtime/mem/rem_set.h"
20 #include "runtime/mem/region_space-inl.h"
21
22 namespace panda::mem {
23
24 template <typename LockConfigT>
RemSet(Region * region)25 RemSet<LockConfigT>::RemSet(Region *region) : region_(region)
26 {
27 allocator_ = region->GetInternalAllocator();
28 }
29
30 template <typename LockConfigT>
~RemSet()31 RemSet<LockConfigT>::~RemSet()
32 {
33 Clear();
34 }
35
36 template <typename LockConfigT>
AddRef(const void * from_field_addr)37 void RemSet<LockConfigT>::AddRef(const void *from_field_addr)
38 {
39 auto from_region = Region::AddrToRegion(from_field_addr);
40 auto card_ptr = GetCardPtr(from_field_addr);
41 auto list = GetCardList(from_region);
42 os::memory::LockHolder lock(rem_set_lock_);
43 if (list == nullptr) {
44 list = allocator_->New<CardList>();
45 // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
46 regions_[from_region] = list;
47 }
48 if (find(list->begin(), list->end(), card_ptr) == list->end()) {
49 list->push_back(card_ptr);
50 }
51 }
52
53 template <typename LockConfigT>
Clear()54 void RemSet<LockConfigT>::Clear()
55 {
56 os::memory::LockHolder lock(rem_set_lock_);
57 for (auto region_iter : regions_) {
58 auto list = region_iter.second;
59 allocator_->Delete(list);
60 }
61 regions_.clear();
62 }
63
64 template <typename LockConfigT>
GetCardList(Region * region)65 CardList *RemSet<LockConfigT>::GetCardList(Region *region)
66 {
67 os::memory::LockHolder lock(rem_set_lock_);
68 if (regions_.find(region) == regions_.end()) {
69 return nullptr;
70 }
71 // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
72 return regions_[region];
73 }
74
75 template <typename LockConfigT>
GetCardPtr(const void * addr)76 CardPtr RemSet<LockConfigT>::GetCardPtr(const void *addr)
77 {
78 return card_table_ != nullptr ? card_table_->GetCardPtr(ToUintPtr(addr)) : nullptr;
79 }
80
81 template <typename LockConfigT>
GetMemoryRange(CardPtr card)82 MemRange RemSet<LockConfigT>::GetMemoryRange(CardPtr card)
83 {
84 return card_table_->GetMemoryRange(card);
85 }
86
87 /* static */
88 template <typename LockConfigT>
AddRefWithAddr(const void * obj_addr,const void * value_addr)89 void RemSet<LockConfigT>::AddRefWithAddr(const void *obj_addr, const void *value_addr)
90 {
91 auto from_region = Region::AddrToRegion(obj_addr);
92 // The eden region must be included in the collection set in GC. So, we don't need add ref here.
93 if (from_region->IsEden()) {
94 return;
95 }
96 auto to_region = Region::AddrToRegion(value_addr);
97 to_region->GetRemSet()->AddRef(obj_addr);
98 }
99
100 /* static */
101 template <typename LockConfigT>
TraverseObjectToAddRef(const void * addr)102 void RemSet<LockConfigT>::TraverseObjectToAddRef(const void *addr)
103 {
104 auto traverse_object_visitor = [](ObjectHeader *from_object, ObjectHeader *object_to_traverse) {
105 AddRefWithAddr(from_object, object_to_traverse);
106 };
107 auto obj = static_cast<ObjectHeader *>(const_cast<void *>(addr));
108 GCStaticObjectHelpers::TraverseAllObjects(obj, traverse_object_visitor);
109 }
110
111 template <typename LockConfigT>
112 template <typename ObjectVisitor>
VisitMarkedCards(const ObjectVisitor & object_visitor)113 inline void RemSet<LockConfigT>::VisitMarkedCards(const ObjectVisitor &object_visitor)
114 {
115 os::memory::LockHolder lock(rem_set_lock_);
116 for (auto region_iter : regions_) {
117 auto *region = region_iter.first;
118 auto *card_list = region_iter.second;
119 for (auto card_ptr : *card_list) {
120 // visit live objects in old region
121 auto mem_range = GetMemoryRange(card_ptr);
122 region->GetLiveBitmap()->IterateOverMarkedChunkInRange(
123 ToVoidPtr(mem_range.GetStartAddress()), ToVoidPtr(mem_range.GetEndAddress()), object_visitor);
124 }
125 }
126 }
127
128 } // namespace panda::mem
129
130 #endif // PANDA_RUNTIME_MEM_REM_SET_INL_H_
131