Mercurial > hg > truffle
comparison src/share/vm/oops/methodData.cpp @ 12875:d13d7aba8c12
8023657: New type profiling points: arguments to call
Summary: x86 interpreter and c1 type profiling for arguments at calls
Reviewed-by: kvn, twisti
author | roland |
---|---|
date | Wed, 09 Oct 2013 16:32:21 +0200 |
parents | a1ebd310d5c1 |
children | ce0cc25bc5e2 |
comparison
equal
deleted
inserted
replaced
12874:46ef27bcacb3 | 12875:d13d7aba8c12 |
---|---|
54 set_cell_at(i, (intptr_t)0); | 54 set_cell_at(i, (intptr_t)0); |
55 } | 55 } |
56 if (needs_array_len(tag)) { | 56 if (needs_array_len(tag)) { |
57 set_cell_at(ArrayData::array_len_off_set, cell_count - 1); // -1 for header. | 57 set_cell_at(ArrayData::array_len_off_set, cell_count - 1); // -1 for header. |
58 } | 58 } |
59 if (tag == call_type_data_tag) { | |
60 CallTypeData::initialize(this, cell_count); | |
61 } else if (tag == virtual_call_type_data_tag) { | |
62 VirtualCallTypeData::initialize(this, cell_count); | |
63 } | |
59 } | 64 } |
60 | 65 |
61 void DataLayout::clean_weak_klass_links(BoolObjectClosure* cl) { | 66 void DataLayout::clean_weak_klass_links(BoolObjectClosure* cl) { |
62 ResourceMark m; | 67 ResourceMark m; |
63 data_in()->clean_weak_klass_links(cl); | 68 data_in()->clean_weak_klass_links(cl); |
74 ProfileData::ProfileData() { | 79 ProfileData::ProfileData() { |
75 _data = NULL; | 80 _data = NULL; |
76 } | 81 } |
77 | 82 |
78 #ifndef PRODUCT | 83 #ifndef PRODUCT |
79 void ProfileData::print_shared(outputStream* st, const char* name) { | 84 void ProfileData::print_shared(outputStream* st, const char* name) const { |
80 st->print("bci: %d", bci()); | 85 st->print("bci: %d", bci()); |
81 st->fill_to(tab_width_one); | 86 st->fill_to(tab_width_one); |
82 st->print("%s", name); | 87 st->print("%s", name); |
83 tab(st); | 88 tab(st); |
84 int trap = trap_state(); | 89 int trap = trap_state(); |
89 int flags = data()->flags(); | 94 int flags = data()->flags(); |
90 if (flags != 0) | 95 if (flags != 0) |
91 st->print("flags(%d) ", flags); | 96 st->print("flags(%d) ", flags); |
92 } | 97 } |
93 | 98 |
94 void ProfileData::tab(outputStream* st) { | 99 void ProfileData::tab(outputStream* st, bool first) const { |
95 st->fill_to(tab_width_two); | 100 st->fill_to(first ? tab_width_one : tab_width_two); |
96 } | 101 } |
97 #endif // !PRODUCT | 102 #endif // !PRODUCT |
98 | 103 |
99 // ================================================================== | 104 // ================================================================== |
100 // BitData | 105 // BitData |
102 // A BitData corresponds to a one-bit flag. This is used to indicate | 107 // A BitData corresponds to a one-bit flag. This is used to indicate |
103 // whether a checkcast bytecode has seen a null value. | 108 // whether a checkcast bytecode has seen a null value. |
104 | 109 |
105 | 110 |
106 #ifndef PRODUCT | 111 #ifndef PRODUCT |
107 void BitData::print_data_on(outputStream* st) { | 112 void BitData::print_data_on(outputStream* st) const { |
108 print_shared(st, "BitData"); | 113 print_shared(st, "BitData"); |
109 } | 114 } |
110 #endif // !PRODUCT | 115 #endif // !PRODUCT |
111 | 116 |
112 // ================================================================== | 117 // ================================================================== |
113 // CounterData | 118 // CounterData |
114 // | 119 // |
115 // A CounterData corresponds to a simple counter. | 120 // A CounterData corresponds to a simple counter. |
116 | 121 |
117 #ifndef PRODUCT | 122 #ifndef PRODUCT |
118 void CounterData::print_data_on(outputStream* st) { | 123 void CounterData::print_data_on(outputStream* st) const { |
119 print_shared(st, "CounterData"); | 124 print_shared(st, "CounterData"); |
120 st->print_cr("count(%u)", count()); | 125 st->print_cr("count(%u)", count()); |
121 } | 126 } |
122 #endif // !PRODUCT | 127 #endif // !PRODUCT |
123 | 128 |
143 int offset = target_di - my_di; | 148 int offset = target_di - my_di; |
144 set_displacement(offset); | 149 set_displacement(offset); |
145 } | 150 } |
146 | 151 |
147 #ifndef PRODUCT | 152 #ifndef PRODUCT |
148 void JumpData::print_data_on(outputStream* st) { | 153 void JumpData::print_data_on(outputStream* st) const { |
149 print_shared(st, "JumpData"); | 154 print_shared(st, "JumpData"); |
150 st->print_cr("taken(%u) displacement(%d)", taken(), displacement()); | 155 st->print_cr("taken(%u) displacement(%d)", taken(), displacement()); |
151 } | 156 } |
152 #endif // !PRODUCT | 157 #endif // !PRODUCT |
158 | |
159 int TypeStackSlotEntries::compute_cell_count(BytecodeStream* stream) { | |
160 int max = TypeProfileArgsLimit; | |
161 assert(Bytecodes::is_invoke(stream->code()), "should be invoke"); | |
162 Bytecode_invoke inv(stream->method(), stream->bci()); | |
163 | |
164 ResourceMark rm; | |
165 SignatureStream ss(inv.signature()); | |
166 int args_count = MIN2(ss.reference_parameter_count(), max); | |
167 | |
168 return args_count * per_arg_cell_count + (args_count > 0 ? header_cell_count() : 0); | |
169 } | |
170 | |
171 class ArgumentOffsetComputer : public SignatureInfo { | |
172 private: | |
173 int _max; | |
174 GrowableArray<int> _offsets; | |
175 | |
176 void set(int size, BasicType type) { _size += size; } | |
177 void do_object(int begin, int end) { | |
178 if (_offsets.length() < _max) { | |
179 _offsets.push(_size); | |
180 } | |
181 SignatureInfo::do_object(begin, end); | |
182 } | |
183 void do_array (int begin, int end) { | |
184 if (_offsets.length() < _max) { | |
185 _offsets.push(_size); | |
186 } | |
187 SignatureInfo::do_array(begin, end); | |
188 } | |
189 | |
190 public: | |
191 ArgumentOffsetComputer(Symbol* signature, int max) | |
192 : SignatureInfo(signature), _max(max), _offsets(Thread::current(), max) { | |
193 } | |
194 | |
195 int total() { lazy_iterate_parameters(); return _size; } | |
196 | |
197 int off_at(int i) const { return _offsets.at(i); } | |
198 }; | |
199 | |
200 void TypeStackSlotEntries::post_initialize(BytecodeStream* stream) { | |
201 ResourceMark rm; | |
202 | |
203 assert(Bytecodes::is_invoke(stream->code()), "should be invoke"); | |
204 Bytecode_invoke inv(stream->method(), stream->bci()); | |
205 | |
206 #ifdef ASSERT | |
207 SignatureStream ss(inv.signature()); | |
208 int count = MIN2(ss.reference_parameter_count(), (int)TypeProfileArgsLimit); | |
209 assert(count > 0, "room for args type but none found?"); | |
210 check_number_of_arguments(count); | |
211 #endif | |
212 | |
213 int start = 0; | |
214 ArgumentOffsetComputer aos(inv.signature(), number_of_arguments()-start); | |
215 aos.total(); | |
216 bool has_receiver = inv.has_receiver(); | |
217 for (int i = start; i < number_of_arguments(); i++) { | |
218 set_stack_slot(i, aos.off_at(i-start) + (has_receiver ? 1 : 0)); | |
219 set_type(i, type_none()); | |
220 } | |
221 } | |
222 | |
223 bool TypeEntries::is_loader_alive(BoolObjectClosure* is_alive_cl, intptr_t p) { | |
224 return !is_type_none(p) && | |
225 !((Klass*)klass_part(p))->is_loader_alive(is_alive_cl); | |
226 } | |
227 | |
228 void TypeStackSlotEntries::clean_weak_klass_links(BoolObjectClosure* is_alive_cl) { | |
229 for (int i = 0; i < number_of_arguments(); i++) { | |
230 intptr_t p = type(i); | |
231 if (is_loader_alive(is_alive_cl, p)) { | |
232 set_type(i, type_none()); | |
233 } | |
234 } | |
235 } | |
236 | |
237 bool TypeStackSlotEntries::arguments_profiling_enabled() { | |
238 return MethodData::profile_arguments(); | |
239 } | |
240 | |
241 #ifndef PRODUCT | |
242 void TypeEntries::print_klass(outputStream* st, intptr_t k) { | |
243 if (is_type_none(k)) { | |
244 st->print("none"); | |
245 } else if (is_type_unknown(k)) { | |
246 st->print("unknown"); | |
247 } else { | |
248 valid_klass(k)->print_value_on(st); | |
249 } | |
250 if (was_null_seen(k)) { | |
251 st->print(" (null seen)"); | |
252 } | |
253 } | |
254 | |
255 void TypeStackSlotEntries::print_data_on(outputStream* st) const { | |
256 _pd->tab(st, true); | |
257 st->print("argument types"); | |
258 for (int i = 0; i < number_of_arguments(); i++) { | |
259 _pd->tab(st); | |
260 st->print("%d: stack(%u) ", i, stack_slot(i)); | |
261 print_klass(st, type(i)); | |
262 st->cr(); | |
263 } | |
264 } | |
265 | |
266 void CallTypeData::print_data_on(outputStream* st) const { | |
267 CounterData::print_data_on(st); | |
268 _args.print_data_on(st); | |
269 } | |
270 | |
271 void VirtualCallTypeData::print_data_on(outputStream* st) const { | |
272 VirtualCallData::print_data_on(st); | |
273 _args.print_data_on(st); | |
274 } | |
275 #endif | |
153 | 276 |
154 // ================================================================== | 277 // ================================================================== |
155 // ReceiverTypeData | 278 // ReceiverTypeData |
156 // | 279 // |
157 // A ReceiverTypeData is used to access profiling information about a | 280 // A ReceiverTypeData is used to access profiling information about a |
167 } | 290 } |
168 } | 291 } |
169 } | 292 } |
170 | 293 |
171 #ifndef PRODUCT | 294 #ifndef PRODUCT |
172 void ReceiverTypeData::print_receiver_data_on(outputStream* st) { | 295 void ReceiverTypeData::print_receiver_data_on(outputStream* st) const { |
173 uint row; | 296 uint row; |
174 int entries = 0; | 297 int entries = 0; |
175 for (row = 0; row < row_limit(); row++) { | 298 for (row = 0; row < row_limit(); row++) { |
176 if (receiver(row) != NULL) entries++; | 299 if (receiver(row) != NULL) entries++; |
177 } | 300 } |
188 receiver(row)->print_value_on(st); | 311 receiver(row)->print_value_on(st); |
189 st->print_cr("(%u %4.2f)", receiver_count(row), (float) receiver_count(row) / (float) total); | 312 st->print_cr("(%u %4.2f)", receiver_count(row), (float) receiver_count(row) / (float) total); |
190 } | 313 } |
191 } | 314 } |
192 } | 315 } |
193 void ReceiverTypeData::print_data_on(outputStream* st) { | 316 void ReceiverTypeData::print_data_on(outputStream* st) const { |
194 print_shared(st, "ReceiverTypeData"); | 317 print_shared(st, "ReceiverTypeData"); |
195 print_receiver_data_on(st); | 318 print_receiver_data_on(st); |
196 } | 319 } |
197 void VirtualCallData::print_data_on(outputStream* st) { | 320 void VirtualCallData::print_data_on(outputStream* st) const { |
198 print_shared(st, "VirtualCallData"); | 321 print_shared(st, "VirtualCallData"); |
199 print_receiver_data_on(st); | 322 print_receiver_data_on(st); |
200 } | 323 } |
201 #endif // !PRODUCT | 324 #endif // !PRODUCT |
202 | 325 |
244 return mdp; | 367 return mdp; |
245 } | 368 } |
246 | 369 |
247 | 370 |
248 #ifndef PRODUCT | 371 #ifndef PRODUCT |
249 void RetData::print_data_on(outputStream* st) { | 372 void RetData::print_data_on(outputStream* st) const { |
250 print_shared(st, "RetData"); | 373 print_shared(st, "RetData"); |
251 uint row; | 374 uint row; |
252 int entries = 0; | 375 int entries = 0; |
253 for (row = 0; row < row_limit(); row++) { | 376 for (row = 0; row < row_limit(); row++) { |
254 if (bci(row) != no_bci) entries++; | 377 if (bci(row) != no_bci) entries++; |
279 int offset = target_di - my_di; | 402 int offset = target_di - my_di; |
280 set_displacement(offset); | 403 set_displacement(offset); |
281 } | 404 } |
282 | 405 |
283 #ifndef PRODUCT | 406 #ifndef PRODUCT |
284 void BranchData::print_data_on(outputStream* st) { | 407 void BranchData::print_data_on(outputStream* st) const { |
285 print_shared(st, "BranchData"); | 408 print_shared(st, "BranchData"); |
286 st->print_cr("taken(%u) displacement(%d)", | 409 st->print_cr("taken(%u) displacement(%d)", |
287 taken(), displacement()); | 410 taken(), displacement()); |
288 tab(st); | 411 tab(st); |
289 st->print_cr("not taken(%u)", not_taken()); | 412 st->print_cr("not taken(%u)", not_taken()); |
353 set_default_displacement(offset); | 476 set_default_displacement(offset); |
354 } | 477 } |
355 } | 478 } |
356 | 479 |
357 #ifndef PRODUCT | 480 #ifndef PRODUCT |
358 void MultiBranchData::print_data_on(outputStream* st) { | 481 void MultiBranchData::print_data_on(outputStream* st) const { |
359 print_shared(st, "MultiBranchData"); | 482 print_shared(st, "MultiBranchData"); |
360 st->print_cr("default_count(%u) displacement(%d)", | 483 st->print_cr("default_count(%u) displacement(%d)", |
361 default_count(), default_displacement()); | 484 default_count(), default_displacement()); |
362 int cases = number_of_cases(); | 485 int cases = number_of_cases(); |
363 for (int i = 0; i < cases; i++) { | 486 for (int i = 0; i < cases; i++) { |
367 } | 490 } |
368 } | 491 } |
369 #endif | 492 #endif |
370 | 493 |
371 #ifndef PRODUCT | 494 #ifndef PRODUCT |
372 void ArgInfoData::print_data_on(outputStream* st) { | 495 void ArgInfoData::print_data_on(outputStream* st) const { |
373 print_shared(st, "ArgInfoData"); | 496 print_shared(st, "ArgInfoData"); |
374 int nargs = number_of_args(); | 497 int nargs = number_of_args(); |
375 for (int i = 0; i < nargs; i++) { | 498 for (int i = 0; i < nargs; i++) { |
376 st->print(" 0x%x", arg_modified(i)); | 499 st->print(" 0x%x", arg_modified(i)); |
377 } | 500 } |
405 } else { | 528 } else { |
406 return BitData::static_cell_count(); | 529 return BitData::static_cell_count(); |
407 } | 530 } |
408 case Bytecodes::_invokespecial: | 531 case Bytecodes::_invokespecial: |
409 case Bytecodes::_invokestatic: | 532 case Bytecodes::_invokestatic: |
410 return CounterData::static_cell_count(); | 533 if (MethodData::profile_arguments()) { |
534 return variable_cell_count; | |
535 } else { | |
536 return CounterData::static_cell_count(); | |
537 } | |
411 case Bytecodes::_goto: | 538 case Bytecodes::_goto: |
412 case Bytecodes::_goto_w: | 539 case Bytecodes::_goto_w: |
413 case Bytecodes::_jsr: | 540 case Bytecodes::_jsr: |
414 case Bytecodes::_jsr_w: | 541 case Bytecodes::_jsr_w: |
415 return JumpData::static_cell_count(); | 542 return JumpData::static_cell_count(); |
416 case Bytecodes::_invokevirtual: | 543 case Bytecodes::_invokevirtual: |
417 case Bytecodes::_invokeinterface: | 544 case Bytecodes::_invokeinterface: |
418 return VirtualCallData::static_cell_count(); | 545 if (MethodData::profile_arguments()) { |
546 return variable_cell_count; | |
547 } else { | |
548 return VirtualCallData::static_cell_count(); | |
549 } | |
419 case Bytecodes::_invokedynamic: | 550 case Bytecodes::_invokedynamic: |
420 return CounterData::static_cell_count(); | 551 if (MethodData::profile_arguments()) { |
552 return variable_cell_count; | |
553 } else { | |
554 return CounterData::static_cell_count(); | |
555 } | |
421 case Bytecodes::_ret: | 556 case Bytecodes::_ret: |
422 return RetData::static_cell_count(); | 557 return RetData::static_cell_count(); |
423 case Bytecodes::_ifeq: | 558 case Bytecodes::_ifeq: |
424 case Bytecodes::_ifne: | 559 case Bytecodes::_ifne: |
425 case Bytecodes::_iflt: | 560 case Bytecodes::_iflt: |
451 int cell_count = bytecode_cell_count(stream->code()); | 586 int cell_count = bytecode_cell_count(stream->code()); |
452 if (cell_count == no_profile_data) { | 587 if (cell_count == no_profile_data) { |
453 return 0; | 588 return 0; |
454 } | 589 } |
455 if (cell_count == variable_cell_count) { | 590 if (cell_count == variable_cell_count) { |
456 cell_count = MultiBranchData::compute_cell_count(stream); | 591 switch (stream->code()) { |
592 case Bytecodes::_lookupswitch: | |
593 case Bytecodes::_tableswitch: | |
594 cell_count = MultiBranchData::compute_cell_count(stream); | |
595 break; | |
596 case Bytecodes::_invokespecial: | |
597 case Bytecodes::_invokestatic: | |
598 case Bytecodes::_invokedynamic: | |
599 assert(MethodData::profile_arguments(), "should be collecting args profile"); | |
600 if (profile_arguments_for_invoke(stream->method(), stream->bci())) { | |
601 cell_count = CallTypeData::compute_cell_count(stream); | |
602 } else { | |
603 cell_count = CounterData::static_cell_count(); | |
604 } | |
605 break; | |
606 case Bytecodes::_invokevirtual: | |
607 case Bytecodes::_invokeinterface: { | |
608 assert(MethodData::profile_arguments(), "should be collecting args profile"); | |
609 if (profile_arguments_for_invoke(stream->method(), stream->bci())) { | |
610 cell_count = VirtualCallTypeData::compute_cell_count(stream); | |
611 } else { | |
612 cell_count = VirtualCallData::static_cell_count(); | |
613 } | |
614 break; | |
615 } | |
616 default: | |
617 fatal("unexpected bytecode for var length profile data"); | |
618 } | |
457 } | 619 } |
458 // Note: cell_count might be zero, meaning that there is just | 620 // Note: cell_count might be zero, meaning that there is just |
459 // a DataLayout header, with no extra cells. | 621 // a DataLayout header, with no extra cells. |
460 assert(cell_count >= 0, "sanity"); | 622 assert(cell_count >= 0, "sanity"); |
461 return DataLayout::compute_size_in_bytes(cell_count); | 623 return DataLayout::compute_size_in_bytes(cell_count); |
497 object_size += extra_data_count * DataLayout::compute_size_in_bytes(0); | 659 object_size += extra_data_count * DataLayout::compute_size_in_bytes(0); |
498 | 660 |
499 // Add a cell to record information about modified arguments. | 661 // Add a cell to record information about modified arguments. |
500 int arg_size = method->size_of_parameters(); | 662 int arg_size = method->size_of_parameters(); |
501 object_size += DataLayout::compute_size_in_bytes(arg_size+1); | 663 object_size += DataLayout::compute_size_in_bytes(arg_size+1); |
664 | |
502 return object_size; | 665 return object_size; |
503 } | 666 } |
504 | 667 |
505 // Compute the size of the MethodData* necessary to store | 668 // Compute the size of the MethodData* necessary to store |
506 // profiling information about a given method. Size is in words | 669 // profiling information about a given method. Size is in words |
532 cell_count = BitData::static_cell_count(); | 695 cell_count = BitData::static_cell_count(); |
533 tag = DataLayout::bit_data_tag; | 696 tag = DataLayout::bit_data_tag; |
534 } | 697 } |
535 break; | 698 break; |
536 case Bytecodes::_invokespecial: | 699 case Bytecodes::_invokespecial: |
537 case Bytecodes::_invokestatic: | 700 case Bytecodes::_invokestatic: { |
538 cell_count = CounterData::static_cell_count(); | 701 int counter_data_cell_count = CounterData::static_cell_count(); |
539 tag = DataLayout::counter_data_tag; | 702 if (profile_arguments_for_invoke(stream->method(), stream->bci())) { |
703 cell_count = CallTypeData::compute_cell_count(stream); | |
704 } else { | |
705 cell_count = counter_data_cell_count; | |
706 } | |
707 if (cell_count > counter_data_cell_count) { | |
708 tag = DataLayout::call_type_data_tag; | |
709 } else { | |
710 tag = DataLayout::counter_data_tag; | |
711 } | |
540 break; | 712 break; |
713 } | |
541 case Bytecodes::_goto: | 714 case Bytecodes::_goto: |
542 case Bytecodes::_goto_w: | 715 case Bytecodes::_goto_w: |
543 case Bytecodes::_jsr: | 716 case Bytecodes::_jsr: |
544 case Bytecodes::_jsr_w: | 717 case Bytecodes::_jsr_w: |
545 cell_count = JumpData::static_cell_count(); | 718 cell_count = JumpData::static_cell_count(); |
546 tag = DataLayout::jump_data_tag; | 719 tag = DataLayout::jump_data_tag; |
547 break; | 720 break; |
548 case Bytecodes::_invokevirtual: | 721 case Bytecodes::_invokevirtual: |
549 case Bytecodes::_invokeinterface: | 722 case Bytecodes::_invokeinterface: { |
550 cell_count = VirtualCallData::static_cell_count(); | 723 int virtual_call_data_cell_count = VirtualCallData::static_cell_count(); |
551 tag = DataLayout::virtual_call_data_tag; | 724 if (profile_arguments_for_invoke(stream->method(), stream->bci())) { |
725 cell_count = VirtualCallTypeData::compute_cell_count(stream); | |
726 } else { | |
727 cell_count = virtual_call_data_cell_count; | |
728 } | |
729 if (cell_count > virtual_call_data_cell_count) { | |
730 tag = DataLayout::virtual_call_type_data_tag; | |
731 } else { | |
732 tag = DataLayout::virtual_call_data_tag; | |
733 } | |
552 break; | 734 break; |
553 case Bytecodes::_invokedynamic: | 735 } |
736 case Bytecodes::_invokedynamic: { | |
554 // %%% should make a type profile for any invokedynamic that takes a ref argument | 737 // %%% should make a type profile for any invokedynamic that takes a ref argument |
555 cell_count = CounterData::static_cell_count(); | 738 int counter_data_cell_count = CounterData::static_cell_count(); |
556 tag = DataLayout::counter_data_tag; | 739 if (profile_arguments_for_invoke(stream->method(), stream->bci())) { |
740 cell_count = CallTypeData::compute_cell_count(stream); | |
741 } else { | |
742 cell_count = counter_data_cell_count; | |
743 } | |
744 if (cell_count > counter_data_cell_count) { | |
745 tag = DataLayout::call_type_data_tag; | |
746 } else { | |
747 tag = DataLayout::counter_data_tag; | |
748 } | |
557 break; | 749 break; |
750 } | |
558 case Bytecodes::_ret: | 751 case Bytecodes::_ret: |
559 cell_count = RetData::static_cell_count(); | 752 cell_count = RetData::static_cell_count(); |
560 tag = DataLayout::ret_data_tag; | 753 tag = DataLayout::ret_data_tag; |
561 break; | 754 break; |
562 case Bytecodes::_ifeq: | 755 case Bytecodes::_ifeq: |
583 cell_count = MultiBranchData::compute_cell_count(stream); | 776 cell_count = MultiBranchData::compute_cell_count(stream); |
584 tag = DataLayout::multi_branch_data_tag; | 777 tag = DataLayout::multi_branch_data_tag; |
585 break; | 778 break; |
586 } | 779 } |
587 assert(tag == DataLayout::multi_branch_data_tag || | 780 assert(tag == DataLayout::multi_branch_data_tag || |
781 (MethodData::profile_arguments() && | |
782 (tag == DataLayout::call_type_data_tag || | |
783 tag == DataLayout::counter_data_tag || | |
784 tag == DataLayout::virtual_call_type_data_tag || | |
785 tag == DataLayout::virtual_call_data_tag)) || | |
588 cell_count == bytecode_cell_count(c), "cell counts must agree"); | 786 cell_count == bytecode_cell_count(c), "cell counts must agree"); |
589 if (cell_count >= 0) { | 787 if (cell_count >= 0) { |
590 assert(tag != DataLayout::no_tag, "bad tag"); | 788 assert(tag != DataLayout::no_tag, "bad tag"); |
591 assert(bytecode_has_profile(c), "agree w/ BHP"); | 789 assert(bytecode_has_profile(c), "agree w/ BHP"); |
592 data_layout->initialize(tag, stream->bci(), cell_count); | 790 data_layout->initialize(tag, stream->bci(), cell_count); |
629 return new BranchData(this); | 827 return new BranchData(this); |
630 case DataLayout::multi_branch_data_tag: | 828 case DataLayout::multi_branch_data_tag: |
631 return new MultiBranchData(this); | 829 return new MultiBranchData(this); |
632 case DataLayout::arg_info_data_tag: | 830 case DataLayout::arg_info_data_tag: |
633 return new ArgInfoData(this); | 831 return new ArgInfoData(this); |
832 case DataLayout::call_type_data_tag: | |
833 return new CallTypeData(this); | |
834 case DataLayout::virtual_call_type_data_tag: | |
835 return new VirtualCallTypeData(this); | |
634 }; | 836 }; |
635 } | 837 } |
636 | 838 |
637 // Iteration over data. | 839 // Iteration over data. |
638 ProfileData* MethodData::next_data(ProfileData* current) const { | 840 ProfileData* MethodData::next_data(ProfileData* current) const { |
896 | 1098 |
897 void MethodData::verify_data_on(outputStream* st) { | 1099 void MethodData::verify_data_on(outputStream* st) { |
898 NEEDS_CLEANUP; | 1100 NEEDS_CLEANUP; |
899 // not yet implemented. | 1101 // not yet implemented. |
900 } | 1102 } |
1103 | |
1104 bool MethodData::profile_jsr292(methodHandle m, int bci) { | |
1105 if (m->is_compiled_lambda_form()) { | |
1106 return true; | |
1107 } | |
1108 | |
1109 Bytecode_invoke inv(m , bci); | |
1110 return inv.is_invokedynamic() || inv.is_invokehandle(); | |
1111 } | |
1112 | |
1113 int MethodData::profile_arguments_flag() { | |
1114 return TypeProfileLevel; | |
1115 } | |
1116 | |
1117 bool MethodData::profile_arguments() { | |
1118 return profile_arguments_flag() > no_type_profile && profile_arguments_flag() <= type_profile_all; | |
1119 } | |
1120 | |
1121 bool MethodData::profile_arguments_jsr292_only() { | |
1122 return profile_arguments_flag() == type_profile_jsr292; | |
1123 } | |
1124 | |
1125 bool MethodData::profile_all_arguments() { | |
1126 return profile_arguments_flag() == type_profile_all; | |
1127 } | |
1128 | |
1129 bool MethodData::profile_arguments_for_invoke(methodHandle m, int bci) { | |
1130 if (!profile_arguments()) { | |
1131 return false; | |
1132 } | |
1133 | |
1134 if (profile_all_arguments()) { | |
1135 return true; | |
1136 } | |
1137 | |
1138 assert(profile_arguments_jsr292_only(), "inconsistent"); | |
1139 return profile_jsr292(m, bci); | |
1140 } | |
1141 |