Mercurial > hg > graal-compiler
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 } |