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 Tue Aug 18 19:06:23 2009
--- new/src/share/vm/opto/library_call.cpp Tue Aug 18 19:06:22 2009
*** 131,140 ****
--- 131,141 ----
}
CallJavaNode* generate_method_call_virtual(vmIntrinsics::ID method_id) {
return generate_method_call(method_id, true, false);
}
+ Node* make_string_method_node(int opcode, Node* str1, Node* str2, Node* cnt1, Node* cnt2);
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();
*** 794,803 ****
--- 795,857 ----
tls_output = thread;
return threadObj;
}
+ //------------------------------make_string_method_node------------------------
+ // Helper method for String intrinsic finctions.
+ Node* LibraryCallKit::make_string_method_node(int opcode, Node* str1, Node* str2, Node* cnt1, Node* cnt2) {
+ 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();
+
+ Node* no_ctrl = NULL;
+
+ ciInstanceKlass* klass = env()->String_klass();
+ const TypeInstPtr* string_type =
+ TypeInstPtr::make(TypePtr::BotPTR, klass, false, NULL, 0);
+
+ const TypeAryPtr* value_type =
+ TypeAryPtr::make(TypePtr::NotNull,
+ TypeAry::make(TypeInt::CHAR,TypeInt::POS),
+ ciTypeArrayKlass::make(T_CHAR), true, 0);
+
+ // Get start addr of string and substring
+ Node* str1_valuea = basic_plus_adr(str1, str1, value_offset);
+ Node* str1_value = make_load(no_ctrl, str1_valuea, value_type, T_OBJECT, string_type->add_offset(value_offset));
+ Node* str1_offseta = basic_plus_adr(str1, str1, offset_offset);
+ Node* str1_offset = make_load(no_ctrl, str1_offseta, TypeInt::INT, T_INT, string_type->add_offset(offset_offset));
+ Node* str1_start = array_element_address(str1_value, str1_offset, T_CHAR);
+
+ Node* str2_valuea = basic_plus_adr(str2, str2, value_offset);
+ Node* str2_value = make_load(no_ctrl, str2_valuea, value_type, T_OBJECT, string_type->add_offset(value_offset));
+ Node* str2_offseta = basic_plus_adr(str2, str2, offset_offset);
+ Node* str2_offset = make_load(no_ctrl, str2_offseta, TypeInt::INT, T_INT, string_type->add_offset(offset_offset));
+ Node* str2_start = array_element_address(str2_value, str2_offset, T_CHAR);
+
+ Node* result = NULL;
+ switch (opcode) {
+ case Op_StrComp:
+ result = new (C, 6) StrCompNode(control(), memory(TypeAryPtr::CHARS),
+ str1_start, str2_start, cnt1, cnt2);
+ break;
+ case Op_StrEquals:
+ result = new (C, 5) StrEqualsNode(control(), memory(TypeAryPtr::CHARS),
+ str1_start, str2_start, cnt1);
+ break;
+ case Op_StrIndexOf:
+ result = new (C, 6) StrIndexOfNode(control(), memory(TypeAryPtr::CHARS),
+ str1_start, str2_start, cnt1, cnt2);
+ break;
+ default:
+ ShouldNotReachHere();
+ return NULL;
+ }
+
+ return _gvn.transform(result);
+ }
+
//------------------------------inline_string_compareTo------------------------
bool LibraryCallKit::inline_string_compareTo() {
if (!Matcher::has_match_rule(Op_StrComp)) return false;
*** 822,841 ****
--- 876,895 ----
}
ciInstanceKlass* klass = env()->String_klass();
const TypeInstPtr* string_type =
TypeInstPtr::make(TypePtr::BotPTR, klass, false, NULL, 0);
+ Node* no_ctrl = NULL;
Node* compare =
_gvn.transform(new (C, 7) StrCompNode(
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));
+ // Get counts for string and argument
+ Node* receiver_cnta = basic_plus_adr(receiver, receiver, count_offset);
+ Node* receiver_cnt = make_load(no_ctrl, receiver_cnta, TypeInt::INT, T_INT, string_type->add_offset(count_offset));
+
+ Node* argument_cnta = basic_plus_adr(argument, argument, count_offset);
+ Node* argument_cnt = make_load(no_ctrl, argument_cnta, TypeInt::INT, T_INT, string_type->add_offset(count_offset));
+
+ Node* compare = make_string_method_node(Op_StrComp, receiver, argument, receiver_cnt, argument_cnt);
push(compare);
return true;
}
//------------------------------inline_string_equals------------------------
*** 863,912 ****
--- 917,991 ----
if (stopped()) {
return true;
}
+ // paths (plus control) merge
+ RegionNode* region = new (C, 5) RegionNode(5);
+ Node* phi = new (C, 5) PhiNode(region, TypeInt::BOOL);
+
+ // does source == target string?
+ Node* cmp = _gvn.transform(new (C, 3) CmpPNode(receiver, argument));
+ Node* bol = _gvn.transform(new (C, 2) BoolNode(cmp, BoolTest::eq));
+
+ Node* if_eq = generate_slow_guard(bol, NULL);
+ if (if_eq != NULL) {
+ // receiver == argument
+ phi->init_req(2, intcon(1));
+ region->init_req(2, if_eq);
+ }
+
// 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);
+ if (!stopped()) {
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));
! Node* bol = _gvn.transform(new (C, 2) BoolNode(cmp, BoolTest::ne));
! IfNode* iff = create_and_map_if(control(), bol, PROB_MAX, COUNT_UNKNOWN);
! Node* inst_false = generate_guard(bol, NULL, PROB_MIN);
+ //instanceOf == true, fallthrough
Node* if_true = _gvn.transform(new (C, 1) IfTrueNode(iff));
! set_control(if_true);
+ if (inst_false != NULL) {
! phi->init_req(3, intcon(0));
+ region->init_req(3, inst_false);
+ }
+ }
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));
+ Node* no_ctrl = NULL;
! Node* receiver_cnt;
+ Node* argument_cnt;
phi->init_req(1, _gvn.transform(equals));
region->init_req(1, if_true);
+ if (!stopped()) {
+ // Get counts for string and argument
+ Node* receiver_cnta = basic_plus_adr(receiver, receiver, count_offset);
+ receiver_cnt = make_load(no_ctrl, receiver_cnta, TypeInt::INT, T_INT, string_type->add_offset(count_offset));
//instanceOf == false, fallthrough
! Node* if_false = _gvn.transform(new (C, 1) IfFalseNode(iff));
set_control(if_false);
+ Node* argument_cnta = basic_plus_adr(argument, argument, count_offset);
! argument_cnt = make_load(no_ctrl, argument_cnta, TypeInt::INT, T_INT, string_type->add_offset(count_offset));
phi->init_req(2, _gvn.transform(intcon(0)));
! region->init_req(2, if_false);
+ // Check for receiver count != argument count
! Node* cmp = _gvn.transform( new(C, 3) CmpINode(receiver_cnt, argument_cnt) );
+ Node* bol = _gvn.transform( new(C, 2) BoolNode(cmp, BoolTest::ne) );
+ Node* if_ne = generate_slow_guard(bol, NULL);
+ if (if_ne != NULL) {
+ phi->init_req(4, intcon(0));
+ region->init_req(4, if_ne);
+ }
+ }
+ // Check for count == 0 is done by mach node StrEquals.
+
+ if (!stopped()) {
+ Node* equals = make_string_method_node(Op_StrEquals, receiver, argument, receiver_cnt, argument_cnt);
+ phi->init_req(1, equals);
+ region->init_req(1, control());
+ }
+
// post merge
set_control(_gvn.transform(region));
record_for_igvn(region);
push(_gvn.transform(phi));
*** 1106,1128 ****
--- 1185,1228 ----
if (stopped()) {
return true;
}
+ // Make the merge point
+ RegionNode* result_rgn = new (C, 3) RegionNode(3);
+ Node* result_phi = new (C, 3) PhiNode(result_rgn, TypeInt::INT);
+ Node* no_ctrl = NULL;
+
ciInstanceKlass* klass = env()->String_klass();
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));
+ // Get counts for string and substr
+ Node* source_cnta = basic_plus_adr(receiver, receiver, count_offset);
+ Node* source_cnt = make_load(no_ctrl, source_cnta, TypeInt::INT, T_INT, string_type->add_offset(count_offset));
+
+ Node* substr_cnta = basic_plus_adr(argument, argument, count_offset);
+ Node* substr_cnt = make_load(no_ctrl, substr_cnta, TypeInt::INT, T_INT, string_type->add_offset(count_offset));
+
+ // Check for substr count > string count
! Node* cmp = _gvn.transform( new(C, 3) CmpINode(substr_cnt, source_cnt) );
+ Node* bol = _gvn.transform( new(C, 2) BoolNode(cmp, BoolTest::gt) );
+ Node* if_gt = generate_slow_guard(bol, NULL);
+ if (if_gt != NULL) {
+ result_phi->init_req(2, intcon(-1));
+ result_rgn->init_req(2, if_gt);
+ }
+
+ if (!stopped()) {
+ result = make_string_method_node(Op_StrIndexOf, receiver, argument, source_cnt, substr_cnt);
+ result_phi->init_req(1, result);
+ result_rgn->init_req(1, control());
+ }
+ set_control(_gvn.transform(result_rgn));
+ record_for_igvn(result_rgn);
+ result = _gvn.transform(result_phi);
+
} else { //Use LibraryCallKit::string_indexOf
// don't intrinsify is argument isn't a constant string.
if (!argument->is_Con()) {
return false;
}
src/share/vm/opto/library_call.cpp
Index
Unified diffs
Context diffs
Sdiffs
Wdiffs
Patch
New
Old
Previous File
Next File