Mercurial > hg > truffle
annotate src/share/vm/c1/c1_Optimizer.cpp @ 1994:6cd6d394f280
7001033: assert(gch->gc_cause() == GCCause::_scavenge_alot || !gch->incremental_collection_failed())
7002546: regression on SpecJbb2005 on 7b118 comparing to 7b117 on small heaps
Summary: Relaxed assertion checking related to incremental_collection_failed flag to allow for ExplicitGCInvokesConcurrent behaviour where we do not want a failing scavenge to bail to a stop-world collection. Parameterized incremental_collection_will_fail() so we can selectively use, or not use, as appropriate, the statistical prediction at specific use sites. This essentially reverts the scavenge bail-out logic to what it was prior to some recent changes that had inadvertently started using the statistical prediction which can be noisy in the presence of bursty loads. Added some associated verbose non-product debugging messages.
Reviewed-by: johnc, tonyp
author | ysr |
---|---|
date | Tue, 07 Dec 2010 21:55:53 -0800 |
parents | f95d63e2154a |
children | 403dc4c1d7f5 |
rev | line source |
---|---|
0 | 1 /* |
1783 | 2 * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved. |
0 | 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 * | |
1552
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
579
diff
changeset
|
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
579
diff
changeset
|
20 * or visit www.oracle.com if you need additional information or have any |
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
579
diff
changeset
|
21 * questions. |
0 | 22 * |
23 */ | |
24 | |
1972 | 25 #include "precompiled.hpp" |
26 #include "c1/c1_Canonicalizer.hpp" | |
27 #include "c1/c1_Optimizer.hpp" | |
28 #include "c1/c1_ValueMap.hpp" | |
29 #include "c1/c1_ValueSet.hpp" | |
30 #include "c1/c1_ValueStack.hpp" | |
31 #include "utilities/bitMap.inline.hpp" | |
0 | 32 |
33 define_array(ValueSetArray, ValueSet*); | |
34 define_stack(ValueSetList, ValueSetArray); | |
35 | |
36 | |
37 Optimizer::Optimizer(IR* ir) { | |
38 assert(ir->is_valid(), "IR must be valid"); | |
39 _ir = ir; | |
40 } | |
41 | |
42 class CE_Eliminator: public BlockClosure { | |
43 private: | |
44 IR* _hir; | |
45 int _cee_count; // the number of CEs successfully eliminated | |
1899 | 46 int _ifop_count; // the number of IfOps successfully simplified |
0 | 47 int _has_substitution; |
48 | |
49 public: | |
1899 | 50 CE_Eliminator(IR* hir) : _cee_count(0), _ifop_count(0), _hir(hir) { |
0 | 51 _has_substitution = false; |
52 _hir->iterate_preorder(this); | |
53 if (_has_substitution) { | |
1899 | 54 // substituted some ifops/phis, so resolve the substitution |
0 | 55 SubstitutionResolver sr(_hir); |
56 } | |
57 } | |
58 int cee_count() const { return _cee_count; } | |
1899 | 59 int ifop_count() const { return _ifop_count; } |
0 | 60 |
61 void adjust_exception_edges(BlockBegin* block, BlockBegin* sux) { | |
62 int e = sux->number_of_exception_handlers(); | |
63 for (int i = 0; i < e; i++) { | |
64 BlockBegin* xhandler = sux->exception_handler_at(i); | |
65 block->add_exception_handler(xhandler); | |
66 | |
67 assert(xhandler->is_predecessor(sux), "missing predecessor"); | |
68 if (sux->number_of_preds() == 0) { | |
69 // sux is disconnected from graph so disconnect from exception handlers | |
70 xhandler->remove_predecessor(sux); | |
71 } | |
72 if (!xhandler->is_predecessor(block)) { | |
73 xhandler->add_predecessor(block); | |
74 } | |
75 } | |
76 } | |
77 | |
1899 | 78 virtual void block_do(BlockBegin* block); |
79 | |
80 private: | |
81 Value make_ifop(Value x, Instruction::Condition cond, Value y, Value tval, Value fval); | |
82 }; | |
0 | 83 |
1899 | 84 void CE_Eliminator::block_do(BlockBegin* block) { |
85 // 1) find conditional expression | |
86 // check if block ends with an If | |
87 If* if_ = block->end()->as_If(); | |
88 if (if_ == NULL) return; | |
0 | 89 |
1899 | 90 // check if If works on int or object types |
91 // (we cannot handle If's working on long, float or doubles yet, | |
92 // since IfOp doesn't support them - these If's show up if cmp | |
93 // operations followed by If's are eliminated) | |
94 ValueType* if_type = if_->x()->type(); | |
95 if (!if_type->is_int() && !if_type->is_object()) return; | |
0 | 96 |
1899 | 97 BlockBegin* t_block = if_->tsux(); |
98 BlockBegin* f_block = if_->fsux(); | |
99 Instruction* t_cur = t_block->next(); | |
100 Instruction* f_cur = f_block->next(); | |
0 | 101 |
1899 | 102 // one Constant may be present between BlockBegin and BlockEnd |
103 Value t_const = NULL; | |
104 Value f_const = NULL; | |
105 if (t_cur->as_Constant() != NULL && !t_cur->can_trap()) { | |
106 t_const = t_cur; | |
107 t_cur = t_cur->next(); | |
108 } | |
109 if (f_cur->as_Constant() != NULL && !f_cur->can_trap()) { | |
110 f_const = f_cur; | |
111 f_cur = f_cur->next(); | |
112 } | |
0 | 113 |
1899 | 114 // check if both branches end with a goto |
115 Goto* t_goto = t_cur->as_Goto(); | |
116 if (t_goto == NULL) return; | |
117 Goto* f_goto = f_cur->as_Goto(); | |
118 if (f_goto == NULL) return; | |
0 | 119 |
1899 | 120 // check if both gotos merge into the same block |
121 BlockBegin* sux = t_goto->default_sux(); | |
122 if (sux != f_goto->default_sux()) return; | |
0 | 123 |
1899 | 124 // check if at least one word was pushed on sux_state |
125 ValueStack* sux_state = sux->state(); | |
126 if (sux_state->stack_size() <= if_->state()->stack_size()) return; | |
0 | 127 |
1899 | 128 // check if phi function is present at end of successor stack and that |
129 // only this phi was pushed on the stack | |
130 Value sux_phi = sux_state->stack_at(if_->state()->stack_size()); | |
131 if (sux_phi == NULL || sux_phi->as_Phi() == NULL || sux_phi->as_Phi()->block() != sux) return; | |
132 if (sux_phi->type()->size() != sux_state->stack_size() - if_->state()->stack_size()) return; | |
0 | 133 |
1899 | 134 // get the values that were pushed in the true- and false-branch |
135 Value t_value = t_goto->state()->stack_at(if_->state()->stack_size()); | |
136 Value f_value = f_goto->state()->stack_at(if_->state()->stack_size()); | |
137 | |
138 // backend does not support floats | |
139 assert(t_value->type()->base() == f_value->type()->base(), "incompatible types"); | |
140 if (t_value->type()->is_float_kind()) return; | |
0 | 141 |
1899 | 142 // check that successor has no other phi functions but sux_phi |
143 // this can happen when t_block or f_block contained additonal stores to local variables | |
144 // that are no longer represented by explicit instructions | |
145 for_each_phi_fun(sux, phi, | |
146 if (phi != sux_phi) return; | |
147 ); | |
148 // true and false blocks can't have phis | |
149 for_each_phi_fun(t_block, phi, return; ); | |
150 for_each_phi_fun(f_block, phi, return; ); | |
151 | |
152 // 2) substitute conditional expression | |
153 // with an IfOp followed by a Goto | |
154 // cut if_ away and get node before | |
155 Instruction* cur_end = if_->prev(block); | |
0 | 156 |
1899 | 157 // append constants of true- and false-block if necessary |
158 // clone constants because original block must not be destroyed | |
159 assert((t_value != f_const && f_value != t_const) || t_const == f_const, "mismatch"); | |
160 if (t_value == t_const) { | |
161 t_value = new Constant(t_const->type()); | |
162 NOT_PRODUCT(t_value->set_printable_bci(if_->printable_bci())); | |
163 cur_end = cur_end->set_next(t_value); | |
164 } | |
165 if (f_value == f_const) { | |
166 f_value = new Constant(f_const->type()); | |
167 NOT_PRODUCT(f_value->set_printable_bci(if_->printable_bci())); | |
168 cur_end = cur_end->set_next(f_value); | |
169 } | |
0 | 170 |
1899 | 171 Value result = make_ifop(if_->x(), if_->cond(), if_->y(), t_value, f_value); |
172 assert(result != NULL, "make_ifop must return a non-null instruction"); | |
173 if (!result->is_linked() && result->can_be_linked()) { | |
1819 | 174 NOT_PRODUCT(result->set_printable_bci(if_->printable_bci())); |
175 cur_end = cur_end->set_next(result); | |
1899 | 176 } |
0 | 177 |
1899 | 178 // append Goto to successor |
179 ValueStack* state_before = if_->is_safepoint() ? if_->state_before() : NULL; | |
180 Goto* goto_ = new Goto(sux, state_before, if_->is_safepoint() || t_goto->is_safepoint() || f_goto->is_safepoint()); | |
181 | |
182 // prepare state for Goto | |
183 ValueStack* goto_state = if_->state(); | |
184 while (sux_state->scope() != goto_state->scope()) { | |
185 goto_state = goto_state->caller_state(); | |
186 assert(goto_state != NULL, "states do not match up"); | |
187 } | |
188 goto_state = goto_state->copy(ValueStack::StateAfter, goto_state->bci()); | |
189 goto_state->push(result->type(), result); | |
190 assert(goto_state->is_same(sux_state), "states must match now"); | |
191 goto_->set_state(goto_state); | |
192 | |
193 cur_end = cur_end->set_next(goto_, goto_state->bci()); | |
194 | |
195 // Adjust control flow graph | |
196 BlockBegin::disconnect_edge(block, t_block); | |
197 BlockBegin::disconnect_edge(block, f_block); | |
198 if (t_block->number_of_preds() == 0) { | |
199 BlockBegin::disconnect_edge(t_block, sux); | |
200 } | |
201 adjust_exception_edges(block, t_block); | |
202 if (f_block->number_of_preds() == 0) { | |
203 BlockBegin::disconnect_edge(f_block, sux); | |
204 } | |
205 adjust_exception_edges(block, f_block); | |
206 | |
207 // update block end | |
208 block->set_end(goto_); | |
209 | |
210 // substitute the phi if possible | |
211 if (sux_phi->as_Phi()->operand_count() == 1) { | |
212 assert(sux_phi->as_Phi()->operand_at(0) == result, "screwed up phi"); | |
213 sux_phi->set_subst(result); | |
214 _has_substitution = true; | |
215 } | |
216 | |
217 // 3) successfully eliminated a conditional expression | |
218 _cee_count++; | |
219 if (PrintCEE) { | |
220 tty->print_cr("%d. CEE in B%d (B%d B%d)", cee_count(), block->block_id(), t_block->block_id(), f_block->block_id()); | |
221 tty->print_cr("%d. IfOp in B%d", ifop_count(), block->block_id()); | |
222 } | |
0 | 223 |
1899 | 224 _hir->verify(); |
225 } | |
226 | |
227 Value CE_Eliminator::make_ifop(Value x, Instruction::Condition cond, Value y, Value tval, Value fval) { | |
228 if (!OptimizeIfOps) { | |
229 return new IfOp(x, cond, y, tval, fval); | |
230 } | |
231 | |
232 tval = tval->subst(); | |
233 fval = fval->subst(); | |
234 if (tval == fval) { | |
235 _ifop_count++; | |
236 return tval; | |
237 } | |
238 | |
239 x = x->subst(); | |
240 y = y->subst(); | |
241 | |
242 Constant* y_const = y->as_Constant(); | |
243 if (y_const != NULL) { | |
244 IfOp* x_ifop = x->as_IfOp(); | |
245 if (x_ifop != NULL) { // x is an ifop, y is a constant | |
246 Constant* x_tval_const = x_ifop->tval()->subst()->as_Constant(); | |
247 Constant* x_fval_const = x_ifop->fval()->subst()->as_Constant(); | |
0 | 248 |
1899 | 249 if (x_tval_const != NULL && x_fval_const != NULL) { |
250 Instruction::Condition x_ifop_cond = x_ifop->cond(); | |
251 | |
252 Constant::CompareResult t_compare_res = x_tval_const->compare(cond, y_const); | |
253 Constant::CompareResult f_compare_res = x_fval_const->compare(cond, y_const); | |
254 | |
255 guarantee(t_compare_res != Constant::not_comparable && f_compare_res != Constant::not_comparable, "incomparable constants in IfOp"); | |
256 | |
257 Value new_tval = t_compare_res == Constant::cond_true ? tval : fval; | |
258 Value new_fval = f_compare_res == Constant::cond_true ? tval : fval; | |
0 | 259 |
1899 | 260 _ifop_count++; |
261 if (new_tval == new_fval) { | |
262 return new_tval; | |
263 } else { | |
264 return new IfOp(x_ifop->x(), x_ifop_cond, x_ifop->y(), new_tval, new_fval); | |
265 } | |
266 } | |
267 } else { | |
268 Constant* x_const = x->as_Constant(); | |
269 if (x_const != NULL) { // x and y are constants | |
270 Constant::CompareResult x_compare_res = x_const->compare(cond, y_const); | |
271 guarantee(x_compare_res != Constant::not_comparable, "incomparable constants in IfOp"); | |
272 | |
273 _ifop_count++; | |
274 return x_compare_res == Constant::cond_true ? tval : fval; | |
275 } | |
0 | 276 } |
277 } | |
1899 | 278 return new IfOp(x, cond, y, tval, fval); |
279 } | |
0 | 280 |
281 void Optimizer::eliminate_conditional_expressions() { | |
282 // find conditional expressions & replace them with IfOps | |
283 CE_Eliminator ce(ir()); | |
284 } | |
285 | |
286 class BlockMerger: public BlockClosure { | |
287 private: | |
288 IR* _hir; | |
289 int _merge_count; // the number of block pairs successfully merged | |
290 | |
291 public: | |
292 BlockMerger(IR* hir) | |
293 : _hir(hir) | |
294 , _merge_count(0) | |
295 { | |
296 _hir->iterate_preorder(this); | |
297 } | |
298 | |
299 bool try_merge(BlockBegin* block) { | |
300 BlockEnd* end = block->end(); | |
301 if (end->as_Goto() != NULL) { | |
302 assert(end->number_of_sux() == 1, "end must have exactly one successor"); | |
303 // Note: It would be sufficient to check for the number of successors (= 1) | |
304 // in order to decide if this block can be merged potentially. That | |
305 // would then also include switch statements w/ only a default case. | |
306 // However, in that case we would need to make sure the switch tag | |
307 // expression is executed if it can produce observable side effects. | |
308 // We should probably have the canonicalizer simplifying such switch | |
309 // statements and then we are sure we don't miss these merge opportunities | |
310 // here (was bug - gri 7/7/99). | |
311 BlockBegin* sux = end->default_sux(); | |
312 if (sux->number_of_preds() == 1 && !sux->is_entry_block() && !end->is_safepoint()) { | |
313 // merge the two blocks | |
314 | |
315 #ifdef ASSERT | |
316 // verify that state at the end of block and at the beginning of sux are equal | |
317 // no phi functions must be present at beginning of sux | |
318 ValueStack* sux_state = sux->state(); | |
319 ValueStack* end_state = end->state(); | |
1819 | 320 |
321 assert(end_state->scope() == sux_state->scope(), "scopes must match"); | |
0 | 322 assert(end_state->stack_size() == sux_state->stack_size(), "stack not equal"); |
323 assert(end_state->locals_size() == sux_state->locals_size(), "locals not equal"); | |
324 | |
325 int index; | |
326 Value sux_value; | |
327 for_each_stack_value(sux_state, index, sux_value) { | |
328 assert(sux_value == end_state->stack_at(index), "stack not equal"); | |
329 } | |
330 for_each_local_value(sux_state, index, sux_value) { | |
331 assert(sux_value == end_state->local_at(index), "locals not equal"); | |
332 } | |
333 assert(sux_state->caller_state() == end_state->caller_state(), "caller not equal"); | |
334 #endif | |
335 | |
336 // find instruction before end & append first instruction of sux block | |
337 Instruction* prev = end->prev(block); | |
338 Instruction* next = sux->next(); | |
339 assert(prev->as_BlockEnd() == NULL, "must not be a BlockEnd"); | |
1819 | 340 prev->set_next(next); |
0 | 341 sux->disconnect_from_graph(); |
342 block->set_end(sux->end()); | |
343 // add exception handlers of deleted block, if any | |
344 for (int k = 0; k < sux->number_of_exception_handlers(); k++) { | |
345 BlockBegin* xhandler = sux->exception_handler_at(k); | |
346 block->add_exception_handler(xhandler); | |
347 | |
348 // also substitute predecessor of exception handler | |
349 assert(xhandler->is_predecessor(sux), "missing predecessor"); | |
350 xhandler->remove_predecessor(sux); | |
351 if (!xhandler->is_predecessor(block)) { | |
352 xhandler->add_predecessor(block); | |
353 } | |
354 } | |
355 | |
356 // debugging output | |
357 _merge_count++; | |
358 if (PrintBlockElimination) { | |
359 tty->print_cr("%d. merged B%d & B%d (stack size = %d)", | |
360 _merge_count, block->block_id(), sux->block_id(), sux->state()->stack_size()); | |
361 } | |
362 | |
363 _hir->verify(); | |
364 | |
365 If* if_ = block->end()->as_If(); | |
366 if (if_) { | |
367 IfOp* ifop = if_->x()->as_IfOp(); | |
368 Constant* con = if_->y()->as_Constant(); | |
369 bool swapped = false; | |
370 if (!con || !ifop) { | |
371 ifop = if_->y()->as_IfOp(); | |
372 con = if_->x()->as_Constant(); | |
373 swapped = true; | |
374 } | |
375 if (con && ifop) { | |
376 Constant* tval = ifop->tval()->as_Constant(); | |
377 Constant* fval = ifop->fval()->as_Constant(); | |
378 if (tval && fval) { | |
379 // Find the instruction before if_, starting with ifop. | |
380 // When if_ and ifop are not in the same block, prev | |
381 // becomes NULL In such (rare) cases it is not | |
382 // profitable to perform the optimization. | |
383 Value prev = ifop; | |
384 while (prev != NULL && prev->next() != if_) { | |
385 prev = prev->next(); | |
386 } | |
387 | |
388 if (prev != NULL) { | |
389 Instruction::Condition cond = if_->cond(); | |
390 BlockBegin* tsux = if_->tsux(); | |
391 BlockBegin* fsux = if_->fsux(); | |
392 if (swapped) { | |
393 cond = Instruction::mirror(cond); | |
394 } | |
395 | |
396 BlockBegin* tblock = tval->compare(cond, con, tsux, fsux); | |
397 BlockBegin* fblock = fval->compare(cond, con, tsux, fsux); | |
398 if (tblock != fblock && !if_->is_safepoint()) { | |
399 If* newif = new If(ifop->x(), ifop->cond(), false, ifop->y(), | |
400 tblock, fblock, if_->state_before(), if_->is_safepoint()); | |
401 newif->set_state(if_->state()->copy()); | |
402 | |
403 assert(prev->next() == if_, "must be guaranteed by above search"); | |
1819 | 404 NOT_PRODUCT(newif->set_printable_bci(if_->printable_bci())); |
405 prev->set_next(newif); | |
0 | 406 block->set_end(newif); |
407 | |
408 _merge_count++; | |
409 if (PrintBlockElimination) { | |
410 tty->print_cr("%d. replaced If and IfOp at end of B%d with single If", _merge_count, block->block_id()); | |
411 } | |
412 | |
413 _hir->verify(); | |
414 } | |
415 } | |
416 } | |
417 } | |
418 } | |
419 | |
420 return true; | |
421 } | |
422 } | |
423 return false; | |
424 } | |
425 | |
426 virtual void block_do(BlockBegin* block) { | |
427 _hir->verify(); | |
428 // repeat since the same block may merge again | |
429 while (try_merge(block)) { | |
430 _hir->verify(); | |
431 } | |
432 } | |
433 }; | |
434 | |
435 | |
436 void Optimizer::eliminate_blocks() { | |
437 // merge blocks if possible | |
438 BlockMerger bm(ir()); | |
439 } | |
440 | |
441 | |
442 class NullCheckEliminator; | |
443 class NullCheckVisitor: public InstructionVisitor { | |
444 private: | |
445 NullCheckEliminator* _nce; | |
446 NullCheckEliminator* nce() { return _nce; } | |
447 | |
448 public: | |
449 NullCheckVisitor() {} | |
450 | |
451 void set_eliminator(NullCheckEliminator* nce) { _nce = nce; } | |
452 | |
453 void do_Phi (Phi* x); | |
454 void do_Local (Local* x); | |
455 void do_Constant (Constant* x); | |
456 void do_LoadField (LoadField* x); | |
457 void do_StoreField (StoreField* x); | |
458 void do_ArrayLength (ArrayLength* x); | |
459 void do_LoadIndexed (LoadIndexed* x); | |
460 void do_StoreIndexed (StoreIndexed* x); | |
461 void do_NegateOp (NegateOp* x); | |
462 void do_ArithmeticOp (ArithmeticOp* x); | |
463 void do_ShiftOp (ShiftOp* x); | |
464 void do_LogicOp (LogicOp* x); | |
465 void do_CompareOp (CompareOp* x); | |
466 void do_IfOp (IfOp* x); | |
467 void do_Convert (Convert* x); | |
468 void do_NullCheck (NullCheck* x); | |
469 void do_Invoke (Invoke* x); | |
470 void do_NewInstance (NewInstance* x); | |
471 void do_NewTypeArray (NewTypeArray* x); | |
472 void do_NewObjectArray (NewObjectArray* x); | |
473 void do_NewMultiArray (NewMultiArray* x); | |
474 void do_CheckCast (CheckCast* x); | |
475 void do_InstanceOf (InstanceOf* x); | |
476 void do_MonitorEnter (MonitorEnter* x); | |
477 void do_MonitorExit (MonitorExit* x); | |
478 void do_Intrinsic (Intrinsic* x); | |
479 void do_BlockBegin (BlockBegin* x); | |
480 void do_Goto (Goto* x); | |
481 void do_If (If* x); | |
482 void do_IfInstanceOf (IfInstanceOf* x); | |
483 void do_TableSwitch (TableSwitch* x); | |
484 void do_LookupSwitch (LookupSwitch* x); | |
485 void do_Return (Return* x); | |
486 void do_Throw (Throw* x); | |
487 void do_Base (Base* x); | |
488 void do_OsrEntry (OsrEntry* x); | |
489 void do_ExceptionObject(ExceptionObject* x); | |
490 void do_RoundFP (RoundFP* x); | |
491 void do_UnsafeGetRaw (UnsafeGetRaw* x); | |
492 void do_UnsafePutRaw (UnsafePutRaw* x); | |
493 void do_UnsafeGetObject(UnsafeGetObject* x); | |
494 void do_UnsafePutObject(UnsafePutObject* x); | |
495 void do_UnsafePrefetchRead (UnsafePrefetchRead* x); | |
496 void do_UnsafePrefetchWrite(UnsafePrefetchWrite* x); | |
497 void do_ProfileCall (ProfileCall* x); | |
1783 | 498 void do_ProfileInvoke (ProfileInvoke* x); |
0 | 499 }; |
500 | |
501 | |
502 // Because of a static contained within (for the purpose of iteration | |
503 // over instructions), it is only valid to have one of these active at | |
504 // a time | |
1584 | 505 class NullCheckEliminator: public ValueVisitor { |
0 | 506 private: |
507 Optimizer* _opt; | |
508 | |
509 ValueSet* _visitable_instructions; // Visit each instruction only once per basic block | |
510 BlockList* _work_list; // Basic blocks to visit | |
511 | |
512 bool visitable(Value x) { | |
513 assert(_visitable_instructions != NULL, "check"); | |
514 return _visitable_instructions->contains(x); | |
515 } | |
516 void mark_visited(Value x) { | |
517 assert(_visitable_instructions != NULL, "check"); | |
518 _visitable_instructions->remove(x); | |
519 } | |
520 void mark_visitable(Value x) { | |
521 assert(_visitable_instructions != NULL, "check"); | |
522 _visitable_instructions->put(x); | |
523 } | |
524 void clear_visitable_state() { | |
525 assert(_visitable_instructions != NULL, "check"); | |
526 _visitable_instructions->clear(); | |
527 } | |
528 | |
529 ValueSet* _set; // current state, propagated to subsequent BlockBegins | |
530 ValueSetList _block_states; // BlockBegin null-check states for all processed blocks | |
531 NullCheckVisitor _visitor; | |
532 NullCheck* _last_explicit_null_check; | |
533 | |
534 bool set_contains(Value x) { assert(_set != NULL, "check"); return _set->contains(x); } | |
535 void set_put (Value x) { assert(_set != NULL, "check"); _set->put(x); } | |
536 void set_remove (Value x) { assert(_set != NULL, "check"); _set->remove(x); } | |
537 | |
538 BlockList* work_list() { return _work_list; } | |
539 | |
540 void iterate_all(); | |
541 void iterate_one(BlockBegin* block); | |
542 | |
543 ValueSet* state() { return _set; } | |
544 void set_state_from (ValueSet* state) { _set->set_from(state); } | |
545 ValueSet* state_for (BlockBegin* block) { return _block_states[block->block_id()]; } | |
546 void set_state_for (BlockBegin* block, ValueSet* stack) { _block_states[block->block_id()] = stack; } | |
547 // Returns true if caused a change in the block's state. | |
548 bool merge_state_for(BlockBegin* block, | |
549 ValueSet* incoming_state); | |
550 | |
551 public: | |
552 // constructor | |
553 NullCheckEliminator(Optimizer* opt) | |
554 : _opt(opt) | |
555 , _set(new ValueSet()) | |
556 , _last_explicit_null_check(NULL) | |
557 , _block_states(BlockBegin::number_of_blocks(), NULL) | |
558 , _work_list(new BlockList()) { | |
559 _visitable_instructions = new ValueSet(); | |
560 _visitor.set_eliminator(this); | |
561 } | |
562 | |
563 Optimizer* opt() { return _opt; } | |
564 IR* ir () { return opt()->ir(); } | |
565 | |
566 // Process a graph | |
567 void iterate(BlockBegin* root); | |
568 | |
1584 | 569 void visit(Value* f); |
570 | |
0 | 571 // In some situations (like NullCheck(x); getfield(x)) the debug |
572 // information from the explicit NullCheck can be used to populate | |
573 // the getfield, even if the two instructions are in different | |
574 // scopes; this allows implicit null checks to be used but the | |
575 // correct exception information to be generated. We must clear the | |
576 // last-traversed NullCheck when we reach a potentially-exception- | |
577 // throwing instruction, as well as in some other cases. | |
578 void set_last_explicit_null_check(NullCheck* check) { _last_explicit_null_check = check; } | |
579 NullCheck* last_explicit_null_check() { return _last_explicit_null_check; } | |
580 Value last_explicit_null_check_obj() { return (_last_explicit_null_check | |
581 ? _last_explicit_null_check->obj() | |
582 : NULL); } | |
583 NullCheck* consume_last_explicit_null_check() { | |
584 _last_explicit_null_check->unpin(Instruction::PinExplicitNullCheck); | |
585 _last_explicit_null_check->set_can_trap(false); | |
586 return _last_explicit_null_check; | |
587 } | |
588 void clear_last_explicit_null_check() { _last_explicit_null_check = NULL; } | |
589 | |
590 // Handlers for relevant instructions | |
591 // (separated out from NullCheckVisitor for clarity) | |
592 | |
593 // The basic contract is that these must leave the instruction in | |
594 // the desired state; must not assume anything about the state of | |
595 // the instruction. We make multiple passes over some basic blocks | |
596 // and the last pass is the only one whose result is valid. | |
597 void handle_AccessField (AccessField* x); | |
598 void handle_ArrayLength (ArrayLength* x); | |
599 void handle_LoadIndexed (LoadIndexed* x); | |
600 void handle_StoreIndexed (StoreIndexed* x); | |
601 void handle_NullCheck (NullCheck* x); | |
602 void handle_Invoke (Invoke* x); | |
603 void handle_NewInstance (NewInstance* x); | |
604 void handle_NewArray (NewArray* x); | |
605 void handle_AccessMonitor (AccessMonitor* x); | |
606 void handle_Intrinsic (Intrinsic* x); | |
607 void handle_ExceptionObject (ExceptionObject* x); | |
608 void handle_Phi (Phi* x); | |
609 }; | |
610 | |
611 | |
612 // NEEDS_CLEANUP | |
613 // There may be other instructions which need to clear the last | |
614 // explicit null check. Anything across which we can not hoist the | |
615 // debug information for a NullCheck instruction must clear it. It | |
616 // might be safer to pattern match "NullCheck ; {AccessField, | |
617 // ArrayLength, LoadIndexed}" but it is more easily structured this way. | |
618 // Should test to see performance hit of clearing it for all handlers | |
619 // with empty bodies below. If it is negligible then we should leave | |
620 // that in for safety, otherwise should think more about it. | |
621 void NullCheckVisitor::do_Phi (Phi* x) { nce()->handle_Phi(x); } | |
622 void NullCheckVisitor::do_Local (Local* x) {} | |
623 void NullCheckVisitor::do_Constant (Constant* x) { /* FIXME: handle object constants */ } | |
624 void NullCheckVisitor::do_LoadField (LoadField* x) { nce()->handle_AccessField(x); } | |
625 void NullCheckVisitor::do_StoreField (StoreField* x) { nce()->handle_AccessField(x); } | |
626 void NullCheckVisitor::do_ArrayLength (ArrayLength* x) { nce()->handle_ArrayLength(x); } | |
627 void NullCheckVisitor::do_LoadIndexed (LoadIndexed* x) { nce()->handle_LoadIndexed(x); } | |
628 void NullCheckVisitor::do_StoreIndexed (StoreIndexed* x) { nce()->handle_StoreIndexed(x); } | |
629 void NullCheckVisitor::do_NegateOp (NegateOp* x) {} | |
630 void NullCheckVisitor::do_ArithmeticOp (ArithmeticOp* x) { if (x->can_trap()) nce()->clear_last_explicit_null_check(); } | |
631 void NullCheckVisitor::do_ShiftOp (ShiftOp* x) {} | |
632 void NullCheckVisitor::do_LogicOp (LogicOp* x) {} | |
633 void NullCheckVisitor::do_CompareOp (CompareOp* x) {} | |
634 void NullCheckVisitor::do_IfOp (IfOp* x) {} | |
635 void NullCheckVisitor::do_Convert (Convert* x) {} | |
636 void NullCheckVisitor::do_NullCheck (NullCheck* x) { nce()->handle_NullCheck(x); } | |
637 void NullCheckVisitor::do_Invoke (Invoke* x) { nce()->handle_Invoke(x); } | |
638 void NullCheckVisitor::do_NewInstance (NewInstance* x) { nce()->handle_NewInstance(x); } | |
639 void NullCheckVisitor::do_NewTypeArray (NewTypeArray* x) { nce()->handle_NewArray(x); } | |
640 void NullCheckVisitor::do_NewObjectArray (NewObjectArray* x) { nce()->handle_NewArray(x); } | |
641 void NullCheckVisitor::do_NewMultiArray (NewMultiArray* x) { nce()->handle_NewArray(x); } | |
642 void NullCheckVisitor::do_CheckCast (CheckCast* x) {} | |
643 void NullCheckVisitor::do_InstanceOf (InstanceOf* x) {} | |
644 void NullCheckVisitor::do_MonitorEnter (MonitorEnter* x) { nce()->handle_AccessMonitor(x); } | |
645 void NullCheckVisitor::do_MonitorExit (MonitorExit* x) { nce()->handle_AccessMonitor(x); } | |
646 void NullCheckVisitor::do_Intrinsic (Intrinsic* x) { nce()->clear_last_explicit_null_check(); } | |
647 void NullCheckVisitor::do_BlockBegin (BlockBegin* x) {} | |
648 void NullCheckVisitor::do_Goto (Goto* x) {} | |
649 void NullCheckVisitor::do_If (If* x) {} | |
650 void NullCheckVisitor::do_IfInstanceOf (IfInstanceOf* x) {} | |
651 void NullCheckVisitor::do_TableSwitch (TableSwitch* x) {} | |
652 void NullCheckVisitor::do_LookupSwitch (LookupSwitch* x) {} | |
653 void NullCheckVisitor::do_Return (Return* x) {} | |
654 void NullCheckVisitor::do_Throw (Throw* x) { nce()->clear_last_explicit_null_check(); } | |
655 void NullCheckVisitor::do_Base (Base* x) {} | |
656 void NullCheckVisitor::do_OsrEntry (OsrEntry* x) {} | |
657 void NullCheckVisitor::do_ExceptionObject(ExceptionObject* x) { nce()->handle_ExceptionObject(x); } | |
658 void NullCheckVisitor::do_RoundFP (RoundFP* x) {} | |
659 void NullCheckVisitor::do_UnsafeGetRaw (UnsafeGetRaw* x) {} | |
660 void NullCheckVisitor::do_UnsafePutRaw (UnsafePutRaw* x) {} | |
661 void NullCheckVisitor::do_UnsafeGetObject(UnsafeGetObject* x) {} | |
662 void NullCheckVisitor::do_UnsafePutObject(UnsafePutObject* x) {} | |
663 void NullCheckVisitor::do_UnsafePrefetchRead (UnsafePrefetchRead* x) {} | |
664 void NullCheckVisitor::do_UnsafePrefetchWrite(UnsafePrefetchWrite* x) {} | |
665 void NullCheckVisitor::do_ProfileCall (ProfileCall* x) { nce()->clear_last_explicit_null_check(); } | |
1783 | 666 void NullCheckVisitor::do_ProfileInvoke (ProfileInvoke* x) {} |
0 | 667 |
668 | |
1584 | 669 void NullCheckEliminator::visit(Value* p) { |
0 | 670 assert(*p != NULL, "should not find NULL instructions"); |
1584 | 671 if (visitable(*p)) { |
672 mark_visited(*p); | |
673 (*p)->visit(&_visitor); | |
0 | 674 } |
675 } | |
676 | |
677 bool NullCheckEliminator::merge_state_for(BlockBegin* block, ValueSet* incoming_state) { | |
678 ValueSet* state = state_for(block); | |
679 if (state == NULL) { | |
680 state = incoming_state->copy(); | |
681 set_state_for(block, state); | |
682 return true; | |
683 } else { | |
684 bool changed = state->set_intersect(incoming_state); | |
685 if (PrintNullCheckElimination && changed) { | |
686 tty->print_cr("Block %d's null check state changed", block->block_id()); | |
687 } | |
688 return changed; | |
689 } | |
690 } | |
691 | |
692 | |
693 void NullCheckEliminator::iterate_all() { | |
694 while (work_list()->length() > 0) { | |
695 iterate_one(work_list()->pop()); | |
696 } | |
697 } | |
698 | |
699 | |
700 void NullCheckEliminator::iterate_one(BlockBegin* block) { | |
701 clear_visitable_state(); | |
702 // clear out an old explicit null checks | |
703 set_last_explicit_null_check(NULL); | |
704 | |
705 if (PrintNullCheckElimination) { | |
706 tty->print_cr(" ...iterating block %d in null check elimination for %s::%s%s", | |
707 block->block_id(), | |
708 ir()->method()->holder()->name()->as_utf8(), | |
709 ir()->method()->name()->as_utf8(), | |
710 ir()->method()->signature()->as_symbol()->as_utf8()); | |
711 } | |
712 | |
713 // Create new state if none present (only happens at root) | |
714 if (state_for(block) == NULL) { | |
715 ValueSet* tmp_state = new ValueSet(); | |
716 set_state_for(block, tmp_state); | |
717 // Initial state is that local 0 (receiver) is non-null for | |
718 // non-static methods | |
719 ValueStack* stack = block->state(); | |
720 IRScope* scope = stack->scope(); | |
721 ciMethod* method = scope->method(); | |
722 if (!method->is_static()) { | |
723 Local* local0 = stack->local_at(0)->as_Local(); | |
724 assert(local0 != NULL, "must be"); | |
725 assert(local0->type() == objectType, "invalid type of receiver"); | |
726 | |
727 if (local0 != NULL) { | |
728 // Local 0 is used in this scope | |
729 tmp_state->put(local0); | |
730 if (PrintNullCheckElimination) { | |
731 tty->print_cr("Local 0 (value %d) proven non-null upon entry", local0->id()); | |
732 } | |
733 } | |
734 } | |
735 } | |
736 | |
737 // Must copy block's state to avoid mutating it during iteration | |
738 // through the block -- otherwise "not-null" states can accidentally | |
739 // propagate "up" through the block during processing of backward | |
740 // branches and algorithm is incorrect (and does not converge) | |
741 set_state_from(state_for(block)); | |
742 | |
743 // allow visiting of Phis belonging to this block | |
744 for_each_phi_fun(block, phi, | |
745 mark_visitable(phi); | |
746 ); | |
747 | |
748 BlockEnd* e = block->end(); | |
749 assert(e != NULL, "incomplete graph"); | |
750 int i; | |
751 | |
752 // Propagate the state before this block into the exception | |
753 // handlers. They aren't true successors since we aren't guaranteed | |
754 // to execute the whole block before executing them. Also putting | |
755 // them on first seems to help reduce the amount of iteration to | |
756 // reach a fixed point. | |
757 for (i = 0; i < block->number_of_exception_handlers(); i++) { | |
758 BlockBegin* next = block->exception_handler_at(i); | |
759 if (merge_state_for(next, state())) { | |
760 if (!work_list()->contains(next)) { | |
761 work_list()->push(next); | |
762 } | |
763 } | |
764 } | |
765 | |
766 // Iterate through block, updating state. | |
767 for (Instruction* instr = block; instr != NULL; instr = instr->next()) { | |
768 // Mark instructions in this block as visitable as they are seen | |
769 // in the instruction list. This keeps the iteration from | |
770 // visiting instructions which are references in other blocks or | |
771 // visiting instructions more than once. | |
772 mark_visitable(instr); | |
1819 | 773 if (instr->is_pinned() || instr->can_trap() || (instr->as_NullCheck() != NULL)) { |
0 | 774 mark_visited(instr); |
1584 | 775 instr->input_values_do(this); |
0 | 776 instr->visit(&_visitor); |
777 } | |
778 } | |
779 | |
780 // Propagate state to successors if necessary | |
781 for (i = 0; i < e->number_of_sux(); i++) { | |
782 BlockBegin* next = e->sux_at(i); | |
783 if (merge_state_for(next, state())) { | |
784 if (!work_list()->contains(next)) { | |
785 work_list()->push(next); | |
786 } | |
787 } | |
788 } | |
789 } | |
790 | |
791 | |
792 void NullCheckEliminator::iterate(BlockBegin* block) { | |
793 work_list()->push(block); | |
794 iterate_all(); | |
795 } | |
796 | |
797 void NullCheckEliminator::handle_AccessField(AccessField* x) { | |
798 if (x->is_static()) { | |
799 if (x->as_LoadField() != NULL) { | |
800 // If the field is a non-null static final object field (as is | |
801 // often the case for sun.misc.Unsafe), put this LoadField into | |
802 // the non-null map | |
803 ciField* field = x->field(); | |
804 if (field->is_constant()) { | |
805 ciConstant field_val = field->constant_value(); | |
806 BasicType field_type = field_val.basic_type(); | |
807 if (field_type == T_OBJECT || field_type == T_ARRAY) { | |
808 ciObject* obj_val = field_val.as_object(); | |
809 if (!obj_val->is_null_object()) { | |
810 if (PrintNullCheckElimination) { | |
811 tty->print_cr("AccessField %d proven non-null by static final non-null oop check", | |
812 x->id()); | |
813 } | |
814 set_put(x); | |
815 } | |
816 } | |
817 } | |
818 } | |
819 // Be conservative | |
820 clear_last_explicit_null_check(); | |
821 return; | |
822 } | |
823 | |
824 Value obj = x->obj(); | |
825 if (set_contains(obj)) { | |
826 // Value is non-null => update AccessField | |
827 if (last_explicit_null_check_obj() == obj && !x->needs_patching()) { | |
828 x->set_explicit_null_check(consume_last_explicit_null_check()); | |
829 x->set_needs_null_check(true); | |
830 if (PrintNullCheckElimination) { | |
831 tty->print_cr("Folded NullCheck %d into AccessField %d's null check for value %d", | |
832 x->explicit_null_check()->id(), x->id(), obj->id()); | |
833 } | |
834 } else { | |
835 x->set_explicit_null_check(NULL); | |
836 x->set_needs_null_check(false); | |
837 if (PrintNullCheckElimination) { | |
838 tty->print_cr("Eliminated AccessField %d's null check for value %d", x->id(), obj->id()); | |
839 } | |
840 } | |
841 } else { | |
842 set_put(obj); | |
843 if (PrintNullCheckElimination) { | |
844 tty->print_cr("AccessField %d of value %d proves value to be non-null", x->id(), obj->id()); | |
845 } | |
846 // Ensure previous passes do not cause wrong state | |
847 x->set_needs_null_check(true); | |
848 x->set_explicit_null_check(NULL); | |
849 } | |
850 clear_last_explicit_null_check(); | |
851 } | |
852 | |
853 | |
854 void NullCheckEliminator::handle_ArrayLength(ArrayLength* x) { | |
855 Value array = x->array(); | |
856 if (set_contains(array)) { | |
857 // Value is non-null => update AccessArray | |
858 if (last_explicit_null_check_obj() == array) { | |
859 x->set_explicit_null_check(consume_last_explicit_null_check()); | |
860 x->set_needs_null_check(true); | |
861 if (PrintNullCheckElimination) { | |
862 tty->print_cr("Folded NullCheck %d into ArrayLength %d's null check for value %d", | |
863 x->explicit_null_check()->id(), x->id(), array->id()); | |
864 } | |
865 } else { | |
866 x->set_explicit_null_check(NULL); | |
867 x->set_needs_null_check(false); | |
868 if (PrintNullCheckElimination) { | |
869 tty->print_cr("Eliminated ArrayLength %d's null check for value %d", x->id(), array->id()); | |
870 } | |
871 } | |
872 } else { | |
873 set_put(array); | |
874 if (PrintNullCheckElimination) { | |
875 tty->print_cr("ArrayLength %d of value %d proves value to be non-null", x->id(), array->id()); | |
876 } | |
877 // Ensure previous passes do not cause wrong state | |
878 x->set_needs_null_check(true); | |
879 x->set_explicit_null_check(NULL); | |
880 } | |
881 clear_last_explicit_null_check(); | |
882 } | |
883 | |
884 | |
885 void NullCheckEliminator::handle_LoadIndexed(LoadIndexed* x) { | |
886 Value array = x->array(); | |
887 if (set_contains(array)) { | |
888 // Value is non-null => update AccessArray | |
889 if (last_explicit_null_check_obj() == array) { | |
890 x->set_explicit_null_check(consume_last_explicit_null_check()); | |
891 x->set_needs_null_check(true); | |
892 if (PrintNullCheckElimination) { | |
893 tty->print_cr("Folded NullCheck %d into LoadIndexed %d's null check for value %d", | |
894 x->explicit_null_check()->id(), x->id(), array->id()); | |
895 } | |
896 } else { | |
897 x->set_explicit_null_check(NULL); | |
898 x->set_needs_null_check(false); | |
899 if (PrintNullCheckElimination) { | |
900 tty->print_cr("Eliminated LoadIndexed %d's null check for value %d", x->id(), array->id()); | |
901 } | |
902 } | |
903 } else { | |
904 set_put(array); | |
905 if (PrintNullCheckElimination) { | |
906 tty->print_cr("LoadIndexed %d of value %d proves value to be non-null", x->id(), array->id()); | |
907 } | |
908 // Ensure previous passes do not cause wrong state | |
909 x->set_needs_null_check(true); | |
910 x->set_explicit_null_check(NULL); | |
911 } | |
912 clear_last_explicit_null_check(); | |
913 } | |
914 | |
915 | |
916 void NullCheckEliminator::handle_StoreIndexed(StoreIndexed* x) { | |
917 Value array = x->array(); | |
918 if (set_contains(array)) { | |
919 // Value is non-null => update AccessArray | |
920 if (PrintNullCheckElimination) { | |
921 tty->print_cr("Eliminated StoreIndexed %d's null check for value %d", x->id(), array->id()); | |
922 } | |
923 x->set_needs_null_check(false); | |
924 } else { | |
925 set_put(array); | |
926 if (PrintNullCheckElimination) { | |
927 tty->print_cr("StoreIndexed %d of value %d proves value to be non-null", x->id(), array->id()); | |
928 } | |
929 // Ensure previous passes do not cause wrong state | |
930 x->set_needs_null_check(true); | |
931 } | |
932 clear_last_explicit_null_check(); | |
933 } | |
934 | |
935 | |
936 void NullCheckEliminator::handle_NullCheck(NullCheck* x) { | |
937 Value obj = x->obj(); | |
938 if (set_contains(obj)) { | |
939 // Already proven to be non-null => this NullCheck is useless | |
940 if (PrintNullCheckElimination) { | |
941 tty->print_cr("Eliminated NullCheck %d for value %d", x->id(), obj->id()); | |
942 } | |
943 // Don't unpin since that may shrink obj's live range and make it unavailable for debug info. | |
944 // The code generator won't emit LIR for a NullCheck that cannot trap. | |
945 x->set_can_trap(false); | |
946 } else { | |
947 // May be null => add to map and set last explicit NullCheck | |
948 x->set_can_trap(true); | |
949 // make sure it's pinned if it can trap | |
950 x->pin(Instruction::PinExplicitNullCheck); | |
951 set_put(obj); | |
952 set_last_explicit_null_check(x); | |
953 if (PrintNullCheckElimination) { | |
954 tty->print_cr("NullCheck %d of value %d proves value to be non-null", x->id(), obj->id()); | |
955 } | |
956 } | |
957 } | |
958 | |
959 | |
960 void NullCheckEliminator::handle_Invoke(Invoke* x) { | |
961 if (!x->has_receiver()) { | |
962 // Be conservative | |
963 clear_last_explicit_null_check(); | |
964 return; | |
965 } | |
966 | |
967 Value recv = x->receiver(); | |
968 if (!set_contains(recv)) { | |
969 set_put(recv); | |
970 if (PrintNullCheckElimination) { | |
971 tty->print_cr("Invoke %d of value %d proves value to be non-null", x->id(), recv->id()); | |
972 } | |
973 } | |
974 clear_last_explicit_null_check(); | |
975 } | |
976 | |
977 | |
978 void NullCheckEliminator::handle_NewInstance(NewInstance* x) { | |
979 set_put(x); | |
980 if (PrintNullCheckElimination) { | |
981 tty->print_cr("NewInstance %d is non-null", x->id()); | |
982 } | |
983 } | |
984 | |
985 | |
986 void NullCheckEliminator::handle_NewArray(NewArray* x) { | |
987 set_put(x); | |
988 if (PrintNullCheckElimination) { | |
989 tty->print_cr("NewArray %d is non-null", x->id()); | |
990 } | |
991 } | |
992 | |
993 | |
994 void NullCheckEliminator::handle_ExceptionObject(ExceptionObject* x) { | |
995 set_put(x); | |
996 if (PrintNullCheckElimination) { | |
997 tty->print_cr("ExceptionObject %d is non-null", x->id()); | |
998 } | |
999 } | |
1000 | |
1001 | |
1002 void NullCheckEliminator::handle_AccessMonitor(AccessMonitor* x) { | |
1003 Value obj = x->obj(); | |
1004 if (set_contains(obj)) { | |
1005 // Value is non-null => update AccessMonitor | |
1006 if (PrintNullCheckElimination) { | |
1007 tty->print_cr("Eliminated AccessMonitor %d's null check for value %d", x->id(), obj->id()); | |
1008 } | |
1009 x->set_needs_null_check(false); | |
1010 } else { | |
1011 set_put(obj); | |
1012 if (PrintNullCheckElimination) { | |
1013 tty->print_cr("AccessMonitor %d of value %d proves value to be non-null", x->id(), obj->id()); | |
1014 } | |
1015 // Ensure previous passes do not cause wrong state | |
1016 x->set_needs_null_check(true); | |
1017 } | |
1018 clear_last_explicit_null_check(); | |
1019 } | |
1020 | |
1021 | |
1022 void NullCheckEliminator::handle_Intrinsic(Intrinsic* x) { | |
1023 if (!x->has_receiver()) { | |
1024 // Be conservative | |
1025 clear_last_explicit_null_check(); | |
1026 return; | |
1027 } | |
1028 | |
1029 Value recv = x->receiver(); | |
1030 if (set_contains(recv)) { | |
1031 // Value is non-null => update Intrinsic | |
1032 if (PrintNullCheckElimination) { | |
1033 tty->print_cr("Eliminated Intrinsic %d's null check for value %d", x->id(), recv->id()); | |
1034 } | |
1035 x->set_needs_null_check(false); | |
1036 } else { | |
1037 set_put(recv); | |
1038 if (PrintNullCheckElimination) { | |
1039 tty->print_cr("Intrinsic %d of value %d proves value to be non-null", x->id(), recv->id()); | |
1040 } | |
1041 // Ensure previous passes do not cause wrong state | |
1042 x->set_needs_null_check(true); | |
1043 } | |
1044 clear_last_explicit_null_check(); | |
1045 } | |
1046 | |
1047 | |
1048 void NullCheckEliminator::handle_Phi(Phi* x) { | |
1049 int i; | |
1050 bool all_non_null = true; | |
1051 if (x->is_illegal()) { | |
1052 all_non_null = false; | |
1053 } else { | |
1054 for (i = 0; i < x->operand_count(); i++) { | |
1055 Value input = x->operand_at(i); | |
1056 if (!set_contains(input)) { | |
1057 all_non_null = false; | |
1058 } | |
1059 } | |
1060 } | |
1061 | |
1062 if (all_non_null) { | |
1063 // Value is non-null => update Phi | |
1064 if (PrintNullCheckElimination) { | |
1065 tty->print_cr("Eliminated Phi %d's null check for phifun because all inputs are non-null", x->id()); | |
1066 } | |
1067 x->set_needs_null_check(false); | |
1068 } else if (set_contains(x)) { | |
1069 set_remove(x); | |
1070 } | |
1071 } | |
1072 | |
1073 | |
1074 void Optimizer::eliminate_null_checks() { | |
1075 ResourceMark rm; | |
1076 | |
1077 NullCheckEliminator nce(this); | |
1078 | |
1079 if (PrintNullCheckElimination) { | |
1080 tty->print_cr("Starting null check elimination for method %s::%s%s", | |
1081 ir()->method()->holder()->name()->as_utf8(), | |
1082 ir()->method()->name()->as_utf8(), | |
1083 ir()->method()->signature()->as_symbol()->as_utf8()); | |
1084 } | |
1085 | |
1086 // Apply to graph | |
1087 nce.iterate(ir()->start()); | |
1088 | |
1089 // walk over the graph looking for exception | |
1090 // handlers and iterate over them as well | |
1091 int nblocks = BlockBegin::number_of_blocks(); | |
1092 BlockList blocks(nblocks); | |
1093 boolArray visited_block(nblocks, false); | |
1094 | |
1095 blocks.push(ir()->start()); | |
1096 visited_block[ir()->start()->block_id()] = true; | |
1097 for (int i = 0; i < blocks.length(); i++) { | |
1098 BlockBegin* b = blocks[i]; | |
1099 // exception handlers need to be treated as additional roots | |
1100 for (int e = b->number_of_exception_handlers(); e-- > 0; ) { | |
1101 BlockBegin* excp = b->exception_handler_at(e); | |
1102 int id = excp->block_id(); | |
1103 if (!visited_block[id]) { | |
1104 blocks.push(excp); | |
1105 visited_block[id] = true; | |
1106 nce.iterate(excp); | |
1107 } | |
1108 } | |
1109 // traverse successors | |
1110 BlockEnd *end = b->end(); | |
1111 for (int s = end->number_of_sux(); s-- > 0; ) { | |
1112 BlockBegin* next = end->sux_at(s); | |
1113 int id = next->block_id(); | |
1114 if (!visited_block[id]) { | |
1115 blocks.push(next); | |
1116 visited_block[id] = true; | |
1117 } | |
1118 } | |
1119 } | |
1120 | |
1121 | |
1122 if (PrintNullCheckElimination) { | |
1123 tty->print_cr("Done with null check elimination for method %s::%s%s", | |
1124 ir()->method()->holder()->name()->as_utf8(), | |
1125 ir()->method()->name()->as_utf8(), | |
1126 ir()->method()->signature()->as_symbol()->as_utf8()); | |
1127 } | |
1128 } |