Path: blob/aarch64-shenandoah-jdk8u272-b10/hotspot/src/share/vm/code/relocInfo.cpp
32285 views
/*1* Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 2 along with this work; if not, write to the Free Software Foundation,16* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.17*18* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*22*/2324#include "precompiled.hpp"25#include "code/codeCache.hpp"26#include "code/compiledIC.hpp"27#include "code/nmethod.hpp"28#include "code/relocInfo.hpp"29#include "memory/resourceArea.hpp"30#include "runtime/stubCodeGenerator.hpp"31#include "utilities/copy.hpp"3233PRAGMA_FORMAT_MUTE_WARNINGS_FOR_GCC3435const RelocationHolder RelocationHolder::none; // its type is relocInfo::none363738// Implementation of relocInfo3940#ifdef ASSERT41relocInfo::relocInfo(relocType t, int off, int f) {42assert(t != data_prefix_tag, "cannot build a prefix this way");43assert((t & type_mask) == t, "wrong type");44assert((f & format_mask) == f, "wrong format");45assert(off >= 0 && off < offset_limit(), "offset out off bounds");46assert((off & (offset_unit-1)) == 0, "misaligned offset");47(*this) = relocInfo(t, RAW_BITS, off, f);48}49#endif5051void relocInfo::initialize(CodeSection* dest, Relocation* reloc) {52relocInfo* data = this+1; // here's where the data might go53dest->set_locs_end(data); // sync end: the next call may read dest.locs_end54reloc->pack_data_to(dest); // maybe write data into locs, advancing locs_end55relocInfo* data_limit = dest->locs_end();56if (data_limit > data) {57relocInfo suffix = (*this);58data_limit = this->finish_prefix((short*) data_limit);59// Finish up with the suffix. (Hack note: pack_data_to might edit this.)60*data_limit = suffix;61dest->set_locs_end(data_limit+1);62}63}6465relocInfo* relocInfo::finish_prefix(short* prefix_limit) {66assert(sizeof(relocInfo) == sizeof(short), "change this code");67short* p = (short*)(this+1);68assert(prefix_limit >= p, "must be a valid span of data");69int plen = prefix_limit - p;70if (plen == 0) {71debug_only(_value = 0xFFFF);72return this; // no data: remove self completely73}74if (plen == 1 && fits_into_immediate(p[0])) {75(*this) = immediate_relocInfo(p[0]); // move data inside self76return this+1;77}78// cannot compact, so just update the count and return the limit pointer79(*this) = prefix_relocInfo(plen); // write new datalen80assert(data() + datalen() == prefix_limit, "pointers must line up");81return (relocInfo*)prefix_limit;82}838485void relocInfo::set_type(relocType t) {86int old_offset = addr_offset();87int old_format = format();88(*this) = relocInfo(t, old_offset, old_format);89assert(type()==(int)t, "sanity check");90assert(addr_offset()==old_offset, "sanity check");91assert(format()==old_format, "sanity check");92}939495void relocInfo::set_format(int f) {96int old_offset = addr_offset();97assert((f & format_mask) == f, "wrong format");98_value = (_value & ~(format_mask << offset_width)) | (f << offset_width);99assert(addr_offset()==old_offset, "sanity check");100}101102103void relocInfo::change_reloc_info_for_address(RelocIterator *itr, address pc, relocType old_type, relocType new_type) {104bool found = false;105while (itr->next() && !found) {106if (itr->addr() == pc) {107assert(itr->type()==old_type, "wrong relocInfo type found");108itr->current()->set_type(new_type);109found=true;110}111}112assert(found, "no relocInfo found for pc");113}114115116void relocInfo::remove_reloc_info_for_address(RelocIterator *itr, address pc, relocType old_type) {117change_reloc_info_for_address(itr, pc, old_type, none);118}119120121// ----------------------------------------------------------------------------------------------------122// Implementation of RelocIterator123124void RelocIterator::initialize(nmethod* nm, address begin, address limit) {125initialize_misc();126127if (nm == NULL && begin != NULL) {128// allow nmethod to be deduced from beginning address129CodeBlob* cb = CodeCache::find_blob(begin);130nm = (cb != NULL) ? cb->as_nmethod_or_null() : NULL;131}132guarantee(nm != NULL, "must be able to deduce nmethod from other arguments");133134_code = nm;135_current = nm->relocation_begin() - 1;136_end = nm->relocation_end();137_addr = nm->content_begin();138139// Initialize code sections.140_section_start[CodeBuffer::SECT_CONSTS] = nm->consts_begin();141_section_start[CodeBuffer::SECT_INSTS ] = nm->insts_begin() ;142_section_start[CodeBuffer::SECT_STUBS ] = nm->stub_begin() ;143144_section_end [CodeBuffer::SECT_CONSTS] = nm->consts_end() ;145_section_end [CodeBuffer::SECT_INSTS ] = nm->insts_end() ;146_section_end [CodeBuffer::SECT_STUBS ] = nm->stub_end() ;147148assert(!has_current(), "just checking");149assert(begin == NULL || begin >= nm->code_begin(), "in bounds");150assert(limit == NULL || limit <= nm->code_end(), "in bounds");151set_limits(begin, limit);152}153154155RelocIterator::RelocIterator(CodeSection* cs, address begin, address limit) {156initialize_misc();157158_current = cs->locs_start()-1;159_end = cs->locs_end();160_addr = cs->start();161_code = NULL; // Not cb->blob();162163CodeBuffer* cb = cs->outer();164assert((int) SECT_LIMIT == CodeBuffer::SECT_LIMIT, "my copy must be equal");165for (int n = (int) CodeBuffer::SECT_FIRST; n < (int) CodeBuffer::SECT_LIMIT; n++) {166CodeSection* cs = cb->code_section(n);167_section_start[n] = cs->start();168_section_end [n] = cs->end();169}170171assert(!has_current(), "just checking");172173assert(begin == NULL || begin >= cs->start(), "in bounds");174assert(limit == NULL || limit <= cs->end(), "in bounds");175set_limits(begin, limit);176}177178179enum { indexCardSize = 128 };180struct RelocIndexEntry {181jint addr_offset; // offset from header_end of an addr()182jint reloc_offset; // offset from header_end of a relocInfo (prefix)183};184185186bool RelocIterator::addr_in_const() const {187const int n = CodeBuffer::SECT_CONSTS;188return section_start(n) <= addr() && addr() < section_end(n);189}190191192static inline int num_cards(int code_size) {193return (code_size-1) / indexCardSize;194}195196197int RelocIterator::locs_and_index_size(int code_size, int locs_size) {198if (!UseRelocIndex) return locs_size; // no index199code_size = round_to(code_size, oopSize);200locs_size = round_to(locs_size, oopSize);201int index_size = num_cards(code_size) * sizeof(RelocIndexEntry);202// format of indexed relocs:203// relocation_begin: relocInfo ...204// index: (addr,reloc#) ...205// indexSize :relocation_end206return locs_size + index_size + BytesPerInt;207}208209210void RelocIterator::create_index(relocInfo* dest_begin, int dest_count, relocInfo* dest_end) {211address relocation_begin = (address)dest_begin;212address relocation_end = (address)dest_end;213int total_size = relocation_end - relocation_begin;214int locs_size = dest_count * sizeof(relocInfo);215if (!UseRelocIndex) {216Copy::fill_to_bytes(relocation_begin + locs_size, total_size-locs_size, 0);217return;218}219int index_size = total_size - locs_size - BytesPerInt; // find out how much space is left220int ncards = index_size / sizeof(RelocIndexEntry);221assert(total_size == locs_size + index_size + BytesPerInt, "checkin'");222assert(index_size >= 0 && index_size % sizeof(RelocIndexEntry) == 0, "checkin'");223jint* index_size_addr = (jint*)relocation_end - 1;224225assert(sizeof(jint) == BytesPerInt, "change this code");226227*index_size_addr = index_size;228if (index_size != 0) {229assert(index_size > 0, "checkin'");230231RelocIndexEntry* index = (RelocIndexEntry *)(relocation_begin + locs_size);232assert(index == (RelocIndexEntry*)index_size_addr - ncards, "checkin'");233234// walk over the relocations, and fill in index entries as we go235RelocIterator iter;236const address initial_addr = NULL;237relocInfo* const initial_current = dest_begin - 1; // biased by -1 like elsewhere238239iter._code = NULL;240iter._addr = initial_addr;241iter._limit = (address)(intptr_t)(ncards * indexCardSize);242iter._current = initial_current;243iter._end = dest_begin + dest_count;244245int i = 0;246address next_card_addr = (address)indexCardSize;247int addr_offset = 0;248int reloc_offset = 0;249while (true) {250// Checkpoint the iterator before advancing it.251addr_offset = iter._addr - initial_addr;252reloc_offset = iter._current - initial_current;253if (!iter.next()) break;254while (iter.addr() >= next_card_addr) {255index[i].addr_offset = addr_offset;256index[i].reloc_offset = reloc_offset;257i++;258next_card_addr += indexCardSize;259}260}261while (i < ncards) {262index[i].addr_offset = addr_offset;263index[i].reloc_offset = reloc_offset;264i++;265}266}267}268269270void RelocIterator::set_limits(address begin, address limit) {271int index_size = 0;272if (UseRelocIndex && _code != NULL) {273index_size = ((jint*)_end)[-1];274_end = (relocInfo*)( (address)_end - index_size - BytesPerInt );275}276277_limit = limit;278279// the limit affects this next stuff:280if (begin != NULL) {281#ifdef ASSERT282// In ASSERT mode we do not actually use the index, but simply283// check that its contents would have led us to the right answer.284address addrCheck = _addr;285relocInfo* infoCheck = _current;286#endif // ASSERT287if (index_size > 0) {288// skip ahead289RelocIndexEntry* index = (RelocIndexEntry*)_end;290RelocIndexEntry* index_limit = (RelocIndexEntry*)((address)index + index_size);291assert(_addr == _code->code_begin(), "_addr must be unadjusted");292int card = (begin - _addr) / indexCardSize;293if (card > 0) {294if (index+card-1 < index_limit) index += card-1;295else index = index_limit - 1;296#ifdef ASSERT297addrCheck = _addr + index->addr_offset;298infoCheck = _current + index->reloc_offset;299#else300// Advance the iterator immediately to the last valid state301// for the previous card. Calling "next" will then advance302// it to the first item on the required card.303_addr += index->addr_offset;304_current += index->reloc_offset;305#endif // ASSERT306}307}308309relocInfo* backup;310address backup_addr;311while (true) {312backup = _current;313backup_addr = _addr;314#ifdef ASSERT315if (backup == infoCheck) {316assert(backup_addr == addrCheck, "must match"); addrCheck = NULL; infoCheck = NULL;317} else {318assert(addrCheck == NULL || backup_addr <= addrCheck, "must not pass addrCheck");319}320#endif // ASSERT321if (!next() || addr() >= begin) break;322}323assert(addrCheck == NULL || addrCheck == backup_addr, "must have matched addrCheck");324assert(infoCheck == NULL || infoCheck == backup, "must have matched infoCheck");325// At this point, either we are at the first matching record,326// or else there is no such record, and !has_current().327// In either case, revert to the immediatly preceding state.328_current = backup;329_addr = backup_addr;330set_has_current(false);331}332}333334335void RelocIterator::set_limit(address limit) {336address code_end = (address)code() + code()->size();337assert(limit == NULL || limit <= code_end, "in bounds");338_limit = limit;339}340341// All the strange bit-encodings are in here.342// The idea is to encode relocation data which are small integers343// very efficiently (a single extra halfword). Larger chunks of344// relocation data need a halfword header to hold their size.345void RelocIterator::advance_over_prefix() {346if (_current->is_datalen()) {347_data = (short*) _current->data();348_datalen = _current->datalen();349_current += _datalen + 1; // skip the embedded data & header350} else {351_databuf = _current->immediate();352_data = &_databuf;353_datalen = 1;354_current++; // skip the header355}356// The client will see the following relocInfo, whatever that is.357// It is the reloc to which the preceding data applies.358}359360361void RelocIterator::initialize_misc() {362set_has_current(false);363for (int i = (int) CodeBuffer::SECT_FIRST; i < (int) CodeBuffer::SECT_LIMIT; i++) {364_section_start[i] = NULL; // these will be lazily computed, if needed365_section_end [i] = NULL;366}367}368369370Relocation* RelocIterator::reloc() {371// (take the "switch" out-of-line)372relocInfo::relocType t = type();373if (false) {}374#define EACH_TYPE(name) \375else if (t == relocInfo::name##_type) { \376return name##_reloc(); \377}378APPLY_TO_RELOCATIONS(EACH_TYPE);379#undef EACH_TYPE380assert(t == relocInfo::none, "must be padding");381return new(_rh) Relocation();382}383384385//////// Methods for flyweight Relocation types386387388RelocationHolder RelocationHolder::plus(int offset) const {389if (offset != 0) {390switch (type()) {391case relocInfo::none:392break;393case relocInfo::oop_type:394{395oop_Relocation* r = (oop_Relocation*)reloc();396return oop_Relocation::spec(r->oop_index(), r->offset() + offset);397}398case relocInfo::metadata_type:399{400metadata_Relocation* r = (metadata_Relocation*)reloc();401return metadata_Relocation::spec(r->metadata_index(), r->offset() + offset);402}403default:404ShouldNotReachHere();405}406}407return (*this);408}409410411void Relocation::guarantee_size() {412guarantee(false, "Make _relocbuf bigger!");413}414415// some relocations can compute their own values416address Relocation::value() {417ShouldNotReachHere();418return NULL;419}420421422void Relocation::set_value(address x) {423ShouldNotReachHere();424}425426427RelocationHolder Relocation::spec_simple(relocInfo::relocType rtype) {428if (rtype == relocInfo::none) return RelocationHolder::none;429relocInfo ri = relocInfo(rtype, 0);430RelocIterator itr;431itr.set_current(ri);432itr.reloc();433return itr._rh;434}435436int32_t Relocation::runtime_address_to_index(address runtime_address) {437assert(!is_reloc_index((intptr_t)runtime_address), "must not look like an index");438439if (runtime_address == NULL) return 0;440441StubCodeDesc* p = StubCodeDesc::desc_for(runtime_address);442if (p != NULL && p->begin() == runtime_address) {443assert(is_reloc_index(p->index()), "there must not be too many stubs");444return (int32_t)p->index();445} else {446// Known "miscellaneous" non-stub pointers:447// os::get_polling_page(), SafepointSynchronize::address_of_state()448if (PrintRelocations) {449tty->print_cr("random unregistered address in relocInfo: " INTPTR_FORMAT, runtime_address);450}451#ifndef _LP64452return (int32_t) (intptr_t)runtime_address;453#else454// didn't fit return non-index455return -1;456#endif /* _LP64 */457}458}459460461address Relocation::index_to_runtime_address(int32_t index) {462if (index == 0) return NULL;463464if (is_reloc_index(index)) {465StubCodeDesc* p = StubCodeDesc::desc_for_index(index);466assert(p != NULL, "there must be a stub for this index");467return p->begin();468} else {469#ifndef _LP64470// this only works on 32bit machines471return (address) ((intptr_t) index);472#else473fatal("Relocation::index_to_runtime_address, int32_t not pointer sized");474return NULL;475#endif /* _LP64 */476}477}478479address Relocation::old_addr_for(address newa,480const CodeBuffer* src, CodeBuffer* dest) {481int sect = dest->section_index_of(newa);482guarantee(sect != CodeBuffer::SECT_NONE, "lost track of this address");483address ostart = src->code_section(sect)->start();484address nstart = dest->code_section(sect)->start();485return ostart + (newa - nstart);486}487488address Relocation::new_addr_for(address olda,489const CodeBuffer* src, CodeBuffer* dest) {490debug_only(const CodeBuffer* src0 = src);491int sect = CodeBuffer::SECT_NONE;492// Look for olda in the source buffer, and all previous incarnations493// if the source buffer has been expanded.494for (; src != NULL; src = src->before_expand()) {495sect = src->section_index_of(olda);496if (sect != CodeBuffer::SECT_NONE) break;497}498guarantee(sect != CodeBuffer::SECT_NONE, "lost track of this address");499address ostart = src->code_section(sect)->start();500address nstart = dest->code_section(sect)->start();501return nstart + (olda - ostart);502}503504void Relocation::normalize_address(address& addr, const CodeSection* dest, bool allow_other_sections) {505address addr0 = addr;506if (addr0 == NULL || dest->allocates2(addr0)) return;507CodeBuffer* cb = dest->outer();508addr = new_addr_for(addr0, cb, cb);509assert(allow_other_sections || dest->contains2(addr),510"addr must be in required section");511}512513514void CallRelocation::set_destination(address x) {515pd_set_call_destination(x);516}517518void CallRelocation::fix_relocation_after_move(const CodeBuffer* src, CodeBuffer* dest) {519// Usually a self-relative reference to an external routine.520// On some platforms, the reference is absolute (not self-relative).521// The enhanced use of pd_call_destination sorts this all out.522address orig_addr = old_addr_for(addr(), src, dest);523address callee = pd_call_destination(orig_addr);524// Reassert the callee address, this time in the new copy of the code.525pd_set_call_destination(callee);526}527528529//// pack/unpack methods530531void oop_Relocation::pack_data_to(CodeSection* dest) {532short* p = (short*) dest->locs_end();533p = pack_2_ints_to(p, _oop_index, _offset);534dest->set_locs_end((relocInfo*) p);535}536537538void oop_Relocation::unpack_data() {539unpack_2_ints(_oop_index, _offset);540}541542void metadata_Relocation::pack_data_to(CodeSection* dest) {543short* p = (short*) dest->locs_end();544p = pack_2_ints_to(p, _metadata_index, _offset);545dest->set_locs_end((relocInfo*) p);546}547548549void metadata_Relocation::unpack_data() {550unpack_2_ints(_metadata_index, _offset);551}552553554void virtual_call_Relocation::pack_data_to(CodeSection* dest) {555short* p = (short*) dest->locs_end();556address point = dest->locs_point();557558normalize_address(_cached_value, dest);559jint x0 = scaled_offset_null_special(_cached_value, point);560p = pack_1_int_to(p, x0);561dest->set_locs_end((relocInfo*) p);562}563564565void virtual_call_Relocation::unpack_data() {566jint x0 = unpack_1_int();567address point = addr();568_cached_value = x0==0? NULL: address_from_scaled_offset(x0, point);569}570571572void static_stub_Relocation::pack_data_to(CodeSection* dest) {573short* p = (short*) dest->locs_end();574CodeSection* insts = dest->outer()->insts();575normalize_address(_static_call, insts);576p = pack_1_int_to(p, scaled_offset(_static_call, insts->start()));577dest->set_locs_end((relocInfo*) p);578}579580void static_stub_Relocation::unpack_data() {581address base = binding()->section_start(CodeBuffer::SECT_INSTS);582_static_call = address_from_scaled_offset(unpack_1_int(), base);583}584585void trampoline_stub_Relocation::pack_data_to(CodeSection* dest ) {586short* p = (short*) dest->locs_end();587CodeSection* insts = dest->outer()->insts();588normalize_address(_owner, insts);589p = pack_1_int_to(p, scaled_offset(_owner, insts->start()));590dest->set_locs_end((relocInfo*) p);591}592593void trampoline_stub_Relocation::unpack_data() {594address base = binding()->section_start(CodeBuffer::SECT_INSTS);595_owner = address_from_scaled_offset(unpack_1_int(), base);596}597598void external_word_Relocation::pack_data_to(CodeSection* dest) {599short* p = (short*) dest->locs_end();600int32_t index = runtime_address_to_index(_target);601#ifndef _LP64602p = pack_1_int_to(p, index);603#else604if (is_reloc_index(index)) {605p = pack_2_ints_to(p, index, 0);606} else {607jlong t = (jlong) _target;608int32_t lo = low(t);609int32_t hi = high(t);610p = pack_2_ints_to(p, lo, hi);611DEBUG_ONLY(jlong t1 = jlong_from(hi, lo));612assert(!is_reloc_index(t1) && (address) t1 == _target, "not symmetric");613}614#endif /* _LP64 */615dest->set_locs_end((relocInfo*) p);616}617618619void external_word_Relocation::unpack_data() {620#ifndef _LP64621_target = index_to_runtime_address(unpack_1_int());622#else623int32_t lo, hi;624unpack_2_ints(lo, hi);625jlong t = jlong_from(hi, lo);;626if (is_reloc_index(t)) {627_target = index_to_runtime_address(t);628} else {629_target = (address) t;630}631#endif /* _LP64 */632}633634635void internal_word_Relocation::pack_data_to(CodeSection* dest) {636short* p = (short*) dest->locs_end();637normalize_address(_target, dest, true);638639// Check whether my target address is valid within this section.640// If not, strengthen the relocation type to point to another section.641int sindex = _section;642if (sindex == CodeBuffer::SECT_NONE && _target != NULL643&& (!dest->allocates(_target) || _target == dest->locs_point())) {644sindex = dest->outer()->section_index_of(_target);645guarantee(sindex != CodeBuffer::SECT_NONE, "must belong somewhere");646relocInfo* base = dest->locs_end() - 1;647assert(base->type() == this->type(), "sanity");648// Change the written type, to be section_word_type instead.649base->set_type(relocInfo::section_word_type);650}651652// Note: An internal_word relocation cannot refer to its own instruction,653// because we reserve "0" to mean that the pointer itself is embedded654// in the code stream. We use a section_word relocation for such cases.655656if (sindex == CodeBuffer::SECT_NONE) {657assert(type() == relocInfo::internal_word_type, "must be base class");658guarantee(_target == NULL || dest->allocates2(_target), "must be within the given code section");659jint x0 = scaled_offset_null_special(_target, dest->locs_point());660assert(!(x0 == 0 && _target != NULL), "correct encoding of null target");661p = pack_1_int_to(p, x0);662} else {663assert(_target != NULL, "sanity");664CodeSection* sect = dest->outer()->code_section(sindex);665guarantee(sect->allocates2(_target), "must be in correct section");666address base = sect->start();667jint offset = scaled_offset(_target, base);668assert((uint)sindex < (uint)CodeBuffer::SECT_LIMIT, "sanity");669assert(CodeBuffer::SECT_LIMIT <= (1 << section_width), "section_width++");670p = pack_1_int_to(p, (offset << section_width) | sindex);671}672673dest->set_locs_end((relocInfo*) p);674}675676677void internal_word_Relocation::unpack_data() {678jint x0 = unpack_1_int();679_target = x0==0? NULL: address_from_scaled_offset(x0, addr());680_section = CodeBuffer::SECT_NONE;681}682683684void section_word_Relocation::unpack_data() {685jint x = unpack_1_int();686jint offset = (x >> section_width);687int sindex = (x & ((1<<section_width)-1));688address base = binding()->section_start(sindex);689690_section = sindex;691_target = address_from_scaled_offset(offset, base);692}693694//// miscellaneous methods695oop* oop_Relocation::oop_addr() {696int n = _oop_index;697if (n == 0) {698// oop is stored in the code stream699return (oop*) pd_address_in_code();700} else {701// oop is stored in table at nmethod::oops_begin702return code()->oop_addr_at(n);703}704}705706707oop oop_Relocation::oop_value() {708oop v = *oop_addr();709// clean inline caches store a special pseudo-null710if (v == (oop)Universe::non_oop_word()) v = NULL;711return v;712}713714715void oop_Relocation::fix_oop_relocation() {716if (!oop_is_immediate()) {717// get the oop from the pool, and re-insert it into the instruction:718set_value(value());719}720}721722723void oop_Relocation::verify_oop_relocation() {724if (!oop_is_immediate()) {725// get the oop from the pool, and re-insert it into the instruction:726verify_value(value());727}728}729730// meta data versions731Metadata** metadata_Relocation::metadata_addr() {732int n = _metadata_index;733if (n == 0) {734// metadata is stored in the code stream735return (Metadata**) pd_address_in_code();736} else {737// metadata is stored in table at nmethod::metadatas_begin738return code()->metadata_addr_at(n);739}740}741742743Metadata* metadata_Relocation::metadata_value() {744Metadata* v = *metadata_addr();745// clean inline caches store a special pseudo-null746if (v == (Metadata*)Universe::non_oop_word()) v = NULL;747return v;748}749750751void metadata_Relocation::fix_metadata_relocation() {752if (!metadata_is_immediate()) {753// get the metadata from the pool, and re-insert it into the instruction:754pd_fix_value(value());755}756}757758759void metadata_Relocation::verify_metadata_relocation() {760if (!metadata_is_immediate()) {761// get the metadata from the pool, and re-insert it into the instruction:762verify_value(value());763}764}765766address virtual_call_Relocation::cached_value() {767assert(_cached_value != NULL && _cached_value < addr(), "must precede ic_call");768return _cached_value;769}770771772void virtual_call_Relocation::clear_inline_cache() {773// No stubs for ICs774// Clean IC775ResourceMark rm;776CompiledIC* icache = CompiledIC_at(this);777icache->set_to_clean();778}779780781void opt_virtual_call_Relocation::clear_inline_cache() {782// No stubs for ICs783// Clean IC784ResourceMark rm;785CompiledIC* icache = CompiledIC_at(this);786icache->set_to_clean();787}788789790address opt_virtual_call_Relocation::static_stub() {791// search for the static stub who points back to this static call792address static_call_addr = addr();793RelocIterator iter(code());794while (iter.next()) {795if (iter.type() == relocInfo::static_stub_type) {796if (iter.static_stub_reloc()->static_call() == static_call_addr) {797return iter.addr();798}799}800}801return NULL;802}803804805void static_call_Relocation::clear_inline_cache() {806// Safe call site info807CompiledStaticCall* handler = compiledStaticCall_at(this);808handler->set_to_clean();809}810811812address static_call_Relocation::static_stub() {813// search for the static stub who points back to this static call814address static_call_addr = addr();815RelocIterator iter(code());816while (iter.next()) {817if (iter.type() == relocInfo::static_stub_type) {818if (iter.static_stub_reloc()->static_call() == static_call_addr) {819return iter.addr();820}821}822}823return NULL;824}825826// Finds the trampoline address for a call. If no trampoline stub is827// found NULL is returned which can be handled by the caller.828address trampoline_stub_Relocation::get_trampoline_for(address call, nmethod* code) {829// There are no relocations available when the code gets relocated830// because of CodeBuffer expansion.831if (code->relocation_size() == 0)832return NULL;833834RelocIterator iter(code, call);835while (iter.next()) {836if (iter.type() == relocInfo::trampoline_stub_type) {837if (iter.trampoline_stub_reloc()->owner() == call) {838return iter.addr();839}840}841}842843return NULL;844}845846void static_stub_Relocation::clear_inline_cache() {847// Call stub is only used when calling the interpreted code.848// It does not really need to be cleared, except that we want to clean out the methodoop.849CompiledStaticCall::set_stub_to_clean(this);850}851852853void external_word_Relocation::fix_relocation_after_move(const CodeBuffer* src, CodeBuffer* dest) {854address target = _target;855if (target == NULL) {856// An absolute embedded reference to an external location,857// which means there is nothing to fix here.858return;859}860// Probably this reference is absolute, not relative, so the861// following is probably a no-op.862assert(src->section_index_of(target) == CodeBuffer::SECT_NONE, "sanity");863set_value(target);864}865866867address external_word_Relocation::target() {868address target = _target;869if (target == NULL) {870target = pd_get_address_from_code();871}872return target;873}874875876void internal_word_Relocation::fix_relocation_after_move(const CodeBuffer* src, CodeBuffer* dest) {877address target = _target;878if (target == NULL) {879target = new_addr_for(this->target(), src, dest);880}881set_value(target);882}883884885address internal_word_Relocation::target() {886address target = _target;887if (target == NULL) {888if (addr_in_const()) {889target = *(address*)addr();890} else {891target = pd_get_address_from_code();892}893}894return target;895}896897//---------------------------------------------------------------------------------898// Non-product code899900#ifndef PRODUCT901902static const char* reloc_type_string(relocInfo::relocType t) {903switch (t) {904#define EACH_CASE(name) \905case relocInfo::name##_type: \906return #name;907908APPLY_TO_RELOCATIONS(EACH_CASE);909#undef EACH_CASE910911case relocInfo::none:912return "none";913case relocInfo::data_prefix_tag:914return "prefix";915default:916return "UNKNOWN RELOC TYPE";917}918}919920921void RelocIterator::print_current() {922if (!has_current()) {923tty->print_cr("(no relocs)");924return;925}926tty->print("relocInfo@" INTPTR_FORMAT " [type=%d(%s) addr=" INTPTR_FORMAT " offset=%d",927_current, type(), reloc_type_string((relocInfo::relocType) type()), _addr, _current->addr_offset());928if (current()->format() != 0)929tty->print(" format=%d", current()->format());930if (datalen() == 1) {931tty->print(" data=%d", data()[0]);932} else if (datalen() > 0) {933tty->print(" data={");934for (int i = 0; i < datalen(); i++) {935tty->print("%04x", data()[i] & 0xFFFF);936}937tty->print("}");938}939tty->print("]");940switch (type()) {941case relocInfo::oop_type:942{943oop_Relocation* r = oop_reloc();944oop* oop_addr = NULL;945oop raw_oop = NULL;946oop oop_value = NULL;947if (code() != NULL || r->oop_is_immediate()) {948oop_addr = r->oop_addr();949raw_oop = *oop_addr;950oop_value = r->oop_value();951}952tty->print(" | [oop_addr=" INTPTR_FORMAT " *=" INTPTR_FORMAT " offset=%d]",953oop_addr, (address)raw_oop, r->offset());954// Do not print the oop by default--we want this routine to955// work even during GC or other inconvenient times.956if (WizardMode && oop_value != NULL) {957tty->print("oop_value=" INTPTR_FORMAT ": ", (address)oop_value);958oop_value->print_value_on(tty);959}960break;961}962case relocInfo::metadata_type:963{964metadata_Relocation* r = metadata_reloc();965Metadata** metadata_addr = NULL;966Metadata* raw_metadata = NULL;967Metadata* metadata_value = NULL;968if (code() != NULL || r->metadata_is_immediate()) {969metadata_addr = r->metadata_addr();970raw_metadata = *metadata_addr;971metadata_value = r->metadata_value();972}973tty->print(" | [metadata_addr=" INTPTR_FORMAT " *=" INTPTR_FORMAT " offset=%d]",974metadata_addr, (address)raw_metadata, r->offset());975if (metadata_value != NULL) {976tty->print("metadata_value=" INTPTR_FORMAT ": ", (address)metadata_value);977metadata_value->print_value_on(tty);978}979break;980}981case relocInfo::external_word_type:982case relocInfo::internal_word_type:983case relocInfo::section_word_type:984{985DataRelocation* r = (DataRelocation*) reloc();986tty->print(" | [target=" INTPTR_FORMAT "]", r->value()); //value==target987break;988}989case relocInfo::static_call_type:990case relocInfo::runtime_call_type:991{992CallRelocation* r = (CallRelocation*) reloc();993tty->print(" | [destination=" INTPTR_FORMAT "]", r->destination());994break;995}996case relocInfo::virtual_call_type:997{998virtual_call_Relocation* r = (virtual_call_Relocation*) reloc();999tty->print(" | [destination=" INTPTR_FORMAT " cached_value=" INTPTR_FORMAT "]",1000r->destination(), r->cached_value());1001break;1002}1003case relocInfo::static_stub_type:1004{1005static_stub_Relocation* r = (static_stub_Relocation*) reloc();1006tty->print(" | [static_call=" INTPTR_FORMAT "]", r->static_call());1007break;1008}1009case relocInfo::trampoline_stub_type:1010{1011trampoline_stub_Relocation* r = (trampoline_stub_Relocation*) reloc();1012tty->print(" | [trampoline owner=" INTPTR_FORMAT "]", r->owner());1013break;1014}1015}1016tty->cr();1017}101810191020void RelocIterator::print() {1021RelocIterator save_this = (*this);1022relocInfo* scan = _current;1023if (!has_current()) scan += 1; // nothing to scan here!10241025bool skip_next = has_current();1026bool got_next;1027while (true) {1028got_next = (skip_next || next());1029skip_next = false;10301031tty->print(" @" INTPTR_FORMAT ": ", scan);1032relocInfo* newscan = _current+1;1033if (!has_current()) newscan -= 1; // nothing to scan here!1034while (scan < newscan) {1035tty->print("%04x", *(short*)scan & 0xFFFF);1036scan++;1037}1038tty->cr();10391040if (!got_next) break;1041print_current();1042}10431044(*this) = save_this;1045}10461047// For the debugger:1048extern "C"1049void print_blob_locs(nmethod* nm) {1050nm->print();1051RelocIterator iter(nm);1052iter.print();1053}1054extern "C"1055void print_buf_locs(CodeBuffer* cb) {1056FlagSetting fs(PrintRelocations, true);1057cb->print();1058}1059#endif // !PRODUCT106010611062