add classloader parameter to functions which may directly or indirectly load classes; include methods inherited from interfaces (but not explicitly declared) in method tables and virtual tables of abstract classes

This commit is contained in:
Joel Dice 2009-08-10 07:56:16 -06:00
parent 54bb64cfb2
commit 001000364d
12 changed files with 429 additions and 186 deletions

View File

@ -33,7 +33,8 @@ public abstract class ClassLoader {
return ClassLoader.class.getClassLoader();
}
private static native Class defineClass(byte[] b, int offset, int length);
private static native Class defineClass
(ClassLoader loader, byte[] b, int offset, int length);
protected Class defineClass(String name, byte[] b, int offset, int length) {
if (b == null) {
@ -44,7 +45,7 @@ public abstract class ClassLoader {
throw new IndexOutOfBoundsException();
}
return defineClass(b, offset, length);
return defineClass(this, b, offset, length);
}
protected Class findClass(String name) throws ClassNotFoundException {

View File

@ -371,6 +371,8 @@ gnu-overrides = \
java/lang/StringBuilder.class \
java/lang/StringBuilder\$$*.class \
java/lang/Thread.class \
java/lang/Thread\$$*.class \
java/lang/ThreadGroup.class \
java/lang/ThreadLocal.class \
java/lang/Throwable.class \
java/lang/ref/PhantomReference.class \

View File

@ -11,17 +11,12 @@
#include "machine.h"
#include "constants.h"
#include "processor.h"
#include "util.h"
using namespace vm;
namespace {
inline void
replace(char a, char b, char* c)
{
for (; *c; ++c) if (*c == a) *c = b;
}
int64_t
search(Thread* t, object name, object (*op)(Thread*, object),
bool replaceDots)
@ -177,15 +172,24 @@ extern "C" JNIEXPORT int64_t JNICALL
Avian_java_lang_ClassLoader_defineClass
(Thread* t, object, uintptr_t* arguments)
{
object b = reinterpret_cast<object>(arguments[0]);
int offset = arguments[1];
int length = arguments[2];
object loader = reinterpret_cast<object>(arguments[0]);
PROTECT(t, loader);
object b = reinterpret_cast<object>(arguments[1]);
int offset = arguments[2];
int length = arguments[3];
uint8_t* buffer = static_cast<uint8_t*>
(t->m->heap->allocate(length));
memcpy(buffer, &byteArrayBody(t, b, offset), length);
object c = parseClass(t, buffer, length);
object c = parseClass(t, loader, buffer, length);
t->m->heap->free(buffer, length);
if (c) {
hashMapInsert(t, classLoaderMap(t, loader), className(t, c), c,
byteArrayHash);
}
return reinterpret_cast<int64_t>(c);
}
@ -195,7 +199,7 @@ Avian_avian_SystemClassLoader_findLoadedClass
{
object name = reinterpret_cast<object>(arguments[1]);
return search(t, name, findLoadedClass, true);
return search(t, name, findLoadedSystemClass, true);
}
extern "C" JNIEXPORT int64_t JNICALL
@ -204,7 +208,7 @@ Avian_avian_SystemClassLoader_findClass
{
object name = reinterpret_cast<object>(arguments[1]);
return search(t, name, resolveClass, true);
return search(t, name, resolveSystemClass, true);
}
extern "C" JNIEXPORT int64_t JNICALL
@ -465,7 +469,8 @@ Avian_java_lang_reflect_Array_makeObjectArray
object elementType = reinterpret_cast<object>(arguments[0]);
int length = arguments[1];
return reinterpret_cast<int64_t>(makeObjectArray(t, elementType, length));
return reinterpret_cast<int64_t>
(makeObjectArray(t, classLoader(t, elementType), elementType, length));
}
extern "C" JNIEXPORT int64_t JNICALL
@ -767,8 +772,10 @@ Avian_java_lang_Throwable_resolveTrace
PROTECT(t, trace);
unsigned length = arrayLength(t, trace);
object elementType = arrayBody
(t, t->m->types, Machine::StackTraceElementType);
object array = makeObjectArray
(t, arrayBody(t, t->m->types, Machine::StackTraceElementType), length);
(t, classLoader(t, elementType), elementType, length);
PROTECT(t, array);
object e = 0;

View File

@ -313,6 +313,12 @@ voidPointer(T function)
return p;
}
inline void
replace(char a, char b, char* c)
{
for (; *c; ++c) if (*c == a) *c = b;
}
class Machine;
class Thread;

View File

@ -147,7 +147,7 @@ resolveTarget(MyThread* t, void* stack, object method)
PROTECT(t, method);
PROTECT(t, class_);
resolveClass(t, className(t, class_));
resolveSystemClass(t, className(t, class_));
if (UNLIKELY(t->exception)) return 0;
}
@ -164,7 +164,7 @@ resolveTarget(MyThread* t, object class_, unsigned index)
if (classVmFlags(t, class_) & BootstrapFlag) {
PROTECT(t, class_);
resolveClass(t, className(t, class_));
resolveSystemClass(t, className(t, class_));
if (UNLIKELY(t->exception)) return 0;
}
@ -2030,10 +2030,11 @@ longToFloat(int64_t a)
}
uint64_t
makeBlankObjectArray(MyThread* t, object class_, int32_t length)
makeBlankObjectArray(MyThread* t, object loader, object class_, int32_t length)
{
if (length >= 0) {
return reinterpret_cast<uint64_t>(makeObjectArray(t, class_, length));
return reinterpret_cast<uint64_t>
(makeObjectArray(t, loader, class_, length));
} else {
object message = makeString(t, "%d", length);
t->exception = makeNegativeArraySizeException(t, message);
@ -2226,6 +2227,9 @@ throw_(MyThread* t, object o)
} else {
t->exception = makeNullPointerException(t);
}
printTrace(t, t->exception);
unwind(t);
}
@ -2746,7 +2750,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip,
case anewarray: {
uint16_t index = codeReadInt16(t, code, ip);
object class_ = resolveClassInPool(t, codePool(t, code), index - 1);
object class_ = resolveClassInPool(t, context->method, index - 1);
if (UNLIKELY(t->exception)) return;
Compiler::Operand* length = frame->popInt();
@ -2757,7 +2761,9 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip,
0,
frame->trace(0, 0),
BytesPerWord,
3, c->register_(t->arch->thread()), frame->append(class_), length));
4, c->register_(t->arch->thread()),
frame->append(classLoader(t, methodClass(t, context->method))),
frame->append(class_), length));
} break;
case areturn: {
@ -2810,7 +2816,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip,
case checkcast: {
uint16_t index = codeReadInt16(t, code, ip);
object class_ = resolveClassInPool(t, codePool(t, code), index - 1);
object class_ = resolveClassInPool(t, context->method, index - 1);
if (UNLIKELY(t->exception)) return;
Compiler::Operand* instance = c->peek(1, 0);
@ -3085,7 +3091,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip,
case getstatic: {
uint16_t index = codeReadInt16(t, code, ip);
object field = resolveField(t, codePool(t, code), index - 1);
object field = resolveField(t, context->method, index - 1);
if (UNLIKELY(t->exception)) return;
Compiler::Operand* table;
@ -3452,7 +3458,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip,
case instanceof: {
uint16_t index = codeReadInt16(t, code, ip);
object class_ = resolveClassInPool(t, codePool(t, code), index - 1);
object class_ = resolveClassInPool(t, context->method, index - 1);
if (UNLIKELY(t->exception)) return;
frame->pushInt
@ -3467,7 +3473,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip,
uint16_t index = codeReadInt16(t, code, ip);
ip += 2;
object target = resolveMethod(t, codePool(t, code), index - 1);
object target = resolveMethod(t, context->method, index - 1);
if (UNLIKELY(t->exception)) return;
assert(t, (methodFlags(t, target) & ACC_STATIC) == 0);
@ -3502,7 +3508,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip,
case invokespecial: {
uint16_t index = codeReadInt16(t, code, ip);
object target = resolveMethod(t, codePool(t, code), index - 1);
object target = resolveMethod(t, context->method, index - 1);
if (UNLIKELY(t->exception)) return;
object class_ = methodClass(t, context->method);
@ -3520,7 +3526,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip,
case invokestatic: {
uint16_t index = codeReadInt16(t, code, ip);
object target = resolveMethod(t, codePool(t, code), index - 1);
object target = resolveMethod(t, context->method, index - 1);
if (UNLIKELY(t->exception)) return;
assert(t, methodFlags(t, target) & ACC_STATIC);
@ -3533,7 +3539,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip,
case invokevirtual: {
uint16_t index = codeReadInt16(t, code, ip);
object target = resolveMethod(t, codePool(t, code), index - 1);
object target = resolveMethod(t, context->method, index - 1);
if (UNLIKELY(t->exception)) return;
assert(t, (methodFlags(t, target) & ACC_STATIC) == 0);
@ -3729,7 +3735,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip,
if (objectClass(t, v)
== arrayBody(t, t->m->types, Machine::ByteArrayType))
{
object class_ = resolveClassInPool(t, pool, index - 1);
object class_ = resolveClassInPool(t, context->method, index - 1);
if (UNLIKELY(t->exception)) return;
frame->pushObject(frame->append(class_));
@ -3934,7 +3940,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip,
uint16_t index = codeReadInt16(t, code, ip);
uint8_t dimensions = codeBody(t, code, ip++);
object class_ = resolveClassInPool(t, codePool(t, code), index - 1);
object class_ = resolveClassInPool(t, context->method, index - 1);
if (UNLIKELY(t->exception)) return;
PROTECT(t, class_);
@ -3958,7 +3964,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip,
case new_: {
uint16_t index = codeReadInt16(t, code, ip);
object class_ = resolveClassInPool(t, codePool(t, code), index - 1);
object class_ = resolveClassInPool(t, context->method, index - 1);
if (UNLIKELY(t->exception)) return;
if (classVmFlags(t, class_) & (WeakReferenceFlag | HasFinalizerFlag)) {
@ -4008,7 +4014,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip,
case putstatic: {
uint16_t index = codeReadInt16(t, code, ip);
object field = resolveField(t, codePool(t, code), index - 1);
object field = resolveField(t, context->method, index - 1);
if (UNLIKELY(t->exception)) return;
object staticTable = 0;
@ -4310,12 +4316,13 @@ logCompile(MyThread* t, const void* code, unsigned size, const char* class_,
}
void
translateExceptionHandlerTable(MyThread* t, Compiler* c, object code,
translateExceptionHandlerTable(MyThread* t, Compiler* c, object method,
intptr_t start)
{
object oldTable = codeExceptionHandlerTable(t, code);
object oldTable = codeExceptionHandlerTable(t, methodCode(t, method));
if (oldTable) {
PROTECT(t, code);
PROTECT(t, method);
PROTECT(t, oldTable);
unsigned length = exceptionHandlerTableLength(t, oldTable);
@ -4344,7 +4351,7 @@ translateExceptionHandlerTable(MyThread* t, Compiler* c, object code,
object type;
if (exceptionHandlerCatchType(oldHandler)) {
type = resolveClassInPool
(t, codePool(t, code), exceptionHandlerCatchType(oldHandler) - 1);
(t, method, exceptionHandlerCatchType(oldHandler) - 1);
if (UNLIKELY(t->exception)) return;
} else {
type = 0;
@ -4353,7 +4360,7 @@ translateExceptionHandlerTable(MyThread* t, Compiler* c, object code,
set(t, newTable, ArrayBody + ((i + 1) * BytesPerWord), type);
}
set(t, code, CodeExceptionHandlerTable, newTable);
set(t, methodCode(t, method), CodeExceptionHandlerTable, newTable);
}
}
@ -4942,8 +4949,8 @@ finish(MyThread* t, Allocator* allocator, Context* context)
}
}
translateExceptionHandlerTable(t, c, methodCode(t, context->method),
reinterpret_cast<intptr_t>(start));
translateExceptionHandlerTable
(t, c, context->method, reinterpret_cast<intptr_t>(start));
if (UNLIKELY(t->exception)) return 0;
translateLineNumberTable(t, c, methodCode(t, context->method),
@ -5020,15 +5027,15 @@ finish(MyThread* t, Allocator* allocator, Context* context)
(&byteArrayBody(t, methodSpec(t, context->method), 0)));
// for debugging:
if (false and
if (//false and
strcmp
(reinterpret_cast<const char*>
(&byteArrayBody(t, className(t, methodClass(t, context->method)), 0)),
"java/lang/Throwable") == 0 and
"org/eclipse/osgi/framework/internal/core/Constants") == 0 and
strcmp
(reinterpret_cast<const char*>
(&byteArrayBody(t, methodName(t, context->method), 0)),
"printStackTrace") == 0)
"getInternalSymbolicName") == 0)
{
trap();
}
@ -5825,6 +5832,8 @@ returnSpec(MyThread* t, object method)
object
returnClass(MyThread* t, object method)
{
PROTECT(t, method);
int8_t* spec = returnSpec(t, method);
unsigned length = strlen(reinterpret_cast<char*>(spec));
object name;
@ -5837,7 +5846,8 @@ returnClass(MyThread* t, object method)
name = makeByteArray(t, length - 1);
memcpy(&byteArrayBody(t, name, 0), spec + 1, length - 2);
}
return resolveClass(t, name);
return resolveClass(t, classLoader(t, methodClass(t, method)), name);
}
bool
@ -5959,7 +5969,7 @@ callContinuation(MyThread* t, object continuation, object result,
PROTECT(t, nextContinuation);
object method = resolveMethod
(t, "avian/Continuations", "rewind",
(t, t->m->loader, "avian/Continuations", "rewind",
"(Ljava/lang/Runnable;Lavian/Callback;Ljava/lang/Object;"
"Ljava/lang/Throwable;)V");
@ -6030,7 +6040,7 @@ callWithCurrentContinuation(MyThread* t, object receiver)
if (receiveMethod(t) == 0) {
object m = resolveMethod
(t, "avian/CallbackReceiver", "receive",
(t, t->m->loader, "avian/CallbackReceiver", "receive",
"(Lavian/Callback;)Ljava/lang/Object;");
if (m) {
@ -6040,7 +6050,7 @@ callWithCurrentContinuation(MyThread* t, object receiver)
(t, t->m->types, Machine::ContinuationType);
if (classVmFlags(t, continuationClass) & BootstrapFlag) {
resolveClass(t, vm::className(t, continuationClass));
resolveSystemClass(t, vm::className(t, continuationClass));
}
}
}
@ -6078,7 +6088,7 @@ dynamicWind(MyThread* t, object before, object thunk, object after)
if (windMethod(t) == 0) {
object method = resolveMethod
(t, "avian/Continuations", "wind",
(t, t->m->loader, "avian/Continuations", "wind",
"(Ljava/lang/Runnable;Ljava/util/concurrent/Callable;"
"Ljava/lang/Runnable;)Lavian/Continuations$UnwindResult;");
@ -6570,6 +6580,16 @@ class MyProcessor: public Processor {
PROTECT(t, method);
if (false) {
compile(static_cast<MyThread*>(t),
::codeAllocator(static_cast<MyThread*>(t)), 0,
resolveMethod(t, t->m->loader,
"java/beans/PropertyChangeSupport",
"firePropertyChange",
"(Ljava/beans/PropertyChangeEvent;)V"));
trap();
}
compile(static_cast<MyThread*>(t),
::codeAllocator(static_cast<MyThread*>(t)), 0, method);
@ -6581,8 +6601,9 @@ class MyProcessor: public Processor {
}
virtual object
invokeList(Thread* t, const char* className, const char* methodName,
const char* methodSpec, object this_, va_list arguments)
invokeList(Thread* t, object loader, const char* className,
const char* methodName, const char* methodSpec,
object this_, va_list arguments)
{
if (UNLIKELY(t->exception)) return 0;
@ -6595,7 +6616,8 @@ class MyProcessor: public Processor {
ArgumentList list
(t, array, size, objectMask, this_, methodSpec, false, arguments);
object method = resolveMethod(t, className, methodName, methodSpec);
object method = resolveMethod
(t, loader, className, methodName, methodSpec);
if (LIKELY(t->exception == 0)) {
assert(t, ((methodFlags(t, method) & ACC_STATIC) == 0) xor (this_ == 0));
@ -7064,7 +7086,7 @@ fixupCode(Thread* t, uintptr_t* map, unsigned size, uint8_t* code,
void
fixupMethods(Thread* t, BootImage* image, uint8_t* code)
{
for (HashMapIterator it(t, t->m->classMap); it.hasMore();) {
for (HashMapIterator it(t, classLoaderMap(t, t->m->loader)); it.hasMore();) {
object c = tripleSecond(t, it.next());
if (classMethodTable(t, c)) {
@ -7194,7 +7216,9 @@ boot(MyThread* t, BootImage* image)
syncInstructionCache(code, image->codeSize);
t->m->classMap = makeClassMap(t, classTable, image->classCount, heap);
object classMap = makeClassMap(t, classTable, image->classCount, heap);
set(t, t->m->loader, ClassLoaderMap, classMap);
t->m->stringMap = makeStringMap(t, stringTable, image->stringCount, heap);
p->callTableSize = image->callCount;

View File

@ -11,6 +11,7 @@
#include "machine.h"
#include "constants.h"
#include "processor.h"
#include "util.h"
using namespace vm;
@ -48,7 +49,7 @@ NewDirectByteBuffer(Thread* t, void* address, jlong capacity)
initSpec = "(I)V";
}
object pointerClass = resolveClass(t, pointerClassName);
object pointerClass = resolveClass(t, t->m->loader, pointerClassName);
if (UNLIKELY(pointerClass == 0)) return 0;
PROTECT(t, pointerClass);
@ -63,7 +64,7 @@ NewDirectByteBuffer(Thread* t, void* address, jlong capacity)
if (UNLIKELY(t->exception)) return 0;
object bufferClass = resolveClass
(t, "java/nio/DirectByteBufferImpl$ReadWrite");
(t, t->m->loader, "java/nio/DirectByteBufferImpl$ReadWrite");
if (UNLIKELY(bufferClass == 0)) return 0;
PROTECT(t, bufferClass);
@ -124,7 +125,7 @@ Avian_gnu_classpath_VMSystemProperties_preInit
PROTECT(t, properties);
object method = resolveMethod
(t, "java/util/Properties", "setProperty",
(t, t->m->loader, "java/util/Properties", "setProperty",
"(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/Object;");
if (UNLIKELY(t->exception)) {
@ -212,7 +213,7 @@ Avian_gnu_classpath_VMStackWalker_getClassContext
if (skipCount == 0) {
if (trace == 0) {
trace = makeObjectArray
(t, arrayBody(t, t->m->types, Machine::ClassType),
(t, t->m->loader, arrayBody(t, t->m->types, Machine::ClassType),
walker->count());
}
@ -240,7 +241,7 @@ Avian_gnu_classpath_VMStackWalker_getClassContext
if (v.trace == 0) {
v.trace = makeObjectArray
(t, arrayBody(t, t->m->types, Machine::ClassType), 0);
(t, t->m->loader, arrayBody(t, t->m->types, Machine::ClassType), 0);
}
return reinterpret_cast<int64_t>(v.trace);
@ -358,7 +359,14 @@ extern "C" JNIEXPORT int64_t JNICALL
Avian_java_lang_VMClassLoader_defineClass
(Thread* t, object, uintptr_t* arguments)
{
uintptr_t args[] = { arguments[2], arguments[3], arguments[4] };
uintptr_t args[]
= { arguments[0], arguments[2], arguments[3], arguments[4] };
// object name = reinterpret_cast<object>(arguments[1]);
// char n[stringLength(t, name) + 1];
// stringChars(t, name, n);
// fprintf(stderr, "define class %s in %p\n", n,
// reinterpret_cast<void*>(arguments[0]));
return Avian_java_lang_ClassLoader_defineClass(t, 0, args);
}
@ -409,18 +417,37 @@ Avian_java_lang_VMClassLoader_loadClass
{
uintptr_t args[] = { 0, arguments[0] };
// object name = reinterpret_cast<object>(arguments[0]);
// char n[stringLength(t, name) + 1];
// stringChars(t, name, n);
// fprintf(stderr, "load bootstrap class %s in %p\n", n, t->m->loader);
return Avian_avian_SystemClassLoader_findClass(t, 0, args);
}
extern "C" JNIEXPORT int64_t JNICALL
Avian_avian_SystemClassLoader_findLoadedClass
(Thread*, object, uintptr_t*);
extern "C" JNIEXPORT int64_t JNICALL
Avian_java_lang_VMClassLoader_findLoadedClass
(Thread* t, object, uintptr_t* arguments)
{
uintptr_t args[] = { 0, arguments[1] };
object loader = reinterpret_cast<object>(arguments[0]);
object map = classLoaderMap(t, loader);
if (map) {
PROTECT(t, loader);
return Avian_avian_SystemClassLoader_findLoadedClass(t, 0, args);
object name = reinterpret_cast<object>(arguments[1]);
PROTECT(t, name);
object n = makeByteArray(t, stringLength(t, name) + 1);
char* s = reinterpret_cast<char*>(&byteArrayBody(t, n, 0));
stringChars(t, name, s);
replace('.', '/', s);
return reinterpret_cast<int64_t>
(hashMapFind
(t, classLoaderMap(t, loader), n, byteArrayHash, byteArrayEqual));
} else {
return 0;
}
}

View File

@ -223,7 +223,7 @@ FindClass(Thread* t, const char* name)
object n = makeByteArray(t, strlen(name) + 1);
replace('.', '/', name, &byteArrayBody(t, n, 0));
return makeLocalReference(t, resolveClass(t, n));
return makeLocalReference(t, resolveClass(t, t->m->loader, n));
}
jint JNICALL
@ -1213,7 +1213,7 @@ NewObjectArray(Thread* t, jsize length, jclass class_, jobject init)
{
ENTER(t, Thread::ActiveState);
object a = makeObjectArray(t, *class_, length);
object a = makeObjectArray(t, classLoader(t, *class_), *class_, length);
object value = (init ? *init : 0);
for (jsize i = 0; i < length; ++i) {
set(t, a, ArrayBody + (i * BytesPerWord), value);

View File

@ -501,6 +501,8 @@ postCollect(Thread* t)
void
finalizeObject(Thread* t, object o)
{
if (true) return;
if (t->state == Thread::ExitState) {
// don't waste time running Java finalizers if we're exiting the
// VM
@ -857,7 +859,7 @@ parseInterfaceTable(Thread* t, Stream& s, object class_, object pool)
object name = singletonObject(t, pool, s.read2() - 1);
PROTECT(t, name);
object interface = resolveClass(t, name);
object interface = resolveClass(t, classLoader(t, class_), name);
if (UNLIKELY(t->exception)) return;
PROTECT(t, interface);
@ -878,7 +880,8 @@ parseInterfaceTable(Thread* t, Stream& s, object class_, object pool)
unsigned i = 0;
for (HashMapIterator it(t, map); it.hasMore();) {
object interface = resolveClass(t, tripleFirst(t, it.next()));
object interface = resolveClass
(t, classLoader(t, class_), tripleFirst(t, it.next()));
if (UNLIKELY(t->exception)) return;
set(t, interfaceTable, ArrayBody + (i * BytesPerWord), interface);
@ -1164,6 +1167,68 @@ scanMethodSpec(Thread* t, const char* s, unsigned* parameterCount,
*returnCode = fieldCode(t, *it.returnSpec());
}
object
addInterfaceMethods(Thread* t, object class_, object virtualMap,
unsigned* virtualCount, bool makeList)
{
object itable = classInterfaceTable(t, class_);
if (itable) {
PROTECT(t, class_);
PROTECT(t, virtualMap);
PROTECT(t, itable);
object list = 0;
PROTECT(t, list);
object method = 0;
PROTECT(t, method);
object vtable = 0;
PROTECT(t, vtable);
unsigned stride = (classFlags(t, class_) & ACC_INTERFACE) ? 1 : 2;
for (unsigned i = 0; i < arrayLength(t, itable); i += stride) {
vtable = classVirtualTable(t, arrayBody(t, itable, i));
if (vtable) {
for (unsigned j = 0; j < arrayLength(t, vtable); ++j) {
method = arrayBody(t, vtable, j);
object n = hashMapFindNode
(t, virtualMap, method, methodHash, methodEqual);
if (n == 0) {
method = makeMethod
(t,
methodVmFlags(t, method),
methodReturnCode(t, method),
methodParameterCount(t, method),
methodParameterFootprint(t, method),
methodFlags(t, method),
(*virtualCount)++,
0,
methodName(t, method),
methodSpec(t, method),
class_,
0,
0);
hashMapInsert(t, virtualMap, method, method, methodHash);
if (makeList) {
if (list == 0) {
list = vm::makeList(t, 0, 0, 0);
}
listAppend(t, list, method);
}
}
}
}
}
return list;
}
return 0;
}
void
parseMethodTable(Thread* t, Stream& s, object class_, object pool)
{
@ -1180,38 +1245,7 @@ parseMethodTable(Thread* t, Stream& s, object class_, object pool)
PROTECT(t, superVirtualTable);
if (classFlags(t, class_) & ACC_INTERFACE) {
object itable = classInterfaceTable(t, class_);
if (itable) {
PROTECT(t, itable);
for (unsigned i = 0; i < arrayLength(t, itable); ++i) {
object vtable = classVirtualTable(t, arrayBody(t, itable, i));
if (vtable) {
PROTECT(t, vtable);
for (unsigned j = 0; j < arrayLength(t, vtable); ++j) {
object method = arrayBody(t, vtable, j);
object n = hashMapFindNode
(t, virtualMap, method, methodHash, methodEqual);
if (n == 0) {
method = makeMethod
(t,
methodVmFlags(t, method),
methodReturnCode(t, method),
methodParameterCount(t, method),
methodParameterFootprint(t, method),
methodFlags(t, method),
virtualCount++,
0,
methodName(t, method),
methodSpec(t, method),
class_,
0,
0);
hashMapInsert(t, virtualMap, method, method, methodHash);
}
}
}
}
}
addInterfaceMethods(t, class_, virtualMap, &virtualCount, false);
} else {
if (classSuper(t, class_)) {
superVirtualTable = classVirtualTable(t, classSuper(t, class_));
@ -1325,6 +1359,15 @@ parseMethodTable(Thread* t, Stream& s, object class_, object pool)
set(t, class_, ClassMethodTable, methodTable);
}
object abstractVirtuals;
if (classFlags(t, class_) & ACC_INTERFACE) {
abstractVirtuals = 0;
} else {
abstractVirtuals = addInterfaceMethods
(t, class_, virtualMap, &virtualCount, true);
}
PROTECT(t, abstractVirtuals);
bool populateInterfaceVtables = false;
if (declaredVirtualCount == 0
@ -1367,6 +1410,8 @@ parseMethodTable(Thread* t, Stream& s, object class_, object pool)
++ i;
}
} else {
populateInterfaceVtables = true;
if (superVirtualTable) {
for (; i < arrayLength(t, superVirtualTable); ++i) {
object method = arrayBody(t, superVirtualTable, i);
@ -1380,15 +1425,40 @@ parseMethodTable(Thread* t, Stream& s, object class_, object pool)
set(t, vtable, ArrayBody + (i * BytesPerWord), pairFirst(t, p));
++ i;
}
if (abstractVirtuals) {
PROTECT(t, abstractVirtuals);
unsigned oldLength = arrayLength(t, classMethodTable(t, class_));
object newMethodTable = makeArray
(t, oldLength + listSize(t, abstractVirtuals));
memcpy(&arrayBody(t, newMethodTable, 0),
&arrayBody(t, classMethodTable(t, class_), 0),
oldLength * sizeof(object));
mark(t, newMethodTable, ArrayBody, oldLength);
unsigned mti = oldLength;
for (object p = listFront(t, abstractVirtuals);
p; p = pairSecond(t, p))
{
set(t, newMethodTable,
ArrayBody + ((mti++) * BytesPerWord), pairFirst(t, p));
set(t, vtable,
ArrayBody + ((i++) * BytesPerWord), pairFirst(t, p));
}
assert(t, arrayLength(t, newMethodTable) == mti);
set(t, class_, ClassMethodTable, newMethodTable);
}
}
assert(t, arrayLength(t, vtable) == i);
set(t, class_, ClassVirtualTable, vtable);
if ((classFlags(t, class_) & ACC_INTERFACE) == 0) {
populateInterfaceVtables = true;
}
}
if (populateInterfaceVtables) {
@ -1406,9 +1476,7 @@ parseMethodTable(Thread* t, Stream& s, object class_, object pool)
object method = arrayBody(t, ivtable, j);
method = hashMapFind
(t, virtualMap, method, methodHash, methodEqual);
// note that method may be null in the case of an abstract
// class
assert(t, method);
set(t, vtable, ArrayBody + (j * BytesPerWord), method);
}
@ -1480,7 +1548,7 @@ updateBootstrapClass(Thread* t, object bootstrapClass, object class_)
}
object
makeArrayClass(Thread* t, unsigned dimensions, object spec,
makeArrayClass(Thread* t, object loader, unsigned dimensions, object spec,
object elementClass)
{
// todo: arrays should implement Cloneable and Serializable
@ -1502,7 +1570,7 @@ makeArrayClass(Thread* t, unsigned dimensions, object spec,
0,
0,
elementClass,
t->m->loader,
loader,
arrayLength(t, vtable));
t->m->processor->initVtable(t, c);
@ -1511,7 +1579,7 @@ makeArrayClass(Thread* t, unsigned dimensions, object spec,
}
object
makeArrayClass(Thread* t, object spec)
makeArrayClass(Thread* t, object loader, object spec)
{
PROTECT(t, spec);
@ -1551,11 +1619,28 @@ makeArrayClass(Thread* t, object spec)
(t, t->m->bootstrapClassMap, elementSpec, byteArrayHash, byteArrayEqual);
if (elementClass == 0) {
elementClass = resolveClass(t, elementSpec);
elementClass = resolveClass(t, loader, elementSpec);
if (UNLIKELY(t->exception)) return 0;
}
return makeArrayClass(t, dimensions, spec, elementClass);
return makeArrayClass(t, loader, dimensions, spec, elementClass);
}
object
resolveArrayClass(Thread* t, object loader, object spec)
{
object c = hashMapFind
(t, t->m->bootstrapClassMap, spec, byteArrayHash, byteArrayEqual);
if (c) {
set(t, c, ClassVirtualTable,
classVirtualTable
(t, arrayBody(t, t->m->types, Machine::JobjectType)));
return c;
} else {
return makeArrayClass(t, loader, spec);
}
}
void
@ -1714,9 +1799,10 @@ boot(Thread* t)
classVmFlags(t, arrayBody(t, m->types, Machine::JvoidType))
|= PrimitiveFlag;
m->bootstrapClassMap = makeHashMap(t, 0, 0);
object classMap = makeHashMap(t, 0, 0);
set(t, t->m->loader, ClassLoaderMap, classMap);
m->classMap = makeHashMap(t, 0, 0);
m->bootstrapClassMap = makeHashMap(t, 0, 0);
m->stringMap = makeWeakHashMap(t, 0, 0);
@ -1846,7 +1932,7 @@ Machine::Machine(System* system, Heap* heap, Finder* finder,
referenceLock(0),
libraries(0),
loader(0),
classMap(0),
loadClassMethod(0),
bootstrapClassMap(0),
monitorMap(0),
stringMap(0),
@ -1980,6 +2066,8 @@ Thread::init()
m->localThread->set(this);
} else {
assert(this, javaThread);
peer = parent->child;
parent->child = this;
}
@ -1990,9 +2078,11 @@ Thread::init()
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, 0);
0, 0, 0, m->loader, 0, 0, group);
}
}
@ -2378,7 +2468,7 @@ isAssignableFrom(Thread* t, object a, object b)
if (classFlags(t, a) & ACC_INTERFACE) {
if (classVmFlags(t, b) & BootstrapFlag) {
resolveClass(t, className(t, b));
resolveSystemClass(t, className(t, b));
if (UNLIKELY(t->exception)) {
t->exception = 0;
return false;
@ -2517,17 +2607,20 @@ primitiveSize(Thread* t, unsigned code)
}
object
findLoadedClass(Thread* t, object spec)
findLoadedSystemClass(Thread* t, object spec)
{
PROTECT(t, spec);
ACQUIRE(t, t->m->classLock);
return hashMapFind(t, t->m->classMap, spec, byteArrayHash, byteArrayEqual);
return hashMapFind(t, classLoaderMap(t, t->m->loader), spec, byteArrayHash,
byteArrayEqual);
}
object
parseClass(Thread* t, const uint8_t* data, unsigned size)
parseClass(Thread* t, object loader, const uint8_t* data, unsigned size)
{
PROTECT(t, loader);
class Client : public Stream::Client {
public:
Client(Thread* t): t(t) { }
@ -2567,13 +2660,13 @@ parseClass(Thread* t, const uint8_t* data, unsigned size)
0, // fields
0, // methods
0, // static table
t->m->loader,
loader,
0);// vtable length
PROTECT(t, class_);
unsigned super = s.read2();
if (super) {
object sc = resolveClass(t, singletonObject(t, pool, super - 1));
object sc = resolveClass(t, loader, singletonObject(t, pool, super - 1));
if (UNLIKELY(t->exception)) return 0;
set(t, class_, ClassSuper, sc);
@ -2623,26 +2716,18 @@ parseClass(Thread* t, const uint8_t* data, unsigned size)
}
object
resolveClass(Thread* t, object spec)
resolveSystemClass(Thread* t, object spec)
{
PROTECT(t, spec);
ACQUIRE(t, t->m->classLock);
object class_ = hashMapFind
(t, t->m->classMap, spec, byteArrayHash, byteArrayEqual);
(t, classLoaderMap(t, t->m->loader), spec, byteArrayHash, byteArrayEqual);
if (class_ == 0) {
if (byteArrayBody(t, spec, 0) == '[') {
class_ = hashMapFind
(t, t->m->bootstrapClassMap, spec, byteArrayHash, byteArrayEqual);
if (class_) {
set(t, class_, ClassVirtualTable,
classVirtualTable
(t, arrayBody(t, t->m->types, Machine::JobjectType)));
} else {
class_ = makeArrayClass(t, spec);
}
class_ = resolveArrayClass(t, t->m->loader, spec);
} else {
char file[byteArrayLength(t, spec) + 6];
memcpy(file, &byteArrayBody(t, spec, 0), byteArrayLength(t, spec) - 1);
@ -2656,7 +2741,8 @@ resolveClass(Thread* t, object spec)
}
// parse class file
class_ = parseClass(t, region->start(), region->length());
class_ = parseClass
(t, t->m->loader, region->start(), region->length());
region->dispose();
if (LIKELY(t->exception == 0)) {
@ -2667,11 +2753,12 @@ resolveClass(Thread* t, object spec)
}
object bootstrapClass = hashMapFind
(t, t->m->bootstrapClassMap, spec, byteArrayHash, byteArrayEqual);
(t, t->m->bootstrapClassMap, spec, byteArrayHash,
byteArrayEqual);
if (bootstrapClass) {
PROTECT(t, bootstrapClass);
updateBootstrapClass(t, bootstrapClass, class_);
class_ = bootstrapClass;
}
@ -2682,7 +2769,8 @@ resolveClass(Thread* t, object spec)
if (class_) {
PROTECT(t, class_);
hashMapInsert(t, t->m->classMap, spec, class_, byteArrayHash);
hashMapInsert(t, classLoaderMap(t, t->m->loader), spec, class_,
byteArrayHash);
} else if (t->exception == 0) {
object message = makeString(t, "%s", &byteArrayBody(t, spec, 0));
t->exception = makeClassNotFoundException(t, message);
@ -2692,6 +2780,76 @@ resolveClass(Thread* t, object spec)
return class_;
}
object
resolveClass(Thread* t, object loader, object spec)
{
if (loader == t->m->loader) {
return resolveSystemClass(t, spec);
} else {
PROTECT(t, loader);
PROTECT(t, spec);
ACQUIRE(t, t->m->classLock);
if (classLoaderMap(t, loader) == 0) {
object map = makeHashMap(t, 0, 0);
set(t, loader, ClassLoaderMap, map);
}
object class_ = hashMapFind
(t, classLoaderMap(t, loader), spec, byteArrayHash, byteArrayEqual);
if (class_ == 0) {
if (byteArrayBody(t, spec, 0) == '[') {
class_ = resolveArrayClass(t, loader, spec);
} else {
if (t->m->loadClassMethod == 0) {
object m = resolveMethod
(t, t->m->loader, "java/lang/ClassLoader", "loadClass",
"(Ljava/lang/String;)Ljava/lang/Class;");
if (m) {
t->m->loadClassMethod = m;
object classLoaderClass = arrayBody
(t, t->m->types, Machine::ClassLoaderType);
if (classVmFlags(t, classLoaderClass) & BootstrapFlag) {
resolveSystemClass(t, vm::className(t, classLoaderClass));
}
}
}
if (LIKELY(t->exception == 0)) {
object method = findMethod
(t, t->m->loadClassMethod, objectClass(t, loader));
if (LIKELY(t->exception == 0)) {
PROTECT(t, method);
object specString = makeString
(t, "%s", &byteArrayBody(t, spec, 0));
class_ = t->m->processor->invoke(t, method, loader, specString);
}
}
}
}
if (class_) {
PROTECT(t, class_);
hashMapInsert(t, classLoaderMap(t, loader), spec, class_,
byteArrayHash);
} else if (t->exception == 0) {
object message = makeString(t, "%s", &byteArrayBody(t, spec, 0));
t->exception = makeClassNotFoundException(t, message);
}
return class_;
}
}
object
resolveMethod(Thread* t, object class_, const char* methodName,
const char* methodSpec)
@ -2748,8 +2906,9 @@ resolveField(Thread* t, object class_, const char* fieldName,
}
object
resolveObjectArrayClass(Thread* t, object elementSpec)
resolveObjectArrayClass(Thread* t, object loader, object elementSpec)
{
PROTECT(t, loader);
PROTECT(t, elementSpec);
object spec;
@ -2770,7 +2929,7 @@ resolveObjectArrayClass(Thread* t, object elementSpec)
byteArrayBody(t, spec, byteArrayLength(t, elementSpec) + 2) = 0;
}
return resolveClass(t, spec);
return resolveClass(t, loader, spec);
}
bool
@ -2860,9 +3019,10 @@ initClass(Thread* t, object c)
}
object
makeObjectArray(Thread* t, object elementClass, unsigned count)
makeObjectArray(Thread* t, object loader, object elementClass, unsigned count)
{
object arrayClass = resolveObjectArrayClass(t, className(t, elementClass));
object arrayClass = resolveObjectArrayClass
(t, loader, className(t, elementClass));
PROTECT(t, arrayClass);
object array = makeArray(t, count);
@ -2926,10 +3086,6 @@ findInHierarchy(Thread* t, object class_, object name, object spec,
for (; o == 0 and class_; class_ = classSuper(t, class_)) {
o = find(t, class_, name, spec);
}
if (o == 0 and find == findMethodInClass) {
o = findInInterfaces(t, originalClass, name, spec, find);
}
}
if (o == 0) {
@ -3153,7 +3309,7 @@ void
visitRoots(Machine* m, Heap::Visitor* v)
{
v->visit(&(m->loader));
v->visit(&(m->classMap));
v->visit(&(m->loadClassMethod));
v->visit(&(m->bootstrapClassMap));
v->visit(&(m->monitorMap));
v->visit(&(m->stringMap));
@ -3275,7 +3431,7 @@ void
runJavaThread(Thread* t)
{
object method = resolveMethod
(t, "java/lang/Thread", "run", "(Ljava/lang/Thread;)V");
(t, t->m->loader, "java/lang/Thread", "run", "(Ljava/lang/Thread;)V");
if (t->exception == 0) {
t->m->processor->invoke(t, method, 0, t->javaThread);

View File

@ -1188,7 +1188,7 @@ class Machine {
System::Monitor* referenceLock;
System::Library* libraries;
object loader;
object classMap;
object loadClassMethod;
object bootstrapClassMap;
object monitorMap;
object stringMap;
@ -2070,7 +2070,7 @@ fieldSize(Thread* t, object field)
}
object
findLoadedClass(Thread* t, object spec);
findLoadedSystemClass(Thread* t, object spec);
inline bool
emptyMethod(Thread* t, object method)
@ -2081,15 +2081,26 @@ emptyMethod(Thread* t, object method)
}
object
parseClass(Thread* t, const uint8_t* data, unsigned length);
parseClass(Thread* t, object loader, const uint8_t* data, unsigned length);
object
resolveClass(Thread* t, object name);
resolveClass(Thread* t, object loader, object name);
inline object
resolveClass(Thread* t, const char* name)
resolveClass(Thread* t, object loader, const char* name)
{
return resolveClass(t, makeByteArray(t, "%s", name));
PROTECT(t, loader);
object n = makeByteArray(t, "%s", name);
return resolveClass(t, loader, n);
}
object
resolveSystemClass(Thread* t, object name);
inline object
resolveSystemClass(Thread* t, const char* name)
{
return resolveSystemClass(t, makeByteArray(t, "%s", name));
}
object
@ -2097,10 +2108,10 @@ resolveMethod(Thread* t, object class_, const char* methodName,
const char* methodSpec);
inline object
resolveMethod(Thread* t, const char* className, const char* methodName,
const char* methodSpec)
resolveMethod(Thread* t, object loader, const char* className,
const char* methodName, const char* methodSpec)
{
object class_ = resolveClass(t, className);
object class_ = resolveClass(t, loader, className);
if (LIKELY(t->exception == 0)) {
return resolveMethod(t, class_, methodName, methodSpec);
} else {
@ -2113,10 +2124,10 @@ resolveField(Thread* t, object class_, const char* fieldName,
const char* fieldSpec);
inline object
resolveField(Thread* t, const char* className, const char* fieldName,
const char* fieldSpec)
resolveField(Thread* t, object loader, const char* className,
const char* fieldName, const char* fieldSpec)
{
object class_ = resolveClass(t, className);
object class_ = resolveClass(t, loader, className);
if (LIKELY(t->exception == 0)) {
return resolveField(t, class_, fieldName, fieldSpec);
} else {
@ -2125,7 +2136,7 @@ resolveField(Thread* t, const char* className, const char* fieldName,
}
object
resolveObjectArrayClass(Thread* t, object elementSpec);
resolveObjectArrayClass(Thread* t, object loader, object elementSpec);
bool
classNeedsInit(Thread* t, object c);
@ -2140,7 +2151,7 @@ void
initClass(Thread* t, object c);
object
makeObjectArray(Thread* t, object elementClass, unsigned count);
makeObjectArray(Thread* t, object loader, object elementClass, unsigned count);
object
findInTable(Thread* t, object table, object name, object spec,

View File

@ -37,13 +37,14 @@ codeReadInt32(Thread* t, object code, unsigned& ip)
}
inline object
resolveClassInObject(Thread* t, object container, unsigned classOffset)
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, o);
o = resolveClass(t, loader, o);
if (UNLIKELY(t->exception)) return 0;
set(t, container, classOffset, o);
@ -52,34 +53,36 @@ resolveClassInObject(Thread* t, object container, unsigned classOffset)
}
inline object
resolveClassInPool(Thread* t, object pool, unsigned index)
resolveClassInPool(Thread* t, object method, unsigned index)
{
object o = singletonObject(t, pool, index);
object o = singletonObject(t, codePool(t, methodCode(t, method)), index);
if (objectClass(t, o) == arrayBody(t, t->m->types, Machine::ByteArrayType)) {
PROTECT(t, pool);
PROTECT(t, method);
o = resolveClass(t, o);
o = resolveClass(t, classLoader(t, methodClass(t, method)), o);
if (UNLIKELY(t->exception)) return 0;
set(t, pool, SingletonBody + (index * BytesPerWord), o);
set(t, codePool(t, methodCode(t, method)),
SingletonBody + (index * BytesPerWord), o);
}
return o;
}
inline object
resolve(Thread* t, object pool, unsigned index,
resolve(Thread* t, object method, unsigned index,
object (*find)(vm::Thread*, object, object, object),
object (*makeError)(vm::Thread*, object))
{
object o = singletonObject(t, pool, index);
object o = singletonObject(t, codePool(t, methodCode(t, method)), index);
if (objectClass(t, o) == arrayBody(t, t->m->types, Machine::ReferenceType))
{
PROTECT(t, pool);
PROTECT(t, method);
object reference = o;
PROTECT(t, reference);
object class_ = resolveClassInObject(t, o, ReferenceClass);
object class_ = resolveClassInObject
(t, classLoader(t, methodClass(t, method)), o, ReferenceClass);
if (UNLIKELY(t->exception)) return 0;
o = findInHierarchy
@ -87,22 +90,23 @@ resolve(Thread* t, object pool, unsigned index,
find, makeError);
if (UNLIKELY(t->exception)) return 0;
set(t, pool, SingletonBody + (index * BytesPerWord), o);
set(t, codePool(t, methodCode(t, method)),
SingletonBody + (index * BytesPerWord), o);
}
return o;
}
inline object
resolveField(Thread* t, object pool, unsigned index)
resolveField(Thread* t, object method, unsigned index)
{
return resolve(t, pool, index, findFieldInClass, makeNoSuchFieldError);
return resolve(t, method, index, findFieldInClass, makeNoSuchFieldError);
}
inline object
resolveMethod(Thread* t, object pool, unsigned index)
resolveMethod(Thread* t, object method, unsigned index)
{
return resolve(t, pool, index, findMethodInClass, makeNoSuchMethodError);
return resolve(t, method, index, findMethodInClass, makeNoSuchMethodError);
}
inline bool
@ -162,7 +166,7 @@ populateMultiArray(Thread* t, object array, int32_t* counts,
&byteArrayBody(t, spec, 1),
byteArrayLength(t, spec) - 1);
object class_ = resolveClass(t, elementSpec);
object class_ = resolveSystemClass(t, elementSpec);
PROTECT(t, class_);
for (int32_t i = 0; i < counts[index]; ++i) {

View File

@ -101,8 +101,9 @@ class Processor {
va_list arguments) = 0;
virtual object
invokeList(Thread* t, const char* className, const char* methodName,
const char* methodSpec, object this_, va_list arguments) = 0;
invokeList(Thread* t, object loader, const char* className,
const char* methodName, const char* methodSpec,
object this_, va_list arguments) = 0;
virtual void
dispose(Thread* t) = 0;
@ -160,13 +161,14 @@ class Processor {
}
object
invoke(Thread* t, const char* className, const char* methodName,
const char* methodSpec, object this_, ...)
invoke(Thread* t, object loader, const char* className,
const char* methodName, const char* methodSpec, object this_, ...)
{
va_list a;
va_start(a, this_);
object r = invokeList(t, className, methodName, methodSpec, this_, a);
object r = invokeList
(t, loader, className, methodName, methodSpec, this_, a);
va_end(a);

View File

@ -6,7 +6,8 @@
(type singleton
(array uintptr_t body))
(type classLoader java/lang/ClassLoader)
(type classLoader java/lang/ClassLoader
(object map))
(type systemClassLoader avian/SystemClassLoader)
@ -128,6 +129,8 @@
(type thread java/lang/Thread)
(type threadGroup java/lang/ThreadGroup)
(type stackTraceElement java/lang/StackTraceElement)
(type throwable java/lang/Throwable)