8016696: PPC64 (part 4): add relocation for trampoline stubs
A trampoline allows to encode a small branch in the code, even if there is the chance that this branch can not reach all possible code locations. If the relocation finds that a branch is too far for the instruction in the code, it can patch it to jump to the trampoline where is sufficient space for a far branch. Needed on PPC. Reviewed-by: kvn, bdelsart, jrose
This commit is contained in:
parent
16f3142152
commit
c12f5a0180
@ -582,6 +582,18 @@ void static_stub_Relocation::unpack_data() {
|
|||||||
_static_call = address_from_scaled_offset(unpack_1_int(), base);
|
_static_call = address_from_scaled_offset(unpack_1_int(), base);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void trampoline_stub_Relocation::pack_data_to(CodeSection* dest ) {
|
||||||
|
short* p = (short*) dest->locs_end();
|
||||||
|
CodeSection* insts = dest->outer()->insts();
|
||||||
|
normalize_address(_owner, insts);
|
||||||
|
p = pack_1_int_to(p, scaled_offset(_owner, insts->start()));
|
||||||
|
dest->set_locs_end((relocInfo*) p);
|
||||||
|
}
|
||||||
|
|
||||||
|
void trampoline_stub_Relocation::unpack_data() {
|
||||||
|
address base = binding()->section_start(CodeBuffer::SECT_INSTS);
|
||||||
|
_owner = address_from_scaled_offset(unpack_1_int(), base);
|
||||||
|
}
|
||||||
|
|
||||||
void external_word_Relocation::pack_data_to(CodeSection* dest) {
|
void external_word_Relocation::pack_data_to(CodeSection* dest) {
|
||||||
short* p = (short*) dest->locs_end();
|
short* p = (short*) dest->locs_end();
|
||||||
@ -811,6 +823,25 @@ address static_call_Relocation::static_stub() {
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Finds the trampoline address for a call. If no trampoline stub is
|
||||||
|
// found NULL is returned which can be handled by the caller.
|
||||||
|
address trampoline_stub_Relocation::get_trampoline_for(address call, nmethod* code) {
|
||||||
|
// There are no relocations available when the code gets relocated
|
||||||
|
// because of CodeBuffer expansion.
|
||||||
|
if (code->relocation_size() == 0)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
RelocIterator iter(code, call);
|
||||||
|
while (iter.next()) {
|
||||||
|
if (iter.type() == relocInfo::trampoline_stub_type) {
|
||||||
|
if (iter.trampoline_stub_reloc()->owner() == call) {
|
||||||
|
return iter.addr();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
void static_stub_Relocation::clear_inline_cache() {
|
void static_stub_Relocation::clear_inline_cache() {
|
||||||
// Call stub is only used when calling the interpreted code.
|
// Call stub is only used when calling the interpreted code.
|
||||||
@ -975,6 +1006,12 @@ void RelocIterator::print_current() {
|
|||||||
tty->print(" | [static_call=" INTPTR_FORMAT "]", r->static_call());
|
tty->print(" | [static_call=" INTPTR_FORMAT "]", r->static_call());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case relocInfo::trampoline_stub_type:
|
||||||
|
{
|
||||||
|
trampoline_stub_Relocation* r = (trampoline_stub_Relocation*) reloc();
|
||||||
|
tty->print(" | [trampoline owner=" INTPTR_FORMAT "]", r->owner());
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
tty->cr();
|
tty->cr();
|
||||||
}
|
}
|
||||||
|
@ -260,8 +260,8 @@ class relocInfo VALUE_OBJ_CLASS_SPEC {
|
|||||||
poll_type = 10, // polling instruction for safepoints
|
poll_type = 10, // polling instruction for safepoints
|
||||||
poll_return_type = 11, // polling instruction for safepoints at return
|
poll_return_type = 11, // polling instruction for safepoints at return
|
||||||
metadata_type = 12, // metadata that used to be oops
|
metadata_type = 12, // metadata that used to be oops
|
||||||
yet_unused_type_1 = 13, // Still unused
|
trampoline_stub_type = 13, // stub-entry for trampoline
|
||||||
yet_unused_type_2 = 14, // Still unused
|
yet_unused_type_1 = 14, // Still unused
|
||||||
data_prefix_tag = 15, // tag for a prefix (carries data arguments)
|
data_prefix_tag = 15, // tag for a prefix (carries data arguments)
|
||||||
type_mask = 15 // A mask which selects only the above values
|
type_mask = 15 // A mask which selects only the above values
|
||||||
};
|
};
|
||||||
@ -301,6 +301,7 @@ class relocInfo VALUE_OBJ_CLASS_SPEC {
|
|||||||
visitor(poll) \
|
visitor(poll) \
|
||||||
visitor(poll_return) \
|
visitor(poll_return) \
|
||||||
visitor(section_word) \
|
visitor(section_word) \
|
||||||
|
visitor(trampoline_stub) \
|
||||||
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@ -1150,6 +1151,43 @@ class runtime_call_Relocation : public CallRelocation {
|
|||||||
public:
|
public:
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Trampoline Relocations.
|
||||||
|
// A trampoline allows to encode a small branch in the code, even if there
|
||||||
|
// is the chance that this branch can not reach all possible code locations.
|
||||||
|
// If the relocation finds that a branch is too far for the instruction
|
||||||
|
// in the code, it can patch it to jump to the trampoline where is
|
||||||
|
// sufficient space for a far branch. Needed on PPC.
|
||||||
|
class trampoline_stub_Relocation : public Relocation {
|
||||||
|
relocInfo::relocType type() { return relocInfo::trampoline_stub_type; }
|
||||||
|
|
||||||
|
public:
|
||||||
|
static RelocationHolder spec(address static_call) {
|
||||||
|
RelocationHolder rh = newHolder();
|
||||||
|
return (new (rh) trampoline_stub_Relocation(static_call));
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
address _owner; // Address of the NativeCall that owns the trampoline.
|
||||||
|
|
||||||
|
trampoline_stub_Relocation(address owner) {
|
||||||
|
_owner = owner;
|
||||||
|
}
|
||||||
|
|
||||||
|
friend class RelocIterator;
|
||||||
|
trampoline_stub_Relocation() { }
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
// Return the address of the NativeCall that owns the trampoline.
|
||||||
|
address owner() { return _owner; }
|
||||||
|
|
||||||
|
void pack_data_to(CodeSection * dest);
|
||||||
|
void unpack_data();
|
||||||
|
|
||||||
|
// Find the trampoline stub for a call.
|
||||||
|
static address get_trampoline_for(address call, nmethod* code);
|
||||||
|
};
|
||||||
|
|
||||||
class external_word_Relocation : public DataRelocation {
|
class external_word_Relocation : public DataRelocation {
|
||||||
relocInfo::relocType type() { return relocInfo::external_word_type; }
|
relocInfo::relocType type() { return relocInfo::external_word_type; }
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user