Mercurial > hg > graal-compiler
comparison src/share/vm/opto/block.cpp @ 14440:41b780b43b74
8029015: PPC64 (part 216): opto: trap based null and range checks
Summary: On PPC64 use tdi instruction that does a compare and raises SIGTRAP for NULL and range checks.
Reviewed-by: kvn
author | goetz |
---|---|
date | Wed, 27 Nov 2013 16:16:21 -0800 |
parents | 044b28168e20 |
children | c3efa8868779 |
comparison
equal
deleted
inserted
replaced
14439:50fdb38839eb | 14440:41b780b43b74 |
---|---|
528 add_block_at(block_no + 1, block); | 528 add_block_at(block_no + 1, block); |
529 } | 529 } |
530 | 530 |
531 // Does this block end in a multiway branch that cannot have the default case | 531 // Does this block end in a multiway branch that cannot have the default case |
532 // flipped for another case? | 532 // flipped for another case? |
533 static bool no_flip_branch( Block *b ) { | 533 static bool no_flip_branch(Block *b) { |
534 int branch_idx = b->number_of_nodes() - b->_num_succs-1; | 534 int branch_idx = b->number_of_nodes() - b->_num_succs-1; |
535 if( branch_idx < 1 ) return false; | 535 if (branch_idx < 1) { |
536 Node *bra = b->get_node(branch_idx); | 536 return false; |
537 if( bra->is_Catch() ) | 537 } |
538 Node *branch = b->get_node(branch_idx); | |
539 if (branch->is_Catch()) { | |
538 return true; | 540 return true; |
539 if( bra->is_Mach() ) { | 541 } |
540 if( bra->is_MachNullCheck() ) | 542 if (branch->is_Mach()) { |
543 if (branch->is_MachNullCheck()) { | |
541 return true; | 544 return true; |
542 int iop = bra->as_Mach()->ideal_Opcode(); | 545 } |
543 if( iop == Op_FastLock || iop == Op_FastUnlock ) | 546 int iop = branch->as_Mach()->ideal_Opcode(); |
547 if (iop == Op_FastLock || iop == Op_FastUnlock) { | |
544 return true; | 548 return true; |
549 } | |
550 // Don't flip if branch has an implicit check. | |
551 if (branch->as_Mach()->is_TrapBasedCheckNode()) { | |
552 return true; | |
553 } | |
545 } | 554 } |
546 return false; | 555 return false; |
547 } | 556 } |
548 | 557 |
549 // Check for NeverBranch at block end. This needs to become a GOTO to the | 558 // Check for NeverBranch at block end. This needs to become a GOTO to the |
698 i--; | 707 i--; |
699 } | 708 } |
700 } // End of for all blocks | 709 } // End of for all blocks |
701 } | 710 } |
702 | 711 |
712 Block *PhaseCFG::fixup_trap_based_check(Node *branch, Block *block, int block_pos, Block *bnext) { | |
713 // Trap based checks must fall through to the successor with | |
714 // PROB_ALWAYS. | |
715 // They should be an If with 2 successors. | |
716 assert(branch->is_MachIf(), "must be If"); | |
717 assert(block->_num_succs == 2, "must have 2 successors"); | |
718 | |
719 // Get the If node and the projection for the first successor. | |
720 MachIfNode *iff = block->get_node(block->number_of_nodes()-3)->as_MachIf(); | |
721 ProjNode *proj0 = block->get_node(block->number_of_nodes()-2)->as_Proj(); | |
722 ProjNode *proj1 = block->get_node(block->number_of_nodes()-1)->as_Proj(); | |
723 ProjNode *projt = (proj0->Opcode() == Op_IfTrue) ? proj0 : proj1; | |
724 ProjNode *projf = (proj0->Opcode() == Op_IfFalse) ? proj0 : proj1; | |
725 | |
726 // Assert that proj0 and succs[0] match up. Similarly for proj1 and succs[1]. | |
727 assert(proj0->raw_out(0) == block->_succs[0]->head(), "Mismatch successor 0"); | |
728 assert(proj1->raw_out(0) == block->_succs[1]->head(), "Mismatch successor 1"); | |
729 | |
730 ProjNode *proj_always; | |
731 ProjNode *proj_never; | |
732 // We must negate the branch if the implicit check doesn't follow | |
733 // the branch's TRUE path. Then, the new TRUE branch target will | |
734 // be the old FALSE branch target. | |
735 if (iff->_prob <= 2*PROB_NEVER) { // There are small rounding errors. | |
736 proj_never = projt; | |
737 proj_always = projf; | |
738 } else { | |
739 // We must negate the branch if the trap doesn't follow the | |
740 // branch's TRUE path. Then, the new TRUE branch target will | |
741 // be the old FALSE branch target. | |
742 proj_never = projf; | |
743 proj_always = projt; | |
744 iff->negate(); | |
745 } | |
746 assert(iff->_prob <= 2*PROB_NEVER, "Trap based checks are expected to trap never!"); | |
747 // Map the successors properly | |
748 block->_succs.map(0, get_block_for_node(proj_never ->raw_out(0))); // The target of the trap. | |
749 block->_succs.map(1, get_block_for_node(proj_always->raw_out(0))); // The fall through target. | |
750 | |
751 // Place the fall through block after this block. | |
752 Block *bs1 = block->non_connector_successor(1); | |
753 if (bs1 != bnext && move_to_next(bs1, block_pos)) { | |
754 bnext = bs1; | |
755 } | |
756 // If the fall through block still is not the next block, insert a goto. | |
757 if (bs1 != bnext) { | |
758 insert_goto_at(block_pos, 1); | |
759 } | |
760 return bnext; | |
761 } | |
762 | |
703 // Fix up the final control flow for basic blocks. | 763 // Fix up the final control flow for basic blocks. |
704 void PhaseCFG::fixup_flow() { | 764 void PhaseCFG::fixup_flow() { |
705 // Fixup final control flow for the blocks. Remove jump-to-next | 765 // Fixup final control flow for the blocks. Remove jump-to-next |
706 // block. If neither arm of an IF follows the conditional branch, we | 766 // block. If neither arm of an IF follows the conditional branch, we |
707 // have to add a second jump after the conditional. We place the | 767 // have to add a second jump after the conditional. We place the |
721 Block* bs0 = block->non_connector_successor(0); | 781 Block* bs0 = block->non_connector_successor(0); |
722 | 782 |
723 // Check for multi-way branches where I cannot negate the test to | 783 // Check for multi-way branches where I cannot negate the test to |
724 // exchange the true and false targets. | 784 // exchange the true and false targets. |
725 if (no_flip_branch(block)) { | 785 if (no_flip_branch(block)) { |
726 // Find fall through case - if must fall into its target | 786 // Find fall through case - if must fall into its target. |
787 // Get the index of the branch's first successor. | |
727 int branch_idx = block->number_of_nodes() - block->_num_succs; | 788 int branch_idx = block->number_of_nodes() - block->_num_succs; |
728 for (uint j2 = 0; j2 < block->_num_succs; j2++) { | 789 |
729 const ProjNode* p = block->get_node(branch_idx + j2)->as_Proj(); | 790 // The branch is 1 before the branch's first successor. |
730 if (p->_con == 0) { | 791 Node *branch = block->get_node(branch_idx-1); |
731 // successor j2 is fall through case | 792 |
732 if (block->non_connector_successor(j2) != bnext) { | 793 // Handle no-flip branches which have implicit checks and which require |
733 // but it is not the next block => insert a goto | 794 // special block ordering and individual semantics of the 'fall through |
734 insert_goto_at(i, j2); | 795 // case'. |
796 if ((TrapBasedNullChecks || TrapBasedRangeChecks) && | |
797 branch->is_Mach() && branch->as_Mach()->is_TrapBasedCheckNode()) { | |
798 bnext = fixup_trap_based_check(branch, block, i, bnext); | |
799 } else { | |
800 // Else, default handling for no-flip branches | |
801 for (uint j2 = 0; j2 < block->_num_succs; j2++) { | |
802 const ProjNode* p = block->get_node(branch_idx + j2)->as_Proj(); | |
803 if (p->_con == 0) { | |
804 // successor j2 is fall through case | |
805 if (block->non_connector_successor(j2) != bnext) { | |
806 // but it is not the next block => insert a goto | |
807 insert_goto_at(i, j2); | |
808 } | |
809 // Put taken branch in slot 0 | |
810 if (j2 == 0 && block->_num_succs == 2) { | |
811 // Flip targets in succs map | |
812 Block *tbs0 = block->_succs[0]; | |
813 Block *tbs1 = block->_succs[1]; | |
814 block->_succs.map(0, tbs1); | |
815 block->_succs.map(1, tbs0); | |
816 } | |
817 break; | |
735 } | 818 } |
736 // Put taken branch in slot 0 | |
737 if (j2 == 0 && block->_num_succs == 2) { | |
738 // Flip targets in succs map | |
739 Block *tbs0 = block->_succs[0]; | |
740 Block *tbs1 = block->_succs[1]; | |
741 block->_succs.map(0, tbs1); | |
742 block->_succs.map(1, tbs0); | |
743 } | |
744 break; | |
745 } | 819 } |
746 } | 820 } |
747 | 821 |
748 // Remove all CatchProjs | 822 // Remove all CatchProjs |
749 for (uint j = 0; j < block->_num_succs; j++) { | 823 for (uint j = 0; j < block->_num_succs; j++) { |