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 <string.h>
#include <stdlib.h>
#include <stdint.h>
#include <dirent.h>
#include "jni.h"
#include "jni-util.h"
#ifdef WIN32
# include <windows.h>
# include <io.h>
# define OPEN _open
@ -34,6 +36,7 @@
# define OPEN_MASK O_BINARY
#else
# include <unistd.h>
# include "sys/mman.h"
# define OPEN open
# define CLOSE close
@ -47,6 +50,8 @@
# define OPEN_MASK 0
#endif
inline void* operator new(size_t, void* p) throw() { return p; }
namespace {
inline bool
@ -95,9 +100,118 @@ doWrite(JNIEnv* e, jint fd, const jbyte* data, jint length)
int r = WRITE(fd, data, length);
if (r != length) {
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
extern "C" JNIEXPORT jstring JNICALL
@ -333,3 +447,42 @@ Java_java_io_FileOutputStream_close(JNIEnv* e, jclass, jint 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 <string.h>
#include <stdlib.h>
#include <stdint.h>
#include <unistd.h>
#include "jni.h"

View File

@ -24,6 +24,13 @@ public class ByteArrayOutputStream extends OutputStream {
this(0);
}
public void reset() {
chain = null;
length = 0;
buffer = null;
position = 0;
}
public int size() {
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) {
int count = 0;
if (methodTable != null) {

View File

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

View File

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

View File

@ -74,7 +74,15 @@ public class StringBuffer implements CharSequence {
sb.append(b, 0, b.length);
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) {
sb.insert(i, s);
return this;
@ -85,6 +93,11 @@ public class StringBuffer implements CharSequence {
return this;
}
public synchronized StringBuffer insert(int i, int v) {
sb.insert(i, v);
return this;
}
public synchronized StringBuffer delete(int start, int end) {
sb.delete(start, end);
return this;
@ -112,6 +125,10 @@ public class StringBuffer implements CharSequence {
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,
int dstOffset)
{

View File

@ -154,6 +154,10 @@ public class StringBuilder implements CharSequence {
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) {
if (start >= end) {
return this;
@ -322,4 +326,10 @@ public class StringBuilder implements CharSequence {
public CharSequence subSequence(int start, int 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,
Object ... arguments)
private static native Object invoke(Method method, Object instance,
Object ... arguments)
throws InvocationTargetException, IllegalAccessException;
public Class getReturnType() {

View File

@ -45,6 +45,12 @@ public abstract class Calendar {
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) {
time = date.getTime();
}

View File

@ -11,7 +11,7 @@
package java.util;
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 country;

View File

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

View File

@ -58,6 +58,21 @@ public class Random {
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() {
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);
public abstract Enumeration<String> getKeys();
}

View File

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

View File

@ -61,8 +61,8 @@ public class Vector<T> implements List<T> {
return list.set(index, value);
}
public T setElementAt(T value, int index) {
return set(index, value);
public void setElementAt(T value, int index) {
set(index, value);
}
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
#define JNI_UTIL
#include "stdio.h"
#include "stdlib.h"
#undef JNIEXPORT
#ifdef __MINGW32__
# define JNIEXPORT __declspec(dllexport)
@ -23,15 +26,37 @@
namespace {
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_);
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);
}
}
inline void*
allocate(JNIEnv* e, unsigned size)
{
void* p = malloc(size);
if (p == 0) {
throwNew(e, "java/lang/OutOfMemoryError", 0);
}
return p;
}
} // namespace
#endif//JNI_UTIL

104
makefile
View File

@ -3,21 +3,18 @@ MAKEFLAGS = -s
name = avian
version = 0.1.1
build-arch = $(shell uname -m)
build-arch = $(shell uname -m | sed 's/^i.86$$/i386/')
ifeq ($(build-arch),Power)
build-arch = powerpc
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)
platform = $(build-platform)
platform = $(subst cygwin,windows,$(subst mingw32,windows,$(build-platform)))
ifeq ($(platform),windows)
arch = i386
@ -44,31 +41,38 @@ cxx = $(build-cxx)
cc = $(build-cc)
ar = ar
ranlib = ranlib
dlltool = dlltool
objcopy = objcopy
vg = nice valgrind --num-callers=32 --db-attach=yes --freelist-vol=100000000
vg += --leak-check=full --suppressions=valgrind.supp
db = gdb --args
javac = javac
jar = jar
javac = "$(JAVA_HOME)/bin/javac"
jar = "$(JAVA_HOME)/bin/jar"
strip = :
strip-all = --strip-all
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 \
-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)\" \
-DBOOT_CLASSPATH=\"[classpathJar]\"
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)
common-lflags = -lm -lz
build-lflags =
lflags = $(common-lflags) -lpthread -ldl
system = posix
@ -83,6 +87,8 @@ so-suffix = .so
shared = -shared
native-path = echo
ifeq ($(arch),i386)
object-arch = i386
object-format = elf32-i386
@ -96,8 +102,7 @@ ifeq ($(arch),powerpc)
endif
ifeq ($(platform),darwin)
build-cflags = $(common-cflags) -fPIC -fvisibility=hidden \
-I$(JAVA_HOME)/include/linux -I$(src)
build-cflags = $(common-cflags) -fPIC -fvisibility=hidden -I$(src)
lflags = $(common-lflags) -ldl -framework CoreFoundation
rdynamic =
strip-all = -S -x
@ -107,25 +112,37 @@ ifeq ($(platform),darwin)
endif
ifeq ($(platform),windows)
inc = $(root)/win32/include
lib = $(root)/win32/lib
inc = "$(root)/win32/include"
lib = "$(root)/win32/lib"
system = windows
object-format = pe-i386
so-prefix =
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
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
ifeq ($(mode),debug)
@ -144,6 +161,10 @@ ifeq ($(mode),fast)
cflags += -O3 -g3 -DNDEBUG
strip = strip
endif
ifeq ($(mode),small)
cflags += -Os -g3 -DNDEBUG
strip = strip
endif
cpp-objects = $(foreach x,$(1),$(patsubst $(2)/%.cpp,$(3)/%.o,$(x)))
asm-objects = $(foreach x,$(1),$(patsubst $(2)/%.S,$(3)/%-asm.o,$(x)))
@ -190,6 +211,11 @@ vm-sources = \
$(src)/process.cpp \
$(src)/$(asm).cpp
ifeq ($(heapdump),true)
vm-sources += $(src)/heapdump.cpp
cflags += -DAVIAN_HEAPDUMP
endif
vm-asm-sources = $(src)/$(asm).S
ifeq ($(process),compile)
@ -220,9 +246,9 @@ generator-objects = \
generator = $(native-build)/generator
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)
executable-dynamic = $(native-build)/$(name)-dynamic
executable-dynamic = $(native-build)/$(name)-dynamic${exe-suffix}
classpath-sources = $(shell find $(classpath) -name '*.java')
classpath-classes = \
@ -261,7 +287,7 @@ vg: build
.PHONY: test
test: build
/bin/bash $(test)/test.sh 2>/dev/null \
/bin/sh $(test)/test.sh 2>/dev/null \
$(executable) $(mode) "$(flags)" \
$(call class-names,$(test-build),$(test-classes))
@ -299,7 +325,7 @@ $(classpath-dep): $(classpath-sources)
@echo "compiling classpath classes"
@mkdir -p $(dir $(@))
$(javac) -d $(dir $(@)) -bootclasspath $(classpath-build) \
$(shell make -s --no-print-directory $(classpath-classes))
$(shell $(MAKE) -s --no-print-directory $(classpath-classes))
@touch $(@)
$(test-build)/%.class: $(test)/%.java
@ -309,7 +335,7 @@ $(test-dep): $(test-sources)
@echo "compiling test classes"
@mkdir -p $(dir $(@))
$(javac) -d $(dir $(@)) -bootclasspath $(classpath-build) \
$(shell make -s --no-print-directory $(test-classes))
$(shell $(MAKE) -s --no-print-directory $(test-classes))
@touch $(@)
define compile-object
@ -318,11 +344,17 @@ define compile-object
$(cxx) $(cflags) -c $(<) -o $(@)
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)
$(compile-object)
$(vm-asm-objects): $(native-build)/%-asm.o: $(src)/%.S
$(compile-object)
$(compile-asm-object)
$(driver-object): $(driver-source)
$(compile-object)
@ -339,7 +371,7 @@ $(boot-object): $(boot-source)
$(build)/classpath.jar: $(classpath-dep)
(wd=$$(pwd); \
cd $(classpath-build); \
$(jar) c0f $${wd}/$(@) $$(find . -name '*.class'))
$(jar) c0f "$$($(native-path) "$${wd}/$(@)")" $$(find . -name '*.class'))
$(binaryToMacho): $(src)/binaryToMacho.cpp
$(cxx) $(^) -o $(@)
@ -353,7 +385,7 @@ else
(wd=$$(pwd); \
cd $(build); \
$(objcopy) -I binary classpath.jar \
-O $(object-format) -B $(object-arch) $${wd}/$(@))
-O $(object-format) -B $(object-arch) "$${wd}/$(@)")
endif
$(generator-objects): $(native-build)/%.o: $(src)/%.cpp
@ -377,7 +409,7 @@ $(executable): \
@echo "linking $(@)"
ifeq ($(platform),windows)
$(dlltool) -z $(@).def $(^)
$(dlltool) -k -d $(@).def -e $(@).exp
$(dlltool) -d $(@).def -e $(@).exp
$(cc) $(@).exp $(^) $(lflags) -o $(@)
else
$(cc) $(^) $(rdynamic) $(lflags) -o $(@)
@ -398,5 +430,5 @@ $(executable-dynamic): $(driver-dynamic-object) $(dynamic-library)
$(generator): $(generator-objects)
@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
$ make
$ 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
@ -40,10 +55,6 @@ Avian can currently target the following platforms:
Win32 (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
--------
@ -60,20 +71,11 @@ Build requirements include:
Earlier versions of some of these packages may also work but have not
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
certain flags described below.
$ 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
default: output of $(uname -s | tr [:upper:] [:lower:])
@ -89,6 +91,33 @@ certain flags described below.
* process - choice between pure interpreter or JIT compiler
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
----------
@ -102,6 +131,9 @@ Embedding
The following series of commands illustrates how to produce a
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
VM object files and bootstrap classpath jar.
@ -223,7 +255,17 @@ main(int ac, const char** av)
return exitCode;
}
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
@ -237,3 +279,9 @@ on Mac OS X:
$ g++ -rdynamic *.o -ldl -lpthread -lz -o hello -framework CoreFoundation
$ 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 {
public:
virtual ~Allocator() { }
virtual void* tryAllocate(unsigned size) = 0;
virtual void* allocate(unsigned size) = 0;
virtual void free(const void* p, unsigned size) = 0;

View File

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

View File

@ -11,10 +11,9 @@
#include "stdint.h"
#include "stdlib.h"
// since we don't link against libstdc++, we must implement some dummy
// functions:
// since we aren't linking against libstdc++, we must implement this
// ourselves:
extern "C" void __cxa_pure_virtual(void) { abort(); }
void operator delete(void*) { abort(); }
#ifdef __MINGW32__
# 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()));
} else if (strcmp(n, "avian.version") == 0) {
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) {
@ -536,8 +543,9 @@ Java_java_lang_Runtime_load(Thread* t, jclass, jstring name, jboolean mapName)
char n[length + 1];
stringChars(t, *name, n);
if (mapName and t->m->builtins) {
const char* s = t->m->builtins;
const char* builtins = findProperty(t, "avian.builtins");
if (mapName and builtins) {
const char* s = builtins;
while (*s) {
if (strncmp(s, n, 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);
}
#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
Java_java_lang_Runtime_exit(Thread* t, jobject, jint code)
{

View File

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

View File

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

View File

@ -21,8 +21,6 @@ class Compiler {
public:
class Client {
public:
virtual ~Client() { }
virtual intptr_t getThunk(UnaryOperation op, unsigned size) = 0;
virtual intptr_t getThunk(TernaryOperation op, unsigned size) = 0;
};
@ -34,8 +32,6 @@ class Compiler {
class StackElement { };
class State { };
virtual ~Compiler() { }
virtual State* saveState() = 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 {
public:
Element(): next(0) { }
virtual ~Element() { }
virtual System::Region* find(const char* name) = 0;
virtual bool exists(const char* name) = 0;
virtual void dispose() = 0;
@ -372,7 +372,7 @@ class JarIndex {
class JarElement: public Element {
public:
JarElement(System* s, const char* name):
s(s), name(name), index(0)
s(s), name(name), region(0), index(0)
{ }
virtual void init() {

View File

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

View File

@ -32,19 +32,16 @@ class Heap: public Allocator {
class Visitor {
public:
virtual ~Visitor() { }
virtual void visit(void*) = 0;
};
class Walker {
public:
virtual ~Walker() { }
virtual bool visit(unsigned) = 0;
};
class Client {
public:
virtual ~Client() { }
virtual void collect(void* context, CollectionType type) = 0;
virtual void visitRoots(Visitor*) = 0;
virtual bool isFixed(void*) = 0;
@ -54,7 +51,6 @@ class Heap: public Allocator {
virtual void walk(void*, Walker*) = 0;
};
virtual ~Heap() { }
virtual void setClient(Client* client) = 0;
virtual void collect(CollectionType type, unsigned footprint) = 0;
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
#define BUILTINS_PROPERTY "avian.builtins"
#define BOOTSTRAP_PROPERTY "avian.bootstrap"
#define CRASHDIR_PROPERTY "avian.crash.dir"
#define CLASSPATH_PROPERTY "java.class.path"
#define BOOTCLASSPATH_PREPEND_OPTION "bootclasspath/p"
#define BOOTCLASSPATH_OPTION "bootclasspath"
#define BOOTCLASSPATH_APPEND_OPTION "bootclasspath/a"
#define BOOTCLASSPATH_APPEND_OPTION "bootclasspath/a"
extern "C" JNIEXPORT jint JNICALL
JNI_GetDefaultJavaVMInitArgs(void*)
@ -2065,12 +2066,14 @@ JNI_CreateJavaVM(Machine** m, Thread** t, void* args)
JavaVMInitArgs* a = static_cast<JavaVMInitArgs*>(args);
unsigned heapLimit = 0;
const char* builtins = 0;
const char* bootLibrary = 0;
const char* classpath = 0;
const char* bootClasspathPrepend = "";
const char* bootClasspath = "";
const char* bootClasspathAppend = "";
const char* crashDumpDirectory = 0;
unsigned propertyCount = 0;
for (int i = 0; i < a->nOptions; ++i) {
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) {
const char* p = a->options[i].optionString + 2;
if (strncmp(p, BUILTINS_PROPERTY "=",
sizeof(BUILTINS_PROPERTY)) == 0)
{
builtins = p + sizeof(BUILTINS_PROPERTY);
} else if (strncmp(p, BOOTSTRAP_PROPERTY "=",
sizeof(BOOTSTRAP_PROPERTY)) == 0)
if (strncmp(p, BOOTSTRAP_PROPERTY "=",
sizeof(BOOTSTRAP_PROPERTY)) == 0)
{
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 "=",
sizeof(CLASSPATH_PROPERTY)) == 0)
{
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, classpath, cpl, 0);
System* s = makeSystem();
System* s = makeSystem(crashDumpDirectory);
Heap* h = makeHeap(s, heapLimit);
Finder* f = makeFinder(s, classpathBuffer, bootLibrary);
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)))
Machine(s, h, f, p, bootLibrary, builtins);
Machine(s, h, f, p, properties, propertyCount);
*t = p->makeThread(*m, 0, 0);

View File

@ -198,13 +198,13 @@ visitRoots(Thread* t, Heap::Visitor* v)
void
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 arrayElementSizeInWords
= 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 (not w->visit(i)) {
return;
@ -222,8 +222,19 @@ walk(Thread*, Heap::Walker* w, uint32_t* mask, unsigned fixedSize,
}
if (arrayObjectElements) {
for (unsigned i = 0; i < arrayLength; ++i) {
for (unsigned j = 0; j < arrayElementSizeInWords; ++j) {
unsigned arrayStart;
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;
if (mask[k / 32] & (static_cast<uint32_t>(1) << (k % 32))) {
if (not w->visit
@ -238,7 +249,7 @@ walk(Thread*, Heap::Walker* w, uint32_t* mask, unsigned fixedSize,
}
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 objectMask = static_cast<object>
@ -255,16 +266,16 @@ walk(Thread* t, Heap::Walker* w, object o)
memcpy(mask, &intArrayBody(t, objectMask, 0),
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) {
unsigned length = singletonLength(t, o);
if (length) {
walk(t, w, singletonMask(t, o),
(singletonCount(t, o) + 2) * BytesPerWord, 0, 0);
} else {
(singletonCount(t, o) + 2) * BytesPerWord, 0, 0, start);
} else if (start == 0) {
w->visit(0);
}
} else {
} else if (start == 0) {
w->visit(0);
}
}
@ -1534,20 +1545,7 @@ class HeapClient: public Heap::Client {
HeapClient(Machine* m): m(m) { }
virtual void visitRoots(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);
}
::visitRoots(m, v);
postVisit(m->rootThread, v);
}
@ -1616,7 +1614,7 @@ class HeapClient: public Heap::Client {
virtual void walk(void* p, Heap::Walker* w) {
object o = static_cast<object>(m->heap->follow(mask(p)));
::walk(m->rootThread, w, o);
::walk(m->rootThread, w, o, 0);
}
void dispose() {
@ -1632,8 +1630,8 @@ class HeapClient: public Heap::Client {
namespace vm {
Machine::Machine(System* system, Heap* heap, Finder* finder,
Processor* processor, const char* bootLibrary,
const char* builtins):
Processor* processor, const char** properties,
unsigned propertyCount):
vtable(&javaVMVTable),
system(system),
heapClient(new (heap->allocate(sizeof(HeapClient)))
@ -1644,7 +1642,8 @@ Machine::Machine(System* system, Heap* heap, Finder* finder,
rootThread(0),
exclusive(0),
jniReferences(0),
builtins(builtins),
properties(properties),
propertyCount(propertyCount),
activeCount(0),
liveCount(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(&classLock)) 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();
}
@ -1706,6 +1706,8 @@ Machine::dispose()
heap->free(heapPool[i], Thread::HeapSizeInBytes);
}
heap->free(properties, sizeof(const char*) * propertyCount);
static_cast<HeapClient*>(heapClient)->dispose();
heap->free(this, sizeof(*this));
@ -2595,12 +2597,14 @@ findInHierarchy(Thread* t, object class_, object name, object spec,
PROTECT(t, class_);
object o = 0;
if (classFlags(t, class_) & ACC_INTERFACE) {
if (classVirtualTable(t, class_)) {
o = findInTable
(t, classVirtualTable(t, class_), name, spec, methodName, methodSpec);
}
} else {
if ((classFlags(t, class_) & ACC_INTERFACE)
and classVirtualTable(t, class_))
{
o = findInTable
(t, classVirtualTable(t, class_), name, spec, methodName, methodSpec);
}
if (o == 0) {
for (; o == 0 and class_; class_ = classSuper(t, class_)) {
o = find(t, class_, name, spec);
}
@ -2765,6 +2769,44 @@ collect(Thread* t, Heap::CollectionType type)
#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
printTrace(Thread* t, object exception)
{

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -10,6 +10,7 @@
#include "sys/stat.h"
#include "windows.h"
#include "sys/timeb.h"
#undef max
#undef min
@ -40,25 +41,11 @@ class MutexResource {
HANDLE m;
};
System::SignalHandler* segFaultHandler = 0;
LPTOP_LEVEL_EXCEPTION_FILTER oldSegFaultHandler = 0;
class MySystem;
MySystem* system;
LONG CALLBACK
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;
}
handleException(LPEXCEPTION_POINTERS e);
DWORD WINAPI
run(void* r)
@ -495,7 +482,14 @@ class MySystem: public System {
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);
assert(this, mutex);
}
@ -721,26 +715,116 @@ class MySystem: public System {
}
virtual void abort() {
asm("int3");
::abort();
// trigger an EXCEPTION_ACCESS_VIOLATION, which we will catch and
// generate a debug dump for
*static_cast<int*>(0) = 0;
}
virtual void dispose() {
system = 0;
CloseHandle(mutex);
::free(this);
}
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 vm {
System*
makeSystem()
makeSystem(const char* crashDumpDirectory)
{
return new (malloc(sizeof(MySystem))) MySystem();
return new (malloc(sizeof(MySystem))) MySystem(crashDumpDirectory);
}
} // namespace vm

View File

@ -216,8 +216,6 @@ class Task {
public:
Task(Task* next): next(next) { }
virtual ~Task() { }
virtual void run(Context* c) = 0;
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}: "
case ${mode} in
debug|debug-fast|fast )
debug|debug-fast|fast|small )
${vm} ${flags} ${test} >>${log} 2>&1;;
stress* )