Skip to content

Commit 3e2cbd9

Browse files
committed
add ResolvedJavaType#getEnclosingMethod and ResolvedJavaType#getEnclosingConstructor
1 parent a7bc6bf commit 3e2cbd9

File tree

7 files changed

+153
-0
lines changed

7 files changed

+153
-0
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/HotSpotResolvedObjectTypeImpl.java

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

1105+
@Override
1106+
public ResolvedJavaMethod getEnclosingMethod() {
1107+
return runtime().reflection.getEnclosingMethod(this);
1108+
}
1109+
1110+
@Override
1111+
public ResolvedJavaMethod getEnclosingConstructor() {
1112+
return runtime().reflection.getEnclosingConstructor(this);
1113+
}
1114+
11051115
@Override
11061116
public ResolvedJavaMethod[] getDeclaredConstructors() {
11071117
link();

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

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -302,6 +302,16 @@ public ResolvedJavaType getEnclosingType() {
302302
return null;
303303
}
304304

305+
@Override
306+
public ResolvedJavaMethod getEnclosingMethod() {
307+
return null;
308+
}
309+
310+
@Override
311+
public ResolvedJavaMethod getEnclosingConstructor() {
312+
return null;
313+
}
314+
305315
@Override
306316
public ResolvedJavaMethod[] getDeclaredConstructors() {
307317
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: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -391,6 +391,38 @@ default ResolvedJavaMethod resolveConcreteMethod(ResolvedJavaMethod method, Reso
391391
*/
392392
ResolvedJavaType getEnclosingType();
393393

394+
/**
395+
* Returns a {@link ResolvedJavaMethod} representing the immediately enclosing
396+
* method of the underlying type, if this type represents a local or anonymous
397+
* 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+
* @return the immediately enclosing method of the underlying class, if
404+
* this type is a local or anonymous class; otherwise {@code null}.
405+
*
406+
* @see Class#getEnclosingMethod()
407+
*/
408+
ResolvedJavaMethod getEnclosingMethod();
409+
410+
/**
411+
* Returns a {@link ResolvedJavaMethod} representing the immediately enclosing
412+
* constructor of the underlying type, if this type represents a local or anonymous
413+
* class within a method. Returns {@code null} otherwise.
414+
*
415+
* In particular, this method returns {@code null} if the underlying
416+
* type is a local or anonymous class immediately enclosed by a class or
417+
* interface declaration, instance initializer or static initializer.
418+
*
419+
* @return the immediately enclosing constructor of the underlying class, if
420+
* this type is a local or anonymous class; otherwise {@code null}.
421+
*
422+
* @see Class#getEnclosingConstructor()
423+
*/
424+
ResolvedJavaMethod getEnclosingConstructor();
425+
394426
/**
395427
* Returns an array reflecting all the constructors declared by this type. This method is
396428
* 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: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -751,6 +751,72 @@ private void assertGetPermittedSubclasses(Class<?> clazz) {
751751
}
752752
}
753753

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

756822
final Method implementation;

0 commit comments

Comments
 (0)