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 } |