diff --git a/classpath/java/lang/Class.java b/classpath/java/lang/Class.java index 1142285aae..6516e5a538 100644 --- a/classpath/java/lang/Class.java +++ b/classpath/java/lang/Class.java @@ -6,10 +6,6 @@ import java.lang.reflect.Field; import java.lang.reflect.Modifier; public final class Class { - private static final int ReferenceFlag = 1 << 0; - private static final int WeakReferenceFlag = 1 << 1; - private static final int NeedInitFlag = 1 << 2; - private short flags; private byte vmFlags; private byte arrayDimensions; @@ -41,17 +37,15 @@ public final class Class { throws ClassNotFoundException { Class c = loader.loadClass(name); - if (initialize && ((c.flags & NeedInitFlag) != 0)) { - c.flags &= ~NeedInitFlag; - Method m = c.findMethod("", new Class[0]); - if (m != null) { - m.invoke(null); - } + if (initialize) { + c.initialize(); } return c; } private static native Class primitiveClass(char name); + + private native void initialize(); static Class forCanonicalName(String name) { try { diff --git a/classpath/java/net/URL.java b/classpath/java/net/URL.java index 70b1c1f68a..65034444bc 100644 --- a/classpath/java/net/URL.java +++ b/classpath/java/net/URL.java @@ -1,9 +1,19 @@ package java.net; -public class URL { - private final String value; +public final class URL { +// private final String protocol; +// private final String host; +// private final int port; +// private final String file; public URL(String s) throws MalformedURLException { - value = s; +// int colon = s.indexOf(':'); +// int slash = s.indexOf('/'); +// if (colon > 0 && (slash < 0 || colon < slash)) { +// protocol = s.substring(0, colon); +// // todo +// } else { +// throw new MalformedURLException(s); +// } } } diff --git a/makefile b/makefile index e7ad338b0a..c29bec3b08 100644 --- a/makefile +++ b/makefile @@ -16,7 +16,7 @@ src = src classpath = classpath test = test -input = $(cls)/Threads.class +input = $(cls)/Reflection.class cxx = g++ cc = gcc diff --git a/src/builtin.cpp b/src/builtin.cpp index 98f6ab9797..6bcae24db3 100644 --- a/src/builtin.cpp +++ b/src/builtin.cpp @@ -131,6 +131,21 @@ Class_primitiveClass(Thread* t, jclass, jchar name) } } +void +Class_initialize(Thread* t, jobject this_) +{ + acquire(t, t->vm->classLock); + object c = *this_; + if (classVmFlags(t, c) & NeedInitFlag + and (classVmFlags(t, c) & InitFlag) == 0) + { + classVmFlags(t, c) |= InitFlag; + run(t, classInitializer(t, c), 0); + } else { + release(t, t->vm->classLock); + } +} + jboolean Class_isAssignableFrom(Thread* t, jobject this_, jclass that) { @@ -665,6 +680,8 @@ populateBuiltinMap(Thread* t, object map) reinterpret_cast(::Class_isAssignableFrom) }, { "Java_java_lang_Class_primitiveClass", reinterpret_cast(::Class_primitiveClass) }, + { "Java_java_lang_Class_initialize", + reinterpret_cast(::Class_initialize) }, { "Java_java_lang_ClassLoader_defineClass", reinterpret_cast(::ClassLoader_defineClass) }, diff --git a/src/machine.cpp b/src/machine.cpp index 7aba445fa2..91fb68bfaa 100644 --- a/src/machine.cpp +++ b/src/machine.cpp @@ -3,6 +3,7 @@ #include "machine.h" #include "stream.h" #include "constants.h" +#include "run.h" using namespace vm; @@ -948,6 +949,7 @@ parseMethodTable(Thread* t, Stream& s, object class_, object pool) if (strcmp(reinterpret_cast(""), &byteArrayBody(t, methodName(t, method), 0)) == 0) { + methodVmFlags(t, method) |= ClassInitFlag; classVmFlags(t, class_) |= NeedInitFlag; } } else { diff --git a/src/machine.h b/src/machine.h index e5c8f642e3..6a2da91c10 100644 --- a/src/machine.h +++ b/src/machine.h @@ -55,9 +55,14 @@ enum StackTag { const int NativeLine = -1; const int UnknownLine = -2; +// class flags: const unsigned ReferenceFlag = 1 << 0; const unsigned WeakReferenceFlag = 1 << 1; const unsigned NeedInitFlag = 1 << 2; +const unsigned InitFlag = 1 << 3; + +// method flags: +const unsigned ClassInitFlag = 1 << 0; class Thread; @@ -1280,18 +1285,32 @@ stress(Thread*) #endif // not VM_STRESS +inline void +acquire(Thread* t, System::Monitor* m) +{ + if (not m->tryAcquire(t->systemThread)) { + ENTER(t, Thread::IdleState); + m->acquire(t->systemThread); + } + + stress(t); +} + +inline void +release(Thread* t, System::Monitor* m) +{ + m->release(t->systemThread); +} + class MonitorResource { public: MonitorResource(Thread* t, System::Monitor* m): t(t), m(m) { - stress(t); - - if (not m->tryAcquire(t->systemThread)) { - ENTER(t, Thread::IdleState); - m->acquire(t->systemThread); - } + acquire(t, m); } - ~MonitorResource() { m->release(t->systemThread); } + ~MonitorResource() { + release(t, m); + } private: Thread* t; @@ -1301,10 +1320,12 @@ class MonitorResource { class RawMonitorResource { public: RawMonitorResource(Thread* t, System::Monitor* m): t(t), m(m) { - m->acquire(t->systemThread); + acquire(t, m); } - ~RawMonitorResource() { m->release(t->systemThread); } + ~RawMonitorResource() { + release(t, m); + } private: Thread* t; @@ -1513,6 +1534,14 @@ makeUnsatisfiedLinkError(Thread* t, object message) return makeUnsatisfiedLinkError(t, message, trace, 0); } +inline object +makeExceptionInInitializerError(Thread* t, object cause) +{ + PROTECT(t, cause); + object trace = makeTrace(t); + return makeExceptionInInitializerError(t, 0, trace, cause); +} + object make(Thread* t, object class_); @@ -2095,12 +2124,7 @@ acquire(Thread* t, object o) t, m, objectHash(t, o)); } - if (not m->tryAcquire(t->systemThread)) { - ENTER(t, Thread::IdleState); - m->acquire(t->systemThread); - } - - stress(t); + acquire(t, m); } inline void @@ -2113,7 +2137,7 @@ release(Thread* t, object o) t, m, objectHash(t, o)); } - m->release(t->systemThread); + release(t, m); } inline void diff --git a/src/run.cpp b/src/run.cpp index 91b2775435..33d563de15 100644 --- a/src/run.cpp +++ b/src/run.cpp @@ -64,6 +64,14 @@ popFrame(Thread* t) release(t, peekObject(t, frameBase(t, t->frame))); } } + + if (UNLIKELY(methodVmFlags(t, method) & ClassInitFlag)) { + if (t->exception) { + t->exception = makeExceptionInInitializerError(t, t->exception); + } + classVmFlags(t, methodClass(t, method)) &= ~(NeedInitFlag | InitFlag); + release(t, t->vm->classLock); + } t->sp = frameBase(t, t->frame); t->frame = frameNext(t, t->frame); @@ -495,6 +503,34 @@ invokeNative(Thread* t, object method) return returnCode; } +bool +classInit2(Thread* t, object class_, unsigned ipOffset) +{ + PROTECT(t, class_); + acquire(t, t->vm->classLock); + if (classVmFlags(t, class_) & NeedInitFlag + and (classVmFlags(t, class_) & InitFlag) == 0) + { + classVmFlags(t, class_) |= InitFlag; + t->code = classInitializer(t, class_); + t->ip -= ipOffset; + return true; + } else { + release(t, t->vm->classLock); + return false; + } +} + +inline bool +classInit(Thread* t, object class_, unsigned ipOffset) +{ + if (UNLIKELY(classVmFlags(t, class_) & NeedInitFlag)) { + return classInit2(t, class_, ipOffset); + } else { + return false; + } +} + object run(Thread* t) { @@ -508,7 +544,13 @@ run(Thread* t) object& exception = t->exception; uintptr_t* stack = t->stack; - if (UNLIKELY(exception)) goto throw_; + if (UNLIKELY(exception)) { + goto throw_; + } + + if (UNLIKELY(classInit(t, methodClass(t, frameMethod(t, frame)), 0))) { + goto invoke; + } loop: instruction = codeBody(t, code, ip++); @@ -901,12 +943,7 @@ run(Thread* t) object field = resolveField(t, codePool(t, code), index - 1); if (UNLIKELY(exception)) goto throw_; - if (classVmFlags(t, fieldClass(t, field)) & NeedInitFlag) { - classVmFlags(t, fieldClass(t, field)) &= ~NeedInitFlag; - code = classInitializer(t, fieldClass(t, field)); - ip -= 3; - goto invoke; - } + if (UNLIKELY(classInit(t, fieldClass(t, field), 3))) goto invoke; object v = arrayBody(t, classStaticTable(t, fieldClass(t, field)), fieldOffset(t, field)); @@ -1324,12 +1361,7 @@ run(Thread* t) resolveClass(t, className(t, class_)); if (UNLIKELY(exception)) goto throw_; - if (classVmFlags(t, class_) & NeedInitFlag) { - classVmFlags(t, class_) &= ~NeedInitFlag; - code = classInitializer(t, class_); - ip -= 3; - goto invoke; - } + if (UNLIKELY(classInit(t, class_, 3))) goto invoke; } code = findMethod(t, method, class_); @@ -1352,12 +1384,7 @@ run(Thread* t) object method = resolveMethod(t, codePool(t, code), index - 1); if (UNLIKELY(exception)) goto throw_; - if (classVmFlags(t, methodClass(t, method)) & NeedInitFlag) { - classVmFlags(t, methodClass(t, method)) &= ~NeedInitFlag; - code = classInitializer(t, methodClass(t, method)); - ip -= 3; - goto invoke; - } + if (UNLIKELY(classInit(t, methodClass(t, method), 3))) goto invoke; code = method; } goto invoke; @@ -1380,12 +1407,7 @@ run(Thread* t) resolveClass(t, className(t, class_)); if (UNLIKELY(exception)) goto throw_; - if (classVmFlags(t, class_) & NeedInitFlag) { - classVmFlags(t, class_) &= ~NeedInitFlag; - code = classInitializer(t, class_); - ip -= 3; - goto invoke; - } + if (UNLIKELY(classInit(t, class_, 3))) goto invoke; } code = findMethod(t, method, class_); @@ -1763,12 +1785,7 @@ run(Thread* t) object class_ = resolveClass(t, codePool(t, code), index - 1); if (UNLIKELY(exception)) goto throw_; - if (classVmFlags(t, class_) & NeedInitFlag) { - classVmFlags(t, class_) &= ~NeedInitFlag; - code = classInitializer(t, class_); - ip -= 3; - goto invoke; - } + if (UNLIKELY(classInit(t, class_, 3))) goto invoke; pushObject(t, make(t, class_)); } goto loop; @@ -1910,12 +1927,7 @@ run(Thread* t) object field = resolveField(t, codePool(t, code), index - 1); if (UNLIKELY(exception)) goto throw_; - if (classVmFlags(t, fieldClass(t, field)) & NeedInitFlag) { - classVmFlags(t, fieldClass(t, field)) &= ~NeedInitFlag; - code = classInitializer(t, fieldClass(t, field)); - ip -= 3; - goto invoke; - } + if (UNLIKELY(classInit(t, fieldClass(t, field), 3))) goto invoke; PROTECT(t, field); diff --git a/src/types.def b/src/types.def index ebc3b48309..1f0619bfe5 100644 --- a/src/types.def +++ b/src/types.def @@ -214,6 +214,9 @@ (type unsatisfiedLinkError java/lang/UnsatisfiedLinkError (extends linkageError)) +(type exceptionInInitializerError java/lang/ExceptionInInitializerError + (extends error)) + (type number java/lang/Number (extends jobject))