1*795d594fSAndroid Build Coastguard Worker /*
2*795d594fSAndroid Build Coastguard Worker * Copyright (C) 2013 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 #include "semi_space-inl.h"
18*795d594fSAndroid Build Coastguard Worker
19*795d594fSAndroid Build Coastguard Worker #include <climits>
20*795d594fSAndroid Build Coastguard Worker #include <functional>
21*795d594fSAndroid Build Coastguard Worker #include <numeric>
22*795d594fSAndroid Build Coastguard Worker #include <sstream>
23*795d594fSAndroid Build Coastguard Worker #include <vector>
24*795d594fSAndroid Build Coastguard Worker
25*795d594fSAndroid Build Coastguard Worker #include "base/logging.h" // For VLOG.
26*795d594fSAndroid Build Coastguard Worker #include "base/macros.h"
27*795d594fSAndroid Build Coastguard Worker #include "base/mutex-inl.h"
28*795d594fSAndroid Build Coastguard Worker #include "base/timing_logger.h"
29*795d594fSAndroid Build Coastguard Worker #include "gc/accounting/heap_bitmap-inl.h"
30*795d594fSAndroid Build Coastguard Worker #include "gc/accounting/mod_union_table.h"
31*795d594fSAndroid Build Coastguard Worker #include "gc/accounting/remembered_set.h"
32*795d594fSAndroid Build Coastguard Worker #include "gc/accounting/space_bitmap-inl.h"
33*795d594fSAndroid Build Coastguard Worker #include "gc/heap.h"
34*795d594fSAndroid Build Coastguard Worker #include "gc/reference_processor.h"
35*795d594fSAndroid Build Coastguard Worker #include "gc/space/bump_pointer_space-inl.h"
36*795d594fSAndroid Build Coastguard Worker #include "gc/space/bump_pointer_space.h"
37*795d594fSAndroid Build Coastguard Worker #include "gc/space/image_space.h"
38*795d594fSAndroid Build Coastguard Worker #include "gc/space/large_object_space.h"
39*795d594fSAndroid Build Coastguard Worker #include "gc/space/space-inl.h"
40*795d594fSAndroid Build Coastguard Worker #include "indirect_reference_table.h"
41*795d594fSAndroid Build Coastguard Worker #include "intern_table.h"
42*795d594fSAndroid Build Coastguard Worker #include "jni/jni_internal.h"
43*795d594fSAndroid Build Coastguard Worker #include "mark_sweep-inl.h"
44*795d594fSAndroid Build Coastguard Worker #include "mirror/object-inl.h"
45*795d594fSAndroid Build Coastguard Worker #include "mirror/object-refvisitor-inl.h"
46*795d594fSAndroid Build Coastguard Worker #include "mirror/reference-inl.h"
47*795d594fSAndroid Build Coastguard Worker #include "monitor.h"
48*795d594fSAndroid Build Coastguard Worker #include "runtime.h"
49*795d594fSAndroid Build Coastguard Worker #include "thread-inl.h"
50*795d594fSAndroid Build Coastguard Worker #include "thread_list.h"
51*795d594fSAndroid Build Coastguard Worker #include "write_barrier-inl.h"
52*795d594fSAndroid Build Coastguard Worker
53*795d594fSAndroid Build Coastguard Worker using ::art::mirror::Object;
54*795d594fSAndroid Build Coastguard Worker
55*795d594fSAndroid Build Coastguard Worker namespace art HIDDEN {
56*795d594fSAndroid Build Coastguard Worker namespace gc {
57*795d594fSAndroid Build Coastguard Worker namespace collector {
58*795d594fSAndroid Build Coastguard Worker
59*795d594fSAndroid Build Coastguard Worker static constexpr bool kProtectFromSpace = true;
60*795d594fSAndroid Build Coastguard Worker static constexpr bool kStoreStackTraces = false;
61*795d594fSAndroid Build Coastguard Worker
BindBitmaps()62*795d594fSAndroid Build Coastguard Worker void SemiSpace::BindBitmaps() {
63*795d594fSAndroid Build Coastguard Worker TimingLogger::ScopedTiming t(__FUNCTION__, GetTimings());
64*795d594fSAndroid Build Coastguard Worker WriterMutexLock mu(self_, *Locks::heap_bitmap_lock_);
65*795d594fSAndroid Build Coastguard Worker // Mark all of the spaces we never collect as immune.
66*795d594fSAndroid Build Coastguard Worker for (const auto& space : GetHeap()->GetContinuousSpaces()) {
67*795d594fSAndroid Build Coastguard Worker if (space->GetGcRetentionPolicy() == space::kGcRetentionPolicyNeverCollect ||
68*795d594fSAndroid Build Coastguard Worker space->GetGcRetentionPolicy() == space::kGcRetentionPolicyFullCollect) {
69*795d594fSAndroid Build Coastguard Worker immune_spaces_.AddSpace(space);
70*795d594fSAndroid Build Coastguard Worker } else if (space->GetLiveBitmap() != nullptr) {
71*795d594fSAndroid Build Coastguard Worker // TODO: We can probably also add this space to the immune region.
72*795d594fSAndroid Build Coastguard Worker if (space == to_space_) {
73*795d594fSAndroid Build Coastguard Worker CHECK(space->IsContinuousMemMapAllocSpace());
74*795d594fSAndroid Build Coastguard Worker space->AsContinuousMemMapAllocSpace()->BindLiveToMarkBitmap();
75*795d594fSAndroid Build Coastguard Worker }
76*795d594fSAndroid Build Coastguard Worker }
77*795d594fSAndroid Build Coastguard Worker }
78*795d594fSAndroid Build Coastguard Worker }
79*795d594fSAndroid Build Coastguard Worker
SemiSpace(Heap * heap,const std::string & name_prefix)80*795d594fSAndroid Build Coastguard Worker SemiSpace::SemiSpace(Heap* heap, const std::string& name_prefix)
81*795d594fSAndroid Build Coastguard Worker : GarbageCollector(heap,
82*795d594fSAndroid Build Coastguard Worker name_prefix + (name_prefix.empty() ? "" : " ") + "semispace"),
83*795d594fSAndroid Build Coastguard Worker mark_stack_(nullptr),
84*795d594fSAndroid Build Coastguard Worker to_space_(nullptr),
85*795d594fSAndroid Build Coastguard Worker to_space_live_bitmap_(nullptr),
86*795d594fSAndroid Build Coastguard Worker from_space_(nullptr),
87*795d594fSAndroid Build Coastguard Worker mark_bitmap_(nullptr),
88*795d594fSAndroid Build Coastguard Worker self_(nullptr),
89*795d594fSAndroid Build Coastguard Worker fallback_space_(nullptr),
90*795d594fSAndroid Build Coastguard Worker bytes_moved_(0U),
91*795d594fSAndroid Build Coastguard Worker objects_moved_(0U),
92*795d594fSAndroid Build Coastguard Worker saved_bytes_(0U),
93*795d594fSAndroid Build Coastguard Worker collector_name_(name_),
94*795d594fSAndroid Build Coastguard Worker swap_semi_spaces_(true) {
95*795d594fSAndroid Build Coastguard Worker }
96*795d594fSAndroid Build Coastguard Worker
RunPhases()97*795d594fSAndroid Build Coastguard Worker void SemiSpace::RunPhases() {
98*795d594fSAndroid Build Coastguard Worker Thread* self = Thread::Current();
99*795d594fSAndroid Build Coastguard Worker InitializePhase();
100*795d594fSAndroid Build Coastguard Worker // Semi-space collector is special since it is sometimes called with the mutators suspended
101*795d594fSAndroid Build Coastguard Worker // during the zygote creation and collector transitions. If we already exclusively hold the
102*795d594fSAndroid Build Coastguard Worker // mutator lock, then we can't lock it again since it will cause a deadlock.
103*795d594fSAndroid Build Coastguard Worker if (Locks::mutator_lock_->IsExclusiveHeld(self)) {
104*795d594fSAndroid Build Coastguard Worker GetHeap()->PreGcVerificationPaused(this);
105*795d594fSAndroid Build Coastguard Worker GetHeap()->PrePauseRosAllocVerification(this);
106*795d594fSAndroid Build Coastguard Worker MarkingPhase();
107*795d594fSAndroid Build Coastguard Worker ReclaimPhase();
108*795d594fSAndroid Build Coastguard Worker GetHeap()->PostGcVerificationPaused(this);
109*795d594fSAndroid Build Coastguard Worker } else {
110*795d594fSAndroid Build Coastguard Worker Locks::mutator_lock_->AssertNotHeld(self);
111*795d594fSAndroid Build Coastguard Worker {
112*795d594fSAndroid Build Coastguard Worker ScopedPause pause(this);
113*795d594fSAndroid Build Coastguard Worker GetHeap()->PreGcVerificationPaused(this);
114*795d594fSAndroid Build Coastguard Worker GetHeap()->PrePauseRosAllocVerification(this);
115*795d594fSAndroid Build Coastguard Worker MarkingPhase();
116*795d594fSAndroid Build Coastguard Worker }
117*795d594fSAndroid Build Coastguard Worker {
118*795d594fSAndroid Build Coastguard Worker ReaderMutexLock mu(self, *Locks::mutator_lock_);
119*795d594fSAndroid Build Coastguard Worker ReclaimPhase();
120*795d594fSAndroid Build Coastguard Worker }
121*795d594fSAndroid Build Coastguard Worker GetHeap()->PostGcVerification(this);
122*795d594fSAndroid Build Coastguard Worker }
123*795d594fSAndroid Build Coastguard Worker FinishPhase();
124*795d594fSAndroid Build Coastguard Worker }
125*795d594fSAndroid Build Coastguard Worker
InitializePhase()126*795d594fSAndroid Build Coastguard Worker void SemiSpace::InitializePhase() {
127*795d594fSAndroid Build Coastguard Worker TimingLogger::ScopedTiming t(__FUNCTION__, GetTimings());
128*795d594fSAndroid Build Coastguard Worker mark_stack_ = heap_->GetMarkStack();
129*795d594fSAndroid Build Coastguard Worker DCHECK(mark_stack_ != nullptr);
130*795d594fSAndroid Build Coastguard Worker immune_spaces_.Reset();
131*795d594fSAndroid Build Coastguard Worker saved_bytes_ = 0;
132*795d594fSAndroid Build Coastguard Worker bytes_moved_ = 0;
133*795d594fSAndroid Build Coastguard Worker objects_moved_ = 0;
134*795d594fSAndroid Build Coastguard Worker self_ = Thread::Current();
135*795d594fSAndroid Build Coastguard Worker CHECK(from_space_->CanMoveObjects()) << "Attempting to move from " << *from_space_;
136*795d594fSAndroid Build Coastguard Worker // Set the initial bitmap.
137*795d594fSAndroid Build Coastguard Worker to_space_live_bitmap_ = to_space_->GetLiveBitmap();
138*795d594fSAndroid Build Coastguard Worker {
139*795d594fSAndroid Build Coastguard Worker // TODO: I don't think we should need heap bitmap lock to Get the mark bitmap.
140*795d594fSAndroid Build Coastguard Worker ReaderMutexLock mu(Thread::Current(), *Locks::heap_bitmap_lock_);
141*795d594fSAndroid Build Coastguard Worker mark_bitmap_ = heap_->GetMarkBitmap();
142*795d594fSAndroid Build Coastguard Worker }
143*795d594fSAndroid Build Coastguard Worker fallback_space_ = GetHeap()->GetNonMovingSpace();
144*795d594fSAndroid Build Coastguard Worker }
145*795d594fSAndroid Build Coastguard Worker
ProcessReferences(Thread * self)146*795d594fSAndroid Build Coastguard Worker void SemiSpace::ProcessReferences(Thread* self) {
147*795d594fSAndroid Build Coastguard Worker WriterMutexLock mu(self, *Locks::heap_bitmap_lock_);
148*795d594fSAndroid Build Coastguard Worker ReferenceProcessor* rp = GetHeap()->GetReferenceProcessor();
149*795d594fSAndroid Build Coastguard Worker rp->Setup(self, this, /*concurrent=*/false, GetCurrentIteration()->GetClearSoftReferences());
150*795d594fSAndroid Build Coastguard Worker rp->ProcessReferences(self, GetTimings());
151*795d594fSAndroid Build Coastguard Worker }
152*795d594fSAndroid Build Coastguard Worker
MarkingPhase()153*795d594fSAndroid Build Coastguard Worker void SemiSpace::MarkingPhase() {
154*795d594fSAndroid Build Coastguard Worker TimingLogger::ScopedTiming t(__FUNCTION__, GetTimings());
155*795d594fSAndroid Build Coastguard Worker CHECK(Locks::mutator_lock_->IsExclusiveHeld(self_));
156*795d594fSAndroid Build Coastguard Worker if (kStoreStackTraces) {
157*795d594fSAndroid Build Coastguard Worker Locks::mutator_lock_->AssertExclusiveHeld(self_);
158*795d594fSAndroid Build Coastguard Worker // Store the stack traces into the runtime fault string in case we Get a heap corruption
159*795d594fSAndroid Build Coastguard Worker // related crash later.
160*795d594fSAndroid Build Coastguard Worker ThreadState old_state = self_->SetStateUnsafe(ThreadState::kRunnable);
161*795d594fSAndroid Build Coastguard Worker std::ostringstream oss;
162*795d594fSAndroid Build Coastguard Worker Runtime* runtime = Runtime::Current();
163*795d594fSAndroid Build Coastguard Worker runtime->GetThreadList()->DumpForSigQuit(oss);
164*795d594fSAndroid Build Coastguard Worker runtime->GetThreadList()->DumpNativeStacks(oss);
165*795d594fSAndroid Build Coastguard Worker runtime->SetFaultMessage(oss.str());
166*795d594fSAndroid Build Coastguard Worker CHECK_EQ(self_->SetStateUnsafe(old_state), ThreadState::kRunnable);
167*795d594fSAndroid Build Coastguard Worker }
168*795d594fSAndroid Build Coastguard Worker // Revoke the thread local buffers since the GC may allocate into a RosAllocSpace and this helps
169*795d594fSAndroid Build Coastguard Worker // to prevent fragmentation.
170*795d594fSAndroid Build Coastguard Worker RevokeAllThreadLocalBuffers();
171*795d594fSAndroid Build Coastguard Worker
172*795d594fSAndroid Build Coastguard Worker // Always clear soft references.
173*795d594fSAndroid Build Coastguard Worker GetCurrentIteration()->SetClearSoftReferences(true);
174*795d594fSAndroid Build Coastguard Worker Locks::mutator_lock_->AssertExclusiveHeld(self_);
175*795d594fSAndroid Build Coastguard Worker // Assume the cleared space is already empty.
176*795d594fSAndroid Build Coastguard Worker BindBitmaps();
177*795d594fSAndroid Build Coastguard Worker // Process dirty cards and add dirty cards to mod-union tables.
178*795d594fSAndroid Build Coastguard Worker heap_->ProcessCards(GetTimings(), /*use_rem_sets=*/false, false, true);
179*795d594fSAndroid Build Coastguard Worker // Clear the whole card table since we cannot get any additional dirty cards during the
180*795d594fSAndroid Build Coastguard Worker // paused GC. This saves memory but only works for pause the world collectors.
181*795d594fSAndroid Build Coastguard Worker t.NewTiming("ClearCardTable");
182*795d594fSAndroid Build Coastguard Worker heap_->GetCardTable()->ClearCardTable();
183*795d594fSAndroid Build Coastguard Worker // Need to do this before the checkpoint since we don't want any threads to add references to
184*795d594fSAndroid Build Coastguard Worker // the live stack during the recursive mark.
185*795d594fSAndroid Build Coastguard Worker if (kUseThreadLocalAllocationStack) {
186*795d594fSAndroid Build Coastguard Worker TimingLogger::ScopedTiming t2("RevokeAllThreadLocalAllocationStacks", GetTimings());
187*795d594fSAndroid Build Coastguard Worker heap_->RevokeAllThreadLocalAllocationStacks(self_);
188*795d594fSAndroid Build Coastguard Worker }
189*795d594fSAndroid Build Coastguard Worker heap_->SwapStacks();
190*795d594fSAndroid Build Coastguard Worker {
191*795d594fSAndroid Build Coastguard Worker WriterMutexLock mu(self_, *Locks::heap_bitmap_lock_);
192*795d594fSAndroid Build Coastguard Worker MarkRoots();
193*795d594fSAndroid Build Coastguard Worker // Recursively mark remaining objects.
194*795d594fSAndroid Build Coastguard Worker MarkReachableObjects();
195*795d594fSAndroid Build Coastguard Worker }
196*795d594fSAndroid Build Coastguard Worker ProcessReferences(self_);
197*795d594fSAndroid Build Coastguard Worker {
198*795d594fSAndroid Build Coastguard Worker ReaderMutexLock mu(self_, *Locks::heap_bitmap_lock_);
199*795d594fSAndroid Build Coastguard Worker SweepSystemWeaks();
200*795d594fSAndroid Build Coastguard Worker }
201*795d594fSAndroid Build Coastguard Worker Runtime::Current()->BroadcastForNewSystemWeaks();
202*795d594fSAndroid Build Coastguard Worker Runtime::Current()->GetClassLinker()->CleanupClassLoaders();
203*795d594fSAndroid Build Coastguard Worker // Revoke buffers before measuring how many objects were moved since the TLABs need to be revoked
204*795d594fSAndroid Build Coastguard Worker // before they are properly counted.
205*795d594fSAndroid Build Coastguard Worker RevokeAllThreadLocalBuffers();
206*795d594fSAndroid Build Coastguard Worker GetHeap()->RecordFreeRevoke(); // This is for the non-moving rosalloc space.
207*795d594fSAndroid Build Coastguard Worker // Record freed memory.
208*795d594fSAndroid Build Coastguard Worker const int64_t from_bytes = from_space_->GetBytesAllocated();
209*795d594fSAndroid Build Coastguard Worker const int64_t to_bytes = bytes_moved_;
210*795d594fSAndroid Build Coastguard Worker const uint64_t from_objects = from_space_->GetObjectsAllocated();
211*795d594fSAndroid Build Coastguard Worker const uint64_t to_objects = objects_moved_;
212*795d594fSAndroid Build Coastguard Worker // Note: Freed bytes can be negative if we copy form a compacted space to a free-list backed
213*795d594fSAndroid Build Coastguard Worker // space.
214*795d594fSAndroid Build Coastguard Worker RecordFree(ObjectBytePair(from_objects - to_objects, from_bytes - to_bytes));
215*795d594fSAndroid Build Coastguard Worker // Clear and protect the from space.
216*795d594fSAndroid Build Coastguard Worker from_space_->Clear();
217*795d594fSAndroid Build Coastguard Worker // b/31172841. Temporarily disable the from-space protection with host debug build
218*795d594fSAndroid Build Coastguard Worker // due to some protection issue in the build server.
219*795d594fSAndroid Build Coastguard Worker if (kProtectFromSpace && !(kIsDebugBuild && !kIsTargetBuild)) {
220*795d594fSAndroid Build Coastguard Worker if (!from_space_->IsRosAllocSpace()) {
221*795d594fSAndroid Build Coastguard Worker // Protect with PROT_NONE.
222*795d594fSAndroid Build Coastguard Worker VLOG(heap) << "Protecting from_space_ : " << *from_space_;
223*795d594fSAndroid Build Coastguard Worker from_space_->GetMemMap()->Protect(PROT_NONE);
224*795d594fSAndroid Build Coastguard Worker } else {
225*795d594fSAndroid Build Coastguard Worker // If RosAllocSpace, we'll leave it as PROT_READ here so the
226*795d594fSAndroid Build Coastguard Worker // rosaloc verification can read the metadata magic number and
227*795d594fSAndroid Build Coastguard Worker // protect it with PROT_NONE later in FinishPhase().
228*795d594fSAndroid Build Coastguard Worker VLOG(heap) << "Protecting from_space_ with PROT_READ : " << *from_space_;
229*795d594fSAndroid Build Coastguard Worker from_space_->GetMemMap()->Protect(PROT_READ);
230*795d594fSAndroid Build Coastguard Worker }
231*795d594fSAndroid Build Coastguard Worker }
232*795d594fSAndroid Build Coastguard Worker heap_->PreSweepingGcVerification(this);
233*795d594fSAndroid Build Coastguard Worker if (swap_semi_spaces_) {
234*795d594fSAndroid Build Coastguard Worker heap_->SwapSemiSpaces();
235*795d594fSAndroid Build Coastguard Worker }
236*795d594fSAndroid Build Coastguard Worker }
237*795d594fSAndroid Build Coastguard Worker
238*795d594fSAndroid Build Coastguard Worker // Used to verify that there's no references to the from-space.
239*795d594fSAndroid Build Coastguard Worker class SemiSpace::VerifyNoFromSpaceReferencesVisitor {
240*795d594fSAndroid Build Coastguard Worker public:
VerifyNoFromSpaceReferencesVisitor(space::ContinuousMemMapAllocSpace * from_space)241*795d594fSAndroid Build Coastguard Worker explicit VerifyNoFromSpaceReferencesVisitor(space::ContinuousMemMapAllocSpace* from_space)
242*795d594fSAndroid Build Coastguard Worker : from_space_(from_space) {}
243*795d594fSAndroid Build Coastguard Worker
operator ()(Object * obj,MemberOffset offset,bool) const244*795d594fSAndroid Build Coastguard Worker void operator()(Object* obj, MemberOffset offset, bool /* is_static */) const
245*795d594fSAndroid Build Coastguard Worker REQUIRES_SHARED(Locks::mutator_lock_) ALWAYS_INLINE {
246*795d594fSAndroid Build Coastguard Worker mirror::Object* ref = obj->GetFieldObject<mirror::Object>(offset);
247*795d594fSAndroid Build Coastguard Worker if (from_space_->HasAddress(ref)) {
248*795d594fSAndroid Build Coastguard Worker LOG(FATAL) << ref << " found in from space";
249*795d594fSAndroid Build Coastguard Worker }
250*795d594fSAndroid Build Coastguard Worker }
251*795d594fSAndroid Build Coastguard Worker
252*795d594fSAndroid Build Coastguard Worker // TODO: Remove NO_THREAD_SAFETY_ANALYSIS when clang better understands visitors.
VisitRootIfNonNull(mirror::CompressedReference<mirror::Object> * root) const253*795d594fSAndroid Build Coastguard Worker void VisitRootIfNonNull(mirror::CompressedReference<mirror::Object>* root) const
254*795d594fSAndroid Build Coastguard Worker NO_THREAD_SAFETY_ANALYSIS {
255*795d594fSAndroid Build Coastguard Worker if (!root->IsNull()) {
256*795d594fSAndroid Build Coastguard Worker VisitRoot(root);
257*795d594fSAndroid Build Coastguard Worker }
258*795d594fSAndroid Build Coastguard Worker }
259*795d594fSAndroid Build Coastguard Worker
VisitRoot(mirror::CompressedReference<mirror::Object> * root) const260*795d594fSAndroid Build Coastguard Worker void VisitRoot(mirror::CompressedReference<mirror::Object>* root) const
261*795d594fSAndroid Build Coastguard Worker NO_THREAD_SAFETY_ANALYSIS {
262*795d594fSAndroid Build Coastguard Worker if (kIsDebugBuild) {
263*795d594fSAndroid Build Coastguard Worker Locks::mutator_lock_->AssertExclusiveHeld(Thread::Current());
264*795d594fSAndroid Build Coastguard Worker Locks::heap_bitmap_lock_->AssertExclusiveHeld(Thread::Current());
265*795d594fSAndroid Build Coastguard Worker }
266*795d594fSAndroid Build Coastguard Worker CHECK(!from_space_->HasAddress(root->AsMirrorPtr()));
267*795d594fSAndroid Build Coastguard Worker }
268*795d594fSAndroid Build Coastguard Worker
269*795d594fSAndroid Build Coastguard Worker private:
270*795d594fSAndroid Build Coastguard Worker space::ContinuousMemMapAllocSpace* const from_space_;
271*795d594fSAndroid Build Coastguard Worker };
272*795d594fSAndroid Build Coastguard Worker
VerifyNoFromSpaceReferences(Object * obj)273*795d594fSAndroid Build Coastguard Worker void SemiSpace::VerifyNoFromSpaceReferences(Object* obj) {
274*795d594fSAndroid Build Coastguard Worker DCHECK(!from_space_->HasAddress(obj)) << "Scanning object " << obj << " in from space";
275*795d594fSAndroid Build Coastguard Worker VerifyNoFromSpaceReferencesVisitor visitor(from_space_);
276*795d594fSAndroid Build Coastguard Worker obj->VisitReferences(visitor, VoidFunctor());
277*795d594fSAndroid Build Coastguard Worker }
278*795d594fSAndroid Build Coastguard Worker
MarkReachableObjects()279*795d594fSAndroid Build Coastguard Worker void SemiSpace::MarkReachableObjects() {
280*795d594fSAndroid Build Coastguard Worker TimingLogger::ScopedTiming t(__FUNCTION__, GetTimings());
281*795d594fSAndroid Build Coastguard Worker {
282*795d594fSAndroid Build Coastguard Worker TimingLogger::ScopedTiming t2("MarkStackAsLive", GetTimings());
283*795d594fSAndroid Build Coastguard Worker accounting::ObjectStack* live_stack = heap_->GetLiveStack();
284*795d594fSAndroid Build Coastguard Worker heap_->MarkAllocStackAsLive(live_stack);
285*795d594fSAndroid Build Coastguard Worker live_stack->Reset();
286*795d594fSAndroid Build Coastguard Worker }
287*795d594fSAndroid Build Coastguard Worker for (auto& space : heap_->GetContinuousSpaces()) {
288*795d594fSAndroid Build Coastguard Worker // If the space is immune then we need to mark the references to other spaces.
289*795d594fSAndroid Build Coastguard Worker accounting::ModUnionTable* table = heap_->FindModUnionTableFromSpace(space);
290*795d594fSAndroid Build Coastguard Worker if (table != nullptr) {
291*795d594fSAndroid Build Coastguard Worker // TODO: Improve naming.
292*795d594fSAndroid Build Coastguard Worker TimingLogger::ScopedTiming t2(
293*795d594fSAndroid Build Coastguard Worker space->IsZygoteSpace() ? "UpdateAndMarkZygoteModUnionTable" :
294*795d594fSAndroid Build Coastguard Worker "UpdateAndMarkImageModUnionTable",
295*795d594fSAndroid Build Coastguard Worker GetTimings());
296*795d594fSAndroid Build Coastguard Worker table->UpdateAndMarkReferences(this);
297*795d594fSAndroid Build Coastguard Worker DCHECK(GetHeap()->FindRememberedSetFromSpace(space) == nullptr);
298*795d594fSAndroid Build Coastguard Worker } else if (space->IsImageSpace() && space->GetLiveBitmap() != nullptr) {
299*795d594fSAndroid Build Coastguard Worker // If the space has no mod union table (the non-moving space, app image spaces, main spaces
300*795d594fSAndroid Build Coastguard Worker // when the bump pointer space only collection is enabled,) then we need to scan its live
301*795d594fSAndroid Build Coastguard Worker // bitmap or dirty cards as roots (including the objects on the live stack which have just
302*795d594fSAndroid Build Coastguard Worker // marked in the live bitmap above in MarkAllocStackAsLive().)
303*795d594fSAndroid Build Coastguard Worker accounting::RememberedSet* rem_set = GetHeap()->FindRememberedSetFromSpace(space);
304*795d594fSAndroid Build Coastguard Worker if (!space->IsImageSpace()) {
305*795d594fSAndroid Build Coastguard Worker DCHECK(space == heap_->GetNonMovingSpace() || space == heap_->GetPrimaryFreeListSpace())
306*795d594fSAndroid Build Coastguard Worker << "Space " << space->GetName();
307*795d594fSAndroid Build Coastguard Worker // App images currently do not have remembered sets.
308*795d594fSAndroid Build Coastguard Worker } else {
309*795d594fSAndroid Build Coastguard Worker DCHECK(rem_set == nullptr);
310*795d594fSAndroid Build Coastguard Worker }
311*795d594fSAndroid Build Coastguard Worker if (rem_set != nullptr) {
312*795d594fSAndroid Build Coastguard Worker TimingLogger::ScopedTiming t2("UpdateAndMarkRememberedSet", GetTimings());
313*795d594fSAndroid Build Coastguard Worker rem_set->UpdateAndMarkReferences(from_space_, this);
314*795d594fSAndroid Build Coastguard Worker } else {
315*795d594fSAndroid Build Coastguard Worker TimingLogger::ScopedTiming t2("VisitLiveBits", GetTimings());
316*795d594fSAndroid Build Coastguard Worker accounting::ContinuousSpaceBitmap* live_bitmap = space->GetLiveBitmap();
317*795d594fSAndroid Build Coastguard Worker live_bitmap->VisitMarkedRange(reinterpret_cast<uintptr_t>(space->Begin()),
318*795d594fSAndroid Build Coastguard Worker reinterpret_cast<uintptr_t>(space->End()),
319*795d594fSAndroid Build Coastguard Worker [this](mirror::Object* obj)
320*795d594fSAndroid Build Coastguard Worker REQUIRES(Locks::mutator_lock_, Locks::heap_bitmap_lock_) {
321*795d594fSAndroid Build Coastguard Worker ScanObject(obj);
322*795d594fSAndroid Build Coastguard Worker });
323*795d594fSAndroid Build Coastguard Worker }
324*795d594fSAndroid Build Coastguard Worker if (kIsDebugBuild) {
325*795d594fSAndroid Build Coastguard Worker // Verify that there are no from-space references that
326*795d594fSAndroid Build Coastguard Worker // remain in the space, that is, the remembered set (and the
327*795d594fSAndroid Build Coastguard Worker // card table) didn't miss any from-space references in the
328*795d594fSAndroid Build Coastguard Worker // space.
329*795d594fSAndroid Build Coastguard Worker accounting::ContinuousSpaceBitmap* live_bitmap = space->GetLiveBitmap();
330*795d594fSAndroid Build Coastguard Worker live_bitmap->VisitMarkedRange(reinterpret_cast<uintptr_t>(space->Begin()),
331*795d594fSAndroid Build Coastguard Worker reinterpret_cast<uintptr_t>(space->End()),
332*795d594fSAndroid Build Coastguard Worker [this](Object* obj)
333*795d594fSAndroid Build Coastguard Worker REQUIRES_SHARED(Locks::heap_bitmap_lock_, Locks::mutator_lock_) {
334*795d594fSAndroid Build Coastguard Worker DCHECK(obj != nullptr);
335*795d594fSAndroid Build Coastguard Worker VerifyNoFromSpaceReferences(obj);
336*795d594fSAndroid Build Coastguard Worker });
337*795d594fSAndroid Build Coastguard Worker }
338*795d594fSAndroid Build Coastguard Worker }
339*795d594fSAndroid Build Coastguard Worker }
340*795d594fSAndroid Build Coastguard Worker // Recursively process the mark stack.
341*795d594fSAndroid Build Coastguard Worker ProcessMarkStack();
342*795d594fSAndroid Build Coastguard Worker }
343*795d594fSAndroid Build Coastguard Worker
ReclaimPhase()344*795d594fSAndroid Build Coastguard Worker void SemiSpace::ReclaimPhase() {
345*795d594fSAndroid Build Coastguard Worker TimingLogger::ScopedTiming t(__FUNCTION__, GetTimings());
346*795d594fSAndroid Build Coastguard Worker WriterMutexLock mu(self_, *Locks::heap_bitmap_lock_);
347*795d594fSAndroid Build Coastguard Worker // Reclaim unmarked objects.
348*795d594fSAndroid Build Coastguard Worker Sweep(false);
349*795d594fSAndroid Build Coastguard Worker // Swap the live and mark bitmaps for each space which we modified space. This is an
350*795d594fSAndroid Build Coastguard Worker // optimization that enables us to not clear live bits inside of the sweep. Only swaps unbound
351*795d594fSAndroid Build Coastguard Worker // bitmaps.
352*795d594fSAndroid Build Coastguard Worker SwapBitmaps();
353*795d594fSAndroid Build Coastguard Worker // Unbind the live and mark bitmaps.
354*795d594fSAndroid Build Coastguard Worker GetHeap()->UnBindBitmaps();
355*795d594fSAndroid Build Coastguard Worker if (saved_bytes_ > 0) {
356*795d594fSAndroid Build Coastguard Worker VLOG(heap) << "Avoided dirtying " << PrettySize(saved_bytes_);
357*795d594fSAndroid Build Coastguard Worker }
358*795d594fSAndroid Build Coastguard Worker }
359*795d594fSAndroid Build Coastguard Worker
ResizeMarkStack(size_t new_size)360*795d594fSAndroid Build Coastguard Worker void SemiSpace::ResizeMarkStack(size_t new_size) {
361*795d594fSAndroid Build Coastguard Worker std::vector<StackReference<Object>> temp(mark_stack_->Begin(), mark_stack_->End());
362*795d594fSAndroid Build Coastguard Worker CHECK_LE(mark_stack_->Size(), new_size);
363*795d594fSAndroid Build Coastguard Worker mark_stack_->Resize(new_size);
364*795d594fSAndroid Build Coastguard Worker for (auto& obj : temp) {
365*795d594fSAndroid Build Coastguard Worker mark_stack_->PushBack(obj.AsMirrorPtr());
366*795d594fSAndroid Build Coastguard Worker }
367*795d594fSAndroid Build Coastguard Worker }
368*795d594fSAndroid Build Coastguard Worker
MarkStackPush(Object * obj)369*795d594fSAndroid Build Coastguard Worker inline void SemiSpace::MarkStackPush(Object* obj) {
370*795d594fSAndroid Build Coastguard Worker if (UNLIKELY(mark_stack_->Size() >= mark_stack_->Capacity())) {
371*795d594fSAndroid Build Coastguard Worker ResizeMarkStack(mark_stack_->Capacity() * 2);
372*795d594fSAndroid Build Coastguard Worker }
373*795d594fSAndroid Build Coastguard Worker // The object must be pushed on to the mark stack.
374*795d594fSAndroid Build Coastguard Worker mark_stack_->PushBack(obj);
375*795d594fSAndroid Build Coastguard Worker }
376*795d594fSAndroid Build Coastguard Worker
CopyAvoidingDirtyingPages(void * dest,const void * src,size_t size)377*795d594fSAndroid Build Coastguard Worker static inline size_t CopyAvoidingDirtyingPages(void* dest, const void* src, size_t size) {
378*795d594fSAndroid Build Coastguard Worker if (LIKELY(size <= static_cast<size_t>(gPageSize))) {
379*795d594fSAndroid Build Coastguard Worker // We will dirty the current page and somewhere in the middle of the next page. This means
380*795d594fSAndroid Build Coastguard Worker // that the next object copied will also dirty that page.
381*795d594fSAndroid Build Coastguard Worker // TODO: Worth considering the last object copied? We may end up dirtying one page which is
382*795d594fSAndroid Build Coastguard Worker // not necessary per GC.
383*795d594fSAndroid Build Coastguard Worker memcpy(dest, src, size);
384*795d594fSAndroid Build Coastguard Worker return 0;
385*795d594fSAndroid Build Coastguard Worker }
386*795d594fSAndroid Build Coastguard Worker size_t saved_bytes = 0;
387*795d594fSAndroid Build Coastguard Worker uint8_t* byte_dest = reinterpret_cast<uint8_t*>(dest);
388*795d594fSAndroid Build Coastguard Worker if (kIsDebugBuild) {
389*795d594fSAndroid Build Coastguard Worker for (size_t i = 0; i < size; ++i) {
390*795d594fSAndroid Build Coastguard Worker CHECK_EQ(byte_dest[i], 0U);
391*795d594fSAndroid Build Coastguard Worker }
392*795d594fSAndroid Build Coastguard Worker }
393*795d594fSAndroid Build Coastguard Worker // Process the start of the page. The page must already be dirty, don't bother with checking.
394*795d594fSAndroid Build Coastguard Worker const uint8_t* byte_src = reinterpret_cast<const uint8_t*>(src);
395*795d594fSAndroid Build Coastguard Worker const uint8_t* limit = byte_src + size;
396*795d594fSAndroid Build Coastguard Worker size_t page_remain = AlignUp(byte_dest, gPageSize) - byte_dest;
397*795d594fSAndroid Build Coastguard Worker // Copy the bytes until the start of the next page.
398*795d594fSAndroid Build Coastguard Worker memcpy(dest, src, page_remain);
399*795d594fSAndroid Build Coastguard Worker byte_src += page_remain;
400*795d594fSAndroid Build Coastguard Worker byte_dest += page_remain;
401*795d594fSAndroid Build Coastguard Worker DCHECK_ALIGNED_PARAM(reinterpret_cast<uintptr_t>(byte_dest), gPageSize);
402*795d594fSAndroid Build Coastguard Worker DCHECK_ALIGNED(reinterpret_cast<uintptr_t>(byte_dest), sizeof(uintptr_t));
403*795d594fSAndroid Build Coastguard Worker DCHECK_ALIGNED(reinterpret_cast<uintptr_t>(byte_src), sizeof(uintptr_t));
404*795d594fSAndroid Build Coastguard Worker while (byte_src + gPageSize < limit) {
405*795d594fSAndroid Build Coastguard Worker bool all_zero = true;
406*795d594fSAndroid Build Coastguard Worker uintptr_t* word_dest = reinterpret_cast<uintptr_t*>(byte_dest);
407*795d594fSAndroid Build Coastguard Worker const uintptr_t* word_src = reinterpret_cast<const uintptr_t*>(byte_src);
408*795d594fSAndroid Build Coastguard Worker for (size_t i = 0; i < gPageSize / sizeof(*word_src); ++i) {
409*795d594fSAndroid Build Coastguard Worker // Assumes the destination of the copy is all zeros.
410*795d594fSAndroid Build Coastguard Worker if (word_src[i] != 0) {
411*795d594fSAndroid Build Coastguard Worker all_zero = false;
412*795d594fSAndroid Build Coastguard Worker word_dest[i] = word_src[i];
413*795d594fSAndroid Build Coastguard Worker }
414*795d594fSAndroid Build Coastguard Worker }
415*795d594fSAndroid Build Coastguard Worker if (all_zero) {
416*795d594fSAndroid Build Coastguard Worker // Avoided copying into the page since it was all zeros.
417*795d594fSAndroid Build Coastguard Worker saved_bytes += gPageSize;
418*795d594fSAndroid Build Coastguard Worker }
419*795d594fSAndroid Build Coastguard Worker byte_src += gPageSize;
420*795d594fSAndroid Build Coastguard Worker byte_dest += gPageSize;
421*795d594fSAndroid Build Coastguard Worker }
422*795d594fSAndroid Build Coastguard Worker // Handle the part of the page at the end.
423*795d594fSAndroid Build Coastguard Worker memcpy(byte_dest, byte_src, limit - byte_src);
424*795d594fSAndroid Build Coastguard Worker return saved_bytes;
425*795d594fSAndroid Build Coastguard Worker }
426*795d594fSAndroid Build Coastguard Worker
MarkNonForwardedObject(mirror::Object * obj)427*795d594fSAndroid Build Coastguard Worker mirror::Object* SemiSpace::MarkNonForwardedObject(mirror::Object* obj) {
428*795d594fSAndroid Build Coastguard Worker const size_t object_size = obj->SizeOf();
429*795d594fSAndroid Build Coastguard Worker size_t bytes_allocated, unused_bytes_tl_bulk_allocated;
430*795d594fSAndroid Build Coastguard Worker // Copy it to the to-space.
431*795d594fSAndroid Build Coastguard Worker mirror::Object* forward_address = to_space_->AllocThreadUnsafe(
432*795d594fSAndroid Build Coastguard Worker self_, object_size, &bytes_allocated, nullptr, &unused_bytes_tl_bulk_allocated);
433*795d594fSAndroid Build Coastguard Worker
434*795d594fSAndroid Build Coastguard Worker if (forward_address != nullptr && to_space_live_bitmap_ != nullptr) {
435*795d594fSAndroid Build Coastguard Worker to_space_live_bitmap_->Set(forward_address);
436*795d594fSAndroid Build Coastguard Worker }
437*795d594fSAndroid Build Coastguard Worker // If it's still null, attempt to use the fallback space.
438*795d594fSAndroid Build Coastguard Worker if (UNLIKELY(forward_address == nullptr)) {
439*795d594fSAndroid Build Coastguard Worker forward_address = fallback_space_->AllocThreadUnsafe(
440*795d594fSAndroid Build Coastguard Worker self_, object_size, &bytes_allocated, nullptr, &unused_bytes_tl_bulk_allocated);
441*795d594fSAndroid Build Coastguard Worker CHECK(forward_address != nullptr) << "Out of memory in the to-space and fallback space.";
442*795d594fSAndroid Build Coastguard Worker accounting::ContinuousSpaceBitmap* bitmap = fallback_space_->GetLiveBitmap();
443*795d594fSAndroid Build Coastguard Worker if (bitmap != nullptr) {
444*795d594fSAndroid Build Coastguard Worker bitmap->Set(forward_address);
445*795d594fSAndroid Build Coastguard Worker }
446*795d594fSAndroid Build Coastguard Worker }
447*795d594fSAndroid Build Coastguard Worker ++objects_moved_;
448*795d594fSAndroid Build Coastguard Worker bytes_moved_ += bytes_allocated;
449*795d594fSAndroid Build Coastguard Worker // Copy over the object and add it to the mark stack since we still need to update its
450*795d594fSAndroid Build Coastguard Worker // references.
451*795d594fSAndroid Build Coastguard Worker saved_bytes_ +=
452*795d594fSAndroid Build Coastguard Worker CopyAvoidingDirtyingPages(reinterpret_cast<void*>(forward_address), obj, object_size);
453*795d594fSAndroid Build Coastguard Worker if (kUseBakerReadBarrier) {
454*795d594fSAndroid Build Coastguard Worker obj->AssertReadBarrierState();
455*795d594fSAndroid Build Coastguard Worker forward_address->AssertReadBarrierState();
456*795d594fSAndroid Build Coastguard Worker }
457*795d594fSAndroid Build Coastguard Worker DCHECK(to_space_->HasAddress(forward_address) || fallback_space_->HasAddress(forward_address))
458*795d594fSAndroid Build Coastguard Worker << forward_address << "\n" << GetHeap()->DumpSpaces();
459*795d594fSAndroid Build Coastguard Worker return forward_address;
460*795d594fSAndroid Build Coastguard Worker }
461*795d594fSAndroid Build Coastguard Worker
MarkObject(mirror::Object * root)462*795d594fSAndroid Build Coastguard Worker mirror::Object* SemiSpace::MarkObject(mirror::Object* root) {
463*795d594fSAndroid Build Coastguard Worker auto ref = StackReference<mirror::Object>::FromMirrorPtr(root);
464*795d594fSAndroid Build Coastguard Worker MarkObjectIfNotInToSpace(&ref);
465*795d594fSAndroid Build Coastguard Worker return ref.AsMirrorPtr();
466*795d594fSAndroid Build Coastguard Worker }
467*795d594fSAndroid Build Coastguard Worker
MarkHeapReference(mirror::HeapReference<mirror::Object> * obj_ptr,bool do_atomic_update)468*795d594fSAndroid Build Coastguard Worker void SemiSpace::MarkHeapReference(mirror::HeapReference<mirror::Object>* obj_ptr,
469*795d594fSAndroid Build Coastguard Worker [[maybe_unused]] bool do_atomic_update) {
470*795d594fSAndroid Build Coastguard Worker MarkObject(obj_ptr);
471*795d594fSAndroid Build Coastguard Worker }
472*795d594fSAndroid Build Coastguard Worker
VisitRoots(mirror::Object *** roots,size_t count,const RootInfo & info)473*795d594fSAndroid Build Coastguard Worker void SemiSpace::VisitRoots(mirror::Object*** roots,
474*795d594fSAndroid Build Coastguard Worker size_t count,
475*795d594fSAndroid Build Coastguard Worker [[maybe_unused]] const RootInfo& info) {
476*795d594fSAndroid Build Coastguard Worker for (size_t i = 0; i < count; ++i) {
477*795d594fSAndroid Build Coastguard Worker auto* root = roots[i];
478*795d594fSAndroid Build Coastguard Worker auto ref = StackReference<mirror::Object>::FromMirrorPtr(*root);
479*795d594fSAndroid Build Coastguard Worker // The root can be in the to-space since we may visit the declaring class of an ArtMethod
480*795d594fSAndroid Build Coastguard Worker // multiple times if it is on the call stack.
481*795d594fSAndroid Build Coastguard Worker MarkObjectIfNotInToSpace(&ref);
482*795d594fSAndroid Build Coastguard Worker if (*root != ref.AsMirrorPtr()) {
483*795d594fSAndroid Build Coastguard Worker *root = ref.AsMirrorPtr();
484*795d594fSAndroid Build Coastguard Worker }
485*795d594fSAndroid Build Coastguard Worker }
486*795d594fSAndroid Build Coastguard Worker }
487*795d594fSAndroid Build Coastguard Worker
VisitRoots(mirror::CompressedReference<mirror::Object> ** roots,size_t count,const RootInfo & info)488*795d594fSAndroid Build Coastguard Worker void SemiSpace::VisitRoots(mirror::CompressedReference<mirror::Object>** roots,
489*795d594fSAndroid Build Coastguard Worker size_t count,
490*795d594fSAndroid Build Coastguard Worker [[maybe_unused]] const RootInfo& info) {
491*795d594fSAndroid Build Coastguard Worker for (size_t i = 0; i < count; ++i) {
492*795d594fSAndroid Build Coastguard Worker MarkObjectIfNotInToSpace(roots[i]);
493*795d594fSAndroid Build Coastguard Worker }
494*795d594fSAndroid Build Coastguard Worker }
495*795d594fSAndroid Build Coastguard Worker
496*795d594fSAndroid Build Coastguard Worker // Marks all objects in the root set.
MarkRoots()497*795d594fSAndroid Build Coastguard Worker void SemiSpace::MarkRoots() {
498*795d594fSAndroid Build Coastguard Worker TimingLogger::ScopedTiming t(__FUNCTION__, GetTimings());
499*795d594fSAndroid Build Coastguard Worker Runtime::Current()->VisitRoots(this);
500*795d594fSAndroid Build Coastguard Worker }
501*795d594fSAndroid Build Coastguard Worker
SweepSystemWeaks()502*795d594fSAndroid Build Coastguard Worker void SemiSpace::SweepSystemWeaks() {
503*795d594fSAndroid Build Coastguard Worker TimingLogger::ScopedTiming t(__FUNCTION__, GetTimings());
504*795d594fSAndroid Build Coastguard Worker Runtime* runtime = Runtime::Current();
505*795d594fSAndroid Build Coastguard Worker runtime->SweepSystemWeaks(this);
506*795d594fSAndroid Build Coastguard Worker runtime->GetThreadList()->SweepInterpreterCaches(this);
507*795d594fSAndroid Build Coastguard Worker }
508*795d594fSAndroid Build Coastguard Worker
ShouldSweepSpace(space::ContinuousSpace * space) const509*795d594fSAndroid Build Coastguard Worker bool SemiSpace::ShouldSweepSpace(space::ContinuousSpace* space) const {
510*795d594fSAndroid Build Coastguard Worker return space != from_space_ && space != to_space_;
511*795d594fSAndroid Build Coastguard Worker }
512*795d594fSAndroid Build Coastguard Worker
Sweep(bool swap_bitmaps)513*795d594fSAndroid Build Coastguard Worker void SemiSpace::Sweep(bool swap_bitmaps) {
514*795d594fSAndroid Build Coastguard Worker TimingLogger::ScopedTiming t(__FUNCTION__, GetTimings());
515*795d594fSAndroid Build Coastguard Worker DCHECK(mark_stack_->IsEmpty());
516*795d594fSAndroid Build Coastguard Worker for (const auto& space : GetHeap()->GetContinuousSpaces()) {
517*795d594fSAndroid Build Coastguard Worker if (space->IsContinuousMemMapAllocSpace()) {
518*795d594fSAndroid Build Coastguard Worker space::ContinuousMemMapAllocSpace* alloc_space = space->AsContinuousMemMapAllocSpace();
519*795d594fSAndroid Build Coastguard Worker if (!ShouldSweepSpace(alloc_space)) {
520*795d594fSAndroid Build Coastguard Worker continue;
521*795d594fSAndroid Build Coastguard Worker }
522*795d594fSAndroid Build Coastguard Worker TimingLogger::ScopedTiming split(
523*795d594fSAndroid Build Coastguard Worker alloc_space->IsZygoteSpace() ? "SweepZygoteSpace" : "SweepAllocSpace", GetTimings());
524*795d594fSAndroid Build Coastguard Worker RecordFree(alloc_space->Sweep(swap_bitmaps));
525*795d594fSAndroid Build Coastguard Worker }
526*795d594fSAndroid Build Coastguard Worker }
527*795d594fSAndroid Build Coastguard Worker SweepLargeObjects(swap_bitmaps);
528*795d594fSAndroid Build Coastguard Worker }
529*795d594fSAndroid Build Coastguard Worker
SweepLargeObjects(bool swap_bitmaps)530*795d594fSAndroid Build Coastguard Worker void SemiSpace::SweepLargeObjects(bool swap_bitmaps) {
531*795d594fSAndroid Build Coastguard Worker space::LargeObjectSpace* los = heap_->GetLargeObjectsSpace();
532*795d594fSAndroid Build Coastguard Worker if (los != nullptr) {
533*795d594fSAndroid Build Coastguard Worker TimingLogger::ScopedTiming split("SweepLargeObjects", GetTimings());
534*795d594fSAndroid Build Coastguard Worker RecordFreeLOS(los->Sweep(swap_bitmaps));
535*795d594fSAndroid Build Coastguard Worker }
536*795d594fSAndroid Build Coastguard Worker }
537*795d594fSAndroid Build Coastguard Worker
538*795d594fSAndroid Build Coastguard Worker // Process the "referent" field in a java.lang.ref.Reference. If the referent has not yet been
539*795d594fSAndroid Build Coastguard Worker // marked, put it on the appropriate list in the heap for later processing.
DelayReferenceReferent(ObjPtr<mirror::Class> klass,ObjPtr<mirror::Reference> reference)540*795d594fSAndroid Build Coastguard Worker void SemiSpace::DelayReferenceReferent(ObjPtr<mirror::Class> klass,
541*795d594fSAndroid Build Coastguard Worker ObjPtr<mirror::Reference> reference) {
542*795d594fSAndroid Build Coastguard Worker heap_->GetReferenceProcessor()->DelayReferenceReferent(klass, reference, this);
543*795d594fSAndroid Build Coastguard Worker }
544*795d594fSAndroid Build Coastguard Worker
545*795d594fSAndroid Build Coastguard Worker class SemiSpace::MarkObjectVisitor {
546*795d594fSAndroid Build Coastguard Worker public:
MarkObjectVisitor(SemiSpace * collector)547*795d594fSAndroid Build Coastguard Worker explicit MarkObjectVisitor(SemiSpace* collector) : collector_(collector) {}
548*795d594fSAndroid Build Coastguard Worker
operator ()(ObjPtr<Object> obj,MemberOffset offset,bool) const549*795d594fSAndroid Build Coastguard Worker void operator()(ObjPtr<Object> obj, MemberOffset offset, bool /* is_static */) const ALWAYS_INLINE
550*795d594fSAndroid Build Coastguard Worker REQUIRES(Locks::mutator_lock_, Locks::heap_bitmap_lock_) {
551*795d594fSAndroid Build Coastguard Worker // Object was already verified when we scanned it.
552*795d594fSAndroid Build Coastguard Worker collector_->MarkObject(obj->GetFieldObjectReferenceAddr<kVerifyNone>(offset));
553*795d594fSAndroid Build Coastguard Worker }
554*795d594fSAndroid Build Coastguard Worker
operator ()(ObjPtr<mirror::Class> klass,ObjPtr<mirror::Reference> ref) const555*795d594fSAndroid Build Coastguard Worker void operator()(ObjPtr<mirror::Class> klass, ObjPtr<mirror::Reference> ref) const
556*795d594fSAndroid Build Coastguard Worker REQUIRES(Locks::mutator_lock_, Locks::heap_bitmap_lock_) {
557*795d594fSAndroid Build Coastguard Worker collector_->DelayReferenceReferent(klass, ref);
558*795d594fSAndroid Build Coastguard Worker }
559*795d594fSAndroid Build Coastguard Worker
560*795d594fSAndroid Build Coastguard Worker // TODO: Remove NO_THREAD_SAFETY_ANALYSIS when clang better understands visitors.
VisitRootIfNonNull(mirror::CompressedReference<mirror::Object> * root) const561*795d594fSAndroid Build Coastguard Worker void VisitRootIfNonNull(mirror::CompressedReference<mirror::Object>* root) const
562*795d594fSAndroid Build Coastguard Worker NO_THREAD_SAFETY_ANALYSIS {
563*795d594fSAndroid Build Coastguard Worker if (!root->IsNull()) {
564*795d594fSAndroid Build Coastguard Worker VisitRoot(root);
565*795d594fSAndroid Build Coastguard Worker }
566*795d594fSAndroid Build Coastguard Worker }
567*795d594fSAndroid Build Coastguard Worker
VisitRoot(mirror::CompressedReference<mirror::Object> * root) const568*795d594fSAndroid Build Coastguard Worker void VisitRoot(mirror::CompressedReference<mirror::Object>* root) const
569*795d594fSAndroid Build Coastguard Worker NO_THREAD_SAFETY_ANALYSIS {
570*795d594fSAndroid Build Coastguard Worker if (kIsDebugBuild) {
571*795d594fSAndroid Build Coastguard Worker Locks::mutator_lock_->AssertExclusiveHeld(Thread::Current());
572*795d594fSAndroid Build Coastguard Worker Locks::heap_bitmap_lock_->AssertExclusiveHeld(Thread::Current());
573*795d594fSAndroid Build Coastguard Worker }
574*795d594fSAndroid Build Coastguard Worker // We may visit the same root multiple times, so avoid marking things in the to-space since
575*795d594fSAndroid Build Coastguard Worker // this is not handled by the GC.
576*795d594fSAndroid Build Coastguard Worker collector_->MarkObjectIfNotInToSpace(root);
577*795d594fSAndroid Build Coastguard Worker }
578*795d594fSAndroid Build Coastguard Worker
579*795d594fSAndroid Build Coastguard Worker private:
580*795d594fSAndroid Build Coastguard Worker SemiSpace* const collector_;
581*795d594fSAndroid Build Coastguard Worker };
582*795d594fSAndroid Build Coastguard Worker
583*795d594fSAndroid Build Coastguard Worker // Visit all of the references of an object and update.
ScanObject(Object * obj)584*795d594fSAndroid Build Coastguard Worker void SemiSpace::ScanObject(Object* obj) {
585*795d594fSAndroid Build Coastguard Worker DCHECK(!from_space_->HasAddress(obj)) << "Scanning object " << obj << " in from space";
586*795d594fSAndroid Build Coastguard Worker MarkObjectVisitor visitor(this);
587*795d594fSAndroid Build Coastguard Worker // Turn off read barrier. ZygoteCompactingCollector doesn't use it (even in the CC build.)
588*795d594fSAndroid Build Coastguard Worker obj->VisitReferences</*kVisitNativeRoots=*/true, kDefaultVerifyFlags, kWithoutReadBarrier>(
589*795d594fSAndroid Build Coastguard Worker visitor, visitor);
590*795d594fSAndroid Build Coastguard Worker }
591*795d594fSAndroid Build Coastguard Worker
592*795d594fSAndroid Build Coastguard Worker // Scan anything that's on the mark stack.
ProcessMarkStack()593*795d594fSAndroid Build Coastguard Worker void SemiSpace::ProcessMarkStack() {
594*795d594fSAndroid Build Coastguard Worker TimingLogger::ScopedTiming t(__FUNCTION__, GetTimings());
595*795d594fSAndroid Build Coastguard Worker while (!mark_stack_->IsEmpty()) {
596*795d594fSAndroid Build Coastguard Worker Object* obj = mark_stack_->PopBack();
597*795d594fSAndroid Build Coastguard Worker ScanObject(obj);
598*795d594fSAndroid Build Coastguard Worker }
599*795d594fSAndroid Build Coastguard Worker }
600*795d594fSAndroid Build Coastguard Worker
IsMarked(mirror::Object * obj)601*795d594fSAndroid Build Coastguard Worker mirror::Object* SemiSpace::IsMarked(mirror::Object* obj) {
602*795d594fSAndroid Build Coastguard Worker // All immune objects are assumed marked.
603*795d594fSAndroid Build Coastguard Worker if (from_space_->HasAddress(obj)) {
604*795d594fSAndroid Build Coastguard Worker // Returns either the forwarding address or null.
605*795d594fSAndroid Build Coastguard Worker return GetForwardingAddressInFromSpace(obj);
606*795d594fSAndroid Build Coastguard Worker } else if (immune_spaces_.IsInImmuneRegion(obj) || to_space_->HasAddress(obj)) {
607*795d594fSAndroid Build Coastguard Worker return obj; // Already forwarded, must be marked.
608*795d594fSAndroid Build Coastguard Worker }
609*795d594fSAndroid Build Coastguard Worker return mark_bitmap_->Test(obj) ? obj : nullptr;
610*795d594fSAndroid Build Coastguard Worker }
611*795d594fSAndroid Build Coastguard Worker
IsNullOrMarkedHeapReference(mirror::HeapReference<mirror::Object> * object,bool do_atomic_update)612*795d594fSAndroid Build Coastguard Worker bool SemiSpace::IsNullOrMarkedHeapReference(mirror::HeapReference<mirror::Object>* object,
613*795d594fSAndroid Build Coastguard Worker // SemiSpace does the GC in a pause. No CAS needed.
614*795d594fSAndroid Build Coastguard Worker [[maybe_unused]] bool do_atomic_update) {
615*795d594fSAndroid Build Coastguard Worker mirror::Object* obj = object->AsMirrorPtr();
616*795d594fSAndroid Build Coastguard Worker if (obj == nullptr) {
617*795d594fSAndroid Build Coastguard Worker return true;
618*795d594fSAndroid Build Coastguard Worker }
619*795d594fSAndroid Build Coastguard Worker mirror::Object* new_obj = IsMarked(obj);
620*795d594fSAndroid Build Coastguard Worker if (new_obj == nullptr) {
621*795d594fSAndroid Build Coastguard Worker return false;
622*795d594fSAndroid Build Coastguard Worker }
623*795d594fSAndroid Build Coastguard Worker if (new_obj != obj) {
624*795d594fSAndroid Build Coastguard Worker // Write barrier is not necessary since it still points to the same object, just at a different
625*795d594fSAndroid Build Coastguard Worker // address.
626*795d594fSAndroid Build Coastguard Worker object->Assign(new_obj);
627*795d594fSAndroid Build Coastguard Worker }
628*795d594fSAndroid Build Coastguard Worker return true;
629*795d594fSAndroid Build Coastguard Worker }
630*795d594fSAndroid Build Coastguard Worker
SetToSpace(space::ContinuousMemMapAllocSpace * to_space)631*795d594fSAndroid Build Coastguard Worker void SemiSpace::SetToSpace(space::ContinuousMemMapAllocSpace* to_space) {
632*795d594fSAndroid Build Coastguard Worker DCHECK(to_space != nullptr);
633*795d594fSAndroid Build Coastguard Worker to_space_ = to_space;
634*795d594fSAndroid Build Coastguard Worker }
635*795d594fSAndroid Build Coastguard Worker
SetFromSpace(space::ContinuousMemMapAllocSpace * from_space)636*795d594fSAndroid Build Coastguard Worker void SemiSpace::SetFromSpace(space::ContinuousMemMapAllocSpace* from_space) {
637*795d594fSAndroid Build Coastguard Worker DCHECK(from_space != nullptr);
638*795d594fSAndroid Build Coastguard Worker from_space_ = from_space;
639*795d594fSAndroid Build Coastguard Worker }
640*795d594fSAndroid Build Coastguard Worker
FinishPhase()641*795d594fSAndroid Build Coastguard Worker void SemiSpace::FinishPhase() {
642*795d594fSAndroid Build Coastguard Worker TimingLogger::ScopedTiming t(__FUNCTION__, GetTimings());
643*795d594fSAndroid Build Coastguard Worker // b/31172841. Temporarily disable the from-space protection with host debug build
644*795d594fSAndroid Build Coastguard Worker // due to some protection issue in the build server.
645*795d594fSAndroid Build Coastguard Worker if (kProtectFromSpace && !(kIsDebugBuild && !kIsTargetBuild)) {
646*795d594fSAndroid Build Coastguard Worker if (from_space_->IsRosAllocSpace()) {
647*795d594fSAndroid Build Coastguard Worker VLOG(heap) << "Protecting from_space_ with PROT_NONE : " << *from_space_;
648*795d594fSAndroid Build Coastguard Worker from_space_->GetMemMap()->Protect(PROT_NONE);
649*795d594fSAndroid Build Coastguard Worker }
650*795d594fSAndroid Build Coastguard Worker }
651*795d594fSAndroid Build Coastguard Worker // Null the "to" and "from" spaces since compacting from one to the other isn't valid until
652*795d594fSAndroid Build Coastguard Worker // further action is done by the heap.
653*795d594fSAndroid Build Coastguard Worker to_space_ = nullptr;
654*795d594fSAndroid Build Coastguard Worker from_space_ = nullptr;
655*795d594fSAndroid Build Coastguard Worker CHECK(mark_stack_->IsEmpty());
656*795d594fSAndroid Build Coastguard Worker mark_stack_->Reset();
657*795d594fSAndroid Build Coastguard Worker // Clear all of the spaces' mark bitmaps.
658*795d594fSAndroid Build Coastguard Worker WriterMutexLock mu(Thread::Current(), *Locks::heap_bitmap_lock_);
659*795d594fSAndroid Build Coastguard Worker heap_->ClearMarkedObjects();
660*795d594fSAndroid Build Coastguard Worker }
661*795d594fSAndroid Build Coastguard Worker
RevokeAllThreadLocalBuffers()662*795d594fSAndroid Build Coastguard Worker void SemiSpace::RevokeAllThreadLocalBuffers() {
663*795d594fSAndroid Build Coastguard Worker TimingLogger::ScopedTiming t(__FUNCTION__, GetTimings());
664*795d594fSAndroid Build Coastguard Worker GetHeap()->RevokeAllThreadLocalBuffers();
665*795d594fSAndroid Build Coastguard Worker }
666*795d594fSAndroid Build Coastguard Worker
667*795d594fSAndroid Build Coastguard Worker } // namespace collector
668*795d594fSAndroid Build Coastguard Worker } // namespace gc
669*795d594fSAndroid Build Coastguard Worker } // namespace art
670