src/share/vm/ci/ciMethodData.cpp

Mon, 07 Oct 2013 10:41:56 -0700

author
twisti
date
Mon, 07 Oct 2013 10:41:56 -0700
changeset 5907
c775af091fe9
parent 5904
5cc2d82aa82a
child 5914
d13d7aba8c12
permissions
-rw-r--r--

8025566: EXCEPTION_ACCESS_VIOLATION in compiled by C1 String.valueOf method
Reviewed-by: kvn

duke@435 1 /*
coleenp@4037 2 * Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved.
duke@435 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
duke@435 4 *
duke@435 5 * This code is free software; you can redistribute it and/or modify it
duke@435 6 * under the terms of the GNU General Public License version 2 only, as
duke@435 7 * published by the Free Software Foundation.
duke@435 8 *
duke@435 9 * This code is distributed in the hope that it will be useful, but WITHOUT
duke@435 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
duke@435 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
duke@435 12 * version 2 for more details (a copy is included in the LICENSE file that
duke@435 13 * accompanied this code).
duke@435 14 *
duke@435 15 * You should have received a copy of the GNU General Public License version
duke@435 16 * 2 along with this work; if not, write to the Free Software Foundation,
duke@435 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
duke@435 18 *
trims@1907 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
trims@1907 20 * or visit www.oracle.com if you need additional information or have any
trims@1907 21 * questions.
duke@435 22 *
duke@435 23 */
duke@435 24
stefank@2314 25 #include "precompiled.hpp"
coleenp@4037 26 #include "ci/ciMetadata.hpp"
stefank@2314 27 #include "ci/ciMethodData.hpp"
minqi@4267 28 #include "ci/ciReplay.hpp"
stefank@2314 29 #include "ci/ciUtilities.hpp"
stefank@2314 30 #include "memory/allocation.inline.hpp"
stefank@2314 31 #include "memory/resourceArea.hpp"
stefank@2314 32 #include "runtime/deoptimization.hpp"
stefank@2314 33 #include "utilities/copy.hpp"
duke@435 34
duke@435 35 // ciMethodData
duke@435 36
duke@435 37 // ------------------------------------------------------------------
duke@435 38 // ciMethodData::ciMethodData
duke@435 39 //
coleenp@4037 40 ciMethodData::ciMethodData(MethodData* md) : ciMetadata(md) {
coleenp@4037 41 assert(md != NULL, "no null method data");
duke@435 42 Copy::zero_to_words((HeapWord*) &_orig, sizeof(_orig) / sizeof(HeapWord));
duke@435 43 _data = NULL;
duke@435 44 _data_size = 0;
duke@435 45 _extra_data_size = 0;
duke@435 46 _current_mileage = 0;
iveresov@2138 47 _invocation_counter = 0;
iveresov@2138 48 _backedge_counter = 0;
duke@435 49 _state = empty_state;
duke@435 50 _saw_free_extra_data = false;
duke@435 51 // Set an initial hint. Don't use set_hint_di() because
duke@435 52 // first_di() may be out of bounds if data_size is 0.
duke@435 53 _hint_di = first_di();
kvn@480 54 // Initialize the escape information (to "don't know.");
kvn@480 55 _eflags = _arg_local = _arg_stack = _arg_returned = 0;
duke@435 56 }
duke@435 57
duke@435 58 // ------------------------------------------------------------------
duke@435 59 // ciMethodData::ciMethodData
duke@435 60 //
coleenp@4037 61 // No MethodData*.
coleenp@4037 62 ciMethodData::ciMethodData() : ciMetadata(NULL) {
duke@435 63 Copy::zero_to_words((HeapWord*) &_orig, sizeof(_orig) / sizeof(HeapWord));
duke@435 64 _data = NULL;
duke@435 65 _data_size = 0;
duke@435 66 _extra_data_size = 0;
duke@435 67 _current_mileage = 0;
iveresov@2138 68 _invocation_counter = 0;
iveresov@2138 69 _backedge_counter = 0;
duke@435 70 _state = empty_state;
duke@435 71 _saw_free_extra_data = false;
duke@435 72 // Set an initial hint. Don't use set_hint_di() because
duke@435 73 // first_di() may be out of bounds if data_size is 0.
duke@435 74 _hint_di = first_di();
kvn@480 75 // Initialize the escape information (to "don't know.");
kvn@480 76 _eflags = _arg_local = _arg_stack = _arg_returned = 0;
duke@435 77 }
duke@435 78
duke@435 79 void ciMethodData::load_data() {
coleenp@4037 80 MethodData* mdo = get_MethodData();
twisti@5907 81 if (mdo == NULL) {
twisti@5907 82 return;
twisti@5907 83 }
duke@435 84
duke@435 85 // To do: don't copy the data if it is not "ripe" -- require a minimum #
duke@435 86 // of invocations.
duke@435 87
duke@435 88 // Snapshot the data -- actually, take an approximate snapshot of
duke@435 89 // the data. Any concurrently executing threads may be changing the
duke@435 90 // data as we copy it.
coleenp@4037 91 Copy::disjoint_words((HeapWord*) mdo,
coleenp@4037 92 (HeapWord*) &_orig,
coleenp@4037 93 sizeof(_orig) / HeapWordSize);
duke@435 94 Arena* arena = CURRENT_ENV->arena();
duke@435 95 _data_size = mdo->data_size();
duke@435 96 _extra_data_size = mdo->extra_data_size();
duke@435 97 int total_size = _data_size + _extra_data_size;
duke@435 98 _data = (intptr_t *) arena->Amalloc(total_size);
duke@435 99 Copy::disjoint_words((HeapWord*) mdo->data_base(), (HeapWord*) _data, total_size / HeapWordSize);
duke@435 100
duke@435 101 // Traverse the profile data, translating any oops into their
duke@435 102 // ci equivalents.
duke@435 103 ResourceMark rm;
duke@435 104 ciProfileData* ci_data = first_data();
duke@435 105 ProfileData* data = mdo->first_data();
duke@435 106 while (is_valid(ci_data)) {
duke@435 107 ci_data->translate_from(data);
duke@435 108 ci_data = next_data(ci_data);
duke@435 109 data = mdo->next_data(data);
duke@435 110 }
duke@435 111 // Note: Extra data are all BitData, and do not need translation.
coleenp@4037 112 _current_mileage = MethodData::mileage_of(mdo->method());
iveresov@2138 113 _invocation_counter = mdo->invocation_count();
iveresov@2138 114 _backedge_counter = mdo->backedge_count();
duke@435 115 _state = mdo->is_mature()? mature_state: immature_state;
duke@435 116
duke@435 117 _eflags = mdo->eflags();
duke@435 118 _arg_local = mdo->arg_local();
duke@435 119 _arg_stack = mdo->arg_stack();
duke@435 120 _arg_returned = mdo->arg_returned();
minqi@4267 121 #ifndef PRODUCT
minqi@4267 122 if (ReplayCompiles) {
minqi@4267 123 ciReplay::initialize(this);
minqi@4267 124 }
minqi@4267 125 #endif
duke@435 126 }
duke@435 127
duke@435 128 void ciReceiverTypeData::translate_receiver_data_from(ProfileData* data) {
duke@435 129 for (uint row = 0; row < row_limit(); row++) {
coleenp@4037 130 Klass* k = data->as_ReceiverTypeData()->receiver(row);
duke@435 131 if (k != NULL) {
coleenp@4037 132 ciKlass* klass = CURRENT_ENV->get_klass(k);
duke@435 133 set_receiver(row, klass);
duke@435 134 }
duke@435 135 }
duke@435 136 }
duke@435 137
duke@435 138
duke@435 139 // Get the data at an arbitrary (sort of) data index.
duke@435 140 ciProfileData* ciMethodData::data_at(int data_index) {
duke@435 141 if (out_of_bounds(data_index)) {
duke@435 142 return NULL;
duke@435 143 }
duke@435 144 DataLayout* data_layout = data_layout_at(data_index);
duke@435 145
duke@435 146 switch (data_layout->tag()) {
duke@435 147 case DataLayout::no_tag:
duke@435 148 default:
duke@435 149 ShouldNotReachHere();
duke@435 150 return NULL;
duke@435 151 case DataLayout::bit_data_tag:
duke@435 152 return new ciBitData(data_layout);
duke@435 153 case DataLayout::counter_data_tag:
duke@435 154 return new ciCounterData(data_layout);
duke@435 155 case DataLayout::jump_data_tag:
duke@435 156 return new ciJumpData(data_layout);
duke@435 157 case DataLayout::receiver_type_data_tag:
duke@435 158 return new ciReceiverTypeData(data_layout);
duke@435 159 case DataLayout::virtual_call_data_tag:
duke@435 160 return new ciVirtualCallData(data_layout);
duke@435 161 case DataLayout::ret_data_tag:
duke@435 162 return new ciRetData(data_layout);
duke@435 163 case DataLayout::branch_data_tag:
duke@435 164 return new ciBranchData(data_layout);
duke@435 165 case DataLayout::multi_branch_data_tag:
duke@435 166 return new ciMultiBranchData(data_layout);
kvn@480 167 case DataLayout::arg_info_data_tag:
kvn@480 168 return new ciArgInfoData(data_layout);
duke@435 169 };
duke@435 170 }
duke@435 171
duke@435 172 // Iteration over data.
duke@435 173 ciProfileData* ciMethodData::next_data(ciProfileData* current) {
duke@435 174 int current_index = dp_to_di(current->dp());
duke@435 175 int next_index = current_index + current->size_in_bytes();
duke@435 176 ciProfileData* next = data_at(next_index);
duke@435 177 return next;
duke@435 178 }
duke@435 179
duke@435 180 // Translate a bci to its corresponding data, or NULL.
duke@435 181 ciProfileData* ciMethodData::bci_to_data(int bci) {
duke@435 182 ciProfileData* data = data_before(bci);
duke@435 183 for ( ; is_valid(data); data = next_data(data)) {
duke@435 184 if (data->bci() == bci) {
duke@435 185 set_hint_di(dp_to_di(data->dp()));
duke@435 186 return data;
duke@435 187 } else if (data->bci() > bci) {
duke@435 188 break;
duke@435 189 }
duke@435 190 }
duke@435 191 // bci_to_extra_data(bci) ...
duke@435 192 DataLayout* dp = data_layout_at(data_size());
duke@435 193 DataLayout* end = data_layout_at(data_size() + extra_data_size());
coleenp@4037 194 for (; dp < end; dp = MethodData::next_extra(dp)) {
duke@435 195 if (dp->tag() == DataLayout::no_tag) {
duke@435 196 _saw_free_extra_data = true; // observed an empty slot (common case)
duke@435 197 return NULL;
duke@435 198 }
kvn@480 199 if (dp->tag() == DataLayout::arg_info_data_tag) {
kvn@480 200 break; // ArgInfoData is at the end of extra data section.
kvn@480 201 }
duke@435 202 if (dp->bci() == bci) {
duke@435 203 assert(dp->tag() == DataLayout::bit_data_tag, "sane");
duke@435 204 return new ciBitData(dp);
duke@435 205 }
duke@435 206 }
duke@435 207 return NULL;
duke@435 208 }
duke@435 209
duke@435 210 // Conservatively decode the trap_state of a ciProfileData.
duke@435 211 int ciMethodData::has_trap_at(ciProfileData* data, int reason) {
duke@435 212 typedef Deoptimization::DeoptReason DR_t;
duke@435 213 int per_bc_reason
duke@435 214 = Deoptimization::reason_recorded_per_bytecode_if_any((DR_t) reason);
duke@435 215 if (trap_count(reason) == 0) {
duke@435 216 // Impossible for this trap to have occurred, regardless of trap_state.
duke@435 217 // Note: This happens if the MDO is empty.
duke@435 218 return 0;
duke@435 219 } else if (per_bc_reason == Deoptimization::Reason_none) {
duke@435 220 // We cannot conclude anything; a trap happened somewhere, maybe here.
duke@435 221 return -1;
duke@435 222 } else if (data == NULL) {
duke@435 223 // No profile here, not even an extra_data record allocated on the fly.
duke@435 224 // If there are empty extra_data records, and there had been a trap,
duke@435 225 // there would have been a non-null data pointer. If there are no
duke@435 226 // free extra_data records, we must return a conservative -1.
duke@435 227 if (_saw_free_extra_data)
duke@435 228 return 0; // Q.E.D.
duke@435 229 else
duke@435 230 return -1; // bail with a conservative answer
duke@435 231 } else {
duke@435 232 return Deoptimization::trap_state_has_reason(data->trap_state(), per_bc_reason);
duke@435 233 }
duke@435 234 }
duke@435 235
duke@435 236 int ciMethodData::trap_recompiled_at(ciProfileData* data) {
duke@435 237 if (data == NULL) {
duke@435 238 return (_saw_free_extra_data? 0: -1); // (see previous method)
duke@435 239 } else {
duke@435 240 return Deoptimization::trap_state_is_recompiled(data->trap_state())? 1: 0;
duke@435 241 }
duke@435 242 }
duke@435 243
duke@435 244 void ciMethodData::clear_escape_info() {
duke@435 245 VM_ENTRY_MARK;
coleenp@4037 246 MethodData* mdo = get_MethodData();
kvn@480 247 if (mdo != NULL) {
duke@435 248 mdo->clear_escape_info();
kvn@480 249 ArgInfoData *aid = arg_info();
kvn@480 250 int arg_count = (aid == NULL) ? 0 : aid->number_of_args();
kvn@480 251 for (int i = 0; i < arg_count; i++) {
kvn@480 252 set_arg_modified(i, 0);
kvn@480 253 }
kvn@480 254 }
duke@435 255 _eflags = _arg_local = _arg_stack = _arg_returned = 0;
duke@435 256 }
duke@435 257
coleenp@4037 258 // copy our escape info to the MethodData* if it exists
duke@435 259 void ciMethodData::update_escape_info() {
duke@435 260 VM_ENTRY_MARK;
coleenp@4037 261 MethodData* mdo = get_MethodData();
duke@435 262 if ( mdo != NULL) {
duke@435 263 mdo->set_eflags(_eflags);
duke@435 264 mdo->set_arg_local(_arg_local);
duke@435 265 mdo->set_arg_stack(_arg_stack);
duke@435 266 mdo->set_arg_returned(_arg_returned);
kvn@480 267 int arg_count = mdo->method()->size_of_parameters();
kvn@480 268 for (int i = 0; i < arg_count; i++) {
kvn@480 269 mdo->set_arg_modified(i, arg_modified(i));
kvn@480 270 }
duke@435 271 }
duke@435 272 }
duke@435 273
iveresov@2138 274 void ciMethodData::set_compilation_stats(short loops, short blocks) {
iveresov@2138 275 VM_ENTRY_MARK;
coleenp@4037 276 MethodData* mdo = get_MethodData();
iveresov@2138 277 if (mdo != NULL) {
iveresov@2138 278 mdo->set_num_loops(loops);
iveresov@2138 279 mdo->set_num_blocks(blocks);
iveresov@2138 280 }
iveresov@2138 281 }
iveresov@2138 282
iveresov@2138 283 void ciMethodData::set_would_profile(bool p) {
iveresov@2138 284 VM_ENTRY_MARK;
coleenp@4037 285 MethodData* mdo = get_MethodData();
iveresov@2138 286 if (mdo != NULL) {
iveresov@2138 287 mdo->set_would_profile(p);
iveresov@2138 288 }
iveresov@2138 289 }
iveresov@2138 290
duke@435 291 bool ciMethodData::has_escape_info() {
coleenp@4037 292 return eflag_set(MethodData::estimated);
duke@435 293 }
duke@435 294
coleenp@4037 295 void ciMethodData::set_eflag(MethodData::EscapeFlag f) {
duke@435 296 set_bits(_eflags, f);
duke@435 297 }
duke@435 298
coleenp@4037 299 void ciMethodData::clear_eflag(MethodData::EscapeFlag f) {
duke@435 300 clear_bits(_eflags, f);
duke@435 301 }
duke@435 302
coleenp@4037 303 bool ciMethodData::eflag_set(MethodData::EscapeFlag f) const {
duke@435 304 return mask_bits(_eflags, f) != 0;
duke@435 305 }
duke@435 306
duke@435 307 void ciMethodData::set_arg_local(int i) {
duke@435 308 set_nth_bit(_arg_local, i);
duke@435 309 }
duke@435 310
duke@435 311 void ciMethodData::set_arg_stack(int i) {
duke@435 312 set_nth_bit(_arg_stack, i);
duke@435 313 }
duke@435 314
duke@435 315 void ciMethodData::set_arg_returned(int i) {
duke@435 316 set_nth_bit(_arg_returned, i);
duke@435 317 }
duke@435 318
kvn@480 319 void ciMethodData::set_arg_modified(int arg, uint val) {
kvn@480 320 ArgInfoData *aid = arg_info();
kvn@480 321 if (aid == NULL)
kvn@480 322 return;
kvn@480 323 assert(arg >= 0 && arg < aid->number_of_args(), "valid argument number");
kvn@480 324 aid->set_arg_modified(arg, val);
kvn@480 325 }
kvn@480 326
duke@435 327 bool ciMethodData::is_arg_local(int i) const {
duke@435 328 return is_set_nth_bit(_arg_local, i);
duke@435 329 }
duke@435 330
duke@435 331 bool ciMethodData::is_arg_stack(int i) const {
duke@435 332 return is_set_nth_bit(_arg_stack, i);
duke@435 333 }
duke@435 334
duke@435 335 bool ciMethodData::is_arg_returned(int i) const {
duke@435 336 return is_set_nth_bit(_arg_returned, i);
duke@435 337 }
duke@435 338
kvn@480 339 uint ciMethodData::arg_modified(int arg) const {
kvn@480 340 ArgInfoData *aid = arg_info();
kvn@480 341 if (aid == NULL)
kvn@480 342 return 0;
kvn@480 343 assert(arg >= 0 && arg < aid->number_of_args(), "valid argument number");
kvn@480 344 return aid->arg_modified(arg);
kvn@480 345 }
kvn@480 346
duke@435 347 ByteSize ciMethodData::offset_of_slot(ciProfileData* data, ByteSize slot_offset_in_data) {
coleenp@4037 348 // Get offset within MethodData* of the data array
coleenp@4037 349 ByteSize data_offset = MethodData::data_offset();
duke@435 350
duke@435 351 // Get cell offset of the ProfileData within data array
duke@435 352 int cell_offset = dp_to_di(data->dp());
duke@435 353
duke@435 354 // Add in counter_offset, the # of bytes into the ProfileData of counter or flag
duke@435 355 int offset = in_bytes(data_offset) + cell_offset + in_bytes(slot_offset_in_data);
duke@435 356
duke@435 357 return in_ByteSize(offset);
duke@435 358 }
duke@435 359
kvn@480 360 ciArgInfoData *ciMethodData::arg_info() const {
kvn@480 361 // Should be last, have to skip all traps.
kvn@480 362 DataLayout* dp = data_layout_at(data_size());
kvn@480 363 DataLayout* end = data_layout_at(data_size() + extra_data_size());
coleenp@4037 364 for (; dp < end; dp = MethodData::next_extra(dp)) {
kvn@480 365 if (dp->tag() == DataLayout::arg_info_data_tag)
kvn@480 366 return new ciArgInfoData(dp);
kvn@480 367 }
kvn@480 368 return NULL;
kvn@480 369 }
kvn@480 370
kvn@480 371
duke@435 372 // Implementation of the print method.
duke@435 373 void ciMethodData::print_impl(outputStream* st) {
coleenp@4037 374 ciMetadata::print_impl(st);
duke@435 375 }
duke@435 376
minqi@4267 377 void ciMethodData::dump_replay_data(outputStream* out) {
vlivanov@4531 378 ResourceMark rm;
minqi@4267 379 MethodData* mdo = get_MethodData();
minqi@4267 380 Method* method = mdo->method();
minqi@4267 381 Klass* holder = method->method_holder();
minqi@4267 382 out->print("ciMethodData %s %s %s %d %d",
minqi@4267 383 holder->name()->as_quoted_ascii(),
minqi@4267 384 method->name()->as_quoted_ascii(),
minqi@4267 385 method->signature()->as_quoted_ascii(),
minqi@4267 386 _state,
minqi@4267 387 current_mileage());
minqi@4267 388
minqi@4267 389 // dump the contents of the MDO header as raw data
minqi@4267 390 unsigned char* orig = (unsigned char*)&_orig;
minqi@4267 391 int length = sizeof(_orig);
minqi@4267 392 out->print(" orig %d", length);
minqi@4267 393 for (int i = 0; i < length; i++) {
minqi@4267 394 out->print(" %d", orig[i]);
minqi@4267 395 }
minqi@4267 396
minqi@4267 397 // dump the MDO data as raw data
minqi@4267 398 int elements = data_size() / sizeof(intptr_t);
minqi@4267 399 out->print(" data %d", elements);
minqi@4267 400 for (int i = 0; i < elements; i++) {
minqi@4267 401 // We could use INTPTR_FORMAT here but that's a zero justified
minqi@4267 402 // which makes comparing it with the SA version of this output
minqi@4267 403 // harder.
minqi@4267 404 #ifdef _LP64
minqi@4267 405 out->print(" 0x%" FORMAT64_MODIFIER "x", data()[i]);
minqi@4267 406 #else
minqi@4267 407 out->print(" 0x%x", data()[i]);
minqi@4267 408 #endif
minqi@4267 409 }
minqi@4267 410
minqi@4267 411 // The MDO contained oop references as ciObjects, so scan for those
minqi@4267 412 // and emit pairs of offset and klass name so that they can be
minqi@4267 413 // reconstructed at runtime. The first round counts the number of
minqi@4267 414 // oop references and the second actually emits them.
minqi@4267 415 int count = 0;
minqi@4267 416 for (int round = 0; round < 2; round++) {
minqi@4267 417 if (round == 1) out->print(" oops %d", count);
minqi@4267 418 ProfileData* pdata = first_data();
minqi@4267 419 for ( ; is_valid(pdata); pdata = next_data(pdata)) {
minqi@4267 420 if (pdata->is_ReceiverTypeData()) {
minqi@4267 421 ciReceiverTypeData* vdata = (ciReceiverTypeData*)pdata;
minqi@4267 422 for (uint i = 0; i < vdata->row_limit(); i++) {
minqi@4267 423 ciKlass* k = vdata->receiver(i);
minqi@4267 424 if (k != NULL) {
minqi@4267 425 if (round == 0) {
minqi@4267 426 count++;
minqi@4267 427 } else {
minqi@4267 428 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 429 }
minqi@4267 430 }
minqi@4267 431 }
minqi@4267 432 } else if (pdata->is_VirtualCallData()) {
minqi@4267 433 ciVirtualCallData* vdata = (ciVirtualCallData*)pdata;
minqi@4267 434 for (uint i = 0; i < vdata->row_limit(); i++) {
minqi@4267 435 ciKlass* k = vdata->receiver(i);
minqi@4267 436 if (k != NULL) {
minqi@4267 437 if (round == 0) {
minqi@4267 438 count++;
minqi@4267 439 } else {
minqi@4267 440 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 441 }
minqi@4267 442 }
minqi@4267 443 }
minqi@4267 444 }
minqi@4267 445 }
minqi@4267 446 }
minqi@4267 447 out->cr();
minqi@4267 448 }
minqi@4267 449
duke@435 450 #ifndef PRODUCT
duke@435 451 void ciMethodData::print() {
duke@435 452 print_data_on(tty);
duke@435 453 }
duke@435 454
duke@435 455 void ciMethodData::print_data_on(outputStream* st) {
duke@435 456 ResourceMark rm;
duke@435 457 ciProfileData* data;
duke@435 458 for (data = first_data(); is_valid(data); data = next_data(data)) {
duke@435 459 st->print("%d", dp_to_di(data->dp()));
duke@435 460 st->fill_to(6);
duke@435 461 data->print_data_on(st);
duke@435 462 }
kvn@480 463 st->print_cr("--- Extra data:");
kvn@480 464 DataLayout* dp = data_layout_at(data_size());
kvn@480 465 DataLayout* end = data_layout_at(data_size() + extra_data_size());
coleenp@4037 466 for (; dp < end; dp = MethodData::next_extra(dp)) {
kvn@480 467 if (dp->tag() == DataLayout::no_tag) continue;
kvn@480 468 if (dp->tag() == DataLayout::bit_data_tag) {
kvn@480 469 data = new BitData(dp);
kvn@480 470 } else {
kvn@480 471 assert(dp->tag() == DataLayout::arg_info_data_tag, "must be BitData or ArgInfo");
kvn@480 472 data = new ciArgInfoData(dp);
kvn@480 473 dp = end; // ArgInfoData is at the end of extra data section.
kvn@480 474 }
kvn@480 475 st->print("%d", dp_to_di(data->dp()));
kvn@480 476 st->fill_to(6);
kvn@480 477 data->print_data_on(st);
kvn@480 478 }
duke@435 479 }
duke@435 480
duke@435 481 void ciReceiverTypeData::print_receiver_data_on(outputStream* st) {
duke@435 482 uint row;
duke@435 483 int entries = 0;
duke@435 484 for (row = 0; row < row_limit(); row++) {
duke@435 485 if (receiver(row) != NULL) entries++;
duke@435 486 }
duke@435 487 st->print_cr("count(%u) entries(%u)", count(), entries);
duke@435 488 for (row = 0; row < row_limit(); row++) {
duke@435 489 if (receiver(row) != NULL) {
duke@435 490 tab(st);
duke@435 491 receiver(row)->print_name_on(st);
duke@435 492 st->print_cr("(%u)", receiver_count(row));
duke@435 493 }
duke@435 494 }
duke@435 495 }
duke@435 496
duke@435 497 void ciReceiverTypeData::print_data_on(outputStream* st) {
duke@435 498 print_shared(st, "ciReceiverTypeData");
duke@435 499 print_receiver_data_on(st);
duke@435 500 }
duke@435 501
duke@435 502 void ciVirtualCallData::print_data_on(outputStream* st) {
duke@435 503 print_shared(st, "ciVirtualCallData");
duke@435 504 rtd_super()->print_receiver_data_on(st);
duke@435 505 }
duke@435 506 #endif

mercurial