comparison src/share/vm/oops/methodData.cpp @ 12962:5ccbab1c69f3

8026251: New type profiling points: parameters to methods Summary: x86 interpreter and c1 type profiling for parameters on method entries Reviewed-by: kvn, twisti
author roland
date Tue, 22 Oct 2013 09:51:47 +0200
parents ce0cc25bc5e2
children 6e1826d5c23e 2b8e28fdf503
comparison
equal deleted inserted replaced
12961:4748b3308cda 12962:5ccbab1c69f3
39 // 39 //
40 // Overlay for generic profiling data. 40 // Overlay for generic profiling data.
41 41
42 // Some types of data layouts need a length field. 42 // Some types of data layouts need a length field.
43 bool DataLayout::needs_array_len(u1 tag) { 43 bool DataLayout::needs_array_len(u1 tag) {
44 return (tag == multi_branch_data_tag) || (tag == arg_info_data_tag); 44 return (tag == multi_branch_data_tag) || (tag == arg_info_data_tag) || (tag == parameters_type_data_tag);
45 } 45 }
46 46
47 // Perform generic initialization of the data. More specific 47 // Perform generic initialization of the data. More specific
48 // initialization occurs in overrides of ProfileData::post_initialize. 48 // initialization occurs in overrides of ProfileData::post_initialize.
49 void DataLayout::initialize(u1 tag, u2 bci, int cell_count) { 49 void DataLayout::initialize(u1 tag, u2 bci, int cell_count) {
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(Symbol* signature, int max) { 159 int TypeStackSlotEntries::compute_cell_count(Symbol* signature, bool include_receiver, int max) {
160 // Parameter profiling include the receiver
161 int args_count = include_receiver ? 1 : 0;
160 ResourceMark rm; 162 ResourceMark rm;
161 SignatureStream ss(signature); 163 SignatureStream ss(signature);
162 int args_count = MIN2(ss.reference_parameter_count(), max); 164 args_count += ss.reference_parameter_count();
165 args_count = MIN2(args_count, max);
163 return args_count * per_arg_cell_count; 166 return args_count * per_arg_cell_count;
164 } 167 }
165 168
166 int TypeEntriesAtCall::compute_cell_count(BytecodeStream* stream) { 169 int TypeEntriesAtCall::compute_cell_count(BytecodeStream* stream) {
167 assert(Bytecodes::is_invoke(stream->code()), "should be invoke"); 170 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"); 171 assert(TypeStackSlotEntries::per_arg_count() > ReturnTypeEntry::static_cell_count(), "code to test for arguments/results broken");
169 Bytecode_invoke inv(stream->method(), stream->bci()); 172 Bytecode_invoke inv(stream->method(), stream->bci());
170 int args_cell = 0; 173 int args_cell = 0;
171 if (arguments_profiling_enabled()) { 174 if (arguments_profiling_enabled()) {
172 args_cell = TypeStackSlotEntries::compute_cell_count(inv.signature(), TypeProfileArgsLimit); 175 args_cell = TypeStackSlotEntries::compute_cell_count(inv.signature(), false, TypeProfileArgsLimit);
173 } 176 }
174 int ret_cell = 0; 177 int ret_cell = 0;
175 if (return_profiling_enabled() && (inv.result_type() == T_OBJECT || inv.result_type() == T_ARRAY)) { 178 if (return_profiling_enabled() && (inv.result_type() == T_OBJECT || inv.result_type() == T_ARRAY)) {
176 ret_cell = ReturnTypeEntry::static_cell_count(); 179 ret_cell = ReturnTypeEntry::static_cell_count();
177 } 180 }
210 int total() { lazy_iterate_parameters(); return _size; } 213 int total() { lazy_iterate_parameters(); return _size; }
211 214
212 int off_at(int i) const { return _offsets.at(i); } 215 int off_at(int i) const { return _offsets.at(i); }
213 }; 216 };
214 217
215 void TypeStackSlotEntries::post_initialize(Symbol* signature, bool has_receiver) { 218 void TypeStackSlotEntries::post_initialize(Symbol* signature, bool has_receiver, bool include_receiver) {
216 ResourceMark rm; 219 ResourceMark rm;
217 ArgumentOffsetComputer aos(signature, _number_of_entries); 220 int start = 0;
221 // Parameter profiling include the receiver
222 if (include_receiver && has_receiver) {
223 set_stack_slot(0, 0);
224 set_type(0, type_none());
225 start += 1;
226 }
227 ArgumentOffsetComputer aos(signature, _number_of_entries-start);
218 aos.total(); 228 aos.total();
219 for (int i = 0; i < _number_of_entries; i++) { 229 for (int i = start; i < _number_of_entries; i++) {
220 set_stack_slot(i, aos.off_at(i) + (has_receiver ? 1 : 0)); 230 set_stack_slot(i, aos.off_at(i-start) + (has_receiver ? 1 : 0));
221 set_type(i, type_none()); 231 set_type(i, type_none());
222 } 232 }
223 } 233 }
224 234
225 void CallTypeData::post_initialize(BytecodeStream* stream, MethodData* mdo) { 235 void CallTypeData::post_initialize(BytecodeStream* stream, MethodData* mdo) {
232 ResourceMark rm; 242 ResourceMark rm;
233 int count = MIN2(ss.reference_parameter_count(), (int)TypeProfileArgsLimit); 243 int count = MIN2(ss.reference_parameter_count(), (int)TypeProfileArgsLimit);
234 assert(count > 0, "room for args type but none found?"); 244 assert(count > 0, "room for args type but none found?");
235 check_number_of_arguments(count); 245 check_number_of_arguments(count);
236 #endif 246 #endif
237 _args.post_initialize(inv.signature(), inv.has_receiver()); 247 _args.post_initialize(inv.signature(), inv.has_receiver(), false);
238 } 248 }
239 249
240 if (has_return()) { 250 if (has_return()) {
241 assert(inv.result_type() == T_OBJECT || inv.result_type() == T_ARRAY, "room for a ret type but doesn't return obj?"); 251 assert(inv.result_type() == T_OBJECT || inv.result_type() == T_ARRAY, "room for a ret type but doesn't return obj?");
242 _ret.post_initialize(); 252 _ret.post_initialize();
253 SignatureStream ss(inv.signature()); 263 SignatureStream ss(inv.signature());
254 int count = MIN2(ss.reference_parameter_count(), (int)TypeProfileArgsLimit); 264 int count = MIN2(ss.reference_parameter_count(), (int)TypeProfileArgsLimit);
255 assert(count > 0, "room for args type but none found?"); 265 assert(count > 0, "room for args type but none found?");
256 check_number_of_arguments(count); 266 check_number_of_arguments(count);
257 #endif 267 #endif
258 _args.post_initialize(inv.signature(), inv.has_receiver()); 268 _args.post_initialize(inv.signature(), inv.has_receiver(), false);
259 } 269 }
260 270
261 if (has_return()) { 271 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?"); 272 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(); 273 _ret.post_initialize();
577 } 587 }
578 st->cr(); 588 st->cr();
579 } 589 }
580 590
581 #endif 591 #endif
592
593 int ParametersTypeData::compute_cell_count(Method* m) {
594 if (!MethodData::profile_parameters_for_method(m)) {
595 return 0;
596 }
597 int max = TypeProfileParmsLimit == -1 ? INT_MAX : TypeProfileParmsLimit;
598 int obj_args = TypeStackSlotEntries::compute_cell_count(m->signature(), !m->is_static(), max);
599 if (obj_args > 0) {
600 return obj_args + 1; // 1 cell for array len
601 }
602 return 0;
603 }
604
605 void ParametersTypeData::post_initialize(BytecodeStream* stream, MethodData* mdo) {
606 _parameters.post_initialize(mdo->method()->signature(), !mdo->method()->is_static(), true);
607 }
608
609 bool ParametersTypeData::profiling_enabled() {
610 return MethodData::profile_parameters();
611 }
612
613 #ifndef PRODUCT
614 void ParametersTypeData::print_data_on(outputStream* st) const {
615 st->print("parameter types");
616 _parameters.print_data_on(st);
617 }
618 #endif
619
582 // ================================================================== 620 // ==================================================================
583 // MethodData* 621 // MethodData*
584 // 622 //
585 // A MethodData* holds information which has been collected about 623 // A MethodData* holds information which has been collected about
586 // a method. 624 // a method.
739 777
740 // Add a cell to record information about modified arguments. 778 // Add a cell to record information about modified arguments.
741 int arg_size = method->size_of_parameters(); 779 int arg_size = method->size_of_parameters();
742 object_size += DataLayout::compute_size_in_bytes(arg_size+1); 780 object_size += DataLayout::compute_size_in_bytes(arg_size+1);
743 781
782 // Reserve room for an area of the MDO dedicated to profiling of
783 // parameters
784 int args_cell = ParametersTypeData::compute_cell_count(method());
785 if (args_cell > 0) {
786 object_size += DataLayout::compute_size_in_bytes(args_cell);
787 }
744 return object_size; 788 return object_size;
745 } 789 }
746 790
747 // Compute the size of the MethodData* necessary to store 791 // Compute the size of the MethodData* necessary to store
748 // profiling information about a given method. Size is in words 792 // profiling information about a given method. Size is in words
913 return new ArgInfoData(this); 957 return new ArgInfoData(this);
914 case DataLayout::call_type_data_tag: 958 case DataLayout::call_type_data_tag:
915 return new CallTypeData(this); 959 return new CallTypeData(this);
916 case DataLayout::virtual_call_type_data_tag: 960 case DataLayout::virtual_call_type_data_tag:
917 return new VirtualCallTypeData(this); 961 return new VirtualCallTypeData(this);
962 case DataLayout::parameters_type_data_tag:
963 return new ParametersTypeData(this);
918 }; 964 };
919 } 965 }
920 966
921 // Iteration over data. 967 // Iteration over data.
922 ProfileData* MethodData::next_data(ProfileData* current) const { 968 ProfileData* MethodData::next_data(ProfileData* current) const {
933 ProfileData* data; 979 ProfileData* data;
934 for (data = first_data(); is_valid(data); data = next_data(data)) { 980 for (data = first_data(); is_valid(data); data = next_data(data)) {
935 stream->set_start(data->bci()); 981 stream->set_start(data->bci());
936 stream->next(); 982 stream->next();
937 data->post_initialize(stream, this); 983 data->post_initialize(stream, this);
984 }
985 if (_parameters_type_data_di != -1) {
986 parameters_type_data()->post_initialize(NULL, this);
938 } 987 }
939 } 988 }
940 989
941 // Initialize the MethodData* corresponding to a given method. 990 // Initialize the MethodData* corresponding to a given method.
942 MethodData::MethodData(methodHandle method, int size, TRAPS) { 991 MethodData::MethodData(methodHandle method, int size, TRAPS) {
973 DataLayout *dp = data_layout_at(data_size + extra_size); 1022 DataLayout *dp = data_layout_at(data_size + extra_size);
974 1023
975 int arg_size = method->size_of_parameters(); 1024 int arg_size = method->size_of_parameters();
976 dp->initialize(DataLayout::arg_info_data_tag, 0, arg_size+1); 1025 dp->initialize(DataLayout::arg_info_data_tag, 0, arg_size+1);
977 1026
978 object_size += extra_size + DataLayout::compute_size_in_bytes(arg_size+1); 1027 int arg_data_size = DataLayout::compute_size_in_bytes(arg_size+1);
1028 object_size += extra_size + arg_data_size;
1029
1030 int args_cell = ParametersTypeData::compute_cell_count(method());
1031 // If we are profiling parameters, we reserver an area near the end
1032 // of the MDO after the slots for bytecodes (because there's no bci
1033 // for method entry so they don't fit with the framework for the
1034 // profiling of bytecodes). We store the offset within the MDO of
1035 // this area (or -1 if no parameter is profiled)
1036 if (args_cell > 0) {
1037 object_size += DataLayout::compute_size_in_bytes(args_cell);
1038 _parameters_type_data_di = data_size + extra_size + arg_data_size;
1039 DataLayout *dp = data_layout_at(data_size + extra_size + arg_data_size);
1040 dp->initialize(DataLayout::parameters_type_data_tag, 0, args_cell);
1041 } else {
1042 _parameters_type_data_di = -1;
1043 }
979 1044
980 // Set an initial hint. Don't use set_hint_di() because 1045 // Set an initial hint. Don't use set_hint_di() because
981 // first_di() may be out of bounds if data_size is 0. 1046 // first_di() may be out of bounds if data_size is 0.
982 // In that situation, _hint_di is never used, but at 1047 // In that situation, _hint_di is never used, but at
983 // least well-defined. 1048 // least well-defined.
1132 1197
1133 #ifndef PRODUCT 1198 #ifndef PRODUCT
1134 void MethodData::print_data_on(outputStream* st) const { 1199 void MethodData::print_data_on(outputStream* st) const {
1135 ResourceMark rm; 1200 ResourceMark rm;
1136 ProfileData* data = first_data(); 1201 ProfileData* data = first_data();
1202 if (_parameters_type_data_di != -1) {
1203 parameters_type_data()->print_data_on(st);
1204 }
1137 for ( ; is_valid(data); data = next_data(data)) { 1205 for ( ; is_valid(data); data = next_data(data)) {
1138 st->print("%d", dp_to_di(data->dp())); 1206 st->print("%d", dp_to_di(data->dp()));
1139 st->fill_to(6); 1207 st->fill_to(6);
1140 data->print_data_on(st); 1208 data->print_data_on(st);
1141 } 1209 }
1220 assert(profile_arguments_jsr292_only(), "inconsistent"); 1288 assert(profile_arguments_jsr292_only(), "inconsistent");
1221 return profile_jsr292(m, bci); 1289 return profile_jsr292(m, bci);
1222 } 1290 }
1223 1291
1224 int MethodData::profile_return_flag() { 1292 int MethodData::profile_return_flag() {
1225 return TypeProfileLevel / 10; 1293 return (TypeProfileLevel % 100) / 10;
1226 } 1294 }
1227 1295
1228 bool MethodData::profile_return() { 1296 bool MethodData::profile_return() {
1229 return profile_return_flag() > no_type_profile && profile_return_flag() <= type_profile_all; 1297 return profile_return_flag() > no_type_profile && profile_return_flag() <= type_profile_all;
1230 } 1298 }
1247 } 1315 }
1248 1316
1249 assert(profile_return_jsr292_only(), "inconsistent"); 1317 assert(profile_return_jsr292_only(), "inconsistent");
1250 return profile_jsr292(m, bci); 1318 return profile_jsr292(m, bci);
1251 } 1319 }
1320
1321 int MethodData::profile_parameters_flag() {
1322 return TypeProfileLevel / 100;
1323 }
1324
1325 bool MethodData::profile_parameters() {
1326 return profile_parameters_flag() > no_type_profile && profile_parameters_flag() <= type_profile_all;
1327 }
1328
1329 bool MethodData::profile_parameters_jsr292_only() {
1330 return profile_parameters_flag() == type_profile_jsr292;
1331 }
1332
1333 bool MethodData::profile_all_parameters() {
1334 return profile_parameters_flag() == type_profile_all;
1335 }
1336
1337 bool MethodData::profile_parameters_for_method(methodHandle m) {
1338 if (!profile_parameters()) {
1339 return false;
1340 }
1341
1342 if (profile_all_parameters()) {
1343 return true;
1344 }
1345
1346 assert(profile_parameters_jsr292_only(), "inconsistent");
1347 return m->is_compiled_lambda_form();
1348 }