JDK-8249603 : C1: assert(has_error == false) failed: register allocation invalid
  • Type: Bug
  • Component: hotspot
  • Sub-Component: compiler
  • Affected Version: 8,11,12,13,14,15,16
  • Priority: P3
  • Status: Resolved
  • Resolution: Fixed
  • Submitted: 2020-07-16
  • Updated: 2023-10-11
  • Resolved: 2020-08-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 16
11.0.10-oracleFixed 16 b11Fixed
Related Reports
Duplicate :  
Relates :  
The attached fuzzer test fails with the following assertion.

To reproduce:
$ java -Xmx1G -Xcomp -Xbatch -XX:CompileOnly=Test Test.java

# A fatal error has been detected by the Java Runtime Environment:
#  Internal Error (/home/christian/jdk/open/src/hotspot/share/c1/c1_LinearScan.cpp:3295), pid=22028, tid=22044
#  assert(has_error == false) failed: register allocation invalid
# JRE version: Java(TM) SE Runtime Environment (16.0) (slowdebug build 16-internal+0-2020-07-13-1111353.christian...)
# Java VM: Java HotSpot(TM) 64-Bit Server VM (slowdebug 16-internal+0-2020-07-13-1111353.christian..., compiled mode, tiered, compressed oops, g1 gc, linux-amd64)
# Problematic frame:
# V  [libjvm.so+0x582a7b]  LinearScan::verify_intervals()+0x5d9
Command Line: -Xmx1G -Xcomp -Xbatch -XX:CompileOnly=Test --add-modules=ALL-DEFAULT jdk.compiler/com.sun.tools.javac.launcher.Main Test.java
Current thread (0x00007f71d0346750):  JavaThread "C1 CompilerThread0" daemon [_thread_in_native, id=22044, stack(0x00007f71c0012000,0x00007f71c0113000)]

Current CompileTask:
C1:  16017  128 % !b  2       Test::mainTest @ 317 (736 bytes)

Stack: [0x00007f71c0012000,0x00007f71c0113000],  sp=0x00007f71c0110bd0,  free space=1018k
Native frames: (J=compiled Java code, A=aot compiled Java code, j=interpreted, Vv=VM code, C=native code)
V  [libjvm.so+0x582a7b]  LinearScan::verify_intervals()+0x5d9
V  [libjvm.so+0x5823c2]  LinearScan::verify()+0x46
V  [libjvm.so+0x581d9e]  LinearScan::do_linear_scan()+0x17a
V  [libjvm.so+0x4f511a]  Compilation::emit_lir()+0x152
V  [libjvm.so+0x4f588c]  Compilation::compile_java_method()+0x21e
V  [libjvm.so+0x4f5bee]  Compilation::compile_method()+0x106
V  [libjvm.so+0x4f63ea]  Compilation::Compilation(AbstractCompiler*, ciEnv*, ciMethod*, int, BufferBlob*, bool, DirectiveSet*)+0x362
V  [libjvm.so+0x4fa13d]  Compiler::compile_method(ciEnv*, ciMethod*, int, bool, DirectiveSet*)+0xd9
V  [libjvm.so+0x6ea926]  CompileBroker::invoke_compiler_on_method(CompileTask*)+0x88e
V  [libjvm.so+0x6e95b3]  CompileBroker::compiler_thread_loop()+0x3df
V  [libjvm.so+0x10a0bdf]  compiler_thread_entry(JavaThread*, Thread*)+0x69
V  [libjvm.so+0x109bd90]  JavaThread::thread_main_inner()+0x146
V  [libjvm.so+0x109bc41]  JavaThread::run()+0x11f
V  [libjvm.so+0x1097eca]  Thread::call_run()+0x180
V  [libjvm.so+0xea6716]  thread_native_entry(Thread*)+0x1e4
Fix Request (11u) This solves the C1 regalloc bug, and keeps codebases in sync (I see 11.0.10-oracle). Patch applies to 11u cleanly after JDK-8220420, passes tier{1,2} tests.

URL: https://hg.openjdk.java.net/jdk/jdk/rev/21ef0858cc7f User: chagedorn Date: 2020-08-12 07:52:27 +0000

http://cr.openjdk.java.net/~chagedorn/8249603/webrev.00/ Register allocation fails in C1 in the testcase because two intervals overlap (they both have the same stack slot assigned). The problem can be traced back to the optimization to assign the same spill slot to non-intersecting intervals in LinearScanWalker::combine_spilled_intervals(). In this method, we look at a split parent interval 'cur' and its register hint interval 'register_hint'. A register hint is present when the interval represents either the source or the target operand of a move operation and the register hint the target or source operand, respectively (the register hint is used to try to assign the same register to the source and target operand such that we can completely remove the move operation). If the register hint is set, then we do some additional checks and make sure that the split parent and the register hint do not intersect. If all checks pass, the split parent 'cur' gets the same spill slot as the register hint [1]. This means that both intervals get the same slot on the stack if they are spilled. The problem now is that we do not consider any split children of the register hint which all share the same spill slot with the register hint (their split parent). In the testcase, the split parent 'cur' does not intersect with the register hint but with one of its split children. As a result, they both get the same spill slot and are later indeed both spilled (i.e. both virtual registers/operands are put to the same stack location at the same time). The fix now additionally checks if the split parent 'cur' does not intersect any split children of the register hint in combine_spilled_intervals(). If there is such an intersection, then we bail out of the optimization. Some standard benchmark testing did not show any regressions. [1] http://hg.openjdk.java.net/jdk/jdk/file/7a3522ab48b3/src/hotspot/share/c1/c1_LinearScan.cpp#l5728