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