From b0ae6343ad271b7367eb4b3d038efb4eec59d78f Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Thu, 31 Mar 2011 19:47:26 -0600 Subject: [PATCH] provide proper implementations of JVM_GetDeclaredClasses, JVM_GetDeclaringClass --- classpath/avian/ClassAddendum.java | 1 + classpath/avian/OpenJDK.java | 27 ++++++++ src/classpath-openjdk.cpp | 98 +++++++++++++++++++++++++----- src/machine.cpp | 33 +++++++++- src/types.def | 6 ++ 5 files changed, 148 insertions(+), 17 deletions(-) diff --git a/classpath/avian/ClassAddendum.java b/classpath/avian/ClassAddendum.java index 1719addfa4..ff11591046 100644 --- a/classpath/avian/ClassAddendum.java +++ b/classpath/avian/ClassAddendum.java @@ -12,4 +12,5 @@ package avian; public class ClassAddendum extends Addendum { public Object[] interfaceTable; + public Object[] innerClassTable; } diff --git a/classpath/avian/OpenJDK.java b/classpath/avian/OpenJDK.java index dcddbc0f67..de9c6f1f40 100644 --- a/classpath/avian/OpenJDK.java +++ b/classpath/avian/OpenJDK.java @@ -34,4 +34,31 @@ public class OpenJDK { return new ProtectionDomain(source, p); } + + private static byte[] replace(int a, int b, byte[] s, int offset, + int length) + { + byte[] array = new byte[length]; + for (int i = 0; i < length; ++i) { + byte c = s[i]; + array[i] = (byte) (c == a ? b : c); + } + 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; + } + } } diff --git a/src/classpath-openjdk.cpp b/src/classpath-openjdk.cpp index 89fab1ff16..127565f2f4 100644 --- a/src/classpath-openjdk.cpp +++ b/src/classpath-openjdk.cpp @@ -3743,31 +3743,101 @@ EXPORT(JVM_GetClassModifiers)(Thread* t, jclass c) return classFlags(t, jclassVmClass(t, *c)); } +uint64_t +jvmGetDeclaredClasses(Thread* t, uintptr_t* arguments) +{ + jclass c = reinterpret_cast(arguments[0]); + + object addendum = classAddendum(t, jclassVmClass(t, *c)); + if (addendum) { + object table = classAddendumInnerClassTable(t, addendum); + if (table) { + PROTECT(t, table); + + unsigned count = 0; + for (unsigned i = 0; i < arrayLength(t, table); ++i) { + if (innerClassReferenceOuter(t, arrayBody(t, table, i))) { + ++ count; + } + } + + object result = makeObjectArray(t, count); + PROTECT(t, result); + + for (unsigned i = 0; i < arrayLength(t, table); ++i) { + 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))))); + + -- count; + set(t, result, ArrayBody + (count * BytesPerWord), inner); + } + } + + return reinterpret_cast(makeLocalReference(t, result)); + } + } + + return reinterpret_cast + (makeLocalReference(t, makeObjectArray(t, 0))); +} + extern "C" JNIEXPORT jobjectArray JNICALL -EXPORT(JVM_GetDeclaredClasses)(Thread*, jclass) { abort(); } +EXPORT(JVM_GetDeclaredClasses)(Thread* t, jclass c) +{ + uintptr_t arguments[] = { reinterpret_cast(c) }; + + return reinterpret_cast(run(t, jvmGetDeclaredClasses, arguments)); +} + +uint64_t +jvmGetDeclaringClass(Thread* t, uintptr_t* arguments) +{ + jclass c = reinterpret_cast(arguments[0]); + + object method = resolveMethod + (t, root(t, Machine::BootLoader), "avian/OpenJDK", "getDeclaringClass", + "(Lavian/VMClass;)Ljava/lang/Class;"); + + return reinterpret_cast + (makeLocalReference + (t, t->m->processor->invoke(t, method, 0, jclassVmClass(t, *c)))); +} extern "C" JNIEXPORT jclass JNICALL -EXPORT(JVM_GetDeclaringClass)(Thread*, jclass) +EXPORT(JVM_GetDeclaringClass)(Thread* t, jclass c) { - // todo: implement properly + uintptr_t arguments[] = { reinterpret_cast(c) }; + + return reinterpret_cast(run(t, jvmGetDeclaringClass, arguments)); +} + +uint64_t +jvmGetClassSignature(Thread* t, uintptr_t* arguments) +{ + jclass c = reinterpret_cast(arguments[0]); + + object addendum = classAddendum(t, jclassVmClass(t, *c)); + if (addendum) { + object signature = addendumSignature(t, addendum); + if (signature) { + return reinterpret_cast + (makeLocalReference + (t, t->m->classpath->makeString + (t, signature, 0, byteArrayLength(t, signature) - 1))); + } + } return 0; } extern "C" JNIEXPORT jstring JNICALL EXPORT(JVM_GetClassSignature)(Thread* t, jclass c) { - ENTER(t, Thread::ActiveState); + uintptr_t arguments[] = { reinterpret_cast(c) }; - object addendum = classAddendum(t, jclassVmClass(t, *c)); - if (addendum) { - object signature = addendumSignature(t, addendum); - if (signature) { - return makeLocalReference - (t, t->m->classpath->makeString - (t, signature, 0, byteArrayLength(t, signature) - 1)); - } - } - return 0; + return reinterpret_cast(run(t, jvmGetClassSignature, arguments)); } extern "C" JNIEXPORT jbyteArray JNICALL diff --git a/src/machine.cpp b/src/machine.cpp index 4ba7426ac0..245b30577b 100644 --- a/src/machine.cpp +++ b/src/machine.cpp @@ -991,7 +991,7 @@ parseInterfaceTable(Thread* t, Stream& s, object class_, object pool, if (count) { table = makeArray(t, count); if (classAddendum(t, class_) == 0) { - object addendum = makeClassAddendum(t, pool, 0, 0, table); + object addendum = makeClassAddendum(t, pool, 0, 0, table, 0); set(t, class_, ClassAddendum, addendum); } } @@ -1724,17 +1724,44 @@ parseAttributeTable(Thread* t, Stream& s, object class_, object pool) &byteArrayBody(t, name, 0)) == 0) { if (addendum == 0) { - addendum = makeClassAddendum(t, pool, 0, 0, 0); + addendum = makeClassAddendum(t, pool, 0, 0, 0, 0); } set(t, addendum, AddendumSignature, singletonObject(t, pool, s.read2() - 1)); + } else if (vm::strcmp(reinterpret_cast("InnerClasses"), + &byteArrayBody(t, name, 0)) == 0) + { + if (addendum == 0) { + addendum = makeClassAddendum(t, pool, 0, 0, 0, 0); + } + + unsigned innerClassCount = s.read2(); + object table = makeArray(t, innerClassCount); + PROTECT(t, table); + + for (unsigned i = 0; i < innerClassCount; ++i) { + int16_t inner = s.read2(); + int16_t outer = s.read2(); + int16_t name = s.read2(); + int16_t flags = s.read2(); + + object reference = makeInnerClassReference + (t, inner ? singletonObject(t, pool, inner - 1) : 0, + outer ? singletonObject(t, pool, outer - 1) : 0, + name ? singletonObject(t, pool, name - 1) : 0, + flags); + + set(t, table, ArrayBody + (i * BytesPerWord), reference); + } + + set(t, addendum, ClassAddendumInnerClassTable, table); } else if (vm::strcmp(reinterpret_cast ("RuntimeVisibleAnnotations"), &byteArrayBody(t, name, 0)) == 0) { if (addendum == 0) { - addendum = makeClassAddendum(t, pool, 0, 0, 0); + addendum = makeClassAddendum(t, pool, 0, 0, 0, 0); } object body = makeByteArray(t, length); diff --git a/src/types.def b/src/types.def index cf04647e06..1ac0d915ea 100644 --- a/src/types.def +++ b/src/types.def @@ -161,6 +161,12 @@ (void* value) (object next)) +(type innerClassReference + (object inner) + (object outer) + (object name) + (int16_t flags)) + (type continuationContext (object next) (object before)