diff --git a/classpath/java/lang/Class.java b/classpath/java/lang/Class.java index f439ba3521..8e5307b5f4 100644 --- a/classpath/java/lang/Class.java +++ b/classpath/java/lang/Class.java @@ -22,6 +22,8 @@ import java.lang.annotation.Annotation; import java.io.InputStream; import java.io.IOException; import java.net.URL; +import java.util.Map; +import java.util.HashMap; import java.security.ProtectionDomain; import java.security.Permissions; import java.security.AllPermission; @@ -134,11 +136,15 @@ public final class Class implements Type, GenericDeclaration { private native void initialize(); public static Class forCanonicalName(String name) { + return forCanonicalName(null, name); + } + + public static Class forCanonicalName(ClassLoader loader, String name) { try { if (name.startsWith("[")) { - return forName(name); + return forName(name, true, loader); } else if (name.startsWith("L")) { - return forName(name.substring(1, name.length() - 1)); + return forName(name.substring(1, name.length() - 1), true, loader); } else { if (name.length() == 1) { return primitiveClass(name.charAt(0)); @@ -444,7 +450,7 @@ public final class Class implements Type, GenericDeclaration { } public boolean isArray() { - return arrayElementSize != 0; + return this != Class.class && arrayElementSize != 0; } public boolean isInstance(Object o) { @@ -484,7 +490,7 @@ public final class Class implements Type, GenericDeclaration { } public Object[] getSigners() { - throw new UnsupportedOperationException(); + return Static.signers.get(this); } public Annotation[] getDeclaredAnnotations() { @@ -531,6 +537,12 @@ public final class Class implements Type, GenericDeclaration { // for GNU Classpath compatibility: void setSigners(Object[] signers) { - throw new UnsupportedOperationException(); + if (signers != null && signers.length > 0) { + Static.signers.put(this, signers); + } + } + + private static class Static { + public static final Map signers = new HashMap(); } } diff --git a/classpath/java/lang/ClassLoader.java b/classpath/java/lang/ClassLoader.java index 3a7012ac27..31006f21dc 100644 --- a/classpath/java/lang/ClassLoader.java +++ b/classpath/java/lang/ClassLoader.java @@ -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 { diff --git a/classpath/java/lang/String.java b/classpath/java/lang/String.java index 79dcc8ee75..1ecb53629c 100644 --- a/classpath/java/lang/String.java +++ b/classpath/java/lang/String.java @@ -357,9 +357,13 @@ public final class String } public int lastIndexOf(String s) { - if (s.length == 0) return length; + return lastIndexOf(s, length - s.length); + } - for (int i = length - s.length; i >= 0; --i) { + public int lastIndexOf(String s, int lastIndex) { + if (s.length == 0) return lastIndex; + + for (int i = Math.min(length - s.length, lastIndex); i >= 0; --i) { int j = 0; for (; j < s.length && i + j < length; ++j) { if (charAt(i + j) != s.charAt(j)) { @@ -521,44 +525,12 @@ public final class String } } - public String[] split(String s) { - String[] array = new String[(length / s.length) + 1]; - int index = 0; - int last = 0; - int position = 0; - for (int i = 0; i < length - s.length + 1;) { - int j; - for (j = 0; j < s.length; ++j) { - if (charAt(i + j) != s.charAt(j)) { - break; - } - } + public String[] split(String regex) { + return split(regex, 0); + } - if (j == s.length) { - if (i > 0) { - if (i > position) { - last = index; - } - array[index++] = substring(position, i); - } - i = position = i + s.length; - } else { - ++ i; - } - } - - if (position < length) { - last = index; - array[index] = substring(position, length); - } - - if (last + 1 < array.length) { - String[] a = new String[last + 1]; - System.arraycopy(array, 0, a, 0, last + 1); - array = a; - } - - return array; + public String[] split(String regex, int limit) { + return Pattern.compile(regex).split(this, limit); } public CharSequence subSequence(int start, int end) { diff --git a/classpath/java/lang/Thread.java b/classpath/java/lang/Thread.java index 4279e5bfbf..e284c00df3 100644 --- a/classpath/java/lang/Thread.java +++ b/classpath/java/lang/Thread.java @@ -38,7 +38,7 @@ public class Thread implements Runnable { public Thread(ThreadGroup group, Runnable task, String name, long stackSize) { - this.group = group; + this.group = (group == null ? Thread.currentThread().group : group); this.task = task; this.name = name; @@ -86,8 +86,11 @@ public class Thread implements Runnable { throw new IllegalStateException("thread already started"); } + state = (byte) State.RUNNABLE.ordinal(); + peer = doStart(); if (peer == 0) { + state = (byte) State.NEW.ordinal(); throw new RuntimeException("unable to start native thread"); } } @@ -95,7 +98,6 @@ public class Thread implements Runnable { private native long doStart(); private static void run(Thread t) throws Throwable { - t.state = (byte) State.RUNNABLE.ordinal(); try { t.run(); } catch (Throwable e) { diff --git a/classpath/java/lang/reflect/Field.java b/classpath/java/lang/reflect/Field.java index 19df851027..36cbe8482a 100644 --- a/classpath/java/lang/reflect/Field.java +++ b/classpath/java/lang/reflect/Field.java @@ -53,7 +53,8 @@ public class Field extends AccessibleObject { } public Class getType() { - return Class.forCanonicalName(new String(spec, 0, spec.length - 1, false)); + return Class.forCanonicalName(class_.getClassLoader(), + new String(spec, 0, spec.length - 1, false)); } public Object get(Object instance) throws IllegalAccessException { diff --git a/classpath/java/lang/reflect/Method.java b/classpath/java/lang/reflect/Method.java index f6ac1bd6cd..ec648042ac 100644 --- a/classpath/java/lang/reflect/Method.java +++ b/classpath/java/lang/reflect/Method.java @@ -73,23 +73,26 @@ public class Method extends AccessibleObject } else if (c == 'L') { int start = i + 1; i = next(';', spec, start); - String name = spec.substring(start, i); - types[index++] = Class.forName(name); + String name = spec.substring(start, i).replace('/', '.'); + types[index++] = Class.forName(name, true, class_.getClassLoader()); } else if (c == '[') { int start = i; while (spec.charAt(i) == '[') ++i; if (spec.charAt(i) == 'L') { i = next(';', spec, i + 1); - String name = spec.substring(start, i); - types[index++] = Class.forName(name); + String name = spec.substring(start, i).replace('/', '.'); + types[index++] = Class.forName + (name, true, class_.getClassLoader()); } else { String name = spec.substring(start, i + 1); - types[index++] = Class.forCanonicalName(name); + types[index++] = Class.forCanonicalName + (class_.getClassLoader(), name); } } else { String name = spec.substring(i, i + 1); - types[index++] = Class.forCanonicalName(name); + types[index++] = Class.forCanonicalName + (class_.getClassLoader(), name); } } } catch (ClassNotFoundException e) { @@ -103,6 +106,17 @@ public class Method extends AccessibleObject throws InvocationTargetException, IllegalAccessException { if ((flags & Modifier.STATIC) != 0 || class_.isInstance(instance)) { + if ((flags & Modifier.STATIC) != 0) { + instance = null; + } + + if (arguments == null) { + if (parameterCount > 0) { + throw new NullPointerException(); + } + arguments = new Object[0]; + } + if (arguments.length == parameterCount) { return invoke(this, instance, arguments); } else { @@ -121,7 +135,8 @@ public class Method extends AccessibleObject for (int i = 0; i < spec.length - 1; ++i) { if (spec[i] == ')') { return Class.forCanonicalName - (new String(spec, i + 1, spec.length - i - 2, false)); + (class_.getClassLoader(), + new String(spec, i + 1, spec.length - i - 2, false)); } } throw new RuntimeException(); diff --git a/makefile b/makefile index 2fa7ba0eff..8007d68521 100644 --- a/makefile +++ b/makefile @@ -375,14 +375,19 @@ gnu-overrides = \ avian/*.class \ avian/resource/*.class \ java/lang/Class.class \ + java/lang/Class\$$*.class \ java/lang/Enum.class \ java/lang/InheritableThreadLocal.class \ java/lang/Object.class \ java/lang/StackTraceElement.class \ - java/lang/String*.class \ + java/lang/String.class \ + java/lang/String\$$*.class \ java/lang/StringBuffer.class \ 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 \ diff --git a/src/builtin.cpp b/src/builtin.cpp index 712dabce0f..6c7dbb74e4 100644 --- a/src/builtin.cpp +++ b/src/builtin.cpp @@ -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,30 @@ extern "C" JNIEXPORT int64_t JNICALL Avian_java_lang_ClassLoader_defineClass (Thread* t, object, uintptr_t* arguments) { - object b = reinterpret_cast(arguments[0]); - int offset = arguments[1]; - int length = arguments[2]; + object loader = reinterpret_cast(arguments[0]); + PROTECT(t, loader); + + object b = reinterpret_cast(arguments[1]); + int offset = arguments[2]; + int length = arguments[3]; uint8_t* buffer = static_cast (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) { + if (classLoaderMap(t, loader) == 0) { + PROTECT(t, c); + object map = makeHashMap(t, 0, 0); + set(t, loader, ClassLoaderMap, map); + } + + hashMapInsert(t, classLoaderMap(t, loader), className(t, c), c, + byteArrayHash); + } + return reinterpret_cast(c); } @@ -195,7 +205,7 @@ Avian_avian_SystemClassLoader_findLoadedClass { object name = reinterpret_cast(arguments[1]); - return search(t, name, findLoadedClass, true); + return search(t, name, findLoadedSystemClass, true); } extern "C" JNIEXPORT int64_t JNICALL @@ -204,7 +214,7 @@ Avian_avian_SystemClassLoader_findClass { object name = reinterpret_cast(arguments[1]); - return search(t, name, resolveClass, true); + return search(t, name, resolveSystemClass, true); } extern "C" JNIEXPORT int64_t JNICALL @@ -465,7 +475,8 @@ Avian_java_lang_reflect_Array_makeObjectArray object elementType = reinterpret_cast(arguments[0]); int length = arguments[1]; - return reinterpret_cast(makeObjectArray(t, elementType, length)); + return reinterpret_cast + (makeObjectArray(t, classLoader(t, elementType), elementType, length)); } extern "C" JNIEXPORT int64_t JNICALL @@ -767,8 +778,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; diff --git a/src/common.h b/src/common.h index 10690c6046..4896bd2201 100644 --- a/src/common.h +++ b/src/common.h @@ -44,14 +44,12 @@ # define ULD "u" # endif #elif defined __x86_64__ +# define LD "ld" +# define LX "lx" # ifdef __MINGW32__ -# define LD "I64d" -# define LX "I64x" # define LLD "I64d" # define ULD "I64x" # else -# define LD "ld" -# define LX "lx" # define LLD "ld" # define ULD "lu" # endif @@ -313,6 +311,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; diff --git a/src/compile.cpp b/src/compile.cpp index add06d4845..cfe268f15f 100644 --- a/src/compile.cpp +++ b/src/compile.cpp @@ -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(makeObjectArray(t, class_, length)); + return reinterpret_cast + (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_)); @@ -3807,37 +3813,42 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, int32_t pairCount = codeReadInt32(t, code, ip); - Compiler::Operand* start = 0; - uint32_t ipTable[pairCount]; - for (int32_t i = 0; i < pairCount; ++i) { - unsigned index = ip + (i * 8); - int32_t key = codeReadInt32(t, code, index); - uint32_t newIp = base + codeReadInt32(t, code, index); - assert(t, newIp < codeLength(t, code)); + if (pairCount) { + Compiler::Operand* start = 0; + uint32_t ipTable[pairCount]; + for (int32_t i = 0; i < pairCount; ++i) { + unsigned index = ip + (i * 8); + int32_t key = codeReadInt32(t, code, index); + uint32_t newIp = base + codeReadInt32(t, code, index); + assert(t, newIp < codeLength(t, code)); - ipTable[i] = newIp; + ipTable[i] = newIp; - Promise* p = c->poolAppend(key); - if (i == 0) { - start = frame->addressOperand(p); + Promise* p = c->poolAppend(key); + if (i == 0) { + start = frame->addressOperand(p); + } + c->poolAppendPromise(frame->addressPromise(c->machineIp(newIp))); } - c->poolAppendPromise(frame->addressPromise(c->machineIp(newIp))); - } - assert(t, start); + assert(t, start); - c->jmp - (c->call - (c->constant(getThunk(t, lookUpAddressThunk)), - 0, 0, BytesPerWord, - 4, key, start, c->constant(pairCount), default_)); + c->jmp + (c->call + (c->constant(getThunk(t, lookUpAddressThunk)), + 0, 0, BytesPerWord, + 4, key, start, c->constant(pairCount), default_)); - Compiler::State* state = c->saveState(); + Compiler::State* state = c->saveState(); - for (int32_t i = 0; i < pairCount; ++i) { - compile(t, frame, ipTable[i]); - if (UNLIKELY(t->exception)) return; + for (int32_t i = 0; i < pairCount; ++i) { + compile(t, frame, ipTable[i]); + if (UNLIKELY(t->exception)) return; - c->restoreState(state); + c->restoreState(state); + } + } else { + // a switch statement with no cases, apparently + c->jmp(default_); } ip = defaultIp; @@ -3934,7 +3945,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 +3969,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 +4019,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 +4321,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 +4356,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 +4365,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 +4954,8 @@ finish(MyThread* t, Allocator* allocator, Context* context) } } - translateExceptionHandlerTable(t, c, methodCode(t, context->method), - reinterpret_cast(start)); + translateExceptionHandlerTable + (t, c, context->method, reinterpret_cast(start)); if (UNLIKELY(t->exception)) return 0; translateLineNumberTable(t, c, methodCode(t, context->method), @@ -5825,6 +5837,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(spec)); object name; @@ -5837,7 +5851,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 +5974,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 +6045,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 +6055,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 +6093,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 +6585,16 @@ class MyProcessor: public Processor { PROTECT(t, method); + if (false) { + compile(static_cast(t), + ::codeAllocator(static_cast(t)), 0, + resolveMethod(t, t->m->loader, + "java/beans/PropertyChangeSupport", + "firePropertyChange", + "(Ljava/beans/PropertyChangeEvent;)V")); + trap(); + } + compile(static_cast(t), ::codeAllocator(static_cast(t)), 0, method); @@ -6581,8 +6606,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 +6621,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 +7091,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 +7221,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; diff --git a/src/compiler.cpp b/src/compiler.cpp index 85fbc379d6..81e84d5d80 100644 --- a/src/compiler.cpp +++ b/src/compiler.cpp @@ -256,7 +256,7 @@ class Read { value(0), event(0), eventNext(0) { } - virtual bool intersect(SiteMask* mask) = 0; + virtual bool intersect(SiteMask* mask, unsigned depth = 0) = 0; virtual Value* successor() = 0; @@ -1939,7 +1939,7 @@ class SingleRead: public Read { next_(0), mask(mask), successor_(successor) { } - virtual bool intersect(SiteMask* mask) { + virtual bool intersect(SiteMask* mask, unsigned) { *mask = ::intersect(*mask, this->mask); return true; @@ -2002,13 +2002,19 @@ class MultiRead: public Read { reads(0), lastRead(0), firstTarget(0), lastTarget(0), visited(false) { } - virtual bool intersect(SiteMask* mask) { + virtual bool intersect(SiteMask* mask, unsigned depth) { + if (depth > 0) { + // short-circuit recursion to avoid poor performance in + // deeply-nested branches + return reads != 0; + } + bool result = false; if (not visited) { visited = true; for (Cell** cell = &reads; *cell;) { Read* r = static_cast((*cell)->value); - bool valid = r->intersect(mask); + bool valid = r->intersect(mask, depth + 1); if (valid) { result = true; cell = &((*cell)->next); @@ -2101,11 +2107,11 @@ class StubRead: public Read { next_(0), read(0), visited(false), valid_(true) { } - virtual bool intersect(SiteMask* mask) { + virtual bool intersect(SiteMask* mask, unsigned depth) { if (not visited) { visited = true; if (read) { - bool valid = read->intersect(mask); + bool valid = read->intersect(mask, depth); if (not valid) { read = 0; } @@ -4319,20 +4325,32 @@ resolveOriginalSites(Context* c, Event* e, SiteRecordList* frozen, FrameIterator::Element el = it.next(c); Value* v = el.value; Read* r = live(v); + Site* s = sites[el.localIndex]; if (r) { - if (sites[el.localIndex]) { + if (s) { if (DebugControl) { char buffer[256]; - sites[el.localIndex]->toString(c, buffer, 256); + s->toString(c, buffer, 256); fprintf(stderr, "resolve original %s for %p local %d frame %d\n", - buffer, el.value, el.localIndex, frameIndex(c, &el)); + buffer, v, el.localIndex, frameIndex(c, &el)); } - acquireSite(c, frozen, sites[el.localIndex], v, r, true); + acquireSite(c, frozen, s, v, r, true); } else { complete = false; } + } else if (s) { + if (DebugControl) { + char buffer[256]; + s->toString(c, buffer, 256); + fprintf(stderr, "freeze original %s for %p local %d frame %d\n", + buffer, v, el.localIndex, frameIndex(c, &el)); + } + + addSite(c, v, s); + removeSite(c, v, s); + freeze(c, frozen, s, v); } } @@ -4513,7 +4531,14 @@ setSites(Context* c, Event* e, Site** sites) if (sites[el.localIndex]) { if (live(el.value)) { setSites(c, el.value, sites[el.localIndex]); + } else if (DebugControl) { + char buffer[256]; sitesToString(c, sites[el.localIndex], buffer, 256); + fprintf(stderr, "skip sites %s for %p local %d frame %d\n", + buffer, el.value, el.localIndex, frameIndex(c, &el)); } + } else if (DebugControl) { + fprintf(stderr, "no sites for %p local %d frame %d\n", + el.value, el.localIndex, frameIndex(c, &el)); } } } diff --git a/src/gnu.cpp b/src/gnu.cpp index 1aa77106b5..ed34e0e5bb 100644 --- a/src/gnu.cpp +++ b/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)) { @@ -133,6 +134,9 @@ Avian_gnu_classpath_VMSystemProperties_preInit PROTECT(t, method); + setProperty(t, method, properties, "java.version", "1.5"); + setProperty(t, method, properties, "java.specification.version", "1.5"); + setProperty(t, method, properties, "java.vm.name", "Avian"); setProperty(t, method, properties, "java.protocol.handler.pkgs", "avian"); @@ -212,7 +216,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 +244,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(v.trace); @@ -341,7 +345,7 @@ Avian_java_lang_VMRuntime_nativeLoad extern "C" JNIEXPORT int64_t JNICALL Avian_java_lang_Class_primitiveClass -(Thread* t, object, uintptr_t*); +(Thread*, object, uintptr_t*); extern "C" JNIEXPORT int64_t JNICALL Avian_java_lang_VMClassLoader_getPrimitiveClass @@ -350,6 +354,26 @@ Avian_java_lang_VMClassLoader_getPrimitiveClass return Avian_java_lang_Class_primitiveClass(t, 0, arguments); } +extern "C" JNIEXPORT int64_t JNICALL +Avian_java_lang_ClassLoader_defineClass +(Thread*, object, uintptr_t*); + +extern "C" JNIEXPORT int64_t JNICALL +Avian_java_lang_VMClassLoader_defineClass +(Thread* t, object, uintptr_t* arguments) +{ + uintptr_t args[] + = { arguments[0], arguments[2], arguments[3], arguments[4] }; + +// object name = reinterpret_cast(arguments[1]); +// char n[stringLength(t, name) + 1]; +// stringChars(t, name, n); +// fprintf(stderr, "define class %s in %p\n", n, +// reinterpret_cast(arguments[0])); + + return Avian_java_lang_ClassLoader_defineClass(t, 0, args); +} + extern "C" JNIEXPORT int64_t JNICALL Avian_java_lang_System_identityHashCode (Thread*, object, uintptr_t*); @@ -396,18 +420,44 @@ Avian_java_lang_VMClassLoader_loadClass { uintptr_t args[] = { 0, arguments[0] }; +// object name = reinterpret_cast(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 void JNICALL +Avian_java_lang_VMClassLoader_resolveClass +(Thread*, object, uintptr_t*) +{ + // ignore +} 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(arguments[0]); + + object map = classLoaderMap(t, loader); + if (map) { + PROTECT(t, loader); - return Avian_avian_SystemClassLoader_findLoadedClass(t, 0, args); + object name = reinterpret_cast(arguments[1]); + PROTECT(t, name); + + object n = makeByteArray(t, stringLength(t, name) + 1); + char* s = reinterpret_cast(&byteArrayBody(t, n, 0)); + stringChars(t, name, s); + + replace('.', '/', s); + + return reinterpret_cast + (hashMapFind + (t, classLoaderMap(t, loader), n, byteArrayHash, byteArrayEqual)); + } else { + return 0; + } } diff --git a/src/jnienv.cpp b/src/jnienv.cpp index ffd96025cc..8c4a96c639 100644 --- a/src/jnienv.cpp +++ b/src/jnienv.cpp @@ -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); diff --git a/src/machine.cpp b/src/machine.cpp index 40420ee1cd..11290bf0bf 100644 --- a/src/machine.cpp +++ b/src/machine.cpp @@ -857,7 +857,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 +878,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 +1165,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 +1243,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 +1357,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 +1408,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 +1423,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 +1474,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 +1546,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 +1568,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 +1577,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 +1617,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 +1797,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 +1930,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 +2064,8 @@ Thread::init() m->localThread->set(this); } else { + assert(this, javaThread); + peer = parent->child; parent->child = this; } @@ -1990,9 +2076,11 @@ Thread::init() const unsigned NewState = 0; const unsigned NormalPriority = 5; + object group = makeThreadGroup(this, 0, 0); + this->javaThread = makeThread (this, reinterpret_cast(this), 0, 0, NewState, NormalPriority, - 0, 0, 0, m->loader, 0, 0, 0); + 0, 0, 0, m->loader, 0, 0, group); } } @@ -2296,6 +2384,8 @@ makeNewGeneral(Thread* t, object class_) { assert(t, t->state == Thread::ActiveState); + PROTECT(t, class_); + object instance = makeNew(t, class_); PROTECT(t, instance); @@ -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,79 @@ 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)); + + replace('/', '.', reinterpret_cast + (&byteArrayBody(t, stringData(t, specString), 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 +2909,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 +2932,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 +3022,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 +3089,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 +3312,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 +3434,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); diff --git a/src/machine.h b/src/machine.h index ab3b038c55..a5e686238c 100644 --- a/src/machine.h +++ b/src/machine.h @@ -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, diff --git a/src/powerpc.cpp b/src/powerpc.cpp index 64e95df96d..073dc8bbf7 100644 --- a/src/powerpc.cpp +++ b/src/powerpc.cpp @@ -501,11 +501,19 @@ void unsignedShiftRightR(Context* con, unsigned size, Reg* a, Reg* b, Reg* t) } } +void +moveRR(Context* c, unsigned srcSize, Assembler::Register* src, + unsigned dstSize, Assembler::Register* dst); + void unsignedShiftRightC(Context* con, unsigned size, Const* a, Reg* b, Reg* t) { int sh = getVal(a); if (size == 8) { - if (sh < 32) { + if (sh == 32) { + Assembler::Register high(b->high); + moveRR(con, 4, &high, 4, t); + issue(con, li(H(t),0)); + } else if (sh < 32) { issue(con, srwi(R(t), R(b), sh)); issue(con, rlwimi(R(t),H(b),32-sh,0,sh-1)); issue(con, rlwinm(H(t),H(b),32-sh,sh,31)); @@ -596,10 +604,6 @@ jumpR(Context* c, unsigned size UNUSED, Assembler::Register* target) issue(c, bctr()); } -void -moveRR(Context* c, unsigned srcSize, Assembler::Register* src, - unsigned dstSize, Assembler::Register* dst); - void swapRR(Context* c, unsigned aSize, Assembler::Register* a, unsigned bSize, Assembler::Register* b) diff --git a/src/process.cpp b/src/process.cpp index a2aad7cd0d..41d4a829e5 100644 --- a/src/process.cpp +++ b/src/process.cpp @@ -203,14 +203,14 @@ namespace vm { void* resolveNativeMethod(Thread* t, object method) { - void* p = ::resolveNativeMethod(t, method, "Java_", 5, -1); + void* p = ::resolveNativeMethod(t, method, "Avian_", 6, 3); if (p) { + methodVmFlags(t, method) |= FastNative; return p; } - p = ::resolveNativeMethod(t, method, "Avian_", 6, 3); + p = ::resolveNativeMethod(t, method, "Java_", 5, -1); if (p) { - methodVmFlags(t, method) |= FastNative; return p; } diff --git a/src/process.h b/src/process.h index ad58e22c67..bc7b987ad8 100644 --- a/src/process.h +++ b/src/process.h @@ -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(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) { diff --git a/src/processor.h b/src/processor.h index 0f2316f6c1..f7de71b425 100644 --- a/src/processor.h +++ b/src/processor.h @@ -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); diff --git a/src/types.def b/src/types.def index b099fc3397..5afa48a8e8 100644 --- a/src/types.def +++ b/src/types.def @@ -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) diff --git a/test/Longs.java b/test/Longs.java index 51fad92969..284a72a8ca 100644 --- a/test/Longs.java +++ b/test/Longs.java @@ -39,6 +39,10 @@ public class Longs { return -1; } + private static long unsignedShiftRight32(long x) { + return x >>> 32; + } + public static void main(String[] args) { expect(((long) negativeOne()) == -1); @@ -211,6 +215,8 @@ public class Longs { buffer.putLong(231); buffer.flip(); expect(buffer.getLong() == 231); + + expect(unsignedShiftRight32(231) == 0); } }