From 4e12847858b7ddaaecdfd5e1ef2696b44a5d735e Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Tue, 23 Apr 2013 13:47:15 -0600 Subject: [PATCH] code rearrangment to improve state of Android libcore tests This mainly moves several sun.misc.Unsafe method implementations from classpath-openjdk.cpp to builtin.cpp so that the Avian and Android builds can use them. It also replaces FinalizerReference.finalizeAllEnqueued with a no-op, since the real implementations assumes too much about how the VM handles (or delegates) finalization. --- classpath/avian/Classes.java | 35 ++++++++ classpath/java/lang/Class.java | 48 +---------- classpath/sun/misc/Unsafe.java | 15 ++++ src/avian/machine.h | 12 +++ src/builtin.cpp | 111 ++++++++++++++++++++++++++ src/classpath-android.cpp | 42 +++++++++- src/classpath-avian.cpp | 5 +- src/classpath-openjdk.cpp | 142 +-------------------------------- src/machine.cpp | 61 ++++++++++++++ 9 files changed, 283 insertions(+), 188 deletions(-) diff --git a/classpath/avian/Classes.java b/classpath/avian/Classes.java index a50118e1b3..a689fafd98 100644 --- a/classpath/avian/Classes.java +++ b/classpath/avian/Classes.java @@ -406,6 +406,41 @@ public class Classes { return -1; } + public static int countMethods(VMClass vmClass, boolean publicOnly) { + int count = 0; + if (vmClass.methodTable != null) { + for (int i = 0; i < vmClass.methodTable.length; ++i) { + if (((! publicOnly) + || ((vmClass.methodTable[i].flags & Modifier.PUBLIC)) + != 0) + && (! toString(vmClass.methodTable[i].name).startsWith("<"))) + { + ++ count; + } + } + } + return count; + } + + public static Method[] getMethods(VMClass vmClass, boolean publicOnly) { + Method[] array = new Method[countMethods(vmClass, publicOnly)]; + if (vmClass.methodTable != null) { + Classes.link(vmClass); + + int ai = 0; + for (int i = 0; i < vmClass.methodTable.length; ++i) { + if ((((vmClass.methodTable[i].flags & Modifier.PUBLIC) != 0) + || (! publicOnly)) + && ! toString(vmClass.methodTable[i].name).startsWith("<")) + { + array[ai++] = makeMethod(SystemClassLoader.getClass(vmClass), i); + } + } + } + + return array; + } + public static Annotation getAnnotation(ClassLoader loader, Object[] a) { if (a[0] == null) { a[0] = Proxy.newProxyInstance diff --git a/classpath/java/lang/Class.java b/classpath/java/lang/Class.java index baebcae4c9..ad118c013b 100644 --- a/classpath/java/lang/Class.java +++ b/classpath/java/lang/Class.java @@ -366,54 +366,12 @@ public final class Class implements Type, AnnotatedElement { return fields.toArray(new Field[fields.size()]); } - private int countMethods(boolean publicOnly) { - int count = 0; - if (vmClass.methodTable != null) { - for (int i = 0; i < vmClass.methodTable.length; ++i) { - if (((! publicOnly) - || ((vmClass.methodTable[i].flags & Modifier.PUBLIC)) - != 0) - && (! Method.getName(vmClass.methodTable[i]).startsWith("<"))) - { - ++ count; - } - } - } - return count; - } - public Method[] getDeclaredMethods() { - Method[] array = new Method[countMethods(false)]; - if (vmClass.methodTable != null) { - Classes.link(vmClass); - - int ai = 0; - for (int i = 0; i < vmClass.methodTable.length; ++i) { - if (! Method.getName(vmClass.methodTable[i]).startsWith("<")) { - array[ai++] = new Method(vmClass.methodTable[i]); - } - } - } - - return array; + return Classes.getMethods(vmClass, false); } public Method[] getMethods() { - Method[] array = new Method[countMethods(true)]; - if (vmClass.methodTable != null) { - Classes.link(vmClass); - - int index = 0; - for (int i = 0; i < vmClass.methodTable.length; ++i) { - if (((vmClass.methodTable[i].flags & Modifier.PUBLIC) != 0) - && (! Method.getName(vmClass.methodTable[i]).startsWith("<"))) - { - array[index++] = new Method(vmClass.methodTable[i]); - } - } - } - - return array; + return Classes.getMethods(vmClass, true); } public Class[] getInterfaces() { @@ -591,7 +549,7 @@ public final class Class implements Type, AnnotatedElement { } public Annotation[] getAnnotations() { - Annotation[] array = new Annotation[countMethods(true)]; + Annotation[] array = new Annotation[countAnnotations()]; int i = 0; for (VMClass c = vmClass; c != null; c = c.super_) { if (c.addendum != null && c.addendum.annotationTable != null) { diff --git a/classpath/sun/misc/Unsafe.java b/classpath/sun/misc/Unsafe.java index 5fea56c54a..57309949e6 100644 --- a/classpath/sun/misc/Unsafe.java +++ b/classpath/sun/misc/Unsafe.java @@ -46,6 +46,14 @@ public final class Unsafe { public native void putDouble(long address, double x); + public native void putIntVolatile(Object o, long offset, int x); + + public native void putOrderedInt(Object o, long offset, int x); + + public native Object getObject(Object o, long offset); + + public native void putObject(Object o, long offset, Object x); + public native long getAddress(long address); public native void putAddress(long address, long x); @@ -54,6 +62,10 @@ public final class Unsafe { public native long objectFieldOffset(Field field); + public native void park(boolean absolute, long time); + + public native void unpark(Object target); + public native void copyMemory(Object srcBase, long srcOffset, Object destBase, long destOffset, long count); @@ -61,6 +73,9 @@ public final class Unsafe { public native boolean compareAndSwapInt(Object o, long offset, int old, int new_); + public native boolean compareAndSwapObject(Object o, long offset, Object old, + Object new_); + public void copyMemory(long src, long dst, long count) { copyMemory(null, src, null, dst, count); } diff --git a/src/avian/machine.h b/src/avian/machine.h index ae6a0368da..e52b2e2c32 100644 --- a/src/avian/machine.h +++ b/src/avian/machine.h @@ -3942,6 +3942,18 @@ lineNumberLine(uint64_t ln) return ln & 0xFFFFFFFF; } +object +interruptLock(Thread* t, object thread); + +void +clearInterrupted(Thread* t); + +void +threadInterrupt(Thread* t, object thread); + +bool +threadIsInterrupted(Thread* t, object thread, bool clear); + inline FILE* errorLog(Thread* t) { diff --git a/src/builtin.cpp b/src/builtin.cpp index b8fa0f75f1..956d52e7e4 100644 --- a/src/builtin.cpp +++ b/src/builtin.cpp @@ -604,6 +604,46 @@ Avian_java_nio_FixedArrayByteBuffer_allocateFixed return reinterpret_cast(array); } +extern "C" JNIEXPORT int64_t JNICALL +Avian_sun_misc_Unsafe_getObject +(Thread*, object, uintptr_t* arguments) +{ + object o = reinterpret_cast(arguments[1]); + int64_t offset; memcpy(&offset, arguments + 2, 8); + + return fieldAtOffset(o, offset); +} + +extern "C" JNIEXPORT void JNICALL +Avian_sun_misc_Unsafe_putObject +(Thread* t, object, uintptr_t* arguments) +{ + object o = reinterpret_cast(arguments[1]); + int64_t offset; memcpy(&offset, arguments + 2, 8); + uintptr_t value = arguments[4]; + + set(t, o, offset, reinterpret_cast(value)); +} + +extern "C" JNIEXPORT int64_t JNICALL +Avian_sun_misc_Unsafe_compareAndSwapObject +(Thread* t, object, uintptr_t* arguments) +{ + object target = reinterpret_cast(arguments[1]); + int64_t offset; memcpy(&offset, arguments + 2, 8); + uintptr_t expect = arguments[4]; + uintptr_t update = arguments[5]; + + bool success = atomicCompareAndSwap + (&fieldAtOffset(target, offset), expect, update); + + if (success) { + mark(t, target, offset); + } + + return success; +} + extern "C" JNIEXPORT int64_t JNICALL Avian_sun_misc_Unsafe_compareAndSwapInt (Thread*, object, uintptr_t* arguments) @@ -617,6 +657,77 @@ Avian_sun_misc_Unsafe_compareAndSwapInt (&fieldAtOffset(target, offset), expect, update); } +extern "C" JNIEXPORT void JNICALL +Avian_sun_misc_Unsafe_unpark +(Thread* t, object, uintptr_t* arguments) +{ + object thread = reinterpret_cast(arguments[1]); + + monitorAcquire(t, interruptLock(t, thread)); + threadUnparked(t, thread) = true; + monitorNotify(t, interruptLock(t, thread)); + monitorRelease(t, interruptLock(t, thread)); +} + +extern "C" JNIEXPORT void JNICALL +Avian_sun_misc_Unsafe_park +(Thread* t, object, uintptr_t* arguments) +{ + bool absolute = arguments[1]; + int64_t time; memcpy(&time, arguments + 2, 8); + + int64_t then = t->m->system->now(); + + if (absolute) { + time -= then; + if (time <= 0) { + return; + } + } else if (time) { + // if not absolute, interpret time as nanoseconds, but make sure + // it doesn't become zero when we convert to milliseconds, since + // zero is interpreted as infinity below + time = (time / (1000 * 1000)) + 1; + } + + monitorAcquire(t, interruptLock(t, t->javaThread)); + while (time >= 0 + and (not (threadUnparked(t, t->javaThread) + or monitorWait + (t, interruptLock(t, t->javaThread), time)))) + { + int64_t now = t->m->system->now(); + time -= now - then; + then = now; + + if (time == 0) { + break; + } + } + threadUnparked(t, t->javaThread) = false; + monitorRelease(t, interruptLock(t, t->javaThread)); +} + +extern "C" JNIEXPORT void JNICALL +Avian_sun_misc_Unsafe_putIntVolatile +(Thread*, object, uintptr_t* arguments) +{ + object o = reinterpret_cast(arguments[1]); + int64_t offset; memcpy(&offset, arguments + 2, 8); + int32_t value = arguments[4]; + + storeStoreMemoryBarrier(); + fieldAtOffset(o, offset) = value; + storeLoadMemoryBarrier(); +} + +extern "C" JNIEXPORT void JNICALL +Avian_sun_misc_Unsafe_putOrderedInt +(Thread* t, object method, uintptr_t* arguments) +{ + Avian_sun_misc_Unsafe_putIntVolatile(t, method, arguments); +} + extern "C" JNIEXPORT int64_t JNICALL Avian_avian_Classes_primitiveClass (Thread* t, object, uintptr_t* arguments) diff --git a/src/classpath-android.cpp b/src/classpath-android.cpp index 87fa114cf0..b086069109 100644 --- a/src/classpath-android.cpp +++ b/src/classpath-android.cpp @@ -48,6 +48,12 @@ loadLibrary(Thread* t, object, uintptr_t* arguments) loadLibrary(t, "", RUNTIME_ARRAY_BODY(n), true, true); } +void JNICALL +finalizeAllEnqueued(Thread*, object, uintptr_t*) +{ + // ignore +} + int64_t JNICALL appLoader(Thread* t, object, uintptr_t*) { @@ -150,6 +156,11 @@ initVmThread(Thread* t, object thread) set(t, thread, fieldOffset(t, field), instance); } + + if (threadGroup(t, thread) == 0) { + set(t, thread, ThreadGroup, threadGroup(t, t->javaThread)); + expect(t, threadGroup(t, thread)); + } } object @@ -352,6 +363,18 @@ class MyClasspath : public Classpath { } } + { object c = resolveClass + (t, root(t, Machine::BootLoader), "java/lang/ref/FinalizerReference", + false); + + if (c) { + PROTECT(t, c); + + intercept(t, c, "finalizeAllEnqueued", "()V", + voidPointer(finalizeAllEnqueued), updateRuntimeData); + } + } + { object c = resolveClass (t, root(t, Machine::BootLoader), "java/lang/ClassLoader", false); @@ -1071,7 +1094,7 @@ Avian_java_lang_VMThread_getStatus (Thread*, object, uintptr_t*) { // todo - return -1; + return 1; } extern "C" JNIEXPORT int64_t JNICALL @@ -1381,6 +1404,23 @@ Avian_java_lang_Class_isInstance } } +extern "C" JNIEXPORT int64_t JNICALL +Avian_java_lang_Class_getDeclaredMethods +(Thread* t, object, uintptr_t* arguments) +{ + object c = reinterpret_cast(arguments[0]); + PROTECT(t, c); + + bool publicOnly = arguments[1]; + + object get = resolveMethod + (t, root(t, Machine::BootLoader), "avian/Classes", "getMethods", + "(Lavian/VMClass;Z)[Ljava/lang/reflect/Method;"); + + return reinterpret_cast + (t->m->processor->invoke(t, get, 0, jclassVmClass(t, c), publicOnly)); +} + extern "C" JNIEXPORT int64_t JNICALL Avian_java_lang_reflect_Method_invokeNative (Thread* t, object, uintptr_t* arguments) diff --git a/src/classpath-avian.cpp b/src/classpath-avian.cpp index ef16a767c1..c0be4b07dc 100644 --- a/src/classpath-avian.cpp +++ b/src/classpath-avian.cpp @@ -661,7 +661,7 @@ Avian_java_lang_Thread_interrupt { int64_t peer; memcpy(&peer, arguments, 8); - interrupt(t, reinterpret_cast(peer)); + threadInterrupt(t, reinterpret_cast(peer)->javaThread); } extern "C" JNIEXPORT int64_t JNICALL @@ -670,7 +670,8 @@ Avian_java_lang_Thread_interrupted { int64_t peer; memcpy(&peer, arguments, 8); - return getAndClearInterrupted(t, reinterpret_cast(peer)); + return threadIsInterrupted + (t, reinterpret_cast(peer)->javaThread, true); } extern "C" JNIEXPORT int64_t JNICALL diff --git a/src/classpath-openjdk.cpp b/src/classpath-openjdk.cpp index fcbf27ea57..ee3a960ddf 100644 --- a/src/classpath-openjdk.cpp +++ b/src/classpath-openjdk.cpp @@ -2461,38 +2461,6 @@ setProperty(Thread* t, object method, object properties, t->m->processor->invoke(t, method, properties, n, v); } -object -interruptLock(Thread* t, object thread) -{ - object lock = threadInterruptLock(t, thread); - - loadMemoryBarrier(); - - if (lock == 0) { - PROTECT(t, thread); - ACQUIRE(t, t->m->referenceLock); - - if (threadInterruptLock(t, thread) == 0) { - object head = makeMonitorNode(t, 0, 0); - object lock = makeMonitor(t, 0, 0, 0, head, head, 0); - - storeStoreMemoryBarrier(); - - set(t, thread, ThreadInterruptLock, lock); - } - } - - return threadInterruptLock(t, thread); -} - -void -clearInterrupted(Thread* t) -{ - monitorAcquire(t, local::interruptLock(t, t->javaThread)); - threadInterrupted(t, t->javaThread) = false; - monitorRelease(t, local::interruptLock(t, t->javaThread)); -} - bool pipeAvailable(int fd, int* available) { @@ -2724,27 +2692,6 @@ Avian_sun_misc_Unsafe_objectFieldOffset (t, jclassVmClass(t, jfieldClazz(t, jfield))), jfieldSlot(t, jfield))); } -extern "C" JNIEXPORT int64_t JNICALL -Avian_sun_misc_Unsafe_getObject -(Thread*, object, uintptr_t* arguments) -{ - object o = reinterpret_cast(arguments[1]); - int64_t offset; memcpy(&offset, arguments + 2, 8); - - return fieldAtOffset(o, offset); -} - -extern "C" JNIEXPORT void JNICALL -Avian_sun_misc_Unsafe_putObject -(Thread* t, object, uintptr_t* arguments) -{ - object o = reinterpret_cast(arguments[1]); - int64_t offset; memcpy(&offset, arguments + 2, 8); - uintptr_t value = arguments[4]; - - set(t, o, offset, reinterpret_cast(value)); -} - extern "C" JNIEXPORT int64_t JNICALL Avian_sun_misc_Unsafe_getShort__Ljava_lang_Object_2J (Thread*, object, uintptr_t* arguments) @@ -2959,25 +2906,6 @@ Avian_sun_misc_Unsafe_putOrderedObject Avian_sun_misc_Unsafe_putObjectVolatile(t, method, arguments); } -extern "C" JNIEXPORT int64_t JNICALL -Avian_sun_misc_Unsafe_compareAndSwapObject -(Thread* t, object, uintptr_t* arguments) -{ - object target = reinterpret_cast(arguments[1]); - int64_t offset; memcpy(&offset, arguments + 2, 8); - uintptr_t expect = arguments[4]; - uintptr_t update = arguments[5]; - - bool success = atomicCompareAndSwap - (&fieldAtOffset(target, offset), expect, update); - - if (success) { - mark(t, target, offset); - } - - return success; -} - extern "C" JNIEXPORT int64_t JNICALL Avian_sun_misc_Unsafe_compareAndSwapLong (Thread* t UNUSED, object, uintptr_t* arguments) @@ -3015,57 +2943,6 @@ Avian_sun_misc_Unsafe_ensureClassInitialized initClass(t, jclassVmClass(t, reinterpret_cast(arguments[1]))); } -extern "C" JNIEXPORT void JNICALL -Avian_sun_misc_Unsafe_unpark -(Thread* t, object, uintptr_t* arguments) -{ - object thread = reinterpret_cast(arguments[1]); - - monitorAcquire(t, local::interruptLock(t, thread)); - threadUnparked(t, thread) = true; - monitorNotify(t, local::interruptLock(t, thread)); - monitorRelease(t, local::interruptLock(t, thread)); -} - -extern "C" JNIEXPORT void JNICALL -Avian_sun_misc_Unsafe_park -(Thread* t, object, uintptr_t* arguments) -{ - bool absolute = arguments[1]; - int64_t time; memcpy(&time, arguments + 2, 8); - - int64_t then = t->m->system->now(); - - if (absolute) { - time -= then; - if (time <= 0) { - return; - } - } else if (time) { - // if not absolute, interpret time as nanoseconds, but make sure - // it doesn't become zero when we convert to milliseconds, since - // zero is interpreted as infinity below - time = (time / (1000 * 1000)) + 1; - } - - monitorAcquire(t, local::interruptLock(t, t->javaThread)); - while (time >= 0 - and (not (threadUnparked(t, t->javaThread) - or monitorWait - (t, local::interruptLock(t, t->javaThread), time)))) - { - int64_t now = t->m->system->now(); - time -= now - then; - then = now; - - if (time == 0) { - break; - } - } - threadUnparked(t, t->javaThread) = false; - monitorRelease(t, local::interruptLock(t, t->javaThread)); -} - extern "C" JNIEXPORT void JNICALL Avian_sun_misc_Unsafe_monitorEnter (Thread* t, object, uintptr_t* arguments) @@ -3635,15 +3512,7 @@ EXPORT(JVM_CountStackFrames)(Thread*, jobject) { abort(); } uint64_t jvmInterrupt(Thread* t, uintptr_t* arguments) { - jobject thread = reinterpret_cast(arguments[0]); - - monitorAcquire(t, local::interruptLock(t, *thread)); - Thread* p = reinterpret_cast(threadPeer(t, *thread)); - if (p) { - interrupt(t, p); - } - threadInterrupted(t, *thread) = true; - monitorRelease(t, local::interruptLock(t, *thread)); + threadInterrupt(t, *reinterpret_cast(arguments[0])); return 1; } @@ -3662,14 +3531,7 @@ jvmIsInterrupted(Thread* t, uintptr_t* arguments) jobject thread = reinterpret_cast(arguments[0]); jboolean clear = arguments[1]; - monitorAcquire(t, local::interruptLock(t, *thread)); - bool v = threadInterrupted(t, *thread); - if (clear) { - threadInterrupted(t, *thread) = false; - } - monitorRelease(t, local::interruptLock(t, *thread)); - - return v; + return threadIsInterrupted(t, *thread, clear); } extern "C" JNIEXPORT jboolean JNICALL diff --git a/src/machine.cpp b/src/machine.cpp index c0cdaaf925..a8b2c3cdd8 100644 --- a/src/machine.cpp +++ b/src/machine.cpp @@ -5186,6 +5186,67 @@ populateMultiArray(Thread* t, object array, int32_t* counts, } } +object +interruptLock(Thread* t, object thread) +{ + object lock = threadInterruptLock(t, thread); + + loadMemoryBarrier(); + + if (lock == 0) { + PROTECT(t, thread); + ACQUIRE(t, t->m->referenceLock); + + if (threadInterruptLock(t, thread) == 0) { + object head = makeMonitorNode(t, 0, 0); + object lock = makeMonitor(t, 0, 0, 0, head, head, 0); + + storeStoreMemoryBarrier(); + + set(t, thread, ThreadInterruptLock, lock); + } + } + + return threadInterruptLock(t, thread); +} + +void +clearInterrupted(Thread* t) +{ + monitorAcquire(t, interruptLock(t, t->javaThread)); + threadInterrupted(t, t->javaThread) = false; + monitorRelease(t, interruptLock(t, t->javaThread)); +} + +void +threadInterrupt(Thread* t, object thread) +{ + PROTECT(t, thread); + + monitorAcquire(t, interruptLock(t, thread)); + Thread* p = reinterpret_cast(threadPeer(t, thread)); + if (p) { + interrupt(t, p); + } + threadInterrupted(t, thread) = true; + monitorRelease(t, interruptLock(t, thread)); +} + +bool +threadIsInterrupted(Thread* t, object thread, bool clear) +{ + PROTECT(t, thread); + + monitorAcquire(t, interruptLock(t, thread)); + bool v = threadInterrupted(t, thread); + if (clear) { + threadInterrupted(t, thread) = false; + } + monitorRelease(t, interruptLock(t, thread)); + + return v; +} + void noop() { }