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);
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));
@ -191,6 +191,10 @@ Java_java_lang_Runtime_exec(JNIEnv* e, jclass,
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()));
return;
@ -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;

View File

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

View File

@ -191,13 +191,23 @@ endif
ifeq ($(arch),arm)
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 $(@)

View File

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

File diff suppressed because it is too large Load Diff

View File

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

View File

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

View File

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

View File

@ -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)
V4(Magic), // magic
V4(cpuType),
V4(cpuSubType),
V4(MH_OBJECT), // filetype,
V4(2), // ncmds
V4(sizeof(SegmentCommand)
+ sizeof(Section)
+ sizeof(symtab_command), // sizeofcmds
0 // flags
+ 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)
VW(0), // vmaddr
VW(pad(size)), // vmsize
VW(sizeof(FileHeader)
+ sizeof(SegmentCommand)
+ sizeof(Section)
+ sizeof(symtab_command), // fileoff
pad(size), // filesize
7, // maxprot
7, // initprot
1, // nsects
0 // flags
+ 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)
VW(0), // addr
VW(pad(size)), // size
V4(sizeof(FileHeader)
+ sizeof(SegmentCommand)
+ sizeof(Section)
+ sizeof(symtab_command), // offset
log(alignment), // align
0, // reloff
0, // nreloc
S_REGULAR, // flags
0, // reserved1
0, // reserved2
+ 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)
V4(LC_SYMTAB), // cmd
V4(sizeof(symtab_command)), // cmdsize
V4(sizeof(FileHeader)
+ sizeof(SegmentCommand)
+ sizeof(Section)
+ sizeof(symtab_command)
+ pad(size), // symoff
2, // nsyms
sizeof(FileHeader)
+ pad(size)), // symoff
V4(2), // nsyms
V4(sizeof(FileHeader)
+ sizeof(SegmentCommand)
+ sizeof(Section)
+ sizeof(symtab_command)
+ pad(size)
+ (sizeof(NList) * 2), // stroff
1 + startNameLength + endNameLength, // strsize
+ (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
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*
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));

View File

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

View File

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

View File

@ -2760,9 +2760,13 @@ notifyAll(Thread* t, object o)
inline void
interrupt(Thread*, Thread* target)
{
if (target->state != Thread::ZombieState
and target->state != Thread::JoinedState)
{
target->systemThread->interrupt();
}
}
inline void
setDaemon(Thread* t, object thread, bool daemon)

View File

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

View File

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

View File

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

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

View File

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

View File

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