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 |
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 |
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); |
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); |
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 |