Mercurial > hg > graal-jvmci-8
annotate src/share/vm/oops/methodDataOop.hpp @ 1091:6aa7255741f3
6906727: UseCompressedOops: some card-marking fixes related to object arrays
Summary: Introduced a new write_ref_array(HeapWords* start, size_t count) method that does the requisite MemRegion range calculation so (some of the) clients of the erstwhile write_ref_array(MemRegion mr) do not need to worry. This removed all external uses of array_size(), which was also simplified and made private. Asserts were added to catch other possible issues. Further, less essential, fixes stemming from this investigation are deferred to CR 6904516 (to follow shortly in hs17).
Reviewed-by: kvn, coleenp, jmasa
author | ysr |
---|---|
date | Thu, 03 Dec 2009 15:01:57 -0800 |
parents | 89e0543e1737 |
children | 87684f1a88b5 |
rev | line source |
---|---|
0 | 1 /* |
948 | 2 * Copyright 2000-2009 Sun Microsystems, Inc. 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 * | |
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 class BytecodeStream; | |
26 | |
27 // The MethodData object collects counts and other profile information | |
28 // during zeroth-tier (interpretive) and first-tier execution. | |
29 // The profile is used later by compilation heuristics. Some heuristics | |
30 // enable use of aggressive (or "heroic") optimizations. An aggressive | |
31 // optimization often has a down-side, a corner case that it handles | |
32 // poorly, but which is thought to be rare. The profile provides | |
33 // evidence of this rarity for a given method or even BCI. It allows | |
34 // the compiler to back out of the optimization at places where it | |
35 // has historically been a poor choice. Other heuristics try to use | |
36 // specific information gathered about types observed at a given site. | |
37 // | |
38 // All data in the profile is approximate. It is expected to be accurate | |
39 // on the whole, but the system expects occasional inaccuraces, due to | |
40 // counter overflow, multiprocessor races during data collection, space | |
41 // limitations, missing MDO blocks, etc. Bad or missing data will degrade | |
42 // optimization quality but will not affect correctness. Also, each MDO | |
43 // is marked with its birth-date ("creation_mileage") which can be used | |
44 // to assess the quality ("maturity") of its data. | |
45 // | |
46 // Short (<32-bit) counters are designed to overflow to a known "saturated" | |
47 // state. Also, certain recorded per-BCI events are given one-bit counters | |
48 // which overflow to a saturated state which applied to all counters at | |
49 // that BCI. In other words, there is a small lattice which approximates | |
50 // the ideal of an infinite-precision counter for each event at each BCI, | |
51 // and the lattice quickly "bottoms out" in a state where all counters | |
52 // are taken to be indefinitely large. | |
53 // | |
54 // The reader will find many data races in profile gathering code, starting | |
55 // with invocation counter incrementation. None of these races harm correct | |
56 // execution of the compiled code. | |
57 | |
941 | 58 // forward decl |
59 class ProfileData; | |
60 | |
0 | 61 // DataLayout |
62 // | |
63 // Overlay for generic profiling data. | |
64 class DataLayout VALUE_OBJ_CLASS_SPEC { | |
65 private: | |
66 // Every data layout begins with a header. This header | |
67 // contains a tag, which is used to indicate the size/layout | |
68 // of the data, 4 bits of flags, which can be used in any way, | |
69 // 4 bits of trap history (none/one reason/many reasons), | |
70 // and a bci, which is used to tie this piece of data to a | |
71 // specific bci in the bytecodes. | |
72 union { | |
73 intptr_t _bits; | |
74 struct { | |
75 u1 _tag; | |
76 u1 _flags; | |
77 u2 _bci; | |
78 } _struct; | |
79 } _header; | |
80 | |
81 // The data layout has an arbitrary number of cells, each sized | |
82 // to accomodate a pointer or an integer. | |
83 intptr_t _cells[1]; | |
84 | |
85 // Some types of data layouts need a length field. | |
86 static bool needs_array_len(u1 tag); | |
87 | |
88 public: | |
89 enum { | |
90 counter_increment = 1 | |
91 }; | |
92 | |
93 enum { | |
94 cell_size = sizeof(intptr_t) | |
95 }; | |
96 | |
97 // Tag values | |
98 enum { | |
99 no_tag, | |
100 bit_data_tag, | |
101 counter_data_tag, | |
102 jump_data_tag, | |
103 receiver_type_data_tag, | |
104 virtual_call_data_tag, | |
105 ret_data_tag, | |
106 branch_data_tag, | |
45
48a3fa21394b
6667615: (Escape Analysis) extend MDO to cache arguments escape state
kvn
parents:
0
diff
changeset
|
107 multi_branch_data_tag, |
48a3fa21394b
6667615: (Escape Analysis) extend MDO to cache arguments escape state
kvn
parents:
0
diff
changeset
|
108 arg_info_data_tag |
0 | 109 }; |
110 | |
111 enum { | |
112 // The _struct._flags word is formatted as [trap_state:4 | flags:4]. | |
113 // The trap state breaks down further as [recompile:1 | reason:3]. | |
114 // This further breakdown is defined in deoptimization.cpp. | |
115 // See Deoptimization::trap_state_reason for an assert that | |
116 // trap_bits is big enough to hold reasons < Reason_RECORDED_LIMIT. | |
117 // | |
118 // The trap_state is collected only if ProfileTraps is true. | |
119 trap_bits = 1+3, // 3: enough to distinguish [0..Reason_RECORDED_LIMIT]. | |
120 trap_shift = BitsPerByte - trap_bits, | |
121 trap_mask = right_n_bits(trap_bits), | |
122 trap_mask_in_place = (trap_mask << trap_shift), | |
123 flag_limit = trap_shift, | |
124 flag_mask = right_n_bits(flag_limit), | |
125 first_flag = 0 | |
126 }; | |
127 | |
128 // Size computation | |
129 static int header_size_in_bytes() { | |
130 return cell_size; | |
131 } | |
132 static int header_size_in_cells() { | |
133 return 1; | |
134 } | |
135 | |
136 static int compute_size_in_bytes(int cell_count) { | |
137 return header_size_in_bytes() + cell_count * cell_size; | |
138 } | |
139 | |
140 // Initialization | |
141 void initialize(u1 tag, u2 bci, int cell_count); | |
142 | |
143 // Accessors | |
144 u1 tag() { | |
145 return _header._struct._tag; | |
146 } | |
147 | |
148 // Return a few bits of trap state. Range is [0..trap_mask]. | |
149 // The state tells if traps with zero, one, or many reasons have occurred. | |
150 // It also tells whether zero or many recompilations have occurred. | |
151 // The associated trap histogram in the MDO itself tells whether | |
152 // traps are common or not. If a BCI shows that a trap X has | |
153 // occurred, and the MDO shows N occurrences of X, we make the | |
154 // simplifying assumption that all N occurrences can be blamed | |
155 // on that BCI. | |
156 int trap_state() { | |
157 return ((_header._struct._flags >> trap_shift) & trap_mask); | |
158 } | |
159 | |
160 void set_trap_state(int new_state) { | |
161 assert(ProfileTraps, "used only under +ProfileTraps"); | |
162 uint old_flags = (_header._struct._flags & flag_mask); | |
163 _header._struct._flags = (new_state << trap_shift) | old_flags; | |
164 } | |
165 | |
166 u1 flags() { | |
167 return _header._struct._flags; | |
168 } | |
169 | |
170 u2 bci() { | |
171 return _header._struct._bci; | |
172 } | |
173 | |
174 void set_header(intptr_t value) { | |
175 _header._bits = value; | |
176 } | |
177 void release_set_header(intptr_t value) { | |
178 OrderAccess::release_store_ptr(&_header._bits, value); | |
179 } | |
180 intptr_t header() { | |
181 return _header._bits; | |
182 } | |
183 void set_cell_at(int index, intptr_t value) { | |
184 _cells[index] = value; | |
185 } | |
186 void release_set_cell_at(int index, intptr_t value) { | |
187 OrderAccess::release_store_ptr(&_cells[index], value); | |
188 } | |
189 intptr_t cell_at(int index) { | |
190 return _cells[index]; | |
191 } | |
192 intptr_t* adr_cell_at(int index) { | |
193 return &_cells[index]; | |
194 } | |
195 oop* adr_oop_at(int index) { | |
196 return (oop*)&(_cells[index]); | |
197 } | |
198 | |
199 void set_flag_at(int flag_number) { | |
200 assert(flag_number < flag_limit, "oob"); | |
201 _header._struct._flags |= (0x1 << flag_number); | |
202 } | |
203 bool flag_at(int flag_number) { | |
204 assert(flag_number < flag_limit, "oob"); | |
205 return (_header._struct._flags & (0x1 << flag_number)) != 0; | |
206 } | |
207 | |
208 // Low-level support for code generation. | |
209 static ByteSize header_offset() { | |
210 return byte_offset_of(DataLayout, _header); | |
211 } | |
212 static ByteSize tag_offset() { | |
213 return byte_offset_of(DataLayout, _header._struct._tag); | |
214 } | |
215 static ByteSize flags_offset() { | |
216 return byte_offset_of(DataLayout, _header._struct._flags); | |
217 } | |
218 static ByteSize bci_offset() { | |
219 return byte_offset_of(DataLayout, _header._struct._bci); | |
220 } | |
221 static ByteSize cell_offset(int index) { | |
222 return byte_offset_of(DataLayout, _cells[index]); | |
223 } | |
224 // Return a value which, when or-ed as a byte into _flags, sets the flag. | |
225 static int flag_number_to_byte_constant(int flag_number) { | |
226 assert(0 <= flag_number && flag_number < flag_limit, "oob"); | |
227 DataLayout temp; temp.set_header(0); | |
228 temp.set_flag_at(flag_number); | |
229 return temp._header._struct._flags; | |
230 } | |
231 // Return a value which, when or-ed as a word into _header, sets the flag. | |
232 static intptr_t flag_mask_to_header_mask(int byte_constant) { | |
233 DataLayout temp; temp.set_header(0); | |
234 temp._header._struct._flags = byte_constant; | |
235 return temp._header._bits; | |
236 } | |
941 | 237 |
238 // GC support | |
239 ProfileData* data_in(); | |
240 void follow_weak_refs(BoolObjectClosure* cl); | |
0 | 241 }; |
242 | |
243 | |
244 // ProfileData class hierarchy | |
245 class ProfileData; | |
246 class BitData; | |
247 class CounterData; | |
248 class ReceiverTypeData; | |
249 class VirtualCallData; | |
250 class RetData; | |
251 class JumpData; | |
252 class BranchData; | |
253 class ArrayData; | |
254 class MultiBranchData; | |
45
48a3fa21394b
6667615: (Escape Analysis) extend MDO to cache arguments escape state
kvn
parents:
0
diff
changeset
|
255 class ArgInfoData; |
0 | 256 |
257 | |
258 // ProfileData | |
259 // | |
260 // A ProfileData object is created to refer to a section of profiling | |
261 // data in a structured way. | |
262 class ProfileData : public ResourceObj { | |
263 private: | |
264 #ifndef PRODUCT | |
265 enum { | |
266 tab_width_one = 16, | |
267 tab_width_two = 36 | |
268 }; | |
269 #endif // !PRODUCT | |
270 | |
271 // This is a pointer to a section of profiling data. | |
272 DataLayout* _data; | |
273 | |
274 protected: | |
275 DataLayout* data() { return _data; } | |
276 | |
277 enum { | |
278 cell_size = DataLayout::cell_size | |
279 }; | |
280 | |
281 public: | |
282 // How many cells are in this? | |
283 virtual int cell_count() { | |
284 ShouldNotReachHere(); | |
285 return -1; | |
286 } | |
287 | |
288 // Return the size of this data. | |
289 int size_in_bytes() { | |
290 return DataLayout::compute_size_in_bytes(cell_count()); | |
291 } | |
292 | |
293 protected: | |
294 // Low-level accessors for underlying data | |
295 void set_intptr_at(int index, intptr_t value) { | |
296 assert(0 <= index && index < cell_count(), "oob"); | |
297 data()->set_cell_at(index, value); | |
298 } | |
299 void release_set_intptr_at(int index, intptr_t value) { | |
300 assert(0 <= index && index < cell_count(), "oob"); | |
301 data()->release_set_cell_at(index, value); | |
302 } | |
303 intptr_t intptr_at(int index) { | |
304 assert(0 <= index && index < cell_count(), "oob"); | |
305 return data()->cell_at(index); | |
306 } | |
307 void set_uint_at(int index, uint value) { | |
308 set_intptr_at(index, (intptr_t) value); | |
309 } | |
310 void release_set_uint_at(int index, uint value) { | |
311 release_set_intptr_at(index, (intptr_t) value); | |
312 } | |
313 uint uint_at(int index) { | |
314 return (uint)intptr_at(index); | |
315 } | |
316 void set_int_at(int index, int value) { | |
317 set_intptr_at(index, (intptr_t) value); | |
318 } | |
319 void release_set_int_at(int index, int value) { | |
320 release_set_intptr_at(index, (intptr_t) value); | |
321 } | |
322 int int_at(int index) { | |
323 return (int)intptr_at(index); | |
324 } | |
325 int int_at_unchecked(int index) { | |
326 return (int)data()->cell_at(index); | |
327 } | |
328 void set_oop_at(int index, oop value) { | |
329 set_intptr_at(index, (intptr_t) value); | |
330 } | |
331 oop oop_at(int index) { | |
332 return (oop)intptr_at(index); | |
333 } | |
334 oop* adr_oop_at(int index) { | |
335 assert(0 <= index && index < cell_count(), "oob"); | |
336 return data()->adr_oop_at(index); | |
337 } | |
338 | |
339 void set_flag_at(int flag_number) { | |
340 data()->set_flag_at(flag_number); | |
341 } | |
342 bool flag_at(int flag_number) { | |
343 return data()->flag_at(flag_number); | |
344 } | |
345 | |
346 // two convenient imports for use by subclasses: | |
347 static ByteSize cell_offset(int index) { | |
348 return DataLayout::cell_offset(index); | |
349 } | |
350 static int flag_number_to_byte_constant(int flag_number) { | |
351 return DataLayout::flag_number_to_byte_constant(flag_number); | |
352 } | |
353 | |
354 ProfileData(DataLayout* data) { | |
355 _data = data; | |
356 } | |
357 | |
358 public: | |
359 // Constructor for invalid ProfileData. | |
360 ProfileData(); | |
361 | |
362 u2 bci() { | |
363 return data()->bci(); | |
364 } | |
365 | |
366 address dp() { | |
367 return (address)_data; | |
368 } | |
369 | |
370 int trap_state() { | |
371 return data()->trap_state(); | |
372 } | |
373 void set_trap_state(int new_state) { | |
374 data()->set_trap_state(new_state); | |
375 } | |
376 | |
377 // Type checking | |
378 virtual bool is_BitData() { return false; } | |
379 virtual bool is_CounterData() { return false; } | |
380 virtual bool is_JumpData() { return false; } | |
381 virtual bool is_ReceiverTypeData(){ return false; } | |
382 virtual bool is_VirtualCallData() { return false; } | |
383 virtual bool is_RetData() { return false; } | |
384 virtual bool is_BranchData() { return false; } | |
385 virtual bool is_ArrayData() { return false; } | |
386 virtual bool is_MultiBranchData() { return false; } | |
45
48a3fa21394b
6667615: (Escape Analysis) extend MDO to cache arguments escape state
kvn
parents:
0
diff
changeset
|
387 virtual bool is_ArgInfoData() { return false; } |
48a3fa21394b
6667615: (Escape Analysis) extend MDO to cache arguments escape state
kvn
parents:
0
diff
changeset
|
388 |
0 | 389 |
390 BitData* as_BitData() { | |
391 assert(is_BitData(), "wrong type"); | |
392 return is_BitData() ? (BitData*) this : NULL; | |
393 } | |
394 CounterData* as_CounterData() { | |
395 assert(is_CounterData(), "wrong type"); | |
396 return is_CounterData() ? (CounterData*) this : NULL; | |
397 } | |
398 JumpData* as_JumpData() { | |
399 assert(is_JumpData(), "wrong type"); | |
400 return is_JumpData() ? (JumpData*) this : NULL; | |
401 } | |
402 ReceiverTypeData* as_ReceiverTypeData() { | |
403 assert(is_ReceiverTypeData(), "wrong type"); | |
404 return is_ReceiverTypeData() ? (ReceiverTypeData*)this : NULL; | |
405 } | |
406 VirtualCallData* as_VirtualCallData() { | |
407 assert(is_VirtualCallData(), "wrong type"); | |
408 return is_VirtualCallData() ? (VirtualCallData*)this : NULL; | |
409 } | |
410 RetData* as_RetData() { | |
411 assert(is_RetData(), "wrong type"); | |
412 return is_RetData() ? (RetData*) this : NULL; | |
413 } | |
414 BranchData* as_BranchData() { | |
415 assert(is_BranchData(), "wrong type"); | |
416 return is_BranchData() ? (BranchData*) this : NULL; | |
417 } | |
418 ArrayData* as_ArrayData() { | |
419 assert(is_ArrayData(), "wrong type"); | |
420 return is_ArrayData() ? (ArrayData*) this : NULL; | |
421 } | |
422 MultiBranchData* as_MultiBranchData() { | |
423 assert(is_MultiBranchData(), "wrong type"); | |
424 return is_MultiBranchData() ? (MultiBranchData*)this : NULL; | |
425 } | |
45
48a3fa21394b
6667615: (Escape Analysis) extend MDO to cache arguments escape state
kvn
parents:
0
diff
changeset
|
426 ArgInfoData* as_ArgInfoData() { |
48a3fa21394b
6667615: (Escape Analysis) extend MDO to cache arguments escape state
kvn
parents:
0
diff
changeset
|
427 assert(is_ArgInfoData(), "wrong type"); |
48a3fa21394b
6667615: (Escape Analysis) extend MDO to cache arguments escape state
kvn
parents:
0
diff
changeset
|
428 return is_ArgInfoData() ? (ArgInfoData*)this : NULL; |
48a3fa21394b
6667615: (Escape Analysis) extend MDO to cache arguments escape state
kvn
parents:
0
diff
changeset
|
429 } |
0 | 430 |
431 | |
432 // Subclass specific initialization | |
433 virtual void post_initialize(BytecodeStream* stream, methodDataOop mdo) {} | |
434 | |
435 // GC support | |
436 virtual void follow_contents() {} | |
437 virtual void oop_iterate(OopClosure* blk) {} | |
438 virtual void oop_iterate_m(OopClosure* blk, MemRegion mr) {} | |
439 virtual void adjust_pointers() {} | |
941 | 440 virtual void follow_weak_refs(BoolObjectClosure* is_alive_closure) {} |
0 | 441 |
442 #ifndef SERIALGC | |
443 // Parallel old support | |
444 virtual void follow_contents(ParCompactionManager* cm) {} | |
445 virtual void update_pointers() {} | |
446 virtual void update_pointers(HeapWord* beg_addr, HeapWord* end_addr) {} | |
447 #endif // SERIALGC | |
448 | |
449 // CI translation: ProfileData can represent both MethodDataOop data | |
450 // as well as CIMethodData data. This function is provided for translating | |
451 // an oop in a ProfileData to the ci equivalent. Generally speaking, | |
452 // most ProfileData don't require any translation, so we provide the null | |
453 // translation here, and the required translators are in the ci subclasses. | |
454 virtual void translate_from(ProfileData* data) {} | |
455 | |
456 virtual void print_data_on(outputStream* st) { | |
457 ShouldNotReachHere(); | |
458 } | |
459 | |
460 #ifndef PRODUCT | |
461 void print_shared(outputStream* st, const char* name); | |
462 void tab(outputStream* st); | |
463 #endif | |
464 }; | |
465 | |
466 // BitData | |
467 // | |
468 // A BitData holds a flag or two in its header. | |
469 class BitData : public ProfileData { | |
470 protected: | |
471 enum { | |
472 // null_seen: | |
473 // saw a null operand (cast/aastore/instanceof) | |
474 null_seen_flag = DataLayout::first_flag + 0 | |
475 }; | |
476 enum { bit_cell_count = 0 }; // no additional data fields needed. | |
477 public: | |
478 BitData(DataLayout* layout) : ProfileData(layout) { | |
479 } | |
480 | |
481 virtual bool is_BitData() { return true; } | |
482 | |
483 static int static_cell_count() { | |
484 return bit_cell_count; | |
485 } | |
486 | |
487 virtual int cell_count() { | |
488 return static_cell_count(); | |
489 } | |
490 | |
491 // Accessor | |
492 | |
493 // The null_seen flag bit is specially known to the interpreter. | |
494 // Consulting it allows the compiler to avoid setting up null_check traps. | |
495 bool null_seen() { return flag_at(null_seen_flag); } | |
496 void set_null_seen() { set_flag_at(null_seen_flag); } | |
497 | |
498 | |
499 // Code generation support | |
500 static int null_seen_byte_constant() { | |
501 return flag_number_to_byte_constant(null_seen_flag); | |
502 } | |
503 | |
504 static ByteSize bit_data_size() { | |
505 return cell_offset(bit_cell_count); | |
506 } | |
507 | |
508 #ifndef PRODUCT | |
509 void print_data_on(outputStream* st); | |
510 #endif | |
511 }; | |
512 | |
513 // CounterData | |
514 // | |
515 // A CounterData corresponds to a simple counter. | |
516 class CounterData : public BitData { | |
517 protected: | |
518 enum { | |
519 count_off, | |
520 counter_cell_count | |
521 }; | |
522 public: | |
523 CounterData(DataLayout* layout) : BitData(layout) {} | |
524 | |
525 virtual bool is_CounterData() { return true; } | |
526 | |
527 static int static_cell_count() { | |
528 return counter_cell_count; | |
529 } | |
530 | |
531 virtual int cell_count() { | |
532 return static_cell_count(); | |
533 } | |
534 | |
535 // Direct accessor | |
536 uint count() { | |
537 return uint_at(count_off); | |
538 } | |
539 | |
540 // Code generation support | |
541 static ByteSize count_offset() { | |
542 return cell_offset(count_off); | |
543 } | |
544 static ByteSize counter_data_size() { | |
545 return cell_offset(counter_cell_count); | |
546 } | |
547 | |
548 #ifndef PRODUCT | |
549 void print_data_on(outputStream* st); | |
550 #endif | |
551 }; | |
552 | |
553 // JumpData | |
554 // | |
555 // A JumpData is used to access profiling information for a direct | |
556 // branch. It is a counter, used for counting the number of branches, | |
557 // plus a data displacement, used for realigning the data pointer to | |
558 // the corresponding target bci. | |
559 class JumpData : public ProfileData { | |
560 protected: | |
561 enum { | |
562 taken_off_set, | |
563 displacement_off_set, | |
564 jump_cell_count | |
565 }; | |
566 | |
567 void set_displacement(int displacement) { | |
568 set_int_at(displacement_off_set, displacement); | |
569 } | |
570 | |
571 public: | |
572 JumpData(DataLayout* layout) : ProfileData(layout) { | |
573 assert(layout->tag() == DataLayout::jump_data_tag || | |
574 layout->tag() == DataLayout::branch_data_tag, "wrong type"); | |
575 } | |
576 | |
577 virtual bool is_JumpData() { return true; } | |
578 | |
579 static int static_cell_count() { | |
580 return jump_cell_count; | |
581 } | |
582 | |
583 virtual int cell_count() { | |
584 return static_cell_count(); | |
585 } | |
586 | |
587 // Direct accessor | |
588 uint taken() { | |
589 return uint_at(taken_off_set); | |
590 } | |
591 // Saturating counter | |
592 uint inc_taken() { | |
593 uint cnt = taken() + 1; | |
594 // Did we wrap? Will compiler screw us?? | |
595 if (cnt == 0) cnt--; | |
596 set_uint_at(taken_off_set, cnt); | |
597 return cnt; | |
598 } | |
599 | |
600 int displacement() { | |
601 return int_at(displacement_off_set); | |
602 } | |
603 | |
604 // Code generation support | |
605 static ByteSize taken_offset() { | |
606 return cell_offset(taken_off_set); | |
607 } | |
608 | |
609 static ByteSize displacement_offset() { | |
610 return cell_offset(displacement_off_set); | |
611 } | |
612 | |
613 // Specific initialization. | |
614 void post_initialize(BytecodeStream* stream, methodDataOop mdo); | |
615 | |
616 #ifndef PRODUCT | |
617 void print_data_on(outputStream* st); | |
618 #endif | |
619 }; | |
620 | |
621 // ReceiverTypeData | |
622 // | |
623 // A ReceiverTypeData is used to access profiling information about a | |
624 // dynamic type check. It consists of a counter which counts the total times | |
625 // that the check is reached, and a series of (klassOop, count) pairs | |
626 // which are used to store a type profile for the receiver of the check. | |
627 class ReceiverTypeData : public CounterData { | |
628 protected: | |
629 enum { | |
630 receiver0_offset = counter_cell_count, | |
631 count0_offset, | |
632 receiver_type_row_cell_count = (count0_offset + 1) - receiver0_offset | |
633 }; | |
634 | |
635 public: | |
636 ReceiverTypeData(DataLayout* layout) : CounterData(layout) { | |
637 assert(layout->tag() == DataLayout::receiver_type_data_tag || | |
638 layout->tag() == DataLayout::virtual_call_data_tag, "wrong type"); | |
639 } | |
640 | |
641 virtual bool is_ReceiverTypeData() { return true; } | |
642 | |
643 static int static_cell_count() { | |
644 return counter_cell_count + (uint) TypeProfileWidth * receiver_type_row_cell_count; | |
645 } | |
646 | |
647 virtual int cell_count() { | |
648 return static_cell_count(); | |
649 } | |
650 | |
651 // Direct accessors | |
652 static uint row_limit() { | |
653 return TypeProfileWidth; | |
654 } | |
655 static int receiver_cell_index(uint row) { | |
656 return receiver0_offset + row * receiver_type_row_cell_count; | |
657 } | |
658 static int receiver_count_cell_index(uint row) { | |
659 return count0_offset + row * receiver_type_row_cell_count; | |
660 } | |
661 | |
662 // Get the receiver at row. The 'unchecked' version is needed by parallel old | |
663 // gc; it does not assert the receiver is a klass. During compaction of the | |
664 // perm gen, the klass may already have moved, so the is_klass() predicate | |
665 // would fail. The 'normal' version should be used whenever possible. | |
666 klassOop receiver_unchecked(uint row) { | |
667 assert(row < row_limit(), "oob"); | |
668 oop recv = oop_at(receiver_cell_index(row)); | |
669 return (klassOop)recv; | |
670 } | |
671 | |
672 klassOop receiver(uint row) { | |
673 klassOop recv = receiver_unchecked(row); | |
674 assert(recv == NULL || ((oop)recv)->is_klass(), "wrong type"); | |
675 return recv; | |
676 } | |
677 | |
941 | 678 void set_receiver(uint row, oop p) { |
679 assert((uint)row < row_limit(), "oob"); | |
680 set_oop_at(receiver_cell_index(row), p); | |
681 } | |
682 | |
0 | 683 uint receiver_count(uint row) { |
684 assert(row < row_limit(), "oob"); | |
685 return uint_at(receiver_count_cell_index(row)); | |
686 } | |
687 | |
941 | 688 void set_receiver_count(uint row, uint count) { |
689 assert(row < row_limit(), "oob"); | |
690 set_uint_at(receiver_count_cell_index(row), count); | |
691 } | |
692 | |
693 void clear_row(uint row) { | |
694 assert(row < row_limit(), "oob"); | |
695 set_receiver(row, NULL); | |
696 set_receiver_count(row, 0); | |
697 } | |
698 | |
0 | 699 // Code generation support |
700 static ByteSize receiver_offset(uint row) { | |
701 return cell_offset(receiver_cell_index(row)); | |
702 } | |
703 static ByteSize receiver_count_offset(uint row) { | |
704 return cell_offset(receiver_count_cell_index(row)); | |
705 } | |
706 static ByteSize receiver_type_data_size() { | |
707 return cell_offset(static_cell_count()); | |
708 } | |
709 | |
710 // GC support | |
711 virtual void follow_contents(); | |
712 virtual void oop_iterate(OopClosure* blk); | |
713 virtual void oop_iterate_m(OopClosure* blk, MemRegion mr); | |
714 virtual void adjust_pointers(); | |
941 | 715 virtual void follow_weak_refs(BoolObjectClosure* is_alive_closure); |
0 | 716 |
717 #ifndef SERIALGC | |
718 // Parallel old support | |
719 virtual void follow_contents(ParCompactionManager* cm); | |
720 virtual void update_pointers(); | |
721 virtual void update_pointers(HeapWord* beg_addr, HeapWord* end_addr); | |
722 #endif // SERIALGC | |
723 | |
724 oop* adr_receiver(uint row) { | |
725 return adr_oop_at(receiver_cell_index(row)); | |
726 } | |
727 | |
728 #ifndef PRODUCT | |
729 void print_receiver_data_on(outputStream* st); | |
730 void print_data_on(outputStream* st); | |
731 #endif | |
732 }; | |
733 | |
734 // VirtualCallData | |
735 // | |
736 // A VirtualCallData is used to access profiling information about a | |
737 // virtual call. For now, it has nothing more than a ReceiverTypeData. | |
738 class VirtualCallData : public ReceiverTypeData { | |
739 public: | |
740 VirtualCallData(DataLayout* layout) : ReceiverTypeData(layout) { | |
741 assert(layout->tag() == DataLayout::virtual_call_data_tag, "wrong type"); | |
742 } | |
743 | |
744 virtual bool is_VirtualCallData() { return true; } | |
745 | |
746 static int static_cell_count() { | |
747 // At this point we could add more profile state, e.g., for arguments. | |
748 // But for now it's the same size as the base record type. | |
749 return ReceiverTypeData::static_cell_count(); | |
750 } | |
751 | |
752 virtual int cell_count() { | |
753 return static_cell_count(); | |
754 } | |
755 | |
756 // Direct accessors | |
757 static ByteSize virtual_call_data_size() { | |
758 return cell_offset(static_cell_count()); | |
759 } | |
760 | |
761 #ifndef PRODUCT | |
762 void print_data_on(outputStream* st); | |
763 #endif | |
764 }; | |
765 | |
766 // RetData | |
767 // | |
768 // A RetData is used to access profiling information for a ret bytecode. | |
769 // It is composed of a count of the number of times that the ret has | |
770 // been executed, followed by a series of triples of the form | |
771 // (bci, count, di) which count the number of times that some bci was the | |
772 // target of the ret and cache a corresponding data displacement. | |
773 class RetData : public CounterData { | |
774 protected: | |
775 enum { | |
776 bci0_offset = counter_cell_count, | |
777 count0_offset, | |
778 displacement0_offset, | |
779 ret_row_cell_count = (displacement0_offset + 1) - bci0_offset | |
780 }; | |
781 | |
782 void set_bci(uint row, int bci) { | |
783 assert((uint)row < row_limit(), "oob"); | |
784 set_int_at(bci0_offset + row * ret_row_cell_count, bci); | |
785 } | |
786 void release_set_bci(uint row, int bci) { | |
787 assert((uint)row < row_limit(), "oob"); | |
788 // 'release' when setting the bci acts as a valid flag for other | |
789 // threads wrt bci_count and bci_displacement. | |
790 release_set_int_at(bci0_offset + row * ret_row_cell_count, bci); | |
791 } | |
792 void set_bci_count(uint row, uint count) { | |
793 assert((uint)row < row_limit(), "oob"); | |
794 set_uint_at(count0_offset + row * ret_row_cell_count, count); | |
795 } | |
796 void set_bci_displacement(uint row, int disp) { | |
797 set_int_at(displacement0_offset + row * ret_row_cell_count, disp); | |
798 } | |
799 | |
800 public: | |
801 RetData(DataLayout* layout) : CounterData(layout) { | |
802 assert(layout->tag() == DataLayout::ret_data_tag, "wrong type"); | |
803 } | |
804 | |
805 virtual bool is_RetData() { return true; } | |
806 | |
807 enum { | |
808 no_bci = -1 // value of bci when bci1/2 are not in use. | |
809 }; | |
810 | |
811 static int static_cell_count() { | |
812 return counter_cell_count + (uint) BciProfileWidth * ret_row_cell_count; | |
813 } | |
814 | |
815 virtual int cell_count() { | |
816 return static_cell_count(); | |
817 } | |
818 | |
819 static uint row_limit() { | |
820 return BciProfileWidth; | |
821 } | |
822 static int bci_cell_index(uint row) { | |
823 return bci0_offset + row * ret_row_cell_count; | |
824 } | |
825 static int bci_count_cell_index(uint row) { | |
826 return count0_offset + row * ret_row_cell_count; | |
827 } | |
828 static int bci_displacement_cell_index(uint row) { | |
829 return displacement0_offset + row * ret_row_cell_count; | |
830 } | |
831 | |
832 // Direct accessors | |
833 int bci(uint row) { | |
834 return int_at(bci_cell_index(row)); | |
835 } | |
836 uint bci_count(uint row) { | |
837 return uint_at(bci_count_cell_index(row)); | |
838 } | |
839 int bci_displacement(uint row) { | |
840 return int_at(bci_displacement_cell_index(row)); | |
841 } | |
842 | |
843 // Interpreter Runtime support | |
844 address fixup_ret(int return_bci, methodDataHandle mdo); | |
845 | |
846 // Code generation support | |
847 static ByteSize bci_offset(uint row) { | |
848 return cell_offset(bci_cell_index(row)); | |
849 } | |
850 static ByteSize bci_count_offset(uint row) { | |
851 return cell_offset(bci_count_cell_index(row)); | |
852 } | |
853 static ByteSize bci_displacement_offset(uint row) { | |
854 return cell_offset(bci_displacement_cell_index(row)); | |
855 } | |
856 | |
857 // Specific initialization. | |
858 void post_initialize(BytecodeStream* stream, methodDataOop mdo); | |
859 | |
860 #ifndef PRODUCT | |
861 void print_data_on(outputStream* st); | |
862 #endif | |
863 }; | |
864 | |
865 // BranchData | |
866 // | |
867 // A BranchData is used to access profiling data for a two-way branch. | |
868 // It consists of taken and not_taken counts as well as a data displacement | |
869 // for the taken case. | |
870 class BranchData : public JumpData { | |
871 protected: | |
872 enum { | |
873 not_taken_off_set = jump_cell_count, | |
874 branch_cell_count | |
875 }; | |
876 | |
877 void set_displacement(int displacement) { | |
878 set_int_at(displacement_off_set, displacement); | |
879 } | |
880 | |
881 public: | |
882 BranchData(DataLayout* layout) : JumpData(layout) { | |
883 assert(layout->tag() == DataLayout::branch_data_tag, "wrong type"); | |
884 } | |
885 | |
886 virtual bool is_BranchData() { return true; } | |
887 | |
888 static int static_cell_count() { | |
889 return branch_cell_count; | |
890 } | |
891 | |
892 virtual int cell_count() { | |
893 return static_cell_count(); | |
894 } | |
895 | |
896 // Direct accessor | |
897 uint not_taken() { | |
898 return uint_at(not_taken_off_set); | |
899 } | |
900 | |
901 uint inc_not_taken() { | |
902 uint cnt = not_taken() + 1; | |
903 // Did we wrap? Will compiler screw us?? | |
904 if (cnt == 0) cnt--; | |
905 set_uint_at(not_taken_off_set, cnt); | |
906 return cnt; | |
907 } | |
908 | |
909 // Code generation support | |
910 static ByteSize not_taken_offset() { | |
911 return cell_offset(not_taken_off_set); | |
912 } | |
913 static ByteSize branch_data_size() { | |
914 return cell_offset(branch_cell_count); | |
915 } | |
916 | |
917 // Specific initialization. | |
918 void post_initialize(BytecodeStream* stream, methodDataOop mdo); | |
919 | |
920 #ifndef PRODUCT | |
921 void print_data_on(outputStream* st); | |
922 #endif | |
923 }; | |
924 | |
925 // ArrayData | |
926 // | |
927 // A ArrayData is a base class for accessing profiling data which does | |
928 // not have a statically known size. It consists of an array length | |
929 // and an array start. | |
930 class ArrayData : public ProfileData { | |
931 protected: | |
932 friend class DataLayout; | |
933 | |
934 enum { | |
935 array_len_off_set, | |
936 array_start_off_set | |
937 }; | |
938 | |
939 uint array_uint_at(int index) { | |
940 int aindex = index + array_start_off_set; | |
941 return uint_at(aindex); | |
942 } | |
943 int array_int_at(int index) { | |
944 int aindex = index + array_start_off_set; | |
945 return int_at(aindex); | |
946 } | |
947 oop array_oop_at(int index) { | |
948 int aindex = index + array_start_off_set; | |
949 return oop_at(aindex); | |
950 } | |
951 void array_set_int_at(int index, int value) { | |
952 int aindex = index + array_start_off_set; | |
953 set_int_at(aindex, value); | |
954 } | |
955 | |
956 // Code generation support for subclasses. | |
957 static ByteSize array_element_offset(int index) { | |
958 return cell_offset(array_start_off_set + index); | |
959 } | |
960 | |
961 public: | |
962 ArrayData(DataLayout* layout) : ProfileData(layout) {} | |
963 | |
964 virtual bool is_ArrayData() { return true; } | |
965 | |
966 static int static_cell_count() { | |
967 return -1; | |
968 } | |
969 | |
970 int array_len() { | |
971 return int_at_unchecked(array_len_off_set); | |
972 } | |
973 | |
974 virtual int cell_count() { | |
975 return array_len() + 1; | |
976 } | |
977 | |
978 // Code generation support | |
979 static ByteSize array_len_offset() { | |
980 return cell_offset(array_len_off_set); | |
981 } | |
982 static ByteSize array_start_offset() { | |
983 return cell_offset(array_start_off_set); | |
984 } | |
985 }; | |
986 | |
987 // MultiBranchData | |
988 // | |
989 // A MultiBranchData is used to access profiling information for | |
990 // a multi-way branch (*switch bytecodes). It consists of a series | |
991 // of (count, displacement) pairs, which count the number of times each | |
992 // case was taken and specify the data displacment for each branch target. | |
993 class MultiBranchData : public ArrayData { | |
994 protected: | |
995 enum { | |
996 default_count_off_set, | |
997 default_disaplacement_off_set, | |
998 case_array_start | |
999 }; | |
1000 enum { | |
1001 relative_count_off_set, | |
1002 relative_displacement_off_set, | |
1003 per_case_cell_count | |
1004 }; | |
1005 | |
1006 void set_default_displacement(int displacement) { | |
1007 array_set_int_at(default_disaplacement_off_set, displacement); | |
1008 } | |
1009 void set_displacement_at(int index, int displacement) { | |
1010 array_set_int_at(case_array_start + | |
1011 index * per_case_cell_count + | |
1012 relative_displacement_off_set, | |
1013 displacement); | |
1014 } | |
1015 | |
1016 public: | |
1017 MultiBranchData(DataLayout* layout) : ArrayData(layout) { | |
1018 assert(layout->tag() == DataLayout::multi_branch_data_tag, "wrong type"); | |
1019 } | |
1020 | |
1021 virtual bool is_MultiBranchData() { return true; } | |
1022 | |
1023 static int compute_cell_count(BytecodeStream* stream); | |
1024 | |
1025 int number_of_cases() { | |
1026 int alen = array_len() - 2; // get rid of default case here. | |
1027 assert(alen % per_case_cell_count == 0, "must be even"); | |
1028 return (alen / per_case_cell_count); | |
1029 } | |
1030 | |
1031 uint default_count() { | |
1032 return array_uint_at(default_count_off_set); | |
1033 } | |
1034 int default_displacement() { | |
1035 return array_int_at(default_disaplacement_off_set); | |
1036 } | |
1037 | |
1038 uint count_at(int index) { | |
1039 return array_uint_at(case_array_start + | |
1040 index * per_case_cell_count + | |
1041 relative_count_off_set); | |
1042 } | |
1043 int displacement_at(int index) { | |
1044 return array_int_at(case_array_start + | |
1045 index * per_case_cell_count + | |
1046 relative_displacement_off_set); | |
1047 } | |
1048 | |
1049 // Code generation support | |
1050 static ByteSize default_count_offset() { | |
1051 return array_element_offset(default_count_off_set); | |
1052 } | |
1053 static ByteSize default_displacement_offset() { | |
1054 return array_element_offset(default_disaplacement_off_set); | |
1055 } | |
1056 static ByteSize case_count_offset(int index) { | |
1057 return case_array_offset() + | |
1058 (per_case_size() * index) + | |
1059 relative_count_offset(); | |
1060 } | |
1061 static ByteSize case_array_offset() { | |
1062 return array_element_offset(case_array_start); | |
1063 } | |
1064 static ByteSize per_case_size() { | |
1065 return in_ByteSize(per_case_cell_count) * cell_size; | |
1066 } | |
1067 static ByteSize relative_count_offset() { | |
1068 return in_ByteSize(relative_count_off_set) * cell_size; | |
1069 } | |
1070 static ByteSize relative_displacement_offset() { | |
1071 return in_ByteSize(relative_displacement_off_set) * cell_size; | |
1072 } | |
1073 | |
1074 // Specific initialization. | |
1075 void post_initialize(BytecodeStream* stream, methodDataOop mdo); | |
1076 | |
1077 #ifndef PRODUCT | |
1078 void print_data_on(outputStream* st); | |
1079 #endif | |
1080 }; | |
1081 | |
45
48a3fa21394b
6667615: (Escape Analysis) extend MDO to cache arguments escape state
kvn
parents:
0
diff
changeset
|
1082 class ArgInfoData : public ArrayData { |
48a3fa21394b
6667615: (Escape Analysis) extend MDO to cache arguments escape state
kvn
parents:
0
diff
changeset
|
1083 |
48a3fa21394b
6667615: (Escape Analysis) extend MDO to cache arguments escape state
kvn
parents:
0
diff
changeset
|
1084 public: |
48a3fa21394b
6667615: (Escape Analysis) extend MDO to cache arguments escape state
kvn
parents:
0
diff
changeset
|
1085 ArgInfoData(DataLayout* layout) : ArrayData(layout) { |
48a3fa21394b
6667615: (Escape Analysis) extend MDO to cache arguments escape state
kvn
parents:
0
diff
changeset
|
1086 assert(layout->tag() == DataLayout::arg_info_data_tag, "wrong type"); |
48a3fa21394b
6667615: (Escape Analysis) extend MDO to cache arguments escape state
kvn
parents:
0
diff
changeset
|
1087 } |
48a3fa21394b
6667615: (Escape Analysis) extend MDO to cache arguments escape state
kvn
parents:
0
diff
changeset
|
1088 |
48a3fa21394b
6667615: (Escape Analysis) extend MDO to cache arguments escape state
kvn
parents:
0
diff
changeset
|
1089 virtual bool is_ArgInfoData() { return true; } |
48a3fa21394b
6667615: (Escape Analysis) extend MDO to cache arguments escape state
kvn
parents:
0
diff
changeset
|
1090 |
48a3fa21394b
6667615: (Escape Analysis) extend MDO to cache arguments escape state
kvn
parents:
0
diff
changeset
|
1091 |
48a3fa21394b
6667615: (Escape Analysis) extend MDO to cache arguments escape state
kvn
parents:
0
diff
changeset
|
1092 int number_of_args() { |
48a3fa21394b
6667615: (Escape Analysis) extend MDO to cache arguments escape state
kvn
parents:
0
diff
changeset
|
1093 return array_len(); |
48a3fa21394b
6667615: (Escape Analysis) extend MDO to cache arguments escape state
kvn
parents:
0
diff
changeset
|
1094 } |
48a3fa21394b
6667615: (Escape Analysis) extend MDO to cache arguments escape state
kvn
parents:
0
diff
changeset
|
1095 |
48a3fa21394b
6667615: (Escape Analysis) extend MDO to cache arguments escape state
kvn
parents:
0
diff
changeset
|
1096 uint arg_modified(int arg) { |
48a3fa21394b
6667615: (Escape Analysis) extend MDO to cache arguments escape state
kvn
parents:
0
diff
changeset
|
1097 return array_uint_at(arg); |
48a3fa21394b
6667615: (Escape Analysis) extend MDO to cache arguments escape state
kvn
parents:
0
diff
changeset
|
1098 } |
48a3fa21394b
6667615: (Escape Analysis) extend MDO to cache arguments escape state
kvn
parents:
0
diff
changeset
|
1099 |
48a3fa21394b
6667615: (Escape Analysis) extend MDO to cache arguments escape state
kvn
parents:
0
diff
changeset
|
1100 void set_arg_modified(int arg, uint val) { |
48a3fa21394b
6667615: (Escape Analysis) extend MDO to cache arguments escape state
kvn
parents:
0
diff
changeset
|
1101 array_set_int_at(arg, val); |
48a3fa21394b
6667615: (Escape Analysis) extend MDO to cache arguments escape state
kvn
parents:
0
diff
changeset
|
1102 } |
48a3fa21394b
6667615: (Escape Analysis) extend MDO to cache arguments escape state
kvn
parents:
0
diff
changeset
|
1103 |
48a3fa21394b
6667615: (Escape Analysis) extend MDO to cache arguments escape state
kvn
parents:
0
diff
changeset
|
1104 #ifndef PRODUCT |
48a3fa21394b
6667615: (Escape Analysis) extend MDO to cache arguments escape state
kvn
parents:
0
diff
changeset
|
1105 void print_data_on(outputStream* st); |
48a3fa21394b
6667615: (Escape Analysis) extend MDO to cache arguments escape state
kvn
parents:
0
diff
changeset
|
1106 #endif |
48a3fa21394b
6667615: (Escape Analysis) extend MDO to cache arguments escape state
kvn
parents:
0
diff
changeset
|
1107 }; |
48a3fa21394b
6667615: (Escape Analysis) extend MDO to cache arguments escape state
kvn
parents:
0
diff
changeset
|
1108 |
0 | 1109 // methodDataOop |
1110 // | |
1111 // A methodDataOop holds information which has been collected about | |
1112 // a method. Its layout looks like this: | |
1113 // | |
1114 // ----------------------------- | |
1115 // | header | | |
1116 // | klass | | |
1117 // ----------------------------- | |
1118 // | method | | |
1119 // | size of the methodDataOop | | |
1120 // ----------------------------- | |
1121 // | Data entries... | | |
1122 // | (variable size) | | |
1123 // | | | |
1124 // . . | |
1125 // . . | |
1126 // . . | |
1127 // | | | |
1128 // ----------------------------- | |
1129 // | |
1130 // The data entry area is a heterogeneous array of DataLayouts. Each | |
1131 // DataLayout in the array corresponds to a specific bytecode in the | |
1132 // method. The entries in the array are sorted by the corresponding | |
1133 // bytecode. Access to the data is via resource-allocated ProfileData, | |
1134 // which point to the underlying blocks of DataLayout structures. | |
1135 // | |
1136 // During interpretation, if profiling in enabled, the interpreter | |
1137 // maintains a method data pointer (mdp), which points at the entry | |
1138 // in the array corresponding to the current bci. In the course of | |
1139 // intepretation, when a bytecode is encountered that has profile data | |
1140 // associated with it, the entry pointed to by mdp is updated, then the | |
1141 // mdp is adjusted to point to the next appropriate DataLayout. If mdp | |
1142 // is NULL to begin with, the interpreter assumes that the current method | |
1143 // is not (yet) being profiled. | |
1144 // | |
1145 // In methodDataOop parlance, "dp" is a "data pointer", the actual address | |
1146 // of a DataLayout element. A "di" is a "data index", the offset in bytes | |
1147 // from the base of the data entry array. A "displacement" is the byte offset | |
1148 // in certain ProfileData objects that indicate the amount the mdp must be | |
1149 // adjusted in the event of a change in control flow. | |
1150 // | |
1151 | |
1152 class methodDataOopDesc : public oopDesc { | |
1153 friend class VMStructs; | |
1154 private: | |
1155 friend class ProfileData; | |
1156 | |
1157 // Back pointer to the methodOop | |
1158 methodOop _method; | |
1159 | |
1160 // Size of this oop in bytes | |
1161 int _size; | |
1162 | |
1163 // Cached hint for bci_to_dp and bci_to_data | |
1164 int _hint_di; | |
1165 | |
1166 // Whole-method sticky bits and flags | |
1167 public: | |
1168 enum { | |
1169 _trap_hist_limit = 16, // decoupled from Deoptimization::Reason_LIMIT | |
1170 _trap_hist_mask = max_jubyte, | |
1171 _extra_data_count = 4 // extra DataLayout headers, for trap history | |
1172 }; // Public flag values | |
1173 private: | |
1174 uint _nof_decompiles; // count of all nmethod removals | |
1175 uint _nof_overflow_recompiles; // recompile count, excluding recomp. bits | |
1176 uint _nof_overflow_traps; // trap count, excluding _trap_hist | |
1177 union { | |
1178 intptr_t _align; | |
1179 u1 _array[_trap_hist_limit]; | |
1180 } _trap_hist; | |
1181 | |
1182 // Support for interprocedural escape analysis, from Thomas Kotzmann. | |
1183 intx _eflags; // flags on escape information | |
1184 intx _arg_local; // bit set of non-escaping arguments | |
1185 intx _arg_stack; // bit set of stack-allocatable arguments | |
1186 intx _arg_returned; // bit set of returned arguments | |
1187 | |
1188 int _creation_mileage; // method mileage at MDO creation | |
1189 | |
1190 // Size of _data array in bytes. (Excludes header and extra_data fields.) | |
1191 int _data_size; | |
1192 | |
1193 // Beginning of the data entries | |
1194 intptr_t _data[1]; | |
1195 | |
1196 // Helper for size computation | |
1197 static int compute_data_size(BytecodeStream* stream); | |
1198 static int bytecode_cell_count(Bytecodes::Code code); | |
1199 enum { no_profile_data = -1, variable_cell_count = -2 }; | |
1200 | |
1201 // Helper for initialization | |
1202 DataLayout* data_layout_at(int data_index) { | |
1203 assert(data_index % sizeof(intptr_t) == 0, "unaligned"); | |
1204 return (DataLayout*) (((address)_data) + data_index); | |
1205 } | |
1206 | |
1207 // Initialize an individual data segment. Returns the size of | |
1208 // the segment in bytes. | |
1209 int initialize_data(BytecodeStream* stream, int data_index); | |
1210 | |
1211 // Helper for data_at | |
1212 DataLayout* limit_data_position() { | |
1213 return (DataLayout*)((address)data_base() + _data_size); | |
1214 } | |
1215 bool out_of_bounds(int data_index) { | |
1216 return data_index >= data_size(); | |
1217 } | |
1218 | |
1219 // Give each of the data entries a chance to perform specific | |
1220 // data initialization. | |
1221 void post_initialize(BytecodeStream* stream); | |
1222 | |
1223 // hint accessors | |
1224 int hint_di() const { return _hint_di; } | |
1225 void set_hint_di(int di) { | |
1226 assert(!out_of_bounds(di), "hint_di out of bounds"); | |
1227 _hint_di = di; | |
1228 } | |
1229 ProfileData* data_before(int bci) { | |
1230 // avoid SEGV on this edge case | |
1231 if (data_size() == 0) | |
1232 return NULL; | |
1233 int hint = hint_di(); | |
1234 if (data_layout_at(hint)->bci() <= bci) | |
1235 return data_at(hint); | |
1236 return first_data(); | |
1237 } | |
1238 | |
1239 // What is the index of the first data entry? | |
1240 int first_di() { return 0; } | |
1241 | |
1242 // Find or create an extra ProfileData: | |
1243 ProfileData* bci_to_extra_data(int bci, bool create_if_missing); | |
1244 | |
45
48a3fa21394b
6667615: (Escape Analysis) extend MDO to cache arguments escape state
kvn
parents:
0
diff
changeset
|
1245 // return the argument info cell |
48a3fa21394b
6667615: (Escape Analysis) extend MDO to cache arguments escape state
kvn
parents:
0
diff
changeset
|
1246 ArgInfoData *arg_info(); |
48a3fa21394b
6667615: (Escape Analysis) extend MDO to cache arguments escape state
kvn
parents:
0
diff
changeset
|
1247 |
0 | 1248 public: |
1249 static int header_size() { | |
1250 return sizeof(methodDataOopDesc)/wordSize; | |
1251 } | |
1252 | |
1253 // Compute the size of a methodDataOop before it is created. | |
1254 static int compute_allocation_size_in_bytes(methodHandle method); | |
1255 static int compute_allocation_size_in_words(methodHandle method); | |
1256 static int compute_extra_data_count(int data_size, int empty_bc_count); | |
1257 | |
1258 // Determine if a given bytecode can have profile information. | |
1259 static bool bytecode_has_profile(Bytecodes::Code code) { | |
1260 return bytecode_cell_count(code) != no_profile_data; | |
1261 } | |
1262 | |
1263 // Perform initialization of a new methodDataOop | |
1264 void initialize(methodHandle method); | |
1265 | |
1266 // My size | |
1267 int object_size_in_bytes() { return _size; } | |
1268 int object_size() { | |
1269 return align_object_size(align_size_up(_size, BytesPerWord)/BytesPerWord); | |
1270 } | |
1271 | |
1272 int creation_mileage() const { return _creation_mileage; } | |
1273 void set_creation_mileage(int x) { _creation_mileage = x; } | |
1274 bool is_mature() const; // consult mileage and ProfileMaturityPercentage | |
1275 static int mileage_of(methodOop m); | |
1276 | |
1277 // Support for interprocedural escape analysis, from Thomas Kotzmann. | |
1278 enum EscapeFlag { | |
1279 estimated = 1 << 0, | |
78
e1e86702e43e
6680665: bytecode Escape Analyzer produces incorrect escape information for methods without oop arguments
kvn
parents:
45
diff
changeset
|
1280 return_local = 1 << 1, |
e1e86702e43e
6680665: bytecode Escape Analyzer produces incorrect escape information for methods without oop arguments
kvn
parents:
45
diff
changeset
|
1281 return_allocated = 1 << 2, |
e1e86702e43e
6680665: bytecode Escape Analyzer produces incorrect escape information for methods without oop arguments
kvn
parents:
45
diff
changeset
|
1282 allocated_escapes = 1 << 3, |
e1e86702e43e
6680665: bytecode Escape Analyzer produces incorrect escape information for methods without oop arguments
kvn
parents:
45
diff
changeset
|
1283 unknown_modified = 1 << 4 |
0 | 1284 }; |
1285 | |
1286 intx eflags() { return _eflags; } | |
1287 intx arg_local() { return _arg_local; } | |
1288 intx arg_stack() { return _arg_stack; } | |
1289 intx arg_returned() { return _arg_returned; } | |
45
48a3fa21394b
6667615: (Escape Analysis) extend MDO to cache arguments escape state
kvn
parents:
0
diff
changeset
|
1290 uint arg_modified(int a) { ArgInfoData *aid = arg_info(); |
48a3fa21394b
6667615: (Escape Analysis) extend MDO to cache arguments escape state
kvn
parents:
0
diff
changeset
|
1291 assert(a >= 0 && a < aid->number_of_args(), "valid argument number"); |
48a3fa21394b
6667615: (Escape Analysis) extend MDO to cache arguments escape state
kvn
parents:
0
diff
changeset
|
1292 return aid->arg_modified(a); } |
0 | 1293 |
1294 void set_eflags(intx v) { _eflags = v; } | |
1295 void set_arg_local(intx v) { _arg_local = v; } | |
1296 void set_arg_stack(intx v) { _arg_stack = v; } | |
1297 void set_arg_returned(intx v) { _arg_returned = v; } | |
45
48a3fa21394b
6667615: (Escape Analysis) extend MDO to cache arguments escape state
kvn
parents:
0
diff
changeset
|
1298 void set_arg_modified(int a, uint v) { ArgInfoData *aid = arg_info(); |
48a3fa21394b
6667615: (Escape Analysis) extend MDO to cache arguments escape state
kvn
parents:
0
diff
changeset
|
1299 assert(a >= 0 && a < aid->number_of_args(), "valid argument number"); |
48a3fa21394b
6667615: (Escape Analysis) extend MDO to cache arguments escape state
kvn
parents:
0
diff
changeset
|
1300 |
48a3fa21394b
6667615: (Escape Analysis) extend MDO to cache arguments escape state
kvn
parents:
0
diff
changeset
|
1301 aid->set_arg_modified(a, v); } |
0 | 1302 |
1303 void clear_escape_info() { _eflags = _arg_local = _arg_stack = _arg_returned = 0; } | |
1304 | |
1305 // Location and size of data area | |
1306 address data_base() const { | |
1307 return (address) _data; | |
1308 } | |
1309 int data_size() { | |
1310 return _data_size; | |
1311 } | |
1312 | |
1313 // Accessors | |
1314 methodOop method() { return _method; } | |
1315 | |
1316 // Get the data at an arbitrary (sort of) data index. | |
1317 ProfileData* data_at(int data_index); | |
1318 | |
1319 // Walk through the data in order. | |
1320 ProfileData* first_data() { return data_at(first_di()); } | |
1321 ProfileData* next_data(ProfileData* current); | |
1322 bool is_valid(ProfileData* current) { return current != NULL; } | |
1323 | |
1324 // Convert a dp (data pointer) to a di (data index). | |
1325 int dp_to_di(address dp) { | |
1326 return dp - ((address)_data); | |
1327 } | |
1328 | |
1329 address di_to_dp(int di) { | |
1330 return (address)data_layout_at(di); | |
1331 } | |
1332 | |
1333 // bci to di/dp conversion. | |
1334 address bci_to_dp(int bci); | |
1335 int bci_to_di(int bci) { | |
1336 return dp_to_di(bci_to_dp(bci)); | |
1337 } | |
1338 | |
1339 // Get the data at an arbitrary bci, or NULL if there is none. | |
1340 ProfileData* bci_to_data(int bci); | |
1341 | |
1342 // Same, but try to create an extra_data record if one is needed: | |
1343 ProfileData* allocate_bci_to_data(int bci) { | |
1344 ProfileData* data = bci_to_data(bci); | |
1345 return (data != NULL) ? data : bci_to_extra_data(bci, true); | |
1346 } | |
1347 | |
1348 // Add a handful of extra data records, for trap tracking. | |
1349 DataLayout* extra_data_base() { return limit_data_position(); } | |
1350 DataLayout* extra_data_limit() { return (DataLayout*)((address)this + object_size_in_bytes()); } | |
1351 int extra_data_size() { return (address)extra_data_limit() | |
1352 - (address)extra_data_base(); } | |
1353 static DataLayout* next_extra(DataLayout* dp) { return (DataLayout*)((address)dp + in_bytes(DataLayout::cell_offset(0))); } | |
1354 | |
1355 // Return (uint)-1 for overflow. | |
1356 uint trap_count(int reason) const { | |
1357 assert((uint)reason < _trap_hist_limit, "oob"); | |
1358 return (int)((_trap_hist._array[reason]+1) & _trap_hist_mask) - 1; | |
1359 } | |
1360 // For loops: | |
1361 static uint trap_reason_limit() { return _trap_hist_limit; } | |
1362 static uint trap_count_limit() { return _trap_hist_mask; } | |
1363 uint inc_trap_count(int reason) { | |
1364 // Count another trap, anywhere in this method. | |
1365 assert(reason >= 0, "must be single trap"); | |
1366 if ((uint)reason < _trap_hist_limit) { | |
1367 uint cnt1 = 1 + _trap_hist._array[reason]; | |
1368 if ((cnt1 & _trap_hist_mask) != 0) { // if no counter overflow... | |
1369 _trap_hist._array[reason] = cnt1; | |
1370 return cnt1; | |
1371 } else { | |
1372 return _trap_hist_mask + (++_nof_overflow_traps); | |
1373 } | |
1374 } else { | |
1375 // Could not represent the count in the histogram. | |
1376 return (++_nof_overflow_traps); | |
1377 } | |
1378 } | |
1379 | |
1380 uint overflow_trap_count() const { | |
1381 return _nof_overflow_traps; | |
1382 } | |
1383 uint overflow_recompile_count() const { | |
1384 return _nof_overflow_recompiles; | |
1385 } | |
1386 void inc_overflow_recompile_count() { | |
1387 _nof_overflow_recompiles += 1; | |
1388 } | |
1389 uint decompile_count() const { | |
1390 return _nof_decompiles; | |
1391 } | |
1392 void inc_decompile_count() { | |
1393 _nof_decompiles += 1; | |
1394 } | |
1395 | |
1396 // Support for code generation | |
1397 static ByteSize data_offset() { | |
1398 return byte_offset_of(methodDataOopDesc, _data[0]); | |
1399 } | |
1400 | |
1401 // GC support | |
1402 oop* adr_method() const { return (oop*)&_method; } | |
1403 bool object_is_parsable() const { return _size != 0; } | |
1404 void set_object_is_parsable(int object_size_in_bytes) { _size = object_size_in_bytes; } | |
1405 | |
1406 #ifndef PRODUCT | |
1407 // printing support for method data | |
1408 void print_data_on(outputStream* st); | |
1409 #endif | |
1410 | |
1411 // verification | |
1412 void verify_data_on(outputStream* st); | |
1413 }; |