comparison src/share/vm/opto/library_call.cpp @ 6057:8f972594effc

6924259: Remove String.count/String.offset Summary: Allow a version of String class that doesn't have count and offset fields. Reviewed-by: never, coleenp
author kvn
date Mon, 14 May 2012 09:36:00 -0700
parents 0105f367a14c
children 6759698e3140
comparison
equal deleted inserted replaced
6054:56d1af561395 6057:8f972594effc
145 } 145 }
146 CallJavaNode* generate_method_call_virtual(vmIntrinsics::ID method_id) { 146 CallJavaNode* generate_method_call_virtual(vmIntrinsics::ID method_id) {
147 return generate_method_call(method_id, true, false); 147 return generate_method_call(method_id, true, false);
148 } 148 }
149 149
150 Node* make_string_method_node(int opcode, Node* str1, Node* cnt1, Node* str2, Node* cnt2); 150 Node* make_string_method_node(int opcode, Node* str1_start, Node* cnt1, Node* str2_start, Node* cnt2);
151 Node* make_string_method_node(int opcode, Node* str1, Node* str2);
151 bool inline_string_compareTo(); 152 bool inline_string_compareTo();
152 bool inline_string_indexOf(); 153 bool inline_string_indexOf();
153 Node* string_indexOf(Node* string_object, ciTypeArray* target_array, jint offset, jint cache_i, jint md2_i); 154 Node* string_indexOf(Node* string_object, ciTypeArray* target_array, jint offset, jint cache_i, jint md2_i);
154 bool inline_string_equals(); 155 bool inline_string_equals();
155 Node* pop_math_arg(); 156 Node* pop_math_arg();
871 return threadObj; 872 return threadObj;
872 } 873 }
873 874
874 875
875 //------------------------------make_string_method_node------------------------ 876 //------------------------------make_string_method_node------------------------
876 // Helper method for String intrinsic finctions. 877 // Helper method for String intrinsic functions. This version is called
877 Node* LibraryCallKit::make_string_method_node(int opcode, Node* str1, Node* cnt1, Node* str2, Node* cnt2) { 878 // with str1 and str2 pointing to String object nodes.
878 const int value_offset = java_lang_String::value_offset_in_bytes(); 879 //
879 const int count_offset = java_lang_String::count_offset_in_bytes(); 880 Node* LibraryCallKit::make_string_method_node(int opcode, Node* str1, Node* str2) {
880 const int offset_offset = java_lang_String::offset_offset_in_bytes();
881
882 Node* no_ctrl = NULL; 881 Node* no_ctrl = NULL;
883 882
884 ciInstanceKlass* klass = env()->String_klass(); 883 // Get start addr of string
885 const TypeOopPtr* string_type = TypeOopPtr::make_from_klass(klass); 884 Node* str1_value = load_String_value(no_ctrl, str1);
886 885 Node* str1_offset = load_String_offset(no_ctrl, str1);
887 const TypeAryPtr* value_type =
888 TypeAryPtr::make(TypePtr::NotNull,
889 TypeAry::make(TypeInt::CHAR,TypeInt::POS),
890 ciTypeArrayKlass::make(T_CHAR), true, 0);
891
892 // Get start addr of string and substring
893 Node* str1_valuea = basic_plus_adr(str1, str1, value_offset);
894 Node* str1_value = make_load(no_ctrl, str1_valuea, value_type, T_OBJECT, string_type->add_offset(value_offset));
895 Node* str1_offseta = basic_plus_adr(str1, str1, offset_offset);
896 Node* str1_offset = make_load(no_ctrl, str1_offseta, TypeInt::INT, T_INT, string_type->add_offset(offset_offset));
897 Node* str1_start = array_element_address(str1_value, str1_offset, T_CHAR); 886 Node* str1_start = array_element_address(str1_value, str1_offset, T_CHAR);
898 887
899 Node* str2_valuea = basic_plus_adr(str2, str2, value_offset); 888 // Get length of string 1
900 Node* str2_value = make_load(no_ctrl, str2_valuea, value_type, T_OBJECT, string_type->add_offset(value_offset)); 889 Node* str1_len = load_String_length(no_ctrl, str1);
901 Node* str2_offseta = basic_plus_adr(str2, str2, offset_offset); 890
902 Node* str2_offset = make_load(no_ctrl, str2_offseta, TypeInt::INT, T_INT, string_type->add_offset(offset_offset)); 891 Node* str2_value = load_String_value(no_ctrl, str2);
892 Node* str2_offset = load_String_offset(no_ctrl, str2);
903 Node* str2_start = array_element_address(str2_value, str2_offset, T_CHAR); 893 Node* str2_start = array_element_address(str2_value, str2_offset, T_CHAR);
894
895 Node* str2_len = NULL;
896 Node* result = NULL;
897
898 switch (opcode) {
899 case Op_StrIndexOf:
900 // Get length of string 2
901 str2_len = load_String_length(no_ctrl, str2);
902
903 result = new (C, 6) StrIndexOfNode(control(), memory(TypeAryPtr::CHARS),
904 str1_start, str1_len, str2_start, str2_len);
905 break;
906 case Op_StrComp:
907 // Get length of string 2
908 str2_len = load_String_length(no_ctrl, str2);
909
910 result = new (C, 6) StrCompNode(control(), memory(TypeAryPtr::CHARS),
911 str1_start, str1_len, str2_start, str2_len);
912 break;
913 case Op_StrEquals:
914 result = new (C, 5) StrEqualsNode(control(), memory(TypeAryPtr::CHARS),
915 str1_start, str2_start, str1_len);
916 break;
917 default:
918 ShouldNotReachHere();
919 return NULL;
920 }
921
922 // All these intrinsics have checks.
923 C->set_has_split_ifs(true); // Has chance for split-if optimization
924
925 return _gvn.transform(result);
926 }
927
928 // Helper method for String intrinsic functions. This version is called
929 // with str1 and str2 pointing to char[] nodes, with cnt1 and cnt2 pointing
930 // to Int nodes containing the lenghts of str1 and str2.
931 //
932 Node* LibraryCallKit::make_string_method_node(int opcode, Node* str1_start, Node* cnt1, Node* str2_start, Node* cnt2) {
904 933
905 Node* result = NULL; 934 Node* result = NULL;
906 switch (opcode) { 935 switch (opcode) {
907 case Op_StrIndexOf: 936 case Op_StrIndexOf:
908 result = new (C, 6) StrIndexOfNode(control(), memory(TypeAryPtr::CHARS), 937 result = new (C, 6) StrIndexOfNode(control(), memory(TypeAryPtr::CHARS),
909 str1_start, cnt1, str2_start, cnt2); 938 str1_start, cnt1, str2_start, cnt2);
910 break; 939 break;
911 case Op_StrComp: 940 case Op_StrComp:
912 result = new (C, 6) StrCompNode(control(), memory(TypeAryPtr::CHARS), 941 result = new (C, 6) StrCompNode(control(), memory(TypeAryPtr::CHARS),
913 str1_start, cnt1, str2_start, cnt2); 942 str1_start, cnt1, str2_start, cnt2);
914 break; 943 break;
915 case Op_StrEquals: 944 case Op_StrEquals:
916 result = new (C, 5) StrEqualsNode(control(), memory(TypeAryPtr::CHARS), 945 result = new (C, 5) StrEqualsNode(control(), memory(TypeAryPtr::CHARS),
917 str1_start, str2_start, cnt1); 946 str1_start, str2_start, cnt1);
918 break; 947 break;
919 default: 948 default:
920 ShouldNotReachHere(); 949 ShouldNotReachHere();
921 return NULL; 950 return NULL;
922 } 951 }
929 958
930 //------------------------------inline_string_compareTo------------------------ 959 //------------------------------inline_string_compareTo------------------------
931 bool LibraryCallKit::inline_string_compareTo() { 960 bool LibraryCallKit::inline_string_compareTo() {
932 961
933 if (!Matcher::has_match_rule(Op_StrComp)) return false; 962 if (!Matcher::has_match_rule(Op_StrComp)) return false;
934
935 const int value_offset = java_lang_String::value_offset_in_bytes();
936 const int count_offset = java_lang_String::count_offset_in_bytes();
937 const int offset_offset = java_lang_String::offset_offset_in_bytes();
938 963
939 _sp += 2; 964 _sp += 2;
940 Node *argument = pop(); // pop non-receiver first: it was pushed second 965 Node *argument = pop(); // pop non-receiver first: it was pushed second
941 Node *receiver = pop(); 966 Node *receiver = pop();
942 967
950 _sp -= 2; 975 _sp -= 2;
951 if (stopped()) { 976 if (stopped()) {
952 return true; 977 return true;
953 } 978 }
954 979
955 ciInstanceKlass* klass = env()->String_klass(); 980 Node* compare = make_string_method_node(Op_StrComp, receiver, argument);
956 const TypeOopPtr* string_type = TypeOopPtr::make_from_klass(klass);
957 Node* no_ctrl = NULL;
958
959 // Get counts for string and argument
960 Node* receiver_cnta = basic_plus_adr(receiver, receiver, count_offset);
961 Node* receiver_cnt = make_load(no_ctrl, receiver_cnta, TypeInt::INT, T_INT, string_type->add_offset(count_offset));
962
963 Node* argument_cnta = basic_plus_adr(argument, argument, count_offset);
964 Node* argument_cnt = make_load(no_ctrl, argument_cnta, TypeInt::INT, T_INT, string_type->add_offset(count_offset));
965
966 Node* compare = make_string_method_node(Op_StrComp, receiver, receiver_cnt, argument, argument_cnt);
967 push(compare); 981 push(compare);
968 return true; 982 return true;
969 } 983 }
970 984
971 //------------------------------inline_string_equals------------------------ 985 //------------------------------inline_string_equals------------------------
972 bool LibraryCallKit::inline_string_equals() { 986 bool LibraryCallKit::inline_string_equals() {
973 987
974 if (!Matcher::has_match_rule(Op_StrEquals)) return false; 988 if (!Matcher::has_match_rule(Op_StrEquals)) return false;
975
976 const int value_offset = java_lang_String::value_offset_in_bytes();
977 const int count_offset = java_lang_String::count_offset_in_bytes();
978 const int offset_offset = java_lang_String::offset_offset_in_bytes();
979 989
980 int nargs = 2; 990 int nargs = 2;
981 _sp += nargs; 991 _sp += nargs;
982 Node* argument = pop(); // pop non-receiver first: it was pushed second 992 Node* argument = pop(); // pop non-receiver first: it was pushed second
983 Node* receiver = pop(); 993 Node* receiver = pop();
1028 phi->init_req(3, intcon(0)); 1038 phi->init_req(3, intcon(0));
1029 region->init_req(3, inst_false); 1039 region->init_req(3, inst_false);
1030 } 1040 }
1031 } 1041 }
1032 1042
1033 const TypeOopPtr* string_type = TypeOopPtr::make_from_klass(klass);
1034
1035 Node* no_ctrl = NULL;
1036 Node* receiver_cnt;
1037 Node* argument_cnt;
1038
1039 if (!stopped()) { 1043 if (!stopped()) {
1044 const TypeOopPtr* string_type = TypeOopPtr::make_from_klass(klass);
1045
1040 // Properly cast the argument to String 1046 // Properly cast the argument to String
1041 argument = _gvn.transform(new (C, 2) CheckCastPPNode(control(), argument, string_type)); 1047 argument = _gvn.transform(new (C, 2) CheckCastPPNode(control(), argument, string_type));
1042 // This path is taken only when argument's type is String:NotNull. 1048 // This path is taken only when argument's type is String:NotNull.
1043 argument = cast_not_null(argument, false); 1049 argument = cast_not_null(argument, false);
1044 1050
1045 // Get counts for string and argument 1051 Node* no_ctrl = NULL;
1046 Node* receiver_cnta = basic_plus_adr(receiver, receiver, count_offset); 1052
1047 receiver_cnt = make_load(no_ctrl, receiver_cnta, TypeInt::INT, T_INT, string_type->add_offset(count_offset)); 1053 // Get start addr of receiver
1048 1054 Node* receiver_val = load_String_value(no_ctrl, receiver);
1049 Node* argument_cnta = basic_plus_adr(argument, argument, count_offset); 1055 Node* receiver_offset = load_String_offset(no_ctrl, receiver);
1050 argument_cnt = make_load(no_ctrl, argument_cnta, TypeInt::INT, T_INT, string_type->add_offset(count_offset)); 1056 Node* receiver_start = array_element_address(receiver_val, receiver_offset, T_CHAR);
1057
1058 // Get length of receiver
1059 Node* receiver_cnt = load_String_length(no_ctrl, receiver);
1060
1061 // Get start addr of argument
1062 Node* argument_val = load_String_value(no_ctrl, argument);
1063 Node* argument_offset = load_String_offset(no_ctrl, argument);
1064 Node* argument_start = array_element_address(argument_val, argument_offset, T_CHAR);
1065
1066 // Get length of argument
1067 Node* argument_cnt = load_String_length(no_ctrl, argument);
1051 1068
1052 // Check for receiver count != argument count 1069 // Check for receiver count != argument count
1053 Node* cmp = _gvn.transform( new(C, 3) CmpINode(receiver_cnt, argument_cnt) ); 1070 Node* cmp = _gvn.transform( new(C, 3) CmpINode(receiver_cnt, argument_cnt) );
1054 Node* bol = _gvn.transform( new(C, 2) BoolNode(cmp, BoolTest::ne) ); 1071 Node* bol = _gvn.transform( new(C, 2) BoolNode(cmp, BoolTest::ne) );
1055 Node* if_ne = generate_slow_guard(bol, NULL); 1072 Node* if_ne = generate_slow_guard(bol, NULL);
1056 if (if_ne != NULL) { 1073 if (if_ne != NULL) {
1057 phi->init_req(4, intcon(0)); 1074 phi->init_req(4, intcon(0));
1058 region->init_req(4, if_ne); 1075 region->init_req(4, if_ne);
1059 } 1076 }
1060 } 1077
1061 1078 // Check for count == 0 is done by assembler code for StrEquals.
1062 // Check for count == 0 is done by mach node StrEquals. 1079
1063 1080 if (!stopped()) {
1064 if (!stopped()) { 1081 Node* equals = make_string_method_node(Op_StrEquals, receiver_start, receiver_cnt, argument_start, argument_cnt);
1065 Node* equals = make_string_method_node(Op_StrEquals, receiver, receiver_cnt, argument, argument_cnt); 1082 phi->init_req(1, equals);
1066 phi->init_req(1, equals); 1083 region->init_req(1, control());
1067 region->init_req(1, control()); 1084 }
1068 } 1085 }
1069 1086
1070 // post merge 1087 // post merge
1071 set_control(_gvn.transform(region)); 1088 set_control(_gvn.transform(region));
1072 record_for_igvn(region); 1089 record_for_igvn(region);
1160 float likely = PROB_LIKELY(0.9); 1177 float likely = PROB_LIKELY(0.9);
1161 float unlikely = PROB_UNLIKELY(0.9); 1178 float unlikely = PROB_UNLIKELY(0.9);
1162 1179
1163 const int nargs = 2; // number of arguments to push back for uncommon trap in predicate 1180 const int nargs = 2; // number of arguments to push back for uncommon trap in predicate
1164 1181
1165 const int value_offset = java_lang_String::value_offset_in_bytes(); 1182 Node* source = load_String_value(no_ctrl, string_object);
1166 const int count_offset = java_lang_String::count_offset_in_bytes(); 1183 Node* sourceOffset = load_String_offset(no_ctrl, string_object);
1167 const int offset_offset = java_lang_String::offset_offset_in_bytes(); 1184 Node* sourceCount = load_String_length(no_ctrl, string_object);
1168
1169 ciInstanceKlass* klass = env()->String_klass();
1170 const TypeOopPtr* string_type = TypeOopPtr::make_from_klass(klass);
1171 const TypeAryPtr* source_type = TypeAryPtr::make(TypePtr::NotNull, TypeAry::make(TypeInt::CHAR,TypeInt::POS), ciTypeArrayKlass::make(T_CHAR), true, 0);
1172
1173 Node* sourceOffseta = basic_plus_adr(string_object, string_object, offset_offset);
1174 Node* sourceOffset = make_load(no_ctrl, sourceOffseta, TypeInt::INT, T_INT, string_type->add_offset(offset_offset));
1175 Node* sourceCounta = basic_plus_adr(string_object, string_object, count_offset);
1176 Node* sourceCount = make_load(no_ctrl, sourceCounta, TypeInt::INT, T_INT, string_type->add_offset(count_offset));
1177 Node* sourcea = basic_plus_adr(string_object, string_object, value_offset);
1178 Node* source = make_load(no_ctrl, sourcea, source_type, T_OBJECT, string_type->add_offset(value_offset));
1179 1185
1180 Node* target = _gvn.transform( makecon(TypeOopPtr::make_from_constant(target_array, true)) ); 1186 Node* target = _gvn.transform( makecon(TypeOopPtr::make_from_constant(target_array, true)) );
1181 jint target_length = target_array->length(); 1187 jint target_length = target_array->length();
1182 const TypeAry* target_array_type = TypeAry::make(TypeInt::CHAR, TypeInt::make(0, target_length, Type::WidenMin)); 1188 const TypeAry* target_array_type = TypeAry::make(TypeInt::CHAR, TypeInt::make(0, target_length, Type::WidenMin));
1183 const TypeAryPtr* target_type = TypeAryPtr::make(TypePtr::BotPTR, target_array_type, target_array->klass(), true, Type::OffsetBot); 1189 const TypeAryPtr* target_type = TypeAryPtr::make(TypePtr::BotPTR, target_array_type, target_array->klass(), true, Type::OffsetBot);
1241 } 1247 }
1242 1248
1243 //------------------------------inline_string_indexOf------------------------ 1249 //------------------------------inline_string_indexOf------------------------
1244 bool LibraryCallKit::inline_string_indexOf() { 1250 bool LibraryCallKit::inline_string_indexOf() {
1245 1251
1246 const int value_offset = java_lang_String::value_offset_in_bytes();
1247 const int count_offset = java_lang_String::count_offset_in_bytes();
1248 const int offset_offset = java_lang_String::offset_offset_in_bytes();
1249
1250 _sp += 2; 1252 _sp += 2;
1251 Node *argument = pop(); // pop non-receiver first: it was pushed second 1253 Node *argument = pop(); // pop non-receiver first: it was pushed second
1252 Node *receiver = pop(); 1254 Node *receiver = pop();
1253 1255
1254 Node* result; 1256 Node* result;
1278 // Make the merge point 1280 // Make the merge point
1279 RegionNode* result_rgn = new (C, 4) RegionNode(4); 1281 RegionNode* result_rgn = new (C, 4) RegionNode(4);
1280 Node* result_phi = new (C, 4) PhiNode(result_rgn, TypeInt::INT); 1282 Node* result_phi = new (C, 4) PhiNode(result_rgn, TypeInt::INT);
1281 Node* no_ctrl = NULL; 1283 Node* no_ctrl = NULL;
1282 1284
1283 // Get counts for string and substr 1285 // Get start addr of source string
1284 Node* source_cnta = basic_plus_adr(receiver, receiver, count_offset); 1286 Node* source = load_String_value(no_ctrl, receiver);
1285 Node* source_cnt = make_load(no_ctrl, source_cnta, TypeInt::INT, T_INT, string_type->add_offset(count_offset)); 1287 Node* source_offset = load_String_offset(no_ctrl, receiver);
1286 1288 Node* source_start = array_element_address(source, source_offset, T_CHAR);
1287 Node* substr_cnta = basic_plus_adr(argument, argument, count_offset); 1289
1288 Node* substr_cnt = make_load(no_ctrl, substr_cnta, TypeInt::INT, T_INT, string_type->add_offset(count_offset)); 1290 // Get length of source string
1291 Node* source_cnt = load_String_length(no_ctrl, receiver);
1292
1293 // Get start addr of substring
1294 Node* substr = load_String_value(no_ctrl, argument);
1295 Node* substr_offset = load_String_offset(no_ctrl, argument);
1296 Node* substr_start = array_element_address(substr, substr_offset, T_CHAR);
1297
1298 // Get length of source string
1299 Node* substr_cnt = load_String_length(no_ctrl, argument);
1289 1300
1290 // Check for substr count > string count 1301 // Check for substr count > string count
1291 Node* cmp = _gvn.transform( new(C, 3) CmpINode(substr_cnt, source_cnt) ); 1302 Node* cmp = _gvn.transform( new(C, 3) CmpINode(substr_cnt, source_cnt) );
1292 Node* bol = _gvn.transform( new(C, 2) BoolNode(cmp, BoolTest::gt) ); 1303 Node* bol = _gvn.transform( new(C, 2) BoolNode(cmp, BoolTest::gt) );
1293 Node* if_gt = generate_slow_guard(bol, NULL); 1304 Node* if_gt = generate_slow_guard(bol, NULL);
1306 result_rgn->init_req(3, if_zero); 1317 result_rgn->init_req(3, if_zero);
1307 } 1318 }
1308 } 1319 }
1309 1320
1310 if (!stopped()) { 1321 if (!stopped()) {
1311 result = make_string_method_node(Op_StrIndexOf, receiver, source_cnt, argument, substr_cnt); 1322 result = make_string_method_node(Op_StrIndexOf, source_start, source_cnt, substr_start, substr_cnt);
1312 result_phi->init_req(1, result); 1323 result_phi->init_req(1, result);
1313 result_rgn->init_req(1, control()); 1324 result_rgn->init_req(1, control());
1314 } 1325 }
1315 set_control(_gvn.transform(result_rgn)); 1326 set_control(_gvn.transform(result_rgn));
1316 record_for_igvn(result_rgn); 1327 record_for_igvn(result_rgn);
1331 return false; 1342 return false;
1332 } 1343 }
1333 ciInstance* str = str_const->as_instance(); 1344 ciInstance* str = str_const->as_instance();
1334 assert(str != NULL, "must be instance"); 1345 assert(str != NULL, "must be instance");
1335 1346
1336 ciObject* v = str->field_value_by_offset(value_offset).as_object(); 1347 ciObject* v = str->field_value_by_offset(java_lang_String::value_offset_in_bytes()).as_object();
1337 int o = str->field_value_by_offset(offset_offset).as_int();
1338 int c = str->field_value_by_offset(count_offset).as_int();
1339 ciTypeArray* pat = v->as_type_array(); // pattern (argument) character array 1348 ciTypeArray* pat = v->as_type_array(); // pattern (argument) character array
1349
1350 int o;
1351 int c;
1352 if (java_lang_String::has_offset_field()) {
1353 o = str->field_value_by_offset(java_lang_String::offset_offset_in_bytes()).as_int();
1354 c = str->field_value_by_offset(java_lang_String::count_offset_in_bytes()).as_int();
1355 } else {
1356 o = 0;
1357 c = pat->length();
1358 }
1340 1359
1341 // constant strings have no offset and count == length which 1360 // constant strings have no offset and count == length which
1342 // simplifies the resulting code somewhat so lets optimize for that. 1361 // simplifies the resulting code somewhat so lets optimize for that.
1343 if (o != 0 || c != pat->length()) { 1362 if (o != 0 || c != pat->length()) {
1344 return false; 1363 return false;