JDK-6865031 : Application gives bad result (throws bad exception) with compressed oops
  • Type: Bug
  • Component: hotspot
  • Sub-Component: compiler
  • Affected Version: 6u14,6u14p
  • Priority: P3
  • Status: Closed
  • Resolution: Fixed
  • OS: generic,linux,solaris_10
  • CPU: generic,x86
  • Submitted: 2009-07-27
  • Updated: 2011-03-08
  • Resolved: 2011-03-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 6 JDK 7 Other
6u16-revFixed 7Fixed hs14.2Fixed
Related Reports
Duplicate :  
Duplicate :  
Relates :  
Relates :  
Relates :  
Description
FULL PRODUCT VERSION :
java 6 update 14

FULL OS VERSION :
Linux RHEL 5

A DESCRIPTION OF THE PROBLEM :
While testing the -XX:+UseCompressedOops option with 6u14, we found that one of our applications started giving bad results and incorrect runtime behaviour. We have reduced this to a test case. The problem doesn't happen if you run without the -XX:+UseCompressedOops flag but that flag is the major driver for moving to this release.

Note that this is *not* the same problem as http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6851282. We tried retrofitting that fix into the 6u14 source base and building a local libjvm.so. Although it fixes the test case in that bug report, we still get the same intermittent exception.

THE PROBLEM WAS REPRODUCIBLE WITH -Xint FLAG: No

THE PROBLEM WAS REPRODUCIBLE WITH -server FLAG: Yes

STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Compile and run the attached code.

I run it as

java -XX:+UseCompressedOops hello goodbye

EXPECTED VERSUS ACTUAL BEHAVIOR :
It should just return normally.

About one time in five (although it varies so you might need to run it more often to make it happen) it crashes with a stack trace. The stack trace is obviously wrong because it shows that the "this" and the argument are both instances of DoubletonList, but the class being accessed is an instance of SingletonList.

Here is the output:

THROWING RT EXC
concurrent modification of this:class DoubletonList:1414159026; that:class DoubletonList:1569228633; i:1
java.lang.IndexOutOfBoundsException: Index: 1, Size: 1
 23     at SingletonList.get(ToS.java:74)
       WeakPool::       at AbstractMemoryEfficientList.equals(ToS.java:34)
ge      at java.util.AbstractList.equals(AbstractList.java:507)
tTable (9 bytes)
        at MultiSynonymKey.equals(ToS.java:544)
        at WeakPool.eq(ToS.java:154)
        at WeakPool.put(ToS.java:307)
        at ToS.main(ToS.java:607)

As you can see, both "this" and the input arg are instances of DoubletonList but the stack trace shows that SingletonList.get() has been called.
ERROR MESSAGES/STACK TRACES THAT OCCUR :
THROWING RT EXC
concurrent modification of this:class DoubletonList:1414159026; that:class DoubletonList:1569228633; i:1
java.lang.IndexOutOfBoundsException: Index: 1, Size: 1
 23     at SingletonList.get(ToS.java:74)
       WeakPool::       at AbstractMemoryEfficientList.equals(ToS.java:34)
ge      at java.util.AbstractList.equals(AbstractList.java:507)
tTable (9 bytes)
        at MultiSynonymKey.equals(ToS.java:544)
        at WeakPool.eq(ToS.java:154)
        at WeakPool.put(ToS.java:307)
        at ToS.main(ToS.java:607)



REPRODUCIBILITY :
This bug can be reproduced occasionally.

---------- BEGIN SOURCE ----------
Attached seperatly
---------- END SOURCE ----------

CUSTOMER SUBMITTED WORKAROUND :
Turn off -XX:+UseCompressedOops, but we only really are using 6u14 to get compressed oops.

Comments
EVALUATION http://hg.openjdk.java.net/jdk7/hotspot-gc/hotspot/rev/55cb84cd1247
10-08-2009

PUBLIC COMMENTS Problem: The problem at the same place as in 6851282. The new Phi narrow type is incorrect since it is based on the type of one of inputs which could be subtype of the original Phi's type. The Phi is used in CmpP node which gives a wrong result since Phi's type is wrong. It leads to incorrect graph and generated code. Solution: Produce narrow type for new Phi from the original type instead of using a type of Phi's input.
31-07-2009

EVALUATION http://hg.openjdk.java.net/jdk7/hotspot-comp/hotspot/rev/55cb84cd1247
31-07-2009

SUGGESTED FIX src/share/vm/opto/cfgnode.cpp Wed Jul 29 18:27:17 2009 -0700 @@ -1792,15 +1792,12 @@ Node *PhiNode::Ideal(PhaseGVN *phase, bo if (UseCompressedOops && can_reshape && progress == NULL) { bool may_push = true; bool has_decodeN = false; - Node* in_decodeN = NULL; for (uint i=1; i<req(); ++i) {// For all paths in Node *ii = in(i); if (ii->is_DecodeN() && ii->bottom_type() == bottom_type()) { - // Note: in_decodeN is used only to define the type of new phi. - // Find a non dead path otherwise phi type will be wrong. + // Do optimization if a non dead path exist. if (ii->in(1)->bottom_type() != Type::TOP) { has_decodeN = true; - in_decodeN = ii->in(1); } } else if (!ii->is_Phi()) { may_push = false; @@ -1809,7 +1806,9 @@ Node *PhiNode::Ideal(PhaseGVN *phase, bo if (has_decodeN && may_push) { PhaseIterGVN *igvn = phase->is_IterGVN(); - PhiNode *new_phi = PhiNode::make_blank(in(0), in_decodeN); + // Make narrow type for new phi. + const Type* narrow_t = TypeNarrowOop::make(this->bottom_type()->is_ptr()); + PhiNode* new_phi = new (phase->C, r->req()) PhiNode(r, narrow_t); uint orig_cnt = req(); for (uint i=1; i<req(); ++i) {// For all paths in Node *ii = in(i); @@ -1822,7 +1821,7 @@ Node *PhiNode::Ideal(PhaseGVN *phase, bo if (ii->as_Phi() == this) { new_ii = new_phi; } else { - new_ii = new (phase->C, 2) EncodePNode(ii, in_decodeN->bottom_type()); + new_ii = new (phase->C, 2) EncodePNode(ii, narrow_t); igvn->register_new_node_with_optimizer(new_ii); } }
30-07-2009

EVALUATION The problem at the same place as in 6851282. The new Phi narrow type is incorrect for the next case since it is based on the type of one of inputs which could be subtype: 2910 ConN === 0 [[ 2854 ]] #narrowoop: precise klass DoubletonList: 0x00000000008101f8:Constant:exact * 2911 ConN === 0 [[ 2853 ]] #narrowoop: precise klass SingletonList: 0x0000000000810118:Constant:exact * 2854 DecodeN === _ 2910 [[ 2869 ]] #klass AbstractMemoryEfficientList: 0x00000000008546b8 * Klass:klass AbstractMemoryEfficientList: 0x00000000008546b8 * !orig=[1876] !jvms: AbstractMemoryEfficientList::equals @ bci:53 AbstractList::equals @ bci:-1 2853 DecodeN === _ 2911 [[ 2869 ]] #klass AbstractMemoryEfficientList: 0x00000000008546b8 * Klass:klass AbstractMemoryEfficientList: 0x00000000008546b8 * !orig=[1876] !jvms: AbstractMemoryEfficientList::equals @ bci:53 AbstractList::equals @ bci:-1 2869 Phi === 2862 2853 2854 [[ 2858 2856 ]] #klass AbstractMemoryEfficientList: 0x00000000008546b8 * Klass:klass AbstractMemoryEfficientList: 0x00000000008546b8 * !orig=[2852],[1876] !jvms: AbstractMemoryEfficientList::equals @ bci:53 AbstractList::equals @ bci:-1 After the optimization in PhiNode::Ideal we will get new Phi with incorrect type: 2910 ConN === 0 [[ 2854 2916 ]] #narrowoop: precise klass DoubletonList: 0x00000000008101f8:Constant:exact * 2911 ConN === 0 [[ 2853 2916 ]] #narrowoop: precise klass SingletonList: 0x0000000000810118:Constant:exact * 2916 Phi === 2862 2911 2910 [[ 2917 ]] #narrowoop: precise klass DoubletonList: 0x00000000008101f8:Constant:exact * !orig=2869,[2852],[1876] !jvms: AbstractMemoryEfficientList::equals @ bci:53 AbstractList::equals @ bci:-1 The Phi is used in Cmp node and as result of wrong type the result of Cmp is wrong. It leads to incorrect graph and generated code.
30-07-2009