diff --git a/classpath/java-lang.cpp b/classpath/java-lang.cpp index b8c961c4e4..b5da316691 100644 --- a/classpath/java-lang.cpp +++ b/classpath/java-lang.cpp @@ -1,3 +1,6 @@ +#include "sys/time.h" +#include "time.h" +#include "time.h" #include "string.h" #include "jni.h" @@ -19,3 +22,12 @@ Java_java_lang_System_getProperty(JNIEnv* e, jclass, jstring key) return value; } + +extern "C" JNIEXPORT jlong JNICALL +Java_java_lang_System_currentTimeMillis(JNIEnv*, jclass) +{ + timeval tv = { 0, 0 }; + gettimeofday(&tv, 0); + return (static_cast(tv.tv_sec) * 1000) + + (static_cast(tv.tv_usec) / 1000); +} diff --git a/classpath/java/lang/Class.java b/classpath/java/lang/Class.java index 9e5e4c07b9..88cc506ea7 100644 --- a/classpath/java/lang/Class.java +++ b/classpath/java/lang/Class.java @@ -19,7 +19,6 @@ public final class Class { private Field[] fieldTable; private Method[] methodTable; private Object[] staticTable; - private Method initializer; private Class() { } @@ -32,9 +31,11 @@ public final class Class { public native boolean isAssignableFrom(Class c); private Field findField(String name) { - for (int i = 0; i < fieldTable.length; ++i) { - if (fieldTable[i].getName().equals(name)) { - return fieldTable[i]; + if (fieldTable != null) { + for (int i = 0; i < fieldTable.length; ++i) { + if (fieldTable[i].getName().equals(name)) { + return fieldTable[i]; + } } } return null; @@ -73,11 +74,13 @@ public final class Class { } private Method findMethod(String name, Class[] parameterTypes) { - for (int i = 0; i < methodTable.length; ++i) { - if (methodTable[i].getName().equals(name) - && match(parameterTypes, methodTable[i].getParameterTypes())) - { - return methodTable[i]; + if (methodTable != null) { + for (int i = 0; i < methodTable.length; ++i) { + if (methodTable[i].getName().equals(name) + && match(parameterTypes, methodTable[i].getParameterTypes())) + { + return methodTable[i]; + } } } return null; @@ -125,12 +128,14 @@ public final class Class { private int countConstructors(boolean publicOnly) { int count = 0; - for (int i = 0; i < methodTable.length; ++i) { - if (((! publicOnly) - || ((methodTable[i].getModifiers() & Modifier.PUBLIC)) != 0) - && methodTable[i].getName().equals("")) - { - ++ count; + if (methodTable != null) { + for (int i = 0; i < methodTable.length; ++i) { + if (((! publicOnly) + || ((methodTable[i].getModifiers() & Modifier.PUBLIC)) != 0) + && methodTable[i].getName().equals("")) + { + ++ count; + } } } return count; @@ -138,10 +143,12 @@ public final class Class { public Constructor[] getDeclaredConstructors() { Constructor[] array = new Constructor[countConstructors(false)]; - int index = 0; - for (int i = 0; i < methodTable.length; ++i) { - if (methodTable[i].getName().equals("")) { - array[index++] = new Constructor(methodTable[i]); + if (methodTable != null) { + int index = 0; + for (int i = 0; i < methodTable.length; ++i) { + if (methodTable[i].getName().equals("")) { + array[index++] = new Constructor(methodTable[i]); + } } } @@ -150,12 +157,14 @@ public final class Class { public Constructor[] getConstructors() { Constructor[] array = new Constructor[countConstructors(true)]; - int index = 0; - for (int i = 0; i < methodTable.length; ++i) { - if (((methodTable[i].getModifiers() & Modifier.PUBLIC) != 0) - && methodTable[i].getName().equals("")) - { - array[index++] = new Constructor(methodTable[i]); + if (methodTable != null) { + int index = 0; + for (int i = 0; i < methodTable.length; ++i) { + if (((methodTable[i].getModifiers() & Modifier.PUBLIC) != 0) + && methodTable[i].getName().equals("")) + { + array[index++] = new Constructor(methodTable[i]); + } } } @@ -163,16 +172,22 @@ public final class Class { } public Field[] getDeclaredFields() { - Field[] array = new Field[fieldTable.length]; - System.arraycopy(fieldTable, 0, array, 0, fieldTable.length); - return array; + if (fieldTable != null) { + Field[] array = new Field[fieldTable.length]; + System.arraycopy(fieldTable, 0, array, 0, fieldTable.length); + return array; + } else { + return new Field[0]; + } } private int countPublicFields() { int count = 0; - for (int i = 0; i < fieldTable.length; ++i) { - if (((fieldTable[i].getModifiers() & Modifier.PUBLIC)) != 0) { - ++ count; + if (fieldTable != null) { + for (int i = 0; i < fieldTable.length; ++i) { + if (((fieldTable[i].getModifiers() & Modifier.PUBLIC)) != 0) { + ++ count; + } } } return count; @@ -180,9 +195,11 @@ public final class Class { public Field[] getFields() { Field[] array = new Field[countPublicFields()]; - for (int i = 0; i < fieldTable.length; ++i) { - if (((fieldTable[i].getModifiers() & Modifier.PUBLIC)) != 0) { - array[i] = fieldTable[i]; + if (fieldTable != null) { + for (int i = 0; i < fieldTable.length; ++i) { + if (((fieldTable[i].getModifiers() & Modifier.PUBLIC)) != 0) { + array[i] = fieldTable[i]; + } } } return array; @@ -203,10 +220,12 @@ public final class Class { public Method[] getDeclaredMethods() { Method[] array = new Method[countMethods(false)]; - int index = 0; - for (int i = 0; i < methodTable.length; ++i) { - if (! methodTable[i].getName().startsWith("<")) { - array[index++] = methodTable[i]; + if (methodTable != null) { + int index = 0; + for (int i = 0; i < methodTable.length; ++i) { + if (! methodTable[i].getName().startsWith("<")) { + array[index++] = methodTable[i]; + } } } @@ -215,12 +234,14 @@ public final class Class { public Method[] getMethods() { Method[] array = new Method[countMethods(true)]; - int index = 0; - for (int i = 0; i < methodTable.length; ++i) { - if (((methodTable[i].getModifiers() & Modifier.PUBLIC) != 0) - && (! methodTable[i].getName().startsWith("<"))) - { - array[index++] = methodTable[i]; + if (methodTable != null) { + int index = 0; + for (int i = 0; i < methodTable.length; ++i) { + if (((methodTable[i].getModifiers() & Modifier.PUBLIC) != 0) + && (! methodTable[i].getName().startsWith("<"))) + { + array[index++] = methodTable[i]; + } } } @@ -228,11 +249,15 @@ public final class Class { } public Class[] getInterfaces() { - Class[] array = new Class[interfaceTable.length / 2]; - for (int i = 0; i < array.length; ++i) { - array[i] = (Class) interfaceTable[i * 2]; + if (interfaceTable != null) { + Class[] array = new Class[interfaceTable.length / 2]; + for (int i = 0; i < array.length; ++i) { + array[i] = (Class) interfaceTable[i * 2]; + } + return array; + } else { + return new Class[0]; } - return array; } public ClassLoader getClassLoader() { diff --git a/classpath/java/lang/Thread.java b/classpath/java/lang/Thread.java index 5bd884f04e..a19cb51aba 100644 --- a/classpath/java/lang/Thread.java +++ b/classpath/java/lang/Thread.java @@ -6,6 +6,7 @@ import java.util.WeakHashMap; public class Thread implements Runnable { private final Runnable task; private Map locals; + private Object sleepLock; private long peer; public Thread(Runnable task) { @@ -17,7 +18,8 @@ public class Thread implements Runnable { if (map != null) { for (Map.Entry e: map.entrySet()) { if (e.getKey() instanceof InheritableThreadLocal) { - locals().put(e.getKey(), e.getValue()); + InheritableThreadLocal itl = (InheritableThreadLocal) e.getKey(); + locals().put(itl, itl.childValue(e.getValue())); } } } @@ -42,6 +44,13 @@ public class Thread implements Runnable { public static native Thread currentThread(); - public static native void sleep(long milliseconds) - throws InterruptedException; + public static void sleep(long milliseconds) throws InterruptedException { + Thread t = currentThread(); + if (t.sleepLock == null) { + t.sleepLock = new Object(); + } + synchronized (t.sleepLock) { + t.sleepLock.wait(milliseconds); + } + } } diff --git a/makefile b/makefile index c29bec3b08..e7ad338b0a 100644 --- a/makefile +++ b/makefile @@ -16,7 +16,7 @@ src = src classpath = classpath test = test -input = $(cls)/Reflection.class +input = $(cls)/Threads.class cxx = g++ cc = gcc diff --git a/src/builtin.cpp b/src/builtin.cpp index 56366023b6..87a757c747 100644 --- a/src/builtin.cpp +++ b/src/builtin.cpp @@ -73,12 +73,11 @@ Class_forName(Thread* t, jclass, jstring name) return 0; } - object clinit = classInitializer(t, c); - if (clinit) { + if (classVmFlags(t, c) & NeedInitFlag) { PROTECT(t, c); - set(t, classInitializer(t, c), 0); - run(t, clinit, 0); + classVmFlags(t, c) &= ~NeedInitFlag; + run(t, classInitializer(t, c), 0); } return pushReference(t, c); @@ -105,9 +104,36 @@ Field_get(Thread* t, jobject this_, jobject instancep) object field = *this_; if (fieldFlags(t, field) & ACC_STATIC) { - return pushReference - (t, arrayBody(t, classStaticTable(t, fieldClass(t, field)), - fieldOffset(t, field))); + object v = arrayBody(t, classStaticTable(t, fieldClass(t, field)), + fieldOffset(t, field)); + + switch (fieldCode(t, field)) { + case ByteField: + return pushReference(t, makeByte(t, intValue(t, v))); + + case BooleanField: + return pushReference(t, makeBoolean(t, intValue(t, v))); + + case CharField: + return pushReference(t, makeChar(t, intValue(t, v))); + + case ShortField: + return pushReference(t, makeShort(t, intValue(t, v))); + + case FloatField: + return pushReference(t, makeFloat(t, intValue(t, v))); + + case DoubleField: + return pushReference(t, makeDouble(t, longValue(t, v))); + + case IntField: + case LongField: + case ObjectField: + return pushReference(t, v); + + default: + abort(t); + } } else if (instancep) { object instance = *instancep; @@ -169,9 +195,44 @@ Field_set(Thread* t, jobject this_, jobject instancep, jobject value) object v = (value ? *value : 0); if (fieldFlags(t, field) & ACC_STATIC) { + object* p = &arrayBody(t, classStaticTable(t, fieldClass(t, field)), + fieldOffset(t, field)); + if (fieldCode(t, field) == ObjectField or v) { - set(t, arrayBody(t, classStaticTable(t, fieldClass(t, field)), - fieldOffset(t, field)), v); + switch (fieldCode(t, field)) { + case ByteField: + set(t, *p, makeInt(t, byteValue(t, v))); + break; + + case BooleanField: + set(t, *p, makeInt(t, booleanValue(t, v))); + break; + + case CharField: + set(t, *p, makeInt(t, charValue(t, v))); + break; + + case ShortField: + set(t, *p, makeInt(t, shortValue(t, v))); + break; + + case FloatField: + set(t, *p, makeInt(t, floatValue(t, v))); + break; + + case DoubleField: + set(t, *p, makeLong(t, longValue(t, v))); + break; + + case IntField: + case LongField: + case ObjectField: + set(t, *p, v); + break; + + default: + abort(t); + } } else { t->exception = makeNullPointerException(t); } @@ -398,12 +459,6 @@ System_arraycopy(Thread* t, jclass, jobject src, jint srcOffset, jobject dst, t->exception = makeArrayStoreException(t); } -jlong -System_currentTimeMillis(Thread* t, jclass) -{ - return t->vm->system->now(); -} - void Runtime_loadLibrary(Thread* t, jobject, jstring name) { @@ -516,15 +571,6 @@ Thread_currentThread(Thread* t, jclass) return pushReference(t, t->javaThread); } -void -Thread_sleep(Thread* t, jclass, jlong milliseconds) -{ - if (milliseconds == 0) milliseconds = INT64_MAX; - - ENTER(t, Thread::IdleState); - - t->vm->system->sleep(milliseconds); -} void Thread_start(Thread* t, jobject this_) { @@ -589,8 +635,6 @@ populateBuiltinMap(Thread* t, object map) { "Java_java_lang_System_arraycopy", reinterpret_cast(::System_arraycopy) }, - { "Java_java_lang_System_currentTimeMillis", - reinterpret_cast(::System_currentTimeMillis) }, { "Java_java_lang_Runtime_loadLibrary", reinterpret_cast(::Runtime_loadLibrary) }, @@ -603,8 +647,6 @@ populateBuiltinMap(Thread* t, object map) reinterpret_cast(::Thread_start) }, { "Java_java_lang_Thread_currentThread", reinterpret_cast(::Thread_currentThread) }, - { "Java_java_lang_Thread_sleep", - reinterpret_cast(::Thread_sleep) }, { "Java_java_lang_Throwable_resolveTrace", reinterpret_cast(::Throwable_resolveTrace) }, diff --git a/src/machine.cpp b/src/machine.cpp index 99a2ccc040..573e692ea3 100644 --- a/src/machine.cpp +++ b/src/machine.cpp @@ -939,7 +939,7 @@ parseMethodTable(Thread* t, Stream& s, object class_, object pool) if (strcmp(reinterpret_cast(""), &byteArrayBody(t, methodName(t, method), 0)) == 0) { - set(t, classInitializer(t, class_), method); + classVmFlags(t, class_) |= NeedInitFlag; } } else { ++ declaredVirtualCount; @@ -1096,8 +1096,7 @@ parseClass(Thread* t, const uint8_t* data, unsigned size) 0, // vtable 0, // fields 0, // methods - 0, // static table - 0); // initializer + 0); // static table PROTECT(t, class_); unsigned super = s.read2(); @@ -1107,7 +1106,8 @@ parseClass(Thread* t, const uint8_t* data, unsigned size) set(t, classSuper(t, class_), sc); - classVmFlags(t, class_) |= classVmFlags(t, sc); + classVmFlags(t, class_) + |= (classVmFlags(t, sc) & (ReferenceFlag | WeakReferenceFlag)); } parseInterfaceTable(t, s, class_, pool); @@ -1143,6 +1143,7 @@ updateBootstrapClass(Thread* t, object bootstrapClass, object class_) ENTER(t, Thread::ExclusiveState); classFlags(t, bootstrapClass) = classFlags(t, class_); + classVmFlags(t, bootstrapClass) |= classVmFlags(t, class_); set(t, classSuper(t, bootstrapClass), classSuper(t, class_)); set(t, classInterfaceTable(t, bootstrapClass), @@ -1151,7 +1152,6 @@ updateBootstrapClass(Thread* t, object bootstrapClass, object class_) set(t, classFieldTable(t, bootstrapClass), classFieldTable(t, class_)); set(t, classMethodTable(t, bootstrapClass), classMethodTable(t, class_)); set(t, classStaticTable(t, bootstrapClass), classStaticTable(t, class_)); - set(t, classInitializer(t, bootstrapClass), classInitializer(t, class_)); object fieldTable = classFieldTable(t, class_); if (fieldTable) { @@ -1186,7 +1186,6 @@ makeArrayClass(Thread* t, unsigned dimensions, object spec, classVirtualTable(t, arrayBody(t, t->vm->types, Machine::JobjectType)), 0, 0, - 0, 0); } @@ -1376,7 +1375,7 @@ Thread::Thread(Machine* m, object javaThread, Thread* parent): populateBuiltinMap(t, m->builtinMap); - t->javaThread = makeThread(t, 0, 0, reinterpret_cast(t)); + t->javaThread = makeThread(t, 0, 0, 0, reinterpret_cast(t)); } else { threadPeer(this, javaThread) = reinterpret_cast(this); parent->child = this; @@ -1680,6 +1679,21 @@ instanceOf(Thread* t, object class_, object o) } } +object +classInitializer(Thread* t, object class_) +{ + for (unsigned i = 0; i < arrayLength(t, classMethodTable(t, class_)); ++i) { + object o = arrayBody(t, classMethodTable(t, class_), i); + + if (strcmp(reinterpret_cast(""), + &byteArrayBody(t, methodName(t, o), 0)) == 0) + { + return o; + } + } + abort(t); +} + unsigned parameterFootprint(const char* s) { diff --git a/src/machine.h b/src/machine.h index 903efe8fa3..015097c913 100644 --- a/src/machine.h +++ b/src/machine.h @@ -22,7 +22,7 @@ namespace vm { const bool Verbose = false; const bool DebugRun = false; const bool DebugStack = false; -const bool DebugMonitors = false; +const bool DebugMonitors = true; const uintptr_t HashTakenMark = 1; const uintptr_t ExtendedMark = 2; @@ -61,6 +61,7 @@ const int UnknownLine = -2; const unsigned ReferenceFlag = 1 << 0; const unsigned WeakReferenceFlag = 1 << 1; +const unsigned NeedInitFlag = 1 << 2; class Thread; @@ -1487,6 +1488,9 @@ isAssignableFrom(Thread* t, object a, object b); bool instanceOf(Thread* t, object class_, object o); +object +classInitializer(Thread* t, object class_); + inline void pushObject(Thread* t, object o) { diff --git a/src/run.cpp b/src/run.cpp index 4409382745..df18a9b9d1 100644 --- a/src/run.cpp +++ b/src/run.cpp @@ -76,13 +76,6 @@ popFrame(Thread* t) } } -inline void -setStatic(Thread* t, object field, object value) -{ - set(t, arrayBody(t, classStaticTable(t, fieldClass(t, field)), - fieldOffset(t, field)), value); -} - object findInterfaceMethod(Thread* t, object method, object o) { @@ -908,10 +901,9 @@ run(Thread* t) object field = resolveField(t, codePool(t, code), index - 1); if (UNLIKELY(exception)) goto throw_; - object clinit = classInitializer(t, fieldClass(t, field)); - if (clinit) { - set(t, classInitializer(t, fieldClass(t, field)), 0); - code = clinit; + if (classVmFlags(t, fieldClass(t, field)) & NeedInitFlag) { + classVmFlags(t, fieldClass(t, field)) &= ~NeedInitFlag; + code = classInitializer(t, fieldClass(t, field)); ip -= 3; goto invoke; } @@ -1332,13 +1324,12 @@ run(Thread* t) resolveClass(t, className(t, class_)); if (UNLIKELY(exception)) goto throw_; - object clinit = classInitializer(t, class_); - if (clinit) { - set(t, classInitializer(t, methodClass(t, method)), 0); - code = clinit; + if (classVmFlags(t, class_) & NeedInitFlag) { + classVmFlags(t, class_) &= ~NeedInitFlag; + code = classInitializer(t, class_); ip -= 3; goto invoke; - } + } } code = findMethod(t, method, class_); @@ -1361,10 +1352,9 @@ run(Thread* t) object method = resolveMethod(t, codePool(t, code), index - 1); if (UNLIKELY(exception)) goto throw_; - object clinit = classInitializer(t, methodClass(t, method)); - if (clinit) { - set(t, classInitializer(t, methodClass(t, method)), 0); - code = clinit; + if (classVmFlags(t, methodClass(t, method)) & NeedInitFlag) { + classVmFlags(t, methodClass(t, method)) &= ~NeedInitFlag; + code = classInitializer(t, methodClass(t, method)); ip -= 3; goto invoke; } @@ -1390,13 +1380,12 @@ run(Thread* t) resolveClass(t, className(t, class_)); if (UNLIKELY(exception)) goto throw_; - object clinit = classInitializer(t, class_); - if (clinit) { - set(t, classInitializer(t, methodClass(t, method)), 0); - code = clinit; + if (classVmFlags(t, class_) & NeedInitFlag) { + classVmFlags(t, class_) &= ~NeedInitFlag; + code = classInitializer(t, class_); ip -= 3; goto invoke; - } + } } code = findMethod(t, method, class_); @@ -1774,10 +1763,9 @@ run(Thread* t) object class_ = resolveClass(t, codePool(t, code), index - 1); if (UNLIKELY(exception)) goto throw_; - object clinit = classInitializer(t, class_); - if (clinit) { - set(t, classInitializer(t, class_), 0); - code = clinit; + if (classVmFlags(t, class_) & NeedInitFlag) { + classVmFlags(t, class_) &= ~NeedInitFlag; + code = classInitializer(t, class_); ip -= 3; goto invoke; } @@ -1922,10 +1910,9 @@ run(Thread* t) object field = resolveField(t, codePool(t, code), index - 1); if (UNLIKELY(exception)) goto throw_; - object clinit = classInitializer(t, fieldClass(t, field)); - if (clinit) { - set(t, classInitializer(t, fieldClass(t, field)), 0); - code = clinit; + if (classVmFlags(t, fieldClass(t, field)) & NeedInitFlag) { + classVmFlags(t, fieldClass(t, field)) &= ~NeedInitFlag; + code = classInitializer(t, fieldClass(t, field)); ip -= 3; goto invoke; } diff --git a/src/system.cpp b/src/system.cpp index 83ecb0fb6c..9353515c9d 100644 --- a/src/system.cpp +++ b/src/system.cpp @@ -86,6 +86,15 @@ using namespace vm; namespace { +int64_t +now() +{ + timeval tv = { 0, 0 }; + gettimeofday(&tv, 0); + return (static_cast(tv.tv_sec) * 1000) + + (static_cast(tv.tv_usec) / 1000); +} + void* run(void* t) { @@ -174,10 +183,10 @@ class MySystem: public System { this->depth = 0; this->context = 0; if (time) { - int64_t then = s->now() + time; + int64_t then = now() + time; timespec ts = { then / 1000, (then % 1000) * 1000 * 1000 }; int rv = pthread_cond_timedwait(&condition, &mutex, &ts); - assert(s, rv == 0); + assert(s, rv == 0 or rv == ETIMEDOUT); } else { int rv = pthread_cond_wait(&condition, &mutex); assert(s, rv == 0); @@ -342,19 +351,6 @@ class MySystem: public System { return 0; } - virtual void sleep(int64_t milliseconds) { - timespec ts = { milliseconds / 1000, (milliseconds % 1000) * 1000 * 1000 }; - - nanosleep(&ts, 0); - } - - virtual int64_t now() { - timeval tv = { 0, 0 }; - gettimeofday(&tv, 0); - return (static_cast(tv.tv_sec) * 1000) + - (static_cast(tv.tv_usec) / 1000); - } - virtual uint64_t call(void* function, uintptr_t* arguments, uint8_t* types, unsigned count, unsigned size, unsigned returnType) { diff --git a/src/system.h b/src/system.h index 5ccdb99f8e..fcb6956565 100644 --- a/src/system.h +++ b/src/system.h @@ -60,8 +60,6 @@ class System: public Allocator { virtual Status attach(Thread**) = 0; virtual Status start(Runnable*) = 0; virtual Status make(Monitor**) = 0; - virtual void sleep(int64_t milliseconds) = 0; - virtual int64_t now() = 0; virtual uint64_t call(void* function, uintptr_t* arguments, uint8_t* types, unsigned count, unsigned size, unsigned returnType) = 0; diff --git a/src/type-generator.cpp b/src/type-generator.cpp index d9e5bdb432..835af84794 100644 --- a/src/type-generator.cpp +++ b/src/type-generator.cpp @@ -1488,7 +1488,7 @@ writeInitialization(Output* out, Object* type) out->write(typeFixedSize(type)); out->write(", "); out->write(typeArrayElementSize(type)); - out->write(", mask, 0, super, 0, 0, 0, 0, 0, 0);\n"); + out->write(", mask, 0, super, 0, 0, 0, 0, 0);\n"); out->write(" set(t, arrayBody(t, t->vm->types, Machine::"); out->write(capitalize(typeName(type))); diff --git a/src/types.def b/src/types.def index 155eb4c704..27aed3796a 100644 --- a/src/types.def +++ b/src/types.def @@ -14,8 +14,7 @@ (object virtualTable) (object fieldTable) (object methodTable) - (object staticTable) - (object initializer)) + (object staticTable)) (type accessibleObject java/lang/reflect/AccessibleObject (extends jobject)) @@ -128,6 +127,7 @@ (extends jobject) (object task) (object locals) + (object sleepLock) (int64_t peer)) (type stackTraceElement java/lang/StackTraceElement