diff options
35 files changed, 262 insertions, 26 deletions
diff --git a/compiler/optimizing/code_generator.cc b/compiler/optimizing/code_generator.cc index 1e44311cb1..f57333741c 100644 --- a/compiler/optimizing/code_generator.cc +++ b/compiler/optimizing/code_generator.cc @@ -736,6 +736,26 @@ void CodeGenerator::GenerateLoadClassRuntimeCall(HLoadClass* cls) { } } +void CodeGenerator::CreateLoadMethodHandleRuntimeCallLocationSummary( + HLoadMethodHandle* method_handle, + Location runtime_proto_index_location, + Location runtime_return_location) { + DCHECK_EQ(method_handle->InputCount(), 1u); + LocationSummary* locations = + new (method_handle->GetBlock()->GetGraph()->GetAllocator()) LocationSummary( + method_handle, LocationSummary::kCallOnMainOnly); + locations->SetInAt(0, Location::NoLocation()); + locations->AddTemp(runtime_proto_index_location); + locations->SetOut(runtime_return_location); +} + +void CodeGenerator::GenerateLoadMethodHandleRuntimeCall(HLoadMethodHandle* method_handle) { + LocationSummary* locations = method_handle->GetLocations(); + MoveConstant(locations->GetTemp(0), method_handle->GetMethodHandleIndex()); + CheckEntrypointTypes<kQuickResolveMethodHandle, void*, uint32_t>(); + InvokeRuntime(kQuickResolveMethodHandle, method_handle, method_handle->GetDexPc()); +} + void CodeGenerator::CreateLoadMethodTypeRuntimeCallLocationSummary( HLoadMethodType* method_type, Location runtime_proto_index_location, diff --git a/compiler/optimizing/code_generator.h b/compiler/optimizing/code_generator.h index 7e84a448cc..bcb25997f4 100644 --- a/compiler/optimizing/code_generator.h +++ b/compiler/optimizing/code_generator.h @@ -564,6 +564,11 @@ class CodeGenerator : public DeletableArenaObject<kArenaAllocCodeGenerator> { Location runtime_return_location); void GenerateLoadClassRuntimeCall(HLoadClass* cls); + static void CreateLoadMethodHandleRuntimeCallLocationSummary(HLoadMethodHandle* method_handle, + Location runtime_handle_index_location, + Location runtime_return_location); + void GenerateLoadMethodHandleRuntimeCall(HLoadMethodHandle* method_handle); + static void CreateLoadMethodTypeRuntimeCallLocationSummary(HLoadMethodType* method_type, Location runtime_type_index_location, Location runtime_return_location); diff --git a/compiler/optimizing/code_generator_arm64.cc b/compiler/optimizing/code_generator_arm64.cc index 0601d2d79a..6f173e19f5 100644 --- a/compiler/optimizing/code_generator_arm64.cc +++ b/compiler/optimizing/code_generator_arm64.cc @@ -5144,6 +5144,16 @@ void InstructionCodeGeneratorARM64::VisitLoadClass(HLoadClass* cls) NO_THREAD_SA } } +void LocationsBuilderARM64::VisitLoadMethodHandle(HLoadMethodHandle* load) { + InvokeRuntimeCallingConvention calling_convention; + Location location = LocationFrom(calling_convention.GetRegisterAt(0)); + CodeGenerator::CreateLoadMethodHandleRuntimeCallLocationSummary(load, location, location); +} + +void InstructionCodeGeneratorARM64::VisitLoadMethodHandle(HLoadMethodHandle* load) { + codegen_->GenerateLoadMethodHandleRuntimeCall(load); +} + void LocationsBuilderARM64::VisitLoadMethodType(HLoadMethodType* load) { InvokeRuntimeCallingConvention calling_convention; Location location = LocationFrom(calling_convention.GetRegisterAt(0)); diff --git a/compiler/optimizing/code_generator_arm_vixl.cc b/compiler/optimizing/code_generator_arm_vixl.cc index 33304c619d..859e1597c6 100644 --- a/compiler/optimizing/code_generator_arm_vixl.cc +++ b/compiler/optimizing/code_generator_arm_vixl.cc @@ -7527,6 +7527,16 @@ void InstructionCodeGeneratorARMVIXL::VisitLoadClass(HLoadClass* cls) NO_THREAD_ } } +void LocationsBuilderARMVIXL::VisitLoadMethodHandle(HLoadMethodHandle* load) { + InvokeRuntimeCallingConventionARMVIXL calling_convention; + Location location = LocationFrom(calling_convention.GetRegisterAt(0)); + CodeGenerator::CreateLoadMethodHandleRuntimeCallLocationSummary(load, location, location); +} + +void InstructionCodeGeneratorARMVIXL::VisitLoadMethodHandle(HLoadMethodHandle* load) { + codegen_->GenerateLoadMethodHandleRuntimeCall(load); +} + void LocationsBuilderARMVIXL::VisitLoadMethodType(HLoadMethodType* load) { InvokeRuntimeCallingConventionARMVIXL calling_convention; Location location = LocationFrom(calling_convention.GetRegisterAt(0)); diff --git a/compiler/optimizing/code_generator_mips.cc b/compiler/optimizing/code_generator_mips.cc index 3a3fcffe15..7f3441fdf4 100644 --- a/compiler/optimizing/code_generator_mips.cc +++ b/compiler/optimizing/code_generator_mips.cc @@ -8226,6 +8226,16 @@ void InstructionCodeGeneratorMIPS::VisitLoadClass(HLoadClass* cls) NO_THREAD_SAF } } +void LocationsBuilderMIPS::VisitLoadMethodHandle(HLoadMethodHandle* load) { + InvokeRuntimeCallingConvention calling_convention; + Location loc = Location::RegisterLocation(calling_convention.GetRegisterAt(0)); + CodeGenerator::CreateLoadMethodHandleRuntimeCallLocationSummary(load, loc, loc); +} + +void InstructionCodeGeneratorMIPS::VisitLoadMethodHandle(HLoadMethodHandle* load) { + codegen_->GenerateLoadMethodHandleRuntimeCall(load); +} + void LocationsBuilderMIPS::VisitLoadMethodType(HLoadMethodType* load) { InvokeRuntimeCallingConvention calling_convention; Location loc = Location::RegisterLocation(calling_convention.GetRegisterAt(0)); diff --git a/compiler/optimizing/code_generator_mips64.cc b/compiler/optimizing/code_generator_mips64.cc index d6fc9a15b8..ee32b96daf 100644 --- a/compiler/optimizing/code_generator_mips64.cc +++ b/compiler/optimizing/code_generator_mips64.cc @@ -6262,6 +6262,16 @@ void InstructionCodeGeneratorMIPS64::VisitLoadClass(HLoadClass* cls) NO_THREAD_S } } +void LocationsBuilderMIPS64::VisitLoadMethodHandle(HLoadMethodHandle* load) { + InvokeRuntimeCallingConvention calling_convention; + Location loc = Location::RegisterLocation(calling_convention.GetRegisterAt(0)); + CodeGenerator::CreateLoadMethodHandleRuntimeCallLocationSummary(load, loc, loc); +} + +void InstructionCodeGeneratorMIPS64::VisitLoadMethodHandle(HLoadMethodHandle* load) { + codegen_->GenerateLoadMethodHandleRuntimeCall(load); +} + void LocationsBuilderMIPS64::VisitLoadMethodType(HLoadMethodType* load) { InvokeRuntimeCallingConvention calling_convention; Location loc = Location::RegisterLocation(calling_convention.GetRegisterAt(0)); diff --git a/compiler/optimizing/code_generator_x86.cc b/compiler/optimizing/code_generator_x86.cc index d18a750faf..9e315381b1 100644 --- a/compiler/optimizing/code_generator_x86.cc +++ b/compiler/optimizing/code_generator_x86.cc @@ -6539,6 +6539,16 @@ void InstructionCodeGeneratorX86::VisitLoadClass(HLoadClass* cls) NO_THREAD_SAFE } } +void LocationsBuilderX86::VisitLoadMethodHandle(HLoadMethodHandle* load) { + InvokeRuntimeCallingConvention calling_convention; + Location location = Location::RegisterLocation(calling_convention.GetRegisterAt(0)); + CodeGenerator::CreateLoadMethodHandleRuntimeCallLocationSummary(load, location, location); +} + +void InstructionCodeGeneratorX86::VisitLoadMethodHandle(HLoadMethodHandle* load) { + codegen_->GenerateLoadMethodHandleRuntimeCall(load); +} + void LocationsBuilderX86::VisitLoadMethodType(HLoadMethodType* load) { InvokeRuntimeCallingConvention calling_convention; Location location = Location::RegisterLocation(calling_convention.GetRegisterAt(0)); diff --git a/compiler/optimizing/code_generator_x86_64.cc b/compiler/optimizing/code_generator_x86_64.cc index 450c8574b0..f7397046d7 100644 --- a/compiler/optimizing/code_generator_x86_64.cc +++ b/compiler/optimizing/code_generator_x86_64.cc @@ -5908,6 +5908,16 @@ void LocationsBuilderX86_64::VisitClinitCheck(HClinitCheck* check) { } } +void LocationsBuilderX86_64::VisitLoadMethodHandle(HLoadMethodHandle* load) { + // Custom calling convention: RAX serves as both input and output. + Location location = Location::RegisterLocation(RAX); + CodeGenerator::CreateLoadMethodHandleRuntimeCallLocationSummary(load, location, location); +} + +void InstructionCodeGeneratorX86_64::VisitLoadMethodHandle(HLoadMethodHandle* load) { + codegen_->GenerateLoadMethodHandleRuntimeCall(load); +} + void LocationsBuilderX86_64::VisitLoadMethodType(HLoadMethodType* load) { // Custom calling convention: RAX serves as both input and output. Location location = Location::RegisterLocation(RAX); diff --git a/compiler/optimizing/graph_visualizer.cc b/compiler/optimizing/graph_visualizer.cc index 87ce1f0c73..d65ad40565 100644 --- a/compiler/optimizing/graph_visualizer.cc +++ b/compiler/optimizing/graph_visualizer.cc @@ -386,6 +386,11 @@ class HGraphVisualizerPrinter : public HGraphDelegateVisitor { << load_class->NeedsAccessCheck() << std::noboolalpha; } + void VisitLoadMethodHandle(HLoadMethodHandle* load_method_handle) OVERRIDE { + StartAttributeStream("load_kind") << "RuntimeCall"; + StartAttributeStream("method_handle_index") << load_method_handle->GetMethodHandleIndex(); + } + void VisitLoadMethodType(HLoadMethodType* load_method_type) OVERRIDE { StartAttributeStream("load_kind") << "RuntimeCall"; const DexFile& dex_file = load_method_type->GetDexFile(); diff --git a/compiler/optimizing/instruction_builder.cc b/compiler/optimizing/instruction_builder.cc index 61730a8128..35a39456a2 100644 --- a/compiler/optimizing/instruction_builder.cc +++ b/compiler/optimizing/instruction_builder.cc @@ -1896,6 +1896,13 @@ bool HInstructionBuilder::LoadClassNeedsAccessCheck(Handle<mirror::Class> klass) } } +void HInstructionBuilder::BuildLoadMethodHandle(uint16_t proto_idx, uint32_t dex_pc) { + const DexFile& dex_file = *dex_compilation_unit_->GetDexFile(); + HLoadMethodHandle* load_method_handle = + new (allocator_) HLoadMethodHandle(graph_->GetCurrentMethod(), proto_idx, dex_file, dex_pc); + AppendInstruction(load_method_handle); +} + void HInstructionBuilder::BuildLoadMethodType(uint16_t proto_idx, uint32_t dex_pc) { const DexFile& dex_file = *dex_compilation_unit_->GetDexFile(); HLoadMethodType* load_method_type = @@ -2934,6 +2941,13 @@ bool HInstructionBuilder::ProcessDexInstruction(const Instruction& instruction, break; } + case Instruction::CONST_METHOD_HANDLE: { + uint16_t method_handle_idx = instruction.VRegB_21c(); + BuildLoadMethodHandle(method_handle_idx, dex_pc); + UpdateLocal(instruction.VRegA_21c(), current_block_->GetLastInstruction()); + break; + } + case Instruction::CONST_METHOD_TYPE: { uint16_t proto_idx = instruction.VRegB_21c(); BuildLoadMethodType(proto_idx, dex_pc); diff --git a/compiler/optimizing/instruction_builder.h b/compiler/optimizing/instruction_builder.h index 3fde54cffa..95ffa6b054 100644 --- a/compiler/optimizing/instruction_builder.h +++ b/compiler/optimizing/instruction_builder.h @@ -240,7 +240,10 @@ class HInstructionBuilder : public ValueObject { bool LoadClassNeedsAccessCheck(Handle<mirror::Class> klass) REQUIRES_SHARED(Locks::mutator_lock_); - // Builds a `HLoadMethodType` loading the given `proto_index`. + // Builds a `HLoadMethodHandle` loading the given `method_handle_idx`. + void BuildLoadMethodHandle(uint16_t method_handle_idx, uint32_t dex_pc); + + // Builds a `HLoadMethodType` loading the given `proto_idx`. void BuildLoadMethodType(uint16_t proto_idx, uint32_t dex_pc); // Returns the outer-most compiling method's class. diff --git a/compiler/optimizing/nodes.h b/compiler/optimizing/nodes.h index 54882ff92b..a7c2d0b125 100644 --- a/compiler/optimizing/nodes.h +++ b/compiler/optimizing/nodes.h @@ -1383,6 +1383,7 @@ class HLoopInformationOutwardIterator : public ValueObject { M(LessThanOrEqual, Condition) \ M(LoadClass, Instruction) \ M(LoadException, Instruction) \ + M(LoadMethodHandle, Instruction) \ M(LoadMethodType, Instruction) \ M(LoadString, Instruction) \ M(LongConstant, Constant) \ @@ -6500,6 +6501,50 @@ inline void HLoadString::AddSpecialInput(HInstruction* special_input) { special_input->AddUseAt(this, 0); } +class HLoadMethodHandle FINAL : public HInstruction { + public: + HLoadMethodHandle(HCurrentMethod* current_method, + uint16_t method_handle_idx, + const DexFile& dex_file, + uint32_t dex_pc) + : HInstruction(kLoadMethodHandle, + DataType::Type::kReference, + SideEffectsForArchRuntimeCalls(), + dex_pc), + special_input_(HUserRecord<HInstruction*>(current_method)), + method_handle_idx_(method_handle_idx), + dex_file_(dex_file) { + } + + using HInstruction::GetInputRecords; // Keep the const version visible. + ArrayRef<HUserRecord<HInstruction*>> GetInputRecords() OVERRIDE FINAL { + return ArrayRef<HUserRecord<HInstruction*>>( + &special_input_, (special_input_.GetInstruction() != nullptr) ? 1u : 0u); + } + + bool IsClonable() const OVERRIDE { return true; } + + uint16_t GetMethodHandleIndex() const { return method_handle_idx_; } + + const DexFile& GetDexFile() const { return dex_file_; } + + static SideEffects SideEffectsForArchRuntimeCalls() { + return SideEffects::CanTriggerGC(); + } + + DECLARE_INSTRUCTION(LoadMethodHandle); + + protected: + DEFAULT_COPY_CONSTRUCTOR(LoadMethodHandle); + + private: + // The special input is the HCurrentMethod for kRuntimeCall. + HUserRecord<HInstruction*> special_input_; + + const uint16_t method_handle_idx_; + const DexFile& dex_file_; +}; + class HLoadMethodType FINAL : public HInstruction { public: HLoadMethodType(HCurrentMethod* current_method, @@ -6540,7 +6585,7 @@ class HLoadMethodType FINAL : public HInstruction { // The special input is the HCurrentMethod for kRuntimeCall. HUserRecord<HInstruction*> special_input_; - uint16_t proto_idx_; + const uint16_t proto_idx_; const DexFile& dex_file_; }; diff --git a/compiler/optimizing/reference_type_propagation.cc b/compiler/optimizing/reference_type_propagation.cc index b15a0ea52f..ecfa790b91 100644 --- a/compiler/optimizing/reference_type_propagation.cc +++ b/compiler/optimizing/reference_type_propagation.cc @@ -59,6 +59,12 @@ ReferenceTypeInfo::TypeHandle ReferenceTypePropagation::HandleCache::GetClassCla return GetRootHandle(handles_, ClassLinker::kJavaLangClass, &class_class_handle_); } +ReferenceTypeInfo::TypeHandle ReferenceTypePropagation::HandleCache::GetMethodHandleClassHandle() { + return GetRootHandle(handles_, + ClassLinker::kJavaLangInvokeMethodHandleImpl, + &method_handle_class_handle_); +} + ReferenceTypeInfo::TypeHandle ReferenceTypePropagation::HandleCache::GetMethodTypeClassHandle() { return GetRootHandle(handles_, ClassLinker::kJavaLangInvokeMethodType, @@ -95,6 +101,7 @@ class ReferenceTypePropagation::RTPVisitor : public HGraphDelegateVisitor { void VisitLoadClass(HLoadClass* load_class) OVERRIDE; void VisitInstanceOf(HInstanceOf* load_class) OVERRIDE; void VisitClinitCheck(HClinitCheck* clinit_check) OVERRIDE; + void VisitLoadMethodHandle(HLoadMethodHandle* instr) OVERRIDE; void VisitLoadMethodType(HLoadMethodType* instr) OVERRIDE; void VisitLoadString(HLoadString* instr) OVERRIDE; void VisitLoadException(HLoadException* instr) OVERRIDE; @@ -675,6 +682,12 @@ void ReferenceTypePropagation::RTPVisitor::VisitClinitCheck(HClinitCheck* instr) instr->SetReferenceTypeInfo(instr->InputAt(0)->GetReferenceTypeInfo()); } +void ReferenceTypePropagation::RTPVisitor::VisitLoadMethodHandle(HLoadMethodHandle* instr) { + instr->SetReferenceTypeInfo(ReferenceTypeInfo::Create( + handle_cache_->GetMethodHandleClassHandle(), + /* is_exact */ true)); +} + void ReferenceTypePropagation::RTPVisitor::VisitLoadMethodType(HLoadMethodType* instr) { instr->SetReferenceTypeInfo( ReferenceTypeInfo::Create(handle_cache_->GetMethodTypeClassHandle(), /* is_exact */ true)); diff --git a/compiler/optimizing/reference_type_propagation.h b/compiler/optimizing/reference_type_propagation.h index da2193d223..d36d592708 100644 --- a/compiler/optimizing/reference_type_propagation.h +++ b/compiler/optimizing/reference_type_propagation.h @@ -75,6 +75,7 @@ class ReferenceTypePropagation : public HOptimization { ReferenceTypeInfo::TypeHandle GetObjectClassHandle(); ReferenceTypeInfo::TypeHandle GetClassClassHandle(); + ReferenceTypeInfo::TypeHandle GetMethodHandleClassHandle(); ReferenceTypeInfo::TypeHandle GetMethodTypeClassHandle(); ReferenceTypeInfo::TypeHandle GetStringClassHandle(); ReferenceTypeInfo::TypeHandle GetThrowableClassHandle(); @@ -84,6 +85,7 @@ class ReferenceTypePropagation : public HOptimization { ReferenceTypeInfo::TypeHandle object_class_handle_; ReferenceTypeInfo::TypeHandle class_class_handle_; + ReferenceTypeInfo::TypeHandle method_handle_class_handle_; ReferenceTypeInfo::TypeHandle method_type_class_handle_; ReferenceTypeInfo::TypeHandle string_class_handle_; ReferenceTypeInfo::TypeHandle throwable_class_handle_; diff --git a/compiler/utils/assembler_thumb_test_expected.cc.inc b/compiler/utils/assembler_thumb_test_expected.cc.inc index ff3e1ba9f0..19c405e517 100644 --- a/compiler/utils/assembler_thumb_test_expected.cc.inc +++ b/compiler/utils/assembler_thumb_test_expected.cc.inc @@ -153,7 +153,7 @@ const char* const VixlJniHelpersResults[] = { " 21c: f8d9 8034 ldr.w r8, [r9, #52] ; 0x34\n", " 220: 4770 bx lr\n", " 222: 4660 mov r0, ip\n", - " 224: f8d9 c2c8 ldr.w ip, [r9, #712] ; 0x2c8\n", + " 224: f8d9 c2cc ldr.w ip, [r9, #716] ; 0x2cc\n", " 228: 47e0 blx ip\n", nullptr }; diff --git a/dex2oat/linker/oat_writer_test.cc b/dex2oat/linker/oat_writer_test.cc index 7bd9f0fe8d..df0641cc7f 100644 --- a/dex2oat/linker/oat_writer_test.cc +++ b/dex2oat/linker/oat_writer_test.cc @@ -497,7 +497,7 @@ TEST_F(OatTest, OatHeaderSizeCheck) { EXPECT_EQ(76U, sizeof(OatHeader)); EXPECT_EQ(4U, sizeof(OatMethodOffsets)); EXPECT_EQ(24U, sizeof(OatQuickMethodHeader)); - EXPECT_EQ(163 * static_cast<size_t>(GetInstructionSetPointerSize(kRuntimeISA)), + EXPECT_EQ(164 * static_cast<size_t>(GetInstructionSetPointerSize(kRuntimeISA)), sizeof(QuickEntryPoints)); } diff --git a/runtime/arch/arm/quick_entrypoints_arm.S b/runtime/arch/arm/quick_entrypoints_arm.S index 1a1f4edad8..cd00125de5 100644 --- a/runtime/arch/arm/quick_entrypoints_arm.S +++ b/runtime/arch/arm/quick_entrypoints_arm.S @@ -1043,6 +1043,7 @@ END \name ONE_ARG_SAVE_EVERYTHING_DOWNCALL_FOR_CLINIT art_quick_initialize_static_storage, artInitializeStaticStorageFromCode ONE_ARG_SAVE_EVERYTHING_DOWNCALL_FOR_CLINIT art_quick_initialize_type, artInitializeTypeFromCode ONE_ARG_SAVE_EVERYTHING_DOWNCALL art_quick_initialize_type_and_verify_access, artInitializeTypeAndVerifyAccessFromCode +ONE_ARG_SAVE_EVERYTHING_DOWNCALL art_quick_resolve_method_handle, artResolveMethodHandleFromCode ONE_ARG_SAVE_EVERYTHING_DOWNCALL art_quick_resolve_method_type, artResolveMethodTypeFromCode ONE_ARG_SAVE_EVERYTHING_DOWNCALL art_quick_resolve_string, artResolveStringFromCode diff --git a/runtime/arch/arm64/quick_entrypoints_arm64.S b/runtime/arch/arm64/quick_entrypoints_arm64.S index 9919e98d6b..ac5b2b8b88 100644 --- a/runtime/arch/arm64/quick_entrypoints_arm64.S +++ b/runtime/arch/arm64/quick_entrypoints_arm64.S @@ -1580,6 +1580,7 @@ TWO_ARG_REF_DOWNCALL art_quick_handle_fill_data, artHandleFillArrayDataFromCode, ONE_ARG_SAVE_EVERYTHING_DOWNCALL_FOR_CLINIT art_quick_initialize_static_storage, artInitializeStaticStorageFromCode ONE_ARG_SAVE_EVERYTHING_DOWNCALL_FOR_CLINIT art_quick_initialize_type, artInitializeTypeFromCode ONE_ARG_SAVE_EVERYTHING_DOWNCALL art_quick_initialize_type_and_verify_access, artInitializeTypeAndVerifyAccessFromCode +ONE_ARG_SAVE_EVERYTHING_DOWNCALL art_quick_resolve_method_handle, artResolveMethodHandleFromCode ONE_ARG_SAVE_EVERYTHING_DOWNCALL art_quick_resolve_method_type, artResolveMethodTypeFromCode ONE_ARG_SAVE_EVERYTHING_DOWNCALL art_quick_resolve_string, artResolveStringFromCode diff --git a/runtime/arch/mips/entrypoints_init_mips.cc b/runtime/arch/mips/entrypoints_init_mips.cc index 58b9d48951..5d6e410101 100644 --- a/runtime/arch/mips/entrypoints_init_mips.cc +++ b/runtime/arch/mips/entrypoints_init_mips.cc @@ -203,6 +203,8 @@ void InitEntryPoints(JniEntryPoints* jpoints, QuickEntryPoints* qpoints) { static_assert(!IsDirectEntrypoint(kQuickInitializeType), "Non-direct C stub marked direct."); qpoints->pResolveString = art_quick_resolve_string; static_assert(!IsDirectEntrypoint(kQuickResolveString), "Non-direct C stub marked direct."); + qpoints->pResolveMethodHandle = art_quick_resolve_method_handle; + static_assert(!IsDirectEntrypoint(kQuickResolveMethodHandle), "Non-direct C stub marked direct."); qpoints->pResolveMethodType = art_quick_resolve_method_type; static_assert(!IsDirectEntrypoint(kQuickResolveMethodType), "Non-direct C stub marked direct."); diff --git a/runtime/arch/mips/quick_entrypoints_mips.S b/runtime/arch/mips/quick_entrypoints_mips.S index 104a4ca6d6..c367ea60c2 100644 --- a/runtime/arch/mips/quick_entrypoints_mips.S +++ b/runtime/arch/mips/quick_entrypoints_mips.S @@ -2056,6 +2056,12 @@ END \name .endm /* + * Entry from managed code to resolve a method handle. On entry, A0 holds the method handle + * index. On success the MethodHandle is returned, otherwise an exception is raised. + */ +ONE_ARG_SAVE_EVERYTHING_DOWNCALL art_quick_resolve_method_handle, artResolveMethodHandleFromCode + + /* * Entry from managed code to resolve a method type. On entry, A0 holds the method type index. * On success the MethodType is returned, otherwise an exception is raised. */ diff --git a/runtime/arch/mips64/quick_entrypoints_mips64.S b/runtime/arch/mips64/quick_entrypoints_mips64.S index 1e94e07c23..1f4f174e26 100644 --- a/runtime/arch/mips64/quick_entrypoints_mips64.S +++ b/runtime/arch/mips64/quick_entrypoints_mips64.S @@ -1956,6 +1956,12 @@ END \name .endm /* + * Entry from managed code to resolve a method handle. On entry, A0 holds the method handle + * index. On success the MethodHandle is returned, otherwise an exception is raised. + */ +ONE_ARG_SAVE_EVERYTHING_DOWNCALL art_quick_resolve_method_handle, artResolveMethodHandleFromCode + + /* * Entry from managed code to resolve a method type. On entry, A0 holds the method type index. * On success the MethodType is returned, otherwise an exception is raised. */ diff --git a/runtime/arch/x86/quick_entrypoints_x86.S b/runtime/arch/x86/quick_entrypoints_x86.S index 0ae691468d..8ab4ce160f 100644 --- a/runtime/arch/x86/quick_entrypoints_x86.S +++ b/runtime/arch/x86/quick_entrypoints_x86.S @@ -1281,6 +1281,7 @@ GENERATE_ALLOC_ARRAY_TLAB art_quick_alloc_array_resolved64_tlab, artAllocArrayFr ONE_ARG_SAVE_EVERYTHING_DOWNCALL_FOR_CLINIT art_quick_initialize_static_storage, artInitializeStaticStorageFromCode ONE_ARG_SAVE_EVERYTHING_DOWNCALL_FOR_CLINIT art_quick_initialize_type, artInitializeTypeFromCode ONE_ARG_SAVE_EVERYTHING_DOWNCALL art_quick_initialize_type_and_verify_access, artInitializeTypeAndVerifyAccessFromCode +ONE_ARG_SAVE_EVERYTHING_DOWNCALL art_quick_resolve_method_handle, artResolveMethodHandleFromCode ONE_ARG_SAVE_EVERYTHING_DOWNCALL art_quick_resolve_method_type, artResolveMethodTypeFromCode ONE_ARG_SAVE_EVERYTHING_DOWNCALL art_quick_resolve_string, artResolveStringFromCode diff --git a/runtime/arch/x86_64/quick_entrypoints_x86_64.S b/runtime/arch/x86_64/quick_entrypoints_x86_64.S index 8fef8020ef..eb945ed366 100644 --- a/runtime/arch/x86_64/quick_entrypoints_x86_64.S +++ b/runtime/arch/x86_64/quick_entrypoints_x86_64.S @@ -1301,6 +1301,7 @@ END_FUNCTION art_quick_alloc_object_initialized_region_tlab ONE_ARG_SAVE_EVERYTHING_DOWNCALL_FOR_CLINIT art_quick_initialize_static_storage, artInitializeStaticStorageFromCode ONE_ARG_SAVE_EVERYTHING_DOWNCALL_FOR_CLINIT art_quick_initialize_type, artInitializeTypeFromCode ONE_ARG_SAVE_EVERYTHING_DOWNCALL art_quick_initialize_type_and_verify_access, artInitializeTypeAndVerifyAccessFromCode +ONE_ARG_SAVE_EVERYTHING_DOWNCALL art_quick_resolve_method_handle, artResolveMethodHandleFromCode ONE_ARG_SAVE_EVERYTHING_DOWNCALL art_quick_resolve_method_type, artResolveMethodTypeFromCode ONE_ARG_SAVE_EVERYTHING_DOWNCALL art_quick_resolve_string, artResolveStringFromCode diff --git a/runtime/asm_support.h b/runtime/asm_support.h index 705e1ff6cf..70ff40d32c 100644 --- a/runtime/asm_support.h +++ b/runtime/asm_support.h @@ -73,7 +73,7 @@ ADD_TEST_EQ(THREAD_LOCAL_OBJECTS_OFFSET, // Offset of field Thread::tlsPtr_.mterp_current_ibase. #define THREAD_CURRENT_IBASE_OFFSET \ - (THREAD_LOCAL_OBJECTS_OFFSET + __SIZEOF_SIZE_T__ + (1 + 163) * __SIZEOF_POINTER__) + (THREAD_LOCAL_OBJECTS_OFFSET + __SIZEOF_SIZE_T__ + (1 + 164) * __SIZEOF_POINTER__) ADD_TEST_EQ(THREAD_CURRENT_IBASE_OFFSET, art::Thread::MterpCurrentIBaseOffset<POINTER_SIZE>().Int32Value()) // Offset of field Thread::tlsPtr_.mterp_default_ibase. diff --git a/runtime/entrypoints/entrypoint_utils.cc b/runtime/entrypoints/entrypoint_utils.cc index df184bc733..a58946ae66 100644 --- a/runtime/entrypoints/entrypoint_utils.cc +++ b/runtime/entrypoints/entrypoint_utils.cc @@ -260,6 +260,13 @@ ArtMethod* GetCalleeSaveOuterMethod(Thread* self, CalleeSaveType type) { return DoGetCalleeSaveMethodOuterCallerAndPc(sp, type).first; } +ObjPtr<mirror::MethodHandle> ResolveMethodHandleFromCode(ArtMethod* referrer, + uint32_t method_handle_idx) { + Thread::PoisonObjectPointersIfDebug(); + ClassLinker* class_linker = Runtime::Current()->GetClassLinker(); + return class_linker->ResolveMethodHandle(Thread::Current(), method_handle_idx, referrer); +} + ObjPtr<mirror::MethodType> ResolveMethodTypeFromCode(ArtMethod* referrer, uint32_t proto_idx) { Thread::PoisonObjectPointersIfDebug(); diff --git a/runtime/entrypoints/entrypoint_utils.h b/runtime/entrypoints/entrypoint_utils.h index 203ff3d031..0a3b5dfc93 100644 --- a/runtime/entrypoints/entrypoint_utils.h +++ b/runtime/entrypoints/entrypoint_utils.h @@ -34,6 +34,7 @@ namespace art { namespace mirror { class Array; class Class; +class MethodHandle; class MethodType; class Object; class String; @@ -152,6 +153,11 @@ inline ObjPtr<mirror::Class> ResolveVerifyAndClinit(dex::TypeIndex type_idx, REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(!Roles::uninterruptible_); +ObjPtr<mirror::MethodHandle> ResolveMethodHandleFromCode(ArtMethod* referrer, + uint32_t method_handle_idx) + REQUIRES_SHARED(Locks::mutator_lock_) + REQUIRES(!Roles::uninterruptible_); + ObjPtr<mirror::MethodType> ResolveMethodTypeFromCode(ArtMethod* referrer, uint32_t proto_idx) REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(!Roles::uninterruptible_); diff --git a/runtime/entrypoints/quick/quick_default_externs.h b/runtime/entrypoints/quick/quick_default_externs.h index d934a532ee..1804d9e64d 100644 --- a/runtime/entrypoints/quick/quick_default_externs.h +++ b/runtime/entrypoints/quick/quick_default_externs.h @@ -37,6 +37,7 @@ extern "C" void art_quick_check_instance_of(art::mirror::Object*, art::mirror::C extern "C" void* art_quick_initialize_static_storage(uint32_t); extern "C" void* art_quick_initialize_type(uint32_t); extern "C" void* art_quick_initialize_type_and_verify_access(uint32_t); +extern "C" void* art_quick_resolve_method_handle(uint32_t); extern "C" void* art_quick_resolve_method_type(uint32_t); extern "C" void* art_quick_resolve_string(uint32_t); diff --git a/runtime/entrypoints/quick/quick_default_init_entrypoints.h b/runtime/entrypoints/quick/quick_default_init_entrypoints.h index a4572f65a7..3f66045576 100644 --- a/runtime/entrypoints/quick/quick_default_init_entrypoints.h +++ b/runtime/entrypoints/quick/quick_default_init_entrypoints.h @@ -37,6 +37,7 @@ static void DefaultInitEntryPoints(JniEntryPoints* jpoints, QuickEntryPoints* qp qpoints->pInitializeStaticStorage = art_quick_initialize_static_storage; qpoints->pInitializeTypeAndVerifyAccess = art_quick_initialize_type_and_verify_access; qpoints->pInitializeType = art_quick_initialize_type; + qpoints->pResolveMethodHandle = art_quick_resolve_method_handle; qpoints->pResolveMethodType = art_quick_resolve_method_type; qpoints->pResolveString = art_quick_resolve_string; diff --git a/runtime/entrypoints/quick/quick_dexcache_entrypoints.cc b/runtime/entrypoints/quick/quick_dexcache_entrypoints.cc index 09cbfffe4b..cf9ddd8aa8 100644 --- a/runtime/entrypoints/quick/quick_dexcache_entrypoints.cc +++ b/runtime/entrypoints/quick/quick_dexcache_entrypoints.cc @@ -183,6 +183,17 @@ extern "C" mirror::Class* artInitializeTypeAndVerifyAccessFromCode(uint32_t type return result.Ptr(); } +extern "C" mirror::MethodHandle* artResolveMethodHandleFromCode(uint32_t method_handle_idx, + Thread* self) + REQUIRES_SHARED(Locks::mutator_lock_) { + ScopedQuickEntrypointChecks sqec(self); + auto caller_and_outer = + GetCalleeSaveMethodCallerAndOuterMethod(self, CalleeSaveType::kSaveEverything); + ArtMethod* caller = caller_and_outer.caller; + ObjPtr<mirror::MethodHandle> result = ResolveMethodHandleFromCode(caller, method_handle_idx); + return result.Ptr(); +} + extern "C" mirror::MethodType* artResolveMethodTypeFromCode(uint32_t proto_idx, Thread* self) REQUIRES_SHARED(Locks::mutator_lock_) { ScopedQuickEntrypointChecks sqec(self); diff --git a/runtime/entrypoints/quick/quick_entrypoints_list.h b/runtime/entrypoints/quick/quick_entrypoints_list.h index 39dcd39208..3a8faca11d 100644 --- a/runtime/entrypoints/quick/quick_entrypoints_list.h +++ b/runtime/entrypoints/quick/quick_entrypoints_list.h @@ -38,6 +38,7 @@ V(InitializeStaticStorage, void*, uint32_t) \ V(InitializeTypeAndVerifyAccess, void*, uint32_t) \ V(InitializeType, void*, uint32_t) \ + V(ResolveMethodHandle, void*, uint32_t) \ V(ResolveMethodType, void*, uint32_t) \ V(ResolveString, void*, uint32_t) \ \ diff --git a/runtime/entrypoints_order_test.cc b/runtime/entrypoints_order_test.cc index b0689f6cd3..1337cd5fb2 100644 --- a/runtime/entrypoints_order_test.cc +++ b/runtime/entrypoints_order_test.cc @@ -183,7 +183,8 @@ class EntrypointsOrderTest : public CommonRuntimeTest { sizeof(void*)); EXPECT_OFFSET_DIFFNP(QuickEntryPoints, pInitializeTypeAndVerifyAccess, pInitializeType, sizeof(void*)); - EXPECT_OFFSET_DIFFNP(QuickEntryPoints, pInitializeType, pResolveMethodType, sizeof(void*)); + EXPECT_OFFSET_DIFFNP(QuickEntryPoints, pInitializeType, pResolveMethodHandle, sizeof(void*)); + EXPECT_OFFSET_DIFFNP(QuickEntryPoints, pResolveMethodHandle, pResolveMethodType, sizeof(void*)); EXPECT_OFFSET_DIFFNP(QuickEntryPoints, pResolveMethodType, pResolveString, sizeof(void*)); EXPECT_OFFSET_DIFFNP(QuickEntryPoints, pResolveString, pSet8Instance, sizeof(void*)); EXPECT_OFFSET_DIFFNP(QuickEntryPoints, pSet8Instance, pSet8Static, sizeof(void*)); diff --git a/runtime/oat.h b/runtime/oat.h index 9a58ded7e8..6c683f1541 100644 --- a/runtime/oat.h +++ b/runtime/oat.h @@ -32,8 +32,8 @@ class InstructionSetFeatures; class PACKED(4) OatHeader { public: static constexpr uint8_t kOatMagic[] = { 'o', 'a', 't', '\n' }; - // Last oat version changed reason: compiler support const-method-type - static constexpr uint8_t kOatVersion[] = { '1', '4', '2', '\0' }; + // Last oat version changed reason: compiler support const-method-handle + static constexpr uint8_t kOatVersion[] = { '1', '4', '3', '\0' }; static constexpr const char* kImageLocationKey = "image-location"; static constexpr const char* kDex2OatCmdLineKey = "dex2oat-cmdline"; diff --git a/runtime/verifier/method_verifier.cc b/runtime/verifier/method_verifier.cc index 5cd60915b5..3518d2facd 100644 --- a/runtime/verifier/method_verifier.cc +++ b/runtime/verifier/method_verifier.cc @@ -2287,8 +2287,6 @@ bool MethodVerifier::CodeFlowVerifyInstruction(uint32_t* start_guess) { case Instruction::CONST_METHOD_HANDLE: work_line_->SetRegisterType<LockOp::kClear>( this, inst->VRegA_21c(), reg_types_.JavaLangInvokeMethodHandle()); - // TODO: add compiler support for const-method-{handle,type} (b/66890674) - Fail(VERIFY_ERROR_FORCE_INTERPRETER); break; case Instruction::CONST_METHOD_TYPE: work_line_->SetRegisterType<LockOp::kClear>( diff --git a/test/979-const-method-handle/expected.txt b/test/979-const-method-handle/expected.txt index 2d169b9508..bbaaedb0af 100644 --- a/test/979-const-method-handle/expected.txt +++ b/test/979-const-method-handle/expected.txt @@ -5,4 +5,5 @@ Hello World! And Hello Zog Hello World! And Hello Zorba name is HoverFly 2.718281828459045 +repeatConstMethodHandle() Attempting to set Math.E raised IAE diff --git a/test/979-const-method-handle/src/Main.java b/test/979-const-method-handle/src/Main.java index 79be913a67..427ca7a306 100644 --- a/test/979-const-method-handle/src/Main.java +++ b/test/979-const-method-handle/src/Main.java @@ -20,12 +20,25 @@ import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodType; class Main { + /** + * Number of iterations run to attempt to trigger JIT compilation. These tests run on ART and + * the RI so they iterate rather than using the ART only native method ensureJitCompiled(). + */ + private static final int ITERATIONS_FOR_JIT = 12000; + + /** A static field updated by method handle getters and setters. */ private static String name = "default"; private static void unreachable() { throw new Error("Unreachable"); } + private static void assertEquals(Object expected, Object actual) { + if (!expected.equals(actual)) { + throw new AssertionError("Assertion failure: " + expected + " != " + actual); + } + } + private static class LocalClass { public LocalClass() {} @@ -52,15 +65,9 @@ class Main { System.out.print("repeatConstMethodType0("); System.out.print(expected); System.out.println(")"); - for (int i = 0; i < 12000; ++i) { + for (int i = 0; i < ITERATIONS_FOR_JIT; ++i) { MethodType actual = methodType0(); - if (!actual.equals(expected)) { - System.out.print("Expected: "); - System.out.println(expected); - System.out.print("Actual: "); - System.out.println(actual); - unreachable(); - } + assertEquals(expected, actual); } } @@ -68,15 +75,9 @@ class Main { System.out.print("repeatConstMethodType1("); System.out.print(expected); System.out.println(")"); - for (int i = 0; i < 12000; ++i) { + for (int i = 0; i < ITERATIONS_FOR_JIT; ++i) { MethodType actual = methodType1(); - if (!actual.equals(expected)) { - System.out.print("Expected: "); - System.out.println(expected); - System.out.print("Actual: "); - System.out.println(actual); - unreachable(); - } + assertEquals(expected, actual); } } @@ -107,6 +108,16 @@ class Main { @ConstantMethodHandle( kind = ConstantMethodHandle.STATIC_GET, + owner = "Main", + fieldOrMethodName = "name", + descriptor = "Ljava/lang/String;") + private static MethodHandle getNameHandle() { + unreachable(); + return null; + } + + @ConstantMethodHandle( + kind = ConstantMethodHandle.STATIC_GET, owner = "java/lang/Math", fieldOrMethodName = "E", descriptor = "D") @@ -125,6 +136,18 @@ class Main { return null; } + private static void repeatConstMethodHandle() throws Throwable { + System.out.println("repeatConstMethodHandle()"); + String[] values = {"A", "B", "C"}; + for (int i = 0; i < ITERATIONS_FOR_JIT; ++i) { + String value = values[i % values.length]; + setNameHandle().invoke(value); + String actual = (String) getNameHandle().invokeExact(); + assertEquals(value, actual); + assertEquals(value, name); + } + } + public static void main(String[] args) throws Throwable { System.out.println(methodType0()); repeatConstMethodType0( @@ -136,6 +159,7 @@ class Main { System.out.print("name is "); System.out.println(name); System.out.println(getMathE().invoke()); + repeatConstMethodHandle(); try { putMathE().invokeExact(Math.PI); unreachable(); |