summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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
-rw-r--r--dex2oat/linker/arm64/relative_patcher_arm64.cc6
-rw-r--r--dex2oat/linker/oat_writer.cc175
-rw-r--r--dex2oat/linker/oat_writer.h20
-rw-r--r--runtime/entrypoints/quick/quick_dexcache_entrypoints.cc26
-rw-r--r--runtime/oat.h4
-rw-r--r--runtime/oat_file.cc12
-rw-r--r--runtime/oat_file.h12
-rw-r--r--test/727-checker-unresolved-class/src/unresolved/UnresolvedPublicClass.java45
20 files changed, 586 insertions, 97 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.
diff --git a/dex2oat/linker/arm64/relative_patcher_arm64.cc b/dex2oat/linker/arm64/relative_patcher_arm64.cc
index 2260f66d1f..494391bd45 100644
--- a/dex2oat/linker/arm64/relative_patcher_arm64.cc
+++ b/dex2oat/linker/arm64/relative_patcher_arm64.cc
@@ -67,6 +67,8 @@ inline bool IsAdrpPatch(const LinkerPatch& patch) {
case LinkerPatch::Type::kMethodBssEntry:
case LinkerPatch::Type::kTypeRelative:
case LinkerPatch::Type::kTypeBssEntry:
+ case LinkerPatch::Type::kPublicTypeBssEntry:
+ case LinkerPatch::Type::kPackageTypeBssEntry:
case LinkerPatch::Type::kStringRelative:
case LinkerPatch::Type::kStringBssEntry:
return patch.LiteralOffset() == patch.PcInsnOffset();
@@ -261,6 +263,8 @@ void Arm64RelativePatcher::PatchPcRelativeReference(std::vector<uint8_t>* code,
patch.GetType() == LinkerPatch::Type::kTypeRelative ||
patch.GetType() == LinkerPatch::Type::kStringRelative ||
patch.GetType() == LinkerPatch::Type::kTypeBssEntry ||
+ patch.GetType() == LinkerPatch::Type::kPublicTypeBssEntry ||
+ patch.GetType() == LinkerPatch::Type::kPackageTypeBssEntry ||
patch.GetType() == LinkerPatch::Type::kStringBssEntry) << patch.GetType();
}
shift = 0u; // No shift for ADD.
@@ -269,6 +273,8 @@ void Arm64RelativePatcher::PatchPcRelativeReference(std::vector<uint8_t>* code,
DCHECK(patch.GetType() == LinkerPatch::Type::kDataBimgRelRo ||
patch.GetType() == LinkerPatch::Type::kMethodBssEntry ||
patch.GetType() == LinkerPatch::Type::kTypeBssEntry ||
+ patch.GetType() == LinkerPatch::Type::kPublicTypeBssEntry ||
+ patch.GetType() == LinkerPatch::Type::kPackageTypeBssEntry ||
patch.GetType() == LinkerPatch::Type::kStringBssEntry) << patch.GetType();
DCHECK_EQ(insn & 0xbfbffc00, 0xb9000000) << std::hex << insn;
}
diff --git a/dex2oat/linker/oat_writer.cc b/dex2oat/linker/oat_writer.cc
index a49b7d4f0d..73ad9e9682 100644
--- a/dex2oat/linker/oat_writer.cc
+++ b/dex2oat/linker/oat_writer.cc
@@ -351,6 +351,8 @@ class OatWriter::OatDexFile {
uint32_t class_offsets_offset_;
uint32_t method_bss_mapping_offset_;
uint32_t type_bss_mapping_offset_;
+ uint32_t public_type_bss_mapping_offset_;
+ uint32_t package_type_bss_mapping_offset_;
uint32_t string_bss_mapping_offset_;
// Offset of dex sections that will have different runtime madvise states.
@@ -412,6 +414,8 @@ OatWriter::OatWriter(const CompilerOptions& compiler_options,
bss_method_entry_references_(),
bss_method_entries_(),
bss_type_entries_(),
+ bss_public_type_entries_(),
+ bss_package_type_entries_(),
bss_string_entries_(),
oat_data_offset_(0u),
oat_header_(nullptr),
@@ -456,6 +460,8 @@ OatWriter::OatWriter(const CompilerOptions& compiler_options,
size_oat_dex_file_dex_layout_sections_alignment_(0),
size_oat_dex_file_method_bss_mapping_offset_(0),
size_oat_dex_file_type_bss_mapping_offset_(0),
+ size_oat_dex_file_public_type_bss_mapping_offset_(0),
+ size_oat_dex_file_package_type_bss_mapping_offset_(0),
size_oat_dex_file_string_bss_mapping_offset_(0),
size_oat_lookup_table_alignment_(0),
size_oat_lookup_table_(0),
@@ -467,6 +473,8 @@ OatWriter::OatWriter(const CompilerOptions& compiler_options,
size_oat_class_method_offsets_(0),
size_method_bss_mappings_(0u),
size_type_bss_mappings_(0u),
+ size_public_type_bss_mappings_(0u),
+ size_package_type_bss_mappings_(0u),
size_string_bss_mappings_(0u),
relative_patcher_(nullptr),
profile_compilation_info_(info),
@@ -917,6 +925,18 @@ class OatWriter::InitBssLayoutMethodVisitor : public DexMethodVisitor {
target_type.dex_file->NumTypeIds(),
&writer_->bss_type_entry_references_);
writer_->bss_type_entries_.Overwrite(target_type, /* placeholder */ 0u);
+ } else if (patch.GetType() == LinkerPatch::Type::kPublicTypeBssEntry) {
+ TypeReference target_type(patch.TargetTypeDexFile(), patch.TargetTypeIndex());
+ AddBssReference(target_type,
+ target_type.dex_file->NumTypeIds(),
+ &writer_->bss_public_type_entry_references_);
+ writer_->bss_public_type_entries_.Overwrite(target_type, /* placeholder */ 0u);
+ } else if (patch.GetType() == LinkerPatch::Type::kPackageTypeBssEntry) {
+ TypeReference target_type(patch.TargetTypeDexFile(), patch.TargetTypeIndex());
+ AddBssReference(target_type,
+ target_type.dex_file->NumTypeIds(),
+ &writer_->bss_package_type_entry_references_);
+ writer_->bss_package_type_entries_.Overwrite(target_type, /* placeholder */ 0u);
} else if (patch.GetType() == LinkerPatch::Type::kStringBssEntry) {
StringReference target_string(patch.TargetStringDexFile(), patch.TargetStringIndex());
AddBssReference(target_string,
@@ -1839,6 +1859,26 @@ class OatWriter::WriteCodeMethodVisitor : public OrderedMethodVisitor {
target_offset);
break;
}
+ case LinkerPatch::Type::kPublicTypeBssEntry: {
+ TypeReference ref(patch.TargetTypeDexFile(), patch.TargetTypeIndex());
+ uint32_t target_offset =
+ writer_->bss_start_ + writer_->bss_public_type_entries_.Get(ref);
+ writer_->relative_patcher_->PatchPcRelativeReference(&patched_code_,
+ patch,
+ offset_ + literal_offset,
+ target_offset);
+ break;
+ }
+ case LinkerPatch::Type::kPackageTypeBssEntry: {
+ TypeReference ref(patch.TargetTypeDexFile(), patch.TargetTypeIndex());
+ uint32_t target_offset =
+ writer_->bss_start_ + writer_->bss_package_type_entries_.Get(ref);
+ writer_->relative_patcher_->PatchPcRelativeReference(&patched_code_,
+ patch,
+ offset_ + literal_offset,
+ target_offset);
+ break;
+ }
case LinkerPatch::Type::kMethodRelative: {
uint32_t target_offset = GetTargetMethodOffset(GetTargetMethod(patch));
writer_->relative_patcher_->PatchPcRelativeReference(&patched_code_,
@@ -2125,9 +2165,22 @@ static size_t CalculateIndexBssMappingSize(size_t number_of_indexes,
return IndexBssMapping::ComputeSize(number_of_entries);
}
+static size_t CalculateIndexBssMappingSize(
+ const DexFile* dex_file,
+ const BitVector& type_indexes,
+ const SafeMap<TypeReference, size_t, TypeReferenceValueComparator>& bss_entries) {
+ return CalculateIndexBssMappingSize(
+ dex_file->NumTypeIds(),
+ sizeof(GcRoot<mirror::Class>),
+ type_indexes,
+ [=](uint32_t index) { return bss_entries.Get({dex_file, dex::TypeIndex(index)}); });
+}
+
size_t OatWriter::InitIndexBssMappings(size_t offset) {
if (bss_method_entry_references_.empty() &&
bss_type_entry_references_.empty() &&
+ bss_public_type_entry_references_.empty() &&
+ bss_package_type_entry_references_.empty() &&
bss_string_entry_references_.empty()) {
return offset;
}
@@ -2138,6 +2191,8 @@ size_t OatWriter::InitIndexBssMappings(size_t offset) {
size_t number_of_method_dex_files = 0u;
size_t number_of_type_dex_files = 0u;
+ size_t number_of_public_type_dex_files = 0u;
+ size_t number_of_package_type_dex_files = 0u;
size_t number_of_string_dex_files = 0u;
PointerSize pointer_size = GetInstructionSetPointerSize(oat_header_->GetInstructionSet());
for (size_t i = 0, size = dex_files_->size(); i != size; ++i) {
@@ -2161,13 +2216,23 @@ size_t OatWriter::InitIndexBssMappings(size_t offset) {
const BitVector& type_indexes = type_it->second;
++number_of_type_dex_files;
oat_dex_files_[i].type_bss_mapping_offset_ = offset;
- offset += CalculateIndexBssMappingSize(
- dex_file->NumTypeIds(),
- sizeof(GcRoot<mirror::Class>),
- type_indexes,
- [=](uint32_t index) {
- return bss_type_entries_.Get({dex_file, dex::TypeIndex(index)});
- });
+ offset += CalculateIndexBssMappingSize(dex_file, type_indexes, bss_type_entries_);
+ }
+
+ auto public_type_it = bss_public_type_entry_references_.find(dex_file);
+ if (public_type_it != bss_public_type_entry_references_.end()) {
+ const BitVector& type_indexes = public_type_it->second;
+ ++number_of_public_type_dex_files;
+ oat_dex_files_[i].public_type_bss_mapping_offset_ = offset;
+ offset += CalculateIndexBssMappingSize(dex_file, type_indexes, bss_public_type_entries_);
+ }
+
+ auto package_type_it = bss_package_type_entry_references_.find(dex_file);
+ if (package_type_it != bss_package_type_entry_references_.end()) {
+ const BitVector& type_indexes = package_type_it->second;
+ ++number_of_package_type_dex_files;
+ oat_dex_files_[i].package_type_bss_mapping_offset_ = offset;
+ offset += CalculateIndexBssMappingSize(dex_file, type_indexes, bss_package_type_entries_);
}
auto string_it = bss_string_entry_references_.find(dex_file);
@@ -2187,6 +2252,8 @@ size_t OatWriter::InitIndexBssMappings(size_t offset) {
// Check that all dex files targeted by bss entries are in `*dex_files_`.
CHECK_EQ(number_of_method_dex_files, bss_method_entry_references_.size());
CHECK_EQ(number_of_type_dex_files, bss_type_entry_references_.size());
+ CHECK_EQ(number_of_public_type_dex_files, bss_public_type_entry_references_.size());
+ CHECK_EQ(number_of_package_type_dex_files, bss_package_type_entry_references_.size());
CHECK_EQ(number_of_string_dex_files, bss_string_entry_references_.size());
return offset;
}
@@ -2338,6 +2405,8 @@ void OatWriter::InitBssLayout(InstructionSet instruction_set) {
DCHECK_EQ(bss_size_, 0u);
if (bss_method_entries_.empty() &&
bss_type_entries_.empty() &&
+ bss_public_type_entries_.empty() &&
+ bss_package_type_entries_.empty() &&
bss_string_entries_.empty()) {
// Nothing to put to the .bss section.
return;
@@ -2361,6 +2430,18 @@ void OatWriter::InitBssLayout(InstructionSet instruction_set) {
entry.second = bss_size_;
bss_size_ += sizeof(GcRoot<mirror::Class>);
}
+ // Prepare offsets for .bss public Class entries.
+ for (auto& entry : bss_public_type_entries_) {
+ DCHECK_EQ(entry.second, 0u);
+ entry.second = bss_size_;
+ bss_size_ += sizeof(GcRoot<mirror::Class>);
+ }
+ // Prepare offsets for .bss package Class entries.
+ for (auto& entry : bss_package_type_entries_) {
+ DCHECK_EQ(entry.second, 0u);
+ entry.second = bss_size_;
+ bss_size_ += sizeof(GcRoot<mirror::Class>);
+ }
// Prepare offsets for .bss String entries.
for (auto& entry : bss_string_entries_) {
DCHECK_EQ(entry.second, 0u);
@@ -2738,6 +2819,8 @@ bool OatWriter::CheckOatSize(OutputStream* out, size_t file_offset, size_t relat
DO_STAT(size_oat_dex_file_dex_layout_sections_alignment_);
DO_STAT(size_oat_dex_file_method_bss_mapping_offset_);
DO_STAT(size_oat_dex_file_type_bss_mapping_offset_);
+ DO_STAT(size_oat_dex_file_public_type_bss_mapping_offset_);
+ DO_STAT(size_oat_dex_file_package_type_bss_mapping_offset_);
DO_STAT(size_oat_dex_file_string_bss_mapping_offset_);
DO_STAT(size_oat_lookup_table_alignment_);
DO_STAT(size_oat_lookup_table_);
@@ -2749,6 +2832,8 @@ bool OatWriter::CheckOatSize(OutputStream* out, size_t file_offset, size_t relat
DO_STAT(size_oat_class_method_offsets_);
DO_STAT(size_method_bss_mappings_);
DO_STAT(size_type_bss_mappings_);
+ DO_STAT(size_public_type_bss_mappings_);
+ DO_STAT(size_package_type_bss_mappings_);
DO_STAT(size_string_bss_mappings_);
#undef DO_STAT
@@ -2914,12 +2999,27 @@ size_t WriteIndexBssMapping(OutputStream* out,
return mappings_size;
}
+size_t WriteIndexBssMapping(
+ OutputStream* out,
+ const DexFile* dex_file,
+ const BitVector& type_indexes,
+ const SafeMap<TypeReference, size_t, TypeReferenceValueComparator>& bss_entries) {
+ return WriteIndexBssMapping(
+ out,
+ dex_file->NumTypeIds(),
+ sizeof(GcRoot<mirror::Class>),
+ type_indexes,
+ [=](uint32_t index) { return bss_entries.Get({dex_file, dex::TypeIndex(index)}); });
+}
+
size_t OatWriter::WriteIndexBssMappings(OutputStream* out,
size_t file_offset,
size_t relative_offset) {
TimingLogger::ScopedTiming split("WriteMethodBssMappings", timings_);
if (bss_method_entry_references_.empty() &&
bss_type_entry_references_.empty() &&
+ bss_public_type_entry_references_.empty() &&
+ bss_package_type_entry_references_.empty() &&
bss_string_entry_references_.empty()) {
return relative_offset;
}
@@ -2960,14 +3060,8 @@ size_t OatWriter::WriteIndexBssMappings(OutputStream* out,
const BitVector& type_indexes = type_it->second;
DCHECK_EQ(relative_offset, oat_dex_file->type_bss_mapping_offset_);
DCHECK_OFFSET();
- size_t type_mappings_size = WriteIndexBssMapping(
- out,
- dex_file->NumTypeIds(),
- sizeof(GcRoot<mirror::Class>),
- type_indexes,
- [=](uint32_t index) {
- return bss_type_entries_.Get({dex_file, dex::TypeIndex(index)});
- });
+ size_t type_mappings_size =
+ WriteIndexBssMapping(out, dex_file, type_indexes, bss_type_entries_);
if (type_mappings_size == 0u) {
return 0u;
}
@@ -2977,6 +3071,38 @@ size_t OatWriter::WriteIndexBssMappings(OutputStream* out,
DCHECK_EQ(0u, oat_dex_file->type_bss_mapping_offset_);
}
+ auto public_type_it = bss_public_type_entry_references_.find(dex_file);
+ if (public_type_it != bss_public_type_entry_references_.end()) {
+ const BitVector& type_indexes = public_type_it->second;
+ DCHECK_EQ(relative_offset, oat_dex_file->public_type_bss_mapping_offset_);
+ DCHECK_OFFSET();
+ size_t public_type_mappings_size =
+ WriteIndexBssMapping(out, dex_file, type_indexes, bss_public_type_entries_);
+ if (public_type_mappings_size == 0u) {
+ return 0u;
+ }
+ size_public_type_bss_mappings_ += public_type_mappings_size;
+ relative_offset += public_type_mappings_size;
+ } else {
+ DCHECK_EQ(0u, oat_dex_file->public_type_bss_mapping_offset_);
+ }
+
+ auto package_type_it = bss_package_type_entry_references_.find(dex_file);
+ if (package_type_it != bss_package_type_entry_references_.end()) {
+ const BitVector& type_indexes = package_type_it->second;
+ DCHECK_EQ(relative_offset, oat_dex_file->package_type_bss_mapping_offset_);
+ DCHECK_OFFSET();
+ size_t package_type_mappings_size =
+ WriteIndexBssMapping(out, dex_file, type_indexes, bss_package_type_entries_);
+ if (package_type_mappings_size == 0u) {
+ return 0u;
+ }
+ size_package_type_bss_mappings_ += package_type_mappings_size;
+ relative_offset += package_type_mappings_size;
+ } else {
+ DCHECK_EQ(0u, oat_dex_file->package_type_bss_mapping_offset_);
+ }
+
auto string_it = bss_string_entry_references_.find(dex_file);
if (string_it != bss_string_entry_references_.end()) {
const BitVector& string_indexes = string_it->second;
@@ -3918,6 +4044,8 @@ OatWriter::OatDexFile::OatDexFile(const char* dex_file_location,
class_offsets_offset_(0u),
method_bss_mapping_offset_(0u),
type_bss_mapping_offset_(0u),
+ public_type_bss_mapping_offset_(0u),
+ package_type_bss_mapping_offset_(0u),
string_bss_mapping_offset_(0u),
dex_sections_layout_offset_(0u),
class_offsets_() {
@@ -3932,6 +4060,8 @@ size_t OatWriter::OatDexFile::SizeOf() const {
+ sizeof(lookup_table_offset_)
+ sizeof(method_bss_mapping_offset_)
+ sizeof(type_bss_mapping_offset_)
+ + sizeof(public_type_bss_mapping_offset_)
+ + sizeof(package_type_bss_mapping_offset_)
+ sizeof(string_bss_mapping_offset_)
+ sizeof(dex_sections_layout_offset_);
}
@@ -3994,6 +4124,21 @@ bool OatWriter::OatDexFile::Write(OatWriter* oat_writer, OutputStream* out) cons
}
oat_writer->size_oat_dex_file_type_bss_mapping_offset_ += sizeof(type_bss_mapping_offset_);
+ if (!out->WriteFully(&public_type_bss_mapping_offset_, sizeof(public_type_bss_mapping_offset_))) {
+ PLOG(ERROR) << "Failed to write public type bss mapping offset to " << out->GetLocation();
+ return false;
+ }
+ oat_writer->size_oat_dex_file_public_type_bss_mapping_offset_ +=
+ sizeof(public_type_bss_mapping_offset_);
+
+ if (!out->WriteFully(&package_type_bss_mapping_offset_,
+ sizeof(package_type_bss_mapping_offset_))) {
+ PLOG(ERROR) << "Failed to write package type bss mapping offset to " << out->GetLocation();
+ return false;
+ }
+ oat_writer->size_oat_dex_file_package_type_bss_mapping_offset_ +=
+ sizeof(package_type_bss_mapping_offset_);
+
if (!out->WriteFully(&string_bss_mapping_offset_, sizeof(string_bss_mapping_offset_))) {
PLOG(ERROR) << "Failed to write string bss mapping offset to " << out->GetLocation();
return false;
diff --git a/dex2oat/linker/oat_writer.h b/dex2oat/linker/oat_writer.h
index 8d4f574bb3..2fd75719f4 100644
--- a/dex2oat/linker/oat_writer.h
+++ b/dex2oat/linker/oat_writer.h
@@ -441,6 +441,12 @@ class OatWriter {
// Map for recording references to GcRoot<mirror::Class> entries in .bss.
SafeMap<const DexFile*, BitVector> bss_type_entry_references_;
+ // Map for recording references to public GcRoot<mirror::Class> entries in .bss.
+ SafeMap<const DexFile*, BitVector> bss_public_type_entry_references_;
+
+ // Map for recording references to package GcRoot<mirror::Class> entries in .bss.
+ SafeMap<const DexFile*, BitVector> bss_package_type_entry_references_;
+
// Map for recording references to GcRoot<mirror::String> entries in .bss.
SafeMap<const DexFile*, BitVector> bss_string_entry_references_;
@@ -454,6 +460,16 @@ class OatWriter {
// is the target offset for patching, starting at `bss_start_ + bss_roots_offset_`.
SafeMap<TypeReference, size_t, TypeReferenceValueComparator> bss_type_entries_;
+ // Map for allocating public Class entries in .bss. Indexed by TypeReference for the source
+ // type in the dex file with the "type value comparator" for deduplication. The value
+ // is the target offset for patching, starting at `bss_start_ + bss_roots_offset_`.
+ SafeMap<TypeReference, size_t, TypeReferenceValueComparator> bss_public_type_entries_;
+
+ // Map for allocating package Class entries in .bss. Indexed by TypeReference for the source
+ // type in the dex file with the "type value comparator" for deduplication. The value
+ // is the target offset for patching, starting at `bss_start_ + bss_roots_offset_`.
+ SafeMap<TypeReference, size_t, TypeReferenceValueComparator> bss_package_type_entries_;
+
// Map for allocating String entries in .bss. Indexed by StringReference for the source
// string in the dex file with the "string value comparator" for deduplication. The value
// is the target offset for patching, starting at `bss_start_ + bss_roots_offset_`.
@@ -519,6 +535,8 @@ class OatWriter {
uint32_t size_oat_dex_file_dex_layout_sections_alignment_;
uint32_t size_oat_dex_file_method_bss_mapping_offset_;
uint32_t size_oat_dex_file_type_bss_mapping_offset_;
+ uint32_t size_oat_dex_file_public_type_bss_mapping_offset_;
+ uint32_t size_oat_dex_file_package_type_bss_mapping_offset_;
uint32_t size_oat_dex_file_string_bss_mapping_offset_;
uint32_t size_oat_lookup_table_alignment_;
uint32_t size_oat_lookup_table_;
@@ -530,6 +548,8 @@ class OatWriter {
uint32_t size_oat_class_method_offsets_;
uint32_t size_method_bss_mappings_;
uint32_t size_type_bss_mappings_;
+ uint32_t size_public_type_bss_mappings_;
+ uint32_t size_package_type_bss_mappings_;
uint32_t size_string_bss_mappings_;
// The helper for processing relative patches is external so that we can patch across oat files.
diff --git a/runtime/entrypoints/quick/quick_dexcache_entrypoints.cc b/runtime/entrypoints/quick/quick_dexcache_entrypoints.cc
index 838b5b5083..c576640e8f 100644
--- a/runtime/entrypoints/quick/quick_dexcache_entrypoints.cc
+++ b/runtime/entrypoints/quick/quick_dexcache_entrypoints.cc
@@ -85,12 +85,22 @@ static inline void StoreTypeInBss(ArtMethod* outer_method,
DCHECK(dex_file != nullptr);
const OatDexFile* oat_dex_file = dex_file->GetOatDexFile();
if (oat_dex_file != nullptr) {
- size_t bss_offset = IndexBssMappingLookup::GetBssOffset(oat_dex_file->GetTypeBssMapping(),
- type_idx.index_,
- dex_file->NumTypeIds(),
- sizeof(GcRoot<mirror::Class>));
- if (bss_offset != IndexBssMappingLookup::npos) {
- StoreObjectInBss(outer_method, oat_dex_file->GetOatFile(), bss_offset, resolved_type);
+ auto store = [=](const IndexBssMapping* mapping) REQUIRES_SHARED(Locks::mutator_lock_) {
+ size_t bss_offset = IndexBssMappingLookup::GetBssOffset(mapping,
+ type_idx.index_,
+ dex_file->NumTypeIds(),
+ sizeof(GcRoot<mirror::Class>));
+ if (bss_offset != IndexBssMappingLookup::npos) {
+ StoreObjectInBss(outer_method, oat_dex_file->GetOatFile(), bss_offset, resolved_type);
+ }
+ };
+ store(oat_dex_file->GetTypeBssMapping());
+ if (resolved_type->IsPublic()) {
+ store(oat_dex_file->GetPublicTypeBssMapping());
+ }
+ if (resolved_type->IsPublic() ||
+ resolved_type->GetClassLoader() == outer_method->GetClassLoader()) {
+ store(oat_dex_file->GetPackageTypeBssMapping());
}
}
}
@@ -180,7 +190,9 @@ extern "C" mirror::Class* artResolveTypeAndVerifyAccessFromCode(uint32_t type_id
self,
/* can_run_clinit= */ false,
/* verify_access= */ true);
- // Do not StoreTypeInBss(); access check entrypoint is never used together with .bss.
+ if (LIKELY(result != nullptr) && CanReferenceBss(caller_and_outer.outer_method, caller)) {
+ StoreTypeInBss(caller_and_outer.outer_method, dex::TypeIndex(type_idx), result);
+ }
return result.Ptr();
}
diff --git a/runtime/oat.h b/runtime/oat.h
index 960e878080..558c1e597b 100644
--- a/runtime/oat.h
+++ b/runtime/oat.h
@@ -32,8 +32,8 @@ class InstructionSetFeatures;
class PACKED(4) OatHeader {
public:
static constexpr std::array<uint8_t, 4> kOatMagic { { 'o', 'a', 't', '\n' } };
- // Last oat version changed reason: Removal of Thread->tls32_.debug_suspend_count
- static constexpr std::array<uint8_t, 4> kOatVersion { { '1', '8', '5', '\0' } };
+ // Last oat version changed reason: Use .bss for ResoveTypeAndVerifyAccess.
+ static constexpr std::array<uint8_t, 4> kOatVersion { { '1', '8', '6', '\0' } };
static constexpr const char* kDex2OatCmdLineKey = "dex2oat-cmdline";
static constexpr const char* kDebuggableKey = "debuggable";
diff --git a/runtime/oat_file.cc b/runtime/oat_file.cc
index 7a89abedf7..499d90b874 100644
--- a/runtime/oat_file.cc
+++ b/runtime/oat_file.cc
@@ -883,12 +883,18 @@ bool OatFileBase::Setup(int zip_fd,
const IndexBssMapping* method_bss_mapping;
const IndexBssMapping* type_bss_mapping;
+ const IndexBssMapping* public_type_bss_mapping;
+ const IndexBssMapping* package_type_bss_mapping;
const IndexBssMapping* string_bss_mapping;
if (!ReadIndexBssMapping(
this, &oat, i, dex_file_location, "method", &method_bss_mapping, error_msg) ||
!ReadIndexBssMapping(
this, &oat, i, dex_file_location, "type", &type_bss_mapping, error_msg) ||
!ReadIndexBssMapping(
+ this, &oat, i, dex_file_location, "type", &public_type_bss_mapping, error_msg) ||
+ !ReadIndexBssMapping(
+ this, &oat, i, dex_file_location, "type", &package_type_bss_mapping, error_msg) ||
+ !ReadIndexBssMapping(
this, &oat, i, dex_file_location, "string", &string_bss_mapping, error_msg)) {
return false;
}
@@ -903,6 +909,8 @@ bool OatFileBase::Setup(int zip_fd,
lookup_table_data,
method_bss_mapping,
type_bss_mapping,
+ public_type_bss_mapping,
+ package_type_bss_mapping,
string_bss_mapping,
class_offsets_pointer,
dex_layout_sections);
@@ -1869,6 +1877,8 @@ OatDexFile::OatDexFile(const OatFile* oat_file,
const uint8_t* lookup_table_data,
const IndexBssMapping* method_bss_mapping_data,
const IndexBssMapping* type_bss_mapping_data,
+ const IndexBssMapping* public_type_bss_mapping_data,
+ const IndexBssMapping* package_type_bss_mapping_data,
const IndexBssMapping* string_bss_mapping_data,
const uint32_t* oat_class_offsets_pointer,
const DexLayoutSections* dex_layout_sections)
@@ -1880,6 +1890,8 @@ OatDexFile::OatDexFile(const OatFile* oat_file,
lookup_table_data_(lookup_table_data),
method_bss_mapping_(method_bss_mapping_data),
type_bss_mapping_(type_bss_mapping_data),
+ public_type_bss_mapping_(public_type_bss_mapping_data),
+ package_type_bss_mapping_(package_type_bss_mapping_data),
string_bss_mapping_(string_bss_mapping_data),
oat_class_offsets_pointer_(oat_class_offsets_pointer),
lookup_table_(),
diff --git a/runtime/oat_file.h b/runtime/oat_file.h
index 039c3de7c6..9e21b7e9e3 100644
--- a/runtime/oat_file.h
+++ b/runtime/oat_file.h
@@ -522,6 +522,14 @@ class OatDexFile final {
return type_bss_mapping_;
}
+ const IndexBssMapping* GetPublicTypeBssMapping() const {
+ return public_type_bss_mapping_;
+ }
+
+ const IndexBssMapping* GetPackageTypeBssMapping() const {
+ return package_type_bss_mapping_;
+ }
+
const IndexBssMapping* GetStringBssMapping() const {
return string_bss_mapping_;
}
@@ -565,6 +573,8 @@ class OatDexFile final {
const uint8_t* lookup_table_data,
const IndexBssMapping* method_bss_mapping,
const IndexBssMapping* type_bss_mapping,
+ const IndexBssMapping* public_type_bss_mapping,
+ const IndexBssMapping* package_type_bss_mapping,
const IndexBssMapping* string_bss_mapping,
const uint32_t* oat_class_offsets_pointer,
const DexLayoutSections* dex_layout_sections);
@@ -588,6 +598,8 @@ class OatDexFile final {
const uint8_t* const lookup_table_data_ = nullptr;
const IndexBssMapping* const method_bss_mapping_ = nullptr;
const IndexBssMapping* const type_bss_mapping_ = nullptr;
+ const IndexBssMapping* const public_type_bss_mapping_ = nullptr;
+ const IndexBssMapping* const package_type_bss_mapping_ = nullptr;
const IndexBssMapping* const string_bss_mapping_ = nullptr;
const uint32_t* const oat_class_offsets_pointer_ = nullptr;
TypeLookupTable lookup_table_;
diff --git a/test/727-checker-unresolved-class/src/unresolved/UnresolvedPublicClass.java b/test/727-checker-unresolved-class/src/unresolved/UnresolvedPublicClass.java
index 073b03ea38..4864e64eba 100644
--- a/test/727-checker-unresolved-class/src/unresolved/UnresolvedPublicClass.java
+++ b/test/727-checker-unresolved-class/src/unresolved/UnresolvedPublicClass.java
@@ -18,6 +18,8 @@ package unresolved;
import getters.GetUnresolvedPublicClass;
import getters.GetUnresolvedPublicClassFromDifferentDexFile;
+import resolved.PackagePrivateSubclassOfUnresolvedClass;
+import resolved.PublicSubclassOfUnresolvedClass;
import resolved.ResolvedPackagePrivateClass;
import resolved.ResolvedPublicSubclassOfPackagePrivateClass;
@@ -31,6 +33,10 @@ public class UnresolvedPublicClass {
$noinline$testResolvedPublicClass();
$noinline$testResolvedPackagePrivateClass();
+ $noinline$testUnresolvedPublicClass();
+ $noinline$testUnresolvedPackagePrivateClass();
+ $noinline$testUnresolvedPublicClassInSamePackage();
+ $noinline$testUnresolvedPackagePrivateClassInSamePackage();
$noinline$testPublicFieldInResolvedPackagePrivateClass();
$noinline$testPublicFieldInPackagePrivateClassViaResolvedPublicSubclass();
@@ -104,6 +110,45 @@ public class UnresolvedPublicClass {
} catch (IllegalAccessError expected) {}
}
+ /// CHECK-START: void unresolved.UnresolvedPublicClass.$noinline$testUnresolvedPublicClass() builder (after)
+ /// CHECK: LoadClass class_name:resolved.PublicSubclassOfUnresolvedClass needs_access_check:true
+
+ /// CHECK-START-{ARM,ARM64,X86,X86_64}: void unresolved.UnresolvedPublicClass.$noinline$testUnresolvedPublicClass() builder (after)
+ /// CHECK: LoadClass load_kind:BssEntryPublic class_name:resolved.PublicSubclassOfUnresolvedClass
+ static void $noinline$testUnresolvedPublicClass() {
+ Class<?> c = PublicSubclassOfUnresolvedClass.class;
+ }
+
+ /// CHECK-START: void unresolved.UnresolvedPublicClass.$noinline$testUnresolvedPackagePrivateClass() builder (after)
+ /// CHECK: LoadClass class_name:resolved.PackagePrivateSubclassOfUnresolvedClass needs_access_check:true
+
+ /// CHECK-START-{ARM,ARM64,X86,X86_64}: void unresolved.UnresolvedPublicClass.$noinline$testUnresolvedPackagePrivateClass() builder (after)
+ /// CHECK: LoadClass load_kind:BssEntryPublic class_name:resolved.PackagePrivateSubclassOfUnresolvedClass
+ static void $noinline$testUnresolvedPackagePrivateClass() {
+ try {
+ Class<?> c = PackagePrivateSubclassOfUnresolvedClass.class;
+ throw new Error("Unreachable");
+ } catch (IllegalAccessError expected) {}
+ }
+
+ /// CHECK-START: void unresolved.UnresolvedPublicClass.$noinline$testUnresolvedPublicClassInSamePackage() builder (after)
+ /// CHECK: LoadClass class_name:unresolved.UnresolvedPublicClazz needs_access_check:true
+
+ /// CHECK-START-{ARM,ARM64,X86,X86_64}: void unresolved.UnresolvedPublicClass.$noinline$testUnresolvedPublicClassInSamePackage() builder (after)
+ /// CHECK: LoadClass load_kind:BssEntryPackage class_name:unresolved.UnresolvedPublicClazz
+ static void $noinline$testUnresolvedPublicClassInSamePackage() {
+ Class<?> c = UnresolvedPublicClazz.class;
+ }
+
+ /// CHECK-START: void unresolved.UnresolvedPublicClass.$noinline$testUnresolvedPackagePrivateClassInSamePackage() builder (after)
+ /// CHECK: LoadClass class_name:unresolved.UnresolvedPackagePrivateClass needs_access_check:true
+
+ /// CHECK-START-{ARM,ARM64,X86,X86_64}: void unresolved.UnresolvedPublicClass.$noinline$testUnresolvedPackagePrivateClassInSamePackage() builder (after)
+ /// CHECK: LoadClass load_kind:BssEntryPackage class_name:unresolved.UnresolvedPackagePrivateClass
+ static void $noinline$testUnresolvedPackagePrivateClassInSamePackage() {
+ Class<?> c = UnresolvedPackagePrivateClass.class;
+ }
+
/// CHECK-START: void unresolved.UnresolvedPublicClass.$noinline$testPublicFieldInResolvedPackagePrivateClass() builder (after)
/// CHECK: UnresolvedStaticFieldSet