summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Vladimir Marko <vmarko@google.com> 2024-10-31 17:38:03 +0100
committer VladimĂ­r Marko <vmarko@google.com> 2024-11-05 13:54:34 +0000
commit4d6fdd9fb379ac6e3575c3ec5406d808e0290636 (patch)
treecd7c157f6ca93745672901a3fafc33a9426c70fe
parent389f84b5c45cb58255ebcc44758f04adc37dd5b6 (diff)
Use .data.img.rel.ro for app image methods.
This should improve app startup as we can skip the target method resolution on the first call. For `invoke-direct` we should never go to the resolution trampoline for app image methods and for `invoke-static` we go to the trampoline only if the class is not yet visibly initialized and in that case we still save time as the target method is already known. Test: m test-art-host-gtest Test: testrunner.py --host --optimizing --speed-profile Test: run-gtests.sh Test: testrunner.py --target --optimizing --speed-profile Bug: 38313278 Change-Id: I1fea5485264b433fe642c9d0092a5411813eb996
-rw-r--r--compiler/linker/linker_patch.h13
-rw-r--r--compiler/optimizing/code_generator_arm64.cc25
-rw-r--r--compiler/optimizing/code_generator_arm64.h9
-rw-r--r--compiler/optimizing/code_generator_arm_vixl.cc19
-rw-r--r--compiler/optimizing/code_generator_arm_vixl.h3
-rw-r--r--compiler/optimizing/code_generator_riscv64.cc22
-rw-r--r--compiler/optimizing/code_generator_riscv64.h4
-rw-r--r--compiler/optimizing/code_generator_x86.cc25
-rw-r--r--compiler/optimizing/code_generator_x86.h3
-rw-r--r--compiler/optimizing/code_generator_x86_64.cc18
-rw-r--r--compiler/optimizing/code_generator_x86_64.h3
-rw-r--r--compiler/optimizing/nodes.h5
-rw-r--r--compiler/optimizing/sharpening.cc17
-rw-r--r--dex2oat/linker/arm64/relative_patcher_arm64.cc2
-rw-r--r--dex2oat/linker/image_writer.cc4
-rw-r--r--dex2oat/linker/image_writer.h8
-rw-r--r--dex2oat/linker/oat_writer.cc64
-rw-r--r--dex2oat/linker/oat_writer.h6
-rw-r--r--runtime/oat/oat.h4
-rw-r--r--test/552-checker-sharpening/profile15
-rw-r--r--test/552-checker-sharpening/run.py20
-rw-r--r--test/552-checker-sharpening/src/Main.java55
22 files changed, 313 insertions, 31 deletions
diff --git a/compiler/linker/linker_patch.h b/compiler/linker/linker_patch.h
index b061e042f0..4eb0782d52 100644
--- a/compiler/linker/linker_patch.h
+++ b/compiler/linker/linker_patch.h
@@ -50,6 +50,7 @@ class LinkerPatch {
kIntrinsicReference, // Boot image reference for an intrinsic, see IntrinsicObjects.
kBootImageRelRo,
kMethodRelative,
+ kMethodAppImageRelRo,
kMethodBssEntry,
kJniEntrypointRelative,
kCallRelative,
@@ -93,6 +94,16 @@ class LinkerPatch {
return patch;
}
+ static LinkerPatch MethodAppImageRelRoPatch(size_t literal_offset,
+ const DexFile* target_dex_file,
+ uint32_t pc_insn_offset,
+ uint32_t target_method_idx) {
+ LinkerPatch patch(literal_offset, Type::kMethodAppImageRelRo, target_dex_file);
+ patch.method_idx_ = target_method_idx;
+ patch.pc_insn_offset_ = pc_insn_offset;
+ return patch;
+ }
+
static LinkerPatch MethodBssEntryPatch(size_t literal_offset,
const DexFile* target_dex_file,
uint32_t pc_insn_offset,
@@ -244,6 +255,7 @@ class LinkerPatch {
MethodReference TargetMethod() const {
DCHECK(patch_type_ == Type::kMethodRelative ||
+ patch_type_ == Type::kMethodAppImageRelRo ||
patch_type_ == Type::kMethodBssEntry ||
patch_type_ == Type::kJniEntrypointRelative ||
patch_type_ == Type::kCallRelative);
@@ -274,6 +286,7 @@ class LinkerPatch {
DCHECK(patch_type_ == Type::kIntrinsicReference ||
patch_type_ == Type::kBootImageRelRo ||
patch_type_ == Type::kMethodRelative ||
+ patch_type_ == Type::kMethodAppImageRelRo ||
patch_type_ == Type::kMethodBssEntry ||
patch_type_ == Type::kJniEntrypointRelative ||
patch_type_ == Type::kTypeRelative ||
diff --git a/compiler/optimizing/code_generator_arm64.cc b/compiler/optimizing/code_generator_arm64.cc
index 13d126d3d4..6854c7266d 100644
--- a/compiler/optimizing/code_generator_arm64.cc
+++ b/compiler/optimizing/code_generator_arm64.cc
@@ -1049,6 +1049,7 @@ CodeGeneratorARM64::CodeGeneratorARM64(HGraph* graph,
assembler_(graph->GetAllocator(),
compiler_options.GetInstructionSetFeatures()->AsArm64InstructionSetFeatures()),
boot_image_method_patches_(graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)),
+ app_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)),
@@ -4969,6 +4970,19 @@ void CodeGeneratorARM64::LoadMethod(MethodLoadKind load_kind, Location temp, HIn
LoadBootImageRelRoEntry(WRegisterFrom(temp), boot_image_offset);
break;
}
+ case MethodLoadKind::kAppImageRelRo: {
+ DCHECK(GetCompilerOptions().IsAppImage());
+ // Add ADRP with its PC-relative method patch.
+ vixl::aarch64::Label* adrp_label =
+ NewAppImageMethodPatch(invoke->GetResolvedMethodReference());
+ EmitAdrpPlaceholder(adrp_label, XRegisterFrom(temp));
+ // Add LDR with its PC-relative method patch.
+ // Note: App image is in the low 4GiB and the entry is 32-bit, so emit a 32-bit load.
+ vixl::aarch64::Label* ldr_label =
+ NewAppImageMethodPatch(invoke->GetResolvedMethodReference(), adrp_label);
+ EmitLdrOffsetPlaceholder(ldr_label, WRegisterFrom(temp), XRegisterFrom(temp));
+ break;
+ }
case MethodLoadKind::kBssEntry: {
// Add ADRP with its PC-relative .bss entry patch.
vixl::aarch64::Label* adrp_label = NewMethodBssEntryPatch(invoke->GetMethodReference());
@@ -5227,6 +5241,13 @@ vixl::aarch64::Label* CodeGeneratorARM64::NewBootImageMethodPatch(
target_method.dex_file, target_method.index, adrp_label, &boot_image_method_patches_);
}
+vixl::aarch64::Label* CodeGeneratorARM64::NewAppImageMethodPatch(
+ MethodReference target_method,
+ vixl::aarch64::Label* adrp_label) {
+ return NewPcRelativePatch(
+ target_method.dex_file, target_method.index, adrp_label, &app_image_method_patches_);
+}
+
vixl::aarch64::Label* CodeGeneratorARM64::NewMethodBssEntryPatch(
MethodReference target_method,
vixl::aarch64::Label* adrp_label) {
@@ -5456,6 +5477,7 @@ void CodeGeneratorARM64::EmitLinkerPatches(ArenaVector<linker::LinkerPatch>* lin
DCHECK(linker_patches->empty());
size_t size =
boot_image_method_patches_.size() +
+ app_image_method_patches_.size() +
method_bss_entry_patches_.size() +
boot_image_type_patches_.size() +
app_image_type_patches_.size() +
@@ -5481,6 +5503,7 @@ 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_method_patches_.empty());
DCHECK_IMPLIES(!GetCompilerOptions().IsAppImage(), app_image_type_patches_.empty());
if (GetCompilerOptions().IsBootImage()) {
EmitPcRelativeLinkerPatches<NoDexFileAdapter<linker::LinkerPatch::IntrinsicReferencePatch>>(
@@ -5488,6 +5511,8 @@ void CodeGeneratorARM64::EmitLinkerPatches(ArenaVector<linker::LinkerPatch>* lin
} else {
EmitPcRelativeLinkerPatches<NoDexFileAdapter<linker::LinkerPatch::BootImageRelRoPatch>>(
boot_image_other_patches_, linker_patches);
+ EmitPcRelativeLinkerPatches<linker::LinkerPatch::MethodAppImageRelRoPatch>(
+ app_image_method_patches_, linker_patches);
EmitPcRelativeLinkerPatches<linker::LinkerPatch::TypeAppImageRelRoPatch>(
app_image_type_patches_, linker_patches);
}
diff --git a/compiler/optimizing/code_generator_arm64.h b/compiler/optimizing/code_generator_arm64.h
index 11c130ce2d..fde9a4021d 100644
--- a/compiler/optimizing/code_generator_arm64.h
+++ b/compiler/optimizing/code_generator_arm64.h
@@ -838,6 +838,13 @@ class CodeGeneratorARM64 : public CodeGenerator {
vixl::aarch64::Label* NewBootImageMethodPatch(MethodReference target_method,
vixl::aarch64::Label* adrp_label = nullptr);
+ // Add a new app image method 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* NewAppImageMethodPatch(MethodReference target_method,
+ vixl::aarch64::Label* adrp_label = nullptr);
+
// Add a new .bss entry method 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`
@@ -1191,6 +1198,8 @@ class CodeGeneratorARM64 : public CodeGenerator {
// PC-relative method patch info for kBootImageLinkTimePcRelative.
ArenaDeque<PcRelativePatchInfo> boot_image_method_patches_;
+ // PC-relative method patch info for kAppImageRelRo.
+ ArenaDeque<PcRelativePatchInfo> app_image_method_patches_;
// PC-relative method patch info for kBssEntry.
ArenaDeque<PcRelativePatchInfo> method_bss_entry_patches_;
// PC-relative type patch info for kBootImageLinkTimePcRelative.
diff --git a/compiler/optimizing/code_generator_arm_vixl.cc b/compiler/optimizing/code_generator_arm_vixl.cc
index fb8f8c0153..34b3aad3d4 100644
--- a/compiler/optimizing/code_generator_arm_vixl.cc
+++ b/compiler/optimizing/code_generator_arm_vixl.cc
@@ -1944,6 +1944,7 @@ CodeGeneratorARMVIXL::CodeGeneratorARMVIXL(HGraph* graph,
move_resolver_(graph->GetAllocator(), this),
assembler_(graph->GetAllocator()),
boot_image_method_patches_(graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)),
+ app_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)),
@@ -9557,6 +9558,14 @@ void CodeGeneratorARMVIXL::LoadMethod(MethodLoadKind load_kind, Location temp, H
LoadBootImageRelRoEntry(RegisterFrom(temp), boot_image_offset);
break;
}
+ case MethodLoadKind::kAppImageRelRo: {
+ DCHECK(GetCompilerOptions().IsAppImage());
+ PcRelativePatchInfo* labels = NewAppImageMethodPatch(invoke->GetResolvedMethodReference());
+ vixl32::Register temp_reg = RegisterFrom(temp);
+ EmitMovwMovtPlaceholder(labels, temp_reg);
+ __ Ldr(temp_reg, MemOperand(temp_reg, /*offset=*/ 0));
+ break;
+ }
case MethodLoadKind::kBssEntry: {
PcRelativePatchInfo* labels = NewMethodBssEntryPatch(invoke->GetMethodReference());
vixl32::Register temp_reg = RegisterFrom(temp);
@@ -9746,6 +9755,12 @@ CodeGeneratorARMVIXL::PcRelativePatchInfo* CodeGeneratorARMVIXL::NewBootImageMet
target_method.dex_file, target_method.index, &boot_image_method_patches_);
}
+CodeGeneratorARMVIXL::PcRelativePatchInfo* CodeGeneratorARMVIXL::NewAppImageMethodPatch(
+ MethodReference target_method) {
+ return NewPcRelativePatch(
+ target_method.dex_file, target_method.index, &app_image_method_patches_);
+}
+
CodeGeneratorARMVIXL::PcRelativePatchInfo* CodeGeneratorARMVIXL::NewMethodBssEntryPatch(
MethodReference target_method) {
return NewPcRelativePatch(
@@ -9946,6 +9961,7 @@ void CodeGeneratorARMVIXL::EmitLinkerPatches(ArenaVector<linker::LinkerPatch>* l
DCHECK(linker_patches->empty());
size_t size =
/* MOVW+MOVT for each entry */ 2u * boot_image_method_patches_.size() +
+ /* MOVW+MOVT for each entry */ 2u * app_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() +
@@ -9970,6 +9986,7 @@ 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_method_patches_.empty());
DCHECK_IMPLIES(!GetCompilerOptions().IsAppImage(), app_image_type_patches_.empty());
if (GetCompilerOptions().IsBootImage()) {
EmitPcRelativeLinkerPatches<NoDexFileAdapter<linker::LinkerPatch::IntrinsicReferencePatch>>(
@@ -9977,6 +9994,8 @@ void CodeGeneratorARMVIXL::EmitLinkerPatches(ArenaVector<linker::LinkerPatch>* l
} else {
EmitPcRelativeLinkerPatches<NoDexFileAdapter<linker::LinkerPatch::BootImageRelRoPatch>>(
boot_image_other_patches_, linker_patches);
+ EmitPcRelativeLinkerPatches<linker::LinkerPatch::MethodAppImageRelRoPatch>(
+ app_image_method_patches_, linker_patches);
EmitPcRelativeLinkerPatches<linker::LinkerPatch::TypeAppImageRelRoPatch>(
app_image_type_patches_, linker_patches);
}
diff --git a/compiler/optimizing/code_generator_arm_vixl.h b/compiler/optimizing/code_generator_arm_vixl.h
index 00b5a69b1d..ea8ec7e485 100644
--- a/compiler/optimizing/code_generator_arm_vixl.h
+++ b/compiler/optimizing/code_generator_arm_vixl.h
@@ -716,6 +716,7 @@ class CodeGeneratorARMVIXL : public CodeGenerator {
PcRelativePatchInfo* NewBootImageIntrinsicPatch(uint32_t intrinsic_data);
PcRelativePatchInfo* NewBootImageRelRoPatch(uint32_t boot_image_offset);
PcRelativePatchInfo* NewBootImageMethodPatch(MethodReference target_method);
+ PcRelativePatchInfo* NewAppImageMethodPatch(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);
@@ -1035,6 +1036,8 @@ class CodeGeneratorARMVIXL : public CodeGenerator {
// PC-relative method patch info for kBootImageLinkTimePcRelative.
ArenaDeque<PcRelativePatchInfo> boot_image_method_patches_;
+ // PC-relative method patch info for kAppImageRelRo.
+ ArenaDeque<PcRelativePatchInfo> app_image_method_patches_;
// PC-relative method patch info for kBssEntry.
ArenaDeque<PcRelativePatchInfo> method_bss_entry_patches_;
// PC-relative type patch info for kBootImageLinkTimePcRelative.
diff --git a/compiler/optimizing/code_generator_riscv64.cc b/compiler/optimizing/code_generator_riscv64.cc
index 43f855a915..c2edce3d6d 100644
--- a/compiler/optimizing/code_generator_riscv64.cc
+++ b/compiler/optimizing/code_generator_riscv64.cc
@@ -5894,6 +5894,7 @@ CodeGeneratorRISCV64::CodeGeneratorRISCV64(HGraph* graph,
uint64_literals_(std::less<uint64_t>(),
graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)),
boot_image_method_patches_(graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)),
+ app_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)),
@@ -6546,6 +6547,12 @@ CodeGeneratorRISCV64::PcRelativePatchInfo* CodeGeneratorRISCV64::NewBootImageMet
target_method.dex_file, target_method.index, info_high, &boot_image_method_patches_);
}
+CodeGeneratorRISCV64::PcRelativePatchInfo* CodeGeneratorRISCV64::NewAppImageMethodPatch(
+ MethodReference target_method, const PcRelativePatchInfo* info_high) {
+ return NewPcRelativePatch(
+ target_method.dex_file, target_method.index, info_high, &app_image_method_patches_);
+}
+
CodeGeneratorRISCV64::PcRelativePatchInfo* CodeGeneratorRISCV64::NewMethodBssEntryPatch(
MethodReference target_method, const PcRelativePatchInfo* info_high) {
return NewPcRelativePatch(
@@ -6723,6 +6730,7 @@ void CodeGeneratorRISCV64::EmitLinkerPatches(ArenaVector<linker::LinkerPatch>* l
DCHECK(linker_patches->empty());
size_t size =
boot_image_method_patches_.size() +
+ app_image_method_patches_.size() +
method_bss_entry_patches_.size() +
boot_image_type_patches_.size() +
app_image_type_patches_.size() +
@@ -6746,6 +6754,7 @@ 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_method_patches_.empty());
DCHECK_IMPLIES(!GetCompilerOptions().IsAppImage(), app_image_type_patches_.empty());
if (GetCompilerOptions().IsBootImage()) {
EmitPcRelativeLinkerPatches<NoDexFileAdapter<linker::LinkerPatch::IntrinsicReferencePatch>>(
@@ -6753,6 +6762,8 @@ void CodeGeneratorRISCV64::EmitLinkerPatches(ArenaVector<linker::LinkerPatch>* l
} else {
EmitPcRelativeLinkerPatches<NoDexFileAdapter<linker::LinkerPatch::BootImageRelRoPatch>>(
boot_image_other_patches_, linker_patches);
+ EmitPcRelativeLinkerPatches<linker::LinkerPatch::MethodAppImageRelRoPatch>(
+ app_image_method_patches_, linker_patches);
EmitPcRelativeLinkerPatches<linker::LinkerPatch::TypeAppImageRelRoPatch>(
app_image_type_patches_, linker_patches);
}
@@ -6853,6 +6864,17 @@ void CodeGeneratorRISCV64::LoadMethod(MethodLoadKind load_kind, Location temp, H
LoadBootImageRelRoEntry(temp.AsRegister<XRegister>(), boot_image_offset);
break;
}
+ case MethodLoadKind::kAppImageRelRo: {
+ DCHECK(GetCompilerOptions().IsAppImage());
+ PcRelativePatchInfo* info_high =
+ NewAppImageMethodPatch(invoke->GetResolvedMethodReference());
+ EmitPcRelativeAuipcPlaceholder(info_high, temp.AsRegister<XRegister>());
+ PcRelativePatchInfo* info_low =
+ NewAppImageMethodPatch(invoke->GetResolvedMethodReference(), info_high);
+ EmitPcRelativeLwuPlaceholder(
+ info_low, temp.AsRegister<XRegister>(), temp.AsRegister<XRegister>());
+ break;
+ }
case MethodLoadKind::kBssEntry: {
PcRelativePatchInfo* info_high = NewMethodBssEntryPatch(invoke->GetMethodReference());
EmitPcRelativeAuipcPlaceholder(info_high, temp.AsRegister<XRegister>());
diff --git a/compiler/optimizing/code_generator_riscv64.h b/compiler/optimizing/code_generator_riscv64.h
index dcd36ffe67..588243e86d 100644
--- a/compiler/optimizing/code_generator_riscv64.h
+++ b/compiler/optimizing/code_generator_riscv64.h
@@ -578,6 +578,8 @@ class CodeGeneratorRISCV64 : public CodeGenerator {
const PcRelativePatchInfo* info_high = nullptr);
PcRelativePatchInfo* NewBootImageRelRoPatch(uint32_t boot_image_offset,
const PcRelativePatchInfo* info_high = nullptr);
+ PcRelativePatchInfo* NewAppImageMethodPatch(MethodReference target_method,
+ const PcRelativePatchInfo* info_high = nullptr);
PcRelativePatchInfo* NewBootImageMethodPatch(MethodReference target_method,
const PcRelativePatchInfo* info_high = nullptr);
PcRelativePatchInfo* NewMethodBssEntryPatch(MethodReference target_method,
@@ -817,6 +819,8 @@ class CodeGeneratorRISCV64 : public CodeGenerator {
// PC-relative method patch info for kBootImageLinkTimePcRelative.
ArenaDeque<PcRelativePatchInfo> boot_image_method_patches_;
+ // PC-relative method patch info for kAppImageRelRo.
+ ArenaDeque<PcRelativePatchInfo> app_image_method_patches_;
// PC-relative method patch info for kBssEntry.
ArenaDeque<PcRelativePatchInfo> method_bss_entry_patches_;
// PC-relative type patch info for kBootImageLinkTimePcRelative.
diff --git a/compiler/optimizing/code_generator_x86.cc b/compiler/optimizing/code_generator_x86.cc
index 7e3c6216eb..d0368be866 100644
--- a/compiler/optimizing/code_generator_x86.cc
+++ b/compiler/optimizing/code_generator_x86.cc
@@ -1171,6 +1171,7 @@ CodeGeneratorX86::CodeGeneratorX86(HGraph* graph,
assembler_(graph->GetAllocator(),
compiler_options.GetInstructionSetFeatures()->AsX86InstructionSetFeatures()),
boot_image_method_patches_(graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)),
+ app_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)),
@@ -5550,6 +5551,13 @@ void CodeGeneratorX86::LoadMethod(MethodLoadKind load_kind, Location temp, HInvo
GetBootImageOffset(invoke));
break;
}
+ case MethodLoadKind::kAppImageRelRo: {
+ DCHECK(GetCompilerOptions().IsAppImage());
+ Register base_reg = GetInvokeExtraParameter(invoke, temp.AsRegister<Register>());
+ __ movl(temp.AsRegister<Register>(), Address(base_reg, kPlaceholder32BitOffset));
+ RecordAppImageMethodPatch(invoke);
+ break;
+ }
case MethodLoadKind::kBssEntry: {
Register base_reg = GetInvokeExtraParameter(invoke, temp.AsRegister<Register>());
__ movl(temp.AsRegister<Register>(), Address(base_reg, kPlaceholder32BitOffset));
@@ -5739,6 +5747,19 @@ void CodeGeneratorX86::RecordBootImageMethodPatch(HInvoke* invoke) {
__ Bind(&boot_image_method_patches_.back().label);
}
+void CodeGeneratorX86::RecordAppImageMethodPatch(HInvoke* invoke) {
+ size_t index = invoke->IsInvokeInterface()
+ ? invoke->AsInvokeInterface()->GetSpecialInputIndex()
+ : invoke->AsInvokeStaticOrDirect()->GetSpecialInputIndex();
+ HX86ComputeBaseMethodAddress* method_address =
+ invoke->InputAt(index)->AsX86ComputeBaseMethodAddress();
+ app_image_method_patches_.emplace_back(
+ method_address,
+ invoke->GetResolvedMethodReference().dex_file,
+ invoke->GetResolvedMethodReference().index);
+ __ Bind(&app_image_method_patches_.back().label);
+}
+
void CodeGeneratorX86::RecordMethodBssEntryPatch(HInvoke* invoke) {
size_t index = invoke->IsInvokeInterface()
? invoke->AsInvokeInterface()->GetSpecialInputIndex()
@@ -5900,6 +5921,7 @@ void CodeGeneratorX86::EmitLinkerPatches(ArenaVector<linker::LinkerPatch>* linke
DCHECK(linker_patches->empty());
size_t size =
boot_image_method_patches_.size() +
+ app_image_method_patches_.size() +
method_bss_entry_patches_.size() +
boot_image_type_patches_.size() +
app_image_type_patches_.size() +
@@ -5923,6 +5945,7 @@ 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_method_patches_.empty());
DCHECK_IMPLIES(!GetCompilerOptions().IsAppImage(), app_image_type_patches_.empty());
if (GetCompilerOptions().IsBootImage()) {
EmitPcRelativeLinkerPatches<NoDexFileAdapter<linker::LinkerPatch::IntrinsicReferencePatch>>(
@@ -5930,6 +5953,8 @@ void CodeGeneratorX86::EmitLinkerPatches(ArenaVector<linker::LinkerPatch>* linke
} else {
EmitPcRelativeLinkerPatches<NoDexFileAdapter<linker::LinkerPatch::BootImageRelRoPatch>>(
boot_image_other_patches_, linker_patches);
+ EmitPcRelativeLinkerPatches<linker::LinkerPatch::MethodAppImageRelRoPatch>(
+ app_image_method_patches_, linker_patches);
EmitPcRelativeLinkerPatches<linker::LinkerPatch::TypeAppImageRelRoPatch>(
app_image_type_patches_, linker_patches);
}
diff --git a/compiler/optimizing/code_generator_x86.h b/compiler/optimizing/code_generator_x86.h
index 321ee92e2e..fae6c7f801 100644
--- a/compiler/optimizing/code_generator_x86.h
+++ b/compiler/optimizing/code_generator_x86.h
@@ -548,6 +548,7 @@ class CodeGeneratorX86 : public CodeGenerator {
void RecordBootImageRelRoPatch(HX86ComputeBaseMethodAddress* method_address,
uint32_t boot_image_offset);
void RecordBootImageMethodPatch(HInvoke* invoke);
+ void RecordAppImageMethodPatch(HInvoke* invoke);
void RecordMethodBssEntryPatch(HInvoke* invoke);
void RecordBootImageTypePatch(HLoadClass* load_class);
void RecordAppImageTypePatch(HLoadClass* load_class);
@@ -783,6 +784,8 @@ class CodeGeneratorX86 : public CodeGenerator {
// PC-relative method patch info for kBootImageLinkTimePcRelative.
ArenaDeque<X86PcRelativePatchInfo> boot_image_method_patches_;
+ // PC-relative method patch info for kAppImageRelRo.
+ ArenaDeque<X86PcRelativePatchInfo> app_image_method_patches_;
// PC-relative method patch info for kBssEntry.
ArenaDeque<X86PcRelativePatchInfo> method_bss_entry_patches_;
// PC-relative type patch info for kBootImageLinkTimePcRelative.
diff --git a/compiler/optimizing/code_generator_x86_64.cc b/compiler/optimizing/code_generator_x86_64.cc
index 51ded684c6..6d3acedb5d 100644
--- a/compiler/optimizing/code_generator_x86_64.cc
+++ b/compiler/optimizing/code_generator_x86_64.cc
@@ -1142,6 +1142,13 @@ void CodeGeneratorX86_64::LoadMethod(MethodLoadKind load_kind, Location temp, HI
RecordBootImageRelRoPatch(GetBootImageOffset(invoke));
break;
}
+ case MethodLoadKind::kAppImageRelRo: {
+ DCHECK(GetCompilerOptions().IsAppImage());
+ __ movl(temp.AsRegister<CpuRegister>(),
+ Address::Absolute(CodeGeneratorX86_64::kPlaceholder32BitOffset, /* no_rip= */ false));
+ RecordAppImageMethodPatch(invoke);
+ break;
+ }
case MethodLoadKind::kBssEntry: {
__ movq(temp.AsRegister<CpuRegister>(),
Address::Absolute(kPlaceholder32BitOffset, /* no_rip= */ false));
@@ -1312,6 +1319,12 @@ void CodeGeneratorX86_64::RecordBootImageMethodPatch(HInvoke* invoke) {
__ Bind(&boot_image_method_patches_.back().label);
}
+void CodeGeneratorX86_64::RecordAppImageMethodPatch(HInvoke* invoke) {
+ app_image_method_patches_.emplace_back(invoke->GetResolvedMethodReference().dex_file,
+ invoke->GetResolvedMethodReference().index);
+ __ Bind(&app_image_method_patches_.back().label);
+}
+
void CodeGeneratorX86_64::RecordMethodBssEntryPatch(HInvoke* invoke) {
DCHECK(IsSameDexFile(GetGraph()->GetDexFile(), *invoke->GetMethodReference().dex_file) ||
GetCompilerOptions().WithinOatFile(invoke->GetMethodReference().dex_file) ||
@@ -1452,6 +1465,7 @@ void CodeGeneratorX86_64::EmitLinkerPatches(ArenaVector<linker::LinkerPatch>* li
DCHECK(linker_patches->empty());
size_t size =
boot_image_method_patches_.size() +
+ app_image_method_patches_.size() +
method_bss_entry_patches_.size() +
boot_image_type_patches_.size() +
app_image_type_patches_.size() +
@@ -1476,6 +1490,7 @@ 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_method_patches_.empty());
DCHECK_IMPLIES(!GetCompilerOptions().IsAppImage(), app_image_type_patches_.empty());
if (GetCompilerOptions().IsBootImage()) {
EmitPcRelativeLinkerPatches<NoDexFileAdapter<linker::LinkerPatch::IntrinsicReferencePatch>>(
@@ -1483,6 +1498,8 @@ void CodeGeneratorX86_64::EmitLinkerPatches(ArenaVector<linker::LinkerPatch>* li
} else {
EmitPcRelativeLinkerPatches<NoDexFileAdapter<linker::LinkerPatch::BootImageRelRoPatch>>(
boot_image_other_patches_, linker_patches);
+ EmitPcRelativeLinkerPatches<linker::LinkerPatch::MethodAppImageRelRoPatch>(
+ app_image_method_patches_, linker_patches);
EmitPcRelativeLinkerPatches<linker::LinkerPatch::TypeAppImageRelRoPatch>(
app_image_type_patches_, linker_patches);
}
@@ -1615,6 +1632,7 @@ CodeGeneratorX86_64::CodeGeneratorX86_64(HGraph* graph,
compiler_options.GetInstructionSetFeatures()->AsX86_64InstructionSetFeatures()),
constant_area_start_(0),
boot_image_method_patches_(graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)),
+ app_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)),
diff --git a/compiler/optimizing/code_generator_x86_64.h b/compiler/optimizing/code_generator_x86_64.h
index b3eb1a0373..3024116402 100644
--- a/compiler/optimizing/code_generator_x86_64.h
+++ b/compiler/optimizing/code_generator_x86_64.h
@@ -542,6 +542,7 @@ class CodeGeneratorX86_64 : public CodeGenerator {
void RecordBootImageIntrinsicPatch(uint32_t intrinsic_data);
void RecordBootImageRelRoPatch(uint32_t boot_image_offset);
void RecordBootImageMethodPatch(HInvoke* invoke);
+ void RecordAppImageMethodPatch(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);
@@ -750,6 +751,8 @@ class CodeGeneratorX86_64 : public CodeGenerator {
// PC-relative method patch info for kBootImageLinkTimePcRelative.
ArenaDeque<PatchInfo<Label>> boot_image_method_patches_;
+ // PC-relative method patch info for kAppImageRelRo.
+ ArenaDeque<PatchInfo<Label>> app_image_method_patches_;
// PC-relative method patch info for kBssEntry.
ArenaDeque<PatchInfo<Label>> method_bss_entry_patches_;
// PC-relative type patch info for kBootImageLinkTimePcRelative.
diff --git a/compiler/optimizing/nodes.h b/compiler/optimizing/nodes.h
index 5a23c8b2a8..7ed4323384 100644
--- a/compiler/optimizing/nodes.h
+++ b/compiler/optimizing/nodes.h
@@ -4537,6 +4537,10 @@ enum class MethodLoadKind {
// Used for app->boot calls with relocatable image.
kBootImageRelRo,
+ // Load from an app image entry in the .data.img.rel.ro using a PC-relative load.
+ // Used for app image methods referenced by apps in AOT-compiled code.
+ kAppImageRelRo,
+
// Load from an entry in the .bss section using a PC-relative load.
// Used for methods outside boot image referenced by AOT-compiled app and boot image code.
kBssEntry,
@@ -4569,6 +4573,7 @@ enum class CodePtrLocation {
static inline bool IsPcRelativeMethodLoadKind(MethodLoadKind load_kind) {
return load_kind == MethodLoadKind::kBootImageLinkTimePcRelative ||
load_kind == MethodLoadKind::kBootImageRelRo ||
+ load_kind == MethodLoadKind::kAppImageRelRo ||
load_kind == MethodLoadKind::kBssEntry;
}
diff --git a/compiler/optimizing/sharpening.cc b/compiler/optimizing/sharpening.cc
index 1b6a9fb601..75efb19722 100644
--- a/compiler/optimizing/sharpening.cc
+++ b/compiler/optimizing/sharpening.cc
@@ -48,8 +48,10 @@ static bool IsInBootImage(ArtMethod* method) {
return heap->IsBootImageAddress(method);
}
-static bool BootImageAOTCanEmbedMethod(ArtMethod* method, const CompilerOptions& compiler_options) {
- DCHECK(compiler_options.IsBootImage() || compiler_options.IsBootImageExtension());
+static bool ImageAOTCanEmbedMethod(ArtMethod* method, const CompilerOptions& compiler_options) {
+ DCHECK(compiler_options.IsBootImage() ||
+ compiler_options.IsBootImageExtension() ||
+ compiler_options.IsAppImage());
ScopedObjectAccess soa(Thread::Current());
ObjPtr<mirror::Class> klass = method->GetDeclaringClass();
DCHECK(klass != nullptr);
@@ -103,7 +105,7 @@ HInvokeStaticOrDirect::DispatchInfo HSharpening::SharpenLoadMethod(
} else if (IsInBootImage(callee)) {
DCHECK(compiler_options.IsBootImageExtension());
method_load_kind = MethodLoadKind::kBootImageRelRo;
- } else if (BootImageAOTCanEmbedMethod(callee, compiler_options)) {
+ } else if (ImageAOTCanEmbedMethod(callee, compiler_options)) {
method_load_kind = MethodLoadKind::kBootImageLinkTimePcRelative;
} else if (!has_method_id) {
method_load_kind = MethodLoadKind::kRuntimeCall;
@@ -135,8 +137,13 @@ HInvokeStaticOrDirect::DispatchInfo HSharpening::SharpenLoadMethod(
code_ptr_location = CodePtrLocation::kCallArtMethod;
} else {
DCHECK(!callee->IsCopied());
- // Use PC-relative access to the .bss methods array.
- method_load_kind = MethodLoadKind::kBssEntry;
+ if (compiler_options.IsAppImage() && ImageAOTCanEmbedMethod(callee, compiler_options)) {
+ // Use PC-relative access to the .data.img.rel.ro app image methods array.
+ method_load_kind = MethodLoadKind::kAppImageRelRo;
+ } else {
+ // Use PC-relative access to the .bss methods array.
+ method_load_kind = MethodLoadKind::kBssEntry;
+ }
code_ptr_location = CodePtrLocation::kCallArtMethod;
}
diff --git a/dex2oat/linker/arm64/relative_patcher_arm64.cc b/dex2oat/linker/arm64/relative_patcher_arm64.cc
index 2956285545..ed700d0fd7 100644
--- a/dex2oat/linker/arm64/relative_patcher_arm64.cc
+++ b/dex2oat/linker/arm64/relative_patcher_arm64.cc
@@ -63,6 +63,7 @@ inline bool IsAdrpPatch(const LinkerPatch& patch) {
case LinkerPatch::Type::kIntrinsicReference:
case LinkerPatch::Type::kBootImageRelRo:
case LinkerPatch::Type::kMethodRelative:
+ case LinkerPatch::Type::kMethodAppImageRelRo:
case LinkerPatch::Type::kMethodBssEntry:
case LinkerPatch::Type::kJniEntrypointRelative:
case LinkerPatch::Type::kTypeRelative:
@@ -273,6 +274,7 @@ void Arm64RelativePatcher::PatchPcRelativeReference(std::vector<uint8_t>* code,
} else {
// LDR/STR 32-bit or 64-bit with imm12 == 0 (unset).
DCHECK(patch.GetType() == LinkerPatch::Type::kBootImageRelRo ||
+ patch.GetType() == LinkerPatch::Type::kMethodAppImageRelRo ||
patch.GetType() == LinkerPatch::Type::kMethodBssEntry ||
patch.GetType() == LinkerPatch::Type::kJniEntrypointRelative ||
patch.GetType() == LinkerPatch::Type::kTypeAppImageRelRo ||
diff --git a/dex2oat/linker/image_writer.cc b/dex2oat/linker/image_writer.cc
index f507fe1f38..179a0bb4f7 100644
--- a/dex2oat/linker/image_writer.cc
+++ b/dex2oat/linker/image_writer.cc
@@ -2873,7 +2873,7 @@ void ImageWriter::CreateHeader(size_t oat_index, size_t component_count) {
target_ptr_size_);
}
-ArtMethod* ImageWriter::GetImageMethodAddress(ArtMethod* method) {
+ArtMethod* ImageWriter::GetImageMethodAddress(ArtMethod* method) const {
NativeObjectRelocation relocation = GetNativeRelocation(method);
const ImageInfo& image_info = GetImageInfo(relocation.oat_index);
CHECK_GE(relocation.offset, image_info.image_end_) << "ArtMethods should be after Objects";
@@ -3299,7 +3299,7 @@ class ImageWriter::FixupClassVisitor final : public FixupVisitor {
}
};
-ImageWriter::NativeObjectRelocation ImageWriter::GetNativeRelocation(void* obj) {
+ImageWriter::NativeObjectRelocation ImageWriter::GetNativeRelocation(void* obj) const {
DCHECK(obj != nullptr);
DCHECK(!IsInBootImage(obj));
auto it = native_object_relocations_.find(obj);
diff --git a/dex2oat/linker/image_writer.h b/dex2oat/linker/image_writer.h
index efe8fa2304..9364e09521 100644
--- a/dex2oat/linker/image_writer.h
+++ b/dex2oat/linker/image_writer.h
@@ -128,6 +128,10 @@ class ImageWriter final {
}
}
+ uint32_t GetGlobalImageOffset(ArtMethod* method) const REQUIRES_SHARED(Locks::mutator_lock_) {
+ return reinterpret_cast<uint8_t*>(GetImageMethodAddress(method)) - global_image_begin_;
+ }
+
uint32_t GetGlobalImageOffset(mirror::Object* object) const REQUIRES_SHARED(Locks::mutator_lock_) {
DCHECK(object != nullptr);
DCHECK(!IsInBootImage(object));
@@ -137,7 +141,7 @@ class ImageWriter final {
image_info.image_begin_ + GetImageOffset(object, oat_index) - global_image_begin_);
}
- ArtMethod* GetImageMethodAddress(ArtMethod* method) REQUIRES_SHARED(Locks::mutator_lock_);
+ ArtMethod* GetImageMethodAddress(ArtMethod* method) const REQUIRES_SHARED(Locks::mutator_lock_);
const void* GetIntrinsicReferenceAddress(uint32_t intrinsic_data)
REQUIRES_SHARED(Locks::mutator_lock_);
@@ -552,7 +556,7 @@ class ImageWriter final {
uintptr_t offset;
};
- NativeObjectRelocation GetNativeRelocation(void* obj) REQUIRES_SHARED(Locks::mutator_lock_);
+ NativeObjectRelocation GetNativeRelocation(void* obj) const REQUIRES_SHARED(Locks::mutator_lock_);
// Location of where the object will be when the image is loaded at runtime.
template <typename T>
diff --git a/dex2oat/linker/oat_writer.cc b/dex2oat/linker/oat_writer.cc
index 4a3e2837bd..76326b472b 100644
--- a/dex2oat/linker/oat_writer.cc
+++ b/dex2oat/linker/oat_writer.cc
@@ -105,7 +105,7 @@ const UnalignedDexFileHeader* AsUnalignedDexFileHeader(const uint8_t* raw_data)
inline uint32_t CodeAlignmentSize(uint32_t header_offset, const CompiledMethod& compiled_method) {
// We want to align the code rather than the preheader.
uint32_t unaligned_code_offset = header_offset + sizeof(OatQuickMethodHeader);
- uint32_t aligned_code_offset = compiled_method.AlignCode(unaligned_code_offset);
+ uint32_t aligned_code_offset = compiled_method.AlignCode(unaligned_code_offset);
return aligned_code_offset - unaligned_code_offset;
}
@@ -372,6 +372,12 @@ OatWriter::OatWriter(const CompilerOptions& compiler_options,
bss_roots_offset_(0u),
boot_image_rel_ro_entries_(),
bss_method_entry_references_(),
+ bss_type_entry_references_(),
+ bss_public_type_entry_references_(),
+ bss_package_type_entry_references_(),
+ bss_string_entry_references_(),
+ bss_method_type_entry_references_(),
+ app_image_rel_ro_method_entries_(),
bss_method_entries_(),
app_image_rel_ro_type_entries_(),
bss_type_entries_(),
@@ -739,6 +745,9 @@ class OatWriter::InitBssLayoutMethodVisitor : public DexMethodVisitor {
if (patch.GetType() == LinkerPatch::Type::kBootImageRelRo) {
writer_->boot_image_rel_ro_entries_.Overwrite(patch.BootImageOffset(),
/* placeholder */ 0u);
+ } else if (patch.GetType() == LinkerPatch::Type::kMethodAppImageRelRo) {
+ MethodReference target_method = patch.TargetMethod();
+ writer_->app_image_rel_ro_method_entries_.Overwrite(target_method, /* placeholder */ 0u);
} else if (patch.GetType() == LinkerPatch::Type::kMethodBssEntry) {
MethodReference target_method = patch.TargetMethod();
AddBssReference(target_method,
@@ -1687,6 +1696,16 @@ class OatWriter::WriteCodeMethodVisitor : public OrderedMethodVisitor {
target_offset);
break;
}
+ case LinkerPatch::Type::kMethodAppImageRelRo: {
+ uint32_t target_offset =
+ writer_->data_img_rel_ro_start_ +
+ writer_->app_image_rel_ro_method_entries_.Get(patch.TargetMethod());
+ writer_->relative_patcher_->PatchPcRelativeReference(&patched_code_,
+ patch,
+ offset_ + literal_offset,
+ target_offset);
+ break;
+ }
case LinkerPatch::Type::kMethodTypeBssEntry: {
uint32_t target_offset =
writer_->bss_start_ + writer_->bss_method_type_entries_.Get(patch.TargetProto());
@@ -2367,7 +2386,9 @@ 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() && app_image_rel_ro_type_entries_.empty()) {
+ if (boot_image_rel_ro_entries_.empty() &&
+ app_image_rel_ro_method_entries_.empty() &&
+ app_image_rel_ro_type_entries_.empty()) {
// Nothing to put to the .data.img.rel.ro section.
return offset;
}
@@ -2382,6 +2403,12 @@ size_t OatWriter::InitDataImgRelRoLayout(size_t offset) {
data_img_rel_ro_app_image_offset_ = data_img_rel_ro_size_;
+ for (auto& entry : app_image_rel_ro_method_entries_) {
+ size_t& entry_offset = entry.second;
+ entry_offset = data_img_rel_ro_size_;
+ data_img_rel_ro_size_ += sizeof(uint32_t);
+ }
+
for (auto& entry : app_image_rel_ro_type_entries_) {
size_t& entry_offset = entry.second;
entry_offset = data_img_rel_ro_size_;
@@ -3188,31 +3215,46 @@ 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() && app_image_rel_ro_type_entries_.empty()) {
+ size_t size = boot_image_rel_ro_entries_.size() +
+ app_image_rel_ro_method_entries_.size() +
+ app_image_rel_ro_type_entries_.size();
+ if (size == 0u) {
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() + app_image_rel_ro_type_entries_.size());
+ data.reserve(size);
for (const auto& entry : boot_image_rel_ro_entries_) {
uint32_t boot_image_offset = entry.first;
data.push_back(boot_image_offset);
}
- if (!app_image_rel_ro_type_entries_.empty()) {
+ if (!app_image_rel_ro_method_entries_.empty() || !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);
+ auto update_for_dex_file = [&](const DexFile* dex_file) REQUIRES_SHARED(Locks::mutator_lock_) {
+ if (dex_file != last_dex_file) {
+ dex_cache = class_linker->FindDexCache(soa.Self(), *dex_file);
class_loader = dex_cache->GetClassLoader();
- last_dex_file = target_type.dex_file;
+ last_dex_file = dex_file;
}
+ };
+ for (const auto& entry : app_image_rel_ro_method_entries_) {
+ MethodReference target_method = entry.first;
+ update_for_dex_file(target_method.dex_file);
+ ArtMethod* method =
+ class_linker->LookupResolvedMethod(target_method.index, dex_cache, class_loader);
+ CHECK(method != nullptr);
+ uint32_t app_image_offset = image_writer_->GetGlobalImageOffset(method);
+ data.push_back(app_image_offset);
+ }
+ for (const auto& entry : app_image_rel_ro_type_entries_) {
+ TypeReference target_type = entry.first;
+ update_for_dex_file(target_type.dex_file);
ObjPtr<mirror::Class> type =
class_linker->LookupResolvedType(target_type.TypeIndex(), dex_cache, class_loader);
CHECK(type != nullptr);
@@ -3220,7 +3262,7 @@ size_t OatWriter::WriteDataImgRelRo(OutputStream* out,
data.push_back(app_image_offset);
}
}
- DCHECK_EQ(data.size(), boot_image_rel_ro_entries_.size() + app_image_rel_ro_type_entries_.size());
+ DCHECK_EQ(data.size(), 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 129a791982..c985812f94 100644
--- a/dex2oat/linker/oat_writer.h
+++ b/dex2oat/linker/oat_writer.h
@@ -457,6 +457,12 @@ class OatWriter {
// Map for recording references to GcRoot<mirror::MethodType> entries in .bss.
SafeMap<const DexFile*, BitVector> bss_method_type_entry_references_;
+ // Map for allocating app image ArtMethod entries in .data.img.rel.ro. Indexed by MethodReference
+ // for the target method in the dex file with the "method reference value comparator" for
+ // deduplication. The value is the target offset for patching, starting at
+ // `data_img_rel_ro_start_`.
+ SafeMap<MethodReference, size_t, MethodReferenceValueComparator> app_image_rel_ro_method_entries_;
+
// Map for allocating ArtMethod entries in .bss. Indexed by MethodReference for the target
// method in the dex file with the "method reference value comparator" for deduplication.
// The value is the target offset for patching, starting at `bss_start_ + bss_methods_offset_`.
diff --git a/runtime/oat/oat.h b/runtime/oat/oat.h
index fa50571b27..d38d50c37c 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: Adding new entrypoints for InvokeExact intrisic.
- static constexpr std::array<uint8_t, 4> kOatVersion{{'2', '4', '7', '\0'}};
+ // Last oat version changed reason: Implement `MethodLoadKind::kAppImageRelRo`.
+ static constexpr std::array<uint8_t, 4> kOatVersion{{'2', '4', '8', '\0'}};
static constexpr const char* kDex2OatCmdLineKey = "dex2oat-cmdline";
static constexpr const char* kDebuggableKey = "debuggable";
diff --git a/test/552-checker-sharpening/profile b/test/552-checker-sharpening/profile
new file mode 100644
index 0000000000..e883f017e4
--- /dev/null
+++ b/test/552-checker-sharpening/profile
@@ -0,0 +1,15 @@
+LAppImageClass;
+HSPLMain;->testSimple(I)I
+HSPLMain;->testSimpleAppImage(I)I
+HSPLMain;->testDiamond(ZI)I
+HSPLMain;->testLoop([II)I
+HSPLMain;->testLoopWithDiamond([IZI)I
+HSPLMain;->$noinline$getBootImageString()Ljava/lang/String;
+HSPLMain;->$noinline$getNonBootImageString()Ljava/lang/String;
+HSPLMain;->$noinline$getStringClass()Ljava/lang/Class;
+HSPLMain;->$noinline$getOtherClass()Ljava/lang/Class;
+HSPLMain;->$noinline$getAppImageClass()Ljava/lang/Class;
+HSPLMain;->$noinline$toHexString(I)Ljava/lang/String;
+HSPLMain;->$noinline$toHexStringIndirect(I)Ljava/lang/String;
+HSPLMain;->$noinline$foo()V
+HSPLMulti;->localToHexString()Ljava/lang/String;
diff --git a/test/552-checker-sharpening/run.py b/test/552-checker-sharpening/run.py
new file mode 100644
index 0000000000..1a893fbb1c
--- /dev/null
+++ b/test/552-checker-sharpening/run.py
@@ -0,0 +1,20 @@
+#!/bin/bash
+#
+# Copyright (C) 2024 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+
+def run(ctx, args):
+ # Use a profile to put specific classes in the app image.
+ ctx.default_run(args, profile=True)
diff --git a/test/552-checker-sharpening/src/Main.java b/test/552-checker-sharpening/src/Main.java
index b017ab024b..730c1c800a 100644
--- a/test/552-checker-sharpening/src/Main.java
+++ b/test/552-checker-sharpening/src/Main.java
@@ -38,7 +38,7 @@ public class Main {
return x;
}
- /// CHECK-START-{ARM,ARM64,X86,X86_64}: int Main.testSimple(int) builder (after)
+ /// CHECK-START-{ARM,ARM64,X86,X86_64,RISCV64}: int Main.testSimple(int) builder (after)
/// CHECK: InvokeStaticOrDirect method_load_kind:BssEntry
/// CHECK-START-X86: int Main.testSimple(int) pc_relative_fixups_x86 (before)
@@ -53,7 +53,22 @@ public class Main {
return $noinline$foo(x);
}
- /// CHECK-START-{ARM,ARM64,X86,X86_64}: int Main.testDiamond(boolean, int) builder (after)
+ /// CHECK-START-{ARM,ARM64,X86,X86_64,RISCV64}: int Main.testSimpleAppImage(int) builder (after)
+ /// CHECK: InvokeStaticOrDirect method_load_kind:AppImageRelRo
+
+ /// CHECK-START-X86: int Main.testSimpleAppImage(int) pc_relative_fixups_x86 (before)
+ /// CHECK-NOT: X86ComputeBaseMethodAddress
+
+ /// CHECK-START-X86: int Main.testSimpleAppImage(int) pc_relative_fixups_x86 (after)
+ /// CHECK: X86ComputeBaseMethodAddress
+ /// CHECK-NOT: X86ComputeBaseMethodAddress
+
+ public static int testSimpleAppImage(int x) {
+ // This call should use PC-relative .data.img.rel.ro array load to retrieve the target method.
+ return AppImageClass.$noinline$foo(x);
+ }
+
+ /// CHECK-START-{ARM,ARM64,X86,X86_64,RISCV64}: int Main.testDiamond(boolean, int) builder (after)
/// CHECK: InvokeStaticOrDirect method_load_kind:BssEntry
/// CHECK: InvokeStaticOrDirect method_load_kind:BssEntry
@@ -128,7 +143,7 @@ public class Main {
return x;
}
- /// CHECK-START-{ARM,ARM64,X86,X86_64}: java.lang.String Main.$noinline$getBootImageString() builder (after)
+ /// CHECK-START-{ARM,ARM64,X86,X86_64,RISCV64}: java.lang.String Main.$noinline$getBootImageString() builder (after)
/// CHECK: LoadString load_kind:BootImageRelRo
public static String $noinline$getBootImageString() {
@@ -136,7 +151,7 @@ public class Main {
return "";
}
- /// CHECK-START-{ARM,ARM64,X86,X86_64}: java.lang.String Main.$noinline$getNonBootImageString() builder (after)
+ /// CHECK-START-{ARM,ARM64,X86,X86_64,RISCV64}: java.lang.String Main.$noinline$getNonBootImageString() builder (after)
/// CHECK: LoadString load_kind:BssEntry
/// CHECK-START-X86: java.lang.String Main.$noinline$getNonBootImageString() pc_relative_fixups_x86 (before)
@@ -151,7 +166,7 @@ public class Main {
return "non-boot-image-string";
}
- /// CHECK-START-{ARM,ARM64,X86,X86_64}: java.lang.Class Main.$noinline$getStringClass() builder (after)
+ /// CHECK-START-{ARM,ARM64,X86,X86_64,RISCV64}: java.lang.Class Main.$noinline$getStringClass() builder (after)
/// CHECK: LoadClass load_kind:BootImageRelRo class_name:java.lang.String
public static Class<?> $noinline$getStringClass() {
@@ -159,7 +174,7 @@ public class Main {
return String.class;
}
- /// CHECK-START-{ARM,ARM64,X86,X86_64}: java.lang.Class Main.$noinline$getOtherClass() builder (after)
+ /// CHECK-START-{ARM,ARM64,X86,X86_64,RISCV64}: java.lang.Class Main.$noinline$getOtherClass() builder (after)
/// CHECK: LoadClass load_kind:BssEntry class_name:Other
/// CHECK-START-X86: java.lang.Class Main.$noinline$getOtherClass() pc_relative_fixups_x86 (before)
@@ -170,17 +185,32 @@ public class Main {
/// CHECK-DAG: LoadClass load_kind:BssEntry class_name:Other
public static Class<?> $noinline$getOtherClass() {
- // Other class is not in the boot image.
+ // Other class is neither in the boot image nor in the app image.
return Other.class;
}
- /// CHECK-START-{ARM,ARM64,X86,X86_64}: java.lang.String Main.$noinline$toHexString(int) builder (after)
+ /// CHECK-START-{ARM,ARM64,X86,X86_64,RISCV64}: java.lang.Class Main.$noinline$getAppImageClass() builder (after)
+ /// CHECK: LoadClass load_kind:AppImageRelRo class_name:AppImageClass
+
+ /// CHECK-START-X86: java.lang.Class Main.$noinline$getAppImageClass() pc_relative_fixups_x86 (before)
+ /// CHECK-NOT: X86ComputeBaseMethodAddress
+
+ /// CHECK-START-X86: java.lang.Class Main.$noinline$getAppImageClass() pc_relative_fixups_x86 (after)
+ /// CHECK-DAG: X86ComputeBaseMethodAddress
+ /// CHECK-DAG: LoadClass load_kind:AppImageRelRo class_name:AppImageClass
+
+ public static Class<?> $noinline$getAppImageClass() {
+ // AppImageClass class is in the app image.
+ return AppImageClass.class;
+ }
+
+ /// CHECK-START-{ARM,ARM64,X86,X86_64,RISCV64}: java.lang.String Main.$noinline$toHexString(int) builder (after)
/// CHECK: InvokeStaticOrDirect method_load_kind:BootImageRelRo
public static String $noinline$toHexString(int value) {
return Integer.toString(value, 16);
}
- /// CHECK-START-{ARM,ARM64,X86,X86_64}: java.lang.String Main.$noinline$toHexStringIndirect(int) builder (after)
+ /// CHECK-START-{ARM,ARM64,X86,X86_64,RISCV64}: java.lang.String Main.$noinline$toHexStringIndirect(int) builder (after)
/// CHECK: InvokeStaticOrDirect method_load_kind:BssEntry
/// CHECK-START-X86: java.lang.String Main.$noinline$toHexStringIndirect(int) pc_relative_fixups_x86 (before)
@@ -195,6 +225,7 @@ public class Main {
public static void main(String[] args) {
assertIntEquals(1, testSimple(1));
+ assertIntEquals(1, testSimpleAppImage(1));
assertIntEquals(1, testDiamond(false, 1));
assertIntEquals(-1, testDiamond(true, 1));
assertIntEquals(3, testLoop(new int[]{ 2 }, 1));
@@ -211,6 +242,12 @@ public class Main {
}
}
+class AppImageClass {
+ public static int $noinline$foo(int x) {
+ return x;
+ }
+}
+
class Other {
}