--- old/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/CompilerToVM.java 2017-06-15 15:05:47.000000000 -0700 +++ new/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/CompilerToVM.java 2017-06-15 15:05:46.000000000 -0700 @@ -644,4 +644,9 @@ * {@link Long} */ native Object getFlagValue(String name); + + /** + * Gets the host class for {@code type}. + */ + native HotSpotResolvedObjectTypeImpl getHostClass(HotSpotResolvedObjectTypeImpl type); } --- old/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedObjectTypeImpl.java 2017-06-15 15:05:47.000000000 -0700 +++ new/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedObjectTypeImpl.java 2017-06-15 15:05:47.000000000 -0700 @@ -412,6 +412,14 @@ } @Override + public ResolvedJavaType getHostClass() { + if (isArray()) { + return null; + } + return compilerToVM().getHostClass(this); + } + + @Override public boolean isJavaLangObject() { return javaClass.equals(Object.class); } --- old/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedPrimitiveType.java 2017-06-15 15:05:48.000000000 -0700 +++ new/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedPrimitiveType.java 2017-06-15 15:05:47.000000000 -0700 @@ -154,6 +154,11 @@ } @Override + public ResolvedJavaType getHostClass() { + return null; + } + + @Override public JavaKind getJavaKind() { return kind; } --- old/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/ResolvedJavaType.java 2017-06-15 15:05:48.000000000 -0700 +++ new/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/ResolvedJavaType.java 2017-06-15 15:05:48.000000000 -0700 @@ -105,6 +105,13 @@ boolean isAssignableFrom(ResolvedJavaType other); /** + * Returns the {@link ResolvedJavaType} object representing the host class of this VM anonymous + * class (as opposed to the unrelated concept specified by {@link Class#isAnonymousClass()}) or + * {@code null} if this object does not represent a VM anonymous class. + */ + ResolvedJavaType getHostClass(); + + /** * Returns true if this type is exactly the type {@link java.lang.Object}. */ default boolean isJavaLangObject() { --- old/src/share/vm/jvmci/jvmciCompilerToVM.cpp 2017-06-15 15:05:48.000000000 -0700 +++ new/src/share/vm/jvmci/jvmciCompilerToVM.cpp 2017-06-15 15:05:48.000000000 -0700 @@ -1692,6 +1692,13 @@ } C2V_END +C2V_VMENTRY(jobject, getHostClass, (JNIEnv*, jobject, jobject jvmci_type)) + InstanceKlass* k = InstanceKlass::cast(CompilerToVM::asKlass(jvmci_type)); + InstanceKlass* host = k->host_klass(); + oop result = CompilerToVM::get_jvmci_type(host, CHECK_NULL); + return JNIHandles::make_local(THREAD, result); +C2V_END + C2V_VMENTRY(int, interpreterFrameSize, (JNIEnv*, jobject, jobject bytecode_frame_handle)) if (bytecode_frame_handle == NULL) { THROW_0(vmSymbols::java_lang_NullPointerException()); @@ -1822,6 +1829,7 @@ {CC "flushDebugOutput", CC "()V", FN_PTR(flushDebugOutput)}, {CC "methodDataProfileDataSize", CC "(JI)I", FN_PTR(methodDataProfileDataSize)}, {CC "getFingerprint", CC "(J)J", FN_PTR(getFingerprint)}, + {CC "getHostClass", CC "(" HS_RESOLVED_KLASS ")" HS_RESOLVED_KLASS, FN_PTR(getHostClass)}, {CC "interpreterFrameSize", CC "(" BYTECODE_FRAME ")I", FN_PTR(interpreterFrameSize)}, {CC "compileToBytecode", CC "(" OBJECT ")V", FN_PTR(compileToBytecode)}, {CC "getFlagValue", CC "(" STRING ")" OBJECT, FN_PTR(getFlagValue)}, --- old/test/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/TestResolvedJavaType.java 2017-06-15 15:05:49.000000000 -0700 +++ new/test/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/TestResolvedJavaType.java 2017-06-15 15:05:49.000000000 -0700 @@ -54,6 +54,7 @@ import java.lang.reflect.Modifier; import java.util.Arrays; import java.util.Collections; +import java.util.function.Supplier; import java.util.HashMap; import java.util.HashSet; import java.util.Map; @@ -143,6 +144,27 @@ } @Test + public void getHostClassTest() { + for (Class c : classes) { + ResolvedJavaType type = metaAccess.lookupJavaType(c); + ResolvedJavaType host = type.getHostClass(); + assertNull(host); + } + + class LocalClass {} + Cloneable clone = new Cloneable() {}; + assertNull(metaAccess.lookupJavaType(LocalClass.class).getHostClass()); + assertNull(metaAccess.lookupJavaType(clone.getClass()).getHostClass()); + + Supplier lambda = () -> () -> System.out.println("run"); + ResolvedJavaType lambdaType = metaAccess.lookupJavaType(lambda.getClass()); + ResolvedJavaType nestedLambdaType = metaAccess.lookupJavaType(lambda.get().getClass()); + assertNotNull(lambdaType.getHostClass()); + assertNotNull(nestedLambdaType.getHostClass()); + assertEquals(lambdaType.getHostClass(), nestedLambdaType.getHostClass()); + } + + @Test public void getModifiersTest() { for (Class c : classes) { ResolvedJavaType type = metaAccess.lookupJavaType(c);