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.
This commit is contained in:
Joel Dice 2013-04-23 13:47:15 -06:00
parent dfdd1f6e6c
commit 4e12847858
9 changed files with 283 additions and 188 deletions

View File

@ -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

View File

@ -366,54 +366,12 @@ public final class Class <T> 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 <T> 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) {

View File

@ -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);
}

View File

@ -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)
{

View File

@ -604,6 +604,46 @@ Avian_java_nio_FixedArrayByteBuffer_allocateFixed
return reinterpret_cast<intptr_t>(array);
}
extern "C" JNIEXPORT int64_t JNICALL
Avian_sun_misc_Unsafe_getObject
(Thread*, object, uintptr_t* arguments)
{
object o = reinterpret_cast<object>(arguments[1]);
int64_t offset; memcpy(&offset, arguments + 2, 8);
return fieldAtOffset<uintptr_t>(o, offset);
}
extern "C" JNIEXPORT void JNICALL
Avian_sun_misc_Unsafe_putObject
(Thread* t, object, uintptr_t* arguments)
{
object o = reinterpret_cast<object>(arguments[1]);
int64_t offset; memcpy(&offset, arguments + 2, 8);
uintptr_t value = arguments[4];
set(t, o, offset, reinterpret_cast<object>(value));
}
extern "C" JNIEXPORT int64_t JNICALL
Avian_sun_misc_Unsafe_compareAndSwapObject
(Thread* t, object, uintptr_t* arguments)
{
object target = reinterpret_cast<object>(arguments[1]);
int64_t offset; memcpy(&offset, arguments + 2, 8);
uintptr_t expect = arguments[4];
uintptr_t update = arguments[5];
bool success = atomicCompareAndSwap
(&fieldAtOffset<uintptr_t>(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<uint32_t>(target, offset), expect, update);
}
extern "C" JNIEXPORT void JNICALL
Avian_sun_misc_Unsafe_unpark
(Thread* t, object, uintptr_t* arguments)
{
object thread = reinterpret_cast<object>(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<object>(arguments[1]);
int64_t offset; memcpy(&offset, arguments + 2, 8);
int32_t value = arguments[4];
storeStoreMemoryBarrier();
fieldAtOffset<int32_t>(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)

View File

@ -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<object>(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<uintptr_t>
(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)

View File

@ -661,7 +661,7 @@ Avian_java_lang_Thread_interrupt
{
int64_t peer; memcpy(&peer, arguments, 8);
interrupt(t, reinterpret_cast<Thread*>(peer));
threadInterrupt(t, reinterpret_cast<Thread*>(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<Thread*>(peer));
return threadIsInterrupted
(t, reinterpret_cast<Thread*>(peer)->javaThread, true);
}
extern "C" JNIEXPORT int64_t JNICALL

View File

@ -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<object>(arguments[1]);
int64_t offset; memcpy(&offset, arguments + 2, 8);
return fieldAtOffset<uintptr_t>(o, offset);
}
extern "C" JNIEXPORT void JNICALL
Avian_sun_misc_Unsafe_putObject
(Thread* t, object, uintptr_t* arguments)
{
object o = reinterpret_cast<object>(arguments[1]);
int64_t offset; memcpy(&offset, arguments + 2, 8);
uintptr_t value = arguments[4];
set(t, o, offset, reinterpret_cast<object>(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<object>(arguments[1]);
int64_t offset; memcpy(&offset, arguments + 2, 8);
uintptr_t expect = arguments[4];
uintptr_t update = arguments[5];
bool success = atomicCompareAndSwap
(&fieldAtOffset<uintptr_t>(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<object>(arguments[1])));
}
extern "C" JNIEXPORT void JNICALL
Avian_sun_misc_Unsafe_unpark
(Thread* t, object, uintptr_t* arguments)
{
object thread = reinterpret_cast<object>(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<jobject>(arguments[0]);
monitorAcquire(t, local::interruptLock(t, *thread));
Thread* p = reinterpret_cast<Thread*>(threadPeer(t, *thread));
if (p) {
interrupt(t, p);
}
threadInterrupted(t, *thread) = true;
monitorRelease(t, local::interruptLock(t, *thread));
threadInterrupt(t, *reinterpret_cast<jobject>(arguments[0]));
return 1;
}
@ -3662,14 +3531,7 @@ jvmIsInterrupted(Thread* t, uintptr_t* arguments)
jobject thread = reinterpret_cast<jobject>(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

View File

@ -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<Thread*>(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()
{ }