8238812: assert(false) failed: bad AD file
Reviewed-by: thartmann, chagedorn, roland
This commit is contained in:
parent
b2a2ddff44
commit
4b5be40ab9
@ -4161,10 +4161,10 @@ Node* Compile::conv_I2X_index(PhaseGVN* phase, Node* idx, const TypeInt* sizetyp
|
||||
}
|
||||
|
||||
// Convert integer value to a narrowed long type dependent on ctrl (for example, a range check)
|
||||
Node* Compile::constrained_convI2L(PhaseGVN* phase, Node* value, const TypeInt* itype, Node* ctrl) {
|
||||
Node* Compile::constrained_convI2L(PhaseGVN* phase, Node* value, const TypeInt* itype, Node* ctrl, bool carry_dependency) {
|
||||
if (ctrl != NULL) {
|
||||
// Express control dependency by a CastII node with a narrow type.
|
||||
value = new CastIINode(value, itype, false, true /* range check dependency */);
|
||||
value = new CastIINode(value, itype, carry_dependency, true /* range check dependency */);
|
||||
// Make the CastII node dependent on the control input to prevent the narrowed ConvI2L
|
||||
// node from floating above the range check during loop optimizations. Otherwise, the
|
||||
// ConvI2L node may be eliminated independently of the range check, causing the data path
|
||||
|
@ -1157,7 +1157,7 @@ class Compile : public Phase {
|
||||
Node* ctrl = NULL);
|
||||
|
||||
// Convert integer value to a narrowed long type dependent on ctrl (for example, a range check)
|
||||
static Node* constrained_convI2L(PhaseGVN* phase, Node* value, const TypeInt* itype, Node* ctrl);
|
||||
static Node* constrained_convI2L(PhaseGVN* phase, Node* value, const TypeInt* itype, Node* ctrl, bool carry_dependency = false);
|
||||
|
||||
// Auxiliary methods for randomized fuzzing/stressing
|
||||
int random();
|
||||
|
@ -863,10 +863,16 @@ bool Parse::create_jump_tables(Node* key_val, SwitchRange* lo, SwitchRange* hi)
|
||||
|
||||
// Clean the 32-bit int into a real 64-bit offset.
|
||||
// Otherwise, the jint value 0 might turn into an offset of 0x0800000000.
|
||||
const TypeInt* ikeytype = TypeInt::make(0, num_cases, Type::WidenMin);
|
||||
// Make I2L conversion control dependent to prevent it from
|
||||
// floating above the range check during loop optimizations.
|
||||
key_val = C->conv_I2X_index(&_gvn, key_val, ikeytype, control());
|
||||
// Do not use a narrow int type here to prevent the data path from dying
|
||||
// while the control path is not removed. This can happen if the type of key_val
|
||||
// is later known to be out of bounds of [0, num_cases] and therefore a narrow cast
|
||||
// would be replaced by TOP while C2 is not able to fold the corresponding range checks.
|
||||
// Set _carry_dependency for the cast to avoid being removed by IGVN.
|
||||
#ifdef _LP64
|
||||
key_val = C->constrained_convI2L(&_gvn, key_val, TypeInt::INT, control(), true /* carry_dependency */);
|
||||
#endif
|
||||
|
||||
// Shift the value by wordsize so we have an index into the table, rather
|
||||
// than a switch value
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* 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
|
||||
@ -23,18 +23,24 @@
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @bug 8229855
|
||||
* @bug 8229855 8238812
|
||||
* @summary Test jump table with key value that gets out of bounds after loop unrolling.
|
||||
* @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;
|
||||
|
||||
public class TestJumpTable {
|
||||
|
||||
public static int test() {
|
||||
public static int test0() {
|
||||
int res = 0;
|
||||
for (int i = 10; i < 50; ++i) {
|
||||
switch (i * 5) {
|
||||
@ -53,9 +59,195 @@ public class TestJumpTable {
|
||||
return res;
|
||||
}
|
||||
|
||||
static int field;
|
||||
|
||||
// Original (slightly simplified) fuzzer generated test
|
||||
public static void 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
|
||||
...
|
||||
}
|
||||
*/
|
||||
public static void 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
|
||||
}
|
||||
*/
|
||||
public static void 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 {
|
||||
...
|
||||
}
|
||||
*/
|
||||
public static void 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 {
|
||||
...
|
||||
}
|
||||
*/
|
||||
public static void 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 {
|
||||
...
|
||||
}
|
||||
*/
|
||||
public static void 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
for (int i = 0; i < 20_000; ++i) {
|
||||
test();
|
||||
for (int i = 0; i < 50_000; ++i) {
|
||||
test0();
|
||||
test1();
|
||||
test2();
|
||||
test3();
|
||||
test4();
|
||||
test5();
|
||||
test6();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user