ART: Move DexCache arrays to native.
This CL has a companion CL in libcore/
https://android-review.googlesource.com/162985
Change-Id: Icbc9e20ad1b565e603195b12714762bb446515fa
diff --git a/runtime/mirror/class-inl.h b/runtime/mirror/class-inl.h
index b2c6e4d..10b381d 100644
--- a/runtime/mirror/class-inl.h
+++ b/runtime/mirror/class-inl.h
@@ -817,12 +817,12 @@
}
}
-inline void Class::SetDexCacheStrings(ObjectArray<String>* new_dex_cache_strings) {
- SetFieldObject<false>(DexCacheStringsOffset(), new_dex_cache_strings);
+inline void Class::SetDexCacheStrings(GcRoot<String>* new_dex_cache_strings) {
+ SetFieldPtr<false>(DexCacheStringsOffset(), new_dex_cache_strings);
}
-inline ObjectArray<String>* Class::GetDexCacheStrings() {
- return GetFieldObject<ObjectArray<String>>(DexCacheStringsOffset());
+inline GcRoot<String>* Class::GetDexCacheStrings() {
+ return GetFieldPtr<GcRoot<String>*>(DexCacheStringsOffset());
}
template<class Visitor>
diff --git a/runtime/mirror/class.h b/runtime/mirror/class.h
index 1420e5b..9422432 100644
--- a/runtime/mirror/class.h
+++ b/runtime/mirror/class.h
@@ -250,6 +250,14 @@
SetClassFlags(kClassFlagClassLoader);
}
+ ALWAYS_INLINE bool IsDexCacheClass() SHARED_REQUIRES(Locks::mutator_lock_) {
+ return (GetClassFlags() & kClassFlagDexCache) != 0;
+ }
+
+ ALWAYS_INLINE void SetDexCacheClass() SHARED_REQUIRES(Locks::mutator_lock_) {
+ SetClassFlags(GetClassFlags() | kClassFlagDexCache);
+ }
+
// Returns true if the class is abstract.
ALWAYS_INLINE bool IsAbstract() SHARED_REQUIRES(Locks::mutator_lock_) {
return (GetAccessFlags() & kAccAbstract) != 0;
@@ -1077,8 +1085,8 @@
bool GetSlowPathEnabled() SHARED_REQUIRES(Locks::mutator_lock_);
void SetSlowPath(bool enabled) SHARED_REQUIRES(Locks::mutator_lock_);
- ObjectArray<String>* GetDexCacheStrings() SHARED_REQUIRES(Locks::mutator_lock_);
- void SetDexCacheStrings(ObjectArray<String>* new_dex_cache_strings)
+ GcRoot<String>* GetDexCacheStrings() SHARED_REQUIRES(Locks::mutator_lock_);
+ void SetDexCacheStrings(GcRoot<String>* new_dex_cache_strings)
SHARED_REQUIRES(Locks::mutator_lock_);
static MemberOffset DexCacheStringsOffset() {
return OFFSET_OF_OBJECT_MEMBER(Class, dex_cache_strings_);
@@ -1173,9 +1181,6 @@
// runtime such as arrays and primitive classes).
HeapReference<DexCache> dex_cache_;
- // Short cuts to dex_cache_ member for fast compiled code access.
- HeapReference<ObjectArray<String>> dex_cache_strings_;
-
// The interface table (iftable_) contains pairs of a interface class and an array of the
// interface methods. There is one pair per interface supported by this class. That means one
// pair for each interface we support directly, indirectly via superclass, or indirectly via a
@@ -1209,9 +1214,8 @@
// virtual_ methods_ for miranda methods.
HeapReference<PointerArray> vtable_;
- // Access flags; low 16 bits are defined by VM spec.
- // Note: Shuffled back.
- uint32_t access_flags_;
+ // Short cuts to dex_cache_ member for fast compiled code access.
+ uint64_t dex_cache_strings_;
// static, private, and <init> methods. Pointer to an ArtMethod length-prefixed array.
uint64_t direct_methods_;
@@ -1234,6 +1238,9 @@
// length-prefixed array.
uint64_t virtual_methods_;
+ // Access flags; low 16 bits are defined by VM spec.
+ uint32_t access_flags_;
+
// Class flags to help speed up visiting object references.
uint32_t class_flags_;
diff --git a/runtime/mirror/class_flags.h b/runtime/mirror/class_flags.h
index eb2e2eb..139c4cb 100644
--- a/runtime/mirror/class_flags.h
+++ b/runtime/mirror/class_flags.h
@@ -41,17 +41,20 @@
// 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 = 0x00000040;
+static constexpr uint32_t kClassFlagSoftReference = 0x00000080;
// Class is a weak reference class.
-static constexpr uint32_t kClassFlagWeakReference = 0x00000080;
+static constexpr uint32_t kClassFlagWeakReference = 0x00000100;
// Class is a finalizer reference class.
-static constexpr uint32_t kClassFlagFinalizerReference = 0x00000100;
+static constexpr uint32_t kClassFlagFinalizerReference = 0x00000200;
// Class is the phantom reference class.
-static constexpr uint32_t kClassFlagPhantomReference = 0x00000200;
+static constexpr uint32_t kClassFlagPhantomReference = 0x00000400;
// Combination of flags to figure out if the class is either the weak/soft/phantom/finalizer
// reference class.
diff --git a/runtime/mirror/dex_cache-inl.h b/runtime/mirror/dex_cache-inl.h
index 4b5063a..f8ccfb1 100644
--- a/runtime/mirror/dex_cache-inl.h
+++ b/runtime/mirror/dex_cache-inl.h
@@ -21,6 +21,7 @@
#include "art_field-inl.h"
#include "art_method-inl.h"
+#include "base/casts.h"
#include "base/logging.h"
#include "mirror/class.h"
#include "runtime.h"
@@ -33,29 +34,53 @@
return Class::ComputeClassSize(true, vtable_entries, 0, 0, 0, 0, 0, pointer_size);
}
-inline void DexCache::SetResolvedType(uint32_t type_idx, Class* resolved) {
- // TODO default transaction support.
- DCHECK(resolved == nullptr || !resolved->IsErroneous());
- GetResolvedTypes()->Set(type_idx, resolved);
+inline String* DexCache::GetResolvedString(uint32_t string_idx) {
+ DCHECK_LT(string_idx, NumStrings());
+ return GetStrings()[string_idx].Read();
}
-inline ArtField* DexCache::GetResolvedField(uint32_t idx, size_t ptr_size) {
+inline void DexCache::SetResolvedString(uint32_t string_idx, String* resolved) {
+ DCHECK_LT(string_idx, NumStrings());
+ // TODO default transaction support.
+ GetStrings()[string_idx] = GcRoot<String>(resolved);
+ // TODO: Fine-grained marking, so that we don't need to go through all arrays in full.
+ Runtime::Current()->GetHeap()->WriteBarrierEveryFieldOf(this);
+}
+
+inline Class* DexCache::GetResolvedType(uint32_t type_idx) {
+ DCHECK_LT(type_idx, NumResolvedTypes());
+ return GetResolvedTypes()[type_idx].Read();
+}
+
+inline void DexCache::SetResolvedType(uint32_t type_idx, Class* resolved) {
+ DCHECK_LT(type_idx, NumResolvedTypes()); // NOTE: Unchecked, i.e. not throwing AIOOB.
+ // TODO default transaction support.
+ DCHECK(resolved == nullptr || !resolved->IsErroneous());
+ GetResolvedTypes()[type_idx] = GcRoot<Class>(resolved);
+ // TODO: Fine-grained marking, so that we don't need to go through all arrays in full.
+ Runtime::Current()->GetHeap()->WriteBarrierEveryFieldOf(this);
+}
+
+inline ArtField* DexCache::GetResolvedField(uint32_t field_idx, size_t ptr_size) {
DCHECK_EQ(Runtime::Current()->GetClassLinker()->GetImagePointerSize(), ptr_size);
- auto* field = GetResolvedFields()->GetElementPtrSize<ArtField*>(idx, ptr_size);
+ DCHECK_LT(field_idx, NumResolvedFields()); // NOTE: Unchecked, i.e. not throwing AIOOB.
+ ArtField* field = GetElementPtrSize(GetResolvedFields(), field_idx, ptr_size);
if (field == nullptr || field->GetDeclaringClass()->IsErroneous()) {
return nullptr;
}
return field;
}
-inline void DexCache::SetResolvedField(uint32_t idx, ArtField* field, size_t ptr_size) {
+inline void DexCache::SetResolvedField(uint32_t field_idx, ArtField* field, size_t ptr_size) {
DCHECK_EQ(Runtime::Current()->GetClassLinker()->GetImagePointerSize(), ptr_size);
- GetResolvedFields()->SetElementPtrSize(idx, field, ptr_size);
+ DCHECK_LT(field_idx, NumResolvedFields()); // NOTE: Unchecked, i.e. not throwing AIOOB.
+ SetElementPtrSize(GetResolvedFields(), field_idx, field, ptr_size);
}
inline ArtMethod* DexCache::GetResolvedMethod(uint32_t method_idx, size_t ptr_size) {
DCHECK_EQ(Runtime::Current()->GetClassLinker()->GetImagePointerSize(), ptr_size);
- auto* method = GetResolvedMethods()->GetElementPtrSize<ArtMethod*>(method_idx, ptr_size);
+ DCHECK_LT(method_idx, NumResolvedMethods()); // NOTE: Unchecked, i.e. not throwing AIOOB.
+ ArtMethod* method = GetElementPtrSize<ArtMethod*>(GetResolvedMethods(), method_idx, ptr_size);
// Hide resolution trampoline methods from the caller
if (method != nullptr && method->IsRuntimeMethod()) {
DCHECK_EQ(method, Runtime::Current()->GetResolutionMethod());
@@ -64,9 +89,52 @@
return method;
}
-inline void DexCache::SetResolvedMethod(uint32_t idx, ArtMethod* method, size_t ptr_size) {
+inline void DexCache::SetResolvedMethod(uint32_t method_idx, ArtMethod* method, size_t ptr_size) {
DCHECK_EQ(Runtime::Current()->GetClassLinker()->GetImagePointerSize(), ptr_size);
- GetResolvedMethods()->SetElementPtrSize(idx, method, ptr_size);
+ DCHECK_LT(method_idx, NumResolvedMethods()); // NOTE: Unchecked, i.e. not throwing AIOOB.
+ SetElementPtrSize(GetResolvedMethods(), method_idx, method, ptr_size);
+}
+
+template <typename PtrType>
+inline PtrType DexCache::GetElementPtrSize(PtrType* ptr_array, size_t idx, size_t ptr_size) {
+ if (ptr_size == 8u) {
+ uint64_t element = reinterpret_cast<const uint64_t*>(ptr_array)[idx];
+ return reinterpret_cast<PtrType>(dchecked_integral_cast<uintptr_t>(element));
+ } else {
+ DCHECK_EQ(ptr_size, 4u);
+ uint32_t element = reinterpret_cast<const uint32_t*>(ptr_array)[idx];
+ return reinterpret_cast<PtrType>(dchecked_integral_cast<uintptr_t>(element));
+ }
+}
+
+template <typename PtrType>
+inline void DexCache::SetElementPtrSize(PtrType* ptr_array,
+ size_t idx,
+ PtrType ptr,
+ size_t ptr_size) {
+ if (ptr_size == 8u) {
+ reinterpret_cast<uint64_t*>(ptr_array)[idx] =
+ dchecked_integral_cast<uint64_t>(reinterpret_cast<uintptr_t>(ptr));
+ } else {
+ DCHECK_EQ(ptr_size, 4u);
+ reinterpret_cast<uint32_t*>(ptr_array)[idx] =
+ dchecked_integral_cast<uint32_t>(reinterpret_cast<uintptr_t>(ptr));
+ }
+}
+
+template <VerifyObjectFlags kVerifyFlags, typename Visitor>
+inline void DexCache::VisitReferences(mirror::Class* klass, const Visitor& visitor) {
+ // Visit instance fields first.
+ VisitInstanceFieldsReferences(klass, visitor);
+ // Visit arrays after.
+ GcRoot<mirror::String>* strings = GetStrings();
+ for (size_t i = 0, num_strings = NumStrings(); i != num_strings; ++i) {
+ visitor.VisitRootIfNonNull(strings[i].AddressWithoutBarrier());
+ }
+ GcRoot<mirror::Class>* resolved_types = GetResolvedTypes();
+ for (size_t i = 0, num_types = NumResolvedTypes(); i != num_types; ++i) {
+ visitor.VisitRootIfNonNull(resolved_types[i].AddressWithoutBarrier());
+ }
}
} // namespace mirror
diff --git a/runtime/mirror/dex_cache.cc b/runtime/mirror/dex_cache.cc
index 630faee..349a319 100644
--- a/runtime/mirror/dex_cache.cc
+++ b/runtime/mirror/dex_cache.cc
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "dex_cache.h"
+#include "dex_cache-inl.h"
#include "art_method-inl.h"
#include "base/logging.h"
@@ -31,22 +31,34 @@
namespace art {
namespace mirror {
-void DexCache::Init(const DexFile* dex_file, String* location, ObjectArray<String>* strings,
- ObjectArray<Class>* resolved_types, PointerArray* resolved_methods,
- PointerArray* resolved_fields, size_t pointer_size) {
+void DexCache::Init(const DexFile* dex_file,
+ String* location,
+ GcRoot<String>* strings,
+ uint32_t num_strings,
+ GcRoot<Class>* resolved_types,
+ uint32_t num_resolved_types,
+ ArtMethod** resolved_methods,
+ uint32_t num_resolved_methods,
+ ArtField** resolved_fields,
+ uint32_t num_resolved_fields,
+ size_t pointer_size) {
CHECK(dex_file != nullptr);
CHECK(location != nullptr);
- CHECK(strings != nullptr);
- CHECK(resolved_types != nullptr);
- CHECK(resolved_methods != nullptr);
- CHECK(resolved_fields != nullptr);
+ CHECK_EQ(num_strings != 0u, strings != nullptr);
+ CHECK_EQ(num_resolved_types != 0u, resolved_types != nullptr);
+ CHECK_EQ(num_resolved_methods != 0u, resolved_methods != nullptr);
+ CHECK_EQ(num_resolved_fields != 0u, resolved_fields != nullptr);
SetDexFile(dex_file);
SetFieldObject<false>(OFFSET_OF_OBJECT_MEMBER(DexCache, location_), location);
- SetFieldObject<false>(StringsOffset(), strings);
- SetFieldObject<false>(ResolvedFieldsOffset(), resolved_fields);
- SetFieldObject<false>(OFFSET_OF_OBJECT_MEMBER(DexCache, resolved_types_), resolved_types);
- SetFieldObject<false>(ResolvedMethodsOffset(), resolved_methods);
+ SetField64<false>(StringsOffset(), reinterpret_cast<uintptr_t>(strings));
+ SetField64<false>(ResolvedTypesOffset(), reinterpret_cast<uintptr_t>(resolved_types));
+ SetField64<false>(ResolvedMethodsOffset(), reinterpret_cast<uintptr_t>(resolved_methods));
+ SetField64<false>(ResolvedFieldsOffset(), reinterpret_cast<uintptr_t>(resolved_fields));
+ SetField32<false>(NumStringsOffset(), num_strings);
+ SetField32<false>(NumResolvedTypesOffset(), num_resolved_types);
+ SetField32<false>(NumResolvedMethodsOffset(), num_resolved_methods);
+ SetField32<false>(NumResolvedFieldsOffset(), num_resolved_fields);
Runtime* const runtime = Runtime::Current();
if (runtime->HasResolutionMethod()) {
@@ -60,9 +72,9 @@
CHECK(trampoline != nullptr);
CHECK(trampoline->IsRuntimeMethod());
auto* resolved_methods = GetResolvedMethods();
- for (size_t i = 0, length = resolved_methods->GetLength(); i < length; i++) {
- if (resolved_methods->GetElementPtrSize<ArtMethod*>(i, pointer_size) == nullptr) {
- resolved_methods->SetElementPtrSize(i, trampoline, pointer_size);
+ for (size_t i = 0, length = NumResolvedMethods(); i < length; i++) {
+ if (GetElementPtrSize<ArtMethod*>(resolved_methods, i, pointer_size) == nullptr) {
+ SetElementPtrSize(resolved_methods, i, trampoline, pointer_size);
}
}
}
diff --git a/runtime/mirror/dex_cache.h b/runtime/mirror/dex_cache.h
index ba49a15..3144553 100644
--- a/runtime/mirror/dex_cache.h
+++ b/runtime/mirror/dex_cache.h
@@ -46,8 +46,16 @@
return sizeof(DexCache);
}
- void Init(const DexFile* dex_file, String* location, ObjectArray<String>* strings,
- ObjectArray<Class>* types, PointerArray* methods, PointerArray* fields,
+ void Init(const DexFile* dex_file,
+ String* location,
+ GcRoot<String>* strings,
+ uint32_t num_strings,
+ GcRoot<Class>* resolved_types,
+ uint32_t num_resolved_types,
+ ArtMethod** resolved_methods,
+ uint32_t num_resolved_methods,
+ ArtField** resolved_fields,
+ uint32_t num_resolved_fields,
size_t pointer_size) SHARED_REQUIRES(Locks::mutator_lock_);
void Fixup(ArtMethod* trampoline, size_t pointer_size)
@@ -65,6 +73,10 @@
return OFFSET_OF_OBJECT_MEMBER(DexCache, strings_);
}
+ static MemberOffset ResolvedTypesOffset() {
+ return OFFSET_OF_OBJECT_MEMBER(DexCache, resolved_types_);
+ }
+
static MemberOffset ResolvedFieldsOffset() {
return OFFSET_OF_OBJECT_MEMBER(DexCache, resolved_fields_);
}
@@ -73,40 +85,32 @@
return OFFSET_OF_OBJECT_MEMBER(DexCache, resolved_methods_);
}
- size_t NumStrings() SHARED_REQUIRES(Locks::mutator_lock_) {
- return GetStrings()->GetLength();
+ static MemberOffset NumStringsOffset() {
+ return OFFSET_OF_OBJECT_MEMBER(DexCache, num_strings_);
}
- size_t NumResolvedTypes() SHARED_REQUIRES(Locks::mutator_lock_) {
- return GetResolvedTypes()->GetLength();
+ static MemberOffset NumResolvedTypesOffset() {
+ return OFFSET_OF_OBJECT_MEMBER(DexCache, num_resolved_types_);
}
- size_t NumResolvedMethods() SHARED_REQUIRES(Locks::mutator_lock_) {
- return GetResolvedMethods()->GetLength();
+ static MemberOffset NumResolvedFieldsOffset() {
+ return OFFSET_OF_OBJECT_MEMBER(DexCache, num_resolved_fields_);
}
- size_t NumResolvedFields() SHARED_REQUIRES(Locks::mutator_lock_) {
- return GetResolvedFields()->GetLength();
+ static MemberOffset NumResolvedMethodsOffset() {
+ return OFFSET_OF_OBJECT_MEMBER(DexCache, num_resolved_methods_);
}
- String* GetResolvedString(uint32_t string_idx) SHARED_REQUIRES(Locks::mutator_lock_) {
- return GetStrings()->Get(string_idx);
- }
+ String* GetResolvedString(uint32_t string_idx) ALWAYS_INLINE
+ SHARED_REQUIRES(Locks::mutator_lock_);
void SetResolvedString(uint32_t string_idx, String* resolved) ALWAYS_INLINE
- SHARED_REQUIRES(Locks::mutator_lock_) {
- // TODO default transaction support.
- GetStrings()->Set(string_idx, resolved);
- }
-
- Class* GetResolvedType(uint32_t type_idx) ALWAYS_INLINE
- SHARED_REQUIRES(Locks::mutator_lock_) {
- return GetResolvedTypes()->Get(type_idx);
- }
-
- void SetResolvedType(uint32_t type_idx, Class* resolved)
SHARED_REQUIRES(Locks::mutator_lock_);
+ Class* GetResolvedType(uint32_t type_idx) SHARED_REQUIRES(Locks::mutator_lock_);
+
+ void SetResolvedType(uint32_t type_idx, Class* resolved) SHARED_REQUIRES(Locks::mutator_lock_);
+
ALWAYS_INLINE ArtMethod* GetResolvedMethod(uint32_t method_idx, size_t ptr_size)
SHARED_REQUIRES(Locks::mutator_lock_);
@@ -121,21 +125,36 @@
ALWAYS_INLINE void SetResolvedField(uint32_t idx, ArtField* field, size_t ptr_size)
SHARED_REQUIRES(Locks::mutator_lock_);
- ObjectArray<String>* GetStrings() ALWAYS_INLINE SHARED_REQUIRES(Locks::mutator_lock_) {
- return GetFieldObject<ObjectArray<String>>(StringsOffset());
+ GcRoot<String>* GetStrings() ALWAYS_INLINE SHARED_REQUIRES(Locks::mutator_lock_) {
+ return GetFieldPtr<GcRoot<String>*>(StringsOffset());
}
- ObjectArray<Class>* GetResolvedTypes() ALWAYS_INLINE SHARED_REQUIRES(Locks::mutator_lock_) {
- return GetFieldObject<ObjectArray<Class>>(
- OFFSET_OF_OBJECT_MEMBER(DexCache, resolved_types_));
+ GcRoot<Class>* GetResolvedTypes() ALWAYS_INLINE SHARED_REQUIRES(Locks::mutator_lock_) {
+ return GetFieldPtr<GcRoot<Class>*>(ResolvedTypesOffset());
}
- PointerArray* GetResolvedMethods() ALWAYS_INLINE SHARED_REQUIRES(Locks::mutator_lock_) {
- return GetFieldObject<PointerArray>(ResolvedMethodsOffset());
+ ArtMethod** GetResolvedMethods() ALWAYS_INLINE SHARED_REQUIRES(Locks::mutator_lock_) {
+ return GetFieldPtr<ArtMethod**>(ResolvedMethodsOffset());
}
- PointerArray* GetResolvedFields() ALWAYS_INLINE SHARED_REQUIRES(Locks::mutator_lock_) {
- return GetFieldObject<PointerArray>(ResolvedFieldsOffset());
+ ArtField** GetResolvedFields() ALWAYS_INLINE SHARED_REQUIRES(Locks::mutator_lock_) {
+ return GetFieldPtr<ArtField**>(ResolvedFieldsOffset());
+ }
+
+ size_t NumStrings() SHARED_REQUIRES(Locks::mutator_lock_) {
+ return GetField32(NumStringsOffset());
+ }
+
+ size_t NumResolvedTypes() SHARED_REQUIRES(Locks::mutator_lock_) {
+ return GetField32(NumResolvedTypesOffset());
+ }
+
+ size_t NumResolvedMethods() SHARED_REQUIRES(Locks::mutator_lock_) {
+ return GetField32(NumResolvedMethodsOffset());
+ }
+
+ size_t NumResolvedFields() SHARED_REQUIRES(Locks::mutator_lock_) {
+ return GetField32(NumResolvedFieldsOffset());
}
const DexFile* GetDexFile() ALWAYS_INLINE SHARED_REQUIRES(Locks::mutator_lock_) {
@@ -147,17 +166,36 @@
return SetFieldPtr<false>(OFFSET_OF_OBJECT_MEMBER(DexCache, dex_file_), dex_file);
}
+ // NOTE: Get/SetElementPtrSize() are intended for working with ArtMethod** and ArtField**
+ // provided by GetResolvedMethods/Fields() and ArtMethod::GetDexCacheResolvedMethods(),
+ // so they need to be public.
+
+ template <typename PtrType>
+ static PtrType GetElementPtrSize(PtrType* ptr_array, size_t idx, size_t ptr_size);
+
+ template <typename PtrType>
+ static void SetElementPtrSize(PtrType* ptr_array, size_t idx, PtrType ptr, size_t ptr_size);
+
private:
+ // Visit instance fields of the dex cache as well as its associated arrays.
+ template <VerifyObjectFlags kVerifyFlags, typename Visitor>
+ void VisitReferences(mirror::Class* klass, const Visitor& visitor)
+ SHARED_REQUIRES(Locks::mutator_lock_) REQUIRES(Locks::heap_bitmap_lock_);
+
HeapReference<Object> dex_;
HeapReference<String> location_;
- // Either an int array or long array based on runtime ISA since these arrays hold pointers.
- HeapReference<PointerArray> resolved_fields_;
- HeapReference<PointerArray> resolved_methods_;
- HeapReference<ObjectArray<Class>> resolved_types_;
- HeapReference<ObjectArray<String>> strings_;
- uint64_t dex_file_;
+ uint64_t dex_file_; // const DexFile*
+ uint64_t resolved_fields_; // ArtField*, array with num_resolved_fields_ elements.
+ uint64_t resolved_methods_; // ArtMethod*, array with num_resolved_methods_ elements.
+ uint64_t resolved_types_; // GcRoot<Class>*, array with num_resolved_types_ elements.
+ uint64_t strings_; // GcRoot<String>*, array with num_strings_ elements.
+ uint32_t num_resolved_fields_; // Number of elements in the resolved_fields_ array.
+ uint32_t num_resolved_methods_; // Number of elements in the resolved_methods_ array.
+ uint32_t num_resolved_types_; // Number of elements in the resolved_types_ array.
+ uint32_t num_strings_; // Number of elements in the strings_ array.
friend struct art::DexCacheOffsets; // for verifying offset information
+ friend class Object; // For VisitReferences
DISALLOW_IMPLICIT_CONSTRUCTORS(DexCache);
};
diff --git a/runtime/mirror/dex_cache_test.cc b/runtime/mirror/dex_cache_test.cc
index 228fce5..8fb860f 100644
--- a/runtime/mirror/dex_cache_test.cc
+++ b/runtime/mirror/dex_cache_test.cc
@@ -43,19 +43,6 @@
EXPECT_EQ(java_lang_dex_file_->NumTypeIds(), dex_cache->NumResolvedTypes());
EXPECT_EQ(java_lang_dex_file_->NumMethodIds(), dex_cache->NumResolvedMethods());
EXPECT_EQ(java_lang_dex_file_->NumFieldIds(), dex_cache->NumResolvedFields());
-
- EXPECT_LE(0, dex_cache->GetStrings()->GetLength());
- EXPECT_LE(0, dex_cache->GetResolvedTypes()->GetLength());
- EXPECT_LE(0, dex_cache->GetResolvedMethods()->GetLength());
- EXPECT_LE(0u, dex_cache->NumResolvedFields());
-
- EXPECT_EQ(java_lang_dex_file_->NumStringIds(),
- static_cast<uint32_t>(dex_cache->GetStrings()->GetLength()));
- EXPECT_EQ(java_lang_dex_file_->NumTypeIds(),
- static_cast<uint32_t>(dex_cache->GetResolvedTypes()->GetLength()));
- EXPECT_EQ(java_lang_dex_file_->NumMethodIds(),
- static_cast<uint32_t>(dex_cache->GetResolvedMethods()->GetLength()));
- EXPECT_EQ(java_lang_dex_file_->NumFieldIds(), dex_cache->NumResolvedFields());
}
} // namespace mirror
diff --git a/runtime/mirror/object-inl.h b/runtime/mirror/object-inl.h
index e35ddcc..90180c5 100644
--- a/runtime/mirror/object-inl.h
+++ b/runtime/mirror/object-inl.h
@@ -27,6 +27,7 @@
#include "class_flags.h"
#include "class_linker.h"
#include "class_loader-inl.h"
+#include "dex_cache-inl.h"
#include "lock_word-inl.h"
#include "monitor.h"
#include "object_array-inl.h"
@@ -1006,6 +1007,17 @@
return down_cast<mirror::ClassLoader*>(this);
}
+template<VerifyObjectFlags kVerifyFlags>
+inline bool Object::IsDexCache() {
+ return GetClass<kVerifyFlags>()->IsDexCacheClass();
+}
+
+template<VerifyObjectFlags kVerifyFlags>
+inline mirror::DexCache* Object::AsDexCache() {
+ DCHECK(IsDexCache<kVerifyFlags>());
+ return down_cast<mirror::DexCache*>(this);
+}
+
template <VerifyObjectFlags kVerifyFlags, typename Visitor, typename JavaLangRefVisitor>
inline void Object::VisitReferences(const Visitor& visitor,
const JavaLangRefVisitor& ref_visitor) {
@@ -1031,6 +1043,9 @@
} else if ((class_flags & kClassFlagReference) != 0) {
VisitInstanceFieldsReferences(klass, visitor);
ref_visitor(klass, AsReference());
+ } else if (class_flags == kClassFlagDexCache) {
+ mirror::DexCache* const dex_cache = AsDexCache<kVerifyFlags>();
+ dex_cache->VisitReferences<kVerifyFlags>(klass, visitor);
} else {
mirror::ClassLoader* const class_loader = AsClassLoader<kVerifyFlags>();
class_loader->VisitReferences<kVerifyFlags>(klass, visitor);
diff --git a/runtime/mirror/object.h b/runtime/mirror/object.h
index 3cec29c..50490bb 100644
--- a/runtime/mirror/object.h
+++ b/runtime/mirror/object.h
@@ -38,6 +38,7 @@
class Array;
class Class;
class ClassLoader;
+class DexCache;
class FinalizerReference;
template<class T> class ObjectArray;
template<class T> class PrimitiveArray;
@@ -162,6 +163,11 @@
template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
ClassLoader* AsClassLoader() SHARED_REQUIRES(Locks::mutator_lock_);
+ template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
+ bool IsDexCache() SHARED_REQUIRES(Locks::mutator_lock_);
+ template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
+ DexCache* AsDexCache() SHARED_REQUIRES(Locks::mutator_lock_);
+
template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags,
ReadBarrierOption kReadBarrierOption = kWithReadBarrier>
bool IsArrayInstance() SHARED_REQUIRES(Locks::mutator_lock_);