1.1 --- a/src/share/vm/oops/methodData.cpp Wed Oct 16 10:52:41 2013 +0200 1.2 +++ b/src/share/vm/oops/methodData.cpp Tue Nov 05 17:38:04 2013 -0800 1.3 @@ -41,7 +41,7 @@ 1.4 1.5 // Some types of data layouts need a length field. 1.6 bool DataLayout::needs_array_len(u1 tag) { 1.7 - return (tag == multi_branch_data_tag) || (tag == arg_info_data_tag); 1.8 + return (tag == multi_branch_data_tag) || (tag == arg_info_data_tag) || (tag == parameters_type_data_tag); 1.9 } 1.10 1.11 // Perform generic initialization of the data. More specific 1.12 @@ -56,6 +56,11 @@ 1.13 if (needs_array_len(tag)) { 1.14 set_cell_at(ArrayData::array_len_off_set, cell_count - 1); // -1 for header. 1.15 } 1.16 + if (tag == call_type_data_tag) { 1.17 + CallTypeData::initialize(this, cell_count); 1.18 + } else if (tag == virtual_call_type_data_tag) { 1.19 + VirtualCallTypeData::initialize(this, cell_count); 1.20 + } 1.21 } 1.22 1.23 void DataLayout::clean_weak_klass_links(BoolObjectClosure* cl) { 1.24 @@ -76,7 +81,7 @@ 1.25 } 1.26 1.27 #ifndef PRODUCT 1.28 -void ProfileData::print_shared(outputStream* st, const char* name) { 1.29 +void ProfileData::print_shared(outputStream* st, const char* name) const { 1.30 st->print("bci: %d", bci()); 1.31 st->fill_to(tab_width_one); 1.32 st->print("%s", name); 1.33 @@ -91,8 +96,8 @@ 1.34 st->print("flags(%d) ", flags); 1.35 } 1.36 1.37 -void ProfileData::tab(outputStream* st) { 1.38 - st->fill_to(tab_width_two); 1.39 +void ProfileData::tab(outputStream* st, bool first) const { 1.40 + st->fill_to(first ? tab_width_one : tab_width_two); 1.41 } 1.42 #endif // !PRODUCT 1.43 1.44 @@ -104,7 +109,7 @@ 1.45 1.46 1.47 #ifndef PRODUCT 1.48 -void BitData::print_data_on(outputStream* st) { 1.49 +void BitData::print_data_on(outputStream* st) const { 1.50 print_shared(st, "BitData"); 1.51 } 1.52 #endif // !PRODUCT 1.53 @@ -115,7 +120,7 @@ 1.54 // A CounterData corresponds to a simple counter. 1.55 1.56 #ifndef PRODUCT 1.57 -void CounterData::print_data_on(outputStream* st) { 1.58 +void CounterData::print_data_on(outputStream* st) const { 1.59 print_shared(st, "CounterData"); 1.60 st->print_cr("count(%u)", count()); 1.61 } 1.62 @@ -145,12 +150,217 @@ 1.63 } 1.64 1.65 #ifndef PRODUCT 1.66 -void JumpData::print_data_on(outputStream* st) { 1.67 +void JumpData::print_data_on(outputStream* st) const { 1.68 print_shared(st, "JumpData"); 1.69 st->print_cr("taken(%u) displacement(%d)", taken(), displacement()); 1.70 } 1.71 #endif // !PRODUCT 1.72 1.73 +int TypeStackSlotEntries::compute_cell_count(Symbol* signature, bool include_receiver, int max) { 1.74 + // Parameter profiling include the receiver 1.75 + int args_count = include_receiver ? 1 : 0; 1.76 + ResourceMark rm; 1.77 + SignatureStream ss(signature); 1.78 + args_count += ss.reference_parameter_count(); 1.79 + args_count = MIN2(args_count, max); 1.80 + return args_count * per_arg_cell_count; 1.81 +} 1.82 + 1.83 +int TypeEntriesAtCall::compute_cell_count(BytecodeStream* stream) { 1.84 + assert(Bytecodes::is_invoke(stream->code()), "should be invoke"); 1.85 + assert(TypeStackSlotEntries::per_arg_count() > ReturnTypeEntry::static_cell_count(), "code to test for arguments/results broken"); 1.86 + Bytecode_invoke inv(stream->method(), stream->bci()); 1.87 + int args_cell = 0; 1.88 + if (arguments_profiling_enabled()) { 1.89 + args_cell = TypeStackSlotEntries::compute_cell_count(inv.signature(), false, TypeProfileArgsLimit); 1.90 + } 1.91 + int ret_cell = 0; 1.92 + if (return_profiling_enabled() && (inv.result_type() == T_OBJECT || inv.result_type() == T_ARRAY)) { 1.93 + ret_cell = ReturnTypeEntry::static_cell_count(); 1.94 + } 1.95 + int header_cell = 0; 1.96 + if (args_cell + ret_cell > 0) { 1.97 + header_cell = header_cell_count(); 1.98 + } 1.99 + 1.100 + return header_cell + args_cell + ret_cell; 1.101 +} 1.102 + 1.103 +class ArgumentOffsetComputer : public SignatureInfo { 1.104 +private: 1.105 + int _max; 1.106 + GrowableArray<int> _offsets; 1.107 + 1.108 + void set(int size, BasicType type) { _size += size; } 1.109 + void do_object(int begin, int end) { 1.110 + if (_offsets.length() < _max) { 1.111 + _offsets.push(_size); 1.112 + } 1.113 + SignatureInfo::do_object(begin, end); 1.114 + } 1.115 + void do_array (int begin, int end) { 1.116 + if (_offsets.length() < _max) { 1.117 + _offsets.push(_size); 1.118 + } 1.119 + SignatureInfo::do_array(begin, end); 1.120 + } 1.121 + 1.122 +public: 1.123 + ArgumentOffsetComputer(Symbol* signature, int max) 1.124 + : SignatureInfo(signature), _max(max), _offsets(Thread::current(), max) { 1.125 + } 1.126 + 1.127 + int total() { lazy_iterate_parameters(); return _size; } 1.128 + 1.129 + int off_at(int i) const { return _offsets.at(i); } 1.130 +}; 1.131 + 1.132 +void TypeStackSlotEntries::post_initialize(Symbol* signature, bool has_receiver, bool include_receiver) { 1.133 + ResourceMark rm; 1.134 + int start = 0; 1.135 + // Parameter profiling include the receiver 1.136 + if (include_receiver && has_receiver) { 1.137 + set_stack_slot(0, 0); 1.138 + set_type(0, type_none()); 1.139 + start += 1; 1.140 + } 1.141 + ArgumentOffsetComputer aos(signature, _number_of_entries-start); 1.142 + aos.total(); 1.143 + for (int i = start; i < _number_of_entries; i++) { 1.144 + set_stack_slot(i, aos.off_at(i-start) + (has_receiver ? 1 : 0)); 1.145 + set_type(i, type_none()); 1.146 + } 1.147 +} 1.148 + 1.149 +void CallTypeData::post_initialize(BytecodeStream* stream, MethodData* mdo) { 1.150 + assert(Bytecodes::is_invoke(stream->code()), "should be invoke"); 1.151 + Bytecode_invoke inv(stream->method(), stream->bci()); 1.152 + 1.153 + SignatureStream ss(inv.signature()); 1.154 + if (has_arguments()) { 1.155 +#ifdef ASSERT 1.156 + ResourceMark rm; 1.157 + int count = MIN2(ss.reference_parameter_count(), (int)TypeProfileArgsLimit); 1.158 + assert(count > 0, "room for args type but none found?"); 1.159 + check_number_of_arguments(count); 1.160 +#endif 1.161 + _args.post_initialize(inv.signature(), inv.has_receiver(), false); 1.162 + } 1.163 + 1.164 + if (has_return()) { 1.165 + assert(inv.result_type() == T_OBJECT || inv.result_type() == T_ARRAY, "room for a ret type but doesn't return obj?"); 1.166 + _ret.post_initialize(); 1.167 + } 1.168 +} 1.169 + 1.170 +void VirtualCallTypeData::post_initialize(BytecodeStream* stream, MethodData* mdo) { 1.171 + assert(Bytecodes::is_invoke(stream->code()), "should be invoke"); 1.172 + Bytecode_invoke inv(stream->method(), stream->bci()); 1.173 + 1.174 + if (has_arguments()) { 1.175 +#ifdef ASSERT 1.176 + ResourceMark rm; 1.177 + SignatureStream ss(inv.signature()); 1.178 + int count = MIN2(ss.reference_parameter_count(), (int)TypeProfileArgsLimit); 1.179 + assert(count > 0, "room for args type but none found?"); 1.180 + check_number_of_arguments(count); 1.181 +#endif 1.182 + _args.post_initialize(inv.signature(), inv.has_receiver(), false); 1.183 + } 1.184 + 1.185 + if (has_return()) { 1.186 + assert(inv.result_type() == T_OBJECT || inv.result_type() == T_ARRAY, "room for a ret type but doesn't return obj?"); 1.187 + _ret.post_initialize(); 1.188 + } 1.189 +} 1.190 + 1.191 +bool TypeEntries::is_loader_alive(BoolObjectClosure* is_alive_cl, intptr_t p) { 1.192 + return !is_type_none(p) && 1.193 + !((Klass*)klass_part(p))->is_loader_alive(is_alive_cl); 1.194 +} 1.195 + 1.196 +void TypeStackSlotEntries::clean_weak_klass_links(BoolObjectClosure* is_alive_cl) { 1.197 + for (int i = 0; i < _number_of_entries; i++) { 1.198 + intptr_t p = type(i); 1.199 + if (is_loader_alive(is_alive_cl, p)) { 1.200 + set_type(i, type_none()); 1.201 + } 1.202 + } 1.203 +} 1.204 + 1.205 +void ReturnTypeEntry::clean_weak_klass_links(BoolObjectClosure* is_alive_cl) { 1.206 + intptr_t p = type(); 1.207 + if (is_loader_alive(is_alive_cl, p)) { 1.208 + set_type(type_none()); 1.209 + } 1.210 +} 1.211 + 1.212 +bool TypeEntriesAtCall::return_profiling_enabled() { 1.213 + return MethodData::profile_return(); 1.214 +} 1.215 + 1.216 +bool TypeEntriesAtCall::arguments_profiling_enabled() { 1.217 + return MethodData::profile_arguments(); 1.218 +} 1.219 + 1.220 +#ifndef PRODUCT 1.221 +void TypeEntries::print_klass(outputStream* st, intptr_t k) { 1.222 + if (is_type_none(k)) { 1.223 + st->print("none"); 1.224 + } else if (is_type_unknown(k)) { 1.225 + st->print("unknown"); 1.226 + } else { 1.227 + valid_klass(k)->print_value_on(st); 1.228 + } 1.229 + if (was_null_seen(k)) { 1.230 + st->print(" (null seen)"); 1.231 + } 1.232 +} 1.233 + 1.234 +void TypeStackSlotEntries::print_data_on(outputStream* st) const { 1.235 + for (int i = 0; i < _number_of_entries; i++) { 1.236 + _pd->tab(st); 1.237 + st->print("%d: stack(%u) ", i, stack_slot(i)); 1.238 + print_klass(st, type(i)); 1.239 + st->cr(); 1.240 + } 1.241 +} 1.242 + 1.243 +void ReturnTypeEntry::print_data_on(outputStream* st) const { 1.244 + _pd->tab(st); 1.245 + print_klass(st, type()); 1.246 + st->cr(); 1.247 +} 1.248 + 1.249 +void CallTypeData::print_data_on(outputStream* st) const { 1.250 + CounterData::print_data_on(st); 1.251 + if (has_arguments()) { 1.252 + tab(st, true); 1.253 + st->print("argument types"); 1.254 + _args.print_data_on(st); 1.255 + } 1.256 + if (has_return()) { 1.257 + tab(st, true); 1.258 + st->print("return type"); 1.259 + _ret.print_data_on(st); 1.260 + } 1.261 +} 1.262 + 1.263 +void VirtualCallTypeData::print_data_on(outputStream* st) const { 1.264 + VirtualCallData::print_data_on(st); 1.265 + if (has_arguments()) { 1.266 + tab(st, true); 1.267 + st->print("argument types"); 1.268 + _args.print_data_on(st); 1.269 + } 1.270 + if (has_return()) { 1.271 + tab(st, true); 1.272 + st->print("return type"); 1.273 + _ret.print_data_on(st); 1.274 + } 1.275 +} 1.276 +#endif 1.277 + 1.278 // ================================================================== 1.279 // ReceiverTypeData 1.280 // 1.281 @@ -169,7 +379,7 @@ 1.282 } 1.283 1.284 #ifndef PRODUCT 1.285 -void ReceiverTypeData::print_receiver_data_on(outputStream* st) { 1.286 +void ReceiverTypeData::print_receiver_data_on(outputStream* st) const { 1.287 uint row; 1.288 int entries = 0; 1.289 for (row = 0; row < row_limit(); row++) { 1.290 @@ -190,11 +400,11 @@ 1.291 } 1.292 } 1.293 } 1.294 -void ReceiverTypeData::print_data_on(outputStream* st) { 1.295 +void ReceiverTypeData::print_data_on(outputStream* st) const { 1.296 print_shared(st, "ReceiverTypeData"); 1.297 print_receiver_data_on(st); 1.298 } 1.299 -void VirtualCallData::print_data_on(outputStream* st) { 1.300 +void VirtualCallData::print_data_on(outputStream* st) const { 1.301 print_shared(st, "VirtualCallData"); 1.302 print_receiver_data_on(st); 1.303 } 1.304 @@ -251,7 +461,7 @@ 1.305 #endif // CC_INTERP 1.306 1.307 #ifndef PRODUCT 1.308 -void RetData::print_data_on(outputStream* st) { 1.309 +void RetData::print_data_on(outputStream* st) const { 1.310 print_shared(st, "RetData"); 1.311 uint row; 1.312 int entries = 0; 1.313 @@ -286,7 +496,7 @@ 1.314 } 1.315 1.316 #ifndef PRODUCT 1.317 -void BranchData::print_data_on(outputStream* st) { 1.318 +void BranchData::print_data_on(outputStream* st) const { 1.319 print_shared(st, "BranchData"); 1.320 st->print_cr("taken(%u) displacement(%d)", 1.321 taken(), displacement()); 1.322 @@ -360,7 +570,7 @@ 1.323 } 1.324 1.325 #ifndef PRODUCT 1.326 -void MultiBranchData::print_data_on(outputStream* st) { 1.327 +void MultiBranchData::print_data_on(outputStream* st) const { 1.328 print_shared(st, "MultiBranchData"); 1.329 st->print_cr("default_count(%u) displacement(%d)", 1.330 default_count(), default_displacement()); 1.331 @@ -374,7 +584,7 @@ 1.332 #endif 1.333 1.334 #ifndef PRODUCT 1.335 -void ArgInfoData::print_data_on(outputStream* st) { 1.336 +void ArgInfoData::print_data_on(outputStream* st) const { 1.337 print_shared(st, "ArgInfoData"); 1.338 int nargs = number_of_args(); 1.339 for (int i = 0; i < nargs; i++) { 1.340 @@ -384,6 +594,34 @@ 1.341 } 1.342 1.343 #endif 1.344 + 1.345 +int ParametersTypeData::compute_cell_count(Method* m) { 1.346 + if (!MethodData::profile_parameters_for_method(m)) { 1.347 + return 0; 1.348 + } 1.349 + int max = TypeProfileParmsLimit == -1 ? INT_MAX : TypeProfileParmsLimit; 1.350 + int obj_args = TypeStackSlotEntries::compute_cell_count(m->signature(), !m->is_static(), max); 1.351 + if (obj_args > 0) { 1.352 + return obj_args + 1; // 1 cell for array len 1.353 + } 1.354 + return 0; 1.355 +} 1.356 + 1.357 +void ParametersTypeData::post_initialize(BytecodeStream* stream, MethodData* mdo) { 1.358 + _parameters.post_initialize(mdo->method()->signature(), !mdo->method()->is_static(), true); 1.359 +} 1.360 + 1.361 +bool ParametersTypeData::profiling_enabled() { 1.362 + return MethodData::profile_parameters(); 1.363 +} 1.364 + 1.365 +#ifndef PRODUCT 1.366 +void ParametersTypeData::print_data_on(outputStream* st) const { 1.367 + st->print("parameter types"); 1.368 + _parameters.print_data_on(st); 1.369 +} 1.370 +#endif 1.371 + 1.372 // ================================================================== 1.373 // MethodData* 1.374 // 1.375 @@ -412,7 +650,11 @@ 1.376 } 1.377 case Bytecodes::_invokespecial: 1.378 case Bytecodes::_invokestatic: 1.379 - return CounterData::static_cell_count(); 1.380 + if (MethodData::profile_arguments() || MethodData::profile_return()) { 1.381 + return variable_cell_count; 1.382 + } else { 1.383 + return CounterData::static_cell_count(); 1.384 + } 1.385 case Bytecodes::_goto: 1.386 case Bytecodes::_goto_w: 1.387 case Bytecodes::_jsr: 1.388 @@ -420,9 +662,17 @@ 1.389 return JumpData::static_cell_count(); 1.390 case Bytecodes::_invokevirtual: 1.391 case Bytecodes::_invokeinterface: 1.392 - return VirtualCallData::static_cell_count(); 1.393 + if (MethodData::profile_arguments() || MethodData::profile_return()) { 1.394 + return variable_cell_count; 1.395 + } else { 1.396 + return VirtualCallData::static_cell_count(); 1.397 + } 1.398 case Bytecodes::_invokedynamic: 1.399 - return CounterData::static_cell_count(); 1.400 + if (MethodData::profile_arguments() || MethodData::profile_return()) { 1.401 + return variable_cell_count; 1.402 + } else { 1.403 + return CounterData::static_cell_count(); 1.404 + } 1.405 case Bytecodes::_ret: 1.406 return RetData::static_cell_count(); 1.407 case Bytecodes::_ifeq: 1.408 @@ -458,7 +708,36 @@ 1.409 return 0; 1.410 } 1.411 if (cell_count == variable_cell_count) { 1.412 - cell_count = MultiBranchData::compute_cell_count(stream); 1.413 + switch (stream->code()) { 1.414 + case Bytecodes::_lookupswitch: 1.415 + case Bytecodes::_tableswitch: 1.416 + cell_count = MultiBranchData::compute_cell_count(stream); 1.417 + break; 1.418 + case Bytecodes::_invokespecial: 1.419 + case Bytecodes::_invokestatic: 1.420 + case Bytecodes::_invokedynamic: 1.421 + assert(MethodData::profile_arguments() || MethodData::profile_return(), "should be collecting args profile"); 1.422 + if (profile_arguments_for_invoke(stream->method(), stream->bci()) || 1.423 + profile_return_for_invoke(stream->method(), stream->bci())) { 1.424 + cell_count = CallTypeData::compute_cell_count(stream); 1.425 + } else { 1.426 + cell_count = CounterData::static_cell_count(); 1.427 + } 1.428 + break; 1.429 + case Bytecodes::_invokevirtual: 1.430 + case Bytecodes::_invokeinterface: { 1.431 + assert(MethodData::profile_arguments() || MethodData::profile_return(), "should be collecting args profile"); 1.432 + if (profile_arguments_for_invoke(stream->method(), stream->bci()) || 1.433 + profile_return_for_invoke(stream->method(), stream->bci())) { 1.434 + cell_count = VirtualCallTypeData::compute_cell_count(stream); 1.435 + } else { 1.436 + cell_count = VirtualCallData::static_cell_count(); 1.437 + } 1.438 + break; 1.439 + } 1.440 + default: 1.441 + fatal("unexpected bytecode for var length profile data"); 1.442 + } 1.443 } 1.444 // Note: cell_count might be zero, meaning that there is just 1.445 // a DataLayout header, with no extra cells. 1.446 @@ -504,6 +783,13 @@ 1.447 // Add a cell to record information about modified arguments. 1.448 int arg_size = method->size_of_parameters(); 1.449 object_size += DataLayout::compute_size_in_bytes(arg_size+1); 1.450 + 1.451 + // Reserve room for an area of the MDO dedicated to profiling of 1.452 + // parameters 1.453 + int args_cell = ParametersTypeData::compute_cell_count(method()); 1.454 + if (args_cell > 0) { 1.455 + object_size += DataLayout::compute_size_in_bytes(args_cell); 1.456 + } 1.457 return object_size; 1.458 } 1.459 1.460 @@ -539,10 +825,21 @@ 1.461 } 1.462 break; 1.463 case Bytecodes::_invokespecial: 1.464 - case Bytecodes::_invokestatic: 1.465 - cell_count = CounterData::static_cell_count(); 1.466 - tag = DataLayout::counter_data_tag; 1.467 + case Bytecodes::_invokestatic: { 1.468 + int counter_data_cell_count = CounterData::static_cell_count(); 1.469 + if (profile_arguments_for_invoke(stream->method(), stream->bci()) || 1.470 + profile_return_for_invoke(stream->method(), stream->bci())) { 1.471 + cell_count = CallTypeData::compute_cell_count(stream); 1.472 + } else { 1.473 + cell_count = counter_data_cell_count; 1.474 + } 1.475 + if (cell_count > counter_data_cell_count) { 1.476 + tag = DataLayout::call_type_data_tag; 1.477 + } else { 1.478 + tag = DataLayout::counter_data_tag; 1.479 + } 1.480 break; 1.481 + } 1.482 case Bytecodes::_goto: 1.483 case Bytecodes::_goto_w: 1.484 case Bytecodes::_jsr: 1.485 @@ -551,15 +848,37 @@ 1.486 tag = DataLayout::jump_data_tag; 1.487 break; 1.488 case Bytecodes::_invokevirtual: 1.489 - case Bytecodes::_invokeinterface: 1.490 - cell_count = VirtualCallData::static_cell_count(); 1.491 - tag = DataLayout::virtual_call_data_tag; 1.492 + case Bytecodes::_invokeinterface: { 1.493 + int virtual_call_data_cell_count = VirtualCallData::static_cell_count(); 1.494 + if (profile_arguments_for_invoke(stream->method(), stream->bci()) || 1.495 + profile_return_for_invoke(stream->method(), stream->bci())) { 1.496 + cell_count = VirtualCallTypeData::compute_cell_count(stream); 1.497 + } else { 1.498 + cell_count = virtual_call_data_cell_count; 1.499 + } 1.500 + if (cell_count > virtual_call_data_cell_count) { 1.501 + tag = DataLayout::virtual_call_type_data_tag; 1.502 + } else { 1.503 + tag = DataLayout::virtual_call_data_tag; 1.504 + } 1.505 break; 1.506 - case Bytecodes::_invokedynamic: 1.507 + } 1.508 + case Bytecodes::_invokedynamic: { 1.509 // %%% should make a type profile for any invokedynamic that takes a ref argument 1.510 - cell_count = CounterData::static_cell_count(); 1.511 - tag = DataLayout::counter_data_tag; 1.512 + int counter_data_cell_count = CounterData::static_cell_count(); 1.513 + if (profile_arguments_for_invoke(stream->method(), stream->bci()) || 1.514 + profile_return_for_invoke(stream->method(), stream->bci())) { 1.515 + cell_count = CallTypeData::compute_cell_count(stream); 1.516 + } else { 1.517 + cell_count = counter_data_cell_count; 1.518 + } 1.519 + if (cell_count > counter_data_cell_count) { 1.520 + tag = DataLayout::call_type_data_tag; 1.521 + } else { 1.522 + tag = DataLayout::counter_data_tag; 1.523 + } 1.524 break; 1.525 + } 1.526 case Bytecodes::_ret: 1.527 cell_count = RetData::static_cell_count(); 1.528 tag = DataLayout::ret_data_tag; 1.529 @@ -590,6 +909,11 @@ 1.530 break; 1.531 } 1.532 assert(tag == DataLayout::multi_branch_data_tag || 1.533 + ((MethodData::profile_arguments() || MethodData::profile_return()) && 1.534 + (tag == DataLayout::call_type_data_tag || 1.535 + tag == DataLayout::counter_data_tag || 1.536 + tag == DataLayout::virtual_call_type_data_tag || 1.537 + tag == DataLayout::virtual_call_data_tag)) || 1.538 cell_count == bytecode_cell_count(c), "cell counts must agree"); 1.539 if (cell_count >= 0) { 1.540 assert(tag != DataLayout::no_tag, "bad tag"); 1.541 @@ -636,6 +960,12 @@ 1.542 return new MultiBranchData(this); 1.543 case DataLayout::arg_info_data_tag: 1.544 return new ArgInfoData(this); 1.545 + case DataLayout::call_type_data_tag: 1.546 + return new CallTypeData(this); 1.547 + case DataLayout::virtual_call_type_data_tag: 1.548 + return new VirtualCallTypeData(this); 1.549 + case DataLayout::parameters_type_data_tag: 1.550 + return new ParametersTypeData(this); 1.551 }; 1.552 } 1.553 1.554 @@ -657,6 +987,9 @@ 1.555 stream->next(); 1.556 data->post_initialize(stream, this); 1.557 } 1.558 + if (_parameters_type_data_di != -1) { 1.559 + parameters_type_data()->post_initialize(NULL, this); 1.560 + } 1.561 } 1.562 1.563 // Initialize the MethodData* corresponding to a given method. 1.564 @@ -696,7 +1029,23 @@ 1.565 int arg_size = method->size_of_parameters(); 1.566 dp->initialize(DataLayout::arg_info_data_tag, 0, arg_size+1); 1.567 1.568 - object_size += extra_size + DataLayout::compute_size_in_bytes(arg_size+1); 1.569 + int arg_data_size = DataLayout::compute_size_in_bytes(arg_size+1); 1.570 + object_size += extra_size + arg_data_size; 1.571 + 1.572 + int args_cell = ParametersTypeData::compute_cell_count(method()); 1.573 + // If we are profiling parameters, we reserver an area near the end 1.574 + // of the MDO after the slots for bytecodes (because there's no bci 1.575 + // for method entry so they don't fit with the framework for the 1.576 + // profiling of bytecodes). We store the offset within the MDO of 1.577 + // this area (or -1 if no parameter is profiled) 1.578 + if (args_cell > 0) { 1.579 + object_size += DataLayout::compute_size_in_bytes(args_cell); 1.580 + _parameters_type_data_di = data_size + extra_size + arg_data_size; 1.581 + DataLayout *dp = data_layout_at(data_size + extra_size + arg_data_size); 1.582 + dp->initialize(DataLayout::parameters_type_data_tag, 0, args_cell); 1.583 + } else { 1.584 + _parameters_type_data_di = -1; 1.585 + } 1.586 1.587 // Set an initial hint. Don't use set_hint_di() because 1.588 // first_di() may be out of bounds if data_size is 0. 1.589 @@ -855,6 +1204,9 @@ 1.590 void MethodData::print_data_on(outputStream* st) const { 1.591 ResourceMark rm; 1.592 ProfileData* data = first_data(); 1.593 + if (_parameters_type_data_di != -1) { 1.594 + parameters_type_data()->print_data_on(st); 1.595 + } 1.596 for ( ; is_valid(data); data = next_data(data)) { 1.597 st->print("%d", dp_to_di(data->dp())); 1.598 st->fill_to(6); 1.599 @@ -903,3 +1255,99 @@ 1.600 NEEDS_CLEANUP; 1.601 // not yet implemented. 1.602 } 1.603 + 1.604 +bool MethodData::profile_jsr292(methodHandle m, int bci) { 1.605 + if (m->is_compiled_lambda_form()) { 1.606 + return true; 1.607 + } 1.608 + 1.609 + Bytecode_invoke inv(m , bci); 1.610 + return inv.is_invokedynamic() || inv.is_invokehandle(); 1.611 +} 1.612 + 1.613 +int MethodData::profile_arguments_flag() { 1.614 + return TypeProfileLevel % 10; 1.615 +} 1.616 + 1.617 +bool MethodData::profile_arguments() { 1.618 + return profile_arguments_flag() > no_type_profile && profile_arguments_flag() <= type_profile_all; 1.619 +} 1.620 + 1.621 +bool MethodData::profile_arguments_jsr292_only() { 1.622 + return profile_arguments_flag() == type_profile_jsr292; 1.623 +} 1.624 + 1.625 +bool MethodData::profile_all_arguments() { 1.626 + return profile_arguments_flag() == type_profile_all; 1.627 +} 1.628 + 1.629 +bool MethodData::profile_arguments_for_invoke(methodHandle m, int bci) { 1.630 + if (!profile_arguments()) { 1.631 + return false; 1.632 + } 1.633 + 1.634 + if (profile_all_arguments()) { 1.635 + return true; 1.636 + } 1.637 + 1.638 + assert(profile_arguments_jsr292_only(), "inconsistent"); 1.639 + return profile_jsr292(m, bci); 1.640 +} 1.641 + 1.642 +int MethodData::profile_return_flag() { 1.643 + return (TypeProfileLevel % 100) / 10; 1.644 +} 1.645 + 1.646 +bool MethodData::profile_return() { 1.647 + return profile_return_flag() > no_type_profile && profile_return_flag() <= type_profile_all; 1.648 +} 1.649 + 1.650 +bool MethodData::profile_return_jsr292_only() { 1.651 + return profile_return_flag() == type_profile_jsr292; 1.652 +} 1.653 + 1.654 +bool MethodData::profile_all_return() { 1.655 + return profile_return_flag() == type_profile_all; 1.656 +} 1.657 + 1.658 +bool MethodData::profile_return_for_invoke(methodHandle m, int bci) { 1.659 + if (!profile_return()) { 1.660 + return false; 1.661 + } 1.662 + 1.663 + if (profile_all_return()) { 1.664 + return true; 1.665 + } 1.666 + 1.667 + assert(profile_return_jsr292_only(), "inconsistent"); 1.668 + return profile_jsr292(m, bci); 1.669 +} 1.670 + 1.671 +int MethodData::profile_parameters_flag() { 1.672 + return TypeProfileLevel / 100; 1.673 +} 1.674 + 1.675 +bool MethodData::profile_parameters() { 1.676 + return profile_parameters_flag() > no_type_profile && profile_parameters_flag() <= type_profile_all; 1.677 +} 1.678 + 1.679 +bool MethodData::profile_parameters_jsr292_only() { 1.680 + return profile_parameters_flag() == type_profile_jsr292; 1.681 +} 1.682 + 1.683 +bool MethodData::profile_all_parameters() { 1.684 + return profile_parameters_flag() == type_profile_all; 1.685 +} 1.686 + 1.687 +bool MethodData::profile_parameters_for_method(methodHandle m) { 1.688 + if (!profile_parameters()) { 1.689 + return false; 1.690 + } 1.691 + 1.692 + if (profile_all_parameters()) { 1.693 + return true; 1.694 + } 1.695 + 1.696 + assert(profile_parameters_jsr292_only(), "inconsistent"); 1.697 + return m->is_compiled_lambda_form(); 1.698 +}