Mercurial > hg > truffle
comparison src/share/vm/ci/ciMethodBlocks.cpp @ 0:a61af66fc99e jdk7-b24
Initial load
author | duke |
---|---|
date | Sat, 01 Dec 2007 00:00:00 +0000 |
parents | |
children | 0871d5cd64cd |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:a61af66fc99e |
---|---|
1 /* | |
2 * Copyright 2006 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, | |
20 * CA 95054 USA or visit www.sun.com if you need additional information or | |
21 * have any questions. | |
22 * | |
23 */ | |
24 | |
25 #include "incls/_precompiled.incl" | |
26 #include "incls/_ciMethodBlocks.cpp.incl" | |
27 | |
28 // ciMethodBlocks | |
29 | |
30 | |
31 | |
32 ciBlock *ciMethodBlocks::block_containing(int bci) { | |
33 ciBlock *blk = _bci_to_block[bci]; | |
34 return blk; | |
35 } | |
36 | |
37 bool ciMethodBlocks::is_block_start(int bci) { | |
38 assert(bci >=0 && bci < _code_size, "valid bytecode range"); | |
39 ciBlock *b = _bci_to_block[bci]; | |
40 assert(b != NULL, "must have block for bytecode"); | |
41 return b->start_bci() == bci; | |
42 } | |
43 | |
44 // ------------------------------------------------------------------ | |
45 // ciMethodBlocks::split_block_at | |
46 // | |
47 // Split the block spanning bci into two separate ranges. The former | |
48 // block becomes the second half and a new range is created for the | |
49 // first half. Returns the range beginning at bci. | |
50 ciBlock *ciMethodBlocks::split_block_at(int bci) { | |
51 ciBlock *former_block = block_containing(bci); | |
52 ciBlock *new_block = new(_arena) ciBlock(_method, _num_blocks++, this, former_block->start_bci()); | |
53 _blocks->append(new_block); | |
54 assert(former_block != NULL, "must not be NULL"); | |
55 new_block->set_limit_bci(bci); | |
56 former_block->set_start_bci(bci); | |
57 for (int pos=bci-1; pos >= 0; pos--) { | |
58 ciBlock *current_block = block_containing(pos); | |
59 if (current_block == former_block) { | |
60 // Replace it. | |
61 _bci_to_block[pos] = new_block; | |
62 } else if (current_block == NULL) { | |
63 // Non-bytecode start. Skip. | |
64 continue; | |
65 } else { | |
66 // We are done with our backwards walk | |
67 break; | |
68 } | |
69 } | |
70 return former_block; | |
71 } | |
72 | |
73 ciBlock *ciMethodBlocks::make_block_at(int bci) { | |
74 ciBlock *cb = block_containing(bci); | |
75 if (cb == NULL ) { | |
76 // This is our first time visiting this bytecode. Create | |
77 // a fresh block and assign it this starting point. | |
78 ciBlock *nb = new(_arena) ciBlock(_method, _num_blocks++, this, bci); | |
79 _blocks->append(nb); | |
80 _bci_to_block[bci] = nb; | |
81 return nb; | |
82 } else if (cb->start_bci() == bci) { | |
83 // The block begins at bci. Simply return it. | |
84 return cb; | |
85 } else { | |
86 // We have already created a block containing bci but | |
87 // not starting at bci. This existing block needs to | |
88 // be split into two. | |
89 return split_block_at(bci); | |
90 } | |
91 } | |
92 | |
93 void ciMethodBlocks::do_analysis() { | |
94 ciBytecodeStream s(_method); | |
95 ciBlock *cur_block = block_containing(0); | |
96 int limit_bci = _method->code_size(); | |
97 | |
98 while (s.next() != ciBytecodeStream::EOBC()) { | |
99 int bci = s.cur_bci(); | |
100 // Determine if a new block has been made at the current bci. If | |
101 // this block differs from our current range, switch to the new | |
102 // one and end the old one. | |
103 assert(cur_block != NULL, "must always have a current block"); | |
104 ciBlock *new_block = block_containing(bci); | |
105 if (new_block == NULL) { | |
106 // We have not marked this bci as the start of a new block. | |
107 // Keep interpreting the current_range. | |
108 _bci_to_block[bci] = cur_block; | |
109 } else { | |
110 cur_block->set_limit_bci(bci); | |
111 cur_block = new_block; | |
112 } | |
113 | |
114 switch (s.cur_bc()) { | |
115 case Bytecodes::_ifeq : | |
116 case Bytecodes::_ifne : | |
117 case Bytecodes::_iflt : | |
118 case Bytecodes::_ifge : | |
119 case Bytecodes::_ifgt : | |
120 case Bytecodes::_ifle : | |
121 case Bytecodes::_if_icmpeq : | |
122 case Bytecodes::_if_icmpne : | |
123 case Bytecodes::_if_icmplt : | |
124 case Bytecodes::_if_icmpge : | |
125 case Bytecodes::_if_icmpgt : | |
126 case Bytecodes::_if_icmple : | |
127 case Bytecodes::_if_acmpeq : | |
128 case Bytecodes::_if_acmpne : | |
129 case Bytecodes::_ifnull : | |
130 case Bytecodes::_ifnonnull : | |
131 { | |
132 cur_block->set_control_bci(bci); | |
133 ciBlock *fall_through = make_block_at(s.next_bci()); | |
134 int dest_bci = s.get_dest(); | |
135 ciBlock *dest = make_block_at(dest_bci); | |
136 break; | |
137 } | |
138 | |
139 case Bytecodes::_goto : | |
140 { | |
141 cur_block->set_control_bci(bci); | |
142 if (s.next_bci() < limit_bci) { | |
143 (void) make_block_at(s.next_bci()); | |
144 } | |
145 int dest_bci = s.get_dest(); | |
146 ciBlock *dest = make_block_at(dest_bci); | |
147 break; | |
148 } | |
149 | |
150 case Bytecodes::_jsr : | |
151 { | |
152 cur_block->set_control_bci(bci); | |
153 ciBlock *ret = make_block_at(s.next_bci()); | |
154 int dest_bci = s.get_dest(); | |
155 ciBlock *dest = make_block_at(dest_bci); | |
156 break; | |
157 } | |
158 | |
159 case Bytecodes::_tableswitch : | |
160 { | |
161 cur_block->set_control_bci(bci); | |
162 Bytecode_tableswitch* switch_ = Bytecode_tableswitch_at(s.cur_bcp()); | |
163 int len = switch_->length(); | |
164 ciBlock *dest; | |
165 int dest_bci; | |
166 for (int i = 0; i < len; i++) { | |
167 dest_bci = s.cur_bci() + switch_->dest_offset_at(i); | |
168 dest = make_block_at(dest_bci); | |
169 } | |
170 dest_bci = s.cur_bci() + switch_->default_offset(); | |
171 make_block_at(dest_bci); | |
172 if (s.next_bci() < limit_bci) { | |
173 dest = make_block_at(s.next_bci()); | |
174 } | |
175 } | |
176 break; | |
177 | |
178 case Bytecodes::_lookupswitch: | |
179 { | |
180 cur_block->set_control_bci(bci); | |
181 Bytecode_lookupswitch* switch_ = Bytecode_lookupswitch_at(s.cur_bcp()); | |
182 int len = switch_->number_of_pairs(); | |
183 ciBlock *dest; | |
184 int dest_bci; | |
185 for (int i = 0; i < len; i++) { | |
186 dest_bci = s.cur_bci() + switch_->pair_at(i)->offset(); | |
187 dest = make_block_at(dest_bci); | |
188 } | |
189 dest_bci = s.cur_bci() + switch_->default_offset(); | |
190 dest = make_block_at(dest_bci); | |
191 if (s.next_bci() < limit_bci) { | |
192 dest = make_block_at(s.next_bci()); | |
193 } | |
194 } | |
195 break; | |
196 | |
197 case Bytecodes::_goto_w : | |
198 { | |
199 cur_block->set_control_bci(bci); | |
200 if (s.next_bci() < limit_bci) { | |
201 (void) make_block_at(s.next_bci()); | |
202 } | |
203 int dest_bci = s.get_far_dest(); | |
204 ciBlock *dest = make_block_at(dest_bci); | |
205 break; | |
206 } | |
207 | |
208 case Bytecodes::_jsr_w : | |
209 { | |
210 cur_block->set_control_bci(bci); | |
211 ciBlock *ret = make_block_at(s.next_bci()); | |
212 int dest_bci = s.get_far_dest(); | |
213 ciBlock *dest = make_block_at(dest_bci); | |
214 break; | |
215 } | |
216 | |
217 case Bytecodes::_athrow : | |
218 cur_block->set_may_throw(); | |
219 // fall-through | |
220 case Bytecodes::_ret : | |
221 case Bytecodes::_ireturn : | |
222 case Bytecodes::_lreturn : | |
223 case Bytecodes::_freturn : | |
224 case Bytecodes::_dreturn : | |
225 case Bytecodes::_areturn : | |
226 case Bytecodes::_return : | |
227 cur_block->set_control_bci(bci); | |
228 if (s.next_bci() < limit_bci) { | |
229 (void) make_block_at(s.next_bci()); | |
230 } | |
231 break; | |
232 } | |
233 } | |
234 // End the last block | |
235 cur_block->set_limit_bci(limit_bci); | |
236 } | |
237 | |
238 ciMethodBlocks::ciMethodBlocks(Arena *arena, ciMethod *meth): _method(meth), | |
239 _arena(arena), _num_blocks(0), _code_size(meth->code_size()) { | |
240 int block_estimate = _code_size / 8; | |
241 | |
242 _blocks = new(_arena) GrowableArray<ciBlock *>(block_estimate); | |
243 int b2bsize = _code_size * sizeof(ciBlock **); | |
244 _bci_to_block = (ciBlock **) arena->Amalloc(b2bsize); | |
245 Copy::zero_to_words((HeapWord*) _bci_to_block, b2bsize / sizeof(HeapWord)); | |
246 | |
247 // create initial block covering the entire method | |
248 ciBlock *b = new(arena) ciBlock(_method, _num_blocks++, this, 0); | |
249 _blocks->append(b); | |
250 _bci_to_block[0] = b; | |
251 | |
252 // create blocks for exception handlers | |
253 if (meth->has_exception_handlers()) { | |
254 for(ciExceptionHandlerStream str(meth); !str.is_done(); str.next()) { | |
255 ciExceptionHandler* handler = str.handler(); | |
256 ciBlock *eb = make_block_at(handler->handler_bci()); | |
257 eb->set_handler(); | |
258 int ex_start = handler->start(); | |
259 int ex_end = handler->limit(); | |
260 eb->set_exception_range(ex_start, ex_end); | |
261 // ensure a block at the start of exception range and start of following code | |
262 (void) make_block_at(ex_start); | |
263 if (ex_end < _code_size) | |
264 (void) make_block_at(ex_end); | |
265 } | |
266 } | |
267 | |
268 // scan the bytecodes and identify blocks | |
269 do_analysis(); | |
270 | |
271 // mark blocks that have exception handlers | |
272 if (meth->has_exception_handlers()) { | |
273 for(ciExceptionHandlerStream str(meth); !str.is_done(); str.next()) { | |
274 ciExceptionHandler* handler = str.handler(); | |
275 int ex_start = handler->start(); | |
276 int ex_end = handler->limit(); | |
277 | |
278 int bci = ex_start; | |
279 while (bci < ex_end) { | |
280 ciBlock *b = block_containing(bci); | |
281 b->set_has_handler(); | |
282 bci = b->limit_bci(); | |
283 } | |
284 } | |
285 } | |
286 } | |
287 | |
288 void ciMethodBlocks::clear_processed() { | |
289 for (int i = 0; i < _blocks->length(); i++) | |
290 _blocks->at(i)->clear_processed(); | |
291 } | |
292 | |
293 #ifndef PRODUCT | |
294 void ciMethodBlocks::dump() { | |
295 tty->print("---- blocks for method: "); | |
296 _method->print(); | |
297 tty->cr(); | |
298 for (int i = 0; i < _blocks->length(); i++) { | |
299 tty->print(" B%d: ", i); _blocks->at(i)->dump(); | |
300 } | |
301 } | |
302 #endif | |
303 | |
304 | |
305 ciBlock::ciBlock(ciMethod *method, int index, ciMethodBlocks *mb, int start_bci) : | |
306 #ifndef PRODUCT | |
307 _method(method), | |
308 #endif | |
309 _idx(index), _flags(0), _start_bci(start_bci), _limit_bci(-1), _control_bci(fall_through_bci), | |
310 _ex_start_bci(-1), _ex_limit_bci(-1) { | |
311 } | |
312 | |
313 void ciBlock::set_exception_range(int start_bci, int limit_bci) { | |
314 assert(limit_bci >= start_bci, "valid range"); | |
315 assert(is_handler(), "must be handler"); | |
316 _ex_start_bci = start_bci; | |
317 _ex_limit_bci = limit_bci; | |
318 } | |
319 | |
320 #ifndef PRODUCT | |
321 static char *flagnames[] = { | |
322 "Processed", | |
323 "Handler", | |
324 "MayThrow", | |
325 "Jsr", | |
326 "Ret", | |
327 "RetTarget", | |
328 "HasHandler", | |
329 }; | |
330 | |
331 void ciBlock::dump() { | |
332 tty->print(" [%d .. %d), {", _start_bci, _limit_bci); | |
333 for (int i = 0; i < 8; i++) { | |
334 if ((_flags & (1 << i)) != 0) { | |
335 tty->print(" %s", flagnames[i]); | |
336 } | |
337 } | |
338 tty->print(" ]"); | |
339 if (is_handler()) | |
340 tty->print(" handles(%d..%d)", _ex_start_bci, _ex_limit_bci); | |
341 tty->cr(); | |
342 } | |
343 | |
344 // ------------------------------------------------------------------ | |
345 // ciBlock::print_on | |
346 void ciBlock::print_on(outputStream* st) const { | |
347 st->print_cr("--------------------------------------------------------"); | |
348 st->print ("ciBlock [%d - %d) control : ", start_bci(), limit_bci()); | |
349 if (control_bci() == fall_through_bci) { | |
350 st->print_cr("%d:fall through", limit_bci()); | |
351 } else { | |
352 st->print_cr("%d:%s", control_bci(), | |
353 Bytecodes::name(method()->java_code_at_bci(control_bci()))); | |
354 } | |
355 | |
356 if (Verbose || WizardMode) { | |
357 method()->print_codes_on(start_bci(), limit_bci(), st); | |
358 } | |
359 } | |
360 #endif |