1 | /* |
2 | * Copyright (c) 2009, 2018, Oracle and/or its affiliates. All rights reserved. |
3 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
4 | * |
5 | * This code is free software; you can redistribute it and/or modify it |
6 | * under the terms of the GNU General Public License version 2 only, as |
7 | * published by the Free Software Foundation. |
8 | * |
9 | * This code is distributed in the hope that it will be useful, but WITHOUT |
10 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
11 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
12 | * version 2 for more details (a copy is included in the LICENSE file that |
13 | * accompanied this code). |
14 | * |
15 | * You should have received a copy of the GNU General Public License version |
16 | * 2 along with this work; if not, write to the Free Software Foundation, |
17 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
18 | * |
19 | * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
20 | * or visit www.oracle.com if you need additional information or have any |
21 | * questions. |
22 | * |
23 | */ |
24 | |
25 | #include "precompiled.hpp" |
26 | #include "compiler/compileLog.hpp" |
27 | #include "opto/addnode.hpp" |
28 | #include "opto/callGenerator.hpp" |
29 | #include "opto/callnode.hpp" |
30 | #include "opto/divnode.hpp" |
31 | #include "opto/graphKit.hpp" |
32 | #include "opto/idealKit.hpp" |
33 | #include "opto/rootnode.hpp" |
34 | #include "opto/runtime.hpp" |
35 | #include "opto/stringopts.hpp" |
36 | #include "opto/subnode.hpp" |
37 | #include "runtime/sharedRuntime.hpp" |
38 | |
39 | #define __ kit. |
40 | |
41 | class StringConcat : public ResourceObj { |
42 | private: |
43 | PhaseStringOpts* _stringopts; |
44 | Node* _string_alloc; |
45 | AllocateNode* _begin; // The allocation the begins the pattern |
46 | CallStaticJavaNode* _end; // The final call of the pattern. Will either be |
47 | // SB.toString or or String.<init>(SB.toString) |
48 | bool _multiple; // indicates this is a fusion of two or more |
49 | // separate StringBuilders |
50 | |
51 | Node* _arguments; // The list of arguments to be concatenated |
52 | GrowableArray<int> _mode; // into a String along with a mode flag |
53 | // indicating how to treat the value. |
54 | Node_List _constructors; // List of constructors (many in case of stacked concat) |
55 | Node_List _control; // List of control nodes that will be deleted |
56 | Node_List _uncommon_traps; // Uncommon traps that needs to be rewritten |
57 | // to restart at the initial JVMState. |
58 | |
59 | public: |
60 | // Mode for converting arguments to Strings |
61 | enum { |
62 | StringMode, |
63 | IntMode, |
64 | CharMode, |
65 | StringNullCheckMode |
66 | }; |
67 | |
68 | StringConcat(PhaseStringOpts* stringopts, CallStaticJavaNode* end): |
69 | _stringopts(stringopts), |
70 | _string_alloc(NULL), |
71 | _begin(NULL), |
72 | _end(end), |
73 | _multiple(false) { |
74 | _arguments = new Node(1); |
75 | _arguments->del_req(0); |
76 | } |
77 | |
78 | bool validate_mem_flow(); |
79 | bool validate_control_flow(); |
80 | |
81 | void merge_add() { |
82 | #if 0 |
83 | // XXX This is place holder code for reusing an existing String |
84 | // allocation but the logic for checking the state safety is |
85 | // probably inadequate at the moment. |
86 | CallProjections endprojs; |
87 | sc->end()->extract_projections(&endprojs, false); |
88 | if (endprojs.resproj != NULL) { |
89 | for (SimpleDUIterator i(endprojs.resproj); i.has_next(); i.next()) { |
90 | CallStaticJavaNode *use = i.get()->isa_CallStaticJava(); |
91 | if (use != NULL && use->method() != NULL && |
92 | use->method()->intrinsic_id() == vmIntrinsics::_String_String && |
93 | use->in(TypeFunc::Parms + 1) == endprojs.resproj) { |
94 | // Found useless new String(sb.toString()) so reuse the newly allocated String |
95 | // when creating the result instead of allocating a new one. |
96 | sc->set_string_alloc(use->in(TypeFunc::Parms)); |
97 | sc->set_end(use); |
98 | } |
99 | } |
100 | } |
101 | #endif |
102 | } |
103 | |
104 | StringConcat* merge(StringConcat* other, Node* arg); |
105 | |
106 | void set_allocation(AllocateNode* alloc) { |
107 | _begin = alloc; |
108 | } |
109 | |
110 | void append(Node* value, int mode) { |
111 | _arguments->add_req(value); |
112 | _mode.append(mode); |
113 | } |
114 | void push(Node* value, int mode) { |
115 | _arguments->ins_req(0, value); |
116 | _mode.insert_before(0, mode); |
117 | } |
118 | |
119 | void push_string(Node* value) { |
120 | push(value, StringMode); |
121 | } |
122 | void push_string_null_check(Node* value) { |
123 | push(value, StringNullCheckMode); |
124 | } |
125 | void push_int(Node* value) { |
126 | push(value, IntMode); |
127 | } |
128 | void push_char(Node* value) { |
129 | push(value, CharMode); |
130 | } |
131 | |
132 | static bool is_SB_toString(Node* call) { |
133 | if (call->is_CallStaticJava()) { |
134 | CallStaticJavaNode* csj = call->as_CallStaticJava(); |
135 | ciMethod* m = csj->method(); |
136 | if (m != NULL && |
137 | (m->intrinsic_id() == vmIntrinsics::_StringBuilder_toString || |
138 | m->intrinsic_id() == vmIntrinsics::_StringBuffer_toString)) { |
139 | return true; |
140 | } |
141 | } |
142 | return false; |
143 | } |
144 | |
145 | static Node* skip_string_null_check(Node* value) { |
146 | // Look for a diamond shaped Null check of toString() result |
147 | // (could be code from String.valueOf()): |
148 | // (Proj == NULL) ? "null":"CastPP(Proj)#NotNULL |
149 | if (value->is_Phi()) { |
150 | int true_path = value->as_Phi()->is_diamond_phi(); |
151 | if (true_path != 0) { |
152 | // phi->region->if_proj->ifnode->bool |
153 | BoolNode* b = value->in(0)->in(1)->in(0)->in(1)->as_Bool(); |
154 | Node* cmp = b->in(1); |
155 | Node* v1 = cmp->in(1); |
156 | Node* v2 = cmp->in(2); |
157 | // Null check of the return of toString which can simply be skipped. |
158 | if (b->_test._test == BoolTest::ne && |
159 | v2->bottom_type() == TypePtr::NULL_PTR && |
160 | value->in(true_path)->Opcode() == Op_CastPP && |
161 | value->in(true_path)->in(1) == v1 && |
162 | v1->is_Proj() && is_SB_toString(v1->in(0))) { |
163 | return v1; |
164 | } |
165 | } |
166 | } |
167 | return value; |
168 | } |
169 | |
170 | Node* argument(int i) { |
171 | return _arguments->in(i); |
172 | } |
173 | Node* argument_uncast(int i) { |
174 | Node* arg = argument(i); |
175 | int amode = mode(i); |
176 | if (amode == StringConcat::StringMode || |
177 | amode == StringConcat::StringNullCheckMode) { |
178 | arg = skip_string_null_check(arg); |
179 | } |
180 | return arg; |
181 | } |
182 | void set_argument(int i, Node* value) { |
183 | _arguments->set_req(i, value); |
184 | } |
185 | int num_arguments() { |
186 | return _mode.length(); |
187 | } |
188 | int mode(int i) { |
189 | return _mode.at(i); |
190 | } |
191 | void add_control(Node* ctrl) { |
192 | assert(!_control.contains(ctrl), "only push once" ); |
193 | _control.push(ctrl); |
194 | } |
195 | void add_constructor(Node* init) { |
196 | assert(!_constructors.contains(init), "only push once" ); |
197 | _constructors.push(init); |
198 | } |
199 | CallStaticJavaNode* end() { return _end; } |
200 | AllocateNode* begin() { return _begin; } |
201 | Node* string_alloc() { return _string_alloc; } |
202 | |
203 | void eliminate_unneeded_control(); |
204 | void eliminate_initialize(InitializeNode* init); |
205 | void eliminate_call(CallNode* call); |
206 | |
207 | void maybe_log_transform() { |
208 | CompileLog* log = _stringopts->C->log(); |
209 | if (log != NULL) { |
210 | log->head("replace_string_concat arguments='%d' string_alloc='%d' multiple='%d'" , |
211 | num_arguments(), |
212 | _string_alloc != NULL, |
213 | _multiple); |
214 | JVMState* p = _begin->jvms(); |
215 | while (p != NULL) { |
216 | log->elem("jvms bci='%d' method='%d'" , p->bci(), log->identify(p->method())); |
217 | p = p->caller(); |
218 | } |
219 | log->tail("replace_string_concat" ); |
220 | } |
221 | } |
222 | |
223 | void convert_uncommon_traps(GraphKit& kit, const JVMState* jvms) { |
224 | for (uint u = 0; u < _uncommon_traps.size(); u++) { |
225 | Node* uct = _uncommon_traps.at(u); |
226 | |
227 | // Build a new call using the jvms state of the allocate |
228 | address call_addr = SharedRuntime::uncommon_trap_blob()->entry_point(); |
229 | const TypeFunc* call_type = OptoRuntime::uncommon_trap_Type(); |
230 | const TypePtr* no_memory_effects = NULL; |
231 | Compile* C = _stringopts->C; |
232 | CallStaticJavaNode* call = new CallStaticJavaNode(call_type, call_addr, "uncommon_trap" , |
233 | jvms->bci(), no_memory_effects); |
234 | for (int e = 0; e < TypeFunc::Parms; e++) { |
235 | call->init_req(e, uct->in(e)); |
236 | } |
237 | // Set the trap request to record intrinsic failure if this trap |
238 | // is taken too many times. Ideally we would handle then traps by |
239 | // doing the original bookkeeping in the MDO so that if it caused |
240 | // the code to be thrown out we could still recompile and use the |
241 | // optimization. Failing the uncommon traps doesn't really mean |
242 | // that the optimization is a bad idea but there's no other way to |
243 | // do the MDO updates currently. |
244 | int trap_request = Deoptimization::make_trap_request(Deoptimization::Reason_intrinsic, |
245 | Deoptimization::Action_make_not_entrant); |
246 | call->init_req(TypeFunc::Parms, __ intcon(trap_request)); |
247 | kit.add_safepoint_edges(call); |
248 | |
249 | _stringopts->gvn()->transform(call); |
250 | C->gvn_replace_by(uct, call); |
251 | uct->disconnect_inputs(NULL, C); |
252 | } |
253 | } |
254 | |
255 | void cleanup() { |
256 | // disconnect the hook node |
257 | _arguments->disconnect_inputs(NULL, _stringopts->C); |
258 | } |
259 | }; |
260 | |
261 | |
262 | void StringConcat::eliminate_unneeded_control() { |
263 | for (uint i = 0; i < _control.size(); i++) { |
264 | Node* n = _control.at(i); |
265 | if (n->is_Allocate()) { |
266 | eliminate_initialize(n->as_Allocate()->initialization()); |
267 | } |
268 | if (n->is_Call()) { |
269 | if (n != _end) { |
270 | eliminate_call(n->as_Call()); |
271 | } |
272 | } else if (n->is_IfTrue()) { |
273 | Compile* C = _stringopts->C; |
274 | C->gvn_replace_by(n, n->in(0)->in(0)); |
275 | // get rid of the other projection |
276 | C->gvn_replace_by(n->in(0)->as_If()->proj_out(false), C->top()); |
277 | } |
278 | } |
279 | } |
280 | |
281 | |
282 | StringConcat* StringConcat::merge(StringConcat* other, Node* arg) { |
283 | StringConcat* result = new StringConcat(_stringopts, _end); |
284 | for (uint x = 0; x < _control.size(); x++) { |
285 | Node* n = _control.at(x); |
286 | if (n->is_Call()) { |
287 | result->_control.push(n); |
288 | } |
289 | } |
290 | for (uint x = 0; x < other->_control.size(); x++) { |
291 | Node* n = other->_control.at(x); |
292 | if (n->is_Call()) { |
293 | result->_control.push(n); |
294 | } |
295 | } |
296 | assert(result->_control.contains(other->_end), "what?" ); |
297 | assert(result->_control.contains(_begin), "what?" ); |
298 | for (int x = 0; x < num_arguments(); x++) { |
299 | Node* argx = argument_uncast(x); |
300 | if (argx == arg) { |
301 | // replace the toString result with the all the arguments that |
302 | // made up the other StringConcat |
303 | for (int y = 0; y < other->num_arguments(); y++) { |
304 | result->append(other->argument(y), other->mode(y)); |
305 | } |
306 | } else { |
307 | result->append(argx, mode(x)); |
308 | } |
309 | } |
310 | result->set_allocation(other->_begin); |
311 | for (uint i = 0; i < _constructors.size(); i++) { |
312 | result->add_constructor(_constructors.at(i)); |
313 | } |
314 | for (uint i = 0; i < other->_constructors.size(); i++) { |
315 | result->add_constructor(other->_constructors.at(i)); |
316 | } |
317 | result->_multiple = true; |
318 | return result; |
319 | } |
320 | |
321 | |
322 | void StringConcat::eliminate_call(CallNode* call) { |
323 | Compile* C = _stringopts->C; |
324 | CallProjections projs; |
325 | call->extract_projections(&projs, false); |
326 | if (projs.fallthrough_catchproj != NULL) { |
327 | C->gvn_replace_by(projs.fallthrough_catchproj, call->in(TypeFunc::Control)); |
328 | } |
329 | if (projs.fallthrough_memproj != NULL) { |
330 | C->gvn_replace_by(projs.fallthrough_memproj, call->in(TypeFunc::Memory)); |
331 | } |
332 | if (projs.catchall_memproj != NULL) { |
333 | C->gvn_replace_by(projs.catchall_memproj, C->top()); |
334 | } |
335 | if (projs.fallthrough_ioproj != NULL) { |
336 | C->gvn_replace_by(projs.fallthrough_ioproj, call->in(TypeFunc::I_O)); |
337 | } |
338 | if (projs.catchall_ioproj != NULL) { |
339 | C->gvn_replace_by(projs.catchall_ioproj, C->top()); |
340 | } |
341 | if (projs.catchall_catchproj != NULL) { |
342 | // EA can't cope with the partially collapsed graph this |
343 | // creates so put it on the worklist to be collapsed later. |
344 | for (SimpleDUIterator i(projs.catchall_catchproj); i.has_next(); i.next()) { |
345 | Node *use = i.get(); |
346 | int opc = use->Opcode(); |
347 | if (opc == Op_CreateEx || opc == Op_Region) { |
348 | _stringopts->record_dead_node(use); |
349 | } |
350 | } |
351 | C->gvn_replace_by(projs.catchall_catchproj, C->top()); |
352 | } |
353 | if (projs.resproj != NULL) { |
354 | C->gvn_replace_by(projs.resproj, C->top()); |
355 | } |
356 | C->gvn_replace_by(call, C->top()); |
357 | } |
358 | |
359 | void StringConcat::eliminate_initialize(InitializeNode* init) { |
360 | Compile* C = _stringopts->C; |
361 | |
362 | // Eliminate Initialize node. |
363 | assert(init->outcnt() <= 2, "only a control and memory projection expected" ); |
364 | assert(init->req() <= InitializeNode::RawStores, "no pending inits" ); |
365 | Node *ctrl_proj = init->proj_out_or_null(TypeFunc::Control); |
366 | if (ctrl_proj != NULL) { |
367 | C->gvn_replace_by(ctrl_proj, init->in(TypeFunc::Control)); |
368 | } |
369 | Node *mem_proj = init->proj_out_or_null(TypeFunc::Memory); |
370 | if (mem_proj != NULL) { |
371 | Node *mem = init->in(TypeFunc::Memory); |
372 | C->gvn_replace_by(mem_proj, mem); |
373 | } |
374 | C->gvn_replace_by(init, C->top()); |
375 | init->disconnect_inputs(NULL, C); |
376 | } |
377 | |
378 | Node_List PhaseStringOpts::collect_toString_calls() { |
379 | Node_List string_calls; |
380 | Node_List worklist; |
381 | |
382 | _visited.Clear(); |
383 | |
384 | // Prime the worklist |
385 | for (uint i = 1; i < C->root()->len(); i++) { |
386 | Node* n = C->root()->in(i); |
387 | if (n != NULL && !_visited.test_set(n->_idx)) { |
388 | worklist.push(n); |
389 | } |
390 | } |
391 | |
392 | while (worklist.size() > 0) { |
393 | Node* ctrl = worklist.pop(); |
394 | if (StringConcat::is_SB_toString(ctrl)) { |
395 | CallStaticJavaNode* csj = ctrl->as_CallStaticJava(); |
396 | string_calls.push(csj); |
397 | } |
398 | if (ctrl->in(0) != NULL && !_visited.test_set(ctrl->in(0)->_idx)) { |
399 | worklist.push(ctrl->in(0)); |
400 | } |
401 | if (ctrl->is_Region()) { |
402 | for (uint i = 1; i < ctrl->len(); i++) { |
403 | if (ctrl->in(i) != NULL && !_visited.test_set(ctrl->in(i)->_idx)) { |
404 | worklist.push(ctrl->in(i)); |
405 | } |
406 | } |
407 | } |
408 | } |
409 | return string_calls; |
410 | } |
411 | |
412 | |
413 | StringConcat* PhaseStringOpts::build_candidate(CallStaticJavaNode* call) { |
414 | ciMethod* m = call->method(); |
415 | ciSymbol* string_sig; |
416 | ciSymbol* int_sig; |
417 | ciSymbol* char_sig; |
418 | if (m->holder() == C->env()->StringBuilder_klass()) { |
419 | string_sig = ciSymbol::String_StringBuilder_signature(); |
420 | int_sig = ciSymbol::int_StringBuilder_signature(); |
421 | char_sig = ciSymbol::char_StringBuilder_signature(); |
422 | } else if (m->holder() == C->env()->StringBuffer_klass()) { |
423 | string_sig = ciSymbol::String_StringBuffer_signature(); |
424 | int_sig = ciSymbol::int_StringBuffer_signature(); |
425 | char_sig = ciSymbol::char_StringBuffer_signature(); |
426 | } else { |
427 | return NULL; |
428 | } |
429 | #ifndef PRODUCT |
430 | if (PrintOptimizeStringConcat) { |
431 | tty->print("considering toString call in " ); |
432 | call->jvms()->dump_spec(tty); tty->cr(); |
433 | } |
434 | #endif |
435 | |
436 | StringConcat* sc = new StringConcat(this, call); |
437 | |
438 | AllocateNode* alloc = NULL; |
439 | InitializeNode* init = NULL; |
440 | |
441 | // possible opportunity for StringBuilder fusion |
442 | CallStaticJavaNode* cnode = call; |
443 | while (cnode) { |
444 | Node* recv = cnode->in(TypeFunc::Parms)->uncast(); |
445 | if (recv->is_Proj()) { |
446 | recv = recv->in(0); |
447 | } |
448 | cnode = recv->isa_CallStaticJava(); |
449 | if (cnode == NULL) { |
450 | alloc = recv->isa_Allocate(); |
451 | if (alloc == NULL) { |
452 | break; |
453 | } |
454 | // Find the constructor call |
455 | Node* result = alloc->result_cast(); |
456 | if (result == NULL || !result->is_CheckCastPP() || alloc->in(TypeFunc::Memory)->is_top()) { |
457 | // strange looking allocation |
458 | #ifndef PRODUCT |
459 | if (PrintOptimizeStringConcat) { |
460 | tty->print("giving up because allocation looks strange " ); |
461 | alloc->jvms()->dump_spec(tty); tty->cr(); |
462 | } |
463 | #endif |
464 | break; |
465 | } |
466 | Node* constructor = NULL; |
467 | for (SimpleDUIterator i(result); i.has_next(); i.next()) { |
468 | CallStaticJavaNode *use = i.get()->isa_CallStaticJava(); |
469 | if (use != NULL && |
470 | use->method() != NULL && |
471 | !use->method()->is_static() && |
472 | use->method()->name() == ciSymbol::object_initializer_name() && |
473 | use->method()->holder() == m->holder()) { |
474 | // Matched the constructor. |
475 | ciSymbol* sig = use->method()->signature()->as_symbol(); |
476 | if (sig == ciSymbol::void_method_signature() || |
477 | sig == ciSymbol::int_void_signature() || |
478 | sig == ciSymbol::string_void_signature()) { |
479 | if (sig == ciSymbol::string_void_signature()) { |
480 | // StringBuilder(String) so pick this up as the first argument |
481 | assert(use->in(TypeFunc::Parms + 1) != NULL, "what?" ); |
482 | const Type* type = _gvn->type(use->in(TypeFunc::Parms + 1)); |
483 | if (type == TypePtr::NULL_PTR) { |
484 | // StringBuilder(null) throws exception. |
485 | #ifndef PRODUCT |
486 | if (PrintOptimizeStringConcat) { |
487 | tty->print("giving up because StringBuilder(null) throws exception" ); |
488 | alloc->jvms()->dump_spec(tty); tty->cr(); |
489 | } |
490 | #endif |
491 | return NULL; |
492 | } |
493 | // StringBuilder(str) argument needs null check. |
494 | sc->push_string_null_check(use->in(TypeFunc::Parms + 1)); |
495 | } |
496 | // The int variant takes an initial size for the backing |
497 | // array so just treat it like the void version. |
498 | constructor = use; |
499 | } else { |
500 | #ifndef PRODUCT |
501 | if (PrintOptimizeStringConcat) { |
502 | tty->print("unexpected constructor signature: %s" , sig->as_utf8()); |
503 | } |
504 | #endif |
505 | } |
506 | break; |
507 | } |
508 | } |
509 | if (constructor == NULL) { |
510 | // couldn't find constructor |
511 | #ifndef PRODUCT |
512 | if (PrintOptimizeStringConcat) { |
513 | tty->print("giving up because couldn't find constructor " ); |
514 | alloc->jvms()->dump_spec(tty); tty->cr(); |
515 | } |
516 | #endif |
517 | break; |
518 | } |
519 | |
520 | // Walked all the way back and found the constructor call so see |
521 | // if this call converted into a direct string concatenation. |
522 | sc->add_control(call); |
523 | sc->add_control(constructor); |
524 | sc->add_control(alloc); |
525 | sc->set_allocation(alloc); |
526 | sc->add_constructor(constructor); |
527 | if (sc->validate_control_flow() && sc->validate_mem_flow()) { |
528 | return sc; |
529 | } else { |
530 | return NULL; |
531 | } |
532 | } else if (cnode->method() == NULL) { |
533 | break; |
534 | } else if (!cnode->method()->is_static() && |
535 | cnode->method()->holder() == m->holder() && |
536 | cnode->method()->name() == ciSymbol::append_name() && |
537 | (cnode->method()->signature()->as_symbol() == string_sig || |
538 | cnode->method()->signature()->as_symbol() == char_sig || |
539 | cnode->method()->signature()->as_symbol() == int_sig)) { |
540 | sc->add_control(cnode); |
541 | Node* arg = cnode->in(TypeFunc::Parms + 1); |
542 | if (cnode->method()->signature()->as_symbol() == int_sig) { |
543 | sc->push_int(arg); |
544 | } else if (cnode->method()->signature()->as_symbol() == char_sig) { |
545 | sc->push_char(arg); |
546 | } else { |
547 | if (arg->is_Proj() && arg->in(0)->is_CallStaticJava()) { |
548 | CallStaticJavaNode* csj = arg->in(0)->as_CallStaticJava(); |
549 | if (csj->method() != NULL && |
550 | csj->method()->intrinsic_id() == vmIntrinsics::_Integer_toString && |
551 | arg->outcnt() == 1) { |
552 | // _control is the list of StringBuilder calls nodes which |
553 | // will be replaced by new String code after this optimization. |
554 | // Integer::toString() call is not part of StringBuilder calls |
555 | // chain. It could be eliminated only if its result is used |
556 | // only by this SB calls chain. |
557 | // Another limitation: it should be used only once because |
558 | // it is unknown that it is used only by this SB calls chain |
559 | // until all related SB calls nodes are collected. |
560 | assert(arg->unique_out() == cnode, "sanity" ); |
561 | sc->add_control(csj); |
562 | sc->push_int(csj->in(TypeFunc::Parms)); |
563 | continue; |
564 | } |
565 | } |
566 | sc->push_string(arg); |
567 | } |
568 | continue; |
569 | } else { |
570 | // some unhandled signature |
571 | #ifndef PRODUCT |
572 | if (PrintOptimizeStringConcat) { |
573 | tty->print("giving up because encountered unexpected signature " ); |
574 | cnode->tf()->dump(); tty->cr(); |
575 | cnode->in(TypeFunc::Parms + 1)->dump(); |
576 | } |
577 | #endif |
578 | break; |
579 | } |
580 | } |
581 | return NULL; |
582 | } |
583 | |
584 | |
585 | PhaseStringOpts::PhaseStringOpts(PhaseGVN* gvn, Unique_Node_List*): |
586 | Phase(StringOpts), |
587 | _gvn(gvn), |
588 | _visited(Thread::current()->resource_area()) { |
589 | |
590 | assert(OptimizeStringConcat, "shouldn't be here" ); |
591 | |
592 | size_table_field = C->env()->Integer_klass()->get_field_by_name(ciSymbol::make("sizeTable" ), |
593 | ciSymbol::make("[I" ), true); |
594 | if (size_table_field == NULL) { |
595 | // Something wrong so give up. |
596 | assert(false, "why can't we find Integer.sizeTable?" ); |
597 | return; |
598 | } |
599 | |
600 | // Collect the types needed to talk about the various slices of memory |
601 | byte_adr_idx = C->get_alias_index(TypeAryPtr::BYTES); |
602 | |
603 | // For each locally allocated StringBuffer see if the usages can be |
604 | // collapsed into a single String construction. |
605 | |
606 | // Run through the list of allocation looking for SB.toString to see |
607 | // if it's possible to fuse the usage of the SB into a single String |
608 | // construction. |
609 | GrowableArray<StringConcat*> concats; |
610 | Node_List toStrings = collect_toString_calls(); |
611 | while (toStrings.size() > 0) { |
612 | StringConcat* sc = build_candidate(toStrings.pop()->as_CallStaticJava()); |
613 | if (sc != NULL) { |
614 | concats.push(sc); |
615 | } |
616 | } |
617 | |
618 | // try to coalesce separate concats |
619 | restart: |
620 | for (int c = 0; c < concats.length(); c++) { |
621 | StringConcat* sc = concats.at(c); |
622 | for (int i = 0; i < sc->num_arguments(); i++) { |
623 | Node* arg = sc->argument_uncast(i); |
624 | if (arg->is_Proj() && StringConcat::is_SB_toString(arg->in(0))) { |
625 | CallStaticJavaNode* csj = arg->in(0)->as_CallStaticJava(); |
626 | for (int o = 0; o < concats.length(); o++) { |
627 | if (c == o) continue; |
628 | StringConcat* other = concats.at(o); |
629 | if (other->end() == csj) { |
630 | #ifndef PRODUCT |
631 | if (PrintOptimizeStringConcat) { |
632 | tty->print_cr("considering stacked concats" ); |
633 | } |
634 | #endif |
635 | |
636 | StringConcat* merged = sc->merge(other, arg); |
637 | if (merged->validate_control_flow() && merged->validate_mem_flow()) { |
638 | #ifndef PRODUCT |
639 | if (PrintOptimizeStringConcat) { |
640 | tty->print_cr("stacking would succeed" ); |
641 | } |
642 | #endif |
643 | if (c < o) { |
644 | concats.remove_at(o); |
645 | concats.at_put(c, merged); |
646 | } else { |
647 | concats.remove_at(c); |
648 | concats.at_put(o, merged); |
649 | } |
650 | goto restart; |
651 | } else { |
652 | #ifndef PRODUCT |
653 | if (PrintOptimizeStringConcat) { |
654 | tty->print_cr("stacking would fail" ); |
655 | } |
656 | #endif |
657 | } |
658 | } |
659 | } |
660 | } |
661 | } |
662 | } |
663 | |
664 | |
665 | for (int c = 0; c < concats.length(); c++) { |
666 | StringConcat* sc = concats.at(c); |
667 | replace_string_concat(sc); |
668 | } |
669 | |
670 | remove_dead_nodes(); |
671 | } |
672 | |
673 | void PhaseStringOpts::record_dead_node(Node* dead) { |
674 | dead_worklist.push(dead); |
675 | } |
676 | |
677 | void PhaseStringOpts::remove_dead_nodes() { |
678 | // Delete any dead nodes to make things clean enough that escape |
679 | // analysis doesn't get unhappy. |
680 | while (dead_worklist.size() > 0) { |
681 | Node* use = dead_worklist.pop(); |
682 | int opc = use->Opcode(); |
683 | switch (opc) { |
684 | case Op_Region: { |
685 | uint i = 1; |
686 | for (i = 1; i < use->req(); i++) { |
687 | if (use->in(i) != C->top()) { |
688 | break; |
689 | } |
690 | } |
691 | if (i >= use->req()) { |
692 | for (SimpleDUIterator i(use); i.has_next(); i.next()) { |
693 | Node* m = i.get(); |
694 | if (m->is_Phi()) { |
695 | dead_worklist.push(m); |
696 | } |
697 | } |
698 | C->gvn_replace_by(use, C->top()); |
699 | } |
700 | break; |
701 | } |
702 | case Op_AddP: |
703 | case Op_CreateEx: { |
704 | // Recurisvely clean up references to CreateEx so EA doesn't |
705 | // get unhappy about the partially collapsed graph. |
706 | for (SimpleDUIterator i(use); i.has_next(); i.next()) { |
707 | Node* m = i.get(); |
708 | if (m->is_AddP()) { |
709 | dead_worklist.push(m); |
710 | } |
711 | } |
712 | C->gvn_replace_by(use, C->top()); |
713 | break; |
714 | } |
715 | case Op_Phi: |
716 | if (use->in(0) == C->top()) { |
717 | C->gvn_replace_by(use, C->top()); |
718 | } |
719 | break; |
720 | } |
721 | } |
722 | } |
723 | |
724 | |
725 | bool StringConcat::validate_mem_flow() { |
726 | Compile* C = _stringopts->C; |
727 | |
728 | for (uint i = 0; i < _control.size(); i++) { |
729 | #ifndef PRODUCT |
730 | Node_List path; |
731 | #endif |
732 | Node* curr = _control.at(i); |
733 | if (curr->is_Call() && curr != _begin) { // For all calls except the first allocation |
734 | // Now here's the main invariant in our case: |
735 | // For memory between the constructor, and appends, and toString we should only see bottom memory, |
736 | // produced by the previous call we know about. |
737 | if (!_constructors.contains(curr)) { |
738 | NOT_PRODUCT(path.push(curr);) |
739 | Node* mem = curr->in(TypeFunc::Memory); |
740 | assert(mem != NULL, "calls should have memory edge" ); |
741 | assert(!mem->is_Phi(), "should be handled by control flow validation" ); |
742 | NOT_PRODUCT(path.push(mem);) |
743 | while (mem->is_MergeMem()) { |
744 | for (uint i = 1; i < mem->req(); i++) { |
745 | if (i != Compile::AliasIdxBot && mem->in(i) != C->top()) { |
746 | #ifndef PRODUCT |
747 | if (PrintOptimizeStringConcat) { |
748 | tty->print("fusion has incorrect memory flow (side effects) for " ); |
749 | _begin->jvms()->dump_spec(tty); tty->cr(); |
750 | path.dump(); |
751 | } |
752 | #endif |
753 | return false; |
754 | } |
755 | } |
756 | // skip through a potential MergeMem chain, linked through Bot |
757 | mem = mem->in(Compile::AliasIdxBot); |
758 | NOT_PRODUCT(path.push(mem);) |
759 | } |
760 | // now let it fall through, and see if we have a projection |
761 | if (mem->is_Proj()) { |
762 | // Should point to a previous known call |
763 | Node *prev = mem->in(0); |
764 | NOT_PRODUCT(path.push(prev);) |
765 | if (!prev->is_Call() || !_control.contains(prev)) { |
766 | #ifndef PRODUCT |
767 | if (PrintOptimizeStringConcat) { |
768 | tty->print("fusion has incorrect memory flow (unknown call) for " ); |
769 | _begin->jvms()->dump_spec(tty); tty->cr(); |
770 | path.dump(); |
771 | } |
772 | #endif |
773 | return false; |
774 | } |
775 | } else { |
776 | assert(mem->is_Store() || mem->is_LoadStore(), "unexpected node type: %s" , mem->Name()); |
777 | #ifndef PRODUCT |
778 | if (PrintOptimizeStringConcat) { |
779 | tty->print("fusion has incorrect memory flow (unexpected source) for " ); |
780 | _begin->jvms()->dump_spec(tty); tty->cr(); |
781 | path.dump(); |
782 | } |
783 | #endif |
784 | return false; |
785 | } |
786 | } else { |
787 | // For memory that feeds into constructors it's more complicated. |
788 | // However the advantage is that any side effect that happens between the Allocate/Initialize and |
789 | // the constructor will have to be control-dependent on Initialize. |
790 | // So we actually don't have to do anything, since it's going to be caught by the control flow |
791 | // analysis. |
792 | #ifdef ASSERT |
793 | // Do a quick verification of the control pattern between the constructor and the initialize node |
794 | assert(curr->is_Call(), "constructor should be a call" ); |
795 | // Go up the control starting from the constructor call |
796 | Node* ctrl = curr->in(0); |
797 | IfNode* iff = NULL; |
798 | RegionNode* copy = NULL; |
799 | |
800 | while (true) { |
801 | // skip known check patterns |
802 | if (ctrl->is_Region()) { |
803 | if (ctrl->as_Region()->is_copy()) { |
804 | copy = ctrl->as_Region(); |
805 | ctrl = copy->is_copy(); |
806 | } else { // a cast |
807 | assert(ctrl->req() == 3 && |
808 | ctrl->in(1) != NULL && ctrl->in(1)->is_Proj() && |
809 | ctrl->in(2) != NULL && ctrl->in(2)->is_Proj() && |
810 | ctrl->in(1)->in(0) == ctrl->in(2)->in(0) && |
811 | ctrl->in(1)->in(0) != NULL && ctrl->in(1)->in(0)->is_If(), |
812 | "must be a simple diamond" ); |
813 | Node* true_proj = ctrl->in(1)->is_IfTrue() ? ctrl->in(1) : ctrl->in(2); |
814 | for (SimpleDUIterator i(true_proj); i.has_next(); i.next()) { |
815 | Node* use = i.get(); |
816 | assert(use == ctrl || use->is_ConstraintCast(), |
817 | "unexpected user: %s" , use->Name()); |
818 | } |
819 | |
820 | iff = ctrl->in(1)->in(0)->as_If(); |
821 | ctrl = iff->in(0); |
822 | } |
823 | } else if (ctrl->is_IfTrue()) { // null checks, class checks |
824 | iff = ctrl->in(0)->as_If(); |
825 | // Verify that the other arm is an uncommon trap |
826 | Node* otherproj = iff->proj_out(1 - ctrl->as_Proj()->_con); |
827 | CallStaticJavaNode* call = otherproj->unique_out()->isa_CallStaticJava(); |
828 | assert(strcmp(call->_name, "uncommon_trap" ) == 0, "must be uncommon trap" ); |
829 | ctrl = iff->in(0); |
830 | } else { |
831 | break; |
832 | } |
833 | } |
834 | |
835 | assert(ctrl->is_Proj(), "must be a projection" ); |
836 | assert(ctrl->in(0)->is_Initialize(), "should be initialize" ); |
837 | for (SimpleDUIterator i(ctrl); i.has_next(); i.next()) { |
838 | Node* use = i.get(); |
839 | assert(use == copy || use == iff || use == curr || use->is_CheckCastPP() || use->is_Load(), |
840 | "unexpected user: %s" , use->Name()); |
841 | } |
842 | #endif // ASSERT |
843 | } |
844 | } |
845 | } |
846 | |
847 | #ifndef PRODUCT |
848 | if (PrintOptimizeStringConcat) { |
849 | tty->print("fusion has correct memory flow for " ); |
850 | _begin->jvms()->dump_spec(tty); tty->cr(); |
851 | tty->cr(); |
852 | } |
853 | #endif |
854 | return true; |
855 | } |
856 | |
857 | bool StringConcat::validate_control_flow() { |
858 | // We found all the calls and arguments now lets see if it's |
859 | // safe to transform the graph as we would expect. |
860 | |
861 | // Check to see if this resulted in too many uncommon traps previously |
862 | if (Compile::current()->too_many_traps(_begin->jvms()->method(), _begin->jvms()->bci(), |
863 | Deoptimization::Reason_intrinsic)) { |
864 | return false; |
865 | } |
866 | |
867 | // Walk backwards over the control flow from toString to the |
868 | // allocation and make sure all the control flow is ok. This |
869 | // means it's either going to be eliminated once the calls are |
870 | // removed or it can safely be transformed into an uncommon |
871 | // trap. |
872 | |
873 | int null_check_count = 0; |
874 | Unique_Node_List ctrl_path; |
875 | |
876 | assert(_control.contains(_begin), "missing" ); |
877 | assert(_control.contains(_end), "missing" ); |
878 | |
879 | // Collect the nodes that we know about and will eliminate into ctrl_path |
880 | for (uint i = 0; i < _control.size(); i++) { |
881 | // Push the call and it's control projection |
882 | Node* n = _control.at(i); |
883 | if (n->is_Allocate()) { |
884 | AllocateNode* an = n->as_Allocate(); |
885 | InitializeNode* init = an->initialization(); |
886 | ctrl_path.push(init); |
887 | ctrl_path.push(init->as_Multi()->proj_out(0)); |
888 | } |
889 | if (n->is_Call()) { |
890 | CallNode* cn = n->as_Call(); |
891 | ctrl_path.push(cn); |
892 | ctrl_path.push(cn->proj_out(0)); |
893 | ctrl_path.push(cn->proj_out(0)->unique_out()); |
894 | Node* catchproj = cn->proj_out(0)->unique_out()->as_Catch()->proj_out_or_null(0); |
895 | if (catchproj != NULL) { |
896 | ctrl_path.push(catchproj); |
897 | } |
898 | } else { |
899 | ShouldNotReachHere(); |
900 | } |
901 | } |
902 | |
903 | // Skip backwards through the control checking for unexpected control flow |
904 | Node* ptr = _end; |
905 | bool fail = false; |
906 | while (ptr != _begin) { |
907 | if (ptr->is_Call() && ctrl_path.member(ptr)) { |
908 | ptr = ptr->in(0); |
909 | } else if (ptr->is_CatchProj() && ctrl_path.member(ptr)) { |
910 | ptr = ptr->in(0)->in(0)->in(0); |
911 | assert(ctrl_path.member(ptr), "should be a known piece of control" ); |
912 | } else if (ptr->is_IfTrue()) { |
913 | IfNode* iff = ptr->in(0)->as_If(); |
914 | BoolNode* b = iff->in(1)->isa_Bool(); |
915 | |
916 | if (b == NULL) { |
917 | #ifndef PRODUCT |
918 | if (PrintOptimizeStringConcat) { |
919 | tty->print_cr("unexpected input to IfNode" ); |
920 | iff->in(1)->dump(); |
921 | tty->cr(); |
922 | } |
923 | #endif |
924 | fail = true; |
925 | break; |
926 | } |
927 | |
928 | Node* cmp = b->in(1); |
929 | Node* v1 = cmp->in(1); |
930 | Node* v2 = cmp->in(2); |
931 | Node* otherproj = iff->proj_out(1 - ptr->as_Proj()->_con); |
932 | |
933 | // Null check of the return of append which can simply be eliminated |
934 | if (b->_test._test == BoolTest::ne && |
935 | v2->bottom_type() == TypePtr::NULL_PTR && |
936 | v1->is_Proj() && ctrl_path.member(v1->in(0))) { |
937 | // NULL check of the return value of the append |
938 | null_check_count++; |
939 | if (otherproj->outcnt() == 1) { |
940 | CallStaticJavaNode* call = otherproj->unique_out()->isa_CallStaticJava(); |
941 | if (call != NULL && call->_name != NULL && strcmp(call->_name, "uncommon_trap" ) == 0) { |
942 | ctrl_path.push(call); |
943 | } |
944 | } |
945 | _control.push(ptr); |
946 | ptr = ptr->in(0)->in(0); |
947 | continue; |
948 | } |
949 | |
950 | // A test which leads to an uncommon trap which should be safe. |
951 | // Later this trap will be converted into a trap that restarts |
952 | // at the beginning. |
953 | if (otherproj->outcnt() == 1) { |
954 | CallStaticJavaNode* call = otherproj->unique_out()->isa_CallStaticJava(); |
955 | if (call != NULL && call->_name != NULL && strcmp(call->_name, "uncommon_trap" ) == 0) { |
956 | // control flow leads to uct so should be ok |
957 | _uncommon_traps.push(call); |
958 | ctrl_path.push(call); |
959 | ptr = ptr->in(0)->in(0); |
960 | continue; |
961 | } |
962 | } |
963 | |
964 | #ifndef PRODUCT |
965 | // Some unexpected control flow we don't know how to handle. |
966 | if (PrintOptimizeStringConcat) { |
967 | tty->print_cr("failing with unknown test" ); |
968 | b->dump(); |
969 | cmp->dump(); |
970 | v1->dump(); |
971 | v2->dump(); |
972 | tty->cr(); |
973 | } |
974 | #endif |
975 | fail = true; |
976 | break; |
977 | } else if (ptr->is_Proj() && ptr->in(0)->is_Initialize()) { |
978 | ptr = ptr->in(0)->in(0); |
979 | } else if (ptr->is_Region()) { |
980 | Node* copy = ptr->as_Region()->is_copy(); |
981 | if (copy != NULL) { |
982 | ptr = copy; |
983 | continue; |
984 | } |
985 | if (ptr->req() == 3 && |
986 | ptr->in(1) != NULL && ptr->in(1)->is_Proj() && |
987 | ptr->in(2) != NULL && ptr->in(2)->is_Proj() && |
988 | ptr->in(1)->in(0) == ptr->in(2)->in(0) && |
989 | ptr->in(1)->in(0) != NULL && ptr->in(1)->in(0)->is_If()) { |
990 | // Simple diamond. |
991 | // XXX should check for possibly merging stores. simple data merges are ok. |
992 | // The IGVN will make this simple diamond go away when it |
993 | // transforms the Region. Make sure it sees it. |
994 | Compile::current()->record_for_igvn(ptr); |
995 | ptr = ptr->in(1)->in(0)->in(0); |
996 | continue; |
997 | } |
998 | #ifndef PRODUCT |
999 | if (PrintOptimizeStringConcat) { |
1000 | tty->print_cr("fusion would fail for region" ); |
1001 | _begin->dump(); |
1002 | ptr->dump(2); |
1003 | } |
1004 | #endif |
1005 | fail = true; |
1006 | break; |
1007 | } else { |
1008 | // other unknown control |
1009 | if (!fail) { |
1010 | #ifndef PRODUCT |
1011 | if (PrintOptimizeStringConcat) { |
1012 | tty->print_cr("fusion would fail for" ); |
1013 | _begin->dump(); |
1014 | } |
1015 | #endif |
1016 | fail = true; |
1017 | } |
1018 | #ifndef PRODUCT |
1019 | if (PrintOptimizeStringConcat) { |
1020 | ptr->dump(); |
1021 | } |
1022 | #endif |
1023 | ptr = ptr->in(0); |
1024 | } |
1025 | } |
1026 | #ifndef PRODUCT |
1027 | if (PrintOptimizeStringConcat && fail) { |
1028 | tty->cr(); |
1029 | } |
1030 | #endif |
1031 | if (fail) return !fail; |
1032 | |
1033 | // Validate that all these results produced are contained within |
1034 | // this cluster of objects. First collect all the results produced |
1035 | // by calls in the region. |
1036 | _stringopts->_visited.Clear(); |
1037 | Node_List worklist; |
1038 | Node* final_result = _end->proj_out_or_null(TypeFunc::Parms); |
1039 | for (uint i = 0; i < _control.size(); i++) { |
1040 | CallNode* cnode = _control.at(i)->isa_Call(); |
1041 | if (cnode != NULL) { |
1042 | _stringopts->_visited.test_set(cnode->_idx); |
1043 | } |
1044 | Node* result = cnode != NULL ? cnode->proj_out_or_null(TypeFunc::Parms) : NULL; |
1045 | if (result != NULL && result != final_result) { |
1046 | worklist.push(result); |
1047 | } |
1048 | } |
1049 | |
1050 | Node* last_result = NULL; |
1051 | while (worklist.size() > 0) { |
1052 | Node* result = worklist.pop(); |
1053 | if (_stringopts->_visited.test_set(result->_idx)) |
1054 | continue; |
1055 | for (SimpleDUIterator i(result); i.has_next(); i.next()) { |
1056 | Node *use = i.get(); |
1057 | if (ctrl_path.member(use)) { |
1058 | // already checked this |
1059 | continue; |
1060 | } |
1061 | int opc = use->Opcode(); |
1062 | if (opc == Op_CmpP || opc == Op_Node) { |
1063 | ctrl_path.push(use); |
1064 | continue; |
1065 | } |
1066 | if (opc == Op_CastPP || opc == Op_CheckCastPP) { |
1067 | for (SimpleDUIterator j(use); j.has_next(); j.next()) { |
1068 | worklist.push(j.get()); |
1069 | } |
1070 | worklist.push(use->in(1)); |
1071 | ctrl_path.push(use); |
1072 | continue; |
1073 | } |
1074 | #ifndef PRODUCT |
1075 | if (PrintOptimizeStringConcat) { |
1076 | if (result != last_result) { |
1077 | last_result = result; |
1078 | tty->print_cr("extra uses for result:" ); |
1079 | last_result->dump(); |
1080 | } |
1081 | use->dump(); |
1082 | } |
1083 | #endif |
1084 | fail = true; |
1085 | break; |
1086 | } |
1087 | } |
1088 | |
1089 | #ifndef PRODUCT |
1090 | if (PrintOptimizeStringConcat && !fail) { |
1091 | ttyLocker ttyl; |
1092 | tty->cr(); |
1093 | tty->print("fusion has correct control flow (%d %d) for " , null_check_count, _uncommon_traps.size()); |
1094 | _begin->jvms()->dump_spec(tty); tty->cr(); |
1095 | for (int i = 0; i < num_arguments(); i++) { |
1096 | argument(i)->dump(); |
1097 | } |
1098 | _control.dump(); |
1099 | tty->cr(); |
1100 | } |
1101 | #endif |
1102 | |
1103 | return !fail; |
1104 | } |
1105 | |
1106 | Node* PhaseStringOpts::fetch_static_field(GraphKit& kit, ciField* field) { |
1107 | const TypeInstPtr* mirror_type = TypeInstPtr::make(field->holder()->java_mirror()); |
1108 | Node* klass_node = __ makecon(mirror_type); |
1109 | BasicType bt = field->layout_type(); |
1110 | ciType* field_klass = field->type(); |
1111 | |
1112 | const Type *type; |
1113 | if( bt == T_OBJECT ) { |
1114 | if (!field->type()->is_loaded()) { |
1115 | type = TypeInstPtr::BOTTOM; |
1116 | } else if (field->is_static_constant()) { |
1117 | // This can happen if the constant oop is non-perm. |
1118 | ciObject* con = field->constant_value().as_object(); |
1119 | // Do not "join" in the previous type; it doesn't add value, |
1120 | // and may yield a vacuous result if the field is of interface type. |
1121 | type = TypeOopPtr::make_from_constant(con, true)->isa_oopptr(); |
1122 | assert(type != NULL, "field singleton type must be consistent" ); |
1123 | return __ makecon(type); |
1124 | } else { |
1125 | type = TypeOopPtr::make_from_klass(field_klass->as_klass()); |
1126 | } |
1127 | } else { |
1128 | type = Type::get_const_basic_type(bt); |
1129 | } |
1130 | |
1131 | return kit.make_load(NULL, kit.basic_plus_adr(klass_node, field->offset_in_bytes()), |
1132 | type, T_OBJECT, |
1133 | C->get_alias_index(mirror_type->add_offset(field->offset_in_bytes())), |
1134 | MemNode::unordered); |
1135 | } |
1136 | |
1137 | Node* PhaseStringOpts::int_stringSize(GraphKit& kit, Node* arg) { |
1138 | if (arg->is_Con()) { |
1139 | // Constant integer. Compute constant length using Integer.sizeTable |
1140 | int arg_val = arg->get_int(); |
1141 | int count = 1; |
1142 | if (arg_val < 0) { |
1143 | arg_val = -arg_val; |
1144 | count++; |
1145 | } |
1146 | |
1147 | ciArray* size_table = (ciArray*)size_table_field->constant_value().as_object(); |
1148 | for (int i = 0; i < size_table->length(); i++) { |
1149 | if (arg_val <= size_table->element_value(i).as_int()) { |
1150 | count += i; |
1151 | break; |
1152 | } |
1153 | } |
1154 | return __ intcon(count); |
1155 | } |
1156 | |
1157 | RegionNode *final_merge = new RegionNode(3); |
1158 | kit.gvn().set_type(final_merge, Type::CONTROL); |
1159 | Node* final_size = new PhiNode(final_merge, TypeInt::INT); |
1160 | kit.gvn().set_type(final_size, TypeInt::INT); |
1161 | |
1162 | IfNode* iff = kit.create_and_map_if(kit.control(), |
1163 | __ Bool(__ CmpI(arg, __ intcon(0x80000000)), BoolTest::ne), |
1164 | PROB_FAIR, COUNT_UNKNOWN); |
1165 | Node* is_min = __ IfFalse(iff); |
1166 | final_merge->init_req(1, is_min); |
1167 | final_size->init_req(1, __ intcon(11)); |
1168 | |
1169 | kit.set_control(__ IfTrue(iff)); |
1170 | if (kit.stopped()) { |
1171 | final_merge->init_req(2, C->top()); |
1172 | final_size->init_req(2, C->top()); |
1173 | } else { |
1174 | |
1175 | // int size = (i < 0) ? stringSize(-i) + 1 : stringSize(i); |
1176 | RegionNode *r = new RegionNode(3); |
1177 | kit.gvn().set_type(r, Type::CONTROL); |
1178 | Node *phi = new PhiNode(r, TypeInt::INT); |
1179 | kit.gvn().set_type(phi, TypeInt::INT); |
1180 | Node *size = new PhiNode(r, TypeInt::INT); |
1181 | kit.gvn().set_type(size, TypeInt::INT); |
1182 | Node* chk = __ CmpI(arg, __ intcon(0)); |
1183 | Node* p = __ Bool(chk, BoolTest::lt); |
1184 | IfNode* iff = kit.create_and_map_if(kit.control(), p, PROB_FAIR, COUNT_UNKNOWN); |
1185 | Node* lessthan = __ IfTrue(iff); |
1186 | Node* greaterequal = __ IfFalse(iff); |
1187 | r->init_req(1, lessthan); |
1188 | phi->init_req(1, __ SubI(__ intcon(0), arg)); |
1189 | size->init_req(1, __ intcon(1)); |
1190 | r->init_req(2, greaterequal); |
1191 | phi->init_req(2, arg); |
1192 | size->init_req(2, __ intcon(0)); |
1193 | kit.set_control(r); |
1194 | C->record_for_igvn(r); |
1195 | C->record_for_igvn(phi); |
1196 | C->record_for_igvn(size); |
1197 | |
1198 | // for (int i=0; ; i++) |
1199 | // if (x <= sizeTable[i]) |
1200 | // return i+1; |
1201 | |
1202 | // Add loop predicate first. |
1203 | kit.add_predicate(); |
1204 | |
1205 | RegionNode *loop = new RegionNode(3); |
1206 | loop->init_req(1, kit.control()); |
1207 | kit.gvn().set_type(loop, Type::CONTROL); |
1208 | |
1209 | Node *index = new PhiNode(loop, TypeInt::INT); |
1210 | index->init_req(1, __ intcon(0)); |
1211 | kit.gvn().set_type(index, TypeInt::INT); |
1212 | kit.set_control(loop); |
1213 | Node* sizeTable = fetch_static_field(kit, size_table_field); |
1214 | |
1215 | sizeTable = kit.access_resolve(sizeTable, ACCESS_READ); |
1216 | Node* value = kit.load_array_element(NULL, sizeTable, index, TypeAryPtr::INTS); |
1217 | C->record_for_igvn(value); |
1218 | Node* limit = __ CmpI(phi, value); |
1219 | Node* limitb = __ Bool(limit, BoolTest::le); |
1220 | IfNode* iff2 = kit.create_and_map_if(kit.control(), limitb, PROB_MIN, COUNT_UNKNOWN); |
1221 | Node* lessEqual = __ IfTrue(iff2); |
1222 | Node* greater = __ IfFalse(iff2); |
1223 | |
1224 | loop->init_req(2, greater); |
1225 | index->init_req(2, __ AddI(index, __ intcon(1))); |
1226 | |
1227 | kit.set_control(lessEqual); |
1228 | C->record_for_igvn(loop); |
1229 | C->record_for_igvn(index); |
1230 | |
1231 | final_merge->init_req(2, kit.control()); |
1232 | final_size->init_req(2, __ AddI(__ AddI(index, size), __ intcon(1))); |
1233 | } |
1234 | |
1235 | kit.set_control(final_merge); |
1236 | C->record_for_igvn(final_merge); |
1237 | C->record_for_igvn(final_size); |
1238 | |
1239 | return final_size; |
1240 | } |
1241 | |
1242 | // Simplified version of Integer.getChars |
1243 | void PhaseStringOpts::getChars(GraphKit& kit, Node* arg, Node* dst_array, BasicType bt, Node* end, Node* final_merge, Node* final_mem, int merge_index) { |
1244 | // if (i < 0) { |
1245 | // sign = '-'; |
1246 | // i = -i; |
1247 | // } |
1248 | IfNode* iff = kit.create_and_map_if(kit.control(), __ Bool(__ CmpI(arg, __ intcon(0)), BoolTest::lt), |
1249 | PROB_FAIR, COUNT_UNKNOWN); |
1250 | |
1251 | RegionNode* merge = new RegionNode(3); |
1252 | kit.gvn().set_type(merge, Type::CONTROL); |
1253 | Node* i = new PhiNode(merge, TypeInt::INT); |
1254 | kit.gvn().set_type(i, TypeInt::INT); |
1255 | Node* sign = new PhiNode(merge, TypeInt::INT); |
1256 | kit.gvn().set_type(sign, TypeInt::INT); |
1257 | |
1258 | merge->init_req(1, __ IfTrue(iff)); |
1259 | i->init_req(1, __ SubI(__ intcon(0), arg)); |
1260 | sign->init_req(1, __ intcon('-')); |
1261 | merge->init_req(2, __ IfFalse(iff)); |
1262 | i->init_req(2, arg); |
1263 | sign->init_req(2, __ intcon(0)); |
1264 | |
1265 | kit.set_control(merge); |
1266 | |
1267 | C->record_for_igvn(merge); |
1268 | C->record_for_igvn(i); |
1269 | C->record_for_igvn(sign); |
1270 | |
1271 | // for (;;) { |
1272 | // q = i / 10; |
1273 | // r = i - ((q << 3) + (q << 1)); // r = i-(q*10) ... |
1274 | // buf [--charPos] = digits [r]; |
1275 | // i = q; |
1276 | // if (i == 0) break; |
1277 | // } |
1278 | |
1279 | // Add loop predicate first. |
1280 | kit.add_predicate(); |
1281 | |
1282 | RegionNode* head = new RegionNode(3); |
1283 | head->init_req(1, kit.control()); |
1284 | |
1285 | kit.gvn().set_type(head, Type::CONTROL); |
1286 | Node* i_phi = new PhiNode(head, TypeInt::INT); |
1287 | i_phi->init_req(1, i); |
1288 | kit.gvn().set_type(i_phi, TypeInt::INT); |
1289 | Node* charPos = new PhiNode(head, TypeInt::INT); |
1290 | charPos->init_req(1, end); |
1291 | kit.gvn().set_type(charPos, TypeInt::INT); |
1292 | Node* mem = PhiNode::make(head, kit.memory(byte_adr_idx), Type::MEMORY, TypeAryPtr::BYTES); |
1293 | kit.gvn().set_type(mem, Type::MEMORY); |
1294 | |
1295 | kit.set_control(head); |
1296 | kit.set_memory(mem, byte_adr_idx); |
1297 | |
1298 | Node* q = __ DivI(kit.null(), i_phi, __ intcon(10)); |
1299 | Node* r = __ SubI(i_phi, __ AddI(__ LShiftI(q, __ intcon(3)), |
1300 | __ LShiftI(q, __ intcon(1)))); |
1301 | Node* index = __ SubI(charPos, __ intcon((bt == T_BYTE) ? 1 : 2)); |
1302 | Node* ch = __ AddI(r, __ intcon('0')); |
1303 | Node* st = __ store_to_memory(kit.control(), kit.array_element_address(dst_array, index, T_BYTE), |
1304 | ch, bt, byte_adr_idx, MemNode::unordered, (bt != T_BYTE) /* mismatched */); |
1305 | |
1306 | iff = kit.create_and_map_if(head, __ Bool(__ CmpI(q, __ intcon(0)), BoolTest::ne), |
1307 | PROB_FAIR, COUNT_UNKNOWN); |
1308 | Node* ne = __ IfTrue(iff); |
1309 | Node* eq = __ IfFalse(iff); |
1310 | |
1311 | head->init_req(2, ne); |
1312 | mem->init_req(2, st); |
1313 | |
1314 | i_phi->init_req(2, q); |
1315 | charPos->init_req(2, index); |
1316 | charPos = index; |
1317 | |
1318 | kit.set_control(eq); |
1319 | kit.set_memory(st, byte_adr_idx); |
1320 | |
1321 | C->record_for_igvn(head); |
1322 | C->record_for_igvn(mem); |
1323 | C->record_for_igvn(i_phi); |
1324 | C->record_for_igvn(charPos); |
1325 | |
1326 | // if (sign != 0) { |
1327 | // buf [--charPos] = sign; |
1328 | // } |
1329 | iff = kit.create_and_map_if(kit.control(), __ Bool(__ CmpI(sign, __ intcon(0)), BoolTest::ne), |
1330 | PROB_FAIR, COUNT_UNKNOWN); |
1331 | |
1332 | final_merge->init_req(merge_index + 2, __ IfFalse(iff)); |
1333 | final_mem->init_req(merge_index + 2, kit.memory(byte_adr_idx)); |
1334 | |
1335 | kit.set_control(__ IfTrue(iff)); |
1336 | if (kit.stopped()) { |
1337 | final_merge->init_req(merge_index + 1, C->top()); |
1338 | final_mem->init_req(merge_index + 1, C->top()); |
1339 | } else { |
1340 | Node* index = __ SubI(charPos, __ intcon((bt == T_BYTE) ? 1 : 2)); |
1341 | st = __ store_to_memory(kit.control(), kit.array_element_address(dst_array, index, T_BYTE), |
1342 | sign, bt, byte_adr_idx, MemNode::unordered, (bt != T_BYTE) /* mismatched */); |
1343 | |
1344 | final_merge->init_req(merge_index + 1, kit.control()); |
1345 | final_mem->init_req(merge_index + 1, st); |
1346 | } |
1347 | } |
1348 | |
1349 | // Copy the characters representing arg into dst_array starting at start |
1350 | Node* PhaseStringOpts::int_getChars(GraphKit& kit, Node* arg, Node* dst_array, Node* dst_coder, Node* start, Node* size) { |
1351 | bool dcon = dst_coder->is_Con(); |
1352 | bool dbyte = dcon ? (dst_coder->get_int() == java_lang_String::CODER_LATIN1) : false; |
1353 | Node* end = __ AddI(start, __ LShiftI(size, dst_coder)); |
1354 | |
1355 | // The final_merge node has 4 entries in case the encoding is known: |
1356 | // (0) Control, (1) result w/ sign, (2) result w/o sign, (3) result for Integer.min_value |
1357 | // or 6 entries in case the encoding is not known: |
1358 | // (0) Control, (1) Latin1 w/ sign, (2) Latin1 w/o sign, (3) min_value, (4) UTF16 w/ sign, (5) UTF16 w/o sign |
1359 | RegionNode* final_merge = new RegionNode(dcon ? 4 : 6); |
1360 | kit.gvn().set_type(final_merge, Type::CONTROL); |
1361 | |
1362 | Node* final_mem = PhiNode::make(final_merge, kit.memory(byte_adr_idx), Type::MEMORY, TypeAryPtr::BYTES); |
1363 | kit.gvn().set_type(final_mem, Type::MEMORY); |
1364 | |
1365 | // need to handle arg == Integer.MIN_VALUE specially because negating doesn't make it positive |
1366 | IfNode* iff = kit.create_and_map_if(kit.control(), __ Bool(__ CmpI(arg, __ intcon(0x80000000)), BoolTest::ne), |
1367 | PROB_FAIR, COUNT_UNKNOWN); |
1368 | |
1369 | Node* old_mem = kit.memory(byte_adr_idx); |
1370 | |
1371 | kit.set_control(__ IfFalse(iff)); |
1372 | if (kit.stopped()) { |
1373 | // Statically not equal to MIN_VALUE so this path is dead |
1374 | final_merge->init_req(3, kit.control()); |
1375 | } else { |
1376 | copy_string(kit, __ makecon(TypeInstPtr::make(C->env()->the_min_jint_string())), |
1377 | dst_array, dst_coder, start); |
1378 | final_merge->init_req(3, kit.control()); |
1379 | final_mem->init_req(3, kit.memory(byte_adr_idx)); |
1380 | } |
1381 | |
1382 | kit.set_control(__ IfTrue(iff)); |
1383 | kit.set_memory(old_mem, byte_adr_idx); |
1384 | |
1385 | if (!dcon) { |
1386 | // Check encoding of destination |
1387 | iff = kit.create_and_map_if(kit.control(), __ Bool(__ CmpI(dst_coder, __ intcon(0)), BoolTest::eq), |
1388 | PROB_FAIR, COUNT_UNKNOWN); |
1389 | old_mem = kit.memory(byte_adr_idx); |
1390 | } |
1391 | if (!dcon || dbyte) { |
1392 | // Destination is Latin1, |
1393 | if (!dcon) { |
1394 | kit.set_control(__ IfTrue(iff)); |
1395 | } |
1396 | getChars(kit, arg, dst_array, T_BYTE, end, final_merge, final_mem); |
1397 | } |
1398 | if (!dcon || !dbyte) { |
1399 | // Destination is UTF16 |
1400 | int merge_index = 0; |
1401 | if (!dcon) { |
1402 | kit.set_control(__ IfFalse(iff)); |
1403 | kit.set_memory(old_mem, byte_adr_idx); |
1404 | merge_index = 3; // Account for Latin1 case |
1405 | } |
1406 | getChars(kit, arg, dst_array, T_CHAR, end, final_merge, final_mem, merge_index); |
1407 | } |
1408 | |
1409 | // Final merge point for Latin1 and UTF16 case |
1410 | kit.set_control(final_merge); |
1411 | kit.set_memory(final_mem, byte_adr_idx); |
1412 | |
1413 | C->record_for_igvn(final_merge); |
1414 | C->record_for_igvn(final_mem); |
1415 | return end; |
1416 | } |
1417 | |
1418 | // Copy 'count' bytes/chars from src_array to dst_array starting at index start |
1419 | void PhaseStringOpts::arraycopy(GraphKit& kit, IdealKit& ideal, Node* src_array, Node* dst_array, BasicType elembt, Node* start, Node* count) { |
1420 | assert(elembt == T_BYTE || elembt == T_CHAR, "Invalid type for arraycopy" ); |
1421 | |
1422 | if (elembt == T_CHAR) { |
1423 | // Get number of chars |
1424 | count = __ RShiftI(count, __ intcon(1)); |
1425 | } |
1426 | |
1427 | Node* = NULL; |
1428 | #ifdef _LP64 |
1429 | count = __ ConvI2L(count); |
1430 | extra = C->top(); |
1431 | #endif |
1432 | |
1433 | Node* src_ptr = __ array_element_address(src_array, __ intcon(0), T_BYTE); |
1434 | Node* dst_ptr = __ array_element_address(dst_array, start, T_BYTE); |
1435 | // Check if destination address is aligned to HeapWordSize |
1436 | const TypeInt* tdst = __ gvn().type(start)->is_int(); |
1437 | bool aligned = tdst->is_con() && ((tdst->get_con() * type2aelembytes(T_BYTE)) % HeapWordSize == 0); |
1438 | // Figure out which arraycopy runtime method to call (disjoint, uninitialized). |
1439 | const char* copyfunc_name = "arraycopy" ; |
1440 | address copyfunc_addr = StubRoutines::select_arraycopy_function(elembt, aligned, true, copyfunc_name, true); |
1441 | ideal.make_leaf_call_no_fp(OptoRuntime::fast_arraycopy_Type(), copyfunc_addr, copyfunc_name, |
1442 | TypeAryPtr::BYTES, src_ptr, dst_ptr, count, extra); |
1443 | } |
1444 | |
1445 | #undef __ |
1446 | #define __ ideal. |
1447 | |
1448 | // Copy contents of a Latin1 encoded string from src_array to dst_array |
1449 | void PhaseStringOpts::copy_latin1_string(GraphKit& kit, IdealKit& ideal, Node* src_array, IdealVariable& count, |
1450 | Node* dst_array, Node* dst_coder, Node* start) { |
1451 | bool dcon = dst_coder->is_Con(); |
1452 | bool dbyte = dcon ? (dst_coder->get_int() == java_lang_String::CODER_LATIN1) : false; |
1453 | |
1454 | if (!dcon) { |
1455 | __ if_then(dst_coder, BoolTest::eq, __ ConI(java_lang_String::CODER_LATIN1)); |
1456 | } |
1457 | if (!dcon || dbyte) { |
1458 | // Destination is Latin1. Simply emit a byte arraycopy. |
1459 | arraycopy(kit, ideal, src_array, dst_array, T_BYTE, start, __ value(count)); |
1460 | } |
1461 | if (!dcon) { |
1462 | __ else_(); |
1463 | } |
1464 | if (!dcon || !dbyte) { |
1465 | // Destination is UTF16. Inflate src_array into dst_array. |
1466 | kit.sync_kit(ideal); |
1467 | if (Matcher::match_rule_supported(Op_StrInflatedCopy)) { |
1468 | // Use fast intrinsic |
1469 | Node* src = kit.array_element_address(src_array, kit.intcon(0), T_BYTE); |
1470 | Node* dst = kit.array_element_address(dst_array, start, T_BYTE); |
1471 | kit.inflate_string(src, dst, TypeAryPtr::BYTES, __ value(count)); |
1472 | } else { |
1473 | // No intrinsic available, use slow method |
1474 | kit.inflate_string_slow(src_array, dst_array, start, __ value(count)); |
1475 | } |
1476 | ideal.sync_kit(&kit); |
1477 | // Multiply count by two since we now need two bytes per char |
1478 | __ set(count, __ LShiftI(__ value(count), __ ConI(1))); |
1479 | } |
1480 | if (!dcon) { |
1481 | __ end_if(); |
1482 | } |
1483 | } |
1484 | |
1485 | // Read two bytes from index and index+1 and convert them to a char |
1486 | static jchar readChar(ciTypeArray* array, int index) { |
1487 | int shift_high, shift_low; |
1488 | #ifdef VM_LITTLE_ENDIAN |
1489 | shift_high = 0; |
1490 | shift_low = 8; |
1491 | #else |
1492 | shift_high = 8; |
1493 | shift_low = 0; |
1494 | #endif |
1495 | |
1496 | jchar b1 = ((jchar) array->byte_at(index)) & 0xff; |
1497 | jchar b2 = ((jchar) array->byte_at(index+1)) & 0xff; |
1498 | return (b1 << shift_high) | (b2 << shift_low); |
1499 | } |
1500 | |
1501 | // Copy contents of constant src_array to dst_array by emitting individual stores |
1502 | void PhaseStringOpts::copy_constant_string(GraphKit& kit, IdealKit& ideal, ciTypeArray* src_array, IdealVariable& count, |
1503 | bool src_is_byte, Node* dst_array, Node* dst_coder, Node* start) { |
1504 | bool dcon = dst_coder->is_Con(); |
1505 | bool dbyte = dcon ? (dst_coder->get_int() == java_lang_String::CODER_LATIN1) : false; |
1506 | int length = src_array->length(); |
1507 | |
1508 | if (!dcon) { |
1509 | __ if_then(dst_coder, BoolTest::eq, __ ConI(java_lang_String::CODER_LATIN1)); |
1510 | } |
1511 | if (!dcon || dbyte) { |
1512 | // Destination is Latin1. Copy each byte of src_array into dst_array. |
1513 | Node* index = start; |
1514 | for (int i = 0; i < length; i++) { |
1515 | Node* adr = kit.array_element_address(dst_array, index, T_BYTE); |
1516 | Node* val = __ ConI(src_array->byte_at(i)); |
1517 | __ store(__ ctrl(), adr, val, T_BYTE, byte_adr_idx, MemNode::unordered); |
1518 | index = __ AddI(index, __ ConI(1)); |
1519 | } |
1520 | } |
1521 | if (!dcon) { |
1522 | __ else_(); |
1523 | } |
1524 | if (!dcon || !dbyte) { |
1525 | // Destination is UTF16. Copy each char of src_array into dst_array. |
1526 | Node* index = start; |
1527 | for (int i = 0; i < length; i++) { |
1528 | Node* adr = kit.array_element_address(dst_array, index, T_BYTE); |
1529 | jchar val; |
1530 | if (src_is_byte) { |
1531 | val = src_array->byte_at(i) & 0xff; |
1532 | } else { |
1533 | val = readChar(src_array, i++); |
1534 | } |
1535 | __ store(__ ctrl(), adr, __ ConI(val), T_CHAR, byte_adr_idx, MemNode::unordered, true /* mismatched */); |
1536 | index = __ AddI(index, __ ConI(2)); |
1537 | } |
1538 | if (src_is_byte) { |
1539 | // Multiply count by two since we now need two bytes per char |
1540 | __ set(count, __ ConI(2 * length)); |
1541 | } |
1542 | } |
1543 | if (!dcon) { |
1544 | __ end_if(); |
1545 | } |
1546 | } |
1547 | |
1548 | // Compress copy contents of the byte/char String str into dst_array starting at index start. |
1549 | Node* PhaseStringOpts::copy_string(GraphKit& kit, Node* str, Node* dst_array, Node* dst_coder, Node* start) { |
1550 | Node* src_array = kit.load_String_value(str, true); |
1551 | src_array = kit.access_resolve(src_array, ACCESS_READ); |
1552 | |
1553 | IdealKit ideal(&kit, true, true); |
1554 | IdealVariable count(ideal); __ declarations_done(); |
1555 | |
1556 | if (str->is_Con()) { |
1557 | // Constant source string |
1558 | ciTypeArray* src_array_type = get_constant_value(kit, str); |
1559 | |
1560 | // Check encoding of constant string |
1561 | bool src_is_byte = (get_constant_coder(kit, str) == java_lang_String::CODER_LATIN1); |
1562 | |
1563 | // For small constant strings just emit individual stores. |
1564 | // A length of 6 seems like a good space/speed tradeof. |
1565 | __ set(count, __ ConI(src_array_type->length())); |
1566 | int src_len = src_array_type->length() / (src_is_byte ? 1 : 2); |
1567 | if (src_len < unroll_string_copy_length) { |
1568 | // Small constant string |
1569 | copy_constant_string(kit, ideal, src_array_type, count, src_is_byte, dst_array, dst_coder, start); |
1570 | } else if (src_is_byte) { |
1571 | // Source is Latin1 |
1572 | copy_latin1_string(kit, ideal, src_array, count, dst_array, dst_coder, start); |
1573 | } else { |
1574 | // Source is UTF16 (destination too). Simply emit a char arraycopy. |
1575 | arraycopy(kit, ideal, src_array, dst_array, T_CHAR, start, __ value(count)); |
1576 | } |
1577 | } else { |
1578 | Node* size = kit.load_array_length(src_array); |
1579 | __ set(count, size); |
1580 | // Non-constant source string |
1581 | if (CompactStrings) { |
1582 | // Emit runtime check for coder |
1583 | Node* coder = kit.load_String_coder(str, true); |
1584 | __ if_then(coder, BoolTest::eq, __ ConI(java_lang_String::CODER_LATIN1)); { |
1585 | // Source is Latin1 |
1586 | copy_latin1_string(kit, ideal, src_array, count, dst_array, dst_coder, start); |
1587 | } __ else_(); |
1588 | } |
1589 | // Source is UTF16 (destination too). Simply emit a char arraycopy. |
1590 | arraycopy(kit, ideal, src_array, dst_array, T_CHAR, start, __ value(count)); |
1591 | |
1592 | if (CompactStrings) { |
1593 | __ end_if(); |
1594 | } |
1595 | } |
1596 | |
1597 | // Finally sync IdealKit and GraphKit. |
1598 | kit.sync_kit(ideal); |
1599 | return __ AddI(start, __ value(count)); |
1600 | } |
1601 | |
1602 | // Compress copy the char into dst_array at index start. |
1603 | Node* PhaseStringOpts::copy_char(GraphKit& kit, Node* val, Node* dst_array, Node* dst_coder, Node* start) { |
1604 | bool dcon = (dst_coder != NULL) && dst_coder->is_Con(); |
1605 | bool dbyte = dcon ? (dst_coder->get_int() == java_lang_String::CODER_LATIN1) : false; |
1606 | |
1607 | IdealKit ideal(&kit, true, true); |
1608 | IdealVariable end(ideal); __ declarations_done(); |
1609 | Node* adr = kit.array_element_address(dst_array, start, T_BYTE); |
1610 | if (!dcon){ |
1611 | __ if_then(dst_coder, BoolTest::eq, __ ConI(java_lang_String::CODER_LATIN1)); |
1612 | } |
1613 | if (!dcon || dbyte) { |
1614 | // Destination is Latin1. Store a byte. |
1615 | __ store(__ ctrl(), adr, val, T_BYTE, byte_adr_idx, MemNode::unordered); |
1616 | __ set(end, __ AddI(start, __ ConI(1))); |
1617 | } |
1618 | if (!dcon) { |
1619 | __ else_(); |
1620 | } |
1621 | if (!dcon || !dbyte) { |
1622 | // Destination is UTF16. Store a char. |
1623 | __ store(__ ctrl(), adr, val, T_CHAR, byte_adr_idx, MemNode::unordered, true /* mismatched */); |
1624 | __ set(end, __ AddI(start, __ ConI(2))); |
1625 | } |
1626 | if (!dcon) { |
1627 | __ end_if(); |
1628 | } |
1629 | // Finally sync IdealKit and GraphKit. |
1630 | kit.sync_kit(ideal); |
1631 | return __ value(end); |
1632 | } |
1633 | |
1634 | #undef __ |
1635 | #define __ kit. |
1636 | |
1637 | // Allocate a byte array of specified length. |
1638 | Node* PhaseStringOpts::allocate_byte_array(GraphKit& kit, IdealKit* ideal, Node* length) { |
1639 | if (ideal != NULL) { |
1640 | // Sync IdealKit and graphKit. |
1641 | kit.sync_kit(*ideal); |
1642 | } |
1643 | Node* byte_array = NULL; |
1644 | { |
1645 | PreserveReexecuteState preexecs(&kit); |
1646 | // The original jvms is for an allocation of either a String or |
1647 | // StringBuffer so no stack adjustment is necessary for proper |
1648 | // reexecution. If we deoptimize in the slow path the bytecode |
1649 | // will be reexecuted and the char[] allocation will be thrown away. |
1650 | kit.jvms()->set_should_reexecute(true); |
1651 | byte_array = kit.new_array(__ makecon(TypeKlassPtr::make(ciTypeArrayKlass::make(T_BYTE))), |
1652 | length, 1); |
1653 | } |
1654 | |
1655 | // Mark the allocation so that zeroing is skipped since the code |
1656 | // below will overwrite the entire array |
1657 | AllocateArrayNode* byte_alloc = AllocateArrayNode::Ideal_array_allocation(byte_array, _gvn); |
1658 | byte_alloc->maybe_set_complete(_gvn); |
1659 | |
1660 | if (ideal != NULL) { |
1661 | // Sync IdealKit and graphKit. |
1662 | ideal->sync_kit(&kit); |
1663 | } |
1664 | return byte_array; |
1665 | } |
1666 | |
1667 | jbyte PhaseStringOpts::get_constant_coder(GraphKit& kit, Node* str) { |
1668 | assert(str->is_Con(), "String must be constant" ); |
1669 | const TypeOopPtr* str_type = kit.gvn().type(str)->isa_oopptr(); |
1670 | ciInstance* str_instance = str_type->const_oop()->as_instance(); |
1671 | jbyte coder = str_instance->field_value_by_offset(java_lang_String::coder_offset_in_bytes()).as_byte(); |
1672 | assert(CompactStrings || (coder == java_lang_String::CODER_UTF16), "Strings must be UTF16 encoded" ); |
1673 | return coder; |
1674 | } |
1675 | |
1676 | int PhaseStringOpts::get_constant_length(GraphKit& kit, Node* str) { |
1677 | assert(str->is_Con(), "String must be constant" ); |
1678 | return get_constant_value(kit, str)->length(); |
1679 | } |
1680 | |
1681 | ciTypeArray* PhaseStringOpts::get_constant_value(GraphKit& kit, Node* str) { |
1682 | assert(str->is_Con(), "String must be constant" ); |
1683 | const TypeOopPtr* str_type = kit.gvn().type(str)->isa_oopptr(); |
1684 | ciInstance* str_instance = str_type->const_oop()->as_instance(); |
1685 | ciObject* src_array = str_instance->field_value_by_offset(java_lang_String::value_offset_in_bytes()).as_object(); |
1686 | return src_array->as_type_array(); |
1687 | } |
1688 | |
1689 | void PhaseStringOpts::replace_string_concat(StringConcat* sc) { |
1690 | // Log a little info about the transformation |
1691 | sc->maybe_log_transform(); |
1692 | |
1693 | // pull the JVMState of the allocation into a SafePointNode to serve as |
1694 | // as a shim for the insertion of the new code. |
1695 | JVMState* jvms = sc->begin()->jvms()->clone_shallow(C); |
1696 | uint size = sc->begin()->req(); |
1697 | SafePointNode* map = new SafePointNode(size, jvms); |
1698 | |
1699 | // copy the control and memory state from the final call into our |
1700 | // new starting state. This allows any preceeding tests to feed |
1701 | // into the new section of code. |
1702 | for (uint i1 = 0; i1 < TypeFunc::Parms; i1++) { |
1703 | map->init_req(i1, sc->end()->in(i1)); |
1704 | } |
1705 | // blow away old allocation arguments |
1706 | for (uint i1 = TypeFunc::Parms; i1 < jvms->debug_start(); i1++) { |
1707 | map->init_req(i1, C->top()); |
1708 | } |
1709 | // Copy the rest of the inputs for the JVMState |
1710 | for (uint i1 = jvms->debug_start(); i1 < sc->begin()->req(); i1++) { |
1711 | map->init_req(i1, sc->begin()->in(i1)); |
1712 | } |
1713 | // Make sure the memory state is a MergeMem for parsing. |
1714 | if (!map->in(TypeFunc::Memory)->is_MergeMem()) { |
1715 | map->set_req(TypeFunc::Memory, MergeMemNode::make(map->in(TypeFunc::Memory))); |
1716 | } |
1717 | |
1718 | jvms->set_map(map); |
1719 | map->ensure_stack(jvms, jvms->method()->max_stack()); |
1720 | |
1721 | // disconnect all the old StringBuilder calls from the graph |
1722 | sc->eliminate_unneeded_control(); |
1723 | |
1724 | // At this point all the old work has been completely removed from |
1725 | // the graph and the saved JVMState exists at the point where the |
1726 | // final toString call used to be. |
1727 | GraphKit kit(jvms); |
1728 | |
1729 | // There may be uncommon traps which are still using the |
1730 | // intermediate states and these need to be rewritten to point at |
1731 | // the JVMState at the beginning of the transformation. |
1732 | sc->convert_uncommon_traps(kit, jvms); |
1733 | |
1734 | // Now insert the logic to compute the size of the string followed |
1735 | // by all the logic to construct array and resulting string. |
1736 | |
1737 | Node* null_string = __ makecon(TypeInstPtr::make(C->env()->the_null_string())); |
1738 | |
1739 | // Create a region for the overflow checks to merge into. |
1740 | int args = MAX2(sc->num_arguments(), 1); |
1741 | RegionNode* overflow = new RegionNode(args); |
1742 | kit.gvn().set_type(overflow, Type::CONTROL); |
1743 | |
1744 | // Create a hook node to hold onto the individual sizes since they |
1745 | // are need for the copying phase. |
1746 | Node* string_sizes = new Node(args); |
1747 | |
1748 | Node* coder = __ intcon(0); |
1749 | Node* length = __ intcon(0); |
1750 | // If at least one argument is UTF16 encoded, we can fix the encoding. |
1751 | bool coder_fixed = false; |
1752 | |
1753 | if (!CompactStrings) { |
1754 | // Fix encoding of result string to UTF16 |
1755 | coder_fixed = true; |
1756 | coder = __ intcon(java_lang_String::CODER_UTF16); |
1757 | } |
1758 | |
1759 | for (int argi = 0; argi < sc->num_arguments(); argi++) { |
1760 | Node* arg = sc->argument(argi); |
1761 | switch (sc->mode(argi)) { |
1762 | case StringConcat::IntMode: { |
1763 | Node* string_size = int_stringSize(kit, arg); |
1764 | |
1765 | // accumulate total |
1766 | length = __ AddI(length, string_size); |
1767 | |
1768 | // Cache this value for the use by int_toString |
1769 | string_sizes->init_req(argi, string_size); |
1770 | break; |
1771 | } |
1772 | case StringConcat::StringNullCheckMode: { |
1773 | const Type* type = kit.gvn().type(arg); |
1774 | assert(type != TypePtr::NULL_PTR, "missing check" ); |
1775 | if (!type->higher_equal(TypeInstPtr::NOTNULL)) { |
1776 | // Null check with uncommon trap since |
1777 | // StringBuilder(null) throws exception. |
1778 | // Use special uncommon trap instead of |
1779 | // calling normal do_null_check(). |
1780 | Node* p = __ Bool(__ CmpP(arg, kit.null()), BoolTest::ne); |
1781 | IfNode* iff = kit.create_and_map_if(kit.control(), p, PROB_MIN, COUNT_UNKNOWN); |
1782 | overflow->add_req(__ IfFalse(iff)); |
1783 | Node* notnull = __ IfTrue(iff); |
1784 | kit.set_control(notnull); // set control for the cast_not_null |
1785 | arg = kit.cast_not_null(arg, false); |
1786 | sc->set_argument(argi, arg); |
1787 | } |
1788 | assert(kit.gvn().type(arg)->higher_equal(TypeInstPtr::NOTNULL), "sanity" ); |
1789 | // Fallthrough to add string length. |
1790 | } |
1791 | case StringConcat::StringMode: { |
1792 | const Type* type = kit.gvn().type(arg); |
1793 | Node* count = NULL; |
1794 | Node* arg_coder = NULL; |
1795 | if (type == TypePtr::NULL_PTR) { |
1796 | // replace the argument with the null checked version |
1797 | arg = null_string; |
1798 | sc->set_argument(argi, arg); |
1799 | count = kit.load_String_length(arg, true); |
1800 | arg_coder = kit.load_String_coder(arg, true); |
1801 | } else if (!type->higher_equal(TypeInstPtr::NOTNULL)) { |
1802 | // s = s != null ? s : "null"; |
1803 | // length = length + (s.count - s.offset); |
1804 | RegionNode *r = new RegionNode(3); |
1805 | kit.gvn().set_type(r, Type::CONTROL); |
1806 | Node *phi = new PhiNode(r, type); |
1807 | kit.gvn().set_type(phi, phi->bottom_type()); |
1808 | Node* p = __ Bool(__ CmpP(arg, kit.null()), BoolTest::ne); |
1809 | IfNode* iff = kit.create_and_map_if(kit.control(), p, PROB_MIN, COUNT_UNKNOWN); |
1810 | Node* notnull = __ IfTrue(iff); |
1811 | Node* isnull = __ IfFalse(iff); |
1812 | kit.set_control(notnull); // set control for the cast_not_null |
1813 | r->init_req(1, notnull); |
1814 | phi->init_req(1, kit.cast_not_null(arg, false)); |
1815 | r->init_req(2, isnull); |
1816 | phi->init_req(2, null_string); |
1817 | kit.set_control(r); |
1818 | C->record_for_igvn(r); |
1819 | C->record_for_igvn(phi); |
1820 | // replace the argument with the null checked version |
1821 | arg = phi; |
1822 | sc->set_argument(argi, arg); |
1823 | count = kit.load_String_length(arg, true); |
1824 | arg_coder = kit.load_String_coder(arg, true); |
1825 | } else { |
1826 | // A corresponding nullcheck will be connected during IGVN MemNode::Ideal_common_DU_postCCP |
1827 | // kit.control might be a different test, that can be hoisted above the actual nullcheck |
1828 | // in case, that the control input is not null, Ideal_common_DU_postCCP will not look for a nullcheck. |
1829 | count = kit.load_String_length(arg, false); |
1830 | arg_coder = kit.load_String_coder(arg, false); |
1831 | } |
1832 | if (arg->is_Con()) { |
1833 | // Constant string. Get constant coder and length. |
1834 | jbyte const_coder = get_constant_coder(kit, arg); |
1835 | int const_length = get_constant_length(kit, arg); |
1836 | if (const_coder == java_lang_String::CODER_LATIN1) { |
1837 | // Can be latin1 encoded |
1838 | arg_coder = __ intcon(const_coder); |
1839 | count = __ intcon(const_length); |
1840 | } else { |
1841 | // Found UTF16 encoded string. Fix result array encoding to UTF16. |
1842 | coder_fixed = true; |
1843 | coder = __ intcon(const_coder); |
1844 | count = __ intcon(const_length / 2); |
1845 | } |
1846 | } |
1847 | |
1848 | if (!coder_fixed) { |
1849 | coder = __ OrI(coder, arg_coder); |
1850 | } |
1851 | length = __ AddI(length, count); |
1852 | string_sizes->init_req(argi, NULL); |
1853 | break; |
1854 | } |
1855 | case StringConcat::CharMode: { |
1856 | // one character only |
1857 | const TypeInt* t = kit.gvn().type(arg)->is_int(); |
1858 | if (!coder_fixed && t->is_con()) { |
1859 | // Constant char |
1860 | if (t->get_con() <= 255) { |
1861 | // Can be latin1 encoded |
1862 | coder = __ OrI(coder, __ intcon(java_lang_String::CODER_LATIN1)); |
1863 | } else { |
1864 | // Must be UTF16 encoded. Fix result array encoding to UTF16. |
1865 | coder_fixed = true; |
1866 | coder = __ intcon(java_lang_String::CODER_UTF16); |
1867 | } |
1868 | } else if (!coder_fixed) { |
1869 | // Not constant |
1870 | #undef __ |
1871 | #define __ ideal. |
1872 | IdealKit ideal(&kit, true, true); |
1873 | IdealVariable char_coder(ideal); __ declarations_done(); |
1874 | // Check if character can be latin1 encoded |
1875 | __ if_then(arg, BoolTest::le, __ ConI(0xFF)); |
1876 | __ set(char_coder, __ ConI(java_lang_String::CODER_LATIN1)); |
1877 | __ else_(); |
1878 | __ set(char_coder, __ ConI(java_lang_String::CODER_UTF16)); |
1879 | __ end_if(); |
1880 | kit.sync_kit(ideal); |
1881 | coder = __ OrI(coder, __ value(char_coder)); |
1882 | #undef __ |
1883 | #define __ kit. |
1884 | } |
1885 | length = __ AddI(length, __ intcon(1)); |
1886 | break; |
1887 | } |
1888 | default: |
1889 | ShouldNotReachHere(); |
1890 | } |
1891 | if (argi > 0) { |
1892 | // Check that the sum hasn't overflowed |
1893 | IfNode* iff = kit.create_and_map_if(kit.control(), |
1894 | __ Bool(__ CmpI(length, __ intcon(0)), BoolTest::lt), |
1895 | PROB_MIN, COUNT_UNKNOWN); |
1896 | kit.set_control(__ IfFalse(iff)); |
1897 | overflow->set_req(argi, __ IfTrue(iff)); |
1898 | } |
1899 | } |
1900 | |
1901 | { |
1902 | // Hook |
1903 | PreserveJVMState pjvms(&kit); |
1904 | kit.set_control(overflow); |
1905 | C->record_for_igvn(overflow); |
1906 | kit.uncommon_trap(Deoptimization::Reason_intrinsic, |
1907 | Deoptimization::Action_make_not_entrant); |
1908 | } |
1909 | |
1910 | Node* result; |
1911 | if (!kit.stopped()) { |
1912 | assert(CompactStrings || (coder->is_Con() && coder->get_int() == java_lang_String::CODER_UTF16), |
1913 | "Result string must be UTF16 encoded if CompactStrings is disabled" ); |
1914 | |
1915 | Node* dst_array = NULL; |
1916 | if (sc->num_arguments() == 1 && |
1917 | (sc->mode(0) == StringConcat::StringMode || |
1918 | sc->mode(0) == StringConcat::StringNullCheckMode)) { |
1919 | // Handle the case when there is only a single String argument. |
1920 | // In this case, we can just pull the value from the String itself. |
1921 | dst_array = kit.load_String_value(sc->argument(0), true); |
1922 | } else { |
1923 | // Allocate destination byte array according to coder |
1924 | dst_array = allocate_byte_array(kit, NULL, __ LShiftI(length, coder)); |
1925 | |
1926 | // Now copy the string representations into the final byte[] |
1927 | Node* start = __ intcon(0); |
1928 | for (int argi = 0; argi < sc->num_arguments(); argi++) { |
1929 | Node* arg = sc->argument(argi); |
1930 | switch (sc->mode(argi)) { |
1931 | case StringConcat::IntMode: { |
1932 | start = int_getChars(kit, arg, dst_array, coder, start, string_sizes->in(argi)); |
1933 | break; |
1934 | } |
1935 | case StringConcat::StringNullCheckMode: |
1936 | case StringConcat::StringMode: { |
1937 | start = copy_string(kit, arg, dst_array, coder, start); |
1938 | break; |
1939 | } |
1940 | case StringConcat::CharMode: { |
1941 | start = copy_char(kit, arg, dst_array, coder, start); |
1942 | break; |
1943 | } |
1944 | default: |
1945 | ShouldNotReachHere(); |
1946 | } |
1947 | } |
1948 | } |
1949 | |
1950 | // If we're not reusing an existing String allocation then allocate one here. |
1951 | result = sc->string_alloc(); |
1952 | if (result == NULL) { |
1953 | PreserveReexecuteState preexecs(&kit); |
1954 | // The original jvms is for an allocation of either a String or |
1955 | // StringBuffer so no stack adjustment is necessary for proper |
1956 | // reexecution. |
1957 | kit.jvms()->set_should_reexecute(true); |
1958 | result = kit.new_instance(__ makecon(TypeKlassPtr::make(C->env()->String_klass()))); |
1959 | } |
1960 | |
1961 | // Initialize the string |
1962 | kit.store_String_value(result, dst_array); |
1963 | kit.store_String_coder(result, coder); |
1964 | |
1965 | // The value field is final. Emit a barrier here to ensure that the effect |
1966 | // of the initialization is committed to memory before any code publishes |
1967 | // a reference to the newly constructed object (see Parse::do_exits()). |
1968 | assert(AllocateNode::Ideal_allocation(result, _gvn) != NULL, "should be newly allocated" ); |
1969 | kit.insert_mem_bar(Op_MemBarRelease, result); |
1970 | } else { |
1971 | result = C->top(); |
1972 | } |
1973 | // hook up the outgoing control and result |
1974 | kit.replace_call(sc->end(), result); |
1975 | |
1976 | // Unhook any hook nodes |
1977 | string_sizes->disconnect_inputs(NULL, C); |
1978 | sc->cleanup(); |
1979 | } |
1980 | |