src/hotspot/cpu/aarch64/gc/shenandoah/shenandoah_aarch64.ad
author rkennke
Wed, 18 Sep 2019 20:56:20 +0200
changeset 58219 bc0648405d67
parent 54423 6c0ab8bd8da5
permissions -rw-r--r--
8231087: Shenandoah: Self-fixing load reference barriers for C1/C2 Reviewed-by: shade

//
// Copyright (c) 2018, Red Hat, Inc. All rights reserved.
//
// 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/shenandoahBarrierSetAssembler.hpp"
%}

encode %{
  enc_class aarch64_enc_cmpxchg_oop_shenandoah(memory mem, iRegP oldval, iRegP newval, iRegPNoSp tmp, iRegINoSp res) %{
    MacroAssembler _masm(&cbuf);
    guarantee($mem$$index == -1 && $mem$$disp == 0, "impossible encoding");
    Register tmp = $tmp$$Register;
    __ mov(tmp, $oldval$$Register); // Must not clobber oldval.
    ShenandoahBarrierSet::assembler()->cmpxchg_oop(&_masm, $mem$$Register, tmp, $newval$$Register,
                                                   /*acquire*/ false, /*release*/ true, /*weak*/ false, /*is_cae*/ false, $res$$Register);
  %}

  enc_class aarch64_enc_cmpxchg_acq_oop_shenandoah(memory mem, iRegP oldval, iRegP newval, iRegPNoSp tmp, iRegINoSp res) %{
    MacroAssembler _masm(&cbuf);
    guarantee($mem$$index == -1 && $mem$$disp == 0, "impossible encoding");
    Register tmp = $tmp$$Register;
    __ mov(tmp, $oldval$$Register); // Must not clobber oldval.
    ShenandoahBarrierSet::assembler()->cmpxchg_oop(&_masm, $mem$$Register, tmp, $newval$$Register,
                                                   /*acquire*/ true, /*release*/ true, /*weak*/ false, /*is_cae*/ false, $res$$Register);
  %}
%}

instruct compareAndSwapP_shenandoah(iRegINoSp res, indirect mem, iRegP oldval, iRegP newval, iRegPNoSp tmp, rFlagsReg cr) %{

  match(Set res (ShenandoahCompareAndSwapP mem (Binary oldval newval)));
  ins_cost(2 * VOLATILE_REF_COST);

  effect(TEMP tmp, KILL cr);

  format %{
    "cmpxchg_shenandoah $mem, $oldval, $newval\t# (ptr) if $mem == $oldval then $mem <-- $newval with temp $tmp"
  %}

  ins_encode(aarch64_enc_cmpxchg_oop_shenandoah(mem, oldval, newval, tmp, res));

  ins_pipe(pipe_slow);
%}

instruct compareAndSwapN_shenandoah(iRegINoSp res, indirect mem, iRegN oldval, iRegN newval, iRegNNoSp tmp, rFlagsReg cr) %{

  match(Set res (ShenandoahCompareAndSwapN mem (Binary oldval newval)));
  ins_cost(2 * VOLATILE_REF_COST);

  effect(TEMP tmp, KILL cr);

  format %{
    "cmpxchgw_shenandoah $mem, $oldval, $newval\t# (ptr) if $mem == $oldval then $mem <-- $newval with temp $tmp"
  %}

  ins_encode %{
    Register tmp = $tmp$$Register;
    __ mov(tmp, $oldval$$Register); // Must not clobber oldval.
    ShenandoahBarrierSet::assembler()->cmpxchg_oop(&_masm, $mem$$Register, tmp, $newval$$Register, /*acquire*/ false, /*release*/ true, /*weak*/ false, /*is_cae*/ false, $res$$Register);
  %}

  ins_pipe(pipe_slow);
%}

instruct compareAndSwapPAcq_shenandoah(iRegINoSp res, indirect mem, iRegP oldval, iRegP newval, iRegPNoSp tmp, rFlagsReg cr) %{

  predicate(needs_acquiring_load_exclusive(n));
  match(Set res (ShenandoahCompareAndSwapP mem (Binary oldval newval)));
  ins_cost(VOLATILE_REF_COST);

  effect(TEMP tmp, KILL cr);

  format %{
    "cmpxchg_acq_shenandoah_oop $mem, $oldval, $newval\t# (ptr) if $mem == $oldval then $mem <-- $newval with temp $tmp"
  %}

  ins_encode(aarch64_enc_cmpxchg_acq_oop_shenandoah(mem, oldval, newval, tmp, res));

  ins_pipe(pipe_slow);
%}

instruct compareAndSwapNAcq_shenandoah(iRegINoSp res, indirect mem, iRegN oldval, iRegN newval, iRegNNoSp tmp, rFlagsReg cr) %{

  predicate(needs_acquiring_load_exclusive(n));
  match(Set res (ShenandoahCompareAndSwapN mem (Binary oldval newval)));
  ins_cost(VOLATILE_REF_COST);

  effect(TEMP tmp, KILL cr);

 format %{
    "cmpxchgw_acq_shenandoah_narrow_oop $mem, $oldval, $newval\t# (ptr) if $mem == $oldval then $mem <-- $newval with temp $tmp"
 %}

  ins_encode %{
    Register tmp = $tmp$$Register;
    __ mov(tmp, $oldval$$Register); // Must not clobber oldval.
    ShenandoahBarrierSet::assembler()->cmpxchg_oop(&_masm, $mem$$Register, tmp, $newval$$Register, /*acquire*/ true, /*release*/ true, /*weak*/ false, /*is_cae*/ false, $res$$Register);
  %}

  ins_pipe(pipe_slow);
%}

instruct compareAndExchangeN_shenandoah(iRegNNoSp res, indirect mem, iRegN oldval, iRegN newval, iRegNNoSp tmp, rFlagsReg cr) %{
  match(Set res (ShenandoahCompareAndExchangeN mem (Binary oldval newval)));
  ins_cost(2 * VOLATILE_REF_COST);
  effect(TEMP_DEF res, TEMP tmp, KILL cr);
  format %{
    "cmpxchgw_shenandoah $res = $mem, $oldval, $newval\t# (narrow oop, weak) if $mem == $oldval then $mem <-- $newval"
  %}
  ins_encode %{
    Register tmp = $tmp$$Register;
    __ mov(tmp, $oldval$$Register); // Must not clobber oldval.
    ShenandoahBarrierSet::assembler()->cmpxchg_oop(&_masm, $mem$$Register, tmp, $newval$$Register,
                                                   /*acquire*/ false, /*release*/ true, /*weak*/ false, /*is_cae*/ true, $res$$Register);
  %}
  ins_pipe(pipe_slow);
%}

instruct compareAndExchangeP_shenandoah(iRegPNoSp res, indirect mem, iRegP oldval, iRegP newval, iRegPNoSp tmp, rFlagsReg cr) %{
  match(Set res (ShenandoahCompareAndExchangeP mem (Binary oldval newval)));
  ins_cost(2 * VOLATILE_REF_COST);
  effect(TEMP_DEF res, TEMP tmp, KILL cr);
  format %{
    "cmpxchg_shenandoah $mem, $oldval, $newval\t# (ptr) if $mem == $oldval then $mem <-- $newval with temp $tmp"
  %}
  ins_encode %{
    Register tmp = $tmp$$Register;
    __ mov(tmp, $oldval$$Register); // Must not clobber oldval.
    ShenandoahBarrierSet::assembler()->cmpxchg_oop(&_masm, $mem$$Register, tmp, $newval$$Register,
                                                   /*acquire*/ false, /*release*/ true, /*weak*/ false, /*is_cae*/ true, $res$$Register);
  %}
  ins_pipe(pipe_slow);
%}

instruct compareAndExchangeNAcq_shenandoah(iRegNNoSp res, indirect mem, iRegN oldval, iRegN newval, iRegNNoSp tmp, rFlagsReg cr) %{
  predicate(needs_acquiring_load_exclusive(n));
  match(Set res (ShenandoahCompareAndExchangeN mem (Binary oldval newval)));
  ins_cost(VOLATILE_REF_COST);
  effect(TEMP_DEF res, TEMP tmp, KILL cr);
  format %{
    "cmpxchgw_acq_shenandoah $res = $mem, $oldval, $newval\t# (narrow oop, weak) if $mem == $oldval then $mem <-- $newval"
  %}
  ins_encode %{
    Register tmp = $tmp$$Register;
    __ mov(tmp, $oldval$$Register); // Must not clobber oldval.
    ShenandoahBarrierSet::assembler()->cmpxchg_oop(&_masm, $mem$$Register, tmp, $newval$$Register,
                                                   /*acquire*/ true, /*release*/ true, /*weak*/ false, /*is_cae*/ true, $res$$Register);
  %}
  ins_pipe(pipe_slow);
%}

instruct compareAndExchangePAcq_shenandoah(iRegPNoSp res, indirect mem, iRegP oldval, iRegP newval, iRegPNoSp tmp, rFlagsReg cr) %{
  predicate(needs_acquiring_load_exclusive(n));
  match(Set res (ShenandoahCompareAndExchangeP mem (Binary oldval newval)));
  ins_cost(VOLATILE_REF_COST);
  effect(TEMP_DEF res, TEMP tmp, KILL cr);
  format %{
    "cmpxchg_acq_shenandoah $mem, $oldval, $newval\t# (ptr) if $mem == $oldval then $mem <-- $newval with temp $tmp"
  %}
  ins_encode %{
    Register tmp = $tmp$$Register;
    __ mov(tmp, $oldval$$Register); // Must not clobber oldval.
    ShenandoahBarrierSet::assembler()->cmpxchg_oop(&_masm, $mem$$Register, tmp, $newval$$Register,
                                                   /*acquire*/ true, /*release*/ true, /*weak*/ false, /*is_cae*/ true, $res$$Register);
  %}
  ins_pipe(pipe_slow);
%}

instruct weakCompareAndSwapN_shenandoah(iRegINoSp res, indirect mem, iRegN oldval, iRegN newval, iRegNNoSp tmp, rFlagsReg cr) %{
  match(Set res (ShenandoahWeakCompareAndSwapN mem (Binary oldval newval)));
  ins_cost(2 * VOLATILE_REF_COST);
  effect(TEMP tmp, KILL cr);
  format %{
    "cmpxchgw_shenandoah $res = $mem, $oldval, $newval\t# (narrow oop, weak) if $mem == $oldval then $mem <-- $newval"
    "csetw $res, EQ\t# $res <-- (EQ ? 1 : 0)"
  %}
  ins_encode %{
    Register tmp = $tmp$$Register;
    __ mov(tmp, $oldval$$Register); // Must not clobber oldval.
    ShenandoahBarrierSet::assembler()->cmpxchg_oop(&_masm, $mem$$Register, tmp, $newval$$Register,
                                                   /*acquire*/ false, /*release*/ true, /*weak*/ true, /*is_cae*/ false, $res$$Register);
  %}
  ins_pipe(pipe_slow);
%}

instruct weakCompareAndSwapP_shenandoah(iRegINoSp res, indirect mem, iRegP oldval, iRegP newval, iRegPNoSp tmp, rFlagsReg cr) %{
  match(Set res (ShenandoahWeakCompareAndSwapP mem (Binary oldval newval)));
  ins_cost(2 * VOLATILE_REF_COST);
  effect(TEMP tmp, KILL cr);
  format %{
    "cmpxchg_shenandoah $res = $mem, $oldval, $newval\t# (ptr, weak) if $mem == $oldval then $mem <-- $newval"
  %}
  ins_encode %{
    Register tmp = $tmp$$Register;
    __ mov(tmp, $oldval$$Register); // Must not clobber oldval.
    ShenandoahBarrierSet::assembler()->cmpxchg_oop(&_masm, $mem$$Register, tmp, $newval$$Register,
                                                   /*acquire*/ false, /*release*/ true, /*weak*/ true, /*is_cae*/ false, $res$$Register);
  %}
  ins_pipe(pipe_slow);
%}

instruct weakCompareAndSwapNAcq_shenandoah(iRegINoSp res, indirect mem, iRegN oldval, iRegN newval, iRegNNoSp tmp, rFlagsReg cr) %{
  predicate(needs_acquiring_load_exclusive(n));
  match(Set res (ShenandoahWeakCompareAndSwapN mem (Binary oldval newval)));
  ins_cost(VOLATILE_REF_COST);
  effect(TEMP tmp, KILL cr);
  format %{
    "cmpxchgw_acq_shenandoah $res = $mem, $oldval, $newval\t# (narrow oop, weak) if $mem == $oldval then $mem <-- $newval"
    "csetw $res, EQ\t# $res <-- (EQ ? 1 : 0)"
  %}
  ins_encode %{
    Register tmp = $tmp$$Register;
    __ mov(tmp, $oldval$$Register); // Must not clobber oldval.
    ShenandoahBarrierSet::assembler()->cmpxchg_oop(&_masm, $mem$$Register, tmp, $newval$$Register,
                                                   /*acquire*/ true, /*release*/ true, /*weak*/ true, /*is_cae*/ false, $res$$Register);
  %}
  ins_pipe(pipe_slow);
%}

instruct weakCompareAndSwapPAcq_shenandoah(iRegINoSp res, indirect mem, iRegP oldval, iRegP newval, iRegPNoSp tmp, rFlagsReg cr) %{
  predicate(needs_acquiring_load_exclusive(n));
  match(Set res (ShenandoahWeakCompareAndSwapP mem (Binary oldval newval)));
  ins_cost(VOLATILE_REF_COST);
  effect(TEMP tmp, KILL cr);
  format %{
    "cmpxchg_acq_shenandoah $res = $mem, $oldval, $newval\t# (ptr, weak) if $mem == $oldval then $mem <-- $newval"
    "csetw $res, EQ\t# $res <-- (EQ ? 1 : 0)"
  %}
  ins_encode %{
    Register tmp = $tmp$$Register;
    __ mov(tmp, $oldval$$Register); // Must not clobber oldval.
    ShenandoahBarrierSet::assembler()->cmpxchg_oop(&_masm, $mem$$Register, tmp, $newval$$Register,
                                                   /*acquire*/ true, /*release*/ true, /*weak*/ true, /*is_cae*/ false, $res$$Register);
  %}
  ins_pipe(pipe_slow);
%}