hotspot/src/share/vm/opto/library_call.cpp
changeset 12623 09fcb0dc71ad
parent 12377 ae6def2813e0
child 12739 09f26b73ae66
--- 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()) {