summaryrefslogtreecommitdiff
path: root/compiler
diff options
context:
space:
mode:
author Vladimir Marko <vmarko@google.com> 2020-09-28 12:10:28 +0100
committer Vladimir Marko <vmarko@google.com> 2020-09-30 13:58:32 +0000
commit8f63f1084b013a129f66cf8a7ed8ab1cae9f02aa (patch)
tree6e9bbf5ad71a55f701f740e2995e0b84e9b87307 /compiler
parent7aa2bfc09541ea5d2516738de84c24cd0269fed0 (diff)
Faster access to unresolved classes from compiled code.
Add two new load kinds to LoadClass, similar to kBssEntry but using the access-checking entrypoint on the slow-path. One is used for classes that are in the literal package and the other for classes outside the literal package of the compiling class. Associate new .bss entries with these load kinds and update them from entrypoints based on the resolved class properties. If the resolved class is public, both types of entries can be updated, otherwise only the package local entry can be updated and only if the defining class loader of the class is the same as the caller's defining class loader (which is identical for all code in an oat file) because the run time access check for same package requires both class loader and literal package name match. Test: Additional tests in 727-checker-unresolved-class. Test: m test-art-host-gtest Test: testrunner.py --host --optimizing Test: aosp_blueline-userdebug boots. Test: run-gtests.sh Test: testrunner.py --target --optimizing Bug: 161898207 Change-Id: I281e06ac2825caf81c6d7ee3128af833abd39992
Diffstat (limited to 'compiler')
-rw-r--r--compiler/linker/linker_patch.h32
-rw-r--r--compiler/optimizing/code_generator_arm64.cc60
-rw-r--r--compiler/optimizing/code_generator_arm64.h7
-rw-r--r--compiler/optimizing/code_generator_arm_vixl.cc53
-rw-r--r--compiler/optimizing/code_generator_arm_vixl.h6
-rw-r--r--compiler/optimizing/code_generator_x86.cc57
-rw-r--r--compiler/optimizing/code_generator_x86.h4
-rw-r--r--compiler/optimizing/code_generator_x86_64.cc51
-rw-r--r--compiler/optimizing/code_generator_x86_64.h4
-rw-r--r--compiler/optimizing/nodes.h41
-rw-r--r--compiler/optimizing/prepare_for_register_allocation.cc1
-rw-r--r--compiler/optimizing/sharpening.cc67
12 files changed, 310 insertions, 73 deletions
diff --git a/compiler/linker/linker_patch.h b/compiler/linker/linker_patch.h
index 7fedf2e86e..4000fc2523 100644
--- a/compiler/linker/linker_patch.h
+++ b/compiler/linker/linker_patch.h
@@ -50,6 +50,8 @@ class LinkerPatch {
kCallRelative,
kTypeRelative,
kTypeBssEntry,
+ kPublicTypeBssEntry,
+ kPackageTypeBssEntry,
kStringRelative,
kStringBssEntry,
kCallEntrypoint,
@@ -122,6 +124,26 @@ class LinkerPatch {
return patch;
}
+ static LinkerPatch PublicTypeBssEntryPatch(size_t literal_offset,
+ const DexFile* target_dex_file,
+ uint32_t pc_insn_offset,
+ uint32_t target_type_idx) {
+ LinkerPatch patch(literal_offset, Type::kPublicTypeBssEntry, target_dex_file);
+ patch.type_idx_ = target_type_idx;
+ patch.pc_insn_offset_ = pc_insn_offset;
+ return patch;
+ }
+
+ static LinkerPatch PackageTypeBssEntryPatch(size_t literal_offset,
+ const DexFile* target_dex_file,
+ uint32_t pc_insn_offset,
+ uint32_t target_type_idx) {
+ LinkerPatch patch(literal_offset, Type::kPackageTypeBssEntry, target_dex_file);
+ patch.type_idx_ = target_type_idx;
+ patch.pc_insn_offset_ = pc_insn_offset;
+ return patch;
+ }
+
static LinkerPatch RelativeStringPatch(size_t literal_offset,
const DexFile* target_dex_file,
uint32_t pc_insn_offset,
@@ -192,13 +214,17 @@ class LinkerPatch {
const DexFile* TargetTypeDexFile() const {
DCHECK(patch_type_ == Type::kTypeRelative ||
- patch_type_ == Type::kTypeBssEntry);
+ patch_type_ == Type::kTypeBssEntry ||
+ patch_type_ == Type::kPublicTypeBssEntry ||
+ patch_type_ == Type::kPackageTypeBssEntry);
return target_dex_file_;
}
dex::TypeIndex TargetTypeIndex() const {
DCHECK(patch_type_ == Type::kTypeRelative ||
- patch_type_ == Type::kTypeBssEntry);
+ patch_type_ == Type::kTypeBssEntry ||
+ patch_type_ == Type::kPublicTypeBssEntry ||
+ patch_type_ == Type::kPackageTypeBssEntry);
return dex::TypeIndex(type_idx_);
}
@@ -221,6 +247,8 @@ class LinkerPatch {
patch_type_ == Type::kMethodBssEntry ||
patch_type_ == Type::kTypeRelative ||
patch_type_ == Type::kTypeBssEntry ||
+ patch_type_ == Type::kPublicTypeBssEntry ||
+ patch_type_ == Type::kPackageTypeBssEntry ||
patch_type_ == Type::kStringRelative ||
patch_type_ == Type::kStringBssEntry);
return pc_insn_offset_;
diff --git a/compiler/optimizing/code_generator_arm64.cc b/compiler/optimizing/code_generator_arm64.cc
index 3ff83b4b81..a5d206064f 100644
--- a/compiler/optimizing/code_generator_arm64.cc
+++ b/compiler/optimizing/code_generator_arm64.cc
@@ -327,8 +327,13 @@ class LoadClassSlowPathARM64 : public SlowPathCodeARM64 {
DCHECK(IsSameDexFile(cls_->GetDexFile(), arm64_codegen->GetGraph()->GetDexFile()));
dex::TypeIndex type_index = cls_->GetTypeIndex();
__ Mov(calling_convention.GetRegisterAt(0).W(), type_index.index_);
- arm64_codegen->InvokeRuntime(kQuickResolveType, instruction_, dex_pc, this);
- CheckEntrypointTypes<kQuickResolveType, void*, uint32_t>();
+ if (cls_->NeedsAccessCheck()) {
+ CheckEntrypointTypes<kQuickResolveTypeAndVerifyAccess, void*, uint32_t>();
+ arm64_codegen->InvokeRuntime(kQuickResolveTypeAndVerifyAccess, instruction_, dex_pc, this);
+ } else {
+ CheckEntrypointTypes<kQuickResolveType, void*, uint32_t>();
+ arm64_codegen->InvokeRuntime(kQuickResolveType, instruction_, dex_pc, this);
+ }
// If we also must_do_clinit, the resolved type is now in the correct register.
} else {
DCHECK(must_do_clinit);
@@ -942,6 +947,8 @@ CodeGeneratorARM64::CodeGeneratorARM64(HGraph* graph,
method_bss_entry_patches_(graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)),
boot_image_type_patches_(graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)),
type_bss_entry_patches_(graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)),
+ public_type_bss_entry_patches_(graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)),
+ package_type_bss_entry_patches_(graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)),
boot_image_string_patches_(graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)),
string_bss_entry_patches_(graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)),
boot_image_other_patches_(graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)),
@@ -4733,10 +4740,26 @@ vixl::aarch64::Label* CodeGeneratorARM64::NewBootImageTypePatch(
}
vixl::aarch64::Label* CodeGeneratorARM64::NewBssEntryTypePatch(
- const DexFile& dex_file,
- dex::TypeIndex type_index,
+ HLoadClass* load_class,
vixl::aarch64::Label* adrp_label) {
- return NewPcRelativePatch(&dex_file, type_index.index_, adrp_label, &type_bss_entry_patches_);
+ const DexFile& dex_file = load_class->GetDexFile();
+ dex::TypeIndex type_index = load_class->GetTypeIndex();
+ ArenaDeque<PcRelativePatchInfo>* patches = nullptr;
+ switch (load_class->GetLoadKind()) {
+ case HLoadClass::LoadKind::kBssEntry:
+ patches = &type_bss_entry_patches_;
+ break;
+ case HLoadClass::LoadKind::kBssEntryPublic:
+ patches = &public_type_bss_entry_patches_;
+ break;
+ case HLoadClass::LoadKind::kBssEntryPackage:
+ patches = &package_type_bss_entry_patches_;
+ break;
+ default:
+ LOG(FATAL) << "Unexpected load kind: " << load_class->GetLoadKind();
+ UNREACHABLE();
+ }
+ return NewPcRelativePatch(&dex_file, type_index.index_, adrp_label, patches);
}
vixl::aarch64::Label* CodeGeneratorARM64::NewBootImageStringPatch(
@@ -4916,6 +4939,8 @@ void CodeGeneratorARM64::EmitLinkerPatches(ArenaVector<linker::LinkerPatch>* lin
method_bss_entry_patches_.size() +
boot_image_type_patches_.size() +
type_bss_entry_patches_.size() +
+ public_type_bss_entry_patches_.size() +
+ package_type_bss_entry_patches_.size() +
boot_image_string_patches_.size() +
string_bss_entry_patches_.size() +
boot_image_other_patches_.size() +
@@ -4945,6 +4970,10 @@ void CodeGeneratorARM64::EmitLinkerPatches(ArenaVector<linker::LinkerPatch>* lin
method_bss_entry_patches_, linker_patches);
EmitPcRelativeLinkerPatches<linker::LinkerPatch::TypeBssEntryPatch>(
type_bss_entry_patches_, linker_patches);
+ EmitPcRelativeLinkerPatches<linker::LinkerPatch::PublicTypeBssEntryPatch>(
+ public_type_bss_entry_patches_, linker_patches);
+ EmitPcRelativeLinkerPatches<linker::LinkerPatch::PackageTypeBssEntryPatch>(
+ package_type_bss_entry_patches_, linker_patches);
EmitPcRelativeLinkerPatches<linker::LinkerPatch::StringBssEntryPatch>(
string_bss_entry_patches_, linker_patches);
for (const PatchInfo<vixl::aarch64::Label>& info : call_entrypoint_patches_) {
@@ -5063,6 +5092,8 @@ HLoadClass::LoadKind CodeGeneratorARM64::GetSupportedLoadClassKind(
case HLoadClass::LoadKind::kBootImageLinkTimePcRelative:
case HLoadClass::LoadKind::kBootImageRelRo:
case HLoadClass::LoadKind::kBssEntry:
+ case HLoadClass::LoadKind::kBssEntryPublic:
+ case HLoadClass::LoadKind::kBssEntryPackage:
DCHECK(!GetCompilerOptions().IsJitCompiler());
break;
case HLoadClass::LoadKind::kJitBootImageAddress:
@@ -5086,7 +5117,9 @@ void LocationsBuilderARM64::VisitLoadClass(HLoadClass* cls) {
DCHECK(calling_convention.GetRegisterAt(0).Is(vixl::aarch64::x0));
return;
}
- DCHECK(!cls->NeedsAccessCheck());
+ DCHECK_EQ(cls->NeedsAccessCheck(),
+ load_kind == HLoadClass::LoadKind::kBssEntryPublic ||
+ load_kind == HLoadClass::LoadKind::kBssEntryPackage);
const bool requires_read_barrier = kEmitCompilerReadBarrier && !cls->IsInBootImage();
LocationSummary::CallKind call_kind = (cls->NeedsEnvironment() || requires_read_barrier)
@@ -5120,7 +5153,9 @@ void InstructionCodeGeneratorARM64::VisitLoadClass(HLoadClass* cls) NO_THREAD_SA
codegen_->MaybeGenerateMarkingRegisterCheck(/* code= */ __LINE__);
return;
}
- DCHECK(!cls->NeedsAccessCheck());
+ DCHECK_EQ(cls->NeedsAccessCheck(),
+ load_kind == HLoadClass::LoadKind::kBssEntryPublic ||
+ load_kind == HLoadClass::LoadKind::kBssEntryPackage);
Location out_loc = cls->GetLocations()->Out();
Register out = OutputRegister(cls);
@@ -5170,16 +5205,15 @@ void InstructionCodeGeneratorARM64::VisitLoadClass(HLoadClass* cls) NO_THREAD_SA
codegen_->EmitLdrOffsetPlaceholder(ldr_label, out.W(), out.X());
break;
}
- case HLoadClass::LoadKind::kBssEntry: {
+ case HLoadClass::LoadKind::kBssEntry:
+ case HLoadClass::LoadKind::kBssEntryPublic:
+ case HLoadClass::LoadKind::kBssEntryPackage: {
// Add ADRP with its PC-relative Class .bss entry patch.
- const DexFile& dex_file = cls->GetDexFile();
- dex::TypeIndex type_index = cls->GetTypeIndex();
vixl::aarch64::Register temp = XRegisterFrom(out_loc);
- vixl::aarch64::Label* adrp_label = codegen_->NewBssEntryTypePatch(dex_file, type_index);
+ vixl::aarch64::Label* adrp_label = codegen_->NewBssEntryTypePatch(cls);
codegen_->EmitAdrpPlaceholder(adrp_label, temp);
// Add LDR with its PC-relative Class .bss entry patch.
- vixl::aarch64::Label* ldr_label =
- codegen_->NewBssEntryTypePatch(dex_file, type_index, adrp_label);
+ vixl::aarch64::Label* ldr_label = codegen_->NewBssEntryTypePatch(cls, adrp_label);
// /* GcRoot<mirror::Class> */ out = *(base_address + offset) /* PC-relative */
// All aligned loads are implicitly atomic consume operations on ARM64.
codegen_->GenerateGcRootFieldLoad(cls,
diff --git a/compiler/optimizing/code_generator_arm64.h b/compiler/optimizing/code_generator_arm64.h
index 04b2c549f4..447c0b501f 100644
--- a/compiler/optimizing/code_generator_arm64.h
+++ b/compiler/optimizing/code_generator_arm64.h
@@ -736,8 +736,7 @@ class CodeGeneratorARM64 : public CodeGenerator {
// to be bound before the instruction. The instruction will be either the
// ADRP (pass `adrp_label = null`) or the ADD (pass `adrp_label` pointing
// to the associated ADRP patch label).
- vixl::aarch64::Label* NewBssEntryTypePatch(const DexFile& dex_file,
- dex::TypeIndex type_index,
+ vixl::aarch64::Label* NewBssEntryTypePatch(HLoadClass* load_class,
vixl::aarch64::Label* adrp_label = nullptr);
// Add a new boot image string patch for an instruction and return the label
@@ -1048,6 +1047,10 @@ class CodeGeneratorARM64 : public CodeGenerator {
ArenaDeque<PcRelativePatchInfo> boot_image_type_patches_;
// PC-relative type patch info for kBssEntry.
ArenaDeque<PcRelativePatchInfo> type_bss_entry_patches_;
+ // PC-relative public type patch info for kBssEntryPublic.
+ ArenaDeque<PcRelativePatchInfo> public_type_bss_entry_patches_;
+ // PC-relative package type patch info for kBssEntryPackage.
+ ArenaDeque<PcRelativePatchInfo> package_type_bss_entry_patches_;
// PC-relative String patch info for kBootImageLinkTimePcRelative.
ArenaDeque<PcRelativePatchInfo> boot_image_string_patches_;
// PC-relative String patch info for kBssEntry.
diff --git a/compiler/optimizing/code_generator_arm_vixl.cc b/compiler/optimizing/code_generator_arm_vixl.cc
index 9b1f5abeee..9aefdabdb4 100644
--- a/compiler/optimizing/code_generator_arm_vixl.cc
+++ b/compiler/optimizing/code_generator_arm_vixl.cc
@@ -530,8 +530,13 @@ class LoadClassSlowPathARMVIXL : public SlowPathCodeARMVIXL {
DCHECK(IsSameDexFile(cls_->GetDexFile(), arm_codegen->GetGraph()->GetDexFile()));
dex::TypeIndex type_index = cls_->GetTypeIndex();
__ Mov(calling_convention.GetRegisterAt(0), type_index.index_);
- arm_codegen->InvokeRuntime(kQuickResolveType, instruction_, dex_pc, this);
- CheckEntrypointTypes<kQuickResolveType, void*, uint32_t>();
+ if (cls_->NeedsAccessCheck()) {
+ CheckEntrypointTypes<kQuickResolveTypeAndVerifyAccess, void*, uint32_t>();
+ arm_codegen->InvokeRuntime(kQuickResolveTypeAndVerifyAccess, instruction_, dex_pc, this);
+ } else {
+ CheckEntrypointTypes<kQuickResolveType, void*, uint32_t>();
+ arm_codegen->InvokeRuntime(kQuickResolveType, instruction_, dex_pc, this);
+ }
// If we also must_do_clinit, the resolved type is now in the correct register.
} else {
DCHECK(must_do_clinit);
@@ -1863,6 +1868,8 @@ CodeGeneratorARMVIXL::CodeGeneratorARMVIXL(HGraph* graph,
method_bss_entry_patches_(graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)),
boot_image_type_patches_(graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)),
type_bss_entry_patches_(graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)),
+ public_type_bss_entry_patches_(graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)),
+ package_type_bss_entry_patches_(graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)),
boot_image_string_patches_(graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)),
string_bss_entry_patches_(graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)),
boot_image_other_patches_(graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)),
@@ -7299,6 +7306,8 @@ HLoadClass::LoadKind CodeGeneratorARMVIXL::GetSupportedLoadClassKind(
case HLoadClass::LoadKind::kBootImageLinkTimePcRelative:
case HLoadClass::LoadKind::kBootImageRelRo:
case HLoadClass::LoadKind::kBssEntry:
+ case HLoadClass::LoadKind::kBssEntryPublic:
+ case HLoadClass::LoadKind::kBssEntryPackage:
DCHECK(!GetCompilerOptions().IsJitCompiler());
break;
case HLoadClass::LoadKind::kJitBootImageAddress:
@@ -7322,7 +7331,9 @@ void LocationsBuilderARMVIXL::VisitLoadClass(HLoadClass* cls) {
DCHECK(calling_convention.GetRegisterAt(0).Is(r0));
return;
}
- DCHECK(!cls->NeedsAccessCheck());
+ DCHECK_EQ(cls->NeedsAccessCheck(),
+ load_kind == HLoadClass::LoadKind::kBssEntryPublic ||
+ load_kind == HLoadClass::LoadKind::kBssEntryPackage);
const bool requires_read_barrier = kEmitCompilerReadBarrier && !cls->IsInBootImage();
LocationSummary::CallKind call_kind = (cls->NeedsEnvironment() || requires_read_barrier)
@@ -7356,7 +7367,9 @@ void InstructionCodeGeneratorARMVIXL::VisitLoadClass(HLoadClass* cls) NO_THREAD_
codegen_->MaybeGenerateMarkingRegisterCheck(/* code= */ 15);
return;
}
- DCHECK(!cls->NeedsAccessCheck());
+ DCHECK_EQ(cls->NeedsAccessCheck(),
+ load_kind == HLoadClass::LoadKind::kBssEntryPublic ||
+ load_kind == HLoadClass::LoadKind::kBssEntryPackage);
LocationSummary* locations = cls->GetLocations();
Location out_loc = locations->Out();
@@ -7396,9 +7409,10 @@ void InstructionCodeGeneratorARMVIXL::VisitLoadClass(HLoadClass* cls) NO_THREAD_
__ Ldr(out, MemOperand(out, /* offset= */ 0));
break;
}
- case HLoadClass::LoadKind::kBssEntry: {
- CodeGeneratorARMVIXL::PcRelativePatchInfo* labels =
- codegen_->NewTypeBssEntryPatch(cls->GetDexFile(), cls->GetTypeIndex());
+ case HLoadClass::LoadKind::kBssEntry:
+ case HLoadClass::LoadKind::kBssEntryPublic:
+ case HLoadClass::LoadKind::kBssEntryPackage: {
+ CodeGeneratorARMVIXL::PcRelativePatchInfo* labels = codegen_->NewTypeBssEntryPatch(cls);
codegen_->EmitMovwMovtPlaceholder(labels, out);
// All aligned loads are implicitly atomic consume operations on ARM.
codegen_->GenerateGcRootFieldLoad(cls, out_loc, out, /* offset= */ 0, read_barrier_option);
@@ -9247,7 +9261,24 @@ CodeGeneratorARMVIXL::PcRelativePatchInfo* CodeGeneratorARMVIXL::NewBootImageTyp
}
CodeGeneratorARMVIXL::PcRelativePatchInfo* CodeGeneratorARMVIXL::NewTypeBssEntryPatch(
- const DexFile& dex_file, dex::TypeIndex type_index) {
+ HLoadClass* load_class) {
+ const DexFile& dex_file = load_class->GetDexFile();
+ dex::TypeIndex type_index = load_class->GetTypeIndex();
+ ArenaDeque<PcRelativePatchInfo>* patches = nullptr;
+ switch (load_class->GetLoadKind()) {
+ case HLoadClass::LoadKind::kBssEntry:
+ patches = &type_bss_entry_patches_;
+ break;
+ case HLoadClass::LoadKind::kBssEntryPublic:
+ patches = &public_type_bss_entry_patches_;
+ break;
+ case HLoadClass::LoadKind::kBssEntryPackage:
+ patches = &package_type_bss_entry_patches_;
+ break;
+ default:
+ LOG(FATAL) << "Unexpected load kind: " << load_class->GetLoadKind();
+ UNREACHABLE();
+ }
return NewPcRelativePatch(&dex_file, type_index.index_, &type_bss_entry_patches_);
}
@@ -9397,6 +9428,8 @@ void CodeGeneratorARMVIXL::EmitLinkerPatches(ArenaVector<linker::LinkerPatch>* l
/* MOVW+MOVT for each entry */ 2u * method_bss_entry_patches_.size() +
/* MOVW+MOVT for each entry */ 2u * boot_image_type_patches_.size() +
/* MOVW+MOVT for each entry */ 2u * type_bss_entry_patches_.size() +
+ /* MOVW+MOVT for each entry */ 2u * public_type_bss_entry_patches_.size() +
+ /* MOVW+MOVT for each entry */ 2u * package_type_bss_entry_patches_.size() +
/* MOVW+MOVT for each entry */ 2u * boot_image_string_patches_.size() +
/* MOVW+MOVT for each entry */ 2u * string_bss_entry_patches_.size() +
/* MOVW+MOVT for each entry */ 2u * boot_image_other_patches_.size() +
@@ -9426,6 +9459,10 @@ void CodeGeneratorARMVIXL::EmitLinkerPatches(ArenaVector<linker::LinkerPatch>* l
method_bss_entry_patches_, linker_patches);
EmitPcRelativeLinkerPatches<linker::LinkerPatch::TypeBssEntryPatch>(
type_bss_entry_patches_, linker_patches);
+ EmitPcRelativeLinkerPatches<linker::LinkerPatch::PublicTypeBssEntryPatch>(
+ public_type_bss_entry_patches_, linker_patches);
+ EmitPcRelativeLinkerPatches<linker::LinkerPatch::PackageTypeBssEntryPatch>(
+ package_type_bss_entry_patches_, linker_patches);
EmitPcRelativeLinkerPatches<linker::LinkerPatch::StringBssEntryPatch>(
string_bss_entry_patches_, linker_patches);
for (const PatchInfo<vixl32::Label>& info : call_entrypoint_patches_) {
diff --git a/compiler/optimizing/code_generator_arm_vixl.h b/compiler/optimizing/code_generator_arm_vixl.h
index f9b7c0d291..0453d20cc6 100644
--- a/compiler/optimizing/code_generator_arm_vixl.h
+++ b/compiler/optimizing/code_generator_arm_vixl.h
@@ -615,7 +615,7 @@ class CodeGeneratorARMVIXL : public CodeGenerator {
PcRelativePatchInfo* NewBootImageMethodPatch(MethodReference target_method);
PcRelativePatchInfo* NewMethodBssEntryPatch(MethodReference target_method);
PcRelativePatchInfo* NewBootImageTypePatch(const DexFile& dex_file, dex::TypeIndex type_index);
- PcRelativePatchInfo* NewTypeBssEntryPatch(const DexFile& dex_file, dex::TypeIndex type_index);
+ PcRelativePatchInfo* NewTypeBssEntryPatch(HLoadClass* load_class);
PcRelativePatchInfo* NewBootImageStringPatch(const DexFile& dex_file,
dex::StringIndex string_index);
PcRelativePatchInfo* NewStringBssEntryPatch(const DexFile& dex_file,
@@ -924,6 +924,10 @@ class CodeGeneratorARMVIXL : public CodeGenerator {
ArenaDeque<PcRelativePatchInfo> boot_image_type_patches_;
// PC-relative type patch info for kBssEntry.
ArenaDeque<PcRelativePatchInfo> type_bss_entry_patches_;
+ // PC-relative public type patch info for kBssEntryPublic.
+ ArenaDeque<PcRelativePatchInfo> public_type_bss_entry_patches_;
+ // PC-relative package type patch info for kBssEntryPackage.
+ ArenaDeque<PcRelativePatchInfo> package_type_bss_entry_patches_;
// PC-relative String patch info for kBootImageLinkTimePcRelative.
ArenaDeque<PcRelativePatchInfo> boot_image_string_patches_;
// PC-relative String patch info for kBssEntry.
diff --git a/compiler/optimizing/code_generator_x86.cc b/compiler/optimizing/code_generator_x86.cc
index 303c35ec3b..86e6b959ed 100644
--- a/compiler/optimizing/code_generator_x86.cc
+++ b/compiler/optimizing/code_generator_x86.cc
@@ -291,8 +291,13 @@ class LoadClassSlowPathX86 : public SlowPathCode {
DCHECK(IsSameDexFile(cls_->GetDexFile(), x86_codegen->GetGraph()->GetDexFile()));
dex::TypeIndex type_index = cls_->GetTypeIndex();
__ movl(calling_convention.GetRegisterAt(0), Immediate(type_index.index_));
- x86_codegen->InvokeRuntime(kQuickResolveType, instruction_, dex_pc, this);
- CheckEntrypointTypes<kQuickResolveType, void*, uint32_t>();
+ if (cls_->NeedsAccessCheck()) {
+ CheckEntrypointTypes<kQuickResolveTypeAndVerifyAccess, void*, uint32_t>();
+ x86_codegen->InvokeRuntime(kQuickResolveTypeAndVerifyAccess, instruction_, dex_pc, this);
+ } else {
+ CheckEntrypointTypes<kQuickResolveType, void*, uint32_t>();
+ x86_codegen->InvokeRuntime(kQuickResolveType, instruction_, dex_pc, this);
+ }
// If we also must_do_clinit, the resolved type is now in the correct register.
} else {
DCHECK(must_do_clinit);
@@ -1056,6 +1061,8 @@ CodeGeneratorX86::CodeGeneratorX86(HGraph* graph,
method_bss_entry_patches_(graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)),
boot_image_type_patches_(graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)),
type_bss_entry_patches_(graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)),
+ public_type_bss_entry_patches_(graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)),
+ package_type_bss_entry_patches_(graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)),
boot_image_string_patches_(graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)),
string_bss_entry_patches_(graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)),
boot_image_other_patches_(graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)),
@@ -5362,9 +5369,24 @@ void CodeGeneratorX86::RecordBootImageTypePatch(HLoadClass* load_class) {
Label* CodeGeneratorX86::NewTypeBssEntryPatch(HLoadClass* load_class) {
HX86ComputeBaseMethodAddress* method_address =
load_class->InputAt(0)->AsX86ComputeBaseMethodAddress();
- type_bss_entry_patches_.emplace_back(
+ ArenaDeque<X86PcRelativePatchInfo>* patches = nullptr;
+ switch (load_class->GetLoadKind()) {
+ case HLoadClass::LoadKind::kBssEntry:
+ patches = &type_bss_entry_patches_;
+ break;
+ case HLoadClass::LoadKind::kBssEntryPublic:
+ patches = &public_type_bss_entry_patches_;
+ break;
+ case HLoadClass::LoadKind::kBssEntryPackage:
+ patches = &package_type_bss_entry_patches_;
+ break;
+ default:
+ LOG(FATAL) << "Unexpected load kind: " << load_class->GetLoadKind();
+ UNREACHABLE();
+ }
+ patches->emplace_back(
method_address, &load_class->GetDexFile(), load_class->GetTypeIndex().index_);
- return &type_bss_entry_patches_.back().label;
+ return &patches->back().label;
}
void CodeGeneratorX86::RecordBootImageStringPatch(HLoadString* load_string) {
@@ -5469,6 +5491,8 @@ void CodeGeneratorX86::EmitLinkerPatches(ArenaVector<linker::LinkerPatch>* linke
method_bss_entry_patches_.size() +
boot_image_type_patches_.size() +
type_bss_entry_patches_.size() +
+ public_type_bss_entry_patches_.size() +
+ package_type_bss_entry_patches_.size() +
boot_image_string_patches_.size() +
string_bss_entry_patches_.size() +
boot_image_other_patches_.size();
@@ -5496,6 +5520,10 @@ void CodeGeneratorX86::EmitLinkerPatches(ArenaVector<linker::LinkerPatch>* linke
method_bss_entry_patches_, linker_patches);
EmitPcRelativeLinkerPatches<linker::LinkerPatch::TypeBssEntryPatch>(
type_bss_entry_patches_, linker_patches);
+ EmitPcRelativeLinkerPatches<linker::LinkerPatch::PublicTypeBssEntryPatch>(
+ public_type_bss_entry_patches_, linker_patches);
+ EmitPcRelativeLinkerPatches<linker::LinkerPatch::PackageTypeBssEntryPatch>(
+ package_type_bss_entry_patches_, linker_patches);
EmitPcRelativeLinkerPatches<linker::LinkerPatch::StringBssEntryPatch>(
string_bss_entry_patches_, linker_patches);
DCHECK_EQ(size, linker_patches->size());
@@ -6933,6 +6961,8 @@ HLoadClass::LoadKind CodeGeneratorX86::GetSupportedLoadClassKind(
case HLoadClass::LoadKind::kBootImageLinkTimePcRelative:
case HLoadClass::LoadKind::kBootImageRelRo:
case HLoadClass::LoadKind::kBssEntry:
+ case HLoadClass::LoadKind::kBssEntryPublic:
+ case HLoadClass::LoadKind::kBssEntryPackage:
DCHECK(!GetCompilerOptions().IsJitCompiler());
break;
case HLoadClass::LoadKind::kJitBootImageAddress:
@@ -6956,7 +6986,9 @@ void LocationsBuilderX86::VisitLoadClass(HLoadClass* cls) {
DCHECK_EQ(calling_convention.GetRegisterAt(0), EAX);
return;
}
- DCHECK(!cls->NeedsAccessCheck());
+ DCHECK_EQ(cls->NeedsAccessCheck(),
+ load_kind == HLoadClass::LoadKind::kBssEntryPublic ||
+ load_kind == HLoadClass::LoadKind::kBssEntryPackage);
const bool requires_read_barrier = kEmitCompilerReadBarrier && !cls->IsInBootImage();
LocationSummary::CallKind call_kind = (cls->NeedsEnvironment() || requires_read_barrier)
@@ -6967,14 +6999,11 @@ void LocationsBuilderX86::VisitLoadClass(HLoadClass* cls) {
locations->SetCustomSlowPathCallerSaves(RegisterSet::Empty()); // No caller-save registers.
}
- if (load_kind == HLoadClass::LoadKind::kReferrersClass ||
- load_kind == HLoadClass::LoadKind::kBootImageLinkTimePcRelative ||
- load_kind == HLoadClass::LoadKind::kBootImageRelRo ||
- load_kind == HLoadClass::LoadKind::kBssEntry) {
+ if (load_kind == HLoadClass::LoadKind::kReferrersClass || cls->HasPcRelativeLoadKind()) {
locations->SetInAt(0, Location::RequiresRegister());
}
locations->SetOut(Location::RequiresRegister());
- if (load_kind == HLoadClass::LoadKind::kBssEntry) {
+ if (call_kind == LocationSummary::kCallOnSlowPath && cls->HasPcRelativeLoadKind()) {
if (!kUseReadBarrier || kUseBakerReadBarrier) {
// Rely on the type resolution and/or initialization to save everything.
locations->SetCustomSlowPathCallerSaves(OneRegInReferenceOutSaveEverythingCallerSaves());
@@ -7002,7 +7031,9 @@ void InstructionCodeGeneratorX86::VisitLoadClass(HLoadClass* cls) NO_THREAD_SAFE
codegen_->GenerateLoadClassRuntimeCall(cls);
return;
}
- DCHECK(!cls->NeedsAccessCheck());
+ DCHECK_EQ(cls->NeedsAccessCheck(),
+ load_kind == HLoadClass::LoadKind::kBssEntryPublic ||
+ load_kind == HLoadClass::LoadKind::kBssEntryPackage);
LocationSummary* locations = cls->GetLocations();
Location out_loc = locations->Out();
@@ -7043,7 +7074,9 @@ void InstructionCodeGeneratorX86::VisitLoadClass(HLoadClass* cls) NO_THREAD_SAFE
codegen_->GetBootImageOffset(cls));
break;
}
- case HLoadClass::LoadKind::kBssEntry: {
+ case HLoadClass::LoadKind::kBssEntry:
+ case HLoadClass::LoadKind::kBssEntryPublic:
+ case HLoadClass::LoadKind::kBssEntryPackage: {
Register method_address = locations->InAt(0).AsRegister<Register>();
Address address(method_address, CodeGeneratorX86::kPlaceholder32BitOffset);
Label* fixup_label = codegen_->NewTypeBssEntryPatch(cls);
diff --git a/compiler/optimizing/code_generator_x86.h b/compiler/optimizing/code_generator_x86.h
index a573e845a0..b0575ba969 100644
--- a/compiler/optimizing/code_generator_x86.h
+++ b/compiler/optimizing/code_generator_x86.h
@@ -715,6 +715,10 @@ class CodeGeneratorX86 : public CodeGenerator {
ArenaDeque<X86PcRelativePatchInfo> boot_image_type_patches_;
// PC-relative type patch info for kBssEntry.
ArenaDeque<X86PcRelativePatchInfo> type_bss_entry_patches_;
+ // PC-relative public type patch info for kBssEntryPublic.
+ ArenaDeque<X86PcRelativePatchInfo> public_type_bss_entry_patches_;
+ // PC-relative package type patch info for kBssEntryPackage.
+ ArenaDeque<X86PcRelativePatchInfo> package_type_bss_entry_patches_;
// PC-relative String patch info for kBootImageLinkTimePcRelative.
ArenaDeque<X86PcRelativePatchInfo> boot_image_string_patches_;
// PC-relative String patch info for kBssEntry.
diff --git a/compiler/optimizing/code_generator_x86_64.cc b/compiler/optimizing/code_generator_x86_64.cc
index f18fde054c..202b58b9ee 100644
--- a/compiler/optimizing/code_generator_x86_64.cc
+++ b/compiler/optimizing/code_generator_x86_64.cc
@@ -272,8 +272,13 @@ class LoadClassSlowPathX86_64 : public SlowPathCode {
DCHECK(IsSameDexFile(cls_->GetDexFile(), x86_64_codegen->GetGraph()->GetDexFile()));
dex::TypeIndex type_index = cls_->GetTypeIndex();
__ movl(CpuRegister(RAX), Immediate(type_index.index_));
- x86_64_codegen->InvokeRuntime(kQuickResolveType, instruction_, dex_pc, this);
- CheckEntrypointTypes<kQuickResolveType, void*, uint32_t>();
+ if (cls_->NeedsAccessCheck()) {
+ CheckEntrypointTypes<kQuickResolveTypeAndVerifyAccess, void*, uint32_t>();
+ x86_64_codegen->InvokeRuntime(kQuickResolveTypeAndVerifyAccess, instruction_, dex_pc, this);
+ } else {
+ CheckEntrypointTypes<kQuickResolveType, void*, uint32_t>();
+ x86_64_codegen->InvokeRuntime(kQuickResolveType, instruction_, dex_pc, this);
+ }
// If we also must_do_clinit, the resolved type is now in the correct register.
} else {
DCHECK(must_do_clinit);
@@ -1162,9 +1167,23 @@ void CodeGeneratorX86_64::RecordBootImageTypePatch(HLoadClass* load_class) {
}
Label* CodeGeneratorX86_64::NewTypeBssEntryPatch(HLoadClass* load_class) {
- type_bss_entry_patches_.emplace_back(
- &load_class->GetDexFile(), load_class->GetTypeIndex().index_);
- return &type_bss_entry_patches_.back().label;
+ ArenaDeque<PatchInfo<Label>>* patches = nullptr;
+ switch (load_class->GetLoadKind()) {
+ case HLoadClass::LoadKind::kBssEntry:
+ patches = &type_bss_entry_patches_;
+ break;
+ case HLoadClass::LoadKind::kBssEntryPublic:
+ patches = &public_type_bss_entry_patches_;
+ break;
+ case HLoadClass::LoadKind::kBssEntryPackage:
+ patches = &package_type_bss_entry_patches_;
+ break;
+ default:
+ LOG(FATAL) << "Unexpected load kind: " << load_class->GetLoadKind();
+ UNREACHABLE();
+ }
+ patches->emplace_back(&load_class->GetDexFile(), load_class->GetTypeIndex().index_);
+ return &patches->back().label;
}
void CodeGeneratorX86_64::RecordBootImageStringPatch(HLoadString* load_string) {
@@ -1249,6 +1268,8 @@ void CodeGeneratorX86_64::EmitLinkerPatches(ArenaVector<linker::LinkerPatch>* li
method_bss_entry_patches_.size() +
boot_image_type_patches_.size() +
type_bss_entry_patches_.size() +
+ public_type_bss_entry_patches_.size() +
+ package_type_bss_entry_patches_.size() +
boot_image_string_patches_.size() +
string_bss_entry_patches_.size() +
boot_image_other_patches_.size();
@@ -1276,6 +1297,10 @@ void CodeGeneratorX86_64::EmitLinkerPatches(ArenaVector<linker::LinkerPatch>* li
method_bss_entry_patches_, linker_patches);
EmitPcRelativeLinkerPatches<linker::LinkerPatch::TypeBssEntryPatch>(
type_bss_entry_patches_, linker_patches);
+ EmitPcRelativeLinkerPatches<linker::LinkerPatch::PublicTypeBssEntryPatch>(
+ public_type_bss_entry_patches_, linker_patches);
+ EmitPcRelativeLinkerPatches<linker::LinkerPatch::PackageTypeBssEntryPatch>(
+ package_type_bss_entry_patches_, linker_patches);
EmitPcRelativeLinkerPatches<linker::LinkerPatch::StringBssEntryPatch>(
string_bss_entry_patches_, linker_patches);
DCHECK_EQ(size, linker_patches->size());
@@ -1370,6 +1395,8 @@ CodeGeneratorX86_64::CodeGeneratorX86_64(HGraph* graph,
method_bss_entry_patches_(graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)),
boot_image_type_patches_(graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)),
type_bss_entry_patches_(graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)),
+ public_type_bss_entry_patches_(graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)),
+ package_type_bss_entry_patches_(graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)),
boot_image_string_patches_(graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)),
string_bss_entry_patches_(graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)),
boot_image_other_patches_(graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)),
@@ -6092,6 +6119,8 @@ HLoadClass::LoadKind CodeGeneratorX86_64::GetSupportedLoadClassKind(
case HLoadClass::LoadKind::kBootImageLinkTimePcRelative:
case HLoadClass::LoadKind::kBootImageRelRo:
case HLoadClass::LoadKind::kBssEntry:
+ case HLoadClass::LoadKind::kBssEntryPublic:
+ case HLoadClass::LoadKind::kBssEntryPackage:
DCHECK(!GetCompilerOptions().IsJitCompiler());
break;
case HLoadClass::LoadKind::kJitBootImageAddress:
@@ -6114,7 +6143,9 @@ void LocationsBuilderX86_64::VisitLoadClass(HLoadClass* cls) {
Location::RegisterLocation(RAX));
return;
}
- DCHECK(!cls->NeedsAccessCheck());
+ DCHECK_EQ(cls->NeedsAccessCheck(),
+ load_kind == HLoadClass::LoadKind::kBssEntryPublic ||
+ load_kind == HLoadClass::LoadKind::kBssEntryPackage);
const bool requires_read_barrier = kEmitCompilerReadBarrier && !cls->IsInBootImage();
LocationSummary::CallKind call_kind = (cls->NeedsEnvironment() || requires_read_barrier)
@@ -6157,7 +6188,9 @@ void InstructionCodeGeneratorX86_64::VisitLoadClass(HLoadClass* cls) NO_THREAD_S
codegen_->GenerateLoadClassRuntimeCall(cls);
return;
}
- DCHECK(!cls->NeedsAccessCheck());
+ DCHECK_EQ(cls->NeedsAccessCheck(),
+ load_kind == HLoadClass::LoadKind::kBssEntryPublic ||
+ load_kind == HLoadClass::LoadKind::kBssEntryPackage);
LocationSummary* locations = cls->GetLocations();
Location out_loc = locations->Out();
@@ -6196,7 +6229,9 @@ void InstructionCodeGeneratorX86_64::VisitLoadClass(HLoadClass* cls) NO_THREAD_S
codegen_->RecordBootImageRelRoPatch(codegen_->GetBootImageOffset(cls));
break;
}
- case HLoadClass::LoadKind::kBssEntry: {
+ case HLoadClass::LoadKind::kBssEntry:
+ case HLoadClass::LoadKind::kBssEntryPublic:
+ case HLoadClass::LoadKind::kBssEntryPackage: {
Address address = Address::Absolute(CodeGeneratorX86_64::kPlaceholder32BitOffset,
/* no_rip= */ false);
Label* fixup_label = codegen_->NewTypeBssEntryPatch(cls);
diff --git a/compiler/optimizing/code_generator_x86_64.h b/compiler/optimizing/code_generator_x86_64.h
index dc18a249be..81988b4386 100644
--- a/compiler/optimizing/code_generator_x86_64.h
+++ b/compiler/optimizing/code_generator_x86_64.h
@@ -668,6 +668,10 @@ class CodeGeneratorX86_64 : public CodeGenerator {
ArenaDeque<PatchInfo<Label>> boot_image_type_patches_;
// PC-relative type patch info for kBssEntry.
ArenaDeque<PatchInfo<Label>> type_bss_entry_patches_;
+ // PC-relative public type patch info for kBssEntryPublic.
+ ArenaDeque<PatchInfo<Label>> public_type_bss_entry_patches_;
+ // PC-relative package type patch info for kBssEntryPackage.
+ ArenaDeque<PatchInfo<Label>> package_type_bss_entry_patches_;
// PC-relative String patch info for kBootImageLinkTimePcRelative.
ArenaDeque<PatchInfo<Label>> boot_image_string_patches_;
// PC-relative String patch info for kBssEntry.
diff --git a/compiler/optimizing/nodes.h b/compiler/optimizing/nodes.h
index d7a66f1400..b674937ee3 100644
--- a/compiler/optimizing/nodes.h
+++ b/compiler/optimizing/nodes.h
@@ -6391,6 +6391,21 @@ class HLoadClass final : public HInstruction {
// Used for classes outside boot image referenced by AOT-compiled app and boot image code.
kBssEntry,
+ // Load from an entry for public class in the .bss section using a PC-relative load.
+ // Used for classes that were unresolved during AOT-compilation outside the literal
+ // package of the compiling class. Such classes are accessible only if they are public
+ // and the .bss entry shall therefore be filled only if the resolved class is public.
+ kBssEntryPublic,
+
+ // Load from an entry for package class in the .bss section using a PC-relative load.
+ // Used for classes that were unresolved during AOT-compilation but within the literal
+ // package of the compiling class. Such classes are accessible if they are public or
+ // in the same package which, given the literal package match, requires only matching
+ // defining class loader and the .bss entry shall therefore be filled only if at least
+ // one of those conditions holds. Note that all code in an oat file belongs to classes
+ // with the same defining class loader.
+ kBssEntryPackage,
+
// Use a known boot image Class* address, embedded in the code by the codegen.
// Used for boot image classes referenced by apps in JIT-compiled code.
kJitBootImageAddress,
@@ -6443,7 +6458,9 @@ class HLoadClass final : public HInstruction {
bool HasPcRelativeLoadKind() const {
return GetLoadKind() == LoadKind::kBootImageLinkTimePcRelative ||
GetLoadKind() == LoadKind::kBootImageRelRo ||
- GetLoadKind() == LoadKind::kBssEntry;
+ GetLoadKind() == LoadKind::kBssEntry ||
+ GetLoadKind() == LoadKind::kBssEntryPublic ||
+ GetLoadKind() == LoadKind::kBssEntryPackage;
}
bool CanBeMoved() const override { return true; }
@@ -6459,9 +6476,6 @@ class HLoadClass final : public HInstruction {
}
void SetMustGenerateClinitCheck(bool generate_clinit_check) {
- // The entrypoint the code generator is going to call does not do
- // clinit of the class.
- DCHECK(!NeedsAccessCheck());
SetPackedFlag<kFlagGenerateClInitCheck>(generate_clinit_check);
}
@@ -6514,9 +6528,14 @@ class HLoadClass final : public HInstruction {
bool MustResolveTypeOnSlowPath() const {
// Check that this instruction has a slow path.
- DCHECK(GetLoadKind() != LoadKind::kRuntimeCall); // kRuntimeCall calls on main path.
- DCHECK(GetLoadKind() == LoadKind::kBssEntry || MustGenerateClinitCheck());
- return GetLoadKind() == LoadKind::kBssEntry;
+ LoadKind load_kind = GetLoadKind();
+ DCHECK(load_kind != LoadKind::kRuntimeCall); // kRuntimeCall calls on main path.
+ bool must_resolve_type_on_slow_path =
+ load_kind == LoadKind::kBssEntry ||
+ load_kind == LoadKind::kBssEntryPublic ||
+ load_kind == LoadKind::kBssEntryPackage;
+ DCHECK(must_resolve_type_on_slow_path || MustGenerateClinitCheck());
+ return must_resolve_type_on_slow_path;
}
void MarkInBootImage() {
@@ -6558,6 +6577,8 @@ class HLoadClass final : public HInstruction {
return load_kind == LoadKind::kReferrersClass ||
load_kind == LoadKind::kBootImageLinkTimePcRelative ||
load_kind == LoadKind::kBssEntry ||
+ load_kind == LoadKind::kBssEntryPublic ||
+ load_kind == LoadKind::kBssEntryPackage ||
load_kind == LoadKind::kRuntimeCall;
}
@@ -6565,14 +6586,14 @@ class HLoadClass final : public HInstruction {
// The special input is the HCurrentMethod for kRuntimeCall or kReferrersClass.
// For other load kinds it's empty or possibly some architecture-specific instruction
- // for PC-relative loads, i.e. kBssEntry or kBootImageLinkTimePcRelative.
+ // for PC-relative loads, i.e. kBssEntry* or kBootImageLinkTimePcRelative.
HUserRecord<HInstruction*> special_input_;
// A type index and dex file where the class can be accessed. The dex file can be:
// - The compiling method's dex file if the class is defined there too.
// - The compiling method's dex file if the class is referenced there.
// - The dex file where the class is defined. When the load kind can only be
- // kBssEntry or kRuntimeCall, we cannot emit code for this `HLoadClass`.
+ // kBssEntry* or kRuntimeCall, we cannot emit code for this `HLoadClass`.
const dex::TypeIndex type_index_;
const DexFile& dex_file_;
@@ -6601,6 +6622,8 @@ inline void HLoadClass::AddSpecialInput(HInstruction* special_input) {
DCHECK(GetLoadKind() == LoadKind::kBootImageLinkTimePcRelative ||
GetLoadKind() == LoadKind::kBootImageRelRo ||
GetLoadKind() == LoadKind::kBssEntry ||
+ GetLoadKind() == LoadKind::kBssEntryPublic ||
+ GetLoadKind() == LoadKind::kBssEntryPackage ||
GetLoadKind() == LoadKind::kJitBootImageAddress) << GetLoadKind();
DCHECK(special_input_.GetInstruction() == nullptr);
special_input_ = HUserRecord<HInstruction*>(special_input);
diff --git a/compiler/optimizing/prepare_for_register_allocation.cc b/compiler/optimizing/prepare_for_register_allocation.cc
index 8c4615d8c2..d5edc3da36 100644
--- a/compiler/optimizing/prepare_for_register_allocation.cc
+++ b/compiler/optimizing/prepare_for_register_allocation.cc
@@ -166,7 +166,6 @@ void PrepareForRegisterAllocation::VisitClinitCheck(HClinitCheck* check) {
}
} else if (can_merge_with_load_class &&
load_class->GetLoadKind() != HLoadClass::LoadKind::kRuntimeCall) {
- DCHECK(!load_class->NeedsAccessCheck());
// Pass the initialization duty to the `HLoadClass` instruction,
// and remove the instruction from the graph.
DCHECK(load_class->HasEnvironment());
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.