diff options
author | 2024-10-22 16:15:54 +0100 | |
---|---|---|
committer | 2024-10-23 11:10:38 +0000 | |
commit | 0cdb0fedbf1eae14d56178eda1e800d133a76bea (patch) | |
tree | ae21c13edecc1b9cd3f4f8245a598816bfde2daf | |
parent | 398bedca50a44d26edc84e24a1c1b587cefaf8de (diff) |
x86-64: handle invoke-direct in invokeExact intrinsic.
Also fix NPE not being thrown in the interpreter when receiver is
null in invoke-direct MethodHandle.
Bug: 297147201
Test: ./art/test/testrunner/testrunner.py --host --64 --optimizing -b
Change-Id: I30d369316b56713dc7428d264fcff98954c63d37
-rw-r--r-- | compiler/optimizing/intrinsics_x86_64.cc | 11 | ||||
-rw-r--r-- | runtime/method_handles.cc | 5 | ||||
-rw-r--r-- | test/956-methodhandles/src/Main.java | 6 |
3 files changed, 19 insertions, 3 deletions
diff --git a/compiler/optimizing/intrinsics_x86_64.cc b/compiler/optimizing/intrinsics_x86_64.cc index c7ee518acb..38954c8fa1 100644 --- a/compiler/optimizing/intrinsics_x86_64.cc +++ b/compiler/optimizing/intrinsics_x86_64.cc @@ -4262,14 +4262,19 @@ void IntrinsicCodeGeneratorX86_64::VisitMethodHandleInvokeExact(HInvoke* invoke) Address method_handle_kind = Address(method_handle, mirror::MethodHandle::HandleKindOffset()); if (invoke->AsInvokePolymorphic()->CanTargetInstanceMethod()) { - // Handle invoke-virtual case. - __ cmpl(method_handle_kind, Immediate(mirror::MethodHandle::Kind::kInvokeVirtual)); - __ j(kNotEqual, &static_dispatch); CpuRegister receiver = locations->InAt(1).AsRegister<CpuRegister>(); + // Receiver shouldn't be null for all the following cases. __ testl(receiver, receiver); __ j(kEqual, slow_path->GetEntryLabel()); + __ cmpl(method_handle_kind, Immediate(mirror::MethodHandle::Kind::kInvokeDirect)); + // No dispatch is needed for invoke-direct. + __ j(kEqual, &execute_target_method); + + // Handle invoke-virtual case. + __ cmpl(method_handle_kind, Immediate(mirror::MethodHandle::Kind::kInvokeVirtual)); + __ j(kNotEqual, &static_dispatch); // Skip virtual dispatch if `method` is private. __ testl(Address(method, ArtMethod::AccessFlagsOffset()), Immediate(kAccPrivate)); __ j(kNotZero, &execute_target_method); diff --git a/runtime/method_handles.cc b/runtime/method_handles.cc index a91348ae63..741ec0d84d 100644 --- a/runtime/method_handles.cc +++ b/runtime/method_handles.cc @@ -466,6 +466,11 @@ ArtMethod* RefineTargetMethod(Thread* self, // String constructors are replaced with static StringFactory methods when a MethodHandle // object is created. DCHECK(!target_method->IsStringConstructor()); + ObjPtr<mirror::Object> receiver(shadow_frame.GetVRegReference(receiver_reg)); + if (receiver == nullptr) { + ThrowNullPointerException("null receiver"); + return nullptr; + } } else if (handle_kind == mirror::MethodHandle::Kind::kInvokeSuper) { // Note that we're not dynamically dispatching on the type of the receiver // here. We use the static type of the "receiver" object that we've diff --git a/test/956-methodhandles/src/Main.java b/test/956-methodhandles/src/Main.java index 168862c040..51f7a17779 100644 --- a/test/956-methodhandles/src/Main.java +++ b/test/956-methodhandles/src/Main.java @@ -185,6 +185,12 @@ public class Main { MethodType.methodType(void.class), D.class /* specialCaller */); mh3.invoke(dInstance); + try { + mh3.invokeExact((D) null); + fail("Expected NPE to be thrown"); + } catch (NullPointerException expected) { + } + // The private method shouldn't be accessible from any special caller except // itself... try { |