mirror of
https://github.com/corda/corda.git
synced 2025-01-05 20:54:13 +00:00
implement ClassLoader.resolveClass and ensure class is linked in e.g. Class.getMethods; minor bugfixes
This commit is contained in:
parent
c27aa559e5
commit
c4edabdc02
@ -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) {
|
||||
|
@ -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;
|
||||
|
@ -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)
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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 {
|
||||
|
174
src/machine.cpp
174
src/machine.cpp
@ -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);
|
||||
}
|
||||
}
|
||||
|
109
src/machine.h
109
src/machine.h
@ -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);
|
||||
|
||||
|
@ -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() {
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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,
|
||||
|
Loading…
Reference in New Issue
Block a user