8276927: [PPC64] Port shenandoahgc to linux on ppc64le

Reviewed-by: rkennke, ihse, mdoerr
This commit is contained in:
Niklas Radomski 2021-11-18 19:00:58 +00:00 committed by Martin Doerr
parent 8db0c361a3
commit 57eb864765
8 changed files with 1521 additions and 2 deletions

View File

@ -307,7 +307,8 @@ AC_DEFUN_ONCE([JVM_FEATURES_CHECK_SHENANDOAHGC],
JVM_FEATURES_CHECK_AVAILABILITY(shenandoahgc, [
AC_MSG_CHECKING([if platform is supported by Shenandoah])
if test "x$OPENJDK_TARGET_CPU_ARCH" = "xx86" || \
test "x$OPENJDK_TARGET_CPU" = "xaarch64" ; then
test "x$OPENJDK_TARGET_CPU" = "xaarch64" || \
test "x$OPENJDK_TARGET_CPU" = "xppc64le"; then
AC_MSG_RESULT([yes])
else
AC_MSG_RESULT([no, $OPENJDK_TARGET_CPU])

View File

@ -149,6 +149,7 @@ ifeq ($(call check-jvm-feature, compiler2), true)
ifeq ($(call check-jvm-feature, shenandoahgc), true)
AD_SRC_FILES += $(call uniq, $(wildcard $(foreach d, $(AD_SRC_ROOTS), \
$d/cpu/$(HOTSPOT_TARGET_CPU_ARCH)/gc/shenandoah/shenandoah_$(HOTSPOT_TARGET_CPU).ad \
$d/cpu/$(HOTSPOT_TARGET_CPU_ARCH)/gc/shenandoah/shenandoah_$(HOTSPOT_TARGET_CPU_ARCH).ad \
)))
endif

View File

@ -151,6 +151,8 @@ void BarrierSetAssembler::nmethod_entry_barrier(MacroAssembler* masm, Register t
assert_different_registers(tmp, R0);
__ block_comment("nmethod_entry_barrier (nmethod_entry_barrier) {");
// Load stub address using toc (fixed instruction size, unlike load_const_optimized)
__ calculate_address_from_global_toc(tmp, StubRoutines::ppc::nmethod_entry_barrier(),
true, true, false); // 2 instructions
@ -167,6 +169,8 @@ void BarrierSetAssembler::nmethod_entry_barrier(MacroAssembler* masm, Register t
// Oops may have been changed; exploiting isync semantics (used as acquire) to make those updates observable.
__ isync();
__ block_comment("} nmethod_entry_barrier (nmethod_entry_barrier)");
}
void BarrierSetAssembler::c2i_entry_barrier(MacroAssembler *masm, Register tmp1, Register tmp2, Register tmp3) {
@ -177,6 +181,8 @@ void BarrierSetAssembler::c2i_entry_barrier(MacroAssembler *masm, Register tmp1,
assert_different_registers(tmp1, tmp2, tmp3);
__ block_comment("c2i_entry_barrier (c2i_entry_barrier) {");
Register tmp1_class_loader_data = tmp1;
Label bad_call, skip_barrier;
@ -207,4 +213,6 @@ void BarrierSetAssembler::c2i_entry_barrier(MacroAssembler *masm, Register tmp1,
__ bctr();
__ bind(skip_barrier);
__ block_comment("} c2i_entry_barrier (c2i_entry_barrier)");
}

View File

@ -0,0 +1,162 @@
/*
* Copyright (c) 2018, 2021, Red Hat, Inc. 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
* 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 "asm/macroAssembler.inline.hpp"
#include "c1/c1_LIRAssembler.hpp"
#include "c1/c1_MacroAssembler.hpp"
#include "gc/shenandoah/shenandoahBarrierSet.hpp"
#include "gc/shenandoah/shenandoahBarrierSetAssembler.hpp"
#include "gc/shenandoah/c1/shenandoahBarrierSetC1.hpp"
#define __ masm->masm()->
void LIR_OpShenandoahCompareAndSwap::emit_code(LIR_Assembler *masm) {
__ block_comment("LIR_OpShenandoahCompareAndSwap (shenandaohgc) {");
Register addr = _addr->as_register_lo();
Register new_val = _new_value->as_register();
Register cmp_val = _cmp_value->as_register();
Register tmp1 = _tmp1->as_register();
Register tmp2 = _tmp2->as_register();
Register result = result_opr()->as_register();
if (ShenandoahIUBarrier) {
ShenandoahBarrierSet::assembler()->iu_barrier(masm->masm(), new_val, tmp1, tmp2,
MacroAssembler::PRESERVATION_FRAME_LR_GP_FP_REGS);
}
if (UseCompressedOops) {
__ encode_heap_oop(cmp_val, cmp_val);
__ encode_heap_oop(new_val, new_val);
}
// Due to the memory barriers emitted in ShenandoahBarrierSetC1::atomic_cmpxchg_at_resolved,
// there is no need to specify stronger memory semantics.
ShenandoahBarrierSet::assembler()->cmpxchg_oop(masm->masm(), addr, cmp_val, new_val, tmp1, tmp2,
false, result);
if (UseCompressedOops) {
__ decode_heap_oop(cmp_val);
__ decode_heap_oop(new_val);
}
__ block_comment("} LIR_OpShenandoahCompareAndSwap (shenandaohgc)");
}
#undef __
#ifdef ASSERT
#define __ gen->lir(__FILE__, __LINE__)->
#else
#define __ gen->lir()->
#endif
LIR_Opr ShenandoahBarrierSetC1::atomic_cmpxchg_at_resolved(LIRAccess &access, LIRItem &cmp_value, LIRItem &new_value) {
BasicType bt = access.type();
if (access.is_oop()) {
LIRGenerator* gen = access.gen();
if (ShenandoahCASBarrier) {
if (support_IRIW_for_not_multiple_copy_atomic_cpu) {
__ membar();
} else {
__ membar_release();
}
}
if (ShenandoahSATBBarrier) {
pre_barrier(gen, access.access_emit_info(), access.decorators(), access.resolved_addr(),
LIR_OprFact::illegalOpr);
}
if (ShenandoahCASBarrier) {
cmp_value.load_item();
new_value.load_item();
LIR_Opr t1 = gen->new_register(T_OBJECT);
LIR_Opr t2 = gen->new_register(T_OBJECT);
LIR_Opr addr = access.resolved_addr()->as_address_ptr()->base();
LIR_Opr result = gen->new_register(T_INT);
__ append(new LIR_OpShenandoahCompareAndSwap(addr, cmp_value.result(), new_value.result(), t1, t2, result));
if (support_IRIW_for_not_multiple_copy_atomic_cpu) {
__ membar_acquire();
} else {
__ membar();
}
return result;
}
}
return BarrierSetC1::atomic_cmpxchg_at_resolved(access, cmp_value, new_value);
}
LIR_Opr ShenandoahBarrierSetC1::atomic_xchg_at_resolved(LIRAccess &access, LIRItem &value) {
LIRGenerator* gen = access.gen();
BasicType type = access.type();
LIR_Opr result = gen->new_register(type);
value.load_item();
LIR_Opr value_opr = value.result();
if (support_IRIW_for_not_multiple_copy_atomic_cpu) {
__ membar();
} else {
__ membar_release();
}
if (access.is_oop()) {
value_opr = iu_barrier(access.gen(), value_opr, access.access_emit_info(), access.decorators());
}
assert(type == T_INT || is_reference_type(type) LP64_ONLY( || type == T_LONG ), "unexpected type");
LIR_Opr tmp_xchg = gen->new_register(T_INT);
__ xchg(access.resolved_addr(), value_opr, result, tmp_xchg);
if (access.is_oop()) {
result = load_reference_barrier_impl(access.gen(), result, LIR_OprFact::addressConst(0),
access.decorators());
LIR_Opr tmp_barrier = gen->new_register(type);
__ move(result, tmp_barrier);
result = tmp_barrier;
if (ShenandoahSATBBarrier) {
pre_barrier(access.gen(), access.access_emit_info(), access.decorators(), LIR_OprFact::illegalOpr, result);
}
}
if (support_IRIW_for_not_multiple_copy_atomic_cpu) {
__ membar_acquire();
} else {
__ membar();
}
return result;
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,118 @@
/*
* Copyright (c) 2018, 2021, Red Hat, Inc. 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
* 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.
*
*/
#ifndef CPU_PPC_GC_SHENANDOAH_SHENANDOAHBARRIERSETASSEMBLER_PPC_HPP
#define CPU_PPC_GC_SHENANDOAH_SHENANDOAHBARRIERSETASSEMBLER_PPC_HPP
#include "asm/macroAssembler.hpp"
#include "gc/shared/barrierSetAssembler.hpp"
#include "gc/shenandoah/shenandoahBarrierSet.hpp"
#ifdef COMPILER1
class LIR_Assembler;
class ShenandoahPreBarrierStub;
class ShenandoahLoadReferenceBarrierStub;
class StubAssembler;
#endif
class StubCodeGenerator;
class ShenandoahBarrierSetAssembler: public BarrierSetAssembler {
private:
/* ==== Actual barrier implementations ==== */
void satb_write_barrier_impl(MacroAssembler* masm, DecoratorSet decorators,
Register base, RegisterOrConstant ind_or_offs,
Register pre_val,
Register tmp1, Register tmp2,
MacroAssembler::PreservationLevel preservation_level);
void load_reference_barrier_impl(MacroAssembler* masm, DecoratorSet decorators,
Register base, RegisterOrConstant ind_or_offs,
Register dst,
Register tmp1, Register tmp2,
MacroAssembler::PreservationLevel preservation_level);
/* ==== Helper methods for barrier implementations ==== */
void resolve_forward_pointer_not_null(MacroAssembler* masm, Register dst, Register tmp);
public:
/* ==== C1 stubs ==== */
#ifdef COMPILER1
void gen_pre_barrier_stub(LIR_Assembler* ce, ShenandoahPreBarrierStub* stub);
void gen_load_reference_barrier_stub(LIR_Assembler* ce, ShenandoahLoadReferenceBarrierStub* stub);
void generate_c1_pre_barrier_runtime_stub(StubAssembler* sasm);
void generate_c1_load_reference_barrier_runtime_stub(StubAssembler* sasm, DecoratorSet decorators);
#endif
/* ==== Available barriers (facades of the actual implementations) ==== */
void satb_write_barrier(MacroAssembler* masm,
Register base, RegisterOrConstant ind_or_offs,
Register tmp1, Register tmp2, Register tmp3,
MacroAssembler::PreservationLevel preservation_level);
void iu_barrier(MacroAssembler* masm,
Register val,
Register tmp1, Register tmp2,
MacroAssembler::PreservationLevel preservation_level, DecoratorSet decorators = 0);
void load_reference_barrier(MacroAssembler* masm, DecoratorSet decorators,
Register base, RegisterOrConstant ind_or_offs,
Register dst,
Register tmp1, Register tmp2,
MacroAssembler::PreservationLevel preservation_level);
/* ==== Helper methods used by C1 and C2 ==== */
void cmpxchg_oop(MacroAssembler* masm, Register base_addr, Register expected, Register new_val,
Register tmp1, Register tmp2,
bool is_cae, Register result);
/* ==== Access api ==== */
virtual void arraycopy_prologue(MacroAssembler* masm, DecoratorSet decorators, BasicType type,
Register src, Register dst, Register count, Register preserve1, Register preserve2);
virtual void store_at(MacroAssembler* masm, DecoratorSet decorators, BasicType type,
Register base, RegisterOrConstant ind_or_offs, Register val,
Register tmp1, Register tmp2, Register tmp3,
MacroAssembler::PreservationLevel preservation_level);
virtual void load_at(MacroAssembler* masm, DecoratorSet decorators, BasicType type,
Register base, RegisterOrConstant ind_or_offs, Register dst,
Register tmp1, Register tmp2,
MacroAssembler::PreservationLevel preservation_level, Label* L_handle_null = NULL);
virtual void try_resolve_jobject_in_native(MacroAssembler* masm, Register dst, Register jni_env,
Register obj, Register tmp, Label& slowpath);
};
#endif // CPU_PPC_GC_SHENANDOAH_SHENANDOAHBARRIERSETASSEMBLER_PPC_HPP

View File

@ -0,0 +1,217 @@
//
// Copyright (c) 2018, 2021, Red Hat, Inc. 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
// 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.
//
//
source_hpp %{
#include "gc/shenandoah/shenandoahBarrierSet.hpp"
#include "gc/shenandoah/shenandoahBarrierSetAssembler.hpp"
%}
// Weak compareAndSwap operations are treated as strong compareAndSwap operations.
// This is motivated by the retry logic of ShenandoahBarrierSetAssembler::cmpxchg_oop which is hard to realise
// using weak CAS operations.
instruct compareAndSwapP_shenandoah(iRegIdst res, indirect mem, iRegPsrc oldval, iRegPsrc newval,
iRegPdst tmp1, iRegPdst tmp2, flagsRegCR0 cr) %{
match(Set res (ShenandoahCompareAndSwapP mem (Binary oldval newval)));
match(Set res (ShenandoahWeakCompareAndSwapP mem (Binary oldval newval)));
effect(TEMP_DEF res, TEMP tmp1, TEMP tmp2, KILL cr);
predicate(((CompareAndSwapNode*)n)->order() != MemNode::acquire
&& ((CompareAndSwapNode*)n)->order() != MemNode::seqcst);
format %{ "CMPXCHG $res, $mem, $oldval, $newval; as bool; ptr" %}
ins_encode %{
ShenandoahBarrierSet::assembler()->cmpxchg_oop(
&_masm,
$mem$$Register, $oldval$$Register, $newval$$Register,
$tmp1$$Register, $tmp2$$Register,
false, $res$$Register
);
%}
ins_pipe(pipe_class_default);
%}
instruct compareAndSwapN_shenandoah(iRegIdst res, indirect mem, iRegNsrc oldval, iRegNsrc newval,
iRegNdst tmp1, iRegNdst tmp2, flagsRegCR0 cr) %{
match(Set res (ShenandoahCompareAndSwapN mem (Binary oldval newval)));
match(Set res (ShenandoahWeakCompareAndSwapN mem (Binary oldval newval)));
effect(TEMP_DEF res, TEMP tmp1, TEMP tmp2, KILL cr);
predicate(((CompareAndSwapNode*)n)->order() != MemNode::acquire
&& ((CompareAndSwapNode*)n)->order() != MemNode::seqcst);
format %{ "CMPXCHG $res, $mem, $oldval, $newval; as bool; ptr" %}
ins_encode %{
ShenandoahBarrierSet::assembler()->cmpxchg_oop(
&_masm,
$mem$$Register, $oldval$$Register, $newval$$Register,
$tmp1$$Register, $tmp2$$Register,
false, $res$$Register
);
%}
ins_pipe(pipe_class_default);
%}
instruct compareAndSwapP_acq_shenandoah(iRegIdst res, indirect mem, iRegPsrc oldval, iRegPsrc newval,
iRegPdst tmp1, iRegPdst tmp2, flagsRegCR0 cr) %{
match(Set res (ShenandoahCompareAndSwapP mem (Binary oldval newval)));
match(Set res (ShenandoahWeakCompareAndSwapP mem (Binary oldval newval)));
effect(TEMP_DEF res, TEMP tmp1, TEMP tmp2, KILL cr);
predicate(((CompareAndSwapNode*)n)->order() == MemNode::acquire
|| ((CompareAndSwapNode*)n)->order() == MemNode::seqcst);
format %{ "CMPXCHGD acq $res, $mem, $oldval, $newval; as bool; ptr" %}
ins_encode %{
ShenandoahBarrierSet::assembler()->cmpxchg_oop(
&_masm,
$mem$$Register, $oldval$$Register, $newval$$Register,
$tmp1$$Register, $tmp2$$Register,
false, $res$$Register
);
if (support_IRIW_for_not_multiple_copy_atomic_cpu) {
__ isync();
} else {
__ sync();
}
%}
ins_pipe(pipe_class_default);
%}
instruct compareAndSwapN_acq_shenandoah(iRegIdst res, indirect mem, iRegNsrc oldval, iRegNsrc newval,
iRegNdst tmp1, iRegNdst tmp2, flagsRegCR0 cr) %{
match(Set res (ShenandoahCompareAndSwapN mem (Binary oldval newval)));
match(Set res (ShenandoahWeakCompareAndSwapN mem (Binary oldval newval)));
effect(TEMP_DEF res, TEMP tmp1, TEMP tmp2, KILL cr);
predicate(((CompareAndSwapNode*)n)->order() == MemNode::acquire
|| ((CompareAndSwapNode*)n)->order() == MemNode::seqcst);
format %{ "CMPXCHGD acq $res, $mem, $oldval, $newval; as bool; ptr" %}
ins_encode %{
ShenandoahBarrierSet::assembler()->cmpxchg_oop(
&_masm,
$mem$$Register, $oldval$$Register, $newval$$Register,
$tmp1$$Register, $tmp2$$Register,
false, $res$$Register
);
if (support_IRIW_for_not_multiple_copy_atomic_cpu) {
__ isync();
} else {
__ sync();
}
%}
ins_pipe(pipe_class_default);
%}
instruct compareAndExchangeP_shenandoah(iRegPdst res, indirect mem, iRegPsrc oldval, iRegPsrc newval,
iRegPdst tmp1, iRegPdst tmp2, flagsRegCR0 cr) %{
match(Set res (ShenandoahCompareAndExchangeP mem (Binary oldval newval)));
effect(TEMP_DEF res, TEMP tmp1, TEMP tmp2, KILL cr);
predicate(((CompareAndSwapNode*)n)->order() != MemNode::acquire
&& ((CompareAndSwapNode*)n)->order() != MemNode::seqcst);
format %{ "CMPXCHGD $res, $mem, $oldval, $newval; as ptr; ptr" %}
ins_encode %{
ShenandoahBarrierSet::assembler()->cmpxchg_oop(
&_masm,
$mem$$Register, $oldval$$Register, $newval$$Register,
$tmp1$$Register, $tmp2$$Register,
true, $res$$Register
);
%}
ins_pipe(pipe_class_default);
%}
instruct compareAndExchangeN_shenandoah(iRegNdst res, indirect mem, iRegNsrc oldval, iRegNsrc newval,
iRegNdst tmp1, iRegNdst tmp2, flagsRegCR0 cr) %{
match(Set res (ShenandoahCompareAndExchangeN mem (Binary oldval newval)));
effect(TEMP_DEF res, TEMP tmp1, TEMP tmp2, KILL cr);
predicate(((CompareAndSwapNode*)n)->order() != MemNode::acquire
&& ((CompareAndSwapNode*)n)->order() != MemNode::seqcst);
format %{ "CMPXCHGD $res, $mem, $oldval, $newval; as ptr; ptr" %}
ins_encode %{
ShenandoahBarrierSet::assembler()->cmpxchg_oop(
&_masm,
$mem$$Register, $oldval$$Register, $newval$$Register,
$tmp1$$Register, $tmp2$$Register,
true, $res$$Register
);
%}
ins_pipe(pipe_class_default);
%}
instruct compareAndExchangePAcq_shenandoah(iRegPdst res, indirect mem, iRegPsrc oldval, iRegPsrc newval,
iRegPdst tmp1, iRegPdst tmp2, flagsRegCR0 cr) %{
match(Set res (ShenandoahCompareAndExchangeP mem (Binary oldval newval)));
effect(TEMP_DEF res, TEMP tmp1, TEMP tmp2, KILL cr);
predicate(((CompareAndSwapNode*)n)->order() == MemNode::acquire
|| ((CompareAndSwapNode*)n)->order() == MemNode::seqcst);
format %{ "CMPXCHGD acq $res, $mem, $oldval, $newval; as ptr; ptr" %}
ins_encode %{
ShenandoahBarrierSet::assembler()->cmpxchg_oop(
&_masm,
$mem$$Register, $oldval$$Register, $newval$$Register,
$tmp1$$Register, $tmp2$$Register,
true, $res$$Register
);
if (support_IRIW_for_not_multiple_copy_atomic_cpu) {
__ isync();
} else {
__ sync();
}
%}
ins_pipe(pipe_class_default);
%}
instruct compareAndExchangeNAcq_shenandoah(iRegNdst res, indirect mem, iRegNsrc oldval, iRegNsrc newval,
iRegNdst tmp1, iRegNdst tmp2, flagsRegCR0 cr) %{
match(Set res (ShenandoahCompareAndExchangeN mem (Binary oldval newval)));
effect(TEMP_DEF res, TEMP tmp1, TEMP tmp2, KILL cr);
predicate(((CompareAndSwapNode*)n)->order() == MemNode::acquire
|| ((CompareAndSwapNode*)n)->order() == MemNode::seqcst);
format %{ "CMPXCHGD acq $res, $mem, $oldval, $newval; as ptr; ptr" %}
ins_encode %{
ShenandoahBarrierSet::assembler()->cmpxchg_oop(
&_masm,
$mem$$Register, $oldval$$Register, $newval$$Register,
$tmp1$$Register, $tmp2$$Register,
true, $res$$Register
);
if (support_IRIW_for_not_multiple_copy_atomic_cpu) {
__ isync();
} else {
__ sync();
}
%}
ins_pipe(pipe_class_default);
%}

View File

@ -35,7 +35,7 @@
#include "utilities/defaultStream.hpp"
void ShenandoahArguments::initialize() {
#if !(defined AARCH64 || defined AMD64 || defined IA32)
#if !(defined AARCH64 || defined AMD64 || defined IA32 || defined PPC64)
vm_exit_during_initialization("Shenandoah GC is not supported on this platform.");
#endif