fix stack mapping bug for try blocks containing jsr/ret instructions

In order to calculate the initial stack map of GC roots for an
exception handler, we do a logical "and" of maps across all the
instructions contained in the try block for that handler.  This is
complicated by the presence of jsr/ret instructions, though, because
instructions in a subroutine may have multiple maps associated with
them corresponding to all the paths from which execution might flow to
them.

The bug in this case was that we were using an uninitialized map in
our calculation, resulting in a map with no GC roots at all.  By the
time the map was initialized, the damage had already been done.  The
solution is to treat an uninitialized map as if it has roots at all
positions so that it has no effect on the calculation until it has
been initialized with real data.
This commit is contained in:
Joel Dice 2012-12-12 15:54:15 -07:00
parent f79f320859
commit 663d8da975
2 changed files with 20 additions and 1 deletions

View File

@ -879,7 +879,7 @@ class TraceElement: public TraceHandler {
flags(flags),
watch(false)
{
memset(map, 0, mapSize * BytesPerWord);
memset(map, 0xFF, mapSize * BytesPerWord);
}
virtual void handleTrace(Promise* address, unsigned argumentIndex) {

View File

@ -15,6 +15,23 @@ public class Subroutine {
if (! v) throw new RuntimeException();
}
private static void stackMap(Object x) {
while (true) {
try {
try {
System.gc();
} catch (DummyException e) {
// ignore
} finally {
x.toString();
}
break;
} catch (DummyException e) {
// ignore
}
}
}
private static byte[] makeTestCode(List pool) throws IOException {
ByteArrayOutputStream out = new ByteArrayOutputStream();
Stream.write2(out, 1); // max stack
@ -292,6 +309,8 @@ public class Subroutine {
makeTestClass().getMethod("test", new Class[0]).invoke
(null, new Object[0]);
stackMap(new Object());
}
private static class DummyException extends RuntimeException { }