1.1 --- a/src/share/vm/opto/library_call.cpp Tue Mar 31 10:02:01 2009 -0700 1.2 +++ b/src/share/vm/opto/library_call.cpp Tue Mar 31 14:07:08 2009 -0700 1.3 @@ -136,6 +136,7 @@ 1.4 bool inline_string_compareTo(); 1.5 bool inline_string_indexOf(); 1.6 Node* string_indexOf(Node* string_object, ciTypeArray* target_array, jint offset, jint cache_i, jint md2_i); 1.7 + bool inline_string_equals(); 1.8 Node* pop_math_arg(); 1.9 bool runtime_math(const TypeFunc* call_type, address funcAddr, const char* funcName); 1.10 bool inline_math_native(vmIntrinsics::ID id); 1.11 @@ -261,6 +262,7 @@ 1.12 switch (id) { 1.13 case vmIntrinsics::_indexOf: 1.14 case vmIntrinsics::_compareTo: 1.15 + case vmIntrinsics::_equals: 1.16 case vmIntrinsics::_equalsC: 1.17 break; // InlineNatives does not control String.compareTo 1.18 default: 1.19 @@ -275,6 +277,9 @@ 1.20 case vmIntrinsics::_indexOf: 1.21 if (!SpecialStringIndexOf) return NULL; 1.22 break; 1.23 + case vmIntrinsics::_equals: 1.24 + if (!SpecialStringEquals) return NULL; 1.25 + break; 1.26 case vmIntrinsics::_equalsC: 1.27 if (!SpecialArraysEquals) return NULL; 1.28 break; 1.29 @@ -442,6 +447,8 @@ 1.30 return inline_string_compareTo(); 1.31 case vmIntrinsics::_indexOf: 1.32 return inline_string_indexOf(); 1.33 + case vmIntrinsics::_equals: 1.34 + return inline_string_equals(); 1.35 1.36 case vmIntrinsics::_getObject: 1.37 return inline_unsafe_access(!is_native_ptr, !is_store, T_OBJECT, false); 1.38 @@ -793,6 +800,8 @@ 1.39 //------------------------------inline_string_compareTo------------------------ 1.40 bool LibraryCallKit::inline_string_compareTo() { 1.41 1.42 + if (!Matcher::has_match_rule(Op_StrComp)) return false; 1.43 + 1.44 const int value_offset = java_lang_String::value_offset_in_bytes(); 1.45 const int count_offset = java_lang_String::count_offset_in_bytes(); 1.46 const int offset_offset = java_lang_String::offset_offset_in_bytes(); 1.47 @@ -830,6 +839,82 @@ 1.48 return true; 1.49 } 1.50 1.51 +//------------------------------inline_string_equals------------------------ 1.52 +bool LibraryCallKit::inline_string_equals() { 1.53 + 1.54 + if (!Matcher::has_match_rule(Op_StrEquals)) return false; 1.55 + 1.56 + const int value_offset = java_lang_String::value_offset_in_bytes(); 1.57 + const int count_offset = java_lang_String::count_offset_in_bytes(); 1.58 + const int offset_offset = java_lang_String::offset_offset_in_bytes(); 1.59 + 1.60 + _sp += 2; 1.61 + Node* argument = pop(); // pop non-receiver first: it was pushed second 1.62 + Node* receiver = pop(); 1.63 + 1.64 + // Null check on self without removing any arguments. The argument 1.65 + // null check technically happens in the wrong place, which can lead to 1.66 + // invalid stack traces when string compare is inlined into a method 1.67 + // which handles NullPointerExceptions. 1.68 + _sp += 2; 1.69 + receiver = do_null_check(receiver, T_OBJECT); 1.70 + //should not do null check for argument for String.equals(), because spec 1.71 + //allows to specify NULL as argument. 1.72 + _sp -= 2; 1.73 + 1.74 + if (stopped()) { 1.75 + return true; 1.76 + } 1.77 + 1.78 + // get String klass for instanceOf 1.79 + ciInstanceKlass* klass = env()->String_klass(); 1.80 + 1.81 + // two paths (plus control) merge 1.82 + RegionNode* region = new (C, 3) RegionNode(3); 1.83 + Node* phi = new (C, 3) PhiNode(region, TypeInt::BOOL); 1.84 + 1.85 + Node* inst = gen_instanceof(argument, makecon(TypeKlassPtr::make(klass))); 1.86 + Node* cmp = _gvn.transform(new (C, 3) CmpINode(inst, intcon(1))); 1.87 + Node* bol = _gvn.transform(new (C, 2) BoolNode(cmp, BoolTest::eq)); 1.88 + 1.89 + IfNode* iff = create_and_map_if(control(), bol, PROB_MAX, COUNT_UNKNOWN); 1.90 + 1.91 + Node* if_true = _gvn.transform(new (C, 1) IfTrueNode(iff)); 1.92 + set_control(if_true); 1.93 + 1.94 + const TypeInstPtr* string_type = 1.95 + TypeInstPtr::make(TypePtr::BotPTR, klass, false, NULL, 0); 1.96 + 1.97 + // instanceOf == true 1.98 + Node* equals = 1.99 + _gvn.transform(new (C, 7) StrEqualsNode( 1.100 + control(), 1.101 + memory(TypeAryPtr::CHARS), 1.102 + memory(string_type->add_offset(value_offset)), 1.103 + memory(string_type->add_offset(count_offset)), 1.104 + memory(string_type->add_offset(offset_offset)), 1.105 + receiver, 1.106 + argument)); 1.107 + 1.108 + phi->init_req(1, _gvn.transform(equals)); 1.109 + region->init_req(1, if_true); 1.110 + 1.111 + //instanceOf == false, fallthrough 1.112 + Node* if_false = _gvn.transform(new (C, 1) IfFalseNode(iff)); 1.113 + set_control(if_false); 1.114 + 1.115 + phi->init_req(2, _gvn.transform(intcon(0))); 1.116 + region->init_req(2, if_false); 1.117 + 1.118 + // post merge 1.119 + set_control(_gvn.transform(region)); 1.120 + record_for_igvn(region); 1.121 + 1.122 + push(_gvn.transform(phi)); 1.123 + 1.124 + return true; 1.125 +} 1.126 + 1.127 //------------------------------inline_array_equals---------------------------- 1.128 bool LibraryCallKit::inline_array_equals() { 1.129 1.130 @@ -994,80 +1079,115 @@ 1.131 return result; 1.132 } 1.133 1.134 - 1.135 //------------------------------inline_string_indexOf------------------------ 1.136 bool LibraryCallKit::inline_string_indexOf() { 1.137 1.138 + const int value_offset = java_lang_String::value_offset_in_bytes(); 1.139 + const int count_offset = java_lang_String::count_offset_in_bytes(); 1.140 + const int offset_offset = java_lang_String::offset_offset_in_bytes(); 1.141 + 1.142 _sp += 2; 1.143 Node *argument = pop(); // pop non-receiver first: it was pushed second 1.144 Node *receiver = pop(); 1.145 1.146 - // don't intrinsify if argument isn't a constant string. 1.147 - if (!argument->is_Con()) { 1.148 - return false; 1.149 + Node* result; 1.150 + if (Matcher::has_match_rule(Op_StrIndexOf) && 1.151 + UseSSE42Intrinsics) { 1.152 + // Generate SSE4.2 version of indexOf 1.153 + // We currently only have match rules that use SSE4.2 1.154 + 1.155 + // Null check on self without removing any arguments. The argument 1.156 + // null check technically happens in the wrong place, which can lead to 1.157 + // invalid stack traces when string compare is inlined into a method 1.158 + // which handles NullPointerExceptions. 1.159 + _sp += 2; 1.160 + receiver = do_null_check(receiver, T_OBJECT); 1.161 + argument = do_null_check(argument, T_OBJECT); 1.162 + _sp -= 2; 1.163 + 1.164 + if (stopped()) { 1.165 + return true; 1.166 + } 1.167 + 1.168 + ciInstanceKlass* klass = env()->String_klass(); 1.169 + const TypeInstPtr* string_type = 1.170 + TypeInstPtr::make(TypePtr::BotPTR, klass, false, NULL, 0); 1.171 + 1.172 + result = 1.173 + _gvn.transform(new (C, 7) 1.174 + StrIndexOfNode(control(), 1.175 + memory(TypeAryPtr::CHARS), 1.176 + memory(string_type->add_offset(value_offset)), 1.177 + memory(string_type->add_offset(count_offset)), 1.178 + memory(string_type->add_offset(offset_offset)), 1.179 + receiver, 1.180 + argument)); 1.181 + } else { //Use LibraryCallKit::string_indexOf 1.182 + // don't intrinsify is argument isn't a constant string. 1.183 + if (!argument->is_Con()) { 1.184 + return false; 1.185 + } 1.186 + const TypeOopPtr* str_type = _gvn.type(argument)->isa_oopptr(); 1.187 + if (str_type == NULL) { 1.188 + return false; 1.189 + } 1.190 + ciInstanceKlass* klass = env()->String_klass(); 1.191 + ciObject* str_const = str_type->const_oop(); 1.192 + if (str_const == NULL || str_const->klass() != klass) { 1.193 + return false; 1.194 + } 1.195 + ciInstance* str = str_const->as_instance(); 1.196 + assert(str != NULL, "must be instance"); 1.197 + 1.198 + ciObject* v = str->field_value_by_offset(value_offset).as_object(); 1.199 + int o = str->field_value_by_offset(offset_offset).as_int(); 1.200 + int c = str->field_value_by_offset(count_offset).as_int(); 1.201 + ciTypeArray* pat = v->as_type_array(); // pattern (argument) character array 1.202 + 1.203 + // constant strings have no offset and count == length which 1.204 + // simplifies the resulting code somewhat so lets optimize for that. 1.205 + if (o != 0 || c != pat->length()) { 1.206 + return false; 1.207 + } 1.208 + 1.209 + // Null check on self without removing any arguments. The argument 1.210 + // null check technically happens in the wrong place, which can lead to 1.211 + // invalid stack traces when string compare is inlined into a method 1.212 + // which handles NullPointerExceptions. 1.213 + _sp += 2; 1.214 + receiver = do_null_check(receiver, T_OBJECT); 1.215 + // No null check on the argument is needed since it's a constant String oop. 1.216 + _sp -= 2; 1.217 + if (stopped()) { 1.218 + return true; 1.219 + } 1.220 + 1.221 + // The null string as a pattern always returns 0 (match at beginning of string) 1.222 + if (c == 0) { 1.223 + push(intcon(0)); 1.224 + return true; 1.225 + } 1.226 + 1.227 + // Generate default indexOf 1.228 + jchar lastChar = pat->char_at(o + (c - 1)); 1.229 + int cache = 0; 1.230 + int i; 1.231 + for (i = 0; i < c - 1; i++) { 1.232 + assert(i < pat->length(), "out of range"); 1.233 + cache |= (1 << (pat->char_at(o + i) & (sizeof(cache) * BitsPerByte - 1))); 1.234 + } 1.235 + 1.236 + int md2 = c; 1.237 + for (i = 0; i < c - 1; i++) { 1.238 + assert(i < pat->length(), "out of range"); 1.239 + if (pat->char_at(o + i) == lastChar) { 1.240 + md2 = (c - 1) - i; 1.241 + } 1.242 + } 1.243 + 1.244 + result = string_indexOf(receiver, pat, o, cache, md2); 1.245 } 1.246 - const TypeOopPtr* str_type = _gvn.type(argument)->isa_oopptr(); 1.247 - if (str_type == NULL) { 1.248 - return false; 1.249 - } 1.250 - ciInstanceKlass* klass = env()->String_klass(); 1.251 - ciObject* str_const = str_type->const_oop(); 1.252 - if (str_const == NULL || str_const->klass() != klass) { 1.253 - return false; 1.254 - } 1.255 - ciInstance* str = str_const->as_instance(); 1.256 - assert(str != NULL, "must be instance"); 1.257 - 1.258 - const int value_offset = java_lang_String::value_offset_in_bytes(); 1.259 - const int count_offset = java_lang_String::count_offset_in_bytes(); 1.260 - const int offset_offset = java_lang_String::offset_offset_in_bytes(); 1.261 - 1.262 - ciObject* v = str->field_value_by_offset(value_offset).as_object(); 1.263 - int o = str->field_value_by_offset(offset_offset).as_int(); 1.264 - int c = str->field_value_by_offset(count_offset).as_int(); 1.265 - ciTypeArray* pat = v->as_type_array(); // pattern (argument) character array 1.266 - 1.267 - // constant strings have no offset and count == length which 1.268 - // simplifies the resulting code somewhat so lets optimize for that. 1.269 - if (o != 0 || c != pat->length()) { 1.270 - return false; 1.271 - } 1.272 - 1.273 - // Null check on self without removing any arguments. The argument 1.274 - // null check technically happens in the wrong place, which can lead to 1.275 - // invalid stack traces when string compare is inlined into a method 1.276 - // which handles NullPointerExceptions. 1.277 - _sp += 2; 1.278 - receiver = do_null_check(receiver, T_OBJECT); 1.279 - // No null check on the argument is needed since it's a constant String oop. 1.280 - _sp -= 2; 1.281 - if (stopped()) { 1.282 - return true; 1.283 - } 1.284 - 1.285 - // The null string as a pattern always returns 0 (match at beginning of string) 1.286 - if (c == 0) { 1.287 - push(intcon(0)); 1.288 - return true; 1.289 - } 1.290 - 1.291 - jchar lastChar = pat->char_at(o + (c - 1)); 1.292 - int cache = 0; 1.293 - int i; 1.294 - for (i = 0; i < c - 1; i++) { 1.295 - assert(i < pat->length(), "out of range"); 1.296 - cache |= (1 << (pat->char_at(o + i) & (sizeof(cache) * BitsPerByte - 1))); 1.297 - } 1.298 - 1.299 - int md2 = c; 1.300 - for (i = 0; i < c - 1; i++) { 1.301 - assert(i < pat->length(), "out of range"); 1.302 - if (pat->char_at(o + i) == lastChar) { 1.303 - md2 = (c - 1) - i; 1.304 - } 1.305 - } 1.306 - 1.307 - Node* result = string_indexOf(receiver, pat, o, cache, md2); 1.308 + 1.309 push(result); 1.310 return true; 1.311 }