summaryrefslogtreecommitdiff
path: root/runtime/class_linker.cc
diff options
context:
space:
mode:
Diffstat (limited to 'runtime/class_linker.cc')
-rw-r--r--runtime/class_linker.cc157
1 files changed, 97 insertions, 60 deletions
diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc
index 7a8e4a3d92..ee13e0389a 100644
--- a/runtime/class_linker.cc
+++ b/runtime/class_linker.cc
@@ -43,7 +43,6 @@
#include "intern_table.h"
#include "interpreter/interpreter.h"
#include "leb128.h"
-#include "method_helper-inl.h"
#include "oat.h"
#include "oat_file.h"
#include "object_lock.h"
@@ -1671,6 +1670,7 @@ void ClassLinker::InitFromImage() {
LOG(FATAL) << "Failed to open dex file " << dex_file_location
<< " from within oat file " << oat_file.GetLocation()
<< " error '" << error_msg << "'";
+ UNREACHABLE();
}
CHECK_EQ(dex_file->GetLocationChecksum(), oat_dex_file->GetDexFileLocationChecksum());
@@ -2393,6 +2393,7 @@ uint32_t ClassLinker::SizeOfClassWithoutEmbeddedTables(const DexFile& dex_file,
break;
default:
LOG(FATAL) << "Unknown descriptor: " << c;
+ UNREACHABLE();
}
}
}
@@ -2442,7 +2443,7 @@ static uint32_t GetOatMethodIndexFromMethodIndex(const DexFile& dex_file, uint16
}
DCHECK(!it.HasNext());
LOG(FATAL) << "Failed to find method index " << method_idx << " in " << dex_file.GetLocation();
- return 0;
+ UNREACHABLE();
}
const OatFile::OatMethod ClassLinker::FindOatMethodFor(mirror::ArtMethod* method, bool* found) {
@@ -2780,7 +2781,7 @@ void ClassLinker::LoadClass(Thread* self, const DexFile& dex_file,
klass->SetDexClassDefIndex(dex_file.GetIndexForClassDef(dex_class_def));
klass->SetDexTypeIndex(dex_class_def.class_idx_);
- klass->SetDexCacheStrings(klass->GetDexCache()->GetStrings());
+ CHECK(klass->GetDexCacheStrings() != nullptr);
const uint8_t* class_data = dex_file.GetClassData(dex_class_def);
if (class_data == nullptr) {
@@ -3078,7 +3079,7 @@ mirror::DexCache* ClassLinker::FindDexCache(const DexFile& dex_file) {
LOG(ERROR) << "Registered dex file " << i << " = " << dex_cache->GetDexFile()->GetLocation();
}
LOG(FATAL) << "Failed to find DexCache for DexFile " << location;
- return nullptr;
+ UNREACHABLE();
}
void ClassLinker::FixupDexCaches(mirror::ArtMethod* resolution_method) {
@@ -3749,8 +3750,7 @@ bool ClassLinker::VerifyClassUsingOatFile(const DexFile& dex_file, mirror::Class
LOG(FATAL) << "Unexpected class status: " << oat_file_class_status
<< " " << dex_file.GetLocation() << " " << PrettyClass(klass) << " "
<< klass->GetDescriptor(&temp);
-
- return false;
+ UNREACHABLE();
}
void ClassLinker::ResolveClassExceptionHandlerTypes(const DexFile& dex_file,
@@ -4345,6 +4345,41 @@ bool ClassLinker::WaitForInitializeClass(Handle<mirror::Class> klass, Thread* se
UNREACHABLE();
}
+static bool HasSameSignatureWithDifferentClassLoaders(Thread* self,
+ Handle<mirror::ArtMethod> method1,
+ Handle<mirror::ArtMethod> method2)
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ {
+ StackHandleScope<1> hs(self);
+ Handle<mirror::Class> return_type(hs.NewHandle(method1->GetReturnType()));
+ if (UNLIKELY(method2->GetReturnType() != return_type.Get())) {
+ return false;
+ }
+ }
+ const DexFile::TypeList* types1 = method1->GetParameterTypeList();
+ const DexFile::TypeList* types2 = method2->GetParameterTypeList();
+ if (types1 == nullptr) {
+ return (types2 == nullptr) || (types2->Size() == 0);
+ } else if (UNLIKELY(types2 == nullptr)) {
+ return types1->Size() == 0;
+ }
+ uint32_t num_types = types1->Size();
+ if (UNLIKELY(num_types != types2->Size())) {
+ return false;
+ }
+ for (uint32_t i = 0; i < num_types; ++i) {
+ mirror::Class* param_type =
+ method1->GetClassFromTypeIndex(types1->GetTypeItem(i).type_idx_, true);
+ mirror::Class* other_param_type =
+ method2->GetClassFromTypeIndex(types2->GetTypeItem(i).type_idx_, true);
+ if (UNLIKELY(param_type != other_param_type)) {
+ return false;
+ }
+ }
+ return true;
+}
+
+
bool ClassLinker::ValidateSuperClassDescriptors(Handle<mirror::Class> klass) {
if (klass->IsInterface()) {
return true;
@@ -4352,19 +4387,19 @@ bool ClassLinker::ValidateSuperClassDescriptors(Handle<mirror::Class> klass) {
// Begin with the methods local to the superclass.
Thread* self = Thread::Current();
StackHandleScope<2> hs(self);
- MutableMethodHelper mh(hs.NewHandle<mirror::ArtMethod>(nullptr));
- MutableMethodHelper super_mh(hs.NewHandle<mirror::ArtMethod>(nullptr));
+ MutableHandle<mirror::ArtMethod> h_m(hs.NewHandle<mirror::ArtMethod>(nullptr));
+ MutableHandle<mirror::ArtMethod> super_h_m(hs.NewHandle<mirror::ArtMethod>(nullptr));
if (klass->HasSuperClass() &&
klass->GetClassLoader() != klass->GetSuperClass()->GetClassLoader()) {
for (int i = klass->GetSuperClass()->GetVTableLength() - 1; i >= 0; --i) {
- mh.ChangeMethod(klass->GetVTableEntry(i));
- super_mh.ChangeMethod(klass->GetSuperClass()->GetVTableEntry(i));
- if (mh.GetMethod() != super_mh.GetMethod() &&
- !mh.HasSameSignatureWithDifferentClassLoaders(self, &super_mh)) {
+ h_m.Assign(klass->GetVTableEntry(i));
+ super_h_m.Assign(klass->GetSuperClass()->GetVTableEntry(i));
+ if (h_m.Get() != super_h_m.Get() &&
+ !HasSameSignatureWithDifferentClassLoaders(self, h_m, super_h_m)) {
ThrowLinkageError(klass.Get(),
"Class %s method %s resolves differently in superclass %s",
PrettyDescriptor(klass.Get()).c_str(),
- PrettyMethod(mh.GetMethod()).c_str(),
+ PrettyMethod(h_m.Get()).c_str(),
PrettyDescriptor(klass->GetSuperClass()).c_str());
return false;
}
@@ -4374,14 +4409,14 @@ bool ClassLinker::ValidateSuperClassDescriptors(Handle<mirror::Class> klass) {
if (klass->GetClassLoader() != klass->GetIfTable()->GetInterface(i)->GetClassLoader()) {
uint32_t num_methods = klass->GetIfTable()->GetInterface(i)->NumVirtualMethods();
for (uint32_t j = 0; j < num_methods; ++j) {
- mh.ChangeMethod(klass->GetIfTable()->GetMethodArray(i)->GetWithoutChecks(j));
- super_mh.ChangeMethod(klass->GetIfTable()->GetInterface(i)->GetVirtualMethod(j));
- if (mh.GetMethod() != super_mh.GetMethod() &&
- !mh.HasSameSignatureWithDifferentClassLoaders(self, &super_mh)) {
+ h_m.Assign(klass->GetIfTable()->GetMethodArray(i)->GetWithoutChecks(j));
+ super_h_m.Assign(klass->GetIfTable()->GetInterface(i)->GetVirtualMethod(j));
+ if (h_m.Get() != super_h_m.Get() &&
+ !HasSameSignatureWithDifferentClassLoaders(self, h_m, super_h_m)) {
ThrowLinkageError(klass.Get(),
"Class %s method %s resolves differently in interface %s",
PrettyDescriptor(klass.Get()).c_str(),
- PrettyMethod(mh.GetMethod()).c_str(),
+ PrettyMethod(h_m.Get()).c_str(),
PrettyDescriptor(klass->GetIfTable()->GetInterface(i)).c_str());
return false;
}
@@ -5566,71 +5601,73 @@ mirror::ArtMethod* ClassLinker::ResolveMethod(const DexFile& dex_file, uint32_t
}
// If we found something, check that it can be accessed by the referrer.
+ bool exception_generated = false;
if (resolved != nullptr && referrer.Get() != nullptr) {
mirror::Class* methods_class = resolved->GetDeclaringClass();
mirror::Class* referring_class = referrer->GetDeclaringClass();
if (!referring_class->CanAccess(methods_class)) {
ThrowIllegalAccessErrorClassForMethodDispatch(referring_class, methods_class,
resolved, type);
- return nullptr;
+ exception_generated = true;
} else if (!referring_class->CanAccessMember(methods_class,
resolved->GetAccessFlags())) {
ThrowIllegalAccessErrorMethod(referring_class, resolved);
- return nullptr;
+ exception_generated = true;
}
}
-
- // Otherwise, throw an IncompatibleClassChangeError if we found something, and check interface
- // methods and throw if we find the method there. If we find nothing, throw a
- // NoSuchMethodError.
- switch (type) {
- case kDirect:
- case kStatic:
- if (resolved != nullptr) {
- ThrowIncompatibleClassChangeError(type, kVirtual, resolved, referrer.Get());
- } else {
- resolved = klass->FindInterfaceMethod(name, signature);
+ if (!exception_generated) {
+ // Otherwise, throw an IncompatibleClassChangeError if we found something, and check
+ // interface methods and throw if we find the method there. If we find nothing, throw a
+ // NoSuchMethodError.
+ switch (type) {
+ case kDirect:
+ case kStatic:
if (resolved != nullptr) {
- ThrowIncompatibleClassChangeError(type, kInterface, resolved, referrer.Get());
+ ThrowIncompatibleClassChangeError(type, kVirtual, resolved, referrer.Get());
} else {
- ThrowNoSuchMethodError(type, klass, name, signature);
+ resolved = klass->FindInterfaceMethod(name, signature);
+ if (resolved != nullptr) {
+ ThrowIncompatibleClassChangeError(type, kInterface, resolved, referrer.Get());
+ } else {
+ ThrowNoSuchMethodError(type, klass, name, signature);
+ }
}
- }
- break;
- case kInterface:
- if (resolved != nullptr) {
- ThrowIncompatibleClassChangeError(type, kDirect, resolved, referrer.Get());
- } else {
- resolved = klass->FindVirtualMethod(name, signature);
+ break;
+ case kInterface:
if (resolved != nullptr) {
- ThrowIncompatibleClassChangeError(type, kVirtual, resolved, referrer.Get());
+ ThrowIncompatibleClassChangeError(type, kDirect, resolved, referrer.Get());
} else {
- ThrowNoSuchMethodError(type, klass, name, signature);
+ resolved = klass->FindVirtualMethod(name, signature);
+ if (resolved != nullptr) {
+ ThrowIncompatibleClassChangeError(type, kVirtual, resolved, referrer.Get());
+ } else {
+ ThrowNoSuchMethodError(type, klass, name, signature);
+ }
}
- }
- break;
- case kSuper:
- if (resolved != nullptr) {
- ThrowIncompatibleClassChangeError(type, kDirect, resolved, referrer.Get());
- } else {
- ThrowNoSuchMethodError(type, klass, name, signature);
- }
- break;
- case kVirtual:
- if (resolved != nullptr) {
- ThrowIncompatibleClassChangeError(type, kDirect, resolved, referrer.Get());
- } else {
- resolved = klass->FindInterfaceMethod(name, signature);
+ break;
+ case kSuper:
if (resolved != nullptr) {
- ThrowIncompatibleClassChangeError(type, kInterface, resolved, referrer.Get());
+ ThrowIncompatibleClassChangeError(type, kDirect, resolved, referrer.Get());
} else {
ThrowNoSuchMethodError(type, klass, name, signature);
}
- }
- break;
+ break;
+ case kVirtual:
+ if (resolved != nullptr) {
+ ThrowIncompatibleClassChangeError(type, kDirect, resolved, referrer.Get());
+ } else {
+ resolved = klass->FindInterfaceMethod(name, signature);
+ if (resolved != nullptr) {
+ ThrowIncompatibleClassChangeError(type, kInterface, resolved, referrer.Get());
+ } else {
+ ThrowNoSuchMethodError(type, klass, name, signature);
+ }
+ }
+ break;
+ }
}
}
- DCHECK(Thread::Current()->IsExceptionPending());
+ Thread::Current()->AssertPendingException();
return nullptr;
}
}