duke@435: /* coleenp@4037: * Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved. duke@435: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. duke@435: * duke@435: * This code is free software; you can redistribute it and/or modify it duke@435: * under the terms of the GNU General Public License version 2 only, as duke@435: * published by the Free Software Foundation. duke@435: * duke@435: * This code is distributed in the hope that it will be useful, but WITHOUT duke@435: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or duke@435: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License duke@435: * version 2 for more details (a copy is included in the LICENSE file that duke@435: * accompanied this code). duke@435: * duke@435: * You should have received a copy of the GNU General Public License version duke@435: * 2 along with this work; if not, write to the Free Software Foundation, duke@435: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. duke@435: * trims@1907: * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA trims@1907: * or visit www.oracle.com if you need additional information or have any trims@1907: * questions. duke@435: * duke@435: */ duke@435: stefank@2314: #include "precompiled.hpp" coleenp@4037: #include "ci/ciMetadata.hpp" stefank@2314: #include "ci/ciMethodData.hpp" minqi@4267: #include "ci/ciReplay.hpp" stefank@2314: #include "ci/ciUtilities.hpp" stefank@2314: #include "memory/allocation.inline.hpp" stefank@2314: #include "memory/resourceArea.hpp" stefank@2314: #include "runtime/deoptimization.hpp" stefank@2314: #include "utilities/copy.hpp" duke@435: duke@435: // ciMethodData duke@435: duke@435: // ------------------------------------------------------------------ duke@435: // ciMethodData::ciMethodData duke@435: // coleenp@4037: ciMethodData::ciMethodData(MethodData* md) : ciMetadata(md) { coleenp@4037: assert(md != NULL, "no null method data"); duke@435: Copy::zero_to_words((HeapWord*) &_orig, sizeof(_orig) / sizeof(HeapWord)); duke@435: _data = NULL; duke@435: _data_size = 0; duke@435: _extra_data_size = 0; duke@435: _current_mileage = 0; iveresov@2138: _invocation_counter = 0; iveresov@2138: _backedge_counter = 0; duke@435: _state = empty_state; duke@435: _saw_free_extra_data = false; duke@435: // Set an initial hint. Don't use set_hint_di() because duke@435: // first_di() may be out of bounds if data_size is 0. duke@435: _hint_di = first_di(); kvn@480: // Initialize the escape information (to "don't know."); kvn@480: _eflags = _arg_local = _arg_stack = _arg_returned = 0; roland@5987: _parameters = NULL; duke@435: } duke@435: duke@435: // ------------------------------------------------------------------ duke@435: // ciMethodData::ciMethodData duke@435: // coleenp@4037: // No MethodData*. coleenp@4037: ciMethodData::ciMethodData() : ciMetadata(NULL) { duke@435: Copy::zero_to_words((HeapWord*) &_orig, sizeof(_orig) / sizeof(HeapWord)); duke@435: _data = NULL; duke@435: _data_size = 0; duke@435: _extra_data_size = 0; duke@435: _current_mileage = 0; iveresov@2138: _invocation_counter = 0; iveresov@2138: _backedge_counter = 0; duke@435: _state = empty_state; duke@435: _saw_free_extra_data = false; duke@435: // Set an initial hint. Don't use set_hint_di() because duke@435: // first_di() may be out of bounds if data_size is 0. duke@435: _hint_di = first_di(); kvn@480: // Initialize the escape information (to "don't know."); kvn@480: _eflags = _arg_local = _arg_stack = _arg_returned = 0; roland@5987: _parameters = NULL; duke@435: } duke@435: duke@435: void ciMethodData::load_data() { coleenp@4037: MethodData* mdo = get_MethodData(); twisti@5907: if (mdo == NULL) { twisti@5907: return; twisti@5907: } duke@435: duke@435: // To do: don't copy the data if it is not "ripe" -- require a minimum # duke@435: // of invocations. duke@435: duke@435: // Snapshot the data -- actually, take an approximate snapshot of duke@435: // the data. Any concurrently executing threads may be changing the duke@435: // data as we copy it. coleenp@4037: Copy::disjoint_words((HeapWord*) mdo, coleenp@4037: (HeapWord*) &_orig, coleenp@4037: sizeof(_orig) / HeapWordSize); duke@435: Arena* arena = CURRENT_ENV->arena(); duke@435: _data_size = mdo->data_size(); duke@435: _extra_data_size = mdo->extra_data_size(); duke@435: int total_size = _data_size + _extra_data_size; duke@435: _data = (intptr_t *) arena->Amalloc(total_size); duke@435: Copy::disjoint_words((HeapWord*) mdo->data_base(), (HeapWord*) _data, total_size / HeapWordSize); duke@435: duke@435: // Traverse the profile data, translating any oops into their duke@435: // ci equivalents. duke@435: ResourceMark rm; duke@435: ciProfileData* ci_data = first_data(); duke@435: ProfileData* data = mdo->first_data(); duke@435: while (is_valid(ci_data)) { duke@435: ci_data->translate_from(data); duke@435: ci_data = next_data(ci_data); duke@435: data = mdo->next_data(data); duke@435: } roland@5987: if (mdo->parameters_type_data() != NULL) { roland@5987: _parameters = data_layout_at(mdo->parameters_type_data_di()); roland@5987: ciParametersTypeData* parameters = new ciParametersTypeData(_parameters); roland@5987: parameters->translate_from(mdo->parameters_type_data()); roland@5987: } roland@5987: duke@435: // Note: Extra data are all BitData, and do not need translation. coleenp@4037: _current_mileage = MethodData::mileage_of(mdo->method()); iveresov@2138: _invocation_counter = mdo->invocation_count(); iveresov@2138: _backedge_counter = mdo->backedge_count(); duke@435: _state = mdo->is_mature()? mature_state: immature_state; duke@435: duke@435: _eflags = mdo->eflags(); duke@435: _arg_local = mdo->arg_local(); duke@435: _arg_stack = mdo->arg_stack(); duke@435: _arg_returned = mdo->arg_returned(); minqi@4267: #ifndef PRODUCT minqi@4267: if (ReplayCompiles) { minqi@4267: ciReplay::initialize(this); minqi@4267: } minqi@4267: #endif duke@435: } duke@435: roland@5914: void ciReceiverTypeData::translate_receiver_data_from(const ProfileData* data) { duke@435: for (uint row = 0; row < row_limit(); row++) { coleenp@4037: Klass* k = data->as_ReceiverTypeData()->receiver(row); duke@435: if (k != NULL) { coleenp@4037: ciKlass* klass = CURRENT_ENV->get_klass(k); duke@435: set_receiver(row, klass); duke@435: } duke@435: } duke@435: } duke@435: duke@435: roland@5914: void ciTypeStackSlotEntries::translate_type_data_from(const TypeStackSlotEntries* entries) { roland@5921: for (int i = 0; i < _number_of_entries; i++) { roland@5914: intptr_t k = entries->type(i); roland@5914: TypeStackSlotEntries::set_type(i, translate_klass(k)); roland@5914: } roland@5914: } roland@5914: roland@5921: void ciReturnTypeEntry::translate_type_data_from(const ReturnTypeEntry* ret) { roland@5921: intptr_t k = ret->type(); roland@5921: set_type(translate_klass(k)); roland@5921: } roland@5921: duke@435: // Get the data at an arbitrary (sort of) data index. duke@435: ciProfileData* ciMethodData::data_at(int data_index) { duke@435: if (out_of_bounds(data_index)) { duke@435: return NULL; duke@435: } duke@435: DataLayout* data_layout = data_layout_at(data_index); duke@435: duke@435: switch (data_layout->tag()) { duke@435: case DataLayout::no_tag: duke@435: default: duke@435: ShouldNotReachHere(); duke@435: return NULL; duke@435: case DataLayout::bit_data_tag: duke@435: return new ciBitData(data_layout); duke@435: case DataLayout::counter_data_tag: duke@435: return new ciCounterData(data_layout); duke@435: case DataLayout::jump_data_tag: duke@435: return new ciJumpData(data_layout); duke@435: case DataLayout::receiver_type_data_tag: duke@435: return new ciReceiverTypeData(data_layout); duke@435: case DataLayout::virtual_call_data_tag: duke@435: return new ciVirtualCallData(data_layout); duke@435: case DataLayout::ret_data_tag: duke@435: return new ciRetData(data_layout); duke@435: case DataLayout::branch_data_tag: duke@435: return new ciBranchData(data_layout); duke@435: case DataLayout::multi_branch_data_tag: duke@435: return new ciMultiBranchData(data_layout); kvn@480: case DataLayout::arg_info_data_tag: kvn@480: return new ciArgInfoData(data_layout); roland@5914: case DataLayout::call_type_data_tag: roland@5914: return new ciCallTypeData(data_layout); roland@5914: case DataLayout::virtual_call_type_data_tag: roland@5914: return new ciVirtualCallTypeData(data_layout); roland@5987: case DataLayout::parameters_type_data_tag: roland@5987: return new ciParametersTypeData(data_layout); duke@435: }; duke@435: } duke@435: duke@435: // Iteration over data. duke@435: ciProfileData* ciMethodData::next_data(ciProfileData* current) { duke@435: int current_index = dp_to_di(current->dp()); duke@435: int next_index = current_index + current->size_in_bytes(); duke@435: ciProfileData* next = data_at(next_index); duke@435: return next; duke@435: } duke@435: duke@435: // Translate a bci to its corresponding data, or NULL. duke@435: ciProfileData* ciMethodData::bci_to_data(int bci) { duke@435: ciProfileData* data = data_before(bci); duke@435: for ( ; is_valid(data); data = next_data(data)) { duke@435: if (data->bci() == bci) { duke@435: set_hint_di(dp_to_di(data->dp())); duke@435: return data; duke@435: } else if (data->bci() > bci) { duke@435: break; duke@435: } duke@435: } duke@435: // bci_to_extra_data(bci) ... duke@435: DataLayout* dp = data_layout_at(data_size()); duke@435: DataLayout* end = data_layout_at(data_size() + extra_data_size()); coleenp@4037: for (; dp < end; dp = MethodData::next_extra(dp)) { duke@435: if (dp->tag() == DataLayout::no_tag) { duke@435: _saw_free_extra_data = true; // observed an empty slot (common case) duke@435: return NULL; duke@435: } kvn@480: if (dp->tag() == DataLayout::arg_info_data_tag) { kvn@480: break; // ArgInfoData is at the end of extra data section. kvn@480: } duke@435: if (dp->bci() == bci) { duke@435: assert(dp->tag() == DataLayout::bit_data_tag, "sane"); duke@435: return new ciBitData(dp); duke@435: } duke@435: } duke@435: return NULL; duke@435: } duke@435: duke@435: // Conservatively decode the trap_state of a ciProfileData. duke@435: int ciMethodData::has_trap_at(ciProfileData* data, int reason) { duke@435: typedef Deoptimization::DeoptReason DR_t; duke@435: int per_bc_reason duke@435: = Deoptimization::reason_recorded_per_bytecode_if_any((DR_t) reason); duke@435: if (trap_count(reason) == 0) { duke@435: // Impossible for this trap to have occurred, regardless of trap_state. duke@435: // Note: This happens if the MDO is empty. duke@435: return 0; duke@435: } else if (per_bc_reason == Deoptimization::Reason_none) { duke@435: // We cannot conclude anything; a trap happened somewhere, maybe here. duke@435: return -1; duke@435: } else if (data == NULL) { duke@435: // No profile here, not even an extra_data record allocated on the fly. duke@435: // If there are empty extra_data records, and there had been a trap, duke@435: // there would have been a non-null data pointer. If there are no duke@435: // free extra_data records, we must return a conservative -1. duke@435: if (_saw_free_extra_data) duke@435: return 0; // Q.E.D. duke@435: else duke@435: return -1; // bail with a conservative answer duke@435: } else { duke@435: return Deoptimization::trap_state_has_reason(data->trap_state(), per_bc_reason); duke@435: } duke@435: } duke@435: duke@435: int ciMethodData::trap_recompiled_at(ciProfileData* data) { duke@435: if (data == NULL) { duke@435: return (_saw_free_extra_data? 0: -1); // (see previous method) duke@435: } else { duke@435: return Deoptimization::trap_state_is_recompiled(data->trap_state())? 1: 0; duke@435: } duke@435: } duke@435: duke@435: void ciMethodData::clear_escape_info() { duke@435: VM_ENTRY_MARK; coleenp@4037: MethodData* mdo = get_MethodData(); kvn@480: if (mdo != NULL) { duke@435: mdo->clear_escape_info(); kvn@480: ArgInfoData *aid = arg_info(); kvn@480: int arg_count = (aid == NULL) ? 0 : aid->number_of_args(); kvn@480: for (int i = 0; i < arg_count; i++) { kvn@480: set_arg_modified(i, 0); kvn@480: } kvn@480: } duke@435: _eflags = _arg_local = _arg_stack = _arg_returned = 0; duke@435: } duke@435: coleenp@4037: // copy our escape info to the MethodData* if it exists duke@435: void ciMethodData::update_escape_info() { duke@435: VM_ENTRY_MARK; coleenp@4037: MethodData* mdo = get_MethodData(); duke@435: if ( mdo != NULL) { duke@435: mdo->set_eflags(_eflags); duke@435: mdo->set_arg_local(_arg_local); duke@435: mdo->set_arg_stack(_arg_stack); duke@435: mdo->set_arg_returned(_arg_returned); kvn@480: int arg_count = mdo->method()->size_of_parameters(); kvn@480: for (int i = 0; i < arg_count; i++) { kvn@480: mdo->set_arg_modified(i, arg_modified(i)); kvn@480: } duke@435: } duke@435: } duke@435: iveresov@2138: void ciMethodData::set_compilation_stats(short loops, short blocks) { iveresov@2138: VM_ENTRY_MARK; coleenp@4037: MethodData* mdo = get_MethodData(); iveresov@2138: if (mdo != NULL) { iveresov@2138: mdo->set_num_loops(loops); iveresov@2138: mdo->set_num_blocks(blocks); iveresov@2138: } iveresov@2138: } iveresov@2138: iveresov@2138: void ciMethodData::set_would_profile(bool p) { iveresov@2138: VM_ENTRY_MARK; coleenp@4037: MethodData* mdo = get_MethodData(); iveresov@2138: if (mdo != NULL) { iveresov@2138: mdo->set_would_profile(p); iveresov@2138: } iveresov@2138: } iveresov@2138: roland@5914: void ciMethodData::set_argument_type(int bci, int i, ciKlass* k) { roland@5914: VM_ENTRY_MARK; roland@5914: MethodData* mdo = get_MethodData(); roland@5914: if (mdo != NULL) { roland@5914: ProfileData* data = mdo->bci_to_data(bci); roland@5914: if (data->is_CallTypeData()) { roland@5914: data->as_CallTypeData()->set_argument_type(i, k->get_Klass()); roland@5914: } else { roland@5914: assert(data->is_VirtualCallTypeData(), "no arguments!"); roland@5914: data->as_VirtualCallTypeData()->set_argument_type(i, k->get_Klass()); roland@5914: } roland@5914: } roland@5914: } roland@5914: roland@5987: void ciMethodData::set_parameter_type(int i, ciKlass* k) { roland@5987: VM_ENTRY_MARK; roland@5987: MethodData* mdo = get_MethodData(); roland@5987: if (mdo != NULL) { roland@5987: mdo->parameters_type_data()->set_type(i, k->get_Klass()); roland@5987: } roland@5987: } roland@5987: roland@5921: void ciMethodData::set_return_type(int bci, ciKlass* k) { roland@5921: VM_ENTRY_MARK; roland@5921: MethodData* mdo = get_MethodData(); roland@5921: if (mdo != NULL) { roland@5921: ProfileData* data = mdo->bci_to_data(bci); roland@5921: if (data->is_CallTypeData()) { roland@5921: data->as_CallTypeData()->set_return_type(k->get_Klass()); roland@5921: } else { roland@5921: assert(data->is_VirtualCallTypeData(), "no arguments!"); roland@5921: data->as_VirtualCallTypeData()->set_return_type(k->get_Klass()); roland@5921: } roland@5921: } roland@5921: } roland@5921: duke@435: bool ciMethodData::has_escape_info() { coleenp@4037: return eflag_set(MethodData::estimated); duke@435: } duke@435: coleenp@4037: void ciMethodData::set_eflag(MethodData::EscapeFlag f) { duke@435: set_bits(_eflags, f); duke@435: } duke@435: coleenp@4037: void ciMethodData::clear_eflag(MethodData::EscapeFlag f) { duke@435: clear_bits(_eflags, f); duke@435: } duke@435: coleenp@4037: bool ciMethodData::eflag_set(MethodData::EscapeFlag f) const { duke@435: return mask_bits(_eflags, f) != 0; duke@435: } duke@435: duke@435: void ciMethodData::set_arg_local(int i) { duke@435: set_nth_bit(_arg_local, i); duke@435: } duke@435: duke@435: void ciMethodData::set_arg_stack(int i) { duke@435: set_nth_bit(_arg_stack, i); duke@435: } duke@435: duke@435: void ciMethodData::set_arg_returned(int i) { duke@435: set_nth_bit(_arg_returned, i); duke@435: } duke@435: kvn@480: void ciMethodData::set_arg_modified(int arg, uint val) { kvn@480: ArgInfoData *aid = arg_info(); kvn@480: if (aid == NULL) kvn@480: return; kvn@480: assert(arg >= 0 && arg < aid->number_of_args(), "valid argument number"); kvn@480: aid->set_arg_modified(arg, val); kvn@480: } kvn@480: duke@435: bool ciMethodData::is_arg_local(int i) const { duke@435: return is_set_nth_bit(_arg_local, i); duke@435: } duke@435: duke@435: bool ciMethodData::is_arg_stack(int i) const { duke@435: return is_set_nth_bit(_arg_stack, i); duke@435: } duke@435: duke@435: bool ciMethodData::is_arg_returned(int i) const { duke@435: return is_set_nth_bit(_arg_returned, i); duke@435: } duke@435: kvn@480: uint ciMethodData::arg_modified(int arg) const { kvn@480: ArgInfoData *aid = arg_info(); kvn@480: if (aid == NULL) kvn@480: return 0; kvn@480: assert(arg >= 0 && arg < aid->number_of_args(), "valid argument number"); kvn@480: return aid->arg_modified(arg); kvn@480: } kvn@480: duke@435: ByteSize ciMethodData::offset_of_slot(ciProfileData* data, ByteSize slot_offset_in_data) { coleenp@4037: // Get offset within MethodData* of the data array coleenp@4037: ByteSize data_offset = MethodData::data_offset(); duke@435: duke@435: // Get cell offset of the ProfileData within data array duke@435: int cell_offset = dp_to_di(data->dp()); duke@435: duke@435: // Add in counter_offset, the # of bytes into the ProfileData of counter or flag duke@435: int offset = in_bytes(data_offset) + cell_offset + in_bytes(slot_offset_in_data); duke@435: duke@435: return in_ByteSize(offset); duke@435: } duke@435: kvn@480: ciArgInfoData *ciMethodData::arg_info() const { kvn@480: // Should be last, have to skip all traps. kvn@480: DataLayout* dp = data_layout_at(data_size()); kvn@480: DataLayout* end = data_layout_at(data_size() + extra_data_size()); coleenp@4037: for (; dp < end; dp = MethodData::next_extra(dp)) { kvn@480: if (dp->tag() == DataLayout::arg_info_data_tag) kvn@480: return new ciArgInfoData(dp); kvn@480: } kvn@480: return NULL; kvn@480: } kvn@480: kvn@480: duke@435: // Implementation of the print method. duke@435: void ciMethodData::print_impl(outputStream* st) { coleenp@4037: ciMetadata::print_impl(st); duke@435: } duke@435: minqi@4267: void ciMethodData::dump_replay_data(outputStream* out) { vlivanov@4531: ResourceMark rm; minqi@4267: MethodData* mdo = get_MethodData(); minqi@4267: Method* method = mdo->method(); minqi@4267: Klass* holder = method->method_holder(); minqi@4267: out->print("ciMethodData %s %s %s %d %d", minqi@4267: holder->name()->as_quoted_ascii(), minqi@4267: method->name()->as_quoted_ascii(), minqi@4267: method->signature()->as_quoted_ascii(), minqi@4267: _state, minqi@4267: current_mileage()); minqi@4267: minqi@4267: // dump the contents of the MDO header as raw data minqi@4267: unsigned char* orig = (unsigned char*)&_orig; minqi@4267: int length = sizeof(_orig); minqi@4267: out->print(" orig %d", length); minqi@4267: for (int i = 0; i < length; i++) { minqi@4267: out->print(" %d", orig[i]); minqi@4267: } minqi@4267: minqi@4267: // dump the MDO data as raw data minqi@4267: int elements = data_size() / sizeof(intptr_t); minqi@4267: out->print(" data %d", elements); minqi@4267: for (int i = 0; i < elements; i++) { minqi@4267: // We could use INTPTR_FORMAT here but that's a zero justified minqi@4267: // which makes comparing it with the SA version of this output minqi@4267: // harder. minqi@4267: #ifdef _LP64 minqi@4267: out->print(" 0x%" FORMAT64_MODIFIER "x", data()[i]); minqi@4267: #else minqi@4267: out->print(" 0x%x", data()[i]); minqi@4267: #endif minqi@4267: } minqi@4267: minqi@4267: // The MDO contained oop references as ciObjects, so scan for those minqi@4267: // and emit pairs of offset and klass name so that they can be minqi@4267: // reconstructed at runtime. The first round counts the number of minqi@4267: // oop references and the second actually emits them. minqi@4267: int count = 0; minqi@4267: for (int round = 0; round < 2; round++) { minqi@4267: if (round == 1) out->print(" oops %d", count); minqi@4267: ProfileData* pdata = first_data(); minqi@4267: for ( ; is_valid(pdata); pdata = next_data(pdata)) { minqi@4267: if (pdata->is_ReceiverTypeData()) { minqi@4267: ciReceiverTypeData* vdata = (ciReceiverTypeData*)pdata; minqi@4267: for (uint i = 0; i < vdata->row_limit(); i++) { minqi@4267: ciKlass* k = vdata->receiver(i); minqi@4267: if (k != NULL) { minqi@4267: if (round == 0) { minqi@4267: count++; minqi@4267: } else { minqi@4267: out->print(" %d %s", dp_to_di(vdata->dp() + in_bytes(vdata->receiver_offset(i))) / sizeof(intptr_t), k->name()->as_quoted_ascii()); minqi@4267: } minqi@4267: } minqi@4267: } minqi@4267: } else if (pdata->is_VirtualCallData()) { minqi@4267: ciVirtualCallData* vdata = (ciVirtualCallData*)pdata; minqi@4267: for (uint i = 0; i < vdata->row_limit(); i++) { minqi@4267: ciKlass* k = vdata->receiver(i); minqi@4267: if (k != NULL) { minqi@4267: if (round == 0) { minqi@4267: count++; minqi@4267: } else { minqi@4267: out->print(" %d %s", dp_to_di(vdata->dp() + in_bytes(vdata->receiver_offset(i))) / sizeof(intptr_t), k->name()->as_quoted_ascii()); minqi@4267: } minqi@4267: } minqi@4267: } minqi@4267: } minqi@4267: } minqi@4267: } minqi@4267: out->cr(); minqi@4267: } minqi@4267: duke@435: #ifndef PRODUCT duke@435: void ciMethodData::print() { duke@435: print_data_on(tty); duke@435: } duke@435: duke@435: void ciMethodData::print_data_on(outputStream* st) { duke@435: ResourceMark rm; duke@435: ciProfileData* data; duke@435: for (data = first_data(); is_valid(data); data = next_data(data)) { duke@435: st->print("%d", dp_to_di(data->dp())); duke@435: st->fill_to(6); duke@435: data->print_data_on(st); duke@435: } kvn@480: st->print_cr("--- Extra data:"); kvn@480: DataLayout* dp = data_layout_at(data_size()); kvn@480: DataLayout* end = data_layout_at(data_size() + extra_data_size()); coleenp@4037: for (; dp < end; dp = MethodData::next_extra(dp)) { kvn@480: if (dp->tag() == DataLayout::no_tag) continue; kvn@480: if (dp->tag() == DataLayout::bit_data_tag) { kvn@480: data = new BitData(dp); kvn@480: } else { kvn@480: assert(dp->tag() == DataLayout::arg_info_data_tag, "must be BitData or ArgInfo"); kvn@480: data = new ciArgInfoData(dp); kvn@480: dp = end; // ArgInfoData is at the end of extra data section. kvn@480: } kvn@480: st->print("%d", dp_to_di(data->dp())); kvn@480: st->fill_to(6); kvn@480: data->print_data_on(st); kvn@480: } duke@435: } duke@435: roland@5914: void ciTypeEntries::print_ciklass(outputStream* st, intptr_t k) { roland@5914: if (TypeEntries::is_type_none(k)) { roland@5914: st->print("none"); roland@5914: } else if (TypeEntries::is_type_unknown(k)) { roland@5914: st->print("unknown"); roland@5914: } else { roland@5914: valid_ciklass(k)->print_name_on(st); roland@5914: } roland@5914: if (TypeEntries::was_null_seen(k)) { roland@5914: st->print(" (null seen)"); roland@5914: } roland@5914: } roland@5914: roland@5914: void ciTypeStackSlotEntries::print_data_on(outputStream* st) const { roland@5921: for (int i = 0; i < _number_of_entries; i++) { roland@5914: _pd->tab(st); roland@5914: st->print("%d: stack (%u) ", i, stack_slot(i)); roland@5914: print_ciklass(st, type(i)); roland@5914: st->cr(); roland@5914: } roland@5914: } roland@5914: roland@5921: void ciReturnTypeEntry::print_data_on(outputStream* st) const { roland@5921: _pd->tab(st); roland@5921: st->print("ret "); roland@5921: print_ciklass(st, type()); roland@5921: st->cr(); roland@5921: } roland@5921: roland@5914: void ciCallTypeData::print_data_on(outputStream* st) const { roland@5914: print_shared(st, "ciCallTypeData"); roland@5921: if (has_arguments()) { roland@5921: tab(st, true); roland@5921: st->print("argument types"); roland@5921: args()->print_data_on(st); roland@5921: } roland@5921: if (has_return()) { roland@5921: tab(st, true); roland@5921: st->print("return type"); roland@5921: ret()->print_data_on(st); roland@5921: } roland@5914: } roland@5914: roland@5914: void ciReceiverTypeData::print_receiver_data_on(outputStream* st) const { duke@435: uint row; duke@435: int entries = 0; duke@435: for (row = 0; row < row_limit(); row++) { duke@435: if (receiver(row) != NULL) entries++; duke@435: } duke@435: st->print_cr("count(%u) entries(%u)", count(), entries); duke@435: for (row = 0; row < row_limit(); row++) { duke@435: if (receiver(row) != NULL) { duke@435: tab(st); duke@435: receiver(row)->print_name_on(st); duke@435: st->print_cr("(%u)", receiver_count(row)); duke@435: } duke@435: } duke@435: } duke@435: roland@5914: void ciReceiverTypeData::print_data_on(outputStream* st) const { duke@435: print_shared(st, "ciReceiverTypeData"); duke@435: print_receiver_data_on(st); duke@435: } duke@435: roland@5914: void ciVirtualCallData::print_data_on(outputStream* st) const { duke@435: print_shared(st, "ciVirtualCallData"); duke@435: rtd_super()->print_receiver_data_on(st); duke@435: } roland@5914: roland@5914: void ciVirtualCallTypeData::print_data_on(outputStream* st) const { roland@5914: print_shared(st, "ciVirtualCallTypeData"); roland@5914: rtd_super()->print_receiver_data_on(st); roland@5921: if (has_arguments()) { roland@5921: tab(st, true); roland@5921: st->print("argument types"); roland@5921: args()->print_data_on(st); roland@5921: } roland@5921: if (has_return()) { roland@5921: tab(st, true); roland@5921: st->print("return type"); roland@5921: ret()->print_data_on(st); roland@5921: } roland@5914: } roland@5987: roland@5987: void ciParametersTypeData::print_data_on(outputStream* st) const { roland@5987: st->print_cr("Parametertypes"); roland@5987: parameters()->print_data_on(st); roland@5987: } duke@435: #endif