mirror of
https://github.com/corda/corda.git
synced 2025-02-05 18:49:14 +00:00
clean up Array.get(), Array.set(), and Method.invoke() implementations
This commit is contained in:
parent
d169e4eadf
commit
aa5e751e69
@ -6,6 +6,8 @@ import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Modifier;
|
||||
|
||||
public final class Class <T> {
|
||||
private static final int PrimitiveFlag = 1 << 4;
|
||||
|
||||
private short flags;
|
||||
private byte vmFlags;
|
||||
private byte arrayDimensions;
|
||||
@ -330,14 +332,6 @@ public final class Class <T> {
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -87,6 +87,27 @@ public class Method<T> 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;
|
||||
}
|
||||
|
155
src/builtin.cpp
155
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<object>(*instance, offset) = (value ? *value : 0);
|
||||
set(t, cast<object>(*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<unsigned>(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<uintptr_t>(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<uintptr_t>(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<uint8_t>
|
||||
(a, (2 * BytesPerWord) + (index * elementSize));
|
||||
if (v) {
|
||||
memcpy(p, &cast<uint8_t>(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<void*>(::Throwable_trace) },
|
||||
|
||||
{ "Java_java_lang_Float_floatToRawIntBits",
|
||||
reinterpret_cast<void*>(::Float_floatToRawIntBits) },
|
||||
{ "Java_java_lang_Float_intBitsToFloat",
|
||||
reinterpret_cast<void*>(::Float_intBitsToFloat) },
|
||||
|
||||
{ "Java_java_lang_Double_doubleToRawLongBits",
|
||||
reinterpret_cast<void*>(::Double_doubleToRawLongBits) },
|
||||
{ "Java_java_lang_Double_longBitsToDouble",
|
||||
reinterpret_cast<void*>(::Double_longBitsToDouble) },
|
||||
|
||||
{ "Java_java_lang_Object_getClass",
|
||||
reinterpret_cast<void*>(::Object_getClass) },
|
||||
{ "Java_java_lang_Object_notify",
|
||||
@ -764,10 +661,10 @@ populateBuiltinMap(Thread* t, object map)
|
||||
{ "Java_java_lang_Object_clone",
|
||||
reinterpret_cast<void*>(::Object_clone) },
|
||||
|
||||
{ "Java_java_lang_reflect_Array_get",
|
||||
reinterpret_cast<void*>(::Array_get) },
|
||||
{ "Java_java_lang_reflect_Array_set",
|
||||
reinterpret_cast<void*>(::Array_set) },
|
||||
{ "Java_java_lang_reflect_Array_getObject",
|
||||
reinterpret_cast<void*>(::Array_getObject) },
|
||||
{ "Java_java_lang_reflect_Array_setObject",
|
||||
reinterpret_cast<void*>(::Array_setObject) },
|
||||
{ "Java_java_lang_reflect_Array_getLength",
|
||||
reinterpret_cast<void*>(::Array_getLength) },
|
||||
{ "Java_java_lang_reflect_Array_makeObjectArray",
|
||||
|
@ -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"
|
||||
|
@ -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;
|
||||
|
Loading…
x
Reference in New Issue
Block a user