Merge branch 'master' into compiler

Conflicts:

	src/compile.cpp
	src/compiler.cpp
	src/compiler.h
This commit is contained in:
Joel Dice 2008-04-13 13:48:20 -06:00
commit 525f733171
60 changed files with 2259 additions and 936 deletions

View File

@ -519,31 +519,6 @@ Java_java_lang_Math_pow(JNIEnv*, jclass, jdouble val, jdouble exp)
return pow(val, exp); return pow(val, exp);
} }
extern "C" JNIEXPORT void JNICALL
Java_java_lang_Math_natRandomInitialize(JNIEnv*, jclass, jlong val)
{
#ifdef WIN32
srand(val);
#else
srand48(val);
#endif
}
extern "C" JNIEXPORT jdouble JNICALL
Java_java_lang_Math_natRandom(JNIEnv*, jclass)
{
#ifdef WIN32
double r = static_cast<double>(rand()) / static_cast<double>(RAND_MAX);
if (r < 0 or r >= 1) {
return 0;
} else {
return r;
}
#else
return drand48();
#endif
}
extern "C" JNIEXPORT jdouble JNICALL extern "C" JNIEXPORT jdouble JNICALL
Java_java_lang_Math_floor(JNIEnv*, jclass, jdouble val) Java_java_lang_Math_floor(JNIEnv*, jclass, jdouble val)
{ {

View File

@ -575,6 +575,13 @@ Java_java_nio_channels_SocketSelector_natDoSocketSelect(JNIEnv *e, jclass,
timeval time = { interval / 1000, (interval % 1000) * 1000 }; timeval time = { interval / 1000, (interval % 1000) * 1000 };
int r = ::select(max + 1, &(s->read), &(s->write), &(s->except), &time); int r = ::select(max + 1, &(s->read), &(s->write), &(s->except), &time);
if (r < 0) {
if (errno != EINTR) {
throwIOException(e);
return 0;
}
}
#ifdef WIN32 #ifdef WIN32
if (FD_ISSET(s->control.writer(), &(s->write)) or if (FD_ISSET(s->control.writer(), &(s->write)) or
FD_ISSET(s->control.writer(), &(s->except))) FD_ISSET(s->control.writer(), &(s->except)))
@ -618,11 +625,6 @@ Java_java_nio_channels_SocketSelector_natDoSocketSelect(JNIEnv *e, jclass,
} }
} }
if (r < 0) {
if (errno != EINTR) {
throwIOException(e);
}
}
return r; return r;
} }

View File

@ -21,6 +21,10 @@ public class ByteArrayInputStream extends InputStream {
this.limit = offset + length; this.limit = offset + length;
} }
public ByteArrayInputStream(byte[] array) {
this(array, 0, array.length);
}
public int read() { public int read() {
if (position < limit) { if (position < limit) {
return array[position++] & 0xff; return array[position++] & 0xff;

View File

@ -52,5 +52,17 @@ public abstract class InputStream {
return 0; return 0;
} }
public void mark(int limit) {
// ignore
}
public void reset() throws IOException {
// ignore
}
public boolean markSupported() {
return false;
}
public void close() throws IOException { } public void close() throws IOException { }
} }

View File

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

View File

@ -11,6 +11,9 @@
package java.lang; package java.lang;
public final class Character implements Comparable<Character> { public final class Character implements Comparable<Character> {
public static final int MIN_RADIX = 2;
public static final int MAX_RADIX = 36;
public static final Class TYPE = Class.forCanonicalName("C"); public static final Class TYPE = Class.forCanonicalName("C");
private final char value; private final char value;
@ -67,6 +70,23 @@ public final class Character implements Comparable<Character> {
return c >= '0' && c <= '9'; return c >= '0' && c <= '9';
} }
public static int digit(char c, int radix) {
int digit = 0;
if ((c >= '0') && (c <= '9')) {
digit = c - '0';
} else if ((c >= 'a') && (c <= 'z')) {
digit = c - 'a' + 10;
} else {
return -1;
}
if (digit < radix) {
return digit;
} else {
return -1;
}
}
public static boolean isLetter(char c) { public static boolean isLetter(char c) {
return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'); return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z');
} }

View File

@ -376,6 +376,10 @@ public final class Class <T> {
return flags; return flags;
} }
public boolean isInterface() {
return (flags & Modifier.INTERFACE) != 0;
}
public Class getSuperclass() { public Class getSuperclass() {
return super_; return super_;
} }

View File

@ -58,6 +58,10 @@ public final class Integer extends Number implements Comparable<Integer> {
return Long.toString(((long) v) & 0xFFFFFFFFL, 16); return Long.toString(((long) v) & 0xFFFFFFFFL, 16);
} }
public static String toBinaryString(int v) {
return Long.toString(((long) v) & 0xFFFFFFFFL, 2);
}
public byte byteValue() { public byte byteValue() {
return (byte) value; return (byte) value;
} }

View File

@ -11,8 +11,10 @@
package java.lang; package java.lang;
public final class Long extends Number implements Comparable<Long> { public final class Long extends Number implements Comparable<Long> {
public static final Long MIN_VALUE = -9223372036854775808l;
public static final Long MAX_VALUE = 9223372036854775807l;
public static final Class TYPE = Class.forCanonicalName("J"); public static final Class TYPE = Class.forCanonicalName("J");
public static final Long MAX_VALUE = 9223372036854775807l;
private final long value; private final long value;
@ -131,16 +133,13 @@ public final class Long extends Number implements Comparable<Long> {
for (; i < s.length(); ++i) { for (; i < s.length(); ++i) {
char c = s.charAt(i); char c = s.charAt(i);
if (((c >= '0') && (c <= '9')) || int digit = Character.digit(c, radix);
((c >= 'a') && (c <= 'z'))) { if (digit >= 0) {
long digit = ((c >= '0' && c <= '9') ? (c - '0') : (c - 'a' + 10)); number += digit * pow(radix, (s.length() - i - 1));
if (digit < radix) { } else {
number += digit * pow(radix, (s.length() - i - 1)); throw new NumberFormatException("invalid character " + c + " code " +
continue; (int) c);
}
} }
throw new NumberFormatException("invalid character " + c + " code " +
(int) c);
} }
if (negative) { if (negative) {

View File

@ -10,10 +10,12 @@
package java.lang; package java.lang;
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 boolean randomInitialized = false; private static final Random random = new Random();
private Math() { } private Math() { }
@ -74,17 +76,9 @@ public final class Math {
} }
public static double random() { public static double random() {
if (randomInitialized) { return random.nextDouble();
natRandomInitialize(System.currentTimeMillis());
randomInitialized = true;
}
return natRandom();
} }
public static native void natRandomInitialize(long val);
public static native double natRandom();
public static native double floor(double v); public static native double floor(double v);
public static native double ceil(double v); public static native double ceil(double v);

View File

@ -108,4 +108,14 @@ public class Thread implements Runnable {
t.sleepLock.wait(milliseconds); t.sleepLock.wait(milliseconds);
} }
} }
public StackTraceElement[] getStackTrace() {
return Throwable.resolveTrace(getStackTrace(peer));
}
private static native Object getStackTrace(long peer);
public static native int activeCount();
public static native int enumerate(Thread[] array);
} }

View File

@ -65,7 +65,7 @@ public class Throwable {
private static native Object trace(int skipCount); private static native Object trace(int skipCount);
private static native StackTraceElement[] resolveTrace(Object trace); static native StackTraceElement[] resolveTrace(Object trace);
private StackTraceElement[] resolveTrace() { private StackTraceElement[] resolveTrace() {
if (! (trace instanceof StackTraceElement[])) { if (! (trace instanceof StackTraceElement[])) {

View File

@ -33,4 +33,6 @@ public final class Modifier {
public static boolean isStatic (int v) { return (v & STATIC) != 0; } public static boolean isStatic (int v) { return (v & STATIC) != 0; }
public static boolean isFinal (int v) { return (v & FINAL) != 0; } public static boolean isFinal (int v) { return (v & FINAL) != 0; }
public static boolean isSuper (int v) { return (v & SUPER) != 0; } public static boolean isSuper (int v) { return (v & SUPER) != 0; }
public static boolean isNative (int v) { return (v & NATIVE) != 0; }
public static boolean isAbstract (int v) { return (v & ABSTRACT) != 0; }
} }

View File

@ -10,7 +10,7 @@
package java.net; package java.net;
public class InetSocketAddress { public class InetSocketAddress extends SocketAddress {
private final String host; private final String host;
private final int port; private final int port;

View File

@ -0,0 +1,17 @@
/* Copyright (c) 2008, Avian Contributors
Permission to use, copy, modify, and/or distribute this software
for any purpose with or without fee is hereby granted, provided
that the above copyright notice and this permission notice appear
in all copies.
There is NO WARRANTY for this software. See license.txt for
details. */
package java.net;
import java.io.IOException;
public abstract class ServerSocket {
public abstract void bind(SocketAddress address) throws IOException;
}

View File

@ -0,0 +1,13 @@
/* Copyright (c) 2008, Avian Contributors
Permission to use, copy, modify, and/or distribute this software
for any purpose with or without fee is hereby granted, provided
that the above copyright notice and this permission notice appear
in all copies.
There is NO WARRANTY for this software. See license.txt for
details. */
package java.net;
public abstract class SocketAddress { }

View File

@ -0,0 +1,59 @@
/* Copyright (c) 2008, Avian Contributors
Permission to use, copy, modify, and/or distribute this software
for any purpose with or without fee is hereby granted, provided
that the above copyright notice and this permission notice appear
in all copies.
There is NO WARRANTY for this software. See license.txt for
details. */
package java.nio;
public abstract class Buffer {
protected int capacity;
protected int position;
protected int limit;
public int limit() {
return limit;
}
public int remaining() {
return limit-position;
}
public int position() {
return position;
}
public int capacity() {
return capacity;
}
public Buffer limit(int newLimit) {
limit = newLimit;
return this;
}
public Buffer position(int newPosition) {
position = newPosition;
return this;
}
public boolean hasRemaining() {
return remaining() > 0;
}
public Buffer clear() {
position = 0;
limit = capacity;
return this;
}
public Buffer flip() {
limit = position;
position = 0;
return this;
}
}

View File

@ -10,27 +10,28 @@
package java.nio; package java.nio;
public class ByteBuffer implements Comparable<ByteBuffer> { public class ByteBuffer extends Buffer implements Comparable<ByteBuffer> {
private final byte[] array; private final byte[] array;
private int arrayOffset; private int arrayOffset;
private int capacity;
private int position;
private int limit;
private final boolean readOnly; private final boolean readOnly;
public static ByteBuffer allocate(int capacity) { public static ByteBuffer allocate(int capacity) {
return new ByteBuffer(new byte[capacity], false); return new ByteBuffer(new byte[capacity], 0, capacity, false);
} }
public static ByteBuffer wrap(byte[] array) { public static ByteBuffer wrap(byte[] array) {
return new ByteBuffer(array, false); return wrap(array, 0, array.length);
} }
private ByteBuffer(byte[] array, boolean readOnly) { public static ByteBuffer wrap(byte[] array, int offset, int length) {
return new ByteBuffer(array, offset, length, false);
}
private ByteBuffer(byte[] array, int offset, int length, boolean readOnly) {
this.array = array; this.array = array;
this.readOnly = readOnly; this.readOnly = readOnly;
arrayOffset = 0; arrayOffset = offset;
capacity = array.length; capacity = length;
limit = capacity; limit = capacity;
position = 0; position = 0;
} }
@ -55,35 +56,8 @@ public class ByteBuffer implements Comparable<ByteBuffer> {
return array; return array;
} }
public ByteBuffer clear() {
position = 0;
limit = capacity;
return this;
}
public ByteBuffer slice() { public ByteBuffer slice() {
ByteBuffer buf = new ByteBuffer(array, true); return new ByteBuffer(array, arrayOffset + position, remaining(), true);
buf.arrayOffset = arrayOffset + position;
buf.position = 0;
buf.capacity = remaining();
buf.limit = buf.capacity;
return buf;
}
public int limit() {
return limit;
}
public int remaining() {
return limit-position;
}
public int position() {
return position;
}
public int capacity() {
return capacity;
} }
public int arrayOffset() { public int arrayOffset() {
@ -100,16 +74,6 @@ public class ByteBuffer implements Comparable<ByteBuffer> {
return this; return this;
} }
public ByteBuffer limit(int newLimit) {
limit = newLimit;
return this;
}
public ByteBuffer position(int newPosition) {
position = newPosition;
return this;
}
public ByteBuffer put(byte val) { public ByteBuffer put(byte val) {
checkPut(1); checkPut(1);
array[arrayOffset+(position++)] = val; array[arrayOffset+(position++)] = val;
@ -164,10 +128,6 @@ public class ByteBuffer implements Comparable<ByteBuffer> {
return this; return this;
} }
public boolean hasRemaining() {
return remaining() > 0;
}
public byte get() { public byte get() {
checkGet(1); checkGet(1);
return array[arrayOffset+(position++)]; return array[arrayOffset+(position++)];
@ -189,12 +149,6 @@ public class ByteBuffer implements Comparable<ByteBuffer> {
return array[arrayOffset+position]; return array[arrayOffset+position];
} }
public ByteBuffer flip() {
limit = position;
position = 0;
return this;
}
public int getInt() { public int getInt() {
checkGet(4); checkGet(4);
int i = get() << 24; int i = get() << 24;

View File

@ -16,22 +16,23 @@ import java.nio.ByteBuffer;
public abstract class SelectableChannel implements Channel { public abstract class SelectableChannel implements Channel {
private SelectionKey key; private SelectionKey key;
public abstract int read(ByteBuffer b) throws Exception; public abstract SelectableChannel configureBlocking(boolean v)
public abstract int write(ByteBuffer b) throws Exception; throws IOException;
public abstract boolean isOpen();
public SelectionKey register(Selector selector, int interestOps, public SelectionKey register(Selector selector, int interestOps,
Object attachment) Object attachment)
{ {
SelectionKey key = new SelectionKey key = new SelectionKey(this, selector, interestOps, attachment);
(this, selector, interestOps, attachment);
selector.add(key); selector.add(key);
return key; return key;
} }
public boolean isOpen() {
return key != null;
}
public void close() throws IOException { public void close() throws IOException {
if (key != null) { if (key != null) {
key.selector().remove(key);
key = null; key = null;
} }
} }

View File

@ -36,8 +36,9 @@ public class SelectionKey {
return interestOps; return interestOps;
} }
public void interestOps(int v) { public SelectionKey interestOps(int v) {
this.interestOps = v; this.interestOps = v;
return this;
} }
public int readyOps() { public int readyOps() {

View File

@ -40,9 +40,9 @@ public abstract class Selector {
public abstract boolean isOpen(); public abstract boolean isOpen();
public abstract void wakeup(); public abstract Selector wakeup();
public abstract void select(long interval) throws IOException; public abstract int select(long interval) throws IOException;
public abstract void close(); public abstract void close();
} }

View File

@ -10,7 +10,11 @@
package java.nio.channels; package java.nio.channels;
import java.io.IOException;
import java.net.InetSocketAddress; import java.net.InetSocketAddress;
import java.net.SocketAddress;
import java.net.ServerSocket;
public class ServerSocketChannel extends SocketChannel { public class ServerSocketChannel extends SocketChannel {
public static ServerSocketChannel open() { public static ServerSocketChannel open() {
@ -24,26 +28,32 @@ public class ServerSocketChannel extends SocketChannel {
return c; return c;
} }
public Handle socket() { public ServerSocket socket() {
return new Handle(); return new Handle();
} }
private int doAccept() throws Exception { private int doAccept() throws IOException {
return natDoAccept(socket); return natDoAccept(socket);
} }
private int doListen(String host, int port) throws Exception { private int doListen(String host, int port) throws IOException {
return natDoListen(host, port); return natDoListen(host, port);
} }
public class Handle { public class Handle extends ServerSocket {
public void bind(InetSocketAddress address) public void bind(SocketAddress address)
throws Exception throws IOException
{ {
socket = doListen(address.getHostName(), address.getPort()); InetSocketAddress a;
try {
a = (InetSocketAddress) address;
} catch (ClassCastException e) {
throw new IllegalArgumentException();
}
socket = doListen(a.getHostName(), a.getPort());
} }
} }
private static native int natDoAccept(int socket) throws Exception; private static native int natDoAccept(int socket) throws IOException;
private static native int natDoListen(String host, int port) throws Exception; private static native int natDoListen(String host, int port) throws IOException;
} }

View File

@ -11,6 +11,7 @@
package java.nio.channels; package java.nio.channels;
import java.io.IOException; import java.io.IOException;
import java.net.SocketAddress;
import java.net.InetSocketAddress; import java.net.InetSocketAddress;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
@ -20,30 +21,33 @@ public class SocketChannel extends SelectableChannel
public static final int InvalidSocket = -1; public static final int InvalidSocket = -1;
protected int socket = InvalidSocket; protected int socket = InvalidSocket;
protected boolean open = true;
protected boolean connected = false; protected boolean connected = false;
public static SocketChannel open() { public static SocketChannel open() {
return new SocketChannel(); return new SocketChannel();
} }
public void configureBlocking(boolean v) { public SelectableChannel configureBlocking(boolean v) {
if (v) throw new IllegalArgumentException(); if (v) throw new IllegalArgumentException();
return this;
} }
public void connect(InetSocketAddress address) throws Exception { public boolean connect(SocketAddress address) throws Exception {
socket = doConnect(address.getHostName(), address.getPort()); InetSocketAddress a;
try {
a = (InetSocketAddress) address;
} catch (ClassCastException e) {
throw new UnsupportedAddressTypeException();
}
socket = doConnect(a.getHostName(), a.getPort());
return connected;
} }
public void close() throws IOException { public void close() throws IOException {
super.close(); if (isOpen()) {
if (! open) return; super.close();
closeSocket(); closeSocket();
open = false; }
}
public boolean isOpen() {
return open;
} }
private int doConnect(String host, int port) throws Exception { private int doConnect(String host, int port) throws Exception {
@ -54,7 +58,7 @@ public class SocketChannel extends SelectableChannel
} }
public int read(ByteBuffer b) throws IOException { public int read(ByteBuffer b) throws IOException {
if (! open) return -1; if (! isOpen()) return -1;
if (b.remaining() == 0) return 0; if (b.remaining() == 0) return 0;
int r = natRead(socket, b.array(), b.arrayOffset() + b.position(), b.remaining()); int r = natRead(socket, b.array(), b.arrayOffset() + b.position(), b.remaining());
if (r > 0) { if (r > 0) {

View File

@ -14,15 +14,10 @@ import java.io.IOException;
import java.util.Iterator; import java.util.Iterator;
class SocketSelector extends Selector { class SocketSelector extends Selector {
private static final boolean IsWin32;
protected long state; protected long state;
protected final Object lock = new Object(); protected final Object lock = new Object();
protected boolean woken = false; protected boolean woken = false;
static {
IsWin32 = false;
}
public SocketSelector() { public SocketSelector() {
state = natInit(); state = natInit();
} }
@ -31,7 +26,7 @@ class SocketSelector extends Selector {
return state != 0; return state != 0;
} }
public void wakeup() { public Selector wakeup() {
synchronized (lock) { synchronized (lock) {
if (! woken) { if (! woken) {
woken = true; woken = true;
@ -39,6 +34,7 @@ class SocketSelector extends Selector {
natWakeup(state); natWakeup(state);
} }
} }
return this;
} }
private boolean clearWoken() { private boolean clearWoken() {
@ -52,10 +48,11 @@ class SocketSelector extends Selector {
} }
} }
public synchronized void select(long interval) throws IOException { public synchronized int select(long interval) throws IOException {
selectedKeys.clear(); selectedKeys.clear();
if (clearWoken()) return; if (clearWoken()) return 0;
int max=0; int max=0;
for (Iterator<SelectionKey> it = keys.iterator(); for (Iterator<SelectionKey> it = keys.iterator();
it.hasNext();) it.hasNext();)
@ -63,14 +60,14 @@ class SocketSelector extends Selector {
SelectionKey key = it.next(); SelectionKey key = it.next();
SocketChannel c = (SocketChannel)key.channel(); SocketChannel c = (SocketChannel)key.channel();
int socket = c.socketFD(); int socket = c.socketFD();
if (! c.isOpen()) { if (c.isOpen()) {
key.readyOps(0);
max = natSelectUpdateInterestSet
(socket, key.interestOps(), state, max);
} else {
natSelectClearAll(socket, state); natSelectClearAll(socket, state);
it.remove(); it.remove();
continue;
} }
key.readyOps(0);
max = natSelectUpdateInterestSet(socket, key.interestOps(), state, max);
} }
int r = natDoSocketSelect(state, max, interval); int r = natDoSocketSelect(state, max, interval);
@ -87,6 +84,8 @@ class SocketSelector extends Selector {
} }
} }
clearWoken(); clearWoken();
return selectedKeys.size();
} }
public void close() { public void close() {

View File

@ -0,0 +1,17 @@
/* Copyright (c) 2008, Avian Contributors
Permission to use, copy, modify, and/or distribute this software
for any purpose with or without fee is hereby granted, provided
that the above copyright notice and this permission notice appear
in all copies.
There is NO WARRANTY for this software. See license.txt for
details. */
package java.nio.channels;
public class UnsupportedAddressTypeException extends IllegalArgumentException {
public UnsupportedAddressTypeException() {
super(null, null);
}
}

View File

@ -11,15 +11,54 @@
package java.util; package java.util;
public class Random { public class Random {
public int nextInt(int n) { private static final long Mask = 0x5DEECE66DL;
return nextInt() % n;
private static long nextSeed = 0;
private long seed;
public Random(long seed) {
setSeed(seed);
}
public Random() {
setSeed((nextSeed++) ^ System.currentTimeMillis());
}
public void setSeed(long seed) {
this.seed = (seed ^ Mask) & ((1L << 48) - 1);
}
protected int next(int bits) {
seed = ((seed * Mask) + 0xBL) & ((1L << 48) - 1);
return (int) (seed >>> (48 - bits));
}
public int nextInt(int limit) {
if (limit <= 0) {
throw new IllegalArgumentException();
}
if ((limit & -limit) == limit) {
// limit is a power of two
return (int) ((limit * (long) next(31)) >> 31);
}
int bits;
int value;
do {
bits = next(31);
value = bits % limit;
} while (bits - value + (limit - 1) < 0);
return value;
} }
public int nextInt() { public int nextInt() {
return (int)(Math.random()*Integer.MAX_VALUE); return next(32);
} }
public double nextDouble() { public double nextDouble() {
return Math.random(); return (((long) next(26) << 27) + next(27)) / (double) (1L << 53);
} }
} }

View File

@ -37,6 +37,10 @@ public class Vector<T> implements List<T> {
list.add(index, element); list.add(index, element);
} }
public void insertElementAt(T element, int index) {
add(index, element);
}
public synchronized boolean add(T element) { public synchronized boolean add(T element) {
return list.add(element); return list.add(element);
} }
@ -57,6 +61,10 @@ public class Vector<T> implements List<T> {
return list.set(index, value); return list.set(index, value);
} }
public T setElementAt(T value, int index) {
return set(index, value);
}
public T elementAt(int index) { public T elementAt(int index) {
return get(index); return get(index);
} }

View File

@ -52,12 +52,12 @@ strip-all = --strip-all
rdynamic = -rdynamic rdynamic = -rdynamic
warnings = -Wall -Wextra -Werror -Wunused-parameter \ warnings = -Wall -Wextra -Werror -Wunused-parameter -Winit-self
-Winit-self -Wconversion
common-cflags = $(warnings) -fno-rtti -fno-exceptions \ common-cflags = $(warnings) -fno-rtti -fno-exceptions \
-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)\" \
-DBOOT_CLASSPATH=\"[classpathJar]\"
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
@ -66,7 +66,7 @@ cflags = $(build-cflags)
common-lflags = -lm -lz common-lflags = -lm -lz
lflags = $(common-lflags) -lpthread -ldl -rdynamic lflags = $(common-lflags) -lpthread -ldl
system = posix system = posix
asm = x86 asm = x86
@ -75,6 +75,11 @@ object-arch = i386:x86-64
object-format = elf64-x86-64 object-format = elf64-x86-64
pointer-size = 8 pointer-size = 8
so-prefix = lib
so-suffix = .so
shared = -shared
ifeq ($(arch),i386) ifeq ($(arch),i386)
object-arch = i386 object-arch = i386
object-format = elf32-i386 object-format = elf32-i386
@ -85,8 +90,11 @@ ifeq ($(platform),darwin)
build-cflags = $(common-cflags) -fPIC -fvisibility=hidden \ build-cflags = $(common-cflags) -fPIC -fvisibility=hidden \
-I$(JAVA_HOME)/include/linux -I$(src) -I$(JAVA_HOME)/include/linux -I$(src)
lflags = $(common-lflags) -ldl -framework CoreFoundation lflags = $(common-lflags) -ldl -framework CoreFoundation
rdynamic =
strip-all = -S -x strip-all = -S -x
binaryToMacho = $(native-build)/binaryToMacho binaryToMacho = $(native-build)/binaryToMacho
so-suffix = .jnilib
shared = -dynamiclib
endif endif
ifeq ($(platform),windows) ifeq ($(platform),windows)
@ -96,6 +104,9 @@ ifeq ($(platform),windows)
system = windows system = windows
object-format = pe-i386 object-format = pe-i386
so-prefix =
so-suffix = .dll
cxx = i586-mingw32msvc-g++ cxx = i586-mingw32msvc-g++
cc = i586-mingw32msvc-gcc cc = i586-mingw32msvc-gcc
dlltool = i586-mingw32msvc-dlltool dlltool = i586-mingw32msvc-dlltool
@ -104,7 +115,7 @@ ifeq ($(platform),windows)
objcopy = i586-mingw32msvc-objcopy objcopy = i586-mingw32msvc-objcopy
rdynamic = -Wl,--export-dynamic rdynamic = -Wl,--export-dynamic
lflags = -L$(lib) $(common-lflags) -lws2_32 -Wl,--kill-at -mwindows -mconsole lflags = -L$(lib) $(common-lflags) -lws2_32 -mwindows -mconsole
cflags = $(common-cflags) -I$(inc) cflags = $(common-cflags) -I$(inc)
endif endif
@ -185,9 +196,12 @@ vm-cpp-objects = $(call cpp-objects,$(vm-sources),$(src),$(native-build))
vm-asm-objects = $(call asm-objects,$(vm-asm-sources),$(src),$(native-build)) vm-asm-objects = $(call asm-objects,$(vm-asm-sources),$(src),$(native-build))
vm-objects = $(vm-cpp-objects) $(vm-asm-objects) vm-objects = $(vm-cpp-objects) $(vm-asm-objects)
driver-sources = $(src)/main.cpp driver-source = $(src)/main.cpp
driver-object = $(native-build)/main.o
driver-dynamic-object = $(native-build)/main-dynamic.o
driver-object = $(call cpp-objects,$(driver-sources),$(src),$(native-build)) boot-source = $(src)/boot.cpp
boot-object = $(native-build)/boot.o
generator-headers = $(src)/constants.h generator-headers = $(src)/constants.h
generator-sources = $(src)/type-generator.cpp generator-sources = $(src)/type-generator.cpp
@ -195,8 +209,10 @@ generator-objects = \
$(call cpp-objects,$(generator-sources),$(src),$(native-build)) $(call cpp-objects,$(generator-sources),$(src),$(native-build))
generator = $(native-build)/generator generator = $(native-build)/generator
libvm = $(native-build)/lib$(name).a static-library = $(native-build)/lib$(name).a
vm = $(native-build)/$(name) executable = $(native-build)/$(name)
dynamic-library = $(native-build)/$(so-prefix)$(name)$(so-suffix)
executable-dynamic = $(native-build)/$(name)-dynamic
classpath-sources = $(shell find $(classpath) -name '*.java') classpath-sources = $(shell find $(classpath) -name '*.java')
classpath-classes = \ classpath-classes = \
@ -216,31 +232,36 @@ flags = -cp $(test-build)
args = $(flags) $(input) args = $(flags) $(input)
.PHONY: build .PHONY: build
build: $(vm) $(libvm) $(classpath-dep) $(test-dep) build: $(static-library) $(executable) $(dynamic-library) \
$(executable-dynamic) $(classpath-dep) $(test-dep)
$(test-classes): $(classpath-dep) $(test-classes): $(classpath-dep)
.PHONY: run .PHONY: run
run: build run: build
$(vm) $(args) $(executable) $(args)
.PHONY: debug .PHONY: debug
debug: build debug: build
gdb --args $(vm) $(args) gdb --args $(executable) $(args)
.PHONY: vg .PHONY: vg
vg: build vg: build
$(vg) $(vm) $(args) $(vg) $(executable) $(args)
.PHONY: test .PHONY: test
test: build test: build
/bin/bash $(test)/test.sh 2>/dev/null \ /bin/bash $(test)/test.sh 2>/dev/null \
$(vm) $(mode) "$(flags)" \ $(executable) $(mode) "$(flags)" \
$(call class-names,$(test-build),$(test-classes)) $(call class-names,$(test-build),$(test-classes))
.PHONY: javadoc .PHONY: javadoc
javadoc: javadoc:
javadoc -sourcepath classpath -d build/javadoc -subpackages java javadoc -sourcepath classpath -d build/javadoc -subpackages java \
-windowtitle "Avian v$(version) Class Library API" \
-doctitle "Avian v$(version) Class Library API" \
-header "Avian v$(version)" \
-bottom "<a href=\"http://oss.readytalk.com/avian/\">http://oss.readytalk.com/avian</a>"
.PHONY: clean .PHONY: clean
clean: clean:
@ -293,7 +314,16 @@ $(vm-cpp-objects): $(native-build)/%.o: $(src)/%.cpp $(vm-depends)
$(vm-asm-objects): $(native-build)/%-asm.o: $(src)/%.S $(vm-asm-objects): $(native-build)/%-asm.o: $(src)/%.S
$(compile-object) $(compile-object)
$(driver-object): $(native-build)/%.o: $(src)/%.cpp $(driver-object): $(driver-source)
$(compile-object)
$(driver-dynamic-object): $(driver-source)
@echo "compiling $(@)"
@mkdir -p $(dir $(@))
$(cxx) $(cflags) -DBOOT_LIBRARY=\"$(so-prefix)$(name)$(so-suffix)\" \
-c $(<) -o $(@)
$(boot-object): $(boot-source)
$(compile-object) $(compile-object)
$(build)/classpath.jar: $(classpath-dep) $(build)/classpath.jar: $(classpath-dep)
@ -305,9 +335,10 @@ $(binaryToMacho): $(src)/binaryToMacho.cpp
$(cxx) $(^) -o $(@) $(cxx) $(^) -o $(@)
$(classpath-object): $(build)/classpath.jar $(binaryToMacho) $(classpath-object): $(build)/classpath.jar $(binaryToMacho)
@echo "creating $(@)"
ifeq ($(platform),darwin) ifeq ($(platform),darwin)
$(binaryToMacho) $(build)/classpath.jar \ $(binaryToMacho) $(build)/classpath.jar \
__binary_classpath_jar_start __binary_classpath_jar_size > $(@) __binary_classpath_jar_start __binary_classpath_jar_end > $(@)
else else
(wd=$$(pwd); \ (wd=$$(pwd); \
cd $(build); \ cd $(build); \
@ -324,23 +355,37 @@ $(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)
$(libvm): $(vm-objects) $(jni-objects) $(static-library): $(vm-objects) $(jni-objects)
@echo "creating $(@)" @echo "creating $(@)"
rm -rf $(@) rm -rf $(@)
$(ar) cru $(@) $(^) $(ar) cru $(@) $(^)
$(ranlib) $(@) $(ranlib) $(@)
$(vm): $(vm-objects) $(classpath-object) $(jni-objects) $(driver-object) $(executable): \
$(vm-objects) $(classpath-object) $(jni-objects) $(driver-object) \
$(boot-object)
@echo "linking $(@)" @echo "linking $(@)"
ifeq ($(platform),windows) ifeq ($(platform),windows)
$(dlltool) -z $(@).def $(^) $(dlltool) -z $(@).def $(^)
$(dlltool) -k -d $(@).def -e $(@).exp $(dlltool) -k -d $(@).def -e $(@).exp
$(cc) $(@).exp $(^) $(lflags) -o $(@) $(cc) $(@).exp $(^) $(lflags) -o $(@)
else else
$(cc) $(^) $(lflags) -o $(@) $(cc) $(^) $(rdynamic) $(lflags) -o $(@)
endif endif
$(strip) $(strip-all) $(@) $(strip) $(strip-all) $(@)
$(dynamic-library): \
$(vm-objects) $(classpath-object) $(dynamic-object) $(jni-objects) \
$(boot-object)
@echo "linking $(@)"
$(cc) $(^) $(shared) $(lflags) -o $(@)
$(strip) $(strip-all) $(@)
$(executable-dynamic): $(driver-dynamic-object) $(dynamic-library)
@echo "linking $(@)"
$(cc) $(^) $(lflags) -o $(@)
$(strip) $(strip-all) $(@)
$(generator): $(generator-objects) $(generator): $(generator-objects)
@echo "linking $(@)" @echo "linking $(@)"
$(build-cc) $(^) -o $(@) $(build-cc) $(^) -o $(@)

View File

@ -165,12 +165,12 @@ setting the classpath to "[bootJar]".
extern "C" { extern "C" {
extern const uint8_t SYMBOL(start)[]; extern const uint8_t SYMBOL(start)[];
extern const uint8_t SYMBOL(size)[]; extern const uint8_t SYMBOL(end)[];
EXPORT const uint8_t* EXPORT const uint8_t*
bootJar(unsigned* size) bootJar(unsigned* size)
{ {
*size = reinterpret_cast<uintptr_t>(SYMBOL(size)); *size = SYMBOL(end) - SYMBOL(start);
return SYMBOL(start); return SYMBOL(start);
} }

View File

@ -18,9 +18,9 @@ namespace vm {
class Allocator { class Allocator {
public: public:
virtual ~Allocator() { } virtual ~Allocator() { }
virtual void* tryAllocate(unsigned size, bool executable) = 0; virtual void* tryAllocate(unsigned size) = 0;
virtual void* allocate(unsigned size, bool executable) = 0; virtual void* allocate(unsigned size) = 0;
virtual void free(const void* p, unsigned size, bool executable) = 0; virtual void free(const void* p, unsigned size) = 0;
}; };
} // namespace vm } // namespace vm

View File

@ -120,17 +120,14 @@ class Assembler {
class Memory: public Operand { class Memory: public Operand {
public: public:
Memory(int base, int offset, int index = NoRegister, unsigned scale = 0, Memory(int base, int offset, int index = NoRegister, unsigned scale = 0):
TraceHandler* traceHandler = 0): base(base), offset(offset), index(index), scale(scale)
base(base), offset(offset), index(index), scale(scale),
traceHandler(traceHandler)
{ } { }
int base; int base;
int offset; int offset;
int index; int index;
unsigned scale; unsigned scale;
TraceHandler* traceHandler;
}; };
class Client { class Client {

View File

@ -30,10 +30,10 @@ pad(unsigned n)
void void
writeObject(FILE* out, const uint8_t* data, unsigned size, writeObject(FILE* out, const uint8_t* data, unsigned size,
const char* dataName, const char* sizeName) const char* startName, const char* endName)
{ {
unsigned dataNameLength = strlen(dataName) + 1; unsigned startNameLength = strlen(startName) + 1;
unsigned sizeNameLength = strlen(sizeName) + 1; unsigned endNameLength = strlen(endName) + 1;
mach_header header = { mach_header header = {
MH_MAGIC, // magic MH_MAGIC, // magic
@ -96,7 +96,7 @@ writeObject(FILE* out, const uint8_t* data, unsigned size,
+ sizeof(symtab_command) + sizeof(symtab_command)
+ pad(size) + pad(size)
+ (sizeof(struct nlist) * 2), // stroff + (sizeof(struct nlist) * 2), // stroff
1 + dataNameLength + sizeNameLength, // strsize 1 + startNameLength + endNameLength, // strsize
}; };
struct nlist symbolList[] = { struct nlist symbolList[] = {
@ -108,9 +108,9 @@ writeObject(FILE* out, const uint8_t* data, unsigned size,
0 // n_value 0 // n_value
}, },
{ {
reinterpret_cast<char*>(1 + dataNameLength), // n_un reinterpret_cast<char*>(1 + startNameLength), // n_un
N_ABS | N_EXT, // n_type N_SECT | N_EXT, // n_type
NO_SECT, // n_sect 1, // n_sect
0, // n_desc 0, // n_desc
size // n_value size // n_value
} }
@ -127,8 +127,8 @@ writeObject(FILE* out, const uint8_t* data, unsigned size,
fwrite(&symbolList, 1, sizeof(symbolList), out); fwrite(&symbolList, 1, sizeof(symbolList), out);
fputc(0, out); fputc(0, out);
fwrite(dataName, 1, dataNameLength, out); fwrite(startName, 1, startNameLength, out);
fwrite(sizeName, 1, sizeNameLength, out); fwrite(endName, 1, endNameLength, out);
} }
} // namespace } // namespace
@ -138,7 +138,7 @@ main(int argc, const char** argv)
{ {
if (argc != 4) { if (argc != 4) {
fprintf(stderr, fprintf(stderr,
"usage: %s <input file> <data symbol name> <size symbol name>\n", "usage: %s <input file> <start symbol name> <end symbol name>\n",
argv[0]); argv[0]);
return -1; return -1;
} }

29
src/boot.cpp Normal file
View File

@ -0,0 +1,29 @@
#include "stdint.h"
#include "stdlib.h"
// since we don't link against libstdc++, we must implement some dummy
// functions:
extern "C" void __cxa_pure_virtual(void) { abort(); }
void operator delete(void*) { abort(); }
#ifdef __MINGW32__
# define EXPORT __declspec(dllexport)
# define SYMBOL(x) binary_classpath_jar_##x
#else
# define EXPORT __attribute__ ((visibility("default")))
# define SYMBOL(x) _binary_classpath_jar_##x
#endif
extern "C" {
extern const uint8_t SYMBOL(start)[];
extern const uint8_t SYMBOL(end)[];
EXPORT const uint8_t*
classpathJar(unsigned* size)
{
*size = SYMBOL(end) - SYMBOL(start);
return SYMBOL(start);
}
}

View File

@ -47,6 +47,19 @@ search(Thread* t, jstring name, object (*op)(Thread*, object),
} }
} }
void
enumerateThreads(Thread* t, Thread* x, object array, unsigned* index,
unsigned limit)
{
if (*index < limit) {
set(t, array, ArrayBody + (*index * BytesPerWord), x->javaThread);
if (x->peer) enumerateThreads(t, x->peer, array, index, limit);
if (x->child) enumerateThreads(t, x->child, array, index, limit);
}
}
} // namespace } // namespace
extern "C" JNIEXPORT jstring JNICALL extern "C" JNIEXPORT jstring JNICALL
@ -134,10 +147,10 @@ Java_java_lang_ClassLoader_defineClass
ENTER(t, Thread::ActiveState); ENTER(t, Thread::ActiveState);
uint8_t* buffer = static_cast<uint8_t*> uint8_t* buffer = static_cast<uint8_t*>
(t->m->heap->allocate(length, false)); (t->m->heap->allocate(length));
memcpy(buffer, &byteArrayBody(t, *b, offset), length); memcpy(buffer, &byteArrayBody(t, *b, offset), length);
object c = parseClass(t, buffer, length); object c = parseClass(t, buffer, length);
t->m->heap->free(buffer, length, false); t->m->heap->free(buffer, length);
return makeLocalReference(t, c); return makeLocalReference(t, c);
} }
@ -697,6 +710,36 @@ Java_java_lang_Thread_interrupt(Thread* t, jclass, jlong peer)
interrupt(t, reinterpret_cast<Thread*>(peer)); interrupt(t, reinterpret_cast<Thread*>(peer));
} }
extern "C" JNIEXPORT jobject JNICALL
Java_java_lang_Thread_getTrace(Thread* t, jclass, jlong peer)
{
if (reinterpret_cast<Thread*>(peer) == t) {
return makeLocalReference(t, makeTrace(t));
} else {
return makeLocalReference
(t, t->m->processor->getStackTrace(t, reinterpret_cast<Thread*>(peer)));
}
}
extern "C" JNIEXPORT jint JNICALL
Java_java_lang_Thread_activeCount(Thread* t, jclass)
{
return t->m->liveCount;
}
extern "C" JNIEXPORT jint JNICALL
Java_java_lang_Thread_enumerate(Thread* t, jclass, jobjectArray array)
{
ACQUIRE_RAW(t, t->m->stateLock);
ENTER(t, Thread::ActiveState);
unsigned count = min(t->m->liveCount, objectArrayLength(t, *array));
unsigned index = 0;
enumerateThreads(t, t->m->rootThread, *array, &index, count);
return count;
}
extern "C" JNIEXPORT jlong JNICALL extern "C" JNIEXPORT jlong JNICALL
Java_java_net_URL_00024ResourceInputStream_open Java_java_net_URL_00024ResourceInputStream_open
(Thread* t, jclass, jstring path) (Thread* t, jclass, jstring path)

File diff suppressed because it is too large Load Diff

View File

@ -745,9 +745,8 @@ register_(Context* c, int low, int high = NoRegister)
class MemoryValue: public Value { class MemoryValue: public Value {
public: public:
MemoryValue(int base, int offset, int index, unsigned scale, MemoryValue(int base, int offset, int index, unsigned scale):
TraceHandler* traceHandler): value(base, offset, index, scale)
value(base, offset, index, scale, traceHandler)
{ } { }
virtual OperandType type(Context*) { return Memory; } virtual OperandType type(Context*) { return Memory; }
@ -785,8 +784,8 @@ class MemoryValue: public Value {
class AbstractMemoryValue: public MemoryValue { class AbstractMemoryValue: public MemoryValue {
public: public:
AbstractMemoryValue(MyOperand* base, int offset, MyOperand* index, AbstractMemoryValue(MyOperand* base, int offset, MyOperand* index,
unsigned scale, TraceHandler* traceHandler): unsigned scale):
MemoryValue(NoRegister, offset, NoRegister, scale, traceHandler), MemoryValue(NoRegister, offset, NoRegister, scale),
base_(base), index_(index) base_(base), index_(index)
{ } { }
@ -831,10 +830,10 @@ class AbstractMemoryValue: public MemoryValue {
AbstractMemoryValue* AbstractMemoryValue*
memory(Context* c, MyOperand* base, int offset, MyOperand* index, memory(Context* c, MyOperand* base, int offset, MyOperand* index,
unsigned scale, TraceHandler* traceHandler) unsigned scale)
{ {
return new (c->zone->allocate(sizeof(AbstractMemoryValue))) return new (c->zone->allocate(sizeof(AbstractMemoryValue)))
AbstractMemoryValue(base, offset, index, scale, traceHandler); AbstractMemoryValue(base, offset, index, scale);
} }
class StackValue: public Value { class StackValue: public Value {
@ -1996,13 +1995,12 @@ class MyCompiler: public Compiler {
virtual Operand* memory(Operand* base, virtual Operand* memory(Operand* base,
int displacement = 0, int displacement = 0,
Operand* index = 0, Operand* index = 0,
unsigned scale = 1, unsigned scale = 1)
TraceHandler* traceHandler = 0)
{ {
MyOperand* result = operand MyOperand* result = operand
(&c, ::memory (&c, ::memory
(&c, static_cast<MyOperand*>(base), displacement, (&c, static_cast<MyOperand*>(base), displacement,
static_cast<MyOperand*>(index), scale, traceHandler)); static_cast<MyOperand*>(index), scale));
appendMemory(&c, static_cast<MyOperand*>(base), appendMemory(&c, static_cast<MyOperand*>(base),
static_cast<MyOperand*>(index), result); static_cast<MyOperand*>(index), result);

View File

@ -45,8 +45,8 @@ class Compiler {
virtual Operand* memory(Operand* base, virtual Operand* memory(Operand* base,
int displacement = 0, int displacement = 0,
Operand* index = 0, Operand* index = 0,
unsigned scale = 1, unsigned scale = 1) = 0;
TraceHandler* traceHandler = 0) = 0;
virtual Operand* stack() = 0; virtual Operand* stack() = 0;
virtual Operand* base() = 0; virtual Operand* base() = 0;
virtual Operand* thread() = 0; virtual Operand* thread() = 0;

View File

@ -19,26 +19,19 @@ namespace {
void* void*
allocate(System* s, unsigned size) allocate(System* s, unsigned size)
{ {
void* p = s->tryAllocate(size, false); void* p = s->tryAllocate(size);
if (p == 0) abort(); if (p == 0) abort();
return p; return p;
} }
void
free(System* s, const void* p, unsigned size)
{
s->free(p, size, false);
}
const char* const char*
append(System* s, unsigned* length, const char* a, const char* b, append(System* s, const char* a, const char* b,
const char* c) const char* c)
{ {
unsigned al = strlen(a); unsigned al = strlen(a);
unsigned bl = strlen(b); unsigned bl = strlen(b);
unsigned cl = strlen(c); unsigned cl = strlen(c);
*length = al + bl + cl; char* p = static_cast<char*>(allocate(s, (al + bl + cl) + 1));
char* p = static_cast<char*>(allocate(s, *length + 1));
memcpy(p, a, al); memcpy(p, a, al);
memcpy(p + al, b, bl); memcpy(p + al, b, bl);
memcpy(p + al + bl, c, cl + 1); memcpy(p + al + bl, c, cl + 1);
@ -46,11 +39,10 @@ append(System* s, unsigned* length, const char* a, const char* b,
} }
const char* const char*
copy(System* s, unsigned* length, const char* a) copy(System* s, const char* a)
{ {
unsigned al = strlen(a); unsigned al = strlen(a);
*length = al; char* p = static_cast<char*>(allocate(s, al + 1));
char* p = static_cast<char*>(allocate(s, *length + 1));
memcpy(p, a, al + 1); memcpy(p, a, al + 1);
return p; return p;
} }
@ -78,16 +70,15 @@ class Element {
class DirectoryElement: public Element { class DirectoryElement: public Element {
public: public:
DirectoryElement(System* s, const char* name, unsigned nameLength): DirectoryElement(System* s, const char* name):
s(s), name(name), nameLength(nameLength) s(s), name(name)
{ } { }
virtual System::Region* find(const char* name) { virtual System::Region* find(const char* name) {
unsigned length; const char* file = append(s, this->name, "/", name);
const char* file = append(s, &length, this->name, "/", name);
System::Region* region; System::Region* region;
System::Status status = s->map(&region, file); System::Status status = s->map(&region, file);
free(s, file, length + 1); s->free(file);
if (s->success(status)) { if (s->success(status)) {
return region; return region;
@ -97,21 +88,19 @@ class DirectoryElement: public Element {
} }
virtual bool exists(const char* name) { virtual bool exists(const char* name) {
unsigned length; const char* file = append(s, this->name, "/", name);
const char* file = append(s, &length, this->name, "/", name);
System::FileType type = s->identify(file); System::FileType type = s->identify(file);
free(s, file, length + 1); s->free(file);
return type != System::DoesNotExist; return type != System::DoesNotExist;
} }
virtual void dispose() { virtual void dispose() {
free(s, name, nameLength + 1); s->free(name);
free(s, this, sizeof(*this)); s->free(this);
} }
System* s; System* s;
const char* name; const char* name;
unsigned nameLength;
}; };
class PointerRegion: public System::Region { class PointerRegion: public System::Region {
@ -131,7 +120,7 @@ class PointerRegion: public System::Region {
} }
virtual void dispose() { virtual void dispose() {
free(s, this, sizeof(*this)); s->free(this);
} }
System* s; System* s;
@ -155,7 +144,7 @@ class DataRegion: public System::Region {
} }
virtual void dispose() { virtual void dispose() {
free(s, this, sizeof(*this) + length_); s->free(this);
} }
System* s; System* s;
@ -376,8 +365,8 @@ class JarIndex {
} }
void dispose() { void dispose() {
free(s, nodes, sizeof(Node) * capacity); s->free(nodes);
free(s, this, sizeof(*this) + (sizeof(Node*) * capacity)); s->free(this);
} }
System* s; System* s;
@ -390,8 +379,8 @@ class JarIndex {
class JarElement: public Element { class JarElement: public Element {
public: public:
JarElement(System* s, const char* name, unsigned nameLength): JarElement(System* s, const char* name):
s(s), name(name), nameLength(nameLength), index(0) s(s), name(name), index(0)
{ } { }
virtual void init() { virtual void init() {
@ -421,33 +410,32 @@ class JarElement: public Element {
} }
virtual void dispose() { virtual void dispose() {
free(s, name, nameLength + 1); s->free(name);
if (index) { if (index) {
index->dispose(); index->dispose();
} }
if (region) { if (region) {
region->dispose(); region->dispose();
} }
free(s, this, sizeof(*this)); s->free(this);
} }
System* s; System* s;
const char* name; const char* name;
unsigned nameLength;
System::Region* region; System::Region* region;
JarIndex* index; JarIndex* index;
}; };
class BuiltinElement: public JarElement { class BuiltinElement: public JarElement {
public: public:
BuiltinElement(System* s, const char* name, unsigned nameLength): BuiltinElement(System* s, const char* name, const char* libraryName):
JarElement(s, name, nameLength) JarElement(s, name),
libraryName(libraryName ? copy(s, libraryName) : 0)
{ } { }
virtual void init() { virtual void init() {
if (index == 0) { if (index == 0) {
System::Library* library; if (s->success(s->load(&library, libraryName, false))) {
if (s->success(s->load(&library, 0, false))) {
void* p = library->resolve(name); void* p = library->resolve(name);
if (p) { if (p) {
uint8_t* (*function)(unsigned*); uint8_t* (*function)(unsigned*);
@ -461,14 +449,22 @@ class BuiltinElement: public JarElement {
index = JarIndex::open(s, region); index = JarIndex::open(s, region);
} }
} }
library->disposeAll();
} }
} }
} }
virtual void dispose() {
library->disposeAll();
s->free(libraryName);
JarElement::dispose();
}
System::Library* library;
const char* libraryName;
}; };
Element* Element*
parsePath(System* s, const char* path) parsePath(System* s, const char* path, const char* bootLibrary)
{ {
class Tokenizer { class Tokenizer {
public: public:
@ -509,7 +505,7 @@ parsePath(System* s, const char* path)
name[token.length - 2] = 0; name[token.length - 2] = 0;
e = new (allocate(s, sizeof(BuiltinElement))) e = new (allocate(s, sizeof(BuiltinElement)))
BuiltinElement(s, name, token.length - 2); BuiltinElement(s, name, bootLibrary);
} else { } else {
char* name = static_cast<char*>(allocate(s, token.length + 1)); char* name = static_cast<char*>(allocate(s, token.length + 1));
memcpy(name, token.s, token.length); memcpy(name, token.s, token.length);
@ -517,17 +513,16 @@ parsePath(System* s, const char* path)
switch (s->identify(name)) { switch (s->identify(name)) {
case System::File: { case System::File: {
e = new (allocate(s, sizeof(JarElement))) e = new (allocate(s, sizeof(JarElement))) JarElement(s, name);
JarElement(s, name, token.length);
} break; } break;
case System::Directory: { case System::Directory: {
e = new (allocate(s, sizeof(DirectoryElement))) e = new (allocate(s, sizeof(DirectoryElement)))
DirectoryElement(s, name, token.length); DirectoryElement(s, name);
} break; } break;
default: { default: {
free(s, name, token.length + 1); s->free(name);
e = 0; e = 0;
} break; } break;
} }
@ -548,10 +543,10 @@ parsePath(System* s, const char* path)
class MyFinder: public Finder { class MyFinder: public Finder {
public: public:
MyFinder(System* system, const char* path): MyFinder(System* system, const char* path, const char* bootLibrary):
system(system), system(system),
path_(parsePath(system, path)), path_(parsePath(system, path, bootLibrary)),
pathString(copy(system, &pathStringLength, path)) pathString(copy(system, path))
{ } { }
virtual System::Region* find(const char* name) { virtual System::Region* find(const char* name) {
@ -585,14 +580,13 @@ class MyFinder: public Finder {
e = e->next; e = e->next;
t->dispose(); t->dispose();
} }
free(system, pathString, pathStringLength + 1); system->free(pathString);
free(system, this, sizeof(*this)); system->free(this);
} }
System* system; System* system;
Element* path_; Element* path_;
const char* pathString; const char* pathString;
unsigned pathStringLength;
}; };
} // namespace } // namespace
@ -600,9 +594,9 @@ class MyFinder: public Finder {
namespace vm { namespace vm {
Finder* Finder*
makeFinder(System* s, const char* path) makeFinder(System* s, const char* path, const char* bootLibrary)
{ {
return new (allocate(s, sizeof(MyFinder))) MyFinder(s, path); return new (allocate(s, sizeof(MyFinder))) MyFinder(s, path, bootLibrary);
} }
} // namespace vm } // namespace vm

View File

@ -27,7 +27,7 @@ class Finder {
}; };
Finder* Finder*
makeFinder(System* s, const char* path); makeFinder(System* s, const char* path, const char* bootLibrary);
} // namespace vm } // namespace vm

View File

@ -58,8 +58,8 @@ void assert(Context*, bool);
#endif #endif
System* system(Context*); System* system(Context*);
void* tryAllocate(Context* c, unsigned size, bool executable); void* tryAllocate(Context* c, unsigned size);
void free(Context* c, const void* p, unsigned size, bool executable); void free(Context* c, const void* p, unsigned size);
inline void* inline void*
get(void* o, unsigned offsetInWords) get(void* o, unsigned offsetInWords)
@ -78,7 +78,7 @@ set(void** o, void* value)
{ {
*o = reinterpret_cast<void*> *o = reinterpret_cast<void*>
(reinterpret_cast<uintptr_t>(value) (reinterpret_cast<uintptr_t>(value)
| reinterpret_cast<uintptr_t>(*o) & (~PointerMask)); | (reinterpret_cast<uintptr_t>(*o) & (~PointerMask)));
} }
inline void inline void
@ -314,8 +314,7 @@ class Segment {
capacity_ = desired; capacity_ = desired;
while (data == 0) { while (data == 0) {
data = static_cast<uintptr_t*> data = static_cast<uintptr_t*>
(tryAllocate (tryAllocate(context, (footprint(capacity_)) * BytesPerWord));
(context, (footprint(capacity_)) * BytesPerWord, false));
if (data == 0) { if (data == 0) {
if (capacity_ > minimum) { if (capacity_ > minimum) {
@ -353,7 +352,7 @@ class Segment {
void replaceWith(Segment* s) { void replaceWith(Segment* s) {
if (data) { if (data) {
free(context, data, (footprint(capacity())) * BytesPerWord, false); free(context, data, (footprint(capacity())) * BytesPerWord);
} }
data = s->data; data = s->data;
s->data = 0; s->data = 0;
@ -404,7 +403,7 @@ class Segment {
} }
void dispose() { void dispose() {
free(context, data, (footprint(capacity())) * BytesPerWord, false); free(context, data, (footprint(capacity())) * BytesPerWord);
data = 0; data = 0;
map = 0; map = 0;
} }
@ -783,7 +782,7 @@ free(Context* c, Fixie** fixies)
if (DebugFixies) { if (DebugFixies) {
fprintf(stderr, "free fixie %p\n", f); fprintf(stderr, "free fixie %p\n", f);
} }
free(c, f, f->totalSize(), false); free(c, f, f->totalSize());
} }
} }
} }
@ -1628,12 +1627,12 @@ collect(Context* c)
} }
} }
void* tryAllocate(Context* c, unsigned size, bool executable) void* tryAllocate(Context* c, unsigned size)
{ {
ACQUIRE(c->lock); ACQUIRE(c->lock);
if (size + c->count < c->limit) { if (size + c->count < c->limit) {
void* p = c->system->tryAllocate(size, executable); void* p = c->system->tryAllocate(size);
if (p) { if (p) {
c->count += size; c->count += size;
return p; return p;
@ -1642,16 +1641,16 @@ void* tryAllocate(Context* c, unsigned size, bool executable)
return 0; return 0;
} }
void free(Context* c, const void* p, unsigned size, bool executable) { void free(Context* c, const void* p, unsigned size) {
ACQUIRE(c->lock); ACQUIRE(c->lock);
expect(c->system, c->count >= size); expect(c->system, c->count >= size);
c->system->free(p, size, executable); c->system->free(p);
c->count -= size; c->count -= size;
} }
void free_(Context* c, const void* p, unsigned size, bool executable) { void free_(Context* c, const void* p, unsigned size) {
free(c, p, size, executable); free(c, p, size);
} }
class MyHeap: public Heap { class MyHeap: public Heap {
@ -1665,18 +1664,18 @@ class MyHeap: public Heap {
c.client = client; c.client = client;
} }
virtual void* tryAllocate(unsigned size, bool executable) { virtual void* tryAllocate(unsigned size) {
return ::tryAllocate(&c, size, executable); return ::tryAllocate(&c, size);
} }
virtual void* allocate(unsigned size, bool executable) { virtual void* allocate(unsigned size) {
void* p = ::tryAllocate(&c, size, executable); void* p = ::tryAllocate(&c, size);
expect(c.system, p); expect(c.system, p);
return p; return p;
} }
virtual void free(const void* p, unsigned size, bool executable) { virtual void free(const void* p, unsigned size) {
free_(&c, p, size, executable); free_(&c, p, size);
} }
virtual void collect(CollectionType type, unsigned incomingFootprint) { virtual void collect(CollectionType type, unsigned incomingFootprint) {
@ -1690,16 +1689,15 @@ class MyHeap: public Heap {
bool objectMask, unsigned* totalInBytes) bool objectMask, unsigned* totalInBytes)
{ {
*totalInBytes = Fixie::totalSize(sizeInWords, objectMask); *totalInBytes = Fixie::totalSize(sizeInWords, objectMask);
return (new (allocator->allocate(*totalInBytes, false)) return (new (allocator->allocate(*totalInBytes))
Fixie(sizeInWords, objectMask, &(c.fixies), false))->body(); Fixie(sizeInWords, objectMask, &(c.fixies), false))->body();
} }
virtual void* allocateImmortal(Allocator* allocator, unsigned sizeInWords, virtual void* allocateImmortal(Allocator* allocator, unsigned sizeInWords,
bool executable, bool objectMask, bool objectMask, unsigned* totalInBytes)
unsigned* totalInBytes)
{ {
*totalInBytes = Fixie::totalSize(sizeInWords, objectMask); *totalInBytes = Fixie::totalSize(sizeInWords, objectMask);
return (new (allocator->allocate(*totalInBytes, executable)) return (new (allocator->allocate(*totalInBytes))
Fixie(sizeInWords, objectMask, &(c.tenuredFixies), true))->body(); Fixie(sizeInWords, objectMask, &(c.tenuredFixies), true))->body();
} }
@ -1809,7 +1807,7 @@ class MyHeap: public Heap {
virtual void dispose() { virtual void dispose() {
c.dispose(); c.dispose();
assert(&c, c.count == 0); assert(&c, c.count == 0);
c.system->free(this, sizeof(*this), false); c.system->free(this);
} }
Context c; Context c;
@ -1822,8 +1820,7 @@ namespace vm {
Heap* Heap*
makeHeap(System* system, unsigned limit) makeHeap(System* system, unsigned limit)
{ {
return new (system->tryAllocate(sizeof(MyHeap), false)) return new (system->tryAllocate(sizeof(MyHeap))) MyHeap(system, limit);
MyHeap(system, limit);
} }
} // namespace vm } // namespace vm

View File

@ -60,8 +60,7 @@ class Heap: public Allocator {
virtual void* allocateFixed(Allocator* allocator, unsigned sizeInWords, virtual void* allocateFixed(Allocator* allocator, unsigned sizeInWords,
bool objectMask, unsigned* totalInBytes) = 0; bool objectMask, unsigned* totalInBytes) = 0;
virtual void* allocateImmortal(Allocator* allocator, unsigned sizeInWords, virtual void* allocateImmortal(Allocator* allocator, unsigned sizeInWords,
bool executable, bool objectMask, bool objectMask, unsigned* totalInBytes) = 0;
unsigned* totalInBytes) = 0;
virtual bool needsMark(void* p) = 0; virtual bool needsMark(void* p) = 0;
virtual void mark(void* p, unsigned offset, unsigned count) = 0; virtual void mark(void* p, unsigned offset, unsigned count) = 0;
virtual void pad(void* p) = 0; virtual void pad(void* p) = 0;

View File

@ -704,6 +704,50 @@ store(Thread* t, unsigned index)
BytesPerWord * 2); BytesPerWord * 2);
} }
ExceptionHandler*
findExceptionHandler(Thread* t, object method, unsigned ip)
{
PROTECT(t, method);
object eht = codeExceptionHandlerTable(t, methodCode(t, method));
if (eht) {
for (unsigned i = 0; i < exceptionHandlerTableLength(t, eht); ++i) {
ExceptionHandler* eh = exceptionHandlerTableBody(t, eht, i);
if (ip - 1 >= exceptionHandlerStart(eh)
and ip - 1 < exceptionHandlerEnd(eh))
{
object catchType = 0;
if (exceptionHandlerCatchType(eh)) {
object e = t->exception;
t->exception = 0;
PROTECT(t, e);
PROTECT(t, eht);
catchType = resolveClassInPool
(t, codePool(t, methodCode(t, method)),
exceptionHandlerCatchType(eh) - 1);
if (catchType) {
eh = exceptionHandlerTableBody(t, eht, i);
t->exception = e;
} else {
// can't find what we're supposed to catch - move on.
continue;
}
}
if (catchType == 0 or instanceOf(t, catchType, t->exception)) {
return eh;
}
}
}
}
return 0;
}
ExceptionHandler* ExceptionHandler*
findExceptionHandler(Thread* t, int frame) findExceptionHandler(Thread* t, int frame)
{ {
@ -1942,6 +1986,14 @@ interpret(Thread* t)
ip = (ip - 5) + static_cast<int32_t>(offset); ip = (ip - 5) + static_cast<int32_t>(offset);
} goto loop; } goto loop;
case l2d: {
pushDouble(t, static_cast<double>(static_cast<int64_t>(popLong(t))));
} goto loop;
case l2f: {
pushFloat(t, static_cast<float>(static_cast<int64_t>(popLong(t))));
} goto loop;
case l2i: { case l2i: {
pushInt(t, static_cast<int32_t>(popLong(t))); pushInt(t, static_cast<int32_t>(popLong(t)));
} goto loop; } goto loop;
@ -2999,6 +3051,11 @@ class MyProcessor: public Processor {
} }
} }
virtual object getStackTrace(Thread*, Thread*) {
// not implemented
return 0;
}
virtual void dispose(vm::Thread* t) { virtual void dispose(vm::Thread* t) {
t->m->heap->free(t, sizeof(Thread), false); t->m->heap->free(t, sizeof(Thread), false);
} }

View File

@ -87,6 +87,35 @@ GetEnv(Machine* m, Thread** t, jint version)
} }
} }
jsize JNICALL
GetStringLength(Thread* t, jstring s)
{
ENTER(t, Thread::ActiveState);
return stringLength(t, *s);
}
const jchar* JNICALL
GetStringChars(Thread* t, jstring s, jboolean* isCopy)
{
ENTER(t, Thread::ActiveState);
jchar* chars = static_cast<jchar*>
(t->m->heap->allocate((stringLength(t, *s) + 1) * sizeof(jchar)));
stringChars(t, *s, chars);
if (isCopy) *isCopy = true;
return chars;
}
void JNICALL
ReleaseStringChars(Thread* t, jstring s, const jchar* chars)
{
ENTER(t, Thread::ActiveState);
t->m->heap->free(chars, (stringLength(t, *s) + 1) * sizeof(jchar));
}
jsize JNICALL jsize JNICALL
GetStringUTFLength(Thread* t, jstring s) GetStringUTFLength(Thread* t, jstring s)
{ {
@ -101,7 +130,7 @@ GetStringUTFChars(Thread* t, jstring s, jboolean* isCopy)
ENTER(t, Thread::ActiveState); ENTER(t, Thread::ActiveState);
char* chars = static_cast<char*> char* chars = static_cast<char*>
(t->m->heap->allocate(stringLength(t, *s) + 1, false)); (t->m->heap->allocate(stringLength(t, *s) + 1));
stringChars(t, *s, chars); stringChars(t, *s, chars);
if (isCopy) *isCopy = true; if (isCopy) *isCopy = true;
@ -111,7 +140,9 @@ GetStringUTFChars(Thread* t, jstring s, jboolean* isCopy)
void JNICALL void JNICALL
ReleaseStringUTFChars(Thread* t, jstring s, const char* chars) ReleaseStringUTFChars(Thread* t, jstring s, const char* chars)
{ {
t->m->heap->free(chars, stringLength(t, *s) + 1, false); ENTER(t, Thread::ActiveState);
t->m->heap->free(chars, stringLength(t, *s) + 1);
} }
jsize JNICALL jsize JNICALL
@ -232,15 +263,13 @@ IsInstanceOf(Thread* t, jobject o, jclass c)
} }
object object
findMethod(Thread* t, object c, const char* name, const char* spec) findMethod(Thread* t, jclass c, const char* name, const char* spec)
{ {
PROTECT(t, c);
object n = makeByteArray(t, "%s", name); object n = makeByteArray(t, "%s", name);
PROTECT(t, n); PROTECT(t, n);
object s = makeByteArray(t, "%s", spec); object s = makeByteArray(t, "%s", spec);
return vm::findMethod(t, c, n, s); return vm::findMethod(t, *c, n, s);
} }
jmethodID JNICALL jmethodID JNICALL
@ -248,7 +277,7 @@ GetMethodID(Thread* t, jclass c, const char* name, const char* spec)
{ {
ENTER(t, Thread::ActiveState); ENTER(t, Thread::ActiveState);
object method = findMethod(t, *c, name, spec); object method = findMethod(t, c, name, spec);
if (UNLIKELY(t->exception)) return 0; if (UNLIKELY(t->exception)) return 0;
if (classFlags(t, *c) & ACC_INTERFACE) { if (classFlags(t, *c) & ACC_INTERFACE) {
@ -278,7 +307,7 @@ GetStaticMethodID(Thread* t, jclass c, const char* name, const char* spec)
{ {
ENTER(t, Thread::ActiveState); ENTER(t, Thread::ActiveState);
object method = findMethod(t, *c, name, spec); object method = findMethod(t, c, name, spec);
if (UNLIKELY(t->exception)) return 0; if (UNLIKELY(t->exception)) return 0;
return methodOffset(t, method) + 1; return methodOffset(t, method) + 1;
@ -289,11 +318,20 @@ getMethod(Thread* t, object o, jmethodID m)
{ {
if (m & InterfaceMethodID) { if (m & InterfaceMethodID) {
return vectorBody(t, t->m->jniInterfaceTable, m & (~InterfaceMethodID)); return vectorBody(t, t->m->jniInterfaceTable, m & (~InterfaceMethodID));
} else if (m & NonVirtualMethodID) {
return arrayBody(t, classMethodTable(t, objectClass(t, o)),
m & (~NonVirtualMethodID));
} else { } else {
return arrayBody(t, classVirtualTable(t, objectClass(t, o)), m - 1); if (classVmFlags(t, objectClass(t, o)) & BootstrapFlag) {
PROTECT(t, o);
resolveClass(t, className(t, objectClass(t, o)));
if (UNLIKELY(t->exception)) return 0;
}
if (m & NonVirtualMethodID) {
return arrayBody(t, classMethodTable(t, objectClass(t, o)),
m & (~NonVirtualMethodID));
} else {
return arrayBody(t, classVirtualTable(t, objectClass(t, o)), m - 1);
}
} }
} }
@ -328,8 +366,9 @@ CallObjectMethodV(Thread* t, jobject o, jmethodID m, va_list a)
{ {
ENTER(t, Thread::ActiveState); ENTER(t, Thread::ActiveState);
return makeLocalReference(t, t->m->processor->invokeList object method = getMethod(t, *o, m);
(t, getMethod(t, *o, m), *o, true, a)); return makeLocalReference
(t, t->m->processor->invokeList(t, method, *o, true, a));
} }
jobject JNICALL jobject JNICALL
@ -350,7 +389,8 @@ CallBooleanMethodV(Thread* t, jobject o, jmethodID m, va_list a)
{ {
ENTER(t, Thread::ActiveState); ENTER(t, Thread::ActiveState);
object r = t->m->processor->invokeList(t, getMethod(t, *o, m), *o, true, a); object method = getMethod(t, *o, m);
object r = t->m->processor->invokeList(t, method, *o, true, a);
return (t->exception ? false : (intValue(t, r) != 0)); return (t->exception ? false : (intValue(t, r) != 0));
} }
@ -372,7 +412,8 @@ CallByteMethodV(Thread* t, jobject o, jmethodID m, va_list a)
{ {
ENTER(t, Thread::ActiveState); ENTER(t, Thread::ActiveState);
object r = t->m->processor->invokeList(t, getMethod(t, *o, m), *o, true, a); object method = getMethod(t, *o, m);
object r = t->m->processor->invokeList(t, method, *o, true, a);
return (t->exception ? 0 : intValue(t, r)); return (t->exception ? 0 : intValue(t, r));
} }
@ -394,7 +435,8 @@ CallCharMethodV(Thread* t, jobject o, jmethodID m, va_list a)
{ {
ENTER(t, Thread::ActiveState); ENTER(t, Thread::ActiveState);
object r = t->m->processor->invokeList(t, getMethod(t, *o, m), *o, true, a); object method = getMethod(t, *o, m);
object r = t->m->processor->invokeList(t, method, *o, true, a);
return (t->exception ? 0 : intValue(t, r)); return (t->exception ? 0 : intValue(t, r));
} }
@ -416,7 +458,8 @@ CallShortMethodV(Thread* t, jobject o, jmethodID m, va_list a)
{ {
ENTER(t, Thread::ActiveState); ENTER(t, Thread::ActiveState);
object r = t->m->processor->invokeList(t, getMethod(t, *o, m), *o, true, a); object method = getMethod(t, *o, m);
object r = t->m->processor->invokeList(t, method, *o, true, a);
return (t->exception ? 0 : intValue(t, r)); return (t->exception ? 0 : intValue(t, r));
} }
@ -438,7 +481,8 @@ CallIntMethodV(Thread* t, jobject o, jmethodID m, va_list a)
{ {
ENTER(t, Thread::ActiveState); ENTER(t, Thread::ActiveState);
object r = t->m->processor->invokeList(t, getMethod(t, *o, m), *o, true, a); object method = getMethod(t, *o, m);
object r = t->m->processor->invokeList(t, method, *o, true, a);
return (t->exception ? 0 : intValue(t, r)); return (t->exception ? 0 : intValue(t, r));
} }
@ -460,7 +504,8 @@ CallLongMethodV(Thread* t, jobject o, jmethodID m, va_list a)
{ {
ENTER(t, Thread::ActiveState); ENTER(t, Thread::ActiveState);
object r = t->m->processor->invokeList(t, getMethod(t, *o, m), *o, true, a); object method = getMethod(t, *o, m);
object r = t->m->processor->invokeList(t, method, *o, true, a);
return (t->exception ? 0 : longValue(t, r)); return (t->exception ? 0 : longValue(t, r));
} }
@ -482,7 +527,8 @@ CallFloatMethodV(Thread* t, jobject o, jmethodID m, va_list a)
{ {
ENTER(t, Thread::ActiveState); ENTER(t, Thread::ActiveState);
object r = t->m->processor->invokeList(t, getMethod(t, *o, m), *o, true, a); object method = getMethod(t, *o, m);
object r = t->m->processor->invokeList(t, method, *o, true, a);
return (t->exception ? 0 : bitsToFloat(intValue(t, r))); return (t->exception ? 0 : bitsToFloat(intValue(t, r)));
} }
@ -504,7 +550,8 @@ CallDoubleMethodV(Thread* t, jobject o, jmethodID m, va_list a)
{ {
ENTER(t, Thread::ActiveState); ENTER(t, Thread::ActiveState);
object r = t->m->processor->invokeList(t, getMethod(t, *o, m), *o, true, a); object method = getMethod(t, *o, m);
object r = t->m->processor->invokeList(t, method, *o, true, a);
return (t->exception ? 0 : bitsToDouble(longValue(t, r))); return (t->exception ? 0 : bitsToDouble(longValue(t, r)));
} }
@ -526,7 +573,8 @@ CallVoidMethodV(Thread* t, jobject o, jmethodID m, va_list a)
{ {
ENTER(t, Thread::ActiveState); ENTER(t, Thread::ActiveState);
t->m->processor->invokeList(t, getMethod(t, *o, m), *o, true, a); object method = getMethod(t, *o, m);
t->m->processor->invokeList(t, method, *o, true, a);
} }
void JNICALL void JNICALL
@ -541,9 +589,16 @@ CallVoidMethod(Thread* t, jobject o, jmethodID m, ...)
} }
inline object inline object
getStaticMethod(Thread* t, object class_, jmethodID m) getStaticMethod(Thread* t, object c, jmethodID m)
{ {
return arrayBody(t, classMethodTable(t, class_), m - 1); if (classVmFlags(t, c) & BootstrapFlag) {
PROTECT(t, c);
resolveClass(t, className(t, c));
if (UNLIKELY(t->exception)) return 0;
}
return arrayBody(t, classMethodTable(t, c), m - 1);
} }
jobject JNICALL jobject JNICALL
@ -772,13 +827,13 @@ CallStaticVoidMethod(Thread* t, jclass c, jmethodID m, ...)
} }
object object
findField(Thread* t, object class_, const char* name, const char* spec) findField(Thread* t, jclass c, const char* name, const char* spec)
{ {
object n = makeByteArray(t, "%s", name); object n = makeByteArray(t, "%s", name);
PROTECT(t, n); PROTECT(t, n);
object s = makeByteArray(t, "%s", spec); object s = makeByteArray(t, "%s", spec);
return vm::findField(t, class_, n, s); return vm::findField(t, *c, n, s);
} }
jfieldID JNICALL jfieldID JNICALL
@ -786,7 +841,7 @@ 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 = findField(t, c, name, spec);
if (UNLIKELY(t->exception)) return 0; if (UNLIKELY(t->exception)) return 0;
return fieldOffset(t, field); return fieldOffset(t, field);
@ -797,7 +852,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 = findField(t, c, name, spec);
if (UNLIKELY(t->exception)) return 0; if (UNLIKELY(t->exception)) return 0;
return fieldOffset(t, field); return fieldOffset(t, field);
@ -1122,7 +1177,7 @@ NewGlobalRef(Thread* t, jobject o)
ACQUIRE(t, t->m->referenceLock); ACQUIRE(t, t->m->referenceLock);
if (o) { if (o) {
Reference* r = new (t->m->heap->allocate(sizeof(Reference), false)) Reference* r = new (t->m->heap->allocate(sizeof(Reference)))
Reference(*o, &(t->m->jniReferences)); Reference(*o, &(t->m->jniReferences));
return &(r->target); return &(r->target);
@ -1267,7 +1322,7 @@ GetBooleanArrayElements(Thread* t, jbooleanArray array, jboolean* isCopy)
ENTER(t, Thread::ActiveState); ENTER(t, Thread::ActiveState);
unsigned size = booleanArrayLength(t, *array) * sizeof(jboolean); unsigned size = booleanArrayLength(t, *array) * sizeof(jboolean);
jboolean* p = static_cast<jboolean*>(t->m->heap->allocate(size, false)); jboolean* p = static_cast<jboolean*>(t->m->heap->allocate(size));
if (size) { if (size) {
memcpy(p, &booleanArrayBody(t, *array, 0), size); memcpy(p, &booleanArrayBody(t, *array, 0), size);
} }
@ -1285,7 +1340,7 @@ GetByteArrayElements(Thread* t, jbyteArray array, jboolean* isCopy)
ENTER(t, Thread::ActiveState); ENTER(t, Thread::ActiveState);
unsigned size = byteArrayLength(t, *array) * sizeof(jbyte); unsigned size = byteArrayLength(t, *array) * sizeof(jbyte);
jbyte* p = static_cast<jbyte*>(t->m->heap->allocate(size, false)); jbyte* p = static_cast<jbyte*>(t->m->heap->allocate(size));
if (size) { if (size) {
memcpy(p, &byteArrayBody(t, *array, 0), size); memcpy(p, &byteArrayBody(t, *array, 0), size);
} }
@ -1303,7 +1358,7 @@ GetCharArrayElements(Thread* t, jcharArray array, jboolean* isCopy)
ENTER(t, Thread::ActiveState); ENTER(t, Thread::ActiveState);
unsigned size = charArrayLength(t, *array) * sizeof(jchar); unsigned size = charArrayLength(t, *array) * sizeof(jchar);
jchar* p = static_cast<jchar*>(t->m->heap->allocate(size, false)); jchar* p = static_cast<jchar*>(t->m->heap->allocate(size));
if (size) { if (size) {
memcpy(p, &charArrayBody(t, *array, 0), size); memcpy(p, &charArrayBody(t, *array, 0), size);
} }
@ -1321,7 +1376,7 @@ GetShortArrayElements(Thread* t, jshortArray array, jboolean* isCopy)
ENTER(t, Thread::ActiveState); ENTER(t, Thread::ActiveState);
unsigned size = shortArrayLength(t, *array) * sizeof(jshort); unsigned size = shortArrayLength(t, *array) * sizeof(jshort);
jshort* p = static_cast<jshort*>(t->m->heap->allocate(size, false)); jshort* p = static_cast<jshort*>(t->m->heap->allocate(size));
if (size) { if (size) {
memcpy(p, &shortArrayBody(t, *array, 0), size); memcpy(p, &shortArrayBody(t, *array, 0), size);
} }
@ -1339,7 +1394,7 @@ GetIntArrayElements(Thread* t, jintArray array, jboolean* isCopy)
ENTER(t, Thread::ActiveState); ENTER(t, Thread::ActiveState);
unsigned size = intArrayLength(t, *array) * sizeof(jint); unsigned size = intArrayLength(t, *array) * sizeof(jint);
jint* p = static_cast<jint*>(t->m->heap->allocate(size, false)); jint* p = static_cast<jint*>(t->m->heap->allocate(size));
if (size) { if (size) {
memcpy(p, &intArrayBody(t, *array, 0), size); memcpy(p, &intArrayBody(t, *array, 0), size);
} }
@ -1357,7 +1412,7 @@ GetLongArrayElements(Thread* t, jlongArray array, jboolean* isCopy)
ENTER(t, Thread::ActiveState); ENTER(t, Thread::ActiveState);
unsigned size = longArrayLength(t, *array) * sizeof(jlong); unsigned size = longArrayLength(t, *array) * sizeof(jlong);
jlong* p = static_cast<jlong*>(t->m->heap->allocate(size, false)); jlong* p = static_cast<jlong*>(t->m->heap->allocate(size));
if (size) { if (size) {
memcpy(p, &longArrayBody(t, *array, 0), size); memcpy(p, &longArrayBody(t, *array, 0), size);
} }
@ -1375,7 +1430,7 @@ GetFloatArrayElements(Thread* t, jfloatArray array, jboolean* isCopy)
ENTER(t, Thread::ActiveState); ENTER(t, Thread::ActiveState);
unsigned size = floatArrayLength(t, *array) * sizeof(jfloat); unsigned size = floatArrayLength(t, *array) * sizeof(jfloat);
jfloat* p = static_cast<jfloat*>(t->m->heap->allocate(size, false)); jfloat* p = static_cast<jfloat*>(t->m->heap->allocate(size));
if (size) { if (size) {
memcpy(p, &floatArrayBody(t, *array, 0), size); memcpy(p, &floatArrayBody(t, *array, 0), size);
} }
@ -1393,7 +1448,7 @@ GetDoubleArrayElements(Thread* t, jdoubleArray array, jboolean* isCopy)
ENTER(t, Thread::ActiveState); ENTER(t, Thread::ActiveState);
unsigned size = doubleArrayLength(t, *array) * sizeof(jdouble); unsigned size = doubleArrayLength(t, *array) * sizeof(jdouble);
jdouble* p = static_cast<jdouble*>(t->m->heap->allocate(size, false)); jdouble* p = static_cast<jdouble*>(t->m->heap->allocate(size));
if (size) { if (size) {
memcpy(p, &doubleArrayBody(t, *array, 0), size); memcpy(p, &doubleArrayBody(t, *array, 0), size);
} }
@ -1420,7 +1475,7 @@ ReleaseBooleanArrayElements(Thread* t, jbooleanArray array, jboolean* p,
} }
if (mode == 0 or mode == JNI_ABORT) { if (mode == 0 or mode == JNI_ABORT) {
t->m->heap->free(p, size, false); t->m->heap->free(p, size);
} }
} }
@ -1438,7 +1493,7 @@ ReleaseByteArrayElements(Thread* t, jbyteArray array, jbyte* p, jint mode)
} }
if (mode == 0 or mode == JNI_ABORT) { if (mode == 0 or mode == JNI_ABORT) {
t->m->heap->free(p, size, false); t->m->heap->free(p, size);
} }
} }
@ -1456,7 +1511,7 @@ ReleaseCharArrayElements(Thread* t, jcharArray array, jchar* p, jint mode)
} }
if (mode == 0 or mode == JNI_ABORT) { if (mode == 0 or mode == JNI_ABORT) {
t->m->heap->free(p, size, false); t->m->heap->free(p, size);
} }
} }
@ -1474,7 +1529,7 @@ ReleaseShortArrayElements(Thread* t, jshortArray array, jshort* p, jint mode)
} }
if (mode == 0 or mode == JNI_ABORT) { if (mode == 0 or mode == JNI_ABORT) {
t->m->heap->free(p, size, false); t->m->heap->free(p, size);
} }
} }
@ -1492,7 +1547,7 @@ ReleaseIntArrayElements(Thread* t, jintArray array, jint* p, jint mode)
} }
if (mode == 0 or mode == JNI_ABORT) { if (mode == 0 or mode == JNI_ABORT) {
t->m->heap->free(p, size, false); t->m->heap->free(p, size);
} }
} }
@ -1510,7 +1565,7 @@ ReleaseLongArrayElements(Thread* t, jlongArray array, jlong* p, jint mode)
} }
if (mode == 0 or mode == JNI_ABORT) { if (mode == 0 or mode == JNI_ABORT) {
t->m->heap->free(p, size, false); t->m->heap->free(p, size);
} }
} }
@ -1528,7 +1583,7 @@ ReleaseFloatArrayElements(Thread* t, jfloatArray array, jfloat* p, jint mode)
} }
if (mode == 0 or mode == JNI_ABORT) { if (mode == 0 or mode == JNI_ABORT) {
t->m->heap->free(p, size, false); t->m->heap->free(p, size);
} }
} }
@ -1547,7 +1602,7 @@ ReleaseDoubleArrayElements(Thread* t, jdoubleArray array, jdouble* p,
} }
if (mode == 0 or mode == JNI_ABORT) { if (mode == 0 or mode == JNI_ABORT) {
t->m->heap->free(p, size, false); t->m->heap->free(p, size);
} }
} }
@ -1781,9 +1836,13 @@ GetJavaVM(Thread* t, Machine** m)
jboolean JNICALL jboolean JNICALL
IsSameObject(Thread* t, jobject a, jobject b) IsSameObject(Thread* t, jobject a, jobject b)
{ {
ENTER(t, Thread::ActiveState); if (a and b) {
ENTER(t, Thread::ActiveState);
return *a == *b; return *a == *b;
} else {
return a == b;
}
} }
struct JDK1_1InitArgs { struct JDK1_1InitArgs {
@ -1826,6 +1885,9 @@ populateJNITables(JavaVMVTable* vmTable, JNIEnvVTable* envTable)
memset(envTable, 0, sizeof(JNIEnvVTable)); memset(envTable, 0, sizeof(JNIEnvVTable));
envTable->GetStringLength = ::GetStringLength;
envTable->GetStringChars = ::GetStringChars;
envTable->ReleaseStringChars = ::ReleaseStringChars;
envTable->GetStringUTFLength = ::GetStringUTFLength; envTable->GetStringUTFLength = ::GetStringUTFLength;
envTable->GetStringUTFChars = ::GetStringUTFChars; envTable->GetStringUTFChars = ::GetStringUTFChars;
envTable->ReleaseStringUTFChars = ::ReleaseStringUTFChars; envTable->ReleaseStringUTFChars = ::ReleaseStringUTFChars;
@ -1988,28 +2050,38 @@ JNI_GetDefaultJavaVMInitArgs(void* args)
return 0; return 0;
} }
#define BUILTINS_PROPERTY "vm.builtins" #define BUILTINS_PROPERTY "avian.builtins"
#define BOOTSTRAP_PROPERTY "avian.bootstrap"
extern "C" JNIEXPORT jint JNICALL extern "C" JNIEXPORT jint JNICALL
JNI_CreateJavaVM(Machine** m, Thread** t, void* args) JNI_CreateJavaVM(Machine** m, Thread** t, void* args)
{ {
JDK1_1InitArgs* a = static_cast<JDK1_1InitArgs*>(args); JDK1_1InitArgs* a = static_cast<JDK1_1InitArgs*>(args);
System* s = makeSystem(); const char* builtins = 0;
Heap* h = makeHeap(s, a->maxHeapSize); const char* bootLibrary = 0;
Finder* f = makeFinder(s, a->classpath);
Processor* p = makeProcessor(s, h);
*m = new (h->allocate(sizeof(Machine), false)) Machine(s, h, f, p);
if (a->properties) { if (a->properties) {
for (const char** p = a->properties; *p; ++p) { for (const char** p = a->properties; *p; ++p) {
if (strncmp(*p, BUILTINS_PROPERTY "=", sizeof(BUILTINS_PROPERTY)) == 0) { if (strncmp(*p, BUILTINS_PROPERTY "=",
(*m)->builtins = (*p) + sizeof(BUILTINS_PROPERTY); sizeof(BUILTINS_PROPERTY)) == 0)
{
builtins = (*p) + sizeof(BUILTINS_PROPERTY);
} else if (strncmp(*p, BOOTSTRAP_PROPERTY "=",
sizeof(BOOTSTRAP_PROPERTY)) == 0)
{
bootLibrary = (*p) + sizeof(BOOTSTRAP_PROPERTY);
} }
} }
} }
System* s = makeSystem();
Heap* h = makeHeap(s, a->maxHeapSize);
Finder* f = makeFinder(s, a->classpath, bootLibrary);
Processor* p = makeProcessor(s, h);
*m = new (h->allocate(sizeof(Machine)))
Machine(s, h, f, p, bootLibrary, builtins);
*t = p->makeThread(*m, 0, 0); *t = p->makeThread(*m, 0, 0);
enter(*t, Thread::ActiveState); enter(*t, Thread::ActiveState);

View File

@ -22,15 +22,9 @@ namespace {
bool bool
find(Thread* t, Thread* o) find(Thread* t, Thread* o)
{ {
if (t == o) return true; return (t == o)
or (t->peer and find(t->peer, o))
for (Thread* p = t->peer; p; p = p->peer) { or (t->child and find(t->child, o));
if (p == o) return true;
}
if (t->child) return find(t->child, o);
return false;
} }
void void
@ -48,11 +42,7 @@ count(Thread* t, Thread* o)
unsigned c = 0; unsigned c = 0;
if (t != o) ++ c; if (t != o) ++ c;
if (t->peer) c += count(t->peer, o);
for (Thread* p = t->peer; p; p = p->peer) {
c += count(p, o);
}
if (t->child) c += count(t->child, o); if (t->child) c += count(t->child, o);
return c; return c;
@ -62,12 +52,8 @@ Thread**
fill(Thread* t, Thread* o, Thread** array) fill(Thread* t, Thread* o, Thread** array)
{ {
if (t != o) *(array++) = t; if (t != o) *(array++) = t;
if (t->peer) fill(t->peer, o, array);
for (Thread* p = t->peer; p; p = p->peer) { if (t->child) fill(t->child, o, array);
array = fill(p, o, array);
}
if (t->child) array = fill(t->child, o, array);
return array; return array;
} }
@ -492,15 +478,22 @@ void
postCollect(Thread* t) postCollect(Thread* t)
{ {
#ifdef VM_STRESS #ifdef VM_STRESS
t->m->heap->free(t->defaultHeap, Thread::HeapSizeInBytes, false); t->m->heap->free(t->defaultHeap, Thread::HeapSizeInBytes);
t->defaultHeap = static_cast<uintptr_t*> t->defaultHeap = static_cast<uintptr_t*>
(t->m->heap->allocate(Thread::HeapSizeInBytes, false)); (t->m->heap->allocate(Thread::HeapSizeInBytes));
#endif #endif
t->heap = t->defaultHeap; t->heap = t->defaultHeap;
t->heapOffset = 0; t->heapOffset = 0;
t->heapIndex = 0; t->heapIndex = 0;
if (t->backupHeap) {
t->m->heap->free
(t->backupHeap, t->backupHeapSizeInWords * BytesPerWord);
t->backupHeapIndex = 0;
t->backupHeapSizeInWords = 0;
}
for (Thread* c = t->child; c; c = c->peer) { for (Thread* c = t->child; c; c = c->peer) {
postCollect(c); postCollect(c);
} }
@ -660,8 +653,7 @@ parsePool(Thread* t, Stream& s)
PROTECT(t, pool); PROTECT(t, pool);
if (count) { if (count) {
uint32_t* index = static_cast<uint32_t*> uint32_t* index = static_cast<uint32_t*>(t->m->heap->allocate(count * 4));
(t->m->heap->allocate(count * 4, false));
for (unsigned i = 0; i < count; ++i) { for (unsigned i = 0; i < count; ++i) {
index[i] = s.position(); index[i] = s.position();
@ -707,7 +699,7 @@ parsePool(Thread* t, Stream& s)
i += parsePoolEntry(t, s, index, pool, i); i += parsePoolEntry(t, s, index, pool, i);
} }
t->m->heap->free(index, count * 4, false); t->m->heap->free(index, count * 4);
s.setPosition(end); s.setPosition(end);
} }
@ -861,7 +853,7 @@ parseFieldTable(Thread* t, Stream& s, object class_, object pool)
if (flags & ACC_STATIC) { if (flags & ACC_STATIC) {
unsigned size = fieldSize(t, code); unsigned size = fieldSize(t, code);
unsigned excess = staticOffset % size; unsigned excess = (staticOffset % size) % BytesPerWord;
if (excess) { if (excess) {
staticOffset += BytesPerWord - excess; staticOffset += BytesPerWord - excess;
} }
@ -878,7 +870,7 @@ parseFieldTable(Thread* t, Stream& s, object class_, object pool)
abort(t); // todo: handle non-static field initializers abort(t); // todo: handle non-static field initializers
} }
unsigned excess = memberOffset % fieldSize(t, code); unsigned excess = (memberOffset % fieldSize(t, code)) % BytesPerWord;
if (excess) { if (excess) {
memberOffset += BytesPerWord - excess; memberOffset += BytesPerWord - excess;
} }
@ -1294,7 +1286,9 @@ parseMethodTable(Thread* t, Stream& s, object class_, object pool)
object method = arrayBody(t, ivtable, j); object method = arrayBody(t, ivtable, j);
method = hashMapFind method = hashMapFind
(t, virtualMap, method, methodHash, methodEqual); (t, virtualMap, method, methodHash, methodEqual);
assert(t, method);
// note that method may be null in the case of an abstract
// class
set(t, vtable, ArrayBody + (j * BytesPerWord), method); set(t, vtable, ArrayBody + (j * BytesPerWord), method);
} }
@ -1630,7 +1624,7 @@ class HeapClient: public Heap::Client {
} }
void dispose() { void dispose() {
m->heap->free(this, sizeof(*this), false); m->heap->free(this, sizeof(*this));
} }
private: private:
@ -1642,10 +1636,11 @@ class HeapClient: public Heap::Client {
namespace vm { namespace vm {
Machine::Machine(System* system, Heap* heap, Finder* finder, Machine::Machine(System* system, Heap* heap, Finder* finder,
Processor* processor): Processor* processor, const char* bootLibrary,
const char* builtins):
vtable(&javaVMVTable), vtable(&javaVMVTable),
system(system), system(system),
heapClient(new (heap->allocate(sizeof(HeapClient), false)) heapClient(new (heap->allocate(sizeof(HeapClient)))
HeapClient(this)), HeapClient(this)),
heap(heap), heap(heap),
finder(finder), finder(finder),
@ -1653,7 +1648,7 @@ Machine::Machine(System* system, Heap* heap, Finder* finder,
rootThread(0), rootThread(0),
exclusive(0), exclusive(0),
jniReferences(0), jniReferences(0),
builtins(0), builtins(builtins),
activeCount(0), activeCount(0),
liveCount(0), liveCount(0),
fixedFootprint(0), fixedFootprint(0),
@ -1686,7 +1681,7 @@ Machine::Machine(System* system, Heap* heap, Finder* finder,
not system->success(system->make(&heapLock)) or not system->success(system->make(&heapLock)) or
not system->success(system->make(&classLock)) or not system->success(system->make(&classLock)) or
not system->success(system->make(&referenceLock)) or not system->success(system->make(&referenceLock)) or
not system->success(system->load(&libraries, 0, false))) not system->success(system->load(&libraries, bootLibrary, false)))
{ {
system->abort(); system->abort();
} }
@ -1708,16 +1703,16 @@ Machine::dispose()
for (Reference* r = jniReferences; r;) { for (Reference* r = jniReferences; r;) {
Reference* tmp = r; Reference* tmp = r;
r = r->next; r = r->next;
heap->free(tmp, sizeof(*tmp), false); heap->free(tmp, sizeof(*tmp));
} }
for (unsigned i = 0; i < heapPoolIndex; ++i) { for (unsigned i = 0; i < heapPoolIndex; ++i) {
heap->free(heapPool[i], Thread::HeapSizeInBytes, false); heap->free(heapPool[i], Thread::HeapSizeInBytes);
} }
static_cast<HeapClient*>(heapClient)->dispose(); static_cast<HeapClient*>(heapClient)->dispose();
heap->free(this, sizeof(*this), false); heap->free(this, sizeof(*this));
} }
Thread::Thread(Machine* m, object javaThread, Thread* parent): Thread::Thread(Machine* m, object javaThread, Thread* parent):
@ -1736,8 +1731,11 @@ Thread::Thread(Machine* m, object javaThread, Thread* parent):
protector(0), protector(0),
runnable(this), runnable(this),
defaultHeap(static_cast<uintptr_t*> defaultHeap(static_cast<uintptr_t*>
(m->heap->allocate(HeapSizeInBytes, false))), (m->heap->allocate(HeapSizeInBytes))),
heap(defaultHeap) heap(defaultHeap),
backupHeap(0),
backupHeapIndex(0),
backupHeapSizeInWords(0)
#ifdef VM_STRESS #ifdef VM_STRESS
, stress(false) , stress(false)
#endif // VM_STRESS #endif // VM_STRESS
@ -1873,7 +1871,7 @@ Thread::dispose()
systemThread->dispose(); systemThread->dispose();
} }
m->heap->free(defaultHeap, Thread::HeapSizeInBytes, false); m->heap->free(defaultHeap, Thread::HeapSizeInBytes);
m->processor->dispose(this); m->processor->dispose(this);
} }
@ -2033,13 +2031,23 @@ allocate2(Thread* t, unsigned sizeInBytes, bool objectMask)
(t, t->m->heap, (t, t->m->heap,
ceiling(sizeInBytes, BytesPerWord) > Thread::HeapSizeInWords ? ceiling(sizeInBytes, BytesPerWord) > Thread::HeapSizeInWords ?
Machine::FixedAllocation : Machine::MovableAllocation, Machine::FixedAllocation : Machine::MovableAllocation,
sizeInBytes, false, objectMask); sizeInBytes, objectMask);
} }
object object
allocate3(Thread* t, Allocator* allocator, Machine::AllocationType type, allocate3(Thread* t, Allocator* allocator, Machine::AllocationType type,
unsigned sizeInBytes, bool executable, bool objectMask) unsigned sizeInBytes, bool objectMask)
{ {
if (t->backupHeap) {
expect(t, t->backupHeapIndex + ceiling(sizeInBytes, BytesPerWord)
<= t->backupHeapSizeInWords);
object o = reinterpret_cast<object>(t->backupHeap + t->backupHeapIndex);
t->backupHeapIndex += ceiling(sizeInBytes, BytesPerWord);
cast<object>(o, 0) = 0;
return o;
}
ACQUIRE_RAW(t, t->m->stateLock); ACQUIRE_RAW(t, t->m->stateLock);
while (t->m->exclusive and t->m->exclusive != t) { while (t->m->exclusive and t->m->exclusive != t) {
@ -2055,12 +2063,12 @@ allocate3(Thread* t, Allocator* allocator, Machine::AllocationType type,
t->heap = 0; t->heap = 0;
} }
} else if (t->heapIndex + ceiling(sizeInBytes, BytesPerWord) } else if (t->heapIndex + ceiling(sizeInBytes, BytesPerWord)
>= Thread::HeapSizeInWords) > Thread::HeapSizeInWords)
{ {
t->heap = 0; t->heap = 0;
if (t->m->heapPoolIndex < Machine::HeapPoolSize) { if (t->m->heapPoolIndex < Machine::HeapPoolSize) {
t->heap = static_cast<uintptr_t*> t->heap = static_cast<uintptr_t*>
(t->m->heap->tryAllocate(Thread::HeapSizeInBytes, false)); (t->m->heap->tryAllocate(Thread::HeapSizeInBytes));
if (t->heap) { if (t->heap) {
t->m->heapPool[t->m->heapPoolIndex++] = t->heap; t->m->heapPool[t->m->heapPoolIndex++] = t->heap;
t->heapOffset += t->heapIndex; t->heapOffset += t->heapIndex;
@ -2098,8 +2106,7 @@ allocate3(Thread* t, Allocator* allocator, Machine::AllocationType type,
unsigned total; unsigned total;
object o = static_cast<object> object o = static_cast<object>
(t->m->heap->allocateImmortal (t->m->heap->allocateImmortal
(allocator, ceiling(sizeInBytes, BytesPerWord), (allocator, ceiling(sizeInBytes, BytesPerWord), objectMask, &total));
executable, objectMask, &total));
cast<uintptr_t>(o, 0) = FixedMark; cast<uintptr_t>(o, 0) = FixedMark;
@ -2150,6 +2157,24 @@ stringChars(Thread* t, object string, char* chars)
chars[stringLength(t, string)] = 0; chars[stringLength(t, string)] = 0;
} }
void
stringChars(Thread* t, object string, uint16_t* chars)
{
object data = stringData(t, string);
if (objectClass(t, data)
== arrayBody(t, t->m->types, Machine::ByteArrayType))
{
for (unsigned i = 0; i < stringLength(t, string); ++i) {
chars[i] = byteArrayBody(t, data, stringOffset(t, string) + i);
}
} else {
memcpy(chars,
&charArrayBody(t, data, stringOffset(t, string)),
stringLength(t, string) * sizeof(uint16_t));
}
chars[stringLength(t, string)] = 0;
}
bool bool
isAssignableFrom(Thread* t, object a, object b) isAssignableFrom(Thread* t, object a, object b)
{ {
@ -2727,7 +2752,7 @@ collect(Thread* t, Heap::CollectionType type)
killZombies(t, m->rootThread); killZombies(t, m->rootThread);
for (unsigned i = 0; i < m->heapPoolIndex; ++i) { for (unsigned i = 0; i < m->heapPoolIndex; ++i) {
m->heap->free(m->heapPool[i], Thread::HeapSizeInBytes, false); m->heap->free(m->heapPool[i], Thread::HeapSizeInBytes);
} }
m->heapPoolIndex = 0; m->heapPoolIndex = 0;
@ -2818,7 +2843,7 @@ makeTrace(Thread* t, Processor::StackWalker* walker)
} }
object object
makeTrace(Thread* t) makeTrace(Thread* t, Thread* target)
{ {
class Visitor: public Processor::StackVisitor { class Visitor: public Processor::StackVisitor {
public: public:
@ -2833,7 +2858,7 @@ makeTrace(Thread* t)
object trace; object trace;
} v(t); } v(t);
t->m->processor->walkStack(t, &v); t->m->processor->walkStack(target, &v);
return v.trace ? v.trace : makeArray(t, 0, true); return v.trace ? v.trace : makeArray(t, 0, true);
} }

View File

@ -1121,7 +1121,8 @@ class Machine {
ImmortalAllocation ImmortalAllocation
}; };
Machine(System* system, Heap* heap, Finder* finder, Processor* processor); Machine(System* system, Heap* heap, Finder* finder, Processor* processor,
const char* bootLibrary, const char* builtins);
~Machine() { ~Machine() {
dispose(); dispose();
@ -1287,6 +1288,9 @@ class Thread {
Runnable runnable; Runnable runnable;
uintptr_t* defaultHeap; uintptr_t* defaultHeap;
uintptr_t* heap; uintptr_t* heap;
uintptr_t* backupHeap;
unsigned backupHeapIndex;
unsigned backupHeapSizeInWords;
#ifdef VM_STRESS #ifdef VM_STRESS
bool stress; bool stress;
#endif // VM_STRESS #endif // VM_STRESS
@ -1327,7 +1331,7 @@ dispose(Thread* t, Reference* r)
if (r->next) { if (r->next) {
r->next->handle = r->handle; r->next->handle = r->handle;
} }
t->m->heap->free(r, sizeof(*r), false); t->m->heap->free(r, sizeof(*r));
} }
void void
@ -1425,12 +1429,26 @@ expect(Thread* t, bool v)
expect(t->m->system, v); expect(t->m->system, v);
} }
inline void
ensure(Thread* t, unsigned sizeInBytes)
{
if (t->heapIndex + ceiling(sizeInBytes, BytesPerWord)
> Thread::HeapSizeInWords)
{
expect(t, t->backupHeap == 0);
t->backupHeap = static_cast<uintptr_t*>
(t->m->heap->allocate(pad(sizeInBytes)));
t->backupHeapIndex = 0;
t->backupHeapSizeInWords = ceiling(sizeInBytes, BytesPerWord);
}
}
object object
allocate2(Thread* t, unsigned sizeInBytes, bool objectMask); allocate2(Thread* t, unsigned sizeInBytes, bool objectMask);
object object
allocate3(Thread* t, Allocator* allocator, Machine::AllocationType type, allocate3(Thread* t, Allocator* allocator, Machine::AllocationType type,
unsigned sizeInBytes, bool executable, bool objectMask); unsigned sizeInBytes, bool objectMask);
inline object inline object
allocateSmall(Thread* t, unsigned sizeInBytes) allocateSmall(Thread* t, unsigned sizeInBytes)
@ -1447,7 +1465,7 @@ allocate(Thread* t, unsigned sizeInBytes, bool objectMask)
stress(t); stress(t);
if (UNLIKELY(t->heapIndex + ceiling(sizeInBytes, BytesPerWord) if (UNLIKELY(t->heapIndex + ceiling(sizeInBytes, BytesPerWord)
>= Thread::HeapSizeInWords > Thread::HeapSizeInWords
or t->m->exclusive)) or t->m->exclusive))
{ {
return allocate2(t, sizeInBytes, objectMask); return allocate2(t, sizeInBytes, objectMask);
@ -1484,7 +1502,7 @@ setObjectClass(Thread*, object o, object value)
cast<object>(o, 0) cast<object>(o, 0)
= reinterpret_cast<object> = reinterpret_cast<object>
(reinterpret_cast<uintptr_t>(value) (reinterpret_cast<uintptr_t>(value)
| reinterpret_cast<uintptr_t>(cast<object>(o, 0)) & (~PointerMask)); | (reinterpret_cast<uintptr_t>(cast<object>(o, 0)) & (~PointerMask)));
} }
object& object&
@ -1526,7 +1544,13 @@ object
makeTrace(Thread* t, Processor::StackWalker* walker); makeTrace(Thread* t, Processor::StackWalker* walker);
object object
makeTrace(Thread* t); makeTrace(Thread* t, Thread* target);
inline object
makeTrace(Thread* t)
{
return makeTrace(t, t);
}
inline object inline object
makeRuntimeException(Thread* t, object message) makeRuntimeException(Thread* t, object message)
@ -1702,6 +1726,9 @@ makeString(Thread* t, const char* format, ...);
void void
stringChars(Thread* t, object string, char* chars); stringChars(Thread* t, object string, char* chars);
void
stringChars(Thread* t, object string, uint16_t* chars);
bool bool
isAssignableFrom(Thread* t, object a, object b); isAssignableFrom(Thread* t, object a, object b);
@ -2231,6 +2258,7 @@ inline object
makeSingleton(Thread* t, unsigned count) makeSingleton(Thread* t, unsigned count)
{ {
object o = makeSingleton(t, count + singletonMaskSize(count), true); object o = makeSingleton(t, count + singletonMaskSize(count), true);
assert(t, singletonLength(t, o) == count + singletonMaskSize(t, o));
if (count) { if (count) {
singletonMask(t, o)[0] = 1; singletonMask(t, o)[0] = 1;
} }

View File

@ -14,37 +14,12 @@
#include "stdint.h" #include "stdint.h"
#include "jni.h" #include "jni.h"
// since we don't link against libstdc++, we must implement some dummy
// functions:
extern "C" void __cxa_pure_virtual(void) { abort(); }
void operator delete(void*) { abort(); }
#ifdef __MINGW32__ #ifdef __MINGW32__
# define PATH_SEPARATOR ';' # define PATH_SEPARATOR ';'
# define EXPORT __declspec(dllexport)
# define SYMBOL(x) binary_classpath_jar_##x
#else #else
# define PATH_SEPARATOR ':' # define PATH_SEPARATOR ':'
# define EXPORT __attribute__ ((visibility("default")))
# define SYMBOL(x) _binary_classpath_jar_##x
#endif #endif
#define BOOT_CLASSPATH "[classpathJar]"
extern "C" {
extern const uint8_t SYMBOL(start)[];
extern const uint8_t SYMBOL(size)[];
EXPORT const uint8_t*
classpathJar(unsigned* size)
{
*size = reinterpret_cast<uintptr_t>(SYMBOL(size));
return SYMBOL(start);
}
}
#ifdef JNI_VERSION_1_6 #ifdef JNI_VERSION_1_6
// todo: use JavaVMInitArgs instead // todo: use JavaVMInitArgs instead
typedef struct JDK1_1InitArgs { typedef struct JDK1_1InitArgs {
@ -121,14 +96,25 @@ main(int ac, const char** av)
vmArgs.classpath = classpath; vmArgs.classpath = classpath;
#endif #endif
const char* properties[propertyCount + 1]; #ifdef BOOT_LIBRARY
properties[propertyCount] = 0; const int BootPropertyCount = 1;
#else
const int BootPropertyCount = 0;
#endif
const char* properties[propertyCount + BootPropertyCount + 1];
properties[propertyCount + BootPropertyCount] = 0;
for (int i = 1; i < ac; ++i) { for (int i = 1; i < ac; ++i) {
if (strncmp(av[i], "-D", 2) == 0) { if (strncmp(av[i], "-D", 2) == 0) {
properties[--propertyCount] = av[i] + 2; properties[--propertyCount] = av[i] + 2;
} }
} }
#ifdef BOOT_LIBRARY
properties[propertyCount + BootPropertyCount - 1]
= "avian.bootstrap=" BOOT_LIBRARY;
#endif
vmArgs.properties = const_cast<char**>(properties); vmArgs.properties = const_cast<char**>(properties);
if (class_ == 0) { if (class_ == 0) {

View File

@ -35,9 +35,6 @@ using namespace vm;
namespace { namespace {
System::SignalHandler* segFaultHandler = 0;
struct sigaction oldSegFaultHandler;
class MutexResource { class MutexResource {
public: public:
MutexResource(pthread_mutex_t& m): m(&m) { MutexResource(pthread_mutex_t& m): m(&m) {
@ -52,12 +49,22 @@ class MutexResource {
pthread_mutex_t* m; pthread_mutex_t* m;
}; };
const int InterruptSignal = SIGUSR2; const int VisitSignal = SIGUSR1;
#ifdef __APPLE__ #ifdef __APPLE__
const int SegFaultSignal = SIGBUS; const int SegFaultSignal = SIGBUS;
#else #else
const int SegFaultSignal = SIGSEGV; const int SegFaultSignal = SIGSEGV;
#endif #endif
const int InterruptSignal = SIGUSR2;
const unsigned VisitSignalIndex = 0;
const unsigned SegFaultSignalIndex = 1;
const unsigned InterruptSignalIndex = 2;
class MySystem;
MySystem* system;
const int signals[] = { VisitSignal, SegFaultSignal, InterruptSignal };
#ifdef __x86_64__ #ifdef __x86_64__
# define IP_REGISTER(context) (context->uc_mcontext.gregs[REG_RIP]) # define IP_REGISTER(context) (context->uc_mcontext.gregs[REG_RIP])
@ -65,10 +72,17 @@ const int SegFaultSignal = SIGSEGV;
# define STACK_REGISTER(context) (context->uc_mcontext.gregs[REG_RSP]) # define STACK_REGISTER(context) (context->uc_mcontext.gregs[REG_RSP])
# define THREAD_REGISTER(context) (context->uc_mcontext.gregs[REG_RBX]) # define THREAD_REGISTER(context) (context->uc_mcontext.gregs[REG_RBX])
#elif defined __APPLE__ #elif defined __APPLE__
# define IP_REGISTER(context) (context->uc_mcontext->__ss.__eip) # if __DARWIN_UNIX03 && defined(_STRUCT_X86_EXCEPTION_STATE32)
# define BASE_REGISTER(context) (context->uc_mcontext->__ss.__ebp) # define IP_REGISTER(context) (context->uc_mcontext->__ss.__eip)
# define STACK_REGISTER(context) (context->uc_mcontext->__ss.__esp) # define BASE_REGISTER(context) (context->uc_mcontext->__ss.__ebp)
# define THREAD_REGISTER(context) (context->uc_mcontext->__ss.__ebx) # define STACK_REGISTER(context) (context->uc_mcontext->__ss.__esp)
# define THREAD_REGISTER(context) (context->uc_mcontext->__ss.__ebx)
# else
# define IP_REGISTER(context) (context->uc_mcontext->ss.eip)
# define BASE_REGISTER(context) (context->uc_mcontext->ss.ebp)
# define STACK_REGISTER(context) (context->uc_mcontext->ss.esp)
# define THREAD_REGISTER(context) (context->uc_mcontext->ss.ebx)
# endif
#elif defined __i386__ #elif defined __i386__
# define IP_REGISTER(context) (context->uc_mcontext.gregs[REG_EIP]) # define IP_REGISTER(context) (context->uc_mcontext.gregs[REG_EIP])
# define BASE_REGISTER(context) (context->uc_mcontext.gregs[REG_EBP]) # define BASE_REGISTER(context) (context->uc_mcontext.gregs[REG_EBP])
@ -79,41 +93,7 @@ const int SegFaultSignal = SIGSEGV;
#endif #endif
void void
handleSignal(int signal, siginfo_t* info, void* context) handleSignal(int signal, siginfo_t* info, void* context);
{
if (signal == SegFaultSignal) {
ucontext_t* c = static_cast<ucontext_t*>(context);
void* ip = reinterpret_cast<void*>(IP_REGISTER(c));
void* base = reinterpret_cast<void*>(BASE_REGISTER(c));
void* stack = reinterpret_cast<void*>(STACK_REGISTER(c));
void* thread = reinterpret_cast<void*>(THREAD_REGISTER(c));
bool jump = segFaultHandler->handleSignal
(&ip, &base, &stack, &thread);
if (jump) {
// I'd like to use setcontext here (and get rid of the
// sigprocmask call), but it doesn't work on my Linux x86_64
// system, and I can't tell from the documentation if it's even
// supposed to work.
sigset_t set;
sigemptyset(&set);
sigaddset(&set, SegFaultSignal);
sigprocmask(SIG_UNBLOCK, &set, 0);
vmJump(ip, base, stack, thread);
} else if (oldSegFaultHandler.sa_flags & SA_SIGINFO) {
oldSegFaultHandler.sa_sigaction(signal, info, context);
} else if (oldSegFaultHandler.sa_handler) {
oldSegFaultHandler.sa_handler(signal);
} else {
abort();
}
}
}
void* void*
run(void* r) run(void* r)
@ -125,7 +105,7 @@ run(void* r)
void* void*
allocate(System* s, unsigned size) allocate(System* s, unsigned size)
{ {
void* p = s->tryAllocate(size, false); void* p = s->tryAllocate(size);
if (p == 0) abort(); if (p == 0) abort();
return p; return p;
} }
@ -187,7 +167,7 @@ class MySystem: public System {
} }
virtual void dispose() { virtual void dispose() {
s->free(this, sizeof(*this), false); s->free(this);
} }
pthread_t thread; pthread_t thread;
@ -215,7 +195,7 @@ class MySystem: public System {
virtual void dispose() { virtual void dispose() {
pthread_mutex_destroy(&mutex); pthread_mutex_destroy(&mutex);
s->free(this, sizeof(*this), false); s->free(this);
} }
System* s; System* s;
@ -414,7 +394,7 @@ class MySystem: public System {
virtual void dispose() { virtual void dispose() {
expect(s, owner_ == 0); expect(s, owner_ == 0);
pthread_mutex_destroy(&mutex); pthread_mutex_destroy(&mutex);
s->free(this, sizeof(*this), false); s->free(this);
} }
System* s; System* s;
@ -445,7 +425,7 @@ class MySystem: public System {
int r UNUSED = pthread_key_delete(key); int r UNUSED = pthread_key_delete(key);
expect(s, r == 0); expect(s, r == 0);
s->free(this, sizeof(*this), false); s->free(this);
} }
System* s; System* s;
@ -472,7 +452,7 @@ class MySystem: public System {
if (start_) { if (start_) {
munmap(start_, length_); munmap(start_, length_);
} }
s->free(this, sizeof(*this), false); s->free(this);
} }
System* s; System* s;
@ -525,10 +505,10 @@ class MySystem: public System {
} }
if (name_) { if (name_) {
s->free(name_, nameLength + 1, false); s->free(name_);
} }
s->free(this, sizeof(*this), false); s->free(this);
} }
System* s; System* s;
@ -540,49 +520,63 @@ class MySystem: public System {
System::Library* next_; System::Library* next_;
}; };
MySystem() { MySystem(): threadVisitor(0), visitTarget(0) {
struct sigaction sa; expect(this, system == 0);
memset(&sa, 0, sizeof(struct sigaction)); system = this;
sigemptyset(&(sa.sa_mask));
sa.sa_flags = SA_SIGINFO; registerHandler(&nullHandler, InterruptSignalIndex);
sa.sa_sigaction = handleSignal; registerHandler(&nullHandler, VisitSignalIndex);
expect(this, make(&visitLock) == 0);
}
int registerHandler(System::SignalHandler* handler, int index) {
if (handler) {
handlers[index] = handler;
struct sigaction sa;
memset(&sa, 0, sizeof(struct sigaction));
sigemptyset(&(sa.sa_mask));
sa.sa_flags = SA_SIGINFO;
sa.sa_sigaction = handleSignal;
int rv UNUSED = sigaction(InterruptSignal, &sa, 0); return sigaction(signals[index], &sa, oldHandlers + index);
expect(this, rv == 0); } else if (handlers[index]) {
} handlers[index] = 0;
return sigaction(signals[index], oldHandlers + index, 0);
virtual void* tryAllocate(unsigned size, bool executable) {
assert(this, (not executable) or (size % LikelyPageSizeInBytes == 0));
#ifndef MAP_32BIT
#define MAP_32BIT 0
#endif
if (executable) {
void* p = mmap(0, size, PROT_EXEC | PROT_READ | PROT_WRITE,
MAP_PRIVATE | MAP_ANON | MAP_32BIT, -1, 0);
if (p == MAP_FAILED) {
return 0;
} else {
return p;
}
} else { } else {
return malloc(size); return 1;
} }
} }
virtual void free(const void* p, unsigned size, bool executable) { virtual void* tryAllocate(unsigned sizeInBytes) {
if (p) { return malloc(sizeInBytes);
if (executable) { }
int r UNUSED = munmap(const_cast<void*>(p), size);
assert(this, r == 0); virtual void free(const void* p) {
} else { if (p) ::free(const_cast<void*>(p));
::free(const_cast<void*>(p)); }
}
virtual void* tryAllocateExecutable(unsigned sizeInBytes) {
assert(this, sizeInBytes % LikelyPageSizeInBytes == 0);
void* p = mmap(0, sizeInBytes, PROT_EXEC | PROT_READ | PROT_WRITE,
MAP_PRIVATE | MAP_ANON, -1, 0);
if (p == MAP_FAILED) {
return 0;
} else {
return p;
} }
} }
virtual void freeExecutable(const void* p, unsigned sizeInBytes) {
assert(this, sizeInBytes % LikelyPageSizeInBytes == 0);
int r UNUSED = munmap(const_cast<void*>(p), sizeInBytes);
assert(this, r == 0);
}
virtual bool success(Status s) { virtual bool success(Status s) {
return s == 0; return s == 0;
} }
@ -618,22 +612,32 @@ class MySystem: public System {
} }
virtual Status handleSegFault(SignalHandler* handler) { virtual Status handleSegFault(SignalHandler* handler) {
if (handler) { return registerHandler(handler, SegFaultSignalIndex);
segFaultHandler = handler; }
struct sigaction sa; virtual Status visit(System::Thread* st, System::Thread* sTarget,
memset(&sa, 0, sizeof(struct sigaction)); ThreadVisitor* visitor)
sigemptyset(&(sa.sa_mask)); {
sa.sa_flags = SA_SIGINFO; assert(this, st != sTarget);
sa.sa_sigaction = handleSignal;
Thread* t = static_cast<Thread*>(st);
return sigaction(SegFaultSignal, &sa, &oldSegFaultHandler); Thread* target = static_cast<Thread*>(sTarget);
} else if (segFaultHandler) {
segFaultHandler = 0; ACQUIRE_MONITOR(t, visitLock);
return sigaction(SegFaultSignal, &oldSegFaultHandler, 0);
} else { while (threadVisitor) visitLock->wait(t, 0);
return 1;
} threadVisitor = visitor;
visitTarget = target;
int rv = pthread_kill(target->thread, VisitSignal);
expect(this, rv == 0);
while (visitTarget) visitLock->wait(t, 0);
threadVisitor = 0;
return 0;
} }
virtual uint64_t call(void* function, uintptr_t* arguments, uint8_t* types, virtual uint64_t call(void* function, uintptr_t* arguments, uint8_t* types,
@ -687,18 +691,18 @@ class MySystem: public System {
bool alreadyAllocated = false; bool alreadyAllocated = false;
bool isMain = false; bool isMain = false;
unsigned nameLength = (name ? strlen(name) : 0); unsigned nameLength = (name ? strlen(name) : 0);
if (mapName) { if (mapName and name) {
unsigned size = nameLength + 3 + sizeof(SO_SUFFIX); unsigned size = nameLength + 3 + sizeof(SO_SUFFIX);
char buffer[size]; char buffer[size];
snprintf(buffer, size, "lib%s" SO_SUFFIX, name); snprintf(buffer, size, "lib%s" SO_SUFFIX, name);
p = dlopen(buffer, RTLD_LAZY); p = dlopen(buffer, RTLD_LAZY | RTLD_LOCAL);
} else { } else {
if (!name) { if (!name) {
pathOfExecutable(this, &name, &nameLength); pathOfExecutable(this, &name, &nameLength);
alreadyAllocated = true; alreadyAllocated = true;
isMain = true; isMain = true;
} }
p = dlopen(name, RTLD_LAZY); p = dlopen(name, RTLD_LAZY | RTLD_LOCAL);
} }
if (p) { if (p) {
@ -711,7 +715,7 @@ class MySystem: public System {
n = static_cast<char*>(allocate(this, nameLength + 1)); n = static_cast<char*>(allocate(this, nameLength + 1));
memcpy(n, name, nameLength + 1); memcpy(n, name, nameLength + 1);
if (alreadyAllocated) { if (alreadyAllocated) {
free(name, nameLength, false); free(name);
} }
} else { } else {
n = 0; n = 0;
@ -747,10 +751,89 @@ class MySystem: public System {
} }
virtual void dispose() { virtual void dispose() {
visitLock->dispose();
registerHandler(0, InterruptSignalIndex);
registerHandler(0, VisitSignalIndex);
system = 0;
::free(this); ::free(this);
} }
class NullSignalHandler: public SignalHandler {
virtual bool handleSignal(void**, void**, void**, void**) { return false; }
} nullHandler;
SignalHandler* handlers[3];
struct sigaction oldHandlers[3];
ThreadVisitor* threadVisitor;
Thread* visitTarget;
System::Monitor* visitLock;
}; };
void
handleSignal(int signal, siginfo_t* info, void* context)
{
ucontext_t* c = static_cast<ucontext_t*>(context);
void* ip = reinterpret_cast<void*>(IP_REGISTER(c));
void* base = reinterpret_cast<void*>(BASE_REGISTER(c));
void* stack = reinterpret_cast<void*>(STACK_REGISTER(c));
void* thread = reinterpret_cast<void*>(THREAD_REGISTER(c));
unsigned index;
switch (signal) {
case VisitSignal: {
index = VisitSignalIndex;
system->threadVisitor->visit(ip, base, stack);
System::Thread* t = system->visitTarget;
system->visitTarget = 0;
system->visitLock->notifyAll(t);
} break;
case SegFaultSignal: {
index = SegFaultSignalIndex;
bool jump = system->handlers[index]->handleSignal
(&ip, &base, &stack, &thread);
if (jump) {
// I'd like to use setcontext here (and get rid of the
// sigprocmask call), but it doesn't work on my Linux x86_64
// system, and I can't tell from the documentation if it's even
// supposed to work.
sigset_t set;
sigemptyset(&set);
sigaddset(&set, SegFaultSignal);
sigprocmask(SIG_UNBLOCK, &set, 0);
vmJump(ip, base, stack, thread);
}
} break;
case InterruptSignal: {
index = InterruptSignalIndex;
} break;
default: abort();
}
if (system->oldHandlers[index].sa_flags & SA_SIGINFO) {
system->oldHandlers[index].sa_sigaction(signal, info, context);
} else if (system->oldHandlers[index].sa_handler) {
system->oldHandlers[index].sa_handler(signal);
} else {
abort();
}
}
} // namespace } // namespace
namespace vm { namespace vm {

View File

@ -191,50 +191,6 @@ resolveNativeMethod2(Thread* t, object method)
return 0; return 0;
} }
ExceptionHandler*
findExceptionHandler(Thread* t, object method, unsigned ip)
{
PROTECT(t, method);
object eht = codeExceptionHandlerTable(t, methodCode(t, method));
if (eht) {
for (unsigned i = 0; i < exceptionHandlerTableLength(t, eht); ++i) {
ExceptionHandler* eh = exceptionHandlerTableBody(t, eht, i);
if (ip - 1 >= exceptionHandlerStart(eh)
and ip - 1 < exceptionHandlerEnd(eh))
{
object catchType = 0;
if (exceptionHandlerCatchType(eh)) {
object e = t->exception;
t->exception = 0;
PROTECT(t, e);
PROTECT(t, eht);
catchType = resolveClassInPool
(t, codePool(t, methodCode(t, method)),
exceptionHandlerCatchType(eh) - 1);
if (catchType) {
eh = exceptionHandlerTableBody(t, eht, i);
t->exception = e;
} else {
// can't find what we're supposed to catch - move on.
continue;
}
}
if (catchType == 0 or instanceOf(t, catchType, t->exception)) {
return eh;
}
}
}
}
return 0;
}
int int
findLineNumber(Thread* t, object method, unsigned ip) findLineNumber(Thread* t, object method, unsigned ip)
{ {

View File

@ -40,8 +40,7 @@ inline object
resolveClassInObject(Thread* t, object container, unsigned classOffset) resolveClassInObject(Thread* t, object container, unsigned classOffset)
{ {
object o = cast<object>(container, classOffset); object o = cast<object>(container, classOffset);
if (objectClass(t, o) == arrayBody(t, t->m->types, Machine::ByteArrayType)) if (objectClass(t, o) == arrayBody(t, t->m->types, Machine::ByteArrayType)) {
{
PROTECT(t, container); PROTECT(t, container);
o = resolveClass(t, o); o = resolveClass(t, o);
@ -56,8 +55,7 @@ inline object
resolveClassInPool(Thread* t, object pool, unsigned index) resolveClassInPool(Thread* t, object pool, unsigned index)
{ {
object o = singletonObject(t, pool, index); object o = singletonObject(t, pool, index);
if (objectClass(t, o) == arrayBody(t, t->m->types, Machine::ByteArrayType)) if (objectClass(t, o) == arrayBody(t, t->m->types, Machine::ByteArrayType)) {
{
PROTECT(t, pool); PROTECT(t, pool);
o = resolveClass(t, o); o = resolveClass(t, o);
@ -194,9 +192,6 @@ populateMultiArray(Thread* t, object array, int32_t* counts,
} }
} }
ExceptionHandler*
findExceptionHandler(Thread* t, object method, unsigned ip);
int int
findLineNumber(Thread* t, object method, unsigned ip); findLineNumber(Thread* t, object method, unsigned ip);

View File

@ -115,6 +115,9 @@ class Processor {
virtual void virtual void
dispose() = 0; dispose() = 0;
virtual object
getStackTrace(Thread* t, Thread* target) = 0;
object object
invoke(Thread* t, object method, object this_, ...) invoke(Thread* t, object method, object this_, ...)
{ {

View File

@ -34,6 +34,12 @@ class System {
virtual void dispose() = 0; virtual void dispose() = 0;
}; };
class ThreadVisitor {
public:
virtual ~ThreadVisitor() { }
virtual void visit(void* ip, void* base, void* stack) = 0;
};
class Runnable { class Runnable {
public: public:
virtual ~Runnable() { } virtual ~Runnable() { }
@ -99,17 +105,36 @@ class System {
void** thread) = 0; void** thread) = 0;
}; };
class MonitorResource {
public:
MonitorResource(System::Thread* t, System::Monitor* m): t(t), m(m) {
m->acquire(t);
}
~MonitorResource() {
m->release(t);
}
private:
System::Thread* t;
System::Monitor* m;
};
virtual ~System() { } virtual ~System() { }
virtual bool success(Status) = 0; virtual bool success(Status) = 0;
virtual void* tryAllocate(unsigned size, bool executable) = 0; virtual void* tryAllocate(unsigned sizeInBytes) = 0;
virtual void free(const void* p, unsigned size, bool executable) = 0; virtual void free(const void* p) = 0;
virtual void* tryAllocateExecutable(unsigned sizeInBytes) = 0;
virtual void freeExecutable(const void* p, unsigned sizeInBytes) = 0;
virtual Status attach(Runnable*) = 0; virtual Status attach(Runnable*) = 0;
virtual Status start(Runnable*) = 0; virtual Status start(Runnable*) = 0;
virtual Status make(Mutex**) = 0; virtual Status make(Mutex**) = 0;
virtual Status make(Monitor**) = 0; virtual Status make(Monitor**) = 0;
virtual Status make(Local**) = 0; virtual Status make(Local**) = 0;
virtual Status handleSegFault(SignalHandler* handler) = 0; virtual Status handleSegFault(SignalHandler* handler) = 0;
virtual Status visit(Thread* thread, Thread* target,
ThreadVisitor* visitor) = 0;
virtual uint64_t call(void* function, uintptr_t* arguments, uint8_t* types, virtual uint64_t call(void* function, uintptr_t* arguments, uint8_t* types,
unsigned count, unsigned size, unsigned count, unsigned size,
unsigned returnType) = 0; unsigned returnType) = 0;
@ -123,6 +148,9 @@ class System {
virtual void dispose() = 0; virtual void dispose() = 0;
}; };
#define ACQUIRE_MONITOR(t, m) \
System::MonitorResource MAKE_NAME(monitorResource_) (t, m)
inline void NO_RETURN inline void NO_RETURN
abort(System* s) abort(System* s)
{ {

View File

@ -1507,7 +1507,7 @@ writeOffset(Output* out, Object* offset, bool allocationStyle = false)
out->write("length"); out->write("length");
} else { } else {
out->write(typeName(memberOwner(o))); out->write(typeName(memberOwner(o)));
out->write(capitalize("length")); out->write("Length");
out->write("(o)"); out->write("(o)");
} }
out->write(" * "); out->write(" * ");
@ -1762,6 +1762,49 @@ typeFixedSize(Object* type)
return length; return length;
} }
unsigned
typeArrayElementSize(Object* type)
{
for (MemberIterator it(type); it.hasMore();) {
Object* m = it.next();
switch (m->type) {
case Object::Scalar: break;
case Object::Array: {
return memberElementSize(m);
} break;
default: UNREACHABLE;
}
}
return 0;
}
void
writeSizes(Output* out, Object* declarations)
{
for (Object* p = declarations; p; p = cdr(p)) {
Object* o = car(p);
switch (o->type) {
case Object::Type: {
out->write("const unsigned FixedSizeOf");
out->write(capitalize(typeName(o)));
out->write(" = ");
out->write(typeFixedSize(o));
out->write(";\n\n");
out->write("const unsigned ArrayElementSizeOf");
out->write(capitalize(typeName(o)));
out->write(" = ");
out->write(typeArrayElementSize(o));
out->write(";\n\n");
} break;
default: break;
}
}
}
const char* const char*
obfuscate(const char* s) obfuscate(const char* s)
{ {
@ -2049,24 +2092,6 @@ set(uint32_t* mask, unsigned index)
} }
} }
unsigned
typeArrayElementSize(Object* type)
{
for (MemberIterator it(type); it.hasMore();) {
Object* m = it.next();
switch (m->type) {
case Object::Scalar: break;
case Object::Array: {
return memberElementSize(m);
} break;
default: UNREACHABLE;
}
}
return 0;
}
uint32_t uint32_t
typeObjectMask(Object* type) typeObjectMask(Object* type)
{ {
@ -2274,6 +2299,7 @@ main(int ac, char** av)
writePods(&out, declarations); writePods(&out, declarations);
writeAccessors(&out, declarations); writeAccessors(&out, declarations);
writeSizes(&out, declarations);
writeInitializerDeclarations(&out, declarations); writeInitializerDeclarations(&out, declarations);
writeConstructorDeclarations(&out, declarations); writeConstructorDeclarations(&out, declarations);
} }

View File

@ -24,10 +24,10 @@
(void* value)) (void* value))
(pod exceptionHandler (pod exceptionHandler
(uint32_t start) (uint16_t start)
(uint32_t end) (uint16_t end)
(uint32_t ip) (uint16_t ip)
(uint32_t catchType)) (uint16_t catchType))
(type exceptionHandlerTable (type exceptionHandlerTable
(array exceptionHandler body)) (array exceptionHandler body))
@ -91,13 +91,22 @@
(object method) (object method)
(int ip)) (int ip))
(type traceNode (type treeNode
(object value)
(object left)
(object right))
(type treePath
(uintptr_t fresh)
(object node)
(object root)
(object ancestors))
(type callNode
(intptr_t address) (intptr_t address)
(object next)
(object method)
(object target) (object target)
(uintptr_t virtualCall) (uintptr_t virtualCall)
(array uintptr_t map)) (object next))
(type array (type array
(noassert array object body)) (noassert array object body))

View File

@ -14,18 +14,241 @@ using namespace vm;
namespace { namespace {
object inline object
clone(Thread* t, object o) getTreeNodeValue(Thread*, object n)
{ {
object class_ = objectClass(t, o); return reinterpret_cast<object>
unsigned size = baseSize(t, o, class_) * BytesPerWord; (cast<intptr_t>(n, TreeNodeValue) & PointerMask);
}
object clone = make(t, class_); inline void
memcpy(reinterpret_cast<void**>(clone) + 1, setTreeNodeValue(Thread* t, object n, object value)
reinterpret_cast<void**>(o) + 1, {
size - BytesPerWord); intptr_t red = cast<intptr_t>(n, TreeNodeValue) & (~PointerMask);
return clone; set(t, n, TreeNodeValue, value);
cast<intptr_t>(n, TreeNodeValue) |= red;
}
inline bool
treeNodeRed(Thread*, object n)
{
return (cast<intptr_t>(n, TreeNodeValue) & (~PointerMask)) == 1;
}
inline void
setTreeNodeRed(Thread*, object n, bool red)
{
if (red) {
cast<intptr_t>(n, TreeNodeValue) |= 1;
} else {
cast<intptr_t>(n, TreeNodeValue) &= PointerMask;
}
}
inline object
cloneTreeNode(Thread* t, object n)
{
PROTECT(t, n);
object newNode = makeTreeNode
(t, getTreeNodeValue(t, n), treeNodeLeft(t, n), treeNodeRight(t, n));
setTreeNodeRed(t, newNode, treeNodeRed(t, n));
return newNode;
}
object
treeFind(Thread* t, object old, object node, object sentinal,
intptr_t (*compare)(Thread* t, object a, object b))
{
PROTECT(t, old);
PROTECT(t, node);
PROTECT(t, sentinal);
object newRoot = cloneTreeNode(t, old);
PROTECT(t, newRoot);
object new_ = newRoot;
PROTECT(t, new_);
object ancestors = 0;
PROTECT(t, ancestors);
while (old != sentinal) {
ancestors = makePair(t, new_, ancestors);
intptr_t difference = compare
(t, getTreeNodeValue(t, node), getTreeNodeValue(t, old));
if (difference < 0) {
old = treeNodeLeft(t, old);
object n = cloneTreeNode(t, old);
set(t, new_, TreeNodeLeft, n);
new_ = n;
} else if (difference > 0) {
old = treeNodeRight(t, old);
object n = cloneTreeNode(t, old);
set(t, new_, TreeNodeRight, n);
new_ = n;
} else {
return makeTreePath(t, false, new_, newRoot, pairSecond(t, ancestors));
}
}
setTreeNodeValue(t, new_, getTreeNodeValue(t, node));
return makeTreePath(t, true, new_, newRoot, ancestors);
}
object
leftRotate(Thread* t, object n)
{
PROTECT(t, n);
object child = cloneTreeNode(t, treeNodeRight(t, n));
set(t, n, TreeNodeRight, treeNodeLeft(t, child));
set(t, child, TreeNodeLeft, n);
return child;
}
object
rightRotate(Thread* t, object n)
{
PROTECT(t, n);
object child = cloneTreeNode(t, treeNodeLeft(t, n));
set(t, n, TreeNodeLeft, treeNodeRight(t, child));
set(t, child, TreeNodeRight, n);
return child;
}
object
treeAdd(Thread* t, object path)
{
object new_ = treePathNode(t, path);
PROTECT(t, new_);
object newRoot = treePathRoot(t, path);
PROTECT(t, newRoot);
object ancestors = treePathAncestors(t, path);
PROTECT(t, ancestors);
// rebalance
setTreeNodeRed(t, new_, true);
while (ancestors != 0 and treeNodeRed(t, pairFirst(t, ancestors))) {
if (pairFirst(t, ancestors)
== treeNodeLeft(t, pairFirst(t, pairSecond(t, ancestors))))
{
if (treeNodeRed
(t, treeNodeRight(t, pairFirst(t, pairSecond(t, ancestors)))))
{
setTreeNodeRed(t, pairFirst(t, ancestors), true);
object n = cloneTreeNode
(t, treeNodeRight(t, pairFirst(t, pairSecond(t, ancestors))));
set(t, pairFirst(t, pairSecond(t, ancestors)), TreeNodeRight, n);
setTreeNodeRed
(t, treeNodeRight
(t, pairFirst(t, pairSecond(t, ancestors))), false);
setTreeNodeRed(t, pairFirst(t, pairSecond(t, ancestors)), false);
new_ = pairFirst(t, pairSecond(t, ancestors));
ancestors = pairSecond(t, pairSecond(t, ancestors));
} else {
if (new_ == treeNodeRight(t, pairFirst(t, ancestors))) {
new_ = pairFirst(t, ancestors);
ancestors = pairSecond(t, ancestors);
object n = leftRotate(t, new_);
if (new_ == treeNodeRight(t, pairFirst(t, ancestors))) {
set(t, pairFirst(t, ancestors), TreeNodeRight, n);
} else {
set(t, pairFirst(t, ancestors), TreeNodeLeft, n);
}
ancestors = makePair(t, n, ancestors);
}
setTreeNodeRed(t, pairFirst(t, ancestors), false);
setTreeNodeRed(t, pairFirst(t, pairSecond(t, ancestors)), true);
object n = rightRotate(t, pairFirst(t, pairSecond(t, ancestors)));
if (pairSecond(t, pairSecond(t, ancestors)) == 0) {
newRoot = n;
} else if (treeNodeRight
(t, pairFirst(t, pairSecond(t, pairSecond(t, ancestors))))
== pairFirst(t, pairSecond(t, ancestors)))
{
set(t, pairFirst(t, pairSecond(t, pairSecond(t, ancestors))),
TreeNodeRight, n);
} else {
set(t, pairFirst(t, pairSecond(t, pairSecond(t, ancestors))),
TreeNodeLeft, n);
}
// done
}
} else { // this is just the reverse of the code above (right and
// left swapped):
if (treeNodeRed
(t, treeNodeLeft(t, pairFirst(t, pairSecond(t, ancestors)))))
{
setTreeNodeRed(t, pairFirst(t, ancestors), true);
object n = cloneTreeNode
(t, treeNodeLeft(t, pairFirst(t, pairSecond(t, ancestors))));
set(t, pairFirst(t, pairSecond(t, ancestors)), TreeNodeLeft, n);
setTreeNodeRed
(t, treeNodeLeft
(t, pairFirst(t, pairSecond(t, ancestors))), false);
setTreeNodeRed(t, pairFirst(t, pairSecond(t, ancestors)), false);
new_ = pairFirst(t, pairSecond(t, ancestors));
ancestors = pairSecond(t, pairSecond(t, ancestors));
} else {
if (new_ == treeNodeLeft(t, pairFirst(t, ancestors))) {
new_ = pairFirst(t, ancestors);
ancestors = pairSecond(t, ancestors);
object n = rightRotate(t, new_);
if (new_ == treeNodeLeft(t, pairFirst(t, ancestors))) {
set(t, pairFirst(t, ancestors), TreeNodeLeft, n);
} else {
set(t, pairFirst(t, ancestors), TreeNodeRight, n);
}
ancestors = makePair(t, n, ancestors);
}
setTreeNodeRed(t, pairFirst(t, ancestors), false);
setTreeNodeRed(t, pairFirst(t, pairSecond(t, ancestors)), true);
object n = leftRotate(t, pairFirst(t, pairSecond(t, ancestors)));
if (pairSecond(t, pairSecond(t, ancestors)) == 0) {
newRoot = n;
} else if (treeNodeLeft
(t, pairFirst(t, pairSecond(t, pairSecond(t, ancestors))))
== pairFirst(t, pairSecond(t, ancestors)))
{
set(t, pairFirst(t, pairSecond(t, pairSecond(t, ancestors))),
TreeNodeLeft, n);
} else {
set(t, pairFirst(t, pairSecond(t, pairSecond(t, ancestors))),
TreeNodeRight, n);
}
// done
}
}
}
setTreeNodeRed(t, newRoot, false);
return newRoot;
} }
} // namespace } // namespace
@ -293,4 +516,40 @@ vectorAppend(Thread* t, object vector, object value)
return vector; return vector;
} }
object
treeQuery(Thread* t, object tree, intptr_t key, object sentinal,
intptr_t (*compare)(Thread* t, intptr_t key, object b))
{
object node = tree;
while (node != sentinal) {
intptr_t difference = compare(t, key, getTreeNodeValue(t, node));
if (difference < 0) {
node = treeNodeLeft(t, node);
} else if (difference > 0) {
node = treeNodeRight(t, node);
} else {
return getTreeNodeValue(t, node);
}
}
return 0;
}
object
treeInsert(Thread* t, object tree, object value, object sentinal,
intptr_t (*compare)(Thread* t, object a, object b))
{
PROTECT(t, tree);
PROTECT(t, sentinal);
object node = makeTreeNode(t, value, sentinal, sentinal);
object path = treeFind(t, tree, node, sentinal, compare);
if (treePathFresh(t, path)) {
return treeAdd(t, path);
} else {
return tree;
}
}
} // namespace vm } // namespace vm

View File

@ -83,6 +83,14 @@ listAppend(Thread* t, object list, object value);
object object
vectorAppend(Thread* t, object vector, object value); vectorAppend(Thread* t, object vector, object value);
object
treeQuery(Thread* t, object tree, intptr_t key, object sentinal,
intptr_t (*compare)(Thread* t, intptr_t key, object b));
object
treeInsert(Thread* t, object tree, object value, object sentinal,
intptr_t (*compare)(Thread* t, object a, object b));
} // vm } // vm
#endif//UTIL_H #endif//UTIL_H

View File

@ -32,7 +32,7 @@ class Vector {
void dispose() { void dispose() {
if (data and minimumCapacity >= 0) { if (data and minimumCapacity >= 0) {
allocator->free(data, capacity, false); allocator->free(data, capacity);
} }
} }
@ -52,10 +52,10 @@ class Vector {
unsigned newCapacity = max unsigned newCapacity = max
(position + space, max(minimumCapacity, capacity * 2)); (position + space, max(minimumCapacity, capacity * 2));
uint8_t* newData = static_cast<uint8_t*> uint8_t* newData = static_cast<uint8_t*>
(allocator->allocate(newCapacity, false)); (allocator->allocate(newCapacity));
if (data) { if (data) {
memcpy(newData, data, position); memcpy(newData, data, position);
allocator->free(data, capacity, false); allocator->free(data, capacity);
} }
data = newData; data = newData;
capacity = newCapacity; capacity = newCapacity;

View File

@ -23,6 +23,23 @@ using namespace vm;
namespace { namespace {
class MutexResource {
public:
MutexResource(System* s, HANDLE m): s(s), m(m) {
int r UNUSED = WaitForSingleObject(m, INFINITE);
assert(s, r == WAIT_OBJECT_0);
}
~MutexResource() {
bool success UNUSED = ReleaseMutex(m);
assert(s, success);
}
private:
System* s;
HANDLE m;
};
System::SignalHandler* segFaultHandler = 0; System::SignalHandler* segFaultHandler = 0;
LPTOP_LEVEL_EXCEPTION_FILTER oldSegFaultHandler = 0; LPTOP_LEVEL_EXCEPTION_FILTER oldSegFaultHandler = 0;
@ -43,23 +60,6 @@ handleException(LPEXCEPTION_POINTERS e)
return EXCEPTION_CONTINUE_SEARCH; return EXCEPTION_CONTINUE_SEARCH;
} }
class MutexResource {
public:
MutexResource(System* s, HANDLE m): s(s), m(m) {
int r UNUSED = WaitForSingleObject(m, INFINITE);
assert(s, r == WAIT_OBJECT_0);
}
~MutexResource() {
bool success UNUSED = ReleaseMutex(m);
assert(s, success);
}
private:
System* s;
HANDLE m;
};
DWORD WINAPI DWORD WINAPI
run(void* r) run(void* r)
{ {
@ -70,7 +70,7 @@ run(void* r)
void* void*
allocate(System* s, unsigned size) allocate(System* s, unsigned size)
{ {
void* p = s->tryAllocate(size, false); void* p = s->tryAllocate(size);
if (p == 0) abort(); if (p == 0) abort();
return p; return p;
} }
@ -117,7 +117,7 @@ class MySystem: public System {
CloseHandle(event); CloseHandle(event);
CloseHandle(mutex); CloseHandle(mutex);
CloseHandle(thread); CloseHandle(thread);
s->free(this, sizeof(*this), false); s->free(this);
} }
HANDLE thread; HANDLE thread;
@ -148,7 +148,7 @@ class MySystem: public System {
virtual void dispose() { virtual void dispose() {
CloseHandle(mutex); CloseHandle(mutex);
s->free(this, sizeof(*this), false); s->free(this);
} }
System* s; System* s;
@ -362,7 +362,7 @@ class MySystem: public System {
virtual void dispose() { virtual void dispose() {
assert(s, owner_ == 0); assert(s, owner_ == 0);
CloseHandle(mutex); CloseHandle(mutex);
s->free(this, sizeof(*this), false); s->free(this);
} }
System* s; System* s;
@ -393,7 +393,7 @@ class MySystem: public System {
bool r UNUSED = TlsFree(key); bool r UNUSED = TlsFree(key);
assert(s, r); assert(s, r);
s->free(this, sizeof(*this), false); s->free(this);
} }
System* s; System* s;
@ -425,7 +425,7 @@ class MySystem: public System {
if (mapping) CloseHandle(mapping); if (mapping) CloseHandle(mapping);
if (file) CloseHandle(file); if (file) CloseHandle(file);
} }
system->free(this, sizeof(*this), false); system->free(this);
} }
System* system; System* system;
@ -437,12 +437,10 @@ class MySystem: public System {
class Library: public System::Library { class Library: public System::Library {
public: public:
Library(System* s, HMODULE handle, const char* name, size_t nameLength, Library(System* s, HMODULE handle, const char* name, bool mapName):
bool mapName):
s(s), s(s),
handle(handle), handle(handle),
name_(name), name_(name),
nameLength(nameLength),
mapName_(mapName), mapName_(mapName),
next_(0) next_(0)
{ } { }
@ -484,16 +482,15 @@ class MySystem: public System {
} }
if (name_) { if (name_) {
s->free(name_, nameLength + 1, false); s->free(name_);
} }
s->free(this, sizeof(*this), false); s->free(this);
} }
System* s; System* s;
HMODULE handle; HMODULE handle;
const char* name_; const char* name_;
size_t nameLength;
bool mapName_; bool mapName_;
System::Library* next_; System::Library* next_;
}; };
@ -503,14 +500,26 @@ class MySystem: public System {
assert(this, mutex); assert(this, mutex);
} }
virtual void* tryAllocate(unsigned size, bool) { virtual void* tryAllocate(unsigned sizeInBytes) {
return malloc(size); return malloc(sizeInBytes);
} }
virtual void free(const void* p, unsigned, bool) { virtual void free(const void* p) {
if (p) ::free(const_cast<void*>(p)); if (p) ::free(const_cast<void*>(p));
} }
virtual void* tryAllocateExecutable(unsigned sizeInBytes) {
assert(this, sizeInBytes % LikelyPageSizeInBytes == 0);
return VirtualAlloc
(0, sizeInBytes, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
}
virtual void freeExecutable(const void* p, unsigned) {
int r UNUSED = VirtualFree(const_cast<void*>(p), 0, MEM_RELEASE);
assert(this, r);
}
virtual bool success(Status s) { virtual bool success(Status s) {
return s == 0; return s == 0;
} }
@ -564,6 +573,32 @@ class MySystem: public System {
} }
} }
virtual Status visit(System::Thread* st UNUSED, System::Thread* sTarget,
ThreadVisitor* visitor)
{
assert(this, st != sTarget);
Thread* target = static_cast<Thread*>(sTarget);
ACQUIRE(this, mutex);
int rv = SuspendThread(target->thread);
expect(this, rv != -1);
CONTEXT context;
rv = GetThreadContext(target->thread, &context);
expect(this, rv);
visitor->visit(reinterpret_cast<void*>(context.Eip),
reinterpret_cast<void*>(context.Ebp),
reinterpret_cast<void*>(context.Esp));
rv = ResumeThread(target->thread);
expect(this, rv != -1);
return 0;
}
virtual uint64_t call(void* function, uintptr_t* arguments, uint8_t* types, virtual uint64_t call(void* function, uintptr_t* arguments, uint8_t* types,
unsigned count, unsigned size, unsigned returnType) unsigned count, unsigned size, unsigned returnType)
{ {
@ -623,7 +658,7 @@ class MySystem: public System {
{ {
HMODULE handle; HMODULE handle;
unsigned nameLength = (name ? strlen(name) : 0); unsigned nameLength = (name ? strlen(name) : 0);
if (mapName) { if (mapName and name) {
unsigned size = sizeof(SO_PREFIX) + nameLength + sizeof(SO_SUFFIX); unsigned size = sizeof(SO_PREFIX) + nameLength + sizeof(SO_SUFFIX);
char buffer[size]; char buffer[size];
snprintf(buffer, size, SO_PREFIX "%s" SO_SUFFIX, name); snprintf(buffer, size, SO_PREFIX "%s" SO_SUFFIX, name);
@ -648,7 +683,7 @@ class MySystem: public System {
} }
*lib = new (allocate(this, sizeof(Library))) *lib = new (allocate(this, sizeof(Library)))
Library(this, handle, n, nameLength, mapName); Library(this, handle, n, mapName);
return 0; return 0;
} else { } else {

View File

@ -214,21 +214,22 @@ encode(Context* c, uint8_t* instruction, unsigned length, int a, int b,
} }
void void
rex(Context* c) rex(Context* c, uint8_t mask, int r)
{ {
if (BytesPerWord == 8) { if (BytesPerWord == 8) {
c->code.append(0x48); c->code.append(mask | ((r & 8) >> 3));
} }
} }
void
rex(Context* c)
{
rex(c, 0x48, rax);
}
void void
encode(Context* c, uint8_t instruction, int a, Assembler::Memory* b, bool rex) encode(Context* c, uint8_t instruction, int a, Assembler::Memory* b, bool rex)
{ {
if (b->traceHandler) {
fprintf(stderr, "handle trace %p\n", b->traceHandler);
b->traceHandler->handleTrace(codePromise(c, c->code.length()));
}
if (rex) { if (rex) {
::rex(c); ::rex(c);
} }
@ -240,11 +241,6 @@ void
encode2(Context* c, uint16_t instruction, int a, Assembler::Memory* b, encode2(Context* c, uint16_t instruction, int a, Assembler::Memory* b,
bool rex) bool rex)
{ {
if (b->traceHandler) {
fprintf(stderr, "handle trace %p\n", b->traceHandler);
b->traceHandler->handleTrace(codePromise(c, c->code.length()));
}
if (rex) { if (rex) {
::rex(c); ::rex(c);
} }
@ -292,18 +288,31 @@ conditional(Context* c, unsigned condition, Assembler::Constant* a)
} }
void void
callC(Context* c, unsigned size UNUSED, Assembler::Constant* a) callC(Context* c, unsigned size, Assembler::Constant* a)
{ {
assert(c, size == BytesPerWord); assert(c, size == BytesPerWord);
unconditional(c, 0xe8, a); if (BytesPerWord == 8) {
Assembler::Register r(r10);
moveCR(c, size, a, &r);
callR(c, size, &r);
c->client->releaseTemporary(r.low);
} else {
unconditional(c, 0xe8, a);
}
} }
void void
alignedCallC(Context* c, unsigned size, Assembler::Constant* a) alignedCallC(Context* c, unsigned size, Assembler::Constant* a)
{ {
while ((c->code.length() + 1) % 4) { if (BytesPerWord == 8) {
c->code.append(0x90); while ((c->code.length() + 2) % 8) {
c->code.append(0x90);
}
} else {
while ((c->code.length() + 1) % 4) {
c->code.append(0x90);
}
} }
callC(c, size, a); callC(c, size, a);
} }
@ -313,6 +322,7 @@ callR(Context* c, unsigned size UNUSED, Assembler::Register* a)
{ {
assert(c, size == BytesPerWord); assert(c, size == BytesPerWord);
if (a->low & 8) rex(c, 0x40, a->low);
c->code.append(0xff); c->code.append(0xff);
c->code.append(0xd0 | a->low); c->code.append(0xd0 | a->low);
} }
@ -521,7 +531,7 @@ moveCR(Context* c, unsigned size UNUSED, Assembler::Constant* a,
{ {
assert(c, BytesPerWord == 8 or size == 4); // todo assert(c, BytesPerWord == 8 or size == 4); // todo
rex(c); rex(c, 0x48, b->low);
c->code.append(0xb8 | b->low); c->code.append(0xb8 | b->low);
if (a->value->resolved()) { if (a->value->resolved()) {
c->code.appendAddress(a->value->value()); c->code.appendAddress(a->value->value());
@ -1131,13 +1141,26 @@ class MyAssembler: public Assembler {
} }
virtual void updateCall(void* returnAddress, void* newTarget) { virtual void updateCall(void* returnAddress, void* newTarget) {
uint8_t* instruction = static_cast<uint8_t*>(returnAddress) - 5; if (BytesPerWord == 8) {
assert(&c, *instruction == 0xE8); uint8_t* instruction = static_cast<uint8_t*>(returnAddress) - 13;
assert(&c, reinterpret_cast<uintptr_t>(instruction + 1) % 4 == 0); assert(&c, instruction[0] == 0x49);
assert(&c, instruction[1] == 0xba);
assert(&c, instruction[10] == 0x41);
assert(&c, instruction[11] == 0xff);
assert(&c, instruction[12] == 0xd2);
assert(&c, reinterpret_cast<uintptr_t>(instruction + 2) % 8 == 0);
int32_t v = static_cast<uint8_t*>(newTarget) intptr_t v = reinterpret_cast<intptr_t>(newTarget);
- static_cast<uint8_t*>(returnAddress); memcpy(instruction + 2, &v, 8);
memcpy(instruction + 1, &v, 4); } else {
uint8_t* instruction = static_cast<uint8_t*>(returnAddress) - 5;
assert(&c, *instruction == 0xE8);
assert(&c, reinterpret_cast<uintptr_t>(instruction + 1) % 4 == 0);
int32_t v = static_cast<uint8_t*>(newTarget)
- static_cast<uint8_t*>(returnAddress);
memcpy(instruction + 1, &v, 4);
}
} }
virtual void dispose() { virtual void dispose() {

View File

@ -27,11 +27,9 @@ class Zone: public Allocator {
uint8_t data[0]; uint8_t data[0];
}; };
Zone(System* s, Allocator* allocator, bool executable, Zone(System* s, Allocator* allocator, unsigned minimumFootprint):
unsigned minimumFootprint):
s(s), s(s),
allocator(allocator), allocator(allocator),
executable(executable),
segment(0), segment(0),
position(0), position(0),
minimumFootprint(minimumFootprint < sizeof(Segment) ? 0 : minimumFootprint(minimumFootprint < sizeof(Segment) ? 0 :
@ -45,11 +43,11 @@ class Zone: public Allocator {
void dispose() { void dispose() {
for (Segment* seg = segment, *next; seg; seg = next) { for (Segment* seg = segment, *next; seg; seg = next) {
next = seg->next; next = seg->next;
allocator->free(seg, sizeof(Segment) + seg->size, executable); allocator->free(seg, sizeof(Segment) + seg->size);
} }
} }
bool ensure(unsigned space, bool executable) { bool ensure(unsigned space) {
if (segment == 0 or position + space > segment->size) { if (segment == 0 or position + space > segment->size) {
unsigned size = max unsigned size = max
(space, max (space, max
@ -60,10 +58,10 @@ class Zone: public Allocator {
size = (size + (LikelyPageSizeInBytes - 1)) size = (size + (LikelyPageSizeInBytes - 1))
& ~(LikelyPageSizeInBytes - 1); & ~(LikelyPageSizeInBytes - 1);
void* p = allocator->tryAllocate(size, executable); void* p = allocator->tryAllocate(size);
if (p == 0) { if (p == 0) {
size = space + sizeof(Segment); size = space + sizeof(Segment);
void* p = allocator->tryAllocate(size, executable); void* p = allocator->tryAllocate(size);
if (p == 0) { if (p == 0) {
return false; return false;
} }
@ -75,11 +73,9 @@ class Zone: public Allocator {
return true; return true;
} }
virtual void* tryAllocate(unsigned size, bool executable) { virtual void* tryAllocate(unsigned size) {
assert(s, executable == this->executable);
size = pad(size); size = pad(size);
if (ensure(size, executable)) { if (ensure(size)) {
void* r = segment->data + position; void* r = segment->data + position;
position += size; position += size;
return r; return r;
@ -88,27 +84,20 @@ class Zone: public Allocator {
} }
} }
virtual void* allocate(unsigned size, bool executable) { virtual void* allocate(unsigned size) {
assert(s, executable == this->executable); void* p = tryAllocate(size);
void* p = tryAllocate(size, executable);
expect(s, p); expect(s, p);
return p; return p;
} }
virtual void free(const void*, unsigned, bool) { virtual void free(const void*, unsigned) {
// not supported // not supported
abort(s); abort(s);
} }
void* allocate(unsigned size) {
return allocate(size, executable);
}
System* s; System* s;
Allocator* allocator; Allocator* allocator;
void* context; void* context;
bool executable;
Segment* segment; Segment* segment;
unsigned position; unsigned position;
unsigned minimumFootprint; unsigned minimumFootprint;

View File

@ -2,7 +2,22 @@ public class Misc {
private static int alpha; private static int alpha;
private static int beta; private static int beta;
private static byte byte1, byte2, byte3; private static byte byte1, byte2, byte3;
private int gamma; private int gamma;
private int pajama;
private boolean boolean1;
private boolean boolean2;
private long time;
public Misc() {
expect(! boolean1);
expect(! boolean2);
time = 0xffffffffffffffffL;
expect(! boolean1);
expect(! boolean2);
}
private String foo(String s) { private String foo(String s) {
return s; return s;