summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Vladimir Marko <vmarko@google.com> 2024-04-12 11:00:19 +0000
committer VladimĂ­r Marko <vmarko@google.com> 2024-05-07 18:06:47 +0000
commit488413f47e7552d067edf9cfd5ceda321fc12f88 (patch)
tree7bc33df1846aa6838babe2f1f5b6c60137a7eb71
parenta463b165408222e3ef6a2052ef31b1560b3afea6 (diff)
Faster `HLoadClass` for app image classes.
Add app image relocations for classes in the app image, similar to the existing relocations for boot image. This new load kind lets the compiled code avoid the null check and slow path. Test: m test-art-host-gtest Test: testrunner.py --host --optimizing --speed-profile Test: run-test.sh Test: testrunner.py --target --optimizing --speed-profile Bug: 38313278 Change-Id: Iffd76fe9ac6b95c37c2781fd6257e1d5cd0790d0
-rw-r--r--compiler/linker/linker_patch.h13
-rw-r--r--compiler/optimizing/code_generator_arm64.cc27
-rw-r--r--compiler/optimizing/code_generator_arm64.h10
-rw-r--r--compiler/optimizing/code_generator_arm_vixl.cc20
-rw-r--r--compiler/optimizing/code_generator_arm_vixl.h3
-rw-r--r--compiler/optimizing/code_generator_riscv64.cc23
-rw-r--r--compiler/optimizing/code_generator_riscv64.h5
-rw-r--r--compiler/optimizing/code_generator_x86.cc22
-rw-r--r--compiler/optimizing/code_generator_x86.h3
-rw-r--r--compiler/optimizing/code_generator_x86_64.cc20
-rw-r--r--compiler/optimizing/code_generator_x86_64.h3
-rw-r--r--compiler/optimizing/nodes.h7
-rw-r--r--compiler/optimizing/sharpening.cc2
-rw-r--r--dex2oat/dex2oat.cc1
-rw-r--r--dex2oat/linker/arm64/relative_patcher_arm64.cc2
-rw-r--r--dex2oat/linker/elf_writer.h1
-rw-r--r--dex2oat/linker/elf_writer_quick.cc3
-rw-r--r--dex2oat/linker/image_test.h1
-rw-r--r--dex2oat/linker/image_writer.h9
-rw-r--r--dex2oat/linker/oat_writer.cc52
-rw-r--r--dex2oat/linker/oat_writer.h12
-rw-r--r--dex2oat/linker/oat_writer_test.cc1
-rw-r--r--libelffile/elf/elf_builder.h15
-rw-r--r--oatdump/oatdump.cc1
-rw-r--r--runtime/mirror/dex_cache.h2
-rw-r--r--runtime/oat/oat.h4
-rw-r--r--runtime/oat/oat_file.cc51
-rw-r--r--runtime/oat/oat_file.h23
-rw-r--r--runtime/oat/oat_file_manager.cc2
-rw-r--r--test/732-checker-app-image/src-ex/Secondary.java2
-rw-r--r--test/732-checker-app-image/src/Main.java12
31 files changed, 323 insertions, 29 deletions
diff --git a/compiler/linker/linker_patch.h b/compiler/linker/linker_patch.h
index 19ee0e640c..b061e042f0 100644
--- a/compiler/linker/linker_patch.h
+++ b/compiler/linker/linker_patch.h
@@ -54,6 +54,7 @@ class LinkerPatch {
kJniEntrypointRelative,
kCallRelative,
kTypeRelative,
+ kTypeAppImageRelRo,
kTypeBssEntry,
kPublicTypeBssEntry,
kPackageTypeBssEntry,
@@ -130,6 +131,16 @@ class LinkerPatch {
return patch;
}
+ static LinkerPatch TypeAppImageRelRoPatch(size_t literal_offset,
+ const DexFile* target_dex_file,
+ uint32_t pc_insn_offset,
+ uint32_t target_type_idx) {
+ LinkerPatch patch(literal_offset, Type::kTypeAppImageRelRo, target_dex_file);
+ patch.type_idx_ = target_type_idx;
+ patch.pc_insn_offset_ = pc_insn_offset;
+ return patch;
+ }
+
static LinkerPatch TypeBssEntryPatch(size_t literal_offset,
const DexFile* target_dex_file,
uint32_t pc_insn_offset,
@@ -241,6 +252,7 @@ class LinkerPatch {
TypeReference TargetType() const {
DCHECK(patch_type_ == Type::kTypeRelative ||
+ patch_type_ == Type::kTypeAppImageRelRo ||
patch_type_ == Type::kTypeBssEntry ||
patch_type_ == Type::kPublicTypeBssEntry ||
patch_type_ == Type::kPackageTypeBssEntry);
@@ -265,6 +277,7 @@ class LinkerPatch {
patch_type_ == Type::kMethodBssEntry ||
patch_type_ == Type::kJniEntrypointRelative ||
patch_type_ == Type::kTypeRelative ||
+ patch_type_ == Type::kTypeAppImageRelRo ||
patch_type_ == Type::kTypeBssEntry ||
patch_type_ == Type::kPublicTypeBssEntry ||
patch_type_ == Type::kPackageTypeBssEntry ||
diff --git a/compiler/optimizing/code_generator_arm64.cc b/compiler/optimizing/code_generator_arm64.cc
index cfa28eda25..988809ee48 100644
--- a/compiler/optimizing/code_generator_arm64.cc
+++ b/compiler/optimizing/code_generator_arm64.cc
@@ -1011,6 +1011,7 @@ CodeGeneratorARM64::CodeGeneratorARM64(HGraph* graph,
boot_image_method_patches_(graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)),
method_bss_entry_patches_(graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)),
boot_image_type_patches_(graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)),
+ app_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)),
@@ -5155,6 +5156,13 @@ vixl::aarch64::Label* CodeGeneratorARM64::NewBootImageTypePatch(
return NewPcRelativePatch(&dex_file, type_index.index_, adrp_label, &boot_image_type_patches_);
}
+vixl::aarch64::Label* CodeGeneratorARM64::NewAppImageTypePatch(
+ const DexFile& dex_file,
+ dex::TypeIndex type_index,
+ vixl::aarch64::Label* adrp_label) {
+ return NewPcRelativePatch(&dex_file, type_index.index_, adrp_label, &app_image_type_patches_);
+}
+
vixl::aarch64::Label* CodeGeneratorARM64::NewBssEntryTypePatch(
HLoadClass* load_class,
vixl::aarch64::Label* adrp_label) {
@@ -5365,6 +5373,7 @@ void CodeGeneratorARM64::EmitLinkerPatches(ArenaVector<linker::LinkerPatch>* lin
boot_image_method_patches_.size() +
method_bss_entry_patches_.size() +
boot_image_type_patches_.size() +
+ app_image_type_patches_.size() +
type_bss_entry_patches_.size() +
public_type_bss_entry_patches_.size() +
package_type_bss_entry_patches_.size() +
@@ -5387,12 +5396,15 @@ void CodeGeneratorARM64::EmitLinkerPatches(ArenaVector<linker::LinkerPatch>* lin
DCHECK(boot_image_type_patches_.empty());
DCHECK(boot_image_string_patches_.empty());
}
+ DCHECK_IMPLIES(!GetCompilerOptions().IsAppImage(), app_image_type_patches_.empty());
if (GetCompilerOptions().IsBootImage()) {
EmitPcRelativeLinkerPatches<NoDexFileAdapter<linker::LinkerPatch::IntrinsicReferencePatch>>(
boot_image_other_patches_, linker_patches);
} else {
EmitPcRelativeLinkerPatches<NoDexFileAdapter<linker::LinkerPatch::BootImageRelRoPatch>>(
boot_image_other_patches_, linker_patches);
+ EmitPcRelativeLinkerPatches<linker::LinkerPatch::TypeAppImageRelRoPatch>(
+ app_image_type_patches_, linker_patches);
}
EmitPcRelativeLinkerPatches<linker::LinkerPatch::MethodBssEntryPatch>(
method_bss_entry_patches_, linker_patches);
@@ -5504,6 +5516,7 @@ HLoadClass::LoadKind CodeGeneratorARM64::GetSupportedLoadClassKind(
break;
case HLoadClass::LoadKind::kBootImageLinkTimePcRelative:
case HLoadClass::LoadKind::kBootImageRelRo:
+ case HLoadClass::LoadKind::kAppImageRelRo:
case HLoadClass::LoadKind::kBssEntry:
case HLoadClass::LoadKind::kBssEntryPublic:
case HLoadClass::LoadKind::kBssEntryPackage:
@@ -5613,6 +5626,20 @@ void InstructionCodeGeneratorARM64::VisitLoadClass(HLoadClass* cls) NO_THREAD_SA
codegen_->LoadBootImageRelRoEntry(out.W(), boot_image_offset);
break;
}
+ case HLoadClass::LoadKind::kAppImageRelRo: {
+ DCHECK(codegen_->GetCompilerOptions().IsAppImage());
+ DCHECK_EQ(read_barrier_option, kWithoutReadBarrier);
+ // Add ADRP with its PC-relative type patch.
+ const DexFile& dex_file = cls->GetDexFile();
+ dex::TypeIndex type_index = cls->GetTypeIndex();
+ vixl::aarch64::Label* adrp_label = codegen_->NewAppImageTypePatch(dex_file, type_index);
+ codegen_->EmitAdrpPlaceholder(adrp_label, out.X());
+ // Add LDR with its PC-relative type patch.
+ vixl::aarch64::Label* ldr_label =
+ codegen_->NewAppImageTypePatch(dex_file, type_index, adrp_label);
+ codegen_->EmitLdrOffsetPlaceholder(ldr_label, out.W(), out.X());
+ break;
+ }
case HLoadClass::LoadKind::kBssEntry:
case HLoadClass::LoadKind::kBssEntryPublic:
case HLoadClass::LoadKind::kBssEntryPackage: {
diff --git a/compiler/optimizing/code_generator_arm64.h b/compiler/optimizing/code_generator_arm64.h
index 32a69a9df7..78049c5675 100644
--- a/compiler/optimizing/code_generator_arm64.h
+++ b/compiler/optimizing/code_generator_arm64.h
@@ -817,6 +817,14 @@ class CodeGeneratorARM64 : public CodeGenerator {
dex::TypeIndex type_index,
vixl::aarch64::Label* adrp_label = nullptr);
+ // Add a new app image type patch for an instruction and return the label
+ // to be bound before the instruction. The instruction will be either the
+ // ADRP (pass `adrp_label = null`) or the LDR (pass `adrp_label` pointing
+ // to the associated ADRP patch label).
+ vixl::aarch64::Label* NewAppImageTypePatch(const DexFile& dex_file,
+ dex::TypeIndex type_index,
+ vixl::aarch64::Label* adrp_label = nullptr);
+
// Add a new .bss entry type patch for an instruction and return the label
// to be bound before the instruction. The instruction will be either the
// ADRP (pass `adrp_label = null`) or the ADD (pass `adrp_label` pointing
@@ -1150,6 +1158,8 @@ class CodeGeneratorARM64 : public CodeGenerator {
ArenaDeque<PcRelativePatchInfo> method_bss_entry_patches_;
// PC-relative type patch info for kBootImageLinkTimePcRelative.
ArenaDeque<PcRelativePatchInfo> boot_image_type_patches_;
+ // PC-relative type patch info for kAppImageRelRo.
+ ArenaDeque<PcRelativePatchInfo> app_image_type_patches_;
// PC-relative type patch info for kBssEntry.
ArenaDeque<PcRelativePatchInfo> type_bss_entry_patches_;
// PC-relative public type patch info for kBssEntryPublic.
diff --git a/compiler/optimizing/code_generator_arm_vixl.cc b/compiler/optimizing/code_generator_arm_vixl.cc
index a7cc5a6d12..7c1a9b21f2 100644
--- a/compiler/optimizing/code_generator_arm_vixl.cc
+++ b/compiler/optimizing/code_generator_arm_vixl.cc
@@ -1946,6 +1946,7 @@ CodeGeneratorARMVIXL::CodeGeneratorARMVIXL(HGraph* graph,
boot_image_method_patches_(graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)),
method_bss_entry_patches_(graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)),
boot_image_type_patches_(graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)),
+ app_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)),
@@ -7657,6 +7658,7 @@ HLoadClass::LoadKind CodeGeneratorARMVIXL::GetSupportedLoadClassKind(
break;
case HLoadClass::LoadKind::kBootImageLinkTimePcRelative:
case HLoadClass::LoadKind::kBootImageRelRo:
+ case HLoadClass::LoadKind::kAppImageRelRo:
case HLoadClass::LoadKind::kBssEntry:
case HLoadClass::LoadKind::kBssEntryPublic:
case HLoadClass::LoadKind::kBssEntryPackage:
@@ -7760,6 +7762,15 @@ void InstructionCodeGeneratorARMVIXL::VisitLoadClass(HLoadClass* cls) NO_THREAD_
codegen_->LoadBootImageRelRoEntry(out, boot_image_offset);
break;
}
+ case HLoadClass::LoadKind::kAppImageRelRo: {
+ DCHECK(codegen_->GetCompilerOptions().IsAppImage());
+ DCHECK_EQ(read_barrier_option, kWithoutReadBarrier);
+ CodeGeneratorARMVIXL::PcRelativePatchInfo* labels =
+ codegen_->NewAppImageTypePatch(cls->GetDexFile(), cls->GetTypeIndex());
+ codegen_->EmitMovwMovtPlaceholder(labels, out);
+ __ Ldr(out, MemOperand(out, /*offset=*/ 0));
+ break;
+ }
case HLoadClass::LoadKind::kBssEntry:
case HLoadClass::LoadKind::kBssEntryPublic:
case HLoadClass::LoadKind::kBssEntryPackage: {
@@ -9691,6 +9702,11 @@ CodeGeneratorARMVIXL::PcRelativePatchInfo* CodeGeneratorARMVIXL::NewBootImageTyp
return NewPcRelativePatch(&dex_file, type_index.index_, &boot_image_type_patches_);
}
+CodeGeneratorARMVIXL::PcRelativePatchInfo* CodeGeneratorARMVIXL::NewAppImageTypePatch(
+ const DexFile& dex_file, dex::TypeIndex type_index) {
+ return NewPcRelativePatch(&dex_file, type_index.index_, &app_image_type_patches_);
+}
+
CodeGeneratorARMVIXL::PcRelativePatchInfo* CodeGeneratorARMVIXL::NewTypeBssEntryPatch(
HLoadClass* load_class) {
const DexFile& dex_file = load_class->GetDexFile();
@@ -9877,6 +9893,7 @@ void CodeGeneratorARMVIXL::EmitLinkerPatches(ArenaVector<linker::LinkerPatch>* l
/* MOVW+MOVT for each entry */ 2u * boot_image_method_patches_.size() +
/* 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 * app_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() +
@@ -9898,12 +9915,15 @@ void CodeGeneratorARMVIXL::EmitLinkerPatches(ArenaVector<linker::LinkerPatch>* l
DCHECK(boot_image_type_patches_.empty());
DCHECK(boot_image_string_patches_.empty());
}
+ DCHECK_IMPLIES(!GetCompilerOptions().IsAppImage(), app_image_type_patches_.empty());
if (GetCompilerOptions().IsBootImage()) {
EmitPcRelativeLinkerPatches<NoDexFileAdapter<linker::LinkerPatch::IntrinsicReferencePatch>>(
boot_image_other_patches_, linker_patches);
} else {
EmitPcRelativeLinkerPatches<NoDexFileAdapter<linker::LinkerPatch::BootImageRelRoPatch>>(
boot_image_other_patches_, linker_patches);
+ EmitPcRelativeLinkerPatches<linker::LinkerPatch::TypeAppImageRelRoPatch>(
+ app_image_type_patches_, linker_patches);
}
EmitPcRelativeLinkerPatches<linker::LinkerPatch::MethodBssEntryPatch>(
method_bss_entry_patches_, linker_patches);
diff --git a/compiler/optimizing/code_generator_arm_vixl.h b/compiler/optimizing/code_generator_arm_vixl.h
index a62097d08f..51bee1cd77 100644
--- a/compiler/optimizing/code_generator_arm_vixl.h
+++ b/compiler/optimizing/code_generator_arm_vixl.h
@@ -709,6 +709,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* NewAppImageTypePatch(const DexFile& dex_file, dex::TypeIndex type_index);
PcRelativePatchInfo* NewTypeBssEntryPatch(HLoadClass* load_class);
PcRelativePatchInfo* NewBootImageStringPatch(const DexFile& dex_file,
dex::StringIndex string_index);
@@ -1029,6 +1030,8 @@ class CodeGeneratorARMVIXL : public CodeGenerator {
ArenaDeque<PcRelativePatchInfo> method_bss_entry_patches_;
// PC-relative type patch info for kBootImageLinkTimePcRelative.
ArenaDeque<PcRelativePatchInfo> boot_image_type_patches_;
+ // PC-relative type patch info for kAppImageRelRo.
+ ArenaDeque<PcRelativePatchInfo> app_image_type_patches_;
// PC-relative type patch info for kBssEntry.
ArenaDeque<PcRelativePatchInfo> type_bss_entry_patches_;
// PC-relative public type patch info for kBssEntryPublic.
diff --git a/compiler/optimizing/code_generator_riscv64.cc b/compiler/optimizing/code_generator_riscv64.cc
index 29594e94c1..9b499a08a2 100644
--- a/compiler/optimizing/code_generator_riscv64.cc
+++ b/compiler/optimizing/code_generator_riscv64.cc
@@ -4373,6 +4373,18 @@ void InstructionCodeGeneratorRISCV64::VisitLoadClass(HLoadClass* instruction)
codegen_->LoadBootImageRelRoEntry(out, boot_image_offset);
break;
}
+ case HLoadClass::LoadKind::kAppImageRelRo: {
+ DCHECK(codegen_->GetCompilerOptions().IsAppImage());
+ DCHECK_EQ(read_barrier_option, kWithoutReadBarrier);
+ CodeGeneratorRISCV64::PcRelativePatchInfo* info_high =
+ codegen_->NewAppImageTypePatch(instruction->GetDexFile(), instruction->GetTypeIndex());
+ codegen_->EmitPcRelativeAuipcPlaceholder(info_high, out);
+ CodeGeneratorRISCV64::PcRelativePatchInfo* info_low =
+ codegen_->NewAppImageTypePatch(
+ instruction->GetDexFile(), instruction->GetTypeIndex(), info_high);
+ codegen_->EmitPcRelativeLwuPlaceholder(info_low, out, out);
+ break;
+ }
case HLoadClass::LoadKind::kBssEntry:
case HLoadClass::LoadKind::kBssEntryPublic:
case HLoadClass::LoadKind::kBssEntryPackage: {
@@ -5820,6 +5832,7 @@ CodeGeneratorRISCV64::CodeGeneratorRISCV64(HGraph* graph,
boot_image_method_patches_(graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)),
method_bss_entry_patches_(graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)),
boot_image_type_patches_(graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)),
+ app_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)),
@@ -6428,6 +6441,7 @@ HLoadClass::LoadKind CodeGeneratorRISCV64::GetSupportedLoadClassKind(
break;
case HLoadClass::LoadKind::kBootImageLinkTimePcRelative:
case HLoadClass::LoadKind::kBootImageRelRo:
+ case HLoadClass::LoadKind::kAppImageRelRo:
case HLoadClass::LoadKind::kBssEntry:
case HLoadClass::LoadKind::kBssEntryPublic:
case HLoadClass::LoadKind::kBssEntryPackage:
@@ -6479,6 +6493,11 @@ CodeGeneratorRISCV64::PcRelativePatchInfo* CodeGeneratorRISCV64::NewBootImageTyp
return NewPcRelativePatch(&dex_file, type_index.index_, info_high, &boot_image_type_patches_);
}
+CodeGeneratorRISCV64::PcRelativePatchInfo* CodeGeneratorRISCV64::NewAppImageTypePatch(
+ const DexFile& dex_file, dex::TypeIndex type_index, const PcRelativePatchInfo* info_high) {
+ return NewPcRelativePatch(&dex_file, type_index.index_, info_high, &app_image_type_patches_);
+}
+
CodeGeneratorRISCV64::PcRelativePatchInfo* CodeGeneratorRISCV64::NewBootImageJniEntrypointPatch(
MethodReference target_method, const PcRelativePatchInfo* info_high) {
return NewPcRelativePatch(
@@ -6642,6 +6661,7 @@ void CodeGeneratorRISCV64::EmitLinkerPatches(ArenaVector<linker::LinkerPatch>* l
boot_image_method_patches_.size() +
method_bss_entry_patches_.size() +
boot_image_type_patches_.size() +
+ app_image_type_patches_.size() +
type_bss_entry_patches_.size() +
public_type_bss_entry_patches_.size() +
package_type_bss_entry_patches_.size() +
@@ -6662,12 +6682,15 @@ void CodeGeneratorRISCV64::EmitLinkerPatches(ArenaVector<linker::LinkerPatch>* l
DCHECK(boot_image_type_patches_.empty());
DCHECK(boot_image_string_patches_.empty());
}
+ DCHECK_IMPLIES(!GetCompilerOptions().IsAppImage(), app_image_type_patches_.empty());
if (GetCompilerOptions().IsBootImage()) {
EmitPcRelativeLinkerPatches<NoDexFileAdapter<linker::LinkerPatch::IntrinsicReferencePatch>>(
boot_image_other_patches_, linker_patches);
} else {
EmitPcRelativeLinkerPatches<NoDexFileAdapter<linker::LinkerPatch::BootImageRelRoPatch>>(
boot_image_other_patches_, linker_patches);
+ EmitPcRelativeLinkerPatches<linker::LinkerPatch::TypeAppImageRelRoPatch>(
+ app_image_type_patches_, linker_patches);
}
EmitPcRelativeLinkerPatches<linker::LinkerPatch::MethodBssEntryPatch>(
method_bss_entry_patches_, linker_patches);
diff --git a/compiler/optimizing/code_generator_riscv64.h b/compiler/optimizing/code_generator_riscv64.h
index 7f4f352341..227882e7b8 100644
--- a/compiler/optimizing/code_generator_riscv64.h
+++ b/compiler/optimizing/code_generator_riscv64.h
@@ -589,6 +589,9 @@ class CodeGeneratorRISCV64 : public CodeGenerator {
PcRelativePatchInfo* NewBootImageTypePatch(const DexFile& dex_file,
dex::TypeIndex type_index,
const PcRelativePatchInfo* info_high = nullptr);
+ PcRelativePatchInfo* NewAppImageTypePatch(const DexFile& dex_file,
+ dex::TypeIndex type_index,
+ const PcRelativePatchInfo* info_high = nullptr);
PcRelativePatchInfo* NewTypeBssEntryPatch(HLoadClass* load_class,
const PcRelativePatchInfo* info_high = nullptr);
PcRelativePatchInfo* NewBootImageStringPatch(const DexFile& dex_file,
@@ -819,6 +822,8 @@ class CodeGeneratorRISCV64 : public CodeGenerator {
ArenaDeque<PcRelativePatchInfo> method_bss_entry_patches_;
// PC-relative type patch info for kBootImageLinkTimePcRelative.
ArenaDeque<PcRelativePatchInfo> boot_image_type_patches_;
+ // PC-relative type patch info for kAppImageRelRo.
+ ArenaDeque<PcRelativePatchInfo> app_image_type_patches_;
// PC-relative type patch info for kBssEntry.
ArenaDeque<PcRelativePatchInfo> type_bss_entry_patches_;
// PC-relative public type patch info for kBssEntryPublic.
diff --git a/compiler/optimizing/code_generator_x86.cc b/compiler/optimizing/code_generator_x86.cc
index 5ad818dd53..4329e40efc 100644
--- a/compiler/optimizing/code_generator_x86.cc
+++ b/compiler/optimizing/code_generator_x86.cc
@@ -1173,6 +1173,7 @@ CodeGeneratorX86::CodeGeneratorX86(HGraph* graph,
boot_image_method_patches_(graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)),
method_bss_entry_patches_(graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)),
boot_image_type_patches_(graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)),
+ app_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)),
@@ -5715,6 +5716,14 @@ void CodeGeneratorX86::RecordBootImageTypePatch(HLoadClass* load_class) {
__ Bind(&boot_image_type_patches_.back().label);
}
+void CodeGeneratorX86::RecordAppImageTypePatch(HLoadClass* load_class) {
+ HX86ComputeBaseMethodAddress* method_address =
+ load_class->InputAt(0)->AsX86ComputeBaseMethodAddress();
+ app_image_type_patches_.emplace_back(
+ method_address, &load_class->GetDexFile(), load_class->GetTypeIndex().index_);
+ __ Bind(&app_image_type_patches_.back().label);
+}
+
Label* CodeGeneratorX86::NewTypeBssEntryPatch(HLoadClass* load_class) {
HX86ComputeBaseMethodAddress* method_address =
load_class->InputAt(0)->AsX86ComputeBaseMethodAddress();
@@ -5844,6 +5853,7 @@ void CodeGeneratorX86::EmitLinkerPatches(ArenaVector<linker::LinkerPatch>* linke
boot_image_method_patches_.size() +
method_bss_entry_patches_.size() +
boot_image_type_patches_.size() +
+ app_image_type_patches_.size() +
type_bss_entry_patches_.size() +
public_type_bss_entry_patches_.size() +
package_type_bss_entry_patches_.size() +
@@ -5864,12 +5874,15 @@ void CodeGeneratorX86::EmitLinkerPatches(ArenaVector<linker::LinkerPatch>* linke
DCHECK(boot_image_type_patches_.empty());
DCHECK(boot_image_string_patches_.empty());
}
+ DCHECK_IMPLIES(!GetCompilerOptions().IsAppImage(), app_image_type_patches_.empty());
if (GetCompilerOptions().IsBootImage()) {
EmitPcRelativeLinkerPatches<NoDexFileAdapter<linker::LinkerPatch::IntrinsicReferencePatch>>(
boot_image_other_patches_, linker_patches);
} else {
EmitPcRelativeLinkerPatches<NoDexFileAdapter<linker::LinkerPatch::BootImageRelRoPatch>>(
boot_image_other_patches_, linker_patches);
+ EmitPcRelativeLinkerPatches<linker::LinkerPatch::TypeAppImageRelRoPatch>(
+ app_image_type_patches_, linker_patches);
}
EmitPcRelativeLinkerPatches<linker::LinkerPatch::MethodBssEntryPatch>(
method_bss_entry_patches_, linker_patches);
@@ -7283,6 +7296,7 @@ HLoadClass::LoadKind CodeGeneratorX86::GetSupportedLoadClassKind(
break;
case HLoadClass::LoadKind::kBootImageLinkTimePcRelative:
case HLoadClass::LoadKind::kBootImageRelRo:
+ case HLoadClass::LoadKind::kAppImageRelRo:
case HLoadClass::LoadKind::kBssEntry:
case HLoadClass::LoadKind::kBssEntryPublic:
case HLoadClass::LoadKind::kBssEntryPackage:
@@ -7396,6 +7410,14 @@ void InstructionCodeGeneratorX86::VisitLoadClass(HLoadClass* cls) NO_THREAD_SAFE
CodeGenerator::GetBootImageOffset(cls));
break;
}
+ case HLoadClass::LoadKind::kAppImageRelRo: {
+ DCHECK(codegen_->GetCompilerOptions().IsAppImage());
+ DCHECK_EQ(read_barrier_option, kWithoutReadBarrier);
+ Register method_address = locations->InAt(0).AsRegister<Register>();
+ __ movl(out, Address(method_address, CodeGeneratorX86::kPlaceholder32BitOffset));
+ codegen_->RecordAppImageTypePatch(cls);
+ break;
+ }
case HLoadClass::LoadKind::kBssEntry:
case HLoadClass::LoadKind::kBssEntryPublic:
case HLoadClass::LoadKind::kBssEntryPackage: {
diff --git a/compiler/optimizing/code_generator_x86.h b/compiler/optimizing/code_generator_x86.h
index ee87947ca0..93f8e6ed9b 100644
--- a/compiler/optimizing/code_generator_x86.h
+++ b/compiler/optimizing/code_generator_x86.h
@@ -539,6 +539,7 @@ class CodeGeneratorX86 : public CodeGenerator {
void RecordBootImageMethodPatch(HInvoke* invoke);
void RecordMethodBssEntryPatch(HInvoke* invoke);
void RecordBootImageTypePatch(HLoadClass* load_class);
+ void RecordAppImageTypePatch(HLoadClass* load_class);
Label* NewTypeBssEntryPatch(HLoadClass* load_class);
void RecordBootImageStringPatch(HLoadString* load_string);
Label* NewStringBssEntryPatch(HLoadString* load_string);
@@ -775,6 +776,8 @@ class CodeGeneratorX86 : public CodeGenerator {
ArenaDeque<X86PcRelativePatchInfo> method_bss_entry_patches_;
// PC-relative type patch info for kBootImageLinkTimePcRelative.
ArenaDeque<X86PcRelativePatchInfo> boot_image_type_patches_;
+ // PC-relative type patch info for kAppImageRelRo.
+ ArenaDeque<X86PcRelativePatchInfo> app_image_type_patches_;
// PC-relative type patch info for kBssEntry.
ArenaDeque<X86PcRelativePatchInfo> type_bss_entry_patches_;
// PC-relative public type patch info for kBssEntryPublic.
diff --git a/compiler/optimizing/code_generator_x86_64.cc b/compiler/optimizing/code_generator_x86_64.cc
index 4855b086ae..5b4f1b8b25 100644
--- a/compiler/optimizing/code_generator_x86_64.cc
+++ b/compiler/optimizing/code_generator_x86_64.cc
@@ -1328,6 +1328,12 @@ void CodeGeneratorX86_64::RecordBootImageTypePatch(const DexFile& dex_file,
__ Bind(&boot_image_type_patches_.back().label);
}
+void CodeGeneratorX86_64::RecordAppImageTypePatch(const DexFile& dex_file,
+ dex::TypeIndex type_index) {
+ app_image_type_patches_.emplace_back(&dex_file, type_index.index_);
+ __ Bind(&app_image_type_patches_.back().label);
+}
+
Label* CodeGeneratorX86_64::NewTypeBssEntryPatch(HLoadClass* load_class) {
ArenaDeque<PatchInfo<Label>>* patches = nullptr;
switch (load_class->GetLoadKind()) {
@@ -1448,6 +1454,7 @@ void CodeGeneratorX86_64::EmitLinkerPatches(ArenaVector<linker::LinkerPatch>* li
boot_image_method_patches_.size() +
method_bss_entry_patches_.size() +
boot_image_type_patches_.size() +
+ app_image_type_patches_.size() +
type_bss_entry_patches_.size() +
public_type_bss_entry_patches_.size() +
package_type_bss_entry_patches_.size() +
@@ -1469,12 +1476,15 @@ void CodeGeneratorX86_64::EmitLinkerPatches(ArenaVector<linker::LinkerPatch>* li
DCHECK(boot_image_type_patches_.empty());
DCHECK(boot_image_string_patches_.empty());
}
+ DCHECK_IMPLIES(!GetCompilerOptions().IsAppImage(), app_image_type_patches_.empty());
if (GetCompilerOptions().IsBootImage()) {
EmitPcRelativeLinkerPatches<NoDexFileAdapter<linker::LinkerPatch::IntrinsicReferencePatch>>(
boot_image_other_patches_, linker_patches);
} else {
EmitPcRelativeLinkerPatches<NoDexFileAdapter<linker::LinkerPatch::BootImageRelRoPatch>>(
boot_image_other_patches_, linker_patches);
+ EmitPcRelativeLinkerPatches<linker::LinkerPatch::TypeAppImageRelRoPatch>(
+ app_image_type_patches_, linker_patches);
}
EmitPcRelativeLinkerPatches<linker::LinkerPatch::MethodBssEntryPatch>(
method_bss_entry_patches_, linker_patches);
@@ -1607,6 +1617,7 @@ CodeGeneratorX86_64::CodeGeneratorX86_64(HGraph* graph,
boot_image_method_patches_(graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)),
method_bss_entry_patches_(graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)),
boot_image_type_patches_(graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)),
+ app_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)),
@@ -6620,6 +6631,7 @@ HLoadClass::LoadKind CodeGeneratorX86_64::GetSupportedLoadClassKind(
break;
case HLoadClass::LoadKind::kBootImageLinkTimePcRelative:
case HLoadClass::LoadKind::kBootImageRelRo:
+ case HLoadClass::LoadKind::kAppImageRelRo:
case HLoadClass::LoadKind::kBssEntry:
case HLoadClass::LoadKind::kBssEntryPublic:
case HLoadClass::LoadKind::kBssEntryPackage:
@@ -6732,6 +6744,14 @@ void InstructionCodeGeneratorX86_64::VisitLoadClass(HLoadClass* cls) NO_THREAD_S
codegen_->RecordBootImageRelRoPatch(CodeGenerator::GetBootImageOffset(cls));
break;
}
+ case HLoadClass::LoadKind::kAppImageRelRo: {
+ DCHECK(codegen_->GetCompilerOptions().IsAppImage());
+ DCHECK_EQ(read_barrier_option, kWithoutReadBarrier);
+ __ movl(out,
+ Address::Absolute(CodeGeneratorX86_64::kPlaceholder32BitOffset, /* no_rip= */ false));
+ codegen_->RecordAppImageTypePatch(cls->GetDexFile(), cls->GetTypeIndex());
+ break;
+ }
case HLoadClass::LoadKind::kBssEntry:
case HLoadClass::LoadKind::kBssEntryPublic:
case HLoadClass::LoadKind::kBssEntryPackage: {
diff --git a/compiler/optimizing/code_generator_x86_64.h b/compiler/optimizing/code_generator_x86_64.h
index b8e2456381..7a5e4aa894 100644
--- a/compiler/optimizing/code_generator_x86_64.h
+++ b/compiler/optimizing/code_generator_x86_64.h
@@ -532,6 +532,7 @@ class CodeGeneratorX86_64 : public CodeGenerator {
void RecordBootImageMethodPatch(HInvoke* invoke);
void RecordMethodBssEntryPatch(HInvoke* invoke);
void RecordBootImageTypePatch(const DexFile& dex_file, dex::TypeIndex type_index);
+ void RecordAppImageTypePatch(const DexFile& dex_file, dex::TypeIndex type_index);
Label* NewTypeBssEntryPatch(HLoadClass* load_class);
void RecordBootImageStringPatch(HLoadString* load_string);
Label* NewStringBssEntryPatch(HLoadString* load_string);
@@ -738,6 +739,8 @@ class CodeGeneratorX86_64 : public CodeGenerator {
ArenaDeque<PatchInfo<Label>> method_bss_entry_patches_;
// PC-relative type patch info for kBootImageLinkTimePcRelative.
ArenaDeque<PatchInfo<Label>> boot_image_type_patches_;
+ // PC-relative type patch info for kAppImageRelRo.
+ ArenaDeque<PatchInfo<Label>> app_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.
diff --git a/compiler/optimizing/nodes.h b/compiler/optimizing/nodes.h
index 90fc5db02e..33ffc07ba8 100644
--- a/compiler/optimizing/nodes.h
+++ b/compiler/optimizing/nodes.h
@@ -6743,6 +6743,10 @@ class HLoadClass final : public HInstruction {
// Used for boot image classes referenced by apps in AOT-compiled code.
kBootImageRelRo,
+ // Load from an app image entry in the .data.img.rel.ro using a PC-relative load.
+ // Used for app image classes referenced by apps in AOT-compiled code.
+ kAppImageRelRo,
+
// Load from an entry in the .bss section using a PC-relative load.
// Used for classes outside boot image referenced by AOT-compiled app and boot image code.
kBssEntry,
@@ -6814,6 +6818,7 @@ class HLoadClass final : public HInstruction {
bool HasPcRelativeLoadKind() const {
return GetLoadKind() == LoadKind::kBootImageLinkTimePcRelative ||
GetLoadKind() == LoadKind::kBootImageRelRo ||
+ GetLoadKind() == LoadKind::kAppImageRelRo ||
GetLoadKind() == LoadKind::kBssEntry ||
GetLoadKind() == LoadKind::kBssEntryPublic ||
GetLoadKind() == LoadKind::kBssEntryPackage;
@@ -6933,6 +6938,7 @@ class HLoadClass final : public HInstruction {
static bool HasTypeReference(LoadKind load_kind) {
return load_kind == LoadKind::kReferrersClass ||
load_kind == LoadKind::kBootImageLinkTimePcRelative ||
+ load_kind == LoadKind::kAppImageRelRo ||
load_kind == LoadKind::kBssEntry ||
load_kind == LoadKind::kBssEntryPublic ||
load_kind == LoadKind::kBssEntryPackage ||
@@ -6978,6 +6984,7 @@ inline void HLoadClass::AddSpecialInput(HInstruction* special_input) {
// including literal pool loads, which are PC-relative too.
DCHECK(GetLoadKind() == LoadKind::kBootImageLinkTimePcRelative ||
GetLoadKind() == LoadKind::kBootImageRelRo ||
+ GetLoadKind() == LoadKind::kAppImageRelRo ||
GetLoadKind() == LoadKind::kBssEntry ||
GetLoadKind() == LoadKind::kBssEntryPublic ||
GetLoadKind() == LoadKind::kBssEntryPackage ||
diff --git a/compiler/optimizing/sharpening.cc b/compiler/optimizing/sharpening.cc
index aa75c2464b..cb94491b8e 100644
--- a/compiler/optimizing/sharpening.cc
+++ b/compiler/optimizing/sharpening.cc
@@ -277,7 +277,7 @@ HLoadClass::LoadKind HSharpening::ComputeLoadClassKind(
} else if (compiler_options.IsAppImage() && is_class_in_current_image()) {
// AOT app compilation, app image class.
is_in_image = true;
- desired_load_kind = HLoadClass::LoadKind::kBssEntry;
+ desired_load_kind = HLoadClass::LoadKind::kAppImageRelRo;
} else {
// Not JIT and the klass is not in boot image or app image.
desired_load_kind = HLoadClass::LoadKind::kBssEntry;
diff --git a/dex2oat/dex2oat.cc b/dex2oat/dex2oat.cc
index 9f2d263de3..9529e6d28b 100644
--- a/dex2oat/dex2oat.cc
+++ b/dex2oat/dex2oat.cc
@@ -2130,6 +2130,7 @@ class Dex2Oat final {
elf_writer->PrepareDynamicSection(oat_writer->GetOatHeader().GetExecutableOffset(),
oat_writer->GetCodeSize(),
oat_writer->GetDataImgRelRoSize(),
+ oat_writer->GetDataImgRelRoAppImageOffset(),
oat_writer->GetBssSize(),
oat_writer->GetBssMethodsOffset(),
oat_writer->GetBssRootsOffset(),
diff --git a/dex2oat/linker/arm64/relative_patcher_arm64.cc b/dex2oat/linker/arm64/relative_patcher_arm64.cc
index 8772974c4b..2956285545 100644
--- a/dex2oat/linker/arm64/relative_patcher_arm64.cc
+++ b/dex2oat/linker/arm64/relative_patcher_arm64.cc
@@ -66,6 +66,7 @@ inline bool IsAdrpPatch(const LinkerPatch& patch) {
case LinkerPatch::Type::kMethodBssEntry:
case LinkerPatch::Type::kJniEntrypointRelative:
case LinkerPatch::Type::kTypeRelative:
+ case LinkerPatch::Type::kTypeAppImageRelRo:
case LinkerPatch::Type::kTypeBssEntry:
case LinkerPatch::Type::kPublicTypeBssEntry:
case LinkerPatch::Type::kPackageTypeBssEntry:
@@ -274,6 +275,7 @@ void Arm64RelativePatcher::PatchPcRelativeReference(std::vector<uint8_t>* code,
DCHECK(patch.GetType() == LinkerPatch::Type::kBootImageRelRo ||
patch.GetType() == LinkerPatch::Type::kMethodBssEntry ||
patch.GetType() == LinkerPatch::Type::kJniEntrypointRelative ||
+ patch.GetType() == LinkerPatch::Type::kTypeAppImageRelRo ||
patch.GetType() == LinkerPatch::Type::kTypeBssEntry ||
patch.GetType() == LinkerPatch::Type::kPublicTypeBssEntry ||
patch.GetType() == LinkerPatch::Type::kPackageTypeBssEntry ||
diff --git a/dex2oat/linker/elf_writer.h b/dex2oat/linker/elf_writer.h
index a1d0ece9de..35e3565592 100644
--- a/dex2oat/linker/elf_writer.h
+++ b/dex2oat/linker/elf_writer.h
@@ -61,6 +61,7 @@ class ElfWriter {
virtual void PrepareDynamicSection(size_t rodata_size,
size_t text_size,
size_t data_img_rel_ro_size,
+ size_t data_img_rel_ro_app_image_offset,
size_t bss_size,
size_t bss_methods_offset,
size_t bss_roots_offset,
diff --git a/dex2oat/linker/elf_writer_quick.cc b/dex2oat/linker/elf_writer_quick.cc
index 373c46ce2c..f87ca6d81e 100644
--- a/dex2oat/linker/elf_writer_quick.cc
+++ b/dex2oat/linker/elf_writer_quick.cc
@@ -92,6 +92,7 @@ class ElfWriterQuick final : public ElfWriter {
void PrepareDynamicSection(size_t rodata_size,
size_t text_size,
size_t data_img_rel_ro_size,
+ size_t data_img_rel_ro_app_image_offset,
size_t bss_size,
size_t bss_methods_offset,
size_t bss_roots_offset,
@@ -173,6 +174,7 @@ template <typename ElfTypes>
void ElfWriterQuick<ElfTypes>::PrepareDynamicSection(size_t rodata_size,
size_t text_size,
size_t data_img_rel_ro_size,
+ size_t data_img_rel_ro_app_image_offset,
size_t bss_size,
size_t bss_methods_offset,
size_t bss_roots_offset,
@@ -191,6 +193,7 @@ void ElfWriterQuick<ElfTypes>::PrepareDynamicSection(size_t rodata_size,
rodata_size_,
text_size_,
data_img_rel_ro_size_,
+ data_img_rel_ro_app_image_offset,
bss_size_,
bss_methods_offset,
bss_roots_offset,
diff --git a/dex2oat/linker/image_test.h b/dex2oat/linker/image_test.h
index 9f553c1c74..f4a87bb84d 100644
--- a/dex2oat/linker/image_test.h
+++ b/dex2oat/linker/image_test.h
@@ -309,6 +309,7 @@ inline void ImageTest::DoCompile(ImageHeader::StorageMode storage_mode,
elf_writer->PrepareDynamicSection(oat_writer->GetOatHeader().GetExecutableOffset(),
oat_writer->GetCodeSize(),
oat_writer->GetDataImgRelRoSize(),
+ oat_writer->GetDataImgRelRoAppImageOffset(),
oat_writer->GetBssSize(),
oat_writer->GetBssMethodsOffset(),
oat_writer->GetBssRootsOffset(),
diff --git a/dex2oat/linker/image_writer.h b/dex2oat/linker/image_writer.h
index 4d45529871..8ffe226bec 100644
--- a/dex2oat/linker/image_writer.h
+++ b/dex2oat/linker/image_writer.h
@@ -128,6 +128,15 @@ class ImageWriter final {
}
}
+ uint32_t GetGlobalImageOffset(mirror::Object* object) const REQUIRES_SHARED(Locks::mutator_lock_) {
+ DCHECK(object != nullptr);
+ DCHECK(!IsInBootImage(object));
+ size_t oat_index = GetOatIndex(object);
+ const ImageInfo& image_info = GetImageInfo(oat_index);
+ return dchecked_integral_cast<uint32_t>(
+ image_info.image_begin_ + GetImageOffset(object, oat_index) - global_image_begin_);
+ }
+
ArtMethod* GetImageMethodAddress(ArtMethod* method) REQUIRES_SHARED(Locks::mutator_lock_);
const void* GetIntrinsicReferenceAddress(uint32_t intrinsic_data)
REQUIRES_SHARED(Locks::mutator_lock_);
diff --git a/dex2oat/linker/oat_writer.cc b/dex2oat/linker/oat_writer.cc
index b1287d9ab3..7c2f8d6249 100644
--- a/dex2oat/linker/oat_writer.cc
+++ b/dex2oat/linker/oat_writer.cc
@@ -373,6 +373,7 @@ OatWriter::OatWriter(const CompilerOptions& compiler_options,
oat_size_(0u),
data_img_rel_ro_start_(0u),
data_img_rel_ro_size_(0u),
+ data_img_rel_ro_app_image_offset_(0u),
bss_start_(0u),
bss_size_(0u),
bss_methods_offset_(0u),
@@ -380,6 +381,7 @@ OatWriter::OatWriter(const CompilerOptions& compiler_options,
boot_image_rel_ro_entries_(),
bss_method_entry_references_(),
bss_method_entries_(),
+ app_image_rel_ro_type_entries_(),
bss_type_entries_(),
bss_public_type_entries_(),
bss_package_type_entries_(),
@@ -754,6 +756,9 @@ class OatWriter::InitBssLayoutMethodVisitor : public DexMethodVisitor {
target_method.dex_file->NumMethodIds(),
&writer_->bss_method_entry_references_);
writer_->bss_method_entries_.Overwrite(target_method, /* placeholder */ 0u);
+ } else if (patch.GetType() == LinkerPatch::Type::kTypeAppImageRelRo) {
+ writer_->app_image_rel_ro_type_entries_.Overwrite(patch.TargetType(),
+ /* placeholder */ 0u);
} else if (patch.GetType() == LinkerPatch::Type::kTypeBssEntry) {
TypeReference target_type = patch.TargetType();
AddBssReference(target_type,
@@ -1710,6 +1715,16 @@ class OatWriter::WriteCodeMethodVisitor : public OrderedMethodVisitor {
target_offset);
break;
}
+ case LinkerPatch::Type::kTypeAppImageRelRo: {
+ uint32_t target_offset =
+ writer_->data_img_rel_ro_start_ +
+ writer_->app_image_rel_ro_type_entries_.Get(patch.TargetType());
+ writer_->relative_patcher_->PatchPcRelativeReference(&patched_code_,
+ patch,
+ offset_ + literal_offset,
+ target_offset);
+ break;
+ }
case LinkerPatch::Type::kTypeBssEntry: {
uint32_t target_offset =
writer_->bss_start_ + writer_->bss_type_entries_.Get(patch.TargetType());
@@ -2364,7 +2379,7 @@ size_t OatWriter::InitOatCodeDexFiles(size_t offset) {
size_t OatWriter::InitDataImgRelRoLayout(size_t offset) {
DCHECK_EQ(data_img_rel_ro_size_, 0u);
- if (boot_image_rel_ro_entries_.empty()) {
+ if (boot_image_rel_ro_entries_.empty() && app_image_rel_ro_type_entries_.empty()) {
// Nothing to put to the .data.img.rel.ro section.
return offset;
}
@@ -2377,6 +2392,14 @@ size_t OatWriter::InitDataImgRelRoLayout(size_t offset) {
data_img_rel_ro_size_ += sizeof(uint32_t);
}
+ data_img_rel_ro_app_image_offset_ = data_img_rel_ro_size_;
+
+ for (auto& entry : app_image_rel_ro_type_entries_) {
+ size_t& entry_offset = entry.second;
+ entry_offset = data_img_rel_ro_size_;
+ data_img_rel_ro_size_ += sizeof(uint32_t);
+ }
+
offset = data_img_rel_ro_start_ + data_img_rel_ro_size_;
return offset;
}
@@ -3177,18 +3200,39 @@ size_t OatWriter::WriteCodeDexFiles(OutputStream* out,
size_t OatWriter::WriteDataImgRelRo(OutputStream* out,
size_t file_offset,
size_t relative_offset) {
- if (boot_image_rel_ro_entries_.empty()) {
+ if (boot_image_rel_ro_entries_.empty() && app_image_rel_ro_type_entries_.empty()) {
return relative_offset;
}
// Write the entire .data.img.rel.ro with a single WriteFully().
std::vector<uint32_t> data;
- data.reserve(boot_image_rel_ro_entries_.size());
+ data.reserve(boot_image_rel_ro_entries_.size() + app_image_rel_ro_type_entries_.size());
for (const auto& entry : boot_image_rel_ro_entries_) {
uint32_t boot_image_offset = entry.first;
data.push_back(boot_image_offset);
}
- DCHECK_EQ(data.size(), boot_image_rel_ro_entries_.size());
+ if (!app_image_rel_ro_type_entries_.empty()) {
+ DCHECK(GetCompilerOptions().IsAppImage());
+ ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
+ ScopedObjectAccess soa(Thread::Current());
+ const DexFile* last_dex_file = nullptr;
+ ObjPtr<mirror::DexCache> dex_cache = nullptr;
+ ObjPtr<mirror::ClassLoader> class_loader = nullptr;
+ for (const auto& entry : app_image_rel_ro_type_entries_) {
+ TypeReference target_type = entry.first;
+ if (target_type.dex_file != last_dex_file) {
+ dex_cache = class_linker->FindDexCache(soa.Self(), *target_type.dex_file);
+ class_loader = dex_cache->GetClassLoader();
+ last_dex_file = target_type.dex_file;
+ }
+ ObjPtr<mirror::Class> type =
+ class_linker->LookupResolvedType(target_type.TypeIndex(), dex_cache, class_loader);
+ CHECK(type != nullptr);
+ uint32_t app_image_offset = image_writer_->GetGlobalImageOffset(type.Ptr());
+ data.push_back(app_image_offset);
+ }
+ }
+ DCHECK_EQ(data.size(), boot_image_rel_ro_entries_.size() + app_image_rel_ro_type_entries_.size());
DCHECK_OFFSET();
if (!out->WriteFully(data.data(), data.size() * sizeof(data[0]))) {
PLOG(ERROR) << "Failed to write .data.img.rel.ro in " << out->GetLocation();
diff --git a/dex2oat/linker/oat_writer.h b/dex2oat/linker/oat_writer.h
index 4e2332e3cc..43c9bc77ff 100644
--- a/dex2oat/linker/oat_writer.h
+++ b/dex2oat/linker/oat_writer.h
@@ -215,6 +215,10 @@ class OatWriter {
return data_img_rel_ro_size_;
}
+ size_t GetDataImgRelRoAppImageOffset() const {
+ return data_img_rel_ro_app_image_offset_;
+ }
+
size_t GetBssSize() const {
return bss_size_;
}
@@ -419,6 +423,9 @@ class OatWriter {
// The size of the optional .data.img.rel.ro section holding the image relocations.
size_t data_img_rel_ro_size_;
+ // The start of app image relocations in the .data.img.rel.ro section.
+ size_t data_img_rel_ro_app_image_offset_;
+
// The start of the optional .bss section.
size_t bss_start_;
@@ -462,6 +469,11 @@ class OatWriter {
// The value is the target offset for patching, starting at `bss_start_ + bss_methods_offset_`.
SafeMap<MethodReference, size_t, MethodReferenceValueComparator> bss_method_entries_;
+ // Map for allocating app image Class entries in .data.img.rel.ro. 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 `data_img_rel_ro_start_`.
+ SafeMap<TypeReference, size_t, TypeReferenceValueComparator> app_image_rel_ro_type_entries_;
+
// Map for allocating 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_`.
diff --git a/dex2oat/linker/oat_writer_test.cc b/dex2oat/linker/oat_writer_test.cc
index 0972e5d14a..f2a6ee47f0 100644
--- a/dex2oat/linker/oat_writer_test.cc
+++ b/dex2oat/linker/oat_writer_test.cc
@@ -211,6 +211,7 @@ class OatTest : public CommonCompilerDriverTest {
elf_writer->PrepareDynamicSection(oat_writer.GetOatHeader().GetExecutableOffset(),
oat_writer.GetCodeSize(),
oat_writer.GetDataImgRelRoSize(),
+ oat_writer.GetDataImgRelRoAppImageOffset(),
oat_writer.GetBssSize(),
oat_writer.GetBssMethodsOffset(),
oat_writer.GetBssRootsOffset(),
diff --git a/libelffile/elf/elf_builder.h b/libelffile/elf/elf_builder.h
index 908ad5cb89..bb82b109bd 100644
--- a/libelffile/elf/elf_builder.h
+++ b/libelffile/elf/elf_builder.h
@@ -641,6 +641,7 @@ class ElfBuilder final {
Elf_Word rodata_size,
Elf_Word text_size,
Elf_Word data_img_rel_ro_size,
+ Elf_Word data_img_rel_ro_app_image_offset,
Elf_Word bss_size,
Elf_Word bss_methods_offset,
Elf_Word bss_roots_offset,
@@ -682,6 +683,7 @@ class ElfBuilder final {
Elf_Word oatlastword_address = rodata_.GetAddress() + rodata_size - 4;
dynsym_.Add(oatlastword, &rodata_, oatlastword_address, 4, STB_GLOBAL, STT_OBJECT);
}
+ DCHECK_LE(data_img_rel_ro_app_image_offset, data_img_rel_ro_size);
if (data_img_rel_ro_size != 0u) {
Elf_Word oatdataimgrelro = dynstr_.Add("oatdataimgrelro");
dynsym_.Add(oatdataimgrelro,
@@ -691,14 +693,21 @@ class ElfBuilder final {
STB_GLOBAL,
STT_OBJECT);
Elf_Word oatdataimgrelrolastword = dynstr_.Add("oatdataimgrelrolastword");
- Elf_Word oatdataimgrelrolastword_address =
- data_img_rel_ro_.GetAddress() + data_img_rel_ro_size - 4;
dynsym_.Add(oatdataimgrelrolastword,
&data_img_rel_ro_,
- oatdataimgrelrolastword_address,
+ data_img_rel_ro_.GetAddress() + data_img_rel_ro_size - 4,
4,
STB_GLOBAL,
STT_OBJECT);
+ if (data_img_rel_ro_app_image_offset != data_img_rel_ro_size) {
+ Elf_Word oatdataimgrelroappimage = dynstr_.Add("oatdataimgrelroappimage");
+ dynsym_.Add(oatdataimgrelroappimage,
+ &data_img_rel_ro_,
+ data_img_rel_ro_.GetAddress() + data_img_rel_ro_app_image_offset,
+ data_img_rel_ro_app_image_offset,
+ STB_GLOBAL,
+ STT_OBJECT);
+ }
}
DCHECK_LE(bss_roots_offset, bss_size);
if (bss_size != 0u) {
diff --git a/oatdump/oatdump.cc b/oatdump/oatdump.cc
index 2c17845417..983316e9a2 100644
--- a/oatdump/oatdump.cc
+++ b/oatdump/oatdump.cc
@@ -183,6 +183,7 @@ class OatSymbolizer final {
rodata_size,
text_size,
oat_file_->DataImgRelRoSize(),
+ oat_file_->DataImgRelRoAppImageOffset(),
oat_file_->BssSize(),
oat_file_->BssMethodsOffset(),
oat_file_->BssRootsOffset(),
diff --git a/runtime/mirror/dex_cache.h b/runtime/mirror/dex_cache.h
index 8910dfcbb5..c1d71e1501 100644
--- a/runtime/mirror/dex_cache.h
+++ b/runtime/mirror/dex_cache.h
@@ -374,7 +374,7 @@ class MANAGED DexCache final : public Object {
void SetClassLoader(ObjPtr<ClassLoader> class_loader) REQUIRES_SHARED(Locks::mutator_lock_);
- ObjPtr<ClassLoader> GetClassLoader() REQUIRES_SHARED(Locks::mutator_lock_);
+ EXPORT ObjPtr<ClassLoader> GetClassLoader() REQUIRES_SHARED(Locks::mutator_lock_);
template <VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags,
ReadBarrierOption kReadBarrierOption = kWithReadBarrier,
diff --git a/runtime/oat/oat.h b/runtime/oat/oat.h
index 84c169a365..b850fe8dd5 100644
--- a/runtime/oat/oat.h
+++ b/runtime/oat/oat.h
@@ -44,8 +44,8 @@ std::ostream& operator<<(std::ostream& stream, StubType stub_type);
class EXPORT PACKED(4) OatHeader {
public:
static constexpr std::array<uint8_t, 4> kOatMagic { { 'o', 'a', 't', '\n' } };
- // Last oat version changed reason: BSS mappings for boot image extension.
- static constexpr std::array<uint8_t, 4> kOatVersion{{'2', '4', '3', '\0'}};
+ // Last oat version changed reason: Implement `HLoadClass::LoadKind::kAppImageRelRo`.
+ static constexpr std::array<uint8_t, 4> kOatVersion{{'2', '4', '4', '\0'}};
static constexpr const char* kDex2OatCmdLineKey = "dex2oat-cmdline";
static constexpr const char* kDebuggableKey = "debuggable";
diff --git a/runtime/oat/oat_file.cc b/runtime/oat/oat_file.cc
index 889b78f015..97db7569cf 100644
--- a/runtime/oat/oat_file.cc
+++ b/runtime/oat/oat_file.cc
@@ -373,6 +373,11 @@ bool OatFileBase::ComputeFields(const std::string& file_path, std::string* error
}
// Readjust to be non-inclusive upper bound.
data_img_rel_ro_end_ += sizeof(uint32_t);
+ data_img_rel_ro_app_image_ =
+ FindDynamicSymbolAddress("oatdataimgrelroappimage", &symbol_error_msg);
+ if (data_img_rel_ro_app_image_ == nullptr) {
+ data_img_rel_ro_app_image_ = data_img_rel_ro_end_;
+ }
}
bss_begin_ = const_cast<uint8_t*>(FindDynamicSymbolAddress("oatbss", &symbol_error_msg));
@@ -648,10 +653,15 @@ bool OatFileBase::Setup(int zip_fd,
if (!IsAligned<sizeof(uint32_t)>(data_img_rel_ro_begin_) ||
!IsAligned<sizeof(uint32_t)>(data_img_rel_ro_end_) ||
- data_img_rel_ro_begin_ > data_img_rel_ro_end_) {
- *error_msg = ErrorPrintf("unaligned or unordered databimgrelro symbol(s): begin = %p, end = %p",
- data_img_rel_ro_begin_,
- data_img_rel_ro_end_);
+ !IsAligned<sizeof(uint32_t)>(data_img_rel_ro_app_image_) ||
+ data_img_rel_ro_begin_ > data_img_rel_ro_end_ ||
+ data_img_rel_ro_begin_ > data_img_rel_ro_app_image_ ||
+ data_img_rel_ro_app_image_ > data_img_rel_ro_end_) {
+ *error_msg = ErrorPrintf(
+ "unaligned or unordered databimgrelro symbol(s): begin = %p, end = %p, app_image = %p",
+ data_img_rel_ro_begin_,
+ data_img_rel_ro_end_,
+ data_img_rel_ro_app_image_);
return false;
}
@@ -2015,6 +2025,7 @@ OatFile::OatFile(const std::string& location, bool is_executable)
end_(nullptr),
data_img_rel_ro_begin_(nullptr),
data_img_rel_ro_end_(nullptr),
+ data_img_rel_ro_app_image_(nullptr),
bss_begin_(nullptr),
bss_end_(nullptr),
bss_methods_(nullptr),
@@ -2022,6 +2033,7 @@ OatFile::OatFile(const std::string& location, bool is_executable)
is_executable_(is_executable),
vdex_begin_(nullptr),
vdex_end_(nullptr),
+ app_image_begin_(nullptr),
secondary_lookup_lock_("OatFile secondary lookup lock", kOatFileSecondaryLookupLock) {
CHECK(!location_.empty());
}
@@ -2054,9 +2066,25 @@ const uint8_t* OatFile::DexEnd() const {
ArrayRef<const uint32_t> OatFile::GetBootImageRelocations() const {
if (data_img_rel_ro_begin_ != nullptr) {
- const uint32_t* relocations = reinterpret_cast<const uint32_t*>(data_img_rel_ro_begin_);
- const uint32_t* relocations_end = reinterpret_cast<const uint32_t*>(data_img_rel_ro_end_);
- return ArrayRef<const uint32_t>(relocations, relocations_end - relocations);
+ const uint32_t* boot_image_relocations =
+ reinterpret_cast<const uint32_t*>(data_img_rel_ro_begin_);
+ const uint32_t* boot_image_relocations_end =
+ reinterpret_cast<const uint32_t*>(data_img_rel_ro_app_image_);
+ return ArrayRef<const uint32_t>(
+ boot_image_relocations, boot_image_relocations_end - boot_image_relocations);
+ } else {
+ return ArrayRef<const uint32_t>();
+ }
+}
+
+ArrayRef<const uint32_t> OatFile::GetAppImageRelocations() const {
+ if (data_img_rel_ro_begin_ != nullptr) {
+ const uint32_t* app_image_relocations =
+ reinterpret_cast<const uint32_t*>(data_img_rel_ro_app_image_);
+ const uint32_t* app_image_relocations_end =
+ reinterpret_cast<const uint32_t*>(data_img_rel_ro_end_);
+ return ArrayRef<const uint32_t>(
+ app_image_relocations, app_image_relocations_end - app_image_relocations);
} else {
return ArrayRef<const uint32_t>();
}
@@ -2476,7 +2504,7 @@ void OatFile::InitializeRelocations() const {
DCHECK(IsExecutable());
// Initialize the .data.img.rel.ro section.
- if (!GetBootImageRelocations().empty()) {
+ if (DataImgRelRoEnd() != DataImgRelRoBegin()) {
uint8_t* reloc_begin = const_cast<uint8_t*>(DataImgRelRoBegin());
CheckedCall(mprotect,
"un-protect boot image relocations",
@@ -2487,6 +2515,13 @@ void OatFile::InitializeRelocations() const {
for (const uint32_t& relocation : GetBootImageRelocations()) {
const_cast<uint32_t&>(relocation) += boot_image_begin;
}
+ if (!GetAppImageRelocations().empty()) {
+ CHECK(app_image_begin_ != nullptr);
+ uint32_t app_image_begin = reinterpret_cast32<uint32_t>(app_image_begin_);
+ for (const uint32_t& relocation : GetAppImageRelocations()) {
+ const_cast<uint32_t&>(relocation) += app_image_begin;
+ }
+ }
CheckedCall(mprotect,
"protect boot image relocations",
reloc_begin,
diff --git a/runtime/oat/oat_file.h b/runtime/oat/oat_file.h
index e17f4c43ff..579fb049f0 100644
--- a/runtime/oat/oat_file.h
+++ b/runtime/oat/oat_file.h
@@ -181,6 +181,12 @@ class OatFile {
ClassLoaderContext* context,
std::string* error_msg);
+ // Set the start of the app image.
+ // Needed for initializing app image relocations in the .data.img.rel.ro section.
+ void SetAppImageBegin(uint8_t* app_image_begin) const {
+ app_image_begin_ = app_image_begin;
+ }
+
// Return whether the `OatFile` uses a vdex-only file.
bool IsBackedByVdexOnly() const;
@@ -329,6 +335,10 @@ class OatFile {
return DataImgRelRoEnd() - DataImgRelRoBegin();
}
+ size_t DataImgRelRoAppImageOffset() const {
+ return DataImgRelRoAppImage() - DataImgRelRoBegin();
+ }
+
size_t BssSize() const {
return BssEnd() - BssBegin();
}
@@ -356,6 +366,7 @@ class OatFile {
const uint8_t* DataImgRelRoBegin() const { return data_img_rel_ro_begin_; }
const uint8_t* DataImgRelRoEnd() const { return data_img_rel_ro_end_; }
+ const uint8_t* DataImgRelRoAppImage() const { return data_img_rel_ro_app_image_; }
const uint8_t* BssBegin() const { return bss_begin_; }
const uint8_t* BssEnd() const { return bss_end_; }
@@ -367,6 +378,7 @@ class OatFile {
EXPORT const uint8_t* DexEnd() const;
EXPORT ArrayRef<const uint32_t> GetBootImageRelocations() const;
+ EXPORT ArrayRef<const uint32_t> GetAppImageRelocations() const;
EXPORT ArrayRef<ArtMethod*> GetBssMethods() const;
EXPORT ArrayRef<GcRoot<mirror::Object>> GetBssGcRoots() const;
@@ -429,16 +441,20 @@ class OatFile {
// Pointer to the end of the .data.img.rel.ro section, if present, otherwise null.
const uint8_t* data_img_rel_ro_end_;
+ // Pointer to the beginning of the app image relocations in the .data.img.rel.ro section,
+ // if present, otherwise null.
+ const uint8_t* data_img_rel_ro_app_image_;
+
// Pointer to the .bss section, if present, otherwise null.
uint8_t* bss_begin_;
// Pointer to the end of the .bss section, if present, otherwise null.
uint8_t* bss_end_;
- // Pointer to the beginning of the ArtMethod*s in .bss section, if present, otherwise null.
+ // Pointer to the beginning of the ArtMethod*s in the .bss section, if present, otherwise null.
uint8_t* bss_methods_;
- // Pointer to the beginning of the GC roots in .bss section, if present, otherwise null.
+ // Pointer to the beginning of the GC roots in the .bss section, if present, otherwise null.
uint8_t* bss_roots_;
// Was this oat_file loaded executable?
@@ -450,6 +466,9 @@ class OatFile {
// Pointer to the end of the .vdex section, if present, otherwise null.
uint8_t* vdex_end_;
+ // Pointer to the beginning of the app image, if any.
+ mutable uint8_t* app_image_begin_;
+
// Owning storage for the OatDexFile objects.
std::vector<const OatDexFile*> oat_dex_files_storage_;
diff --git a/runtime/oat/oat_file_manager.cc b/runtime/oat/oat_file_manager.cc
index 11333b0249..fea361b8ee 100644
--- a/runtime/oat/oat_file_manager.cc
+++ b/runtime/oat/oat_file_manager.cc
@@ -312,6 +312,7 @@ std::vector<std::unique_ptr<const DexFile>> OatFileManager::OpenDexFilesFromOat(
hs.NewHandle(soa.Decode<mirror::ClassLoader>(class_loader)));
// Can not load app image without class loader.
if (h_loader != nullptr) {
+ oat_file->SetAppImageBegin(image_space->Begin());
std::string temp_error_msg;
// Add image space has a race condition since other threads could be reading from the
// spaces array.
@@ -344,6 +345,7 @@ std::vector<std::unique_ptr<const DexFile>> OatFileManager::OpenDexFilesFromOat(
}
} else {
LOG(INFO) << "Failed to add image file: " << temp_error_msg;
+ oat_file->SetAppImageBegin(nullptr);
dex_files.clear();
{
ScopedThreadSuspension sts(self, ThreadState::kSuspended);
diff --git a/test/732-checker-app-image/src-ex/Secondary.java b/test/732-checker-app-image/src-ex/Secondary.java
index 52354856d6..e544e6c162 100644
--- a/test/732-checker-app-image/src-ex/Secondary.java
+++ b/test/732-checker-app-image/src-ex/Secondary.java
@@ -22,7 +22,7 @@ public class Secondary {
}
/// CHECK-START: java.lang.Class Secondary.$noinline$getSecondaryAppImageClass() builder (after)
- /// CHECK: LoadClass load_kind:BssEntry in_image:true
+ /// CHECK: LoadClass load_kind:AppImageRelRo in_image:true
public static Class<?> $noinline$getSecondaryAppImageClass() {
return SecondaryAppImageClass.class;
}
diff --git a/test/732-checker-app-image/src/Main.java b/test/732-checker-app-image/src/Main.java
index ac8d2254c9..815902940d 100644
--- a/test/732-checker-app-image/src/Main.java
+++ b/test/732-checker-app-image/src/Main.java
@@ -50,7 +50,7 @@ public class Main {
}
/// CHECK-START: java.lang.Class Main.$noinline$getAppImageClass() builder (after)
- /// CHECK: LoadClass load_kind:BssEntry in_image:true
+ /// CHECK: LoadClass load_kind:AppImageRelRo in_image:true
public static Class<?> $noinline$getAppImageClass() {
return AppImageClass.class;
}
@@ -77,22 +77,20 @@ public class Main {
}
/// CHECK-START: void Main.$noinline$callAppImageClassWithClinitNop() builder (after)
- /// CHECK: LoadClass load_kind:BssEntry in_image:true gen_clinit_check:false
+ /// CHECK: LoadClass load_kind:AppImageRelRo in_image:true gen_clinit_check:false
/// CHECK: ClinitCheck
/// CHECK: InvokeStaticOrDirect clinit_check:explicit
/// CHECK-START: void Main.$noinline$callAppImageClassWithClinitNop() inliner (after)
- /// CHECK: LoadClass load_kind:BssEntry in_image:true gen_clinit_check:false
+ /// CHECK: LoadClass load_kind:AppImageRelRo in_image:true gen_clinit_check:false
/// CHECK: ClinitCheck
/// CHECK-START: void Main.$noinline$callAppImageClassWithClinitNop() inliner (after)
/// CHECK-NOT: InvokeStaticOrDirect
/// CHECK-START: void Main.$noinline$callAppImageClassWithClinitNop() prepare_for_register_allocation (after)
- /// CHECK: LoadClass load_kind:BssEntry in_image:true gen_clinit_check:true
-
- /// CHECK-START: void Main.$noinline$callAppImageClassWithClinitNop() prepare_for_register_allocation (after)
- /// CHECK-NOT: ClinitCheck
+ /// CHECK: LoadClass load_kind:AppImageRelRo in_image:true gen_clinit_check:false
+ /// CHECK: ClinitCheck
public static void $noinline$callAppImageClassWithClinitNop() {
AppImageClassWithClinit.$inline$nop();
}