• 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()26 RemSet<LockConfigT>::~RemSet()
27 {
28     Clear();
29 }
30 
31 template <typename LockConfigT>
32 template <bool NEED_LOCK>
AddRef(const ObjectHeader * fromObjAddr,size_t offset)33 void RemSet<LockConfigT>::AddRef(const ObjectHeader *fromObjAddr, size_t offset)
34 {
35     ASSERT(fromObjAddr != nullptr);
36     auto ref = ToUintPtr(fromObjAddr) + offset;
37     auto bitmapBeginAddr = ref & ~DEFAULT_REGION_MASK;
38     os::memory::LockHolder<LockConfigT, NEED_LOCK> lock(remSetLock_);
39     // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
40     bitmaps_[bitmapBeginAddr].Set(GetIdxInBitmap(ref, bitmapBeginAddr));
41 }
42 
43 template <typename LockConfigT>
Clear()44 void RemSet<LockConfigT>::Clear()
45 {
46     os::memory::LockHolder lock(remSetLock_);
47     bitmaps_.clear();
48     refRegions_.clear();
49 }
50 
51 /* static */
52 template <typename LockConfigT>
53 template <bool NEED_LOCK>
InvalidateRegion(Region * invalidRegion)54 void RemSet<LockConfigT>::InvalidateRegion(Region *invalidRegion)
55 {
56     RemSet<> *invalidRemset = invalidRegion->GetRemSet();
57     os::memory::LockHolder<LockConfigT, NEED_LOCK> lock(invalidRemset->remSetLock_);
58 
59     for (Region *refReg : invalidRemset->refRegions_) {
60         refReg->GetRemSet()->RemoveFromRegion<NEED_LOCK>(invalidRegion);
61     }
62 
63     for (auto entry : invalidRemset->bitmaps_) {
64         auto bitmapBeginAddr = entry.first;
65         auto *fromRegion = AddrToRegion(ToVoidPtr(bitmapBeginAddr));
66         fromRegion->GetRemSet()->RemoveRefRegion<NEED_LOCK>(invalidRegion);
67     }
68 }
69 
70 /* static */
71 template <typename LockConfigT>
72 template <bool NEED_LOCK>
InvalidateRefsFromRegion(Region * invalidRegion)73 void RemSet<LockConfigT>::InvalidateRefsFromRegion(Region *invalidRegion)
74 {
75     RemSet<> *invalidRemset = invalidRegion->GetRemSet();
76     os::memory::LockHolder<LockConfigT, NEED_LOCK> lock(invalidRemset->remSetLock_);
77     for (Region *refReg : invalidRemset->refRegions_) {
78         refReg->GetRemSet()->RemoveFromRegion<NEED_LOCK>(invalidRegion);
79     }
80     invalidRemset->refRegions_.clear();
81 }
82 
83 /* static */
84 template <typename LockConfigT>
85 template <bool NEED_LOCK>
AddRefWithAddr(const ObjectHeader * objAddr,size_t offset,const ObjectHeader * valueAddr)86 void RemSet<LockConfigT>::AddRefWithAddr(const ObjectHeader *objAddr, size_t offset, const ObjectHeader *valueAddr)
87 {
88     auto *fromRegion = ObjectToRegion(objAddr);
89     auto *toRegion = ObjectToRegion(valueAddr);
90     // TSAN thinks that we can have a data race here when we get region or getRemSet from region, because we don't have
91     // synchronization between these events. In reality it's impossible, because if we get write from/to region it
92     // should be created already by allocator in mutator thread, and only then writes happens.
93     TSAN_ANNOTATE_IGNORE_WRITES_BEGIN();
94     ASSERT(fromRegion != nullptr);
95     ASSERT(fromRegion->GetRemSet() != nullptr);
96     ASSERT(toRegion != nullptr);
97     ASSERT_PRINT(toRegion->GetRemSet() != nullptr,
98                  "region " << toRegion << ", obj " << objAddr << ", value " << valueAddr);
99 
100     toRegion->GetRemSet()->AddRef<NEED_LOCK>(objAddr, offset);
101     fromRegion->GetRemSet()->AddRefRegion<NEED_LOCK>(toRegion);
102     TSAN_ANNOTATE_IGNORE_WRITES_END();
103 }
104 
105 template <typename LockConfigT>
106 template <typename RegionPred, typename MemVisitor>
Iterate(const RegionPred & regionPred,const MemVisitor & visitor)107 inline void RemSet<LockConfigT>::Iterate(const RegionPred &regionPred, const MemVisitor &visitor)
108 {
109     for (auto &[bitmap_begin_addr, bitmap] : bitmaps_) {
110         auto *region = AddrToRegion(ToVoidPtr(bitmap_begin_addr));
111         if (regionPred(region)) {
112             MemRange bitmapRange(bitmap_begin_addr, bitmap_begin_addr + DEFAULT_REGION_SIZE);
113             bitmap.Iterate(bitmapRange, [region, visitor](const MemRange &range) { visitor(region, range); });
114         }
115     }
116 }
117 
118 template <typename LockConfigT>
119 template <typename Visitor>
IterateOverObjects(const Visitor & visitor)120 inline void RemSet<LockConfigT>::IterateOverObjects(const Visitor &visitor)
121 {
122     auto regionPred = []([[maybe_unused]] Region *region) { return true; };
123     Iterate(regionPred, [visitor](Region *region, const MemRange &range) {
124         region->GetLiveBitmap()->IterateOverMarkedChunkInRange(
125             ToVoidPtr(range.GetStartAddress()), ToVoidPtr(range.GetEndAddress()),
126             [visitor](void *mem) { visitor(static_cast<ObjectHeader *>(mem)); });
127     });
128 }
129 
130 template <typename LockConfigT>
131 template <bool NEED_LOCK>
GetRefRegions()132 PandaUnorderedSet<Region *> *RemSet<LockConfigT>::GetRefRegions()
133 {
134     os::memory::LockHolder lock(remSetLock_);
135     return &refRegions_;
136 }
137 
138 template <typename LockConfigT>
139 template <bool NEED_LOCK>
AddRefRegion(Region * region)140 void RemSet<LockConfigT>::AddRefRegion(Region *region)
141 {
142     os::memory::LockHolder<LockConfigT, NEED_LOCK> lock(remSetLock_);
143     refRegions_.insert(region);
144 }
145 
146 template <typename LockConfigT>
147 template <bool NEED_LOCK>
RemoveFromRegion(Region * region)148 void RemSet<LockConfigT>::RemoveFromRegion(Region *region)
149 {
150     os::memory::LockHolder<LockConfigT, NEED_LOCK> lock(remSetLock_);
151     for (auto bitmapBeginAddr = ToUintPtr(region); bitmapBeginAddr < region->End();
152          bitmapBeginAddr += DEFAULT_REGION_SIZE) {
153         bitmaps_.erase(bitmapBeginAddr);
154     }
155 }
156 
157 template <typename LockConfigT>
158 template <bool NEED_LOCK>
RemoveRefRegion(Region * region)159 void RemSet<LockConfigT>::RemoveRefRegion(Region *region)
160 {
161     os::memory::LockHolder<LockConfigT, NEED_LOCK> lock(remSetLock_);
162     refRegions_.erase(region);
163 }
164 
165 template <typename LockConfigT>
GetIdxInBitmap(uintptr_t addr,uintptr_t bitmapBeginAddr)166 size_t RemSet<LockConfigT>::GetIdxInBitmap(uintptr_t addr, uintptr_t bitmapBeginAddr)
167 {
168     size_t memSize = DEFAULT_REGION_SIZE / Bitmap::GetNumBits();
169     ASSERT(bitmapBeginAddr <= addr && addr < bitmapBeginAddr + DEFAULT_REGION_SIZE);
170     return (addr - bitmapBeginAddr) / memSize;
171 }
172 
173 template <typename LockConfigT>
Dump(std::ostream & out)174 void RemSet<LockConfigT>::Dump(std::ostream &out)
175 {
176     os::memory::LockHolder lock(remSetLock_);
177     auto pred = []([[maybe_unused]] Region *region) { return true; };
178     Iterate(pred, [&out](Region *region, const MemRange &range) {
179         if (region->HasFlag(RegionFlag::IS_LARGE_OBJECT)) {
180             out << " H";
181         } else if (region->HasFlag(RegionFlag::IS_NONMOVABLE)) {
182             out << " NM";
183         } else if (region->HasFlag(RegionFlag::IS_OLD)) {
184             out << " T";
185         } else {
186             out << " Y";
187         }
188         out << "[" << ToVoidPtr(range.GetStartAddress()) << "-" << ToVoidPtr(range.GetEndAddress()) << "]";
189     });
190     out << " To:";
191     for (auto reg : refRegions_) {
192         out << " " << *reg;
193     }
194     out << std::dec;
195 }
196 
197 }  // namespace panda::mem
198 
199 #endif  // PANDA_MEM_GC_G1_REM_SET_INL_H
200