JDK-8060036 : C2: CmpU nodes can end up with wrong type information
  • Type: Bug
  • Component: hotspot
  • Sub-Component: compiler
  • Affected Version: 8u20,8u40,8u45,8u60,9
  • Priority: P3
  • Status: Resolved
  • Resolution: Fixed
  • OS: generic
  • Submitted: 2014-10-09
  • Updated: 2017-10-24
  • Resolved: 2015-05-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 8 JDK 9
8u60Fixed 9 b69Fixed
Related Reports
Duplicate :  
Duplicate :  
Relates :  
Relates :  
Description
Caused by: java.lang.NullPointerException
at javax.swing.text.GlyphView.getBreakSpot(GlyphView.java:799)
at javax.swing.text.GlyphView.getBreakWeight(GlyphView.java:724)
at javax.swing.text.FlowView$LogicalView.getPreferredSpan(FlowView.java:733)
at
javax.swing.text.FlowView.calculateMinorAxisRequirements(FlowView.java:233)
at
javax.swing.text.ParagraphView.calculateMinorAxisRequirements(ParagraphView.ja
va:717)
at javax.swing.text.BoxView.checkRequests(BoxView.java:935)
at javax.swing.text.BoxView.getMinimumSpan(BoxView.java:568)
at javax.swing.text.BoxView.calculateMinorAxisRequirements(BoxView.java:903)
at javax.swing.text.BoxView.checkRequests(BoxView.java:935)
at javax.swing.text.BoxView.setSpanOnAxis(BoxView.java:343)
at javax.swing.text.BoxView.layout(BoxView.java:708)
at javax.swing.text.BoxView.setSize(BoxView.java:397)
at
javax.swing.plaf.basic.BasicTextUI$RootView.setSize(BasicTextUI.java:1722)
at javax.swing.plaf.basic.BasicTextUI.getPreferredSize(BasicTextUI.java:912)
at javax.swing.JComponent.getPreferredSize(JComponent.java:1659)
.... 
Comments
On 8/12/15 4:09 AM, Dawid Weiss wrote: FYI. Found it by bisecting hotspot changes and recompiling in fastdebug. The problem is present consistently before this commit: $ hg log -r 7381 changeset: 7381:03596ae35800 user: aeriksso date: Thu May 21 16:49:11 2015 +0200 summary: 8060036: C2: CmpU nodes can end up with wrong type information I cannot explain why -XX:-TieredCompilation helps here, perhaps it collects different stats and the compilation graph is different (?). In any case, the bug issue [1] has incorrect "Affect" field of "8u60"; should be at least "8x45", perhaps lower than that (and a related bug [2] has it set correctly). Dawid [1] https://bugs.openjdk.java.net/browse/JDK-8060036 [2] https://bugs.openjdk.java.net/browse/JDK-8080156 On Tue, Aug 11, 2015 at 11:27 PM, Dawid Weiss <dawid.weiss@gmail.com> wrote: > We tried to narrow it down. The problem is tied to tiered compilation > somehow because turning it off makes the test pass with flying colors: > > # 1.8.0_45-b14 > PASSES -Xint > PASSES -Xmx4g -Xbatch -XX:CICompilerCount=1 -XX:-TieredCompilation > PASSES -Xmx4g -XX:-TieredCompilation > FAILS -Xmx4g -XX:+TieredCompilation > FAILS -Xmx4g -Xbatch -XX:CICompilerCount=2 -XX:+TieredCompilation > > What's more interesting is that 1.9 and the most recent ea of 1.8 > (u60) also pass, even with tiered compilation turned on: > > # 1.9.0-ea-b71 > PASSES -Xmx4g -Xbatch -XX:CICompilerCount=2 -XX:+TieredCompilation > > # 1.8.0_60-ea-b25 > PASSES [always, regardless of options] > > I can't tell whether it's something masking the original problem or > whether the bug has been fixed in between. I looked at JIRA logs, but > can't find anything specific. If somebody knows what this could be, > I'd appreciate a pointer. > > Dawid > > On Tue, Aug 11, 2015 at 4:25 PM, Dawid Weiss <dawid.weiss@gmail.com> wrote: >> Hello, >> >> We have encountered a transient miscompilation problem (on 1.8u40). We >> get an AIOOB exception from a snippet of code which (provably) cannot >> throw it. The AIOOB is thrown without a stack trace. What's >> interesting is that when we set: >> >> -XX:-OmitStackTraceInFastThrow >> >> we get an NPE exception (which, again, is provably impossible at Java >> code level). >> >> The problem does not reproduce on my machine with i7 3770K (at least >> so far), but does reproduce consistently on i7 2600K (and our >> customer's machine; exact spec unknown). >> >> I will be looking into isolating this issue as it is in our >> proprietary code, but the pattern seems to be as follows: >> >> 1) new instance of A is created, with a new instance of B, which is a >> single-implementation of interface C. >> >> 2) there is a tight loop which calls A (and B) methods. >> >> There is no way for an AIOOB (or NPE) to be present in any of A or B, >> but the stack trace indicates A. >> >> I suspect an OSR miscompilation somewhere, but since I can't reproduce >> it locally it's a bit of a problem to experiment with JVM versions and >> internal flags. >> >> Any hints on what it can be related to (flags to try, etc.) would be >> appreciated. >> >> Dawid
03-09-2015

I will push a regression test for this with JDK-8080156.
22-05-2015

Attached test case I've been using to reproduce this somewhat reliably. I've been running it with: java -XX:+UnlockDiagnosticVMOptions -XX:-OmitStackTraceInFastThrow -XX:CompileCommand=inline,javax/swing/text/GlyphView.getBreakSpot -XX:-UseTypeSpeculation -XX:-OptimizeExpensiveOps -XX:-PartialPeelLoop -XX:LoopMaxUnroll=0 -XX:-UseLoopPredicate -XX:-OptimizeFill -XX:-LoopUnswitching -XX:-UseOnStackReplacement SwingOOS4 When the test fails it throws a NullPointerException from getBreakSpot wrapped in an InvocationtargetException. When it passes the test exits cleanly.
19-05-2015

The problem is with type propagation in C2. A CmpU can use type information from nodes two steps up in the graph, when input 1 is an AddI or SubI node. If the AddI/SubI overflows the CmpU node type computation will set up two type ranges based on the inputs to the AddI/SubI instead. These type ranges will then be compared to input 2 of the CmpU node to see if we can make any meaningful observations on the real type of the CmpU. This means that the type of the AddI/SubI can be bottom, but the CmpU can still use the type of the AddI/SubI inputs to get a more specific type itself. The problem with this is that the types of the AddI/SubI inputs can be updated at a later pass, but since the AddI/SubI is of type bottom the propagation pass will stop there. At that point the CmpU node is never made aware of the new types of the AddI/SubI inputs, and it is left with a type that is based on old type information. When this happens other optimizations using the type information can go very wrong; in this particular case a branch to a range_check trap that normally never happened was optimized to always be taken.
19-05-2015

Output from a failing run, plus a hs_err file produced by calling fatal when the nullpointer is detected in InterpreterRuntime::exception_handler_for_exception.
24-02-2015

I have a theory on why this is happening: 1) Compiled code encounters a range check trap, and begins a deoptimization. 2.a) During deoptimization the compiled code believes that this range check will fail, and assumes the interpreter have to throw an ArrayIndexOutOfBoundsException directly after deopt. 2.b) Since there is no exception handler in the current method the exception will propagate upwards in the call stack. So we don't need any locals for the method(s) we are in now, and they are killed. 3.a) Once in the interpreter, there seems to be no exception, and it keeps running. 3.b) Since all locals were killed (and therefore set to 0 / NULL / Top) we get a nullpointer exception once we need local 10 for an object lookup. I'm not entirely sure where the problem is still, it could be one of: * The compiled code makes the wrong assumption on that the interpreter have to throw an exception. * The interpreter should throw the array index exception, but something goes wrong (either in the deoptimization, or in the interpreter) so that it never happens.
20-02-2015

Has also been seen on windows by external reporters.
16-02-2015

In a compiled getBreakSpot we have WhitespaceBasedBreakIterator.preceding, WhitespaceBasedBreakIterator.adjacent and WhitespaceBasedBreakIterator.checkhit inlined. In checkhit we are getting a deoptimization because of a range_check trap at bci 138 of getBreakSpot. After this deoptimization the locals in getBreakSpot are null, and at bci 145 the getField will fail and throw NullPointerException. The locals are not null in the compiled code, since the getField at bci 129 succeeded. I'm looking into why the interpreter locals are null after deopt now. getBreakSpot bytecode: 127: aload 10 129: getfield #140 // Field javax/swing/text/Segment.offset:I 132: iload 12 134: iload 8 136: isub 137: iadd 138: invokevirtual #141 // Method java/text/BreakIterator.preceding:(I)I 141: iload 8 143: aload 10 145: getfield #140 // Field javax/swing/text/Segment.offset:I
09-02-2015