summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndreas Gampe <agampe@google.com>2014-07-31 16:23:49 -0700
committerAndreas Gampe <agampe@google.com>2014-08-06 15:57:05 -0700
commit58a5af8568d224ca7eccf2483396ff9862f8d1ee (patch)
tree4dfac17316970040e079244523b9b1e2ea163f05
parent1b192268f167f603fc372f02f9067f3ce5d82daf (diff)
downloadart-58a5af8568d224ca7eccf2483396ff9862f8d1ee.zip
art-58a5af8568d224ca7eccf2483396ff9862f8d1ee.tar.gz
art-58a5af8568d224ca7eccf2483396ff9862f8d1ee.tar.bz2
ART: Add guards to the dex cache and its shortcuts
Do not return fields, methods or classes if the (declaring) class is erroneous. Bug: 16692788 Change-Id: If43c2414ad0eb22db5eba7cf66396c7f16c26597
-rw-r--r--compiler/driver/compiler_driver.cc8
-rw-r--r--runtime/class_linker-inl.h25
-rw-r--r--runtime/class_linker.cc25
-rw-r--r--runtime/class_linker_test.cc20
-rw-r--r--runtime/entrypoints/entrypoint_utils-inl.h4
-rw-r--r--runtime/entrypoints/entrypoint_utils.cc2
-rw-r--r--runtime/entrypoints/portable/portable_throw_entrypoints.cc2
-rw-r--r--runtime/entrypoints/quick/quick_trampoline_entrypoints.cc6
-rw-r--r--runtime/method_helper-inl.h2
-rw-r--r--runtime/mirror/art_method-inl.h53
-rw-r--r--runtime/mirror/art_method.h20
-rw-r--r--runtime/mirror/dex_cache.h12
-rw-r--r--runtime/verifier/reg_type_cache.cc2
13 files changed, 125 insertions, 56 deletions
diff --git a/compiler/driver/compiler_driver.cc b/compiler/driver/compiler_driver.cc
index ed126ad..6b0cc50 100644
--- a/compiler/driver/compiler_driver.cc
+++ b/compiler/driver/compiler_driver.cc
@@ -811,11 +811,15 @@ void CompilerDriver::UpdateImageClasses(TimingLogger* timings) {
bool CompilerDriver::CanAssumeTypeIsPresentInDexCache(const DexFile& dex_file, uint32_t type_idx) {
if (IsImage() &&
IsImageClass(dex_file.StringDataByIdx(dex_file.GetTypeId(type_idx).descriptor_idx_))) {
- if (kIsDebugBuild) {
+ {
ScopedObjectAccess soa(Thread::Current());
mirror::DexCache* dex_cache = Runtime::Current()->GetClassLinker()->FindDexCache(dex_file);
mirror::Class* resolved_class = dex_cache->GetResolvedType(type_idx);
- CHECK(resolved_class != NULL);
+ if (resolved_class == nullptr) {
+ // Erroneous class.
+ stats_->TypeNotInDexCache();
+ return false;
+ }
}
stats_->TypeInDexCache();
return true;
diff --git a/runtime/class_linker-inl.h b/runtime/class_linker-inl.h
index cf25810..9921bdd 100644
--- a/runtime/class_linker-inl.h
+++ b/runtime/class_linker-inl.h
@@ -77,7 +77,7 @@ inline mirror::String* ClassLinker::ResolveString(uint32_t string_idx,
inline mirror::Class* ClassLinker::ResolveType(uint16_t type_idx,
mirror::ArtMethod* referrer) {
- mirror::Class* resolved_type = referrer->GetDexCacheResolvedTypes()->Get(type_idx);
+ mirror::Class* resolved_type = referrer->GetDexCacheResolvedType(type_idx);
if (UNLIKELY(resolved_type == nullptr)) {
mirror::Class* declaring_class = referrer->GetDeclaringClass();
StackHandleScope<2> hs(Thread::Current());
@@ -85,9 +85,8 @@ inline mirror::Class* ClassLinker::ResolveType(uint16_t type_idx,
Handle<mirror::ClassLoader> class_loader(hs.NewHandle(declaring_class->GetClassLoader()));
const DexFile& dex_file = *dex_cache->GetDexFile();
resolved_type = ResolveType(dex_file, type_idx, dex_cache, class_loader);
- if (resolved_type != nullptr) {
- DCHECK_EQ(dex_cache->GetResolvedType(type_idx), resolved_type);
- }
+ // Note: We cannot check here to see whether we added the type to the cache. The type
+ // might be an erroneous class, which results in it being hidden from us.
}
return resolved_type;
}
@@ -102,9 +101,8 @@ inline mirror::Class* ClassLinker::ResolveType(uint16_t type_idx, mirror::ArtFie
Handle<mirror::ClassLoader> class_loader(hs.NewHandle(declaring_class->GetClassLoader()));
const DexFile& dex_file = *dex_cache->GetDexFile();
resolved_type = ResolveType(dex_file, type_idx, dex_cache, class_loader);
- if (resolved_type != nullptr) {
- DCHECK_EQ(dex_cache->GetResolvedType(type_idx), resolved_type);
- }
+ // Note: We cannot check here to see whether we added the type to the cache. The type
+ // might be an erroneous class, which results in it being hidden from us.
}
return resolved_type;
}
@@ -112,8 +110,7 @@ inline mirror::Class* ClassLinker::ResolveType(uint16_t type_idx, mirror::ArtFie
inline mirror::ArtMethod* ClassLinker::GetResolvedMethod(uint32_t method_idx,
mirror::ArtMethod* referrer,
InvokeType type) {
- mirror::ArtMethod* resolved_method =
- referrer->GetDexCacheResolvedMethods()->Get(method_idx);
+ mirror::ArtMethod* resolved_method = referrer->GetDexCacheResolvedMethod(method_idx);
if (resolved_method == nullptr || resolved_method->IsRuntimeMethod()) {
return nullptr;
}
@@ -135,9 +132,8 @@ inline mirror::ArtMethod* ClassLinker::ResolveMethod(Thread* self, uint32_t meth
const DexFile* dex_file = h_dex_cache->GetDexFile();
resolved_method = ResolveMethod(*dex_file, method_idx, h_dex_cache, h_class_loader, h_referrer,
type);
- if (resolved_method != nullptr) {
- DCHECK_EQ(h_dex_cache->GetResolvedMethod(method_idx), resolved_method);
- }
+ // Note: We cannot check here to see whether we added the method to the cache. It
+ // might be an erroneous class, which results in it being hidden from us.
return resolved_method;
}
@@ -156,9 +152,8 @@ inline mirror::ArtField* ClassLinker::ResolveField(uint32_t field_idx, mirror::A
Handle<mirror::ClassLoader> class_loader(hs.NewHandle(declaring_class->GetClassLoader()));
const DexFile& dex_file = *dex_cache->GetDexFile();
resolved_field = ResolveField(dex_file, field_idx, dex_cache, class_loader, is_static);
- if (resolved_field != nullptr) {
- DCHECK_EQ(dex_cache->GetResolvedField(field_idx), resolved_field);
- }
+ // Note: We cannot check here to see whether we added the field to the cache. The type
+ // might be an erroneous class, which results in it being hidden from us.
}
return resolved_field;
}
diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc
index f0b1b95..72572a0 100644
--- a/runtime/class_linker.cc
+++ b/runtime/class_linker.cc
@@ -3488,22 +3488,21 @@ mirror::ArtMethod* ClassLinker::FindMethodForProxy(mirror::Class* proxy_class,
DCHECK(proxy_class->IsProxyClass());
DCHECK(proxy_method->IsProxyMethod());
// Locate the dex cache of the original interface/Object
- mirror::DexCache* dex_cache = NULL;
+ mirror::DexCache* dex_cache = nullptr;
{
- mirror::ObjectArray<mirror::Class>* resolved_types = proxy_method->GetDexCacheResolvedTypes();
ReaderMutexLock mu(Thread::Current(), dex_lock_);
for (size_t i = 0; i != dex_caches_.size(); ++i) {
mirror::DexCache* a_dex_cache = GetDexCache(i);
- if (a_dex_cache->GetResolvedTypes() == resolved_types) {
+ if (proxy_method->HasSameDexCacheResolvedTypes(a_dex_cache->GetResolvedTypes())) {
dex_cache = a_dex_cache;
break;
}
}
}
- CHECK(dex_cache != NULL);
+ CHECK(dex_cache != nullptr);
uint32_t method_idx = proxy_method->GetDexMethodIndex();
mirror::ArtMethod* resolved_method = dex_cache->GetResolvedMethod(method_idx);
- CHECK(resolved_method != NULL);
+ CHECK(resolved_method != nullptr);
return resolved_method;
}
@@ -3583,8 +3582,8 @@ static void CheckProxyMethod(Handle<mirror::ArtMethod> method, Handle<mirror::Ar
// The proxy method doesn't have its own dex cache or dex file and so it steals those of its
// interface prototype. The exception to this are Constructors and the Class of the Proxy itself.
CHECK_EQ(prototype->GetDexCacheStrings(), method->GetDexCacheStrings());
- CHECK_EQ(prototype->GetDexCacheResolvedMethods(), method->GetDexCacheResolvedMethods());
- CHECK_EQ(prototype->GetDexCacheResolvedTypes(), method->GetDexCacheResolvedTypes());
+ CHECK(prototype->HasSameDexCacheResolvedMethods(method.Get()));
+ CHECK(prototype->HasSameDexCacheResolvedTypes(method.Get()));
CHECK_EQ(prototype->GetDexMethodIndex(), method->GetDexMethodIndex());
MethodHelper mh(method);
@@ -4952,7 +4951,7 @@ mirror::ArtField* ClassLinker::ResolveField(const DexFile& dex_file, uint32_t fi
bool is_static) {
DCHECK(dex_cache.Get() != nullptr);
mirror::ArtField* resolved = dex_cache->GetResolvedField(field_idx);
- if (resolved != NULL) {
+ if (resolved != nullptr) {
return resolved;
}
const DexFile::FieldId& field_id = dex_file.GetFieldId(field_idx);
@@ -4960,9 +4959,9 @@ mirror::ArtField* ClassLinker::ResolveField(const DexFile& dex_file, uint32_t fi
StackHandleScope<1> hs(self);
Handle<mirror::Class> klass(
hs.NewHandle(ResolveType(dex_file, field_id.class_idx_, dex_cache, class_loader)));
- if (klass.Get() == NULL) {
+ if (klass.Get() == nullptr) {
DCHECK(Thread::Current()->IsExceptionPending());
- return NULL;
+ return nullptr;
}
if (is_static) {
@@ -4971,7 +4970,7 @@ mirror::ArtField* ClassLinker::ResolveField(const DexFile& dex_file, uint32_t fi
resolved = klass->FindInstanceField(dex_cache.Get(), field_idx);
}
- if (resolved == NULL) {
+ if (resolved == nullptr) {
const char* name = dex_file.GetFieldName(field_id);
const char* type = dex_file.GetFieldTypeDescriptor(field_id);
if (is_static) {
@@ -4979,7 +4978,7 @@ mirror::ArtField* ClassLinker::ResolveField(const DexFile& dex_file, uint32_t fi
} else {
resolved = klass->FindInstanceField(name, type);
}
- if (resolved == NULL) {
+ if (resolved == nullptr) {
ThrowNoSuchFieldError(is_static ? "static " : "instance ", klass.Get(), type, name);
return NULL;
}
@@ -4994,7 +4993,7 @@ mirror::ArtField* ClassLinker::ResolveFieldJLS(const DexFile& dex_file,
Handle<mirror::ClassLoader> class_loader) {
DCHECK(dex_cache.Get() != nullptr);
mirror::ArtField* resolved = dex_cache->GetResolvedField(field_idx);
- if (resolved != NULL) {
+ if (resolved != nullptr) {
return resolved;
}
const DexFile::FieldId& field_id = dex_file.GetFieldId(field_idx);
diff --git a/runtime/class_linker_test.cc b/runtime/class_linker_test.cc
index 8e16d9b..8d93265 100644
--- a/runtime/class_linker_test.cc
+++ b/runtime/class_linker_test.cc
@@ -156,20 +156,20 @@ class ClassLinkerTest : public CommonRuntimeTest {
}
void AssertMethod(mirror::ArtMethod* method) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- EXPECT_TRUE(method != NULL);
- EXPECT_TRUE(method->GetClass() != NULL);
- EXPECT_TRUE(method->GetName() != NULL);
+ EXPECT_TRUE(method != nullptr);
+ EXPECT_TRUE(method->GetClass() != nullptr);
+ EXPECT_TRUE(method->GetName() != nullptr);
EXPECT_TRUE(method->GetSignature() != Signature::NoSignature());
- EXPECT_TRUE(method->GetDexCacheStrings() != NULL);
- EXPECT_TRUE(method->GetDexCacheResolvedMethods() != NULL);
- EXPECT_TRUE(method->GetDexCacheResolvedTypes() != NULL);
+ EXPECT_TRUE(method->GetDexCacheStrings() != nullptr);
+ EXPECT_TRUE(method->HasDexCacheResolvedMethods());
+ EXPECT_TRUE(method->HasDexCacheResolvedTypes());
EXPECT_EQ(method->GetDeclaringClass()->GetDexCache()->GetStrings(),
method->GetDexCacheStrings());
- EXPECT_EQ(method->GetDeclaringClass()->GetDexCache()->GetResolvedMethods(),
- method->GetDexCacheResolvedMethods());
- EXPECT_EQ(method->GetDeclaringClass()->GetDexCache()->GetResolvedTypes(),
- method->GetDexCacheResolvedTypes());
+ EXPECT_TRUE(method->HasSameDexCacheResolvedMethods(
+ method->GetDeclaringClass()->GetDexCache()->GetResolvedMethods()));
+ EXPECT_TRUE(method->HasSameDexCacheResolvedTypes(
+ method->GetDeclaringClass()->GetDexCache()->GetResolvedTypes()));
}
void AssertField(mirror::Class* klass, mirror::ArtField* field)
diff --git a/runtime/entrypoints/entrypoint_utils-inl.h b/runtime/entrypoints/entrypoint_utils-inl.h
index cb0be04..af71c19 100644
--- a/runtime/entrypoints/entrypoint_utils-inl.h
+++ b/runtime/entrypoints/entrypoint_utils-inl.h
@@ -40,7 +40,7 @@ template <const bool kAccessCheck>
static inline mirror::Class* CheckObjectAlloc(uint32_t type_idx,
mirror::ArtMethod* method,
Thread* self, bool* slow_path) {
- mirror::Class* klass = method->GetDexCacheResolvedTypes()->GetWithoutChecks(type_idx);
+ mirror::Class* klass = method->GetDexCacheResolvedType<false>(type_idx);
if (UNLIKELY(klass == NULL)) {
klass = Runtime::Current()->GetClassLinker()->ResolveType(type_idx, method);
*slow_path = true;
@@ -178,7 +178,7 @@ static inline mirror::Class* CheckArrayAlloc(uint32_t type_idx,
*slow_path = true;
return nullptr; // Failure
}
- mirror::Class* klass = method->GetDexCacheResolvedTypes()->GetWithoutChecks(type_idx);
+ mirror::Class* klass = method->GetDexCacheResolvedType<false>(type_idx);
if (UNLIKELY(klass == nullptr)) { // Not in dex cache so try to resolve
klass = Runtime::Current()->GetClassLinker()->ResolveType(type_idx, method);
*slow_path = true;
diff --git a/runtime/entrypoints/entrypoint_utils.cc b/runtime/entrypoints/entrypoint_utils.cc
index c1c7631..be3895a 100644
--- a/runtime/entrypoints/entrypoint_utils.cc
+++ b/runtime/entrypoints/entrypoint_utils.cc
@@ -41,7 +41,7 @@ static inline mirror::Class* CheckFilledNewArrayAlloc(uint32_t type_idx, mirror:
ThrowNegativeArraySizeException(component_count);
return nullptr; // Failure
}
- mirror::Class* klass = referrer->GetDexCacheResolvedTypes()->GetWithoutChecks(type_idx);
+ mirror::Class* klass = referrer->GetDexCacheResolvedType<false>(type_idx);
if (UNLIKELY(klass == NULL)) { // Not in dex cache so try to resolve
klass = Runtime::Current()->GetClassLinker()->ResolveType(type_idx, referrer);
if (klass == NULL) { // Error
diff --git a/runtime/entrypoints/portable/portable_throw_entrypoints.cc b/runtime/entrypoints/portable/portable_throw_entrypoints.cc
index be6231c..4317358 100644
--- a/runtime/entrypoints/portable/portable_throw_entrypoints.cc
+++ b/runtime/entrypoints/portable/portable_throw_entrypoints.cc
@@ -98,7 +98,7 @@ extern "C" int32_t art_portable_find_catch_block_from_code(mirror::ArtMethod* cu
}
// Does this catch exception type apply?
mirror::Class* iter_exception_type =
- current_method->GetDexCacheResolvedTypes()->Get(iter_type_idx);
+ current_method->GetDexCacheResolvedType(iter_type_idx);
if (UNLIKELY(iter_exception_type == NULL)) {
// TODO: check, the verifier (class linker?) should take care of resolving all exception
// classes early.
diff --git a/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc b/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc
index fa198d7..4730701 100644
--- a/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc
+++ b/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc
@@ -790,8 +790,8 @@ extern "C" const void* artQuickResolutionTrampoline(mirror::ArtMethod* called,
// We came here because of sharpening. Ensure the dex cache is up-to-date on the method index
// of the sharpened method.
- if (called->GetDexCacheResolvedMethods() == caller->GetDexCacheResolvedMethods()) {
- caller->GetDexCacheResolvedMethods()->Set<false>(called->GetDexMethodIndex(), called);
+ if (called->HasSameDexCacheResolvedMethods(caller)) {
+ caller->SetDexCacheResolvedMethod(called->GetDexMethodIndex(), called);
} else {
// Calling from one dex file to another, need to compute the method index appropriate to
// the caller's dex file. Since we get here only if the original called was a runtime
@@ -801,7 +801,7 @@ extern "C" const void* artQuickResolutionTrampoline(mirror::ArtMethod* called,
MethodHelper mh(hs.NewHandle(called));
uint32_t method_index = mh.FindDexMethodIndexInOtherDexFile(*dex_file, dex_method_idx);
if (method_index != DexFile::kDexNoIndex) {
- caller->GetDexCacheResolvedMethods()->Set<false>(method_index, called);
+ caller->SetDexCacheResolvedMethod(method_index, called);
}
}
}
diff --git a/runtime/method_helper-inl.h b/runtime/method_helper-inl.h
index 4f95a28..3a5056a 100644
--- a/runtime/method_helper-inl.h
+++ b/runtime/method_helper-inl.h
@@ -28,7 +28,7 @@ namespace art {
inline mirror::Class* MethodHelper::GetClassFromTypeIdx(uint16_t type_idx, bool resolve) {
mirror::ArtMethod* method = GetMethod();
- mirror::Class* type = method->GetDexCacheResolvedTypes()->Get(type_idx);
+ mirror::Class* type = method->GetDexCacheResolvedType(type_idx);
if (type == nullptr && resolve) {
type = Runtime::Current()->GetClassLinker()->ResolveType(type_idx, method);
CHECK(type != nullptr || Thread::Current()->IsExceptionPending());
diff --git a/runtime/mirror/art_method-inl.h b/runtime/mirror/art_method-inl.h
index 73de683..0dd1588 100644
--- a/runtime/mirror/art_method-inl.h
+++ b/runtime/mirror/art_method-inl.h
@@ -19,6 +19,8 @@
#include "art_method.h"
+#include "art_field.h"
+#include "class.h"
#include "class_linker.h"
#include "dex_cache.h"
#include "dex_file.h"
@@ -87,11 +89,60 @@ inline ObjectArray<ArtMethod>* ArtMethod::GetDexCacheResolvedMethods() {
OFFSET_OF_OBJECT_MEMBER(ArtMethod, dex_cache_resolved_methods_));
}
+inline ArtMethod* ArtMethod::GetDexCacheResolvedMethod(uint16_t method_index) {
+ ArtMethod* method = GetDexCacheResolvedMethods()->Get(method_index);
+ if (method != nullptr && !method->GetDeclaringClass()->IsErroneous()) {
+ return method;
+ } else {
+ return nullptr;
+ }
+}
+
+inline void ArtMethod::SetDexCacheResolvedMethod(uint16_t method_idx, ArtMethod* new_method) {
+ GetDexCacheResolvedMethods()->Set<false>(method_idx, new_method);
+}
+
+inline bool ArtMethod::HasDexCacheResolvedMethods() {
+ return GetDexCacheResolvedMethods() != nullptr;
+}
+
+inline bool ArtMethod::HasSameDexCacheResolvedMethods(ObjectArray<ArtMethod>* other_cache) {
+ return GetDexCacheResolvedMethods() == other_cache;
+}
+
+inline bool ArtMethod::HasSameDexCacheResolvedMethods(ArtMethod* other) {
+ return GetDexCacheResolvedMethods() == other->GetDexCacheResolvedMethods();
+}
+
+
inline ObjectArray<Class>* ArtMethod::GetDexCacheResolvedTypes() {
return GetFieldObject<ObjectArray<Class>>(
OFFSET_OF_OBJECT_MEMBER(ArtMethod, dex_cache_resolved_types_));
}
+template <bool kWithCheck>
+inline Class* ArtMethod::GetDexCacheResolvedType(uint32_t type_index) {
+ Class* klass;
+ if (kWithCheck) {
+ klass = GetDexCacheResolvedTypes()->Get(type_index);
+ } else {
+ klass = GetDexCacheResolvedTypes()->GetWithoutChecks(type_index);
+ }
+ return (klass != nullptr && !klass->IsErroneous()) ? klass : nullptr;
+}
+
+inline bool ArtMethod::HasDexCacheResolvedTypes() {
+ return GetDexCacheResolvedTypes() != nullptr;
+}
+
+inline bool ArtMethod::HasSameDexCacheResolvedTypes(ObjectArray<Class>* other_cache) {
+ return GetDexCacheResolvedTypes() == other_cache;
+}
+
+inline bool ArtMethod::HasSameDexCacheResolvedTypes(ArtMethod* other) {
+ return GetDexCacheResolvedTypes() == other->GetDexCacheResolvedTypes();
+}
+
inline uint32_t ArtMethod::GetCodeSize() {
DCHECK(!IsRuntimeMethod() && !IsProxyMethod()) << PrettyMethod(this);
const void* code = EntryPointToCodePointer(GetEntryPointFromQuickCompiledCode());
@@ -396,7 +447,7 @@ inline const DexFile::CodeItem* ArtMethod::GetCodeItem() {
inline bool ArtMethod::IsResolvedTypeIdx(uint16_t type_idx) {
mirror::ArtMethod* method = GetInterfaceMethodIfProxy();
- return method->GetDexCacheResolvedTypes()->Get(type_idx) != nullptr;
+ return method->GetDexCacheResolvedType(type_idx) != nullptr;
}
inline int32_t ArtMethod::GetLineNumFromDexPC(uint32_t dex_pc) {
diff --git a/runtime/mirror/art_method.h b/runtime/mirror/art_method.h
index 01e6149..4ebceff 100644
--- a/runtime/mirror/art_method.h
+++ b/runtime/mirror/art_method.h
@@ -216,13 +216,25 @@ class MANAGED ArtMethod FINAL : public Object {
return OFFSET_OF_OBJECT_MEMBER(ArtMethod, dex_cache_resolved_types_);
}
- ObjectArray<ArtMethod>* GetDexCacheResolvedMethods() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ ArtMethod* GetDexCacheResolvedMethod(uint16_t method_idx)
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ void SetDexCacheResolvedMethod(uint16_t method_idx, ArtMethod* new_method)
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
void SetDexCacheResolvedMethods(ObjectArray<ArtMethod>* new_dex_cache_methods)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ bool HasDexCacheResolvedMethods() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ bool HasSameDexCacheResolvedMethods(ArtMethod* other) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ bool HasSameDexCacheResolvedMethods(ObjectArray<ArtMethod>* other_cache)
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- ObjectArray<Class>* GetDexCacheResolvedTypes() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ template <bool kWithCheck = true>
+ Class* GetDexCacheResolvedType(uint32_t type_idx) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
void SetDexCacheResolvedTypes(ObjectArray<Class>* new_dex_cache_types)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ bool HasDexCacheResolvedTypes() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ bool HasSameDexCacheResolvedTypes(ArtMethod* other) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ bool HasSameDexCacheResolvedTypes(ObjectArray<Class>* other_cache)
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
// Find the method that this method overrides
ArtMethod* FindOverriddenMethod() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
@@ -518,6 +530,10 @@ class MANAGED ArtMethod FINAL : public Object {
static GcRoot<Class> java_lang_reflect_ArtMethod_;
private:
+ ObjectArray<ArtMethod>* GetDexCacheResolvedMethods() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
+ ObjectArray<Class>* GetDexCacheResolvedTypes() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
friend struct art::ArtMethodOffsets; // for verifying offset information
DISALLOW_IMPLICIT_CONSTRUCTORS(ArtMethod);
};
diff --git a/runtime/mirror/dex_cache.h b/runtime/mirror/dex_cache.h
index 2c5fbcd..3c947ab 100644
--- a/runtime/mirror/dex_cache.h
+++ b/runtime/mirror/dex_cache.h
@@ -17,7 +17,9 @@
#ifndef ART_RUNTIME_MIRROR_DEX_CACHE_H_
#define ART_RUNTIME_MIRROR_DEX_CACHE_H_
+#include "art_field.h"
#include "art_method.h"
+#include "class.h"
#include "object.h"
#include "object_array.h"
@@ -30,9 +32,6 @@ union JValue;
namespace mirror {
-class ArtField;
-class ArtMethod;
-class Class;
class String;
// C++ mirror of java.lang.DexCache.
@@ -115,7 +114,12 @@ class MANAGED DexCache FINAL : public Object {
ArtField* GetResolvedField(uint32_t field_idx) ALWAYS_INLINE
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- return GetResolvedFields()->Get(field_idx);
+ ArtField* field = GetResolvedFields()->Get(field_idx);
+ if (UNLIKELY(field == nullptr || field->GetDeclaringClass()->IsErroneous())) {
+ return nullptr;
+ } else {
+ return field;
+ }
}
void SetResolvedField(uint32_t field_idx, ArtField* resolved) ALWAYS_INLINE
diff --git a/runtime/verifier/reg_type_cache.cc b/runtime/verifier/reg_type_cache.cc
index 255b506..c0e4351 100644
--- a/runtime/verifier/reg_type_cache.cc
+++ b/runtime/verifier/reg_type_cache.cc
@@ -209,7 +209,7 @@ RegType& RegTypeCache::From(mirror::ClassLoader* loader, const char* descriptor,
}
RegType& RegTypeCache::FromClass(const char* descriptor, mirror::Class* klass, bool precise) {
- DCHECK(klass != nullptr && !klass->IsErroneous());
+ DCHECK(klass != nullptr);
if (klass->IsPrimitive()) {
// Note: precise isn't used for primitive classes. A char is assignable to an int. All
// primitive classes are final.