mirror of
https://github.com/openjdk/jdk.git
synced 2026-02-03 23:18:28 +00:00
472 lines
17 KiB
Java
472 lines
17 KiB
Java
/*
|
|
* Copyright (c) 2025, 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 id=Xbatch
|
|
* @bug 8288981 8350579
|
|
* @summary Test all possible cases in which Assertion Predicates are required such that the graph is not left in a
|
|
* broken state to trigger assertions. Additional tests ensure the correctness of the implementation.
|
|
* All tests additionally -XX:+AbortVMOnCompilationFailure which would catch bad graphs as a result of missing
|
|
or wrong Assertion Predicates where we simply bail out of C2 compilation.
|
|
* @run main/othervm -Xbatch
|
|
* -XX:+UnlockDiagnosticVMOptions -XX:+AbortVMOnCompilationFailure
|
|
* -XX:CompileCommand=compileonly,compiler.predicates.TestAssertionPredicates::*
|
|
* -XX:CompileCommand=dontinline,compiler.predicates.TestAssertionPredicates::*
|
|
* compiler.predicates.TestAssertionPredicates Xbatch
|
|
*/
|
|
|
|
/*
|
|
* @test id=NoTieredCompilation
|
|
* @bug 8288981 8350579
|
|
|
|
* @run main/othervm -Xbatch -XX:-TieredCompilation
|
|
* -XX:+UnlockDiagnosticVMOptions -XX:+AbortVMOnCompilationFailure
|
|
* -XX:CompileCommand=compileonly,compiler.predicates.TestAssertionPredicates::*
|
|
* -XX:CompileCommand=dontinline,compiler.predicates.TestAssertionPredicates::*
|
|
* compiler.predicates.TestAssertionPredicates NoTieredCompilation
|
|
*/
|
|
|
|
/*
|
|
* @test id=Xcomp
|
|
* @bug 8288981 8350579
|
|
* @run main/othervm -Xcomp
|
|
* -XX:+UnlockDiagnosticVMOptions -XX:+AbortVMOnCompilationFailure
|
|
* -XX:CompileCommand=compileonly,compiler.predicates.TestAssertionPredicates::*
|
|
* -XX:CompileCommand=dontinline,compiler.predicates.TestAssertionPredicates::*
|
|
* -XX:CompileCommand=inline,compiler.predicates.TestAssertionPredicates::inline
|
|
* compiler.predicates.TestAssertionPredicates Xcomp
|
|
*/
|
|
|
|
/*
|
|
* @test id=LoopMaxUnroll0
|
|
* @bug 8288981 8350579
|
|
* @requires vm.compiler2.enabled
|
|
* @run main/othervm -Xcomp -XX:LoopMaxUnroll=0
|
|
* -XX:+UnlockDiagnosticVMOptions -XX:+AbortVMOnCompilationFailure
|
|
* -XX:CompileCommand=compileonly,compiler.predicates.TestAssertionPredicates::*
|
|
* -XX:CompileCommand=dontinline,compiler.predicates.TestAssertionPredicates::*
|
|
* compiler.predicates.TestAssertionPredicates LoopMaxUnroll0
|
|
*/
|
|
|
|
/*
|
|
* @test id=StressXcomp
|
|
* @bug 8288981 8350579
|
|
* @requires vm.compiler2.enabled
|
|
* @run main/othervm -Xcomp -XX:+UnlockDiagnosticVMOptions -XX:+StressIGVN -XX:+StressGCM -XX:+AbortVMOnCompilationFailure
|
|
* -XX:CompileCommand=compileonly,compiler.predicates.TestAssertionPredicates::*
|
|
* -XX:CompileCommand=dontinline,compiler.predicates.TestAssertionPredicates::*
|
|
* compiler.predicates.TestAssertionPredicates Stress
|
|
*/
|
|
|
|
/*
|
|
* @test id=StressXbatch
|
|
* @bug 8288981 8350579
|
|
* @requires vm.compiler2.enabled
|
|
* @run main/othervm -Xbatch -XX:+UnlockDiagnosticVMOptions -XX:+StressIGVN -XX:+StressGCM -XX:+AbortVMOnCompilationFailure
|
|
* -XX:CompileCommand=compileonly,compiler.predicates.TestAssertionPredicates::*
|
|
* -XX:CompileCommand=dontinline,compiler.predicates.TestAssertionPredicates::*
|
|
* compiler.predicates.TestAssertionPredicates Stress
|
|
*/
|
|
|
|
/*
|
|
* @test id=NoLoopPredication
|
|
* @bug 8288981 8350579
|
|
* @requires vm.compiler2.enabled
|
|
* @run main/othervm -Xbatch -XX:-UseLoopPredicate
|
|
* -XX:+UnlockDiagnosticVMOptions -XX:+AbortVMOnCompilationFailure
|
|
* -XX:CompileCommand=compileonly,compiler.predicates.TestAssertionPredicates::*
|
|
* -XX:CompileCommand=dontinline,compiler.predicates.TestAssertionPredicates::*
|
|
* compiler.predicates.TestAssertionPredicates NoLoopPredication
|
|
*/
|
|
|
|
/*
|
|
* @test id=NoFlags
|
|
* @bug 8288981 8350579
|
|
* @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+AbortVMOnCompilationFailure
|
|
* compiler.predicates.TestAssertionPredicates NoFlags
|
|
*/
|
|
|
|
package compiler.predicates;
|
|
|
|
public class TestAssertionPredicates {
|
|
static int[] iArrShort = new int[10];
|
|
static int[] iArr = new int[200];
|
|
static int[] iArr2 = new int[200];
|
|
static int[] iArr3 = new int[300];
|
|
static short[] sArr = new short[10];
|
|
|
|
static boolean flag;
|
|
static int iFld = 34;
|
|
static int iFld2, iFld3;
|
|
static float fFld;
|
|
static short five = 5;
|
|
|
|
|
|
public static void main(String[] args) {
|
|
switch (args[0]) {
|
|
case "Xbatch" -> {
|
|
for (int i = 0; i < 10000; i++) {
|
|
flag = !flag;
|
|
testTemplateAssertionPredicateNotRemovedHalt();
|
|
testTemplateAssertionPredicateNotRemovedMalformedGraph();
|
|
test8305428();
|
|
test8305428No2();
|
|
}
|
|
}
|
|
case "NoTieredCompilation" -> {
|
|
for (int i = 0; i < 1000; i++) {
|
|
test8320920();
|
|
test8332501();
|
|
}
|
|
}
|
|
case "LoopMaxUnroll0" -> {
|
|
testDyingRuntimePredicate();
|
|
testDyingNegatedRuntimePredicate();
|
|
}
|
|
case "Xcomp" -> {
|
|
testDyingInitializedAssertionPredicate();
|
|
}
|
|
case "NoLoopPredication", "NoFlags", "Stress" -> {
|
|
for (int i = 0; i < 10000; i++) {
|
|
runAllTests();
|
|
}
|
|
}
|
|
default -> throw new RuntimeException("invalid arg");
|
|
}
|
|
}
|
|
|
|
static void runAllTests() {
|
|
testTemplateAssertionPredicateNotRemovedHalt();
|
|
testTemplateAssertionPredicateNotRemovedMalformedGraph();
|
|
testDyingRuntimePredicate();
|
|
testDyingNegatedRuntimePredicate();
|
|
testDyingInitializedAssertionPredicate();
|
|
test8305428();
|
|
test8305428No2();
|
|
test8320920();
|
|
test8332501();
|
|
}
|
|
|
|
// Corresponds to JDK-8305428.
|
|
// -Xbatch -XX:CompileCommand=compileonly,Test*::*
|
|
public static void testTemplateAssertionPredicateNotRemovedHalt() {
|
|
int one = 34;
|
|
|
|
int limit = 2;
|
|
for (; limit < 4; limit *= 2);
|
|
for (int i = 2; i < limit; i++) {
|
|
one = 1;
|
|
}
|
|
|
|
int i = 80;
|
|
// 1) Found to be a counted loop with a limit between 1 and 34 (C2 only knows after CCP that 'one'
|
|
// is the constant 1).
|
|
// 2b) Two Hoisted Range Check Predicates.
|
|
// Two Template Assertion Predicates but triggering this bug, we only need to focus on one:
|
|
// Init Value: OpaqueLoopInit(0) <u iArrShort.length
|
|
// 4) After CCP, we know that this loop only runs for one iteration. The backedge is never taken
|
|
// and the CountedLoopNode can be folded away during IGVN.
|
|
// The Parse Predicates together with the Template Assertion Predicate from 2b) now end up
|
|
// above the partially peeled inner loop.
|
|
for (int j = 0; j < one; j++) {
|
|
// 3) Apply Partial Peeling which gives us the following loop:
|
|
// for (i = 80; i >= 5; i--) { fFld += 34; }
|
|
// Note that this loop does not have any Parse Predicates above its loop entry.
|
|
// 5) This loop is converted to a counted loop.
|
|
// 6) We pre-main-post this loop and update the Template Assertion Predicate for the main-loop
|
|
// The problem now is, that we use the init value of this loop which is completely
|
|
// unrelated to the init value of the outer loop for which this Tempalte Asseriton Predicate
|
|
// was originally created! We get the following wrong Template Assertion Predicate for the
|
|
// init value:
|
|
// OpaqueLoopInit(79) <u iArrShort.length
|
|
// From that we create a wrong Initialized Assertion Predicate:
|
|
// 79 <u iArrShort.length
|
|
// During runtime, we know the length:
|
|
// 79 <u iArrShort.length = 10
|
|
// And the Initialized Assertion Predidate fails. We execute the corresponding Halt node
|
|
// and the VM crashes.
|
|
while (true) {
|
|
|
|
// Found as loop head in ciTypeFlow, but both paths inside loop -> head not cloned.
|
|
// As a result, this head has the safepoint as backedge instead of the loop exit test
|
|
// and we cannot create a counted loop (yet). We first need to partial peel.
|
|
if (flag) {
|
|
}
|
|
|
|
// Loop exit test.
|
|
if (i < 5) {
|
|
break;
|
|
}
|
|
// <-- Partial Peeling CUT -->
|
|
// Safepoint
|
|
fFld += 34; // Make sure loop not empty.
|
|
i--;
|
|
}
|
|
// 2a) Loop Predication hoists this check out of the loop with two Hoisted Range Check
|
|
// Predicates and two Template Assertion Predicates at 2b).
|
|
iArrShort[j] = 3;
|
|
}
|
|
}
|
|
|
|
// Corresponds to JDK-8305428 but with different manifestation (malformed graph).
|
|
// -Xbatch -XX:CompileCommand=compileonly,Test*::*
|
|
public static void testTemplateAssertionPredicateNotRemovedMalformedGraph() {
|
|
int zero = 34;
|
|
|
|
int limit = 2;
|
|
for (; limit < 4; limit *= 2);
|
|
for (int i = 2; i < limit; i++) {
|
|
zero = 1;
|
|
}
|
|
|
|
int i = 80;
|
|
for (int j = 0; j < zero; j++) {
|
|
while (true) {
|
|
|
|
// Found as loop head in ciTypeFlow, but both paths inside loop -> head not cloned.
|
|
// As a result, this head has the safepoint as backedge instead of the loop exit test
|
|
// and we cannot create a counted loop (yet). We first need to partial peel.
|
|
if (flag) {
|
|
}
|
|
|
|
// Loop exit test.
|
|
if (i < -5) {
|
|
break;
|
|
}
|
|
// <-- Partial Peeling CUT -->
|
|
// Safepoint
|
|
fFld = iArr2[i+5];
|
|
i--;
|
|
}
|
|
iArr[j] = 3;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Some tests catching some issues while adding the new implementation.
|
|
*/
|
|
|
|
// Initialized Assertion Predicate with ConI as bool node is not recognized, and we miss to remove a Template
|
|
// Assertion Predicate from which we later create a wrong Initialized Assertion Predicate (for wrong loop).
|
|
static void testDyingInitializedAssertionPredicate() {
|
|
boolean b = false;
|
|
int i4, i6, i7 = 14, i8, iArr[][] = new int[10][10];
|
|
for (int i = 0; i < iArr.length; i++) {
|
|
inline(iArr[i]);
|
|
}
|
|
for (i4 = 7; i4 < 10; i4++) {
|
|
iArr2[1] += 5;
|
|
}
|
|
for (i6 = 100; i6 > 4; --i6) {
|
|
i8 = 1;
|
|
while (++i8 < 6) {
|
|
sArr[i8] = 3;
|
|
i7 += i8 + i8;
|
|
iArr2[i8] -= 34;
|
|
}
|
|
}
|
|
}
|
|
|
|
public static void inline(int[] a) {
|
|
for (int i = 0; i < a.length; i++) {
|
|
a[i] = 4;
|
|
}
|
|
}
|
|
|
|
static void testDyingRuntimePredicate() {
|
|
int zero = 34;
|
|
int[] iArrLoc = new int[100];
|
|
|
|
int limit = 2;
|
|
int loopInit = -10;
|
|
int four = -10;
|
|
for (; limit < 4; limit *= 2);
|
|
for (int i = 2; i < limit; i++) {
|
|
zero = 0;
|
|
loopInit = 99;
|
|
four = 4;
|
|
}
|
|
|
|
// Template + Hoisted Range Check Predicate for iArr[i]. Hoisted Invariant Check Predicate IC for iArr3[index].
|
|
// After CCP: ConI for IC and uncommon proj already killed -> IGVN will fold this away. But Predicate logic
|
|
// need to still recognize this predicate to find the Template above to kill it. If we don't do it, then it
|
|
// will end up at loop below and peeling will clone the template and create a completely wrong Initialized
|
|
// Assertion Predicate, killing some parts of the graph and leaving us with a broken graph.
|
|
for (int i = loopInit; i < 100; i++) {
|
|
iArr[i] = 34;
|
|
iArrLoc[four] = 34;
|
|
}
|
|
|
|
int i = -10;
|
|
while (true) {
|
|
|
|
// Found as loop head in ciTypeFlow, but both paths inside loop -> head not cloned.
|
|
// As a result, this head has the safepoint as backedge instead of the loop exit test
|
|
// and we cannot create a counted loop (yet). We first need to partial peel.
|
|
if (zero * i == 34) {
|
|
iFld2 = 23;
|
|
} else {
|
|
iFld = 2;
|
|
}
|
|
|
|
// Loop exit test.
|
|
if (i >= -2) {
|
|
break;
|
|
}
|
|
// <-- Partial Peeling CUT -->
|
|
// Safepoint
|
|
if (zero * i + five == 0) {
|
|
return;
|
|
}
|
|
iFld2 = 34;
|
|
i++;
|
|
}
|
|
}
|
|
|
|
static void testDyingNegatedRuntimePredicate() {
|
|
int zero = 34;
|
|
int[] iArrLoc = new int[100];
|
|
|
|
int limit = 2;
|
|
int loopInit = -10;
|
|
int four = -10;
|
|
for (; limit < 4; limit *= 2);
|
|
for (int i = 2; i < limit; i++) {
|
|
zero = 0;
|
|
loopInit = 99;
|
|
four = 4;
|
|
}
|
|
|
|
// Template + Hoisted Range Check Predicate for iArr[i]. Hoisted Invariant Check Predicate IC for iArr3[index].
|
|
// After CCP: ConI for IC and uncommon proj already killed -> IGVN will fold this away. But Predicate logic
|
|
// need to still recognize this predicate to find the Template above to kill it. If we don't do it, then it
|
|
// will end up at loop below and peeling will clone the template and create a completely wrong Initialized
|
|
// Assertion Predicate, killing some parts of the graph and leaving us with a broken graph.
|
|
for (int i = loopInit; i < 100; i++) {
|
|
iArr[i] = 34;
|
|
if (-3 > loopInit) {
|
|
// Negated Hoisted Invariant Check Predicate.
|
|
iArrLoc[101] = 34; // Always out of bounds and will be a range_check trap in the graph.
|
|
}
|
|
}
|
|
|
|
int i = -10;
|
|
while (true) {
|
|
|
|
// Found as loop head in ciTypeFlow, but both paths inside loop -> head not cloned.
|
|
// As a result, this head has the safepoint as backedge instead of the loop exit test
|
|
// and we cannot create a counted loop (yet). We first need to partial peel.
|
|
if (zero * i == 34) {
|
|
iFld2 = 23;
|
|
} else {
|
|
iFld = 2;
|
|
}
|
|
|
|
// Loop exit test.
|
|
if (i >= -2) {
|
|
break;
|
|
}
|
|
// <-- Partial Peeling CUT -->
|
|
// Safepoint
|
|
if (zero * i + five == 0) {
|
|
return;
|
|
}
|
|
iFld2 = 34;
|
|
i++;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Tests collected in JBS and duplicated issues
|
|
*/
|
|
|
|
|
|
// -Xbatch -XX:CompileCommand=compileonly,Test*::*
|
|
static void test8305428() {
|
|
int j = 1;
|
|
do {
|
|
for (int k = 270; k > 1; --k) {
|
|
iFld++;
|
|
}
|
|
|
|
switch (j) {
|
|
case 1:
|
|
switch (92) {
|
|
case 92:
|
|
flag = flag;
|
|
}
|
|
case 2:
|
|
iArr[j] = 3;
|
|
}
|
|
} while (++j < 100);
|
|
}
|
|
|
|
// -Xbatch -XX:CompileCommand=compileonly,Test*::*
|
|
static void test8305428No2() {
|
|
int i = 1;
|
|
do {
|
|
for (int j = 103; j > 1; --j) {
|
|
iArr[i] = iArr[j / 34];
|
|
}
|
|
for (int j = 103; j > 4; j -= 3) {
|
|
switch (i % 9) {
|
|
case 0:
|
|
case 2:
|
|
case 3:
|
|
iArr[i - 1] = 34;
|
|
case 8:
|
|
}
|
|
}
|
|
} while (++i < 99);
|
|
}
|
|
|
|
static void test8320920() {
|
|
int i = 1;
|
|
do {
|
|
for (int j = 83; j > i; j--) {
|
|
iFld = 3;
|
|
}
|
|
for (int j = 5; j < 83; j++) {
|
|
for (int k = i; k < 2; k++)
|
|
;
|
|
}
|
|
iArr3[i - 1] = 34;
|
|
} while (++i < 300);
|
|
}
|
|
|
|
static void test8332501() {
|
|
int i = 1;
|
|
do {
|
|
for (int j = 108; j > 1; j -= 2) {
|
|
fFld += j;
|
|
}
|
|
for (int j = 3; 108 > j; j++) {
|
|
for (int k = 2; k > i; --k) {
|
|
}
|
|
}
|
|
iArr[i] = 34;
|
|
} while (++i < 150);
|
|
}
|
|
}
|