8261957: [PPC64] Support for Concurrent Thread-Stack Processing

Reviewed-by: lucy, nradomski
This commit is contained in:
Martin Doerr 2021-03-31 09:37:16 +00:00
parent 8a4a9117f5
commit 9061271b0b
16 changed files with 215 additions and 51 deletions

@ -1,6 +1,6 @@
/*
* Copyright (c) 1999, 2020, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012, 2018 SAP SE. All rights reserved.
* Copyright (c) 1999, 2021, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012, 2021 SAP SE. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -39,7 +39,29 @@
#define __ ce->masm()->
void C1SafepointPollStub::emit_code(LIR_Assembler* ce) {
ShouldNotReachHere();
if (UseSIGTRAP) {
DEBUG_ONLY( __ should_not_reach_here("C1SafepointPollStub::emit_code"); )
} else {
assert(SharedRuntime::polling_page_return_handler_blob() != NULL,
"polling page return stub not created yet");
address stub = SharedRuntime::polling_page_return_handler_blob()->entry_point();
__ bind(_entry);
// Using pc relative address computation.
{
Label next_pc;
__ bl(next_pc);
__ bind(next_pc);
}
int current_offset = __ offset();
__ mflr(R12);
__ add_const_optimized(R12, R12, safepoint_offset() - current_offset);
__ std(R12, in_bytes(JavaThread::saved_exception_pc_offset()), R16_thread);
__ add_const_optimized(R0, R29_TOC, MacroAssembler::offset_to_global_toc(stub));
__ mtctr(R0);
__ bctr();
}
}
RangeCheckStub::RangeCheckStub(CodeEmitInfo* info, LIR_Opr index, LIR_Opr array)

@ -1320,8 +1320,8 @@ void LIR_Assembler::reg2mem(LIR_Opr from_reg, LIR_Opr dest, BasicType type,
void LIR_Assembler::return_op(LIR_Opr result, C1SafepointPollStub* code_stub) {
const Register return_pc = R31; // Must survive C-call to enable_stack_reserved_zone().
const Register polling_page = R12;
const Register return_pc = R31; // Must survive C-call to enable_stack_reserved_zone().
const Register temp = R12;
// Pop the stack before the safepoint code.
int frame_size = initial_frame_size_in_bytes();
@ -1331,8 +1331,6 @@ void LIR_Assembler::return_op(LIR_Opr result, C1SafepointPollStub* code_stub) {
__ pop_frame();
}
__ ld(polling_page, in_bytes(Thread::polling_page_offset()), R16_thread);
// Restore return pc relative to callers' sp.
__ ld(return_pc, _abi0(lr), R1_SP);
// Move return pc to LR.
@ -1344,8 +1342,11 @@ void LIR_Assembler::return_op(LIR_Opr result, C1SafepointPollStub* code_stub) {
// We need to mark the code position where the load from the safepoint
// polling page was emitted as relocInfo::poll_return_type here.
__ relocate(relocInfo::poll_return_type);
__ load_from_polling_page(polling_page);
if (!UseSIGTRAP) {
code_stub->set_safepoint_offset(__ offset());
__ relocate(relocInfo::poll_return_type);
}
__ safepoint_poll(*code_stub->entry(), temp, true /* at_return */, true /* in_nmethod */);
// Return.
__ blr();

@ -0,0 +1,57 @@
/*
* Copyright (c) 2020, 2021, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2021 SAP SE. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
#include "precompiled.hpp"
#include "macroAssembler_ppc.inline.hpp"
#include "opto/compile.hpp"
#include "opto/node.hpp"
#include "opto/output.hpp"
#include "runtime/sharedRuntime.hpp"
#define __ masm.
void C2SafepointPollStubTable::emit_stub_impl(MacroAssembler& masm, C2SafepointPollStub* entry) const {
assert(SharedRuntime::polling_page_return_handler_blob() != NULL,
"polling page return stub not created yet");
address stub = SharedRuntime::polling_page_return_handler_blob()->entry_point();
__ bind(entry->_stub_label);
// Using pc relative address computation.
{
Label next_pc;
__ bl(next_pc);
__ bind(next_pc);
}
int current_offset = __ offset();
// Code size should not depend on offset: see _stub_size computation in output.cpp
__ load_const32(R12, entry->_safepoint_offset - current_offset);
__ mflr(R0);
__ add(R12, R12, R0);
__ std(R12, in_bytes(JavaThread::saved_exception_pc_offset()), R16_thread);
__ add_const_optimized(R0, R29_TOC, MacroAssembler::offset_to_global_toc(stub));
__ mtctr(R0);
__ bctr();
}
#undef __

@ -1,6 +1,6 @@
/*
* Copyright (c) 2000, 2021, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012, 2017 SAP SE. All rights reserved.
* Copyright (c) 2012, 2021 SAP SE. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -37,6 +37,7 @@
#include "runtime/monitorChunk.hpp"
#include "runtime/os.inline.hpp"
#include "runtime/signature.hpp"
#include "runtime/stackWatermarkSet.hpp"
#include "runtime/stubCodeGenerator.hpp"
#include "runtime/stubRoutines.hpp"
#ifdef COMPILER1
@ -229,7 +230,7 @@ address* frame::compiled_sender_pc_addr(CodeBlob* cb) const {
return sender_pc_addr();
}
frame frame::sender(RegisterMap* map) const {
frame frame::sender_raw(RegisterMap* map) const {
// Default is we do have to follow them. The sender_for_xxx will
// update it accordingly.
map->set_include_argument_oops(false);
@ -246,6 +247,16 @@ frame frame::sender(RegisterMap* map) const {
return frame(sender_sp(), sender_pc());
}
frame frame::sender(RegisterMap* map) const {
frame result = sender_raw(map);
if (map->process_frames()) {
StackWatermarkSet::on_iteration(map->thread(), result);
}
return result;
}
void frame::patch_pc(Thread* thread, address pc) {
assert(_cb == CodeCache::find_blob(pc), "unexpected pc");
if (TracePcPatching) {

@ -1,6 +1,6 @@
/*
* Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012, 2015 SAP SE. All rights reserved.
* Copyright (c) 2000, 2021, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012, 2021 SAP SE. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -418,4 +418,7 @@
static jint interpreter_frame_expression_stack_direction() { return -1; }
// returns the sending frame, without applying any barriers
frame sender_raw(RegisterMap* map) const;
#endif // CPU_PPC_FRAME_PPC_HPP

@ -827,6 +827,7 @@ void InterpreterMacroAssembler::narrow(Register result) {
// Remove activation.
//
// Apply stack watermark barrier.
// Unlock the receiver if this is a synchronized method.
// Unlock any Java monitors from synchronized blocks.
// Remove the activation from the stack.
@ -842,6 +843,23 @@ void InterpreterMacroAssembler::remove_activation(TosState state,
bool throw_monitor_exception,
bool install_monitor_exception) {
BLOCK_COMMENT("remove_activation {");
// The below poll is for the stack watermark barrier. It allows fixing up frames lazily,
// that would normally not be safe to use. Such bad returns into unsafe territory of
// the stack, will call InterpreterRuntime::at_unwind.
Label slow_path;
Label fast_path;
safepoint_poll(slow_path, R11_scratch1, true /* at_return */, false /* in_nmethod */);
b(fast_path);
bind(slow_path);
push(state);
set_last_Java_frame(R1_SP, noreg);
call_VM_leaf(CAST_FROM_FN_PTR(address, InterpreterRuntime::at_unwind), R16_thread);
reset_last_Java_frame();
pop(state);
align(32);
bind(fast_path);
unlock_if_synchronized_method(state, throw_monitor_exception, install_monitor_exception);
// Save result (push state before jvmti call and pop it afterwards) and notify jvmti.

@ -3057,11 +3057,32 @@ void MacroAssembler::compiler_fast_unlock_object(ConditionRegister flag, Registe
// flag == NE indicates failure
}
void MacroAssembler::safepoint_poll(Label& slow_path, Register temp_reg) {
ld(temp_reg, in_bytes(Thread::polling_word_offset()), R16_thread);
// Armed page has poll_bit set.
andi_(temp_reg, temp_reg, SafepointMechanism::poll_bit());
bne(CCR0, slow_path);
void MacroAssembler::safepoint_poll(Label& slow_path, Register temp, bool at_return, bool in_nmethod) {
ld(temp, in_bytes(Thread::polling_word_offset()), R16_thread);
if (at_return) {
if (in_nmethod) {
if (UseSIGTRAP) {
// Use Signal Handler.
relocate(relocInfo::poll_return_type);
td(traptoGreaterThanUnsigned, R1_SP, temp);
} else {
cmpld(CCR0, R1_SP, temp);
// Stub may be out of range for short conditional branch.
bc_far_optimized(Assembler::bcondCRbiIs1, bi0(CCR0, Assembler::greater), slow_path);
}
} else { // Not in nmethod.
// Frame still on stack, need to get fp.
Register fp = R0;
ld(fp, _abi0(callers_sp), R1_SP);
cmpld(CCR0, fp, temp);
bgt(CCR0, slow_path);
}
} else { // Normal safepoint poll. Not at return.
assert(!in_nmethod, "should use load_from_polling_page");
andi_(temp, temp, SafepointMechanism::poll_bit());
bne(CCR0, slow_path);
}
}
void MacroAssembler::resolve_jobject(Register value, Register tmp1, Register tmp2,

@ -666,7 +666,7 @@ class MacroAssembler: public Assembler {
bool try_bias = UseBiasedLocking, bool use_rtm = false);
// Check if safepoint requested and if so branch
void safepoint_poll(Label& slow_path, Register temp_reg);
void safepoint_poll(Label& slow_path, Register temp, bool at_return, bool in_nmethod);
void resolve_jobject(Register value, Register tmp1, Register tmp2,
MacroAssembler::PreservationLevel preservation_level);

@ -1,6 +1,6 @@
/*
* Copyright (c) 2002, 2020, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012, 2018 SAP SE. All rights reserved.
* Copyright (c) 2002, 2021, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012, 2021 SAP SE. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -83,7 +83,6 @@ class NativeInstruction {
#endif
bool is_safepoint_poll() {
// Is the current instruction a POTENTIAL read access to the polling page?
// The current arguments of the instruction are not checked!
if (USE_POLL_BIT_ONLY) {
int encoding = SafepointMechanism::poll_bit();
@ -93,6 +92,12 @@ class NativeInstruction {
return MacroAssembler::is_load_from_polling_page(long_at(0), NULL);
}
bool is_safepoint_poll_return() {
// Safepoint poll at nmethod return with watermark check.
return MacroAssembler::is_td(long_at(0), Assembler::traptoGreaterThanUnsigned,
/* R1_SP */ 1, /* any reg */ -1);
}
address get_stack_bang_address(void *ucontext) {
// If long_at(0) is not a stack bang, return 0. Otherwise, return
// banged address.

@ -1,6 +1,6 @@
//
// Copyright (c) 2011, 2021, Oracle and/or its affiliates. All rights reserved.
// Copyright (c) 2012, 2020 SAP SE. All rights reserved.
// Copyright (c) 2012, 2021 SAP SE. All rights reserved.
// DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
//
// This code is free software; you can redistribute it and/or modify it
@ -1562,7 +1562,7 @@ void MachEpilogNode::format(PhaseRegAlloc *ra_, outputStream *st) const {
st->print("pop frame\n\t");
if (do_polling() && C->is_method_compilation()) {
st->print("touch polling page\n\t");
st->print("safepoint poll\n\t");
}
}
#endif
@ -1577,18 +1577,11 @@ void MachEpilogNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const {
const bool method_needs_polling = do_polling() && C->is_method_compilation();
const bool method_is_frameless = false /* TODO: PPC port C->is_frameless_method()*/;
const Register return_pc = R31; // Must survive C-call to enable_stack_reserved_zone().
const Register polling_page = R12;
const Register temp = R12;
if (!method_is_frameless) {
// Restore return pc relative to callers' sp.
__ ld(return_pc, ((int)framesize) + _abi0(lr), R1_SP);
}
if (method_needs_polling) {
__ ld(polling_page, in_bytes(JavaThread::polling_page_offset()), R16_thread);
}
if (!method_is_frameless) {
// Move return pc to LR.
__ mtlr(return_pc);
// Pop frame (fixed frame-size).
@ -1600,10 +1593,13 @@ void MachEpilogNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const {
}
if (method_needs_polling) {
// We need to mark the code position where the load from the safepoint
// polling page was emitted as relocInfo::poll_return_type here.
__ relocate(relocInfo::poll_return_type);
__ load_from_polling_page(polling_page);
Label dummy_label;
Label* code_stub = &dummy_label;
if (!UseSIGTRAP && !C->output()->in_scratch_emit_size()) {
code_stub = &C->output()->safepoint_poll_table()->add_safepoint(__ offset());
__ relocate(relocInfo::poll_return_type);
}
__ safepoint_poll(*code_stub, temp, true /* at_return */, true /* in_nmethod */);
}
}

@ -2262,7 +2262,10 @@ nmethod *SharedRuntime::generate_native_wrapper(MacroAssembler *masm,
if (is_critical_native) {
Label needs_safepoint;
Register sync_state = r_temp_5;
__ safepoint_poll(needs_safepoint, sync_state);
// Note: We should not reach here with active stack watermark. There's no safepoint between
// start of the native wrapper and this check where it could have been added.
// We don't check the watermark in the fast path.
__ safepoint_poll(needs_safepoint, sync_state, false /* at_return */, false /* in_nmethod */);
Register suspend_flags = r_temp_6;
__ lwz(suspend_flags, thread_(suspend_flags));
@ -2309,7 +2312,7 @@ nmethod *SharedRuntime::generate_native_wrapper(MacroAssembler *masm,
// No synchronization in progress nor yet synchronized
// (cmp-br-isync on one path, release (same as acquire on PPC64) on the other path).
__ safepoint_poll(sync, sync_state);
__ safepoint_poll(sync, sync_state, true /* at_return */, false /* in_nmethod */);
// Not suspended.
// TODO: PPC port assert(4 == Thread::sz_suspend_flags(), "unexpected field size");
@ -3008,7 +3011,7 @@ SafepointBlob* SharedRuntime::generate_handler_blob(address call_ptr, int poll_t
if (cause_return) {
// Nothing to do here. The frame has already been popped in MachEpilogNode.
// Register LR already contains the return pc.
return_pc_location = RegisterSaver::return_pc_is_lr;
return_pc_location = RegisterSaver::return_pc_is_pre_saved;
} else {
// Use thread()->saved_exception_pc() as return pc.
return_pc_location = RegisterSaver::return_pc_is_thread_saved_exception_pc;

@ -1449,7 +1449,7 @@ address TemplateInterpreterGenerator::generate_native_entry(bool synchronized) {
Label do_safepoint, sync_check_done;
// No synchronization in progress nor yet synchronized.
__ safepoint_poll(do_safepoint, sync_state);
__ safepoint_poll(do_safepoint, sync_state, true /* at_return */, false /* in_nmethod */);
// Not suspended.
// TODO PPC port assert(4 == Thread::sz_suspend_flags(), "unexpected field size");
@ -1749,7 +1749,7 @@ address TemplateInterpreterGenerator::generate_CRC32_update_entry() {
// Safepoint check
const Register sync_state = R11_scratch1;
__ safepoint_poll(slow_path, sync_state);
__ safepoint_poll(slow_path, sync_state, false /* at_return */, false /* in_nmethod */);
// We don't generate local frame and don't align stack because
// we not even call stub code (we generate the code inline)
@ -1803,7 +1803,7 @@ address TemplateInterpreterGenerator::generate_CRC32_updateBytes_entry(AbstractI
// Safepoint check
const Register sync_state = R11_scratch1;
__ safepoint_poll(slow_path, sync_state);
__ safepoint_poll(slow_path, sync_state, false /* at_return */, false /* in_nmethod */);
// We don't generate local frame and don't align stack because
// we not even call stub code (we generate the code inline)

@ -1,6 +1,6 @@
/*
* Copyright (c) 1997, 2020, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012, 2020 SAP SE. All rights reserved.
* Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012, 2021 SAP SE. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -98,6 +98,7 @@ public:
// PPC64 supports fast class initialization checks for static methods.
static bool supports_fast_class_init_checks() { return true; }
constexpr static bool supports_stack_watermark_barrier() { return true; }
static bool is_determine_features_test_running() { return _is_determine_features_test_running; }
// CPU instruction support

@ -1,5 +1,5 @@
/*
* Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2017, 2021, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -110,6 +110,6 @@ void SafepointMechanism::pd_initialize() {
}
uintptr_t bad_page_val = reinterpret_cast<uintptr_t>(map_address),
good_page_val = bad_page_val + os::vm_page_size();
_poll_page_armed_value = bad_page_val + poll_bit();
_poll_page_armed_value = bad_page_val;
_poll_page_disarmed_value = good_page_val;
}

@ -1,6 +1,6 @@
/*
* Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012, 2020 SAP SE. All rights reserved.
* Copyright (c) 2012, 2021 SAP SE. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -221,6 +221,7 @@ bool PosixSignals::pd_hotspot_signal_handler(int sig, siginfo_t* info,
// happens rarely. In heap based and disjoint base compressd oop modes also loads
// are used for null checks.
CodeBlob *cb = NULL;
int stop_type = -1;
// Handle signal from NativeJump::patch_verified_entry().
if (sig == SIGILL && nativeInstruction_at(pc)->is_sigill_zombie_not_entrant()) {
@ -231,9 +232,11 @@ bool PosixSignals::pd_hotspot_signal_handler(int sig, siginfo_t* info,
goto run_stub;
}
else if (USE_POLL_BIT_ONLY
? (sig == SIGTRAP && ((NativeInstruction*)pc)->is_safepoint_poll())
: (sig == SIGSEGV && SafepointMechanism::is_poll_address(addr))) {
else if ((sig == USE_POLL_BIT_ONLY ? SIGTRAP : SIGSEGV) &&
((NativeInstruction*)pc)->is_safepoint_poll() &&
CodeCache::contains((void*) pc) &&
((cb = CodeCache::find_blob(pc)) != NULL) &&
cb->is_compiled()) {
if (TraceTraps) {
tty->print_cr("trap: safepoint_poll at " INTPTR_FORMAT " (%s)", p2i(pc),
USE_POLL_BIT_ONLY ? "SIGTRAP" : "SIGSEGV");
@ -242,6 +245,18 @@ bool PosixSignals::pd_hotspot_signal_handler(int sig, siginfo_t* info,
goto run_stub;
}
else if (UseSIGTRAP && sig == SIGTRAP &&
((NativeInstruction*)pc)->is_safepoint_poll_return() &&
CodeCache::contains((void*) pc) &&
((cb = CodeCache::find_blob(pc)) != NULL) &&
cb->is_compiled()) {
if (TraceTraps) {
tty->print_cr("trap: safepoint_poll at return at " INTPTR_FORMAT " (nmethod)", p2i(pc));
}
stub = SharedRuntime::polling_page_return_handler_blob()->entry_point();
goto run_stub;
}
// SIGTRAP-based ic miss check in compiled code.
else if (sig == SIGTRAP && TrapBasedICMissChecks &&
nativeInstruction_at(pc)->is_sigtrap_ic_miss_check()) {

@ -1,6 +1,6 @@
/*
* Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012, 2019 SAP SE. All rights reserved.
* Copyright (c) 2012, 2021 SAP SE. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -270,6 +270,17 @@ bool PosixSignals::pd_hotspot_signal_handler(int sig, siginfo_t* info,
stub = SharedRuntime::get_poll_stub(pc);
}
else if (UseSIGTRAP && sig == SIGTRAP &&
((NativeInstruction*)pc)->is_safepoint_poll_return() &&
CodeCache::contains((void*) pc) &&
((cb = CodeCache::find_blob(pc)) != NULL) &&
cb->is_compiled()) {
if (TraceTraps) {
tty->print_cr("trap: safepoint_poll at return at " INTPTR_FORMAT " (nmethod)", p2i(pc));
}
stub = SharedRuntime::polling_page_return_handler_blob()->entry_point();
}
// SIGTRAP-based ic miss check in compiled code.
else if (sig == SIGTRAP && TrapBasedICMissChecks &&
nativeInstruction_at(pc)->is_sigtrap_ic_miss_check()) {