void ciMethodData::load_extra_data() { MethodData* mdo = get_MethodData(); MutexLocker(mdo->extra_data_lock()); // speculative trap entries also hold a pointer to a Method so need to be translated DataLayout* dp_src = mdo->extra_data_base(); DataLayout* end_src = mdo->args_data_limit(); DataLayout* dp_dst = extra_data_base(); for (;; dp_src = MethodData::next_extra(dp_src), dp_dst = MethodData::next_extra(dp_dst)) { assert(dp_src < end_src, "moved past end of extra data"); assert(((intptr_t)dp_dst) - ((intptr_t)extra_data_base()) == ((intptr_t)dp_src) - ((intptr_t)mdo->extra_data_base()), "source and destination don't match"); // New traps in the MDO may have been added since we copied the // data (concurrent deoptimizations before we acquired // extra_data_lock above) or can be removed (a safepoint may occur // in the translate_from call below) as we translate the copy: // update the copy as we go. int tag = dp_src->tag(); if (tag != DataLayout::arg_info_data_tag) { memcpy(dp_dst, dp_src, ((intptr_t)MethodData::next_extra(dp_src)) - ((intptr_t)dp_src)); } switch(tag) { case DataLayout::speculative_trap_data_tag: { ciSpeculativeTrapData* data_dst = new ciSpeculativeTrapData(dp_dst); SpeculativeTrapData* data_src = new SpeculativeTrapData(dp_src); data_dst->translate_from(data_src); #ifdef ASSERT SpeculativeTrapData* data_src2 = new SpeculativeTrapData(dp_src); assert(data_src2->method() == data_src->method() && data_src2->bci() == data_src->bci(), "entries changed while translating"); #endif break; } case DataLayout::bit_data_tag: break; case DataLayout::no_tag: case DataLayout::arg_info_data_tag: // An empty slot or ArgInfoData entry marks the end of the trap data return; default: fatal(err_msg("bad tag = %d", dp_dst->tag())); } } }
void methodDataOopDesc::print_data_on(outputStream* st) { ResourceMark rm; ProfileData* data = first_data(); 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); } st->print_cr("--- Extra data:"); DataLayout* dp = extra_data_base(); DataLayout* end = extra_data_limit(); for (; dp < end; dp = next_extra(dp)) { // 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) { data = new BitData(dp); } else { assert(dp->tag() == DataLayout::arg_info_data_tag, "must be BitData or ArgInfo"); data = new ArgInfoData(dp); dp = end; // ArgInfoData is at the end of extra data section. } st->print("%d", dp_to_di(data->dp())); st->fill_to(6); data->print_data_on(st); } }
// Translate a bci to its corresponding extra data, or NULL. ProfileData* methodDataOopDesc::bci_to_extra_data(int bci, bool create_if_missing) { DataLayout* dp = extra_data_base(); DataLayout* end = extra_data_limit(); DataLayout* avail = NULL; for (; dp < end; dp = next_extra(dp)) { // 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; } if (dp->bci() == bci) { assert(dp->tag() == DataLayout::bit_data_tag, "sane"); return new BitData(dp); } } 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. 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"); return new BitData(dp); } return NULL; }
void ciMethodData::dump_replay_data_extra_data_helper(outputStream* out, int round, int& count) { DataLayout* dp = extra_data_base(); DataLayout* end = args_data_limit(); for (;dp < end; dp = MethodData::next_extra(dp)) { switch(dp->tag()) { case DataLayout::no_tag: case DataLayout::arg_info_data_tag: return; case DataLayout::bit_data_tag: break; case DataLayout::speculative_trap_data_tag: { ciSpeculativeTrapData* data = new ciSpeculativeTrapData(dp); ciMethod* m = data->method(); if (m != NULL) { if (round == 0) { count++; } else { out->print(" %d ", (int)(dp_to_di(((address)dp) + in_bytes(ciSpeculativeTrapData::method_offset())) / sizeof(intptr_t))); m->dump_name_as_ascii(out); } } break; } default: fatal(err_msg("bad tag = %d", dp->tag())); } } }
ciProfileData* ciMethodData::bci_to_extra_data(int bci, ciMethod* m, bool& two_free_slots) { DataLayout* dp = extra_data_base(); DataLayout* end = args_data_limit(); two_free_slots = false; for (;dp < end; dp = MethodData::next_extra(dp)) { switch(dp->tag()) { case DataLayout::no_tag: _saw_free_extra_data = true; // observed an empty slot (common case) two_free_slots = (MethodData::next_extra(dp)->tag() == DataLayout::no_tag); return NULL; case DataLayout::arg_info_data_tag: return NULL; // ArgInfoData is at the end of extra data section. case DataLayout::bit_data_tag: if (m == NULL && dp->bci() == bci) { return new ciBitData(dp); } break; case DataLayout::speculative_trap_data_tag: { ciSpeculativeTrapData* data = new ciSpeculativeTrapData(dp); // data->method() might be null if the MDO is snapshotted // concurrently with a trap if (m != NULL && data->method() == m && dp->bci() == bci) { return data; } break; } default: fatal(err_msg("bad tag = %d", dp->tag())); } } return NULL; }
ArgInfoData *methodDataOopDesc::arg_info() { DataLayout* dp = extra_data_base(); DataLayout* end = extra_data_limit(); for (; dp < end; dp = next_extra(dp)) { if (dp->tag() == DataLayout::arg_info_data_tag) return new ArgInfoData(dp); } return NULL; }
ciArgInfoData *ciMethodData::arg_info() const { // Should be last, have to skip all traps. DataLayout* dp = extra_data_base(); DataLayout* end = args_data_limit(); for (; dp < end; dp = MethodData::next_extra(dp)) { if (dp->tag() == DataLayout::arg_info_data_tag) return new ciArgInfoData(dp); } return NULL; }
void MethodData::initialize() { No_Safepoint_Verifier no_safepoint; // init function atomic wrt GC ResourceMark rm; init(); set_creation_mileage(mileage_of(method())); // Go through the bytecodes and allocate and initialize the // corresponding data cells. 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; while ((c = stream.next()) >= 0) { int size_in_bytes = initialize_data(&stream, data_size); data_size += size_in_bytes; if (is_empty_data(size_in_bytes, c)) empty_bc_count++; } _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); int extra_size = extra_data_count * DataLayout::compute_size_in_bytes(0); object_size += extra_size; Copy::zero_to_bytes((HeapWord*) extra_data_base(), extra_size); #ifndef GRAALVM // 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); int arg_size = method()->size_of_parameters(); dp->initialize(DataLayout::arg_info_data_tag, 0, arg_size+1); object_size += DataLayout::compute_size_in_bytes(arg_size+1); #endif // Set an initial hint. Don't use set_hint_di() because // first_di() may be out of bounds if data_size is 0. // In that situation, _hint_di is never used, but at // least well-defined. _hint_di = first_di(); post_initialize(&stream); set_size(object_size); }
void methodDataOopDesc::print_data_on(outputStream* st) { ResourceMark rm; ProfileData* data = first_data(); 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); } DataLayout* dp = extra_data_base(); DataLayout* end = extra_data_limit(); for (; dp < end; dp = next_extra(dp)) { // No need for "OrderAccess::load_acquire" ops, // since the data structure is monotonic. if (dp->tag() == DataLayout::no_tag) break; if (dp == extra_data_base()) st->print_cr("--- Extra data:"); data = new BitData(dp); st->print("%d", dp_to_di(data->dp())); st->fill_to(6); data->print_data_on(st); } }
void ciMethodData::print_data_on(outputStream* st) { ResourceMark rm; ciParametersTypeData* parameters = parameters_type_data(); if (parameters != NULL) { parameters->print_data_on(st); } ciProfileData* data; for (data = first_data(); is_valid(data); data = next_data(data)) { st->print("%d", dp_to_di(data->dp())); st->fill_to(6); data->print_data_on(st); } st->print_cr("--- Extra data:"); DataLayout* dp = extra_data_base(); DataLayout* end = args_data_limit(); for (;; dp = MethodData::next_extra(dp)) { assert(dp < end, "moved past end of extra data"); switch (dp->tag()) { case DataLayout::no_tag: continue; case DataLayout::bit_data_tag: data = new BitData(dp); break; case DataLayout::arg_info_data_tag: data = new ciArgInfoData(dp); dp = end; // ArgInfoData is at the end of extra data section. break; case DataLayout::speculative_trap_data_tag: data = new ciSpeculativeTrapData(dp); 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); if (dp >= end) return; } }