mirror of
https://github.com/corda/corda.git
synced 2025-01-05 20:54:13 +00:00
fix various Android test suite regressions and add more reflection tests
Most of these regressions were simply due to testing a lot more stuff, esp. annotations and reflection, revealing holes in the Android compatibility code. There are still some holes, but at least the suite is passing (except for a fragile test in Serialize.java which I will open an issue for). Sorry this is such a big commit; there was more to address than I initially expected.
This commit is contained in:
parent
39e3850ed8
commit
7056315c18
@ -441,6 +441,39 @@ public class Classes {
|
|||||||
return array;
|
return array;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static int countFields(VMClass vmClass, boolean publicOnly) {
|
||||||
|
int count = 0;
|
||||||
|
if (vmClass.fieldTable != null) {
|
||||||
|
for (int i = 0; i < vmClass.fieldTable.length; ++i) {
|
||||||
|
if ((! publicOnly)
|
||||||
|
|| ((vmClass.fieldTable[i].flags & Modifier.PUBLIC))
|
||||||
|
!= 0)
|
||||||
|
{
|
||||||
|
++ count;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Field[] getFields(VMClass vmClass, boolean publicOnly) {
|
||||||
|
Field[] array = new Field[countFields(vmClass, publicOnly)];
|
||||||
|
if (vmClass.fieldTable != null) {
|
||||||
|
Classes.link(vmClass);
|
||||||
|
|
||||||
|
int ai = 0;
|
||||||
|
for (int i = 0; i < vmClass.fieldTable.length; ++i) {
|
||||||
|
if (((vmClass.fieldTable[i].flags & Modifier.PUBLIC) != 0)
|
||||||
|
|| (! publicOnly))
|
||||||
|
{
|
||||||
|
array[ai++] = makeField(SystemClassLoader.getClass(vmClass), i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return array;
|
||||||
|
}
|
||||||
|
|
||||||
public static Annotation getAnnotation(ClassLoader loader, Object[] a) {
|
public static Annotation getAnnotation(ClassLoader loader, Object[] a) {
|
||||||
if (a[0] == null) {
|
if (a[0] == null) {
|
||||||
a[0] = Proxy.newProxyInstance
|
a[0] = Proxy.newProxyInstance
|
||||||
@ -469,7 +502,21 @@ public class Classes {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static int index(VMMethod m) {
|
||||||
|
VMMethod[] table = m.class_.methodTable;
|
||||||
|
for (int i = 0; i < table.length; ++i) {
|
||||||
|
if (m == table[i]) return i;
|
||||||
|
}
|
||||||
|
throw new AssertionError();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Method makeMethod(VMMethod m) {
|
||||||
|
return makeMethod(SystemClassLoader.getClass(m.class_), index(m));
|
||||||
|
}
|
||||||
|
|
||||||
public static native Method makeMethod(Class c, int slot);
|
public static native Method makeMethod(Class c, int slot);
|
||||||
|
|
||||||
|
public static native Field makeField(Class c, int slot);
|
||||||
|
|
||||||
private static native void acquireClassLock();
|
private static native void acquireClassLock();
|
||||||
|
|
||||||
|
@ -11,4 +11,5 @@
|
|||||||
package java.lang.annotation;
|
package java.lang.annotation;
|
||||||
|
|
||||||
public interface Annotation {
|
public interface Annotation {
|
||||||
|
Class<? extends Annotation> annotationType();
|
||||||
}
|
}
|
||||||
|
@ -161,6 +161,40 @@ public class Field<T> extends AccessibleObject {
|
|||||||
return ((Double) get(instance)).doubleValue();
|
return ((Double) get(instance)).doubleValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean matchType(Object value) {
|
||||||
|
switch (vmField.code) {
|
||||||
|
case ByteField:
|
||||||
|
return value instanceof Byte;
|
||||||
|
|
||||||
|
case BooleanField:
|
||||||
|
return value instanceof Boolean;
|
||||||
|
|
||||||
|
case CharField:
|
||||||
|
return value instanceof Character;
|
||||||
|
|
||||||
|
case ShortField:
|
||||||
|
return value instanceof Short;
|
||||||
|
|
||||||
|
case IntField:
|
||||||
|
return value instanceof Integer;
|
||||||
|
|
||||||
|
case LongField:
|
||||||
|
return value instanceof Long;
|
||||||
|
|
||||||
|
case FloatField:
|
||||||
|
return value instanceof Float;
|
||||||
|
|
||||||
|
case DoubleField:
|
||||||
|
return value instanceof Double;
|
||||||
|
|
||||||
|
case ObjectField:
|
||||||
|
return value == null || getType().isInstance(value);
|
||||||
|
|
||||||
|
default:
|
||||||
|
throw new Error();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public void set(Object instance, Object value)
|
public void set(Object instance, Object value)
|
||||||
throws IllegalAccessException
|
throws IllegalAccessException
|
||||||
{
|
{
|
||||||
@ -173,6 +207,10 @@ public class Field<T> extends AccessibleObject {
|
|||||||
throw new IllegalArgumentException();
|
throw new IllegalArgumentException();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (! matchType(value)) {
|
||||||
|
throw new IllegalArgumentException();
|
||||||
|
}
|
||||||
|
|
||||||
Classes.initialize(vmField.class_);
|
Classes.initialize(vmField.class_);
|
||||||
|
|
||||||
switch (vmField.code) {
|
switch (vmField.code) {
|
||||||
@ -212,14 +250,7 @@ public class Field<T> extends AccessibleObject {
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case ObjectField:
|
case ObjectField:
|
||||||
if (value == null || getType().isInstance(value)) {
|
setObject(target, vmField.offset, value);
|
||||||
setObject(target, vmField.offset, value);
|
|
||||||
} else {
|
|
||||||
throw new IllegalArgumentException
|
|
||||||
("needed " + getType() + ", got "
|
|
||||||
+ value.getClass().getName() +
|
|
||||||
" when setting " + Class.getName(vmField.class_) + "." + getName());
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
@ -384,7 +384,7 @@ public class Proxy {
|
|||||||
ConstantPool.addUtf8(pool, Classes.toString(m.spec)),
|
ConstantPool.addUtf8(pool, Classes.toString(m.spec)),
|
||||||
makeInvokeCode(pool, name, m.spec, m.parameterCount,
|
makeInvokeCode(pool, name, m.spec, m.parameterCount,
|
||||||
m.parameterFootprint, methodTable.size())));
|
m.parameterFootprint, methodTable.size())));
|
||||||
refs.add(new Method(m));
|
refs.add(Classes.makeMethod(m));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -674,6 +674,78 @@ getFinder(Thread* t, const char* name, unsigned nameLength)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
object
|
||||||
|
getDeclaredClasses(Thread* t, object c, bool publicOnly)
|
||||||
|
{
|
||||||
|
object addendum = classAddendum(t, c);
|
||||||
|
if (addendum) {
|
||||||
|
object table = classAddendumInnerClassTable(t, addendum);
|
||||||
|
if (table) {
|
||||||
|
PROTECT(t, table);
|
||||||
|
|
||||||
|
unsigned count = 0;
|
||||||
|
for (unsigned i = 0; i < arrayLength(t, table); ++i) {
|
||||||
|
object reference = arrayBody(t, table, i);
|
||||||
|
object outer = innerClassReferenceOuter(t, reference);
|
||||||
|
if (outer and byteArrayEqual(t, outer, className(t, c))
|
||||||
|
and ((not publicOnly)
|
||||||
|
or (innerClassReferenceFlags(t, reference) & ACC_PUBLIC)))
|
||||||
|
{
|
||||||
|
++ count;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
object result = makeObjectArray(t, type(t, Machine::JclassType), count);
|
||||||
|
PROTECT(t, result);
|
||||||
|
|
||||||
|
for (unsigned i = 0; i < arrayLength(t, table); ++i) {
|
||||||
|
object reference = arrayBody(t, table, i);
|
||||||
|
object outer = innerClassReferenceOuter(t, reference);
|
||||||
|
if (outer and byteArrayEqual(t, outer, className(t, c))
|
||||||
|
and ((not publicOnly)
|
||||||
|
or (innerClassReferenceFlags(t, reference) & ACC_PUBLIC)))
|
||||||
|
{
|
||||||
|
object inner = getJClass
|
||||||
|
(t, resolveClass
|
||||||
|
(t, classLoader(t, c),
|
||||||
|
innerClassReferenceInner(t, arrayBody(t, table, i))));
|
||||||
|
|
||||||
|
-- count;
|
||||||
|
set(t, result, ArrayBody + (count * BytesPerWord), inner);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return makeObjectArray(t, type(t, Machine::JclassType), 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
object
|
||||||
|
getDeclaringClass(Thread* t, object c)
|
||||||
|
{
|
||||||
|
object addendum = classAddendum(t, c);
|
||||||
|
if (addendum) {
|
||||||
|
object table = classAddendumInnerClassTable(t, addendum);
|
||||||
|
if (table) {
|
||||||
|
for (unsigned i = 0; i < arrayLength(t, table); ++i) {
|
||||||
|
object reference = arrayBody(t, table, i);
|
||||||
|
if (strcmp
|
||||||
|
(&byteArrayBody(t, innerClassReferenceInner(t, reference), 0),
|
||||||
|
&byteArrayBody(t, className(t, c), 0)) == 0)
|
||||||
|
{
|
||||||
|
return getJClass
|
||||||
|
(t, resolveClass
|
||||||
|
(t, classLoader(t, c), innerClassReferenceOuter(t, reference)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace vm
|
} // namespace vm
|
||||||
|
|
||||||
#endif//CLASSPATH_COMMON_H
|
#endif//CLASSPATH_COMMON_H
|
||||||
|
@ -142,11 +142,12 @@ makeField(Thread* t, object c, unsigned index)
|
|||||||
|
|
||||||
PROTECT(t, field);
|
PROTECT(t, field);
|
||||||
|
|
||||||
object type = resolveClassBySpec
|
object type = getJClass
|
||||||
(t, classLoader(t, fieldClass(t, field)),
|
(t, resolveClassBySpec
|
||||||
reinterpret_cast<char*>
|
(t, classLoader(t, fieldClass(t, field)),
|
||||||
(&byteArrayBody(t, fieldSpec(t, field), 0)),
|
reinterpret_cast<char*>
|
||||||
byteArrayLength(t, fieldSpec(t, field)) - 1);
|
(&byteArrayBody(t, fieldSpec(t, field), 0)),
|
||||||
|
byteArrayLength(t, fieldSpec(t, field)) - 1));
|
||||||
PROTECT(t, type);
|
PROTECT(t, type);
|
||||||
|
|
||||||
object name = t->m->classpath->makeString
|
object name = t->m->classpath->makeString
|
||||||
@ -604,6 +605,177 @@ closeMemoryMappedFile(Thread* t, object method, uintptr_t* arguments)
|
|||||||
file);
|
file);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
matchType(Thread* t, object field, object o)
|
||||||
|
{
|
||||||
|
switch (fieldCode(t, field)) {
|
||||||
|
case ByteField:
|
||||||
|
return objectClass(t, o) == type(t, Machine::ByteType);
|
||||||
|
|
||||||
|
case BooleanField:
|
||||||
|
return objectClass(t, o) == type(t, Machine::BooleanType);
|
||||||
|
|
||||||
|
case CharField:
|
||||||
|
return objectClass(t, o) == type(t, Machine::CharType);
|
||||||
|
|
||||||
|
case ShortField:
|
||||||
|
return objectClass(t, o) == type(t, Machine::ShortType);
|
||||||
|
|
||||||
|
case IntField:
|
||||||
|
return objectClass(t, o) == type(t, Machine::IntType);
|
||||||
|
|
||||||
|
case LongField:
|
||||||
|
return objectClass(t, o) == type(t, Machine::LongType);
|
||||||
|
|
||||||
|
case FloatField:
|
||||||
|
return objectClass(t, o) == type(t, Machine::FloatType);
|
||||||
|
|
||||||
|
case DoubleField:
|
||||||
|
return objectClass(t, o) == type(t, Machine::DoubleType);
|
||||||
|
|
||||||
|
case ObjectField:
|
||||||
|
if (o == 0) {
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
PROTECT(t, o);
|
||||||
|
|
||||||
|
object spec;
|
||||||
|
if (byteArrayBody(t, fieldSpec(t, field), 0) == '[') {
|
||||||
|
spec = fieldSpec(t, field);;
|
||||||
|
} else {
|
||||||
|
spec = makeByteArray(t, byteArrayLength(t, fieldSpec(t, field)) - 2);
|
||||||
|
|
||||||
|
memcpy(&byteArrayBody(t, spec, 0),
|
||||||
|
&byteArrayBody(t, fieldSpec(t, field), 1),
|
||||||
|
byteArrayLength(t, fieldSpec(t, field)) - 3);
|
||||||
|
|
||||||
|
byteArrayBody
|
||||||
|
(t, spec, byteArrayLength(t, fieldSpec(t, field)) - 3) = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return instanceOf
|
||||||
|
(t, resolveClass(t, classLoader(t, fieldClass(t, field)), spec), o);
|
||||||
|
}
|
||||||
|
|
||||||
|
default: abort(t);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
object
|
||||||
|
getField(Thread* t, object field, object instance)
|
||||||
|
{
|
||||||
|
PROTECT(t, field);
|
||||||
|
PROTECT(t, instance);
|
||||||
|
|
||||||
|
initClass(t, fieldClass(t, field));
|
||||||
|
|
||||||
|
object target;
|
||||||
|
if (fieldFlags(t, field) & ACC_STATIC) {
|
||||||
|
target = classStaticTable(t, fieldClass(t, field));
|
||||||
|
} else if (instanceOf(t, fieldClass(t, field), instance)){
|
||||||
|
target = instance;
|
||||||
|
} else {
|
||||||
|
throwNew(t, Machine::IllegalArgumentExceptionType);
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned offset = fieldOffset(t, field);
|
||||||
|
switch (fieldCode(t, field)) {
|
||||||
|
case ByteField:
|
||||||
|
return makeByte(t, fieldAtOffset<int8_t>(target, offset));
|
||||||
|
|
||||||
|
case BooleanField:
|
||||||
|
return makeBoolean(t, fieldAtOffset<int8_t>(target, offset));
|
||||||
|
|
||||||
|
case CharField:
|
||||||
|
return makeChar(t, fieldAtOffset<int16_t>(target, offset));
|
||||||
|
|
||||||
|
case ShortField:
|
||||||
|
return makeShort(t, fieldAtOffset<int16_t>(target, offset));
|
||||||
|
|
||||||
|
case IntField:
|
||||||
|
return makeInt(t, fieldAtOffset<int32_t>(target, offset));
|
||||||
|
|
||||||
|
case LongField:
|
||||||
|
return makeLong(t, fieldAtOffset<int64_t>(target, offset));
|
||||||
|
|
||||||
|
case FloatField:
|
||||||
|
return makeFloat(t, fieldAtOffset<int32_t>(target, offset));
|
||||||
|
|
||||||
|
case DoubleField:
|
||||||
|
return makeDouble(t, fieldAtOffset<int64_t>(target, offset));
|
||||||
|
|
||||||
|
case ObjectField:
|
||||||
|
return fieldAtOffset<object>(target, offset);
|
||||||
|
|
||||||
|
default: abort(t);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
setField(Thread* t, object field, object instance, object value)
|
||||||
|
{
|
||||||
|
PROTECT(t, field);
|
||||||
|
PROTECT(t, instance);
|
||||||
|
PROTECT(t, value);
|
||||||
|
|
||||||
|
if (not matchType(t, field, value)) {
|
||||||
|
throwNew(t, Machine::IllegalArgumentExceptionType);
|
||||||
|
}
|
||||||
|
|
||||||
|
object target;
|
||||||
|
if ((fieldFlags(t, field) & ACC_STATIC) != 0) {
|
||||||
|
target = classStaticTable(t, fieldClass(t, field));
|
||||||
|
} else if (instanceOf(t, fieldClass(t, field), instance)){
|
||||||
|
target = instance;
|
||||||
|
} else {
|
||||||
|
throwNew(t, Machine::IllegalArgumentExceptionType);
|
||||||
|
}
|
||||||
|
PROTECT(t, target);
|
||||||
|
|
||||||
|
initClass(t, fieldClass(t, field));
|
||||||
|
|
||||||
|
unsigned offset = fieldOffset(t, field);
|
||||||
|
switch (fieldCode(t, field)) {
|
||||||
|
case ByteField:
|
||||||
|
fieldAtOffset<int8_t>(target, offset) = byteValue(t, value);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case BooleanField:
|
||||||
|
fieldAtOffset<int8_t>(target, offset) = booleanValue(t, value);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case CharField:
|
||||||
|
fieldAtOffset<int16_t>(target, offset) = charValue(t, value);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ShortField:
|
||||||
|
fieldAtOffset<int16_t>(target, offset) = shortValue(t, value);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case IntField:
|
||||||
|
fieldAtOffset<int32_t>(target, offset) = intValue(t, value);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case LongField:
|
||||||
|
fieldAtOffset<int64_t>(target, offset) = longValue(t, value);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case FloatField:
|
||||||
|
fieldAtOffset<int32_t>(target, offset) = floatValue(t, value);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DoubleField:
|
||||||
|
fieldAtOffset<int64_t>(target, offset) = doubleValue(t, value);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ObjectField:
|
||||||
|
set(t, target, offset, value);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default: abort(t);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace local
|
} // namespace local
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
@ -788,6 +960,14 @@ Avian_java_lang_String_length
|
|||||||
return stringLength(t, reinterpret_cast<object>(arguments[0]));
|
return stringLength(t, reinterpret_cast<object>(arguments[0]));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extern "C" AVIAN_EXPORT int64_t JNICALL
|
||||||
|
Avian_java_lang_String_intern
|
||||||
|
(Thread* t, object, uintptr_t* arguments)
|
||||||
|
{
|
||||||
|
return reinterpret_cast<intptr_t>
|
||||||
|
(intern(t, reinterpret_cast<object>(arguments[0])));
|
||||||
|
}
|
||||||
|
|
||||||
extern "C" AVIAN_EXPORT int64_t JNICALL
|
extern "C" AVIAN_EXPORT int64_t JNICALL
|
||||||
Avian_java_lang_String_charAt
|
Avian_java_lang_String_charAt
|
||||||
(Thread* t, object, uintptr_t* arguments)
|
(Thread* t, object, uintptr_t* arguments)
|
||||||
@ -849,6 +1029,63 @@ Avian_java_lang_Class_getInterfaces
|
|||||||
(makeObjectArray(t, type(t, Machine::JclassType), 0));
|
(makeObjectArray(t, type(t, Machine::JclassType), 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extern "C" AVIAN_EXPORT int64_t JNICALL
|
||||||
|
Avian_java_lang_Class_getDeclaredClasses
|
||||||
|
(Thread* t, object, uintptr_t* arguments)
|
||||||
|
{
|
||||||
|
return reinterpret_cast<intptr_t>
|
||||||
|
(getDeclaredClasses
|
||||||
|
(t, jclassVmClass(t, reinterpret_cast<object>(arguments[0])),
|
||||||
|
arguments[1]));
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" AVIAN_EXPORT int64_t JNICALL
|
||||||
|
Avian_java_lang_Class_getDeclaringClass
|
||||||
|
(Thread* t, object, uintptr_t* arguments)
|
||||||
|
{
|
||||||
|
return reinterpret_cast<intptr_t>
|
||||||
|
(getDeclaringClass
|
||||||
|
(t, jclassVmClass(t, reinterpret_cast<object>(arguments[0]))));
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" AVIAN_EXPORT int64_t JNICALL
|
||||||
|
Avian_java_lang_Class_getEnclosingMethod
|
||||||
|
(Thread* t, object, uintptr_t* arguments)
|
||||||
|
{
|
||||||
|
object c = jclassVmClass(t, reinterpret_cast<object>(arguments[0]));
|
||||||
|
PROTECT(t, c);
|
||||||
|
|
||||||
|
object addendum = classAddendum(t, c);
|
||||||
|
if (addendum) {
|
||||||
|
object enclosingClass = classAddendumEnclosingClass(t, addendum);
|
||||||
|
if (enclosingClass) {
|
||||||
|
PROTECT(t, enclosingClass);
|
||||||
|
|
||||||
|
enclosingClass = getJClass
|
||||||
|
(t, resolveClass(t, classLoader(t, c), enclosingClass));
|
||||||
|
|
||||||
|
object enclosingMethod = classAddendumEnclosingMethod(t, addendum);
|
||||||
|
if (enclosingMethod) {
|
||||||
|
PROTECT(t, enclosingMethod);
|
||||||
|
|
||||||
|
return reinterpret_cast<uintptr_t>
|
||||||
|
(t->m->classpath->makeJMethod
|
||||||
|
(t, findMethodInClass
|
||||||
|
(t, enclosingClass, pairFirst(t, enclosingMethod),
|
||||||
|
pairSecond(t, enclosingMethod))));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" AVIAN_EXPORT int64_t JNICALL
|
||||||
|
Avian_java_lang_Class_getEnclosingConstructor
|
||||||
|
(Thread* t, object method, uintptr_t* arguments)
|
||||||
|
{
|
||||||
|
return Avian_java_lang_Class_getEnclosingMethod(t, method, arguments);
|
||||||
|
}
|
||||||
|
|
||||||
extern "C" AVIAN_EXPORT int64_t JNICALL
|
extern "C" AVIAN_EXPORT int64_t JNICALL
|
||||||
Avian_java_lang_Class_newInstanceImpl
|
Avian_java_lang_Class_newInstanceImpl
|
||||||
(Thread* t, object, uintptr_t* arguments)
|
(Thread* t, object, uintptr_t* arguments)
|
||||||
@ -1201,6 +1438,50 @@ Avian_dalvik_system_VMStack_getCallingClassLoader
|
|||||||
return reinterpret_cast<uintptr_t>(v.loader);
|
return reinterpret_cast<uintptr_t>(v.loader);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extern "C" AVIAN_EXPORT int64_t JNICALL
|
||||||
|
Avian_dalvik_system_VMStack_getClasses
|
||||||
|
(Thread* t, object, uintptr_t*)
|
||||||
|
{
|
||||||
|
class Visitor: public Processor::StackVisitor {
|
||||||
|
public:
|
||||||
|
Visitor(Thread* t):
|
||||||
|
t(t), array(0), counter(0)
|
||||||
|
{ }
|
||||||
|
|
||||||
|
virtual bool visit(Processor::StackWalker* walker) {
|
||||||
|
if (counter < 2) {
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
if (array == 0) {
|
||||||
|
array = makeObjectArray
|
||||||
|
(t, type(t, Machine::JclassType), walker->count());
|
||||||
|
}
|
||||||
|
|
||||||
|
object c = getJClass(t, methodClass(t, walker->method()));
|
||||||
|
|
||||||
|
assert(t, counter - 2 < objectArrayLength(t, array));
|
||||||
|
|
||||||
|
set(t, array, ArrayBody + ((counter - 2) * BytesPerWord), c);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
++ counter;
|
||||||
|
}
|
||||||
|
|
||||||
|
Thread* t;
|
||||||
|
object array;
|
||||||
|
unsigned counter;
|
||||||
|
} v(t);
|
||||||
|
|
||||||
|
PROTECT(t, v.array);
|
||||||
|
|
||||||
|
t->m->processor->walkStack(t, &v);
|
||||||
|
|
||||||
|
return reinterpret_cast<uintptr_t>
|
||||||
|
(v.array ? v.array : makeObjectArray(t, type(t, Machine::JclassType), 0));
|
||||||
|
}
|
||||||
|
|
||||||
extern "C" AVIAN_EXPORT int64_t JNICALL
|
extern "C" AVIAN_EXPORT int64_t JNICALL
|
||||||
Avian_java_lang_Math_min
|
Avian_java_lang_Math_min
|
||||||
(Thread*, object, uintptr_t* arguments)
|
(Thread*, object, uintptr_t* arguments)
|
||||||
@ -1391,6 +1672,23 @@ Avian_java_lang_Class_isPrimitive
|
|||||||
& PrimitiveFlag) != 0;
|
& PrimitiveFlag) != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extern "C" AVIAN_EXPORT int64_t JNICALL
|
||||||
|
Avian_java_lang_Class_isAnonymousClass
|
||||||
|
(Thread* t, object, uintptr_t* arguments)
|
||||||
|
{
|
||||||
|
object name = className
|
||||||
|
(t, jclassVmClass(t, reinterpret_cast<object>(arguments[0])));
|
||||||
|
|
||||||
|
for (unsigned i = 0; i < byteArrayLength(t, name) - 1; ++i) {
|
||||||
|
int c = byteArrayBody(t, name, i);
|
||||||
|
if (c != '$' and (c < '0' or c > '9')) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
extern "C" AVIAN_EXPORT int64_t JNICALL
|
extern "C" AVIAN_EXPORT int64_t JNICALL
|
||||||
Avian_java_lang_Class_getClassLoader
|
Avian_java_lang_Class_getClassLoader
|
||||||
(Thread* t, object, uintptr_t* arguments)
|
(Thread* t, object, uintptr_t* arguments)
|
||||||
@ -1446,6 +1744,23 @@ Avian_java_lang_Class_getDeclaredMethods
|
|||||||
(t->m->processor->invoke(t, get, 0, jclassVmClass(t, c), publicOnly));
|
(t->m->processor->invoke(t, get, 0, jclassVmClass(t, c), publicOnly));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extern "C" AVIAN_EXPORT int64_t JNICALL
|
||||||
|
Avian_java_lang_Class_getDeclaredFields
|
||||||
|
(Thread* t, object, uintptr_t* arguments)
|
||||||
|
{
|
||||||
|
object c = reinterpret_cast<object>(arguments[0]);
|
||||||
|
PROTECT(t, c);
|
||||||
|
|
||||||
|
bool publicOnly = arguments[1];
|
||||||
|
|
||||||
|
object get = resolveMethod
|
||||||
|
(t, root(t, Machine::BootLoader), "avian/Classes", "getFields",
|
||||||
|
"(Lavian/VMClass;Z)[Ljava/lang/reflect/Field;");
|
||||||
|
|
||||||
|
return reinterpret_cast<uintptr_t>
|
||||||
|
(t->m->processor->invoke(t, get, 0, jclassVmClass(t, c), publicOnly));
|
||||||
|
}
|
||||||
|
|
||||||
extern "C" AVIAN_EXPORT int64_t JNICALL
|
extern "C" AVIAN_EXPORT int64_t JNICALL
|
||||||
Avian_java_lang_reflect_Method_invokeNative
|
Avian_java_lang_reflect_Method_invokeNative
|
||||||
(Thread* t, object, uintptr_t* arguments)
|
(Thread* t, object, uintptr_t* arguments)
|
||||||
@ -1581,6 +1896,31 @@ Avian_java_lang_reflect_Method_getDeclaredAnnotations
|
|||||||
0));
|
0));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extern "C" AVIAN_EXPORT int64_t JNICALL
|
||||||
|
Avian_java_lang_reflect_Method_getDefaultValue
|
||||||
|
(Thread* t, object, uintptr_t* arguments)
|
||||||
|
{
|
||||||
|
object method = arrayBody
|
||||||
|
(t, classMethodTable
|
||||||
|
(t, jclassVmClass(t, reinterpret_cast<object>(arguments[1]))),
|
||||||
|
arguments[2]);
|
||||||
|
|
||||||
|
object addendum = methodAddendum(t, method);
|
||||||
|
if (addendum) {
|
||||||
|
object get = resolveMethod
|
||||||
|
(t, root(t, Machine::BootLoader), "avian/Classes",
|
||||||
|
"getAnnotationDefaultValue",
|
||||||
|
"(Ljava/lang/ClassLoader;Lavian/MethodAddendum;)"
|
||||||
|
"Ljava/lang/Object;");
|
||||||
|
|
||||||
|
return reinterpret_cast<uintptr_t>
|
||||||
|
(t->m->processor->invoke
|
||||||
|
(t, get, 0, classLoader(t, methodClass(t, method)), addendum));
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
extern "C" AVIAN_EXPORT int64_t JNICALL
|
extern "C" AVIAN_EXPORT int64_t JNICALL
|
||||||
Avian_java_lang_reflect_Constructor_constructNative
|
Avian_java_lang_reflect_Constructor_constructNative
|
||||||
(Thread* t, object, uintptr_t* arguments)
|
(Thread* t, object, uintptr_t* arguments)
|
||||||
@ -1589,6 +1929,9 @@ Avian_java_lang_reflect_Constructor_constructNative
|
|||||||
PROTECT(t, args);
|
PROTECT(t, args);
|
||||||
|
|
||||||
object c = jclassVmClass(t, reinterpret_cast<object>(arguments[2]));
|
object c = jclassVmClass(t, reinterpret_cast<object>(arguments[2]));
|
||||||
|
PROTECT(t, c);
|
||||||
|
|
||||||
|
initClass(t, c);
|
||||||
|
|
||||||
object method = arrayBody(t, classMethodTable(t, c), arguments[4]);
|
object method = arrayBody(t, classMethodTable(t, c), arguments[4]);
|
||||||
PROTECT(t, method);
|
PROTECT(t, method);
|
||||||
@ -1609,16 +1952,84 @@ Avian_java_lang_reflect_Field_getField
|
|||||||
(t, classFieldTable
|
(t, classFieldTable
|
||||||
(t, jclassVmClass(t, reinterpret_cast<object>(arguments[2]))),
|
(t, jclassVmClass(t, reinterpret_cast<object>(arguments[2]))),
|
||||||
arguments[4]);
|
arguments[4]);
|
||||||
|
|
||||||
|
PROTECT(t, field);
|
||||||
|
|
||||||
if (fieldFlags(t, field) & ACC_STATIC) {
|
object instance = reinterpret_cast<object>(arguments[1]);
|
||||||
return reinterpret_cast<uintptr_t>
|
PROTECT(t, instance);
|
||||||
(fieldAtOffset<object>
|
|
||||||
(classStaticTable(t, fieldClass(t, field)), fieldOffset(t, field)));
|
return reinterpret_cast<intptr_t>(local::getField(t, field, instance));
|
||||||
} else {
|
}
|
||||||
return reinterpret_cast<uintptr_t>
|
|
||||||
(fieldAtOffset<object>
|
extern "C" AVIAN_EXPORT int64_t JNICALL
|
||||||
(reinterpret_cast<object>(arguments[1]), fieldOffset(t, field)));
|
Avian_java_lang_reflect_Field_getIField
|
||||||
}
|
(Thread* t, object, uintptr_t* arguments)
|
||||||
|
{
|
||||||
|
object field = arrayBody
|
||||||
|
(t, classFieldTable
|
||||||
|
(t, jclassVmClass(t, reinterpret_cast<object>(arguments[2]))),
|
||||||
|
arguments[4]);
|
||||||
|
|
||||||
|
PROTECT(t, field);
|
||||||
|
|
||||||
|
object instance = reinterpret_cast<object>(arguments[1]);
|
||||||
|
PROTECT(t, instance);
|
||||||
|
|
||||||
|
return intValue(t, local::getField(t, field, instance));
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" AVIAN_EXPORT int64_t JNICALL
|
||||||
|
Avian_java_lang_reflect_Field_getJField
|
||||||
|
(Thread* t, object, uintptr_t* arguments)
|
||||||
|
{
|
||||||
|
object field = arrayBody
|
||||||
|
(t, classFieldTable
|
||||||
|
(t, jclassVmClass(t, reinterpret_cast<object>(arguments[2]))),
|
||||||
|
arguments[4]);
|
||||||
|
|
||||||
|
PROTECT(t, field);
|
||||||
|
|
||||||
|
object instance = reinterpret_cast<object>(arguments[1]);
|
||||||
|
PROTECT(t, instance);
|
||||||
|
|
||||||
|
return longValue(t, local::getField(t, field, instance));
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" AVIAN_EXPORT void JNICALL
|
||||||
|
Avian_java_lang_reflect_Field_setField
|
||||||
|
(Thread* t, object, uintptr_t* arguments)
|
||||||
|
{
|
||||||
|
object field = arrayBody
|
||||||
|
(t, classFieldTable
|
||||||
|
(t, jclassVmClass(t, reinterpret_cast<object>(arguments[2]))),
|
||||||
|
arguments[4]);
|
||||||
|
|
||||||
|
PROTECT(t, field);
|
||||||
|
|
||||||
|
object instance = reinterpret_cast<object>(arguments[1]);
|
||||||
|
PROTECT(t, instance);
|
||||||
|
|
||||||
|
object value = reinterpret_cast<object>(arguments[6]);
|
||||||
|
PROTECT(t, value);
|
||||||
|
|
||||||
|
local::setField(t, field, instance, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" AVIAN_EXPORT void JNICALL
|
||||||
|
Avian_java_lang_reflect_Field_setIField
|
||||||
|
(Thread* t, object, uintptr_t* arguments)
|
||||||
|
{
|
||||||
|
object field = arrayBody
|
||||||
|
(t, classFieldTable
|
||||||
|
(t, jclassVmClass(t, reinterpret_cast<object>(arguments[2]))),
|
||||||
|
arguments[4]);
|
||||||
|
|
||||||
|
object instance = reinterpret_cast<object>(arguments[1]);
|
||||||
|
PROTECT(t, instance);
|
||||||
|
|
||||||
|
object value = makeInt(t, arguments[7]);
|
||||||
|
|
||||||
|
local::setField(t, field, instance, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" AVIAN_EXPORT int64_t JNICALL
|
extern "C" AVIAN_EXPORT int64_t JNICALL
|
||||||
@ -1632,6 +2043,71 @@ Avian_java_lang_reflect_Field_getFieldModifiers
|
|||||||
arguments[2]));
|
arguments[2]));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extern "C" AVIAN_EXPORT int64_t JNICALL
|
||||||
|
Avian_java_lang_reflect_Field_getAnnotation
|
||||||
|
(Thread* t, object, uintptr_t* arguments)
|
||||||
|
{
|
||||||
|
object field = arrayBody
|
||||||
|
(t, classFieldTable
|
||||||
|
(t, jclassVmClass(t, reinterpret_cast<object>(arguments[0]))),
|
||||||
|
arguments[1]);
|
||||||
|
|
||||||
|
object addendum = fieldAddendum(t, field);
|
||||||
|
if (addendum) {
|
||||||
|
object table = addendumAnnotationTable(t, addendum);
|
||||||
|
if (table) {
|
||||||
|
for (unsigned i = 0; i < objectArrayLength(t, table); ++i) {
|
||||||
|
if (objectArrayBody(t, objectArrayBody(t, table, i), 1)
|
||||||
|
== reinterpret_cast<object>(arguments[2]))
|
||||||
|
{
|
||||||
|
PROTECT(t, field);
|
||||||
|
PROTECT(t, table);
|
||||||
|
|
||||||
|
object get = resolveMethod
|
||||||
|
(t, root(t, Machine::BootLoader), "avian/Classes", "getAnnotation",
|
||||||
|
"(Ljava/lang/ClassLoader;[Ljava/lang/Object;)"
|
||||||
|
"Ljava/lang/annotation/Annotation;");
|
||||||
|
|
||||||
|
return reinterpret_cast<uintptr_t>
|
||||||
|
(t->m->processor->invoke
|
||||||
|
(t, get, 0, classLoader(t, fieldClass(t, field)),
|
||||||
|
objectArrayBody(t, table, i)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" AVIAN_EXPORT int64_t JNICALL
|
||||||
|
Avian_java_lang_reflect_Field_getSignatureAnnotation
|
||||||
|
(Thread* t, object, uintptr_t* arguments)
|
||||||
|
{
|
||||||
|
object field = arrayBody
|
||||||
|
(t, classFieldTable
|
||||||
|
(t, jclassVmClass(t, reinterpret_cast<object>(arguments[1]))),
|
||||||
|
arguments[2]);
|
||||||
|
|
||||||
|
object addendum = fieldAddendum(t, field);
|
||||||
|
if (addendum) {
|
||||||
|
object signature = addendumSignature(t, addendum);
|
||||||
|
if (signature) {
|
||||||
|
object array = makeObjectArray(t, 1);
|
||||||
|
PROTECT(t, array);
|
||||||
|
|
||||||
|
object string = t->m->classpath->makeString
|
||||||
|
(t, signature, 0, byteArrayLength(t, signature) - 1);
|
||||||
|
|
||||||
|
set(t, array, ArrayBody, string);
|
||||||
|
|
||||||
|
return reinterpret_cast<uintptr_t>(array);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return reinterpret_cast<uintptr_t>(makeObjectArray(t, 0));
|
||||||
|
}
|
||||||
|
|
||||||
extern "C" AVIAN_EXPORT int64_t JNICALL
|
extern "C" AVIAN_EXPORT int64_t JNICALL
|
||||||
Avian_java_lang_Throwable_nativeFillInStackTrace
|
Avian_java_lang_Throwable_nativeFillInStackTrace
|
||||||
(Thread* t, object, uintptr_t*)
|
(Thread* t, object, uintptr_t*)
|
||||||
@ -1656,6 +2132,15 @@ Avian_avian_Classes_makeMethod
|
|||||||
(t, reinterpret_cast<object>(arguments[0]), arguments[1]));
|
(t, reinterpret_cast<object>(arguments[0]), arguments[1]));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extern "C" AVIAN_EXPORT int64_t JNICALL
|
||||||
|
Avian_avian_Classes_makeField
|
||||||
|
(Thread* t, object, uintptr_t* arguments)
|
||||||
|
{
|
||||||
|
return reinterpret_cast<uintptr_t>
|
||||||
|
(local::makeField
|
||||||
|
(t, reinterpret_cast<object>(arguments[0]), arguments[1]));
|
||||||
|
}
|
||||||
|
|
||||||
extern "C" AVIAN_EXPORT int64_t JNICALL
|
extern "C" AVIAN_EXPORT int64_t JNICALL
|
||||||
Avian_java_lang_reflect_Array_createObjectArray
|
Avian_java_lang_reflect_Array_createObjectArray
|
||||||
(Thread* t, object, uintptr_t* arguments)
|
(Thread* t, object, uintptr_t* arguments)
|
||||||
|
@ -4297,49 +4297,10 @@ EXPORT(JVM_GetClassModifiers)(Thread* t, jclass c)
|
|||||||
uint64_t
|
uint64_t
|
||||||
jvmGetDeclaredClasses(Thread* t, uintptr_t* arguments)
|
jvmGetDeclaredClasses(Thread* t, uintptr_t* arguments)
|
||||||
{
|
{
|
||||||
jclass c = reinterpret_cast<jobject>(arguments[0]);
|
|
||||||
|
|
||||||
object addendum = classAddendum(t, jclassVmClass(t, *c));
|
|
||||||
if (addendum) {
|
|
||||||
object table = classAddendumInnerClassTable(t, addendum);
|
|
||||||
if (table) {
|
|
||||||
PROTECT(t, table);
|
|
||||||
|
|
||||||
unsigned count = 0;
|
|
||||||
for (unsigned i = 0; i < arrayLength(t, table); ++i) {
|
|
||||||
object outer = innerClassReferenceOuter(t, arrayBody(t, table, i));
|
|
||||||
if (outer and byteArrayEqual
|
|
||||||
(t, outer, className(t, jclassVmClass(t, *c))))
|
|
||||||
{
|
|
||||||
++ count;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
object result = makeObjectArray(t, type(t, Machine::JclassType), count);
|
|
||||||
PROTECT(t, result);
|
|
||||||
|
|
||||||
for (unsigned i = 0; i < arrayLength(t, table); ++i) {
|
|
||||||
object outer = innerClassReferenceOuter(t, arrayBody(t, table, i));
|
|
||||||
if (outer and byteArrayEqual
|
|
||||||
(t, outer, className(t, jclassVmClass(t, *c))))
|
|
||||||
{
|
|
||||||
object inner = getJClass
|
|
||||||
(t, resolveClass
|
|
||||||
(t, classLoader(t, jclassVmClass(t, *c)),
|
|
||||||
innerClassReferenceInner(t, arrayBody(t, table, i))));
|
|
||||||
|
|
||||||
-- count;
|
|
||||||
set(t, result, ArrayBody + (count * BytesPerWord), inner);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return reinterpret_cast<uintptr_t>(makeLocalReference(t, result));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return reinterpret_cast<uintptr_t>
|
return reinterpret_cast<uintptr_t>
|
||||||
(makeLocalReference
|
(makeLocalReference
|
||||||
(t, makeObjectArray(t, type(t, Machine::JclassType), 0)));
|
(t, getDeclaredClasses
|
||||||
|
(t, jclassVmClass(t, *reinterpret_cast<jobject>(arguments[0])), false)));
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" AVIAN_EXPORT jobjectArray JNICALL
|
extern "C" AVIAN_EXPORT jobjectArray JNICALL
|
||||||
@ -4353,31 +4314,10 @@ EXPORT(JVM_GetDeclaredClasses)(Thread* t, jclass c)
|
|||||||
uint64_t
|
uint64_t
|
||||||
jvmGetDeclaringClass(Thread* t, uintptr_t* arguments)
|
jvmGetDeclaringClass(Thread* t, uintptr_t* arguments)
|
||||||
{
|
{
|
||||||
jclass c = reinterpret_cast<jobject>(arguments[0]);
|
return reinterpret_cast<uintptr_t>
|
||||||
|
(makeLocalReference
|
||||||
object class_ = jclassVmClass(t, *c);
|
(t, getDeclaringClass
|
||||||
object addendum = classAddendum(t, class_);
|
(t, jclassVmClass(t, *reinterpret_cast<jobject>(arguments[0])))));
|
||||||
if (addendum) {
|
|
||||||
object table = classAddendumInnerClassTable(t, addendum);
|
|
||||||
if (table) {
|
|
||||||
for (unsigned i = 0; i < arrayLength(t, table); ++i) {
|
|
||||||
object reference = arrayBody(t, table, i);
|
|
||||||
if (strcmp
|
|
||||||
(&byteArrayBody(t, innerClassReferenceInner(t, reference), 0),
|
|
||||||
&byteArrayBody(t, className(t, class_), 0)) == 0)
|
|
||||||
{
|
|
||||||
return reinterpret_cast<uintptr_t>
|
|
||||||
(makeLocalReference
|
|
||||||
(t, getJClass
|
|
||||||
(t, resolveClass
|
|
||||||
(t, classLoader(t, class_), innerClassReferenceOuter
|
|
||||||
(t, reference)))));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" AVIAN_EXPORT jclass JNICALL
|
extern "C" AVIAN_EXPORT jclass JNICALL
|
||||||
|
@ -1947,9 +1947,7 @@ parseMethodTable(Thread* t, Stream& s, object class_, object pool)
|
|||||||
object superVirtualTable = 0;
|
object superVirtualTable = 0;
|
||||||
PROTECT(t, superVirtualTable);
|
PROTECT(t, superVirtualTable);
|
||||||
|
|
||||||
if (classFlags(t, class_) & ACC_INTERFACE) {
|
if ((classFlags(t, class_) & ACC_INTERFACE) == 0) {
|
||||||
addInterfaceMethods(t, class_, virtualMap, &virtualCount, false);
|
|
||||||
} else {
|
|
||||||
if (classSuper(t, class_)) {
|
if (classSuper(t, class_)) {
|
||||||
superVirtualTable = classVirtualTable(t, classSuper(t, class_));
|
superVirtualTable = classVirtualTable(t, classSuper(t, class_));
|
||||||
}
|
}
|
||||||
@ -2144,13 +2142,10 @@ parseMethodTable(Thread* t, Stream& s, object class_, object pool)
|
|||||||
set(t, class_, ClassMethodTable, methodTable);
|
set(t, class_, ClassMethodTable, methodTable);
|
||||||
}
|
}
|
||||||
|
|
||||||
object abstractVirtuals;
|
|
||||||
if (classFlags(t, class_) & ACC_INTERFACE) {
|
object abstractVirtuals = addInterfaceMethods
|
||||||
abstractVirtuals = 0;
|
(t, class_, virtualMap, &virtualCount, true);
|
||||||
} else {
|
|
||||||
abstractVirtuals = addInterfaceMethods
|
|
||||||
(t, class_, virtualMap, &virtualCount, true);
|
|
||||||
}
|
|
||||||
PROTECT(t, abstractVirtuals);
|
PROTECT(t, abstractVirtuals);
|
||||||
|
|
||||||
bool populateInterfaceVtables = false;
|
bool populateInterfaceVtables = false;
|
||||||
@ -2212,43 +2207,45 @@ parseMethodTable(Thread* t, Stream& s, object class_, object pool)
|
|||||||
set(t, vtable, ArrayBody + (i * BytesPerWord), pairFirst(t, p));
|
set(t, vtable, ArrayBody + (i * BytesPerWord), pairFirst(t, p));
|
||||||
++ i;
|
++ i;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (abstractVirtuals) {
|
if (abstractVirtuals) {
|
||||||
PROTECT(t, vtable);
|
PROTECT(t, vtable);
|
||||||
|
|
||||||
object addendum = getClassAddendum(t, class_, pool);
|
object addendum = getClassAddendum(t, class_, pool);
|
||||||
set(t, addendum, ClassAddendumMethodTable,
|
set(t, addendum, ClassAddendumMethodTable,
|
||||||
classMethodTable(t, class_));
|
classMethodTable(t, class_));
|
||||||
|
|
||||||
unsigned oldLength = classMethodTable(t, class_) ?
|
unsigned oldLength = classMethodTable(t, class_) ?
|
||||||
arrayLength(t, classMethodTable(t, class_)) : 0;
|
arrayLength(t, classMethodTable(t, class_)) : 0;
|
||||||
|
|
||||||
object newMethodTable = makeArray
|
object newMethodTable = makeArray
|
||||||
(t, oldLength + listSize(t, abstractVirtuals));
|
(t, oldLength + listSize(t, abstractVirtuals));
|
||||||
|
|
||||||
if (oldLength) {
|
if (oldLength) {
|
||||||
memcpy(&arrayBody(t, newMethodTable, 0),
|
memcpy(&arrayBody(t, newMethodTable, 0),
|
||||||
&arrayBody(t, classMethodTable(t, class_), 0),
|
&arrayBody(t, classMethodTable(t, class_), 0),
|
||||||
oldLength * sizeof(object));
|
oldLength * sizeof(object));
|
||||||
}
|
}
|
||||||
|
|
||||||
mark(t, newMethodTable, ArrayBody, oldLength);
|
mark(t, newMethodTable, ArrayBody, oldLength);
|
||||||
|
|
||||||
unsigned mti = oldLength;
|
unsigned mti = oldLength;
|
||||||
for (object p = listFront(t, abstractVirtuals);
|
for (object p = listFront(t, abstractVirtuals);
|
||||||
p; p = pairSecond(t, p))
|
p; p = pairSecond(t, p))
|
||||||
{
|
{
|
||||||
set(t, newMethodTable,
|
set(t, newMethodTable,
|
||||||
ArrayBody + ((mti++) * BytesPerWord), pairFirst(t, p));
|
ArrayBody + ((mti++) * BytesPerWord), pairFirst(t, p));
|
||||||
|
|
||||||
|
if ((classFlags(t, class_) & ACC_INTERFACE) == 0) {
|
||||||
set(t, vtable,
|
set(t, vtable,
|
||||||
ArrayBody + ((i++) * BytesPerWord), pairFirst(t, p));
|
ArrayBody + ((i++) * BytesPerWord), pairFirst(t, p));
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(t, arrayLength(t, newMethodTable) == mti);
|
|
||||||
|
|
||||||
set(t, class_, ClassMethodTable, newMethodTable);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
assert(t, arrayLength(t, newMethodTable) == mti);
|
||||||
|
|
||||||
|
set(t, class_, ClassMethodTable, newMethodTable);
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(t, arrayLength(t, vtable) == i);
|
assert(t, arrayLength(t, vtable) == i);
|
||||||
|
@ -59,6 +59,10 @@ public class Reflection {
|
|||||||
expect(egads.getAnnotation(Deprecated.class) == null);
|
expect(egads.getAnnotation(Deprecated.class) == null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Integer[] array;
|
||||||
|
|
||||||
|
private Integer integer;
|
||||||
|
|
||||||
public static Hello<Hello<Reflection>>.World<Hello<String>> pinky;
|
public static Hello<Hello<Reflection>>.World<Hello<String>> pinky;
|
||||||
|
|
||||||
private static void genericType() throws Exception {
|
private static void genericType() throws Exception {
|
||||||
@ -131,10 +135,58 @@ public class Reflection {
|
|||||||
expect(7.0 == (Double) Reflection.class.getMethod
|
expect(7.0 == (Double) Reflection.class.getMethod
|
||||||
("doubleMethod").invoke(null));
|
("doubleMethod").invoke(null));
|
||||||
|
|
||||||
Class[][] array = new Class[][] { { Class.class } };
|
{ Class[][] array = new Class[][] { { Class.class } };
|
||||||
expect("[Ljava.lang.Class;".equals(array[0].getClass().getName()));
|
expect("[Ljava.lang.Class;".equals(array[0].getClass().getName()));
|
||||||
expect(Class[].class == array[0].getClass());
|
expect(Class[].class == array[0].getClass());
|
||||||
expect(array.getClass().getComponentType() == array[0].getClass());
|
expect(array.getClass().getComponentType() == array[0].getClass());
|
||||||
|
}
|
||||||
|
|
||||||
|
{ Reflection r = new Reflection();
|
||||||
|
expect(r.egads == 0);
|
||||||
|
|
||||||
|
Reflection.class.getDeclaredField("egads").set(r, 42);
|
||||||
|
expect(((int) Reflection.class.getDeclaredField("egads").get(r)) == 42);
|
||||||
|
|
||||||
|
Reflection.class.getDeclaredField("egads").setInt(r, 43);
|
||||||
|
expect(Reflection.class.getDeclaredField("egads").getInt(r) == 43);
|
||||||
|
|
||||||
|
Integer[] array = new Integer[0];
|
||||||
|
Reflection.class.getDeclaredField("array").set(r, array);
|
||||||
|
expect(Reflection.class.getDeclaredField("array").get(r) == array);
|
||||||
|
|
||||||
|
try {
|
||||||
|
Reflection.class.getDeclaredField("array").set(r, new Object());
|
||||||
|
expect(false);
|
||||||
|
} catch (IllegalArgumentException e) {
|
||||||
|
// cool
|
||||||
|
}
|
||||||
|
|
||||||
|
Integer integer = 45;
|
||||||
|
Reflection.class.getDeclaredField("integer").set(r, integer);
|
||||||
|
expect(Reflection.class.getDeclaredField("integer").get(r) == integer);
|
||||||
|
|
||||||
|
try {
|
||||||
|
Reflection.class.getDeclaredField("integer").set(r, new Object());
|
||||||
|
expect(false);
|
||||||
|
} catch (IllegalArgumentException e) {
|
||||||
|
// cool
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
Reflection.class.getDeclaredField("integer").set
|
||||||
|
(new Object(), integer);
|
||||||
|
expect(false);
|
||||||
|
} catch (IllegalArgumentException e) {
|
||||||
|
// cool
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
Reflection.class.getDeclaredField("integer").get(new Object());
|
||||||
|
expect(false);
|
||||||
|
} catch (IllegalArgumentException e) {
|
||||||
|
// cool
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
Foo.class.getMethod("foo").invoke(null);
|
Foo.class.getMethod("foo").invoke(null);
|
||||||
@ -157,6 +209,22 @@ public class Reflection {
|
|||||||
// cool
|
// cool
|
||||||
}
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
Foo.class.getField("foo").set(null, 42);
|
||||||
|
expect(false);
|
||||||
|
} catch (NoClassDefFoundError e) {
|
||||||
|
// cool
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
Foo.class.getField("foo").set(null, new Object());
|
||||||
|
expect(false);
|
||||||
|
} catch (IllegalArgumentException e) {
|
||||||
|
// cool
|
||||||
|
} catch (NoClassDefFoundError e) {
|
||||||
|
// cool
|
||||||
|
}
|
||||||
|
|
||||||
{ Method m = Reflection.class.getMethod("throwOOME");
|
{ Method m = Reflection.class.getMethod("throwOOME");
|
||||||
try {
|
try {
|
||||||
m.invoke(null);
|
m.invoke(null);
|
||||||
|
Loading…
Reference in New Issue
Block a user