Home | History | Annotate | Download | only in collector
      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