/* * Copyright (c) 2002, 2022, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2012, 2021 SAP SE. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * 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. *
*/
// We have interfaces for the following instructions: // // - NativeInstruction // - NativeCall // - NativeFarCall // - NativeMovConstReg // - NativeJump // - NativeIllegalInstruction // - NativeConditionalFarBranch // - NativeCallTrampolineStub
// The base class for different kinds of native instruction abstractions. // It provides the primitive operations to manipulate code relative to this. class NativeInstruction { friendclass Relocation;
int get_stop_type() { return MacroAssembler::tdi_get_si16(long_at(0), Assembler::traptoUnconditional, 0);
}
// We use an illtrap for marking a method as not_entrant. bool is_sigill_not_entrant() { // Work around a C++ compiler bug which changes 'this'. return NativeInstruction::is_sigill_not_entrant_at(addr_at(0));
} staticbool is_sigill_not_entrant_at(address addr);
bool is_safepoint_poll() { // The current arguments of the instruction are not checked! if (USE_POLL_BIT_ONLY) { int encoding = SafepointMechanism::poll_bit(); return MacroAssembler::is_tdi(long_at(0), Assembler::traptoGreaterThanUnsigned | Assembler::traptoEqual,
-1, encoding);
} return MacroAssembler::is_load_from_polling_page(long_at(0), NULL);
}
bool is_safepoint_poll_return() { // Safepoint poll at nmethod return with watermark check. return MacroAssembler::is_td(long_at(0), Assembler::traptoGreaterThanUnsigned, /* R1_SP */ 1, /* any reg */ -1);
}
address get_stack_bang_address(void *ucontext) { // If long_at(0) is not a stack bang, return 0. Otherwise, return // banged address. return MacroAssembler::get_stack_bang_address(long_at(0), ucontext);
}
// The NativeCall is an abstraction for accessing/manipulating call // instructions. It is used to manipulate inline caches, primitive & // dll calls, etc. // // Sparc distinguishes `NativeCall' and `NativeFarCall'. On PPC64, // at present, we provide a single class `NativeCall' representing the // sequence `load_const, mtctr, bctrl' or the sequence 'ld_from_toc, // mtctr, bctrl'. class NativeCall: public NativeInstruction { public:
enum ppc_specific_constants {
load_const_instruction_size = 28,
load_const_from_method_toc_instruction_size = 16,
instruction_size = 16 // Used in shared code for calls with reloc_info.
};
staticbool is_call_at(address a) { return Assembler::is_bl(*(int*)(a));
}
address next_instruction_address() const { // We have only bl.
assert(MacroAssembler::is_bl(*(int*)instruction_address()), "Should be bl instruction!"); return addr_at(4);
}
// The NativeFarCall is an abstraction for accessing/manipulating native // call-anywhere instructions. // Used to call native methods which may be loaded anywhere in the address // space, possibly out of reach of a call instruction. class NativeFarCall: public NativeInstruction { public: // We use MacroAssembler::bl64_patchable() for implementing a // call-anywhere instruction.
// Checks whether instr points at a NativeFarCall instruction. staticbool is_far_call_at(address instr) { return MacroAssembler::is_bl64_patchable_at(instr);
}
// Does the NativeFarCall implementation use a pc-relative encoding // of the call destination? // Used when relocating code. bool is_pcrelative() {
assert(MacroAssembler::is_bl64_patchable_at((address)this), "unexpected call type"); return MacroAssembler::is_bl64_patchable_pcrelative_at((address)this);
}
// Sets the NativeCall's destination, not necessarily mt-safe. // Used when relocating code. void set_destination(address dest) { // Set new destination (implementation of call may change here).
assert(MacroAssembler::is_bl64_patchable_at((address)this), "unexpected call type");
MacroAssembler::set_dest_of_bl64_patchable_at((address)this, dest);
}
void verify() NOT_DEBUG_RETURN;
};
// Instantiates a NativeFarCall object starting at the given instruction // address and returns the NativeFarCall object. inline NativeFarCall* nativeFarCall_at(address instr) {
NativeFarCall* call = (NativeFarCall*)instr;
call->verify(); return call;
}
// An interface for accessing/manipulating native set_oop imm, reg instructions // (used to manipulate inlined data references, etc.). class NativeMovConstReg: public NativeInstruction { public:
enum ppc_specific_constants {
load_const_instruction_size = 20,
load_const_from_method_toc_instruction_size = 8,
instruction_size = 8 // Used in shared code for calls with reloc_info.
};
// The NativeJump is an abstraction for accessing/manipulating native // jump-anywhere instructions. class NativeJump: public NativeInstruction { public: // We use MacroAssembler::b64_patchable() for implementing a // jump-anywhere instruction.
// Does the NativeJump implementation use a pc-relative encoding // of the call destination? // Used when relocating code or patching jumps. bool is_pcrelative() { return MacroAssembler::is_b64_patchable_pcrelative_at((address)this);
}
// Sets the NativeJump's destination, not necessarily mt-safe. // Used when relocating code or patching jumps. void set_jump_destination(address dest) { // Set new destination (implementation of call may change here). if (MacroAssembler::is_b64_patchable_at((address)this)) {
MacroAssembler::set_dest_of_b64_patchable_at((address)this, dest);
} elseif (MacroAssembler::is_load_const_from_method_toc_at((address)this)
&& Assembler::is_mtctr(*(int*)((address)this + 2 * 4))
&& Assembler::is_bctr(*(int*)((address)this + 3 * 4))) {
((NativeMovConstReg *)this)->set_data((intptr_t)dest);
} else {
ShouldNotReachHere();
}
}
// MT-safe insertion of native jump at verified method entry staticvoid patch_verified_entry(address entry, address verified_entry, address dest);
void verify() NOT_DEBUG_RETURN;
staticvoid check_verified_entry_alignment(address entry, address verified_entry) { // We just patch one instruction on ppc64, so the jump doesn't have to // be aligned. Nothing to do here.
}
};
// Instantiates a NativeJump object starting at the given instruction // address and returns the NativeJump object. inline NativeJump* nativeJump_at(address instr) {
NativeJump* call = (NativeJump*)instr;
call->verify(); return call;
}
// NativeConditionalFarBranch is abstraction for accessing/manipulating // conditional far branches. class NativeConditionalFarBranch : public NativeInstruction { public:
inline NativeConditionalFarBranch* NativeConditionalFarBranch_at(address address) {
assert(NativeConditionalFarBranch::is_conditional_far_branch_at(address), "must be a conditional far branch"); return (NativeConditionalFarBranch*)address;
}
// Call trampoline stubs. class NativeCallTrampolineStub : public NativeInstruction { private:
address encoded_destination_addr() const;
public:
address destination(nmethod *nm = NULL) const; int destination_toc_offset() const;
void set_destination(address new_destination);
};
// Note: Other stubs must not begin with this pattern. inlinebool is_NativeCallTrampolineStub_at(address address) { int first_instr = *(int*)address; // calculate_address_from_global_toc and long form of ld_largeoffset_unchecked begin with addis with target R12 if (Assembler::is_addis(first_instr) &&
(Register)(intptr_t)Assembler::inv_rt_field(first_instr) == R12_scratch2) returntrue;
// short form of ld_largeoffset_unchecked is ld which is followed by mtctr int second_instr = *((int*)address + 1); if (Assembler::is_ld(first_instr) &&
(Register)(intptr_t)Assembler::inv_rt_field(first_instr) == R12_scratch2 &&
Assembler::is_mtctr(second_instr) &&
(Register)(intptr_t)Assembler::inv_rs_field(second_instr) == R12_scratch2) returntrue;
// An interface for accessing/manipulating native load int (load_const32). class NativeMovRegMem; inline NativeMovRegMem* nativeMovRegMem_at(address address); class NativeMovRegMem: public NativeInstruction { public:
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung ist noch experimentell.