--- old/src/share/vm/oops/methodData.cpp 2013-10-17 20:38:42.461740285 +0200 +++ new/src/share/vm/oops/methodData.cpp 2013-10-17 20:38:42.231899941 +0200 @@ -41,7 +41,7 @@ // 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); + return (tag == multi_branch_data_tag) || (tag == arg_info_data_tag) || (tag == parameters_type_data_tag); } // Perform generic initialization of the data. More specific @@ -156,10 +156,13 @@ } #endif // !PRODUCT -int TypeStackSlotEntries::compute_cell_count(Symbol* signature, int max) { +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); - int args_count = MIN2(ss.reference_parameter_count(), max); + args_count += ss.reference_parameter_count(); + args_count = MIN2(args_count, max); return args_count * per_arg_cell_count; } @@ -169,7 +172,7 @@ Bytecode_invoke inv(stream->method(), stream->bci()); int args_cell = 0; if (arguments_profiling_enabled()) { - args_cell = TypeStackSlotEntries::compute_cell_count(inv.signature(), TypeProfileArgsLimit); + 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)) { @@ -212,12 +215,19 @@ int off_at(int i) const { return _offsets.at(i); } }; -void TypeStackSlotEntries::post_initialize(Symbol* signature, bool has_receiver) { +void TypeStackSlotEntries::post_initialize(Symbol* signature, bool has_receiver, bool include_receiver) { ResourceMark rm; - ArgumentOffsetComputer aos(signature, _number_of_entries); + 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 = 0; i < _number_of_entries; i++) { - set_stack_slot(i, aos.off_at(i) + (has_receiver ? 1 : 0)); + 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()); } } @@ -234,7 +244,7 @@ assert(count > 0, "room for args type but none found?"); check_number_of_arguments(count); #endif - _args.post_initialize(inv.signature(), inv.has_receiver()); + _args.post_initialize(inv.signature(), inv.has_receiver(), false); } if (has_return()) { @@ -255,7 +265,7 @@ assert(count > 0, "room for args type but none found?"); check_number_of_arguments(count); #endif - _args.post_initialize(inv.signature(), inv.has_receiver()); + _args.post_initialize(inv.signature(), inv.has_receiver(), false); } if (has_return()) { @@ -579,6 +589,34 @@ } #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* // @@ -741,6 +779,12 @@ 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; } @@ -915,6 +959,8 @@ 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); }; } @@ -936,6 +982,9 @@ 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. @@ -975,7 +1024,23 @@ 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); + 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. @@ -1134,6 +1199,9 @@ 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); @@ -1222,7 +1290,7 @@ } int MethodData::profile_return_flag() { - return TypeProfileLevel / 10; + return (TypeProfileLevel % 100) / 10; } bool MethodData::profile_return() { @@ -1249,3 +1317,32 @@ 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(); +}