JDK-8244407 : JVM crashes after transformation in C2 IdealLoopTree::split_fall_in
  • Type: Bug
  • Component: hotspot
  • Sub-Component: compiler
  • Affected Version: openjdk8u262,11,15
  • Priority: P2
  • Status: Closed
  • Resolution: Fixed
  • OS: generic
  • CPU: generic
  • Submitted: 2020-05-05
  • Updated: 2022-10-03
  • Resolved: 2020-05-12
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
JDK 11 JDK 13 JDK 15 Other
11.0.10-oracleFixed 13.0.4Fixed 15 b23Fixed openjdk8u262Fixed
Related Reports
Relates :  
Description
Reduced fuzz test case:

public class TestBeautifyLoops_2 {

    private class X {
        public int x() {
            return -1;
        }
    }

    private int mI = 0;
    private float mF = 0;
    private boolean mZ = false;
    private X mX = new X();
    private long[] mArray = new long[331];

    private void testMethod() {
        double d = 0;

        for (int i = 0; i < 331; i++) {
            if (mZ) {
                continue;
            }

            try {
                for (int j = mArray.length - 1; j >= 0; j--) {
                    {
                        for (int k = 0; k < 331; k++) {
                            d += ((double) new Double(d));
                            switch (267) {
                                case 256:
                                default: {
                                    mF += (mX.x());
                                    break;
                                }
                            }
                        }
                    }
                }
            } catch (Exception ignore) {
            }
        }
    }

    public static void main(String[] args) {
        TestBeautifyLoops_2 obj = new TestBeautifyLoops_2();
        obj.testMethod();
    }

}

Command line: java -Xcomp -XX:-BackgroundCompilation -XX:CompileCommand=compileonly,TestBeautifyLoops_2::testMethod  TestBeautifyLoops_2

JVM crashes on x86-64 linux:
# To suppress the following error report, specify this argument
# after -XX: or in .hotspotrc:  SuppressErrorAt=/loopnode.cpp:2258
#
# A fatal error has been detected by the Java Runtime Environment:
#
#  Internal Error (/home/yangfei/openjdk-jdk/src/hotspot/share/opto/loopnode.cpp:2258), pid=33823, tid=33837
#  assert(_phase->is_dominator(_head, nlpt->_head)) failed: inner head dominated by outer head
#
# JRE version: OpenJDK Runtime Environment (15.0) (slowdebug build 15-internal+0-adhoc.yangfei.openjdk-jdk)
# Java VM: OpenJDK 64-Bit Server VM (slowdebug 15-internal+0-adhoc.yangfei.openjdk-jdk, compiled mode, sharing, tiered, compressed oops, g1 gc, linux-amd64)
# Problematic frame:
# V  [libjvm.so+0xd24378]  IdealLoopTree::check_safepts(VectorSet&, Node_List&)+0x2f4
#
# Core dump will be written. Default location: Core dumps may be processed with "/usr/share/apport/apport %p %s %c %d %P %E" (or dumping to /home/yangfei/576/core.33823)
#
# An error report file with more information is saved as:
# /home/yangfei/576/hs_err_pid33823.log
#
# Compiler replay data is saved as:
# /home/yangfei/576/replay_pid33823.log

Call trace:
18 ---------------  S U M M A R Y ------------
 19
 20 Command Line: -Xcomp -XX:-BackgroundCompilation -XX:CompileCommand=compileonly,TestBeautifyLoops_2::testMethod TestBeautifyLoops_2
 21
 22 Host: ubuntu18, Intel(R) Xeon(R) CPU E5-2690 v3 @ 2.60GHz, 48 cores, 377G, Ubuntu 18.04.2 LTS
 23 Time: Tue May  5 15:59:46 2020 CST elapsed time: 0.589157 seconds (0d 0h 0m 0s)
 24
 25 ---------------  T H R E A D  ---------------
 26
 27 Current thread (0x00007f9470362000):  JavaThread "C2 CompilerThread0" daemon [_thread_in_native, id=33837, stack(0x00007f93fd03c000,0x00007f93fd13d000)]
 28
 29
 30 Current CompileTask:
 31 C2:    589    3 % !b  4       TestBeautifyLoops_2::testMethod @ 38 (121 bytes)
 32
 33 Stack: [0x00007f93fd03c000,0x00007f93fd13d000],  sp=0x00007f93fd1373f0,  free space=1004k
 34 Native frames: (J=compiled Java code, A=aot compiled Java code, j=interpreted, Vv=VM code, C=native code)
 35 V  [libjvm.so+0xd24378]  IdealLoopTree::check_safepts(VectorSet&, Node_List&)+0x2f4
 36 V  [libjvm.so+0xd240cd]  IdealLoopTree::check_safepts(VectorSet&, Node_List&)+0x49
 37 V  [libjvm.so+0xd26fcd]  PhaseIdealLoop::build_and_optimize(LoopOptsMode)+0x7d9
 38 V  [libjvm.so+0x6f69a7]  PhaseIdealLoop::PhaseIdealLoop(PhaseIterGVN&, LoopOptsMode)+0xb3
 39 V  [libjvm.so+0x6f6aa2]  PhaseIdealLoop::optimize(PhaseIterGVN&, LoopOptsMode)+0x46
 40 V  [libjvm.so+0x6eae1a]  Compile::Optimize()+0x580
 41 V  [libjvm.so+0x6e4745]  Compile::Compile(ciEnv*, ciMethod*, int, bool, bool, bool, DirectiveSet*)+0x10e9
 42 V  [libjvm.so+0x5e2185]  C2Compiler::compile_method(ciEnv*, ciMethod*, int, DirectiveSet*)+0x141
 43 V  [libjvm.so+0x6fee46]  CompileBroker::invoke_compiler_on_method(CompileTask*)+0x7f0
 44 V  [libjvm.so+0x6fdb61]  CompileBroker::compiler_thread_loop()+0x3dd
 45 V  [libjvm.so+0x114c765]  compiler_thread_entry(JavaThread*, Thread*)+0x69
 46 V  [libjvm.so+0x1147985]  JavaThread::thread_main_inner()+0x149
 47 V  [libjvm.so+0x1147833]  JavaThread::run()+0x11f
 48 V  [libjvm.so+0x1143aa0]  Thread::call_run()+0x180
 49 V  [libjvm.so+0xeb4ac0]  thread_native_entry(Thread*)+0x1e4

Comments
Fix request (13u): The original change applies cleanly, tier1 tests pass. The new test fails without the patch and passes with the patch.
11-06-2020

As it doesn't apply cleanly, please post a webrev for review. Should be trivial if there are only minor context differences.
22-05-2020

Fix request (8u) This is a follow-up fix for JDK-8240576. Fix for JDK-8240576 has been backported to jdk8u-dev on 2020-04-28. This bug cannot be reproduced with jdk8u-dev using the provided test case due to difference in C2 graph shape when compared with jdk11u or jdk15. But we saw this bug triggers in one of our production line running a private aarch64 jdk8u release which contains a backport of fix for JDK-8240576. So a backport of the fix to jdk8u-dev would be desirable. Patch doesn't apply cleanly due to conflict on the copyright header update and file path difference, no other conflicts witnessed. Run full jtreg test on x86-64 linux platform.
13-05-2020

Fix request (11u) This is a follow-up fix for JDK-8240576. Fix for JDK-8240576 has been backported to JDK-11 on 2020-03-11. Test show JDK-11 is affected by this bug so a backport of the fix would be desirable. Patch doesn't apply cleanly due to conflict on the copyright header update, no other conflicts witnessed. Tier1-3 tested on x86-64 linux platform. Newly added test case fail without the fix and pass otherwise.
13-05-2020

URL: https://hg.openjdk.java.net/jdk/jdk/rev/c9f5a16d6980 User: fyang Date: 2020-05-12 23:26:52 +0000
12-05-2020

Will post a webrev on public list for review.
05-05-2020

Some initial analysis: With the fix for JDK-8240576, loop tree may be changed by split_fall_in() in IdealLoopTree::beautify_loops. But loop tree is not rebuilt after that. Take the test case for example, irreducible loop tree looks like: 1: Loop: N649/N644 Loop: N649/N644 IRREDUCIBLE <-- this Loop: N649/N797 sfpts={ 683 } With the fix for JDK-8240576,we won't do merge_many_backedges in IdealLoopTree::beautify_loops for this irreducible loop tree. if( _head->req() > 3 && !_irreducible) { // Merge the many backedges into a single backedge but leave // the hottest backedge as separate edge for the following peel. merge_many_backedges( phase ); result = true; } N660 N644 N797 | | | | | | | v | | +---+----+ | +----->+ N649 +<-----+ +--------+ 649 Region === 649 660 797 644 [[ .... ]] !jvms: Test::testMethod @ bci:543 Then we come to the child loop: // Now recursively beautify nested loops if( _child ) result |= _child->beautify_loops( phase ); 2: Loop: N649/N797 Loop: N649/N644 IRREDUCIBLE Loop: N649/N797 sfpts={ 683 } <-- this After spilt_fall_in,N660 and N644 are merged. if( fall_in_cnt > 1 ) // Need a loop landing pad to merge fall-ins split_fall_in( phase, fall_in_cnt ); N660 N644 | + | | | | | +--------+ | +---->+ N946 +<-----+ +----+---+ | N797 | | | | | | | +--------+ | +----> | N649 + <-----+ +--------+ Loop tree is structurally changed into: Loop: N946/N644 IRREDUCIBLE Loop: N649/N797 sfpts={ 683 } But local variable result in IdealLoopTree::beautify_loops hasn't got a chance to be set to true since _head->req() is not bigger than 3 after split_fall_in. And C2 won't rebuild loop tree after IdealLoopTree::beautify_loops, which further leads to the crash. Proposed fix still sets result to true for irreducible loop with multiple backedges: diff -r b9029734989a src/hotspot/share/opto/loopnode.cpp --- a/src/hotspot/share/opto/loopnode.cpp Mon May 04 23:16:44 2020 +0200 +++ b/src/hotspot/share/opto/loopnode.cpp Tue May 05 11:34:25 2020 +0800 @@ -2098,10 +2098,11 @@ // If I am a shared header (multiple backedges), peel off the many // backedges into a private merge point and use the merge point as // the one true backedge. - if (_head->req() > 3 && !_irreducible) { + if (_head->req() > 3) { // Merge the many backedges into a single backedge but leave // the hottest backedge as separate edge for the following peel. - merge_many_backedges( phase ); + if (!_irreducible) + merge_many_backedges( phase ); result = true; }
05-05-2020