xref: /aosp_15_r20/art/runtime/gc/collector/mark_compact-inl.h (revision 795d594fd825385562da6b089ea9b2033f3abf5a)
1*795d594fSAndroid Build Coastguard Worker /*
2*795d594fSAndroid Build Coastguard Worker  * Copyright 2021 The Android Open Source Project
3*795d594fSAndroid Build Coastguard Worker  *
4*795d594fSAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*795d594fSAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*795d594fSAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*795d594fSAndroid Build Coastguard Worker  *
8*795d594fSAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*795d594fSAndroid Build Coastguard Worker  *
10*795d594fSAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*795d594fSAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*795d594fSAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*795d594fSAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*795d594fSAndroid Build Coastguard Worker  * limitations under the License.
15*795d594fSAndroid Build Coastguard Worker  */
16*795d594fSAndroid Build Coastguard Worker 
17*795d594fSAndroid Build Coastguard Worker #ifndef ART_RUNTIME_GC_COLLECTOR_MARK_COMPACT_INL_H_
18*795d594fSAndroid Build Coastguard Worker #define ART_RUNTIME_GC_COLLECTOR_MARK_COMPACT_INL_H_
19*795d594fSAndroid Build Coastguard Worker 
20*795d594fSAndroid Build Coastguard Worker #include "gc/space/bump_pointer_space.h"
21*795d594fSAndroid Build Coastguard Worker #include "mark_compact.h"
22*795d594fSAndroid Build Coastguard Worker #include "mirror/object-inl.h"
23*795d594fSAndroid Build Coastguard Worker #include "thread-inl.h"
24*795d594fSAndroid Build Coastguard Worker 
25*795d594fSAndroid Build Coastguard Worker namespace art HIDDEN {
26*795d594fSAndroid Build Coastguard Worker namespace gc {
27*795d594fSAndroid Build Coastguard Worker namespace collector {
28*795d594fSAndroid Build Coastguard Worker 
UpdateClassAfterObjectMap(mirror::Object * obj)29*795d594fSAndroid Build Coastguard Worker inline void MarkCompact::UpdateClassAfterObjectMap(mirror::Object* obj) {
30*795d594fSAndroid Build Coastguard Worker   mirror::Class* klass = obj->GetClass<kVerifyNone, kWithoutReadBarrier>();
31*795d594fSAndroid Build Coastguard Worker   if (UNLIKELY(std::less<mirror::Object*>{}(obj, klass) && HasAddress(klass))) {
32*795d594fSAndroid Build Coastguard Worker     auto [iter, success] = class_after_obj_map_.try_emplace(ObjReference::FromMirrorPtr(klass),
33*795d594fSAndroid Build Coastguard Worker                                                             ObjReference::FromMirrorPtr(obj));
34*795d594fSAndroid Build Coastguard Worker     if (!success && std::less<mirror::Object*>{}(obj, iter->second.AsMirrorPtr())) {
35*795d594fSAndroid Build Coastguard Worker       iter->second = ObjReference::FromMirrorPtr(obj);
36*795d594fSAndroid Build Coastguard Worker     }
37*795d594fSAndroid Build Coastguard Worker   }
38*795d594fSAndroid Build Coastguard Worker }
39*795d594fSAndroid Build Coastguard Worker 
40*795d594fSAndroid Build Coastguard Worker template <size_t kAlignment>
SetLiveWords(uintptr_t begin,size_t size)41*795d594fSAndroid Build Coastguard Worker inline uintptr_t MarkCompact::LiveWordsBitmap<kAlignment>::SetLiveWords(uintptr_t begin,
42*795d594fSAndroid Build Coastguard Worker                                                                         size_t size) {
43*795d594fSAndroid Build Coastguard Worker   const uintptr_t begin_bit_idx = MemRangeBitmap::BitIndexFromAddr(begin);
44*795d594fSAndroid Build Coastguard Worker   DCHECK(!Bitmap::TestBit(begin_bit_idx));
45*795d594fSAndroid Build Coastguard Worker   // Range to set bit: [begin, end]
46*795d594fSAndroid Build Coastguard Worker   uintptr_t end = begin + size - kAlignment;
47*795d594fSAndroid Build Coastguard Worker   const uintptr_t end_bit_idx = MemRangeBitmap::BitIndexFromAddr(end);
48*795d594fSAndroid Build Coastguard Worker   uintptr_t* begin_bm_address = Bitmap::Begin() + Bitmap::BitIndexToWordIndex(begin_bit_idx);
49*795d594fSAndroid Build Coastguard Worker   uintptr_t* end_bm_address = Bitmap::Begin() + Bitmap::BitIndexToWordIndex(end_bit_idx);
50*795d594fSAndroid Build Coastguard Worker   ptrdiff_t diff = end_bm_address - begin_bm_address;
51*795d594fSAndroid Build Coastguard Worker   uintptr_t mask = Bitmap::BitIndexToMask(begin_bit_idx);
52*795d594fSAndroid Build Coastguard Worker   // Bits that needs to be set in the first word, if it's not also the last word
53*795d594fSAndroid Build Coastguard Worker   mask = ~(mask - 1);
54*795d594fSAndroid Build Coastguard Worker   if (diff > 0) {
55*795d594fSAndroid Build Coastguard Worker     *begin_bm_address |= mask;
56*795d594fSAndroid Build Coastguard Worker     mask = ~0;
57*795d594fSAndroid Build Coastguard Worker     // Even though memset can handle the (diff == 1) case but we should avoid the
58*795d594fSAndroid Build Coastguard Worker     // overhead of a function call for this, highly likely (as most of the objects
59*795d594fSAndroid Build Coastguard Worker     // are small), case.
60*795d594fSAndroid Build Coastguard Worker     if (diff > 1) {
61*795d594fSAndroid Build Coastguard Worker       // Set all intermediate bits to 1.
62*795d594fSAndroid Build Coastguard Worker       std::memset(static_cast<void*>(begin_bm_address + 1), 0xff, (diff - 1) * sizeof(uintptr_t));
63*795d594fSAndroid Build Coastguard Worker     }
64*795d594fSAndroid Build Coastguard Worker   }
65*795d594fSAndroid Build Coastguard Worker   uintptr_t end_mask = Bitmap::BitIndexToMask(end_bit_idx);
66*795d594fSAndroid Build Coastguard Worker   *end_bm_address |= mask & (end_mask | (end_mask - 1));
67*795d594fSAndroid Build Coastguard Worker   return begin_bit_idx;
68*795d594fSAndroid Build Coastguard Worker }
69*795d594fSAndroid Build Coastguard Worker 
70*795d594fSAndroid Build Coastguard Worker template <size_t kAlignment> template <typename Visitor>
VisitLiveStrides(uintptr_t begin_bit_idx,uint8_t * end,const size_t bytes,Visitor && visitor)71*795d594fSAndroid Build Coastguard Worker inline void MarkCompact::LiveWordsBitmap<kAlignment>::VisitLiveStrides(uintptr_t begin_bit_idx,
72*795d594fSAndroid Build Coastguard Worker                                                                        uint8_t* end,
73*795d594fSAndroid Build Coastguard Worker                                                                        const size_t bytes,
74*795d594fSAndroid Build Coastguard Worker                                                                        Visitor&& visitor) const {
75*795d594fSAndroid Build Coastguard Worker   // Range to visit [begin_bit_idx, end_bit_idx]
76*795d594fSAndroid Build Coastguard Worker   DCHECK(IsAligned<kAlignment>(end));
77*795d594fSAndroid Build Coastguard Worker   end -= kAlignment;
78*795d594fSAndroid Build Coastguard Worker   const uintptr_t end_bit_idx = MemRangeBitmap::BitIndexFromAddr(reinterpret_cast<uintptr_t>(end));
79*795d594fSAndroid Build Coastguard Worker   DCHECK_LE(begin_bit_idx, end_bit_idx);
80*795d594fSAndroid Build Coastguard Worker   uintptr_t begin_word_idx = Bitmap::BitIndexToWordIndex(begin_bit_idx);
81*795d594fSAndroid Build Coastguard Worker   const uintptr_t end_word_idx = Bitmap::BitIndexToWordIndex(end_bit_idx);
82*795d594fSAndroid Build Coastguard Worker   DCHECK(Bitmap::TestBit(begin_bit_idx));
83*795d594fSAndroid Build Coastguard Worker   size_t stride_size = 0;
84*795d594fSAndroid Build Coastguard Worker   size_t idx_in_word = 0;
85*795d594fSAndroid Build Coastguard Worker   size_t num_heap_words = bytes / kAlignment;
86*795d594fSAndroid Build Coastguard Worker   uintptr_t live_stride_start_idx;
87*795d594fSAndroid Build Coastguard Worker   uintptr_t word = Bitmap::Begin()[begin_word_idx];
88*795d594fSAndroid Build Coastguard Worker 
89*795d594fSAndroid Build Coastguard Worker   // Setup the first word.
90*795d594fSAndroid Build Coastguard Worker   word &= ~(Bitmap::BitIndexToMask(begin_bit_idx) - 1);
91*795d594fSAndroid Build Coastguard Worker   begin_bit_idx = RoundDown(begin_bit_idx, Bitmap::kBitsPerBitmapWord);
92*795d594fSAndroid Build Coastguard Worker 
93*795d594fSAndroid Build Coastguard Worker   do {
94*795d594fSAndroid Build Coastguard Worker     if (UNLIKELY(begin_word_idx == end_word_idx)) {
95*795d594fSAndroid Build Coastguard Worker       uintptr_t mask = Bitmap::BitIndexToMask(end_bit_idx);
96*795d594fSAndroid Build Coastguard Worker       word &= mask | (mask - 1);
97*795d594fSAndroid Build Coastguard Worker     }
98*795d594fSAndroid Build Coastguard Worker     if (~word == 0) {
99*795d594fSAndroid Build Coastguard Worker       // All bits in the word are marked.
100*795d594fSAndroid Build Coastguard Worker       if (stride_size == 0) {
101*795d594fSAndroid Build Coastguard Worker         live_stride_start_idx = begin_bit_idx;
102*795d594fSAndroid Build Coastguard Worker       }
103*795d594fSAndroid Build Coastguard Worker       stride_size += Bitmap::kBitsPerBitmapWord;
104*795d594fSAndroid Build Coastguard Worker       if (num_heap_words <= stride_size) {
105*795d594fSAndroid Build Coastguard Worker         break;
106*795d594fSAndroid Build Coastguard Worker       }
107*795d594fSAndroid Build Coastguard Worker     } else {
108*795d594fSAndroid Build Coastguard Worker       while (word != 0) {
109*795d594fSAndroid Build Coastguard Worker         // discard 0s
110*795d594fSAndroid Build Coastguard Worker         size_t shift = CTZ(word);
111*795d594fSAndroid Build Coastguard Worker         idx_in_word += shift;
112*795d594fSAndroid Build Coastguard Worker         word >>= shift;
113*795d594fSAndroid Build Coastguard Worker         if (stride_size > 0) {
114*795d594fSAndroid Build Coastguard Worker           if (shift > 0) {
115*795d594fSAndroid Build Coastguard Worker             if (num_heap_words <= stride_size) {
116*795d594fSAndroid Build Coastguard Worker               break;
117*795d594fSAndroid Build Coastguard Worker             }
118*795d594fSAndroid Build Coastguard Worker             visitor(live_stride_start_idx, stride_size, /*is_last*/ false);
119*795d594fSAndroid Build Coastguard Worker             num_heap_words -= stride_size;
120*795d594fSAndroid Build Coastguard Worker             live_stride_start_idx = begin_bit_idx + idx_in_word;
121*795d594fSAndroid Build Coastguard Worker             stride_size = 0;
122*795d594fSAndroid Build Coastguard Worker           }
123*795d594fSAndroid Build Coastguard Worker         } else {
124*795d594fSAndroid Build Coastguard Worker           live_stride_start_idx = begin_bit_idx + idx_in_word;
125*795d594fSAndroid Build Coastguard Worker         }
126*795d594fSAndroid Build Coastguard Worker         // consume 1s
127*795d594fSAndroid Build Coastguard Worker         shift = CTZ(~word);
128*795d594fSAndroid Build Coastguard Worker         DCHECK_NE(shift, 0u);
129*795d594fSAndroid Build Coastguard Worker         word >>= shift;
130*795d594fSAndroid Build Coastguard Worker         idx_in_word += shift;
131*795d594fSAndroid Build Coastguard Worker         stride_size += shift;
132*795d594fSAndroid Build Coastguard Worker       }
133*795d594fSAndroid Build Coastguard Worker       // If the whole word == 0 or the higher bits are 0s, then we exit out of
134*795d594fSAndroid Build Coastguard Worker       // the above loop without completely consuming the word, so call visitor,
135*795d594fSAndroid Build Coastguard Worker       // if needed.
136*795d594fSAndroid Build Coastguard Worker       if (idx_in_word < Bitmap::kBitsPerBitmapWord && stride_size > 0) {
137*795d594fSAndroid Build Coastguard Worker         if (num_heap_words <= stride_size) {
138*795d594fSAndroid Build Coastguard Worker           break;
139*795d594fSAndroid Build Coastguard Worker         }
140*795d594fSAndroid Build Coastguard Worker         visitor(live_stride_start_idx, stride_size, /*is_last*/ false);
141*795d594fSAndroid Build Coastguard Worker         num_heap_words -= stride_size;
142*795d594fSAndroid Build Coastguard Worker         stride_size = 0;
143*795d594fSAndroid Build Coastguard Worker       }
144*795d594fSAndroid Build Coastguard Worker       idx_in_word = 0;
145*795d594fSAndroid Build Coastguard Worker     }
146*795d594fSAndroid Build Coastguard Worker     begin_bit_idx += Bitmap::kBitsPerBitmapWord;
147*795d594fSAndroid Build Coastguard Worker     begin_word_idx++;
148*795d594fSAndroid Build Coastguard Worker     if (UNLIKELY(begin_word_idx > end_word_idx)) {
149*795d594fSAndroid Build Coastguard Worker       num_heap_words = std::min(stride_size, num_heap_words);
150*795d594fSAndroid Build Coastguard Worker       break;
151*795d594fSAndroid Build Coastguard Worker     }
152*795d594fSAndroid Build Coastguard Worker     word = Bitmap::Begin()[begin_word_idx];
153*795d594fSAndroid Build Coastguard Worker   } while (true);
154*795d594fSAndroid Build Coastguard Worker 
155*795d594fSAndroid Build Coastguard Worker   if (stride_size > 0) {
156*795d594fSAndroid Build Coastguard Worker     visitor(live_stride_start_idx, num_heap_words, /*is_last*/ true);
157*795d594fSAndroid Build Coastguard Worker   }
158*795d594fSAndroid Build Coastguard Worker }
159*795d594fSAndroid Build Coastguard Worker 
160*795d594fSAndroid Build Coastguard Worker template <size_t kAlignment>
161*795d594fSAndroid Build Coastguard Worker inline
FindNthLiveWordOffset(size_t chunk_idx,uint32_t n)162*795d594fSAndroid Build Coastguard Worker uint32_t MarkCompact::LiveWordsBitmap<kAlignment>::FindNthLiveWordOffset(size_t chunk_idx,
163*795d594fSAndroid Build Coastguard Worker                                                                          uint32_t n) const {
164*795d594fSAndroid Build Coastguard Worker   DCHECK_LT(n, kBitsPerVectorWord);
165*795d594fSAndroid Build Coastguard Worker   const size_t index = chunk_idx * kBitmapWordsPerVectorWord;
166*795d594fSAndroid Build Coastguard Worker   for (uint32_t i = 0; i < kBitmapWordsPerVectorWord; i++) {
167*795d594fSAndroid Build Coastguard Worker     uintptr_t word = Bitmap::Begin()[index + i];
168*795d594fSAndroid Build Coastguard Worker     if (~word == 0) {
169*795d594fSAndroid Build Coastguard Worker       if (n < Bitmap::kBitsPerBitmapWord) {
170*795d594fSAndroid Build Coastguard Worker         return i * Bitmap::kBitsPerBitmapWord + n;
171*795d594fSAndroid Build Coastguard Worker       }
172*795d594fSAndroid Build Coastguard Worker       n -= Bitmap::kBitsPerBitmapWord;
173*795d594fSAndroid Build Coastguard Worker     } else {
174*795d594fSAndroid Build Coastguard Worker       uint32_t j = 0;
175*795d594fSAndroid Build Coastguard Worker       while (word != 0) {
176*795d594fSAndroid Build Coastguard Worker         // count contiguous 0s
177*795d594fSAndroid Build Coastguard Worker         uint32_t shift = CTZ(word);
178*795d594fSAndroid Build Coastguard Worker         word >>= shift;
179*795d594fSAndroid Build Coastguard Worker         j += shift;
180*795d594fSAndroid Build Coastguard Worker         // count contiguous 1s
181*795d594fSAndroid Build Coastguard Worker         shift = CTZ(~word);
182*795d594fSAndroid Build Coastguard Worker         DCHECK_NE(shift, 0u);
183*795d594fSAndroid Build Coastguard Worker         if (shift > n) {
184*795d594fSAndroid Build Coastguard Worker           return i * Bitmap::kBitsPerBitmapWord + j + n;
185*795d594fSAndroid Build Coastguard Worker         }
186*795d594fSAndroid Build Coastguard Worker         n -= shift;
187*795d594fSAndroid Build Coastguard Worker         word >>= shift;
188*795d594fSAndroid Build Coastguard Worker         j += shift;
189*795d594fSAndroid Build Coastguard Worker       }
190*795d594fSAndroid Build Coastguard Worker     }
191*795d594fSAndroid Build Coastguard Worker   }
192*795d594fSAndroid Build Coastguard Worker   LOG(FATAL) << "Unreachable";
193*795d594fSAndroid Build Coastguard Worker   UNREACHABLE();
194*795d594fSAndroid Build Coastguard Worker }
195*795d594fSAndroid Build Coastguard Worker 
IsOnAllocStack(mirror::Object * ref)196*795d594fSAndroid Build Coastguard Worker inline bool MarkCompact::IsOnAllocStack(mirror::Object* ref) {
197*795d594fSAndroid Build Coastguard Worker   // Pairs with release fence after allocation-stack push in
198*795d594fSAndroid Build Coastguard Worker   // Heap::AllocObjectWithAllocator().
199*795d594fSAndroid Build Coastguard Worker   std::atomic_thread_fence(std::memory_order_acquire);
200*795d594fSAndroid Build Coastguard Worker   accounting::ObjectStack* stack = heap_->GetAllocationStack();
201*795d594fSAndroid Build Coastguard Worker   return stack->Contains(ref);
202*795d594fSAndroid Build Coastguard Worker }
203*795d594fSAndroid Build Coastguard Worker 
UpdateRef(mirror::Object * obj,MemberOffset offset,uint8_t * begin,uint8_t * end)204*795d594fSAndroid Build Coastguard Worker inline void MarkCompact::UpdateRef(mirror::Object* obj,
205*795d594fSAndroid Build Coastguard Worker                                    MemberOffset offset,
206*795d594fSAndroid Build Coastguard Worker                                    uint8_t* begin,
207*795d594fSAndroid Build Coastguard Worker                                    uint8_t* end) {
208*795d594fSAndroid Build Coastguard Worker   mirror::Object* old_ref = obj->GetFieldObject<
209*795d594fSAndroid Build Coastguard Worker       mirror::Object, kVerifyNone, kWithoutReadBarrier, /*kIsVolatile*/false>(offset);
210*795d594fSAndroid Build Coastguard Worker   if (kIsDebugBuild) {
211*795d594fSAndroid Build Coastguard Worker     if (HasAddress(old_ref) &&
212*795d594fSAndroid Build Coastguard Worker         reinterpret_cast<uint8_t*>(old_ref) < black_allocations_begin_ &&
213*795d594fSAndroid Build Coastguard Worker         !moving_space_bitmap_->Test(old_ref)) {
214*795d594fSAndroid Build Coastguard Worker       mirror::Object* from_ref = GetFromSpaceAddr(old_ref);
215*795d594fSAndroid Build Coastguard Worker       std::ostringstream oss;
216*795d594fSAndroid Build Coastguard Worker       heap_->DumpSpaces(oss);
217*795d594fSAndroid Build Coastguard Worker       MemMap::DumpMaps(oss, /* terse= */ true);
218*795d594fSAndroid Build Coastguard Worker       LOG(FATAL) << "Not marked in the bitmap ref=" << old_ref
219*795d594fSAndroid Build Coastguard Worker                  << " from_ref=" << from_ref
220*795d594fSAndroid Build Coastguard Worker                  << " offset=" << offset
221*795d594fSAndroid Build Coastguard Worker                  << " obj=" << obj
222*795d594fSAndroid Build Coastguard Worker                  << " obj-validity=" << IsValidObject(obj)
223*795d594fSAndroid Build Coastguard Worker                  << " from-space=" << static_cast<void*>(from_space_begin_)
224*795d594fSAndroid Build Coastguard Worker                  << " bitmap= " << moving_space_bitmap_->DumpMemAround(old_ref)
225*795d594fSAndroid Build Coastguard Worker                  << " from_ref "
226*795d594fSAndroid Build Coastguard Worker                  << heap_->GetVerification()->DumpRAMAroundAddress(
227*795d594fSAndroid Build Coastguard Worker                      reinterpret_cast<uintptr_t>(from_ref), 128)
228*795d594fSAndroid Build Coastguard Worker                  << " obj "
229*795d594fSAndroid Build Coastguard Worker                  << heap_->GetVerification()->DumpRAMAroundAddress(
230*795d594fSAndroid Build Coastguard Worker                      reinterpret_cast<uintptr_t>(obj), 128)
231*795d594fSAndroid Build Coastguard Worker                  << " old_ref " << heap_->GetVerification()->DumpRAMAroundAddress(
232*795d594fSAndroid Build Coastguard Worker                      reinterpret_cast<uintptr_t>(old_ref), 128)
233*795d594fSAndroid Build Coastguard Worker                  << " maps\n" << oss.str();
234*795d594fSAndroid Build Coastguard Worker     }
235*795d594fSAndroid Build Coastguard Worker   }
236*795d594fSAndroid Build Coastguard Worker   mirror::Object* new_ref = PostCompactAddress(old_ref, begin, end);
237*795d594fSAndroid Build Coastguard Worker   if (new_ref != old_ref) {
238*795d594fSAndroid Build Coastguard Worker     obj->SetFieldObjectWithoutWriteBarrier<
239*795d594fSAndroid Build Coastguard Worker         /*kTransactionActive*/false, /*kCheckTransaction*/false, kVerifyNone, /*kIsVolatile*/false>(
240*795d594fSAndroid Build Coastguard Worker             offset,
241*795d594fSAndroid Build Coastguard Worker             new_ref);
242*795d594fSAndroid Build Coastguard Worker   }
243*795d594fSAndroid Build Coastguard Worker }
244*795d594fSAndroid Build Coastguard Worker 
VerifyRootSingleUpdate(void * root,mirror::Object * old_ref,const RootInfo & info)245*795d594fSAndroid Build Coastguard Worker inline bool MarkCompact::VerifyRootSingleUpdate(void* root,
246*795d594fSAndroid Build Coastguard Worker                                                 mirror::Object* old_ref,
247*795d594fSAndroid Build Coastguard Worker                                                 const RootInfo& info) {
248*795d594fSAndroid Build Coastguard Worker   // ASAN promotes stack-frames to heap in order to detect
249*795d594fSAndroid Build Coastguard Worker   // stack-use-after-return issues. And HWASAN has pointers tagged, which makes
250*795d594fSAndroid Build Coastguard Worker   // it difficult to recognize and prevent stack pointers from being checked.
251*795d594fSAndroid Build Coastguard Worker   // So skip using double-root update detection on ASANs.
252*795d594fSAndroid Build Coastguard Worker   if (kIsDebugBuild && !kMemoryToolIsAvailable && !kHwAsanEnabled) {
253*795d594fSAndroid Build Coastguard Worker     void* stack_low_addr = stack_low_addr_;
254*795d594fSAndroid Build Coastguard Worker     void* stack_high_addr = stack_high_addr_;
255*795d594fSAndroid Build Coastguard Worker     if (!HasAddress(old_ref)) {
256*795d594fSAndroid Build Coastguard Worker       return false;
257*795d594fSAndroid Build Coastguard Worker     }
258*795d594fSAndroid Build Coastguard Worker     Thread* self = Thread::Current();
259*795d594fSAndroid Build Coastguard Worker     if (UNLIKELY(stack_low_addr == nullptr)) {
260*795d594fSAndroid Build Coastguard Worker       // TODO(Simulator): Test that this should not operate on the simulated stack when the
261*795d594fSAndroid Build Coastguard Worker       // simulator supports mark compact.
262*795d594fSAndroid Build Coastguard Worker       stack_low_addr = self->GetStackEnd<kNativeStackType>();
263*795d594fSAndroid Build Coastguard Worker       stack_high_addr = reinterpret_cast<char*>(stack_low_addr)
264*795d594fSAndroid Build Coastguard Worker                         + self->GetUsableStackSize<kNativeStackType>();
265*795d594fSAndroid Build Coastguard Worker     }
266*795d594fSAndroid Build Coastguard Worker     if (std::less<void*>{}(root, stack_low_addr) || std::greater<void*>{}(root, stack_high_addr)) {
267*795d594fSAndroid Build Coastguard Worker       bool inserted;
268*795d594fSAndroid Build Coastguard Worker       {
269*795d594fSAndroid Build Coastguard Worker         MutexLock mu(self, lock_);
270*795d594fSAndroid Build Coastguard Worker         inserted = updated_roots_->insert(root).second;
271*795d594fSAndroid Build Coastguard Worker       }
272*795d594fSAndroid Build Coastguard Worker       if (!inserted) {
273*795d594fSAndroid Build Coastguard Worker         std::ostringstream oss;
274*795d594fSAndroid Build Coastguard Worker         heap_->DumpSpaces(oss);
275*795d594fSAndroid Build Coastguard Worker         MemMap::DumpMaps(oss, /* terse= */ true);
276*795d594fSAndroid Build Coastguard Worker         CHECK(inserted) << "root=" << root << " old_ref=" << old_ref
277*795d594fSAndroid Build Coastguard Worker                         << " stack_low_addr=" << stack_low_addr
278*795d594fSAndroid Build Coastguard Worker                         << " stack_high_addr=" << stack_high_addr << " maps\n"
279*795d594fSAndroid Build Coastguard Worker                         << oss.str();
280*795d594fSAndroid Build Coastguard Worker       }
281*795d594fSAndroid Build Coastguard Worker     }
282*795d594fSAndroid Build Coastguard Worker     DCHECK(reinterpret_cast<uint8_t*>(old_ref) >= black_allocations_begin_ ||
283*795d594fSAndroid Build Coastguard Worker            live_words_bitmap_->Test(old_ref))
284*795d594fSAndroid Build Coastguard Worker         << "ref=" << old_ref << " <" << mirror::Object::PrettyTypeOf(old_ref) << "> RootInfo ["
285*795d594fSAndroid Build Coastguard Worker         << info << "]";
286*795d594fSAndroid Build Coastguard Worker   }
287*795d594fSAndroid Build Coastguard Worker   return true;
288*795d594fSAndroid Build Coastguard Worker }
289*795d594fSAndroid Build Coastguard Worker 
UpdateRoot(mirror::CompressedReference<mirror::Object> * root,uint8_t * begin,uint8_t * end,const RootInfo & info)290*795d594fSAndroid Build Coastguard Worker inline void MarkCompact::UpdateRoot(mirror::CompressedReference<mirror::Object>* root,
291*795d594fSAndroid Build Coastguard Worker                                     uint8_t* begin,
292*795d594fSAndroid Build Coastguard Worker                                     uint8_t* end,
293*795d594fSAndroid Build Coastguard Worker                                     const RootInfo& info) {
294*795d594fSAndroid Build Coastguard Worker   DCHECK(!root->IsNull());
295*795d594fSAndroid Build Coastguard Worker   mirror::Object* old_ref = root->AsMirrorPtr();
296*795d594fSAndroid Build Coastguard Worker   if (VerifyRootSingleUpdate(root, old_ref, info)) {
297*795d594fSAndroid Build Coastguard Worker     mirror::Object* new_ref = PostCompactAddress(old_ref, begin, end);
298*795d594fSAndroid Build Coastguard Worker     if (old_ref != new_ref) {
299*795d594fSAndroid Build Coastguard Worker       root->Assign(new_ref);
300*795d594fSAndroid Build Coastguard Worker     }
301*795d594fSAndroid Build Coastguard Worker   }
302*795d594fSAndroid Build Coastguard Worker }
303*795d594fSAndroid Build Coastguard Worker 
UpdateRoot(mirror::Object ** root,uint8_t * begin,uint8_t * end,const RootInfo & info)304*795d594fSAndroid Build Coastguard Worker inline void MarkCompact::UpdateRoot(mirror::Object** root,
305*795d594fSAndroid Build Coastguard Worker                                     uint8_t* begin,
306*795d594fSAndroid Build Coastguard Worker                                     uint8_t* end,
307*795d594fSAndroid Build Coastguard Worker                                     const RootInfo& info) {
308*795d594fSAndroid Build Coastguard Worker   mirror::Object* old_ref = *root;
309*795d594fSAndroid Build Coastguard Worker   if (VerifyRootSingleUpdate(root, old_ref, info)) {
310*795d594fSAndroid Build Coastguard Worker     mirror::Object* new_ref = PostCompactAddress(old_ref, begin, end);
311*795d594fSAndroid Build Coastguard Worker     if (old_ref != new_ref) {
312*795d594fSAndroid Build Coastguard Worker       *root = new_ref;
313*795d594fSAndroid Build Coastguard Worker     }
314*795d594fSAndroid Build Coastguard Worker   }
315*795d594fSAndroid Build Coastguard Worker }
316*795d594fSAndroid Build Coastguard Worker 
317*795d594fSAndroid Build Coastguard Worker template <size_t kAlignment>
CountLiveWordsUpto(size_t bit_idx)318*795d594fSAndroid Build Coastguard Worker inline size_t MarkCompact::LiveWordsBitmap<kAlignment>::CountLiveWordsUpto(size_t bit_idx) const {
319*795d594fSAndroid Build Coastguard Worker   const size_t word_offset = Bitmap::BitIndexToWordIndex(bit_idx);
320*795d594fSAndroid Build Coastguard Worker   uintptr_t word;
321*795d594fSAndroid Build Coastguard Worker   size_t ret = 0;
322*795d594fSAndroid Build Coastguard Worker   // This is needed only if we decide to make chunks 128-bit but still
323*795d594fSAndroid Build Coastguard Worker   // choose to use 64-bit word for bitmap. Ideally we should use 128-bit
324*795d594fSAndroid Build Coastguard Worker   // SIMD instructions to compute popcount.
325*795d594fSAndroid Build Coastguard Worker   if (kBitmapWordsPerVectorWord > 1) {
326*795d594fSAndroid Build Coastguard Worker     for (size_t i = RoundDown(word_offset, kBitmapWordsPerVectorWord); i < word_offset; i++) {
327*795d594fSAndroid Build Coastguard Worker       word = Bitmap::Begin()[i];
328*795d594fSAndroid Build Coastguard Worker       ret += POPCOUNT(word);
329*795d594fSAndroid Build Coastguard Worker     }
330*795d594fSAndroid Build Coastguard Worker   }
331*795d594fSAndroid Build Coastguard Worker   word = Bitmap::Begin()[word_offset];
332*795d594fSAndroid Build Coastguard Worker   const uintptr_t mask = Bitmap::BitIndexToMask(bit_idx);
333*795d594fSAndroid Build Coastguard Worker   DCHECK_NE(word & mask, 0u)
334*795d594fSAndroid Build Coastguard Worker         << " word_offset:" << word_offset
335*795d594fSAndroid Build Coastguard Worker         << " bit_idx:" << bit_idx
336*795d594fSAndroid Build Coastguard Worker         << " bit_idx_in_word:" << (bit_idx % Bitmap::kBitsPerBitmapWord)
337*795d594fSAndroid Build Coastguard Worker         << std::hex << " word: 0x" << word
338*795d594fSAndroid Build Coastguard Worker         << " mask: 0x" << mask << std::dec;
339*795d594fSAndroid Build Coastguard Worker   ret += POPCOUNT(word & (mask - 1));
340*795d594fSAndroid Build Coastguard Worker   return ret;
341*795d594fSAndroid Build Coastguard Worker }
342*795d594fSAndroid Build Coastguard Worker 
PostCompactBlackObjAddr(mirror::Object * old_ref)343*795d594fSAndroid Build Coastguard Worker inline mirror::Object* MarkCompact::PostCompactBlackObjAddr(mirror::Object* old_ref) const {
344*795d594fSAndroid Build Coastguard Worker   return reinterpret_cast<mirror::Object*>(reinterpret_cast<uint8_t*>(old_ref)
345*795d594fSAndroid Build Coastguard Worker                                            - black_objs_slide_diff_);
346*795d594fSAndroid Build Coastguard Worker }
347*795d594fSAndroid Build Coastguard Worker 
PostCompactOldObjAddr(mirror::Object * old_ref)348*795d594fSAndroid Build Coastguard Worker inline mirror::Object* MarkCompact::PostCompactOldObjAddr(mirror::Object* old_ref) const {
349*795d594fSAndroid Build Coastguard Worker   const uintptr_t begin = live_words_bitmap_->Begin();
350*795d594fSAndroid Build Coastguard Worker   const uintptr_t addr_offset = reinterpret_cast<uintptr_t>(old_ref) - begin;
351*795d594fSAndroid Build Coastguard Worker   const size_t vec_idx = addr_offset / kOffsetChunkSize;
352*795d594fSAndroid Build Coastguard Worker   const size_t live_bytes_in_bitmap_word =
353*795d594fSAndroid Build Coastguard Worker       live_words_bitmap_->CountLiveWordsUpto(addr_offset / kAlignment) * kAlignment;
354*795d594fSAndroid Build Coastguard Worker   return reinterpret_cast<mirror::Object*>(begin
355*795d594fSAndroid Build Coastguard Worker                                            + chunk_info_vec_[vec_idx]
356*795d594fSAndroid Build Coastguard Worker                                            + live_bytes_in_bitmap_word);
357*795d594fSAndroid Build Coastguard Worker }
358*795d594fSAndroid Build Coastguard Worker 
PostCompactAddressUnchecked(mirror::Object * old_ref)359*795d594fSAndroid Build Coastguard Worker inline mirror::Object* MarkCompact::PostCompactAddressUnchecked(mirror::Object* old_ref) const {
360*795d594fSAndroid Build Coastguard Worker   if (reinterpret_cast<uint8_t*>(old_ref) >= black_allocations_begin_) {
361*795d594fSAndroid Build Coastguard Worker     return PostCompactBlackObjAddr(old_ref);
362*795d594fSAndroid Build Coastguard Worker   }
363*795d594fSAndroid Build Coastguard Worker   if (kIsDebugBuild) {
364*795d594fSAndroid Build Coastguard Worker     mirror::Object* from_ref = GetFromSpaceAddr(old_ref);
365*795d594fSAndroid Build Coastguard Worker     DCHECK(live_words_bitmap_->Test(old_ref))
366*795d594fSAndroid Build Coastguard Worker          << "ref=" << old_ref;
367*795d594fSAndroid Build Coastguard Worker     if (!moving_space_bitmap_->Test(old_ref)) {
368*795d594fSAndroid Build Coastguard Worker       std::ostringstream oss;
369*795d594fSAndroid Build Coastguard Worker       Runtime::Current()->GetHeap()->DumpSpaces(oss);
370*795d594fSAndroid Build Coastguard Worker       MemMap::DumpMaps(oss, /* terse= */ true);
371*795d594fSAndroid Build Coastguard Worker       LOG(FATAL) << "ref=" << old_ref
372*795d594fSAndroid Build Coastguard Worker                  << " from_ref=" << from_ref
373*795d594fSAndroid Build Coastguard Worker                  << " from-space=" << static_cast<void*>(from_space_begin_)
374*795d594fSAndroid Build Coastguard Worker                  << " bitmap= " << moving_space_bitmap_->DumpMemAround(old_ref)
375*795d594fSAndroid Build Coastguard Worker                  << heap_->GetVerification()->DumpRAMAroundAddress(
376*795d594fSAndroid Build Coastguard Worker                          reinterpret_cast<uintptr_t>(from_ref), 128)
377*795d594fSAndroid Build Coastguard Worker                  << " maps\n" << oss.str();
378*795d594fSAndroid Build Coastguard Worker     }
379*795d594fSAndroid Build Coastguard Worker   }
380*795d594fSAndroid Build Coastguard Worker   return PostCompactOldObjAddr(old_ref);
381*795d594fSAndroid Build Coastguard Worker }
382*795d594fSAndroid Build Coastguard Worker 
PostCompactAddress(mirror::Object * old_ref,uint8_t * begin,uint8_t * end)383*795d594fSAndroid Build Coastguard Worker inline mirror::Object* MarkCompact::PostCompactAddress(mirror::Object* old_ref,
384*795d594fSAndroid Build Coastguard Worker                                                        uint8_t* begin,
385*795d594fSAndroid Build Coastguard Worker                                                        uint8_t* end) const {
386*795d594fSAndroid Build Coastguard Worker   if (LIKELY(HasAddress(old_ref, begin, end))) {
387*795d594fSAndroid Build Coastguard Worker     return PostCompactAddressUnchecked(old_ref);
388*795d594fSAndroid Build Coastguard Worker   }
389*795d594fSAndroid Build Coastguard Worker   return old_ref;
390*795d594fSAndroid Build Coastguard Worker }
391*795d594fSAndroid Build Coastguard Worker 
392*795d594fSAndroid Build Coastguard Worker }  // namespace collector
393*795d594fSAndroid Build Coastguard Worker }  // namespace gc
394*795d594fSAndroid Build Coastguard Worker }  // namespace art
395*795d594fSAndroid Build Coastguard Worker 
396*795d594fSAndroid Build Coastguard Worker #endif  // ART_RUNTIME_GC_COLLECTOR_MARK_COMPACT_INL_H_
397