Skip to content

Commit 99b9652

Browse files
committed
ppc64 part of JDK-8369238
1 parent ac55715 commit 99b9652

17 files changed

+147
-60
lines changed

src/hotspot/cpu/ppc/continuationFreezeThaw_ppc.inline.hpp

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -72,9 +72,16 @@ void FreezeBase::adjust_interpreted_frame_unextended_sp(frame& f) {
7272
}
7373

7474
inline void FreezeBase::prepare_freeze_interpreted_top_frame(frame& f) {
75-
// nothing to do
76-
DEBUG_ONLY( intptr_t* lspp = (intptr_t*) &(f.get_ijava_state()->top_frame_sp); )
77-
assert(*lspp == f.unextended_sp() - f.fp(), "should be " INTPTR_FORMAT " usp:" INTPTR_FORMAT " fp:" INTPTR_FORMAT, *lspp, p2i(f.unextended_sp()), p2i(f.fp()));
75+
// Nothing to do. We don't save a last sp since we cannot use sp as esp.
76+
// Instead the top frame is trimmed when making an i2i call. The original
77+
// top_frame_sp is set when the frame is pushed (see generate_fixed_frame()).
78+
// An interpreter top frame that was just thawed is resized to top_frame_sp by the
79+
// resume adapter (see generate_cont_resume_interpreter_adapter()). So the assertion is
80+
// false, if we freeze again right after thawing as we do when redoing a vm call wasn't
81+
// successful.
82+
assert(_thread->interp_redoing_vm_call() ||
83+
((intptr_t*)f.at_relative(ijava_idx(top_frame_sp)) == f.unextended_sp()),
84+
"top_frame_sp:" PTR_FORMAT " usp:" PTR_FORMAT, f.at_relative(ijava_idx(top_frame_sp)), p2i(f.unextended_sp()));
7885
}
7986

8087
inline void FreezeBase::relativize_interpreted_frame_metadata(const frame& f, const frame& hf) {
@@ -338,6 +345,8 @@ inline void FreezeBase::patch_pd_unused(intptr_t* sp) {
338345
}
339346

340347
inline intptr_t* AnchorMark::anchor_mark_set_pd() {
348+
// Nothing to do on PPC because the interpreter does not use SP as expression stack pointer.
349+
// Instead there is a dedicated register R15_esp which is not affected by VM calls.
341350
return _top_frame.sp();
342351
}
343352

@@ -574,8 +583,16 @@ inline intptr_t* ThawBase::push_cleanup_continuation() {
574583
}
575584

576585
inline intptr_t* ThawBase::push_preempt_adapter() {
577-
Unimplemented();
578-
return nullptr;
586+
frame enterSpecial = new_entry_frame();
587+
frame::common_abi* enterSpecial_abi = (frame::common_abi*)enterSpecial.sp();
588+
589+
enterSpecial_abi->lr = (intptr_t)StubRoutines::cont_preempt_stub();
590+
591+
log_develop_trace(continuations, preempt)("push_preempt_adapter enterSpecial sp: " INTPTR_FORMAT " adapter pc: " INTPTR_FORMAT,
592+
p2i(enterSpecial_abi),
593+
p2i(StubRoutines::cont_preempt_stub()));
594+
595+
return enterSpecial.sp();
579596
}
580597

581598
inline void ThawBase::patch_pd(frame& f, const frame& caller) {

src/hotspot/cpu/ppc/continuationHelper_ppc.inline.hpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,9 @@ static inline void patch_return_pc_with_preempt_stub(frame& f) {
3737
// The target will check for preemption once it returns to the interpreter
3838
// or the native wrapper code and will manually jump to the preempt stub.
3939
JavaThread *thread = JavaThread::current();
40+
DEBUG_ONLY(Method* m = f.is_interpreted_frame() ? f.interpreter_frame_method() : f.cb()->as_nmethod()->method();)
41+
assert(m->is_object_wait0() || thread->interp_at_preemptable_vmcall_cnt() > 0,
42+
"preemptable VM call not using call_VM_preemptable");
4043
thread->set_preempt_alternate_return(StubRoutines::cont_preempt_stub());
4144
}
4245
}

src/hotspot/cpu/ppc/frame_ppc.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -215,7 +215,7 @@
215215
uint64_t bcp;
216216
uint64_t esp;
217217
uint64_t mdx;
218-
uint64_t top_frame_sp; // Maybe define parent_frame_abi and move there.
218+
uint64_t top_frame_sp; // Original sp to be restored when returning from an i2i call
219219
uint64_t sender_sp;
220220
// Slots only needed for native calls. Maybe better to move elsewhere.
221221
uint64_t oop_tmp;

src/hotspot/cpu/ppc/interp_masm_ppc.hpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,12 +49,14 @@ class InterpreterMacroAssembler: public MacroAssembler {
4949
virtual void check_and_handle_popframe(Register scratch_reg);
5050
virtual void check_and_handle_earlyret(Register scratch_reg);
5151

52+
// Use for vthread preemption
5253
void call_VM_preemptable(Register oop_result, address entry_point, Register arg_1, bool check_exceptions = true);
54+
void call_VM_preemptable(Register oop_result, address entry_point, Register arg_1, Register arg_2, bool check_exceptions = true);
5355
void restore_after_resume(Register fp);
5456
// R22 and R31 are preserved when a vthread gets preempted in the interpreter.
5557
// The interpreter already assumes that these registers are nonvolatile across native calls.
5658
bool nonvolatile_accross_vthread_preemtion(Register r) const {
57-
return r->is_nonvolatile() && ((r == R22) || (r == R31));
59+
return r->is_nonvolatile() && ((r == R24) || (r == R31));
5860
}
5961

6062
// Base routine for all dispatches.

src/hotspot/cpu/ppc/interp_masm_ppc_64.cpp

Lines changed: 51 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,8 @@ void InterpreterMacroAssembler::dispatch_prolog(TosState state, int bcp_incr) {
108108
// own dispatch. The dispatch address in R24_dispatch_addr is used for the
109109
// dispatch.
110110
void InterpreterMacroAssembler::dispatch_epilog(TosState state, int bcp_incr) {
111+
assert(nonvolatile_accross_vthread_preemtion(R24_dispatch_addr),
112+
"Requirement of field accesses (e.g. putstatic)");
111113
if (bcp_incr) { addi(R14_bcp, R14_bcp, bcp_incr); }
112114
mtctr(R24_dispatch_addr);
113115
bcctr(bcondAlways, 0, bhintbhBCCTRisNotPredictable);
@@ -862,6 +864,9 @@ void InterpreterMacroAssembler::remove_activation(TosState state,
862864
bool install_monitor_exception) {
863865
BLOCK_COMMENT("remove_activation {");
864866

867+
asm_assert_mem8_is_zero(in_bytes(JavaThread::preempt_alternate_return_offset()), R16_thread,
868+
"remove_activation: should not have alternate return address set");
869+
865870
unlock_if_synchronized_method(state, throw_monitor_exception, install_monitor_exception);
866871

867872
// The below poll is for the stack watermark barrier. It allows fixing up frames lazily,
@@ -2014,57 +2019,89 @@ void InterpreterMacroAssembler::call_VM(Register oop_result, address entry_point
20142019
}
20152020

20162021
void InterpreterMacroAssembler::call_VM_preemptable(Register oop_result, address entry_point,
2017-
Register arg_1, bool check_exceptions) {
2022+
Register arg_1,
2023+
bool check_exceptions) {
20182024
if (!Continuations::enabled()) {
20192025
call_VM(oop_result, entry_point, arg_1, check_exceptions);
20202026
return;
20212027
}
2028+
call_VM_preemptable(oop_result, entry_point, arg_1, noreg /* arg_2 */, check_exceptions);
2029+
}
2030+
2031+
void InterpreterMacroAssembler::call_VM_preemptable(Register oop_result, address entry_point,
2032+
Register arg_1, Register arg_2,
2033+
bool check_exceptions) {
2034+
if (!Continuations::enabled()) {
2035+
call_VM(oop_result, entry_point, arg_1, arg_2, check_exceptions);
2036+
return;
2037+
}
20222038

20232039
Label resume_pc, not_preempted;
2040+
Register tmp = R11_scratch1;
2041+
assert_different_registers(arg_1, tmp);
2042+
assert_different_registers(arg_2, tmp);
20242043

2025-
DEBUG_ONLY(ld(R0, in_bytes(JavaThread::preempt_alternate_return_offset()), R16_thread));
2026-
DEBUG_ONLY(cmpdi(CR0, R0, 0));
2027-
asm_assert_eq("Should not have alternate return address set");
2044+
#ifdef ASSERT
2045+
asm_assert_mem8_is_zero(in_bytes(JavaThread::preempt_alternate_return_offset()), R16_thread,
2046+
"Should not have alternate return address set");
2047+
// We check this counter in patch_return_pc_with_preempt_stub() during freeze.
2048+
lwa(tmp, in_bytes(JavaThread::interp_at_preemptable_vmcall_cnt_offset()), R16_thread);
2049+
addi(tmp, tmp, 1);
2050+
cmpwi(CR0, tmp, 0);
2051+
stw(tmp, in_bytes(JavaThread::interp_at_preemptable_vmcall_cnt_offset()), R16_thread);
2052+
asm_assert(gt, "call_VM_preemptable: should be > 0");
2053+
#endif // ASSERT
20282054

20292055
// Preserve 2 registers
2030-
assert(nonvolatile_accross_vthread_preemtion(R31) && nonvolatile_accross_vthread_preemtion(R22), "");
2056+
assert(nonvolatile_accross_vthread_preemtion(R31) && nonvolatile_accross_vthread_preemtion(R24), "");
20312057
ld(R3_ARG1, _abi0(callers_sp), R1_SP); // load FP
20322058
std(R31, _ijava_state_neg(lresult), R3_ARG1);
2033-
std(R22, _ijava_state_neg(fresult), R3_ARG1);
2059+
std(R24, _ijava_state_neg(fresult), R3_ARG1);
20342060

20352061
// We set resume_pc as last java pc. It will be saved if the vthread gets preempted.
20362062
// Later execution will continue right there.
20372063
mr_if_needed(R4_ARG2, arg_1);
2064+
assert(arg_2 != R4_ARG2, "smashed argument");
2065+
mr_if_needed(R5_ARG3, arg_2, true /* allow_noreg */);
20382066
push_cont_fastpath();
2039-
call_VM(oop_result, entry_point, false /*check_exceptions*/, &resume_pc /* last_java_pc */);
2067+
call_VM(noreg /* oop_result */, entry_point, false /*check_exceptions*/, &resume_pc /* last_java_pc */);
20402068
pop_cont_fastpath();
20412069

2070+
#ifdef ASSERT
2071+
lwa(tmp, in_bytes(JavaThread::interp_at_preemptable_vmcall_cnt_offset()), R16_thread);
2072+
addi(tmp, tmp, -1);
2073+
cmpwi(CR0, tmp, 0);
2074+
stw(tmp, in_bytes(JavaThread::interp_at_preemptable_vmcall_cnt_offset()), R16_thread);
2075+
asm_assert(ge, "call_VM_preemptable: should be >= 0");
2076+
#endif // ASSERT
2077+
20422078
// Jump to handler if the call was preempted
20432079
ld(R0, in_bytes(JavaThread::preempt_alternate_return_offset()), R16_thread);
20442080
cmpdi(CR0, R0, 0);
20452081
beq(CR0, not_preempted);
2082+
// Preempted. Frames are already frozen on heap.
20462083
mtlr(R0);
20472084
li(R0, 0);
20482085
std(R0, in_bytes(JavaThread::preempt_alternate_return_offset()), R16_thread);
20492086
blr();
20502087

20512088
bind(resume_pc); // Location to resume execution
20522089
restore_after_resume(noreg /* fp */);
2090+
20532091
bind(not_preempted);
2092+
if (check_exceptions) {
2093+
check_and_forward_exception(R11_scratch1, R12_scratch2);
2094+
}
2095+
if (oop_result->is_valid()) {
2096+
get_vm_result_oop(oop_result);
2097+
}
20542098
}
20552099

20562100
void InterpreterMacroAssembler::restore_after_resume(Register fp) {
2057-
if (!Continuations::enabled()) return;
2058-
20592101
const address resume_adapter = TemplateInterpreter::cont_resume_interpreter_adapter();
20602102
add_const_optimized(R31, R29_TOC, MacroAssembler::offset_to_global_toc(resume_adapter));
20612103
mtctr(R31);
20622104
bctrl();
2063-
// Restore registers that are preserved across vthread preemption
2064-
assert(nonvolatile_accross_vthread_preemtion(R31) && nonvolatile_accross_vthread_preemtion(R22), "");
2065-
ld(R3_ARG1, _abi0(callers_sp), R1_SP); // load FP
2066-
ld(R31, _ijava_state_neg(lresult), R3_ARG1);
2067-
ld(R22, _ijava_state_neg(fresult), R3_ARG1);
20682105
#ifdef ASSERT
20692106
// Assert FP is in R11_scratch1 (see generate_cont_resume_interpreter_adapter())
20702107
{

src/hotspot/cpu/ppc/macroAssembler_ppc.cpp

Lines changed: 25 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -757,10 +757,11 @@ void MacroAssembler::clobber_nonvolatile_registers() {
757757
R31
758758
};
759759
Register bad = regs[0];
760-
load_const_optimized(bad, 0xbad0101babe11111);
760+
load_const_optimized(bad, 0xbad0101babe00000);
761761
for (uint32_t i = 1; i < (sizeof(regs) / sizeof(Register)); i++) {
762-
mr(regs[i], bad);
762+
addi(regs[i], regs[0], regs[i]->encoding());
763763
}
764+
addi(regs[0], regs[0], regs[0]->encoding());
764765
BLOCK_COMMENT("} clobber nonvolatile registers");
765766
}
766767
#endif // ASSERT
@@ -4341,21 +4342,36 @@ void MacroAssembler::multiply_to_len(Register x, Register xlen,
43414342
bind(L_done);
43424343
} // multiply_to_len
43434344

4344-
void MacroAssembler::asm_assert(bool check_equal, const char *msg) {
43454345
#ifdef ASSERT
4346+
void MacroAssembler::asm_assert(AsmAssertCond cond, const char *msg) {
43464347
Label ok;
4347-
if (check_equal) {
4348+
switch (cond) {
4349+
case eq:
43484350
beq(CR0, ok);
4349-
} else {
4351+
break;
4352+
case ne:
43504353
bne(CR0, ok);
4354+
break;
4355+
case ge:
4356+
bge(CR0, ok);
4357+
break;
4358+
case gt:
4359+
bgt(CR0, ok);
4360+
break;
4361+
case lt:
4362+
blt(CR0, ok);
4363+
break;
4364+
case le:
4365+
ble(CR0, ok);
4366+
break;
4367+
default:
4368+
assert(false, "unknown cond:%d", cond);
43514369
}
43524370
stop(msg);
43534371
bind(ok);
4354-
#endif
43554372
}
43564373

4357-
#ifdef ASSERT
4358-
void MacroAssembler::asm_assert_mems_zero(bool check_equal, int size, int mem_offset,
4374+
void MacroAssembler::asm_assert_mems_zero(AsmAssertCond cond, int size, int mem_offset,
43594375
Register mem_base, const char* msg) {
43604376
switch (size) {
43614377
case 4:
@@ -4369,7 +4385,7 @@ void MacroAssembler::asm_assert_mems_zero(bool check_equal, int size, int mem_of
43694385
default:
43704386
ShouldNotReachHere();
43714387
}
4372-
asm_assert(check_equal, msg);
4388+
asm_assert(cond, msg);
43734389
}
43744390
#endif // ASSERT
43754391

src/hotspot/cpu/ppc/macroAssembler_ppc.hpp

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ class MacroAssembler: public Assembler {
6868
void store_sized_value(Register dst, RegisterOrConstant offs, Register base, size_t size_in_bytes);
6969

7070
// Move register if destination register and target register are different
71-
inline void mr_if_needed(Register rd, Register rs);
71+
inline void mr_if_needed(Register rd, Register rs, bool allow_invalid = false);
7272
inline void fmr_if_needed(FloatRegister rd, FloatRegister rs);
7373
// This is dedicated for emitting scheduled mach nodes. For better
7474
// readability of the ad file I put it here.
@@ -942,21 +942,29 @@ class MacroAssembler: public Assembler {
942942
//
943943

944944
// assert on cr0
945-
void asm_assert(bool check_equal, const char* msg);
946-
void asm_assert_eq(const char* msg) { asm_assert(true, msg); }
947-
void asm_assert_ne(const char* msg) { asm_assert(false, msg); }
945+
enum AsmAssertCond {
946+
eq,
947+
ne,
948+
ge,
949+
gt,
950+
lt,
951+
le
952+
};
953+
void asm_assert(AsmAssertCond cond, const char* msg) PRODUCT_RETURN;
954+
void asm_assert_eq(const char* msg) { asm_assert(eq, msg); }
955+
void asm_assert_ne(const char* msg) { asm_assert(ne, msg); }
948956

949957
private:
950-
void asm_assert_mems_zero(bool check_equal, int size, int mem_offset, Register mem_base,
958+
void asm_assert_mems_zero(AsmAssertCond cond, int size, int mem_offset, Register mem_base,
951959
const char* msg) NOT_DEBUG_RETURN;
952960

953961
public:
954962

955963
void asm_assert_mem8_is_zero(int mem_offset, Register mem_base, const char* msg) {
956-
asm_assert_mems_zero(true, 8, mem_offset, mem_base, msg);
964+
asm_assert_mems_zero(eq, 8, mem_offset, mem_base, msg);
957965
}
958966
void asm_assert_mem8_isnot_zero(int mem_offset, Register mem_base, const char* msg) {
959-
asm_assert_mems_zero(false, 8, mem_offset, mem_base, msg);
967+
asm_assert_mems_zero(ne, 8, mem_offset, mem_base, msg);
960968
}
961969

962970
// Calls verify_oop. If UseCompressedOops is on, decodes the oop.

src/hotspot/cpu/ppc/macroAssembler_ppc.inline.hpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,8 @@ inline void MacroAssembler::round_to(Register r, int modulus) {
6565
}
6666

6767
// Move register if destination register and target register are different.
68-
inline void MacroAssembler::mr_if_needed(Register rd, Register rs) {
68+
inline void MacroAssembler::mr_if_needed(Register rd, Register rs, bool allow_noreg) {
69+
if (allow_noreg && (rs == noreg)) return;
6970
if (rs != rd) mr(rd, rs);
7071
}
7172
inline void MacroAssembler::fmr_if_needed(FloatRegister rd, FloatRegister rs) {

src/hotspot/cpu/ppc/smallRegisterMap_ppc.inline.hpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -61,22 +61,22 @@ class SmallRegisterMapType {
6161

6262
JavaThread* thread() const {
6363
#ifndef ASSERT
64-
guarantee (false, "");
64+
guarantee (false, "unreachable");
6565
#endif
6666
return nullptr;
6767
}
6868

6969
bool update_map() const { return false; }
7070
bool walk_cont() const { return false; }
71-
bool include_argument_oops() const { return false; }
71+
bool include_argument_oops() const { return IncludeArgs; }
7272
void set_include_argument_oops(bool f) {}
7373
bool in_cont() const { return false; }
7474
stackChunkHandle stack_chunk() const { return stackChunkHandle(); }
7575

7676
#ifdef ASSERT
7777
bool should_skip_missing() const { return false; }
7878
VMReg find_register_spilled_here(void* p, intptr_t* sp) {
79-
Unimplemented();
79+
assert(false, "Shouldn't reach here! p:" PTR_FORMAT " sp:" PTR_FORMAT, p2i(p), p2i(p));
8080
return nullptr;
8181
}
8282
void print() const { print_on(tty); }

src/hotspot/cpu/ppc/stackChunkFrameStream_ppc.inline.hpp

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -180,14 +180,10 @@ template <typename RegisterMapT>
180180
inline int StackChunkFrameStream<frame_kind>::interpreter_frame_num_oops(RegisterMapT* map) const {
181181
assert_is_interpreted_and_frame_type_mixed();
182182
ResourceMark rm;
183-
InterpreterOopMap mask;
184183
frame f = to_frame();
185-
f.interpreted_frame_oop_map(&mask);
186-
return mask.num_oops()
187-
+ 1 // for the mirror oop
188-
+ (f.interpreter_frame_method()->is_native() ? 1 : 0) // temp oop slot
189-
+ pointer_delta_as_int((intptr_t*)f.interpreter_frame_monitor_begin(),
190-
(intptr_t*)f.interpreter_frame_monitor_end())/BasicObjectLock::size();
184+
InterpreterOopCount closure;
185+
f.oops_interpreted_do(&closure, map);
186+
return closure.count();
191187
}
192188

193189
template<>

0 commit comments

Comments
 (0)