Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-8261730

C2 compilation fails with assert(store->find_edge(load) != -1) failed: missing precedence edge

    XMLWordPrintable

    Details

    • Subcomponent:
    • Resolved In Build:
      b13

      Backports

        Description

        FAILURE:

        The attached program triggers the following assertion failure within C2:

        $ java -Xcomp -XX:CompileOnly=Test::foo Test.java

        # A fatal error has been detected by the Java Runtime Environment:
        #
        # Internal Error (../../src/hotspot/share/opto/gcm.cpp:773), pid=312231, tid=312244
        # assert(store->find_edge(load) != -1) failed: missing precedence edge
         
        ANALYSIS:

        The assertion failure falsely reports a potential anti-dependence violation by the implicit null check transformation (PhaseCFG::implicit_null_check()) that runs opportunistically between global and local scheduling. This transformation tries to reuse memory operations to perform null checks, hoisting the former into null-check blocks if necessary.

        When hoisting stores, implicit_null_check() preserves anti-dependences between the hoisted store and loads in the corresponding null-check and not-null blocks, but disregards possible anti-dependences with loads in the null block. This is safe, as the null block is only executed when the hoisted store has "failed" (attempted to write to the null address). The verification code in PhaseCFG::verify() is not aware of this fact and reports a false anti-dependence violation (missing precedence edge from the load in the null block to the store hoisted to the null-check block).

        The problem is illustrated in the attached CFGs. After global scheduling (before-implicit-null-check.pdf), implicit_null_check() detects a store (17 storeImmIO) in B6 that could potentially perform the null check done by (5 testN_reg) in B4. After checking that neither B4 or B6 contain anti-dependent loads, the transformation replaces (5 testN_reg) with (17 storeImmIO) by hoisting the latter into B4 and adding an additional (46 NullCheck) pseudo-operation (after-implicit-null-check.pdf). Finally, after local scheduling, PhaseCFG::verify() falsely reports that (17 storeImmIO) can overwrite the memory value read by the load operation (34 subI_rReg_mem) in the null block B5, and fails. This overwrite cannot happen, because executing B5 implies (17 storeImmIO)'s failure to store any value.

        WORKAROUND:

        Ignore the assertion failure, e.g. using the JVM option -XX:SuppressErrorAt=/gcm.cpp:773

        TENTATIVE SOLUTION:

        Relax the assertion code in PhaseCFG::verify() by considering the case where the store implements a null check and the load is placed in the corresponding null block.

        ORIGINAL REPORT:

        class a {
          int b;
          long[] c;
          double q;
        }
        class MainClass {
          a d = new a();
          long[] e(a[] f, int g) {
            for (int h = 0; h < 7;) {
              for (int i = 0; i < 4; ++i)
                ;
              d.b = -f[0].b;
              for (int j = 0;;)
                d.b = j;
            }
            return f[0].c;
          }
          double k(int l, int m) {
            a[] n = {new a()};
            e(n, l);
            return n[0].q;
          }
          public static void main(String[] args) {
            MainClass o = new MainClass();
            for (int p = 0;;)
              o.k(p, p);
          }
        }

        # A fatal error has been detected by the Java Runtime Environment:
        #
        # Internal Error (workspace/open/src/hotspot/share/opto/gcm.cpp:773), pid=4056702, tid=4056716
        # assert(store->find_edge(load) != -1) failed: missing precedence edge


        Current CompileTask:
        C2: 731 7 4 MainClass::e (59 bytes)

        Stack: [0x00007f0b302a2000,0x00007f0b303a3000], sp=0x00007f0b3039e000, free space=1008k
        Native frames: (J=compiled Java code, A=aot compiled Java code, j=interpreted, Vv=VM code, C=native code)
        V [libjvm.so+0xd0466d] PhaseCFG::insert_anti_dependences(Block*, Node*, bool)+0x177d
        V [libjvm.so+0x6abc34] PhaseCFG::verify() const+0x664
        V [libjvm.so+0xa03164] Compile::Code_Gen()+0x2c4
        V [libjvm.so+0xa0df8c] Compile::Compile(ciEnv*, ciMethod*, int, bool, bool, bool, bool, DirectiveSet*)+0x19dc
        V [libjvm.so+0x83a09a] C2Compiler::compile_method(ciEnv*, ciMethod*, int, bool, DirectiveSet*)+0x1ea
        V [libjvm.so+0xa1dd81] CompileBroker::invoke_compiler_on_method(CompileTask*)+0xea1
        V [libjvm.so+0xa1ea08] CompileBroker::compiler_thread_loop()+0x5a8
        V [libjvm.so+0x1840926] JavaThread::thread_main_inner()+0x256
        V [libjvm.so+0x1846da0] Thread::call_run()+0x100
        V [libjvm.so+0x1532f56] thread_native_entry(Thread*)+0x116

          Attachments

          1. after-implicit-null-check.pdf
            26 kB
          2. before-implicit-null-check.pdf
            26 kB
          3. hs_err_pid4056702.log
            62 kB
          4. replay_pid4056702.log
            109 kB
          5. Test.java
            0.4 kB

            Issue Links

              Activity

                People

                Assignee:
                rcastanedalo Roberto Castaneda Lozano
                Reporter:
                thartmann Tobias Hartmann
                Votes:
                0 Vote for this issue
                Watchers:
                5 Start watching this issue

                  Dates

                  Created:
                  Updated:
                  Resolved: