mirror of
https://github.com/corda/corda.git
synced 2025-06-14 05:08:18 +00:00
Merge remote-tracking branch 'rt/master'
This commit is contained in:
@ -8,7 +8,9 @@ os:
|
|||||||
env:
|
env:
|
||||||
matrix:
|
matrix:
|
||||||
- BUILD_STEP=""
|
- BUILD_STEP=""
|
||||||
- BUILD_STEP="PUBLISH"
|
# disabled until/unless jfrog.org credentials are updated and someone
|
||||||
|
# decides they care about published artifacts:
|
||||||
|
# - BUILD_STEP="PUBLISH"
|
||||||
global:
|
global:
|
||||||
- TERM=dumb
|
- TERM=dumb
|
||||||
- secure: rh1utD4shKmYtokItuRYEF9WsfTnvZO5XqnTU4DHTS7quHHgLihtOO2/3+B+2W2hEd5Obr2or8zx+zmzWcNUyLokZ0j/FRLWSScNkLzTtm12pupLrncY+/g1NIdfbhn+OLRIzBz6zB6m6a2qWFEJ+bScUNGD/7wZVtzkujqlDEE=
|
- secure: rh1utD4shKmYtokItuRYEF9WsfTnvZO5XqnTU4DHTS7quHHgLihtOO2/3+B+2W2hEd5Obr2or8zx+zmzWcNUyLokZ0j/FRLWSScNkLzTtm12pupLrncY+/g1NIdfbhn+OLRIzBz6zB6m6a2qWFEJ+bScUNGD/7wZVtzkujqlDEE=
|
||||||
|
24
README.md
24
README.md
@ -45,7 +45,7 @@ Introduction
|
|||||||
Avian is a lightweight virtual machine and class library designed to
|
Avian is a lightweight virtual machine and class library designed to
|
||||||
provide a useful subset of Java's features, suitable for building
|
provide a useful subset of Java's features, suitable for building
|
||||||
self-contained applications. More information is available at the
|
self-contained applications. More information is available at the
|
||||||
project [web site](http://oss.readytalk.com/avian).
|
project [web site](http://readytalk.github.io/avian).
|
||||||
|
|
||||||
If you have any trouble building, running, or embedding Avian, please
|
If you have any trouble building, running, or embedding Avian, please
|
||||||
post a message to our [discussion group](http://groups.google.com/group/avian).
|
post a message to our [discussion group](http://groups.google.com/group/avian).
|
||||||
@ -168,8 +168,8 @@ Library" below for details.
|
|||||||
These flags determine the name of the directory used for the build.
|
These flags determine the name of the directory used for the build.
|
||||||
The name always starts with _${platform}-${arch}_, and each non-default
|
The name always starts with _${platform}-${arch}_, and each non-default
|
||||||
build option is appended to the name. For example, a debug build with
|
build option is appended to the name. For example, a debug build with
|
||||||
bootimage enabled on Linux/i386 would be built in
|
bootimage enabled on Linux/x86_64 would be built in
|
||||||
_build/linux-i386-debug-bootimage_. This allows you to build with
|
_build/linux-x86_64-debug-bootimage_. This allows you to build with
|
||||||
several different sets of options independently and even
|
several different sets of options independently and even
|
||||||
simultaneously without doing a clean build each time.
|
simultaneously without doing a clean build each time.
|
||||||
|
|
||||||
@ -293,9 +293,10 @@ You can reduce the size futher for embedded builds by using ProGuard
|
|||||||
and the supplied openjdk.pro configuration file (see "Embedding with
|
and the supplied openjdk.pro configuration file (see "Embedding with
|
||||||
ProGuard and a Boot Image" below). Note that you'll still need to use
|
ProGuard and a Boot Image" below). Note that you'll still need to use
|
||||||
vm.pro in that case -- openjdk.pro just adds additional constraints
|
vm.pro in that case -- openjdk.pro just adds additional constraints
|
||||||
specific to the OpenJDK port. Also see app.mk in
|
specific to the OpenJDK port. Also see
|
||||||
_git://oss.readytalk.com/avian-swt-examples.git_ for an example of using
|
[app.mk](https://github.com/ReadyTalk/avian-swt-examples/blob/master/app.mk)
|
||||||
Avian, OpenJDK, ProGuard, and UPX in concert.
|
in the _avian-swt-examples_ project for an example of using Avian,
|
||||||
|
OpenJDK, ProGuard, and UPX in concert.
|
||||||
|
|
||||||
Here are some examples of how to install OpenJDK and build Avian with
|
Here are some examples of how to install OpenJDK and build Avian with
|
||||||
it on various OSes:
|
it on various OSes:
|
||||||
@ -575,7 +576,7 @@ For boot image builds:
|
|||||||
Note you can use ProGuard without using a boot image and vice-versa,
|
Note you can use ProGuard without using a boot image and vice-versa,
|
||||||
as desired.
|
as desired.
|
||||||
|
|
||||||
The following instructions assume we are building for Linux/i386.
|
The following instructions assume we are building for Linux/x86_64.
|
||||||
Please refer to the previous example for guidance on other platforms.
|
Please refer to the previous example for guidance on other platforms.
|
||||||
|
|
||||||
__1.__ Build Avian, create a new directory, and populate it with the
|
__1.__ Build Avian, create a new directory, and populate it with the
|
||||||
@ -584,13 +585,13 @@ VM object files.
|
|||||||
$ make bootimage=true
|
$ make bootimage=true
|
||||||
$ mkdir hello
|
$ mkdir hello
|
||||||
$ cd hello
|
$ cd hello
|
||||||
$ ar x ../build/linux-i386-bootimage/libavian.a
|
$ ar x ../build/linux-x86_64-bootimage/libavian.a
|
||||||
|
|
||||||
__2.__ Create a stage1 directory and extract the contents of the
|
__2.__ Create a stage1 directory and extract the contents of the
|
||||||
class library jar into it.
|
class library jar into it.
|
||||||
|
|
||||||
$ mkdir stage1
|
$ mkdir stage1
|
||||||
$ (cd stage1 && jar xf ../../build/linux-i386-bootimage/classpath.jar)
|
$ (cd stage1 && jar xf ../../build/linux-x86_64-bootimage/classpath.jar)
|
||||||
|
|
||||||
__3.__ Build the Java code and add it to stage1.
|
__3.__ Build the Java code and add it to stage1.
|
||||||
|
|
||||||
@ -630,10 +631,11 @@ using the OpenJDK library.)
|
|||||||
|
|
||||||
__6.__ Build the boot and code images.
|
__6.__ Build the boot and code images.
|
||||||
|
|
||||||
$ ../build/linux-i386-bootimage/bootimage-generator \
|
$ ../build/linux-x86_64-bootimage/bootimage-generator \
|
||||||
-cp stage2 \
|
-cp stage2 \
|
||||||
-bootimage bootimage-bin.o \
|
-bootimage bootimage-bin.o \
|
||||||
-codeimage codeimage-bin.o
|
-codeimage codeimage-bin.o \
|
||||||
|
-hostvm ../build/linux-x86_64-interpret/libjvm.so
|
||||||
|
|
||||||
Note that you can override the default names for the start and end
|
Note that you can override the default names for the start and end
|
||||||
symbols in the boot/code image by also passing:
|
symbols in the boot/code image by also passing:
|
||||||
|
@ -423,6 +423,27 @@ public class Classes {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static VMMethod findMethod(ClassLoader loader,
|
||||||
|
String class_,
|
||||||
|
String name,
|
||||||
|
String spec)
|
||||||
|
throws ClassNotFoundException
|
||||||
|
{
|
||||||
|
VMClass c = SystemClassLoader.vmClass(loader.loadClass(class_));
|
||||||
|
VMMethod[] methodTable = c.methodTable;
|
||||||
|
if (methodTable != null) {
|
||||||
|
link(c);
|
||||||
|
|
||||||
|
for (int i = 0; i < methodTable.length; ++i) {
|
||||||
|
VMMethod m = methodTable[i];
|
||||||
|
if (toString(m.name).equals(name) && toString(m.spec).equals(spec)) {
|
||||||
|
return m;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
public static int findMethod(VMClass vmClass, String name,
|
public static int findMethod(VMClass vmClass, String name,
|
||||||
Class[] parameterTypes)
|
Class[] parameterTypes)
|
||||||
{
|
{
|
||||||
|
@ -20,6 +20,8 @@ import java.util.Enumeration;
|
|||||||
import java.util.NoSuchElementException;
|
import java.util.NoSuchElementException;
|
||||||
|
|
||||||
public class SystemClassLoader extends ClassLoader {
|
public class SystemClassLoader extends ClassLoader {
|
||||||
|
public static native ClassLoader appLoader();
|
||||||
|
|
||||||
private native VMClass findVMClass(String name)
|
private native VMClass findVMClass(String name)
|
||||||
throws ClassNotFoundException;
|
throws ClassNotFoundException;
|
||||||
|
|
||||||
@ -81,6 +83,8 @@ public class SystemClassLoader extends ClassLoader {
|
|||||||
if (source != null) {
|
if (source != null) {
|
||||||
// todo: load attributes from JAR manifest
|
// todo: load attributes from JAR manifest
|
||||||
definePackage(name, null, null, null, null, null, null, null);
|
definePackage(name, null, null, null, null, null, null, null);
|
||||||
|
} else {
|
||||||
|
definePackage(name, null, null, null, null, null, null, null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -10,17 +10,111 @@
|
|||||||
|
|
||||||
package avian.http;
|
package avian.http;
|
||||||
|
|
||||||
import java.net.URL;
|
import java.io.BufferedInputStream;
|
||||||
import java.net.URLStreamHandler;
|
import java.io.BufferedReader;
|
||||||
import java.net.URLConnection;
|
import java.io.BufferedWriter;
|
||||||
|
import java.io.ByteArrayInputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.FileNotFoundException;
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.FileInputStream;
|
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
|
import java.io.InputStreamReader;
|
||||||
|
import java.io.OutputStream;
|
||||||
|
import java.io.OutputStreamWriter;
|
||||||
|
import java.net.Socket;
|
||||||
|
import java.net.URL;
|
||||||
|
import java.net.URLConnection;
|
||||||
|
import java.net.URLStreamHandler;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
public class Handler extends URLStreamHandler {
|
public class Handler extends URLStreamHandler
|
||||||
protected URLConnection openConnection(URL url) {
|
{
|
||||||
throw new UnsupportedOperationException();
|
public URLConnection openConnection(URL url) throws IOException
|
||||||
}
|
{
|
||||||
|
return new HttpURLConnection(url);
|
||||||
|
}
|
||||||
|
|
||||||
|
class HttpURLConnection extends URLConnection
|
||||||
|
{
|
||||||
|
Socket socket;
|
||||||
|
private BufferedWriter writer;
|
||||||
|
private InputStream bin;
|
||||||
|
private Map<String,String> header = new HashMap<String, String>();
|
||||||
|
private int status;
|
||||||
|
|
||||||
|
protected HttpURLConnection(URL url)
|
||||||
|
{
|
||||||
|
super(url);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void connect() throws IOException
|
||||||
|
{
|
||||||
|
if(socket == null)
|
||||||
|
{
|
||||||
|
URLConnection con = null;
|
||||||
|
String host = url.getHost();
|
||||||
|
int port =url.getPort();
|
||||||
|
if(port < 0) port = 80;
|
||||||
|
socket = new Socket(host, port);
|
||||||
|
OutputStream out = socket.getOutputStream();
|
||||||
|
writer = new BufferedWriter(new OutputStreamWriter(out));
|
||||||
|
writer.write("GET " + url.getPath() + " HTTP/1.1");
|
||||||
|
writer.write("\r\nHost: " + host);
|
||||||
|
writer.write("\r\n\r\n");
|
||||||
|
writer.flush();
|
||||||
|
bin = new BufferedInputStream(socket.getInputStream());
|
||||||
|
readHeader();
|
||||||
|
// System.out.println("Status: " + status);
|
||||||
|
// System.out.println("Headers: " + header);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void readHeader() throws IOException
|
||||||
|
{
|
||||||
|
byte[] buf = new byte[8192];
|
||||||
|
int b = 0;
|
||||||
|
int index = 0;
|
||||||
|
while(b >= 0)
|
||||||
|
{
|
||||||
|
if(index >= 4 && buf[index-4] == '\r' && buf[index-3] == '\n' && buf[index-2] == '\r' && buf[index-1] == '\n')
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
b = bin.read();
|
||||||
|
buf[index] = (byte) b;
|
||||||
|
index++;
|
||||||
|
if(index >= buf.length)
|
||||||
|
{
|
||||||
|
throw new IOException("Header exceeded maximum size of 8k.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
BufferedReader reader = new BufferedReader(new InputStreamReader(new ByteArrayInputStream(buf, 0, index)));
|
||||||
|
String line = reader.readLine();
|
||||||
|
int x = line.indexOf(' ');
|
||||||
|
status = Integer.parseInt(line.substring(x + 1 , line.indexOf(' ', x+1)));
|
||||||
|
while(line != null)
|
||||||
|
{
|
||||||
|
int i = line.indexOf(':');
|
||||||
|
if(i > 0)
|
||||||
|
{
|
||||||
|
header.put(line.substring(0, i), line.substring(i + 1) .trim());
|
||||||
|
}
|
||||||
|
line = reader.readLine();
|
||||||
|
}
|
||||||
|
reader.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public InputStream getInputStream() throws IOException
|
||||||
|
{
|
||||||
|
connect();
|
||||||
|
return bin;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public OutputStream getOutputStream() throws IOException
|
||||||
|
{
|
||||||
|
throw new UnsupportedOperationException("Can' write to HTTP Connection");
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -7,9 +7,11 @@
|
|||||||
|
|
||||||
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.io;
|
package java.io;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
|
||||||
public class BufferedInputStream extends InputStream {
|
public class BufferedInputStream extends InputStream {
|
||||||
private final InputStream in;
|
private final InputStream in;
|
||||||
private final byte[] buffer;
|
private final byte[] buffer;
|
||||||
@ -25,17 +27,16 @@ public class BufferedInputStream extends InputStream {
|
|||||||
this(in, 4096);
|
this(in, 4096);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void fill() throws IOException {
|
private int fill() throws IOException {
|
||||||
position = 0;
|
position = 0;
|
||||||
limit = in.read(buffer);
|
limit = in.read(buffer);
|
||||||
|
|
||||||
|
return limit;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int read() throws IOException {
|
public int read() throws IOException {
|
||||||
if (position >= limit) {
|
if (position >= limit && fill() == -1) {
|
||||||
fill();
|
return -1;
|
||||||
if (limit == -1) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return buffer[position++] & 0xFF;
|
return buffer[position++] & 0xFF;
|
||||||
@ -43,7 +44,9 @@ public class BufferedInputStream extends InputStream {
|
|||||||
|
|
||||||
public int read(byte[] b, int offset, int length) throws IOException {
|
public int read(byte[] b, int offset, int length) throws IOException {
|
||||||
int count = 0;
|
int count = 0;
|
||||||
|
if (position >= limit && fill() == -1) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
if (position < limit) {
|
if (position < limit) {
|
||||||
int remaining = limit - position;
|
int remaining = limit - position;
|
||||||
if (remaining > length) {
|
if (remaining > length) {
|
||||||
@ -57,8 +60,8 @@ public class BufferedInputStream extends InputStream {
|
|||||||
offset += remaining;
|
offset += remaining;
|
||||||
length -= remaining;
|
length -= remaining;
|
||||||
}
|
}
|
||||||
|
while (length > 0 && in.available() > 0)
|
||||||
while (length > 0) {
|
{
|
||||||
int c = in.read(b, offset, length);
|
int c = in.read(b, offset, length);
|
||||||
if (c == -1) {
|
if (c == -1) {
|
||||||
if (count == 0) {
|
if (count == 0) {
|
||||||
@ -69,13 +72,8 @@ public class BufferedInputStream extends InputStream {
|
|||||||
offset += c;
|
offset += c;
|
||||||
count += c;
|
count += c;
|
||||||
length -= c;
|
length -= c;
|
||||||
|
|
||||||
if (in.available() <= 0) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -87,3 +85,4 @@ public class BufferedInputStream extends InputStream {
|
|||||||
in.close();
|
in.close();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -15,7 +15,10 @@ import java.util.Random;
|
|||||||
public final class Math {
|
public final class Math {
|
||||||
public static final double E = 2.718281828459045;
|
public static final double E = 2.718281828459045;
|
||||||
public static final double PI = 3.141592653589793;
|
public static final double PI = 3.141592653589793;
|
||||||
private static final Random random = new Random();
|
|
||||||
|
private static class Static {
|
||||||
|
public static final Random random = new Random();
|
||||||
|
}
|
||||||
|
|
||||||
private Math() { }
|
private Math() { }
|
||||||
|
|
||||||
@ -84,7 +87,7 @@ public final class Math {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static double random() {
|
public static double random() {
|
||||||
return random.nextDouble();
|
return Static.random.nextDouble();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static native double floor(double v);
|
public static native double floor(double v);
|
||||||
|
@ -22,7 +22,9 @@ import java.util.Hashtable;
|
|||||||
import java.util.Properties;
|
import java.util.Properties;
|
||||||
|
|
||||||
public abstract class System {
|
public abstract class System {
|
||||||
private static final long NanoTimeBaseInMillis = currentTimeMillis();
|
private static class NanoTime {
|
||||||
|
public static final long BaseInMillis = currentTimeMillis();
|
||||||
|
}
|
||||||
|
|
||||||
private static class Static {
|
private static class Static {
|
||||||
public static Properties properties = makeProperties();
|
public static Properties properties = makeProperties();
|
||||||
@ -94,7 +96,7 @@ public abstract class System {
|
|||||||
public static native int identityHashCode(Object o);
|
public static native int identityHashCode(Object o);
|
||||||
|
|
||||||
public static long nanoTime() {
|
public static long nanoTime() {
|
||||||
return (currentTimeMillis() - NanoTimeBaseInMillis) * 1000000;
|
return (currentTimeMillis() - NanoTime.BaseInMillis) * 1000000;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String mapLibraryName(String name) {
|
public static String mapLibraryName(String name) {
|
||||||
|
@ -187,14 +187,28 @@ public class LambdaMetafactory {
|
|||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static CallSite metafactory(MethodHandles.Lookup caller,
|
public static byte[] makeLambda(String invokedName,
|
||||||
String invokedName,
|
String invokedType,
|
||||||
MethodType invokedType,
|
String methodType,
|
||||||
MethodType methodType,
|
String implementationClass,
|
||||||
MethodHandle methodImplementation,
|
String implementationName,
|
||||||
MethodType instantiatedMethodType)
|
String implementationSpec,
|
||||||
throws LambdaConversionException
|
int implementationKind)
|
||||||
|
{
|
||||||
|
return makeLambda(invokedName,
|
||||||
|
new MethodType(invokedType),
|
||||||
|
new MethodType(methodType),
|
||||||
|
new MethodHandle(implementationClass,
|
||||||
|
implementationName,
|
||||||
|
implementationSpec,
|
||||||
|
implementationKind));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static byte[] makeLambda(String invokedName,
|
||||||
|
MethodType invokedType,
|
||||||
|
MethodType methodType,
|
||||||
|
MethodHandle methodImplementation)
|
||||||
{
|
{
|
||||||
String className;
|
String className;
|
||||||
{ int number;
|
{ int number;
|
||||||
@ -265,8 +279,19 @@ public class LambdaMetafactory {
|
|||||||
throw error;
|
throw error;
|
||||||
}
|
}
|
||||||
|
|
||||||
byte[] classData = out.toByteArray();
|
return out.toByteArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static CallSite metafactory(MethodHandles.Lookup caller,
|
||||||
|
String invokedName,
|
||||||
|
MethodType invokedType,
|
||||||
|
MethodType methodType,
|
||||||
|
MethodHandle methodImplementation,
|
||||||
|
MethodType instantiatedMethodType)
|
||||||
|
throws LambdaConversionException
|
||||||
|
{
|
||||||
|
byte[] classData = makeLambda(invokedName, invokedType, methodType, methodImplementation);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
return new CallSite
|
return new CallSite
|
||||||
(new MethodHandle
|
(new MethodHandle
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package java.lang.invoke;
|
package java.lang.invoke;
|
||||||
|
|
||||||
import avian.Classes;
|
import avian.Classes;
|
||||||
|
import avian.SystemClassLoader;
|
||||||
|
|
||||||
public class MethodHandle {
|
public class MethodHandle {
|
||||||
static final int REF_invokeStatic = 6;
|
static final int REF_invokeStatic = 6;
|
||||||
@ -17,6 +18,20 @@ public class MethodHandle {
|
|||||||
this.method = method;
|
this.method = method;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MethodHandle(String class_,
|
||||||
|
String name,
|
||||||
|
String spec,
|
||||||
|
int kind)
|
||||||
|
{
|
||||||
|
this.kind = kind;
|
||||||
|
this.loader = SystemClassLoader.appLoader();
|
||||||
|
try {
|
||||||
|
this.method = Classes.findMethod(this.loader, class_, name, spec);
|
||||||
|
} catch (ClassNotFoundException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public String toString() {
|
public String toString() {
|
||||||
StringBuilder sb = new StringBuilder();
|
StringBuilder sb = new StringBuilder();
|
||||||
if (method.class_ != null) {
|
if (method.class_ != null) {
|
||||||
|
@ -4,6 +4,7 @@ import static avian.Assembler.*;
|
|||||||
|
|
||||||
import avian.Assembler;
|
import avian.Assembler;
|
||||||
import avian.Classes;
|
import avian.Classes;
|
||||||
|
import avian.SystemClassLoader;
|
||||||
import avian.VMClass;
|
import avian.VMClass;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@ -25,6 +26,12 @@ public final class MethodType implements java.io.Serializable {
|
|||||||
this.spec = spec;
|
this.spec = spec;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MethodType(String spec) {
|
||||||
|
this.loader = SystemClassLoader.appLoader();
|
||||||
|
this.spec = new byte[spec.length() + 1];
|
||||||
|
spec.getBytes(0, spec.length(), this.spec, 0);
|
||||||
|
}
|
||||||
|
|
||||||
public String toMethodDescriptorString() {
|
public String toMethodDescriptorString() {
|
||||||
return Classes.makeString(spec, 0, spec.length - 1);
|
return Classes.makeString(spec, 0, spec.length - 1);
|
||||||
}
|
}
|
||||||
|
@ -86,18 +86,16 @@ public class Socket implements Closeable, AutoCloseable {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int read(byte[] buffer) throws IOException {
|
public int read(byte[] buffer) throws IOException {
|
||||||
|
if(buffer.length == 0) return 0; //spec says return 0 if buffer length is zero.
|
||||||
int fullSize = buffer.length;
|
int fullSize = buffer.length;
|
||||||
int index = 0;
|
|
||||||
int size;
|
int size;
|
||||||
do {
|
size = recv(sock, buffer, 0, Math.min(fullSize, Socket.BUFFER_SIZE));
|
||||||
size = recv(sock, buffer, index, Math.min(fullSize, Socket.BUFFER_SIZE));
|
fullSize -= size;
|
||||||
fullSize -= size;
|
//removed loop, because otherwise interactive protocols will not work.
|
||||||
index += size;
|
if(size < 0) throw new IOException("Error while reading stream"); //as the manpage of recv says, a value below zero indicates an error.
|
||||||
} while (fullSize != 0 && size != 0);
|
if(size == 0) return -1; // if the stream is closed (size == 0), then return -1 to indicate end of stream.
|
||||||
return index;
|
return size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private class SocketOutputStream extends OutputStream {
|
private class SocketOutputStream extends OutputStream {
|
||||||
|
@ -1,13 +1,18 @@
|
|||||||
FROM debian:jessie
|
FROM debian:jessie
|
||||||
MAINTAINER Joshua Warner, joshuawarner32@gmail.com
|
MAINTAINER Joshua Warner, joshuawarner32@gmail.com
|
||||||
|
|
||||||
|
RUN echo 'deb http://http.debian.net/debian jessie-backports main' >> /etc/apt/sources.list && \
|
||||||
|
echo 'deb-src http://http.debian.net/debian jessie-backports main' >> /etc/apt/sources.list && \
|
||||||
|
dpkg --add-architecture i386 && \
|
||||||
|
apt-get update && \
|
||||||
|
mkdir /var/src/
|
||||||
|
|
||||||
# Install base dependencies and build tools, general debugging tools
|
# Install base dependencies and build tools, general debugging tools
|
||||||
RUN apt-get update && \
|
RUN apt-get install -y \
|
||||||
apt-get install -y \
|
|
||||||
build-essential \
|
build-essential \
|
||||||
g++-4.8 \
|
g++-4.9 \
|
||||||
zlib1g-dev \
|
zlib1g-dev \
|
||||||
openjdk-7-jdk \
|
openjdk-8-jdk \
|
||||||
locales \
|
locales \
|
||||||
--no-install-recommends && \
|
--no-install-recommends && \
|
||||||
apt-get clean all
|
apt-get clean all
|
||||||
@ -20,8 +25,59 @@ RUN dpkg-reconfigure locales && \
|
|||||||
ENV LC_ALL C.UTF-8
|
ENV LC_ALL C.UTF-8
|
||||||
|
|
||||||
# Set JAVA_HOME for avian's benefit
|
# Set JAVA_HOME for avian's benefit
|
||||||
ENV JAVA_HOME /usr/lib/jvm/java-7-openjdk-amd64
|
ENV JAVA_HOME /usr/lib/jvm/java-8-openjdk-amd64
|
||||||
|
|
||||||
|
# Add i386 libraries
|
||||||
|
RUN apt-get install -y \
|
||||||
|
libc6-dev-i386 && \
|
||||||
|
apt-get download \
|
||||||
|
zlib1g-dev:i386 && \
|
||||||
|
dpkg -x *.deb / && \
|
||||||
|
rm *.deb && \
|
||||||
|
apt-get clean all
|
||||||
|
|
||||||
|
# Install cross-compile toolchain and emulator for testing
|
||||||
|
RUN apt-get install -y \
|
||||||
|
mingw-w64 \
|
||||||
|
wget \
|
||||||
|
unzip \
|
||||||
|
--no-install-recommends && \
|
||||||
|
apt-get clean all
|
||||||
|
|
||||||
|
# Download win32 and win64 adjacent to avian
|
||||||
|
RUN cd /var/src/ && \
|
||||||
|
wget https://github.com/ReadyTalk/win32/archive/master.zip -O win32.zip && \
|
||||||
|
unzip win32.zip && \
|
||||||
|
rm win32.zip && \
|
||||||
|
mv win32-* win32 && \
|
||||||
|
wget https://github.com/ReadyTalk/win64/archive/master.zip -O win64.zip && \
|
||||||
|
unzip win64.zip && \
|
||||||
|
rm win64.zip && \
|
||||||
|
mv win64-* win64
|
||||||
|
|
||||||
|
# Add openjdk-src stuff
|
||||||
|
RUN apt-get install -y \
|
||||||
|
libcups2-dev \
|
||||||
|
libgconf2-dev && \
|
||||||
|
mkdir /var/src/openjdk/ && \
|
||||||
|
cd /var/src/openjdk/ && \
|
||||||
|
apt-get source openjdk-8 && \
|
||||||
|
apt-get clean all && \
|
||||||
|
find /var/src/openjdk && \
|
||||||
|
rm /var/src/openjdk/*.gz /var/src/openjdk/*.dsc && \
|
||||||
|
cd /var/src/openjdk/ && \
|
||||||
|
tar -xf /var/src/openjdk/openjdk*/jdk.tar.xz && \
|
||||||
|
mv /var/src/openjdk/jdk-*/src /var/src/openjdk-src && \
|
||||||
|
rm -rf /var/src/openjdk && \
|
||||||
|
apt-get clean all
|
||||||
|
|
||||||
|
# Download/extract lzma source
|
||||||
|
RUN mkdir /var/src/lzma && \
|
||||||
|
cd /var/src/lzma && \
|
||||||
|
apt-get install -y p7zip && \
|
||||||
|
wget http://www.7-zip.org/a/lzma1507.7z -O lzma.7z && \
|
||||||
|
p7zip -d lzma.7z
|
||||||
|
|
||||||
# Avian build location
|
# Avian build location
|
||||||
VOLUME /var/avian
|
VOLUME /var/src/avian
|
||||||
WORKDIR /var/avian
|
WORKDIR /var/src/avian
|
||||||
|
@ -38,4 +38,4 @@ fi
|
|||||||
|
|
||||||
DIR=$(cd $(dirname "$0") && cd .. && pwd)
|
DIR=$(cd $(dirname "$0") && cd .. && pwd)
|
||||||
|
|
||||||
docker run --rm -i -t -v "${DIR}":/var/avian ${THE_USER} "${CONTAINER}" "${@}"
|
docker run --rm -i -t -v "${DIR}":/var/src/avian ${THE_USER} "${CONTAINER}" "${@}"
|
||||||
|
@ -1,12 +0,0 @@
|
|||||||
FROM joshuawarner32/avian-build
|
|
||||||
MAINTAINER Joshua Warner, joshuawarner32@gmail.com
|
|
||||||
|
|
||||||
RUN dpkg --add-architecture i386 && \
|
|
||||||
apt-get update && \
|
|
||||||
apt-get install -y \
|
|
||||||
libc6-dev-i386 && \
|
|
||||||
apt-get download \
|
|
||||||
zlib1g-dev:i386 && \
|
|
||||||
dpkg -x *.deb / && \
|
|
||||||
rm *.deb && \
|
|
||||||
apt-get clean all
|
|
@ -1,17 +0,0 @@
|
|||||||
FROM joshuawarner32/avian-build-i386
|
|
||||||
MAINTAINER Joshua Warner, joshuawarner32@gmail.com
|
|
||||||
|
|
||||||
RUN echo 'deb-src http://http.debian.net/debian jessie main' >> /etc/apt/sources.list && \
|
|
||||||
apt-get update && \
|
|
||||||
apt-get install -y \
|
|
||||||
libcups2-dev \
|
|
||||||
libgconf2-dev && \
|
|
||||||
mkdir /var/openjdk/ && \
|
|
||||||
cd /var/openjdk/ && \
|
|
||||||
apt-get source openjdk-7 && \
|
|
||||||
apt-get clean all && \
|
|
||||||
rm /var/openjdk/*.gz /var/openjdk/*.dsc && \
|
|
||||||
cd /var/openjdk/ && \
|
|
||||||
tar -xzf /var/openjdk/openjdk*/jdk.tar.gz && \
|
|
||||||
mv /var/openjdk/jdk-*/src /var/openjdk-src && \
|
|
||||||
rm -rf /var/openjdk
|
|
@ -1,23 +0,0 @@
|
|||||||
FROM joshuawarner32/avian-build
|
|
||||||
MAINTAINER Joshua Warner, joshuawarner32@gmail.com
|
|
||||||
|
|
||||||
# Install cross-compile toolchain and emulator for testing
|
|
||||||
RUN apt-get update && \
|
|
||||||
apt-get install -y \
|
|
||||||
mingw-w64 \
|
|
||||||
wget \
|
|
||||||
unzip \
|
|
||||||
--no-install-recommends && \
|
|
||||||
apt-get clean all
|
|
||||||
|
|
||||||
# Download win32 and win64 adjacent to avian
|
|
||||||
RUN cd .. && \
|
|
||||||
wget https://github.com/ReadyTalk/win32/archive/master.zip -O win32.zip && \
|
|
||||||
unzip win32.zip && \
|
|
||||||
rm win32.zip && \
|
|
||||||
mv win32-* win32 && \
|
|
||||||
wget https://github.com/ReadyTalk/win64/archive/master.zip -O win64.zip && \
|
|
||||||
unzip win64.zip && \
|
|
||||||
rm win64.zip && \
|
|
||||||
mv win64-* win64
|
|
||||||
|
|
@ -176,7 +176,7 @@ inline void NO_RETURN sysAbort(System* s)
|
|||||||
|
|
||||||
// #endif // not NDEBUG
|
// #endif // not NDEBUG
|
||||||
|
|
||||||
AVIAN_EXPORT System* makeSystem();
|
AVIAN_EXPORT System* makeSystem(bool reentrant = false);
|
||||||
|
|
||||||
} // namespace vm
|
} // namespace vm
|
||||||
|
|
||||||
|
118
makefile
118
makefile
@ -45,6 +45,11 @@ ifneq ($(lzma),)
|
|||||||
endif
|
endif
|
||||||
ifeq ($(bootimage),true)
|
ifeq ($(bootimage),true)
|
||||||
options := $(options)-bootimage
|
options := $(options)-bootimage
|
||||||
|
ifeq ($(bootimage-test),true)
|
||||||
|
# this option indicates that we should AOT-compile the test
|
||||||
|
# classes as well as the class library
|
||||||
|
options := $(options)-test
|
||||||
|
endif
|
||||||
endif
|
endif
|
||||||
ifeq ($(tails),true)
|
ifeq ($(tails),true)
|
||||||
options := $(options)-tails
|
options := $(options)-tails
|
||||||
@ -92,6 +97,12 @@ ifeq ($(platform),ios)
|
|||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
ifeq ($(bootimage-test),true)
|
||||||
|
ifneq ($(bootimage),true)
|
||||||
|
x := $(error "bootimage-test=true only works when bootimage=true")
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
|
||||||
aot-only = false
|
aot-only = false
|
||||||
root := $(shell (cd .. && pwd))
|
root := $(shell (cd .. && pwd))
|
||||||
build = build/$(platform)-$(arch)$(options)
|
build = build/$(platform)-$(arch)$(options)
|
||||||
@ -109,6 +120,12 @@ wp8 ?= $(root)/wp8
|
|||||||
|
|
||||||
classpath = avian
|
classpath = avian
|
||||||
|
|
||||||
|
bootimage-classpath = $(classpath-build)
|
||||||
|
|
||||||
|
ifeq ($(bootimage-test),true)
|
||||||
|
bootimage-classpath = $(classpath-build):$(test-build)
|
||||||
|
endif
|
||||||
|
|
||||||
test-executable = $(shell pwd)/$(executable)
|
test-executable = $(shell pwd)/$(executable)
|
||||||
boot-classpath = $(classpath-build)
|
boot-classpath = $(classpath-build)
|
||||||
embed-prefix = /avian-embedded
|
embed-prefix = /avian-embedded
|
||||||
@ -746,13 +763,14 @@ ifeq ($(kernel),darwin)
|
|||||||
rpath =
|
rpath =
|
||||||
|
|
||||||
ifeq ($(platform),ios)
|
ifeq ($(platform),ios)
|
||||||
ifeq (,$(filter arm arm64,$(arch)))
|
ifeq ($(sim),true)
|
||||||
target = iPhoneSimulator
|
target = iPhoneSimulator
|
||||||
sdk = iphonesimulator$(ios-version)
|
sdk = iphonesimulator$(ios-version)
|
||||||
ifeq ($(arch),i386)
|
ifeq ($(arch),i386)
|
||||||
arch-flag = -arch i386
|
arch-flag = -arch i386
|
||||||
else
|
else
|
||||||
arch-flag = -arch x86_64
|
arch-flag = -arch x86_64
|
||||||
|
arch = x86_64
|
||||||
endif
|
endif
|
||||||
release = Release-iphonesimulator
|
release = Release-iphonesimulator
|
||||||
else
|
else
|
||||||
@ -762,6 +780,7 @@ ifeq ($(kernel),darwin)
|
|||||||
arch-flag = -arch armv7
|
arch-flag = -arch armv7
|
||||||
else
|
else
|
||||||
arch-flag = -arch arm64
|
arch-flag = -arch arm64
|
||||||
|
arch = arm64
|
||||||
endif
|
endif
|
||||||
release = Release-iphoneos
|
release = Release-iphoneos
|
||||||
endif
|
endif
|
||||||
@ -770,7 +789,9 @@ ifeq ($(kernel),darwin)
|
|||||||
sdk-dir = $(platform-dir)/Developer/SDKs
|
sdk-dir = $(platform-dir)/Developer/SDKs
|
||||||
|
|
||||||
ios-version := $(shell \
|
ios-version := $(shell \
|
||||||
if test -d $(sdk-dir)/$(target)8.3.sdk; then echo 8.3; \
|
if test -L $(sdk-dir)/$(target)9.1.sdk; then echo 9.1; \
|
||||||
|
elif test -L $(sdk-dir)/$(target)9.0.sdk; then echo 9.0; \
|
||||||
|
elif test -d $(sdk-dir)/$(target)8.3.sdk; then echo 8.3; \
|
||||||
elif test -d $(sdk-dir)/$(target)8.2.sdk; then echo 8.2; \
|
elif test -d $(sdk-dir)/$(target)8.2.sdk; then echo 8.2; \
|
||||||
elif test -d $(sdk-dir)/$(target)8.1.sdk; then echo 8.1; \
|
elif test -d $(sdk-dir)/$(target)8.1.sdk; then echo 8.1; \
|
||||||
elif test -d $(sdk-dir)/$(target)8.0.sdk; then echo 8.0; \
|
elif test -d $(sdk-dir)/$(target)8.0.sdk; then echo 8.0; \
|
||||||
@ -811,39 +832,57 @@ ifeq ($(kernel),darwin)
|
|||||||
cflags += $(flags)
|
cflags += $(flags)
|
||||||
asmflags += $(flags)
|
asmflags += $(flags)
|
||||||
lflags += $(flags)
|
lflags += $(flags)
|
||||||
endif
|
|
||||||
|
ios-version-min=$(ios-version)
|
||||||
ifeq ($(arch),i386)
|
ifdef ios_deployment_target
|
||||||
ifeq ($(platform),ios)
|
ios-version-min=ios_deployment_target
|
||||||
classpath-extra-cflags += \
|
endif
|
||||||
-arch i386 -miphoneos-version-min=$(ios-version)
|
|
||||||
cflags += -arch i386 -miphoneos-version-min=$(ios-version)
|
ifeq ($(sim),true)
|
||||||
asmflags += -arch i386 -miphoneos-version-min=$(ios-version)
|
ifeq ($(arch),x86_64)
|
||||||
lflags += -arch i386 -miphoneos-version-min=$(ios-version)
|
classpath-extra-cflags += \
|
||||||
|
-arch x86_64 -miphoneos-version-min=$(ios-version-min)
|
||||||
|
cflags += -arch x86_64 -miphoneos-version-min=$(ios-version-min)
|
||||||
|
asmflags += -arch x86_64 -miphoneos-version-min=$(ios-version-min)
|
||||||
|
lflags += -arch x86_64 -miphoneos-version-min=$(ios-version-min)
|
||||||
|
else
|
||||||
|
classpath-extra-cflags += \
|
||||||
|
-arch i386 -miphoneos-version-min=$(ios-version-min)
|
||||||
|
cflags += -arch i386 -miphoneos-version-min=$(ios-version-min)
|
||||||
|
asmflags += -arch i386 -miphoneos-version-min=$(ios-version-min)
|
||||||
|
lflags += -arch i386 -miphoneos-version-min=$(ios-version-min)
|
||||||
|
endif
|
||||||
else
|
else
|
||||||
classpath-extra-cflags += \
|
ifeq ($(arch),arm64)
|
||||||
-arch i386 -mmacosx-version-min=${OSX_SDK_VERSION}
|
classpath-extra-cflags += \
|
||||||
cflags += -arch i386 -mmacosx-version-min=${OSX_SDK_VERSION}
|
-arch arm64 -miphoneos-version-min=$(ios-version-min)
|
||||||
asmflags += -arch i386 -mmacosx-version-min=${OSX_SDK_VERSION}
|
cflags += -arch arm64 -miphoneos-version-min=$(ios-version-min)
|
||||||
lflags += -arch i386 -mmacosx-version-min=${OSX_SDK_VERSION}
|
asmflags += -arch arm64 -miphoneos-version-min=$(ios-version-min)
|
||||||
|
lflags += -arch arm64 -miphoneos-version-min=$(ios-version-min)
|
||||||
|
else
|
||||||
|
classpath-extra-cflags += \
|
||||||
|
-arch armv7 -miphoneos-version-min=$(ios-version-min)
|
||||||
|
cflags += -arch armv7 -miphoneos-version-min=$(ios-version-min)
|
||||||
|
asmflags += -arch armv7 -miphoneos-version-min=$(ios-version-min)
|
||||||
|
lflags += -arch armv7 -miphoneos-version-min=$(ios-version-min)
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
else # not ios
|
||||||
|
ifeq ($(arch),i386)
|
||||||
|
classpath-extra-cflags += \
|
||||||
|
-arch i386 -mmacosx-version-min=${OSX_SDK_VERSION}
|
||||||
|
cflags += -arch i386 -mmacosx-version-min=${OSX_SDK_VERSION}
|
||||||
|
asmflags += -arch i386 -mmacosx-version-min=${OSX_SDK_VERSION}
|
||||||
|
lflags += -arch i386 -mmacosx-version-min=${OSX_SDK_VERSION}
|
||||||
|
endif
|
||||||
|
|
||||||
|
ifeq ($(arch),x86_64)
|
||||||
|
classpath-extra-cflags += -arch x86_64
|
||||||
|
cflags += -arch x86_64
|
||||||
|
asmflags += -arch x86_64
|
||||||
|
lflags += -arch x86_64
|
||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifeq ($(arch),x86_64)
|
|
||||||
ifeq ($(platform),ios)
|
|
||||||
classpath-extra-cflags += \
|
|
||||||
-arch x86_64 -miphoneos-version-min=$(ios-version)
|
|
||||||
cflags += -arch x86_64 -miphoneos-version-min=$(ios-version)
|
|
||||||
asmflags += -arch x86_64 -miphoneos-version-min=$(ios-version)
|
|
||||||
lflags += -arch x86_64 -miphoneos-version-min=$(ios-version)
|
|
||||||
else
|
|
||||||
classpath-extra-cflags += -arch x86_64
|
|
||||||
cflags += -arch x86_64
|
|
||||||
asmflags += -arch x86_64
|
|
||||||
lflags += -arch x86_64
|
|
||||||
endif
|
|
||||||
endif
|
|
||||||
|
|
||||||
cflags += -I$(JAVA_HOME)/include/darwin
|
cflags += -I$(JAVA_HOME)/include/darwin
|
||||||
endif
|
endif
|
||||||
|
|
||||||
@ -1333,6 +1372,12 @@ bootimage-generator-objects = \
|
|||||||
$(call cpp-objects,$(bootimage-generator-sources),$(src),$(build))
|
$(call cpp-objects,$(bootimage-generator-sources),$(src),$(build))
|
||||||
bootimage-generator = $(build)/bootimage-generator
|
bootimage-generator = $(build)/bootimage-generator
|
||||||
|
|
||||||
|
ifneq ($(mode),fast)
|
||||||
|
host-vm-options := -$(mode)
|
||||||
|
endif
|
||||||
|
|
||||||
|
host-vm = build/$(build-platform)-$(build-arch)-interpret$(host-vm-options)/libjvm.so
|
||||||
|
|
||||||
bootimage-object = $(build)/bootimage-bin.o
|
bootimage-object = $(build)/bootimage-bin.o
|
||||||
codeimage-object = $(build)/codeimage-bin.o
|
codeimage-object = $(build)/codeimage-bin.o
|
||||||
|
|
||||||
@ -1641,7 +1686,6 @@ debug: build
|
|||||||
vg: build
|
vg: build
|
||||||
$(library-path) $(vg) $(test-executable) $(test-args)
|
$(library-path) $(vg) $(test-executable) $(test-args)
|
||||||
|
|
||||||
|
|
||||||
.PHONY: test
|
.PHONY: test
|
||||||
test: build-test run-test
|
test: build-test run-test
|
||||||
|
|
||||||
@ -2060,11 +2104,12 @@ else
|
|||||||
endif
|
endif
|
||||||
|
|
||||||
$(bootimage-object) $(codeimage-object): $(bootimage-generator) \
|
$(bootimage-object) $(codeimage-object): $(bootimage-generator) \
|
||||||
$(classpath-jar-dep)
|
$(classpath-jar-dep) $(test-dep)
|
||||||
@echo "generating bootimage and codeimage binaries from $(classpath-build) using $(<)"
|
@echo "generating bootimage and codeimage binaries from $(classpath-build) using $(<)"
|
||||||
$(<) -cp $(classpath-build) -bootimage $(bootimage-object) -codeimage $(codeimage-object) \
|
$(<) -cp $(bootimage-classpath) -bootimage $(bootimage-object) -codeimage $(codeimage-object) \
|
||||||
-bootimage-symbols $(bootimage-symbols) \
|
-bootimage-symbols $(bootimage-symbols) \
|
||||||
-codeimage-symbols $(codeimage-symbols)
|
-codeimage-symbols $(codeimage-symbols) \
|
||||||
|
-hostvm $(host-vm)
|
||||||
|
|
||||||
executable-objects = $(vm-objects) $(classpath-objects) $(driver-object) \
|
executable-objects = $(vm-objects) $(classpath-objects) $(driver-object) \
|
||||||
$(vm-heapwalk-objects) $(boot-object) $(vm-classpath-objects) \
|
$(vm-heapwalk-objects) $(boot-object) $(vm-classpath-objects) \
|
||||||
@ -2119,6 +2164,7 @@ $(unittest-executable): $(unittest-executable-objects)
|
|||||||
|
|
||||||
$(bootimage-generator): $(bootimage-generator-objects) $(vm-objects)
|
$(bootimage-generator): $(bootimage-generator-objects) $(vm-objects)
|
||||||
echo building $(bootimage-generator) arch=$(build-arch) platform=$(bootimage-platform)
|
echo building $(bootimage-generator) arch=$(build-arch) platform=$(bootimage-platform)
|
||||||
|
$(MAKE) process=interpret bootimage= bootimage-test= mode=$(mode)
|
||||||
$(MAKE) mode=$(mode) \
|
$(MAKE) mode=$(mode) \
|
||||||
build=$(host-build-root) \
|
build=$(host-build-root) \
|
||||||
arch=$(build-arch) \
|
arch=$(build-arch) \
|
||||||
|
@ -55,10 +55,13 @@ class BootImage {
|
|||||||
} PACKED;
|
} PACKED;
|
||||||
|
|
||||||
class GcField;
|
class GcField;
|
||||||
|
class GcClass;
|
||||||
|
|
||||||
class OffsetResolver {
|
class OffsetResolver {
|
||||||
public:
|
public:
|
||||||
virtual unsigned fieldOffset(Thread*, GcField*) = 0;
|
virtual unsigned fieldOffset(Thread*, GcField*) = 0;
|
||||||
|
|
||||||
|
virtual void addClass(Thread*, GcClass*, const uint8_t*, size_t) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define NAME(x) Target##x
|
#define NAME(x) Target##x
|
||||||
|
@ -20,6 +20,7 @@
|
|||||||
#define EMBED_PREFIX_PROPERTY "avian.embed.prefix"
|
#define EMBED_PREFIX_PROPERTY "avian.embed.prefix"
|
||||||
#define CLASSPATH_PROPERTY "java.class.path"
|
#define CLASSPATH_PROPERTY "java.class.path"
|
||||||
#define JAVA_HOME_PROPERTY "java.home"
|
#define JAVA_HOME_PROPERTY "java.home"
|
||||||
|
#define REENTRANT_PROPERTY "avian.reentrant"
|
||||||
#define BOOTCLASSPATH_PREPEND_OPTION "bootclasspath/p"
|
#define BOOTCLASSPATH_PREPEND_OPTION "bootclasspath/p"
|
||||||
#define BOOTCLASSPATH_OPTION "bootclasspath"
|
#define BOOTCLASSPATH_OPTION "bootclasspath"
|
||||||
#define BOOTCLASSPATH_APPEND_OPTION "bootclasspath/a"
|
#define BOOTCLASSPATH_APPEND_OPTION "bootclasspath/a"
|
||||||
|
@ -198,6 +198,14 @@ const unsigned ConstructorFlag = 1 << 1;
|
|||||||
#define JNI_VERSION_1_6 0x00010006
|
#define JNI_VERSION_1_6 0x00010006
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef JNI_TRUE
|
||||||
|
#define JNI_TRUE 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef JNI_OK
|
||||||
|
#define JNI_OK 0
|
||||||
|
#endif
|
||||||
|
|
||||||
typedef Machine JavaVM;
|
typedef Machine JavaVM;
|
||||||
typedef Thread JNIEnv;
|
typedef Thread JNIEnv;
|
||||||
|
|
||||||
@ -207,6 +215,19 @@ struct JNINativeMethod {
|
|||||||
void* function;
|
void* function;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct JavaVMOption {
|
||||||
|
char* optionString;
|
||||||
|
void* extraInfo;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct JavaVMInitArgs {
|
||||||
|
jint version;
|
||||||
|
|
||||||
|
jint nOptions;
|
||||||
|
JavaVMOption* options;
|
||||||
|
jboolean ignoreUnrecognized;
|
||||||
|
};
|
||||||
|
|
||||||
struct JavaVMVTable {
|
struct JavaVMVTable {
|
||||||
void* reserved0;
|
void* reserved0;
|
||||||
void* reserved1;
|
void* reserved1;
|
||||||
@ -3737,10 +3758,10 @@ void populateMultiArray(Thread* t,
|
|||||||
|
|
||||||
GcMethod* getCaller(Thread* t, unsigned target, bool skipMethodInvoke = false);
|
GcMethod* getCaller(Thread* t, unsigned target, bool skipMethodInvoke = false);
|
||||||
|
|
||||||
object defineClass(Thread* t,
|
GcClass* defineClass(Thread* t,
|
||||||
GcClassLoader* loader,
|
GcClassLoader* loader,
|
||||||
const uint8_t* buffer,
|
const uint8_t* buffer,
|
||||||
unsigned length);
|
unsigned length);
|
||||||
|
|
||||||
inline GcMethod* methodClone(Thread* t, GcMethod* method)
|
inline GcMethod* methodClone(Thread* t, GcMethod* method)
|
||||||
{
|
{
|
||||||
|
@ -170,7 +170,8 @@ class Processor {
|
|||||||
GcTriple** calls,
|
GcTriple** calls,
|
||||||
avian::codegen::DelayedPromise** addresses,
|
avian::codegen::DelayedPromise** addresses,
|
||||||
GcMethod* method,
|
GcMethod* method,
|
||||||
OffsetResolver* resolver) = 0;
|
OffsetResolver* resolver,
|
||||||
|
Machine* hostVM) = 0;
|
||||||
|
|
||||||
virtual void visitRoots(Thread* t, HeapWalker* w) = 0;
|
virtual void visitRoots(Thread* t, HeapWalker* w) = 0;
|
||||||
|
|
||||||
|
@ -183,6 +183,12 @@ extern "C" AVIAN_EXPORT int64_t JNICALL
|
|||||||
t->m->classpath->makeString(t, array, offset, length));
|
t->m->classpath->makeString(t, array, offset, length));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extern "C" AVIAN_EXPORT int64_t JNICALL
|
||||||
|
Avian_avian_SystemClassLoader_appLoader(Thread* t, object, uintptr_t*)
|
||||||
|
{
|
||||||
|
return reinterpret_cast<int64_t>(roots(t)->appLoader());
|
||||||
|
}
|
||||||
|
|
||||||
extern "C" AVIAN_EXPORT int64_t JNICALL
|
extern "C" AVIAN_EXPORT int64_t JNICALL
|
||||||
Avian_avian_SystemClassLoader_findLoadedVMClass(Thread* t,
|
Avian_avian_SystemClassLoader_findLoadedVMClass(Thread* t,
|
||||||
object,
|
object,
|
||||||
|
221
src/compile.cpp
221
src/compile.cpp
@ -909,14 +909,16 @@ class BootContext {
|
|||||||
GcTriple* calls,
|
GcTriple* calls,
|
||||||
avian::codegen::DelayedPromise* addresses,
|
avian::codegen::DelayedPromise* addresses,
|
||||||
Zone* zone,
|
Zone* zone,
|
||||||
OffsetResolver* resolver)
|
OffsetResolver* resolver,
|
||||||
|
JavaVM* hostVM)
|
||||||
: protector(t, this),
|
: protector(t, this),
|
||||||
constants(constants),
|
constants(constants),
|
||||||
calls(calls),
|
calls(calls),
|
||||||
addresses(addresses),
|
addresses(addresses),
|
||||||
addressSentinal(addresses),
|
addressSentinal(addresses),
|
||||||
zone(zone),
|
zone(zone),
|
||||||
resolver(resolver)
|
resolver(resolver),
|
||||||
|
hostVM(hostVM)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -927,6 +929,7 @@ class BootContext {
|
|||||||
avian::codegen::DelayedPromise* addressSentinal;
|
avian::codegen::DelayedPromise* addressSentinal;
|
||||||
Zone* zone;
|
Zone* zone;
|
||||||
OffsetResolver* resolver;
|
OffsetResolver* resolver;
|
||||||
|
JavaVM* hostVM;
|
||||||
};
|
};
|
||||||
|
|
||||||
class Context {
|
class Context {
|
||||||
@ -3991,6 +3994,34 @@ void checkField(Thread* t, GcField* field, bool shouldBeStatic)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool isLambda(Thread* t,
|
||||||
|
GcClassLoader* loader,
|
||||||
|
GcCharArray* bootstrapArray,
|
||||||
|
GcInvocation* invocation)
|
||||||
|
{
|
||||||
|
GcMethod* bootstrap = cast<GcMethod>(t,
|
||||||
|
resolve(t,
|
||||||
|
loader,
|
||||||
|
invocation->pool(),
|
||||||
|
bootstrapArray->body()[0],
|
||||||
|
findMethodInClass,
|
||||||
|
GcNoSuchMethodError::Type));
|
||||||
|
PROTECT(t, bootstrap);
|
||||||
|
|
||||||
|
return vm::strcmp(reinterpret_cast<const int8_t*>(
|
||||||
|
"java/lang/invoke/LambdaMetafactory"),
|
||||||
|
bootstrap->class_()->name()->body().begin()) == 0
|
||||||
|
and vm::strcmp(reinterpret_cast<const int8_t*>("metafactory"),
|
||||||
|
bootstrap->name()->body().begin()) == 0
|
||||||
|
and vm::strcmp(
|
||||||
|
reinterpret_cast<const int8_t*>(
|
||||||
|
"(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/"
|
||||||
|
"String;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/"
|
||||||
|
"MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/"
|
||||||
|
"invoke/MethodType;)Ljava/lang/invoke/CallSite;"),
|
||||||
|
bootstrap->spec()->body().begin()) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
void compile(MyThread* t,
|
void compile(MyThread* t,
|
||||||
Frame* initialFrame,
|
Frame* initialFrame,
|
||||||
unsigned initialIp,
|
unsigned initialIp,
|
||||||
@ -5054,36 +5085,168 @@ loop:
|
|||||||
|
|
||||||
invocation->setClass(t, context->method->class_());
|
invocation->setClass(t, context->method->class_());
|
||||||
|
|
||||||
unsigned index = addDynamic(t, invocation);
|
BootContext* bc = context->bootContext;
|
||||||
|
if (bc) {
|
||||||
|
// When we're AOT-compiling an application, we can't handle
|
||||||
|
// invokedynamic in general, since it usually implies runtime
|
||||||
|
// code generation. However, Java 8 lambda expressions are a
|
||||||
|
// special case for which we can generate code ahead of time.
|
||||||
|
//
|
||||||
|
// The only tricky part about it is that the class synthesis
|
||||||
|
// code resides in LambdaMetaFactory, which means we need to
|
||||||
|
// call out to a separate Java VM to execute it (the VM we're
|
||||||
|
// currently executing in won't work because it only knows how
|
||||||
|
// to compile code for the target machine, which might not be
|
||||||
|
// the same as the host; plus we don't want to pollute the
|
||||||
|
// runtime heap image with stuff that's only needed at compile
|
||||||
|
// time).
|
||||||
|
|
||||||
GcMethod* template_ = invocation->template_();
|
GcClass* c = context->method->class_();
|
||||||
unsigned returnCode = template_->returnCode();
|
PROTECT(t, c);
|
||||||
unsigned rSize = resultSize(t, returnCode);
|
|
||||||
unsigned parameterFootprint = template_->parameterFootprint();
|
|
||||||
|
|
||||||
// TODO: can we allow tailCalls in general?
|
GcCharArray* bootstrapArray = cast<GcCharArray>(
|
||||||
// e.g. what happens if the call site is later bound to a method that can't be tail called?
|
t,
|
||||||
// NOTE: calling isTailCall right now would cause an segfault, since
|
cast<GcArray>(t, c->addendum()->bootstrapMethodTable())
|
||||||
// invocation->template_()->class_() will be null.
|
->body()[invocation->bootstrap()]);
|
||||||
// bool tailCall
|
PROTECT(t, bootstrapArray);
|
||||||
// = isTailCall(t, code, ip, context->method, invocation->template_());
|
|
||||||
bool tailCall = false;
|
|
||||||
|
|
||||||
// todo: do we need to tell the compiler to add a load barrier
|
if (isLambda(t, c->loader(), bootstrapArray, invocation)) {
|
||||||
// here for VolatileCallSite instances?
|
JNIEnv* e;
|
||||||
|
if (bc->hostVM->vtable->AttachCurrentThread(bc->hostVM, &e, 0) == 0) {
|
||||||
|
e->vtable->PushLocalFrame(e, 256);
|
||||||
|
|
||||||
ir::Value* result = c->stackCall(
|
jclass lmfClass
|
||||||
c->memory(c->memory(c->threadRegister(), ir::Type::object(),
|
= e->vtable->FindClass(e, "java/lang/invoke/LambdaMetafactory");
|
||||||
TARGET_THREAD_DYNAMICTABLE),
|
jmethodID makeLambda = e->vtable->GetStaticMethodID(
|
||||||
ir::Type::object(), index * TargetBytesPerWord),
|
e,
|
||||||
tailCall ? Compiler::TailJump : 0, frame->trace(0, 0),
|
lmfClass,
|
||||||
operandTypeForFieldCode(t, returnCode),
|
"makeLambda",
|
||||||
frame->peekMethodArguments(parameterFootprint));
|
"(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/"
|
||||||
|
"lang/String;Ljava/lang/String;Ljava/lang/String;I)[B");
|
||||||
|
|
||||||
frame->popFootprint(parameterFootprint);
|
GcReference* reference = cast<GcReference>(
|
||||||
|
t,
|
||||||
|
singletonObject(
|
||||||
|
t, invocation->pool(), bootstrapArray->body()[2]));
|
||||||
|
int kind = reference->kind();
|
||||||
|
|
||||||
if (rSize) {
|
GcMethod* method
|
||||||
frame->pushReturnValue(returnCode, result);
|
= cast<GcMethod>(t,
|
||||||
|
resolve(t,
|
||||||
|
c->loader(),
|
||||||
|
invocation->pool(),
|
||||||
|
bootstrapArray->body()[2],
|
||||||
|
findMethodInClass,
|
||||||
|
GcNoSuchMethodError::Type));
|
||||||
|
|
||||||
|
jarray lambda = e->vtable->CallStaticObjectMethod(
|
||||||
|
e,
|
||||||
|
lmfClass,
|
||||||
|
makeLambda,
|
||||||
|
e->vtable->NewStringUTF(
|
||||||
|
e,
|
||||||
|
reinterpret_cast<const char*>(
|
||||||
|
invocation->template_()->name()->body().begin())),
|
||||||
|
e->vtable->NewStringUTF(
|
||||||
|
e,
|
||||||
|
reinterpret_cast<const char*>(
|
||||||
|
invocation->template_()->spec()->body().begin())),
|
||||||
|
e->vtable->NewStringUTF(
|
||||||
|
e,
|
||||||
|
reinterpret_cast<const char*>(
|
||||||
|
cast<GcByteArray>(
|
||||||
|
t,
|
||||||
|
singletonObject(t,
|
||||||
|
invocation->pool(),
|
||||||
|
bootstrapArray->body()[1]))
|
||||||
|
->body()
|
||||||
|
.begin())),
|
||||||
|
e->vtable->NewStringUTF(
|
||||||
|
e,
|
||||||
|
reinterpret_cast<const char*>(
|
||||||
|
method->class_()->name()->body().begin())),
|
||||||
|
e->vtable->NewStringUTF(e,
|
||||||
|
reinterpret_cast<const char*>(
|
||||||
|
method->name()->body().begin())),
|
||||||
|
e->vtable->NewStringUTF(e,
|
||||||
|
reinterpret_cast<const char*>(
|
||||||
|
method->spec()->body().begin())),
|
||||||
|
kind);
|
||||||
|
|
||||||
|
uint8_t* bytes = reinterpret_cast<uint8_t*>(
|
||||||
|
e->vtable->GetPrimitiveArrayCritical(e, lambda, 0));
|
||||||
|
|
||||||
|
GcClass* lambdaClass
|
||||||
|
= defineClass(t,
|
||||||
|
roots(t)->appLoader(),
|
||||||
|
bytes,
|
||||||
|
e->vtable->GetArrayLength(e, lambda));
|
||||||
|
|
||||||
|
bc->resolver->addClass(
|
||||||
|
t, lambdaClass, bytes, e->vtable->GetArrayLength(e, lambda));
|
||||||
|
|
||||||
|
e->vtable->ReleasePrimitiveArrayCritical(e, lambda, bytes, 0);
|
||||||
|
|
||||||
|
e->vtable->PopLocalFrame(e, 0);
|
||||||
|
|
||||||
|
THREAD_RUNTIME_ARRAY(
|
||||||
|
t, char, spec, invocation->template_()->spec()->length());
|
||||||
|
memcpy(RUNTIME_ARRAY_BODY(spec),
|
||||||
|
invocation->template_()->spec()->body().begin(),
|
||||||
|
invocation->template_()->spec()->length());
|
||||||
|
|
||||||
|
GcMethod* target = resolveMethod(
|
||||||
|
t, lambdaClass, "make", RUNTIME_ARRAY_BODY(spec));
|
||||||
|
|
||||||
|
bool tailCall = isTailCall(t, code, ip, context->method, target);
|
||||||
|
compileDirectInvoke(t, frame, target, tailCall);
|
||||||
|
} else {
|
||||||
|
throwNew(
|
||||||
|
t, GcVirtualMachineError::Type, "unable to attach to host VM");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
throwNew(t,
|
||||||
|
GcVirtualMachineError::Type,
|
||||||
|
"invokedynamic not supported for AOT-compiled code except "
|
||||||
|
"in the case of lambda expressions");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
unsigned index = addDynamic(t, invocation);
|
||||||
|
|
||||||
|
GcMethod* template_ = invocation->template_();
|
||||||
|
unsigned returnCode = template_->returnCode();
|
||||||
|
unsigned rSize = resultSize(t, returnCode);
|
||||||
|
unsigned parameterFootprint = template_->parameterFootprint();
|
||||||
|
|
||||||
|
// TODO: can we allow tailCalls in general?
|
||||||
|
// e.g. what happens if the call site is later bound to a method that
|
||||||
|
// can't be tail called?
|
||||||
|
// NOTE: calling isTailCall right now would cause an segfault, since
|
||||||
|
// invocation->template_()->class_() will be null.
|
||||||
|
// bool tailCall
|
||||||
|
// = isTailCall(t, code, ip, context->method,
|
||||||
|
// invocation->template_());
|
||||||
|
bool tailCall = false;
|
||||||
|
|
||||||
|
// todo: do we need to tell the compiler to add a load barrier
|
||||||
|
// here for VolatileCallSite instances?
|
||||||
|
|
||||||
|
ir::Value* result
|
||||||
|
= c->stackCall(c->memory(c->memory(c->threadRegister(),
|
||||||
|
ir::Type::object(),
|
||||||
|
TARGET_THREAD_DYNAMICTABLE),
|
||||||
|
ir::Type::object(),
|
||||||
|
index * TargetBytesPerWord),
|
||||||
|
tailCall ? Compiler::TailJump : 0,
|
||||||
|
frame->trace(0, 0),
|
||||||
|
operandTypeForFieldCode(t, returnCode),
|
||||||
|
frame->peekMethodArguments(parameterFootprint));
|
||||||
|
|
||||||
|
frame->popFootprint(parameterFootprint);
|
||||||
|
|
||||||
|
if (rSize) {
|
||||||
|
frame->pushReturnValue(returnCode, result);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
@ -9134,10 +9297,12 @@ class MyProcessor : public Processor {
|
|||||||
GcTriple** calls,
|
GcTriple** calls,
|
||||||
avian::codegen::DelayedPromise** addresses,
|
avian::codegen::DelayedPromise** addresses,
|
||||||
GcMethod* method,
|
GcMethod* method,
|
||||||
OffsetResolver* resolver)
|
OffsetResolver* resolver,
|
||||||
|
JavaVM* hostVM)
|
||||||
{
|
{
|
||||||
MyThread* t = static_cast<MyThread*>(vmt);
|
MyThread* t = static_cast<MyThread*>(vmt);
|
||||||
BootContext bootContext(t, *constants, *calls, *addresses, zone, resolver);
|
BootContext bootContext(
|
||||||
|
t, *constants, *calls, *addresses, zone, resolver, hostVM);
|
||||||
|
|
||||||
compile(t, &codeAllocator, &bootContext, method);
|
compile(t, &codeAllocator, &bootContext, method);
|
||||||
|
|
||||||
|
@ -3512,7 +3512,8 @@ class MyProcessor : public Processor {
|
|||||||
GcTriple**,
|
GcTriple**,
|
||||||
avian::codegen::DelayedPromise**,
|
avian::codegen::DelayedPromise**,
|
||||||
GcMethod*,
|
GcMethod*,
|
||||||
OffsetResolver*)
|
OffsetResolver*,
|
||||||
|
JavaVM*)
|
||||||
{
|
{
|
||||||
abort(s);
|
abort(s);
|
||||||
}
|
}
|
||||||
|
@ -3617,6 +3617,7 @@ extern "C" AVIAN_EXPORT jint JNICALL
|
|||||||
const char* bootLibraries = 0;
|
const char* bootLibraries = 0;
|
||||||
const char* classpath = 0;
|
const char* classpath = 0;
|
||||||
const char* javaHome = AVIAN_JAVA_HOME;
|
const char* javaHome = AVIAN_JAVA_HOME;
|
||||||
|
bool reentrant = false;
|
||||||
const char* embedPrefix = AVIAN_EMBED_PREFIX;
|
const char* embedPrefix = AVIAN_EMBED_PREFIX;
|
||||||
const char* bootClasspathPrepend = "";
|
const char* bootClasspathPrepend = "";
|
||||||
const char* bootClasspath = 0;
|
const char* bootClasspath = 0;
|
||||||
@ -3667,6 +3668,9 @@ extern "C" AVIAN_EXPORT jint JNICALL
|
|||||||
} else if (strncmp(p, JAVA_HOME_PROPERTY "=", sizeof(JAVA_HOME_PROPERTY))
|
} else if (strncmp(p, JAVA_HOME_PROPERTY "=", sizeof(JAVA_HOME_PROPERTY))
|
||||||
== 0) {
|
== 0) {
|
||||||
javaHome = p + sizeof(JAVA_HOME_PROPERTY);
|
javaHome = p + sizeof(JAVA_HOME_PROPERTY);
|
||||||
|
} else if (strncmp(p, REENTRANT_PROPERTY "=", sizeof(REENTRANT_PROPERTY))
|
||||||
|
== 0) {
|
||||||
|
reentrant = strcmp(p + sizeof(REENTRANT_PROPERTY), "true") == 0;
|
||||||
} else if (strncmp(p,
|
} else if (strncmp(p,
|
||||||
EMBED_PREFIX_PROPERTY "=",
|
EMBED_PREFIX_PROPERTY "=",
|
||||||
sizeof(EMBED_PREFIX_PROPERTY)) == 0) {
|
sizeof(EMBED_PREFIX_PROPERTY)) == 0) {
|
||||||
@ -3689,7 +3693,7 @@ extern "C" AVIAN_EXPORT jint JNICALL
|
|||||||
++propertyCount;
|
++propertyCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
System* s = makeSystem();
|
System* s = makeSystem(reentrant);
|
||||||
Heap* h = makeHeap(s, heapLimit);
|
Heap* h = makeHeap(s, heapLimit);
|
||||||
Classpath* c = makeClasspath(s, h, javaHome, embedPrefix);
|
Classpath* c = makeClasspath(s, h, javaHome, embedPrefix);
|
||||||
|
|
||||||
|
@ -5889,14 +5889,14 @@ GcMethod* getCaller(Thread* t, unsigned target, bool skipMethodInvoke)
|
|||||||
return v.method;
|
return v.method;
|
||||||
}
|
}
|
||||||
|
|
||||||
object defineClass(Thread* t,
|
GcClass* defineClass(Thread* t,
|
||||||
GcClassLoader* loader,
|
GcClassLoader* loader,
|
||||||
const uint8_t* buffer,
|
const uint8_t* buffer,
|
||||||
unsigned length)
|
unsigned length)
|
||||||
{
|
{
|
||||||
PROTECT(t, loader);
|
PROTECT(t, loader);
|
||||||
|
|
||||||
object c = parseClass(t, loader, buffer, length);
|
GcClass* c = parseClass(t, loader, buffer, length);
|
||||||
|
|
||||||
// char name[byteArrayLength(t, className(t, c))];
|
// char name[byteArrayLength(t, className(t, c))];
|
||||||
// memcpy(name, &byteArrayBody(t, className(t, c), 0),
|
// memcpy(name, &byteArrayBody(t, className(t, c), 0),
|
||||||
@ -5915,7 +5915,7 @@ object defineClass(Thread* t,
|
|||||||
|
|
||||||
PROTECT(t, c);
|
PROTECT(t, c);
|
||||||
|
|
||||||
saveLoadedClass(t, loader, cast<GcClass>(t, c));
|
saveLoadedClass(t, loader, c);
|
||||||
|
|
||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
|
@ -92,7 +92,7 @@ const int signals[] = {VisitSignal, InterruptSignal, PipeSignal};
|
|||||||
const unsigned SignalCount = 3;
|
const unsigned SignalCount = 3;
|
||||||
|
|
||||||
class MySystem;
|
class MySystem;
|
||||||
MySystem* system;
|
MySystem* globalSystem;
|
||||||
|
|
||||||
void handleSignal(int signal, siginfo_t* info, void* context);
|
void handleSignal(int signal, siginfo_t* info, void* context);
|
||||||
|
|
||||||
@ -624,16 +624,18 @@ class MySystem : public System {
|
|||||||
System::Library* next_;
|
System::Library* next_;
|
||||||
};
|
};
|
||||||
|
|
||||||
MySystem() : threadVisitor(0), visitTarget(0)
|
MySystem(bool reentrant) : reentrant(reentrant), threadVisitor(0), visitTarget(0)
|
||||||
{
|
{
|
||||||
expect(this, system == 0);
|
if (not reentrant) {
|
||||||
system = this;
|
expect(this, globalSystem == 0);
|
||||||
|
globalSystem = this;
|
||||||
|
|
||||||
expect(this, registerHandler(InterruptSignalIndex));
|
expect(this, registerHandler(InterruptSignalIndex));
|
||||||
expect(this, registerHandler(VisitSignalIndex));
|
expect(this, registerHandler(VisitSignalIndex));
|
||||||
expect(this, registerHandler(PipeSignalIndex));
|
expect(this, registerHandler(PipeSignalIndex));
|
||||||
|
|
||||||
expect(this, make(&visitLock) == 0);
|
expect(this, make(&visitLock) == 0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns true on success, false on failure
|
// Returns true on success, false on failure
|
||||||
@ -708,6 +710,8 @@ class MySystem : public System {
|
|||||||
System::Thread* sTarget,
|
System::Thread* sTarget,
|
||||||
ThreadVisitor* visitor)
|
ThreadVisitor* visitor)
|
||||||
{
|
{
|
||||||
|
expect(this, not reentrant);
|
||||||
|
|
||||||
assertT(this, st != sTarget);
|
assertT(this, st != sTarget);
|
||||||
|
|
||||||
Thread* target = static_cast<Thread*>(sTarget);
|
Thread* target = static_cast<Thread*>(sTarget);
|
||||||
@ -767,7 +771,7 @@ class MySystem : public System {
|
|||||||
|
|
||||||
threadVisitor = 0;
|
threadVisitor = 0;
|
||||||
|
|
||||||
system->visitLock->notifyAll(t);
|
globalSystem->visitLock->notifyAll(t);
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
#endif // not __APPLE__
|
#endif // not __APPLE__
|
||||||
@ -938,18 +942,21 @@ class MySystem : public System {
|
|||||||
|
|
||||||
virtual void dispose()
|
virtual void dispose()
|
||||||
{
|
{
|
||||||
visitLock->dispose();
|
if (not reentrant) {
|
||||||
|
visitLock->dispose();
|
||||||
|
|
||||||
expect(this, unregisterHandler(InterruptSignalIndex));
|
expect(this, unregisterHandler(InterruptSignalIndex));
|
||||||
expect(this, unregisterHandler(VisitSignalIndex));
|
expect(this, unregisterHandler(VisitSignalIndex));
|
||||||
expect(this, unregisterHandler(PipeSignalIndex));
|
expect(this, unregisterHandler(PipeSignalIndex));
|
||||||
system = 0;
|
globalSystem = 0;
|
||||||
|
}
|
||||||
|
|
||||||
::free(this);
|
::free(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct sigaction oldHandlers[SignalCount];
|
struct sigaction oldHandlers[SignalCount];
|
||||||
|
|
||||||
|
bool reentrant;
|
||||||
ThreadVisitor* threadVisitor;
|
ThreadVisitor* threadVisitor;
|
||||||
Thread* visitTarget;
|
Thread* visitTarget;
|
||||||
System::Monitor* visitLock;
|
System::Monitor* visitLock;
|
||||||
@ -965,13 +972,13 @@ void handleSignal(int signal, siginfo_t*, void* context)
|
|||||||
|
|
||||||
switch (signal) {
|
switch (signal) {
|
||||||
case VisitSignal: {
|
case VisitSignal: {
|
||||||
system->threadVisitor->visit(ip, stack, link);
|
globalSystem->threadVisitor->visit(ip, stack, link);
|
||||||
|
|
||||||
System::Thread* t = system->visitTarget;
|
System::Thread* t = globalSystem->visitTarget;
|
||||||
system->visitTarget = 0;
|
globalSystem->visitTarget = 0;
|
||||||
|
|
||||||
ACQUIRE_MONITOR(t, system->visitLock);
|
ACQUIRE_MONITOR(t, globalSystem->visitLock);
|
||||||
system->visitLock->notifyAll(t);
|
globalSystem->visitLock->notifyAll(t);
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case InterruptSignal:
|
case InterruptSignal:
|
||||||
@ -987,9 +994,9 @@ void handleSignal(int signal, siginfo_t*, void* context)
|
|||||||
|
|
||||||
namespace vm {
|
namespace vm {
|
||||||
|
|
||||||
AVIAN_EXPORT System* makeSystem()
|
AVIAN_EXPORT System* makeSystem(bool reentrant)
|
||||||
{
|
{
|
||||||
return new (malloc(sizeof(MySystem))) MySystem();
|
return new (malloc(sizeof(MySystem))) MySystem(reentrant);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace vm
|
} // namespace vm
|
||||||
|
@ -115,7 +115,7 @@ class MutexResource {
|
|||||||
};
|
};
|
||||||
|
|
||||||
class MySystem;
|
class MySystem;
|
||||||
MySystem* system;
|
MySystem* globalSystem;
|
||||||
|
|
||||||
DWORD WINAPI run(void* r)
|
DWORD WINAPI run(void* r)
|
||||||
{
|
{
|
||||||
@ -655,10 +655,12 @@ class MySystem : public System {
|
|||||||
System::Library* next_;
|
System::Library* next_;
|
||||||
};
|
};
|
||||||
|
|
||||||
MySystem()
|
MySystem(bool reentrant): reentrant(reentrant)
|
||||||
{
|
{
|
||||||
expect(this, system == 0);
|
if (not reentrant) {
|
||||||
system = this;
|
expect(this, globalSystem == 0);
|
||||||
|
globalSystem = this;
|
||||||
|
}
|
||||||
|
|
||||||
mutex = CreateMutex(0, false, 0);
|
mutex = CreateMutex(0, false, 0);
|
||||||
assertT(this, mutex);
|
assertT(this, mutex);
|
||||||
@ -1007,21 +1009,25 @@ class MySystem : public System {
|
|||||||
|
|
||||||
virtual void dispose()
|
virtual void dispose()
|
||||||
{
|
{
|
||||||
system = 0;
|
if (not reentrant) {
|
||||||
|
globalSystem = 0;
|
||||||
|
}
|
||||||
|
|
||||||
CloseHandle(mutex);
|
CloseHandle(mutex);
|
||||||
::free(this);
|
::free(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
HANDLE mutex;
|
HANDLE mutex;
|
||||||
|
bool reentrant;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
namespace vm {
|
namespace vm {
|
||||||
|
|
||||||
AVIAN_EXPORT System* makeSystem()
|
AVIAN_EXPORT System* makeSystem(bool reentrant)
|
||||||
{
|
{
|
||||||
return new (malloc(sizeof(MySystem))) MySystem();
|
return new (malloc(sizeof(MySystem))) MySystem(reentrant);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace vm
|
} // namespace vm
|
||||||
|
File diff suppressed because it is too large
Load Diff
80
test/BufferedInputStreamTest.java
Normal file
80
test/BufferedInputStreamTest.java
Normal file
@ -0,0 +1,80 @@
|
|||||||
|
|
||||||
|
import java.io.ByteArrayInputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.BufferedInputStream;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks that BufferedInputStream does not block if data is available in it's internal buffer.
|
||||||
|
*/
|
||||||
|
public class BufferedInputStreamTest
|
||||||
|
{
|
||||||
|
public static void main(String[] args) throws IOException
|
||||||
|
{
|
||||||
|
MyByteArrayStream in = new MyByteArrayStream(new byte[100]);
|
||||||
|
|
||||||
|
BufferedInputStream bin = new BufferedInputStream(in);
|
||||||
|
//read a single byte to fill the buffer
|
||||||
|
int b = bin.read();
|
||||||
|
byte[] buf = new byte[10];
|
||||||
|
//now try to read 10 bytes. this should a least return the content of the buffer. On OpenJDK this are
|
||||||
|
//4 bytes (the rest of the buffer returned by MyByteArrayStream in the first call).
|
||||||
|
//It should definately NOT block.
|
||||||
|
int count = bin.read(buf);
|
||||||
|
System.out.println("Read bytes: " + count);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Internal Stream used to show the BufferedInputStream behaviour.
|
||||||
|
*/
|
||||||
|
static class MyByteArrayStream extends ByteArrayInputStream
|
||||||
|
{
|
||||||
|
boolean stopReading = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param buf
|
||||||
|
*/
|
||||||
|
public MyByteArrayStream(byte[] buf)
|
||||||
|
{
|
||||||
|
super(buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* (non-Javadoc)
|
||||||
|
* @see java.io.ByteArrayInputStream#read(byte[], int, int)
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public synchronized int read(byte[] b, int off, int len)
|
||||||
|
{
|
||||||
|
if(stopReading == false)
|
||||||
|
{ //On the first call 5 bytes are returned.
|
||||||
|
stopReading = true;
|
||||||
|
return super.read(b, off, 5);
|
||||||
|
}
|
||||||
|
//on all following calls block. The spec says, that a least one byte is returned, if the
|
||||||
|
//stream is not at EOF.
|
||||||
|
while(available() == 0)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Thread.sleep(100);
|
||||||
|
}
|
||||||
|
catch (InterruptedException e)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* (non-Javadoc)
|
||||||
|
* @see java.io.ByteArrayInputStream#available()
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public synchronized int available()
|
||||||
|
{
|
||||||
|
if(stopReading)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return super.available();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -291,9 +291,18 @@ public class Misc {
|
|||||||
test = true;
|
test = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
expect(count == 2);
|
// This test is only relevant if multi-classpath-test.txt
|
||||||
expect(test);
|
// actually exists in somewhere under the classpath from which
|
||||||
expect(extraDir);
|
// Misc.class was loaded. Since we run this test from an
|
||||||
|
// AOT-compiled boot image as well as straight from the
|
||||||
|
// filesystem, and the boot image does not contain
|
||||||
|
// multi-classpath-test.txt, we'll skip the test if it's not
|
||||||
|
// present.
|
||||||
|
if (count != 0) {
|
||||||
|
expect(count == 2);
|
||||||
|
expect(test);
|
||||||
|
expect(extraDir);
|
||||||
|
}
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
throw new RuntimeException(e);
|
throw new RuntimeException(e);
|
||||||
}
|
}
|
||||||
|
@ -97,6 +97,7 @@ else
|
|||||||
if has_flag openjdk-src || ! has_flag openjdk; then
|
if has_flag openjdk-src || ! has_flag openjdk; then
|
||||||
run make ${flags} mode=debug bootimage=true ${make_target}
|
run make ${flags} mode=debug bootimage=true ${make_target}
|
||||||
run make ${flags} bootimage=true ${make_target}
|
run make ${flags} bootimage=true ${make_target}
|
||||||
|
run make ${flags} bootimage=true bootimage-test=true ${make_target}
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if ! has_flag openjdk && ! has_flag android && ! has_flag arch; then
|
if ! has_flag openjdk && ! has_flag android && ! has_flag arch; then
|
||||||
|
Reference in New Issue
Block a user