Endless loops in computation code (1.6.0_22).
Dawid Weiss
dawid.weiss at gmail.com
Sat Mar 26 02:39:58 PDT 2011
> [snip] code was replacing the loop with the result it produced but that's only valid if it already has a zero trip guard. Pretty much all the time it does but in this case it didn't.
Ok, clear -- thanks.
> Note that neither your original program nor the test case have an obvious empty loop. In both cases it results from optimizations on the original loop
These transformations that happen at the graph level are quite
magical. I wonder how long does it take for the a-ha moment when you
grasp what's going on in the jit/ optimizer code -- I looked at it a
few times and it's still magic to me.
Anyway, an interesting social-research problem: isn't it intriguing
that a loop optimizer bug would not manifest itself more frequently
given the number of lines of code in Java out there in the world? I
mean: even if the probability of hitting this is very close to zero,
multiplied by the number of Java code lines should bring it to
attention earlier... unless Java coding patterns are stone-carved in
people's minds without them being aware of this fact (this particular
snippet was rewritten from the C world). This made me think if a
random code fuzzifier executed on two different JVMs would bring more
of such highlights to our attention (by comparing the results, or
stack snapshots?). This has been done for detecting JavaScript/
browser exploits and worked wonders -- can't remember the pointer off
the top of my head, but shouldn't be too hard to find. Interesting.
> It's in the bug report and I made a regression test for it which I included in my fix. http://cr.openjdk.java.net/~never/7024475/raw_files/new/test/compiler/7024475/Test7024475.java
I played with it a little bit wondering what's the minimal set of
clauses that would show this behavior. Randomly fuzzifying the code
here and there I could bring it down to this:
public class Test7024475 {
static int x1;
static void test(int i, int c0, int j, int c1) {
for (;;) {
if (c1 > c0) {
if (c0 > 253) {
throw new InternalError("c0 = " + c0);
}
if (1 < j - i)
x1 = 0;
j = i;
c1--;
} else {
c0--;
if (j <= 0)
break;
c1 = 255;
}
}
}
public static void main(String args[]) {
Test7024475 t = new Test7024475();
for (int n = 0; n < 100000; n++) {
test(2, 85, 1, 134);
}
}
}
Removing anything from here on either changes the logic of the program
or doesn't cause the buggy optimization to happen. More precisely,
removing
if (1 < j - i)
x1 = 0;
still causes InternalError to occur, but it takes a much longer time
(in seconds as opposed to nearly immediately).
Dawid
More information about the hotspot-compiler-dev
mailing list