src/share/vm/opto/library_call.cpp
Index
Unified diffs
Context diffs
Sdiffs
Wdiffs
Patch
New
Old
Previous File
Next File
*** old/src/share/vm/opto/library_call.cpp Fri Feb 6 14:00:20 2009
--- new/src/share/vm/opto/library_call.cpp Fri Feb 6 14:00:20 2009
*** 134,143 ****
--- 134,144 ----
}
bool inline_string_compareTo();
bool inline_string_indexOf();
Node* string_indexOf(Node* string_object, ciTypeArray* target_array, jint offset, jint cache_i, jint md2_i);
+ bool inline_string_equals();
Node* pop_math_arg();
bool runtime_math(const TypeFunc* call_type, address funcAddr, const char* funcName);
bool inline_math_native(vmIntrinsics::ID id);
bool inline_trig(vmIntrinsics::ID id);
bool inline_trans(vmIntrinsics::ID id);
*** 258,267 ****
--- 259,269 ----
// -XX:-InlineNatives disables nearly all intrinsics:
if (!InlineNatives) {
switch (id) {
case vmIntrinsics::_indexOf:
case vmIntrinsics::_compareTo:
+ case vmIntrinsics::_equals:
case vmIntrinsics::_equalsC:
break; // InlineNatives does not control String.compareTo
default:
return NULL;
}
*** 272,281 ****
--- 274,286 ----
if (!SpecialStringCompareTo) return NULL;
break;
case vmIntrinsics::_indexOf:
if (!SpecialStringIndexOf) return NULL;
break;
+ case vmIntrinsics::_equals:
+ if (!SpecialStringEquals) return NULL;
+ break;
case vmIntrinsics::_equalsC:
if (!SpecialArraysEquals) return NULL;
break;
case vmIntrinsics::_arraycopy:
if (!InlineArrayCopy) return NULL;
*** 434,443 ****
--- 439,450 ----
case vmIntrinsics::_compareTo:
return inline_string_compareTo();
case vmIntrinsics::_indexOf:
return inline_string_indexOf();
+ case vmIntrinsics::_equals:
+ return inline_string_equals();
case vmIntrinsics::_getObject:
return inline_unsafe_access(!is_native_ptr, !is_store, T_OBJECT, false);
case vmIntrinsics::_getBoolean:
return inline_unsafe_access(!is_native_ptr, !is_store, T_BOOLEAN, false);
*** 818,827 ****
--- 825,910 ----
argument));
push(compare);
return true;
}
+ //------------------------------inline_string_equals------------------------
+ bool LibraryCallKit::inline_string_equals() {
+
+ if (!Matcher::has_match_rule(Op_StrEquals)) return false;
+
+ const int value_offset = java_lang_String::value_offset_in_bytes();
+ const int count_offset = java_lang_String::count_offset_in_bytes();
+ const int offset_offset = java_lang_String::offset_offset_in_bytes();
+
+ _sp += 2;
+ Node* argument = pop(); // pop non-receiver first: it was pushed second
+ Node* receiver = pop();
+
+
+ // Null check on self without removing any arguments. The argument
+ // null check technically happens in the wrong place, which can lead to
+ // invalid stack traces when string compare is inlined into a method
+ // which handles NullPointerExceptions.
+ _sp += 2;
+ receiver = do_null_check(receiver, T_OBJECT);
+ //should not do null check for argument for String.equals(), because spec
+ //allows to specify NULL as argument.
+ _sp -= 2;
+ if (stopped()) {
+ return true;
+ }
+
+ // get String klass for instanceOf
+ ciInstanceKlass* klass = env()->String_klass();
+
+ // two paths (plus control) merge
+ RegionNode* region = new (C, 3) RegionNode(3);
+ Node* phi = new (C, 3) PhiNode(region, TypeInt::BOOL);
+
+ Node* inst = gen_instanceof(argument, makecon(TypeKlassPtr::make(klass)));
+ Node* cmp = _gvn.transform(new (C, 3) CmpINode(inst, intcon(1)));
+ Node* bol = _gvn.transform(new (C, 2) BoolNode(cmp, BoolTest::eq));
+
+ IfNode* iff = create_and_map_if(control(), bol, PROB_MAX, COUNT_UNKNOWN);
+
+ Node* if_true = _gvn.transform(new (C, 1) IfTrueNode(iff));
+ set_control(if_true);
+
+ const TypeInstPtr* string_type =
+ TypeInstPtr::make(TypePtr::BotPTR, klass, false, NULL, 0);
+
+ // instanceOf == true
+ Node* equals =
+ _gvn.transform(new (C, 7) StrEqualsNode(
+ control(),
+ memory(TypeAryPtr::CHARS),
+ memory(string_type->add_offset(value_offset)),
+ memory(string_type->add_offset(count_offset)),
+ memory(string_type->add_offset(offset_offset)),
+ receiver,
+ argument));
+
+ phi->init_req(1, _gvn.transform(equals));
+ region->init_req(1, if_true);
+
+ //instanceOf == false, fallthrough
+ Node* if_false = _gvn.transform(new (C, 1) IfFalseNode(iff));
+ set_control(if_false);
+
+ phi->init_req(2, _gvn.transform(intcon(0)));
+ region->init_req(2, if_false);
+
+ // post merge
+ set_control(_gvn.transform(region));
+ record_for_igvn(region);
+
+ push(_gvn.transform(phi));
+
+ return true;
+ }
+
//------------------------------inline_array_equals----------------------------
bool LibraryCallKit::inline_array_equals() {
if (!Matcher::has_match_rule(Op_AryEq)) return false;
*** 982,992 ****
--- 1065,1074 ----
#undef __
C->set_has_loops(true);
return result;
}
//------------------------------inline_string_indexOf------------------------
bool LibraryCallKit::inline_string_indexOf() {
_sp += 2;
Node *argument = pop(); // pop non-receiver first: it was pushed second
*** 1039,1048 ****
--- 1121,1149 ----
if (c == 0) {
push(intcon(0));
return true;
}
+ Node* result;
+ if (Matcher::has_match_rule(Op_StrIndexOf) &&
+ UseSSE >= 4 && UseSSE42Intrinsics) {
+ // Generate SSE4.2 version of indexOf
+ // We currently only have match rules that use SSE4.2
+ const TypeInstPtr* string_type =
+ TypeInstPtr::make(TypePtr::BotPTR, klass, false, NULL, 0);
+
+ result =
+ _gvn.transform(new (C, 7)
+ StrIndexOfNode(control(),
+ memory(TypeAryPtr::CHARS),
+ memory(string_type->add_offset(value_offset)),
+ memory(string_type->add_offset(count_offset)),
+ memory(string_type->add_offset(offset_offset)),
+ receiver,
+ argument));
+ } else {
+ // Generate default indexOf
jchar lastChar = pat->char_at(o + (c - 1));
int cache = 0;
int i;
for (i = 0; i < c - 1; i++) {
assert(i < pat->length(), "out of range");
*** 1055,1065 ****
--- 1156,1167 ----
if (pat->char_at(o + i) == lastChar) {
md2 = (c - 1) - i;
}
}
! Node* result = string_indexOf(receiver, pat, o, cache, md2);
! result = string_indexOf(receiver, pat, o, cache, md2);
+ }
push(result);
return true;
}
//--------------------------pop_math_arg--------------------------------
src/share/vm/opto/library_call.cpp
Index
Unified diffs
Context diffs
Sdiffs
Wdiffs
Patch
New
Old
Previous File
Next File