comparison src/share/vm/opto/library_call.cpp @ 986:62001a362ce9

6827605: new String intrinsics may prevent EA scalar replacement 6875866: Intrinsic for String.indexOf() is broken on x86 with SSE4.2 Summary: Modify String intrinsic methods to pass char[] pointers instead of string oops. Reviewed-by: never
author kvn
date Mon, 14 Sep 2009 12:14:20 -0700
parents c7e94e8fff43
children 39b01ab7035a
comparison
equal deleted inserted replaced
985:685e959d09ea 986:62001a362ce9
131 } 131 }
132 CallJavaNode* generate_method_call_virtual(vmIntrinsics::ID method_id) { 132 CallJavaNode* generate_method_call_virtual(vmIntrinsics::ID method_id) {
133 return generate_method_call(method_id, true, false); 133 return generate_method_call(method_id, true, false);
134 } 134 }
135 135
136 Node* make_string_method_node(int opcode, Node* str1, Node* cnt1, Node* str2, Node* cnt2);
136 bool inline_string_compareTo(); 137 bool inline_string_compareTo();
137 bool inline_string_indexOf(); 138 bool inline_string_indexOf();
138 Node* string_indexOf(Node* string_object, ciTypeArray* target_array, jint offset, jint cache_i, jint md2_i); 139 Node* string_indexOf(Node* string_object, ciTypeArray* target_array, jint offset, jint cache_i, jint md2_i);
139 bool inline_string_equals(); 140 bool inline_string_equals();
140 Node* pop_math_arg(); 141 Node* pop_math_arg();
794 tls_output = thread; 795 tls_output = thread;
795 return threadObj; 796 return threadObj;
796 } 797 }
797 798
798 799
800 //------------------------------make_string_method_node------------------------
801 // Helper method for String intrinsic finctions.
802 Node* LibraryCallKit::make_string_method_node(int opcode, Node* str1, Node* cnt1, Node* str2, Node* cnt2) {
803 const int value_offset = java_lang_String::value_offset_in_bytes();
804 const int count_offset = java_lang_String::count_offset_in_bytes();
805 const int offset_offset = java_lang_String::offset_offset_in_bytes();
806
807 Node* no_ctrl = NULL;
808
809 ciInstanceKlass* klass = env()->String_klass();
810 const TypeInstPtr* string_type =
811 TypeInstPtr::make(TypePtr::BotPTR, klass, false, NULL, 0);
812
813 const TypeAryPtr* value_type =
814 TypeAryPtr::make(TypePtr::NotNull,
815 TypeAry::make(TypeInt::CHAR,TypeInt::POS),
816 ciTypeArrayKlass::make(T_CHAR), true, 0);
817
818 // Get start addr of string and substring
819 Node* str1_valuea = basic_plus_adr(str1, str1, value_offset);
820 Node* str1_value = make_load(no_ctrl, str1_valuea, value_type, T_OBJECT, string_type->add_offset(value_offset));
821 Node* str1_offseta = basic_plus_adr(str1, str1, offset_offset);
822 Node* str1_offset = make_load(no_ctrl, str1_offseta, TypeInt::INT, T_INT, string_type->add_offset(offset_offset));
823 Node* str1_start = array_element_address(str1_value, str1_offset, T_CHAR);
824
825 // Pin loads from String::equals() argument since it could be NULL.
826 Node* str2_ctrl = (opcode == Op_StrEquals) ? control() : no_ctrl;
827 Node* str2_valuea = basic_plus_adr(str2, str2, value_offset);
828 Node* str2_value = make_load(str2_ctrl, str2_valuea, value_type, T_OBJECT, string_type->add_offset(value_offset));
829 Node* str2_offseta = basic_plus_adr(str2, str2, offset_offset);
830 Node* str2_offset = make_load(str2_ctrl, str2_offseta, TypeInt::INT, T_INT, string_type->add_offset(offset_offset));
831 Node* str2_start = array_element_address(str2_value, str2_offset, T_CHAR);
832
833 Node* result = NULL;
834 switch (opcode) {
835 case Op_StrIndexOf:
836 result = new (C, 6) StrIndexOfNode(control(), memory(TypeAryPtr::CHARS),
837 str1_start, cnt1, str2_start, cnt2);
838 break;
839 case Op_StrComp:
840 result = new (C, 6) StrCompNode(control(), memory(TypeAryPtr::CHARS),
841 str1_start, cnt1, str2_start, cnt2);
842 break;
843 case Op_StrEquals:
844 result = new (C, 5) StrEqualsNode(control(), memory(TypeAryPtr::CHARS),
845 str1_start, str2_start, cnt1);
846 break;
847 default:
848 ShouldNotReachHere();
849 return NULL;
850 }
851
852 // All these intrinsics have checks.
853 C->set_has_split_ifs(true); // Has chance for split-if optimization
854
855 return _gvn.transform(result);
856 }
857
799 //------------------------------inline_string_compareTo------------------------ 858 //------------------------------inline_string_compareTo------------------------
800 bool LibraryCallKit::inline_string_compareTo() { 859 bool LibraryCallKit::inline_string_compareTo() {
801 860
802 if (!Matcher::has_match_rule(Op_StrComp)) return false; 861 if (!Matcher::has_match_rule(Op_StrComp)) return false;
803 862
822 } 881 }
823 882
824 ciInstanceKlass* klass = env()->String_klass(); 883 ciInstanceKlass* klass = env()->String_klass();
825 const TypeInstPtr* string_type = 884 const TypeInstPtr* string_type =
826 TypeInstPtr::make(TypePtr::BotPTR, klass, false, NULL, 0); 885 TypeInstPtr::make(TypePtr::BotPTR, klass, false, NULL, 0);
827 886 Node* no_ctrl = NULL;
828 Node* compare = 887
829 _gvn.transform(new (C, 7) StrCompNode( 888 // Get counts for string and argument
830 control(), 889 Node* receiver_cnta = basic_plus_adr(receiver, receiver, count_offset);
831 memory(TypeAryPtr::CHARS), 890 Node* receiver_cnt = make_load(no_ctrl, receiver_cnta, TypeInt::INT, T_INT, string_type->add_offset(count_offset));
832 memory(string_type->add_offset(value_offset)), 891
833 memory(string_type->add_offset(count_offset)), 892 Node* argument_cnta = basic_plus_adr(argument, argument, count_offset);
834 memory(string_type->add_offset(offset_offset)), 893 Node* argument_cnt = make_load(no_ctrl, argument_cnta, TypeInt::INT, T_INT, string_type->add_offset(count_offset));
835 receiver, 894
836 argument)); 895 Node* compare = make_string_method_node(Op_StrComp, receiver, receiver_cnt, argument, argument_cnt);
837 push(compare); 896 push(compare);
838 return true; 897 return true;
839 } 898 }
840 899
841 //------------------------------inline_string_equals------------------------ 900 //------------------------------inline_string_equals------------------------
863 922
864 if (stopped()) { 923 if (stopped()) {
865 return true; 924 return true;
866 } 925 }
867 926
927 // paths (plus control) merge
928 RegionNode* region = new (C, 5) RegionNode(5);
929 Node* phi = new (C, 5) PhiNode(region, TypeInt::BOOL);
930
931 // does source == target string?
932 Node* cmp = _gvn.transform(new (C, 3) CmpPNode(receiver, argument));
933 Node* bol = _gvn.transform(new (C, 2) BoolNode(cmp, BoolTest::eq));
934
935 Node* if_eq = generate_slow_guard(bol, NULL);
936 if (if_eq != NULL) {
937 // receiver == argument
938 phi->init_req(2, intcon(1));
939 region->init_req(2, if_eq);
940 }
941
868 // get String klass for instanceOf 942 // get String klass for instanceOf
869 ciInstanceKlass* klass = env()->String_klass(); 943 ciInstanceKlass* klass = env()->String_klass();
870 944
871 // two paths (plus control) merge 945 if (!stopped()) {
872 RegionNode* region = new (C, 3) RegionNode(3); 946 Node* inst = gen_instanceof(argument, makecon(TypeKlassPtr::make(klass)));
873 Node* phi = new (C, 3) PhiNode(region, TypeInt::BOOL); 947 Node* cmp = _gvn.transform(new (C, 3) CmpINode(inst, intcon(1)));
874 948 Node* bol = _gvn.transform(new (C, 2) BoolNode(cmp, BoolTest::ne));
875 Node* inst = gen_instanceof(argument, makecon(TypeKlassPtr::make(klass))); 949
876 Node* cmp = _gvn.transform(new (C, 3) CmpINode(inst, intcon(1))); 950 Node* inst_false = generate_guard(bol, NULL, PROB_MIN);
877 Node* bol = _gvn.transform(new (C, 2) BoolNode(cmp, BoolTest::eq)); 951 //instanceOf == true, fallthrough
878 952
879 IfNode* iff = create_and_map_if(control(), bol, PROB_MAX, COUNT_UNKNOWN); 953 if (inst_false != NULL) {
880 954 phi->init_req(3, intcon(0));
881 Node* if_true = _gvn.transform(new (C, 1) IfTrueNode(iff)); 955 region->init_req(3, inst_false);
882 set_control(if_true); 956 }
957 }
883 958
884 const TypeInstPtr* string_type = 959 const TypeInstPtr* string_type =
885 TypeInstPtr::make(TypePtr::BotPTR, klass, false, NULL, 0); 960 TypeInstPtr::make(TypePtr::BotPTR, klass, false, NULL, 0);
886 961
887 // instanceOf == true 962 Node* no_ctrl = NULL;
888 Node* equals = 963 Node* receiver_cnt;
889 _gvn.transform(new (C, 7) StrEqualsNode( 964 Node* argument_cnt;
890 control(), 965
891 memory(TypeAryPtr::CHARS), 966 if (!stopped()) {
892 memory(string_type->add_offset(value_offset)), 967 // Get counts for string and argument
893 memory(string_type->add_offset(count_offset)), 968 Node* receiver_cnta = basic_plus_adr(receiver, receiver, count_offset);
894 memory(string_type->add_offset(offset_offset)), 969 receiver_cnt = make_load(no_ctrl, receiver_cnta, TypeInt::INT, T_INT, string_type->add_offset(count_offset));
895 receiver, 970
896 argument)); 971 // Pin load from argument string since it could be NULL.
897 972 Node* argument_cnta = basic_plus_adr(argument, argument, count_offset);
898 phi->init_req(1, _gvn.transform(equals)); 973 argument_cnt = make_load(control(), argument_cnta, TypeInt::INT, T_INT, string_type->add_offset(count_offset));
899 region->init_req(1, if_true); 974
900 975 // Check for receiver count != argument count
901 //instanceOf == false, fallthrough 976 Node* cmp = _gvn.transform( new(C, 3) CmpINode(receiver_cnt, argument_cnt) );
902 Node* if_false = _gvn.transform(new (C, 1) IfFalseNode(iff)); 977 Node* bol = _gvn.transform( new(C, 2) BoolNode(cmp, BoolTest::ne) );
903 set_control(if_false); 978 Node* if_ne = generate_slow_guard(bol, NULL);
904 979 if (if_ne != NULL) {
905 phi->init_req(2, _gvn.transform(intcon(0))); 980 phi->init_req(4, intcon(0));
906 region->init_req(2, if_false); 981 region->init_req(4, if_ne);
982 }
983 }
984
985 // Check for count == 0 is done by mach node StrEquals.
986
987 if (!stopped()) {
988 Node* equals = make_string_method_node(Op_StrEquals, receiver, receiver_cnt, argument, argument_cnt);
989 phi->init_req(1, equals);
990 region->init_req(1, control());
991 }
907 992
908 // post merge 993 // post merge
909 set_control(_gvn.transform(region)); 994 set_control(_gvn.transform(region));
910 record_for_igvn(region); 995 record_for_igvn(region);
911 996
922 _sp += 2; 1007 _sp += 2;
923 Node *argument2 = pop(); 1008 Node *argument2 = pop();
924 Node *argument1 = pop(); 1009 Node *argument1 = pop();
925 1010
926 Node* equals = 1011 Node* equals =
927 _gvn.transform(new (C, 3) AryEqNode(control(), 1012 _gvn.transform(new (C, 4) AryEqNode(control(), memory(TypeAryPtr::CHARS),
928 argument1, 1013 argument1, argument2) );
929 argument2)
930 );
931 push(equals); 1014 push(equals);
932 return true; 1015 return true;
933 } 1016 }
934 1017
935 // Java version of String.indexOf(constant string) 1018 // Java version of String.indexOf(constant string)
1106 1189
1107 if (stopped()) { 1190 if (stopped()) {
1108 return true; 1191 return true;
1109 } 1192 }
1110 1193
1194 // Make the merge point
1195 RegionNode* result_rgn = new (C, 3) RegionNode(3);
1196 Node* result_phi = new (C, 3) PhiNode(result_rgn, TypeInt::INT);
1197 Node* no_ctrl = NULL;
1198
1111 ciInstanceKlass* klass = env()->String_klass(); 1199 ciInstanceKlass* klass = env()->String_klass();
1112 const TypeInstPtr* string_type = 1200 const TypeInstPtr* string_type =
1113 TypeInstPtr::make(TypePtr::BotPTR, klass, false, NULL, 0); 1201 TypeInstPtr::make(TypePtr::BotPTR, klass, false, NULL, 0);
1114 1202
1115 result = 1203 // Get counts for string and substr
1116 _gvn.transform(new (C, 7) 1204 Node* source_cnta = basic_plus_adr(receiver, receiver, count_offset);
1117 StrIndexOfNode(control(), 1205 Node* source_cnt = make_load(no_ctrl, source_cnta, TypeInt::INT, T_INT, string_type->add_offset(count_offset));
1118 memory(TypeAryPtr::CHARS), 1206
1119 memory(string_type->add_offset(value_offset)), 1207 Node* substr_cnta = basic_plus_adr(argument, argument, count_offset);
1120 memory(string_type->add_offset(count_offset)), 1208 Node* substr_cnt = make_load(no_ctrl, substr_cnta, TypeInt::INT, T_INT, string_type->add_offset(count_offset));
1121 memory(string_type->add_offset(offset_offset)), 1209
1122 receiver, 1210 // Check for substr count > string count
1123 argument)); 1211 Node* cmp = _gvn.transform( new(C, 3) CmpINode(substr_cnt, source_cnt) );
1212 Node* bol = _gvn.transform( new(C, 2) BoolNode(cmp, BoolTest::gt) );
1213 Node* if_gt = generate_slow_guard(bol, NULL);
1214 if (if_gt != NULL) {
1215 result_phi->init_req(2, intcon(-1));
1216 result_rgn->init_req(2, if_gt);
1217 }
1218
1219 if (!stopped()) {
1220 result = make_string_method_node(Op_StrIndexOf, receiver, source_cnt, argument, substr_cnt);
1221 result_phi->init_req(1, result);
1222 result_rgn->init_req(1, control());
1223 }
1224 set_control(_gvn.transform(result_rgn));
1225 record_for_igvn(result_rgn);
1226 result = _gvn.transform(result_phi);
1227
1124 } else { //Use LibraryCallKit::string_indexOf 1228 } else { //Use LibraryCallKit::string_indexOf
1125 // don't intrinsify is argument isn't a constant string. 1229 // don't intrinsify is argument isn't a constant string.
1126 if (!argument->is_Con()) { 1230 if (!argument->is_Con()) {
1127 return false; 1231 return false;
1128 } 1232 }