diff options
-rw-r--r-- | compiler/optimizing/intrinsics_arm64.cc | 35 | ||||
-rw-r--r-- | compiler/optimizing/intrinsics_x86_64.cc | 35 | ||||
-rw-r--r-- | runtime/class_linker.cc | 5 | ||||
-rw-r--r-- | runtime/mirror/method_handle_impl.cc | 13 | ||||
-rw-r--r-- | runtime/mirror/method_handle_impl.h | 10 | ||||
-rw-r--r-- | runtime/well_known_classes.cc | 8 | ||||
-rw-r--r-- | runtime/well_known_classes.h | 1 |
7 files changed, 96 insertions, 11 deletions
diff --git a/compiler/optimizing/intrinsics_arm64.cc b/compiler/optimizing/intrinsics_arm64.cc index 75607b77e0..c4f8681631 100644 --- a/compiler/optimizing/intrinsics_arm64.cc +++ b/compiler/optimizing/intrinsics_arm64.cc @@ -16,6 +16,8 @@ #include "intrinsics_arm64.h" +#include "aarch64/assembler-aarch64.h" +#include "aarch64/operands-aarch64.h" #include "arch/arm64/callee_save_frame_arm64.h" #include "arch/arm64/instruction_set_features_arm64.h" #include "art_method.h" @@ -33,6 +35,7 @@ #include "mirror/array-inl.h" #include "mirror/class.h" #include "mirror/method_handle_impl.h" +#include "mirror/method_type.h" #include "mirror/object.h" #include "mirror/object_array-inl.h" #include "mirror/reference.h" @@ -5981,30 +5984,46 @@ void IntrinsicLocationsBuilderARM64::VisitMethodHandleInvokeExact(HInvoke* invok InvokeDexCallingConventionVisitorARM64 calling_convention; locations->SetOut(calling_convention.GetReturnLocation(invoke->GetType())); - locations->SetInAt(0, Location::RequiresRegister()); - // Accomodating LocationSummary for underlying invoke-* call. uint32_t number_of_args = invoke->GetNumberOfArguments(); + for (uint32_t i = 1; i < number_of_args; ++i) { locations->SetInAt(i, calling_convention.GetNextLocation(invoke->InputAt(i)->GetType())); } + // Passing MethodHandle object as the last parameter: accessors implementation rely on it. + DCHECK_EQ(invoke->InputAt(0)->GetType(), DataType::Type::kReference); + Location receiver_mh_loc = calling_convention.GetNextLocation(DataType::Type::kReference); + locations->SetInAt(0, receiver_mh_loc); + // The last input is MethodType object corresponding to the call-site. locations->SetInAt(number_of_args, Location::RequiresRegister()); locations->AddTemp(calling_convention.GetMethodLocation()); locations->AddRegisterTemps(4); + + if (!receiver_mh_loc.IsRegister()) { + locations->AddTemp(Location::RequiresRegister()); + } } void IntrinsicCodeGeneratorARM64::VisitMethodHandleInvokeExact(HInvoke* invoke) { LocationSummary* locations = invoke->GetLocations(); + MacroAssembler* masm = codegen_->GetVIXLAssembler(); + + Location receiver_mh_loc = locations->InAt(0); + Register method_handle = receiver_mh_loc.IsRegister() + ? InputRegisterAt(invoke, 0) + : WRegisterFrom(locations->GetTemp(5)); - Register method_handle = InputRegisterAt(invoke, 0); + if (!receiver_mh_loc.IsRegister()) { + DCHECK(receiver_mh_loc.IsStackSlot()); + __ Ldr(method_handle.W(), MemOperand(sp, receiver_mh_loc.GetStackIndex())); + } SlowPathCodeARM64* slow_path = new (codegen_->GetScopedAllocator()) InvokePolymorphicSlowPathARM64(invoke, method_handle); codegen_->AddSlowPath(slow_path); - MacroAssembler* masm = codegen_->GetVIXLAssembler(); Register call_site_type = InputRegisterAt(invoke, invoke->GetNumberOfArguments()); @@ -6019,10 +6038,18 @@ void IntrinsicCodeGeneratorARM64::VisitMethodHandleInvokeExact(HInvoke* invoke) __ Ldr(method, HeapOperand(method_handle.W(), mirror::MethodHandle::ArtFieldOrMethodOffset())); vixl::aarch64::Label execute_target_method; + vixl::aarch64::Label method_dispatch; Register method_handle_kind = WRegisterFrom(locations->GetTemp(2)); __ Ldr(method_handle_kind, HeapOperand(method_handle.W(), mirror::MethodHandle::HandleKindOffset())); + + __ Cmp(method_handle_kind, Operand(mirror::MethodHandle::Kind::kFirstAccessorKind)); + __ B(lt, &method_dispatch); + __ Ldr(method, HeapOperand(method_handle.W(), mirror::MethodHandleImpl::TargetOffset())); + __ B(&execute_target_method); + + __ Bind(&method_dispatch); __ Cmp(method_handle_kind, Operand(mirror::MethodHandle::Kind::kInvokeStatic)); __ B(eq, &execute_target_method); diff --git a/compiler/optimizing/intrinsics_x86_64.cc b/compiler/optimizing/intrinsics_x86_64.cc index 281f196f06..2508df3382 100644 --- a/compiler/optimizing/intrinsics_x86_64.cc +++ b/compiler/optimizing/intrinsics_x86_64.cc @@ -32,6 +32,7 @@ #include "intrinsics_utils.h" #include "lock_word.h" #include "mirror/array-inl.h" +#include "mirror/method_handle_impl.h" #include "mirror/object_array-inl.h" #include "mirror/reference.h" #include "mirror/string.h" @@ -4241,31 +4242,47 @@ void IntrinsicLocationsBuilderX86_64::VisitMethodHandleInvokeExact(HInvoke* invo InvokeDexCallingConventionVisitorX86_64 calling_convention; locations->SetOut(calling_convention.GetReturnLocation(invoke->GetType())); - locations->SetInAt(0, Location::RequiresRegister()); + uint32_t number_of_args = invoke->GetNumberOfArguments(); // Accomodating LocationSummary for underlying invoke-* call. - uint32_t number_of_args = invoke->GetNumberOfArguments(); for (uint32_t i = 1; i < number_of_args; ++i) { locations->SetInAt(i, calling_convention.GetNextLocation(invoke->InputAt(i)->GetType())); } + // Passing MethodHandle object as the last parameter: accessors implementation rely on it. + DCHECK_EQ(invoke->InputAt(0)->GetType(), DataType::Type::kReference); + Location receiver_mh_loc = calling_convention.GetNextLocation(DataType::Type::kReference); + locations->SetInAt(0, receiver_mh_loc); + // The last input is MethodType object corresponding to the call-site. locations->SetInAt(number_of_args, Location::RequiresRegister()); locations->AddTemp(Location::RequiresRegister()); // Hidden arg for invoke-interface. locations->AddTemp(Location::RegisterLocation(RAX)); + + if (!receiver_mh_loc.IsRegister()) { + locations->AddTemp(Location::RequiresRegister()); + } } void IntrinsicCodeGeneratorX86_64::VisitMethodHandleInvokeExact(HInvoke* invoke) { LocationSummary* locations = invoke->GetLocations(); + X86_64Assembler* assembler = codegen_->GetAssembler(); - CpuRegister method_handle = locations->InAt(0).AsRegister<CpuRegister>(); + Location receiver_mh_loc = locations->InAt(0); + CpuRegister method_handle = receiver_mh_loc.IsRegister() + ? receiver_mh_loc.AsRegister<CpuRegister>() + : locations->GetTemp(2).AsRegister<CpuRegister>(); + + if (!receiver_mh_loc.IsRegister()) { + DCHECK(receiver_mh_loc.IsStackSlot()); + __ movl(method_handle, Address(CpuRegister(RSP), receiver_mh_loc.GetStackIndex())); + } SlowPathCode* slow_path = new (codegen_->GetScopedAllocator()) InvokePolymorphicSlowPathX86_64(invoke, method_handle); codegen_->AddSlowPath(slow_path); - X86_64Assembler* assembler = codegen_->GetAssembler(); CpuRegister call_site_type = locations->InAt(invoke->GetNumberOfArguments()).AsRegister<CpuRegister>(); @@ -4278,10 +4295,18 @@ void IntrinsicCodeGeneratorX86_64::VisitMethodHandleInvokeExact(HInvoke* invoke) CpuRegister method = CpuRegister(kMethodRegisterArgument); __ movq(method, Address(method_handle, mirror::MethodHandle::ArtFieldOrMethodOffset())); - Label static_dispatch; Label execute_target_method; + Label method_dispatch; + Label static_dispatch; Address method_handle_kind = Address(method_handle, mirror::MethodHandle::HandleKindOffset()); + + __ cmpl(method_handle_kind, Immediate(mirror::MethodHandle::kFirstAccessorKind)); + __ j(kLess, &method_dispatch); + __ movq(method, Address(method_handle, mirror::MethodHandleImpl::TargetOffset())); + __ Jump(&execute_target_method); + + __ Bind(&method_dispatch); if (invoke->AsInvokePolymorphic()->CanTargetInstanceMethod()) { CpuRegister receiver = locations->InAt(1).AsRegister<CpuRegister>(); diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc index 70eea2d268..009d705caf 100644 --- a/runtime/class_linker.cc +++ b/runtime/class_linker.cc @@ -10569,7 +10569,7 @@ ObjPtr<mirror::MethodHandle> ClassLinker::ResolveMethodHandleForField( return nullptr; } - StackHandleScope<4> hs(self); + StackHandleScope<5> hs(self); ObjPtr<mirror::Class> array_of_class = GetClassRoot<mirror::ObjectArray<mirror::Class>>(this); Handle<mirror::ObjectArray<mirror::Class>> method_params(hs.NewHandle( mirror::ObjectArray<mirror::Class>::Alloc(self, array_of_class, num_params))); @@ -10629,7 +10629,8 @@ ObjPtr<mirror::MethodHandle> ClassLinker::ResolveMethodHandleForField( return nullptr; } - uintptr_t target = reinterpret_cast<uintptr_t>(target_field); + Handle<mirror::Field> target(hs.NewHandle( + mirror::Field::CreateFromArtField(self, target_field, /*force_resolve=*/ true))); return mirror::MethodHandleImpl::Create(self, target, kind, method_type); } diff --git a/runtime/mirror/method_handle_impl.cc b/runtime/mirror/method_handle_impl.cc index 5e80fb0925..0190c4bb4a 100644 --- a/runtime/mirror/method_handle_impl.cc +++ b/runtime/mirror/method_handle_impl.cc @@ -58,6 +58,19 @@ ObjPtr<mirror::MethodHandleImpl> MethodHandleImpl::Create(Thread* const self, return mh.Get(); } +ObjPtr<mirror::MethodHandleImpl> MethodHandleImpl::Create(Thread* const self, + Handle<Field> field, + MethodHandle::Kind kind, + Handle<MethodType> method_type) + REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(!Roles::uninterruptible_) { + StackHandleScope<1> hs(self); + Handle<mirror::MethodHandleImpl> mh(hs.NewHandle(ObjPtr<MethodHandleImpl>::DownCast( + WellKnownClasses::java_lang_invoke_MethodHandleImpl_fieldInit->NewObject<'L', 'I', 'L'>( + self, field, static_cast<uint32_t>(kind), method_type)))); + + return mh.Get(); +} + void MethodHandle::VisitTarget(ReflectiveValueVisitor* v) { void* target = GetTargetField(); void* result; diff --git a/runtime/mirror/method_handle_impl.h b/runtime/mirror/method_handle_impl.h index b5d1d9ad25..a4a6e67a5a 100644 --- a/runtime/mirror/method_handle_impl.h +++ b/runtime/mirror/method_handle_impl.h @@ -128,6 +128,16 @@ class MANAGED MethodHandleImpl : public MethodHandle { Handle<MethodType> method_type) REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(!Roles::uninterruptible_); + EXPORT static ObjPtr<mirror::MethodHandleImpl> Create(Thread* const self, + Handle<Field> field, + MethodHandle::Kind kind, + Handle<MethodType> method_type) + REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(!Roles::uninterruptible_); + + static MemberOffset TargetOffset() { + return MemberOffset(OFFSETOF_MEMBER(MethodHandleImpl, target_)); + } + private: HeapReference<mirror::Field> field_; HeapReference<mirror::Object> target_class_or_info_; // Unused by the runtime. diff --git a/runtime/well_known_classes.cc b/runtime/well_known_classes.cc index 5a1e7f4264..14b0feecb6 100644 --- a/runtime/well_known_classes.cc +++ b/runtime/well_known_classes.cc @@ -95,6 +95,7 @@ ArtMethod* WellKnownClasses::java_lang_ThreadGroup_add; ArtMethod* WellKnownClasses::java_lang_ThreadGroup_threadTerminated; ArtMethod* WellKnownClasses::java_lang_invoke_MethodHandle_asType; ArtMethod* WellKnownClasses::java_lang_invoke_MethodHandle_invokeExact; +ArtMethod* WellKnownClasses::java_lang_invoke_MethodHandleImpl_fieldInit; ArtMethod* WellKnownClasses::java_lang_invoke_MethodHandleImpl_init; ArtMethod* WellKnownClasses::java_lang_invoke_MethodHandles_lookup; ArtMethod* WellKnownClasses::java_lang_invoke_MethodHandles_makeIdentity; @@ -645,6 +646,12 @@ void WellKnownClasses::InitFieldsAndMethodsOnly(JNIEnv* env) { "invokeExact", "([Ljava/lang/Object;)Ljava/lang/Object;", pointer_size); + java_lang_invoke_MethodHandleImpl_fieldInit = CacheMethod( + j_l_i_MethodHandleImpl.Get(), + /*is_static=*/ false, + "<init>", + "(Ljava/lang/reflect/Field;ILjava/lang/invoke/MethodType;)V", + pointer_size); java_lang_invoke_MethodHandleImpl_init = CacheMethod( j_l_i_MethodHandleImpl.Get(), /*is_static=*/ false, @@ -955,6 +962,7 @@ void WellKnownClasses::Clear() { java_lang_invoke_MethodHandle_asType = nullptr; java_lang_invoke_MethodHandle_invokeExact = nullptr; java_lang_invoke_MethodHandleImpl_init = nullptr; + java_lang_invoke_MethodHandleImpl_fieldInit = nullptr; java_lang_invoke_MethodHandles_lookup = nullptr; java_lang_invoke_MethodHandles_makeIdentity = nullptr; java_lang_invoke_MethodHandles_Lookup_findConstructor = nullptr; diff --git a/runtime/well_known_classes.h b/runtime/well_known_classes.h index 5a70b80839..8798744448 100644 --- a/runtime/well_known_classes.h +++ b/runtime/well_known_classes.h @@ -141,6 +141,7 @@ struct EXPORT WellKnownClasses { static ArtMethod* java_lang_ThreadGroup_threadTerminated; static ArtMethod* java_lang_invoke_MethodHandle_asType; static ArtMethod* java_lang_invoke_MethodHandle_invokeExact; + static ArtMethod* java_lang_invoke_MethodHandleImpl_fieldInit; static ArtMethod* java_lang_invoke_MethodHandleImpl_init; static ArtMethod* java_lang_invoke_MethodHandles_lookup; static ArtMethod* java_lang_invoke_MethodHandles_makeIdentity; |