--- a/hotspot/src/share/vm/opto/library_call.cpp Fri May 11 14:54:35 2012 -0700
+++ b/hotspot/src/share/vm/opto/library_call.cpp Mon May 14 09:36:00 2012 -0700
@@ -147,7 +147,8 @@
return generate_method_call(method_id, true, false);
}
- Node* make_string_method_node(int opcode, Node* str1, Node* cnt1, Node* str2, Node* cnt2);
+ Node* make_string_method_node(int opcode, Node* str1_start, Node* cnt1, Node* str2_start, Node* cnt2);
+ Node* make_string_method_node(int opcode, Node* str1, Node* str2);
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);
@@ -873,48 +874,76 @@
//------------------------------make_string_method_node------------------------
-// Helper method for String intrinsic finctions.
-Node* LibraryCallKit::make_string_method_node(int opcode, Node* str1, Node* cnt1, Node* str2, 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();
-
+// Helper method for String intrinsic functions. This version is called
+// with str1 and str2 pointing to String object nodes.
+//
+Node* LibraryCallKit::make_string_method_node(int opcode, Node* str1, Node* str2) {
Node* no_ctrl = NULL;
- ciInstanceKlass* klass = env()->String_klass();
- const TypeOopPtr* string_type = TypeOopPtr::make_from_klass(klass);
-
- 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));
+ // Get start addr of string
+ Node* str1_value = load_String_value(no_ctrl, str1);
+ Node* str1_offset = load_String_offset(no_ctrl, str1);
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));
+ // Get length of string 1
+ Node* str1_len = load_String_length(no_ctrl, str1);
+
+ Node* str2_value = load_String_value(no_ctrl, str2);
+ Node* str2_offset = load_String_offset(no_ctrl, str2);
Node* str2_start = array_element_address(str2_value, str2_offset, T_CHAR);
+ Node* str2_len = NULL;
+ Node* result = NULL;
+
+ switch (opcode) {
+ case Op_StrIndexOf:
+ // Get length of string 2
+ str2_len = load_String_length(no_ctrl, str2);
+
+ result = new (C, 6) StrIndexOfNode(control(), memory(TypeAryPtr::CHARS),
+ str1_start, str1_len, str2_start, str2_len);
+ break;
+ case Op_StrComp:
+ // Get length of string 2
+ str2_len = load_String_length(no_ctrl, str2);
+
+ result = new (C, 6) StrCompNode(control(), memory(TypeAryPtr::CHARS),
+ str1_start, str1_len, str2_start, str2_len);
+ break;
+ case Op_StrEquals:
+ result = new (C, 5) StrEqualsNode(control(), memory(TypeAryPtr::CHARS),
+ str1_start, str2_start, str1_len);
+ break;
+ default:
+ ShouldNotReachHere();
+ return NULL;
+ }
+
+ // All these intrinsics have checks.
+ C->set_has_split_ifs(true); // Has chance for split-if optimization
+
+ return _gvn.transform(result);
+}
+
+// Helper method for String intrinsic functions. This version is called
+// with str1 and str2 pointing to char[] nodes, with cnt1 and cnt2 pointing
+// to Int nodes containing the lenghts of str1 and str2.
+//
+Node* LibraryCallKit::make_string_method_node(int opcode, Node* str1_start, Node* cnt1, Node* str2_start, Node* cnt2) {
+
Node* result = NULL;
switch (opcode) {
case Op_StrIndexOf:
result = new (C, 6) StrIndexOfNode(control(), memory(TypeAryPtr::CHARS),
- str1_start, cnt1, str2_start, cnt2);
+ str1_start, cnt1, str2_start, cnt2);
break;
case Op_StrComp:
result = new (C, 6) StrCompNode(control(), memory(TypeAryPtr::CHARS),
- str1_start, cnt1, str2_start, cnt2);
+ str1_start, cnt1, str2_start, cnt2);
break;
case Op_StrEquals:
result = new (C, 5) StrEqualsNode(control(), memory(TypeAryPtr::CHARS),
- str1_start, str2_start, cnt1);
+ str1_start, str2_start, cnt1);
break;
default:
ShouldNotReachHere();
@@ -932,10 +961,6 @@
if (!Matcher::has_match_rule(Op_StrComp)) 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();
@@ -952,18 +977,7 @@
return true;
}
- ciInstanceKlass* klass = env()->String_klass();
- const TypeOopPtr* string_type = TypeOopPtr::make_from_klass(klass);
- Node* no_ctrl = NULL;
-
- // 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, receiver_cnt, argument, argument_cnt);
+ Node* compare = make_string_method_node(Op_StrComp, receiver, argument);
push(compare);
return true;
}
@@ -973,10 +987,6 @@
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();
-
int nargs = 2;
_sp += nargs;
Node* argument = pop(); // pop non-receiver first: it was pushed second
@@ -1030,24 +1040,31 @@
}
}
- const TypeOopPtr* string_type = TypeOopPtr::make_from_klass(klass);
-
- Node* no_ctrl = NULL;
- Node* receiver_cnt;
- Node* argument_cnt;
-
if (!stopped()) {
+ const TypeOopPtr* string_type = TypeOopPtr::make_from_klass(klass);
+
// Properly cast the argument to String
argument = _gvn.transform(new (C, 2) CheckCastPPNode(control(), argument, string_type));
// This path is taken only when argument's type is String:NotNull.
argument = cast_not_null(argument, false);
- // 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));
-
- 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));
+ Node* no_ctrl = NULL;
+
+ // Get start addr of receiver
+ Node* receiver_val = load_String_value(no_ctrl, receiver);
+ Node* receiver_offset = load_String_offset(no_ctrl, receiver);
+ Node* receiver_start = array_element_address(receiver_val, receiver_offset, T_CHAR);
+
+ // Get length of receiver
+ Node* receiver_cnt = load_String_length(no_ctrl, receiver);
+
+ // Get start addr of argument
+ Node* argument_val = load_String_value(no_ctrl, argument);
+ Node* argument_offset = load_String_offset(no_ctrl, argument);
+ Node* argument_start = array_element_address(argument_val, argument_offset, T_CHAR);
+
+ // Get length of argument
+ Node* argument_cnt = load_String_length(no_ctrl, argument);
// Check for receiver count != argument count
Node* cmp = _gvn.transform( new(C, 3) CmpINode(receiver_cnt, argument_cnt) );
@@ -1057,14 +1074,14 @@
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, receiver_cnt, argument, argument_cnt);
- phi->init_req(1, equals);
- region->init_req(1, control());
+
+ // Check for count == 0 is done by assembler code for StrEquals.
+
+ if (!stopped()) {
+ Node* equals = make_string_method_node(Op_StrEquals, receiver_start, receiver_cnt, argument_start, argument_cnt);
+ phi->init_req(1, equals);
+ region->init_req(1, control());
+ }
}
// post merge
@@ -1162,20 +1179,9 @@
const int nargs = 2; // number of arguments to push back for uncommon trap in predicate
- 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();
-
- ciInstanceKlass* klass = env()->String_klass();
- const TypeOopPtr* string_type = TypeOopPtr::make_from_klass(klass);
- const TypeAryPtr* source_type = TypeAryPtr::make(TypePtr::NotNull, TypeAry::make(TypeInt::CHAR,TypeInt::POS), ciTypeArrayKlass::make(T_CHAR), true, 0);
-
- Node* sourceOffseta = basic_plus_adr(string_object, string_object, offset_offset);
- Node* sourceOffset = make_load(no_ctrl, sourceOffseta, TypeInt::INT, T_INT, string_type->add_offset(offset_offset));
- Node* sourceCounta = basic_plus_adr(string_object, string_object, count_offset);
- Node* sourceCount = make_load(no_ctrl, sourceCounta, TypeInt::INT, T_INT, string_type->add_offset(count_offset));
- Node* sourcea = basic_plus_adr(string_object, string_object, value_offset);
- Node* source = make_load(no_ctrl, sourcea, source_type, T_OBJECT, string_type->add_offset(value_offset));
+ Node* source = load_String_value(no_ctrl, string_object);
+ Node* sourceOffset = load_String_offset(no_ctrl, string_object);
+ Node* sourceCount = load_String_length(no_ctrl, string_object);
Node* target = _gvn.transform( makecon(TypeOopPtr::make_from_constant(target_array, true)) );
jint target_length = target_array->length();
@@ -1243,10 +1249,6 @@
//------------------------------inline_string_indexOf------------------------
bool LibraryCallKit::inline_string_indexOf() {
- 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();
@@ -1280,12 +1282,21 @@
Node* result_phi = new (C, 4) PhiNode(result_rgn, TypeInt::INT);
Node* no_ctrl = NULL;
- // 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));
+ // Get start addr of source string
+ Node* source = load_String_value(no_ctrl, receiver);
+ Node* source_offset = load_String_offset(no_ctrl, receiver);
+ Node* source_start = array_element_address(source, source_offset, T_CHAR);
+
+ // Get length of source string
+ Node* source_cnt = load_String_length(no_ctrl, receiver);
+
+ // Get start addr of substring
+ Node* substr = load_String_value(no_ctrl, argument);
+ Node* substr_offset = load_String_offset(no_ctrl, argument);
+ Node* substr_start = array_element_address(substr, substr_offset, T_CHAR);
+
+ // Get length of source string
+ Node* substr_cnt = load_String_length(no_ctrl, argument);
// Check for substr count > string count
Node* cmp = _gvn.transform( new(C, 3) CmpINode(substr_cnt, source_cnt) );
@@ -1308,7 +1319,7 @@
}
if (!stopped()) {
- result = make_string_method_node(Op_StrIndexOf, receiver, source_cnt, argument, substr_cnt);
+ result = make_string_method_node(Op_StrIndexOf, source_start, source_cnt, substr_start, substr_cnt);
result_phi->init_req(1, result);
result_rgn->init_req(1, control());
}
@@ -1333,11 +1344,19 @@
ciInstance* str = str_const->as_instance();
assert(str != NULL, "must be instance");
- ciObject* v = str->field_value_by_offset(value_offset).as_object();
- int o = str->field_value_by_offset(offset_offset).as_int();
- int c = str->field_value_by_offset(count_offset).as_int();
+ ciObject* v = str->field_value_by_offset(java_lang_String::value_offset_in_bytes()).as_object();
ciTypeArray* pat = v->as_type_array(); // pattern (argument) character array
+ int o;
+ int c;
+ if (java_lang_String::has_offset_field()) {
+ o = str->field_value_by_offset(java_lang_String::offset_offset_in_bytes()).as_int();
+ c = str->field_value_by_offset(java_lang_String::count_offset_in_bytes()).as_int();
+ } else {
+ o = 0;
+ c = pat->length();
+ }
+
// constant strings have no offset and count == length which
// simplifies the resulting code somewhat so lets optimize for that.
if (o != 0 || c != pat->length()) {