|
1 /* |
|
2 * Copyright 2000-2007 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/_methodDataOop.cpp.incl" |
|
27 |
|
28 // ================================================================== |
|
29 // DataLayout |
|
30 // |
|
31 // Overlay for generic profiling data. |
|
32 |
|
33 // Some types of data layouts need a length field. |
|
34 bool DataLayout::needs_array_len(u1 tag) { |
|
35 return (tag == multi_branch_data_tag); |
|
36 } |
|
37 |
|
38 // Perform generic initialization of the data. More specific |
|
39 // initialization occurs in overrides of ProfileData::post_initialize. |
|
40 void DataLayout::initialize(u1 tag, u2 bci, int cell_count) { |
|
41 _header._bits = (intptr_t)0; |
|
42 _header._struct._tag = tag; |
|
43 _header._struct._bci = bci; |
|
44 for (int i = 0; i < cell_count; i++) { |
|
45 set_cell_at(i, (intptr_t)0); |
|
46 } |
|
47 if (needs_array_len(tag)) { |
|
48 set_cell_at(ArrayData::array_len_off_set, cell_count - 1); // -1 for header. |
|
49 } |
|
50 } |
|
51 |
|
52 // ================================================================== |
|
53 // ProfileData |
|
54 // |
|
55 // A ProfileData object is created to refer to a section of profiling |
|
56 // data in a structured way. |
|
57 |
|
58 // Constructor for invalid ProfileData. |
|
59 ProfileData::ProfileData() { |
|
60 _data = NULL; |
|
61 } |
|
62 |
|
63 #ifndef PRODUCT |
|
64 void ProfileData::print_shared(outputStream* st, const char* name) { |
|
65 st->print("bci: %d", bci()); |
|
66 st->fill_to(tab_width_one); |
|
67 st->print("%s", name); |
|
68 tab(st); |
|
69 int trap = trap_state(); |
|
70 if (trap != 0) { |
|
71 char buf[100]; |
|
72 st->print("trap(%s) ", Deoptimization::format_trap_state(buf, sizeof(buf), trap)); |
|
73 } |
|
74 int flags = data()->flags(); |
|
75 if (flags != 0) |
|
76 st->print("flags(%d) ", flags); |
|
77 } |
|
78 |
|
79 void ProfileData::tab(outputStream* st) { |
|
80 st->fill_to(tab_width_two); |
|
81 } |
|
82 #endif // !PRODUCT |
|
83 |
|
84 // ================================================================== |
|
85 // BitData |
|
86 // |
|
87 // A BitData corresponds to a one-bit flag. This is used to indicate |
|
88 // whether a checkcast bytecode has seen a null value. |
|
89 |
|
90 |
|
91 #ifndef PRODUCT |
|
92 void BitData::print_data_on(outputStream* st) { |
|
93 print_shared(st, "BitData"); |
|
94 } |
|
95 #endif // !PRODUCT |
|
96 |
|
97 // ================================================================== |
|
98 // CounterData |
|
99 // |
|
100 // A CounterData corresponds to a simple counter. |
|
101 |
|
102 #ifndef PRODUCT |
|
103 void CounterData::print_data_on(outputStream* st) { |
|
104 print_shared(st, "CounterData"); |
|
105 st->print_cr("count(%u)", count()); |
|
106 } |
|
107 #endif // !PRODUCT |
|
108 |
|
109 // ================================================================== |
|
110 // JumpData |
|
111 // |
|
112 // A JumpData is used to access profiling information for a direct |
|
113 // branch. It is a counter, used for counting the number of branches, |
|
114 // plus a data displacement, used for realigning the data pointer to |
|
115 // the corresponding target bci. |
|
116 |
|
117 void JumpData::post_initialize(BytecodeStream* stream, methodDataOop mdo) { |
|
118 assert(stream->bci() == bci(), "wrong pos"); |
|
119 int target; |
|
120 Bytecodes::Code c = stream->code(); |
|
121 if (c == Bytecodes::_goto_w || c == Bytecodes::_jsr_w) { |
|
122 target = stream->dest_w(); |
|
123 } else { |
|
124 target = stream->dest(); |
|
125 } |
|
126 int my_di = mdo->dp_to_di(dp()); |
|
127 int target_di = mdo->bci_to_di(target); |
|
128 int offset = target_di - my_di; |
|
129 set_displacement(offset); |
|
130 } |
|
131 |
|
132 #ifndef PRODUCT |
|
133 void JumpData::print_data_on(outputStream* st) { |
|
134 print_shared(st, "JumpData"); |
|
135 st->print_cr("taken(%u) displacement(%d)", taken(), displacement()); |
|
136 } |
|
137 #endif // !PRODUCT |
|
138 |
|
139 // ================================================================== |
|
140 // ReceiverTypeData |
|
141 // |
|
142 // A ReceiverTypeData is used to access profiling information about a |
|
143 // dynamic type check. It consists of a counter which counts the total times |
|
144 // that the check is reached, and a series of (klassOop, count) pairs |
|
145 // which are used to store a type profile for the receiver of the check. |
|
146 |
|
147 void ReceiverTypeData::follow_contents() { |
|
148 for (uint row = 0; row < row_limit(); row++) { |
|
149 if (receiver(row) != NULL) { |
|
150 MarkSweep::mark_and_push(adr_receiver(row)); |
|
151 } |
|
152 } |
|
153 } |
|
154 |
|
155 #ifndef SERIALGC |
|
156 void ReceiverTypeData::follow_contents(ParCompactionManager* cm) { |
|
157 for (uint row = 0; row < row_limit(); row++) { |
|
158 if (receiver(row) != NULL) { |
|
159 PSParallelCompact::mark_and_push(cm, adr_receiver(row)); |
|
160 } |
|
161 } |
|
162 } |
|
163 #endif // SERIALGC |
|
164 |
|
165 void ReceiverTypeData::oop_iterate(OopClosure* blk) { |
|
166 for (uint row = 0; row < row_limit(); row++) { |
|
167 if (receiver(row) != NULL) { |
|
168 blk->do_oop(adr_receiver(row)); |
|
169 } |
|
170 } |
|
171 } |
|
172 |
|
173 void ReceiverTypeData::oop_iterate_m(OopClosure* blk, MemRegion mr) { |
|
174 for (uint row = 0; row < row_limit(); row++) { |
|
175 if (receiver(row) != NULL) { |
|
176 oop* adr = adr_receiver(row); |
|
177 if (mr.contains(adr)) { |
|
178 blk->do_oop(adr); |
|
179 } |
|
180 } |
|
181 } |
|
182 } |
|
183 |
|
184 void ReceiverTypeData::adjust_pointers() { |
|
185 for (uint row = 0; row < row_limit(); row++) { |
|
186 if (receiver(row) != NULL) { |
|
187 MarkSweep::adjust_pointer(adr_receiver(row)); |
|
188 } |
|
189 } |
|
190 } |
|
191 |
|
192 #ifndef SERIALGC |
|
193 void ReceiverTypeData::update_pointers() { |
|
194 for (uint row = 0; row < row_limit(); row++) { |
|
195 if (receiver_unchecked(row) != NULL) { |
|
196 PSParallelCompact::adjust_pointer(adr_receiver(row)); |
|
197 } |
|
198 } |
|
199 } |
|
200 |
|
201 void ReceiverTypeData::update_pointers(HeapWord* beg_addr, HeapWord* end_addr) { |
|
202 // The loop bounds could be computed based on beg_addr/end_addr and the |
|
203 // boundary test hoisted outside the loop (see klassVTable for an example); |
|
204 // however, row_limit() is small enough (2) to make that less efficient. |
|
205 for (uint row = 0; row < row_limit(); row++) { |
|
206 if (receiver_unchecked(row) != NULL) { |
|
207 PSParallelCompact::adjust_pointer(adr_receiver(row), beg_addr, end_addr); |
|
208 } |
|
209 } |
|
210 } |
|
211 #endif // SERIALGC |
|
212 |
|
213 #ifndef PRODUCT |
|
214 void ReceiverTypeData::print_receiver_data_on(outputStream* st) { |
|
215 uint row; |
|
216 int entries = 0; |
|
217 for (row = 0; row < row_limit(); row++) { |
|
218 if (receiver(row) != NULL) entries++; |
|
219 } |
|
220 st->print_cr("count(%u) entries(%u)", count(), entries); |
|
221 for (row = 0; row < row_limit(); row++) { |
|
222 if (receiver(row) != NULL) { |
|
223 tab(st); |
|
224 receiver(row)->print_value_on(st); |
|
225 st->print_cr("(%u)", receiver_count(row)); |
|
226 } |
|
227 } |
|
228 } |
|
229 void ReceiverTypeData::print_data_on(outputStream* st) { |
|
230 print_shared(st, "ReceiverTypeData"); |
|
231 print_receiver_data_on(st); |
|
232 } |
|
233 void VirtualCallData::print_data_on(outputStream* st) { |
|
234 print_shared(st, "VirtualCallData"); |
|
235 print_receiver_data_on(st); |
|
236 } |
|
237 #endif // !PRODUCT |
|
238 |
|
239 // ================================================================== |
|
240 // RetData |
|
241 // |
|
242 // A RetData is used to access profiling information for a ret bytecode. |
|
243 // It is composed of a count of the number of times that the ret has |
|
244 // been executed, followed by a series of triples of the form |
|
245 // (bci, count, di) which count the number of times that some bci was the |
|
246 // target of the ret and cache a corresponding displacement. |
|
247 |
|
248 void RetData::post_initialize(BytecodeStream* stream, methodDataOop mdo) { |
|
249 for (uint row = 0; row < row_limit(); row++) { |
|
250 set_bci_displacement(row, -1); |
|
251 set_bci(row, no_bci); |
|
252 } |
|
253 // release so other threads see a consistent state. bci is used as |
|
254 // a valid flag for bci_displacement. |
|
255 OrderAccess::release(); |
|
256 } |
|
257 |
|
258 // This routine needs to atomically update the RetData structure, so the |
|
259 // caller needs to hold the RetData_lock before it gets here. Since taking |
|
260 // the lock can block (and allow GC) and since RetData is a ProfileData is a |
|
261 // wrapper around a derived oop, taking the lock in _this_ method will |
|
262 // basically cause the 'this' pointer's _data field to contain junk after the |
|
263 // lock. We require the caller to take the lock before making the ProfileData |
|
264 // structure. Currently the only caller is InterpreterRuntime::update_mdp_for_ret |
|
265 address RetData::fixup_ret(int return_bci, methodDataHandle h_mdo) { |
|
266 // First find the mdp which corresponds to the return bci. |
|
267 address mdp = h_mdo->bci_to_dp(return_bci); |
|
268 |
|
269 // Now check to see if any of the cache slots are open. |
|
270 for (uint row = 0; row < row_limit(); row++) { |
|
271 if (bci(row) == no_bci) { |
|
272 set_bci_displacement(row, mdp - dp()); |
|
273 set_bci_count(row, DataLayout::counter_increment); |
|
274 // Barrier to ensure displacement is written before the bci; allows |
|
275 // the interpreter to read displacement without fear of race condition. |
|
276 release_set_bci(row, return_bci); |
|
277 break; |
|
278 } |
|
279 } |
|
280 return mdp; |
|
281 } |
|
282 |
|
283 |
|
284 #ifndef PRODUCT |
|
285 void RetData::print_data_on(outputStream* st) { |
|
286 print_shared(st, "RetData"); |
|
287 uint row; |
|
288 int entries = 0; |
|
289 for (row = 0; row < row_limit(); row++) { |
|
290 if (bci(row) != no_bci) entries++; |
|
291 } |
|
292 st->print_cr("count(%u) entries(%u)", count(), entries); |
|
293 for (row = 0; row < row_limit(); row++) { |
|
294 if (bci(row) != no_bci) { |
|
295 tab(st); |
|
296 st->print_cr("bci(%d: count(%u) displacement(%d))", |
|
297 bci(row), bci_count(row), bci_displacement(row)); |
|
298 } |
|
299 } |
|
300 } |
|
301 #endif // !PRODUCT |
|
302 |
|
303 // ================================================================== |
|
304 // BranchData |
|
305 // |
|
306 // A BranchData is used to access profiling data for a two-way branch. |
|
307 // It consists of taken and not_taken counts as well as a data displacement |
|
308 // for the taken case. |
|
309 |
|
310 void BranchData::post_initialize(BytecodeStream* stream, methodDataOop mdo) { |
|
311 assert(stream->bci() == bci(), "wrong pos"); |
|
312 int target = stream->dest(); |
|
313 int my_di = mdo->dp_to_di(dp()); |
|
314 int target_di = mdo->bci_to_di(target); |
|
315 int offset = target_di - my_di; |
|
316 set_displacement(offset); |
|
317 } |
|
318 |
|
319 #ifndef PRODUCT |
|
320 void BranchData::print_data_on(outputStream* st) { |
|
321 print_shared(st, "BranchData"); |
|
322 st->print_cr("taken(%u) displacement(%d)", |
|
323 taken(), displacement()); |
|
324 tab(st); |
|
325 st->print_cr("not taken(%u)", not_taken()); |
|
326 } |
|
327 #endif |
|
328 |
|
329 // ================================================================== |
|
330 // MultiBranchData |
|
331 // |
|
332 // A MultiBranchData is used to access profiling information for |
|
333 // a multi-way branch (*switch bytecodes). It consists of a series |
|
334 // of (count, displacement) pairs, which count the number of times each |
|
335 // case was taken and specify the data displacment for each branch target. |
|
336 |
|
337 int MultiBranchData::compute_cell_count(BytecodeStream* stream) { |
|
338 int cell_count = 0; |
|
339 if (stream->code() == Bytecodes::_tableswitch) { |
|
340 Bytecode_tableswitch* sw = Bytecode_tableswitch_at(stream->bcp()); |
|
341 cell_count = 1 + per_case_cell_count * (1 + sw->length()); // 1 for default |
|
342 } else { |
|
343 Bytecode_lookupswitch* sw = Bytecode_lookupswitch_at(stream->bcp()); |
|
344 cell_count = 1 + per_case_cell_count * (sw->number_of_pairs() + 1); // 1 for default |
|
345 } |
|
346 return cell_count; |
|
347 } |
|
348 |
|
349 void MultiBranchData::post_initialize(BytecodeStream* stream, |
|
350 methodDataOop mdo) { |
|
351 assert(stream->bci() == bci(), "wrong pos"); |
|
352 int target; |
|
353 int my_di; |
|
354 int target_di; |
|
355 int offset; |
|
356 if (stream->code() == Bytecodes::_tableswitch) { |
|
357 Bytecode_tableswitch* sw = Bytecode_tableswitch_at(stream->bcp()); |
|
358 int len = sw->length(); |
|
359 assert(array_len() == per_case_cell_count * (len + 1), "wrong len"); |
|
360 for (int count = 0; count < len; count++) { |
|
361 target = sw->dest_offset_at(count) + bci(); |
|
362 my_di = mdo->dp_to_di(dp()); |
|
363 target_di = mdo->bci_to_di(target); |
|
364 offset = target_di - my_di; |
|
365 set_displacement_at(count, offset); |
|
366 } |
|
367 target = sw->default_offset() + bci(); |
|
368 my_di = mdo->dp_to_di(dp()); |
|
369 target_di = mdo->bci_to_di(target); |
|
370 offset = target_di - my_di; |
|
371 set_default_displacement(offset); |
|
372 |
|
373 } else { |
|
374 Bytecode_lookupswitch* sw = Bytecode_lookupswitch_at(stream->bcp()); |
|
375 int npairs = sw->number_of_pairs(); |
|
376 assert(array_len() == per_case_cell_count * (npairs + 1), "wrong len"); |
|
377 for (int count = 0; count < npairs; count++) { |
|
378 LookupswitchPair *pair = sw->pair_at(count); |
|
379 target = pair->offset() + bci(); |
|
380 my_di = mdo->dp_to_di(dp()); |
|
381 target_di = mdo->bci_to_di(target); |
|
382 offset = target_di - my_di; |
|
383 set_displacement_at(count, offset); |
|
384 } |
|
385 target = sw->default_offset() + bci(); |
|
386 my_di = mdo->dp_to_di(dp()); |
|
387 target_di = mdo->bci_to_di(target); |
|
388 offset = target_di - my_di; |
|
389 set_default_displacement(offset); |
|
390 } |
|
391 } |
|
392 |
|
393 #ifndef PRODUCT |
|
394 void MultiBranchData::print_data_on(outputStream* st) { |
|
395 print_shared(st, "MultiBranchData"); |
|
396 st->print_cr("default_count(%u) displacement(%d)", |
|
397 default_count(), default_displacement()); |
|
398 int cases = number_of_cases(); |
|
399 for (int i = 0; i < cases; i++) { |
|
400 tab(st); |
|
401 st->print_cr("count(%u) displacement(%d)", |
|
402 count_at(i), displacement_at(i)); |
|
403 } |
|
404 } |
|
405 #endif |
|
406 |
|
407 // ================================================================== |
|
408 // methodDataOop |
|
409 // |
|
410 // A methodDataOop holds information which has been collected about |
|
411 // a method. |
|
412 |
|
413 int methodDataOopDesc::bytecode_cell_count(Bytecodes::Code code) { |
|
414 switch (code) { |
|
415 case Bytecodes::_checkcast: |
|
416 case Bytecodes::_instanceof: |
|
417 case Bytecodes::_aastore: |
|
418 if (TypeProfileCasts) { |
|
419 return ReceiverTypeData::static_cell_count(); |
|
420 } else { |
|
421 return BitData::static_cell_count(); |
|
422 } |
|
423 case Bytecodes::_invokespecial: |
|
424 case Bytecodes::_invokestatic: |
|
425 return CounterData::static_cell_count(); |
|
426 case Bytecodes::_goto: |
|
427 case Bytecodes::_goto_w: |
|
428 case Bytecodes::_jsr: |
|
429 case Bytecodes::_jsr_w: |
|
430 return JumpData::static_cell_count(); |
|
431 case Bytecodes::_invokevirtual: |
|
432 case Bytecodes::_invokeinterface: |
|
433 return VirtualCallData::static_cell_count(); |
|
434 case Bytecodes::_ret: |
|
435 return RetData::static_cell_count(); |
|
436 case Bytecodes::_ifeq: |
|
437 case Bytecodes::_ifne: |
|
438 case Bytecodes::_iflt: |
|
439 case Bytecodes::_ifge: |
|
440 case Bytecodes::_ifgt: |
|
441 case Bytecodes::_ifle: |
|
442 case Bytecodes::_if_icmpeq: |
|
443 case Bytecodes::_if_icmpne: |
|
444 case Bytecodes::_if_icmplt: |
|
445 case Bytecodes::_if_icmpge: |
|
446 case Bytecodes::_if_icmpgt: |
|
447 case Bytecodes::_if_icmple: |
|
448 case Bytecodes::_if_acmpeq: |
|
449 case Bytecodes::_if_acmpne: |
|
450 case Bytecodes::_ifnull: |
|
451 case Bytecodes::_ifnonnull: |
|
452 return BranchData::static_cell_count(); |
|
453 case Bytecodes::_lookupswitch: |
|
454 case Bytecodes::_tableswitch: |
|
455 return variable_cell_count; |
|
456 } |
|
457 return no_profile_data; |
|
458 } |
|
459 |
|
460 // Compute the size of the profiling information corresponding to |
|
461 // the current bytecode. |
|
462 int methodDataOopDesc::compute_data_size(BytecodeStream* stream) { |
|
463 int cell_count = bytecode_cell_count(stream->code()); |
|
464 if (cell_count == no_profile_data) { |
|
465 return 0; |
|
466 } |
|
467 if (cell_count == variable_cell_count) { |
|
468 cell_count = MultiBranchData::compute_cell_count(stream); |
|
469 } |
|
470 // Note: cell_count might be zero, meaning that there is just |
|
471 // a DataLayout header, with no extra cells. |
|
472 assert(cell_count >= 0, "sanity"); |
|
473 return DataLayout::compute_size_in_bytes(cell_count); |
|
474 } |
|
475 |
|
476 int methodDataOopDesc::compute_extra_data_count(int data_size, int empty_bc_count) { |
|
477 if (ProfileTraps) { |
|
478 // Assume that up to 3% of BCIs with no MDP will need to allocate one. |
|
479 int extra_data_count = (uint)(empty_bc_count * 3) / 128 + 1; |
|
480 // If the method is large, let the extra BCIs grow numerous (to ~1%). |
|
481 int one_percent_of_data |
|
482 = (uint)data_size / (DataLayout::header_size_in_bytes()*128); |
|
483 if (extra_data_count < one_percent_of_data) |
|
484 extra_data_count = one_percent_of_data; |
|
485 if (extra_data_count > empty_bc_count) |
|
486 extra_data_count = empty_bc_count; // no need for more |
|
487 return extra_data_count; |
|
488 } else { |
|
489 return 0; |
|
490 } |
|
491 } |
|
492 |
|
493 // Compute the size of the methodDataOop necessary to store |
|
494 // profiling information about a given method. Size is in bytes. |
|
495 int methodDataOopDesc::compute_allocation_size_in_bytes(methodHandle method) { |
|
496 int data_size = 0; |
|
497 BytecodeStream stream(method); |
|
498 Bytecodes::Code c; |
|
499 int empty_bc_count = 0; // number of bytecodes lacking data |
|
500 while ((c = stream.next()) >= 0) { |
|
501 int size_in_bytes = compute_data_size(&stream); |
|
502 data_size += size_in_bytes; |
|
503 if (size_in_bytes == 0) empty_bc_count += 1; |
|
504 } |
|
505 int object_size = in_bytes(data_offset()) + data_size; |
|
506 |
|
507 // Add some extra DataLayout cells (at least one) to track stray traps. |
|
508 int extra_data_count = compute_extra_data_count(data_size, empty_bc_count); |
|
509 object_size += extra_data_count * DataLayout::compute_size_in_bytes(0); |
|
510 |
|
511 return object_size; |
|
512 } |
|
513 |
|
514 // Compute the size of the methodDataOop necessary to store |
|
515 // profiling information about a given method. Size is in words |
|
516 int methodDataOopDesc::compute_allocation_size_in_words(methodHandle method) { |
|
517 int byte_size = compute_allocation_size_in_bytes(method); |
|
518 int word_size = align_size_up(byte_size, BytesPerWord) / BytesPerWord; |
|
519 return align_object_size(word_size); |
|
520 } |
|
521 |
|
522 // Initialize an individual data segment. Returns the size of |
|
523 // the segment in bytes. |
|
524 int methodDataOopDesc::initialize_data(BytecodeStream* stream, |
|
525 int data_index) { |
|
526 int cell_count = -1; |
|
527 int tag = DataLayout::no_tag; |
|
528 DataLayout* data_layout = data_layout_at(data_index); |
|
529 Bytecodes::Code c = stream->code(); |
|
530 switch (c) { |
|
531 case Bytecodes::_checkcast: |
|
532 case Bytecodes::_instanceof: |
|
533 case Bytecodes::_aastore: |
|
534 if (TypeProfileCasts) { |
|
535 cell_count = ReceiverTypeData::static_cell_count(); |
|
536 tag = DataLayout::receiver_type_data_tag; |
|
537 } else { |
|
538 cell_count = BitData::static_cell_count(); |
|
539 tag = DataLayout::bit_data_tag; |
|
540 } |
|
541 break; |
|
542 case Bytecodes::_invokespecial: |
|
543 case Bytecodes::_invokestatic: |
|
544 cell_count = CounterData::static_cell_count(); |
|
545 tag = DataLayout::counter_data_tag; |
|
546 break; |
|
547 case Bytecodes::_goto: |
|
548 case Bytecodes::_goto_w: |
|
549 case Bytecodes::_jsr: |
|
550 case Bytecodes::_jsr_w: |
|
551 cell_count = JumpData::static_cell_count(); |
|
552 tag = DataLayout::jump_data_tag; |
|
553 break; |
|
554 case Bytecodes::_invokevirtual: |
|
555 case Bytecodes::_invokeinterface: |
|
556 cell_count = VirtualCallData::static_cell_count(); |
|
557 tag = DataLayout::virtual_call_data_tag; |
|
558 break; |
|
559 case Bytecodes::_ret: |
|
560 cell_count = RetData::static_cell_count(); |
|
561 tag = DataLayout::ret_data_tag; |
|
562 break; |
|
563 case Bytecodes::_ifeq: |
|
564 case Bytecodes::_ifne: |
|
565 case Bytecodes::_iflt: |
|
566 case Bytecodes::_ifge: |
|
567 case Bytecodes::_ifgt: |
|
568 case Bytecodes::_ifle: |
|
569 case Bytecodes::_if_icmpeq: |
|
570 case Bytecodes::_if_icmpne: |
|
571 case Bytecodes::_if_icmplt: |
|
572 case Bytecodes::_if_icmpge: |
|
573 case Bytecodes::_if_icmpgt: |
|
574 case Bytecodes::_if_icmple: |
|
575 case Bytecodes::_if_acmpeq: |
|
576 case Bytecodes::_if_acmpne: |
|
577 case Bytecodes::_ifnull: |
|
578 case Bytecodes::_ifnonnull: |
|
579 cell_count = BranchData::static_cell_count(); |
|
580 tag = DataLayout::branch_data_tag; |
|
581 break; |
|
582 case Bytecodes::_lookupswitch: |
|
583 case Bytecodes::_tableswitch: |
|
584 cell_count = MultiBranchData::compute_cell_count(stream); |
|
585 tag = DataLayout::multi_branch_data_tag; |
|
586 break; |
|
587 } |
|
588 assert(tag == DataLayout::multi_branch_data_tag || |
|
589 cell_count == bytecode_cell_count(c), "cell counts must agree"); |
|
590 if (cell_count >= 0) { |
|
591 assert(tag != DataLayout::no_tag, "bad tag"); |
|
592 assert(bytecode_has_profile(c), "agree w/ BHP"); |
|
593 data_layout->initialize(tag, stream->bci(), cell_count); |
|
594 return DataLayout::compute_size_in_bytes(cell_count); |
|
595 } else { |
|
596 assert(!bytecode_has_profile(c), "agree w/ !BHP"); |
|
597 return 0; |
|
598 } |
|
599 } |
|
600 |
|
601 // Get the data at an arbitrary (sort of) data index. |
|
602 ProfileData* methodDataOopDesc::data_at(int data_index) { |
|
603 if (out_of_bounds(data_index)) { |
|
604 return NULL; |
|
605 } |
|
606 DataLayout* data_layout = data_layout_at(data_index); |
|
607 |
|
608 switch (data_layout->tag()) { |
|
609 case DataLayout::no_tag: |
|
610 default: |
|
611 ShouldNotReachHere(); |
|
612 return NULL; |
|
613 case DataLayout::bit_data_tag: |
|
614 return new BitData(data_layout); |
|
615 case DataLayout::counter_data_tag: |
|
616 return new CounterData(data_layout); |
|
617 case DataLayout::jump_data_tag: |
|
618 return new JumpData(data_layout); |
|
619 case DataLayout::receiver_type_data_tag: |
|
620 return new ReceiverTypeData(data_layout); |
|
621 case DataLayout::virtual_call_data_tag: |
|
622 return new VirtualCallData(data_layout); |
|
623 case DataLayout::ret_data_tag: |
|
624 return new RetData(data_layout); |
|
625 case DataLayout::branch_data_tag: |
|
626 return new BranchData(data_layout); |
|
627 case DataLayout::multi_branch_data_tag: |
|
628 return new MultiBranchData(data_layout); |
|
629 }; |
|
630 } |
|
631 |
|
632 // Iteration over data. |
|
633 ProfileData* methodDataOopDesc::next_data(ProfileData* current) { |
|
634 int current_index = dp_to_di(current->dp()); |
|
635 int next_index = current_index + current->size_in_bytes(); |
|
636 ProfileData* next = data_at(next_index); |
|
637 return next; |
|
638 } |
|
639 |
|
640 // Give each of the data entries a chance to perform specific |
|
641 // data initialization. |
|
642 void methodDataOopDesc::post_initialize(BytecodeStream* stream) { |
|
643 ResourceMark rm; |
|
644 ProfileData* data; |
|
645 for (data = first_data(); is_valid(data); data = next_data(data)) { |
|
646 stream->set_start(data->bci()); |
|
647 stream->next(); |
|
648 data->post_initialize(stream, this); |
|
649 } |
|
650 } |
|
651 |
|
652 // Initialize the methodDataOop corresponding to a given method. |
|
653 void methodDataOopDesc::initialize(methodHandle method) { |
|
654 ResourceMark rm; |
|
655 |
|
656 // Set the method back-pointer. |
|
657 _method = method(); |
|
658 set_creation_mileage(mileage_of(method())); |
|
659 |
|
660 // Initialize flags and trap history. |
|
661 _nof_decompiles = 0; |
|
662 _nof_overflow_recompiles = 0; |
|
663 _nof_overflow_traps = 0; |
|
664 assert(sizeof(_trap_hist) % sizeof(HeapWord) == 0, "align"); |
|
665 Copy::zero_to_words((HeapWord*) &_trap_hist, |
|
666 sizeof(_trap_hist) / sizeof(HeapWord)); |
|
667 |
|
668 // Go through the bytecodes and allocate and initialize the |
|
669 // corresponding data cells. |
|
670 int data_size = 0; |
|
671 int empty_bc_count = 0; // number of bytecodes lacking data |
|
672 BytecodeStream stream(method); |
|
673 Bytecodes::Code c; |
|
674 while ((c = stream.next()) >= 0) { |
|
675 int size_in_bytes = initialize_data(&stream, data_size); |
|
676 data_size += size_in_bytes; |
|
677 if (size_in_bytes == 0) empty_bc_count += 1; |
|
678 } |
|
679 _data_size = data_size; |
|
680 int object_size = in_bytes(data_offset()) + data_size; |
|
681 |
|
682 // Add some extra DataLayout cells (at least one) to track stray traps. |
|
683 int extra_data_count = compute_extra_data_count(data_size, empty_bc_count); |
|
684 object_size += extra_data_count * DataLayout::compute_size_in_bytes(0); |
|
685 |
|
686 // Set an initial hint. Don't use set_hint_di() because |
|
687 // first_di() may be out of bounds if data_size is 0. |
|
688 // In that situation, _hint_di is never used, but at |
|
689 // least well-defined. |
|
690 _hint_di = first_di(); |
|
691 |
|
692 post_initialize(&stream); |
|
693 |
|
694 set_object_is_parsable(object_size); |
|
695 } |
|
696 |
|
697 // Get a measure of how much mileage the method has on it. |
|
698 int methodDataOopDesc::mileage_of(methodOop method) { |
|
699 int mileage = 0; |
|
700 int iic = method->interpreter_invocation_count(); |
|
701 if (mileage < iic) mileage = iic; |
|
702 |
|
703 InvocationCounter* ic = method->invocation_counter(); |
|
704 InvocationCounter* bc = method->backedge_counter(); |
|
705 |
|
706 int icval = ic->count(); |
|
707 if (ic->carry()) icval += CompileThreshold; |
|
708 if (mileage < icval) mileage = icval; |
|
709 int bcval = bc->count(); |
|
710 if (bc->carry()) bcval += CompileThreshold; |
|
711 if (mileage < bcval) mileage = bcval; |
|
712 return mileage; |
|
713 } |
|
714 |
|
715 bool methodDataOopDesc::is_mature() const { |
|
716 uint current = mileage_of(_method); |
|
717 uint initial = creation_mileage(); |
|
718 if (current < initial) |
|
719 return true; // some sort of overflow |
|
720 uint target; |
|
721 if (ProfileMaturityPercentage <= 0) |
|
722 target = (uint) -ProfileMaturityPercentage; // absolute value |
|
723 else |
|
724 target = (uint)( (ProfileMaturityPercentage * CompileThreshold) / 100 ); |
|
725 return (current >= initial + target); |
|
726 } |
|
727 |
|
728 // Translate a bci to its corresponding data index (di). |
|
729 address methodDataOopDesc::bci_to_dp(int bci) { |
|
730 ResourceMark rm; |
|
731 ProfileData* data = data_before(bci); |
|
732 ProfileData* prev = NULL; |
|
733 for ( ; is_valid(data); data = next_data(data)) { |
|
734 if (data->bci() >= bci) { |
|
735 if (data->bci() == bci) set_hint_di(dp_to_di(data->dp())); |
|
736 else if (prev != NULL) set_hint_di(dp_to_di(prev->dp())); |
|
737 return data->dp(); |
|
738 } |
|
739 prev = data; |
|
740 } |
|
741 return (address)limit_data_position(); |
|
742 } |
|
743 |
|
744 // Translate a bci to its corresponding data, or NULL. |
|
745 ProfileData* methodDataOopDesc::bci_to_data(int bci) { |
|
746 ProfileData* data = data_before(bci); |
|
747 for ( ; is_valid(data); data = next_data(data)) { |
|
748 if (data->bci() == bci) { |
|
749 set_hint_di(dp_to_di(data->dp())); |
|
750 return data; |
|
751 } else if (data->bci() > bci) { |
|
752 break; |
|
753 } |
|
754 } |
|
755 return bci_to_extra_data(bci, false); |
|
756 } |
|
757 |
|
758 // Translate a bci to its corresponding extra data, or NULL. |
|
759 ProfileData* methodDataOopDesc::bci_to_extra_data(int bci, bool create_if_missing) { |
|
760 DataLayout* dp = extra_data_base(); |
|
761 DataLayout* end = extra_data_limit(); |
|
762 DataLayout* avail = NULL; |
|
763 for (; dp < end; dp = next_extra(dp)) { |
|
764 // No need for "OrderAccess::load_acquire" ops, |
|
765 // since the data structure is monotonic. |
|
766 if (dp->tag() == DataLayout::no_tag) break; |
|
767 if (dp->bci() == bci) { |
|
768 assert(dp->tag() == DataLayout::bit_data_tag, "sane"); |
|
769 return new BitData(dp); |
|
770 } |
|
771 } |
|
772 if (create_if_missing && dp < end) { |
|
773 // Allocate this one. There is no mutual exclusion, |
|
774 // so two threads could allocate different BCIs to the |
|
775 // same data layout. This means these extra data |
|
776 // records, like most other MDO contents, must not be |
|
777 // trusted too much. |
|
778 DataLayout temp; |
|
779 temp.initialize(DataLayout::bit_data_tag, bci, 0); |
|
780 dp->release_set_header(temp.header()); |
|
781 assert(dp->tag() == DataLayout::bit_data_tag, "sane"); |
|
782 //NO: assert(dp->bci() == bci, "no concurrent allocation"); |
|
783 return new BitData(dp); |
|
784 } |
|
785 return NULL; |
|
786 } |
|
787 |
|
788 #ifndef PRODUCT |
|
789 void methodDataOopDesc::print_data_on(outputStream* st) { |
|
790 ResourceMark rm; |
|
791 ProfileData* data = first_data(); |
|
792 for ( ; is_valid(data); data = next_data(data)) { |
|
793 st->print("%d", dp_to_di(data->dp())); |
|
794 st->fill_to(6); |
|
795 data->print_data_on(st); |
|
796 } |
|
797 DataLayout* dp = extra_data_base(); |
|
798 DataLayout* end = extra_data_limit(); |
|
799 for (; dp < end; dp = next_extra(dp)) { |
|
800 // No need for "OrderAccess::load_acquire" ops, |
|
801 // since the data structure is monotonic. |
|
802 if (dp->tag() == DataLayout::no_tag) break; |
|
803 if (dp == extra_data_base()) |
|
804 st->print_cr("--- Extra data:"); |
|
805 data = new BitData(dp); |
|
806 st->print("%d", dp_to_di(data->dp())); |
|
807 st->fill_to(6); |
|
808 data->print_data_on(st); |
|
809 } |
|
810 } |
|
811 #endif |
|
812 |
|
813 void methodDataOopDesc::verify_data_on(outputStream* st) { |
|
814 NEEDS_CLEANUP; |
|
815 // not yet implemented. |
|
816 } |