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	Thu Jan 16 17:24:39 2014
--- new/src/share/vm/oops/methodData.cpp	Thu Jan 16 17:24:38 2014

*** 78,101 **** --- 78,139 ---- // Constructor for invalid ProfileData. ProfileData::ProfileData() { _data = NULL; } + char* ProfileData::print_data_on_helper(const MethodData* md) const { + DataLayout* dp = md->extra_data_base(); + DataLayout* end = md->extra_data_limit(); + stringStream ss; + for (;; dp = MethodData::next_extra(dp)) { + assert(dp < end, "moved past end of extra data"); + switch(dp->tag()) { + case DataLayout::speculative_trap_data_tag: + if (dp->bci() == bci()) { + SpeculativeTrapData* data = new SpeculativeTrapData(dp); + int trap = data->trap_state(); + char buf[100]; + ss.print("trap/"); + data->method()->print_short_name(&ss); + ss.print("(%s) ", Deoptimization::format_trap_state(buf, sizeof(buf), trap)); + } + break; + case DataLayout::bit_data_tag: + break; + case DataLayout::no_tag: + case DataLayout::arg_info_data_tag: + return ss.as_string(); + break; + default: + fatal(err_msg("unexpected tag %d", dp->tag())); + } + } + return NULL; + } + + void ProfileData::print_data_on(outputStream* st, const MethodData* md) const { + print_data_on(st, print_data_on_helper(md)); + } + #ifndef PRODUCT ! void ProfileData::print_shared(outputStream* st, const char* name, const char* extra) const { st->print("bci: %d", bci()); st->fill_to(tab_width_one); st->print("%s", name); tab(st); int trap = trap_state(); if (trap != 0) { char buf[100]; st->print("trap(%s) ", Deoptimization::format_trap_state(buf, sizeof(buf), trap)); } + if (extra != NULL) { + st->print(extra); + } int flags = data()->flags(); ! if (flags != 0) { st->print("flags(%d) ", flags); + } } void ProfileData::tab(outputStream* st, bool first) const { st->fill_to(first ? tab_width_one : tab_width_two); }
*** 107,129 **** --- 145,167 ---- // 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 char* extra) const { ! print_shared(st, "BitData", extra); } #endif // !PRODUCT // ================================================================== // CounterData // // A CounterData corresponds to a simple counter. #ifndef PRODUCT ! void CounterData::print_data_on(outputStream* st, const char* extra) const { ! print_shared(st, "CounterData", extra); st->print_cr("count(%u)", count()); } #endif // !PRODUCT // ==================================================================
*** 148,159 **** --- 186,197 ---- int offset = target_di - my_di; set_displacement(offset); } #ifndef PRODUCT ! void JumpData::print_data_on(outputStream* st, const char* extra) const { ! print_shared(st, "JumpData", extra); st->print_cr("taken(%u) displacement(%d)", taken(), displacement()); } #endif // !PRODUCT int TypeStackSlotEntries::compute_cell_count(Symbol* signature, bool include_receiver, int max) {
*** 330,341 **** --- 368,379 ---- _pd->tab(st); print_klass(st, type()); st->cr(); } ! void CallTypeData::print_data_on(outputStream* st, const char* extra) const { ! CounterData::print_data_on(st, extra); if (has_arguments()) { tab(st, true); st->print("argument types"); _args.print_data_on(st); }
*** 344,355 **** --- 382,393 ---- st->print("return type"); _ret.print_data_on(st); } } ! void VirtualCallTypeData::print_data_on(outputStream* st, const char* extra) const { ! VirtualCallData::print_data_on(st, extra); if (has_arguments()) { tab(st, true); st->print("argument types"); _args.print_data_on(st); }
*** 398,413 **** --- 436,451 ---- 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 char* extra) const { ! print_shared(st, "ReceiverTypeData", extra); print_receiver_data_on(st); } ! void VirtualCallData::print_data_on(outputStream* st, const char* extra) const { ! print_shared(st, "VirtualCallData", extra); print_receiver_data_on(st); } #endif // !PRODUCT // ==================================================================
*** 454,465 **** --- 492,503 ---- return mdp; } #ifndef PRODUCT ! void RetData::print_data_on(outputStream* st, const char* extra) const { ! print_shared(st, "RetData", extra); uint row; int entries = 0; for (row = 0; row < row_limit(); row++) { if (bci(row) != no_bci) entries++; }
*** 489,500 **** --- 527,538 ---- int offset = target_di - my_di; set_displacement(offset); } #ifndef PRODUCT ! void BranchData::print_data_on(outputStream* st, const char* extra) const { ! print_shared(st, "BranchData", extra); st->print_cr("taken(%u) displacement(%d)", taken(), displacement()); tab(st); st->print_cr("not taken(%u)", not_taken()); }
*** 563,574 **** --- 601,612 ---- set_default_displacement(offset); } } #ifndef PRODUCT ! void MultiBranchData::print_data_on(outputStream* st, const char* extra) const { ! print_shared(st, "MultiBranchData", extra); st->print_cr("default_count(%u) displacement(%d)", default_count(), default_displacement()); int cases = number_of_cases(); for (int i = 0; i < cases; i++) { tab(st);
*** 577,588 **** --- 615,626 ---- } } #endif #ifndef PRODUCT ! void ArgInfoData::print_data_on(outputStream* st, const char* extra) const { ! print_shared(st, "ArgInfoData", extra); int nargs = number_of_args(); for (int i = 0; i < nargs; i++) { st->print(" 0x%x", arg_modified(i)); } st->cr();
*** 609,622 **** --- 647,667 ---- bool ParametersTypeData::profiling_enabled() { return MethodData::profile_parameters(); } #ifndef PRODUCT ! void ParametersTypeData::print_data_on(outputStream* st, const char* extra) const { ! st->print("parameter types", extra); _parameters.print_data_on(st); } + + void SpeculativeTrapData::print_data_on(outputStream* st, const char* extra) const { + print_shared(st, "SpeculativeTrapData", extra); + tab(st); + method()->print_short_name(st); + st->cr(); + } #endif // ================================================================== // MethodData* //
*** 738,759 **** --- 783,833 ---- // a DataLayout header, with no extra cells. assert(cell_count >= 0, "sanity"); return DataLayout::compute_size_in_bytes(cell_count); } ! int MethodData::compute_extra_data_count(int data_size, int empty_bc_count) { ! bool MethodData::speculative_trap_bytecode(Bytecodes::Code code) { + // Bytecodes for which we may use speculation + switch (code) { + case Bytecodes::_checkcast: + case Bytecodes::_instanceof: + case Bytecodes::_aastore: + case Bytecodes::_invokevirtual: + case Bytecodes::_invokeinterface: + case Bytecodes::_if_acmpeq: + case Bytecodes::_if_acmpne: + case Bytecodes::_invokestatic: + return UseTypeSpeculation; + default: + return false; + } + return false; + } + + int MethodData::compute_extra_data_count(int data_size, int empty_bc_count, bool needs_speculative_traps) { if (ProfileTraps) { // Assume that up to 3% of BCIs with no MDP will need to allocate one. int extra_data_count = (uint)(empty_bc_count * 3) / 128 + 1; // If the method is large, let the extra BCIs grow numerous (to ~1%). int one_percent_of_data = (uint)data_size / (DataLayout::header_size_in_bytes()*128); if (extra_data_count < one_percent_of_data) extra_data_count = one_percent_of_data; if (extra_data_count > empty_bc_count) extra_data_count = empty_bc_count; // no need for more return extra_data_count; + + // Make sure we have a minimum number of extra data slots to + // allocate SpeculativeTrapData entries. We would want to have one + // entry per compilation that inlines this method and for which + // some type speculation assumption fails. So the room we need for + // the SpeculativeTrapData entries doesn't directly depend on the + // size of the method. Because it's hard to estimate, we reserve + // space for an arbitrary number of entries. + int spec_data_count = (needs_speculative_traps ? SpecTrapLimitExtraEntries : 0) * + (SpeculativeTrapData::static_cell_count() + DataLayout::header_size_in_cells()); + + return MAX2(extra_data_count, spec_data_count); } else { return 0; } }
*** 762,780 **** --- 836,856 ---- int MethodData::compute_allocation_size_in_bytes(methodHandle method) { int data_size = 0; BytecodeStream stream(method); Bytecodes::Code c; int empty_bc_count = 0; // number of bytecodes lacking data + bool needs_speculative_traps = false; while ((c = stream.next()) >= 0) { int size_in_bytes = compute_data_size(&stream); data_size += size_in_bytes; if (size_in_bytes == 0) empty_bc_count += 1; + needs_speculative_traps = needs_speculative_traps || speculative_trap_bytecode(c); } int object_size = in_bytes(data_offset()) + data_size; // Add some extra DataLayout cells (at least one) to track stray traps. ! int extra_data_count = compute_extra_data_count(data_size, empty_bc_count, needs_speculative_traps); 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);
*** 1002,1023 **** --- 1078,1104 ---- int data_size = 0; int empty_bc_count = 0; // number of bytecodes lacking data _data[0] = 0; // apparently not set below. BytecodeStream stream(method); Bytecodes::Code c; + bool needs_speculative_traps = false; while ((c = stream.next()) >= 0) { int size_in_bytes = initialize_data(&stream, data_size); data_size += size_in_bytes; if (size_in_bytes == 0) empty_bc_count += 1; + needs_speculative_traps = needs_speculative_traps || speculative_trap_bytecode(c); } _data_size = data_size; int object_size = in_bytes(data_offset()) + data_size; // Add some extra DataLayout cells (at least one) to track stray traps. ! int extra_data_count = compute_extra_data_count(data_size, empty_bc_count, needs_speculative_traps); int extra_size = extra_data_count * DataLayout::compute_size_in_bytes(0); + // Let's zero the space for the extra data + Copy::zero_to_bytes(((address)_data) + data_size, extra_size); + // Add a cell to record information about modified arguments. // Set up _args_modified array after traps cells so that // the code for traps cells works. DataLayout *dp = data_layout_at(data_size + extra_size);
*** 1025,1045 **** --- 1106,1126 ---- dp->initialize(DataLayout::arg_info_data_tag, 0, arg_size+1); int arg_data_size = DataLayout::compute_size_in_bytes(arg_size+1); object_size += extra_size + arg_data_size; ! int args_cell = ParametersTypeData::compute_cell_count(method()); ! int parms_cell = ParametersTypeData::compute_cell_count(method()); // If we are profiling parameters, we reserver an area near the end // of the MDO after the slots for bytecodes (because there's no bci // for method entry so they don't fit with the framework for the // profiling of bytecodes). We store the offset within the MDO of // this area (or -1 if no parameter is profiled) ! if (args_cell > 0) { ! object_size += DataLayout::compute_size_in_bytes(args_cell); ! if (parms_cell > 0) { ! object_size += DataLayout::compute_size_in_bytes(parms_cell); _parameters_type_data_di = data_size + extra_size + arg_data_size; DataLayout *dp = data_layout_at(data_size + extra_size + arg_data_size); ! dp->initialize(DataLayout::parameters_type_data_tag, 0, args_cell); ! dp->initialize(DataLayout::parameters_type_data_tag, 0, parms_cell); } else { _parameters_type_data_di = -1; } // Set an initial hint. Don't use set_hint_di() because
*** 1126,1168 **** --- 1207,1323 ---- return data; } else if (data->bci() > bci) { break; } } ! return bci_to_extra_data(bci, NULL, false); } // Translate a bci to its corresponding extra data, or NULL. ProfileData* MethodData::bci_to_extra_data(int bci, bool create_if_missing) { DataLayout* dp = extra_data_base(); + DataLayout* MethodData::next_extra(DataLayout* dp) { + int nb_cells = 0; + switch(dp->tag()) { + case DataLayout::bit_data_tag: + case DataLayout::no_tag: + nb_cells = BitData::static_cell_count(); + break; + case DataLayout::speculative_trap_data_tag: + nb_cells = SpeculativeTrapData::static_cell_count(); + break; + default: + fatal(err_msg("unexpected tag %d", dp->tag())); + } + return (DataLayout*)((address)dp + DataLayout::compute_size_in_bytes(nb_cells)); + } + + ProfileData* MethodData::bci_to_extra_data_helper(int bci, Method* m, DataLayout*& dp) { DataLayout* end = extra_data_limit(); DataLayout* avail = NULL; - for (; dp < end; dp = next_extra(dp)) { + + assert(dp < end, "moved past end of extra data"); // No need for "OrderAccess::load_acquire" ops, // since the data structure is monotonic. if (dp->tag() == DataLayout::no_tag) break; if (dp->tag() == DataLayout::arg_info_data_tag) { dp = end; // ArgInfoData is at the end of extra data section. break; + switch(dp->tag()) { + case DataLayout::no_tag: + return NULL; + case DataLayout::arg_info_data_tag: + dp = end; + return NULL; // ArgInfoData is at the end of extra data section. + case DataLayout::bit_data_tag: + if (m == NULL && dp->bci() == bci) { + return new BitData(dp); } + break; + case DataLayout::speculative_trap_data_tag: + if (m != NULL) { + SpeculativeTrapData* data = new SpeculativeTrapData(dp); + // data->method() may be null in case of a concurrent + // allocation. Assume it's for the same method and use that + // entry in that case. if (dp->bci() == bci) { assert(dp->tag() == DataLayout::bit_data_tag, "sane"); ! return new BitData(dp); + if (data->method() == NULL) { ! return NULL; + } else if (data->method() == m) { + return data; } } + } + break; + default: + fatal(err_msg("unexpected tag %d", dp->tag())); + } + } + return NULL; + } + + + // Translate a bci to its corresponding extra data, or NULL. + ProfileData* MethodData::bci_to_extra_data(int bci, Method* m, bool create_if_missing) { + // This code assumes an entry for a SpeculativeTrapData is 2 cells + assert(2*DataLayout::compute_size_in_bytes(BitData::static_cell_count()) == + DataLayout::compute_size_in_bytes(SpeculativeTrapData::static_cell_count()), + "code needs to be adjusted"); + + DataLayout* dp = extra_data_base(); + DataLayout* end = extra_data_limit(); + + // Allocation in the extra data space has to be atomic because not + // all entries have the same size and non atomic concurrent + // allocation would result in a corrupted extra data space. + while (true) { + ProfileData* result = bci_to_extra_data_helper(bci, m, dp); + if (result != NULL) { + return result; + } + if (create_if_missing && dp < end) { // Allocate this one. There is no mutual exclusion, // so two threads could allocate different BCIs to the // same data layout. This means these extra data // records, like most other MDO contents, must not be // trusted too much. + assert(dp->tag() == DataLayout::no_tag || (dp->tag() == DataLayout::speculative_trap_data_tag && m != NULL), "should be free"); + assert(next_extra(dp)->tag() == DataLayout::no_tag || next_extra(dp)->tag() == DataLayout::arg_info_data_tag, "should be free or arg info"); + u1 tag = m == NULL ? DataLayout::bit_data_tag : DataLayout::speculative_trap_data_tag; + // SpeculativeTrapData is 2 slots. Make sure we have room. + if (m != NULL && next_extra(dp)->tag() != DataLayout::no_tag) { + return NULL; + } DataLayout temp; ! temp.initialize(DataLayout::bit_data_tag, bci, 0); dp->release_set_header(temp.header()); assert(dp->tag() == DataLayout::bit_data_tag, "sane"); //NO: assert(dp->bci() == bci, "no concurrent allocation"); ! temp.initialize(tag, bci, 0); + // May have been set concurrently + if (dp->header() != temp.header() && !dp->atomic_set_header(temp.header())) { + // Allocation failure because of concurrent allocation. Try + // again. + continue; + } + assert(dp->tag() == tag, "sane"); + assert(dp->bci() == bci, "no concurrent allocation"); + if (tag == DataLayout::bit_data_tag) { return new BitData(dp); + } else { + // If being allocated concurrently, one trap may be lost + SpeculativeTrapData* data = new SpeculativeTrapData(dp); + data->set_method(m); + return data; + } + } + return NULL; } return NULL; } ArgInfoData *MethodData::arg_info() {
*** 1198,1231 **** --- 1353,1396 ---- #ifndef PRODUCT void MethodData::print_data_on(outputStream* st) const { ResourceMark rm; ProfileData* data = first_data(); if (_parameters_type_data_di != -1) { ! parameters_type_data()->print_data_on(st, (const char*)NULL); } for ( ; is_valid(data); data = next_data(data)) { st->print("%d", dp_to_di(data->dp())); st->fill_to(6); ! data->print_data_on(st, this); } st->print_cr("--- Extra data:"); DataLayout* dp = extra_data_base(); DataLayout* end = extra_data_limit(); - for (; dp < end; dp = next_extra(dp)) { + assert(dp < end, "moved past end of extra data"); // No need for "OrderAccess::load_acquire" ops, // since the data structure is monotonic. if (dp->tag() == DataLayout::no_tag) continue; if (dp->tag() == DataLayout::bit_data_tag) { + switch(dp->tag()) { + case DataLayout::no_tag: + continue; + case DataLayout::bit_data_tag: data = new BitData(dp); } else { assert(dp->tag() == DataLayout::arg_info_data_tag, "must be BitData or ArgInfo"); + break; + case DataLayout::speculative_trap_data_tag: + data = new SpeculativeTrapData(dp); + break; + case DataLayout::arg_info_data_tag: data = new ArgInfoData(dp); dp = end; // ArgInfoData is at the end of extra data section. + break; + default: + fatal(err_msg("unexpected tag %d", dp->tag())); } st->print("%d", dp_to_di(data->dp())); st->fill_to(6); ! data->print_data_on(st, (const char*)NULL); + if (dp >= end) return; } } #endif #if INCLUDE_SERVICES
*** 1344,1348 **** --- 1509,1548 ---- } assert(profile_parameters_jsr292_only(), "inconsistent"); return m->is_compiled_lambda_form(); } + + void MethodData::clean_method_data(BoolObjectClosure* is_alive) { + for (ProfileData* data = first_data(); + is_valid(data); + data = next_data(data)) { + data->clean_weak_klass_links(is_alive); + } + ParametersTypeData* parameters = parameters_type_data(); + if (parameters != NULL) { + parameters->clean_weak_klass_links(is_alive); + } + + #ifdef ASSERT + DataLayout* dp = extra_data_base(); + DataLayout* end = extra_data_limit(); + + for (; dp < end; dp = next_extra(dp)) { + switch(dp->tag()) { + case DataLayout::speculative_trap_data_tag: { + SpeculativeTrapData* data = new SpeculativeTrapData(dp); + Method* m = data->method(); + assert(m != NULL && m->method_holder()->is_loader_alive(is_alive), "Method should exist"); + break; + } + case dp->DataLayout::bit_data_tag: + continue; + case DataLayout::no_tag: + case DataLayout::arg_info_data_tag: + return; + default: + fatal(err_msg("unexpected tag %d", dp->tag())); + } + } + #endif + }

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