Mercurial > hg > truffle
annotate src/share/vm/c1/c1_Optimizer.cpp @ 4710:41406797186b
7113012: G1: rename not-fully-young GCs as "mixed"
Summary: Renamed partially-young GCs as mixed and fully-young GCs as young. Change all external output that includes those terms (GC log and GC ergo log) as well as any comments, fields, methods, etc. The changeset also includes very minor code tidying up (added some curly brackets).
Reviewed-by: johnc, brutisso
author | tonyp |
---|---|
date | Fri, 16 Dec 2011 02:14:27 -0500 |
parents | 15559220ce79 |
children | 7bca37d28f32 |
rev | line source |
---|---|
0 | 1 /* |
2166
403dc4c1d7f5
6809483: hotspot:::method_entry are not correctly generated for "method()V"
never
parents:
1972
diff
changeset
|
2 * Copyright (c) 1999, 2011, 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 | |
3362
d4c1fbc3de95
7042153: guarantee(x_compare_res != Constant::not_comparable) failed: incomparable constants in IfOp
iveresov
parents:
2446
diff
changeset
|
255 // not_comparable here is a valid return in case we're comparing unloaded oop constants |
d4c1fbc3de95
7042153: guarantee(x_compare_res != Constant::not_comparable) failed: incomparable constants in IfOp
iveresov
parents:
2446
diff
changeset
|
256 if (t_compare_res != Constant::not_comparable && f_compare_res != Constant::not_comparable) { |
d4c1fbc3de95
7042153: guarantee(x_compare_res != Constant::not_comparable) failed: incomparable constants in IfOp
iveresov
parents:
2446
diff
changeset
|
257 Value new_tval = t_compare_res == Constant::cond_true ? tval : fval; |
d4c1fbc3de95
7042153: guarantee(x_compare_res != Constant::not_comparable) failed: incomparable constants in IfOp
iveresov
parents:
2446
diff
changeset
|
258 Value new_fval = f_compare_res == Constant::cond_true ? tval : fval; |
0 | 259 |
3362
d4c1fbc3de95
7042153: guarantee(x_compare_res != Constant::not_comparable) failed: incomparable constants in IfOp
iveresov
parents:
2446
diff
changeset
|
260 _ifop_count++; |
d4c1fbc3de95
7042153: guarantee(x_compare_res != Constant::not_comparable) failed: incomparable constants in IfOp
iveresov
parents:
2446
diff
changeset
|
261 if (new_tval == new_fval) { |
d4c1fbc3de95
7042153: guarantee(x_compare_res != Constant::not_comparable) failed: incomparable constants in IfOp
iveresov
parents:
2446
diff
changeset
|
262 return new_tval; |
d4c1fbc3de95
7042153: guarantee(x_compare_res != Constant::not_comparable) failed: incomparable constants in IfOp
iveresov
parents:
2446
diff
changeset
|
263 } else { |
d4c1fbc3de95
7042153: guarantee(x_compare_res != Constant::not_comparable) failed: incomparable constants in IfOp
iveresov
parents:
2446
diff
changeset
|
264 return new IfOp(x_ifop->x(), x_ifop_cond, x_ifop->y(), new_tval, new_fval); |
d4c1fbc3de95
7042153: guarantee(x_compare_res != Constant::not_comparable) failed: incomparable constants in IfOp
iveresov
parents:
2446
diff
changeset
|
265 } |
1899 | 266 } |
267 } | |
268 } else { | |
269 Constant* x_const = x->as_Constant(); | |
270 if (x_const != NULL) { // x and y are constants | |
271 Constant::CompareResult x_compare_res = x_const->compare(cond, y_const); | |
3362
d4c1fbc3de95
7042153: guarantee(x_compare_res != Constant::not_comparable) failed: incomparable constants in IfOp
iveresov
parents:
2446
diff
changeset
|
272 // not_comparable here is a valid return in case we're comparing unloaded oop constants |
d4c1fbc3de95
7042153: guarantee(x_compare_res != Constant::not_comparable) failed: incomparable constants in IfOp
iveresov
parents:
2446
diff
changeset
|
273 if (x_compare_res != Constant::not_comparable) { |
d4c1fbc3de95
7042153: guarantee(x_compare_res != Constant::not_comparable) failed: incomparable constants in IfOp
iveresov
parents:
2446
diff
changeset
|
274 _ifop_count++; |
d4c1fbc3de95
7042153: guarantee(x_compare_res != Constant::not_comparable) failed: incomparable constants in IfOp
iveresov
parents:
2446
diff
changeset
|
275 return x_compare_res == Constant::cond_true ? tval : fval; |
d4c1fbc3de95
7042153: guarantee(x_compare_res != Constant::not_comparable) failed: incomparable constants in IfOp
iveresov
parents:
2446
diff
changeset
|
276 } |
1899 | 277 } |
0 | 278 } |
279 } | |
1899 | 280 return new IfOp(x, cond, y, tval, fval); |
281 } | |
0 | 282 |
283 void Optimizer::eliminate_conditional_expressions() { | |
284 // find conditional expressions & replace them with IfOps | |
285 CE_Eliminator ce(ir()); | |
286 } | |
287 | |
288 class BlockMerger: public BlockClosure { | |
289 private: | |
290 IR* _hir; | |
291 int _merge_count; // the number of block pairs successfully merged | |
292 | |
293 public: | |
294 BlockMerger(IR* hir) | |
295 : _hir(hir) | |
296 , _merge_count(0) | |
297 { | |
298 _hir->iterate_preorder(this); | |
299 } | |
300 | |
301 bool try_merge(BlockBegin* block) { | |
302 BlockEnd* end = block->end(); | |
303 if (end->as_Goto() != NULL) { | |
304 assert(end->number_of_sux() == 1, "end must have exactly one successor"); | |
305 // Note: It would be sufficient to check for the number of successors (= 1) | |
306 // in order to decide if this block can be merged potentially. That | |
307 // would then also include switch statements w/ only a default case. | |
308 // However, in that case we would need to make sure the switch tag | |
309 // expression is executed if it can produce observable side effects. | |
310 // We should probably have the canonicalizer simplifying such switch | |
311 // statements and then we are sure we don't miss these merge opportunities | |
312 // here (was bug - gri 7/7/99). | |
313 BlockBegin* sux = end->default_sux(); | |
314 if (sux->number_of_preds() == 1 && !sux->is_entry_block() && !end->is_safepoint()) { | |
315 // merge the two blocks | |
316 | |
317 #ifdef ASSERT | |
318 // verify that state at the end of block and at the beginning of sux are equal | |
319 // no phi functions must be present at beginning of sux | |
320 ValueStack* sux_state = sux->state(); | |
321 ValueStack* end_state = end->state(); | |
1819 | 322 |
323 assert(end_state->scope() == sux_state->scope(), "scopes must match"); | |
0 | 324 assert(end_state->stack_size() == sux_state->stack_size(), "stack not equal"); |
325 assert(end_state->locals_size() == sux_state->locals_size(), "locals not equal"); | |
326 | |
327 int index; | |
328 Value sux_value; | |
329 for_each_stack_value(sux_state, index, sux_value) { | |
330 assert(sux_value == end_state->stack_at(index), "stack not equal"); | |
331 } | |
332 for_each_local_value(sux_state, index, sux_value) { | |
333 assert(sux_value == end_state->local_at(index), "locals not equal"); | |
334 } | |
335 assert(sux_state->caller_state() == end_state->caller_state(), "caller not equal"); | |
336 #endif | |
337 | |
338 // find instruction before end & append first instruction of sux block | |
339 Instruction* prev = end->prev(block); | |
340 Instruction* next = sux->next(); | |
341 assert(prev->as_BlockEnd() == NULL, "must not be a BlockEnd"); | |
1819 | 342 prev->set_next(next); |
0 | 343 sux->disconnect_from_graph(); |
344 block->set_end(sux->end()); | |
345 // add exception handlers of deleted block, if any | |
346 for (int k = 0; k < sux->number_of_exception_handlers(); k++) { | |
347 BlockBegin* xhandler = sux->exception_handler_at(k); | |
348 block->add_exception_handler(xhandler); | |
349 | |
350 // also substitute predecessor of exception handler | |
351 assert(xhandler->is_predecessor(sux), "missing predecessor"); | |
352 xhandler->remove_predecessor(sux); | |
353 if (!xhandler->is_predecessor(block)) { | |
354 xhandler->add_predecessor(block); | |
355 } | |
356 } | |
357 | |
358 // debugging output | |
359 _merge_count++; | |
360 if (PrintBlockElimination) { | |
361 tty->print_cr("%d. merged B%d & B%d (stack size = %d)", | |
362 _merge_count, block->block_id(), sux->block_id(), sux->state()->stack_size()); | |
363 } | |
364 | |
365 _hir->verify(); | |
366 | |
367 If* if_ = block->end()->as_If(); | |
368 if (if_) { | |
369 IfOp* ifop = if_->x()->as_IfOp(); | |
370 Constant* con = if_->y()->as_Constant(); | |
371 bool swapped = false; | |
372 if (!con || !ifop) { | |
373 ifop = if_->y()->as_IfOp(); | |
374 con = if_->x()->as_Constant(); | |
375 swapped = true; | |
376 } | |
377 if (con && ifop) { | |
378 Constant* tval = ifop->tval()->as_Constant(); | |
379 Constant* fval = ifop->fval()->as_Constant(); | |
380 if (tval && fval) { | |
381 // Find the instruction before if_, starting with ifop. | |
382 // When if_ and ifop are not in the same block, prev | |
383 // becomes NULL In such (rare) cases it is not | |
384 // profitable to perform the optimization. | |
385 Value prev = ifop; | |
386 while (prev != NULL && prev->next() != if_) { | |
387 prev = prev->next(); | |
388 } | |
389 | |
390 if (prev != NULL) { | |
391 Instruction::Condition cond = if_->cond(); | |
392 BlockBegin* tsux = if_->tsux(); | |
393 BlockBegin* fsux = if_->fsux(); | |
394 if (swapped) { | |
395 cond = Instruction::mirror(cond); | |
396 } | |
397 | |
398 BlockBegin* tblock = tval->compare(cond, con, tsux, fsux); | |
399 BlockBegin* fblock = fval->compare(cond, con, tsux, fsux); | |
400 if (tblock != fblock && !if_->is_safepoint()) { | |
401 If* newif = new If(ifop->x(), ifop->cond(), false, ifop->y(), | |
402 tblock, fblock, if_->state_before(), if_->is_safepoint()); | |
403 newif->set_state(if_->state()->copy()); | |
404 | |
405 assert(prev->next() == if_, "must be guaranteed by above search"); | |
1819 | 406 NOT_PRODUCT(newif->set_printable_bci(if_->printable_bci())); |
407 prev->set_next(newif); | |
0 | 408 block->set_end(newif); |
409 | |
410 _merge_count++; | |
411 if (PrintBlockElimination) { | |
412 tty->print_cr("%d. replaced If and IfOp at end of B%d with single If", _merge_count, block->block_id()); | |
413 } | |
414 | |
415 _hir->verify(); | |
416 } | |
417 } | |
418 } | |
419 } | |
420 } | |
421 | |
422 return true; | |
423 } | |
424 } | |
425 return false; | |
426 } | |
427 | |
428 virtual void block_do(BlockBegin* block) { | |
429 _hir->verify(); | |
430 // repeat since the same block may merge again | |
431 while (try_merge(block)) { | |
432 _hir->verify(); | |
433 } | |
434 } | |
435 }; | |
436 | |
437 | |
438 void Optimizer::eliminate_blocks() { | |
439 // merge blocks if possible | |
440 BlockMerger bm(ir()); | |
441 } | |
442 | |
443 | |
444 class NullCheckEliminator; | |
445 class NullCheckVisitor: public InstructionVisitor { | |
446 private: | |
447 NullCheckEliminator* _nce; | |
448 NullCheckEliminator* nce() { return _nce; } | |
449 | |
450 public: | |
451 NullCheckVisitor() {} | |
452 | |
453 void set_eliminator(NullCheckEliminator* nce) { _nce = nce; } | |
454 | |
455 void do_Phi (Phi* x); | |
456 void do_Local (Local* x); | |
457 void do_Constant (Constant* x); | |
458 void do_LoadField (LoadField* x); | |
459 void do_StoreField (StoreField* x); | |
460 void do_ArrayLength (ArrayLength* x); | |
461 void do_LoadIndexed (LoadIndexed* x); | |
462 void do_StoreIndexed (StoreIndexed* x); | |
463 void do_NegateOp (NegateOp* x); | |
464 void do_ArithmeticOp (ArithmeticOp* x); | |
465 void do_ShiftOp (ShiftOp* x); | |
466 void do_LogicOp (LogicOp* x); | |
467 void do_CompareOp (CompareOp* x); | |
468 void do_IfOp (IfOp* x); | |
469 void do_Convert (Convert* x); | |
470 void do_NullCheck (NullCheck* x); | |
471 void do_Invoke (Invoke* x); | |
472 void do_NewInstance (NewInstance* x); | |
473 void do_NewTypeArray (NewTypeArray* x); | |
474 void do_NewObjectArray (NewObjectArray* x); | |
475 void do_NewMultiArray (NewMultiArray* x); | |
476 void do_CheckCast (CheckCast* x); | |
477 void do_InstanceOf (InstanceOf* x); | |
478 void do_MonitorEnter (MonitorEnter* x); | |
479 void do_MonitorExit (MonitorExit* x); | |
480 void do_Intrinsic (Intrinsic* x); | |
481 void do_BlockBegin (BlockBegin* x); | |
482 void do_Goto (Goto* x); | |
483 void do_If (If* x); | |
484 void do_IfInstanceOf (IfInstanceOf* x); | |
485 void do_TableSwitch (TableSwitch* x); | |
486 void do_LookupSwitch (LookupSwitch* x); | |
487 void do_Return (Return* x); | |
488 void do_Throw (Throw* x); | |
489 void do_Base (Base* x); | |
490 void do_OsrEntry (OsrEntry* x); | |
491 void do_ExceptionObject(ExceptionObject* x); | |
492 void do_RoundFP (RoundFP* x); | |
493 void do_UnsafeGetRaw (UnsafeGetRaw* x); | |
494 void do_UnsafePutRaw (UnsafePutRaw* x); | |
495 void do_UnsafeGetObject(UnsafeGetObject* x); | |
496 void do_UnsafePutObject(UnsafePutObject* x); | |
497 void do_UnsafePrefetchRead (UnsafePrefetchRead* x); | |
498 void do_UnsafePrefetchWrite(UnsafePrefetchWrite* x); | |
499 void do_ProfileCall (ProfileCall* x); | |
1783 | 500 void do_ProfileInvoke (ProfileInvoke* x); |
2166
403dc4c1d7f5
6809483: hotspot:::method_entry are not correctly generated for "method()V"
never
parents:
1972
diff
changeset
|
501 void do_RuntimeCall (RuntimeCall* x); |
0 | 502 }; |
503 | |
504 | |
505 // Because of a static contained within (for the purpose of iteration | |
506 // over instructions), it is only valid to have one of these active at | |
507 // a time | |
1584 | 508 class NullCheckEliminator: public ValueVisitor { |
0 | 509 private: |
510 Optimizer* _opt; | |
511 | |
512 ValueSet* _visitable_instructions; // Visit each instruction only once per basic block | |
513 BlockList* _work_list; // Basic blocks to visit | |
514 | |
515 bool visitable(Value x) { | |
516 assert(_visitable_instructions != NULL, "check"); | |
517 return _visitable_instructions->contains(x); | |
518 } | |
519 void mark_visited(Value x) { | |
520 assert(_visitable_instructions != NULL, "check"); | |
521 _visitable_instructions->remove(x); | |
522 } | |
523 void mark_visitable(Value x) { | |
524 assert(_visitable_instructions != NULL, "check"); | |
525 _visitable_instructions->put(x); | |
526 } | |
527 void clear_visitable_state() { | |
528 assert(_visitable_instructions != NULL, "check"); | |
529 _visitable_instructions->clear(); | |
530 } | |
531 | |
532 ValueSet* _set; // current state, propagated to subsequent BlockBegins | |
533 ValueSetList _block_states; // BlockBegin null-check states for all processed blocks | |
534 NullCheckVisitor _visitor; | |
535 NullCheck* _last_explicit_null_check; | |
536 | |
537 bool set_contains(Value x) { assert(_set != NULL, "check"); return _set->contains(x); } | |
538 void set_put (Value x) { assert(_set != NULL, "check"); _set->put(x); } | |
539 void set_remove (Value x) { assert(_set != NULL, "check"); _set->remove(x); } | |
540 | |
541 BlockList* work_list() { return _work_list; } | |
542 | |
543 void iterate_all(); | |
544 void iterate_one(BlockBegin* block); | |
545 | |
546 ValueSet* state() { return _set; } | |
547 void set_state_from (ValueSet* state) { _set->set_from(state); } | |
548 ValueSet* state_for (BlockBegin* block) { return _block_states[block->block_id()]; } | |
549 void set_state_for (BlockBegin* block, ValueSet* stack) { _block_states[block->block_id()] = stack; } | |
550 // Returns true if caused a change in the block's state. | |
551 bool merge_state_for(BlockBegin* block, | |
552 ValueSet* incoming_state); | |
553 | |
554 public: | |
555 // constructor | |
556 NullCheckEliminator(Optimizer* opt) | |
557 : _opt(opt) | |
558 , _set(new ValueSet()) | |
559 , _last_explicit_null_check(NULL) | |
560 , _block_states(BlockBegin::number_of_blocks(), NULL) | |
561 , _work_list(new BlockList()) { | |
562 _visitable_instructions = new ValueSet(); | |
563 _visitor.set_eliminator(this); | |
564 } | |
565 | |
566 Optimizer* opt() { return _opt; } | |
567 IR* ir () { return opt()->ir(); } | |
568 | |
569 // Process a graph | |
570 void iterate(BlockBegin* root); | |
571 | |
1584 | 572 void visit(Value* f); |
573 | |
0 | 574 // In some situations (like NullCheck(x); getfield(x)) the debug |
575 // information from the explicit NullCheck can be used to populate | |
576 // the getfield, even if the two instructions are in different | |
577 // scopes; this allows implicit null checks to be used but the | |
578 // correct exception information to be generated. We must clear the | |
579 // last-traversed NullCheck when we reach a potentially-exception- | |
580 // throwing instruction, as well as in some other cases. | |
581 void set_last_explicit_null_check(NullCheck* check) { _last_explicit_null_check = check; } | |
582 NullCheck* last_explicit_null_check() { return _last_explicit_null_check; } | |
583 Value last_explicit_null_check_obj() { return (_last_explicit_null_check | |
584 ? _last_explicit_null_check->obj() | |
585 : NULL); } | |
586 NullCheck* consume_last_explicit_null_check() { | |
587 _last_explicit_null_check->unpin(Instruction::PinExplicitNullCheck); | |
588 _last_explicit_null_check->set_can_trap(false); | |
589 return _last_explicit_null_check; | |
590 } | |
591 void clear_last_explicit_null_check() { _last_explicit_null_check = NULL; } | |
592 | |
593 // Handlers for relevant instructions | |
594 // (separated out from NullCheckVisitor for clarity) | |
595 | |
596 // The basic contract is that these must leave the instruction in | |
597 // the desired state; must not assume anything about the state of | |
598 // the instruction. We make multiple passes over some basic blocks | |
599 // and the last pass is the only one whose result is valid. | |
600 void handle_AccessField (AccessField* x); | |
601 void handle_ArrayLength (ArrayLength* x); | |
602 void handle_LoadIndexed (LoadIndexed* x); | |
603 void handle_StoreIndexed (StoreIndexed* x); | |
604 void handle_NullCheck (NullCheck* x); | |
605 void handle_Invoke (Invoke* x); | |
606 void handle_NewInstance (NewInstance* x); | |
607 void handle_NewArray (NewArray* x); | |
608 void handle_AccessMonitor (AccessMonitor* x); | |
609 void handle_Intrinsic (Intrinsic* x); | |
610 void handle_ExceptionObject (ExceptionObject* x); | |
611 void handle_Phi (Phi* x); | |
612 }; | |
613 | |
614 | |
615 // NEEDS_CLEANUP | |
616 // There may be other instructions which need to clear the last | |
617 // explicit null check. Anything across which we can not hoist the | |
618 // debug information for a NullCheck instruction must clear it. It | |
619 // might be safer to pattern match "NullCheck ; {AccessField, | |
620 // ArrayLength, LoadIndexed}" but it is more easily structured this way. | |
621 // Should test to see performance hit of clearing it for all handlers | |
622 // with empty bodies below. If it is negligible then we should leave | |
623 // that in for safety, otherwise should think more about it. | |
624 void NullCheckVisitor::do_Phi (Phi* x) { nce()->handle_Phi(x); } | |
625 void NullCheckVisitor::do_Local (Local* x) {} | |
626 void NullCheckVisitor::do_Constant (Constant* x) { /* FIXME: handle object constants */ } | |
627 void NullCheckVisitor::do_LoadField (LoadField* x) { nce()->handle_AccessField(x); } | |
628 void NullCheckVisitor::do_StoreField (StoreField* x) { nce()->handle_AccessField(x); } | |
629 void NullCheckVisitor::do_ArrayLength (ArrayLength* x) { nce()->handle_ArrayLength(x); } | |
630 void NullCheckVisitor::do_LoadIndexed (LoadIndexed* x) { nce()->handle_LoadIndexed(x); } | |
631 void NullCheckVisitor::do_StoreIndexed (StoreIndexed* x) { nce()->handle_StoreIndexed(x); } | |
632 void NullCheckVisitor::do_NegateOp (NegateOp* x) {} | |
633 void NullCheckVisitor::do_ArithmeticOp (ArithmeticOp* x) { if (x->can_trap()) nce()->clear_last_explicit_null_check(); } | |
634 void NullCheckVisitor::do_ShiftOp (ShiftOp* x) {} | |
635 void NullCheckVisitor::do_LogicOp (LogicOp* x) {} | |
636 void NullCheckVisitor::do_CompareOp (CompareOp* x) {} | |
637 void NullCheckVisitor::do_IfOp (IfOp* x) {} | |
638 void NullCheckVisitor::do_Convert (Convert* x) {} | |
639 void NullCheckVisitor::do_NullCheck (NullCheck* x) { nce()->handle_NullCheck(x); } | |
640 void NullCheckVisitor::do_Invoke (Invoke* x) { nce()->handle_Invoke(x); } | |
641 void NullCheckVisitor::do_NewInstance (NewInstance* x) { nce()->handle_NewInstance(x); } | |
642 void NullCheckVisitor::do_NewTypeArray (NewTypeArray* x) { nce()->handle_NewArray(x); } | |
643 void NullCheckVisitor::do_NewObjectArray (NewObjectArray* x) { nce()->handle_NewArray(x); } | |
644 void NullCheckVisitor::do_NewMultiArray (NewMultiArray* x) { nce()->handle_NewArray(x); } | |
3792
15559220ce79
6478991: C1 NullCheckEliminator yields incorrect exceptions
never
parents:
3362
diff
changeset
|
645 void NullCheckVisitor::do_CheckCast (CheckCast* x) { nce()->clear_last_explicit_null_check(); } |
0 | 646 void NullCheckVisitor::do_InstanceOf (InstanceOf* x) {} |
647 void NullCheckVisitor::do_MonitorEnter (MonitorEnter* x) { nce()->handle_AccessMonitor(x); } | |
648 void NullCheckVisitor::do_MonitorExit (MonitorExit* x) { nce()->handle_AccessMonitor(x); } | |
2446 | 649 void NullCheckVisitor::do_Intrinsic (Intrinsic* x) { nce()->handle_Intrinsic(x); } |
0 | 650 void NullCheckVisitor::do_BlockBegin (BlockBegin* x) {} |
651 void NullCheckVisitor::do_Goto (Goto* x) {} | |
652 void NullCheckVisitor::do_If (If* x) {} | |
653 void NullCheckVisitor::do_IfInstanceOf (IfInstanceOf* x) {} | |
654 void NullCheckVisitor::do_TableSwitch (TableSwitch* x) {} | |
655 void NullCheckVisitor::do_LookupSwitch (LookupSwitch* x) {} | |
656 void NullCheckVisitor::do_Return (Return* x) {} | |
657 void NullCheckVisitor::do_Throw (Throw* x) { nce()->clear_last_explicit_null_check(); } | |
658 void NullCheckVisitor::do_Base (Base* x) {} | |
659 void NullCheckVisitor::do_OsrEntry (OsrEntry* x) {} | |
660 void NullCheckVisitor::do_ExceptionObject(ExceptionObject* x) { nce()->handle_ExceptionObject(x); } | |
661 void NullCheckVisitor::do_RoundFP (RoundFP* x) {} | |
662 void NullCheckVisitor::do_UnsafeGetRaw (UnsafeGetRaw* x) {} | |
663 void NullCheckVisitor::do_UnsafePutRaw (UnsafePutRaw* x) {} | |
664 void NullCheckVisitor::do_UnsafeGetObject(UnsafeGetObject* x) {} | |
665 void NullCheckVisitor::do_UnsafePutObject(UnsafePutObject* x) {} | |
666 void NullCheckVisitor::do_UnsafePrefetchRead (UnsafePrefetchRead* x) {} | |
667 void NullCheckVisitor::do_UnsafePrefetchWrite(UnsafePrefetchWrite* x) {} | |
668 void NullCheckVisitor::do_ProfileCall (ProfileCall* x) { nce()->clear_last_explicit_null_check(); } | |
1783 | 669 void NullCheckVisitor::do_ProfileInvoke (ProfileInvoke* x) {} |
2166
403dc4c1d7f5
6809483: hotspot:::method_entry are not correctly generated for "method()V"
never
parents:
1972
diff
changeset
|
670 void NullCheckVisitor::do_RuntimeCall (RuntimeCall* x) {} |
0 | 671 |
672 | |
1584 | 673 void NullCheckEliminator::visit(Value* p) { |
0 | 674 assert(*p != NULL, "should not find NULL instructions"); |
1584 | 675 if (visitable(*p)) { |
676 mark_visited(*p); | |
677 (*p)->visit(&_visitor); | |
0 | 678 } |
679 } | |
680 | |
681 bool NullCheckEliminator::merge_state_for(BlockBegin* block, ValueSet* incoming_state) { | |
682 ValueSet* state = state_for(block); | |
683 if (state == NULL) { | |
684 state = incoming_state->copy(); | |
685 set_state_for(block, state); | |
686 return true; | |
687 } else { | |
688 bool changed = state->set_intersect(incoming_state); | |
689 if (PrintNullCheckElimination && changed) { | |
690 tty->print_cr("Block %d's null check state changed", block->block_id()); | |
691 } | |
692 return changed; | |
693 } | |
694 } | |
695 | |
696 | |
697 void NullCheckEliminator::iterate_all() { | |
698 while (work_list()->length() > 0) { | |
699 iterate_one(work_list()->pop()); | |
700 } | |
701 } | |
702 | |
703 | |
704 void NullCheckEliminator::iterate_one(BlockBegin* block) { | |
705 clear_visitable_state(); | |
706 // clear out an old explicit null checks | |
707 set_last_explicit_null_check(NULL); | |
708 | |
709 if (PrintNullCheckElimination) { | |
710 tty->print_cr(" ...iterating block %d in null check elimination for %s::%s%s", | |
711 block->block_id(), | |
712 ir()->method()->holder()->name()->as_utf8(), | |
713 ir()->method()->name()->as_utf8(), | |
714 ir()->method()->signature()->as_symbol()->as_utf8()); | |
715 } | |
716 | |
717 // Create new state if none present (only happens at root) | |
718 if (state_for(block) == NULL) { | |
719 ValueSet* tmp_state = new ValueSet(); | |
720 set_state_for(block, tmp_state); | |
721 // Initial state is that local 0 (receiver) is non-null for | |
722 // non-static methods | |
723 ValueStack* stack = block->state(); | |
724 IRScope* scope = stack->scope(); | |
725 ciMethod* method = scope->method(); | |
726 if (!method->is_static()) { | |
727 Local* local0 = stack->local_at(0)->as_Local(); | |
728 assert(local0 != NULL, "must be"); | |
729 assert(local0->type() == objectType, "invalid type of receiver"); | |
730 | |
731 if (local0 != NULL) { | |
732 // Local 0 is used in this scope | |
733 tmp_state->put(local0); | |
734 if (PrintNullCheckElimination) { | |
735 tty->print_cr("Local 0 (value %d) proven non-null upon entry", local0->id()); | |
736 } | |
737 } | |
738 } | |
739 } | |
740 | |
741 // Must copy block's state to avoid mutating it during iteration | |
742 // through the block -- otherwise "not-null" states can accidentally | |
743 // propagate "up" through the block during processing of backward | |
744 // branches and algorithm is incorrect (and does not converge) | |
745 set_state_from(state_for(block)); | |
746 | |
747 // allow visiting of Phis belonging to this block | |
748 for_each_phi_fun(block, phi, | |
749 mark_visitable(phi); | |
750 ); | |
751 | |
752 BlockEnd* e = block->end(); | |
753 assert(e != NULL, "incomplete graph"); | |
754 int i; | |
755 | |
756 // Propagate the state before this block into the exception | |
757 // handlers. They aren't true successors since we aren't guaranteed | |
758 // to execute the whole block before executing them. Also putting | |
759 // them on first seems to help reduce the amount of iteration to | |
760 // reach a fixed point. | |
761 for (i = 0; i < block->number_of_exception_handlers(); i++) { | |
762 BlockBegin* next = block->exception_handler_at(i); | |
763 if (merge_state_for(next, state())) { | |
764 if (!work_list()->contains(next)) { | |
765 work_list()->push(next); | |
766 } | |
767 } | |
768 } | |
769 | |
770 // Iterate through block, updating state. | |
771 for (Instruction* instr = block; instr != NULL; instr = instr->next()) { | |
772 // Mark instructions in this block as visitable as they are seen | |
773 // in the instruction list. This keeps the iteration from | |
774 // visiting instructions which are references in other blocks or | |
775 // visiting instructions more than once. | |
776 mark_visitable(instr); | |
1819 | 777 if (instr->is_pinned() || instr->can_trap() || (instr->as_NullCheck() != NULL)) { |
0 | 778 mark_visited(instr); |
1584 | 779 instr->input_values_do(this); |
0 | 780 instr->visit(&_visitor); |
781 } | |
782 } | |
783 | |
784 // Propagate state to successors if necessary | |
785 for (i = 0; i < e->number_of_sux(); i++) { | |
786 BlockBegin* next = e->sux_at(i); | |
787 if (merge_state_for(next, state())) { | |
788 if (!work_list()->contains(next)) { | |
789 work_list()->push(next); | |
790 } | |
791 } | |
792 } | |
793 } | |
794 | |
795 | |
796 void NullCheckEliminator::iterate(BlockBegin* block) { | |
797 work_list()->push(block); | |
798 iterate_all(); | |
799 } | |
800 | |
801 void NullCheckEliminator::handle_AccessField(AccessField* x) { | |
802 if (x->is_static()) { | |
803 if (x->as_LoadField() != NULL) { | |
804 // If the field is a non-null static final object field (as is | |
805 // often the case for sun.misc.Unsafe), put this LoadField into | |
806 // the non-null map | |
807 ciField* field = x->field(); | |
808 if (field->is_constant()) { | |
809 ciConstant field_val = field->constant_value(); | |
810 BasicType field_type = field_val.basic_type(); | |
811 if (field_type == T_OBJECT || field_type == T_ARRAY) { | |
812 ciObject* obj_val = field_val.as_object(); | |
813 if (!obj_val->is_null_object()) { | |
814 if (PrintNullCheckElimination) { | |
815 tty->print_cr("AccessField %d proven non-null by static final non-null oop check", | |
816 x->id()); | |
817 } | |
818 set_put(x); | |
819 } | |
820 } | |
821 } | |
822 } | |
823 // Be conservative | |
824 clear_last_explicit_null_check(); | |
825 return; | |
826 } | |
827 | |
828 Value obj = x->obj(); | |
829 if (set_contains(obj)) { | |
830 // Value is non-null => update AccessField | |
831 if (last_explicit_null_check_obj() == obj && !x->needs_patching()) { | |
832 x->set_explicit_null_check(consume_last_explicit_null_check()); | |
833 x->set_needs_null_check(true); | |
834 if (PrintNullCheckElimination) { | |
835 tty->print_cr("Folded NullCheck %d into AccessField %d's null check for value %d", | |
836 x->explicit_null_check()->id(), x->id(), obj->id()); | |
837 } | |
838 } else { | |
839 x->set_explicit_null_check(NULL); | |
840 x->set_needs_null_check(false); | |
841 if (PrintNullCheckElimination) { | |
842 tty->print_cr("Eliminated AccessField %d's null check for value %d", x->id(), obj->id()); | |
843 } | |
844 } | |
845 } else { | |
846 set_put(obj); | |
847 if (PrintNullCheckElimination) { | |
848 tty->print_cr("AccessField %d of value %d proves value to be non-null", x->id(), obj->id()); | |
849 } | |
850 // Ensure previous passes do not cause wrong state | |
851 x->set_needs_null_check(true); | |
852 x->set_explicit_null_check(NULL); | |
853 } | |
854 clear_last_explicit_null_check(); | |
855 } | |
856 | |
857 | |
858 void NullCheckEliminator::handle_ArrayLength(ArrayLength* x) { | |
859 Value array = x->array(); | |
860 if (set_contains(array)) { | |
861 // Value is non-null => update AccessArray | |
862 if (last_explicit_null_check_obj() == array) { | |
863 x->set_explicit_null_check(consume_last_explicit_null_check()); | |
864 x->set_needs_null_check(true); | |
865 if (PrintNullCheckElimination) { | |
866 tty->print_cr("Folded NullCheck %d into ArrayLength %d's null check for value %d", | |
867 x->explicit_null_check()->id(), x->id(), array->id()); | |
868 } | |
869 } else { | |
870 x->set_explicit_null_check(NULL); | |
871 x->set_needs_null_check(false); | |
872 if (PrintNullCheckElimination) { | |
873 tty->print_cr("Eliminated ArrayLength %d's null check for value %d", x->id(), array->id()); | |
874 } | |
875 } | |
876 } else { | |
877 set_put(array); | |
878 if (PrintNullCheckElimination) { | |
879 tty->print_cr("ArrayLength %d of value %d proves value to be non-null", x->id(), array->id()); | |
880 } | |
881 // Ensure previous passes do not cause wrong state | |
882 x->set_needs_null_check(true); | |
883 x->set_explicit_null_check(NULL); | |
884 } | |
885 clear_last_explicit_null_check(); | |
886 } | |
887 | |
888 | |
889 void NullCheckEliminator::handle_LoadIndexed(LoadIndexed* x) { | |
890 Value array = x->array(); | |
891 if (set_contains(array)) { | |
892 // Value is non-null => update AccessArray | |
893 if (last_explicit_null_check_obj() == array) { | |
894 x->set_explicit_null_check(consume_last_explicit_null_check()); | |
895 x->set_needs_null_check(true); | |
896 if (PrintNullCheckElimination) { | |
897 tty->print_cr("Folded NullCheck %d into LoadIndexed %d's null check for value %d", | |
898 x->explicit_null_check()->id(), x->id(), array->id()); | |
899 } | |
900 } else { | |
901 x->set_explicit_null_check(NULL); | |
902 x->set_needs_null_check(false); | |
903 if (PrintNullCheckElimination) { | |
904 tty->print_cr("Eliminated LoadIndexed %d's null check for value %d", x->id(), array->id()); | |
905 } | |
906 } | |
907 } else { | |
908 set_put(array); | |
909 if (PrintNullCheckElimination) { | |
910 tty->print_cr("LoadIndexed %d of value %d proves value to be non-null", x->id(), array->id()); | |
911 } | |
912 // Ensure previous passes do not cause wrong state | |
913 x->set_needs_null_check(true); | |
914 x->set_explicit_null_check(NULL); | |
915 } | |
916 clear_last_explicit_null_check(); | |
917 } | |
918 | |
919 | |
920 void NullCheckEliminator::handle_StoreIndexed(StoreIndexed* x) { | |
921 Value array = x->array(); | |
922 if (set_contains(array)) { | |
923 // Value is non-null => update AccessArray | |
924 if (PrintNullCheckElimination) { | |
925 tty->print_cr("Eliminated StoreIndexed %d's null check for value %d", x->id(), array->id()); | |
926 } | |
927 x->set_needs_null_check(false); | |
928 } else { | |
929 set_put(array); | |
930 if (PrintNullCheckElimination) { | |
931 tty->print_cr("StoreIndexed %d of value %d proves value to be non-null", x->id(), array->id()); | |
932 } | |
933 // Ensure previous passes do not cause wrong state | |
934 x->set_needs_null_check(true); | |
935 } | |
936 clear_last_explicit_null_check(); | |
937 } | |
938 | |
939 | |
940 void NullCheckEliminator::handle_NullCheck(NullCheck* x) { | |
941 Value obj = x->obj(); | |
942 if (set_contains(obj)) { | |
943 // Already proven to be non-null => this NullCheck is useless | |
944 if (PrintNullCheckElimination) { | |
945 tty->print_cr("Eliminated NullCheck %d for value %d", x->id(), obj->id()); | |
946 } | |
947 // Don't unpin since that may shrink obj's live range and make it unavailable for debug info. | |
948 // The code generator won't emit LIR for a NullCheck that cannot trap. | |
949 x->set_can_trap(false); | |
950 } else { | |
951 // May be null => add to map and set last explicit NullCheck | |
952 x->set_can_trap(true); | |
953 // make sure it's pinned if it can trap | |
954 x->pin(Instruction::PinExplicitNullCheck); | |
955 set_put(obj); | |
956 set_last_explicit_null_check(x); | |
957 if (PrintNullCheckElimination) { | |
958 tty->print_cr("NullCheck %d of value %d proves value to be non-null", x->id(), obj->id()); | |
959 } | |
960 } | |
961 } | |
962 | |
963 | |
964 void NullCheckEliminator::handle_Invoke(Invoke* x) { | |
965 if (!x->has_receiver()) { | |
966 // Be conservative | |
967 clear_last_explicit_null_check(); | |
968 return; | |
969 } | |
970 | |
971 Value recv = x->receiver(); | |
972 if (!set_contains(recv)) { | |
973 set_put(recv); | |
974 if (PrintNullCheckElimination) { | |
975 tty->print_cr("Invoke %d of value %d proves value to be non-null", x->id(), recv->id()); | |
976 } | |
977 } | |
978 clear_last_explicit_null_check(); | |
979 } | |
980 | |
981 | |
982 void NullCheckEliminator::handle_NewInstance(NewInstance* x) { | |
983 set_put(x); | |
984 if (PrintNullCheckElimination) { | |
985 tty->print_cr("NewInstance %d is non-null", x->id()); | |
986 } | |
987 } | |
988 | |
989 | |
990 void NullCheckEliminator::handle_NewArray(NewArray* x) { | |
991 set_put(x); | |
992 if (PrintNullCheckElimination) { | |
993 tty->print_cr("NewArray %d is non-null", x->id()); | |
994 } | |
995 } | |
996 | |
997 | |
998 void NullCheckEliminator::handle_ExceptionObject(ExceptionObject* x) { | |
999 set_put(x); | |
1000 if (PrintNullCheckElimination) { | |
1001 tty->print_cr("ExceptionObject %d is non-null", x->id()); | |
1002 } | |
1003 } | |
1004 | |
1005 | |
1006 void NullCheckEliminator::handle_AccessMonitor(AccessMonitor* x) { | |
1007 Value obj = x->obj(); | |
1008 if (set_contains(obj)) { | |
1009 // Value is non-null => update AccessMonitor | |
1010 if (PrintNullCheckElimination) { | |
1011 tty->print_cr("Eliminated AccessMonitor %d's null check for value %d", x->id(), obj->id()); | |
1012 } | |
1013 x->set_needs_null_check(false); | |
1014 } else { | |
1015 set_put(obj); | |
1016 if (PrintNullCheckElimination) { | |
1017 tty->print_cr("AccessMonitor %d of value %d proves value to be non-null", x->id(), obj->id()); | |
1018 } | |
1019 // Ensure previous passes do not cause wrong state | |
1020 x->set_needs_null_check(true); | |
1021 } | |
1022 clear_last_explicit_null_check(); | |
1023 } | |
1024 | |
1025 | |
1026 void NullCheckEliminator::handle_Intrinsic(Intrinsic* x) { | |
1027 if (!x->has_receiver()) { | |
2446 | 1028 if (x->id() == vmIntrinsics::_arraycopy) { |
1029 for (int i = 0; i < x->number_of_arguments(); i++) { | |
1030 x->set_arg_needs_null_check(i, !set_contains(x->argument_at(i))); | |
1031 } | |
1032 } | |
1033 | |
0 | 1034 // Be conservative |
1035 clear_last_explicit_null_check(); | |
1036 return; | |
1037 } | |
1038 | |
1039 Value recv = x->receiver(); | |
1040 if (set_contains(recv)) { | |
1041 // Value is non-null => update Intrinsic | |
1042 if (PrintNullCheckElimination) { | |
1043 tty->print_cr("Eliminated Intrinsic %d's null check for value %d", x->id(), recv->id()); | |
1044 } | |
1045 x->set_needs_null_check(false); | |
1046 } else { | |
1047 set_put(recv); | |
1048 if (PrintNullCheckElimination) { | |
1049 tty->print_cr("Intrinsic %d of value %d proves value to be non-null", x->id(), recv->id()); | |
1050 } | |
1051 // Ensure previous passes do not cause wrong state | |
1052 x->set_needs_null_check(true); | |
1053 } | |
1054 clear_last_explicit_null_check(); | |
1055 } | |
1056 | |
1057 | |
1058 void NullCheckEliminator::handle_Phi(Phi* x) { | |
1059 int i; | |
1060 bool all_non_null = true; | |
1061 if (x->is_illegal()) { | |
1062 all_non_null = false; | |
1063 } else { | |
1064 for (i = 0; i < x->operand_count(); i++) { | |
1065 Value input = x->operand_at(i); | |
1066 if (!set_contains(input)) { | |
1067 all_non_null = false; | |
1068 } | |
1069 } | |
1070 } | |
1071 | |
1072 if (all_non_null) { | |
1073 // Value is non-null => update Phi | |
1074 if (PrintNullCheckElimination) { | |
1075 tty->print_cr("Eliminated Phi %d's null check for phifun because all inputs are non-null", x->id()); | |
1076 } | |
1077 x->set_needs_null_check(false); | |
1078 } else if (set_contains(x)) { | |
1079 set_remove(x); | |
1080 } | |
1081 } | |
1082 | |
1083 | |
1084 void Optimizer::eliminate_null_checks() { | |
1085 ResourceMark rm; | |
1086 | |
1087 NullCheckEliminator nce(this); | |
1088 | |
1089 if (PrintNullCheckElimination) { | |
1090 tty->print_cr("Starting null check elimination for method %s::%s%s", | |
1091 ir()->method()->holder()->name()->as_utf8(), | |
1092 ir()->method()->name()->as_utf8(), | |
1093 ir()->method()->signature()->as_symbol()->as_utf8()); | |
1094 } | |
1095 | |
1096 // Apply to graph | |
1097 nce.iterate(ir()->start()); | |
1098 | |
1099 // walk over the graph looking for exception | |
1100 // handlers and iterate over them as well | |
1101 int nblocks = BlockBegin::number_of_blocks(); | |
1102 BlockList blocks(nblocks); | |
1103 boolArray visited_block(nblocks, false); | |
1104 | |
1105 blocks.push(ir()->start()); | |
1106 visited_block[ir()->start()->block_id()] = true; | |
1107 for (int i = 0; i < blocks.length(); i++) { | |
1108 BlockBegin* b = blocks[i]; | |
1109 // exception handlers need to be treated as additional roots | |
1110 for (int e = b->number_of_exception_handlers(); e-- > 0; ) { | |
1111 BlockBegin* excp = b->exception_handler_at(e); | |
1112 int id = excp->block_id(); | |
1113 if (!visited_block[id]) { | |
1114 blocks.push(excp); | |
1115 visited_block[id] = true; | |
1116 nce.iterate(excp); | |
1117 } | |
1118 } | |
1119 // traverse successors | |
1120 BlockEnd *end = b->end(); | |
1121 for (int s = end->number_of_sux(); s-- > 0; ) { | |
1122 BlockBegin* next = end->sux_at(s); | |
1123 int id = next->block_id(); | |
1124 if (!visited_block[id]) { | |
1125 blocks.push(next); | |
1126 visited_block[id] = true; | |
1127 } | |
1128 } | |
1129 } | |
1130 | |
1131 | |
1132 if (PrintNullCheckElimination) { | |
1133 tty->print_cr("Done with null check elimination for method %s::%s%s", | |
1134 ir()->method()->holder()->name()->as_utf8(), | |
1135 ir()->method()->name()->as_utf8(), | |
1136 ir()->method()->signature()->as_symbol()->as_utf8()); | |
1137 } | |
1138 } |