annotate src/share/vm/c1/c1_Optimizer.cpp @ 1721:413ad0331a0c

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