From 3f0981b56a1b9a415383c552c063b890c840b13e Mon Sep 17 00:00:00 2001 From: Almaz Mingaleev Date: Fri, 15 Dec 2023 15:47:22 +0000 Subject: Revert^2 "x86_64: Store resolved MethodType-s in .bss." This reverts commit d014fd019e84471665ac02f2de285541009892cd. Reason for revert: fix codegen to do runtime call in JIT for now. Bug: 297147201 Test: ./art/test/testrunner/testrunner.py --host --64 --optimizing -b Test: ./art/test/testrunner/testrunner.py --jvm -b Test: ./art/test.py --host -b Test: ./art/test/testrunner/testrunner.py --host --64 --jit -b Change-Id: I0f01c8391b09659bb6195955ecd8f88159141872 --- compiler/linker/linker_patch.h | 23 ++++++++ compiler/optimizing/code_generator.cc | 1 + compiler/optimizing/code_generator_x86_64.cc | 88 ++++++++++++++++++++++++++-- compiler/optimizing/code_generator_x86_64.h | 3 + compiler/optimizing/instruction_builder.cc | 3 + compiler/optimizing/nodes.h | 36 ++++++++++++ 6 files changed, 150 insertions(+), 4 deletions(-) (limited to 'compiler') diff --git a/compiler/linker/linker_patch.h b/compiler/linker/linker_patch.h index 8ed7fce0ff..133088240b 100644 --- a/compiler/linker/linker_patch.h +++ b/compiler/linker/linker_patch.h @@ -56,6 +56,7 @@ class LinkerPatch { kPackageTypeBssEntry, kStringRelative, kStringBssEntry, + kMethodTypeBssEntry, kCallEntrypoint, kBakerReadBarrierBranch, }; @@ -176,6 +177,16 @@ class LinkerPatch { return patch; } + static LinkerPatch MethodTypeBssEntryPatch(size_t literal_offset, + const DexFile* target_dex_file, + uint32_t pc_insn_offset, + uint32_t target_proto_idx) { + LinkerPatch patch(literal_offset, Type::kMethodTypeBssEntry, target_dex_file); + patch.proto_idx_ = target_proto_idx; + patch.pc_insn_offset_ = pc_insn_offset; + return patch; + } + static LinkerPatch CallEntrypointPatch(size_t literal_offset, uint32_t entrypoint_offset) { LinkerPatch patch(literal_offset, @@ -253,6 +264,16 @@ class LinkerPatch { return dex::StringIndex(string_idx_); } + const DexFile* TargetProtoDexFile() const { + DCHECK(patch_type_ == Type::kMethodTypeBssEntry); + return target_dex_file_; + } + + dex::ProtoIndex TargetProtoIndex() const { + DCHECK(patch_type_ == Type::kMethodTypeBssEntry); + return dex::ProtoIndex(proto_idx_); + } + uint32_t PcInsnOffset() const { DCHECK(patch_type_ == Type::kIntrinsicReference || patch_type_ == Type::kDataBimgRelRo || @@ -305,12 +326,14 @@ class LinkerPatch { uint32_t method_idx_; // Method index for Call/Method patches. uint32_t type_idx_; // Type index for Type patches. uint32_t string_idx_; // String index for String patches. + uint32_t proto_idx_; // Proto index for MethodType patches. uint32_t intrinsic_data_; // Data for IntrinsicObjects. uint32_t entrypoint_offset_; // Entrypoint offset in the Thread object. uint32_t baker_custom_value1_; static_assert(sizeof(method_idx_) == sizeof(cmp1_), "needed by relational operators"); static_assert(sizeof(type_idx_) == sizeof(cmp1_), "needed by relational operators"); static_assert(sizeof(string_idx_) == sizeof(cmp1_), "needed by relational operators"); + static_assert(sizeof(proto_idx_) == sizeof(cmp1_), "needed by relational operators"); static_assert(sizeof(intrinsic_data_) == sizeof(cmp1_), "needed by relational operators"); static_assert(sizeof(baker_custom_value1_) == sizeof(cmp1_), "needed by relational operators"); }; diff --git a/compiler/optimizing/code_generator.cc b/compiler/optimizing/code_generator.cc index 34400c9d22..b0e07e32ea 100644 --- a/compiler/optimizing/code_generator.cc +++ b/compiler/optimizing/code_generator.cc @@ -1682,6 +1682,7 @@ void CodeGenerator::ValidateInvokeRuntimeWithoutRecordingPcInfo(HInstruction* in instruction->IsArrayGet() || instruction->IsArraySet() || instruction->IsLoadClass() || + instruction->IsLoadMethodType() || instruction->IsLoadString() || instruction->IsInstanceOf() || instruction->IsCheckCast() || diff --git a/compiler/optimizing/code_generator_x86_64.cc b/compiler/optimizing/code_generator_x86_64.cc index d43d3dd95f..69fde66b2a 100644 --- a/compiler/optimizing/code_generator_x86_64.cc +++ b/compiler/optimizing/code_generator_x86_64.cc @@ -270,6 +270,38 @@ class BoundsCheckSlowPathX86_64 : public SlowPathCode { DISALLOW_COPY_AND_ASSIGN(BoundsCheckSlowPathX86_64); }; +class LoadMethodTypeSlowPathX86_64: public SlowPathCode { + public: + explicit LoadMethodTypeSlowPathX86_64(HLoadMethodType* mt) : SlowPathCode(mt) {} + + void EmitNativeCode(CodeGenerator* codegen) override { + LocationSummary* locations = instruction_->GetLocations(); + DCHECK(!locations->GetLiveRegisters()->ContainsCoreRegister(locations->Out().reg())); + + CodeGeneratorX86_64* x86_64_codegen = down_cast(codegen); + __ Bind(GetEntryLabel()); + SaveLiveRegisters(codegen, locations); + + const dex::ProtoIndex proto_index = instruction_->AsLoadMethodType()->GetProtoIndex(); + // Custom calling convention: RAX serves as both input and output. + __ movl(CpuRegister(RAX), Immediate(proto_index.index_)); + x86_64_codegen->InvokeRuntime(kQuickResolveMethodType, + instruction_, + instruction_->GetDexPc(), + this); + CheckEntrypointTypes(); + x86_64_codegen->Move(locations->Out(), Location::RegisterLocation(RAX)); + RestoreLiveRegisters(codegen, locations); + + __ jmp(GetExitLabel()); + } + + const char* GetDescription() const override { return "LoadMethodTypeSlowPathX86_64"; } + + private: + DISALLOW_COPY_AND_ASSIGN(LoadMethodTypeSlowPathX86_64); +}; + class LoadClassSlowPathX86_64 : public SlowPathCode { public: LoadClassSlowPathX86_64(HLoadClass* cls, HInstruction* at) @@ -529,6 +561,7 @@ class ReadBarrierMarkSlowPathX86_64 : public SlowPathCode { instruction_->IsArrayGet() || instruction_->IsArraySet() || instruction_->IsLoadClass() || + instruction_->IsLoadMethodType() || instruction_->IsLoadString() || instruction_->IsInstanceOf() || instruction_->IsCheckCast() || @@ -1319,6 +1352,12 @@ Label* CodeGeneratorX86_64::NewStringBssEntryPatch(HLoadString* load_string) { return &string_bss_entry_patches_.back().label; } +Label* CodeGeneratorX86_64::NewMethodTypeBssEntryPatch(HLoadMethodType* load_method_type) { + method_type_bss_entry_patches_.emplace_back( + &load_method_type->GetDexFile(), load_method_type->GetProtoIndex().index_); + return &method_type_bss_entry_patches_.back().label; +} + void CodeGeneratorX86_64::RecordBootImageJniEntrypointPatch(HInvokeStaticOrDirect* invoke) { boot_image_jni_entrypoint_patches_.emplace_back(invoke->GetResolvedMethodReference().dex_file, invoke->GetResolvedMethodReference().index); @@ -1406,6 +1445,7 @@ void CodeGeneratorX86_64::EmitLinkerPatches(ArenaVector* li package_type_bss_entry_patches_.size() + boot_image_string_patches_.size() + string_bss_entry_patches_.size() + + method_type_bss_entry_patches_.size() + boot_image_jni_entrypoint_patches_.size() + boot_image_other_patches_.size(); linker_patches->reserve(size); @@ -1438,6 +1478,8 @@ void CodeGeneratorX86_64::EmitLinkerPatches(ArenaVector* li package_type_bss_entry_patches_, linker_patches); EmitPcRelativeLinkerPatches( string_bss_entry_patches_, linker_patches); + EmitPcRelativeLinkerPatches( + method_type_bss_entry_patches_, linker_patches); EmitPcRelativeLinkerPatches( boot_image_jni_entrypoint_patches_, linker_patches); DCHECK_EQ(size, linker_patches->size()); @@ -1562,6 +1604,7 @@ CodeGeneratorX86_64::CodeGeneratorX86_64(HGraph* graph, package_type_bss_entry_patches_(graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)), boot_image_string_patches_(graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)), string_bss_entry_patches_(graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)), + method_type_bss_entry_patches_(graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)), boot_image_jni_entrypoint_patches_(graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)), boot_image_other_patches_(graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)), jit_string_patches_(graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)), @@ -6673,13 +6716,50 @@ void InstructionCodeGeneratorX86_64::VisitLoadMethodHandle(HLoadMethodHandle* lo } void LocationsBuilderX86_64::VisitLoadMethodType(HLoadMethodType* load) { - // Custom calling convention: RAX serves as both input and output. - Location location = Location::RegisterLocation(RAX); - CodeGenerator::CreateLoadMethodTypeRuntimeCallLocationSummary(load, location, location); + LocationSummary* locations = + new (GetGraph()->GetAllocator()) LocationSummary(load, LocationSummary::kCallOnSlowPath); + if (load->GetLoadKind() == HLoadMethodType::LoadKind::kRuntimeCall) { + Location location = Location::RegisterLocation(RAX); + CodeGenerator::CreateLoadMethodTypeRuntimeCallLocationSummary(load, location, location); + } else { + DCHECK_EQ(load->GetLoadKind(), HLoadMethodType::LoadKind::kBssEntry); + locations->SetOut(Location::RequiresRegister()); + if (codegen_->EmitNonBakerReadBarrier()) { + // For non-Baker read barrier we have a temp-clobbering call. + } else { + // Rely on the pResolveMethodType to save everything. + locations->SetCustomSlowPathCallerSaves(OneRegInReferenceOutSaveEverythingCallerSaves()); + } + } } void InstructionCodeGeneratorX86_64::VisitLoadMethodType(HLoadMethodType* load) { - codegen_->GenerateLoadMethodTypeRuntimeCall(load); + LocationSummary* locations = load->GetLocations(); + Location out_loc = locations->Out(); + CpuRegister out = out_loc.AsRegister(); + + switch (load->GetLoadKind()) { + case HLoadMethodType::LoadKind::kBssEntry: { + Address address = Address::Absolute(CodeGeneratorX86_64::kPlaceholder32BitOffset, + /* no_rip= */ false); + Label* fixup_label = codegen_->NewMethodTypeBssEntryPatch(load); + // /* GcRoot */ out = *address /* PC-relative */ + GenerateGcRootFieldLoad( + load, out_loc, address, fixup_label, codegen_->GetCompilerReadBarrierOption()); + // No need for memory fence, thanks to the x86-64 memory model. + SlowPathCode* slow_path = + new (codegen_->GetScopedAllocator()) LoadMethodTypeSlowPathX86_64(load); + codegen_->AddSlowPath(slow_path); + __ testl(out, out); + __ j(kEqual, slow_path->GetEntryLabel()); + __ Bind(slow_path->GetExitLabel()); + return; + } + default: + DCHECK_EQ(load->GetLoadKind(), HLoadMethodType::LoadKind::kRuntimeCall); + codegen_->GenerateLoadMethodTypeRuntimeCall(load); + break; + } } void InstructionCodeGeneratorX86_64::VisitClinitCheck(HClinitCheck* check) { diff --git a/compiler/optimizing/code_generator_x86_64.h b/compiler/optimizing/code_generator_x86_64.h index 7da2e39583..e4d3eac6bc 100644 --- a/compiler/optimizing/code_generator_x86_64.h +++ b/compiler/optimizing/code_generator_x86_64.h @@ -523,6 +523,7 @@ class CodeGeneratorX86_64 : public CodeGenerator { Label* NewTypeBssEntryPatch(HLoadClass* load_class); void RecordBootImageStringPatch(HLoadString* load_string); Label* NewStringBssEntryPatch(HLoadString* load_string); + Label* NewMethodTypeBssEntryPatch(HLoadMethodType* load_method_type); void RecordBootImageJniEntrypointPatch(HInvokeStaticOrDirect* invoke); Label* NewJitRootStringPatch(const DexFile& dex_file, dex::StringIndex string_index, @@ -735,6 +736,8 @@ class CodeGeneratorX86_64 : public CodeGenerator { ArenaDeque> boot_image_string_patches_; // PC-relative String patch info for kBssEntry. ArenaDeque> string_bss_entry_patches_; + // PC-relative MethodType patch info for kBssEntry. + ArenaDeque> method_type_bss_entry_patches_; // PC-relative method patch info for kBootImageLinkTimePcRelative+kCallCriticalNative. ArenaDeque> boot_image_jni_entrypoint_patches_; // PC-relative patch info for IntrinsicObjects for the boot image, diff --git a/compiler/optimizing/instruction_builder.cc b/compiler/optimizing/instruction_builder.cc index 281da6f9ec..fe0f3fe319 100644 --- a/compiler/optimizing/instruction_builder.cc +++ b/compiler/optimizing/instruction_builder.cc @@ -2699,6 +2699,9 @@ void HInstructionBuilder::BuildLoadMethodType(dex::ProtoIndex proto_index, uint3 const DexFile& dex_file = *dex_compilation_unit_->GetDexFile(); HLoadMethodType* load_method_type = new (allocator_) HLoadMethodType(graph_->GetCurrentMethod(), proto_index, dex_file, dex_pc); + if (!code_generator_->GetCompilerOptions().IsJitCompiler()) { + load_method_type->SetLoadKind(HLoadMethodType::LoadKind::kBssEntry); + } AppendInstruction(load_method_type); } diff --git a/compiler/optimizing/nodes.h b/compiler/optimizing/nodes.h index d84ff7be73..0efe8f4335 100644 --- a/compiler/optimizing/nodes.h +++ b/compiler/optimizing/nodes.h @@ -7313,6 +7313,16 @@ class HLoadMethodHandle final : public HInstruction { class HLoadMethodType final : public HInstruction { public: + // Determines how to load the MethodType. + enum class LoadKind { + // Load from an entry in the .bss section using a PC-relative load. + kBssEntry, + // Load using a single runtime call. + kRuntimeCall, + + kLast = kRuntimeCall, + }; + HLoadMethodType(HCurrentMethod* current_method, dex::ProtoIndex proto_index, const DexFile& dex_file, @@ -7324,6 +7334,7 @@ class HLoadMethodType final : public HInstruction { special_input_(HUserRecord(current_method)), proto_index_(proto_index), dex_file_(dex_file) { + SetPackedField(LoadKind::kRuntimeCall); } using HInstruction::GetInputRecords; // Keep the const version visible. @@ -7334,6 +7345,12 @@ class HLoadMethodType final : public HInstruction { bool IsClonable() const override { return true; } + void SetLoadKind(LoadKind load_kind); + + LoadKind GetLoadKind() const { + return GetPackedField(); + } + dex::ProtoIndex GetProtoIndex() const { return proto_index_; } const DexFile& GetDexFile() const { return dex_file_; } @@ -7352,6 +7369,14 @@ class HLoadMethodType final : public HInstruction { DEFAULT_COPY_CONSTRUCTOR(LoadMethodType); private: + static constexpr size_t kFieldLoadKind = kNumberOfGenericPackedBits; + static constexpr size_t kFieldLoadKindSize = + MinimumBitsToStore(static_cast(LoadKind::kLast)); + static constexpr size_t kNumberOfLoadMethodTypePackedBits = kFieldLoadKind + kFieldLoadKindSize; + static_assert(kNumberOfLoadMethodTypePackedBits <= kMaxNumberOfPackedBits, + "Too many packed fields."); + using LoadKindField = BitField; + // The special input is the HCurrentMethod for kRuntimeCall. HUserRecord special_input_; @@ -7359,6 +7384,17 @@ class HLoadMethodType final : public HInstruction { const DexFile& dex_file_; }; +std::ostream& operator<<(std::ostream& os, HLoadMethodType::LoadKind rhs); + +// Note: defined outside class to see operator<<(., HLoadMethodType::LoadKind). +inline void HLoadMethodType::SetLoadKind(LoadKind load_kind) { + // The load kind should be determined before inserting the instruction to the graph. + DCHECK(GetBlock() == nullptr); + DCHECK(GetEnvironment() == nullptr); + DCHECK_EQ(GetLoadKind(), LoadKind::kRuntimeCall); + SetPackedField(load_kind); +} + /** * Performs an initialization check on its Class object input. */ -- cgit v1.2.3-59-g8ed1b