summaryrefslogtreecommitdiff
path: root/runtime/class_linker.cc
diff options
context:
space:
mode:
author Treehugger Robot <treehugger-gerrit@google.com> 2016-10-20 18:50:24 +0000
committer Gerrit Code Review <noreply-gerritcodereview@google.com> 2016-10-20 18:50:25 +0000
commitfc5fbfc13fd6873d42fe82c308ee68a685258b4c (patch)
treed68edb92308bc83f8097a2fd8ef651500f183fa9 /runtime/class_linker.cc
parenteb6b620b8e3366fbe5e26ad6fe7651f0585e9686 (diff)
parentc7a420c95376953ecb3bd84b0ac2e245e90d827c (diff)
Merge "Ensure that overrides work in presence of package-private methods."
Diffstat (limited to 'runtime/class_linker.cc')
-rw-r--r--runtime/class_linker.cc43
1 files changed, 25 insertions, 18 deletions
diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc
index a7d8b13014..cea8377c58 100644
--- a/runtime/class_linker.cc
+++ b/runtime/class_linker.cc
@@ -5643,27 +5643,29 @@ X86_OPTNONE bool ClassLinker::LinkVirtualMethods(
for (size_t j = 0; j < super_vtable_length; ++j) {
// Search the hash table to see if we are overridden by any method.
ArtMethod* super_method = vtable->GetElementPtrSize<ArtMethod*>(j, image_pointer_size_);
+ if (!klass->CanAccessMember(super_method->GetDeclaringClass(),
+ super_method->GetAccessFlags())) {
+ // Continue on to the next method since this one is package private and canot be overridden.
+ // Before Android 4.1, the package-private method super_method might have been incorrectly
+ // overridden.
+ continue;
+ }
MethodNameAndSignatureComparator super_method_name_comparator(
super_method->GetInterfaceMethodIfProxy(image_pointer_size_));
+ // We remove the method so that subsequent lookups will be faster by making the hash-map
+ // smaller as we go on.
uint32_t hash_index = hash_table.FindAndRemove(&super_method_name_comparator);
if (hash_index != hash_table.GetNotFoundIndex()) {
ArtMethod* virtual_method = klass->GetVirtualMethodDuringLinking(
hash_index, image_pointer_size_);
- if (klass->CanAccessMember(super_method->GetDeclaringClass(),
- super_method->GetAccessFlags())) {
- if (super_method->IsFinal()) {
- ThrowLinkageError(klass.Get(), "Method %s overrides final method in class %s",
- ArtMethod::PrettyMethod(virtual_method).c_str(),
- super_method->GetDeclaringClassDescriptor());
- return false;
- }
- vtable->SetElementPtrSize(j, virtual_method, image_pointer_size_);
- virtual_method->SetMethodIndex(j);
- } else {
- LOG(WARNING) << "Before Android 4.1, method " << ArtMethod::PrettyMethod(virtual_method)
- << " would have incorrectly overridden the package-private method in "
- << PrettyDescriptor(super_method->GetDeclaringClassDescriptor());
+ if (super_method->IsFinal()) {
+ ThrowLinkageError(klass.Get(), "Method %s overrides final method in class %s",
+ virtual_method->PrettyMethod().c_str(),
+ super_method->GetDeclaringClassDescriptor());
+ return false;
}
+ vtable->SetElementPtrSize(j, virtual_method, image_pointer_size_);
+ virtual_method->SetMethodIndex(j);
} else if (super_method->IsOverridableByDefaultMethod()) {
// We didn't directly override this method but we might through default methods...
// Check for default method update.
@@ -6458,15 +6460,20 @@ static void CheckVTableHasNoDuplicates(Thread* self,
}
MethodNameAndSignatureComparator name_comparator(
vtable_entry->GetInterfaceMethodIfProxy(pointer_size));
- for (int32_t j = i+1; j < num_entries; j++) {
+ for (int32_t j = i + 1; j < num_entries; j++) {
ArtMethod* other_entry = vtable->GetElementPtrSize<ArtMethod*>(j, pointer_size);
+ if (!klass->CanAccessMember(other_entry->GetDeclaringClass(),
+ other_entry->GetAccessFlags())) {
+ continue;
+ }
CHECK(vtable_entry != other_entry &&
!name_comparator.HasSameNameAndSignature(
other_entry->GetInterfaceMethodIfProxy(pointer_size)))
<< "vtable entries " << i << " and " << j << " are identical for "
- << klass->PrettyClass() << " in method "
- << vtable_entry->PrettyMethod()
- << " and " << other_entry->PrettyMethod();
+ << klass->PrettyClass() << " in method " << vtable_entry->PrettyMethod() << " (0x"
+ << std::hex << reinterpret_cast<uintptr_t>(vtable_entry) << ") and "
+ << other_entry->PrettyMethod() << " (0x" << std::hex
+ << reinterpret_cast<uintptr_t>(other_entry) << ")";
}
}
}