From c3320c2c97daf66762b7a4b5e984272aac0a6760 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Wed, 4 Jul 2007 16:27:08 -0600 Subject: [PATCH] flesh out classpath enough to test threading; fix indexing bug in parsePool() --- classpath/TestThreads.java | 2 +- classpath/java/lang/Class.java | 2 + classpath/java/lang/InterruptedException.java | 19 +++++++ classpath/java/lang/Long.java | 13 +++++ classpath/java/lang/Runnable.java | 5 ++ classpath/java/lang/StackTraceElement.java | 37 ++++++++++++-- classpath/java/lang/String.java | 35 ++++++++++++- classpath/java/lang/StringBuilder.java | 42 ++++++++++++++++ classpath/java/lang/System.java | 10 +++- classpath/java/lang/Thread.java | 20 ++++++++ classpath/java/lang/Throwable.java | 50 ++++++++++++++++++- classpath/vm/Strings.java | 5 ++ makefile | 2 +- src/vm.cpp | 10 ++-- 14 files changed, 240 insertions(+), 12 deletions(-) create mode 100644 classpath/java/lang/InterruptedException.java create mode 100644 classpath/java/lang/Long.java create mode 100644 classpath/java/lang/Runnable.java create mode 100644 classpath/java/lang/StringBuilder.java create mode 100644 classpath/java/lang/Thread.java create mode 100644 classpath/vm/Strings.java diff --git a/classpath/TestThreads.java b/classpath/TestThreads.java index 004e249138..a2a23166e1 100644 --- a/classpath/TestThreads.java +++ b/classpath/TestThreads.java @@ -1,4 +1,4 @@ -public class TestThreads { +public class TestThreads implements Runnable { public static void main(String[] args) { TestThreads test = new TestThreads(); diff --git a/classpath/java/lang/Class.java b/classpath/java/lang/Class.java index 089286e17a..1a75ac97ee 100644 --- a/classpath/java/lang/Class.java +++ b/classpath/java/lang/Class.java @@ -4,4 +4,6 @@ public final class Class { private Object body; private Class() { } + + public native String getName(); } diff --git a/classpath/java/lang/InterruptedException.java b/classpath/java/lang/InterruptedException.java new file mode 100644 index 0000000000..d9a951e5ed --- /dev/null +++ b/classpath/java/lang/InterruptedException.java @@ -0,0 +1,19 @@ +package java.lang; + +public class InterruptedException extends Exception { + public InterruptedException(String message, Throwable cause) { + super(message, cause); + } + + public InterruptedException(String message) { + this(message, null); + } + + public InterruptedException(Throwable cause) { + this(null, cause); + } + + public InterruptedException() { + this(null, null); + } +} diff --git a/classpath/java/lang/Long.java b/classpath/java/lang/Long.java new file mode 100644 index 0000000000..c4040168ff --- /dev/null +++ b/classpath/java/lang/Long.java @@ -0,0 +1,13 @@ +package java.lang; + +public class Long { + private final long value; + + public Long(long value) { + this.value = value; + } + + public long longValue() { + return value; + } +} diff --git a/classpath/java/lang/Runnable.java b/classpath/java/lang/Runnable.java new file mode 100644 index 0000000000..892ce4b2b5 --- /dev/null +++ b/classpath/java/lang/Runnable.java @@ -0,0 +1,5 @@ +package java.lang; + +public interface Runnable { + public void run(); +} diff --git a/classpath/java/lang/StackTraceElement.java b/classpath/java/lang/StackTraceElement.java index 73bf1b38b0..acf1986dc8 100644 --- a/classpath/java/lang/StackTraceElement.java +++ b/classpath/java/lang/StackTraceElement.java @@ -1,8 +1,39 @@ package java.lang; public class StackTraceElement { - private Object method; - private int ip; + private static int NativeLine = -2; - private StackTraceElement() { } + private String class_; + private String method; + private String file; + private int line; + + private StackTraceElement(String class_, String method, String file, + int line) + { + this.class_ = class_; + this.method = method; + this.file = file; + this.line = line; + } + + public String getClassName() { + return class_; + } + + public String getMethodName() { + return method; + } + + public String getFileName() { + return file; + } + + public int getLineNumber() { + return line; + } + + public boolean isNativeMethod() { + return line == NativeLine; + } } diff --git a/classpath/java/lang/String.java b/classpath/java/lang/String.java index 9690e1bace..922951dc81 100644 --- a/classpath/java/lang/String.java +++ b/classpath/java/lang/String.java @@ -1,8 +1,41 @@ package java.lang; public final class String { - private byte[] bytes; + private Object data; private int offset; private int length; private int hash; + + public int length() { + return length; + } + + public static String valueOf(int v) { + return valueOf((long) v); + } + + public native void getChars(int offset, int length, + char[] dst, int dstLength); + + public static String valueOf(long v) { + if (v == 0) { + return valueOf('0'); + } else { + final int Max = 21; + char[] array = new char[Max]; + int index = Max; + long x = (v >= 0 ? v : -v); + + while (x != 0) { + array[--index] = (char) ('0' + (x % 10)); + x /= 10; + } + + if (v < 0) { + array[--index] = '-'; + } + + return vm.Strings.wrap(array, index, Max - index); + } + } } diff --git a/classpath/java/lang/StringBuilder.java b/classpath/java/lang/StringBuilder.java new file mode 100644 index 0000000000..0eda361183 --- /dev/null +++ b/classpath/java/lang/StringBuilder.java @@ -0,0 +1,42 @@ +package java.lang; + +public class StringBuilder { + private Cell chain; + private int length; + + public StringBuilder append(String s) { + chain = new Cell(s, chain); + length += s.length(); + return this; + } + + public StringBuilder append(int v) { + append(String.valueOf(v)); + return this; + } + + public StringBuilder append(long v) { + append(String.valueOf(v)); + return this; + } + + public String toString() { + char[] array = new char[length]; + int index = length; + for (Cell c = chain; c != null; c = c.next) { + index -= c.value.length(); + c.value.getChars(0, c.value.length(), array, index); + } + return vm.Strings.wrap(array, 0, array.length); + } + + private static class Cell { + public final String value; + public final Cell next; + + public Cell(String value, Cell next) { + this.value = value; + this.next = next; + } + } +} diff --git a/classpath/java/lang/System.java b/classpath/java/lang/System.java index 8a7dd91297..1c04f0a319 100644 --- a/classpath/java/lang/System.java +++ b/classpath/java/lang/System.java @@ -2,6 +2,7 @@ package java.lang; public abstract class System { public static final Output out = new Output(); + public static final Output err = out; static { loadLibrary("natives"); @@ -9,7 +10,14 @@ public abstract class System { public static native void loadLibrary(String name); + public static native String getProperty(String name); + public static class Output { - public native void println(String s); + public native void print(String s); + + public void println(String s) { + print(s); + print(getProperty("line.separator")); + } } } diff --git a/classpath/java/lang/Thread.java b/classpath/java/lang/Thread.java new file mode 100644 index 0000000000..9eac90f6aa --- /dev/null +++ b/classpath/java/lang/Thread.java @@ -0,0 +1,20 @@ +package java.lang; + +public class Thread implements Runnable { + private final Runnable task; + + public Thread(Runnable task) { + this.task = task; + } + + public native void start(); + + public void run() { + if (task != null) { + task.run(); + } + } + + public static native void sleep(long milliseconds) + throws InterruptedException; +} diff --git a/classpath/java/lang/Throwable.java b/classpath/java/lang/Throwable.java index d4330f7bf4..cc1464e275 100644 --- a/classpath/java/lang/Throwable.java +++ b/classpath/java/lang/Throwable.java @@ -2,7 +2,7 @@ package java.lang; public class Throwable { private String message; - private StackTraceElement[] trace; + private Object trace; private Throwable cause; public Throwable(String message, Throwable cause) { @@ -23,5 +23,51 @@ public class Throwable { this(null, null); } - private static native StackTraceElement[] trace(int skipCount); + private static native Object trace(int skipCount); + + private static native StackTraceElement[] resolveTrace(Object trace); + + private StackTraceElement[] resolveTrace() { + if (! (trace instanceof StackTraceElement[])) { + trace = resolveTrace(trace); + } + return (StackTraceElement[]) trace; + } + + public void printStackTrace() { + StringBuilder sb = new StringBuilder(); + printStackTrace(sb, System.getProperty("line.separator")); + System.err.print(sb.toString()); + } + + private void printStackTrace(StringBuilder sb, String nl) { + sb.append(getClass().getName()); + if (message != null) { + sb.append(": ").append(message); + } + sb.append(nl); + + StackTraceElement[] trace = resolveTrace(); + for (int i = 0; i < trace.length; ++i) { + sb.append(" at ") + .append(trace[i].getClassName()) + .append(trace[i].getMethodName()); + + if (trace[i].isNativeMethod()) { + sb.append(" (native)"); + } else { + int line = trace[i].getLineNumber(); + if (line >= 0) { + sb.append(" (line ").append(line).append(")"); + } + } + + sb.append(nl); + } + + if (cause != null) { + sb.append("caused by: "); + cause.printStackTrace(sb, nl); + } + } } diff --git a/classpath/vm/Strings.java b/classpath/vm/Strings.java new file mode 100644 index 0000000000..fe4c4b3de6 --- /dev/null +++ b/classpath/vm/Strings.java @@ -0,0 +1,5 @@ +package vm; + +public abstract class Strings { + public static native String wrap(char[] array, int offset, int length); +} diff --git a/makefile b/makefile index 00cb5e6ddc..b8cf7a9447 100644 --- a/makefile +++ b/makefile @@ -127,7 +127,7 @@ fast-cflags = $(fast) $(cflags) classpath-sources = $(shell find $(classpath)/java -name '*.java') classpath-classes = $(call java-classes,$(classpath-sources),$(classpath)) -input = $(bld)/classes/Hello.class +input = $(bld)/classes/TestThreads.class input-depends = \ $(classpath-classes) \ $(jni-library) diff --git a/src/vm.cpp b/src/vm.cpp index 5937c00fdf..6614d4ee36 100644 --- a/src/vm.cpp +++ b/src/vm.cpp @@ -20,7 +20,7 @@ using namespace vm; namespace { -const bool Verbose = false; +const bool Verbose = true; const bool Debug = false; const bool DebugRun = false; const bool DebugStack = false; @@ -1542,11 +1542,13 @@ parsePool(Thread* t, Stream& s) case CONSTANT_Long: { object value = makeLong(t, s.read8()); set(t, arrayBody(t, pool, i), value); + ++i; } break; case CONSTANT_Double: { object value = makeLong(t, s.readDouble()); set(t, arrayBody(t, pool, i), value); + ++i; } break; case CONSTANT_Utf8: { @@ -1595,7 +1597,8 @@ parsePool(Thread* t, Stream& s) for (unsigned i = 0; i < poolCount; ++i) { object o = arrayBody(t, pool, i); - if (objectClass(t, o) == arrayBody(t, t->vm->types, Machine::IntArrayType)) + if (o and objectClass(t, o) + == arrayBody(t, t->vm->types, Machine::IntArrayType)) { switch (intArrayBody(t, o, 0)) { case CONSTANT_Class: { @@ -1621,7 +1624,8 @@ parsePool(Thread* t, Stream& s) for (unsigned i = 0; i < poolCount; ++i) { object o = arrayBody(t, pool, i); - if (objectClass(t, o) == arrayBody(t, t->vm->types, Machine::IntArrayType)) + if (o and objectClass(t, o) + == arrayBody(t, t->vm->types, Machine::IntArrayType)) { switch (intArrayBody(t, o, 0)) { case CONSTANT_Fieldref: