Clear mod-union tables for immune spaces in PreZygoteFork am: 157084ac62
Original change: https://android-review.googlesource.com/c/platform/art/+/2390333
Change-Id: Idbeb93f7701a8da812e7df4006813adeb0f7d601
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
diff --git a/runtime/gc/collector/mark_compact-inl.h b/runtime/gc/collector/mark_compact-inl.h
index d6919aa..57517d5 100644
--- a/runtime/gc/collector/mark_compact-inl.h
+++ b/runtime/gc/collector/mark_compact-inl.h
@@ -276,7 +276,7 @@
stack_high_addr = reinterpret_cast<char*>(stack_low_addr) + self->GetStackSize();
}
if (root < stack_low_addr || root > stack_high_addr) {
- auto ret = updated_roots_.insert(root);
+ auto ret = updated_roots_->insert(root);
DCHECK(ret.second) << "root=" << root << " old_ref=" << old_ref
<< " stack_low_addr=" << stack_low_addr
<< " stack_high_addr=" << stack_high_addr;
diff --git a/runtime/gc/collector/mark_compact.cc b/runtime/gc/collector/mark_compact.cc
index c9b2ff4..f262b66 100644
--- a/runtime/gc/collector/mark_compact.cc
+++ b/runtime/gc/collector/mark_compact.cc
@@ -254,6 +254,9 @@
uffd_minor_fault_supported_(false),
minor_fault_initialized_(false),
map_linear_alloc_shared_(false) {
+ if (kIsDebugBuild) {
+ updated_roots_.reset(new std::unordered_set<void*>());
+ }
// TODO: Depending on how the bump-pointer space move is implemented. If we
// switch between two virtual memories each time, then we will have to
// initialize live_words_bitmap_ accordingly.
@@ -445,6 +448,28 @@
}
}
+void MarkCompact::MarkZygoteLargeObjects() {
+ Thread* self = thread_running_gc_;
+ DCHECK_EQ(self, Thread::Current());
+ space::LargeObjectSpace* const los = heap_->GetLargeObjectsSpace();
+ if (los != nullptr) {
+ // Pick the current live bitmap (mark bitmap if swapped).
+ accounting::LargeObjectBitmap* const live_bitmap = los->GetLiveBitmap();
+ accounting::LargeObjectBitmap* const mark_bitmap = los->GetMarkBitmap();
+ // Walk through all of the objects and explicitly mark the zygote ones so they don't get swept.
+ std::pair<uint8_t*, uint8_t*> range = los->GetBeginEndAtomic();
+ live_bitmap->VisitMarkedRange(reinterpret_cast<uintptr_t>(range.first),
+ reinterpret_cast<uintptr_t>(range.second),
+ [mark_bitmap, los, self](mirror::Object* obj)
+ REQUIRES(Locks::heap_bitmap_lock_)
+ REQUIRES_SHARED(Locks::mutator_lock_) {
+ if (los->IsZygoteLargeObject(self, obj)) {
+ mark_bitmap->Set(obj);
+ }
+ });
+ }
+}
+
void MarkCompact::InitializePhase() {
TimingLogger::ScopedTiming t(__FUNCTION__, GetTimings());
mark_stack_ = heap_->GetMarkStack();
@@ -3452,6 +3477,7 @@
DCHECK_EQ(thread_running_gc_, Thread::Current());
WriterMutexLock mu(thread_running_gc_, *Locks::heap_bitmap_lock_);
BindAndResetBitmaps();
+ MarkZygoteLargeObjects();
MarkRoots(
static_cast<VisitRootFlags>(kVisitRootFlagAllRoots | kVisitRootFlagStartLoggingNewRoots));
MarkReachableObjects();
@@ -3622,8 +3648,15 @@
<< " doesn't belong to any of the spaces and large object space doesn't exist";
accounting::LargeObjectBitmap* los_bitmap = heap_->GetLargeObjectsSpace()->GetMarkBitmap();
DCHECK(los_bitmap->HasAddress(obj));
- return kParallel ? !los_bitmap->AtomicTestAndSet(obj)
- : !los_bitmap->Set(obj);
+ if (kParallel) {
+ los_bitmap->AtomicTestAndSet(obj);
+ } else {
+ los_bitmap->Set(obj);
+ }
+ // We only have primitive arrays in large object space. So there is no
+ // reason to push into mark-stack.
+ DCHECK(obj->IsString() || (obj->IsArrayInstance() && !obj->IsObjectArray()));
+ return false;
}
}
@@ -3763,7 +3796,9 @@
}
CHECK(mark_stack_->IsEmpty()); // Ensure that the mark stack is empty.
mark_stack_->Reset();
- updated_roots_.clear();
+ if (kIsDebugBuild && updated_roots_.get() != nullptr) {
+ updated_roots_->clear();
+ }
class_after_obj_ordered_map_.clear();
delete[] moving_pages_status_;
linear_alloc_arenas_.clear();
diff --git a/runtime/gc/collector/mark_compact.h b/runtime/gc/collector/mark_compact.h
index 2a10bcd..febd70e 100644
--- a/runtime/gc/collector/mark_compact.h
+++ b/runtime/gc/collector/mark_compact.h
@@ -510,6 +510,9 @@
// the lowest-address obj is compacted.
void UpdateClassAfterObjMap();
+ void MarkZygoteLargeObjects() REQUIRES_SHARED(Locks::mutator_lock_)
+ REQUIRES(Locks::heap_bitmap_lock_);
+
// Buffers, one per worker thread + gc-thread, to be used when
// kObjPtrPoisoning == true as in that case we can't have the buffer on the
// stack. The first page of the buffer is assigned to
@@ -536,7 +539,7 @@
// GC-root is updated twice.
// TODO: Must be replaced with an efficient mechanism eventually. Or ensure
// that double updation doesn't happen in the first place.
- std::unordered_set<void*> updated_roots_;
+ std::unique_ptr<std::unordered_set<void*>> updated_roots_;
MemMap from_space_map_;
MemMap shadow_to_space_map_;
// Any array of live-bytes in logical chunks of kOffsetChunkSize size
diff --git a/runtime/gc/heap.cc b/runtime/gc/heap.cc
index b433623..e0b0ed5 100644
--- a/runtime/gc/heap.cc
+++ b/runtime/gc/heap.cc
@@ -2542,7 +2542,7 @@
new accounting::ModUnionTableCardCache("zygote space mod-union table", this, zygote_space_);
CHECK(mod_union_table != nullptr) << "Failed to create zygote space mod-union table";
- if (collector_type_ != kCollectorTypeCC) {
+ if (collector_type_ != kCollectorTypeCC && collector_type_ != kCollectorTypeCMC) {
// Set all the cards in the mod-union table since we don't know which objects contain references
// to large objects.
mod_union_table->SetCards();
@@ -2554,10 +2554,10 @@
mod_union_table->ProcessCards();
mod_union_table->ClearTable();
- // For CC we never collect zygote large objects. This means we do not need to set the cards for
- // the zygote mod-union table and we can also clear all of the existing image mod-union tables.
- // The existing mod-union tables are only for image spaces and may only reference zygote and
- // image objects.
+ // For CC and CMC we never collect zygote large objects. This means we do not need to set the
+ // cards for the zygote mod-union table and we can also clear all of the existing image
+ // mod-union tables. The existing mod-union tables are only for image spaces and may only
+ // reference zygote and image objects.
for (auto& pair : mod_union_tables_) {
CHECK(pair.first->IsImageSpace());
CHECK(!pair.first->AsImageSpace()->GetImageHeader().IsAppImage());