JDK-8242895 : failed: sanity at src/hotspot/share/opto/escape.cpp:2361
  • Type: Bug
  • Component: hotspot
  • Sub-Component: compiler
  • Affected Version: 15
  • Priority: P2
  • Status: Closed
  • Resolution: Fixed
  • Submitted: 2020-04-16
  • Updated: 2024-10-17
  • Resolved: 2020-07-21
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 15 JDK 16
15 b33Fixed 16Fixed
Related Reports
Relates :  
Description
in runs w/ "-XX:+CreateCoredumpOnCrash -ea -esa -XX:CompileThreshold=100 -XX:+UnlockExperimentalVMOptions -server -Xcomp -XX:-TieredCompilation" api/javax_print/attribute/Size2DSyntax/GetXY.html hits the following assert on windows-x64-debug:

# To suppress the following error report, specify this argument
# after -XX: or in .hotspotrc:  SuppressErrorAt=t:/workspace/open/src/hotspot/share/opto/escape.cpp:2361
#
# A fatal error has been detected by the Java Runtime Environment:
#
#  Internal Error (t:/workspace/open/src/hotspot/share/opto/escape.cpp:2361), pid=9912, tid=936
#  assert(opcode == Op_ConP || opcode == Op_ThreadLocal || opcode == Op_CastX2P || uncast_base->is_DecodeNarrowPtr() || (uncast_base->is_Mem() && (uncast_base->bottom_type()->isa_rawptr() != 0LL)) || (uncast_base->is_Proj() && uncast_base->in(0)->is_Allocate())) failed: sanity
#
# JRE version: Java(TM) SE Runtime Environment (15.0+17) (fastdebug build 15-ea+17-717)
# Java VM: Java HotSpot(TM) 64-Bit Server VM (fastdebug 15-ea+17-717, compiled mode, sharing, compressed oops, g1 gc, windows-amd64)
# Core dump will be written. Default location: T:\\testoutput\\test-support\\jck_runtime_api_javax_print\\hs_err_pid9912.mdmp
#
# An error report file with more information is saved as:
# T:\\testoutput\\test-support\\jck_runtime_api_javax_print\\hs_err_pid9912.log
#
# Compiler replay data is saved as:
# T:\\testoutput\\test-support\\jck_runtime_api_javax_print\\replay_pid9912.log
#
# If you would like to submit a bug report, please visit:
#   https://bugreport.java.com/bugreport/crash.jsp
Comments
URL: https://hg.openjdk.java.net/jdk/jdk15/rev/4bf2a3f7e05a User: jcm Date: 2020-07-21 15:44:30 +0000
21-07-2020

Fix request for JDK 15 approved.
21-07-2020

Fix Request: Enhancement JDK-8231291 integrated in JDK15 caused regression in EA functionality for some cases. Locks can get incorrectly eliminated causing synchronization issues. This happens when alloc init is in different outer loop than alloc node(due to control break from the loop). This creates phi between init and alloc making it difficult for current code to detect init captured stores. Fix looks at outs of raw address(if it i/p is phi)and then stores. As we don't expect any cases with this septup(other than init captured store), checking out shouldn't have any performance issues. (Incorrect scalarization wouldn't happen as it depend on additional use info from Ideal Graph) patch: http://cr.openjdk.java.net/~jcm/8242895/webrev_fix_EA.04/ reviewed-by : Vladimir Kozlov, Tobias Hartmann testing: mach tier1-5
21-07-2020

I will approve it after testing is done and test links are posted here for http://cr.openjdk.java.net/~jcm/8242895/webrev_fix_EA.04/
20-07-2020

Thank you Vladimir
20-07-2020

Running the test confirmed my evaluation. EA exit very early because it can't fine non-escaping candidates: http://hg.openjdk.java.net/jdk/jdk/file/14f465f62984/src/hotspot/share/opto/escape.cpp#l192
17-07-2020

f1 = new IntA(l1); // l1 is escaping Yes, IntA allocation should be global escape because assignment to static ver. There should be merge region after loop where Initializations and allocations should be merging and stored into 'f1'. I will check.
17-07-2020

Hi [~kvn], I have written a test case where it elides lock when actually it shouldn't. test case for elided lock public class TestIdealAllocShape { static IntA f1; static class IntA { IntA f1; IntA(IntA a) { this.f1 = a; } } public static IntA test(int n) { IntA l1 = new IntA(null); for (int i=0; i<2; i++) { try { f1 = new IntA(l1); // l1 is escaping break; } catch (Exception e) { } } synchronized(l1) { //elided sync // some content p(); } return null; } public static void main(String argv[]) { for (int i=0; i<20000; i++) { TestIdealAllocShape.test(i); } } public static void p() { } }
17-07-2020

Thank you Vladimir, Yes I agree. but there is slight overhead for unsafe raw stores, It will check for my special condition(which it definitely fail, but it may take more time) and later mark the store as GlobalEscape. So I thought instead of analyzing to store in this special objects, mark all stores to these raw fields as GlobalEscape, just like unsafe raw store. Normally these special case java objects (return new obj() and uncommon trap after global alloc is GlobalEscape). So store to GlobalEscape should be GlobalEscape. only the other case that is left out is throw new obj() which is caught, which could be ignored (i.e will mark stores to those raw fields too as GlobalEscape, although it needn't be a GlobalEscape case).
09-07-2020

Hmm, we don't have loop info when has_candidates executed. May be what you do in webrev_fix_EA is correct thing.
09-07-2020

I think we should avoid EA for such kind of loops: loop (back branch) is executed only if allocation throws exception. For example, in ConnectionGraph::has_candidates() check if Initialize node is in different loop from Allocation or Initialize node is merged for several allocations. Our EA definitely can't handle such case.
09-07-2020

putting some comments from the code ====================================== // The init has somehow disappeared; be cautious and clear everything. // // This can happen if a node is allocated but an uncommon trap occurs // immediately. In this case, the Initialize gets associated with the // trap, and may be placed in a different (outer) loop, if the Allocate // is in a loop. If (this is rare) the inner loop gets unrolled, then // there can be two Allocates to one Initialize. The answer in all these // edge cases is safety first. It is always safe to clear immediately // within an Allocate, and then (maybe or maybe not) clear some more later. https://github.com/openjdk/jdk/blob/a16994ff7b321af20f49a56e11f458e052133568/src/hotspot/share/opto/macro.cpp#L1769 =============================================== so assuming the case is relatively rare for now.
19-06-2020

Adding a test class Test { static class ExA extends Exception { } static class IntA { public int a; IntA(int o) { a = o; } } public static IntA test1(int o) throws ExA { return new IntA(o); } public static int test() { for (int i=0; i<2; i++) { try { return test1(i).a; } catch (ExA e) { } } return -1; } public static void main(String argv[]) { for (int i = 0; i < 20000; i++) { Test.test(); } } }
10-06-2020

fails after changeset: 57963:51fb05ec531d user: roland date: Fri Dec 20 17:17:37 2019 +0100 summary: 8231291: C2: loop opts before EA should maximally unroll loops
20-05-2020

seems to be reproducible from replay file.
11-05-2020

attached hs_err and replay files.
16-04-2020