(四) VisitReferences引用遍历

// Normal instance with at least one ref field other than the class.
static constexpr uint32_t kClassFlagNormal             = 0x00000000;

// Only normal objects which have no reference fields, e.g. string or primitive array or normal
// class instance with no fields other than klass.
static constexpr uint32_t kClassFlagNoReferenceFields  = 0x00000001;

// Class is java.lang.String.class.
static constexpr uint32_t kClassFlagString             = 0x00000004;

// Class is an object array class.
static constexpr uint32_t kClassFlagObjectArray        = 0x00000008;

// Class is java.lang.Class.class.
static constexpr uint32_t kClassFlagClass              = 0x00000010;

// Class is ClassLoader or one of its subclasses.
static constexpr uint32_t kClassFlagClassLoader        = 0x00000020;

// Class is DexCache.
static constexpr uint32_t kClassFlagDexCache           = 0x00000040;

// Class is a soft/weak/phantom class.
static constexpr uint32_t kClassFlagSoftReference      = 0x00000080;

// Class is a weak reference class.
static constexpr uint32_t kClassFlagWeakReference      = 0x00000100;

// Class is a finalizer reference class.
static constexpr uint32_t kClassFlagFinalizerReference = 0x00000200;

// Class is the phantom reference class.
static constexpr uint32_t kClassFlagPhantomReference   = 0x00000400;

template <bool kVisitNativeRoots,
          VerifyObjectFlags kVerifyFlags,
          ReadBarrierOption kReadBarrierOption,
          typename Visitor,
          typename JavaLangRefVisitor>
inline void Object::VisitReferences(const Visitor& visitor,
                                    const JavaLangRefVisitor& ref_visitor) {
  visitor(this, ClassOffset(), /* is_static= */ false);
  ObjPtr<Class> klass = GetClass<kVerifyFlags, kReadBarrierOption>();
  const uint32_t class_flags = klass->GetClassFlags<kVerifyNone>();
  if (LIKELY(class_flags == kClassFlagNormal)) {
    DCHECK((!klass->IsVariableSize<kVerifyFlags>()));
    VisitInstanceFieldsReferences<kVerifyFlags, kReadBarrierOption>(klass, visitor);
    DCHECK((!klass->IsClassClass<kVerifyFlags>()));
    DCHECK(!klass->IsStringClass<kVerifyFlags>());
    DCHECK(!klass->IsClassLoaderClass<kVerifyFlags>());
    DCHECK((!klass->IsArrayClass<kVerifyFlags>()));
  } else {
    if ((class_flags & kClassFlagNoReferenceFields) == 0) {
      DCHECK(!klass->IsStringClass<kVerifyFlags>());
      if (class_flags == kClassFlagClass) {
        DCHECK((klass->IsClassClass<kVerifyFlags>()));
        ObjPtr<Class> as_klass = AsClass<kVerifyNone>();
        as_klass->VisitReferences<kVisitNativeRoots, kVerifyFlags, kReadBarrierOption>(klass,
                                                                                       visitor);
      } else if (class_flags == kClassFlagObjectArray) {
        DCHECK((klass->IsObjectArrayClass<kVerifyFlags>()));
        AsObjectArray<mirror::Object, kVerifyNone>()->VisitReferences(visitor);
      } else if ((class_flags & kClassFlagReference) != 0) {
        VisitInstanceFieldsReferences<kVerifyFlags, kReadBarrierOption>(klass, visitor);
        ref_visitor(klass, AsReference<kVerifyFlags, kReadBarrierOption>());
      } else if (class_flags == kClassFlagDexCache) {
        ObjPtr<mirror::DexCache> const dex_cache = AsDexCache<kVerifyFlags, kReadBarrierOption>();
        dex_cache->VisitReferences<kVisitNativeRoots,
                                   kVerifyFlags,
                                   kReadBarrierOption>(klass, visitor);
      } else {
        ObjPtr<mirror::ClassLoader> const class_loader =
            AsClassLoader<kVerifyFlags, kReadBarrierOption>();
        class_loader->VisitReferences<kVisitNativeRoots,
                                      kVerifyFlags,
                                      kReadBarrierOption>(klass, visitor);
      }
    } else if (kIsDebugBuild) {
      CHECK((!klass->IsClassClass<kVerifyFlags>()));
      CHECK((!klass->IsObjectArrayClass<kVerifyFlags>()));
      // String still has instance fields for reflection purposes but these don't exist in
      // actual string instances.
      if (!klass->IsStringClass<kVerifyFlags>()) {
        size_t total_reference_instance_fields = 0;
        ObjPtr<Class> super_class = klass;
        do {
          total_reference_instance_fields +=
              super_class->NumReferenceInstanceFields<kVerifyFlags>();
          super_class = super_class->GetSuperClass<kVerifyFlags, kReadBarrierOption>();
        } while (super_class != nullptr);
        // The only reference field should be the object's class. This field is handled at the
        // beginning of the function.
        CHECK_EQ(total_reference_instance_fields, 1u);
      }
    }
  }
}

class

template <bool kVisitNativeRoots,
          VerifyObjectFlags kVerifyFlags,
          ReadBarrierOption kReadBarrierOption,
          typename Visitor>
inline void Class::VisitReferences(ObjPtr<Class> klass, const Visitor& visitor) {
  VisitInstanceFieldsReferences<kVerifyFlags, kReadBarrierOption>(klass.Ptr(), visitor);
  // Right after a class is allocated, but not yet loaded
  // (ClassStatus::kNotReady, see ClassLinker::LoadClass()), GC may find it
  // and scan it. IsTemp() may call Class::GetAccessFlags() but may
  // fail in the DCHECK in Class::GetAccessFlags() because the class
  // status is ClassStatus::kNotReady. To avoid it, rely on IsResolved()
  // only. This is fine because a temp class never goes into the
  // ClassStatus::kResolved state.
  if (IsResolved<kVerifyFlags>()) {
    // Temp classes don't ever populate imt/vtable or static fields and they are not even
    // allocated with the right size for those. Also, unresolved classes don't have fields
    // linked yet.
    VisitStaticFieldsReferences<kVerifyFlags, kReadBarrierOption>(this, visitor);
  }
  if (kVisitNativeRoots) {
    // Since this class is reachable, we must also visit the associated roots when we scan it.
    VisitNativeRoots<kReadBarrierOption>(
        visitor, Runtime::Current()->GetClassLinker()->GetImagePointerSize());
  }
}

template<ReadBarrierOption kReadBarrierOption, class Visitor>
void Class::VisitNativeRoots(Visitor& visitor, PointerSize pointer_size) {
  VisitFields<kReadBarrierOption>([&](ArtField* field) REQUIRES_SHARED(art::Locks::mutator_lock_) {
    field->VisitRoots(visitor);
    if (kIsDebugBuild && IsResolved()) {
      CHECK_EQ(field->GetDeclaringClass<kReadBarrierOption>(), this)
          << GetStatus() << field->GetDeclaringClass()->PrettyClass() << " != " << PrettyClass();
    }
  });
  // Don't use VisitMethods because we don't want to hit the class-ext methods twice.
  for (ArtMethod& method : GetMethods(pointer_size)) {
    method.VisitRoots<kReadBarrierOption>(visitor, pointer_size);
  }
  ObjPtr<ClassExt> ext(GetExtData<kDefaultVerifyFlags, kReadBarrierOption>());
  if (!ext.IsNull()) {
    ext->VisitNativeRoots<kReadBarrierOption, Visitor>(visitor, pointer_size);
  }
}

ObjectArray

template<class T> template<typename Visitor>
inline void ObjectArray<T>::VisitReferences(const Visitor& visitor) {
  const size_t length = static_cast<size_t>(GetLength());
  for (size_t i = 0; i < length; ++i) {
    visitor(this, OffsetOfElement(i), false);
  }
}

DexCache

template <bool kVisitNativeRoots,
          VerifyObjectFlags kVerifyFlags,
          ReadBarrierOption kReadBarrierOption,
          typename Visitor>
inline void DexCache::VisitReferences(ObjPtr<Class> klass, const Visitor& visitor) {
  // Visit instance fields first.
  VisitInstanceFieldsReferences<kVerifyFlags, kReadBarrierOption>(klass, visitor);
  // Visit arrays after.
  if (kVisitNativeRoots) {
    VisitDexCachePairs<String, kReadBarrierOption, Visitor>(
        GetStrings<kVerifyFlags>(), NumStrings<kVerifyFlags>(), visitor);

    VisitDexCachePairs<Class, kReadBarrierOption, Visitor>(
        GetResolvedTypes<kVerifyFlags>(), NumResolvedTypes<kVerifyFlags>(), visitor);

    VisitDexCachePairs<MethodType, kReadBarrierOption, Visitor>(
        GetResolvedMethodTypes<kVerifyFlags>(), NumResolvedMethodTypes<kVerifyFlags>(), visitor);

    GcRoot<mirror::CallSite>* resolved_call_sites = GetResolvedCallSites<kVerifyFlags>();
    size_t num_call_sites = NumResolvedCallSites<kVerifyFlags>();
    for (size_t i = 0; i != num_call_sites; ++i) {
      visitor.VisitRootIfNonNull(resolved_call_sites[i].AddressWithoutBarrier());
    }

    GcRoot<mirror::String>* const preresolved_strings = GetPreResolvedStrings();
    if (preresolved_strings != nullptr) {
      const size_t num_preresolved_strings = NumPreResolvedStrings();
      for (size_t i = 0; i != num_preresolved_strings; ++i) {
        visitor.VisitRootIfNonNull(preresolved_strings[i].AddressWithoutBarrier());
      }
    }
  }
}

ClassLoader

template <bool kVisitClasses,
          VerifyObjectFlags kVerifyFlags,
          ReadBarrierOption kReadBarrierOption,
          typename Visitor>
inline void ClassLoader::VisitReferences(ObjPtr<mirror::Class> klass, const Visitor& visitor) {
  // Visit instance fields first.
  VisitInstanceFieldsReferences<kVerifyFlags, kReadBarrierOption>(klass, visitor);
  if (kVisitClasses) {
    // Visit classes loaded after.
    ClassTable* const class_table = GetClassTable<kVerifyFlags>();
    if (class_table != nullptr) {
      class_table->VisitRoots(visitor);
    }
  }
}
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容