mirror of
https://github.com/corda/corda.git
synced 2025-01-04 04:04:27 +00:00
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:
parent
2304a656cf
commit
c80eb51c17
@ -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));
|
||||||
|
}
|
||||||
|
@ -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"
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
72
classpath/java/io/RandomAccessFile.java
Normal file
72
classpath/java/io/RandomAccessFile.java
Normal 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);
|
||||||
|
}
|
@ -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) {
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
|
@ -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)
|
||||||
{
|
{
|
||||||
|
@ -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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -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() {
|
||||||
|
@ -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();
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
|
@ -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();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
@ -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();
|
||||||
}
|
}
|
||||||
|
@ -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() {
|
||||||
|
@ -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) {
|
||||||
|
16
classpath/java/util/zip/ZipEntry.java
Normal file
16
classpath/java/util/zip/ZipEntry.java
Normal 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();
|
||||||
|
}
|
313
classpath/java/util/zip/ZipFile.java
Normal file
313
classpath/java/util/zip/ZipFile.java
Normal 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -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
104
makefile
@ -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 $(@)
|
||||||
|
|
||||||
|
78
readme.txt
78
readme.txt
@ -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
|
||||||
|
@ -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;
|
||||||
|
@ -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;
|
||||||
|
@ -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)
|
||||||
|
@ -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)
|
||||||
{
|
{
|
||||||
|
@ -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;
|
||||||
|
|
||||||
|
@ -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;
|
||||||
|
@ -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;
|
||||||
|
|
||||||
|
@ -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() {
|
||||||
|
@ -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;
|
||||||
|
@ -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
329
src/heapdump.cpp
Normal 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
|
@ -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);
|
||||||
|
|
||||||
|
110
src/machine.cpp
110
src/machine.cpp
@ -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)
|
||||||
{
|
{
|
||||||
|
@ -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
|
||||||
|
@ -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();
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
|
@ -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;
|
||||||
|
@ -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;
|
||||||
|
|
||||||
|
@ -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;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
14
src/system.h
14
src/system.h
@ -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
|
||||||
|
|
||||||
|
@ -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");
|
||||||
|
128
src/windows.cpp
128
src/windows.cpp
@ -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
|
||||||
|
@ -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
26
test/Zip.java
Normal 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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -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* )
|
||||||
|
Loading…
Reference in New Issue
Block a user