8209835: Aarch64: elide barriers on all volatile operations

Reviewed-by: aph, adinn
This commit is contained in:
Roland Westrelin 2018-11-05 12:53:55 +01:00
parent 03ef2b0df5
commit b5d2e875f6
12 changed files with 1541 additions and 143 deletions

View File

@ -1036,7 +1036,7 @@ class HandlerImpl {
}
};
bool is_CAS(int opcode);
bool is_CAS(int opcode, bool maybe_volatile);
// predicates controlling emit of ldr<x>/ldar<x> and associated dmb
@ -1259,12 +1259,12 @@ source %{
// relevant dmb instructions.
//
// is_CAS(int opcode)
// is_CAS(int opcode, bool maybe_volatile)
//
// return true if opcode is one of the possible CompareAndSwapX
// values otherwise false.
bool is_CAS(int opcode)
bool is_CAS(int opcode, bool maybe_volatile)
{
switch(opcode) {
// We handle these
@ -1272,23 +1272,28 @@ source %{
case Op_CompareAndSwapL:
case Op_CompareAndSwapP:
case Op_CompareAndSwapN:
// case Op_CompareAndSwapB:
// case Op_CompareAndSwapS:
case Op_CompareAndSwapB:
case Op_CompareAndSwapS:
case Op_GetAndSetI:
case Op_GetAndSetL:
case Op_GetAndSetP:
case Op_GetAndSetN:
case Op_GetAndAddI:
case Op_GetAndAddL:
return true;
// These are TBD
case Op_CompareAndExchangeI:
case Op_CompareAndExchangeN:
case Op_CompareAndExchangeB:
case Op_CompareAndExchangeS:
case Op_CompareAndExchangeL:
case Op_CompareAndExchangeP:
case Op_WeakCompareAndSwapB:
case Op_WeakCompareAndSwapS:
case Op_WeakCompareAndSwapI:
case Op_WeakCompareAndSwapL:
case Op_WeakCompareAndSwapP:
case Op_WeakCompareAndSwapN:
case Op_CompareAndExchangeB:
case Op_CompareAndExchangeS:
case Op_CompareAndExchangeI:
case Op_CompareAndExchangeL:
case Op_CompareAndExchangeP:
case Op_CompareAndExchangeN:
return false;
return maybe_volatile;
default:
return false;
}
@ -1318,7 +1323,7 @@ bool unnecessary_acquire(const Node *barrier)
if (mb->trailing_load_store()) {
Node* load_store = mb->in(MemBarNode::Precedent);
assert(load_store->is_LoadStore(), "unexpected graph shape");
return is_CAS(load_store->Opcode());
return is_CAS(load_store->Opcode(), true);
}
return false;
@ -1365,7 +1370,7 @@ bool unnecessary_release(const Node *n)
} else {
assert(mem->is_LoadStore(), "");
assert(trailing_mb->Opcode() == Op_MemBarAcquire, "");
return is_CAS(mem->Opcode());
return is_CAS(mem->Opcode(), true);
}
}
return false;
@ -1416,13 +1421,17 @@ bool needs_releasing_store(const Node *n)
bool needs_acquiring_load_exclusive(const Node *n)
{
assert(is_CAS(n->Opcode()), "expecting a compare and swap");
assert(is_CAS(n->Opcode(), true), "expecting a compare and swap");
if (UseBarriersForVolatile) {
return false;
}
LoadStoreNode* ldst = n->as_LoadStore();
assert(ldst->trailing_membar() != NULL, "expected trailing membar");
if (is_CAS(n->Opcode(), false)) {
assert(ldst->trailing_membar() != NULL, "expected trailing membar");
} else {
return ldst->trailing_membar() != NULL;
}
// so we can just return true here
return true;
@ -2943,6 +2952,21 @@ encode %{
/*weak*/ false, noreg);
%}
enc_class aarch64_enc_cmpxchgs_acq(memory mem, iRegINoSp oldval, iRegINoSp newval) %{
MacroAssembler _masm(&cbuf);
guarantee($mem$$index == -1 && $mem$$disp == 0, "impossible encoding");
__ cmpxchg($mem$$base$$Register, $oldval$$Register, $newval$$Register,
Assembler::halfword, /*acquire*/ true, /*release*/ true,
/*weak*/ false, noreg);
%}
enc_class aarch64_enc_cmpxchgb_acq(memory mem, iRegINoSp oldval, iRegINoSp newval) %{
MacroAssembler _masm(&cbuf);
guarantee($mem$$index == -1 && $mem$$disp == 0, "impossible encoding");
__ cmpxchg($mem$$base$$Register, $oldval$$Register, $newval$$Register,
Assembler::byte, /*acquire*/ true, /*release*/ true,
/*weak*/ false, noreg);
%}
// auxiliary used for CompareAndSwapX to set result register
enc_class aarch64_enc_cset_eq(iRegINoSp res) %{
@ -8240,6 +8264,44 @@ instruct compareAndSwapN(iRegINoSp res, indirect mem, iRegNNoSp oldval, iRegNNoS
// alternative CompareAndSwapX when we are eliding barriers
instruct compareAndSwapBAcq(iRegINoSp res, indirect mem, iRegINoSp oldval, iRegINoSp newval, rFlagsReg cr) %{
predicate(needs_acquiring_load_exclusive(n));
match(Set res (CompareAndSwapB mem (Binary oldval newval)));
ins_cost(VOLATILE_REF_COST);
effect(KILL cr);
format %{
"cmpxchgb_acq $mem, $oldval, $newval\t# (int) if $mem == $oldval then $mem <-- $newval"
"cset $res, EQ\t# $res <-- (EQ ? 1 : 0)"
%}
ins_encode(aarch64_enc_cmpxchgb_acq(mem, oldval, newval),
aarch64_enc_cset_eq(res));
ins_pipe(pipe_slow);
%}
instruct compareAndSwapSAcq(iRegINoSp res, indirect mem, iRegINoSp oldval, iRegINoSp newval, rFlagsReg cr) %{
predicate(needs_acquiring_load_exclusive(n));
match(Set res (CompareAndSwapS mem (Binary oldval newval)));
ins_cost(VOLATILE_REF_COST);
effect(KILL cr);
format %{
"cmpxchgs_acq $mem, $oldval, $newval\t# (int) if $mem == $oldval then $mem <-- $newval"
"cset $res, EQ\t# $res <-- (EQ ? 1 : 0)"
%}
ins_encode(aarch64_enc_cmpxchgs_acq(mem, oldval, newval),
aarch64_enc_cset_eq(res));
ins_pipe(pipe_slow);
%}
instruct compareAndSwapIAcq(iRegINoSp res, indirect mem, iRegINoSp oldval, iRegINoSp newval, rFlagsReg cr) %{
predicate(needs_acquiring_load_exclusive(n));
@ -8338,7 +8400,7 @@ instruct compareAndExchangeB(iRegINoSp res, indirect mem, iRegI oldval, iRegI ne
ins_cost(2 * VOLATILE_REF_COST);
effect(TEMP_DEF res, KILL cr);
format %{
"cmpxchg $res = $mem, $oldval, $newval\t# (byte, weak) if $mem == $oldval then $mem <-- $newval"
"cmpxchgb $res = $mem, $oldval, $newval\t# (byte, weak) if $mem == $oldval then $mem <-- $newval"
%}
ins_encode %{
__ cmpxchg($mem$$Register, $oldval$$Register, $newval$$Register,
@ -8354,7 +8416,7 @@ instruct compareAndExchangeS(iRegINoSp res, indirect mem, iRegI oldval, iRegI ne
ins_cost(2 * VOLATILE_REF_COST);
effect(TEMP_DEF res, KILL cr);
format %{
"cmpxchg $res = $mem, $oldval, $newval\t# (short, weak) if $mem == $oldval then $mem <-- $newval"
"cmpxchgs $res = $mem, $oldval, $newval\t# (short, weak) if $mem == $oldval then $mem <-- $newval"
%}
ins_encode %{
__ cmpxchg($mem$$Register, $oldval$$Register, $newval$$Register,
@ -8370,7 +8432,7 @@ instruct compareAndExchangeI(iRegINoSp res, indirect mem, iRegI oldval, iRegI ne
ins_cost(2 * VOLATILE_REF_COST);
effect(TEMP_DEF res, KILL cr);
format %{
"cmpxchg $res = $mem, $oldval, $newval\t# (int, weak) if $mem == $oldval then $mem <-- $newval"
"cmpxchgw $res = $mem, $oldval, $newval\t# (int, weak) if $mem == $oldval then $mem <-- $newval"
%}
ins_encode %{
__ cmpxchg($mem$$Register, $oldval$$Register, $newval$$Register,
@ -8400,7 +8462,7 @@ instruct compareAndExchangeN(iRegNNoSp res, indirect mem, iRegN oldval, iRegN ne
ins_cost(2 * VOLATILE_REF_COST);
effect(TEMP_DEF res, KILL cr);
format %{
"cmpxchg $res = $mem, $oldval, $newval\t# (narrow oop, weak) if $mem == $oldval then $mem <-- $newval"
"cmpxchgw $res = $mem, $oldval, $newval\t# (narrow oop, weak) if $mem == $oldval then $mem <-- $newval"
%}
ins_encode %{
__ cmpxchg($mem$$Register, $oldval$$Register, $newval$$Register,
@ -8425,12 +8487,112 @@ instruct compareAndExchangeP(iRegPNoSp res, indirect mem, iRegP oldval, iRegP ne
ins_pipe(pipe_slow);
%}
instruct compareAndExchangeBAcq(iRegINoSp res, indirect mem, iRegI oldval, iRegI newval, rFlagsReg cr) %{
predicate(needs_acquiring_load_exclusive(n));
match(Set res (CompareAndExchangeB mem (Binary oldval newval)));
ins_cost(VOLATILE_REF_COST);
effect(TEMP_DEF res, KILL cr);
format %{
"cmpxchgb_acq $res = $mem, $oldval, $newval\t# (byte, weak) if $mem == $oldval then $mem <-- $newval"
%}
ins_encode %{
__ cmpxchg($mem$$Register, $oldval$$Register, $newval$$Register,
Assembler::byte, /*acquire*/ true, /*release*/ true,
/*weak*/ false, $res$$Register);
__ sxtbw($res$$Register, $res$$Register);
%}
ins_pipe(pipe_slow);
%}
instruct compareAndExchangeSAcq(iRegINoSp res, indirect mem, iRegI oldval, iRegI newval, rFlagsReg cr) %{
predicate(needs_acquiring_load_exclusive(n));
match(Set res (CompareAndExchangeS mem (Binary oldval newval)));
ins_cost(VOLATILE_REF_COST);
effect(TEMP_DEF res, KILL cr);
format %{
"cmpxchgs_acq $res = $mem, $oldval, $newval\t# (short, weak) if $mem == $oldval then $mem <-- $newval"
%}
ins_encode %{
__ cmpxchg($mem$$Register, $oldval$$Register, $newval$$Register,
Assembler::halfword, /*acquire*/ true, /*release*/ true,
/*weak*/ false, $res$$Register);
__ sxthw($res$$Register, $res$$Register);
%}
ins_pipe(pipe_slow);
%}
instruct compareAndExchangeIAcq(iRegINoSp res, indirect mem, iRegI oldval, iRegI newval, rFlagsReg cr) %{
predicate(needs_acquiring_load_exclusive(n));
match(Set res (CompareAndExchangeI mem (Binary oldval newval)));
ins_cost(VOLATILE_REF_COST);
effect(TEMP_DEF res, KILL cr);
format %{
"cmpxchgw_acq $res = $mem, $oldval, $newval\t# (int, weak) if $mem == $oldval then $mem <-- $newval"
%}
ins_encode %{
__ cmpxchg($mem$$Register, $oldval$$Register, $newval$$Register,
Assembler::word, /*acquire*/ true, /*release*/ true,
/*weak*/ false, $res$$Register);
%}
ins_pipe(pipe_slow);
%}
instruct compareAndExchangeLAcq(iRegLNoSp res, indirect mem, iRegL oldval, iRegL newval, rFlagsReg cr) %{
predicate(needs_acquiring_load_exclusive(n));
match(Set res (CompareAndExchangeL mem (Binary oldval newval)));
ins_cost(VOLATILE_REF_COST);
effect(TEMP_DEF res, KILL cr);
format %{
"cmpxchg_acq $res = $mem, $oldval, $newval\t# (long, weak) if $mem == $oldval then $mem <-- $newval"
%}
ins_encode %{
__ cmpxchg($mem$$Register, $oldval$$Register, $newval$$Register,
Assembler::xword, /*acquire*/ true, /*release*/ true,
/*weak*/ false, $res$$Register);
%}
ins_pipe(pipe_slow);
%}
instruct compareAndExchangeNAcq(iRegNNoSp res, indirect mem, iRegN oldval, iRegN newval, rFlagsReg cr) %{
predicate(needs_acquiring_load_exclusive(n));
match(Set res (CompareAndExchangeN mem (Binary oldval newval)));
ins_cost(VOLATILE_REF_COST);
effect(TEMP_DEF res, KILL cr);
format %{
"cmpxchgw_acq $res = $mem, $oldval, $newval\t# (narrow oop, weak) if $mem == $oldval then $mem <-- $newval"
%}
ins_encode %{
__ cmpxchg($mem$$Register, $oldval$$Register, $newval$$Register,
Assembler::word, /*acquire*/ true, /*release*/ true,
/*weak*/ false, $res$$Register);
%}
ins_pipe(pipe_slow);
%}
instruct compareAndExchangePAcq(iRegPNoSp res, indirect mem, iRegP oldval, iRegP newval, rFlagsReg cr) %{
predicate(needs_acquiring_load_exclusive(n));
match(Set res (CompareAndExchangeP mem (Binary oldval newval)));
ins_cost(VOLATILE_REF_COST);
effect(TEMP_DEF res, KILL cr);
format %{
"cmpxchg_acq $res = $mem, $oldval, $newval\t# (ptr, weak) if $mem == $oldval then $mem <-- $newval"
%}
ins_encode %{
__ cmpxchg($mem$$Register, $oldval$$Register, $newval$$Register,
Assembler::xword, /*acquire*/ true, /*release*/ true,
/*weak*/ false, $res$$Register);
%}
ins_pipe(pipe_slow);
%}
instruct weakCompareAndSwapB(iRegINoSp res, indirect mem, iRegI oldval, iRegI newval, rFlagsReg cr) %{
match(Set res (WeakCompareAndSwapB mem (Binary oldval newval)));
ins_cost(2 * VOLATILE_REF_COST);
effect(KILL cr);
format %{
"cmpxchg $res = $mem, $oldval, $newval\t# (byte, weak) if $mem == $oldval then $mem <-- $newval"
"cmpxchgb $res = $mem, $oldval, $newval\t# (byte, weak) if $mem == $oldval then $mem <-- $newval"
"csetw $res, EQ\t# $res <-- (EQ ? 1 : 0)"
%}
ins_encode %{
@ -8447,7 +8609,7 @@ instruct weakCompareAndSwapS(iRegINoSp res, indirect mem, iRegI oldval, iRegI ne
ins_cost(2 * VOLATILE_REF_COST);
effect(KILL cr);
format %{
"cmpxchg $res = $mem, $oldval, $newval\t# (short, weak) if $mem == $oldval then $mem <-- $newval"
"cmpxchgs $res = $mem, $oldval, $newval\t# (short, weak) if $mem == $oldval then $mem <-- $newval"
"csetw $res, EQ\t# $res <-- (EQ ? 1 : 0)"
%}
ins_encode %{
@ -8464,7 +8626,7 @@ instruct weakCompareAndSwapI(iRegINoSp res, indirect mem, iRegI oldval, iRegI ne
ins_cost(2 * VOLATILE_REF_COST);
effect(KILL cr);
format %{
"cmpxchg $res = $mem, $oldval, $newval\t# (int, weak) if $mem == $oldval then $mem <-- $newval"
"cmpxchgw $res = $mem, $oldval, $newval\t# (int, weak) if $mem == $oldval then $mem <-- $newval"
"csetw $res, EQ\t# $res <-- (EQ ? 1 : 0)"
%}
ins_encode %{
@ -8498,7 +8660,7 @@ instruct weakCompareAndSwapN(iRegINoSp res, indirect mem, iRegN oldval, iRegN ne
ins_cost(2 * VOLATILE_REF_COST);
effect(KILL cr);
format %{
"cmpxchg $res = $mem, $oldval, $newval\t# (narrow oop, weak) if $mem == $oldval then $mem <-- $newval"
"cmpxchgw $res = $mem, $oldval, $newval\t# (narrow oop, weak) if $mem == $oldval then $mem <-- $newval"
"csetw $res, EQ\t# $res <-- (EQ ? 1 : 0)"
%}
ins_encode %{
@ -8527,11 +8689,120 @@ instruct weakCompareAndSwapP(iRegINoSp res, indirect mem, iRegP oldval, iRegP ne
ins_pipe(pipe_slow);
%}
instruct weakCompareAndSwapBAcq(iRegINoSp res, indirect mem, iRegI oldval, iRegI newval, rFlagsReg cr) %{
predicate(needs_acquiring_load_exclusive(n));
match(Set res (WeakCompareAndSwapB mem (Binary oldval newval)));
ins_cost(VOLATILE_REF_COST);
effect(KILL cr);
format %{
"cmpxchgb_acq $res = $mem, $oldval, $newval\t# (byte, weak) if $mem == $oldval then $mem <-- $newval"
"csetw $res, EQ\t# $res <-- (EQ ? 1 : 0)"
%}
ins_encode %{
__ cmpxchg($mem$$Register, $oldval$$Register, $newval$$Register,
Assembler::byte, /*acquire*/ true, /*release*/ true,
/*weak*/ true, noreg);
__ csetw($res$$Register, Assembler::EQ);
%}
ins_pipe(pipe_slow);
%}
instruct weakCompareAndSwapSAcq(iRegINoSp res, indirect mem, iRegI oldval, iRegI newval, rFlagsReg cr) %{
predicate(needs_acquiring_load_exclusive(n));
match(Set res (WeakCompareAndSwapS mem (Binary oldval newval)));
ins_cost(VOLATILE_REF_COST);
effect(KILL cr);
format %{
"cmpxchgs_acq $res = $mem, $oldval, $newval\t# (short, weak) if $mem == $oldval then $mem <-- $newval"
"csetw $res, EQ\t# $res <-- (EQ ? 1 : 0)"
%}
ins_encode %{
__ cmpxchg($mem$$Register, $oldval$$Register, $newval$$Register,
Assembler::halfword, /*acquire*/ true, /*release*/ true,
/*weak*/ true, noreg);
__ csetw($res$$Register, Assembler::EQ);
%}
ins_pipe(pipe_slow);
%}
instruct weakCompareAndSwapIAcq(iRegINoSp res, indirect mem, iRegI oldval, iRegI newval, rFlagsReg cr) %{
predicate(needs_acquiring_load_exclusive(n));
match(Set res (WeakCompareAndSwapI mem (Binary oldval newval)));
ins_cost(VOLATILE_REF_COST);
effect(KILL cr);
format %{
"cmpxchgw_acq $res = $mem, $oldval, $newval\t# (int, weak) if $mem == $oldval then $mem <-- $newval"
"csetw $res, EQ\t# $res <-- (EQ ? 1 : 0)"
%}
ins_encode %{
__ cmpxchg($mem$$Register, $oldval$$Register, $newval$$Register,
Assembler::word, /*acquire*/ true, /*release*/ true,
/*weak*/ true, noreg);
__ csetw($res$$Register, Assembler::EQ);
%}
ins_pipe(pipe_slow);
%}
instruct weakCompareAndSwapLAcq(iRegINoSp res, indirect mem, iRegL oldval, iRegL newval, rFlagsReg cr) %{
predicate(needs_acquiring_load_exclusive(n));
match(Set res (WeakCompareAndSwapL mem (Binary oldval newval)));
ins_cost(VOLATILE_REF_COST);
effect(KILL cr);
format %{
"cmpxchg_acq $res = $mem, $oldval, $newval\t# (long, weak) if $mem == $oldval then $mem <-- $newval"
"csetw $res, EQ\t# $res <-- (EQ ? 1 : 0)"
%}
ins_encode %{
__ cmpxchg($mem$$Register, $oldval$$Register, $newval$$Register,
Assembler::xword, /*acquire*/ true, /*release*/ true,
/*weak*/ true, noreg);
__ csetw($res$$Register, Assembler::EQ);
%}
ins_pipe(pipe_slow);
%}
instruct weakCompareAndSwapNAcq(iRegINoSp res, indirect mem, iRegN oldval, iRegN newval, rFlagsReg cr) %{
predicate(needs_acquiring_load_exclusive(n));
match(Set res (WeakCompareAndSwapN mem (Binary oldval newval)));
ins_cost(VOLATILE_REF_COST);
effect(KILL cr);
format %{
"cmpxchgw_acq $res = $mem, $oldval, $newval\t# (narrow oop, weak) if $mem == $oldval then $mem <-- $newval"
"csetw $res, EQ\t# $res <-- (EQ ? 1 : 0)"
%}
ins_encode %{
__ cmpxchg($mem$$Register, $oldval$$Register, $newval$$Register,
Assembler::word, /*acquire*/ true, /*release*/ true,
/*weak*/ true, noreg);
__ csetw($res$$Register, Assembler::EQ);
%}
ins_pipe(pipe_slow);
%}
instruct weakCompareAndSwapPAcq(iRegINoSp res, indirect mem, iRegP oldval, iRegP newval, rFlagsReg cr) %{
predicate(needs_acquiring_load_exclusive(n));
match(Set res (WeakCompareAndSwapP mem (Binary oldval newval)));
ins_cost(VOLATILE_REF_COST);
effect(KILL cr);
format %{
"cmpxchg_acq $res = $mem, $oldval, $newval\t# (ptr, weak) if $mem == $oldval then $mem <-- $newval"
"csetw $res, EQ\t# $res <-- (EQ ? 1 : 0)"
%}
ins_encode %{
__ cmpxchg($mem$$Register, $oldval$$Register, $newval$$Register,
Assembler::xword, /*acquire*/ true, /*release*/ true,
/*weak*/ true, noreg);
__ csetw($res$$Register, Assembler::EQ);
%}
ins_pipe(pipe_slow);
%}
// END This section of the file is automatically generated. Do not edit --------------
// ---------------------------------------------------------------------
instruct get_and_setI(indirect mem, iRegI newv, iRegINoSp prev) %{
match(Set prev (GetAndSetI mem newv));
ins_cost(2 * VOLATILE_REF_COST);
format %{ "atomic_xchgw $prev, $newv, [$mem]" %}
ins_encode %{
__ atomic_xchgw($prev$$Register, $newv$$Register, as_Register($mem$$base));
@ -8541,6 +8812,7 @@ instruct get_and_setI(indirect mem, iRegI newv, iRegINoSp prev) %{
instruct get_and_setL(indirect mem, iRegL newv, iRegLNoSp prev) %{
match(Set prev (GetAndSetL mem newv));
ins_cost(2 * VOLATILE_REF_COST);
format %{ "atomic_xchg $prev, $newv, [$mem]" %}
ins_encode %{
__ atomic_xchg($prev$$Register, $newv$$Register, as_Register($mem$$base));
@ -8550,6 +8822,7 @@ instruct get_and_setL(indirect mem, iRegL newv, iRegLNoSp prev) %{
instruct get_and_setN(indirect mem, iRegN newv, iRegINoSp prev) %{
match(Set prev (GetAndSetN mem newv));
ins_cost(2 * VOLATILE_REF_COST);
format %{ "atomic_xchgw $prev, $newv, [$mem]" %}
ins_encode %{
__ atomic_xchgw($prev$$Register, $newv$$Register, as_Register($mem$$base));
@ -8559,6 +8832,7 @@ instruct get_and_setN(indirect mem, iRegN newv, iRegINoSp prev) %{
instruct get_and_setP(indirect mem, iRegP newv, iRegPNoSp prev) %{
match(Set prev (GetAndSetP mem newv));
ins_cost(2 * VOLATILE_REF_COST);
format %{ "atomic_xchg $prev, $newv, [$mem]" %}
ins_encode %{
__ atomic_xchg($prev$$Register, $newv$$Register, as_Register($mem$$base));
@ -8566,10 +8840,54 @@ instruct get_and_setP(indirect mem, iRegP newv, iRegPNoSp prev) %{
ins_pipe(pipe_serial);
%}
instruct get_and_setIAcq(indirect mem, iRegI newv, iRegINoSp prev) %{
predicate(needs_acquiring_load_exclusive(n));
match(Set prev (GetAndSetI mem newv));
ins_cost(VOLATILE_REF_COST);
format %{ "atomic_xchgw_acq $prev, $newv, [$mem]" %}
ins_encode %{
__ atomic_xchgalw($prev$$Register, $newv$$Register, as_Register($mem$$base));
%}
ins_pipe(pipe_serial);
%}
instruct get_and_setLAcq(indirect mem, iRegL newv, iRegLNoSp prev) %{
predicate(needs_acquiring_load_exclusive(n));
match(Set prev (GetAndSetL mem newv));
ins_cost(VOLATILE_REF_COST);
format %{ "atomic_xchg_acq $prev, $newv, [$mem]" %}
ins_encode %{
__ atomic_xchgal($prev$$Register, $newv$$Register, as_Register($mem$$base));
%}
ins_pipe(pipe_serial);
%}
instruct get_and_setNAcq(indirect mem, iRegN newv, iRegINoSp prev) %{
predicate(needs_acquiring_load_exclusive(n));
match(Set prev (GetAndSetN mem newv));
ins_cost(VOLATILE_REF_COST);
format %{ "atomic_xchgw_acq $prev, $newv, [$mem]" %}
ins_encode %{
__ atomic_xchgalw($prev$$Register, $newv$$Register, as_Register($mem$$base));
%}
ins_pipe(pipe_serial);
%}
instruct get_and_setPAcq(indirect mem, iRegP newv, iRegPNoSp prev) %{
predicate(needs_acquiring_load_exclusive(n));
match(Set prev (GetAndSetP mem newv));
ins_cost(VOLATILE_REF_COST);
format %{ "atomic_xchg_acq $prev, $newv, [$mem]" %}
ins_encode %{
__ atomic_xchgal($prev$$Register, $newv$$Register, as_Register($mem$$base));
%}
ins_pipe(pipe_serial);
%}
instruct get_and_addL(indirect mem, iRegLNoSp newval, iRegL incr) %{
match(Set newval (GetAndAddL mem incr));
ins_cost(INSN_COST * 10);
ins_cost(2 * VOLATILE_REF_COST + 1);
format %{ "get_and_addL $newval, [$mem], $incr" %}
ins_encode %{
__ atomic_add($newval$$Register, $incr$$Register, as_Register($mem$$base));
@ -8580,7 +8898,7 @@ instruct get_and_addL(indirect mem, iRegLNoSp newval, iRegL incr) %{
instruct get_and_addL_no_res(indirect mem, Universe dummy, iRegL incr) %{
predicate(n->as_LoadStore()->result_not_used());
match(Set dummy (GetAndAddL mem incr));
ins_cost(INSN_COST * 9);
ins_cost(2 * VOLATILE_REF_COST);
format %{ "get_and_addL [$mem], $incr" %}
ins_encode %{
__ atomic_add(noreg, $incr$$Register, as_Register($mem$$base));
@ -8590,7 +8908,7 @@ instruct get_and_addL_no_res(indirect mem, Universe dummy, iRegL incr) %{
instruct get_and_addLi(indirect mem, iRegLNoSp newval, immLAddSub incr) %{
match(Set newval (GetAndAddL mem incr));
ins_cost(INSN_COST * 10);
ins_cost(2 * VOLATILE_REF_COST + 1);
format %{ "get_and_addL $newval, [$mem], $incr" %}
ins_encode %{
__ atomic_add($newval$$Register, $incr$$constant, as_Register($mem$$base));
@ -8601,7 +8919,7 @@ instruct get_and_addLi(indirect mem, iRegLNoSp newval, immLAddSub incr) %{
instruct get_and_addLi_no_res(indirect mem, Universe dummy, immLAddSub incr) %{
predicate(n->as_LoadStore()->result_not_used());
match(Set dummy (GetAndAddL mem incr));
ins_cost(INSN_COST * 9);
ins_cost(2 * VOLATILE_REF_COST);
format %{ "get_and_addL [$mem], $incr" %}
ins_encode %{
__ atomic_add(noreg, $incr$$constant, as_Register($mem$$base));
@ -8611,7 +8929,7 @@ instruct get_and_addLi_no_res(indirect mem, Universe dummy, immLAddSub incr) %{
instruct get_and_addI(indirect mem, iRegINoSp newval, iRegIorL2I incr) %{
match(Set newval (GetAndAddI mem incr));
ins_cost(INSN_COST * 10);
ins_cost(2 * VOLATILE_REF_COST + 1);
format %{ "get_and_addI $newval, [$mem], $incr" %}
ins_encode %{
__ atomic_addw($newval$$Register, $incr$$Register, as_Register($mem$$base));
@ -8622,7 +8940,7 @@ instruct get_and_addI(indirect mem, iRegINoSp newval, iRegIorL2I incr) %{
instruct get_and_addI_no_res(indirect mem, Universe dummy, iRegIorL2I incr) %{
predicate(n->as_LoadStore()->result_not_used());
match(Set dummy (GetAndAddI mem incr));
ins_cost(INSN_COST * 9);
ins_cost(2 * VOLATILE_REF_COST);
format %{ "get_and_addI [$mem], $incr" %}
ins_encode %{
__ atomic_addw(noreg, $incr$$Register, as_Register($mem$$base));
@ -8632,7 +8950,7 @@ instruct get_and_addI_no_res(indirect mem, Universe dummy, iRegIorL2I incr) %{
instruct get_and_addIi(indirect mem, iRegINoSp newval, immIAddSub incr) %{
match(Set newval (GetAndAddI mem incr));
ins_cost(INSN_COST * 10);
ins_cost(2 * VOLATILE_REF_COST + 1);
format %{ "get_and_addI $newval, [$mem], $incr" %}
ins_encode %{
__ atomic_addw($newval$$Register, $incr$$constant, as_Register($mem$$base));
@ -8643,7 +8961,7 @@ instruct get_and_addIi(indirect mem, iRegINoSp newval, immIAddSub incr) %{
instruct get_and_addIi_no_res(indirect mem, Universe dummy, immIAddSub incr) %{
predicate(n->as_LoadStore()->result_not_used());
match(Set dummy (GetAndAddI mem incr));
ins_cost(INSN_COST * 9);
ins_cost(2 * VOLATILE_REF_COST);
format %{ "get_and_addI [$mem], $incr" %}
ins_encode %{
__ atomic_addw(noreg, $incr$$constant, as_Register($mem$$base));
@ -8651,6 +8969,94 @@ instruct get_and_addIi_no_res(indirect mem, Universe dummy, immIAddSub incr) %{
ins_pipe(pipe_serial);
%}
instruct get_and_addLAcq(indirect mem, iRegLNoSp newval, iRegL incr) %{
predicate(needs_acquiring_load_exclusive(n));
match(Set newval (GetAndAddL mem incr));
ins_cost(VOLATILE_REF_COST + 1);
format %{ "get_and_addL_acq $newval, [$mem], $incr" %}
ins_encode %{
__ atomic_addal($newval$$Register, $incr$$Register, as_Register($mem$$base));
%}
ins_pipe(pipe_serial);
%}
instruct get_and_addL_no_resAcq(indirect mem, Universe dummy, iRegL incr) %{
predicate(n->as_LoadStore()->result_not_used() && needs_acquiring_load_exclusive(n));
match(Set dummy (GetAndAddL mem incr));
ins_cost(VOLATILE_REF_COST);
format %{ "get_and_addL_acq [$mem], $incr" %}
ins_encode %{
__ atomic_addal(noreg, $incr$$Register, as_Register($mem$$base));
%}
ins_pipe(pipe_serial);
%}
instruct get_and_addLiAcq(indirect mem, iRegLNoSp newval, immLAddSub incr) %{
predicate(needs_acquiring_load_exclusive(n));
match(Set newval (GetAndAddL mem incr));
ins_cost(VOLATILE_REF_COST + 1);
format %{ "get_and_addL_acq $newval, [$mem], $incr" %}
ins_encode %{
__ atomic_addal($newval$$Register, $incr$$constant, as_Register($mem$$base));
%}
ins_pipe(pipe_serial);
%}
instruct get_and_addLi_no_resAcq(indirect mem, Universe dummy, immLAddSub incr) %{
predicate(n->as_LoadStore()->result_not_used() && needs_acquiring_load_exclusive(n));
match(Set dummy (GetAndAddL mem incr));
ins_cost(VOLATILE_REF_COST);
format %{ "get_and_addL_acq [$mem], $incr" %}
ins_encode %{
__ atomic_addal(noreg, $incr$$constant, as_Register($mem$$base));
%}
ins_pipe(pipe_serial);
%}
instruct get_and_addIAcq(indirect mem, iRegINoSp newval, iRegIorL2I incr) %{
predicate(needs_acquiring_load_exclusive(n));
match(Set newval (GetAndAddI mem incr));
ins_cost(VOLATILE_REF_COST + 1);
format %{ "get_and_addI_acq $newval, [$mem], $incr" %}
ins_encode %{
__ atomic_addalw($newval$$Register, $incr$$Register, as_Register($mem$$base));
%}
ins_pipe(pipe_serial);
%}
instruct get_and_addI_no_resAcq(indirect mem, Universe dummy, iRegIorL2I incr) %{
predicate(n->as_LoadStore()->result_not_used() && needs_acquiring_load_exclusive(n));
match(Set dummy (GetAndAddI mem incr));
ins_cost(VOLATILE_REF_COST);
format %{ "get_and_addI_acq [$mem], $incr" %}
ins_encode %{
__ atomic_addalw(noreg, $incr$$Register, as_Register($mem$$base));
%}
ins_pipe(pipe_serial);
%}
instruct get_and_addIiAcq(indirect mem, iRegINoSp newval, immIAddSub incr) %{
predicate(needs_acquiring_load_exclusive(n));
match(Set newval (GetAndAddI mem incr));
ins_cost(VOLATILE_REF_COST + 1);
format %{ "get_and_addI_acq $newval, [$mem], $incr" %}
ins_encode %{
__ atomic_addalw($newval$$Register, $incr$$constant, as_Register($mem$$base));
%}
ins_pipe(pipe_serial);
%}
instruct get_and_addIi_no_resAcq(indirect mem, Universe dummy, immIAddSub incr) %{
predicate(n->as_LoadStore()->result_not_used() && needs_acquiring_load_exclusive(n));
match(Set dummy (GetAndAddI mem incr));
ins_cost(VOLATILE_REF_COST);
format %{ "get_and_addI_acq [$mem], $incr" %}
ins_encode %{
__ atomic_addalw(noreg, $incr$$constant, as_Register($mem$$base));
%}
ins_pipe(pipe_serial);
%}
// Manifest a CmpL result in an integer register.
// (src1 < src2) ? -1 : ((src1 > src2) ? 1 : 0)
instruct cmpL3_reg_reg(iRegINoSp dst, iRegL src1, iRegL src2, rFlagsReg flags)

View File

@ -0,0 +1,133 @@
/*
* Copyright (c) 2018, Red Hat, Inc. 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.
*/
package compiler.c2.aarch64;
import java.lang.reflect.Field;
import jdk.internal.misc.Unsafe;
class TestUnsafeVolatileCAE
{
public volatile int f_int = 0;
public volatile Integer f_obj = Integer.valueOf(0);
public volatile long f_long = 0;
public volatile byte f_byte = 0;
public volatile short f_short = 0;
public static Unsafe unsafe = Unsafe.getUnsafe();
public static Field f_int_field;
public static Field f_obj_field;
public static Field f_long_field;
public static Field f_byte_field;
public static Field f_short_field;
public static long f_int_off;
public static long f_obj_off;
public static long f_long_off;
public static long f_byte_off;
public static long f_short_off;
static {
try {
f_int_field = TestUnsafeVolatileCAE.class.getField("f_int");
f_obj_field = TestUnsafeVolatileCAE.class.getField("f_obj");
f_long_field = TestUnsafeVolatileCAE.class.getField("f_long");
f_byte_field = TestUnsafeVolatileCAE.class.getField("f_byte");
f_short_field = TestUnsafeVolatileCAE.class.getField("f_short");
f_int_off = unsafe.objectFieldOffset(f_int_field);
f_obj_off = unsafe.objectFieldOffset(f_obj_field);
f_long_off = unsafe.objectFieldOffset(f_long_field);
f_byte_off = unsafe.objectFieldOffset(f_byte_field);
f_short_off = unsafe.objectFieldOffset(f_short_field);
} catch (Exception e) {
System.out.println("reflection failed " + e);
e.printStackTrace();
}
}
public static void main(String[] args)
{
final TestUnsafeVolatileCAE t = new TestUnsafeVolatileCAE();
for (int i = 0; i < 100_000; i++) {
t.f_int = -1;
int res = t.testInt(-1, i);
if (res != -1 || t.f_int != i) {
throw new RuntimeException("bad result!");
}
}
for (int i = 0; i < 100_000; i++) {
t.f_long = -1;
long res = t.testLong(-1, i);
if (res != -1 || t.f_long != i) {
throw new RuntimeException("bad result!");
}
}
for (int i = 0; i < 100_000; i++) {
t.f_byte = -1;
byte i_b = (byte)i;
byte res = t.testByte((byte)-1, i_b);
if (res != (byte)-1 || t.f_byte != i_b) {
throw new RuntimeException("bad result!");
}
}
for (int i = 0; i < 100_000; i++) {
t.f_short = -1;
short i_s = (short)i;
short res = t.testShort((byte)-1, i_s);
if (res != (short)-1 || t.f_short != i_s) {
throw new RuntimeException("bad result!");
}
}
Integer minusOne = Integer.valueOf(-1);
for (int i = 0; i < 100_000; i++) {
t.f_obj = minusOne;
Object res = t.testObj(minusOne, Integer.valueOf(i));
if (res != minusOne || t.f_obj != i) {
throw new RuntimeException("bad result!");
}
}
}
public int testInt(int x, int i)
{
return unsafe.compareAndExchangeInt(this, f_int_off, x, i);
}
public Object testObj(Object x, Object o)
{
return unsafe.compareAndExchangeReference(this, f_obj_off, x, o);
}
public long testLong(long x, long i)
{
return unsafe.compareAndExchangeLong(this, f_long_off, x, i);
}
public byte testByte(byte x, byte i)
{
return unsafe.compareAndExchangeByte(this, f_byte_off, x, i);
}
public short testShort(short x, short i)
{
return unsafe.compareAndExchangeShort(this, f_short_off, x, i);
}
}

View File

@ -30,19 +30,34 @@ class TestUnsafeVolatileCAS
{
public volatile int f_int = 0;
public volatile Integer f_obj = Integer.valueOf(0);
public volatile long f_long = 0;
public volatile byte f_byte = 0;
public volatile short f_short = 0;
public static Unsafe unsafe = Unsafe.getUnsafe();
public static Field f_int_field;
public static Field f_obj_field;
public static Field f_long_field;
public static Field f_byte_field;
public static Field f_short_field;
public static long f_int_off;
public static long f_obj_off;
public static long f_long_off;
public static long f_byte_off;
public static long f_short_off;
static {
try {
f_int_field = TestUnsafeVolatileCAS.class.getField("f_int");
f_obj_field = TestUnsafeVolatileCAS.class.getField("f_obj");
f_long_field = TestUnsafeVolatileCAS.class.getField("f_long");
f_byte_field = TestUnsafeVolatileCAS.class.getField("f_byte");
f_short_field = TestUnsafeVolatileCAS.class.getField("f_short");
f_int_off = unsafe.objectFieldOffset(f_int_field);
f_obj_off = unsafe.objectFieldOffset(f_obj_field);
f_long_off = unsafe.objectFieldOffset(f_long_field);
f_byte_off = unsafe.objectFieldOffset(f_byte_field);
f_short_off = unsafe.objectFieldOffset(f_short_field);
} catch (Exception e) {
System.out.println("reflection failed " + e);
e.printStackTrace();
@ -59,6 +74,29 @@ class TestUnsafeVolatileCAS
throw new RuntimeException("bad result!");
}
}
for (int i = 0; i < 100_000; i++) {
t.f_long = -1;
t.testLong(-1, i);
if (t.f_long != i) {
throw new RuntimeException("bad result!");
}
}
for (int i = 0; i < 100_000; i++) {
t.f_byte = -1;
byte i_b = (byte)i;
t.testByte((byte)-1, i_b);
if (t.f_byte != i_b) {
throw new RuntimeException("bad result!");
}
}
for (int i = 0; i < 100_000; i++) {
t.f_short = -1;
short i_s = (short)i;
t.testShort((byte)-1, i_s);
if (t.f_short != i_s) {
throw new RuntimeException("bad result!");
}
}
Integer minusOne = Integer.valueOf(-1);
for (int i = 0; i < 100_000; i++) {
t.f_obj = minusOne;
@ -68,6 +106,7 @@ class TestUnsafeVolatileCAS
}
}
}
public void testInt(int x, int i)
{
unsafe.compareAndSetInt(this, f_int_off, x, i);
@ -77,4 +116,19 @@ class TestUnsafeVolatileCAS
{
unsafe.compareAndSetReference(this, f_obj_off, x, o);
}
public void testLong(long x, long i)
{
unsafe.compareAndSetLong(this, f_long_off, x, i);
}
public void testByte(byte x, byte i)
{
unsafe.compareAndSetByte(this, f_byte_off, x, i);
}
public void testShort(short x, short i)
{
unsafe.compareAndSetShort(this, f_short_off, x, i);
}
}

View File

@ -0,0 +1,76 @@
/*
* Copyright (c) 2018, Red Hat, Inc. 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.
*/
package compiler.c2.aarch64;
import java.lang.reflect.Field;
import jdk.internal.misc.Unsafe;
class TestUnsafeVolatileGAA
{
public volatile int f_int = -1;
public volatile long f_long = -1;
public static Unsafe unsafe = Unsafe.getUnsafe();
public static Field f_int_field;
public static Field f_long_field;
public static long f_int_off;
public static long f_long_off;
static {
try {
f_int_field = TestUnsafeVolatileGAA.class.getField("f_int");
f_long_field = TestUnsafeVolatileGAA.class.getField("f_long");
f_int_off = unsafe.objectFieldOffset(f_int_field);
f_long_off = unsafe.objectFieldOffset(f_long_field);
} catch (Exception e) {
System.out.println("reflection failed " + e);
e.printStackTrace();
}
}
public static void main(String[] args)
{
final TestUnsafeVolatileGAA t = new TestUnsafeVolatileGAA();
for (int i = 0; i < 100_000; i++) {
if (t.testInt() != i-1) {
throw new RuntimeException("bad result!");
}
}
for (int i = 0; i < 100_000; i++) {
if (t.testLong() != i-1) {
throw new RuntimeException("bad result!");
}
}
}
public int testInt()
{
return unsafe.getAndAddInt(this, f_int_off, 1);
}
public long testLong()
{
return unsafe.getAndAddLong(this, f_long_off, 1);
}
}

View File

@ -0,0 +1,90 @@
/*
* Copyright (c) 2018, Red Hat, Inc. 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.
*/
package compiler.c2.aarch64;
import java.lang.reflect.Field;
import jdk.internal.misc.Unsafe;
class TestUnsafeVolatileGAS
{
public volatile int f_int = -1;
public volatile Integer f_obj = Integer.valueOf(-1);
public volatile long f_long = -1;
public static Unsafe unsafe = Unsafe.getUnsafe();
public static Field f_int_field;
public static Field f_obj_field;
public static Field f_long_field;
public static long f_int_off;
public static long f_obj_off;
public static long f_long_off;
static {
try {
f_int_field = TestUnsafeVolatileGAS.class.getField("f_int");
f_obj_field = TestUnsafeVolatileGAS.class.getField("f_obj");
f_long_field = TestUnsafeVolatileGAS.class.getField("f_long");
f_int_off = unsafe.objectFieldOffset(f_int_field);
f_obj_off = unsafe.objectFieldOffset(f_obj_field);
f_long_off = unsafe.objectFieldOffset(f_long_field);
} catch (Exception e) {
System.out.println("reflection failed " + e);
e.printStackTrace();
}
}
public static void main(String[] args)
{
final TestUnsafeVolatileGAS t = new TestUnsafeVolatileGAS();
for (int i = 0; i < 100_000; i++) {
if (t.testInt(i) != i-1) {
throw new RuntimeException("bad result!");
}
}
for (int i = 0; i < 100_000; i++) {
if (t.testLong(i) != i-1) {
throw new RuntimeException("bad result!");
}
}
for (int i = 0; i < 100_000; i++) {
if ((Integer)t.testObj(Integer.valueOf(i)) != i-1) {
throw new RuntimeException("bad result!");
}
}
}
public int testInt(int i)
{
return unsafe.getAndSetInt(this, f_int_off, i);
}
public Object testObj(Object o)
{
return unsafe.getAndSetReference(this, f_obj_off, o);
}
public long testLong(long i)
{
return unsafe.getAndSetLong(this, f_long_off, i);
}
}

View File

@ -0,0 +1,139 @@
/*
* Copyright (c) 2018, Red Hat, Inc. 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.
*/
package compiler.c2.aarch64;
import java.lang.reflect.Field;
import jdk.internal.misc.Unsafe;
class TestUnsafeVolatileWeakCAS
{
public volatile int f_int = 0;
public volatile Integer f_obj = Integer.valueOf(0);
public volatile long f_long = 0;
public volatile byte f_byte = 0;
public volatile short f_short = 0;
public static Unsafe unsafe = Unsafe.getUnsafe();
public static Field f_int_field;
public static Field f_obj_field;
public static Field f_long_field;
public static Field f_byte_field;
public static Field f_short_field;
public static long f_int_off;
public static long f_obj_off;
public static long f_long_off;
public static long f_byte_off;
public static long f_short_off;
static {
try {
f_int_field = TestUnsafeVolatileWeakCAS.class.getField("f_int");
f_obj_field = TestUnsafeVolatileWeakCAS.class.getField("f_obj");
f_long_field = TestUnsafeVolatileWeakCAS.class.getField("f_long");
f_byte_field = TestUnsafeVolatileWeakCAS.class.getField("f_byte");
f_short_field = TestUnsafeVolatileWeakCAS.class.getField("f_short");
f_int_off = unsafe.objectFieldOffset(f_int_field);
f_obj_off = unsafe.objectFieldOffset(f_obj_field);
f_long_off = unsafe.objectFieldOffset(f_long_field);
f_byte_off = unsafe.objectFieldOffset(f_byte_field);
f_short_off = unsafe.objectFieldOffset(f_short_field);
} catch (Exception e) {
System.out.println("reflection failed " + e);
e.printStackTrace();
}
}
public static void main(String[] args)
{
final TestUnsafeVolatileWeakCAS t = new TestUnsafeVolatileWeakCAS();
for (int i = 0; i < 100_000; i++) {
t.f_int = -1;
if (t.testInt(-1, i)) {
if (t.f_int != i) {
throw new RuntimeException("bad result!");
}
}
}
for (int i = 0; i < 100_000; i++) {
t.f_long = -1;
if (t.testLong(-1, i)) {
if (t.f_long != i) {
throw new RuntimeException("bad result!");
}
}
}
for (int i = 0; i < 100_000; i++) {
t.f_byte = -1;
byte i_b = (byte)i;
if (t.testByte((byte)-1, i_b)) {
if (t.f_byte != i_b) {
throw new RuntimeException("bad result!");
}
}
}
for (int i = 0; i < 100_000; i++) {
t.f_short = -1;
short i_s = (short)i;
if (t.testShort((byte)-1, i_s)) {
if (t.f_short != i_s) {
throw new RuntimeException("bad result!");
}
}
}
Integer minusOne = Integer.valueOf(-1);
for (int i = 0; i < 100_000; i++) {
t.f_obj = minusOne;
if (t.testObj(minusOne, Integer.valueOf(i))) {
if (t.f_obj != i) {
throw new RuntimeException("bad result!");
}
}
}
}
public boolean testInt(int x, int i)
{
return unsafe.weakCompareAndSetInt(this, f_int_off, x, i);
}
public boolean testObj(Object x, Object o)
{
return unsafe.weakCompareAndSetReference(this, f_obj_off, x, o);
}
public boolean testLong(long x, long i)
{
return unsafe.weakCompareAndSetLong(this, f_long_off, x, i);
}
public boolean testByte(byte x, byte i)
{
return unsafe.weakCompareAndSetByte(this, f_byte_off, x, i);
}
public boolean testShort(short x, short i)
{
return unsafe.weakCompareAndSetShort(this, f_short_off, x, i);
}
}

View File

@ -31,7 +31,10 @@
* TestVolatileStore,
* TestUnsafeVolatileLoad,
* TestUnsafeVolatileStore,
* TestUnsafeVolatileCAS}
* TestUnsafeVolatileCAS,
* TestUnsafeVolatileWeakCAS,
* TestUnsafeVolatileCAE,
* TestUnsafeVolatileGAS}
* and <testtype> in {G1,
* CMS,
* CMSCondMark,
@ -43,13 +46,16 @@
package compiler.c2.aarch64;
import java.util.List;
import java.util.ListIterator;
import java.util.Iterator;
import java.util.regex.Pattern;
import java.io.*;
import jdk.test.lib.Asserts;
import jdk.test.lib.compiler.InMemoryJavaCompiler;
import jdk.test.lib.process.OutputAnalyzer;
import jdk.test.lib.process.ProcessTools;
import sun.hotspot.WhiteBox;
// runner class that spawns a new JVM to exercises a combination of
// volatile MemOp and GC. The ops are compiled with the dmb -->
@ -68,28 +74,28 @@ public class TestVolatiles {
// i.e. GC type plus GC conifg
switch(testType) {
case "G1":
argcount = 8;
argcount = 9;
procArgs = new String[argcount];
procArgs[argcount - 2] = "-XX:+UseG1GC";
break;
case "Parallel":
argcount = 8;
argcount = 9;
procArgs = new String[argcount];
procArgs[argcount - 2] = "-XX:+UseParallelGC";
break;
case "Serial":
argcount = 8;
argcount = 9;
procArgs = new String[argcount];
procArgs[argcount - 2] = "-XX:+UseSerialGC";
break;
case "CMS":
argcount = 9 ;
argcount = 10;
procArgs = new String[argcount];
procArgs[argcount - 3] = "-XX:+UseConcMarkSweepGC";
procArgs[argcount - 2] = "-XX:-UseCondCardMark";
break;
case "CMSCondMark":
argcount = 9 ;
argcount = 10;
procArgs = new String[argcount];
procArgs[argcount - 3] = "-XX:+UseConcMarkSweepGC";
procArgs[argcount - 2] = "-XX:+UseCondCardMark";
@ -106,14 +112,34 @@ public class TestVolatiles {
// disable the transform.
procArgs[0] = "-XX:-UseBarriersForVolatile";
procArgs[1] = "-XX:+UseCompressedOops";
procArgs[1] = "-XX:-TieredCompilation";
procArgs[2] = "-XX:+PrintOptoAssembly";
procArgs[3] = "-XX:CompileCommand=compileonly," + fullclassname + "::" + "test*";
procArgs[4] = "--add-exports";
procArgs[5] = "java.base/jdk.internal.misc=ALL-UNNAMED";
procArgs[2] = "-XX:-TieredCompilation";
procArgs[3] = "-XX:+PrintOptoAssembly";
procArgs[4] = "-XX:CompileCommand=compileonly," + fullclassname + "::" + "test*";
procArgs[5] = "--add-exports";
procArgs[6] = "java.base/jdk.internal.misc=ALL-UNNAMED";
procArgs[argcount - 1] = fullclassname;
runtest(classname, testType, false, true, procArgs);
// rerun the test class without the transform applied and
// check the alternative generation is as expected
procArgs[0] = "-XX:+UseBarriersForVolatile";
runtest(classname, testType, true, true, procArgs);
if (!classname.equals("TestUnsafeVolatileGAA")) {
procArgs[0] = "-XX:-UseBarriersForVolatile";
procArgs[1] = "-XX:-UseCompressedOops";
runtest(classname, testType, false, false, procArgs);
procArgs[0] = "-XX:+UseBarriersForVolatile";
runtest(classname, testType, true, false, procArgs);
}
}
public void runtest(String classname, String testType, boolean useBarriersForVolatile, boolean useCompressedOops, String[] procArgs) throws Throwable {
ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(procArgs);
OutputAnalyzer output = new OutputAnalyzer(pb.start());
@ -125,23 +151,7 @@ public class TestVolatiles {
// appropriate to test class, test type and whether transform
// was applied
checkoutput(output, classname, testType, false);
// rerun the test class without the transform applied and
// check the alternative generation is as expected
procArgs[0] = "-XX:+UseBarriersForVolatile";
pb = ProcessTools.createJavaProcessBuilder(procArgs);
output = new OutputAnalyzer(pb.start());
output.stderrShouldBeEmptyIgnoreVMWarnings();
output.stdoutShouldNotBeEmpty();
output.shouldHaveExitValue(0);
// again check the output for the correct asm sequence
checkoutput(output, classname, testType, true);
checkoutput(output, classname, testType, useBarriersForVolatile, useCompressedOops);
}
// skip through output returning a line containing the desireed
@ -150,7 +160,7 @@ public class TestVolatiles {
{
while (iter.hasNext()) {
String nextLine = iter.next();
if (nextLine.contains(substring)) {
if (nextLine.matches(".*" + substring + ".*")) {
return nextLine;
}
}
@ -163,7 +173,7 @@ public class TestVolatiles {
// n.b. the spawned JVM's output is included in the exception
// message to make it easeir to identify what is missing.
private void checkCompile(Iterator<String> iter, String methodname, String[] expected, OutputAnalyzer output)
private boolean checkCompile(Iterator<String> iter, String methodname, String[] expected, OutputAnalyzer output, boolean do_throw)
{
// trace call to allow eyeball check of what we are checking against
System.out.println("checkCompile(" + methodname + ",");
@ -176,30 +186,43 @@ public class TestVolatiles {
System.out.println(" })");
// look for the start of an opto assembly print block
String match = skipTo(iter, "{method}");
String match = skipTo(iter, Pattern.quote("{method}"));
if (match == null) {
throw new RuntimeException("Missing compiler output for " + methodname + "!\n\n" + output.getOutput());
if (do_throw) {
throw new RuntimeException("Missing compiler output for " + methodname + "!\n\n" + output.getOutput());
}
return false;
}
// check the compiled method name is right
match = skipTo(iter, "- name:");
match = skipTo(iter, Pattern.quote("- name:"));
if (match == null) {
throw new RuntimeException("Missing compiled method name!\n\n" + output.getOutput());
if (do_throw) {
throw new RuntimeException("Missing compiled method name!\n\n" + output.getOutput());
}
return false;
}
if (!match.contains(methodname)) {
throw new RuntimeException("Wrong method " + match + "!\n -- expecting " + methodname + "\n\n" + output.getOutput());
if (do_throw) {
throw new RuntimeException("Wrong method " + match + "!\n -- expecting " + methodname + "\n\n" + output.getOutput());
}
return false;
}
// make sure we can match each expected term in order
for (String s : expected) {
match = skipTo(iter, s);
if (match == null) {
throw new RuntimeException("Missing expected output " + s + "!\n\n" + output.getOutput());
if (do_throw) {
throw new RuntimeException("Missing expected output " + s + "!\n\n" + output.getOutput());
}
return false;
}
}
return true;
}
// check for expected asm output from a volatile load
private void checkload(OutputAnalyzer output, String testType, boolean useBarriersForVolatile) throws Throwable
private void checkload(OutputAnalyzer output, String testType, boolean useBarriersForVolatile, boolean useCompressedOops) throws Throwable
{
Iterator<String> iter = output.asLines().listIterator();
@ -211,7 +234,7 @@ public class TestVolatiles {
if (!useBarriersForVolatile) {
matches = new String[] {
"ldarw",
"membar_acquire (elided)",
"membar_acquire \\(elided\\)",
"ret"
};
} else {
@ -223,15 +246,30 @@ public class TestVolatiles {
};
}
checkCompile(iter, "testInt", matches, output);
checkCompile(iter, "testInt", matches, output, true);
checkCompile(iter, "testObj", matches, output) ;
if (!useBarriersForVolatile) {
matches = new String[] {
useCompressedOops ? "ldarw?" : "ldar",
"membar_acquire \\(elided\\)",
"ret"
};
} else {
matches = new String[] {
useCompressedOops ? "ldrw?" : "ldr",
"membar_acquire",
"dmb ish",
"ret"
};
}
checkCompile(iter, "testObj", matches, output, true);
}
// check for expected asm output from a volatile store
private void checkstore(OutputAnalyzer output, String testType, boolean useBarriersForVolatile) throws Throwable
private void checkstore(OutputAnalyzer output, String testType, boolean useBarriersForVolatile, boolean useCompressedOops) throws Throwable
{
Iterator<String> iter = output.asLines().listIterator();
@ -241,9 +279,9 @@ public class TestVolatiles {
if (!useBarriersForVolatile) {
// this is the sequence of instructions for all cases
matches = new String[] {
"membar_release (elided)",
"membar_release \\(elided\\)",
"stlrw",
"membar_volatile (elided)",
"membar_volatile \\(elided\\)",
"ret"
};
} else {
@ -258,7 +296,7 @@ public class TestVolatiles {
};
}
checkCompile(iter, "testInt", matches, output);
checkCompile(iter, "testInt", matches, output, true);
// object stores will be as above except for when the GC
// introduces barriers for card marking
@ -268,9 +306,9 @@ public class TestVolatiles {
default:
// this is the basic sequence of instructions
matches = new String[] {
"membar_release (elided)",
"stlrw",
"membar_volatile (elided)",
"membar_release \\(elided\\)",
useCompressedOops ? "stlrw?" : "stlr",
"membar_volatile \\(elided\\)",
"ret"
};
break;
@ -278,12 +316,12 @@ public class TestVolatiles {
// a card mark volatile barrier should be generated
// before the card mark strb
matches = new String[] {
"membar_release (elided)",
"stlrw",
"membar_release \\(elided\\)",
useCompressedOops ? "stlrw?" : "stlr",
"membar_volatile",
"dmb ish",
"strb",
"membar_volatile (elided)",
"membar_volatile \\(elided\\)",
"ret"
};
break;
@ -292,13 +330,13 @@ public class TestVolatiles {
// before the card mark strb from the StoreCM and the
// storestore barrier from the StoreCM should be elided
matches = new String[] {
"membar_release (elided)",
"stlrw",
"membar_release \\(elided\\)",
useCompressedOops ? "stlrw?" : "stlr",
"membar_volatile",
"dmb ish",
"storestore (elided)",
"storestore \\(elided\\)",
"strb",
"membar_volatile (elided)",
"membar_volatile \\(elided\\)",
"ret"
};
break;
@ -308,12 +346,12 @@ public class TestVolatiles {
// storestore barrier from the StoreCM should be
// generated as "dmb ishst"
matches = new String[] {
"membar_release (elided)",
"stlrw",
"membar_release \\(elided\\)",
useCompressedOops ? "stlrw?" : "stlr",
"storestore",
"dmb ishst",
"strb",
"membar_volatile (elided)",
"membar_volatile \\(elided\\)",
"ret"
};
break;
@ -325,7 +363,7 @@ public class TestVolatiles {
matches = new String[] {
"membar_release",
"dmb ish",
"strw",
useCompressedOops ? "strw?" : "str",
"membar_volatile",
"dmb ish",
"ret"
@ -337,7 +375,7 @@ public class TestVolatiles {
matches = new String[] {
"membar_release",
"dmb ish",
"strw",
useCompressedOops ? "strw?" : "str",
"membar_volatile",
"dmb ish",
"strb",
@ -353,10 +391,10 @@ public class TestVolatiles {
matches = new String[] {
"membar_release",
"dmb ish",
"strw",
useCompressedOops ? "strw?" : "str",
"membar_volatile",
"dmb ish",
"storestore (elided)",
"storestore \\(elided\\)",
"strb",
"membar_volatile",
"dmb ish",
@ -371,7 +409,7 @@ public class TestVolatiles {
matches = new String[] {
"membar_release",
"dmb ish",
"strw",
useCompressedOops ? "strw?" : "str",
"storestore",
"dmb ishst",
"strb",
@ -383,40 +421,48 @@ public class TestVolatiles {
}
}
checkCompile(iter, "testObj", matches, output);
checkCompile(iter, "testObj", matches, output, true);
}
// check for expected asm output from a volatile cas
private void checkcas(OutputAnalyzer output, String testType, boolean useBarriersForVolatile) throws Throwable
private void checkcas(OutputAnalyzer output, String testType, boolean useBarriersForVolatile, boolean useCompressedOops) throws Throwable
{
Iterator<String> iter = output.asLines().listIterator();
String[] matches;
String[][] tests = {
{ "testInt", "cmpxchgw" },
{ "testLong", "cmpxchg" },
{ "testByte", "cmpxchgb" },
{ "testShort", "cmpxchgs" },
};
// non object stores are straightforward
if (!useBarriersForVolatile) {
// this is the sequence of instructions for all cases
matches = new String[] {
"membar_release (elided)",
"cmpxchgw_acq",
"membar_acquire (elided)",
"ret"
};
} else {
// this is the alternative sequence of instructions
matches = new String[] {
"membar_release",
"dmb ish",
"cmpxchgw",
"membar_acquire",
"dmb ish",
"ret"
};
for (String[] test : tests) {
// non object stores are straightforward
if (!useBarriersForVolatile) {
// this is the sequence of instructions for all cases
matches = new String[] {
"membar_release \\(elided\\)",
test[1] + "_acq",
"membar_acquire \\(elided\\)",
"ret"
};
} else {
// this is the alternative sequence of instructions
matches = new String[] {
"membar_release",
"dmb ish",
test[1] + " ",
"membar_acquire",
"dmb ish",
"ret"
};
}
checkCompile(iter, test[0], matches, output, true);
}
checkCompile(iter, "testInt", matches, output);
// object stores will be as above except for when the GC
// introduces barriers for card marking
@ -425,10 +471,10 @@ public class TestVolatiles {
default:
// this is the basic sequence of instructions
matches = new String[] {
"membar_release (elided)",
"cmpxchgw_acq",
"membar_release \\(elided\\)",
useCompressedOops ? "cmpxchgw?_acq" : "cmpxchg_acq",
"strb",
"membar_acquire (elided)",
"membar_acquire \\(elided\\)",
"ret"
};
break;
@ -436,12 +482,12 @@ public class TestVolatiles {
// a card mark volatile barrier should be generated
// before the card mark strb
matches = new String[] {
"membar_release (elided)",
"cmpxchgw_acq",
"membar_release \\(elided\\)",
useCompressedOops ? "cmpxchgw?_acq" : "cmpxchg_acq",
"membar_volatile",
"dmb ish",
"strb",
"membar_acquire (elided)",
"membar_acquire \\(elided\\)",
"ret"
};
break;
@ -450,13 +496,13 @@ public class TestVolatiles {
// before the card mark strb from the StoreCM and the
// storestore barrier from the StoreCM should be elided
matches = new String[] {
"membar_release (elided)",
"cmpxchgw_acq",
"membar_release \\(elided\\)",
useCompressedOops ? "cmpxchgw?_acq" : "cmpxchg_acq",
"membar_volatile",
"dmb ish",
"storestore (elided)",
"storestore \\(elided\\)",
"strb",
"membar_acquire (elided)",
"membar_acquire \\(elided\\)",
"ret"
};
break;
@ -465,12 +511,12 @@ public class TestVolatiles {
// before the card mark strb from the StoreCM and the
// storestore barrier from the StoreCM should be elided
matches = new String[] {
"membar_release (elided)",
"cmpxchgw_acq",
"membar_release \\(elided\\)",
useCompressedOops ? "cmpxchgw?_acq" : "cmpxchg_acq",
"storestore",
"dmb ishst",
"strb",
"membar_acquire (elided)",
"membar_acquire \\(elided\\)",
"ret"
};
break;
@ -482,7 +528,7 @@ public class TestVolatiles {
matches = new String[] {
"membar_release",
"dmb ish",
"cmpxchgw",
useCompressedOops ? "cmpxchgw? " : "cmpxchg ",
"membar_acquire",
"dmb ish",
"ret"
@ -494,7 +540,7 @@ public class TestVolatiles {
matches = new String[] {
"membar_release",
"dmb ish",
"cmpxchgw",
useCompressedOops ? "cmpxchgw? " : "cmpxchg ",
"membar_volatile",
"dmb ish",
"strb",
@ -510,10 +556,10 @@ public class TestVolatiles {
matches = new String[] {
"membar_release",
"dmb ish",
"cmpxchgw",
useCompressedOops ? "cmpxchgw? " : "cmpxchg ",
"membar_volatile",
"dmb ish",
"storestore (elided)",
"storestore \\(elided\\)",
"strb",
"membar_acquire",
"dmb ish",
@ -528,7 +574,7 @@ public class TestVolatiles {
matches = new String[] {
"membar_release",
"dmb ish",
"cmpxchgw",
useCompressedOops ? "cmpxchgw? " : "cmpxchg ",
"storestore",
"dmb ishst",
"strb",
@ -540,12 +586,391 @@ public class TestVolatiles {
}
}
checkCompile(iter, "testObj", matches, output);
checkCompile(iter, "testObj", matches, output, true);
}
private void checkcae(OutputAnalyzer output, String testType, boolean useBarriersForVolatile, boolean useCompressedOops) throws Throwable
{
ListIterator<String> iter = output.asLines().listIterator();
String[] matches;
String[][] tests = {
{ "testInt", "cmpxchgw" },
{ "testLong", "cmpxchg" },
{ "testByte", "cmpxchgb" },
{ "testShort", "cmpxchgs" },
};
for (String[] test : tests) {
// non object stores are straightforward
if (!useBarriersForVolatile) {
// this is the sequence of instructions for all cases
matches = new String[] {
"membar_release \\(elided\\)",
test[1] + "_acq",
"membar_acquire \\(elided\\)",
"ret"
};
} else {
// this is the alternative sequence of instructions
matches = new String[] {
"membar_release",
"dmb ish",
test[1] + " ",
"membar_acquire",
"dmb ish",
"ret"
};
}
checkCompile(iter, test[0], matches, output, true);
}
// object stores will be as above except for when the GC
// introduces barriers for card marking
if (!useBarriersForVolatile) {
switch (testType) {
default:
// this is the basic sequence of instructions
matches = new String[] {
"membar_release \\(elided\\)",
"strb",
useCompressedOops ? "cmpxchgw?_acq" : "cmpxchg_acq",
"membar_acquire \\(elided\\)",
"ret"
};
// card marking store may be scheduled before or after
// the cmpxchg so try both sequences.
int idx = iter.nextIndex();
if (!checkCompile(iter, "testObj", matches, output, false)) {
iter = output.asLines().listIterator(idx);
matches = new String[] {
"membar_release \\(elided\\)",
useCompressedOops ? "cmpxchgw?_acq" : "cmpxchg_acq",
"strb",
"membar_acquire \\(elided\\)",
"ret"
};
checkCompile(iter, "testObj", matches, output, true);
}
return;
case "G1":
// a card mark volatile barrier should be generated
// before the card mark strb
matches = new String[] {
"membar_release \\(elided\\)",
useCompressedOops ? "cmpxchgw?_acq" : "cmpxchg_acq",
"membar_volatile",
"dmb ish",
"strb",
"membar_acquire \\(elided\\)",
"ret"
};
break;
case "CMSCondMark":
// a card mark volatile barrier should be generated
// before the card mark strb from the StoreCM and the
// storestore barrier from the StoreCM should be elided
matches = new String[] {
"membar_release \\(elided\\)",
useCompressedOops ? "cmpxchgw?_acq" : "cmpxchg_acq",
"membar_volatile",
"dmb ish",
"storestore \\(elided\\)",
"strb",
"membar_acquire \\(elided\\)",
"ret"
};
break;
case "CMS":
// a volatile card mark membar should not be generated
// before the card mark strb from the StoreCM and the
// storestore barrier from the StoreCM should be elided
matches = new String[] {
"membar_release \\(elided\\)",
useCompressedOops ? "cmpxchgw?_acq" : "cmpxchg_acq",
"storestore",
"dmb ishst",
"strb",
"membar_acquire \\(elided\\)",
"ret"
};
break;
}
} else {
switch (testType) {
default:
// this is the basic sequence of instructions
matches = new String[] {
"membar_release",
"dmb ish",
useCompressedOops ? "cmpxchgw? " : "cmpxchg ",
"membar_acquire",
"dmb ish",
"ret"
};
break;
case "G1":
// a card mark volatile barrier should be generated
// before the card mark strb
matches = new String[] {
"membar_release",
"dmb ish",
useCompressedOops ? "cmpxchgw? " : "cmpxchg ",
"membar_volatile",
"dmb ish",
"strb",
"membar_acquire",
"dmb ish",
"ret"
};
break;
case "CMSCondMark":
// a card mark volatile barrier should be generated
// before the card mark strb from the StoreCM and the
// storestore barrier from the StoreCM should be elided
matches = new String[] {
"membar_release",
"dmb ish",
useCompressedOops ? "cmpxchgw? " : "cmpxchg ",
"membar_volatile",
"dmb ish",
"storestore \\(elided\\)",
"strb",
"membar_acquire",
"dmb ish",
"ret"
};
break;
case "CMS":
// a volatile card mark membar should not be generated
// before the card mark strb from the StoreCM and the
// storestore barrier from the StoreCM should be generated
// as "dmb ishst"
matches = new String[] {
"membar_release",
"dmb ish",
useCompressedOops ? "cmpxchgw? " : "cmpxchg ",
"storestore",
"dmb ishst",
"strb",
"membar_acquire",
"dmb ish",
"ret"
};
break;
}
}
checkCompile(iter, "testObj", matches, output, true);
}
private void checkgas(OutputAnalyzer output, String testType, boolean useBarriersForVolatile, boolean useCompressedOops) throws Throwable
{
Iterator<String> iter = output.asLines().listIterator();
String[] matches;
String[][] tests = {
{ "testInt", "atomic_xchgw" },
{ "testLong", "atomic_xchg" },
};
for (String[] test : tests) {
// non object stores are straightforward
if (!useBarriersForVolatile) {
// this is the sequence of instructions for all cases
matches = new String[] {
"membar_release \\(elided\\)",
test[1] + "_acq",
"membar_acquire \\(elided\\)",
"ret"
};
} else {
// this is the alternative sequence of instructions
matches = new String[] {
"membar_release",
"dmb ish",
test[1] + " ",
"membar_acquire",
"dmb ish",
"ret"
};
}
checkCompile(iter, test[0], matches, output, true);
}
// object stores will be as above except for when the GC
// introduces barriers for card marking
if (!useBarriersForVolatile) {
switch (testType) {
default:
// this is the basic sequence of instructions
matches = new String[] {
"membar_release \\(elided\\)",
useCompressedOops ? "atomic_xchgw?_acq" : "atomic_xchg_acq",
"strb",
"membar_acquire \\(elided\\)",
"ret"
};
break;
case "G1":
// a card mark volatile barrier should be generated
// before the card mark strb
matches = new String[] {
"membar_release \\(elided\\)",
useCompressedOops ? "atomic_xchgw?_acq" : "atomic_xchg_acq",
"membar_volatile",
"dmb ish",
"strb",
"membar_acquire \\(elided\\)",
"ret"
};
break;
case "CMSCondMark":
// a card mark volatile barrier should be generated
// before the card mark strb from the StoreCM and the
// storestore barrier from the StoreCM should be elided
matches = new String[] {
"membar_release \\(elided\\)",
useCompressedOops ? "atomic_xchgw?_acq" : "atomic_xchg_acq",
"membar_volatile",
"dmb ish",
"storestore \\(elided\\)",
"strb",
"membar_acquire \\(elided\\)",
"ret"
};
break;
case "CMS":
// a volatile card mark membar should not be generated
// before the card mark strb from the StoreCM and the
// storestore barrier from the StoreCM should be elided
matches = new String[] {
"membar_release \\(elided\\)",
useCompressedOops ? "atomic_xchgw?_acq" : "atomic_xchg_acq",
"storestore",
"dmb ishst",
"strb",
"membar_acquire \\(elided\\)",
"ret"
};
break;
}
} else {
switch (testType) {
default:
// this is the basic sequence of instructions
matches = new String[] {
"membar_release",
"dmb ish",
useCompressedOops ? "atomic_xchgw? " : "atomic_xchg ",
"membar_acquire",
"dmb ish",
"ret"
};
break;
case "G1":
// a card mark volatile barrier should be generated
// before the card mark strb
matches = new String[] {
"membar_release",
"dmb ish",
useCompressedOops ? "atomic_xchgw? " : "atomic_xchg ",
"membar_volatile",
"dmb ish",
"strb",
"membar_acquire",
"dmb ish",
"ret"
};
break;
case "CMSCondMark":
// a card mark volatile barrier should be generated
// before the card mark strb from the StoreCM and the
// storestore barrier from the StoreCM should be elided
matches = new String[] {
"membar_release",
"dmb ish",
useCompressedOops ? "atomic_xchgw? " : "atomic_xchg ",
"membar_volatile",
"dmb ish",
"storestore \\(elided\\)",
"strb",
"membar_acquire",
"dmb ish",
"ret"
};
break;
case "CMS":
// a volatile card mark membar should not be generated
// before the card mark strb from the StoreCM and the
// storestore barrier from the StoreCM should be generated
// as "dmb ishst"
matches = new String[] {
"membar_release",
"dmb ish",
useCompressedOops ? "atomic_xchgw? " : "atomic_xchg ",
"storestore",
"dmb ishst",
"strb",
"membar_acquire",
"dmb ish",
"ret"
};
break;
}
}
checkCompile(iter, "testObj", matches, output, true);
}
private void checkgaa(OutputAnalyzer output, String testType, boolean useBarriersForVolatile) throws Throwable
{
Iterator<String> iter = output.asLines().listIterator();
String[] matches;
String[][] tests = {
{ "testInt", "get_and_addI" },
{ "testLong", "get_and_addL" },
};
for (String[] test : tests) {
// non object stores are straightforward
if (!useBarriersForVolatile) {
// this is the sequence of instructions for all cases
matches = new String[] {
"membar_release \\(elided\\)",
test[1] + "_acq",
"membar_acquire \\(elided\\)",
"ret"
};
} else {
// this is the alternative sequence of instructions
matches = new String[] {
"membar_release",
"dmb ish",
test[1] + " ",
"membar_acquire",
"dmb ish",
"ret"
};
}
checkCompile(iter, test[0], matches, output, true);
}
}
// perform a check appropriate to the classname
private void checkoutput(OutputAnalyzer output, String classname, String testType, boolean useBarriersForVolatile) throws Throwable
private void checkoutput(OutputAnalyzer output, String classname, String testType, boolean useBarriersForVolatile, boolean useCompressedOops) throws Throwable
{
// trace call to allow eyeball check of what is being checked
System.out.println("checkoutput(" +
@ -556,19 +981,29 @@ public class TestVolatiles {
switch (classname) {
case "TestVolatileLoad":
checkload(output, testType, useBarriersForVolatile);
checkload(output, testType, useBarriersForVolatile, useCompressedOops);
break;
case "TestVolatileStore":
checkstore(output, testType, useBarriersForVolatile);
checkstore(output, testType, useBarriersForVolatile, useCompressedOops);
break;
case "TestUnsafeVolatileLoad":
checkload(output, testType, useBarriersForVolatile);
checkload(output, testType, useBarriersForVolatile, useCompressedOops);
break;
case "TestUnsafeVolatileStore":
checkstore(output, testType, useBarriersForVolatile);
checkstore(output, testType, useBarriersForVolatile, useCompressedOops);
break;
case "TestUnsafeVolatileCAS":
checkcas(output, testType, useBarriersForVolatile);
case "TestUnsafeVolatileWeakCAS":
checkcas(output, testType, useBarriersForVolatile, useCompressedOops);
break;
case "TestUnsafeVolatileCAE":
checkcae(output, testType, useBarriersForVolatile, useCompressedOops);
break;
case "TestUnsafeVolatileGAS":
checkgas(output, testType, useBarriersForVolatile, useCompressedOops);
break;
case "TestUnsafeVolatileGAA":
checkgaa(output, testType, useBarriersForVolatile);
break;
}
}

View File

@ -38,6 +38,9 @@
* compiler.c2.aarch64.TestVolatileStore
* compiler.c2.aarch64.TestUnsafeVolatileStore
* compiler.c2.aarch64.TestUnsafeVolatileCAS
* compiler.c2.aarch64.TestUnsafeVolatileWeakCAS
* compiler.c2.aarch64.TestUnsafeVolatileCAE
* compiler.c2.aarch64.TestUnsafeVolatileGAS
*
* @run driver compiler.c2.aarch64.TestVolatilesCMS
* TestVolatileLoad CMS
@ -53,6 +56,15 @@
*
* @run driver compiler.c2.aarch64.TestVolatilesCMS
* TestUnsafeVolatileCAS CMS
*
* @run driver compiler.c2.aarch64.TestVolatilesCMS
* TestUnsafeVolatileWeakCAS CMS
*
* @run driver compiler.c2.aarch64.TestVolatilesCMS
* TestUnsafeVolatileCAE CMS
*
* @run driver compiler.c2.aarch64.TestVolatilesCMS
* TestUnsafeVolatileGAS CMS
*/
package compiler.c2.aarch64;

View File

@ -38,6 +38,9 @@
* compiler.c2.aarch64.TestVolatileStore
* compiler.c2.aarch64.TestUnsafeVolatileStore
* compiler.c2.aarch64.TestUnsafeVolatileCAS
* compiler.c2.aarch64.TestUnsafeVolatileWeakCAS
* compiler.c2.aarch64.TestUnsafeVolatileCAE
* compiler.c2.aarch64.TestUnsafeVolatileGAS
*
* @run driver compiler.c2.aarch64.TestVolatilesCMSCondMark
* TestVolatileLoad CMSCondMark
@ -53,6 +56,15 @@
*
* @run driver compiler.c2.aarch64.TestVolatilesCMSCondMark
* TestUnsafeVolatileCAS CMSCondMark
*
* @run driver compiler.c2.aarch64.TestVolatilesCMSCondMark
* TestUnsafeVolatileWeakCAS CMSCondMark
*
* @run driver compiler.c2.aarch64.TestVolatilesCMSCondMark
* TestUnsafeVolatileCAE CMSCondMark
*
* @run driver compiler.c2.aarch64.TestVolatilesCMSCondMark
* TestUnsafeVolatileGAS CMSCondMark
*/
package compiler.c2.aarch64;

View File

@ -38,6 +38,10 @@
* compiler.c2.aarch64.TestVolatileStore
* compiler.c2.aarch64.TestUnsafeVolatileStore
* compiler.c2.aarch64.TestUnsafeVolatileCAS
* compiler.c2.aarch64.TestUnsafeVolatileWeakCAS
* compiler.c2.aarch64.TestUnsafeVolatileCAE
* compiler.c2.aarch64.TestUnsafeVolatileGAS
* compiler.c2.aarch64.TestUnsafeVolatileGAA
*
* @run driver compiler.c2.aarch64.TestVolatilesG1
* TestVolatileLoad G1
@ -53,8 +57,21 @@
*
* @run driver compiler.c2.aarch64.TestVolatilesG1
* TestUnsafeVolatileCAS G1
*
* @run driver compiler.c2.aarch64.TestVolatilesG1
* TestUnsafeVolatileWeakCAS G1
*
* @run driver compiler.c2.aarch64.TestVolatilesG1
* TestUnsafeVolatileCAE G1
*
* @run driver compiler.c2.aarch64.TestVolatilesG1
* TestUnsafeVolatileGAS G1
*
* @run driver compiler.c2.aarch64.TestVolatilesG1
* TestUnsafeVolatileGAA G1
*/
package compiler.c2.aarch64;
public class TestVolatilesG1 {

View File

@ -38,6 +38,9 @@
* compiler.c2.aarch64.TestVolatileStore
* compiler.c2.aarch64.TestUnsafeVolatileStore
* compiler.c2.aarch64.TestUnsafeVolatileCAS
* compiler.c2.aarch64.TestUnsafeVolatileWeakCAS
* compiler.c2.aarch64.TestUnsafeVolatileCAE
* compiler.c2.aarch64.TestUnsafeVolatileGAS
*
* @run driver compiler.c2.aarch64.TestVolatilesParallel
* TestVolatileLoad Parallel
@ -53,6 +56,15 @@
*
* @run driver compiler.c2.aarch64.TestVolatilesParallel
* TestUnsafeVolatileCAS Parallel
*
* @run driver compiler.c2.aarch64.TestVolatilesParallel
* TestUnsafeVolatileWeakCAS Parallel
*
* @run driver compiler.c2.aarch64.TestVolatilesParallel
* TestUnsafeVolatileCAE Parallel
*
* @run driver compiler.c2.aarch64.TestVolatilesParallel
* TestUnsafeVolatileGAS Parallel
*/
package compiler.c2.aarch64;

View File

@ -38,6 +38,9 @@
* compiler.c2.aarch64.TestVolatileStore
* compiler.c2.aarch64.TestUnsafeVolatileStore
* compiler.c2.aarch64.TestUnsafeVolatileCAS
* compiler.c2.aarch64.TestUnsafeVolatileWeakCAS
* compiler.c2.aarch64.TestUnsafeVolatileCAE
* compiler.c2.aarch64.TestUnsafeVolatileGAS
*
* @run driver compiler.c2.aarch64.TestVolatilesSerial
* TestVolatileLoad Serial
@ -53,6 +56,15 @@
*
* @run driver compiler.c2.aarch64.TestVolatilesSerial
* TestUnsafeVolatileCAS Serial
*
* @run driver compiler.c2.aarch64.TestVolatilesSerial
* TestUnsafeVolatileWeakCAS Serial
*
* @run driver compiler.c2.aarch64.TestVolatilesSerial
* TestUnsafeVolatileCAE Serial
*
* @run driver compiler.c2.aarch64.TestVolatilesSerial
* TestUnsafeVolatileGAS Serial
*/
package compiler.c2.aarch64;