File: | jdk/src/hotspot/share/ci/ciMethodBlocks.cpp |
Warning: | line 184, column 13 Value stored to 'dest' is never read |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | /* |
2 | * Copyright (c) 2006, 2017, Oracle and/or its affiliates. All rights reserved. |
3 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
4 | * |
5 | * This code is free software; you can redistribute it and/or modify it |
6 | * under the terms of the GNU General Public License version 2 only, as |
7 | * published by the Free Software Foundation. |
8 | * |
9 | * This code is distributed in the hope that it will be useful, but WITHOUT |
10 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
11 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
12 | * version 2 for more details (a copy is included in the LICENSE file that |
13 | * accompanied this code). |
14 | * |
15 | * You should have received a copy of the GNU General Public License version |
16 | * 2 along with this work; if not, write to the Free Software Foundation, |
17 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
18 | * |
19 | * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
20 | * or visit www.oracle.com if you need additional information or have any |
21 | * questions. |
22 | * |
23 | */ |
24 | |
25 | #include "precompiled.hpp" |
26 | #include "ci/ciMethodBlocks.hpp" |
27 | #include "ci/ciStreams.hpp" |
28 | #include "interpreter/bytecode.hpp" |
29 | #include "utilities/copy.hpp" |
30 | |
31 | // ciMethodBlocks |
32 | |
33 | |
34 | |
35 | ciBlock *ciMethodBlocks::block_containing(int bci) { |
36 | ciBlock *blk = _bci_to_block[bci]; |
37 | return blk; |
38 | } |
39 | |
40 | bool ciMethodBlocks::is_block_start(int bci) { |
41 | assert(bci >=0 && bci < _code_size, "valid bytecode range")do { if (!(bci >=0 && bci < _code_size)) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/ci/ciMethodBlocks.cpp" , 41, "assert(" "bci >=0 && bci < _code_size" ") failed" , "valid bytecode range"); ::breakpoint(); } } while (0); |
42 | ciBlock *b = _bci_to_block[bci]; |
43 | assert(b != NULL, "must have block for bytecode")do { if (!(b != __null)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/ci/ciMethodBlocks.cpp" , 43, "assert(" "b != __null" ") failed", "must have block for bytecode" ); ::breakpoint(); } } while (0); |
44 | return b->start_bci() == bci; |
45 | } |
46 | |
47 | // ------------------------------------------------------------------ |
48 | // ciMethodBlocks::split_block_at |
49 | // |
50 | // Split the block spanning bci into two separate ranges. The former |
51 | // block becomes the second half and a new range is created for the |
52 | // first half. Returns the range beginning at bci. |
53 | ciBlock *ciMethodBlocks::split_block_at(int bci) { |
54 | ciBlock *former_block = block_containing(bci); |
55 | ciBlock *new_block = new(_arena) ciBlock(_method, _num_blocks++, former_block->start_bci()); |
56 | _blocks->append(new_block); |
57 | assert(former_block != NULL, "must not be NULL")do { if (!(former_block != __null)) { (*g_assert_poison) = 'X' ;; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/ci/ciMethodBlocks.cpp" , 57, "assert(" "former_block != __null" ") failed", "must not be NULL" ); ::breakpoint(); } } while (0); |
58 | new_block->set_limit_bci(bci); |
59 | former_block->set_start_bci(bci); |
60 | for (int pos=bci-1; pos >= 0; pos--) { |
61 | ciBlock *current_block = block_containing(pos); |
62 | if (current_block == former_block) { |
63 | // Replace it. |
64 | _bci_to_block[pos] = new_block; |
65 | } else if (current_block == NULL__null) { |
66 | // Non-bytecode start. Skip. |
67 | continue; |
68 | } else { |
69 | // We are done with our backwards walk |
70 | break; |
71 | } |
72 | } |
73 | // Move an exception handler information if needed. |
74 | if (former_block->is_handler()) { |
75 | int ex_start = former_block->ex_start_bci(); |
76 | int ex_end = former_block->ex_limit_bci(); |
77 | new_block->set_exception_range(ex_start, ex_end); |
78 | // Clear information in former_block. |
79 | former_block->clear_exception_handler(); |
80 | } |
81 | return former_block; |
82 | } |
83 | |
84 | ciBlock *ciMethodBlocks::make_block_at(int bci) { |
85 | ciBlock *cb = block_containing(bci); |
86 | if (cb == NULL__null ) { |
87 | // This is our first time visiting this bytecode. Create |
88 | // a fresh block and assign it this starting point. |
89 | ciBlock *nb = new(_arena) ciBlock(_method, _num_blocks++, bci); |
90 | _blocks->append(nb); |
91 | _bci_to_block[bci] = nb; |
92 | return nb; |
93 | } else if (cb->start_bci() == bci) { |
94 | // The block begins at bci. Simply return it. |
95 | return cb; |
96 | } else { |
97 | // We have already created a block containing bci but |
98 | // not starting at bci. This existing block needs to |
99 | // be split into two. |
100 | return split_block_at(bci); |
101 | } |
102 | } |
103 | |
104 | ciBlock *ciMethodBlocks::make_dummy_block() { |
105 | ciBlock *dum = new(_arena) ciBlock(_method, -1, 0); |
106 | return dum; |
107 | } |
108 | |
109 | void ciMethodBlocks::do_analysis() { |
110 | ciBytecodeStream s(_method); |
111 | ciBlock *cur_block = block_containing(0); |
112 | int limit_bci = _method->code_size(); |
113 | |
114 | while (s.next() != ciBytecodeStream::EOBC()) { |
115 | int bci = s.cur_bci(); |
116 | // Determine if a new block has been made at the current bci. If |
117 | // this block differs from our current range, switch to the new |
118 | // one and end the old one. |
119 | assert(cur_block != NULL, "must always have a current block")do { if (!(cur_block != __null)) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/ci/ciMethodBlocks.cpp" , 119, "assert(" "cur_block != __null" ") failed", "must always have a current block" ); ::breakpoint(); } } while (0); |
120 | ciBlock *new_block = block_containing(bci); |
121 | if (new_block == NULL__null || new_block == cur_block) { |
122 | // We have not marked this bci as the start of a new block. |
123 | // Keep interpreting the current_range. |
124 | _bci_to_block[bci] = cur_block; |
125 | } else { |
126 | cur_block->set_limit_bci(bci); |
127 | cur_block = new_block; |
128 | } |
129 | |
130 | switch (s.cur_bc()) { |
131 | case Bytecodes::_ifeq : |
132 | case Bytecodes::_ifne : |
133 | case Bytecodes::_iflt : |
134 | case Bytecodes::_ifge : |
135 | case Bytecodes::_ifgt : |
136 | case Bytecodes::_ifle : |
137 | case Bytecodes::_if_icmpeq : |
138 | case Bytecodes::_if_icmpne : |
139 | case Bytecodes::_if_icmplt : |
140 | case Bytecodes::_if_icmpge : |
141 | case Bytecodes::_if_icmpgt : |
142 | case Bytecodes::_if_icmple : |
143 | case Bytecodes::_if_acmpeq : |
144 | case Bytecodes::_if_acmpne : |
145 | case Bytecodes::_ifnull : |
146 | case Bytecodes::_ifnonnull : |
147 | { |
148 | cur_block->set_control_bci(bci); |
149 | ciBlock *fall_through = make_block_at(s.next_bci()); |
150 | int dest_bci = s.get_dest(); |
151 | ciBlock *dest = make_block_at(dest_bci); |
152 | break; |
153 | } |
154 | |
155 | case Bytecodes::_goto : |
156 | { |
157 | cur_block->set_control_bci(bci); |
158 | if (s.next_bci() < limit_bci) { |
159 | (void) make_block_at(s.next_bci()); |
160 | } |
161 | int dest_bci = s.get_dest(); |
162 | ciBlock *dest = make_block_at(dest_bci); |
163 | break; |
164 | } |
165 | |
166 | case Bytecodes::_jsr : |
167 | { |
168 | cur_block->set_control_bci(bci); |
169 | ciBlock *ret = make_block_at(s.next_bci()); |
170 | int dest_bci = s.get_dest(); |
171 | ciBlock *dest = make_block_at(dest_bci); |
172 | break; |
173 | } |
174 | |
175 | case Bytecodes::_tableswitch : |
176 | { |
177 | cur_block->set_control_bci(bci); |
178 | Bytecode_tableswitch sw(&s); |
179 | int len = sw.length(); |
180 | ciBlock *dest; |
181 | int dest_bci; |
182 | for (int i = 0; i < len; i++) { |
183 | dest_bci = s.cur_bci() + sw.dest_offset_at(i); |
184 | dest = make_block_at(dest_bci); |
Value stored to 'dest' is never read | |
185 | } |
186 | dest_bci = s.cur_bci() + sw.default_offset(); |
187 | make_block_at(dest_bci); |
188 | if (s.next_bci() < limit_bci) { |
189 | dest = make_block_at(s.next_bci()); |
190 | } |
191 | } |
192 | break; |
193 | |
194 | case Bytecodes::_lookupswitch: |
195 | { |
196 | cur_block->set_control_bci(bci); |
197 | Bytecode_lookupswitch sw(&s); |
198 | int len = sw.number_of_pairs(); |
199 | ciBlock *dest; |
200 | int dest_bci; |
201 | for (int i = 0; i < len; i++) { |
202 | dest_bci = s.cur_bci() + sw.pair_at(i).offset(); |
203 | dest = make_block_at(dest_bci); |
204 | } |
205 | dest_bci = s.cur_bci() + sw.default_offset(); |
206 | dest = make_block_at(dest_bci); |
207 | if (s.next_bci() < limit_bci) { |
208 | dest = make_block_at(s.next_bci()); |
209 | } |
210 | } |
211 | break; |
212 | |
213 | case Bytecodes::_goto_w : |
214 | { |
215 | cur_block->set_control_bci(bci); |
216 | if (s.next_bci() < limit_bci) { |
217 | (void) make_block_at(s.next_bci()); |
218 | } |
219 | int dest_bci = s.get_far_dest(); |
220 | ciBlock *dest = make_block_at(dest_bci); |
221 | break; |
222 | } |
223 | |
224 | case Bytecodes::_jsr_w : |
225 | { |
226 | cur_block->set_control_bci(bci); |
227 | ciBlock *ret = make_block_at(s.next_bci()); |
228 | int dest_bci = s.get_far_dest(); |
229 | ciBlock *dest = make_block_at(dest_bci); |
230 | break; |
231 | } |
232 | |
233 | case Bytecodes::_athrow : |
234 | cur_block->set_may_throw(); |
235 | // fall-through |
236 | case Bytecodes::_ret : |
237 | case Bytecodes::_ireturn : |
238 | case Bytecodes::_lreturn : |
239 | case Bytecodes::_freturn : |
240 | case Bytecodes::_dreturn : |
241 | case Bytecodes::_areturn : |
242 | case Bytecodes::_return : |
243 | cur_block->set_control_bci(bci); |
244 | if (s.next_bci() < limit_bci) { |
245 | (void) make_block_at(s.next_bci()); |
246 | } |
247 | break; |
248 | |
249 | default: |
250 | break; |
251 | } |
252 | } |
253 | // End the last block |
254 | cur_block->set_limit_bci(limit_bci); |
255 | } |
256 | |
257 | ciMethodBlocks::ciMethodBlocks(Arena *arena, ciMethod *meth): _method(meth), |
258 | _arena(arena), _num_blocks(0), _code_size(meth->code_size()) { |
259 | int block_estimate = _code_size / 8; |
260 | |
261 | _blocks = new(_arena) GrowableArray<ciBlock *>(_arena, block_estimate, 0, NULL__null); |
262 | int b2bsize = _code_size * sizeof(ciBlock **); |
263 | _bci_to_block = (ciBlock **) arena->Amalloc(b2bsize); |
264 | Copy::zero_to_words((HeapWord*) _bci_to_block, b2bsize / sizeof(HeapWord)); |
265 | |
266 | // create initial block covering the entire method |
267 | ciBlock *b = new(arena) ciBlock(_method, _num_blocks++, 0); |
268 | _blocks->append(b); |
269 | _bci_to_block[0] = b; |
270 | |
271 | // create blocks for exception handlers |
272 | if (meth->has_exception_handlers()) { |
273 | for(ciExceptionHandlerStream str(meth); !str.is_done(); str.next()) { |
274 | ciExceptionHandler* handler = str.handler(); |
275 | ciBlock *eb = make_block_at(handler->handler_bci()); |
276 | // |
277 | // Several exception handlers can have the same handler_bci: |
278 | // |
279 | // try { |
280 | // if (a.foo(b) < 0) { |
281 | // return a.error(); |
282 | // } |
283 | // return CoderResult.UNDERFLOW; |
284 | // } finally { |
285 | // a.position(b); |
286 | // } |
287 | // |
288 | // The try block above is divided into 2 exception blocks |
289 | // separated by 'areturn' bci. |
290 | // |
291 | int ex_start = handler->start(); |
292 | int ex_end = handler->limit(); |
293 | // ensure a block at the start of exception range and start of following code |
294 | (void) make_block_at(ex_start); |
295 | if (ex_end < _code_size) |
296 | (void) make_block_at(ex_end); |
297 | |
298 | if (eb->is_handler()) { |
299 | // Extend old handler exception range to cover additional range. |
300 | int old_ex_start = eb->ex_start_bci(); |
301 | int old_ex_end = eb->ex_limit_bci(); |
302 | if (ex_start > old_ex_start) |
303 | ex_start = old_ex_start; |
304 | if (ex_end < old_ex_end) |
305 | ex_end = old_ex_end; |
306 | eb->clear_exception_handler(); // Reset exception information |
307 | } |
308 | eb->set_exception_range(ex_start, ex_end); |
309 | } |
310 | } |
311 | |
312 | // scan the bytecodes and identify blocks |
313 | do_analysis(); |
314 | |
315 | // mark blocks that have exception handlers |
316 | if (meth->has_exception_handlers()) { |
317 | for(ciExceptionHandlerStream str(meth); !str.is_done(); str.next()) { |
318 | ciExceptionHandler* handler = str.handler(); |
319 | int ex_start = handler->start(); |
320 | int ex_end = handler->limit(); |
321 | |
322 | int bci = ex_start; |
323 | while (bci < ex_end) { |
324 | ciBlock *b = block_containing(bci); |
325 | b->set_has_handler(); |
326 | bci = b->limit_bci(); |
327 | } |
328 | } |
329 | } |
330 | } |
331 | |
332 | void ciMethodBlocks::clear_processed() { |
333 | for (int i = 0; i < _blocks->length(); i++) |
334 | _blocks->at(i)->clear_processed(); |
335 | } |
336 | |
337 | #ifndef PRODUCT |
338 | void ciMethodBlocks::dump() { |
339 | tty->print("---- blocks for method: "); |
340 | _method->print(); |
341 | tty->cr(); |
342 | for (int i = 0; i < _blocks->length(); i++) { |
343 | tty->print(" B%d: ", i); _blocks->at(i)->dump(); |
344 | } |
345 | } |
346 | #endif |
347 | |
348 | ciBlock::ciBlock(ciMethod *method, int index, int start_bci) : |
349 | _idx(index), _start_bci(start_bci), _limit_bci(-1), _control_bci(fall_through_bci), |
350 | _flags(0), _ex_start_bci(-1), _ex_limit_bci(-1) |
351 | #ifndef PRODUCT |
352 | , _method(method) |
353 | #endif |
354 | { |
355 | } |
356 | |
357 | void ciBlock::set_exception_range(int start_bci, int limit_bci) { |
358 | assert(limit_bci >= start_bci, "valid range")do { if (!(limit_bci >= start_bci)) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/ci/ciMethodBlocks.cpp" , 358, "assert(" "limit_bci >= start_bci" ") failed", "valid range" ); ::breakpoint(); } } while (0); |
359 | assert(!is_handler() && _ex_start_bci == -1 && _ex_limit_bci == -1, "must not be handler")do { if (!(!is_handler() && _ex_start_bci == -1 && _ex_limit_bci == -1)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/ci/ciMethodBlocks.cpp" , 359, "assert(" "!is_handler() && _ex_start_bci == -1 && _ex_limit_bci == -1" ") failed", "must not be handler"); ::breakpoint(); } } while (0); |
360 | _ex_start_bci = start_bci; |
361 | _ex_limit_bci = limit_bci; |
362 | set_handler(); |
363 | } |
364 | |
365 | #ifndef PRODUCT |
366 | static const char *flagnames[] = { |
367 | "Processed", |
368 | "Handler", |
369 | "MayThrow", |
370 | "Jsr", |
371 | "Ret", |
372 | "RetTarget", |
373 | "HasHandler", |
374 | }; |
375 | |
376 | void ciBlock::dump() { |
377 | tty->print(" [%d .. %d), {", _start_bci, _limit_bci); |
378 | for (int i = 0; i < 7; i++) { |
379 | if ((_flags & (1 << i)) != 0) { |
380 | tty->print(" %s", flagnames[i]); |
381 | } |
382 | } |
383 | tty->print(" ]"); |
384 | if (is_handler()) |
385 | tty->print(" handles(%d..%d)", _ex_start_bci, _ex_limit_bci); |
386 | tty->cr(); |
387 | } |
388 | |
389 | // ------------------------------------------------------------------ |
390 | // ciBlock::print_on |
391 | void ciBlock::print_on(outputStream* st) const { |
392 | st->print_cr("--------------------------------------------------------"); |
393 | st->print ("ciBlock [%d - %d) control : ", start_bci(), limit_bci()); |
394 | if (control_bci() == fall_through_bci) { |
395 | st->print_cr("%d:fall through", limit_bci()); |
396 | } else { |
397 | st->print_cr("%d:%s", control_bci(), |
398 | Bytecodes::name(method()->java_code_at_bci(control_bci()))); |
399 | } |
400 | |
401 | if (Verbose || WizardMode) { |
402 | method()->print_codes_on(start_bci(), limit_bci(), st); |
403 | } |
404 | } |
405 | #endif |