154 print_shared(st, "JumpData"); |
154 print_shared(st, "JumpData"); |
155 st->print_cr("taken(%u) displacement(%d)", taken(), displacement()); |
155 st->print_cr("taken(%u) displacement(%d)", taken(), displacement()); |
156 } |
156 } |
157 #endif // !PRODUCT |
157 #endif // !PRODUCT |
158 |
158 |
159 int TypeStackSlotEntries::compute_cell_count(BytecodeStream* stream) { |
159 int TypeStackSlotEntries::compute_cell_count(Symbol* signature, int max) { |
160 int max = TypeProfileArgsLimit; |
160 ResourceMark rm; |
|
161 SignatureStream ss(signature); |
|
162 int args_count = MIN2(ss.reference_parameter_count(), max); |
|
163 return args_count * per_arg_cell_count; |
|
164 } |
|
165 |
|
166 int TypeEntriesAtCall::compute_cell_count(BytecodeStream* stream) { |
161 assert(Bytecodes::is_invoke(stream->code()), "should be invoke"); |
167 assert(Bytecodes::is_invoke(stream->code()), "should be invoke"); |
|
168 assert(TypeStackSlotEntries::per_arg_count() > ReturnTypeEntry::static_cell_count(), "code to test for arguments/results broken"); |
162 Bytecode_invoke inv(stream->method(), stream->bci()); |
169 Bytecode_invoke inv(stream->method(), stream->bci()); |
163 |
170 int args_cell = 0; |
164 ResourceMark rm; |
171 if (arguments_profiling_enabled()) { |
165 SignatureStream ss(inv.signature()); |
172 args_cell = TypeStackSlotEntries::compute_cell_count(inv.signature(), TypeProfileArgsLimit); |
166 int args_count = MIN2(ss.reference_parameter_count(), max); |
173 } |
167 |
174 int ret_cell = 0; |
168 return args_count * per_arg_cell_count + (args_count > 0 ? header_cell_count() : 0); |
175 if (return_profiling_enabled() && (inv.result_type() == T_OBJECT || inv.result_type() == T_ARRAY)) { |
|
176 ret_cell = ReturnTypeEntry::static_cell_count(); |
|
177 } |
|
178 int header_cell = 0; |
|
179 if (args_cell + ret_cell > 0) { |
|
180 header_cell = header_cell_count(); |
|
181 } |
|
182 |
|
183 return header_cell + args_cell + ret_cell; |
169 } |
184 } |
170 |
185 |
171 class ArgumentOffsetComputer : public SignatureInfo { |
186 class ArgumentOffsetComputer : public SignatureInfo { |
172 private: |
187 private: |
173 int _max; |
188 int _max; |
195 int total() { lazy_iterate_parameters(); return _size; } |
210 int total() { lazy_iterate_parameters(); return _size; } |
196 |
211 |
197 int off_at(int i) const { return _offsets.at(i); } |
212 int off_at(int i) const { return _offsets.at(i); } |
198 }; |
213 }; |
199 |
214 |
200 void TypeStackSlotEntries::post_initialize(BytecodeStream* stream) { |
215 void TypeStackSlotEntries::post_initialize(Symbol* signature, bool has_receiver) { |
201 ResourceMark rm; |
216 ResourceMark rm; |
202 |
217 ArgumentOffsetComputer aos(signature, _number_of_entries); |
|
218 aos.total(); |
|
219 for (int i = 0; i < _number_of_entries; i++) { |
|
220 set_stack_slot(i, aos.off_at(i) + (has_receiver ? 1 : 0)); |
|
221 set_type(i, type_none()); |
|
222 } |
|
223 } |
|
224 |
|
225 void CallTypeData::post_initialize(BytecodeStream* stream, MethodData* mdo) { |
203 assert(Bytecodes::is_invoke(stream->code()), "should be invoke"); |
226 assert(Bytecodes::is_invoke(stream->code()), "should be invoke"); |
204 Bytecode_invoke inv(stream->method(), stream->bci()); |
227 Bytecode_invoke inv(stream->method(), stream->bci()); |
205 |
228 |
|
229 SignatureStream ss(inv.signature()); |
|
230 if (has_arguments()) { |
206 #ifdef ASSERT |
231 #ifdef ASSERT |
207 SignatureStream ss(inv.signature()); |
232 ResourceMark rm; |
208 int count = MIN2(ss.reference_parameter_count(), (int)TypeProfileArgsLimit); |
233 int count = MIN2(ss.reference_parameter_count(), (int)TypeProfileArgsLimit); |
209 assert(count > 0, "room for args type but none found?"); |
234 assert(count > 0, "room for args type but none found?"); |
210 check_number_of_arguments(count); |
235 check_number_of_arguments(count); |
211 #endif |
236 #endif |
212 |
237 _args.post_initialize(inv.signature(), inv.has_receiver()); |
213 int start = 0; |
238 } |
214 ArgumentOffsetComputer aos(inv.signature(), number_of_arguments()-start); |
239 |
215 aos.total(); |
240 if (has_return()) { |
216 bool has_receiver = inv.has_receiver(); |
241 assert(inv.result_type() == T_OBJECT || inv.result_type() == T_ARRAY, "room for a ret type but doesn't return obj?"); |
217 for (int i = start; i < number_of_arguments(); i++) { |
242 _ret.post_initialize(); |
218 set_stack_slot(i, aos.off_at(i-start) + (has_receiver ? 1 : 0)); |
243 } |
219 set_type(i, type_none()); |
244 } |
|
245 |
|
246 void VirtualCallTypeData::post_initialize(BytecodeStream* stream, MethodData* mdo) { |
|
247 assert(Bytecodes::is_invoke(stream->code()), "should be invoke"); |
|
248 Bytecode_invoke inv(stream->method(), stream->bci()); |
|
249 |
|
250 if (has_arguments()) { |
|
251 #ifdef ASSERT |
|
252 ResourceMark rm; |
|
253 SignatureStream ss(inv.signature()); |
|
254 int count = MIN2(ss.reference_parameter_count(), (int)TypeProfileArgsLimit); |
|
255 assert(count > 0, "room for args type but none found?"); |
|
256 check_number_of_arguments(count); |
|
257 #endif |
|
258 _args.post_initialize(inv.signature(), inv.has_receiver()); |
|
259 } |
|
260 |
|
261 if (has_return()) { |
|
262 assert(inv.result_type() == T_OBJECT || inv.result_type() == T_ARRAY, "room for a ret type but doesn't return obj?"); |
|
263 _ret.post_initialize(); |
220 } |
264 } |
221 } |
265 } |
222 |
266 |
223 bool TypeEntries::is_loader_alive(BoolObjectClosure* is_alive_cl, intptr_t p) { |
267 bool TypeEntries::is_loader_alive(BoolObjectClosure* is_alive_cl, intptr_t p) { |
224 return !is_type_none(p) && |
268 return !is_type_none(p) && |
225 !((Klass*)klass_part(p))->is_loader_alive(is_alive_cl); |
269 !((Klass*)klass_part(p))->is_loader_alive(is_alive_cl); |
226 } |
270 } |
227 |
271 |
228 void TypeStackSlotEntries::clean_weak_klass_links(BoolObjectClosure* is_alive_cl) { |
272 void TypeStackSlotEntries::clean_weak_klass_links(BoolObjectClosure* is_alive_cl) { |
229 for (int i = 0; i < number_of_arguments(); i++) { |
273 for (int i = 0; i < _number_of_entries; i++) { |
230 intptr_t p = type(i); |
274 intptr_t p = type(i); |
231 if (is_loader_alive(is_alive_cl, p)) { |
275 if (is_loader_alive(is_alive_cl, p)) { |
232 set_type(i, type_none()); |
276 set_type(i, type_none()); |
233 } |
277 } |
234 } |
278 } |
235 } |
279 } |
236 |
280 |
237 bool TypeStackSlotEntries::arguments_profiling_enabled() { |
281 void ReturnTypeEntry::clean_weak_klass_links(BoolObjectClosure* is_alive_cl) { |
|
282 intptr_t p = type(); |
|
283 if (is_loader_alive(is_alive_cl, p)) { |
|
284 set_type(type_none()); |
|
285 } |
|
286 } |
|
287 |
|
288 bool TypeEntriesAtCall::return_profiling_enabled() { |
|
289 return MethodData::profile_return(); |
|
290 } |
|
291 |
|
292 bool TypeEntriesAtCall::arguments_profiling_enabled() { |
238 return MethodData::profile_arguments(); |
293 return MethodData::profile_arguments(); |
239 } |
294 } |
240 |
295 |
241 #ifndef PRODUCT |
296 #ifndef PRODUCT |
242 void TypeEntries::print_klass(outputStream* st, intptr_t k) { |
297 void TypeEntries::print_klass(outputStream* st, intptr_t k) { |
251 st->print(" (null seen)"); |
306 st->print(" (null seen)"); |
252 } |
307 } |
253 } |
308 } |
254 |
309 |
255 void TypeStackSlotEntries::print_data_on(outputStream* st) const { |
310 void TypeStackSlotEntries::print_data_on(outputStream* st) const { |
256 _pd->tab(st, true); |
311 for (int i = 0; i < _number_of_entries; i++) { |
257 st->print("argument types"); |
|
258 for (int i = 0; i < number_of_arguments(); i++) { |
|
259 _pd->tab(st); |
312 _pd->tab(st); |
260 st->print("%d: stack(%u) ", i, stack_slot(i)); |
313 st->print("%d: stack(%u) ", i, stack_slot(i)); |
261 print_klass(st, type(i)); |
314 print_klass(st, type(i)); |
262 st->cr(); |
315 st->cr(); |
263 } |
316 } |
264 } |
317 } |
265 |
318 |
|
319 void ReturnTypeEntry::print_data_on(outputStream* st) const { |
|
320 _pd->tab(st); |
|
321 print_klass(st, type()); |
|
322 st->cr(); |
|
323 } |
|
324 |
266 void CallTypeData::print_data_on(outputStream* st) const { |
325 void CallTypeData::print_data_on(outputStream* st) const { |
267 CounterData::print_data_on(st); |
326 CounterData::print_data_on(st); |
268 _args.print_data_on(st); |
327 if (has_arguments()) { |
|
328 tab(st, true); |
|
329 st->print("argument types"); |
|
330 _args.print_data_on(st); |
|
331 } |
|
332 if (has_return()) { |
|
333 tab(st, true); |
|
334 st->print("return type"); |
|
335 _ret.print_data_on(st); |
|
336 } |
269 } |
337 } |
270 |
338 |
271 void VirtualCallTypeData::print_data_on(outputStream* st) const { |
339 void VirtualCallTypeData::print_data_on(outputStream* st) const { |
272 VirtualCallData::print_data_on(st); |
340 VirtualCallData::print_data_on(st); |
273 _args.print_data_on(st); |
341 if (has_arguments()) { |
|
342 tab(st, true); |
|
343 st->print("argument types"); |
|
344 _args.print_data_on(st); |
|
345 } |
|
346 if (has_return()) { |
|
347 tab(st, true); |
|
348 st->print("return type"); |
|
349 _ret.print_data_on(st); |
|
350 } |
274 } |
351 } |
275 #endif |
352 #endif |
276 |
353 |
277 // ================================================================== |
354 // ================================================================== |
278 // ReceiverTypeData |
355 // ReceiverTypeData |
540 case Bytecodes::_jsr: |
617 case Bytecodes::_jsr: |
541 case Bytecodes::_jsr_w: |
618 case Bytecodes::_jsr_w: |
542 return JumpData::static_cell_count(); |
619 return JumpData::static_cell_count(); |
543 case Bytecodes::_invokevirtual: |
620 case Bytecodes::_invokevirtual: |
544 case Bytecodes::_invokeinterface: |
621 case Bytecodes::_invokeinterface: |
545 if (MethodData::profile_arguments()) { |
622 if (MethodData::profile_arguments() || MethodData::profile_return()) { |
546 return variable_cell_count; |
623 return variable_cell_count; |
547 } else { |
624 } else { |
548 return VirtualCallData::static_cell_count(); |
625 return VirtualCallData::static_cell_count(); |
549 } |
626 } |
550 case Bytecodes::_invokedynamic: |
627 case Bytecodes::_invokedynamic: |
551 if (MethodData::profile_arguments()) { |
628 if (MethodData::profile_arguments() || MethodData::profile_return()) { |
552 return variable_cell_count; |
629 return variable_cell_count; |
553 } else { |
630 } else { |
554 return CounterData::static_cell_count(); |
631 return CounterData::static_cell_count(); |
555 } |
632 } |
556 case Bytecodes::_ret: |
633 case Bytecodes::_ret: |
594 cell_count = MultiBranchData::compute_cell_count(stream); |
671 cell_count = MultiBranchData::compute_cell_count(stream); |
595 break; |
672 break; |
596 case Bytecodes::_invokespecial: |
673 case Bytecodes::_invokespecial: |
597 case Bytecodes::_invokestatic: |
674 case Bytecodes::_invokestatic: |
598 case Bytecodes::_invokedynamic: |
675 case Bytecodes::_invokedynamic: |
599 assert(MethodData::profile_arguments(), "should be collecting args profile"); |
676 assert(MethodData::profile_arguments() || MethodData::profile_return(), "should be collecting args profile"); |
600 if (profile_arguments_for_invoke(stream->method(), stream->bci())) { |
677 if (profile_arguments_for_invoke(stream->method(), stream->bci()) || |
|
678 profile_return_for_invoke(stream->method(), stream->bci())) { |
601 cell_count = CallTypeData::compute_cell_count(stream); |
679 cell_count = CallTypeData::compute_cell_count(stream); |
602 } else { |
680 } else { |
603 cell_count = CounterData::static_cell_count(); |
681 cell_count = CounterData::static_cell_count(); |
604 } |
682 } |
605 break; |
683 break; |
606 case Bytecodes::_invokevirtual: |
684 case Bytecodes::_invokevirtual: |
607 case Bytecodes::_invokeinterface: { |
685 case Bytecodes::_invokeinterface: { |
608 assert(MethodData::profile_arguments(), "should be collecting args profile"); |
686 assert(MethodData::profile_arguments() || MethodData::profile_return(), "should be collecting args profile"); |
609 if (profile_arguments_for_invoke(stream->method(), stream->bci())) { |
687 if (profile_arguments_for_invoke(stream->method(), stream->bci()) || |
|
688 profile_return_for_invoke(stream->method(), stream->bci())) { |
610 cell_count = VirtualCallTypeData::compute_cell_count(stream); |
689 cell_count = VirtualCallTypeData::compute_cell_count(stream); |
611 } else { |
690 } else { |
612 cell_count = VirtualCallData::static_cell_count(); |
691 cell_count = VirtualCallData::static_cell_count(); |
613 } |
692 } |
614 break; |
693 break; |
719 tag = DataLayout::jump_data_tag; |
799 tag = DataLayout::jump_data_tag; |
720 break; |
800 break; |
721 case Bytecodes::_invokevirtual: |
801 case Bytecodes::_invokevirtual: |
722 case Bytecodes::_invokeinterface: { |
802 case Bytecodes::_invokeinterface: { |
723 int virtual_call_data_cell_count = VirtualCallData::static_cell_count(); |
803 int virtual_call_data_cell_count = VirtualCallData::static_cell_count(); |
724 if (profile_arguments_for_invoke(stream->method(), stream->bci())) { |
804 if (profile_arguments_for_invoke(stream->method(), stream->bci()) || |
|
805 profile_return_for_invoke(stream->method(), stream->bci())) { |
725 cell_count = VirtualCallTypeData::compute_cell_count(stream); |
806 cell_count = VirtualCallTypeData::compute_cell_count(stream); |
726 } else { |
807 } else { |
727 cell_count = virtual_call_data_cell_count; |
808 cell_count = virtual_call_data_cell_count; |
728 } |
809 } |
729 if (cell_count > virtual_call_data_cell_count) { |
810 if (cell_count > virtual_call_data_cell_count) { |
776 cell_count = MultiBranchData::compute_cell_count(stream); |
858 cell_count = MultiBranchData::compute_cell_count(stream); |
777 tag = DataLayout::multi_branch_data_tag; |
859 tag = DataLayout::multi_branch_data_tag; |
778 break; |
860 break; |
779 } |
861 } |
780 assert(tag == DataLayout::multi_branch_data_tag || |
862 assert(tag == DataLayout::multi_branch_data_tag || |
781 (MethodData::profile_arguments() && |
863 ((MethodData::profile_arguments() || MethodData::profile_return()) && |
782 (tag == DataLayout::call_type_data_tag || |
864 (tag == DataLayout::call_type_data_tag || |
783 tag == DataLayout::counter_data_tag || |
865 tag == DataLayout::counter_data_tag || |
784 tag == DataLayout::virtual_call_type_data_tag || |
866 tag == DataLayout::virtual_call_type_data_tag || |
785 tag == DataLayout::virtual_call_data_tag)) || |
867 tag == DataLayout::virtual_call_data_tag)) || |
786 cell_count == bytecode_cell_count(c), "cell counts must agree"); |
868 cell_count == bytecode_cell_count(c), "cell counts must agree"); |
1137 |
1219 |
1138 assert(profile_arguments_jsr292_only(), "inconsistent"); |
1220 assert(profile_arguments_jsr292_only(), "inconsistent"); |
1139 return profile_jsr292(m, bci); |
1221 return profile_jsr292(m, bci); |
1140 } |
1222 } |
1141 |
1223 |
|
1224 int MethodData::profile_return_flag() { |
|
1225 return TypeProfileLevel / 10; |
|
1226 } |
|
1227 |
|
1228 bool MethodData::profile_return() { |
|
1229 return profile_return_flag() > no_type_profile && profile_return_flag() <= type_profile_all; |
|
1230 } |
|
1231 |
|
1232 bool MethodData::profile_return_jsr292_only() { |
|
1233 return profile_return_flag() == type_profile_jsr292; |
|
1234 } |
|
1235 |
|
1236 bool MethodData::profile_all_return() { |
|
1237 return profile_return_flag() == type_profile_all; |
|
1238 } |
|
1239 |
|
1240 bool MethodData::profile_return_for_invoke(methodHandle m, int bci) { |
|
1241 if (!profile_return()) { |
|
1242 return false; |
|
1243 } |
|
1244 |
|
1245 if (profile_all_return()) { |
|
1246 return true; |
|
1247 } |
|
1248 |
|
1249 assert(profile_return_jsr292_only(), "inconsistent"); |
|
1250 return profile_jsr292(m, bci); |
|
1251 } |