Merge remote branch 'origin/master' into openjdk

Conflicts:
	makefile
	src/compile.cpp
	src/compiler.cpp
	src/type-generator.cpp
This commit is contained in:
Joel Dice 2010-11-16 10:18:08 -07:00
commit a611ccda6f
22 changed files with 1759 additions and 711 deletions

View File

@ -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));
@ -190,6 +190,10 @@ Java_java_lang_Runtime_exec(JNIEnv* e, jclass,
BOOL success = CreateProcess(0, (LPSTR) RUNTIME_ARRAY_BODY(line), 0, 0, 1, BOOL success = CreateProcess(0, (LPSTR) RUNTIME_ARRAY_BODY(line), 0, 0, 1,
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()));
@ -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;

View File

@ -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;
} }
} }

View File

@ -189,15 +189,25 @@ ifeq ($(arch),powerpc)
pointer-size = 4 pointer-size = 4
endif 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 $(@)

View File

@ -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

File diff suppressed because it is too large Load Diff

View File

@ -27,7 +27,7 @@ namespace vm {
inline void inline void
trap() trap()
{ {
asm("nop"); asm("bkpt");
} }
inline void inline void

View File

@ -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;
}; };

View File

@ -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;

View File

@ -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
View 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

View File

@ -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));

View File

@ -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

View File

@ -45,7 +45,11 @@ void
join(Thread* t, Thread* o) join(Thread* t, Thread* o)
{ {
if (t != o) { if (t != o) {
o->systemThread->join(); if (o->state != Thread::ZombieState
and o->state != Thread::JoinedState)
{
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()
{ {
lock->dispose(); if (lock) {
lock->dispose();
}
if (systemThread) { if (systemThread) {
systemThread->dispose(); systemThread->dispose();

View File

@ -2761,7 +2761,11 @@ notifyAll(Thread* t, object o)
inline void inline void
interrupt(Thread*, Thread* target) interrupt(Thread*, Thread* target)
{ {
target->systemThread->interrupt(); if (target->state != Thread::ZombieState
and target->state != Thread::JoinedState)
{
target->systemThread->interrupt();
}
} }
inline void inline void

View File

@ -784,6 +784,7 @@ class MySystem: public System {
} }
virtual void abort() { virtual void abort() {
*static_cast<void**>(0) = 0;
::abort(); ::abort();
} }

View File

@ -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() {

View File

@ -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)

View File

@ -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;

View File

@ -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() {

View File

@ -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
View 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
View 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);
}
}