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

This commit is contained in:
jet 2009-08-18 15:17:34 -06:00
commit 1528a9dddf
28 changed files with 744 additions and 236 deletions

View File

@ -26,7 +26,7 @@ public abstract class Writer {
public void write(String s, int offset, int length) throws IOException {
char[] b = new char[length];
s.getChars(offset, length, b, 0);
s.getChars(offset, offset + length, b, 0);
write(b);
}

View File

@ -32,10 +32,10 @@ public final class Class <T> implements Type, GenericDeclaration {
private static final int PrimitiveFlag = 1 << 5;
private short flags;
private byte vmFlags;
private byte arrayDimensions;
private short vmFlags;
private short fixedSize;
private short arrayElementSize;
private byte arrayElementSize;
private byte arrayDimensions;
private int[] objectMask;
private byte[] name;
private Class super_;
@ -96,6 +96,32 @@ public final class Class <T> implements Type, GenericDeclaration {
(replace('/', '.', name, 0, name.length - 1), 0, name.length - 1, false);
}
public String getCanonicalName() {
if ((vmFlags & PrimitiveFlag) != 0) {
return getName();
} else if (isArray()) {
return getComponentType().getCanonicalName() + "[]";
} else {
return getName().replace('$', '.');
}
}
public String getSimpleName() {
if ((vmFlags & PrimitiveFlag) != 0) {
return getName();
} else if (isArray()) {
return getComponentType().getSimpleName() + "[]";
} else {
String name = getCanonicalName();
int index = name.lastIndexOf('.');
if (index >= 0) {
return name.substring(index + 1);
} else {
return name;
}
}
}
public Object staticTable() {
return staticTable;
}
@ -125,6 +151,7 @@ public final class Class <T> implements Type, GenericDeclaration {
loader = Class.class.loader;
}
Class c = loader.loadClass(name);
c.link(loader);
if (initialize) {
c.initialize();
}
@ -133,6 +160,8 @@ public final class Class <T> implements Type, GenericDeclaration {
private static native Class primitiveClass(char name);
private native void link(ClassLoader loader);
private native void initialize();
public static Class forCanonicalName(String name) {
@ -159,6 +188,26 @@ public final class Class <T> implements Type, GenericDeclaration {
public Class getComponentType() {
if (isArray()) {
String n = getName();
if ("[Z".equals(n)) {
return primitiveClass('Z');
} else if ("[B".equals(n)) {
return primitiveClass('B');
} else if ("[S".equals(n)) {
return primitiveClass('S');
} else if ("[C".equals(n)) {
return primitiveClass('C');
} else if ("[I".equals(n)) {
return primitiveClass('I');
} else if ("[F".equals(n)) {
return primitiveClass('F');
} else if ("[J".equals(n)) {
return primitiveClass('J');
} else if ("[D".equals(n)) {
return primitiveClass('D');
}
if (staticTable == null) throw new AssertionError(name);
return (Class) staticTable;
} else {
return null;
@ -169,6 +218,8 @@ public final class Class <T> implements Type, GenericDeclaration {
private Field findField(String name) {
if (fieldTable != null) {
link(loader);
for (int i = 0; i < fieldTable.length; ++i) {
if (fieldTable[i].getName().equals(name)) {
return fieldTable[i];
@ -212,8 +263,12 @@ public final class Class <T> implements Type, GenericDeclaration {
private Method findMethod(String name, Class[] parameterTypes) {
if (methodTable != null) {
if (parameterTypes == null)
link(loader);
if (parameterTypes == null) {
parameterTypes = new Class[0];
}
for (int i = 0; i < methodTable.length; ++i) {
if (methodTable[i].getName().equals(name)
&& match(parameterTypes, methodTable[i].getParameterTypes()))
@ -302,6 +357,8 @@ public final class Class <T> implements Type, GenericDeclaration {
public Constructor[] getDeclaredConstructors() {
Constructor[] array = new Constructor[countConstructors(false)];
if (methodTable != null) {
link(loader);
int index = 0;
for (int i = 0; i < methodTable.length; ++i) {
if (methodTable[i].getName().equals("<init>")) {
@ -316,6 +373,8 @@ public final class Class <T> implements Type, GenericDeclaration {
public Constructor[] getConstructors() {
Constructor[] array = new Constructor[countConstructors(true)];
if (methodTable != null) {
link(loader);
int index = 0;
for (int i = 0; i < methodTable.length; ++i) {
if (((methodTable[i].getModifiers() & Modifier.PUBLIC) != 0)
@ -354,6 +413,8 @@ public final class Class <T> implements Type, GenericDeclaration {
public Field[] getFields() {
Field[] array = new Field[countPublicFields()];
if (fieldTable != null) {
link(loader);
int ai = 0;
for (int i = 0; i < fieldTable.length; ++i) {
if (((fieldTable[i].getModifiers() & Modifier.PUBLIC)) != 0) {
@ -382,6 +443,8 @@ public final class Class <T> implements Type, GenericDeclaration {
public Method[] getDeclaredMethods() {
Method[] array = new Method[countMethods(false)];
if (methodTable != null) {
link(loader);
int ai = 0;
for (int i = 0; i < methodTable.length; ++i) {
if (! methodTable[i].getName().startsWith("<")) {
@ -396,6 +459,8 @@ public final class Class <T> implements Type, GenericDeclaration {
public Method[] getMethods() {
Method[] array = new Method[countMethods(true)];
if (methodTable != null) {
link(loader);
int index = 0;
for (int i = 0; i < methodTable.length; ++i) {
if (((methodTable[i].getModifiers() & Modifier.PUBLIC) != 0)
@ -411,6 +476,8 @@ public final class Class <T> implements Type, GenericDeclaration {
public Class[] getInterfaces() {
if (interfaceTable != null) {
link(loader);
Class[] array = new Class[interfaceTable.length / 2];
for (int i = 0; i < array.length; ++i) {
array[i] = (Class) interfaceTable[i * 2];
@ -450,7 +517,7 @@ public final class Class <T> implements Type, GenericDeclaration {
}
public boolean isArray() {
return this != Class.class && arrayElementSize != 0;
return arrayDimensions != 0;
}
public boolean isInstance(Object o) {
@ -485,6 +552,14 @@ public final class Class <T> implements Type, GenericDeclaration {
return false;
}
public <T> Class<? extends T> asSubclass(Class<T> c) {
if (! c.isAssignableFrom(this)) {
throw new ClassCastException();
}
return (Class<? extends T>) this;
}
public T cast(Object o) {
return (T) o;
}
@ -493,6 +568,21 @@ public final class Class <T> implements Type, GenericDeclaration {
return Static.signers.get(this);
}
public Package getPackage() {
if ((vmFlags & PrimitiveFlag) != 0 || isArray()) {
return null;
} else {
String name = getCanonicalName();
int index = name.lastIndexOf('.');
if (index >= 0) {
return new Package(name.substring(0, index),
null, null, null, null, null, null, null, null);
} else {
return null;
}
}
}
public Annotation[] getDeclaredAnnotations() {
throw new UnsupportedOperationException();
}
@ -505,10 +595,6 @@ public final class Class <T> implements Type, GenericDeclaration {
throw new UnsupportedOperationException();
}
public String getSimpleName() {
throw new UnsupportedOperationException();
}
public Method getEnclosingMethod() {
throw new UnsupportedOperationException();
}

View File

@ -83,9 +83,7 @@ public abstract class ClassLoader {
return c;
}
protected void resolveClass(Class c) {
// ignore
}
protected native void resolveClass(Class c);
private ClassLoader getParent() {
return parent;

View File

@ -26,20 +26,21 @@ public abstract class Enum<E extends Enum<E>> implements Comparable<E> {
}
public static <T extends Enum<T>> T valueOf(Class<T> enumType, String name) {
if (name != null) {
try {
Method method = enumType.getMethod("values");
Enum values[] = (Enum[])(method.invoke(null));
for (Enum value : values) {
if (name.equals(value.name)) {
return (T) value;
}
if (name == null) throw new NullPointerException();
try {
Method method = enumType.getMethod("values");
Enum values[] = (Enum[]) (method.invoke(null));
for (Enum value: values) {
if (name.equals(value.name)) {
return (T) value;
}
} catch (Exception ex) {
throw new RuntimeException(ex);
}
} catch (Exception ex) {
throw new RuntimeException(ex);
}
return null;
throw new IllegalArgumentException(name);
}
public int ordinal() {

View File

@ -0,0 +1,46 @@
/* Copyright (c) 2008, Avian Contributors
Permission to use, copy, modify, and/or distribute this software
for any purpose with or without fee is hereby granted, provided
that the above copyright notice and this permission notice appear
in all copies.
There is NO WARRANTY for this software. See license.txt for
details. */
package java.lang;
import java.net.URL;
public class Package {
private final String name;
private final String implementationTitle;
private final String implementationVendor;
private final String implementationVersion;
private final String specementationTitle;
private final String specementationVendor;
private final String specementationVersion;
private final URL sealed;
private final ClassLoader loader;
Package(String name,
String implementationTitle,
String implementationVendor,
String implementationVersion,
String specementationTitle,
String specementationVendor,
String specementationVersion,
URL sealed,
ClassLoader loader)
{
this.name = name;
this.implementationTitle = implementationTitle;
this.implementationVendor = implementationVendor;
this.implementationVersion = implementationVersion;
this.specementationTitle = specementationTitle;
this.specementationVendor = specementationVendor;
this.specementationVersion = specementationVersion;
this.sealed = sealed;
this.loader = loader;
}
}

View File

@ -13,6 +13,7 @@ package java.lang;
import java.io.UnsupportedEncodingException;
import java.util.regex.Pattern;
import java.util.Comparator;
import java.util.Formatter;
import java.util.Locale;
import java.io.ByteArrayOutputStream;
import java.io.Serializable;
@ -52,7 +53,9 @@ public final class String
throws UnsupportedEncodingException
{
this(bytes, offset, length);
if (! charsetName.equalsIgnoreCase("UTF-8")) {
if (! (charsetName.equalsIgnoreCase("UTF-8")
|| charsetName.equalsIgnoreCase("ISO-8859-1")))
{
throw new UnsupportedEncodingException(charsetName);
}
}
@ -76,10 +79,7 @@ public final class String
public String(byte[] data, String charset)
throws UnsupportedEncodingException
{
this(data);
if (! charset.equals("UTF-8")) {
throw new UnsupportedEncodingException(charset);
}
this(data, 0, data.length, charset);
}
public String(byte bytes[], int highByte, int offset, int length) {
@ -540,6 +540,10 @@ public final class String
public boolean matches(String regex) {
return Pattern.matches(regex, this);
}
public String replaceFirst(String regex, String replacement) {
return Pattern.compile(regex).matcher(this).replaceFirst(replacement);
}
public String replaceAll(String regex, String replacement) {
return Pattern.compile(regex).matcher(this).replaceAll(replacement);
@ -625,8 +629,8 @@ public final class String
return length == 0;
}
public boolean contains(String match) {
return indexOf(match) != -1;
public boolean contains(CharSequence match) {
return indexOf(match.toString()) != -1;
}
public int codePointAt(int offset) {
@ -649,6 +653,14 @@ public final class String
throw new UnsupportedOperationException();
}
public static String format(Locale locale, String format, Object ... args) {
return new Formatter(locale).format(format, args).toString();
}
public static String format(String format, Object ... args) {
return format(Locale.getDefault(), format, args);
}
// for GNU Classpath compatibility:
static char[] zeroBasedStringValue(String s) {
if (s.offset == 0) {

View File

@ -129,10 +129,10 @@ public class StringBuffer implements CharSequence {
sb.setCharAt(index, ch);
}
public synchronized void getChars(int srcOffset, int srcLength, char[] dst,
int dstOffset)
public synchronized void getChars(int srcStart, int srcEnd, char[] dst,
int dstStart)
{
sb.getChars(srcOffset, srcLength, dst, dstOffset);
sb.getChars(srcStart, srcEnd, dst, dstStart);
}
public synchronized String toString() {

View File

@ -248,6 +248,29 @@ public class StringBuilder implements CharSequence, Appendable {
return -1;
}
public int lastIndexOf(String s) {
return lastIndexOf(s, length - s.length());
}
public int lastIndexOf(String s, int lastIndex) {
int slength = s.length();
if (slength == 0) return lastIndex;
for (int i = Math.min(length - slength, lastIndex); i >= 0; --i) {
int j = 0;
for (; j < slength && i + j < length; ++j) {
if (charAt(i + j) != s.charAt(j)) {
break;
}
}
if (j == slength) {
return i;
}
}
return -1;
}
public int length() {
return length;
@ -283,9 +306,8 @@ public class StringBuilder implements CharSequence, Appendable {
}
}
public void getChars(int srcOffset, int srcLength, char[] dst, int dstOffset)
{
if (srcOffset < 0 || srcOffset + srcLength > length) {
public void getChars(int srcStart, int srcEnd, char[] dst, int dstStart) {
if (srcStart < 0 || srcEnd > length) {
throw new IndexOutOfBoundsException();
}
@ -297,17 +319,17 @@ public class StringBuilder implements CharSequence, Appendable {
int end = index;
index = start;
if (start < srcOffset) {
start = srcOffset;
if (start < srcStart) {
start = srcStart;
}
if (end > srcOffset + srcLength) {
end = srcOffset + srcLength;
if (end > srcEnd) {
end = srcEnd;
}
if (start < end) {
c.value.getChars(start - index, end - start,
dst, dstOffset + (start - srcOffset));
c.value.getChars(start - index, end - index,
dst, dstStart + (start - srcStart));
}
}
}
@ -328,10 +350,14 @@ public class StringBuilder implements CharSequence, Appendable {
}
}
public String substring(int start) {
return substring(start, length);
}
public String substring(int start, int end) {
int len = end-start;
char[] buf = new char[len];
getChars(start, len, buf,0 );
getChars(start, end, buf, 0);
return new String(buf, 0, len, false);
}

View File

@ -19,6 +19,10 @@ public class ThreadGroup implements Thread.UncaughtExceptionHandler {
this.name = name;
}
public ThreadGroup(String name) {
this(Thread.currentThread().getThreadGroup(), name);
}
public void uncaughtException(Thread t, Throwable e) {
if (parent != null) {
parent.uncaughtException(t, e);

View File

@ -55,6 +55,10 @@ public class Throwable implements Serializable {
return message;
}
public String getLocalizedMessage() {
return getMessage();
}
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append(getClass().getName());
@ -79,6 +83,10 @@ public class Throwable implements Serializable {
return resolveTrace();
}
public void setStackTrace(StackTraceElement[] trace) {
this.trace = trace;
}
public void printStackTrace(PrintStream out) {
StringBuilder sb = new StringBuilder();
printStackTrace(sb, System.getProperty("line.separator"));

View File

@ -0,0 +1,21 @@
/* Copyright (c) 2009, Avian Contributors
Permission to use, copy, modify, and/or distribute this software
for any purpose with or without fee is hereby granted, provided
that the above copyright notice and this permission notice appear
in all copies.
There is NO WARRANTY for this software. See license.txt for
details. */
package java.lang.ref;
public class SoftReference<T> extends Reference<T> {
public SoftReference(T target, ReferenceQueue<? super T> queue) {
super(target, queue);
}
public SoftReference(T target) {
this(target, null);
}
}

View File

@ -16,4 +16,8 @@ public abstract class AccessibleObject {
public abstract boolean isAccessible();
public abstract void setAccessible(boolean v);
public static void setAccessible(AccessibleObject[] array, boolean v) {
for (AccessibleObject o: array) o.setAccessible(v);
}
}

View File

@ -0,0 +1,23 @@
/* Copyright (c) 2009, Avian Contributors
Permission to use, copy, modify, and/or distribute this software
for any purpose with or without fee is hereby granted, provided
that the above copyright notice and this permission notice appear
in all copies.
There is NO WARRANTY for this software. See license.txt for
details. */
package java.util;
public class Formatter {
private final Locale locale;
public Formatter(Locale locale) {
this.locale = locale;
}
public Formatter format(String format, Object ... args) {
throw new UnsupportedOperationException();
}
}

View File

@ -393,6 +393,7 @@ gnu-overrides = \
java/lang/ref/PhantomReference.class \
java/lang/ref/Reference.class \
java/lang/ref/ReferenceQueue.class \
java/lang/ref/SoftReference.class \
java/lang/ref/WeakReference.class \
java/lang/reflect/AccessibleObject.class \
java/lang/reflect/Constructor.class \

View File

@ -199,6 +199,16 @@ Avian_java_lang_ClassLoader_defineClass
return reinterpret_cast<int64_t>(c);
}
extern "C" JNIEXPORT void JNICALL
Avian_java_lang_ClassLoader_resolveClass
(Thread* t, object, uintptr_t* arguments)
{
object loader = reinterpret_cast<object>(arguments[0]);
object class_ = reinterpret_cast<object>(arguments[1]);
linkClass(t, loader, class_);
}
extern "C" JNIEXPORT int64_t JNICALL
Avian_avian_SystemClassLoader_findLoadedClass
(Thread* t, object, uintptr_t* arguments)
@ -291,6 +301,16 @@ Avian_java_lang_Class_initialize
initClass(t, this_);
}
extern "C" JNIEXPORT void JNICALL
Avian_java_lang_Class_link
(Thread* t, object, uintptr_t* arguments)
{
object this_ = reinterpret_cast<object>(arguments[0]);
object loader = reinterpret_cast<object>(arguments[1]);
linkClass(t, loader, this_);
}
extern "C" JNIEXPORT int64_t JNICALL
Avian_java_lang_Class_isAssignableFrom
(Thread* t, object, uintptr_t* arguments)

View File

@ -138,6 +138,19 @@ resolveThisPointer(MyThread* t, void* stack)
[t->arch->frameFooterSize() + t->arch->frameReturnAddressSize()];
}
object
findMethod(Thread* t, object method, object instance)
{
if ((methodFlags(t, method) & ACC_STATIC) == 0) {
if (methodVirtual(t, method)) {
return findVirtualMethod(t, method, objectClass(t, instance));
} else if (classFlags(t, methodClass(t, method)) & ACC_INTERFACE) {
return findInterfaceMethod(t, method, objectClass(t, instance));
}
}
return method;
}
object
resolveTarget(MyThread* t, void* stack, object method)
{
@ -154,7 +167,7 @@ resolveTarget(MyThread* t, void* stack, object method)
if (classFlags(t, methodClass(t, method)) & ACC_INTERFACE) {
return findInterfaceMethod(t, method, class_);
} else {
return findMethod(t, method, class_);
return findVirtualMethod(t, method, class_);
}
}
@ -2498,7 +2511,7 @@ bool
needsReturnBarrier(MyThread* t, object method)
{
return (methodFlags(t, method) & ConstructorFlag)
and (classFlags(t, methodClass(t, method)) & HasFinalMemberFlag);
and (classVmFlags(t, methodClass(t, method)) & HasFinalMemberFlag);
}
bool
@ -3513,7 +3526,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip,
object class_ = methodClass(t, context->method);
if (isSpecialMethod(t, target, class_)) {
target = findMethod(t, target, classSuper(t, class_));
target = findVirtualMethod(t, target, classSuper(t, class_));
}
assert(t, (methodFlags(t, target) & ACC_STATIC) == 0);
@ -3733,7 +3746,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip,
if (singletonIsObject(t, pool, index - 1)) {
object v = singletonObject(t, pool, index - 1);
if (objectClass(t, v)
== arrayBody(t, t->m->types, Machine::ByteArrayType))
== arrayBody(t, t->m->types, Machine::ReferenceType))
{
object class_ = resolveClassInPool(t, context->method, index - 1);
if (UNLIKELY(t->exception)) return;
@ -6333,6 +6346,8 @@ class SegFaultHandler: public System::SignalHandler {
t->exception = makeNullPointerException(t);
t->tracing = false;
// printTrace(t, t->exception);
findUnwindTarget(t, ip, base, stack);
t->ip = oldIp;
@ -6429,10 +6444,10 @@ class MyProcessor: public Processor {
virtual object
makeClass(vm::Thread* t,
uint16_t flags,
uint8_t vmFlags,
uint8_t arrayDimensions,
uint16_t vmFlags,
uint16_t fixedSize,
uint16_t arrayElementSize,
uint8_t arrayElementSize,
uint8_t arrayDimensions,
object objectMask,
object name,
object super,
@ -6445,7 +6460,7 @@ class MyProcessor: public Processor {
unsigned vtableLength)
{
return vm::makeClass
(t, flags, vmFlags, arrayDimensions, fixedSize, arrayElementSize,
(t, flags, vmFlags, fixedSize, arrayElementSize, arrayDimensions,
objectMask, name, super, interfaceTable, virtualTable, fieldTable,
methodTable, staticTable, loader, vtableLength);
}
@ -6543,6 +6558,8 @@ class MyProcessor: public Processor {
assert(t, ((methodFlags(t, method) & ACC_STATIC) == 0) xor (this_ == 0));
method = findMethod(t, method, this_);
const char* spec = reinterpret_cast<char*>
(&byteArrayBody(t, methodSpec(t, method), 0));
@ -6574,6 +6591,8 @@ class MyProcessor: public Processor {
assert(t, ((methodFlags(t, method) & ACC_STATIC) == 0) xor (this_ == 0));
method = findMethod(t, method, this_);
const char* spec = reinterpret_cast<char*>
(&byteArrayBody(t, methodSpec(t, method), 0));

View File

@ -183,20 +183,17 @@ Avian_gnu_classpath_VMSystemProperties_preInit
#endif
#ifdef __i386__
setProperty(t, method, properties, "gnu.cpu.endian", "little");
setProperty(t, method, properties, "os.arch", "x86");
#elif defined __x86_64__
setProperty(t, method, properties, "gnu.cpu.endian", "little");
setProperty(t, method, properties, "os.arch", "x86_64");
#elif defined(__ppc__) || defined(__powerpc__) \
|| defined(__ppc64__) || defined(__powerpc64__)
setProperty(t, method, properties, "gnu.cpu.endian", "big");
setProperty(t, method, properties, "os.arch", "ppc");
#elif defined __ia64__
setProperty(t, method, properties, "os.arch", "ia64");
#elif defined __arm__
setProperty(t, method, properties, "os.arch", "arm");
#elif defined __alpha__
setProperty(t, method, properties, "os.arch", "alpha");
#elif defined __sparc64__
setProperty(t, method, properties, "os.arch", "sparc64");
#else
setProperty(t, method, properties, "os.arch", "unknown");
#endif
@ -461,3 +458,43 @@ Avian_java_lang_VMClassLoader_findLoadedClass
return 0;
}
}
extern "C" JNIEXPORT int64_t JNICALL
Avian_sun_misc_Unsafe_compareAndSwapInt
(Thread*, object, uintptr_t* arguments)
{
object target = reinterpret_cast<object>(arguments[1]);
int64_t offset; memcpy(&offset, arguments + 2, 8);
int32_t expect = arguments[4];
int32_t update = arguments[5];
return __sync_bool_compare_and_swap
(&cast<int32_t>(target, offset), expect, update);
}
extern "C" JNIEXPORT int64_t JNICALL
Avian_sun_misc_Unsafe_compareAndSwapLong
(Thread*, object, uintptr_t* arguments)
{
object target = reinterpret_cast<object>(arguments[1]);
int64_t offset; memcpy(&offset, arguments + 2, 8);
int64_t expect; memcpy(&expect, arguments + 4, 8);
int64_t update; memcpy(&update, arguments + 6, 8);
return __sync_bool_compare_and_swap
(&cast<int64_t>(target, offset), expect, update);
}
extern "C" JNIEXPORT int64_t JNICALL
Avian_sun_misc_Unsafe_objectFieldOffset
(Thread* t, object, uintptr_t* arguments)
{
return fieldOffset(t, reinterpret_cast<object>(arguments[1]));
}
extern "C" JNIEXPORT int64_t JNICALL
Avian_java_util_concurrent_atomic_AtomicLong_VMSupportsCS8
(Thread*, object, uintptr_t*)
{
return 0;
}

View File

@ -844,8 +844,7 @@ findExceptionHandler(Thread* t, object method, unsigned ip)
PROTECT(t, eht);
catchType = resolveClassInPool
(t, codePool(t, methodCode(t, method)),
exceptionHandlerCatchType(eh) - 1);
(t, method, exceptionHandlerCatchType(eh) - 1);
if (catchType) {
eh = exceptionHandlerTableBody(t, eht, i);
@ -1025,10 +1024,12 @@ interpret(Thread* t)
if (LIKELY(count >= 0)) {
uint16_t index = codeReadInt16(t, code, ip);
object class_ = resolveClassInPool(t, codePool(t, code), index - 1);
object class_ = resolveClassInPool(t, frameMethod(t, frame), index - 1);
if (UNLIKELY(exception)) goto throw_;
pushObject(t, makeObjectArray(t, class_, count));
pushObject(t, makeObjectArray
(t, classLoader(t, methodClass(t, frameMethod(t, frame))),
class_, count));
} else {
object message = makeString(t, "%d", count);
exception = makeNegativeArraySizeException(t, message);
@ -1211,7 +1212,7 @@ interpret(Thread* t)
uint16_t index = codeReadInt16(t, code, ip);
if (peekObject(t, sp - 1)) {
object class_ = resolveClassInPool(t, codePool(t, code), index - 1);
object class_ = resolveClassInPool(t, frameMethod(t, frame), index - 1);
if (UNLIKELY(exception)) goto throw_;
if (not instanceOf(t, class_, peekObject(t, sp - 1))) {
@ -1568,7 +1569,7 @@ interpret(Thread* t)
if (LIKELY(peekObject(t, sp - 1))) {
uint16_t index = codeReadInt16(t, code, ip);
object field = resolveField(t, codePool(t, code), index - 1);
object field = resolveField(t, frameMethod(t, frame), index - 1);
if (UNLIKELY(exception)) goto throw_;
assert(t, (fieldFlags(t, field) & ACC_STATIC) == 0);
@ -1602,7 +1603,7 @@ interpret(Thread* t)
case getstatic: {
uint16_t index = codeReadInt16(t, code, ip);
object field = resolveField(t, codePool(t, code), index - 1);
object field = resolveField(t, frameMethod(t, frame), index - 1);
if (UNLIKELY(exception)) goto throw_;
assert(t, fieldFlags(t, field) & ACC_STATIC);
@ -1958,7 +1959,7 @@ interpret(Thread* t)
uint16_t index = codeReadInt16(t, code, ip);
if (peekObject(t, sp - 1)) {
object class_ = resolveClassInPool(t, codePool(t, code), index - 1);
object class_ = resolveClassInPool(t, frameMethod(t, frame), index - 1);
if (UNLIKELY(exception)) goto throw_;
if (instanceOf(t, class_, popObject(t))) {
@ -1977,7 +1978,7 @@ interpret(Thread* t)
ip += 2;
object method = resolveMethod(t, codePool(t, code), index - 1);
object method = resolveMethod(t, frameMethod(t, frame), index - 1);
if (UNLIKELY(exception)) goto throw_;
unsigned parameterFootprint = methodParameterFootprint(t, method);
@ -1994,7 +1995,7 @@ interpret(Thread* t)
case invokespecial: {
uint16_t index = codeReadInt16(t, code, ip);
object method = resolveMethod(t, codePool(t, code), index - 1);
object method = resolveMethod(t, frameMethod(t, frame), index - 1);
if (UNLIKELY(exception)) goto throw_;
unsigned parameterFootprint = methodParameterFootprint(t, method);
@ -2004,7 +2005,7 @@ interpret(Thread* t)
class_ = classSuper(t, class_);
if (UNLIKELY(classInit(t, class_, 3))) goto invoke;
code = findMethod(t, method, class_);
code = findVirtualMethod(t, method, class_);
} else {
code = method;
}
@ -2019,7 +2020,7 @@ interpret(Thread* t)
case invokestatic: {
uint16_t index = codeReadInt16(t, code, ip);
object method = resolveMethod(t, codePool(t, code), index - 1);
object method = resolveMethod(t, frameMethod(t, frame), index - 1);
if (UNLIKELY(exception)) goto throw_;
PROTECT(t, method);
@ -2031,7 +2032,7 @@ interpret(Thread* t)
case invokevirtual: {
uint16_t index = codeReadInt16(t, code, ip);
object method = resolveMethod(t, codePool(t, code), index - 1);
object method = resolveMethod(t, frameMethod(t, frame), index - 1);
if (UNLIKELY(exception)) goto throw_;
unsigned parameterFootprint = methodParameterFootprint(t, method);
@ -2039,7 +2040,7 @@ interpret(Thread* t)
object class_ = objectClass(t, peekObject(t, sp - parameterFootprint));
if (UNLIKELY(classInit(t, class_, 3))) goto invoke;
code = findMethod(t, method, class_);
code = findVirtualMethod(t, method, class_);
goto invoke;
} else {
exception = makeNullPointerException(t);
@ -2246,9 +2247,10 @@ interpret(Thread* t)
if (singletonIsObject(t, pool, index - 1)) {
object v = singletonObject(t, pool, index - 1);
if (objectClass(t, v)
== arrayBody(t, t->m->types, Machine::ByteArrayType))
== arrayBody(t, t->m->types, Machine::ReferenceType))
{
object class_ = resolveClassInPool(t, pool, index - 1);
object class_ = resolveClassInPool
(t, frameMethod(t, frame), index - 1);
if (UNLIKELY(exception)) goto throw_;
pushObject(t, class_);
@ -2455,7 +2457,7 @@ interpret(Thread* t)
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, frameMethod(t, frame), index - 1);
if (UNLIKELY(exception)) goto throw_;
PROTECT(t, class_);
@ -2481,7 +2483,7 @@ interpret(Thread* t)
case new_: {
uint16_t index = codeReadInt16(t, code, ip);
object class_ = resolveClassInPool(t, codePool(t, code), index - 1);
object class_ = resolveClassInPool(t, frameMethod(t, frame), index - 1);
if (UNLIKELY(exception)) goto throw_;
PROTECT(t, class_);
@ -2555,7 +2557,7 @@ interpret(Thread* t)
case putfield: {
uint16_t index = codeReadInt16(t, code, ip);
object field = resolveField(t, codePool(t, code), index - 1);
object field = resolveField(t, frameMethod(t, frame), index - 1);
if (UNLIKELY(exception)) goto throw_;
if (UNLIKELY(fieldFlags(t, field) & ACC_VOLATILE)) {
@ -2645,7 +2647,7 @@ interpret(Thread* t)
case putstatic: {
uint16_t index = codeReadInt16(t, code, ip);
object field = resolveField(t, codePool(t, code), index - 1);
object field = resolveField(t, frameMethod(t, frame), index - 1);
if (UNLIKELY(exception)) goto throw_;
if (UNLIKELY(fieldFlags(t, field) & ACC_VOLATILE)) {
@ -2724,7 +2726,7 @@ interpret(Thread* t)
case return_: {
object method = frameMethod(t, frame);
if ((methodFlags(t, method) & ConstructorFlag)
and (classFlags(t, methodClass(t, method)) & HasFinalMemberFlag))
and (classVmFlags(t, methodClass(t, method)) & HasFinalMemberFlag))
{
storeStoreMemoryBarrier();
}
@ -2825,13 +2827,14 @@ interpret(Thread* t)
ip -= 2;
uint16_t index = codeReadInt16(t, code, ip);
object method = resolveMethod(t, codePool(t, code), index - 1);
object method = resolveMethod(t, frameMethod(t, frame), index - 1);
unsigned parameterFootprint = methodParameterFootprint(t, method);
object class_ = objectClass(t, peekObject(t, sp - parameterFootprint));
assert(t, classVmFlags(t, class_) & BootstrapFlag);
resolveClass(t, className(t, class_));
resolveClass(t, classLoader(t, methodClass(t, frameMethod(t, frame))),
className(t, class_));
if (UNLIKELY(exception)) goto throw_;
ip -= 3;
@ -2999,13 +3002,13 @@ invoke(Thread* t, object method)
class_ = objectClass(t, peekObject(t, t->sp - parameterFootprint));
if (classVmFlags(t, class_) & BootstrapFlag) {
resolveClass(t, className(t, class_));
resolveClass(t, t->m->loader, className(t, class_));
}
if (classFlags(t, methodClass(t, method)) & ACC_INTERFACE) {
method = findInterfaceMethod(t, method, class_);
} else {
method = findMethod(t, method, class_);
method = findVirtualMethod(t, method, class_);
}
} else {
class_ = methodClass(t, method);
@ -3100,10 +3103,10 @@ class MyProcessor: public Processor {
virtual object
makeClass(vm::Thread* t,
uint16_t flags,
uint8_t vmFlags,
uint8_t arrayDimensions,
uint16_t vmFlags,
uint16_t fixedSize,
uint16_t arrayElementSize,
uint8_t arrayElementSize,
uint8_t arrayDimensions,
object objectMask,
object name,
object super,
@ -3116,7 +3119,7 @@ class MyProcessor: public Processor {
unsigned vtableLength UNUSED)
{
return vm::makeClass
(t, flags, vmFlags, arrayDimensions, fixedSize, arrayElementSize,
(t, flags, vmFlags, fixedSize, arrayElementSize, arrayDimensions,
objectMask, name, super, interfaceTable, virtualTable, fieldTable,
methodTable, staticTable, loader, 0);
}
@ -3230,8 +3233,9 @@ class MyProcessor: public Processor {
}
virtual object
invokeList(vm::Thread* vmt, const char* className, const char* methodName,
const char* methodSpec, object this_, va_list arguments)
invokeList(vm::Thread* vmt, object loader, const char* className,
const char* methodName, const char* methodSpec, object this_,
va_list arguments)
{
Thread* t = static_cast<Thread*>(vmt);
@ -3247,7 +3251,9 @@ class MyProcessor: public Processor {
pushArguments(t, 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));

View File

@ -77,6 +77,7 @@ DetachCurrentThread(Machine* m)
{
Thread* t = static_cast<Thread*>(m->localThread->get());
if (t) {
m->localThread->set(0);
t->exit();
return 0;
} else {
@ -2003,6 +2004,7 @@ populateJNITables(JavaVMVTable* vmTable, JNIEnvVTable* envTable)
envTable->SetStaticFloatField = ::SetStaticFloatField;
envTable->SetStaticDoubleField = ::SetStaticDoubleField;
envTable->NewGlobalRef = ::NewGlobalRef;
envTable->NewWeakGlobalRef = ::NewGlobalRef;
envTable->DeleteGlobalRef = ::DeleteGlobalRef;
envTable->ExceptionOccurred = ::ExceptionOccurred;
envTable->ExceptionDescribe = ::ExceptionDescribe;

View File

@ -19,6 +19,8 @@ using namespace vm;
namespace {
const unsigned NoByte = 0xFFFF;
bool
find(Thread* t, Thread* o)
{
@ -540,9 +542,65 @@ makeByteArray(Thread* t, const char* format, va_list a)
return s;
}
unsigned
resolveSpec(Thread* t, object loader, object spec, unsigned offset)
{
int8_t* s = &byteArrayBody(t, spec, offset);
unsigned result;
switch (*s) {
case 'L':
++ offset;
while (*s and *s != ';') ++ s;
result = s + 1 - &byteArrayBody(t, spec, 0);
break;
case '[':
while (*s == '[') ++ s;
switch (*s) {
case 'L':
while (*s and *s != ';') ++ s;
++ s;
break;
default:
++ s;
break;
}
result = s - &byteArrayBody(t, spec, 0);
break;
default:
return offset + 1;
}
PROTECT(t, spec);
unsigned length = s - &byteArrayBody(t, spec, offset);
object name = makeByteArray(t, length + 1);
memcpy(&byteArrayBody(t, name, 0),
&byteArrayBody(t, spec, offset),
length);
resolveClass(t, loader, name);
return result;
}
unsigned
readByte(Stream& s, unsigned* value)
{
if (*value == NoByte) {
return s.read1();
} else {
unsigned r = *value;
*value = NoByte;
return r;
}
}
object
parseUtf8NonAscii(Thread* t, Stream& s, object bytesSoFar, unsigned byteCount,
unsigned sourceIndex, unsigned lastByteRead)
unsigned sourceIndex, unsigned byteA, unsigned byteB)
{
PROTECT(t, bytesSoFar);
@ -554,15 +612,14 @@ parseUtf8NonAscii(Thread* t, Stream& s, object bytesSoFar, unsigned byteCount,
charArrayBody(t, value, vi) = byteArrayBody(t, bytesSoFar, vi);
}
unsigned a = lastByteRead;
unsigned si = sourceIndex;
while (true) {
for (unsigned si = sourceIndex; si < length; ++si) {
unsigned a = readByte(s, &byteA);
if (a & 0x80) {
if (a & 0x20) {
// 3 bytes
si += 2;
assert(t, si < length);
unsigned b = s.read1();
unsigned b = readByte(s, &byteB);
unsigned c = s.read1();
charArrayBody(t, value, vi++)
= ((a & 0xf) << 12) | ((b & 0x3f) << 6) | (c & 0x3f);
@ -570,7 +627,7 @@ parseUtf8NonAscii(Thread* t, Stream& s, object bytesSoFar, unsigned byteCount,
// 2 bytes
++ si;
assert(t, si < length);
unsigned b = s.read1();
unsigned b = readByte(s, &byteB);
if (a == 0xC0 and b == 0x80) {
charArrayBody(t, value, vi++) = 0;
@ -580,12 +637,6 @@ parseUtf8NonAscii(Thread* t, Stream& s, object bytesSoFar, unsigned byteCount,
}
} else {
charArrayBody(t, value, vi++) = a;
}
if (++si < length) {
a = s.read1();
} else {
break;
}
}
@ -611,7 +662,7 @@ parseUtf8(Thread* t, Stream& s, unsigned length)
if (a & 0x80) {
if (a & 0x20) {
// 3 bytes
return parseUtf8NonAscii(t, s, value, vi, si, a);
return parseUtf8NonAscii(t, s, value, vi, si, a, NoByte);
} else {
// 2 bytes
unsigned b = s.read1();
@ -621,7 +672,7 @@ parseUtf8(Thread* t, Stream& s, unsigned length)
assert(t, si < length);
byteArrayBody(t, value, vi++) = 0;
} else {
return parseUtf8NonAscii(t, s, value, vi, si, a);
return parseUtf8NonAscii(t, s, value, vi, si, a, b);
}
}
} else {
@ -699,7 +750,7 @@ parsePoolEntry(Thread* t, Stream& s, uint32_t* index, object pool, unsigned i)
unsigned si = s.read2() - 1;
parsePoolEntry(t, s, index, pool, si);
object value = singletonObject(t, pool, si);
object value = makeReference(t, 0, singletonObject(t, pool, si), 0);
set(t, pool, SingletonBody + (i * BytesPerWord), value);
}
} return 1;
@ -742,7 +793,7 @@ parsePoolEntry(Thread* t, Stream& s, uint32_t* index, object pool, unsigned i)
parsePoolEntry(t, s, index, pool, ci);
parsePoolEntry(t, s, index, pool, nti);
object class_ = singletonObject(t, pool, ci);
object class_ = referenceName(t, singletonObject(t, pool, ci));
object nameAndType = singletonObject(t, pool, nti);
object value = makeReference
(t, class_, pairFirst(t, nameAndType), pairSecond(t, nameAndType));
@ -854,7 +905,7 @@ parseInterfaceTable(Thread* t, Stream& s, object class_, object pool)
unsigned count = s.read2();
for (unsigned i = 0; i < count; ++i) {
object name = singletonObject(t, pool, s.read2() - 1);
object name = referenceName(t, singletonObject(t, pool, s.read2() - 1));
PROTECT(t, name);
object interface = resolveClass(t, classLoader(t, class_), name);
@ -976,7 +1027,7 @@ parseFieldTable(Thread* t, Stream& s, object class_, object pool)
staticTypes[staticCount++] = code;
} else {
if (flags & ACC_FINAL) {
classFlags(t, class_) |= HasFinalMemberFlag;
classVmFlags(t, class_) |= HasFinalMemberFlag;
}
unsigned excess = (memberOffset % fieldSize(t, code)) % BytesPerWord;
@ -1326,7 +1377,8 @@ parseMethodTable(Thread* t, Stream& s, object class_, object pool)
hashMapInsert(t, virtualMap, method, method, methodHash);
}
if (UNLIKELY(strcmp
if (UNLIKELY((classFlags(t, class_) & ACC_INTERFACE) == 0
and strcmp
(reinterpret_cast<const int8_t*>("finalize"),
&byteArrayBody(t, methodName(t, method), 0)) == 0
and strcmp
@ -1557,9 +1609,9 @@ makeArrayClass(Thread* t, object loader, unsigned dimensions, object spec,
(t,
0,
0,
dimensions,
2 * BytesPerWord,
BytesPerWord,
dimensions,
classObjectMask(t, arrayBody(t, t->m->types, Machine::ArrayType)),
spec,
arrayBody(t, t->m->types, Machine::JobjectType),
@ -1696,7 +1748,7 @@ bootClass(Thread* t, Machine::Type type, int superType, uint32_t objectMask,
super = (superType >= 0 ? arrayBody(t, t->m->types, superType) : 0);
object class_ = t->m->processor->makeClass
(t, 0, BootstrapFlag, 0, fixedSize, arrayElementSize, mask, 0, super, 0, 0,
(t, 0, BootstrapFlag, fixedSize, arrayElementSize, 0, mask, 0, super, 0, 0,
0, 0, 0, t->m->loader, vtableLength);
set(t, t->m->types, ArrayBody + (type * BytesPerWord), class_);
@ -1765,16 +1817,18 @@ boot(Thread* t)
m->unsafe = false;
classFlags(t, arrayBody(t, m->types, Machine::SingletonType))
classVmFlags(t, arrayBody(t, m->types, Machine::SingletonType))
|= SingletonFlag;
classFlags(t, arrayBody(t, m->types, Machine::ContinuationType))
classVmFlags(t, arrayBody(t, m->types, Machine::ContinuationType))
|= ContinuationFlag;
classVmFlags(t, arrayBody(t, m->types, Machine::JreferenceType))
|= ReferenceFlag;
classVmFlags(t, arrayBody(t, m->types, Machine::WeakReferenceType))
|= ReferenceFlag | WeakReferenceFlag;
classVmFlags(t, arrayBody(t, m->types, Machine::SoftReferenceType))
|= ReferenceFlag | WeakReferenceFlag;
classVmFlags(t, arrayBody(t, m->types, Machine::PhantomReferenceType))
|= ReferenceFlag | WeakReferenceFlag;
@ -2064,8 +2118,6 @@ Thread::init()
m->localThread->set(this);
} else {
assert(this, javaThread);
peer = parent->child;
parent->child = this;
}
@ -2073,11 +2125,16 @@ Thread::init()
if (javaThread) {
threadPeer(this, javaThread) = reinterpret_cast<jlong>(this);
} else {
object group;
if (parent) {
group = threadGroup(this, parent->javaThread);
} else {
group = makeThreadGroup(this, 0, 0);
}
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, group);
@ -2428,16 +2485,18 @@ makeString(Thread* t, const char* format, ...)
void
stringChars(Thread* t, object string, char* chars)
{
object data = stringData(t, string);
if (objectClass(t, data)
== arrayBody(t, t->m->types, Machine::ByteArrayType))
{
memcpy(chars,
&byteArrayBody(t, data, stringOffset(t, string)),
stringLength(t, string));
} else {
for (unsigned i = 0; i < stringLength(t, string); ++i) {
chars[i] = charArrayBody(t, data, stringOffset(t, string) + i);
if (stringLength(t, string)) {
object data = stringData(t, string);
if (objectClass(t, data)
== arrayBody(t, t->m->types, Machine::ByteArrayType))
{
memcpy(chars,
&byteArrayBody(t, data, stringOffset(t, string)),
stringLength(t, string));
} else {
for (unsigned i = 0; i < stringLength(t, string); ++i) {
chars[i] = charArrayBody(t, data, stringOffset(t, string) + i);
}
}
}
chars[stringLength(t, string)] = 0;
@ -2446,17 +2505,19 @@ stringChars(Thread* t, object string, char* chars)
void
stringChars(Thread* t, object string, uint16_t* chars)
{
object data = stringData(t, string);
if (objectClass(t, data)
== arrayBody(t, t->m->types, Machine::ByteArrayType))
{
for (unsigned i = 0; i < stringLength(t, string); ++i) {
chars[i] = byteArrayBody(t, data, stringOffset(t, string) + i);
if (stringLength(t, string)) {
object data = stringData(t, string);
if (objectClass(t, data)
== arrayBody(t, t->m->types, Machine::ByteArrayType))
{
for (unsigned i = 0; i < stringLength(t, string); ++i) {
chars[i] = byteArrayBody(t, data, stringOffset(t, string) + i);
}
} else {
memcpy(chars,
&charArrayBody(t, data, stringOffset(t, string)),
stringLength(t, string) * sizeof(uint16_t));
}
} else {
memcpy(chars,
&charArrayBody(t, data, stringOffset(t, string)),
stringLength(t, string) * sizeof(uint16_t));
}
chars[stringLength(t, string)] = 0;
}
@ -2649,11 +2710,12 @@ parseClass(Thread* t, object loader, const uint8_t* data, unsigned size)
object class_ = makeClass(t,
flags,
0, // VM flags
0, // array dimensions
0, // fixed size
0, // array size
0, // array dimensions
0, // object mask
singletonObject(t, pool, name - 1),
referenceName
(t, singletonObject(t, pool, name - 1)),
0, // super
0, // interfaces
0, // vtable
@ -2666,7 +2728,8 @@ parseClass(Thread* t, object loader, const uint8_t* data, unsigned size)
unsigned super = s.read2();
if (super) {
object sc = resolveClass(t, loader, singletonObject(t, pool, super - 1));
object sc = resolveClass
(t, loader, referenceName(t, singletonObject(t, pool, super - 1)));
if (UNLIKELY(t->exception)) return 0;
set(t, class_, ClassSuper, sc);
@ -2692,9 +2755,9 @@ parseClass(Thread* t, object loader, const uint8_t* data, unsigned size)
(t,
classFlags(t, class_),
classVmFlags(t, class_),
classArrayDimensions(t, class_),
classFixedSize(t, class_),
classArrayElementSize(t, class_),
classArrayDimensions(t, class_),
classObjectMask(t, class_),
className(t, class_),
classSuper(t, class_),
@ -2821,7 +2884,7 @@ resolveClass(Thread* t, object loader, object spec)
}
if (LIKELY(t->exception == 0)) {
object method = findMethod
object method = findVirtualMethod
(t, t->m->loadClassMethod, objectClass(t, loader));
if (LIKELY(t->exception == 0)) {
@ -2853,6 +2916,95 @@ resolveClass(Thread* t, object loader, object spec)
}
}
void
linkClass(Thread* t, object loader, object class_)
{
PROTECT(t, loader);
PROTECT(t, class_);
ACQUIRE(t, t->m->classLock);
if ((classVmFlags(t, class_) & LinkFlag) == 0) {
if (classSuper(t, class_)) {
linkClass(t, loader, classSuper(t, class_));
}
if (classInterfaceTable(t, class_)) {
unsigned increment = 2;
if (classFlags(t, class_) & ACC_INTERFACE) {
increment = 1;
}
for (unsigned i = 0; i < arrayLength(t, classInterfaceTable(t, class_));
i += increment)
{
linkClass(t, loader, arrayBody(t, classInterfaceTable(t, class_), i));
}
}
if (classMethodTable(t, class_)) {
bool resolvedPool = false;
for (unsigned i = 0;
i < arrayLength(t, classMethodTable(t, class_)); ++i)
{
object method = arrayBody(t, classMethodTable(t, class_), i);
PROTECT(t, method);
object code = methodCode(t, method);
if ((not resolvedPool)
and code
and codePool(t, code)
and objectClass(t, codePool(t, code))
== arrayBody(t, t->m->types, Machine::SingletonType))
{
object pool = codePool(t, code);
PROTECT(t, pool);
unsigned count = singletonCount(t, pool);
for (unsigned j = 0; j < count; ++j) {
if (singletonIsObject(t, pool, j)) {
object entry = singletonObject(t, pool, j);
if (objectClass(t, entry)
== arrayBody(t, t->m->types, Machine::ReferenceType))
{
if (referenceSpec(t, entry) == 0) {
resolveClassInPool(t, loader, method, j);
} else if (byteArrayBody(t, referenceSpec(t, entry), 0) == '(')
{
resolveMethod(t, loader, method, j);
} else {
resolveField(t, loader, method, j);
}
if (UNLIKELY(t->exception)) return;
}
}
}
resolvedPool = true;
}
object spec = methodSpec(t, method);
PROTECT(t, spec);
for (unsigned j = 1; j < byteArrayLength(t, spec);) {
j = resolveSpec(t, loader, spec, j);
if (UNLIKELY(t->exception)) return;
}
}
}
if (classFieldTable(t, class_)) {
for (unsigned i = 0; i < arrayLength(t, classFieldTable(t, class_)); ++i)
{
resolveSpec(t, loader, fieldSpec
(t, arrayBody(t, classFieldTable(t, class_), i)), 0);
if (UNLIKELY(t->exception)) return;
}
}
classVmFlags(t, class_) |= LinkFlag;
}
}
object
resolveMethod(Thread* t, object class_, const char* methodName,
const char* methodSpec)
@ -3272,7 +3424,7 @@ walk(Thread* t, Heap::Walker* w, object o, unsigned start)
intArrayLength(t, objectMask) * 4);
more = ::walk(t, w, mask, fixedSize, arrayElementSize, arrayLength, start);
} else if (classFlags(t, class_) & SingletonFlag) {
} else if (classVmFlags(t, class_) & SingletonFlag) {
unsigned length = singletonLength(t, o);
if (length) {
more = ::walk(t, w, singletonMask(t, o),
@ -3284,7 +3436,7 @@ walk(Thread* t, Heap::Walker* w, object o, unsigned start)
more = w->visit(0);
}
if (more and classFlags(t, class_) & ContinuationFlag) {
if (more and classVmFlags(t, class_) & ContinuationFlag) {
t->m->processor->walkContinuationBody(t, w, o, start);
}
}

View File

@ -74,12 +74,6 @@ enum StackTag {
const int NativeLine = -1;
const int UnknownLine = -2;
// class flags (note that we must be careful not to overlap the
// standard ACC_* flags):
const unsigned HasFinalMemberFlag = 1 << 13;
const unsigned SingletonFlag = 1 << 14;
const unsigned ContinuationFlag = 1 << 15;
// class vmFlags:
const unsigned ReferenceFlag = 1 << 0;
const unsigned WeakReferenceFlag = 1 << 1;
@ -89,6 +83,10 @@ const unsigned InitErrorFlag = 1 << 4;
const unsigned PrimitiveFlag = 1 << 5;
const unsigned BootstrapFlag = 1 << 6;
const unsigned HasFinalizerFlag = 1 << 7;
const unsigned LinkFlag = 1 << 8;
const unsigned HasFinalMemberFlag = 1 << 9;
const unsigned SingletonFlag = 1 << 10;
const unsigned ContinuationFlag = 1 << 11;
// method vmFlags:
const unsigned ClassInitFlag = 1 << 0;
@ -1816,6 +1814,7 @@ makeNew(Thread* t, object class_)
PROTECT(t, class_);
unsigned sizeInBytes = pad(classFixedSize(t, class_));
assert(t, sizeInBytes);
object instance = allocate(t, sizeInBytes, classObjectMask(t, class_));
setObjectClass(t, instance, class_);
@ -2103,6 +2102,9 @@ resolveSystemClass(Thread* t, const char* name)
return resolveSystemClass(t, makeByteArray(t, "%s", name));
}
void
linkClass(Thread* t, object loader, object class_);
object
resolveMethod(Thread* t, object class_, const char* methodName,
const char* methodSpec);
@ -2185,7 +2187,7 @@ findMethod(Thread* t, object class_, object name, object spec)
}
inline object
findMethod(Thread* t, object method, object class_)
findVirtualMethod(Thread* t, object method, object class_)
{
return arrayBody(t, classVirtualTable(t, class_),
methodOffset(t, method));
@ -2444,6 +2446,101 @@ makeSingletonOfSize(Thread* t, unsigned count)
return o;
}
inline object
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, loader, o);
if (UNLIKELY(t->exception)) return 0;
set(t, container, classOffset, o);
}
return o;
}
inline object
resolveClassInPool(Thread* t, object loader, object method, unsigned index)
{
object o = singletonObject(t, codePool(t, methodCode(t, method)), index);
if (objectClass(t, o) == arrayBody(t, t->m->types, Machine::ReferenceType)) {
PROTECT(t, method);
o = resolveClass(t, loader, referenceName(t, o));
if (UNLIKELY(t->exception)) return 0;
set(t, codePool(t, methodCode(t, method)),
SingletonBody + (index * BytesPerWord), o);
}
return o;
}
inline object
resolveClassInPool(Thread* t, object method, unsigned index)
{
return resolveClassInPool(t, classLoader(t, methodClass(t, method)),
method, index);
}
inline object
resolve(Thread* t, object loader, object method, unsigned index,
object (*find)(vm::Thread*, object, object, object),
object (*makeError)(vm::Thread*, object))
{
object o = singletonObject(t, codePool(t, methodCode(t, method)), index);
if (objectClass(t, o) == arrayBody(t, t->m->types, Machine::ReferenceType))
{
PROTECT(t, method);
object reference = o;
PROTECT(t, reference);
object class_ = resolveClassInObject(t, loader, o, ReferenceClass);
if (UNLIKELY(t->exception)) return 0;
o = findInHierarchy
(t, class_, referenceName(t, reference), referenceSpec(t, reference),
find, makeError);
if (UNLIKELY(t->exception)) return 0;
set(t, codePool(t, methodCode(t, method)),
SingletonBody + (index * BytesPerWord), o);
}
return o;
}
inline object
resolveField(Thread* t, object loader, object method, unsigned index)
{
return resolve(t, loader, method, index, findFieldInClass,
makeNoSuchFieldError);
}
inline object
resolveField(Thread* t, object method, unsigned index)
{
return resolveField
(t, classLoader(t, methodClass(t, method)), method, index);
}
inline object
resolveMethod(Thread* t, object loader, object method, unsigned index)
{
return resolve(t, loader, method, index, findMethodInClass,
makeNoSuchMethodError);
}
inline object
resolveMethod(Thread* t, object method, unsigned index)
{
return resolveMethod
(t, classLoader(t, methodClass(t, method)), method, index);
}
void
dumpHeap(Thread* t, FILE* out);

View File

@ -129,7 +129,7 @@ class MySystem: public System {
virtual void join() {
int rv UNUSED = pthread_join(thread, 0);
expect(s, rv == 0);
//expect(s, rv == 0);
}
virtual void dispose() {

View File

@ -36,79 +36,6 @@ codeReadInt32(Thread* t, object code, unsigned& ip)
return ((v1 << 24) | (v2 << 16) | (v3 << 8) | v4);
}
inline object
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, loader, o);
if (UNLIKELY(t->exception)) return 0;
set(t, container, classOffset, o);
}
return o;
}
inline object
resolveClassInPool(Thread* t, object method, unsigned index)
{
object o = singletonObject(t, codePool(t, methodCode(t, method)), index);
if (objectClass(t, o) == arrayBody(t, t->m->types, Machine::ByteArrayType)) {
PROTECT(t, method);
o = resolveClass(t, classLoader(t, methodClass(t, method)), o);
if (UNLIKELY(t->exception)) return 0;
set(t, codePool(t, methodCode(t, method)),
SingletonBody + (index * BytesPerWord), o);
}
return o;
}
inline object
resolve(Thread* t, object method, unsigned index,
object (*find)(vm::Thread*, object, object, object),
object (*makeError)(vm::Thread*, object))
{
object o = singletonObject(t, codePool(t, methodCode(t, method)), index);
if (objectClass(t, o) == arrayBody(t, t->m->types, Machine::ReferenceType))
{
PROTECT(t, method);
object reference = o;
PROTECT(t, reference);
object class_ = resolveClassInObject
(t, classLoader(t, methodClass(t, method)), o, ReferenceClass);
if (UNLIKELY(t->exception)) return 0;
o = findInHierarchy
(t, class_, referenceName(t, reference), referenceSpec(t, reference),
find, makeError);
if (UNLIKELY(t->exception)) return 0;
set(t, codePool(t, methodCode(t, method)),
SingletonBody + (index * BytesPerWord), o);
}
return o;
}
inline object
resolveField(Thread* t, object method, unsigned index)
{
return resolve(t, method, index, findFieldInClass, makeNoSuchFieldError);
}
inline object
resolveMethod(Thread* t, object method, unsigned index)
{
return resolve(t, method, index, findMethodInClass, makeNoSuchMethodError);
}
inline bool
isSuperclass(Thread* t, object class_, object base)
{

View File

@ -60,10 +60,10 @@ class Processor {
virtual object
makeClass(Thread* t,
uint16_t flags,
uint8_t vmFlags,
uint8_t arrayDimensions,
uint16_t vmFlags,
uint16_t fixedSize,
uint16_t arrayElementSize,
uint8_t arrayElementSize,
uint8_t arrayDimensions,
object objectMask,
object name,
object super,

View File

@ -210,6 +210,8 @@
(type weakReference java/lang/ref/WeakReference)
(type softReference java/lang/ref/SoftReference)
(type phantomReference java/lang/ref/PhantomReference)
(type byteArray [B

View File

@ -873,10 +873,10 @@ handleException(LPEXCEPTION_POINTERS e)
if (jump) {
return EXCEPTION_CONTINUE_EXECUTION;
}
}
if (system->crashDumpDirectory) {
dump(e, system->crashDumpDirectory);
if (system->crashDumpDirectory) {
dump(e, system->crashDumpDirectory);
}
}
return EXCEPTION_CONTINUE_SEARCH;

View File

@ -91,11 +91,6 @@ public class Misc {
}
public static void main(String[] args) {
expect(new String(new byte[] { 99, 111, 109, 46, 101, 99, 111, 118, 97,
116, 101, 46, 110, 97, 116, 46, 98, 117,
115, 46, 83, 121, 109, 98, 111, 108 })
.equals("com.ecovate.nat.bus.Symbol"));
expect(queryDefault(new Object()) != null);
{ Foo foo = new Foo();

21
test/Strings.java Normal file
View File

@ -0,0 +1,21 @@
public class Strings {
private static void expect(boolean v) {
if (! v) throw new RuntimeException();
}
public static void main(String[] args) {
expect(new String(new byte[] { 99, 111, 109, 46, 101, 99, 111, 118, 97,
116, 101, 46, 110, 97, 116, 46, 98, 117,
115, 46, 83, 121, 109, 98, 111, 108 })
.equals("com.ecovate.nat.bus.Symbol"));
// We don't yet have a regex implementation, so this test will fail:
// final String months = "Jan\u00aeFeb\u00aeMar\u00ae";
// expect(months.split("\u00ae").length == 3);
StringBuilder sb = new StringBuilder();
sb.append('$');
sb.append('2');
expect(sb.substring(1).equals("2"));
}
}