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)); object method = methodName(t, traceElementMethod(t, e));
method = makeString(t, method, 0, byteArrayLength(t, method) - 1, 0); 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)); (t, traceElementMethod(t, e), traceElementIp(t, e));
object ste = makeStackTraceElement(t, class_, method, 0, line); object ste = makeStackTraceElement(t, class_, method, 0, line);

View File

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

View File

@ -15,7 +15,7 @@ extern "C" void
vmCall(); vmCall();
extern "C" void NO_RETURN extern "C" void NO_RETURN
vmJump(void* address, void* base); vmJump(void* address, void* base, void* stack);
namespace { namespace {
@ -141,7 +141,8 @@ class MyThread: public Thread {
inline void* inline void*
frameBase(void* frame) frameBase(void* frame)
{ {
return static_cast<void**>(frame)[(-FrameFootprint / BytesPerWord) - 2]; return static_cast<void**>(frame)
[static_cast<int>(- (FrameFootprint / BytesPerWord) - 2)];
} }
inline bool inline bool
@ -165,7 +166,8 @@ frameMethod(void* frame)
inline void* inline void*
frameAddress(void* frame) frameAddress(void* frame)
{ {
return static_cast<void**>(frame)[(-FrameFootprint / BytesPerWord) - 1]; return static_cast<void**>(frame)
[static_cast<int>(- (FrameFootprint / BytesPerWord) - 1)];
} }
inline void* inline void*
@ -180,25 +182,38 @@ compiledCode(Compiled* code)
return compiledBody(code); return compiledBody(code);
} }
inline unsigned
compiledLineNumberCount(Thread*, Compiled* code)
{
return compiledLineNumberTableLength(code) / sizeof(NativeLineNumber);
}
inline NativeLineNumber* inline NativeLineNumber*
compiledLineNumber(Thread* t, Compiled* code, unsigned index) compiledLineNumber(Thread* t, Compiled* code, unsigned index)
{ {
assert(t, index < compiledLineNumberTableLength(code)); assert(t, index < compiledLineNumberCount(t, code));
return reinterpret_cast<NativeLineNumber*> 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* inline NativeExceptionHandler*
compiledExceptionHandler(Thread* t, Compiled* code, unsigned index) compiledExceptionHandler(Thread* t, Compiled* code, unsigned index)
{ {
assert(t, index < compiledExceptionHandlerTableLength(code)); assert(t, index < compiledExceptionHandlerCount(t, code));
return reinterpret_cast<NativeExceptionHandler*> return reinterpret_cast<NativeExceptionHandler*>
(compiledBody(code) + pad(compiledCodeLength(code)) (compiledBody(code) + pad(compiledCodeLength(code))
+ pad(compiledLineNumberTableLength(code))); + pad(compiledLineNumberTableLength(code))) + index;
} }
inline Compiled* inline Compiled*
makeCompiled(Thread* t, Buffer* code, Buffer* lineNumbers, makeCompiled(Thread* t, object method, Buffer* code, Buffer* lineNumbers,
Buffer* exceptionHandlers) Buffer* exceptionHandlers)
{ {
Compiled* c = static_cast<Compiled*> Compiled* c = static_cast<Compiled*>
@ -207,6 +222,13 @@ makeCompiled(Thread* t, Buffer* code, Buffer* lineNumbers,
+ pad(lineNumbers->length()) + pad(lineNumbers->length())
+ pad(exceptionHandlers->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(); compiledCodeLength(c) = code->length();
compiledLineNumberTableLength(c) = lineNumbers->length(); compiledLineNumberTableLength(c) = lineNumbers->length();
compiledExceptionHandlerTableLength(c) = exceptionHandlers->length(); compiledExceptionHandlerTableLength(c) = exceptionHandlers->length();
@ -237,7 +259,7 @@ findExceptionHandler(Thread* t, void* frame)
object method = frameMethod(frame); object method = frameMethod(frame);
Compiled* code = reinterpret_cast<Compiled*>(methodCompiled(t, method)); 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); NativeExceptionHandler* handler = compiledExceptionHandler(t, code, i);
unsigned offset = addressOffset(t, method, frameAddress(frame)); 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)) { 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; return handler;
} }
} }
@ -266,21 +296,40 @@ void NO_RETURN
unwind(MyThread* t) unwind(MyThread* t)
{ {
for (void* frame = t->frame; frameValid(frame); frame = frameNext(frame)) { 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); void* next = frameNext(frame);
if (not frameValid(next) if (not frameValid(next)
or methodFlags(t, frameMethod(next)) & ACC_NATIVE) or methodFlags(t, frameMethod(next)) & ACC_NATIVE)
{ {
t->frame = next; t->frame = next;
vmJump(frameReturnAddress(frame), frameBase(frame)); vmJump(frameReturnAddress(frame),
} else if ((methodFlags(t, frameMethod(frame)) & ACC_NATIVE) == 0) { *static_cast<void**>(frameBase(frame)),
NativeExceptionHandler* eh = findExceptionHandler(t, frame); static_cast<void**>(frameBase(frame)) + 2);
if (eh) {
Compiled* code = reinterpret_cast<Compiled*>
(methodCompiled(t, frameMethod(frame)));
t->frame = frame;
vmJump(compiledCode(code) + nativeExceptionHandlerIp(eh),
frameBase(frame));
}
} }
} }
abort(t); abort(t);
@ -1563,6 +1612,10 @@ class Compiler: public Assembler {
mov(rax, rsp, 0); mov(rax, rsp, 0);
break; break;
case i2l:
push(0);
break;
case iadd: case iadd:
pop(rax); pop(rax);
pop(rcx); pop(rcx);
@ -1819,9 +1872,7 @@ class Compiler: public Assembler {
if (instruction == ldc) { if (instruction == ldc) {
index = codeBody(t, code, ip++); index = codeBody(t, code, ip++);
} else { } else {
uint8_t index1 = codeBody(t, code, ip++); index = codeReadInt16(t, code, ip);
uint8_t index2 = codeBody(t, code, ip++);
index = (index1 << 8) | index2;
} }
object v = arrayBody(t, codePool(t, code), index - 1); object v = arrayBody(t, codePool(t, code), index - 1);
@ -1843,6 +1894,99 @@ class Compiler: public Assembler {
} }
} break; } 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_: { case new_: {
uint16_t index = codeReadInt16(t, code, ip); uint16_t index = codeReadInt16(t, code, ip);
@ -2038,7 +2182,7 @@ class Compiler: public Assembler {
resolveJumps(); resolveJumps();
buildExceptionHandlerTable(code); buildExceptionHandlerTable(code);
return finish(); return finish(method);
} }
uint32_t machineIpForJavaIp(uint16_t javaIP) { uint32_t machineIpForJavaIp(uint16_t javaIP) {
@ -2135,7 +2279,7 @@ class Compiler: public Assembler {
add(CompiledBody, rax); add(CompiledBody, rax);
jmp(rax); // call compiled code jmp(rax); // call compiled code
return finish(); return finish(0);
} }
Compiled* compileNativeInvoker() { Compiled* compileNativeInvoker() {
@ -2161,7 +2305,7 @@ class Compiler: public Assembler {
pop(rbp); pop(rbp);
ret(); ret();
return finish(); return finish(0);
} }
Compiled* compileCaller() { Compiled* compileCaller() {
@ -2171,11 +2315,11 @@ class Compiler: public Assembler {
jmp(rbx); jmp(rbx);
return finish(); return finish(0);
} }
Compiled* finish() { Compiled* finish(object method) {
return makeCompiled(t, &code, &lineNumbers, &exceptionHandlers); return makeCompiled(t, method, &code, &lineNumbers, &exceptionHandlers);
} }
object makePool() { object makePool() {
@ -2273,7 +2417,8 @@ updateCaller(MyThread* t, object method)
a.call(rax); 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) { if (memcmp(a.code.data, caller, a.code.length()) == 0) {
// it's a direct call - update caller to point to new code // it's a direct call - update caller to point to new code
@ -2587,9 +2732,7 @@ class MyProcessor: public Processor {
case 'J': case 'J':
case 'D': case 'D':
++ s; ++ s;
if (BytesPerWord == 4) { ++ footprint;
++ footprint;
}
break; break;
default: default:
@ -2662,6 +2805,40 @@ class MyProcessor: public Processor {
return addressOffset(t, ::frameMethod(f), ::frameAddress(f)); 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* virtual object*
makeLocalReference(Thread* vmt, object o) makeLocalReference(Thread* vmt, object o)
{ {

View File

@ -1936,22 +1936,17 @@ interpret(Thread* t)
} goto loop; } goto loop;
case jsr: { case jsr: {
uint8_t offset1 = codeBody(t, code, ip++); uint16_t offset = codeReadInt16(t, code, ip);
uint8_t offset2 = codeBody(t, code, ip++);
pushInt(t, ip); pushInt(t, ip);
ip = (ip - 3) + static_cast<int16_t>(((offset1 << 8) | offset2)); ip = (ip - 3) + static_cast<int16_t>(offset);
} goto loop; } goto loop;
case jsr_w: { case jsr_w: {
uint8_t offset1 = codeBody(t, code, ip++); uint32_t offset = codeReadInt32(t, code, ip);
uint8_t offset2 = codeBody(t, code, ip++);
uint8_t offset3 = codeBody(t, code, ip++);
uint8_t offset4 = codeBody(t, code, ip++);
pushInt(t, ip); pushInt(t, ip);
ip = (ip - 3) + static_cast<int32_t> ip = (ip - 3) + static_cast<int32_t>(offset);
((offset1 << 24) | (offset2 << 16) | (offset3 << 8) | offset4);
} goto loop; } goto loop;
case l2i: { case l2i: {
@ -2037,9 +2032,7 @@ interpret(Thread* t)
if (instruction == ldc) { if (instruction == ldc) {
index = codeBody(t, code, ip++); index = codeBody(t, code, ip++);
} else { } else {
uint8_t index1 = codeBody(t, code, ip++); index = codeReadInt16(t, code, ip);
uint8_t index2 = codeBody(t, code, ip++);
index = (index1 << 8) | index2;
} }
object v = arrayBody(t, codePool(t, code), index - 1); object v = arrayBody(t, codePool(t, code), index - 1);
@ -2063,10 +2056,9 @@ interpret(Thread* t)
} goto loop; } goto loop;
case ldc2_w: { case ldc2_w: {
uint8_t index1 = codeBody(t, code, ip++); uint16_t index = codeReadInt16(t, code, ip);
uint8_t index2 = codeBody(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)) { if (objectClass(t, v) == arrayBody(t, t->m->types, Machine::LongType)) {
pushLong(t, longValue(t, v)); pushLong(t, longValue(t, v));
@ -2987,6 +2979,30 @@ class MyProcessor: public Processor {
return ::frameIp(t, frame); 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* virtual object*
makeLocalReference(vm::Thread* vmt, object o) makeLocalReference(vm::Thread* vmt, object o)
{ {

View File

@ -2366,30 +2366,6 @@ findInHierarchy(Thread* t, object class_, object name, object spec,
return o; 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 void
addFinalizer(Thread* t, object target, void (*finalize)(Thread*, object)) 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); (t, className(t, methodClass(t, traceElementMethod(t, e))), 0);
const int8_t* method = &byteArrayBody const int8_t* method = &byteArrayBody
(t, methodName(t, traceElementMethod(t, e)), 0); (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); 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); return cast<object>(array, (2 + index) * BytesPerWord);
} }
int
lineNumber(Thread* t, object method, unsigned ip);
void void
addFinalizer(Thread* t, object target, void (*finalize)(Thread*, object)); addFinalizer(Thread* t, object target, void (*finalize)(Thread*, object));

View File

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

View File

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