mirror of
https://github.com/corda/corda.git
synced 2025-01-06 05:04:20 +00:00
Merge branch 'master' of oss.readytalk.com:/var/local/git/avian
This commit is contained in:
commit
bf75e73aa9
@ -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();
|
||||
}
|
||||
}
|
||||
|
@ -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 {
|
||||
|
@ -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) {
|
||||
|
@ -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) {
|
||||
|
@ -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 {
|
||||
|
@ -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();
|
||||
|
7
makefile
7
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 \
|
||||
|
@ -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;
|
||||
|
12
src/common.h
12
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;
|
||||
|
||||
|
145
src/compile.cpp
145
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<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;
|
||||
|
@ -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));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
72
src/gnu.cpp
72
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<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;
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
|
323
src/machine.cpp
323
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<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);
|
||||
|
@ -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,
|
||||
|
@ -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)
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -37,13 +37,14 @@ codeReadInt32(Thread* t, object code, unsigned& ip)
|
||||
}
|
||||
|
||||
inline object
|
||||
resolveClassInObject(Thread* t, object container, unsigned classOffset)
|
||||
resolveClassInObject(Thread* t, object loader, object container,
|
||||
unsigned classOffset)
|
||||
{
|
||||
object o = cast<object>(container, classOffset);
|
||||
if (objectClass(t, o) == arrayBody(t, t->m->types, Machine::ByteArrayType)) {
|
||||
PROTECT(t, container);
|
||||
|
||||
o = resolveClass(t, o);
|
||||
o = resolveClass(t, loader, o);
|
||||
if (UNLIKELY(t->exception)) return 0;
|
||||
|
||||
set(t, container, classOffset, o);
|
||||
@ -52,34 +53,36 @@ resolveClassInObject(Thread* t, object container, unsigned classOffset)
|
||||
}
|
||||
|
||||
inline object
|
||||
resolveClassInPool(Thread* t, object pool, unsigned index)
|
||||
resolveClassInPool(Thread* t, object method, unsigned index)
|
||||
{
|
||||
object o = singletonObject(t, pool, index);
|
||||
object o = singletonObject(t, codePool(t, methodCode(t, method)), index);
|
||||
if (objectClass(t, o) == arrayBody(t, t->m->types, Machine::ByteArrayType)) {
|
||||
PROTECT(t, pool);
|
||||
PROTECT(t, method);
|
||||
|
||||
o = resolveClass(t, o);
|
||||
o = resolveClass(t, classLoader(t, methodClass(t, method)), o);
|
||||
if (UNLIKELY(t->exception)) return 0;
|
||||
|
||||
set(t, pool, SingletonBody + (index * BytesPerWord), o);
|
||||
set(t, codePool(t, methodCode(t, method)),
|
||||
SingletonBody + (index * BytesPerWord), o);
|
||||
}
|
||||
return o;
|
||||
}
|
||||
|
||||
inline object
|
||||
resolve(Thread* t, object pool, unsigned index,
|
||||
resolve(Thread* t, object method, unsigned index,
|
||||
object (*find)(vm::Thread*, object, object, object),
|
||||
object (*makeError)(vm::Thread*, object))
|
||||
{
|
||||
object o = singletonObject(t, pool, index);
|
||||
object o = singletonObject(t, codePool(t, methodCode(t, method)), index);
|
||||
if (objectClass(t, o) == arrayBody(t, t->m->types, Machine::ReferenceType))
|
||||
{
|
||||
PROTECT(t, pool);
|
||||
PROTECT(t, method);
|
||||
|
||||
object reference = o;
|
||||
PROTECT(t, reference);
|
||||
|
||||
object class_ = resolveClassInObject(t, o, ReferenceClass);
|
||||
object class_ = resolveClassInObject
|
||||
(t, classLoader(t, methodClass(t, method)), o, ReferenceClass);
|
||||
if (UNLIKELY(t->exception)) return 0;
|
||||
|
||||
o = findInHierarchy
|
||||
@ -87,22 +90,23 @@ resolve(Thread* t, object pool, unsigned index,
|
||||
find, makeError);
|
||||
if (UNLIKELY(t->exception)) return 0;
|
||||
|
||||
set(t, pool, SingletonBody + (index * BytesPerWord), o);
|
||||
set(t, codePool(t, methodCode(t, method)),
|
||||
SingletonBody + (index * BytesPerWord), o);
|
||||
}
|
||||
|
||||
return o;
|
||||
}
|
||||
|
||||
inline object
|
||||
resolveField(Thread* t, object pool, unsigned index)
|
||||
resolveField(Thread* t, object method, unsigned index)
|
||||
{
|
||||
return resolve(t, pool, index, findFieldInClass, makeNoSuchFieldError);
|
||||
return resolve(t, method, index, findFieldInClass, makeNoSuchFieldError);
|
||||
}
|
||||
|
||||
inline object
|
||||
resolveMethod(Thread* t, object pool, unsigned index)
|
||||
resolveMethod(Thread* t, object method, unsigned index)
|
||||
{
|
||||
return resolve(t, pool, index, findMethodInClass, makeNoSuchMethodError);
|
||||
return resolve(t, method, index, findMethodInClass, makeNoSuchMethodError);
|
||||
}
|
||||
|
||||
inline bool
|
||||
@ -162,7 +166,7 @@ populateMultiArray(Thread* t, object array, int32_t* counts,
|
||||
&byteArrayBody(t, spec, 1),
|
||||
byteArrayLength(t, spec) - 1);
|
||||
|
||||
object class_ = resolveClass(t, elementSpec);
|
||||
object class_ = resolveSystemClass(t, elementSpec);
|
||||
PROTECT(t, class_);
|
||||
|
||||
for (int32_t i = 0; i < counts[index]; ++i) {
|
||||
|
@ -101,8 +101,9 @@ class Processor {
|
||||
va_list arguments) = 0;
|
||||
|
||||
virtual object
|
||||
invokeList(Thread* t, const char* className, const char* methodName,
|
||||
const char* methodSpec, object this_, va_list arguments) = 0;
|
||||
invokeList(Thread* t, object loader, const char* className,
|
||||
const char* methodName, const char* methodSpec,
|
||||
object this_, va_list arguments) = 0;
|
||||
|
||||
virtual void
|
||||
dispose(Thread* t) = 0;
|
||||
@ -160,13 +161,14 @@ class Processor {
|
||||
}
|
||||
|
||||
object
|
||||
invoke(Thread* t, const char* className, const char* methodName,
|
||||
const char* methodSpec, object this_, ...)
|
||||
invoke(Thread* t, object loader, const char* className,
|
||||
const char* methodName, const char* methodSpec, object this_, ...)
|
||||
{
|
||||
va_list a;
|
||||
va_start(a, this_);
|
||||
|
||||
object r = invokeList(t, className, methodName, methodSpec, this_, a);
|
||||
object r = invokeList
|
||||
(t, loader, className, methodName, methodSpec, this_, a);
|
||||
|
||||
va_end(a);
|
||||
|
||||
|
@ -6,7 +6,8 @@
|
||||
(type singleton
|
||||
(array uintptr_t body))
|
||||
|
||||
(type classLoader java/lang/ClassLoader)
|
||||
(type classLoader java/lang/ClassLoader
|
||||
(object map))
|
||||
|
||||
(type systemClassLoader avian/SystemClassLoader)
|
||||
|
||||
@ -128,6 +129,8 @@
|
||||
|
||||
(type thread java/lang/Thread)
|
||||
|
||||
(type threadGroup java/lang/ThreadGroup)
|
||||
|
||||
(type stackTraceElement java/lang/StackTraceElement)
|
||||
|
||||
(type throwable java/lang/Throwable)
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user