JDK-8287700 : C2 Crash running eclipse benchmark from Dacapo
  • Type: Bug
  • Component: hotspot
  • Sub-Component: compiler
  • Affected Version: 19
  • Priority: P2
  • Status: Closed
  • Resolution: Fixed
  • OS: linux
  • CPU: x86
  • Submitted: 2022-06-01
  • Updated: 2022-07-11
  • Resolved: 2022-06-08
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 19
19 b26Fixed
Related Reports
Relates :  
Description
To reproduce:
```
java -XX:+UseShenandoahGC -jar dacapo-evaluation-git+309e1fa.jar --scratch-directory dacapo/shenandoah --no-validation --variance 5 --no-pre-iteration-gc --iterations 10 --size small avrora batik eclipse h2 jython luindex lusearch pmd sunflow xalan tomcat
```
The dacapo jar can be downloaded from here: https://sourceforge.net/projects/dacapobench/files/evaluation/dacapo-evaluation-git%2B309e1fa.jar/download

Part way through the execution of the eclipse benchmark, there is a crash:
```
#
# A fatal error has been detected by the Java Runtime Environment:
#
#  Internal Error (/codebuild/output/src896/src/s3/00/src/hotspot/share/opto/escape.cpp:3333), pid=1246, tid=1258
#  assert(tn_type == TypePtr::NULL_PTR || tn_t != __null && !tinst->is_java_subtype_of(tn_t)) failed: unexpected type
#
# JRE version: OpenJDK Runtime Environment (19.0) (fastdebug build 19-root-mainline-x86.ef2009)
# Java VM: OpenJDK 64-Bit Server VM (fastdebug 19-root-mainline-x86.ef2009, mixed mode, sharing, tiered, compressed oops, compressed class ptrs, shenandoah gc, linux-amd64)
# Problematic frame:
# V  [libjvm.so+0xb40a7f]  ConnectionGraph::split_unique_types(GrowableArray<Node*>&, GrowableArray<ArrayCopyNode*>&, GrowableArray<MergeMemNode*>&)+0x139f
#
# Core dump will be written. Default location: /codebuild/output/src050/src/s3/00/jtreg/results/core.1246.%i
#
# If you would like to submit a bug report, please visit:
#   https://bugreport.java.com/bugreport/crash.jsp
#

```
This happens reliably. The crash has occurred on x86_64 machines, but we have not seen it on aarch64. We have seen the crash with G1 and Shenandoah.

Comments
New created compiler/types/TestEACheckCastPP.java test passed in JDK 19 ATR.
11-07-2022

Changeset: 0960ecc4 Author: Roland Westrelin <roland@openjdk.org> Date: 2022-06-08 06:36:52 +0000 URL: https://git.openjdk.java.net/jdk/commit/0960ecc407f8049903e3d183ac75c6a85dcc5b5f
08-06-2022

Hi, Roland, Thank you for fixing this issue. Your PR looks good to me. > "I think it's a dead path because the CheckCastPP casts the result of an allocation to a different, exact type. " You are right, but I still don't understand where it comes from. I studied your testcase TestEACheckCastPP. I think the point of interest is this method. private static void test(boolean flag) { I i = test_helper(); test_helper2(i, flag); } If we call test(false), we get 145 CheckCastPP and 217 EncodeP and their types are both "exact"!!! JavaObject(5) NoEscape(NoEscape) [ 137F [ 47 52 111 145 217 220 ]] 35 Allocate === 5 6 7 8 1 ( 33 31 32 1 1 10 1 1 ) [[ 36 37 38 45 46 47 ]] rawptr:NotNull ( int:>=0, java/lang/Object:NotNull *, bool, top, bool ) TestEACheckCastPP::test_helper @ bci:0 (line 56) TestEACheckCastPP::test @ bci:0 (line 42) !jvms: TestEACheckCastPP::test_helper @ bci:0 (line 56) TestEACheckCastPP::test @ bci:0 (line 42) LocalVar(10) [ 35P [ 52 ]] 47 Proj === 35 [[ 48 52 ]] #5 !jvms: TestEACheckCastPP::test_helper @ bci:0 (line 56) TestEACheckCastPP::test @ bci:0 (line 42) LocalVar(13) [ 47 35P [ 111 ]] 52 CheckCastPP === 49 47 [[ 111 ]] #TestEACheckCastPP$B:NotNull:exact * Oop:TestEACheckCastPP$B:NotNull:exact * !jvms: TestEACheckCastPP::test_helper @ bci:0 (line 56) TestEACheckCastPP::test @ bci:0 (line 42) LocalVar(15) [ 52 35P [ 145 137b ]] 111 CheckCastPP === _ 52 [[ 145 137 137 149 ]] #TestEACheckCastPP$I:NotNull * Interface:TestEACheckCastPP$I:NotNull * !jvms: TestEACheckCastPP::test_helper @ bci:9 (line 57) TestEACheckCastPP::test @ bci:0 (line 42) LocalVar(16) [ 111 35P [ 217 ]] 145 CheckCastPP === 252 111 [[ 217 156 ]] #TestEACheckCastPP$A:NotNull:exact * Oop:TestEACheckCastPP$A:NotNull:exact * !jvms: TestEACheckCastPP::test_helper2 @ bci:5 (line 49) TestEACheckCastPP::test @ bci:6 (line 43) LocalVar(17) [ 145 35P [ 220 ]] 217 EncodeP === _ 145 [[ 219 ]] #narrowoop: TestEACheckCastPP$A:NotNull:exact * !jvms: TestEACheckCastPP::test_helper2 @ bci:19 (line 51) TestEACheckCastPP::test @ bci:6 (line 43) I think that's why you call it "dead path". this code block is never evaluated. I think c2 gets all types from ciTypeFlow. if (flag) { // branch never taken when called from test() A a = (A)i; C c = new C(); c.a = a; } By contrast, if we call test(true) long enough, we will get types without "exact" qualifiers. see 158 and 230. JavaObject(5) NoEscape(NoEscape) [ [ 47 52 111 158 230 233 ]] 35 Allocate === 5 6 7 8 1 ( 33 31 32 1 1 10 1 1 ) [[ 36 37 38 45 46 47 ]] rawptr:NotNull ( int:>=0, java/lang/Object:NotNull *, bool, top, bool ) TestEACheckCastPP::test_helper @ bci:0 (line 57) TestEACheckCastPP::test @ bci:0 (line 43) !jvms: TestEACheckCastPP::test_helper @ bci:0 (line 57) TestEACheckCastPP::test @ bci:0 (line 43) LocalVar(9) [ 35P [ 52 ]] 47 Proj === 35 [[ 48 52 ]] #5 !jvms: TestEACheckCastPP::test_helper @ bci:0 (line 57) TestEACheckCastPP::test @ bci:0 (line 43) LocalVar(11) [ 47 35P [ 111 ]] 52 CheckCastPP === 49 47 [[ 111 ]] #TestEACheckCastPP$B:NotNull:exact * Oop:TestEACheckCastPP$B:NotNull:exact * !jvms: TestEACheckCastPP::test_helper @ bci:0 (line 57) TestEACheckCastPP::test @ bci:0 (line 43) LocalVar(13) [ 52 35P [ 158 ]] 111 CheckCastPP === _ 52 [[ 158 141 132 162 ]] #TestEACheckCastPP$I:NotNull * Interface:TestEACheckCastPP$I:NotNull * !jvms: TestEACheckCastPP::test_helper @ bci:9 (line 58) TestEACheckCastPP::test @ bci:0 (line 43) LocalVar(14) [ 111 35P [ 230 ]] 158 CheckCastPP === 257 111 [[ 230 169 ]] #TestEACheckCastPP$A:NotNull * Oop:TestEACheckCastPP$A:NotNull * !jvms: TestEACheckCastPP::test_helper2 @ bci:5 (line 50) TestEACheckCastPP::test @ bci:6 (line 44) LocalVar(15) [ 158 35P [ 233 ]] 230 EncodeP === _ 158 [[ 232 ]] #narrowoop: TestEACheckCastPP$A:NotNull * !jvms: TestEACheckCastPP::test_helper2 @ bci:19 (line 52) TestEACheckCastPP::test @ bci:6 (line 44) How come we get even more vague types after we evaluate them? I think those types are still from ciTypeFlow, why they don't have "exact" qualifier this time? Instead of calling those code "dead path", should we call it dry path? technically speaking, it's not dead code. we just haven't got chance to execute it.
08-06-2022

A pull request was submitted for review. URL: https://git.openjdk.java.net/jdk/pull/9054 Date: 2022-06-07 07:48:42 +0000
07-06-2022

I think it's a dead path because the CheckCastPP casts the result of an allocation to a different, exact type. This said you're right that the previous didn't detect it as a dead path. I think it's likely harmless that it's not detected as a dead path anyway.
07-06-2022

Sure. sounds good. I am still trying to understand this code snippet. Why do you say it's in dead path? Like C++, Java also supports covariant return type for virtual functions. It seems to me that it creates a UnixFileAttributeViews$Posix object but returns a pointer sun/nio/fs/UnixFileAttributeViews$Basic*. that's typical pattern. class A { virtual A* foo() {return new A; } }; class B : public A { B* foo() {return new B; } }; void main() { B b; A* p= &b; A* p2 = p->foo(); } The previous logic seems to accept it. tinst->klass()->is_subtype_of(tn_t->klass()) is true, it casts tn's type to 'tinst'. In this case, it casts 801's type to UnixFileAttributeViews$Posix*. in the end, c2 manages to eliminated JO(51).
03-06-2022

@~roland, I guess where is wrong. Can I assign this to me? This chunk is suspicious of JDK-8275201. @@ -3310,11 +3314,11 @@ if (tn_type->isa_narrowoop()) { tn_t = tn_type->make_ptr()->isa_oopptr(); } else { tn_t = tn_type->isa_oopptr(); } - if (tn_t != NULL && tinst->klass()->is_subtype_of(tn_t->klass())) { + if (tn_t != NULL && tn_t->maybe_java_subtype_of(tinst)) { if (tn_type->isa_narrowoop()) { tn_type = tinst->make_narrowoop(); } else { tn_type = tinst; } It flips order. In this case, tinst is subclass of tn_t. they are both exact klasses. order matters here. tn_t->maybe_java_subtype_of(tinst) return false.
03-06-2022

[~xliu] I already started working on it. I wrote a simple test case. That line you point to is maybe problematic but given both types are exact and different, we're hitting a dead path and the correct execution is to take the else branch.
03-06-2022

C2 EA has difficulty handling node 801, whose type is sun/nio/fs/UnixFileAttributeViews$Basic:NotNull:exact *. The type of java object(51) is sun/nio/fs/UnixFileAttributeViews$Posix:NotNull:exact *, iiid=1242. UnixFileAttributeViews$Posix is subclass of UnixFileAttributeViews$Base. JavaObject(51) NoEscape(NoEscape) [ 3083F 3544F 3296F 3291F 3088F 2597F [ 1992 1388 796 799 2983 801 ]] 1242 Allocate === 1681 772 1812 125 1 ( 1237 1813 285 1 1 1 1 283 158 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 283 285 ) [[ 2421 1332 656 3082 794 1992 ]] rawptr:NotNull ( int:>=0, java/lang/Object:NotNull *, bool, top, bool ) UnixFileAttributeViews::createPosixView @ bci:0 (line 411) UnixFileSystemProvider::getFileAttributeView @ bci:36 (line 124) LinuxFileSystemProvider::getFileAttributeView @ bci:48 (line 68) UnixFileSystemProvider::readAttributes @ bci:51 (line 148) LinuxFileSystemProvider::readAttributes @ bci:31 (line 99) Files::readAttributes @ bci:7 (line 1851) PosixHandler::fetchFileInfo @ bci:59 (line 53) !jvms: FileInfo::setName @ bci:14 (line 256) PosixHandler::fetchFileInfo @ bci:43 (line 50) LocalVar(243) [ 1242P [ 1388 ]] 1992 Proj === 1242 [[ 2589 1388 ]] #5 !jvms: UnixFileSystemProvider::readAttributes @ bci:57 (line 148) LinuxFileSystemProvider::readAttributes @ bci:31 (line 99) Files::readAttributes @ bci:7 (line 1851) PosixHandler::fetchFileInfo @ bci:59 (line 53) LocalVar(405) [ 1992 1242P [ 796 3083b ]] 1388 CheckCastPP === 1990 1992 [[ 796 1387 3083 3083 ]] #sun/nio/fs/UnixFileAttributeViews$Posix:NotNull:exact * Oop:sun/nio/fs/UnixFileAttributeViews$Posix:NotNull:exact * LocalVar(521) [ 1388 1242P [ 799 ]] 796 CheckCastPP === _ 1388 [[ 799 2588 403 ]] #java/nio/file/attribute/FileAttributeView:NotNull * Interface:java/nio/file/attribute/FileAttributeView:NotNull * !jvms: PosixHandler::fetchFileInfo @ bci:38 (line 50) LocalVar(594) [ 796 1242P [ 2983 801 3544b ]] 799 CheckCastPP === 1390 796 [[ 404 801 3544 3544 2983 ]] #java/nio/file/attribute/BasicFileAttributeView:NotNull * Interface:java/nio/file/attribute/BasicFileAttributeView:NotNull * !jvms: PosixHandler::fetchFileInfo @ bci:38 (line 50) LocalVar(607) [ 799 1242P [ 3296b 3291b ]] 2983 CheckCastPP === 2980 799 [[ 3296 2442 2441 2440 3291 3291 3296 ]] #sun/nio/fs/UnixFileAttributeViews$Posix:NotNull:exact * Oop:sun/nio/fs/UnixFileAttributeViews$Posix:NotNull:exact * !orig=[2545] !jvms: Object::<init> @ bci:0 (line 45) FileTime::<init> @ bci:1 (line 77) FileTime::from @ bci:14 (line 97) UnixFileAttributes::toFileTime @ bci:32 (line 115) UnixFileAttributes::lastModifiedTime @ bci:8 (line 137) PosixHandler::fetchFileInfo @ bci:122 (line 62) LocalVar(608) [ 799 1242P [ 3088b 2597b ]] 801 CheckCastPP === 1392 799 [[ 405 1815 406 1814 1394 2597 2597 3088 3088 ]] #sun/nio/fs/UnixFileAttributeViews$Basic:NotNull:exact * Oop:sun/nio/fs/UnixFileAttributeViews$Basic:NotNull:exact * !orig=[2191] !jvms: PosixHandler::fetchFileInfo @ bci:38 (line 50) for use 801, it comes from eclipse platform. https://github.com/eclipse-platform/eclipse.platform.resources/blob/3a09e2afbd6abfc7d17376c8151506fa769f1f03/bundles/org.eclipse.core.filesystem/src/org/eclipse/core/internal/filesystem/local/nio/PosixHandler.java#L50
02-06-2022

Dacapo jar is a launcher. once it ever executed benchmark 'eclipse', you can find the complete dependencies in scratch directory. in this case, it's 'dacapo/shenandoah' here is the command to replay the compilation. $java -XX:+ReplayCompiles -XX:+ReplayIgnoreInitErrors '-XX:ReplayDataFile=replay_pid1269.log' -cp ./dacapo/shenandoah/eclipse/plugins/org.eclipse.equinox.registry_3.8.100.v20180827-1235.jar:./dacapo/shenandoah/eclipse/plugins/org.eclipse.equinox.app_1.3.600.v20180827-1235.jar:./dacapo/shenandoah/eclipse/plugins/org.eclipse.core.resources_3.13.100.v20180828-0158.jar:./dacapo/shenandoah/eclipse/plugins/org.eclipse.debug.core_3.13.0.v20180821-1744.jar:./dacapo/shenandoah/eclipse/plugins/org.eclipse.jdt.debug_3.12.0.v20180827-1040/jdimodel.jar:./dacapo/shenandoah/eclipse/plugins/org.eclipse.jdt.debug_3.12.0.v20180827-1040/jdi.jar:./dacapo/shenandoah/eclipse/plugins/org.eclipse.core.contenttype_3.7.100.v20180817-1401.jar:./dacapo/shenandoah/eclipse/plugins/org.eclipse.equinox.common_3.10.100.v20180827-1235.jar:./dacapo/shenandoah/eclipse/plugins/org.eclipse.jdt.core_3.15.0.v20180905-0317.jar:./dacapo/shenandoah/eclipse/plugins/org.eclipse.osgi_3.13.100.v20180827-1536.jar:./dacapo/shenandoah/eclipse/plugins/org.eclipse.core.commands_3.9.200.v20180827-1727.jar:./dacapo/shenandoah/eclipse/plugins/org.eclipse.core.variables_3.4.200.v20180821-1744.jar:./dacapo/shenandoah/eclipse/plugins/com.ibm.icu_62.1.0.v20180727-1652.jar:./dacapo/shenandoah/eclipse/plugins/org.dacapo.eclipse_1.0.0.jar:./dacapo/shenandoah/eclipse/plugins/org.eclipse.jdt.launching_3.11.0.v20180827-1040.jar:./dacapo/shenandoah/eclipse/plugins/org.eclipse.text_3.7.0.v20180822-1511.jar:./dacapo/shenandoah/eclipse/plugins/org.eclipse.core.filesystem_1.7.200.v20180828-0158.jar:./dacapo/shenandoah/eclipse/plugins/org.eclipse.equinox.simpleconfigurator_1.3.100.v20180827-1122.jar:./dacapo/shenandoah/eclipse/plugins/org.eclipse.core.expressions_3.6.200.v20180817-1401.jar:./dacapo/shenandoah/eclipse/plugins/org.eclipse.equinox.preferences_3.7.200.v20180827-1235.jar:./dacapo/shenandoah/eclipse/plugins/org.eclipse.core.jobs_3.10.100.v20180817-1215.jar:./dacapo/shenandoah/eclipse/plugins/org.eclipse.core.runtime_3.15.0.v20180817-1401.jar
02-06-2022

ILW = C2 assertion in EA, with Dacapo and recently changed assert, disable EA or disable compilation of affected method = HMM = P2
02-06-2022

The assert was modified by JDK-8275201. Assigning to Roland to look.
02-06-2022

Thank you for hs_err and replay files.
02-06-2022

We already have bug JDK-8287662 filed today
02-06-2022