src/share/vm/opto/library_call.cpp

changeset 1116
fbde8ec322d0
parent 1078
c771b7f43bbf
child 1165
9c6be3edf0dc
     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  }

mercurial