Skip to content

Commit bbef534

Browse files
committed
PPC64 implementation.
1 parent cc8719f commit bbef534

File tree

10 files changed

+184
-42
lines changed

10 files changed

+184
-42
lines changed

src/hotspot/cpu/ppc/frame_ppc.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -363,7 +363,7 @@
363363
inline frame(intptr_t* sp, intptr_t* fp, address pc);
364364
inline frame(intptr_t* sp, address pc, kind knd = kind::nmethod);
365365
inline frame(intptr_t* sp, address pc, intptr_t* unextended_sp, intptr_t* fp = nullptr, CodeBlob* cb = nullptr);
366-
inline frame(intptr_t* sp, intptr_t* unextended_sp, intptr_t* fp, address pc, CodeBlob* cb, const ImmutableOopMap* oop_map);
366+
inline frame(intptr_t* sp, intptr_t* unextended_sp, intptr_t* fp, address pc, CodeBlob* cb, const ImmutableOopMap* oop_map = nullptr);
367367
inline frame(intptr_t* sp, intptr_t* unextended_sp, intptr_t* fp, address pc, CodeBlob* cb, const ImmutableOopMap* oop_map, bool on_heap);
368368

369369
private:

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

Lines changed: 41 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/*
2-
* Copyright (c) 2000, 2024, Oracle and/or its affiliates. All rights reserved.
3-
* Copyright (c) 2012, 2024 SAP SE. All rights reserved.
2+
* Copyright (c) 2000, 2025, Oracle and/or its affiliates. All rights reserved.
3+
* Copyright (c) 2012, 2025 SAP SE. All rights reserved.
44
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
55
*
66
* This code is free software; you can redistribute it and/or modify it
@@ -391,4 +391,43 @@ void frame::update_map_with_saved_link(RegisterMapT* map, intptr_t** link_addr)
391391
// Nothing to do.
392392
}
393393

394+
#if INCLUDE_JFR
395+
396+
// Static helper routines
397+
inline intptr_t* frame::sender_sp(intptr_t* fp) { return fp; }
398+
399+
// Extract common_abi parts.
400+
inline intptr_t* frame::fp(const intptr_t* sp) {
401+
assert(sp != nullptr, "invariant");
402+
return reinterpret_cast<intptr_t*>(((common_abi*)sp)->callers_sp);
403+
}
404+
405+
inline intptr_t* frame::link(const intptr_t* fp) { return frame::fp(fp); }
406+
407+
inline address frame::return_address(const intptr_t* sp) {
408+
assert(sp != nullptr, "invariant");
409+
return reinterpret_cast<address>(((common_abi*)sp)->lr);
410+
}
411+
412+
inline address frame::interpreter_return_address(const intptr_t* fp) { return frame::return_address(fp); }
413+
414+
// Extract java interpreter state parts.
415+
inline address frame::interpreter_bcp(const intptr_t* fp) {
416+
assert(fp != nullptr, "invariant");
417+
return reinterpret_cast<address>(*(fp + ijava_idx(bcp)));
418+
}
419+
420+
inline intptr_t* frame::interpreter_sender_sp(const intptr_t* fp) {
421+
assert(fp != nullptr, "invariant");
422+
return reinterpret_cast<intptr_t*>(*(fp + ijava_idx(sender_sp)));
423+
}
424+
425+
inline bool frame::is_interpreter_frame_setup_at(const intptr_t* fp, const void* sp) {
426+
assert(fp != nullptr, "invariant");
427+
assert(sp != nullptr, "invariant");
428+
return sp <= fp - ((frame::ijava_state_size + frame::top_ijava_frame_abi_size) >> LogBytesPerWord);
429+
}
430+
431+
#endif // INCLUDE_JFR
432+
394433
#endif // CPU_PPC_FRAME_PPC_INLINE_HPP

src/hotspot/cpu/ppc/interp_masm_ppc.hpp

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/*
2-
* Copyright (c) 2002, 2024, Oracle and/or its affiliates. All rights reserved.
3-
* Copyright (c) 2012, 2023 SAP SE. All rights reserved.
2+
* Copyright (c) 2002, 2025, Oracle and/or its affiliates. All rights reserved.
3+
* Copyright (c) 2012, 2025 SAP SE. All rights reserved.
44
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
55
*
66
* This code is free software; you can redistribute it and/or modify it
@@ -170,7 +170,11 @@ class InterpreterMacroAssembler: public MacroAssembler {
170170
void remove_activation(TosState state,
171171
bool throw_monitor_exception = true,
172172
bool install_monitor_exception = true);
173-
void merge_frames(Register Rtop_frame_sp, Register return_pc, Register Rscratch1, Register Rscratch2); // merge top frames
173+
JFR_ONLY(void enter_jfr_critical_section();)
174+
JFR_ONLY(void leave_jfr_critical_section();)
175+
void load_fp(Register fp);
176+
void remove_top_frame_given_fp(Register fp, Register sender_sp, Register sender_fp, Register return_pc, Register temp);
177+
void merge_frames(Register sender_sp, Register return_pc, Register temp1, Register temp2); // merge top frames
174178

175179
void add_monitor_to_stack(bool stack_is_empty, Register Rtemp1, Register Rtemp2);
176180

src/hotspot/cpu/ppc/interp_masm_ppc_64.cpp

Lines changed: 42 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -793,19 +793,27 @@ void InterpreterMacroAssembler::unlock_if_synchronized_method(TosState state,
793793
}
794794

795795
// Support function for remove_activation & Co.
796-
void InterpreterMacroAssembler::merge_frames(Register Rsender_sp, Register return_pc,
797-
Register Rscratch1, Register Rscratch2) {
798-
// Pop interpreter frame.
799-
ld(Rscratch1, 0, R1_SP); // *SP
800-
ld(Rsender_sp, _ijava_state_neg(sender_sp), Rscratch1); // top_frame_sp
801-
ld(Rscratch2, 0, Rscratch1); // **SP
802-
if (return_pc!=noreg) {
803-
ld(return_pc, _abi0(lr), Rscratch1); // LR
796+
void InterpreterMacroAssembler::load_fp(Register fp) {
797+
ld(fp, _abi0(callers_sp), R1_SP); // *SP
798+
}
799+
800+
void InterpreterMacroAssembler::remove_top_frame_given_fp(Register fp, Register sender_sp, Register sender_fp,
801+
Register return_pc, Register temp) {
802+
assert_different_registers(sender_sp, sender_fp, return_pc, temp);
803+
ld(sender_sp, _ijava_state_neg(sender_sp), fp);
804+
ld(sender_fp, _abi0(callers_sp), fp); // **SP
805+
if (return_pc != noreg) {
806+
ld(return_pc, _abi0(lr), fp); // last usage of fp, register can be reused
804807
}
808+
subf(temp, R1_SP, sender_sp); // sender_sp - SP
809+
stdux(sender_fp, R1_SP, temp); // atomically set *(SP = sender_sp) = sender_fp
810+
}
805811

806-
// Merge top frames.
807-
subf(Rscratch1, R1_SP, Rsender_sp); // top_frame_sp - SP
808-
stdux(Rscratch2, R1_SP, Rscratch1); // atomically set *(SP = top_frame_sp) = **SP
812+
void InterpreterMacroAssembler::merge_frames(Register sender_sp, Register return_pc,
813+
Register temp1, Register temp2) {
814+
Register fp = temp1, sender_fp = temp2;
815+
load_fp(fp);
816+
remove_top_frame_given_fp(fp, sender_sp, sender_fp, return_pc, /* temp */ fp);
809817
}
810818

811819
void InterpreterMacroAssembler::narrow(Register result) {
@@ -864,11 +872,16 @@ void InterpreterMacroAssembler::remove_activation(TosState state,
864872
bool install_monitor_exception) {
865873
BLOCK_COMMENT("remove_activation {");
866874

875+
unlock_if_synchronized_method(state, throw_monitor_exception, install_monitor_exception);
876+
867877
// The below poll is for the stack watermark barrier. It allows fixing up frames lazily,
868878
// that would normally not be safe to use. Such bad returns into unsafe territory of
869879
// the stack, will call InterpreterRuntime::at_unwind.
870-
Label slow_path;
871-
Label fast_path;
880+
Label slow_path, fast_path;
881+
Register fp = R22_tmp2;
882+
load_fp(fp);
883+
884+
JFR_ONLY(enter_jfr_critical_section();)
872885
safepoint_poll(slow_path, R11_scratch1, true /* at_return */, false /* in_nmethod */);
873886
b(fast_path);
874887
bind(slow_path);
@@ -880,8 +893,6 @@ void InterpreterMacroAssembler::remove_activation(TosState state,
880893
align(32);
881894
bind(fast_path);
882895

883-
unlock_if_synchronized_method(state, throw_monitor_exception, install_monitor_exception);
884-
885896
// Save result (push state before jvmti call and pop it afterwards) and notify jvmti.
886897
notify_method_exit(false, state, NotifyJVMTI, true);
887898

@@ -901,8 +912,7 @@ void InterpreterMacroAssembler::remove_activation(TosState state,
901912
// call could have a smaller SP, so that this compare succeeds for an
902913
// inner call of the method annotated with ReservedStack.
903914
ld_ptr(R0, JavaThread::reserved_stack_activation_offset(), R16_thread);
904-
ld_ptr(R11_scratch1, _abi0(callers_sp), R1_SP); // Load frame pointer.
905-
cmpld(CR0, R11_scratch1, R0);
915+
cmpld(CR0, fp, R0);
906916
blt_predict_taken(CR0, no_reserved_zone_enabling);
907917

908918
// Enable reserved zone again, throw stack overflow exception.
@@ -916,12 +926,26 @@ void InterpreterMacroAssembler::remove_activation(TosState state,
916926

917927
verify_oop(R17_tos, state);
918928

919-
merge_frames(/*top_frame_sp*/ R21_sender_SP, /*return_pc*/ R0, R11_scratch1, R12_scratch2);
929+
remove_top_frame_given_fp(fp, R21_sender_SP, R23_tmp3, /*return_pc*/ R0, R11_scratch1);
920930
mtlr(R0);
921931
pop_cont_fastpath();
932+
JFR_ONLY(leave_jfr_critical_section();)
933+
922934
BLOCK_COMMENT("} remove_activation");
923935
}
924936

937+
#if INCLUDE_JFR
938+
void InterpreterMacroAssembler::enter_jfr_critical_section() {
939+
li(R0, 1);
940+
stb(R0, in_bytes(SAMPLING_CRITICAL_SECTION_OFFSET_JFR), R16_thread);
941+
}
942+
943+
void InterpreterMacroAssembler::leave_jfr_critical_section() {
944+
li(R0, 0);
945+
stb(R0, in_bytes(SAMPLING_CRITICAL_SECTION_OFFSET_JFR), R16_thread);
946+
}
947+
#endif // INCLUDE_JFR
948+
925949
// Lock object
926950
//
927951
// Registers alive

src/hotspot/cpu/ppc/javaFrameAnchor_ppc.hpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/*
2-
* Copyright (c) 2002, 2023, Oracle and/or its affiliates. All rights reserved.
3-
* Copyright (c) 2012, 2014 SAP SE. All rights reserved.
2+
* Copyright (c) 2002, 2025, Oracle and/or its affiliates. All rights reserved.
3+
* Copyright (c) 2012, 2025 SAP SE. All rights reserved.
44
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
55
*
66
* This code is free software; you can redistribute it and/or modify it
@@ -73,6 +73,8 @@
7373

7474
address last_Java_pc(void) { return _last_Java_pc; }
7575

76+
intptr_t* last_Java_fp() const { return *(intptr_t**)_last_Java_sp; }
77+
7678
void set_last_Java_sp(intptr_t* sp) { OrderAccess::release(); _last_Java_sp = sp; }
7779

7880
#endif // CPU_PPC_JAVAFRAMEANCHOR_PPC_HPP

src/hotspot/cpu/ppc/sharedRuntime_ppc.cpp

Lines changed: 37 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2740,30 +2740,59 @@ nmethod *SharedRuntime::generate_native_wrapper(MacroAssembler *masm,
27402740
__ li(r_temp_2, 0);
27412741
__ stw(r_temp_2, in_bytes(JNIHandleBlock::top_offset()), r_temp_1);
27422742

2743+
// Prepare for return
2744+
// --------------------------------------------------------------------------
2745+
__ pop_frame();
2746+
__ restore_LR(R11);
27432747

27442748
// Check for pending exceptions.
27452749
// --------------------------------------------------------------------------
27462750
__ ld(r_temp_2, thread_(pending_exception));
27472751
__ cmpdi(CR0, r_temp_2, 0);
27482752
__ bne(CR0, handle_pending_exception);
27492753

2750-
// Return
2751-
// --------------------------------------------------------------------------
2752-
2753-
__ pop_frame();
2754-
__ restore_LR(R11);
2754+
#if INCLUDE_JFR
2755+
// We need to do a poll test after unwind in case the sampler
2756+
// managed to sample the native frame after returning to Java.
2757+
Label L_stub;
2758+
int safepoint_offset = __ offset();
2759+
if (!UseSIGTRAP) {
2760+
__ relocate(relocInfo::poll_return_type);
2761+
}
2762+
__ safepoint_poll(L_stub, r_temp_2, true /* at_return */, true /* in_nmethod: frame already popped */);
27552763
__ blr();
27562764

2765+
if (!UseSIGTRAP) {
2766+
assert(SharedRuntime::polling_page_return_handler_blob() != nullptr,
2767+
"polling page return stub not created yet");
2768+
address stub = SharedRuntime::polling_page_return_handler_blob()->entry_point();
2769+
2770+
__ bind(L_stub);
2771+
// Using pc relative address computation.
2772+
{
2773+
Label next_pc;
2774+
__ bl(next_pc);
2775+
__ bind(next_pc);
2776+
}
2777+
int current_offset = __ offset();
2778+
__ mflr(R12);
2779+
__ add_const_optimized(R12, R12, safepoint_offset - current_offset);
2780+
__ std(R12, in_bytes(JavaThread::saved_exception_pc_offset()), R16_thread);
2781+
2782+
__ add_const_optimized(R0, R29_TOC, MacroAssembler::offset_to_global_toc(stub));
2783+
__ mtctr(R0);
2784+
__ bctr();
2785+
}
2786+
#else // INCLUDE_JFR
2787+
__ blr();
2788+
#endif
27572789

27582790
// Handler for pending exceptions (out-of-line).
27592791
// --------------------------------------------------------------------------
27602792
// Since this is a native call, we know the proper exception handler
27612793
// is the empty function. We just pop this frame and then jump to
27622794
// forward_exception_entry.
27632795
__ bind(handle_pending_exception);
2764-
2765-
__ pop_frame();
2766-
__ restore_LR(R11);
27672796
__ b64_patchable((address)StubRoutines::forward_exception_entry(),
27682797
relocInfo::runtime_call_type);
27692798

src/hotspot/cpu/ppc/templateInterpreterGenerator_ppc.cpp

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1584,6 +1584,24 @@ address TemplateInterpreterGenerator::generate_native_entry(bool synchronized) {
15841584
__ st_ptr(R0, JavaThread::pending_jni_exception_check_fn_offset(), R16_thread);
15851585
}
15861586

1587+
#if INCLUDE_JFR
1588+
__ enter_jfr_critical_section();
1589+
1590+
// This poll test is to uphold the invariant that a JFR sampled frame
1591+
// must not return to its caller without a prior safepoint poll check.
1592+
// The earlier poll check in this routine is insufficient for this purpose
1593+
// because the thread has transitioned back to Java.
1594+
1595+
Label slow_path, fast_path;
1596+
__ safepoint_poll(slow_path, R11_scratch1, true /* at_return */, false /* in_nmethod */);
1597+
__ b(fast_path);
1598+
__ bind(slow_path);
1599+
__ call_VM_leaf(CAST_FROM_FN_PTR(address, InterpreterRuntime::at_unwind), R16_thread);
1600+
__ align(32);
1601+
__ bind(fast_path);
1602+
1603+
#endif // INCLUDE_JFR
1604+
15871605
__ reset_last_Java_frame();
15881606

15891607
// Jvmdi/jvmpi support. Whether we've got an exception pending or
@@ -1625,11 +1643,12 @@ address TemplateInterpreterGenerator::generate_native_entry(bool synchronized) {
16251643
__ lfd(F1_RET, _ijava_state_neg(fresult), R11_scratch1);
16261644
__ call_stub(result_handler_addr);
16271645

1628-
__ merge_frames(/*top_frame_sp*/ R21_sender_SP, /*return_pc*/ R0, R11_scratch1, R12_scratch2);
1646+
__ merge_frames(/*top_frame_sp*/ R21_sender_SP, /*return_pc*/ R12_scratch2, R11_scratch1, R0);
1647+
JFR_ONLY(__ leave_jfr_critical_section();)
16291648

16301649
// Must use the return pc which was loaded from the caller's frame
16311650
// as the VM uses return-pc-patching for deoptimization.
1632-
__ mtlr(R0);
1651+
__ mtlr(R12_scratch2);
16331652
__ blr();
16341653

16351654
//-----------------------------------------------------------------------------
@@ -1655,6 +1674,7 @@ address TemplateInterpreterGenerator::generate_native_entry(bool synchronized) {
16551674
R16_thread,
16561675
return_pc /* return pc */);
16571676
__ merge_frames(/*top_frame_sp*/ R21_sender_SP, noreg, R11_scratch1, R12_scratch2);
1677+
JFR_ONLY(__ leave_jfr_critical_section();)
16581678

16591679
// Load the PC of the exception handler into LR.
16601680
__ mtlr(R3_RET);

src/hotspot/cpu/ppc/templateTable_ppc_64.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1748,16 +1748,18 @@ void TemplateTable::branch(bool is_jsr, bool is_wide) {
17481748
const Register osr_nmethod = R31;
17491749
__ mr(osr_nmethod, R3_RET);
17501750
__ set_top_ijava_frame_at_SP_as_last_Java_frame(R1_SP, R11_scratch1);
1751+
JFR_ONLY(__ enter_jfr_critical_section();)
17511752
__ call_VM_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::OSR_migration_begin), R16_thread);
17521753
__ reset_last_Java_frame();
17531754
// OSR buffer is in ARG1.
17541755

17551756
// Remove the interpreter frame.
1756-
__ merge_frames(/*top_frame_sp*/ R21_sender_SP, /*return_pc*/ R0, R11_scratch1, R12_scratch2);
1757+
__ merge_frames(/*top_frame_sp*/ R21_sender_SP, /*return_pc*/ R12_scratch2, R11_scratch1, R0);
1758+
JFR_ONLY(__ leave_jfr_critical_section();)
17571759

17581760
// Jump to the osr code.
17591761
__ ld(R11_scratch1, nmethod::osr_entry_point_offset(), osr_nmethod);
1760-
__ mtlr(R0);
1762+
__ mtlr(R12_scratch2);
17611763
__ mtctr(R11_scratch1);
17621764
__ bctr();
17631765

src/hotspot/os_cpu/aix_ppc/os_aix_ppc.cpp

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -138,9 +138,20 @@ frame os::fetch_compiled_frame_from_context(const void* ucVoid) {
138138
return frame(sp, lr, frame::kind::unknown);
139139
}
140140

141+
#ifdef ASSERT
142+
static bool is_interpreter(const ucontext_t* uc) {
143+
assert(uc != nullptr, "invariant");
144+
address pc = os::Posix::ucontext_get_pc(uc);
145+
assert(pc != nullptr, "invariant");
146+
return Interpreter::contains(pc);
147+
}
148+
#endif
149+
141150
intptr_t* os::fetch_bcp_from_context(const void* ucVoid) {
142-
Unimplemented();
143-
return nullptr;
151+
assert(ucVoid != nullptr, "invariant");
152+
const ucontext_t* uc = (const ucontext_t*)ucVoid;
153+
assert(is_interpreter(uc), "invariant");
154+
return reinterpret_cast<intptr_t*>(uc->uc_mcontext.jmp_context.gpr[14]); // R14_bcp
144155
}
145156

146157
frame os::get_sender_for_C_frame(frame* fr) {

src/hotspot/os_cpu/linux_ppc/os_linux_ppc.cpp

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -170,9 +170,20 @@ frame os::fetch_compiled_frame_from_context(const void* ucVoid) {
170170
return frame(sp, lr, frame::kind::unknown);
171171
}
172172

173+
#ifdef ASSERT
174+
static bool is_interpreter(const ucontext_t* uc) {
175+
assert(uc != nullptr, "invariant");
176+
address pc = os::Posix::ucontext_get_pc(uc);
177+
assert(pc != nullptr, "invariant");
178+
return Interpreter::contains(pc);
179+
}
180+
#endif
181+
173182
intptr_t* os::fetch_bcp_from_context(const void* ucVoid) {
174-
Unimplemented();
175-
return nullptr;
183+
assert(ucVoid != nullptr, "invariant");
184+
const ucontext_t* uc = (const ucontext_t*)ucVoid;
185+
assert(is_interpreter(uc), "invariant");
186+
return reinterpret_cast<intptr_t*>(uc->uc_mcontext.regs->gpr[14]); // R14_bcp
176187
}
177188

178189
frame os::get_sender_for_C_frame(frame* fr) {

0 commit comments

Comments
 (0)