Merge branch 'master' into powerpc

Conflicts:

	makefile
	src/assembler.h
	src/compile.cpp
	src/compiler.cpp
	src/compiler.h
	src/finder.cpp
This commit is contained in:
Joel Dice 2008-11-11 08:20:49 -07:00
parent 2304a656cf
commit c80eb51c17
47 changed files with 1508 additions and 282 deletions

View File

@ -14,12 +14,14 @@
#include <errno.h> #include <errno.h>
#include <string.h> #include <string.h>
#include <stdlib.h> #include <stdlib.h>
#include <stdint.h>
#include <dirent.h> #include <dirent.h>
#include "jni.h" #include "jni.h"
#include "jni-util.h" #include "jni-util.h"
#ifdef WIN32 #ifdef WIN32
# include <windows.h>
# include <io.h> # include <io.h>
# define OPEN _open # define OPEN _open
@ -34,6 +36,7 @@
# define OPEN_MASK O_BINARY # define OPEN_MASK O_BINARY
#else #else
# include <unistd.h> # include <unistd.h>
# include "sys/mman.h"
# define OPEN open # define OPEN open
# define CLOSE close # define CLOSE close
@ -47,6 +50,8 @@
# define OPEN_MASK 0 # define OPEN_MASK 0
#endif #endif
inline void* operator new(size_t, void* p) throw() { return p; }
namespace { namespace {
inline bool inline bool
@ -95,9 +100,118 @@ doWrite(JNIEnv* e, jint fd, const jbyte* data, jint length)
int r = WRITE(fd, data, length); int r = WRITE(fd, data, length);
if (r != length) { if (r != length) {
throwNew(e, "java/io/IOException", strerror(errno)); throwNew(e, "java/io/IOException", strerror(errno));
} }
} }
#ifdef WIN32
class Mapping {
public:
Mapping(uint8_t* start, size_t length, HANDLE mapping, HANDLE file):
start(start),
length(length),
mapping(mapping),
file(file)
{ }
uint8_t* start;
size_t length;
HANDLE mapping;
HANDLE file;
};
inline Mapping*
map(JNIEnv* e, const char* path)
{
Mapping* result = 0;
HANDLE file = CreateFile(path, FILE_READ_DATA, FILE_SHARE_READ, 0,
OPEN_EXISTING, 0, 0);
if (file != INVALID_HANDLE_VALUE) {
unsigned size = GetFileSize(file, 0);
if (size != INVALID_FILE_SIZE) {
HANDLE mapping = CreateFileMapping(file, 0, PAGE_READONLY, 0, size, 0);
if (mapping) {
void* data = MapViewOfFile(mapping, FILE_MAP_READ, 0, 0, 0);
if (data) {
void* p = allocate(e, sizeof(Mapping));
if (not e->ExceptionOccurred()) {
result = new (p)
Mapping(static_cast<uint8_t*>(data), size, file, mapping);
}
}
if (result == 0) {
CloseHandle(mapping);
}
}
}
if (result == 0) {
CloseHandle(file);
}
}
if (result == 0 and not e->ExceptionOccurred()) {
throwNew(e, "java/io/IOException", "%d", GetLastError());
}
return result;
}
inline void
unmap(JNIEnv*, Mapping* mapping)
{
UnmapViewOfFile(mapping->start);
CloseHandle(mapping->mapping);
CloseHandle(mapping->file);
free(mapping);
}
#else // not WIN32
class Mapping {
public:
Mapping(uint8_t* start, size_t length):
start(start),
length(length)
{ }
uint8_t* start;
size_t length;
};
inline Mapping*
map(JNIEnv* e, const char* path)
{
Mapping* result = 0;
int fd = open(path, O_RDONLY);
if (fd != -1) {
struct stat s;
int r = fstat(fd, &s);
if (r != -1) {
void* data = mmap(0, s.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
if (data) {
void* p = allocate(e, sizeof(Mapping));
if (not e->ExceptionOccurred()) {
result = new (p) Mapping(static_cast<uint8_t*>(data), s.st_size);
}
}
}
close(fd);
}
if (result == 0 and not e->ExceptionOccurred()) {
throwNew(e, "java/io/IOException", strerror(errno));
}
return result;
}
inline void
unmap(JNIEnv*, Mapping* mapping)
{
munmap(mapping->start, mapping->length);
free(mapping);
}
#endif // not WIN32
} // namespace } // namespace
extern "C" JNIEXPORT jstring JNICALL extern "C" JNIEXPORT jstring JNICALL
@ -333,3 +447,42 @@ Java_java_io_FileOutputStream_close(JNIEnv* e, jclass, jint fd)
{ {
doClose(e, fd); doClose(e, fd);
} }
extern "C" JNIEXPORT void JNICALL
Java_java_io_RandomAccessFile_open(JNIEnv* e, jclass, jstring path,
jlongArray result)
{
const char* chars = e->GetStringUTFChars(path, 0);
if (chars) {
Mapping* mapping = map(e, chars);
jlong peer = reinterpret_cast<jlong>(mapping);
e->SetLongArrayRegion(result, 0, 1, &peer);
jlong length = (mapping ? mapping->length : 0);
e->SetLongArrayRegion(result, 1, 1, &length);
e->ReleaseStringUTFChars(path, chars);
}
}
extern "C" JNIEXPORT void JNICALL
Java_java_io_RandomAccessFile_copy(JNIEnv* e, jclass, jlong peer,
jlong position, jbyteArray buffer,
int offset, int length)
{
uint8_t* dst = reinterpret_cast<uint8_t*>
(e->GetPrimitiveArrayCritical(buffer, 0));
memcpy(dst + offset,
reinterpret_cast<Mapping*>(peer)->start + position,
length);
e->ReleasePrimitiveArrayCritical(buffer, dst, 0);
}
extern "C" JNIEXPORT void JNICALL
Java_java_io_RandomAccessFile_close(JNIEnv* e, jclass, jlong peer)
{
unmap(e, reinterpret_cast<Mapping*>(peer));
}

View File

@ -12,6 +12,7 @@
#include <sys/stat.h> #include <sys/stat.h>
#include <string.h> #include <string.h>
#include <stdlib.h> #include <stdlib.h>
#include <stdint.h>
#include <unistd.h> #include <unistd.h>
#include "jni.h" #include "jni.h"

View File

@ -24,6 +24,13 @@ public class ByteArrayOutputStream extends OutputStream {
this(0); this(0);
} }
public void reset() {
chain = null;
length = 0;
buffer = null;
position = 0;
}
public int size() { public int size() {
return length; return length;
} }

View File

@ -0,0 +1,72 @@
/* 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.io;
public class RandomAccessFile {
private long peer;
private long length;
private long position = 0;
public RandomAccessFile(String name, String mode)
throws FileNotFoundException
{
if (! mode.equals("r")) throw new IllegalArgumentException();
long[] result = new long[2];
open(name, result);
peer = result[0];
length = result[1];
}
private static native void open(String name, long[] result)
throws FileNotFoundException;
public long length() throws IOException {
return length;
}
public long getFilePointer() throws IOException {
return position;
}
public void seek(long position) throws IOException {
if (position < 0 || position > length) throw new IOException();
this.position = position;
}
public void readFully(byte[] buffer, int offset, int length)
throws IOException
{
if (peer == 0) throw new IOException();
if (length == 0) return;
if (position + length > this.length) throw new EOFException();
if (offset < 0 || offset + length > buffer.length)
throw new ArrayIndexOutOfBoundsException();
copy(peer, position, buffer, offset, length);
}
private static native void copy(long peer, long position, byte[] buffer,
int offset, int length);
public void close() throws IOException {
if (peer != 0) {
close(peer);
peer = 0;
}
}
private static native void close(long peer);
}

View File

@ -219,6 +219,25 @@ public final class Class <T> {
} }
} }
public Constructor getDeclaredConstructor(Class ... parameterTypes)
throws NoSuchMethodException
{
Constructor c = null;
Constructor[] constructors = getDeclaredConstructors();
for (int i = 0; i < constructors.length; ++i) {
if (match(parameterTypes, constructors[i].getParameterTypes())) {
c = constructors[i];
}
}
if (c == null) {
throw new NoSuchMethodException();
} else {
return c;
}
}
private int countConstructors(boolean publicOnly) { private int countConstructors(boolean publicOnly) {
int count = 0; int count = 0;
if (methodTable != null) { if (methodTable != null) {

View File

@ -30,6 +30,10 @@ public final class Integer extends Number implements Comparable<Integer> {
return new Integer(value); return new Integer(value);
} }
public static Integer valueOf(String value) {
return valueOf(parseInt(value));
}
public boolean equals(Object o) { public boolean equals(Object o) {
return o instanceof Integer && ((Integer) o).value == value; return o instanceof Integer && ((Integer) o).value == value;
} }

View File

@ -75,6 +75,8 @@ public class Runtime {
public native long totalMemory(); public native long totalMemory();
public static native void dumpHeap(String outputFile);
private static class MyProcess extends Process { private static class MyProcess extends Process {
private long pid; private long pid;
private final int in; private final int in;

View File

@ -74,7 +74,15 @@ public class StringBuffer implements CharSequence {
sb.append(b, 0, b.length); sb.append(b, 0, b.length);
return this; return this;
} }
public synchronized int indexOf(String s) {
return sb.indexOf(s);
}
public synchronized int indexOf(String s, int fromIndex) {
return sb.indexOf(s, fromIndex);
}
public synchronized StringBuffer insert(int i, String s) { public synchronized StringBuffer insert(int i, String s) {
sb.insert(i, s); sb.insert(i, s);
return this; return this;
@ -85,6 +93,11 @@ public class StringBuffer implements CharSequence {
return this; return this;
} }
public synchronized StringBuffer insert(int i, int v) {
sb.insert(i, v);
return this;
}
public synchronized StringBuffer delete(int start, int end) { public synchronized StringBuffer delete(int start, int end) {
sb.delete(start, end); sb.delete(start, end);
return this; return this;
@ -112,6 +125,10 @@ public class StringBuffer implements CharSequence {
sb.setLength(v); sb.setLength(v);
} }
public synchronized void setCharAt(int index, char ch) {
sb.setCharAt(index, ch);
}
public synchronized void getChars(int srcOffset, int srcLength, char[] dst, public synchronized void getChars(int srcOffset, int srcLength, char[] dst,
int dstOffset) int dstOffset)
{ {

View File

@ -154,6 +154,10 @@ public class StringBuilder implements CharSequence {
return insert(i, new String(new char[] { c }, 0, 1, false)); return insert(i, new String(new char[] { c }, 0, 1, false));
} }
public StringBuilder insert(int i, int v) {
return insert(i, String.valueOf(v));
}
public StringBuilder delete(int start, int end) { public StringBuilder delete(int start, int end) {
if (start >= end) { if (start >= end) {
return this; return this;
@ -322,4 +326,10 @@ public class StringBuilder implements CharSequence {
public CharSequence subSequence(int start, int end) { public CharSequence subSequence(int start, int end) {
return substring(start, end); return substring(start, end);
} }
public void setCharAt(int index, char ch) {
if(index < 0 || index >= length) throw new IndexOutOfBoundsException();
deleteCharAt(index);
insert(index, ch);
}
} }

View File

@ -111,8 +111,8 @@ public class Method<T> extends AccessibleObject implements Member {
} }
} }
public static native Object invoke(Method method, Object instance, private static native Object invoke(Method method, Object instance,
Object ... arguments) Object ... arguments)
throws InvocationTargetException, IllegalAccessException; throws InvocationTargetException, IllegalAccessException;
public Class getReturnType() { public Class getReturnType() {

View File

@ -45,6 +45,12 @@ public abstract class Calendar {
fields[field] = value; fields[field] = value;
} }
public void set(int year, int month, int date) {
set(YEAR, year);
set(MONTH, month);
set(DAY_OF_MONTH, date);
}
public void setTime(Date date) { public void setTime(Date date) {
time = date.getTime(); time = date.getTime();
} }

View File

@ -11,7 +11,7 @@
package java.util; package java.util;
public class Locale { public class Locale {
public static final Locale ENGLISH = new Locale("en"); public static final Locale ENGLISH = new Locale("en", "us");
private final String language; private final String language;
private final String country; private final String country;

View File

@ -23,4 +23,8 @@ public class PropertyResourceBundle extends ResourceBundle {
public Object handleGetObject(String key) { public Object handleGetObject(String key) {
return map.get(key); return map.get(key);
} }
public Enumeration<String> getKeys() {
return map.keys();
}
} }

View File

@ -58,6 +58,21 @@ public class Random {
return next(32); return next(32);
} }
public void nextBytes(byte[] bytes) {
final int length = bytes.length;
for (int i = 0; i < length;) {
int r = nextInt();
for (int j = Math.min(length - i, 4); j > 0; --j) {
bytes[i++] = (byte) r;
r >>= 8;
}
}
}
public long nextLong() {
return ((long) next(32) << 32) + next(32);
}
public double nextDouble() { public double nextDouble() {
return (((long) next(26) << 27) + next(27)) / (double) (1L << 53); return (((long) next(26) << 27) + next(27)) / (double) (1L << 53);
} }

View File

@ -118,4 +118,6 @@ public abstract class ResourceBundle {
} }
protected abstract Object handleGetObject(String key); protected abstract Object handleGetObject(String key);
public abstract Enumeration<String> getKeys();
} }

View File

@ -12,7 +12,7 @@ package java.util;
public class Stack<T> extends Vector<T> { public class Stack<T> extends Vector<T> {
public boolean empty() { public boolean empty() {
return size() != 0; return size() == 0;
} }
public T peek() { public T peek() {

View File

@ -61,8 +61,8 @@ public class Vector<T> implements List<T> {
return list.set(index, value); return list.set(index, value);
} }
public T setElementAt(T value, int index) { public void setElementAt(T value, int index) {
return set(index, value); set(index, value);
} }
public T elementAt(int index) { public T elementAt(int index) {

View File

@ -0,0 +1,16 @@
/* 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.util.zip;
public abstract class ZipEntry {
public abstract String getName();
public abstract int getCompressedSize();
}

View File

@ -0,0 +1,313 @@
/* 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.util.zip;
import java.io.File;
import java.io.RandomAccessFile;
import java.io.InputStream;
import java.io.IOException;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.Map;
import java.util.HashMap;
public class ZipFile {
private final RandomAccessFile file;
private final Window window;
private final Map<String,Integer> index = new HashMap();
public ZipFile(String name) throws IOException {
file = new RandomAccessFile(name, "r");
window = new Window(file, 4096);
int fileLength = (int) file.length();
int pointer = fileLength - 22;
byte[] magic = new byte[] { 0x50, 0x4B, 0x05, 0x06 };
while (pointer > 0) {
if (equal(window.data, window.seek(pointer, magic.length),
magic, 0, magic.length))
{
pointer = directoryOffset(window, pointer);
magic = new byte[] { 0x50, 0x4B, 0x01, 0x02 };
while (pointer < fileLength) {
if (equal(window.data, window.seek(pointer, magic.length),
magic, 0, magic.length))
{
index.put(entryName(window, pointer), pointer);
pointer = entryEnd(window, pointer);
} else {
pointer = fileLength;
}
}
pointer = 0;
} else {
-- pointer;
}
}
}
public ZipFile(File file) throws IOException {
this(file.getAbsolutePath());
}
public int size() {
return index.size();
}
public Enumeration<ZipEntry> entries() {
return new MyEnumeration(window, index.values().iterator());
}
public ZipEntry getEntry(String name) {
Integer pointer = index.get(name);
return (pointer == null ? null : new MyZipEntry(window, pointer));
}
public InputStream getInputStream(ZipEntry entry) throws IOException {
int pointer = ((MyZipEntry) entry).pointer;
int method = compressionMethod(window, pointer);
int size = compressedSize(window, pointer);
InputStream in = new MyInputStream(file, fileData(window, pointer), size);
final int Stored = 0;
final int Deflated = 8;
switch (method) {
case Stored:
return in;
case Deflated:
return new InflaterInputStream(in, new Inflater(true));
default:
throw new IOException();
}
}
private static boolean equal(byte[] a, int aOffset, byte[] b, int bOffset,
int size)
{
for (int i = 0; i < size; ++i) {
if (a[aOffset + i] != b[bOffset + i]) return false;
}
return true;
}
private static int get2(Window w, int p) throws IOException {
int offset = w.seek(p, 2);
return
((w.data[offset + 1] & 0xFF) << 8) |
((w.data[offset ] & 0xFF) );
}
private static int get4(Window w, int p) throws IOException {
int offset = w.seek(p, 4);
return
((w.data[offset + 3] & 0xFF) << 24) |
((w.data[offset + 2] & 0xFF) << 16) |
((w.data[offset + 1] & 0xFF) << 8) |
((w.data[offset ] & 0xFF) );
}
private static int directoryOffset(Window w, int p) throws IOException {
return get4(w, p + 16);
}
private static int entryNameLength(Window w, int p) throws IOException {
return get2(w, p + 28);
}
private static String entryName(Window w, int p) throws IOException {
int length = entryNameLength(w, p);
return new String(w.data, w.seek(p + 46, length), length);
}
private static int compressionMethod(Window w, int p) throws IOException {
return get2(w, p + 10);
}
private static int compressedSize(Window w, int p) throws IOException {
return get4(w, p + 20);
}
private static int fileNameLength(Window w, int p) throws IOException {
return get2(w, p + 28);
}
private static int extraFieldLength(Window w, int p) throws IOException {
return get2(w, p + 30);
}
private static int commentFieldLength(Window w, int p) throws IOException {
return get2(w, p + 32);
}
private static int entryEnd(Window w, int p) throws IOException {
final int HeaderSize = 46;
return p + HeaderSize
+ fileNameLength(w, p)
+ extraFieldLength(w, p)
+ commentFieldLength(w, p);
}
private static int fileData(Window w, int p) throws IOException {
int localHeader = localHeader(w, p);
final int LocalHeaderSize = 30;
return localHeader
+ LocalHeaderSize
+ localFileNameLength(w, localHeader)
+ localExtraFieldLength(w, localHeader);
}
private static int localHeader(Window w, int p) throws IOException {
return get4(w, p + 42);
}
private static int localFileNameLength(Window w, int p) throws IOException {
return get2(w, p + 26);
}
private static int localExtraFieldLength(Window w, int p)
throws IOException
{
return get2(w, p + 28);
}
public void close() throws IOException {
file.close();
}
private static class Window {
private final RandomAccessFile file;
public final byte[] data;
public int start;
public int length;
public Window(RandomAccessFile file, int size) {
this.file = file;
data = new byte[size];
}
public int seek(int start, int length) throws IOException {
int fileLength = (int) file.length();
if (length > data.length) {
throw new IllegalArgumentException
("length " + length + " greater than buffer length " + data.length);
}
if (start < 0) {
throw new IllegalArgumentException("negative start " + start);
}
if (start + length > fileLength) {
throw new IllegalArgumentException
("end " + (start + length) + " greater than file length " +
fileLength);
}
if (start < this.start || start + length > this.start + this.length) {
this.length = Math.min(data.length, fileLength);
this.start = start - ((this.length - length) / 2);
if (this.start < 0) {
this.start = 0;
} else if (this.start + this.length > fileLength) {
this.start = fileLength - this.length;
}
file.seek(this.start);
file.readFully(data, 0, this.length);
}
return start - this.start;
}
}
private static class MyZipEntry extends ZipEntry {
public final Window window;
public final int pointer;
public MyZipEntry(Window window, int pointer) {
this.window = window;
this.pointer = pointer;
}
public String getName() {
try {
return entryName(window, pointer);
} catch (IOException e) {
return null;
}
}
public int getCompressedSize() {
try {
return compressedSize(window, pointer);
} catch (IOException e) {
return 0;
}
}
}
private static class MyEnumeration implements Enumeration<ZipEntry> {
private final Window window;
private final Iterator<Integer> iterator;
public MyEnumeration(Window window, Iterator<Integer> iterator) {
this.window = window;
this.iterator = iterator;
}
public boolean hasMoreElements() {
return iterator.hasNext();
}
public ZipEntry nextElement() {
return new MyZipEntry(window, iterator.next());
}
}
private static class MyInputStream extends InputStream {
private RandomAccessFile file;
private int offset;
private int length;
public MyInputStream(RandomAccessFile file, int start, int length) {
this.file = file;
this.offset = start;
this.length = length;
}
public int read() throws IOException {
byte[] b = new byte[1];
int c = read(b);
return (c == -1 ? -1 : b[0] & 0xFF);
}
public int read(byte[] b, int offset, int length) throws IOException {
if (this.length == 0) return -1;
if (length > this.length) length = this.length;
file.seek(this.offset);
file.readFully(b, offset, length);
this.offset += length;
this.length -= length;
return length;
}
public void close() throws IOException {
file = null;
}
}
}

View File

@ -11,6 +11,9 @@
#ifndef JNI_UTIL #ifndef JNI_UTIL
#define JNI_UTIL #define JNI_UTIL
#include "stdio.h"
#include "stdlib.h"
#undef JNIEXPORT #undef JNIEXPORT
#ifdef __MINGW32__ #ifdef __MINGW32__
# define JNIEXPORT __declspec(dllexport) # define JNIEXPORT __declspec(dllexport)
@ -23,15 +26,37 @@
namespace { namespace {
inline void inline void
throwNew(JNIEnv* e, const char* class_, const char* message) throwNew(JNIEnv* e, const char* class_, const char* message, ...)
{ {
jclass c = e->FindClass(class_); jclass c = e->FindClass(class_);
if (c) { if (c) {
e->ThrowNew(c, message); if (message) {
static const unsigned BufferSize = 256;
char buffer[BufferSize];
va_list list;
va_start(list, message);
vsnprintf(buffer, BufferSize - 1, message, list);
va_end(list);
e->ThrowNew(c, buffer);
} else {
e->ThrowNew(c, 0);
}
e->DeleteLocalRef(c); e->DeleteLocalRef(c);
} }
} }
inline void*
allocate(JNIEnv* e, unsigned size)
{
void* p = malloc(size);
if (p == 0) {
throwNew(e, "java/lang/OutOfMemoryError", 0);
}
return p;
}
} // namespace } // namespace
#endif//JNI_UTIL #endif//JNI_UTIL

104
makefile
View File

@ -3,21 +3,18 @@ MAKEFLAGS = -s
name = avian name = avian
version = 0.1.1 version = 0.1.1
build-arch = $(shell uname -m) build-arch = $(shell uname -m | sed 's/^i.86$$/i386/')
ifeq ($(build-arch),Power) ifeq ($(build-arch),Power)
build-arch = powerpc build-arch = powerpc
endif endif
ifeq ($(build-arch),i586)
build-arch = i386
endif
ifeq ($(build-arch),i686)
build-arch = i386
endif
build-platform = $(shell uname -s | tr [:upper:] [:lower:]) build-platform = \
$(shell uname -s | tr [:upper:] [:lower:] \
| sed 's/^mingw32.*$$/mingw32/' \
| sed 's/^cygwin.*$$/cygwin/')
arch = $(build-arch) arch = $(build-arch)
platform = $(build-platform) platform = $(subst cygwin,windows,$(subst mingw32,windows,$(build-platform)))
ifeq ($(platform),windows) ifeq ($(platform),windows)
arch = i386 arch = i386
@ -44,31 +41,38 @@ cxx = $(build-cxx)
cc = $(build-cc) cc = $(build-cc)
ar = ar ar = ar
ranlib = ranlib ranlib = ranlib
dlltool = dlltool
objcopy = objcopy objcopy = objcopy
vg = nice valgrind --num-callers=32 --db-attach=yes --freelist-vol=100000000 vg = nice valgrind --num-callers=32 --db-attach=yes --freelist-vol=100000000
vg += --leak-check=full --suppressions=valgrind.supp vg += --leak-check=full --suppressions=valgrind.supp
db = gdb --args db = gdb --args
javac = javac javac = "$(JAVA_HOME)/bin/javac"
jar = jar jar = "$(JAVA_HOME)/bin/jar"
strip = : strip = :
strip-all = --strip-all strip-all = --strip-all
rdynamic = -rdynamic rdynamic = -rdynamic
warnings = -Wall -Wextra -Werror -Wunused-parameter -Winit-self # note that we supress the non-virtual-dtor warning because we never
# use the delete operator, which means we don't need virtual
# destructors:
warnings = -Wall -Wextra -Werror -Wunused-parameter -Winit-self \
-Wno-non-virtual-dtor
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]\" -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
cflags = $(build-cflags) cflags = $(build-cflags)
common-lflags = -lm -lz common-lflags = -lm -lz
build-lflags =
lflags = $(common-lflags) -lpthread -ldl lflags = $(common-lflags) -lpthread -ldl
system = posix system = posix
@ -83,6 +87,8 @@ so-suffix = .so
shared = -shared shared = -shared
native-path = echo
ifeq ($(arch),i386) ifeq ($(arch),i386)
object-arch = i386 object-arch = i386
object-format = elf32-i386 object-format = elf32-i386
@ -96,8 +102,7 @@ ifeq ($(arch),powerpc)
endif endif
ifeq ($(platform),darwin) ifeq ($(platform),darwin)
build-cflags = $(common-cflags) -fPIC -fvisibility=hidden \ build-cflags = $(common-cflags) -fPIC -fvisibility=hidden -I$(src)
-I$(JAVA_HOME)/include/linux -I$(src)
lflags = $(common-lflags) -ldl -framework CoreFoundation lflags = $(common-lflags) -ldl -framework CoreFoundation
rdynamic = rdynamic =
strip-all = -S -x strip-all = -S -x
@ -107,25 +112,37 @@ ifeq ($(platform),darwin)
endif endif
ifeq ($(platform),windows) ifeq ($(platform),windows)
inc = $(root)/win32/include inc = "$(root)/win32/include"
lib = $(root)/win32/lib lib = "$(root)/win32/lib"
system = windows system = windows
object-format = pe-i386 object-format = pe-i386
so-prefix = so-prefix =
so-suffix = .dll so-suffix = .dll
exe-suffix = .exe
cxx = i586-mingw32msvc-g++
cc = i586-mingw32msvc-gcc
dlltool = i586-mingw32msvc-dlltool
ar = i586-mingw32msvc-ar
ranlib = i586-mingw32msvc-ranlib
objcopy = i586-mingw32msvc-objcopy
rdynamic = -Wl,--export-dynamic
lflags = -L$(lib) $(common-lflags) -lws2_32 -mwindows -mconsole lflags = -L$(lib) $(common-lflags) -lws2_32 -mwindows -mconsole
cflags = $(common-cflags) -I$(inc) cflags = $(common-cflags) -I$(inc)
ifeq (,$(filter mingw32 cygwin,$(build-platform)))
cxx = i586-mingw32msvc-g++
cc = i586-mingw32msvc-gcc
dlltool = i586-mingw32msvc-dlltool
ar = i586-mingw32msvc-ar
ranlib = i586-mingw32msvc-ranlib
objcopy = i586-mingw32msvc-objcopy
else
build-cflags = $(common-cflags) \
"-I$(JAVA_HOME)/include/win32" -I$(src) -mthreads
ifeq ($(build-platform),cygwin)
build-lflags += -mno-cygwin
build-cflags += -mno-cygwin
lflags += -mno-cygwin
cflags += -mno-cygwin
native-path = cygpath -m
endif
endif
endif endif
ifeq ($(mode),debug) ifeq ($(mode),debug)
@ -144,6 +161,10 @@ ifeq ($(mode),fast)
cflags += -O3 -g3 -DNDEBUG cflags += -O3 -g3 -DNDEBUG
strip = strip strip = strip
endif endif
ifeq ($(mode),small)
cflags += -Os -g3 -DNDEBUG
strip = strip
endif
cpp-objects = $(foreach x,$(1),$(patsubst $(2)/%.cpp,$(3)/%.o,$(x))) cpp-objects = $(foreach x,$(1),$(patsubst $(2)/%.cpp,$(3)/%.o,$(x)))
asm-objects = $(foreach x,$(1),$(patsubst $(2)/%.S,$(3)/%-asm.o,$(x))) asm-objects = $(foreach x,$(1),$(patsubst $(2)/%.S,$(3)/%-asm.o,$(x)))
@ -190,6 +211,11 @@ vm-sources = \
$(src)/process.cpp \ $(src)/process.cpp \
$(src)/$(asm).cpp $(src)/$(asm).cpp
ifeq ($(heapdump),true)
vm-sources += $(src)/heapdump.cpp
cflags += -DAVIAN_HEAPDUMP
endif
vm-asm-sources = $(src)/$(asm).S vm-asm-sources = $(src)/$(asm).S
ifeq ($(process),compile) ifeq ($(process),compile)
@ -220,9 +246,9 @@ generator-objects = \
generator = $(native-build)/generator generator = $(native-build)/generator
static-library = $(native-build)/lib$(name).a static-library = $(native-build)/lib$(name).a
executable = $(native-build)/$(name) executable = $(native-build)/$(name)${exe-suffix}
dynamic-library = $(native-build)/$(so-prefix)$(name)$(so-suffix) dynamic-library = $(native-build)/$(so-prefix)$(name)$(so-suffix)
executable-dynamic = $(native-build)/$(name)-dynamic executable-dynamic = $(native-build)/$(name)-dynamic${exe-suffix}
classpath-sources = $(shell find $(classpath) -name '*.java') classpath-sources = $(shell find $(classpath) -name '*.java')
classpath-classes = \ classpath-classes = \
@ -261,7 +287,7 @@ vg: build
.PHONY: test .PHONY: test
test: build test: build
/bin/bash $(test)/test.sh 2>/dev/null \ /bin/sh $(test)/test.sh 2>/dev/null \
$(executable) $(mode) "$(flags)" \ $(executable) $(mode) "$(flags)" \
$(call class-names,$(test-build),$(test-classes)) $(call class-names,$(test-build),$(test-classes))
@ -299,7 +325,7 @@ $(classpath-dep): $(classpath-sources)
@echo "compiling classpath classes" @echo "compiling classpath classes"
@mkdir -p $(dir $(@)) @mkdir -p $(dir $(@))
$(javac) -d $(dir $(@)) -bootclasspath $(classpath-build) \ $(javac) -d $(dir $(@)) -bootclasspath $(classpath-build) \
$(shell make -s --no-print-directory $(classpath-classes)) $(shell $(MAKE) -s --no-print-directory $(classpath-classes))
@touch $(@) @touch $(@)
$(test-build)/%.class: $(test)/%.java $(test-build)/%.class: $(test)/%.java
@ -309,7 +335,7 @@ $(test-dep): $(test-sources)
@echo "compiling test classes" @echo "compiling test classes"
@mkdir -p $(dir $(@)) @mkdir -p $(dir $(@))
$(javac) -d $(dir $(@)) -bootclasspath $(classpath-build) \ $(javac) -d $(dir $(@)) -bootclasspath $(classpath-build) \
$(shell make -s --no-print-directory $(test-classes)) $(shell $(MAKE) -s --no-print-directory $(test-classes))
@touch $(@) @touch $(@)
define compile-object define compile-object
@ -318,11 +344,17 @@ define compile-object
$(cxx) $(cflags) -c $(<) -o $(@) $(cxx) $(cflags) -c $(<) -o $(@)
endef endef
define compile-asm-object
@echo "compiling $(@)"
@mkdir -p $(dir $(@))
$(cc) -I$(src) -c $(<) -o $(@)
endef
$(vm-cpp-objects): $(native-build)/%.o: $(src)/%.cpp $(vm-depends) $(vm-cpp-objects): $(native-build)/%.o: $(src)/%.cpp $(vm-depends)
$(compile-object) $(compile-object)
$(vm-asm-objects): $(native-build)/%-asm.o: $(src)/%.S $(vm-asm-objects): $(native-build)/%-asm.o: $(src)/%.S
$(compile-object) $(compile-asm-object)
$(driver-object): $(driver-source) $(driver-object): $(driver-source)
$(compile-object) $(compile-object)
@ -339,7 +371,7 @@ $(boot-object): $(boot-source)
$(build)/classpath.jar: $(classpath-dep) $(build)/classpath.jar: $(classpath-dep)
(wd=$$(pwd); \ (wd=$$(pwd); \
cd $(classpath-build); \ cd $(classpath-build); \
$(jar) c0f $${wd}/$(@) $$(find . -name '*.class')) $(jar) c0f "$$($(native-path) "$${wd}/$(@)")" $$(find . -name '*.class'))
$(binaryToMacho): $(src)/binaryToMacho.cpp $(binaryToMacho): $(src)/binaryToMacho.cpp
$(cxx) $(^) -o $(@) $(cxx) $(^) -o $(@)
@ -353,7 +385,7 @@ else
(wd=$$(pwd); \ (wd=$$(pwd); \
cd $(build); \ cd $(build); \
$(objcopy) -I binary classpath.jar \ $(objcopy) -I binary classpath.jar \
-O $(object-format) -B $(object-arch) $${wd}/$(@)) -O $(object-format) -B $(object-arch) "$${wd}/$(@)")
endif endif
$(generator-objects): $(native-build)/%.o: $(src)/%.cpp $(generator-objects): $(native-build)/%.o: $(src)/%.cpp
@ -377,7 +409,7 @@ $(executable): \
@echo "linking $(@)" @echo "linking $(@)"
ifeq ($(platform),windows) ifeq ($(platform),windows)
$(dlltool) -z $(@).def $(^) $(dlltool) -z $(@).def $(^)
$(dlltool) -k -d $(@).def -e $(@).exp $(dlltool) -d $(@).def -e $(@).exp
$(cc) $(@).exp $(^) $(lflags) -o $(@) $(cc) $(@).exp $(^) $(lflags) -o $(@)
else else
$(cc) $(^) $(rdynamic) $(lflags) -o $(@) $(cc) $(^) $(rdynamic) $(lflags) -o $(@)
@ -398,5 +430,5 @@ $(executable-dynamic): $(driver-dynamic-object) $(dynamic-library)
$(generator): $(generator-objects) $(generator): $(generator-objects)
@echo "linking $(@)" @echo "linking $(@)"
$(build-cc) $(^) -o $(@) $(build-cc) $(^) $(build-lflags) -o $(@)

View File

@ -10,6 +10,21 @@ on Mac OS X:
$ export JAVA_HOME=/Library/Java/Home $ export JAVA_HOME=/Library/Java/Home
$ make $ make
$ build/darwin-i386-compile-fast/avian -cp build/test Hello $ build/darwin-i386-compile-fast/avian -cp build/test Hello
on Windows (MSYS):
$ export JAVA_HOME="C:/Program Files/Java/jdk1.6.0_07"
$ make
$ build/windows-i386-compile-fast/avian -cp build/test Hello
on Windows (Cygwin):
$ export JAVA_HOME="/cygdrive/c/Program Files/Java/jdk1.6.0_07"
$ make
$ build/windows-i386-compile-fast/avian -cp build/test Hello
Adjust JAVA_HOME according to your system, but be sure to use forward
slashes in the path.
Introduction Introduction
@ -40,10 +55,6 @@ Avian can currently target the following platforms:
Win32 (i386) Win32 (i386)
Mac OS X (i386) Mac OS X (i386)
The Win32 port may be built on Linux using a MinGW cross compiler and
build environment. Builds on MSYS or Cygwin are not yet supported,
but patches to enable them are welcome.
Building Building
-------- --------
@ -60,20 +71,11 @@ Build requirements include:
Earlier versions of some of these packages may also work but have not Earlier versions of some of these packages may also work but have not
been tested. been tested.
If you are cross-compiling for Windows, you may find it useful to use
our win32 repository: (run this from the directory containing the
avian directory)
$ git clone git://oss.readytalk.com/win32.git
This gives you the Windows JNI headers, zlib headers and library, and
a few other useful libraries like OpenSSL and libjpeg.
The build is directed by a single makefile and may be influenced via The build is directed by a single makefile and may be influenced via
certain flags described below. certain flags described below.
$ make platform={linux,windows,darwin} arch={i386,x86_64} \ $ make platform={linux,windows,darwin} arch={i386,x86_64} \
process={compile,interpret} mode={debug,debug-fast,fast} process={compile,interpret} mode={debug,debug-fast,fast,small}
* platform - the target platform * platform - the target platform
default: output of $(uname -s | tr [:upper:] [:lower:]) default: output of $(uname -s | tr [:upper:] [:lower:])
@ -89,6 +91,33 @@ certain flags described below.
* process - choice between pure interpreter or JIT compiler * process - choice between pure interpreter or JIT compiler
default: compile default: compile
If you are compiling for Windows, you may either cross-compile using
MinGW or build natively on Windows under MSYS or Cygwin.
Installing MSYS:
1. Download and install the current MinGW and MSYS packages from
mingw.org, selecting the C and C++ compilers when prompted. Use the
post-install script to create the filesystem link to the compiler.
2. Download GNU Make 3.81 from the MSYS download page
(make-3.81-MSYS-1.0.11-2.tar.bz2) and extract the tar file into
e.g. c:/msys/1.0.
Installing Cygwin:
1. Download and run setup.exe from cygwin.com, installing the base
system and these packages: make, gcc-mingw-g++, and (optionally)
git.
You may also find our win32 repository useful: (run this from the
directory containing the avian directory)
$ git clone git://oss.readytalk.com/win32.git
This gives you the Windows JNI headers, zlib headers and library, and
a few other useful libraries like OpenSSL and libjpeg.
Installing Installing
---------- ----------
@ -102,6 +131,9 @@ Embedding
The following series of commands illustrates how to produce a The following series of commands illustrates how to produce a
stand-alone executable out of a Java application using Avian. stand-alone executable out of a Java application using Avian.
Note: if you are building on Cygwin, add -mno-cygwin to each of the
compile and link commands below.
Step 1: Build Avian, create a new directory, and populate it with the Step 1: Build Avian, create a new directory, and populate it with the
VM object files and bootstrap classpath jar. VM object files and bootstrap classpath jar.
@ -223,7 +255,17 @@ main(int ac, const char** av)
return exitCode; return exitCode;
} }
EOF EOF
$ g++ -I$JAVA_HOME/include -c main.cpp -o main.o
on Linux:
$ g++ -I$JAVA_HOME/include -I$JAVA_HOME/include/linux \
-D_JNI_IMPLEMENTATION_ -c main.cpp -o main.o
on Mac OS X:
$ g++ -I$JAVA_HOME/include -D_JNI_IMPLEMENTATION_ -c main.cpp -o main.o
on Windows:
$ g++ -I$JAVA_HOME/include -I$JAVA_HOME/include/win32 \
-D_JNI_IMPLEMENTATION_ -c main.cpp -o main.o
Step 5: Link the objects produced above to produce the final Step 5: Link the objects produced above to produce the final
@ -237,3 +279,9 @@ on Mac OS X:
$ g++ -rdynamic *.o -ldl -lpthread -lz -o hello -framework CoreFoundation $ g++ -rdynamic *.o -ldl -lpthread -lz -o hello -framework CoreFoundation
$ strip -S -x hello $ strip -S -x hello
on Windows:
$ dlltool -z hello.def *.o
$ dlltool -d hello.def -e hello.exp
$ g++ hello.exp *.o -L../../win32/lib -lmingwthrd -lm -lz -lws2_32 \
-mwindows -mconsole -o hello.exe
$ strip --strip-all hello.exe

View File

@ -17,7 +17,6 @@ namespace vm {
class Allocator { class Allocator {
public: public:
virtual ~Allocator() { }
virtual void* tryAllocate(unsigned size) = 0; virtual void* tryAllocate(unsigned size) = 0;
virtual void* allocate(unsigned size) = 0; virtual void* allocate(unsigned size) = 0;
virtual void free(const void* p, unsigned size) = 0; virtual void free(const void* p, unsigned size) = 0;

View File

@ -78,8 +78,6 @@ const int NoRegister = -1;
class Promise { class Promise {
public: public:
virtual ~Promise() { }
virtual int64_t value() = 0; virtual int64_t value() = 0;
virtual bool resolved() = 0; virtual bool resolved() = 0;
}; };
@ -101,8 +99,6 @@ class ResolvedPromise: public Promise {
class TraceHandler { class TraceHandler {
public: public:
virtual ~TraceHandler() { }
virtual void handleTrace(Promise* address, unsigned padIndex, virtual void handleTrace(Promise* address, unsigned padIndex,
unsigned padding) = 0; unsigned padding) = 0;
}; };
@ -147,8 +143,6 @@ class Assembler {
class Client { class Client {
public: public:
virtual ~Client() { }
virtual int acquireTemporary virtual int acquireTemporary
(uint32_t mask = ~static_cast<uint32_t>(0)) = 0; (uint32_t mask = ~static_cast<uint32_t>(0)) = 0;
virtual void releaseTemporary(int r) = 0; virtual void releaseTemporary(int r) = 0;
@ -159,15 +153,11 @@ class Assembler {
class Block { class Block {
public: public:
virtual ~Block() { }
virtual unsigned resolve(unsigned start, Block* next) = 0; virtual unsigned resolve(unsigned start, Block* next) = 0;
}; };
class Architecture { class Architecture {
public: public:
virtual ~Architecture() { }
virtual unsigned registerCount() = 0; virtual unsigned registerCount() = 0;
virtual int stack() = 0; virtual int stack() = 0;
@ -214,8 +204,6 @@ class Assembler {
virtual void release() = 0; virtual void release() = 0;
}; };
virtual ~Assembler() { }
virtual void setClient(Client* client) = 0; virtual void setClient(Client* client) = 0;
virtual Architecture* arch() = 0; virtual Architecture* arch() = 0;

View File

@ -11,10 +11,9 @@
#include "stdint.h" #include "stdint.h"
#include "stdlib.h" #include "stdlib.h"
// since we don't link against libstdc++, we must implement some dummy // since we aren't linking against libstdc++, we must implement this
// functions: // ourselves:
extern "C" void __cxa_pure_virtual(void) { abort(); } extern "C" void __cxa_pure_virtual(void) { abort(); }
void operator delete(void*) { abort(); }
#ifdef __MINGW32__ #ifdef __MINGW32__
# define EXPORT __declspec(dllexport) # define EXPORT __declspec(dllexport)

View File

@ -456,6 +456,13 @@ Java_java_lang_System_getVMProperty(Thread* t, jclass, jstring name,
r = makeLocalReference(t, makeString(t, "%s", t->m->finder->path())); r = makeLocalReference(t, makeString(t, "%s", t->m->finder->path()));
} else if (strcmp(n, "avian.version") == 0) { } else if (strcmp(n, "avian.version") == 0) {
r = makeLocalReference(t, makeString(t, AVIAN_VERSION)); r = makeLocalReference(t, makeString(t, AVIAN_VERSION));
} else if (strcmp(n, "file.encoding") == 0) {
r = makeLocalReference(t, makeString(t, "ASCII"));
} else {
const char* v = findProperty(t, n);
if (v) {
r = makeLocalReference(t, makeString(t, v));
}
} }
if (r) { if (r) {
@ -536,8 +543,9 @@ Java_java_lang_Runtime_load(Thread* t, jclass, jstring name, jboolean mapName)
char n[length + 1]; char n[length + 1];
stringChars(t, *name, n); stringChars(t, *name, n);
if (mapName and t->m->builtins) { const char* builtins = findProperty(t, "avian.builtins");
const char* s = t->m->builtins; if (mapName and builtins) {
const char* s = builtins;
while (*s) { while (*s) {
if (strncmp(s, n, length) == 0 if (strncmp(s, n, length) == 0
and (s[length] == ',' or s[length] == 0)) and (s[length] == ',' or s[length] == 0))
@ -578,6 +586,30 @@ Java_java_lang_Runtime_gc(Thread* t, jobject)
collect(t, Heap::MajorCollection); collect(t, Heap::MajorCollection);
} }
#ifdef AVIAN_HEAPDUMP
extern "C" JNIEXPORT void JNICALL
Java_java_lang_Runtime_dumpHeap(Thread* t, jclass, jstring outputFile)
{
ENTER(t, Thread::ActiveState);
unsigned length = stringLength(t, *outputFile);
char n[length + 1];
stringChars(t, *outputFile, n);
FILE* out = fopen(n, "wb");
if (out) {
{ ENTER(t, Thread::ExclusiveState);
dumpHeap(t, out);
}
fclose(out);
} else {
object message = makeString(t, "file not found: %s", n);
t->exception = makeRuntimeException(t, message);
}
}
#endif//AVIAN_HEAPDUMP
extern "C" JNIEXPORT void JNICALL extern "C" JNIEXPORT void JNICALL
Java_java_lang_Runtime_exit(Thread* t, jobject, jint code) Java_java_lang_Runtime_exit(Thread* t, jobject, jint code)
{ {

View File

@ -27,7 +27,7 @@ vmCall();
namespace { namespace {
const bool Verbose = true; const bool DebugCompile = true;
const bool DebugNatives = false; const bool DebugNatives = false;
const bool DebugCallTable = false; const bool DebugCallTable = false;
const bool DebugMethodTree = false; const bool DebugMethodTree = false;
@ -2387,7 +2387,8 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip,
} break; } break;
case goto_: { case goto_: {
uint32_t newIp = (ip - 3) + codeReadInt16(t, code, ip); uint32_t offset = codeReadInt16(t, code, ip);
uint32_t newIp = (ip - 3) + offset;
assert(t, newIp < codeLength(t, code)); assert(t, newIp < codeLength(t, code));
c->jmp(frame->machineIp(newIp)); c->jmp(frame->machineIp(newIp));
@ -2395,7 +2396,8 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip,
} break; } break;
case goto_w: { case goto_w: {
uint32_t newIp = (ip - 5) + codeReadInt32(t, code, ip); uint32_t offset = codeReadInt32(t, code, ip);
uint32_t newIp = (ip - 5) + offset;
assert(t, newIp < codeLength(t, code)); assert(t, newIp < codeLength(t, code));
c->jmp(frame->machineIp(newIp)); c->jmp(frame->machineIp(newIp));
@ -2480,7 +2482,8 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip,
case if_acmpeq: case if_acmpeq:
case if_acmpne: { case if_acmpne: {
uint32_t newIp = (ip - 3) + codeReadInt16(t, code, ip); uint32_t offset = codeReadInt16(t, code, ip);
uint32_t newIp = (ip - 3) + offset;
assert(t, newIp < codeLength(t, code)); assert(t, newIp < codeLength(t, code));
Compiler::Operand* a = frame->popObject(); Compiler::Operand* a = frame->popObject();
@ -2504,7 +2507,8 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip,
case if_icmpge: case if_icmpge:
case if_icmplt: case if_icmplt:
case if_icmple: { case if_icmple: {
uint32_t newIp = (ip - 3) + codeReadInt16(t, code, ip); uint32_t offset = codeReadInt16(t, code, ip);
uint32_t newIp = (ip - 3) + offset;
assert(t, newIp < codeLength(t, code)); assert(t, newIp < codeLength(t, code));
Compiler::Operand* a = frame->popInt(); Compiler::Operand* a = frame->popInt();
@ -2543,7 +2547,8 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip,
case ifge: case ifge:
case iflt: case iflt:
case ifle: { case ifle: {
uint32_t newIp = (ip - 3) + codeReadInt16(t, code, ip); uint32_t offset = codeReadInt16(t, code, ip);
uint32_t newIp = (ip - 3) + offset;
assert(t, newIp < codeLength(t, code)); assert(t, newIp < codeLength(t, code));
Compiler::Operand* a = frame->popInt(); Compiler::Operand* a = frame->popInt();
@ -2577,7 +2582,8 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip,
case ifnull: case ifnull:
case ifnonnull: { case ifnonnull: {
uint32_t newIp = (ip - 3) + codeReadInt16(t, code, ip); uint32_t offset = codeReadInt16(t, code, ip);
uint32_t newIp = (ip - 3) + offset;
assert(t, newIp < codeLength(t, code)); assert(t, newIp < codeLength(t, code));
Compiler::Operand* a = frame->popObject(); Compiler::Operand* a = frame->popObject();
@ -2824,14 +2830,18 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip,
uint32_t newIp; uint32_t newIp;
if (instruction == jsr) { if (instruction == jsr) {
newIp = (ip - 3) + codeReadInt16(t, code, ip); uint32_t offset = codeReadInt16(t, code, ip);
newIp = (ip - 3) + offset;
} else { } else {
newIp = (ip - 5) + codeReadInt32(t, code, ip); uint32_t offset = codeReadInt32(t, code, ip);
newIp = (ip - 5) + offset;
} }
assert(t, newIp < codeLength(t, code)); assert(t, newIp < codeLength(t, code));
// todo: flush stack to memory here // todo: flush stack to memory here
abort(t);
Compiler::State* state = c->saveState(); Compiler::State* state = c->saveState();
frame->pushAddress(frame->machineIp(ip)); frame->pushAddress(frame->machineIp(ip));
@ -3447,12 +3457,26 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip,
} }
void void
logCompile(const void* code, unsigned size, const char* class_, logCompile(MyThread* t, const void* code, unsigned size, const char* class_,
const char* name, const char* spec) const char* name, const char* spec)
{ {
fprintf(stderr, "%s.%s%s: %p %p\n", static FILE* log = 0;
class_, name, spec, code, static bool open = false;
static_cast<const uint8_t*>(code) + size); if (not open) {
open = true;
const char* path = findProperty(t, "avian.jit.log");
if (name) {
log = fopen(path, "wb");
} else if (DebugCompile) {
log = stderr;
}
}
if (log) {
fprintf(log, "%p %p %s.%s%s\n",
code, static_cast<const uint8_t*>(code) + size,
class_, name, spec);
}
} }
void void
@ -3717,9 +3741,7 @@ finish(MyThread* t, Assembler* a, const char* name)
a->writeTo(start); a->writeTo(start);
if (Verbose) { logCompile(t, start, a->length(), 0, name, 0);
logCompile(start, a->length(), 0, name, 0);
}
return result; return result;
} }
@ -3861,16 +3883,14 @@ finish(MyThread* t, Context* context)
set(t, result, SingletonBody + offset, p->value); set(t, result, SingletonBody + offset, p->value);
} }
if (Verbose) { logCompile
logCompile (t, start, codeSize,
(start, codeSize, reinterpret_cast<const char*>
reinterpret_cast<const char*> (&byteArrayBody(t, className(t, methodClass(t, context->method)), 0)),
(&byteArrayBody(t, className(t, methodClass(t, context->method)), 0)), reinterpret_cast<const char*>
reinterpret_cast<const char*> (&byteArrayBody(t, methodName(t, context->method), 0)),
(&byteArrayBody(t, methodName(t, context->method), 0)), reinterpret_cast<const char*>
reinterpret_cast<const char*> (&byteArrayBody(t, methodSpec(t, context->method), 0)));
(&byteArrayBody(t, methodSpec(t, context->method), 0)));
}
// for debugging: // for debugging:
if (false and if (false and
@ -5092,10 +5112,7 @@ compileThunks(MyThread* t, MyProcessor* p)
uint8_t* start = reinterpret_cast<uint8_t*> uint8_t* start = reinterpret_cast<uint8_t*>
(&singletonValue(t, p->thunkTable, 0)); (&singletonValue(t, p->thunkTable, 0));
if (Verbose) { logCompile(t, start, p->thunkSize * ThunkCount, 0, "thunkTable", 0);
logCompile(start, p->thunkSize * ThunkCount, 0, "thunkTable", 0);
fprintf(stderr, "thunk size: %d\n", p->thunkSize);
}
tableContext.promise.resolved_ = true; tableContext.promise.resolved_ = true;

View File

@ -86,8 +86,6 @@ class Site {
public: public:
Site(): next(0) { } Site(): next(0) { }
virtual ~Site() { }
virtual Site* readTarget(Context*, Read*) { return this; } virtual Site* readTarget(Context*, Read*) { return this; }
virtual void toString(Context*, char*, unsigned) = 0; virtual void toString(Context*, char*, unsigned) = 0;
@ -219,8 +217,6 @@ class Read {
value(0), event(0), eventNext(0), size(size) value(0), event(0), eventNext(0), size(size)
{ } { }
virtual ~Read() { }
virtual Site* pickSite(Context* c, Value* v, bool includeBuddies) = 0; virtual Site* pickSite(Context* c, Value* v, bool includeBuddies) = 0;
virtual Site* allocateSite(Context* c) = 0; virtual Site* allocateSite(Context* c) = 0;
@ -257,8 +253,6 @@ class Value: public Compiler::Operand {
local(false) local(false)
{ } { }
virtual ~Value() { }
virtual void addPredecessor(Context*, Event*) { } virtual void addPredecessor(Context*, Event*) { }
Read* reads; Read* reads;
@ -559,8 +553,6 @@ class Event {
readCount(0) readCount(0)
{ } { }
virtual ~Event() { }
virtual const char* name() = 0; virtual const char* name() = 0;
virtual void compile(Context* c) = 0; virtual void compile(Context* c) = 0;

View File

@ -21,8 +21,6 @@ class Compiler {
public: public:
class Client { class Client {
public: public:
virtual ~Client() { }
virtual intptr_t getThunk(UnaryOperation op, unsigned size) = 0; virtual intptr_t getThunk(UnaryOperation op, unsigned size) = 0;
virtual intptr_t getThunk(TernaryOperation op, unsigned size) = 0; virtual intptr_t getThunk(TernaryOperation op, unsigned size) = 0;
}; };
@ -34,8 +32,6 @@ class Compiler {
class StackElement { }; class StackElement { };
class State { }; class State { };
virtual ~Compiler() { }
virtual State* saveState() = 0; virtual State* saveState() = 0;
virtual void restoreState(State* state) = 0; virtual void restoreState(State* state) = 0;

View File

@ -52,7 +52,7 @@ equal(const void* a, unsigned al, const void* b, unsigned bl)
class Element { class Element {
public: public:
Element(): next(0) { } Element(): next(0) { }
virtual ~Element() { }
virtual System::Region* find(const char* name) = 0; virtual System::Region* find(const char* name) = 0;
virtual bool exists(const char* name) = 0; virtual bool exists(const char* name) = 0;
virtual void dispose() = 0; virtual void dispose() = 0;
@ -372,7 +372,7 @@ class JarIndex {
class JarElement: public Element { class JarElement: public Element {
public: public:
JarElement(System* s, const char* name): JarElement(System* s, const char* name):
s(s), name(name), index(0) s(s), name(name), region(0), index(0)
{ } { }
virtual void init() { virtual void init() {

View File

@ -19,7 +19,6 @@ namespace vm {
class Finder { class Finder {
public: public:
virtual ~Finder() { }
virtual System::Region* find(const char* name) = 0; virtual System::Region* find(const char* name) = 0;
virtual bool exists(const char* name) = 0; virtual bool exists(const char* name) = 0;
virtual const char* path() = 0; virtual const char* path() = 0;

View File

@ -32,19 +32,16 @@ class Heap: public Allocator {
class Visitor { class Visitor {
public: public:
virtual ~Visitor() { }
virtual void visit(void*) = 0; virtual void visit(void*) = 0;
}; };
class Walker { class Walker {
public: public:
virtual ~Walker() { }
virtual bool visit(unsigned) = 0; virtual bool visit(unsigned) = 0;
}; };
class Client { class Client {
public: public:
virtual ~Client() { }
virtual void collect(void* context, CollectionType type) = 0; virtual void collect(void* context, CollectionType type) = 0;
virtual void visitRoots(Visitor*) = 0; virtual void visitRoots(Visitor*) = 0;
virtual bool isFixed(void*) = 0; virtual bool isFixed(void*) = 0;
@ -54,7 +51,6 @@ class Heap: public Allocator {
virtual void walk(void*, Walker*) = 0; virtual void walk(void*, Walker*) = 0;
}; };
virtual ~Heap() { }
virtual void setClient(Client* client) = 0; virtual void setClient(Client* client) = 0;
virtual void collect(CollectionType type, unsigned footprint) = 0; virtual void collect(CollectionType type, unsigned footprint) = 0;
virtual void* allocateFixed(Allocator* allocator, unsigned sizeInWords, virtual void* allocateFixed(Allocator* allocator, unsigned sizeInWords,

329
src/heapdump.cpp Normal file
View File

@ -0,0 +1,329 @@
/* 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. */
#include "machine.h"
using namespace vm;
namespace {
const uintptr_t PointerShift = log(BytesPerWord);
class Set {
public:
class Entry {
public:
object value;
uint32_t number;
int next;
};
static unsigned footprint(unsigned capacity) {
return sizeof(Set)
+ pad(sizeof(int) * capacity)
+ pad(sizeof(Set::Entry) * capacity);
}
Set(unsigned capacity):
size(0),
capacity(capacity),
index(reinterpret_cast<int*>
(reinterpret_cast<uint8_t*>(this)
+ sizeof(Set))),
entries(reinterpret_cast<Entry*>
(reinterpret_cast<uint8_t*>(index)
+ pad(sizeof(int) * capacity)))
{ }
unsigned size;
unsigned capacity;
int* index;
Entry* entries;
};
class Stack {
public:
class Entry {
public:
object value;
int offset;
};
static const unsigned Capacity = 4096;
Stack(Stack* next): next(next), entryCount(0) { }
Stack* next;
unsigned entryCount;
Entry entries[Capacity];
};
class Context {
public:
Context(Thread* thread, FILE* out):
thread(thread), out(out), objects(0), stack(0), nextNumber(1)
{ }
~Context() {
if (objects) {
thread->m->heap->free(objects, Set::footprint(objects->capacity));
}
while (stack) {
Stack* dead = stack;
stack = dead->next;
thread->m->heap->free(stack, sizeof(Stack));
}
}
Thread* thread;
FILE* out;
Set* objects;
Stack* stack;
uint32_t nextNumber;
};
void
push(Context* c, object p, int offset)
{
if (c->stack == 0 or c->stack->entryCount == Stack::Capacity) {
c->stack = new (c->thread->m->heap->allocate(sizeof(Stack)))
Stack(c->stack);
}
Stack::Entry* e = c->stack->entries + (c->stack->entryCount++);
e->value = p;
e->offset = offset;
}
bool
pop(Context* c, object* p, int* offset)
{
if (c->stack) {
if (c->stack->entryCount == 0) {
if (c->stack->next) {
Stack* dead = c->stack;
c->stack = dead->next;
c->thread->m->heap->free(dead, sizeof(Stack));
} else {
return false;
}
}
Stack::Entry* e = c->stack->entries + (--c->stack->entryCount);
*p = e->value;
*offset = e->offset;
return true;
} else {
return false;
}
}
unsigned
hash(object p, unsigned capacity)
{
return (reinterpret_cast<uintptr_t>(p) >> PointerShift)
& (capacity - 1);
}
Set::Entry*
find(Context* c, object p)
{
if (c->objects == 0) return false;
for (int i = c->objects->index[hash(p, c->objects->capacity)]; i >= 0;) {
Set::Entry* e = c->objects->entries + i;
if (e->value == p) {
return e;
}
i = e->next;
}
return false;
}
Set::Entry*
add(Context* c UNUSED, Set* set, object p, uint32_t number)
{
assert(c->thread, set->size < set->capacity);
unsigned index = hash(p, set->capacity);
int offset = set->size++;
Set::Entry* e = set->entries + offset;
e->value = p;
e->number = number;
e->next = set->index[index];
set->index[index] = offset;
return e;
}
Set::Entry*
add(Context* c, object p)
{
if (c->objects == 0 or c->objects->size == c->objects->capacity) {
unsigned capacity;
if (c->objects) {
capacity = c->objects->capacity * 2;
} else {
capacity = 4096; // must be power of two
}
Set* set = new (c->thread->m->heap->allocate(Set::footprint(capacity)))
Set(capacity);
memset(set->index, 0xFF, sizeof(int) * capacity);
if (c->objects) {
for (unsigned i = 0; i < c->objects->capacity; ++i) {
for (int j = c->objects->index[i]; j >= 0;) {
Set::Entry* e = c->objects->entries + j;
add(c, set, e->value, e->number);
j = e->next;
}
}
c->thread->m->heap->free
(c->objects, Set::footprint(c->objects->capacity));
}
c->objects = set;
}
return add(c, c->objects, p, 0);
}
enum {
Root,
Size,
ClassName,
Push,
Pop
};
inline object
get(object o, unsigned offsetInWords)
{
return static_cast<object>
(mask(cast<void*>(o, offsetInWords * BytesPerWord)));
}
void
write1(Context* c, uint8_t v)
{
fwrite(&v, 1, 1, c->out);
}
void
write4(Context* c, uint32_t v)
{
uint8_t b[] = { v >> 24, (v >> 16) & 0xFF, (v >> 8) & 0xFF, v & 0xFF };
fwrite(b, 4, 1, c->out);
}
void
writeString(Context* c, int8_t* p, unsigned size)
{
write4(c, size);
fwrite(p, size, 1, c->out);
}
unsigned
objectSize(Thread* t, object o)
{
unsigned n = baseSize(t, o, objectClass(t, o));
if (objectExtended(t, o)) {
++ n;
}
return n;
}
void
visit(Context* c, object p)
{
Thread* t = c->thread;
int nextChildOffset;
write1(c, Root);
visit: {
Set::Entry* e = find(c, p);
if (e) {
write4(c, e->number);
} else {
e = add(c, p);
e->number = c->nextNumber++;
write4(c, e->number);
write1(c, Size);
write4(c, objectSize(t, p));
if (objectClass(t, p) == arrayBody(t, t->m->types, Machine::ClassType)) {
object name = className(t, p);
if (name) {
write1(c, ClassName);
writeString(c, &byteArrayBody(t, name, 0),
byteArrayLength(t, name) - 1);
}
}
nextChildOffset = walkNext(t, p, -1);
if (nextChildOffset != -1) {
goto children;
}
}
}
goto pop;
children: {
write1(c, Push);
push(c, p, nextChildOffset);
p = get(p, nextChildOffset);
goto visit;
}
pop: {
if (pop(c, &p, &nextChildOffset)) {
write1(c, Pop);
nextChildOffset = walkNext(t, p, nextChildOffset);
if (nextChildOffset >= 0) {
goto children;
} else {
goto pop;
}
}
}
}
} // namespace
namespace vm {
void
dumpHeap(Thread* t, FILE* out)
{
Context context(t, out);
class Visitor : public Heap::Visitor {
public:
Visitor(Context* c): c(c) { }
virtual void visit(void* p) {
::visit(c, static_cast<object>(mask(*static_cast<void**>(p))));
}
Context* c;
} v(&context);
add(&context, 0)->number = 0;
visitRoots(t->m, &v);
}
} // namespace vm

View File

@ -2046,12 +2046,13 @@ populateJNITables(JavaVMVTable* vmTable, JNIEnvVTable* envTable)
} // namespace vm } // namespace vm
#define BUILTINS_PROPERTY "avian.builtins"
#define BOOTSTRAP_PROPERTY "avian.bootstrap" #define BOOTSTRAP_PROPERTY "avian.bootstrap"
#define CRASHDIR_PROPERTY "avian.crash.dir"
#define CLASSPATH_PROPERTY "java.class.path" #define CLASSPATH_PROPERTY "java.class.path"
#define BOOTCLASSPATH_PREPEND_OPTION "bootclasspath/p" #define BOOTCLASSPATH_PREPEND_OPTION "bootclasspath/p"
#define BOOTCLASSPATH_OPTION "bootclasspath" #define BOOTCLASSPATH_OPTION "bootclasspath"
#define BOOTCLASSPATH_APPEND_OPTION "bootclasspath/a" #define BOOTCLASSPATH_APPEND_OPTION "bootclasspath/a"
#define BOOTCLASSPATH_APPEND_OPTION "bootclasspath/a"
extern "C" JNIEXPORT jint JNICALL extern "C" JNIEXPORT jint JNICALL
JNI_GetDefaultJavaVMInitArgs(void*) JNI_GetDefaultJavaVMInitArgs(void*)
@ -2065,12 +2066,14 @@ JNI_CreateJavaVM(Machine** m, Thread** t, void* args)
JavaVMInitArgs* a = static_cast<JavaVMInitArgs*>(args); JavaVMInitArgs* a = static_cast<JavaVMInitArgs*>(args);
unsigned heapLimit = 0; unsigned heapLimit = 0;
const char* builtins = 0;
const char* bootLibrary = 0; const char* bootLibrary = 0;
const char* classpath = 0; const char* classpath = 0;
const char* bootClasspathPrepend = ""; const char* bootClasspathPrepend = "";
const char* bootClasspath = ""; const char* bootClasspath = "";
const char* bootClasspathAppend = ""; const char* bootClasspathAppend = "";
const char* crashDumpDirectory = 0;
unsigned propertyCount = 0;
for (int i = 0; i < a->nOptions; ++i) { for (int i = 0; i < a->nOptions; ++i) {
if (strncmp(a->options[i].optionString, "-X", 2) == 0) { if (strncmp(a->options[i].optionString, "-X", 2) == 0) {
@ -2092,21 +2095,21 @@ JNI_CreateJavaVM(Machine** m, Thread** t, void* args)
} }
} else if (strncmp(a->options[i].optionString, "-D", 2) == 0) { } else if (strncmp(a->options[i].optionString, "-D", 2) == 0) {
const char* p = a->options[i].optionString + 2; const char* p = a->options[i].optionString + 2;
if (strncmp(p, BUILTINS_PROPERTY "=", if (strncmp(p, BOOTSTRAP_PROPERTY "=",
sizeof(BUILTINS_PROPERTY)) == 0) sizeof(BOOTSTRAP_PROPERTY)) == 0)
{
builtins = p + sizeof(BUILTINS_PROPERTY);
} else if (strncmp(p, BOOTSTRAP_PROPERTY "=",
sizeof(BOOTSTRAP_PROPERTY)) == 0)
{ {
bootLibrary = p + sizeof(BOOTSTRAP_PROPERTY); bootLibrary = p + sizeof(BOOTSTRAP_PROPERTY);
} else if (strncmp(p, CRASHDIR_PROPERTY "=",
sizeof(CRASHDIR_PROPERTY)) == 0)
{
crashDumpDirectory = p + sizeof(CRASHDIR_PROPERTY);
} else if (strncmp(p, CLASSPATH_PROPERTY "=", } else if (strncmp(p, CLASSPATH_PROPERTY "=",
sizeof(CLASSPATH_PROPERTY)) == 0) sizeof(CLASSPATH_PROPERTY)) == 0)
{ {
classpath = p + sizeof(CLASSPATH_PROPERTY); classpath = p + sizeof(CLASSPATH_PROPERTY);
} }
// todo: add properties to VM ++ propertyCount;
} }
} }
@ -2128,13 +2131,22 @@ JNI_CreateJavaVM(Machine** m, Thread** t, void* args)
append(&classpathPointer, bootClasspathAppend, bcpal, PATH_SEPARATOR); append(&classpathPointer, bootClasspathAppend, bcpal, PATH_SEPARATOR);
append(&classpathPointer, classpath, cpl, 0); append(&classpathPointer, classpath, cpl, 0);
System* s = makeSystem(); System* s = makeSystem(crashDumpDirectory);
Heap* h = makeHeap(s, heapLimit); Heap* h = makeHeap(s, heapLimit);
Finder* f = makeFinder(s, classpathBuffer, bootLibrary); Finder* f = makeFinder(s, classpathBuffer, bootLibrary);
Processor* p = makeProcessor(s, h); Processor* p = makeProcessor(s, h);
const char** properties = static_cast<const char**>
(h->allocate(sizeof(const char*) * propertyCount));
const char** propertyPointer = properties;
for (int i = 0; i < a->nOptions; ++i) {
if (strncmp(a->options[i].optionString, "-D", 2) == 0) {
*(propertyPointer++) = a->options[i].optionString + 2;
}
}
*m = new (h->allocate(sizeof(Machine))) *m = new (h->allocate(sizeof(Machine)))
Machine(s, h, f, p, bootLibrary, builtins); Machine(s, h, f, p, properties, propertyCount);
*t = p->makeThread(*m, 0, 0); *t = p->makeThread(*m, 0, 0);

View File

@ -198,13 +198,13 @@ visitRoots(Thread* t, Heap::Visitor* v)
void void
walk(Thread*, Heap::Walker* w, uint32_t* mask, unsigned fixedSize, walk(Thread*, Heap::Walker* w, uint32_t* mask, unsigned fixedSize,
unsigned arrayElementSize, unsigned arrayLength) unsigned arrayElementSize, unsigned arrayLength, unsigned start)
{ {
unsigned fixedSizeInWords = ceiling(fixedSize, BytesPerWord); unsigned fixedSizeInWords = ceiling(fixedSize, BytesPerWord);
unsigned arrayElementSizeInWords unsigned arrayElementSizeInWords
= ceiling(arrayElementSize, BytesPerWord); = ceiling(arrayElementSize, BytesPerWord);
for (unsigned i = 0; i < fixedSizeInWords; ++i) { for (unsigned i = start; i < fixedSizeInWords; ++i) {
if (mask[i / 32] & (static_cast<uint32_t>(1) << (i % 32))) { if (mask[i / 32] & (static_cast<uint32_t>(1) << (i % 32))) {
if (not w->visit(i)) { if (not w->visit(i)) {
return; return;
@ -222,8 +222,19 @@ walk(Thread*, Heap::Walker* w, uint32_t* mask, unsigned fixedSize,
} }
if (arrayObjectElements) { if (arrayObjectElements) {
for (unsigned i = 0; i < arrayLength; ++i) { unsigned arrayStart;
for (unsigned j = 0; j < arrayElementSizeInWords; ++j) { unsigned elementStart;
if (start > fixedSizeInWords) {
unsigned s = start - fixedSizeInWords;
arrayStart = s / arrayElementSizeInWords;
elementStart = s % arrayElementSizeInWords;
} else {
arrayStart = 0;
elementStart = 0;
}
for (unsigned i = arrayStart; i < arrayLength; ++i) {
for (unsigned j = elementStart; j < arrayElementSizeInWords; ++j) {
unsigned k = fixedSizeInWords + j; unsigned k = fixedSizeInWords + j;
if (mask[k / 32] & (static_cast<uint32_t>(1) << (k % 32))) { if (mask[k / 32] & (static_cast<uint32_t>(1) << (k % 32))) {
if (not w->visit if (not w->visit
@ -238,7 +249,7 @@ walk(Thread*, Heap::Walker* w, uint32_t* mask, unsigned fixedSize,
} }
void void
walk(Thread* t, Heap::Walker* w, object o) walk(Thread* t, Heap::Walker* w, object o, unsigned start)
{ {
object class_ = static_cast<object>(t->m->heap->follow(objectClass(t, o))); object class_ = static_cast<object>(t->m->heap->follow(objectClass(t, o)));
object objectMask = static_cast<object> object objectMask = static_cast<object>
@ -255,16 +266,16 @@ walk(Thread* t, Heap::Walker* w, object o)
memcpy(mask, &intArrayBody(t, objectMask, 0), memcpy(mask, &intArrayBody(t, objectMask, 0),
intArrayLength(t, objectMask) * 4); intArrayLength(t, objectMask) * 4);
walk(t, w, mask, fixedSize, arrayElementSize, arrayLength); walk(t, w, mask, fixedSize, arrayElementSize, arrayLength, start);
} else if (classVmFlags(t, class_) & SingletonFlag) { } else if (classVmFlags(t, class_) & SingletonFlag) {
unsigned length = singletonLength(t, o); unsigned length = singletonLength(t, o);
if (length) { if (length) {
walk(t, w, singletonMask(t, o), walk(t, w, singletonMask(t, o),
(singletonCount(t, o) + 2) * BytesPerWord, 0, 0); (singletonCount(t, o) + 2) * BytesPerWord, 0, 0, start);
} else { } else if (start == 0) {
w->visit(0); w->visit(0);
} }
} else { } else if (start == 0) {
w->visit(0); w->visit(0);
} }
} }
@ -1534,20 +1545,7 @@ class HeapClient: public Heap::Client {
HeapClient(Machine* m): m(m) { } HeapClient(Machine* m): m(m) { }
virtual void visitRoots(Heap::Visitor* v) { virtual void visitRoots(Heap::Visitor* v) {
v->visit(&(m->loader)); ::visitRoots(m, v);
v->visit(&(m->bootstrapClassMap));
v->visit(&(m->monitorMap));
v->visit(&(m->stringMap));
v->visit(&(m->types));
v->visit(&(m->jniMethodTable));
for (Reference* r = m->jniReferences; r; r = r->next) {
v->visit(&(r->target));
}
for (Thread* t = m->rootThread; t; t = t->peer) {
::visitRoots(t, v);
}
postVisit(m->rootThread, v); postVisit(m->rootThread, v);
} }
@ -1616,7 +1614,7 @@ class HeapClient: public Heap::Client {
virtual void walk(void* p, Heap::Walker* w) { virtual void walk(void* p, Heap::Walker* w) {
object o = static_cast<object>(m->heap->follow(mask(p))); object o = static_cast<object>(m->heap->follow(mask(p)));
::walk(m->rootThread, w, o); ::walk(m->rootThread, w, o, 0);
} }
void dispose() { void dispose() {
@ -1632,8 +1630,8 @@ 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, const char* bootLibrary, Processor* processor, const char** properties,
const char* builtins): unsigned propertyCount):
vtable(&javaVMVTable), vtable(&javaVMVTable),
system(system), system(system),
heapClient(new (heap->allocate(sizeof(HeapClient))) heapClient(new (heap->allocate(sizeof(HeapClient)))
@ -1644,7 +1642,8 @@ Machine::Machine(System* system, Heap* heap, Finder* finder,
rootThread(0), rootThread(0),
exclusive(0), exclusive(0),
jniReferences(0), jniReferences(0),
builtins(builtins), properties(properties),
propertyCount(propertyCount),
activeCount(0), activeCount(0),
liveCount(0), liveCount(0),
fixedFootprint(0), fixedFootprint(0),
@ -1677,7 +1676,8 @@ 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, bootLibrary, false))) not system->success
(system->load(&libraries, findProperty(this, "avian.bootstrap"), false)))
{ {
system->abort(); system->abort();
} }
@ -1706,6 +1706,8 @@ Machine::dispose()
heap->free(heapPool[i], Thread::HeapSizeInBytes); heap->free(heapPool[i], Thread::HeapSizeInBytes);
} }
heap->free(properties, sizeof(const char*) * propertyCount);
static_cast<HeapClient*>(heapClient)->dispose(); static_cast<HeapClient*>(heapClient)->dispose();
heap->free(this, sizeof(*this)); heap->free(this, sizeof(*this));
@ -2595,12 +2597,14 @@ findInHierarchy(Thread* t, object class_, object name, object spec,
PROTECT(t, class_); PROTECT(t, class_);
object o = 0; object o = 0;
if (classFlags(t, class_) & ACC_INTERFACE) { if ((classFlags(t, class_) & ACC_INTERFACE)
if (classVirtualTable(t, class_)) { and classVirtualTable(t, class_))
o = findInTable {
(t, classVirtualTable(t, class_), name, spec, methodName, methodSpec); o = findInTable
} (t, classVirtualTable(t, class_), name, spec, methodName, methodSpec);
} else { }
if (o == 0) {
for (; o == 0 and class_; class_ = classSuper(t, class_)) { for (; o == 0 and class_; class_ = classSuper(t, class_)) {
o = find(t, class_, name, spec); o = find(t, class_, name, spec);
} }
@ -2765,6 +2769,44 @@ collect(Thread* t, Heap::CollectionType type)
#endif #endif
} }
int
walkNext(Thread* t, object o, int previous)
{
class Walker: public Heap::Walker {
public:
Walker(): value(-1) { }
bool visit(unsigned offset) {
value = offset;
return false;
}
int value;
} walker;
walk(t, &walker, o, previous + 1);
return walker.value;
}
void
visitRoots(Machine* m, Heap::Visitor* v)
{
v->visit(&(m->loader));
v->visit(&(m->bootstrapClassMap));
v->visit(&(m->monitorMap));
v->visit(&(m->stringMap));
v->visit(&(m->types));
v->visit(&(m->jniMethodTable));
for (Reference* r = m->jniReferences; r; r = r->next) {
v->visit(&(r->target));
}
for (Thread* t = m->rootThread; t; t = t->peer) {
::visitRoots(t, v);
}
}
void void
printTrace(Thread* t, object exception) printTrace(Thread* t, object exception)
{ {

View File

@ -1138,7 +1138,7 @@ class Machine {
}; };
Machine(System* system, Heap* heap, Finder* finder, Processor* processor, Machine(System* system, Heap* heap, Finder* finder, Processor* processor,
const char* bootLibrary, const char* builtins); const char** properties, unsigned propertyCount);
~Machine() { ~Machine() {
dispose(); dispose();
@ -1159,7 +1159,8 @@ class Machine {
Thread* rootThread; Thread* rootThread;
Thread* exclusive; Thread* exclusive;
Reference* jniReferences; Reference* jniReferences;
const char* builtins; const char** properties;
unsigned propertyCount;
unsigned activeCount; unsigned activeCount;
unsigned liveCount; unsigned liveCount;
unsigned fixedFootprint; unsigned fixedFootprint;
@ -1227,7 +1228,7 @@ class Thread {
t->protector = this; t->protector = this;
} }
virtual ~Protector() { ~Protector() {
t->protector = next; t->protector = next;
} }
@ -1526,6 +1527,29 @@ setObjectClass(Thread*, object o, object value)
| (reinterpret_cast<uintptr_t>(cast<object>(o, 0)) & (~PointerMask))); | (reinterpret_cast<uintptr_t>(cast<object>(o, 0)) & (~PointerMask)));
} }
inline const char*
findProperty(Machine* m, const char* name)
{
for (unsigned i = 0; i < m->propertyCount; ++i) {
const char* p = m->properties[i];
const char* n = name;
while (*p and *p != '=' and *n and *p == *n) {
++ p;
++ n;
}
if (*p == '=' and *n == 0) {
return p + 1;
}
}
return 0;
}
inline const char*
findProperty(Thread* t, const char* name)
{
return findProperty(t->m, name);
}
object& object&
arrayBodyUnsafe(Thread*, object, unsigned); arrayBodyUnsafe(Thread*, object, unsigned);
@ -2200,6 +2224,12 @@ intern(Thread* t, object s);
void void
exit(Thread* t); exit(Thread* t);
int
walkNext(Thread* t, object o, int previous);
void
visitRoots(Machine* m, Heap::Visitor* v);
inline jobject inline jobject
makeLocalReference(Thread* t, object o) makeLocalReference(Thread* t, object o)
{ {
@ -2293,6 +2323,9 @@ makeSingleton(Thread* t, unsigned count)
return o; return o;
} }
void
dumpHeap(Thread* t, FILE* out);
} // namespace vm } // namespace vm
void void

View File

@ -257,9 +257,10 @@ class MySystem: public System {
Thread* t = static_cast<Thread*>(context); Thread* t = static_cast<Thread*>(context);
if (owner_ == t) { if (owner_ == t) {
bool interrupted; // Initialized here to make gcc 4.2 a happy compiler
bool notified; bool interrupted = false;
unsigned depth; bool notified = false;
unsigned depth = 0;
{ ACQUIRE(t->mutex); { ACQUIRE(t->mutex);
@ -820,7 +821,7 @@ handleSignal(int signal, siginfo_t* info, void* context)
namespace vm { namespace vm {
System* System*
makeSystem() makeSystem(const char*)
{ {
return new (malloc(sizeof(MySystem))) MySystem(); return new (malloc(sizeof(MySystem))) MySystem();
} }

View File

@ -301,8 +301,6 @@ class Task {
public: public:
Task(Task* next): next(next) { } Task(Task* next): next(next) { }
virtual ~Task() { }
virtual void run(Context* c) = 0; virtual void run(Context* c) = 0;
Task* next; Task* next;

View File

@ -167,8 +167,7 @@ resolveNativeMethod2(Thread* t, object method)
} }
#ifdef __MINGW32__ #ifdef __MINGW32__
// on windows, we also try the _%s@%d variant, since the SWT // on windows, we also try the _%s@%d and %s@%d variants
// libraries use it.
unsigned footprint = methodParameterFootprint(t, method) + 1; unsigned footprint = methodParameterFootprint(t, method) + 1;
if (methodFlags(t, method) & ACC_STATIC) { if (methodFlags(t, method) & ACC_STATIC) {
++ footprint; ++ footprint;
@ -186,6 +185,12 @@ resolveNativeMethod2(Thread* t, object method)
if (p) { if (p) {
return p; return p;
} }
// one more try without the leading underscore
p = ::resolveNativeMethod(t, undecorated + 1, decorated + 1);
if (p) {
return p;
}
#endif #endif
return 0; return 0;

View File

@ -23,15 +23,11 @@ class Processor {
class StackVisitor { class StackVisitor {
public: public:
virtual ~StackVisitor() { }
virtual bool visit(StackWalker* walker) = 0; virtual bool visit(StackWalker* walker) = 0;
}; };
class StackWalker { class StackWalker {
public: public:
virtual ~StackWalker() { }
virtual void walk(StackVisitor* v) = 0; virtual void walk(StackVisitor* v) = 0;
virtual object method() = 0; virtual object method() = 0;
@ -41,8 +37,6 @@ class Processor {
virtual unsigned count() = 0; virtual unsigned count() = 0;
}; };
virtual ~Processor() { }
virtual Thread* virtual Thread*
makeThread(Machine* m, object javaThread, Thread* parent) = 0; makeThread(Machine* m, object javaThread, Thread* parent) = 0;

View File

@ -19,7 +19,6 @@ class Stream {
public: public:
class Client { class Client {
public: public:
virtual ~Client() { }
virtual void NO_RETURN handleError() = 0; virtual void NO_RETURN handleError() = 0;
}; };

View File

@ -28,7 +28,6 @@ class System {
class Thread { class Thread {
public: public:
virtual ~Thread() { }
virtual void interrupt() = 0; virtual void interrupt() = 0;
virtual void join() = 0; virtual void join() = 0;
virtual void dispose() = 0; virtual void dispose() = 0;
@ -36,13 +35,11 @@ class System {
class ThreadVisitor { class ThreadVisitor {
public: public:
virtual ~ThreadVisitor() { }
virtual void visit(void* ip, void* base, void* stack) = 0; virtual void visit(void* ip, void* base, void* stack) = 0;
}; };
class Runnable { class Runnable {
public: public:
virtual ~Runnable() { }
virtual void attach(Thread*) = 0; virtual void attach(Thread*) = 0;
virtual void run() = 0; virtual void run() = 0;
virtual bool interrupted() = 0; virtual bool interrupted() = 0;
@ -51,7 +48,6 @@ class System {
class Mutex { class Mutex {
public: public:
virtual ~Mutex() { }
virtual void acquire() = 0; virtual void acquire() = 0;
virtual void release() = 0; virtual void release() = 0;
virtual void dispose() = 0; virtual void dispose() = 0;
@ -59,7 +55,6 @@ class System {
class Monitor { class Monitor {
public: public:
virtual ~Monitor() { }
virtual bool tryAcquire(Thread* context) = 0; virtual bool tryAcquire(Thread* context) = 0;
virtual void acquire(Thread* context) = 0; virtual void acquire(Thread* context) = 0;
virtual void release(Thread* context) = 0; virtual void release(Thread* context) = 0;
@ -72,7 +67,6 @@ class System {
class Local { class Local {
public: public:
virtual ~Local() { }
virtual void* get() = 0; virtual void* get() = 0;
virtual void set(void* p) = 0; virtual void set(void* p) = 0;
virtual void dispose() = 0; virtual void dispose() = 0;
@ -80,7 +74,6 @@ class System {
class Region { class Region {
public: public:
virtual ~Region() { }
virtual const uint8_t* start() = 0; virtual const uint8_t* start() = 0;
virtual size_t length() = 0; virtual size_t length() = 0;
virtual void dispose() = 0; virtual void dispose() = 0;
@ -88,7 +81,6 @@ class System {
class Library { class Library {
public: public:
virtual ~Library() { }
virtual void* resolve(const char* function) = 0; virtual void* resolve(const char* function) = 0;
virtual const char* name() = 0; virtual const char* name() = 0;
virtual bool mapName() = 0; virtual bool mapName() = 0;
@ -99,8 +91,6 @@ class System {
class SignalHandler { class SignalHandler {
public: public:
virtual ~SignalHandler() { }
virtual bool handleSignal(void** ip, void** base, void** stack, virtual bool handleSignal(void** ip, void** base, void** stack,
void** thread) = 0; void** thread) = 0;
}; };
@ -120,8 +110,6 @@ class System {
System::Monitor* m; System::Monitor* m;
}; };
virtual ~System() { }
virtual bool success(Status) = 0; virtual bool success(Status) = 0;
virtual void* tryAllocate(unsigned sizeInBytes) = 0; virtual void* tryAllocate(unsigned sizeInBytes) = 0;
virtual void free(const void* p) = 0; virtual void free(const void* p) = 0;
@ -193,7 +181,7 @@ assert(System* s, bool v)
#endif // not NDEBUG #endif // not NDEBUG
System* System*
makeSystem(); makeSystem(const char* crashDumpDirectory);
} // namespace vm } // namespace vm

View File

@ -371,7 +371,6 @@ class Scalar : public Object {
unsigned elementSize; unsigned elementSize;
bool noassert; bool noassert;
bool nogc; bool nogc;
bool hide;
static Scalar* make(Object* owner, Object* typeObject, const char* typeName, static Scalar* make(Object* owner, Object* typeObject, const char* typeName,
const char* name, unsigned size) const char* name, unsigned size)
@ -385,7 +384,6 @@ class Scalar : public Object {
o->elementSize = size; o->elementSize = size;
o->noassert = false; o->noassert = false;
o->nogc = false; o->nogc = false;
o->hide = false;
return o; return o;
} }
}; };
@ -527,19 +525,6 @@ memberGC(Object* o)
return not memberNoGC(o) and equal(memberTypeName(o), "object"); return not memberNoGC(o) and equal(memberTypeName(o), "object");
} }
bool&
memberHide(Object* o)
{
switch (o->type) {
case Object::Scalar:
case Object::Array:
return static_cast<Scalar*>(o)->hide;
default:
UNREACHABLE;
}
}
class Method : public Object { class Method : public Object {
public: public:
Object* owner; Object* owner;
@ -588,7 +573,6 @@ class Type : public Object {
Object* super; Object* super;
List members; List members;
List methods; List methods;
bool hideConstructor;
bool overridesMethods; bool overridesMethods;
static Type* make(Object::ObjectType type, const char* name, static Type* make(Object::ObjectType type, const char* name,
@ -601,7 +585,6 @@ class Type : public Object {
o->super = 0; o->super = 0;
o->members.first = o->members.last = 0; o->members.first = o->members.last = 0;
o->methods.first = o->methods.last = 0; o->methods.first = o->methods.last = 0;
o->hideConstructor = false;
o->overridesMethods = false; o->overridesMethods = false;
return o; return o;
} }
@ -718,18 +701,6 @@ typeSuper(Object* o)
} }
} }
bool&
typeHideConstructor(Object* o)
{
switch (o->type) {
case Object::Type:
return static_cast<Type*>(o)->hideConstructor;
default:
UNREACHABLE;
}
}
class Number : public Object { class Number : public Object {
public: public:
unsigned value; unsigned value;
@ -1141,15 +1112,7 @@ void
parseSubdeclaration(Object* t, Object* p, Object* declarations) parseSubdeclaration(Object* t, Object* p, Object* declarations)
{ {
const char* front = string(car(p)); const char* front = string(car(p));
if (equal(front, "hide")) { if (equal(front, "extends")) {
if (equal(string(car(cdr(p))), "constructor")) {
typeHideConstructor(t) = true;
} else {
Object* member = parseMember(t, cdr(p), declarations);
memberHide(member) = true;
addMember(t, member);
}
} else if (equal(front, "extends")) {
assert(t->type == Object::Type); assert(t->type == Object::Type);
assert(typeSuper(t) == 0); assert(typeSuper(t) == 0);
typeSuper(t) = declaration(string(car(cdr(p))), declarations); typeSuper(t) = declaration(string(car(cdr(p))), declarations);
@ -1169,8 +1132,7 @@ memberEqual(Object* a, Object* b)
case Object::Scalar: case Object::Scalar:
return equal(memberTypeName(a), memberTypeName(b)) return equal(memberTypeName(a), memberTypeName(b))
and memberNoAssert(a) == memberNoAssert(b) and memberNoAssert(a) == memberNoAssert(b)
and memberNoGC(a) == memberNoGC(b) and memberNoGC(a) == memberNoGC(b);
and memberHide(a) == memberHide(b);
// todo: compare array fields // todo: compare array fields
@ -1468,8 +1430,7 @@ parse(Input* in, const char* javaClassDirectory)
} }
void void
writeAccessorName(Output* out, Object* member, bool respectHide = false, writeAccessorName(Output* out, Object* member, bool unsafe = false)
bool unsafe = false)
{ {
const char* owner = typeName(memberOwner(member)); const char* owner = typeName(memberOwner(member));
out->write(owner); out->write(owner);
@ -1477,9 +1438,6 @@ writeAccessorName(Output* out, Object* member, bool respectHide = false,
if (unsafe) { if (unsafe) {
out->write("Unsafe"); out->write("Unsafe");
} }
if (respectHide and memberHide(member)) {
out->write("0");
}
} }
void void
@ -1557,7 +1515,7 @@ writeAccessor(Output* out, Object* member, Object* offset, bool unsafe = false)
} }
out->write("\n"); out->write("\n");
writeAccessorName(out, member, true, unsafe); writeAccessorName(out, member, unsafe);
if (memberOwner(member)->type == Object::Pod) { if (memberOwner(member)->type == Object::Pod) {
out->write("("); out->write("(");
out->write(capitalize(::typeName(memberOwner(member)))); out->write(capitalize(::typeName(memberOwner(member))));
@ -1876,7 +1834,7 @@ writeConstructorInitializations(Output* out, Object* t)
switch (m->type) { switch (m->type) {
case Object::Scalar: { case Object::Scalar: {
out->write(" "); out->write(" ");
writeAccessorName(out, m, true); writeAccessorName(out, m);
out->write("(t, o) = "); out->write("(t, o) = ");
out->write(obfuscate(memberName(m))); out->write(obfuscate(memberName(m)));
out->write(";\n"); out->write(";\n");
@ -1887,7 +1845,7 @@ writeConstructorInitializations(Output* out, Object* t)
if (memberTypeObject(m) == 0) { if (memberTypeObject(m) == 0) {
out->write("&"); out->write("&");
} }
writeAccessorName(out, m, true); writeAccessorName(out, m);
out->write("(t, o, 0), 0, length * "); out->write("(t, o, 0), 0, length * ");
out->write(arrayElementSize(m)); out->write(arrayElementSize(m));
out->write(");\n"); out->write(");\n");
@ -1914,7 +1872,6 @@ writeInitializerDeclarations(Output* out, Object* declarations)
case Object::Type: { case Object::Type: {
out->write("void init"); out->write("void init");
out->write(capitalize(typeName(o))); out->write(capitalize(typeName(o)));
if (typeHideConstructor(o)) out->write("0");
out->write("(Thread* t, object o"); out->write("(Thread* t, object o");
writeConstructorParameters(out, o); writeConstructorParameters(out, o);
@ -1936,7 +1893,6 @@ writeConstructorDeclarations(Output* out, Object* declarations)
case Object::Type: { case Object::Type: {
out->write("object make"); out->write("object make");
out->write(capitalize(typeName(o))); out->write(capitalize(typeName(o)));
if (typeHideConstructor(o)) out->write("0");
out->write("(Thread* t"); out->write("(Thread* t");
writeConstructorParameters(out, o); writeConstructorParameters(out, o);
@ -1958,7 +1914,6 @@ writeInitializers(Output* out, Object* declarations)
case Object::Type: { case Object::Type: {
out->write("void\ninit"); out->write("void\ninit");
out->write(capitalize(typeName(o))); out->write(capitalize(typeName(o)));
if (typeHideConstructor(o)) out->write("0");
out->write("(Thread* t, object o"); out->write("(Thread* t, object o");
writeConstructorParameters(out, o); writeConstructorParameters(out, o);
@ -1989,7 +1944,6 @@ writeConstructors(Output* out, Object* declarations)
case Object::Type: { case Object::Type: {
out->write("object make"); out->write("object make");
out->write(capitalize(typeName(o))); out->write(capitalize(typeName(o)));
if (typeHideConstructor(o)) out->write("0");
out->write("(Thread* t"); out->write("(Thread* t");
writeConstructorParameters(out, o); writeConstructorParameters(out, o);
@ -2027,7 +1981,6 @@ writeConstructors(Output* out, Object* declarations)
out->write(" init"); out->write(" init");
out->write(capitalize(typeName(o))); out->write(capitalize(typeName(o)));
if (typeHideConstructor(o)) out->write("0");
out->write("(t, o"); out->write("(t, o");
writeConstructorArguments(out, o); writeConstructorArguments(out, o);
out->write(");\n"); out->write(");\n");

View File

@ -10,6 +10,7 @@
#include "sys/stat.h" #include "sys/stat.h"
#include "windows.h" #include "windows.h"
#include "sys/timeb.h"
#undef max #undef max
#undef min #undef min
@ -40,25 +41,11 @@ class MutexResource {
HANDLE m; HANDLE m;
}; };
System::SignalHandler* segFaultHandler = 0; class MySystem;
LPTOP_LEVEL_EXCEPTION_FILTER oldSegFaultHandler = 0; MySystem* system;
LONG CALLBACK LONG CALLBACK
handleException(LPEXCEPTION_POINTERS e) handleException(LPEXCEPTION_POINTERS e);
{
if (e->ExceptionRecord->ExceptionCode == EXCEPTION_ACCESS_VIOLATION) {
bool jump = segFaultHandler->handleSignal
(reinterpret_cast<void**>(&(e->ContextRecord->Eip)),
reinterpret_cast<void**>(&(e->ContextRecord->Ebp)),
reinterpret_cast<void**>(&(e->ContextRecord->Esp)),
reinterpret_cast<void**>(&(e->ContextRecord->Ebx)));
if (jump) {
return EXCEPTION_CONTINUE_EXECUTION;
}
}
return EXCEPTION_CONTINUE_SEARCH;
}
DWORD WINAPI DWORD WINAPI
run(void* r) run(void* r)
@ -495,7 +482,14 @@ class MySystem: public System {
System::Library* next_; System::Library* next_;
}; };
MySystem() { MySystem(const char* crashDumpDirectory):
segFaultHandler(0),
oldSegFaultHandler(0),
crashDumpDirectory(crashDumpDirectory)
{
expect(this, system == 0);
system = this;
mutex = CreateMutex(0, false, 0); mutex = CreateMutex(0, false, 0);
assert(this, mutex); assert(this, mutex);
} }
@ -721,26 +715,116 @@ class MySystem: public System {
} }
virtual void abort() { virtual void abort() {
asm("int3"); // trigger an EXCEPTION_ACCESS_VIOLATION, which we will catch and
::abort(); // generate a debug dump for
*static_cast<int*>(0) = 0;
} }
virtual void dispose() { virtual void dispose() {
system = 0;
CloseHandle(mutex); CloseHandle(mutex);
::free(this); ::free(this);
} }
HANDLE mutex; HANDLE mutex;
System::SignalHandler* segFaultHandler;
LPTOP_LEVEL_EXCEPTION_FILTER oldSegFaultHandler;
const char* crashDumpDirectory;
}; };
struct MINIDUMP_EXCEPTION_INFORMATION {
DWORD thread;
LPEXCEPTION_POINTERS exception;
BOOL exceptionInCurrentAddressSpace;
};
struct MINIDUMP_USER_STREAM_INFORMATION;
struct MINIDUMP_CALLBACK_INFORMATION;
enum MINIDUMP_TYPE {
MiniDumpNormal = 0
};
typedef BOOL (*MiniDumpWriteDumpType)
(HANDLE processHandle,
DWORD processId,
HANDLE file,
MINIDUMP_TYPE type,
const MINIDUMP_EXCEPTION_INFORMATION* exception,
const MINIDUMP_USER_STREAM_INFORMATION* userStream,
const MINIDUMP_CALLBACK_INFORMATION* callback);
void
dump(LPEXCEPTION_POINTERS e, const char* directory)
{
HINSTANCE dbghelp = LoadLibrary("dbghelp.dll");
if (dbghelp) {
MiniDumpWriteDumpType MiniDumpWriteDump = reinterpret_cast
<MiniDumpWriteDumpType>(GetProcAddress(dbghelp, "MiniDumpWriteDump"));
if (MiniDumpWriteDump) {
char name[MAX_PATH];
_timeb tb;
_ftime(&tb);
snprintf(name, MAX_PATH, "%s\\crash-%lld.mdmp", directory,
(static_cast<int64_t>(tb.time) * 1000)
+ static_cast<int64_t>(tb.millitm));
HANDLE file = CreateFile
(name, FILE_WRITE_DATA, 0, 0, CREATE_ALWAYS, 0, 0);
if (file != INVALID_HANDLE_VALUE) {
MINIDUMP_EXCEPTION_INFORMATION exception
= { GetCurrentThreadId(), e, true };
MiniDumpWriteDump
(GetCurrentProcess(),
GetCurrentProcessId(),
file,
MiniDumpNormal,
&exception,
0,
0);
CloseHandle(file);
}
}
FreeLibrary(dbghelp);
}
}
LONG CALLBACK
handleException(LPEXCEPTION_POINTERS e)
{
if (e->ExceptionRecord->ExceptionCode == EXCEPTION_ACCESS_VIOLATION) {
bool jump = system->segFaultHandler->handleSignal
(reinterpret_cast<void**>(&(e->ContextRecord->Eip)),
reinterpret_cast<void**>(&(e->ContextRecord->Ebp)),
reinterpret_cast<void**>(&(e->ContextRecord->Esp)),
reinterpret_cast<void**>(&(e->ContextRecord->Ebx)));
if (jump) {
return EXCEPTION_CONTINUE_EXECUTION;
}
}
if (system->crashDumpDirectory) {
dump(e, system->crashDumpDirectory);
}
return EXCEPTION_CONTINUE_SEARCH;
}
} // namespace } // namespace
namespace vm { namespace vm {
System* System*
makeSystem() makeSystem(const char* crashDumpDirectory)
{ {
return new (malloc(sizeof(MySystem))) MySystem(); return new (malloc(sizeof(MySystem))) MySystem(crashDumpDirectory);
} }
} // namespace vm } // namespace vm

View File

@ -216,8 +216,6 @@ class Task {
public: public:
Task(Task* next): next(next) { } Task(Task* next): next(next) { }
virtual ~Task() { }
virtual void run(Context* c) = 0; virtual void run(Context* c) = 0;
Task* next; Task* next;

26
test/Zip.java Normal file
View File

@ -0,0 +1,26 @@
import java.io.InputStream;
import java.util.Enumeration;
import java.util.zip.ZipFile;
import java.util.zip.ZipEntry;
public class Zip {
public static void main(String[] args) throws Exception {
ZipFile file = new ZipFile("build/classpath.jar");
byte[] buffer = new byte[4096];
for (Enumeration<ZipEntry> e = file.entries(); e.hasMoreElements();) {
ZipEntry entry = e.nextElement();
InputStream in = file.getInputStream(entry);
try {
int size = 0;
int c; while ((c = in.read(buffer)) != -1) size += c;
System.out.println
(entry.getName() + " " + entry.getCompressedSize() + " " + size);
} finally {
in.read();
}
}
}
}

View File

@ -17,7 +17,7 @@ for test in ${tests}; do
printf "%16s" "${test}: " printf "%16s" "${test}: "
case ${mode} in case ${mode} in
debug|debug-fast|fast ) debug|debug-fast|fast|small )
${vm} ${flags} ${test} >>${log} 2>&1;; ${vm} ${flags} ${test} >>${log} 2>&1;;
stress* ) stress* )