Mercurial > hg > truffle
comparison src/share/vm/opto/compile.cpp @ 1080:7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
Reviewed-by: kvn, twisti
author | never |
---|---|
date | Thu, 12 Nov 2009 09:24:21 -0800 |
parents | cd18bd5e667c |
children | f96a1a986f7b |
comparison
equal
deleted
inserted
replaced
1078:8e7adf982378 | 1080:7c57aead6d3e |
---|---|
220 } | 220 } |
221 | 221 |
222 bool Compile::valid_bundle_info(const Node *n) { | 222 bool Compile::valid_bundle_info(const Node *n) { |
223 return (_node_bundling_limit > n->_idx); | 223 return (_node_bundling_limit > n->_idx); |
224 } | 224 } |
225 | |
226 | |
227 void Compile::gvn_replace_by(Node* n, Node* nn) { | |
228 for (DUIterator_Last imin, i = n->last_outs(imin); i >= imin; ) { | |
229 Node* use = n->last_out(i); | |
230 bool is_in_table = initial_gvn()->hash_delete(use); | |
231 uint uses_found = 0; | |
232 for (uint j = 0; j < use->len(); j++) { | |
233 if (use->in(j) == n) { | |
234 if (j < use->req()) | |
235 use->set_req(j, nn); | |
236 else | |
237 use->set_prec(j, nn); | |
238 uses_found++; | |
239 } | |
240 } | |
241 if (is_in_table) { | |
242 // reinsert into table | |
243 initial_gvn()->hash_find_insert(use); | |
244 } | |
245 record_for_igvn(use); | |
246 i -= uses_found; // we deleted 1 or more copies of this edge | |
247 } | |
248 } | |
249 | |
250 | |
225 | 251 |
226 | 252 |
227 // Identify all nodes that are reachable from below, useful. | 253 // Identify all nodes that are reachable from below, useful. |
228 // Use breadth-first pass that records state in a Unique_Node_List, | 254 // Use breadth-first pass that records state in a Unique_Node_List, |
229 // recursive traversal is slower. | 255 // recursive traversal is slower. |
551 // Any exceptions that escape from this call must be rethrown | 577 // Any exceptions that escape from this call must be rethrown |
552 // to whatever caller is dynamically above us on the stack. | 578 // to whatever caller is dynamically above us on the stack. |
553 // This is done by a special, unique RethrowNode bound to root. | 579 // This is done by a special, unique RethrowNode bound to root. |
554 rethrow_exceptions(kit.transfer_exceptions_into_jvms()); | 580 rethrow_exceptions(kit.transfer_exceptions_into_jvms()); |
555 } | 581 } |
582 | |
583 if (!failing() && has_stringbuilder()) { | |
584 { | |
585 // remove useless nodes to make the usage analysis simpler | |
586 ResourceMark rm; | |
587 PhaseRemoveUseless pru(initial_gvn(), &for_igvn); | |
588 } | |
589 | |
590 { | |
591 ResourceMark rm; | |
592 print_method("Before StringOpts", 3); | |
593 PhaseStringOpts pso(initial_gvn(), &for_igvn); | |
594 print_method("After StringOpts", 3); | |
595 } | |
596 | |
597 // now inline anything that we skipped the first time around | |
598 while (_late_inlines.length() > 0) { | |
599 CallGenerator* cg = _late_inlines.pop(); | |
600 cg->do_late_inline(); | |
601 } | |
602 } | |
603 assert(_late_inlines.length() == 0, "should have been processed"); | |
556 | 604 |
557 print_method("Before RemoveUseless", 3); | 605 print_method("Before RemoveUseless", 3); |
558 | 606 |
559 // Remove clutter produced by parsing. | 607 // Remove clutter produced by parsing. |
560 if (!failing()) { | 608 if (!failing()) { |
818 env()->set_dependencies(new Dependencies(env())); | 866 env()->set_dependencies(new Dependencies(env())); |
819 | 867 |
820 _fixed_slots = 0; | 868 _fixed_slots = 0; |
821 set_has_split_ifs(false); | 869 set_has_split_ifs(false); |
822 set_has_loops(has_method() && method()->has_loops()); // first approximation | 870 set_has_loops(has_method() && method()->has_loops()); // first approximation |
871 set_has_stringbuilder(false); | |
823 _deopt_happens = true; // start out assuming the worst | 872 _deopt_happens = true; // start out assuming the worst |
824 _trap_can_recompile = false; // no traps emitted yet | 873 _trap_can_recompile = false; // no traps emitted yet |
825 _major_progress = true; // start out assuming good things will happen | 874 _major_progress = true; // start out assuming good things will happen |
826 set_has_unsafe_access(false); | 875 set_has_unsafe_access(false); |
827 Copy::zero_to_bytes(_trap_hist, sizeof(_trap_hist)); | 876 Copy::zero_to_bytes(_trap_hist, sizeof(_trap_hist)); |
2238 in1->disconnect_inputs(NULL); | 2287 in1->disconnect_inputs(NULL); |
2239 } | 2288 } |
2240 break; | 2289 break; |
2241 } | 2290 } |
2242 | 2291 |
2292 case Op_Proj: { | |
2293 if (OptimizeStringConcat) { | |
2294 ProjNode* p = n->as_Proj(); | |
2295 if (p->_is_io_use) { | |
2296 // Separate projections were used for the exception path which | |
2297 // are normally removed by a late inline. If it wasn't inlined | |
2298 // then they will hang around and should just be replaced with | |
2299 // the original one. | |
2300 Node* proj = NULL; | |
2301 // Replace with just one | |
2302 for (SimpleDUIterator i(p->in(0)); i.has_next(); i.next()) { | |
2303 Node *use = i.get(); | |
2304 if (use->is_Proj() && p != use && use->as_Proj()->_con == p->_con) { | |
2305 proj = use; | |
2306 break; | |
2307 } | |
2308 } | |
2309 assert(p != NULL, "must be found"); | |
2310 p->subsume_by(proj); | |
2311 } | |
2312 } | |
2313 break; | |
2314 } | |
2315 | |
2243 case Op_Phi: | 2316 case Op_Phi: |
2244 if (n->as_Phi()->bottom_type()->isa_narrowoop()) { | 2317 if (n->as_Phi()->bottom_type()->isa_narrowoop()) { |
2245 // The EncodeP optimization may create Phi with the same edges | 2318 // The EncodeP optimization may create Phi with the same edges |
2246 // for all paths. It is not handled well by Register Allocator. | 2319 // for all paths. It is not handled well by Register Allocator. |
2247 Node* unique_in = n->in(1); | 2320 Node* unique_in = n->in(1); |