mirror of
https://github.com/corda/corda.git
synced 2025-01-19 03:06:36 +00:00
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:
parent
54bb64cfb2
commit
001000364d
@ -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 {
|
||||
|
2
makefile
2
makefile
@ -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 \
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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;
|
||||
|
51
src/gnu.cpp
51
src/gnu.cpp
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
|
320
src/machine.cpp
320
src/machine.cpp
@ -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);
|
||||
|
@ -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,
|
||||
|
@ -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) {
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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)
|
||||
|
Loading…
Reference in New Issue
Block a user