/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
#include "precompiled.hpp"
#include "code/compiledIC.hpp"
#include "code/nmethod.hpp"
#include "code/relocInfo.hpp"
#include "memory/resourceArea.hpp"
#include "runtime/stubCodeGenerator.hpp"
#ifdef TARGET_ARCH_x86
# include "assembler_x86.inline.hpp"
# include "nativeInst_x86.hpp"
#endif
#ifdef TARGET_ARCH_sparc
# include "assembler_sparc.inline.hpp"
# include "nativeInst_sparc.hpp"
#endif
#ifdef TARGET_ARCH_zero
# include "assembler_zero.inline.hpp"
# include "nativeInst_zero.hpp"
#endif
#ifdef TARGET_ARCH_arm
# include "assembler_arm.inline.hpp"
# include "nativeInst_arm.hpp"
#endif
#ifdef TARGET_ARCH_ppc
# include "assembler_ppc.inline.hpp"
# include "nativeInst_ppc.hpp"
#endif
// Implementation of relocInfo
#ifdef ASSERT
}
#endif
if (data_limit > data) {
// Finish up with the suffix. (Hack note: pack_data_to might edit this.)
*data_limit = suffix;
}
}
short* p = (short*)(this+1);
if (plen == 0) {
return this; // no data: remove self completely
}
(*this) = immediate_relocInfo(p[0]); // move data inside self
return this+1;
}
// cannot compact, so just update the count and return the limit pointer
return (relocInfo*)prefix_limit;
}
}
}
void relocInfo::change_reloc_info_for_address(RelocIterator *itr, address pc, relocType old_type, relocType new_type) {
bool found = false;
found=true;
}
}
}
}
// ----------------------------------------------------------------------------------------------------
// Implementation of RelocIterator
// allow nmethod to be deduced from beginning address
}
// Initialize code sections.
}
}
}
struct RelocIndexEntry {
};
const int n = CodeBuffer::SECT_CONSTS;
}
}
// format of indexed relocs:
// relocation_begin: relocInfo ...
// index: (addr,reloc#) ...
// indexSize :relocation_end
}
if (!UseRelocIndex) {
return;
}
if (index_size != 0) {
// walk over the relocations, and fill in index entries as we go
int i = 0;
int addr_offset = 0;
int reloc_offset = 0;
while (true) {
// Checkpoint the iterator before advancing it.
i++;
}
}
while (i < ncards) {
i++;
}
}
}
int index_size = 0;
}
// the limit affects this next stuff:
#ifdef ASSERT
// In ASSERT mode we do not actually use the index, but simply
// check that its contents would have led us to the right answer.
#endif // ASSERT
if (index_size > 0) {
// skip ahead
if (card > 0) {
#ifdef ASSERT
#else
// Advance the iterator immediately to the last valid state
// for the previous card. Calling "next" will then advance
// it to the first item on the required card.
#endif // ASSERT
}
}
while (true) {
backup_addr = _addr;
#ifdef ASSERT
} else {
}
#endif // ASSERT
}
// At this point, either we are at the first matching record,
// or else there is no such record, and !has_current().
// In either case, revert to the immediatly preceding state.
_addr = backup_addr;
set_has_current(false);
}
}
}
// turn breakpoints off during patching
_init_state = (*this); // save cursor
while (next()) {
breakpoint_reloc()->set_active(false);
}
}
}
// turn breakpoints back on after patching
while (next()) {
}
}
}
// All the strange bit-encodings are in here.
// The idea is to encode relocation data which are small integers
// very efficiently (a single extra halfword). Larger chunks of
// relocation data need a halfword header to hold their size.
if (_current->is_datalen()) {
} else {
_datalen = 1;
_current++; // skip the header
}
// The client will see the following relocInfo, whatever that is.
// It is the reloc to which the preceding data applies.
}
set_has_current(false);
_section_end [i] = NULL;
}
}
// (take the "switch" out-of-line)
if (false) {}
}
return new(_rh) Relocation();
}
//////// Methods for flyweight Relocation types
if (offset != 0) {
switch (type()) {
break;
{
}
default:
}
}
return (*this);
}
guarantee(false, "Make _relocbuf bigger!");
}
// some relocations can compute their own values
return NULL;
}
}
}
if (runtime_address == NULL) return 0;
} else {
// Known "miscellaneous" non-stub pointers:
// os::get_polling_page(), SafepointSynchronize::address_of_state()
if (PrintRelocations) {
}
#ifndef _LP64
#else
// didn't fit return non-index
return -1;
#endif /* _LP64 */
}
}
if (is_reloc_index(index)) {
return p->begin();
} else {
#ifndef _LP64
// this only works on 32bit machines
#else
fatal("Relocation::index_to_runtime_address, int32_t not pointer sized");
return NULL;
#endif /* _LP64 */
}
}
}
// Look for olda in the source buffer, and all previous incarnations
// if the source buffer has been expanded.
}
}
void Relocation::normalize_address(address& addr, const CodeSection* dest, bool allow_other_sections) {
"addr must be in required section");
}
}
// Usually a self-relative reference to an external routine.
// On some platforms, the reference is absolute (not self-relative).
// The enhanced use of pd_call_destination sorts this all out.
// Reassert the callee address, this time in the new copy of the code.
}
}
}
// Try to make a pointer NULL first.
if (_oop_limit >= point &&
_oop_limit = NULL;
}
// If the _oop_limit is NULL, it "defaults" to the end of the call.
// See ic_call_Relocation::oop_limit() below.
}
}
}
}
#ifndef _LP64
p = pack_1_int_to(p, index);
#else
if (is_reloc_index(index)) {
p = pack_2_ints_to(p, index, 0);
} else {
}
#endif /* _LP64 */
}
#ifndef _LP64
#else
if (is_reloc_index(t)) {
} else {
}
#endif /* _LP64 */
}
// Check whether my target address is valid within this section.
// If not, strengthen the relocation type to point to another section.
// Change the written type, to be section_word_type instead.
}
// Note: An internal_word relocation cannot refer to its own instruction,
// because we reserve "0" to mean that the pointer itself is embedded
// in the code stream. We use a section_word relocation for such cases.
p = pack_1_int_to(p, x0);
} else {
}
}
}
jint x = unpack_1_int();
}
*p++ = _bits;
if (settable()) {
// save space for set_target later
p = add_jint(p, target_bits);
} else {
p = add_var_int(p, target_bits);
}
for (int i = 0; i < instrlen(); i++) {
// put placeholder words until bytes can be saved
p = add_short(p, (short)0x7777);
}
}
if (targetlen == 0) target_bits = 0;
else { ShouldNotReachHere(); }
}
//// miscellaneous methods
int n = _oop_index;
if (n == 0) {
// oop is stored in the code stream
return (oop*) pd_address_in_code();
} else {
// oop is stored in table at nmethod::oops_begin
return code()->oop_addr_at(n);
}
}
// clean inline caches store a special pseudo-null
return v;
}
if (!oop_is_immediate()) {
// get the oop from the pool, and re-insert it into the instruction:
}
}
if (!oop_is_immediate()) {
// get the oop from the pool, and re-insert it into the instruction:
verify_value(value());
}
}
}
}
// search for the ic_call at the given address
*is_optimized = false;
} else {
*is_optimized = true;
return iter;
}
}
// search for the first_oop, to get its oop_addr
bool found_oop = false;
found_oop = true;
break;
}
}
bool did_reset = false;
// search forward for the ic_call matching the given first_oop
break;
}
}
}
did_reset = true;
}
return all_oops;
}
return _first_oop;
}
if (_oop_limit == NULL)
else
return _oop_limit;
}
// No stubs for ICs
// Clean IC
icache->set_to_clean();
}
// No stubs for ICs
// Clean IC
icache->set_to_clean();
}
// search for the static stub who points back to this static call
}
}
}
return NULL;
}
// Safe call site info
handler->set_to_clean();
}
// search for the static stub who points back to this static call
}
}
}
return NULL;
}
// Call stub is only used when calling the interpreted code.
// It does not really need to be cleared, except that we want to clean out the methodoop.
CompiledStaticCall::set_stub_to_clean(this);
}
// An absolute embedded reference to an external location,
// which means there is nothing to fix here.
return;
}
// Probably this reference is absolute, not relative, so the
// following is probably a no-op.
}
}
return target;
}
if (addr_in_const()) {
} else {
}
}
}
}
return target;
}
bool active = false;
}
return _target;
}
: runtime_address_to_index(x));
short* p = &live_bits() + 1;
p = add_jint(p, target_bits);
_target = x;
}
if (enabled() == b) return;
if (b) {
} else {
set_active(false); // remove the actual breakpoint insn, if any
}
}
if (active() == b) return;
// %%% should probably seize a lock here (might not be the right lock)
//MutexLockerEx ml_patch(Patching_lock, true);
//if (active() == b) return; // recheck state after locking
if (b) {
if (instrlen() == 0)
fatal("breakpoints in original code must be undoable");
} else {
}
}
//---------------------------------------------------------------------------------
// Non-product code
#ifndef PRODUCT
switch (t) {
return #name;
return "none";
case relocInfo::data_prefix_tag:
return "prefix";
default:
return "UNKNOWN RELOC TYPE";
}
}
if (!has_current()) {
return;
}
_current, type(), reloc_type_string((relocInfo::relocType) type()), _addr, _current->addr_offset());
if (datalen() == 1) {
} else if (datalen() > 0) {
for (int i = 0; i < datalen(); i++) {
}
}
switch (type()) {
{
oop_Relocation* r = oop_reloc();
}
// Do not print the oop by default--we want this routine to
// work even during GC or other inconvenient times.
}
break;
}
case relocInfo::external_word_type:
case relocInfo::internal_word_type:
case relocInfo::section_word_type:
{
break;
}
case relocInfo::static_call_type:
case relocInfo::runtime_call_type:
{
break;
}
case relocInfo::virtual_call_type:
{
tty->print(" | [destination=" INTPTR_FORMAT " first_oop=" INTPTR_FORMAT " oop_limit=" INTPTR_FORMAT "]",
break;
}
case relocInfo::static_stub_type:
{
break;
}
}
}
bool got_next;
while (true) {
skip_next = false;
scan++;
}
if (!got_next) break;
}
(*this) = save_this;
}
// For the debugger:
extern "C"
}
extern "C"
}
#endif // !PRODUCT