mirror of
https://github.com/corda/corda.git
synced 2025-01-17 02:09:50 +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);
|
||||
jlong inDescriptor = static_cast<jlong>(descriptor(e, in[0]));
|
||||
if(e->ExceptionCheck()) return;
|
||||
e->SetLongArrayRegion(process, 1, 1, &inDescriptor);
|
||||
e->SetLongArrayRegion(process, 2, 1, &inDescriptor);
|
||||
makePipe(e, out);
|
||||
SetHandleInformation(out[1], HANDLE_FLAG_INHERIT, 0);
|
||||
jlong outDescriptor = static_cast<jlong>(descriptor(e, out[1]));
|
||||
if(e->ExceptionCheck()) return;
|
||||
e->SetLongArrayRegion(process, 2, 1, &outDescriptor);
|
||||
e->SetLongArrayRegion(process, 3, 1, &outDescriptor);
|
||||
makePipe(e, err);
|
||||
SetHandleInformation(err[0], HANDLE_FLAG_INHERIT, 0);
|
||||
jlong errDescriptor = static_cast<jlong>(descriptor(e, err[0]));
|
||||
if(e->ExceptionCheck()) return;
|
||||
e->SetLongArrayRegion(process, 3, 1, &errDescriptor);
|
||||
e->SetLongArrayRegion(process, 4, 1, &errDescriptor);
|
||||
|
||||
PROCESS_INFORMATION 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,
|
||||
CREATE_NO_WINDOW | CREATE_UNICODE_ENVIRONMENT,
|
||||
0, 0, &si, &pi);
|
||||
|
||||
CloseHandle(in[1]);
|
||||
CloseHandle(out[0]);
|
||||
CloseHandle(err[1]);
|
||||
|
||||
if (not success) {
|
||||
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);
|
||||
e->SetLongArrayRegion(process, 0, 1, &pid);
|
||||
|
||||
jlong tid = reinterpret_cast<jlong>(pi.hThread);
|
||||
e->SetLongArrayRegion(process, 1, 1, &tid);
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT jint JNICALL
|
||||
Java_java_lang_Runtime_exitValue(JNIEnv* e, jclass, jlong pid)
|
||||
{
|
||||
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)
|
||||
Java_java_lang_Runtime_waitFor(JNIEnv* e, jclass, jlong pid, jlong tid)
|
||||
{
|
||||
DWORD exitCode;
|
||||
WaitForSingleObject(reinterpret_cast<HANDLE>(pid), INFINITE);
|
||||
@ -223,6 +215,10 @@ Java_java_lang_Runtime_waitFor(JNIEnv* e, jclass, jlong pid)
|
||||
if(not success){
|
||||
throwNew(e, "java/lang/Exception", getErrorStr(GetLastError()));
|
||||
}
|
||||
|
||||
CloseHandle(reinterpret_cast<HANDLE>(pid));
|
||||
CloseHandle(reinterpret_cast<HANDLE>(tid));
|
||||
|
||||
return exitCode;
|
||||
}
|
||||
#else
|
||||
@ -248,15 +244,15 @@ Java_java_lang_Runtime_exec(JNIEnv* e, jclass,
|
||||
makePipe(e, in);
|
||||
if(e->ExceptionCheck()) return;
|
||||
jlong inDescriptor = static_cast<jlong>(in[0]);
|
||||
e->SetLongArrayRegion(process, 1, 1, &inDescriptor);
|
||||
e->SetLongArrayRegion(process, 2, 1, &inDescriptor);
|
||||
makePipe(e, out);
|
||||
if(e->ExceptionCheck()) return;
|
||||
jlong outDescriptor = static_cast<jlong>(out[1]);
|
||||
e->SetLongArrayRegion(process, 2, 1, &outDescriptor);
|
||||
e->SetLongArrayRegion(process, 3, 1, &outDescriptor);
|
||||
makePipe(e, err);
|
||||
if(e->ExceptionCheck()) return;
|
||||
jlong errDescriptor = static_cast<jlong>(err[0]);
|
||||
e->SetLongArrayRegion(process, 3, 1, &errDescriptor);
|
||||
e->SetLongArrayRegion(process, 4, 1, &errDescriptor);
|
||||
makePipe(e, msg);
|
||||
if(e->ExceptionCheck()) return;
|
||||
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
|
||||
Java_java_lang_Runtime_exitValue(JNIEnv* e, jclass, jlong pid)
|
||||
{
|
||||
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)
|
||||
Java_java_lang_Runtime_waitFor(JNIEnv*, jclass, jlong pid, jlong)
|
||||
{
|
||||
bool finished = false;
|
||||
int status;
|
||||
|
@ -44,28 +44,80 @@ public class Runtime {
|
||||
}
|
||||
|
||||
public Process exec(String command) throws IOException {
|
||||
long[] process = new long[4];
|
||||
StringTokenizer t = new StringTokenizer(command);
|
||||
String[] cmd = new String[t.countTokens()];
|
||||
for (int i = 0; i < cmd.length; i++)
|
||||
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) {
|
||||
long[] process = new long[4];
|
||||
exec(command, process);
|
||||
return new MyProcess(process[0], (int) process[1], (int) process[2], (int) process[3]);
|
||||
public Process exec(final String[] command) throws IOException {
|
||||
final MyProcess[] process = new MyProcess[1];
|
||||
final Throwable[] exception = new Throwable[1];
|
||||
|
||||
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);
|
||||
|
||||
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);
|
||||
private static native int waitFor(long pid, long tid);
|
||||
|
||||
private static native void load(String name, boolean mapName);
|
||||
|
||||
@ -79,13 +131,15 @@ public class Runtime {
|
||||
|
||||
private static class MyProcess extends Process {
|
||||
private long pid;
|
||||
private long tid;
|
||||
private final int in;
|
||||
private final int out;
|
||||
private final int err;
|
||||
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.tid = tid;
|
||||
this.in = in;
|
||||
this.out = out;
|
||||
this.err = err;
|
||||
@ -95,13 +149,6 @@ public class Runtime {
|
||||
throw new RuntimeException("not implemented");
|
||||
}
|
||||
|
||||
public int exitValue() {
|
||||
if (pid != 0) {
|
||||
exitCode = Runtime.exitValue(pid);
|
||||
}
|
||||
return exitCode;
|
||||
}
|
||||
|
||||
public InputStream getInputStream() {
|
||||
return new FileInputStream(new FileDescriptor(in));
|
||||
}
|
||||
@ -114,11 +161,19 @@ public class Runtime {
|
||||
return new FileInputStream(new FileDescriptor(err));
|
||||
}
|
||||
|
||||
public int waitFor() throws InterruptedException {
|
||||
public synchronized int exitValue() {
|
||||
if (pid != 0) {
|
||||
exitCode = Runtime.waitFor(pid);
|
||||
pid = 0;
|
||||
throw new IllegalThreadStateException();
|
||||
}
|
||||
|
||||
return exitCode;
|
||||
}
|
||||
|
||||
public synchronized int waitFor() throws InterruptedException {
|
||||
while (pid != 0) {
|
||||
wait();
|
||||
}
|
||||
|
||||
return exitCode;
|
||||
}
|
||||
}
|
||||
|
38
makefile
38
makefile
@ -189,15 +189,25 @@ ifeq ($(arch),powerpc)
|
||||
pointer-size = 4
|
||||
endif
|
||||
ifeq ($(arch),arm)
|
||||
asm = arm
|
||||
pointer-size = 4
|
||||
asm = arm
|
||||
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
|
||||
|
||||
ifeq ($(platform),darwin)
|
||||
version-script-flag =
|
||||
build-cflags = $(common-cflags) -fPIC -fvisibility=hidden -I$(src)
|
||||
build-lflags += -framework CoreFoundation
|
||||
lflags = $(common-lflags) -ldl -framework CoreFoundation -framework CoreServices
|
||||
lflags = $(common-lflags) -ldl -framework CoreFoundation \
|
||||
-framework CoreServices
|
||||
ifeq ($(bootimage),true)
|
||||
bootimage-lflags = -Wl,-segprot,__RWX,rwx,rwx
|
||||
endif
|
||||
@ -207,6 +217,9 @@ ifeq ($(platform),darwin)
|
||||
shared = -dynamiclib
|
||||
|
||||
ifeq ($(arch),powerpc)
|
||||
ifneq (,$(filter i386 x86_64,$(build-arch)))
|
||||
converter-cflags = -DOPPOSITE_ENDIAN
|
||||
endif
|
||||
openjdk-extra-cflags += -arch ppc
|
||||
cflags += -arch ppc
|
||||
asmflags += -arch ppc
|
||||
@ -214,6 +227,9 @@ ifeq ($(platform),darwin)
|
||||
endif
|
||||
|
||||
ifeq ($(arch),i386)
|
||||
ifeq ($(build-arch),powerpc)
|
||||
converter-cflags = -DOPPOSITE_ENDIAN
|
||||
endif
|
||||
openjdk-extra-cflags += -arch i386
|
||||
cflags += -arch i386
|
||||
asmflags += -arch i386
|
||||
@ -221,6 +237,9 @@ ifeq ($(platform),darwin)
|
||||
endif
|
||||
|
||||
ifeq ($(arch),x86_64)
|
||||
ifeq ($(build-arch),powerpc)
|
||||
converter-cflags = -DOPPOSITE_ENDIAN
|
||||
endif
|
||||
openjdk-extra-cflags += -arch x86_64
|
||||
cflags += -arch x86_64
|
||||
asmflags += -arch x86_64
|
||||
@ -364,7 +383,8 @@ generated-code = \
|
||||
$(build)/type-declarations.cpp \
|
||||
$(build)/type-constructors.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)
|
||||
|
||||
@ -650,19 +670,19 @@ $(build)/binaryToObject-main.o: $(src)/binaryToObject/main.cpp
|
||||
$(build-cxx) -c $(^) -o $(@)
|
||||
|
||||
$(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-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-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-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-cxx) -c $(^) -o $(@)
|
||||
$(build-cxx) $(converter-cflags) -c $(^) -o $(@)
|
||||
|
||||
$(converter): $(converter-objects)
|
||||
$(build-cxx) $(^) -o $(@)
|
||||
|
@ -50,7 +50,9 @@ vmNativeCall:
|
||||
|
||||
.globl vmJump
|
||||
vmJump:
|
||||
mov lr, r0
|
||||
ldr r0, [sp]
|
||||
ldr r1, [sp, #4]
|
||||
mov sp, r2
|
||||
mov r4, r3
|
||||
ldmia sp, {r0,r1}
|
||||
mov pc, lr
|
||||
mov r8, r3
|
||||
bx lr
|
||||
|
1467
src/arm.cpp
1467
src/arm.cpp
File diff suppressed because it is too large
Load Diff
@ -27,7 +27,7 @@ namespace vm {
|
||||
inline void
|
||||
trap()
|
||||
{
|
||||
asm("nop");
|
||||
asm("bkpt");
|
||||
}
|
||||
|
||||
inline void
|
||||
|
@ -418,9 +418,9 @@ class Assembler {
|
||||
|
||||
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;
|
||||
};
|
||||
|
@ -232,7 +232,7 @@ writeObject(const uint8_t* data, unsigned size, FILE* out,
|
||||
fileHeader.e_entry = 0;
|
||||
fileHeader.e_phoff = 0;
|
||||
fileHeader.e_shoff = sizeof(FileHeader);
|
||||
fileHeader.e_flags = 0;
|
||||
fileHeader.e_flags = (machine == EM_ARM ? 0x04000000 : 0);
|
||||
fileHeader.e_ehsize = sizeof(FileHeader);
|
||||
fileHeader.e_phentsize = 0;
|
||||
fileHeader.e_phnum = 0;
|
||||
|
@ -12,6 +12,32 @@
|
||||
#include "stdio.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 0xfeedface
|
||||
|
||||
@ -37,6 +63,7 @@
|
||||
#define CPU_SUBTYPE_POWERPC_ALL 0
|
||||
|
||||
#if (BITS_PER_WORD == 64)
|
||||
# define VW(v) V8(v)
|
||||
# define Magic MH_MAGIC_64
|
||||
# define Segment LC_SEGMENT_64
|
||||
# define FileHeader mach_header_64
|
||||
@ -44,6 +71,7 @@
|
||||
# define Section section_64
|
||||
# define NList struct nlist_64
|
||||
#elif (BITS_PER_WORD == 32)
|
||||
# define VW(v) V4(v)
|
||||
# define Magic MH_MAGIC
|
||||
# define Segment LC_SEGMENT
|
||||
# define FileHeader mach_header
|
||||
@ -191,32 +219,32 @@ writeObject(const uint8_t* data, unsigned size, FILE* out,
|
||||
unsigned endNameLength = strlen(endName) + 1;
|
||||
|
||||
FileHeader header = {
|
||||
Magic, // magic
|
||||
cpuType,
|
||||
cpuSubType,
|
||||
MH_OBJECT, // filetype,
|
||||
2, // ncmds
|
||||
sizeof(SegmentCommand)
|
||||
+ sizeof(Section)
|
||||
+ sizeof(symtab_command), // sizeofcmds
|
||||
0 // flags
|
||||
V4(Magic), // magic
|
||||
V4(cpuType),
|
||||
V4(cpuSubType),
|
||||
V4(MH_OBJECT), // filetype,
|
||||
V4(2), // ncmds
|
||||
V4(sizeof(SegmentCommand)
|
||||
+ sizeof(Section)
|
||||
+ sizeof(symtab_command)), // sizeofcmds
|
||||
V4(0) // flags
|
||||
};
|
||||
|
||||
SegmentCommand segment = {
|
||||
Segment, // cmd
|
||||
sizeof(SegmentCommand) + sizeof(Section), // cmdsize
|
||||
V4(Segment), // cmd
|
||||
V4(sizeof(SegmentCommand) + sizeof(Section)), // cmdsize
|
||||
"", // segname
|
||||
0, // vmaddr
|
||||
pad(size), // vmsize
|
||||
sizeof(FileHeader)
|
||||
+ sizeof(SegmentCommand)
|
||||
+ sizeof(Section)
|
||||
+ sizeof(symtab_command), // fileoff
|
||||
pad(size), // filesize
|
||||
7, // maxprot
|
||||
7, // initprot
|
||||
1, // nsects
|
||||
0 // flags
|
||||
VW(0), // vmaddr
|
||||
VW(pad(size)), // vmsize
|
||||
VW(sizeof(FileHeader)
|
||||
+ sizeof(SegmentCommand)
|
||||
+ sizeof(Section)
|
||||
+ sizeof(symtab_command)), // fileoff
|
||||
VW(pad(size)), // filesize
|
||||
V4(7), // maxprot
|
||||
V4(7), // initprot
|
||||
V4(1), // nsects
|
||||
V4(0) // flags
|
||||
};
|
||||
|
||||
strncpy(segment.segname, segmentName, sizeof(segment.segname));
|
||||
@ -224,55 +252,55 @@ writeObject(const uint8_t* data, unsigned size, FILE* out,
|
||||
Section sect = {
|
||||
"", // sectname
|
||||
"", // segname
|
||||
0, // addr
|
||||
pad(size), // size
|
||||
sizeof(FileHeader)
|
||||
+ sizeof(SegmentCommand)
|
||||
+ sizeof(Section)
|
||||
+ sizeof(symtab_command), // offset
|
||||
log(alignment), // align
|
||||
0, // reloff
|
||||
0, // nreloc
|
||||
S_REGULAR, // flags
|
||||
0, // reserved1
|
||||
0, // reserved2
|
||||
VW(0), // addr
|
||||
VW(pad(size)), // size
|
||||
V4(sizeof(FileHeader)
|
||||
+ sizeof(SegmentCommand)
|
||||
+ sizeof(Section)
|
||||
+ sizeof(symtab_command)), // offset
|
||||
V4(log(alignment)), // align
|
||||
V4(0), // reloff
|
||||
V4(0), // nreloc
|
||||
V4(S_REGULAR), // flags
|
||||
V4(0), // reserved1
|
||||
V4(0), // reserved2
|
||||
};
|
||||
|
||||
strncpy(sect.segname, segmentName, sizeof(sect.segname));
|
||||
strncpy(sect.sectname, sectionName, sizeof(sect.sectname));
|
||||
|
||||
symtab_command symbolTable = {
|
||||
LC_SYMTAB, // cmd
|
||||
sizeof(symtab_command), // cmdsize
|
||||
sizeof(FileHeader)
|
||||
+ sizeof(SegmentCommand)
|
||||
+ sizeof(Section)
|
||||
+ sizeof(symtab_command)
|
||||
+ pad(size), // symoff
|
||||
2, // nsyms
|
||||
sizeof(FileHeader)
|
||||
+ sizeof(SegmentCommand)
|
||||
+ sizeof(Section)
|
||||
+ sizeof(symtab_command)
|
||||
+ pad(size)
|
||||
+ (sizeof(NList) * 2), // stroff
|
||||
1 + startNameLength + endNameLength, // strsize
|
||||
V4(LC_SYMTAB), // cmd
|
||||
V4(sizeof(symtab_command)), // cmdsize
|
||||
V4(sizeof(FileHeader)
|
||||
+ sizeof(SegmentCommand)
|
||||
+ sizeof(Section)
|
||||
+ sizeof(symtab_command)
|
||||
+ pad(size)), // symoff
|
||||
V4(2), // nsyms
|
||||
V4(sizeof(FileHeader)
|
||||
+ sizeof(SegmentCommand)
|
||||
+ sizeof(Section)
|
||||
+ sizeof(symtab_command)
|
||||
+ pad(size)
|
||||
+ (sizeof(NList) * 2)), // stroff
|
||||
V4(1 + startNameLength + endNameLength), // strsize
|
||||
};
|
||||
|
||||
NList symbolList[] = {
|
||||
{
|
||||
1, // n_un
|
||||
N_SECT | N_EXT, // n_type
|
||||
1, // n_sect
|
||||
0, // n_desc
|
||||
0 // n_value
|
||||
V4(1), // n_un
|
||||
V1(N_SECT | N_EXT), // n_type
|
||||
V1(1), // n_sect
|
||||
V2(0), // n_desc
|
||||
VW(0) // n_value
|
||||
},
|
||||
{
|
||||
1 + startNameLength, // n_un
|
||||
N_SECT | N_EXT, // n_type
|
||||
1, // n_sect
|
||||
0, // n_desc
|
||||
size // n_value
|
||||
V4(1 + startNameLength), // n_un
|
||||
V1(N_SECT | N_EXT), // n_type
|
||||
V1(1), // n_sect
|
||||
V2(0), // n_desc
|
||||
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*
|
||||
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*>
|
||||
(allocator->allocate(pad(a->length())));
|
||||
uint8_t* start = static_cast<uint8_t*>(allocator->allocate(pad(length)));
|
||||
|
||||
a->writeTo(start);
|
||||
|
||||
logCompile(t, start, a->length(), 0, name, 0);
|
||||
logCompile(t, start, length, 0, name, 0);
|
||||
|
||||
return start;
|
||||
}
|
||||
@ -8275,9 +8275,7 @@ compileThunks(MyThread* t, Allocator* allocator, MyProcessor* p)
|
||||
Assembler::Register result(t->arch->returnLow());
|
||||
a->apply(Jump, BytesPerWord, RegisterOperand, &result);
|
||||
|
||||
a->endBlock(false)->resolve(0, 0);
|
||||
|
||||
p->thunks.default_.length = a->length();
|
||||
p->thunks.default_.length = a->endBlock(false)->resolve(0, 0);
|
||||
}
|
||||
|
||||
ThunkContext defaultVirtualContext(t, &zone);
|
||||
@ -8321,9 +8319,7 @@ compileThunks(MyThread* t, Allocator* allocator, MyProcessor* p)
|
||||
Assembler::Register result(t->arch->returnLow());
|
||||
a->apply(Jump, BytesPerWord, RegisterOperand, &result);
|
||||
|
||||
a->endBlock(false)->resolve(0, 0);
|
||||
|
||||
p->thunks.defaultVirtual.length = a->length();
|
||||
p->thunks.defaultVirtual.length = a->endBlock(false)->resolve(0, 0);
|
||||
}
|
||||
|
||||
ThunkContext nativeContext(t, &zone);
|
||||
@ -8342,9 +8338,7 @@ compileThunks(MyThread* t, Allocator* allocator, MyProcessor* p)
|
||||
|
||||
a->popFrameAndUpdateStackAndReturn(difference(&(t->stack), t));
|
||||
|
||||
a->endBlock(false)->resolve(0, 0);
|
||||
|
||||
p->thunks.native.length = a->length();
|
||||
p->thunks.native.length = a->endBlock(false)->resolve(0, 0);
|
||||
}
|
||||
|
||||
ThunkContext aioobContext(t, &zone);
|
||||
@ -8361,9 +8355,7 @@ compileThunks(MyThread* t, Allocator* allocator, MyProcessor* p)
|
||||
Assembler::Constant proc(&(aioobContext.promise));
|
||||
a->apply(LongCall, BytesPerWord, ConstantOperand, &proc);
|
||||
|
||||
a->endBlock(false)->resolve(0, 0);
|
||||
|
||||
p->thunks.aioob.length = a->length();
|
||||
p->thunks.aioob.length = a->endBlock(false)->resolve(0, 0);
|
||||
}
|
||||
|
||||
ThunkContext tableContext(t, &zone);
|
||||
@ -8377,13 +8369,12 @@ compileThunks(MyThread* t, Allocator* allocator, MyProcessor* p)
|
||||
Assembler::Constant proc(&(tableContext.promise));
|
||||
a->apply(LongJump, BytesPerWord, ConstantOperand, &proc);
|
||||
|
||||
a->endBlock(false)->resolve(0, 0);
|
||||
|
||||
p->thunks.table.length = a->length();
|
||||
p->thunks.table.length = a->endBlock(false)->resolve(0, 0);
|
||||
}
|
||||
|
||||
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;
|
||||
uint8_t* imageBase = p->codeAllocator.base;
|
||||
@ -8398,7 +8389,8 @@ compileThunks(MyThread* t, Allocator* allocator, MyProcessor* p)
|
||||
}
|
||||
|
||||
p->thunks.defaultVirtual.start = finish
|
||||
(t, allocator, defaultVirtualContext.context.assembler, "defaultVirtual");
|
||||
(t, allocator, defaultVirtualContext.context.assembler, "defaultVirtual",
|
||||
p->thunks.defaultVirtual.length);
|
||||
|
||||
{ void* call;
|
||||
defaultVirtualContext.promise.listener->resolve
|
||||
@ -8411,7 +8403,8 @@ compileThunks(MyThread* t, Allocator* allocator, MyProcessor* p)
|
||||
}
|
||||
|
||||
p->thunks.native.start = finish
|
||||
(t, allocator, nativeContext.context.assembler, "native");
|
||||
(t, allocator, nativeContext.context.assembler, "native",
|
||||
p->thunks.native.length);
|
||||
|
||||
{ void* call;
|
||||
nativeContext.promise.listener->resolve
|
||||
@ -8423,7 +8416,8 @@ compileThunks(MyThread* t, Allocator* allocator, MyProcessor* p)
|
||||
}
|
||||
|
||||
p->thunks.aioob.start = finish
|
||||
(t, allocator, aioobContext.context.assembler, "aioob");
|
||||
(t, allocator, aioobContext.context.assembler, "aioob",
|
||||
p->thunks.aioob.length);
|
||||
|
||||
{ void* call;
|
||||
aioobContext.promise.listener->resolve
|
||||
@ -8535,9 +8529,7 @@ compileVirtualThunk(MyThread* t, unsigned index, unsigned* size)
|
||||
Assembler::Constant thunk(&defaultVirtualThunkPromise);
|
||||
a->apply(Jump, BytesPerWord, ConstantOperand, &thunk);
|
||||
|
||||
a->endBlock(false)->resolve(0, 0);
|
||||
|
||||
*size = a->length();
|
||||
*size = a->endBlock(false)->resolve(0, 0);
|
||||
|
||||
uint8_t* start = static_cast<uint8_t*>(codeAllocator(t)->allocate(*size));
|
||||
|
||||
|
@ -4890,10 +4890,14 @@ class BoundsCheckEvent: public Event {
|
||||
CodePromise* nextPromise = codePromise
|
||||
(c, static_cast<Promise*>(0));
|
||||
|
||||
index->source->freeze(c, index);
|
||||
|
||||
ConstantSite next(nextPromise);
|
||||
apply(c, JumpIfGreater, 4, index->source, index->source, 4, &length,
|
||||
&length, BytesPerWord, &next, &next);
|
||||
|
||||
index->source->thaw(c, index);
|
||||
|
||||
if (constant == 0) {
|
||||
outOfBoundsPromise->offset = a->offset();
|
||||
}
|
||||
@ -5700,6 +5704,8 @@ compile(Context* c)
|
||||
p->offset = a->offset();
|
||||
}
|
||||
|
||||
a->endEvent();
|
||||
|
||||
LogicalInstruction* nextInstruction = next(c, e->logicalInstruction);
|
||||
if (e->next == 0
|
||||
or (e->next->logicalInstruction != e->logicalInstruction
|
||||
@ -5737,7 +5743,7 @@ compile(Context* c)
|
||||
block = next;
|
||||
}
|
||||
|
||||
return block->assemblerBlock->resolve(block->start, 0) + a->scratchSize();
|
||||
return block->assemblerBlock->resolve(block->start, 0);
|
||||
}
|
||||
|
||||
unsigned
|
||||
|
@ -45,7 +45,11 @@ void
|
||||
join(Thread* t, Thread* o)
|
||||
{
|
||||
if (t != o) {
|
||||
o->systemThread->join();
|
||||
if (o->state != Thread::ZombieState
|
||||
and o->state != Thread::JoinedState)
|
||||
{
|
||||
o->systemThread->join();
|
||||
}
|
||||
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);
|
||||
}
|
||||
|
||||
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
|
||||
boot(Thread* t)
|
||||
{
|
||||
@ -2098,6 +2109,10 @@ boot(Thread* t)
|
||||
PROTECT(t, bootMethod);
|
||||
|
||||
#include "type-java-initializations.cpp"
|
||||
|
||||
#ifdef AVIAN_HEAPDUMP
|
||||
# include "type-name-initializations.cpp"
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
@ -2393,6 +2408,12 @@ Thread::exit()
|
||||
} else {
|
||||
threadPeer(this, javaThread) = 0;
|
||||
enter(this, Thread::ZombieState);
|
||||
|
||||
lock->dispose();
|
||||
lock = 0;
|
||||
|
||||
systemThread->dispose();
|
||||
systemThread = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -2400,7 +2421,9 @@ Thread::exit()
|
||||
void
|
||||
Thread::dispose()
|
||||
{
|
||||
lock->dispose();
|
||||
if (lock) {
|
||||
lock->dispose();
|
||||
}
|
||||
|
||||
if (systemThread) {
|
||||
systemThread->dispose();
|
||||
|
@ -2761,7 +2761,11 @@ notifyAll(Thread* t, object o)
|
||||
inline void
|
||||
interrupt(Thread*, Thread* target)
|
||||
{
|
||||
target->systemThread->interrupt();
|
||||
if (target->state != Thread::ZombieState
|
||||
and target->state != Thread::JoinedState)
|
||||
{
|
||||
target->systemThread->interrupt();
|
||||
}
|
||||
}
|
||||
|
||||
inline void
|
||||
|
@ -784,6 +784,7 @@ class MySystem: public System {
|
||||
}
|
||||
|
||||
virtual void abort() {
|
||||
*static_cast<void**>(0) = 0;
|
||||
::abort();
|
||||
}
|
||||
|
||||
|
@ -2393,12 +2393,12 @@ class MyAssembler: public Assembler {
|
||||
return b;
|
||||
}
|
||||
|
||||
virtual unsigned length() {
|
||||
return c.code.length();
|
||||
virtual void endEvent() {
|
||||
// ignore
|
||||
}
|
||||
|
||||
virtual unsigned scratchSize() {
|
||||
return c.constantPoolCount * BytesPerWord;
|
||||
virtual unsigned length() {
|
||||
return c.code.length();
|
||||
}
|
||||
|
||||
virtual void dispose() {
|
||||
|
@ -15,7 +15,7 @@
|
||||
#include "common.h"
|
||||
|
||||
#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 STACK_REGISTER(context) (context->uc_mcontext->__ss.__r1)
|
||||
# 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
|
||||
usageAndExit(const char* command)
|
||||
{
|
||||
fprintf(stderr,
|
||||
"usage: %s <classpath> <input file> <output file> "
|
||||
"{enums,declarations,constructors,initializations,"
|
||||
"java-initializations}\n",
|
||||
"java-initializations,name-initializations}\n",
|
||||
command);
|
||||
exit(-1);
|
||||
}
|
||||
@ -2207,7 +2228,8 @@ main(int ac, char** av)
|
||||
or local::equal(av[4], "declarations")
|
||||
or local::equal(av[4], "constructors")
|
||||
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]);
|
||||
}
|
||||
@ -2277,6 +2299,8 @@ main(int ac, char** av)
|
||||
local::writeInitializations(&out, declarations);
|
||||
} else if (local::equal(av[4], "java-initializations")) {
|
||||
local::writeJavaInitializations(&out, declarations);
|
||||
} else if (local::equal(av[4], "name-initializations")) {
|
||||
local::writeNameInitializations(&out, declarations);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -3532,12 +3532,12 @@ class MyAssembler: public Assembler {
|
||||
return b;
|
||||
}
|
||||
|
||||
virtual unsigned length() {
|
||||
return c.code.length();
|
||||
virtual void endEvent() {
|
||||
// ignore
|
||||
}
|
||||
|
||||
virtual unsigned scratchSize() {
|
||||
return 0;
|
||||
virtual unsigned length() {
|
||||
return c.code.length();
|
||||
}
|
||||
|
||||
virtual void dispose() {
|
||||
|
@ -65,5 +65,11 @@ public class Arrays {
|
||||
p = false;
|
||||
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