implement ClassLoader.resolveClass and ensure class is linked in e.g. Class.getMethods; minor bugfixes

This commit is contained in:
Joel Dice 2009-08-18 14:26:28 -06:00
parent c27aa559e5
commit c4edabdc02
11 changed files with 323 additions and 121 deletions

View File

@ -32,10 +32,10 @@ public final class Class <T> implements Type, GenericDeclaration {
private static final int PrimitiveFlag = 1 << 5;
private short flags;
private byte vmFlags;
private byte arrayDimensions;
private short vmFlags;
private short fixedSize;
private short arrayElementSize;
private byte arrayElementSize;
private byte arrayDimensions;
private int[] objectMask;
private byte[] name;
private Class super_;
@ -151,6 +151,7 @@ public final class Class <T> implements Type, GenericDeclaration {
loader = Class.class.loader;
}
Class c = loader.loadClass(name);
c.link(loader);
if (initialize) {
c.initialize();
}
@ -159,6 +160,8 @@ public final class Class <T> implements Type, GenericDeclaration {
private static native Class primitiveClass(char name);
private native void link(ClassLoader loader);
private native void initialize();
public static Class forCanonicalName(String name) {
@ -215,6 +218,8 @@ public final class Class <T> implements Type, GenericDeclaration {
private Field findField(String name) {
if (fieldTable != null) {
link(loader);
for (int i = 0; i < fieldTable.length; ++i) {
if (fieldTable[i].getName().equals(name)) {
return fieldTable[i];
@ -258,8 +263,12 @@ public final class Class <T> implements Type, GenericDeclaration {
private Method findMethod(String name, Class[] parameterTypes) {
if (methodTable != null) {
if (parameterTypes == null)
link(loader);
if (parameterTypes == null) {
parameterTypes = new Class[0];
}
for (int i = 0; i < methodTable.length; ++i) {
if (methodTable[i].getName().equals(name)
&& match(parameterTypes, methodTable[i].getParameterTypes()))
@ -348,6 +357,8 @@ public final class Class <T> implements Type, GenericDeclaration {
public Constructor[] getDeclaredConstructors() {
Constructor[] array = new Constructor[countConstructors(false)];
if (methodTable != null) {
link(loader);
int index = 0;
for (int i = 0; i < methodTable.length; ++i) {
if (methodTable[i].getName().equals("<init>")) {
@ -362,6 +373,8 @@ public final class Class <T> implements Type, GenericDeclaration {
public Constructor[] getConstructors() {
Constructor[] array = new Constructor[countConstructors(true)];
if (methodTable != null) {
link(loader);
int index = 0;
for (int i = 0; i < methodTable.length; ++i) {
if (((methodTable[i].getModifiers() & Modifier.PUBLIC) != 0)
@ -400,6 +413,8 @@ public final class Class <T> implements Type, GenericDeclaration {
public Field[] getFields() {
Field[] array = new Field[countPublicFields()];
if (fieldTable != null) {
link(loader);
int ai = 0;
for (int i = 0; i < fieldTable.length; ++i) {
if (((fieldTable[i].getModifiers() & Modifier.PUBLIC)) != 0) {
@ -428,6 +443,8 @@ public final class Class <T> implements Type, GenericDeclaration {
public Method[] getDeclaredMethods() {
Method[] array = new Method[countMethods(false)];
if (methodTable != null) {
link(loader);
int ai = 0;
for (int i = 0; i < methodTable.length; ++i) {
if (! methodTable[i].getName().startsWith("<")) {
@ -442,6 +459,8 @@ public final class Class <T> implements Type, GenericDeclaration {
public Method[] getMethods() {
Method[] array = new Method[countMethods(true)];
if (methodTable != null) {
link(loader);
int index = 0;
for (int i = 0; i < methodTable.length; ++i) {
if (((methodTable[i].getModifiers() & Modifier.PUBLIC) != 0)
@ -457,6 +476,8 @@ public final class Class <T> implements Type, GenericDeclaration {
public Class[] getInterfaces() {
if (interfaceTable != null) {
link(loader);
Class[] array = new Class[interfaceTable.length / 2];
for (int i = 0; i < array.length; ++i) {
array[i] = (Class) interfaceTable[i * 2];
@ -496,7 +517,7 @@ public final class Class <T> implements Type, GenericDeclaration {
}
public boolean isArray() {
return this != Class.class && arrayElementSize != 0;
return arrayDimensions != 0;
}
public boolean isInstance(Object o) {

View File

@ -83,9 +83,7 @@ public abstract class ClassLoader {
return c;
}
protected void resolveClass(Class c) {
// ignore
}
protected native void resolveClass(Class c);
private ClassLoader getParent() {
return parent;

View File

@ -199,6 +199,16 @@ 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)
@ -291,6 +301,16 @@ Avian_java_lang_Class_initialize
initClass(t, this_);
}
extern "C" JNIEXPORT void JNICALL
Avian_java_lang_Class_link
(Thread* t, object, uintptr_t* arguments)
{
object this_ = reinterpret_cast<object>(arguments[0]);
object loader = reinterpret_cast<object>(arguments[1]);
linkClass(t, loader, this_);
}
extern "C" JNIEXPORT int64_t JNICALL
Avian_java_lang_Class_isAssignableFrom
(Thread* t, object, uintptr_t* arguments)

View File

@ -2511,7 +2511,7 @@ bool
needsReturnBarrier(MyThread* t, object method)
{
return (methodFlags(t, method) & ConstructorFlag)
and (classFlags(t, methodClass(t, method)) & HasFinalMemberFlag);
and (classVmFlags(t, methodClass(t, method)) & HasFinalMemberFlag);
}
bool
@ -3746,7 +3746,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip,
if (singletonIsObject(t, pool, index - 1)) {
object v = singletonObject(t, pool, index - 1);
if (objectClass(t, v)
== arrayBody(t, t->m->types, Machine::ByteArrayType))
== arrayBody(t, t->m->types, Machine::ReferenceType))
{
object class_ = resolveClassInPool(t, context->method, index - 1);
if (UNLIKELY(t->exception)) return;
@ -6444,10 +6444,10 @@ class MyProcessor: public Processor {
virtual object
makeClass(vm::Thread* t,
uint16_t flags,
uint8_t vmFlags,
uint8_t arrayDimensions,
uint16_t vmFlags,
uint16_t fixedSize,
uint16_t arrayElementSize,
uint8_t arrayElementSize,
uint8_t arrayDimensions,
object objectMask,
object name,
object super,
@ -6460,7 +6460,7 @@ class MyProcessor: public Processor {
unsigned vtableLength)
{
return vm::makeClass
(t, flags, vmFlags, arrayDimensions, fixedSize, arrayElementSize,
(t, flags, vmFlags, fixedSize, arrayElementSize, arrayDimensions,
objectMask, name, super, interfaceTable, virtualTable, fieldTable,
methodTable, staticTable, loader, vtableLength);
}

View File

@ -2246,7 +2246,7 @@ interpret(Thread* t)
if (singletonIsObject(t, pool, index - 1)) {
object v = singletonObject(t, pool, index - 1);
if (objectClass(t, v)
== arrayBody(t, t->m->types, Machine::ByteArrayType))
== arrayBody(t, t->m->types, Machine::ReferenceType))
{
object class_ = resolveClassInPool(t, pool, index - 1);
if (UNLIKELY(exception)) goto throw_;
@ -2724,7 +2724,7 @@ interpret(Thread* t)
case return_: {
object method = frameMethod(t, frame);
if ((methodFlags(t, method) & ConstructorFlag)
and (classFlags(t, methodClass(t, method)) & HasFinalMemberFlag))
and (classVmFlags(t, methodClass(t, method)) & HasFinalMemberFlag))
{
storeStoreMemoryBarrier();
}
@ -3100,10 +3100,10 @@ class MyProcessor: public Processor {
virtual object
makeClass(vm::Thread* t,
uint16_t flags,
uint8_t vmFlags,
uint8_t arrayDimensions,
uint16_t vmFlags,
uint16_t fixedSize,
uint16_t arrayElementSize,
uint8_t arrayElementSize,
uint8_t arrayDimensions,
object objectMask,
object name,
object super,
@ -3116,7 +3116,7 @@ class MyProcessor: public Processor {
unsigned vtableLength UNUSED)
{
return vm::makeClass
(t, flags, vmFlags, arrayDimensions, fixedSize, arrayElementSize,
(t, flags, vmFlags, fixedSize, arrayElementSize, arrayDimensions,
objectMask, name, super, interfaceTable, virtualTable, fieldTable,
methodTable, staticTable, loader, 0);
}

View File

@ -77,6 +77,7 @@ DetachCurrentThread(Machine* m)
{
Thread* t = static_cast<Thread*>(m->localThread->get());
if (t) {
m->localThread->set(0);
t->exit();
return 0;
} else {

View File

@ -542,6 +542,50 @@ 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);
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)
{
@ -706,7 +750,7 @@ parsePoolEntry(Thread* t, Stream& s, uint32_t* index, object pool, unsigned i)
unsigned si = s.read2() - 1;
parsePoolEntry(t, s, index, pool, si);
object value = singletonObject(t, pool, si);
object value = makeReference(t, 0, singletonObject(t, pool, si), 0);
set(t, pool, SingletonBody + (i * BytesPerWord), value);
}
} return 1;
@ -749,7 +793,7 @@ parsePoolEntry(Thread* t, Stream& s, uint32_t* index, object pool, unsigned i)
parsePoolEntry(t, s, index, pool, ci);
parsePoolEntry(t, s, index, pool, nti);
object class_ = singletonObject(t, pool, ci);
object class_ = referenceName(t, singletonObject(t, pool, ci));
object nameAndType = singletonObject(t, pool, nti);
object value = makeReference
(t, class_, pairFirst(t, nameAndType), pairSecond(t, nameAndType));
@ -861,7 +905,7 @@ parseInterfaceTable(Thread* t, Stream& s, object class_, object pool)
unsigned count = s.read2();
for (unsigned i = 0; i < count; ++i) {
object name = singletonObject(t, pool, s.read2() - 1);
object name = referenceName(t, singletonObject(t, pool, s.read2() - 1));
PROTECT(t, name);
object interface = resolveClass(t, classLoader(t, class_), name);
@ -983,7 +1027,7 @@ parseFieldTable(Thread* t, Stream& s, object class_, object pool)
staticTypes[staticCount++] = code;
} else {
if (flags & ACC_FINAL) {
classFlags(t, class_) |= HasFinalMemberFlag;
classVmFlags(t, class_) |= HasFinalMemberFlag;
}
unsigned excess = (memberOffset % fieldSize(t, code)) % BytesPerWord;
@ -1565,9 +1609,9 @@ makeArrayClass(Thread* t, object loader, unsigned dimensions, object spec,
(t,
0,
0,
dimensions,
2 * BytesPerWord,
BytesPerWord,
dimensions,
classObjectMask(t, arrayBody(t, t->m->types, Machine::ArrayType)),
spec,
arrayBody(t, t->m->types, Machine::JobjectType),
@ -1704,7 +1748,7 @@ bootClass(Thread* t, Machine::Type type, int superType, uint32_t objectMask,
super = (superType >= 0 ? arrayBody(t, t->m->types, superType) : 0);
object class_ = t->m->processor->makeClass
(t, 0, BootstrapFlag, 0, fixedSize, arrayElementSize, mask, 0, super, 0, 0,
(t, 0, BootstrapFlag, fixedSize, arrayElementSize, 0, mask, 0, super, 0, 0,
0, 0, 0, t->m->loader, vtableLength);
set(t, t->m->types, ArrayBody + (type * BytesPerWord), class_);
@ -1773,10 +1817,10 @@ boot(Thread* t)
m->unsafe = false;
classFlags(t, arrayBody(t, m->types, Machine::SingletonType))
classVmFlags(t, arrayBody(t, m->types, Machine::SingletonType))
|= SingletonFlag;
classFlags(t, arrayBody(t, m->types, Machine::ContinuationType))
classVmFlags(t, arrayBody(t, m->types, Machine::ContinuationType))
|= ContinuationFlag;
classVmFlags(t, arrayBody(t, m->types, Machine::JreferenceType))
@ -2074,8 +2118,6 @@ Thread::init()
m->localThread->set(this);
} else {
assert(this, javaThread);
peer = parent->child;
parent->child = this;
}
@ -2083,11 +2125,16 @@ Thread::init()
if (javaThread) {
threadPeer(this, javaThread) = reinterpret_cast<jlong>(this);
} else {
object group;
if (parent) {
group = threadGroup(this, parent->javaThread);
} else {
group = makeThreadGroup(this, 0, 0);
}
const unsigned NewState = 0;
const unsigned NormalPriority = 5;
object group = makeThreadGroup(this, 0, 0);
this->javaThread = makeThread
(this, reinterpret_cast<int64_t>(this), 0, 0, NewState, NormalPriority,
0, 0, 0, m->loader, 0, 0, group);
@ -2663,11 +2710,12 @@ parseClass(Thread* t, object loader, const uint8_t* data, unsigned size)
object class_ = makeClass(t,
flags,
0, // VM flags
0, // array dimensions
0, // fixed size
0, // array size
0, // array dimensions
0, // object mask
singletonObject(t, pool, name - 1),
referenceName
(t, singletonObject(t, pool, name - 1)),
0, // super
0, // interfaces
0, // vtable
@ -2680,7 +2728,8 @@ parseClass(Thread* t, object loader, const uint8_t* data, unsigned size)
unsigned super = s.read2();
if (super) {
object sc = resolveClass(t, loader, singletonObject(t, pool, super - 1));
object sc = resolveClass
(t, loader, referenceName(t, singletonObject(t, pool, super - 1)));
if (UNLIKELY(t->exception)) return 0;
set(t, class_, ClassSuper, sc);
@ -2706,9 +2755,9 @@ parseClass(Thread* t, object loader, const uint8_t* data, unsigned size)
(t,
classFlags(t, class_),
classVmFlags(t, class_),
classArrayDimensions(t, class_),
classFixedSize(t, class_),
classArrayElementSize(t, class_),
classArrayDimensions(t, class_),
classObjectMask(t, class_),
className(t, class_),
classSuper(t, class_),
@ -2867,6 +2916,95 @@ 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_)) {
bool resolvedPool = false;
for (unsigned i = 0;
i < arrayLength(t, classMethodTable(t, class_)); ++i)
{
object method = arrayBody(t, classMethodTable(t, class_), i);
PROTECT(t, method);
object code = methodCode(t, method);
if ((not resolvedPool)
and code
and codePool(t, code)
and objectClass(t, codePool(t, code))
== arrayBody(t, t->m->types, Machine::SingletonType))
{
object pool = codePool(t, code);
PROTECT(t, pool);
unsigned count = singletonCount(t, pool);
for (unsigned j = 0; j < count; ++j) {
if (singletonIsObject(t, pool, j)) {
object entry = singletonObject(t, pool, j);
if (objectClass(t, entry)
== arrayBody(t, t->m->types, Machine::ReferenceType))
{
if (referenceSpec(t, entry) == 0) {
resolveClassInPool(t, loader, method, j);
} else if (byteArrayBody(t, referenceSpec(t, entry), 0) == '(')
{
resolveMethod(t, loader, method, j);
} else {
resolveField(t, loader, method, j);
}
if (UNLIKELY(t->exception)) return;
}
}
}
resolvedPool = true;
}
object spec = methodSpec(t, method);
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)
@ -3286,7 +3424,7 @@ walk(Thread* t, Heap::Walker* w, object o, unsigned start)
intArrayLength(t, objectMask) * 4);
more = ::walk(t, w, mask, fixedSize, arrayElementSize, arrayLength, start);
} else if (classFlags(t, class_) & SingletonFlag) {
} else if (classVmFlags(t, class_) & SingletonFlag) {
unsigned length = singletonLength(t, o);
if (length) {
more = ::walk(t, w, singletonMask(t, o),
@ -3298,7 +3436,7 @@ walk(Thread* t, Heap::Walker* w, object o, unsigned start)
more = w->visit(0);
}
if (more and classFlags(t, class_) & ContinuationFlag) {
if (more and classVmFlags(t, class_) & ContinuationFlag) {
t->m->processor->walkContinuationBody(t, w, o, start);
}
}

View File

@ -74,12 +74,6 @@ enum StackTag {
const int NativeLine = -1;
const int UnknownLine = -2;
// class flags (note that we must be careful not to overlap the
// standard ACC_* flags):
const unsigned HasFinalMemberFlag = 1 << 13;
const unsigned SingletonFlag = 1 << 14;
const unsigned ContinuationFlag = 1 << 15;
// class vmFlags:
const unsigned ReferenceFlag = 1 << 0;
const unsigned WeakReferenceFlag = 1 << 1;
@ -89,6 +83,10 @@ const unsigned InitErrorFlag = 1 << 4;
const unsigned PrimitiveFlag = 1 << 5;
const unsigned BootstrapFlag = 1 << 6;
const unsigned HasFinalizerFlag = 1 << 7;
const unsigned LinkFlag = 1 << 8;
const unsigned HasFinalMemberFlag = 1 << 9;
const unsigned SingletonFlag = 1 << 10;
const unsigned ContinuationFlag = 1 << 11;
// method vmFlags:
const unsigned ClassInitFlag = 1 << 0;
@ -1816,6 +1814,7 @@ makeNew(Thread* t, object class_)
PROTECT(t, class_);
unsigned sizeInBytes = pad(classFixedSize(t, class_));
assert(t, sizeInBytes);
object instance = allocate(t, sizeInBytes, classObjectMask(t, class_));
setObjectClass(t, instance, class_);
@ -2103,6 +2102,9 @@ resolveSystemClass(Thread* t, const char* name)
return resolveSystemClass(t, makeByteArray(t, "%s", name));
}
void
linkClass(Thread* t, object loader, object class_);
object
resolveMethod(Thread* t, object class_, const char* methodName,
const char* methodSpec);
@ -2444,6 +2446,101 @@ makeSingletonOfSize(Thread* t, unsigned count)
return o;
}
inline object
resolveClassInObject(Thread* t, object loader, object container,
unsigned classOffset)
{
object o = cast<object>(container, classOffset);
if (objectClass(t, o) == arrayBody(t, t->m->types, Machine::ByteArrayType)) {
PROTECT(t, container);
o = resolveClass(t, loader, o);
if (UNLIKELY(t->exception)) return 0;
set(t, container, classOffset, o);
}
return o;
}
inline object
resolveClassInPool(Thread* t, object loader, object method, unsigned index)
{
object o = singletonObject(t, codePool(t, methodCode(t, method)), index);
if (objectClass(t, o) == arrayBody(t, t->m->types, Machine::ReferenceType)) {
PROTECT(t, method);
o = resolveClass(t, loader, referenceName(t, o));
if (UNLIKELY(t->exception)) return 0;
set(t, codePool(t, methodCode(t, method)),
SingletonBody + (index * BytesPerWord), o);
}
return o;
}
inline object
resolveClassInPool(Thread* t, object method, unsigned index)
{
return resolveClassInPool(t, classLoader(t, methodClass(t, method)),
method, index);
}
inline object
resolve(Thread* t, object loader, object method, unsigned index,
object (*find)(vm::Thread*, object, object, object),
object (*makeError)(vm::Thread*, object))
{
object o = singletonObject(t, codePool(t, methodCode(t, method)), index);
if (objectClass(t, o) == arrayBody(t, t->m->types, Machine::ReferenceType))
{
PROTECT(t, method);
object reference = o;
PROTECT(t, reference);
object class_ = resolveClassInObject(t, loader, o, ReferenceClass);
if (UNLIKELY(t->exception)) return 0;
o = findInHierarchy
(t, class_, referenceName(t, reference), referenceSpec(t, reference),
find, makeError);
if (UNLIKELY(t->exception)) return 0;
set(t, codePool(t, methodCode(t, method)),
SingletonBody + (index * BytesPerWord), o);
}
return o;
}
inline object
resolveField(Thread* t, object loader, object method, unsigned index)
{
return resolve(t, loader, method, index, findFieldInClass,
makeNoSuchFieldError);
}
inline object
resolveField(Thread* t, object method, unsigned index)
{
return resolveField
(t, classLoader(t, methodClass(t, method)), method, index);
}
inline object
resolveMethod(Thread* t, object loader, object method, unsigned index)
{
return resolve(t, loader, method, index, findMethodInClass,
makeNoSuchMethodError);
}
inline object
resolveMethod(Thread* t, object method, unsigned index)
{
return resolveMethod
(t, classLoader(t, methodClass(t, method)), method, index);
}
void
dumpHeap(Thread* t, FILE* out);

View File

@ -129,7 +129,7 @@ class MySystem: public System {
virtual void join() {
int rv UNUSED = pthread_join(thread, 0);
expect(s, rv == 0);
//expect(s, rv == 0);
}
virtual void dispose() {

View File

@ -36,79 +36,6 @@ codeReadInt32(Thread* t, object code, unsigned& ip)
return ((v1 << 24) | (v2 << 16) | (v3 << 8) | v4);
}
inline object
resolveClassInObject(Thread* t, object loader, object container,
unsigned classOffset)
{
object o = cast<object>(container, classOffset);
if (objectClass(t, o) == arrayBody(t, t->m->types, Machine::ByteArrayType)) {
PROTECT(t, container);
o = resolveClass(t, loader, o);
if (UNLIKELY(t->exception)) return 0;
set(t, container, classOffset, o);
}
return o;
}
inline object
resolveClassInPool(Thread* t, object method, unsigned index)
{
object o = singletonObject(t, codePool(t, methodCode(t, method)), index);
if (objectClass(t, o) == arrayBody(t, t->m->types, Machine::ByteArrayType)) {
PROTECT(t, method);
o = resolveClass(t, classLoader(t, methodClass(t, method)), o);
if (UNLIKELY(t->exception)) return 0;
set(t, codePool(t, methodCode(t, method)),
SingletonBody + (index * BytesPerWord), o);
}
return o;
}
inline object
resolve(Thread* t, object method, unsigned index,
object (*find)(vm::Thread*, object, object, object),
object (*makeError)(vm::Thread*, object))
{
object o = singletonObject(t, codePool(t, methodCode(t, method)), index);
if (objectClass(t, o) == arrayBody(t, t->m->types, Machine::ReferenceType))
{
PROTECT(t, method);
object reference = o;
PROTECT(t, reference);
object class_ = resolveClassInObject
(t, classLoader(t, methodClass(t, method)), o, ReferenceClass);
if (UNLIKELY(t->exception)) return 0;
o = findInHierarchy
(t, class_, referenceName(t, reference), referenceSpec(t, reference),
find, makeError);
if (UNLIKELY(t->exception)) return 0;
set(t, codePool(t, methodCode(t, method)),
SingletonBody + (index * BytesPerWord), o);
}
return o;
}
inline object
resolveField(Thread* t, object method, unsigned index)
{
return resolve(t, method, index, findFieldInClass, makeNoSuchFieldError);
}
inline object
resolveMethod(Thread* t, object method, unsigned index)
{
return resolve(t, method, index, findMethodInClass, makeNoSuchMethodError);
}
inline bool
isSuperclass(Thread* t, object class_, object base)
{

View File

@ -60,10 +60,10 @@ class Processor {
virtual object
makeClass(Thread* t,
uint16_t flags,
uint8_t vmFlags,
uint8_t arrayDimensions,
uint16_t vmFlags,
uint16_t fixedSize,
uint16_t arrayElementSize,
uint8_t arrayElementSize,
uint8_t arrayDimensions,
object objectMask,
object name,
object super,