1 /*
2 * Copyright (C) 2013 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 #ifndef ART_RUNTIME_GC_HEAP_VISIT_OBJECTS_INL_H_
18 #define ART_RUNTIME_GC_HEAP_VISIT_OBJECTS_INL_H_
19
20 #include "heap.h"
21
22 #include "base/mutex-inl.h"
23 #include "gc/accounting/heap_bitmap-inl.h"
24 #include "gc/space/bump_pointer_space-walk-inl.h"
25 #include "gc/space/region_space-inl.h"
26 #include "mirror/object-inl.h"
27 #include "obj_ptr-inl.h"
28 #include "scoped_thread_state_change-inl.h"
29 #include "thread-current-inl.h"
30 #include "thread_list.h"
31
32 namespace art {
33 namespace gc {
34
35 // Visit objects when threads aren't suspended. If concurrent moving
36 // GC, disable moving GC and suspend threads and then visit objects.
37 template <typename Visitor>
VisitObjects(Visitor && visitor)38 inline void Heap::VisitObjects(Visitor&& visitor) {
39 Thread* self = Thread::Current();
40 Locks::mutator_lock_->AssertSharedHeld(self);
41 DCHECK(!Locks::mutator_lock_->IsExclusiveHeld(self)) << "Call VisitObjectsPaused() instead";
42 if (IsGcConcurrentAndMoving()) {
43 // Concurrent moving GC. Just suspending threads isn't sufficient
44 // because a collection isn't one big pause and we could suspend
45 // threads in the middle (between phases) of a concurrent moving
46 // collection where it's not easily known which objects are alive
47 // (both the region space and the non-moving space) or which
48 // copies of objects to visit, and the to-space invariant could be
49 // easily broken. Visit objects while GC isn't running by using
50 // IncrementDisableMovingGC() and threads are suspended.
51 IncrementDisableMovingGC(self);
52 {
53 ScopedThreadSuspension sts(self, kWaitingForVisitObjects);
54 ScopedSuspendAll ssa(__FUNCTION__);
55 VisitObjectsInternalRegionSpace(visitor);
56 VisitObjectsInternal(visitor);
57 }
58 DecrementDisableMovingGC(self);
59 } else {
60 // Since concurrent moving GC has thread suspension, also poison ObjPtr the normal case to
61 // catch bugs.
62 self->PoisonObjectPointers();
63 // GCs can move objects, so don't allow this.
64 ScopedAssertNoThreadSuspension ants("Visiting objects");
65 DCHECK(region_space_ == nullptr);
66 VisitObjectsInternal(visitor);
67 self->PoisonObjectPointers();
68 }
69 }
70
71 template <typename Visitor>
VisitObjectsPaused(Visitor && visitor)72 inline void Heap::VisitObjectsPaused(Visitor&& visitor) {
73 Thread* self = Thread::Current();
74 Locks::mutator_lock_->AssertExclusiveHeld(self);
75 VisitObjectsInternalRegionSpace(visitor);
76 VisitObjectsInternal(visitor);
77 }
78
79 // Visit objects in the region spaces.
80 template <typename Visitor>
VisitObjectsInternalRegionSpace(Visitor && visitor)81 inline void Heap::VisitObjectsInternalRegionSpace(Visitor&& visitor) {
82 Thread* self = Thread::Current();
83 Locks::mutator_lock_->AssertExclusiveHeld(self);
84 if (region_space_ != nullptr) {
85 DCHECK(IsGcConcurrentAndMoving());
86 if (!zygote_creation_lock_.IsExclusiveHeld(self)) {
87 // Exclude the pre-zygote fork time where the semi-space collector
88 // calls VerifyHeapReferences() as part of the zygote compaction
89 // which then would call here without the moving GC disabled,
90 // which is fine.
91 bool is_thread_running_gc = false;
92 if (kIsDebugBuild) {
93 MutexLock mu(self, *gc_complete_lock_);
94 is_thread_running_gc = self == thread_running_gc_;
95 }
96 // If we are not the thread running the GC on in a GC exclusive region, then moving GC
97 // must be disabled.
98 DCHECK(is_thread_running_gc || IsMovingGCDisabled(self));
99 }
100 region_space_->Walk(visitor);
101 }
102 }
103
104 // Visit objects in the other spaces.
105 template <typename Visitor>
VisitObjectsInternal(Visitor && visitor)106 inline void Heap::VisitObjectsInternal(Visitor&& visitor) {
107 if (bump_pointer_space_ != nullptr) {
108 // Visit objects in bump pointer space.
109 bump_pointer_space_->Walk(visitor);
110 }
111 // TODO: Switch to standard begin and end to use ranged a based loop.
112 for (auto* it = allocation_stack_->Begin(), *end = allocation_stack_->End(); it < end; ++it) {
113 mirror::Object* const obj = it->AsMirrorPtr();
114
115 mirror::Class* kls = nullptr;
116 if (obj != nullptr && (kls = obj->GetClass()) != nullptr) {
117 // Below invariant is safe regardless of what space the Object is in.
118 // For speed reasons, only perform it when Rosalloc could possibly be used.
119 // (Disabled for read barriers because it never uses Rosalloc).
120 // (See the DCHECK in RosAllocSpace constructor).
121 if (!kUseReadBarrier) {
122 // Rosalloc has a race in allocation. Objects can be written into the allocation
123 // stack before their header writes are visible to this thread.
124 // See b/28790624 for more details.
125 //
126 // obj.class will either be pointing to a valid Class*, or it will point
127 // to a rosalloc free buffer.
128 //
129 // If it's pointing to a valid Class* then that Class's Class will be the
130 // ClassClass (whose Class is itself).
131 //
132 // A rosalloc free buffer will point to another rosalloc free buffer
133 // (or to null), and never to itself.
134 //
135 // Either way dereferencing while its not-null is safe because it will
136 // always point to another valid pointer or to null.
137 mirror::Class* klsClass = kls->GetClass();
138
139 if (klsClass == nullptr) {
140 continue;
141 } else if (klsClass->GetClass() != klsClass) {
142 continue;
143 }
144 } else {
145 // Ensure the invariant is not broken for non-rosalloc cases.
146 DCHECK(Heap::rosalloc_space_ == nullptr)
147 << "unexpected rosalloc with read barriers";
148 DCHECK(kls->GetClass() != nullptr)
149 << "invalid object: class does not have a class";
150 DCHECK_EQ(kls->GetClass()->GetClass(), kls->GetClass())
151 << "invalid object: class's class is not ClassClass";
152 }
153
154 // Avoid the race condition caused by the object not yet being written into the allocation
155 // stack or the class not yet being written in the object. Or, if
156 // kUseThreadLocalAllocationStack, there can be nulls on the allocation stack.
157 visitor(obj);
158 }
159 }
160 {
161 ReaderMutexLock mu(Thread::Current(), *Locks::heap_bitmap_lock_);
162 GetLiveBitmap()->Visit<Visitor>(visitor);
163 }
164 }
165
166 } // namespace gc
167 } // namespace art
168
169 #endif // ART_RUNTIME_GC_HEAP_VISIT_OBJECTS_INL_H_
170