diff --git a/src/builtin.cpp b/src/builtin.cpp index 8b3bfd1053..1f6542dcf0 100644 --- a/src/builtin.cpp +++ b/src/builtin.cpp @@ -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); diff --git a/src/compile.S b/src/compile.S index d616272dc7..40f6630e06 100644 --- a/src/compile.S +++ b/src/compile.S @@ -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 diff --git a/src/compile.cpp b/src/compile.cpp index bb09450bd3..f44b72cefd 100644 --- a/src/compile.cpp +++ b/src/compile.cpp @@ -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(frame)[(-FrameFootprint / BytesPerWord) - 2]; + return static_cast(frame) + [static_cast(- (FrameFootprint / BytesPerWord) - 2)]; } inline bool @@ -165,7 +166,8 @@ frameMethod(void* frame) inline void* frameAddress(void* frame) { - return static_cast(frame)[(-FrameFootprint / BytesPerWord) - 1]; + return static_cast(frame) + [static_cast(- (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 - (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 (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 @@ -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(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 + (methodCompiled(t, method)); + t->frame = frame; + + void** stack = static_cast(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 - (methodCompiled(t, frameMethod(frame))); - t->frame = frame; - vmJump(compiledCode(code) + nativeExceptionHandlerIp(eh), - frameBase(frame)); - } + vmJump(frameReturnAddress(frame), + *static_cast(frameBase(frame)), + static_cast(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(t->frame)[1] - a.code.length(); + uint8_t* caller = static_cast(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(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) { diff --git a/src/interpret.cpp b/src/interpret.cpp index 98881f3312..97d753c6f1 100644 --- a/src/interpret.cpp +++ b/src/interpret.cpp @@ -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(((offset1 << 8) | offset2)); + ip = (ip - 3) + static_cast(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 - ((offset1 << 24) | (offset2 << 16) | (offset3 << 8) | offset4); + ip = (ip - 3) + static_cast(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) { diff --git a/src/machine.cpp b/src/machine.cpp index 3e8aa96849..217ca8b350 100644 --- a/src/machine.cpp +++ b/src/machine.cpp @@ -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); diff --git a/src/machine.h b/src/machine.h index 7ab2103948..13a3fafe06 100644 --- a/src/machine.h +++ b/src/machine.h @@ -2008,9 +2008,6 @@ objectArrayBody(Thread* t UNUSED, object array, unsigned index) return cast(array, (2 + index) * BytesPerWord); } -int -lineNumber(Thread* t, object method, unsigned ip); - void addFinalizer(Thread* t, object target, void (*finalize)(Thread*, object)); diff --git a/src/processor.h b/src/processor.h index 32ff29d289..7b32e3eff2 100644 --- a/src/processor.h +++ b/src/processor.h @@ -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; diff --git a/src/types.def b/src/types.def index 2da6b7912d..fc0656e807 100644 --- a/src/types.def +++ b/src/types.def @@ -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