src/share/vm/oops/methodData.cpp
Index Unified diffs Context diffs Sdiffs Patch New Old Previous File Next File
*** old/src/share/vm/oops/methodData.cpp	Tue Oct  8 14:00:26 2013
--- new/src/share/vm/oops/methodData.cpp	Tue Oct  8 14:00:26 2013

*** 54,63 **** --- 54,68 ---- set_cell_at(i, (intptr_t)0); } if (needs_array_len(tag)) { set_cell_at(ArrayData::array_len_off_set, cell_count - 1); // -1 for header. } + if (tag == call_type_data_tag) { + CallTypeData::initialize(this, cell_count); + } else if (tag == virtual_call_type_data_tag) { + VirtualCallTypeData::initialize(this, cell_count); + } } void DataLayout::clean_weak_klass_links(BoolObjectClosure* cl) { ResourceMark m; data_in()->clean_weak_klass_links(cl);
*** 74,84 **** --- 79,89 ---- ProfileData::ProfileData() { _data = NULL; } #ifndef PRODUCT ! void ProfileData::print_shared(outputStream* st, const char* name) const { st->print("bci: %d", bci()); st->fill_to(tab_width_one); st->print("%s", name); tab(st); int trap = trap_state();
*** 89,100 **** --- 94,105 ---- int flags = data()->flags(); if (flags != 0) st->print("flags(%d) ", flags); } ! void ProfileData::tab(outputStream* st, bool first) const { ! st->fill_to(tab_width_two); ! st->fill_to(first ? tab_width_one : tab_width_two); } #endif // !PRODUCT // ================================================================== // BitData
*** 102,123 **** --- 107,128 ---- // A BitData corresponds to a one-bit flag. This is used to indicate // whether a checkcast bytecode has seen a null value. #ifndef PRODUCT ! void BitData::print_data_on(outputStream* st) const { print_shared(st, "BitData"); } #endif // !PRODUCT // ================================================================== // CounterData // // A CounterData corresponds to a simple counter. #ifndef PRODUCT ! void CounterData::print_data_on(outputStream* st) const { print_shared(st, "CounterData"); st->print_cr("count(%u)", count()); } #endif // !PRODUCT
*** 143,158 **** --- 148,281 ---- int offset = target_di - my_di; set_displacement(offset); } #ifndef PRODUCT ! void JumpData::print_data_on(outputStream* st) const { print_shared(st, "JumpData"); st->print_cr("taken(%u) displacement(%d)", taken(), displacement()); } #endif // !PRODUCT + int TypeStackSlotEntries::compute_cell_count(BytecodeStream* stream) { + int max = TypeProfileArgsLimit; + assert(Bytecodes::is_invoke(stream->code()), "should be invoke"); + Bytecode_invoke inv(stream->method(), stream->bci()); + + ResourceMark rm; + SignatureStream ss(inv.signature()); + int args_count = MIN2(ss.reference_parameter_count(), max); + + return args_count * per_arg_cell_count + (args_count > 0 ? header_cell_count() : 0); + } + + class ArgumentOffsetComputer : public SignatureInfo { + private: + int _max; + GrowableArray<int> _offsets; + + void set(int size, BasicType type) { _size += size; } + void do_object(int begin, int end) { + if (_offsets.length() < _max) { + _offsets.push(_size); + } + SignatureInfo::do_object(begin, end); + } + void do_array (int begin, int end) { + if (_offsets.length() < _max) { + _offsets.push(_size); + } + SignatureInfo::do_array(begin, end); + } + + public: + ArgumentOffsetComputer(Symbol* signature, int max) + : SignatureInfo(signature), _max(max), _offsets(Thread::current(), max) { + } + + int total() { lazy_iterate_parameters(); return _size; } + + int off_at(int i) const { return _offsets.at(i); } + }; + + void TypeStackSlotEntries::post_initialize(BytecodeStream* stream) { + ResourceMark rm; + + assert(Bytecodes::is_invoke(stream->code()), "should be invoke"); + Bytecode_invoke inv(stream->method(), stream->bci()); + + #ifdef ASSERT + SignatureStream ss(inv.signature()); + int count = MIN2(ss.reference_parameter_count(), TypeProfileArgsLimit); + assert(count > 0, "room for args type but none found?"); + check_number_of_arguments(count); + #endif + + int start = 0; + ArgumentOffsetComputer aos(inv.signature(), number_of_arguments()-start); + aos.total(); + bool has_receiver = inv.has_receiver(); + for (int i = start; i < number_of_arguments(); i++) { + set_stack_slot(i, aos.off_at(i-start) + (has_receiver ? 1 : 0)); + set_type(i, type_none()); + } + } + + bool TypeEntries::is_loader_alive(BoolObjectClosure* is_alive_cl, intptr_t p) { + return !is_type_none(p) && + !((Klass*)klass_part(p))->is_loader_alive(is_alive_cl); + } + + void TypeStackSlotEntries::clean_weak_klass_links(BoolObjectClosure* is_alive_cl) { + for (int i = 0; i < number_of_arguments(); i++) { + intptr_t p = type(i); + if (is_loader_alive(is_alive_cl, p)) { + set_type(i, type_none()); + } + } + } + + bool TypeStackSlotEntries::arguments_profiling_enabled() { + return MethodData::profile_arguments(); + } + + #ifndef PRODUCT + void TypeEntries::print_klass(outputStream* st, intptr_t k) { + if (is_type_none(k)) { + st->print("none"); + } else if (is_type_unknown(k)) { + st->print("unknown"); + } else { + valid_klass(k)->print_value_on(st); + } + if (was_null_seen(k)) { + st->print(" (null seen)"); + } + } + + void TypeStackSlotEntries::print_data_on(outputStream* st) const { + _pd->tab(st, true); + st->print("argument types"); + for (int i = 0; i < number_of_arguments(); i++) { + _pd->tab(st); + st->print("%d: stack(%u) ", i, stack_slot(i)); + print_klass(st, type(i)); + st->cr(); + } + } + + void CallTypeData::print_data_on(outputStream* st) const { + CounterData::print_data_on(st); + _args.print_data_on(st); + } + + void VirtualCallTypeData::print_data_on(outputStream* st) const { + VirtualCallData::print_data_on(st); + _args.print_data_on(st); + } + #endif + // ================================================================== // ReceiverTypeData // // A ReceiverTypeData is used to access profiling information about a // dynamic type check. It consists of a counter which counts the total times
*** 167,177 **** --- 290,300 ---- } } } #ifndef PRODUCT ! void ReceiverTypeData::print_receiver_data_on(outputStream* st) const { uint row; int entries = 0; for (row = 0; row < row_limit(); row++) { if (receiver(row) != NULL) entries++; }
*** 188,202 **** --- 311,325 ---- receiver(row)->print_value_on(st); st->print_cr("(%u %4.2f)", receiver_count(row), (float) receiver_count(row) / (float) total); } } } ! void ReceiverTypeData::print_data_on(outputStream* st) const { print_shared(st, "ReceiverTypeData"); print_receiver_data_on(st); } ! void VirtualCallData::print_data_on(outputStream* st) const { print_shared(st, "VirtualCallData"); print_receiver_data_on(st); } #endif // !PRODUCT
*** 244,254 **** --- 367,377 ---- return mdp; } #ifndef PRODUCT ! void RetData::print_data_on(outputStream* st) const { print_shared(st, "RetData"); uint row; int entries = 0; for (row = 0; row < row_limit(); row++) { if (bci(row) != no_bci) entries++;
*** 279,289 **** --- 402,412 ---- int offset = target_di - my_di; set_displacement(offset); } #ifndef PRODUCT ! void BranchData::print_data_on(outputStream* st) const { print_shared(st, "BranchData"); st->print_cr("taken(%u) displacement(%d)", taken(), displacement()); tab(st); st->print_cr("not taken(%u)", not_taken());
*** 353,363 **** --- 476,486 ---- set_default_displacement(offset); } } #ifndef PRODUCT ! void MultiBranchData::print_data_on(outputStream* st) const { print_shared(st, "MultiBranchData"); st->print_cr("default_count(%u) displacement(%d)", default_count(), default_displacement()); int cases = number_of_cases(); for (int i = 0; i < cases; i++) {
*** 367,377 **** --- 490,500 ---- } } #endif #ifndef PRODUCT ! void ArgInfoData::print_data_on(outputStream* st) const { print_shared(st, "ArgInfoData"); int nargs = number_of_args(); for (int i = 0; i < nargs; i++) { st->print(" 0x%x", arg_modified(i)); }
*** 405,425 **** --- 528,560 ---- } else { return BitData::static_cell_count(); } case Bytecodes::_invokespecial: case Bytecodes::_invokestatic: + if (MethodData::profile_arguments()) { + return variable_cell_count; + } else { return CounterData::static_cell_count(); + } case Bytecodes::_goto: case Bytecodes::_goto_w: case Bytecodes::_jsr: case Bytecodes::_jsr_w: return JumpData::static_cell_count(); case Bytecodes::_invokevirtual: case Bytecodes::_invokeinterface: + if (MethodData::profile_arguments()) { + return variable_cell_count; + } else { return VirtualCallData::static_cell_count(); + } case Bytecodes::_invokedynamic: + if (MethodData::profile_arguments()) { + return variable_cell_count; + } else { return CounterData::static_cell_count(); + } case Bytecodes::_ret: return RetData::static_cell_count(); case Bytecodes::_ifeq: case Bytecodes::_ifne: case Bytecodes::_iflt:
*** 451,461 **** --- 586,623 ---- int cell_count = bytecode_cell_count(stream->code()); if (cell_count == no_profile_data) { return 0; } if (cell_count == variable_cell_count) { + switch (stream->code()) { + case Bytecodes::_lookupswitch: + case Bytecodes::_tableswitch: cell_count = MultiBranchData::compute_cell_count(stream); + break; + case Bytecodes::_invokespecial: + case Bytecodes::_invokestatic: + case Bytecodes::_invokedynamic: + assert(MethodData::profile_arguments(), "should be collecting args profile"); + if (profile_arguments_for_invoke(stream->method(), stream->bci())) { + cell_count = CallTypeData::compute_cell_count(stream); + } else { + cell_count = CounterData::static_cell_count(); + } + break; + case Bytecodes::_invokevirtual: + case Bytecodes::_invokeinterface: { + assert(MethodData::profile_arguments(), "should be collecting args profile"); + if (profile_arguments_for_invoke(stream->method(), stream->bci())) { + cell_count = VirtualCallTypeData::compute_cell_count(stream); + } else { + cell_count = VirtualCallData::static_cell_count(); + } + break; + } + default: + fatal("unexpected bytecode for var length profile data"); + } } // Note: cell_count might be zero, meaning that there is just // a DataLayout header, with no extra cells. assert(cell_count >= 0, "sanity"); return DataLayout::compute_size_in_bytes(cell_count);
*** 497,506 **** --- 659,669 ---- object_size += extra_data_count * DataLayout::compute_size_in_bytes(0); // Add a cell to record information about modified arguments. int arg_size = method->size_of_parameters(); object_size += DataLayout::compute_size_in_bytes(arg_size+1); + return object_size; } // Compute the size of the MethodData* necessary to store // profiling information about a given method. Size is in words
*** 532,562 **** --- 695,755 ---- cell_count = BitData::static_cell_count(); tag = DataLayout::bit_data_tag; } break; case Bytecodes::_invokespecial: ! case Bytecodes::_invokestatic: { ! int counter_data_cell_count = CounterData::static_cell_count(); + if (profile_arguments_for_invoke(stream->method(), stream->bci())) { + cell_count = CallTypeData::compute_cell_count(stream); + } else { + cell_count = counter_data_cell_count; + } + if (cell_count > counter_data_cell_count) { + tag = DataLayout::call_type_data_tag; + } else { tag = DataLayout::counter_data_tag; + } break; + } case Bytecodes::_goto: case Bytecodes::_goto_w: case Bytecodes::_jsr: case Bytecodes::_jsr_w: cell_count = JumpData::static_cell_count(); tag = DataLayout::jump_data_tag; break; case Bytecodes::_invokevirtual: ! case Bytecodes::_invokeinterface: { ! int virtual_call_data_cell_count = VirtualCallData::static_cell_count(); + if (profile_arguments_for_invoke(stream->method(), stream->bci())) { + cell_count = VirtualCallTypeData::compute_cell_count(stream); + } else { + cell_count = virtual_call_data_cell_count; + } + if (cell_count > virtual_call_data_cell_count) { + tag = DataLayout::virtual_call_type_data_tag; + } else { tag = DataLayout::virtual_call_data_tag; + } break; case Bytecodes::_invokedynamic: + } + case Bytecodes::_invokedynamic: { // %%% should make a type profile for any invokedynamic that takes a ref argument ! int counter_data_cell_count = CounterData::static_cell_count(); + if (profile_arguments_for_invoke(stream->method(), stream->bci())) { + cell_count = CallTypeData::compute_cell_count(stream); + } else { + cell_count = counter_data_cell_count; + } + if (cell_count > counter_data_cell_count) { + tag = DataLayout::call_type_data_tag; + } else { tag = DataLayout::counter_data_tag; + } break; + } case Bytecodes::_ret: cell_count = RetData::static_cell_count(); tag = DataLayout::ret_data_tag; break; case Bytecodes::_ifeq:
*** 583,592 **** --- 776,790 ---- cell_count = MultiBranchData::compute_cell_count(stream); tag = DataLayout::multi_branch_data_tag; break; } assert(tag == DataLayout::multi_branch_data_tag || + (MethodData::profile_arguments() && + (tag == DataLayout::call_type_data_tag || + tag == DataLayout::counter_data_tag || + tag == DataLayout::virtual_call_type_data_tag || + tag == DataLayout::virtual_call_data_tag)) || cell_count == bytecode_cell_count(c), "cell counts must agree"); if (cell_count >= 0) { assert(tag != DataLayout::no_tag, "bad tag"); assert(bytecode_has_profile(c), "agree w/ BHP"); data_layout->initialize(tag, stream->bci(), cell_count);
*** 629,638 **** --- 827,840 ---- return new BranchData(this); case DataLayout::multi_branch_data_tag: return new MultiBranchData(this); case DataLayout::arg_info_data_tag: return new ArgInfoData(this); + case DataLayout::call_type_data_tag: + return new CallTypeData(this); + case DataLayout::virtual_call_type_data_tag: + return new VirtualCallTypeData(this); }; } // Iteration over data. ProfileData* MethodData::next_data(ProfileData* current) const {
*** 896,900 **** --- 1098,1141 ---- void MethodData::verify_data_on(outputStream* st) { NEEDS_CLEANUP; // not yet implemented. } + + bool MethodData::profile_jsr292(methodHandle m, int bci) { + if (m->is_compiled_lambda_form()) { + return true; + } + + Bytecode_invoke inv(m , bci); + return inv.is_invokedynamic() || inv.is_invokehandle(); + } + + int MethodData::profile_arguments_flag() { + return TypeProfileLevel; + } + + bool MethodData::profile_arguments() { + return profile_arguments_flag() > no_type_profile && profile_arguments_flag() <= type_profile_all; + } + + bool MethodData::profile_arguments_jsr292_only() { + return profile_arguments_flag() == type_profile_jsr292; + } + + bool MethodData::profile_all_arguments() { + return profile_arguments_flag() == type_profile_all; + } + + bool MethodData::profile_arguments_for_invoke(methodHandle m, int bci) { + if (!profile_arguments()) { + return false; + } + + if (profile_all_arguments()) { + return true; + } + + assert(profile_arguments_jsr292_only(), "inconsistent"); + return profile_jsr292(m, bci); + } +

src/share/vm/oops/methodData.cpp
Index Unified diffs Context diffs Sdiffs Patch New Old Previous File Next File