Merge
This commit is contained in:
commit
ee8db43354
@ -124,6 +124,7 @@ class Argument VALUE_OBJ_CLASS_SPEC {
|
||||
}
|
||||
};
|
||||
|
||||
#if !defined(ABI_ELFv2)
|
||||
// A ppc64 function descriptor.
|
||||
struct FunctionDescriptor VALUE_OBJ_CLASS_SPEC {
|
||||
private:
|
||||
@ -161,6 +162,7 @@ struct FunctionDescriptor VALUE_OBJ_CLASS_SPEC {
|
||||
_env = (address) 0xbad;
|
||||
}
|
||||
};
|
||||
#endif
|
||||
|
||||
class Assembler : public AbstractAssembler {
|
||||
protected:
|
||||
@ -1067,6 +1069,7 @@ class Assembler : public AbstractAssembler {
|
||||
// Emit an address.
|
||||
inline address emit_addr(const address addr = NULL);
|
||||
|
||||
#if !defined(ABI_ELFv2)
|
||||
// Emit a function descriptor with the specified entry point, TOC,
|
||||
// and ENV. If the entry point is NULL, the descriptor will point
|
||||
// just past the descriptor.
|
||||
@ -1074,6 +1077,7 @@ class Assembler : public AbstractAssembler {
|
||||
inline address emit_fd(address entry = NULL,
|
||||
address toc = (address) FunctionDescriptor::friend_toc,
|
||||
address env = (address) FunctionDescriptor::friend_env);
|
||||
#endif
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////
|
||||
// PPC instructions
|
||||
|
@ -55,6 +55,7 @@ inline address Assembler::emit_addr(const address addr) {
|
||||
return start;
|
||||
}
|
||||
|
||||
#if !defined(ABI_ELFv2)
|
||||
// Emit a function descriptor with the specified entry point, TOC, and
|
||||
// ENV. If the entry point is NULL, the descriptor will point just
|
||||
// past the descriptor.
|
||||
@ -73,6 +74,7 @@ inline address Assembler::emit_fd(address entry, address toc, address env) {
|
||||
|
||||
return (address)fd;
|
||||
}
|
||||
#endif
|
||||
|
||||
// Issue an illegal instruction. 0 is guaranteed to be an illegal instruction.
|
||||
inline void Assembler::illtrap() { Assembler::emit_int32(0); }
|
||||
|
@ -1136,7 +1136,9 @@ address CppInterpreterGenerator::generate_native_entry(void) {
|
||||
// (outgoing C args), R3_ARG1 to R10_ARG8, and F1_ARG1 to
|
||||
// F13_ARG13.
|
||||
__ mr(R3_ARG1, R18_locals);
|
||||
#if !defined(ABI_ELFv2)
|
||||
__ ld(signature_handler_fd, 0, signature_handler_fd);
|
||||
#endif
|
||||
__ call_stub(signature_handler_fd);
|
||||
// reload method
|
||||
__ ld(R19_method, state_(_method));
|
||||
@ -1295,8 +1297,13 @@ address CppInterpreterGenerator::generate_native_entry(void) {
|
||||
// native result acrosss the call. No oop is present
|
||||
|
||||
__ mr(R3_ARG1, R16_thread);
|
||||
#if defined(ABI_ELFv2)
|
||||
__ call_c(CAST_FROM_FN_PTR(address, JavaThread::check_special_condition_for_native_trans),
|
||||
relocInfo::none);
|
||||
#else
|
||||
__ call_c(CAST_FROM_FN_PTR(FunctionDescriptor*, JavaThread::check_special_condition_for_native_trans),
|
||||
relocInfo::none);
|
||||
#endif
|
||||
__ bind(sync_check_done);
|
||||
|
||||
//=============================================================================
|
||||
@ -1413,7 +1420,7 @@ address CppInterpreterGenerator::generate_native_entry(void) {
|
||||
// First, pop to caller's frame.
|
||||
__ pop_interpreter_frame(R11_scratch1, R12_scratch2, R21_tmp1 /* set to return pc */, R22_tmp2);
|
||||
|
||||
__ push_frame_abi112(0, R11_scratch1);
|
||||
__ push_frame_reg_args(0, R11_scratch1);
|
||||
// Get the address of the exception handler.
|
||||
__ call_VM_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::exception_handler_for_return_address),
|
||||
R16_thread,
|
||||
@ -2545,7 +2552,7 @@ address CppInterpreterGenerator::generate_normal_entry(void) {
|
||||
__ mr(R4_ARG2, R3_ARG1); // ARG2 := ARG1
|
||||
|
||||
// Find the address of the "catch_exception" stub.
|
||||
__ push_frame_abi112(0, R11_scratch1);
|
||||
__ push_frame_reg_args(0, R11_scratch1);
|
||||
__ call_VM_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::exception_handler_for_return_address),
|
||||
R16_thread,
|
||||
R4_ARG2);
|
||||
|
@ -50,7 +50,7 @@
|
||||
// [C_FRAME]
|
||||
//
|
||||
// C_FRAME:
|
||||
// 0 [ABI_112]
|
||||
// 0 [ABI_REG_ARGS]
|
||||
// 112 CARG_9: outgoing arg 9 (arg_1 ... arg_8 via gpr_3 ... gpr_{10})
|
||||
// ...
|
||||
// 40+M*8 CARG_M: outgoing arg M (M is the maximum of outgoing args taken over all call sites in the procedure)
|
||||
@ -77,7 +77,7 @@
|
||||
// 32 reserved
|
||||
// 40 space for TOC (=R2) register for next call
|
||||
//
|
||||
// ABI_112:
|
||||
// ABI_REG_ARGS:
|
||||
// 0 [ABI_48]
|
||||
// 48 CARG_1: spill slot for outgoing arg 1. used by next callee.
|
||||
// ... ...
|
||||
@ -95,23 +95,25 @@
|
||||
log_2_of_alignment_in_bits = 7
|
||||
};
|
||||
|
||||
// ABI_48:
|
||||
struct abi_48 {
|
||||
// ABI_MINFRAME:
|
||||
struct abi_minframe {
|
||||
uint64_t callers_sp;
|
||||
uint64_t cr; //_16
|
||||
uint64_t lr;
|
||||
#if !defined(ABI_ELFv2)
|
||||
uint64_t reserved1; //_16
|
||||
uint64_t reserved2;
|
||||
#endif
|
||||
uint64_t toc; //_16
|
||||
// nothing to add here!
|
||||
// aligned to frame::alignment_in_bytes (16)
|
||||
};
|
||||
|
||||
enum {
|
||||
abi_48_size = sizeof(abi_48)
|
||||
abi_minframe_size = sizeof(abi_minframe)
|
||||
};
|
||||
|
||||
struct abi_112 : abi_48 {
|
||||
struct abi_reg_args : abi_minframe {
|
||||
uint64_t carg_1;
|
||||
uint64_t carg_2; //_16
|
||||
uint64_t carg_3;
|
||||
@ -124,13 +126,13 @@
|
||||
};
|
||||
|
||||
enum {
|
||||
abi_112_size = sizeof(abi_112)
|
||||
abi_reg_args_size = sizeof(abi_reg_args)
|
||||
};
|
||||
|
||||
#define _abi(_component) \
|
||||
(offset_of(frame::abi_112, _component))
|
||||
(offset_of(frame::abi_reg_args, _component))
|
||||
|
||||
struct abi_112_spill : abi_112 {
|
||||
struct abi_reg_args_spill : abi_reg_args {
|
||||
// additional spill slots
|
||||
uint64_t spill_ret;
|
||||
uint64_t spill_fret; //_16
|
||||
@ -138,11 +140,11 @@
|
||||
};
|
||||
|
||||
enum {
|
||||
abi_112_spill_size = sizeof(abi_112_spill)
|
||||
abi_reg_args_spill_size = sizeof(abi_reg_args_spill)
|
||||
};
|
||||
|
||||
#define _abi_112_spill(_component) \
|
||||
(offset_of(frame::abi_112_spill, _component))
|
||||
#define _abi_reg_args_spill(_component) \
|
||||
(offset_of(frame::abi_reg_args_spill, _component))
|
||||
|
||||
// non-volatile GPRs:
|
||||
|
||||
@ -242,7 +244,7 @@
|
||||
// [ENTRY_FRAME_LOCALS]
|
||||
//
|
||||
// PARENT_IJAVA_FRAME_ABI:
|
||||
// 0 [ABI_48]
|
||||
// 0 [ABI_MINFRAME]
|
||||
// top_frame_sp
|
||||
// initial_caller_sp
|
||||
//
|
||||
@ -258,7 +260,7 @@
|
||||
|
||||
// PARENT_IJAVA_FRAME_ABI
|
||||
|
||||
struct parent_ijava_frame_abi : abi_48 {
|
||||
struct parent_ijava_frame_abi : abi_minframe {
|
||||
// SOE registers.
|
||||
// C2i adapters spill their top-frame stack-pointer here.
|
||||
uint64_t top_frame_sp; // carg_1
|
||||
@ -285,7 +287,7 @@
|
||||
uint64_t carg_6_unused; //_16 carg_6
|
||||
uint64_t carg_7_unused; // carg_7
|
||||
// Use arg8 for storing frame_manager_lr. The size of
|
||||
// top_ijava_frame_abi must match abi_112.
|
||||
// top_ijava_frame_abi must match abi_reg_args.
|
||||
uint64_t frame_manager_lr; //_16 carg_8
|
||||
// nothing to add here!
|
||||
// aligned to frame::alignment_in_bytes (16)
|
||||
@ -395,8 +397,8 @@
|
||||
intptr_t* fp() const { return _fp; }
|
||||
|
||||
// Accessors for ABIs
|
||||
inline abi_48* own_abi() const { return (abi_48*) _sp; }
|
||||
inline abi_48* callers_abi() const { return (abi_48*) _fp; }
|
||||
inline abi_minframe* own_abi() const { return (abi_minframe*) _sp; }
|
||||
inline abi_minframe* callers_abi() const { return (abi_minframe*) _fp; }
|
||||
|
||||
private:
|
||||
|
||||
|
@ -109,8 +109,10 @@ void InterpreterRuntime::SignatureHandlerGenerator::pass_object() {
|
||||
}
|
||||
|
||||
void InterpreterRuntime::SignatureHandlerGenerator::generate(uint64_t fingerprint) {
|
||||
#if !defined(ABI_ELFv2)
|
||||
// Emit fd for current codebuffer. Needs patching!
|
||||
__ emit_fd();
|
||||
#endif
|
||||
|
||||
// Generate code to handle arguments.
|
||||
iterate(fingerprint);
|
||||
@ -127,11 +129,13 @@ void InterpreterRuntime::SignatureHandlerGenerator::generate(uint64_t fingerprin
|
||||
// Implementation of SignatureHandlerLibrary
|
||||
|
||||
void SignatureHandlerLibrary::pd_set_handler(address handler) {
|
||||
#if !defined(ABI_ELFv2)
|
||||
// patch fd here.
|
||||
FunctionDescriptor* fd = (FunctionDescriptor*) handler;
|
||||
|
||||
fd->set_entry(handler + (int)sizeof(FunctionDescriptor));
|
||||
assert(fd->toc() == (address)0xcafe, "need to adjust TOC here");
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
@ -128,13 +128,13 @@ address AbstractInterpreterGenerator::generate_slow_signature_handler() {
|
||||
const Register target_sp = R28_tmp8;
|
||||
const FloatRegister floatSlot = F0;
|
||||
|
||||
address entry = __ emit_fd();
|
||||
address entry = __ function_entry();
|
||||
|
||||
__ save_LR_CR(R0);
|
||||
__ save_nonvolatile_gprs(R1_SP, _spill_nonvolatiles_neg(r14));
|
||||
// We use target_sp for storing arguments in the C frame.
|
||||
__ mr(target_sp, R1_SP);
|
||||
__ push_frame_abi112_nonvolatiles(0, R11_scratch1);
|
||||
__ push_frame_reg_args_nonvolatiles(0, R11_scratch1);
|
||||
|
||||
__ mr(arg_java, R3_ARG1);
|
||||
|
||||
@ -474,7 +474,7 @@ address InterpreterGenerator::generate_abstract_entry(void) {
|
||||
|
||||
// Push a new C frame and save LR.
|
||||
__ save_LR_CR(R0);
|
||||
__ push_frame_abi112(0, R11_scratch1);
|
||||
__ push_frame_reg_args(0, R11_scratch1);
|
||||
|
||||
// This is not a leaf but we have a JavaFrameAnchor now and we will
|
||||
// check (create) exceptions afterward so this is ok.
|
||||
|
@ -594,7 +594,13 @@ void MacroAssembler::bxx64_patchable(address dest, relocInfo::relocType rt, bool
|
||||
"can't identify emitted call");
|
||||
} else {
|
||||
// variant 1:
|
||||
|
||||
#if defined(ABI_ELFv2)
|
||||
nop();
|
||||
calculate_address_from_global_toc(R12, dest, true, true, false);
|
||||
mtctr(R12);
|
||||
nop();
|
||||
nop();
|
||||
#else
|
||||
mr(R0, R11); // spill R11 -> R0.
|
||||
|
||||
// Load the destination address into CTR,
|
||||
@ -604,6 +610,7 @@ void MacroAssembler::bxx64_patchable(address dest, relocInfo::relocType rt, bool
|
||||
mtctr(R11);
|
||||
mr(R11, R0); // spill R11 <- R0.
|
||||
nop();
|
||||
#endif
|
||||
|
||||
// do the call/jump
|
||||
if (link) {
|
||||
@ -912,16 +919,16 @@ void MacroAssembler::push_frame(unsigned int bytes, Register tmp) {
|
||||
}
|
||||
}
|
||||
|
||||
// Push a frame of size `bytes' plus abi112 on top.
|
||||
void MacroAssembler::push_frame_abi112(unsigned int bytes, Register tmp) {
|
||||
push_frame(bytes + frame::abi_112_size, tmp);
|
||||
// Push a frame of size `bytes' plus abi_reg_args on top.
|
||||
void MacroAssembler::push_frame_reg_args(unsigned int bytes, Register tmp) {
|
||||
push_frame(bytes + frame::abi_reg_args_size, tmp);
|
||||
}
|
||||
|
||||
// Setup up a new C frame with a spill area for non-volatile GPRs and
|
||||
// additional space for local variables.
|
||||
void MacroAssembler::push_frame_abi112_nonvolatiles(unsigned int bytes,
|
||||
Register tmp) {
|
||||
push_frame(bytes + frame::abi_112_size + frame::spill_nonvolatiles_size, tmp);
|
||||
void MacroAssembler::push_frame_reg_args_nonvolatiles(unsigned int bytes,
|
||||
Register tmp) {
|
||||
push_frame(bytes + frame::abi_reg_args_size + frame::spill_nonvolatiles_size, tmp);
|
||||
}
|
||||
|
||||
// Pop current C frame.
|
||||
@ -929,6 +936,42 @@ void MacroAssembler::pop_frame() {
|
||||
ld(R1_SP, _abi(callers_sp), R1_SP);
|
||||
}
|
||||
|
||||
#if defined(ABI_ELFv2)
|
||||
address MacroAssembler::branch_to(Register r_function_entry, bool and_link) {
|
||||
// TODO(asmundak): make sure the caller uses R12 as function descriptor
|
||||
// most of the times.
|
||||
if (R12 != r_function_entry) {
|
||||
mr(R12, r_function_entry);
|
||||
}
|
||||
mtctr(R12);
|
||||
// Do a call or a branch.
|
||||
if (and_link) {
|
||||
bctrl();
|
||||
} else {
|
||||
bctr();
|
||||
}
|
||||
_last_calls_return_pc = pc();
|
||||
|
||||
return _last_calls_return_pc;
|
||||
}
|
||||
|
||||
// Call a C function via a function descriptor and use full C
|
||||
// calling conventions. Updates and returns _last_calls_return_pc.
|
||||
address MacroAssembler::call_c(Register r_function_entry) {
|
||||
return branch_to(r_function_entry, /*and_link=*/true);
|
||||
}
|
||||
|
||||
// For tail calls: only branch, don't link, so callee returns to caller of this function.
|
||||
address MacroAssembler::call_c_and_return_to_caller(Register r_function_entry) {
|
||||
return branch_to(r_function_entry, /*and_link=*/false);
|
||||
}
|
||||
|
||||
address MacroAssembler::call_c(address function_entry, relocInfo::relocType rt) {
|
||||
load_const(R12, function_entry, R0);
|
||||
return branch_to(R12, /*and_link=*/true);
|
||||
}
|
||||
|
||||
#else
|
||||
// Generic version of a call to C function via a function descriptor
|
||||
// with variable support for C calling conventions (TOC, ENV, etc.).
|
||||
// Updates and returns _last_calls_return_pc.
|
||||
@ -1077,6 +1120,7 @@ address MacroAssembler::call_c_using_toc(const FunctionDescriptor* fd,
|
||||
}
|
||||
return _last_calls_return_pc;
|
||||
}
|
||||
#endif
|
||||
|
||||
void MacroAssembler::call_VM_base(Register oop_result,
|
||||
Register last_java_sp,
|
||||
@ -1091,8 +1135,11 @@ void MacroAssembler::call_VM_base(Register oop_result,
|
||||
|
||||
// ARG1 must hold thread address.
|
||||
mr(R3_ARG1, R16_thread);
|
||||
|
||||
#if defined(ABI_ELFv2)
|
||||
address return_pc = call_c(entry_point, relocInfo::none);
|
||||
#else
|
||||
address return_pc = call_c((FunctionDescriptor*)entry_point, relocInfo::none);
|
||||
#endif
|
||||
|
||||
reset_last_Java_frame();
|
||||
|
||||
@ -1113,7 +1160,11 @@ void MacroAssembler::call_VM_base(Register oop_result,
|
||||
|
||||
void MacroAssembler::call_VM_leaf_base(address entry_point) {
|
||||
BLOCK_COMMENT("call_VM_leaf {");
|
||||
#if defined(ABI_ELFv2)
|
||||
call_c(entry_point, relocInfo::none);
|
||||
#else
|
||||
call_c(CAST_FROM_FN_PTR(FunctionDescriptor*, entry_point), relocInfo::none);
|
||||
#endif
|
||||
BLOCK_COMMENT("} call_VM_leaf");
|
||||
}
|
||||
|
||||
@ -2227,7 +2278,7 @@ void MacroAssembler::g1_write_barrier_pre(Register Robj, RegisterOrConstant offs
|
||||
// VM call need frame to access(write) O register.
|
||||
if (needs_frame) {
|
||||
save_LR_CR(Rtmp1);
|
||||
push_frame_abi112(0, Rtmp2);
|
||||
push_frame_reg_args(0, Rtmp2);
|
||||
}
|
||||
|
||||
if (Rpre_val->is_volatile() && Robj == noreg) mr(R31, Rpre_val); // Save pre_val across C call if it was preloaded.
|
||||
@ -3006,13 +3057,13 @@ void MacroAssembler::verify_oop(Register oop, const char* msg) {
|
||||
mr(R0, tmp);
|
||||
// kill tmp
|
||||
save_LR_CR(tmp);
|
||||
push_frame_abi112(nbytes_save, tmp);
|
||||
push_frame_reg_args(nbytes_save, tmp);
|
||||
// restore tmp
|
||||
mr(tmp, R0);
|
||||
save_volatile_gprs(R1_SP, 112); // except R0
|
||||
// load FunctionDescriptor**
|
||||
// load FunctionDescriptor** / entry_address *
|
||||
load_const(tmp, fd);
|
||||
// load FunctionDescriptor*
|
||||
// load FunctionDescriptor* / entry_address
|
||||
ld(tmp, 0, tmp);
|
||||
mr(R4_ARG2, oop);
|
||||
load_const(R3_ARG1, (address)msg);
|
||||
|
@ -279,12 +279,12 @@ class MacroAssembler: public Assembler {
|
||||
// Push a frame of size `bytes'. No abi space provided.
|
||||
void push_frame(unsigned int bytes, Register tmp);
|
||||
|
||||
// Push a frame of size `bytes' plus abi112 on top.
|
||||
void push_frame_abi112(unsigned int bytes, Register tmp);
|
||||
// Push a frame of size `bytes' plus abi_reg_args on top.
|
||||
void push_frame_reg_args(unsigned int bytes, Register tmp);
|
||||
|
||||
// Setup up a new C frame with a spill area for non-volatile GPRs and additional
|
||||
// space for local variables
|
||||
void push_frame_abi112_nonvolatiles(unsigned int bytes, Register tmp);
|
||||
void push_frame_reg_args_nonvolatiles(unsigned int bytes, Register tmp);
|
||||
|
||||
// pop current C frame
|
||||
void pop_frame();
|
||||
@ -296,17 +296,31 @@ class MacroAssembler: public Assembler {
|
||||
private:
|
||||
address _last_calls_return_pc;
|
||||
|
||||
#if defined(ABI_ELFv2)
|
||||
// Generic version of a call to C function.
|
||||
// Updates and returns _last_calls_return_pc.
|
||||
address branch_to(Register function_entry, bool and_link);
|
||||
#else
|
||||
// Generic version of a call to C function via a function descriptor
|
||||
// with variable support for C calling conventions (TOC, ENV, etc.).
|
||||
// updates and returns _last_calls_return_pc.
|
||||
address branch_to(Register function_descriptor, bool and_link, bool save_toc_before_call,
|
||||
bool restore_toc_after_call, bool load_toc_of_callee, bool load_env_of_callee);
|
||||
#endif
|
||||
|
||||
public:
|
||||
|
||||
// Get the pc where the last call will return to. returns _last_calls_return_pc.
|
||||
inline address last_calls_return_pc();
|
||||
|
||||
#if defined(ABI_ELFv2)
|
||||
// Call a C function via a function descriptor and use full C
|
||||
// calling conventions. Updates and returns _last_calls_return_pc.
|
||||
address call_c(Register function_entry);
|
||||
// For tail calls: only branch, don't link, so callee returns to caller of this function.
|
||||
address call_c_and_return_to_caller(Register function_entry);
|
||||
address call_c(address function_entry, relocInfo::relocType rt);
|
||||
#else
|
||||
// Call a C function via a function descriptor and use full C
|
||||
// calling conventions. Updates and returns _last_calls_return_pc.
|
||||
address call_c(Register function_descriptor);
|
||||
@ -315,6 +329,7 @@ class MacroAssembler: public Assembler {
|
||||
address call_c(const FunctionDescriptor* function_descriptor, relocInfo::relocType rt);
|
||||
address call_c_using_toc(const FunctionDescriptor* function_descriptor, relocInfo::relocType rt,
|
||||
Register toc);
|
||||
#endif
|
||||
|
||||
protected:
|
||||
|
||||
@ -649,6 +664,11 @@ class MacroAssembler: public Assembler {
|
||||
void _verify_method_ptr(Register reg, const char * msg, const char * file, int line) {}
|
||||
void _verify_klass_ptr(Register reg, const char * msg, const char * file, int line) {}
|
||||
|
||||
// Convenience method returning function entry. For the ELFv1 case
|
||||
// creates function descriptor at the current address and returs
|
||||
// the pointer to it. For the ELFv2 case returns the current address.
|
||||
inline address function_entry();
|
||||
|
||||
#define verify_method_ptr(reg) _verify_method_ptr(reg, "broken method " #reg, __FILE__, __LINE__)
|
||||
#define verify_klass_ptr(reg) _verify_klass_ptr(reg, "broken klass " #reg, __FILE__, __LINE__)
|
||||
|
||||
|
@ -385,4 +385,10 @@ inline void MacroAssembler::trap_range_check_ge(Register a, int si16) {
|
||||
twi(traptoEqual | traptoGreaterThanUnsigned, a/*reg a*/, si16);
|
||||
}
|
||||
|
||||
#if defined(ABI_ELFv2)
|
||||
inline address MacroAssembler::function_entry() { return pc(); }
|
||||
#else
|
||||
inline address MacroAssembler::function_entry() { return emit_fd(); }
|
||||
#endif
|
||||
|
||||
#endif // CPU_PPC_VM_MACROASSEMBLER_PPC_INLINE_HPP
|
||||
|
@ -453,11 +453,11 @@ void trace_method_handle_stub(const char* adaptername,
|
||||
|
||||
if (Verbose) {
|
||||
tty->print_cr("Registers:");
|
||||
const int abi_offset = frame::abi_112_size / 8;
|
||||
const int abi_offset = frame::abi_reg_args_size / 8;
|
||||
for (int i = R3->encoding(); i <= R12->encoding(); i++) {
|
||||
Register r = as_Register(i);
|
||||
int count = i - R3->encoding();
|
||||
// The registers are stored in reverse order on the stack (by save_volatile_gprs(R1_SP, abi_112_size)).
|
||||
// The registers are stored in reverse order on the stack (by save_volatile_gprs(R1_SP, abi_reg_args_size)).
|
||||
tty->print("%3s=" PTR_FORMAT, r->name(), saved_regs[abi_offset + count]);
|
||||
if ((count + 1) % 4 == 0) {
|
||||
tty->cr();
|
||||
@ -524,9 +524,9 @@ void MethodHandles::trace_method_handle(MacroAssembler* _masm, const char* adapt
|
||||
__ save_LR_CR(R0);
|
||||
__ mr(R0, R1_SP); // saved_sp
|
||||
assert(Assembler::is_simm(-nbytes_save, 16), "Overwriting R0");
|
||||
// push_frame_abi112 only uses R0 if nbytes_save is wider than 16 bit
|
||||
__ push_frame_abi112(nbytes_save, R0);
|
||||
__ save_volatile_gprs(R1_SP, frame::abi_112_size); // Except R0.
|
||||
// Push_frame_reg_args only uses R0 if nbytes_save is wider than 16 bit.
|
||||
__ push_frame_reg_args(nbytes_save, R0);
|
||||
__ save_volatile_gprs(R1_SP, frame::abi_reg_args_size); // Except R0.
|
||||
|
||||
__ load_const(R3_ARG1, (address)adaptername);
|
||||
__ mr(R4_ARG2, R23_method_handle);
|
||||
|
@ -1008,7 +1008,11 @@ int MachCallDynamicJavaNode::ret_addr_offset() {
|
||||
}
|
||||
|
||||
int MachCallRuntimeNode::ret_addr_offset() {
|
||||
#if defined(ABI_ELFv2)
|
||||
return 28;
|
||||
#else
|
||||
return 40;
|
||||
#endif
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
@ -3674,6 +3678,10 @@ encode %{
|
||||
MacroAssembler _masm(&cbuf);
|
||||
const address start_pc = __ pc();
|
||||
|
||||
#if defined(ABI_ELFv2)
|
||||
address entry= !($meth$$method) ? NULL : (address)$meth$$method;
|
||||
__ call_c(entry, relocInfo::runtime_call_type);
|
||||
#else
|
||||
// The function we're going to call.
|
||||
FunctionDescriptor fdtemp;
|
||||
const FunctionDescriptor* fd = !($meth$$method) ? &fdtemp : (FunctionDescriptor*)$meth$$method;
|
||||
@ -3684,6 +3692,7 @@ encode %{
|
||||
// Put entry, env, toc into the constant pool, this needs up to 3 constant
|
||||
// pool entries; call_c_using_toc will optimize the call.
|
||||
__ call_c_using_toc(fd, relocInfo::runtime_call_type, Rtoc);
|
||||
#endif
|
||||
|
||||
// Check the ret_addr_offset.
|
||||
assert(((MachCallRuntimeNode*)this)->ret_addr_offset() == __ last_calls_return_pc() - start_pc,
|
||||
@ -3699,20 +3708,25 @@ encode %{
|
||||
__ mtctr($src$$Register);
|
||||
%}
|
||||
|
||||
// postalloc expand emitter for runtime leaf calls.
|
||||
// Postalloc expand emitter for runtime leaf calls.
|
||||
enc_class postalloc_expand_java_to_runtime_call(method meth, iRegLdst toc) %{
|
||||
loadConLNodesTuple loadConLNodes_Entry;
|
||||
#if defined(ABI_ELFv2)
|
||||
jlong entry_address = (jlong) this->entry_point();
|
||||
assert(entry_address, "need address here");
|
||||
loadConLNodes_Entry = loadConLNodesTuple_create(C, ra_, n_toc, new (C) immLOper(entry_address),
|
||||
OptoReg::Name(R12_H_num), OptoReg::Name(R12_num));
|
||||
#else
|
||||
// Get the struct that describes the function we are about to call.
|
||||
FunctionDescriptor* fd = (FunctionDescriptor*) this->entry_point();
|
||||
assert(fd, "need fd here");
|
||||
jlong entry_address = (jlong) fd->entry();
|
||||
// new nodes
|
||||
loadConLNodesTuple loadConLNodes_Entry;
|
||||
loadConLNodesTuple loadConLNodes_Env;
|
||||
loadConLNodesTuple loadConLNodes_Toc;
|
||||
MachNode *mtctr = NULL;
|
||||
MachCallLeafNode *call = NULL;
|
||||
|
||||
// Create nodes and operands for loading the entry point.
|
||||
loadConLNodes_Entry = loadConLNodesTuple_create(C, ra_, n_toc, new (C) immLOper((jlong) fd->entry()),
|
||||
loadConLNodes_Entry = loadConLNodesTuple_create(C, ra_, n_toc, new (C) immLOper(entry_address),
|
||||
OptoReg::Name(R12_H_num), OptoReg::Name(R12_num));
|
||||
|
||||
|
||||
@ -3733,8 +3747,9 @@ encode %{
|
||||
// Create nodes and operands for loading the Toc point.
|
||||
loadConLNodes_Toc = loadConLNodesTuple_create(C, ra_, n_toc, new (C) immLOper((jlong) fd->toc()),
|
||||
OptoReg::Name(R2_H_num), OptoReg::Name(R2_num));
|
||||
#endif // ABI_ELFv2
|
||||
// mtctr node
|
||||
mtctr = new (C) CallLeafDirect_mtctrNode();
|
||||
MachNode *mtctr = new (C) CallLeafDirect_mtctrNode();
|
||||
|
||||
assert(loadConLNodes_Entry._last != NULL, "entry must exist");
|
||||
mtctr->add_req(0, loadConLNodes_Entry._last);
|
||||
@ -3743,10 +3758,10 @@ encode %{
|
||||
mtctr->_opnds[1] = new (C) iRegLdstOper();
|
||||
|
||||
// call node
|
||||
call = new (C) CallLeafDirectNode();
|
||||
MachCallLeafNode *call = new (C) CallLeafDirectNode();
|
||||
|
||||
call->_opnds[0] = _opnds[0];
|
||||
call->_opnds[1] = new (C) methodOper((intptr_t) fd->entry()); // may get set later
|
||||
call->_opnds[1] = new (C) methodOper((intptr_t) entry_address); // May get set later.
|
||||
|
||||
// Make the new call node look like the old one.
|
||||
call->_name = _name;
|
||||
@ -3773,8 +3788,10 @@ encode %{
|
||||
// These must be reqired edges, as the registers are live up to
|
||||
// the call. Else the constants are handled as kills.
|
||||
call->add_req(mtctr);
|
||||
#if !defined(ABI_ELFv2)
|
||||
call->add_req(loadConLNodes_Env._last);
|
||||
call->add_req(loadConLNodes_Toc._last);
|
||||
#endif
|
||||
|
||||
// ...as well as prec
|
||||
for (uint i = req(); i < len(); ++i) {
|
||||
@ -3787,10 +3804,12 @@ encode %{
|
||||
// Insert the new nodes.
|
||||
if (loadConLNodes_Entry._large_hi) nodes->push(loadConLNodes_Entry._large_hi);
|
||||
if (loadConLNodes_Entry._last) nodes->push(loadConLNodes_Entry._last);
|
||||
#if !defined(ABI_ELFv2)
|
||||
if (loadConLNodes_Env._large_hi) nodes->push(loadConLNodes_Env._large_hi);
|
||||
if (loadConLNodes_Env._last) nodes->push(loadConLNodes_Env._last);
|
||||
if (loadConLNodes_Toc._large_hi) nodes->push(loadConLNodes_Toc._large_hi);
|
||||
if (loadConLNodes_Toc._last) nodes->push(loadConLNodes_Toc._last);
|
||||
#endif
|
||||
nodes->push(mtctr);
|
||||
nodes->push(call);
|
||||
%}
|
||||
@ -3837,7 +3856,7 @@ frame %{
|
||||
// out_preserve_stack_slots for calls to C. Supports the var-args
|
||||
// backing area for register parms.
|
||||
//
|
||||
varargs_C_out_slots_killed(((frame::abi_112_size - frame::jit_out_preserve_size) / VMRegImpl::stack_slot_size));
|
||||
varargs_C_out_slots_killed(((frame::abi_reg_args_size - frame::jit_out_preserve_size) / VMRegImpl::stack_slot_size));
|
||||
|
||||
// The after-PROLOG location of the return address. Location of
|
||||
// return address specifies a type (REG or STACK) and a number
|
||||
|
@ -87,7 +87,7 @@ void OptoRuntime::generate_exception_blob() {
|
||||
|
||||
address start = __ pc();
|
||||
|
||||
int frame_size_in_bytes = frame::abi_112_size;
|
||||
int frame_size_in_bytes = frame::abi_reg_args_size;
|
||||
OopMap* map = new OopMap(frame_size_in_bytes / sizeof(jint), 0);
|
||||
|
||||
// Exception pc is 'return address' for stack walker.
|
||||
@ -99,7 +99,7 @@ void OptoRuntime::generate_exception_blob() {
|
||||
|
||||
// Save callee-saved registers.
|
||||
// Push a C frame for the exception blob. It is needed for the C call later on.
|
||||
__ push_frame_abi112(0, R11_scratch1);
|
||||
__ push_frame_reg_args(0, R11_scratch1);
|
||||
|
||||
// This call does all the hard work. It checks if an exception handler
|
||||
// exists in the method.
|
||||
@ -109,8 +109,12 @@ void OptoRuntime::generate_exception_blob() {
|
||||
__ set_last_Java_frame(/*sp=*/R1_SP, noreg);
|
||||
|
||||
__ mr(R3_ARG1, R16_thread);
|
||||
#if defined(ABI_ELFv2)
|
||||
__ call_c((address) OptoRuntime::handle_exception_C, relocInfo::none);
|
||||
#else
|
||||
__ call_c(CAST_FROM_FN_PTR(FunctionDescriptor*, OptoRuntime::handle_exception_C),
|
||||
relocInfo::none);
|
||||
#endif
|
||||
address calls_return_pc = __ last_calls_return_pc();
|
||||
# ifdef ASSERT
|
||||
__ cmpdi(CCR0, R3_RET, 0);
|
||||
@ -162,7 +166,11 @@ void OptoRuntime::generate_exception_blob() {
|
||||
__ bind(mh_callsite);
|
||||
__ mr(R31, R3_RET); // Save branch address.
|
||||
__ mr(R3_ARG1, R16_thread);
|
||||
#if defined(ABI_ELFv2)
|
||||
__ call_c((address) adjust_SP_for_methodhandle_callsite, relocInfo::none);
|
||||
#else
|
||||
__ call_c(CAST_FROM_FN_PTR(FunctionDescriptor*, adjust_SP_for_methodhandle_callsite), relocInfo::none);
|
||||
#endif
|
||||
// Returns unextended_sp in R3_RET.
|
||||
|
||||
__ mtctr(R31); // Move address of exception handler to SR_CTR.
|
||||
|
@ -67,7 +67,7 @@ class RegisterSaver {
|
||||
return_pc_is_thread_saved_exception_pc
|
||||
};
|
||||
|
||||
static OopMap* push_frame_abi112_and_save_live_registers(MacroAssembler* masm,
|
||||
static OopMap* push_frame_reg_args_and_save_live_registers(MacroAssembler* masm,
|
||||
int* out_frame_size_in_bytes,
|
||||
bool generate_oop_map,
|
||||
int return_pc_adjustment,
|
||||
@ -200,12 +200,12 @@ static const RegisterSaver::LiveRegType RegisterSaver_LiveRegs[] = {
|
||||
RegisterSaver_LiveIntReg( R30 ), // r30 must be the last register
|
||||
};
|
||||
|
||||
OopMap* RegisterSaver::push_frame_abi112_and_save_live_registers(MacroAssembler* masm,
|
||||
OopMap* RegisterSaver::push_frame_reg_args_and_save_live_registers(MacroAssembler* masm,
|
||||
int* out_frame_size_in_bytes,
|
||||
bool generate_oop_map,
|
||||
int return_pc_adjustment,
|
||||
ReturnPCLocation return_pc_location) {
|
||||
// Push an abi112-frame and store all registers which may be live.
|
||||
// Push an abi_reg_args-frame and store all registers which may be live.
|
||||
// If requested, create an OopMap: Record volatile registers as
|
||||
// callee-save values in an OopMap so their save locations will be
|
||||
// propagated to the RegisterMap of the caller frame during
|
||||
@ -221,7 +221,7 @@ OopMap* RegisterSaver::push_frame_abi112_and_save_live_registers(MacroAssembler*
|
||||
sizeof(RegisterSaver::LiveRegType);
|
||||
const int register_save_size = regstosave_num * reg_size;
|
||||
const int frame_size_in_bytes = round_to(register_save_size, frame::alignment_in_bytes)
|
||||
+ frame::abi_112_size;
|
||||
+ frame::abi_reg_args_size;
|
||||
*out_frame_size_in_bytes = frame_size_in_bytes;
|
||||
const int frame_size_in_slots = frame_size_in_bytes / sizeof(jint);
|
||||
const int register_save_offset = frame_size_in_bytes - register_save_size;
|
||||
@ -229,7 +229,7 @@ OopMap* RegisterSaver::push_frame_abi112_and_save_live_registers(MacroAssembler*
|
||||
// OopMap frame size is in c2 stack slots (sizeof(jint)) not bytes or words.
|
||||
OopMap* map = generate_oop_map ? new OopMap(frame_size_in_slots, 0) : NULL;
|
||||
|
||||
BLOCK_COMMENT("push_frame_abi112_and_save_live_registers {");
|
||||
BLOCK_COMMENT("push_frame_reg_args_and_save_live_registers {");
|
||||
|
||||
// Save r30 in the last slot of the not yet pushed frame so that we
|
||||
// can use it as scratch reg.
|
||||
@ -294,7 +294,7 @@ OopMap* RegisterSaver::push_frame_abi112_and_save_live_registers(MacroAssembler*
|
||||
offset += reg_size;
|
||||
}
|
||||
|
||||
BLOCK_COMMENT("} push_frame_abi112_and_save_live_registers");
|
||||
BLOCK_COMMENT("} push_frame_reg_args_and_save_live_registers");
|
||||
|
||||
// And we're done.
|
||||
return map;
|
||||
@ -699,15 +699,19 @@ int SharedRuntime::c_calling_convention(const BasicType *sig_bt,
|
||||
|
||||
int i;
|
||||
VMReg reg;
|
||||
// Leave room for C-compatible ABI_112.
|
||||
int stk = (frame::abi_112_size - frame::jit_out_preserve_size) / VMRegImpl::stack_slot_size;
|
||||
// Leave room for C-compatible ABI_REG_ARGS.
|
||||
int stk = (frame::abi_reg_args_size - frame::jit_out_preserve_size) / VMRegImpl::stack_slot_size;
|
||||
int arg = 0;
|
||||
int freg = 0;
|
||||
|
||||
// Avoid passing C arguments in the wrong stack slots.
|
||||
#if defined(ABI_ELFv2)
|
||||
assert((SharedRuntime::out_preserve_stack_slots() + stk) * VMRegImpl::stack_slot_size == 96,
|
||||
"passing C arguments in wrong stack slots");
|
||||
#else
|
||||
assert((SharedRuntime::out_preserve_stack_slots() + stk) * VMRegImpl::stack_slot_size == 112,
|
||||
"passing C arguments in wrong stack slots");
|
||||
|
||||
#endif
|
||||
// We fill-out regs AND regs2 if an argument must be passed in a
|
||||
// register AND in a stack slot. If regs2 is NULL in such a
|
||||
// situation, we bail-out with a fatal error.
|
||||
@ -1504,7 +1508,11 @@ static void check_needs_gc_for_critical_native(MacroAssembler* masm,
|
||||
|
||||
__ block_comment("block_for_jni_critical");
|
||||
address entry_point = CAST_FROM_FN_PTR(address, SharedRuntime::block_for_jni_critical);
|
||||
#if defined(ABI_ELFv2)
|
||||
__ call_c(entry_point, relocInfo::runtime_call_type);
|
||||
#else
|
||||
__ call_c(CAST_FROM_FN_PTR(FunctionDescriptor*, entry_point), relocInfo::runtime_call_type);
|
||||
#endif
|
||||
address start = __ pc() - __ offset(),
|
||||
calls_return_pc = __ last_calls_return_pc();
|
||||
oop_maps->add_gc_map(calls_return_pc - start, map);
|
||||
@ -1877,7 +1885,7 @@ nmethod *SharedRuntime::generate_native_wrapper(MacroAssembler *masm,
|
||||
// Layout of the native wrapper frame:
|
||||
// (stack grows upwards, memory grows downwards)
|
||||
//
|
||||
// NW [ABI_112] <-- 1) R1_SP
|
||||
// NW [ABI_REG_ARGS] <-- 1) R1_SP
|
||||
// [outgoing arguments] <-- 2) R1_SP + out_arg_slot_offset
|
||||
// [oopHandle area] <-- 3) R1_SP + oop_handle_offset (save area for critical natives)
|
||||
// klass <-- 4) R1_SP + klass_offset
|
||||
@ -2211,8 +2219,8 @@ nmethod *SharedRuntime::generate_native_wrapper(MacroAssembler *masm,
|
||||
// slow case of monitor enter. Inline a special case of call_VM that
|
||||
// disallows any pending_exception.
|
||||
|
||||
// Save argument registers and leave room for C-compatible ABI_112.
|
||||
int frame_size = frame::abi_112_size +
|
||||
// Save argument registers and leave room for C-compatible ABI_REG_ARGS.
|
||||
int frame_size = frame::abi_reg_args_size +
|
||||
round_to(total_c_args * wordSize, frame::alignment_in_bytes);
|
||||
__ mr(R11_scratch1, R1_SP);
|
||||
RegisterSaver::push_frame_and_save_argument_registers(masm, R12_scratch2, frame_size, total_c_args, out_regs, out_regs2);
|
||||
@ -2250,9 +2258,12 @@ nmethod *SharedRuntime::generate_native_wrapper(MacroAssembler *masm,
|
||||
|
||||
// The JNI call
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
#if defined(ABI_ELFv2)
|
||||
__ call_c(native_func, relocInfo::runtime_call_type);
|
||||
#else
|
||||
FunctionDescriptor* fd_native_method = (FunctionDescriptor*) native_func;
|
||||
__ call_c(fd_native_method, relocInfo::runtime_call_type);
|
||||
#endif
|
||||
|
||||
|
||||
// Now, we are back from the native code.
|
||||
@ -2724,7 +2735,7 @@ void SharedRuntime::generate_deopt_blob() {
|
||||
OopMapSet *oop_maps = new OopMapSet();
|
||||
|
||||
// size of ABI112 plus spill slots for R3_RET and F1_RET.
|
||||
const int frame_size_in_bytes = frame::abi_112_spill_size;
|
||||
const int frame_size_in_bytes = frame::abi_reg_args_spill_size;
|
||||
const int frame_size_in_slots = frame_size_in_bytes / sizeof(jint);
|
||||
int first_frame_size_in_bytes = 0; // frame size of "unpack frame" for call to fetch_unroll_info.
|
||||
|
||||
@ -2757,11 +2768,11 @@ void SharedRuntime::generate_deopt_blob() {
|
||||
|
||||
// Push the "unpack frame"
|
||||
// Save everything in sight.
|
||||
map = RegisterSaver::push_frame_abi112_and_save_live_registers(masm,
|
||||
&first_frame_size_in_bytes,
|
||||
/*generate_oop_map=*/ true,
|
||||
return_pc_adjustment_no_exception,
|
||||
RegisterSaver::return_pc_is_lr);
|
||||
map = RegisterSaver::push_frame_reg_args_and_save_live_registers(masm,
|
||||
&first_frame_size_in_bytes,
|
||||
/*generate_oop_map=*/ true,
|
||||
return_pc_adjustment_no_exception,
|
||||
RegisterSaver::return_pc_is_lr);
|
||||
assert(map != NULL, "OopMap must have been created");
|
||||
|
||||
__ li(exec_mode_reg, Deoptimization::Unpack_deopt);
|
||||
@ -2787,11 +2798,11 @@ void SharedRuntime::generate_deopt_blob() {
|
||||
// Push the "unpack frame".
|
||||
// Save everything in sight.
|
||||
assert(R4 == R4_ARG2, "exception pc must be in r4");
|
||||
RegisterSaver::push_frame_abi112_and_save_live_registers(masm,
|
||||
&first_frame_size_in_bytes,
|
||||
/*generate_oop_map=*/ false,
|
||||
return_pc_adjustment_exception,
|
||||
RegisterSaver::return_pc_is_r4);
|
||||
RegisterSaver::push_frame_reg_args_and_save_live_registers(masm,
|
||||
&first_frame_size_in_bytes,
|
||||
/*generate_oop_map=*/ false,
|
||||
return_pc_adjustment_exception,
|
||||
RegisterSaver::return_pc_is_r4);
|
||||
|
||||
// Deopt during an exception. Save exec mode for unpack_frames.
|
||||
__ li(exec_mode_reg, Deoptimization::Unpack_exception);
|
||||
@ -2876,8 +2887,8 @@ void SharedRuntime::generate_deopt_blob() {
|
||||
// ...).
|
||||
|
||||
// Spill live volatile registers since we'll do a call.
|
||||
__ std( R3_RET, _abi_112_spill(spill_ret), R1_SP);
|
||||
__ stfd(F1_RET, _abi_112_spill(spill_fret), R1_SP);
|
||||
__ std( R3_RET, _abi_reg_args_spill(spill_ret), R1_SP);
|
||||
__ stfd(F1_RET, _abi_reg_args_spill(spill_fret), R1_SP);
|
||||
|
||||
// Let the unpacker layout information in the skeletal frames just
|
||||
// allocated.
|
||||
@ -2889,8 +2900,8 @@ void SharedRuntime::generate_deopt_blob() {
|
||||
__ reset_last_Java_frame();
|
||||
|
||||
// Restore the volatiles saved above.
|
||||
__ ld( R3_RET, _abi_112_spill(spill_ret), R1_SP);
|
||||
__ lfd(F1_RET, _abi_112_spill(spill_fret), R1_SP);
|
||||
__ ld( R3_RET, _abi_reg_args_spill(spill_ret), R1_SP);
|
||||
__ lfd(F1_RET, _abi_reg_args_spill(spill_fret), R1_SP);
|
||||
|
||||
// Pop the unpack frame.
|
||||
__ pop_frame();
|
||||
@ -2930,7 +2941,7 @@ void SharedRuntime::generate_uncommon_trap_blob() {
|
||||
Register unc_trap_reg = R23_tmp3;
|
||||
|
||||
OopMapSet* oop_maps = new OopMapSet();
|
||||
int frame_size_in_bytes = frame::abi_112_size;
|
||||
int frame_size_in_bytes = frame::abi_reg_args_size;
|
||||
OopMap* map = new OopMap(frame_size_in_bytes / sizeof(jint), 0);
|
||||
|
||||
// stack: (deoptee, optional i2c, caller_of_deoptee, ...).
|
||||
@ -2943,7 +2954,7 @@ void SharedRuntime::generate_uncommon_trap_blob() {
|
||||
__ save_LR_CR(R11_scratch1);
|
||||
|
||||
// Push an "uncommon_trap" frame.
|
||||
__ push_frame_abi112(0, R11_scratch1);
|
||||
__ push_frame_reg_args(0, R11_scratch1);
|
||||
|
||||
// stack: (unpack frame, deoptee, optional i2c, caller_of_deoptee, ...).
|
||||
|
||||
@ -2996,7 +3007,7 @@ void SharedRuntime::generate_uncommon_trap_blob() {
|
||||
// interpreter frames just created.
|
||||
|
||||
// Push a simple "unpack frame" here.
|
||||
__ push_frame_abi112(0, R11_scratch1);
|
||||
__ push_frame_reg_args(0, R11_scratch1);
|
||||
|
||||
// stack: (unpack frame, skeletal interpreter frame, ..., optional
|
||||
// skeletal interpreter frame, optional c2i, caller of deoptee,
|
||||
@ -3064,11 +3075,11 @@ SafepointBlob* SharedRuntime::generate_handler_blob(address call_ptr, int poll_t
|
||||
}
|
||||
|
||||
// Save registers, fpu state, and flags.
|
||||
map = RegisterSaver::push_frame_abi112_and_save_live_registers(masm,
|
||||
&frame_size_in_bytes,
|
||||
/*generate_oop_map=*/ true,
|
||||
/*return_pc_adjustment=*/0,
|
||||
return_pc_location);
|
||||
map = RegisterSaver::push_frame_reg_args_and_save_live_registers(masm,
|
||||
&frame_size_in_bytes,
|
||||
/*generate_oop_map=*/ true,
|
||||
/*return_pc_adjustment=*/0,
|
||||
return_pc_location);
|
||||
|
||||
// The following is basically a call_VM. However, we need the precise
|
||||
// address of the call in order to generate an oopmap. Hence, we do all the
|
||||
@ -3151,11 +3162,11 @@ RuntimeStub* SharedRuntime::generate_resolve_blob(address destination, const cha
|
||||
|
||||
address start = __ pc();
|
||||
|
||||
map = RegisterSaver::push_frame_abi112_and_save_live_registers(masm,
|
||||
&frame_size_in_bytes,
|
||||
/*generate_oop_map*/ true,
|
||||
/*return_pc_adjustment*/ 0,
|
||||
RegisterSaver::return_pc_is_lr);
|
||||
map = RegisterSaver::push_frame_reg_args_and_save_live_registers(masm,
|
||||
&frame_size_in_bytes,
|
||||
/*generate_oop_map*/ true,
|
||||
/*return_pc_adjustment*/ 0,
|
||||
RegisterSaver::return_pc_is_lr);
|
||||
|
||||
// Use noreg as last_Java_pc, the return pc will be reconstructed
|
||||
// from the physical frame.
|
||||
|
@ -79,11 +79,11 @@ class StubGenerator: public StubCodeGenerator {
|
||||
|
||||
StubCodeMark mark(this, "StubRoutines", "call_stub");
|
||||
|
||||
address start = __ emit_fd();
|
||||
address start = __ function_entry();
|
||||
|
||||
// some sanity checks
|
||||
assert((sizeof(frame::abi_48) % 16) == 0, "unaligned");
|
||||
assert((sizeof(frame::abi_112) % 16) == 0, "unaligned");
|
||||
assert((sizeof(frame::abi_minframe) % 16) == 0, "unaligned");
|
||||
assert((sizeof(frame::abi_reg_args) % 16) == 0, "unaligned");
|
||||
assert((sizeof(frame::spill_nonvolatiles) % 16) == 0, "unaligned");
|
||||
assert((sizeof(frame::parent_ijava_frame_abi) % 16) == 0, "unaligned");
|
||||
assert((sizeof(frame::entry_frame_locals) % 16) == 0, "unaligned");
|
||||
@ -444,7 +444,7 @@ class StubGenerator: public StubCodeGenerator {
|
||||
|
||||
// Save LR/CR and copy exception pc (LR) into R4_ARG2.
|
||||
__ save_LR_CR(R4_ARG2);
|
||||
__ push_frame_abi112(0, R0);
|
||||
__ push_frame_reg_args(0, R0);
|
||||
// Find exception handler.
|
||||
__ call_VM_leaf(CAST_FROM_FN_PTR(address,
|
||||
SharedRuntime::exception_handler_for_return_address),
|
||||
@ -519,7 +519,7 @@ class StubGenerator: public StubCodeGenerator {
|
||||
MacroAssembler* masm = new MacroAssembler(&code);
|
||||
|
||||
OopMapSet* oop_maps = new OopMapSet();
|
||||
int frame_size_in_bytes = frame::abi_112_size;
|
||||
int frame_size_in_bytes = frame::abi_reg_args_size;
|
||||
OopMap* map = new OopMap(frame_size_in_bytes / sizeof(jint), 0);
|
||||
|
||||
StubCodeMark mark(this, "StubRoutines", "throw_exception");
|
||||
@ -529,7 +529,7 @@ class StubGenerator: public StubCodeGenerator {
|
||||
__ save_LR_CR(R11_scratch1);
|
||||
|
||||
// Push a frame.
|
||||
__ push_frame_abi112(0, R11_scratch1);
|
||||
__ push_frame_reg_args(0, R11_scratch1);
|
||||
|
||||
address frame_complete_pc = __ pc();
|
||||
|
||||
@ -551,8 +551,11 @@ class StubGenerator: public StubCodeGenerator {
|
||||
if (arg2 != noreg) {
|
||||
__ mr(R5_ARG3, arg2);
|
||||
}
|
||||
__ call_c(CAST_FROM_FN_PTR(FunctionDescriptor*, runtime_entry),
|
||||
relocInfo::none);
|
||||
#if defined(ABI_ELFv2)
|
||||
__ call_c(runtime_entry, relocInfo::none);
|
||||
#else
|
||||
__ call_c(CAST_FROM_FN_PTR(FunctionDescriptor*, runtime_entry), relocInfo::none);
|
||||
#endif
|
||||
|
||||
// Set an oopmap for the call site.
|
||||
oop_maps->add_gc_map((int)(gc_map_pc - start), map);
|
||||
@ -614,7 +617,7 @@ class StubGenerator: public StubCodeGenerator {
|
||||
// With G1, don't generate the call if we statically know that the target in uninitialized
|
||||
if (!dest_uninitialized) {
|
||||
const int spill_slots = 4 * wordSize;
|
||||
const int frame_size = frame::abi_112_size + spill_slots;
|
||||
const int frame_size = frame::abi_reg_args_size + spill_slots;
|
||||
Label filtered;
|
||||
|
||||
// Is marking active?
|
||||
@ -628,7 +631,7 @@ class StubGenerator: public StubCodeGenerator {
|
||||
__ beq(CCR0, filtered);
|
||||
|
||||
__ save_LR_CR(R0);
|
||||
__ push_frame_abi112(spill_slots, R0);
|
||||
__ push_frame_reg_args(spill_slots, R0);
|
||||
__ std(from, frame_size - 1 * wordSize, R1_SP);
|
||||
__ std(to, frame_size - 2 * wordSize, R1_SP);
|
||||
__ std(count, frame_size - 3 * wordSize, R1_SP);
|
||||
@ -672,7 +675,7 @@ class StubGenerator: public StubCodeGenerator {
|
||||
if (branchToEnd) {
|
||||
__ save_LR_CR(R0);
|
||||
// We need this frame only to spill LR.
|
||||
__ push_frame_abi112(0, R0);
|
||||
__ push_frame_reg_args(0, R0);
|
||||
__ call_VM_leaf(CAST_FROM_FN_PTR(address, BarrierSet::static_write_ref_array_post), addr, count);
|
||||
__ pop_frame();
|
||||
__ restore_LR_CR(R0);
|
||||
@ -742,7 +745,7 @@ class StubGenerator: public StubCodeGenerator {
|
||||
StubCodeMark mark(this, "StubRoutines", "zero_words_aligned8");
|
||||
|
||||
// Implemented as in ClearArray.
|
||||
address start = __ emit_fd();
|
||||
address start = __ function_entry();
|
||||
|
||||
Register base_ptr_reg = R3_ARG1; // tohw (needs to be 8b aligned)
|
||||
Register cnt_dwords_reg = R4_ARG2; // count (in dwords)
|
||||
@ -820,7 +823,7 @@ class StubGenerator: public StubCodeGenerator {
|
||||
//
|
||||
address generate_handler_for_unsafe_access() {
|
||||
StubCodeMark mark(this, "StubRoutines", "handler_for_unsafe_access");
|
||||
address start = __ emit_fd();
|
||||
address start = __ function_entry();
|
||||
__ unimplemented("StubRoutines::handler_for_unsafe_access", 93);
|
||||
return start;
|
||||
}
|
||||
@ -861,7 +864,7 @@ class StubGenerator: public StubCodeGenerator {
|
||||
// to read from the safepoint polling page.
|
||||
address generate_load_from_poll() {
|
||||
StubCodeMark mark(this, "StubRoutines", "generate_load_from_poll");
|
||||
address start = __ emit_fd();
|
||||
address start = __ function_entry();
|
||||
__ unimplemented("StubRoutines::verify_oop", 95); // TODO PPC port
|
||||
return start;
|
||||
}
|
||||
@ -885,7 +888,7 @@ class StubGenerator: public StubCodeGenerator {
|
||||
//
|
||||
address generate_fill(BasicType t, bool aligned, const char* name) {
|
||||
StubCodeMark mark(this, "StubRoutines", name);
|
||||
address start = __ emit_fd();
|
||||
address start = __ function_entry();
|
||||
|
||||
const Register to = R3_ARG1; // source array address
|
||||
const Register value = R4_ARG2; // fill value
|
||||
@ -1123,7 +1126,7 @@ class StubGenerator: public StubCodeGenerator {
|
||||
//
|
||||
address generate_disjoint_byte_copy(bool aligned, const char * name) {
|
||||
StubCodeMark mark(this, "StubRoutines", name);
|
||||
address start = __ emit_fd();
|
||||
address start = __ function_entry();
|
||||
|
||||
Register tmp1 = R6_ARG4;
|
||||
Register tmp2 = R7_ARG5;
|
||||
@ -1254,15 +1257,21 @@ class StubGenerator: public StubCodeGenerator {
|
||||
//
|
||||
address generate_conjoint_byte_copy(bool aligned, const char * name) {
|
||||
StubCodeMark mark(this, "StubRoutines", name);
|
||||
address start = __ emit_fd();
|
||||
address start = __ function_entry();
|
||||
|
||||
Register tmp1 = R6_ARG4;
|
||||
Register tmp2 = R7_ARG5;
|
||||
Register tmp3 = R8_ARG6;
|
||||
|
||||
#if defined(ABI_ELFv2)
|
||||
address nooverlap_target = aligned ?
|
||||
StubRoutines::arrayof_jbyte_disjoint_arraycopy() :
|
||||
StubRoutines::jbyte_disjoint_arraycopy();
|
||||
#else
|
||||
address nooverlap_target = aligned ?
|
||||
((FunctionDescriptor*)StubRoutines::arrayof_jbyte_disjoint_arraycopy())->entry() :
|
||||
((FunctionDescriptor*)StubRoutines::jbyte_disjoint_arraycopy())->entry();
|
||||
#endif
|
||||
|
||||
array_overlap_test(nooverlap_target, 0);
|
||||
// Do reverse copy. We assume the case of actual overlap is rare enough
|
||||
@ -1345,7 +1354,7 @@ class StubGenerator: public StubCodeGenerator {
|
||||
Register tmp3 = R8_ARG6;
|
||||
Register tmp4 = R9_ARG7;
|
||||
|
||||
address start = __ emit_fd();
|
||||
address start = __ function_entry();
|
||||
|
||||
Label l_1, l_2, l_3, l_4, l_5, l_6, l_7, l_8;
|
||||
// don't try anything fancy if arrays don't have many elements
|
||||
@ -1474,15 +1483,21 @@ class StubGenerator: public StubCodeGenerator {
|
||||
//
|
||||
address generate_conjoint_short_copy(bool aligned, const char * name) {
|
||||
StubCodeMark mark(this, "StubRoutines", name);
|
||||
address start = __ emit_fd();
|
||||
address start = __ function_entry();
|
||||
|
||||
Register tmp1 = R6_ARG4;
|
||||
Register tmp2 = R7_ARG5;
|
||||
Register tmp3 = R8_ARG6;
|
||||
|
||||
#if defined(ABI_ELFv2)
|
||||
address nooverlap_target = aligned ?
|
||||
StubRoutines::arrayof_jshort_disjoint_arraycopy() :
|
||||
StubRoutines::jshort_disjoint_arraycopy();
|
||||
#else
|
||||
address nooverlap_target = aligned ?
|
||||
((FunctionDescriptor*)StubRoutines::arrayof_jshort_disjoint_arraycopy())->entry() :
|
||||
((FunctionDescriptor*)StubRoutines::jshort_disjoint_arraycopy())->entry();
|
||||
#endif
|
||||
|
||||
array_overlap_test(nooverlap_target, 1);
|
||||
|
||||
@ -1597,7 +1612,7 @@ class StubGenerator: public StubCodeGenerator {
|
||||
//
|
||||
address generate_disjoint_int_copy(bool aligned, const char * name) {
|
||||
StubCodeMark mark(this, "StubRoutines", name);
|
||||
address start = __ emit_fd();
|
||||
address start = __ function_entry();
|
||||
generate_disjoint_int_copy_core(aligned);
|
||||
__ blr();
|
||||
return start;
|
||||
@ -1681,11 +1696,17 @@ class StubGenerator: public StubCodeGenerator {
|
||||
//
|
||||
address generate_conjoint_int_copy(bool aligned, const char * name) {
|
||||
StubCodeMark mark(this, "StubRoutines", name);
|
||||
address start = __ emit_fd();
|
||||
address start = __ function_entry();
|
||||
|
||||
#if defined(ABI_ELFv2)
|
||||
address nooverlap_target = aligned ?
|
||||
StubRoutines::arrayof_jint_disjoint_arraycopy() :
|
||||
StubRoutines::jint_disjoint_arraycopy();
|
||||
#else
|
||||
address nooverlap_target = aligned ?
|
||||
((FunctionDescriptor*)StubRoutines::arrayof_jint_disjoint_arraycopy())->entry() :
|
||||
((FunctionDescriptor*)StubRoutines::jint_disjoint_arraycopy())->entry();
|
||||
#endif
|
||||
|
||||
array_overlap_test(nooverlap_target, 2);
|
||||
|
||||
@ -1767,7 +1788,7 @@ class StubGenerator: public StubCodeGenerator {
|
||||
//
|
||||
address generate_disjoint_long_copy(bool aligned, const char * name) {
|
||||
StubCodeMark mark(this, "StubRoutines", name);
|
||||
address start = __ emit_fd();
|
||||
address start = __ function_entry();
|
||||
generate_disjoint_long_copy_core(aligned);
|
||||
__ blr();
|
||||
|
||||
@ -1849,11 +1870,17 @@ class StubGenerator: public StubCodeGenerator {
|
||||
//
|
||||
address generate_conjoint_long_copy(bool aligned, const char * name) {
|
||||
StubCodeMark mark(this, "StubRoutines", name);
|
||||
address start = __ emit_fd();
|
||||
address start = __ function_entry();
|
||||
|
||||
#if defined(ABI_ELFv2)
|
||||
address nooverlap_target = aligned ?
|
||||
StubRoutines::arrayof_jlong_disjoint_arraycopy() :
|
||||
StubRoutines::jlong_disjoint_arraycopy();
|
||||
#else
|
||||
address nooverlap_target = aligned ?
|
||||
((FunctionDescriptor*)StubRoutines::arrayof_jlong_disjoint_arraycopy())->entry() :
|
||||
((FunctionDescriptor*)StubRoutines::jlong_disjoint_arraycopy())->entry();
|
||||
#endif
|
||||
|
||||
array_overlap_test(nooverlap_target, 3);
|
||||
generate_conjoint_long_copy_core(aligned);
|
||||
@ -1875,11 +1902,17 @@ class StubGenerator: public StubCodeGenerator {
|
||||
address generate_conjoint_oop_copy(bool aligned, const char * name, bool dest_uninitialized) {
|
||||
StubCodeMark mark(this, "StubRoutines", name);
|
||||
|
||||
address start = __ emit_fd();
|
||||
address start = __ function_entry();
|
||||
|
||||
#if defined(ABI_ELFv2)
|
||||
address nooverlap_target = aligned ?
|
||||
StubRoutines::arrayof_oop_disjoint_arraycopy() :
|
||||
StubRoutines::oop_disjoint_arraycopy();
|
||||
#else
|
||||
address nooverlap_target = aligned ?
|
||||
((FunctionDescriptor*)StubRoutines::arrayof_oop_disjoint_arraycopy())->entry() :
|
||||
((FunctionDescriptor*)StubRoutines::oop_disjoint_arraycopy())->entry();
|
||||
#endif
|
||||
|
||||
gen_write_ref_array_pre_barrier(R3_ARG1, R4_ARG2, R5_ARG3, dest_uninitialized, R9_ARG7);
|
||||
|
||||
@ -1910,7 +1943,7 @@ class StubGenerator: public StubCodeGenerator {
|
||||
//
|
||||
address generate_disjoint_oop_copy(bool aligned, const char * name, bool dest_uninitialized) {
|
||||
StubCodeMark mark(this, "StubRoutines", name);
|
||||
address start = __ emit_fd();
|
||||
address start = __ function_entry();
|
||||
|
||||
gen_write_ref_array_pre_barrier(R3_ARG1, R4_ARG2, R5_ARG3, dest_uninitialized, R9_ARG7);
|
||||
|
||||
@ -1991,7 +2024,7 @@ class StubGenerator: public StubCodeGenerator {
|
||||
StubCodeMark mark(this, "StubRoutines", name);
|
||||
|
||||
// Entry point, pc or function descriptor.
|
||||
*entry = __ emit_fd();
|
||||
*entry = __ function_entry();
|
||||
|
||||
// Load *adr into R4_ARG2, may fault.
|
||||
*fault_pc = __ pc();
|
||||
|
@ -24,7 +24,8 @@
|
||||
*/
|
||||
|
||||
#include "precompiled.hpp"
|
||||
#include "assembler_ppc.inline.hpp"
|
||||
#include "asm/assembler.inline.hpp"
|
||||
#include "asm/macroAssembler.inline.hpp"
|
||||
#include "compiler/disassembler.hpp"
|
||||
#include "memory/resourceArea.hpp"
|
||||
#include "runtime/java.hpp"
|
||||
@ -168,7 +169,7 @@ void VM_Version::determine_section_size() {
|
||||
|
||||
uint32_t *code = (uint32_t *)a->pc();
|
||||
// Emit code.
|
||||
void (*test1)() = (void(*)())(void *)a->emit_fd();
|
||||
void (*test1)() = (void(*)())(void *)a->function_entry();
|
||||
|
||||
Label l1;
|
||||
|
||||
@ -242,7 +243,7 @@ void VM_Version::determine_section_size() {
|
||||
a->blr();
|
||||
|
||||
// Emit code.
|
||||
void (*test2)() = (void(*)())(void *)a->emit_fd();
|
||||
void (*test2)() = (void(*)())(void *)a->function_entry();
|
||||
// uint32_t *code = (uint32_t *)a->pc();
|
||||
|
||||
Label l2;
|
||||
@ -383,8 +384,12 @@ void VM_Version::determine_section_size() {
|
||||
#endif // COMPILER2
|
||||
|
||||
void VM_Version::determine_features() {
|
||||
#if defined(ABI_ELFv2)
|
||||
const int code_size = (num_features+1+2*7)*BytesPerInstWord; // TODO(asmundak): calculation is incorrect.
|
||||
#else
|
||||
// 7 InstWords for each call (function descriptor + blr instruction).
|
||||
const int code_size = (num_features+1+2*7)*BytesPerInstWord;
|
||||
#endif
|
||||
int features = 0;
|
||||
|
||||
// create test area
|
||||
@ -398,7 +403,7 @@ void VM_Version::determine_features() {
|
||||
MacroAssembler* a = new MacroAssembler(&cb);
|
||||
|
||||
// Emit code.
|
||||
void (*test)(address addr, uint64_t offset)=(void(*)(address addr, uint64_t offset))(void *)a->emit_fd();
|
||||
void (*test)(address addr, uint64_t offset)=(void(*)(address addr, uint64_t offset))(void *)a->function_entry();
|
||||
uint32_t *code = (uint32_t *)a->pc();
|
||||
// Don't use R0 in ldarx.
|
||||
// Keep R3_ARG1 unmodified, it contains &field (see below).
|
||||
@ -415,7 +420,7 @@ void VM_Version::determine_features() {
|
||||
a->blr();
|
||||
|
||||
// Emit function to set one cache line to zero. Emit function descriptor and get pointer to it.
|
||||
void (*zero_cacheline_func_ptr)(char*) = (void(*)(char*))(void *)a->emit_fd();
|
||||
void (*zero_cacheline_func_ptr)(char*) = (void(*)(char*))(void *)a->function_entry();
|
||||
a->dcbz(R3_ARG1); // R3_ARG1 = addr
|
||||
a->blr();
|
||||
|
||||
|
@ -140,7 +140,7 @@ bool ElfFile::load_tables() {
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(PPC64)
|
||||
#if defined(PPC64) && !defined(ABI_ELFv2)
|
||||
// Now read the .opd section wich contains the PPC64 function descriptor table.
|
||||
// The .opd section is only available on PPC64 (see for example:
|
||||
// http://refspecs.linuxfoundation.org/LSB_3.1.1/LSB-Core-PPC64/LSB-Core-PPC64/specialsections.html)
|
||||
|
Loading…
Reference in New Issue
Block a user