From 363801af1c78273b306230d4657dee527f7c9ebc Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Fri, 27 Jul 2007 17:56:19 -0600 Subject: [PATCH] classpath progress --- classpath/java/lang/Character.java | 2 +- classpath/java/lang/Class.java | 102 ++++++++++++++++++++----- classpath/java/lang/ClassLoader.java | 6 +- classpath/java/lang/Integer.java | 4 + classpath/java/lang/Long.java | 24 ++++++ classpath/java/lang/String.java | 4 +- classpath/java/lang/reflect/Array.java | 2 + classpath/java/lang/reflect/Field.java | 2 + src/builtin.cpp | 87 ++++++++++++++++++++- src/machine.h | 2 +- 10 files changed, 211 insertions(+), 24 deletions(-) diff --git a/classpath/java/lang/Character.java b/classpath/java/lang/Character.java index 41b693a725..7f8614887a 100644 --- a/classpath/java/lang/Character.java +++ b/classpath/java/lang/Character.java @@ -45,7 +45,7 @@ public final class Character { return (c >= 'A' && c <= 'Z'); } - public static boolean isWhiteSpace(char c) { + public static boolean isWhitespace(char c) { return c == ' ' || c == '\t' || c == '\n'; } } diff --git a/classpath/java/lang/Class.java b/classpath/java/lang/Class.java index c6ea1eeb18..9e5e4c07b9 100644 --- a/classpath/java/lang/Class.java +++ b/classpath/java/lang/Class.java @@ -3,6 +3,7 @@ package java.lang; import java.lang.reflect.Constructor; import java.lang.reflect.Method; import java.lang.reflect.Field; +import java.lang.reflect.Modifier; public final class Class { private short flags; @@ -85,21 +86,27 @@ public final class Class { public Method getDeclaredMethod(String name, Class ... parameterTypes) throws NoSuchMethodException { - Method f = findMethod(name, parameterTypes); - if (f == null) { + if (name.startsWith("<")) { + throw new NoSuchMethodException(name); + } + Method m = findMethod(name, parameterTypes); + if (m == null) { throw new NoSuchMethodException(name); } else { - return f; + return m; } } public Method getMethod(String name, Class ... parameterTypes) throws NoSuchMethodException { + if (name.startsWith("<")) { + throw new NoSuchMethodException(name); + } for (Class c = this; c != null; c = c.super_) { - Method f = c.findMethod(name, parameterTypes); - if (f != null) { - return f; + Method m = c.findMethod(name, parameterTypes); + if (m != null) { + return m; } } throw new NoSuchMethodException(name); @@ -108,18 +115,29 @@ public final class Class { public Constructor getConstructor(Class ... parameterTypes) throws NoSuchMethodException { - return new Constructor(getDeclaredMethod("", parameterTypes)); + Method m = findMethod("", parameterTypes); + if (m == null) { + throw new NoSuchMethodException(); + } else { + return new Constructor(m); + } } - public Constructor[] getConstructors() { + private int countConstructors(boolean publicOnly) { int count = 0; for (int i = 0; i < methodTable.length; ++i) { - if (methodTable[i].getName().equals("")) { + if (((! publicOnly) + || ((methodTable[i].getModifiers() & Modifier.PUBLIC)) != 0) + && methodTable[i].getName().equals("")) + { ++ count; } } + return count; + } - Constructor[] array = new Constructor[count]; + public Constructor[] getDeclaredConstructors() { + Constructor[] array = new Constructor[countConstructors(false)]; int index = 0; for (int i = 0; i < methodTable.length; ++i) { if (methodTable[i].getName().equals("")) { @@ -130,8 +148,18 @@ public final class Class { return array; } - public Constructor[] getDeclaredConstructors() { - return getConstructors(); + public Constructor[] getConstructors() { + Constructor[] array = new Constructor[countConstructors(true)]; + int index = 0; + for (int i = 0; i < methodTable.length; ++i) { + if (((methodTable[i].getModifiers() & Modifier.PUBLIC) != 0) + && methodTable[i].getName().equals("")) + { + array[index++] = new Constructor(methodTable[i]); + } + } + + return array; } public Field[] getDeclaredFields() { @@ -140,18 +168,58 @@ public final class Class { return array; } - public Method[] getDeclaredMethods() { + private int countPublicFields() { int count = 0; - for (int i = 0; i < methodTable.length; ++i) { - if (! methodTable[i].getName().equals("")) { + for (int i = 0; i < fieldTable.length; ++i) { + if (((fieldTable[i].getModifiers() & Modifier.PUBLIC)) != 0) { ++ count; } } + return count; + } - Method[] array = new Method[count]; + public Field[] getFields() { + Field[] array = new Field[countPublicFields()]; + for (int i = 0; i < fieldTable.length; ++i) { + if (((fieldTable[i].getModifiers() & Modifier.PUBLIC)) != 0) { + array[i] = fieldTable[i]; + } + } + return array; + } + + private int countMethods(boolean publicOnly) { + int count = 0; + for (int i = 0; i < methodTable.length; ++i) { + if (((! publicOnly) + || ((methodTable[i].getModifiers() & Modifier.PUBLIC)) != 0) + && (! methodTable[i].getName().startsWith("<"))) + { + ++ count; + } + } + return count; + } + + public Method[] getDeclaredMethods() { + Method[] array = new Method[countMethods(false)]; int index = 0; for (int i = 0; i < methodTable.length; ++i) { - if (! methodTable[i].getName().equals("")) { + if (! methodTable[i].getName().startsWith("<")) { + array[index++] = methodTable[i]; + } + } + + return array; + } + + public Method[] getMethods() { + Method[] array = new Method[countMethods(true)]; + int index = 0; + for (int i = 0; i < methodTable.length; ++i) { + if (((methodTable[i].getModifiers() & Modifier.PUBLIC) != 0) + && (! methodTable[i].getName().startsWith("<"))) + { array[index++] = methodTable[i]; } } diff --git a/classpath/java/lang/ClassLoader.java b/classpath/java/lang/ClassLoader.java index 426cc994c2..f66dd46814 100644 --- a/classpath/java/lang/ClassLoader.java +++ b/classpath/java/lang/ClassLoader.java @@ -7,5 +7,9 @@ public class ClassLoader { public static ClassLoader getSystemClassLoader() { return instance; - } + } + + public Class loadClass(String name) { + return Class.forName(name); + } } diff --git a/classpath/java/lang/Integer.java b/classpath/java/lang/Integer.java index 3ce7ef1797..4363ff41ec 100644 --- a/classpath/java/lang/Integer.java +++ b/classpath/java/lang/Integer.java @@ -32,4 +32,8 @@ public final class Integer extends Number { public double doubleValue() { return (double) value; } + + public static int parseInt(String s, int radix) { + return (int) Long.parseLong(s, radix); + } } diff --git a/classpath/java/lang/Long.java b/classpath/java/lang/Long.java index 3e1c6e3786..9b68062330 100644 --- a/classpath/java/lang/Long.java +++ b/classpath/java/lang/Long.java @@ -32,4 +32,28 @@ public final class Long extends Number { public double doubleValue() { return (double) value; } + + private static long pow(long a, long b) { + long c = 1; + for (int i = 0; i < b; ++i) c *= a; + return c; + } + + public static long parseLong(String s, int radix) { + long number = 0; + + for (int i = 0; i < s.length(); ++i) { + char c = s.charAt(i); + if (((c >= '0') && (c <= '9')) || + ((c >= 'a') && (c <= 'z'))) { + long digit = ((c >= '0' && c <= '9') ? (c - '0') : (c - 'a' + 10)); + number += digit * pow(radix, (s.length() - i - 1)); + } else { + throw new NumberFormatException("Invalid character " + c + " code " + + (int) c); + } + } + + return number; + } } diff --git a/classpath/java/lang/String.java b/classpath/java/lang/String.java index 482de19b1c..d188fb2e1a 100644 --- a/classpath/java/lang/String.java +++ b/classpath/java/lang/String.java @@ -144,7 +144,7 @@ public final class String implements Comparable { public boolean startsWith(String s) { if (length >= s.length) { - return substring(0, s.length).compareTo(s) != 0; + return substring(0, s.length).compareTo(s) == 0; } else { return false; } @@ -152,7 +152,7 @@ public final class String implements Comparable { public boolean endsWith(String s) { if (length >= s.length) { - return substring(length - s.length).compareTo(s) != 0; + return substring(length - s.length).compareTo(s) == 0; } else { return false; } diff --git a/classpath/java/lang/reflect/Array.java b/classpath/java/lang/reflect/Array.java index 01dc908b04..3d9e752265 100644 --- a/classpath/java/lang/reflect/Array.java +++ b/classpath/java/lang/reflect/Array.java @@ -5,6 +5,8 @@ public final class Array { public static native Object get(Object array, int index); + public static native void set(Object array, int index, Object value); + public static native int getLength(Object array); private static native Object makeObjectArray(Class elementType, int length); diff --git a/classpath/java/lang/reflect/Field.java b/classpath/java/lang/reflect/Field.java index f9fc796858..e1097ab548 100644 --- a/classpath/java/lang/reflect/Field.java +++ b/classpath/java/lang/reflect/Field.java @@ -32,4 +32,6 @@ public class Field extends AccessibleObject { } public native Object get(Object instance); + + public native void set(Object instance, Object value); } diff --git a/src/builtin.cpp b/src/builtin.cpp index 6c895343f9..56366023b6 100644 --- a/src/builtin.cpp +++ b/src/builtin.cpp @@ -154,11 +154,51 @@ Field_get(Thread* t, jobject this_, jobject instancep) } } else { t->exception = makeIllegalArgumentException(t); - return 0; } } else { t->exception = makeNullPointerException(t); - return 0; + } + + return 0; +} + +void +Field_set(Thread* t, jobject this_, jobject instancep, jobject value) +{ + object field = *this_; + object v = (value ? *value : 0); + + if (fieldFlags(t, field) & ACC_STATIC) { + if (fieldCode(t, field) == ObjectField or v) { + set(t, arrayBody(t, classStaticTable(t, fieldClass(t, field)), + fieldOffset(t, field)), v); + } else { + t->exception = makeNullPointerException(t); + } + } else if (instancep) { + object instance = *instancep; + + if (instanceOf(t, fieldClass(t, this_), instance)) { + switch (fieldCode(t, field)) { + case ObjectField: + set(t, cast(instance, fieldOffset(t, field)), v); + break; + + default: { + uint8_t* body = &cast(instance, fieldOffset(t, field)); + if (v) { + memcpy(body, &cast(v, BytesPerWord), + primitiveSize(t, fieldCode(t, field))); + } else { + t->exception = makeNullPointerException(t); + } + } break; + } + } else { + t->exception = makeIllegalArgumentException(t); + } + } else { + t->exception = makeNullPointerException(t); } } @@ -255,6 +295,45 @@ Array_get(Thread* t, jobject array, int index) return 0; } +void +Array_set(Thread* t, jobject array, int index, jobject value) +{ + if (LIKELY(array)) { + object a = *array; + object v = (value ? *value : 0); + unsigned elementSize = classArrayElementSize(t, objectClass(t, a)); + + if (LIKELY(elementSize)) { + intptr_t length = cast(a, BytesPerWord); + + if (LIKELY(index >= 0 and index < length)) { + switch (byteArrayBody(t, className(t, objectClass(t, a)), 1)) { + case 'L': + case '[': + set(t, objectArrayBody(t, a, index), v); + break; + + default: { + uint8_t* p = &cast + (a, (2 * BytesPerWord) + (index * elementSize)); + if (v) { + memcpy(p, &cast(v, BytesPerWord), elementSize); + } else { + t->exception = makeNullPointerException(t); + } + } break; + } + } else { + t->exception = makeArrayIndexOutOfBoundsException(t, 0); + } + } else { + t->exception = makeIllegalArgumentException(t); + } + } else { + t->exception = makeNullPointerException(t); + } +} + jint Array_getLength(Thread* t, jobject array) { @@ -545,6 +624,8 @@ populateBuiltinMap(Thread* t, object map) { "Java_java_lang_reflect_Array_get", reinterpret_cast(::Array_get) }, + { "Java_java_lang_reflect_Array_set", + reinterpret_cast(::Array_set) }, { "Java_java_lang_reflect_Array_getLength", reinterpret_cast(::Array_getLength) }, { "Java_java_lang_reflect_Array_makeObjectArray", @@ -555,6 +636,8 @@ populateBuiltinMap(Thread* t, object map) { "Java_java_lang_reflect_Field_get", reinterpret_cast(::Field_get) }, + { "Java_java_lang_reflect_Field_set", + reinterpret_cast(::Field_set) }, { "Java_java_lang_reflect_Method_invoke", reinterpret_cast(::Method_invoke) }, diff --git a/src/machine.h b/src/machine.h index 7b2668d56e..903efe8fa3 100644 --- a/src/machine.h +++ b/src/machine.h @@ -20,7 +20,7 @@ namespace vm { const bool Verbose = false; -const bool DebugRun = true; +const bool DebugRun = false; const bool DebugStack = false; const bool DebugMonitors = false;