src/share/vm/code/relocInfo.cpp

Mon, 19 Aug 2019 10:11:31 +0200

author
neugens
date
Mon, 19 Aug 2019 10:11:31 +0200
changeset 9861
a248d0be1309
parent 8773
1eaa9a72d705
child 8856
ac27a9c85bea
permissions
-rw-r--r--

8229401: Fix JFR code cache test failures
8223689: Add JFR Thread Sampling Support
8223690: Add JFR BiasedLock Event Support
8223691: Add JFR G1 Region Type Change Event Support
8223692: Add JFR G1 Heap Summary Event Support
Summary: Backport JFR from JDK11, additional fixes
Reviewed-by: neugens, apetushkov
Contributed-by: denghui.ddh@alibaba-inc.com

duke@435 1 /*
drchase@6680 2 * Copyright (c) 1997, 2014, 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"
twisti@4318 26 #include "code/codeCache.hpp"
stefank@2314 27 #include "code/compiledIC.hpp"
stefank@2314 28 #include "code/nmethod.hpp"
stefank@2314 29 #include "code/relocInfo.hpp"
stefank@2314 30 #include "memory/resourceArea.hpp"
stefank@2314 31 #include "runtime/stubCodeGenerator.hpp"
stefank@2314 32 #include "utilities/copy.hpp"
duke@435 33
drchase@6680 34 PRAGMA_FORMAT_MUTE_WARNINGS_FOR_GCC
duke@435 35
duke@435 36 const RelocationHolder RelocationHolder::none; // its type is relocInfo::none
duke@435 37
duke@435 38
duke@435 39 // Implementation of relocInfo
duke@435 40
duke@435 41 #ifdef ASSERT
duke@435 42 relocInfo::relocInfo(relocType t, int off, int f) {
duke@435 43 assert(t != data_prefix_tag, "cannot build a prefix this way");
duke@435 44 assert((t & type_mask) == t, "wrong type");
duke@435 45 assert((f & format_mask) == f, "wrong format");
duke@435 46 assert(off >= 0 && off < offset_limit(), "offset out off bounds");
duke@435 47 assert((off & (offset_unit-1)) == 0, "misaligned offset");
duke@435 48 (*this) = relocInfo(t, RAW_BITS, off, f);
duke@435 49 }
duke@435 50 #endif
duke@435 51
duke@435 52 void relocInfo::initialize(CodeSection* dest, Relocation* reloc) {
duke@435 53 relocInfo* data = this+1; // here's where the data might go
duke@435 54 dest->set_locs_end(data); // sync end: the next call may read dest.locs_end
duke@435 55 reloc->pack_data_to(dest); // maybe write data into locs, advancing locs_end
duke@435 56 relocInfo* data_limit = dest->locs_end();
duke@435 57 if (data_limit > data) {
duke@435 58 relocInfo suffix = (*this);
duke@435 59 data_limit = this->finish_prefix((short*) data_limit);
duke@435 60 // Finish up with the suffix. (Hack note: pack_data_to might edit this.)
duke@435 61 *data_limit = suffix;
duke@435 62 dest->set_locs_end(data_limit+1);
duke@435 63 }
duke@435 64 }
duke@435 65
duke@435 66 relocInfo* relocInfo::finish_prefix(short* prefix_limit) {
duke@435 67 assert(sizeof(relocInfo) == sizeof(short), "change this code");
duke@435 68 short* p = (short*)(this+1);
duke@435 69 assert(prefix_limit >= p, "must be a valid span of data");
duke@435 70 int plen = prefix_limit - p;
duke@435 71 if (plen == 0) {
duke@435 72 debug_only(_value = 0xFFFF);
duke@435 73 return this; // no data: remove self completely
duke@435 74 }
duke@435 75 if (plen == 1 && fits_into_immediate(p[0])) {
duke@435 76 (*this) = immediate_relocInfo(p[0]); // move data inside self
duke@435 77 return this+1;
duke@435 78 }
duke@435 79 // cannot compact, so just update the count and return the limit pointer
duke@435 80 (*this) = prefix_relocInfo(plen); // write new datalen
duke@435 81 assert(data() + datalen() == prefix_limit, "pointers must line up");
duke@435 82 return (relocInfo*)prefix_limit;
duke@435 83 }
duke@435 84
duke@435 85
duke@435 86 void relocInfo::set_type(relocType t) {
duke@435 87 int old_offset = addr_offset();
duke@435 88 int old_format = format();
duke@435 89 (*this) = relocInfo(t, old_offset, old_format);
duke@435 90 assert(type()==(int)t, "sanity check");
duke@435 91 assert(addr_offset()==old_offset, "sanity check");
duke@435 92 assert(format()==old_format, "sanity check");
duke@435 93 }
duke@435 94
duke@435 95
duke@435 96 void relocInfo::set_format(int f) {
duke@435 97 int old_offset = addr_offset();
duke@435 98 assert((f & format_mask) == f, "wrong format");
duke@435 99 _value = (_value & ~(format_mask << offset_width)) | (f << offset_width);
duke@435 100 assert(addr_offset()==old_offset, "sanity check");
duke@435 101 }
duke@435 102
duke@435 103
duke@435 104 void relocInfo::change_reloc_info_for_address(RelocIterator *itr, address pc, relocType old_type, relocType new_type) {
duke@435 105 bool found = false;
duke@435 106 while (itr->next() && !found) {
duke@435 107 if (itr->addr() == pc) {
duke@435 108 assert(itr->type()==old_type, "wrong relocInfo type found");
duke@435 109 itr->current()->set_type(new_type);
duke@435 110 found=true;
duke@435 111 }
duke@435 112 }
duke@435 113 assert(found, "no relocInfo found for pc");
duke@435 114 }
duke@435 115
duke@435 116
duke@435 117 void relocInfo::remove_reloc_info_for_address(RelocIterator *itr, address pc, relocType old_type) {
duke@435 118 change_reloc_info_for_address(itr, pc, old_type, none);
duke@435 119 }
duke@435 120
duke@435 121
duke@435 122 // ----------------------------------------------------------------------------------------------------
duke@435 123 // Implementation of RelocIterator
duke@435 124
twisti@1918 125 void RelocIterator::initialize(nmethod* nm, address begin, address limit) {
duke@435 126 initialize_misc();
duke@435 127
twisti@1918 128 if (nm == NULL && begin != NULL) {
twisti@1918 129 // allow nmethod to be deduced from beginning address
twisti@1918 130 CodeBlob* cb = CodeCache::find_blob(begin);
thartmann@8773 131 nm = (cb != NULL) ? cb->as_nmethod_or_null() : NULL;
duke@435 132 }
thartmann@8773 133 guarantee(nm != NULL, "must be able to deduce nmethod from other arguments");
duke@435 134
twisti@1918 135 _code = nm;
twisti@1918 136 _current = nm->relocation_begin() - 1;
twisti@1918 137 _end = nm->relocation_end();
twisti@2117 138 _addr = nm->content_begin();
twisti@2117 139
twisti@2117 140 // Initialize code sections.
twisti@2117 141 _section_start[CodeBuffer::SECT_CONSTS] = nm->consts_begin();
twisti@2117 142 _section_start[CodeBuffer::SECT_INSTS ] = nm->insts_begin() ;
twisti@2117 143 _section_start[CodeBuffer::SECT_STUBS ] = nm->stub_begin() ;
twisti@2117 144
twisti@2117 145 _section_end [CodeBuffer::SECT_CONSTS] = nm->consts_end() ;
twisti@2117 146 _section_end [CodeBuffer::SECT_INSTS ] = nm->insts_end() ;
twisti@2117 147 _section_end [CodeBuffer::SECT_STUBS ] = nm->stub_end() ;
duke@435 148
duke@435 149 assert(!has_current(), "just checking");
twisti@2103 150 assert(begin == NULL || begin >= nm->code_begin(), "in bounds");
twisti@2103 151 assert(limit == NULL || limit <= nm->code_end(), "in bounds");
duke@435 152 set_limits(begin, limit);
duke@435 153 }
duke@435 154
duke@435 155
duke@435 156 RelocIterator::RelocIterator(CodeSection* cs, address begin, address limit) {
duke@435 157 initialize_misc();
duke@435 158
duke@435 159 _current = cs->locs_start()-1;
duke@435 160 _end = cs->locs_end();
duke@435 161 _addr = cs->start();
duke@435 162 _code = NULL; // Not cb->blob();
duke@435 163
duke@435 164 CodeBuffer* cb = cs->outer();
twisti@2117 165 assert((int) SECT_LIMIT == CodeBuffer::SECT_LIMIT, "my copy must be equal");
twisti@2117 166 for (int n = (int) CodeBuffer::SECT_FIRST; n < (int) CodeBuffer::SECT_LIMIT; n++) {
twisti@2117 167 CodeSection* cs = cb->code_section(n);
twisti@2117 168 _section_start[n] = cs->start();
twisti@2117 169 _section_end [n] = cs->end();
duke@435 170 }
duke@435 171
duke@435 172 assert(!has_current(), "just checking");
duke@435 173
duke@435 174 assert(begin == NULL || begin >= cs->start(), "in bounds");
duke@435 175 assert(limit == NULL || limit <= cs->end(), "in bounds");
duke@435 176 set_limits(begin, limit);
duke@435 177 }
duke@435 178
duke@435 179
duke@435 180 enum { indexCardSize = 128 };
duke@435 181 struct RelocIndexEntry {
duke@435 182 jint addr_offset; // offset from header_end of an addr()
duke@435 183 jint reloc_offset; // offset from header_end of a relocInfo (prefix)
duke@435 184 };
duke@435 185
duke@435 186
twisti@2117 187 bool RelocIterator::addr_in_const() const {
twisti@2117 188 const int n = CodeBuffer::SECT_CONSTS;
twisti@2117 189 return section_start(n) <= addr() && addr() < section_end(n);
twisti@2117 190 }
twisti@2117 191
twisti@2117 192
duke@435 193 static inline int num_cards(int code_size) {
duke@435 194 return (code_size-1) / indexCardSize;
duke@435 195 }
duke@435 196
duke@435 197
duke@435 198 int RelocIterator::locs_and_index_size(int code_size, int locs_size) {
duke@435 199 if (!UseRelocIndex) return locs_size; // no index
duke@435 200 code_size = round_to(code_size, oopSize);
duke@435 201 locs_size = round_to(locs_size, oopSize);
duke@435 202 int index_size = num_cards(code_size) * sizeof(RelocIndexEntry);
duke@435 203 // format of indexed relocs:
duke@435 204 // relocation_begin: relocInfo ...
duke@435 205 // index: (addr,reloc#) ...
duke@435 206 // indexSize :relocation_end
duke@435 207 return locs_size + index_size + BytesPerInt;
duke@435 208 }
duke@435 209
duke@435 210
duke@435 211 void RelocIterator::create_index(relocInfo* dest_begin, int dest_count, relocInfo* dest_end) {
duke@435 212 address relocation_begin = (address)dest_begin;
duke@435 213 address relocation_end = (address)dest_end;
duke@435 214 int total_size = relocation_end - relocation_begin;
duke@435 215 int locs_size = dest_count * sizeof(relocInfo);
duke@435 216 if (!UseRelocIndex) {
duke@435 217 Copy::fill_to_bytes(relocation_begin + locs_size, total_size-locs_size, 0);
duke@435 218 return;
duke@435 219 }
duke@435 220 int index_size = total_size - locs_size - BytesPerInt; // find out how much space is left
duke@435 221 int ncards = index_size / sizeof(RelocIndexEntry);
duke@435 222 assert(total_size == locs_size + index_size + BytesPerInt, "checkin'");
duke@435 223 assert(index_size >= 0 && index_size % sizeof(RelocIndexEntry) == 0, "checkin'");
duke@435 224 jint* index_size_addr = (jint*)relocation_end - 1;
duke@435 225
duke@435 226 assert(sizeof(jint) == BytesPerInt, "change this code");
duke@435 227
duke@435 228 *index_size_addr = index_size;
duke@435 229 if (index_size != 0) {
duke@435 230 assert(index_size > 0, "checkin'");
duke@435 231
duke@435 232 RelocIndexEntry* index = (RelocIndexEntry *)(relocation_begin + locs_size);
duke@435 233 assert(index == (RelocIndexEntry*)index_size_addr - ncards, "checkin'");
duke@435 234
duke@435 235 // walk over the relocations, and fill in index entries as we go
duke@435 236 RelocIterator iter;
duke@435 237 const address initial_addr = NULL;
duke@435 238 relocInfo* const initial_current = dest_begin - 1; // biased by -1 like elsewhere
duke@435 239
duke@435 240 iter._code = NULL;
duke@435 241 iter._addr = initial_addr;
duke@435 242 iter._limit = (address)(intptr_t)(ncards * indexCardSize);
duke@435 243 iter._current = initial_current;
duke@435 244 iter._end = dest_begin + dest_count;
duke@435 245
duke@435 246 int i = 0;
duke@435 247 address next_card_addr = (address)indexCardSize;
duke@435 248 int addr_offset = 0;
duke@435 249 int reloc_offset = 0;
duke@435 250 while (true) {
duke@435 251 // Checkpoint the iterator before advancing it.
duke@435 252 addr_offset = iter._addr - initial_addr;
duke@435 253 reloc_offset = iter._current - initial_current;
duke@435 254 if (!iter.next()) break;
duke@435 255 while (iter.addr() >= next_card_addr) {
duke@435 256 index[i].addr_offset = addr_offset;
duke@435 257 index[i].reloc_offset = reloc_offset;
duke@435 258 i++;
duke@435 259 next_card_addr += indexCardSize;
duke@435 260 }
duke@435 261 }
duke@435 262 while (i < ncards) {
duke@435 263 index[i].addr_offset = addr_offset;
duke@435 264 index[i].reloc_offset = reloc_offset;
duke@435 265 i++;
duke@435 266 }
duke@435 267 }
duke@435 268 }
duke@435 269
duke@435 270
duke@435 271 void RelocIterator::set_limits(address begin, address limit) {
duke@435 272 int index_size = 0;
duke@435 273 if (UseRelocIndex && _code != NULL) {
duke@435 274 index_size = ((jint*)_end)[-1];
duke@435 275 _end = (relocInfo*)( (address)_end - index_size - BytesPerInt );
duke@435 276 }
duke@435 277
duke@435 278 _limit = limit;
duke@435 279
duke@435 280 // the limit affects this next stuff:
duke@435 281 if (begin != NULL) {
duke@435 282 #ifdef ASSERT
duke@435 283 // In ASSERT mode we do not actually use the index, but simply
duke@435 284 // check that its contents would have led us to the right answer.
duke@435 285 address addrCheck = _addr;
duke@435 286 relocInfo* infoCheck = _current;
duke@435 287 #endif // ASSERT
duke@435 288 if (index_size > 0) {
duke@435 289 // skip ahead
duke@435 290 RelocIndexEntry* index = (RelocIndexEntry*)_end;
duke@435 291 RelocIndexEntry* index_limit = (RelocIndexEntry*)((address)index + index_size);
twisti@2103 292 assert(_addr == _code->code_begin(), "_addr must be unadjusted");
duke@435 293 int card = (begin - _addr) / indexCardSize;
duke@435 294 if (card > 0) {
duke@435 295 if (index+card-1 < index_limit) index += card-1;
duke@435 296 else index = index_limit - 1;
duke@435 297 #ifdef ASSERT
duke@435 298 addrCheck = _addr + index->addr_offset;
duke@435 299 infoCheck = _current + index->reloc_offset;
duke@435 300 #else
duke@435 301 // Advance the iterator immediately to the last valid state
duke@435 302 // for the previous card. Calling "next" will then advance
duke@435 303 // it to the first item on the required card.
duke@435 304 _addr += index->addr_offset;
duke@435 305 _current += index->reloc_offset;
duke@435 306 #endif // ASSERT
duke@435 307 }
duke@435 308 }
duke@435 309
duke@435 310 relocInfo* backup;
duke@435 311 address backup_addr;
duke@435 312 while (true) {
duke@435 313 backup = _current;
duke@435 314 backup_addr = _addr;
duke@435 315 #ifdef ASSERT
duke@435 316 if (backup == infoCheck) {
duke@435 317 assert(backup_addr == addrCheck, "must match"); addrCheck = NULL; infoCheck = NULL;
duke@435 318 } else {
duke@435 319 assert(addrCheck == NULL || backup_addr <= addrCheck, "must not pass addrCheck");
duke@435 320 }
duke@435 321 #endif // ASSERT
duke@435 322 if (!next() || addr() >= begin) break;
duke@435 323 }
duke@435 324 assert(addrCheck == NULL || addrCheck == backup_addr, "must have matched addrCheck");
duke@435 325 assert(infoCheck == NULL || infoCheck == backup, "must have matched infoCheck");
duke@435 326 // At this point, either we are at the first matching record,
duke@435 327 // or else there is no such record, and !has_current().
duke@435 328 // In either case, revert to the immediatly preceding state.
duke@435 329 _current = backup;
duke@435 330 _addr = backup_addr;
duke@435 331 set_has_current(false);
duke@435 332 }
duke@435 333 }
duke@435 334
duke@435 335
duke@435 336 void RelocIterator::set_limit(address limit) {
duke@435 337 address code_end = (address)code() + code()->size();
duke@435 338 assert(limit == NULL || limit <= code_end, "in bounds");
duke@435 339 _limit = limit;
duke@435 340 }
duke@435 341
duke@435 342 // All the strange bit-encodings are in here.
duke@435 343 // The idea is to encode relocation data which are small integers
duke@435 344 // very efficiently (a single extra halfword). Larger chunks of
duke@435 345 // relocation data need a halfword header to hold their size.
duke@435 346 void RelocIterator::advance_over_prefix() {
duke@435 347 if (_current->is_datalen()) {
duke@435 348 _data = (short*) _current->data();
duke@435 349 _datalen = _current->datalen();
duke@435 350 _current += _datalen + 1; // skip the embedded data & header
duke@435 351 } else {
duke@435 352 _databuf = _current->immediate();
duke@435 353 _data = &_databuf;
duke@435 354 _datalen = 1;
duke@435 355 _current++; // skip the header
duke@435 356 }
duke@435 357 // The client will see the following relocInfo, whatever that is.
duke@435 358 // It is the reloc to which the preceding data applies.
duke@435 359 }
duke@435 360
duke@435 361
twisti@2117 362 void RelocIterator::initialize_misc() {
twisti@2117 363 set_has_current(false);
twisti@2117 364 for (int i = (int) CodeBuffer::SECT_FIRST; i < (int) CodeBuffer::SECT_LIMIT; i++) {
twisti@2117 365 _section_start[i] = NULL; // these will be lazily computed, if needed
twisti@2117 366 _section_end [i] = NULL;
duke@435 367 }
duke@435 368 }
duke@435 369
duke@435 370
duke@435 371 Relocation* RelocIterator::reloc() {
duke@435 372 // (take the "switch" out-of-line)
duke@435 373 relocInfo::relocType t = type();
duke@435 374 if (false) {}
duke@435 375 #define EACH_TYPE(name) \
duke@435 376 else if (t == relocInfo::name##_type) { \
duke@435 377 return name##_reloc(); \
duke@435 378 }
duke@435 379 APPLY_TO_RELOCATIONS(EACH_TYPE);
duke@435 380 #undef EACH_TYPE
duke@435 381 assert(t == relocInfo::none, "must be padding");
duke@435 382 return new(_rh) Relocation();
duke@435 383 }
duke@435 384
duke@435 385
duke@435 386 //////// Methods for flyweight Relocation types
duke@435 387
duke@435 388
duke@435 389 RelocationHolder RelocationHolder::plus(int offset) const {
duke@435 390 if (offset != 0) {
duke@435 391 switch (type()) {
duke@435 392 case relocInfo::none:
duke@435 393 break;
duke@435 394 case relocInfo::oop_type:
duke@435 395 {
duke@435 396 oop_Relocation* r = (oop_Relocation*)reloc();
duke@435 397 return oop_Relocation::spec(r->oop_index(), r->offset() + offset);
duke@435 398 }
coleenp@4037 399 case relocInfo::metadata_type:
coleenp@4037 400 {
coleenp@4037 401 metadata_Relocation* r = (metadata_Relocation*)reloc();
coleenp@4037 402 return metadata_Relocation::spec(r->metadata_index(), r->offset() + offset);
coleenp@4037 403 }
duke@435 404 default:
duke@435 405 ShouldNotReachHere();
duke@435 406 }
duke@435 407 }
duke@435 408 return (*this);
duke@435 409 }
duke@435 410
duke@435 411
duke@435 412 void Relocation::guarantee_size() {
duke@435 413 guarantee(false, "Make _relocbuf bigger!");
duke@435 414 }
duke@435 415
duke@435 416 // some relocations can compute their own values
duke@435 417 address Relocation::value() {
duke@435 418 ShouldNotReachHere();
duke@435 419 return NULL;
duke@435 420 }
duke@435 421
duke@435 422
duke@435 423 void Relocation::set_value(address x) {
duke@435 424 ShouldNotReachHere();
duke@435 425 }
duke@435 426
duke@435 427
duke@435 428 RelocationHolder Relocation::spec_simple(relocInfo::relocType rtype) {
duke@435 429 if (rtype == relocInfo::none) return RelocationHolder::none;
duke@435 430 relocInfo ri = relocInfo(rtype, 0);
duke@435 431 RelocIterator itr;
duke@435 432 itr.set_current(ri);
duke@435 433 itr.reloc();
duke@435 434 return itr._rh;
duke@435 435 }
duke@435 436
duke@435 437 int32_t Relocation::runtime_address_to_index(address runtime_address) {
never@2737 438 assert(!is_reloc_index((intptr_t)runtime_address), "must not look like an index");
duke@435 439
duke@435 440 if (runtime_address == NULL) return 0;
duke@435 441
duke@435 442 StubCodeDesc* p = StubCodeDesc::desc_for(runtime_address);
duke@435 443 if (p != NULL && p->begin() == runtime_address) {
never@2737 444 assert(is_reloc_index(p->index()), "there must not be too many stubs");
duke@435 445 return (int32_t)p->index();
duke@435 446 } else {
duke@435 447 // Known "miscellaneous" non-stub pointers:
duke@435 448 // os::get_polling_page(), SafepointSynchronize::address_of_state()
duke@435 449 if (PrintRelocations) {
duke@435 450 tty->print_cr("random unregistered address in relocInfo: " INTPTR_FORMAT, runtime_address);
duke@435 451 }
duke@435 452 #ifndef _LP64
duke@435 453 return (int32_t) (intptr_t)runtime_address;
duke@435 454 #else
duke@435 455 // didn't fit return non-index
duke@435 456 return -1;
duke@435 457 #endif /* _LP64 */
duke@435 458 }
duke@435 459 }
duke@435 460
duke@435 461
duke@435 462 address Relocation::index_to_runtime_address(int32_t index) {
duke@435 463 if (index == 0) return NULL;
duke@435 464
never@2737 465 if (is_reloc_index(index)) {
duke@435 466 StubCodeDesc* p = StubCodeDesc::desc_for_index(index);
duke@435 467 assert(p != NULL, "there must be a stub for this index");
duke@435 468 return p->begin();
duke@435 469 } else {
duke@435 470 #ifndef _LP64
duke@435 471 // this only works on 32bit machines
duke@435 472 return (address) ((intptr_t) index);
duke@435 473 #else
duke@435 474 fatal("Relocation::index_to_runtime_address, int32_t not pointer sized");
duke@435 475 return NULL;
duke@435 476 #endif /* _LP64 */
duke@435 477 }
duke@435 478 }
duke@435 479
duke@435 480 address Relocation::old_addr_for(address newa,
duke@435 481 const CodeBuffer* src, CodeBuffer* dest) {
duke@435 482 int sect = dest->section_index_of(newa);
duke@435 483 guarantee(sect != CodeBuffer::SECT_NONE, "lost track of this address");
duke@435 484 address ostart = src->code_section(sect)->start();
duke@435 485 address nstart = dest->code_section(sect)->start();
duke@435 486 return ostart + (newa - nstart);
duke@435 487 }
duke@435 488
duke@435 489 address Relocation::new_addr_for(address olda,
duke@435 490 const CodeBuffer* src, CodeBuffer* dest) {
duke@435 491 debug_only(const CodeBuffer* src0 = src);
duke@435 492 int sect = CodeBuffer::SECT_NONE;
duke@435 493 // Look for olda in the source buffer, and all previous incarnations
duke@435 494 // if the source buffer has been expanded.
duke@435 495 for (; src != NULL; src = src->before_expand()) {
duke@435 496 sect = src->section_index_of(olda);
duke@435 497 if (sect != CodeBuffer::SECT_NONE) break;
duke@435 498 }
duke@435 499 guarantee(sect != CodeBuffer::SECT_NONE, "lost track of this address");
duke@435 500 address ostart = src->code_section(sect)->start();
duke@435 501 address nstart = dest->code_section(sect)->start();
duke@435 502 return nstart + (olda - ostart);
duke@435 503 }
duke@435 504
duke@435 505 void Relocation::normalize_address(address& addr, const CodeSection* dest, bool allow_other_sections) {
duke@435 506 address addr0 = addr;
duke@435 507 if (addr0 == NULL || dest->allocates2(addr0)) return;
duke@435 508 CodeBuffer* cb = dest->outer();
duke@435 509 addr = new_addr_for(addr0, cb, cb);
duke@435 510 assert(allow_other_sections || dest->contains2(addr),
duke@435 511 "addr must be in required section");
duke@435 512 }
duke@435 513
duke@435 514
duke@435 515 void CallRelocation::set_destination(address x) {
duke@435 516 pd_set_call_destination(x);
duke@435 517 }
duke@435 518
duke@435 519 void CallRelocation::fix_relocation_after_move(const CodeBuffer* src, CodeBuffer* dest) {
duke@435 520 // Usually a self-relative reference to an external routine.
duke@435 521 // On some platforms, the reference is absolute (not self-relative).
duke@435 522 // The enhanced use of pd_call_destination sorts this all out.
duke@435 523 address orig_addr = old_addr_for(addr(), src, dest);
duke@435 524 address callee = pd_call_destination(orig_addr);
duke@435 525 // Reassert the callee address, this time in the new copy of the code.
duke@435 526 pd_set_call_destination(callee);
duke@435 527 }
duke@435 528
duke@435 529
duke@435 530 //// pack/unpack methods
duke@435 531
duke@435 532 void oop_Relocation::pack_data_to(CodeSection* dest) {
duke@435 533 short* p = (short*) dest->locs_end();
duke@435 534 p = pack_2_ints_to(p, _oop_index, _offset);
duke@435 535 dest->set_locs_end((relocInfo*) p);
duke@435 536 }
duke@435 537
duke@435 538
duke@435 539 void oop_Relocation::unpack_data() {
duke@435 540 unpack_2_ints(_oop_index, _offset);
duke@435 541 }
duke@435 542
coleenp@4037 543 void metadata_Relocation::pack_data_to(CodeSection* dest) {
coleenp@4037 544 short* p = (short*) dest->locs_end();
coleenp@4037 545 p = pack_2_ints_to(p, _metadata_index, _offset);
coleenp@4037 546 dest->set_locs_end((relocInfo*) p);
coleenp@4037 547 }
coleenp@4037 548
coleenp@4037 549
coleenp@4037 550 void metadata_Relocation::unpack_data() {
coleenp@4037 551 unpack_2_ints(_metadata_index, _offset);
coleenp@4037 552 }
coleenp@4037 553
duke@435 554
duke@435 555 void virtual_call_Relocation::pack_data_to(CodeSection* dest) {
duke@435 556 short* p = (short*) dest->locs_end();
duke@435 557 address point = dest->locs_point();
duke@435 558
coleenp@4037 559 normalize_address(_cached_value, dest);
coleenp@4037 560 jint x0 = scaled_offset_null_special(_cached_value, point);
coleenp@4037 561 p = pack_1_int_to(p, x0);
duke@435 562 dest->set_locs_end((relocInfo*) p);
duke@435 563 }
duke@435 564
duke@435 565
duke@435 566 void virtual_call_Relocation::unpack_data() {
coleenp@4037 567 jint x0 = unpack_1_int();
duke@435 568 address point = addr();
coleenp@4037 569 _cached_value = x0==0? NULL: address_from_scaled_offset(x0, point);
duke@435 570 }
duke@435 571
duke@435 572
duke@435 573 void static_stub_Relocation::pack_data_to(CodeSection* dest) {
duke@435 574 short* p = (short*) dest->locs_end();
duke@435 575 CodeSection* insts = dest->outer()->insts();
duke@435 576 normalize_address(_static_call, insts);
duke@435 577 p = pack_1_int_to(p, scaled_offset(_static_call, insts->start()));
duke@435 578 dest->set_locs_end((relocInfo*) p);
duke@435 579 }
duke@435 580
duke@435 581 void static_stub_Relocation::unpack_data() {
duke@435 582 address base = binding()->section_start(CodeBuffer::SECT_INSTS);
duke@435 583 _static_call = address_from_scaled_offset(unpack_1_int(), base);
duke@435 584 }
duke@435 585
goetz@6447 586 void trampoline_stub_Relocation::pack_data_to(CodeSection* dest ) {
goetz@6447 587 short* p = (short*) dest->locs_end();
goetz@6447 588 CodeSection* insts = dest->outer()->insts();
goetz@6447 589 normalize_address(_owner, insts);
goetz@6447 590 p = pack_1_int_to(p, scaled_offset(_owner, insts->start()));
goetz@6447 591 dest->set_locs_end((relocInfo*) p);
goetz@6447 592 }
goetz@6447 593
goetz@6447 594 void trampoline_stub_Relocation::unpack_data() {
goetz@6447 595 address base = binding()->section_start(CodeBuffer::SECT_INSTS);
goetz@6447 596 _owner = address_from_scaled_offset(unpack_1_int(), base);
goetz@6447 597 }
duke@435 598
duke@435 599 void external_word_Relocation::pack_data_to(CodeSection* dest) {
duke@435 600 short* p = (short*) dest->locs_end();
duke@435 601 int32_t index = runtime_address_to_index(_target);
duke@435 602 #ifndef _LP64
duke@435 603 p = pack_1_int_to(p, index);
duke@435 604 #else
never@2737 605 if (is_reloc_index(index)) {
duke@435 606 p = pack_2_ints_to(p, index, 0);
duke@435 607 } else {
duke@435 608 jlong t = (jlong) _target;
duke@435 609 int32_t lo = low(t);
duke@435 610 int32_t hi = high(t);
duke@435 611 p = pack_2_ints_to(p, lo, hi);
duke@435 612 DEBUG_ONLY(jlong t1 = jlong_from(hi, lo));
never@2737 613 assert(!is_reloc_index(t1) && (address) t1 == _target, "not symmetric");
duke@435 614 }
duke@435 615 #endif /* _LP64 */
duke@435 616 dest->set_locs_end((relocInfo*) p);
duke@435 617 }
duke@435 618
duke@435 619
duke@435 620 void external_word_Relocation::unpack_data() {
duke@435 621 #ifndef _LP64
duke@435 622 _target = index_to_runtime_address(unpack_1_int());
duke@435 623 #else
duke@435 624 int32_t lo, hi;
duke@435 625 unpack_2_ints(lo, hi);
duke@435 626 jlong t = jlong_from(hi, lo);;
never@2737 627 if (is_reloc_index(t)) {
duke@435 628 _target = index_to_runtime_address(t);
duke@435 629 } else {
duke@435 630 _target = (address) t;
duke@435 631 }
duke@435 632 #endif /* _LP64 */
duke@435 633 }
duke@435 634
duke@435 635
duke@435 636 void internal_word_Relocation::pack_data_to(CodeSection* dest) {
duke@435 637 short* p = (short*) dest->locs_end();
duke@435 638 normalize_address(_target, dest, true);
duke@435 639
duke@435 640 // Check whether my target address is valid within this section.
duke@435 641 // If not, strengthen the relocation type to point to another section.
duke@435 642 int sindex = _section;
duke@435 643 if (sindex == CodeBuffer::SECT_NONE && _target != NULL
duke@435 644 && (!dest->allocates(_target) || _target == dest->locs_point())) {
duke@435 645 sindex = dest->outer()->section_index_of(_target);
duke@435 646 guarantee(sindex != CodeBuffer::SECT_NONE, "must belong somewhere");
duke@435 647 relocInfo* base = dest->locs_end() - 1;
duke@435 648 assert(base->type() == this->type(), "sanity");
duke@435 649 // Change the written type, to be section_word_type instead.
duke@435 650 base->set_type(relocInfo::section_word_type);
duke@435 651 }
duke@435 652
duke@435 653 // Note: An internal_word relocation cannot refer to its own instruction,
duke@435 654 // because we reserve "0" to mean that the pointer itself is embedded
duke@435 655 // in the code stream. We use a section_word relocation for such cases.
duke@435 656
duke@435 657 if (sindex == CodeBuffer::SECT_NONE) {
duke@435 658 assert(type() == relocInfo::internal_word_type, "must be base class");
duke@435 659 guarantee(_target == NULL || dest->allocates2(_target), "must be within the given code section");
duke@435 660 jint x0 = scaled_offset_null_special(_target, dest->locs_point());
duke@435 661 assert(!(x0 == 0 && _target != NULL), "correct encoding of null target");
duke@435 662 p = pack_1_int_to(p, x0);
duke@435 663 } else {
duke@435 664 assert(_target != NULL, "sanity");
duke@435 665 CodeSection* sect = dest->outer()->code_section(sindex);
duke@435 666 guarantee(sect->allocates2(_target), "must be in correct section");
duke@435 667 address base = sect->start();
duke@435 668 jint offset = scaled_offset(_target, base);
duke@435 669 assert((uint)sindex < (uint)CodeBuffer::SECT_LIMIT, "sanity");
duke@435 670 assert(CodeBuffer::SECT_LIMIT <= (1 << section_width), "section_width++");
duke@435 671 p = pack_1_int_to(p, (offset << section_width) | sindex);
duke@435 672 }
duke@435 673
duke@435 674 dest->set_locs_end((relocInfo*) p);
duke@435 675 }
duke@435 676
duke@435 677
duke@435 678 void internal_word_Relocation::unpack_data() {
duke@435 679 jint x0 = unpack_1_int();
duke@435 680 _target = x0==0? NULL: address_from_scaled_offset(x0, addr());
duke@435 681 _section = CodeBuffer::SECT_NONE;
duke@435 682 }
duke@435 683
duke@435 684
duke@435 685 void section_word_Relocation::unpack_data() {
duke@435 686 jint x = unpack_1_int();
duke@435 687 jint offset = (x >> section_width);
duke@435 688 int sindex = (x & ((1<<section_width)-1));
duke@435 689 address base = binding()->section_start(sindex);
duke@435 690
duke@435 691 _section = sindex;
duke@435 692 _target = address_from_scaled_offset(offset, base);
duke@435 693 }
duke@435 694
duke@435 695 //// miscellaneous methods
duke@435 696 oop* oop_Relocation::oop_addr() {
duke@435 697 int n = _oop_index;
duke@435 698 if (n == 0) {
duke@435 699 // oop is stored in the code stream
duke@435 700 return (oop*) pd_address_in_code();
duke@435 701 } else {
twisti@1918 702 // oop is stored in table at nmethod::oops_begin
duke@435 703 return code()->oop_addr_at(n);
duke@435 704 }
duke@435 705 }
duke@435 706
duke@435 707
duke@435 708 oop oop_Relocation::oop_value() {
duke@435 709 oop v = *oop_addr();
duke@435 710 // clean inline caches store a special pseudo-null
duke@435 711 if (v == (oop)Universe::non_oop_word()) v = NULL;
duke@435 712 return v;
duke@435 713 }
duke@435 714
duke@435 715
duke@435 716 void oop_Relocation::fix_oop_relocation() {
duke@435 717 if (!oop_is_immediate()) {
duke@435 718 // get the oop from the pool, and re-insert it into the instruction:
duke@435 719 set_value(value());
duke@435 720 }
duke@435 721 }
duke@435 722
duke@435 723
never@2657 724 void oop_Relocation::verify_oop_relocation() {
never@2657 725 if (!oop_is_immediate()) {
never@2657 726 // get the oop from the pool, and re-insert it into the instruction:
never@2657 727 verify_value(value());
never@2657 728 }
never@2657 729 }
never@2657 730
coleenp@4037 731 // meta data versions
coleenp@4037 732 Metadata** metadata_Relocation::metadata_addr() {
coleenp@4037 733 int n = _metadata_index;
coleenp@4037 734 if (n == 0) {
coleenp@4037 735 // metadata is stored in the code stream
coleenp@4037 736 return (Metadata**) pd_address_in_code();
duke@435 737 } else {
coleenp@4037 738 // metadata is stored in table at nmethod::metadatas_begin
coleenp@4037 739 return code()->metadata_addr_at(n);
duke@435 740 }
duke@435 741 }
duke@435 742
duke@435 743
coleenp@4037 744 Metadata* metadata_Relocation::metadata_value() {
coleenp@4037 745 Metadata* v = *metadata_addr();
coleenp@4037 746 // clean inline caches store a special pseudo-null
coleenp@4037 747 if (v == (Metadata*)Universe::non_oop_word()) v = NULL;
coleenp@4037 748 return v;
duke@435 749 }
duke@435 750
coleenp@4037 751
coleenp@4037 752 void metadata_Relocation::fix_metadata_relocation() {
coleenp@4037 753 if (!metadata_is_immediate()) {
coleenp@4037 754 // get the metadata from the pool, and re-insert it into the instruction:
coleenp@4037 755 pd_fix_value(value());
coleenp@4037 756 }
duke@435 757 }
duke@435 758
duke@435 759
coleenp@4037 760 void metadata_Relocation::verify_metadata_relocation() {
coleenp@4037 761 if (!metadata_is_immediate()) {
coleenp@4037 762 // get the metadata from the pool, and re-insert it into the instruction:
coleenp@4037 763 verify_value(value());
coleenp@4037 764 }
duke@435 765 }
duke@435 766
coleenp@4037 767 address virtual_call_Relocation::cached_value() {
coleenp@4037 768 assert(_cached_value != NULL && _cached_value < addr(), "must precede ic_call");
coleenp@4037 769 return _cached_value;
duke@435 770 }
duke@435 771
duke@435 772
duke@435 773 void virtual_call_Relocation::clear_inline_cache() {
duke@435 774 // No stubs for ICs
duke@435 775 // Clean IC
duke@435 776 ResourceMark rm;
duke@435 777 CompiledIC* icache = CompiledIC_at(this);
duke@435 778 icache->set_to_clean();
duke@435 779 }
duke@435 780
duke@435 781
duke@435 782 void opt_virtual_call_Relocation::clear_inline_cache() {
duke@435 783 // No stubs for ICs
duke@435 784 // Clean IC
duke@435 785 ResourceMark rm;
duke@435 786 CompiledIC* icache = CompiledIC_at(this);
duke@435 787 icache->set_to_clean();
duke@435 788 }
duke@435 789
duke@435 790
duke@435 791 address opt_virtual_call_Relocation::static_stub() {
duke@435 792 // search for the static stub who points back to this static call
duke@435 793 address static_call_addr = addr();
duke@435 794 RelocIterator iter(code());
duke@435 795 while (iter.next()) {
duke@435 796 if (iter.type() == relocInfo::static_stub_type) {
duke@435 797 if (iter.static_stub_reloc()->static_call() == static_call_addr) {
duke@435 798 return iter.addr();
duke@435 799 }
duke@435 800 }
duke@435 801 }
duke@435 802 return NULL;
duke@435 803 }
duke@435 804
duke@435 805
duke@435 806 void static_call_Relocation::clear_inline_cache() {
duke@435 807 // Safe call site info
duke@435 808 CompiledStaticCall* handler = compiledStaticCall_at(this);
duke@435 809 handler->set_to_clean();
duke@435 810 }
duke@435 811
duke@435 812
duke@435 813 address static_call_Relocation::static_stub() {
duke@435 814 // search for the static stub who points back to this static call
duke@435 815 address static_call_addr = addr();
duke@435 816 RelocIterator iter(code());
duke@435 817 while (iter.next()) {
duke@435 818 if (iter.type() == relocInfo::static_stub_type) {
duke@435 819 if (iter.static_stub_reloc()->static_call() == static_call_addr) {
duke@435 820 return iter.addr();
duke@435 821 }
duke@435 822 }
duke@435 823 }
duke@435 824 return NULL;
duke@435 825 }
duke@435 826
goetz@6447 827 // Finds the trampoline address for a call. If no trampoline stub is
goetz@6447 828 // found NULL is returned which can be handled by the caller.
goetz@6447 829 address trampoline_stub_Relocation::get_trampoline_for(address call, nmethod* code) {
goetz@6447 830 // There are no relocations available when the code gets relocated
goetz@6447 831 // because of CodeBuffer expansion.
goetz@6447 832 if (code->relocation_size() == 0)
goetz@6447 833 return NULL;
goetz@6447 834
goetz@6447 835 RelocIterator iter(code, call);
goetz@6447 836 while (iter.next()) {
goetz@6447 837 if (iter.type() == relocInfo::trampoline_stub_type) {
goetz@6447 838 if (iter.trampoline_stub_reloc()->owner() == call) {
goetz@6447 839 return iter.addr();
goetz@6447 840 }
goetz@6447 841 }
goetz@6447 842 }
goetz@6447 843
goetz@6447 844 return NULL;
goetz@6447 845 }
duke@435 846
duke@435 847 void static_stub_Relocation::clear_inline_cache() {
duke@435 848 // Call stub is only used when calling the interpreted code.
duke@435 849 // It does not really need to be cleared, except that we want to clean out the methodoop.
duke@435 850 CompiledStaticCall::set_stub_to_clean(this);
duke@435 851 }
duke@435 852
duke@435 853
duke@435 854 void external_word_Relocation::fix_relocation_after_move(const CodeBuffer* src, CodeBuffer* dest) {
duke@435 855 address target = _target;
duke@435 856 if (target == NULL) {
duke@435 857 // An absolute embedded reference to an external location,
duke@435 858 // which means there is nothing to fix here.
duke@435 859 return;
duke@435 860 }
duke@435 861 // Probably this reference is absolute, not relative, so the
duke@435 862 // following is probably a no-op.
duke@435 863 assert(src->section_index_of(target) == CodeBuffer::SECT_NONE, "sanity");
duke@435 864 set_value(target);
duke@435 865 }
duke@435 866
duke@435 867
duke@435 868 address external_word_Relocation::target() {
duke@435 869 address target = _target;
duke@435 870 if (target == NULL) {
duke@435 871 target = pd_get_address_from_code();
duke@435 872 }
duke@435 873 return target;
duke@435 874 }
duke@435 875
duke@435 876
duke@435 877 void internal_word_Relocation::fix_relocation_after_move(const CodeBuffer* src, CodeBuffer* dest) {
duke@435 878 address target = _target;
duke@435 879 if (target == NULL) {
thartmann@7194 880 target = new_addr_for(this->target(), src, dest);
duke@435 881 }
duke@435 882 set_value(target);
duke@435 883 }
duke@435 884
duke@435 885
duke@435 886 address internal_word_Relocation::target() {
duke@435 887 address target = _target;
duke@435 888 if (target == NULL) {
thartmann@7194 889 if (addr_in_const()) {
thartmann@7194 890 target = *(address*)addr();
thartmann@7194 891 } else {
thartmann@7194 892 target = pd_get_address_from_code();
thartmann@7194 893 }
duke@435 894 }
duke@435 895 return target;
duke@435 896 }
duke@435 897
duke@435 898 //---------------------------------------------------------------------------------
duke@435 899 // Non-product code
duke@435 900
duke@435 901 #ifndef PRODUCT
duke@435 902
duke@435 903 static const char* reloc_type_string(relocInfo::relocType t) {
duke@435 904 switch (t) {
duke@435 905 #define EACH_CASE(name) \
duke@435 906 case relocInfo::name##_type: \
duke@435 907 return #name;
duke@435 908
duke@435 909 APPLY_TO_RELOCATIONS(EACH_CASE);
duke@435 910 #undef EACH_CASE
duke@435 911
duke@435 912 case relocInfo::none:
duke@435 913 return "none";
duke@435 914 case relocInfo::data_prefix_tag:
duke@435 915 return "prefix";
duke@435 916 default:
duke@435 917 return "UNKNOWN RELOC TYPE";
duke@435 918 }
duke@435 919 }
duke@435 920
duke@435 921
duke@435 922 void RelocIterator::print_current() {
duke@435 923 if (!has_current()) {
duke@435 924 tty->print_cr("(no relocs)");
duke@435 925 return;
duke@435 926 }
iveresov@2344 927 tty->print("relocInfo@" INTPTR_FORMAT " [type=%d(%s) addr=" INTPTR_FORMAT " offset=%d",
iveresov@2344 928 _current, type(), reloc_type_string((relocInfo::relocType) type()), _addr, _current->addr_offset());
duke@435 929 if (current()->format() != 0)
duke@435 930 tty->print(" format=%d", current()->format());
duke@435 931 if (datalen() == 1) {
duke@435 932 tty->print(" data=%d", data()[0]);
duke@435 933 } else if (datalen() > 0) {
duke@435 934 tty->print(" data={");
duke@435 935 for (int i = 0; i < datalen(); i++) {
duke@435 936 tty->print("%04x", data()[i] & 0xFFFF);
duke@435 937 }
duke@435 938 tty->print("}");
duke@435 939 }
duke@435 940 tty->print("]");
duke@435 941 switch (type()) {
duke@435 942 case relocInfo::oop_type:
duke@435 943 {
duke@435 944 oop_Relocation* r = oop_reloc();
duke@435 945 oop* oop_addr = NULL;
duke@435 946 oop raw_oop = NULL;
duke@435 947 oop oop_value = NULL;
duke@435 948 if (code() != NULL || r->oop_is_immediate()) {
duke@435 949 oop_addr = r->oop_addr();
duke@435 950 raw_oop = *oop_addr;
duke@435 951 oop_value = r->oop_value();
duke@435 952 }
duke@435 953 tty->print(" | [oop_addr=" INTPTR_FORMAT " *=" INTPTR_FORMAT " offset=%d]",
duke@435 954 oop_addr, (address)raw_oop, r->offset());
duke@435 955 // Do not print the oop by default--we want this routine to
duke@435 956 // work even during GC or other inconvenient times.
duke@435 957 if (WizardMode && oop_value != NULL) {
duke@435 958 tty->print("oop_value=" INTPTR_FORMAT ": ", (address)oop_value);
duke@435 959 oop_value->print_value_on(tty);
duke@435 960 }
duke@435 961 break;
duke@435 962 }
coleenp@4037 963 case relocInfo::metadata_type:
coleenp@4037 964 {
coleenp@4037 965 metadata_Relocation* r = metadata_reloc();
coleenp@4037 966 Metadata** metadata_addr = NULL;
coleenp@4037 967 Metadata* raw_metadata = NULL;
coleenp@4037 968 Metadata* metadata_value = NULL;
coleenp@4037 969 if (code() != NULL || r->metadata_is_immediate()) {
coleenp@4037 970 metadata_addr = r->metadata_addr();
coleenp@4037 971 raw_metadata = *metadata_addr;
coleenp@4037 972 metadata_value = r->metadata_value();
coleenp@4037 973 }
coleenp@4037 974 tty->print(" | [metadata_addr=" INTPTR_FORMAT " *=" INTPTR_FORMAT " offset=%d]",
coleenp@4037 975 metadata_addr, (address)raw_metadata, r->offset());
coleenp@4037 976 if (metadata_value != NULL) {
coleenp@4037 977 tty->print("metadata_value=" INTPTR_FORMAT ": ", (address)metadata_value);
coleenp@4037 978 metadata_value->print_value_on(tty);
coleenp@4037 979 }
coleenp@4037 980 break;
coleenp@4037 981 }
duke@435 982 case relocInfo::external_word_type:
duke@435 983 case relocInfo::internal_word_type:
duke@435 984 case relocInfo::section_word_type:
duke@435 985 {
duke@435 986 DataRelocation* r = (DataRelocation*) reloc();
duke@435 987 tty->print(" | [target=" INTPTR_FORMAT "]", r->value()); //value==target
duke@435 988 break;
duke@435 989 }
duke@435 990 case relocInfo::static_call_type:
duke@435 991 case relocInfo::runtime_call_type:
duke@435 992 {
duke@435 993 CallRelocation* r = (CallRelocation*) reloc();
duke@435 994 tty->print(" | [destination=" INTPTR_FORMAT "]", r->destination());
duke@435 995 break;
duke@435 996 }
duke@435 997 case relocInfo::virtual_call_type:
duke@435 998 {
duke@435 999 virtual_call_Relocation* r = (virtual_call_Relocation*) reloc();
coleenp@4037 1000 tty->print(" | [destination=" INTPTR_FORMAT " cached_value=" INTPTR_FORMAT "]",
coleenp@4037 1001 r->destination(), r->cached_value());
duke@435 1002 break;
duke@435 1003 }
duke@435 1004 case relocInfo::static_stub_type:
duke@435 1005 {
duke@435 1006 static_stub_Relocation* r = (static_stub_Relocation*) reloc();
duke@435 1007 tty->print(" | [static_call=" INTPTR_FORMAT "]", r->static_call());
duke@435 1008 break;
duke@435 1009 }
goetz@6447 1010 case relocInfo::trampoline_stub_type:
goetz@6447 1011 {
goetz@6447 1012 trampoline_stub_Relocation* r = (trampoline_stub_Relocation*) reloc();
goetz@6447 1013 tty->print(" | [trampoline owner=" INTPTR_FORMAT "]", r->owner());
goetz@6447 1014 break;
goetz@6447 1015 }
duke@435 1016 }
duke@435 1017 tty->cr();
duke@435 1018 }
duke@435 1019
duke@435 1020
duke@435 1021 void RelocIterator::print() {
duke@435 1022 RelocIterator save_this = (*this);
duke@435 1023 relocInfo* scan = _current;
duke@435 1024 if (!has_current()) scan += 1; // nothing to scan here!
duke@435 1025
duke@435 1026 bool skip_next = has_current();
duke@435 1027 bool got_next;
duke@435 1028 while (true) {
duke@435 1029 got_next = (skip_next || next());
duke@435 1030 skip_next = false;
duke@435 1031
duke@435 1032 tty->print(" @" INTPTR_FORMAT ": ", scan);
duke@435 1033 relocInfo* newscan = _current+1;
duke@435 1034 if (!has_current()) newscan -= 1; // nothing to scan here!
duke@435 1035 while (scan < newscan) {
duke@435 1036 tty->print("%04x", *(short*)scan & 0xFFFF);
duke@435 1037 scan++;
duke@435 1038 }
duke@435 1039 tty->cr();
duke@435 1040
duke@435 1041 if (!got_next) break;
duke@435 1042 print_current();
duke@435 1043 }
duke@435 1044
duke@435 1045 (*this) = save_this;
duke@435 1046 }
duke@435 1047
duke@435 1048 // For the debugger:
duke@435 1049 extern "C"
twisti@1918 1050 void print_blob_locs(nmethod* nm) {
twisti@1918 1051 nm->print();
twisti@1918 1052 RelocIterator iter(nm);
duke@435 1053 iter.print();
duke@435 1054 }
duke@435 1055 extern "C"
duke@435 1056 void print_buf_locs(CodeBuffer* cb) {
duke@435 1057 FlagSetting fs(PrintRelocations, true);
duke@435 1058 cb->print();
duke@435 1059 }
duke@435 1060 #endif // !PRODUCT

mercurial