Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 52 additions & 0 deletions src/hotspot/share/jvmci/jvmciCompilerToVM.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2033,6 +2033,57 @@ C2V_VMENTRY_NULL(jobject, getComponentType, (JNIEnv* env, jobject, ARGUMENT_PAIR
return JVMCIENV->get_jobject(result);
C2V_END

// Iterates over the inner classes of `k` and adds them to `inner_types` if it is non-null.
// Returns the number of inner classes.
static int iterate_inner_classes(InstanceKlass* k, JVMCIObjectArray& inner_types, JavaThread* THREAD, JVMCIEnv* JVMCIENV) {
InnerClassesIterator iter(k);
constantPoolHandle cp(THREAD, k->constants());
int length = iter.length();
int members = 0;
for (; !iter.done(); iter.next()) {
int ioff = iter.inner_class_info_index();
int ooff = iter.outer_class_info_index();

if (ioff != 0 && ooff != 0) {
// Check to see if the name matches the class we're looking for
// before attempting to find the class.
if (cp->klass_name_at_matches(k, ooff)) {
Klass* outer_klass = cp->klass_at(ooff, CHECK_0);
if (outer_klass == k) {
Klass* ik = cp->klass_at(ioff, CHECK_0);
InstanceKlass* inner_klass = InstanceKlass::cast(ik);
if (inner_types.is_null()) {
// Throws an exception if outer klass has not declared k as
// an inner klass
Reflection::check_for_inner_class(k, inner_klass, true, CHECK_0);
} else {
JVMCIObject inner_type = JVMCIENV->get_jvmci_type(JVMCIKlassHandle(THREAD, inner_klass), JVMCI_CHECK_0);
JVMCIENV->put_object_at(inner_types, members, inner_type);
}
members++;
}
}
}
}
return members;
}

C2V_VMENTRY_NULL(jobject, getDeclaredTypes, (JNIEnv* env, jobject, ARGUMENT_PAIR(klass)))
Klass* klass = UNPACK_PAIR(Klass, klass);
if (klass == nullptr) {
JVMCI_THROW_NULL(NullPointerException);
}
if (!klass->is_instance_klass()) {
JVMCI_THROW_MSG_NULL(InternalError, err_msg("Class %s must be instance klass", klass->external_name()));
}
InstanceKlass* k = InstanceKlass::cast(klass);
JVMCIObjectArray inner_types;
int length = iterate_inner_classes(k, inner_types, thread, JVMCIENV);
inner_types = JVMCIENV->new_HotSpotResolvedObjectTypeImpl_array(length, JVMCI_CHECK_NULL);
iterate_inner_classes(k, inner_types, thread, JVMCIENV);
return JVMCIENV->get_jobject(inner_types);
C2V_END

C2V_VMENTRY(void, ensureInitialized, (JNIEnv* env, jobject, ARGUMENT_PAIR(klass)))
Klass* klass = UNPACK_PAIR(Klass, klass);
if (klass == nullptr) {
Expand Down Expand Up @@ -3445,6 +3496,7 @@ JNINativeMethod CompilerToVM::methods[] = {
{CC "updateCompilerThreadCanCallJava", CC "(Z)Z", FN_PTR(updateCompilerThreadCanCallJava)},
{CC "getCompilationActivityMode", CC "()I", FN_PTR(getCompilationActivityMode)},
{CC "isCompilerThread", CC "()Z", FN_PTR(isCompilerThread)},
{CC "getDeclaredTypes", CC "(" HS_KLASS2 ")[" HS_KLASS, FN_PTR(getDeclaredTypes)},
};

int CompilerToVM::methods_count() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1182,6 +1182,15 @@ HotSpotResolvedObjectTypeImpl.FieldInfo[] getDeclaredFieldsInfo(HotSpotResolvedO

native HotSpotResolvedObjectTypeImpl.FieldInfo[] getDeclaredFieldsInfo(HotSpotResolvedObjectTypeImpl klass, long klassPointer);

/**
* @see ResolvedJavaType#getDeclaredTypes()
*/
HotSpotResolvedObjectTypeImpl[] getDeclaredTypes(HotSpotResolvedObjectTypeImpl klass) {
return getDeclaredTypes(klass, klass.getKlassPointer());
}

native HotSpotResolvedObjectTypeImpl[] getDeclaredTypes(HotSpotResolvedObjectTypeImpl klass, long klassPointer);

/**
* Reads the current value of a static field of {@code declaringKlass}. Extra sanity checking is
* performed on the offset and kind of the read being performed.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,6 @@
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.nio.ByteOrder;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;

Expand Down Expand Up @@ -1075,6 +1072,14 @@ public List<ResolvedJavaMethod> getAllMethods(boolean forceLink) {
return List.of(runtime().compilerToVm.getAllMethods(this));
}

@Override
public ResolvedJavaType[] getDeclaredTypes() {
if (isArray()) {
return new ResolvedJavaType[0];
}
return compilerToVM().getDeclaredTypes(this);
}

@Override
public ResolvedJavaMethod getClassInitializer() {
if (!isArray()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -307,6 +307,11 @@ public ResolvedJavaMethod[] getDeclaredMethods(boolean forceLink) {
return new ResolvedJavaMethod[0];
}

@Override
public ResolvedJavaType[] getDeclaredTypes() {
return new ResolvedJavaType[0];
}

@Override
public ResolvedJavaMethod[] getDeclaredMethods() {
return new ResolvedJavaMethod[0];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -333,9 +333,23 @@ default ResolvedJavaMethod resolveConcreteMethod(ResolvedJavaMethod method, Reso

/**
* Returns {@code true} if the type is a member type.
*
* @see Class#isMemberClass()
*/
boolean isMember();

/**
* Gets the classes and interfaces declared as members of this type.
* This includes public, protected, default
* (package) access, and private classes and interfaces declared by the
* class, but excludes inherited classes and interfaces. This method
* returns an array of length 0 if this type declares no classes or
* interfaces as members, or if it is a primitive type, an array class, or void.
*
* @see Class#getDeclaredClasses()
*/
ResolvedJavaType[] getDeclaredTypes();

/**
* Returns the enclosing type of this type, if it exists, or {@code null}.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,6 @@
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.function.BiConsumer;
import java.util.function.Supplier;
import java.util.HashMap;
Expand Down Expand Up @@ -1084,6 +1083,25 @@ public void getAllMethodsTest() {
}
}

@Test
public void getDeclaredTypesTest() {
for (Class<?> c : classes) {
ResolvedJavaType type = metaAccess.lookupJavaType(c);
Class<?>[] raw = c.getDeclaredClasses();
Set<ResolvedJavaType> expected = new HashSet<>();
for (Class<?> e : raw) {
ResolvedJavaType resolvedType = metaAccess.lookupJavaType(e);
assertNotNull(resolvedType);
expected.add(resolvedType);
}
Set<ResolvedJavaType> actual = new HashSet<>(Arrays.asList(type.getDeclaredTypes()));
for (ResolvedJavaType t : actual) {
assertNotNull(t.toString(), runtime.getMirror(t));
}
assertEquals(expected, actual);
}
}

static class A {
static String name = "foo";
}
Expand Down
Loading