diff --git a/classpath/java/lang/Class.java b/classpath/java/lang/Class.java index da3ce0bf9f..649c60a580 100644 --- a/classpath/java/lang/Class.java +++ b/classpath/java/lang/Class.java @@ -27,6 +27,10 @@ public final class Class { return new String(name, 0, name.length - 1, false); } + public Object[] staticTable() { + return staticTable; + } + public static Class forName(String name) throws ClassNotFoundException { return forName (name, true, Method.getCaller().getDeclaringClass().getClassLoader()); diff --git a/classpath/java/lang/Double.java b/classpath/java/lang/Double.java index 89d681ac29..caffeb5177 100644 --- a/classpath/java/lang/Double.java +++ b/classpath/java/lang/Double.java @@ -63,8 +63,7 @@ public final class Double extends Number { return 0.0; } - public static long doubleToRawLongBits(double value) { - // todo - return 0; - } + public static native long doubleToRawLongBits(double value); + + public static native double longBitsToDouble(long bits); } diff --git a/classpath/java/lang/Float.java b/classpath/java/lang/Float.java index 5bbad02ad3..c06bdc9dc9 100644 --- a/classpath/java/lang/Float.java +++ b/classpath/java/lang/Float.java @@ -53,8 +53,7 @@ public final class Float extends Number { return (double) value; } - public static int floatToRawIntBits(float value) { - // todo - return 0; - } + public static native int floatToRawIntBits(float value); + + public static native float intBitsToFloat(int bits); } diff --git a/classpath/java/lang/reflect/Field.java b/classpath/java/lang/reflect/Field.java index ef8992d7f7..9f744b2549 100644 --- a/classpath/java/lang/reflect/Field.java +++ b/classpath/java/lang/reflect/Field.java @@ -1,6 +1,17 @@ package java.lang.reflect; public class Field extends AccessibleObject { + private static final int VoidField = 0; + private static final int ByteField = 1; + private static final int CharField = 2; + private static final int DoubleField = 3; + private static final int FloatField = 4; + private static final int IntField = 5; + private static final int LongField = 6; + private static final int ShortField = 7; + private static final int BooleanField = 8; + private static final int ObjectField = 9; + private byte vmFlags; private byte code; private short flags; @@ -35,8 +46,182 @@ public class Field extends AccessibleObject { return Class.forCanonicalName(getName()); } - public native Object get(Object instance) throws IllegalAccessException; + public Object get(Object instance) throws IllegalAccessException { + if ((flags & Modifier.STATIC) != 0) { + Object v = class_.staticTable()[offset]; + switch (code) { + case ByteField: + return Byte.valueOf((byte) ((Integer) v).intValue()); - public native void set(Object instance, Object value) - throws IllegalAccessException; + case BooleanField: + return Boolean.valueOf(((Integer) v) != 0); + + case CharField: + return Character.valueOf((char) ((Integer) v).intValue()); + + case ShortField: + return Short.valueOf((short) ((Integer) v).intValue()); + + case FloatField: + return Float.valueOf(Float.intBitsToFloat((Integer) v)); + + case DoubleField: + return Double.valueOf(Double.longBitsToDouble((Long) v)); + + case IntField: + case LongField: + case ObjectField: + return v; + + default: + throw new Error(); + } + } else if (class_.isInstance(instance)) { + switch (code) { + case ByteField: + return Byte.valueOf((byte) getPrimitive(instance, code, offset)); + + case BooleanField: + return Boolean.valueOf(getPrimitive(instance, code, offset) != 0); + + case CharField: + return Character.valueOf((char) getPrimitive(instance, code, offset)); + + case ShortField: + return Short.valueOf((short) getPrimitive(instance, code, offset)); + + case IntField: + return Integer.valueOf((int) getPrimitive(instance, code, offset)); + + case LongField: + return Long.valueOf((int) getPrimitive(instance, code, offset)); + + case FloatField: + return Float.valueOf + (Float.intBitsToFloat((int) getPrimitive(instance, code, offset))); + + case DoubleField: + return Double.valueOf + (Double.longBitsToDouble(getPrimitive(instance, code, offset))); + + case ObjectField: + return getObject(instance, offset); + + default: + throw new Error(); + } + } else { + throw new IllegalArgumentException(); + } + } + + public void set(Object instance, Object value) + throws IllegalAccessException + { + if ((flags & Modifier.STATIC) != 0) { + Object[] a = class_.staticTable(); + switch (code) { + case ByteField: + a[offset] = Integer.valueOf((Byte) value); + break; + + case BooleanField: + a[offset] = Integer.valueOf(((Boolean) value) ? 1 : 0); + break; + + case CharField: + a[offset] = Integer.valueOf((Character) value); + break; + + case ShortField: + a[offset] = Integer.valueOf((Short) value); + break; + + case FloatField: + a[offset] = Integer.valueOf(Float.floatToRawIntBits((Float) value)); + break; + + case DoubleField: + a[offset] = Long.valueOf(Double.doubleToRawLongBits((Double) value)); + break; + + case IntField: + case LongField: + a[offset] = value; + break; + + case ObjectField: + if (getType().isInstance(value)) { + a[offset] = value; + } else { + throw new IllegalArgumentException(); + } + break; + + default: + throw new Error(); + } + } else if (class_.isInstance(instance)) { + switch (code) { + case ByteField: + setPrimitive(instance, code, offset, (Byte) value); + break; + + case BooleanField: + setPrimitive(instance, code, offset, ((Boolean) value) ? 1 : 0); + break; + + case CharField: + setPrimitive(instance, code, offset, (Character) value); + break; + + case ShortField: + setPrimitive(instance, code, offset, (Short) value); + break; + + case IntField: + setPrimitive(instance, code, offset, (Integer) value); + break; + + case LongField: + setPrimitive(instance, code, offset, (Long) value); + break; + + case FloatField: + setPrimitive(instance, code, offset, + Float.floatToRawIntBits((Float) value)); + break; + + case DoubleField: + setPrimitive(instance, code, offset, + Double.doubleToRawLongBits((Double) value)); + break; + + case ObjectField: + if (getType().isInstance(value)) { + setObject(instance, offset, value); + } else { + throw new IllegalArgumentException(); + } + break; + + default: + throw new Error(); + } + } else { + throw new IllegalArgumentException(); + } + } + + private static native long getPrimitive + (Object instance, int code, int offset); + + private static native Object getObject + (Object instance, int offset); + + private static native void setPrimitive + (Object instance, int code, int offset, long value); + + private static native void setObject + (Object instance, int offset, Object value); } diff --git a/src/builtin.cpp b/src/builtin.cpp index 689ab82be5..a0af3c380d 100644 --- a/src/builtin.cpp +++ b/src/builtin.cpp @@ -195,171 +195,78 @@ Class_isAssignableFrom(Thread* t, jobject this_, jclass that) } } -jobject -Field_get(Thread* t, jobject this_, jobject instancep) +jlong +Field_getPrimitive(Thread* t, jclass, jobject instance, jint code, jint offset) { - object field = *this_; - - if (fieldFlags(t, field) & ACC_STATIC) { - object v = arrayBody(t, classStaticTable(t, fieldClass(t, field)), - fieldOffset(t, field)); - - switch (fieldCode(t, field)) { - case ByteField: - return pushReference(t, makeByte(t, intValue(t, v))); - - case BooleanField: - return pushReference(t, makeBoolean(t, intValue(t, v))); - - case CharField: - return pushReference(t, makeChar(t, intValue(t, v))); - - case ShortField: - return pushReference(t, makeShort(t, intValue(t, v))); - - case FloatField: - return pushReference(t, makeFloat(t, intValue(t, v))); - - case DoubleField: - return pushReference(t, makeDouble(t, longValue(t, v))); - - case IntField: - case LongField: - case ObjectField: - return pushReference(t, v); - - default: - abort(t); - } - } else if (instancep) { - object instance = *instancep; - - if (instanceOf(t, fieldClass(t, this_), instance)) { - switch (fieldCode(t, field)) { - case ByteField: - return pushReference - (t, makeByte(t, cast(instance, fieldOffset(t, field)))); - - case BooleanField: - return pushReference - (t, makeBoolean(t, cast(instance, fieldOffset(t, field)))); - - case CharField: - return pushReference - (t, makeChar(t, cast(instance, fieldOffset(t, field)))); - - case ShortField: - return pushReference - (t, makeShort(t, cast(instance, fieldOffset(t, field)))); - - case FloatField: - return pushReference - (t, makeFloat(t, cast(instance, fieldOffset(t, field)))); - - case IntField: - return pushReference - (t, makeInt(t, cast(instance, fieldOffset(t, field)))); - - case DoubleField: - return pushReference - (t, makeDouble(t, cast(instance, fieldOffset(t, field)))); - - case LongField: - return pushReference - (t, makeLong(t, cast(instance, fieldOffset(t, field)))); - - case ObjectField: - return pushReference - (t, cast(instance, fieldOffset(t, field))); - - default: - abort(t); - } - } else { - t->exception = makeIllegalArgumentException(t); - } - } else { - t->exception = makeNullPointerException(t); + switch (code) { + case ByteField: + return cast(*instance, offset); + case BooleanField: + return cast(*instance, offset); + case CharField: + return cast(*instance, offset); + case ShortField: + return cast(*instance, offset); + case IntField: + return cast(*instance, offset); + case LongField: + return cast(*instance, offset); + case FloatField: + return cast(*instance, offset); + case DoubleField: + return cast(*instance, offset); + default: + abort(t); } +} - return 0; +jobject +Field_getObject(Thread* t, jclass, jobject instance, jint offset) +{ + return pushReference(t, cast(*instance, offset)); } void -Field_set(Thread* t, jobject this_, jobject instancep, jobject value) +Field_setPrimitive(Thread* t, jclass, jobject instance, jint code, jint offset, + jlong value) { - object field = *this_; - object v = (value ? *value : 0); - - if (fieldFlags(t, field) & ACC_STATIC) { - object* p = &arrayBody(t, classStaticTable(t, fieldClass(t, field)), - fieldOffset(t, field)); - - if (fieldCode(t, field) == ObjectField or v) { - switch (fieldCode(t, field)) { - case ByteField: - set(t, *p, makeInt(t, byteValue(t, v))); - break; - - case BooleanField: - set(t, *p, makeInt(t, booleanValue(t, v))); - break; - - case CharField: - set(t, *p, makeInt(t, charValue(t, v))); - break; - - case ShortField: - set(t, *p, makeInt(t, shortValue(t, v))); - break; - - case FloatField: - set(t, *p, makeInt(t, floatValue(t, v))); - break; - - case DoubleField: - set(t, *p, makeLong(t, longValue(t, v))); - break; - - case IntField: - case LongField: - case ObjectField: - set(t, *p, v); - break; - - default: - abort(t); - } - } 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); + switch (code) { + case ByteField: + cast(*instance, offset) = static_cast(value); + break; + case BooleanField: + cast(*instance, offset) = static_cast(value); + break; + case CharField: + cast(*instance, offset) = static_cast(value); + break; + case ShortField: + cast(*instance, offset) = static_cast(value); + break; + case IntField: + cast(*instance, offset) = static_cast(value); + break; + case LongField: + cast(*instance, offset) = static_cast(value); + break; + case FloatField: + cast(*instance, offset) = static_cast(value); + break; + case DoubleField: + cast(*instance, offset) = static_cast(value); + break; + default: + abort(t); } } +void +Field_setObject(Thread*, jclass, jobject instance, jint offset, + jobject value) +{ + cast(*instance, offset) = (value ? *value : 0); +} + jobject Constructor_make(Thread* t, jclass, jclass c) { @@ -523,6 +430,34 @@ Array_makeObjectArray(Thread* t, jclass, jclass elementType, jint length) return pushReference(t, makeObjectArray(t, *elementType, length, true)); } +jint +Float_floatToRawIntBits(Thread*, jclass, jfloat v) +{ + int32_t r; memcpy(&r, &v, 4); + return r; +} + +jfloat +Float_intBitsToFloat(Thread*, jclass, jint v) +{ + jfloat r; memcpy(&r, &v, 4); + return r; +} + +jlong +Double_doubleToRawLongBits(Thread*, jclass, jdouble v) +{ + int64_t r; memcpy(&r, &v, 8); + return r; +} + +jdouble +Double_longBitsToDouble(Thread*, jclass, jlong v) +{ + jdouble r; memcpy(&r, &v, 8); + return r; +} + jobject String_intern(Thread* t, jobject this_) { @@ -841,10 +776,14 @@ populateBuiltinMap(Thread* t, object map) { "Java_java_lang_reflect_Constructor_make", reinterpret_cast(::Constructor_make) }, - { "Java_java_lang_reflect_Field_get", - reinterpret_cast(::Field_get) }, - { "Java_java_lang_reflect_Field_set", - reinterpret_cast(::Field_set) }, + { "Java_java_lang_reflect_Field_getPrimitive", + reinterpret_cast(::Field_getPrimitive) }, + { "Java_java_lang_reflect_Field_getObject", + reinterpret_cast(::Field_getObject) }, + { "Java_java_lang_reflect_Field_setPrimitive", + reinterpret_cast(::Field_setPrimitive) }, + { "Java_java_lang_reflect_Field_setObject", + reinterpret_cast(::Field_setObject) }, { "Java_java_lang_reflect_Method_getCaller", reinterpret_cast(::Method_getCaller) },