diff --git a/classpath/TestThreads.java b/classpath/TestThreads.java index 544d835291..025f944790 100644 --- a/classpath/TestThreads.java +++ b/classpath/TestThreads.java @@ -22,7 +22,7 @@ public class TestThreads implements Runnable { try { System.out.println("I'm running in a seperate thread!"); - final int arrayCount = 64; + final int arrayCount = 8; final int arraySize = 4; System.out.println("Allocating and discarding " + arrayCount + " arrays of " + arraySize + "MB each"); diff --git a/classpath/java/lang/ArrayIndexOutOfBoundsException.java b/classpath/java/lang/ArrayIndexOutOfBoundsException.java new file mode 100644 index 0000000000..2807999837 --- /dev/null +++ b/classpath/java/lang/ArrayIndexOutOfBoundsException.java @@ -0,0 +1,19 @@ +package java.lang; + +public class ArrayIndexOutOfBoundsException extends RuntimeException { + public ArrayIndexOutOfBoundsException(String message, Throwable cause) { + super(message, cause); + } + + public ArrayIndexOutOfBoundsException(String message) { + this(message, null); + } + + public ArrayIndexOutOfBoundsException(Throwable cause) { + this(null, cause); + } + + public ArrayIndexOutOfBoundsException() { + this(null, null); + } +} diff --git a/classpath/java/lang/Object.java b/classpath/java/lang/Object.java index 3879e8d39b..fc38ca11c2 100644 --- a/classpath/java/lang/Object.java +++ b/classpath/java/lang/Object.java @@ -19,9 +19,9 @@ public class Object { public native String toString(); - public native final void wait(); + public final void wait() { + wait(0); + } public native final void wait(long timeout); - - public native final void wait(long timeout, int nanos); } diff --git a/classpath/java/lang/String.java b/classpath/java/lang/String.java index 922951dc81..fcebbb5303 100644 --- a/classpath/java/lang/String.java +++ b/classpath/java/lang/String.java @@ -6,6 +6,20 @@ public final class String { private int length; private int hash; + public String(char[] data, int offset, int length, boolean copy) { + if (copy) { + char[] c = new char[length]; + System.arraycopy(data, offset, c, 0, length); + + this.data = c; + this.length = length; + } else { + this.data = data; + this.offset = offset; + this.length = length; + } + } + public int length() { return length; } @@ -14,8 +28,23 @@ public final class String { return valueOf((long) v); } - public native void getChars(int offset, int length, - char[] dst, int dstLength); + public void getChars(int srcOffset, int srcLength, + char[] dst, int dstOffset) + { + if (srcOffset + srcLength > length) { + throw new ArrayIndexOutOfBoundsException(); + } + + if (data instanceof char[]) { + char[] src = (char[]) data; + System.arraycopy(src, offset + srcOffset, dst, dstOffset, srcLength); + } else { + byte[] src = (byte[]) data; + for (int i = 0; i < srcLength; ++i) { + dst[i + dstOffset] = (char) src[i + offset + srcOffset]; + } + } + } public static String valueOf(long v) { if (v == 0) { @@ -35,7 +64,7 @@ public final class String { array[--index] = '-'; } - return vm.Strings.wrap(array, index, Max - index); + return new String(array, index, Max - index, false); } } } diff --git a/classpath/java/lang/StringBuilder.java b/classpath/java/lang/StringBuilder.java index 0eda361183..f9b2260370 100644 --- a/classpath/java/lang/StringBuilder.java +++ b/classpath/java/lang/StringBuilder.java @@ -27,7 +27,7 @@ public class StringBuilder { index -= c.value.length(); c.value.getChars(0, c.value.length(), array, index); } - return vm.Strings.wrap(array, 0, array.length); + return new String(array, 0, array.length, false); } private static class Cell { diff --git a/classpath/java/lang/System.cpp b/classpath/java/lang/System.cpp index 6e8e5beabc..5c96c81a6e 100644 --- a/classpath/java/lang/System.cpp +++ b/classpath/java/lang/System.cpp @@ -1,16 +1,34 @@ #include "stdio.h" +#include "string.h" #include "jni.h" #undef JNIEXPORT #define JNIEXPORT __attribute__ ((visibility("default"))) extern "C" JNIEXPORT void JNICALL -Java_java_lang_System_00024Output_println(JNIEnv* e, jobject, jstring s) +Java_java_lang_System_00024Output_print(JNIEnv* e, jobject, jstring s) { jboolean isCopy; const char* chars = e->GetStringUTFChars(s, &isCopy); if (chars) { - printf("%s\n", chars); + printf("%s", chars); } e->ReleaseStringUTFChars(s, chars); } + +extern "C" JNIEXPORT jstring JNICALL +Java_java_lang_System_getProperty(JNIEnv* e, jstring key) +{ + jstring value = 0; + + jboolean isCopy; + const char* chars = e->GetStringUTFChars(key, &isCopy); + if (chars) { + if (strcmp(chars, "line.separator") == 0) { + value = e->NewStringUTF("\n"); + } + } + e->ReleaseStringUTFChars(key, chars); + + return value; +} diff --git a/classpath/java/lang/System.java b/classpath/java/lang/System.java index 1c04f0a319..30f4de747c 100644 --- a/classpath/java/lang/System.java +++ b/classpath/java/lang/System.java @@ -8,14 +8,17 @@ public abstract class System { loadLibrary("natives"); } + public static native void arraycopy(Object src, int srcOffset, Object dst, + int dstOffset, int length); + public static native void loadLibrary(String name); public static native String getProperty(String name); public static class Output { - public native void print(String s); + public synchronized native void print(String s); - public void println(String s) { + public synchronized void println(String s) { print(s); print(getProperty("line.separator")); } diff --git a/classpath/vm/Strings.java b/classpath/vm/Strings.java deleted file mode 100644 index fe4c4b3de6..0000000000 --- a/classpath/vm/Strings.java +++ /dev/null @@ -1,5 +0,0 @@ -package vm; - -public abstract class Strings { - public static native String wrap(char[] array, int offset, int length); -} diff --git a/src/builtin.cpp b/src/builtin.cpp index 1ed875b6e4..51d627f7d6 100644 --- a/src/builtin.cpp +++ b/src/builtin.cpp @@ -5,6 +5,35 @@ namespace vm { namespace builtin { +jstring +toString(Thread* t, jobject this_) +{ + object s = makeString + (t, "%s@%p", + &byteArrayBody(t, className(t, objectClass(t, *this_)), 0), + *this_); + + return pushReference(t, s); +} + +void +wait(Thread* t, jobject this_, jlong milliseconds) +{ + vm::wait(t, *this_, milliseconds); +} + +void +notify(Thread* t, jobject this_) +{ + vm::notify(t, *this_); +} + +void +notifyAll(Thread* t, jobject this_) +{ + vm::notifyAll(t, *this_); +} + void loadLibrary(Thread* t, jstring nameString) { @@ -30,15 +59,53 @@ loadLibrary(Thread* t, jstring nameString) } } -jstring -toString(Thread* t, jobject this_) +void +arraycopy(Thread* t, jobject src, jint srcOffset, jobject dst, jint dstOffset, + jint length) { - object s = makeString - (t, "%s@%p", - &byteArrayBody(t, className(t, objectClass(t, *this_)), 0), - *this_); + if (LIKELY(src and dst)) { + object s = *src; + object d = *dst; - return pushReference(t, s); + if (LIKELY(objectClass(t, s) == objectClass(t, d))) { + unsigned elementSize = classArrayElementSize(t, objectClass(t, s)); + + if (LIKELY(elementSize)) { + unsigned offset = 0; + + if (objectClass(t, s) + == arrayBody(t, t->vm->types, Machine::ObjectArrayType)) + { + if (LIKELY(objectArrayElementClass(t, s) + == objectArrayElementClass(t, d))) + { + offset = 1; + } else { + t->exception = makeArrayStoreException(t); + return; + } + } + + int32_t sl = cast(s, offset * BytesPerWord); + int32_t dl = cast(d, offset * BytesPerWord); + if (LIKELY(srcOffset >= 0 and srcOffset + length <= sl and + dstOffset >= 0 and dstOffset + length < dl)) + { + uint8_t* sbody = &cast(s, (offset * BytesPerWord) + 4); + uint8_t* dbody = &cast(s, (offset * BytesPerWord) + 4); + memcpy(sbody + (srcOffset * elementSize), + dbody + (dstOffset * elementSize), + length * elementSize); + return; + } + } + } + } else { + t->exception = makeNullPointerException(t); + return; + } + + t->exception = makeArrayStoreException(t); } jarray @@ -100,7 +167,6 @@ start(Thread* t, jobject this_) } } } - void populate(Thread* t, object map) { @@ -110,8 +176,16 @@ populate(Thread* t, object map) } builtins[] = { { "Java_java_lang_Object_toString", reinterpret_cast(toString) }, + { "Java_java_lang_Object_wait", + reinterpret_cast(wait) }, + { "Java_java_lang_Object_notify", + reinterpret_cast(notify) }, + { "Java_java_lang_Object_notifyAll", + reinterpret_cast(notifyAll) }, { "Java_java_lang_System_loadLibrary", reinterpret_cast(loadLibrary) }, + { "Java_java_lang_System_arraycopy", + reinterpret_cast(arraycopy) }, { "Java_java_lang_Throwable_trace", reinterpret_cast(trace) }, { "Java_java_lang_Thread_start", diff --git a/src/constants.h b/src/constants.h index 91ab9855d1..799b931547 100644 --- a/src/constants.h +++ b/src/constants.h @@ -235,18 +235,19 @@ enum Constant { CONSTANT_Utf8 = 1 }; -const unsigned ACC_PUBLIC = 1 << 0; -const unsigned ACC_PRIVATE = 1 << 1; -const unsigned ACC_PROTECTED = 1 << 2; -const unsigned ACC_STATIC = 1 << 3; -const unsigned ACC_FINAL = 1 << 4; -const unsigned ACC_SUPER = 1 << 5; -const unsigned ACC_VOLATILE = 1 << 6; -const unsigned ACC_TRANSIENT = 1 << 7; -const unsigned ACC_NATIVE = 1 << 8; -const unsigned ACC_INTERFACE = 1 << 9; -const unsigned ACC_ABSTRACT = 1 << 10; -const unsigned ACC_STRICT = 1 << 11; +const unsigned ACC_PUBLIC = 1 << 0; +const unsigned ACC_PRIVATE = 1 << 1; +const unsigned ACC_PROTECTED = 1 << 2; +const unsigned ACC_STATIC = 1 << 3; +const unsigned ACC_FINAL = 1 << 4; +const unsigned ACC_SUPER = 1 << 5; +const unsigned ACC_SYNCHRONIZED = ACC_SUPER; +const unsigned ACC_VOLATILE = 1 << 6; +const unsigned ACC_TRANSIENT = 1 << 7; +const unsigned ACC_NATIVE = 1 << 8; +const unsigned ACC_INTERFACE = 1 << 9; +const unsigned ACC_ABSTRACT = 1 << 10; +const unsigned ACC_STRICT = 1 << 11; } // namespace vm diff --git a/src/jnienv.cpp b/src/jnienv.cpp index b499a08502..3962ecc4dc 100644 --- a/src/jnienv.cpp +++ b/src/jnienv.cpp @@ -36,6 +36,14 @@ ReleaseStringUTFChars(Thread* t, jstring, const char* chars) t->vm->system->free(chars); } +jstring +NewStringUTF(Thread* t, const char* chars) +{ + ENTER(t, Thread::ActiveState); + + return pushReference(t, makeString(t, "%s", chars)); +} + void populate(JNIEnvVTable* table) { @@ -44,6 +52,7 @@ populate(JNIEnvVTable* table) table->GetStringUTFLength = GetStringUTFLength; table->GetStringUTFChars = GetStringUTFChars; table->ReleaseStringUTFChars = ReleaseStringUTFChars; + table->NewStringUTF = NewStringUTF; } } // namespace jni diff --git a/src/machine.cpp b/src/machine.cpp index f532fd7702..7990b625c9 100644 --- a/src/machine.cpp +++ b/src/machine.cpp @@ -6,45 +6,6 @@ using namespace vm; namespace { -void -visitRoots(Thread* t, Heap::Visitor* v) -{ - if (t->state != Thread::ZombieState) { - t->heapIndex = 0; - - v->visit(&(t->javaThread)); - v->visit(&(t->code)); - v->visit(&(t->exception)); - - for (unsigned i = 0; i < t->sp; ++i) { - if (t->stack[i * 2] == ObjectTag) { - v->visit(reinterpret_cast(t->stack + (i * 2) + 1)); - } - } - - for (Thread::Protector* p = t->protector; p; p = p->next) { - v->visit(p->p); - } - } - - for (Thread* c = t->child; c; c = c->peer) { - visitRoots(c, v); - } -} - -void -postCollect(Thread* t) -{ - if (t->large) { - t->vm->system->free(t->large); - t->large = 0; - } - - for (Thread* c = t->child; c; c = c->peer) { - postCollect(c); - } -} - bool find(Thread* t, Thread* o) { @@ -140,6 +101,45 @@ killZombies(Thread* t, Thread* o) } } +void +visitRoots(Thread* t, Heap::Visitor* v) +{ + if (t->state != Thread::ZombieState) { + t->heapIndex = 0; + + v->visit(&(t->javaThread)); + v->visit(&(t->code)); + v->visit(&(t->exception)); + + for (unsigned i = 0; i < t->sp; ++i) { + if (t->stack[i * 2] == ObjectTag) { + v->visit(reinterpret_cast(t->stack + (i * 2) + 1)); + } + } + + for (Thread::Protector* p = t->protector; p; p = p->next) { + v->visit(p->p); + } + } + + for (Thread* c = t->child; c; c = c->peer) { + visitRoots(c, v); + } +} + +void +postCollect(Thread* t) +{ + if (t->large) { + t->vm->system->free(t->large); + t->large = 0; + } + + for (Thread* c = t->child; c; c = c->peer) { + postCollect(c); + } +} + void collect(Thread* t, Heap::CollectionType type) { @@ -174,13 +174,8 @@ collect(Thread* t, Heap::CollectionType type) } } - for (object* f = &(m->finalizers); *f; f = &finalizerNext(t, *f)) { - v->visit(f); - } - - for (object* f = &(m->doomed); *f; f = &finalizerNext(t, *f)) { - v->visit(f); - } + v->visit(&(m->finalizers)); + v->visit(&(m->doomed)); for (object p = m->weakReferences; p;) { object o = jreferenceTarget(t, p); @@ -193,8 +188,8 @@ collect(Thread* t, Heap::CollectionType type) } object last = p; - p = weakReferenceNext(t, p); - weakReferenceNext(t, last) = 0; + p = jreferenceNext(t, p); + jreferenceNext(t, last) = 0; } } @@ -233,13 +228,16 @@ collect(Thread* t, Heap::CollectionType type) memcpy(dst, o, n * BytesPerWord); if (hashTaken(t, o)) { - extendedWord(t, dst, base) = takeHash(t, o); cast(dst, 0) &= PointerMask; cast(dst, 0) |= ExtendedMark; + extendedWord(t, dst, base) = takeHash(t, o); } if (classVmFlags(t, class_) & WeakReferenceFlag) { - weakReferenceNext(t, dst) = m->weakReferences; + fprintf(stderr, "weak reference to %p at %p\n", + jreferenceTarget(t, dst), + &jreferenceTarget(t, dst)); + jreferenceNext(t, dst) = m->weakReferences; m->weakReferences = dst; } } @@ -255,7 +253,6 @@ collect(Thread* t, Heap::CollectionType type) // fprintf(stderr, "p: %p; class: %p; mask: %p; mask length: %d\n", // p, class_, objectMask, intArrayLength(t, objectMask)); - unsigned vmFlags = classVmFlags(t, class_); unsigned fixedSize = classFixedSize(t, class_); unsigned arrayElementSize = classArrayElementSize(t, class_); unsigned arrayLength @@ -275,9 +272,7 @@ collect(Thread* t, Heap::CollectionType type) = divide(arrayElementSize, BytesPerWord); for (unsigned i = 0; i < fixedSizeInWords; ++i) { - if ((i != 1 or (vmFlags & WeakReferenceFlag) == 0) - and mask[wordOf(i)] & (static_cast(1) << bitOf(i))) - { + if (mask[wordOf(i)] & (static_cast(1) << bitOf(i))) { if (not w->visit(i)) { return; } @@ -322,7 +317,7 @@ collect(Thread* t, Heap::CollectionType type) postCollect(m->rootThread); - for (object f = m->doomed; f; f = tripleThird(t, f)) { + for (object f = m->doomed; f; f = finalizerNext(t, f)) { reinterpret_cast(finalizerFinalize(t, f)) (t, finalizerTarget(t, f)); } @@ -451,6 +446,8 @@ Thread::Thread(Machine* m, Allocator* allocator, object javaThread, object intArrayClass = arrayBody(t, m->types, Machine::IntArrayType); set(t, cast(intArrayClass, 0), classClass); + set(t, classSuper(t, intArrayClass), + arrayBody(t, m->types, Machine::JobjectType)); m->unsafe = false; diff --git a/src/machine.h b/src/machine.h index ea5b7b6a54..20ef67e945 100644 --- a/src/machine.h +++ b/src/machine.h @@ -24,7 +24,7 @@ namespace vm { const bool Verbose = false; const bool Debug = false; const bool DebugRun = true; -const bool DebugStack = false; +const bool DebugStack = true; const uintptr_t HashTakenMark = 1; const uintptr_t ExtendedMark = 2; @@ -1311,6 +1311,12 @@ makeIllegalStateException(Thread* t, object message) return makeIllegalStateException(t, message, trace, 0); } +inline object +makeIllegalMonitorStateException(Thread* t) +{ + return makeIllegalMonitorStateException(t, 0, makeTrace(t), 0); +} + inline object makeArrayIndexOutOfBoundsException(Thread* t, object message) { @@ -1320,11 +1326,17 @@ makeArrayIndexOutOfBoundsException(Thread* t, object message) } inline object -makeNegativeArrayStoreException(Thread* t, object message) +makeArrayStoreException(Thread* t) +{ + return makeArrayStoreException(t, 0, makeTrace(t), 0); +} + +inline object +makeNegativeArraySizeException(Thread* t, object message) { PROTECT(t, message); object trace = makeTrace(t); - return makeNegativeArrayStoreException(t, message, trace, 0); + return makeNegativeArraySizeException(t, message, trace, 0); } inline object @@ -1535,7 +1547,7 @@ pokeLong(Thread* t, unsigned index, uint64_t value) } pokeInt(t, index, value >> 32); - pokeInt(t, index + 2, value & 0xFF); + pokeInt(t, index + 1, value & 0xFF); } inline object* @@ -1807,6 +1819,56 @@ addFinalizer(Thread* t, object target, void (*finalize)(Thread*, object)); System::Monitor* objectMonitor(Thread* t, object o); +inline void +acquire(Thread* t, object o) +{ + System::Monitor* m = objectMonitor(t, o); + if (not m->tryAcquire(t)) { + ENTER(t, Thread::IdleState); + m->acquire(t); + } +} + +inline void +release(Thread* t, object o) +{ + objectMonitor(t, o)->release(t); +} + +inline void +wait(Thread* t, object o, int64_t milliseconds) +{ + System::Monitor* m = objectMonitor(t, o); + if (m->owner() == t) { + ENTER(t, Thread::IdleState); + m->wait(t, milliseconds); + } else { + t->exception = makeIllegalMonitorStateException(t); + } +} + +inline void +notify(Thread* t, object o) +{ + System::Monitor* m = objectMonitor(t, o); + if (m->owner() == t) { + m->notify(t); + } else { + t->exception = makeIllegalMonitorStateException(t); + } +} + +inline void +notifyAll(Thread* t, object o) +{ + System::Monitor* m = objectMonitor(t, o); + if (m->owner() == t) { + m->notifyAll(t); + } else { + t->exception = makeIllegalMonitorStateException(t); + } +} + void exit(Thread* t); diff --git a/src/main.cpp b/src/main.cpp index 8034ec1ea3..1f5e13a0d4 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -226,6 +226,10 @@ class System: public vm::System { vm::abort(s); } } + + virtual void* owner() { + return context; + } virtual void dispose() { pthread_mutex_destroy(&mutex); diff --git a/src/run.cpp b/src/run.cpp index 683e71c2f5..ad9a35cc4f 100644 --- a/src/run.cpp +++ b/src/run.cpp @@ -42,11 +42,30 @@ pushFrame(Thread* t, object method) pokeInt(t, frame + FrameBaseOffset, base); pokeObject(t, frame + FrameMethodOffset, method); + pokeInt(t, t->frame + FrameIpOffset, 0); + + if (methodFlags(t, method) & ACC_SYNCHRONIZED) { + if (methodFlags(t, method) & ACC_STATIC) { + acquire(t, methodClass(t, method)); + } else { + acquire(t, peekObject(t, base)); + } + } } void popFrame(Thread* t) { + object method = frameMethod(t, t->frame); + + if (methodFlags(t, method) & ACC_SYNCHRONIZED) { + if (methodFlags(t, method) & ACC_STATIC) { + release(t, methodClass(t, method)); + } else { + release(t, peekObject(t, frameBase(t, t->frame))); + } + } + t->sp = frameBase(t, t->frame); t->frame = frameNext(t, t->frame); if (t->frame >= 0) { @@ -1214,10 +1233,20 @@ resolveClass(Thread* t, object spec) hashMapInsert(t, t->vm->classMap, spec, class_, byteArrayHash); } else { - object message = makeString(t, "%s", &byteArrayBody(t, spec, 0)); - t->exception = makeClassNotFoundException(t, message); + class_ = hashMapFind + (t, t->vm->bootstrapClassMap, spec, byteArrayHash, byteArrayEqual); + + if (class_ == 0) { + object message = makeString(t, "%s", &byteArrayBody(t, spec, 0)); + t->exception = makeClassNotFoundException(t, message); + } + } + + if (class_) { + hashMapInsert(t, t->vm->classMap, spec, class_, byteArrayHash); } } + return class_; } @@ -1452,6 +1481,12 @@ invokeNative(Thread* t, object method) enter(t, Thread::IdleState); } + if (DebugRun) { + fprintf(stderr, "invoke native method %s.%s\n", + &byteArrayBody(t, className(t, methodClass(t, method)), 0), + &byteArrayBody(t, methodName(t, method), 0)); + } + uint64_t result = t->vm->system->call (function, args, @@ -1460,6 +1495,14 @@ invokeNative(Thread* t, object method) size, returnType); + if (DebugRun) { + fprintf(stderr, "return from native method %s.%s\n", + &byteArrayBody + (t, className(t, methodClass(t, frameMethod(t, t->frame))), 0), + &byteArrayBody + (t, methodName(t, frameMethod(t, t->frame)), 0)); + } + if (not builtin) { enter(t, oldState); } @@ -1477,15 +1520,26 @@ invokeNative(Thread* t, object method) case ShortField: case FloatField: case IntField: + if (DebugRun) { + fprintf(stderr, "result: " LLD "\n", result); + } pushInt(t, result); break; case LongField: case DoubleField: + if (DebugRun) { + fprintf(stderr, "result: " LLD "\n", result); + } pushLong(t, result); break; case ObjectField: + if (DebugRun) { + fprintf(stderr, "result: %p at %p\n", result == 0 ? 0 : + *reinterpret_cast(static_cast(result)), + reinterpret_cast(static_cast(result))); + } pushObject(t, result == 0 ? 0 : *reinterpret_cast(static_cast(result))); break; @@ -1622,28 +1676,19 @@ run(Thread* t) pushObject(t, array); } else { object message = makeString(t, "%d", count); - exception = makeNegativeArrayStoreException(t, message); + exception = makeNegativeArraySizeException(t, message); goto throw_; } } goto loop; - case areturn: - case ireturn: - case lreturn: { + case areturn: { + object result = popObject(t); popFrame(t); if (frame >= 0) { + pushObject(t, result); goto loop; } else { - switch (instruction) { - case areturn: - return popObject(t); - - case ireturn: - return makeInt(t, popInt(t)); - - case lreturn: - return makeLong(t, popLong(t)); - } + return result; } } goto loop; @@ -1655,14 +1700,14 @@ run(Thread* t) { pushInt(t, objectArrayLength(t, array)); } else { - // for all other array types, the length follow the class pointer. + // for all other array types, the length follows the class pointer. pushInt(t, cast(array, BytesPerWord)); } } else { exception = makeNullPointerException(t); goto throw_; } - } abort(t); + } goto loop; case astore: { setLocalObject(t, codeBody(t, code, ip++), popObject(t)); @@ -2168,7 +2213,7 @@ run(Thread* t) int32_t b = popInt(t); int32_t a = popInt(t); - if (a < b) { + if (a <= b) { ip = (ip - 3) + static_cast(((offset1 << 8) | offset2)); } } goto loop; @@ -2405,6 +2450,17 @@ run(Thread* t) pushInt(t, a % b); } goto loop; + case ireturn: { + int32_t result = popInt(t); + popFrame(t); + if (frame >= 0) { + pushInt(t, result); + goto loop; + } else { + return makeInt(t, result); + } + } goto loop; + case ishl: { int32_t b = popInt(t); int32_t a = popInt(t); @@ -2480,7 +2536,7 @@ run(Thread* t) } goto loop; case l2i: { - pushLong(t, static_cast(popLong(t))); + pushInt(t, static_cast(popLong(t))); } goto loop; case ladd: { @@ -2649,6 +2705,17 @@ run(Thread* t) pushLong(t, a % b); } goto loop; + case lreturn: { + int64_t result = popLong(t); + popFrame(t); + if (frame >= 0) { + pushLong(t, result); + goto loop; + } else { + return makeLong(t, result); + } + } goto loop; + case lshl: { int64_t b = popLong(t); int64_t a = popLong(t); @@ -2707,7 +2774,7 @@ run(Thread* t) case monitorenter: { object o = popObject(t); if (LIKELY(o)) { - objectMonitor(t, o)->acquire(t); + acquire(t, o); } else { exception = makeNullPointerException(t); goto throw_; @@ -2717,7 +2784,7 @@ run(Thread* t) case monitorexit: { object o = popObject(t); if (LIKELY(o)) { - objectMonitor(t, o)->release(t); + release(t, o); } else { exception = makeNullPointerException(t); goto throw_; @@ -2790,7 +2857,7 @@ run(Thread* t) pushObject(t, array); } else { object message = makeString(t, "%d", count); - exception = makeNegativeArrayStoreException(t, message); + exception = makeNegativeArraySizeException(t, message); goto throw_; } } goto loop; diff --git a/src/system.h b/src/system.h index caa96135d6..3f875402bb 100644 --- a/src/system.h +++ b/src/system.h @@ -40,6 +40,7 @@ class System: public Allocator { virtual void wait(void* context, int64_t time) = 0; virtual void notify(void* context) = 0; virtual void notifyAll(void* context) = 0; + virtual void* owner() = 0; virtual void dispose() = 0; }; diff --git a/src/type-generator.cpp b/src/type-generator.cpp index 97b950bd22..9a5017183b 100644 --- a/src/type-generator.cpp +++ b/src/type-generator.cpp @@ -1475,23 +1475,11 @@ writeInitialization(Output* out, Object* type) out->write(" object mask = 0;\n"); } - if (typeJavaName(type)) { - if (typeObjectMask(type) != 1) { - out->write(" PROTECT(t, mask);\n"); - } - out->write(" object name = ::makeByteArray(t, \""); - out->write(typeJavaName(type)); - out->write("\");\n"); - - if (typeSuper(type)) { - out->write(" object super = arrayBody(t, t->vm->types, Machine::"); - out->write(capitalize(typeName(typeSuper(type)))); - out->write("Type);\n"); - } else { - out->write(" object super = 0;\n"); - } + if (typeJavaName(type) and typeSuper(type)) { + out->write(" object super = arrayBody(t, t->vm->types, Machine::"); + out->write(capitalize(typeName(typeSuper(type)))); + out->write("Type);\n"); } else { - out->write(" object name = 0;\n"); out->write(" object super = 0;\n"); } @@ -1500,17 +1488,12 @@ writeInitialization(Output* out, Object* type) out->write(typeFixedSize(type)); out->write(", "); out->write(typeArrayElementSize(type)); - out->write(", mask, name, super, 0, 0, 0, 0, 0, 0);\n"); + out->write(", mask, 0, super, 0, 0, 0, 0, 0, 0);\n"); out->write(" set(t, arrayBody(t, t->vm->types, Machine::"); out->write(capitalize(typeName(type))); out->write("Type), class_);\n"); - if (typeJavaName(type)) { - out->write(" hashMapInsert(t, t->vm->bootstrapClassMap, "); - out->write("className(t, class_), class_, byteArrayHash);\n"); - } - out->write("}\n\n"); } @@ -1549,10 +1532,38 @@ writeInitializations(Output* out, Object* declarations) for (Object* p = declarations; p; p = cdr(p)) { Object* o = car(p); - if (o->type == Object::Type and typeJavaName(o) == 0) { + if (o->type == Object::Type and equal(typeName(o), "intArray")) { writeInitialization(out, o); } } + + for (Object* p = declarations; p; p = cdr(p)) { + Object* o = car(p); + if (o->type == Object::Type and not equal(typeName(o), "intArray")) { + writeInitialization(out, o); + } + } +} + +void +writeJavaInitialization(Output* out, Object* type) +{ + out->write("{\n"); + + out->write(" object name = ::makeByteArray(t, \""); + out->write(typeJavaName(type)); + out->write("\");\n"); + + out->write(" object class_ = arrayBody(t, t->vm->types, Machine::"); + out->write(capitalize(typeName(type))); + out->write("Type);\n"); + + out->write(" set(t, className(t, class_), name);\n"); + + out->write(" hashMapInsert(t, t->vm->bootstrapClassMap, "); + out->write("name, class_, byteArrayHash);\n"); + + out->write("}\n\n"); } void @@ -1561,7 +1572,7 @@ writeJavaInitializations(Output* out, Object* declarations) for (Object* p = declarations; p; p = cdr(p)) { Object* o = car(p); if (o->type == Object::Type and typeJavaName(o)) { - writeInitialization(out, o); + writeJavaInitialization(out, o); } } } @@ -1570,7 +1581,8 @@ void usageAndExit(const char* command) { fprintf(stderr, - "usage: %s {enums,declarations,constructors,initializations}\n", + "usage: %s {enums,declarations,constructors,initializations," + "java-initializations}\n", command); exit(-1); } diff --git a/src/types.def b/src/types.def index b977a72976..4d23db57c1 100644 --- a/src/types.def +++ b/src/types.def @@ -1,6 +1,3 @@ -(type intArray - (array int32_t body)) - (type class (uint16_t flags) (uint16_t vmFlags) @@ -108,31 +105,6 @@ (type array (noassert array object body)) -(type objectArray - (object elementClass) - (array object body)) - -(type byteArray - (array int8_t body)) - -(type booleanArray - (array int8_t body)) - -(type shortArray - (array int16_t body)) - -(type charArray - (array uint16_t body)) - -(type longArray - (array int64_t body)) - -(type floatArray - (array uint32_t body)) - -(type doubleArray - (array uint64_t body)) - (type jobject java/lang/Object) @@ -166,11 +138,17 @@ (type illegalStateException java/lang/IllegalStateException (extends runtimeException)) +(type illegalMonitorStateException java/lang/IllegalMonitorStateException + (extends runtimeException)) + (type arrayIndexOutOfBoundsException java/lang/ArrayIndexOutOfBoundsException (extends runtimeException)) -(type negativeArrayStoreException java/lang/NegativeArrayStoreException +(type arrayStoreException java/lang/arrayStoreException + (extends runtimeException)) + +(type negativeArraySizeException java/lang/NegativeArraySizeException (extends runtimeException)) (type classCastException java/lang/ClassCastException @@ -228,8 +206,45 @@ (type jreference java/lang/ref/Reference (extends jobject) - (object target)) + (void* target) + (void* next)) (type weakReference java/lang/ref/WeakReference - (extends jreference) - (object next)) + (extends jreference)) + +(type objectArray [ + (extends jobject) + (object elementClass) + (array object body)) + +(type byteArray [B + (extends jobject) + (array int8_t body)) + +(type booleanArray [Z + (extends jobject) + (array int8_t body)) + +(type shortArray [S + (extends jobject) + (array int16_t body)) + +(type charArray [C + (extends jobject) + (array uint16_t body)) + +(type intArray [I + (extends jobject) + (array int32_t body)) + +(type longArray [J + (extends jobject) + (array int64_t body)) + +(type floatArray [F + (extends jobject) + (array uint32_t body)) + +(type doubleArray [D + (extends jobject) + (array uint64_t body))