# HG changeset patch # User goetz # Date 1372927891 -7200 # Node ID 422557569a6bb34e88444647f90a36888b654a99 # Parent 40e74d1a401a45b2f015232f93653686b3bd4a53 8016696: PPC64 (part 4): add relocation for trampoline stubs Summary: 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 diff -r 40e74d1a401a -r 422557569a6b hotspot/src/share/vm/code/relocInfo.cpp --- a/hotspot/src/share/vm/code/relocInfo.cpp Wed Jul 03 11:50:29 2013 -0700 +++ b/hotspot/src/share/vm/code/relocInfo.cpp Thu Jul 04 10:51:31 2013 +0200 @@ -582,6 +582,18 @@ _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) { short* p = (short*) dest->locs_end(); @@ -811,6 +823,25 @@ 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() { // Call stub is only used when calling the interpreted code. @@ -975,6 +1006,12 @@ tty->print(" | [static_call=" INTPTR_FORMAT "]", r->static_call()); 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(); } diff -r 40e74d1a401a -r 422557569a6b hotspot/src/share/vm/code/relocInfo.hpp --- a/hotspot/src/share/vm/code/relocInfo.hpp Wed Jul 03 11:50:29 2013 -0700 +++ b/hotspot/src/share/vm/code/relocInfo.hpp Thu Jul 04 10:51:31 2013 +0200 @@ -260,8 +260,8 @@ poll_type = 10, // polling instruction for safepoints poll_return_type = 11, // polling instruction for safepoints at return metadata_type = 12, // metadata that used to be oops - yet_unused_type_1 = 13, // Still unused - yet_unused_type_2 = 14, // Still unused + trampoline_stub_type = 13, // stub-entry for trampoline + yet_unused_type_1 = 14, // Still unused data_prefix_tag = 15, // tag for a prefix (carries data arguments) type_mask = 15 // A mask which selects only the above values }; @@ -301,6 +301,7 @@ visitor(poll) \ visitor(poll_return) \ visitor(section_word) \ + visitor(trampoline_stub) \ public: @@ -1150,6 +1151,43 @@ 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 { relocInfo::relocType type() { return relocInfo::external_word_type; }