summaryrefslogtreecommitdiff
path: root/compiler/optimizing/instruction_builder.cc
diff options
context:
space:
mode:
authorVladimir Marko <vmarko@google.com>2020-08-26 16:44:01 +0100
committerVladimir Marko <vmarko@google.com>2020-08-27 14:12:17 +0000
commit4100e5e2ebb9376696ae3b9f26dccde5ebcf5c7e (patch)
tree71110e5e4a6eb13baf409271d6f012ac97825123 /compiler/optimizing/instruction_builder.cc
parent4313ccb65b6d77821b1fb976d76a90f1000adaea (diff)
Optimizing: Improve generated code for field access...
... to resolved fields that are package-private or protected and/or defined in a package-private class but still known to be accessible from the unresolved compiling class. Test: Update test 727-checker-unresolved-class Test: m test-art-host-gtest Test: testrunner.py --host --optimizing Bug: 161898207 Change-Id: I3c90253014da209fd6a665cc230ac375b5ef1a9b
Diffstat (limited to 'compiler/optimizing/instruction_builder.cc')
-rw-r--r--compiler/optimizing/instruction_builder.cc26
1 files changed, 23 insertions, 3 deletions
diff --git a/compiler/optimizing/instruction_builder.cc b/compiler/optimizing/instruction_builder.cc
index 1993fa2512..1aef100a89 100644
--- a/compiler/optimizing/instruction_builder.cc
+++ b/compiler/optimizing/instruction_builder.cc
@@ -2023,9 +2023,29 @@ ArtField* HInstructionBuilder::ResolveField(uint16_t field_idx, bool is_static,
// Check access.
Handle<mirror::Class> compiling_class = dex_compilation_unit_->GetCompilingClass();
if (compiling_class == nullptr) {
- // For unresolved compiling class, handle only the simple case of a public field
- // in a public class and use a slow runtime call for all other cases.
- if (!resolved_field->IsPublic() || !resolved_field->GetDeclaringClass()->IsPublic()) {
+ // Check if the declaring class or referencing class is accessible.
+ SamePackageCompare same_package(*dex_compilation_unit_);
+ ObjPtr<mirror::Class> declaring_class = resolved_field->GetDeclaringClass();
+ bool declaring_class_accessible = declaring_class->IsPublic() || same_package(declaring_class);
+ if (!declaring_class_accessible) {
+ // It is possible to access members from an inaccessible superclass
+ // by referencing them through an accessible subclass.
+ ObjPtr<mirror::Class> referenced_class = class_linker->LookupResolvedType(
+ dex_compilation_unit_->GetDexFile()->GetFieldId(field_idx).class_idx_,
+ dex_compilation_unit_->GetDexCache().Get(),
+ class_loader.Get());
+ DCHECK(referenced_class != nullptr); // Must have been resolved when resolving the field.
+ if (!referenced_class->IsPublic() && !same_package(referenced_class)) {
+ return nullptr;
+ }
+ }
+ // Check whether the field itself is accessible.
+ // Since the referrer is unresolved but the field is resolved, it cannot be
+ // inside the same class, so a private field is known to be inaccessible.
+ // And without a resolved referrer, we cannot check for protected member access
+ // in superlass, so we handle only access to public member or within the package.
+ if (resolved_field->IsPrivate() ||
+ (!resolved_field->IsPublic() && !declaring_class_accessible)) {
return nullptr;
}
} else if (!compiling_class->CanAccessResolvedField(resolved_field->GetDeclaringClass(),