mirror of
https://github.com/corda/corda.git
synced 2025-01-17 10:20:02 +00:00
Merge remote branch 'origin/master' into openjdk
Conflicts: makefile src/compile.cpp src/compiler.cpp src/type-generator.cpp
This commit is contained in:
commit
a611ccda6f
@ -164,17 +164,17 @@ Java_java_lang_Runtime_exec(JNIEnv* e, jclass,
|
|||||||
SetHandleInformation(in[0], HANDLE_FLAG_INHERIT, 0);
|
SetHandleInformation(in[0], HANDLE_FLAG_INHERIT, 0);
|
||||||
jlong inDescriptor = static_cast<jlong>(descriptor(e, in[0]));
|
jlong inDescriptor = static_cast<jlong>(descriptor(e, in[0]));
|
||||||
if(e->ExceptionCheck()) return;
|
if(e->ExceptionCheck()) return;
|
||||||
e->SetLongArrayRegion(process, 1, 1, &inDescriptor);
|
e->SetLongArrayRegion(process, 2, 1, &inDescriptor);
|
||||||
makePipe(e, out);
|
makePipe(e, out);
|
||||||
SetHandleInformation(out[1], HANDLE_FLAG_INHERIT, 0);
|
SetHandleInformation(out[1], HANDLE_FLAG_INHERIT, 0);
|
||||||
jlong outDescriptor = static_cast<jlong>(descriptor(e, out[1]));
|
jlong outDescriptor = static_cast<jlong>(descriptor(e, out[1]));
|
||||||
if(e->ExceptionCheck()) return;
|
if(e->ExceptionCheck()) return;
|
||||||
e->SetLongArrayRegion(process, 2, 1, &outDescriptor);
|
e->SetLongArrayRegion(process, 3, 1, &outDescriptor);
|
||||||
makePipe(e, err);
|
makePipe(e, err);
|
||||||
SetHandleInformation(err[0], HANDLE_FLAG_INHERIT, 0);
|
SetHandleInformation(err[0], HANDLE_FLAG_INHERIT, 0);
|
||||||
jlong errDescriptor = static_cast<jlong>(descriptor(e, err[0]));
|
jlong errDescriptor = static_cast<jlong>(descriptor(e, err[0]));
|
||||||
if(e->ExceptionCheck()) return;
|
if(e->ExceptionCheck()) return;
|
||||||
e->SetLongArrayRegion(process, 3, 1, &errDescriptor);
|
e->SetLongArrayRegion(process, 4, 1, &errDescriptor);
|
||||||
|
|
||||||
PROCESS_INFORMATION pi;
|
PROCESS_INFORMATION pi;
|
||||||
ZeroMemory(&pi, sizeof(pi));
|
ZeroMemory(&pi, sizeof(pi));
|
||||||
@ -191,6 +191,10 @@ Java_java_lang_Runtime_exec(JNIEnv* e, jclass,
|
|||||||
CREATE_NO_WINDOW | CREATE_UNICODE_ENVIRONMENT,
|
CREATE_NO_WINDOW | CREATE_UNICODE_ENVIRONMENT,
|
||||||
0, 0, &si, &pi);
|
0, 0, &si, &pi);
|
||||||
|
|
||||||
|
CloseHandle(in[1]);
|
||||||
|
CloseHandle(out[0]);
|
||||||
|
CloseHandle(err[1]);
|
||||||
|
|
||||||
if (not success) {
|
if (not success) {
|
||||||
throwNew(e, "java/io/IOException", getErrorStr(GetLastError()));
|
throwNew(e, "java/io/IOException", getErrorStr(GetLastError()));
|
||||||
return;
|
return;
|
||||||
@ -198,24 +202,12 @@ Java_java_lang_Runtime_exec(JNIEnv* e, jclass,
|
|||||||
|
|
||||||
jlong pid = reinterpret_cast<jlong>(pi.hProcess);
|
jlong pid = reinterpret_cast<jlong>(pi.hProcess);
|
||||||
e->SetLongArrayRegion(process, 0, 1, &pid);
|
e->SetLongArrayRegion(process, 0, 1, &pid);
|
||||||
|
jlong tid = reinterpret_cast<jlong>(pi.hThread);
|
||||||
|
e->SetLongArrayRegion(process, 1, 1, &tid);
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" JNIEXPORT jint JNICALL
|
extern "C" JNIEXPORT jint JNICALL
|
||||||
Java_java_lang_Runtime_exitValue(JNIEnv* e, jclass, jlong pid)
|
Java_java_lang_Runtime_waitFor(JNIEnv* e, jclass, jlong pid, jlong tid)
|
||||||
{
|
|
||||||
DWORD exitCode;
|
|
||||||
BOOL success = GetExitCodeProcess(reinterpret_cast<HANDLE>(pid), &exitCode);
|
|
||||||
if(not success){
|
|
||||||
throwNew(e, "java/lang/Exception", getErrorStr(GetLastError()));
|
|
||||||
} else if(exitCode == STILL_ACTIVE){
|
|
||||||
throwNew(e, "java/lang/IllegalThreadStateException", "Process is still active");
|
|
||||||
}
|
|
||||||
return exitCode;
|
|
||||||
}
|
|
||||||
|
|
||||||
extern "C" JNIEXPORT jint JNICALL
|
|
||||||
Java_java_lang_Runtime_waitFor(JNIEnv* e, jclass, jlong pid)
|
|
||||||
{
|
{
|
||||||
DWORD exitCode;
|
DWORD exitCode;
|
||||||
WaitForSingleObject(reinterpret_cast<HANDLE>(pid), INFINITE);
|
WaitForSingleObject(reinterpret_cast<HANDLE>(pid), INFINITE);
|
||||||
@ -223,6 +215,10 @@ Java_java_lang_Runtime_waitFor(JNIEnv* e, jclass, jlong pid)
|
|||||||
if(not success){
|
if(not success){
|
||||||
throwNew(e, "java/lang/Exception", getErrorStr(GetLastError()));
|
throwNew(e, "java/lang/Exception", getErrorStr(GetLastError()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CloseHandle(reinterpret_cast<HANDLE>(pid));
|
||||||
|
CloseHandle(reinterpret_cast<HANDLE>(tid));
|
||||||
|
|
||||||
return exitCode;
|
return exitCode;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
@ -248,15 +244,15 @@ Java_java_lang_Runtime_exec(JNIEnv* e, jclass,
|
|||||||
makePipe(e, in);
|
makePipe(e, in);
|
||||||
if(e->ExceptionCheck()) return;
|
if(e->ExceptionCheck()) return;
|
||||||
jlong inDescriptor = static_cast<jlong>(in[0]);
|
jlong inDescriptor = static_cast<jlong>(in[0]);
|
||||||
e->SetLongArrayRegion(process, 1, 1, &inDescriptor);
|
e->SetLongArrayRegion(process, 2, 1, &inDescriptor);
|
||||||
makePipe(e, out);
|
makePipe(e, out);
|
||||||
if(e->ExceptionCheck()) return;
|
if(e->ExceptionCheck()) return;
|
||||||
jlong outDescriptor = static_cast<jlong>(out[1]);
|
jlong outDescriptor = static_cast<jlong>(out[1]);
|
||||||
e->SetLongArrayRegion(process, 2, 1, &outDescriptor);
|
e->SetLongArrayRegion(process, 3, 1, &outDescriptor);
|
||||||
makePipe(e, err);
|
makePipe(e, err);
|
||||||
if(e->ExceptionCheck()) return;
|
if(e->ExceptionCheck()) return;
|
||||||
jlong errDescriptor = static_cast<jlong>(err[0]);
|
jlong errDescriptor = static_cast<jlong>(err[0]);
|
||||||
e->SetLongArrayRegion(process, 3, 1, &errDescriptor);
|
e->SetLongArrayRegion(process, 4, 1, &errDescriptor);
|
||||||
makePipe(e, msg);
|
makePipe(e, msg);
|
||||||
if(e->ExceptionCheck()) return;
|
if(e->ExceptionCheck()) return;
|
||||||
if(fcntl(msg[1], F_SETFD, FD_CLOEXEC) != 0) {
|
if(fcntl(msg[1], F_SETFD, FD_CLOEXEC) != 0) {
|
||||||
@ -317,21 +313,7 @@ Java_java_lang_Runtime_exec(JNIEnv* e, jclass,
|
|||||||
}
|
}
|
||||||
|
|
||||||
extern "C" JNIEXPORT jint JNICALL
|
extern "C" JNIEXPORT jint JNICALL
|
||||||
Java_java_lang_Runtime_exitValue(JNIEnv* e, jclass, jlong pid)
|
Java_java_lang_Runtime_waitFor(JNIEnv*, jclass, jlong pid, jlong)
|
||||||
{
|
|
||||||
int status;
|
|
||||||
pid_t returned = waitpid(pid, &status, WNOHANG);
|
|
||||||
if(returned == 0){
|
|
||||||
throwNewErrno(e, "java/lang/IllegalThreadStateException");
|
|
||||||
} else if(returned == -1){
|
|
||||||
throwNewErrno(e, "java/lang/Exception");
|
|
||||||
}
|
|
||||||
|
|
||||||
return WEXITSTATUS(status);
|
|
||||||
}
|
|
||||||
|
|
||||||
extern "C" JNIEXPORT jint JNICALL
|
|
||||||
Java_java_lang_Runtime_waitFor(JNIEnv*, jclass, jlong pid)
|
|
||||||
{
|
{
|
||||||
bool finished = false;
|
bool finished = false;
|
||||||
int status;
|
int status;
|
||||||
|
@ -44,28 +44,80 @@ public class Runtime {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public Process exec(String command) throws IOException {
|
public Process exec(String command) throws IOException {
|
||||||
long[] process = new long[4];
|
|
||||||
StringTokenizer t = new StringTokenizer(command);
|
StringTokenizer t = new StringTokenizer(command);
|
||||||
String[] cmd = new String[t.countTokens()];
|
String[] cmd = new String[t.countTokens()];
|
||||||
for (int i = 0; i < cmd.length; i++)
|
for (int i = 0; i < cmd.length; i++)
|
||||||
cmd[i] = t.nextToken();
|
cmd[i] = t.nextToken();
|
||||||
exec(cmd, process);
|
|
||||||
return new MyProcess(process[0], (int) process[1], (int) process[2], (int) process[3]);
|
return exec(cmd);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Process exec(String[] command) {
|
public Process exec(final String[] command) throws IOException {
|
||||||
long[] process = new long[4];
|
final MyProcess[] process = new MyProcess[1];
|
||||||
exec(command, process);
|
final Throwable[] exception = new Throwable[1];
|
||||||
return new MyProcess(process[0], (int) process[1], (int) process[2], (int) process[3]);
|
|
||||||
|
synchronized (process) {
|
||||||
|
Thread t = new Thread() {
|
||||||
|
public void run() {
|
||||||
|
synchronized (process) {
|
||||||
|
try {
|
||||||
|
long[] info = new long[5];
|
||||||
|
exec(command, info);
|
||||||
|
process[0] = new MyProcess
|
||||||
|
(info[0], info[1], (int) info[2], (int) info[3],
|
||||||
|
(int) info[4]);
|
||||||
|
} catch (Throwable e) {
|
||||||
|
exception[0] = e;
|
||||||
|
} finally {
|
||||||
|
process.notifyAll();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
MyProcess p = process[0];
|
||||||
|
if (p != null) {
|
||||||
|
synchronized (p) {
|
||||||
|
try {
|
||||||
|
if (p.pid != 0) {
|
||||||
|
p.exitCode = Runtime.waitFor(p.pid, p.tid);
|
||||||
|
p.pid = 0;
|
||||||
|
p.tid = 0;
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
p.notifyAll();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
t.setDaemon(true);
|
||||||
|
t.start();
|
||||||
|
|
||||||
|
while (process[0] == null && exception[0] == null) {
|
||||||
|
try {
|
||||||
|
process.wait();
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (exception[0] != null) {
|
||||||
|
if (exception[0] instanceof IOException) {
|
||||||
|
throw new IOException(exception[0]);
|
||||||
|
} else {
|
||||||
|
throw new RuntimeException(exception[0]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return process[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
public native void addShutdownHook(Thread t);
|
public native void addShutdownHook(Thread t);
|
||||||
|
|
||||||
private static native void exec(String[] command, long[] process);
|
private static native void exec(String[] command, long[] process)
|
||||||
|
throws IOException;
|
||||||
|
|
||||||
private static native int exitValue(long pid);
|
private static native int waitFor(long pid, long tid);
|
||||||
|
|
||||||
private static native int waitFor(long pid);
|
|
||||||
|
|
||||||
private static native void load(String name, boolean mapName);
|
private static native void load(String name, boolean mapName);
|
||||||
|
|
||||||
@ -79,13 +131,15 @@ public class Runtime {
|
|||||||
|
|
||||||
private static class MyProcess extends Process {
|
private static class MyProcess extends Process {
|
||||||
private long pid;
|
private long pid;
|
||||||
|
private long tid;
|
||||||
private final int in;
|
private final int in;
|
||||||
private final int out;
|
private final int out;
|
||||||
private final int err;
|
private final int err;
|
||||||
private int exitCode;
|
private int exitCode;
|
||||||
|
|
||||||
public MyProcess(long pid, int in, int out, int err) {
|
public MyProcess(long pid, long tid, int in, int out, int err) {
|
||||||
this.pid = pid;
|
this.pid = pid;
|
||||||
|
this.tid = tid;
|
||||||
this.in = in;
|
this.in = in;
|
||||||
this.out = out;
|
this.out = out;
|
||||||
this.err = err;
|
this.err = err;
|
||||||
@ -95,13 +149,6 @@ public class Runtime {
|
|||||||
throw new RuntimeException("not implemented");
|
throw new RuntimeException("not implemented");
|
||||||
}
|
}
|
||||||
|
|
||||||
public int exitValue() {
|
|
||||||
if (pid != 0) {
|
|
||||||
exitCode = Runtime.exitValue(pid);
|
|
||||||
}
|
|
||||||
return exitCode;
|
|
||||||
}
|
|
||||||
|
|
||||||
public InputStream getInputStream() {
|
public InputStream getInputStream() {
|
||||||
return new FileInputStream(new FileDescriptor(in));
|
return new FileInputStream(new FileDescriptor(in));
|
||||||
}
|
}
|
||||||
@ -114,11 +161,19 @@ public class Runtime {
|
|||||||
return new FileInputStream(new FileDescriptor(err));
|
return new FileInputStream(new FileDescriptor(err));
|
||||||
}
|
}
|
||||||
|
|
||||||
public int waitFor() throws InterruptedException {
|
public synchronized int exitValue() {
|
||||||
if (pid != 0) {
|
if (pid != 0) {
|
||||||
exitCode = Runtime.waitFor(pid);
|
throw new IllegalThreadStateException();
|
||||||
pid = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return exitCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized int waitFor() throws InterruptedException {
|
||||||
|
while (pid != 0) {
|
||||||
|
wait();
|
||||||
|
}
|
||||||
|
|
||||||
return exitCode;
|
return exitCode;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
34
makefile
34
makefile
@ -191,13 +191,23 @@ endif
|
|||||||
ifeq ($(arch),arm)
|
ifeq ($(arch),arm)
|
||||||
asm = arm
|
asm = arm
|
||||||
pointer-size = 4
|
pointer-size = 4
|
||||||
|
cflags += -Wno-psabi
|
||||||
|
|
||||||
|
ifneq ($(arch),$(build-arch))
|
||||||
|
cxx = arm-linux-gnueabi-g++
|
||||||
|
cc = arm-linux-gnueabi-gcc
|
||||||
|
ar = arm-linux-gnueabi-ar
|
||||||
|
ranlib = arm-linux-gnueabi-ranlib
|
||||||
|
strip = arm-linux-gnueabi-strip
|
||||||
|
endif
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifeq ($(platform),darwin)
|
ifeq ($(platform),darwin)
|
||||||
version-script-flag =
|
version-script-flag =
|
||||||
build-cflags = $(common-cflags) -fPIC -fvisibility=hidden -I$(src)
|
build-cflags = $(common-cflags) -fPIC -fvisibility=hidden -I$(src)
|
||||||
build-lflags += -framework CoreFoundation
|
build-lflags += -framework CoreFoundation
|
||||||
lflags = $(common-lflags) -ldl -framework CoreFoundation -framework CoreServices
|
lflags = $(common-lflags) -ldl -framework CoreFoundation \
|
||||||
|
-framework CoreServices
|
||||||
ifeq ($(bootimage),true)
|
ifeq ($(bootimage),true)
|
||||||
bootimage-lflags = -Wl,-segprot,__RWX,rwx,rwx
|
bootimage-lflags = -Wl,-segprot,__RWX,rwx,rwx
|
||||||
endif
|
endif
|
||||||
@ -207,6 +217,9 @@ ifeq ($(platform),darwin)
|
|||||||
shared = -dynamiclib
|
shared = -dynamiclib
|
||||||
|
|
||||||
ifeq ($(arch),powerpc)
|
ifeq ($(arch),powerpc)
|
||||||
|
ifneq (,$(filter i386 x86_64,$(build-arch)))
|
||||||
|
converter-cflags = -DOPPOSITE_ENDIAN
|
||||||
|
endif
|
||||||
openjdk-extra-cflags += -arch ppc
|
openjdk-extra-cflags += -arch ppc
|
||||||
cflags += -arch ppc
|
cflags += -arch ppc
|
||||||
asmflags += -arch ppc
|
asmflags += -arch ppc
|
||||||
@ -214,6 +227,9 @@ ifeq ($(platform),darwin)
|
|||||||
endif
|
endif
|
||||||
|
|
||||||
ifeq ($(arch),i386)
|
ifeq ($(arch),i386)
|
||||||
|
ifeq ($(build-arch),powerpc)
|
||||||
|
converter-cflags = -DOPPOSITE_ENDIAN
|
||||||
|
endif
|
||||||
openjdk-extra-cflags += -arch i386
|
openjdk-extra-cflags += -arch i386
|
||||||
cflags += -arch i386
|
cflags += -arch i386
|
||||||
asmflags += -arch i386
|
asmflags += -arch i386
|
||||||
@ -221,6 +237,9 @@ ifeq ($(platform),darwin)
|
|||||||
endif
|
endif
|
||||||
|
|
||||||
ifeq ($(arch),x86_64)
|
ifeq ($(arch),x86_64)
|
||||||
|
ifeq ($(build-arch),powerpc)
|
||||||
|
converter-cflags = -DOPPOSITE_ENDIAN
|
||||||
|
endif
|
||||||
openjdk-extra-cflags += -arch x86_64
|
openjdk-extra-cflags += -arch x86_64
|
||||||
cflags += -arch x86_64
|
cflags += -arch x86_64
|
||||||
asmflags += -arch x86_64
|
asmflags += -arch x86_64
|
||||||
@ -364,7 +383,8 @@ generated-code = \
|
|||||||
$(build)/type-declarations.cpp \
|
$(build)/type-declarations.cpp \
|
||||||
$(build)/type-constructors.cpp \
|
$(build)/type-constructors.cpp \
|
||||||
$(build)/type-initializations.cpp \
|
$(build)/type-initializations.cpp \
|
||||||
$(build)/type-java-initializations.cpp
|
$(build)/type-java-initializations.cpp \
|
||||||
|
$(build)/type-name-initializations.cpp
|
||||||
|
|
||||||
vm-depends := $(generated-code) $(wildcard $(src)/*.h)
|
vm-depends := $(generated-code) $(wildcard $(src)/*.h)
|
||||||
|
|
||||||
@ -650,19 +670,19 @@ $(build)/binaryToObject-main.o: $(src)/binaryToObject/main.cpp
|
|||||||
$(build-cxx) -c $(^) -o $(@)
|
$(build-cxx) -c $(^) -o $(@)
|
||||||
|
|
||||||
$(build)/binaryToObject-elf64.o: $(src)/binaryToObject/elf.cpp
|
$(build)/binaryToObject-elf64.o: $(src)/binaryToObject/elf.cpp
|
||||||
$(build-cxx) -DBITS_PER_WORD=64 -c $(^) -o $(@)
|
$(build-cxx) $(converter-cflags) -DBITS_PER_WORD=64 -c $(^) -o $(@)
|
||||||
|
|
||||||
$(build)/binaryToObject-elf32.o: $(src)/binaryToObject/elf.cpp
|
$(build)/binaryToObject-elf32.o: $(src)/binaryToObject/elf.cpp
|
||||||
$(build-cxx) -DBITS_PER_WORD=32 -c $(^) -o $(@)
|
$(build-cxx) $(converter-cflags) -DBITS_PER_WORD=32 -c $(^) -o $(@)
|
||||||
|
|
||||||
$(build)/binaryToObject-mach-o64.o: $(src)/binaryToObject/mach-o.cpp
|
$(build)/binaryToObject-mach-o64.o: $(src)/binaryToObject/mach-o.cpp
|
||||||
$(build-cxx) -DBITS_PER_WORD=64 -c $(^) -o $(@)
|
$(build-cxx) $(converter-cflags) -DBITS_PER_WORD=64 -c $(^) -o $(@)
|
||||||
|
|
||||||
$(build)/binaryToObject-mach-o32.o: $(src)/binaryToObject/mach-o.cpp
|
$(build)/binaryToObject-mach-o32.o: $(src)/binaryToObject/mach-o.cpp
|
||||||
$(build-cxx) -DBITS_PER_WORD=32 -c $(^) -o $(@)
|
$(build-cxx) $(converter-cflags) -DBITS_PER_WORD=32 -c $(^) -o $(@)
|
||||||
|
|
||||||
$(build)/binaryToObject-pe.o: $(src)/binaryToObject/pe.cpp
|
$(build)/binaryToObject-pe.o: $(src)/binaryToObject/pe.cpp
|
||||||
$(build-cxx) -c $(^) -o $(@)
|
$(build-cxx) $(converter-cflags) -c $(^) -o $(@)
|
||||||
|
|
||||||
$(converter): $(converter-objects)
|
$(converter): $(converter-objects)
|
||||||
$(build-cxx) $(^) -o $(@)
|
$(build-cxx) $(^) -o $(@)
|
||||||
|
@ -50,7 +50,9 @@ vmNativeCall:
|
|||||||
|
|
||||||
.globl vmJump
|
.globl vmJump
|
||||||
vmJump:
|
vmJump:
|
||||||
|
mov lr, r0
|
||||||
|
ldr r0, [sp]
|
||||||
|
ldr r1, [sp, #4]
|
||||||
mov sp, r2
|
mov sp, r2
|
||||||
mov r4, r3
|
mov r8, r3
|
||||||
ldmia sp, {r0,r1}
|
bx lr
|
||||||
mov pc, lr
|
|
||||||
|
1487
src/arm.cpp
1487
src/arm.cpp
File diff suppressed because it is too large
Load Diff
@ -27,7 +27,7 @@ namespace vm {
|
|||||||
inline void
|
inline void
|
||||||
trap()
|
trap()
|
||||||
{
|
{
|
||||||
asm("nop");
|
asm("bkpt");
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void
|
inline void
|
||||||
|
@ -418,9 +418,9 @@ class Assembler {
|
|||||||
|
|
||||||
virtual Block* endBlock(bool startNew) = 0;
|
virtual Block* endBlock(bool startNew) = 0;
|
||||||
|
|
||||||
virtual unsigned length() = 0;
|
virtual void endEvent() = 0;
|
||||||
|
|
||||||
virtual unsigned scratchSize() = 0;
|
virtual unsigned length() = 0;
|
||||||
|
|
||||||
virtual void dispose() = 0;
|
virtual void dispose() = 0;
|
||||||
};
|
};
|
||||||
|
@ -232,7 +232,7 @@ writeObject(const uint8_t* data, unsigned size, FILE* out,
|
|||||||
fileHeader.e_entry = 0;
|
fileHeader.e_entry = 0;
|
||||||
fileHeader.e_phoff = 0;
|
fileHeader.e_phoff = 0;
|
||||||
fileHeader.e_shoff = sizeof(FileHeader);
|
fileHeader.e_shoff = sizeof(FileHeader);
|
||||||
fileHeader.e_flags = 0;
|
fileHeader.e_flags = (machine == EM_ARM ? 0x04000000 : 0);
|
||||||
fileHeader.e_ehsize = sizeof(FileHeader);
|
fileHeader.e_ehsize = sizeof(FileHeader);
|
||||||
fileHeader.e_phentsize = 0;
|
fileHeader.e_phentsize = 0;
|
||||||
fileHeader.e_phnum = 0;
|
fileHeader.e_phnum = 0;
|
||||||
|
@ -12,6 +12,32 @@
|
|||||||
#include "stdio.h"
|
#include "stdio.h"
|
||||||
#include "string.h"
|
#include "string.h"
|
||||||
|
|
||||||
|
#define V1(v) v
|
||||||
|
|
||||||
|
#ifdef OPPOSITE_ENDIAN
|
||||||
|
# define V2(v) \
|
||||||
|
((((v) >> 8) & 0xFF) | \
|
||||||
|
(((v) << 8)))
|
||||||
|
# define V4(v) \
|
||||||
|
((((v) >> 24) & 0x000000FF) | \
|
||||||
|
(((v) >> 8) & 0x0000FF00) | \
|
||||||
|
(((v) << 8) & 0x00FF0000) | \
|
||||||
|
(((v) << 24)))
|
||||||
|
# define V8(v) \
|
||||||
|
(((static_cast<uint64_t>(v) >> 56) & UINT64_C(0x00000000000000FF)) | \
|
||||||
|
((static_cast<uint64_t>(v) >> 40) & UINT64_C(0x000000000000FF00)) | \
|
||||||
|
((static_cast<uint64_t>(v) >> 24) & UINT64_C(0x0000000000FF0000)) | \
|
||||||
|
((static_cast<uint64_t>(v) >> 8) & UINT64_C(0x00000000FF000000)) | \
|
||||||
|
((static_cast<uint64_t>(v) << 8) & UINT64_C(0x000000FF00000000)) | \
|
||||||
|
((static_cast<uint64_t>(v) << 24) & UINT64_C(0x0000FF0000000000)) | \
|
||||||
|
((static_cast<uint64_t>(v) << 40) & UINT64_C(0x00FF000000000000)) | \
|
||||||
|
((static_cast<uint64_t>(v) << 56)))
|
||||||
|
#else
|
||||||
|
# define V2(v) v
|
||||||
|
# define V4(v) v
|
||||||
|
# define V8(v) v
|
||||||
|
#endif
|
||||||
|
|
||||||
#define MH_MAGIC_64 0xfeedfacf
|
#define MH_MAGIC_64 0xfeedfacf
|
||||||
#define MH_MAGIC 0xfeedface
|
#define MH_MAGIC 0xfeedface
|
||||||
|
|
||||||
@ -37,6 +63,7 @@
|
|||||||
#define CPU_SUBTYPE_POWERPC_ALL 0
|
#define CPU_SUBTYPE_POWERPC_ALL 0
|
||||||
|
|
||||||
#if (BITS_PER_WORD == 64)
|
#if (BITS_PER_WORD == 64)
|
||||||
|
# define VW(v) V8(v)
|
||||||
# define Magic MH_MAGIC_64
|
# define Magic MH_MAGIC_64
|
||||||
# define Segment LC_SEGMENT_64
|
# define Segment LC_SEGMENT_64
|
||||||
# define FileHeader mach_header_64
|
# define FileHeader mach_header_64
|
||||||
@ -44,6 +71,7 @@
|
|||||||
# define Section section_64
|
# define Section section_64
|
||||||
# define NList struct nlist_64
|
# define NList struct nlist_64
|
||||||
#elif (BITS_PER_WORD == 32)
|
#elif (BITS_PER_WORD == 32)
|
||||||
|
# define VW(v) V4(v)
|
||||||
# define Magic MH_MAGIC
|
# define Magic MH_MAGIC
|
||||||
# define Segment LC_SEGMENT
|
# define Segment LC_SEGMENT
|
||||||
# define FileHeader mach_header
|
# define FileHeader mach_header
|
||||||
@ -191,32 +219,32 @@ writeObject(const uint8_t* data, unsigned size, FILE* out,
|
|||||||
unsigned endNameLength = strlen(endName) + 1;
|
unsigned endNameLength = strlen(endName) + 1;
|
||||||
|
|
||||||
FileHeader header = {
|
FileHeader header = {
|
||||||
Magic, // magic
|
V4(Magic), // magic
|
||||||
cpuType,
|
V4(cpuType),
|
||||||
cpuSubType,
|
V4(cpuSubType),
|
||||||
MH_OBJECT, // filetype,
|
V4(MH_OBJECT), // filetype,
|
||||||
2, // ncmds
|
V4(2), // ncmds
|
||||||
sizeof(SegmentCommand)
|
V4(sizeof(SegmentCommand)
|
||||||
+ sizeof(Section)
|
+ sizeof(Section)
|
||||||
+ sizeof(symtab_command), // sizeofcmds
|
+ sizeof(symtab_command)), // sizeofcmds
|
||||||
0 // flags
|
V4(0) // flags
|
||||||
};
|
};
|
||||||
|
|
||||||
SegmentCommand segment = {
|
SegmentCommand segment = {
|
||||||
Segment, // cmd
|
V4(Segment), // cmd
|
||||||
sizeof(SegmentCommand) + sizeof(Section), // cmdsize
|
V4(sizeof(SegmentCommand) + sizeof(Section)), // cmdsize
|
||||||
"", // segname
|
"", // segname
|
||||||
0, // vmaddr
|
VW(0), // vmaddr
|
||||||
pad(size), // vmsize
|
VW(pad(size)), // vmsize
|
||||||
sizeof(FileHeader)
|
VW(sizeof(FileHeader)
|
||||||
+ sizeof(SegmentCommand)
|
+ sizeof(SegmentCommand)
|
||||||
+ sizeof(Section)
|
+ sizeof(Section)
|
||||||
+ sizeof(symtab_command), // fileoff
|
+ sizeof(symtab_command)), // fileoff
|
||||||
pad(size), // filesize
|
VW(pad(size)), // filesize
|
||||||
7, // maxprot
|
V4(7), // maxprot
|
||||||
7, // initprot
|
V4(7), // initprot
|
||||||
1, // nsects
|
V4(1), // nsects
|
||||||
0 // flags
|
V4(0) // flags
|
||||||
};
|
};
|
||||||
|
|
||||||
strncpy(segment.segname, segmentName, sizeof(segment.segname));
|
strncpy(segment.segname, segmentName, sizeof(segment.segname));
|
||||||
@ -224,55 +252,55 @@ writeObject(const uint8_t* data, unsigned size, FILE* out,
|
|||||||
Section sect = {
|
Section sect = {
|
||||||
"", // sectname
|
"", // sectname
|
||||||
"", // segname
|
"", // segname
|
||||||
0, // addr
|
VW(0), // addr
|
||||||
pad(size), // size
|
VW(pad(size)), // size
|
||||||
sizeof(FileHeader)
|
V4(sizeof(FileHeader)
|
||||||
+ sizeof(SegmentCommand)
|
+ sizeof(SegmentCommand)
|
||||||
+ sizeof(Section)
|
+ sizeof(Section)
|
||||||
+ sizeof(symtab_command), // offset
|
+ sizeof(symtab_command)), // offset
|
||||||
log(alignment), // align
|
V4(log(alignment)), // align
|
||||||
0, // reloff
|
V4(0), // reloff
|
||||||
0, // nreloc
|
V4(0), // nreloc
|
||||||
S_REGULAR, // flags
|
V4(S_REGULAR), // flags
|
||||||
0, // reserved1
|
V4(0), // reserved1
|
||||||
0, // reserved2
|
V4(0), // reserved2
|
||||||
};
|
};
|
||||||
|
|
||||||
strncpy(sect.segname, segmentName, sizeof(sect.segname));
|
strncpy(sect.segname, segmentName, sizeof(sect.segname));
|
||||||
strncpy(sect.sectname, sectionName, sizeof(sect.sectname));
|
strncpy(sect.sectname, sectionName, sizeof(sect.sectname));
|
||||||
|
|
||||||
symtab_command symbolTable = {
|
symtab_command symbolTable = {
|
||||||
LC_SYMTAB, // cmd
|
V4(LC_SYMTAB), // cmd
|
||||||
sizeof(symtab_command), // cmdsize
|
V4(sizeof(symtab_command)), // cmdsize
|
||||||
sizeof(FileHeader)
|
V4(sizeof(FileHeader)
|
||||||
+ sizeof(SegmentCommand)
|
+ sizeof(SegmentCommand)
|
||||||
+ sizeof(Section)
|
+ sizeof(Section)
|
||||||
+ sizeof(symtab_command)
|
+ sizeof(symtab_command)
|
||||||
+ pad(size), // symoff
|
+ pad(size)), // symoff
|
||||||
2, // nsyms
|
V4(2), // nsyms
|
||||||
sizeof(FileHeader)
|
V4(sizeof(FileHeader)
|
||||||
+ sizeof(SegmentCommand)
|
+ sizeof(SegmentCommand)
|
||||||
+ sizeof(Section)
|
+ sizeof(Section)
|
||||||
+ sizeof(symtab_command)
|
+ sizeof(symtab_command)
|
||||||
+ pad(size)
|
+ pad(size)
|
||||||
+ (sizeof(NList) * 2), // stroff
|
+ (sizeof(NList) * 2)), // stroff
|
||||||
1 + startNameLength + endNameLength, // strsize
|
V4(1 + startNameLength + endNameLength), // strsize
|
||||||
};
|
};
|
||||||
|
|
||||||
NList symbolList[] = {
|
NList symbolList[] = {
|
||||||
{
|
{
|
||||||
1, // n_un
|
V4(1), // n_un
|
||||||
N_SECT | N_EXT, // n_type
|
V1(N_SECT | N_EXT), // n_type
|
||||||
1, // n_sect
|
V1(1), // n_sect
|
||||||
0, // n_desc
|
V2(0), // n_desc
|
||||||
0 // n_value
|
VW(0) // n_value
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
1 + startNameLength, // n_un
|
V4(1 + startNameLength), // n_un
|
||||||
N_SECT | N_EXT, // n_type
|
V1(N_SECT | N_EXT), // n_type
|
||||||
1, // n_sect
|
V1(1), // n_sect
|
||||||
0, // n_desc
|
V2(0), // n_desc
|
||||||
size // n_value
|
VW(size) // n_value
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
264
src/compile-arm.S
Normal file
264
src/compile-arm.S
Normal file
@ -0,0 +1,264 @@
|
|||||||
|
/* Copyright (c) 2010, 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 "types.h"
|
||||||
|
|
||||||
|
.text
|
||||||
|
|
||||||
|
#define BYTES_PER_WORD 4
|
||||||
|
|
||||||
|
#define LOCAL(x) .L##x
|
||||||
|
|
||||||
|
#ifdef __APPLE__
|
||||||
|
# define GLOBAL(x) _##x
|
||||||
|
#else
|
||||||
|
# define GLOBAL(x) x
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define THREAD_STACK 2144
|
||||||
|
#define THREAD_CONTINUATION 2148
|
||||||
|
#define THREAD_EXCEPTION 44
|
||||||
|
#define THREAD_EXCEPTION_STACK_ADJUSTMENT 2152
|
||||||
|
#define THREAD_EXCEPTION_OFFSET 2156
|
||||||
|
#define THREAD_EXCEPTION_HANDLER 2160
|
||||||
|
|
||||||
|
#define CONTINUATION_NEXT 4
|
||||||
|
#define CONTINUATION_ADDRESS 16
|
||||||
|
#define CONTINUATION_RETURN_ADDRESS_OFFSET 20
|
||||||
|
#define CONTINUATION_FRAME_POINTER_OFFSET 24
|
||||||
|
#define CONTINUATION_LENGTH 28
|
||||||
|
#define CONTINUATION_BODY 32
|
||||||
|
|
||||||
|
#define ARGUMENT_BASE (BYTES_PER_WORD * 2)
|
||||||
|
|
||||||
|
.globl GLOBAL(vmInvoke)
|
||||||
|
GLOBAL(vmInvoke):
|
||||||
|
/*
|
||||||
|
arguments
|
||||||
|
r0 : thread
|
||||||
|
r1 : function
|
||||||
|
r2 : arguments
|
||||||
|
r3 : argumentFootprint
|
||||||
|
[sp, #0] : frameSize (not used)
|
||||||
|
[sp, #4] : returnType
|
||||||
|
*/
|
||||||
|
|
||||||
|
// save stack frame
|
||||||
|
mov ip, sp
|
||||||
|
|
||||||
|
// save all non-volatile registers
|
||||||
|
stmfd sp!, {r4-r11, lr}
|
||||||
|
|
||||||
|
// save return type
|
||||||
|
ldr r4, [ip, #4]
|
||||||
|
str r4, [sp, #-4]!
|
||||||
|
|
||||||
|
// we're at the bottom of our local stack frame; save it
|
||||||
|
mov ip, sp
|
||||||
|
|
||||||
|
// align stack, if necessary
|
||||||
|
eor r4, sp, r3
|
||||||
|
tst r4, #4
|
||||||
|
subne sp, sp, #4
|
||||||
|
|
||||||
|
// copy arguments into place
|
||||||
|
sub sp, r3
|
||||||
|
mov r4, #0
|
||||||
|
b LOCAL(vmInvoke_argumentTest)
|
||||||
|
|
||||||
|
LOCAL(vmInvoke_argumentLoop):
|
||||||
|
ldr r5, [r2, r4]
|
||||||
|
str r5, [sp, r4]
|
||||||
|
add r4, r4, #BYTES_PER_WORD
|
||||||
|
|
||||||
|
LOCAL(vmInvoke_argumentTest):
|
||||||
|
cmp r4, r3
|
||||||
|
blt LOCAL(vmInvoke_argumentLoop)
|
||||||
|
|
||||||
|
// save frame
|
||||||
|
str ip, [sp, #-8]!
|
||||||
|
|
||||||
|
// we use r8 to hold the thread pointer, by convention
|
||||||
|
mov r8, r0
|
||||||
|
|
||||||
|
// load and call function address
|
||||||
|
blx r1
|
||||||
|
|
||||||
|
.globl GLOBAL(vmInvoke_returnAddress)
|
||||||
|
GLOBAL(vmInvoke_returnAddress):
|
||||||
|
|
||||||
|
// restore frame
|
||||||
|
ldr sp, [sp]
|
||||||
|
|
||||||
|
.globl GLOBAL(vmInvoke_safeStack)
|
||||||
|
GLOBAL(vmInvoke_safeStack):
|
||||||
|
|
||||||
|
#ifdef AVIAN_CONTINUATIONS
|
||||||
|
// call the next continuation, if any
|
||||||
|
ldr r5,[r8,#THREAD_CONTINUATION]
|
||||||
|
cmp r5,#0
|
||||||
|
beq LOCAL(vmInvoke_exit)
|
||||||
|
|
||||||
|
ldr r6,[r5,#CONTINUATION_LENGTH]
|
||||||
|
lsl r6,r6,#2
|
||||||
|
neg r7,r6
|
||||||
|
add r7,r7,#-80
|
||||||
|
mov r4,sp
|
||||||
|
str r4,[sp,r7]!
|
||||||
|
|
||||||
|
add r7,r5,#CONTINUATION_BODY
|
||||||
|
|
||||||
|
mov r11,#0
|
||||||
|
add r10,sp,#ARGUMENT_BASE
|
||||||
|
b LOCAL(vmInvoke_continuationTest)
|
||||||
|
|
||||||
|
LOCAL(vmInvoke_continuationLoop):
|
||||||
|
ldr r9,[r7,r11]
|
||||||
|
str r9,[r10,r11]
|
||||||
|
add r11,r11,#4
|
||||||
|
|
||||||
|
LOCAL(vmInvoke_continuationTest):
|
||||||
|
cmp r11,r6
|
||||||
|
ble LOCAL(vmInvoke_continuationLoop)
|
||||||
|
|
||||||
|
ldr r7,[r5,#CONTINUATION_RETURN_ADDRESS_OFFSET]
|
||||||
|
ldr r10,LOCAL(vmInvoke_returnAddress_word)
|
||||||
|
ldr r11,LOCAL(vmInvoke_getAddress_word)
|
||||||
|
LOCAL(vmInvoke_getAddress):
|
||||||
|
add r11,pc,r11
|
||||||
|
ldr r11,[r11,r10]
|
||||||
|
str r11,[sp,r7]
|
||||||
|
|
||||||
|
ldr r7,[r5,#CONTINUATION_FRAME_POINTER_OFFSET]
|
||||||
|
ldr r11,[sp]
|
||||||
|
add r7,r7,sp
|
||||||
|
str r11,[r7]
|
||||||
|
str r7,[sp]
|
||||||
|
|
||||||
|
ldr r7,[r5,#CONTINUATION_NEXT]
|
||||||
|
str r7,[r8,#THREAD_CONTINUATION]
|
||||||
|
|
||||||
|
// call the continuation unless we're handling an exception
|
||||||
|
ldr r7,[r8,#THREAD_EXCEPTION]
|
||||||
|
cmp r7,#0
|
||||||
|
bne LOCAL(vmInvoke_handleException)
|
||||||
|
ldr r7,[r5,#CONTINUATION_ADDRESS]
|
||||||
|
bx r7
|
||||||
|
|
||||||
|
LOCAL(vmInvoke_handleException):
|
||||||
|
// we're handling an exception - call the exception handler instead
|
||||||
|
mov r11,#0
|
||||||
|
str r11,[r8,#THREAD_EXCEPTION]
|
||||||
|
ldr r11,[r8,#THREAD_EXCEPTION_STACK_ADJUSTMENT]
|
||||||
|
ldr r9,[sp]
|
||||||
|
neg r11,r11
|
||||||
|
str r9,[sp,r11]!
|
||||||
|
ldr r11,[r8,#THREAD_EXCEPTION_OFFSET]
|
||||||
|
str r7,[sp,r11]
|
||||||
|
|
||||||
|
ldr r7,[r8,#THREAD_EXCEPTION_HANDLER]
|
||||||
|
bx r7
|
||||||
|
|
||||||
|
LOCAL(vmInvoke_exit):
|
||||||
|
#endif // AVIAN_CONTINUATIONS
|
||||||
|
|
||||||
|
mov ip, #0
|
||||||
|
str ip, [r8, #THREAD_STACK]
|
||||||
|
|
||||||
|
// restore return type
|
||||||
|
ldr ip, [sp], #4
|
||||||
|
|
||||||
|
// restore callee-saved registers
|
||||||
|
ldmfd sp!, {r4-r11, lr}
|
||||||
|
|
||||||
|
LOCAL(vmInvoke_void):
|
||||||
|
cmp ip, #VOID_TYPE
|
||||||
|
beq LOCAL(vmInvoke_return)
|
||||||
|
|
||||||
|
LOCAL(vmInvoke_int64):
|
||||||
|
cmp ip, #INT64_TYPE
|
||||||
|
beq LOCAL(vmInvoke_return)
|
||||||
|
|
||||||
|
LOCAL(vmInvoke_int32):
|
||||||
|
mov r1, #0
|
||||||
|
|
||||||
|
LOCAL(vmInvoke_return):
|
||||||
|
bx lr
|
||||||
|
|
||||||
|
.globl GLOBAL(vmJumpAndInvoke)
|
||||||
|
GLOBAL(vmJumpAndInvoke):
|
||||||
|
#ifdef AVIAN_CONTINUATIONS
|
||||||
|
// r0: thread
|
||||||
|
// r1: address
|
||||||
|
// r2: (unused)
|
||||||
|
// r3: stack
|
||||||
|
// [sp,#0]: argumentFootprint
|
||||||
|
// [sp,#4]: arguments
|
||||||
|
// [sp,#8]: frameSize
|
||||||
|
|
||||||
|
ldr r4,[sp]
|
||||||
|
ldr r5,[sp,#4]
|
||||||
|
ldr r6,[sp,#8]
|
||||||
|
|
||||||
|
// restore (pseudo)-stack pointer (we don't want to touch the real
|
||||||
|
// stack pointer, since we haven't copied the arguments yet)
|
||||||
|
ldr r3,[r3]
|
||||||
|
|
||||||
|
// make everything between sp and r3 one big stack frame while we
|
||||||
|
// shuffle things around
|
||||||
|
str r3,[sp]
|
||||||
|
|
||||||
|
// allocate new frame, adding room for callee-saved registers
|
||||||
|
neg r10,r6
|
||||||
|
add r10,r10,#-80
|
||||||
|
mov r2,r3
|
||||||
|
str r2,[r3,r10]!
|
||||||
|
|
||||||
|
mov r8,r0
|
||||||
|
|
||||||
|
// copy arguments into place
|
||||||
|
mov r6,#0
|
||||||
|
add r9,r3,#ARGUMENT_BASE
|
||||||
|
b LOCAL(vmJumpAndInvoke_argumentTest)
|
||||||
|
|
||||||
|
LOCAL(vmJumpAndInvoke_argumentLoop):
|
||||||
|
ldr r12,[r5,r6]
|
||||||
|
str r12,[r9,r6]
|
||||||
|
add r6,r6,#4
|
||||||
|
|
||||||
|
LOCAL(vmJumpAndInvoke_argumentTest):
|
||||||
|
cmp r6,r4
|
||||||
|
ble LOCAL(vmJumpAndInvoke_argumentLoop)
|
||||||
|
|
||||||
|
// the arguments have been copied, so we can set the real stack
|
||||||
|
// pointer now
|
||||||
|
mov sp,r3
|
||||||
|
|
||||||
|
// set return address to vmInvoke_returnAddress
|
||||||
|
ldr r10,LOCAL(vmInvoke_returnAddress_word)
|
||||||
|
ldr r11,LOCAL(vmJumpAndInvoke_getAddress_word)
|
||||||
|
LOCAL(vmJumpAndInvoke_getAddress):
|
||||||
|
add r11,pc,r11
|
||||||
|
ldr lr,[r11,r10]
|
||||||
|
|
||||||
|
bx r1
|
||||||
|
|
||||||
|
LOCAL(vmInvoke_returnAddress_word):
|
||||||
|
.word GLOBAL(vmInvoke_returnAddress)(GOT)
|
||||||
|
LOCAL(vmInvoke_getAddress_word):
|
||||||
|
.word _GLOBAL_OFFSET_TABLE_-(LOCAL(vmInvoke_getAddress)+8)
|
||||||
|
LOCAL(vmJumpAndInvoke_getAddress_word):
|
||||||
|
.word _GLOBAL_OFFSET_TABLE_-(LOCAL(vmJumpAndInvoke_getAddress)+8)
|
||||||
|
|
||||||
|
#else // not AVIAN_CONTINUATIONS
|
||||||
|
// vmJumpAndInvoke should only be called when continuations are
|
||||||
|
// enabled
|
||||||
|
bkpt
|
||||||
|
#endif // not AVIAN_CONTINUATIONS
|
@ -5416,14 +5416,14 @@ codeSingletonSizeInBytes(MyThread*, unsigned codeSizeInBytes)
|
|||||||
}
|
}
|
||||||
|
|
||||||
uint8_t*
|
uint8_t*
|
||||||
finish(MyThread* t, Allocator* allocator, Assembler* a, const char* name)
|
finish(MyThread* t, Allocator* allocator, Assembler* a, const char* name,
|
||||||
|
unsigned length)
|
||||||
{
|
{
|
||||||
uint8_t* start = static_cast<uint8_t*>
|
uint8_t* start = static_cast<uint8_t*>(allocator->allocate(pad(length)));
|
||||||
(allocator->allocate(pad(a->length())));
|
|
||||||
|
|
||||||
a->writeTo(start);
|
a->writeTo(start);
|
||||||
|
|
||||||
logCompile(t, start, a->length(), 0, name, 0);
|
logCompile(t, start, length, 0, name, 0);
|
||||||
|
|
||||||
return start;
|
return start;
|
||||||
}
|
}
|
||||||
@ -8275,9 +8275,7 @@ compileThunks(MyThread* t, Allocator* allocator, MyProcessor* p)
|
|||||||
Assembler::Register result(t->arch->returnLow());
|
Assembler::Register result(t->arch->returnLow());
|
||||||
a->apply(Jump, BytesPerWord, RegisterOperand, &result);
|
a->apply(Jump, BytesPerWord, RegisterOperand, &result);
|
||||||
|
|
||||||
a->endBlock(false)->resolve(0, 0);
|
p->thunks.default_.length = a->endBlock(false)->resolve(0, 0);
|
||||||
|
|
||||||
p->thunks.default_.length = a->length();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ThunkContext defaultVirtualContext(t, &zone);
|
ThunkContext defaultVirtualContext(t, &zone);
|
||||||
@ -8321,9 +8319,7 @@ compileThunks(MyThread* t, Allocator* allocator, MyProcessor* p)
|
|||||||
Assembler::Register result(t->arch->returnLow());
|
Assembler::Register result(t->arch->returnLow());
|
||||||
a->apply(Jump, BytesPerWord, RegisterOperand, &result);
|
a->apply(Jump, BytesPerWord, RegisterOperand, &result);
|
||||||
|
|
||||||
a->endBlock(false)->resolve(0, 0);
|
p->thunks.defaultVirtual.length = a->endBlock(false)->resolve(0, 0);
|
||||||
|
|
||||||
p->thunks.defaultVirtual.length = a->length();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ThunkContext nativeContext(t, &zone);
|
ThunkContext nativeContext(t, &zone);
|
||||||
@ -8342,9 +8338,7 @@ compileThunks(MyThread* t, Allocator* allocator, MyProcessor* p)
|
|||||||
|
|
||||||
a->popFrameAndUpdateStackAndReturn(difference(&(t->stack), t));
|
a->popFrameAndUpdateStackAndReturn(difference(&(t->stack), t));
|
||||||
|
|
||||||
a->endBlock(false)->resolve(0, 0);
|
p->thunks.native.length = a->endBlock(false)->resolve(0, 0);
|
||||||
|
|
||||||
p->thunks.native.length = a->length();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ThunkContext aioobContext(t, &zone);
|
ThunkContext aioobContext(t, &zone);
|
||||||
@ -8361,9 +8355,7 @@ compileThunks(MyThread* t, Allocator* allocator, MyProcessor* p)
|
|||||||
Assembler::Constant proc(&(aioobContext.promise));
|
Assembler::Constant proc(&(aioobContext.promise));
|
||||||
a->apply(LongCall, BytesPerWord, ConstantOperand, &proc);
|
a->apply(LongCall, BytesPerWord, ConstantOperand, &proc);
|
||||||
|
|
||||||
a->endBlock(false)->resolve(0, 0);
|
p->thunks.aioob.length = a->endBlock(false)->resolve(0, 0);
|
||||||
|
|
||||||
p->thunks.aioob.length = a->length();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ThunkContext tableContext(t, &zone);
|
ThunkContext tableContext(t, &zone);
|
||||||
@ -8377,13 +8369,12 @@ compileThunks(MyThread* t, Allocator* allocator, MyProcessor* p)
|
|||||||
Assembler::Constant proc(&(tableContext.promise));
|
Assembler::Constant proc(&(tableContext.promise));
|
||||||
a->apply(LongJump, BytesPerWord, ConstantOperand, &proc);
|
a->apply(LongJump, BytesPerWord, ConstantOperand, &proc);
|
||||||
|
|
||||||
a->endBlock(false)->resolve(0, 0);
|
p->thunks.table.length = a->endBlock(false)->resolve(0, 0);
|
||||||
|
|
||||||
p->thunks.table.length = a->length();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
p->thunks.default_.start = finish
|
p->thunks.default_.start = finish
|
||||||
(t, allocator, defaultContext.context.assembler, "default");
|
(t, allocator, defaultContext.context.assembler, "default",
|
||||||
|
p->thunks.default_.length);
|
||||||
|
|
||||||
BootImage* image = p->bootImage;
|
BootImage* image = p->bootImage;
|
||||||
uint8_t* imageBase = p->codeAllocator.base;
|
uint8_t* imageBase = p->codeAllocator.base;
|
||||||
@ -8398,7 +8389,8 @@ compileThunks(MyThread* t, Allocator* allocator, MyProcessor* p)
|
|||||||
}
|
}
|
||||||
|
|
||||||
p->thunks.defaultVirtual.start = finish
|
p->thunks.defaultVirtual.start = finish
|
||||||
(t, allocator, defaultVirtualContext.context.assembler, "defaultVirtual");
|
(t, allocator, defaultVirtualContext.context.assembler, "defaultVirtual",
|
||||||
|
p->thunks.defaultVirtual.length);
|
||||||
|
|
||||||
{ void* call;
|
{ void* call;
|
||||||
defaultVirtualContext.promise.listener->resolve
|
defaultVirtualContext.promise.listener->resolve
|
||||||
@ -8411,7 +8403,8 @@ compileThunks(MyThread* t, Allocator* allocator, MyProcessor* p)
|
|||||||
}
|
}
|
||||||
|
|
||||||
p->thunks.native.start = finish
|
p->thunks.native.start = finish
|
||||||
(t, allocator, nativeContext.context.assembler, "native");
|
(t, allocator, nativeContext.context.assembler, "native",
|
||||||
|
p->thunks.native.length);
|
||||||
|
|
||||||
{ void* call;
|
{ void* call;
|
||||||
nativeContext.promise.listener->resolve
|
nativeContext.promise.listener->resolve
|
||||||
@ -8423,7 +8416,8 @@ compileThunks(MyThread* t, Allocator* allocator, MyProcessor* p)
|
|||||||
}
|
}
|
||||||
|
|
||||||
p->thunks.aioob.start = finish
|
p->thunks.aioob.start = finish
|
||||||
(t, allocator, aioobContext.context.assembler, "aioob");
|
(t, allocator, aioobContext.context.assembler, "aioob",
|
||||||
|
p->thunks.aioob.length);
|
||||||
|
|
||||||
{ void* call;
|
{ void* call;
|
||||||
aioobContext.promise.listener->resolve
|
aioobContext.promise.listener->resolve
|
||||||
@ -8535,9 +8529,7 @@ compileVirtualThunk(MyThread* t, unsigned index, unsigned* size)
|
|||||||
Assembler::Constant thunk(&defaultVirtualThunkPromise);
|
Assembler::Constant thunk(&defaultVirtualThunkPromise);
|
||||||
a->apply(Jump, BytesPerWord, ConstantOperand, &thunk);
|
a->apply(Jump, BytesPerWord, ConstantOperand, &thunk);
|
||||||
|
|
||||||
a->endBlock(false)->resolve(0, 0);
|
*size = a->endBlock(false)->resolve(0, 0);
|
||||||
|
|
||||||
*size = a->length();
|
|
||||||
|
|
||||||
uint8_t* start = static_cast<uint8_t*>(codeAllocator(t)->allocate(*size));
|
uint8_t* start = static_cast<uint8_t*>(codeAllocator(t)->allocate(*size));
|
||||||
|
|
||||||
|
@ -4890,10 +4890,14 @@ class BoundsCheckEvent: public Event {
|
|||||||
CodePromise* nextPromise = codePromise
|
CodePromise* nextPromise = codePromise
|
||||||
(c, static_cast<Promise*>(0));
|
(c, static_cast<Promise*>(0));
|
||||||
|
|
||||||
|
index->source->freeze(c, index);
|
||||||
|
|
||||||
ConstantSite next(nextPromise);
|
ConstantSite next(nextPromise);
|
||||||
apply(c, JumpIfGreater, 4, index->source, index->source, 4, &length,
|
apply(c, JumpIfGreater, 4, index->source, index->source, 4, &length,
|
||||||
&length, BytesPerWord, &next, &next);
|
&length, BytesPerWord, &next, &next);
|
||||||
|
|
||||||
|
index->source->thaw(c, index);
|
||||||
|
|
||||||
if (constant == 0) {
|
if (constant == 0) {
|
||||||
outOfBoundsPromise->offset = a->offset();
|
outOfBoundsPromise->offset = a->offset();
|
||||||
}
|
}
|
||||||
@ -5700,6 +5704,8 @@ compile(Context* c)
|
|||||||
p->offset = a->offset();
|
p->offset = a->offset();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
a->endEvent();
|
||||||
|
|
||||||
LogicalInstruction* nextInstruction = next(c, e->logicalInstruction);
|
LogicalInstruction* nextInstruction = next(c, e->logicalInstruction);
|
||||||
if (e->next == 0
|
if (e->next == 0
|
||||||
or (e->next->logicalInstruction != e->logicalInstruction
|
or (e->next->logicalInstruction != e->logicalInstruction
|
||||||
@ -5737,7 +5743,7 @@ compile(Context* c)
|
|||||||
block = next;
|
block = next;
|
||||||
}
|
}
|
||||||
|
|
||||||
return block->assemblerBlock->resolve(block->start, 0) + a->scratchSize();
|
return block->assemblerBlock->resolve(block->start, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned
|
unsigned
|
||||||
|
@ -45,7 +45,11 @@ void
|
|||||||
join(Thread* t, Thread* o)
|
join(Thread* t, Thread* o)
|
||||||
{
|
{
|
||||||
if (t != o) {
|
if (t != o) {
|
||||||
|
if (o->state != Thread::ZombieState
|
||||||
|
and o->state != Thread::JoinedState)
|
||||||
|
{
|
||||||
o->systemThread->join();
|
o->systemThread->join();
|
||||||
|
}
|
||||||
o->state = Thread::JoinedState;
|
o->state = Thread::JoinedState;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1979,6 +1983,13 @@ bootJavaClass(Thread* t, Machine::Type type, int superType, const char* name,
|
|||||||
(t, root(t, Machine::BootstrapClassMap), n, class_, byteArrayHash);
|
(t, root(t, Machine::BootstrapClassMap), n, class_, byteArrayHash);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
nameClass(Thread* t, Machine::Type type, const char* name)
|
||||||
|
{
|
||||||
|
object n = makeByteArray(t, name);
|
||||||
|
set(t, arrayBody(t, t->m->types, type), ClassName, n);
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
boot(Thread* t)
|
boot(Thread* t)
|
||||||
{
|
{
|
||||||
@ -2098,6 +2109,10 @@ boot(Thread* t)
|
|||||||
PROTECT(t, bootMethod);
|
PROTECT(t, bootMethod);
|
||||||
|
|
||||||
#include "type-java-initializations.cpp"
|
#include "type-java-initializations.cpp"
|
||||||
|
|
||||||
|
#ifdef AVIAN_HEAPDUMP
|
||||||
|
# include "type-name-initializations.cpp"
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2393,6 +2408,12 @@ Thread::exit()
|
|||||||
} else {
|
} else {
|
||||||
threadPeer(this, javaThread) = 0;
|
threadPeer(this, javaThread) = 0;
|
||||||
enter(this, Thread::ZombieState);
|
enter(this, Thread::ZombieState);
|
||||||
|
|
||||||
|
lock->dispose();
|
||||||
|
lock = 0;
|
||||||
|
|
||||||
|
systemThread->dispose();
|
||||||
|
systemThread = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2400,7 +2421,9 @@ Thread::exit()
|
|||||||
void
|
void
|
||||||
Thread::dispose()
|
Thread::dispose()
|
||||||
{
|
{
|
||||||
|
if (lock) {
|
||||||
lock->dispose();
|
lock->dispose();
|
||||||
|
}
|
||||||
|
|
||||||
if (systemThread) {
|
if (systemThread) {
|
||||||
systemThread->dispose();
|
systemThread->dispose();
|
||||||
|
@ -2761,7 +2761,11 @@ notifyAll(Thread* t, object o)
|
|||||||
inline void
|
inline void
|
||||||
interrupt(Thread*, Thread* target)
|
interrupt(Thread*, Thread* target)
|
||||||
{
|
{
|
||||||
|
if (target->state != Thread::ZombieState
|
||||||
|
and target->state != Thread::JoinedState)
|
||||||
|
{
|
||||||
target->systemThread->interrupt();
|
target->systemThread->interrupt();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void
|
inline void
|
||||||
|
@ -784,6 +784,7 @@ class MySystem: public System {
|
|||||||
}
|
}
|
||||||
|
|
||||||
virtual void abort() {
|
virtual void abort() {
|
||||||
|
*static_cast<void**>(0) = 0;
|
||||||
::abort();
|
::abort();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2393,12 +2393,12 @@ class MyAssembler: public Assembler {
|
|||||||
return b;
|
return b;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual unsigned length() {
|
virtual void endEvent() {
|
||||||
return c.code.length();
|
// ignore
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual unsigned scratchSize() {
|
virtual unsigned length() {
|
||||||
return c.constantPoolCount * BytesPerWord;
|
return c.code.length();
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void dispose() {
|
virtual void dispose() {
|
||||||
|
@ -15,7 +15,7 @@
|
|||||||
#include "common.h"
|
#include "common.h"
|
||||||
|
|
||||||
#ifdef __APPLE__
|
#ifdef __APPLE__
|
||||||
# if __DARWIN_UNIX03 && defined(_STRUCT_X86_EXCEPTION_STATE32)
|
# if __DARWIN_UNIX03 && defined(_STRUCT_PPC_EXCEPTION_STATE)
|
||||||
# define IP_REGISTER(context) (context->uc_mcontext->__ss.__srr0)
|
# define IP_REGISTER(context) (context->uc_mcontext->__ss.__srr0)
|
||||||
# define STACK_REGISTER(context) (context->uc_mcontext->__ss.__r1)
|
# define STACK_REGISTER(context) (context->uc_mcontext->__ss.__r1)
|
||||||
# define THREAD_REGISTER(context) (context->uc_mcontext->__ss.__r13)
|
# define THREAD_REGISTER(context) (context->uc_mcontext->__ss.__r13)
|
||||||
|
@ -2172,13 +2172,34 @@ writeJavaInitializations(Output* out, Object* declarations)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
writeNameInitialization(Output* out, Object* type)
|
||||||
|
{
|
||||||
|
out->write("nameClass(t, Machine::");
|
||||||
|
out->write(capitalize(typeName(type)));
|
||||||
|
out->write("Type, \"vm::");
|
||||||
|
out->write(typeName(type));
|
||||||
|
out->write("\");\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
writeNameInitializations(Output* out, Object* declarations)
|
||||||
|
{
|
||||||
|
for (Object* p = declarations; p; p = cdr(p)) {
|
||||||
|
Object* o = car(p);
|
||||||
|
if (o->type == Object::Type and typeJavaName(o) == 0) {
|
||||||
|
writeNameInitialization(out, o);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
usageAndExit(const char* command)
|
usageAndExit(const char* command)
|
||||||
{
|
{
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
"usage: %s <classpath> <input file> <output file> "
|
"usage: %s <classpath> <input file> <output file> "
|
||||||
"{enums,declarations,constructors,initializations,"
|
"{enums,declarations,constructors,initializations,"
|
||||||
"java-initializations}\n",
|
"java-initializations,name-initializations}\n",
|
||||||
command);
|
command);
|
||||||
exit(-1);
|
exit(-1);
|
||||||
}
|
}
|
||||||
@ -2207,7 +2228,8 @@ main(int ac, char** av)
|
|||||||
or local::equal(av[4], "declarations")
|
or local::equal(av[4], "declarations")
|
||||||
or local::equal(av[4], "constructors")
|
or local::equal(av[4], "constructors")
|
||||||
or local::equal(av[4], "initializations")
|
or local::equal(av[4], "initializations")
|
||||||
or local::equal(av[4], "java-initializations")))
|
or local::equal(av[4], "java-initializations")
|
||||||
|
or local::equal(av[4], "name-initializations")))
|
||||||
{
|
{
|
||||||
local::usageAndExit(av[0]);
|
local::usageAndExit(av[0]);
|
||||||
}
|
}
|
||||||
@ -2277,6 +2299,8 @@ main(int ac, char** av)
|
|||||||
local::writeInitializations(&out, declarations);
|
local::writeInitializations(&out, declarations);
|
||||||
} else if (local::equal(av[4], "java-initializations")) {
|
} else if (local::equal(av[4], "java-initializations")) {
|
||||||
local::writeJavaInitializations(&out, declarations);
|
local::writeJavaInitializations(&out, declarations);
|
||||||
|
} else if (local::equal(av[4], "name-initializations")) {
|
||||||
|
local::writeNameInitializations(&out, declarations);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -3532,12 +3532,12 @@ class MyAssembler: public Assembler {
|
|||||||
return b;
|
return b;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual unsigned length() {
|
virtual void endEvent() {
|
||||||
return c.code.length();
|
// ignore
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual unsigned scratchSize() {
|
virtual unsigned length() {
|
||||||
return 0;
|
return c.code.length();
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void dispose() {
|
virtual void dispose() {
|
||||||
|
@ -65,5 +65,11 @@ public class Arrays {
|
|||||||
p = false;
|
p = false;
|
||||||
expect(array[1] == array[p ? 0 : 1]);
|
expect(array[1] == array[p ? 0 : 1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
{ int[] array = new int[1024];
|
||||||
|
array[1023] = -1;
|
||||||
|
expect(array[1023] == -1);
|
||||||
|
expect(array[1022] == 0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
147
test/extra/DumpStats.java
Normal file
147
test/extra/DumpStats.java
Normal file
@ -0,0 +1,147 @@
|
|||||||
|
package extra;
|
||||||
|
|
||||||
|
import java.io.PrintStream;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.FileInputStream;
|
||||||
|
import java.io.BufferedInputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.EOFException;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Comparator;
|
||||||
|
import java.util.Arrays;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This is a simple utility to generate and print statistics from a
|
||||||
|
* heap dump generated by Avian's heapdump.cpp. The output is a list
|
||||||
|
* of classes (identified by number in the case of anonymous,
|
||||||
|
* VM-internal classes), each followed by (1) the total memory
|
||||||
|
* footprint of all instances of the class, and (2) the number of
|
||||||
|
* instances. The output is ordered by instance memory footprint.
|
||||||
|
*/
|
||||||
|
public class DumpStats {
|
||||||
|
private static final int Root = 0;
|
||||||
|
private static final int Size = 1;
|
||||||
|
private static final int ClassName = 2;
|
||||||
|
private static final int Push = 3;
|
||||||
|
private static final int Pop = 4;
|
||||||
|
|
||||||
|
private static int readInt(InputStream in) throws IOException {
|
||||||
|
int b1 = in.read();
|
||||||
|
int b2 = in.read();
|
||||||
|
int b3 = in.read();
|
||||||
|
int b4 = in.read();
|
||||||
|
if (b4 == -1) throw new EOFException();
|
||||||
|
return (int) ((b1 << 24) | (b2 << 16) | (b3 << 8) | (b4));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String readString(InputStream in) throws IOException {
|
||||||
|
int count = readInt(in);
|
||||||
|
byte[] b = new byte[count];
|
||||||
|
int offset = 0;
|
||||||
|
int c;
|
||||||
|
while ((c = in.read(b, offset, b.length - offset)) != -1
|
||||||
|
&& offset < b.length)
|
||||||
|
{
|
||||||
|
offset += c;
|
||||||
|
}
|
||||||
|
if (offset != b.length) throw new EOFException();
|
||||||
|
return new String(b);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Record record(Map<Integer, Record> map, int key) {
|
||||||
|
Record r = map.get(key);
|
||||||
|
if (r == null) {
|
||||||
|
map.put(key, r = new Record(key));
|
||||||
|
}
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Map<Integer, Record> read(InputStream in)
|
||||||
|
throws IOException
|
||||||
|
{
|
||||||
|
boolean done = false;
|
||||||
|
boolean popped = false;
|
||||||
|
int size = 0;
|
||||||
|
int last = 0;
|
||||||
|
Map<Integer, Record> map = new HashMap();
|
||||||
|
|
||||||
|
while (! done) {
|
||||||
|
int flag = in.read();
|
||||||
|
switch (flag) {
|
||||||
|
case Root: {
|
||||||
|
last = readInt(in);
|
||||||
|
popped = false;
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case ClassName: {
|
||||||
|
record(map, last).name = readString(in);
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case Push: {
|
||||||
|
last = readInt(in);
|
||||||
|
if (! popped) {
|
||||||
|
Record r = record(map, last);
|
||||||
|
r.footprint += size;
|
||||||
|
++ r.count;
|
||||||
|
}
|
||||||
|
popped = false;
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case Pop: {
|
||||||
|
popped = true;
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case Size: {
|
||||||
|
size = readInt(in);
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case -1:
|
||||||
|
done = true;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
throw new RuntimeException("bad flag: " + flag);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return map;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void main(String[] args) throws Exception {
|
||||||
|
Map<Integer, Record> map = read
|
||||||
|
(new BufferedInputStream(new FileInputStream(args[0])));
|
||||||
|
|
||||||
|
Record[] array = map.values().toArray(new Record[map.size()]);
|
||||||
|
Arrays.sort(array, new Comparator<Record>() {
|
||||||
|
public int compare(Record a, Record b) {
|
||||||
|
return b.footprint - a.footprint;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
int footprint = 0;
|
||||||
|
int count = 0;
|
||||||
|
for (Record r: array) {
|
||||||
|
if (r.name == null) {
|
||||||
|
r.name = String.valueOf(r.key);
|
||||||
|
}
|
||||||
|
System.out.println(r.name + ": " + r.footprint + " " + r.count);
|
||||||
|
footprint += r.footprint;
|
||||||
|
count += r.count;
|
||||||
|
}
|
||||||
|
|
||||||
|
System.out.println();
|
||||||
|
System.out.println("total: " + footprint + " " + count);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class Record {
|
||||||
|
public final int key;
|
||||||
|
public String name;
|
||||||
|
public int footprint;
|
||||||
|
public int count;
|
||||||
|
|
||||||
|
public Record(int key) {
|
||||||
|
this.key = key;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
101
test/extra/PrintDump.java
Normal file
101
test/extra/PrintDump.java
Normal file
@ -0,0 +1,101 @@
|
|||||||
|
package extra;
|
||||||
|
|
||||||
|
import java.io.PrintStream;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.FileInputStream;
|
||||||
|
import java.io.BufferedInputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.EOFException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This is a simple utility to print the contents of a heap dump
|
||||||
|
* generated by Avian's heapdump.cpp in a human-readable format.
|
||||||
|
*/
|
||||||
|
public class PrintDump {
|
||||||
|
private static final int Root = 0;
|
||||||
|
private static final int Size = 1;
|
||||||
|
private static final int ClassName = 2;
|
||||||
|
private static final int Push = 3;
|
||||||
|
private static final int Pop = 4;
|
||||||
|
|
||||||
|
private static void indent(PrintStream out, int level) {
|
||||||
|
for (; level > 0; --level) out.print(" ");
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int readInt(InputStream in) throws IOException {
|
||||||
|
int b1 = in.read();
|
||||||
|
int b2 = in.read();
|
||||||
|
int b3 = in.read();
|
||||||
|
int b4 = in.read();
|
||||||
|
if (b4 == -1) throw new EOFException();
|
||||||
|
return (int) ((b1 << 24) | (b2 << 16) | (b3 << 8) | (b4));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String readString(InputStream in) throws IOException {
|
||||||
|
int count = readInt(in);
|
||||||
|
byte[] b = new byte[count];
|
||||||
|
int offset = 0;
|
||||||
|
int c;
|
||||||
|
while ((c = in.read(b, offset, b.length - offset)) != -1
|
||||||
|
&& offset < b.length)
|
||||||
|
{
|
||||||
|
offset += c;
|
||||||
|
}
|
||||||
|
if (offset != b.length) throw new EOFException();
|
||||||
|
return new String(b);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void pipe(InputStream in, PrintStream out)
|
||||||
|
throws IOException
|
||||||
|
{
|
||||||
|
boolean done = false;
|
||||||
|
boolean popped = false;
|
||||||
|
int level = 0;
|
||||||
|
while (! done) {
|
||||||
|
int flag = in.read();
|
||||||
|
switch (flag) {
|
||||||
|
case Root: {
|
||||||
|
out.print("\nroot " + readInt(in));
|
||||||
|
popped = false;
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case ClassName: {
|
||||||
|
out.print(" class " + readString(in));
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case Push: {
|
||||||
|
++ level;
|
||||||
|
out.println();
|
||||||
|
indent(out, level);
|
||||||
|
if (! popped) {
|
||||||
|
out.print("first ");
|
||||||
|
}
|
||||||
|
out.print("child " + readInt(in));
|
||||||
|
popped = false;
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case Pop: {
|
||||||
|
-- level;
|
||||||
|
popped = true;
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case Size: {
|
||||||
|
out.print(" size " + readInt(in));
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case -1:
|
||||||
|
out.println();
|
||||||
|
out.flush();
|
||||||
|
done = true;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
throw new RuntimeException("bad flag: " + flag);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void main(String[] args) throws Exception {
|
||||||
|
pipe(new BufferedInputStream(new FileInputStream(args[0])), System.out);
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user