/* * Copyright (c) 2020, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions.
*/
/** * @test * @key stress randomness * @bug 8229855 8238812 * @summary Test jump table with key value that gets out of bounds after loop unrolling. * @requires vm.compiler2.enabled * * @run main/othervm -XX:CompileCommand=dontinline,compiler.c2.TestJumpTable::test* * -Xbatch -XX:+UnlockDiagnosticVMOptions -XX:-TieredCompilation -XX:-UseSwitchProfiling * compiler.c2.TestJumpTable * @run main/othervm -XX:CompileCommand=dontinline,compiler.c2.TestJumpTable::test* * -Xbatch -XX:-TieredCompilation -XX:-UseOnStackReplacement * compiler.c2.TestJumpTable * @run main/othervm -XX:CompileCommand=dontinline,compiler.c2.TestJumpTable::test* * -Xbatch -XX:+UnlockDiagnosticVMOptions -XX:-TieredCompilation -XX:+StressIGVN * compiler.c2.TestJumpTable
*/
package compiler.c2;
publicclass TestJumpTable {
publicstaticint test0() { int res = 0; for (int i = 10; i < 50; ++i) { switch (i * 5) { case 15: case 25: case 40: case 101: return 42; case 45: case 51: case 60:
res++; break;
}
} return res;
}
staticint field;
// Original (slightly simplified) fuzzer generated test publicstaticvoid test1() { int i4, i5 = 99, i6, i9 = 89; for (i4 = 12; i4 < 365; i4++) { for (i6 = 5; i6 > 1; i6--) { switch ((i6 * 5) + 11) { case 13: case 19: case 26: case 31: case 35: case 41: case 43: case 61: case 71: case 83: case 314:
i9 = i5; break;
}
}
}
}
// This generates the following subgraph: /* // i: -10..4 if ((i+min_jint) u<= max_jint) { <- This is always true but not folded by C2 ... } else { ... CastII(i-5, 0..45) <- Replaced by TOP because i-5 range is -15..-1 but still considered reachable by C2 although it is dead code ... }
*/ publicstaticvoid test2() { for (int i = 5; i > -10; i--) { switch (i) { case 0: case 4: case 10: case 20: case 30: case 40: case 50: case 100:
field = 42; break;
}
}
}
// This generates the following subgraph: /* // i: -20..0 if (i != 0) { // i: -20..-1 if (i < 0) { <- This is always true but not folded by C2 // Fall through } else { ... CastII(i-1, 0..4) <- Replaced by TOP because i-1 range is -21..-1 but still considered reachable by C2 although it is dead code ... } } else { StoreI <- Due to this additional store on, IfNode::has_shared_region returns false and the fold compares optimization does not kick in }
*/ publicstaticvoid test3() { for (int i = 5; i > -20; i -= 5) { switch (i) { case 0: case 10: case 20: case 30: case 40: case 50: case 60: case 100:
field = 42; break;
}
}
}
// This generates the following subgraph: /* // i: -20..0 if (i != 0) { // i: -20..-1 if (i u< 101) { <- This is always false but not folded by C2 because CmpU is not handled CastII(i-1, 0..49) <- Replaced by TOP because i-1 range is -21..-1 but still considered reachable by C2 although it is dead code } else { ... } } else { ... }
*/ publicstaticvoid test4() { int local = 0; for (int i = 5; i > -20; i -= 5) { switch (i) { case 0: case 10: case 20: case 30: case 40: case 50: case 100:
local = 42; break;
}
}
}
// This generates the following subgraph: /* // i: 0..20 if (i != 20) { // i: 0..19 if ((i-20) u< 281) { <- This is always false but not folded by C2 because the two ifs compare different values CastII(i-21, 0..49) <- Replaced by TOP because i-21 range is -21..-1 but still considered reachable by C2 although it is dead code } else { ... } } else { ... }
*/ publicstaticvoid test5() { int local; for (int i = 25; i > 0; i -= 5) { switch (i) { case 20: case 30: case 40: case 50: case 60: case 70: case 300:
local = 42; break;
}
}
}
// This generates the following subgraph: /* // i: 0..20 if ((i+10) != 30) { // i: 0..19 if ((i-20) u< 271) { <- This is always false but not folded by C2 because the two ifs compare different values CastII(i-21, 0..4) <- Replaced by TOP because i-21 range is -21..-1 but still considered reachable by C2 although it is dead code } else { ... } } else { ... }
*/ publicstaticvoid test6() { int local; for (int i = 25; i > 0; i -= 5) { switch (i + 10) { case 30: case 40: case 50: case 60: case 70: case 80: case 300:
local = 42; break;
}
}
}
publicstaticvoid main(String[] args) { for (int i = 0; i < 50_000; ++i) {
test0();
test1();
test2();
test3();
test4();
test5();
test6();
}
}
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.