I would really appreciate a mention in the PR: I extracted the JASM file from a class-file, reduced it, and was able to recreate a JAVA file from that. This simplifies the debug job and the triaging (class-file would have been limited to JDK22 and newer).
Affected: 23, 22, 21, 17 (did not reproduce with 11)
Assert in debug. Product: infinite loop as expected, but not sure if there is no wrong result possible.
Only reproduced with JDK17 and newer, but you will have to see why it does not reproduce with JDK11.
Looks like a problem with infinite-loops, see java code and the NeverBranch as evidence that there is no loop exit:
(rr) p x_ctrl->dump_bfs(100,x_ctrl,"#cA")
dist apd dump
---------------------------------------------
7 14 84 IfFalse === 82 [[ 87 91 ]] #0 !jvms: Test::test @ bci:4 (line 12)
6 7 87 Region === 87 84 83 [[ 87 112 92 105 107 130 ]] #reducible !jvms: Test::test @ bci:11 (line 15)
5 7 107 SafePoint === 87 1 108 1 1 112 106 [[ 73 ]] SafePoint !jvms: Test::test @ bci:24 (line 16)
4 7 73 Region === 73 107 72 [[ 73 119 77 118 117 ]] #reducible !jvms: Test::test @ bci:2 (line 12)
3 7 119 NeverBranch === 73 [[ 120 121 ]]
2 7 120 CProj === 119 [[ 82 ]] #0
1 7 82 If === 120 81 [[ 83 84 ]] P=0.500000, C=-1.000000 !jvms: Test::test @ bci:4 (line 12)
0 0 83 IfTrue === 82 [[ 87 ]] #1 !jvms: Test::test @ bci:4 (line 12)
We have had many open bugs with infinite-loops: they are quite rare in the wild but tricky to get right with loop-opts.
JDK-8308749: C2 failed: regular loops only (counted loop inside infinite loop)
JDK-8296389: C2: PhaseCFG::convert_NeverBranch_to_Goto must handle both orders of successors
JDK-8297642: PhaseIdealLoop::only_has_infinite_loops must detect all loops that never lead to termination
JDK-8296318: use-def assert: special case undetected loops nested in infinite loops
JDK-8296412: Special case infinite loops with unmerged backedges in IdealLoopTree::check_safepts
Maybe we should just disable PhaseIdealLoop::try_sink_out_of_loop for infinite loops: they never terminate anyway, and thus their performance is not very important.
/oracle-work/jdk-fork2/build/linux-x64-debug/jdk/bin/java -Xcomp -XX:CompileCommand=compileonly,Test::* -XX:CompileCommand=printcompilation,Test::* -XX:+TraceLoopOpts Test.java
CompileCommand: compileonly Test.* bool compileonly = true
CompileCommand: PrintCompilation Test.* bool PrintCompilation = true
36751 97 b 3 Test::main (4 bytes)
36773 99 b 4 Test::main (4 bytes)
36775 100 % b 4 Test::test @ 2 (27 bytes)
#
# A fatal error has been detected by the Java Runtime Environment:
#
# Internal Error (/oracle-work/jdk-fork2/open/src/hotspot/share/opto/loopopts.cpp:1266), pid=4119505, tid=4119519
# assert(!loop->is_member(get_loop(useblock))) failed: must be outside loop
#
# JRE version: Java(TM) SE Runtime Environment (24.0) (fastdebug build 24-internal-2024-07-04-1039391.emanuel...)
# Java VM: Java HotSpot(TM) 64-Bit Server VM (fastdebug 24-internal-2024-07-04-1039391.emanuel..., compiled mode, tiered, compressed oops, compressed class ptrs, g1 gc, linux-amd64)
# Problematic frame:
# V [libjvm.so+0x12a2718] PhaseIdealLoop::place_outside_loop(Node*, IdealLoopTree*) const+0x348
#
# Core dump will be written. Default location: Core dumps may be processed with "/usr/share/apport/apport -p%p -s%s -c%c -d%d -P%P -u%u -g%g -- %E" (or dumping to /oracle-work/xyz/core.4119505)
#
# An error report file with more information is saved as:
# /oracle-work/xyz/hs_err_pid4119505.log
#
# Compiler replay data is saved as:
# /oracle-work/xyz/replay_pid4119505.log
#
# If you would like to submit a bug report, please visit:
# https://bugreport.java.com/bugreport/crash.jsp
#
Current CompileTask:
C2:36803 100 % b 4 Test::test @ 2 (27 bytes)
Stack: [0x00007f4fc436f000,0x00007f4fc4470000], sp=0x00007f4fc446ad80, free space=1007k
Native frames: (J=compiled Java code, j=interpreted, Vv=VM code, C=native code)
V [libjvm.so+0x12a2718] PhaseIdealLoop::place_outside_loop(Node*, IdealLoopTree*) const+0x348 (loopopts.cpp:1266)
V [libjvm.so+0x12a5bd6] PhaseIdealLoop::try_sink_out_of_loop(Node*)+0x376 (loopopts.cpp:1753)
V [libjvm.so+0x12a6603] PhaseIdealLoop::split_if_with_blocks_post(Node*)+0x83 (loopopts.cpp:1531)
V [libjvm.so+0x12a6ec6] PhaseIdealLoop::split_if_with_blocks(VectorSet&, Node_Stack&)+0x96 (loopopts.cpp:1964)
V [libjvm.so+0x1299519] PhaseIdealLoop::build_and_optimize()+0xee9 (loopnode.cpp:4815)
V [libjvm.so+0x9e4770] PhaseIdealLoop::optimize(PhaseIterGVN&, LoopOptsMode)+0x390 (loopnode.hpp:1117)
V [libjvm.so+0x9df283] Compile::Optimize()+0x4c3 (compile.cpp:2366)
V [libjvm.so+0x9e3326] Compile::Compile(ciEnv*, ciMethod*, int, Options, DirectiveSet*)+0x1b06 (compile.cpp:852)
V [libjvm.so+0x835575] C2Compiler::compile_method(ciEnv*, ciMethod*, int, bool, DirectiveSet*)+0x1d5 (c2compiler.cpp:142)
V [libjvm.so+0x9eef68] CompileBroker::invoke_compiler_on_method(CompileTask*)+0x928 (compileBroker.cpp:2303)
V [libjvm.so+0x9efbf8] CompileBroker::compiler_thread_loop()+0x478 (compileBroker.cpp:1961)
V [libjvm.so+0xe994dc] JavaThread::thread_main_inner()+0xcc (javaThread.cpp:757)
V [libjvm.so+0x17b9076] Thread::call_run()+0xb6 (thread.cpp:225)
V [libjvm.so+0x14a1717] thread_native_entry(Thread*)+0x127 (os_linux.cpp:858)