blob: 6b1b617eb43fe3adb79b82ba097fa91e3734e9b9 [file] [log] [blame]
Ian Rogers2dd0e2c2013-01-24 12:42:14 -08001/*
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
Brian Carlstromfc0e3212013-07-17 14:40:12 -070017#ifndef ART_RUNTIME_GC_COLLECTOR_MARK_SWEEP_INL_H_
18#define ART_RUNTIME_GC_COLLECTOR_MARK_SWEEP_INL_H_
Ian Rogers2dd0e2c2013-01-24 12:42:14 -080019
Ian Rogers1d54e732013-05-02 21:10:01 -070020#include "gc/collector/mark_sweep.h"
21
22#include "gc/heap.h"
Ian Rogers2dd0e2c2013-01-24 12:42:14 -080023#include "mirror/class.h"
24#include "mirror/field.h"
25#include "mirror/object_array.h"
26
27namespace art {
Ian Rogers1d54e732013-05-02 21:10:01 -070028namespace gc {
29namespace collector {
Ian Rogers2dd0e2c2013-01-24 12:42:14 -080030
31template <typename MarkVisitor>
32inline 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 (klass == java_lang_Class_) {
41 DCHECK_EQ(klass->GetClass(), java_lang_Class_);
42 if (kCountScannedTypes) {
43 ++class_count_;
44 }
45 VisitClassReferences(klass, obj, visitor);
46 } else if (klass->IsArrayClass()) {
47 if (kCountScannedTypes) {
48 ++array_count_;
49 }
50 visitor(obj, klass, mirror::Object::ClassOffset(), false);
51 if (klass->IsObjectArrayClass()) {
52 VisitObjectArrayReferences(obj->AsObjectArray<mirror::Object>(), visitor);
53 }
54 } else {
55 if (kCountScannedTypes) {
56 ++other_count_;
57 }
58 VisitOtherReferences(klass, obj, visitor);
59 if (UNLIKELY(klass->IsReferenceClass())) {
60 DelayReferenceReferent(const_cast<mirror::Object*>(obj));
61 }
62 }
63}
64
65template <typename Visitor>
66inline void MarkSweep::VisitObjectReferences(const mirror::Object* obj, const Visitor& visitor)
67 SHARED_LOCKS_REQUIRED(Locks::heap_bitmap_lock_,
68 Locks::mutator_lock_) {
69 DCHECK(obj != NULL);
70 DCHECK(obj->GetClass() != NULL);
71
72 mirror::Class* klass = obj->GetClass();
73 DCHECK(klass != NULL);
74 if (klass == mirror::Class::GetJavaLangClass()) {
75 DCHECK_EQ(klass->GetClass(), mirror::Class::GetJavaLangClass());
76 VisitClassReferences(klass, obj, visitor);
77 } else {
78 if (klass->IsArrayClass()) {
79 visitor(obj, klass, mirror::Object::ClassOffset(), false);
80 if (klass->IsObjectArrayClass()) {
81 VisitObjectArrayReferences(obj->AsObjectArray<mirror::Object>(), visitor);
82 }
83 } else {
84 VisitOtherReferences(klass, obj, visitor);
85 }
86 }
87}
88
89template <typename Visitor>
90inline void MarkSweep::VisitInstanceFieldsReferences(const mirror::Class* klass,
91 const mirror::Object* obj,
92 const Visitor& visitor)
93 SHARED_LOCKS_REQUIRED(Locks::heap_bitmap_lock_, Locks::mutator_lock_) {
94 DCHECK(obj != NULL);
95 DCHECK(klass != NULL);
96 VisitFieldsReferences(obj, klass->GetReferenceInstanceOffsets(), false, visitor);
97}
98
99template <typename Visitor>
100inline void MarkSweep::VisitClassReferences(const mirror::Class* klass, const mirror::Object* obj,
101 const Visitor& visitor)
102 SHARED_LOCKS_REQUIRED(Locks::heap_bitmap_lock_, Locks::mutator_lock_) {
103 VisitInstanceFieldsReferences(klass, obj, visitor);
104 VisitStaticFieldsReferences(obj->AsClass(), visitor);
105}
106
107template <typename Visitor>
108inline void MarkSweep::VisitStaticFieldsReferences(const mirror::Class* klass,
109 const Visitor& visitor)
110 SHARED_LOCKS_REQUIRED(Locks::heap_bitmap_lock_, Locks::mutator_lock_) {
111 DCHECK(klass != NULL);
112 VisitFieldsReferences(klass, klass->GetReferenceStaticOffsets(), true, visitor);
113}
114
115template <typename Visitor>
116inline void MarkSweep::VisitFieldsReferences(const mirror::Object* obj, uint32_t ref_offsets,
117 bool is_static, const Visitor& visitor) {
118 if (LIKELY(ref_offsets != CLASS_WALK_SUPER)) {
119 // Found a reference offset bitmap. Mark the specified offsets.
120 while (ref_offsets != 0) {
121 size_t right_shift = CLZ(ref_offsets);
122 MemberOffset field_offset = CLASS_OFFSET_FROM_CLZ(right_shift);
123 const mirror::Object* ref = obj->GetFieldObject<const mirror::Object*>(field_offset, false);
124 visitor(obj, ref, field_offset, is_static);
125 ref_offsets &= ~(CLASS_HIGH_BIT >> right_shift);
126 }
127 } else {
128 // There is no reference offset bitmap. In the non-static case,
129 // walk up the class inheritance hierarchy and find reference
130 // offsets the hard way. In the static case, just consider this
131 // class.
132 for (const mirror::Class* klass = is_static ? obj->AsClass() : obj->GetClass();
133 klass != NULL;
134 klass = is_static ? NULL : klass->GetSuperClass()) {
135 size_t num_reference_fields = (is_static
136 ? klass->NumReferenceStaticFields()
137 : klass->NumReferenceInstanceFields());
138 for (size_t i = 0; i < num_reference_fields; ++i) {
139 mirror::Field* field = (is_static ? klass->GetStaticField(i)
140 : klass->GetInstanceField(i));
141 MemberOffset field_offset = field->GetOffset();
142 const mirror::Object* ref = obj->GetFieldObject<const mirror::Object*>(field_offset, false);
143 visitor(obj, ref, field_offset, is_static);
144 }
145 }
146 }
147}
148
149template <typename Visitor>
150inline void MarkSweep::VisitObjectArrayReferences(const mirror::ObjectArray<mirror::Object>* array,
151 const Visitor& visitor) {
152 const int32_t length = array->GetLength();
153 for (int32_t i = 0; i < length; ++i) {
154 const mirror::Object* element = array->GetWithoutChecks(i);
155 const size_t width = sizeof(mirror::Object*);
156 MemberOffset offset = MemberOffset(i * width + mirror::Array::DataOffset(width).Int32Value());
157 visitor(array, element, offset, false);
158 }
159}
160
Ian Rogers1d54e732013-05-02 21:10:01 -0700161} // namespace collector
162} // namespace gc
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800163} // namespace art
164
Brian Carlstromfc0e3212013-07-17 14:40:12 -0700165#endif // ART_RUNTIME_GC_COLLECTOR_MARK_SWEEP_INL_H_