mirror of
https://github.com/corda/corda.git
synced 2025-02-11 05:12:09 +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;
|
import java.lang.reflect.Modifier;
|
||||||
|
|
||||||
public final class Class <T> {
|
public final class Class <T> {
|
||||||
|
private static final int PrimitiveFlag = 1 << 4;
|
||||||
|
|
||||||
private short flags;
|
private short flags;
|
||||||
private byte vmFlags;
|
private byte vmFlags;
|
||||||
private byte arrayDimensions;
|
private byte arrayDimensions;
|
||||||
@ -330,14 +332,6 @@ public final class Class <T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public boolean isPrimitive() {
|
public boolean isPrimitive() {
|
||||||
return equals(boolean.class)
|
return (vmFlags & PrimitiveFlag) != 0;
|
||||||
|| equals(byte.class)
|
|
||||||
|| equals(char.class)
|
|
||||||
|| equals(short.class)
|
|
||||||
|| equals(int.class)
|
|
||||||
|| equals(long.class)
|
|
||||||
|| equals(float.class)
|
|
||||||
|| equals(double.class)
|
|
||||||
|| equals(void.class);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,9 +3,86 @@ package java.lang.reflect;
|
|||||||
public final class Array {
|
public final class Array {
|
||||||
private 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);
|
public static native int getLength(Object array);
|
||||||
|
|
||||||
@ -16,6 +93,7 @@ public final class Array {
|
|||||||
throw new NegativeArraySizeException();
|
throw new NegativeArraySizeException();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (elementType.isPrimitive()) {
|
||||||
if (elementType.equals(boolean.class)) {
|
if (elementType.equals(boolean.class)) {
|
||||||
return new boolean[length];
|
return new boolean[length];
|
||||||
} else if (elementType.equals(byte.class)) {
|
} else if (elementType.equals(byte.class)) {
|
||||||
@ -32,6 +110,9 @@ public final class Array {
|
|||||||
return new float[length];
|
return new float[length];
|
||||||
} else if (elementType.equals(double.class)) {
|
} else if (elementType.equals(double.class)) {
|
||||||
return new double[length];
|
return new double[length];
|
||||||
|
} else {
|
||||||
|
throw new IllegalArgumentException();
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
return makeObjectArray(elementType, length);
|
return makeObjectArray(elementType, length);
|
||||||
}
|
}
|
||||||
|
@ -87,6 +87,27 @@ public class Method<T> extends AccessibleObject implements Member {
|
|||||||
return types;
|
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;
|
throws InvocationTargetException, IllegalAccessException;
|
||||||
}
|
}
|
||||||
|
155
src/builtin.cpp
155
src/builtin.cpp
@ -7,16 +7,6 @@ using namespace vm;
|
|||||||
|
|
||||||
namespace {
|
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
|
inline void
|
||||||
replace(char a, char b, char* c)
|
replace(char a, char b, char* c)
|
||||||
{
|
{
|
||||||
@ -261,10 +251,10 @@ Field_setPrimitive(Thread* t, jclass, jobject instance, jint code, jint offset,
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
Field_setObject(Thread*, jclass, jobject instance, jint offset,
|
Field_setObject(Thread* t, jclass, jobject instance, jint offset,
|
||||||
jobject value)
|
jobject value)
|
||||||
{
|
{
|
||||||
cast<object>(*instance, offset) = (value ? *value : 0);
|
set(t, cast<object>(*instance, offset), (value ? *value : 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
jobject
|
jobject
|
||||||
@ -281,129 +271,26 @@ Method_getCaller(Thread* t, jclass)
|
|||||||
}
|
}
|
||||||
|
|
||||||
jobject
|
jobject
|
||||||
Method_invoke(Thread* t, jobject this_, jobject instancep,
|
Method_invoke(Thread* t, jclass, jobject method, jobject instance,
|
||||||
jobjectArray argumentsp)
|
jobjectArray arguments)
|
||||||
{
|
{
|
||||||
object method = *this_;
|
object v = run2(t, *method, (instance ? *instance : 0), *arguments);
|
||||||
|
if (t->exception) {
|
||||||
if (argumentsp) {
|
t->exception = makeInvocationTargetException(t, t->exception);
|
||||||
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) {
|
return pushReference(t, v);
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
jobject
|
jobject
|
||||||
Array_get(Thread* t, jobject array, int index)
|
Array_getObject(Thread* t, jobject array, int index)
|
||||||
{
|
{
|
||||||
if (LIKELY(array)) {
|
return pushReference(t, objectArrayBody(t, *array, index));
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
Array_set(Thread* t, jobject array, int index, jobject value)
|
Array_setObject(Thread* t, jobject array, int index, jobject value)
|
||||||
{
|
{
|
||||||
if (LIKELY(array)) {
|
set(t, objectArrayBody(t, *array, index), (value ? *value : 0));
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
jint
|
jint
|
||||||
@ -749,6 +636,16 @@ populateBuiltinMap(Thread* t, object map)
|
|||||||
{ "Java_java_lang_Throwable_trace",
|
{ "Java_java_lang_Throwable_trace",
|
||||||
reinterpret_cast<void*>(::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",
|
{ "Java_java_lang_Object_getClass",
|
||||||
reinterpret_cast<void*>(::Object_getClass) },
|
reinterpret_cast<void*>(::Object_getClass) },
|
||||||
{ "Java_java_lang_Object_notify",
|
{ "Java_java_lang_Object_notify",
|
||||||
@ -764,10 +661,10 @@ populateBuiltinMap(Thread* t, object map)
|
|||||||
{ "Java_java_lang_Object_clone",
|
{ "Java_java_lang_Object_clone",
|
||||||
reinterpret_cast<void*>(::Object_clone) },
|
reinterpret_cast<void*>(::Object_clone) },
|
||||||
|
|
||||||
{ "Java_java_lang_reflect_Array_get",
|
{ "Java_java_lang_reflect_Array_getObject",
|
||||||
reinterpret_cast<void*>(::Array_get) },
|
reinterpret_cast<void*>(::Array_getObject) },
|
||||||
{ "Java_java_lang_reflect_Array_set",
|
{ "Java_java_lang_reflect_Array_setObject",
|
||||||
reinterpret_cast<void*>(::Array_set) },
|
reinterpret_cast<void*>(::Array_setObject) },
|
||||||
{ "Java_java_lang_reflect_Array_getLength",
|
{ "Java_java_lang_reflect_Array_getLength",
|
||||||
reinterpret_cast<void*>(::Array_getLength) },
|
reinterpret_cast<void*>(::Array_getLength) },
|
||||||
{ "Java_java_lang_reflect_Array_makeObjectArray",
|
{ "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))
|
classVmFlags(t, arrayBody(t, m->types, Machine::PhantomReferenceType))
|
||||||
|= ReferenceFlag | WeakReferenceFlag;
|
|= 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);
|
m->bootstrapClassMap = makeHashMap(this, 0, 0);
|
||||||
|
|
||||||
#include "type-java-initializations.cpp"
|
#include "type-java-initializations.cpp"
|
||||||
|
@ -60,6 +60,7 @@ const unsigned ReferenceFlag = 1 << 0;
|
|||||||
const unsigned WeakReferenceFlag = 1 << 1;
|
const unsigned WeakReferenceFlag = 1 << 1;
|
||||||
const unsigned NeedInitFlag = 1 << 2;
|
const unsigned NeedInitFlag = 1 << 2;
|
||||||
const unsigned InitFlag = 1 << 3;
|
const unsigned InitFlag = 1 << 3;
|
||||||
|
const unsigned PrimitiveFlag = 1 << 4;
|
||||||
|
|
||||||
// method flags:
|
// method flags:
|
||||||
const unsigned ClassInitFlag = 1 << 0;
|
const unsigned ClassInitFlag = 1 << 0;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user