This commit is contained in:
Joel Dice 2007-10-03 18:41:54 -06:00
parent ba03aa88df
commit 404d996c1e
11 changed files with 399 additions and 337 deletions

View File

@ -11,7 +11,7 @@ public class Method<T> extends AccessibleObject implements Member {
private byte[] spec;
private Class<T> class_;
private Object code;
private Object compiled;
private long compiled;
private Method() { }

View File

@ -71,7 +71,7 @@ cflags += -g3 -O3 -DNDEBUG
endif
cpp-objects = $(foreach x,$(1),$(patsubst $(2)/%.cpp,$(bld)/%.o,$(x)))
asm-objects = $(foreach x,$(1),$(patsubst $(2)/%.S,$(bld)/%.o,$(x)))
asm-objects = $(foreach x,$(1),$(patsubst $(2)/%.S,$(bld)/%-asm.o,$(x)))
java-classes = $(foreach x,$(1),$(patsubst $(2)/%.java,$(cls)/%.class,$(x)))
stdcpp-sources = $(src)/stdc++.cpp
@ -112,14 +112,7 @@ interpreter-sources = \
$(src)/jnienv.cpp \
$(src)/main.cpp
interpreter-asm-sources = $(src)/vmInvoke.S
ifeq ($(arch),i386)
interpreter-asm-sources += $(src)/cdecl.S
endif
ifeq ($(arch),x86_64)
interpreter-asm-sources += $(src)/amd64.S
endif
interpreter-asm-sources = $(src)/compile.S $(src)/system.S
interpreter-cpp-objects = \
$(call cpp-objects,$(interpreter-sources),$(src))
@ -219,7 +212,7 @@ $(stdcpp-objects): $(bld)/%.o: $(src)/%.cpp
$(interpreter-cpp-objects): $(bld)/%.o: $(src)/%.cpp $(interpreter-depends)
$(compile-object)
$(interpreter-asm-objects): $(bld)/%.o: $(src)/%.S
$(interpreter-asm-objects): $(bld)/%-asm.o: $(src)/%.S
$(compile-object)
$(generator-objects): $(bld)/%.o: $(src)/%.cpp

View File

@ -1,86 +0,0 @@
#include "types.h"
.text
#ifdef __APPLE__
.globl _cdeclCall
_cdeclCall:
#else
.globl cdeclCall
cdeclCall:
#endif
pushl %ebp
movl %esp,%ebp
// 8(%ebp): function
// 12(%ebp): stack
// 16(%ebp): stackSize
// 20(%ebp): returnType
// reserve space for arguments
movl 16(%ebp),%ecx
#ifdef __APPLE__
// align to a 16 byte boundary on Darwin
addl $15,%ecx
andl $0xFFFFFFF0,%ecx
addl $8,%ecx
#endif
subl %ecx,%esp
// copy arguments into place
movl $0,%ecx
jmp test
loop:
movl %ecx,%eax
movl %ecx,%edx
addl %esp,%edx
addl 12(%ebp),%eax
movl (%eax),%eax
movl %eax,(%edx)
addl $4,%ecx
test:
cmpl 16(%ebp),%ecx
jb loop
// call function
call *8(%ebp)
// handle return value based on expected type
movl 20(%ebp),%ecx
void:
cmpl $VOID_TYPE,%ecx
jne int64
jmp exit
int64:
cmpl $INT64_TYPE,%ecx
jne float
jmp exit
float:
cmpl $FLOAT_TYPE,%ecx
jne double
fstps 8(%ebp)
movl 8(%ebp),%eax
jmp int32
double:
cmpl $DOUBLE_TYPE,%ecx
jne int32
fstpl 8(%ebp)
movl 8(%ebp),%eax
movl 12(%ebp),%edx
jmp exit
int32:
movl $0,%edx
exit:
movl %ebp,%esp
popl %ebp
ret

View File

@ -2,10 +2,10 @@
.text
.globl vmInvoke
vmInvoke:
#ifdef __x86_64__
.globl vmInvoke
vmInvoke:
pushq %rbp
movq %rsp,%rbp
@ -40,9 +40,19 @@ test:
movq %rbp,%rsp
popq %rbp
ret
.globl vmJump
vmJump:
// %rdi: address
// %rsi: base
movq %rsi,%rsp
popq %rbp
jmp *(%rdi)
#elif defined __i386__
.globl vmInvoke
vmInvoke:
pushl %ebp
movl %esp,%ebp
@ -96,7 +106,16 @@ exit:
movl %ebp,%esp
popl %ebp
ret
.globl vmJump
vmJump:
// 8(%ebp): address
// 12(%ebp): base
movq 8(%ebp),%eax
movq 12(%ebp),%rsp
popq %rbp
jmp *(%eax)
#else
# error unsupported platform
#endif

View File

@ -12,15 +12,15 @@ vmInvoke(void* function, void* stack, unsigned stackSize,
unsigned returnType);
extern "C" void NO_RETURN
vmJump(void* address);
vmJump(void* address, void* base);
namespace {
const bool Verbose = false;
const bool Verbose = true;
const unsigned FrameThread = BytesPerWord * 2;
const unsigned FrameMethod = FrameThread + BytesPerWord;
const unsigned FrameNext = FrameNext + BytesPerWord;
const unsigned FrameNext = FrameMethod + BytesPerWord;
const unsigned FrameFootprint = BytesPerWord * 3;
class ArgumentList;
@ -121,50 +121,6 @@ class Buffer {
unsigned minimumCapacity;
};
class Code {
public:
Code(Buffer* code, Buffer* lineNumbers, Buffer* exceptionHandlers):
codeLength_(code->length()),
lineNumberTableLength_(lineNumbers->length()),
exceptionHandlerTableLength_(exceptionHandlers->length())
{
code->copyTo(body);
lineNumbers->copyTo(lineNumber(0));
exceptionHandlers->copyTo(exceptionHandler(0));
}
uint8_t* code() {
return body;
}
unsigned codeLength() {
return codeLength_;
}
NativeLineNumber* lineNumber(unsigned index) {
return reinterpret_cast<NativeLineNumber*>
(body + pad(codeLength_)) + index;
}
unsigned lineNumberTableLength() {
return lineNumberTableLength_ / sizeof(NativeLineNumber);
}
NativeExceptionHandler* exceptionHandler(unsigned index) {
return reinterpret_cast<NativeExceptionHandler*>
(body + pad(codeLength_) + pad(lineNumberTableLength_)) + index;
}
unsigned exceptionHandlerTableLength() {
return exceptionHandlerTableLength_ / sizeof(NativeExceptionHandler);
}
uint32_t codeLength_;
uint32_t lineNumberTableLength_;
uint32_t exceptionHandlerTableLength_;
uint8_t body[0];
};
class MyThread: public Thread {
public:
MyThread(Machine* m, object javaThread, vm::Thread* parent):
@ -179,22 +135,22 @@ class MyThread: public Thread {
Reference* reference;
};
inline bool
frameValid(void* frame)
{
return frame != 0;
}
inline void*
frameBase(void* frame)
{
return static_cast<void**>(frame)[- (FrameFootprint / BytesPerWord) - 1];
return *static_cast<void**>(frame);
}
inline bool
frameValid(void* frame)
{
return frameBase(frame) != 0;
}
inline void*
frameNext(void* frame)
{
return static_cast<void**>(frameBase(frame))[FrameNext / BytesPerWord];
return static_cast<void**>(frameBase(frame))[FrameNext / BytesPerWord] ;
}
inline object
@ -206,7 +162,7 @@ frameMethod(void* frame)
inline void*
frameAddress(void* frame)
{
return static_cast<void**>(frame)[- (FrameFootprint / BytesPerWord)];
return static_cast<void**>(frame)[1];
}
inline void*
@ -215,21 +171,71 @@ frameReturnAddress(void* frame)
return static_cast<void**>(frameBase(frame))[1];
}
inline uint8_t*
compiledCode(Compiled* code)
{
return compiledBody(code);
}
inline NativeLineNumber*
compiledLineNumber(Thread* t, Compiled* code, unsigned index)
{
assert(t, index < compiledLineNumberTableLength(code));
return reinterpret_cast<NativeLineNumber*>
(compiledBody(code) + pad(compiledCodeLength(code)));
}
inline NativeExceptionHandler*
compiledExceptionHandler(Thread* t, Compiled* code, unsigned index)
{
assert(t, index < compiledExceptionHandlerTableLength(code));
return reinterpret_cast<NativeExceptionHandler*>
(compiledBody(code) + pad(compiledCodeLength(code))
+ pad(compiledLineNumberTableLength(code)));
}
inline Compiled*
makeCompiled(Thread* t, Buffer* code, Buffer* lineNumbers,
Buffer* exceptionHandlers)
{
Compiled* c = static_cast<Compiled*>
(t->m->system->allocate(sizeof(Compiled)
+ pad(code->length())
+ pad(lineNumbers->length())
+ pad(exceptionHandlers->length())));
compiledCodeLength(c) = code->length();
compiledLineNumberTableLength(c) = lineNumbers->length();
compiledExceptionHandlerTableLength(c) = exceptionHandlers->length();
if (code->length()) {
code->copyTo(compiledCode(c));
}
if (lineNumbers->length()) {
lineNumbers->copyTo(compiledLineNumber(t, c, 0));
}
if (exceptionHandlers->length()) {
exceptionHandlers->copyTo(compiledExceptionHandler(t, c, 0));
}
return c;
}
inline unsigned
addressOffset(Thread* t, object method, void* address)
{
Code* code = static_cast<Code*>(methodCompiled(t, method));
return static_cast<uint8_t*>(address) - code->code();
Compiled* code = reinterpret_cast<Compiled*>(methodCompiled(t, method));
return static_cast<uint8_t*>(address) - compiledCode(code);
}
NativeExceptionHandler*
findExceptionHandler(Thread* t, void* frame)
{
object method = frameMethod(frame);
Code* code = static_cast<Code*>(methodCompiled(t, method));
Compiled* code = reinterpret_cast<Compiled*>(methodCompiled(t, method));
for (unsigned i = 0; i < code->exceptionHandlerTableLength(); ++i) {
NativeExceptionHandler* handler = code->exceptionHandler(i);
for (unsigned i = 0; i < compiledExceptionHandlerTableLength(code); ++i) {
NativeExceptionHandler* handler = compiledExceptionHandler(t, code, i);
unsigned offset = addressOffset(t, method, frameAddress(frame));
if (offset - 1 >= nativeExceptionHandlerStart(handler)
@ -262,13 +268,15 @@ unwind(MyThread* t)
or methodFlags(t, frameMethod(next)) & ACC_NATIVE)
{
t->frame = next;
vmJump(frameReturnAddress(frame));
vmJump(frameReturnAddress(frame), frameBase(frame));
} else if ((methodFlags(t, frameMethod(frame)) & ACC_NATIVE) == 0) {
NativeExceptionHandler* eh = findExceptionHandler(t, frame);
if (eh) {
Code* code = static_cast<Code*>(methodCompiled(t, frameMethod(frame)));
Compiled* code = reinterpret_cast<Compiled*>
(methodCompiled(t, frameMethod(frame)));
t->frame = frame;
vmJump(code->code() + nativeExceptionHandlerIp(eh));
vmJump(compiledCode(code) + nativeExceptionHandlerIp(eh),
frameBase(frame));
}
}
}
@ -286,9 +294,9 @@ void NO_RETURN
throw_(MyThread* t, object o)
{
if (o) {
t->exception = makeNullPointerException(t);
} else {
t->exception = o;
} else {
t->exception = makeNullPointerException(t);
}
unwind(t);
}
@ -652,6 +660,11 @@ class Assembler {
code.appendAddress(v);
}
void lea(Register src, int32_t srcOffset, Register dst) {
rex();
offsetInstruction(0x8d, 0, 0x40, 0x80, dst, src, srcOffset);
}
void nop() {
code.append(0x90);
}
@ -949,17 +962,15 @@ parameterOffset(unsigned index)
class Compiler: public Assembler {
public:
Compiler(Thread* t):
Assembler(s),
Compiler(MyThread* t):
Assembler(t->m->system),
t(t),
threadFrameOffset(reinterpret_cast<uintptr_t>(&(t->frame))
- reinterpret_cast<uintptr_t>(t))
poolRegisterClobbered(true),
javaIPs(s, 1024),
machineIPs(s, 1024),
lineNumbers(s, 256),
exceptionHandlers(s, 256),
pool(s, 256)
javaIPs(t->m->system, 1024),
machineIPs(t->m->system, 1024),
lineNumbers(t->m->system, 256),
exceptionHandlers(t->m->system, 256),
pool(t->m->system, 256)
{ }
void pushReturnValue(unsigned code) {
@ -992,19 +1003,31 @@ class Compiler: public Assembler {
unsigned footprint = FrameFootprint
+ (methodParameterFootprint(t, target) * BytesPerWord);
Code* code = static_cast<Code*>(methodCompiled(t, target));
Compiled* code = reinterpret_cast<Compiled*>(methodCompiled(t, target));
push(rsp);
push(rbp);
push(poolRegister(), poolReference(target));
push(rbp, FrameThread);
callAlignedAddress(code->code());
callAlignedAddress(compiledCode(code));
add(footprint, rsp); // pop arguments
pushReturnValue(methodReturnCode(t, target));
}
void compileCall2(void* function, unsigned argCount) {
mov(rbp, FrameThread, rax);
lea(rsp, -(BytesPerWord * 2), rcx);
mov(rcx, rax, threadFrameOffset()); // set thread frame to current
callAddress(function);
if (BytesPerWord == 4) {
add(BytesPerWord * argCount, rsp);
}
}
void compileCall(void* function, object arg1) {
if (BytesPerWord == 4) {
push(poolRegister(), poolReference(arg1));
@ -1014,14 +1037,7 @@ class Compiler: public Assembler {
mov(rbp, FrameThread, rdi);
}
mov(rbp, FrameThread, rax);
mov(rbp, rax, threadFrameOffset); // set thread frame to current
callAddress(function);
if (BytesPerWord == 4) {
add(BytesPerWord * 2, rsp);
}
compileCall2(function, 2);
}
void compileCall(void* function, Register arg1) {
@ -1033,14 +1049,7 @@ class Compiler: public Assembler {
mov(rbp, FrameThread, rdi);
}
mov(rbp, FrameThread, rax);
mov(rbp, rax, threadFrameOffset); // set thread frame to current
callAddress(function);
if (BytesPerWord == 4) {
add(BytesPerWord * 2, rsp);
}
compileCall2(function, 2);
}
void compileCall(void* function, object arg1, Register arg2) {
@ -1054,38 +1063,21 @@ class Compiler: public Assembler {
mov(rbp, FrameThread, rdi);
}
mov(rbp, FrameThread, rax);
mov(rbp, rax, threadFrameOffset); // set thread frame to current
callAddress(function);
if (BytesPerWord == 4) {
add(BytesPerWord * 3, rsp);
}
compileCall2(function, 3);
}
void compileCall(void* function, void* arg1, Register arg2) {
mov(rbp, FrameThread, rax);
mov(rbp, rax, frameOffset); // set thread frame to current
if (BytesPerWord == 4) {
push(arg2);
pushAddress(arg1);
pushAddress(reinterpret_cast<uintptr_t>(arg1));
push(rbp, FrameThread);
} else {
mov(arg2, rdx);
mov(arg1, rsi);
mov(reinterpret_cast<uintptr_t>(arg1), rsi);
mov(rbp, FrameThread, rdi);
}
mov(rbp, FrameThread, rax);
mov(rbp, rax, threadFrameOffset); // set thread frame to current
callAddress(function);
if (BytesPerWord == 4) {
add(BytesPerWord * 3, rsp);
}
compileCall2(function, 3);
}
void compileCall(void* function, Register arg1, Register arg2) {
@ -1099,17 +1091,10 @@ class Compiler: public Assembler {
mov(rbp, FrameThread, rdi);
}
mov(rbp, FrameThread, rax);
mov(rbp, rax, threadFrameOffset); // set thread frame to current
callAddress(function);
if (BytesPerWord == 4) {
add(BytesPerWord * 3, rsp);
}
compileCall2(function, 3);
}
void compile(MyThread* t, object method) {
Compiled* compile(object method) {
PROTECT(t, method);
object code = methodCode(t, method);
@ -1133,7 +1118,7 @@ class Compiler: public Assembler {
if (lnt and lineNumberTableLength(t, lnt)) {
lineNumberIndex = 0;
} else {
lineNumberIndex = 0;
lineNumberIndex = -1;
}
for (unsigned ip = 0; ip < codeLength(t, code);) {
@ -1144,11 +1129,15 @@ class Compiler: public Assembler {
object lnt = codeLineNumberTable(t, code);
LineNumber* ln = lineNumberTableBody(t, lnt, lineNumberIndex);
if (lineNumberIp(t, ln) == ip) {
if (lineNumberIp(ln) == ip) {
lineNumbers.append4(this->code.length());
lineNumbers.append4(lineNumberLine(t, ln));
if (lineNumberIndex < lineNumberTableLength(t, lnt)) {
lineNumbers.append4(lineNumberLine(ln));
if (static_cast<unsigned>(lineNumberIndex) + 1
< lineNumberTableLength(t, lnt))
{
++ lineNumberIndex;
} else {
lineNumberIndex = -1;
}
}
}
@ -1221,7 +1210,7 @@ class Compiler: public Assembler {
outOfBounds.mark();
compileCall
(throwNew,
(reinterpret_cast<void*>(throwNew),
arrayBody
(t, t->m->types, Machine::ArrayIndexOutOfBoundsExceptionType));
@ -1289,7 +1278,7 @@ class Compiler: public Assembler {
outOfBounds.mark();
compileCall
(throwNew,
(reinterpret_cast<void*>(throwNew),
arrayBody
(t, t->m->types, Machine::ArrayIndexOutOfBoundsExceptionType));
@ -1334,7 +1323,7 @@ class Compiler: public Assembler {
uint16_t index = codeReadInt16(t, code, ip);
object class_ = resolveClass(t, codePool(t, code), index - 1);
if (UNLIKELY(t->exception)) return;
if (UNLIKELY(t->exception)) return 0;
Label nonnegative(this);
@ -1343,11 +1332,12 @@ class Compiler: public Assembler {
jle(nonnegative);
compileCall
(throwNew,
(reinterpret_cast<void*>(throwNew),
arrayBody(t, t->m->types, Machine::NegativeArraySizeExceptionType));
nonnegative.mark();
compileCall(makeBlankObjectArray, class_, rax);
compileCall(reinterpret_cast<void*>(makeBlankObjectArray),
class_, rax);
push(rax);
} break;
@ -1397,7 +1387,7 @@ class Compiler: public Assembler {
case athrow:
pop(rax);
compileCall(throw_, rax);
compileCall(reinterpret_cast<void*>(throw_), rax);
break;
case bipush: {
@ -1408,7 +1398,7 @@ class Compiler: public Assembler {
uint16_t index = codeReadInt16(t, code, ip);
object class_ = resolveClass(t, codePool(t, code), index - 1);
if (UNLIKELY(t->exception)) return;
if (UNLIKELY(t->exception)) return 0;
Label next(this);
@ -1421,12 +1411,12 @@ class Compiler: public Assembler {
cmp(rcx, rax);
je(next);
compileCall(isAssignableFrom, rcx, rax);
compileCall(reinterpret_cast<void*>(isAssignableFrom), rcx, rax);
cmp(0, rax);
jne(next);
compileCall
(throwNew,
(reinterpret_cast<void*>(throwNew),
arrayBody(t, t->m->types, Machine::ClassCastExceptionType));
next.mark();
@ -1440,7 +1430,7 @@ class Compiler: public Assembler {
uint16_t index = codeReadInt16(t, code, ip);
object field = resolveField(t, codePool(t, code), index - 1);
if (UNLIKELY(t->exception)) return;
if (UNLIKELY(t->exception)) return 0;
pop(rax);
@ -1485,11 +1475,11 @@ class Compiler: public Assembler {
uint16_t index = codeReadInt16(t, code, ip);
object field = resolveField(t, codePool(t, code), index - 1);
if (UNLIKELY(t->exception)) return;
if (UNLIKELY(t->exception)) return 0;
PROTECT(t, field);
initClass(t, fieldClass(t, field));
if (UNLIKELY(t->exception)) return;
if (UNLIKELY(t->exception)) return 0;
object table = classStaticTable(t, fieldClass(t, field));
@ -1725,7 +1715,7 @@ class Compiler: public Assembler {
uint16_t index = codeReadInt16(t, code, ip);
object class_ = resolveClass(t, codePool(t, code), index - 1);
if (UNLIKELY(t->exception)) return;
if (UNLIKELY(t->exception)) return 0;
Label call(this);
Label zero(this);
@ -1744,7 +1734,7 @@ class Compiler: public Assembler {
jmp(next);
call.mark();
compileCall(isAssignableFrom, rcx, rax);
compileCall(reinterpret_cast<void*>(isAssignableFrom), rcx, rax);
push(rax);
jmp(next);
@ -1758,34 +1748,34 @@ class Compiler: public Assembler {
uint16_t index = codeReadInt16(t, code, ip);
object target = resolveMethod(t, codePool(t, code), index - 1);
if (UNLIKELY(t->exception)) return;
if (UNLIKELY(t->exception)) return 0;
object class_ = methodClass(t, target);
if (isSpecialMethod(t, target, class_)) {
target = findMethod(t, target, classSuper(t, class_));
}
compileDirectInvoke(t, target);
compileDirectInvoke(target);
} break;
case invokestatic: {
uint16_t index = codeReadInt16(t, code, ip);
object target = resolveMethod(t, codePool(t, code), index - 1);
if (UNLIKELY(t->exception)) return;
if (UNLIKELY(t->exception)) return 0;
PROTECT(t, target);
initClass(t, methodClass(t, target));
if (UNLIKELY(t->exception)) return;
if (UNLIKELY(t->exception)) return 0;
compileDirectInvoke(t, target);
compileDirectInvoke(target);
} break;
case invokevirtual: {
uint16_t index = codeReadInt16(t, code, ip);
object target = resolveMethod(t, codePool(t, code), index - 1);
if (UNLIKELY(t->exception)) return;
if (UNLIKELY(t->exception)) return 0;
unsigned parameterFootprint
= methodParameterFootprint(t, target) * BytesPerWord;
@ -1812,7 +1802,7 @@ class Compiler: public Assembler {
add(footprint, rsp); // pop arguments
pushReturnValue(t, methodReturnCode(t, target));
pushReturnValue(methodReturnCode(t, target));
} break;
case isub:
@ -1857,16 +1847,16 @@ class Compiler: public Assembler {
uint16_t index = codeReadInt16(t, code, ip);
object class_ = resolveClass(t, codePool(t, code), index - 1);
if (UNLIKELY(t->exception)) return;
if (UNLIKELY(t->exception)) return 0;
PROTECT(t, class_);
initClass(t, class_);
if (UNLIKELY(t->exception)) return;
if (UNLIKELY(t->exception)) return 0;
if (classVmFlags(t, class_) & WeakReferenceFlag) {
compileCall(makeNewWeakReference, class_);
compileCall(reinterpret_cast<void*>(makeNewWeakReference), class_);
} else {
compileCall(makeNew, class_);
compileCall(reinterpret_cast<void*>(makeNew), class_);
}
push(rax);
@ -1882,7 +1872,7 @@ class Compiler: public Assembler {
jge(nonnegative);
compileCall
(throwNew,
(reinterpret_cast<void*>(throwNew),
arrayBody
(t, t->m->types, Machine::NegativeArraySizeExceptionType));
@ -1925,7 +1915,8 @@ class Compiler: public Assembler {
default: abort(t);
}
compileCall(makeBlankArray, constructor, rax);
compileCall(reinterpret_cast<void*>(makeBlankArray),
reinterpret_cast<void*>(constructor), rax);
push(rax);
} break;
@ -1937,7 +1928,7 @@ class Compiler: public Assembler {
uint16_t index = codeReadInt16(t, code, ip);
object field = resolveField(t, codePool(t, code), index - 1);
if (UNLIKELY(t->exception)) return;
if (UNLIKELY(t->exception)) return 0;
switch (fieldCode(t, field)) {
case ByteField:
@ -1989,10 +1980,10 @@ class Compiler: public Assembler {
uint16_t index = codeReadInt16(t, code, ip);
object field = resolveField(t, codePool(t, code), index - 1);
if (UNLIKELY(t->exception)) return;
if (UNLIKELY(t->exception)) return 0;
initClass(t, fieldClass(t, field));
if (UNLIKELY(t->exception)) return;
if (UNLIKELY(t->exception)) return 0;
object table = classStaticTable(t, fieldClass(t, field));
@ -2006,14 +1997,16 @@ class Compiler: public Assembler {
case ShortField:
case FloatField:
case IntField: {
compileCall(makeNew, arrayBody(t, t->m->types, Machine::IntType));
compileCall(reinterpret_cast<void*>(makeNew),
arrayBody(t, t->m->types, Machine::IntType));
pop4(rax, IntValue);
} break;
case DoubleField:
case LongField: {
compileCall(makeNew, arrayBody(t, t->m->types, Machine::LongType));
compileCall(reinterpret_cast<void*>(makeNew),
arrayBody(t, t->m->types, Machine::LongType));
pop4(rax, LongValue);
pop4(rax, LongValue + 4);
@ -2051,7 +2044,6 @@ class Compiler: public Assembler {
uint32_t machineIpForJavaIp(uint16_t javaIP) {
unsigned bottom = 0;
unsigned top = javaIPs.length() / 2;
bool success = false;
for (unsigned span = top - bottom; span; span = top - bottom) {
unsigned middle = bottom + (span / 2);
uint32_t k = javaIPs.get2(middle * 2);
@ -2080,36 +2072,45 @@ class Compiler: public Assembler {
PROTECT(t, code);
object eht = codeExceptionHandlerTable(t, code);
PROTECT(t, eht);
if (eht) {
PROTECT(t, eht);
for (unsigned i = 0; i < exceptionHandlerTableLength(t, eht); ++i) {
ExceptionHandler* eh = exceptionHandlerTableBody(t, eht, i);
for (unsigned i = 0; i < exceptionHandlerTableLength(t, eht); ++i) {
ExceptionHandler* eh = exceptionHandlerTableBody(t, eht, i);
exceptionHandlers.append4(machineIpForJavaIp(exceptionHandlerStart(eh)));
exceptionHandlers.append4(machineIpForJavaIp(exceptionHandlerEnd(eh)));
exceptionHandlers.append4(machineIpForJavaIp(exceptionHandlerIp(eh)));
exceptionHandlers.append4
(machineIpForJavaIp(exceptionHandlerStart(eh)));
unsigned ct = exceptionHandlerCatchType(eh);
object catchType;
if (ct) {
catchType = resolveClass
(t, codePool(t, code), exceptionHandlerCatchType(eh) - 1);
} else {
catchType = 0;
exceptionHandlers.append4
(machineIpForJavaIp(exceptionHandlerEnd(eh)));
exceptionHandlers.append4
(machineIpForJavaIp(exceptionHandlerIp(eh)));
unsigned ct = exceptionHandlerCatchType(eh);
object catchType;
if (ct) {
catchType = resolveClass
(t, codePool(t, code), exceptionHandlerCatchType(eh) - 1);
} else {
catchType = 0;
}
exceptionHandlers.append4
(catchType ? (poolReference(catchType) / BytesPerWord) - 1 : 0);
}
exceptionHandlers.append4
(catchType ? (poolReference(catchType) / BytesPerWord) - 1 : 0);
}
}
Code* compileNativeInvoker() {
unsigned threadFrameOffset() {
return reinterpret_cast<uintptr_t>(&(t->frame))
- reinterpret_cast<uintptr_t>(t);
}
Compiled* compileNativeInvoker() {
push(rbp);
mov(rsp, rbp);
mov(rbp, FrameThread, rax);
mov(rbp, rax, threadFrameOffset); // set thread frame to current
if (BytesPerWord == 4) {
push(rbp, FrameMethod);
push(rbp, FrameThread);
@ -2118,6 +2119,9 @@ class Compiler: public Assembler {
mov(rbp, FrameThread, rdi);
}
mov(rbp, FrameThread, rax);
mov(rbp, rax, threadFrameOffset()); // set thread frame to current
mov(reinterpret_cast<uintptr_t>(invokeNative), rax);
call(rax);
@ -2132,13 +2136,10 @@ class Compiler: public Assembler {
return finish();
}
Code* compileStub() {
Compiled* compileStub() {
push(rbp);
mov(rsp, rbp);
mov(rbp, FrameThread, rax);
mov(rbp, rax, threadFrameOffset); // set thread frame to current
if (BytesPerWord == 4) {
push(rbp, FrameMethod);
push(rbp, FrameThread);
@ -2147,6 +2148,9 @@ class Compiler: public Assembler {
mov(rbp, FrameThread, rdi);
}
mov(rbp, FrameThread, rax);
mov(rbp, rax, threadFrameOffset()); // set thread frame to current
mov(reinterpret_cast<uintptr_t>(compileMethod), rax);
call(rax);
@ -2166,19 +2170,14 @@ class Compiler: public Assembler {
return finish();
}
Code* finish() {
unsigned footprint = pad(code.length())
+ pad(lineNumbers.length())
+ pad(exceptionHandlers.length());
return new (t->m->system->allocate(sizeof(Code) + footprint))
Code(&code, &lineNumbers, &exceptionHandlers);
Compiled* finish() {
return makeCompiled(t, &code, &lineNumbers, &exceptionHandlers);
}
object makePool() {
if (pool.length()) {
object array = makeArray(t, pool.length() / BytesPerWord, false);
pool.copyTo(&arrayBody(t, array));
pool.copyTo(&arrayBody(t, array, 0));
return array;
} else {
return 0;
@ -2195,7 +2194,7 @@ class Compiler: public Assembler {
mov(rdi, MethodCode, rdi);
poolRegisterClobbered = false;
}
pool.appendAddress(o);
pool.appendAddress(reinterpret_cast<uintptr_t>(o));
return pool.length() + BytesPerWord;
}
@ -2212,7 +2211,6 @@ class Compiler: public Assembler {
}
MyThread* t;
unsigned threadFrameOffset;
bool poolRegisterClobbered;
Buffer javaIPs;
Buffer machineIPs;
@ -2224,12 +2222,16 @@ class Compiler: public Assembler {
void
compileMethod2(MyThread* t, object method)
{
if (methodCompiled(t, method) == t->m->processor->methodStub(t)) {
if (reinterpret_cast<Compiled*>(methodCompiled(t, method))
== t->m->processor->methodStub(t))
{
PROTECT(t, method);
ACQUIRE(t, t->m->classLock);
if (methodCompiled(t, method) == t->m->processor->methodStub(t)) {
if (reinterpret_cast<Compiled*>(methodCompiled(t, method))
== t->m->processor->methodStub(t))
{
if (Verbose) {
fprintf(stderr, "compiling %s.%s\n",
&byteArrayBody(t, className(t, methodClass(t, method)), 0),
@ -2237,17 +2239,17 @@ compileMethod2(MyThread* t, object method)
}
Compiler c(t);
Code* code = c.compile(method);
Compiled* code = c.compile(method);
if (Verbose) {
fprintf(stderr, "compiled %s.%s from %p to %p\n",
&byteArrayBody(t, className(t, methodClass(t, method)), 0),
&byteArrayBody(t, methodName(t, method), 0),
code->code(),
code->code() + code->codeLength());
compiledCode(code),
compiledCode(code) + compiledCodeLength(code));
}
set(t, methodCompiled(t, method), compiled);
methodCompiled(t, method) = reinterpret_cast<uint64_t>(code);
object pool = c.makePool();
set(t, methodCode(t, method), pool);
@ -2259,7 +2261,7 @@ void
updateCaller(MyThread* t, object method)
{
uintptr_t stub = reinterpret_cast<uintptr_t>
(&compiledBody(t, t->m->processor->methodStub(t), 0));
(compiledCode(static_cast<Compiled*>(t->m->processor->methodStub(t))));
Assembler a(t->m->system);
a.mov(stub, rax);
@ -2277,7 +2279,7 @@ updateCaller(MyThread* t, object method)
% BytesPerWord == 0);
*reinterpret_cast<void**>(caller + offset)
= &compiledBody(t, methodCompiled(t, method), 0);
= compiledCode(reinterpret_cast<Compiled*>(methodCompiled(t, method)));
}
}
@ -2466,9 +2468,10 @@ invoke(Thread* thread, object method, ArgumentList* arguments)
void* frame = t->frame;
Reference* reference = t->reference;
Compiled* code = reinterpret_cast<Compiled*>(methodCompiled(t, method));
uint64_t result = vmInvoke
(&compiledBody(t, methodCompiled(t, method), 0), arguments->array,
arguments->position * BytesPerWord, returnType);
(compiledCode(code), arguments->array, arguments->position * BytesPerWord,
returnType);
while (t->reference != reference) {
dispose(t, t->reference);
@ -2616,31 +2619,33 @@ class MyProcessor: public Processor {
virtual uintptr_t
frameStart(Thread* vmt)
{
return static_cast<MyThread*>(vmt)->frame;
return reinterpret_cast<uintptr_t>(static_cast<MyThread*>(vmt)->frame);
}
virtual uintptr_t
frameNext(Thread*, uintptr_t frame)
{
::frameNext(reinterpret_cast<void*>(frame));
return reinterpret_cast<uintptr_t>
(::frameNext(reinterpret_cast<void*>(frame)));
}
virtual bool
frameValid(Thread*, uintptr_t frame)
{
return ::frameValid(frame);
return ::frameValid(reinterpret_cast<void*>(frame));
}
virtual object
frameMethod(Thread*, uintptr_t frame)
{
return ::frameMethod(frame);
return ::frameMethod(reinterpret_cast<void*>(frame));
}
virtual unsigned
frameIp(Thread* t, uintptr_t frame)
{
return addressOffset(t, frameMethod(frame), frameAddress(frame));
void* f = reinterpret_cast<void*>(frame);
return addressOffset(t, ::frameMethod(f), ::frameAddress(f));
}
virtual object*
@ -2742,8 +2747,8 @@ class MyProcessor: public Processor {
}
System* s;
void* methodStub_;
void* nativeInvoker_;
Compiled* methodStub_;
Compiled* nativeInvoker_;
};
} // namespace

View File

@ -2855,13 +2855,13 @@ class MyProcessor: public Processor {
return new (s->allocate(sizeof(Thread))) Thread(m, javaThread, parent);
}
virtual object
virtual Compiled*
methodStub(vm::Thread*)
{
return 0;
}
virtual object
virtual Compiled*
nativeInvoker(vm::Thread*)
{
return 0;

View File

@ -992,11 +992,11 @@ parseMethodTable(Thread* t, Stream& s, object class_, object pool)
unsigned parameterFootprint = t->m->processor->parameterFootprint
(t, specString, flags & ACC_STATIC);
object compiled;
Compiled* compiled;
if (flags & ACC_NATIVE) {
compiled = t->m->processor->nativeInvoker(t);
compiled = static_cast<Compiled*>(t->m->processor->nativeInvoker(t));
} else {
compiled = t->m->processor->methodStub(t);
compiled = static_cast<Compiled*>(t->m->processor->methodStub(t));
}
object method = makeMethod(t,
@ -1010,7 +1010,7 @@ parseMethodTable(Thread* t, Stream& s, object class_, object pool)
arrayBody(t, pool, spec - 1),
class_,
code,
compiled);
reinterpret_cast<uint64_t>(compiled));
PROTECT(t, method);
if (flags & ACC_STATIC) {

View File

@ -14,10 +14,10 @@ class Processor {
virtual Thread*
makeThread(Machine* m, object javaThread, Thread* parent) = 0;
virtual object
virtual void*
methodStub(Thread* t) = 0;
virtual object
virtual void*
nativeInvoker(Thread* t) = 0;
virtual unsigned

View File

@ -1,8 +1,10 @@
#include "types.h"
.text
#ifdef __x86_64__
.globl amd64Call
amd64Call:
pushq %rbp
@ -100,3 +102,92 @@ exit:
popq %rbp
ret
#elif defined __i386__
#ifdef __APPLE__
.globl _cdeclCall
_cdeclCall:
#else
.globl cdeclCall
cdeclCall:
#endif
pushl %ebp
movl %esp,%ebp
// 8(%ebp): function
// 12(%ebp): stack
// 16(%ebp): stackSize
// 20(%ebp): returnType
// reserve space for arguments
movl 16(%ebp),%ecx
#ifdef __APPLE__
// align to a 16 byte boundary on Darwin
addl $15,%ecx
andl $0xFFFFFFF0,%ecx
addl $8,%ecx
#endif
subl %ecx,%esp
// copy arguments into place
movl $0,%ecx
jmp test
loop:
movl %ecx,%eax
movl %ecx,%edx
addl %esp,%edx
addl 12(%ebp),%eax
movl (%eax),%eax
movl %eax,(%edx)
addl $4,%ecx
test:
cmpl 16(%ebp),%ecx
jb loop
// call function
call *8(%ebp)
// handle return value based on expected type
movl 20(%ebp),%ecx
void:
cmpl $VOID_TYPE,%ecx
jne int64
jmp exit
int64:
cmpl $INT64_TYPE,%ecx
jne float
jmp exit
float:
cmpl $FLOAT_TYPE,%ecx
jne double
fstps 8(%ebp)
movl 8(%ebp),%eax
jmp int32
double:
cmpl $DOUBLE_TYPE,%ecx
jne int32
fstpl 8(%ebp)
movl 8(%ebp),%eax
movl 12(%ebp),%edx
jmp exit
int32:
movl $0,%edx
exit:
movl %ebp,%esp
popl %ebp
ret
#else
# error unsupported platform
#endif

View File

@ -14,7 +14,7 @@ inline unsigned
pad(unsigned size, unsigned alignment)
{
unsigned n = alignment;
while (n % size and n % sizeof(void*)) ++ n;
while (size and n % size and n % sizeof(void*)) ++ n;
return n - alignment;
}
@ -46,6 +46,24 @@ startsWith(const char* a, const char* b)
return strncmp(a, b, strlen(a)) == 0;
}
inline bool
endsWith(const char* a, const char* b)
{
unsigned al = strlen(a);
unsigned bl = strlen(b);
return (bl >= al) and strncmp(a, b + (bl - al), al) == 0;
}
inline const char*
take(unsigned n, const char* c)
{
char* r = static_cast<char*>(malloc(n + 1));
assert(r);
memcpy(r, c, n);
r[n] = 0;
return r;
}
class Object {
public:
typedef enum {
@ -776,6 +794,8 @@ sizeOf(const char* type, Object* declarations)
return sizeof(uint64_t);
} else if (equal(type, "char")) {
return sizeof(char);
} else if (endsWith("[0]", type)) {
return 0;
} else if (namesPointer(type)) {
return sizeof(void*);
} else {
@ -1051,12 +1071,19 @@ writeAccessor(Output* out, Object* member, Object* offset, bool unsafe = false)
}
out->write("inline ");
out->write(typeName);
if (member->type != Object::Scalar and memberTypeObject(member)) {
if (endsWith("[0]", typeName)) {
out->write(take(strlen(typeName) - 3, typeName));
out->write("*");
} else {
out->write("&");
out->write(typeName);
if (member->type != Object::Scalar and memberTypeObject(member)) {
out->write("*");
} else {
out->write("&");
}
}
out->write("\n");
writeAccessorName(out, member, true, unsafe);
if (memberOwner(member)->type == Object::Pod) {
@ -1093,18 +1120,28 @@ writeAccessor(Output* out, Object* member, Object* offset, bool unsafe = false)
}
out->write(" return reinterpret_cast<");
out->write(typeName);
if (member->type != Object::Scalar and memberTypeObject(member)) {
if (endsWith("[0]", typeName)) {
out->write(take(strlen(typeName) - 3, typeName));
out->write("*");
} else {
out->write("&");
out->write(typeName);
if (member->type != Object::Scalar and memberTypeObject(member)) {
out->write("*");
} else {
out->write("&");
}
}
if (memberOwner(member)->type == Object::Pod) {
out->write(">(o->body");
} else {
out->write(">(reinterpret_cast<uint8_t*>(o)");
}
if (member->type != Object::Scalar and memberTypeObject(member)) {
if (endsWith("[0]", typeName)
or (member->type != Object::Scalar
and memberTypeObject(member)))
{
out->write(" + ");
} else {
out->write("[");
@ -1121,7 +1158,10 @@ writeAccessor(Output* out, Object* member, Object* offset, bool unsafe = false)
out->write(elementSize);
out->write(")");
}
if (member->type == Object::Scalar or memberTypeObject(member) == 0) {
if (not endsWith("[0]", typeName)
and (member->type == Object::Scalar
or memberTypeObject(member) == 0))
{
out->write("]");
}
out->write(");\n}\n\n");

View File

@ -38,6 +38,12 @@
(object spec)
(object class))
(pod compiled
(uint32_t codeLength)
(uint16_t lineNumberTableLength)
(uint16_t exceptionHandlerTableLength)
(uint8_t[0] body))
(type method java/lang/reflect/Method
(extends accessibleObject)
(uint8_t vmFlags)
@ -50,13 +56,7 @@
(object spec)
(object class)
(object code)
(void* compiled))
(type compiled
(nogc object pool)
(uint32_t lineNumbers)
(uint32_t exceptionHandlers)
(array uint8_t body))
(uint64_t compiled))
(type nativeMethodData
(void* function)