src/share/vm/oops/methodData.cpp
Index Unified diffs Context diffs Sdiffs Patch New Old Previous File Next File hotspot Cdiff src/share/vm/oops/methodData.cpp

src/share/vm/oops/methodData.cpp

Print this page
rev 5403 : 8023657: New type profiling points: arguments to call
Summary: x86 interpreter and c1 type profiling for arguments at calls
Reviewed-by: kvn, twisti
rev 5404 : 8026054: New type profiling points: type of return values at calls
Summary: x86 interpreter and c1 type profiling for return values at calls
Reviewed-by:
rev 5405 : imported patch kvn
rev 5406 : imported patch twisti
rev 5407 : imported patch fixreturn

*** 154,173 **** print_shared(st, "JumpData"); st->print_cr("taken(%u) displacement(%d)", taken(), displacement()); } #endif // !PRODUCT ! int TypeStackSlotEntries::compute_cell_count(BytecodeStream* stream) { ! int max = TypeProfileArgsLimit; ! assert(Bytecodes::is_invoke(stream->code()), "should be invoke"); ! Bytecode_invoke inv(stream->method(), stream->bci()); ! ResourceMark rm; ! SignatureStream ss(inv.signature()); int args_count = MIN2(ss.reference_parameter_count(), max); ! return args_count * per_arg_cell_count + (args_count > 0 ? header_cell_count() : 0); } class ArgumentOffsetComputer : public SignatureInfo { private: int _max; --- 154,188 ---- print_shared(st, "JumpData"); st->print_cr("taken(%u) displacement(%d)", taken(), displacement()); } #endif // !PRODUCT ! int TypeStackSlotEntries::compute_cell_count(Symbol* signature, int max) { ResourceMark rm; ! SignatureStream ss(signature); int args_count = MIN2(ss.reference_parameter_count(), max); + return args_count * per_arg_cell_count; + } ! int TypeEntriesAtCall::compute_cell_count(BytecodeStream* stream) { ! assert(Bytecodes::is_invoke(stream->code()), "should be invoke"); ! assert(TypeStackSlotEntries::per_arg_count() > ReturnTypeEntry::static_cell_count(), "code to test for arguments/results broken"); ! Bytecode_invoke inv(stream->method(), stream->bci()); ! int args_cell = 0; ! if (arguments_profiling_enabled()) { ! args_cell = TypeStackSlotEntries::compute_cell_count(inv.signature(), TypeProfileArgsLimit); ! } ! int ret_cell = 0; ! if (return_profiling_enabled() && (inv.result_type() == T_OBJECT || inv.result_type() == T_ARRAY)) { ! ret_cell = ReturnTypeEntry::static_cell_count(); ! } ! int header_cell = 0; ! if (args_cell + ret_cell > 0) { ! header_cell = header_cell_count(); ! } ! ! return header_cell + args_cell + ret_cell; } class ArgumentOffsetComputer : public SignatureInfo { private: int _max;
*** 195,242 **** int total() { lazy_iterate_parameters(); return _size; } int off_at(int i) const { return _offsets.at(i); } }; ! void TypeStackSlotEntries::post_initialize(BytecodeStream* stream) { ResourceMark rm; assert(Bytecodes::is_invoke(stream->code()), "should be invoke"); Bytecode_invoke inv(stream->method(), stream->bci()); #ifdef ASSERT SignatureStream ss(inv.signature()); int count = MIN2(ss.reference_parameter_count(), (int)TypeProfileArgsLimit); assert(count > 0, "room for args type but none found?"); check_number_of_arguments(count); #endif ! int start = 0; ! ArgumentOffsetComputer aos(inv.signature(), number_of_arguments()-start); ! aos.total(); ! bool has_receiver = inv.has_receiver(); ! for (int i = start; i < number_of_arguments(); i++) { ! set_stack_slot(i, aos.off_at(i-start) + (has_receiver ? 1 : 0)); ! set_type(i, type_none()); } } bool TypeEntries::is_loader_alive(BoolObjectClosure* is_alive_cl, intptr_t p) { return !is_type_none(p) && !((Klass*)klass_part(p))->is_loader_alive(is_alive_cl); } void TypeStackSlotEntries::clean_weak_klass_links(BoolObjectClosure* is_alive_cl) { ! for (int i = 0; i < number_of_arguments(); i++) { intptr_t p = type(i); if (is_loader_alive(is_alive_cl, p)) { set_type(i, type_none()); } } } ! bool TypeStackSlotEntries::arguments_profiling_enabled() { return MethodData::profile_arguments(); } #ifndef PRODUCT void TypeEntries::print_klass(outputStream* st, intptr_t k) { --- 210,297 ---- int total() { lazy_iterate_parameters(); return _size; } int off_at(int i) const { return _offsets.at(i); } }; ! void TypeStackSlotEntries::post_initialize(Symbol* signature, bool has_receiver) { ! ResourceMark rm; ! ArgumentOffsetComputer aos(signature, _number_of_entries); ! aos.total(); ! for (int i = 0; i < _number_of_entries; i++) { ! set_stack_slot(i, aos.off_at(i) + (has_receiver ? 1 : 0)); ! set_type(i, type_none()); ! } ! } ! ! void CallTypeData::post_initialize(BytecodeStream* stream, MethodData* mdo) { ! assert(Bytecodes::is_invoke(stream->code()), "should be invoke"); ! Bytecode_invoke inv(stream->method(), stream->bci()); ! ! SignatureStream ss(inv.signature()); ! if (has_arguments()) { ! #ifdef ASSERT ResourceMark rm; + int count = MIN2(ss.reference_parameter_count(), (int)TypeProfileArgsLimit); + assert(count > 0, "room for args type but none found?"); + check_number_of_arguments(count); + #endif + _args.post_initialize(inv.signature(), inv.has_receiver()); + } + + if (has_return()) { + assert(inv.result_type() == T_OBJECT || inv.result_type() == T_ARRAY, "room for a ret type but doesn't return obj?"); + _ret.post_initialize(); + } + } + void VirtualCallTypeData::post_initialize(BytecodeStream* stream, MethodData* mdo) { assert(Bytecodes::is_invoke(stream->code()), "should be invoke"); Bytecode_invoke inv(stream->method(), stream->bci()); + if (has_arguments()) { #ifdef ASSERT + ResourceMark rm; SignatureStream ss(inv.signature()); int count = MIN2(ss.reference_parameter_count(), (int)TypeProfileArgsLimit); assert(count > 0, "room for args type but none found?"); check_number_of_arguments(count); #endif + _args.post_initialize(inv.signature(), inv.has_receiver()); + } ! if (has_return()) { ! assert(inv.result_type() == T_OBJECT || inv.result_type() == T_ARRAY, "room for a ret type but doesn't return obj?"); ! _ret.post_initialize(); } } bool TypeEntries::is_loader_alive(BoolObjectClosure* is_alive_cl, intptr_t p) { return !is_type_none(p) && !((Klass*)klass_part(p))->is_loader_alive(is_alive_cl); } void TypeStackSlotEntries::clean_weak_klass_links(BoolObjectClosure* is_alive_cl) { ! for (int i = 0; i < _number_of_entries; i++) { intptr_t p = type(i); if (is_loader_alive(is_alive_cl, p)) { set_type(i, type_none()); } } } ! void ReturnTypeEntry::clean_weak_klass_links(BoolObjectClosure* is_alive_cl) { ! intptr_t p = type(); ! if (is_loader_alive(is_alive_cl, p)) { ! set_type(type_none()); ! } ! } ! ! bool TypeEntriesAtCall::return_profiling_enabled() { ! return MethodData::profile_return(); ! } ! ! bool TypeEntriesAtCall::arguments_profiling_enabled() { return MethodData::profile_arguments(); } #ifndef PRODUCT void TypeEntries::print_klass(outputStream* st, intptr_t k) {
*** 251,278 **** st->print(" (null seen)"); } } void TypeStackSlotEntries::print_data_on(outputStream* st) const { ! _pd->tab(st, true); ! st->print("argument types"); ! for (int i = 0; i < number_of_arguments(); i++) { _pd->tab(st); st->print("%d: stack(%u) ", i, stack_slot(i)); print_klass(st, type(i)); st->cr(); } } void CallTypeData::print_data_on(outputStream* st) const { CounterData::print_data_on(st); _args.print_data_on(st); } void VirtualCallTypeData::print_data_on(outputStream* st) const { VirtualCallData::print_data_on(st); _args.print_data_on(st); } #endif // ================================================================== // ReceiverTypeData --- 306,355 ---- st->print(" (null seen)"); } } void TypeStackSlotEntries::print_data_on(outputStream* st) const { ! for (int i = 0; i < _number_of_entries; i++) { _pd->tab(st); st->print("%d: stack(%u) ", i, stack_slot(i)); print_klass(st, type(i)); st->cr(); } } + void ReturnTypeEntry::print_data_on(outputStream* st) const { + _pd->tab(st); + print_klass(st, type()); + st->cr(); + } + void CallTypeData::print_data_on(outputStream* st) const { CounterData::print_data_on(st); + if (has_arguments()) { + tab(st, true); + st->print("argument types"); _args.print_data_on(st); + } + if (has_return()) { + tab(st, true); + st->print("return type"); + _ret.print_data_on(st); + } } void VirtualCallTypeData::print_data_on(outputStream* st) const { VirtualCallData::print_data_on(st); + if (has_arguments()) { + tab(st, true); + st->print("argument types"); _args.print_data_on(st); + } + if (has_return()) { + tab(st, true); + st->print("return type"); + _ret.print_data_on(st); + } } #endif // ================================================================== // ReceiverTypeData
*** 528,538 **** } else { return BitData::static_cell_count(); } case Bytecodes::_invokespecial: case Bytecodes::_invokestatic: ! if (MethodData::profile_arguments()) { return variable_cell_count; } else { return CounterData::static_cell_count(); } case Bytecodes::_goto: --- 605,615 ---- } else { return BitData::static_cell_count(); } case Bytecodes::_invokespecial: case Bytecodes::_invokestatic: ! if (MethodData::profile_arguments() || MethodData::profile_return()) { return variable_cell_count; } else { return CounterData::static_cell_count(); } case Bytecodes::_goto:
*** 540,556 **** case Bytecodes::_jsr: case Bytecodes::_jsr_w: return JumpData::static_cell_count(); case Bytecodes::_invokevirtual: case Bytecodes::_invokeinterface: ! if (MethodData::profile_arguments()) { return variable_cell_count; } else { return VirtualCallData::static_cell_count(); } case Bytecodes::_invokedynamic: ! if (MethodData::profile_arguments()) { return variable_cell_count; } else { return CounterData::static_cell_count(); } case Bytecodes::_ret: --- 617,633 ---- case Bytecodes::_jsr: case Bytecodes::_jsr_w: return JumpData::static_cell_count(); case Bytecodes::_invokevirtual: case Bytecodes::_invokeinterface: ! if (MethodData::profile_arguments() || MethodData::profile_return()) { return variable_cell_count; } else { return VirtualCallData::static_cell_count(); } case Bytecodes::_invokedynamic: ! if (MethodData::profile_arguments() || MethodData::profile_return()) { return variable_cell_count; } else { return CounterData::static_cell_count(); } case Bytecodes::_ret:
*** 594,614 **** cell_count = MultiBranchData::compute_cell_count(stream); break; case Bytecodes::_invokespecial: case Bytecodes::_invokestatic: case Bytecodes::_invokedynamic: ! assert(MethodData::profile_arguments(), "should be collecting args profile"); ! if (profile_arguments_for_invoke(stream->method(), stream->bci())) { cell_count = CallTypeData::compute_cell_count(stream); } else { cell_count = CounterData::static_cell_count(); } break; case Bytecodes::_invokevirtual: case Bytecodes::_invokeinterface: { ! assert(MethodData::profile_arguments(), "should be collecting args profile"); ! if (profile_arguments_for_invoke(stream->method(), stream->bci())) { cell_count = VirtualCallTypeData::compute_cell_count(stream); } else { cell_count = VirtualCallData::static_cell_count(); } break; --- 671,693 ---- cell_count = MultiBranchData::compute_cell_count(stream); break; case Bytecodes::_invokespecial: case Bytecodes::_invokestatic: case Bytecodes::_invokedynamic: ! assert(MethodData::profile_arguments() || MethodData::profile_return(), "should be collecting args profile"); ! if (profile_arguments_for_invoke(stream->method(), stream->bci()) || ! profile_return_for_invoke(stream->method(), stream->bci())) { cell_count = CallTypeData::compute_cell_count(stream); } else { cell_count = CounterData::static_cell_count(); } break; case Bytecodes::_invokevirtual: case Bytecodes::_invokeinterface: { ! assert(MethodData::profile_arguments() || MethodData::profile_return(), "should be collecting args profile"); ! if (profile_arguments_for_invoke(stream->method(), stream->bci()) || ! profile_return_for_invoke(stream->method(), stream->bci())) { cell_count = VirtualCallTypeData::compute_cell_count(stream); } else { cell_count = VirtualCallData::static_cell_count(); } break;
*** 697,707 **** } break; case Bytecodes::_invokespecial: case Bytecodes::_invokestatic: { int counter_data_cell_count = CounterData::static_cell_count(); ! if (profile_arguments_for_invoke(stream->method(), stream->bci())) { cell_count = CallTypeData::compute_cell_count(stream); } else { cell_count = counter_data_cell_count; } if (cell_count > counter_data_cell_count) { --- 776,787 ---- } break; case Bytecodes::_invokespecial: case Bytecodes::_invokestatic: { int counter_data_cell_count = CounterData::static_cell_count(); ! if (profile_arguments_for_invoke(stream->method(), stream->bci()) || ! profile_return_for_invoke(stream->method(), stream->bci())) { cell_count = CallTypeData::compute_cell_count(stream); } else { cell_count = counter_data_cell_count; } if (cell_count > counter_data_cell_count) {
*** 719,729 **** tag = DataLayout::jump_data_tag; break; case Bytecodes::_invokevirtual: case Bytecodes::_invokeinterface: { int virtual_call_data_cell_count = VirtualCallData::static_cell_count(); ! if (profile_arguments_for_invoke(stream->method(), stream->bci())) { cell_count = VirtualCallTypeData::compute_cell_count(stream); } else { cell_count = virtual_call_data_cell_count; } if (cell_count > virtual_call_data_cell_count) { --- 799,810 ---- tag = DataLayout::jump_data_tag; break; case Bytecodes::_invokevirtual: case Bytecodes::_invokeinterface: { int virtual_call_data_cell_count = VirtualCallData::static_cell_count(); ! if (profile_arguments_for_invoke(stream->method(), stream->bci()) || ! profile_return_for_invoke(stream->method(), stream->bci())) { cell_count = VirtualCallTypeData::compute_cell_count(stream); } else { cell_count = virtual_call_data_cell_count; } if (cell_count > virtual_call_data_cell_count) {
*** 734,744 **** break; } case Bytecodes::_invokedynamic: { // %%% should make a type profile for any invokedynamic that takes a ref argument int counter_data_cell_count = CounterData::static_cell_count(); ! if (profile_arguments_for_invoke(stream->method(), stream->bci())) { cell_count = CallTypeData::compute_cell_count(stream); } else { cell_count = counter_data_cell_count; } if (cell_count > counter_data_cell_count) { --- 815,826 ---- break; } case Bytecodes::_invokedynamic: { // %%% should make a type profile for any invokedynamic that takes a ref argument int counter_data_cell_count = CounterData::static_cell_count(); ! if (profile_arguments_for_invoke(stream->method(), stream->bci()) || ! profile_return_for_invoke(stream->method(), stream->bci())) { cell_count = CallTypeData::compute_cell_count(stream); } else { cell_count = counter_data_cell_count; } if (cell_count > counter_data_cell_count) {
*** 776,786 **** cell_count = MultiBranchData::compute_cell_count(stream); tag = DataLayout::multi_branch_data_tag; break; } assert(tag == DataLayout::multi_branch_data_tag || ! (MethodData::profile_arguments() && (tag == DataLayout::call_type_data_tag || tag == DataLayout::counter_data_tag || tag == DataLayout::virtual_call_type_data_tag || tag == DataLayout::virtual_call_data_tag)) || cell_count == bytecode_cell_count(c), "cell counts must agree"); --- 858,868 ---- cell_count = MultiBranchData::compute_cell_count(stream); tag = DataLayout::multi_branch_data_tag; break; } assert(tag == DataLayout::multi_branch_data_tag || ! ((MethodData::profile_arguments() || MethodData::profile_return()) && (tag == DataLayout::call_type_data_tag || tag == DataLayout::counter_data_tag || tag == DataLayout::virtual_call_type_data_tag || tag == DataLayout::virtual_call_data_tag)) || cell_count == bytecode_cell_count(c), "cell counts must agree");
*** 1109,1119 **** Bytecode_invoke inv(m , bci); return inv.is_invokedynamic() || inv.is_invokehandle(); } int MethodData::profile_arguments_flag() { ! return TypeProfileLevel; } bool MethodData::profile_arguments() { return profile_arguments_flag() > no_type_profile && profile_arguments_flag() <= type_profile_all; } --- 1191,1201 ---- Bytecode_invoke inv(m , bci); return inv.is_invokedynamic() || inv.is_invokehandle(); } int MethodData::profile_arguments_flag() { ! return TypeProfileLevel % 10; } bool MethodData::profile_arguments() { return profile_arguments_flag() > no_type_profile && profile_arguments_flag() <= type_profile_all; }
*** 1137,1141 **** --- 1219,1251 ---- assert(profile_arguments_jsr292_only(), "inconsistent"); return profile_jsr292(m, bci); } + int MethodData::profile_return_flag() { + return TypeProfileLevel / 10; + } + + bool MethodData::profile_return() { + return profile_return_flag() > no_type_profile && profile_return_flag() <= type_profile_all; + } + + bool MethodData::profile_return_jsr292_only() { + return profile_return_flag() == type_profile_jsr292; + } + + bool MethodData::profile_all_return() { + return profile_return_flag() == type_profile_all; + } + + bool MethodData::profile_return_for_invoke(methodHandle m, int bci) { + if (!profile_return()) { + return false; + } + + if (profile_all_return()) { + return true; + } + + assert(profile_return_jsr292_only(), "inconsistent"); + return profile_jsr292(m, bci); + }
src/share/vm/oops/methodData.cpp
Index Unified diffs Context diffs Sdiffs Patch New Old Previous File Next File