From 36aa0d67922ed874345123b93ea11476950b5410 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Fri, 8 Apr 2011 18:50:22 -0600 Subject: [PATCH] improve handling of unusual bytecode in JIT compiler Bytecode generated by compilers other than javac or ecj (such as jython's dynamically generated classes) can contain unreachable code and exception handlers which apply to more than one try/catch scope. Previously, the VM's JIT compiler did not handle either of these cases well, hence this commit. --- src/compile.cpp | 251 ++++++++++++++++++++++++++++++------------------ 1 file changed, 159 insertions(+), 92 deletions(-) diff --git a/src/compile.cpp b/src/compile.cpp index 21ce8d231d..8e06e89a01 100644 --- a/src/compile.cpp +++ b/src/compile.cpp @@ -5883,36 +5883,75 @@ logCompile(MyThread* t, const void* code, unsigned size, const char* class_, } } -unsigned -resolveIp(MyThread* t, Context* context, object code, unsigned ip) +int +resolveIpForwards(Context* context, int start, int end) { - if (context->visitTable[ip]) { - return ip; - } else { - // Very rarely, we'll encounter an unreachable goto which is - // referred to by the exception handler table or line number - // table. This can be a problem if we need to determine the - // corresponding machine address for the bytecode instruction - // since we never generated any machine code for it. For now, we - // just follow the goto. The "proper" fix is probably to go ahead - // and generate machine code even though it's unreachable; that - // will protect us against unreachable instructions which aren't - // gotos as well. - switch (codeBody(t, code, ip)) { - case goto_: { - unsigned tmp = ip + 1; - return ip + codeReadInt16(t, code, tmp); - } - - case goto_w: { - unsigned tmp = ip + 1; - return ip + codeReadInt32(t, code, tmp); - } - - default: - return ip; - } + while (start < end and context->visitTable[start] == 0) { + ++ start; } + + if (start >= end) { + return -1; + } else { + return start; + } +} + +int +resolveIpBackwards(Context* context, int start, int end) +{ + while (start >= end and context->visitTable[start] == 0) { + -- start; + } + + if (start < end) { + return -1; + } else { + return start; + } +} + +object +truncateIntArray(Thread* t, object array, unsigned length) +{ + expect(t, intArrayLength(t, array) > length); + + PROTECT(t, array); + + object newArray = makeIntArray(t, length); + memcpy(&intArrayBody(t, newArray, 0), &intArrayBody(t, array, 0), + length * 4); + + return newArray; +} + +object +truncateArray(Thread* t, object array, unsigned length) +{ + expect(t, arrayLength(t, array) > length); + + PROTECT(t, array); + + object newArray = makeArray(t, length); + memcpy(&arrayBody(t, newArray, 0), &arrayBody(t, array, 0), + length * BytesPerWord); + + return newArray; +} + +object +truncateLineNumberTable(Thread* t, object table, unsigned length) +{ + expect(t, lineNumberTableLength(t, table) > length); + + PROTECT(t, table); + + object newTable = makeLineNumberTable(t, length); + memcpy(lineNumberTableBody(t, newTable, 0), + lineNumberTableBody(t, table, 0), + length * sizeof(LineNumber)); + + return newTable; } object @@ -5934,35 +5973,52 @@ translateExceptionHandlerTable(MyThread* t, Context* context, intptr_t start) object newTable = makeArray(t, length + 1); PROTECT(t, newTable); - set(t, newTable, ArrayBody, newIndex); - - for (unsigned i = 0; i < length; ++i) { + unsigned ni = 0; + for (unsigned oi = 0; oi < length; ++ oi) { ExceptionHandler* oldHandler = exceptionHandlerTableBody - (t, oldTable, i); + (t, oldTable, oi); - intArrayBody(t, newIndex, i * 3) - = c->machineIp - (resolveIp - (t, context, methodCode(t, context->method), - exceptionHandlerStart(oldHandler)))->value() - start; + int handlerStart = resolveIpForwards + (context, exceptionHandlerStart(oldHandler), + exceptionHandlerEnd(oldHandler)); - intArrayBody(t, newIndex, (i * 3) + 1) - = c->machineIp(exceptionHandlerEnd(oldHandler))->value() - start; + if (LIKELY(handlerStart >= 0)) { + int handlerEnd = resolveIpBackwards + (context, exceptionHandlerEnd(oldHandler), + exceptionHandlerStart(oldHandler)); - intArrayBody(t, newIndex, (i * 3) + 2) - = c->machineIp(exceptionHandlerIp(oldHandler))->value() - start; + assert(t, handlerEnd >= 0); - object type; - if (exceptionHandlerCatchType(oldHandler)) { - type = resolveClassInPool - (t, context->method, exceptionHandlerCatchType(oldHandler) - 1); - } else { - type = 0; + intArrayBody(t, newIndex, ni * 3) + = c->machineIp(handlerStart)->value() - start; + + intArrayBody(t, newIndex, (ni * 3) + 1) + = c->machineIp(handlerEnd)->value() - start; + + intArrayBody(t, newIndex, (ni * 3) + 2) + = c->machineIp(exceptionHandlerIp(oldHandler))->value() - start; + + object type; + if (exceptionHandlerCatchType(oldHandler)) { + type = resolveClassInPool + (t, context->method, exceptionHandlerCatchType(oldHandler) - 1); + } else { + type = 0; + } + + set(t, newTable, ArrayBody + ((ni + 1) * BytesPerWord), type); + + ++ ni; } - - set(t, newTable, ArrayBody + ((i + 1) * BytesPerWord), type); } + if (UNLIKELY(ni < length)) { + newIndex = truncateIntArray(t, newIndex, ni * 3); + newTable = truncateArray(t, newTable, ni + 1); + } + + set(t, newTable, ArrayBody, newIndex); + return newTable; } else { return 0; @@ -5978,18 +6034,28 @@ translateLineNumberTable(MyThread* t, Context* context, intptr_t start) unsigned length = lineNumberTableLength(t, oldTable); object newTable = makeLineNumberTable(t, length); - for (unsigned i = 0; i < length; ++i) { - LineNumber* oldLine = lineNumberTableBody(t, oldTable, i); - LineNumber* newLine = lineNumberTableBody(t, newTable, i); + unsigned ni = 0; + for (unsigned oi = 0; oi < length; ++oi) { + LineNumber* oldLine = lineNumberTableBody(t, oldTable, oi); + LineNumber* newLine = lineNumberTableBody(t, newTable, ni); - lineNumberIp(newLine) - = context->compiler->machineIp - (resolveIp - (t, context, methodCode(t, context->method), lineNumberIp(oldLine))) - ->value() - - start; + int ip = resolveIpForwards + (context, lineNumberIp(oldLine), oi + 1 < length + ? lineNumberIp(lineNumberTableBody(t, oldTable, oi + 1)) - 1 + : lineNumberIp(oldLine) + 1); - lineNumberLine(newLine) = lineNumberLine(oldLine); + if (LIKELY(ip >= 0)) { + lineNumberIp(newLine) + = context->compiler->machineIp(ip)->value() - start; + + lineNumberLine(newLine) = lineNumberLine(oldLine); + + ++ ni; + } + } + + if (UNLIKELY(ni < length)) { + newTable = truncateLineNumberTable(t, newTable, ni); } return newTable; @@ -6881,55 +6947,56 @@ compile(MyThread* t, Context* context) THREAD_RUNTIME_ARRAY(t, bool, visited, visitCount); memset(RUNTIME_ARRAY_BODY(visited), 0, visitCount * sizeof(bool)); - while (visitCount) { - bool progress UNUSED = false; + bool progress = true; + while (progress) { + progress = false; for (unsigned i = 0; i < exceptionHandlerTableLength(t, eht); ++i) { c->restoreState(state); ExceptionHandler* eh = exceptionHandlerTableBody(t, eht, i); - unsigned start = resolveIp - (t, context, methodCode(t, context->method), - exceptionHandlerStart(eh)); + int start = resolveIpForwards + (context, exceptionHandlerStart(eh), exceptionHandlerEnd(eh)); if ((not RUNTIME_ARRAY_BODY(visited)[i]) + and start >= 0 and context->visitTable[start]) { - -- visitCount; RUNTIME_ARRAY_BODY(visited)[i] = true; progress = true; - THREAD_RUNTIME_ARRAY(t, uint8_t, stackMap, - codeMaxStack(t, methodCode(t, context->method))); - Frame frame2(&frame, RUNTIME_ARRAY_BODY(stackMap)); + if (context->visitTable[exceptionHandlerIp(eh)] == 0) { + THREAD_RUNTIME_ARRAY + (t, uint8_t, stackMap, + codeMaxStack(t, methodCode(t, context->method))); + Frame frame2(&frame, RUNTIME_ARRAY_BODY(stackMap)); - unsigned end = exceptionHandlerEnd(eh); - if (exceptionHandlerIp(eh) >= start - and exceptionHandlerIp(eh) < end) - { - end = exceptionHandlerIp(eh); + unsigned end = exceptionHandlerEnd(eh); + if (exceptionHandlerIp(eh) >= start + and exceptionHandlerIp(eh) < end) + { + end = exceptionHandlerIp(eh); + } + + context->eventLog.append(PushExceptionHandlerEvent); + context->eventLog.append2(start); + context->eventLog.append2(end); + + for (unsigned i = 1; + i < codeMaxStack(t, methodCode(t, context->method)); + ++i) + { + frame2.set(localSize(t, context->method) + i, Frame::Integer); + } + + compile(t, &frame2, exceptionHandlerIp(eh), start); + + context->eventLog.append(PopContextEvent); + + eventIndex = calculateFrameMaps(t, context, 0, eventIndex); } - - context->eventLog.append(PushExceptionHandlerEvent); - context->eventLog.append2(start); - context->eventLog.append2(end); - - for (unsigned i = 1; - i < codeMaxStack(t, methodCode(t, context->method)); - ++i) - { - frame2.set(localSize(t, context->method) + i, Frame::Integer); - } - - compile(t, &frame2, exceptionHandlerIp(eh), start); - - context->eventLog.append(PopContextEvent); - - eventIndex = calculateFrameMaps(t, context, 0, eventIndex); } } - - assert(t, progress); } }