ART: Clean up art_method.h
Clean up the header. Fix up other headers including the -inl file,
in an effort to prune the include graph. Fix broken transitive
includes by making includes explicit. Introduce new -inl files
for method handles and reference visiting.
Test: source build/envsetup.sh && lunch aosp_angler-userdebug && mmma art
Test: source build/envsetup.sh && lunch aosp_mips64-userdebug && mmma art
Change-Id: I8f60f1160c2a702fdf3598149dae38f6fa6bc851
diff --git a/runtime/mirror/array-inl.h b/runtime/mirror/array-inl.h
index 04c80c5..be03f04 100644
--- a/runtime/mirror/array-inl.h
+++ b/runtime/mirror/array-inl.h
@@ -24,7 +24,7 @@
#include "base/bit_utils.h"
#include "base/casts.h"
#include "base/logging.h"
-#include "class-inl.h"
+#include "class.h"
#include "gc/heap-inl.h"
#include "obj_ptr-inl.h"
#include "thread.h"
diff --git a/runtime/mirror/class-inl.h b/runtime/mirror/class-inl.h
index 9124a3a..d78ed7f 100644
--- a/runtime/mirror/class-inl.h
+++ b/runtime/mirror/class-inl.h
@@ -21,7 +21,6 @@
#include "art_field-inl.h"
#include "art_method.h"
-#include "art_method-inl.h"
#include "base/array_slice.h"
#include "base/length_prefixed_array.h"
#include "class_loader.h"
@@ -29,7 +28,6 @@
#include "dex_file.h"
#include "gc/heap-inl.h"
#include "iftable.h"
-#include "class_ext-inl.h"
#include "object_array-inl.h"
#include "read_barrier-inl.h"
#include "reference-inl.h"
@@ -343,6 +341,21 @@
return false;
}
+template<VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption>
+inline bool Class::IsVariableSize() {
+ // Classes, arrays, and strings vary in size, and so the object_size_ field cannot
+ // be used to Get their instance size
+ return IsClassClass<kVerifyFlags, kReadBarrierOption>() ||
+ IsArrayClass<kVerifyFlags, kReadBarrierOption>() ||
+ IsStringClass();
+}
+
+inline void Class::SetObjectSize(uint32_t new_object_size) {
+ DCHECK(!IsVariableSize());
+ // Not called within a transaction.
+ return SetField32<false>(OFFSET_OF_OBJECT_MEMBER(Class, object_size_), new_object_size);
+}
+
// Determine whether "this" is assignable from "src", where both of these
// are array classes.
//
@@ -784,32 +797,6 @@
return size;
}
-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
- // (kStatusNotReady, 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 kStatusNotReady. To avoid it, rely on IsResolved()
- // only. This is fine because a temp class never goes into the
- // kStatusResolved 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>
inline bool Class::IsReferenceClass() const {
return this == Reference::GetJavaLangRefReference<kReadBarrierOption>();
@@ -942,31 +929,6 @@
}
}
-template<ReadBarrierOption kReadBarrierOption, class Visitor>
-void Class::VisitNativeRoots(Visitor& visitor, PointerSize pointer_size) {
- for (ArtField& field : GetSFieldsUnchecked()) {
- // Visit roots first in case the declaring class gets moved.
- field.VisitRoots(visitor);
- if (kIsDebugBuild && IsResolved()) {
- CHECK_EQ(field.GetDeclaringClass<kReadBarrierOption>(), this) << GetStatus();
- }
- }
- for (ArtField& field : GetIFieldsUnchecked()) {
- // Visit roots first in case the declaring class gets moved.
- field.VisitRoots(visitor);
- if (kIsDebugBuild && IsResolved()) {
- CHECK_EQ(field.GetDeclaringClass<kReadBarrierOption>(), this) << GetStatus();
- }
- }
- 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);
- }
-}
-
inline IterationRange<StrideIterator<ArtMethod>> Class::GetDirectMethods(PointerSize pointer_size) {
CheckPointerSize(pointer_size);
return GetDirectMethodsSliceUnchecked(pointer_size).AsRange();
@@ -1036,6 +998,12 @@
return GetComponentType<kVerifyFlags, kReadBarrierOption>() != nullptr;
}
+template<VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption>
+inline bool Class::IsObjectArrayClass() {
+ ObjPtr<Class> const component_type = GetComponentType<kVerifyFlags, kReadBarrierOption>();
+ return component_type != nullptr && !component_type->IsPrimitive();
+}
+
inline bool Class::IsAssignableFrom(ObjPtr<Class> src) {
DCHECK(src != nullptr);
if (this == src) {
diff --git a/runtime/mirror/class-refvisitor-inl.h b/runtime/mirror/class-refvisitor-inl.h
new file mode 100644
index 0000000..ffc4af5
--- /dev/null
+++ b/runtime/mirror/class-refvisitor-inl.h
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ART_RUNTIME_MIRROR_CLASS_REFVISITOR_INL_H_
+#define ART_RUNTIME_MIRROR_CLASS_REFVISITOR_INL_H_
+
+#include "class-inl.h"
+
+#include "class_ext-inl.h"
+
+namespace art {
+namespace mirror {
+
+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
+ // (kStatusNotReady, 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 kStatusNotReady. To avoid it, rely on IsResolved()
+ // only. This is fine because a temp class never goes into the
+ // kStatusResolved 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) {
+ for (ArtField& field : GetSFieldsUnchecked()) {
+ // Visit roots first in case the declaring class gets moved.
+ field.VisitRoots(visitor);
+ if (kIsDebugBuild && IsResolved()) {
+ CHECK_EQ(field.GetDeclaringClass<kReadBarrierOption>(), this) << GetStatus();
+ }
+ }
+ for (ArtField& field : GetIFieldsUnchecked()) {
+ // Visit roots first in case the declaring class gets moved.
+ field.VisitRoots(visitor);
+ if (kIsDebugBuild && IsResolved()) {
+ CHECK_EQ(field.GetDeclaringClass<kReadBarrierOption>(), this) << GetStatus();
+ }
+ }
+ 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);
+ }
+}
+
+} // namespace mirror
+} // namespace art
+
+#endif // ART_RUNTIME_MIRROR_CLASS_REFVISITOR_INL_H_
diff --git a/runtime/mirror/class.cc b/runtime/mirror/class.cc
index 26af488..06ee3d3 100644
--- a/runtime/mirror/class.cc
+++ b/runtime/mirror/class.cc
@@ -32,6 +32,7 @@
#include "method.h"
#include "object_array-inl.h"
#include "object-inl.h"
+#include "object-refvisitor-inl.h"
#include "object_lock.h"
#include "runtime.h"
#include "thread.h"
diff --git a/runtime/mirror/class.h b/runtime/mirror/class.h
index 27aecd5..dfb2788 100644
--- a/runtime/mirror/class.h
+++ b/runtime/mirror/class.h
@@ -530,10 +530,7 @@
template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags,
ReadBarrierOption kReadBarrierOption = kWithReadBarrier>
- bool IsObjectArrayClass() REQUIRES_SHARED(Locks::mutator_lock_) {
- ObjPtr<Class> const component_type = GetComponentType<kVerifyFlags, kReadBarrierOption>();
- return component_type != nullptr && !component_type->IsPrimitive();
- }
+ ALWAYS_INLINE bool IsObjectArrayClass() REQUIRES_SHARED(Locks::mutator_lock_);
template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
bool IsIntArrayClass() REQUIRES_SHARED(Locks::mutator_lock_) {
@@ -561,12 +558,7 @@
template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags,
ReadBarrierOption kReadBarrierOption = kWithReadBarrier>
- bool IsVariableSize() REQUIRES_SHARED(Locks::mutator_lock_) {
- // Classes, arrays, and strings vary in size, and so the object_size_ field cannot
- // be used to Get their instance size
- return IsClassClass<kVerifyFlags, kReadBarrierOption>() ||
- IsArrayClass<kVerifyFlags, kReadBarrierOption>() || IsStringClass();
- }
+ ALWAYS_INLINE bool IsVariableSize() REQUIRES_SHARED(Locks::mutator_lock_);
template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags,
ReadBarrierOption kReadBarrierOption = kWithReadBarrier>
@@ -614,11 +606,7 @@
return OFFSET_OF_OBJECT_MEMBER(Class, object_size_alloc_fast_path_);
}
- void SetObjectSize(uint32_t new_object_size) REQUIRES_SHARED(Locks::mutator_lock_) {
- DCHECK(!IsVariableSize());
- // Not called within a transaction.
- return SetField32<false>(OFFSET_OF_OBJECT_MEMBER(Class, object_size_), new_object_size);
- }
+ ALWAYS_INLINE void SetObjectSize(uint32_t new_object_size) REQUIRES_SHARED(Locks::mutator_lock_);
void SetObjectSizeAllocFastPath(uint32_t new_object_size) REQUIRES_SHARED(Locks::mutator_lock_);
diff --git a/runtime/mirror/dex_cache-inl.h b/runtime/mirror/dex_cache-inl.h
index 5d3af50..37a67e8 100644
--- a/runtime/mirror/dex_cache-inl.h
+++ b/runtime/mirror/dex_cache-inl.h
@@ -20,7 +20,7 @@
#include "dex_cache.h"
#include "art_field-inl.h"
-#include "art_method-inl.h"
+#include "art_method.h"
#include "base/casts.h"
#include "base/enums.h"
#include "base/logging.h"
diff --git a/runtime/mirror/dex_cache_test.cc b/runtime/mirror/dex_cache_test.cc
index 71a47f6..a110ed7 100644
--- a/runtime/mirror/dex_cache_test.cc
+++ b/runtime/mirror/dex_cache_test.cc
@@ -18,6 +18,7 @@
#include <stdio.h>
+#include "art_method-inl.h"
#include "class_linker.h"
#include "common_runtime_test.h"
#include "linear_alloc.h"
diff --git a/runtime/mirror/method_handle_impl-inl.h b/runtime/mirror/method_handle_impl-inl.h
new file mode 100644
index 0000000..0840d16
--- /dev/null
+++ b/runtime/mirror/method_handle_impl-inl.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ART_RUNTIME_MIRROR_METHOD_HANDLE_IMPL_INL_H_
+#define ART_RUNTIME_MIRROR_METHOD_HANDLE_IMPL_INL_H_
+
+#include "method_handle_impl.h"
+
+#include "art_method-inl.h"
+#include "object-inl.h"
+
+namespace art {
+namespace mirror {
+
+inline mirror::MethodType* MethodHandle::GetMethodType() {
+ return GetFieldObject<mirror::MethodType>(OFFSET_OF_OBJECT_MEMBER(MethodHandle, method_type_));
+}
+
+inline mirror::MethodType* MethodHandle::GetNominalType() {
+ return GetFieldObject<mirror::MethodType>(OFFSET_OF_OBJECT_MEMBER(MethodHandle, nominal_type_));
+}
+
+inline ObjPtr<mirror::Class> MethodHandle::GetTargetClass() {
+ Kind kind = GetHandleKind();
+ return (kind <= kLastValidKind) ?
+ GetTargetMethod()->GetDeclaringClass() : GetTargetField()->GetDeclaringClass();
+}
+
+} // namespace mirror
+} // namespace art
+
+#endif // ART_RUNTIME_MIRROR_METHOD_HANDLE_IMPL_INL_H_
diff --git a/runtime/mirror/method_handle_impl.cc b/runtime/mirror/method_handle_impl.cc
index fa4d25a..42b8473 100644
--- a/runtime/mirror/method_handle_impl.cc
+++ b/runtime/mirror/method_handle_impl.cc
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "method_handle_impl.h"
+#include "method_handle_impl-inl.h"
#include "class-inl.h"
#include "gc_root-inl.h"
@@ -42,6 +42,10 @@
GcRoot<mirror::Class> MethodHandleImpl::static_class_;
+mirror::Class* MethodHandleImpl::StaticClass() {
+ return static_class_.Read();
+}
+
void MethodHandleImpl::SetClass(Class* klass) {
CHECK(static_class_.IsNull()) << static_class_.Read() << " " << klass;
CHECK(klass != nullptr);
diff --git a/runtime/mirror/method_handle_impl.h b/runtime/mirror/method_handle_impl.h
index 9938af8..c598fa3 100644
--- a/runtime/mirror/method_handle_impl.h
+++ b/runtime/mirror/method_handle_impl.h
@@ -21,7 +21,7 @@
#include "art_method.h"
#include "class.h"
#include "gc_root.h"
-#include "object-inl.h"
+#include "object.h"
#include "method_type.h"
namespace art {
@@ -65,13 +65,9 @@
return static_cast<Kind>(handle_kind);
}
- mirror::MethodType* GetMethodType() REQUIRES_SHARED(Locks::mutator_lock_) {
- return GetFieldObject<mirror::MethodType>(OFFSET_OF_OBJECT_MEMBER(MethodHandle, method_type_));
- }
+ ALWAYS_INLINE mirror::MethodType* GetMethodType() REQUIRES_SHARED(Locks::mutator_lock_);
- mirror::MethodType* GetNominalType() REQUIRES_SHARED(Locks::mutator_lock_) {
- return GetFieldObject<mirror::MethodType>(OFFSET_OF_OBJECT_MEMBER(MethodHandle, nominal_type_));
- }
+ ALWAYS_INLINE mirror::MethodType* GetNominalType() REQUIRES_SHARED(Locks::mutator_lock_);
ArtField* GetTargetField() REQUIRES_SHARED(Locks::mutator_lock_) {
return reinterpret_cast<ArtField*>(
@@ -83,11 +79,7 @@
GetField64(OFFSET_OF_OBJECT_MEMBER(MethodHandle, art_field_or_method_)));
}
- ObjPtr<mirror::Class> GetTargetClass() REQUIRES_SHARED(Locks::mutator_lock_) {
- Kind kind = GetHandleKind();
- return (kind <= kLastValidKind) ?
- GetTargetMethod()->GetDeclaringClass() : GetTargetField()->GetDeclaringClass();
- }
+ ALWAYS_INLINE ObjPtr<mirror::Class> GetTargetClass() REQUIRES_SHARED(Locks::mutator_lock_);
static mirror::Class* StaticClass() REQUIRES_SHARED(Locks::mutator_lock_);
@@ -132,9 +124,7 @@
Handle<MethodType> method_type)
REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(!Roles::uninterruptible_);
- static mirror::Class* StaticClass() REQUIRES_SHARED(Locks::mutator_lock_) {
- return static_class_.Read();
- }
+ static mirror::Class* StaticClass() REQUIRES_SHARED(Locks::mutator_lock_);
static void SetClass(Class* klass) REQUIRES_SHARED(Locks::mutator_lock_);
static void ResetClass() REQUIRES_SHARED(Locks::mutator_lock_);
diff --git a/runtime/mirror/method_handles_lookup.cc b/runtime/mirror/method_handles_lookup.cc
index c758e54..0c25fa8 100644
--- a/runtime/mirror/method_handles_lookup.cc
+++ b/runtime/mirror/method_handles_lookup.cc
@@ -16,7 +16,7 @@
#include "method_handles_lookup.h"
-#include "class.h"
+#include "class-inl.h"
#include "gc_root-inl.h"
#include "object-inl.h"
#include "handle_scope.h"
diff --git a/runtime/mirror/method_type_test.cc b/runtime/mirror/method_type_test.cc
index 41231ef..a361772 100644
--- a/runtime/mirror/method_type_test.cc
+++ b/runtime/mirror/method_type_test.cc
@@ -20,7 +20,7 @@
#include <vector>
#include "class-inl.h"
-#include "class_linker.h"
+#include "class_linker-inl.h"
#include "class_loader.h"
#include "common_runtime_test.h"
#include "handle_scope-inl.h"
diff --git a/runtime/mirror/object-inl.h b/runtime/mirror/object-inl.h
index f83645e..aaa590b 100644
--- a/runtime/mirror/object-inl.h
+++ b/runtime/mirror/object-inl.h
@@ -23,7 +23,7 @@
#include "art_method.h"
#include "atomic.h"
#include "array-inl.h"
-#include "class.h"
+#include "class-inl.h"
#include "class_flags.h"
#include "class_linker.h"
#include "class_loader-inl.h"
@@ -798,19 +798,6 @@
return atomic_addr->CompareExchangeStrongSequentiallyConsistent(old_value, new_value);
}
-template<VerifyObjectFlags kVerifyFlags, bool kIsVolatile>
-inline int64_t Object::GetField64(MemberOffset field_offset) {
- if (kVerifyFlags & kVerifyThis) {
- VerifyObject(this);
- }
- return GetField<int64_t, kIsVolatile>(field_offset);
-}
-
-template<VerifyObjectFlags kVerifyFlags>
-inline int64_t Object::GetField64Volatile(MemberOffset field_offset) {
- return GetField64<kVerifyFlags, true>(field_offset);
-}
-
template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags,
bool kIsVolatile>
inline void Object::SetField64(MemberOffset field_offset, int64_t new_value) {
@@ -1186,67 +1173,6 @@
return down_cast<mirror::DexCache*>(this);
}
-template <bool kVisitNativeRoots,
- VerifyObjectFlags kVerifyFlags,
- ReadBarrierOption kReadBarrierOption,
- typename Visitor,
- typename JavaLangRefVisitor>
-inline void Object::VisitReferences(const Visitor& visitor,
- const JavaLangRefVisitor& ref_visitor) {
- ObjPtr<Class> klass = GetClass<kVerifyFlags, kReadBarrierOption>();
- visitor(this, ClassOffset(), false);
- const uint32_t class_flags = klass->GetClassFlags<kVerifyNone>();
- if (LIKELY(class_flags == kClassFlagNormal)) {
- DCHECK((!klass->IsVariableSize<kVerifyFlags, kReadBarrierOption>()));
- VisitInstanceFieldsReferences<kVerifyFlags, kReadBarrierOption>(klass, visitor);
- DCHECK((!klass->IsClassClass<kVerifyFlags, kReadBarrierOption>()));
- DCHECK(!klass->IsStringClass());
- DCHECK(!klass->IsClassLoaderClass());
- DCHECK((!klass->IsArrayClass<kVerifyFlags, kReadBarrierOption>()));
- } else {
- if ((class_flags & kClassFlagNoReferenceFields) == 0) {
- DCHECK(!klass->IsStringClass());
- if (class_flags == kClassFlagClass) {
- DCHECK((klass->IsClassClass<kVerifyFlags, kReadBarrierOption>()));
- ObjPtr<Class> as_klass = AsClass<kVerifyNone, kReadBarrierOption>();
- as_klass->VisitReferences<kVisitNativeRoots, kVerifyFlags, kReadBarrierOption>(klass,
- visitor);
- } else if (class_flags == kClassFlagObjectArray) {
- DCHECK((klass->IsObjectArrayClass<kVerifyFlags, kReadBarrierOption>()));
- AsObjectArray<mirror::Object, kVerifyNone, kReadBarrierOption>()->VisitReferences(visitor);
- } else if ((class_flags & kClassFlagReference) != 0) {
- VisitInstanceFieldsReferences<kVerifyFlags, kReadBarrierOption>(klass, visitor);
- ref_visitor(klass, AsReference<kVerifyFlags, kReadBarrierOption>());
- } else if (class_flags == kClassFlagDexCache) {
- mirror::DexCache* const dex_cache = AsDexCache<kVerifyFlags, kReadBarrierOption>();
- dex_cache->VisitReferences<kVisitNativeRoots,
- kVerifyFlags,
- kReadBarrierOption>(klass, visitor);
- } else {
- mirror::ClassLoader* const class_loader = AsClassLoader<kVerifyFlags, kReadBarrierOption>();
- class_loader->VisitReferences<kVisitNativeRoots,
- kVerifyFlags,
- kReadBarrierOption>(klass, visitor);
- }
- } else if (kIsDebugBuild) {
- CHECK((!klass->IsClassClass<kVerifyFlags, kReadBarrierOption>()));
- CHECK((!klass->IsObjectArrayClass<kVerifyFlags, kReadBarrierOption>()));
- // String still has instance fields for reflection purposes but these don't exist in
- // actual string instances.
- if (!klass->IsStringClass()) {
- size_t total_reference_instance_fields = 0;
- ObjPtr<Class> super_class = klass;
- do {
- total_reference_instance_fields += super_class->NumReferenceInstanceFields();
- 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);
- }
- }
- }
-}
} // namespace mirror
} // namespace art
diff --git a/runtime/mirror/object-refvisitor-inl.h b/runtime/mirror/object-refvisitor-inl.h
new file mode 100644
index 0000000..49ab7c2
--- /dev/null
+++ b/runtime/mirror/object-refvisitor-inl.h
@@ -0,0 +1,92 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ART_RUNTIME_MIRROR_OBJECT_REFVISITOR_INL_H_
+#define ART_RUNTIME_MIRROR_OBJECT_REFVISITOR_INL_H_
+
+#include "object-inl.h"
+
+#include "class-refvisitor-inl.h"
+
+namespace art {
+namespace mirror {
+
+template <bool kVisitNativeRoots,
+ VerifyObjectFlags kVerifyFlags,
+ ReadBarrierOption kReadBarrierOption,
+ typename Visitor,
+ typename JavaLangRefVisitor>
+inline void Object::VisitReferences(const Visitor& visitor,
+ const JavaLangRefVisitor& ref_visitor) {
+ ObjPtr<Class> klass = GetClass<kVerifyFlags, kReadBarrierOption>();
+ visitor(this, ClassOffset(), false);
+ const uint32_t class_flags = klass->GetClassFlags<kVerifyNone>();
+ if (LIKELY(class_flags == kClassFlagNormal)) {
+ DCHECK((!klass->IsVariableSize<kVerifyFlags, kReadBarrierOption>()));
+ VisitInstanceFieldsReferences<kVerifyFlags, kReadBarrierOption>(klass, visitor);
+ DCHECK((!klass->IsClassClass<kVerifyFlags, kReadBarrierOption>()));
+ DCHECK(!klass->IsStringClass());
+ DCHECK(!klass->IsClassLoaderClass());
+ DCHECK((!klass->IsArrayClass<kVerifyFlags, kReadBarrierOption>()));
+ } else {
+ if ((class_flags & kClassFlagNoReferenceFields) == 0) {
+ DCHECK(!klass->IsStringClass());
+ if (class_flags == kClassFlagClass) {
+ DCHECK((klass->IsClassClass<kVerifyFlags, kReadBarrierOption>()));
+ ObjPtr<Class> as_klass = AsClass<kVerifyNone, kReadBarrierOption>();
+ as_klass->VisitReferences<kVisitNativeRoots, kVerifyFlags, kReadBarrierOption>(klass,
+ visitor);
+ } else if (class_flags == kClassFlagObjectArray) {
+ DCHECK((klass->IsObjectArrayClass<kVerifyFlags, kReadBarrierOption>()));
+ AsObjectArray<mirror::Object, kVerifyNone, kReadBarrierOption>()->VisitReferences(visitor);
+ } else if ((class_flags & kClassFlagReference) != 0) {
+ VisitInstanceFieldsReferences<kVerifyFlags, kReadBarrierOption>(klass, visitor);
+ ref_visitor(klass, AsReference<kVerifyFlags, kReadBarrierOption>());
+ } else if (class_flags == kClassFlagDexCache) {
+ mirror::DexCache* const dex_cache = AsDexCache<kVerifyFlags, kReadBarrierOption>();
+ dex_cache->VisitReferences<kVisitNativeRoots,
+ kVerifyFlags,
+ kReadBarrierOption>(klass, visitor);
+ } else {
+ mirror::ClassLoader* const class_loader = AsClassLoader<kVerifyFlags, kReadBarrierOption>();
+ class_loader->VisitReferences<kVisitNativeRoots,
+ kVerifyFlags,
+ kReadBarrierOption>(klass, visitor);
+ }
+ } else if (kIsDebugBuild) {
+ CHECK((!klass->IsClassClass<kVerifyFlags, kReadBarrierOption>()));
+ CHECK((!klass->IsObjectArrayClass<kVerifyFlags, kReadBarrierOption>()));
+ // String still has instance fields for reflection purposes but these don't exist in
+ // actual string instances.
+ if (!klass->IsStringClass()) {
+ size_t total_reference_instance_fields = 0;
+ ObjPtr<Class> super_class = klass;
+ do {
+ total_reference_instance_fields += super_class->NumReferenceInstanceFields();
+ 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);
+ }
+ }
+ }
+}
+
+} // namespace mirror
+} // namespace art
+
+#endif // ART_RUNTIME_MIRROR_OBJECT_REFVISITOR_INL_H_
diff --git a/runtime/mirror/object.cc b/runtime/mirror/object.cc
index eabc29a..6e5fdb7 100644
--- a/runtime/mirror/object.cc
+++ b/runtime/mirror/object.cc
@@ -30,6 +30,7 @@
#include "iftable-inl.h"
#include "monitor.h"
#include "object-inl.h"
+#include "object-refvisitor-inl.h"
#include "object_array-inl.h"
#include "runtime.h"
#include "handle_scope-inl.h"
diff --git a/runtime/mirror/object.h b/runtime/mirror/object.h
index 417a22d..35a1b73 100644
--- a/runtime/mirror/object.h
+++ b/runtime/mirror/object.h
@@ -487,11 +487,18 @@
template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags, bool kIsVolatile = false>
ALWAYS_INLINE int64_t GetField64(MemberOffset field_offset)
- REQUIRES_SHARED(Locks::mutator_lock_);
+ REQUIRES_SHARED(Locks::mutator_lock_) {
+ if (kVerifyFlags & kVerifyThis) {
+ VerifyObject(this);
+ }
+ return GetField<int64_t, kIsVolatile>(field_offset);
+ }
template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
ALWAYS_INLINE int64_t GetField64Volatile(MemberOffset field_offset)
- REQUIRES_SHARED(Locks::mutator_lock_);
+ REQUIRES_SHARED(Locks::mutator_lock_) {
+ return GetField64<kVerifyFlags, true>(field_offset);
+ }
template<bool kTransactionActive, bool kCheckTransaction = true,
VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags, bool kIsVolatile = false>
diff --git a/runtime/mirror/object_test.cc b/runtime/mirror/object_test.cc
index d306f9c..d7527d5 100644
--- a/runtime/mirror/object_test.cc
+++ b/runtime/mirror/object_test.cc
@@ -73,6 +73,13 @@
}
EXPECT_EQ(expected_hash, string->GetHashCode());
}
+
+ template <class T>
+ mirror::ObjectArray<T>* AllocObjectArray(Thread* self, size_t length)
+ REQUIRES_SHARED(Locks::mutator_lock_) {
+ return mirror::ObjectArray<T>::Alloc(
+ self, class_linker_->GetClassRoot(ClassLinker::ClassRoot::kObjectArrayClass), length);
+ }
};
// Keep constants in sync.
@@ -100,8 +107,7 @@
TEST_F(ObjectTest, Clone) {
ScopedObjectAccess soa(Thread::Current());
StackHandleScope<2> hs(soa.Self());
- Handle<ObjectArray<Object>> a1(
- hs.NewHandle(class_linker_->AllocObjectArray<Object>(soa.Self(), 256)));
+ Handle<ObjectArray<Object>> a1(hs.NewHandle(AllocObjectArray<Object>(soa.Self(), 256)));
size_t s1 = a1->SizeOf();
Object* clone = a1->Clone(soa.Self());
EXPECT_EQ(s1, clone->SizeOf());
@@ -111,8 +117,7 @@
TEST_F(ObjectTest, AllocObjectArray) {
ScopedObjectAccess soa(Thread::Current());
StackHandleScope<2> hs(soa.Self());
- Handle<ObjectArray<Object>> oa(
- hs.NewHandle(class_linker_->AllocObjectArray<Object>(soa.Self(), 2)));
+ Handle<ObjectArray<Object>> oa(hs.NewHandle(AllocObjectArray<Object>(soa.Self(), 2)));
EXPECT_EQ(2, oa->GetLength());
EXPECT_TRUE(oa->Get(0) == nullptr);
EXPECT_TRUE(oa->Get(1) == nullptr);