Merge branch 'master' of oss.readytalk.com:/var/local/git/avian

This commit is contained in:
jet 2009-08-13 09:57:40 -06:00
commit bf75e73aa9
21 changed files with 601 additions and 283 deletions

View File

@ -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 <T> 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 <T> 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 <T> 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 <T> 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<Class,Object[]> signers = new HashMap();
}
}

View File

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

View File

@ -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) {

View File

@ -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) {

View File

@ -53,7 +53,8 @@ public class Field<T> 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 {

View File

@ -73,23 +73,26 @@ public class Method<T> 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<T> 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<T> 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();

View File

@ -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 \

View File

@ -11,17 +11,12 @@
#include "machine.h"
#include "constants.h"
#include "processor.h"
#include "util.h"
using namespace vm;
namespace {
inline void
replace(char a, char b, char* c)
{
for (; *c; ++c) if (*c == a) *c = b;
}
int64_t
search(Thread* t, object name, object (*op)(Thread*, object),
bool replaceDots)
@ -177,15 +172,30 @@ 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) {
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<int64_t>(c);
}
@ -195,7 +205,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 +214,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 +475,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 +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;

View File

@ -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;

View File

@ -147,7 +147,7 @@ resolveTarget(MyThread* t, void* stack, object method)
PROTECT(t, method);
PROTECT(t, class_);
resolveClass(t, className(t, class_));
resolveSystemClass(t, className(t, class_));
if (UNLIKELY(t->exception)) return 0;
}
@ -164,7 +164,7 @@ resolveTarget(MyThread* t, object class_, unsigned index)
if (classVmFlags(t, class_) & BootstrapFlag) {
PROTECT(t, class_);
resolveClass(t, className(t, class_));
resolveSystemClass(t, className(t, class_));
if (UNLIKELY(t->exception)) return 0;
}
@ -2030,10 +2030,11 @@ longToFloat(int64_t a)
}
uint64_t
makeBlankObjectArray(MyThread* t, object class_, int32_t length)
makeBlankObjectArray(MyThread* t, object loader, object class_, int32_t length)
{
if (length >= 0) {
return reinterpret_cast<uint64_t>(makeObjectArray(t, class_, length));
return reinterpret_cast<uint64_t>
(makeObjectArray(t, loader, class_, length));
} else {
object message = makeString(t, "%d", length);
t->exception = makeNegativeArraySizeException(t, message);
@ -2226,6 +2227,9 @@ throw_(MyThread* t, object o)
} else {
t->exception = makeNullPointerException(t);
}
// printTrace(t, t->exception);
unwind(t);
}
@ -2746,7 +2750,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip,
case anewarray: {
uint16_t index = codeReadInt16(t, code, ip);
object class_ = resolveClassInPool(t, codePool(t, code), index - 1);
object class_ = resolveClassInPool(t, context->method, index - 1);
if (UNLIKELY(t->exception)) return;
Compiler::Operand* length = frame->popInt();
@ -2757,7 +2761,9 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip,
0,
frame->trace(0, 0),
BytesPerWord,
3, c->register_(t->arch->thread()), frame->append(class_), length));
4, c->register_(t->arch->thread()),
frame->append(classLoader(t, methodClass(t, context->method))),
frame->append(class_), length));
} break;
case areturn: {
@ -2810,7 +2816,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip,
case checkcast: {
uint16_t index = codeReadInt16(t, code, ip);
object class_ = resolveClassInPool(t, codePool(t, code), index - 1);
object class_ = resolveClassInPool(t, context->method, index - 1);
if (UNLIKELY(t->exception)) return;
Compiler::Operand* instance = c->peek(1, 0);
@ -3085,7 +3091,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip,
case getstatic: {
uint16_t index = codeReadInt16(t, code, ip);
object field = resolveField(t, codePool(t, code), index - 1);
object field = resolveField(t, context->method, index - 1);
if (UNLIKELY(t->exception)) return;
Compiler::Operand* table;
@ -3452,7 +3458,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip,
case instanceof: {
uint16_t index = codeReadInt16(t, code, ip);
object class_ = resolveClassInPool(t, codePool(t, code), index - 1);
object class_ = resolveClassInPool(t, context->method, index - 1);
if (UNLIKELY(t->exception)) return;
frame->pushInt
@ -3467,7 +3473,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip,
uint16_t index = codeReadInt16(t, code, ip);
ip += 2;
object target = resolveMethod(t, codePool(t, code), index - 1);
object target = resolveMethod(t, context->method, index - 1);
if (UNLIKELY(t->exception)) return;
assert(t, (methodFlags(t, target) & ACC_STATIC) == 0);
@ -3502,7 +3508,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip,
case invokespecial: {
uint16_t index = codeReadInt16(t, code, ip);
object target = resolveMethod(t, codePool(t, code), index - 1);
object target = resolveMethod(t, context->method, index - 1);
if (UNLIKELY(t->exception)) return;
object class_ = methodClass(t, context->method);
@ -3520,7 +3526,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip,
case invokestatic: {
uint16_t index = codeReadInt16(t, code, ip);
object target = resolveMethod(t, codePool(t, code), index - 1);
object target = resolveMethod(t, context->method, index - 1);
if (UNLIKELY(t->exception)) return;
assert(t, methodFlags(t, target) & ACC_STATIC);
@ -3533,7 +3539,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip,
case invokevirtual: {
uint16_t index = codeReadInt16(t, code, ip);
object target = resolveMethod(t, codePool(t, code), index - 1);
object target = resolveMethod(t, context->method, index - 1);
if (UNLIKELY(t->exception)) return;
assert(t, (methodFlags(t, target) & ACC_STATIC) == 0);
@ -3729,7 +3735,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip,
if (objectClass(t, v)
== arrayBody(t, t->m->types, Machine::ByteArrayType))
{
object class_ = resolveClassInPool(t, pool, index - 1);
object class_ = resolveClassInPool(t, context->method, index - 1);
if (UNLIKELY(t->exception)) return;
frame->pushObject(frame->append(class_));
@ -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<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),
@ -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<char*>(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<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 +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;

View File

@ -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<Read*>((*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));
}
}
}

View File

@ -11,6 +11,7 @@
#include "machine.h"
#include "constants.h"
#include "processor.h"
#include "util.h"
using namespace vm;
@ -48,7 +49,7 @@ NewDirectByteBuffer(Thread* t, void* address, jlong capacity)
initSpec = "(I)V";
}
object pointerClass = resolveClass(t, pointerClassName);
object pointerClass = resolveClass(t, t->m->loader, pointerClassName);
if (UNLIKELY(pointerClass == 0)) return 0;
PROTECT(t, pointerClass);
@ -63,7 +64,7 @@ NewDirectByteBuffer(Thread* t, void* address, jlong capacity)
if (UNLIKELY(t->exception)) return 0;
object bufferClass = resolveClass
(t, "java/nio/DirectByteBufferImpl$ReadWrite");
(t, t->m->loader, "java/nio/DirectByteBufferImpl$ReadWrite");
if (UNLIKELY(bufferClass == 0)) return 0;
PROTECT(t, bufferClass);
@ -124,7 +125,7 @@ Avian_gnu_classpath_VMSystemProperties_preInit
PROTECT(t, properties);
object method = resolveMethod
(t, "java/util/Properties", "setProperty",
(t, t->m->loader, "java/util/Properties", "setProperty",
"(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/Object;");
if (UNLIKELY(t->exception)) {
@ -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<int64_t>(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<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);
}
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<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 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<object>(arguments[0]);
object map = classLoaderMap(t, loader);
if (map) {
PROTECT(t, loader);
return Avian_avian_SystemClassLoader_findLoadedClass(t, 0, args);
object name = reinterpret_cast<object>(arguments[1]);
PROTECT(t, name);
object n = makeByteArray(t, stringLength(t, name) + 1);
char* s = reinterpret_cast<char*>(&byteArrayBody(t, n, 0));
stringChars(t, name, s);
replace('.', '/', s);
return reinterpret_cast<int64_t>
(hashMapFind
(t, classLoaderMap(t, loader), n, byteArrayHash, byteArrayEqual));
} else {
return 0;
}
}

View File

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

View File

@ -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<int64_t>(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<char*>
(&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);

View File

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

View File

@ -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)

View File

@ -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;
}

View File

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

View File

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

View File

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

View File

@ -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);
}
}