Use virtual dispatch for `MethodHandle.asType()`.
The non-virtual dispatch was a mistake in
https://android-review.googlesource.com/1944906 .
Change well known method handle methods to `ArtMethod*`.
Test: m test-art-host-gtest
Test: testrunner.py --host --optimizing
Test: atest CtsLibcoreTestCases
Change-Id: I3670ca6a229942e2edbd351a922f83f5d20d0c09
diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc
index 919383f..6480dfd 100644
--- a/runtime/class_linker.cc
+++ b/runtime/class_linker.cc
@@ -1144,6 +1144,8 @@
// Ensure `Thread` and `ThreadGroup` classes are initialized (avoid check at runtime).
WellKnownClasses::java_lang_Thread_init,
WellKnownClasses::java_lang_ThreadGroup_add,
+ // Ensure `MethodHandles` class is initialized (avoid check at runtime).
+ WellKnownClasses::java_lang_invoke_MethodHandles_lookup,
// Ensure `DirectByteBuffer` class is initialized (avoid check at runtime).
WellKnownClasses::java_nio_DirectByteBuffer_init,
// Ensure reflection annotation classes are initialized (avoid check at runtime).
diff --git a/runtime/method_handles.cc b/runtime/method_handles.cc
index 73ec31e..a992af0 100644
--- a/runtime/method_handles.cc
+++ b/runtime/method_handles.cc
@@ -864,19 +864,13 @@
if (atc == nullptr || !callsite_type->IsExactMatch(atc->GetMethodType())) {
// Cached asType adapter does not exist or is for another call site. Call
// MethodHandle::asType() to get an appropriate adapter.
- ArtMethod* as_type =
- jni::DecodeArtMethod(WellKnownClasses::java_lang_invoke_MethodHandle_asType);
- uint32_t as_type_args[] = {
- static_cast<uint32_t>(reinterpret_cast<uintptr_t>(method_handle.Get())),
- static_cast<uint32_t>(reinterpret_cast<uintptr_t>(callsite_type.Get()))};
- JValue atc_result;
- as_type->Invoke(self, as_type_args, sizeof(as_type_args), &atc_result, "LL");
- if (atc_result.GetL() == nullptr) {
+ ArtMethod* as_type = WellKnownClasses::java_lang_invoke_MethodHandle_asType;
+ ObjPtr<mirror::MethodHandle> atc_method_handle = ObjPtr<mirror::MethodHandle>::DownCast(
+ as_type->InvokeVirtual<'L', 'L'>(self, method_handle.Get(), callsite_type.Get()));
+ if (atc_method_handle == nullptr) {
DCHECK(self->IsExceptionPending());
return false;
}
- ObjPtr<mirror::MethodHandle> atc_method_handle =
- down_cast<mirror::MethodHandle*>(atc_result.GetL());
atc.Assign(atc_method_handle);
DCHECK(!atc.IsNull());
}
@@ -917,8 +911,7 @@
const uint16_t num_vregs = callsite_type->NumberOfVRegs();
const char* old_cause = self->StartAssertNoThreadSuspension("EmulatedStackFrame to ShadowFrame");
- ArtMethod* invoke_exact =
- jni::DecodeArtMethod(WellKnownClasses::java_lang_invoke_MethodHandle_invokeExact);
+ ArtMethod* invoke_exact = WellKnownClasses::java_lang_invoke_MethodHandle_invokeExact;
ShadowFrameAllocaUniquePtr shadow_frame =
CREATE_SHADOW_FRAME(num_vregs, invoke_exact, /*dex_pc*/ 0);
emulated_frame->WriteToShadowFrame(self, callsite_type, 0, shadow_frame.get());
diff --git a/runtime/mirror/method_handles_lookup.cc b/runtime/mirror/method_handles_lookup.cc
index e9c41f9..c4c2b58 100644
--- a/runtime/mirror/method_handles_lookup.cc
+++ b/runtime/mirror/method_handles_lookup.cc
@@ -20,7 +20,6 @@
#include "class_root-inl.h"
#include "dex/modifiers.h"
#include "handle_scope.h"
-#include "jni/jni_internal.h"
#include "mirror/method_handle_impl.h"
#include "obj_ptr-inl.h"
#include "object-inl.h"
@@ -42,25 +41,18 @@
}
ObjPtr<MethodHandlesLookup> MethodHandlesLookup::GetDefault(Thread* const self) {
- ArtMethod* lookup = jni::DecodeArtMethod(WellKnownClasses::java_lang_invoke_MethodHandles_lookup);
- JValue result;
- lookup->Invoke(self, nullptr, 0, &result, "L");
- return ObjPtr<MethodHandlesLookup>::DownCast(result.GetL());
+ ArtMethod* lookup = WellKnownClasses::java_lang_invoke_MethodHandles_lookup;
+ DCHECK(lookup->GetDeclaringClass()->IsInitialized());
+ return ObjPtr<MethodHandlesLookup>::DownCast(lookup->InvokeStatic<'L'>(self));
}
ObjPtr<MethodHandle> MethodHandlesLookup::FindConstructor(Thread* const self,
Handle<Class> klass,
Handle<MethodType> method_type) {
- ArtMethod* findConstructor =
- jni::DecodeArtMethod(WellKnownClasses::java_lang_invoke_MethodHandles_Lookup_findConstructor);
- uint32_t args[] = {
- static_cast<uint32_t>(reinterpret_cast<uintptr_t>(this)),
- static_cast<uint32_t>(reinterpret_cast<uintptr_t>(klass.Get())),
- static_cast<uint32_t>(reinterpret_cast<uintptr_t>(method_type.Get()))
- };
- JValue result;
- findConstructor->Invoke(self, args, sizeof(args), &result, "LLL");
- return ObjPtr<MethodHandle>::DownCast(result.GetL());
+ ArtMethod* find_constructor =
+ WellKnownClasses::java_lang_invoke_MethodHandles_Lookup_findConstructor;
+ return ObjPtr<MethodHandle>::DownCast(
+ find_constructor->InvokeFinal<'L', 'L', 'L'>(self, this, klass.Get(), method_type.Get()));
}
} // namespace mirror
diff --git a/runtime/well_known_classes.cc b/runtime/well_known_classes.cc
index 9f1b8e7..a30d2d0 100644
--- a/runtime/well_known_classes.cc
+++ b/runtime/well_known_classes.cc
@@ -95,10 +95,10 @@
ArtMethod* WellKnownClasses::java_lang_Float_floatToRawIntBits;
ArtMethod* WellKnownClasses::java_lang_Float_valueOf;
ArtMethod* WellKnownClasses::java_lang_Integer_valueOf;
-jmethodID WellKnownClasses::java_lang_invoke_MethodHandle_asType;
-jmethodID WellKnownClasses::java_lang_invoke_MethodHandle_invokeExact;
-jmethodID WellKnownClasses::java_lang_invoke_MethodHandles_lookup;
-jmethodID WellKnownClasses::java_lang_invoke_MethodHandles_Lookup_findConstructor;
+ArtMethod* WellKnownClasses::java_lang_invoke_MethodHandle_asType;
+ArtMethod* WellKnownClasses::java_lang_invoke_MethodHandle_invokeExact;
+ArtMethod* WellKnownClasses::java_lang_invoke_MethodHandles_lookup;
+ArtMethod* WellKnownClasses::java_lang_invoke_MethodHandles_Lookup_findConstructor;
ArtMethod* WellKnownClasses::java_lang_Long_valueOf;
jmethodID WellKnownClasses::java_lang_ref_FinalizerReference_add;
jmethodID WellKnownClasses::java_lang_ref_ReferenceQueue_add;
@@ -430,10 +430,6 @@
java_lang_Daemons_start = CacheMethod(env, java_lang_Daemons, true, "start", "()V");
java_lang_Daemons_stop = CacheMethod(env, java_lang_Daemons, true, "stop", "()V");
java_lang_Daemons_waitForDaemonStart = CacheMethod(env, java_lang_Daemons, true, "waitForDaemonStart", "()V");
- java_lang_invoke_MethodHandle_asType = CacheMethod(env, "java/lang/invoke/MethodHandle", false, "asType", "(Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/MethodHandle;");
- java_lang_invoke_MethodHandle_invokeExact = CacheMethod(env, "java/lang/invoke/MethodHandle", false, "invokeExact", "([Ljava/lang/Object;)Ljava/lang/Object;");
- java_lang_invoke_MethodHandles_lookup = CacheMethod(env, "java/lang/invoke/MethodHandles", true, "lookup", "()Ljava/lang/invoke/MethodHandles$Lookup;");
- java_lang_invoke_MethodHandles_Lookup_findConstructor = CacheMethod(env, "java/lang/invoke/MethodHandles$Lookup", false, "findConstructor", "(Ljava/lang/Class;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/MethodHandle;");
java_lang_ref_FinalizerReference_add = CacheMethod(env, "java/lang/ref/FinalizerReference", true, "add", "(Ljava/lang/Object;)V");
java_lang_ref_ReferenceQueue_add = CacheMethod(env, "java/lang/ref/ReferenceQueue", true, "add", "(Ljava/lang/ref/Reference;)V");
@@ -442,7 +438,7 @@
java_lang_reflect_Parameter_init = CacheMethod(env, java_lang_reflect_Parameter, false, "<init>", "(Ljava/lang/String;ILjava/lang/reflect/Executable;I)V");
java_lang_String_charAt = CacheMethod(env, java_lang_String, false, "charAt", "(I)C");
- StackHandleScope<14u> hs(self);
+ StackHandleScope<17u> hs(self);
Handle<mirror::Class> d_s_vmr =
hs.NewHandle(FindSystemClass(class_linker, self, "Ldalvik/system/VMRuntime;"));
Handle<mirror::Class> j_i_fd =
@@ -451,6 +447,12 @@
hs.NewHandle(FindSystemClass(class_linker, self, "Ljava/lang/Thread;"));
Handle<mirror::Class> j_l_tg =
hs.NewHandle(FindSystemClass(class_linker, self, "Ljava/lang/ThreadGroup;"));
+ Handle<mirror::Class> j_l_i_MethodHandle =
+ hs.NewHandle(FindSystemClass(class_linker, self, "Ljava/lang/invoke/MethodHandle;"));
+ Handle<mirror::Class> j_l_i_MethodHandles =
+ hs.NewHandle(FindSystemClass(class_linker, self, "Ljava/lang/invoke/MethodHandles;"));
+ Handle<mirror::Class> j_l_i_MethodHandles_Lookup =
+ hs.NewHandle(FindSystemClass(class_linker, self, "Ljava/lang/invoke/MethodHandles$Lookup;"));
Handle<mirror::Class> j_n_b =
hs.NewHandle(FindSystemClass(class_linker, self, "Ljava/nio/Buffer;"));
Handle<mirror::Class> j_n_bb =
@@ -512,6 +514,31 @@
"(Ljava/lang/Thread;)V",
pointer_size);
+ java_lang_invoke_MethodHandle_asType = CacheMethod(
+ j_l_i_MethodHandle.Get(),
+ /*is_static=*/ false,
+ "asType",
+ "(Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/MethodHandle;",
+ pointer_size);
+ java_lang_invoke_MethodHandle_invokeExact = CacheMethod(
+ j_l_i_MethodHandle.Get(),
+ /*is_static=*/ false,
+ "invokeExact",
+ "([Ljava/lang/Object;)Ljava/lang/Object;",
+ pointer_size);
+ java_lang_invoke_MethodHandles_lookup = CacheMethod(
+ j_l_i_MethodHandles.Get(),
+ /*is_static=*/ true,
+ "lookup",
+ "()Ljava/lang/invoke/MethodHandles$Lookup;",
+ pointer_size);
+ java_lang_invoke_MethodHandles_Lookup_findConstructor = CacheMethod(
+ j_l_i_MethodHandles_Lookup.Get(),
+ /*is_static=*/ false,
+ "findConstructor",
+ "(Ljava/lang/Class;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/MethodHandle;",
+ pointer_size);
+
java_nio_Buffer_isDirect =
CacheMethod(j_n_b.Get(), /*is_static=*/ false, "isDirect", "()Z", pointer_size);
java_nio_DirectByteBuffer_init =
diff --git a/runtime/well_known_classes.h b/runtime/well_known_classes.h
index 0a58766..1f5b03f 100644
--- a/runtime/well_known_classes.h
+++ b/runtime/well_known_classes.h
@@ -106,10 +106,10 @@
static ArtMethod* java_lang_Float_floatToRawIntBits;
static ArtMethod* java_lang_Float_valueOf;
static ArtMethod* java_lang_Integer_valueOf;
- static jmethodID java_lang_invoke_MethodHandle_asType;
- static jmethodID java_lang_invoke_MethodHandle_invokeExact;
- static jmethodID java_lang_invoke_MethodHandles_lookup;
- static jmethodID java_lang_invoke_MethodHandles_Lookup_findConstructor;
+ static ArtMethod* java_lang_invoke_MethodHandle_asType;
+ static ArtMethod* java_lang_invoke_MethodHandle_invokeExact;
+ static ArtMethod* java_lang_invoke_MethodHandles_lookup;
+ static ArtMethod* java_lang_invoke_MethodHandles_Lookup_findConstructor;
static ArtMethod* java_lang_Long_valueOf;
static jmethodID java_lang_ref_FinalizerReference_add;
static jmethodID java_lang_ref_ReferenceQueue_add;