From b1ddda01bf8683e6cd1bedc556807bb0f21d4dda Mon Sep 17 00:00:00 2001 From: Tom Shull Date: Wed, 28 May 2025 16:34:59 +0200 Subject: [PATCH 1/5] Add Support for Retrieving All Non-Static Methods of a ResolvedJavaType. --- src/hotspot/share/jvmci/jvmciCompilerToVM.cpp | 34 +++++++++++++++++++ .../jdk/vm/ci/hotspot/CompilerToVM.java | 22 +++++++++++- .../HotSpotResolvedJavaMethodImpl.java | 13 +++++++ .../HotSpotResolvedObjectTypeImpl.java | 12 +++++++ .../hotspot/HotSpotResolvedPrimitiveType.java | 5 +++ .../jdk/vm/ci/meta/ResolvedJavaMethod.java | 6 ++++ .../jdk/vm/ci/meta/ResolvedJavaType.java | 8 +++++ .../runtime/test/TestResolvedJavaMethod.java | 14 ++++++++ .../ci/runtime/test/TestResolvedJavaType.java | 17 ++++++++++ 9 files changed, 130 insertions(+), 1 deletion(-) diff --git a/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp b/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp index b4b8150917dd5..435b77cd77153 100644 --- a/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp +++ b/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp @@ -577,6 +577,11 @@ C2V_VMENTRY_0(jboolean, isCompilable,(JNIEnv* env, jobject, ARGUMENT_PAIR(method return !method->is_not_compilable(CompLevel_full_optimization); C2V_END +C2V_VMENTRY_0(jboolean, isOverpass,(JNIEnv* env, jobject, ARGUMENT_PAIR(method))) + Method* method = UNPACK_PAIR(Method, method); + return method->is_overpass(); +C2V_END + C2V_VMENTRY_0(jboolean, hasNeverInlineDirective,(JNIEnv* env, jobject, ARGUMENT_PAIR(method))) methodHandle method (THREAD, UNPACK_PAIR(Method, method)); return !Inline || CompilerOracle::should_not_inline(method) || method->dont_inline(); @@ -2219,6 +2224,33 @@ C2V_VMENTRY_NULL(jobjectArray, getDeclaredMethods, (JNIEnv* env, jobject, ARGUME return JVMCIENV->get_jobjectArray(methods); C2V_END +C2V_VMENTRY_NULL(jobjectArray, getInstanceMethods, (JNIEnv* env, jobject, ARGUMENT_PAIR(klass))) + Klass* klass = UNPACK_PAIR(Klass, klass); + if (klass == nullptr) { + JVMCI_THROW_NULL(NullPointerException); + } + if (!klass->is_instance_klass()) { + JVMCIObjectArray methods = JVMCIENV->new_ResolvedJavaMethod_array(0, JVMCI_CHECK_NULL); + return JVMCIENV->get_jobjectArray(methods); + } + + InstanceKlass* iklass = InstanceKlass::cast(klass); + GrowableArray methods_array; + for (int i = 0; i < iklass->methods()->length(); i++) { + Method* m = iklass->methods()->at(i); + if (!m->is_object_initializer() && !m->is_static_initializer()) { + methods_array.append(m); + } + } + JVMCIObjectArray methods = JVMCIENV->new_ResolvedJavaMethod_array(methods_array.length(), JVMCI_CHECK_NULL); + for (int i = 0; i < methods_array.length(); i++) { + methodHandle mh(THREAD, methods_array.at(i)); + JVMCIObject method = JVMCIENV->get_jvmci_method(mh, JVMCI_CHECK_NULL); + JVMCIENV->put_object_at(methods, i, method); + } + return JVMCIENV->get_jobjectArray(methods); +C2V_END + C2V_VMENTRY_NULL(jobjectArray, getDeclaredFieldsInfo, (JNIEnv* env, jobject, ARGUMENT_PAIR(klass))) Klass* klass = UNPACK_PAIR(Klass, klass); if (klass == nullptr) { @@ -3280,6 +3312,7 @@ JNINativeMethod CompilerToVM::methods[] = { {CC "methodIsIgnoredBySecurityStackWalk", CC "(" HS_METHOD2 ")Z", FN_PTR(methodIsIgnoredBySecurityStackWalk)}, {CC "setNotInlinableOrCompilable", CC "(" HS_METHOD2 ")V", FN_PTR(setNotInlinableOrCompilable)}, {CC "isCompilable", CC "(" HS_METHOD2 ")Z", FN_PTR(isCompilable)}, + {CC "isOverpass", CC "(" HS_METHOD2 ")Z", FN_PTR(isOverpass)}, {CC "hasNeverInlineDirective", CC "(" HS_METHOD2 ")Z", FN_PTR(hasNeverInlineDirective)}, {CC "shouldInlineMethod", CC "(" HS_METHOD2 ")Z", FN_PTR(shouldInlineMethod)}, {CC "lookupType", CC "(" STRING HS_KLASS2 "IZ)" HS_RESOLVED_TYPE, FN_PTR(lookupType)}, @@ -3354,6 +3387,7 @@ JNINativeMethod CompilerToVM::methods[] = { {CC "boxPrimitive", CC "(" OBJECT ")" OBJECTCONSTANT, FN_PTR(boxPrimitive)}, {CC "getDeclaredConstructors", CC "(" HS_KLASS2 ")[" RESOLVED_METHOD, FN_PTR(getDeclaredConstructors)}, {CC "getDeclaredMethods", CC "(" HS_KLASS2 ")[" RESOLVED_METHOD, FN_PTR(getDeclaredMethods)}, + {CC "getInstanceMethods", CC "(" HS_KLASS2 ")[" RESOLVED_METHOD, FN_PTR(getInstanceMethods)}, {CC "getDeclaredFieldsInfo", CC "(" HS_KLASS2 ")[" FIELDINFO, FN_PTR(getDeclaredFieldsInfo)}, {CC "readStaticFieldValue", CC "(" HS_KLASS2 "JC)" JAVACONSTANT, FN_PTR(readStaticFieldValue)}, {CC "readFieldValue", CC "(" OBJECTCONSTANT HS_KLASS2 "JC)" JAVACONSTANT, FN_PTR(readFieldValue)}, diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/CompilerToVM.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/CompilerToVM.java index d73566592960d..e10d8cbf74328 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/CompilerToVM.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/CompilerToVM.java @@ -176,6 +176,17 @@ boolean isCompilable(HotSpotResolvedJavaMethodImpl method) { private native boolean isCompilable(HotSpotResolvedJavaMethodImpl method, long methodPointer); + /** + * Returns whether {@code method} is an overpass method. + * Overpass methods are instance methods which are created when otherwise a valid candidate + * for method resolution would not be found. + */ + boolean isOverpass(HotSpotResolvedJavaMethodImpl method) { + return isOverpass(method, method.getMethodPointer()); + } + + private native boolean isOverpass(HotSpotResolvedJavaMethodImpl method, long methodPointer); + /** * Determines if {@code method} is targeted by a VM directive (e.g., * {@code -XX:CompileCommand=dontinline,}) or annotation (e.g., @@ -1148,7 +1159,7 @@ ResolvedJavaMethod[] getDeclaredConstructors(HotSpotResolvedObjectTypeImpl klass native ResolvedJavaMethod[] getDeclaredConstructors(HotSpotResolvedObjectTypeImpl klass, long klassPointer); /** - * Gets the {@link ResolvedJavaMethod}s for all the non-constructor methods of {@code klass}. + * Gets the {@link ResolvedJavaMethod}s for all non-overpass instance methods of {@code klass}. */ ResolvedJavaMethod[] getDeclaredMethods(HotSpotResolvedObjectTypeImpl klass) { return getDeclaredMethods(klass, klass.getKlassPointer()); @@ -1156,6 +1167,15 @@ ResolvedJavaMethod[] getDeclaredMethods(HotSpotResolvedObjectTypeImpl klass) { native ResolvedJavaMethod[] getDeclaredMethods(HotSpotResolvedObjectTypeImpl klass, long klassPointer); + /** + * Gets the {@link ResolvedJavaMethod}s for all instance methods of {@code klass}. + */ + ResolvedJavaMethod[] getInstanceMethods(HotSpotResolvedObjectTypeImpl klass) { + return getInstanceMethods(klass, klass.getKlassPointer()); + } + + native ResolvedJavaMethod[] getInstanceMethods(HotSpotResolvedObjectTypeImpl klass, long klassPointer); + HotSpotResolvedObjectTypeImpl.FieldInfo[] getDeclaredFieldsInfo(HotSpotResolvedObjectTypeImpl klass) { return getDeclaredFieldsInfo(klass, klass.getKlassPointer()); } diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedJavaMethodImpl.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedJavaMethodImpl.java index 59f5320cc5479..8f696df6a437e 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedJavaMethodImpl.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedJavaMethodImpl.java @@ -573,6 +573,19 @@ public boolean isDefault() { return ((getModifiers() & mask) == Modifier.PUBLIC) && getDeclaringClass().isInterface(); } + /* + * Currently in hotspot an instance method can either be a "normal" or an "overpass" method. + * Overpass methods are instance methods which are created when otherwise a valid candidate + * for method resolution would not be found. + */ + @Override + public boolean isDeclared() { + if (isConstructor() || isStatic()) { + return false; + } + return !compilerToVM().isOverpass(this); + } + @Override public Type[] getGenericParameterTypes() { if (isClassInitializer()) { diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedObjectTypeImpl.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedObjectTypeImpl.java index 8d3b9f48b4cd1..f70ca6879f081 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedObjectTypeImpl.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedObjectTypeImpl.java @@ -1067,6 +1067,18 @@ public ResolvedJavaMethod[] getDeclaredMethods(boolean forceLink) { return runtime().compilerToVm.getDeclaredMethods(this); } + @Override + public List getNonStaticMethods(boolean forceLink) { + if (forceLink) { + link(); + } + ResolvedJavaMethod[] instanceMethods = runtime().compilerToVm.getInstanceMethods(this); + if (instanceMethods.length == 0) { + return List.of(); + } + return Collections.unmodifiableList(Arrays.asList(instanceMethods)); + } + @Override public ResolvedJavaMethod getClassInitializer() { if (!isArray()) { diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedPrimitiveType.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedPrimitiveType.java index 4425ade0880a1..3649abf43b802 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedPrimitiveType.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedPrimitiveType.java @@ -296,6 +296,11 @@ public ResolvedJavaMethod[] getDeclaredMethods() { return new ResolvedJavaMethod[0]; } + @Override + public List getNonStaticMethods(boolean forceLink) { + return List.of(); + } + @Override public ResolvedJavaMethod getClassInitializer() { return null; diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/meta/ResolvedJavaMethod.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/meta/ResolvedJavaMethod.java index 8758dbb3bb620..fc59401b9eb80 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/meta/ResolvedJavaMethod.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/meta/ResolvedJavaMethod.java @@ -114,6 +114,12 @@ default boolean isFinal() { */ boolean isDefault(); + /** + * Returns {@code true} if this method would be contained in the array returned by + * {@code getDeclaringClass().getDeclaredMethods()} + */ + boolean isDeclared(); + /** * Checks whether this method is a class initializer. * diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/meta/ResolvedJavaType.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/meta/ResolvedJavaType.java index b5d29733a6969..42d0d3f492b25 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/meta/ResolvedJavaType.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/meta/ResolvedJavaType.java @@ -23,6 +23,7 @@ package jdk.vm.ci.meta; import java.lang.reflect.AnnotatedElement; +import java.util.List; import jdk.vm.ci.meta.Assumptions.AssumptionResult; @@ -365,6 +366,13 @@ default ResolvedJavaMethod[] getDeclaredMethods(boolean forceLink) { throw new UnsupportedOperationException(); } + /** + * Returns a list containing all the non-static methods present within this type. + * + * @param forceLink if {@code true}, forces this type to be {@link #link linked} + */ + List getNonStaticMethods(boolean forceLink); + /** * Returns the {@code } method for this class if there is one. */ diff --git a/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/TestResolvedJavaMethod.java b/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/TestResolvedJavaMethod.java index 75f074ad09df8..69ea87874deb3 100644 --- a/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/TestResolvedJavaMethod.java +++ b/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/TestResolvedJavaMethod.java @@ -425,6 +425,20 @@ public void isDefaultTest() { } } + @Test + public void isDeclaredTest() { + for (Map.Entry e : methods.entrySet()) { + ResolvedJavaMethod m = e.getValue(); + Method k = e.getKey(); + boolean expectedDeclared = !Modifier.isStatic(k.getModifiers()); + assertEquals(expectedDeclared, m.isDeclared()); + } + for (Map.Entry, ResolvedJavaMethod> e : constructors.entrySet()) { + ResolvedJavaMethod m = e.getValue(); + assertFalse(m.isDeclared()); + } + } + @Test public void hasReceiverTest() { for (Map.Entry e : methods.entrySet()) { diff --git a/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/TestResolvedJavaType.java b/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/TestResolvedJavaType.java index 456c4a5fd88a4..c45d80ff3417d 100644 --- a/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/TestResolvedJavaType.java +++ b/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/TestResolvedJavaType.java @@ -1019,6 +1019,23 @@ public void getDeclaredMethodsTest() { } } + @Test + public void getNonStaticMethodsTest() { + for (Class c : classes) { + ResolvedJavaType type = metaAccess.lookupJavaType(c); + Method[] raw = c.getDeclaredMethods(); + Set expected = new HashSet<>(); + for (Method m : raw) { + ResolvedJavaMethod resolvedMethod = metaAccess.lookupJavaMethod(m); + assertNotNull(resolvedMethod); + expected.add(resolvedMethod); + } + Set actual = new HashSet<>(type.getNonStaticMethods(false)); + assertTrue(actual.size() >= expected.size()); + assertTrue(actual.containsAll(expected)); + } + } + static class A { static String name = "foo"; } From 412b1feee36feb4560a6346eab6a31f9377d5a4d Mon Sep 17 00:00:00 2001 From: Tom Shull Date: Thu, 29 May 2025 00:45:12 +0200 Subject: [PATCH 2/5] address reviewer feedback --- src/hotspot/share/jvmci/jvmciCompilerToVM.cpp | 10 ++------- src/hotspot/share/jvmci/vmStructs_jvmci.cpp | 1 + .../jdk/vm/ci/hotspot/CompilerToVM.java | 21 +++++-------------- .../HotSpotResolvedJavaMethodImpl.java | 4 ++-- .../HotSpotResolvedObjectTypeImpl.java | 4 ++-- .../hotspot/HotSpotResolvedPrimitiveType.java | 2 +- .../jdk/vm/ci/hotspot/HotSpotVMConfig.java | 1 + .../jdk/vm/ci/meta/ResolvedJavaMethod.java | 2 +- .../jdk/vm/ci/meta/ResolvedJavaType.java | 6 ++++-- .../runtime/test/TestResolvedJavaMethod.java | 3 +-- .../ci/runtime/test/TestResolvedJavaType.java | 4 ++-- 11 files changed, 22 insertions(+), 36 deletions(-) diff --git a/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp b/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp index 435b77cd77153..ae3e370299dea 100644 --- a/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp +++ b/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp @@ -577,11 +577,6 @@ C2V_VMENTRY_0(jboolean, isCompilable,(JNIEnv* env, jobject, ARGUMENT_PAIR(method return !method->is_not_compilable(CompLevel_full_optimization); C2V_END -C2V_VMENTRY_0(jboolean, isOverpass,(JNIEnv* env, jobject, ARGUMENT_PAIR(method))) - Method* method = UNPACK_PAIR(Method, method); - return method->is_overpass(); -C2V_END - C2V_VMENTRY_0(jboolean, hasNeverInlineDirective,(JNIEnv* env, jobject, ARGUMENT_PAIR(method))) methodHandle method (THREAD, UNPACK_PAIR(Method, method)); return !Inline || CompilerOracle::should_not_inline(method) || method->dont_inline(); @@ -2224,7 +2219,7 @@ C2V_VMENTRY_NULL(jobjectArray, getDeclaredMethods, (JNIEnv* env, jobject, ARGUME return JVMCIENV->get_jobjectArray(methods); C2V_END -C2V_VMENTRY_NULL(jobjectArray, getInstanceMethods, (JNIEnv* env, jobject, ARGUMENT_PAIR(klass))) +C2V_VMENTRY_NULL(jobjectArray, getNonInitializerMethods, (JNIEnv* env, jobject, ARGUMENT_PAIR(klass))) Klass* klass = UNPACK_PAIR(Klass, klass); if (klass == nullptr) { JVMCI_THROW_NULL(NullPointerException); @@ -3312,7 +3307,6 @@ JNINativeMethod CompilerToVM::methods[] = { {CC "methodIsIgnoredBySecurityStackWalk", CC "(" HS_METHOD2 ")Z", FN_PTR(methodIsIgnoredBySecurityStackWalk)}, {CC "setNotInlinableOrCompilable", CC "(" HS_METHOD2 ")V", FN_PTR(setNotInlinableOrCompilable)}, {CC "isCompilable", CC "(" HS_METHOD2 ")Z", FN_PTR(isCompilable)}, - {CC "isOverpass", CC "(" HS_METHOD2 ")Z", FN_PTR(isOverpass)}, {CC "hasNeverInlineDirective", CC "(" HS_METHOD2 ")Z", FN_PTR(hasNeverInlineDirective)}, {CC "shouldInlineMethod", CC "(" HS_METHOD2 ")Z", FN_PTR(shouldInlineMethod)}, {CC "lookupType", CC "(" STRING HS_KLASS2 "IZ)" HS_RESOLVED_TYPE, FN_PTR(lookupType)}, @@ -3387,7 +3381,7 @@ JNINativeMethod CompilerToVM::methods[] = { {CC "boxPrimitive", CC "(" OBJECT ")" OBJECTCONSTANT, FN_PTR(boxPrimitive)}, {CC "getDeclaredConstructors", CC "(" HS_KLASS2 ")[" RESOLVED_METHOD, FN_PTR(getDeclaredConstructors)}, {CC "getDeclaredMethods", CC "(" HS_KLASS2 ")[" RESOLVED_METHOD, FN_PTR(getDeclaredMethods)}, - {CC "getInstanceMethods", CC "(" HS_KLASS2 ")[" RESOLVED_METHOD, FN_PTR(getInstanceMethods)}, + {CC "getNonInitializerMethods", CC "(" HS_KLASS2 ")[" RESOLVED_METHOD, FN_PTR(getNonInitializerMethods)}, {CC "getDeclaredFieldsInfo", CC "(" HS_KLASS2 ")[" FIELDINFO, FN_PTR(getDeclaredFieldsInfo)}, {CC "readStaticFieldValue", CC "(" HS_KLASS2 "JC)" JAVACONSTANT, FN_PTR(readStaticFieldValue)}, {CC "readFieldValue", CC "(" OBJECTCONSTANT HS_KLASS2 "JC)" JAVACONSTANT, FN_PTR(readFieldValue)}, diff --git a/src/hotspot/share/jvmci/vmStructs_jvmci.cpp b/src/hotspot/share/jvmci/vmStructs_jvmci.cpp index fc5b80f1d2ec0..835a69c9dae57 100644 --- a/src/hotspot/share/jvmci/vmStructs_jvmci.cpp +++ b/src/hotspot/share/jvmci/vmStructs_jvmci.cpp @@ -691,6 +691,7 @@ declare_constant(ConstMethodFlags::_misc_reserved_stack_access) \ declare_constant(ConstMethodFlags::_misc_changes_current_thread) \ declare_constant(ConstMethodFlags::_misc_is_scoped) \ + declare_constant(ConstMethodFlags::_misc_is_overpass) \ \ declare_constant(CounterData::count_off) \ \ diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/CompilerToVM.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/CompilerToVM.java index e10d8cbf74328..ecd002f0789b6 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/CompilerToVM.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/CompilerToVM.java @@ -176,17 +176,6 @@ boolean isCompilable(HotSpotResolvedJavaMethodImpl method) { private native boolean isCompilable(HotSpotResolvedJavaMethodImpl method, long methodPointer); - /** - * Returns whether {@code method} is an overpass method. - * Overpass methods are instance methods which are created when otherwise a valid candidate - * for method resolution would not be found. - */ - boolean isOverpass(HotSpotResolvedJavaMethodImpl method) { - return isOverpass(method, method.getMethodPointer()); - } - - private native boolean isOverpass(HotSpotResolvedJavaMethodImpl method, long methodPointer); - /** * Determines if {@code method} is targeted by a VM directive (e.g., * {@code -XX:CompileCommand=dontinline,}) or annotation (e.g., @@ -1159,7 +1148,7 @@ ResolvedJavaMethod[] getDeclaredConstructors(HotSpotResolvedObjectTypeImpl klass native ResolvedJavaMethod[] getDeclaredConstructors(HotSpotResolvedObjectTypeImpl klass, long klassPointer); /** - * Gets the {@link ResolvedJavaMethod}s for all non-overpass instance methods of {@code klass}. + * Gets the {@link ResolvedJavaMethod}s for all non-overpass and non-initializer methods of {@code klass}. */ ResolvedJavaMethod[] getDeclaredMethods(HotSpotResolvedObjectTypeImpl klass) { return getDeclaredMethods(klass, klass.getKlassPointer()); @@ -1168,13 +1157,13 @@ ResolvedJavaMethod[] getDeclaredMethods(HotSpotResolvedObjectTypeImpl klass) { native ResolvedJavaMethod[] getDeclaredMethods(HotSpotResolvedObjectTypeImpl klass, long klassPointer); /** - * Gets the {@link ResolvedJavaMethod}s for all instance methods of {@code klass}. + * Gets the {@link ResolvedJavaMethod}s for all non-initializer methods of {@code klass}. */ - ResolvedJavaMethod[] getInstanceMethods(HotSpotResolvedObjectTypeImpl klass) { - return getInstanceMethods(klass, klass.getKlassPointer()); + ResolvedJavaMethod[] getNonInitializerMethods(HotSpotResolvedObjectTypeImpl klass) { + return getNonInitializerMethods(klass, klass.getKlassPointer()); } - native ResolvedJavaMethod[] getInstanceMethods(HotSpotResolvedObjectTypeImpl klass, long klassPointer); + native ResolvedJavaMethod[] getNonInitializerMethods(HotSpotResolvedObjectTypeImpl klass, long klassPointer); HotSpotResolvedObjectTypeImpl.FieldInfo[] getDeclaredFieldsInfo(HotSpotResolvedObjectTypeImpl klass) { return getDeclaredFieldsInfo(klass, klass.getKlassPointer()); diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedJavaMethodImpl.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedJavaMethodImpl.java index 8f696df6a437e..cbf37dc1a811d 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedJavaMethodImpl.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedJavaMethodImpl.java @@ -580,10 +580,10 @@ public boolean isDefault() { */ @Override public boolean isDeclared() { - if (isConstructor() || isStatic()) { + if (isConstructor() || isClassInitializer()) { return false; } - return !compilerToVM().isOverpass(this); + return (getConstMethodFlags() & config().constMethodFlagsIsOverpass) == 0; } @Override diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedObjectTypeImpl.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedObjectTypeImpl.java index f70ca6879f081..b16780becb888 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedObjectTypeImpl.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedObjectTypeImpl.java @@ -1068,11 +1068,11 @@ public ResolvedJavaMethod[] getDeclaredMethods(boolean forceLink) { } @Override - public List getNonStaticMethods(boolean forceLink) { + public List getNonInitializerMethods(boolean forceLink) { if (forceLink) { link(); } - ResolvedJavaMethod[] instanceMethods = runtime().compilerToVm.getInstanceMethods(this); + ResolvedJavaMethod[] instanceMethods = runtime().compilerToVm.getNonInitializerMethods(this); if (instanceMethods.length == 0) { return List.of(); } diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedPrimitiveType.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedPrimitiveType.java index 3649abf43b802..16f19c92f96cd 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedPrimitiveType.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedPrimitiveType.java @@ -297,7 +297,7 @@ public ResolvedJavaMethod[] getDeclaredMethods() { } @Override - public List getNonStaticMethods(boolean forceLink) { + public List getNonInitializerMethods(boolean forceLink) { return List.of(); } diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotVMConfig.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotVMConfig.java index e93b98042b62a..bc2e121fe903d 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotVMConfig.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotVMConfig.java @@ -196,6 +196,7 @@ long prototypeMarkWord() { final int constMethodFlagsCallerSensitive = getConstant("ConstMethodFlags::_misc_caller_sensitive", Integer.class); final int constMethodFlagsIntrinsicCandidate = getConstant("ConstMethodFlags::_misc_intrinsic_candidate", Integer.class); final int constMethodFlagsIsScoped = getConstant("ConstMethodFlags::_misc_is_scoped", Integer.class); + final int constMethodFlagsIsOverpass = getConstant("ConstMethodFlags::_misc_is_overpass", Integer.class); final int constMethodHasLineNumberTable = getConstant("ConstMethodFlags::_misc_has_linenumber_table", Integer.class); final int constMethodHasLocalVariableTable = getConstant("ConstMethodFlags::_misc_has_localvariable_table", Integer.class); final int constMethodHasMethodAnnotations = getConstant("ConstMethodFlags::_misc_has_method_annotations", Integer.class); diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/meta/ResolvedJavaMethod.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/meta/ResolvedJavaMethod.java index fc59401b9eb80..f401bc30f83ee 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/meta/ResolvedJavaMethod.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/meta/ResolvedJavaMethod.java @@ -115,7 +115,7 @@ default boolean isFinal() { boolean isDefault(); /** - * Returns {@code true} if this method would be contained in the array returned by + * Returns {@code true} if this method is contained in the array returned by * {@code getDeclaringClass().getDeclaredMethods()} */ boolean isDeclared(); diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/meta/ResolvedJavaType.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/meta/ResolvedJavaType.java index 42d0d3f492b25..3ee7520f87143 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/meta/ResolvedJavaType.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/meta/ResolvedJavaType.java @@ -367,11 +367,13 @@ default ResolvedJavaMethod[] getDeclaredMethods(boolean forceLink) { } /** - * Returns a list containing all the non-static methods present within this type. + * Returns a list containing all the non-initializer methods (constructors & {@code }) + * present within this type. The returned List is unmodifiable; calls to any mutator method + * will always cause {@code UnsupportedOperationException} to be thrown. * * @param forceLink if {@code true}, forces this type to be {@link #link linked} */ - List getNonStaticMethods(boolean forceLink); + List getNonInitializerMethods(boolean forceLink); /** * Returns the {@code } method for this class if there is one. diff --git a/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/TestResolvedJavaMethod.java b/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/TestResolvedJavaMethod.java index 69ea87874deb3..6151ae68ce7ab 100644 --- a/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/TestResolvedJavaMethod.java +++ b/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/TestResolvedJavaMethod.java @@ -429,8 +429,7 @@ public void isDefaultTest() { public void isDeclaredTest() { for (Map.Entry e : methods.entrySet()) { ResolvedJavaMethod m = e.getValue(); - Method k = e.getKey(); - boolean expectedDeclared = !Modifier.isStatic(k.getModifiers()); + boolean expectedDeclared = Arrays.stream(m.getDeclaringClass().getDeclaredMethods()).anyMatch(i -> i.equals(m)); assertEquals(expectedDeclared, m.isDeclared()); } for (Map.Entry, ResolvedJavaMethod> e : constructors.entrySet()) { diff --git a/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/TestResolvedJavaType.java b/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/TestResolvedJavaType.java index c45d80ff3417d..835e62ddb0880 100644 --- a/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/TestResolvedJavaType.java +++ b/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/TestResolvedJavaType.java @@ -1020,7 +1020,7 @@ public void getDeclaredMethodsTest() { } @Test - public void getNonStaticMethodsTest() { + public void getNonInitializerMethodsTest() { for (Class c : classes) { ResolvedJavaType type = metaAccess.lookupJavaType(c); Method[] raw = c.getDeclaredMethods(); @@ -1030,7 +1030,7 @@ public void getNonStaticMethodsTest() { assertNotNull(resolvedMethod); expected.add(resolvedMethod); } - Set actual = new HashSet<>(type.getNonStaticMethods(false)); + Set actual = new HashSet<>(type.getNonInitializerMethods(false)); assertTrue(actual.size() >= expected.size()); assertTrue(actual.containsAll(expected)); } From 1f42f05fed4c49becdb478b4a7c8f7e898fed7ce Mon Sep 17 00:00:00 2001 From: Tom Shull Date: Thu, 29 May 2025 21:14:00 +0200 Subject: [PATCH 3/5] implement getAllMethods --- src/hotspot/share/jvmci/jvmciCompilerToVM.cpp | 15 ++++----------- .../classes/jdk/vm/ci/hotspot/CompilerToVM.java | 8 ++++---- .../hotspot/HotSpotResolvedJavaMethodImpl.java | 2 +- .../hotspot/HotSpotResolvedObjectTypeImpl.java | 4 ++-- .../hotspot/HotSpotResolvedPrimitiveType.java | 2 +- .../jdk/vm/ci/meta/ResolvedJavaType.java | 7 ++++--- .../ci/runtime/test/TestResolvedJavaType.java | 17 +++++++---------- 7 files changed, 23 insertions(+), 32 deletions(-) diff --git a/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp b/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp index ae3e370299dea..efb57f948da46 100644 --- a/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp +++ b/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp @@ -2219,7 +2219,7 @@ C2V_VMENTRY_NULL(jobjectArray, getDeclaredMethods, (JNIEnv* env, jobject, ARGUME return JVMCIENV->get_jobjectArray(methods); C2V_END -C2V_VMENTRY_NULL(jobjectArray, getNonInitializerMethods, (JNIEnv* env, jobject, ARGUMENT_PAIR(klass))) +C2V_VMENTRY_NULL(jobjectArray, getAllMethods, (JNIEnv* env, jobject, ARGUMENT_PAIR(klass))) Klass* klass = UNPACK_PAIR(Klass, klass); if (klass == nullptr) { JVMCI_THROW_NULL(NullPointerException); @@ -2230,16 +2230,9 @@ C2V_VMENTRY_NULL(jobjectArray, getNonInitializerMethods, (JNIEnv* env, jobject, } InstanceKlass* iklass = InstanceKlass::cast(klass); - GrowableArray methods_array; + JVMCIObjectArray methods = JVMCIENV->new_ResolvedJavaMethod_array(iklass->methods()->length(), JVMCI_CHECK_NULL); for (int i = 0; i < iklass->methods()->length(); i++) { - Method* m = iklass->methods()->at(i); - if (!m->is_object_initializer() && !m->is_static_initializer()) { - methods_array.append(m); - } - } - JVMCIObjectArray methods = JVMCIENV->new_ResolvedJavaMethod_array(methods_array.length(), JVMCI_CHECK_NULL); - for (int i = 0; i < methods_array.length(); i++) { - methodHandle mh(THREAD, methods_array.at(i)); + methodHandle mh(THREAD, iklass->methods()->at(i)); JVMCIObject method = JVMCIENV->get_jvmci_method(mh, JVMCI_CHECK_NULL); JVMCIENV->put_object_at(methods, i, method); } @@ -3381,7 +3374,7 @@ JNINativeMethod CompilerToVM::methods[] = { {CC "boxPrimitive", CC "(" OBJECT ")" OBJECTCONSTANT, FN_PTR(boxPrimitive)}, {CC "getDeclaredConstructors", CC "(" HS_KLASS2 ")[" RESOLVED_METHOD, FN_PTR(getDeclaredConstructors)}, {CC "getDeclaredMethods", CC "(" HS_KLASS2 ")[" RESOLVED_METHOD, FN_PTR(getDeclaredMethods)}, - {CC "getNonInitializerMethods", CC "(" HS_KLASS2 ")[" RESOLVED_METHOD, FN_PTR(getNonInitializerMethods)}, + {CC "getAllMethods", CC "(" HS_KLASS2 ")[" RESOLVED_METHOD, FN_PTR(getAllMethods)}, {CC "getDeclaredFieldsInfo", CC "(" HS_KLASS2 ")[" FIELDINFO, FN_PTR(getDeclaredFieldsInfo)}, {CC "readStaticFieldValue", CC "(" HS_KLASS2 "JC)" JAVACONSTANT, FN_PTR(readStaticFieldValue)}, {CC "readFieldValue", CC "(" OBJECTCONSTANT HS_KLASS2 "JC)" JAVACONSTANT, FN_PTR(readFieldValue)}, diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/CompilerToVM.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/CompilerToVM.java index ecd002f0789b6..a6c2c07c11de5 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/CompilerToVM.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/CompilerToVM.java @@ -1157,13 +1157,13 @@ ResolvedJavaMethod[] getDeclaredMethods(HotSpotResolvedObjectTypeImpl klass) { native ResolvedJavaMethod[] getDeclaredMethods(HotSpotResolvedObjectTypeImpl klass, long klassPointer); /** - * Gets the {@link ResolvedJavaMethod}s for all non-initializer methods of {@code klass}. + * Gets the {@link ResolvedJavaMethod}s for all methods of {@code klass}. */ - ResolvedJavaMethod[] getNonInitializerMethods(HotSpotResolvedObjectTypeImpl klass) { - return getNonInitializerMethods(klass, klass.getKlassPointer()); + ResolvedJavaMethod[] getAllMethods(HotSpotResolvedObjectTypeImpl klass) { + return getAllMethods(klass, klass.getKlassPointer()); } - native ResolvedJavaMethod[] getNonInitializerMethods(HotSpotResolvedObjectTypeImpl klass, long klassPointer); + native ResolvedJavaMethod[] getAllMethods(HotSpotResolvedObjectTypeImpl klass, long klassPointer); HotSpotResolvedObjectTypeImpl.FieldInfo[] getDeclaredFieldsInfo(HotSpotResolvedObjectTypeImpl klass) { return getDeclaredFieldsInfo(klass, klass.getKlassPointer()); diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedJavaMethodImpl.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedJavaMethodImpl.java index cbf37dc1a811d..a1bf47fae4805 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedJavaMethodImpl.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedJavaMethodImpl.java @@ -574,7 +574,7 @@ public boolean isDefault() { } /* - * Currently in hotspot an instance method can either be a "normal" or an "overpass" method. + * Currently in hotspot a method can either be a "normal" or an "overpass" method. * Overpass methods are instance methods which are created when otherwise a valid candidate * for method resolution would not be found. */ diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedObjectTypeImpl.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedObjectTypeImpl.java index b16780becb888..e9ab01d8f8dd3 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedObjectTypeImpl.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedObjectTypeImpl.java @@ -1068,11 +1068,11 @@ public ResolvedJavaMethod[] getDeclaredMethods(boolean forceLink) { } @Override - public List getNonInitializerMethods(boolean forceLink) { + public List getAllMethods(boolean forceLink) { if (forceLink) { link(); } - ResolvedJavaMethod[] instanceMethods = runtime().compilerToVm.getNonInitializerMethods(this); + ResolvedJavaMethod[] instanceMethods = runtime().compilerToVm.getAllMethods(this); if (instanceMethods.length == 0) { return List.of(); } diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedPrimitiveType.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedPrimitiveType.java index 16f19c92f96cd..b707906af0826 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedPrimitiveType.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedPrimitiveType.java @@ -297,7 +297,7 @@ public ResolvedJavaMethod[] getDeclaredMethods() { } @Override - public List getNonInitializerMethods(boolean forceLink) { + public List getAllMethods(boolean forceLink) { return List.of(); } diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/meta/ResolvedJavaType.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/meta/ResolvedJavaType.java index 3ee7520f87143..b00129759cb00 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/meta/ResolvedJavaType.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/meta/ResolvedJavaType.java @@ -367,13 +367,14 @@ default ResolvedJavaMethod[] getDeclaredMethods(boolean forceLink) { } /** - * Returns a list containing all the non-initializer methods (constructors & {@code }) - * present within this type. The returned List is unmodifiable; calls to any mutator method + * Returns a list containing all methods present within this type. This list can include + * methods implicitly created and used by the VM that are not present in {@link #getDeclaredMethods}. + * The returned List is unmodifiable; calls to any mutator method * will always cause {@code UnsupportedOperationException} to be thrown. * * @param forceLink if {@code true}, forces this type to be {@link #link linked} */ - List getNonInitializerMethods(boolean forceLink); + List getAllMethods(boolean forceLink); /** * Returns the {@code } method for this class if there is one. diff --git a/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/TestResolvedJavaType.java b/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/TestResolvedJavaType.java index 835e62ddb0880..35b09d58f1bdf 100644 --- a/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/TestResolvedJavaType.java +++ b/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/TestResolvedJavaType.java @@ -1020,19 +1020,16 @@ public void getDeclaredMethodsTest() { } @Test - public void getNonInitializerMethodsTest() { + public void getAllMethodsTest() { for (Class c : classes) { ResolvedJavaType type = metaAccess.lookupJavaType(c); - Method[] raw = c.getDeclaredMethods(); - Set expected = new HashSet<>(); - for (Method m : raw) { - ResolvedJavaMethod resolvedMethod = metaAccess.lookupJavaMethod(m); - assertNotNull(resolvedMethod); - expected.add(resolvedMethod); + Set allMethods = new HashSet<>(type.getAllMethods(true)); + boolean included = Arrays.stream(type.getDeclaredMethods()).allMatch(m -> allMethods.contains(m)); + included = included && Arrays.stream(type.getDeclaredConstructors()).allMatch(m -> allMethods.contains(m)); + if (included && type.getClassInitializer() != null) { + included = allMethods.contains(type.getClassInitializer()); } - Set actual = new HashSet<>(type.getNonInitializerMethods(false)); - assertTrue(actual.size() >= expected.size()); - assertTrue(actual.containsAll(expected)); + assertTrue(included); } } From 0de1feaefeca1b845e4359cb3716c60c2a95e298 Mon Sep 17 00:00:00 2001 From: Tom Shull Date: Mon, 2 Jun 2025 10:04:25 +0200 Subject: [PATCH 4/5] format javadoc and update test --- .../share/classes/jdk/vm/ci/hotspot/CompilerToVM.java | 3 ++- .../vm/ci/hotspot/HotSpotResolvedJavaMethodImpl.java | 6 +++--- .../share/classes/jdk/vm/ci/meta/ResolvedJavaType.java | 9 +++++---- .../jdk/vm/ci/runtime/test/TestResolvedJavaType.java | 10 ++++------ 4 files changed, 14 insertions(+), 14 deletions(-) diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/CompilerToVM.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/CompilerToVM.java index a6c2c07c11de5..045b1f0fc1263 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/CompilerToVM.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/CompilerToVM.java @@ -1148,7 +1148,8 @@ ResolvedJavaMethod[] getDeclaredConstructors(HotSpotResolvedObjectTypeImpl klass native ResolvedJavaMethod[] getDeclaredConstructors(HotSpotResolvedObjectTypeImpl klass, long klassPointer); /** - * Gets the {@link ResolvedJavaMethod}s for all non-overpass and non-initializer methods of {@code klass}. + * Gets the {@link ResolvedJavaMethod}s for all non-overpass and non-initializer + * methods of {@code klass}. */ ResolvedJavaMethod[] getDeclaredMethods(HotSpotResolvedObjectTypeImpl klass) { return getDeclaredMethods(klass, klass.getKlassPointer()); diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedJavaMethodImpl.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedJavaMethodImpl.java index a1bf47fae4805..9440a719dd4b0 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedJavaMethodImpl.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedJavaMethodImpl.java @@ -574,9 +574,9 @@ public boolean isDefault() { } /* - * Currently in hotspot a method can either be a "normal" or an "overpass" method. - * Overpass methods are instance methods which are created when otherwise a valid candidate - * for method resolution would not be found. + * Currently in hotspot a method can either be a "normal" or an "overpass" + * method. Overpass methods are instance methods which are created when + * otherwise a valid candidate for method resolution would not be found. */ @Override public boolean isDeclared() { diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/meta/ResolvedJavaType.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/meta/ResolvedJavaType.java index b00129759cb00..929a4713330ad 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/meta/ResolvedJavaType.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/meta/ResolvedJavaType.java @@ -367,10 +367,11 @@ default ResolvedJavaMethod[] getDeclaredMethods(boolean forceLink) { } /** - * Returns a list containing all methods present within this type. This list can include - * methods implicitly created and used by the VM that are not present in {@link #getDeclaredMethods}. - * The returned List is unmodifiable; calls to any mutator method - * will always cause {@code UnsupportedOperationException} to be thrown. + * Returns a list containing all methods present within this type. This list can + * include methods implicitly created and used by the VM that are not present in + * {@link #getDeclaredMethods}. The returned List is unmodifiable; calls to any + * mutator method will always cause {@code UnsupportedOperationException} to be + * thrown. * * @param forceLink if {@code true}, forces this type to be {@link #link linked} */ diff --git a/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/TestResolvedJavaType.java b/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/TestResolvedJavaType.java index 35b09d58f1bdf..ee48724b71d1b 100644 --- a/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/TestResolvedJavaType.java +++ b/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/TestResolvedJavaType.java @@ -1024,12 +1024,10 @@ public void getAllMethodsTest() { for (Class c : classes) { ResolvedJavaType type = metaAccess.lookupJavaType(c); Set allMethods = new HashSet<>(type.getAllMethods(true)); - boolean included = Arrays.stream(type.getDeclaredMethods()).allMatch(m -> allMethods.contains(m)); - included = included && Arrays.stream(type.getDeclaredConstructors()).allMatch(m -> allMethods.contains(m)); - if (included && type.getClassInitializer() != null) { - included = allMethods.contains(type.getClassInitializer()); - } - assertTrue(included); + Stream allKnownMethods = Stream.concat(Arrays.stream(type.getDeclaredMethods()), Arrays.stream(type.getDeclaredConstructors())); + allKnownMethods = Stream.concat(allKnownMethods, Stream.ofNullable(type.getClassInitializer())); + List missingMethods = allKnownMethods.filter(m -> !allMethods.contains(m)).toList(); + assertTrue(missingMethods.toString(), missingMethods.isEmpty()); } } From ae81d46f8cba3cf12e8abe2d254d70a9707f7702 Mon Sep 17 00:00:00 2001 From: Tom Shull Date: Mon, 2 Jun 2025 22:31:53 +0200 Subject: [PATCH 5/5] return List.of() from getAllMethods --- .../jdk/vm/ci/hotspot/HotSpotResolvedObjectTypeImpl.java | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedObjectTypeImpl.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedObjectTypeImpl.java index e9ab01d8f8dd3..17eede6f49074 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedObjectTypeImpl.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedObjectTypeImpl.java @@ -1072,11 +1072,7 @@ public List getAllMethods(boolean forceLink) { if (forceLink) { link(); } - ResolvedJavaMethod[] instanceMethods = runtime().compilerToVm.getAllMethods(this); - if (instanceMethods.length == 0) { - return List.of(); - } - return Collections.unmodifiableList(Arrays.asList(instanceMethods)); + return List.of(runtime().compilerToVm.getAllMethods(this)); } @Override