support runtime-visible annotations and java.lang.reflect.Proxy

This commit is contained in:
Joel Dice
2009-09-18 18:01:54 -06:00
parent a2a33c259e
commit 7aa906d97b
23 changed files with 1278 additions and 169 deletions

View File

@ -79,6 +79,242 @@ runOnLoadIfFound(Thread* t, System::Library* library)
}
}
void JNICALL
proxyConstruct(Thread* t, object, uintptr_t* arguments)
{
set(t, reinterpret_cast<object>(arguments[0]), ProxyH,
reinterpret_cast<object>(arguments[1]));
}
int64_t JNICALL
proxyInvoke(Thread* t, object method, uintptr_t* arguments)
{
PROTECT(t, method);
unsigned size = methodParameterFootprint(t, method);
RUNTIME_ARRAY(bool, objectMask, size);
assert(t, (methodFlags(t, method) & ACC_STATIC) == 0);
unsigned i = 0;
RUNTIME_ARRAY_BODY(objectMask)[i++] = true;
unsigned argumentCount = 0;
for (MethodSpecIterator it
(t, reinterpret_cast<char*>
(&byteArrayBody(t, methodSpec(t, method), 0)));
it.hasNext();)
{
++ argumentCount;
switch (*it.next()) {
case 'L':
case '[':
RUNTIME_ARRAY_BODY(objectMask)[i++] = true;
break;
case 'J':
case 'D':
RUNTIME_ARRAY_BODY(objectMask)[i++] = false;
RUNTIME_ARRAY_BODY(objectMask)[i++] = false;
break;
default:
RUNTIME_ARRAY_BODY(objectMask)[i++] = false;
break;
}
}
class MyProtector: public Thread::Protector {
public:
MyProtector(Thread* t, uintptr_t* array, bool* mask, unsigned count):
Protector(t), array(array), mask(mask), count(count) { }
virtual void visit(Heap::Visitor* v) {
for (unsigned i = 0; i < count; ++i) {
if (mask[i]) {
v->visit(reinterpret_cast<object*>(array + i));
}
}
}
uintptr_t* array;
bool* mask;
unsigned count;
} protector(t, arguments, RUNTIME_ARRAY_BODY(objectMask), i);
object array = makeObjectArray
(t, t->m->loader, arrayBody(t, t->m->types, Machine::JobjectType),
argumentCount);
PROTECT(t, array);
i = 0;
unsigned ai = 1;
for (MethodSpecIterator it
(t, reinterpret_cast<char*>
(&byteArrayBody(t, methodSpec(t, method), 0)));
it.hasNext();)
{
object a;
unsigned size;
switch (*it.next()) {
case 'L':
case '[':
a = reinterpret_cast<object>(arguments[ai]);
size = 1;
break;
case 'Z':
a = makeBoolean(t, static_cast<int8_t>(arguments[ai]));
size = 1;
break;
case 'B':
a = makeByte(t, static_cast<int8_t>(arguments[ai]));
size = 1;
break;
case 'S':
a = makeShort(t, static_cast<int16_t>(arguments[ai]));
size = 1;
break;
case 'C':
a = makeChar(t, static_cast<uint16_t>(arguments[ai]));
size = 1;
break;
case 'I':
a = makeInt(t, static_cast<int32_t>(arguments[ai]));
size = 1;
break;
case 'F':
a = makeFloat(t, bitsToFloat(static_cast<int32_t>(arguments[ai])));
size = 1;
break;
case 'J': {
int64_t v; memcpy(&v, arguments + ai, 8);
a = makeLong(t, v);
size = 2;
} break;
case 'D': {
double v; memcpy(&v, arguments + ai, 8);
a = makeDouble(t, v);
size = 2;
} break;
default:
abort(t);
}
set(t, array, ArrayBody + (i * BytesPerWord), a);
++ i;
ai += size;
}
if (t->m->invokeMethod == 0) {
object m = resolveMethod
(t, t->m->loader, "java/lang/reflect/InvocationHandler", "invoke",
"(Ljava/lang/Object;Ljava/lang/reflect/Method;[Ljava/lang/Object;)"
"Ljava/lang/Object;");
if (m) {
t->m->invokeMethod = m;
}
if (UNLIKELY(t->exception)) return 0;
}
object invoke = findInterfaceMethod
(t, t->m->invokeMethod, objectClass
(t, proxyH(t, reinterpret_cast<object>(arguments[0]))));
PROTECT(t, invoke);
object result = t->m->processor->invoke
(t, invoke, proxyH(t, reinterpret_cast<object>(arguments[0])),
reinterpret_cast<object>(arguments[0]), method, array);
if (UNLIKELY(t->exception)) return 0;
switch (methodReturnCode(t, method)) {
case BooleanField:
return booleanValue(t, result);
case ByteField:
return byteValue(t, result);
case CharField:
return charValue(t, result);
case ShortField:
return shortValue(t, result);
case FloatField:
return floatToBits(floatValue(t, result));
case IntField:
return intValue(t, result);
case LongField:
return longValue(t, result);
case DoubleField:
return doubleToBits(doubleValue(t, result));
case ObjectField:
return reinterpret_cast<int64_t>(result);
case VoidField:
return 0;
default:
abort(t);
}
}
void
addInterface(Thread* t, object map, object interface)
{
hashMapInsertMaybe
(t, map, className(t, interface), interface, byteArrayHash,
byteArrayEqual);
}
object
allInterfaces(Thread* t, object array)
{
PROTECT(t, array);
object map = makeHashMap(t, 0, 0);
PROTECT(t, map);
for (unsigned i = 0; i < objectArrayLength(t, array); ++i) {
addInterface(t, map, objectArrayBody(t, array, i));
object itable = classInterfaceTable(t, objectArrayBody(t, array, i));
if (itable) {
PROTECT(t, itable);
for (unsigned j = 0; j < arrayLength(t, itable); ++j) {
addInterface(t, map, arrayBody(t, itable, j));
}
}
}
object result = makeArray(t, hashMapSize(t, map));
unsigned i = 0;
for (HashMapIterator it(t, map); it.hasMore();) {
set(t, result, ArrayBody + (i * BytesPerWord), tripleSecond(t, it.next()));
++ i;
}
return result;
}
} // namespace
extern "C" JNIEXPORT int64_t JNICALL
@ -199,16 +435,6 @@ Avian_java_lang_ClassLoader_defineClass
return reinterpret_cast<int64_t>(c);
}
extern "C" JNIEXPORT void JNICALL
Avian_java_lang_ClassLoader_resolveClass
(Thread* t, object, uintptr_t* arguments)
{
object loader = reinterpret_cast<object>(arguments[0]);
object class_ = reinterpret_cast<object>(arguments[1]);
linkClass(t, loader, class_);
}
extern "C" JNIEXPORT int64_t JNICALL
Avian_avian_SystemClassLoader_findLoadedClass
(Thread* t, object, uintptr_t* arguments)
@ -302,13 +528,17 @@ Avian_java_lang_Class_initialize
}
extern "C" JNIEXPORT void JNICALL
Avian_java_lang_Class_link
(Thread* t, object, uintptr_t* arguments)
Avian_java_lang_Class_acquireClassLock
(Thread* t, object)
{
object this_ = reinterpret_cast<object>(arguments[0]);
object loader = reinterpret_cast<object>(arguments[1]);
acquire(t, t->m->classLock);
}
linkClass(t, loader, this_);
extern "C" JNIEXPORT void JNICALL
Avian_java_lang_Class_releaseClassLock
(Thread* t, object)
{
release(t, t->m->classLock);
}
extern "C" JNIEXPORT int64_t JNICALL
@ -499,6 +729,195 @@ Avian_java_lang_reflect_Array_makeObjectArray
(makeObjectArray(t, classLoader(t, elementType), elementType, length));
}
extern "C" JNIEXPORT int64_t JNICALL
Avian_java_lang_reflect_Proxy_makeClass
(Thread* t, object, uintptr_t* arguments)
{
object loader = reinterpret_cast<object>(arguments[0]);
PROTECT(t, loader);
object interfaces = allInterfaces(t, reinterpret_cast<object>(arguments[1]));
PROTECT(t, interfaces);
object name = reinterpret_cast<object>(arguments[2]);
PROTECT(t, name);
object virtualMap = makeHashMap(t, 0, 0);
PROTECT(t, virtualMap);
object superVtable = classVirtualTable
(t, arrayBody(t, t->m->types, Machine::ProxyType));
PROTECT(t, superVtable);
for (unsigned i = 0; i < arrayLength(t, superVtable); ++i) {
object method = arrayBody(t, superVtable, i);
hashMapInsert(t, virtualMap, method, method, methodHash);
}
unsigned virtualCount = arrayLength(t, superVtable);
object newVirtuals = makeList(t, 0, 0, 0);
PROTECT(t, newVirtuals);
object ivtable = 0;
PROTECT(t, ivtable);
object method = 0;
PROTECT(t, method);
for (unsigned i = 0; i < arrayLength(t, interfaces); ++i) {
ivtable = classVirtualTable(t, arrayBody(t, interfaces, i));
if (ivtable) {
for (unsigned j = 0; j < arrayLength(t, ivtable); ++j) {
method = arrayBody(t, ivtable, j);
method = makeMethod
(t,
methodVmFlags(t, method) | FastNative,
methodReturnCode(t, method),
methodParameterCount(t, method),
methodParameterFootprint(t, method),
methodFlags(t, method) | ACC_NATIVE,
0,
0,
methodName(t, method),
methodSpec(t, method),
0,
0,
0,
reinterpret_cast<int64_t>(proxyInvoke));
object p = hashMapFindNode
(t, virtualMap, method, methodHash, methodEqual);
if (p) {
methodOffset(t, method) = methodOffset(t, tripleFirst(t, p));
set(t, p, TripleSecond, method);
} else {
methodOffset(t, method) = virtualCount++;
listAppend(t, newVirtuals, method);
hashMapInsert(t, virtualMap, method, method, methodHash);
}
}
}
}
object vtable = makeArray(t, virtualCount);
PROTECT(t, vtable);
unsigned i = 0;
for (; i < arrayLength(t, superVtable); ++i) {
method = hashMapFind
(t, virtualMap, arrayBody(t, superVtable, i), methodHash, methodEqual);
set(t, vtable, ArrayBody + (i * BytesPerWord), method);
}
object methodTable = makeArray(t, listSize(t, newVirtuals) + 1);
PROTECT(t, methodTable);
unsigned mti = 0;
for (object p = listFront(t, newVirtuals); p; p = pairSecond(t, p)) {
set(t, vtable, ArrayBody + (i * BytesPerWord), pairFirst(t, p));
++ i;
set(t, methodTable, ArrayBody + (mti * BytesPerWord), pairFirst(t, p));
++ mti;
}
#define NAME "<init>"
object constructorName = makeByteArray(t, sizeof(NAME));
PROTECT(t, constructorName);
memcpy(&byteArrayBody(t, constructorName, 0), NAME, sizeof(NAME));
#define SPEC "(Ljava/lang/reflect/InvocationHandler;)V"
object constructorSpec = makeByteArray(t, sizeof(SPEC));
PROTECT(t, constructorSpec);
memcpy(&byteArrayBody(t, constructorSpec, 0), SPEC, sizeof(SPEC));
object constructor = makeMethod
(t,
methodVmFlags(t, method) | FastNative,
VoidField,
1,
2,
methodFlags(t, method) | ACC_NATIVE,
0,
0,
constructorName,
constructorSpec,
0,
0,
0,
reinterpret_cast<int64_t>(proxyConstruct));
set(t, methodTable, ArrayBody + (mti * BytesPerWord), constructor);
++ mti;
assert(t, arrayLength(t, vtable) == i);
assert(t, arrayLength(t, methodTable) == mti);
object itable = makeArray(t, arrayLength(t, interfaces) * 2);
PROTECT(t, itable);
object newIVTable = 0;
PROTECT(t, newIVTable);
for (unsigned i = 0; i < arrayLength(t, interfaces); ++i) {
object interface = arrayBody(t, interfaces, i);
set(t, itable, ArrayBody + ((i * 2) * BytesPerWord), interface);
ivtable = classVirtualTable(t, interface);
if (ivtable) {
newIVTable = makeArray(t, arrayLength(t, ivtable));
set(t, itable, ArrayBody + (((i * 2) + 1) * BytesPerWord), newIVTable);
for (unsigned j = 0; j < arrayLength(t, ivtable); ++j) {
method = hashMapFind
(t, virtualMap, arrayBody(t, ivtable, j), methodHash, methodEqual);
assert(t, method);
set(t, newIVTable, ArrayBody + (j * BytesPerWord), method);
}
}
}
object c = t->m->processor->makeClass
(t,
0,
0,
classFixedSize(t, arrayBody(t, t->m->types, Machine::ProxyType)),
0,
0,
classObjectMask(t, arrayBody(t, t->m->types, Machine::ProxyType)),
name,
0,
arrayBody(t, t->m->types, Machine::ProxyType),
itable,
vtable,
0,
methodTable,
0,
0,
loader,
arrayLength(t, vtable));
PROTECT(t, c);
t->m->processor->initVtable(t, c);
for (unsigned i = 0; i < arrayLength(t, methodTable); ++i) {
set(t, arrayBody(t, methodTable, i), MethodClass, c);
}
return reinterpret_cast<int64_t>(c);
}
extern "C" JNIEXPORT int64_t JNICALL
Avian_java_lang_Float_floatToRawIntBits
(Thread*, object, uintptr_t* arguments)

View File

@ -6331,7 +6331,7 @@ invoke(Thread* thread, object method, ArgumentList* arguments)
default:
abort(t);
};
}
return r;
}
@ -6450,12 +6450,13 @@ class MyProcessor: public Processor {
uint16_t offset,
object name,
object spec,
object addendum,
object class_,
object code)
{
return vm::makeMethod
(t, vmFlags, returnCode, parameterCount, parameterFootprint, flags,
offset, 0, name, spec, class_, code,
offset, 0, name, spec, addendum, class_, code,
local::defaultThunk(static_cast<MyThread*>(t)));
}
@ -6475,13 +6476,14 @@ class MyProcessor: public Processor {
object fieldTable,
object methodTable,
object staticTable,
object addendum,
object loader,
unsigned vtableLength)
{
return vm::makeClass
(t, flags, vmFlags, fixedSize, arrayElementSize, arrayDimensions,
objectMask, name, sourceFile, super, interfaceTable, virtualTable,
fieldTable, methodTable, staticTable, loader, vtableLength);
fieldTable, methodTable, staticTable, addendum, loader, vtableLength);
}
virtual void
@ -7656,6 +7658,7 @@ compile(MyThread* t, Allocator* allocator, BootContext* bootContext,
methodNativeID(t, method),
methodName(t, method),
methodSpec(t, method),
methodAddendum(t, method),
methodClass(t, method),
methodCode(t, method),
reinterpret_cast<intptr_t>(compiled));

View File

@ -3093,11 +3093,12 @@ class MyProcessor: public Processor {
object name,
object spec,
object class_,
object addendum,
object code)
{
return vm::makeMethod
(t, vmFlags, returnCode, parameterCount, parameterFootprint, flags,
offset, 0, name, spec, class_, code, 0);
offset, 0, name, spec, addendum, class_, code, 0);
}
virtual object
@ -3116,13 +3117,14 @@ class MyProcessor: public Processor {
object fieldTable,
object methodTable,
object staticTable,
object addendum,
object loader,
unsigned vtableLength UNUSED)
{
return vm::makeClass
(t, flags, vmFlags, fixedSize, arrayElementSize, arrayDimensions,
objectMask, name, sourceFile, super, interfaceTable, virtualTable,
fieldTable, methodTable, staticTable, loader, 0);
fieldTable, methodTable, addendum, staticTable, loader, 0);
}
virtual void

View File

@ -68,9 +68,8 @@ dispose(Thread* t, Thread* o, bool remove)
expect(t, find(t->m->rootThread, o));
unsigned c = count(t->m->rootThread, o);
Thread** threads = static_cast<Thread**>
(allocate(t->m->system, c * sizeof(Thread*)));
fill(t->m->rootThread, o, threads);
RUNTIME_ARRAY(Thread*, threads, c);
fill(t->m->rootThread, o, RUNTIME_ARRAY_BODY(threads));
#endif
if (o->parent) {
@ -115,7 +114,7 @@ dispose(Thread* t, Thread* o, bool remove)
expect(t, not find(t->m->rootThread, o));
for (unsigned i = 0; i < c; ++i) {
expect(t, find(t->m->rootThread, threads[i]));
expect(t, find(t->m->rootThread, RUNTIME_ARRAY_BODY(threads)[i]));
}
#endif
}
@ -604,51 +603,6 @@ makeByteArray(Thread* t, const char* format, va_list a)
return s;
}
unsigned
resolveSpec(Thread* t, object loader, object spec, unsigned offset)
{
int8_t* s = &byteArrayBody(t, spec, offset);
unsigned result;
switch (*s) {
case 'L':
++ offset;
while (*s and *s != ';') ++ s;
result = s + 1 - &byteArrayBody(t, spec, 0);
break;
case '[':
while (*s == '[') ++ s;
switch (*s) {
case 'L':
while (*s and *s != ';') ++ s;
++ s;
break;
default:
++ s;
break;
}
result = s - &byteArrayBody(t, spec, 0);
break;
default:
return offset + 1;
}
PROTECT(t, spec);
PROTECT(t, loader);
unsigned length = s - &byteArrayBody(t, spec, offset);
object name = makeByteArray(t, length + 1);
memcpy(&byteArrayBody(t, name, 0),
&byteArrayBody(t, spec, offset),
length);
resolveClass(t, loader, name);
return result;
}
unsigned
readByte(Stream& s, unsigned* value)
{
@ -983,7 +937,7 @@ parseInterfaceTable(Thread* t, Stream& s, object class_, object pool)
object interfaceTable = 0;
if (hashMapSize(t, map)) {
unsigned length = hashMapSize(t, map) ;
unsigned length = hashMapSize(t, map);
if ((classFlags(t, class_) & ACC_INTERFACE) == 0) {
length *= 2;
}
@ -1016,6 +970,122 @@ parseInterfaceTable(Thread* t, Stream& s, object class_, object pool)
set(t, class_, ClassInterfaceTable, interfaceTable);
}
object
parseAnnotation(Thread* t, Stream& s, object pool);
object
parseAnnotationValue(Thread* t, Stream& s, object pool)
{
unsigned tag = s.read1();
switch (tag) {
case 'Z':
return makeBoolean(t, singletonValue(t, pool, s.read2() - 1));
case 'B':
return makeByte(t, singletonValue(t, pool, s.read2() - 1));
case 'C':
return makeChar(t, singletonValue(t, pool, s.read2() - 1));
case 'S':
return makeShort(t, singletonValue(t, pool, s.read2() - 1));
case 'I':
return makeInt(t, singletonValue(t, pool, s.read2() - 1));
case 'F':
return makeFloat(t, bitsToFloat(singletonValue(t, pool, s.read2() - 1)));
case 'J': {
int64_t v; memcpy(&v, &singletonValue(t, pool, s.read2() - 1), 8);
return makeLong(t, v);
}
case 'D': {
double v; memcpy(&v, &singletonValue(t, pool, s.read2() - 1), 8);
return makeDouble(t, v);
}
case 's': {
object value = singletonObject(t, pool, s.read2() - 1);
return intern
(t, makeString(t, value, 0, byteArrayLength(t, value) - 1, 0));
}
case 'e': {
unsigned typeNameIndex = s.read2() - 1;
unsigned nameIndex = s.read2() - 1;
return makePair(t, singletonObject(t, pool, typeNameIndex),
singletonObject(t, pool, nameIndex));
}
case 'c':
return singletonObject(t, pool, s.read2() - 1);
case '@':
return parseAnnotation(t, s, pool);
case '[': {
unsigned count = s.read2();
object array = makeObjectArray(t, count);
PROTECT(t, array);
for (unsigned i = 0; i < count; ++i) {
object value = parseAnnotationValue(t, s, pool);
if (UNLIKELY(t->exception)) return 0;
set(t, array, ArrayBody + (i * BytesPerWord), value);
}
return array;
}
default: abort(t);
}
}
object
parseAnnotation(Thread* t, Stream& s, object pool)
{
PROTECT(t, pool);
unsigned typeIndex = s.read2() - 1;
unsigned elementCount = s.read2();
object array = makeObjectArray(t, (elementCount * 2) + 2);
PROTECT(t, array);
set(t, array, ArrayBody + BytesPerWord, singletonObject(t, pool, typeIndex));
for (unsigned i = 0; i < elementCount; ++i) {
set(t, array, ArrayBody + (((i * 2) + 2) * BytesPerWord),
singletonObject(t, pool, s.read2() - 1));
object value = parseAnnotationValue(t, s, pool);
if (UNLIKELY(t->exception)) return 0;
set(t, array, ArrayBody + (((i * 2) + 3) * BytesPerWord), value);
}
return array;
}
object
parseAnnotationTable(Thread* t, Stream& s, object pool)
{
PROTECT(t, pool);
unsigned annotationCount = s.read2();
object annotations = makeArray(t, annotationCount);
PROTECT(t, annotations);
for (unsigned i = 0; i < annotationCount; ++i) {
object annotation = parseAnnotation(t, s, pool);
if (UNLIKELY(t->exception)) return 0;
set(t, annotations, ArrayBody + (i * BytesPerWord), annotation);
}
return annotations;
}
void
parseFieldTable(Thread* t, Stream& s, object class_, object pool)
{
@ -1038,6 +1108,9 @@ parseFieldTable(Thread* t, Stream& s, object class_, object pool)
object staticValueTable = makeIntArray(t, count);
PROTECT(t, staticValueTable);
object addendum = 0;
PROTECT(t, addendum);
RUNTIME_ARRAY(uint8_t, staticTypes, count);
for (unsigned i = 0; i < count; ++i) {
@ -1059,6 +1132,11 @@ parseFieldTable(Thread* t, Stream& s, object class_, object pool)
&byteArrayBody(t, name, 0)) == 0)
{
value = s.read2();
} else if (vm::strcmp(reinterpret_cast<const int8_t*>
("RuntimeVisibleAnnotations"),
&byteArrayBody(t, name, 0)) == 0)
{
addendum = makeFieldAddendum(t, parseAnnotationTable(t, s, pool));
} else {
s.skip(length);
}
@ -1072,6 +1150,7 @@ parseFieldTable(Thread* t, Stream& s, object class_, object pool)
0, // offset
singletonObject(t, pool, name - 1),
singletonObject(t, pool, spec - 1),
addendum,
class_);
if (flags & ACC_STATIC) {
@ -1318,6 +1397,7 @@ addInterfaceMethods(Thread* t, object class_, object virtualMap,
0,
methodName(t, method),
methodSpec(t, method),
0,
class_,
0,
0);
@ -1380,12 +1460,19 @@ parseMethodTable(Thread* t, Stream& s, object class_, object pool)
object methodTable = makeArray(t, count);
PROTECT(t, methodTable);
object addendum = 0;
PROTECT(t, addendum);
object code = 0;
PROTECT(t, code);
for (unsigned i = 0; i < count; ++i) {
unsigned flags = s.read2();
unsigned name = s.read2();
unsigned spec = s.read2();
object code = 0;
code = 0;
unsigned attributeCount = s.read2();
for (unsigned j = 0; j < attributeCount; ++j) {
object name = singletonObject(t, pool, s.read2() - 1);
@ -1395,6 +1482,11 @@ parseMethodTable(Thread* t, Stream& s, object class_, object pool)
&byteArrayBody(t, name, 0)) == 0)
{
code = parseCode(t, s, pool);
} else if (vm::strcmp(reinterpret_cast<const int8_t*>
("RuntimeVisibleAnnotations"),
&byteArrayBody(t, name, 0)) == 0)
{
addendum = makeMethodAddendum(t, parseAnnotationTable(t, s, pool));
} else {
s.skip(length);
}
@ -1417,6 +1509,7 @@ parseMethodTable(Thread* t, Stream& s, object class_, object pool)
0, // offset
singletonObject(t, pool, name - 1),
singletonObject(t, pool, spec - 1),
addendum,
class_,
code);
@ -1493,7 +1586,8 @@ parseMethodTable(Thread* t, Stream& s, object class_, object pool)
if (classInterfaceTable(t, classSuper(t, class_))
and arrayLength(t, classInterfaceTable(t, class_))
== arrayLength(t, classInterfaceTable(t, classSuper(t, class_))))
== arrayLength
(t, classInterfaceTable(t, classSuper(t, class_))))
{
// inherit interface table from superclass
set(t, class_, ClassInterfaceTable,
@ -1541,6 +1635,7 @@ parseMethodTable(Thread* t, Stream& s, object class_, object pool)
}
if (abstractVirtuals) {
PROTECT(t, vtable);
PROTECT(t, abstractVirtuals);
unsigned oldLength = arrayLength(t, classMethodTable(t, class_));
@ -1592,7 +1687,7 @@ parseMethodTable(Thread* t, Stream& s, object class_, object pool)
(t, virtualMap, method, methodHash, methodEqual);
assert(t, method);
set(t, vtable, ArrayBody + (j * BytesPerWord), method);
set(t, vtable, ArrayBody + (j * BytesPerWord), method);
}
}
}
@ -1612,6 +1707,14 @@ parseAttributeTable(Thread* t, Stream& s, object class_, object pool)
&byteArrayBody(t, name, 0)) == 0)
{
set(t, class_, ClassSourceFile, singletonObject(t, pool, s.read2() - 1));
} else if (vm::strcmp(reinterpret_cast<const int8_t*>
("RuntimeVisibleAnnotations"),
&byteArrayBody(t, name, 0)) == 0)
{
object addendum = makeClassAddendum
(t, parseAnnotationTable(t, s, pool), 0);
set(t, class_, ClassAddendum, addendum);
} else {
s.skip(length);
}
@ -1702,6 +1805,7 @@ makeArrayClass(Thread* t, object loader, unsigned dimensions, object spec,
vtable,
0,
0,
0,
elementClass,
loader,
arrayLength(t, vtable));
@ -1832,7 +1936,7 @@ bootClass(Thread* t, Machine::Type type, int superType, uint32_t objectMask,
object class_ = t->m->processor->makeClass
(t, 0, BootstrapFlag, fixedSize, arrayElementSize, 0, mask, 0, 0, super, 0,
0, 0, 0, 0, t->m->loader, vtableLength);
0, 0, 0, 0, 0, t->m->loader, vtableLength);
set(t, t->m->types, ArrayBody + (type * BytesPerWord), class_);
}
@ -1945,7 +2049,7 @@ boot(Thread* t)
{ object bootCode = makeCode(t, 0, 0, 0, 0, 0, 1);
codeBody(t, bootCode, 0) = impdep1;
object bootMethod = makeMethod
(t, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, bootCode, 0);
(t, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, bootCode, 0);
PROTECT(t, bootMethod);
#include "type-java-initializations.cpp"
@ -2084,6 +2188,7 @@ Machine::Machine(System* system, Heap* heap, Finder* finder,
tenuredWeakReferences(0),
shutdownHooks(0),
objectsToFinalize(0),
invokeMethod(0),
unsafe(false),
triedBuiltinOnLoad(false),
heapPoolIndex(0)
@ -2824,12 +2929,13 @@ parseClass(Thread* t, object loader, const uint8_t* data, unsigned size)
0, // object mask
referenceName
(t, singletonObject(t, pool, name - 1)),
0,
0, // source file
0, // super
0, // interfaces
0, // vtable
0, // fields
0, // methods
0, // addendum
0, // static table
loader,
0);// vtable length
@ -2878,6 +2984,7 @@ parseClass(Thread* t, object loader, const uint8_t* data, unsigned size)
classVirtualTable(t, class_),
classFieldTable(t, class_),
classMethodTable(t, class_),
classAddendum(t, class_),
classStaticTable(t, class_),
classLoader(t, class_),
vtableLength);
@ -3032,60 +3139,6 @@ resolveClass(Thread* t, object loader, object spec)
}
}
void
linkClass(Thread* t, object loader, object class_)
{
PROTECT(t, loader);
PROTECT(t, class_);
ACQUIRE(t, t->m->classLock);
if ((classVmFlags(t, class_) & LinkFlag) == 0) {
if (classSuper(t, class_)) {
linkClass(t, loader, classSuper(t, class_));
}
if (classInterfaceTable(t, class_)) {
unsigned increment = 2;
if (classFlags(t, class_) & ACC_INTERFACE) {
increment = 1;
}
for (unsigned i = 0; i < arrayLength(t, classInterfaceTable(t, class_));
i += increment)
{
linkClass(t, loader, arrayBody(t, classInterfaceTable(t, class_), i));
}
}
if (classMethodTable(t, class_)) {
for (unsigned i = 0;
i < arrayLength(t, classMethodTable(t, class_)); ++i)
{
object spec = methodSpec
(t, arrayBody(t, classMethodTable(t, class_), i));
PROTECT(t, spec);
for (unsigned j = 1; j < byteArrayLength(t, spec);) {
j = resolveSpec(t, loader, spec, j);
if (UNLIKELY(t->exception)) return;
}
}
}
if (classFieldTable(t, class_)) {
for (unsigned i = 0; i < arrayLength(t, classFieldTable(t, class_)); ++i)
{
resolveSpec(t, loader, fieldSpec
(t, arrayBody(t, classFieldTable(t, class_), i)), 0);
if (UNLIKELY(t->exception)) return;
}
}
classVmFlags(t, class_) |= LinkFlag;
}
}
object
resolveMethod(Thread* t, object class_, const char* methodName,
const char* methodSpec)
@ -3573,6 +3626,7 @@ visitRoots(Machine* m, Heap::Visitor* v)
v->visit(&(m->jniMethodTable));
v->visit(&(m->shutdownHooks));
v->visit(&(m->objectsToFinalize));
v->visit(&(m->invokeMethod));
for (Thread* t = m->rootThread; t; t = t->peer) {
::visitRoots(t, v);

View File

@ -1204,6 +1204,7 @@ class Machine {
object tenuredWeakReferences;
object shutdownHooks;
object objectsToFinalize;
object invokeMethod;
bool unsafe;
bool triedBuiltinOnLoad;
JavaVMVTable javaVMVTable;
@ -1846,6 +1847,12 @@ makeExceptionInInitializerError(Thread* t, object cause)
return makeExceptionInInitializerError(t, 0, trace, cause, cause);
}
inline object
makeIncompatibleClassChangeError(Thread* t)
{
return makeIncompatibleClassChangeError(t, 0, makeTrace(t), 0);
}
inline object
makeNew(Thread* t, object class_)
{
@ -2194,6 +2201,13 @@ initClass(Thread* t, object c);
object
makeObjectArray(Thread* t, object loader, object elementClass, unsigned count);
inline object
makeObjectArray(Thread* t, unsigned count)
{
return makeObjectArray
(t, t->m->loader, arrayBody(t, t->m->types, Machine::JobjectType), count);
}
object
findInTable(Thread* t, object table, object name, object spec,
object& (*getName)(Thread*, object),
@ -2232,6 +2246,22 @@ findVirtualMethod(Thread* t, object method, object class_)
methodOffset(t, method));
}
inline object
findInterfaceMethod(Thread* t, object method, object class_)
{
assert(t, (classVmFlags(t, class_) & BootstrapFlag) == 0);
object interface = methodClass(t, method);
object itable = classInterfaceTable(t, class_);
for (unsigned i = 0; i < arrayLength(t, itable); i += 2) {
if (arrayBody(t, itable, i) == interface) {
return arrayBody(t, arrayBody(t, itable, i + 1),
methodOffset(t, method));
}
}
abort(t);
}
inline unsigned
objectArrayLength(Thread* t UNUSED, object array)
{
@ -2248,7 +2278,7 @@ objectArrayBody(Thread* t UNUSED, object array, unsigned index)
assert(t, classObjectMask(t, objectClass(t, array))
== classObjectMask(t, arrayBody
(t, t->m->types, Machine::ArrayType)));
return cast<object>(array, (2 + index) * BytesPerWord);
return cast<object>(array, ArrayBody + (index * BytesPerWord));
}
unsigned

View File

@ -59,22 +59,6 @@ isSpecialMethod(Thread* t, object method, object class_)
void*
resolveNativeMethod(Thread* t, object method);
inline object
findInterfaceMethod(Thread* t, object method, object class_)
{
assert(t, (classVmFlags(t, class_) & BootstrapFlag) == 0);
object interface = methodClass(t, method);
object itable = classInterfaceTable(t, class_);
for (unsigned i = 0; i < arrayLength(t, itable); i += 2) {
if (arrayBody(t, itable, i) == interface) {
return arrayBody(t, arrayBody(t, itable, i + 1),
methodOffset(t, method));
}
}
abort(t);
}
inline void
populateMultiArray(Thread* t, object array, int32_t* counts,
unsigned index, unsigned dimensions)

View File

@ -54,6 +54,7 @@ class Processor {
uint16_t offset,
object name,
object spec,
object addendum,
object class_,
object code) = 0;
@ -72,6 +73,7 @@ class Processor {
object virtualTable,
object fieldTable,
object methodTable,
object addendum,
object staticTable,
object loader,
unsigned vtableLength) = 0;

View File

@ -13,10 +13,20 @@
(type accessibleObject java/lang/reflect/AccessibleObject)
(type classAddendum java/lang/Class$Addendum)
(type field java/lang/reflect/Field)
(type fieldAddendum java/lang/reflect/Field$Addendum)
(type method java/lang/reflect/Method)
(type methodAddendum java/lang/reflect/Method$Addendum)
(type proxy java/lang/reflect/Proxy)
(type pair avian/Pair)
(type nativeMethodData
(void* function)
(uint16_t argumentTableSize)
@ -54,10 +64,6 @@
(object name)
(object spec))
(type pair
(object first)
(object second))
(type triple
(object first)
(object second)