1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/src/share/vm/code/relocInfo.cpp Sat Dec 01 00:00:00 2007 +0000 1.3 @@ -0,0 +1,1188 @@ 1.4 +/* 1.5 + * Copyright 1997-2007 Sun Microsystems, Inc. All Rights Reserved. 1.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 1.7 + * 1.8 + * This code is free software; you can redistribute it and/or modify it 1.9 + * under the terms of the GNU General Public License version 2 only, as 1.10 + * published by the Free Software Foundation. 1.11 + * 1.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 1.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 1.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 1.15 + * version 2 for more details (a copy is included in the LICENSE file that 1.16 + * accompanied this code). 1.17 + * 1.18 + * You should have received a copy of the GNU General Public License version 1.19 + * 2 along with this work; if not, write to the Free Software Foundation, 1.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 1.21 + * 1.22 + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, 1.23 + * CA 95054 USA or visit www.sun.com if you need additional information or 1.24 + * have any questions. 1.25 + * 1.26 + */ 1.27 + 1.28 +# include "incls/_precompiled.incl" 1.29 +# include "incls/_relocInfo.cpp.incl" 1.30 + 1.31 + 1.32 +const RelocationHolder RelocationHolder::none; // its type is relocInfo::none 1.33 + 1.34 + 1.35 +// Implementation of relocInfo 1.36 + 1.37 +#ifdef ASSERT 1.38 +relocInfo::relocInfo(relocType t, int off, int f) { 1.39 + assert(t != data_prefix_tag, "cannot build a prefix this way"); 1.40 + assert((t & type_mask) == t, "wrong type"); 1.41 + assert((f & format_mask) == f, "wrong format"); 1.42 + assert(off >= 0 && off < offset_limit(), "offset out off bounds"); 1.43 + assert((off & (offset_unit-1)) == 0, "misaligned offset"); 1.44 + (*this) = relocInfo(t, RAW_BITS, off, f); 1.45 +} 1.46 +#endif 1.47 + 1.48 +void relocInfo::initialize(CodeSection* dest, Relocation* reloc) { 1.49 + relocInfo* data = this+1; // here's where the data might go 1.50 + dest->set_locs_end(data); // sync end: the next call may read dest.locs_end 1.51 + reloc->pack_data_to(dest); // maybe write data into locs, advancing locs_end 1.52 + relocInfo* data_limit = dest->locs_end(); 1.53 + if (data_limit > data) { 1.54 + relocInfo suffix = (*this); 1.55 + data_limit = this->finish_prefix((short*) data_limit); 1.56 + // Finish up with the suffix. (Hack note: pack_data_to might edit this.) 1.57 + *data_limit = suffix; 1.58 + dest->set_locs_end(data_limit+1); 1.59 + } 1.60 +} 1.61 + 1.62 +relocInfo* relocInfo::finish_prefix(short* prefix_limit) { 1.63 + assert(sizeof(relocInfo) == sizeof(short), "change this code"); 1.64 + short* p = (short*)(this+1); 1.65 + assert(prefix_limit >= p, "must be a valid span of data"); 1.66 + int plen = prefix_limit - p; 1.67 + if (plen == 0) { 1.68 + debug_only(_value = 0xFFFF); 1.69 + return this; // no data: remove self completely 1.70 + } 1.71 + if (plen == 1 && fits_into_immediate(p[0])) { 1.72 + (*this) = immediate_relocInfo(p[0]); // move data inside self 1.73 + return this+1; 1.74 + } 1.75 + // cannot compact, so just update the count and return the limit pointer 1.76 + (*this) = prefix_relocInfo(plen); // write new datalen 1.77 + assert(data() + datalen() == prefix_limit, "pointers must line up"); 1.78 + return (relocInfo*)prefix_limit; 1.79 +} 1.80 + 1.81 + 1.82 +void relocInfo::set_type(relocType t) { 1.83 + int old_offset = addr_offset(); 1.84 + int old_format = format(); 1.85 + (*this) = relocInfo(t, old_offset, old_format); 1.86 + assert(type()==(int)t, "sanity check"); 1.87 + assert(addr_offset()==old_offset, "sanity check"); 1.88 + assert(format()==old_format, "sanity check"); 1.89 +} 1.90 + 1.91 + 1.92 +void relocInfo::set_format(int f) { 1.93 + int old_offset = addr_offset(); 1.94 + assert((f & format_mask) == f, "wrong format"); 1.95 + _value = (_value & ~(format_mask << offset_width)) | (f << offset_width); 1.96 + assert(addr_offset()==old_offset, "sanity check"); 1.97 +} 1.98 + 1.99 + 1.100 +void relocInfo::change_reloc_info_for_address(RelocIterator *itr, address pc, relocType old_type, relocType new_type) { 1.101 + bool found = false; 1.102 + while (itr->next() && !found) { 1.103 + if (itr->addr() == pc) { 1.104 + assert(itr->type()==old_type, "wrong relocInfo type found"); 1.105 + itr->current()->set_type(new_type); 1.106 + found=true; 1.107 + } 1.108 + } 1.109 + assert(found, "no relocInfo found for pc"); 1.110 +} 1.111 + 1.112 + 1.113 +void relocInfo::remove_reloc_info_for_address(RelocIterator *itr, address pc, relocType old_type) { 1.114 + change_reloc_info_for_address(itr, pc, old_type, none); 1.115 +} 1.116 + 1.117 + 1.118 +// ---------------------------------------------------------------------------------------------------- 1.119 +// Implementation of RelocIterator 1.120 + 1.121 +void RelocIterator::initialize(CodeBlob* cb, address begin, address limit) { 1.122 + initialize_misc(); 1.123 + 1.124 + if (cb == NULL && begin != NULL) { 1.125 + // allow CodeBlob to be deduced from beginning address 1.126 + cb = CodeCache::find_blob(begin); 1.127 + } 1.128 + assert(cb != NULL, "must be able to deduce nmethod from other arguments"); 1.129 + 1.130 + _code = cb; 1.131 + _current = cb->relocation_begin()-1; 1.132 + _end = cb->relocation_end(); 1.133 + _addr = (address) cb->instructions_begin(); 1.134 + 1.135 + assert(!has_current(), "just checking"); 1.136 + address code_end = cb->instructions_end(); 1.137 + 1.138 + assert(begin == NULL || begin >= cb->instructions_begin(), "in bounds"); 1.139 + // FIX THIS assert(limit == NULL || limit <= code_end, "in bounds"); 1.140 + set_limits(begin, limit); 1.141 +} 1.142 + 1.143 + 1.144 +RelocIterator::RelocIterator(CodeSection* cs, address begin, address limit) { 1.145 + initialize_misc(); 1.146 + 1.147 + _current = cs->locs_start()-1; 1.148 + _end = cs->locs_end(); 1.149 + _addr = cs->start(); 1.150 + _code = NULL; // Not cb->blob(); 1.151 + 1.152 + CodeBuffer* cb = cs->outer(); 1.153 + assert((int)SECT_LIMIT == CodeBuffer::SECT_LIMIT, "my copy must be equal"); 1.154 + for (int n = 0; n < (int)SECT_LIMIT; n++) { 1.155 + _section_start[n] = cb->code_section(n)->start(); 1.156 + } 1.157 + 1.158 + assert(!has_current(), "just checking"); 1.159 + 1.160 + assert(begin == NULL || begin >= cs->start(), "in bounds"); 1.161 + assert(limit == NULL || limit <= cs->end(), "in bounds"); 1.162 + set_limits(begin, limit); 1.163 +} 1.164 + 1.165 + 1.166 +enum { indexCardSize = 128 }; 1.167 +struct RelocIndexEntry { 1.168 + jint addr_offset; // offset from header_end of an addr() 1.169 + jint reloc_offset; // offset from header_end of a relocInfo (prefix) 1.170 +}; 1.171 + 1.172 + 1.173 +static inline int num_cards(int code_size) { 1.174 + return (code_size-1) / indexCardSize; 1.175 +} 1.176 + 1.177 + 1.178 +int RelocIterator::locs_and_index_size(int code_size, int locs_size) { 1.179 + if (!UseRelocIndex) return locs_size; // no index 1.180 + code_size = round_to(code_size, oopSize); 1.181 + locs_size = round_to(locs_size, oopSize); 1.182 + int index_size = num_cards(code_size) * sizeof(RelocIndexEntry); 1.183 + // format of indexed relocs: 1.184 + // relocation_begin: relocInfo ... 1.185 + // index: (addr,reloc#) ... 1.186 + // indexSize :relocation_end 1.187 + return locs_size + index_size + BytesPerInt; 1.188 +} 1.189 + 1.190 + 1.191 +void RelocIterator::create_index(relocInfo* dest_begin, int dest_count, relocInfo* dest_end) { 1.192 + address relocation_begin = (address)dest_begin; 1.193 + address relocation_end = (address)dest_end; 1.194 + int total_size = relocation_end - relocation_begin; 1.195 + int locs_size = dest_count * sizeof(relocInfo); 1.196 + if (!UseRelocIndex) { 1.197 + Copy::fill_to_bytes(relocation_begin + locs_size, total_size-locs_size, 0); 1.198 + return; 1.199 + } 1.200 + int index_size = total_size - locs_size - BytesPerInt; // find out how much space is left 1.201 + int ncards = index_size / sizeof(RelocIndexEntry); 1.202 + assert(total_size == locs_size + index_size + BytesPerInt, "checkin'"); 1.203 + assert(index_size >= 0 && index_size % sizeof(RelocIndexEntry) == 0, "checkin'"); 1.204 + jint* index_size_addr = (jint*)relocation_end - 1; 1.205 + 1.206 + assert(sizeof(jint) == BytesPerInt, "change this code"); 1.207 + 1.208 + *index_size_addr = index_size; 1.209 + if (index_size != 0) { 1.210 + assert(index_size > 0, "checkin'"); 1.211 + 1.212 + RelocIndexEntry* index = (RelocIndexEntry *)(relocation_begin + locs_size); 1.213 + assert(index == (RelocIndexEntry*)index_size_addr - ncards, "checkin'"); 1.214 + 1.215 + // walk over the relocations, and fill in index entries as we go 1.216 + RelocIterator iter; 1.217 + const address initial_addr = NULL; 1.218 + relocInfo* const initial_current = dest_begin - 1; // biased by -1 like elsewhere 1.219 + 1.220 + iter._code = NULL; 1.221 + iter._addr = initial_addr; 1.222 + iter._limit = (address)(intptr_t)(ncards * indexCardSize); 1.223 + iter._current = initial_current; 1.224 + iter._end = dest_begin + dest_count; 1.225 + 1.226 + int i = 0; 1.227 + address next_card_addr = (address)indexCardSize; 1.228 + int addr_offset = 0; 1.229 + int reloc_offset = 0; 1.230 + while (true) { 1.231 + // Checkpoint the iterator before advancing it. 1.232 + addr_offset = iter._addr - initial_addr; 1.233 + reloc_offset = iter._current - initial_current; 1.234 + if (!iter.next()) break; 1.235 + while (iter.addr() >= next_card_addr) { 1.236 + index[i].addr_offset = addr_offset; 1.237 + index[i].reloc_offset = reloc_offset; 1.238 + i++; 1.239 + next_card_addr += indexCardSize; 1.240 + } 1.241 + } 1.242 + while (i < ncards) { 1.243 + index[i].addr_offset = addr_offset; 1.244 + index[i].reloc_offset = reloc_offset; 1.245 + i++; 1.246 + } 1.247 + } 1.248 +} 1.249 + 1.250 + 1.251 +void RelocIterator::set_limits(address begin, address limit) { 1.252 + int index_size = 0; 1.253 + if (UseRelocIndex && _code != NULL) { 1.254 + index_size = ((jint*)_end)[-1]; 1.255 + _end = (relocInfo*)( (address)_end - index_size - BytesPerInt ); 1.256 + } 1.257 + 1.258 + _limit = limit; 1.259 + 1.260 + // the limit affects this next stuff: 1.261 + if (begin != NULL) { 1.262 +#ifdef ASSERT 1.263 + // In ASSERT mode we do not actually use the index, but simply 1.264 + // check that its contents would have led us to the right answer. 1.265 + address addrCheck = _addr; 1.266 + relocInfo* infoCheck = _current; 1.267 +#endif // ASSERT 1.268 + if (index_size > 0) { 1.269 + // skip ahead 1.270 + RelocIndexEntry* index = (RelocIndexEntry*)_end; 1.271 + RelocIndexEntry* index_limit = (RelocIndexEntry*)((address)index + index_size); 1.272 + assert(_addr == _code->instructions_begin(), "_addr must be unadjusted"); 1.273 + int card = (begin - _addr) / indexCardSize; 1.274 + if (card > 0) { 1.275 + if (index+card-1 < index_limit) index += card-1; 1.276 + else index = index_limit - 1; 1.277 +#ifdef ASSERT 1.278 + addrCheck = _addr + index->addr_offset; 1.279 + infoCheck = _current + index->reloc_offset; 1.280 +#else 1.281 + // Advance the iterator immediately to the last valid state 1.282 + // for the previous card. Calling "next" will then advance 1.283 + // it to the first item on the required card. 1.284 + _addr += index->addr_offset; 1.285 + _current += index->reloc_offset; 1.286 +#endif // ASSERT 1.287 + } 1.288 + } 1.289 + 1.290 + relocInfo* backup; 1.291 + address backup_addr; 1.292 + while (true) { 1.293 + backup = _current; 1.294 + backup_addr = _addr; 1.295 +#ifdef ASSERT 1.296 + if (backup == infoCheck) { 1.297 + assert(backup_addr == addrCheck, "must match"); addrCheck = NULL; infoCheck = NULL; 1.298 + } else { 1.299 + assert(addrCheck == NULL || backup_addr <= addrCheck, "must not pass addrCheck"); 1.300 + } 1.301 +#endif // ASSERT 1.302 + if (!next() || addr() >= begin) break; 1.303 + } 1.304 + assert(addrCheck == NULL || addrCheck == backup_addr, "must have matched addrCheck"); 1.305 + assert(infoCheck == NULL || infoCheck == backup, "must have matched infoCheck"); 1.306 + // At this point, either we are at the first matching record, 1.307 + // or else there is no such record, and !has_current(). 1.308 + // In either case, revert to the immediatly preceding state. 1.309 + _current = backup; 1.310 + _addr = backup_addr; 1.311 + set_has_current(false); 1.312 + } 1.313 +} 1.314 + 1.315 + 1.316 +void RelocIterator::set_limit(address limit) { 1.317 + address code_end = (address)code() + code()->size(); 1.318 + assert(limit == NULL || limit <= code_end, "in bounds"); 1.319 + _limit = limit; 1.320 +} 1.321 + 1.322 + 1.323 +void PatchingRelocIterator:: prepass() { 1.324 + // turn breakpoints off during patching 1.325 + _init_state = (*this); // save cursor 1.326 + while (next()) { 1.327 + if (type() == relocInfo::breakpoint_type) { 1.328 + breakpoint_reloc()->set_active(false); 1.329 + } 1.330 + } 1.331 + (RelocIterator&)(*this) = _init_state; // reset cursor for client 1.332 +} 1.333 + 1.334 + 1.335 +void PatchingRelocIterator:: postpass() { 1.336 + // turn breakpoints back on after patching 1.337 + (RelocIterator&)(*this) = _init_state; // reset cursor again 1.338 + while (next()) { 1.339 + if (type() == relocInfo::breakpoint_type) { 1.340 + breakpoint_Relocation* bpt = breakpoint_reloc(); 1.341 + bpt->set_active(bpt->enabled()); 1.342 + } 1.343 + } 1.344 +} 1.345 + 1.346 + 1.347 +// All the strange bit-encodings are in here. 1.348 +// The idea is to encode relocation data which are small integers 1.349 +// very efficiently (a single extra halfword). Larger chunks of 1.350 +// relocation data need a halfword header to hold their size. 1.351 +void RelocIterator::advance_over_prefix() { 1.352 + if (_current->is_datalen()) { 1.353 + _data = (short*) _current->data(); 1.354 + _datalen = _current->datalen(); 1.355 + _current += _datalen + 1; // skip the embedded data & header 1.356 + } else { 1.357 + _databuf = _current->immediate(); 1.358 + _data = &_databuf; 1.359 + _datalen = 1; 1.360 + _current++; // skip the header 1.361 + } 1.362 + // The client will see the following relocInfo, whatever that is. 1.363 + // It is the reloc to which the preceding data applies. 1.364 +} 1.365 + 1.366 + 1.367 +address RelocIterator::compute_section_start(int n) const { 1.368 +// This routine not only computes a section start, but also 1.369 +// memoizes it for later. 1.370 +#define CACHE ((RelocIterator*)this)->_section_start[n] 1.371 + CodeBlob* cb = code(); 1.372 + guarantee(cb != NULL, "must have a code blob"); 1.373 + if (n == CodeBuffer::SECT_INSTS) 1.374 + return CACHE = cb->instructions_begin(); 1.375 + assert(cb->is_nmethod(), "only nmethods have these sections"); 1.376 + nmethod* nm = (nmethod*) cb; 1.377 + address res = NULL; 1.378 + switch (n) { 1.379 + case CodeBuffer::SECT_STUBS: 1.380 + res = nm->stub_begin(); 1.381 + break; 1.382 + case CodeBuffer::SECT_CONSTS: 1.383 + res = nm->consts_begin(); 1.384 + break; 1.385 + default: 1.386 + ShouldNotReachHere(); 1.387 + } 1.388 + assert(nm->contains(res) || res == nm->instructions_end(), "tame pointer"); 1.389 + CACHE = res; 1.390 + return res; 1.391 +#undef CACHE 1.392 +} 1.393 + 1.394 + 1.395 +Relocation* RelocIterator::reloc() { 1.396 + // (take the "switch" out-of-line) 1.397 + relocInfo::relocType t = type(); 1.398 + if (false) {} 1.399 + #define EACH_TYPE(name) \ 1.400 + else if (t == relocInfo::name##_type) { \ 1.401 + return name##_reloc(); \ 1.402 + } 1.403 + APPLY_TO_RELOCATIONS(EACH_TYPE); 1.404 + #undef EACH_TYPE 1.405 + assert(t == relocInfo::none, "must be padding"); 1.406 + return new(_rh) Relocation(); 1.407 +} 1.408 + 1.409 + 1.410 +//////// Methods for flyweight Relocation types 1.411 + 1.412 + 1.413 +RelocationHolder RelocationHolder::plus(int offset) const { 1.414 + if (offset != 0) { 1.415 + switch (type()) { 1.416 + case relocInfo::none: 1.417 + break; 1.418 + case relocInfo::oop_type: 1.419 + { 1.420 + oop_Relocation* r = (oop_Relocation*)reloc(); 1.421 + return oop_Relocation::spec(r->oop_index(), r->offset() + offset); 1.422 + } 1.423 + default: 1.424 + ShouldNotReachHere(); 1.425 + } 1.426 + } 1.427 + return (*this); 1.428 +} 1.429 + 1.430 + 1.431 +void Relocation::guarantee_size() { 1.432 + guarantee(false, "Make _relocbuf bigger!"); 1.433 +} 1.434 + 1.435 + // some relocations can compute their own values 1.436 +address Relocation::value() { 1.437 + ShouldNotReachHere(); 1.438 + return NULL; 1.439 +} 1.440 + 1.441 + 1.442 +void Relocation::set_value(address x) { 1.443 + ShouldNotReachHere(); 1.444 +} 1.445 + 1.446 + 1.447 +RelocationHolder Relocation::spec_simple(relocInfo::relocType rtype) { 1.448 + if (rtype == relocInfo::none) return RelocationHolder::none; 1.449 + relocInfo ri = relocInfo(rtype, 0); 1.450 + RelocIterator itr; 1.451 + itr.set_current(ri); 1.452 + itr.reloc(); 1.453 + return itr._rh; 1.454 +} 1.455 + 1.456 + 1.457 +static inline bool is_index(intptr_t index) { 1.458 + return 0 < index && index < os::vm_page_size(); 1.459 +} 1.460 + 1.461 + 1.462 +int32_t Relocation::runtime_address_to_index(address runtime_address) { 1.463 + assert(!is_index((intptr_t)runtime_address), "must not look like an index"); 1.464 + 1.465 + if (runtime_address == NULL) return 0; 1.466 + 1.467 + StubCodeDesc* p = StubCodeDesc::desc_for(runtime_address); 1.468 + if (p != NULL && p->begin() == runtime_address) { 1.469 + assert(is_index(p->index()), "there must not be too many stubs"); 1.470 + return (int32_t)p->index(); 1.471 + } else { 1.472 + // Known "miscellaneous" non-stub pointers: 1.473 + // os::get_polling_page(), SafepointSynchronize::address_of_state() 1.474 + if (PrintRelocations) { 1.475 + tty->print_cr("random unregistered address in relocInfo: " INTPTR_FORMAT, runtime_address); 1.476 + } 1.477 +#ifndef _LP64 1.478 + return (int32_t) (intptr_t)runtime_address; 1.479 +#else 1.480 + // didn't fit return non-index 1.481 + return -1; 1.482 +#endif /* _LP64 */ 1.483 + } 1.484 +} 1.485 + 1.486 + 1.487 +address Relocation::index_to_runtime_address(int32_t index) { 1.488 + if (index == 0) return NULL; 1.489 + 1.490 + if (is_index(index)) { 1.491 + StubCodeDesc* p = StubCodeDesc::desc_for_index(index); 1.492 + assert(p != NULL, "there must be a stub for this index"); 1.493 + return p->begin(); 1.494 + } else { 1.495 +#ifndef _LP64 1.496 + // this only works on 32bit machines 1.497 + return (address) ((intptr_t) index); 1.498 +#else 1.499 + fatal("Relocation::index_to_runtime_address, int32_t not pointer sized"); 1.500 + return NULL; 1.501 +#endif /* _LP64 */ 1.502 + } 1.503 +} 1.504 + 1.505 +address Relocation::old_addr_for(address newa, 1.506 + const CodeBuffer* src, CodeBuffer* dest) { 1.507 + int sect = dest->section_index_of(newa); 1.508 + guarantee(sect != CodeBuffer::SECT_NONE, "lost track of this address"); 1.509 + address ostart = src->code_section(sect)->start(); 1.510 + address nstart = dest->code_section(sect)->start(); 1.511 + return ostart + (newa - nstart); 1.512 +} 1.513 + 1.514 +address Relocation::new_addr_for(address olda, 1.515 + const CodeBuffer* src, CodeBuffer* dest) { 1.516 + debug_only(const CodeBuffer* src0 = src); 1.517 + int sect = CodeBuffer::SECT_NONE; 1.518 + // Look for olda in the source buffer, and all previous incarnations 1.519 + // if the source buffer has been expanded. 1.520 + for (; src != NULL; src = src->before_expand()) { 1.521 + sect = src->section_index_of(olda); 1.522 + if (sect != CodeBuffer::SECT_NONE) break; 1.523 + } 1.524 + guarantee(sect != CodeBuffer::SECT_NONE, "lost track of this address"); 1.525 + address ostart = src->code_section(sect)->start(); 1.526 + address nstart = dest->code_section(sect)->start(); 1.527 + return nstart + (olda - ostart); 1.528 +} 1.529 + 1.530 +void Relocation::normalize_address(address& addr, const CodeSection* dest, bool allow_other_sections) { 1.531 + address addr0 = addr; 1.532 + if (addr0 == NULL || dest->allocates2(addr0)) return; 1.533 + CodeBuffer* cb = dest->outer(); 1.534 + addr = new_addr_for(addr0, cb, cb); 1.535 + assert(allow_other_sections || dest->contains2(addr), 1.536 + "addr must be in required section"); 1.537 +} 1.538 + 1.539 + 1.540 +void CallRelocation::set_destination(address x) { 1.541 + pd_set_call_destination(x); 1.542 +} 1.543 + 1.544 +void CallRelocation::fix_relocation_after_move(const CodeBuffer* src, CodeBuffer* dest) { 1.545 + // Usually a self-relative reference to an external routine. 1.546 + // On some platforms, the reference is absolute (not self-relative). 1.547 + // The enhanced use of pd_call_destination sorts this all out. 1.548 + address orig_addr = old_addr_for(addr(), src, dest); 1.549 + address callee = pd_call_destination(orig_addr); 1.550 + // Reassert the callee address, this time in the new copy of the code. 1.551 + pd_set_call_destination(callee); 1.552 +} 1.553 + 1.554 + 1.555 +//// pack/unpack methods 1.556 + 1.557 +void oop_Relocation::pack_data_to(CodeSection* dest) { 1.558 + short* p = (short*) dest->locs_end(); 1.559 + p = pack_2_ints_to(p, _oop_index, _offset); 1.560 + dest->set_locs_end((relocInfo*) p); 1.561 +} 1.562 + 1.563 + 1.564 +void oop_Relocation::unpack_data() { 1.565 + unpack_2_ints(_oop_index, _offset); 1.566 +} 1.567 + 1.568 + 1.569 +void virtual_call_Relocation::pack_data_to(CodeSection* dest) { 1.570 + short* p = (short*) dest->locs_end(); 1.571 + address point = dest->locs_point(); 1.572 + 1.573 + // Try to make a pointer NULL first. 1.574 + if (_oop_limit >= point && 1.575 + _oop_limit <= point + NativeCall::instruction_size) { 1.576 + _oop_limit = NULL; 1.577 + } 1.578 + // If the _oop_limit is NULL, it "defaults" to the end of the call. 1.579 + // See ic_call_Relocation::oop_limit() below. 1.580 + 1.581 + normalize_address(_first_oop, dest); 1.582 + normalize_address(_oop_limit, dest); 1.583 + jint x0 = scaled_offset_null_special(_first_oop, point); 1.584 + jint x1 = scaled_offset_null_special(_oop_limit, point); 1.585 + p = pack_2_ints_to(p, x0, x1); 1.586 + dest->set_locs_end((relocInfo*) p); 1.587 +} 1.588 + 1.589 + 1.590 +void virtual_call_Relocation::unpack_data() { 1.591 + jint x0, x1; unpack_2_ints(x0, x1); 1.592 + address point = addr(); 1.593 + _first_oop = x0==0? NULL: address_from_scaled_offset(x0, point); 1.594 + _oop_limit = x1==0? NULL: address_from_scaled_offset(x1, point); 1.595 +} 1.596 + 1.597 + 1.598 +void static_stub_Relocation::pack_data_to(CodeSection* dest) { 1.599 + short* p = (short*) dest->locs_end(); 1.600 + CodeSection* insts = dest->outer()->insts(); 1.601 + normalize_address(_static_call, insts); 1.602 + p = pack_1_int_to(p, scaled_offset(_static_call, insts->start())); 1.603 + dest->set_locs_end((relocInfo*) p); 1.604 +} 1.605 + 1.606 +void static_stub_Relocation::unpack_data() { 1.607 + address base = binding()->section_start(CodeBuffer::SECT_INSTS); 1.608 + _static_call = address_from_scaled_offset(unpack_1_int(), base); 1.609 +} 1.610 + 1.611 + 1.612 +void external_word_Relocation::pack_data_to(CodeSection* dest) { 1.613 + short* p = (short*) dest->locs_end(); 1.614 + int32_t index = runtime_address_to_index(_target); 1.615 +#ifndef _LP64 1.616 + p = pack_1_int_to(p, index); 1.617 +#else 1.618 + if (is_index(index)) { 1.619 + p = pack_2_ints_to(p, index, 0); 1.620 + } else { 1.621 + jlong t = (jlong) _target; 1.622 + int32_t lo = low(t); 1.623 + int32_t hi = high(t); 1.624 + p = pack_2_ints_to(p, lo, hi); 1.625 + DEBUG_ONLY(jlong t1 = jlong_from(hi, lo)); 1.626 + assert(!is_index(t1) && (address) t1 == _target, "not symmetric"); 1.627 + } 1.628 +#endif /* _LP64 */ 1.629 + dest->set_locs_end((relocInfo*) p); 1.630 +} 1.631 + 1.632 + 1.633 +void external_word_Relocation::unpack_data() { 1.634 +#ifndef _LP64 1.635 + _target = index_to_runtime_address(unpack_1_int()); 1.636 +#else 1.637 + int32_t lo, hi; 1.638 + unpack_2_ints(lo, hi); 1.639 + jlong t = jlong_from(hi, lo);; 1.640 + if (is_index(t)) { 1.641 + _target = index_to_runtime_address(t); 1.642 + } else { 1.643 + _target = (address) t; 1.644 + } 1.645 +#endif /* _LP64 */ 1.646 +} 1.647 + 1.648 + 1.649 +void internal_word_Relocation::pack_data_to(CodeSection* dest) { 1.650 + short* p = (short*) dest->locs_end(); 1.651 + normalize_address(_target, dest, true); 1.652 + 1.653 + // Check whether my target address is valid within this section. 1.654 + // If not, strengthen the relocation type to point to another section. 1.655 + int sindex = _section; 1.656 + if (sindex == CodeBuffer::SECT_NONE && _target != NULL 1.657 + && (!dest->allocates(_target) || _target == dest->locs_point())) { 1.658 + sindex = dest->outer()->section_index_of(_target); 1.659 + guarantee(sindex != CodeBuffer::SECT_NONE, "must belong somewhere"); 1.660 + relocInfo* base = dest->locs_end() - 1; 1.661 + assert(base->type() == this->type(), "sanity"); 1.662 + // Change the written type, to be section_word_type instead. 1.663 + base->set_type(relocInfo::section_word_type); 1.664 + } 1.665 + 1.666 + // Note: An internal_word relocation cannot refer to its own instruction, 1.667 + // because we reserve "0" to mean that the pointer itself is embedded 1.668 + // in the code stream. We use a section_word relocation for such cases. 1.669 + 1.670 + if (sindex == CodeBuffer::SECT_NONE) { 1.671 + assert(type() == relocInfo::internal_word_type, "must be base class"); 1.672 + guarantee(_target == NULL || dest->allocates2(_target), "must be within the given code section"); 1.673 + jint x0 = scaled_offset_null_special(_target, dest->locs_point()); 1.674 + assert(!(x0 == 0 && _target != NULL), "correct encoding of null target"); 1.675 + p = pack_1_int_to(p, x0); 1.676 + } else { 1.677 + assert(_target != NULL, "sanity"); 1.678 + CodeSection* sect = dest->outer()->code_section(sindex); 1.679 + guarantee(sect->allocates2(_target), "must be in correct section"); 1.680 + address base = sect->start(); 1.681 + jint offset = scaled_offset(_target, base); 1.682 + assert((uint)sindex < (uint)CodeBuffer::SECT_LIMIT, "sanity"); 1.683 + assert(CodeBuffer::SECT_LIMIT <= (1 << section_width), "section_width++"); 1.684 + p = pack_1_int_to(p, (offset << section_width) | sindex); 1.685 + } 1.686 + 1.687 + dest->set_locs_end((relocInfo*) p); 1.688 +} 1.689 + 1.690 + 1.691 +void internal_word_Relocation::unpack_data() { 1.692 + jint x0 = unpack_1_int(); 1.693 + _target = x0==0? NULL: address_from_scaled_offset(x0, addr()); 1.694 + _section = CodeBuffer::SECT_NONE; 1.695 +} 1.696 + 1.697 + 1.698 +void section_word_Relocation::unpack_data() { 1.699 + jint x = unpack_1_int(); 1.700 + jint offset = (x >> section_width); 1.701 + int sindex = (x & ((1<<section_width)-1)); 1.702 + address base = binding()->section_start(sindex); 1.703 + 1.704 + _section = sindex; 1.705 + _target = address_from_scaled_offset(offset, base); 1.706 +} 1.707 + 1.708 + 1.709 +void breakpoint_Relocation::pack_data_to(CodeSection* dest) { 1.710 + short* p = (short*) dest->locs_end(); 1.711 + address point = dest->locs_point(); 1.712 + 1.713 + *p++ = _bits; 1.714 + 1.715 + assert(_target != NULL, "sanity"); 1.716 + 1.717 + if (internal()) normalize_address(_target, dest); 1.718 + 1.719 + jint target_bits = 1.720 + (jint)( internal() ? scaled_offset (_target, point) 1.721 + : runtime_address_to_index(_target) ); 1.722 + if (settable()) { 1.723 + // save space for set_target later 1.724 + p = add_jint(p, target_bits); 1.725 + } else { 1.726 + p = add_var_int(p, target_bits); 1.727 + } 1.728 + 1.729 + for (int i = 0; i < instrlen(); i++) { 1.730 + // put placeholder words until bytes can be saved 1.731 + p = add_short(p, (short)0x7777); 1.732 + } 1.733 + 1.734 + dest->set_locs_end((relocInfo*) p); 1.735 +} 1.736 + 1.737 + 1.738 +void breakpoint_Relocation::unpack_data() { 1.739 + _bits = live_bits(); 1.740 + 1.741 + int targetlen = datalen() - 1 - instrlen(); 1.742 + jint target_bits = 0; 1.743 + if (targetlen == 0) target_bits = 0; 1.744 + else if (targetlen == 1) target_bits = *(data()+1); 1.745 + else if (targetlen == 2) target_bits = relocInfo::jint_from_data(data()+1); 1.746 + else { ShouldNotReachHere(); } 1.747 + 1.748 + _target = internal() ? address_from_scaled_offset(target_bits, addr()) 1.749 + : index_to_runtime_address (target_bits); 1.750 +} 1.751 + 1.752 + 1.753 +//// miscellaneous methods 1.754 +oop* oop_Relocation::oop_addr() { 1.755 + int n = _oop_index; 1.756 + if (n == 0) { 1.757 + // oop is stored in the code stream 1.758 + return (oop*) pd_address_in_code(); 1.759 + } else { 1.760 + // oop is stored in table at CodeBlob::oops_begin 1.761 + return code()->oop_addr_at(n); 1.762 + } 1.763 +} 1.764 + 1.765 + 1.766 +oop oop_Relocation::oop_value() { 1.767 + oop v = *oop_addr(); 1.768 + // clean inline caches store a special pseudo-null 1.769 + if (v == (oop)Universe::non_oop_word()) v = NULL; 1.770 + return v; 1.771 +} 1.772 + 1.773 + 1.774 +void oop_Relocation::fix_oop_relocation() { 1.775 + if (!oop_is_immediate()) { 1.776 + // get the oop from the pool, and re-insert it into the instruction: 1.777 + set_value(value()); 1.778 + } 1.779 +} 1.780 + 1.781 + 1.782 +RelocIterator virtual_call_Relocation::parse_ic(CodeBlob* &code, address &ic_call, address &first_oop, 1.783 + oop* &oop_addr, bool *is_optimized) { 1.784 + assert(ic_call != NULL, "ic_call address must be set"); 1.785 + assert(ic_call != NULL || first_oop != NULL, "must supply a non-null input"); 1.786 + if (code == NULL) { 1.787 + if (ic_call != NULL) { 1.788 + code = CodeCache::find_blob(ic_call); 1.789 + } else if (first_oop != NULL) { 1.790 + code = CodeCache::find_blob(first_oop); 1.791 + } 1.792 + assert(code != NULL, "address to parse must be in CodeBlob"); 1.793 + } 1.794 + assert(ic_call == NULL || code->contains(ic_call), "must be in CodeBlob"); 1.795 + assert(first_oop == NULL || code->contains(first_oop), "must be in CodeBlob"); 1.796 + 1.797 + address oop_limit = NULL; 1.798 + 1.799 + if (ic_call != NULL) { 1.800 + // search for the ic_call at the given address 1.801 + RelocIterator iter(code, ic_call, ic_call+1); 1.802 + bool ret = iter.next(); 1.803 + assert(ret == true, "relocInfo must exist at this address"); 1.804 + assert(iter.addr() == ic_call, "must find ic_call"); 1.805 + if (iter.type() == relocInfo::virtual_call_type) { 1.806 + virtual_call_Relocation* r = iter.virtual_call_reloc(); 1.807 + first_oop = r->first_oop(); 1.808 + oop_limit = r->oop_limit(); 1.809 + *is_optimized = false; 1.810 + } else { 1.811 + assert(iter.type() == relocInfo::opt_virtual_call_type, "must be a virtual call"); 1.812 + *is_optimized = true; 1.813 + oop_addr = NULL; 1.814 + first_oop = NULL; 1.815 + return iter; 1.816 + } 1.817 + } 1.818 + 1.819 + // search for the first_oop, to get its oop_addr 1.820 + RelocIterator all_oops(code, first_oop); 1.821 + RelocIterator iter = all_oops; 1.822 + iter.set_limit(first_oop+1); 1.823 + bool found_oop = false; 1.824 + while (iter.next()) { 1.825 + if (iter.type() == relocInfo::oop_type) { 1.826 + assert(iter.addr() == first_oop, "must find first_oop"); 1.827 + oop_addr = iter.oop_reloc()->oop_addr(); 1.828 + found_oop = true; 1.829 + break; 1.830 + } 1.831 + } 1.832 + assert(found_oop, "must find first_oop"); 1.833 + 1.834 + bool did_reset = false; 1.835 + while (ic_call == NULL) { 1.836 + // search forward for the ic_call matching the given first_oop 1.837 + while (iter.next()) { 1.838 + if (iter.type() == relocInfo::virtual_call_type) { 1.839 + virtual_call_Relocation* r = iter.virtual_call_reloc(); 1.840 + if (r->first_oop() == first_oop) { 1.841 + ic_call = r->addr(); 1.842 + oop_limit = r->oop_limit(); 1.843 + break; 1.844 + } 1.845 + } 1.846 + } 1.847 + guarantee(!did_reset, "cannot find ic_call"); 1.848 + iter = RelocIterator(code); // search the whole CodeBlob 1.849 + did_reset = true; 1.850 + } 1.851 + 1.852 + assert(oop_limit != NULL && first_oop != NULL && ic_call != NULL, ""); 1.853 + all_oops.set_limit(oop_limit); 1.854 + return all_oops; 1.855 +} 1.856 + 1.857 + 1.858 +address virtual_call_Relocation::first_oop() { 1.859 + assert(_first_oop != NULL && _first_oop < addr(), "must precede ic_call"); 1.860 + return _first_oop; 1.861 +} 1.862 + 1.863 + 1.864 +address virtual_call_Relocation::oop_limit() { 1.865 + if (_oop_limit == NULL) 1.866 + return addr() + NativeCall::instruction_size; 1.867 + else 1.868 + return _oop_limit; 1.869 +} 1.870 + 1.871 + 1.872 + 1.873 +void virtual_call_Relocation::clear_inline_cache() { 1.874 + // No stubs for ICs 1.875 + // Clean IC 1.876 + ResourceMark rm; 1.877 + CompiledIC* icache = CompiledIC_at(this); 1.878 + icache->set_to_clean(); 1.879 +} 1.880 + 1.881 + 1.882 +void opt_virtual_call_Relocation::clear_inline_cache() { 1.883 + // No stubs for ICs 1.884 + // Clean IC 1.885 + ResourceMark rm; 1.886 + CompiledIC* icache = CompiledIC_at(this); 1.887 + icache->set_to_clean(); 1.888 +} 1.889 + 1.890 + 1.891 +address opt_virtual_call_Relocation::static_stub() { 1.892 + // search for the static stub who points back to this static call 1.893 + address static_call_addr = addr(); 1.894 + RelocIterator iter(code()); 1.895 + while (iter.next()) { 1.896 + if (iter.type() == relocInfo::static_stub_type) { 1.897 + if (iter.static_stub_reloc()->static_call() == static_call_addr) { 1.898 + return iter.addr(); 1.899 + } 1.900 + } 1.901 + } 1.902 + return NULL; 1.903 +} 1.904 + 1.905 + 1.906 +void static_call_Relocation::clear_inline_cache() { 1.907 + // Safe call site info 1.908 + CompiledStaticCall* handler = compiledStaticCall_at(this); 1.909 + handler->set_to_clean(); 1.910 +} 1.911 + 1.912 + 1.913 +address static_call_Relocation::static_stub() { 1.914 + // search for the static stub who points back to this static call 1.915 + address static_call_addr = addr(); 1.916 + RelocIterator iter(code()); 1.917 + while (iter.next()) { 1.918 + if (iter.type() == relocInfo::static_stub_type) { 1.919 + if (iter.static_stub_reloc()->static_call() == static_call_addr) { 1.920 + return iter.addr(); 1.921 + } 1.922 + } 1.923 + } 1.924 + return NULL; 1.925 +} 1.926 + 1.927 + 1.928 +void static_stub_Relocation::clear_inline_cache() { 1.929 + // Call stub is only used when calling the interpreted code. 1.930 + // It does not really need to be cleared, except that we want to clean out the methodoop. 1.931 + CompiledStaticCall::set_stub_to_clean(this); 1.932 +} 1.933 + 1.934 + 1.935 +void external_word_Relocation::fix_relocation_after_move(const CodeBuffer* src, CodeBuffer* dest) { 1.936 + address target = _target; 1.937 + if (target == NULL) { 1.938 + // An absolute embedded reference to an external location, 1.939 + // which means there is nothing to fix here. 1.940 + return; 1.941 + } 1.942 + // Probably this reference is absolute, not relative, so the 1.943 + // following is probably a no-op. 1.944 + assert(src->section_index_of(target) == CodeBuffer::SECT_NONE, "sanity"); 1.945 + set_value(target); 1.946 +} 1.947 + 1.948 + 1.949 +address external_word_Relocation::target() { 1.950 + address target = _target; 1.951 + if (target == NULL) { 1.952 + target = pd_get_address_from_code(); 1.953 + } 1.954 + return target; 1.955 +} 1.956 + 1.957 + 1.958 +void internal_word_Relocation::fix_relocation_after_move(const CodeBuffer* src, CodeBuffer* dest) { 1.959 + address target = _target; 1.960 + if (target == NULL) { 1.961 + if (addr_in_const()) { 1.962 + target = new_addr_for(*(address*)addr(), src, dest); 1.963 + } else { 1.964 + target = new_addr_for(pd_get_address_from_code(), src, dest); 1.965 + } 1.966 + } 1.967 + set_value(target); 1.968 +} 1.969 + 1.970 + 1.971 +address internal_word_Relocation::target() { 1.972 + address target = _target; 1.973 + if (target == NULL) { 1.974 + target = pd_get_address_from_code(); 1.975 + } 1.976 + return target; 1.977 +} 1.978 + 1.979 + 1.980 +breakpoint_Relocation::breakpoint_Relocation(int kind, address target, bool internal) { 1.981 + bool active = false; 1.982 + bool enabled = (kind == initialization); 1.983 + bool removable = (kind != safepoint); 1.984 + bool settable = (target == NULL); 1.985 + 1.986 + int bits = kind; 1.987 + if (enabled) bits |= enabled_state; 1.988 + if (internal) bits |= internal_attr; 1.989 + if (removable) bits |= removable_attr; 1.990 + if (settable) bits |= settable_attr; 1.991 + 1.992 + _bits = bits | high_bit; 1.993 + _target = target; 1.994 + 1.995 + assert(this->kind() == kind, "kind encoded"); 1.996 + assert(this->enabled() == enabled, "enabled encoded"); 1.997 + assert(this->active() == active, "active encoded"); 1.998 + assert(this->internal() == internal, "internal encoded"); 1.999 + assert(this->removable() == removable, "removable encoded"); 1.1000 + assert(this->settable() == settable, "settable encoded"); 1.1001 +} 1.1002 + 1.1003 + 1.1004 +address breakpoint_Relocation::target() const { 1.1005 + return _target; 1.1006 +} 1.1007 + 1.1008 + 1.1009 +void breakpoint_Relocation::set_target(address x) { 1.1010 + assert(settable(), "must be settable"); 1.1011 + jint target_bits = 1.1012 + (jint)(internal() ? scaled_offset (x, addr()) 1.1013 + : runtime_address_to_index(x)); 1.1014 + short* p = &live_bits() + 1; 1.1015 + p = add_jint(p, target_bits); 1.1016 + assert(p == instrs(), "new target must fit"); 1.1017 + _target = x; 1.1018 +} 1.1019 + 1.1020 + 1.1021 +void breakpoint_Relocation::set_enabled(bool b) { 1.1022 + if (enabled() == b) return; 1.1023 + 1.1024 + if (b) { 1.1025 + set_bits(bits() | enabled_state); 1.1026 + } else { 1.1027 + set_active(false); // remove the actual breakpoint insn, if any 1.1028 + set_bits(bits() & ~enabled_state); 1.1029 + } 1.1030 +} 1.1031 + 1.1032 + 1.1033 +void breakpoint_Relocation::set_active(bool b) { 1.1034 + assert(!b || enabled(), "cannot activate a disabled breakpoint"); 1.1035 + 1.1036 + if (active() == b) return; 1.1037 + 1.1038 + // %%% should probably seize a lock here (might not be the right lock) 1.1039 + //MutexLockerEx ml_patch(Patching_lock, true); 1.1040 + //if (active() == b) return; // recheck state after locking 1.1041 + 1.1042 + if (b) { 1.1043 + set_bits(bits() | active_state); 1.1044 + if (instrlen() == 0) 1.1045 + fatal("breakpoints in original code must be undoable"); 1.1046 + pd_swap_in_breakpoint (addr(), instrs(), instrlen()); 1.1047 + } else { 1.1048 + set_bits(bits() & ~active_state); 1.1049 + pd_swap_out_breakpoint(addr(), instrs(), instrlen()); 1.1050 + } 1.1051 +} 1.1052 + 1.1053 + 1.1054 +//--------------------------------------------------------------------------------- 1.1055 +// Non-product code 1.1056 + 1.1057 +#ifndef PRODUCT 1.1058 + 1.1059 +static const char* reloc_type_string(relocInfo::relocType t) { 1.1060 + switch (t) { 1.1061 + #define EACH_CASE(name) \ 1.1062 + case relocInfo::name##_type: \ 1.1063 + return #name; 1.1064 + 1.1065 + APPLY_TO_RELOCATIONS(EACH_CASE); 1.1066 + #undef EACH_CASE 1.1067 + 1.1068 + case relocInfo::none: 1.1069 + return "none"; 1.1070 + case relocInfo::data_prefix_tag: 1.1071 + return "prefix"; 1.1072 + default: 1.1073 + return "UNKNOWN RELOC TYPE"; 1.1074 + } 1.1075 +} 1.1076 + 1.1077 + 1.1078 +void RelocIterator::print_current() { 1.1079 + if (!has_current()) { 1.1080 + tty->print_cr("(no relocs)"); 1.1081 + return; 1.1082 + } 1.1083 + tty->print("relocInfo@" INTPTR_FORMAT " [type=%d(%s) addr=" INTPTR_FORMAT, 1.1084 + _current, type(), reloc_type_string((relocInfo::relocType) type()), _addr); 1.1085 + if (current()->format() != 0) 1.1086 + tty->print(" format=%d", current()->format()); 1.1087 + if (datalen() == 1) { 1.1088 + tty->print(" data=%d", data()[0]); 1.1089 + } else if (datalen() > 0) { 1.1090 + tty->print(" data={"); 1.1091 + for (int i = 0; i < datalen(); i++) { 1.1092 + tty->print("%04x", data()[i] & 0xFFFF); 1.1093 + } 1.1094 + tty->print("}"); 1.1095 + } 1.1096 + tty->print("]"); 1.1097 + switch (type()) { 1.1098 + case relocInfo::oop_type: 1.1099 + { 1.1100 + oop_Relocation* r = oop_reloc(); 1.1101 + oop* oop_addr = NULL; 1.1102 + oop raw_oop = NULL; 1.1103 + oop oop_value = NULL; 1.1104 + if (code() != NULL || r->oop_is_immediate()) { 1.1105 + oop_addr = r->oop_addr(); 1.1106 + raw_oop = *oop_addr; 1.1107 + oop_value = r->oop_value(); 1.1108 + } 1.1109 + tty->print(" | [oop_addr=" INTPTR_FORMAT " *=" INTPTR_FORMAT " offset=%d]", 1.1110 + oop_addr, (address)raw_oop, r->offset()); 1.1111 + // Do not print the oop by default--we want this routine to 1.1112 + // work even during GC or other inconvenient times. 1.1113 + if (WizardMode && oop_value != NULL) { 1.1114 + tty->print("oop_value=" INTPTR_FORMAT ": ", (address)oop_value); 1.1115 + oop_value->print_value_on(tty); 1.1116 + } 1.1117 + break; 1.1118 + } 1.1119 + case relocInfo::external_word_type: 1.1120 + case relocInfo::internal_word_type: 1.1121 + case relocInfo::section_word_type: 1.1122 + { 1.1123 + DataRelocation* r = (DataRelocation*) reloc(); 1.1124 + tty->print(" | [target=" INTPTR_FORMAT "]", r->value()); //value==target 1.1125 + break; 1.1126 + } 1.1127 + case relocInfo::static_call_type: 1.1128 + case relocInfo::runtime_call_type: 1.1129 + { 1.1130 + CallRelocation* r = (CallRelocation*) reloc(); 1.1131 + tty->print(" | [destination=" INTPTR_FORMAT "]", r->destination()); 1.1132 + break; 1.1133 + } 1.1134 + case relocInfo::virtual_call_type: 1.1135 + { 1.1136 + virtual_call_Relocation* r = (virtual_call_Relocation*) reloc(); 1.1137 + tty->print(" | [destination=" INTPTR_FORMAT " first_oop=" INTPTR_FORMAT " oop_limit=" INTPTR_FORMAT "]", 1.1138 + r->destination(), r->first_oop(), r->oop_limit()); 1.1139 + break; 1.1140 + } 1.1141 + case relocInfo::static_stub_type: 1.1142 + { 1.1143 + static_stub_Relocation* r = (static_stub_Relocation*) reloc(); 1.1144 + tty->print(" | [static_call=" INTPTR_FORMAT "]", r->static_call()); 1.1145 + break; 1.1146 + } 1.1147 + } 1.1148 + tty->cr(); 1.1149 +} 1.1150 + 1.1151 + 1.1152 +void RelocIterator::print() { 1.1153 + RelocIterator save_this = (*this); 1.1154 + relocInfo* scan = _current; 1.1155 + if (!has_current()) scan += 1; // nothing to scan here! 1.1156 + 1.1157 + bool skip_next = has_current(); 1.1158 + bool got_next; 1.1159 + while (true) { 1.1160 + got_next = (skip_next || next()); 1.1161 + skip_next = false; 1.1162 + 1.1163 + tty->print(" @" INTPTR_FORMAT ": ", scan); 1.1164 + relocInfo* newscan = _current+1; 1.1165 + if (!has_current()) newscan -= 1; // nothing to scan here! 1.1166 + while (scan < newscan) { 1.1167 + tty->print("%04x", *(short*)scan & 0xFFFF); 1.1168 + scan++; 1.1169 + } 1.1170 + tty->cr(); 1.1171 + 1.1172 + if (!got_next) break; 1.1173 + print_current(); 1.1174 + } 1.1175 + 1.1176 + (*this) = save_this; 1.1177 +} 1.1178 + 1.1179 +// For the debugger: 1.1180 +extern "C" 1.1181 +void print_blob_locs(CodeBlob* cb) { 1.1182 + cb->print(); 1.1183 + RelocIterator iter(cb); 1.1184 + iter.print(); 1.1185 +} 1.1186 +extern "C" 1.1187 +void print_buf_locs(CodeBuffer* cb) { 1.1188 + FlagSetting fs(PrintRelocations, true); 1.1189 + cb->print(); 1.1190 +} 1.1191 +#endif // !PRODUCT