src/share/vm/opto/stringopts.cpp
Index Unified diffs Context diffs Sdiffs Wdiffs Patch New Old Previous File Next File
*** old/src/share/vm/opto/stringopts.cpp	Mon Jun 25 15:52:12 2012
--- new/src/share/vm/opto/stringopts.cpp	Mon Jun 25 15:52:11 2012

*** 110,119 **** --- 110,120 ---- } void push(Node* value, int mode) { _arguments->ins_req(0, value); _mode.insert_before(0, mode); } + void push_string(Node* value) { push(value, StringMode); } void push_string_null_check(Node* value) { push(value, StringNullCheckMode);
*** 123,135 **** --- 124,183 ---- } void push_char(Node* value) { push(value, CharMode); } + static bool is_SB_toString(Node* call) { + if (call->is_CallStaticJava()) { + CallStaticJavaNode* csj = call->as_CallStaticJava(); + ciMethod* m = csj->method(); + if (m != NULL && + (m->intrinsic_id() == vmIntrinsics::_StringBuilder_toString || + m->intrinsic_id() == vmIntrinsics::_StringBuffer_toString)) { + return true; + } + } + return false; + } + + static Node* skip_string_null_check(Node* value) { + // Look for a diamond shaped Null check of toString() result + // (could be code from String.valueOf()): + // (Proj == NULL) ? "null":"CastPP(Proj)#NotNULL + if (value->is_Phi()) { + int true_path = value->as_Phi()->is_diamond_phi(); + if (true_path != 0) { + // phi->region->if_proj->ifnode->bool + BoolNode* b = value->in(0)->in(1)->in(0)->in(1)->as_Bool(); + Node* cmp = b->in(1); + Node* v1 = cmp->in(1); + Node* v2 = cmp->in(2); + // Null check of the return of toString which can simply be skipped. + if (b->_test._test == BoolTest::ne && + v2->bottom_type() == TypePtr::NULL_PTR && + value->in(true_path)->Opcode() == Op_CastPP && + value->in(true_path)->in(1) == v1 && + v1->is_Proj() && is_SB_toString(v1->in(0))) { + value = v1; + } + } + } + return value; + } + Node* argument(int i) { return _arguments->in(i); } + Node* argument_uncast(int i) { + Node* arg = argument(i); + int amode = mode(i); + if (amode == StringConcat::StringMode || + amode == StringConcat::StringNullCheckMode) { + arg = skip_string_null_check(arg); + } + return arg; + } void set_argument(int i, Node* value) { _arguments->set_req(i, value); } int num_arguments() { return _mode.length();
*** 204,216 **** --- 252,266 ---- } }; void StringConcat::eliminate_unneeded_control() { eliminate_initialize(begin()->initialization()); for (uint i = 0; i < _control.size(); i++) { Node* n = _control.at(i); + if (n->is_Allocate()) { + eliminate_initialize(n->as_Allocate()->initialization()); + } if (n->is_Call()) { if (n != _end) { eliminate_call(n->as_Call()); } } else if (n->is_IfTrue()) {
*** 237,254 **** --- 287,305 ---- } } assert(result->_control.contains(other->_end), "what?"); assert(result->_control.contains(_begin), "what?"); for (int x = 0; x < num_arguments(); x++) { if (argument(x) == arg) { + Node* argx = argument_uncast(x); + if (argx == arg) { // replace the toString result with the all the arguments that // made up the other StringConcat for (int y = 0; y < other->num_arguments(); y++) { result->append(other->argument(y), other->mode(y)); } } else { ! result->append(argument(x), mode(x)); ! result->append(argx, mode(x)); } } result->set_allocation(other->_begin); result->_multiple = true; return result;
*** 325,343 **** --- 376,389 ---- } } while (worklist.size() > 0) { Node* ctrl = worklist.pop(); ! if (ctrl->is_CallStaticJava()) { ! if (StringConcat::is_SB_toString(ctrl)) { CallStaticJavaNode* csj = ctrl->as_CallStaticJava(); ciMethod* m = csj->method(); if (m != NULL && (m->intrinsic_id() == vmIntrinsics::_StringBuffer_toString || m->intrinsic_id() == vmIntrinsics::_StringBuilder_toString)) { string_calls.push(csj); } } if (ctrl->in(0) != NULL && !_visited.test_set(ctrl->in(0)->_idx)) { worklist.push(ctrl->in(0)); } if (ctrl->is_Region()) { for (uint i = 1; i < ctrl->len(); i++) {
*** 548,563 **** --- 594,606 ---- // try to coalesce separate concats restart: for (int c = 0; c < concats.length(); c++) { StringConcat* sc = concats.at(c); for (int i = 0; i < sc->num_arguments(); i++) { ! Node* arg = sc->argument_uncast(i); ! if (arg->is_Proj() && arg->in(0)->is_CallStaticJava()) { ! if (arg->is_Proj() && StringConcat::is_SB_toString(arg->in(0))) { CallStaticJavaNode* csj = arg->in(0)->as_CallStaticJava(); if (csj->method() != NULL && (csj->method()->intrinsic_id() == vmIntrinsics::_StringBuilder_toString || csj->method()->intrinsic_id() == vmIntrinsics::_StringBuffer_toString)) { for (int o = 0; o < concats.length(); o++) { if (c == o) continue; StringConcat* other = concats.at(o); if (other->end() == csj) { #ifndef PRODUCT
*** 587,597 **** --- 630,639 ---- tty->print_cr("stacking would fail"); } #endif } } } } } } }

src/share/vm/opto/stringopts.cpp
Index Unified diffs Context diffs Sdiffs Wdiffs Patch New Old Previous File Next File