Skip to content

Commit 97eeb8f

Browse files
committed
[JVMCI] Add ResolvedJavaType#getEnclosingMethod [GR-70132]
1 parent 93a16f0 commit 97eeb8f

File tree

8 files changed

+122
-1
lines changed

8 files changed

+122
-1
lines changed

src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotJDKReflection.java

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727

2828
import java.lang.annotation.Annotation;
2929
import java.lang.reflect.Array;
30+
import java.lang.reflect.Constructor;
3031
import java.lang.reflect.Executable;
3132
import java.lang.reflect.Field;
3233
import java.lang.reflect.Method;
@@ -103,6 +104,26 @@ HotSpotResolvedObjectType getEnclosingClass(HotSpotResolvedObjectTypeImpl holder
103104
return (HotSpotResolvedObjectType) runtime().fromClass(javaMirror.getEnclosingClass());
104105
}
105106

107+
@Override
108+
HotSpotResolvedJavaMethod getEnclosingMethod(HotSpotResolvedObjectTypeImpl holder) {
109+
Class<?> javaMirror = getMirror(holder);
110+
Method enclosingMethod = javaMirror.getEnclosingMethod();
111+
if (enclosingMethod == null) {
112+
return null;
113+
}
114+
return compilerToVM().asResolvedJavaMethod(enclosingMethod);
115+
}
116+
117+
@Override
118+
HotSpotResolvedJavaMethod getEnclosingConstructor(HotSpotResolvedObjectTypeImpl holder) {
119+
Class<?> javaMirror = getMirror(holder);
120+
Constructor<?> enclosingMethod = javaMirror.getEnclosingConstructor();
121+
if (enclosingMethod == null) {
122+
return null;
123+
}
124+
return compilerToVM().asResolvedJavaMethod(enclosingMethod);
125+
}
126+
106127
@Override
107128
boolean equals(HotSpotObjectConstantImpl a, HotSpotObjectConstantImpl b) {
108129
return resolveObject(a) == resolveObject(b) && a.isCompressed() == b.isCompressed();

src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotJVMCIReflection.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,10 @@ abstract class HotSpotJVMCIReflection {
5050

5151
abstract HotSpotResolvedObjectType getEnclosingClass(HotSpotResolvedObjectTypeImpl holder);
5252

53+
abstract HotSpotResolvedJavaMethod getEnclosingMethod(HotSpotResolvedObjectTypeImpl holder);
54+
55+
abstract HotSpotResolvedJavaMethod getEnclosingConstructor(HotSpotResolvedObjectTypeImpl holder);
56+
5357
abstract boolean equals(HotSpotObjectConstantImpl hotSpotResolvedJavaType, HotSpotObjectConstantImpl that);
5458

5559
abstract ResolvedJavaMethod.Parameter[] getParameters(HotSpotResolvedJavaMethodImpl javaMethod);

src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedJavaType.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626

2727
import jdk.vm.ci.meta.AnnotationData;
2828
import jdk.vm.ci.meta.JavaConstant;
29+
import jdk.vm.ci.meta.ResolvedJavaMethod;
2930
import jdk.vm.ci.meta.ResolvedJavaType;
3031

3132
public abstract class HotSpotResolvedJavaType extends HotSpotJavaType implements ResolvedJavaType {
@@ -62,6 +63,9 @@ public HotSpotResolvedObjectType getArrayClass() {
6263
return arrayOfType;
6364
}
6465

66+
@Override
67+
public abstract HotSpotResolvedJavaMethod getEnclosingMethod();
68+
6569
/**
6670
* Checks whether this type is currently being initialized. If a type is being initialized it
6771
* implies that it was {@link #isLinked() linked} and that the static initializer is currently

src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedObjectTypeImpl.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1102,6 +1102,12 @@ public HotSpotResolvedObjectType getEnclosingType() {
11021102
return runtime().reflection.getEnclosingClass(this);
11031103
}
11041104

1105+
@Override
1106+
public HotSpotResolvedJavaMethod getEnclosingMethod() {
1107+
HotSpotResolvedJavaMethod enclosingMethod = runtime().reflection.getEnclosingMethod(this);
1108+
return enclosingMethod != null ? enclosingMethod : runtime().reflection.getEnclosingConstructor(this);
1109+
}
1110+
11051111
@Override
11061112
public ResolvedJavaMethod[] getDeclaredConstructors() {
11071113
link();

src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedPrimitiveType.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,6 @@
2727

2828
import java.lang.annotation.Annotation;
2929
import java.lang.reflect.Modifier;
30-
import java.util.Collections;
3130
import java.util.List;
3231

3332
import jdk.vm.ci.common.JVMCIError;
@@ -302,6 +301,11 @@ public ResolvedJavaType getEnclosingType() {
302301
return null;
303302
}
304303

304+
@Override
305+
public HotSpotResolvedJavaMethod getEnclosingMethod() {
306+
return null;
307+
}
308+
305309
@Override
306310
public ResolvedJavaMethod[] getDeclaredConstructors() {
307311
return new ResolvedJavaMethod[0];

src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/SharedLibraryJVMCIReflection.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,16 @@ HotSpotResolvedObjectType getEnclosingClass(HotSpotResolvedObjectTypeImpl holder
7171
throw new HotSpotJVMCIUnsupportedOperationError("requires a call Class.getEnclosingClass()");
7272
}
7373

74+
@Override
75+
HotSpotResolvedJavaMethod getEnclosingMethod(HotSpotResolvedObjectTypeImpl holder) {
76+
throw new HotSpotJVMCIUnsupportedOperationError("requires a call Class.getEnclosingMethod()");
77+
}
78+
79+
@Override
80+
HotSpotResolvedJavaMethod getEnclosingConstructor(HotSpotResolvedObjectTypeImpl holder) {
81+
throw new HotSpotJVMCIUnsupportedOperationError("requires a call Class.getEnclosingConstructor()");
82+
}
83+
7484
@Override
7585
boolean equals(HotSpotObjectConstantImpl x, HotSpotObjectConstantImpl y) {
7686
if (x == y) {

src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/meta/ResolvedJavaType.java

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -391,6 +391,26 @@ default ResolvedJavaMethod resolveConcreteMethod(ResolvedJavaMethod method, Reso
391391
*/
392392
ResolvedJavaType getEnclosingType();
393393

394+
/**
395+
* Returns a {@link ResolvedJavaMethod} representing the immediately enclosing
396+
* method or constructor of the underlying type, if this type represents a local
397+
* or anonymous class within a method. Returns {@code null} otherwise.
398+
*
399+
* In particular, this method returns {@code null} if the underlying
400+
* type is a local or anonymous class immediately enclosed by a class or
401+
* interface declaration, instance initializer or static initializer.
402+
*
403+
* Note that in contrast to {@link Class#getEnclosingMethod()}, this returns
404+
* both, methods and constructors.
405+
*
406+
* @return the immediately enclosing method or constructor of the underlying
407+
* class, if this type is a local or anonymous class, otherwise {@code null}.
408+
*
409+
* @see Class#getEnclosingMethod()
410+
* @see Class#getEnclosingConstructor()
411+
*/
412+
ResolvedJavaMethod getEnclosingMethod();
413+
394414
/**
395415
* Returns an array reflecting all the constructors declared by this type. This method is
396416
* similar to {@link Class#getDeclaredConstructors()} in terms of returned constructors. Calling

test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/TestResolvedJavaType.java

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@
7070
import java.lang.reflect.AnnotatedElement;
7171
import java.lang.reflect.Array;
7272
import java.lang.reflect.Constructor;
73+
import java.lang.reflect.Executable;
7374
import java.lang.reflect.Field;
7475
import java.lang.reflect.Method;
7576
import java.lang.reflect.Modifier;
@@ -751,6 +752,57 @@ private void assertGetPermittedSubclasses(Class<?> clazz) {
751752
}
752753
}
753754

755+
@Test
756+
public void getEnclosingMethodTest() {
757+
// no anonymous class -> expected null
758+
Object obj0 = new Object();
759+
testEnclosingMethod(obj0.getClass(), false);
760+
761+
// anonymous class -> not null
762+
Object obj1 = new Object() {};
763+
testEnclosingMethod(obj1.getClass(), true);
764+
765+
// local class -> not null
766+
class Foo {};
767+
testEnclosingMethod(Foo.class, true);
768+
769+
class Bar {
770+
final Object obj0;
771+
final Object obj1;
772+
final Object obj2;
773+
774+
Bar() {
775+
// no anonymous class -> expected null
776+
obj0 = new Object();
777+
778+
// anonymous class -> not null
779+
obj1 = new Object() {};
780+
781+
// local class -> not null
782+
class Foo {};
783+
obj2 = new Foo();
784+
}
785+
}
786+
Bar bar = new Bar();
787+
testEnclosingMethod(bar.obj0.getClass(), false);
788+
testEnclosingMethod(bar.obj1.getClass(), true);
789+
testEnclosingMethod(bar.obj2.getClass(), true);
790+
}
791+
792+
private static void testEnclosingMethod(Class<?> clazz, boolean isEnclosed) {
793+
ResolvedJavaType type = metaAccess.lookupJavaType(clazz);
794+
Method enclosingMethod = clazz.getEnclosingMethod();
795+
Executable expected = enclosingMethod != null ? enclosingMethod : clazz.getEnclosingConstructor();
796+
ResolvedJavaMethod actual = type.getEnclosingMethod();
797+
if (expected == null) {
798+
assertFalse(isEnclosed);
799+
assertNull(actual);
800+
} else {
801+
assertTrue(isEnclosed);
802+
assertEquals(metaAccess.lookupJavaMethod(expected), actual);
803+
}
804+
}
805+
754806
static class Declarations {
755807

756808
final Method implementation;

0 commit comments

Comments
 (0)