756 // skip through a potential MergeMem chain, linked through Bot 757 mem = mem->in(Compile::AliasIdxBot); 758 NOT_PRODUCT(path.push(mem);) 759 } 760 // now let it fall through, and see if we have a projection 761 if (mem->is_Proj()) { 762 // Should point to a previous known call 763 Node *prev = mem->in(0); 764 NOT_PRODUCT(path.push(prev);) 765 if (!prev->is_Call() || !_control.contains(prev)) { 766 #ifndef PRODUCT 767 if (PrintOptimizeStringConcat) { 768 tty->print("fusion has incorrect memory flow (unknown call) for "); 769 _begin->jvms()->dump_spec(tty); tty->cr(); 770 path.dump(); 771 } 772 #endif 773 return false; 774 } 775 } else { 776 assert(mem->is_Store() || mem->is_LoadStore(), err_msg_res("unexpected node type: %s", mem->Name())); 777 #ifndef PRODUCT 778 if (PrintOptimizeStringConcat) { 779 tty->print("fusion has incorrect memory flow (unexpected source) for "); 780 _begin->jvms()->dump_spec(tty); tty->cr(); 781 path.dump(); 782 } 783 #endif 784 return false; 785 } 786 } else { 787 // For memory that feeds into constructors it's more complicated. 788 // However the advantage is that any side effect that happens between the Allocate/Initialize and 789 // the constructor will have to be control-dependent on Initialize. 790 // So we actually don't have to do anything, since it's going to be caught by the control flow 791 // analysis. 792 #ifdef ASSERT 793 // Do a quick verification of the control pattern between the constructor and the initialize node 794 assert(curr->is_Call(), "constructor should be a call"); 795 // Go up the control starting from the constructor call 796 Node* ctrl = curr->in(0); 797 IfNode* iff = NULL; 798 RegionNode* copy = NULL; 799 800 while (true) { 801 // skip known check patterns 802 if (ctrl->is_Region()) { 803 if (ctrl->as_Region()->is_copy()) { 804 copy = ctrl->as_Region(); 805 ctrl = copy->is_copy(); 806 } else { // a cast 807 assert(ctrl->req() == 3 && 808 ctrl->in(1) != NULL && ctrl->in(1)->is_Proj() && 809 ctrl->in(2) != NULL && ctrl->in(2)->is_Proj() && 810 ctrl->in(1)->in(0) == ctrl->in(2)->in(0) && 811 ctrl->in(1)->in(0) != NULL && ctrl->in(1)->in(0)->is_If(), 812 "must be a simple diamond"); 813 Node* true_proj = ctrl->in(1)->is_IfTrue() ? ctrl->in(1) : ctrl->in(2); 814 for (SimpleDUIterator i(true_proj); i.has_next(); i.next()) { 815 Node* use = i.get(); 816 assert(use == ctrl || use->is_ConstraintCast(), 817 err_msg_res("unexpected user: %s", use->Name())); 818 } 819 820 iff = ctrl->in(1)->in(0)->as_If(); 821 ctrl = iff->in(0); 822 } 823 } else if (ctrl->is_IfTrue()) { // null checks, class checks 824 iff = ctrl->in(0)->as_If(); 825 assert(iff->is_If(), "must be if"); 826 // Verify that the other arm is an uncommon trap 827 Node* otherproj = iff->proj_out(1 - ctrl->as_Proj()->_con); 828 CallStaticJavaNode* call = otherproj->unique_out()->isa_CallStaticJava(); 829 assert(strcmp(call->_name, "uncommon_trap") == 0, "must be uncommond trap"); 830 ctrl = iff->in(0); 831 } else { 832 break; 833 } 834 } 835 836 assert(ctrl->is_Proj(), "must be a projection"); 837 assert(ctrl->in(0)->is_Initialize(), "should be initialize"); 838 for (SimpleDUIterator i(ctrl); i.has_next(); i.next()) { 839 Node* use = i.get(); 840 assert(use == copy || use == iff || use == curr || use->is_CheckCastPP() || use->is_Load(), 841 err_msg_res("unexpected user: %s", use->Name())); 842 } 843 #endif // ASSERT 844 } 845 } 846 } 847 848 #ifndef PRODUCT 849 if (PrintOptimizeStringConcat) { 850 tty->print("fusion has correct memory flow for "); 851 _begin->jvms()->dump_spec(tty); tty->cr(); 852 tty->cr(); 853 } 854 #endif 855 return true; 856 } 857 858 bool StringConcat::validate_control_flow() { 859 // We found all the calls and arguments now lets see if it's 860 // safe to transform the graph as we would expect. 861 | 756 // skip through a potential MergeMem chain, linked through Bot 757 mem = mem->in(Compile::AliasIdxBot); 758 NOT_PRODUCT(path.push(mem);) 759 } 760 // now let it fall through, and see if we have a projection 761 if (mem->is_Proj()) { 762 // Should point to a previous known call 763 Node *prev = mem->in(0); 764 NOT_PRODUCT(path.push(prev);) 765 if (!prev->is_Call() || !_control.contains(prev)) { 766 #ifndef PRODUCT 767 if (PrintOptimizeStringConcat) { 768 tty->print("fusion has incorrect memory flow (unknown call) for "); 769 _begin->jvms()->dump_spec(tty); tty->cr(); 770 path.dump(); 771 } 772 #endif 773 return false; 774 } 775 } else { 776 assert(mem->is_Store() || mem->is_LoadStore(), "unexpected node type: %s", mem->Name()); 777 #ifndef PRODUCT 778 if (PrintOptimizeStringConcat) { 779 tty->print("fusion has incorrect memory flow (unexpected source) for "); 780 _begin->jvms()->dump_spec(tty); tty->cr(); 781 path.dump(); 782 } 783 #endif 784 return false; 785 } 786 } else { 787 // For memory that feeds into constructors it's more complicated. 788 // However the advantage is that any side effect that happens between the Allocate/Initialize and 789 // the constructor will have to be control-dependent on Initialize. 790 // So we actually don't have to do anything, since it's going to be caught by the control flow 791 // analysis. 792 #ifdef ASSERT 793 // Do a quick verification of the control pattern between the constructor and the initialize node 794 assert(curr->is_Call(), "constructor should be a call"); 795 // Go up the control starting from the constructor call 796 Node* ctrl = curr->in(0); 797 IfNode* iff = NULL; 798 RegionNode* copy = NULL; 799 800 while (true) { 801 // skip known check patterns 802 if (ctrl->is_Region()) { 803 if (ctrl->as_Region()->is_copy()) { 804 copy = ctrl->as_Region(); 805 ctrl = copy->is_copy(); 806 } else { // a cast 807 assert(ctrl->req() == 3 && 808 ctrl->in(1) != NULL && ctrl->in(1)->is_Proj() && 809 ctrl->in(2) != NULL && ctrl->in(2)->is_Proj() && 810 ctrl->in(1)->in(0) == ctrl->in(2)->in(0) && 811 ctrl->in(1)->in(0) != NULL && ctrl->in(1)->in(0)->is_If(), 812 "must be a simple diamond"); 813 Node* true_proj = ctrl->in(1)->is_IfTrue() ? ctrl->in(1) : ctrl->in(2); 814 for (SimpleDUIterator i(true_proj); i.has_next(); i.next()) { 815 Node* use = i.get(); 816 assert(use == ctrl || use->is_ConstraintCast(), 817 "unexpected user: %s", use->Name()); 818 } 819 820 iff = ctrl->in(1)->in(0)->as_If(); 821 ctrl = iff->in(0); 822 } 823 } else if (ctrl->is_IfTrue()) { // null checks, class checks 824 iff = ctrl->in(0)->as_If(); 825 assert(iff->is_If(), "must be if"); 826 // Verify that the other arm is an uncommon trap 827 Node* otherproj = iff->proj_out(1 - ctrl->as_Proj()->_con); 828 CallStaticJavaNode* call = otherproj->unique_out()->isa_CallStaticJava(); 829 assert(strcmp(call->_name, "uncommon_trap") == 0, "must be uncommond trap"); 830 ctrl = iff->in(0); 831 } else { 832 break; 833 } 834 } 835 836 assert(ctrl->is_Proj(), "must be a projection"); 837 assert(ctrl->in(0)->is_Initialize(), "should be initialize"); 838 for (SimpleDUIterator i(ctrl); i.has_next(); i.next()) { 839 Node* use = i.get(); 840 assert(use == copy || use == iff || use == curr || use->is_CheckCastPP() || use->is_Load(), 841 "unexpected user: %s", use->Name()); 842 } 843 #endif // ASSERT 844 } 845 } 846 } 847 848 #ifndef PRODUCT 849 if (PrintOptimizeStringConcat) { 850 tty->print("fusion has correct memory flow for "); 851 _begin->jvms()->dump_spec(tty); tty->cr(); 852 tty->cr(); 853 } 854 #endif 855 return true; 856 } 857 858 bool StringConcat::validate_control_flow() { 859 // We found all the calls and arguments now lets see if it's 860 // safe to transform the graph as we would expect. 861 |