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 { public void write(String s, int offset, int length) throws IOException {
char[] b = new char[length]; char[] b = new char[length];
s.getChars(offset, length, b, 0); s.getChars(offset, offset + length, b, 0);
write(b); write(b);
} }

View File

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

View File

@ -83,9 +83,7 @@ public abstract class ClassLoader {
return c; return c;
} }
protected void resolveClass(Class c) { protected native void resolveClass(Class c);
// ignore
}
private ClassLoader getParent() { private ClassLoader getParent() {
return parent; 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) { public static <T extends Enum<T>> T valueOf(Class<T> enumType, String name) {
if (name != null) { if (name == null) throw new NullPointerException();
try {
Method method = enumType.getMethod("values"); try {
Enum values[] = (Enum[])(method.invoke(null)); Method method = enumType.getMethod("values");
for (Enum value : values) { Enum values[] = (Enum[]) (method.invoke(null));
if (name.equals(value.name)) { for (Enum value: values) {
return (T) value; 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() { 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.io.UnsupportedEncodingException;
import java.util.regex.Pattern; import java.util.regex.Pattern;
import java.util.Comparator; import java.util.Comparator;
import java.util.Formatter;
import java.util.Locale; import java.util.Locale;
import java.io.ByteArrayOutputStream; import java.io.ByteArrayOutputStream;
import java.io.Serializable; import java.io.Serializable;
@ -52,7 +53,9 @@ public final class String
throws UnsupportedEncodingException throws UnsupportedEncodingException
{ {
this(bytes, offset, length); this(bytes, offset, length);
if (! charsetName.equalsIgnoreCase("UTF-8")) { if (! (charsetName.equalsIgnoreCase("UTF-8")
|| charsetName.equalsIgnoreCase("ISO-8859-1")))
{
throw new UnsupportedEncodingException(charsetName); throw new UnsupportedEncodingException(charsetName);
} }
} }
@ -76,10 +79,7 @@ public final class String
public String(byte[] data, String charset) public String(byte[] data, String charset)
throws UnsupportedEncodingException throws UnsupportedEncodingException
{ {
this(data); this(data, 0, data.length, charset);
if (! charset.equals("UTF-8")) {
throw new UnsupportedEncodingException(charset);
}
} }
public String(byte bytes[], int highByte, int offset, int length) { public String(byte bytes[], int highByte, int offset, int length) {
@ -540,6 +540,10 @@ public final class String
public boolean matches(String regex) { public boolean matches(String regex) {
return Pattern.matches(regex, this); 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) { public String replaceAll(String regex, String replacement) {
return Pattern.compile(regex).matcher(this).replaceAll(replacement); return Pattern.compile(regex).matcher(this).replaceAll(replacement);
@ -625,8 +629,8 @@ public final class String
return length == 0; return length == 0;
} }
public boolean contains(String match) { public boolean contains(CharSequence match) {
return indexOf(match) != -1; return indexOf(match.toString()) != -1;
} }
public int codePointAt(int offset) { public int codePointAt(int offset) {
@ -649,6 +653,14 @@ public final class String
throw new UnsupportedOperationException(); 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: // for GNU Classpath compatibility:
static char[] zeroBasedStringValue(String s) { static char[] zeroBasedStringValue(String s) {
if (s.offset == 0) { if (s.offset == 0) {

View File

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

View File

@ -248,6 +248,29 @@ public class StringBuilder implements CharSequence, Appendable {
return -1; 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() { public int length() {
return length; return length;
@ -283,9 +306,8 @@ public class StringBuilder implements CharSequence, Appendable {
} }
} }
public void getChars(int srcOffset, int srcLength, char[] dst, int dstOffset) public void getChars(int srcStart, int srcEnd, char[] dst, int dstStart) {
{ if (srcStart < 0 || srcEnd > length) {
if (srcOffset < 0 || srcOffset + srcLength > length) {
throw new IndexOutOfBoundsException(); throw new IndexOutOfBoundsException();
} }
@ -297,17 +319,17 @@ public class StringBuilder implements CharSequence, Appendable {
int end = index; int end = index;
index = start; index = start;
if (start < srcOffset) { if (start < srcStart) {
start = srcOffset; start = srcStart;
} }
if (end > srcOffset + srcLength) { if (end > srcEnd) {
end = srcOffset + srcLength; end = srcEnd;
} }
if (start < end) { if (start < end) {
c.value.getChars(start - index, end - start, c.value.getChars(start - index, end - index,
dst, dstOffset + (start - srcOffset)); 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) { public String substring(int start, int end) {
int len = end-start; int len = end-start;
char[] buf = new char[len]; char[] buf = new char[len];
getChars(start, len, buf,0 ); getChars(start, end, buf, 0);
return new String(buf, 0, len, false); return new String(buf, 0, len, false);
} }

View File

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

View File

@ -55,6 +55,10 @@ public class Throwable implements Serializable {
return message; return message;
} }
public String getLocalizedMessage() {
return getMessage();
}
public String toString() { public String toString() {
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
sb.append(getClass().getName()); sb.append(getClass().getName());
@ -79,6 +83,10 @@ public class Throwable implements Serializable {
return resolveTrace(); return resolveTrace();
} }
public void setStackTrace(StackTraceElement[] trace) {
this.trace = trace;
}
public void printStackTrace(PrintStream out) { public void printStackTrace(PrintStream out) {
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
printStackTrace(sb, System.getProperty("line.separator")); 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 boolean isAccessible();
public abstract void setAccessible(boolean v); 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/PhantomReference.class \
java/lang/ref/Reference.class \ java/lang/ref/Reference.class \
java/lang/ref/ReferenceQueue.class \ java/lang/ref/ReferenceQueue.class \
java/lang/ref/SoftReference.class \
java/lang/ref/WeakReference.class \ java/lang/ref/WeakReference.class \
java/lang/reflect/AccessibleObject.class \ java/lang/reflect/AccessibleObject.class \
java/lang/reflect/Constructor.class \ java/lang/reflect/Constructor.class \

View File

@ -199,6 +199,16 @@ Avian_java_lang_ClassLoader_defineClass
return reinterpret_cast<int64_t>(c); 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 extern "C" JNIEXPORT int64_t JNICALL
Avian_avian_SystemClassLoader_findLoadedClass Avian_avian_SystemClassLoader_findLoadedClass
(Thread* t, object, uintptr_t* arguments) (Thread* t, object, uintptr_t* arguments)
@ -291,6 +301,16 @@ Avian_java_lang_Class_initialize
initClass(t, this_); 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 extern "C" JNIEXPORT int64_t JNICALL
Avian_java_lang_Class_isAssignableFrom Avian_java_lang_Class_isAssignableFrom
(Thread* t, object, uintptr_t* arguments) (Thread* t, object, uintptr_t* arguments)

View File

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

View File

@ -183,20 +183,17 @@ Avian_gnu_classpath_VMSystemProperties_preInit
#endif #endif
#ifdef __i386__ #ifdef __i386__
setProperty(t, method, properties, "gnu.cpu.endian", "little");
setProperty(t, method, properties, "os.arch", "x86"); setProperty(t, method, properties, "os.arch", "x86");
#elif defined __x86_64__ #elif defined __x86_64__
setProperty(t, method, properties, "gnu.cpu.endian", "little");
setProperty(t, method, properties, "os.arch", "x86_64"); setProperty(t, method, properties, "os.arch", "x86_64");
#elif defined(__ppc__) || defined(__powerpc__) \ #elif defined(__ppc__) || defined(__powerpc__) \
|| defined(__ppc64__) || defined(__powerpc64__) || defined(__ppc64__) || defined(__powerpc64__)
setProperty(t, method, properties, "gnu.cpu.endian", "big");
setProperty(t, method, properties, "os.arch", "ppc"); setProperty(t, method, properties, "os.arch", "ppc");
#elif defined __ia64__
setProperty(t, method, properties, "os.arch", "ia64");
#elif defined __arm__ #elif defined __arm__
setProperty(t, method, properties, "os.arch", "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 #else
setProperty(t, method, properties, "os.arch", "unknown"); setProperty(t, method, properties, "os.arch", "unknown");
#endif #endif
@ -461,3 +458,43 @@ Avian_java_lang_VMClassLoader_findLoadedClass
return 0; 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); PROTECT(t, eht);
catchType = resolveClassInPool catchType = resolveClassInPool
(t, codePool(t, methodCode(t, method)), (t, method, exceptionHandlerCatchType(eh) - 1);
exceptionHandlerCatchType(eh) - 1);
if (catchType) { if (catchType) {
eh = exceptionHandlerTableBody(t, eht, i); eh = exceptionHandlerTableBody(t, eht, i);
@ -1025,10 +1024,12 @@ interpret(Thread* t)
if (LIKELY(count >= 0)) { if (LIKELY(count >= 0)) {
uint16_t index = codeReadInt16(t, code, ip); 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_; 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 { } else {
object message = makeString(t, "%d", count); object message = makeString(t, "%d", count);
exception = makeNegativeArraySizeException(t, message); exception = makeNegativeArraySizeException(t, message);
@ -1211,7 +1212,7 @@ interpret(Thread* t)
uint16_t index = codeReadInt16(t, code, ip); uint16_t index = codeReadInt16(t, code, ip);
if (peekObject(t, sp - 1)) { 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 (UNLIKELY(exception)) goto throw_;
if (not instanceOf(t, class_, peekObject(t, sp - 1))) { if (not instanceOf(t, class_, peekObject(t, sp - 1))) {
@ -1568,7 +1569,7 @@ interpret(Thread* t)
if (LIKELY(peekObject(t, sp - 1))) { if (LIKELY(peekObject(t, sp - 1))) {
uint16_t index = codeReadInt16(t, code, ip); 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(exception)) goto throw_;
assert(t, (fieldFlags(t, field) & ACC_STATIC) == 0); assert(t, (fieldFlags(t, field) & ACC_STATIC) == 0);
@ -1602,7 +1603,7 @@ interpret(Thread* t)
case getstatic: { case getstatic: {
uint16_t index = codeReadInt16(t, code, ip); 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(exception)) goto throw_;
assert(t, fieldFlags(t, field) & ACC_STATIC); assert(t, fieldFlags(t, field) & ACC_STATIC);
@ -1958,7 +1959,7 @@ interpret(Thread* t)
uint16_t index = codeReadInt16(t, code, ip); uint16_t index = codeReadInt16(t, code, ip);
if (peekObject(t, sp - 1)) { 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 (UNLIKELY(exception)) goto throw_;
if (instanceOf(t, class_, popObject(t))) { if (instanceOf(t, class_, popObject(t))) {
@ -1977,7 +1978,7 @@ interpret(Thread* t)
ip += 2; 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_; if (UNLIKELY(exception)) goto throw_;
unsigned parameterFootprint = methodParameterFootprint(t, method); unsigned parameterFootprint = methodParameterFootprint(t, method);
@ -1994,7 +1995,7 @@ interpret(Thread* t)
case invokespecial: { case invokespecial: {
uint16_t index = codeReadInt16(t, code, ip); 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_; if (UNLIKELY(exception)) goto throw_;
unsigned parameterFootprint = methodParameterFootprint(t, method); unsigned parameterFootprint = methodParameterFootprint(t, method);
@ -2004,7 +2005,7 @@ interpret(Thread* t)
class_ = classSuper(t, class_); class_ = classSuper(t, class_);
if (UNLIKELY(classInit(t, class_, 3))) goto invoke; if (UNLIKELY(classInit(t, class_, 3))) goto invoke;
code = findMethod(t, method, class_); code = findVirtualMethod(t, method, class_);
} else { } else {
code = method; code = method;
} }
@ -2019,7 +2020,7 @@ interpret(Thread* t)
case invokestatic: { case invokestatic: {
uint16_t index = codeReadInt16(t, code, ip); 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_; if (UNLIKELY(exception)) goto throw_;
PROTECT(t, method); PROTECT(t, method);
@ -2031,7 +2032,7 @@ interpret(Thread* t)
case invokevirtual: { case invokevirtual: {
uint16_t index = codeReadInt16(t, code, ip); 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_; if (UNLIKELY(exception)) goto throw_;
unsigned parameterFootprint = methodParameterFootprint(t, method); unsigned parameterFootprint = methodParameterFootprint(t, method);
@ -2039,7 +2040,7 @@ interpret(Thread* t)
object class_ = objectClass(t, peekObject(t, sp - parameterFootprint)); object class_ = objectClass(t, peekObject(t, sp - parameterFootprint));
if (UNLIKELY(classInit(t, class_, 3))) goto invoke; if (UNLIKELY(classInit(t, class_, 3))) goto invoke;
code = findMethod(t, method, class_); code = findVirtualMethod(t, method, class_);
goto invoke; goto invoke;
} else { } else {
exception = makeNullPointerException(t); exception = makeNullPointerException(t);
@ -2246,9 +2247,10 @@ interpret(Thread* t)
if (singletonIsObject(t, pool, index - 1)) { if (singletonIsObject(t, pool, index - 1)) {
object v = singletonObject(t, pool, index - 1); object v = singletonObject(t, pool, index - 1);
if (objectClass(t, v) 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_; if (UNLIKELY(exception)) goto throw_;
pushObject(t, class_); pushObject(t, class_);
@ -2455,7 +2457,7 @@ interpret(Thread* t)
uint16_t index = codeReadInt16(t, code, ip); uint16_t index = codeReadInt16(t, code, ip);
uint8_t dimensions = codeBody(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_; if (UNLIKELY(exception)) goto throw_;
PROTECT(t, class_); PROTECT(t, class_);
@ -2481,7 +2483,7 @@ interpret(Thread* t)
case new_: { case new_: {
uint16_t index = codeReadInt16(t, code, ip); 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_; if (UNLIKELY(exception)) goto throw_;
PROTECT(t, class_); PROTECT(t, class_);
@ -2555,7 +2557,7 @@ interpret(Thread* t)
case putfield: { case putfield: {
uint16_t index = codeReadInt16(t, code, ip); 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(exception)) goto throw_;
if (UNLIKELY(fieldFlags(t, field) & ACC_VOLATILE)) { if (UNLIKELY(fieldFlags(t, field) & ACC_VOLATILE)) {
@ -2645,7 +2647,7 @@ interpret(Thread* t)
case putstatic: { case putstatic: {
uint16_t index = codeReadInt16(t, code, ip); 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(exception)) goto throw_;
if (UNLIKELY(fieldFlags(t, field) & ACC_VOLATILE)) { if (UNLIKELY(fieldFlags(t, field) & ACC_VOLATILE)) {
@ -2724,7 +2726,7 @@ interpret(Thread* t)
case return_: { case return_: {
object method = frameMethod(t, frame); object method = frameMethod(t, frame);
if ((methodFlags(t, method) & ConstructorFlag) if ((methodFlags(t, method) & ConstructorFlag)
and (classFlags(t, methodClass(t, method)) & HasFinalMemberFlag)) and (classVmFlags(t, methodClass(t, method)) & HasFinalMemberFlag))
{ {
storeStoreMemoryBarrier(); storeStoreMemoryBarrier();
} }
@ -2825,13 +2827,14 @@ interpret(Thread* t)
ip -= 2; ip -= 2;
uint16_t index = codeReadInt16(t, code, ip); 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); unsigned parameterFootprint = methodParameterFootprint(t, method);
object class_ = objectClass(t, peekObject(t, sp - parameterFootprint)); object class_ = objectClass(t, peekObject(t, sp - parameterFootprint));
assert(t, classVmFlags(t, class_) & BootstrapFlag); 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_; if (UNLIKELY(exception)) goto throw_;
ip -= 3; ip -= 3;
@ -2999,13 +3002,13 @@ invoke(Thread* t, object method)
class_ = objectClass(t, peekObject(t, t->sp - parameterFootprint)); class_ = objectClass(t, peekObject(t, t->sp - parameterFootprint));
if (classVmFlags(t, class_) & BootstrapFlag) { 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) { if (classFlags(t, methodClass(t, method)) & ACC_INTERFACE) {
method = findInterfaceMethod(t, method, class_); method = findInterfaceMethod(t, method, class_);
} else { } else {
method = findMethod(t, method, class_); method = findVirtualMethod(t, method, class_);
} }
} else { } else {
class_ = methodClass(t, method); class_ = methodClass(t, method);
@ -3100,10 +3103,10 @@ class MyProcessor: public Processor {
virtual object virtual object
makeClass(vm::Thread* t, makeClass(vm::Thread* t,
uint16_t flags, uint16_t flags,
uint8_t vmFlags, uint16_t vmFlags,
uint8_t arrayDimensions,
uint16_t fixedSize, uint16_t fixedSize,
uint16_t arrayElementSize, uint8_t arrayElementSize,
uint8_t arrayDimensions,
object objectMask, object objectMask,
object name, object name,
object super, object super,
@ -3116,7 +3119,7 @@ class MyProcessor: public Processor {
unsigned vtableLength UNUSED) unsigned vtableLength UNUSED)
{ {
return vm::makeClass return vm::makeClass
(t, flags, vmFlags, arrayDimensions, fixedSize, arrayElementSize, (t, flags, vmFlags, fixedSize, arrayElementSize, arrayDimensions,
objectMask, name, super, interfaceTable, virtualTable, fieldTable, objectMask, name, super, interfaceTable, virtualTable, fieldTable,
methodTable, staticTable, loader, 0); methodTable, staticTable, loader, 0);
} }
@ -3230,8 +3233,9 @@ class MyProcessor: public Processor {
} }
virtual object virtual object
invokeList(vm::Thread* vmt, const char* className, const char* methodName, invokeList(vm::Thread* vmt, object loader, const char* className,
const char* methodSpec, object this_, va_list arguments) const char* methodName, const char* methodSpec, object this_,
va_list arguments)
{ {
Thread* t = static_cast<Thread*>(vmt); Thread* t = static_cast<Thread*>(vmt);
@ -3247,7 +3251,9 @@ class MyProcessor: public Processor {
pushArguments(t, this_, methodSpec, false, arguments); 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)) { if (LIKELY(t->exception == 0)) {
assert(t, ((methodFlags(t, method) & ACC_STATIC) == 0) xor (this_ == 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()); Thread* t = static_cast<Thread*>(m->localThread->get());
if (t) { if (t) {
m->localThread->set(0);
t->exit(); t->exit();
return 0; return 0;
} else { } else {
@ -2003,6 +2004,7 @@ populateJNITables(JavaVMVTable* vmTable, JNIEnvVTable* envTable)
envTable->SetStaticFloatField = ::SetStaticFloatField; envTable->SetStaticFloatField = ::SetStaticFloatField;
envTable->SetStaticDoubleField = ::SetStaticDoubleField; envTable->SetStaticDoubleField = ::SetStaticDoubleField;
envTable->NewGlobalRef = ::NewGlobalRef; envTable->NewGlobalRef = ::NewGlobalRef;
envTable->NewWeakGlobalRef = ::NewGlobalRef;
envTable->DeleteGlobalRef = ::DeleteGlobalRef; envTable->DeleteGlobalRef = ::DeleteGlobalRef;
envTable->ExceptionOccurred = ::ExceptionOccurred; envTable->ExceptionOccurred = ::ExceptionOccurred;
envTable->ExceptionDescribe = ::ExceptionDescribe; envTable->ExceptionDescribe = ::ExceptionDescribe;

View File

@ -19,6 +19,8 @@ using namespace vm;
namespace { namespace {
const unsigned NoByte = 0xFFFF;
bool bool
find(Thread* t, Thread* o) find(Thread* t, Thread* o)
{ {
@ -540,9 +542,65 @@ makeByteArray(Thread* t, const char* format, va_list a)
return s; 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 object
parseUtf8NonAscii(Thread* t, Stream& s, object bytesSoFar, unsigned byteCount, parseUtf8NonAscii(Thread* t, Stream& s, object bytesSoFar, unsigned byteCount,
unsigned sourceIndex, unsigned lastByteRead) unsigned sourceIndex, unsigned byteA, unsigned byteB)
{ {
PROTECT(t, bytesSoFar); PROTECT(t, bytesSoFar);
@ -554,15 +612,14 @@ parseUtf8NonAscii(Thread* t, Stream& s, object bytesSoFar, unsigned byteCount,
charArrayBody(t, value, vi) = byteArrayBody(t, bytesSoFar, vi); charArrayBody(t, value, vi) = byteArrayBody(t, bytesSoFar, vi);
} }
unsigned a = lastByteRead; for (unsigned si = sourceIndex; si < length; ++si) {
unsigned si = sourceIndex; unsigned a = readByte(s, &byteA);
while (true) {
if (a & 0x80) { if (a & 0x80) {
if (a & 0x20) { if (a & 0x20) {
// 3 bytes // 3 bytes
si += 2; si += 2;
assert(t, si < length); assert(t, si < length);
unsigned b = s.read1(); unsigned b = readByte(s, &byteB);
unsigned c = s.read1(); unsigned c = s.read1();
charArrayBody(t, value, vi++) charArrayBody(t, value, vi++)
= ((a & 0xf) << 12) | ((b & 0x3f) << 6) | (c & 0x3f); = ((a & 0xf) << 12) | ((b & 0x3f) << 6) | (c & 0x3f);
@ -570,7 +627,7 @@ parseUtf8NonAscii(Thread* t, Stream& s, object bytesSoFar, unsigned byteCount,
// 2 bytes // 2 bytes
++ si; ++ si;
assert(t, si < length); assert(t, si < length);
unsigned b = s.read1(); unsigned b = readByte(s, &byteB);
if (a == 0xC0 and b == 0x80) { if (a == 0xC0 and b == 0x80) {
charArrayBody(t, value, vi++) = 0; charArrayBody(t, value, vi++) = 0;
@ -580,12 +637,6 @@ parseUtf8NonAscii(Thread* t, Stream& s, object bytesSoFar, unsigned byteCount,
} }
} else { } else {
charArrayBody(t, value, vi++) = a; 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 & 0x80) {
if (a & 0x20) { if (a & 0x20) {
// 3 bytes // 3 bytes
return parseUtf8NonAscii(t, s, value, vi, si, a); return parseUtf8NonAscii(t, s, value, vi, si, a, NoByte);
} else { } else {
// 2 bytes // 2 bytes
unsigned b = s.read1(); unsigned b = s.read1();
@ -621,7 +672,7 @@ parseUtf8(Thread* t, Stream& s, unsigned length)
assert(t, si < length); assert(t, si < length);
byteArrayBody(t, value, vi++) = 0; byteArrayBody(t, value, vi++) = 0;
} else { } else {
return parseUtf8NonAscii(t, s, value, vi, si, a); return parseUtf8NonAscii(t, s, value, vi, si, a, b);
} }
} }
} else { } else {
@ -699,7 +750,7 @@ parsePoolEntry(Thread* t, Stream& s, uint32_t* index, object pool, unsigned i)
unsigned si = s.read2() - 1; unsigned si = s.read2() - 1;
parsePoolEntry(t, s, index, pool, si); 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); set(t, pool, SingletonBody + (i * BytesPerWord), value);
} }
} return 1; } 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, ci);
parsePoolEntry(t, s, index, pool, nti); 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 nameAndType = singletonObject(t, pool, nti);
object value = makeReference object value = makeReference
(t, class_, pairFirst(t, nameAndType), pairSecond(t, nameAndType)); (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(); unsigned count = s.read2();
for (unsigned i = 0; i < count; ++i) { 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); PROTECT(t, name);
object interface = resolveClass(t, classLoader(t, class_), 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; staticTypes[staticCount++] = code;
} else { } else {
if (flags & ACC_FINAL) { if (flags & ACC_FINAL) {
classFlags(t, class_) |= HasFinalMemberFlag; classVmFlags(t, class_) |= HasFinalMemberFlag;
} }
unsigned excess = (memberOffset % fieldSize(t, code)) % BytesPerWord; 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); 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"), (reinterpret_cast<const int8_t*>("finalize"),
&byteArrayBody(t, methodName(t, method), 0)) == 0 &byteArrayBody(t, methodName(t, method), 0)) == 0
and strcmp and strcmp
@ -1557,9 +1609,9 @@ makeArrayClass(Thread* t, object loader, unsigned dimensions, object spec,
(t, (t,
0, 0,
0, 0,
dimensions,
2 * BytesPerWord, 2 * BytesPerWord,
BytesPerWord, BytesPerWord,
dimensions,
classObjectMask(t, arrayBody(t, t->m->types, Machine::ArrayType)), classObjectMask(t, arrayBody(t, t->m->types, Machine::ArrayType)),
spec, spec,
arrayBody(t, t->m->types, Machine::JobjectType), 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); super = (superType >= 0 ? arrayBody(t, t->m->types, superType) : 0);
object class_ = t->m->processor->makeClass 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); 0, 0, 0, t->m->loader, vtableLength);
set(t, t->m->types, ArrayBody + (type * BytesPerWord), class_); set(t, t->m->types, ArrayBody + (type * BytesPerWord), class_);
@ -1765,16 +1817,18 @@ boot(Thread* t)
m->unsafe = false; m->unsafe = false;
classFlags(t, arrayBody(t, m->types, Machine::SingletonType)) classVmFlags(t, arrayBody(t, m->types, Machine::SingletonType))
|= SingletonFlag; |= SingletonFlag;
classFlags(t, arrayBody(t, m->types, Machine::ContinuationType)) classVmFlags(t, arrayBody(t, m->types, Machine::ContinuationType))
|= ContinuationFlag; |= ContinuationFlag;
classVmFlags(t, arrayBody(t, m->types, Machine::JreferenceType)) classVmFlags(t, arrayBody(t, m->types, Machine::JreferenceType))
|= ReferenceFlag; |= ReferenceFlag;
classVmFlags(t, arrayBody(t, m->types, Machine::WeakReferenceType)) classVmFlags(t, arrayBody(t, m->types, Machine::WeakReferenceType))
|= ReferenceFlag | WeakReferenceFlag; |= ReferenceFlag | WeakReferenceFlag;
classVmFlags(t, arrayBody(t, m->types, Machine::SoftReferenceType))
|= ReferenceFlag | WeakReferenceFlag;
classVmFlags(t, arrayBody(t, m->types, Machine::PhantomReferenceType)) classVmFlags(t, arrayBody(t, m->types, Machine::PhantomReferenceType))
|= ReferenceFlag | WeakReferenceFlag; |= ReferenceFlag | WeakReferenceFlag;
@ -2064,8 +2118,6 @@ Thread::init()
m->localThread->set(this); m->localThread->set(this);
} else { } else {
assert(this, javaThread);
peer = parent->child; peer = parent->child;
parent->child = this; parent->child = this;
} }
@ -2073,11 +2125,16 @@ Thread::init()
if (javaThread) { if (javaThread) {
threadPeer(this, javaThread) = reinterpret_cast<jlong>(this); threadPeer(this, javaThread) = reinterpret_cast<jlong>(this);
} else { } else {
object group;
if (parent) {
group = threadGroup(this, parent->javaThread);
} else {
group = makeThreadGroup(this, 0, 0);
}
const unsigned NewState = 0; const unsigned NewState = 0;
const unsigned NormalPriority = 5; const unsigned NormalPriority = 5;
object group = makeThreadGroup(this, 0, 0);
this->javaThread = makeThread this->javaThread = makeThread
(this, reinterpret_cast<int64_t>(this), 0, 0, NewState, NormalPriority, (this, reinterpret_cast<int64_t>(this), 0, 0, NewState, NormalPriority,
0, 0, 0, m->loader, 0, 0, group); 0, 0, 0, m->loader, 0, 0, group);
@ -2428,16 +2485,18 @@ makeString(Thread* t, const char* format, ...)
void void
stringChars(Thread* t, object string, char* chars) stringChars(Thread* t, object string, char* chars)
{ {
object data = stringData(t, string); if (stringLength(t, string)) {
if (objectClass(t, data) object data = stringData(t, string);
== arrayBody(t, t->m->types, Machine::ByteArrayType)) if (objectClass(t, data)
{ == arrayBody(t, t->m->types, Machine::ByteArrayType))
memcpy(chars, {
&byteArrayBody(t, data, stringOffset(t, string)), memcpy(chars,
stringLength(t, string)); &byteArrayBody(t, data, stringOffset(t, string)),
} else { stringLength(t, string));
for (unsigned i = 0; i < stringLength(t, string); ++i) { } else {
chars[i] = charArrayBody(t, data, stringOffset(t, string) + i); for (unsigned i = 0; i < stringLength(t, string); ++i) {
chars[i] = charArrayBody(t, data, stringOffset(t, string) + i);
}
} }
} }
chars[stringLength(t, string)] = 0; chars[stringLength(t, string)] = 0;
@ -2446,17 +2505,19 @@ stringChars(Thread* t, object string, char* chars)
void void
stringChars(Thread* t, object string, uint16_t* chars) stringChars(Thread* t, object string, uint16_t* chars)
{ {
object data = stringData(t, string); if (stringLength(t, string)) {
if (objectClass(t, data) object data = stringData(t, string);
== arrayBody(t, t->m->types, Machine::ByteArrayType)) 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); 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; chars[stringLength(t, string)] = 0;
} }
@ -2649,11 +2710,12 @@ parseClass(Thread* t, object loader, const uint8_t* data, unsigned size)
object class_ = makeClass(t, object class_ = makeClass(t,
flags, flags,
0, // VM flags 0, // VM flags
0, // array dimensions
0, // fixed size 0, // fixed size
0, // array size 0, // array size
0, // array dimensions
0, // object mask 0, // object mask
singletonObject(t, pool, name - 1), referenceName
(t, singletonObject(t, pool, name - 1)),
0, // super 0, // super
0, // interfaces 0, // interfaces
0, // vtable 0, // vtable
@ -2666,7 +2728,8 @@ parseClass(Thread* t, object loader, const uint8_t* data, unsigned size)
unsigned super = s.read2(); unsigned super = s.read2();
if (super) { 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; if (UNLIKELY(t->exception)) return 0;
set(t, class_, ClassSuper, sc); set(t, class_, ClassSuper, sc);
@ -2692,9 +2755,9 @@ parseClass(Thread* t, object loader, const uint8_t* data, unsigned size)
(t, (t,
classFlags(t, class_), classFlags(t, class_),
classVmFlags(t, class_), classVmFlags(t, class_),
classArrayDimensions(t, class_),
classFixedSize(t, class_), classFixedSize(t, class_),
classArrayElementSize(t, class_), classArrayElementSize(t, class_),
classArrayDimensions(t, class_),
classObjectMask(t, class_), classObjectMask(t, class_),
className(t, class_), className(t, class_),
classSuper(t, class_), classSuper(t, class_),
@ -2821,7 +2884,7 @@ resolveClass(Thread* t, object loader, object spec)
} }
if (LIKELY(t->exception == 0)) { if (LIKELY(t->exception == 0)) {
object method = findMethod object method = findVirtualMethod
(t, t->m->loadClassMethod, objectClass(t, loader)); (t, t->m->loadClassMethod, objectClass(t, loader));
if (LIKELY(t->exception == 0)) { 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 object
resolveMethod(Thread* t, object class_, const char* methodName, resolveMethod(Thread* t, object class_, const char* methodName,
const char* methodSpec) const char* methodSpec)
@ -3272,7 +3424,7 @@ walk(Thread* t, Heap::Walker* w, object o, unsigned start)
intArrayLength(t, objectMask) * 4); intArrayLength(t, objectMask) * 4);
more = ::walk(t, w, mask, fixedSize, arrayElementSize, arrayLength, start); 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); unsigned length = singletonLength(t, o);
if (length) { if (length) {
more = ::walk(t, w, singletonMask(t, o), 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); 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); t->m->processor->walkContinuationBody(t, w, o, start);
} }
} }

View File

@ -74,12 +74,6 @@ enum StackTag {
const int NativeLine = -1; const int NativeLine = -1;
const int UnknownLine = -2; 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: // class vmFlags:
const unsigned ReferenceFlag = 1 << 0; const unsigned ReferenceFlag = 1 << 0;
const unsigned WeakReferenceFlag = 1 << 1; const unsigned WeakReferenceFlag = 1 << 1;
@ -89,6 +83,10 @@ const unsigned InitErrorFlag = 1 << 4;
const unsigned PrimitiveFlag = 1 << 5; const unsigned PrimitiveFlag = 1 << 5;
const unsigned BootstrapFlag = 1 << 6; const unsigned BootstrapFlag = 1 << 6;
const unsigned HasFinalizerFlag = 1 << 7; 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: // method vmFlags:
const unsigned ClassInitFlag = 1 << 0; const unsigned ClassInitFlag = 1 << 0;
@ -1816,6 +1814,7 @@ makeNew(Thread* t, object class_)
PROTECT(t, class_); PROTECT(t, class_);
unsigned sizeInBytes = pad(classFixedSize(t, class_)); unsigned sizeInBytes = pad(classFixedSize(t, class_));
assert(t, sizeInBytes);
object instance = allocate(t, sizeInBytes, classObjectMask(t, class_)); object instance = allocate(t, sizeInBytes, classObjectMask(t, class_));
setObjectClass(t, instance, class_); setObjectClass(t, instance, class_);
@ -2103,6 +2102,9 @@ resolveSystemClass(Thread* t, const char* name)
return resolveSystemClass(t, makeByteArray(t, "%s", name)); return resolveSystemClass(t, makeByteArray(t, "%s", name));
} }
void
linkClass(Thread* t, object loader, object class_);
object object
resolveMethod(Thread* t, object class_, const char* methodName, resolveMethod(Thread* t, object class_, const char* methodName,
const char* methodSpec); const char* methodSpec);
@ -2185,7 +2187,7 @@ findMethod(Thread* t, object class_, object name, object spec)
} }
inline object inline object
findMethod(Thread* t, object method, object class_) findVirtualMethod(Thread* t, object method, object class_)
{ {
return arrayBody(t, classVirtualTable(t, class_), return arrayBody(t, classVirtualTable(t, class_),
methodOffset(t, method)); methodOffset(t, method));
@ -2444,6 +2446,101 @@ makeSingletonOfSize(Thread* t, unsigned count)
return o; 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 void
dumpHeap(Thread* t, FILE* out); dumpHeap(Thread* t, FILE* out);

View File

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

View File

@ -36,79 +36,6 @@ codeReadInt32(Thread* t, object code, unsigned& ip)
return ((v1 << 24) | (v2 << 16) | (v3 << 8) | v4); 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 inline bool
isSuperclass(Thread* t, object class_, object base) isSuperclass(Thread* t, object class_, object base)
{ {

View File

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

View File

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

View File

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

View File

@ -91,11 +91,6 @@ public class Misc {
} }
public static void main(String[] args) { 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); expect(queryDefault(new Object()) != null);
{ Foo foo = new Foo(); { 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"));
}
}