From 48226f988c506a16c5fa5f0ee82b0cccb927e5eb Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Sat, 21 Jul 2007 11:50:26 -0600 Subject: [PATCH 1/5] add a bunch of classes to classpath and flesh out a few existing ones --- classpath/java/lang/Byte.java | 22 ++++++- classpath/java/lang/ClassCastException.java | 11 ++++ classpath/java/lang/ClassLoader.java | 5 ++ .../java/lang/ClassNotFoundException.java | 15 +++++ .../java/lang/CloneNotSupportedException.java | 11 ++++ classpath/java/lang/Double.java | 20 ++++++ classpath/java/lang/Float.java | 22 ++++++- .../java/lang/IllegalAccessException.java | 11 ++++ .../java/lang/IllegalArgumentException.java | 19 ++++++ .../java/lang/InstantiationException.java | 11 ++++ classpath/java/lang/Integer.java | 22 ++++++- classpath/java/lang/Long.java | 22 ++++++- classpath/java/lang/NoClassDefFoundError.java | 11 ++++ classpath/java/lang/NoSuchFieldException.java | 11 ++++ .../java/lang/NoSuchMethodException.java | 11 ++++ classpath/java/lang/Number.java | 10 +++ .../java/lang/NumberFormatException.java | 11 ++++ classpath/java/lang/Runtime.java | 17 +++++ classpath/java/lang/SecurityException.java | 19 ++++++ classpath/java/lang/Short.java | 22 ++++++- classpath/java/lang/System.java | 14 +++- classpath/java/lang/ref/Reference.java | 2 +- .../java/lang/reflect/AccessibleObject.java | 9 +++ classpath/java/lang/reflect/Constructor.java | 20 ++++++ classpath/java/lang/reflect/Field.java | 21 ++++++ classpath/java/lang/reflect/Method.java | 23 +++++++ makefile | 2 +- src/builtin.cpp | 66 ++++++++++++------- src/machine.cpp | 19 ++++-- src/run.cpp | 4 +- src/system.cpp | 21 +++++- src/system.h | 2 + src/types.def | 19 ++++-- 33 files changed, 475 insertions(+), 50 deletions(-) create mode 100644 classpath/java/lang/ClassCastException.java create mode 100644 classpath/java/lang/ClassLoader.java create mode 100644 classpath/java/lang/ClassNotFoundException.java create mode 100644 classpath/java/lang/CloneNotSupportedException.java create mode 100644 classpath/java/lang/IllegalAccessException.java create mode 100644 classpath/java/lang/IllegalArgumentException.java create mode 100644 classpath/java/lang/InstantiationException.java create mode 100644 classpath/java/lang/NoClassDefFoundError.java create mode 100644 classpath/java/lang/NoSuchFieldException.java create mode 100644 classpath/java/lang/NoSuchMethodException.java create mode 100644 classpath/java/lang/Number.java create mode 100644 classpath/java/lang/NumberFormatException.java create mode 100644 classpath/java/lang/Runtime.java create mode 100644 classpath/java/lang/SecurityException.java create mode 100644 classpath/java/lang/reflect/AccessibleObject.java create mode 100644 classpath/java/lang/reflect/Constructor.java create mode 100644 classpath/java/lang/reflect/Field.java create mode 100644 classpath/java/lang/reflect/Method.java diff --git a/classpath/java/lang/Byte.java b/classpath/java/lang/Byte.java index 03250631a1..0ace19db24 100644 --- a/classpath/java/lang/Byte.java +++ b/classpath/java/lang/Byte.java @@ -1,6 +1,6 @@ package java.lang; -public final class Byte { +public final class Byte extends Number { private final byte value; public Byte(byte value) { @@ -10,4 +10,24 @@ public final class Byte { public byte byteValue() { return value; } + + public short shortValue() { + return value; + } + + public int intValue() { + return value; + } + + public long longValue() { + return value; + } + + public float floatValue() { + return (float) value; + } + + public double doubleValue() { + return (double) value; + } } diff --git a/classpath/java/lang/ClassCastException.java b/classpath/java/lang/ClassCastException.java new file mode 100644 index 0000000000..1160942a11 --- /dev/null +++ b/classpath/java/lang/ClassCastException.java @@ -0,0 +1,11 @@ +package java.lang; + +public class ClassCastException extends RuntimeException { + public ClassCastException(String message) { + super(message); + } + + public ClassCastException() { + super(); + } +} diff --git a/classpath/java/lang/ClassLoader.java b/classpath/java/lang/ClassLoader.java new file mode 100644 index 0000000000..b9648d565c --- /dev/null +++ b/classpath/java/lang/ClassLoader.java @@ -0,0 +1,5 @@ +package java.lang; + +public abstract class ClassLoader { + +} diff --git a/classpath/java/lang/ClassNotFoundException.java b/classpath/java/lang/ClassNotFoundException.java new file mode 100644 index 0000000000..9a68dfa54f --- /dev/null +++ b/classpath/java/lang/ClassNotFoundException.java @@ -0,0 +1,15 @@ +package java.lang; + +public class ClassNotFoundException extends Exception { + public ClassNotFoundException(String message, Throwable cause) { + super(message, cause); + } + + public ClassNotFoundException(String message) { + this(message, null); + } + + public ClassNotFoundException() { + this(null, null); + } +} diff --git a/classpath/java/lang/CloneNotSupportedException.java b/classpath/java/lang/CloneNotSupportedException.java new file mode 100644 index 0000000000..59d8e9fa05 --- /dev/null +++ b/classpath/java/lang/CloneNotSupportedException.java @@ -0,0 +1,11 @@ +package java.lang; + +public class CloneNotSupportedException extends Exception { + public CloneNotSupportedException(String message) { + super(message); + } + + public CloneNotSupportedException() { + super(); + } +} diff --git a/classpath/java/lang/Double.java b/classpath/java/lang/Double.java index 8765d9541e..2c8f388e76 100644 --- a/classpath/java/lang/Double.java +++ b/classpath/java/lang/Double.java @@ -7,6 +7,26 @@ public final class Double { this.value = value; } + public byte byteValue() { + return (byte) value; + } + + public short shortValue() { + return (short) value; + } + + public int intValue() { + return (int) value; + } + + public long longValue() { + return (long) value; + } + + public float floatValue() { + return (float) value; + } + public double doubleValue() { return value; } diff --git a/classpath/java/lang/Float.java b/classpath/java/lang/Float.java index 3e8d6b5eef..9c4aa3ffb2 100644 --- a/classpath/java/lang/Float.java +++ b/classpath/java/lang/Float.java @@ -1,13 +1,33 @@ package java.lang; -public final class Float { +public final class Float extends Number { private final float value; public Float(float value) { this.value = value; } + public byte byteValue() { + return (byte) value; + } + + public short shortValue() { + return (short) value; + } + + public int intValue() { + return (int) value; + } + + public long longValue() { + return (long) value; + } + public float floatValue() { return value; } + + public double doubleValue() { + return (double) value; + } } diff --git a/classpath/java/lang/IllegalAccessException.java b/classpath/java/lang/IllegalAccessException.java new file mode 100644 index 0000000000..57b0afd726 --- /dev/null +++ b/classpath/java/lang/IllegalAccessException.java @@ -0,0 +1,11 @@ +package java.lang; + +public class IllegalAccessException extends Exception { + public IllegalAccessException(String message) { + super(message); + } + + public IllegalAccessException() { + super(); + } +} diff --git a/classpath/java/lang/IllegalArgumentException.java b/classpath/java/lang/IllegalArgumentException.java new file mode 100644 index 0000000000..13c8d1d34f --- /dev/null +++ b/classpath/java/lang/IllegalArgumentException.java @@ -0,0 +1,19 @@ +package java.lang; + +public class IllegalArgumentException extends RuntimeException { + public IllegalArgumentException(String message, Throwable cause) { + super(message, cause); + } + + public IllegalArgumentException(String message) { + this(message, null); + } + + public IllegalArgumentException(Throwable cause) { + this(null, cause); + } + + public IllegalArgumentException() { + this(null, null); + } +} diff --git a/classpath/java/lang/InstantiationException.java b/classpath/java/lang/InstantiationException.java new file mode 100644 index 0000000000..fffa241189 --- /dev/null +++ b/classpath/java/lang/InstantiationException.java @@ -0,0 +1,11 @@ +package java.lang; + +public class InstantiationException extends Exception { + public InstantiationException(String message) { + super(message); + } + + public InstantiationException() { + super(); + } +} diff --git a/classpath/java/lang/Integer.java b/classpath/java/lang/Integer.java index 68eb18b006..2a98535024 100644 --- a/classpath/java/lang/Integer.java +++ b/classpath/java/lang/Integer.java @@ -1,13 +1,33 @@ package java.lang; -public final class Integer { +public final class Integer extends Number { private final int value; public Integer(int value) { this.value = value; } + public byte byteValue() { + return (byte) value; + } + + public short shortValue() { + return (short) value; + } + public int intValue() { return value; } + + public long longValue() { + return value; + } + + public float floatValue() { + return (float) value; + } + + public double doubleValue() { + return (double) value; + } } diff --git a/classpath/java/lang/Long.java b/classpath/java/lang/Long.java index ed0c74f157..1fce98ec72 100644 --- a/classpath/java/lang/Long.java +++ b/classpath/java/lang/Long.java @@ -1,13 +1,33 @@ package java.lang; -public final class Long { +public final class Long extends Number { private final long value; public Long(long value) { this.value = value; } + public byte byteValue() { + return (byte) value; + } + + public short shortValue() { + return (short) value; + } + + public int intValue() { + return (int) value; + } + public long longValue() { return value; } + + public float floatValue() { + return (float) value; + } + + public double doubleValue() { + return (double) value; + } } diff --git a/classpath/java/lang/NoClassDefFoundError.java b/classpath/java/lang/NoClassDefFoundError.java new file mode 100644 index 0000000000..fbfb21be6f --- /dev/null +++ b/classpath/java/lang/NoClassDefFoundError.java @@ -0,0 +1,11 @@ +package java.lang; + +public class NoClassDefFoundError extends LinkageError { + public NoClassDefFoundError(String message) { + super(message); + } + + public NoClassDefFoundError() { + super(); + } +} diff --git a/classpath/java/lang/NoSuchFieldException.java b/classpath/java/lang/NoSuchFieldException.java new file mode 100644 index 0000000000..c8bdbf3c11 --- /dev/null +++ b/classpath/java/lang/NoSuchFieldException.java @@ -0,0 +1,11 @@ +package java.lang; + +public class NoSuchFieldException extends Exception { + public NoSuchFieldException(String message) { + super(message); + } + + public NoSuchFieldException() { + super(); + } +} diff --git a/classpath/java/lang/NoSuchMethodException.java b/classpath/java/lang/NoSuchMethodException.java new file mode 100644 index 0000000000..5633f33ce9 --- /dev/null +++ b/classpath/java/lang/NoSuchMethodException.java @@ -0,0 +1,11 @@ +package java.lang; + +public class NoSuchMethodException extends Exception { + public NoSuchMethodException(String message) { + super(message); + } + + public NoSuchMethodException() { + super(); + } +} diff --git a/classpath/java/lang/Number.java b/classpath/java/lang/Number.java new file mode 100644 index 0000000000..8135a7a26e --- /dev/null +++ b/classpath/java/lang/Number.java @@ -0,0 +1,10 @@ +package java.lang; + +public abstract class Number { + public abstract byte byteValue(); + public abstract short shortValue(); + public abstract int intValue(); + public abstract long longValue(); + public abstract float floatValue(); + public abstract double doubleValue(); +} diff --git a/classpath/java/lang/NumberFormatException.java b/classpath/java/lang/NumberFormatException.java new file mode 100644 index 0000000000..57fcba7f6c --- /dev/null +++ b/classpath/java/lang/NumberFormatException.java @@ -0,0 +1,11 @@ +package java.lang; + +public class NumberFormatException extends IllegalArgumentException { + public NumberFormatException(String message) { + super(message); + } + + public NumberFormatException() { + super(); + } +} diff --git a/classpath/java/lang/Runtime.java b/classpath/java/lang/Runtime.java new file mode 100644 index 0000000000..94c220b7b1 --- /dev/null +++ b/classpath/java/lang/Runtime.java @@ -0,0 +1,17 @@ +package java.lang; + +public class Runtime { + private static final Runtime instance = new Runtime(); + + private Runtime() { } + + public static Runtime getRuntime() { + return instance; + } + + public native void loadLibrary(String name); + + public native void gc(); + + public native void exit(int code); +} diff --git a/classpath/java/lang/SecurityException.java b/classpath/java/lang/SecurityException.java new file mode 100644 index 0000000000..4007351a67 --- /dev/null +++ b/classpath/java/lang/SecurityException.java @@ -0,0 +1,19 @@ +package java.lang; + +public class SecurityException extends RuntimeException { + public SecurityException(String message, Throwable cause) { + super(message, cause); + } + + public SecurityException(String message) { + this(message, null); + } + + public SecurityException(Throwable cause) { + this(null, cause); + } + + public SecurityException() { + this(null, null); + } +} diff --git a/classpath/java/lang/Short.java b/classpath/java/lang/Short.java index 214cc0efe0..b860feee6a 100644 --- a/classpath/java/lang/Short.java +++ b/classpath/java/lang/Short.java @@ -1,13 +1,33 @@ package java.lang; -public final class Short { +public final class Short extends Number { private final short value; public Short(short value) { this.value = value; } + public byte byteValue() { + return (byte) value; + } + public short shortValue() { return value; } + + public int intValue() { + return value; + } + + public long longValue() { + return value; + } + + public float floatValue() { + return (float) value; + } + + public double doubleValue() { + return (double) value; + } } diff --git a/classpath/java/lang/System.java b/classpath/java/lang/System.java index af5df4b24e..4499401131 100644 --- a/classpath/java/lang/System.java +++ b/classpath/java/lang/System.java @@ -11,11 +11,19 @@ public abstract class System { 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 native void gc(); + public static void loadLibrary(String name) { + Runtime.getRuntime().loadLibrary(name); + } + + public static void gc() { + Runtime.getRuntime().gc(); + } + + public static void exit(int code) { + Runtime.getRuntime().exit(code); + } public static class Output { public synchronized native void print(String s); diff --git a/classpath/java/lang/ref/Reference.java b/classpath/java/lang/ref/Reference.java index 48451617c3..b015112c32 100644 --- a/classpath/java/lang/ref/Reference.java +++ b/classpath/java/lang/ref/Reference.java @@ -1,9 +1,9 @@ package java.lang.ref; public abstract class Reference { + private Object vmNext; private T target; private ReferenceQueue queue; - private Object vmNext; Reference next; protected Reference(T target, ReferenceQueue queue) { diff --git a/classpath/java/lang/reflect/AccessibleObject.java b/classpath/java/lang/reflect/AccessibleObject.java new file mode 100644 index 0000000000..41783d1255 --- /dev/null +++ b/classpath/java/lang/reflect/AccessibleObject.java @@ -0,0 +1,9 @@ +package java.lang.reflect; + +public abstract class AccessibleObject { + protected static final int Accessible = 1 << 0; + + public abstract boolean isAccessible(); + + public abstract void setAccessible(boolean v); +} diff --git a/classpath/java/lang/reflect/Constructor.java b/classpath/java/lang/reflect/Constructor.java new file mode 100644 index 0000000000..cba1ec9331 --- /dev/null +++ b/classpath/java/lang/reflect/Constructor.java @@ -0,0 +1,20 @@ +package java.lang.reflect; + +public class Constructor extends AccessibleObject { + private Method method; + + private Constructor() { } + + public boolean equals(Object o) { + return o instanceof Constructor + && ((Constructor) o).method.equals(method); + } + + public boolean isAccessible() { + return method.isAccessible(); + } + + public void setAccessible(boolean v) { + method.setAccessible(v); + } +} diff --git a/classpath/java/lang/reflect/Field.java b/classpath/java/lang/reflect/Field.java new file mode 100644 index 0000000000..9fd11bf112 --- /dev/null +++ b/classpath/java/lang/reflect/Field.java @@ -0,0 +1,21 @@ +package java.lang.reflect; + +public class Field extends AccessibleObject { + private byte vmFlags; + private byte code; + private short flags; + private short offset; + private byte[] name; + private byte[] spec; + private Class class_; + + private Field() { } + + public boolean isAccessible() { + return (vmFlags & Accessible) != 0; + } + + public void setAccessible(boolean v) { + if (v) vmFlags |= Accessible; else vmFlags &= ~Accessible; + } +} diff --git a/classpath/java/lang/reflect/Method.java b/classpath/java/lang/reflect/Method.java new file mode 100644 index 0000000000..4d18a19a0a --- /dev/null +++ b/classpath/java/lang/reflect/Method.java @@ -0,0 +1,23 @@ +package java.lang.reflect; + +public class Method extends AccessibleObject { + private byte vmFlags; + private byte parameterCount; + private short parameterFootprint; + private short flags; + private short offset; + private byte[] name; + private byte[] spec; + private Class class_; + private Object code; + + private Method() { } + + public boolean isAccessible() { + return (vmFlags & Accessible) != 0; + } + + public void setAccessible(boolean v) { + if (v) vmFlags |= Accessible; else vmFlags &= ~Accessible; + } +} diff --git a/makefile b/makefile index e875719e7a..daf0b7b600 100644 --- a/makefile +++ b/makefile @@ -1,4 +1,4 @@ -#MAKEFLAGS = -s +MAKEFLAGS = -s arch = $(shell uname -m) ifeq ($(arch),i586) diff --git a/src/builtin.cpp b/src/builtin.cpp index 50d685dfdc..5f8a9dd60d 100644 --- a/src/builtin.cpp +++ b/src/builtin.cpp @@ -51,28 +51,6 @@ sleep(Thread* t, jlong milliseconds) t->vm->system->sleep(milliseconds); } -void -loadLibrary(Thread* t, jstring nameString) -{ - if (LIKELY(nameString)) { - object n = *nameString; - char name[stringLength(t, n) + 1]; - stringChars(t, n, name); - - System::Library* lib; - if (LIKELY(t->vm->system->success - (t->vm->system->load(&lib, name, t->vm->libraries)))) - { - t->vm->libraries = lib; - } else { - object message = makeString(t, "library not found: %s", name); - t->exception = makeRuntimeException(t, message); - } - } else { - t->exception = makeNullPointerException(t); - } -} - void arraycopy(Thread* t, jobject src, jint srcOffset, jobject dst, jint dstOffset, jint length) @@ -108,13 +86,48 @@ arraycopy(Thread* t, jobject src, jint srcOffset, jobject dst, jint dstOffset, } void -gc(Thread* t) +loadLibrary(Thread* t, jobject, jstring nameString) +{ + if (LIKELY(nameString)) { + object n = *nameString; + char name[stringLength(t, n) + 1]; + stringChars(t, n, name); + + for (System::Library* lib = t->vm->libraries; lib; lib = lib->next()) { + if (::strcmp(lib->name(), name) == 0) { + // already loaded + return; + } + } + + System::Library* lib; + if (LIKELY(t->vm->system->success + (t->vm->system->load(&lib, name, t->vm->libraries)))) + { + t->vm->libraries = lib; + } else { + object message = makeString(t, "library not found: %s", name); + t->exception = makeRuntimeException(t, message); + } + } else { + t->exception = makeNullPointerException(t); + } +} + +void +gc(Thread* t, jobject) { ENTER(t, Thread::ExclusiveState); collect(t, Heap::MajorCollection); } +void +exit(Thread* t, jobject, jint code) +{ + t->vm->system->exit(code); +} + jobject trace(Thread* t, jint skipCount) { @@ -224,10 +237,13 @@ populate(Thread* t, object map) } builtins[] = { { "Java_java_lang_System_arraycopy", reinterpret_cast(arraycopy) }, - { "Java_java_lang_System_loadLibrary", + + { "Java_java_lang_Runtime_loadLibrary", reinterpret_cast(loadLibrary) }, - { "Java_java_lang_System_gc", + { "Java_java_lang_Runtime_gc", reinterpret_cast(gc) }, + { "Java_java_lang_Runtiime_exit", + reinterpret_cast(exit) }, { "Java_java_lang_Thread_start", reinterpret_cast(start) }, diff --git a/src/machine.cpp b/src/machine.cpp index 0c45c4b693..ed08d9151b 100644 --- a/src/machine.cpp +++ b/src/machine.cpp @@ -139,6 +139,9 @@ visitRoots(Thread* t, Heap::Visitor* v) void referenceTargetUnreachable(Thread* t, object* p, Heap::Visitor* v) { +// fprintf(stderr, "target %p unreachable for reference %p\n", +// jreferenceTarget(t, *p), *p); + v->visit(p); jreferenceTarget(t, *p) = 0; @@ -166,6 +169,9 @@ referenceTargetUnreachable(Thread* t, object* p, Heap::Visitor* v) void referenceUnreachable(Thread* t, object* p, Heap::Visitor* v) { +// fprintf(stderr, "reference %p unreachable\n", +// *p); + if (jreferenceQueue(t, *p) and t->vm->heap->status(jreferenceQueue(t, *p)) != Heap::Unreachable) { @@ -177,6 +183,9 @@ referenceUnreachable(Thread* t, object* p, Heap::Visitor* v) void referenceTargetReachable(Thread* t, object* p, Heap::Visitor* v) { +// fprintf(stderr, "target %p reachable for reference %p\n", +// jreferenceTarget(t, *p), *p); + v->visit(p); v->visit(&jreferenceTarget(t, *p)); @@ -711,9 +720,10 @@ parseFieldTable(Thread* t, Stream& s, object class_, object pool) object field = makeField (t, + 0, // vm flags + fieldCode(t, byteArrayBody(t, arrayBody(t, pool, spec - 1), 0)), flags, 0, // offset - fieldCode(t, byteArrayBody(t, arrayBody(t, pool, spec - 1), 0)), arrayBody(t, pool, name - 1), arrayBody(t, pool, spec - 1), class_); @@ -914,10 +924,11 @@ parseMethodTable(Thread* t, Stream& s, object class_, object pool) } object method = makeMethod(t, - flags, - 0, // offset + 0, // vm flags parameterCount, parameterFootprint, + flags, + 0, // offset arrayBody(t, pool, name - 1), arrayBody(t, pool, spec - 1), class_, @@ -1791,7 +1802,7 @@ hashMapInsert(Thread* t, object map, object key, object value, PROTECT(t, value); t->vm->weakReferences = makeWeakReference - (t, 0, 0, t->vm->weakReferences, 0); + (t, t->vm->weakReferences, 0, 0, 0); jreferenceTarget(t, t->vm->weakReferences) = key; key = t->vm->weakReferences; } diff --git a/src/run.cpp b/src/run.cpp index 239373fac5..a583077374 100644 --- a/src/run.cpp +++ b/src/run.cpp @@ -91,8 +91,8 @@ make(Thread* t, object class_) ACQUIRE(t, t->vm->referenceLock); - // jreferenceNext(t, r) - cast(instance, 3 * BytesPerWord) = t->vm->weakReferences; + // jreferenceNext(t, instance) + cast(instance, BytesPerWord) = t->vm->weakReferences; t->vm->weakReferences = instance; } diff --git a/src/system.cpp b/src/system.cpp index 2db57b5555..b98477e7e3 100644 --- a/src/system.cpp +++ b/src/system.cpp @@ -236,9 +236,10 @@ class MySystem: public System { class Library: public System::Library { public: - Library(System* s, void* p, System::Library* next): + Library(System* s, void* p, const char* name, System::Library* next): s(s), p(p), + name_(name), next_(next) { } @@ -246,6 +247,10 @@ class MySystem: public System { return dlsym(p, function); } + virtual const char* name() { + return name_; + } + virtual System::Library* next() { return next_; } @@ -260,11 +265,14 @@ class MySystem: public System { if (next_) { next_->dispose(); } + + s->free(name_); s->free(this); } System* s; void* p; + const char* name_; System::Library* next_; }; @@ -359,7 +367,8 @@ class MySystem: public System { const char* name, System::Library* next) { - unsigned size = strlen(name) + 7; + unsigned nameLength = strlen(name); + unsigned size = nameLength + 7; char buffer[size]; snprintf(buffer, size, "lib%s.so", name); @@ -369,13 +378,19 @@ class MySystem: public System { fprintf(stderr, "open %s as %p\n", buffer, p); } - *lib = new (System::allocate(sizeof(Library))) Library(this, p, next); + char* n = static_cast(System::allocate(nameLength + 1)); + memcpy(n, name, nameLength + 1); + *lib = new (System::allocate(sizeof(Library))) Library(this, p, n, next); return 0; } else { return 1; } } + virtual void exit(int code) { + ::exit(code); + } + virtual void abort() { ::abort(); } diff --git a/src/system.h b/src/system.h index 03a3d8275f..f6db4ae5e8 100644 --- a/src/system.h +++ b/src/system.h @@ -49,6 +49,7 @@ class System: public Allocator { public: virtual ~Library() { } virtual void* resolve(const char* function) = 0; + virtual const char* name() = 0; virtual Library* next() = 0; virtual void dispose() = 0; }; @@ -64,6 +65,7 @@ class System: public Allocator { unsigned count, unsigned size, unsigned returnType) = 0; virtual Status load(Library**, const char* name, Library* next) = 0; + virtual void exit(int code) = 0; virtual void abort() = 0; virtual void dispose() = 0; diff --git a/src/types.def b/src/types.def index b97224add7..8025a86036 100644 --- a/src/types.def +++ b/src/types.def @@ -17,19 +17,26 @@ (object staticTable) (object initializer)) -(type field +(type accessibleObject java/lang/reflect/AccessibleObject + (extends jobject)) + +(type field java/lang/reflect/Field + (extends accessibleObject) + (uint8_t vmFlags) + (uint8_t code) (uint16_t flags) (uint16_t offset) - (uint8_t code) (object name) (object spec) (object class)) -(type method +(type method java/lang/reflect/Method + (extends accessibleObject) + (uint8_t vmFlags) + (uint8_t parameterCount) + (uint16_t parameterFootprint) (uint16_t flags) (uint16_t offset) - (uint16_t parameterCount) - (uint16_t parameterFootprint) (object name) (object spec) (object class) @@ -223,9 +230,9 @@ (type jreference java/lang/ref/Reference (extends jobject) + (void* next) (void* target) (void* queue) - (void* next) (object jnext)) (type weakReference java/lang/ref/WeakReference From fd770fd884f3e4beea857578519743966cec5b1f Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Sat, 21 Jul 2007 14:44:39 -0600 Subject: [PATCH 2/5] sketch a few more classpath classes --- classpath/java/lang/Thread.java | 13 ++ classpath/java/lang/ThreadLocal.java | 36 +++ classpath/java/lang/Throwable.java | 4 + classpath/java/lang/reflect/Array.java | 7 + classpath/java/lang/reflect/Constructor.java | 14 +- classpath/java/lang/reflect/Field.java | 12 + .../reflect/InvocationTargetException.java | 19 ++ classpath/java/lang/reflect/Member.java | 12 + classpath/java/lang/reflect/Method.java | 14 +- classpath/java/lang/reflect/Modifier.java | 19 ++ classpath/java/util/HashMap.java | 220 ++++++++++++++++++ classpath/java/util/Map.java | 19 ++ classpath/java/util/WeakHashMap.java | 95 ++++++++ src/builtin.cpp | 8 + src/common.h | 4 - src/machine.cpp | 7 +- src/types.def | 1 + 17 files changed, 497 insertions(+), 7 deletions(-) create mode 100644 classpath/java/lang/ThreadLocal.java create mode 100644 classpath/java/lang/reflect/Array.java create mode 100644 classpath/java/lang/reflect/InvocationTargetException.java create mode 100644 classpath/java/lang/reflect/Member.java create mode 100644 classpath/java/lang/reflect/Modifier.java create mode 100644 classpath/java/util/HashMap.java create mode 100644 classpath/java/util/Map.java create mode 100644 classpath/java/util/WeakHashMap.java diff --git a/classpath/java/lang/Thread.java b/classpath/java/lang/Thread.java index 53ddd25a44..20a95cad01 100644 --- a/classpath/java/lang/Thread.java +++ b/classpath/java/lang/Thread.java @@ -1,7 +1,11 @@ package java.lang; +import java.util.Map; +import java.util.WeakHashMap; + public class Thread implements Runnable { private final Runnable task; + private Map locals; private long peer; public Thread(Runnable task) { @@ -16,6 +20,15 @@ public class Thread implements Runnable { } } + public Map locals() { + if (locals == null) { + locals = new WeakHashMap(); + } + return locals; + } + + public static native Thread currentThread(); + public static native void sleep(long milliseconds) throws InterruptedException; } diff --git a/classpath/java/lang/ThreadLocal.java b/classpath/java/lang/ThreadLocal.java new file mode 100644 index 0000000000..35003edb22 --- /dev/null +++ b/classpath/java/lang/ThreadLocal.java @@ -0,0 +1,36 @@ +package java.lang; + +import java.util.Map; + +public class ThreadLocal { + private static final Object Null = new Object(); + + protected T initialValue() { + return null; + } + + public T get() { + Map map = Thread.currentThread().locals(); + Object o = map.get(this); + if (o == null) { + o = initialValue(); + if (o == null) { + o = Null; + } + map.put(this, o); + } + if (o == Null) { + o = null; + } + return (T) o; + } + + public void set(T value) { + Map map = Thread.currentThread().locals(); + Object o = value; + if (o == null) { + o = Null; + } + map.put(this, o); + } +} diff --git a/classpath/java/lang/Throwable.java b/classpath/java/lang/Throwable.java index f81486d93c..40db7c1d7e 100644 --- a/classpath/java/lang/Throwable.java +++ b/classpath/java/lang/Throwable.java @@ -23,6 +23,10 @@ public class Throwable { this(null, null); } + public Throwable getCause() { + return cause; + } + private static native Object trace(int skipCount); private static native StackTraceElement[] resolveTrace(Object trace); diff --git a/classpath/java/lang/reflect/Array.java b/classpath/java/lang/reflect/Array.java new file mode 100644 index 0000000000..e0eae6a055 --- /dev/null +++ b/classpath/java/lang/reflect/Array.java @@ -0,0 +1,7 @@ +package java.lang.reflect; + +public final class Array { + private Array() { } + + +} diff --git a/classpath/java/lang/reflect/Constructor.java b/classpath/java/lang/reflect/Constructor.java index cba1ec9331..c6eaf2c307 100644 --- a/classpath/java/lang/reflect/Constructor.java +++ b/classpath/java/lang/reflect/Constructor.java @@ -1,6 +1,6 @@ package java.lang.reflect; -public class Constructor extends AccessibleObject { +public class Constructor extends AccessibleObject implements Member { private Method method; private Constructor() { } @@ -17,4 +17,16 @@ public class Constructor extends AccessibleObject { public void setAccessible(boolean v) { method.setAccessible(v); } + + public Class getDeclaringClass() { + return method.getDeclaringClass(); + } + + public int getModifiers() { + return method.getModifiers(); + } + + public String getName() { + return method.getName(); + } } diff --git a/classpath/java/lang/reflect/Field.java b/classpath/java/lang/reflect/Field.java index 9fd11bf112..175f22f287 100644 --- a/classpath/java/lang/reflect/Field.java +++ b/classpath/java/lang/reflect/Field.java @@ -18,4 +18,16 @@ public class Field extends AccessibleObject { public void setAccessible(boolean v) { if (v) vmFlags |= Accessible; else vmFlags &= ~Accessible; } + + public Class getDeclaringClass() { + return class_; + } + + public int getModifiers() { + return flags; + } + + public String getName() { + return new String(name, 0, name.length - 1, false); + } } diff --git a/classpath/java/lang/reflect/InvocationTargetException.java b/classpath/java/lang/reflect/InvocationTargetException.java new file mode 100644 index 0000000000..a67d5c4357 --- /dev/null +++ b/classpath/java/lang/reflect/InvocationTargetException.java @@ -0,0 +1,19 @@ +package java.lang.reflect; + +public class InvocationTargetException extends Exception { + public InvocationTargetException(Throwable targetException, String message) { + super(message, targetException); + } + + public InvocationTargetException(Throwable targetException) { + this(targetException, null); + } + + public InvocationTargetException() { + this(null, null); + } + + public Throwable getTargetException() { + return getCause(); + } +} diff --git a/classpath/java/lang/reflect/Member.java b/classpath/java/lang/reflect/Member.java new file mode 100644 index 0000000000..2c0cd10384 --- /dev/null +++ b/classpath/java/lang/reflect/Member.java @@ -0,0 +1,12 @@ +package java.lang.reflect; + +public interface Member { + public static final int PUBLIC = 0; + public static final int DECLARED = 1; + + public Class getDeclaringClass(); + + public int getModifiers(); + + public String getName(); +} diff --git a/classpath/java/lang/reflect/Method.java b/classpath/java/lang/reflect/Method.java index 4d18a19a0a..236138d439 100644 --- a/classpath/java/lang/reflect/Method.java +++ b/classpath/java/lang/reflect/Method.java @@ -1,6 +1,6 @@ package java.lang.reflect; -public class Method extends AccessibleObject { +public class Method extends AccessibleObject implements Member { private byte vmFlags; private byte parameterCount; private short parameterFootprint; @@ -20,4 +20,16 @@ public class Method extends AccessibleObject { public void setAccessible(boolean v) { if (v) vmFlags |= Accessible; else vmFlags &= ~Accessible; } + + public Class getDeclaringClass() { + return class_; + } + + public int getModifiers() { + return flags; + } + + public String getName() { + return new String(name, 0, name.length - 1, false); + } } diff --git a/classpath/java/lang/reflect/Modifier.java b/classpath/java/lang/reflect/Modifier.java new file mode 100644 index 0000000000..033bf0e464 --- /dev/null +++ b/classpath/java/lang/reflect/Modifier.java @@ -0,0 +1,19 @@ +package java.lang.reflect; + +public final class Modifier { + public static final int PUBLIC = 1 << 0; + public static final int PRIVATE = 1 << 1; + public static final int PROTECTED = 1 << 2; + public static final int STATIC = 1 << 3; + public static final int FINAL = 1 << 4; + public static final int SUPER = 1 << 5; + public static final int SYNCHRONIZED = SUPER; + public static final int VOLATILE = 1 << 6; + public static final int TRANSIENT = 1 << 7; + public static final int NATIVE = 1 << 8; + public static final int INTERFACE = 1 << 9; + public static final int ABSTRACT = 1 << 10; + public static final int STRICT = 1 << 11; + + private Modifier() { } +} diff --git a/classpath/java/util/HashMap.java b/classpath/java/util/HashMap.java new file mode 100644 index 0000000000..5eff151671 --- /dev/null +++ b/classpath/java/util/HashMap.java @@ -0,0 +1,220 @@ +package java.util; + +public class HashMap implements Map { + private int size; + private Cell[] array; + private Cell nullCell; + private final CellFactory factory; + + HashMap(int capacity, CellFactory factory) { + if (capacity > 0) { + array = new Cell[nextPowerOfTwo(capacity)]; + } + this.factory = factory; + } + + public HashMap(int capacity) { + this(capacity, new MyCellFactory()); + } + + public HashMap() { + this(0); + } + + private static int nextPowerOfTwo(int n) { + int r = 1; + while (r < n) r <<= 1; + return r; + } + + public int size() { + return size; + } + + private void resize() { + if (array == null || size >= array.length * 2) { + resize(array == null ? 16 : array.length * 2); + } else if (size <= array.length / 3) { + resize(array.length / 2); + } + } + + private void resize(int capacity) { + Cell[] newArray = null; + if (capacity != 0) { + capacity = nextPowerOfTwo(capacity); + if (array != null && array.length == capacity) { + return; + } + + newArray = new Cell[capacity]; + if (array != null) { + for (int i = 0; i < array.length; ++i) { + Cell next; + for (Cell c = array[i]; c != null; c = next) { + next = c.next(); + int index = c.getKey().hashCode() & (capacity - 1); + c.setNext(array[index]); + array[index] = c; + } + } + } + } + array = newArray; + } + + private Cell find(K key) { + if (key == null) { + return nullCell; + } else { + if (array != null) { + int index = key.hashCode() & (array.length - 1); + for (Cell c = array[index]; c != null; c = c.next()) { + if (key.equals(c.getKey())) { + return c; + } + } + } + + return null; + } + } + + private void insert(Cell cell) { + ++ size; + + if (cell.getKey() == null) { + nullCell = cell; + } else { + resize(); + + int index = cell.hashCode() & (array.length - 1); + cell.setNext(array[index]); + array[index] = cell; + } + } + + // primarily for use by WeakHashMap: + void remove(Cell cell) { + if (cell == nullCell) { + nullCell = null; + -- size; + } else { + int index = cell.hashCode() & (array.length - 1); + Cell p = null; + for (Cell c = array[index]; c != null; c = c.next()) { + if (c == cell) { + if (p == null) { + array[index] = c.next(); + } else { + p.setNext(c.next()); + } + -- size; + break; + } + } + + resize(); + } + } + + public V get(K key) { + Cell c = find(key); + return (c == null ? null : c.getValue()); + } + + public V put(K key, V value) { + Cell c = find(key); + if (c == null) { + insert(factory.make(key, value, null)); + return null; + } else { + V old = c.getValue(); + c.setValue(value); + return old; + } + } + + public V remove(K key) { + V old = null; + if (key == null) { + if (nullCell != null) { + old = nullCell.getValue(); + nullCell = null; + -- size; + } + } else { + if (array != null) { + int index = key.hashCode() & (array.length - 1); + Cell p = null; + for (Cell c = array[index]; c != null; c = c.next()) { + if (key.equals(c.getKey())) { + old = c.getValue(); + if (p == null) { + array[index] = c.next(); + } else { + p.setNext(c.next()); + } + -- size; + break; + } + } + + resize(); + } + } + return old; + } + + interface Cell extends Entry { + public HashMap.Cell next(); + + public void setNext(HashMap.Cell next); + } + + interface CellFactory { + public Cell make(K key, V value, Cell next); + } + + private static class MyCell implements Cell { + public final K key; + public V value; + public Cell next; + + public MyCell(K key, V value, Cell next) { + this.key = key; + this.value = value; + this.next = next; + } + + public K getKey() { + return key; + } + + public V getValue() { + return value; + } + + public void setValue(V value) { + this.value = value; + } + + public HashMap.Cell next() { + return next; + } + + public void setNext(HashMap.Cell next) { + this.next = next; + } + + public int hashCode() { + return key.hashCode(); + } + } + + private static class MyCellFactory implements CellFactory { + public Cell make(K key, V value, Cell next) { + return new MyCell(key, value, next); + } + } +} diff --git a/classpath/java/util/Map.java b/classpath/java/util/Map.java new file mode 100644 index 0000000000..2be7083a45 --- /dev/null +++ b/classpath/java/util/Map.java @@ -0,0 +1,19 @@ +package java.util; + +public interface Map { + public int size(); + + public V get(K key); + + public V put(K key, V value); + + public V remove(K key); + + public interface Entry { + public K getKey(); + + public V getValue(); + + public void setValue(V value); + } +} diff --git a/classpath/java/util/WeakHashMap.java b/classpath/java/util/WeakHashMap.java new file mode 100644 index 0000000000..716ab340f8 --- /dev/null +++ b/classpath/java/util/WeakHashMap.java @@ -0,0 +1,95 @@ +package java.util; + +import java.lang.ref.ReferenceQueue; +import java.lang.ref.Reference; +import java.lang.ref.WeakReference; + +public class WeakHashMap implements Map { + private final HashMap map; + private final ReferenceQueue queue; + + public WeakHashMap(int capacity) { + map = new HashMap(capacity, new MyCellFactory()); + queue = new ReferenceQueue(); + } + + public WeakHashMap() { + this(0); + } + + private void poll() { + for (MyCell c = (MyCell) queue.poll(); + c != null; + c = (MyCell) queue.poll()) + { + map.remove(c); + } + } + + public int size() { + return map.size(); + } + + public V get(K key) { + poll(); + return map.get(key); + } + + public V put(K key, V value) { + poll(); + return map.put(key, value); + } + + public V remove(K key) { + poll(); + return map.remove(key); + } + + private static class MyCell + extends WeakReference + implements HashMap.Cell + { + public V value; + public HashMap.Cell next; + public int hashCode; + + public MyCell(K key, V value, HashMap.Cell next) { + super(key); + this.value = value; + this.next = next; + this.hashCode = key.hashCode(); + } + + public K getKey() { + return get(); + } + + public V getValue() { + return value; + } + + public void setValue(V value) { + this.value = value; + } + + public HashMap.Cell next() { + return next; + } + + public void setNext(HashMap.Cell next) { + this.next = next; + } + + public int hashCode() { + return hashCode; + } + } + + private static class MyCellFactory + implements HashMap.CellFactory + { + public HashMap.Cell make(K key, V value, HashMap.Cell next) { + return new MyCell(key, value, next); + } + } +} diff --git a/src/builtin.cpp b/src/builtin.cpp index 5f8a9dd60d..89096d9ab9 100644 --- a/src/builtin.cpp +++ b/src/builtin.cpp @@ -41,6 +41,12 @@ notifyAll(Thread* t, jobject this_) vm::notifyAll(t, *this_); } +jobject +currentThread(Thread* t) +{ + return pushReference(t, t->javaThread); +} + void sleep(Thread* t, jlong milliseconds) { @@ -247,6 +253,8 @@ populate(Thread* t, object map) { "Java_java_lang_Thread_start", reinterpret_cast(start) }, + { "Java_java_lang_Thread_currentThread", + reinterpret_cast(currentThread) }, { "Java_java_lang_Thread_sleep", reinterpret_cast(sleep) }, diff --git a/src/common.h b/src/common.h index 76d6473a60..b7fd62dd16 100644 --- a/src/common.h +++ b/src/common.h @@ -1,8 +1,6 @@ #ifndef COMMON_H #define COMMON_H - - #include "stdint.h" #include "stdlib.h" #include "stdarg.h" @@ -29,8 +27,6 @@ inline void* operator new(size_t, void* p) throw() { return p; } - - namespace vm { typedef void* object; diff --git a/src/machine.cpp b/src/machine.cpp index ed08d9151b..e5268e293b 100644 --- a/src/machine.cpp +++ b/src/machine.cpp @@ -1382,7 +1382,7 @@ Thread::Thread(Machine* m, Allocator* allocator, object javaThread, builtin::populate(t, m->builtinMap); - javaThread = makeThread(t, 0, reinterpret_cast(t)); + javaThread = makeThread(t, 0, 0, reinterpret_cast(t)); } else { threadPeer(this, javaThread) = reinterpret_cast(this); parent->child = this; @@ -1749,6 +1749,10 @@ hashMapResize(Thread* t, object map, uint32_t (*hash)(Thread*, object), PROTECT(t, oldArray); unsigned newLength = nextPowerOfTwo(size); + if (oldArray and arrayLength(t, oldArray) == newLength) { + return; + } + newArray = makeArray(t, newLength, true); if (oldArray) { @@ -1832,6 +1836,7 @@ hashMapRemove(Thread* t, object map, object key, o = tripleSecond(t, *n); set(t, *n, tripleThird(t, *n)); -- hashMapSize(t, map); + break; } else { n = &tripleThird(t, *n); } diff --git a/src/types.def b/src/types.def index 8025a86036..cb2d124737 100644 --- a/src/types.def +++ b/src/types.def @@ -127,6 +127,7 @@ (type thread java/lang/Thread (extends jobject) (object task) + (object locals) (int64_t peer)) (type stackTraceElement java/lang/StackTraceElement From 90d60b34590075a143097c89c02094b8209778b5 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Sat, 21 Jul 2007 16:36:51 -0600 Subject: [PATCH 3/5] more classpath classes --- .../java/lang/IllegalStateException.java | 19 +++ .../java/lang/InheritableThreadLocal.java | 9 ++ classpath/java/lang/Iterable.java | 7 + classpath/java/lang/Thread.java | 15 +- classpath/java/util/Collection.java | 11 ++ classpath/java/util/HashMap.java | 134 +++++++++++++++--- classpath/java/util/HashSet.java | 55 +++++++ classpath/java/util/Iterator.java | 9 ++ classpath/java/util/Map.java | 4 + .../java/util/NoSuchElementException.java | 11 ++ classpath/java/util/Set.java | 3 + classpath/java/util/WeakHashMap.java | 8 ++ src/builtin.cpp | 2 +- 13 files changed, 269 insertions(+), 18 deletions(-) create mode 100644 classpath/java/lang/IllegalStateException.java create mode 100644 classpath/java/lang/InheritableThreadLocal.java create mode 100644 classpath/java/lang/Iterable.java create mode 100644 classpath/java/util/Collection.java create mode 100644 classpath/java/util/HashSet.java create mode 100644 classpath/java/util/Iterator.java create mode 100644 classpath/java/util/NoSuchElementException.java create mode 100644 classpath/java/util/Set.java diff --git a/classpath/java/lang/IllegalStateException.java b/classpath/java/lang/IllegalStateException.java new file mode 100644 index 0000000000..c111a55398 --- /dev/null +++ b/classpath/java/lang/IllegalStateException.java @@ -0,0 +1,19 @@ +package java.lang; + +public class IllegalStateException extends RuntimeException { + public IllegalStateException(String message, Throwable cause) { + super(message, cause); + } + + public IllegalStateException(String message) { + this(message, null); + } + + public IllegalStateException(Throwable cause) { + this(null, cause); + } + + public IllegalStateException() { + this(null, null); + } +} diff --git a/classpath/java/lang/InheritableThreadLocal.java b/classpath/java/lang/InheritableThreadLocal.java new file mode 100644 index 0000000000..826f749cd3 --- /dev/null +++ b/classpath/java/lang/InheritableThreadLocal.java @@ -0,0 +1,9 @@ +package java.lang; + +import java.util.Map; + +public class InheritableThreadLocal extends ThreadLocal { + protected T childValue(T parentValue) { + return parentValue; + } +} diff --git a/classpath/java/lang/Iterable.java b/classpath/java/lang/Iterable.java new file mode 100644 index 0000000000..26cc2e112e --- /dev/null +++ b/classpath/java/lang/Iterable.java @@ -0,0 +1,7 @@ +package java.lang; + +import java.util.Iterator; + +public interface Iterable { + public Iterator iterator(); +} diff --git a/classpath/java/lang/Thread.java b/classpath/java/lang/Thread.java index 20a95cad01..5bd884f04e 100644 --- a/classpath/java/lang/Thread.java +++ b/classpath/java/lang/Thread.java @@ -12,7 +12,20 @@ public class Thread implements Runnable { this.task = task; } - public synchronized native void start(); + public synchronized void start() { + Map map = currentThread().locals; + if (map != null) { + for (Map.Entry e: map.entrySet()) { + if (e.getKey() instanceof InheritableThreadLocal) { + locals().put(e.getKey(), e.getValue()); + } + } + } + + doStart(); + } + + private native void doStart(); public void run() { if (task != null) { diff --git a/classpath/java/util/Collection.java b/classpath/java/util/Collection.java new file mode 100644 index 0000000000..1a79f11c62 --- /dev/null +++ b/classpath/java/util/Collection.java @@ -0,0 +1,11 @@ +package java.util; + +public interface Collection extends Iterable { + public int size(); + + public boolean add(T entry); + + public boolean remove(T entry); + + public void clear(); +} diff --git a/classpath/java/util/HashMap.java b/classpath/java/util/HashMap.java index 5eff151671..abe6a3b96e 100644 --- a/classpath/java/util/HashMap.java +++ b/classpath/java/util/HashMap.java @@ -118,28 +118,27 @@ public class HashMap implements Map { } } + private Cell putCell(K key, V value) { + Cell c = find(key); + if (c == null) { + insert(factory.make(key, value, null)); + } else { + V old = c.getValue(); + c.setValue(value); + } + return c; + } + public V get(K key) { Cell c = find(key); return (c == null ? null : c.getValue()); } - public V put(K key, V value) { - Cell c = find(key); - if (c == null) { - insert(factory.make(key, value, null)); - return null; - } else { - V old = c.getValue(); - c.setValue(value); - return old; - } - } - - public V remove(K key) { - V old = null; + public Cell removeCell(K key) { + Cell old = null; if (key == null) { if (nullCell != null) { - old = nullCell.getValue(); + old = nullCell; nullCell = null; -- size; } @@ -149,7 +148,7 @@ public class HashMap implements Map { Cell p = null; for (Cell c = array[index]; c != null; c = c.next()) { if (key.equals(c.getKey())) { - old = c.getValue(); + old = c; if (p == null) { array[index] = c.next(); } else { @@ -166,6 +165,28 @@ public class HashMap implements Map { return old; } + public V put(K key, V value) { + Cell c = putCell(key, value); + return (c == null ? null : c.getValue()); + } + + public V remove(K key) { + Cell c = removeCell(key); + return (c == null ? null : c.getValue()); + } + + public void clear() { + array = null; + } + + public Set> entrySet() { + return new MySet(); + } + + Iterator> iterator() { + return new MyIterator(); + } + interface Cell extends Entry { public HashMap.Cell next(); @@ -217,4 +238,85 @@ public class HashMap implements Map { return new MyCell(key, value, next); } } + + private class MySet implements Set> { + public int size() { + return HashMap.this.size(); + } + + public boolean add(Entry e) { + return putCell(e.getKey(), e.getValue()) != null; + } + + public boolean remove(Entry e) { + return removeCell(e.getKey()) != null; + } + + public void clear() { + HashMap.this.clear(); + } + + public Iterator> iterator() { + return new MyIterator(); + } + } + + private class MyIterator implements Iterator> { + private int currentIndex = -1; + private int nextIndex = -1; + private Cell previousCell; + private Cell currentCell; + private Cell nextCell; + + public MyIterator() { + hasNext(); + } + + public Entry next() { + if (hasNext()) { + if (currentCell != null && currentCell.next() != null) { + previousCell = currentCell; + } else { + previousCell = null; + } + + currentCell = nextCell; + currentIndex = nextIndex; + + nextCell = nextCell.next(); + + return currentCell; + } else { + throw new NoSuchElementException(); + } + } + + public boolean hasNext() { + if (array != null) { + while (nextCell == null && ++ nextIndex < array.length) { + if (array[nextIndex] != null) { + nextCell = array[nextIndex]; + return true; + } + } + } + return false; + } + + public void remove() { + if (currentCell != null) { + if (previousCell == null) { + array[currentIndex] = currentCell.next(); + } else { + previousCell.setNext(currentCell.next()); + if (previousCell.next() == null) { + previousCell = null; + } + } + currentCell = null; + } else { + throw new IllegalStateException(); + } + } + } } diff --git a/classpath/java/util/HashSet.java b/classpath/java/util/HashSet.java new file mode 100644 index 0000000000..c685417db6 --- /dev/null +++ b/classpath/java/util/HashSet.java @@ -0,0 +1,55 @@ +package java.util; + +public class HashSet implements Set { + private static final Object Value = new Object(); + + private final HashMap map; + + public HashSet(int capacity) { + map = new HashMap(capacity); + } + + public HashSet() { + this(0); + } + + public int size() { + return map.size(); + } + + public boolean add(T element) { + return map.put(element, Value) != Value; + } + + public boolean remove(T element) { + return map.remove(element) != Value; + } + + public void clear() { + map.clear(); + } + + public Iterator iterator() { + return new MyIterator(map.iterator()); + } + + private static class MyIterator implements Iterator { + private final Iterator> it; + + public MyIterator(Iterator> it) { + this.it = it; + } + + public T next() { + return it.next().getKey(); + } + + public boolean hasNext() { + return it.hasNext(); + } + + public void remove() { + it.remove(); + } + } +} diff --git a/classpath/java/util/Iterator.java b/classpath/java/util/Iterator.java new file mode 100644 index 0000000000..c0e611d5af --- /dev/null +++ b/classpath/java/util/Iterator.java @@ -0,0 +1,9 @@ +package java.util; + +public interface Iterator { + public T next(); + + public boolean hasNext(); + + public void remove(); +} diff --git a/classpath/java/util/Map.java b/classpath/java/util/Map.java index 2be7083a45..03c632a307 100644 --- a/classpath/java/util/Map.java +++ b/classpath/java/util/Map.java @@ -9,6 +9,10 @@ public interface Map { public V remove(K key); + public void clear(); + + public Set> entrySet(); + public interface Entry { public K getKey(); diff --git a/classpath/java/util/NoSuchElementException.java b/classpath/java/util/NoSuchElementException.java new file mode 100644 index 0000000000..cf7e19d7f4 --- /dev/null +++ b/classpath/java/util/NoSuchElementException.java @@ -0,0 +1,11 @@ +package java.util; + +public class NoSuchElementException extends RuntimeException { + public NoSuchElementException(String message) { + super(message); + } + + public NoSuchElementException() { + super(); + } +} diff --git a/classpath/java/util/Set.java b/classpath/java/util/Set.java new file mode 100644 index 0000000000..d01a5ec704 --- /dev/null +++ b/classpath/java/util/Set.java @@ -0,0 +1,3 @@ +package java.util; + +public interface Set extends Collection { } diff --git a/classpath/java/util/WeakHashMap.java b/classpath/java/util/WeakHashMap.java index 716ab340f8..08050b1aaa 100644 --- a/classpath/java/util/WeakHashMap.java +++ b/classpath/java/util/WeakHashMap.java @@ -45,6 +45,14 @@ public class WeakHashMap implements Map { return map.remove(key); } + public void clear() { + map.clear(); + } + + public Set> entrySet() { + return map.entrySet(); + } + private static class MyCell extends WeakReference implements HashMap.Cell diff --git a/src/builtin.cpp b/src/builtin.cpp index 89096d9ab9..1bfeb5b596 100644 --- a/src/builtin.cpp +++ b/src/builtin.cpp @@ -251,7 +251,7 @@ populate(Thread* t, object map) { "Java_java_lang_Runtiime_exit", reinterpret_cast(exit) }, - { "Java_java_lang_Thread_start", + { "Java_java_lang_Thread_doStart", reinterpret_cast(start) }, { "Java_java_lang_Thread_currentThread", reinterpret_cast(currentThread) }, From da17490206960873f0c609ec9858a3077044d680 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Sat, 21 Jul 2007 21:47:08 -0600 Subject: [PATCH 4/5] fun with collections --- classpath/java/util/Collection.java | 4 +- classpath/java/util/HashMap.java | 98 ++++++++++++++++++++++++++++- classpath/java/util/Map.java | 4 ++ src/builtin.cpp | 12 +++- 4 files changed, 111 insertions(+), 7 deletions(-) diff --git a/classpath/java/util/Collection.java b/classpath/java/util/Collection.java index 1a79f11c62..a39e1f8344 100644 --- a/classpath/java/util/Collection.java +++ b/classpath/java/util/Collection.java @@ -3,9 +3,9 @@ package java.util; public interface Collection extends Iterable { public int size(); - public boolean add(T entry); + public boolean add(T element); - public boolean remove(T entry); + public boolean remove(T element); public void clear(); } diff --git a/classpath/java/util/HashMap.java b/classpath/java/util/HashMap.java index abe6a3b96e..77ecae8a02 100644 --- a/classpath/java/util/HashMap.java +++ b/classpath/java/util/HashMap.java @@ -177,10 +177,19 @@ public class HashMap implements Map { public void clear() { array = null; + size = 0; } public Set> entrySet() { - return new MySet(); + return new EntrySet(); + } + + public Set keySet() { + return new KeySet(); + } + + public Collection values() { + return new Values(); } Iterator> iterator() { @@ -239,7 +248,7 @@ public class HashMap implements Map { } } - private class MySet implements Set> { + private class EntrySet implements Set> { public int size() { return HashMap.this.size(); } @@ -261,6 +270,51 @@ public class HashMap implements Map { } } + private class KeySet implements Set { + public int size() { + return HashMap.this.size(); + } + + public boolean add(K key) { + return putCell(key, null) != null; + } + + public boolean remove(K key) { + return removeCell(key) != null; + } + + public void clear() { + HashMap.this.clear(); + } + + public Iterator iterator() { + return new KeyIterator(new MyIterator()); + } + } + + + private class Values implements Collection { + public int size() { + return HashMap.this.size(); + } + + public boolean add(V value) { + throw new UnsupportedOperationException(); + } + + public boolean remove(V value) { + throw new UnsupportedOperationException(); + } + + public void clear() { + HashMap.this.clear(); + } + + public Iterator iterator() { + return new ValueIterator(new MyIterator()); + } + } + private class MyIterator implements Iterator> { private int currentIndex = -1; private int nextIndex = -1; @@ -319,4 +373,44 @@ public class HashMap implements Map { } } } + + private static class KeyIterator implements Iterator { + private final Iterator> it; + + public KeyIterator(Iterator> it) { + this.it = it; + } + + public K next() { + return it.next().getKey(); + } + + public boolean hasNext() { + return it.hasNext(); + } + + public void remove() { + it.remove(); + } + } + + private static class ValueIterator implements Iterator { + private final Iterator> it; + + public ValueIterator(Iterator> it) { + this.it = it; + } + + public V next() { + return it.next().getValue(); + } + + public boolean hasNext() { + return it.hasNext(); + } + + public void remove() { + it.remove(); + } + } } diff --git a/classpath/java/util/Map.java b/classpath/java/util/Map.java index 03c632a307..b6de098b3f 100644 --- a/classpath/java/util/Map.java +++ b/classpath/java/util/Map.java @@ -13,6 +13,10 @@ public interface Map { public Set> entrySet(); + public Set keySet(); + + public Collection values(); + public interface Entry { public K getKey(); diff --git a/src/builtin.cpp b/src/builtin.cpp index 1bfeb5b596..6eabd1cb8c 100644 --- a/src/builtin.cpp +++ b/src/builtin.cpp @@ -76,9 +76,15 @@ arraycopy(Thread* t, jobject src, jint srcOffset, jobject dst, jint dstOffset, { uint8_t* sbody = &cast(s, 2 * BytesPerWord); uint8_t* dbody = &cast(d, 2 * BytesPerWord); - memcpy(dbody + (dstOffset * elementSize), - sbody + (srcOffset * elementSize), - length * elementSize); + if (src == dst) { + memmove(dbody + (dstOffset * elementSize), + sbody + (srcOffset * elementSize), + length * elementSize); + } else { + memcpy(dbody + (dstOffset * elementSize), + sbody + (srcOffset * elementSize), + length * elementSize); + } return; } } From ecd31a10a457d21cb0610c60fb469b943f53e66d Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Sat, 21 Jul 2007 21:47:29 -0600 Subject: [PATCH 5/5] fun with collections --- .../java/lang/IndexOutOfBoundsException.java | 19 +++ .../lang/UnsupportedOperationException.java | 19 +++ classpath/java/util/ArrayList.java | 95 ++++++++++++ classpath/java/util/Arrays.java | 37 +++++ classpath/java/util/Collections.java | 114 ++++++++++++++ classpath/java/util/Enumeration.java | 7 + classpath/java/util/Hashtable.java | 54 +++++++ classpath/java/util/LinkedList.java | 140 ++++++++++++++++++ classpath/java/util/List.java | 7 + classpath/java/util/Stack.java | 20 +++ classpath/java/util/Vector.java | 54 +++++++ 11 files changed, 566 insertions(+) create mode 100644 classpath/java/lang/IndexOutOfBoundsException.java create mode 100644 classpath/java/lang/UnsupportedOperationException.java create mode 100644 classpath/java/util/ArrayList.java create mode 100644 classpath/java/util/Arrays.java create mode 100644 classpath/java/util/Collections.java create mode 100644 classpath/java/util/Enumeration.java create mode 100644 classpath/java/util/Hashtable.java create mode 100644 classpath/java/util/LinkedList.java create mode 100644 classpath/java/util/List.java create mode 100644 classpath/java/util/Stack.java create mode 100644 classpath/java/util/Vector.java diff --git a/classpath/java/lang/IndexOutOfBoundsException.java b/classpath/java/lang/IndexOutOfBoundsException.java new file mode 100644 index 0000000000..4110743c12 --- /dev/null +++ b/classpath/java/lang/IndexOutOfBoundsException.java @@ -0,0 +1,19 @@ +package java.lang; + +public class IndexOutOfBoundsException extends RuntimeException { + public IndexOutOfBoundsException(String message, Throwable cause) { + super(message, cause); + } + + public IndexOutOfBoundsException(String message) { + this(message, null); + } + + public IndexOutOfBoundsException(Throwable cause) { + this(null, cause); + } + + public IndexOutOfBoundsException() { + this(null, null); + } +} diff --git a/classpath/java/lang/UnsupportedOperationException.java b/classpath/java/lang/UnsupportedOperationException.java new file mode 100644 index 0000000000..29acff4929 --- /dev/null +++ b/classpath/java/lang/UnsupportedOperationException.java @@ -0,0 +1,19 @@ +package java.lang; + +public class UnsupportedOperationException extends RuntimeException { + public UnsupportedOperationException(String message, Throwable cause) { + super(message, cause); + } + + public UnsupportedOperationException(String message) { + this(message, null); + } + + public UnsupportedOperationException(Throwable cause) { + this(null, cause); + } + + public UnsupportedOperationException() { + this(null, null); + } +} diff --git a/classpath/java/util/ArrayList.java b/classpath/java/util/ArrayList.java new file mode 100644 index 0000000000..60121ee9b7 --- /dev/null +++ b/classpath/java/util/ArrayList.java @@ -0,0 +1,95 @@ +package java.util; + +public class ArrayList implements List { + private Object[] array; + private int size; + + public ArrayList(int capacity) { + if (capacity != 0) { + array = new Object[capacity]; + } + } + + public ArrayList() { + this(0); + } + + private void resize() { + if (array == null || size >= array.length - 1) { + resize(array == null ? 16 : array.length * 2); + } else if (size <= array.length / 3) { + resize(array.length / 2); + } + } + + private void resize(int capacity) { + Object[] newArray = null; + if (capacity != 0) { + if (array != null && array.length == capacity) { + return; + } + + newArray = new Object[capacity]; + if (array != null) { + System.arraycopy(array, 0, newArray, 0, size); + } + } + array = newArray; + } + + private static boolean equal(Object a, Object b) { + return (a == null && b == null) || (a != null && a.equals(b)); + } + + public int size() { + return size; + } + + public boolean add(T element) { + resize(); + array[size++] = element; + return true; + } + + public T get(int index) { + if (index >= 0 && index < size) { + return (T) array[index]; + } else { + throw new IndexOutOfBoundsException(index + " not in [0, " + size + ")"); + } + } + + public T remove(int index) { + T v = get(index); + + if (index == size - 1) { + array[index] = null; + } else { + System.arraycopy(array, index + 1, array, index, size - index); + } + + -- size; + resize(); + + return v; + } + + public boolean remove(T element) { + for (int i = 0; i < size; ++i) { + if (equal(element, array[i])) { + remove(i); + return true; + } + } + return false; + } + + public void clear() { + array = null; + size = 0; + } + + public Iterator iterator() { + return new Collections.ArrayListIterator(this); + } +} diff --git a/classpath/java/util/Arrays.java b/classpath/java/util/Arrays.java new file mode 100644 index 0000000000..b1ca3f103d --- /dev/null +++ b/classpath/java/util/Arrays.java @@ -0,0 +1,37 @@ +package java.util; + +public class Arrays { + private Arrays() { } + + public static List asList(final T ... array) { + return new List() { + public int size() { + return array.length; + } + + public boolean add(T element) { + throw new UnsupportedOperationException(); + } + + public T get(int index) { + return array[index]; + } + + public T remove(int index) { + throw new UnsupportedOperationException(); + } + + public boolean remove(T element) { + throw new UnsupportedOperationException(); + } + + public void clear() { + throw new UnsupportedOperationException(); + } + + public Iterator iterator() { + return new Collections.ArrayListIterator(this); + } + }; + } +} diff --git a/classpath/java/util/Collections.java b/classpath/java/util/Collections.java new file mode 100644 index 0000000000..e7f7352c1f --- /dev/null +++ b/classpath/java/util/Collections.java @@ -0,0 +1,114 @@ +package java.util; + +public class Collections { + private Collections() { } + + static class IteratorEnumeration implements Enumeration { + private final Iterator it; + + public IteratorEnumeration(Iterator it) { + this.it = it; + } + + public T nextElement() { + return it.next(); + } + + public boolean hasMoreElements() { + return it.hasNext(); + } + } + + static class SynchronizedCollection implements Collection { + private final Object lock; + private final Collection collection; + + public SynchronizedCollection(Object lock, Collection collection) { + this.lock = lock; + this.collection = collection; + } + + public synchronized int size() { + synchronized (lock) { return collection.size(); } + } + + public synchronized boolean add(T e) { + synchronized (lock) { return collection.add(e); } + } + + public synchronized boolean remove(T e) { + synchronized (lock) { return collection.remove(e); } + } + + public synchronized void clear() { + synchronized (lock) { collection.clear(); } + } + + public Iterator iterator() { + return new SynchronizedIterator(lock, collection.iterator()); + } + } + + static class SynchronizedSet + extends SynchronizedCollection + implements Set + { + public SynchronizedSet(Object lock, Set set) { + super(lock, set); + } + } + + static class SynchronizedIterator implements Iterator { + private final Object lock; + private final Iterator it; + + public SynchronizedIterator(Object lock, Iterator it) { + this.lock = lock; + this.it = it; + } + + public T next() { + synchronized (lock) { return it.next(); } + } + + public boolean hasNext() { + synchronized (lock) { return it.hasNext(); } + } + + public void remove() { + synchronized (lock) { it.remove(); } + } + } + + static class ArrayListIterator implements Iterator { + private final List list; + private boolean canRemove = false; + private int index = -1; + + public ArrayListIterator(List list) { + this.list = list; + } + + public T next() { + if (hasNext()) { + canRemove = true; + return list.get(++index); + } else { + throw new NoSuchElementException(); + } + } + + public boolean hasNext() { + return index + 1 < list.size(); + } + + public void remove() { + if (canRemove) { + canRemove = false; + list.remove(index--); + } else { + throw new IllegalStateException(); + } + } + } +} diff --git a/classpath/java/util/Enumeration.java b/classpath/java/util/Enumeration.java new file mode 100644 index 0000000000..26399b5f43 --- /dev/null +++ b/classpath/java/util/Enumeration.java @@ -0,0 +1,7 @@ +package java.util; + +public interface Enumeration { + public T nextElement(); + + public boolean hasMoreElements(); +} diff --git a/classpath/java/util/Hashtable.java b/classpath/java/util/Hashtable.java new file mode 100644 index 0000000000..5dd443ceaf --- /dev/null +++ b/classpath/java/util/Hashtable.java @@ -0,0 +1,54 @@ +package java.util; + +public class Hashtable implements Map { + private final HashMap map; + + public Hashtable(int capacity) { + map = new HashMap(capacity); + } + + public Hashtable() { + this(0); + } + + public synchronized int size() { + return map.size(); + } + + public synchronized V get(K key) { + return map.get(key); + } + + public synchronized V put(K key, V value) { + return map.put(key, value); + } + + public synchronized V remove(K key) { + return map.remove(key); + } + + public synchronized void clear() { + map.clear(); + } + + public Enumeration keys() { + return new Collections.IteratorEnumeration(keySet().iterator()); + } + + public Enumeration elements() { + return new Collections.IteratorEnumeration(values().iterator()); + } + + public Set> entrySet() { + return new Collections.SynchronizedSet(this, map.entrySet()); + } + + public Set keySet() { + return new Collections.SynchronizedSet(this, map.keySet()); + } + + public Collection values() { + return new Collections.SynchronizedCollection(this, map.values()); + } + +} diff --git a/classpath/java/util/LinkedList.java b/classpath/java/util/LinkedList.java new file mode 100644 index 0000000000..7fc1bd7e2c --- /dev/null +++ b/classpath/java/util/LinkedList.java @@ -0,0 +1,140 @@ +package java.util; + +public class LinkedList implements List { + private Cell front; + private Cell rear; + private int size; + + private Cell find(int index) { + int i = 0; + for (Cell c = front; c != null; c = c.next) { + if (i == index) { + return c; + } + ++ i; + } + throw new IndexOutOfBoundsException(index + " not in [0, " + size + ")"); + } + + private static boolean equal(Object a, Object b) { + return (a == null && b == null) || (a != null && a.equals(b)); + } + + private void add(Cell c) { + ++ size; + + if (front == null) { + front = rear = c; + } else { + c.prev = rear; + rear = c; + } + } + + private Cell find(T element) { + for (Cell c = front; c != null; c = c.next) { + if (equal(c.value, element)) { + return c; + } + } + return null; + } + + private void remove(Cell c) { + -- size; + + if (c.prev == null) { + front = c.next; + } else { + c.prev.next = c.next; + } + + if (c.next == null) { + rear = c.prev; + } else { + c.next.prev = c.prev; + } + } + + public int size() { + return size; + } + + public boolean add(T element) { + add(new Cell(element, null, null)); + return true; + } + + public T get(int index) { + return find(index).value; + } + + public T remove(int index) { + Cell c = find(index); + remove(c); + return c.value; + } + + public boolean remove(T element) { + Cell c = find(element); + if (c == null) { + return false; + } else { + remove(c); + return true; + } + } + + public void clear() { + front = rear = null; + size = 0; + } + + public Iterator iterator() { + return new MyIterator(front); + } + + private static class Cell { + public T value; + public Cell prev; + public Cell next; + + public Cell(T value, Cell prev, Cell next) { + this.value = value; + this.prev = prev; + this.next = next; + } + } + + private class MyIterator implements Iterator { + private Cell current; + private Cell next; + + public MyIterator(Cell start) { + next = start; + } + + public T next() { + if (hasNext()) { + current = next; + next = next.next; + return current.value; + } else { + throw new NoSuchElementException(); + } + } + + public boolean hasNext() { + return next != null; + } + + public void remove() { + if (current != null) { + LinkedList.this.remove(current); + current = null; + } else { + throw new IllegalStateException(); + } + } + } +} diff --git a/classpath/java/util/List.java b/classpath/java/util/List.java new file mode 100644 index 0000000000..d23084f657 --- /dev/null +++ b/classpath/java/util/List.java @@ -0,0 +1,7 @@ +package java.util; + +public interface List extends Collection { + public T get(int index); + + public T remove(int index); +} diff --git a/classpath/java/util/Stack.java b/classpath/java/util/Stack.java new file mode 100644 index 0000000000..3f3d6ad69d --- /dev/null +++ b/classpath/java/util/Stack.java @@ -0,0 +1,20 @@ +package java.util; + +public class Stack extends Vector { + public boolean empty() { + return size() != 0; + } + + public T peek() { + return get(size() - 1); + } + + public T pop() { + return remove(size() - 1); + } + + public T push(T element) { + add(element); + return element; + } +} diff --git a/classpath/java/util/Vector.java b/classpath/java/util/Vector.java new file mode 100644 index 0000000000..65ce7fb908 --- /dev/null +++ b/classpath/java/util/Vector.java @@ -0,0 +1,54 @@ +package java.util; + +public class Vector implements List { + private final ArrayList list; + + public Vector(int capacity) { + list = new ArrayList(capacity); + } + + public Vector() { + this(0); + } + + public synchronized int size() { + return list.size(); + } + + public synchronized boolean add(T element) { + return list.add(element); + } + + public void addElement(T element) { + add(element); + } + + public synchronized T get(int index) { + return list.get(index); + } + + public T elementAt(int index) { + return get(index); + } + + public synchronized T remove(int index) { + return list.remove(index); + } + + public synchronized boolean remove(T element) { + return list.remove(element); + } + + public synchronized void clear() { + list.clear(); + } + + public Iterator iterator() { + return new Collections.ArrayListIterator(this); + } + + public Enumeration elements() { + return new Collections.IteratorEnumeration(iterator()); + } + +}