diff options
author | 2024-10-31 17:38:03 +0100 | |
---|---|---|
committer | 2024-11-05 13:54:34 +0000 | |
commit | 4d6fdd9fb379ac6e3575c3ec5406d808e0290636 (patch) | |
tree | cd7c157f6ca93745672901a3fafc33a9426c70fe | |
parent | 389f84b5c45cb58255ebcc44758f04adc37dd5b6 (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
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 { } |