Mercurial > hg > truffle
annotate src/share/vm/oops/methodDataOop.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 | a97fd181b813 |
children | f7251c729b31 |
rev | line source |
---|---|
0 | 1 /* |
2142 | 2 * Copyright (c) 2000, 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:
941
diff
changeset
|
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
941
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:
941
diff
changeset
|
21 * questions. |
0 | 22 * |
23 */ | |
24 | |
1972 | 25 #include "precompiled.hpp" |
26 #include "classfile/systemDictionary.hpp" | |
27 #include "gc_implementation/shared/markSweep.inline.hpp" | |
28 #include "interpreter/bytecode.hpp" | |
29 #include "interpreter/bytecodeStream.hpp" | |
30 #include "interpreter/linkResolver.hpp" | |
31 #include "oops/methodDataOop.hpp" | |
32 #include "oops/oop.inline.hpp" | |
33 #include "runtime/compilationPolicy.hpp" | |
34 #include "runtime/deoptimization.hpp" | |
35 #include "runtime/handles.inline.hpp" | |
0 | 36 |
37 // ================================================================== | |
38 // DataLayout | |
39 // | |
40 // Overlay for generic profiling data. | |
41 | |
42 // Some types of data layouts need a length field. | |
43 bool DataLayout::needs_array_len(u1 tag) { | |
45
48a3fa21394b
6667615: (Escape Analysis) extend MDO to cache arguments escape state
kvn
parents:
0
diff
changeset
|
44 return (tag == multi_branch_data_tag) || (tag == arg_info_data_tag); |
0 | 45 } |
46 | |
47 // Perform generic initialization of the data. More specific | |
48 // initialization occurs in overrides of ProfileData::post_initialize. | |
49 void DataLayout::initialize(u1 tag, u2 bci, int cell_count) { | |
50 _header._bits = (intptr_t)0; | |
51 _header._struct._tag = tag; | |
52 _header._struct._bci = bci; | |
53 for (int i = 0; i < cell_count; i++) { | |
54 set_cell_at(i, (intptr_t)0); | |
55 } | |
56 if (needs_array_len(tag)) { | |
57 set_cell_at(ArrayData::array_len_off_set, cell_count - 1); // -1 for header. | |
58 } | |
59 } | |
60 | |
941 | 61 void DataLayout::follow_weak_refs(BoolObjectClosure* cl) { |
62 ResourceMark m; | |
63 data_in()->follow_weak_refs(cl); | |
64 } | |
65 | |
66 | |
0 | 67 // ================================================================== |
68 // ProfileData | |
69 // | |
70 // A ProfileData object is created to refer to a section of profiling | |
71 // data in a structured way. | |
72 | |
73 // Constructor for invalid ProfileData. | |
74 ProfileData::ProfileData() { | |
75 _data = NULL; | |
76 } | |
77 | |
78 #ifndef PRODUCT | |
79 void ProfileData::print_shared(outputStream* st, const char* name) { | |
80 st->print("bci: %d", bci()); | |
81 st->fill_to(tab_width_one); | |
82 st->print("%s", name); | |
83 tab(st); | |
84 int trap = trap_state(); | |
85 if (trap != 0) { | |
86 char buf[100]; | |
87 st->print("trap(%s) ", Deoptimization::format_trap_state(buf, sizeof(buf), trap)); | |
88 } | |
89 int flags = data()->flags(); | |
90 if (flags != 0) | |
91 st->print("flags(%d) ", flags); | |
92 } | |
93 | |
94 void ProfileData::tab(outputStream* st) { | |
95 st->fill_to(tab_width_two); | |
96 } | |
97 #endif // !PRODUCT | |
98 | |
99 // ================================================================== | |
100 // BitData | |
101 // | |
102 // A BitData corresponds to a one-bit flag. This is used to indicate | |
103 // whether a checkcast bytecode has seen a null value. | |
104 | |
105 | |
106 #ifndef PRODUCT | |
107 void BitData::print_data_on(outputStream* st) { | |
108 print_shared(st, "BitData"); | |
109 } | |
110 #endif // !PRODUCT | |
111 | |
112 // ================================================================== | |
113 // CounterData | |
114 // | |
115 // A CounterData corresponds to a simple counter. | |
116 | |
117 #ifndef PRODUCT | |
118 void CounterData::print_data_on(outputStream* st) { | |
119 print_shared(st, "CounterData"); | |
120 st->print_cr("count(%u)", count()); | |
121 } | |
122 #endif // !PRODUCT | |
123 | |
124 // ================================================================== | |
125 // JumpData | |
126 // | |
127 // A JumpData is used to access profiling information for a direct | |
128 // branch. It is a counter, used for counting the number of branches, | |
129 // plus a data displacement, used for realigning the data pointer to | |
130 // the corresponding target bci. | |
131 | |
132 void JumpData::post_initialize(BytecodeStream* stream, methodDataOop mdo) { | |
133 assert(stream->bci() == bci(), "wrong pos"); | |
134 int target; | |
135 Bytecodes::Code c = stream->code(); | |
136 if (c == Bytecodes::_goto_w || c == Bytecodes::_jsr_w) { | |
137 target = stream->dest_w(); | |
138 } else { | |
139 target = stream->dest(); | |
140 } | |
141 int my_di = mdo->dp_to_di(dp()); | |
142 int target_di = mdo->bci_to_di(target); | |
143 int offset = target_di - my_di; | |
144 set_displacement(offset); | |
145 } | |
146 | |
147 #ifndef PRODUCT | |
148 void JumpData::print_data_on(outputStream* st) { | |
149 print_shared(st, "JumpData"); | |
150 st->print_cr("taken(%u) displacement(%d)", taken(), displacement()); | |
151 } | |
152 #endif // !PRODUCT | |
153 | |
154 // ================================================================== | |
155 // ReceiverTypeData | |
156 // | |
157 // A ReceiverTypeData is used to access profiling information about a | |
158 // dynamic type check. It consists of a counter which counts the total times | |
159 // that the check is reached, and a series of (klassOop, count) pairs | |
160 // which are used to store a type profile for the receiver of the check. | |
161 | |
162 void ReceiverTypeData::follow_contents() { | |
941 | 163 // This is a set of weak references that need |
164 // to be followed at the end of the strong marking | |
165 // phase. Memoize this object so it can be visited | |
166 // in the weak roots processing phase. | |
167 MarkSweep::revisit_mdo(data()); | |
0 | 168 } |
169 | |
170 #ifndef SERIALGC | |
171 void ReceiverTypeData::follow_contents(ParCompactionManager* cm) { | |
941 | 172 // This is a set of weak references that need |
173 // to be followed at the end of the strong marking | |
174 // phase. Memoize this object so it can be visited | |
175 // in the weak roots processing phase. | |
176 PSParallelCompact::revisit_mdo(cm, data()); | |
0 | 177 } |
178 #endif // SERIALGC | |
179 | |
180 void ReceiverTypeData::oop_iterate(OopClosure* blk) { | |
941 | 181 if (blk->should_remember_mdo()) { |
182 // This is a set of weak references that need | |
183 // to be followed at the end of the strong marking | |
184 // phase. Memoize this object so it can be visited | |
185 // in the weak roots processing phase. | |
186 blk->remember_mdo(data()); | |
187 } else { // normal scan | |
188 for (uint row = 0; row < row_limit(); row++) { | |
189 if (receiver(row) != NULL) { | |
190 oop* adr = adr_receiver(row); | |
0 | 191 blk->do_oop(adr); |
192 } | |
193 } | |
194 } | |
195 } | |
196 | |
941 | 197 void ReceiverTypeData::oop_iterate_m(OopClosure* blk, MemRegion mr) { |
198 // Currently, this interface is called only during card-scanning for | |
199 // a young gen gc, in which case this object cannot contribute anything, | |
200 // since it does not contain any references that cross out of | |
201 // the perm gen. However, for future more general use we allow | |
202 // the possibility of calling for instance from more general | |
203 // iterators (for example, a future regionalized perm gen for G1, | |
204 // or the possibility of moving some references out of perm in | |
205 // the case of other collectors). In that case, you will need | |
206 // to relax or remove some of the assertions below. | |
207 #ifdef ASSERT | |
208 // Verify that none of the embedded oop references cross out of | |
209 // this generation. | |
210 for (uint row = 0; row < row_limit(); row++) { | |
211 if (receiver(row) != NULL) { | |
212 oop* adr = adr_receiver(row); | |
213 CollectedHeap* h = Universe::heap(); | |
214 assert(h->is_permanent(adr) && h->is_permanent_or_null(*adr), "Not intra-perm"); | |
215 } | |
216 } | |
217 #endif // ASSERT | |
218 assert(!blk->should_remember_mdo(), "Not expected to remember MDO"); | |
219 return; // Nothing to do, see comment above | |
220 #if 0 | |
221 if (blk->should_remember_mdo()) { | |
222 // This is a set of weak references that need | |
223 // to be followed at the end of the strong marking | |
224 // phase. Memoize this object so it can be visited | |
225 // in the weak roots processing phase. | |
226 blk->remember_mdo(data()); | |
227 } else { // normal scan | |
228 for (uint row = 0; row < row_limit(); row++) { | |
229 if (receiver(row) != NULL) { | |
230 oop* adr = adr_receiver(row); | |
231 if (mr.contains(adr)) { | |
232 blk->do_oop(adr); | |
233 } else if ((HeapWord*)adr >= mr.end()) { | |
234 // Test that the current cursor and the two ends of the range | |
235 // that we may have skipped iterating over are monotonically ordered; | |
236 // this is just a paranoid assertion, just in case represetations | |
237 // should change in the future rendering the short-circuit return | |
238 // here invalid. | |
239 assert((row+1 >= row_limit() || adr_receiver(row+1) > adr) && | |
240 (row+2 >= row_limit() || adr_receiver(row_limit()-1) > adr_receiver(row+1)), "Reducing?"); | |
241 break; // remaining should be outside this mr too | |
242 } | |
243 } | |
244 } | |
245 } | |
246 #endif | |
247 } | |
248 | |
0 | 249 void ReceiverTypeData::adjust_pointers() { |
250 for (uint row = 0; row < row_limit(); row++) { | |
251 if (receiver(row) != NULL) { | |
252 MarkSweep::adjust_pointer(adr_receiver(row)); | |
253 } | |
254 } | |
255 } | |
256 | |
941 | 257 void ReceiverTypeData::follow_weak_refs(BoolObjectClosure* is_alive_cl) { |
258 for (uint row = 0; row < row_limit(); row++) { | |
259 klassOop p = receiver(row); | |
260 if (p != NULL && !is_alive_cl->do_object_b(p)) { | |
261 clear_row(row); | |
262 } | |
263 } | |
264 } | |
265 | |
0 | 266 #ifndef SERIALGC |
267 void ReceiverTypeData::update_pointers() { | |
268 for (uint row = 0; row < row_limit(); row++) { | |
269 if (receiver_unchecked(row) != NULL) { | |
270 PSParallelCompact::adjust_pointer(adr_receiver(row)); | |
271 } | |
272 } | |
273 } | |
274 #endif // SERIALGC | |
275 | |
276 #ifndef PRODUCT | |
277 void ReceiverTypeData::print_receiver_data_on(outputStream* st) { | |
278 uint row; | |
279 int entries = 0; | |
280 for (row = 0; row < row_limit(); row++) { | |
281 if (receiver(row) != NULL) entries++; | |
282 } | |
283 st->print_cr("count(%u) entries(%u)", count(), entries); | |
1783 | 284 int total = count(); |
285 for (row = 0; row < row_limit(); row++) { | |
286 if (receiver(row) != NULL) { | |
287 total += receiver_count(row); | |
288 } | |
289 } | |
0 | 290 for (row = 0; row < row_limit(); row++) { |
291 if (receiver(row) != NULL) { | |
292 tab(st); | |
293 receiver(row)->print_value_on(st); | |
1783 | 294 st->print_cr("(%u %4.2f)", receiver_count(row), (float) receiver_count(row) / (float) total); |
0 | 295 } |
296 } | |
297 } | |
298 void ReceiverTypeData::print_data_on(outputStream* st) { | |
299 print_shared(st, "ReceiverTypeData"); | |
300 print_receiver_data_on(st); | |
301 } | |
302 void VirtualCallData::print_data_on(outputStream* st) { | |
303 print_shared(st, "VirtualCallData"); | |
304 print_receiver_data_on(st); | |
305 } | |
306 #endif // !PRODUCT | |
307 | |
308 // ================================================================== | |
309 // RetData | |
310 // | |
311 // A RetData is used to access profiling information for a ret bytecode. | |
312 // It is composed of a count of the number of times that the ret has | |
313 // been executed, followed by a series of triples of the form | |
314 // (bci, count, di) which count the number of times that some bci was the | |
315 // target of the ret and cache a corresponding displacement. | |
316 | |
317 void RetData::post_initialize(BytecodeStream* stream, methodDataOop mdo) { | |
318 for (uint row = 0; row < row_limit(); row++) { | |
319 set_bci_displacement(row, -1); | |
320 set_bci(row, no_bci); | |
321 } | |
322 // release so other threads see a consistent state. bci is used as | |
323 // a valid flag for bci_displacement. | |
324 OrderAccess::release(); | |
325 } | |
326 | |
327 // This routine needs to atomically update the RetData structure, so the | |
328 // caller needs to hold the RetData_lock before it gets here. Since taking | |
329 // the lock can block (and allow GC) and since RetData is a ProfileData is a | |
330 // wrapper around a derived oop, taking the lock in _this_ method will | |
331 // basically cause the 'this' pointer's _data field to contain junk after the | |
332 // lock. We require the caller to take the lock before making the ProfileData | |
333 // structure. Currently the only caller is InterpreterRuntime::update_mdp_for_ret | |
334 address RetData::fixup_ret(int return_bci, methodDataHandle h_mdo) { | |
335 // First find the mdp which corresponds to the return bci. | |
336 address mdp = h_mdo->bci_to_dp(return_bci); | |
337 | |
338 // Now check to see if any of the cache slots are open. | |
339 for (uint row = 0; row < row_limit(); row++) { | |
340 if (bci(row) == no_bci) { | |
341 set_bci_displacement(row, mdp - dp()); | |
342 set_bci_count(row, DataLayout::counter_increment); | |
343 // Barrier to ensure displacement is written before the bci; allows | |
344 // the interpreter to read displacement without fear of race condition. | |
345 release_set_bci(row, return_bci); | |
346 break; | |
347 } | |
348 } | |
349 return mdp; | |
350 } | |
351 | |
352 | |
353 #ifndef PRODUCT | |
354 void RetData::print_data_on(outputStream* st) { | |
355 print_shared(st, "RetData"); | |
356 uint row; | |
357 int entries = 0; | |
358 for (row = 0; row < row_limit(); row++) { | |
359 if (bci(row) != no_bci) entries++; | |
360 } | |
361 st->print_cr("count(%u) entries(%u)", count(), entries); | |
362 for (row = 0; row < row_limit(); row++) { | |
363 if (bci(row) != no_bci) { | |
364 tab(st); | |
365 st->print_cr("bci(%d: count(%u) displacement(%d))", | |
366 bci(row), bci_count(row), bci_displacement(row)); | |
367 } | |
368 } | |
369 } | |
370 #endif // !PRODUCT | |
371 | |
372 // ================================================================== | |
373 // BranchData | |
374 // | |
375 // A BranchData is used to access profiling data for a two-way branch. | |
376 // It consists of taken and not_taken counts as well as a data displacement | |
377 // for the taken case. | |
378 | |
379 void BranchData::post_initialize(BytecodeStream* stream, methodDataOop mdo) { | |
380 assert(stream->bci() == bci(), "wrong pos"); | |
381 int target = stream->dest(); | |
382 int my_di = mdo->dp_to_di(dp()); | |
383 int target_di = mdo->bci_to_di(target); | |
384 int offset = target_di - my_di; | |
385 set_displacement(offset); | |
386 } | |
387 | |
388 #ifndef PRODUCT | |
389 void BranchData::print_data_on(outputStream* st) { | |
390 print_shared(st, "BranchData"); | |
391 st->print_cr("taken(%u) displacement(%d)", | |
392 taken(), displacement()); | |
393 tab(st); | |
394 st->print_cr("not taken(%u)", not_taken()); | |
395 } | |
396 #endif | |
397 | |
398 // ================================================================== | |
399 // MultiBranchData | |
400 // | |
401 // A MultiBranchData is used to access profiling information for | |
402 // a multi-way branch (*switch bytecodes). It consists of a series | |
403 // of (count, displacement) pairs, which count the number of times each | |
404 // case was taken and specify the data displacment for each branch target. | |
405 | |
406 int MultiBranchData::compute_cell_count(BytecodeStream* stream) { | |
407 int cell_count = 0; | |
408 if (stream->code() == Bytecodes::_tableswitch) { | |
2142 | 409 Bytecode_tableswitch sw(stream->method()(), stream->bcp()); |
410 cell_count = 1 + per_case_cell_count * (1 + sw.length()); // 1 for default | |
0 | 411 } else { |
2142 | 412 Bytecode_lookupswitch sw(stream->method()(), stream->bcp()); |
413 cell_count = 1 + per_case_cell_count * (sw.number_of_pairs() + 1); // 1 for default | |
0 | 414 } |
415 return cell_count; | |
416 } | |
417 | |
418 void MultiBranchData::post_initialize(BytecodeStream* stream, | |
419 methodDataOop mdo) { | |
420 assert(stream->bci() == bci(), "wrong pos"); | |
421 int target; | |
422 int my_di; | |
423 int target_di; | |
424 int offset; | |
425 if (stream->code() == Bytecodes::_tableswitch) { | |
2142 | 426 Bytecode_tableswitch sw(stream->method()(), stream->bcp()); |
427 int len = sw.length(); | |
0 | 428 assert(array_len() == per_case_cell_count * (len + 1), "wrong len"); |
429 for (int count = 0; count < len; count++) { | |
2142 | 430 target = sw.dest_offset_at(count) + bci(); |
0 | 431 my_di = mdo->dp_to_di(dp()); |
432 target_di = mdo->bci_to_di(target); | |
433 offset = target_di - my_di; | |
434 set_displacement_at(count, offset); | |
435 } | |
2142 | 436 target = sw.default_offset() + bci(); |
0 | 437 my_di = mdo->dp_to_di(dp()); |
438 target_di = mdo->bci_to_di(target); | |
439 offset = target_di - my_di; | |
440 set_default_displacement(offset); | |
441 | |
442 } else { | |
2142 | 443 Bytecode_lookupswitch sw(stream->method()(), stream->bcp()); |
444 int npairs = sw.number_of_pairs(); | |
0 | 445 assert(array_len() == per_case_cell_count * (npairs + 1), "wrong len"); |
446 for (int count = 0; count < npairs; count++) { | |
2142 | 447 LookupswitchPair pair = sw.pair_at(count); |
448 target = pair.offset() + bci(); | |
0 | 449 my_di = mdo->dp_to_di(dp()); |
450 target_di = mdo->bci_to_di(target); | |
451 offset = target_di - my_di; | |
452 set_displacement_at(count, offset); | |
453 } | |
2142 | 454 target = sw.default_offset() + bci(); |
0 | 455 my_di = mdo->dp_to_di(dp()); |
456 target_di = mdo->bci_to_di(target); | |
457 offset = target_di - my_di; | |
458 set_default_displacement(offset); | |
459 } | |
460 } | |
461 | |
462 #ifndef PRODUCT | |
463 void MultiBranchData::print_data_on(outputStream* st) { | |
464 print_shared(st, "MultiBranchData"); | |
465 st->print_cr("default_count(%u) displacement(%d)", | |
466 default_count(), default_displacement()); | |
467 int cases = number_of_cases(); | |
468 for (int i = 0; i < cases; i++) { | |
469 tab(st); | |
470 st->print_cr("count(%u) displacement(%d)", | |
471 count_at(i), displacement_at(i)); | |
472 } | |
473 } | |
474 #endif | |
475 | |
45
48a3fa21394b
6667615: (Escape Analysis) extend MDO to cache arguments escape state
kvn
parents:
0
diff
changeset
|
476 #ifndef PRODUCT |
48a3fa21394b
6667615: (Escape Analysis) extend MDO to cache arguments escape state
kvn
parents:
0
diff
changeset
|
477 void ArgInfoData::print_data_on(outputStream* st) { |
48a3fa21394b
6667615: (Escape Analysis) extend MDO to cache arguments escape state
kvn
parents:
0
diff
changeset
|
478 print_shared(st, "ArgInfoData"); |
48a3fa21394b
6667615: (Escape Analysis) extend MDO to cache arguments escape state
kvn
parents:
0
diff
changeset
|
479 int nargs = number_of_args(); |
48a3fa21394b
6667615: (Escape Analysis) extend MDO to cache arguments escape state
kvn
parents:
0
diff
changeset
|
480 for (int i = 0; i < nargs; i++) { |
48a3fa21394b
6667615: (Escape Analysis) extend MDO to cache arguments escape state
kvn
parents:
0
diff
changeset
|
481 st->print(" 0x%x", arg_modified(i)); |
48a3fa21394b
6667615: (Escape Analysis) extend MDO to cache arguments escape state
kvn
parents:
0
diff
changeset
|
482 } |
48a3fa21394b
6667615: (Escape Analysis) extend MDO to cache arguments escape state
kvn
parents:
0
diff
changeset
|
483 st->cr(); |
48a3fa21394b
6667615: (Escape Analysis) extend MDO to cache arguments escape state
kvn
parents:
0
diff
changeset
|
484 } |
48a3fa21394b
6667615: (Escape Analysis) extend MDO to cache arguments escape state
kvn
parents:
0
diff
changeset
|
485 |
48a3fa21394b
6667615: (Escape Analysis) extend MDO to cache arguments escape state
kvn
parents:
0
diff
changeset
|
486 #endif |
0 | 487 // ================================================================== |
488 // methodDataOop | |
489 // | |
490 // A methodDataOop holds information which has been collected about | |
491 // a method. | |
492 | |
493 int methodDataOopDesc::bytecode_cell_count(Bytecodes::Code code) { | |
494 switch (code) { | |
495 case Bytecodes::_checkcast: | |
496 case Bytecodes::_instanceof: | |
497 case Bytecodes::_aastore: | |
498 if (TypeProfileCasts) { | |
499 return ReceiverTypeData::static_cell_count(); | |
500 } else { | |
501 return BitData::static_cell_count(); | |
502 } | |
503 case Bytecodes::_invokespecial: | |
504 case Bytecodes::_invokestatic: | |
505 return CounterData::static_cell_count(); | |
506 case Bytecodes::_goto: | |
507 case Bytecodes::_goto_w: | |
508 case Bytecodes::_jsr: | |
509 case Bytecodes::_jsr_w: | |
510 return JumpData::static_cell_count(); | |
511 case Bytecodes::_invokevirtual: | |
512 case Bytecodes::_invokeinterface: | |
513 return VirtualCallData::static_cell_count(); | |
726
be93aad57795
6655646: dynamic languages need dynamically linked call sites
jrose
parents:
196
diff
changeset
|
514 case Bytecodes::_invokedynamic: |
be93aad57795
6655646: dynamic languages need dynamically linked call sites
jrose
parents:
196
diff
changeset
|
515 return CounterData::static_cell_count(); |
0 | 516 case Bytecodes::_ret: |
517 return RetData::static_cell_count(); | |
518 case Bytecodes::_ifeq: | |
519 case Bytecodes::_ifne: | |
520 case Bytecodes::_iflt: | |
521 case Bytecodes::_ifge: | |
522 case Bytecodes::_ifgt: | |
523 case Bytecodes::_ifle: | |
524 case Bytecodes::_if_icmpeq: | |
525 case Bytecodes::_if_icmpne: | |
526 case Bytecodes::_if_icmplt: | |
527 case Bytecodes::_if_icmpge: | |
528 case Bytecodes::_if_icmpgt: | |
529 case Bytecodes::_if_icmple: | |
530 case Bytecodes::_if_acmpeq: | |
531 case Bytecodes::_if_acmpne: | |
532 case Bytecodes::_ifnull: | |
533 case Bytecodes::_ifnonnull: | |
534 return BranchData::static_cell_count(); | |
535 case Bytecodes::_lookupswitch: | |
536 case Bytecodes::_tableswitch: | |
537 return variable_cell_count; | |
538 } | |
539 return no_profile_data; | |
540 } | |
541 | |
542 // Compute the size of the profiling information corresponding to | |
543 // the current bytecode. | |
544 int methodDataOopDesc::compute_data_size(BytecodeStream* stream) { | |
545 int cell_count = bytecode_cell_count(stream->code()); | |
546 if (cell_count == no_profile_data) { | |
547 return 0; | |
548 } | |
549 if (cell_count == variable_cell_count) { | |
550 cell_count = MultiBranchData::compute_cell_count(stream); | |
551 } | |
552 // Note: cell_count might be zero, meaning that there is just | |
553 // a DataLayout header, with no extra cells. | |
554 assert(cell_count >= 0, "sanity"); | |
555 return DataLayout::compute_size_in_bytes(cell_count); | |
556 } | |
557 | |
558 int methodDataOopDesc::compute_extra_data_count(int data_size, int empty_bc_count) { | |
559 if (ProfileTraps) { | |
560 // Assume that up to 3% of BCIs with no MDP will need to allocate one. | |
561 int extra_data_count = (uint)(empty_bc_count * 3) / 128 + 1; | |
562 // If the method is large, let the extra BCIs grow numerous (to ~1%). | |
563 int one_percent_of_data | |
564 = (uint)data_size / (DataLayout::header_size_in_bytes()*128); | |
565 if (extra_data_count < one_percent_of_data) | |
566 extra_data_count = one_percent_of_data; | |
567 if (extra_data_count > empty_bc_count) | |
568 extra_data_count = empty_bc_count; // no need for more | |
569 return extra_data_count; | |
570 } else { | |
571 return 0; | |
572 } | |
573 } | |
574 | |
575 // Compute the size of the methodDataOop necessary to store | |
576 // profiling information about a given method. Size is in bytes. | |
577 int methodDataOopDesc::compute_allocation_size_in_bytes(methodHandle method) { | |
578 int data_size = 0; | |
579 BytecodeStream stream(method); | |
580 Bytecodes::Code c; | |
581 int empty_bc_count = 0; // number of bytecodes lacking data | |
582 while ((c = stream.next()) >= 0) { | |
583 int size_in_bytes = compute_data_size(&stream); | |
584 data_size += size_in_bytes; | |
585 if (size_in_bytes == 0) empty_bc_count += 1; | |
586 } | |
587 int object_size = in_bytes(data_offset()) + data_size; | |
588 | |
589 // Add some extra DataLayout cells (at least one) to track stray traps. | |
590 int extra_data_count = compute_extra_data_count(data_size, empty_bc_count); | |
591 object_size += extra_data_count * DataLayout::compute_size_in_bytes(0); | |
592 | |
45
48a3fa21394b
6667615: (Escape Analysis) extend MDO to cache arguments escape state
kvn
parents:
0
diff
changeset
|
593 // Add a cell to record information about modified arguments. |
48a3fa21394b
6667615: (Escape Analysis) extend MDO to cache arguments escape state
kvn
parents:
0
diff
changeset
|
594 int arg_size = method->size_of_parameters(); |
48a3fa21394b
6667615: (Escape Analysis) extend MDO to cache arguments escape state
kvn
parents:
0
diff
changeset
|
595 object_size += DataLayout::compute_size_in_bytes(arg_size+1); |
0 | 596 return object_size; |
597 } | |
598 | |
599 // Compute the size of the methodDataOop necessary to store | |
600 // profiling information about a given method. Size is in words | |
601 int methodDataOopDesc::compute_allocation_size_in_words(methodHandle method) { | |
602 int byte_size = compute_allocation_size_in_bytes(method); | |
603 int word_size = align_size_up(byte_size, BytesPerWord) / BytesPerWord; | |
604 return align_object_size(word_size); | |
605 } | |
606 | |
607 // Initialize an individual data segment. Returns the size of | |
608 // the segment in bytes. | |
609 int methodDataOopDesc::initialize_data(BytecodeStream* stream, | |
610 int data_index) { | |
611 int cell_count = -1; | |
612 int tag = DataLayout::no_tag; | |
613 DataLayout* data_layout = data_layout_at(data_index); | |
614 Bytecodes::Code c = stream->code(); | |
615 switch (c) { | |
616 case Bytecodes::_checkcast: | |
617 case Bytecodes::_instanceof: | |
618 case Bytecodes::_aastore: | |
619 if (TypeProfileCasts) { | |
620 cell_count = ReceiverTypeData::static_cell_count(); | |
621 tag = DataLayout::receiver_type_data_tag; | |
622 } else { | |
623 cell_count = BitData::static_cell_count(); | |
624 tag = DataLayout::bit_data_tag; | |
625 } | |
626 break; | |
627 case Bytecodes::_invokespecial: | |
628 case Bytecodes::_invokestatic: | |
629 cell_count = CounterData::static_cell_count(); | |
630 tag = DataLayout::counter_data_tag; | |
631 break; | |
632 case Bytecodes::_goto: | |
633 case Bytecodes::_goto_w: | |
634 case Bytecodes::_jsr: | |
635 case Bytecodes::_jsr_w: | |
636 cell_count = JumpData::static_cell_count(); | |
637 tag = DataLayout::jump_data_tag; | |
638 break; | |
639 case Bytecodes::_invokevirtual: | |
640 case Bytecodes::_invokeinterface: | |
641 cell_count = VirtualCallData::static_cell_count(); | |
642 tag = DataLayout::virtual_call_data_tag; | |
643 break; | |
726
be93aad57795
6655646: dynamic languages need dynamically linked call sites
jrose
parents:
196
diff
changeset
|
644 case Bytecodes::_invokedynamic: |
be93aad57795
6655646: dynamic languages need dynamically linked call sites
jrose
parents:
196
diff
changeset
|
645 // %%% should make a type profile for any invokedynamic that takes a ref argument |
be93aad57795
6655646: dynamic languages need dynamically linked call sites
jrose
parents:
196
diff
changeset
|
646 cell_count = CounterData::static_cell_count(); |
be93aad57795
6655646: dynamic languages need dynamically linked call sites
jrose
parents:
196
diff
changeset
|
647 tag = DataLayout::counter_data_tag; |
be93aad57795
6655646: dynamic languages need dynamically linked call sites
jrose
parents:
196
diff
changeset
|
648 break; |
0 | 649 case Bytecodes::_ret: |
650 cell_count = RetData::static_cell_count(); | |
651 tag = DataLayout::ret_data_tag; | |
652 break; | |
653 case Bytecodes::_ifeq: | |
654 case Bytecodes::_ifne: | |
655 case Bytecodes::_iflt: | |
656 case Bytecodes::_ifge: | |
657 case Bytecodes::_ifgt: | |
658 case Bytecodes::_ifle: | |
659 case Bytecodes::_if_icmpeq: | |
660 case Bytecodes::_if_icmpne: | |
661 case Bytecodes::_if_icmplt: | |
662 case Bytecodes::_if_icmpge: | |
663 case Bytecodes::_if_icmpgt: | |
664 case Bytecodes::_if_icmple: | |
665 case Bytecodes::_if_acmpeq: | |
666 case Bytecodes::_if_acmpne: | |
667 case Bytecodes::_ifnull: | |
668 case Bytecodes::_ifnonnull: | |
669 cell_count = BranchData::static_cell_count(); | |
670 tag = DataLayout::branch_data_tag; | |
671 break; | |
672 case Bytecodes::_lookupswitch: | |
673 case Bytecodes::_tableswitch: | |
674 cell_count = MultiBranchData::compute_cell_count(stream); | |
675 tag = DataLayout::multi_branch_data_tag; | |
676 break; | |
677 } | |
678 assert(tag == DataLayout::multi_branch_data_tag || | |
679 cell_count == bytecode_cell_count(c), "cell counts must agree"); | |
680 if (cell_count >= 0) { | |
681 assert(tag != DataLayout::no_tag, "bad tag"); | |
682 assert(bytecode_has_profile(c), "agree w/ BHP"); | |
683 data_layout->initialize(tag, stream->bci(), cell_count); | |
684 return DataLayout::compute_size_in_bytes(cell_count); | |
685 } else { | |
686 assert(!bytecode_has_profile(c), "agree w/ !BHP"); | |
687 return 0; | |
688 } | |
689 } | |
690 | |
691 // Get the data at an arbitrary (sort of) data index. | |
692 ProfileData* methodDataOopDesc::data_at(int data_index) { | |
693 if (out_of_bounds(data_index)) { | |
694 return NULL; | |
695 } | |
696 DataLayout* data_layout = data_layout_at(data_index); | |
941 | 697 return data_layout->data_in(); |
698 } | |
0 | 699 |
941 | 700 ProfileData* DataLayout::data_in() { |
701 switch (tag()) { | |
0 | 702 case DataLayout::no_tag: |
703 default: | |
704 ShouldNotReachHere(); | |
705 return NULL; | |
706 case DataLayout::bit_data_tag: | |
941 | 707 return new BitData(this); |
0 | 708 case DataLayout::counter_data_tag: |
941 | 709 return new CounterData(this); |
0 | 710 case DataLayout::jump_data_tag: |
941 | 711 return new JumpData(this); |
0 | 712 case DataLayout::receiver_type_data_tag: |
941 | 713 return new ReceiverTypeData(this); |
0 | 714 case DataLayout::virtual_call_data_tag: |
941 | 715 return new VirtualCallData(this); |
0 | 716 case DataLayout::ret_data_tag: |
941 | 717 return new RetData(this); |
0 | 718 case DataLayout::branch_data_tag: |
941 | 719 return new BranchData(this); |
0 | 720 case DataLayout::multi_branch_data_tag: |
941 | 721 return new MultiBranchData(this); |
45
48a3fa21394b
6667615: (Escape Analysis) extend MDO to cache arguments escape state
kvn
parents:
0
diff
changeset
|
722 case DataLayout::arg_info_data_tag: |
941 | 723 return new ArgInfoData(this); |
0 | 724 }; |
725 } | |
726 | |
727 // Iteration over data. | |
728 ProfileData* methodDataOopDesc::next_data(ProfileData* current) { | |
729 int current_index = dp_to_di(current->dp()); | |
730 int next_index = current_index + current->size_in_bytes(); | |
731 ProfileData* next = data_at(next_index); | |
732 return next; | |
733 } | |
734 | |
735 // Give each of the data entries a chance to perform specific | |
736 // data initialization. | |
737 void methodDataOopDesc::post_initialize(BytecodeStream* stream) { | |
738 ResourceMark rm; | |
739 ProfileData* data; | |
740 for (data = first_data(); is_valid(data); data = next_data(data)) { | |
741 stream->set_start(data->bci()); | |
742 stream->next(); | |
743 data->post_initialize(stream, this); | |
744 } | |
745 } | |
746 | |
747 // Initialize the methodDataOop corresponding to a given method. | |
748 void methodDataOopDesc::initialize(methodHandle method) { | |
749 ResourceMark rm; | |
750 // Set the method back-pointer. | |
751 _method = method(); | |
1783 | 752 |
753 if (TieredCompilation) { | |
754 _invocation_counter.init(); | |
755 _backedge_counter.init(); | |
2252 | 756 _invocation_counter_start = 0; |
757 _backedge_counter_start = 0; | |
1783 | 758 _num_loops = 0; |
759 _num_blocks = 0; | |
760 _highest_comp_level = 0; | |
761 _highest_osr_comp_level = 0; | |
2252 | 762 _would_profile = true; |
1783 | 763 } |
0 | 764 set_creation_mileage(mileage_of(method())); |
765 | |
766 // Initialize flags and trap history. | |
767 _nof_decompiles = 0; | |
768 _nof_overflow_recompiles = 0; | |
769 _nof_overflow_traps = 0; | |
770 assert(sizeof(_trap_hist) % sizeof(HeapWord) == 0, "align"); | |
771 Copy::zero_to_words((HeapWord*) &_trap_hist, | |
772 sizeof(_trap_hist) / sizeof(HeapWord)); | |
773 | |
774 // Go through the bytecodes and allocate and initialize the | |
775 // corresponding data cells. | |
776 int data_size = 0; | |
777 int empty_bc_count = 0; // number of bytecodes lacking data | |
778 BytecodeStream stream(method); | |
779 Bytecodes::Code c; | |
780 while ((c = stream.next()) >= 0) { | |
781 int size_in_bytes = initialize_data(&stream, data_size); | |
782 data_size += size_in_bytes; | |
783 if (size_in_bytes == 0) empty_bc_count += 1; | |
784 } | |
785 _data_size = data_size; | |
786 int object_size = in_bytes(data_offset()) + data_size; | |
787 | |
788 // Add some extra DataLayout cells (at least one) to track stray traps. | |
789 int extra_data_count = compute_extra_data_count(data_size, empty_bc_count); | |
45
48a3fa21394b
6667615: (Escape Analysis) extend MDO to cache arguments escape state
kvn
parents:
0
diff
changeset
|
790 int extra_size = extra_data_count * DataLayout::compute_size_in_bytes(0); |
48a3fa21394b
6667615: (Escape Analysis) extend MDO to cache arguments escape state
kvn
parents:
0
diff
changeset
|
791 |
48a3fa21394b
6667615: (Escape Analysis) extend MDO to cache arguments escape state
kvn
parents:
0
diff
changeset
|
792 // Add a cell to record information about modified arguments. |
48a3fa21394b
6667615: (Escape Analysis) extend MDO to cache arguments escape state
kvn
parents:
0
diff
changeset
|
793 // Set up _args_modified array after traps cells so that |
48a3fa21394b
6667615: (Escape Analysis) extend MDO to cache arguments escape state
kvn
parents:
0
diff
changeset
|
794 // the code for traps cells works. |
48a3fa21394b
6667615: (Escape Analysis) extend MDO to cache arguments escape state
kvn
parents:
0
diff
changeset
|
795 DataLayout *dp = data_layout_at(data_size + extra_size); |
48a3fa21394b
6667615: (Escape Analysis) extend MDO to cache arguments escape state
kvn
parents:
0
diff
changeset
|
796 |
48a3fa21394b
6667615: (Escape Analysis) extend MDO to cache arguments escape state
kvn
parents:
0
diff
changeset
|
797 int arg_size = method->size_of_parameters(); |
48a3fa21394b
6667615: (Escape Analysis) extend MDO to cache arguments escape state
kvn
parents:
0
diff
changeset
|
798 dp->initialize(DataLayout::arg_info_data_tag, 0, arg_size+1); |
48a3fa21394b
6667615: (Escape Analysis) extend MDO to cache arguments escape state
kvn
parents:
0
diff
changeset
|
799 |
48a3fa21394b
6667615: (Escape Analysis) extend MDO to cache arguments escape state
kvn
parents:
0
diff
changeset
|
800 object_size += extra_size + DataLayout::compute_size_in_bytes(arg_size+1); |
0 | 801 |
802 // Set an initial hint. Don't use set_hint_di() because | |
803 // first_di() may be out of bounds if data_size is 0. | |
804 // In that situation, _hint_di is never used, but at | |
805 // least well-defined. | |
806 _hint_di = first_di(); | |
807 | |
808 post_initialize(&stream); | |
809 | |
810 set_object_is_parsable(object_size); | |
811 } | |
812 | |
813 // Get a measure of how much mileage the method has on it. | |
814 int methodDataOopDesc::mileage_of(methodOop method) { | |
815 int mileage = 0; | |
1783 | 816 if (TieredCompilation) { |
817 mileage = MAX2(method->invocation_count(), method->backedge_count()); | |
818 } else { | |
819 int iic = method->interpreter_invocation_count(); | |
820 if (mileage < iic) mileage = iic; | |
821 InvocationCounter* ic = method->invocation_counter(); | |
822 InvocationCounter* bc = method->backedge_counter(); | |
823 int icval = ic->count(); | |
824 if (ic->carry()) icval += CompileThreshold; | |
825 if (mileage < icval) mileage = icval; | |
826 int bcval = bc->count(); | |
827 if (bc->carry()) bcval += CompileThreshold; | |
828 if (mileage < bcval) mileage = bcval; | |
829 } | |
0 | 830 return mileage; |
831 } | |
832 | |
833 bool methodDataOopDesc::is_mature() const { | |
1783 | 834 return CompilationPolicy::policy()->is_mature(_method); |
0 | 835 } |
836 | |
837 // Translate a bci to its corresponding data index (di). | |
838 address methodDataOopDesc::bci_to_dp(int bci) { | |
839 ResourceMark rm; | |
840 ProfileData* data = data_before(bci); | |
841 ProfileData* prev = NULL; | |
842 for ( ; is_valid(data); data = next_data(data)) { | |
843 if (data->bci() >= bci) { | |
844 if (data->bci() == bci) set_hint_di(dp_to_di(data->dp())); | |
845 else if (prev != NULL) set_hint_di(dp_to_di(prev->dp())); | |
846 return data->dp(); | |
847 } | |
848 prev = data; | |
849 } | |
850 return (address)limit_data_position(); | |
851 } | |
852 | |
853 // Translate a bci to its corresponding data, or NULL. | |
854 ProfileData* methodDataOopDesc::bci_to_data(int bci) { | |
855 ProfileData* data = data_before(bci); | |
856 for ( ; is_valid(data); data = next_data(data)) { | |
857 if (data->bci() == bci) { | |
858 set_hint_di(dp_to_di(data->dp())); | |
859 return data; | |
860 } else if (data->bci() > bci) { | |
861 break; | |
862 } | |
863 } | |
864 return bci_to_extra_data(bci, false); | |
865 } | |
866 | |
867 // Translate a bci to its corresponding extra data, or NULL. | |
868 ProfileData* methodDataOopDesc::bci_to_extra_data(int bci, bool create_if_missing) { | |
869 DataLayout* dp = extra_data_base(); | |
870 DataLayout* end = extra_data_limit(); | |
871 DataLayout* avail = NULL; | |
872 for (; dp < end; dp = next_extra(dp)) { | |
873 // No need for "OrderAccess::load_acquire" ops, | |
874 // since the data structure is monotonic. | |
875 if (dp->tag() == DataLayout::no_tag) break; | |
45
48a3fa21394b
6667615: (Escape Analysis) extend MDO to cache arguments escape state
kvn
parents:
0
diff
changeset
|
876 if (dp->tag() == DataLayout::arg_info_data_tag) { |
48a3fa21394b
6667615: (Escape Analysis) extend MDO to cache arguments escape state
kvn
parents:
0
diff
changeset
|
877 dp = end; // ArgInfoData is at the end of extra data section. |
48a3fa21394b
6667615: (Escape Analysis) extend MDO to cache arguments escape state
kvn
parents:
0
diff
changeset
|
878 break; |
48a3fa21394b
6667615: (Escape Analysis) extend MDO to cache arguments escape state
kvn
parents:
0
diff
changeset
|
879 } |
0 | 880 if (dp->bci() == bci) { |
881 assert(dp->tag() == DataLayout::bit_data_tag, "sane"); | |
882 return new BitData(dp); | |
883 } | |
884 } | |
885 if (create_if_missing && dp < end) { | |
886 // Allocate this one. There is no mutual exclusion, | |
887 // so two threads could allocate different BCIs to the | |
888 // same data layout. This means these extra data | |
889 // records, like most other MDO contents, must not be | |
890 // trusted too much. | |
891 DataLayout temp; | |
892 temp.initialize(DataLayout::bit_data_tag, bci, 0); | |
893 dp->release_set_header(temp.header()); | |
894 assert(dp->tag() == DataLayout::bit_data_tag, "sane"); | |
895 //NO: assert(dp->bci() == bci, "no concurrent allocation"); | |
896 return new BitData(dp); | |
897 } | |
898 return NULL; | |
899 } | |
900 | |
45
48a3fa21394b
6667615: (Escape Analysis) extend MDO to cache arguments escape state
kvn
parents:
0
diff
changeset
|
901 ArgInfoData *methodDataOopDesc::arg_info() { |
48a3fa21394b
6667615: (Escape Analysis) extend MDO to cache arguments escape state
kvn
parents:
0
diff
changeset
|
902 DataLayout* dp = extra_data_base(); |
48a3fa21394b
6667615: (Escape Analysis) extend MDO to cache arguments escape state
kvn
parents:
0
diff
changeset
|
903 DataLayout* end = extra_data_limit(); |
48a3fa21394b
6667615: (Escape Analysis) extend MDO to cache arguments escape state
kvn
parents:
0
diff
changeset
|
904 for (; dp < end; dp = next_extra(dp)) { |
48a3fa21394b
6667615: (Escape Analysis) extend MDO to cache arguments escape state
kvn
parents:
0
diff
changeset
|
905 if (dp->tag() == DataLayout::arg_info_data_tag) |
48a3fa21394b
6667615: (Escape Analysis) extend MDO to cache arguments escape state
kvn
parents:
0
diff
changeset
|
906 return new ArgInfoData(dp); |
48a3fa21394b
6667615: (Escape Analysis) extend MDO to cache arguments escape state
kvn
parents:
0
diff
changeset
|
907 } |
48a3fa21394b
6667615: (Escape Analysis) extend MDO to cache arguments escape state
kvn
parents:
0
diff
changeset
|
908 return NULL; |
48a3fa21394b
6667615: (Escape Analysis) extend MDO to cache arguments escape state
kvn
parents:
0
diff
changeset
|
909 } |
48a3fa21394b
6667615: (Escape Analysis) extend MDO to cache arguments escape state
kvn
parents:
0
diff
changeset
|
910 |
0 | 911 #ifndef PRODUCT |
912 void methodDataOopDesc::print_data_on(outputStream* st) { | |
913 ResourceMark rm; | |
914 ProfileData* data = first_data(); | |
915 for ( ; is_valid(data); data = next_data(data)) { | |
916 st->print("%d", dp_to_di(data->dp())); | |
917 st->fill_to(6); | |
918 data->print_data_on(st); | |
919 } | |
45
48a3fa21394b
6667615: (Escape Analysis) extend MDO to cache arguments escape state
kvn
parents:
0
diff
changeset
|
920 st->print_cr("--- Extra data:"); |
0 | 921 DataLayout* dp = extra_data_base(); |
922 DataLayout* end = extra_data_limit(); | |
923 for (; dp < end; dp = next_extra(dp)) { | |
924 // No need for "OrderAccess::load_acquire" ops, | |
925 // since the data structure is monotonic. | |
45
48a3fa21394b
6667615: (Escape Analysis) extend MDO to cache arguments escape state
kvn
parents:
0
diff
changeset
|
926 if (dp->tag() == DataLayout::no_tag) continue; |
48a3fa21394b
6667615: (Escape Analysis) extend MDO to cache arguments escape state
kvn
parents:
0
diff
changeset
|
927 if (dp->tag() == DataLayout::bit_data_tag) { |
48a3fa21394b
6667615: (Escape Analysis) extend MDO to cache arguments escape state
kvn
parents:
0
diff
changeset
|
928 data = new BitData(dp); |
48a3fa21394b
6667615: (Escape Analysis) extend MDO to cache arguments escape state
kvn
parents:
0
diff
changeset
|
929 } else { |
48a3fa21394b
6667615: (Escape Analysis) extend MDO to cache arguments escape state
kvn
parents:
0
diff
changeset
|
930 assert(dp->tag() == DataLayout::arg_info_data_tag, "must be BitData or ArgInfo"); |
48a3fa21394b
6667615: (Escape Analysis) extend MDO to cache arguments escape state
kvn
parents:
0
diff
changeset
|
931 data = new ArgInfoData(dp); |
48a3fa21394b
6667615: (Escape Analysis) extend MDO to cache arguments escape state
kvn
parents:
0
diff
changeset
|
932 dp = end; // ArgInfoData is at the end of extra data section. |
48a3fa21394b
6667615: (Escape Analysis) extend MDO to cache arguments escape state
kvn
parents:
0
diff
changeset
|
933 } |
0 | 934 st->print("%d", dp_to_di(data->dp())); |
935 st->fill_to(6); | |
936 data->print_data_on(st); | |
937 } | |
938 } | |
939 #endif | |
940 | |
941 void methodDataOopDesc::verify_data_on(outputStream* st) { | |
942 NEEDS_CLEANUP; | |
943 // not yet implemented. | |
944 } |