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
|