summaryrefslogtreecommitdiff
path: root/compiler/optimizing/sharpening.cc
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/optimizing/sharpening.cc')
-rw-r--r--compiler/optimizing/sharpening.cc67
1 files changed, 50 insertions, 17 deletions
diff --git a/compiler/optimizing/sharpening.cc b/compiler/optimizing/sharpening.cc
index 393369dcb6..f570c60843 100644
--- a/compiler/optimizing/sharpening.cc
+++ b/compiler/optimizing/sharpening.cc
@@ -158,24 +158,55 @@ HLoadClass::LoadKind HSharpening::ComputeLoadClassKind(
load_class->GetLoadKind() == HLoadClass::LoadKind::kReferrersClass)
<< load_class->GetLoadKind();
DCHECK(!load_class->IsInBootImage()) << "HLoadClass should not be optimized before sharpening.";
+ const DexFile& dex_file = load_class->GetDexFile();
+ dex::TypeIndex type_index = load_class->GetTypeIndex();
+ const CompilerOptions& compiler_options = codegen->GetCompilerOptions();
- HLoadClass::LoadKind load_kind = load_class->GetLoadKind();
+ bool is_in_boot_image = false;
+ HLoadClass::LoadKind desired_load_kind = HLoadClass::LoadKind::kInvalid;
- if (load_class->NeedsAccessCheck()) {
- // We need to call the runtime anyway, so we simply get the class as that call's return value.
- } else if (load_kind == HLoadClass::LoadKind::kReferrersClass) {
+ if (load_class->GetLoadKind() == HLoadClass::LoadKind::kReferrersClass) {
+ DCHECK(!load_class->NeedsAccessCheck());
// Loading from the ArtMethod* is the most efficient retrieval in code size.
// TODO: This may not actually be true for all architectures and
// locations of target classes. The additional register pressure
// for using the ArtMethod* should be considered.
+ desired_load_kind = HLoadClass::LoadKind::kReferrersClass;
+ } else if (load_class->NeedsAccessCheck()) {
+ DCHECK_EQ(load_class->GetLoadKind(), HLoadClass::LoadKind::kRuntimeCall);
+ if (klass != nullptr) {
+ // Resolved class that needs access check must be really inaccessible
+ // and the access check is bound to fail. Just emit the runtime call.
+ desired_load_kind = HLoadClass::LoadKind::kRuntimeCall;
+ } else if (compiler_options.IsJitCompiler()) {
+ // Unresolved class while JITting means that either we never hit this
+ // instruction or it failed. Either way, just emit the runtime call.
+ // (Though we could consider emitting Deoptimize instead and
+ // recompile if the instruction succeeds in interpreter.)
+ desired_load_kind = HLoadClass::LoadKind::kRuntimeCall;
+ } else {
+ // For AOT, check if the class is in the same literal package as the
+ // compiling class and pick an appropriate .bss entry.
+ auto package_length = [](const char* descriptor) {
+ const char* slash_pos = strrchr(descriptor, '/');
+ return (slash_pos != nullptr) ? static_cast<size_t>(slash_pos - descriptor) : 0u;
+ };
+ const char* klass_descriptor = dex_file.StringByTypeIdx(type_index);
+ const uint32_t klass_package_length = package_length(klass_descriptor);
+ const DexFile* referrer_dex_file = dex_compilation_unit.GetDexFile();
+ const dex::TypeIndex referrer_type_index =
+ referrer_dex_file->GetClassDef(dex_compilation_unit.GetClassDefIndex()).class_idx_;
+ const char* referrer_descriptor = referrer_dex_file->StringByTypeIdx(referrer_type_index);
+ const uint32_t referrer_package_length = package_length(referrer_descriptor);
+ bool same_package =
+ (referrer_package_length == klass_package_length) &&
+ memcmp(referrer_descriptor, klass_descriptor, referrer_package_length) == 0;
+ desired_load_kind = same_package
+ ? HLoadClass::LoadKind::kBssEntryPackage
+ : HLoadClass::LoadKind::kBssEntryPublic;
+ }
} else {
- const DexFile& dex_file = load_class->GetDexFile();
- dex::TypeIndex type_index = load_class->GetTypeIndex();
-
- bool is_in_boot_image = false;
- HLoadClass::LoadKind desired_load_kind = HLoadClass::LoadKind::kInvalid;
Runtime* runtime = Runtime::Current();
- const CompilerOptions& compiler_options = codegen->GetCompilerOptions();
if (compiler_options.IsBootImage() || compiler_options.IsBootImageExtension()) {
// Compiling boot image or boot image extension. Check if the class is a boot image class.
DCHECK(!compiler_options.IsJitCompiler());
@@ -227,17 +258,19 @@ HLoadClass::LoadKind HSharpening::ComputeLoadClassKind(
desired_load_kind = HLoadClass::LoadKind::kBssEntry;
}
}
- DCHECK_NE(desired_load_kind, HLoadClass::LoadKind::kInvalid);
+ }
+ DCHECK_NE(desired_load_kind, HLoadClass::LoadKind::kInvalid);
- if (is_in_boot_image) {
- load_class->MarkInBootImage();
- }
- load_kind = codegen->GetSupportedLoadClassKind(desired_load_kind);
+ if (is_in_boot_image) {
+ load_class->MarkInBootImage();
}
+ HLoadClass::LoadKind load_kind = codegen->GetSupportedLoadClassKind(desired_load_kind);
if (!IsSameDexFile(load_class->GetDexFile(), *dex_compilation_unit.GetDexFile())) {
- if ((load_kind == HLoadClass::LoadKind::kRuntimeCall) ||
- (load_kind == HLoadClass::LoadKind::kBssEntry)) {
+ if (load_kind == HLoadClass::LoadKind::kRuntimeCall ||
+ load_kind == HLoadClass::LoadKind::kBssEntry ||
+ load_kind == HLoadClass::LoadKind::kBssEntryPublic ||
+ load_kind == HLoadClass::LoadKind::kBssEntryPackage) {
// We actually cannot reference this class, we're forced to bail.
// We cannot reference this class with Bss, as the entrypoint will lookup the class
// in the caller's dex file, but that dex file does not reference the class.