1.1 --- a/src/share/vm/opto/stringopts.cpp Fri Jun 22 10:40:48 2012 -0700 1.2 +++ b/src/share/vm/opto/stringopts.cpp Tue Jun 26 09:06:16 2012 -0700 1.3 @@ -112,6 +112,7 @@ 1.4 _arguments->ins_req(0, value); 1.5 _mode.insert_before(0, mode); 1.6 } 1.7 + 1.8 void push_string(Node* value) { 1.9 push(value, StringMode); 1.10 } 1.11 @@ -125,9 +126,56 @@ 1.12 push(value, CharMode); 1.13 } 1.14 1.15 + static bool is_SB_toString(Node* call) { 1.16 + if (call->is_CallStaticJava()) { 1.17 + CallStaticJavaNode* csj = call->as_CallStaticJava(); 1.18 + ciMethod* m = csj->method(); 1.19 + if (m != NULL && 1.20 + (m->intrinsic_id() == vmIntrinsics::_StringBuilder_toString || 1.21 + m->intrinsic_id() == vmIntrinsics::_StringBuffer_toString)) { 1.22 + return true; 1.23 + } 1.24 + } 1.25 + return false; 1.26 + } 1.27 + 1.28 + static Node* skip_string_null_check(Node* value) { 1.29 + // Look for a diamond shaped Null check of toString() result 1.30 + // (could be code from String.valueOf()): 1.31 + // (Proj == NULL) ? "null":"CastPP(Proj)#NotNULL 1.32 + if (value->is_Phi()) { 1.33 + int true_path = value->as_Phi()->is_diamond_phi(); 1.34 + if (true_path != 0) { 1.35 + // phi->region->if_proj->ifnode->bool 1.36 + BoolNode* b = value->in(0)->in(1)->in(0)->in(1)->as_Bool(); 1.37 + Node* cmp = b->in(1); 1.38 + Node* v1 = cmp->in(1); 1.39 + Node* v2 = cmp->in(2); 1.40 + // Null check of the return of toString which can simply be skipped. 1.41 + if (b->_test._test == BoolTest::ne && 1.42 + v2->bottom_type() == TypePtr::NULL_PTR && 1.43 + value->in(true_path)->Opcode() == Op_CastPP && 1.44 + value->in(true_path)->in(1) == v1 && 1.45 + v1->is_Proj() && is_SB_toString(v1->in(0))) { 1.46 + return v1; 1.47 + } 1.48 + } 1.49 + } 1.50 + return value; 1.51 + } 1.52 + 1.53 Node* argument(int i) { 1.54 return _arguments->in(i); 1.55 } 1.56 + Node* argument_uncast(int i) { 1.57 + Node* arg = argument(i); 1.58 + int amode = mode(i); 1.59 + if (amode == StringConcat::StringMode || 1.60 + amode == StringConcat::StringNullCheckMode) { 1.61 + arg = skip_string_null_check(arg); 1.62 + } 1.63 + return arg; 1.64 + } 1.65 void set_argument(int i, Node* value) { 1.66 _arguments->set_req(i, value); 1.67 } 1.68 @@ -206,9 +254,11 @@ 1.69 1.70 1.71 void StringConcat::eliminate_unneeded_control() { 1.72 - eliminate_initialize(begin()->initialization()); 1.73 for (uint i = 0; i < _control.size(); i++) { 1.74 Node* n = _control.at(i); 1.75 + if (n->is_Allocate()) { 1.76 + eliminate_initialize(n->as_Allocate()->initialization()); 1.77 + } 1.78 if (n->is_Call()) { 1.79 if (n != _end) { 1.80 eliminate_call(n->as_Call()); 1.81 @@ -239,14 +289,15 @@ 1.82 assert(result->_control.contains(other->_end), "what?"); 1.83 assert(result->_control.contains(_begin), "what?"); 1.84 for (int x = 0; x < num_arguments(); x++) { 1.85 - if (argument(x) == arg) { 1.86 + Node* argx = argument_uncast(x); 1.87 + if (argx == arg) { 1.88 // replace the toString result with the all the arguments that 1.89 // made up the other StringConcat 1.90 for (int y = 0; y < other->num_arguments(); y++) { 1.91 result->append(other->argument(y), other->mode(y)); 1.92 } 1.93 } else { 1.94 - result->append(argument(x), mode(x)); 1.95 + result->append(argx, mode(x)); 1.96 } 1.97 } 1.98 result->set_allocation(other->_begin); 1.99 @@ -327,14 +378,9 @@ 1.100 1.101 while (worklist.size() > 0) { 1.102 Node* ctrl = worklist.pop(); 1.103 - if (ctrl->is_CallStaticJava()) { 1.104 + if (StringConcat::is_SB_toString(ctrl)) { 1.105 CallStaticJavaNode* csj = ctrl->as_CallStaticJava(); 1.106 - ciMethod* m = csj->method(); 1.107 - if (m != NULL && 1.108 - (m->intrinsic_id() == vmIntrinsics::_StringBuffer_toString || 1.109 - m->intrinsic_id() == vmIntrinsics::_StringBuilder_toString)) { 1.110 - string_calls.push(csj); 1.111 - } 1.112 + string_calls.push(csj); 1.113 } 1.114 if (ctrl->in(0) != NULL && !_visited.test_set(ctrl->in(0)->_idx)) { 1.115 worklist.push(ctrl->in(0)); 1.116 @@ -550,44 +596,40 @@ 1.117 for (int c = 0; c < concats.length(); c++) { 1.118 StringConcat* sc = concats.at(c); 1.119 for (int i = 0; i < sc->num_arguments(); i++) { 1.120 - Node* arg = sc->argument(i); 1.121 - if (arg->is_Proj() && arg->in(0)->is_CallStaticJava()) { 1.122 + Node* arg = sc->argument_uncast(i); 1.123 + if (arg->is_Proj() && StringConcat::is_SB_toString(arg->in(0))) { 1.124 CallStaticJavaNode* csj = arg->in(0)->as_CallStaticJava(); 1.125 - if (csj->method() != NULL && 1.126 - (csj->method()->intrinsic_id() == vmIntrinsics::_StringBuilder_toString || 1.127 - csj->method()->intrinsic_id() == vmIntrinsics::_StringBuffer_toString)) { 1.128 - for (int o = 0; o < concats.length(); o++) { 1.129 - if (c == o) continue; 1.130 - StringConcat* other = concats.at(o); 1.131 - if (other->end() == csj) { 1.132 + for (int o = 0; o < concats.length(); o++) { 1.133 + if (c == o) continue; 1.134 + StringConcat* other = concats.at(o); 1.135 + if (other->end() == csj) { 1.136 +#ifndef PRODUCT 1.137 + if (PrintOptimizeStringConcat) { 1.138 + tty->print_cr("considering stacked concats"); 1.139 + } 1.140 +#endif 1.141 + 1.142 + StringConcat* merged = sc->merge(other, arg); 1.143 + if (merged->validate_control_flow()) { 1.144 #ifndef PRODUCT 1.145 if (PrintOptimizeStringConcat) { 1.146 - tty->print_cr("considering stacked concats"); 1.147 + tty->print_cr("stacking would succeed"); 1.148 } 1.149 #endif 1.150 - 1.151 - StringConcat* merged = sc->merge(other, arg); 1.152 - if (merged->validate_control_flow()) { 1.153 + if (c < o) { 1.154 + concats.remove_at(o); 1.155 + concats.at_put(c, merged); 1.156 + } else { 1.157 + concats.remove_at(c); 1.158 + concats.at_put(o, merged); 1.159 + } 1.160 + goto restart; 1.161 + } else { 1.162 #ifndef PRODUCT 1.163 - if (PrintOptimizeStringConcat) { 1.164 - tty->print_cr("stacking would succeed"); 1.165 - } 1.166 + if (PrintOptimizeStringConcat) { 1.167 + tty->print_cr("stacking would fail"); 1.168 + } 1.169 #endif 1.170 - if (c < o) { 1.171 - concats.remove_at(o); 1.172 - concats.at_put(c, merged); 1.173 - } else { 1.174 - concats.remove_at(c); 1.175 - concats.at_put(o, merged); 1.176 - } 1.177 - goto restart; 1.178 - } else { 1.179 -#ifndef PRODUCT 1.180 - if (PrintOptimizeStringConcat) { 1.181 - tty->print_cr("stacking would fail"); 1.182 - } 1.183 -#endif 1.184 - } 1.185 } 1.186 } 1.187 }