diff --git a/classpath/java/lang/Class.java b/classpath/java/lang/Class.java index 649c60a580..f100438489 100644 --- a/classpath/java/lang/Class.java +++ b/classpath/java/lang/Class.java @@ -6,6 +6,8 @@ import java.lang.reflect.Field; import java.lang.reflect.Modifier; public final class Class { + private static final int PrimitiveFlag = 1 << 4; + private short flags; private byte vmFlags; private byte arrayDimensions; @@ -330,14 +332,6 @@ public final class Class { } public boolean isPrimitive() { - return equals(boolean.class) - || equals(byte.class) - || equals(char.class) - || equals(short.class) - || equals(int.class) - || equals(long.class) - || equals(float.class) - || equals(double.class) - || equals(void.class); + return (vmFlags & PrimitiveFlag) != 0; } } diff --git a/classpath/java/lang/reflect/Array.java b/classpath/java/lang/reflect/Array.java index 3d9e752265..eb4d9abc56 100644 --- a/classpath/java/lang/reflect/Array.java +++ b/classpath/java/lang/reflect/Array.java @@ -3,9 +3,86 @@ package java.lang.reflect; public final class Array { private Array() { } - public static native Object get(Object array, int index); + public static Object get(Object array, int index) { + String className = array.getClass().getName(); + if (! className.startsWith("[")) { + throw new IllegalArgumentException(); + } - public static native void set(Object array, int index, Object value); + switch (className.charAt(1)) { + case 'B': + return Byte.valueOf(((byte[]) array)[index]); + case 'C': + return Character.valueOf(((char[]) array)[index]); + case 'D': + return Double.valueOf(((double[]) array)[index]); + case 'F': + return Float.valueOf(((float[]) array)[index]); + case 'I': + return Integer.valueOf(((int[]) array)[index]); + case 'J': + return Long.valueOf(((long[]) array)[index]); + case 'S': + return Short.valueOf(((short[]) array)[index]); + case 'Z': + return Boolean.valueOf(((boolean[]) array)[index]); + case 'L': + case '[': + return getObject(array, index); + + default: + throw new Error(); + } + } + + private static native Object getObject(Object array, int index); + + public static void set(Object array, int index, Object value) { + String className = array.getClass().getName(); + if (! className.startsWith("[")) { + throw new IllegalArgumentException(); + } + + switch (className.charAt(1)) { + case 'B': + ((byte[]) array)[index] = (Byte) value; + break; + case 'C': + ((char[]) array)[index] = (Character) value; + break; + case 'D': + ((double[]) array)[index] = (Double) value; + break; + case 'F': + ((float[]) array)[index] = (Float) value; + break; + case 'I': + ((int[]) array)[index] = (Integer) value; + break; + case 'J': + ((long[]) array)[index] = (Long) value; + break; + case 'S': + ((short[]) array)[index] = (Short) value; + break; + case 'Z': + ((boolean[]) array)[index] = (Boolean) value; + break; + case 'L': + case '[': + if (array.getClass().getComponentType().isInstance(value)) { + setObject(array, index, value); + } else { + throw new IllegalArgumentException(); + } + break; + + default: + throw new Error(); + } + } + + private static native void setObject(Object array, int index, Object value); public static native int getLength(Object array); @@ -16,22 +93,26 @@ public final class Array { throw new NegativeArraySizeException(); } - if (elementType.equals(boolean.class)) { - return new boolean[length]; - } else if (elementType.equals(byte.class)) { - return new byte[length]; - } else if (elementType.equals(char.class)) { - return new char[length]; - } else if (elementType.equals(short.class)) { - return new short[length]; - } else if (elementType.equals(int.class)) { - return new int[length]; - } else if (elementType.equals(long.class)) { - return new long[length]; - } else if (elementType.equals(float.class)) { - return new float[length]; - } else if (elementType.equals(double.class)) { - return new double[length]; + if (elementType.isPrimitive()) { + if (elementType.equals(boolean.class)) { + return new boolean[length]; + } else if (elementType.equals(byte.class)) { + return new byte[length]; + } else if (elementType.equals(char.class)) { + return new char[length]; + } else if (elementType.equals(short.class)) { + return new short[length]; + } else if (elementType.equals(int.class)) { + return new int[length]; + } else if (elementType.equals(long.class)) { + return new long[length]; + } else if (elementType.equals(float.class)) { + return new float[length]; + } else if (elementType.equals(double.class)) { + return new double[length]; + } else { + throw new IllegalArgumentException(); + } } else { return makeObjectArray(elementType, length); } diff --git a/classpath/java/lang/reflect/Method.java b/classpath/java/lang/reflect/Method.java index 711c0e2d1f..d48e843872 100644 --- a/classpath/java/lang/reflect/Method.java +++ b/classpath/java/lang/reflect/Method.java @@ -87,6 +87,27 @@ public class Method extends AccessibleObject implements Member { return types; } - public native Object invoke(Object instance, Object ... arguments) + public Object invoke(Object instance, Object ... arguments) + throws InvocationTargetException, IllegalAccessException + { + if ((flags & Modifier.STATIC) != 0) { + if (arguments.length == parameterCount) { + return invoke(this, instance, arguments); + } else { + throw new ArrayIndexOutOfBoundsException(); + } + } else if (class_.isInstance(instance)) { + if (arguments.length == parameterCount - 1) { + return invoke(this, instance, arguments); + } else { + throw new ArrayIndexOutOfBoundsException(); + } + } else { + throw new IllegalArgumentException(); + } + } + + public static native Object invoke(Method method, Object instance, + Object ... arguments) throws InvocationTargetException, IllegalAccessException; } diff --git a/src/builtin.cpp b/src/builtin.cpp index a0af3c380d..94d2beecbd 100644 --- a/src/builtin.cpp +++ b/src/builtin.cpp @@ -7,16 +7,6 @@ using namespace vm; namespace { -object -doInvoke(Thread* t, object this_, object instance, object arguments) -{ - object v = run2(t, this_, instance, arguments); - if (t->exception) { - t->exception = makeInvocationTargetException(t, t->exception); - } - return v; -} - inline void replace(char a, char b, char* c) { @@ -261,10 +251,10 @@ Field_setPrimitive(Thread* t, jclass, jobject instance, jint code, jint offset, } void -Field_setObject(Thread*, jclass, jobject instance, jint offset, +Field_setObject(Thread* t, jclass, jobject instance, jint offset, jobject value) { - cast(*instance, offset) = (value ? *value : 0); + set(t, cast(*instance, offset), (value ? *value : 0)); } jobject @@ -281,129 +271,26 @@ Method_getCaller(Thread* t, jclass) } jobject -Method_invoke(Thread* t, jobject this_, jobject instancep, - jobjectArray argumentsp) +Method_invoke(Thread* t, jclass, jobject method, jobject instance, + jobjectArray arguments) { - object method = *this_; - - if (argumentsp) { - object arguments = *argumentsp; - - if (methodFlags(t, method) & ACC_STATIC) { - if (objectArrayLength(t, arguments) - == methodParameterCount(t, method)) - { - return pushReference(t, doInvoke(t, method, 0, arguments)); - } else { - t->exception = makeArrayIndexOutOfBoundsException(t, 0); - } - } else if (instancep) { - object instance = *instancep; - - if (instanceOf(t, methodClass(t, method), instance)) { - if (objectArrayLength(t, arguments) - == static_cast(methodParameterCount(t, method) - 1)) - { - return pushReference(t, doInvoke(t, method, instance, arguments)); - } else { - t->exception = makeArrayIndexOutOfBoundsException(t, 0); - } - } - } else { - t->exception = makeNullPointerException(t); - } - } else { - t->exception = makeNullPointerException(t); + object v = run2(t, *method, (instance ? *instance : 0), *arguments); + if (t->exception) { + t->exception = makeInvocationTargetException(t, t->exception); } - - return 0; + return pushReference(t, v); } jobject -Array_get(Thread* t, jobject array, int index) +Array_getObject(Thread* t, jobject array, int index) { - if (LIKELY(array)) { - object a = *array; - 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 'B': - return pushReference(t, makeByte(t, byteArrayBody(t, a, index))); - case 'C': - return pushReference(t, makeChar(t, charArrayBody(t, a, index))); - case 'D': - return pushReference(t, makeDouble(t, doubleArrayBody(t, a, index))); - case 'F': - return pushReference(t, makeFloat(t, floatArrayBody(t, a, index))); - case 'I': - return pushReference(t, makeInt(t, intArrayBody(t, a, index))); - case 'J': - return pushReference(t, makeLong(t, longArrayBody(t, a, index))); - case 'S': - return pushReference(t, makeShort(t, shortArrayBody(t, a, index))); - case 'Z': - return pushReference - (t, makeBoolean(t, booleanArrayBody(t, a, index))); - case 'L': - case '[': - return pushReference(t, objectArrayBody(t, a, index)); - - default: abort(t); - } - } else { - t->exception = makeArrayIndexOutOfBoundsException(t, 0); - } - } else { - t->exception = makeIllegalArgumentException(t); - } - } else { - t->exception = makeNullPointerException(t); - } - - return 0; + return pushReference(t, objectArrayBody(t, *array, index)); } void -Array_set(Thread* t, jobject array, int index, jobject value) +Array_setObject(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); - } + set(t, objectArrayBody(t, *array, index), (value ? *value : 0)); } jint @@ -749,6 +636,16 @@ populateBuiltinMap(Thread* t, object map) { "Java_java_lang_Throwable_trace", reinterpret_cast(::Throwable_trace) }, + { "Java_java_lang_Float_floatToRawIntBits", + reinterpret_cast(::Float_floatToRawIntBits) }, + { "Java_java_lang_Float_intBitsToFloat", + reinterpret_cast(::Float_intBitsToFloat) }, + + { "Java_java_lang_Double_doubleToRawLongBits", + reinterpret_cast(::Double_doubleToRawLongBits) }, + { "Java_java_lang_Double_longBitsToDouble", + reinterpret_cast(::Double_longBitsToDouble) }, + { "Java_java_lang_Object_getClass", reinterpret_cast(::Object_getClass) }, { "Java_java_lang_Object_notify", @@ -764,10 +661,10 @@ populateBuiltinMap(Thread* t, object map) { "Java_java_lang_Object_clone", reinterpret_cast(::Object_clone) }, - { "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_getObject", + reinterpret_cast(::Array_getObject) }, + { "Java_java_lang_reflect_Array_setObject", + reinterpret_cast(::Array_setObject) }, { "Java_java_lang_reflect_Array_getLength", reinterpret_cast(::Array_getLength) }, { "Java_java_lang_reflect_Array_makeObjectArray", diff --git a/src/machine.cpp b/src/machine.cpp index 6b38ff0ddf..2b22f1d6ff 100644 --- a/src/machine.cpp +++ b/src/machine.cpp @@ -1364,6 +1364,25 @@ Thread::Thread(Machine* m, object javaThread, Thread* parent): classVmFlags(t, arrayBody(t, m->types, Machine::PhantomReferenceType)) |= ReferenceFlag | WeakReferenceFlag; + classVmFlags(t, arrayBody(t, m->types, Machine::JbooleanType)) + |= PrimitiveFlag; + classVmFlags(t, arrayBody(t, m->types, Machine::JbyteType)) + |= PrimitiveFlag; + classVmFlags(t, arrayBody(t, m->types, Machine::JcharType)) + |= PrimitiveFlag; + classVmFlags(t, arrayBody(t, m->types, Machine::JshortType)) + |= PrimitiveFlag; + classVmFlags(t, arrayBody(t, m->types, Machine::JintType)) + |= PrimitiveFlag; + classVmFlags(t, arrayBody(t, m->types, Machine::JlongType)) + |= PrimitiveFlag; + classVmFlags(t, arrayBody(t, m->types, Machine::JfloatType)) + |= PrimitiveFlag; + classVmFlags(t, arrayBody(t, m->types, Machine::JdoubleType)) + |= PrimitiveFlag; + classVmFlags(t, arrayBody(t, m->types, Machine::JvoidType)) + |= PrimitiveFlag; + m->bootstrapClassMap = makeHashMap(this, 0, 0); #include "type-java-initializations.cpp" diff --git a/src/machine.h b/src/machine.h index bb1765a3c1..f27632bfc0 100644 --- a/src/machine.h +++ b/src/machine.h @@ -60,6 +60,7 @@ const unsigned ReferenceFlag = 1 << 0; const unsigned WeakReferenceFlag = 1 << 1; const unsigned NeedInitFlag = 1 << 2; const unsigned InitFlag = 1 << 3; +const unsigned PrimitiveFlag = 1 << 4; // method flags: const unsigned ClassInitFlag = 1 << 0;