• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2011 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_COLLECTOR_MARK_SWEEP_INL_H_
18 #define ART_RUNTIME_GC_COLLECTOR_MARK_SWEEP_INL_H_
19 
20 #include "gc/collector/mark_sweep.h"
21 
22 #include "gc/heap.h"
23 #include "mirror/art_field.h"
24 #include "mirror/class.h"
25 #include "mirror/object_array.h"
26 
27 namespace art {
28 namespace gc {
29 namespace collector {
30 
31 template <typename MarkVisitor>
ScanObjectVisit(const mirror::Object * obj,const MarkVisitor & visitor)32 inline void MarkSweep::ScanObjectVisit(const mirror::Object* obj, const MarkVisitor& visitor) {
33   DCHECK(obj != NULL);
34   if (kIsDebugBuild && !IsMarked(obj)) {
35     heap_->DumpSpaces();
36     LOG(FATAL) << "Scanning unmarked object " << obj;
37   }
38   mirror::Class* klass = obj->GetClass();
39   DCHECK(klass != NULL);
40   if (UNLIKELY(klass->IsArrayClass())) {
41     if (kCountScannedTypes) {
42       ++array_count_;
43     }
44     if (klass->IsObjectArrayClass()) {
45       VisitObjectArrayReferences(obj->AsObjectArray<mirror::Object>(), visitor);
46     }
47   } else if (UNLIKELY(klass == java_lang_Class_)) {
48     DCHECK_EQ(klass->GetClass(), java_lang_Class_);
49     if (kCountScannedTypes) {
50       ++class_count_;
51     }
52     VisitClassReferences(klass, obj, visitor);
53   } else {
54     if (kCountScannedTypes) {
55       ++other_count_;
56     }
57     VisitOtherReferences(klass, obj, visitor);
58     if (UNLIKELY(klass->IsReferenceClass())) {
59       DelayReferenceReferent(klass, const_cast<mirror::Object*>(obj));
60     }
61   }
62 }
63 
64 template <typename Visitor>
VisitObjectReferences(const mirror::Object * obj,const Visitor & visitor)65 inline void MarkSweep::VisitObjectReferences(const mirror::Object* obj, const Visitor& visitor)
66     SHARED_LOCKS_REQUIRED(Locks::heap_bitmap_lock_,
67                           Locks::mutator_lock_) {
68   DCHECK(obj != NULL);
69   DCHECK(obj->GetClass() != NULL);
70 
71   mirror::Class* klass = obj->GetClass();
72   DCHECK(klass != NULL);
73   if (klass == mirror::Class::GetJavaLangClass()) {
74     DCHECK_EQ(klass->GetClass(), mirror::Class::GetJavaLangClass());
75     VisitClassReferences(klass, obj, visitor);
76   } else {
77     if (klass->IsArrayClass()) {
78       visitor(obj, klass, mirror::Object::ClassOffset(), false);
79       if (klass->IsObjectArrayClass()) {
80         VisitObjectArrayReferences(obj->AsObjectArray<mirror::Object>(), visitor);
81       }
82     } else {
83       VisitOtherReferences(klass, obj, visitor);
84     }
85   }
86 }
87 
88 template <typename Visitor>
VisitInstanceFieldsReferences(const mirror::Class * klass,const mirror::Object * obj,const Visitor & visitor)89 inline void MarkSweep::VisitInstanceFieldsReferences(const mirror::Class* klass,
90                                                      const mirror::Object* obj,
91                                                      const Visitor& visitor)
92     SHARED_LOCKS_REQUIRED(Locks::heap_bitmap_lock_, Locks::mutator_lock_) {
93   DCHECK(obj != NULL);
94   DCHECK(klass != NULL);
95   VisitFieldsReferences(obj, klass->GetReferenceInstanceOffsets(), false, visitor);
96 }
97 
98 template <typename Visitor>
VisitClassReferences(const mirror::Class * klass,const mirror::Object * obj,const Visitor & visitor)99 inline void MarkSweep::VisitClassReferences(const mirror::Class* klass, const mirror::Object* obj,
100                                             const Visitor& visitor)
101     SHARED_LOCKS_REQUIRED(Locks::heap_bitmap_lock_, Locks::mutator_lock_) {
102   VisitInstanceFieldsReferences(klass, obj, visitor);
103   VisitStaticFieldsReferences(obj->AsClass(), visitor);
104 }
105 
106 template <typename Visitor>
VisitStaticFieldsReferences(const mirror::Class * klass,const Visitor & visitor)107 inline void MarkSweep::VisitStaticFieldsReferences(const mirror::Class* klass,
108                                                    const Visitor& visitor)
109     SHARED_LOCKS_REQUIRED(Locks::heap_bitmap_lock_, Locks::mutator_lock_) {
110   DCHECK(klass != NULL);
111   VisitFieldsReferences(klass, klass->GetReferenceStaticOffsets(), true, visitor);
112 }
113 
114 template <typename Visitor>
VisitFieldsReferences(const mirror::Object * obj,uint32_t ref_offsets,bool is_static,const Visitor & visitor)115 inline void MarkSweep::VisitFieldsReferences(const mirror::Object* obj, uint32_t ref_offsets,
116                                              bool is_static, const Visitor& visitor) {
117   if (LIKELY(ref_offsets != CLASS_WALK_SUPER)) {
118     // Found a reference offset bitmap.  Mark the specified offsets.
119 #ifndef MOVING_COLLECTOR
120     // Clear the class bit since we mark the class as part of marking the classlinker roots.
121     DCHECK_EQ(mirror::Object::ClassOffset().Uint32Value(), 0U);
122     ref_offsets &= (1U << (sizeof(ref_offsets) * 8 - 1)) - 1;
123 #endif
124     while (ref_offsets != 0) {
125       size_t right_shift = CLZ(ref_offsets);
126       MemberOffset field_offset = CLASS_OFFSET_FROM_CLZ(right_shift);
127       const mirror::Object* ref = obj->GetFieldObject<const mirror::Object*>(field_offset, false);
128       visitor(obj, ref, field_offset, is_static);
129       ref_offsets &= ~(CLASS_HIGH_BIT >> right_shift);
130     }
131   } else {
132     // There is no reference offset bitmap.  In the non-static case,
133     // walk up the class inheritance hierarchy and find reference
134     // offsets the hard way. In the static case, just consider this
135     // class.
136     for (const mirror::Class* klass = is_static ? obj->AsClass() : obj->GetClass();
137          klass != NULL;
138          klass = is_static ? NULL : klass->GetSuperClass()) {
139       size_t num_reference_fields = (is_static
140                                      ? klass->NumReferenceStaticFields()
141                                      : klass->NumReferenceInstanceFields());
142       for (size_t i = 0; i < num_reference_fields; ++i) {
143         mirror::ArtField* field = (is_static ? klass->GetStaticField(i)
144                                    : klass->GetInstanceField(i));
145         MemberOffset field_offset = field->GetOffset();
146         const mirror::Object* ref = obj->GetFieldObject<const mirror::Object*>(field_offset, false);
147         visitor(obj, ref, field_offset, is_static);
148       }
149     }
150   }
151 }
152 
153 template <typename Visitor>
VisitObjectArrayReferences(const mirror::ObjectArray<mirror::Object> * array,const Visitor & visitor)154 inline void MarkSweep::VisitObjectArrayReferences(const mirror::ObjectArray<mirror::Object>* array,
155                                                   const Visitor& visitor) {
156   const size_t length = static_cast<size_t>(array->GetLength());
157   for (size_t i = 0; i < length; ++i) {
158     const mirror::Object* element = array->GetWithoutChecks(static_cast<int32_t>(i));
159     const size_t width = sizeof(mirror::Object*);
160     MemberOffset offset(i * width + mirror::Array::DataOffset(width).Int32Value());
161     visitor(array, element, offset, false);
162   }
163 }
164 
165 }  // namespace collector
166 }  // namespace gc
167 }  // namespace art
168 
169 #endif  // ART_RUNTIME_GC_COLLECTOR_MARK_SWEEP_INL_H_
170