We hit the following assert while running an api JCK:
api/java_util/logging/Logger/index.html#LogpLSSSO
...
# To suppress the following error report, specify this argument # after
-XX: or in .hotspotrc: SuppressErrorAt=/chaitin.cpp:1455]
#
# An unexpected error has been detected by HotSpot Virtual Machine:
#
# Internal Error
(/CLO/Components/JAVA_HOTSPOT/Src/src/share/vm/opto/chaitin.cpp, 1455),
pid=29347, tid=12 # # Java VM: Java HotSpot(TM) Server VM (1.5.0.04
jinteg:06.08.06-10:33
IA64 debug mixed mode)
#
# Error: assert(n->outcnt() != 0 || C->top() == n || n->is_Proj(),"No dead
instructions after post-alloc") # An error report file with more
information is saved as hs_err_pid29347.log ...
This is an intermittent issue and it fails once in 200 runs.
Analysis:
We hit this issue while compiling
"sun.security.provider.PolicyParser.parseExtDirs".
Block B326 has a dead node,
B326: # B4 <- N2288 Freq: 1.4808e-05 StartOffset: 0xffffffff,
EndOffset: 0xffffffff
2486 Region === 2486 1631 [[ 2486 2048 1683 ]]
1683 CreateException === 2486 681 [[ 1653 ]]
java/lang/Throwable:NotNullOop: java/lang/Throwable:NotNull *
2731 loadI === _ 683 693 [[ 2729 ]]
2730 loadP === _ 683 684 [[ 2728 2728 2725 ]] char
[int+]:exact*
2729 lShiftI_reg_imm === _ 2731 [[ 2728 ]] #1
2728 addP_reg_reg === _ 2730 2730 2729 [[ 2725 ]]
2725 addP_reg_imm14 === _ 2730 2728 [[ 2723 ]] #12
2723 prefetch_read === _ 681 2725 [[]] <====== dead
instruction
2048 branch === 2486 [[ 3 ]]
This dead node is suppose to be removed in post_allocate_copy_removal
(actually in yank_if_dead() ) method
The first two input arguments to yank_if_dead() method are
old: 2723 prefetch_read === _ 681 2725 [[]]
current_block:
B326: # B4 <- N2288 Freq: 1.4808e-05 StartOffset: 0xffffffff,
EndOffset: 0xffffffff
2486 Region === 2486 1631 [[ 2486 2048 1683 ]]
1683 CreateException === 2486 681 [[ 1653 ]]
java/lang/Throwable:NotNull * Oop:java/lang/Throwable:NotNull *
2731 loadI === _ 683 693 [[ 2729 ]]
2730 loadP === _ 683 684 [[ 2728 2728 2725 ]] char
[int+]:exact*
2729 lShiftI_reg_imm === _ 2731 [[ 2728 ]] #1
2728 addP_reg_reg === _ 2730 2730 2729 [[ 2725 ]]
2725 addP_reg_imm14 === _ 2730 2728 [[ 2723 ]] #12
2723 prefetch_read === _ 681 2725 [[]] <========== dead
instruction
2048 branch === 2486 [[ 3 ]]
old (preferch_read) node has three node inputs.
in(1) = 681 MachProj === 640 [[ 638 2723 1643 1683
2714]] #1
in(2) = 2725 addP_reg_imm14 === _ 2730 2728 [[ 2723 ]] #12
in(3) = 0x0
Even though we have three input nodes to this node, As per "yank_if_dead()"
method source code, it considers only the first input and the rest of the
nodes are not considered.
77 Node *tmp = old->req() > 1 ? old->in(1) : NULL;
78 old->disconnect_inputs(NULL);
After remving "prefetch_read" and disconnecting inputs to this node,
current_block looks like this
B326: # B4 <- N2288 Freq: 1.4808e-05 StartOffset: 0xffffffff,
EndOffset: 0xffffffff
2486 Region === 2486 1631 [[ 2486 2048 1683 ]]
1683 CreateException === 2486 681 [[ 1653 ]]
java/lang/Throwable:NotNull * Oop:java/lang/Throwable:NotNull *
2731 loadI === _ 683 693 [[ 2729 ]]
2730 loadP === _ 683 684 [[ 2728 2728 2725 ]] char
[int+]:exact*
2729 lShiftI_reg_imm === _ 2731 [[ 2728 ]] #1
2728 addP_reg_reg === _ 2730 2730 2729 [[ 2725 ]]
2725 addP_reg_imm14 === _ 2730 2728 [[]] #12
2048 branch === 2486 [[ 3 ]]
in(1) , which is not part of the current_block looks like this
681 MachProj === 640 [[ 638 2714 1643 1683 ]] #1
So we still have a dead node (addP_reg_imm14) in B326.
The same problem can be reproduced while compiling "java.io.File::toURI".
workaround: This issue can be resolved by recursively deleting all dead
input nodes to the current dead node.
Here is the modified source code for yank_if_dead method
> > if (old->outcnt() == 0 && old != C->top()) {
> > Block *oldb = _cfg._bbs[old->_idx];
> > if(oldb) {
> > oldb->find_remove(old);
> > // Count 1 if deleting an instruction from the current block
> > if( oldb == current_block ) blk_adjust++;
> > _cfg._bbs.map(old->_idx,NULL);
> > OptoReg::Name old_reg = lrgs(n2lidx(old)).reg();
> > if( regnd && (*regnd)[old_reg]==old ) { // Instruction is currently
available?
> > value->map(old_reg,NULL); // Yank from value/regnd maps
> > regnd->map(old_reg,NULL); // This register's value is now unknown
> > }
> > // Deletion of a dead node may result in few more dead nodes.
> > // So it is mandatory to check whether all inputs to the current
> > // dead node are valid nodes after deleting the current dead node.
> > Node_List *ins_list;
> > ins_list = new Node_List();
> > for ( int i =0; i< old->req(); i++ )
> > ins_list->push( old->in(i));
> > old->disconnect_inputs(NULL);
> >
> > for ( int j=0; jsize(); j++ ) {
> > Node *tmp = ins_list->pop();
> > if ( tmp)
> > blk_adjust += yank_if_dead ( tmp, current_block, value, regnd);
> > }
> > }
> > }