more work on JIT unwinding

This commit is contained in:
Joel Dice 2007-10-04 16:41:19 -06:00
parent 2135f62584
commit feeaecbfd8
8 changed files with 256 additions and 88 deletions

View File

@ -590,7 +590,7 @@ Java_java_lang_Throwable_resolveTrace(Thread* t, jclass, jobject trace)
object method = methodName(t, traceElementMethod(t, e));
method = makeString(t, method, 0, byteArrayLength(t, method) - 1, 0);
unsigned line = lineNumber
unsigned line = t->m->processor->lineNumber
(t, traceElementMethod(t, e), traceElementIp(t, e));
object ste = makeStackTraceElement(t, class_, method, 0, line);

View File

@ -43,12 +43,10 @@ test:
.globl vmJump
vmJump:
// %rdi: address
// %rsi: base
movq %rsi,%rsp
popq %rbp
jmp *(%rdi)
movq %rsi,%rbp
movq %rdx,%rsp
jmp *%rdi
#elif defined __i386__
.globl vmInvoke
@ -109,11 +107,9 @@ exit:
.globl vmJump
vmJump:
// 4(%esp): address
// 8(%esp): base
movl 4(%esp),%eax
movl 8(%esp),%esp
popl %ebp
movl 8(%esp),%ebp
movl 12(%esp),%esp
jmp *%eax
#else

View File

@ -15,7 +15,7 @@ extern "C" void
vmCall();
extern "C" void NO_RETURN
vmJump(void* address, void* base);
vmJump(void* address, void* base, void* stack);
namespace {
@ -141,7 +141,8 @@ class MyThread: public Thread {
inline void*
frameBase(void* frame)
{
return static_cast<void**>(frame)[(-FrameFootprint / BytesPerWord) - 2];
return static_cast<void**>(frame)
[static_cast<int>(- (FrameFootprint / BytesPerWord) - 2)];
}
inline bool
@ -165,7 +166,8 @@ frameMethod(void* frame)
inline void*
frameAddress(void* frame)
{
return static_cast<void**>(frame)[(-FrameFootprint / BytesPerWord) - 1];
return static_cast<void**>(frame)
[static_cast<int>(- (FrameFootprint / BytesPerWord) - 1)];
}
inline void*
@ -180,25 +182,38 @@ compiledCode(Compiled* code)
return compiledBody(code);
}
inline unsigned
compiledLineNumberCount(Thread*, Compiled* code)
{
return compiledLineNumberTableLength(code) / sizeof(NativeLineNumber);
}
inline NativeLineNumber*
compiledLineNumber(Thread* t, Compiled* code, unsigned index)
{
assert(t, index < compiledLineNumberTableLength(code));
assert(t, index < compiledLineNumberCount(t, code));
return reinterpret_cast<NativeLineNumber*>
(compiledBody(code) + pad(compiledCodeLength(code)));
(compiledBody(code) + pad(compiledCodeLength(code))) + index;
}
inline unsigned
compiledExceptionHandlerCount(Thread*, Compiled* code)
{
return compiledExceptionHandlerTableLength(code)
/ sizeof(NativeExceptionHandler);
}
inline NativeExceptionHandler*
compiledExceptionHandler(Thread* t, Compiled* code, unsigned index)
{
assert(t, index < compiledExceptionHandlerTableLength(code));
assert(t, index < compiledExceptionHandlerCount(t, code));
return reinterpret_cast<NativeExceptionHandler*>
(compiledBody(code) + pad(compiledCodeLength(code))
+ pad(compiledLineNumberTableLength(code)));
+ pad(compiledLineNumberTableLength(code))) + index;
}
inline Compiled*
makeCompiled(Thread* t, Buffer* code, Buffer* lineNumbers,
makeCompiled(Thread* t, object method, Buffer* code, Buffer* lineNumbers,
Buffer* exceptionHandlers)
{
Compiled* c = static_cast<Compiled*>
@ -207,6 +222,13 @@ makeCompiled(Thread* t, Buffer* code, Buffer* lineNumbers,
+ pad(lineNumbers->length())
+ pad(exceptionHandlers->length())));
if (method) {
compiledMaxLocals(c) = codeMaxLocals(t, methodCode(t, method));
compiledMaxStack(c) = codeMaxStack(t, methodCode(t, method));
} else {
compiledMaxLocals(c) = 0;
compiledMaxStack(c) = 0;
}
compiledCodeLength(c) = code->length();
compiledLineNumberTableLength(c) = lineNumbers->length();
compiledExceptionHandlerTableLength(c) = exceptionHandlers->length();
@ -237,7 +259,7 @@ findExceptionHandler(Thread* t, void* frame)
object method = frameMethod(frame);
Compiled* code = reinterpret_cast<Compiled*>(methodCompiled(t, method));
for (unsigned i = 0; i < compiledExceptionHandlerTableLength(code); ++i) {
for (unsigned i = 0; i < compiledExceptionHandlerCount(t, code); ++i) {
NativeExceptionHandler* handler = compiledExceptionHandler(t, code, i);
unsigned offset = addressOffset(t, method, frameAddress(frame));
@ -254,6 +276,14 @@ findExceptionHandler(Thread* t, void* frame)
}
if (catchType == 0 or instanceOf(t, catchType, t->exception)) {
fprintf(stderr, "exception handler match for %d in %s: "
"start: %d; end: %d; ip: %d\n",
offset,
&byteArrayBody(t, methodName(t, frameMethod(frame)), 0),
nativeExceptionHandlerStart(handler),
nativeExceptionHandlerEnd(handler),
nativeExceptionHandlerIp(handler));
return handler;
}
}
@ -266,21 +296,40 @@ void NO_RETURN
unwind(MyThread* t)
{
for (void* frame = t->frame; frameValid(frame); frame = frameNext(frame)) {
if ((methodFlags(t, frameMethod(frame)) & ACC_NATIVE) == 0) {
NativeExceptionHandler* eh = findExceptionHandler(t, frame);
if (eh) {
object method = frameMethod(frame);
Compiled* code = reinterpret_cast<Compiled*>
(methodCompiled(t, method));
t->frame = frame;
void** stack = static_cast<void**>(frameBase(frame));
unsigned parameterFootprint = methodParameterFootprint(t, method);
unsigned localFootprint = compiledMaxLocals(code);
if (localFootprint > parameterFootprint) {
stack -= (localFootprint - parameterFootprint);
}
*(--stack) = t->exception;
t->exception = 0;
vmJump(compiledCode(code) + nativeExceptionHandlerIp(eh),
frameBase(frame),
stack);
}
}
void* next = frameNext(frame);
if (not frameValid(next)
or methodFlags(t, frameMethod(next)) & ACC_NATIVE)
{
t->frame = next;
vmJump(frameReturnAddress(frame), frameBase(frame));
} else if ((methodFlags(t, frameMethod(frame)) & ACC_NATIVE) == 0) {
NativeExceptionHandler* eh = findExceptionHandler(t, frame);
if (eh) {
Compiled* code = reinterpret_cast<Compiled*>
(methodCompiled(t, frameMethod(frame)));
t->frame = frame;
vmJump(compiledCode(code) + nativeExceptionHandlerIp(eh),
frameBase(frame));
}
vmJump(frameReturnAddress(frame),
*static_cast<void**>(frameBase(frame)),
static_cast<void**>(frameBase(frame)) + 2);
}
}
abort(t);
@ -1563,6 +1612,10 @@ class Compiler: public Assembler {
mov(rax, rsp, 0);
break;
case i2l:
push(0);
break;
case iadd:
pop(rax);
pop(rcx);
@ -1819,9 +1872,7 @@ class Compiler: public Assembler {
if (instruction == ldc) {
index = codeBody(t, code, ip++);
} else {
uint8_t index1 = codeBody(t, code, ip++);
uint8_t index2 = codeBody(t, code, ip++);
index = (index1 << 8) | index2;
index = codeReadInt16(t, code, ip);
}
object v = arrayBody(t, codePool(t, code), index - 1);
@ -1843,6 +1894,99 @@ class Compiler: public Assembler {
}
} break;
case ldc2_w: {
uint16_t index = codeReadInt16(t, code, ip);
object v = arrayBody(t, codePool(t, code), index - 1);
if (objectClass(t, v) == arrayBody(t, t->m->types, Machine::LongType))
{
push((longValue(t, v) ) & 0xFFFFFFFF);
push((longValue(t, v) >> 32) & 0xFFFFFFFF);
} else if (objectClass(t, v)
== arrayBody(t, t->m->types, Machine::DoubleType))
{
push((doubleValue(t, v) ) & 0xFFFFFFFF);
push((doubleValue(t, v) >> 32) & 0xFFFFFFFF);
} else {
abort(t);
}
} break;
case lconst_0:
push(0);
push(0);
break;
case lconst_1:
push(0);
push(1);
break;
// todo:
// case lcmp: {
// pop(rax);
// pop(rdx);
// if (BytesPerWord == 8) {
// shl(32, rax);
// }
// pushInt(t, a > b ? 1 : a == b ? 0 : -1);
// } goto loop;
case lload: {
unsigned index = codeBody(t, code, ip++);
push(rbp, localOffset(index, parameterFootprint));
push(rbp, localOffset(index + 1, parameterFootprint));
} break;
case lload_0: {
push(rbp, localOffset(0, parameterFootprint));
push(rbp, localOffset(1, parameterFootprint));
} break;
case lload_1: {
push(rbp, localOffset(1, parameterFootprint));
push(rbp, localOffset(2, parameterFootprint));
} break;
case lload_2: {
push(rbp, localOffset(2, parameterFootprint));
push(rbp, localOffset(3, parameterFootprint));
} break;
case lload_3: {
push(rbp, localOffset(3, parameterFootprint));
push(rbp, localOffset(4, parameterFootprint));
} break;
case lstore: {
unsigned index = codeBody(t, code, ip++);
pop(rbp, localOffset(index + 1, parameterFootprint));
pop(rbp, localOffset(index, parameterFootprint));
} break;
case lstore_0: {
pop(rbp, localOffset(1, parameterFootprint));
pop(rbp, localOffset(0, parameterFootprint));
} break;
case lstore_1: {
pop(rbp, localOffset(2, parameterFootprint));
pop(rbp, localOffset(1, parameterFootprint));
} break;
case lstore_2: {
pop(rbp, localOffset(3, parameterFootprint));
pop(rbp, localOffset(2, parameterFootprint));
} break;
case lstore_3: {
pop(rbp, localOffset(4, parameterFootprint));
pop(rbp, localOffset(3, parameterFootprint));
} break;
case new_: {
uint16_t index = codeReadInt16(t, code, ip);
@ -2038,7 +2182,7 @@ class Compiler: public Assembler {
resolveJumps();
buildExceptionHandlerTable(code);
return finish();
return finish(method);
}
uint32_t machineIpForJavaIp(uint16_t javaIP) {
@ -2135,7 +2279,7 @@ class Compiler: public Assembler {
add(CompiledBody, rax);
jmp(rax); // call compiled code
return finish();
return finish(0);
}
Compiled* compileNativeInvoker() {
@ -2161,7 +2305,7 @@ class Compiler: public Assembler {
pop(rbp);
ret();
return finish();
return finish(0);
}
Compiled* compileCaller() {
@ -2171,11 +2315,11 @@ class Compiler: public Assembler {
jmp(rbx);
return finish();
return finish(0);
}
Compiled* finish() {
return makeCompiled(t, &code, &lineNumbers, &exceptionHandlers);
Compiled* finish(object method) {
return makeCompiled(t, method, &code, &lineNumbers, &exceptionHandlers);
}
object makePool() {
@ -2273,7 +2417,8 @@ updateCaller(MyThread* t, object method)
a.call(rax);
uint8_t* caller = static_cast<uint8_t**>(t->frame)[1] - a.code.length();
uint8_t* caller = static_cast<uint8_t*>(frameAddress(t->frame))
- a.code.length();
if (memcmp(a.code.data, caller, a.code.length()) == 0) {
// it's a direct call - update caller to point to new code
@ -2587,9 +2732,7 @@ class MyProcessor: public Processor {
case 'J':
case 'D':
++ s;
if (BytesPerWord == 4) {
++ footprint;
}
++ footprint;
break;
default:
@ -2662,6 +2805,40 @@ class MyProcessor: public Processor {
return addressOffset(t, ::frameMethod(f), ::frameAddress(f));
}
virtual int
lineNumber(Thread* t, object method, unsigned ip)
{
if (methodFlags(t, method) & ACC_NATIVE) {
return NativeLine;
}
Compiled* code = reinterpret_cast<Compiled*>(methodCompiled(t, method));
if (compiledLineNumberCount(t, code)) {
unsigned bottom = 0;
unsigned top = compiledLineNumberCount(t, code);
for (unsigned span = top - bottom; span; span = top - bottom) {
unsigned middle = bottom + (span / 2);
NativeLineNumber* ln = compiledLineNumber(t, code, middle);
if (ip >= nativeLineNumberIp(ln)
and (middle + 1 == compiledLineNumberCount(t, code)
or ip < nativeLineNumberIp
(compiledLineNumber(t, code, middle + 1))))
{
return nativeLineNumberLine(ln);
} else if (ip < nativeLineNumberIp(ln)) {
top = middle;
} else if (ip > nativeLineNumberIp(ln)) {
bottom = middle + 1;
}
}
abort(t);
} else {
return UnknownLine;
}
}
virtual object*
makeLocalReference(Thread* vmt, object o)
{

View File

@ -1936,22 +1936,17 @@ interpret(Thread* t)
} goto loop;
case jsr: {
uint8_t offset1 = codeBody(t, code, ip++);
uint8_t offset2 = codeBody(t, code, ip++);
uint16_t offset = codeReadInt16(t, code, ip);
pushInt(t, ip);
ip = (ip - 3) + static_cast<int16_t>(((offset1 << 8) | offset2));
ip = (ip - 3) + static_cast<int16_t>(offset);
} goto loop;
case jsr_w: {
uint8_t offset1 = codeBody(t, code, ip++);
uint8_t offset2 = codeBody(t, code, ip++);
uint8_t offset3 = codeBody(t, code, ip++);
uint8_t offset4 = codeBody(t, code, ip++);
uint32_t offset = codeReadInt32(t, code, ip);
pushInt(t, ip);
ip = (ip - 3) + static_cast<int32_t>
((offset1 << 24) | (offset2 << 16) | (offset3 << 8) | offset4);
ip = (ip - 3) + static_cast<int32_t>(offset);
} goto loop;
case l2i: {
@ -2037,9 +2032,7 @@ interpret(Thread* t)
if (instruction == ldc) {
index = codeBody(t, code, ip++);
} else {
uint8_t index1 = codeBody(t, code, ip++);
uint8_t index2 = codeBody(t, code, ip++);
index = (index1 << 8) | index2;
index = codeReadInt16(t, code, ip);
}
object v = arrayBody(t, codePool(t, code), index - 1);
@ -2063,10 +2056,9 @@ interpret(Thread* t)
} goto loop;
case ldc2_w: {
uint8_t index1 = codeBody(t, code, ip++);
uint8_t index2 = codeBody(t, code, ip++);
uint16_t index = codeReadInt16(t, code, ip);
object v = arrayBody(t, codePool(t, code), ((index1 << 8) | index2) - 1);
object v = arrayBody(t, codePool(t, code), index - 1);
if (objectClass(t, v) == arrayBody(t, t->m->types, Machine::LongType)) {
pushLong(t, longValue(t, v));
@ -2987,6 +2979,30 @@ class MyProcessor: public Processor {
return ::frameIp(t, frame);
}
virtual int
lineNumber(Thread* t, object method, unsigned ip)
{
if (methodFlags(t, method) & ACC_NATIVE) {
return NativeLine;
}
object table = codeLineNumberTable(t, methodCode(t, method));
if (table) {
// todo: do a binary search:
int last = UnknownLine;
for (unsigned i = 0; i < lineNumberTableLength(t, table); ++i) {
if (ip <= lineNumberIp(lineNumberTableBody(t, table, i))) {
return last;
} else {
last = lineNumberLine(lineNumberTableBody(t, table, i));
}
}
return last;
} else {
return UnknownLine;
}
}
virtual object*
makeLocalReference(vm::Thread* vmt, object o)
{

View File

@ -2366,30 +2366,6 @@ findInHierarchy(Thread* t, object class_, object name, object spec,
return o;
}
int
lineNumber(Thread* t, object method, unsigned ip)
{
if (methodFlags(t, method) & ACC_NATIVE) {
return NativeLine;
}
object table = codeLineNumberTable(t, methodCode(t, method));
if (table) {
// todo: do a binary search:
int last = UnknownLine;
for (unsigned i = 0; i < lineNumberTableLength(t, table); ++i) {
if (ip <= lineNumberIp(lineNumberTableBody(t, table, i))) {
return last;
} else {
last = lineNumberLine(lineNumberTableBody(t, table, i));
}
}
return last;
} else {
return UnknownLine;
}
}
void
addFinalizer(Thread* t, object target, void (*finalize)(Thread*, object))
{
@ -2649,7 +2625,8 @@ printTrace(Thread* t, object exception)
(t, className(t, methodClass(t, traceElementMethod(t, e))), 0);
const int8_t* method = &byteArrayBody
(t, methodName(t, traceElementMethod(t, e)), 0);
int line = lineNumber(t, traceElementMethod(t, e), traceElementIp(t, e));
int line = t->m->processor->lineNumber
(t, traceElementMethod(t, e), traceElementIp(t, e));
fprintf(stderr, " at %s.%s ", class_, method);

View File

@ -2008,9 +2008,6 @@ objectArrayBody(Thread* t UNUSED, object array, unsigned index)
return cast<object>(array, (2 + index) * BytesPerWord);
}
int
lineNumber(Thread* t, object method, unsigned ip);
void
addFinalizer(Thread* t, object target, void (*finalize)(Thread*, object));

View File

@ -44,6 +44,9 @@ class Processor {
virtual unsigned
frameIp(Thread* t, uintptr_t frame) = 0;
virtual int
lineNumber(Thread* t, object method, unsigned ip) = 0;
virtual object*
makeLocalReference(Thread* t, object o) = 0;

View File

@ -39,9 +39,11 @@
(object class))
(pod compiled
(uint16_t maxLocals)
(uint16_t maxStack)
(uint32_t codeLength)
(uint16_t lineNumberTableLength)
(uint16_t exceptionHandlerTableLength)
(uint32_t lineNumberTableLength)
(uint32_t exceptionHandlerTableLength)
(uint8_t[0] body))
(type method java/lang/reflect/Method