Mercurial > hg > truffle
annotate src/share/vm/ci/ciMethodBlocks.cpp @ 3762:5c0a3c1858b1
7048782: CMS: assert(last_chunk_index_to_check<= last_chunk_index) failed: parCardTableModRefBS.cpp:359
Summary: The LNC array is sized before the start of a scavenge, while the heap may expand during a scavenge. With CMS, the last block of an arbitrary suffice of the LNC array may expand due to coalition with the expansion delta. We now take care not to attempt access past the end of the LNC array. LNC array code will be cleaned up and suitably encapsulated as part of the forthcoming performance RFE 7043675.
Reviewed-by: brutisso
author | ysr |
---|---|
date | Thu, 02 Jun 2011 10:23:36 -0700 |
parents | 8012aa3ccede |
children |
rev | line source |
---|---|
0 | 1 /* |
2142 | 2 * Copyright (c) 2006, 2011, Oracle and/or its affiliates. All rights reserved. |
0 | 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
4 * | |
5 * This code is free software; you can redistribute it and/or modify it | |
6 * under the terms of the GNU General Public License version 2 only, as | |
7 * published by the Free Software Foundation. | |
8 * | |
9 * This code is distributed in the hope that it will be useful, but WITHOUT | |
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
12 * version 2 for more details (a copy is included in the LICENSE file that | |
13 * accompanied this code). | |
14 * | |
15 * You should have received a copy of the GNU General Public License version | |
16 * 2 along with this work; if not, write to the Free Software Foundation, | |
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. | |
18 * | |
1552
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
844
diff
changeset
|
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
844
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:
844
diff
changeset
|
21 * questions. |
0 | 22 * |
23 */ | |
24 | |
1972 | 25 #include "precompiled.hpp" |
26 #include "ci/ciMethodBlocks.hpp" | |
27 #include "ci/ciStreams.hpp" | |
28 #include "interpreter/bytecode.hpp" | |
29 #include "utilities/copy.hpp" | |
0 | 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"); | |
42 ciBlock *b = _bci_to_block[bci]; | |
43 assert(b != NULL, "must have block for bytecode"); | |
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); | |
367
194b8e3a2fc4
6384206: Phis which are later unneeded are impairing our ability to inline based on static types
never
parents:
250
diff
changeset
|
55 ciBlock *new_block = new(_arena) ciBlock(_method, _num_blocks++, former_block->start_bci()); |
0 | 56 _blocks->append(new_block); |
57 assert(former_block != NULL, "must not be NULL"); | |
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) { | |
66 // Non-bytecode start. Skip. | |
67 continue; | |
68 } else { | |
69 // We are done with our backwards walk | |
70 break; | |
71 } | |
72 } | |
26
0871d5cd64cd
6621084: ciMethodBlocks::split_block_at() is broken for methods with exception handler
kvn
parents:
0
diff
changeset
|
73 // Move an exception handler information if needed. |
0871d5cd64cd
6621084: ciMethodBlocks::split_block_at() is broken for methods with exception handler
kvn
parents:
0
diff
changeset
|
74 if (former_block->is_handler()) { |
0871d5cd64cd
6621084: ciMethodBlocks::split_block_at() is broken for methods with exception handler
kvn
parents:
0
diff
changeset
|
75 int ex_start = former_block->ex_start_bci(); |
0871d5cd64cd
6621084: ciMethodBlocks::split_block_at() is broken for methods with exception handler
kvn
parents:
0
diff
changeset
|
76 int ex_end = former_block->ex_limit_bci(); |
0871d5cd64cd
6621084: ciMethodBlocks::split_block_at() is broken for methods with exception handler
kvn
parents:
0
diff
changeset
|
77 new_block->set_exception_range(ex_start, ex_end); |
0871d5cd64cd
6621084: ciMethodBlocks::split_block_at() is broken for methods with exception handler
kvn
parents:
0
diff
changeset
|
78 // Clear information in former_block. |
0871d5cd64cd
6621084: ciMethodBlocks::split_block_at() is broken for methods with exception handler
kvn
parents:
0
diff
changeset
|
79 former_block->clear_exception_handler(); |
0871d5cd64cd
6621084: ciMethodBlocks::split_block_at() is broken for methods with exception handler
kvn
parents:
0
diff
changeset
|
80 } |
0 | 81 return former_block; |
82 } | |
83 | |
84 ciBlock *ciMethodBlocks::make_block_at(int bci) { | |
85 ciBlock *cb = block_containing(bci); | |
86 if (cb == NULL ) { | |
87 // This is our first time visiting this bytecode. Create | |
88 // a fresh block and assign it this starting point. | |
367
194b8e3a2fc4
6384206: Phis which are later unneeded are impairing our ability to inline based on static types
never
parents:
250
diff
changeset
|
89 ciBlock *nb = new(_arena) ciBlock(_method, _num_blocks++, bci); |
0 | 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 | |
367
194b8e3a2fc4
6384206: Phis which are later unneeded are impairing our ability to inline based on static types
never
parents:
250
diff
changeset
|
104 ciBlock *ciMethodBlocks::make_dummy_block() { |
194b8e3a2fc4
6384206: Phis which are later unneeded are impairing our ability to inline based on static types
never
parents:
250
diff
changeset
|
105 ciBlock *dum = new(_arena) ciBlock(_method, -1, 0); |
194b8e3a2fc4
6384206: Phis which are later unneeded are impairing our ability to inline based on static types
never
parents:
250
diff
changeset
|
106 return dum; |
194b8e3a2fc4
6384206: Phis which are later unneeded are impairing our ability to inline based on static types
never
parents:
250
diff
changeset
|
107 } |
194b8e3a2fc4
6384206: Phis which are later unneeded are impairing our ability to inline based on static types
never
parents:
250
diff
changeset
|
108 |
0 | 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"); | |
120 ciBlock *new_block = block_containing(bci); | |
26
0871d5cd64cd
6621084: ciMethodBlocks::split_block_at() is broken for methods with exception handler
kvn
parents:
0
diff
changeset
|
121 if (new_block == NULL || new_block == cur_block) { |
0 | 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); | |
2142 | 178 Bytecode_tableswitch sw(&s); |
179 int len = sw.length(); | |
0 | 180 ciBlock *dest; |
181 int dest_bci; | |
182 for (int i = 0; i < len; i++) { | |
2142 | 183 dest_bci = s.cur_bci() + sw.dest_offset_at(i); |
0 | 184 dest = make_block_at(dest_bci); |
185 } | |
2142 | 186 dest_bci = s.cur_bci() + sw.default_offset(); |
0 | 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); | |
2142 | 197 Bytecode_lookupswitch sw(&s); |
198 int len = sw.number_of_pairs(); | |
0 | 199 ciBlock *dest; |
200 int dest_bci; | |
201 for (int i = 0; i < len; i++) { | |
2142 | 202 dest_bci = s.cur_bci() + sw.pair_at(i).offset(); |
0 | 203 dest = make_block_at(dest_bci); |
204 } | |
2142 | 205 dest_bci = s.cur_bci() + sw.default_offset(); |
0 | 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 } | |
250 // End the last block | |
251 cur_block->set_limit_bci(limit_bci); | |
252 } | |
253 | |
254 ciMethodBlocks::ciMethodBlocks(Arena *arena, ciMethod *meth): _method(meth), | |
255 _arena(arena), _num_blocks(0), _code_size(meth->code_size()) { | |
256 int block_estimate = _code_size / 8; | |
257 | |
1685 | 258 _blocks = new(_arena) GrowableArray<ciBlock *>(_arena, block_estimate, 0, NULL); |
0 | 259 int b2bsize = _code_size * sizeof(ciBlock **); |
260 _bci_to_block = (ciBlock **) arena->Amalloc(b2bsize); | |
261 Copy::zero_to_words((HeapWord*) _bci_to_block, b2bsize / sizeof(HeapWord)); | |
262 | |
263 // create initial block covering the entire method | |
367
194b8e3a2fc4
6384206: Phis which are later unneeded are impairing our ability to inline based on static types
never
parents:
250
diff
changeset
|
264 ciBlock *b = new(arena) ciBlock(_method, _num_blocks++, 0); |
0 | 265 _blocks->append(b); |
266 _bci_to_block[0] = b; | |
267 | |
268 // create blocks for exception handlers | |
269 if (meth->has_exception_handlers()) { | |
270 for(ciExceptionHandlerStream str(meth); !str.is_done(); str.next()) { | |
271 ciExceptionHandler* handler = str.handler(); | |
272 ciBlock *eb = make_block_at(handler->handler_bci()); | |
26
0871d5cd64cd
6621084: ciMethodBlocks::split_block_at() is broken for methods with exception handler
kvn
parents:
0
diff
changeset
|
273 // |
0871d5cd64cd
6621084: ciMethodBlocks::split_block_at() is broken for methods with exception handler
kvn
parents:
0
diff
changeset
|
274 // Several exception handlers can have the same handler_bci: |
0871d5cd64cd
6621084: ciMethodBlocks::split_block_at() is broken for methods with exception handler
kvn
parents:
0
diff
changeset
|
275 // |
0871d5cd64cd
6621084: ciMethodBlocks::split_block_at() is broken for methods with exception handler
kvn
parents:
0
diff
changeset
|
276 // try { |
0871d5cd64cd
6621084: ciMethodBlocks::split_block_at() is broken for methods with exception handler
kvn
parents:
0
diff
changeset
|
277 // if (a.foo(b) < 0) { |
0871d5cd64cd
6621084: ciMethodBlocks::split_block_at() is broken for methods with exception handler
kvn
parents:
0
diff
changeset
|
278 // return a.error(); |
0871d5cd64cd
6621084: ciMethodBlocks::split_block_at() is broken for methods with exception handler
kvn
parents:
0
diff
changeset
|
279 // } |
0871d5cd64cd
6621084: ciMethodBlocks::split_block_at() is broken for methods with exception handler
kvn
parents:
0
diff
changeset
|
280 // return CoderResult.UNDERFLOW; |
0871d5cd64cd
6621084: ciMethodBlocks::split_block_at() is broken for methods with exception handler
kvn
parents:
0
diff
changeset
|
281 // } finally { |
0871d5cd64cd
6621084: ciMethodBlocks::split_block_at() is broken for methods with exception handler
kvn
parents:
0
diff
changeset
|
282 // a.position(b); |
0871d5cd64cd
6621084: ciMethodBlocks::split_block_at() is broken for methods with exception handler
kvn
parents:
0
diff
changeset
|
283 // } |
0871d5cd64cd
6621084: ciMethodBlocks::split_block_at() is broken for methods with exception handler
kvn
parents:
0
diff
changeset
|
284 // |
0871d5cd64cd
6621084: ciMethodBlocks::split_block_at() is broken for methods with exception handler
kvn
parents:
0
diff
changeset
|
285 // The try block above is divided into 2 exception blocks |
0871d5cd64cd
6621084: ciMethodBlocks::split_block_at() is broken for methods with exception handler
kvn
parents:
0
diff
changeset
|
286 // separated by 'areturn' bci. |
0871d5cd64cd
6621084: ciMethodBlocks::split_block_at() is broken for methods with exception handler
kvn
parents:
0
diff
changeset
|
287 // |
0 | 288 int ex_start = handler->start(); |
289 int ex_end = handler->limit(); | |
646 | 290 // ensure a block at the start of exception range and start of following code |
291 (void) make_block_at(ex_start); | |
292 if (ex_end < _code_size) | |
293 (void) make_block_at(ex_end); | |
294 | |
26
0871d5cd64cd
6621084: ciMethodBlocks::split_block_at() is broken for methods with exception handler
kvn
parents:
0
diff
changeset
|
295 if (eb->is_handler()) { |
0871d5cd64cd
6621084: ciMethodBlocks::split_block_at() is broken for methods with exception handler
kvn
parents:
0
diff
changeset
|
296 // Extend old handler exception range to cover additional range. |
0871d5cd64cd
6621084: ciMethodBlocks::split_block_at() is broken for methods with exception handler
kvn
parents:
0
diff
changeset
|
297 int old_ex_start = eb->ex_start_bci(); |
0871d5cd64cd
6621084: ciMethodBlocks::split_block_at() is broken for methods with exception handler
kvn
parents:
0
diff
changeset
|
298 int old_ex_end = eb->ex_limit_bci(); |
0871d5cd64cd
6621084: ciMethodBlocks::split_block_at() is broken for methods with exception handler
kvn
parents:
0
diff
changeset
|
299 if (ex_start > old_ex_start) |
0871d5cd64cd
6621084: ciMethodBlocks::split_block_at() is broken for methods with exception handler
kvn
parents:
0
diff
changeset
|
300 ex_start = old_ex_start; |
0871d5cd64cd
6621084: ciMethodBlocks::split_block_at() is broken for methods with exception handler
kvn
parents:
0
diff
changeset
|
301 if (ex_end < old_ex_end) |
0871d5cd64cd
6621084: ciMethodBlocks::split_block_at() is broken for methods with exception handler
kvn
parents:
0
diff
changeset
|
302 ex_end = old_ex_end; |
0871d5cd64cd
6621084: ciMethodBlocks::split_block_at() is broken for methods with exception handler
kvn
parents:
0
diff
changeset
|
303 eb->clear_exception_handler(); // Reset exception information |
0871d5cd64cd
6621084: ciMethodBlocks::split_block_at() is broken for methods with exception handler
kvn
parents:
0
diff
changeset
|
304 } |
0 | 305 eb->set_exception_range(ex_start, ex_end); |
306 } | |
307 } | |
308 | |
309 // scan the bytecodes and identify blocks | |
310 do_analysis(); | |
311 | |
312 // mark blocks that have exception handlers | |
313 if (meth->has_exception_handlers()) { | |
314 for(ciExceptionHandlerStream str(meth); !str.is_done(); str.next()) { | |
315 ciExceptionHandler* handler = str.handler(); | |
316 int ex_start = handler->start(); | |
317 int ex_end = handler->limit(); | |
318 | |
319 int bci = ex_start; | |
320 while (bci < ex_end) { | |
321 ciBlock *b = block_containing(bci); | |
322 b->set_has_handler(); | |
323 bci = b->limit_bci(); | |
324 } | |
325 } | |
326 } | |
327 } | |
328 | |
329 void ciMethodBlocks::clear_processed() { | |
330 for (int i = 0; i < _blocks->length(); i++) | |
331 _blocks->at(i)->clear_processed(); | |
332 } | |
333 | |
334 #ifndef PRODUCT | |
335 void ciMethodBlocks::dump() { | |
336 tty->print("---- blocks for method: "); | |
337 _method->print(); | |
338 tty->cr(); | |
339 for (int i = 0; i < _blocks->length(); i++) { | |
340 tty->print(" B%d: ", i); _blocks->at(i)->dump(); | |
341 } | |
342 } | |
343 #endif | |
344 | |
345 | |
367
194b8e3a2fc4
6384206: Phis which are later unneeded are impairing our ability to inline based on static types
never
parents:
250
diff
changeset
|
346 ciBlock::ciBlock(ciMethod *method, int index, int start_bci) : |
0 | 347 #ifndef PRODUCT |
348 _method(method), | |
349 #endif | |
350 _idx(index), _flags(0), _start_bci(start_bci), _limit_bci(-1), _control_bci(fall_through_bci), | |
351 _ex_start_bci(-1), _ex_limit_bci(-1) { | |
352 } | |
353 | |
354 void ciBlock::set_exception_range(int start_bci, int limit_bci) { | |
355 assert(limit_bci >= start_bci, "valid range"); | |
26
0871d5cd64cd
6621084: ciMethodBlocks::split_block_at() is broken for methods with exception handler
kvn
parents:
0
diff
changeset
|
356 assert(!is_handler() && _ex_start_bci == -1 && _ex_limit_bci == -1, "must not be handler"); |
0 | 357 _ex_start_bci = start_bci; |
358 _ex_limit_bci = limit_bci; | |
26
0871d5cd64cd
6621084: ciMethodBlocks::split_block_at() is broken for methods with exception handler
kvn
parents:
0
diff
changeset
|
359 set_handler(); |
0 | 360 } |
361 | |
362 #ifndef PRODUCT | |
250
6ca61c728c2d
6712835: Server compiler fails with assertion (loop_count < K,"infinite loop in PhaseIterGVN::transform")
never
parents:
196
diff
changeset
|
363 static const char *flagnames[] = { |
0 | 364 "Processed", |
365 "Handler", | |
366 "MayThrow", | |
367 "Jsr", | |
368 "Ret", | |
369 "RetTarget", | |
370 "HasHandler", | |
371 }; | |
372 | |
373 void ciBlock::dump() { | |
374 tty->print(" [%d .. %d), {", _start_bci, _limit_bci); | |
375 for (int i = 0; i < 8; i++) { | |
376 if ((_flags & (1 << i)) != 0) { | |
377 tty->print(" %s", flagnames[i]); | |
378 } | |
379 } | |
380 tty->print(" ]"); | |
381 if (is_handler()) | |
382 tty->print(" handles(%d..%d)", _ex_start_bci, _ex_limit_bci); | |
383 tty->cr(); | |
384 } | |
385 | |
386 // ------------------------------------------------------------------ | |
387 // ciBlock::print_on | |
388 void ciBlock::print_on(outputStream* st) const { | |
389 st->print_cr("--------------------------------------------------------"); | |
390 st->print ("ciBlock [%d - %d) control : ", start_bci(), limit_bci()); | |
391 if (control_bci() == fall_through_bci) { | |
392 st->print_cr("%d:fall through", limit_bci()); | |
393 } else { | |
394 st->print_cr("%d:%s", control_bci(), | |
395 Bytecodes::name(method()->java_code_at_bci(control_bci()))); | |
396 } | |
397 | |
398 if (Verbose || WizardMode) { | |
399 method()->print_codes_on(start_bci(), limit_bci(), st); | |
400 } | |
401 } | |
402 #endif |