-
Bug
-
Resolution: Fixed
-
P3
-
11, 17, 19, 20, 21
-
b03
Issue | Fix Version | Assignee | Priority | Status | Resolution | Resolved In Build |
---|---|---|---|---|---|---|
JDK-8307046 | 20u-cpu | Tobias Hartmann | P3 | Resolved | Fixed | master |
JDK-8305876 | 20.0.2 | Tobias Hartmann | P3 | Resolved | Fixed | b03 |
JDK-8305168 | 17.0.8-oracle | Tobias Hartmann | P3 | Resolved | Fixed | b01 |
JDK-8306826 | 17.0.8 | Goetz Lindenmaier | P3 | Resolved | Fixed | b01 |
Maybe backedge of irreducible loop is missing a SafePoint.
During fuzzing work of
# Internal Error (/home/emanuel/Documents/fork2-jdk/open/src/hotspot/share/opto/loopnode.cpp:3610), pid=159269, tid=159282
# assert(is_member(nlpt)) failed: nested loop
#
# JRE version: Java(TM) SE Runtime Environment (20.0) (slowdebug build 20-internal-2022-10-06-1045569.emanuel...)
# Java VM: Java HotSpot(TM) 64-Bit Server VM (slowdebug 20-internal-2022-10-06-1045569.emanuel..., compiled mode, compressed oops, compressed class ptrs, g1 gc, linux-amd64)
# Problematic frame:
# V [libjvm.so+0xf5cb86] IdealLoopTree::check_safepts(VectorSet&, Node_List&)+0x200
Current CompileTask:
C2: 742 26 b S::test (27 bytes)
Stack: [0x00007f4a65dfe000,0x00007f4a65eff000], sp=0x00007f4a65ef9090, free space=1004k
Native frames: (J=compiled Java code, j=interpreted, Vv=VM code, C=native code)
V [libjvm.so+0xf5cb86] IdealLoopTree::check_safepts(VectorSet&, Node_List&)+0x200 (loopnode.cpp:3610)
V [libjvm.so+0xf5c9f7] IdealLoopTree::check_safepts(VectorSet&, Node_List&)+0x71 (loopnode.cpp:3584)
V [libjvm.so+0xf5c9cf] IdealLoopTree::check_safepts(VectorSet&, Node_List&)+0x49 (loopnode.cpp:3583)
V [libjvm.so+0xf5ff1f] PhaseIdealLoop::build_and_optimize()+0x8bf (loopnode.cpp:4358)
V [libjvm.so+0x8a6343] PhaseIdealLoop::PhaseIdealLoop(PhaseIterGVN&, LoopOptsMode)+0x105 (loopnode.hpp:1087)
V [libjvm.so+0x8a653e] PhaseIdealLoop::optimize(PhaseIterGVN&, LoopOptsMode)+0x46 (loopnode.hpp:1166)
V [libjvm.so+0x899177] Compile::Optimize()+0xa69 (compile.cpp:2365)
V [libjvm.so+0x892104] Compile::Compile(ciEnv*, ciMethod*, int, Options, DirectiveSet*)+0x1404 (compile.cpp:830)
V [libjvm.so+0x780a9b] C2Compiler::compile_method(ciEnv*, ciMethod*, int, bool, DirectiveSet*)+0x179 (c2compiler.cpp:113)
V [libjvm.so+0x8b0df8] CompileBroker::invoke_compiler_on_method(CompileTask*)+0x916 (compileBroker.cpp:2240)
V [libjvm.so+0x8afa61] CompileBroker::compiler_thread_loop()+0x3ed (compileBroker.cpp:1916)
V [libjvm.so+0x8d01aa] CompilerThread::thread_entry(JavaThread*, JavaThread*)+0x72 (compilerThread.cpp:58)
V [libjvm.so+0xc5e0cc] JavaThread::thread_main_inner()+0x144 (javaThread.cpp:699)
V [libjvm.so+0xc5df84] JavaThread::run()+0x182 (javaThread.cpp:684)
V [libjvm.so+0x13306e7] Thread::call_run()+0x195 (thread.cpp:224)
V [libjvm.so+0x10ddf15] thread_native_entry(Thread*)+0x19b (os_linux.cpp:710)
Reproduce it:
java -jar ~/Documents/asmtools-7.0-build/release/lib/asmtools.jar jasm S.jasm
java -Xcomp -XX:CompileCommand=compileonly,S::test -XX:-TieredCompilation -XX:PerMethodTrapLimit=0 -XX:-RenumberLiveNodes S
Note that the flags
-XX:PerMethodTrapLimit=0 -XX:-RenumberLiveNodes
are not required, but simplify the graph by removing traps (no predicates inserted), and the node idx are stable as they are not renumbered during remove useless.
While it is well possible that this is only reproducilbe with irreducible loops, it does not seem to have to do with dead irreducible loops, so it is a separate bug from
Analysis:
(please look at attached png's for node idx)
In IdealLoopTree::check_safepts.
this:
Loop: N37/N57
Loop: N37/N56 sfpts={ 44 }
We start walking from n = tail() up the n = idom(n):
57 IfFalse
55 If
We realize that 55 If belongs to:
Loop: N37/N56
Hence, we jump to head of that loop, so set n:
37 Region
(note: this is the loop head of "this" loop, we should abort the idom walk)
We take n = idom(n), and get:
25 IfTrue
(this node is outside the loop, but the assumption of the code is that we are still inside the loop)
This node's loop (nlpt) is:
Loop: N0/N0 has_sfpt
Loop: N103/N102 sfpts={ 82 70 }
Loop: N37/N57
Loop: N37/N56 sfpts={ 44 }
(this is the root loop)
Now we hit the assert, we check that "nlpt" is a member of "this".
Why does this usually work?
Usually, when we have a nested loop, where the loop is shared, we seem to always have a SafePoint on the backedge of the outer loop. So when we exit the inner loop, we expect to go through a SafePoint before we take the backedge to the loop head.
This seems not to be given, and may well have to do with the fact that we have an irreducible loop here (37 and 38 Region).
What could be solutions?
I have not really understood the issue. But some first thoughts include:
1) Checking when we jump to the loop-head of the inner loop, if this is also the loop head of the outer loop. But this would be accepting that backedges of outer-loops do not have safepoints.
2) Insert the safepoint during parsing.
- backported by
-
JDK-8305168 Special case infinite loops with unmerged backedges in IdealLoopTree::check_safepts
- Resolved
-
JDK-8305876 Special case infinite loops with unmerged backedges in IdealLoopTree::check_safepts
- Resolved
-
JDK-8306826 Special case infinite loops with unmerged backedges in IdealLoopTree::check_safepts
- Resolved
-
JDK-8307046 Special case infinite loops with unmerged backedges in IdealLoopTree::check_safepts
- Resolved
- relates to
-
JDK-8280126 C2: detect and remove dead irreducible loops
- Resolved
-
JDK-8296318 use-def assert: special case undetected loops nested in infinite loops
- Resolved
-
JDK-8299214 Bytecode Fuzzer for irreducible/infinite loops and more
- Open
- links to
-
Commit openjdk/jdk17u-dev/ee63f83e
-
Commit openjdk/jdk20u/a85a0593
-
Commit openjdk/jdk/da38d43f
-
Review openjdk/jdk17u-dev/1287
-
Review openjdk/jdk20u/49
-
Review openjdk/jdk/11706