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