Mercurial > hg > graal-compiler
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; |