mirror of
https://github.com/corda/corda.git
synced 2025-01-09 06:23:04 +00:00
Merge branch 'gnu'
This commit is contained in:
commit
08dd7d0a5a
@ -1,4 +1,4 @@
|
|||||||
/* Copyright (c) 2008, Avian Contributors
|
/* Copyright (c) 2009, Avian Contributors
|
||||||
|
|
||||||
Permission to use, copy, modify, and/or distribute this software
|
Permission to use, copy, modify, and/or distribute this software
|
||||||
for any purpose with or without fee is hereby granted, provided
|
for any purpose with or without fee is hereby granted, provided
|
||||||
@ -8,7 +8,7 @@
|
|||||||
There is NO WARRANTY for this software. See license.txt for
|
There is NO WARRANTY for this software. See license.txt for
|
||||||
details. */
|
details. */
|
||||||
|
|
||||||
package java.util;
|
package avian;
|
||||||
|
|
||||||
public class Cell <T> {
|
public class Cell <T> {
|
||||||
public T value;
|
public T value;
|
@ -1,4 +1,4 @@
|
|||||||
/* Copyright (c) 2008, Avian Contributors
|
/* Copyright (c) 2009, Avian Contributors
|
||||||
|
|
||||||
Permission to use, copy, modify, and/or distribute this software
|
Permission to use, copy, modify, and/or distribute this software
|
||||||
for any purpose with or without fee is hereby granted, provided
|
for any purpose with or without fee is hereby granted, provided
|
||||||
@ -8,7 +8,9 @@
|
|||||||
There is NO WARRANTY for this software. See license.txt for
|
There is NO WARRANTY for this software. See license.txt for
|
||||||
details. */
|
details. */
|
||||||
|
|
||||||
package java.util;
|
package avian;
|
||||||
|
|
||||||
|
import java.util.Comparator;
|
||||||
|
|
||||||
public class PersistentSet <T> implements Iterable <T> {
|
public class PersistentSet <T> implements Iterable <T> {
|
||||||
private static final Node NullNode = new Node(null);
|
private static final Node NullNode = new Node(null);
|
101
classpath/avian/resource/Handler.java
Normal file
101
classpath/avian/resource/Handler.java
Normal file
@ -0,0 +1,101 @@
|
|||||||
|
/* Copyright (c) 2008-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 avian.resource;
|
||||||
|
|
||||||
|
import java.net.URL;
|
||||||
|
import java.net.URLStreamHandler;
|
||||||
|
import java.net.URLConnection;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.FileNotFoundException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
|
||||||
|
public class Handler extends URLStreamHandler {
|
||||||
|
protected URLConnection openConnection(URL url) {
|
||||||
|
return new ResourceConnection(url);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class ResourceConnection extends URLConnection {
|
||||||
|
public ResourceConnection(URL url) {
|
||||||
|
super(url);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getContentLength() {
|
||||||
|
return ResourceInputStream.getContentLength(url.getFile());
|
||||||
|
}
|
||||||
|
|
||||||
|
public InputStream getInputStream() throws IOException {
|
||||||
|
return new ResourceInputStream(url.getFile());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class ResourceInputStream extends InputStream {
|
||||||
|
private long peer;
|
||||||
|
private int position;
|
||||||
|
|
||||||
|
public ResourceInputStream(String path) throws IOException {
|
||||||
|
peer = open(path);
|
||||||
|
if (peer == 0) {
|
||||||
|
throw new FileNotFoundException(path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static native int getContentLength(String path);
|
||||||
|
|
||||||
|
private static native long open(String path) throws IOException;
|
||||||
|
|
||||||
|
private static native int read(long peer, int position) throws IOException;
|
||||||
|
|
||||||
|
private static native int read(long peer, int position,
|
||||||
|
byte[] b, int offset, int length)
|
||||||
|
throws IOException;
|
||||||
|
|
||||||
|
public static native void close(long peer) throws IOException;
|
||||||
|
|
||||||
|
public int read() throws IOException {
|
||||||
|
if (peer != 0) {
|
||||||
|
int c = read(peer, position);
|
||||||
|
if (c >= 0) {
|
||||||
|
++ position;
|
||||||
|
}
|
||||||
|
return c;
|
||||||
|
} else {
|
||||||
|
throw new IOException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public int read(byte[] b, int offset, int length) throws IOException {
|
||||||
|
if (peer != 0) {
|
||||||
|
if (b == null) {
|
||||||
|
throw new NullPointerException();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (offset < 0 || offset + length > b.length) {
|
||||||
|
throw new ArrayIndexOutOfBoundsException();
|
||||||
|
}
|
||||||
|
|
||||||
|
int c = read(peer, position, b, offset, length);
|
||||||
|
if (c >= 0) {
|
||||||
|
position += c;
|
||||||
|
}
|
||||||
|
return c;
|
||||||
|
} else {
|
||||||
|
throw new IOException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void close() throws IOException {
|
||||||
|
if (peer != 0) {
|
||||||
|
close(peer);
|
||||||
|
peer = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -23,6 +23,7 @@
|
|||||||
#ifdef WIN32
|
#ifdef WIN32
|
||||||
# include <windows.h>
|
# include <windows.h>
|
||||||
# include <io.h>
|
# include <io.h>
|
||||||
|
# include <direct.h>
|
||||||
|
|
||||||
# define OPEN _open
|
# define OPEN _open
|
||||||
# define CLOSE _close
|
# define CLOSE _close
|
||||||
|
@ -82,7 +82,7 @@ namespace {
|
|||||||
|
|
||||||
int descriptor(JNIEnv* e, HANDLE h)
|
int descriptor(JNIEnv* e, HANDLE h)
|
||||||
{
|
{
|
||||||
int fd = _open_osfhandle(reinterpret_cast<long>(h), 0);
|
int fd = _open_osfhandle(reinterpret_cast<intptr_t>(h), 0);
|
||||||
if (fd == -1) {
|
if (fd == -1) {
|
||||||
throwNew(e, "java/io/IOException", strerror(errno));
|
throwNew(e, "java/io/IOException", strerror(errno));
|
||||||
}
|
}
|
||||||
|
22
classpath/java/lang/Appendable.java
Normal file
22
classpath/java/lang/Appendable.java
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
/* 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;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
public interface Appendable {
|
||||||
|
public Appendable append(char c) throws IOException;
|
||||||
|
|
||||||
|
public Appendable append(CharSequence sequence) throws IOException;
|
||||||
|
|
||||||
|
public Appendable append(CharSequence sequence, int start, int end)
|
||||||
|
throws IOException;
|
||||||
|
}
|
@ -1,4 +1,4 @@
|
|||||||
/* Copyright (c) 2008, Avian Contributors
|
/* Copyright (c) 2008-2009, Avian Contributors
|
||||||
|
|
||||||
Permission to use, copy, modify, and/or distribute this software
|
Permission to use, copy, modify, and/or distribute this software
|
||||||
for any purpose with or without fee is hereby granted, provided
|
for any purpose with or without fee is hereby granted, provided
|
||||||
@ -10,7 +10,7 @@
|
|||||||
|
|
||||||
package java.lang;
|
package java.lang;
|
||||||
|
|
||||||
public class ArrayIndexOutOfBoundsException extends RuntimeException {
|
public class ArrayIndexOutOfBoundsException extends IndexOutOfBoundsException {
|
||||||
public ArrayIndexOutOfBoundsException(String message, Throwable cause) {
|
public ArrayIndexOutOfBoundsException(String message, Throwable cause) {
|
||||||
super(message, cause);
|
super(message, cause);
|
||||||
}
|
}
|
||||||
|
@ -187,4 +187,40 @@ public final class Character implements Comparable<Character> {
|
|||||||
return isHighSurrogate(high) && isLowSurrogate(low);
|
return isHighSurrogate(high) && isLowSurrogate(low);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static int codePointAt(CharSequence sequence, int offset) {
|
||||||
|
int length = sequence.length();
|
||||||
|
if (offset < 0 || offset >= length) {
|
||||||
|
throw new IndexOutOfBoundsException();
|
||||||
|
}
|
||||||
|
|
||||||
|
char high = sequence.charAt(offset);
|
||||||
|
if (! isHighSurrogate(high) || offset >= length) {
|
||||||
|
return high;
|
||||||
|
}
|
||||||
|
char low = sequence.charAt(offset + 1);
|
||||||
|
if (! isLowSurrogate(low)) {
|
||||||
|
return high;
|
||||||
|
}
|
||||||
|
|
||||||
|
return toCodePoint(high, low);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int codePointCount(CharSequence sequence, int start, int end) {
|
||||||
|
int length = sequence.length();
|
||||||
|
if (start < 0 || start > end || end >= length) {
|
||||||
|
throw new IndexOutOfBoundsException();
|
||||||
|
}
|
||||||
|
|
||||||
|
int count = 0;
|
||||||
|
for (int i = start; i < end; ++i) {
|
||||||
|
if (isHighSurrogate(sequence.charAt(i))
|
||||||
|
&& (i + 1) < end
|
||||||
|
&& isLowSurrogate(sequence.charAt(i + 1)))
|
||||||
|
{
|
||||||
|
++ i;
|
||||||
|
}
|
||||||
|
++ count;
|
||||||
|
}
|
||||||
|
return count;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -14,12 +14,19 @@ import java.lang.reflect.Constructor;
|
|||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
import java.lang.reflect.Field;
|
import java.lang.reflect.Field;
|
||||||
import java.lang.reflect.Modifier;
|
import java.lang.reflect.Modifier;
|
||||||
|
import java.lang.reflect.Type;
|
||||||
|
import java.lang.reflect.TypeVariable;
|
||||||
import java.lang.reflect.InvocationTargetException;
|
import java.lang.reflect.InvocationTargetException;
|
||||||
|
import java.lang.reflect.GenericDeclaration;
|
||||||
|
import java.lang.annotation.Annotation;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
|
import java.security.ProtectionDomain;
|
||||||
|
import java.security.Permissions;
|
||||||
|
import java.security.AllPermission;
|
||||||
|
|
||||||
public final class Class <T> {
|
public final class Class <T> implements Type, GenericDeclaration {
|
||||||
private static final int PrimitiveFlag = 1 << 4;
|
private static final int PrimitiveFlag = 1 << 4;
|
||||||
|
|
||||||
private short flags;
|
private short flags;
|
||||||
@ -84,6 +91,9 @@ public final class Class <T> {
|
|||||||
ClassLoader loader)
|
ClassLoader loader)
|
||||||
throws ClassNotFoundException
|
throws ClassNotFoundException
|
||||||
{
|
{
|
||||||
|
if (loader == null) {
|
||||||
|
loader = Class.class.loader;
|
||||||
|
}
|
||||||
Class c = loader.loadClass(name);
|
Class c = loader.loadClass(name);
|
||||||
if (initialize) {
|
if (initialize) {
|
||||||
c.initialize();
|
c.initialize();
|
||||||
@ -168,6 +178,8 @@ public final class Class <T> {
|
|||||||
|
|
||||||
private Method findMethod(String name, Class[] parameterTypes) {
|
private Method findMethod(String name, Class[] parameterTypes) {
|
||||||
if (methodTable != null) {
|
if (methodTable != null) {
|
||||||
|
if (parameterTypes == null)
|
||||||
|
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()))
|
||||||
@ -438,4 +450,59 @@ public final class Class <T> {
|
|||||||
public boolean desiredAssertionStatus() {
|
public boolean desiredAssertionStatus() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public T cast(Object o) {
|
||||||
|
return (T) o;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Object[] getSigners() {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Annotation[] getDeclaredAnnotations() {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isEnum() {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public TypeVariable<Class<T>>[] getTypeParameters() {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getSimpleName() {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Method getEnclosingMethod() {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Constructor getEnclosingConstructor() {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Class getEnclosingClass() {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Class[] getDeclaredClasses() {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public <A extends Annotation> A getAnnotation(Class<A> c) {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public ProtectionDomain getProtectionDomain() {
|
||||||
|
Permissions p = new Permissions();
|
||||||
|
p.add(new AllPermission());
|
||||||
|
return new ProtectionDomain(null, p);
|
||||||
|
}
|
||||||
|
|
||||||
|
// for GNU Classpath compatibility:
|
||||||
|
void setSigners(Object[] signers) {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/* Copyright (c) 2008, Avian Contributors
|
/* Copyright (c) 2008-2009, Avian Contributors
|
||||||
|
|
||||||
Permission to use, copy, modify, and/or distribute this software
|
Permission to use, copy, modify, and/or distribute this software
|
||||||
for any purpose with or without fee is hereby granted, provided
|
for any purpose with or without fee is hereby granted, provided
|
||||||
@ -11,8 +11,11 @@
|
|||||||
package java.lang;
|
package java.lang;
|
||||||
|
|
||||||
public class ClassNotFoundException extends Exception {
|
public class ClassNotFoundException extends Exception {
|
||||||
|
private final Throwable cause2;
|
||||||
|
|
||||||
public ClassNotFoundException(String message, Throwable cause) {
|
public ClassNotFoundException(String message, Throwable cause) {
|
||||||
super(message, cause);
|
super(message, cause);
|
||||||
|
cause2 = cause;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ClassNotFoundException(String message) {
|
public ClassNotFoundException(String message) {
|
||||||
|
@ -53,4 +53,12 @@ public abstract class Enum<E extends Enum<E>> implements Comparable<E> {
|
|||||||
public String toString() {
|
public String toString() {
|
||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Class<E> getDeclaringClass() {
|
||||||
|
Class c = getClass();
|
||||||
|
while (c.getSuperclass() != Enum.class) {
|
||||||
|
c = c.getSuperclass();
|
||||||
|
}
|
||||||
|
return c;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/* Copyright (c) 2008, Avian Contributors
|
/* Copyright (c) 2008-2009, Avian Contributors
|
||||||
|
|
||||||
Permission to use, copy, modify, and/or distribute this software
|
Permission to use, copy, modify, and/or distribute this software
|
||||||
for any purpose with or without fee is hereby granted, provided
|
for any purpose with or without fee is hereby granted, provided
|
||||||
@ -11,11 +11,14 @@
|
|||||||
package java.lang;
|
package java.lang;
|
||||||
|
|
||||||
public class ExceptionInInitializerError extends Error {
|
public class ExceptionInInitializerError extends Error {
|
||||||
|
private final Throwable cause2;
|
||||||
|
|
||||||
public ExceptionInInitializerError(String message) {
|
public ExceptionInInitializerError(String message) {
|
||||||
super(message);
|
super(message);
|
||||||
|
cause2 = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ExceptionInInitializerError() {
|
public ExceptionInInitializerError() {
|
||||||
super();
|
this(null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -25,7 +25,7 @@ public class Object {
|
|||||||
return this == o;
|
return this == o;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void finalize() { }
|
protected void finalize() throws Throwable { }
|
||||||
|
|
||||||
public native final Class<? extends Object> getClass();
|
public native final Class<? extends Object> getClass();
|
||||||
|
|
||||||
@ -41,5 +41,14 @@ public class Object {
|
|||||||
wait(0);
|
wait(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
public native final void wait(long timeout) throws InterruptedException;
|
public native final void wait(long milliseconds) throws InterruptedException;
|
||||||
|
|
||||||
|
public final void wait(long milliseconds, int nanoseconds)
|
||||||
|
throws InterruptedException
|
||||||
|
{
|
||||||
|
if (nanoseconds != 0) {
|
||||||
|
++ milliseconds;
|
||||||
|
}
|
||||||
|
wait(milliseconds);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/* Copyright (c) 2008, Avian Contributors
|
/* Copyright (c) 2008-2009, Avian Contributors
|
||||||
|
|
||||||
Permission to use, copy, modify, and/or distribute this software
|
Permission to use, copy, modify, and/or distribute this software
|
||||||
for any purpose with or without fee is hereby granted, provided
|
for any purpose with or without fee is hereby granted, provided
|
||||||
@ -10,9 +10,9 @@
|
|||||||
|
|
||||||
package java.lang;
|
package java.lang;
|
||||||
|
|
||||||
public class StackOverflowError extends Error {
|
public class StackOverflowError extends VirtualMachineError {
|
||||||
public StackOverflowError(String message) {
|
public StackOverflowError(String message) {
|
||||||
super(message, null);
|
super(message);
|
||||||
}
|
}
|
||||||
|
|
||||||
public StackOverflowError() {
|
public StackOverflowError() {
|
||||||
|
@ -18,8 +18,8 @@ public class StackTraceElement {
|
|||||||
private String file;
|
private String file;
|
||||||
private int line;
|
private int line;
|
||||||
|
|
||||||
private StackTraceElement(String class_, String method, String file,
|
public StackTraceElement(String class_, String method, String file,
|
||||||
int line)
|
int line)
|
||||||
{
|
{
|
||||||
this.class_ = class_;
|
this.class_ = class_;
|
||||||
this.method = method;
|
this.method = method;
|
||||||
@ -56,7 +56,7 @@ public class StackTraceElement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public String getClassName() {
|
public String getClassName() {
|
||||||
return class_;
|
return class_.replace('/', '.');
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getMethodName() {
|
public String getMethodName() {
|
||||||
|
@ -12,14 +12,30 @@ 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.Locale;
|
||||||
import java.io.ByteArrayOutputStream;
|
import java.io.ByteArrayOutputStream;
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
public final class String
|
||||||
|
implements Comparable<String>, CharSequence, Serializable
|
||||||
|
{
|
||||||
|
public static Comparator<String> CASE_INSENSITIVE_ORDER
|
||||||
|
= new Comparator<String>() {
|
||||||
|
public int compare(String a, String b) {
|
||||||
|
return a.compareToIgnoreCase(b);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
public final class String implements Comparable<String>, CharSequence {
|
|
||||||
private final Object data;
|
private final Object data;
|
||||||
private final int offset;
|
private final int offset;
|
||||||
private final int length;
|
private final int length;
|
||||||
private int hashCode;
|
private int hashCode;
|
||||||
|
|
||||||
|
public String() {
|
||||||
|
this(new char[0], 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
public String(char[] data, int offset, int length, boolean copy) {
|
public String(char[] data, int offset, int length, boolean copy) {
|
||||||
this((Object) data, offset, length, copy);
|
this((Object) data, offset, length, copy);
|
||||||
}
|
}
|
||||||
@ -32,9 +48,11 @@ public final class String implements Comparable<String>, CharSequence {
|
|||||||
this(data, 0, data.length);
|
this(data, 0, data.length);
|
||||||
}
|
}
|
||||||
|
|
||||||
public String(byte bytes[], int offset, int length, String charsetName) throws UnsupportedEncodingException {
|
public String(byte bytes[], int offset, int length, String charsetName)
|
||||||
|
throws UnsupportedEncodingException
|
||||||
|
{
|
||||||
this(bytes, offset, length);
|
this(bytes, offset, length);
|
||||||
if (!charsetName.equals("UTF-8")) {
|
if (! charsetName.equalsIgnoreCase("UTF-8")) {
|
||||||
throw new UnsupportedEncodingException(charsetName);
|
throw new UnsupportedEncodingException(charsetName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -57,12 +75,29 @@ public final class String implements Comparable<String>, CharSequence {
|
|||||||
|
|
||||||
public String(byte[] data, String charset)
|
public String(byte[] data, String charset)
|
||||||
throws UnsupportedEncodingException
|
throws UnsupportedEncodingException
|
||||||
{
|
{
|
||||||
this(data);
|
this(data);
|
||||||
if (! charset.equals("UTF-8")) {
|
if (! charset.equals("UTF-8")) {
|
||||||
throw new UnsupportedEncodingException(charset);
|
throw new UnsupportedEncodingException(charset);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public String(byte bytes[], int highByte, int offset, int length) {
|
||||||
|
if (offset < 0 || offset + length > bytes.length) {
|
||||||
|
throw new IndexOutOfBoundsException
|
||||||
|
(offset + " < 0 or " + offset + " + " + length + " > " + bytes.length);
|
||||||
|
}
|
||||||
|
|
||||||
|
char[] c = new char[length];
|
||||||
|
int mask = highByte << 8;
|
||||||
|
for (int i = 0; i < length; ++i) {
|
||||||
|
c[i] = (char) ((bytes[offset + i] & 0xFF) | mask);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.data = c;
|
||||||
|
this.offset = 0;
|
||||||
|
this.length = length;
|
||||||
|
}
|
||||||
|
|
||||||
private String(Object data, int offset, int length, boolean copy) {
|
private String(Object data, int offset, int length, boolean copy) {
|
||||||
int l;
|
int l;
|
||||||
@ -200,7 +235,7 @@ public final class String implements Comparable<String>, CharSequence {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public boolean equalsIgnoreCase(String s) {
|
public boolean equalsIgnoreCase(String s) {
|
||||||
return this == s || compareToIgnoreCase(s) == 0;
|
return this == s || (s != null && compareToIgnoreCase(s) == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
public int compareTo(String s) {
|
public int compareTo(String s) {
|
||||||
@ -381,7 +416,7 @@ public final class String implements Comparable<String>, CharSequence {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
throw new IndexOutOfBoundsException
|
throw new IndexOutOfBoundsException
|
||||||
(start + " not in (0, " + end + ") or " + end + " > " + length);
|
(start + " not in [0, " + end + ") or " + end + " > " + length);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -534,6 +569,10 @@ public final class String implements Comparable<String>, CharSequence {
|
|||||||
return Pattern.matches(regex, this);
|
return Pattern.matches(regex, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String replaceAll(String regex, String replacement) {
|
||||||
|
return Pattern.compile(regex).matcher(this).replaceAll(replacement);
|
||||||
|
}
|
||||||
|
|
||||||
public native String intern();
|
public native String intern();
|
||||||
|
|
||||||
public static String valueOf(Object s) {
|
public static String valueOf(Object s) {
|
||||||
@ -557,7 +596,9 @@ public final class String implements Comparable<String>, CharSequence {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static String valueOf(int v) {
|
public static String valueOf(int v) {
|
||||||
return Integer.toString(v);
|
// use Integer.toString(int, int), because GNU Classpath's
|
||||||
|
// Integer.toString(int) just calls String.valueOf(int):
|
||||||
|
return Integer.toString(v, 10);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String valueOf(long v) {
|
public static String valueOf(long v) {
|
||||||
@ -572,6 +613,14 @@ public final class String implements Comparable<String>, CharSequence {
|
|||||||
return Double.toString(v);
|
return Double.toString(v);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static String valueOf(char[] data, int offset, int length) {
|
||||||
|
return new String(data, offset, length);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String valueOf(char[] data) {
|
||||||
|
return valueOf(data, 0, data.length);
|
||||||
|
}
|
||||||
|
|
||||||
public int lastIndexOf(int ch, int lastIndex) {
|
public int lastIndexOf(int ch, int lastIndex) {
|
||||||
for (int i = lastIndex ; i >= 0; --i) {
|
for (int i = lastIndex ; i >= 0; --i) {
|
||||||
if (charAt(i) == ch) {
|
if (charAt(i) == ch) {
|
||||||
@ -581,4 +630,63 @@ public final class String implements Comparable<String>, CharSequence {
|
|||||||
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean regionMatches(int thisOffset, String match, int matchOffset,
|
||||||
|
int length)
|
||||||
|
{
|
||||||
|
return regionMatches(false, thisOffset, match, matchOffset, length);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean regionMatches(boolean ignoreCase, int thisOffset,
|
||||||
|
String match, int matchOffset, int length)
|
||||||
|
{
|
||||||
|
String a = substring(thisOffset, thisOffset + length);
|
||||||
|
String b = match.substring(matchOffset, matchOffset + length);
|
||||||
|
if (ignoreCase) {
|
||||||
|
return a.equalsIgnoreCase(b);
|
||||||
|
} else {
|
||||||
|
return a.equals(b);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isEmpty() {
|
||||||
|
return length == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean contains(String match) {
|
||||||
|
return indexOf(match) != -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int codePointAt(int offset) {
|
||||||
|
return Character.codePointAt(this, offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int codePointCount(int start, int end) {
|
||||||
|
return Character.codePointCount(this, start, end);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String replace(CharSequence match, CharSequence replacement) {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toUpperCase(Locale locale) {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toLowerCase(Locale locale) {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
// for GNU Classpath compatibility:
|
||||||
|
static char[] zeroBasedStringValue(String s) {
|
||||||
|
if (s.offset == 0) {
|
||||||
|
if (s.data instanceof char[]) {
|
||||||
|
char[] data = (char[]) s.data;
|
||||||
|
if (data.length == s.length) {
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return s.toCharArray();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -10,7 +10,7 @@
|
|||||||
|
|
||||||
package java.lang;
|
package java.lang;
|
||||||
|
|
||||||
public class StringBuilder implements CharSequence {
|
public class StringBuilder implements CharSequence, Appendable {
|
||||||
private static final int BufferSize = 32;
|
private static final int BufferSize = 32;
|
||||||
|
|
||||||
private Cell chain;
|
private Cell chain;
|
||||||
@ -54,6 +54,14 @@ public class StringBuilder implements CharSequence {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public StringBuilder append(CharSequence sequence) {
|
||||||
|
return append(sequence.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
public Appendable append(CharSequence sequence, int start, int end) {
|
||||||
|
return append(sequence.subSequence(start, end));
|
||||||
|
}
|
||||||
|
|
||||||
public StringBuilder append(char[] b, int offset, int length) {
|
public StringBuilder append(char[] b, int offset, int length) {
|
||||||
return append(new String(b, offset, length));
|
return append(new String(b, offset, length));
|
||||||
}
|
}
|
||||||
@ -150,6 +158,10 @@ public class StringBuilder implements CharSequence {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public StringBuilder insert(int i, CharSequence s) {
|
||||||
|
return insert(i, s.toString());
|
||||||
|
}
|
||||||
|
|
||||||
public StringBuilder insert(int i, char c) {
|
public StringBuilder insert(int i, char c) {
|
||||||
return insert(i, new String(new char[] { c }, 0, 1, false));
|
return insert(i, new String(new char[] { c }, 0, 1, false));
|
||||||
}
|
}
|
||||||
@ -332,4 +344,8 @@ public class StringBuilder implements CharSequence {
|
|||||||
deleteCharAt(index);
|
deleteCharAt(index);
|
||||||
insert(index, ch);
|
insert(index, ch);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void ensureCapacity(int capacity) {
|
||||||
|
// ignore
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/* Copyright (c) 2008, Avian Contributors
|
/* Copyright (c) 2008-2009, Avian Contributors
|
||||||
|
|
||||||
Permission to use, copy, modify, and/or distribute this software
|
Permission to use, copy, modify, and/or distribute this software
|
||||||
for any purpose with or without fee is hereby granted, provided
|
for any purpose with or without fee is hereby granted, provided
|
||||||
@ -15,14 +15,30 @@ import java.util.WeakHashMap;
|
|||||||
|
|
||||||
public class Thread implements Runnable {
|
public class Thread implements Runnable {
|
||||||
private long peer;
|
private long peer;
|
||||||
|
private boolean interrupted;
|
||||||
|
private boolean daemon;
|
||||||
|
private byte state;
|
||||||
|
private byte priority;
|
||||||
private final Runnable task;
|
private final Runnable task;
|
||||||
private Map<ThreadLocal, Object> locals;
|
private Map<ThreadLocal, Object> locals;
|
||||||
private boolean interrupted;
|
|
||||||
private Object sleepLock;
|
private Object sleepLock;
|
||||||
private ClassLoader classLoader;
|
private ClassLoader classLoader;
|
||||||
private String name;
|
private UncaughtExceptionHandler exceptionHandler;
|
||||||
|
|
||||||
public Thread(Runnable task, String name) {
|
// package private for GNU Classpath, which inexplicably bypasses
|
||||||
|
// the accessor methods:
|
||||||
|
String name;
|
||||||
|
ThreadGroup group;
|
||||||
|
|
||||||
|
private static UncaughtExceptionHandler defaultExceptionHandler;
|
||||||
|
|
||||||
|
public static final int MIN_PRIORITY = 1;
|
||||||
|
public static final int NORM_PRIORITY = 5;
|
||||||
|
public static final int MAX_PRIORITY = 10;
|
||||||
|
|
||||||
|
public Thread(ThreadGroup group, Runnable task, String name, long stackSize)
|
||||||
|
{
|
||||||
|
this.group = group;
|
||||||
this.task = task;
|
this.task = task;
|
||||||
this.name = name;
|
this.name = name;
|
||||||
|
|
||||||
@ -41,8 +57,28 @@ public class Thread implements Runnable {
|
|||||||
classLoader = current.classLoader;
|
classLoader = current.classLoader;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Thread(ThreadGroup group, Runnable task, String name) {
|
||||||
|
this(group, task, name, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Thread(ThreadGroup group, String name) {
|
||||||
|
this(null, null, name);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Thread(Runnable task, String name) {
|
||||||
|
this(null, task, name);
|
||||||
|
}
|
||||||
|
|
||||||
public Thread(Runnable task) {
|
public Thread(Runnable task) {
|
||||||
this(task, "Thread["+task+"]");
|
this(null, task, "Thread["+task+"]");
|
||||||
|
}
|
||||||
|
|
||||||
|
public Thread(String name) {
|
||||||
|
this(null, null, name);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Thread() {
|
||||||
|
this((Runnable) null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public synchronized void start() {
|
public synchronized void start() {
|
||||||
@ -58,6 +94,28 @@ public class Thread implements Runnable {
|
|||||||
|
|
||||||
private native long doStart();
|
private native long doStart();
|
||||||
|
|
||||||
|
private static void run(Thread t) throws Throwable {
|
||||||
|
t.state = (byte) State.RUNNABLE.ordinal();
|
||||||
|
try {
|
||||||
|
t.run();
|
||||||
|
} catch (Throwable e) {
|
||||||
|
UncaughtExceptionHandler eh = t.exceptionHandler;
|
||||||
|
UncaughtExceptionHandler deh = defaultExceptionHandler;
|
||||||
|
if (eh != null) {
|
||||||
|
eh.uncaughtException(t, e);
|
||||||
|
} else if (deh != null) {
|
||||||
|
deh.uncaughtException(t, e);
|
||||||
|
} else {
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
synchronized (t) {
|
||||||
|
t.state = (byte) State.TERMINATED.ordinal();
|
||||||
|
t.notifyAll();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public void run() {
|
public void run() {
|
||||||
if (task != null) {
|
if (task != null) {
|
||||||
task.run();
|
task.run();
|
||||||
@ -101,6 +159,10 @@ public class Thread implements Runnable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static boolean isInterrupted() {
|
||||||
|
return currentThread().interrupted;
|
||||||
|
}
|
||||||
|
|
||||||
public static void sleep(long milliseconds) throws InterruptedException {
|
public static void sleep(long milliseconds) throws InterruptedException {
|
||||||
Thread t = currentThread();
|
Thread t = currentThread();
|
||||||
if (t.sleepLock == null) {
|
if (t.sleepLock == null) {
|
||||||
@ -111,6 +173,16 @@ public class Thread implements Runnable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void sleep(long milliseconds, int nanoseconds)
|
||||||
|
throws InterruptedException
|
||||||
|
{
|
||||||
|
if (nanoseconds > 0) {
|
||||||
|
++ milliseconds;
|
||||||
|
}
|
||||||
|
|
||||||
|
sleep(milliseconds);
|
||||||
|
}
|
||||||
|
|
||||||
public StackTraceElement[] getStackTrace() {
|
public StackTraceElement[] getStackTrace() {
|
||||||
return Throwable.resolveTrace(getStackTrace(peer));
|
return Throwable.resolveTrace(getStackTrace(peer));
|
||||||
}
|
}
|
||||||
@ -125,4 +197,124 @@ public class Thread implements Runnable {
|
|||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setName(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public UncaughtExceptionHandler getUncaughtExceptionHandler() {
|
||||||
|
UncaughtExceptionHandler eh = exceptionHandler;
|
||||||
|
return (eh == null ? group : eh);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static UncaughtExceptionHandler getDefaultUncaughtExceptionHandler() {
|
||||||
|
return defaultExceptionHandler;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setUncaughtExceptionHandler(UncaughtExceptionHandler h) {
|
||||||
|
exceptionHandler = h;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void setDefaultUncaughtExceptionHandler
|
||||||
|
(UncaughtExceptionHandler h)
|
||||||
|
{
|
||||||
|
defaultExceptionHandler = h;
|
||||||
|
}
|
||||||
|
|
||||||
|
public State getState() {
|
||||||
|
return State.values()[state];
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isAlive() {
|
||||||
|
switch (getState()) {
|
||||||
|
case NEW:
|
||||||
|
case TERMINATED:
|
||||||
|
return false;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getPriority() {
|
||||||
|
return priority;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPriority(int priority) {
|
||||||
|
if (priority < MIN_PRIORITY || priority > MAX_PRIORITY) {
|
||||||
|
throw new IllegalArgumentException();
|
||||||
|
}
|
||||||
|
this.priority = (byte) priority;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isDaemon() {
|
||||||
|
return daemon;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDaemon(boolean v) {
|
||||||
|
daemon = v;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static native void yield();
|
||||||
|
|
||||||
|
public synchronized void join() throws InterruptedException {
|
||||||
|
while (getState() != State.TERMINATED) {
|
||||||
|
wait();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized void join(long milliseconds) throws InterruptedException
|
||||||
|
{
|
||||||
|
long then = System.currentTimeMillis();
|
||||||
|
long remaining = milliseconds;
|
||||||
|
while (remaining > 0 && getState() != State.TERMINATED) {
|
||||||
|
wait(remaining);
|
||||||
|
|
||||||
|
remaining = milliseconds - (System.currentTimeMillis() - then);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void join(long milliseconds, int nanoseconds)
|
||||||
|
throws InterruptedException
|
||||||
|
{
|
||||||
|
if (nanoseconds > 0) {
|
||||||
|
++ milliseconds;
|
||||||
|
}
|
||||||
|
|
||||||
|
join(milliseconds);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ThreadGroup getThreadGroup() {
|
||||||
|
return group;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static native boolean holdsLock(Object o);
|
||||||
|
|
||||||
|
public long getId() {
|
||||||
|
return peer;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void stop() {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void stop(Throwable t) {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void suspend() {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void resume() {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public interface UncaughtExceptionHandler {
|
||||||
|
public void uncaughtException(Thread t, Throwable e);
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum State {
|
||||||
|
NEW, RUNNABLE, BLOCKED, WAITING, TIMED_WAITING, TERMINATED
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
15
classpath/java/lang/ThreadDeath.java
Normal file
15
classpath/java/lang/ThreadDeath.java
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
/* 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;
|
||||||
|
|
||||||
|
public class ThreadDeath extends Error {
|
||||||
|
public ThreadDeath() { }
|
||||||
|
}
|
35
classpath/java/lang/ThreadGroup.java
Normal file
35
classpath/java/lang/ThreadGroup.java
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
/* 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;
|
||||||
|
|
||||||
|
public class ThreadGroup implements Thread.UncaughtExceptionHandler {
|
||||||
|
private final ThreadGroup parent;
|
||||||
|
private final String name;
|
||||||
|
|
||||||
|
public ThreadGroup(ThreadGroup parent, String name) {
|
||||||
|
this.parent = parent;
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void uncaughtException(Thread t, Throwable e) {
|
||||||
|
if (parent != null) {
|
||||||
|
parent.uncaughtException(t, e);
|
||||||
|
} else {
|
||||||
|
Thread.UncaughtExceptionHandler deh
|
||||||
|
= Thread.getDefaultUncaughtExceptionHandler();
|
||||||
|
if (deh != null) {
|
||||||
|
deh.uncaughtException(t, e);
|
||||||
|
} else if (! (e instanceof ThreadDeath)) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -13,8 +13,9 @@ package java.lang;
|
|||||||
import java.io.PrintStream;
|
import java.io.PrintStream;
|
||||||
import java.io.PrintWriter;
|
import java.io.PrintWriter;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
public class Throwable {
|
public class Throwable implements Serializable {
|
||||||
private String message;
|
private String message;
|
||||||
private Object trace;
|
private Object trace;
|
||||||
private Throwable cause;
|
private Throwable cause;
|
||||||
@ -109,4 +110,9 @@ public class Throwable {
|
|||||||
cause.printStackTrace(sb, nl);
|
cause.printStackTrace(sb, nl);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Throwable fillInStackTrace() {
|
||||||
|
trace = trace(0);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
21
classpath/java/lang/VirtualMachineError.java
Normal file
21
classpath/java/lang/VirtualMachineError.java
Normal 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;
|
||||||
|
|
||||||
|
public class VirtualMachineError extends Error {
|
||||||
|
public VirtualMachineError(String message) {
|
||||||
|
super(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
public VirtualMachineError() {
|
||||||
|
this(null);
|
||||||
|
}
|
||||||
|
}
|
@ -22,6 +22,10 @@ public abstract class Reference<T> {
|
|||||||
this.queue = queue;
|
this.queue = queue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected Reference(T target) {
|
||||||
|
this(target, null);
|
||||||
|
}
|
||||||
|
|
||||||
public T get() {
|
public T get() {
|
||||||
return target;
|
return target;
|
||||||
}
|
}
|
||||||
|
@ -10,7 +10,9 @@
|
|||||||
|
|
||||||
package java.lang.reflect;
|
package java.lang.reflect;
|
||||||
|
|
||||||
public class Constructor<T> extends AccessibleObject implements Member {
|
public class Constructor<T> extends AccessibleObject
|
||||||
|
implements Member, GenericDeclaration
|
||||||
|
{
|
||||||
private Method<T> method;
|
private Method<T> method;
|
||||||
|
|
||||||
public Constructor(Method<T> method) {
|
public Constructor(Method<T> method) {
|
||||||
@ -46,6 +48,18 @@ public class Constructor<T> extends AccessibleObject implements Member {
|
|||||||
return method.getName();
|
return method.getName();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isSynthetic() {
|
||||||
|
return method.isSynthetic();
|
||||||
|
}
|
||||||
|
|
||||||
|
public TypeVariable<Constructor<T>>[] getTypeParameters() {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Type[] getGenericParameterTypes() {
|
||||||
|
return method.getGenericParameterTypes();
|
||||||
|
}
|
||||||
|
|
||||||
private static native <T> T make(Class<T> c);
|
private static native <T> T make(Class<T> c);
|
||||||
|
|
||||||
public T newInstance(Object ... arguments)
|
public T newInstance(Object ... arguments)
|
||||||
|
@ -101,6 +101,38 @@ public class Field<T> extends AccessibleObject {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean getBoolean(Object instance) throws IllegalAccessException {
|
||||||
|
return ((Boolean) get(instance)).booleanValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte getByte(Object instance) throws IllegalAccessException {
|
||||||
|
return ((Byte) get(instance)).byteValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
public short getShort(Object instance) throws IllegalAccessException {
|
||||||
|
return ((Short) get(instance)).shortValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
public char getChar(Object instance) throws IllegalAccessException {
|
||||||
|
return ((Character) get(instance)).charValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getInt(Object instance) throws IllegalAccessException {
|
||||||
|
return ((Integer) get(instance)).intValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
public float getFloat(Object instance) throws IllegalAccessException {
|
||||||
|
return ((Float) get(instance)).floatValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getLong(Object instance) throws IllegalAccessException {
|
||||||
|
return ((Long) get(instance)).longValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getDouble(Object instance) throws IllegalAccessException {
|
||||||
|
return ((Double) get(instance)).doubleValue();
|
||||||
|
}
|
||||||
|
|
||||||
public void set(Object instance, Object value)
|
public void set(Object instance, Object value)
|
||||||
throws IllegalAccessException
|
throws IllegalAccessException
|
||||||
{
|
{
|
||||||
@ -162,6 +194,10 @@ public class Field<T> extends AccessibleObject {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isEnumConstant() {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
private static native long getPrimitive
|
private static native long getPrimitive
|
||||||
(Object instance, int code, int offset);
|
(Object instance, int code, int offset);
|
||||||
|
|
||||||
|
15
classpath/java/lang/reflect/GenericDeclaration.java
Normal file
15
classpath/java/lang/reflect/GenericDeclaration.java
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
/* 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.reflect;
|
||||||
|
|
||||||
|
public interface GenericDeclaration {
|
||||||
|
public TypeVariable<?>[] getTypeParameters();
|
||||||
|
}
|
@ -19,4 +19,6 @@ public interface Member {
|
|||||||
public int getModifiers();
|
public int getModifiers();
|
||||||
|
|
||||||
public String getName();
|
public String getName();
|
||||||
|
|
||||||
|
public boolean isSynthetic();
|
||||||
}
|
}
|
||||||
|
@ -10,7 +10,9 @@
|
|||||||
|
|
||||||
package java.lang.reflect;
|
package java.lang.reflect;
|
||||||
|
|
||||||
public class Method<T> extends AccessibleObject implements Member {
|
public class Method<T> extends AccessibleObject
|
||||||
|
implements Member, GenericDeclaration
|
||||||
|
{
|
||||||
private byte vmFlags;
|
private byte vmFlags;
|
||||||
private byte returnCode;
|
private byte returnCode;
|
||||||
private byte parameterCount;
|
private byte parameterCount;
|
||||||
@ -124,4 +126,28 @@ public class Method<T> extends AccessibleObject implements Member {
|
|||||||
}
|
}
|
||||||
throw new RuntimeException();
|
throw new RuntimeException();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isSynthetic() {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Object getDefaultValue() {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Type[] getGenericParameterTypes() {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Type getGenericReturnType() {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Class[] getExceptionTypes() {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public TypeVariable<Method<T>>[] getTypeParameters() {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
13
classpath/java/lang/reflect/Type.java
Normal file
13
classpath/java/lang/reflect/Type.java
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
/* 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.reflect;
|
||||||
|
|
||||||
|
public interface Type { }
|
19
classpath/java/lang/reflect/TypeVariable.java
Normal file
19
classpath/java/lang/reflect/TypeVariable.java
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
/* 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.reflect;
|
||||||
|
|
||||||
|
public interface TypeVariable<T extends GenericDeclaration>
|
||||||
|
extends Type
|
||||||
|
{
|
||||||
|
public Type[] getBounds();
|
||||||
|
public T getGenericDeclaration();
|
||||||
|
public String getName();
|
||||||
|
}
|
@ -1,4 +1,4 @@
|
|||||||
/* Copyright (c) 2008, Avian Contributors
|
/* Copyright (c) 2008-2009, Avian Contributors
|
||||||
|
|
||||||
Permission to use, copy, modify, and/or distribute this software
|
Permission to use, copy, modify, and/or distribute this software
|
||||||
for any purpose with or without fee is hereby granted, provided
|
for any purpose with or without fee is hereby granted, provided
|
||||||
@ -11,7 +11,6 @@
|
|||||||
package java.net;
|
package java.net;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.FileNotFoundException;
|
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
|
|
||||||
public final class URL {
|
public final class URL {
|
||||||
@ -73,7 +72,7 @@ public final class URL {
|
|||||||
throws MalformedURLException
|
throws MalformedURLException
|
||||||
{
|
{
|
||||||
if ("resource".equals(protocol)) {
|
if ("resource".equals(protocol)) {
|
||||||
return new ResourceHandler();
|
return new avian.resource.Handler();
|
||||||
} else {
|
} else {
|
||||||
throw new MalformedURLException("unknown protocol: " + protocol);
|
throw new MalformedURLException("unknown protocol: " + protocol);
|
||||||
}
|
}
|
||||||
@ -88,87 +87,4 @@ public final class URL {
|
|||||||
this.file = file;
|
this.file = file;
|
||||||
this.ref = ref;
|
this.ref = ref;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class ResourceHandler extends URLStreamHandler {
|
|
||||||
protected URLConnection openConnection(URL url) {
|
|
||||||
return new ResourceConnection(url);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static class ResourceConnection extends URLConnection {
|
|
||||||
public ResourceConnection(URL url) {
|
|
||||||
super(url);
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getContentLength() {
|
|
||||||
return ResourceInputStream.getContentLength(url.getFile());
|
|
||||||
}
|
|
||||||
|
|
||||||
public InputStream getInputStream() throws IOException {
|
|
||||||
return new ResourceInputStream(url.getFile());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static class ResourceInputStream extends InputStream {
|
|
||||||
private long peer;
|
|
||||||
private int position;
|
|
||||||
|
|
||||||
public ResourceInputStream(String path) throws IOException {
|
|
||||||
peer = open(path);
|
|
||||||
if (peer == 0) {
|
|
||||||
throw new FileNotFoundException(path);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static native int getContentLength(String path);
|
|
||||||
|
|
||||||
private static native long open(String path) throws IOException;
|
|
||||||
|
|
||||||
private static native int read(long peer, int position) throws IOException;
|
|
||||||
|
|
||||||
private static native int read(long peer, int position,
|
|
||||||
byte[] b, int offset, int length)
|
|
||||||
throws IOException;
|
|
||||||
|
|
||||||
public static native void close(long peer) throws IOException;
|
|
||||||
|
|
||||||
public int read() throws IOException {
|
|
||||||
if (peer != 0) {
|
|
||||||
int c = read(peer, position);
|
|
||||||
if (c >= 0) {
|
|
||||||
++ position;
|
|
||||||
}
|
|
||||||
return c;
|
|
||||||
} else {
|
|
||||||
throw new IOException();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public int read(byte[] b, int offset, int length) throws IOException {
|
|
||||||
if (peer != 0) {
|
|
||||||
if (b == null) {
|
|
||||||
throw new NullPointerException();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (offset < 0 || offset + length > b.length) {
|
|
||||||
throw new ArrayIndexOutOfBoundsException();
|
|
||||||
}
|
|
||||||
|
|
||||||
int c = read(peer, position, b, offset, length);
|
|
||||||
if (c >= 0) {
|
|
||||||
position += c;
|
|
||||||
}
|
|
||||||
return c;
|
|
||||||
} else {
|
|
||||||
throw new IOException();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void close() throws IOException {
|
|
||||||
if (peer != 0) {
|
|
||||||
close(peer);
|
|
||||||
peer = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
13
classpath/java/security/AllPermission.java
Normal file
13
classpath/java/security/AllPermission.java
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
/* 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.security;
|
||||||
|
|
||||||
|
public class AllPermission extends Permission { }
|
13
classpath/java/security/CodeSource.java
Normal file
13
classpath/java/security/CodeSource.java
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
/* 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.security;
|
||||||
|
|
||||||
|
public class CodeSource { }
|
17
classpath/java/security/Permission.java
Normal file
17
classpath/java/security/Permission.java
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
/* 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.security;
|
||||||
|
|
||||||
|
public abstract class Permission {
|
||||||
|
public PermissionCollection newPermissionCollection() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
15
classpath/java/security/PermissionCollection.java
Normal file
15
classpath/java/security/PermissionCollection.java
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
/* 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.security;
|
||||||
|
|
||||||
|
public abstract class PermissionCollection {
|
||||||
|
public abstract void add(Permission p);
|
||||||
|
}
|
41
classpath/java/security/Permissions.java
Normal file
41
classpath/java/security/Permissions.java
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
/* 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.security;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.HashSet;
|
||||||
|
|
||||||
|
public class Permissions extends PermissionCollection {
|
||||||
|
private final Map<Class,PermissionCollection> collections = new HashMap();
|
||||||
|
|
||||||
|
public void add(Permission p) {
|
||||||
|
Class c = p.getClass();
|
||||||
|
PermissionCollection pc = collections.get(c);
|
||||||
|
if (pc == null) {
|
||||||
|
pc = p.newPermissionCollection();
|
||||||
|
if (pc == null) {
|
||||||
|
pc = new MyPermissionCollection();
|
||||||
|
}
|
||||||
|
collections.put(c, pc);
|
||||||
|
}
|
||||||
|
pc.add(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class MyPermissionCollection extends PermissionCollection {
|
||||||
|
private final Set<Permission> permissions = new HashSet();
|
||||||
|
|
||||||
|
public void add(Permission p) {
|
||||||
|
permissions.add(p);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
23
classpath/java/security/ProtectionDomain.java
Normal file
23
classpath/java/security/ProtectionDomain.java
Normal 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.security;
|
||||||
|
|
||||||
|
public class ProtectionDomain {
|
||||||
|
private final CodeSource codeSource;
|
||||||
|
private final PermissionCollection permissions;
|
||||||
|
|
||||||
|
public ProtectionDomain(CodeSource codeSource,
|
||||||
|
PermissionCollection permissions)
|
||||||
|
{
|
||||||
|
this.codeSource = codeSource;
|
||||||
|
this.permissions = permissions;
|
||||||
|
}
|
||||||
|
}
|
@ -1,4 +1,4 @@
|
|||||||
/* Copyright (c) 2008, Avian Contributors
|
/* Copyright (c) 2009, Avian Contributors
|
||||||
|
|
||||||
Permission to use, copy, modify, and/or distribute this software
|
Permission to use, copy, modify, and/or distribute this software
|
||||||
for any purpose with or without fee is hereby granted, provided
|
for any purpose with or without fee is hereby granted, provided
|
||||||
@ -10,6 +10,9 @@
|
|||||||
|
|
||||||
package java.util;
|
package java.util;
|
||||||
|
|
||||||
|
import avian.PersistentSet;
|
||||||
|
import avian.Cell;
|
||||||
|
|
||||||
public class TreeSet<T> extends AbstractSet<T> implements Collection<T> {
|
public class TreeSet<T> extends AbstractSet<T> implements Collection<T> {
|
||||||
private PersistentSet<Cell<T>> set;
|
private PersistentSet<Cell<T>> set;
|
||||||
private int size;
|
private int size;
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/* Copyright (c) 2008, Avian Contributors
|
/* Copyright (c) 2008-2009, Avian Contributors
|
||||||
|
|
||||||
Permission to use, copy, modify, and/or distribute this software
|
Permission to use, copy, modify, and/or distribute this software
|
||||||
for any purpose with or without fee is hereby granted, provided
|
for any purpose with or without fee is hereby granted, provided
|
||||||
@ -63,7 +63,7 @@ public class ZipFile {
|
|||||||
return index.size();
|
return index.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Enumeration<ZipEntry> entries() {
|
public Enumeration<? extends ZipEntry> entries() {
|
||||||
return new MyEnumeration(window, index.values().iterator());
|
return new MyEnumeration(window, index.values().iterator());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
148
makefile
148
makefile
@ -18,10 +18,6 @@ bootimage-platform = \
|
|||||||
$(subst cygwin,windows,$(subst mingw32,windows,$(build-platform)))
|
$(subst cygwin,windows,$(subst mingw32,windows,$(build-platform)))
|
||||||
platform = $(bootimage-platform)
|
platform = $(bootimage-platform)
|
||||||
|
|
||||||
ifeq ($(platform),windows)
|
|
||||||
arch = i386
|
|
||||||
endif
|
|
||||||
|
|
||||||
mode = fast
|
mode = fast
|
||||||
process = compile
|
process = compile
|
||||||
|
|
||||||
@ -43,6 +39,23 @@ endif
|
|||||||
ifeq ($(continuations),true)
|
ifeq ($(continuations),true)
|
||||||
options := $(options)-continuations
|
options := $(options)-continuations
|
||||||
endif
|
endif
|
||||||
|
ifdef gnu
|
||||||
|
options := $(options)-gnu
|
||||||
|
gnu-sources = $(src)/gnu.cpp
|
||||||
|
gnu-jar = $(gnu)/share/classpath/glibj.zip
|
||||||
|
gnu-libraries = \
|
||||||
|
$(gnu)/lib/classpath/libjavaio.a \
|
||||||
|
$(gnu)/lib/classpath/libjavalang.a \
|
||||||
|
$(gnu)/lib/classpath/libjavalangreflect.a \
|
||||||
|
$(gnu)/lib/classpath/libjavamath.a \
|
||||||
|
$(gnu)/lib/classpath/libjavanet.a \
|
||||||
|
$(gnu)/lib/classpath/libjavanio.a \
|
||||||
|
$(gnu)/lib/classpath/libjavautil.a
|
||||||
|
gnu-object-dep = $(build)/gnu-object.dep
|
||||||
|
gnu-cflags = -DBOOT_BUILTINS=\"javaio,javalang,javalangreflect,javamath,javanet,javanio,javautil\" -DAVIAN_GNU
|
||||||
|
gnu-lflags = -lgmp
|
||||||
|
gnu-objects = $(shell find $(build)/gnu-objects -name "*.o")
|
||||||
|
endif
|
||||||
|
|
||||||
root = $(shell (cd .. && pwd))
|
root = $(shell (cd .. && pwd))
|
||||||
build = build
|
build = build
|
||||||
@ -53,6 +66,12 @@ src = src
|
|||||||
classpath = classpath
|
classpath = classpath
|
||||||
test = test
|
test = test
|
||||||
|
|
||||||
|
ifdef gnu
|
||||||
|
avian-classpath-build = $(build)/avian-classpath
|
||||||
|
else
|
||||||
|
avian-classpath-build = $(classpath-build)
|
||||||
|
endif
|
||||||
|
|
||||||
input = List
|
input = List
|
||||||
|
|
||||||
build-cxx = g++
|
build-cxx = g++
|
||||||
@ -83,13 +102,14 @@ warnings = -Wall -Wextra -Werror -Wunused-parameter -Winit-self \
|
|||||||
common-cflags = $(warnings) -fno-rtti -fno-exceptions -fno-omit-frame-pointer \
|
common-cflags = $(warnings) -fno-rtti -fno-exceptions -fno-omit-frame-pointer \
|
||||||
"-I$(JAVA_HOME)/include" -idirafter $(src) -I$(native-build) \
|
"-I$(JAVA_HOME)/include" -idirafter $(src) -I$(native-build) \
|
||||||
-D__STDC_LIMIT_MACROS -D_JNI_IMPLEMENTATION_ -DAVIAN_VERSION=\"$(version)\" \
|
-D__STDC_LIMIT_MACROS -D_JNI_IMPLEMENTATION_ -DAVIAN_VERSION=\"$(version)\" \
|
||||||
|
$(gnu-cflags)
|
||||||
|
|
||||||
build-cflags = $(common-cflags) -fPIC -fvisibility=hidden \
|
build-cflags = $(common-cflags) -fPIC -fvisibility=hidden \
|
||||||
"-I$(JAVA_HOME)/include/linux" -I$(src) -pthread
|
"-I$(JAVA_HOME)/include/linux" -I$(src) -pthread
|
||||||
|
|
||||||
cflags = $(build-cflags)
|
cflags = $(build-cflags)
|
||||||
|
|
||||||
common-lflags = -lm -lz
|
common-lflags = -lm -lz $(gnu-lflags)
|
||||||
|
|
||||||
build-lflags =
|
build-lflags =
|
||||||
|
|
||||||
@ -167,6 +187,21 @@ ifeq ($(platform),windows)
|
|||||||
native-path = cygpath -m
|
native-path = cygpath -m
|
||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
ifeq ($(arch),x86_64)
|
||||||
|
cxx = x86_64-pc-mingw32-g++
|
||||||
|
cc = x86_64-pc-mingw32-gcc
|
||||||
|
dlltool = x86_64-pc-mingw32-dlltool
|
||||||
|
ar = x86_64-pc-mingw32-ar
|
||||||
|
ranlib = x86_64-pc-mingw32-ranlib
|
||||||
|
objcopy = x86_64-pc-mingw32-objcopy
|
||||||
|
strip = :
|
||||||
|
inc = "$(root)/win64/include"
|
||||||
|
lib = "$(root)/win64/lib"
|
||||||
|
pointer-size = 8
|
||||||
|
object-format = pe-x86-64
|
||||||
|
endif
|
||||||
|
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifeq ($(mode),debug)
|
ifeq ($(mode),debug)
|
||||||
@ -232,7 +267,8 @@ vm-sources = \
|
|||||||
$(src)/$(process).cpp \
|
$(src)/$(process).cpp \
|
||||||
$(src)/builtin.cpp \
|
$(src)/builtin.cpp \
|
||||||
$(src)/jnienv.cpp \
|
$(src)/jnienv.cpp \
|
||||||
$(src)/process.cpp
|
$(src)/process.cpp \
|
||||||
|
$(gnu-sources)
|
||||||
|
|
||||||
vm-asm-sources = $(src)/$(asm).S
|
vm-asm-sources = $(src)/$(asm).S
|
||||||
|
|
||||||
@ -314,16 +350,43 @@ classpath-sources = $(shell find $(classpath) -name '*.java')
|
|||||||
classpath-classes = \
|
classpath-classes = \
|
||||||
$(call java-classes,$(classpath-sources),$(classpath),$(classpath-build))
|
$(call java-classes,$(classpath-sources),$(classpath),$(classpath-build))
|
||||||
classpath-object = $(native-build)/classpath-jar.o
|
classpath-object = $(native-build)/classpath-jar.o
|
||||||
classpath-dep = $(classpath-build)/dep
|
classpath-dep = $(classpath-build).dep
|
||||||
|
|
||||||
|
gnu-blacklist = \
|
||||||
|
java/lang/AbstractStringBuffer.class \
|
||||||
|
java/lang/reflect/Proxy.class
|
||||||
|
|
||||||
|
gnu-overrides = \
|
||||||
|
avian/*.class \
|
||||||
|
avian/resource/*.class \
|
||||||
|
java/lang/Class.class \
|
||||||
|
java/lang/Enum.class \
|
||||||
|
java/lang/InheritableThreadLocal.class \
|
||||||
|
java/lang/Object.class \
|
||||||
|
java/lang/StackTraceElement.class \
|
||||||
|
java/lang/String*.class \
|
||||||
|
java/lang/StringBuffer.class \
|
||||||
|
java/lang/StringBuilder.class \
|
||||||
|
java/lang/Thread.class \
|
||||||
|
java/lang/ThreadLocal.class \
|
||||||
|
java/lang/Throwable.class \
|
||||||
|
java/lang/ref/PhantomReference.class \
|
||||||
|
java/lang/ref/Reference.class \
|
||||||
|
java/lang/ref/ReferenceQueue.class \
|
||||||
|
java/lang/ref/WeakReference.class \
|
||||||
|
java/lang/reflect/AccessibleObject.class \
|
||||||
|
java/lang/reflect/Constructor.class \
|
||||||
|
java/lang/reflect/Field.class \
|
||||||
|
java/lang/reflect/Method.class
|
||||||
|
|
||||||
test-sources = $(wildcard $(test)/*.java)
|
test-sources = $(wildcard $(test)/*.java)
|
||||||
test-classes = $(call java-classes,$(test-sources),$(test),$(test-build))
|
test-classes = $(call java-classes,$(test-sources),$(test),$(test-build))
|
||||||
test-dep = $(test-build)/dep
|
test-dep = $(test-build).dep
|
||||||
|
|
||||||
test-extra-sources = $(wildcard $(test)/extra/*.java)
|
test-extra-sources = $(wildcard $(test)/extra/*.java)
|
||||||
test-extra-classes = \
|
test-extra-classes = \
|
||||||
$(call java-classes,$(test-extra-sources),$(test),$(test-build))
|
$(call java-classes,$(test-extra-sources),$(test),$(test-build))
|
||||||
test-extra-dep = $(test-build)/extra/dep
|
test-extra-dep = $(test-build)-extra.dep
|
||||||
|
|
||||||
class-name = $(patsubst $(1)/%.class,%,$(2))
|
class-name = $(patsubst $(1)/%.class,%,$(2))
|
||||||
class-names = $(foreach x,$(2),$(call class-name,$(1),$(x)))
|
class-names = $(foreach x,$(2),$(call class-name,$(1),$(x)))
|
||||||
@ -393,11 +456,24 @@ $(native-build)/type-generator.o: \
|
|||||||
$(classpath-build)/%.class: $(classpath)/%.java
|
$(classpath-build)/%.class: $(classpath)/%.java
|
||||||
@echo $(<)
|
@echo $(<)
|
||||||
|
|
||||||
$(classpath-dep): $(classpath-sources)
|
$(classpath-dep): $(classpath-sources) $(gnu-jar)
|
||||||
@echo "compiling classpath classes"
|
@echo "compiling classpath classes"
|
||||||
@mkdir -p $(dir $(@))
|
@mkdir -p $(avian-classpath-build)
|
||||||
$(javac) -d $(dir $(@)) -bootclasspath $(classpath-build) \
|
$(javac) -d $(avian-classpath-build) \
|
||||||
|
-bootclasspath $(avian-classpath-build) \
|
||||||
$(shell $(MAKE) -s --no-print-directory $(classpath-classes))
|
$(shell $(MAKE) -s --no-print-directory $(classpath-classes))
|
||||||
|
ifdef gnu
|
||||||
|
(wd=$$(pwd) && \
|
||||||
|
cd $(avian-classpath-build) && \
|
||||||
|
$(jar) c0f "$$($(native-path) "$${wd}/$(build)/overrides.jar")" \
|
||||||
|
$(gnu-overrides))
|
||||||
|
@mkdir -p $(classpath-build)
|
||||||
|
(wd=$$(pwd) && \
|
||||||
|
cd $(classpath-build) && \
|
||||||
|
$(jar) xf $(gnu-jar) && \
|
||||||
|
rm $(gnu-blacklist) && \
|
||||||
|
jar xf "$$($(native-path) "$${wd}/$(build)/overrides.jar")")
|
||||||
|
endif
|
||||||
@touch $(@)
|
@touch $(@)
|
||||||
|
|
||||||
$(test-build)/%.class: $(test)/%.java
|
$(test-build)/%.class: $(test)/%.java
|
||||||
@ -405,16 +481,16 @@ $(test-build)/%.class: $(test)/%.java
|
|||||||
|
|
||||||
$(test-dep): $(test-sources)
|
$(test-dep): $(test-sources)
|
||||||
@echo "compiling test classes"
|
@echo "compiling test classes"
|
||||||
@mkdir -p $(dir $(@))
|
@mkdir -p $(test-build)
|
||||||
$(javac) -d $(dir $(@)) -bootclasspath $(classpath-build) \
|
$(javac) -d $(test-build) -bootclasspath $(classpath-build) \
|
||||||
$(shell $(MAKE) -s --no-print-directory $(test-classes))
|
$(shell $(MAKE) -s --no-print-directory $(test-classes))
|
||||||
$(javac) -source 1.2 -target 1.1 -XDjsrlimit=0 -d $(dir $(@)) \
|
$(javac) -source 1.2 -target 1.1 -XDjsrlimit=0 -d $(test-build) \
|
||||||
test/Subroutine.java
|
test/Subroutine.java
|
||||||
@touch $(@)
|
@touch $(@)
|
||||||
|
|
||||||
$(test-extra-dep): $(test-extra-sources)
|
$(test-extra-dep): $(test-extra-sources)
|
||||||
@echo "compiling extra test classes"
|
@echo "compiling extra test classes"
|
||||||
@mkdir -p $(dir $(@))
|
@mkdir -p $(test-build)
|
||||||
$(javac) -d $(test-build) -bootclasspath $(classpath-build) \
|
$(javac) -d $(test-build) -bootclasspath $(classpath-build) \
|
||||||
$(shell $(MAKE) -s --no-print-directory $(test-extra-classes))
|
$(shell $(MAKE) -s --no-print-directory $(test-extra-classes))
|
||||||
@touch $(@)
|
@touch $(@)
|
||||||
@ -456,9 +532,9 @@ $(boot-object): $(boot-source)
|
|||||||
$(compile-object)
|
$(compile-object)
|
||||||
|
|
||||||
$(build)/classpath.jar: $(classpath-dep)
|
$(build)/classpath.jar: $(classpath-dep)
|
||||||
(wd=$$(pwd); \
|
(wd=$$(pwd) && \
|
||||||
cd $(classpath-build); \
|
cd $(classpath-build) && \
|
||||||
$(jar) c0f "$$($(native-path) "$${wd}/$(@)")" $$(find . -name '*.class'))
|
$(jar) c0f "$$($(native-path) "$${wd}/$(@)")" .)
|
||||||
|
|
||||||
$(binaryToMacho): $(src)/binaryToMacho.cpp
|
$(binaryToMacho): $(src)/binaryToMacho.cpp
|
||||||
$(cxx) $(^) -o $(@)
|
$(cxx) $(^) -o $(@)
|
||||||
@ -469,8 +545,8 @@ ifeq ($(platform),darwin)
|
|||||||
$(binaryToMacho) $(asm) $(build)/classpath.jar __TEXT __text \
|
$(binaryToMacho) $(asm) $(build)/classpath.jar __TEXT __text \
|
||||||
__binary_classpath_jar_start __binary_classpath_jar_end > $(@)
|
__binary_classpath_jar_start __binary_classpath_jar_end > $(@)
|
||||||
else
|
else
|
||||||
(wd=$$(pwd); \
|
(wd=$$(pwd) && \
|
||||||
cd $(build); \
|
cd $(build) && \
|
||||||
$(objcopy) -I binary classpath.jar \
|
$(objcopy) -I binary classpath.jar \
|
||||||
-O $(object-format) -B $(object-arch) "$${wd}/$(@)")
|
-O $(object-format) -B $(object-arch) "$${wd}/$(@)")
|
||||||
endif
|
endif
|
||||||
@ -484,10 +560,11 @@ $(generator-objects): $(native-build)/%.o: $(src)/%.cpp
|
|||||||
$(jni-objects): $(native-build)/%.o: $(classpath)/%.cpp
|
$(jni-objects): $(native-build)/%.o: $(classpath)/%.cpp
|
||||||
$(compile-object)
|
$(compile-object)
|
||||||
|
|
||||||
|
$(static-library): $(gnu-object-dep)
|
||||||
$(static-library): $(vm-objects) $(jni-objects) $(vm-heapwalk-objects)
|
$(static-library): $(vm-objects) $(jni-objects) $(vm-heapwalk-objects)
|
||||||
@echo "creating $(@)"
|
@echo "creating $(@)"
|
||||||
rm -rf $(@)
|
rm -rf $(@)
|
||||||
$(ar) cru $(@) $(^)
|
$(ar) cru $(@) $(^) $(call gnu-objects)
|
||||||
$(ranlib) $(@)
|
$(ranlib) $(@)
|
||||||
|
|
||||||
$(bootimage-bin): $(bootimage-generator)
|
$(bootimage-bin): $(bootimage-generator)
|
||||||
@ -499,24 +576,32 @@ ifeq ($(platform),darwin)
|
|||||||
$(binaryToMacho) $(asm) $(<) __BOOT __boot \
|
$(binaryToMacho) $(asm) $(<) __BOOT __boot \
|
||||||
__binary_bootimage_bin_start __binary_bootimage_bin_end > $(@)
|
__binary_bootimage_bin_start __binary_bootimage_bin_end > $(@)
|
||||||
else
|
else
|
||||||
(wd=$$(pwd); \
|
(wd=$$(pwd) && \
|
||||||
cd $(native-build); \
|
cd $(native-build) && \
|
||||||
$(objcopy) --rename-section=.data=.boot -I binary bootimage.bin \
|
$(objcopy) --rename-section=.data=.boot -I binary bootimage.bin \
|
||||||
-O $(object-format) -B $(object-arch) "$${wd}/$(@).tmp"; \
|
-O $(object-format) -B $(object-arch) "$${wd}/$(@).tmp" && \
|
||||||
$(objcopy) --set-section-flags .boot=alloc,load,code "$${wd}/$(@).tmp" \
|
$(objcopy) --set-section-flags .boot=alloc,load,code "$${wd}/$(@).tmp" \
|
||||||
"$${wd}/$(@)")
|
"$${wd}/$(@)")
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
$(gnu-object-dep): $(gnu-libraries)
|
||||||
|
@mkdir -p $(build)/gnu-objects
|
||||||
|
(cd $(build)/gnu-objects && \
|
||||||
|
for x in $(gnu-libraries); do ar x $${x}; done)
|
||||||
|
@touch $(@)
|
||||||
|
|
||||||
|
$(executable): $(gnu-object-dep)
|
||||||
$(executable): \
|
$(executable): \
|
||||||
$(vm-objects) $(jni-objects) $(driver-object) $(vm-heapwalk-objects) \
|
$(vm-objects) $(jni-objects) $(driver-object) $(vm-heapwalk-objects) \
|
||||||
$(boot-object) $(vm-classpath-object)
|
$(boot-object) $(vm-classpath-object)
|
||||||
@echo "linking $(@)"
|
@echo "linking $(@)"
|
||||||
ifeq ($(platform),windows)
|
ifeq ($(platform),windows)
|
||||||
$(dlltool) -z $(@).def $(^)
|
$(dlltool) -z $(@).def $(^) $(call gnu-objects)
|
||||||
$(dlltool) -d $(@).def -e $(@).exp
|
$(dlltool) -d $(@).def -e $(@).exp
|
||||||
$(cc) $(@).exp $(^) $(lflags) -o $(@)
|
$(cc) $(@).exp $(^) $(call gnu-objects) $(lflags) -o $(@)
|
||||||
else
|
else
|
||||||
$(cc) $(^) $(rdynamic) $(lflags) $(bootimage-lflags) -o $(@)
|
$(cc) $(^) $(call gnu-objects) $(rdynamic) $(lflags) $(bootimage-lflags) \
|
||||||
|
-o $(@)
|
||||||
endif
|
endif
|
||||||
$(strip) $(strip-all) $(@)
|
$(strip) $(strip-all) $(@)
|
||||||
|
|
||||||
@ -545,11 +630,13 @@ else
|
|||||||
$(cc) $(^) $(rdynamic) $(lflags) -o $(@)
|
$(cc) $(^) $(rdynamic) $(lflags) -o $(@)
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
$(dynamic-library): $(gnu-object-dep)
|
||||||
$(dynamic-library): \
|
$(dynamic-library): \
|
||||||
$(vm-objects) $(dynamic-object) $(jni-objects) $(vm-heapwalk-objects) \
|
$(vm-objects) $(dynamic-object) $(jni-objects) $(vm-heapwalk-objects) \
|
||||||
$(boot-object) $(vm-classpath-object)
|
$(boot-object) $(vm-classpath-object) $(gnu-libraries)
|
||||||
@echo "linking $(@)"
|
@echo "linking $(@)"
|
||||||
$(cc) $(^) $(shared) $(lflags) $(bootimage-lflags) -o $(@)
|
$(cc) $(^) $(call gnu-objects) $(shared) $(lflags) $(bootimage-lflags) \
|
||||||
|
-o $(@)
|
||||||
$(strip) $(strip-all) $(@)
|
$(strip) $(strip-all) $(@)
|
||||||
|
|
||||||
$(executable-dynamic): $(driver-dynamic-object) $(dynamic-library)
|
$(executable-dynamic): $(driver-dynamic-object) $(dynamic-library)
|
||||||
@ -560,4 +647,3 @@ $(executable-dynamic): $(driver-dynamic-object) $(dynamic-library)
|
|||||||
$(generator): $(generator-objects)
|
$(generator): $(generator-objects)
|
||||||
@echo "linking $(@)"
|
@echo "linking $(@)"
|
||||||
$(build-cc) $(^) $(build-lflags) -o $(@)
|
$(build-cc) $(^) $(build-lflags) -o $(@)
|
||||||
|
|
||||||
|
@ -303,6 +303,10 @@ writeBootImage(Thread* t, FILE* out, BootImage* image, uint8_t* code,
|
|||||||
(t->m->heap->allocate(heapMapSize(HeapCapacity)));
|
(t->m->heap->allocate(heapMapSize(HeapCapacity)));
|
||||||
memset(heapMap, 0, heapMapSize(HeapCapacity));
|
memset(heapMap, 0, heapMapSize(HeapCapacity));
|
||||||
|
|
||||||
|
// this map will not be used when the bootimage is loaded, so
|
||||||
|
// there's no need to preserve it:
|
||||||
|
t->m->byteArrayMap = makeWeakHashMap(t, 0, 0);
|
||||||
|
|
||||||
collect(t, Heap::MajorCollection);
|
collect(t, Heap::MajorCollection);
|
||||||
|
|
||||||
HeapWalker* heapWalker = makeHeapImage
|
HeapWalker* heapWalker = makeHeapImage
|
||||||
|
@ -63,6 +63,25 @@ enumerateThreads(Thread* t, Thread* x, object array, unsigned* index,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
compatibleArrayTypes(Thread* t, object a, object b)
|
||||||
|
{
|
||||||
|
return classArrayElementSize(t, a)
|
||||||
|
and classArrayElementSize(t, b)
|
||||||
|
and (a == b
|
||||||
|
or (not ((classVmFlags(t, a) & PrimitiveFlag)
|
||||||
|
or (classVmFlags(t, b) & PrimitiveFlag))));
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
runOnLoadIfFound(Thread* t, System::Library* library)
|
||||||
|
{
|
||||||
|
void* p = library->resolve("JNI_OnLoad");
|
||||||
|
if (p) {
|
||||||
|
reinterpret_cast<jint (JNICALL *)(Machine*, void*)>(p)(t->m, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
extern "C" JNIEXPORT int64_t JNICALL
|
extern "C" JNIEXPORT int64_t JNICALL
|
||||||
@ -530,7 +549,9 @@ Avian_java_lang_System_arraycopy
|
|||||||
int32_t length = arguments[4];
|
int32_t length = arguments[4];
|
||||||
|
|
||||||
if (LIKELY(src and dst)) {
|
if (LIKELY(src and dst)) {
|
||||||
if (LIKELY(objectClass(t, src) == objectClass(t, dst))) {
|
if (LIKELY(compatibleArrayTypes
|
||||||
|
(t, objectClass(t, src), objectClass(t, dst))))
|
||||||
|
{
|
||||||
unsigned elementSize = classArrayElementSize(t, objectClass(t, src));
|
unsigned elementSize = classArrayElementSize(t, objectClass(t, src));
|
||||||
|
|
||||||
if (LIKELY(elementSize)) {
|
if (LIKELY(elementSize)) {
|
||||||
@ -602,6 +623,10 @@ Avian_java_lang_Runtime_load
|
|||||||
and (s[length] == ',' or s[length] == 0))
|
and (s[length] == ',' or s[length] == 0))
|
||||||
{
|
{
|
||||||
// library is built in to this executable
|
// library is built in to this executable
|
||||||
|
if (not t->m->triedBuiltinOnLoad) {
|
||||||
|
t->m->triedBuiltinOnLoad = true;
|
||||||
|
runOnLoadIfFound(t, t->m->libraries);
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
while (*s and *s != ',') ++ s;
|
while (*s and *s != ',') ++ s;
|
||||||
@ -625,6 +650,7 @@ Avian_java_lang_Runtime_load
|
|||||||
System::Library* lib;
|
System::Library* lib;
|
||||||
if (LIKELY(t->m->system->success(t->m->system->load(&lib, n, mapName)))) {
|
if (LIKELY(t->m->system->success(t->m->system->load(&lib, n, mapName)))) {
|
||||||
last->setNext(lib);
|
last->setNext(lib);
|
||||||
|
runOnLoadIfFound(t, lib);
|
||||||
} else {
|
} else {
|
||||||
object message = makeString(t, "library not found: %s", n);
|
object message = makeString(t, "library not found: %s", n);
|
||||||
t->exception = makeUnsatisfiedLinkError(t, message);
|
t->exception = makeUnsatisfiedLinkError(t, message);
|
||||||
@ -836,7 +862,7 @@ Avian_java_lang_Thread_enumerate
|
|||||||
}
|
}
|
||||||
|
|
||||||
extern "C" JNIEXPORT int64_t JNICALL
|
extern "C" JNIEXPORT int64_t JNICALL
|
||||||
Avian_java_net_URL_00024ResourceInputStream_getContentLength
|
Avian_avian_resource_Handler_00024ResourceInputStream_getContentLength
|
||||||
(Thread* t, object, uintptr_t* arguments)
|
(Thread* t, object, uintptr_t* arguments)
|
||||||
{
|
{
|
||||||
object path = reinterpret_cast<object>(*arguments);
|
object path = reinterpret_cast<object>(*arguments);
|
||||||
@ -856,7 +882,7 @@ Avian_java_net_URL_00024ResourceInputStream_getContentLength
|
|||||||
}
|
}
|
||||||
|
|
||||||
extern "C" JNIEXPORT int64_t JNICALL
|
extern "C" JNIEXPORT int64_t JNICALL
|
||||||
Avian_java_net_URL_00024ResourceInputStream_open
|
Avian_avian_resource_Handler_00024ResourceInputStream_open
|
||||||
(Thread* t, object, uintptr_t* arguments)
|
(Thread* t, object, uintptr_t* arguments)
|
||||||
{
|
{
|
||||||
object path = reinterpret_cast<object>(*arguments);
|
object path = reinterpret_cast<object>(*arguments);
|
||||||
@ -873,7 +899,7 @@ Avian_java_net_URL_00024ResourceInputStream_open
|
|||||||
}
|
}
|
||||||
|
|
||||||
extern "C" JNIEXPORT int64_t JNICALL
|
extern "C" JNIEXPORT int64_t JNICALL
|
||||||
Avian_java_net_URL_00024ResourceInputStream_read__JI
|
Avian_avian_resource_Handler_00024ResourceInputStream_read__JI
|
||||||
(Thread*, object, uintptr_t* arguments)
|
(Thread*, object, uintptr_t* arguments)
|
||||||
{
|
{
|
||||||
int64_t peer; memcpy(&peer, arguments, 8);
|
int64_t peer; memcpy(&peer, arguments, 8);
|
||||||
@ -888,7 +914,7 @@ Avian_java_net_URL_00024ResourceInputStream_read__JI
|
|||||||
}
|
}
|
||||||
|
|
||||||
extern "C" JNIEXPORT int64_t JNICALL
|
extern "C" JNIEXPORT int64_t JNICALL
|
||||||
Avian_java_net_URL_00024ResourceInputStream_read__JI_3BII
|
Avian_avian_resource_Handler_00024ResourceInputStream_read__JI_3BII
|
||||||
(Thread* t, object, uintptr_t* arguments)
|
(Thread* t, object, uintptr_t* arguments)
|
||||||
{
|
{
|
||||||
int64_t peer; memcpy(&peer, arguments, 8);
|
int64_t peer; memcpy(&peer, arguments, 8);
|
||||||
@ -913,7 +939,7 @@ Avian_java_net_URL_00024ResourceInputStream_read__JI_3BII
|
|||||||
}
|
}
|
||||||
|
|
||||||
extern "C" JNIEXPORT void JNICALL
|
extern "C" JNIEXPORT void JNICALL
|
||||||
Avian_java_net_URL_00024ResourceInputStream_close
|
Avian_avian_resource_Handler_00024ResourceInputStream_close
|
||||||
(Thread*, object, uintptr_t* arguments)
|
(Thread*, object, uintptr_t* arguments)
|
||||||
{
|
{
|
||||||
int64_t peer; memcpy(&peer, arguments, 8);
|
int64_t peer; memcpy(&peer, arguments, 8);
|
||||||
|
16
src/common.h
16
src/common.h
@ -40,10 +40,17 @@
|
|||||||
# define ULD "u"
|
# define ULD "u"
|
||||||
#endif
|
#endif
|
||||||
#elif defined __x86_64__
|
#elif defined __x86_64__
|
||||||
# define LD "ld"
|
# ifdef __MINGW32__
|
||||||
# define LX "lx"
|
# define LD "I64d"
|
||||||
# define LLD "ld"
|
# define LX "I64x"
|
||||||
# define ULD "lu"
|
# define LLD "I64d"
|
||||||
|
# define ULD "I64x"
|
||||||
|
# else
|
||||||
|
# define LD "ld"
|
||||||
|
# define LX "lx"
|
||||||
|
# define LLD "ld"
|
||||||
|
# define ULD "lu"
|
||||||
|
# endif
|
||||||
#else
|
#else
|
||||||
# error "Unsupported architecture"
|
# error "Unsupported architecture"
|
||||||
#endif
|
#endif
|
||||||
@ -115,7 +122,6 @@ pad(unsigned n)
|
|||||||
return pad(n, BytesPerWord);
|
return pad(n, BytesPerWord);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
inline unsigned
|
inline unsigned
|
||||||
ceiling(unsigned n, unsigned d)
|
ceiling(unsigned n, unsigned d)
|
||||||
{
|
{
|
||||||
|
@ -22,18 +22,139 @@
|
|||||||
|
|
||||||
#ifdef __x86_64__
|
#ifdef __x86_64__
|
||||||
|
|
||||||
#define THREAD_CONTINUATION 168
|
#ifdef __MINGW32__
|
||||||
#define THREAD_EXCEPTION 64
|
|
||||||
#define THREAD_EXCEPTION_STACK_ADJUSTMENT 176
|
|
||||||
#define THREAD_EXCEPTION_OFFSET 184
|
|
||||||
#define THREAD_EXCEPTION_HANDLER 192
|
|
||||||
|
|
||||||
#define CONTINUATION_NEXT 8
|
#define CALLEE_SAVED_REGISTER_FOOTPRINT 64
|
||||||
#define CONTINUATION_ADDRESS 32
|
|
||||||
#define CONTINUATION_RETURN_ADDRESS_OFFSET 40
|
.globl GLOBAL(vmInvoke)
|
||||||
#define CONTINUATION_FRAME_POINTER_OFFSET 48
|
GLOBAL(vmInvoke):
|
||||||
#define CONTINUATION_LENGTH 56
|
pushq %rbp
|
||||||
#define CONTINUATION_BODY 64
|
movq %rsp,%rbp
|
||||||
|
|
||||||
|
// %rcx: thread
|
||||||
|
// %rdx: function
|
||||||
|
// %r8 : arguments
|
||||||
|
// %r9 : argumentsFootprint
|
||||||
|
// 48(%rbp) : frameSize
|
||||||
|
// 56(%rbp) : returnType (ignored)
|
||||||
|
|
||||||
|
// allocate stack space, adding room for callee-saved registers
|
||||||
|
movl 48(%rbp),%eax
|
||||||
|
subq %rax,%rsp
|
||||||
|
subq $CALLEE_SAVED_REGISTER_FOOTPRINT,%rsp
|
||||||
|
|
||||||
|
// save callee-saved registers
|
||||||
|
movq %rsp,%r11
|
||||||
|
addq %rax,%r11
|
||||||
|
|
||||||
|
movq %rbx,0(%r11)
|
||||||
|
movq %r12,8(%r11)
|
||||||
|
movq %r13,16(%r11)
|
||||||
|
movq %r14,24(%r11)
|
||||||
|
movq %r15,32(%r11)
|
||||||
|
movq %rsi,40(%r11)
|
||||||
|
movq %rdi,48(%r11)
|
||||||
|
|
||||||
|
// we use rbx to hold the thread pointer, by convention
|
||||||
|
mov %rcx,%rbx
|
||||||
|
|
||||||
|
// copy arguments into place
|
||||||
|
movq $0,%r11
|
||||||
|
jmp LOCAL(vmInvoke_argumentTest)
|
||||||
|
|
||||||
|
LOCAL(vmInvoke_argumentLoop):
|
||||||
|
movq (%r8,%r11,1),%rsi
|
||||||
|
movq %rsi,(%rsp,%r11,1)
|
||||||
|
addq $8,%r11
|
||||||
|
|
||||||
|
LOCAL(vmInvoke_argumentTest):
|
||||||
|
cmpq %r9,%r11
|
||||||
|
jb LOCAL(vmInvoke_argumentLoop)
|
||||||
|
|
||||||
|
// call function
|
||||||
|
call *%rdx
|
||||||
|
|
||||||
|
.globl GLOBAL(vmInvoke_returnAddress)
|
||||||
|
GLOBAL(vmInvoke_returnAddress):
|
||||||
|
// restore stack pointer
|
||||||
|
movq %rbp,%rsp
|
||||||
|
|
||||||
|
#ifdef AVIAN_CONTINUATIONS
|
||||||
|
# include "continuations-x86.S"
|
||||||
|
#endif // AVIAN_CONTINUATIONS
|
||||||
|
|
||||||
|
// restore callee-saved registers (below the stack pointer, but in
|
||||||
|
// the red zone)
|
||||||
|
movq %rsp,%r11
|
||||||
|
subq $CALLEE_SAVED_REGISTER_FOOTPRINT,%r11
|
||||||
|
|
||||||
|
movq 0(%r11),%rbx
|
||||||
|
movq 8(%r11),%r12
|
||||||
|
movq 16(%r11),%r13
|
||||||
|
movq 24(%r11),%r14
|
||||||
|
movq 32(%r11),%r15
|
||||||
|
movq 40(%r11),%rsi
|
||||||
|
movq 48(%r11),%rdi
|
||||||
|
|
||||||
|
// return
|
||||||
|
popq %rbp
|
||||||
|
ret
|
||||||
|
|
||||||
|
.globl GLOBAL(vmJumpAndInvoke)
|
||||||
|
GLOBAL(vmJumpAndInvoke):
|
||||||
|
#ifdef AVIAN_CONTINUATIONS
|
||||||
|
// %rcx: thread
|
||||||
|
// %rdx: address
|
||||||
|
// %r8 : base
|
||||||
|
// %r9 : (unused)
|
||||||
|
// 8(%rsp): argumentFootprint
|
||||||
|
// 16(%rsp): arguments
|
||||||
|
// 24(%rsp): frameSize
|
||||||
|
|
||||||
|
movq %r8,%rbp
|
||||||
|
|
||||||
|
// restore (pseudo)-stack pointer (we don't want to touch the real
|
||||||
|
// stack pointer, since we haven't copied the arguments yet)
|
||||||
|
movq %rbp,%r9
|
||||||
|
|
||||||
|
// allocate new frame, adding room for callee-saved registers
|
||||||
|
movl 24(%rsp),%eax
|
||||||
|
subq %rax,%r9
|
||||||
|
subq $CALLEE_SAVED_REGISTER_FOOTPRINT,%r9
|
||||||
|
|
||||||
|
movq %rcx,%rbx
|
||||||
|
|
||||||
|
// set return address
|
||||||
|
movq vmInvoke_returnAddress@GOTPCREL(%rip),%r10
|
||||||
|
movq %r10,(%r9)
|
||||||
|
|
||||||
|
// copy arguments into place
|
||||||
|
movq $0,%r11
|
||||||
|
movq 16(%rsp),%r8
|
||||||
|
movq 8(%rsp),%rax
|
||||||
|
jmp LOCAL(vmJumpAndInvoke_argumentTest)
|
||||||
|
|
||||||
|
LOCAL(vmJumpAndInvoke_argumentLoop):
|
||||||
|
movq (%r8,%r11,1),%r10
|
||||||
|
movq %r10,8(%r9,%r11,1)
|
||||||
|
addq $8,%r11
|
||||||
|
|
||||||
|
LOCAL(vmJumpAndInvoke_argumentTest):
|
||||||
|
cmpq %rax,%r11
|
||||||
|
jb LOCAL(vmJumpAndInvoke_argumentLoop)
|
||||||
|
|
||||||
|
// the arguments have been copied, so we can set the real stack
|
||||||
|
// pointer now
|
||||||
|
movq %r9,%rsp
|
||||||
|
|
||||||
|
jmp *%rdx
|
||||||
|
#else // not AVIAN_CONTINUATIONS
|
||||||
|
// vmJumpAndInvoke should only be called when continuations are
|
||||||
|
// enabled
|
||||||
|
int3
|
||||||
|
#endif // not AVIAN_CONTINUATIONS
|
||||||
|
|
||||||
|
#else // not __MINGW32__
|
||||||
|
|
||||||
#define CALLEE_SAVED_REGISTER_FOOTPRINT 48
|
#define CALLEE_SAVED_REGISTER_FOOTPRINT 48
|
||||||
|
|
||||||
@ -88,65 +209,7 @@ GLOBAL(vmInvoke_returnAddress):
|
|||||||
movq %rbp,%rsp
|
movq %rbp,%rsp
|
||||||
|
|
||||||
#ifdef AVIAN_CONTINUATIONS
|
#ifdef AVIAN_CONTINUATIONS
|
||||||
// call the next continuation, if any
|
# include "continuations-x86.S"
|
||||||
movq THREAD_CONTINUATION(%rbx),%rcx
|
|
||||||
cmpq $0,%rcx
|
|
||||||
je LOCAL(vmInvoke_exit)
|
|
||||||
|
|
||||||
// allocate a frame of size (continuation.length * BYTES_PER_WORD)
|
|
||||||
// + CALLEE_SAVED_REGISTER_FOOTPRINT
|
|
||||||
movq CONTINUATION_LENGTH(%rcx),%rsi
|
|
||||||
shlq $3,%rsi
|
|
||||||
subq %rsi,%rsp
|
|
||||||
subq $CALLEE_SAVED_REGISTER_FOOTPRINT,%rsp
|
|
||||||
|
|
||||||
// copy the continuation body into the frame
|
|
||||||
leaq CONTINUATION_BODY(%rcx),%rdi
|
|
||||||
|
|
||||||
movq $0,%r9
|
|
||||||
jmp LOCAL(vmInvoke_continuationTest)
|
|
||||||
|
|
||||||
LOCAL(vmInvoke_continuationLoop):
|
|
||||||
movq (%rdi,%r9,1),%r8
|
|
||||||
movq %r8,(%rsp,%r9,1)
|
|
||||||
addq $8,%r9
|
|
||||||
|
|
||||||
LOCAL(vmInvoke_continuationTest):
|
|
||||||
cmpq %rsi,%r9
|
|
||||||
jb LOCAL(vmInvoke_continuationLoop)
|
|
||||||
|
|
||||||
// set the return address to vmInvoke_returnAddress
|
|
||||||
movq CONTINUATION_RETURN_ADDRESS_OFFSET(%rcx),%rdi
|
|
||||||
movq vmInvoke_returnAddress@GOTPCREL(%rip),%r10
|
|
||||||
movq %r10,(%rsp,%rdi,1)
|
|
||||||
|
|
||||||
// save the current base pointer in the frame and update it
|
|
||||||
movq CONTINUATION_FRAME_POINTER_OFFSET(%rcx),%rdi
|
|
||||||
movq %rbp,(%rsp,%rdi,1)
|
|
||||||
addq %rsp,%rdi
|
|
||||||
movq %rdi,%rbp
|
|
||||||
|
|
||||||
// consume the continuation
|
|
||||||
movq CONTINUATION_NEXT(%rcx),%rdi
|
|
||||||
movq %rdi,THREAD_CONTINUATION(%rbx)
|
|
||||||
|
|
||||||
// call the continuation unless we're handling an exception
|
|
||||||
movq THREAD_EXCEPTION(%rbx),%rsi
|
|
||||||
cmpq $0,%rsi
|
|
||||||
jne LOCAL(vmInvoke_handleException)
|
|
||||||
jmp *CONTINUATION_ADDRESS(%rcx)
|
|
||||||
|
|
||||||
LOCAL(vmInvoke_handleException):
|
|
||||||
// we're handling an exception - call the exception handler instead
|
|
||||||
movq $0,THREAD_EXCEPTION(%rbx)
|
|
||||||
movq THREAD_EXCEPTION_STACK_ADJUSTMENT(%rbx),%rdi
|
|
||||||
subq %rdi,%rsp
|
|
||||||
movq THREAD_EXCEPTION_OFFSET(%rbx),%rdi
|
|
||||||
movq %rsi,(%rsp,%rdi,1)
|
|
||||||
|
|
||||||
jmp *THREAD_EXCEPTION_HANDLER(%rbx)
|
|
||||||
|
|
||||||
LOCAL(vmInvoke_exit):
|
|
||||||
#endif // AVIAN_CONTINUATIONS
|
#endif // AVIAN_CONTINUATIONS
|
||||||
|
|
||||||
// restore callee-saved registers (below the stack pointer, but in
|
// restore callee-saved registers (below the stack pointer, but in
|
||||||
@ -216,21 +279,10 @@ LOCAL(vmJumpAndInvoke_argumentTest):
|
|||||||
int3
|
int3
|
||||||
#endif // not AVIAN_CONTINUATIONS
|
#endif // not AVIAN_CONTINUATIONS
|
||||||
|
|
||||||
|
#endif // not __MINGW32__
|
||||||
|
|
||||||
#elif defined __i386__
|
#elif defined __i386__
|
||||||
|
|
||||||
#define THREAD_CONTINUATION 96
|
|
||||||
#define THREAD_EXCEPTION 36
|
|
||||||
#define THREAD_EXCEPTION_STACK_ADJUSTMENT 100
|
|
||||||
#define THREAD_EXCEPTION_OFFSET 104
|
|
||||||
#define THREAD_EXCEPTION_HANDLER 108
|
|
||||||
|
|
||||||
#define CONTINUATION_NEXT 4
|
|
||||||
#define CONTINUATION_ADDRESS 16
|
|
||||||
#define CONTINUATION_RETURN_ADDRESS_OFFSET 20
|
|
||||||
#define CONTINUATION_FRAME_POINTER_OFFSET 24
|
|
||||||
#define CONTINUATION_LENGTH 28
|
|
||||||
#define CONTINUATION_BODY 32
|
|
||||||
|
|
||||||
#define CALLEE_SAVED_REGISTER_FOOTPRINT 16
|
#define CALLEE_SAVED_REGISTER_FOOTPRINT 16
|
||||||
|
|
||||||
.globl GLOBAL(vmInvoke)
|
.globl GLOBAL(vmInvoke)
|
||||||
@ -286,72 +338,7 @@ vmInvoke_returnAddress:
|
|||||||
movl %ecx,%esp
|
movl %ecx,%esp
|
||||||
|
|
||||||
#ifdef AVIAN_CONTINUATIONS
|
#ifdef AVIAN_CONTINUATIONS
|
||||||
// call the next continuation, if any
|
# include "continuations-x86.S"
|
||||||
movl THREAD_CONTINUATION(%ebx),%ecx
|
|
||||||
cmpl $0,%ecx
|
|
||||||
je LOCAL(vmInvoke_exit)
|
|
||||||
|
|
||||||
// allocate a frame of size (continuation.length * BYTES_PER_WORD)
|
|
||||||
movl CONTINUATION_LENGTH(%ecx),%esi
|
|
||||||
shll $2,%esi
|
|
||||||
subl %esi,%esp
|
|
||||||
|
|
||||||
// copy the continuation body into the frame
|
|
||||||
leal CONTINUATION_BODY(%ecx),%edi
|
|
||||||
|
|
||||||
push %eax
|
|
||||||
push %edx
|
|
||||||
|
|
||||||
movl $0,%edx
|
|
||||||
jmp LOCAL(vmInvoke_continuationTest)
|
|
||||||
|
|
||||||
LOCAL(vmInvoke_continuationLoop):
|
|
||||||
movl (%edi,%edx,1),%eax
|
|
||||||
movl %eax,8(%esp,%edx,1)
|
|
||||||
addl $4,%edx
|
|
||||||
|
|
||||||
LOCAL(vmInvoke_continuationTest):
|
|
||||||
cmpl %esi,%edx
|
|
||||||
jb LOCAL(vmInvoke_continuationLoop)
|
|
||||||
|
|
||||||
pop %edx
|
|
||||||
pop %eax
|
|
||||||
|
|
||||||
// set the return address to vmInvoke_returnAddress
|
|
||||||
movl CONTINUATION_RETURN_ADDRESS_OFFSET(%ecx),%edi
|
|
||||||
call LOCAL(getPC)
|
|
||||||
addl $_GLOBAL_OFFSET_TABLE_,%esi
|
|
||||||
movl vmInvoke_returnAddress@GOT(%esi),%esi
|
|
||||||
movl %esi,(%esp,%edi,1)
|
|
||||||
|
|
||||||
// save the current base pointer in the frame and update it
|
|
||||||
movl CONTINUATION_FRAME_POINTER_OFFSET(%ecx),%edi
|
|
||||||
movl %ebp,(%esp,%edi,1)
|
|
||||||
addl %esp,%edi
|
|
||||||
movl %edi,%ebp
|
|
||||||
|
|
||||||
// consume the continuation
|
|
||||||
movl CONTINUATION_NEXT(%ecx),%edi
|
|
||||||
movl %edi,THREAD_CONTINUATION(%ebx)
|
|
||||||
|
|
||||||
// call the continuation unless we're handling an exception
|
|
||||||
movl THREAD_EXCEPTION(%ebx),%esi
|
|
||||||
cmpl $0,%esi
|
|
||||||
jne LOCAL(vmInvoke_handleException)
|
|
||||||
|
|
||||||
jmp *CONTINUATION_ADDRESS(%ecx)
|
|
||||||
|
|
||||||
LOCAL(vmInvoke_handleException):
|
|
||||||
// we're handling an exception - call the exception handler instead
|
|
||||||
movl $0,THREAD_EXCEPTION(%ebx)
|
|
||||||
movl THREAD_EXCEPTION_STACK_ADJUSTMENT(%ebx),%edi
|
|
||||||
subl %edi,%esp
|
|
||||||
movl THREAD_EXCEPTION_OFFSET(%ebx),%edi
|
|
||||||
movl %esi,(%esp,%edi,1)
|
|
||||||
|
|
||||||
jmp *THREAD_EXCEPTION_HANDLER(%ebx)
|
|
||||||
|
|
||||||
LOCAL(vmInvoke_exit):
|
|
||||||
#endif // AVIAN_CONTINUATIONS
|
#endif // AVIAN_CONTINUATIONS
|
||||||
|
|
||||||
// restore callee-saved registers
|
// restore callee-saved registers
|
||||||
@ -443,5 +430,5 @@ LOCAL(vmJumpAndInvoke_argumentTest):
|
|||||||
#endif // AVIAN_CONTINUATIONS
|
#endif // AVIAN_CONTINUATIONS
|
||||||
|
|
||||||
#else
|
#else
|
||||||
# error unsupported platform
|
#error unsupported architecture
|
||||||
#endif
|
#endif //def __x86_64__
|
||||||
|
928
src/compile.cpp
928
src/compile.cpp
File diff suppressed because it is too large
Load Diff
@ -2052,7 +2052,7 @@ class MultiRead: public Read {
|
|||||||
}
|
}
|
||||||
lastRead = cell;
|
lastRead = cell;
|
||||||
|
|
||||||
// fprintf(stderr, "append %p to %p for %p\n", r, lastTarget, this);
|
// fprintf(stderr, "append %p to %p for %p\n", r, lastTarget, this);
|
||||||
|
|
||||||
lastTarget->value = r;
|
lastTarget->value = r;
|
||||||
}
|
}
|
||||||
@ -2064,7 +2064,7 @@ class MultiRead: public Read {
|
|||||||
void allocateTarget(Context* c) {
|
void allocateTarget(Context* c) {
|
||||||
Cell* cell = cons(c, 0, 0);
|
Cell* cell = cons(c, 0, 0);
|
||||||
|
|
||||||
// fprintf(stderr, "allocate target for %p: %p\n", this, cell);
|
// fprintf(stderr, "allocate target for %p: %p\n", this, cell);
|
||||||
|
|
||||||
if (lastTarget) {
|
if (lastTarget) {
|
||||||
lastTarget->next = cell;
|
lastTarget->next = cell;
|
||||||
@ -4016,6 +4016,31 @@ appendSaveLocals(Context* c)
|
|||||||
SaveLocalsEvent(c));
|
SaveLocalsEvent(c));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class CleanLocalsEvent: public Event {
|
||||||
|
public:
|
||||||
|
CleanLocalsEvent(Context* c):
|
||||||
|
Event(c)
|
||||||
|
{ }
|
||||||
|
|
||||||
|
virtual const char* name() {
|
||||||
|
return "CleanLocalsEvent";
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void compile(Context* c) {
|
||||||
|
for (FrameIterator it(c, 0, c->locals); it.hasMore();) {
|
||||||
|
FrameIterator::Element e = it.next(c);
|
||||||
|
clean(c, e.value, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
void
|
||||||
|
appendCleanLocals(Context* c)
|
||||||
|
{
|
||||||
|
append(c, new (c->zone->allocate(sizeof(CleanLocalsEvent)))
|
||||||
|
CleanLocalsEvent(c));
|
||||||
|
}
|
||||||
|
|
||||||
class DummyEvent: public Event {
|
class DummyEvent: public Event {
|
||||||
public:
|
public:
|
||||||
DummyEvent(Context* c):
|
DummyEvent(Context* c):
|
||||||
@ -4927,11 +4952,12 @@ class MyCompiler: public Compiler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
virtual void endSubroutine(Subroutine* subroutine) {
|
virtual void endSubroutine(Subroutine* subroutine) {
|
||||||
|
appendCleanLocals(&c);
|
||||||
static_cast<MySubroutine*>(subroutine)->forkState = ::saveState(&c);
|
static_cast<MySubroutine*>(subroutine)->forkState = ::saveState(&c);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void restoreFromSubroutine(Subroutine* subroutine) {
|
virtual void linkSubroutine(Subroutine* subroutine) {
|
||||||
::restoreState(&c, static_cast<MySubroutine*>(subroutine)->forkState);
|
restoreState(static_cast<MySubroutine*>(subroutine)->forkState);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void init(unsigned logicalCodeLength, unsigned parameterFootprint,
|
virtual void init(unsigned logicalCodeLength, unsigned parameterFootprint,
|
||||||
@ -5032,12 +5058,30 @@ class MyCompiler: public Compiler {
|
|||||||
(c.zone->allocate(sizeof(LogicalInstruction)))
|
(c.zone->allocate(sizeof(LogicalInstruction)))
|
||||||
LogicalInstruction(logicalIp, c.stack, c.locals);
|
LogicalInstruction(logicalIp, c.stack, c.locals);
|
||||||
|
|
||||||
if (c.subroutine) {
|
bool startSubroutine = c.subroutine != 0;
|
||||||
|
if (startSubroutine) {
|
||||||
c.logicalCode[logicalIp]->subroutine = c.subroutine;
|
c.logicalCode[logicalIp]->subroutine = c.subroutine;
|
||||||
c.subroutine = 0;
|
c.subroutine = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
c.logicalIp = logicalIp;
|
c.logicalIp = logicalIp;
|
||||||
|
|
||||||
|
if (startSubroutine) {
|
||||||
|
// assume all local variables are initialized on entry to a
|
||||||
|
// subroutine, since other calls to the subroutine may
|
||||||
|
// initialize them:
|
||||||
|
unsigned sizeInBytes = sizeof(Local) * c.localFootprint;
|
||||||
|
Local* newLocals = static_cast<Local*>(c.zone->allocate(sizeInBytes));
|
||||||
|
memcpy(newLocals, c.locals, sizeInBytes);
|
||||||
|
c.locals = newLocals;
|
||||||
|
|
||||||
|
for (unsigned li = 0; li < c.localFootprint; ++li) {
|
||||||
|
Local* local = c.locals + li;
|
||||||
|
if (local->value == 0) {
|
||||||
|
initLocal(1, li);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual Promise* machineIp(unsigned logicalIp) {
|
virtual Promise* machineIp(unsigned logicalIp) {
|
||||||
|
@ -43,7 +43,7 @@ class Compiler {
|
|||||||
|
|
||||||
virtual Subroutine* startSubroutine() = 0;
|
virtual Subroutine* startSubroutine() = 0;
|
||||||
virtual void endSubroutine(Subroutine* subroutine) = 0;
|
virtual void endSubroutine(Subroutine* subroutine) = 0;
|
||||||
virtual void restoreFromSubroutine(Subroutine* subroutine) = 0;
|
virtual void linkSubroutine(Subroutine* subroutine) = 0;
|
||||||
|
|
||||||
virtual void init(unsigned logicalCodeSize, unsigned parameterFootprint,
|
virtual void init(unsigned logicalCodeSize, unsigned parameterFootprint,
|
||||||
unsigned localFootprint, unsigned alignedFrameSize) = 0;
|
unsigned localFootprint, unsigned alignedFrameSize) = 0;
|
||||||
|
161
src/continuations-x86.S
Normal file
161
src/continuations-x86.S
Normal file
@ -0,0 +1,161 @@
|
|||||||
|
#ifdef __x86_64__
|
||||||
|
|
||||||
|
#define THREAD_CONTINUATION 168
|
||||||
|
#define THREAD_EXCEPTION 64
|
||||||
|
#define THREAD_EXCEPTION_STACK_ADJUSTMENT 176
|
||||||
|
#define THREAD_EXCEPTION_OFFSET 184
|
||||||
|
#define THREAD_EXCEPTION_HANDLER 192
|
||||||
|
|
||||||
|
#define CONTINUATION_NEXT 8
|
||||||
|
#define CONTINUATION_ADDRESS 32
|
||||||
|
#define CONTINUATION_RETURN_ADDRESS_OFFSET 40
|
||||||
|
#define CONTINUATION_FRAME_POINTER_OFFSET 48
|
||||||
|
#define CONTINUATION_LENGTH 56
|
||||||
|
#define CONTINUATION_BODY 64
|
||||||
|
|
||||||
|
// call the next continuation, if any
|
||||||
|
movq THREAD_CONTINUATION(%rbx),%rcx
|
||||||
|
cmpq $0,%rcx
|
||||||
|
je LOCAL(vmInvoke_exit)
|
||||||
|
|
||||||
|
// allocate a frame of size (continuation.length * BYTES_PER_WORD)
|
||||||
|
// + CALLEE_SAVED_REGISTER_FOOTPRINT
|
||||||
|
movq CONTINUATION_LENGTH(%rcx),%rsi
|
||||||
|
shlq $3,%rsi
|
||||||
|
subq %rsi,%rsp
|
||||||
|
subq $CALLEE_SAVED_REGISTER_FOOTPRINT,%rsp
|
||||||
|
|
||||||
|
// copy the continuation body into the frame
|
||||||
|
leaq CONTINUATION_BODY(%rcx),%rdi
|
||||||
|
|
||||||
|
movq $0,%r9
|
||||||
|
jmp LOCAL(vmInvoke_continuationTest)
|
||||||
|
|
||||||
|
LOCAL(vmInvoke_continuationLoop):
|
||||||
|
movq (%rdi,%r9,1),%r8
|
||||||
|
movq %r8,(%rsp,%r9,1)
|
||||||
|
addq $8,%r9
|
||||||
|
|
||||||
|
LOCAL(vmInvoke_continuationTest):
|
||||||
|
cmpq %rsi,%r9
|
||||||
|
jb LOCAL(vmInvoke_continuationLoop)
|
||||||
|
|
||||||
|
// set the return address to vmInvoke_returnAddress
|
||||||
|
movq CONTINUATION_RETURN_ADDRESS_OFFSET(%rcx),%rdi
|
||||||
|
movq vmInvoke_returnAddress@GOTPCREL(%rip),%r10
|
||||||
|
movq %r10,(%rsp,%rdi,1)
|
||||||
|
|
||||||
|
// save the current base pointer in the frame and update it
|
||||||
|
movq CONTINUATION_FRAME_POINTER_OFFSET(%rcx),%rdi
|
||||||
|
movq %rbp,(%rsp,%rdi,1)
|
||||||
|
addq %rsp,%rdi
|
||||||
|
movq %rdi,%rbp
|
||||||
|
|
||||||
|
// consume the continuation
|
||||||
|
movq CONTINUATION_NEXT(%rcx),%rdi
|
||||||
|
movq %rdi,THREAD_CONTINUATION(%rbx)
|
||||||
|
|
||||||
|
// call the continuation unless we're handling an exception
|
||||||
|
movq THREAD_EXCEPTION(%rbx),%rsi
|
||||||
|
cmpq $0,%rsi
|
||||||
|
jne LOCAL(vmInvoke_handleException)
|
||||||
|
jmp *CONTINUATION_ADDRESS(%rcx)
|
||||||
|
|
||||||
|
LOCAL(vmInvoke_handleException):
|
||||||
|
// we're handling an exception - call the exception handler instead
|
||||||
|
movq $0,THREAD_EXCEPTION(%rbx)
|
||||||
|
movq THREAD_EXCEPTION_STACK_ADJUSTMENT(%rbx),%rdi
|
||||||
|
subq %rdi,%rsp
|
||||||
|
movq THREAD_EXCEPTION_OFFSET(%rbx),%rdi
|
||||||
|
movq %rsi,(%rsp,%rdi,1)
|
||||||
|
|
||||||
|
jmp *THREAD_EXCEPTION_HANDLER(%rbx)
|
||||||
|
|
||||||
|
LOCAL(vmInvoke_exit):
|
||||||
|
|
||||||
|
#elif defined __i386__
|
||||||
|
|
||||||
|
#define THREAD_CONTINUATION 96
|
||||||
|
#define THREAD_EXCEPTION 36
|
||||||
|
#define THREAD_EXCEPTION_STACK_ADJUSTMENT 100
|
||||||
|
#define THREAD_EXCEPTION_OFFSET 104
|
||||||
|
#define THREAD_EXCEPTION_HANDLER 108
|
||||||
|
|
||||||
|
#define CONTINUATION_NEXT 4
|
||||||
|
#define CONTINUATION_ADDRESS 16
|
||||||
|
#define CONTINUATION_RETURN_ADDRESS_OFFSET 20
|
||||||
|
#define CONTINUATION_FRAME_POINTER_OFFSET 24
|
||||||
|
#define CONTINUATION_LENGTH 28
|
||||||
|
#define CONTINUATION_BODY 32
|
||||||
|
|
||||||
|
// call the next continuation, if any
|
||||||
|
movl THREAD_CONTINUATION(%ebx),%ecx
|
||||||
|
cmpl $0,%ecx
|
||||||
|
je LOCAL(vmInvoke_exit)
|
||||||
|
|
||||||
|
// allocate a frame of size (continuation.length * BYTES_PER_WORD)
|
||||||
|
movl CONTINUATION_LENGTH(%ecx),%esi
|
||||||
|
shll $2,%esi
|
||||||
|
subl %esi,%esp
|
||||||
|
|
||||||
|
// copy the continuation body into the frame
|
||||||
|
leal CONTINUATION_BODY(%ecx),%edi
|
||||||
|
|
||||||
|
push %eax
|
||||||
|
push %edx
|
||||||
|
|
||||||
|
movl $0,%edx
|
||||||
|
jmp LOCAL(vmInvoke_continuationTest)
|
||||||
|
|
||||||
|
LOCAL(vmInvoke_continuationLoop):
|
||||||
|
movl (%edi,%edx,1),%eax
|
||||||
|
movl %eax,8(%esp,%edx,1)
|
||||||
|
addl $4,%edx
|
||||||
|
|
||||||
|
LOCAL(vmInvoke_continuationTest):
|
||||||
|
cmpl %esi,%edx
|
||||||
|
jb LOCAL(vmInvoke_continuationLoop)
|
||||||
|
|
||||||
|
pop %edx
|
||||||
|
pop %eax
|
||||||
|
|
||||||
|
// set the return address to vmInvoke_returnAddress
|
||||||
|
movl CONTINUATION_RETURN_ADDRESS_OFFSET(%ecx),%edi
|
||||||
|
call LOCAL(getPC)
|
||||||
|
addl $_GLOBAL_OFFSET_TABLE_,%esi
|
||||||
|
movl vmInvoke_returnAddress@GOT(%esi),%esi
|
||||||
|
movl %esi,(%esp,%edi,1)
|
||||||
|
|
||||||
|
// save the current base pointer in the frame and update it
|
||||||
|
movl CONTINUATION_FRAME_POINTER_OFFSET(%ecx),%edi
|
||||||
|
movl %ebp,(%esp,%edi,1)
|
||||||
|
addl %esp,%edi
|
||||||
|
movl %edi,%ebp
|
||||||
|
|
||||||
|
// consume the continuation
|
||||||
|
movl CONTINUATION_NEXT(%ecx),%edi
|
||||||
|
movl %edi,THREAD_CONTINUATION(%ebx)
|
||||||
|
|
||||||
|
// call the continuation unless we're handling an exception
|
||||||
|
movl THREAD_EXCEPTION(%ebx),%esi
|
||||||
|
cmpl $0,%esi
|
||||||
|
jne LOCAL(vmInvoke_handleException)
|
||||||
|
|
||||||
|
jmp *CONTINUATION_ADDRESS(%ecx)
|
||||||
|
|
||||||
|
LOCAL(vmInvoke_handleException):
|
||||||
|
// we're handling an exception - call the exception handler instead
|
||||||
|
movl $0,THREAD_EXCEPTION(%ebx)
|
||||||
|
movl THREAD_EXCEPTION_STACK_ADJUSTMENT(%ebx),%edi
|
||||||
|
subl %edi,%esp
|
||||||
|
movl THREAD_EXCEPTION_OFFSET(%ebx),%edi
|
||||||
|
movl %esi,(%esp,%edi,1)
|
||||||
|
|
||||||
|
jmp *THREAD_EXCEPTION_HANDLER(%ebx)
|
||||||
|
|
||||||
|
LOCAL(vmInvoke_exit):
|
||||||
|
|
||||||
|
#else
|
||||||
|
# error unsupported architecture
|
||||||
|
#endif
|
||||||
|
|
394
src/gnu.cpp
Normal file
394
src/gnu.cpp
Normal file
@ -0,0 +1,394 @@
|
|||||||
|
/* 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. */
|
||||||
|
|
||||||
|
#include "machine.h"
|
||||||
|
#include "constants.h"
|
||||||
|
#include "processor.h"
|
||||||
|
|
||||||
|
using namespace vm;
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
void
|
||||||
|
setProperty(Thread* t, object method, object properties,
|
||||||
|
const char* name, const void* value, const char* format = "%s")
|
||||||
|
{
|
||||||
|
PROTECT(t, method);
|
||||||
|
PROTECT(t, properties);
|
||||||
|
|
||||||
|
object n = makeString(t, "%s", name);
|
||||||
|
PROTECT(t, n);
|
||||||
|
|
||||||
|
object v = makeString(t, format, value);
|
||||||
|
|
||||||
|
t->m->processor->invoke(t, method, properties, n, v);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
namespace vm {
|
||||||
|
|
||||||
|
jobject JNICALL
|
||||||
|
NewDirectByteBuffer(Thread* t, void* address, jlong capacity)
|
||||||
|
{
|
||||||
|
const char* pointerClassName;
|
||||||
|
const char* initSpec;
|
||||||
|
if (BytesPerWord == 8) {
|
||||||
|
pointerClassName = "gnu/classpath/Pointer64";
|
||||||
|
initSpec = "(J)V";
|
||||||
|
} else {
|
||||||
|
pointerClassName = "gnu/classpath/Pointer32";
|
||||||
|
initSpec = "(I)V";
|
||||||
|
}
|
||||||
|
|
||||||
|
object pointerClass = resolveClass(t, pointerClassName);
|
||||||
|
if (UNLIKELY(pointerClass == 0)) return 0;
|
||||||
|
PROTECT(t, pointerClass);
|
||||||
|
|
||||||
|
object pointerConstructor = resolveMethod
|
||||||
|
(t, pointerClass, "<init>", initSpec);
|
||||||
|
if (UNLIKELY(pointerConstructor == 0)) return 0;
|
||||||
|
|
||||||
|
object pointer = make(t, pointerClass);
|
||||||
|
PROTECT(t, pointer);
|
||||||
|
|
||||||
|
t->m->processor->invoke(t, pointerConstructor, pointer, address);
|
||||||
|
if (UNLIKELY(t->exception)) return 0;
|
||||||
|
|
||||||
|
object bufferClass = resolveClass
|
||||||
|
(t, "java/nio/DirectByteBufferImpl$ReadWrite");
|
||||||
|
if (UNLIKELY(bufferClass == 0)) return 0;
|
||||||
|
PROTECT(t, bufferClass);
|
||||||
|
|
||||||
|
object bufferConstructor = resolveMethod
|
||||||
|
(t, bufferClass, "<init>", "(Lgnu/classpath/Pointer;int)V");
|
||||||
|
if (UNLIKELY(bufferConstructor == 0)) return 0;
|
||||||
|
|
||||||
|
object buffer = make(t, bufferClass);
|
||||||
|
PROTECT(t, buffer);
|
||||||
|
|
||||||
|
t->m->processor->invoke
|
||||||
|
(t, bufferConstructor, buffer, &pointer, static_cast<jint>(capacity));
|
||||||
|
if (UNLIKELY(t->exception)) return 0;
|
||||||
|
|
||||||
|
return makeLocalReference(t, buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
void* JNICALL
|
||||||
|
GetDirectBufferAddress(Thread* t, jobject buffer)
|
||||||
|
{
|
||||||
|
object addressField = resolveField
|
||||||
|
(t, objectClass(t, *buffer), "address", "Lgnu/classpath/Pointer;");
|
||||||
|
if (UNLIKELY(addressField == 0)) return 0;
|
||||||
|
|
||||||
|
object address = cast<object>(*buffer, fieldOffset(t, addressField));
|
||||||
|
if (address == 0) return 0;
|
||||||
|
|
||||||
|
const char* dataSpec;
|
||||||
|
if (BytesPerWord == 8) {
|
||||||
|
dataSpec = "J";
|
||||||
|
} else {
|
||||||
|
dataSpec = "I";
|
||||||
|
}
|
||||||
|
|
||||||
|
object dataField = resolveField
|
||||||
|
(t, objectClass(t, address), "data", dataSpec);
|
||||||
|
if (UNLIKELY(dataField == 0)) return 0;
|
||||||
|
|
||||||
|
return cast<void*>(address, fieldOffset(t, dataField));
|
||||||
|
}
|
||||||
|
|
||||||
|
jlong JNICALL
|
||||||
|
GetDirectBufferCapacity(Thread* t, jobject buffer)
|
||||||
|
{
|
||||||
|
object capField = resolveField(t, objectClass(t, *buffer), "cap", "I");
|
||||||
|
if (UNLIKELY(capField == 0)) return 0;
|
||||||
|
|
||||||
|
return cast<jint>(*buffer, fieldOffset(t, capField));
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace vm
|
||||||
|
|
||||||
|
extern "C" JNIEXPORT void JNICALL
|
||||||
|
Avian_gnu_classpath_VMSystemProperties_preInit
|
||||||
|
(Thread* t, object, uintptr_t* arguments)
|
||||||
|
{
|
||||||
|
object properties = reinterpret_cast<object>(arguments[0]);
|
||||||
|
PROTECT(t, properties);
|
||||||
|
|
||||||
|
object method = resolveMethod
|
||||||
|
(t, "java/util/Properties", "setProperty",
|
||||||
|
"(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/Object;");
|
||||||
|
|
||||||
|
if (UNLIKELY(t->exception)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
PROTECT(t, method);
|
||||||
|
|
||||||
|
setProperty(t, method, properties, "java.vm.name", "Avian");
|
||||||
|
|
||||||
|
setProperty(t, method, properties, "java.protocol.handler.pkgs", "avian");
|
||||||
|
|
||||||
|
setProperty(t, method, properties, "file.encoding", "ASCII");
|
||||||
|
|
||||||
|
// specify a bogus library path so we can do our own search in
|
||||||
|
// VMRuntime.nativeLoad:
|
||||||
|
#define LIBRARY_PATH_SENTINAL "*"
|
||||||
|
setProperty(t, method, properties, "java.library.path",
|
||||||
|
LIBRARY_PATH_SENTINAL);
|
||||||
|
|
||||||
|
#ifdef WIN32
|
||||||
|
# define FILE_SEPARATOR "\\"
|
||||||
|
|
||||||
|
setProperty(t, method, properties, "line.separator", "\r\n");
|
||||||
|
setProperty(t, method, properties, "file.separator", FILE_SEPARATOR);
|
||||||
|
setProperty(t, method, properties, "path.separator", ";");
|
||||||
|
setProperty(t, method, properties, "os.name", "Windows");
|
||||||
|
|
||||||
|
TCHAR buffer[MAX_PATH];
|
||||||
|
GetTempPath(MAX_PATH, buffer);
|
||||||
|
setProperty(t, method, properties, "java.io.tmpdir", buffer);
|
||||||
|
|
||||||
|
setProperty(t, method, properties, "user.home",
|
||||||
|
_wgetenv(L"USERPROFILE"), "%ls");
|
||||||
|
|
||||||
|
GetCurrentDirectory(MAX_PATH, buffer);
|
||||||
|
setProperty(t, method, properties, "user.dir", buffer);
|
||||||
|
#else
|
||||||
|
# define FILE_SEPARATOR "/"
|
||||||
|
|
||||||
|
setProperty(t, method, properties, "line.separator", "\n");
|
||||||
|
setProperty(t, method, properties, "file.separator", FILE_SEPARATOR);
|
||||||
|
setProperty(t, method, properties, "path.separator", ":");
|
||||||
|
# ifdef __APPLE__
|
||||||
|
setProperty(t, method, properties, "os.name", "Mac OS X");
|
||||||
|
# else
|
||||||
|
setProperty(t, method, properties, "os.name", "Linux");
|
||||||
|
# endif
|
||||||
|
setProperty(t, method, properties, "java.io.tmpdir", "/tmp");
|
||||||
|
setProperty(t, method, properties, "user.home", getenv("HOME"));
|
||||||
|
setProperty(t, method, properties, "user.dir", getenv("PWD"));
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" JNIEXPORT int64_t JNICALL
|
||||||
|
Avian_gnu_classpath_VMStackWalker_getClassContext
|
||||||
|
(Thread* t, object, uintptr_t*)
|
||||||
|
{
|
||||||
|
class Visitor: public Processor::StackVisitor {
|
||||||
|
public:
|
||||||
|
Visitor(Thread* t):
|
||||||
|
t(t), skipCount(1), trace(0), index(0), protector(t, &trace)
|
||||||
|
{ }
|
||||||
|
|
||||||
|
virtual bool visit(Processor::StackWalker* walker) {
|
||||||
|
if (skipCount == 0) {
|
||||||
|
if (trace == 0) {
|
||||||
|
trace = makeObjectArray
|
||||||
|
(t, arrayBody(t, t->m->types, Machine::ClassType),
|
||||||
|
walker->count());
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(t, index < objectArrayLength(t, trace));
|
||||||
|
|
||||||
|
set(t, trace, ArrayBody + (index * BytesPerWord),
|
||||||
|
methodClass(t, walker->method()));
|
||||||
|
|
||||||
|
++ index;
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
-- skipCount;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Thread* t;
|
||||||
|
unsigned skipCount;
|
||||||
|
object trace;
|
||||||
|
unsigned index;
|
||||||
|
Thread::SingleProtector protector;
|
||||||
|
} v(t);
|
||||||
|
|
||||||
|
t->m->processor->walkStack(t, &v);
|
||||||
|
|
||||||
|
if (v.trace == 0) {
|
||||||
|
v.trace = makeObjectArray
|
||||||
|
(t, arrayBody(t, t->m->types, Machine::ClassType), 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
return reinterpret_cast<int64_t>(v.trace);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" JNIEXPORT int64_t JNICALL
|
||||||
|
Avian_gnu_classpath_VMStackWalker_getClassLoader
|
||||||
|
(Thread* t, object, uintptr_t* arguments)
|
||||||
|
{
|
||||||
|
return reinterpret_cast<int64_t>
|
||||||
|
(classLoader(t, reinterpret_cast<object>(arguments[0])));
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" JNIEXPORT int64_t JNICALL
|
||||||
|
Avian_java_lang_VMRuntime_mapLibraryName
|
||||||
|
(Thread* t, object, uintptr_t* arguments)
|
||||||
|
{
|
||||||
|
object name = reinterpret_cast<object>(arguments[0]);
|
||||||
|
PROTECT(t, name);
|
||||||
|
|
||||||
|
const unsigned soPrefixLength = sizeof(SO_PREFIX) - 1;
|
||||||
|
const unsigned nameLength = stringLength(t, name);
|
||||||
|
const unsigned soSuffixLength = sizeof(SO_SUFFIX) - 1;
|
||||||
|
const unsigned total = soPrefixLength + nameLength + soSuffixLength;
|
||||||
|
|
||||||
|
object s = makeByteArray(t, total + 1);
|
||||||
|
char* p = reinterpret_cast<char*>(&byteArrayBody(t, s, 0));
|
||||||
|
|
||||||
|
memcpy(p, SO_PREFIX, soPrefixLength);
|
||||||
|
stringChars(t, name, p + soPrefixLength);
|
||||||
|
memcpy(p + soPrefixLength + nameLength, SO_SUFFIX, soSuffixLength);
|
||||||
|
p[total] = 0;
|
||||||
|
|
||||||
|
return reinterpret_cast<int64_t>(makeString(t, s, 0, total, 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" JNIEXPORT void JNICALL
|
||||||
|
Avian_java_lang_System_arraycopy
|
||||||
|
(Thread*, object, uintptr_t*);
|
||||||
|
|
||||||
|
extern "C" JNIEXPORT void JNICALL
|
||||||
|
Avian_java_lang_VMSystem_arraycopy
|
||||||
|
(Thread* t, object, uintptr_t* arguments)
|
||||||
|
{
|
||||||
|
Avian_java_lang_System_arraycopy(t, 0, arguments);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" JNIEXPORT void JNICALL
|
||||||
|
Avian_java_lang_Runtime_load
|
||||||
|
(Thread* t, object, uintptr_t*);
|
||||||
|
|
||||||
|
extern "C" JNIEXPORT int64_t JNICALL
|
||||||
|
Avian_java_lang_VMRuntime_nativeLoad
|
||||||
|
(Thread* t, object, uintptr_t* arguments)
|
||||||
|
{
|
||||||
|
object name = reinterpret_cast<object>(arguments[0]);
|
||||||
|
|
||||||
|
// given that we set java.library.path to LIBRARY_PATH_SENTINAL, we
|
||||||
|
// can determine which names are filenames and which are library
|
||||||
|
// names by looking for the prefix LIBRARY_PATH_SENTINAL
|
||||||
|
// FILE_SEPARATOR
|
||||||
|
|
||||||
|
unsigned length = stringLength(t, name);
|
||||||
|
char n[length + 1];
|
||||||
|
stringChars(t, name, n);
|
||||||
|
|
||||||
|
const unsigned pathPrefixLength
|
||||||
|
= sizeof(LIBRARY_PATH_SENTINAL) - 1
|
||||||
|
+ sizeof(FILE_SEPARATOR) - 1;
|
||||||
|
|
||||||
|
bool mapName = (strncmp(n, LIBRARY_PATH_SENTINAL FILE_SEPARATOR,
|
||||||
|
pathPrefixLength) == 0);
|
||||||
|
if (mapName) {
|
||||||
|
// strip the path prefix, SO prefix, and SO suffix before passing
|
||||||
|
// the name to Runtime.load
|
||||||
|
|
||||||
|
const unsigned soPrefixLength = sizeof(SO_PREFIX) - 1;
|
||||||
|
const unsigned soSuffixLength = sizeof(SO_SUFFIX) - 1;
|
||||||
|
const unsigned newOffset
|
||||||
|
= stringOffset(t, name) + pathPrefixLength + soPrefixLength;
|
||||||
|
const unsigned newLength
|
||||||
|
= length - pathPrefixLength - soPrefixLength - soSuffixLength;
|
||||||
|
|
||||||
|
name = makeString(t, stringData(t, name), newOffset, newLength, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
uintptr_t args[] = { reinterpret_cast<uintptr_t>(name), mapName };
|
||||||
|
|
||||||
|
Avian_java_lang_Runtime_load(t, 0, args);
|
||||||
|
|
||||||
|
if (t->exception) {
|
||||||
|
t->exception = 0;
|
||||||
|
return 0;
|
||||||
|
} else {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" JNIEXPORT int64_t JNICALL
|
||||||
|
Avian_java_lang_Class_primitiveClass
|
||||||
|
(Thread* t, object, uintptr_t*);
|
||||||
|
|
||||||
|
extern "C" JNIEXPORT int64_t JNICALL
|
||||||
|
Avian_java_lang_VMClassLoader_getPrimitiveClass
|
||||||
|
(Thread* t, object, uintptr_t* arguments)
|
||||||
|
{
|
||||||
|
return Avian_java_lang_Class_primitiveClass(t, 0, arguments);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" JNIEXPORT int64_t JNICALL
|
||||||
|
Avian_java_lang_System_identityHashCode
|
||||||
|
(Thread*, object, uintptr_t*);
|
||||||
|
|
||||||
|
extern "C" JNIEXPORT int64_t JNICALL
|
||||||
|
Avian_java_lang_VMSystem_identityHashCode
|
||||||
|
(Thread* t, object, uintptr_t* arguments)
|
||||||
|
{
|
||||||
|
return Avian_java_lang_System_identityHashCode(t, 0, arguments);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" JNIEXPORT void JNICALL
|
||||||
|
Avian_java_lang_Runtime_gc
|
||||||
|
(Thread*, object, uintptr_t*);
|
||||||
|
|
||||||
|
extern "C" JNIEXPORT void JNICALL
|
||||||
|
Avian_java_lang_VMRuntime_gc
|
||||||
|
(Thread* t, object, uintptr_t*)
|
||||||
|
{
|
||||||
|
Avian_java_lang_Runtime_gc(t, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" JNIEXPORT void JNICALL
|
||||||
|
Avian_java_lang_VMRuntime_runFinalizationForExit
|
||||||
|
(Thread*, object, uintptr_t*)
|
||||||
|
{
|
||||||
|
// ignore
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" JNIEXPORT void JNICALL
|
||||||
|
Avian_java_lang_VMRuntime_exit
|
||||||
|
(Thread*, object, uintptr_t* arguments)
|
||||||
|
{
|
||||||
|
exit(arguments[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" JNIEXPORT int64_t JNICALL
|
||||||
|
Avian_avian_SystemClassLoader_findClass
|
||||||
|
(Thread*, object, uintptr_t*);
|
||||||
|
|
||||||
|
extern "C" JNIEXPORT int64_t JNICALL
|
||||||
|
Avian_java_lang_VMClassLoader_loadClass
|
||||||
|
(Thread* t, object, uintptr_t* arguments)
|
||||||
|
{
|
||||||
|
uintptr_t args[] = { 0, arguments[0] };
|
||||||
|
|
||||||
|
return Avian_avian_SystemClassLoader_findClass(t, 0, args);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" JNIEXPORT int64_t JNICALL
|
||||||
|
Avian_avian_SystemClassLoader_findLoadedClass
|
||||||
|
(Thread*, object, uintptr_t*);
|
||||||
|
|
||||||
|
extern "C" JNIEXPORT int64_t JNICALL
|
||||||
|
Avian_java_lang_VMClassLoader_findLoadedClass
|
||||||
|
(Thread* t, object, uintptr_t* arguments)
|
||||||
|
{
|
||||||
|
uintptr_t args[] = { 0, arguments[1] };
|
||||||
|
|
||||||
|
return Avian_avian_SystemClassLoader_findLoadedClass(t, 0, args);
|
||||||
|
}
|
@ -88,7 +88,7 @@ class Context {
|
|||||||
while (stack) {
|
while (stack) {
|
||||||
Stack* dead = stack;
|
Stack* dead = stack;
|
||||||
stack = dead->next;
|
stack = dead->next;
|
||||||
thread->m->heap->free(stack, sizeof(Stack));
|
thread->m->heap->free(dead, sizeof(Stack));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -26,6 +26,8 @@ const unsigned FrameMethodOffset = 2;
|
|||||||
const unsigned FrameIpOffset = 3;
|
const unsigned FrameIpOffset = 3;
|
||||||
const unsigned FrameFootprint = 4;
|
const unsigned FrameFootprint = 4;
|
||||||
|
|
||||||
|
class ClassInitList;
|
||||||
|
|
||||||
class Thread: public vm::Thread {
|
class Thread: public vm::Thread {
|
||||||
public:
|
public:
|
||||||
static const unsigned StackSizeInBytes = 64 * 1024;
|
static const unsigned StackSizeInBytes = 64 * 1024;
|
||||||
@ -36,16 +38,39 @@ class Thread: public vm::Thread {
|
|||||||
ip(0),
|
ip(0),
|
||||||
sp(0),
|
sp(0),
|
||||||
frame(-1),
|
frame(-1),
|
||||||
code(0)
|
code(0),
|
||||||
|
classInitList(0)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
unsigned ip;
|
unsigned ip;
|
||||||
unsigned sp;
|
unsigned sp;
|
||||||
int frame;
|
int frame;
|
||||||
object code;
|
object code;
|
||||||
|
ClassInitList* classInitList;
|
||||||
uintptr_t stack[StackSizeInWords];
|
uintptr_t stack[StackSizeInWords];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class ClassInitList {
|
||||||
|
public:
|
||||||
|
ClassInitList(Thread* t, object class_, ClassInitList* next):
|
||||||
|
t(t), class_(class_), next(next)
|
||||||
|
{ }
|
||||||
|
|
||||||
|
static void push(Thread* t, object class_) {
|
||||||
|
t->classInitList = new (t->m->heap->allocate(sizeof(ClassInitList)))
|
||||||
|
ClassInitList(t, class_, t->classInitList);
|
||||||
|
}
|
||||||
|
|
||||||
|
void pop() {
|
||||||
|
t->classInitList = next;
|
||||||
|
t->m->heap->free(this, sizeof(ClassInitList));
|
||||||
|
}
|
||||||
|
|
||||||
|
Thread* t;
|
||||||
|
object class_;
|
||||||
|
ClassInitList* next;
|
||||||
|
};
|
||||||
|
|
||||||
inline void
|
inline void
|
||||||
pushObject(Thread* t, object o)
|
pushObject(Thread* t, object o)
|
||||||
{
|
{
|
||||||
@ -348,12 +373,14 @@ popFrame(Thread* t)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (UNLIKELY(methodVmFlags(t, method) & ClassInitFlag)) {
|
if (UNLIKELY(methodVmFlags(t, method) & ClassInitFlag)
|
||||||
if (t->exception) {
|
and t->classInitList)
|
||||||
t->exception = makeExceptionInInitializerError(t, t->exception);
|
{
|
||||||
}
|
assert(t, t->classInitList->class_ == methodClass(t, method));
|
||||||
classVmFlags(t, methodClass(t, method)) &= ~(NeedInitFlag | InitFlag);
|
|
||||||
release(t, t->m->classLock);
|
t->classInitList->pop();
|
||||||
|
|
||||||
|
postInitClass(t, methodClass(t, method));
|
||||||
}
|
}
|
||||||
|
|
||||||
t->sp = frameBase(t, t->frame);
|
t->sp = frameBase(t, t->frame);
|
||||||
@ -732,17 +759,21 @@ invokeNative(Thread* t, object method)
|
|||||||
bool
|
bool
|
||||||
classInit2(Thread* t, object class_, unsigned ipOffset)
|
classInit2(Thread* t, object class_, unsigned ipOffset)
|
||||||
{
|
{
|
||||||
|
for (ClassInitList* list = t->classInitList; list; list = list->next) {
|
||||||
|
if (list->class_ == class_) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
PROTECT(t, class_);
|
PROTECT(t, class_);
|
||||||
acquire(t, t->m->classLock);
|
|
||||||
if (classVmFlags(t, class_) & NeedInitFlag
|
if (preInitClass(t, class_)) {
|
||||||
and (classVmFlags(t, class_) & InitFlag) == 0)
|
ClassInitList::push(t, class_);
|
||||||
{
|
|
||||||
classVmFlags(t, class_) |= InitFlag;
|
|
||||||
t->code = classInitializer(t, class_);
|
t->code = classInitializer(t, class_);
|
||||||
t->ip -= ipOffset;
|
t->ip -= ipOffset;
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
release(t, t->m->classLock);
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -3070,22 +3101,6 @@ class MyProcessor: public Processor {
|
|||||||
// ignore
|
// ignore
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void
|
|
||||||
initClass(vm::Thread* t, object c)
|
|
||||||
{
|
|
||||||
PROTECT(t, c);
|
|
||||||
|
|
||||||
acquire(t, t->m->classLock);
|
|
||||||
if (classVmFlags(t, c) & NeedInitFlag
|
|
||||||
and (classVmFlags(t, c) & InitFlag) == 0)
|
|
||||||
{
|
|
||||||
classVmFlags(t, c) |= InitFlag;
|
|
||||||
invoke(t, classInitializer(t, c), 0);
|
|
||||||
} else {
|
|
||||||
release(t, t->m->classLock);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual void
|
virtual void
|
||||||
visitObjects(vm::Thread* vmt, Heap::Visitor* v)
|
visitObjects(vm::Thread* vmt, Heap::Visitor* v)
|
||||||
{
|
{
|
||||||
@ -3098,6 +3113,10 @@ class MyProcessor: public Processor {
|
|||||||
v->visit(reinterpret_cast<object*>(t->stack + (i * 2) + 1));
|
v->visit(reinterpret_cast<object*>(t->stack + (i * 2) + 1));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (ClassInitList* list = t->classInitList; list; list = list->next) {
|
||||||
|
v->visit(reinterpret_cast<object*>(&(list->class_)));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void
|
virtual void
|
||||||
|
@ -62,8 +62,10 @@ AttachCurrentThread(Machine* m, Thread** t, void*)
|
|||||||
*t = static_cast<Thread*>(m->localThread->get());
|
*t = static_cast<Thread*>(m->localThread->get());
|
||||||
if (*t == 0) {
|
if (*t == 0) {
|
||||||
*t = m->processor->makeThread(m, 0, m->rootThread);
|
*t = m->processor->makeThread(m, 0, m->rootThread);
|
||||||
|
m->system->attach(&((*t)->runnable));
|
||||||
|
|
||||||
enter(*t, Thread::ActiveState);
|
enter(*t, Thread::ActiveState);
|
||||||
|
enter(*t, Thread::IdleState);
|
||||||
|
|
||||||
m->localThread->set(*t);
|
m->localThread->set(*t);
|
||||||
}
|
}
|
||||||
@ -264,6 +266,26 @@ ExceptionCheck(Thread* t)
|
|||||||
return t->exception != 0;
|
return t->exception != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef AVIAN_GNU
|
||||||
|
jobject JNICALL
|
||||||
|
NewDirectByteBuffer(Thread*, void*, jlong)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void* JNICALL
|
||||||
|
GetDirectBufferAddress(Thread*, jobject)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
jlong JNICALL
|
||||||
|
GetDirectBufferCapacity(Thread*, jobject)
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
#endif// not AVIAN_GNU
|
||||||
|
|
||||||
jclass JNICALL
|
jclass JNICALL
|
||||||
GetObjectClass(Thread* t, jobject o)
|
GetObjectClass(Thread* t, jobject o)
|
||||||
{
|
{
|
||||||
@ -823,22 +845,12 @@ CallStaticVoidMethod(Thread* t, jclass c, jmethodID m, ...)
|
|||||||
va_end(a);
|
va_end(a);
|
||||||
}
|
}
|
||||||
|
|
||||||
object
|
|
||||||
findField(Thread* t, jclass c, const char* name, const char* spec)
|
|
||||||
{
|
|
||||||
object n = makeByteArray(t, "%s", name);
|
|
||||||
PROTECT(t, n);
|
|
||||||
|
|
||||||
object s = makeByteArray(t, "%s", spec);
|
|
||||||
return vm::findField(t, *c, n, s);
|
|
||||||
}
|
|
||||||
|
|
||||||
jfieldID JNICALL
|
jfieldID JNICALL
|
||||||
GetFieldID(Thread* t, jclass c, const char* name, const char* spec)
|
GetFieldID(Thread* t, jclass c, const char* name, const char* spec)
|
||||||
{
|
{
|
||||||
ENTER(t, Thread::ActiveState);
|
ENTER(t, Thread::ActiveState);
|
||||||
|
|
||||||
object field = findField(t, c, name, spec);
|
object field = resolveField(t, *c, name, spec);
|
||||||
if (UNLIKELY(t->exception)) return 0;
|
if (UNLIKELY(t->exception)) return 0;
|
||||||
|
|
||||||
return fieldOffset(t, field);
|
return fieldOffset(t, field);
|
||||||
@ -849,7 +861,7 @@ GetStaticFieldID(Thread* t, jclass c, const char* name, const char* spec)
|
|||||||
{
|
{
|
||||||
ENTER(t, Thread::ActiveState);
|
ENTER(t, Thread::ActiveState);
|
||||||
|
|
||||||
object field = findField(t, c, name, spec);
|
object field = resolveField(t, *c, name, spec);
|
||||||
if (UNLIKELY(t->exception)) return 0;
|
if (UNLIKELY(t->exception)) return 0;
|
||||||
|
|
||||||
return fieldOffset(t, field);
|
return fieldOffset(t, field);
|
||||||
@ -1889,6 +1901,17 @@ append(char** p, const char* value, unsigned length, char tail)
|
|||||||
|
|
||||||
namespace vm {
|
namespace vm {
|
||||||
|
|
||||||
|
#ifdef AVIAN_GNU
|
||||||
|
jobject JNICALL
|
||||||
|
NewDirectByteBuffer(Thread*, void*, jlong);
|
||||||
|
|
||||||
|
void* JNICALL
|
||||||
|
GetDirectBufferAddress(Thread*, jobject);
|
||||||
|
|
||||||
|
jlong JNICALL
|
||||||
|
GetDirectBufferCapacity(Thread*, jobject);
|
||||||
|
#endif//AVIAN_GNU
|
||||||
|
|
||||||
void
|
void
|
||||||
populateJNITables(JavaVMVTable* vmTable, JNIEnvVTable* envTable)
|
populateJNITables(JavaVMVTable* vmTable, JNIEnvVTable* envTable)
|
||||||
{
|
{
|
||||||
@ -1914,6 +1937,9 @@ populateJNITables(JavaVMVTable* vmTable, JNIEnvVTable* envTable)
|
|||||||
envTable->FindClass = ::FindClass;
|
envTable->FindClass = ::FindClass;
|
||||||
envTable->ThrowNew = ::ThrowNew;
|
envTable->ThrowNew = ::ThrowNew;
|
||||||
envTable->ExceptionCheck = ::ExceptionCheck;
|
envTable->ExceptionCheck = ::ExceptionCheck;
|
||||||
|
envTable->NewDirectByteBuffer = ::NewDirectByteBuffer;
|
||||||
|
envTable->GetDirectBufferAddress = ::GetDirectBufferAddress;
|
||||||
|
envTable->GetDirectBufferCapacity = ::GetDirectBufferCapacity;
|
||||||
envTable->DeleteLocalRef = ::DeleteLocalRef;
|
envTable->DeleteLocalRef = ::DeleteLocalRef;
|
||||||
envTable->GetObjectClass = ::GetObjectClass;
|
envTable->GetObjectClass = ::GetObjectClass;
|
||||||
envTable->IsInstanceOf = ::IsInstanceOf;
|
envTable->IsInstanceOf = ::IsInstanceOf;
|
||||||
|
357
src/machine.cpp
357
src/machine.cpp
@ -481,6 +481,33 @@ postCollect(Thread* t)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
finalizeObject(Thread* t, object o)
|
||||||
|
{
|
||||||
|
if (t->state == Thread::ExitState) {
|
||||||
|
// don't waste time running Java finalizers if we're exiting the
|
||||||
|
// VM
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (object c = objectClass(t, o); c; c = classSuper(t, c)) {
|
||||||
|
for (unsigned i = 0; i < arrayLength(t, classMethodTable(t, c)); ++i) {
|
||||||
|
object m = arrayBody(t, classMethodTable(t, c), i);
|
||||||
|
|
||||||
|
if (strcmp(reinterpret_cast<const int8_t*>("finalize"),
|
||||||
|
&byteArrayBody(t, methodName(t, m), 0)) == 0
|
||||||
|
and strcmp(reinterpret_cast<const int8_t*>("()V"),
|
||||||
|
&byteArrayBody(t, methodSpec(t, m), 0)) == 0)
|
||||||
|
{
|
||||||
|
t->m->processor->invoke(t, m, o);
|
||||||
|
t->exception = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
abort(t);
|
||||||
|
}
|
||||||
|
|
||||||
object
|
object
|
||||||
makeByteArray(Thread* t, const char* format, va_list a)
|
makeByteArray(Thread* t, const char* format, va_list a)
|
||||||
{
|
{
|
||||||
@ -497,21 +524,31 @@ makeByteArray(Thread* t, const char* format, va_list a)
|
|||||||
}
|
}
|
||||||
|
|
||||||
object
|
object
|
||||||
parseUtf8(Thread* t, Stream& s, unsigned length)
|
parseUtf8NonAscii(Thread* t, Stream& s, object bytesSoFar, unsigned byteCount,
|
||||||
|
unsigned sourceIndex, unsigned lastByteRead)
|
||||||
{
|
{
|
||||||
object value = makeByteArray(t, length + 1);
|
PROTECT(t, bytesSoFar);
|
||||||
|
|
||||||
|
unsigned length = byteArrayLength(t, bytesSoFar) - 1;
|
||||||
|
object value = makeCharArray(t, length + 1);
|
||||||
|
|
||||||
unsigned vi = 0;
|
unsigned vi = 0;
|
||||||
for (unsigned si = 0; si < length; ++si) {
|
for (; vi < byteCount; ++vi) {
|
||||||
unsigned a = s.read1();
|
charArrayBody(t, value, vi) = byteArrayBody(t, bytesSoFar, vi);
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned a = lastByteRead;
|
||||||
|
unsigned si = sourceIndex;
|
||||||
|
while (true) {
|
||||||
if (a & 0x80) {
|
if (a & 0x80) {
|
||||||
// todo: handle non-ASCII characters properly
|
|
||||||
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 = s.read1();
|
||||||
/*unsigned c = */s.read1();
|
unsigned c = s.read1();
|
||||||
byteArrayBody(t, value, vi++) = '_';
|
charArrayBody(t, value, vi++)
|
||||||
|
= ((a & 0xf) << 12) | ((b & 0x3f) << 6) | (c & 0x3f);
|
||||||
} else {
|
} else {
|
||||||
// 2 bytes
|
// 2 bytes
|
||||||
++ si;
|
++ si;
|
||||||
@ -519,9 +556,55 @@ parseUtf8(Thread* t, Stream& s, unsigned length)
|
|||||||
unsigned b = s.read1();
|
unsigned b = s.read1();
|
||||||
|
|
||||||
if (a == 0xC0 and b == 0x80) {
|
if (a == 0xC0 and b == 0x80) {
|
||||||
|
charArrayBody(t, value, vi++) = 0;
|
||||||
|
} else {
|
||||||
|
charArrayBody(t, value, vi++) = ((a & 0x1f) << 6) | (b & 0x3f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
charArrayBody(t, value, vi++) = a;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (++si < length) {
|
||||||
|
a = s.read1();
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (vi < length) {
|
||||||
|
PROTECT(t, value);
|
||||||
|
|
||||||
|
object v = makeCharArray(t, vi + 1);
|
||||||
|
memcpy(&charArrayBody(t, v, 0), &charArrayBody(t, value, 0), vi * 2);
|
||||||
|
value = v;
|
||||||
|
}
|
||||||
|
|
||||||
|
charArrayBody(t, value, vi) = 0;
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
object
|
||||||
|
parseUtf8(Thread* t, Stream& s, unsigned length)
|
||||||
|
{
|
||||||
|
object value = makeByteArray(t, length + 1);
|
||||||
|
unsigned vi = 0;
|
||||||
|
for (unsigned si = 0; si < length; ++si) {
|
||||||
|
unsigned a = s.read1();
|
||||||
|
if (a & 0x80) {
|
||||||
|
if (a & 0x20) {
|
||||||
|
// 3 bytes
|
||||||
|
return parseUtf8NonAscii(t, s, value, vi, si, a);
|
||||||
|
} else {
|
||||||
|
// 2 bytes
|
||||||
|
unsigned b = s.read1();
|
||||||
|
|
||||||
|
if (a == 0xC0 and b == 0x80) {
|
||||||
|
++ si;
|
||||||
|
assert(t, si < length);
|
||||||
byteArrayBody(t, value, vi++) = 0;
|
byteArrayBody(t, value, vi++) = 0;
|
||||||
} else {
|
} else {
|
||||||
byteArrayBody(t, value, vi++) = '_';
|
return parseUtf8NonAscii(t, s, value, vi, si, a);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -541,6 +624,28 @@ parseUtf8(Thread* t, Stream& s, unsigned length)
|
|||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
removeByteArray(Thread* t, object o)
|
||||||
|
{
|
||||||
|
hashMapRemove(t, t->m->byteArrayMap, o, byteArrayHash, objectEqual);
|
||||||
|
}
|
||||||
|
|
||||||
|
object
|
||||||
|
internByteArray(Thread* t, object array)
|
||||||
|
{
|
||||||
|
PROTECT(t, array);
|
||||||
|
|
||||||
|
object n = hashMapFindNode
|
||||||
|
(t, t->m->byteArrayMap, array, byteArrayHash, byteArrayEqual);
|
||||||
|
if (n) {
|
||||||
|
return jreferenceTarget(t, tripleFirst(t, n));
|
||||||
|
} else {
|
||||||
|
hashMapInsert(t, t->m->byteArrayMap, array, 0, byteArrayHash);
|
||||||
|
addFinalizer(t, array, removeByteArray);
|
||||||
|
return array;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
unsigned
|
unsigned
|
||||||
parsePoolEntry(Thread* t, Stream& s, uint32_t* index, object pool, unsigned i)
|
parsePoolEntry(Thread* t, Stream& s, uint32_t* index, object pool, unsigned i)
|
||||||
{
|
{
|
||||||
@ -563,6 +668,11 @@ parsePoolEntry(Thread* t, Stream& s, uint32_t* index, object pool, unsigned i)
|
|||||||
case CONSTANT_Utf8: {
|
case CONSTANT_Utf8: {
|
||||||
if (singletonObject(t, pool, i) == 0) {
|
if (singletonObject(t, pool, i) == 0) {
|
||||||
object value = parseUtf8(t, s, s.read2());
|
object value = parseUtf8(t, s, s.read2());
|
||||||
|
if (objectClass(t, value)
|
||||||
|
== arrayBody(t, t->m->types, Machine::ByteArrayType))
|
||||||
|
{
|
||||||
|
value = internByteArray(t, value);
|
||||||
|
}
|
||||||
set(t, pool, SingletonBody + (i * BytesPerWord), value);
|
set(t, pool, SingletonBody + (i * BytesPerWord), value);
|
||||||
}
|
}
|
||||||
} return 1;
|
} return 1;
|
||||||
@ -583,7 +693,8 @@ parsePoolEntry(Thread* t, Stream& s, uint32_t* index, object pool, unsigned i)
|
|||||||
parsePoolEntry(t, s, index, pool, si);
|
parsePoolEntry(t, s, index, pool, si);
|
||||||
|
|
||||||
object value = singletonObject(t, pool, si);
|
object value = singletonObject(t, pool, si);
|
||||||
value = makeString(t, value, 0, byteArrayLength(t, value) - 1, 0);
|
value = makeString
|
||||||
|
(t, value, 0, cast<uintptr_t>(value, BytesPerWord) - 1, 0);
|
||||||
value = intern(t, value);
|
value = intern(t, value);
|
||||||
set(t, pool, SingletonBody + (i * BytesPerWord), value);
|
set(t, pool, SingletonBody + (i * BytesPerWord), value);
|
||||||
}
|
}
|
||||||
@ -1163,6 +1274,17 @@ parseMethodTable(Thread* t, Stream& s, object class_, object pool)
|
|||||||
|
|
||||||
hashMapInsert(t, virtualMap, method, method, methodHash);
|
hashMapInsert(t, virtualMap, method, method, methodHash);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (UNLIKELY(strcmp
|
||||||
|
(reinterpret_cast<const int8_t*>("finalize"),
|
||||||
|
&byteArrayBody(t, methodName(t, method), 0)) == 0
|
||||||
|
and strcmp
|
||||||
|
(reinterpret_cast<const int8_t*>("()V"),
|
||||||
|
&byteArrayBody(t, methodSpec(t, method), 0)) == 0
|
||||||
|
and (not emptyMethod(t, method))))
|
||||||
|
{
|
||||||
|
classVmFlags(t, class_) |= HasFinalizerFlag;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
methodOffset(t, method) = i;
|
methodOffset(t, method) = i;
|
||||||
|
|
||||||
@ -1317,6 +1439,8 @@ updateBootstrapClass(Thread* t, object bootstrapClass, object class_)
|
|||||||
expect(t, bootstrapClass == arrayBody(t, t->m->types, Machine::ClassType)
|
expect(t, bootstrapClass == arrayBody(t, t->m->types, Machine::ClassType)
|
||||||
or classFixedSize(t, bootstrapClass) >= classFixedSize(t, class_));
|
or classFixedSize(t, bootstrapClass) >= classFixedSize(t, class_));
|
||||||
|
|
||||||
|
expect(t, (classVmFlags(t, class_) & HasFinalizerFlag) == 0);
|
||||||
|
|
||||||
PROTECT(t, bootstrapClass);
|
PROTECT(t, bootstrapClass);
|
||||||
PROTECT(t, class_);
|
PROTECT(t, class_);
|
||||||
|
|
||||||
@ -1513,7 +1637,7 @@ boot(Thread* t)
|
|||||||
|
|
||||||
m->unsafe = true;
|
m->unsafe = true;
|
||||||
|
|
||||||
m->loader = allocate(t, sizeof(void*) * 3, true);
|
m->loader = allocate(t, FixedSizeOfSystemClassLoader, true);
|
||||||
|
|
||||||
m->types = allocate(t, pad((TypeCount + 2) * BytesPerWord), true);
|
m->types = allocate(t, pad((TypeCount + 2) * BytesPerWord), true);
|
||||||
arrayLength(t, m->types) = TypeCount;
|
arrayLength(t, m->types) = TypeCount;
|
||||||
@ -1707,6 +1831,7 @@ Machine::Machine(System* system, Heap* heap, Finder* finder,
|
|||||||
bootstrapClassMap(0),
|
bootstrapClassMap(0),
|
||||||
monitorMap(0),
|
monitorMap(0),
|
||||||
stringMap(0),
|
stringMap(0),
|
||||||
|
byteArrayMap(0),
|
||||||
types(0),
|
types(0),
|
||||||
jniMethodTable(0),
|
jniMethodTable(0),
|
||||||
finalizers(0),
|
finalizers(0),
|
||||||
@ -1715,6 +1840,7 @@ Machine::Machine(System* system, Heap* heap, Finder* finder,
|
|||||||
weakReferences(0),
|
weakReferences(0),
|
||||||
tenuredWeakReferences(0),
|
tenuredWeakReferences(0),
|
||||||
unsafe(false),
|
unsafe(false),
|
||||||
|
triedBuiltinOnLoad(false),
|
||||||
heapPoolIndex(0)
|
heapPoolIndex(0)
|
||||||
{
|
{
|
||||||
heap->setClient(heapClient);
|
heap->setClient(heapClient);
|
||||||
@ -1777,6 +1903,7 @@ Thread::Thread(Machine* m, object javaThread, Thread* parent):
|
|||||||
heapIndex(0),
|
heapIndex(0),
|
||||||
heapOffset(0),
|
heapOffset(0),
|
||||||
protector(0),
|
protector(0),
|
||||||
|
classInitStack(0),
|
||||||
runnable(this),
|
runnable(this),
|
||||||
defaultHeap(static_cast<uintptr_t*>
|
defaultHeap(static_cast<uintptr_t*>
|
||||||
(m->heap->allocate(ThreadHeapSizeInBytes))),
|
(m->heap->allocate(ThreadHeapSizeInBytes))),
|
||||||
@ -1827,6 +1954,7 @@ Thread::init()
|
|||||||
boot(this);
|
boot(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
m->byteArrayMap = makeWeakHashMap(this, 0, 0);
|
||||||
m->monitorMap = makeWeakHashMap(this, 0, 0);
|
m->monitorMap = makeWeakHashMap(this, 0, 0);
|
||||||
|
|
||||||
m->jniMethodTable = makeVector(this, 0, 0);
|
m->jniMethodTable = makeVector(this, 0, 0);
|
||||||
@ -1840,8 +1968,12 @@ Thread::init()
|
|||||||
if (javaThread) {
|
if (javaThread) {
|
||||||
threadPeer(this, javaThread) = reinterpret_cast<jlong>(this);
|
threadPeer(this, javaThread) = reinterpret_cast<jlong>(this);
|
||||||
} else {
|
} else {
|
||||||
|
const unsigned NewState = 0;
|
||||||
|
const unsigned NormalPriority = 5;
|
||||||
|
|
||||||
this->javaThread = makeThread
|
this->javaThread = makeThread
|
||||||
(this, reinterpret_cast<int64_t>(this), 0, 0, 0, 0, m->loader, 0);
|
(this, reinterpret_cast<int64_t>(this), 0, 0, NewState, NormalPriority,
|
||||||
|
0, 0, 0, m->loader, 0, 0, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2140,6 +2272,28 @@ allocate3(Thread* t, Allocator* allocator, Machine::AllocationType type,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
object
|
||||||
|
makeNewGeneral(Thread* t, object class_)
|
||||||
|
{
|
||||||
|
assert(t, t->state == Thread::ActiveState);
|
||||||
|
|
||||||
|
object instance = makeNew(t, class_);
|
||||||
|
PROTECT(t, instance);
|
||||||
|
|
||||||
|
if (classVmFlags(t, class_) & WeakReferenceFlag) {
|
||||||
|
ACQUIRE(t, t->m->referenceLock);
|
||||||
|
|
||||||
|
jreferenceVmNext(t, instance) = t->m->weakReferences;
|
||||||
|
t->m->weakReferences = instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (classVmFlags(t, class_) & HasFinalizerFlag) {
|
||||||
|
addFinalizer(t, instance, finalizeObject);
|
||||||
|
}
|
||||||
|
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
|
||||||
object
|
object
|
||||||
makeByteArray(Thread* t, const char* format, ...)
|
makeByteArray(Thread* t, const char* format, ...)
|
||||||
{
|
{
|
||||||
@ -2406,7 +2560,8 @@ parseClass(Thread* t, const uint8_t* data, unsigned size)
|
|||||||
set(t, class_, ClassSuper, sc);
|
set(t, class_, ClassSuper, sc);
|
||||||
|
|
||||||
classVmFlags(t, class_)
|
classVmFlags(t, class_)
|
||||||
|= (classVmFlags(t, sc) & (ReferenceFlag | WeakReferenceFlag));
|
|= (classVmFlags(t, sc)
|
||||||
|
& (ReferenceFlag | WeakReferenceFlag | HasFinalizerFlag));
|
||||||
}
|
}
|
||||||
|
|
||||||
parseInterfaceTable(t, s, class_, pool);
|
parseInterfaceTable(t, s, class_, pool);
|
||||||
@ -2519,24 +2674,57 @@ resolveClass(Thread* t, object spec)
|
|||||||
}
|
}
|
||||||
|
|
||||||
object
|
object
|
||||||
resolveMethod(Thread* t, const char* className, const char* methodName,
|
resolveMethod(Thread* t, object class_, const char* methodName,
|
||||||
const char* methodSpec)
|
const char* methodSpec)
|
||||||
{
|
{
|
||||||
object class_ = resolveClass(t, makeByteArray(t, "%s", className));
|
PROTECT(t, class_);
|
||||||
if (LIKELY(t->exception == 0)) {
|
|
||||||
PROTECT(t, class_);
|
|
||||||
|
|
||||||
object name = makeByteArray(t, methodName);
|
object name = makeByteArray(t, methodName);
|
||||||
PROTECT(t, name);
|
PROTECT(t, name);
|
||||||
|
|
||||||
object spec = makeByteArray(t, methodSpec);
|
object spec = makeByteArray(t, methodSpec);
|
||||||
object reference = makeReference(t, class_, name, spec);
|
|
||||||
|
|
||||||
return findMethodInClass(t, class_, referenceName(t, reference),
|
object method = findMethodInClass(t, class_, name, spec);
|
||||||
referenceSpec(t, reference));
|
|
||||||
|
if (t->exception == 0 and method == 0) {
|
||||||
|
object message = makeString
|
||||||
|
(t, "%s %s not found in %s", methodName, methodSpec,
|
||||||
|
&byteArrayBody(t, className(t, class_), 0));
|
||||||
|
|
||||||
|
t->exception = makeNoSuchMethodError(t, message);
|
||||||
|
return 0;
|
||||||
|
} else {
|
||||||
|
return method;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
object
|
||||||
|
resolveField(Thread* t, object class_, const char* fieldName,
|
||||||
|
const char* fieldSpec)
|
||||||
|
{
|
||||||
|
PROTECT(t, class_);
|
||||||
|
|
||||||
|
object name = makeByteArray(t, fieldName);
|
||||||
|
PROTECT(t, name);
|
||||||
|
|
||||||
|
object spec = makeByteArray(t, fieldSpec);
|
||||||
|
PROTECT(t, spec);
|
||||||
|
|
||||||
|
object field = 0;
|
||||||
|
for (; class_ != 0 and field == 0; class_ = classSuper(t, class_)) {
|
||||||
|
field = findFieldInClass(t, class_, name, spec);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
if (t->exception == 0 and field == 0) {
|
||||||
|
object message = makeString
|
||||||
|
(t, "%s %s not found in %s", fieldName, fieldSpec,
|
||||||
|
&byteArrayBody(t, className(t, class_), 0));
|
||||||
|
|
||||||
|
t->exception = makeNoSuchFieldError(t, message);
|
||||||
|
return 0;
|
||||||
|
} else {
|
||||||
|
return field;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
object
|
object
|
||||||
@ -2565,6 +2753,92 @@ resolveObjectArrayClass(Thread* t, object elementSpec)
|
|||||||
return resolveClass(t, spec);
|
return resolveClass(t, spec);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
classNeedsInit(Thread* t, object c)
|
||||||
|
{
|
||||||
|
if (classVmFlags(t, c) & NeedInitFlag) {
|
||||||
|
if (classVmFlags(t, c) & InitFlag) {
|
||||||
|
// the class is currently being initialized. If this the thread
|
||||||
|
// which is initializing it, we should not try to initialize it
|
||||||
|
// recursively. Otherwise, we must wait for the responsible
|
||||||
|
// thread to finish.
|
||||||
|
for (Thread::ClassInitStack* s = t->classInitStack; s; s = s->next) {
|
||||||
|
if (s->class_ == c) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
preInitClass(Thread* t, object c)
|
||||||
|
{
|
||||||
|
if (classVmFlags(t, c) & NeedInitFlag) {
|
||||||
|
PROTECT(t, c);
|
||||||
|
ACQUIRE(t, t->m->classLock);
|
||||||
|
if (classVmFlags(t, c) & NeedInitFlag) {
|
||||||
|
if (classVmFlags(t, c) & InitFlag) {
|
||||||
|
// the class is currently being initialized. If this the
|
||||||
|
// thread which is initializing it, we should not try to
|
||||||
|
// initialize it recursively.
|
||||||
|
for (Thread::ClassInitStack* s = t->classInitStack; s; s = s->next) {
|
||||||
|
if (s->class_ == c) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// some other thread is on the job - wait for it to finish.
|
||||||
|
while (classVmFlags(t, c) & InitFlag) {
|
||||||
|
ENTER(t, Thread::IdleState);
|
||||||
|
t->m->classLock->wait(t->systemThread, 0);
|
||||||
|
}
|
||||||
|
} else if (classVmFlags(t, c) & InitErrorFlag) {
|
||||||
|
object message = makeString
|
||||||
|
(t, "%s", &byteArrayBody(t, className(t, c), 0));
|
||||||
|
t->exception = makeNoClassDefFoundError(t, message);
|
||||||
|
} else {
|
||||||
|
classVmFlags(t, c) |= InitFlag;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
postInitClass(Thread* t, object c)
|
||||||
|
{
|
||||||
|
PROTECT(t, c);
|
||||||
|
|
||||||
|
ACQUIRE(t, t->m->classLock);
|
||||||
|
if (t->exception) {
|
||||||
|
t->exception = makeExceptionInInitializerError(t, t->exception);
|
||||||
|
classVmFlags(t, c) |= NeedInitFlag | InitErrorFlag;
|
||||||
|
classVmFlags(t, c) &= ~InitFlag;
|
||||||
|
} else {
|
||||||
|
classVmFlags(t, c) &= ~(NeedInitFlag | InitFlag);
|
||||||
|
}
|
||||||
|
t->m->classLock->notifyAll(t->systemThread);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
initClass(Thread* t, object c)
|
||||||
|
{
|
||||||
|
PROTECT(t, c);
|
||||||
|
|
||||||
|
if (preInitClass(t, c)) {
|
||||||
|
Thread::ClassInitStack stack(t, c);
|
||||||
|
|
||||||
|
t->m->processor->invoke(t, classInitializer(t, c), 0);
|
||||||
|
|
||||||
|
postInitClass(t, c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
object
|
object
|
||||||
makeObjectArray(Thread* t, object elementClass, unsigned count)
|
makeObjectArray(Thread* t, object elementClass, unsigned count)
|
||||||
{
|
{
|
||||||
@ -2856,6 +3130,7 @@ visitRoots(Machine* m, Heap::Visitor* v)
|
|||||||
v->visit(&(m->bootstrapClassMap));
|
v->visit(&(m->bootstrapClassMap));
|
||||||
v->visit(&(m->monitorMap));
|
v->visit(&(m->monitorMap));
|
||||||
v->visit(&(m->stringMap));
|
v->visit(&(m->stringMap));
|
||||||
|
v->visit(&(m->byteArrayMap));
|
||||||
v->visit(&(m->types));
|
v->visit(&(m->types));
|
||||||
v->visit(&(m->jniMethodTable));
|
v->visit(&(m->jniMethodTable));
|
||||||
|
|
||||||
@ -2972,11 +3247,11 @@ makeTrace(Thread* t, Thread* target)
|
|||||||
void
|
void
|
||||||
runJavaThread(Thread* t)
|
runJavaThread(Thread* t)
|
||||||
{
|
{
|
||||||
object method = resolveMethod(t, "java/lang/Thread", "run", "()V");
|
object method = resolveMethod
|
||||||
|
(t, "java/lang/Thread", "run", "(Ljava/lang/Thread;)V");
|
||||||
|
|
||||||
if (t->exception == 0) {
|
if (t->exception == 0) {
|
||||||
t->m->processor->invoke
|
t->m->processor->invoke(t, method, 0, t->javaThread);
|
||||||
(t, findMethod(t, method, objectClass(t, t->javaThread)),
|
|
||||||
t->javaThread);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3025,3 +3300,29 @@ vmPrintTrace(Thread* t)
|
|||||||
|
|
||||||
t->m->processor->walkStack(t, &v);
|
t->m->processor->walkStack(t, &v);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// also for debugging
|
||||||
|
void*
|
||||||
|
vmAddressFromLine(Thread* t, object m, unsigned line)
|
||||||
|
{
|
||||||
|
object code = methodCode(t, m);
|
||||||
|
printf("code: %p\n", code);
|
||||||
|
object lnt = codeLineNumberTable(t, code);
|
||||||
|
printf("lnt: %p\n", lnt);
|
||||||
|
|
||||||
|
if (lnt) {
|
||||||
|
unsigned last = 0;
|
||||||
|
unsigned bottom = 0;
|
||||||
|
unsigned top = lineNumberTableLength(t, lnt);
|
||||||
|
for(unsigned i = bottom; i < top; i++)
|
||||||
|
{
|
||||||
|
LineNumber* ln = lineNumberTableBody(t, lnt, i);
|
||||||
|
if(lineNumberLine(ln) == line)
|
||||||
|
return reinterpret_cast<void*>(lineNumberIp(ln));
|
||||||
|
else if(lineNumberLine(ln) > line)
|
||||||
|
return reinterpret_cast<void*>(last);
|
||||||
|
last = lineNumberIp(ln);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
141
src/machine.h
141
src/machine.h
@ -76,6 +76,7 @@ const int UnknownLine = -2;
|
|||||||
|
|
||||||
// class flags (note that we must be careful not to overlap the
|
// class flags (note that we must be careful not to overlap the
|
||||||
// standard ACC_* flags):
|
// standard ACC_* flags):
|
||||||
|
const unsigned HasFinalMemberFlag = 1 << 13;
|
||||||
const unsigned SingletonFlag = 1 << 14;
|
const unsigned SingletonFlag = 1 << 14;
|
||||||
const unsigned ContinuationFlag = 1 << 15;
|
const unsigned ContinuationFlag = 1 << 15;
|
||||||
|
|
||||||
@ -84,9 +85,10 @@ const unsigned ReferenceFlag = 1 << 0;
|
|||||||
const unsigned WeakReferenceFlag = 1 << 1;
|
const unsigned WeakReferenceFlag = 1 << 1;
|
||||||
const unsigned NeedInitFlag = 1 << 2;
|
const unsigned NeedInitFlag = 1 << 2;
|
||||||
const unsigned InitFlag = 1 << 3;
|
const unsigned InitFlag = 1 << 3;
|
||||||
const unsigned PrimitiveFlag = 1 << 4;
|
const unsigned InitErrorFlag = 1 << 4;
|
||||||
const unsigned BootstrapFlag = 1 << 5;
|
const unsigned PrimitiveFlag = 1 << 5;
|
||||||
const unsigned HasFinalMemberFlag = 1 << 6;
|
const unsigned BootstrapFlag = 1 << 6;
|
||||||
|
const unsigned HasFinalizerFlag = 1 << 7;
|
||||||
|
|
||||||
// method vmFlags:
|
// method vmFlags:
|
||||||
const unsigned ClassInitFlag = 1 << 0;
|
const unsigned ClassInitFlag = 1 << 0;
|
||||||
@ -1190,6 +1192,7 @@ class Machine {
|
|||||||
object bootstrapClassMap;
|
object bootstrapClassMap;
|
||||||
object monitorMap;
|
object monitorMap;
|
||||||
object stringMap;
|
object stringMap;
|
||||||
|
object byteArrayMap;
|
||||||
object types;
|
object types;
|
||||||
object jniMethodTable;
|
object jniMethodTable;
|
||||||
object finalizers;
|
object finalizers;
|
||||||
@ -1198,6 +1201,7 @@ class Machine {
|
|||||||
object weakReferences;
|
object weakReferences;
|
||||||
object tenuredWeakReferences;
|
object tenuredWeakReferences;
|
||||||
bool unsafe;
|
bool unsafe;
|
||||||
|
bool triedBuiltinOnLoad;
|
||||||
JavaVMVTable javaVMVTable;
|
JavaVMVTable javaVMVTable;
|
||||||
JNIEnvVTable jniEnvVTable;
|
JNIEnvVTable jniEnvVTable;
|
||||||
uintptr_t* heapPool[ThreadHeapPoolSize];
|
uintptr_t* heapPool[ThreadHeapPoolSize];
|
||||||
@ -1265,6 +1269,25 @@ class Thread {
|
|||||||
object* p;
|
object* p;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class ClassInitStack {
|
||||||
|
public:
|
||||||
|
ClassInitStack(Thread* t, object class_):
|
||||||
|
next(t->classInitStack),
|
||||||
|
class_(class_),
|
||||||
|
protector(t, &(this->class_))
|
||||||
|
{
|
||||||
|
t->classInitStack = this;
|
||||||
|
}
|
||||||
|
|
||||||
|
~ClassInitStack() {
|
||||||
|
protector.t->classInitStack = next;
|
||||||
|
}
|
||||||
|
|
||||||
|
ClassInitStack* next;
|
||||||
|
object class_;
|
||||||
|
SingleProtector protector;
|
||||||
|
};
|
||||||
|
|
||||||
class Runnable: public System::Runnable {
|
class Runnable: public System::Runnable {
|
||||||
public:
|
public:
|
||||||
Runnable(Thread* t): t(t) { }
|
Runnable(Thread* t): t(t) { }
|
||||||
@ -1317,6 +1340,7 @@ class Thread {
|
|||||||
unsigned heapIndex;
|
unsigned heapIndex;
|
||||||
unsigned heapOffset;
|
unsigned heapOffset;
|
||||||
Protector* protector;
|
Protector* protector;
|
||||||
|
ClassInitStack* classInitStack;
|
||||||
Runnable runnable;
|
Runnable runnable;
|
||||||
uintptr_t* defaultHeap;
|
uintptr_t* defaultHeap;
|
||||||
uintptr_t* heap;
|
uintptr_t* heap;
|
||||||
@ -1710,7 +1734,7 @@ makeClassNotFoundException(Thread* t, object message)
|
|||||||
{
|
{
|
||||||
PROTECT(t, message);
|
PROTECT(t, message);
|
||||||
object trace = makeTrace(t);
|
object trace = makeTrace(t);
|
||||||
return makeClassNotFoundException(t, message, trace, 0);
|
return makeClassNotFoundException(t, message, trace, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline object
|
inline object
|
||||||
@ -1761,6 +1785,14 @@ makeNoSuchMethodError(Thread* t, object message)
|
|||||||
return makeNoSuchMethodError(t, message, trace, 0);
|
return makeNoSuchMethodError(t, message, trace, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline object
|
||||||
|
makeNoClassDefFoundError(Thread* t, object message)
|
||||||
|
{
|
||||||
|
PROTECT(t, message);
|
||||||
|
object trace = makeTrace(t);
|
||||||
|
return makeNoClassDefFoundError(t, message, trace, 0);
|
||||||
|
}
|
||||||
|
|
||||||
inline object
|
inline object
|
||||||
makeUnsatisfiedLinkError(Thread* t, object message)
|
makeUnsatisfiedLinkError(Thread* t, object message)
|
||||||
{
|
{
|
||||||
@ -1774,7 +1806,7 @@ makeExceptionInInitializerError(Thread* t, object cause)
|
|||||||
{
|
{
|
||||||
PROTECT(t, cause);
|
PROTECT(t, cause);
|
||||||
object trace = makeTrace(t);
|
object trace = makeTrace(t);
|
||||||
return makeExceptionInInitializerError(t, 0, trace, cause);
|
return makeExceptionInInitializerError(t, 0, trace, cause, cause);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline object
|
inline object
|
||||||
@ -1790,27 +1822,16 @@ makeNew(Thread* t, object class_)
|
|||||||
return instance;
|
return instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline object
|
object
|
||||||
makeNewWeakReference(Thread* t, object class_)
|
makeNewGeneral(Thread* t, object class_);
|
||||||
{
|
|
||||||
assert(t, t->state == Thread::ActiveState);
|
|
||||||
|
|
||||||
object instance = makeNew(t, class_);
|
|
||||||
PROTECT(t, instance);
|
|
||||||
|
|
||||||
ACQUIRE(t, t->m->referenceLock);
|
|
||||||
|
|
||||||
jreferenceVmNext(t, instance) = t->m->weakReferences;
|
|
||||||
t->m->weakReferences = instance;
|
|
||||||
|
|
||||||
return instance;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline object
|
inline object
|
||||||
make(Thread* t, object class_)
|
make(Thread* t, object class_)
|
||||||
{
|
{
|
||||||
if (UNLIKELY(classVmFlags(t, class_) & WeakReferenceFlag)) {
|
if (UNLIKELY(classVmFlags(t, class_)
|
||||||
return makeNewWeakReference(t, class_);
|
& (WeakReferenceFlag | HasFinalizerFlag)))
|
||||||
|
{
|
||||||
|
return makeNewGeneral(t, class_);
|
||||||
} else {
|
} else {
|
||||||
return makeNew(t, class_);
|
return makeNew(t, class_);
|
||||||
}
|
}
|
||||||
@ -1933,9 +1954,9 @@ stringCharAt(Thread* t, object s, int i)
|
|||||||
if (objectClass(t, data)
|
if (objectClass(t, data)
|
||||||
== arrayBody(t, t->m->types, Machine::ByteArrayType))
|
== arrayBody(t, t->m->types, Machine::ByteArrayType))
|
||||||
{
|
{
|
||||||
return byteArrayBody(t, data, i);
|
return byteArrayBody(t, data, stringOffset(t, s) + i);
|
||||||
} else {
|
} else {
|
||||||
return charArrayBody(t, data, i);
|
return charArrayBody(t, data, stringOffset(t, s) + i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2051,33 +2072,72 @@ fieldSize(Thread* t, object field)
|
|||||||
object
|
object
|
||||||
findLoadedClass(Thread* t, object spec);
|
findLoadedClass(Thread* t, object spec);
|
||||||
|
|
||||||
|
inline bool
|
||||||
|
emptyMethod(Thread* t, object method)
|
||||||
|
{
|
||||||
|
return ((methodFlags(t, method) & ACC_NATIVE) == 0)
|
||||||
|
and (codeLength(t, methodCode(t, method)) == 1)
|
||||||
|
and (codeBody(t, methodCode(t, method), 0) == return_);
|
||||||
|
}
|
||||||
|
|
||||||
object
|
object
|
||||||
parseClass(Thread* t, const uint8_t* data, unsigned length);
|
parseClass(Thread* t, const uint8_t* data, unsigned length);
|
||||||
|
|
||||||
object
|
object
|
||||||
resolveClass(Thread* t, object spec);
|
resolveClass(Thread* t, object name);
|
||||||
|
|
||||||
|
inline object
|
||||||
|
resolveClass(Thread* t, const char* name)
|
||||||
|
{
|
||||||
|
return resolveClass(t, makeByteArray(t, "%s", name));
|
||||||
|
}
|
||||||
|
|
||||||
object
|
object
|
||||||
resolveMethod(Thread* t, const char* className, const char* methodName,
|
resolveMethod(Thread* t, object class_, const char* methodName,
|
||||||
const char* methodSpec);
|
const char* methodSpec);
|
||||||
|
|
||||||
|
inline object
|
||||||
|
resolveMethod(Thread* t, const char* className, const char* methodName,
|
||||||
|
const char* methodSpec)
|
||||||
|
{
|
||||||
|
object class_ = resolveClass(t, className);
|
||||||
|
if (LIKELY(t->exception == 0)) {
|
||||||
|
return resolveMethod(t, class_, methodName, methodSpec);
|
||||||
|
} else {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
object
|
||||||
|
resolveField(Thread* t, object class_, const char* fieldName,
|
||||||
|
const char* fieldSpec);
|
||||||
|
|
||||||
|
inline object
|
||||||
|
resolveField(Thread* t, const char* className, const char* fieldName,
|
||||||
|
const char* fieldSpec)
|
||||||
|
{
|
||||||
|
object class_ = resolveClass(t, className);
|
||||||
|
if (LIKELY(t->exception == 0)) {
|
||||||
|
return resolveField(t, class_, fieldName, fieldSpec);
|
||||||
|
} else {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
object
|
object
|
||||||
resolveObjectArrayClass(Thread* t, object elementSpec);
|
resolveObjectArrayClass(Thread* t, object elementSpec);
|
||||||
|
|
||||||
inline bool
|
bool
|
||||||
classNeedsInit(Thread* t, object c)
|
classNeedsInit(Thread* t, object c);
|
||||||
{
|
|
||||||
return classVmFlags(t, c) & NeedInitFlag
|
|
||||||
and (classVmFlags(t, c) & InitFlag) == 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void
|
bool
|
||||||
initClass(Thread* t, object c)
|
preInitClass(Thread* t, object c);
|
||||||
{
|
|
||||||
if (classNeedsInit(t, c)) {
|
void
|
||||||
t->m->processor->initClass(t, c);
|
postInitClass(Thread* t, object c);
|
||||||
}
|
|
||||||
}
|
void
|
||||||
|
initClass(Thread* t, object c);
|
||||||
|
|
||||||
object
|
object
|
||||||
makeObjectArray(Thread* t, object elementClass, unsigned count);
|
makeObjectArray(Thread* t, object elementClass, unsigned count);
|
||||||
@ -2388,4 +2448,7 @@ dumpHeap(Thread* t, FILE* out);
|
|||||||
void
|
void
|
||||||
vmPrintTrace(vm::Thread* t);
|
vmPrintTrace(vm::Thread* t);
|
||||||
|
|
||||||
|
void*
|
||||||
|
vmAddressFromLine(vm::Thread* t, vm::object m, unsigned line);
|
||||||
|
|
||||||
#endif//MACHINE_H
|
#endif//MACHINE_H
|
||||||
|
@ -83,6 +83,10 @@ main(int ac, const char** av)
|
|||||||
++ vmArgs.nOptions;
|
++ vmArgs.nOptions;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef BOOT_BUILTINS
|
||||||
|
++ vmArgs.nOptions;
|
||||||
|
#endif
|
||||||
|
|
||||||
JavaVMOption options[vmArgs.nOptions];
|
JavaVMOption options[vmArgs.nOptions];
|
||||||
vmArgs.options = options;
|
vmArgs.options = options;
|
||||||
|
|
||||||
@ -103,6 +107,11 @@ main(int ac, const char** av)
|
|||||||
= const_cast<char*>("-Davian.bootstrap=" BOOT_LIBRARY);
|
= const_cast<char*>("-Davian.bootstrap=" BOOT_LIBRARY);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef BOOT_BUILTINS
|
||||||
|
options[optionIndex++].optionString
|
||||||
|
= const_cast<char*>("-Davian.builtins=" BOOT_BUILTINS);
|
||||||
|
#endif
|
||||||
|
|
||||||
#define CLASSPATH_PROPERTY "-Djava.class.path="
|
#define CLASSPATH_PROPERTY "-Djava.class.path="
|
||||||
|
|
||||||
unsigned classpathSize = strlen(classpath);
|
unsigned classpathSize = strlen(classpath);
|
||||||
|
@ -124,9 +124,7 @@ class MySystem: public System {
|
|||||||
|
|
||||||
r->setInterrupted(true);
|
r->setInterrupted(true);
|
||||||
|
|
||||||
if (flags & Waiting) {
|
pthread_kill(thread, InterruptSignal);
|
||||||
pthread_kill(thread, InterruptSignal);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void join() {
|
virtual void join() {
|
||||||
@ -852,6 +850,7 @@ handleSignal(int signal, siginfo_t* info, void* context)
|
|||||||
} else {
|
} else {
|
||||||
switch (signal) {
|
switch (signal) {
|
||||||
case VisitSignal:
|
case VisitSignal:
|
||||||
|
case InterruptSignal:
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
@ -78,9 +78,6 @@ class Processor {
|
|||||||
virtual void
|
virtual void
|
||||||
initVtable(Thread* t, object c) = 0;
|
initVtable(Thread* t, object c) = 0;
|
||||||
|
|
||||||
virtual void
|
|
||||||
initClass(Thread* t, object c) = 0;
|
|
||||||
|
|
||||||
virtual void
|
virtual void
|
||||||
visitObjects(Thread* t, Heap::Visitor* v) = 0;
|
visitObjects(Thread* t, Heap::Visitor* v) = 0;
|
||||||
|
|
||||||
|
@ -38,7 +38,7 @@ THUNK(makeMultidimensionalArray)
|
|||||||
THUNK(throw_)
|
THUNK(throw_)
|
||||||
THUNK(checkCast)
|
THUNK(checkCast)
|
||||||
THUNK(instanceOf64)
|
THUNK(instanceOf64)
|
||||||
THUNK(makeNewWeakReference64)
|
THUNK(makeNewGeneral64)
|
||||||
THUNK(makeNew64)
|
THUNK(makeNew64)
|
||||||
THUNK(set)
|
THUNK(set)
|
||||||
THUNK(gcIfNecessary)
|
THUNK(gcIfNecessary)
|
||||||
|
@ -144,8 +144,9 @@
|
|||||||
|
|
||||||
(type illegalMonitorStateException java/lang/IllegalMonitorStateException)
|
(type illegalMonitorStateException java/lang/IllegalMonitorStateException)
|
||||||
|
|
||||||
(type arrayIndexOutOfBoundsException
|
(type indexOutOfBoundsException java/lang/IndexOutOfBoundsException)
|
||||||
java/lang/ArrayIndexOutOfBoundsException)
|
|
||||||
|
(type arrayIndexOutOfBoundsException java/lang/ArrayIndexOutOfBoundsException)
|
||||||
|
|
||||||
(type arrayStoreException java/lang/ArrayStoreException)
|
(type arrayStoreException java/lang/ArrayStoreException)
|
||||||
|
|
||||||
@ -161,6 +162,8 @@
|
|||||||
|
|
||||||
(type error java/lang/Error)
|
(type error java/lang/Error)
|
||||||
|
|
||||||
|
(type virtualMachineError java/lang/VirtualMachineError)
|
||||||
|
|
||||||
(type stackOverflowError java/lang/StackOverflowError)
|
(type stackOverflowError java/lang/StackOverflowError)
|
||||||
|
|
||||||
(type linkageError java/lang/LinkageError)
|
(type linkageError java/lang/LinkageError)
|
||||||
@ -171,6 +174,8 @@
|
|||||||
|
|
||||||
(type noSuchMethodError java/lang/NoSuchMethodError)
|
(type noSuchMethodError java/lang/NoSuchMethodError)
|
||||||
|
|
||||||
|
(type noClassDefFoundError java/lang/NoClassDefFoundError)
|
||||||
|
|
||||||
(type unsatisfiedLinkError java/lang/UnsatisfiedLinkError)
|
(type unsatisfiedLinkError java/lang/UnsatisfiedLinkError)
|
||||||
|
|
||||||
(type exceptionInInitializerError java/lang/ExceptionInInitializerError)
|
(type exceptionInInitializerError java/lang/ExceptionInInitializerError)
|
||||||
|
@ -110,6 +110,11 @@ class Vector {
|
|||||||
append(&v, BytesPerWord);
|
append(&v, BytesPerWord);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void set2(unsigned offset, uint16_t v) {
|
||||||
|
assert(s, offset <= position - 2);
|
||||||
|
memcpy(data + offset, &v, 2);
|
||||||
|
}
|
||||||
|
|
||||||
unsigned get(unsigned offset) {
|
unsigned get(unsigned offset) {
|
||||||
uint8_t v; get(offset, &v, 1);
|
uint8_t v; get(offset, &v, 1);
|
||||||
return v;
|
return v;
|
||||||
|
@ -574,11 +574,20 @@ class MySystem: public System {
|
|||||||
if (handler) {
|
if (handler) {
|
||||||
segFaultHandler = handler;
|
segFaultHandler = handler;
|
||||||
|
|
||||||
|
#ifdef __i386__
|
||||||
oldSegFaultHandler = SetUnhandledExceptionFilter(handleException);
|
oldSegFaultHandler = SetUnhandledExceptionFilter(handleException);
|
||||||
|
#elif defined __x86_64__
|
||||||
|
AddVectoredExceptionHandler(1, handleException);
|
||||||
|
oldSegFaultHandler = 0;
|
||||||
|
#endif
|
||||||
return 0;
|
return 0;
|
||||||
} else if (segFaultHandler) {
|
} else if (segFaultHandler) {
|
||||||
segFaultHandler = 0;
|
segFaultHandler = 0;
|
||||||
|
#ifdef __i386__
|
||||||
SetUnhandledExceptionFilter(oldSegFaultHandler);
|
SetUnhandledExceptionFilter(oldSegFaultHandler);
|
||||||
|
#elif defined __x86_64__
|
||||||
|
//do nothing, handlers are never "unregistered" anyway
|
||||||
|
#endif
|
||||||
return 0;
|
return 0;
|
||||||
} else {
|
} else {
|
||||||
return 1;
|
return 1;
|
||||||
@ -600,10 +609,15 @@ class MySystem: public System {
|
|||||||
CONTEXT context;
|
CONTEXT context;
|
||||||
rv = GetThreadContext(target->thread, &context);
|
rv = GetThreadContext(target->thread, &context);
|
||||||
expect(this, rv);
|
expect(this, rv);
|
||||||
|
#ifdef __i386__
|
||||||
visitor->visit(reinterpret_cast<void*>(context.Eip),
|
visitor->visit(reinterpret_cast<void*>(context.Eip),
|
||||||
reinterpret_cast<void*>(context.Ebp),
|
reinterpret_cast<void*>(context.Ebp),
|
||||||
reinterpret_cast<void*>(context.Esp));
|
reinterpret_cast<void*>(context.Esp));
|
||||||
|
#elif defined __x86_64__
|
||||||
|
visitor->visit(reinterpret_cast<void*>(context.Rip),
|
||||||
|
reinterpret_cast<void*>(context.Rbp),
|
||||||
|
reinterpret_cast<void*>(context.Rsp));
|
||||||
|
#endif
|
||||||
|
|
||||||
rv = ResumeThread(target->thread);
|
rv = ResumeThread(target->thread);
|
||||||
expect(this, rv != -1);
|
expect(this, rv != -1);
|
||||||
@ -798,7 +812,7 @@ dump(LPEXCEPTION_POINTERS e, const char* directory)
|
|||||||
char name[MAX_PATH];
|
char name[MAX_PATH];
|
||||||
_timeb tb;
|
_timeb tb;
|
||||||
_ftime(&tb);
|
_ftime(&tb);
|
||||||
snprintf(name, MAX_PATH, "%s\\crash-%lld.mdmp", directory,
|
snprintf(name, MAX_PATH, "%s\\crash-%"LLD".mdmp", directory,
|
||||||
(static_cast<int64_t>(tb.time) * 1000)
|
(static_cast<int64_t>(tb.time) * 1000)
|
||||||
+ static_cast<int64_t>(tb.millitm));
|
+ static_cast<int64_t>(tb.millitm));
|
||||||
|
|
||||||
@ -830,18 +844,31 @@ LONG CALLBACK
|
|||||||
handleException(LPEXCEPTION_POINTERS e)
|
handleException(LPEXCEPTION_POINTERS e)
|
||||||
{
|
{
|
||||||
if (e->ExceptionRecord->ExceptionCode == EXCEPTION_ACCESS_VIOLATION) {
|
if (e->ExceptionRecord->ExceptionCode == EXCEPTION_ACCESS_VIOLATION) {
|
||||||
|
#ifdef __i386__
|
||||||
void* ip = reinterpret_cast<void*>(e->ContextRecord->Eip);
|
void* ip = reinterpret_cast<void*>(e->ContextRecord->Eip);
|
||||||
void* base = reinterpret_cast<void*>(e->ContextRecord->Ebp);
|
void* base = reinterpret_cast<void*>(e->ContextRecord->Ebp);
|
||||||
void* stack = reinterpret_cast<void*>(e->ContextRecord->Esp);
|
void* stack = reinterpret_cast<void*>(e->ContextRecord->Esp);
|
||||||
void* thread = reinterpret_cast<void*>(e->ContextRecord->Ebx);
|
void* thread = reinterpret_cast<void*>(e->ContextRecord->Ebx);
|
||||||
|
#elif defined __x86_64__
|
||||||
|
void* ip = reinterpret_cast<void*>(e->ContextRecord->Rip);
|
||||||
|
void* base = reinterpret_cast<void*>(e->ContextRecord->Rbp);
|
||||||
|
void* stack = reinterpret_cast<void*>(e->ContextRecord->Rsp);
|
||||||
|
void* thread = reinterpret_cast<void*>(e->ContextRecord->Rbx);
|
||||||
|
#endif
|
||||||
|
|
||||||
bool jump = system->segFaultHandler->handleSignal
|
bool jump = system->segFaultHandler->handleSignal
|
||||||
(&ip, &base, &stack, &thread);
|
(&ip, &base, &stack, &thread);
|
||||||
|
#ifdef __i386__
|
||||||
e->ContextRecord->Eip = reinterpret_cast<DWORD>(ip);
|
e->ContextRecord->Eip = reinterpret_cast<DWORD>(ip);
|
||||||
e->ContextRecord->Ebp = reinterpret_cast<DWORD>(base);
|
e->ContextRecord->Ebp = reinterpret_cast<DWORD>(base);
|
||||||
e->ContextRecord->Esp = reinterpret_cast<DWORD>(stack);
|
e->ContextRecord->Esp = reinterpret_cast<DWORD>(stack);
|
||||||
e->ContextRecord->Ebx = reinterpret_cast<DWORD>(thread);
|
e->ContextRecord->Ebx = reinterpret_cast<DWORD>(thread);
|
||||||
|
#elif defined __x86_64__
|
||||||
|
e->ContextRecord->Rip = reinterpret_cast<DWORD64>(ip);
|
||||||
|
e->ContextRecord->Rbp = reinterpret_cast<DWORD64>(base);
|
||||||
|
e->ContextRecord->Rsp = reinterpret_cast<DWORD64>(stack);
|
||||||
|
e->ContextRecord->Rbx = reinterpret_cast<DWORD64>(thread);
|
||||||
|
#endif
|
||||||
|
|
||||||
if (jump) {
|
if (jump) {
|
||||||
return EXCEPTION_CONTINUE_EXECUTION;
|
return EXCEPTION_CONTINUE_EXECUTION;
|
||||||
|
161
src/x86.S
161
src/x86.S
@ -8,16 +8,145 @@
|
|||||||
There is NO WARRANTY for this software. See license.txt for
|
There is NO WARRANTY for this software. See license.txt for
|
||||||
details. */
|
details. */
|
||||||
|
|
||||||
|
|
||||||
#include "types.h"
|
#include "types.h"
|
||||||
|
|
||||||
#define LOCAL(x) .L##x
|
#define LOCAL(x) .L##x
|
||||||
|
|
||||||
|
#if defined __APPLE__ || defined __MINGW32__ || defined __CYGWIN32__
|
||||||
|
# define GLOBAL(x) _##x
|
||||||
|
#else
|
||||||
|
# define GLOBAL(x) x
|
||||||
|
#endif
|
||||||
|
|
||||||
.text
|
.text
|
||||||
|
|
||||||
#ifdef __x86_64__
|
#ifdef __x86_64__
|
||||||
|
|
||||||
.globl vmNativeCall
|
#ifdef __MINGW32__
|
||||||
vmNativeCall:
|
|
||||||
|
.globl GLOBAL(vmNativeCall)
|
||||||
|
GLOBAL(vmNativeCall):
|
||||||
|
pushq %rbp
|
||||||
|
//save nonvolatile registers
|
||||||
|
pushq %r12
|
||||||
|
pushq %r13
|
||||||
|
pushq %r14
|
||||||
|
pushq %r15
|
||||||
|
movq %rsp, %rbp
|
||||||
|
|
||||||
|
|
||||||
|
// %rcx: function
|
||||||
|
// %rdx: arguments
|
||||||
|
// %r8: arguments count
|
||||||
|
// %r9: return type
|
||||||
|
|
||||||
|
movq %rcx, %r10
|
||||||
|
movq %rdx, %r11
|
||||||
|
movq %r8, %r12
|
||||||
|
movq %r9, %r13
|
||||||
|
|
||||||
|
// %r10: function
|
||||||
|
// %r11: arguments
|
||||||
|
// %r12: arguments count
|
||||||
|
// %r13: return type
|
||||||
|
|
||||||
|
//allocate initial stack space
|
||||||
|
subq $32, %rsp
|
||||||
|
|
||||||
|
//first arg
|
||||||
|
cmp $0, %r12
|
||||||
|
je LOCAL(call)
|
||||||
|
movq 0(%r11),%rcx
|
||||||
|
movq 0(%r11),%xmm0
|
||||||
|
subq $1, %r12
|
||||||
|
|
||||||
|
//second arg
|
||||||
|
cmp $0, %r12
|
||||||
|
je LOCAL(call)
|
||||||
|
movq 8(%r11),%rdx
|
||||||
|
movq 8(%r11),%xmm1
|
||||||
|
subq $1, %r12
|
||||||
|
|
||||||
|
//third arg
|
||||||
|
cmp $0, %r12
|
||||||
|
je LOCAL(call)
|
||||||
|
movq 16(%r11),%r8
|
||||||
|
movq 16(%r11),%xmm2
|
||||||
|
subq $1, %r12
|
||||||
|
|
||||||
|
//fourth arg
|
||||||
|
cmp $0, %r12
|
||||||
|
je LOCAL(call)
|
||||||
|
movq 24(%r11),%r9
|
||||||
|
movq 24(%r11),%xmm3
|
||||||
|
subq $1, %r12
|
||||||
|
|
||||||
|
|
||||||
|
//calculate stack space for arguments, aligned
|
||||||
|
movq $8, %r15
|
||||||
|
leaq (%r15, %r12, 8), %r15
|
||||||
|
andq $0xFFFFFFFFFFFFFFF0, %r15
|
||||||
|
|
||||||
|
//reserve stack space for arguments
|
||||||
|
subq %r15, %rsp
|
||||||
|
|
||||||
|
//reset the counter
|
||||||
|
addq $3, %r12
|
||||||
|
jmp LOCAL(loopend)
|
||||||
|
|
||||||
|
LOCAL(loop):
|
||||||
|
movq (%r11, %r12, 8), %r14
|
||||||
|
movq %r14, (%rsp, %r12, 8);
|
||||||
|
subq $1, %r12
|
||||||
|
|
||||||
|
LOCAL(loopend):
|
||||||
|
//we don't need to move arg 3 and lower
|
||||||
|
cmpq $3, %r12
|
||||||
|
jne LOCAL(loop)
|
||||||
|
|
||||||
|
LOCAL(call):
|
||||||
|
call *%r10
|
||||||
|
|
||||||
|
LOCAL(void):
|
||||||
|
cmpq $VOID_TYPE,%r13
|
||||||
|
jne LOCAL(float)
|
||||||
|
jmp LOCAL(exit)
|
||||||
|
|
||||||
|
LOCAL(float):
|
||||||
|
cmpq $FLOAT_TYPE,%r13
|
||||||
|
je LOCAL(copy)
|
||||||
|
cmpq $DOUBLE_TYPE,%r13
|
||||||
|
jne LOCAL(exit)
|
||||||
|
|
||||||
|
LOCAL(copy):
|
||||||
|
movq %xmm0,%rax
|
||||||
|
|
||||||
|
LOCAL(exit):
|
||||||
|
|
||||||
|
movq %rbp, %rsp
|
||||||
|
//return nonvolatile registers to their former state
|
||||||
|
popq %r15
|
||||||
|
popq %r14
|
||||||
|
popq %r13
|
||||||
|
popq %r12
|
||||||
|
|
||||||
|
popq %rbp
|
||||||
|
ret
|
||||||
|
|
||||||
|
.globl GLOBAL(vmJump)
|
||||||
|
GLOBAL(vmJump):
|
||||||
|
movq %rdx,%rbp
|
||||||
|
movq 8(%rsp),%rax
|
||||||
|
movq 16(%rsp),%rdx
|
||||||
|
movq %r8,%rsp
|
||||||
|
movq %r9,%rbx
|
||||||
|
jmp *%rcx
|
||||||
|
|
||||||
|
#else // not __MINGW32__
|
||||||
|
|
||||||
|
.globl GLOBAL(vmNativeCall)
|
||||||
|
GLOBAL(vmNativeCall):
|
||||||
pushq %rbp
|
pushq %rbp
|
||||||
movq %rsp,%rbp
|
movq %rsp,%rbp
|
||||||
|
|
||||||
@ -113,8 +242,8 @@ LOCAL(exit):
|
|||||||
popq %rbp
|
popq %rbp
|
||||||
ret
|
ret
|
||||||
|
|
||||||
.globl vmJump
|
.globl GLOBAL(vmJump)
|
||||||
vmJump:
|
GLOBAL(vmJump):
|
||||||
movq %rsi,%rbp
|
movq %rsi,%rbp
|
||||||
movq %rdx,%rsp
|
movq %rdx,%rsp
|
||||||
movq %rcx,%rbx
|
movq %rcx,%rbx
|
||||||
@ -122,15 +251,12 @@ vmJump:
|
|||||||
movq %r9,%rdx
|
movq %r9,%rdx
|
||||||
jmp *%rdi
|
jmp *%rdi
|
||||||
|
|
||||||
|
#endif // not __MINGW32__
|
||||||
|
|
||||||
#elif defined __i386__
|
#elif defined __i386__
|
||||||
|
|
||||||
# if defined __APPLE__ || defined __MINGW32__ || defined __CYGWIN32__
|
.globl GLOBAL(vmNativeCall)
|
||||||
.globl _vmNativeCall
|
GLOBAL(vmNativeCall):
|
||||||
_vmNativeCall:
|
|
||||||
# else
|
|
||||||
.globl vmNativeCall
|
|
||||||
vmNativeCall:
|
|
||||||
# endif
|
|
||||||
pushl %ebp
|
pushl %ebp
|
||||||
movl %esp,%ebp
|
movl %esp,%ebp
|
||||||
|
|
||||||
@ -201,13 +327,8 @@ LOCAL(exit):
|
|||||||
popl %ebp
|
popl %ebp
|
||||||
ret
|
ret
|
||||||
|
|
||||||
# if defined __APPLE__ || defined __MINGW32__ || defined __CYGWIN32__
|
.globl GLOBAL(vmJump)
|
||||||
.globl _vmJump
|
GLOBAL(vmJump):
|
||||||
_vmJump:
|
|
||||||
# else
|
|
||||||
.globl vmJump
|
|
||||||
vmJump:
|
|
||||||
# endif
|
|
||||||
movl 4(%esp),%esi
|
movl 4(%esp),%esi
|
||||||
movl 8(%esp),%ebp
|
movl 8(%esp),%ebp
|
||||||
movl 16(%esp),%ebx
|
movl 16(%esp),%ebx
|
||||||
@ -216,6 +337,4 @@ vmJump:
|
|||||||
movl 12(%esp),%esp
|
movl 12(%esp),%esp
|
||||||
jmp *%esi
|
jmp *%esi
|
||||||
|
|
||||||
#else
|
#endif //def __x86_64__
|
||||||
# error unsupported platform
|
|
||||||
#endif
|
|
||||||
|
677
src/x86.cpp
677
src/x86.cpp
File diff suppressed because it is too large
Load Diff
14
src/x86.h
14
src/x86.h
@ -58,11 +58,24 @@ dynamicCall(void* function, uintptr_t* arguments, uint8_t*,
|
|||||||
# define THREAD_REGISTER(context) (context->uc_mcontext.gregs[REG_RBX])
|
# define THREAD_REGISTER(context) (context->uc_mcontext.gregs[REG_RBX])
|
||||||
|
|
||||||
extern "C" uint64_t
|
extern "C" uint64_t
|
||||||
|
# ifdef __MINGW32__
|
||||||
|
vmNativeCall(void* function, void* stack, unsigned stackSize,
|
||||||
|
unsigned returnType);
|
||||||
|
# else
|
||||||
vmNativeCall(void* function, void* stack, unsigned stackSize,
|
vmNativeCall(void* function, void* stack, unsigned stackSize,
|
||||||
void* gprTable, void* sseTable, unsigned returnType);
|
void* gprTable, void* sseTable, unsigned returnType);
|
||||||
|
# endif
|
||||||
|
|
||||||
namespace vm {
|
namespace vm {
|
||||||
|
|
||||||
|
# ifdef __MINGW32__
|
||||||
|
inline uint64_t
|
||||||
|
dynamicCall(void* function, uint64_t* arguments, UNUSED uint8_t* argumentTypes,
|
||||||
|
unsigned argumentCount, unsigned, unsigned returnType)
|
||||||
|
{
|
||||||
|
return vmNativeCall(function, arguments, argumentCount, returnType);
|
||||||
|
}
|
||||||
|
# else
|
||||||
inline uint64_t
|
inline uint64_t
|
||||||
dynamicCall(void* function, uint64_t* arguments, uint8_t* argumentTypes,
|
dynamicCall(void* function, uint64_t* arguments, uint8_t* argumentTypes,
|
||||||
unsigned argumentCount, unsigned, unsigned returnType)
|
unsigned argumentCount, unsigned, unsigned returnType)
|
||||||
@ -103,6 +116,7 @@ dynamicCall(void* function, uint64_t* arguments, uint8_t* argumentTypes,
|
|||||||
(gprIndex ? gprTable : 0),
|
(gprIndex ? gprTable : 0),
|
||||||
(sseIndex ? sseTable : 0), returnType);
|
(sseIndex ? sseTable : 0), returnType);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
} // namespace vm
|
} // namespace vm
|
||||||
|
|
||||||
|
34
test/Finalizers.java
Normal file
34
test/Finalizers.java
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
public class Finalizers {
|
||||||
|
private static boolean finalized = false;
|
||||||
|
|
||||||
|
private static void expect(boolean v) {
|
||||||
|
if (! v) throw new RuntimeException();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void finalize() {
|
||||||
|
finalized = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
new Finalizers();
|
||||||
|
|
||||||
|
expect(! finalized);
|
||||||
|
|
||||||
|
System.gc();
|
||||||
|
|
||||||
|
expect(finalized);
|
||||||
|
|
||||||
|
new Finalizers2();
|
||||||
|
|
||||||
|
finalized = false;
|
||||||
|
|
||||||
|
expect(! finalized);
|
||||||
|
|
||||||
|
System.gc();
|
||||||
|
|
||||||
|
expect(finalized);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class Finalizers2 extends Finalizers { }
|
||||||
|
|
||||||
|
}
|
@ -3,13 +3,14 @@ public class Subroutine {
|
|||||||
if (! v) throw new RuntimeException();
|
if (! v) throw new RuntimeException();
|
||||||
}
|
}
|
||||||
|
|
||||||
// This test is intended to cover the jsr and ret instructions.
|
// These tests are intended to cover the jsr and ret instructions.
|
||||||
// However, recent Sun javac versions avoid generating these
|
// However, recent Sun javac versions avoid generating these
|
||||||
// instructions by default, so we must compile this class using
|
// instructions by default, so we must compile this class using
|
||||||
// -source 1.2 -target 1.1 -XDjsrlimit=0.
|
// -source 1.2 -target 1.1 -XDjsrlimit=0.
|
||||||
//
|
//
|
||||||
// http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4381996
|
// http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4381996
|
||||||
//
|
//
|
||||||
|
|
||||||
private static void test(boolean throw_, boolean predicate) {
|
private static void test(boolean throw_, boolean predicate) {
|
||||||
int x = 42;
|
int x = 42;
|
||||||
int y = 99;
|
int y = 99;
|
||||||
@ -32,10 +33,159 @@ public class Subroutine {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static Object test2(int path) {
|
||||||
|
try {
|
||||||
|
try {
|
||||||
|
switch (path) {
|
||||||
|
case 1:
|
||||||
|
return new Object();
|
||||||
|
|
||||||
|
case 2: {
|
||||||
|
int a = 42;
|
||||||
|
return Integer.valueOf(a);
|
||||||
|
}
|
||||||
|
|
||||||
|
case 3:
|
||||||
|
throw new DummyException();
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
System.gc();
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
} catch (DummyException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Object test3(int path1, int path2, int path3) {
|
||||||
|
try {
|
||||||
|
try {
|
||||||
|
switch (path1) {
|
||||||
|
case 1:
|
||||||
|
return new Object();
|
||||||
|
|
||||||
|
case 2: {
|
||||||
|
int a = 42;
|
||||||
|
return Integer.valueOf(a);
|
||||||
|
}
|
||||||
|
|
||||||
|
case 3:
|
||||||
|
throw new DummyException();
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
try {
|
||||||
|
switch (path2) {
|
||||||
|
case 1:
|
||||||
|
return new Object();
|
||||||
|
|
||||||
|
case 2: {
|
||||||
|
int a = 42;
|
||||||
|
return Integer.valueOf(a);
|
||||||
|
}
|
||||||
|
|
||||||
|
case 3:
|
||||||
|
throw new DummyException();
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
try {
|
||||||
|
switch (path3) {
|
||||||
|
case 1:
|
||||||
|
return new Object();
|
||||||
|
|
||||||
|
case 2: {
|
||||||
|
int a = 42;
|
||||||
|
return Integer.valueOf(a);
|
||||||
|
}
|
||||||
|
|
||||||
|
case 3:
|
||||||
|
throw new DummyException();
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
System.gc();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
} catch (DummyException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static long test4(int path) {
|
||||||
|
try {
|
||||||
|
try {
|
||||||
|
switch (path) {
|
||||||
|
case 1:
|
||||||
|
return 42L;
|
||||||
|
|
||||||
|
case 2: {
|
||||||
|
int a = 42;
|
||||||
|
return 52L;
|
||||||
|
}
|
||||||
|
|
||||||
|
case 3:
|
||||||
|
throw new DummyException();
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
System.gc();
|
||||||
|
}
|
||||||
|
return 0L;
|
||||||
|
} catch (DummyException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
return 0L;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public static void main(String[] args) {
|
public static void main(String[] args) {
|
||||||
test(false, false);
|
test(false, false);
|
||||||
test(false, true);
|
test(false, true);
|
||||||
test(true, false);
|
test(true, false);
|
||||||
|
|
||||||
|
String.valueOf(test2(1));
|
||||||
|
String.valueOf(test2(2));
|
||||||
|
String.valueOf(test2(3));
|
||||||
|
|
||||||
|
String.valueOf(test3(1, 1, 1));
|
||||||
|
String.valueOf(test3(2, 1, 1));
|
||||||
|
String.valueOf(test3(3, 1, 1));
|
||||||
|
|
||||||
|
String.valueOf(test3(1, 2, 1));
|
||||||
|
String.valueOf(test3(2, 2, 1));
|
||||||
|
String.valueOf(test3(3, 2, 1));
|
||||||
|
|
||||||
|
String.valueOf(test3(1, 3, 1));
|
||||||
|
String.valueOf(test3(2, 3, 1));
|
||||||
|
String.valueOf(test3(3, 3, 1));
|
||||||
|
|
||||||
|
String.valueOf(test3(1, 1, 2));
|
||||||
|
String.valueOf(test3(2, 1, 2));
|
||||||
|
String.valueOf(test3(3, 1, 2));
|
||||||
|
|
||||||
|
String.valueOf(test3(1, 2, 2));
|
||||||
|
String.valueOf(test3(2, 2, 2));
|
||||||
|
String.valueOf(test3(3, 2, 2));
|
||||||
|
|
||||||
|
String.valueOf(test3(1, 3, 2));
|
||||||
|
String.valueOf(test3(2, 3, 2));
|
||||||
|
String.valueOf(test3(3, 3, 2));
|
||||||
|
|
||||||
|
String.valueOf(test3(1, 1, 3));
|
||||||
|
String.valueOf(test3(2, 1, 3));
|
||||||
|
String.valueOf(test3(3, 1, 3));
|
||||||
|
|
||||||
|
String.valueOf(test3(1, 2, 3));
|
||||||
|
String.valueOf(test3(2, 2, 3));
|
||||||
|
String.valueOf(test3(3, 2, 3));
|
||||||
|
|
||||||
|
String.valueOf(test3(1, 3, 3));
|
||||||
|
String.valueOf(test3(2, 3, 3));
|
||||||
|
String.valueOf(test3(3, 3, 3));
|
||||||
|
|
||||||
|
String.valueOf(test4(1));
|
||||||
|
String.valueOf(test4(2));
|
||||||
|
String.valueOf(test4(3));
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class DummyException extends RuntimeException { }
|
private static class DummyException extends RuntimeException { }
|
||||||
|
@ -88,26 +88,4 @@ public class Tree {
|
|||||||
|
|
||||||
isEqual(printMap(map), "a=A, b=B, c=C, q=Q, y=Y, z=Z");
|
isEqual(printMap(map), "a=A, b=B, c=C, q=Q, y=Y, z=Z");
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class MyEntry<K,V> implements Map.Entry<K,V> {
|
|
||||||
public final K key;
|
|
||||||
public V value;
|
|
||||||
|
|
||||||
public MyEntry(K key, V value) {
|
|
||||||
this.key = key;
|
|
||||||
this.value = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
public K getKey() {
|
|
||||||
return key;
|
|
||||||
}
|
|
||||||
|
|
||||||
public V getValue() {
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setValue(V value) {
|
|
||||||
this.value = value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -9,7 +9,9 @@ public class Zip {
|
|||||||
ZipFile file = new ZipFile("build/classpath.jar");
|
ZipFile file = new ZipFile("build/classpath.jar");
|
||||||
|
|
||||||
byte[] buffer = new byte[4096];
|
byte[] buffer = new byte[4096];
|
||||||
for (Enumeration<ZipEntry> e = file.entries(); e.hasMoreElements();) {
|
for (Enumeration<? extends ZipEntry> e = file.entries();
|
||||||
|
e.hasMoreElements();)
|
||||||
|
{
|
||||||
ZipEntry entry = e.nextElement();
|
ZipEntry entry = e.nextElement();
|
||||||
InputStream in = file.getInputStream(entry);
|
InputStream in = file.getInputStream(entry);
|
||||||
try {
|
try {
|
||||||
|
4
vm.pro
4
vm.pro
@ -73,7 +73,9 @@
|
|||||||
|
|
||||||
# Thread.run is called by name in the VM
|
# Thread.run is called by name in the VM
|
||||||
|
|
||||||
-keepclassmembernames class java.lang.Thread { void run(); }
|
-keepclassmembers class java.lang.Thread {
|
||||||
|
private static void run(java.lang.Thread);
|
||||||
|
}
|
||||||
|
|
||||||
# when continuations are enabled, the VM may call these methods by name:
|
# when continuations are enabled, the VM may call these methods by name:
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user