Path: blob/master/src/hotspot/share/ci/ciMethodData.cpp
40931 views
/*1* Copyright (c) 2001, 2021, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 2 along with this work; if not, write to the Free Software Foundation,16* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.17*18* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*22*/2324#include "precompiled.hpp"25#include "ci/ciMetadata.hpp"26#include "ci/ciMethodData.hpp"27#include "ci/ciReplay.hpp"28#include "ci/ciUtilities.inline.hpp"29#include "compiler/compiler_globals.hpp"30#include "memory/allocation.inline.hpp"31#include "memory/resourceArea.hpp"32#include "oops/klass.inline.hpp"33#include "runtime/deoptimization.hpp"34#include "utilities/copy.hpp"3536// ciMethodData3738// ------------------------------------------------------------------39// ciMethodData::ciMethodData40//41ciMethodData::ciMethodData(MethodData* md)42: ciMetadata(md),43_data_size(0), _extra_data_size(0), _data(NULL),44// Set an initial hint. Don't use set_hint_di() because45// first_di() may be out of bounds if data_size is 0.46_hint_di(first_di()),47_state(empty_state),48_saw_free_extra_data(false),49// Initialize the escape information (to "don't know.");50_eflags(0), _arg_local(0), _arg_stack(0), _arg_returned(0),51_creation_mileage(0),52_current_mileage(0),53_invocation_counter(0),54_backedge_counter(0),55_orig(),56_parameters(NULL) {}5758// Check for entries that reference an unloaded method59class PrepareExtraDataClosure : public CleanExtraDataClosure {60MethodData* _mdo;61SafepointStateTracker _safepoint_tracker;62GrowableArray<Method*> _uncached_methods;6364public:65PrepareExtraDataClosure(MethodData* mdo)66: _mdo(mdo),67_safepoint_tracker(SafepointSynchronize::safepoint_state_tracker()),68_uncached_methods()69{ }7071bool is_live(Method* m) {72if (!m->method_holder()->is_loader_alive()) {73return false;74}75if (CURRENT_ENV->cached_metadata(m) == NULL) {76// Uncached entries need to be pre-populated.77_uncached_methods.append(m);78}79return true;80}8182bool has_safepointed() {83return _safepoint_tracker.safepoint_state_changed();84}8586bool finish() {87if (_uncached_methods.length() == 0) {88// Preparation finished iff all Methods* were already cached.89return true;90}91// Holding locks through safepoints is bad practice.92MutexUnlocker mu(_mdo->extra_data_lock());93for (int i = 0; i < _uncached_methods.length(); ++i) {94if (has_safepointed()) {95// The metadata in the growable array might contain stale96// entries after a safepoint.97return false;98}99Method* method = _uncached_methods.at(i);100// Populating ciEnv caches may cause safepoints due101// to taking the Compile_lock with safepoint checks.102(void)CURRENT_ENV->get_method(method);103}104return false;105}106};107108void ciMethodData::prepare_metadata() {109MethodData* mdo = get_MethodData();110111for (;;) {112ResourceMark rm;113PrepareExtraDataClosure cl(mdo);114mdo->clean_extra_data(&cl);115if (cl.finish()) {116// When encountering uncached metadata, the Compile_lock might be117// acquired when creating ciMetadata handles, causing safepoints118// which requires a new round of preparation to clean out potentially119// new unloading metadata.120return;121}122}123}124125void ciMethodData::load_remaining_extra_data() {126MethodData* mdo = get_MethodData();127MutexLocker ml(mdo->extra_data_lock());128// Deferred metadata cleaning due to concurrent class unloading.129prepare_metadata();130// After metadata preparation, there is no stale metadata,131// and no safepoints can introduce more stale metadata.132NoSafepointVerifier no_safepoint;133134assert((mdo->data_size() == _data_size) && (mdo->extra_data_size() == _extra_data_size), "sanity, unchanged");135assert(extra_data_base() == (DataLayout*)((address) _data + _data_size), "sanity");136137// Copy the extra data once it is prepared (i.e. cache populated, no release of extra data lock anymore)138Copy::disjoint_words_atomic((HeapWord*) mdo->extra_data_base(),139(HeapWord*)((address) _data + _data_size),140(_extra_data_size - mdo->parameters_size_in_bytes()) / HeapWordSize);141142// speculative trap entries also hold a pointer to a Method so need to be translated143DataLayout* dp_src = mdo->extra_data_base();144DataLayout* end_src = mdo->args_data_limit();145DataLayout* dp_dst = extra_data_base();146for (;; dp_src = MethodData::next_extra(dp_src), dp_dst = MethodData::next_extra(dp_dst)) {147assert(dp_src < end_src, "moved past end of extra data");148assert(((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");149150int tag = dp_src->tag();151switch(tag) {152case DataLayout::speculative_trap_data_tag: {153ciSpeculativeTrapData data_dst(dp_dst);154SpeculativeTrapData data_src(dp_src);155data_dst.translate_from(&data_src);156break;157}158case DataLayout::bit_data_tag:159break;160case DataLayout::no_tag:161case DataLayout::arg_info_data_tag:162// An empty slot or ArgInfoData entry marks the end of the trap data163{164return; // Need a block to avoid SS compiler bug165}166default:167fatal("bad tag = %d", tag);168}169}170}171172bool ciMethodData::load_data() {173MethodData* mdo = get_MethodData();174if (mdo == NULL) {175return false;176}177178// To do: don't copy the data if it is not "ripe" -- require a minimum #179// of invocations.180181// Snapshot the data and extra parameter data first without the extra trap and arg info data.182// Those are copied in a second step. Actually, an approximate snapshot of the data is taken.183// Any concurrently executing threads may be changing the data as we copy it.184//185// The first snapshot step requires two copies (data entries and parameter data entries) since186// the MDO is laid out as follows:187//188// data_base: ---------------------------189// | data entries |190// | ... |191// extra_data_base: ---------------------------192// | trap data entries |193// | ... |194// | one arg info data entry |195// | data for each arg |196// | ... |197// args_data_limit: ---------------------------198// | parameter data entries |199// | ... |200// extra_data_limit: ---------------------------201//202// _data_size = extra_data_base - data_base203// _extra_data_size = extra_data_limit - extra_data_base204// total_size = _data_size + _extra_data_size205// args_data_limit = data_base + total_size - parameter_data_size206207#ifndef ZERO208// Some Zero platforms do not have expected alignment, and do not use209// this code. static_assert would still fire and fail for them.210static_assert(sizeof(_orig) % HeapWordSize == 0, "align");211#endif212Copy::disjoint_words_atomic((HeapWord*) &mdo->_compiler_counters,213(HeapWord*) &_orig,214sizeof(_orig) / HeapWordSize);215Arena* arena = CURRENT_ENV->arena();216_data_size = mdo->data_size();217_extra_data_size = mdo->extra_data_size();218int total_size = _data_size + _extra_data_size;219_data = (intptr_t *) arena->Amalloc(total_size);220Copy::disjoint_words_atomic((HeapWord*) mdo->data_base(),221(HeapWord*) _data,222_data_size / HeapWordSize);223224int parameters_data_size = mdo->parameters_size_in_bytes();225if (parameters_data_size > 0) {226// Snapshot the parameter data227Copy::disjoint_words_atomic((HeapWord*) mdo->args_data_limit(),228(HeapWord*) ((address)_data + total_size - parameters_data_size),229parameters_data_size / HeapWordSize);230}231// Traverse the profile data, translating any oops into their232// ci equivalents.233ResourceMark rm;234ciProfileData* ci_data = first_data();235ProfileData* data = mdo->first_data();236while (is_valid(ci_data)) {237ci_data->translate_from(data);238ci_data = next_data(ci_data);239data = mdo->next_data(data);240}241if (mdo->parameters_type_data() != NULL) {242_parameters = data_layout_at(mdo->parameters_type_data_di());243ciParametersTypeData* parameters = new ciParametersTypeData(_parameters);244parameters->translate_from(mdo->parameters_type_data());245}246247assert((DataLayout*) ((address)_data + total_size - parameters_data_size) == args_data_limit(),248"sanity - parameter data starts after the argument data of the single ArgInfoData entry");249load_remaining_extra_data();250251// Note: Extra data are all BitData, and do not need translation.252_creation_mileage = mdo->creation_mileage();253_current_mileage = MethodData::mileage_of(mdo->method());254_invocation_counter = mdo->invocation_count();255_backedge_counter = mdo->backedge_count();256_state = mdo->is_mature()? mature_state: immature_state;257258_eflags = mdo->eflags();259_arg_local = mdo->arg_local();260_arg_stack = mdo->arg_stack();261_arg_returned = mdo->arg_returned();262#ifndef PRODUCT263if (ReplayCompiles) {264ciReplay::initialize(this);265if (is_empty()) {266return false;267}268}269#endif270return true;271}272273void ciReceiverTypeData::translate_receiver_data_from(const ProfileData* data) {274for (uint row = 0; row < row_limit(); row++) {275Klass* k = data->as_ReceiverTypeData()->receiver(row);276if (k != NULL) {277if (k->is_loader_alive()) {278ciKlass* klass = CURRENT_ENV->get_klass(k);279set_receiver(row, klass);280} else {281// With concurrent class unloading, the MDO could have stale metadata; override it282clear_row(row);283}284} else {285set_receiver(row, NULL);286}287}288}289290void ciTypeStackSlotEntries::translate_type_data_from(const TypeStackSlotEntries* entries) {291for (int i = 0; i < number_of_entries(); i++) {292intptr_t k = entries->type(i);293Klass* klass = (Klass*)klass_part(k);294if (klass != NULL && !klass->is_loader_alive()) {295// With concurrent class unloading, the MDO could have stale metadata; override it296TypeStackSlotEntries::set_type(i, TypeStackSlotEntries::with_status((Klass*)NULL, k));297} else {298TypeStackSlotEntries::set_type(i, translate_klass(k));299}300}301}302303void ciReturnTypeEntry::translate_type_data_from(const ReturnTypeEntry* ret) {304intptr_t k = ret->type();305Klass* klass = (Klass*)klass_part(k);306if (klass != NULL && !klass->is_loader_alive()) {307// With concurrent class unloading, the MDO could have stale metadata; override it308set_type(ReturnTypeEntry::with_status((Klass*)NULL, k));309} else {310set_type(translate_klass(k));311}312}313314void ciSpeculativeTrapData::translate_from(const ProfileData* data) {315Method* m = data->as_SpeculativeTrapData()->method();316ciMethod* ci_m = CURRENT_ENV->get_method(m);317set_method(ci_m);318}319320// Get the data at an arbitrary (sort of) data index.321ciProfileData* ciMethodData::data_at(int data_index) {322if (out_of_bounds(data_index)) {323return NULL;324}325DataLayout* data_layout = data_layout_at(data_index);326return data_from(data_layout);327}328329ciProfileData* ciMethodData::data_from(DataLayout* data_layout) {330switch (data_layout->tag()) {331case DataLayout::no_tag:332default:333ShouldNotReachHere();334return NULL;335case DataLayout::bit_data_tag:336return new ciBitData(data_layout);337case DataLayout::counter_data_tag:338return new ciCounterData(data_layout);339case DataLayout::jump_data_tag:340return new ciJumpData(data_layout);341case DataLayout::receiver_type_data_tag:342return new ciReceiverTypeData(data_layout);343case DataLayout::virtual_call_data_tag:344return new ciVirtualCallData(data_layout);345case DataLayout::ret_data_tag:346return new ciRetData(data_layout);347case DataLayout::branch_data_tag:348return new ciBranchData(data_layout);349case DataLayout::multi_branch_data_tag:350return new ciMultiBranchData(data_layout);351case DataLayout::arg_info_data_tag:352return new ciArgInfoData(data_layout);353case DataLayout::call_type_data_tag:354return new ciCallTypeData(data_layout);355case DataLayout::virtual_call_type_data_tag:356return new ciVirtualCallTypeData(data_layout);357case DataLayout::parameters_type_data_tag:358return new ciParametersTypeData(data_layout);359};360}361362// Iteration over data.363ciProfileData* ciMethodData::next_data(ciProfileData* current) {364int current_index = dp_to_di(current->dp());365int next_index = current_index + current->size_in_bytes();366ciProfileData* next = data_at(next_index);367return next;368}369370DataLayout* ciMethodData::next_data_layout(DataLayout* current) {371int current_index = dp_to_di((address)current);372int next_index = current_index + current->size_in_bytes();373if (out_of_bounds(next_index)) {374return NULL;375}376DataLayout* next = data_layout_at(next_index);377return next;378}379380ciProfileData* ciMethodData::bci_to_extra_data(int bci, ciMethod* m, bool& two_free_slots) {381DataLayout* dp = extra_data_base();382DataLayout* end = args_data_limit();383two_free_slots = false;384for (;dp < end; dp = MethodData::next_extra(dp)) {385switch(dp->tag()) {386case DataLayout::no_tag:387_saw_free_extra_data = true; // observed an empty slot (common case)388two_free_slots = (MethodData::next_extra(dp)->tag() == DataLayout::no_tag);389return NULL;390case DataLayout::arg_info_data_tag:391return NULL; // ArgInfoData is after the trap data right before the parameter data.392case DataLayout::bit_data_tag:393if (m == NULL && dp->bci() == bci) {394return new ciBitData(dp);395}396break;397case DataLayout::speculative_trap_data_tag: {398ciSpeculativeTrapData* data = new ciSpeculativeTrapData(dp);399// data->method() might be null if the MDO is snapshotted400// concurrently with a trap401if (m != NULL && data->method() == m && dp->bci() == bci) {402return data;403}404break;405}406default:407fatal("bad tag = %d", dp->tag());408}409}410return NULL;411}412413// Translate a bci to its corresponding data, or NULL.414ciProfileData* ciMethodData::bci_to_data(int bci, ciMethod* m) {415// If m is not NULL we look for a SpeculativeTrapData entry416if (m == NULL) {417DataLayout* data_layout = data_layout_before(bci);418for ( ; is_valid(data_layout); data_layout = next_data_layout(data_layout)) {419if (data_layout->bci() == bci) {420set_hint_di(dp_to_di((address)data_layout));421return data_from(data_layout);422} else if (data_layout->bci() > bci) {423break;424}425}426}427bool two_free_slots = false;428ciProfileData* result = bci_to_extra_data(bci, m, two_free_slots);429if (result != NULL) {430return result;431}432if (m != NULL && !two_free_slots) {433// We were looking for a SpeculativeTrapData entry we didn't434// find. Room is not available for more SpeculativeTrapData435// entries, look in the non SpeculativeTrapData entries.436return bci_to_data(bci, NULL);437}438return NULL;439}440441// Conservatively decode the trap_state of a ciProfileData.442int ciMethodData::has_trap_at(ciProfileData* data, int reason) {443typedef Deoptimization::DeoptReason DR_t;444int per_bc_reason445= Deoptimization::reason_recorded_per_bytecode_if_any((DR_t) reason);446if (trap_count(reason) == 0) {447// Impossible for this trap to have occurred, regardless of trap_state.448// Note: This happens if the MDO is empty.449return 0;450} else if (per_bc_reason == Deoptimization::Reason_none) {451// We cannot conclude anything; a trap happened somewhere, maybe here.452return -1;453} else if (data == NULL) {454// No profile here, not even an extra_data record allocated on the fly.455// If there are empty extra_data records, and there had been a trap,456// there would have been a non-null data pointer. If there are no457// free extra_data records, we must return a conservative -1.458if (_saw_free_extra_data)459return 0; // Q.E.D.460else461return -1; // bail with a conservative answer462} else {463return Deoptimization::trap_state_has_reason(data->trap_state(), per_bc_reason);464}465}466467int ciMethodData::trap_recompiled_at(ciProfileData* data) {468if (data == NULL) {469return (_saw_free_extra_data? 0: -1); // (see previous method)470} else {471return Deoptimization::trap_state_is_recompiled(data->trap_state())? 1: 0;472}473}474475void ciMethodData::clear_escape_info() {476VM_ENTRY_MARK;477MethodData* mdo = get_MethodData();478if (mdo != NULL) {479mdo->clear_escape_info();480ArgInfoData *aid = arg_info();481int arg_count = (aid == NULL) ? 0 : aid->number_of_args();482for (int i = 0; i < arg_count; i++) {483set_arg_modified(i, 0);484}485}486_eflags = _arg_local = _arg_stack = _arg_returned = 0;487}488489// copy our escape info to the MethodData* if it exists490void ciMethodData::update_escape_info() {491VM_ENTRY_MARK;492MethodData* mdo = get_MethodData();493if ( mdo != NULL) {494mdo->set_eflags(_eflags);495mdo->set_arg_local(_arg_local);496mdo->set_arg_stack(_arg_stack);497mdo->set_arg_returned(_arg_returned);498int arg_count = mdo->method()->size_of_parameters();499for (int i = 0; i < arg_count; i++) {500mdo->set_arg_modified(i, arg_modified(i));501}502}503}504505void ciMethodData::set_compilation_stats(short loops, short blocks) {506VM_ENTRY_MARK;507MethodData* mdo = get_MethodData();508if (mdo != NULL) {509mdo->set_num_loops(loops);510mdo->set_num_blocks(blocks);511}512}513514void ciMethodData::set_would_profile(bool p) {515VM_ENTRY_MARK;516MethodData* mdo = get_MethodData();517if (mdo != NULL) {518mdo->set_would_profile(p);519}520}521522void ciMethodData::set_argument_type(int bci, int i, ciKlass* k) {523VM_ENTRY_MARK;524MethodData* mdo = get_MethodData();525if (mdo != NULL) {526ProfileData* data = mdo->bci_to_data(bci);527if (data != NULL) {528if (data->is_CallTypeData()) {529data->as_CallTypeData()->set_argument_type(i, k->get_Klass());530} else {531assert(data->is_VirtualCallTypeData(), "no arguments!");532data->as_VirtualCallTypeData()->set_argument_type(i, k->get_Klass());533}534}535}536}537538void ciMethodData::set_parameter_type(int i, ciKlass* k) {539VM_ENTRY_MARK;540MethodData* mdo = get_MethodData();541if (mdo != NULL) {542mdo->parameters_type_data()->set_type(i, k->get_Klass());543}544}545546void ciMethodData::set_return_type(int bci, ciKlass* k) {547VM_ENTRY_MARK;548MethodData* mdo = get_MethodData();549if (mdo != NULL) {550ProfileData* data = mdo->bci_to_data(bci);551if (data != NULL) {552if (data->is_CallTypeData()) {553data->as_CallTypeData()->set_return_type(k->get_Klass());554} else {555assert(data->is_VirtualCallTypeData(), "no arguments!");556data->as_VirtualCallTypeData()->set_return_type(k->get_Klass());557}558}559}560}561562bool ciMethodData::has_escape_info() {563return eflag_set(MethodData::estimated);564}565566void ciMethodData::set_eflag(MethodData::EscapeFlag f) {567set_bits(_eflags, f);568}569570bool ciMethodData::eflag_set(MethodData::EscapeFlag f) const {571return mask_bits(_eflags, f) != 0;572}573574void ciMethodData::set_arg_local(int i) {575set_nth_bit(_arg_local, i);576}577578void ciMethodData::set_arg_stack(int i) {579set_nth_bit(_arg_stack, i);580}581582void ciMethodData::set_arg_returned(int i) {583set_nth_bit(_arg_returned, i);584}585586void ciMethodData::set_arg_modified(int arg, uint val) {587ArgInfoData *aid = arg_info();588if (aid == NULL)589return;590assert(arg >= 0 && arg < aid->number_of_args(), "valid argument number");591aid->set_arg_modified(arg, val);592}593594bool ciMethodData::is_arg_local(int i) const {595return is_set_nth_bit(_arg_local, i);596}597598bool ciMethodData::is_arg_stack(int i) const {599return is_set_nth_bit(_arg_stack, i);600}601602bool ciMethodData::is_arg_returned(int i) const {603return is_set_nth_bit(_arg_returned, i);604}605606uint ciMethodData::arg_modified(int arg) const {607ArgInfoData *aid = arg_info();608if (aid == NULL)609return 0;610assert(arg >= 0 && arg < aid->number_of_args(), "valid argument number");611return aid->arg_modified(arg);612}613614ByteSize ciMethodData::offset_of_slot(ciProfileData* data, ByteSize slot_offset_in_data) {615// Get offset within MethodData* of the data array616ByteSize data_offset = MethodData::data_offset();617618// Get cell offset of the ProfileData within data array619int cell_offset = dp_to_di(data->dp());620621// Add in counter_offset, the # of bytes into the ProfileData of counter or flag622int offset = in_bytes(data_offset) + cell_offset + in_bytes(slot_offset_in_data);623624return in_ByteSize(offset);625}626627ciArgInfoData *ciMethodData::arg_info() const {628// Should be last, have to skip all traps.629DataLayout* dp = extra_data_base();630DataLayout* end = args_data_limit();631for (; dp < end; dp = MethodData::next_extra(dp)) {632if (dp->tag() == DataLayout::arg_info_data_tag)633return new ciArgInfoData(dp);634}635return NULL;636}637638639// Implementation of the print method.640void ciMethodData::print_impl(outputStream* st) {641ciMetadata::print_impl(st);642}643644void ciMethodData::dump_replay_data_type_helper(outputStream* out, int round, int& count, ProfileData* pdata, ByteSize offset, ciKlass* k) {645if (k != NULL) {646if (round == 0) {647count++;648} else {649out->print(" %d %s", (int)(dp_to_di(pdata->dp() + in_bytes(offset)) / sizeof(intptr_t)), k->name()->as_quoted_ascii());650}651}652}653654template<class T> void ciMethodData::dump_replay_data_receiver_type_helper(outputStream* out, int round, int& count, T* vdata) {655for (uint i = 0; i < vdata->row_limit(); i++) {656dump_replay_data_type_helper(out, round, count, vdata, vdata->receiver_offset(i), vdata->receiver(i));657}658}659660template<class T> void ciMethodData::dump_replay_data_call_type_helper(outputStream* out, int round, int& count, T* call_type_data) {661if (call_type_data->has_arguments()) {662for (int i = 0; i < call_type_data->number_of_arguments(); i++) {663dump_replay_data_type_helper(out, round, count, call_type_data, call_type_data->argument_type_offset(i), call_type_data->valid_argument_type(i));664}665}666if (call_type_data->has_return()) {667dump_replay_data_type_helper(out, round, count, call_type_data, call_type_data->return_type_offset(), call_type_data->valid_return_type());668}669}670671void ciMethodData::dump_replay_data_extra_data_helper(outputStream* out, int round, int& count) {672DataLayout* dp = extra_data_base();673DataLayout* end = args_data_limit();674675for (;dp < end; dp = MethodData::next_extra(dp)) {676switch(dp->tag()) {677case DataLayout::no_tag:678case DataLayout::arg_info_data_tag:679return;680case DataLayout::bit_data_tag:681break;682case DataLayout::speculative_trap_data_tag: {683ciSpeculativeTrapData* data = new ciSpeculativeTrapData(dp);684ciMethod* m = data->method();685if (m != NULL) {686if (round == 0) {687count++;688} else {689out->print(" %d ", (int)(dp_to_di(((address)dp) + in_bytes(ciSpeculativeTrapData::method_offset())) / sizeof(intptr_t)));690m->dump_name_as_ascii(out);691}692}693break;694}695default:696fatal("bad tag = %d", dp->tag());697}698}699}700701void ciMethodData::dump_replay_data(outputStream* out) {702ResourceMark rm;703MethodData* mdo = get_MethodData();704Method* method = mdo->method();705Klass* holder = method->method_holder();706out->print("ciMethodData %s %s %s %d %d",707holder->name()->as_quoted_ascii(),708method->name()->as_quoted_ascii(),709method->signature()->as_quoted_ascii(),710_state,711current_mileage());712713// dump the contents of the MDO header as raw data714unsigned char* orig = (unsigned char*)&_orig;715int length = sizeof(_orig);716out->print(" orig %d", length);717for (int i = 0; i < length; i++) {718out->print(" %d", orig[i]);719}720721// dump the MDO data as raw data722int elements = (data_size() + extra_data_size()) / sizeof(intptr_t);723out->print(" data %d", elements);724for (int i = 0; i < elements; i++) {725// We could use INTPTR_FORMAT here but that's zero justified726// which makes comparing it with the SA version of this output727// harder. data()'s element type is intptr_t.728out->print(" " INTPTRNZ_FORMAT, data()[i]);729}730731// The MDO contained oop references as ciObjects, so scan for those732// and emit pairs of offset and klass name so that they can be733// reconstructed at runtime. The first round counts the number of734// oop references and the second actually emits them.735ciParametersTypeData* parameters = parameters_type_data();736for (int count = 0, round = 0; round < 2; round++) {737if (round == 1) out->print(" oops %d", count);738ProfileData* pdata = first_data();739for ( ; is_valid(pdata); pdata = next_data(pdata)) {740if (pdata->is_VirtualCallData()) {741ciVirtualCallData* vdata = (ciVirtualCallData*)pdata;742dump_replay_data_receiver_type_helper<ciVirtualCallData>(out, round, count, vdata);743if (pdata->is_VirtualCallTypeData()) {744ciVirtualCallTypeData* call_type_data = (ciVirtualCallTypeData*)pdata;745dump_replay_data_call_type_helper<ciVirtualCallTypeData>(out, round, count, call_type_data);746}747} else if (pdata->is_ReceiverTypeData()) {748ciReceiverTypeData* vdata = (ciReceiverTypeData*)pdata;749dump_replay_data_receiver_type_helper<ciReceiverTypeData>(out, round, count, vdata);750} else if (pdata->is_CallTypeData()) {751ciCallTypeData* call_type_data = (ciCallTypeData*)pdata;752dump_replay_data_call_type_helper<ciCallTypeData>(out, round, count, call_type_data);753}754}755if (parameters != NULL) {756for (int i = 0; i < parameters->number_of_parameters(); i++) {757dump_replay_data_type_helper(out, round, count, parameters, ParametersTypeData::type_offset(i), parameters->valid_parameter_type(i));758}759}760}761for (int count = 0, round = 0; round < 2; round++) {762if (round == 1) out->print(" methods %d", count);763dump_replay_data_extra_data_helper(out, round, count);764}765out->cr();766}767768#ifndef PRODUCT769void ciMethodData::print() {770print_data_on(tty);771}772773void ciMethodData::print_data_on(outputStream* st) {774ResourceMark rm;775ciParametersTypeData* parameters = parameters_type_data();776if (parameters != NULL) {777parameters->print_data_on(st);778}779ciProfileData* data;780for (data = first_data(); is_valid(data); data = next_data(data)) {781st->print("%d", dp_to_di(data->dp()));782st->fill_to(6);783data->print_data_on(st);784}785st->print_cr("--- Extra data:");786DataLayout* dp = extra_data_base();787DataLayout* end = args_data_limit();788for (;; dp = MethodData::next_extra(dp)) {789assert(dp < end, "moved past end of extra data");790switch (dp->tag()) {791case DataLayout::no_tag:792continue;793case DataLayout::bit_data_tag:794data = new BitData(dp);795break;796case DataLayout::arg_info_data_tag:797data = new ciArgInfoData(dp);798dp = end; // ArgInfoData is after the trap data right before the parameter data.799break;800case DataLayout::speculative_trap_data_tag:801data = new ciSpeculativeTrapData(dp);802break;803default:804fatal("unexpected tag %d", dp->tag());805}806st->print("%d", dp_to_di(data->dp()));807st->fill_to(6);808data->print_data_on(st);809if (dp >= end) return;810}811}812813void ciTypeEntries::print_ciklass(outputStream* st, intptr_t k) {814if (TypeEntries::is_type_none(k)) {815st->print("none");816} else if (TypeEntries::is_type_unknown(k)) {817st->print("unknown");818} else {819valid_ciklass(k)->print_name_on(st);820}821if (TypeEntries::was_null_seen(k)) {822st->print(" (null seen)");823}824}825826void ciTypeStackSlotEntries::print_data_on(outputStream* st) const {827for (int i = 0; i < number_of_entries(); i++) {828_pd->tab(st);829st->print("%d: stack (%u) ", i, stack_slot(i));830print_ciklass(st, type(i));831st->cr();832}833}834835void ciReturnTypeEntry::print_data_on(outputStream* st) const {836_pd->tab(st);837st->print("ret ");838print_ciklass(st, type());839st->cr();840}841842void ciCallTypeData::print_data_on(outputStream* st, const char* extra) const {843print_shared(st, "ciCallTypeData", extra);844if (has_arguments()) {845tab(st, true);846st->print_cr("argument types");847args()->print_data_on(st);848}849if (has_return()) {850tab(st, true);851st->print_cr("return type");852ret()->print_data_on(st);853}854}855856void ciReceiverTypeData::print_receiver_data_on(outputStream* st) const {857uint row;858int entries = 0;859for (row = 0; row < row_limit(); row++) {860if (receiver(row) != NULL) entries++;861}862st->print_cr("count(%u) entries(%u)", count(), entries);863for (row = 0; row < row_limit(); row++) {864if (receiver(row) != NULL) {865tab(st);866receiver(row)->print_name_on(st);867st->print_cr("(%u)", receiver_count(row));868}869}870}871872void ciReceiverTypeData::print_data_on(outputStream* st, const char* extra) const {873print_shared(st, "ciReceiverTypeData", extra);874print_receiver_data_on(st);875}876877void ciVirtualCallData::print_data_on(outputStream* st, const char* extra) const {878print_shared(st, "ciVirtualCallData", extra);879rtd_super()->print_receiver_data_on(st);880}881882void ciVirtualCallTypeData::print_data_on(outputStream* st, const char* extra) const {883print_shared(st, "ciVirtualCallTypeData", extra);884rtd_super()->print_receiver_data_on(st);885if (has_arguments()) {886tab(st, true);887st->print("argument types");888args()->print_data_on(st);889}890if (has_return()) {891tab(st, true);892st->print("return type");893ret()->print_data_on(st);894}895}896897void ciParametersTypeData::print_data_on(outputStream* st, const char* extra) const {898st->print_cr("ciParametersTypeData");899parameters()->print_data_on(st);900}901902void ciSpeculativeTrapData::print_data_on(outputStream* st, const char* extra) const {903st->print_cr("ciSpeculativeTrapData");904tab(st);905method()->print_short_name(st);906st->cr();907}908#endif909910911