8308984: Relativize last_sp (and top_frame_sp) in interpreter frames

Reviewed-by: pchilanomate, aph, haosun
This commit is contained in:
Fredrik Bredberg 2023-08-18 14:29:28 +00:00 committed by Patricio Chilano Mateo
parent fdac6a6ac8
commit c36e009772
25 changed files with 107 additions and 48 deletions

@ -83,7 +83,7 @@ frame FreezeBase::new_heap_frame(frame& f, frame& caller) {
intptr_t *sp, *fp; // sp is really our unextended_sp
if (FKind::interpreted) {
assert((intptr_t*)f.at(frame::interpreter_frame_last_sp_offset) == nullptr
|| f.unextended_sp() == (intptr_t*)f.at(frame::interpreter_frame_last_sp_offset), "");
|| f.unextended_sp() == (intptr_t*)f.at_relative(frame::interpreter_frame_last_sp_offset), "");
intptr_t locals_offset = *f.addr_at(frame::interpreter_frame_locals_offset);
// If the caller.is_empty(), i.e. we're freezing into an empty chunk, then we set
// the chunk's argsize in finalize_freeze and make room for it above the unextended_sp
@ -123,7 +123,7 @@ frame FreezeBase::new_heap_frame(frame& f, frame& caller) {
void FreezeBase::adjust_interpreted_frame_unextended_sp(frame& f) {
assert((f.at(frame::interpreter_frame_last_sp_offset) != 0) || (f.unextended_sp() == f.sp()), "");
intptr_t* real_unextended_sp = (intptr_t*)f.at(frame::interpreter_frame_last_sp_offset);
intptr_t* real_unextended_sp = (intptr_t*)f.at_relative_or_null(frame::interpreter_frame_last_sp_offset);
if (real_unextended_sp != nullptr) {
f.set_unextended_sp(real_unextended_sp); // can be null at a safepoint
}
@ -149,8 +149,8 @@ inline void FreezeBase::relativize_interpreted_frame_metadata(const frame& f, co
// because we freeze the padding word (see recurse_freeze_interpreted_frame) in order to keep the same relativized
// locals value, we don't need to change the locals value here.
// at(frame::interpreter_frame_last_sp_offset) can be null at safepoint preempts
*hf.addr_at(frame::interpreter_frame_last_sp_offset) = hf.unextended_sp() - hf.fp();
// Make sure that last_sp is already relativized.
assert((intptr_t*)hf.at_relative(frame::interpreter_frame_last_sp_offset) == hf.unextended_sp(), "");
relativize_one(vfp, hfp, frame::interpreter_frame_initial_sp_offset); // == block_top == block_bottom
relativize_one(vfp, hfp, frame::interpreter_frame_extended_sp_offset);
@ -290,7 +290,9 @@ static inline void derelativize_one(intptr_t* const fp, int offset) {
inline void ThawBase::derelativize_interpreted_frame_metadata(const frame& hf, const frame& f) {
intptr_t* vfp = f.fp();
derelativize_one(vfp, frame::interpreter_frame_last_sp_offset);
// Make sure that last_sp is kept relativized.
assert((intptr_t*)f.at_relative(frame::interpreter_frame_last_sp_offset) == f.unextended_sp(), "");
derelativize_one(vfp, frame::interpreter_frame_initial_sp_offset);
derelativize_one(vfp, frame::interpreter_frame_extended_sp_offset);
}

@ -125,7 +125,8 @@ inline intptr_t* ContinuationHelper::InterpretedFrame::frame_top(const frame& f,
assert(res == (intptr_t*)f.interpreter_frame_monitor_end() - expression_stack_sz, "");
assert(res >= f.unextended_sp(),
"res: " INTPTR_FORMAT " initial_sp: " INTPTR_FORMAT " last_sp: " INTPTR_FORMAT " unextended_sp: " INTPTR_FORMAT " expression_stack_size: %d",
p2i(res), p2i(f.addr_at(frame::interpreter_frame_initial_sp_offset)), f.at(frame::interpreter_frame_last_sp_offset), p2i(f.unextended_sp()), expression_stack_sz);
p2i(res), p2i(f.addr_at(frame::interpreter_frame_initial_sp_offset)), f.at_relative_or_null(frame::interpreter_frame_last_sp_offset),
p2i(f.unextended_sp()), expression_stack_sz);
return res;
}

@ -355,7 +355,9 @@ void frame::interpreter_frame_set_monitor_end(BasicObjectLock* value) {
// Used by template based interpreter deoptimization
void frame::interpreter_frame_set_last_sp(intptr_t* sp) {
*((intptr_t**)addr_at(interpreter_frame_last_sp_offset)) = sp;
assert(is_interpreted_frame(), "interpreted frame expected");
// set relativized last_sp
ptr_at_put(interpreter_frame_last_sp_offset, sp != nullptr ? (sp - fp()) : 0);
}
// Used by template based interpreter deoptimization

@ -262,7 +262,9 @@ inline intptr_t* frame::interpreter_frame_locals() const {
}
inline intptr_t* frame::interpreter_frame_last_sp() const {
return (intptr_t*)at(interpreter_frame_last_sp_offset);
intptr_t n = *addr_at(interpreter_frame_last_sp_offset);
assert(n <= 0, "n: " INTPTR_FORMAT, n);
return n != 0 ? &fp()[n] : nullptr;
}
inline intptr_t* frame::interpreter_frame_bcp_addr() const {

@ -430,7 +430,9 @@ void InterpreterMacroAssembler::prepare_to_jump_from_interpreted() {
// set sender sp
mov(r19_sender_sp, sp);
// record last_sp
str(esp, Address(rfp, frame::interpreter_frame_last_sp_offset * wordSize));
sub(rscratch1, esp, rfp);
asr(rscratch1, rscratch1, Interpreter::logStackElementSize);
str(rscratch1, Address(rfp, frame::interpreter_frame_last_sp_offset * wordSize));
}
// Jump to from_interpreted entry of a call unless single stepping is possible

@ -465,7 +465,8 @@ address TemplateInterpreterGenerator::generate_return_entry_for(TosState state,
address entry = __ pc();
// Restore stack bottom in case i2c adjusted stack
__ ldr(esp, Address(rfp, frame::interpreter_frame_last_sp_offset * wordSize));
__ ldr(rscratch1, Address(rfp, frame::interpreter_frame_last_sp_offset * wordSize));
__ lea(esp, Address(rfp, rscratch1, Address::lsl(Interpreter::logStackElementSize)));
// and null it as marker that esp is now tos until next java call
__ str(zr, Address(rfp, frame::interpreter_frame_last_sp_offset * wordSize));
__ restore_bcp();
@ -521,7 +522,8 @@ address TemplateInterpreterGenerator::generate_deopt_entry_for(TosState state,
__ restore_sp_after_call(); // Restore SP to extended SP
// Restore expression stack pointer
__ ldr(esp, Address(rfp, frame::interpreter_frame_last_sp_offset * wordSize));
__ ldr(rscratch1, Address(rfp, frame::interpreter_frame_last_sp_offset * wordSize));
__ lea(esp, Address(rfp, rscratch1, Address::lsl(Interpreter::logStackElementSize)));
// null last_sp until next java call
__ str(zr, Address(rfp, frame::interpreter_frame_last_sp_offset * wordSize));
@ -1867,7 +1869,8 @@ void TemplateInterpreterGenerator::generate_throw_exception() {
/* notify_jvmdi */ false);
// Restore the last_sp and null it out
__ ldr(esp, Address(rfp, frame::interpreter_frame_last_sp_offset * wordSize));
__ ldr(rscratch1, Address(rfp, frame::interpreter_frame_last_sp_offset * wordSize));
__ lea(esp, Address(rfp, rscratch1, Address::lsl(Interpreter::logStackElementSize)));
__ str(zr, Address(rfp, frame::interpreter_frame_last_sp_offset * wordSize));
__ restore_bcp();

@ -89,7 +89,7 @@ inline void FreezeBase::relativize_interpreted_frame_metadata(const frame& f, co
relativize_one(vfp, hfp, ijava_idx(monitors));
relativize_one(vfp, hfp, ijava_idx(esp));
relativize_one(vfp, hfp, ijava_idx(top_frame_sp));
// top_frame_sp is already relativized
// hfp == hf.sp() + (f.fp() - f.sp()) is not true on ppc because the stack frame has room for
// the maximal expression stack and the expression stack in the heap frame is trimmed.
@ -544,7 +544,7 @@ inline void ThawBase::derelativize_interpreted_frame_metadata(const frame& hf, c
derelativize_one(vfp, ijava_idx(monitors));
derelativize_one(vfp, ijava_idx(esp));
derelativize_one(vfp, ijava_idx(top_frame_sp));
// Keep top_frame_sp relativized.
}
inline void ThawBase::patch_pd(frame& f, const frame& caller) {

@ -86,7 +86,7 @@ inline void ContinuationHelper::InterpretedFrame::patch_sender_sp(frame& f, cons
intptr_t* sp = caller.unextended_sp();
if (!f.is_heap_frame() && caller.is_interpreted_frame()) {
// See diagram "Interpreter Calling Procedure on PPC" at the end of continuationFreezeThaw_ppc.inline.hpp
sp = (intptr_t*)caller.at(ijava_idx(top_frame_sp));
sp = (intptr_t*)caller.at_relative(ijava_idx(top_frame_sp));
}
assert(f.is_interpreted_frame(), "");
assert(f.is_heap_frame() || is_aligned(sp, frame::alignment_in_bytes), "");

@ -231,7 +231,13 @@ inline intptr_t* frame::interpreter_frame_esp() const {
inline void frame::interpreter_frame_set_monitor_end(BasicObjectLock* end) { get_ijava_state()->monitors = (intptr_t) end;}
inline void frame::interpreter_frame_set_cpcache(ConstantPoolCache* cp) { *interpreter_frame_cache_addr() = cp; }
inline void frame::interpreter_frame_set_esp(intptr_t* esp) { get_ijava_state()->esp = (intptr_t) esp; }
inline void frame::interpreter_frame_set_top_frame_sp(intptr_t* top_frame_sp) { get_ijava_state()->top_frame_sp = (intptr_t) top_frame_sp; }
inline void frame::interpreter_frame_set_top_frame_sp(intptr_t* top_frame_sp) {
assert(is_interpreted_frame(), "interpreted frame expected");
// set relativized top_frame_sp
get_ijava_state()->top_frame_sp = (intptr_t) (top_frame_sp - fp());
}
inline void frame::interpreter_frame_set_sender_sp(intptr_t* sender_sp) { get_ijava_state()->sender_sp = (intptr_t) sender_sp; }
inline intptr_t* frame::interpreter_frame_expression_stack() const {

@ -1241,6 +1241,9 @@ void InterpreterMacroAssembler::call_from_interpreter(Register Rtarget_method, R
save_interpreter_state(Rscratch2);
#ifdef ASSERT
ld(Rscratch1, _ijava_state_neg(top_frame_sp), Rscratch2); // Rscratch2 contains fp
sldi(Rscratch1, Rscratch1, Interpreter::logStackElementSize);
add(Rscratch1, Rscratch1, Rscratch2); // Rscratch2 contains fp
// Compare sender_sp with the derelativized top_frame_sp
cmpd(CCR0, R21_sender_SP, Rscratch1);
asm_assert_eq("top_frame_sp incorrect");
#endif
@ -2015,7 +2018,10 @@ void InterpreterMacroAssembler::add_monitor_to_stack(bool stack_is_empty, Regist
"size of a monitor must respect alignment of SP");
resize_frame(-monitor_size, /*temp*/esp); // Allocate space for new monitor
std(R1_SP, _ijava_state_neg(top_frame_sp), esp); // esp contains fp
subf(Rtemp2, esp, R1_SP); // esp contains fp
sradi(Rtemp2, Rtemp2, Interpreter::logStackElementSize);
// Store relativized top_frame_sp
std(Rtemp2, _ijava_state_neg(top_frame_sp), esp); // esp contains fp
// Shuffle expression stack down. Recall that stack_base points
// just above the new expression stack bottom. Old_tos and new_tos
@ -2251,6 +2257,9 @@ void InterpreterMacroAssembler::restore_interpreter_state(Register scratch, bool
Register tfsp = R18_locals;
Register scratch2 = R26_monitor;
ld(tfsp, _ijava_state_neg(top_frame_sp), scratch);
// Derelativize top_frame_sp
sldi(tfsp, tfsp, Interpreter::logStackElementSize);
add(tfsp, tfsp, scratch);
resize_frame_absolute(tfsp, scratch2, R0);
}
ld(R14_bcp, _ijava_state_neg(bcp), scratch); // Changed by VM code (exception).

@ -1061,8 +1061,10 @@ void TemplateInterpreterGenerator::generate_fixed_frame(bool native_call, Regist
__ std(R0, _ijava_state_neg(oop_tmp), R1_SP); // only used for native_call
// Store sender's SP and this frame's top SP.
__ subf(R12_scratch2, Rtop_frame_size, R1_SP);
__ std(R21_sender_SP, _ijava_state_neg(sender_sp), R1_SP);
__ neg(R12_scratch2, Rtop_frame_size);
__ sradi(R12_scratch2, R12_scratch2, Interpreter::logStackElementSize);
// Store relativized top_frame_sp
__ std(R12_scratch2, _ijava_state_neg(top_frame_sp), R1_SP);
// Push top frame.

@ -82,7 +82,7 @@ template<typename FKind> frame FreezeBase::new_heap_frame(frame& f, frame& calle
intptr_t *sp, *fp; // sp is really our unextended_sp
if (FKind::interpreted) {
assert((intptr_t*)f.at(frame::interpreter_frame_last_sp_offset) == nullptr
|| f.unextended_sp() == (intptr_t*)f.at(frame::interpreter_frame_last_sp_offset), "");
|| f.unextended_sp() == (intptr_t*)f.at_relative(frame::interpreter_frame_last_sp_offset), "");
intptr_t locals_offset = *f.addr_at(frame::interpreter_frame_locals_offset);
// If the caller.is_empty(), i.e. we're freezing into an empty chunk, then we set
// the chunk's argsize in finalize_freeze and make room for it above the unextended_sp
@ -121,7 +121,7 @@ template<typename FKind> frame FreezeBase::new_heap_frame(frame& f, frame& calle
void FreezeBase::adjust_interpreted_frame_unextended_sp(frame& f) {
assert((f.at(frame::interpreter_frame_last_sp_offset) != 0) || (f.unextended_sp() == f.sp()), "");
intptr_t* real_unextended_sp = (intptr_t*)f.at(frame::interpreter_frame_last_sp_offset);
intptr_t* real_unextended_sp = (intptr_t*)f.at_relative_or_null(frame::interpreter_frame_last_sp_offset);
if (real_unextended_sp != nullptr) {
f.set_unextended_sp(real_unextended_sp); // can be null at a safepoint
}
@ -147,8 +147,8 @@ inline void FreezeBase::relativize_interpreted_frame_metadata(const frame& f, co
// because we freeze the padding word (see recurse_freeze_interpreted_frame) in order to keep the same relativized
// locals value, we don't need to change the locals value here.
// at(frame::interpreter_frame_last_sp_offset) can be null at safepoint preempts
*hf.addr_at(frame::interpreter_frame_last_sp_offset) = hf.unextended_sp() - hf.fp();
// Make sure that last_sp is already relativized.
assert((intptr_t*)hf.at_relative(frame::interpreter_frame_last_sp_offset) == hf.unextended_sp(), "");
relativize_one(vfp, hfp, frame::interpreter_frame_initial_sp_offset); // == block_top == block_bottom
relativize_one(vfp, hfp, frame::interpreter_frame_extended_sp_offset);
@ -292,7 +292,9 @@ static inline void derelativize_one(intptr_t* const fp, int offset) {
inline void ThawBase::derelativize_interpreted_frame_metadata(const frame& hf, const frame& f) {
intptr_t* vfp = f.fp();
derelativize_one(vfp, frame::interpreter_frame_last_sp_offset);
// Make sure that last_sp is kept relativized.
assert((intptr_t*)f.at_relative(frame::interpreter_frame_last_sp_offset) == f.unextended_sp(), "");
derelativize_one(vfp, frame::interpreter_frame_initial_sp_offset);
derelativize_one(vfp, frame::interpreter_frame_extended_sp_offset);
}

@ -125,7 +125,8 @@ inline intptr_t* ContinuationHelper::InterpretedFrame::frame_top(const frame& f,
assert(res == (intptr_t*)f.interpreter_frame_monitor_end() - expression_stack_sz, "");
assert(res >= f.unextended_sp(),
"res: " INTPTR_FORMAT " initial_sp: " INTPTR_FORMAT " last_sp: " INTPTR_FORMAT " unextended_sp: " INTPTR_FORMAT " expression_stack_size: %d",
p2i(res), p2i(f.addr_at(frame::interpreter_frame_initial_sp_offset)), f.at(frame::interpreter_frame_last_sp_offset), p2i(f.unextended_sp()), expression_stack_sz);
p2i(res), p2i(f.addr_at(frame::interpreter_frame_initial_sp_offset)), f.at_relative_or_null(frame::interpreter_frame_last_sp_offset),
p2i(f.unextended_sp()), expression_stack_sz);
return res;
}

@ -331,7 +331,9 @@ void frame::interpreter_frame_set_monitor_end(BasicObjectLock* value) {
// Used by template based interpreter deoptimization
void frame::interpreter_frame_set_last_sp(intptr_t* last_sp) {
*((intptr_t**)addr_at(interpreter_frame_last_sp_offset)) = last_sp;
assert(is_interpreted_frame(), "interpreted frame expected");
// set relativized last_sp
ptr_at_put(interpreter_frame_last_sp_offset, last_sp != nullptr ? (last_sp - fp()) : 0);
}
void frame::interpreter_frame_set_extended_sp(intptr_t* sp) {

@ -253,7 +253,9 @@ inline intptr_t* frame::interpreter_frame_locals() const {
}
inline intptr_t* frame::interpreter_frame_last_sp() const {
return (intptr_t*)at(interpreter_frame_last_sp_offset);
intptr_t n = *addr_at(interpreter_frame_last_sp_offset);
assert(n <= 0, "n: " INTPTR_FORMAT, n);
return n != 0 ? &fp()[n] : nullptr;
}
inline intptr_t* frame::interpreter_frame_bcp_addr() const {

@ -491,7 +491,9 @@ void InterpreterMacroAssembler::prepare_to_jump_from_interpreted() {
// set sender sp
mv(x19_sender_sp, sp);
// record last_sp
sd(esp, Address(fp, frame::interpreter_frame_last_sp_offset * wordSize));
sub(t0, esp, fp);
srai(t0, t0, Interpreter::logStackElementSize);
sd(t0, Address(fp, frame::interpreter_frame_last_sp_offset * wordSize));
}
// Jump to from_interpreted entry of a call unless single stepping is possible

@ -426,7 +426,8 @@ address TemplateInterpreterGenerator::generate_return_entry_for(TosState state,
address entry = __ pc();
// Restore stack bottom in case i2c adjusted stack
__ ld(esp, Address(fp, frame::interpreter_frame_last_sp_offset * wordSize));
__ ld(t0, Address(fp, frame::interpreter_frame_last_sp_offset * wordSize));
__ shadd(esp, t0, fp, t0, LogBytesPerWord);
// and null it as marker that esp is now tos until next java call
__ sd(zr, Address(fp, frame::interpreter_frame_last_sp_offset * wordSize));
__ restore_bcp();
@ -483,7 +484,8 @@ address TemplateInterpreterGenerator::generate_deopt_entry_for(TosState state,
__ restore_sp_after_call(); // Restore SP to extended SP
// Restore expression stack pointer
__ ld(esp, Address(fp, frame::interpreter_frame_last_sp_offset * wordSize));
__ ld(t0, Address(fp, frame::interpreter_frame_last_sp_offset * wordSize));
__ shadd(esp, t0, fp, t0, LogBytesPerWord);
// null last_sp until next java call
__ sd(zr, Address(fp, frame::interpreter_frame_last_sp_offset * wordSize));
@ -1604,7 +1606,8 @@ void TemplateInterpreterGenerator::generate_throw_exception() {
/* notify_jvmdi */ false);
// Restore the last_sp and null it out
__ ld(esp, Address(fp, frame::interpreter_frame_last_sp_offset * wordSize));
__ ld(t0, Address(fp, frame::interpreter_frame_last_sp_offset * wordSize));
__ shadd(esp, t0, fp, t0, LogBytesPerWord);
__ sd(zr, Address(fp, frame::interpreter_frame_last_sp_offset * wordSize));
__ restore_bcp();

@ -79,8 +79,8 @@ frame FreezeBase::new_heap_frame(frame& f, frame& caller) {
intptr_t *sp, *fp; // sp is really our unextended_sp
if (FKind::interpreted) {
assert((intptr_t*)f.at(frame::interpreter_frame_last_sp_offset) == nullptr
|| f.unextended_sp() == (intptr_t*)f.at(frame::interpreter_frame_last_sp_offset), "");
assert((intptr_t*)f.at_relative_or_null(frame::interpreter_frame_last_sp_offset) == nullptr
|| f.unextended_sp() == (intptr_t*)f.at_relative(frame::interpreter_frame_last_sp_offset), "");
intptr_t locals_offset = *f.addr_at(frame::interpreter_frame_locals_offset);
// If the caller.is_empty(), i.e. we're freezing into an empty chunk, then we set
// the chunk's argsize in finalize_freeze and make room for it above the unextended_sp
@ -120,7 +120,7 @@ frame FreezeBase::new_heap_frame(frame& f, frame& caller) {
void FreezeBase::adjust_interpreted_frame_unextended_sp(frame& f) {
assert((f.at(frame::interpreter_frame_last_sp_offset) != 0) || (f.unextended_sp() == f.sp()), "");
intptr_t* real_unextended_sp = (intptr_t*)f.at(frame::interpreter_frame_last_sp_offset);
intptr_t* real_unextended_sp = (intptr_t*)f.at_relative_or_null(frame::interpreter_frame_last_sp_offset);
if (real_unextended_sp != nullptr) {
f.set_unextended_sp(real_unextended_sp); // can be null at a safepoint
}
@ -141,8 +141,8 @@ inline void FreezeBase::relativize_interpreted_frame_metadata(const frame& f, co
|| (f.unextended_sp() == f.sp()), "");
assert(f.fp() > (intptr_t*)f.at(frame::interpreter_frame_initial_sp_offset), "");
// at(frame::interpreter_frame_last_sp_offset) can be null at safepoint preempts
*hf.addr_at(frame::interpreter_frame_last_sp_offset) = hf.unextended_sp() - hf.fp();
// Make sure that last_sp is already relativized.
assert((intptr_t*)hf.at_relative(frame::interpreter_frame_last_sp_offset) == hf.unextended_sp(), "");
// Make sure that locals is already relativized.
assert((*hf.addr_at(frame::interpreter_frame_locals_offset) == frame::sender_sp_offset + f.interpreter_frame_method()->max_locals() - 1), "");
@ -282,7 +282,9 @@ static inline void derelativize_one(intptr_t* const fp, int offset) {
inline void ThawBase::derelativize_interpreted_frame_metadata(const frame& hf, const frame& f) {
intptr_t* vfp = f.fp();
derelativize_one(vfp, frame::interpreter_frame_last_sp_offset);
// Make sure that last_sp is kept relativized.
assert((intptr_t*)f.at_relative(frame::interpreter_frame_last_sp_offset) == f.unextended_sp(), "");
derelativize_one(vfp, frame::interpreter_frame_initial_sp_offset);
}

@ -125,7 +125,8 @@ inline intptr_t* ContinuationHelper::InterpretedFrame::frame_top(const frame& f,
assert(res == (intptr_t*)f.interpreter_frame_monitor_end() - expression_stack_sz, "");
assert(res >= f.unextended_sp(),
"res: " INTPTR_FORMAT " initial_sp: " INTPTR_FORMAT " last_sp: " INTPTR_FORMAT " unextended_sp: " INTPTR_FORMAT " expression_stack_size: %d",
p2i(res), p2i(f.addr_at(frame::interpreter_frame_initial_sp_offset)), f.at(frame::interpreter_frame_last_sp_offset), p2i(f.unextended_sp()), expression_stack_sz);
p2i(res), p2i(f.addr_at(frame::interpreter_frame_initial_sp_offset)), f.at_relative_or_null(frame::interpreter_frame_last_sp_offset),
p2i(f.unextended_sp()), expression_stack_sz);
return res;
}

@ -352,7 +352,9 @@ void frame::interpreter_frame_set_monitor_end(BasicObjectLock* value) {
// Used by template based interpreter deoptimization
void frame::interpreter_frame_set_last_sp(intptr_t* sp) {
*((intptr_t**)addr_at(interpreter_frame_last_sp_offset)) = sp;
assert(is_interpreted_frame(), "interpreted frame expected");
// set relativized last_sp
ptr_at_put(interpreter_frame_last_sp_offset, sp != nullptr ? (sp - fp()) : 0);
}
frame frame::sender_for_entry_frame(RegisterMap* map) const {

@ -250,7 +250,9 @@ inline intptr_t* frame::interpreter_frame_locals() const {
}
inline intptr_t* frame::interpreter_frame_last_sp() const {
return (intptr_t*)at(interpreter_frame_last_sp_offset);
intptr_t n = *addr_at(interpreter_frame_last_sp_offset);
assert(n <= 0, "n: " INTPTR_FORMAT, n);
return n != 0 ? &fp()[n] : nullptr;
}
inline intptr_t* frame::interpreter_frame_bcp_addr() const {

@ -795,7 +795,10 @@ void InterpreterMacroAssembler::prepare_to_jump_from_interpreted() {
// set sender sp
lea(_bcp_register, Address(rsp, wordSize));
// record last_sp
movptr(Address(rbp, frame::interpreter_frame_last_sp_offset * wordSize), _bcp_register);
mov(rcx, _bcp_register);
subptr(rcx, rbp);
sarptr(rcx, LogBytesPerWord);
movptr(Address(rbp, frame::interpreter_frame_last_sp_offset * wordSize), rcx);
}

@ -206,7 +206,8 @@ address TemplateInterpreterGenerator::generate_return_entry_for(TosState state,
#endif // _LP64
// Restore stack bottom in case i2c adjusted stack
__ movptr(rsp, Address(rbp, frame::interpreter_frame_last_sp_offset * wordSize));
__ movptr(rcx, Address(rbp, frame::interpreter_frame_last_sp_offset * wordSize));
__ lea(rsp, Address(rbp, rcx, Address::times_ptr));
// and null it as marker that esp is now tos until next java call
__ movptr(Address(rbp, frame::interpreter_frame_last_sp_offset * wordSize), NULL_WORD);
@ -1616,6 +1617,7 @@ void TemplateInterpreterGenerator::generate_throw_exception() {
#ifndef _LP64
__ mov(rax, rsp);
__ movptr(rbx, Address(rbp, frame::interpreter_frame_last_sp_offset * wordSize));
__ lea(rbx, Address(rbp, rbx, Address::times_ptr));
__ get_thread(thread);
// PC must point into interpreter here
__ set_last_Java_frame(thread, noreg, rbp, __ pc(), noreg);
@ -1624,6 +1626,7 @@ void TemplateInterpreterGenerator::generate_throw_exception() {
#else
__ mov(c_rarg1, rsp);
__ movptr(c_rarg2, Address(rbp, frame::interpreter_frame_last_sp_offset * wordSize));
__ lea(c_rarg2, Address(rbp, c_rarg2, Address::times_ptr));
// PC must point into interpreter here
__ set_last_Java_frame(noreg, rbp, __ pc(), rscratch1);
__ super_call_VM_leaf(CAST_FROM_FN_PTR(address, InterpreterRuntime::popframe_move_outgoing_args), r15_thread, c_rarg1, c_rarg2);
@ -1631,7 +1634,8 @@ void TemplateInterpreterGenerator::generate_throw_exception() {
__ reset_last_Java_frame(thread, true);
// Restore the last_sp and null it out
__ movptr(rsp, Address(rbp, frame::interpreter_frame_last_sp_offset * wordSize));
__ movptr(rcx, Address(rbp, frame::interpreter_frame_last_sp_offset * wordSize));
__ lea(rsp, Address(rbp, rcx, Address::times_ptr));
__ movptr(Address(rbp, frame::interpreter_frame_last_sp_offset * wordSize), NULL_WORD);
__ restore_bcp();

@ -1612,10 +1612,10 @@ void FrameValues::print_on(stackChunkOop chunk, outputStream* st) {
while (!(start <= v0 && v0 <= end)) v0 = _values.at(++min_index).location;
while (!(start <= v1 && v1 <= end)) v1 = _values.at(--max_index).location;
print_on(st, min_index, max_index, v0, v1, true /* on_heap */);
print_on(st, min_index, max_index, v0, v1);
}
void FrameValues::print_on(outputStream* st, int min_index, int max_index, intptr_t* v0, intptr_t* v1, bool on_heap) {
void FrameValues::print_on(outputStream* st, int min_index, int max_index, intptr_t* v0, intptr_t* v1) {
intptr_t* min = MIN2(v0, v1);
intptr_t* max = MAX2(v0, v1);
intptr_t* cur = max;
@ -1630,8 +1630,7 @@ void FrameValues::print_on(outputStream* st, int min_index, int max_index, intpt
const char* spacer = " " LP64_ONLY(" ");
st->print_cr(" %s %s %s", spacer, spacer, fv.description);
} else {
if (on_heap
&& *fv.location != 0 && *fv.location > -100 && *fv.location < 100
if (*fv.location != 0 && *fv.location > -100 && *fv.location < 100
#if !defined(PPC64)
&& (strncmp(fv.description, "interpreter_frame_", 18) == 0 || strstr(fv.description, " method "))
#else // !defined(PPC64)

@ -249,6 +249,12 @@ class frame {
// Interpreter frames in continuation stacks are on the heap, and internal addresses are relative to fp.
intptr_t at_relative(int index) const { return (intptr_t)(fp() + fp()[index]); }
intptr_t at_relative_or_null(int index) const {
return (fp()[index] != 0)
? (intptr_t)(fp() + fp()[index])
: 0;
}
intptr_t at(int index) const {
return _on_heap ? at_relative(index) : at_absolute(index);
}
@ -519,8 +525,7 @@ class FrameValues {
return checked_cast<int>(a->location - b->location);
}
void print_on(outputStream* out, int min_index, int max_index, intptr_t* v0, intptr_t* v1,
bool on_heap = false);
void print_on(outputStream* out, int min_index, int max_index, intptr_t* v0, intptr_t* v1);
public:
// Used by frame functions to describe locations.