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 5462 : 8026251: New type profiling points: parameters to methods
Summary: x86 interpreter and c1 type profiling for parameters on method entries
Reviewed-by:

*** 39,49 **** // // Overlay for generic profiling data. // Some types of data layouts need a length field. bool DataLayout::needs_array_len(u1 tag) { ! return (tag == multi_branch_data_tag) || (tag == arg_info_data_tag); } // Perform generic initialization of the data. More specific // initialization occurs in overrides of ProfileData::post_initialize. void DataLayout::initialize(u1 tag, u2 bci, int cell_count) { --- 39,49 ---- // // Overlay for generic profiling data. // Some types of data layouts need a length field. bool DataLayout::needs_array_len(u1 tag) { ! return (tag == multi_branch_data_tag) || (tag == arg_info_data_tag) || (tag == parameters_type_data_tag); } // Perform generic initialization of the data. More specific // initialization occurs in overrides of ProfileData::post_initialize. void DataLayout::initialize(u1 tag, u2 bci, int cell_count) {
*** 154,177 **** 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(); } --- 154,180 ---- print_shared(st, "JumpData"); st->print_cr("taken(%u) displacement(%d)", taken(), displacement()); } #endif // !PRODUCT ! int TypeStackSlotEntries::compute_cell_count(Symbol* signature, bool include_receiver, int max) { ! // Parameter profiling include the receiver ! int args_count = include_receiver ? 1 : 0; ResourceMark rm; SignatureStream ss(signature); ! args_count += ss.reference_parameter_count(); ! args_count = MIN2(args_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(), false, 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(); }
*** 210,225 **** 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) { --- 213,235 ---- 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, bool include_receiver) { ResourceMark rm; ! int start = 0; ! // Parameter profiling include the receiver ! if (include_receiver && has_receiver) { ! set_stack_slot(0, 0); ! set_type(0, type_none()); ! start += 1; ! } ! ArgumentOffsetComputer aos(signature, _number_of_entries-start); aos.total(); ! for (int i = start; i < _number_of_entries; i++) { ! set_stack_slot(i, aos.off_at(i-start) + (has_receiver ? 1 : 0)); set_type(i, type_none()); } } void CallTypeData::post_initialize(BytecodeStream* stream, MethodData* mdo) {
*** 232,242 **** 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(); --- 242,252 ---- 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(), false); } 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();
*** 253,263 **** 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(); --- 263,273 ---- 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(), false); } 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();
*** 577,586 **** --- 587,624 ---- } st->cr(); } #endif + + int ParametersTypeData::compute_cell_count(Method* m) { + if (!MethodData::profile_parameters_for_method(m)) { + return 0; + } + int max = TypeProfileParmsLimit == -1 ? INT_MAX : TypeProfileParmsLimit; + int obj_args = TypeStackSlotEntries::compute_cell_count(m->signature(), !m->is_static(), max); + if (obj_args > 0) { + return obj_args + 1; // 1 cell for array len + } + return 0; + } + + void ParametersTypeData::post_initialize(BytecodeStream* stream, MethodData* mdo) { + _parameters.post_initialize(mdo->method()->signature(), !mdo->method()->is_static(), true); + } + + bool ParametersTypeData::profiling_enabled() { + return MethodData::profile_parameters(); + } + + #ifndef PRODUCT + void ParametersTypeData::print_data_on(outputStream* st) const { + st->print("parameter types"); + _parameters.print_data_on(st); + } + #endif + // ================================================================== // MethodData* // // A MethodData* holds information which has been collected about // a method.
*** 739,748 **** --- 777,792 ---- // Add a cell to record information about modified arguments. int arg_size = method->size_of_parameters(); object_size += DataLayout::compute_size_in_bytes(arg_size+1); + // Reserve room for an area of the MDO dedicated to profiling of + // parameters + int args_cell = ParametersTypeData::compute_cell_count(method()); + if (args_cell > 0) { + object_size += DataLayout::compute_size_in_bytes(args_cell); + } return object_size; } // Compute the size of the MethodData* necessary to store // profiling information about a given method. Size is in words
*** 913,922 **** --- 957,968 ---- return new ArgInfoData(this); case DataLayout::call_type_data_tag: return new CallTypeData(this); case DataLayout::virtual_call_type_data_tag: return new VirtualCallTypeData(this); + case DataLayout::parameters_type_data_tag: + return new ParametersTypeData(this); }; } // Iteration over data. ProfileData* MethodData::next_data(ProfileData* current) const {
*** 934,943 **** --- 980,992 ---- for (data = first_data(); is_valid(data); data = next_data(data)) { stream->set_start(data->bci()); stream->next(); data->post_initialize(stream, this); } + if (_parameters_type_data_di != -1) { + parameters_type_data()->post_initialize(NULL, this); + } } // Initialize the MethodData* corresponding to a given method. MethodData::MethodData(methodHandle method, int size, TRAPS) { No_Safepoint_Verifier no_safepoint; // init function atomic wrt GC
*** 973,983 **** DataLayout *dp = data_layout_at(data_size + extra_size); int arg_size = method->size_of_parameters(); dp->initialize(DataLayout::arg_info_data_tag, 0, arg_size+1); ! object_size += extra_size + DataLayout::compute_size_in_bytes(arg_size+1); // Set an initial hint. Don't use set_hint_di() because // first_di() may be out of bounds if data_size is 0. // In that situation, _hint_di is never used, but at // least well-defined. --- 1022,1048 ---- DataLayout *dp = data_layout_at(data_size + extra_size); int arg_size = method->size_of_parameters(); dp->initialize(DataLayout::arg_info_data_tag, 0, arg_size+1); ! int arg_data_size = DataLayout::compute_size_in_bytes(arg_size+1); ! object_size += extra_size + arg_data_size; ! ! int args_cell = ParametersTypeData::compute_cell_count(method()); ! // If we are profiling parameters, we reserver an area near the end ! // of the MDO after the slots for bytecodes (because there's no bci ! // for method entry so they don't fit with the framework for the ! // profiling of bytecodes). We store the offset within the MDO of ! // this area (or -1 if no parameter is profiled) ! if (args_cell > 0) { ! object_size += DataLayout::compute_size_in_bytes(args_cell); ! _parameters_type_data_di = data_size + extra_size + arg_data_size; ! DataLayout *dp = data_layout_at(data_size + extra_size + arg_data_size); ! dp->initialize(DataLayout::parameters_type_data_tag, 0, args_cell); ! } else { ! _parameters_type_data_di = -1; ! } // Set an initial hint. Don't use set_hint_di() because // first_di() may be out of bounds if data_size is 0. // In that situation, _hint_di is never used, but at // least well-defined.
*** 1132,1141 **** --- 1197,1209 ---- #ifndef PRODUCT void MethodData::print_data_on(outputStream* st) const { ResourceMark rm; ProfileData* data = first_data(); + if (_parameters_type_data_di != -1) { + parameters_type_data()->print_data_on(st); + } for ( ; is_valid(data); data = next_data(data)) { st->print("%d", dp_to_di(data->dp())); st->fill_to(6); data->print_data_on(st); }
*** 1220,1230 **** 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; } --- 1288,1298 ---- assert(profile_arguments_jsr292_only(), "inconsistent"); return profile_jsr292(m, bci); } int MethodData::profile_return_flag() { ! return (TypeProfileLevel % 100) / 10; } bool MethodData::profile_return() { return profile_return_flag() > no_type_profile && profile_return_flag() <= type_profile_all; }
*** 1247,1251 **** --- 1315,1348 ---- } assert(profile_return_jsr292_only(), "inconsistent"); return profile_jsr292(m, bci); } + + int MethodData::profile_parameters_flag() { + return TypeProfileLevel / 100; + } + + bool MethodData::profile_parameters() { + return profile_parameters_flag() > no_type_profile && profile_parameters_flag() <= type_profile_all; + } + + bool MethodData::profile_parameters_jsr292_only() { + return profile_parameters_flag() == type_profile_jsr292; + } + + bool MethodData::profile_all_parameters() { + return profile_parameters_flag() == type_profile_all; + } + + bool MethodData::profile_parameters_for_method(methodHandle m) { + if (!profile_parameters()) { + return false; + } + + if (profile_all_parameters()) { + return true; + } + + assert(profile_parameters_jsr292_only(), "inconsistent"); + return m->is_compiled_lambda_form(); + }
src/share/vm/oops/methodData.cpp
Index Unified diffs Context diffs Sdiffs Patch New Old Previous File Next File