8288971: AArch64: Clean up stack and register handling in interpreter

Reviewed-by: adinn, ngasson
This commit is contained in:
Andrew Haley 2022-07-04 13:26:54 +00:00
parent d53b02eb9f
commit b5d965656d
15 changed files with 132 additions and 104 deletions

View File

@ -90,7 +90,7 @@ int AbstractInterpreter::size_activation(int max_stack,
// for the callee's params we only need to account for the extra // for the callee's params we only need to account for the extra
// locals. // locals.
int size = overhead + int size = overhead +
(callee_locals - callee_params) + (callee_locals - callee_params) * Interpreter::stackElementWords +
monitors * frame::interpreter_frame_monitor_size() + monitors * frame::interpreter_frame_monitor_size() +
// On the top frame, at all times SP <= ESP, and SP is // On the top frame, at all times SP <= ESP, and SP is
// 16-aligned. We ensure this by adjusting SP on method // 16-aligned. We ensure this by adjusting SP on method
@ -135,7 +135,7 @@ void AbstractInterpreter::layout_activation(Method* method,
// NOTE the difference in using sender_sp and // NOTE the difference in using sender_sp and
// interpreter_frame_sender_sp interpreter_frame_sender_sp is // interpreter_frame_sender_sp interpreter_frame_sender_sp is
// the original sp of the caller (the unextended_sp) and // the original sp of the caller (the unextended_sp) and
// sender_sp is fp+8/16 (32bit/64bit) XXX // sender_sp is fp+16
// //
// The interpreted method entry on AArch64 aligns SP to 16 bytes // The interpreted method entry on AArch64 aligns SP to 16 bytes
// before generating the fixed part of the activation frame. So there // before generating the fixed part of the activation frame. So there
@ -165,6 +165,19 @@ void AbstractInterpreter::layout_activation(Method* method,
popframe_extra_args; popframe_extra_args;
interpreter_frame->interpreter_frame_set_last_sp(esp); interpreter_frame->interpreter_frame_set_last_sp(esp);
// We have to add extra reserved slots to max_stack. There are 3 users of the extra slots,
// none of which are at the same time, so we just need to make sure there is enough room
// for the biggest user:
// -reserved slot for exception handler
// -reserved slots for JSR292. Method::extra_stack_entries() is the size.
// -reserved slots for TraceBytecodes
int max_stack = method->constMethod()->max_stack() + MAX2(3, Method::extra_stack_entries());
intptr_t* extended_sp = (intptr_t*) monbot -
(max_stack * Interpreter::stackElementWords) -
popframe_extra_args;
extended_sp = align_down(extended_sp, StackAlignmentInBytes);
interpreter_frame->interpreter_frame_set_extended_sp(extended_sp);
// All frames but the initial (oldest) interpreter frame we fill in have // All frames but the initial (oldest) interpreter frame we fill in have
// a value for sender_sp that allows walking the stack but isn't // a value for sender_sp that allows walking the stack but isn't
// truly correct. Correct the value here. // truly correct. Correct the value here.

View File

@ -31,7 +31,7 @@
#include "memory/resourceArea.hpp" #include "memory/resourceArea.hpp"
#ifndef PRODUCT #ifndef PRODUCT
const uintptr_t Assembler::asm_bp = 0x00007fffee09ac88; const uintptr_t Assembler::asm_bp = 0x0000ffffac221240;
#endif #endif
static float unpack(unsigned value); static float unpack(unsigned value);

View File

@ -142,16 +142,18 @@ REGISTER_DECLARATION(Register, rthread, r28);
REGISTER_DECLARATION(Register, rheapbase, r27); REGISTER_DECLARATION(Register, rheapbase, r27);
// constant pool cache // constant pool cache
REGISTER_DECLARATION(Register, rcpool, r26); REGISTER_DECLARATION(Register, rcpool, r26);
// monitors allocated on stack // r25 is a callee-saved temp
REGISTER_DECLARATION(Register, rmonitors, r25); // REGISTER_DECLARATION(Register, unused, r25);
// locals on stack // locals on stack
REGISTER_DECLARATION(Register, rlocals, r24); REGISTER_DECLARATION(Register, rlocals, r24);
// bytecode pointer // bytecode pointer
REGISTER_DECLARATION(Register, rbcp, r22); REGISTER_DECLARATION(Register, rbcp, r22);
// Dispatch table base // Dispatch table base
REGISTER_DECLARATION(Register, rdispatch, r21); REGISTER_DECLARATION(Register, rdispatch, r21);
// Java stack pointer // Java expression stack pointer
REGISTER_DECLARATION(Register, esp, r20); REGISTER_DECLARATION(Register, esp, r20);
// Sender's SP while in interpreter
REGISTER_DECLARATION(Register, r19_sender_sp, r19);
// Preserved predicate register with all elements set TRUE. // Preserved predicate register with all elements set TRUE.
REGISTER_DECLARATION(PRegister, ptrue, p7); REGISTER_DECLARATION(PRegister, ptrue, p7);

View File

@ -354,6 +354,11 @@ void frame::interpreter_frame_set_last_sp(intptr_t* sp) {
*((intptr_t**)addr_at(interpreter_frame_last_sp_offset)) = sp; *((intptr_t**)addr_at(interpreter_frame_last_sp_offset)) = sp;
} }
// Used by template based interpreter deoptimization
void frame::interpreter_frame_set_extended_sp(intptr_t* sp) {
*((intptr_t**)addr_at(interpreter_frame_extended_sp_offset)) = sp;
}
frame frame::sender_for_entry_frame(RegisterMap* map) const { frame frame::sender_for_entry_frame(RegisterMap* map) const {
assert(map != NULL, "map must be set"); assert(map != NULL, "map must be set");
// Java frame called from C; skip all C frames and return top C // Java frame called from C; skip all C frames and return top C
@ -599,6 +604,7 @@ void frame::describe_pd(FrameValues& values, int frame_no) {
DESCRIBE_FP_OFFSET(interpreter_frame_last_sp); DESCRIBE_FP_OFFSET(interpreter_frame_last_sp);
DESCRIBE_FP_OFFSET(interpreter_frame_method); DESCRIBE_FP_OFFSET(interpreter_frame_method);
DESCRIBE_FP_OFFSET(interpreter_frame_mdp); DESCRIBE_FP_OFFSET(interpreter_frame_mdp);
DESCRIBE_FP_OFFSET(interpreter_frame_extended_sp);
DESCRIBE_FP_OFFSET(interpreter_frame_mirror); DESCRIBE_FP_OFFSET(interpreter_frame_mirror);
DESCRIBE_FP_OFFSET(interpreter_frame_cache); DESCRIBE_FP_OFFSET(interpreter_frame_cache);
DESCRIBE_FP_OFFSET(interpreter_frame_locals); DESCRIBE_FP_OFFSET(interpreter_frame_locals);
@ -670,6 +676,8 @@ void internal_pf(uintptr_t sp, uintptr_t fp, uintptr_t pc, uintptr_t bcx) {
DESCRIBE_FP_OFFSET(interpreter_frame_last_sp); DESCRIBE_FP_OFFSET(interpreter_frame_last_sp);
DESCRIBE_FP_OFFSET(interpreter_frame_method); DESCRIBE_FP_OFFSET(interpreter_frame_method);
DESCRIBE_FP_OFFSET(interpreter_frame_mdp); DESCRIBE_FP_OFFSET(interpreter_frame_mdp);
DESCRIBE_FP_OFFSET(interpreter_frame_extended_sp);
DESCRIBE_FP_OFFSET(interpreter_frame_mirror);
DESCRIBE_FP_OFFSET(interpreter_frame_cache); DESCRIBE_FP_OFFSET(interpreter_frame_cache);
DESCRIBE_FP_OFFSET(interpreter_frame_locals); DESCRIBE_FP_OFFSET(interpreter_frame_locals);
DESCRIBE_FP_OFFSET(interpreter_frame_bcp); DESCRIBE_FP_OFFSET(interpreter_frame_bcp);
@ -772,4 +780,3 @@ void JavaFrameAnchor::make_walkable() {
_last_Java_pc = (address)_last_Java_sp[-1]; _last_Java_pc = (address)_last_Java_sp[-1];
vmassert(walkable(), "something went wrong"); vmassert(walkable(), "something went wrong");
} }

View File

@ -47,13 +47,13 @@
// [constant pool cache ] = cache() cache_offset // [constant pool cache ] = cache() cache_offset
// [klass of method ] = mirror() mirror_offset // [klass of method ] = mirror() mirror_offset
// [padding ] // [extended SP ] extended_sp offset
// [methodData ] = mdp() mdx_offset // [methodData ] = mdp() mdx_offset
// [Method ] = method() method_offset // [Method ] = method() method_offset
// [last esp ] = last_sp() last_sp_offset // [last esp ] = last_sp() last_sp_offset
// [old stack pointer ] (sender_sp) sender_sp_offset // [sender's SP ] (sender_sp) sender_sp_offset
// [old frame pointer ] <- fp = link() // [old frame pointer ] <- fp = link()
// [return pc ] // [return pc ]
@ -82,8 +82,8 @@
interpreter_frame_last_sp_offset = interpreter_frame_sender_sp_offset - 1, interpreter_frame_last_sp_offset = interpreter_frame_sender_sp_offset - 1,
interpreter_frame_method_offset = interpreter_frame_last_sp_offset - 1, interpreter_frame_method_offset = interpreter_frame_last_sp_offset - 1,
interpreter_frame_mdp_offset = interpreter_frame_method_offset - 1, interpreter_frame_mdp_offset = interpreter_frame_method_offset - 1,
interpreter_frame_padding_offset = interpreter_frame_mdp_offset - 1, interpreter_frame_extended_sp_offset = interpreter_frame_mdp_offset - 1,
interpreter_frame_mirror_offset = interpreter_frame_padding_offset - 1, interpreter_frame_mirror_offset = interpreter_frame_extended_sp_offset - 1,
interpreter_frame_cache_offset = interpreter_frame_mirror_offset - 1, interpreter_frame_cache_offset = interpreter_frame_mirror_offset - 1,
interpreter_frame_locals_offset = interpreter_frame_cache_offset - 1, interpreter_frame_locals_offset = interpreter_frame_cache_offset - 1,
interpreter_frame_bcp_offset = interpreter_frame_locals_offset - 1, interpreter_frame_bcp_offset = interpreter_frame_locals_offset - 1,
@ -182,6 +182,8 @@
// expression stack tos if we are nested in a java call // expression stack tos if we are nested in a java call
intptr_t* interpreter_frame_last_sp() const; intptr_t* interpreter_frame_last_sp() const;
void interpreter_frame_set_extended_sp(intptr_t* sp);
template <typename RegisterMapT> template <typename RegisterMapT>
static void update_map_with_saved_link(RegisterMapT* map, intptr_t** link_addr); static void update_map_with_saved_link(RegisterMapT* map, intptr_t** link_addr);

View File

@ -421,7 +421,7 @@ void InterpreterMacroAssembler::load_double(Address src) {
void InterpreterMacroAssembler::prepare_to_jump_from_interpreted() { void InterpreterMacroAssembler::prepare_to_jump_from_interpreted() {
// set sender sp // set sender sp
mov(r13, sp); mov(r19_sender_sp, sp);
// record last_sp // record last_sp
str(esp, Address(rfp, frame::interpreter_frame_last_sp_offset * wordSize)); str(esp, Address(rfp, frame::interpreter_frame_last_sp_offset * wordSize));
} }

View File

@ -82,6 +82,31 @@ class InterpreterMacroAssembler: public MacroAssembler {
ldr(rcpool, Address(rfp, frame::interpreter_frame_cache_offset * wordSize)); ldr(rcpool, Address(rfp, frame::interpreter_frame_cache_offset * wordSize));
} }
void restore_sp_after_call() {
Label L;
ldr(rscratch1, Address(rfp, frame::interpreter_frame_extended_sp_offset * wordSize));
#ifdef ASSERT
cbnz(rscratch1, L);
stop("SP is null");
#endif
bind(L);
mov(sp, rscratch1);
}
void check_extended_sp(const char* msg = "check extended SP") {
#ifdef ASSERT
Label L;
ldr(rscratch1, Address(rfp, frame::interpreter_frame_extended_sp_offset * wordSize));
cmp(sp, rscratch1);
br(EQ, L);
stop(msg);
bind(L);
#endif
}
#define check_extended_sp() \
check_extended_sp("SP does not match extended SP in frame at " __FILE__ ":" XSTR(__LINE__))
void get_dispatch(); void get_dispatch();
// Helpers for runtime call arguments/results // Helpers for runtime call arguments/results

View File

@ -185,7 +185,7 @@ address MethodHandles::generate_method_handle_interpreter_entry(MacroAssembler*
return NULL; return NULL;
} }
// r13: sender SP (must preserve; see prepare_to_jump_from_interpreted) // r19_sender_sp: sender SP (must preserve; see prepare_to_jump_from_interpreted)
// rmethod: Method* // rmethod: Method*
// r3: argument locator (parameter slot count, added to rsp) // r3: argument locator (parameter slot count, added to rsp)
// r1: used as temp to hold mh or receiver // r1: used as temp to hold mh or receiver
@ -283,7 +283,7 @@ void MethodHandles::generate_method_handle_dispatch(MacroAssembler* _masm,
// temps used in this code are not used in *either* compiled or interpreted calling sequences // temps used in this code are not used in *either* compiled or interpreted calling sequences
Register temp1 = r10; Register temp1 = r10;
Register temp2 = r11; Register temp2 = r11;
Register temp3 = r14; // r13 is live by this point: it contains the sender SP Register temp3 = r14;
if (for_compiler_entry) { if (for_compiler_entry) {
assert(receiver_reg == (iid == vmIntrinsics::_linkToStatic || iid == vmIntrinsics::_linkToNative ? noreg : j_rarg0), "only valid assignment"); assert(receiver_reg == (iid == vmIntrinsics::_linkToStatic || iid == vmIntrinsics::_linkToNative ? noreg : j_rarg0), "only valid assignment");
assert_different_registers(temp1, j_rarg0, j_rarg1, j_rarg2, j_rarg3, j_rarg4, j_rarg5, j_rarg6, j_rarg7); assert_different_registers(temp1, j_rarg0, j_rarg1, j_rarg2, j_rarg3, j_rarg4, j_rarg5, j_rarg6, j_rarg7);
@ -356,7 +356,7 @@ void MethodHandles::generate_method_handle_dispatch(MacroAssembler* _masm,
// Live registers at this point: // Live registers at this point:
// member_reg - MemberName that was the trailing argument // member_reg - MemberName that was the trailing argument
// temp1_recv_klass - klass of stacked receiver, if needed // temp1_recv_klass - klass of stacked receiver, if needed
// r13 - interpreter linkage (if interpreted) ??? FIXME // r19 - interpreter linkage (if interpreted)
// r1 ... r0 - compiler arguments (if compiled) // r1 ... r0 - compiler arguments (if compiled)
Label L_incompatible_class_change_error; Label L_incompatible_class_change_error;
@ -443,7 +443,7 @@ void MethodHandles::generate_method_handle_dispatch(MacroAssembler* _masm,
break; break;
} }
// live at this point: rmethod, r13 (if interpreted) // live at this point: rmethod, r19_sender_sp (if interpreted)
// After figuring out which concrete method to call, jump into it. // After figuring out which concrete method to call, jump into it.
// Note that this works in the interpreter with no data motion. // Note that this works in the interpreter with no data motion.

View File

@ -44,11 +44,9 @@ const int ConcreteRegisterImpl::max_pr
const char* RegisterImpl::name() const { const char* RegisterImpl::name() const {
static const char *const names[number_of_registers] = { static const char *const names[number_of_registers] = {
"c_rarg0", "c_rarg1", "c_rarg2", "c_rarg3", "c_rarg4", "c_rarg5", "c_rarg6", "c_rarg7", "c_rarg0", "c_rarg1", "c_rarg2", "c_rarg3", "c_rarg4", "c_rarg5", "c_rarg6", "c_rarg7",
"rscratch1", "rscratch2", "rscratch1", "rscratch2", "r10", "r11", "r12", "r13", "r14", "r15",
"r10", "r11", "r12", "r13", "r14", "r15", "r16", "r16", "r17", "r18_tls", "r19", "resp", "rdispatch", "rbcp", "r23",
"r17", "r18_tls", "r19", "rlocals", "r25", "rcpool", "rheapbase", "rthread", "rfp", "lr", "sp"
"resp", "rdispatch", "rbcp", "r23", "rlocals", "rmonitors", "rcpool", "rheapbase",
"rthread", "rfp", "lr", "sp"
}; };
return is_valid() ? names[encoding()] : "noreg"; return is_valid() ? names[encoding()] : "noreg";
} }

View File

@ -435,7 +435,7 @@ static void gen_c2i_adapter(MacroAssembler *masm,
int extraspace = total_args_passed * Interpreter::stackElementSize; int extraspace = total_args_passed * Interpreter::stackElementSize;
__ mov(r13, sp); __ mov(r19_sender_sp, sp);
// stack is aligned, keep it that way // stack is aligned, keep it that way
extraspace = align_up(extraspace, 2*wordSize); extraspace = align_up(extraspace, 2*wordSize);
@ -552,12 +552,10 @@ void SharedRuntime::gen_i2c_adapter(MacroAssembler *masm,
const BasicType *sig_bt, const BasicType *sig_bt,
const VMRegPair *regs) { const VMRegPair *regs) {
// Note: r13 contains the senderSP on entry. We must preserve it since // Note: r19_sender_sp contains the senderSP on entry. We must
// we may do a i2c -> c2i transition if we lose a race where compiled // preserve it since we may do a i2c -> c2i transition if we lose a
// code goes non-entrant while we get args ready. // race where compiled code goes non-entrant while we get args
// ready.
// In addition we use r13 to locate all the interpreter args because
// we must align the stack to 16 bytes.
// Adapters are frameless. // Adapters are frameless.

View File

@ -298,9 +298,9 @@ class StubGenerator: public StubCodeGenerator {
// call Java entry -- passing methdoOop, and current sp // call Java entry -- passing methdoOop, and current sp
// rmethod: Method* // rmethod: Method*
// r13: sender sp // r19_sender_sp: sender sp
BLOCK_COMMENT("call Java function"); BLOCK_COMMENT("call Java function");
__ mov(r13, sp); __ mov(r19_sender_sp, sp);
__ blr(c_rarg4); __ blr(c_rarg4);
// we do this here because the notify will already have been done // we do this here because the notify will already have been done

View File

@ -146,7 +146,7 @@ address TemplateInterpreterGenerator::generate_slow_signature_handler() {
address TemplateInterpreterGenerator::generate_math_entry(AbstractInterpreter::MethodKind kind) { address TemplateInterpreterGenerator::generate_math_entry(AbstractInterpreter::MethodKind kind) {
// rmethod: Method* // rmethod: Method*
// r13: sender sp // r19_sender_sp: sender sp
// esp: args // esp: args
if (!InlineIntrinsics) return NULL; // Generate a vanilla entry if (!InlineIntrinsics) return NULL; // Generate a vanilla entry
@ -174,13 +174,13 @@ address TemplateInterpreterGenerator::generate_math_entry(AbstractInterpreter::M
entry_point = __ pc(); entry_point = __ pc();
__ ldrd(v0, Address(esp)); __ ldrd(v0, Address(esp));
__ fabsd(v0, v0); __ fabsd(v0, v0);
__ mov(sp, r13); // Restore caller's SP __ mov(sp, r19_sender_sp); // Restore caller's SP
break; break;
case Interpreter::java_lang_math_sqrt: case Interpreter::java_lang_math_sqrt:
entry_point = __ pc(); entry_point = __ pc();
__ ldrd(v0, Address(esp)); __ ldrd(v0, Address(esp));
__ fsqrtd(v0, v0); __ fsqrtd(v0, v0);
__ mov(sp, r13); __ mov(sp, r19_sender_sp);
break; break;
case Interpreter::java_lang_math_sin : case Interpreter::java_lang_math_sin :
case Interpreter::java_lang_math_cos : case Interpreter::java_lang_math_cos :
@ -190,18 +190,18 @@ address TemplateInterpreterGenerator::generate_math_entry(AbstractInterpreter::M
case Interpreter::java_lang_math_exp : case Interpreter::java_lang_math_exp :
entry_point = __ pc(); entry_point = __ pc();
__ ldrd(v0, Address(esp)); __ ldrd(v0, Address(esp));
__ mov(sp, r13); __ mov(sp, r19_sender_sp);
__ mov(r19, lr); __ mov(r23, lr);
continuation = r19; // The first callee-saved register continuation = r23; // The first free callee-saved register
generate_transcendental_entry(kind, 1); generate_transcendental_entry(kind, 1);
break; break;
case Interpreter::java_lang_math_pow : case Interpreter::java_lang_math_pow :
entry_point = __ pc(); entry_point = __ pc();
__ mov(r19, lr); __ mov(r23, lr);
continuation = r19; continuation = r23;
__ ldrd(v0, Address(esp, 2 * Interpreter::stackElementSize)); __ ldrd(v0, Address(esp, 2 * Interpreter::stackElementSize));
__ ldrd(v1, Address(esp)); __ ldrd(v1, Address(esp));
__ mov(sp, r13); __ mov(sp, r19_sender_sp);
generate_transcendental_entry(kind, 2); generate_transcendental_entry(kind, 2);
break; break;
case Interpreter::java_lang_math_fmaD : case Interpreter::java_lang_math_fmaD :
@ -211,7 +211,7 @@ address TemplateInterpreterGenerator::generate_math_entry(AbstractInterpreter::M
__ ldrd(v1, Address(esp, 2 * Interpreter::stackElementSize)); __ ldrd(v1, Address(esp, 2 * Interpreter::stackElementSize));
__ ldrd(v2, Address(esp)); __ ldrd(v2, Address(esp));
__ fmaddd(v0, v0, v1, v2); __ fmaddd(v0, v0, v1, v2);
__ mov(sp, r13); // Restore caller's SP __ mov(sp, r19_sender_sp); // Restore caller's SP
} }
break; break;
case Interpreter::java_lang_math_fmaF : case Interpreter::java_lang_math_fmaF :
@ -221,7 +221,7 @@ address TemplateInterpreterGenerator::generate_math_entry(AbstractInterpreter::M
__ ldrs(v1, Address(esp, Interpreter::stackElementSize)); __ ldrs(v1, Address(esp, Interpreter::stackElementSize));
__ ldrs(v2, Address(esp)); __ ldrs(v2, Address(esp));
__ fmadds(v0, v0, v1, v2); __ fmadds(v0, v0, v1, v2);
__ mov(sp, r13); // Restore caller's SP __ mov(sp, r19_sender_sp); // Restore caller's SP
} }
break; break;
default: default:
@ -307,7 +307,7 @@ void TemplateInterpreterGenerator::generate_transcendental_entry(AbstractInterpr
// Attempt to execute abstract method. Throw exception // Attempt to execute abstract method. Throw exception
address TemplateInterpreterGenerator::generate_abstract_entry(void) { address TemplateInterpreterGenerator::generate_abstract_entry(void) {
// rmethod: Method* // rmethod: Method*
// r13: sender SP // r19_sender_sp: sender SP
address entry_point = __ pc(); address entry_point = __ pc();
@ -458,13 +458,7 @@ address TemplateInterpreterGenerator::generate_return_entry_for(TosState state,
__ add(esp, esp, r1, Assembler::LSL, 3); __ add(esp, esp, r1, Assembler::LSL, 3);
// Restore machine SP // Restore machine SP
__ ldr(rscratch1, Address(rmethod, Method::const_offset())); __ restore_sp_after_call();
__ ldrh(rscratch1, Address(rscratch1, ConstMethod::max_stack_offset()));
__ add(rscratch1, rscratch1, frame::interpreter_frame_monitor_size() + 2);
__ ldr(rscratch2,
Address(rfp, frame::interpreter_frame_initial_sp_offset * wordSize));
__ sub(rscratch1, rscratch2, rscratch1, ext::uxtw, 3);
__ andr(sp, rscratch1, -16);
__ check_and_handle_popframe(rthread); __ check_and_handle_popframe(rthread);
__ check_and_handle_earlyret(rthread); __ check_and_handle_earlyret(rthread);
@ -485,14 +479,7 @@ address TemplateInterpreterGenerator::generate_deopt_entry_for(TosState state,
__ get_method(rmethod); __ get_method(rmethod);
__ get_dispatch(); __ get_dispatch();
// Calculate stack limit __ restore_sp_after_call(); // Restore SP to extended SP
__ ldr(rscratch1, Address(rmethod, Method::const_offset()));
__ ldrh(rscratch1, Address(rscratch1, ConstMethod::max_stack_offset()));
__ add(rscratch1, rscratch1, frame::interpreter_frame_monitor_size() + 2);
__ ldr(rscratch2,
Address(rfp, frame::interpreter_frame_initial_sp_offset * wordSize));
__ sub(rscratch1, rscratch2, rscratch1, ext::uxtx, 3);
__ andr(sp, rscratch1, -16);
// Restore expression stack pointer // Restore expression stack pointer
__ ldr(esp, Address(rfp, frame::interpreter_frame_last_sp_offset * wordSize)); __ ldr(esp, Address(rfp, frame::interpreter_frame_last_sp_offset * wordSize));
@ -715,9 +702,9 @@ void TemplateInterpreterGenerator::generate_stack_overflow_check(void) {
// was in the caller. This is not strictly necessary, but unless we // was in the caller. This is not strictly necessary, but unless we
// do so the stack frame may have a garbage FP; this ensures a // do so the stack frame may have a garbage FP; this ensures a
// correct call stack that we can always unwind. The ANDR should be // correct call stack that we can always unwind. The ANDR should be
// unnecessary because the sender SP in r13 is always aligned, but // unnecessary because the sender SP in r19 is always aligned, but
// it doesn't hurt. // it doesn't hurt.
__ andr(sp, r13, -16); __ andr(sp, r19_sender_sp, -16);
// Note: the restored frame is not necessarily interpreted. // Note: the restored frame is not necessarily interpreted.
// Use the shared runtime version of the StackOverflowError. // Use the shared runtime version of the StackOverflowError.
@ -780,10 +767,12 @@ void TemplateInterpreterGenerator::lock_method() {
} }
// add space for monitor & lock // add space for monitor & lock
__ check_extended_sp();
__ sub(sp, sp, entry_size); // add space for a monitor entry __ sub(sp, sp, entry_size); // add space for a monitor entry
__ sub(esp, esp, entry_size); __ sub(esp, esp, entry_size);
__ mov(rscratch1, esp); __ mov(rscratch1, sp);
__ str(rscratch1, monitor_block_top); // set new monitor block top __ str(rscratch1, Address(rfp, frame::interpreter_frame_extended_sp_offset * wordSize));
__ str(esp, monitor_block_top); // set new monitor block top
// store object // store object
__ str(r0, Address(esp, BasicObjectLock::obj_offset_in_bytes())); __ str(r0, Address(esp, BasicObjectLock::obj_offset_in_bytes()));
__ mov(c_rarg1, esp); // object address __ mov(c_rarg1, esp); // object address
@ -810,7 +799,7 @@ void TemplateInterpreterGenerator::generate_fixed_frame(bool native_call) {
__ stp(zr, zr, Address(sp, 12 * wordSize)); __ stp(zr, zr, Address(sp, 12 * wordSize));
} else { } else {
__ sub(esp, sp, 12 * wordSize); __ sub(esp, sp, 12 * wordSize);
__ ldr(rscratch1, Address(rmethod, Method::const_offset())); // get ConstMethod __ ldr(rscratch1, Address(rmethod, Method::const_offset())); // get ConstMethod
__ add(rbcp, rscratch1, in_bytes(ConstMethod::codes_offset())); // get codebase __ add(rbcp, rscratch1, in_bytes(ConstMethod::codes_offset())); // get codebase
__ stp(esp, rbcp, Address(__ pre(sp, -12 * wordSize))); __ stp(esp, rbcp, Address(__ pre(sp, -12 * wordSize)));
} }
@ -823,13 +812,9 @@ void TemplateInterpreterGenerator::generate_fixed_frame(bool native_call) {
__ bind(method_data_continue); __ bind(method_data_continue);
__ stp(rscratch1, rmethod, Address(sp, 6 * wordSize)); // save Method* and mdp (method data pointer) __ stp(rscratch1, rmethod, Address(sp, 6 * wordSize)); // save Method* and mdp (method data pointer)
} else { } else {
__ stp(zr, rmethod, Address(sp, 6 * wordSize)); // save Method* (no mdp) __ stp(zr, rmethod, Address(sp, 6 * wordSize)); // save Method* (no mdp)
} }
// Get mirror and store it in the frame as GC root for this Method*
__ load_mirror(r10, rmethod);
__ stp(r10, zr, Address(sp, 4 * wordSize));
__ ldr(rcpool, Address(rmethod, Method::const_offset())); __ ldr(rcpool, Address(rmethod, Method::const_offset()));
__ ldr(rcpool, Address(rcpool, ConstMethod::constants_offset())); __ ldr(rcpool, Address(rcpool, ConstMethod::constants_offset()));
__ ldr(rcpool, Address(rcpool, ConstantPool::cache_offset_in_bytes())); __ ldr(rcpool, Address(rcpool, ConstantPool::cache_offset_in_bytes()));
@ -841,15 +826,23 @@ void TemplateInterpreterGenerator::generate_fixed_frame(bool native_call) {
// set sender sp // set sender sp
// leave last_sp as null // leave last_sp as null
__ stp(zr, r13, Address(sp, 8 * wordSize)); __ stp(zr, r19_sender_sp, Address(sp, 8 * wordSize));
// Move SP out of the way // Get mirror
__ load_mirror(r10, rmethod);
if (! native_call) { if (! native_call) {
__ ldr(rscratch1, Address(rmethod, Method::const_offset())); __ ldr(rscratch1, Address(rmethod, Method::const_offset()));
__ ldrh(rscratch1, Address(rscratch1, ConstMethod::max_stack_offset())); __ ldrh(rscratch1, Address(rscratch1, ConstMethod::max_stack_offset()));
__ add(rscratch1, rscratch1, frame::interpreter_frame_monitor_size() + 2); __ add(rscratch1, rscratch1, MAX2(3, Method::extra_stack_entries()));
__ sub(rscratch1, sp, rscratch1, ext::uxtw, 3); __ sub(rscratch1, sp, rscratch1, ext::uxtw, 3);
__ andr(sp, rscratch1, -16); __ andr(rscratch1, rscratch1, -16);
// Store extended SP and mirror
__ stp(r10, rscratch1, Address(sp, 4 * wordSize));
// Move SP out of the way
__ mov(sp, rscratch1);
} else {
__ mov(rscratch1, sp);
__ stp(zr, rscratch1, Address(sp, 4 * wordSize));
} }
} }
@ -900,7 +893,7 @@ address TemplateInterpreterGenerator::generate_Reference_get_entry(void) {
// This code is based on generate_accessor_entry. // This code is based on generate_accessor_entry.
// //
// rmethod: Method* // rmethod: Method*
// r13: senderSP must preserve for slow path, set SP to it on fast path // r19_sender_sp: senderSP must preserve for slow path, set SP to it on fast path
// LR is live. It must be saved around calls. // LR is live. It must be saved around calls.
@ -915,15 +908,13 @@ address TemplateInterpreterGenerator::generate_Reference_get_entry(void) {
__ ldr(local_0, Address(esp, 0)); __ ldr(local_0, Address(esp, 0));
__ cbz(local_0, slow_path); __ cbz(local_0, slow_path);
__ mov(r19, r13); // Move senderSP to a callee-saved register
// Load the value of the referent field. // Load the value of the referent field.
const Address field_address(local_0, referent_offset); const Address field_address(local_0, referent_offset);
BarrierSetAssembler *bs = BarrierSet::barrier_set()->barrier_set_assembler(); BarrierSetAssembler *bs = BarrierSet::barrier_set()->barrier_set_assembler();
bs->load_at(_masm, IN_HEAP | ON_WEAK_OOP_REF, T_OBJECT, local_0, field_address, /*tmp1*/ rscratch2, /*tmp2*/ rscratch1); bs->load_at(_masm, IN_HEAP | ON_WEAK_OOP_REF, T_OBJECT, local_0, field_address, /*tmp1*/ rscratch2, /*tmp2*/ rscratch1);
// areturn // areturn
__ andr(sp, r19, -16); // done with stack __ andr(sp, r19_sender_sp, -16); // done with stack
__ ret(lr); __ ret(lr);
// generate a vanilla interpreter entry as the slow path // generate a vanilla interpreter entry as the slow path
@ -942,7 +933,7 @@ address TemplateInterpreterGenerator::generate_CRC32_update_entry() {
address entry = __ pc(); address entry = __ pc();
// rmethod: Method* // rmethod: Method*
// r13: senderSP must preserved for slow path // r19_sender_sp: senderSP must preserved for slow path
// esp: args // esp: args
Label slow_path; Label slow_path;
@ -971,7 +962,7 @@ address TemplateInterpreterGenerator::generate_CRC32_update_entry() {
// result in c_rarg0 // result in c_rarg0
__ andr(sp, r13, -16); __ andr(sp, r19_sender_sp, -16);
__ ret(lr); __ ret(lr);
// generate a vanilla native entry as the slow path // generate a vanilla native entry as the slow path
@ -992,7 +983,7 @@ address TemplateInterpreterGenerator::generate_CRC32_updateBytes_entry(AbstractI
address entry = __ pc(); address entry = __ pc();
// rmethod,: Method* // rmethod,: Method*
// r13: senderSP must preserved for slow path // r19_sender_sp: senderSP must preserved for slow path
Label slow_path; Label slow_path;
// If we need a safepoint check, generate full interpreter entry. // If we need a safepoint check, generate full interpreter entry.
@ -1024,7 +1015,7 @@ address TemplateInterpreterGenerator::generate_CRC32_updateBytes_entry(AbstractI
// Can now load 'len' since we're finished with 'off' // Can now load 'len' since we're finished with 'off'
__ ldrw(len, Address(esp, 0x0)); // Length __ ldrw(len, Address(esp, 0x0)); // Length
__ andr(sp, r13, -16); // Restore the caller's SP __ andr(sp, r19_sender_sp, -16); // Restore the caller's SP
// We are frameless so we can just jump to the stub. // We are frameless so we can just jump to the stub.
__ b(CAST_FROM_FN_PTR(address, StubRoutines::updateBytesCRC32())); __ b(CAST_FROM_FN_PTR(address, StubRoutines::updateBytesCRC32()));
@ -1068,7 +1059,7 @@ address TemplateInterpreterGenerator::generate_CRC32C_updateBytes_entry(Abstract
__ ldrw(crc, Address(esp, 3*wordSize)); // long crc __ ldrw(crc, Address(esp, 3*wordSize)); // long crc
} }
__ andr(sp, r13, -16); // Restore the caller's SP __ andr(sp, r19_sender_sp, -16); // Restore the caller's SP
// Jump to the stub. // Jump to the stub.
__ b(CAST_FROM_FN_PTR(address, StubRoutines::updateBytesCRC32C())); __ b(CAST_FROM_FN_PTR(address, StubRoutines::updateBytesCRC32C()));
@ -1234,7 +1225,7 @@ address TemplateInterpreterGenerator::generate_native_entry(bool synchronized) {
__ ldr(rscratch1, monitor_block_top); __ ldr(rscratch1, monitor_block_top);
__ cmp(esp, rscratch1); __ cmp(esp, rscratch1);
__ br(Assembler::EQ, L); __ br(Assembler::EQ, L);
__ stop("broken stack frame setup in interpreter"); __ stop("broken stack frame setup in interpreter 1");
__ bind(L); __ bind(L);
} }
#endif #endif
@ -1532,7 +1523,7 @@ address TemplateInterpreterGenerator::generate_native_entry(bool synchronized) {
// remove frame anchor // remove frame anchor
__ leave(); __ leave();
// resture sender sp // restore sender sp
__ mov(sp, esp); __ mov(sp, esp);
__ ret(lr); __ ret(lr);
@ -1685,7 +1676,7 @@ address TemplateInterpreterGenerator::generate_normal_entry(bool synchronized) {
__ ldr(rscratch1, monitor_block_top); __ ldr(rscratch1, monitor_block_top);
__ cmp(esp, rscratch1); __ cmp(esp, rscratch1);
__ br(Assembler::EQ, L); __ br(Assembler::EQ, L);
__ stop("broken stack frame setup in interpreter"); __ stop("broken stack frame setup in interpreter 2");
__ bind(L); __ bind(L);
} }
#endif #endif
@ -1743,14 +1734,8 @@ void TemplateInterpreterGenerator::generate_throw_exception() {
InterpreterRuntime::exception_handler_for_exception), InterpreterRuntime::exception_handler_for_exception),
c_rarg1); c_rarg1);
// Calculate stack limit // Restore machine SP
__ ldr(rscratch1, Address(rmethod, Method::const_offset())); __ restore_sp_after_call();
__ ldrh(rscratch1, Address(rscratch1, ConstMethod::max_stack_offset()));
__ add(rscratch1, rscratch1, frame::interpreter_frame_monitor_size() + 4);
__ ldr(rscratch2,
Address(rfp, frame::interpreter_frame_initial_sp_offset * wordSize));
__ sub(rscratch1, rscratch2, rscratch1, ext::uxtx, 3);
__ andr(sp, rscratch1, -16);
// r0: exception handler entry point // r0: exception handler entry point
// r3: preserved exception oop // r3: preserved exception oop
@ -1879,13 +1864,7 @@ void TemplateInterpreterGenerator::generate_throw_exception() {
#endif // INCLUDE_JVMTI #endif // INCLUDE_JVMTI
// Restore machine SP // Restore machine SP
__ ldr(rscratch1, Address(rmethod, Method::const_offset())); __ restore_sp_after_call();
__ ldrh(rscratch1, Address(rscratch1, ConstMethod::max_stack_offset()));
__ add(rscratch1, rscratch1, frame::interpreter_frame_monitor_size() + 4);
__ ldr(rscratch2,
Address(rfp, frame::interpreter_frame_initial_sp_offset * wordSize));
__ sub(rscratch1, rscratch2, rscratch1, ext::uxtw, 3);
__ andr(sp, rscratch1, -16);
__ dispatch_next(vtos); __ dispatch_next(vtos);
// end of PopFrame support // end of PopFrame support

View File

@ -3827,14 +3827,18 @@ void TemplateTable::monitorenter()
{ {
Label entry, loop; Label entry, loop;
// 1. compute new pointers // rsp: old expression stack top // 1. compute new pointers // rsp: old expression stack top
__ check_extended_sp();
__ sub(sp, sp, entry_size); // make room for the monitor
__ mov(rscratch1, sp);
__ str(rscratch1, Address(rfp, frame::interpreter_frame_extended_sp_offset * wordSize));
__ ldr(c_rarg1, monitor_block_bot); // c_rarg1: old expression stack bottom __ ldr(c_rarg1, monitor_block_bot); // c_rarg1: old expression stack bottom
__ sub(esp, esp, entry_size); // move expression stack top __ sub(esp, esp, entry_size); // move expression stack top
__ sub(c_rarg1, c_rarg1, entry_size); // move expression stack bottom __ sub(c_rarg1, c_rarg1, entry_size); // move expression stack bottom
__ mov(c_rarg3, esp); // set start value for copy loop __ mov(c_rarg3, esp); // set start value for copy loop
__ str(c_rarg1, monitor_block_bot); // set new monitor block bottom __ str(c_rarg1, monitor_block_bot); // set new monitor block bottom
__ sub(sp, sp, entry_size); // make room for the monitor
__ b(entry); __ b(entry);
// 2. move expression stack contents // 2. move expression stack contents
__ bind(loop); __ bind(loop);

View File

@ -893,7 +893,7 @@ address TemplateInterpreterGenerator::generate_native_entry(bool synchronized) {
__ ldr(Rtemp, Address(FP, frame::interpreter_frame_monitor_block_top_offset * wordSize)); __ ldr(Rtemp, Address(FP, frame::interpreter_frame_monitor_block_top_offset * wordSize));
__ cmp(Rtemp, Rstack_top); __ cmp(Rtemp, Rstack_top);
__ b(L, eq); __ b(L, eq);
__ stop("broken stack frame setup in interpreter"); __ stop("broken stack frame setup in interpreter 3");
__ bind(L); __ bind(L);
} }
#endif #endif
@ -1247,7 +1247,7 @@ address TemplateInterpreterGenerator::generate_normal_entry(bool synchronized) {
__ ldr(Rtemp, Address(FP, frame::interpreter_frame_monitor_block_top_offset * wordSize)); __ ldr(Rtemp, Address(FP, frame::interpreter_frame_monitor_block_top_offset * wordSize));
__ cmp(Rtemp, Rstack_top); __ cmp(Rtemp, Rstack_top);
__ b(L, eq); __ b(L, eq);
__ stop("broken stack frame setup in interpreter"); __ stop("broken stack frame setup in interpreter 4");
__ bind(L); __ bind(L);
} }
#endif #endif

View File

@ -907,7 +907,7 @@ address TemplateInterpreterGenerator::generate_native_entry(bool synchronized) {
__ movptr(rax, monitor_block_top); __ movptr(rax, monitor_block_top);
__ cmpptr(rax, rsp); __ cmpptr(rax, rsp);
__ jcc(Assembler::equal, L); __ jcc(Assembler::equal, L);
__ stop("broken stack frame setup in interpreter"); __ stop("broken stack frame setup in interpreter 5");
__ bind(L); __ bind(L);
} }
#endif #endif
@ -1461,7 +1461,7 @@ address TemplateInterpreterGenerator::generate_normal_entry(bool synchronized) {
__ movptr(rax, monitor_block_top); __ movptr(rax, monitor_block_top);
__ cmpptr(rax, rsp); __ cmpptr(rax, rsp);
__ jcc(Assembler::equal, L); __ jcc(Assembler::equal, L);
__ stop("broken stack frame setup in interpreter"); __ stop("broken stack frame setup in interpreter 6");
__ bind(L); __ bind(L);
} }
#endif #endif