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> 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> 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> 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> 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> 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> 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> 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