blob: 0a15e9eb900652a65a5be5c9b82a4124f9f4dd39 [file] [log] [blame]
Ian Rogers1d54e732013-05-02 21:10:01 -07001/*
2 * Copyright (C) 2012 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include "mod_union_table.h"
18
Ian Rogers700a4022014-05-19 16:49:03 -070019#include <memory>
20
Ian Rogers1d54e732013-05-02 21:10:01 -070021#include "base/stl_util.h"
22#include "card_table-inl.h"
23#include "heap_bitmap.h"
Mathieu Chartiera8e8f9c2014-04-09 14:51:05 -070024#include "gc/accounting/space_bitmap-inl.h"
Mathieu Chartier11409ae2013-09-23 11:49:36 -070025#include "gc/collector/mark_sweep.h"
Ian Rogers1d54e732013-05-02 21:10:01 -070026#include "gc/collector/mark_sweep-inl.h"
27#include "gc/heap.h"
28#include "gc/space/space.h"
Brian Carlstromea46f952013-07-30 01:26:50 -070029#include "mirror/art_field-inl.h"
Ian Rogers1d54e732013-05-02 21:10:01 -070030#include "mirror/object-inl.h"
31#include "mirror/class-inl.h"
Ian Rogers1d54e732013-05-02 21:10:01 -070032#include "mirror/object_array-inl.h"
33#include "space_bitmap-inl.h"
34#include "thread.h"
Ian Rogers1d54e732013-05-02 21:10:01 -070035
Brian Carlstrom3e3d5912013-07-18 00:19:45 -070036using ::art::mirror::Object;
Ian Rogers1d54e732013-05-02 21:10:01 -070037
38namespace art {
39namespace gc {
40namespace accounting {
41
Ian Rogers1d54e732013-05-02 21:10:01 -070042class ModUnionClearCardSetVisitor {
43 public:
Mathieu Chartier0a9dc052013-07-25 11:01:28 -070044 explicit ModUnionClearCardSetVisitor(ModUnionTable::CardSet* const cleared_cards)
Ian Rogers1d54e732013-05-02 21:10:01 -070045 : cleared_cards_(cleared_cards) {
46 }
47
Ian Rogers13735952014-10-08 12:43:28 -070048 inline void operator()(uint8_t* card, uint8_t expected_value, uint8_t new_value) const {
Ian Rogers6a3c1fc2014-10-31 00:33:20 -070049 UNUSED(new_value);
Ian Rogers1d54e732013-05-02 21:10:01 -070050 if (expected_value == CardTable::kCardDirty) {
51 cleared_cards_->insert(card);
52 }
53 }
54
55 private:
Mathieu Chartier0a9dc052013-07-25 11:01:28 -070056 ModUnionTable::CardSet* const cleared_cards_;
Ian Rogers1d54e732013-05-02 21:10:01 -070057};
58
59class ModUnionClearCardVisitor {
60 public:
Ian Rogers13735952014-10-08 12:43:28 -070061 explicit ModUnionClearCardVisitor(std::vector<uint8_t*>* cleared_cards)
Ian Rogers1d54e732013-05-02 21:10:01 -070062 : cleared_cards_(cleared_cards) {
63 }
64
Ian Rogers13735952014-10-08 12:43:28 -070065 void operator()(uint8_t* card, uint8_t expected_card, uint8_t new_card) const {
Ian Rogers6a3c1fc2014-10-31 00:33:20 -070066 UNUSED(new_card);
Ian Rogers1d54e732013-05-02 21:10:01 -070067 if (expected_card == CardTable::kCardDirty) {
68 cleared_cards_->push_back(card);
69 }
70 }
71 private:
Ian Rogers13735952014-10-08 12:43:28 -070072 std::vector<uint8_t*>* const cleared_cards_;
Ian Rogers1d54e732013-05-02 21:10:01 -070073};
74
Mathieu Chartier11409ae2013-09-23 11:49:36 -070075class ModUnionUpdateObjectReferencesVisitor {
Ian Rogers1d54e732013-05-02 21:10:01 -070076 public:
Mathieu Chartiere4cab172014-08-19 18:24:04 -070077 ModUnionUpdateObjectReferencesVisitor(MarkHeapReferenceCallback* callback, void* arg,
78 space::ContinuousSpace* from_space,
79 bool* contains_reference_to_other_space)
80 : callback_(callback), arg_(arg), from_space_(from_space),
81 contains_reference_to_other_space_(contains_reference_to_other_space) {
Mathieu Chartier11409ae2013-09-23 11:49:36 -070082 }
Ian Rogers1d54e732013-05-02 21:10:01 -070083
Mathieu Chartier11409ae2013-09-23 11:49:36 -070084 // Extra parameters are required since we use this same visitor signature for checking objects.
Mathieu Chartier4aeec172014-03-27 16:09:46 -070085 void operator()(Object* obj, MemberOffset offset, bool /*is_static*/) const
Mathieu Chartier407f7022014-02-18 14:37:05 -080086 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Mathieu Chartier11409ae2013-09-23 11:49:36 -070087 // Only add the reference if it is non null and fits our criteria.
Mathieu Chartier407f7022014-02-18 14:37:05 -080088 mirror::HeapReference<Object>* obj_ptr = obj->GetFieldObjectReferenceAddr(offset);
Mathieu Chartiere4cab172014-08-19 18:24:04 -070089 mirror::Object* ref = obj_ptr->AsMirrorPtr();
90 if (ref != nullptr && !from_space_->HasAddress(ref)) {
91 *contains_reference_to_other_space_ = true;
Mathieu Chartier407f7022014-02-18 14:37:05 -080092 callback_(obj_ptr, arg_);
Mathieu Chartier11409ae2013-09-23 11:49:36 -070093 }
Ian Rogers1d54e732013-05-02 21:10:01 -070094 }
95
96 private:
Mathieu Chartier407f7022014-02-18 14:37:05 -080097 MarkHeapReferenceCallback* const callback_;
Mathieu Chartier11409ae2013-09-23 11:49:36 -070098 void* arg_;
Mathieu Chartiere4cab172014-08-19 18:24:04 -070099 // Space which we are scanning
100 space::ContinuousSpace* const from_space_;
101 // Set if we have any references to another space.
102 bool* const contains_reference_to_other_space_;
Ian Rogers1d54e732013-05-02 21:10:01 -0700103};
104
Mathieu Chartier11409ae2013-09-23 11:49:36 -0700105class ModUnionScanImageRootVisitor {
106 public:
Mathieu Chartiere4cab172014-08-19 18:24:04 -0700107 ModUnionScanImageRootVisitor(MarkHeapReferenceCallback* callback, void* arg,
108 space::ContinuousSpace* from_space,
109 bool* contains_reference_to_other_space)
110 : callback_(callback), arg_(arg), from_space_(from_space),
111 contains_reference_to_other_space_(contains_reference_to_other_space) {}
Mathieu Chartier11409ae2013-09-23 11:49:36 -0700112
113 void operator()(Object* root) const
114 EXCLUSIVE_LOCKS_REQUIRED(Locks::heap_bitmap_lock_)
115 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
116 DCHECK(root != NULL);
Mathieu Chartiere4cab172014-08-19 18:24:04 -0700117 ModUnionUpdateObjectReferencesVisitor ref_visitor(callback_, arg_, from_space_,
118 contains_reference_to_other_space_);
Ian Rogersb0fa5dc2014-04-28 16:47:08 -0700119 root->VisitReferences<kMovingClasses>(ref_visitor, VoidFunctor());
Mathieu Chartier11409ae2013-09-23 11:49:36 -0700120 }
121
122 private:
Mathieu Chartier407f7022014-02-18 14:37:05 -0800123 MarkHeapReferenceCallback* const callback_;
Mathieu Chartier83c8ee02014-01-28 14:50:23 -0800124 void* const arg_;
Mathieu Chartiere4cab172014-08-19 18:24:04 -0700125 // Space which we are scanning
126 space::ContinuousSpace* const from_space_;
127 // Set if we have any references to another space.
128 bool* const contains_reference_to_other_space_;
Mathieu Chartier11409ae2013-09-23 11:49:36 -0700129};
130
131void ModUnionTableReferenceCache::ClearCards() {
Ian Rogers1d54e732013-05-02 21:10:01 -0700132 CardTable* card_table = GetHeap()->GetCardTable();
133 ModUnionClearCardSetVisitor visitor(&cleared_cards_);
134 // Clear dirty cards in the this space and update the corresponding mod-union bits.
Mathieu Chartier11409ae2013-09-23 11:49:36 -0700135 card_table->ModifyCardsAtomic(space_->Begin(), space_->End(), AgeCardVisitor(), visitor);
Ian Rogers1d54e732013-05-02 21:10:01 -0700136}
137
138class AddToReferenceArrayVisitor {
139 public:
140 explicit AddToReferenceArrayVisitor(ModUnionTableReferenceCache* mod_union_table,
Ian Rogersef7d42f2014-01-06 12:55:46 -0800141 std::vector<mirror::HeapReference<Object>*>* references)
142 : mod_union_table_(mod_union_table), references_(references) {
Ian Rogers1d54e732013-05-02 21:10:01 -0700143 }
144
145 // Extra parameters are required since we use this same visitor signature for checking objects.
Mathieu Chartier4aeec172014-03-27 16:09:46 -0700146 void operator()(Object* obj, MemberOffset offset, bool /*is_static*/) const
Mathieu Chartier407f7022014-02-18 14:37:05 -0800147 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
148 mirror::HeapReference<Object>* ref_ptr = obj->GetFieldObjectReferenceAddr(offset);
149 mirror::Object* ref = ref_ptr->AsMirrorPtr();
Ian Rogers1d54e732013-05-02 21:10:01 -0700150 // Only add the reference if it is non null and fits our criteria.
Mathieu Chartier4aeec172014-03-27 16:09:46 -0700151 if (ref != nullptr && mod_union_table_->ShouldAddReference(ref)) {
Mathieu Chartier11409ae2013-09-23 11:49:36 -0700152 // Push the adddress of the reference.
Mathieu Chartier407f7022014-02-18 14:37:05 -0800153 references_->push_back(ref_ptr);
Ian Rogers1d54e732013-05-02 21:10:01 -0700154 }
155 }
156
157 private:
158 ModUnionTableReferenceCache* const mod_union_table_;
Ian Rogersef7d42f2014-01-06 12:55:46 -0800159 std::vector<mirror::HeapReference<Object>*>* const references_;
Ian Rogers1d54e732013-05-02 21:10:01 -0700160};
161
162class ModUnionReferenceVisitor {
163 public:
164 explicit ModUnionReferenceVisitor(ModUnionTableReferenceCache* const mod_union_table,
Ian Rogersef7d42f2014-01-06 12:55:46 -0800165 std::vector<mirror::HeapReference<Object>*>* references)
Ian Rogers1d54e732013-05-02 21:10:01 -0700166 : mod_union_table_(mod_union_table),
167 references_(references) {
168 }
169
Mathieu Chartier11409ae2013-09-23 11:49:36 -0700170 void operator()(Object* obj) const
Ian Rogers1d54e732013-05-02 21:10:01 -0700171 SHARED_LOCKS_REQUIRED(Locks::heap_bitmap_lock_, Locks::mutator_lock_) {
Ian Rogers1d54e732013-05-02 21:10:01 -0700172 // We don't have an early exit since we use the visitor pattern, an early
173 // exit should significantly speed this up.
174 AddToReferenceArrayVisitor visitor(mod_union_table_, references_);
Ian Rogersb0fa5dc2014-04-28 16:47:08 -0700175 obj->VisitReferences<kMovingClasses>(visitor, VoidFunctor());
Ian Rogers1d54e732013-05-02 21:10:01 -0700176 }
177 private:
178 ModUnionTableReferenceCache* const mod_union_table_;
Ian Rogersef7d42f2014-01-06 12:55:46 -0800179 std::vector<mirror::HeapReference<Object>*>* const references_;
Ian Rogers1d54e732013-05-02 21:10:01 -0700180};
181
182class CheckReferenceVisitor {
183 public:
184 explicit CheckReferenceVisitor(ModUnionTableReferenceCache* mod_union_table,
185 const std::set<const Object*>& references)
186 : mod_union_table_(mod_union_table),
187 references_(references) {
188 }
189
190 // Extra parameters are required since we use this same visitor signature for checking objects.
Mathieu Chartier4aeec172014-03-27 16:09:46 -0700191 void operator()(Object* obj, MemberOffset offset, bool /*is_static*/) const
Ian Rogers1d54e732013-05-02 21:10:01 -0700192 SHARED_LOCKS_REQUIRED(Locks::heap_bitmap_lock_, Locks::mutator_lock_) {
Ian Rogersb0fa5dc2014-04-28 16:47:08 -0700193 mirror::Object* ref = obj->GetFieldObject<mirror::Object>(offset);
Mathieu Chartier4aeec172014-03-27 16:09:46 -0700194 if (ref != nullptr && mod_union_table_->ShouldAddReference(ref) &&
Ian Rogers1d54e732013-05-02 21:10:01 -0700195 references_.find(ref) == references_.end()) {
Mathieu Chartier407f7022014-02-18 14:37:05 -0800196 Heap* heap = mod_union_table_->GetHeap();
Ian Rogers1d54e732013-05-02 21:10:01 -0700197 space::ContinuousSpace* from_space = heap->FindContinuousSpaceFromObject(obj, false);
198 space::ContinuousSpace* to_space = heap->FindContinuousSpaceFromObject(ref, false);
Mathieu Chartier407f7022014-02-18 14:37:05 -0800199 LOG(INFO) << "Object " << reinterpret_cast<const void*>(obj) << "(" << PrettyTypeOf(obj)
200 << ")" << "References " << reinterpret_cast<const void*>(ref) << "(" << PrettyTypeOf(ref)
201 << ") without being in mod-union table";
202 LOG(INFO) << "FromSpace " << from_space->GetName() << " type "
203 << from_space->GetGcRetentionPolicy();
204 LOG(INFO) << "ToSpace " << to_space->GetName() << " type "
205 << to_space->GetGcRetentionPolicy();
Mathieu Chartier4c13a3f2014-07-14 14:57:16 -0700206 heap->DumpSpaces(LOG(INFO));
Ian Rogers1d54e732013-05-02 21:10:01 -0700207 LOG(FATAL) << "FATAL ERROR";
208 }
209 }
210
211 private:
212 ModUnionTableReferenceCache* const mod_union_table_;
213 const std::set<const Object*>& references_;
214};
215
216class ModUnionCheckReferences {
217 public:
Brian Carlstromdf629502013-07-17 22:39:56 -0700218 explicit ModUnionCheckReferences(ModUnionTableReferenceCache* mod_union_table,
219 const std::set<const Object*>& references)
Ian Rogers1d54e732013-05-02 21:10:01 -0700220 EXCLUSIVE_LOCKS_REQUIRED(Locks::heap_bitmap_lock_)
221 : mod_union_table_(mod_union_table), references_(references) {
222 }
223
Mathieu Chartier11409ae2013-09-23 11:49:36 -0700224 void operator()(Object* obj) const NO_THREAD_SAFETY_ANALYSIS {
Ian Rogers1d54e732013-05-02 21:10:01 -0700225 Locks::heap_bitmap_lock_->AssertSharedHeld(Thread::Current());
Ian Rogers1d54e732013-05-02 21:10:01 -0700226 CheckReferenceVisitor visitor(mod_union_table_, references_);
Ian Rogersb0fa5dc2014-04-28 16:47:08 -0700227 obj->VisitReferences<kMovingClasses>(visitor, VoidFunctor());
Ian Rogers1d54e732013-05-02 21:10:01 -0700228 }
229
230 private:
231 ModUnionTableReferenceCache* const mod_union_table_;
232 const std::set<const Object*>& references_;
233};
234
235void ModUnionTableReferenceCache::Verify() {
236 // Start by checking that everything in the mod union table is marked.
Mathieu Chartier11409ae2013-09-23 11:49:36 -0700237 for (const auto& ref_pair : references_) {
Ian Rogersef7d42f2014-01-06 12:55:46 -0800238 for (mirror::HeapReference<Object>* ref : ref_pair.second) {
239 CHECK(heap_->IsLiveObjectLocked(ref->AsMirrorPtr()));
Ian Rogers1d54e732013-05-02 21:10:01 -0700240 }
241 }
242
243 // Check the references of each clean card which is also in the mod union table.
Mathieu Chartier11409ae2013-09-23 11:49:36 -0700244 CardTable* card_table = heap_->GetCardTable();
Mathieu Chartiera8e8f9c2014-04-09 14:51:05 -0700245 ContinuousSpaceBitmap* live_bitmap = space_->GetLiveBitmap();
Mathieu Chartier11409ae2013-09-23 11:49:36 -0700246 for (const auto& ref_pair : references_) {
Ian Rogers13735952014-10-08 12:43:28 -0700247 const uint8_t* card = ref_pair.first;
Ian Rogers1d54e732013-05-02 21:10:01 -0700248 if (*card == CardTable::kCardClean) {
Mathieu Chartier11409ae2013-09-23 11:49:36 -0700249 std::set<const Object*> reference_set;
Ian Rogersef7d42f2014-01-06 12:55:46 -0800250 for (mirror::HeapReference<Object>* obj_ptr : ref_pair.second) {
251 reference_set.insert(obj_ptr->AsMirrorPtr());
Mathieu Chartier11409ae2013-09-23 11:49:36 -0700252 }
Ian Rogers1d54e732013-05-02 21:10:01 -0700253 ModUnionCheckReferences visitor(this, reference_set);
254 uintptr_t start = reinterpret_cast<uintptr_t>(card_table->AddrFromCard(card));
Mathieu Chartier11409ae2013-09-23 11:49:36 -0700255 live_bitmap->VisitMarkedRange(start, start + CardTable::kCardSize, visitor);
Ian Rogers1d54e732013-05-02 21:10:01 -0700256 }
257 }
258}
259
260void ModUnionTableReferenceCache::Dump(std::ostream& os) {
261 CardTable* card_table = heap_->GetCardTable();
Ian Rogers1d54e732013-05-02 21:10:01 -0700262 os << "ModUnionTable cleared cards: [";
Ian Rogers13735952014-10-08 12:43:28 -0700263 for (uint8_t* card_addr : cleared_cards_) {
Mathieu Chartier02e25112013-08-14 16:14:24 -0700264 uintptr_t start = reinterpret_cast<uintptr_t>(card_table->AddrFromCard(card_addr));
Ian Rogers1d54e732013-05-02 21:10:01 -0700265 uintptr_t end = start + CardTable::kCardSize;
266 os << reinterpret_cast<void*>(start) << "-" << reinterpret_cast<void*>(end) << ",";
267 }
268 os << "]\nModUnionTable references: [";
Mathieu Chartier11409ae2013-09-23 11:49:36 -0700269 for (const auto& ref_pair : references_) {
Ian Rogers13735952014-10-08 12:43:28 -0700270 const uint8_t* card_addr = ref_pair.first;
Mathieu Chartier02e25112013-08-14 16:14:24 -0700271 uintptr_t start = reinterpret_cast<uintptr_t>(card_table->AddrFromCard(card_addr));
Ian Rogers1d54e732013-05-02 21:10:01 -0700272 uintptr_t end = start + CardTable::kCardSize;
273 os << reinterpret_cast<void*>(start) << "-" << reinterpret_cast<void*>(end) << "->{";
Ian Rogersef7d42f2014-01-06 12:55:46 -0800274 for (mirror::HeapReference<Object>* ref : ref_pair.second) {
275 os << reinterpret_cast<const void*>(ref->AsMirrorPtr()) << ",";
Ian Rogers1d54e732013-05-02 21:10:01 -0700276 }
277 os << "},";
278 }
279}
280
Mathieu Chartier407f7022014-02-18 14:37:05 -0800281void ModUnionTableReferenceCache::UpdateAndMarkReferences(MarkHeapReferenceCallback* callback,
Mathieu Chartier815873e2014-02-13 18:02:13 -0800282 void* arg) {
Mathieu Chartier4aeec172014-03-27 16:09:46 -0700283 CardTable* card_table = heap_->GetCardTable();
Ian Rogers1d54e732013-05-02 21:10:01 -0700284
Ian Rogersef7d42f2014-01-06 12:55:46 -0800285 std::vector<mirror::HeapReference<Object>*> cards_references;
Mathieu Chartier11409ae2013-09-23 11:49:36 -0700286 ModUnionReferenceVisitor add_visitor(this, &cards_references);
Ian Rogers1d54e732013-05-02 21:10:01 -0700287
Mathieu Chartier02e25112013-08-14 16:14:24 -0700288 for (const auto& card : cleared_cards_) {
Ian Rogers1d54e732013-05-02 21:10:01 -0700289 // Clear and re-compute alloc space references associated with this card.
290 cards_references.clear();
291 uintptr_t start = reinterpret_cast<uintptr_t>(card_table->AddrFromCard(card));
292 uintptr_t end = start + CardTable::kCardSize;
Mathieu Chartier4aeec172014-03-27 16:09:46 -0700293 auto* space = heap_->FindContinuousSpaceFromObject(reinterpret_cast<Object*>(start), false);
Mathieu Chartier02e25112013-08-14 16:14:24 -0700294 DCHECK(space != nullptr);
Mathieu Chartiera8e8f9c2014-04-09 14:51:05 -0700295 ContinuousSpaceBitmap* live_bitmap = space->GetLiveBitmap();
Mathieu Chartier11409ae2013-09-23 11:49:36 -0700296 live_bitmap->VisitMarkedRange(start, end, add_visitor);
Ian Rogers1d54e732013-05-02 21:10:01 -0700297
298 // Update the corresponding references for the card.
Mathieu Chartier02e25112013-08-14 16:14:24 -0700299 auto found = references_.find(card);
Ian Rogers1d54e732013-05-02 21:10:01 -0700300 if (found == references_.end()) {
301 if (cards_references.empty()) {
302 // No reason to add empty array.
303 continue;
304 }
305 references_.Put(card, cards_references);
306 } else {
307 found->second = cards_references;
308 }
309 }
310 cleared_cards_.clear();
Ian Rogers1d54e732013-05-02 21:10:01 -0700311 size_t count = 0;
Mathieu Chartier02e25112013-08-14 16:14:24 -0700312 for (const auto& ref : references_) {
Ian Rogersef7d42f2014-01-06 12:55:46 -0800313 for (mirror::HeapReference<Object>* obj_ptr : ref.second) {
Mathieu Chartier407f7022014-02-18 14:37:05 -0800314 callback(obj_ptr, arg);
Ian Rogers1d54e732013-05-02 21:10:01 -0700315 }
Mathieu Chartier11409ae2013-09-23 11:49:36 -0700316 count += ref.second.size();
Ian Rogers1d54e732013-05-02 21:10:01 -0700317 }
318 if (VLOG_IS_ON(heap)) {
319 VLOG(gc) << "Marked " << count << " references in mod union table";
320 }
321}
322
Mathieu Chartier11409ae2013-09-23 11:49:36 -0700323void ModUnionTableCardCache::ClearCards() {
Ian Rogers1d54e732013-05-02 21:10:01 -0700324 CardTable* card_table = GetHeap()->GetCardTable();
325 ModUnionClearCardSetVisitor visitor(&cleared_cards_);
326 // Clear dirty cards in the this space and update the corresponding mod-union bits.
Mathieu Chartier11409ae2013-09-23 11:49:36 -0700327 card_table->ModifyCardsAtomic(space_->Begin(), space_->End(), AgeCardVisitor(), visitor);
Ian Rogers1d54e732013-05-02 21:10:01 -0700328}
329
330// Mark all references to the alloc space(s).
Mathieu Chartier407f7022014-02-18 14:37:05 -0800331void ModUnionTableCardCache::UpdateAndMarkReferences(MarkHeapReferenceCallback* callback,
332 void* arg) {
Ian Rogers1d54e732013-05-02 21:10:01 -0700333 CardTable* card_table = heap_->GetCardTable();
Mathieu Chartiera8e8f9c2014-04-09 14:51:05 -0700334 ContinuousSpaceBitmap* bitmap = space_->GetLiveBitmap();
Mathieu Chartiere4cab172014-08-19 18:24:04 -0700335 bool reference_to_other_space = false;
336 ModUnionScanImageRootVisitor scan_visitor(callback, arg, space_, &reference_to_other_space);
337 for (auto it = cleared_cards_.begin(), end = cleared_cards_.end(); it != end; ) {
338 uintptr_t start = reinterpret_cast<uintptr_t>(card_table->AddrFromCard(*it));
Mathieu Chartier11409ae2013-09-23 11:49:36 -0700339 DCHECK(space_->HasAddress(reinterpret_cast<Object*>(start)));
Mathieu Chartiere4cab172014-08-19 18:24:04 -0700340 reference_to_other_space = false;
Mathieu Chartier11409ae2013-09-23 11:49:36 -0700341 bitmap->VisitMarkedRange(start, start + CardTable::kCardSize, scan_visitor);
Mathieu Chartiere4cab172014-08-19 18:24:04 -0700342 if (!reference_to_other_space) {
343 // No non null reference to another space, remove the card.
344 it = cleared_cards_.erase(it);
345 } else {
346 ++it;
347 }
Ian Rogers1d54e732013-05-02 21:10:01 -0700348 }
349}
350
351void ModUnionTableCardCache::Dump(std::ostream& os) {
352 CardTable* card_table = heap_->GetCardTable();
Ian Rogers1d54e732013-05-02 21:10:01 -0700353 os << "ModUnionTable dirty cards: [";
Ian Rogers13735952014-10-08 12:43:28 -0700354 for (const uint8_t* card_addr : cleared_cards_) {
Mathieu Chartier02e25112013-08-14 16:14:24 -0700355 auto start = reinterpret_cast<uintptr_t>(card_table->AddrFromCard(card_addr));
356 auto end = start + CardTable::kCardSize;
Mathieu Chartier590fee92013-09-13 13:46:47 -0700357 os << reinterpret_cast<void*>(start) << "-" << reinterpret_cast<void*>(end) << "\n";
Ian Rogers1d54e732013-05-02 21:10:01 -0700358 }
359 os << "]";
360}
361
Mathieu Chartiere4cab172014-08-19 18:24:04 -0700362void ModUnionTableCardCache::SetCards() {
363 CardTable* card_table = heap_->GetCardTable();
Ian Rogers13735952014-10-08 12:43:28 -0700364 for (uint8_t* addr = space_->Begin(); addr < AlignUp(space_->End(), CardTable::kCardSize);
Mathieu Chartiere4cab172014-08-19 18:24:04 -0700365 addr += CardTable::kCardSize) {
366 cleared_cards_.insert(card_table->CardFromAddr(addr));
367 }
368}
369
370void ModUnionTableReferenceCache::SetCards() {
371}
372
Ian Rogers1d54e732013-05-02 21:10:01 -0700373} // namespace accounting
374} // namespace gc
375} // namespace art