src/share/vm/code/relocInfo.cpp

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

mercurial