fix Class.getModifiers for inner classes and implement JVM_GetDeclaringClass and JVM_GetEnclosingMethodInfo properly

This fixes a couple of tests in the Scala test suite
(run/reflection-modulemirror-toplevel-badpath.scala and
run/reflection-constructormirror-nested-good.scala).
This commit is contained in:
Joel Dice 2013-04-17 15:12:58 -06:00
parent aa513c2c1d
commit 81d7786716
5 changed files with 105 additions and 30 deletions

View File

@ -14,4 +14,6 @@ public class ClassAddendum extends Addendum {
public Object[] interfaceTable;
public Object[] innerClassTable;
public Object[] methodTable;
public Object enclosingClass;
public Object enclosingMethod;
}

View File

@ -45,20 +45,4 @@ public class OpenJDK {
}
return array;
}
public static Class getDeclaringClass(VMClass c) {
try {
String name = new String
(replace('/', '.', c.name, 0, c.name.length - 1), 0,
c.name.length - 1);
int index = name.lastIndexOf("$");
if (index == -1) {
return null;
} else {
return c.loader.loadClass(name.substring(0, index));
}
} catch (ClassNotFoundException e) {
return null;
}
}
}

View File

@ -4445,8 +4445,8 @@ jvmGetDeclaredClasses(Thread* t, uintptr_t* arguments)
if (innerClassReferenceOuter(t, arrayBody(t, table, i))) {
object inner = getJClass
(t, resolveClass
(t, classLoader(t, jclassVmClass(t, *c)), referenceName
(t, innerClassReferenceInner(t, arrayBody(t, table, i)))));
(t, classLoader(t, jclassVmClass(t, *c)),
innerClassReferenceInner(t, arrayBody(t, table, i))));
-- count;
set(t, result, ArrayBody + (count * BytesPerWord), inner);
@ -4474,13 +4474,29 @@ jvmGetDeclaringClass(Thread* t, uintptr_t* arguments)
{
jclass c = reinterpret_cast<jobject>(arguments[0]);
object method = resolveMethod
(t, root(t, Machine::BootLoader), "avian/OpenJDK", "getDeclaringClass",
"(Lavian/VMClass;)Ljava/lang/Class;");
object class_ = jclassVmClass(t, *c);
object addendum = classAddendum(t, class_);
if (addendum) {
object table = classAddendumInnerClassTable(t, addendum);
if (table) {
for (unsigned i = 0; i < arrayLength(t, table); ++i) {
object reference = arrayBody(t, table, i);
if (strcmp
(&byteArrayBody(t, innerClassReferenceInner(t, reference), 0),
&byteArrayBody(t, className(t, class_), 0)) == 0)
{
return reinterpret_cast<uintptr_t>
(makeLocalReference
(t, getJClass
(t, resolveClass
(t, classLoader(t, class_), innerClassReferenceOuter
(t, reference)))));
}
}
}
}
return reinterpret_cast<uintptr_t>
(makeLocalReference
(t, t->m->processor->invoke(t, method, 0, jclassVmClass(t, *c))));
return 0;
}
extern "C" JNIEXPORT jclass JNICALL
@ -5517,13 +5533,61 @@ EXPORT(JVM_GetManagement)(jint version)
extern "C" JNIEXPORT jobject JNICALL
EXPORT(JVM_InitAgentProperties)(Thread*, jobject) { abort(); }
extern "C" JNIEXPORT jobjectArray JNICALL
EXPORT(JVM_GetEnclosingMethodInfo)(JNIEnv*, jclass)
uint64_t
getEnclosingMethodInfo(Thread* t, uintptr_t* arguments)
{
// todo: implement properly
jclass c = reinterpret_cast<jclass>(arguments[0]);
object class_ = jclassVmClass(t, *c);
PROTECT(t, class_);
object addendum = classAddendum(t, class_);
if (addendum) {
object enclosingClass = classAddendumEnclosingClass(t, addendum);
if (enclosingClass) {
PROTECT(t, enclosingClass);
object array = makeObjectArray(t, type(t, Machine::JobjectType), 3);
PROTECT(t, array);
enclosingClass = getJClass
(t, resolveClass(t, classLoader(t, class_), enclosingClass));
set(t, array, ArrayBody, enclosingClass);
object enclosingMethod = classAddendumEnclosingMethod(t, addendum);
if (enclosingMethod) {
PROTECT(t, enclosingMethod);
object name = t->m->classpath->makeString
(t, pairFirst(t, enclosingMethod), 0,
byteArrayLength(t, pairFirst(t, enclosingMethod)) - 1);
set(t, array, ArrayBody + BytesPerWord, name);
object spec = t->m->classpath->makeString
(t, pairSecond(t, enclosingMethod), 0,
byteArrayLength(t, pairSecond(t, enclosingMethod)) - 1);
set(t, array, ArrayBody + (2 * BytesPerWord), spec);
}
return reinterpret_cast<uintptr_t>(makeLocalReference(t, array));
}
}
return 0;
}
extern "C" JNIEXPORT jobjectArray JNICALL
EXPORT(JVM_GetEnclosingMethodInfo)(Thread* t, jclass c)
{
uintptr_t arguments[] = { reinterpret_cast<uintptr_t>(c) };
return reinterpret_cast<jobjectArray>
(run(t, getEnclosingMethodInfo, arguments));
}
extern "C" JNIEXPORT jintArray JNICALL
EXPORT(JVM_GetThreadStateValues)(JNIEnv*, jint) { abort(); }

View File

@ -1123,7 +1123,7 @@ getClassAddendum(Thread* t, object class_, object pool)
if (addendum == 0) {
PROTECT(t, class_);
addendum = makeClassAddendum(t, pool, 0, 0, 0, 0, 0);
addendum = makeClassAddendum(t, pool, 0, 0, 0, 0, 0, 0, 0);
set(t, class_, ClassAddendum, addendum);
}
return addendum;
@ -2303,12 +2303,20 @@ parseAttributeTable(Thread* t, Stream& s, object class_, object pool)
int16_t flags = s.read2();
object reference = makeInnerClassReference
(t, inner ? singletonObject(t, pool, inner - 1) : 0,
outer ? singletonObject(t, pool, outer - 1) : 0,
(t,
inner ? referenceName(t, singletonObject(t, pool, inner - 1)) : 0,
outer ? referenceName(t, singletonObject(t, pool, outer - 1)) : 0,
name ? singletonObject(t, pool, name - 1) : 0,
flags);
set(t, table, ArrayBody + (i * BytesPerWord), reference);
if (0 == strcmp
(&byteArrayBody(t, className(t, class_), 0),
&byteArrayBody(t, innerClassReferenceInner(t, reference), 0)))
{
classFlags(t, class_) |= flags;
}
}
object addendum = getClassAddendum(t, class_, pool);
@ -2323,6 +2331,20 @@ parseAttributeTable(Thread* t, Stream& s, object class_, object pool)
object addendum = getClassAddendum(t, class_, pool);
set(t, addendum, AddendumAnnotationTable, body);
} else if (vm::strcmp(reinterpret_cast<const int8_t*>
("EnclosingMethod"),
&byteArrayBody(t, name, 0)) == 0)
{
int16_t enclosingClass = s.read2();
int16_t enclosingMethod = s.read2();
object addendum = getClassAddendum(t, class_, pool);
set(t, addendum, ClassAddendumEnclosingClass,
referenceName(t, singletonObject(t, pool, enclosingClass - 1)));
set(t, addendum, ClassAddendumEnclosingMethod, enclosingMethod
? singletonObject(t, pool, enclosingMethod - 1) : 0);
} else {
s.skip(length);
}

View File

@ -256,5 +256,8 @@ public class Misc {
expect(new Object[0] instanceof Cloneable);
expect(new Object[0] instanceof java.io.Serializable);
expect((Baz.class.getModifiers() & java.lang.reflect.Modifier.STATIC)
!= 0);
}
}