440 |
445 |
441 case vmIntrinsics::_compareTo: |
446 case vmIntrinsics::_compareTo: |
442 return inline_string_compareTo(); |
447 return inline_string_compareTo(); |
443 case vmIntrinsics::_indexOf: |
448 case vmIntrinsics::_indexOf: |
444 return inline_string_indexOf(); |
449 return inline_string_indexOf(); |
|
450 case vmIntrinsics::_equals: |
|
451 return inline_string_equals(); |
445 |
452 |
446 case vmIntrinsics::_getObject: |
453 case vmIntrinsics::_getObject: |
447 return inline_unsafe_access(!is_native_ptr, !is_store, T_OBJECT, false); |
454 return inline_unsafe_access(!is_native_ptr, !is_store, T_OBJECT, false); |
448 case vmIntrinsics::_getBoolean: |
455 case vmIntrinsics::_getBoolean: |
449 return inline_unsafe_access(!is_native_ptr, !is_store, T_BOOLEAN, false); |
456 return inline_unsafe_access(!is_native_ptr, !is_store, T_BOOLEAN, false); |
825 memory(string_type->add_offset(count_offset)), |
834 memory(string_type->add_offset(count_offset)), |
826 memory(string_type->add_offset(offset_offset)), |
835 memory(string_type->add_offset(offset_offset)), |
827 receiver, |
836 receiver, |
828 argument)); |
837 argument)); |
829 push(compare); |
838 push(compare); |
|
839 return true; |
|
840 } |
|
841 |
|
842 //------------------------------inline_string_equals------------------------ |
|
843 bool LibraryCallKit::inline_string_equals() { |
|
844 |
|
845 if (!Matcher::has_match_rule(Op_StrEquals)) return false; |
|
846 |
|
847 const int value_offset = java_lang_String::value_offset_in_bytes(); |
|
848 const int count_offset = java_lang_String::count_offset_in_bytes(); |
|
849 const int offset_offset = java_lang_String::offset_offset_in_bytes(); |
|
850 |
|
851 _sp += 2; |
|
852 Node* argument = pop(); // pop non-receiver first: it was pushed second |
|
853 Node* receiver = pop(); |
|
854 |
|
855 // Null check on self without removing any arguments. The argument |
|
856 // null check technically happens in the wrong place, which can lead to |
|
857 // invalid stack traces when string compare is inlined into a method |
|
858 // which handles NullPointerExceptions. |
|
859 _sp += 2; |
|
860 receiver = do_null_check(receiver, T_OBJECT); |
|
861 //should not do null check for argument for String.equals(), because spec |
|
862 //allows to specify NULL as argument. |
|
863 _sp -= 2; |
|
864 |
|
865 if (stopped()) { |
|
866 return true; |
|
867 } |
|
868 |
|
869 // get String klass for instanceOf |
|
870 ciInstanceKlass* klass = env()->String_klass(); |
|
871 |
|
872 // two paths (plus control) merge |
|
873 RegionNode* region = new (C, 3) RegionNode(3); |
|
874 Node* phi = new (C, 3) PhiNode(region, TypeInt::BOOL); |
|
875 |
|
876 Node* inst = gen_instanceof(argument, makecon(TypeKlassPtr::make(klass))); |
|
877 Node* cmp = _gvn.transform(new (C, 3) CmpINode(inst, intcon(1))); |
|
878 Node* bol = _gvn.transform(new (C, 2) BoolNode(cmp, BoolTest::eq)); |
|
879 |
|
880 IfNode* iff = create_and_map_if(control(), bol, PROB_MAX, COUNT_UNKNOWN); |
|
881 |
|
882 Node* if_true = _gvn.transform(new (C, 1) IfTrueNode(iff)); |
|
883 set_control(if_true); |
|
884 |
|
885 const TypeInstPtr* string_type = |
|
886 TypeInstPtr::make(TypePtr::BotPTR, klass, false, NULL, 0); |
|
887 |
|
888 // instanceOf == true |
|
889 Node* equals = |
|
890 _gvn.transform(new (C, 7) StrEqualsNode( |
|
891 control(), |
|
892 memory(TypeAryPtr::CHARS), |
|
893 memory(string_type->add_offset(value_offset)), |
|
894 memory(string_type->add_offset(count_offset)), |
|
895 memory(string_type->add_offset(offset_offset)), |
|
896 receiver, |
|
897 argument)); |
|
898 |
|
899 phi->init_req(1, _gvn.transform(equals)); |
|
900 region->init_req(1, if_true); |
|
901 |
|
902 //instanceOf == false, fallthrough |
|
903 Node* if_false = _gvn.transform(new (C, 1) IfFalseNode(iff)); |
|
904 set_control(if_false); |
|
905 |
|
906 phi->init_req(2, _gvn.transform(intcon(0))); |
|
907 region->init_req(2, if_false); |
|
908 |
|
909 // post merge |
|
910 set_control(_gvn.transform(region)); |
|
911 record_for_igvn(region); |
|
912 |
|
913 push(_gvn.transform(phi)); |
|
914 |
830 return true; |
915 return true; |
831 } |
916 } |
832 |
917 |
833 //------------------------------inline_array_equals---------------------------- |
918 //------------------------------inline_array_equals---------------------------- |
834 bool LibraryCallKit::inline_array_equals() { |
919 bool LibraryCallKit::inline_array_equals() { |
992 #undef __ |
1077 #undef __ |
993 C->set_has_loops(true); |
1078 C->set_has_loops(true); |
994 return result; |
1079 return result; |
995 } |
1080 } |
996 |
1081 |
997 |
|
998 //------------------------------inline_string_indexOf------------------------ |
1082 //------------------------------inline_string_indexOf------------------------ |
999 bool LibraryCallKit::inline_string_indexOf() { |
1083 bool LibraryCallKit::inline_string_indexOf() { |
|
1084 |
|
1085 const int value_offset = java_lang_String::value_offset_in_bytes(); |
|
1086 const int count_offset = java_lang_String::count_offset_in_bytes(); |
|
1087 const int offset_offset = java_lang_String::offset_offset_in_bytes(); |
1000 |
1088 |
1001 _sp += 2; |
1089 _sp += 2; |
1002 Node *argument = pop(); // pop non-receiver first: it was pushed second |
1090 Node *argument = pop(); // pop non-receiver first: it was pushed second |
1003 Node *receiver = pop(); |
1091 Node *receiver = pop(); |
1004 |
1092 |
1005 // don't intrinsify if argument isn't a constant string. |
1093 Node* result; |
1006 if (!argument->is_Con()) { |
1094 if (Matcher::has_match_rule(Op_StrIndexOf) && |
1007 return false; |
1095 UseSSE42Intrinsics) { |
1008 } |
1096 // Generate SSE4.2 version of indexOf |
1009 const TypeOopPtr* str_type = _gvn.type(argument)->isa_oopptr(); |
1097 // We currently only have match rules that use SSE4.2 |
1010 if (str_type == NULL) { |
1098 |
1011 return false; |
1099 // Null check on self without removing any arguments. The argument |
1012 } |
1100 // null check technically happens in the wrong place, which can lead to |
1013 ciInstanceKlass* klass = env()->String_klass(); |
1101 // invalid stack traces when string compare is inlined into a method |
1014 ciObject* str_const = str_type->const_oop(); |
1102 // which handles NullPointerExceptions. |
1015 if (str_const == NULL || str_const->klass() != klass) { |
1103 _sp += 2; |
1016 return false; |
1104 receiver = do_null_check(receiver, T_OBJECT); |
1017 } |
1105 argument = do_null_check(argument, T_OBJECT); |
1018 ciInstance* str = str_const->as_instance(); |
1106 _sp -= 2; |
1019 assert(str != NULL, "must be instance"); |
1107 |
1020 |
1108 if (stopped()) { |
1021 const int value_offset = java_lang_String::value_offset_in_bytes(); |
1109 return true; |
1022 const int count_offset = java_lang_String::count_offset_in_bytes(); |
1110 } |
1023 const int offset_offset = java_lang_String::offset_offset_in_bytes(); |
1111 |
1024 |
1112 ciInstanceKlass* klass = env()->String_klass(); |
1025 ciObject* v = str->field_value_by_offset(value_offset).as_object(); |
1113 const TypeInstPtr* string_type = |
1026 int o = str->field_value_by_offset(offset_offset).as_int(); |
1114 TypeInstPtr::make(TypePtr::BotPTR, klass, false, NULL, 0); |
1027 int c = str->field_value_by_offset(count_offset).as_int(); |
1115 |
1028 ciTypeArray* pat = v->as_type_array(); // pattern (argument) character array |
1116 result = |
1029 |
1117 _gvn.transform(new (C, 7) |
1030 // constant strings have no offset and count == length which |
1118 StrIndexOfNode(control(), |
1031 // simplifies the resulting code somewhat so lets optimize for that. |
1119 memory(TypeAryPtr::CHARS), |
1032 if (o != 0 || c != pat->length()) { |
1120 memory(string_type->add_offset(value_offset)), |
1033 return false; |
1121 memory(string_type->add_offset(count_offset)), |
1034 } |
1122 memory(string_type->add_offset(offset_offset)), |
1035 |
1123 receiver, |
1036 // Null check on self without removing any arguments. The argument |
1124 argument)); |
1037 // null check technically happens in the wrong place, which can lead to |
1125 } else { //Use LibraryCallKit::string_indexOf |
1038 // invalid stack traces when string compare is inlined into a method |
1126 // don't intrinsify is argument isn't a constant string. |
1039 // which handles NullPointerExceptions. |
1127 if (!argument->is_Con()) { |
1040 _sp += 2; |
1128 return false; |
1041 receiver = do_null_check(receiver, T_OBJECT); |
1129 } |
1042 // No null check on the argument is needed since it's a constant String oop. |
1130 const TypeOopPtr* str_type = _gvn.type(argument)->isa_oopptr(); |
1043 _sp -= 2; |
1131 if (str_type == NULL) { |
1044 if (stopped()) { |
1132 return false; |
1045 return true; |
1133 } |
1046 } |
1134 ciInstanceKlass* klass = env()->String_klass(); |
1047 |
1135 ciObject* str_const = str_type->const_oop(); |
1048 // The null string as a pattern always returns 0 (match at beginning of string) |
1136 if (str_const == NULL || str_const->klass() != klass) { |
1049 if (c == 0) { |
1137 return false; |
1050 push(intcon(0)); |
1138 } |
1051 return true; |
1139 ciInstance* str = str_const->as_instance(); |
1052 } |
1140 assert(str != NULL, "must be instance"); |
1053 |
1141 |
1054 jchar lastChar = pat->char_at(o + (c - 1)); |
1142 ciObject* v = str->field_value_by_offset(value_offset).as_object(); |
1055 int cache = 0; |
1143 int o = str->field_value_by_offset(offset_offset).as_int(); |
1056 int i; |
1144 int c = str->field_value_by_offset(count_offset).as_int(); |
1057 for (i = 0; i < c - 1; i++) { |
1145 ciTypeArray* pat = v->as_type_array(); // pattern (argument) character array |
1058 assert(i < pat->length(), "out of range"); |
1146 |
1059 cache |= (1 << (pat->char_at(o + i) & (sizeof(cache) * BitsPerByte - 1))); |
1147 // constant strings have no offset and count == length which |
1060 } |
1148 // simplifies the resulting code somewhat so lets optimize for that. |
1061 |
1149 if (o != 0 || c != pat->length()) { |
1062 int md2 = c; |
1150 return false; |
1063 for (i = 0; i < c - 1; i++) { |
1151 } |
1064 assert(i < pat->length(), "out of range"); |
1152 |
1065 if (pat->char_at(o + i) == lastChar) { |
1153 // Null check on self without removing any arguments. The argument |
1066 md2 = (c - 1) - i; |
1154 // null check technically happens in the wrong place, which can lead to |
1067 } |
1155 // invalid stack traces when string compare is inlined into a method |
1068 } |
1156 // which handles NullPointerExceptions. |
1069 |
1157 _sp += 2; |
1070 Node* result = string_indexOf(receiver, pat, o, cache, md2); |
1158 receiver = do_null_check(receiver, T_OBJECT); |
|
1159 // No null check on the argument is needed since it's a constant String oop. |
|
1160 _sp -= 2; |
|
1161 if (stopped()) { |
|
1162 return true; |
|
1163 } |
|
1164 |
|
1165 // The null string as a pattern always returns 0 (match at beginning of string) |
|
1166 if (c == 0) { |
|
1167 push(intcon(0)); |
|
1168 return true; |
|
1169 } |
|
1170 |
|
1171 // Generate default indexOf |
|
1172 jchar lastChar = pat->char_at(o + (c - 1)); |
|
1173 int cache = 0; |
|
1174 int i; |
|
1175 for (i = 0; i < c - 1; i++) { |
|
1176 assert(i < pat->length(), "out of range"); |
|
1177 cache |= (1 << (pat->char_at(o + i) & (sizeof(cache) * BitsPerByte - 1))); |
|
1178 } |
|
1179 |
|
1180 int md2 = c; |
|
1181 for (i = 0; i < c - 1; i++) { |
|
1182 assert(i < pat->length(), "out of range"); |
|
1183 if (pat->char_at(o + i) == lastChar) { |
|
1184 md2 = (c - 1) - i; |
|
1185 } |
|
1186 } |
|
1187 |
|
1188 result = string_indexOf(receiver, pat, o, cache, md2); |
|
1189 } |
|
1190 |
1071 push(result); |
1191 push(result); |
1072 return true; |
1192 return true; |
1073 } |
1193 } |
1074 |
1194 |
1075 //--------------------------pop_math_arg-------------------------------- |
1195 //--------------------------pop_math_arg-------------------------------- |