提交 b9f75f35 编写于 作者: I iveresov

7009231: C1: Incorrect CAS code for longs on SPARC 32bit

Summary: Fix CAS of longs on SPARC 32bit and cmove on SPARC 64bit.
Reviewed-by: kvn
上级 8f6f72b9
...@@ -1705,8 +1705,7 @@ void LIR_Assembler::comp_fl2i(LIR_Code code, LIR_Opr left, LIR_Opr right, LIR_Op ...@@ -1705,8 +1705,7 @@ void LIR_Assembler::comp_fl2i(LIR_Code code, LIR_Opr left, LIR_Opr right, LIR_Op
} }
void LIR_Assembler::cmove(LIR_Condition condition, LIR_Opr opr1, LIR_Opr opr2, LIR_Opr result) { void LIR_Assembler::cmove(LIR_Condition condition, LIR_Opr opr1, LIR_Opr opr2, LIR_Opr result, BasicType type) {
Assembler::Condition acond; Assembler::Condition acond;
switch (condition) { switch (condition) {
case lir_cond_equal: acond = Assembler::equal; break; case lir_cond_equal: acond = Assembler::equal; break;
...@@ -1737,7 +1736,12 @@ void LIR_Assembler::cmove(LIR_Condition condition, LIR_Opr opr1, LIR_Opr opr2, L ...@@ -1737,7 +1736,12 @@ void LIR_Assembler::cmove(LIR_Condition condition, LIR_Opr opr1, LIR_Opr opr2, L
ShouldNotReachHere(); ShouldNotReachHere();
} }
Label skip; Label skip;
#ifdef _LP64
if (type == T_INT) {
__ br(acond, false, Assembler::pt, skip); __ br(acond, false, Assembler::pt, skip);
} else
#endif
__ brx(acond, false, Assembler::pt, skip); // checks icc on 32bit and xcc on 64bit
if (opr1->is_constant() && opr1->type() == T_INT) { if (opr1->is_constant() && opr1->type() == T_INT) {
Register dest = result->as_register(); Register dest = result->as_register();
if (Assembler::is_simm13(opr1->as_jint())) { if (Assembler::is_simm13(opr1->as_jint())) {
...@@ -2688,6 +2692,11 @@ void LIR_Assembler::emit_compare_and_swap(LIR_OpCompareAndSwap* op) { ...@@ -2688,6 +2692,11 @@ void LIR_Assembler::emit_compare_and_swap(LIR_OpCompareAndSwap* op) {
#ifdef _LP64 #ifdef _LP64
__ mov(cmp_value_lo, t1); __ mov(cmp_value_lo, t1);
__ mov(new_value_lo, t2); __ mov(new_value_lo, t2);
// perform the compare and swap operation
__ casx(addr, t1, t2);
// generate condition code - if the swap succeeded, t2 ("new value" reg) was
// overwritten with the original value in "addr" and will be equal to t1.
__ cmp(t1, t2);
#else #else
// move high and low halves of long values into single registers // move high and low halves of long values into single registers
__ sllx(cmp_value_hi, 32, t1); // shift high half into temp reg __ sllx(cmp_value_hi, 32, t1); // shift high half into temp reg
...@@ -2696,13 +2705,15 @@ void LIR_Assembler::emit_compare_and_swap(LIR_OpCompareAndSwap* op) { ...@@ -2696,13 +2705,15 @@ void LIR_Assembler::emit_compare_and_swap(LIR_OpCompareAndSwap* op) {
__ sllx(new_value_hi, 32, t2); __ sllx(new_value_hi, 32, t2);
__ srl(new_value_lo, 0, new_value_lo); __ srl(new_value_lo, 0, new_value_lo);
__ or3(t2, new_value_lo, t2); // t2 holds 64-bit value to swap __ or3(t2, new_value_lo, t2); // t2 holds 64-bit value to swap
#endif
// perform the compare and swap operation // perform the compare and swap operation
__ casx(addr, t1, t2); __ casx(addr, t1, t2);
// generate condition code - if the swap succeeded, t2 ("new value" reg) was // generate condition code - if the swap succeeded, t2 ("new value" reg) was
// overwritten with the original value in "addr" and will be equal to t1. // overwritten with the original value in "addr" and will be equal to t1.
__ cmp(t1, t2); // Produce icc flag for 32bit.
__ sub(t1, t2, t2);
__ srlx(t2, 32, t1);
__ orcc(t2, t1, G0);
#endif
} else if (op->code() == lir_cas_int || op->code() == lir_cas_obj) { } else if (op->code() == lir_cas_int || op->code() == lir_cas_obj) {
Register addr = op->addr()->as_pointer_register(); Register addr = op->addr()->as_pointer_register();
Register cmp_value = op->cmp_value()->as_register(); Register cmp_value = op->cmp_value()->as_register();
......
...@@ -662,7 +662,7 @@ void LIRGenerator::do_AttemptUpdate(Intrinsic* x) { ...@@ -662,7 +662,7 @@ void LIRGenerator::do_AttemptUpdate(Intrinsic* x) {
// generate conditional move of boolean result // generate conditional move of boolean result
LIR_Opr result = rlock_result(x); LIR_Opr result = rlock_result(x);
__ cmove(lir_cond_equal, LIR_OprFact::intConst(1), LIR_OprFact::intConst(0), result); __ cmove(lir_cond_equal, LIR_OprFact::intConst(1), LIR_OprFact::intConst(0), result, T_LONG);
} }
...@@ -699,10 +699,10 @@ void LIRGenerator::do_CompareAndSwap(Intrinsic* x, ValueType* type) { ...@@ -699,10 +699,10 @@ void LIRGenerator::do_CompareAndSwap(Intrinsic* x, ValueType* type) {
else { else {
ShouldNotReachHere(); ShouldNotReachHere();
} }
// generate conditional move of boolean result // generate conditional move of boolean result
LIR_Opr result = rlock_result(x); LIR_Opr result = rlock_result(x);
__ cmove(lir_cond_equal, LIR_OprFact::intConst(1), LIR_OprFact::intConst(0), result); __ cmove(lir_cond_equal, LIR_OprFact::intConst(1), LIR_OprFact::intConst(0),
result, as_BasicType(type));
if (type == objectType) { // Write-barrier needed for Object fields. if (type == objectType) { // Write-barrier needed for Object fields.
// Precise card mark since could either be object or array // Precise card mark since could either be object or array
post_barrier(addr, val.result()); post_barrier(addr, val.result());
......
...@@ -2036,7 +2036,7 @@ void LIR_Assembler::emit_compare_and_swap(LIR_OpCompareAndSwap* op) { ...@@ -2036,7 +2036,7 @@ void LIR_Assembler::emit_compare_and_swap(LIR_OpCompareAndSwap* op) {
} }
} }
void LIR_Assembler::cmove(LIR_Condition condition, LIR_Opr opr1, LIR_Opr opr2, LIR_Opr result) { void LIR_Assembler::cmove(LIR_Condition condition, LIR_Opr opr1, LIR_Opr opr2, LIR_Opr result, BasicType type) {
Assembler::Condition acond, ncond; Assembler::Condition acond, ncond;
switch (condition) { switch (condition) {
case lir_cond_equal: acond = Assembler::equal; ncond = Assembler::notEqual; break; case lir_cond_equal: acond = Assembler::equal; ncond = Assembler::notEqual; break;
......
...@@ -741,7 +741,7 @@ void LIRGenerator::do_AttemptUpdate(Intrinsic* x) { ...@@ -741,7 +741,7 @@ void LIRGenerator::do_AttemptUpdate(Intrinsic* x) {
// generate conditional move of boolean result // generate conditional move of boolean result
LIR_Opr result = rlock_result(x); LIR_Opr result = rlock_result(x);
__ cmove(lir_cond_equal, LIR_OprFact::intConst(1), LIR_OprFact::intConst(0), result); __ cmove(lir_cond_equal, LIR_OprFact::intConst(1), LIR_OprFact::intConst(0), result, T_LONG);
} }
...@@ -810,7 +810,8 @@ void LIRGenerator::do_CompareAndSwap(Intrinsic* x, ValueType* type) { ...@@ -810,7 +810,8 @@ void LIRGenerator::do_CompareAndSwap(Intrinsic* x, ValueType* type) {
// generate conditional move of boolean result // generate conditional move of boolean result
LIR_Opr result = rlock_result(x); LIR_Opr result = rlock_result(x);
__ cmove(lir_cond_equal, LIR_OprFact::intConst(1), LIR_OprFact::intConst(0), result); __ cmove(lir_cond_equal, LIR_OprFact::intConst(1), LIR_OprFact::intConst(0),
result, as_BasicType(type));
if (type == objectType) { // Write-barrier needed for Object fields. if (type == objectType) { // Write-barrier needed for Object fields.
// Seems to be precise // Seems to be precise
post_barrier(addr, val.result()); post_barrier(addr, val.result());
......
...@@ -1568,15 +1568,16 @@ class LIR_Op2: public LIR_Op { ...@@ -1568,15 +1568,16 @@ class LIR_Op2: public LIR_Op {
assert(code == lir_cmp, "code check"); assert(code == lir_cmp, "code check");
} }
LIR_Op2(LIR_Code code, LIR_Condition condition, LIR_Opr opr1, LIR_Opr opr2, LIR_Opr result) LIR_Op2(LIR_Code code, LIR_Condition condition, LIR_Opr opr1, LIR_Opr opr2, LIR_Opr result, BasicType type)
: LIR_Op(code, result, NULL) : LIR_Op(code, result, NULL)
, _opr1(opr1) , _opr1(opr1)
, _opr2(opr2) , _opr2(opr2)
, _type(T_ILLEGAL) , _type(type)
, _condition(condition) , _condition(condition)
, _fpu_stack_size(0) , _fpu_stack_size(0)
, _tmp(LIR_OprFact::illegalOpr) { , _tmp(LIR_OprFact::illegalOpr) {
assert(code == lir_cmove, "code check"); assert(code == lir_cmove, "code check");
assert(type != T_ILLEGAL, "cmove should have type");
} }
LIR_Op2(LIR_Code code, LIR_Opr opr1, LIR_Opr opr2, LIR_Opr result = LIR_OprFact::illegalOpr, LIR_Op2(LIR_Code code, LIR_Opr opr1, LIR_Opr opr2, LIR_Opr result = LIR_OprFact::illegalOpr,
...@@ -1993,8 +1994,8 @@ class LIR_List: public CompilationResourceObj { ...@@ -1993,8 +1994,8 @@ class LIR_List: public CompilationResourceObj {
void cmp_mem_int(LIR_Condition condition, LIR_Opr base, int disp, int c, CodeEmitInfo* info); void cmp_mem_int(LIR_Condition condition, LIR_Opr base, int disp, int c, CodeEmitInfo* info);
void cmp_reg_mem(LIR_Condition condition, LIR_Opr reg, LIR_Address* addr, CodeEmitInfo* info); void cmp_reg_mem(LIR_Condition condition, LIR_Opr reg, LIR_Address* addr, CodeEmitInfo* info);
void cmove(LIR_Condition condition, LIR_Opr src1, LIR_Opr src2, LIR_Opr dst) { void cmove(LIR_Condition condition, LIR_Opr src1, LIR_Opr src2, LIR_Opr dst, BasicType type) {
append(new LIR_Op2(lir_cmove, condition, src1, src2, dst)); append(new LIR_Op2(lir_cmove, condition, src1, src2, dst, type));
} }
void cas_long(LIR_Opr addr, LIR_Opr cmp_value, LIR_Opr new_value, void cas_long(LIR_Opr addr, LIR_Opr cmp_value, LIR_Opr new_value,
......
...@@ -685,7 +685,7 @@ void LIR_Assembler::emit_op2(LIR_Op2* op) { ...@@ -685,7 +685,7 @@ void LIR_Assembler::emit_op2(LIR_Op2* op) {
break; break;
case lir_cmove: case lir_cmove:
cmove(op->condition(), op->in_opr1(), op->in_opr2(), op->result_opr()); cmove(op->condition(), op->in_opr1(), op->in_opr2(), op->result_opr(), op->type());
break; break;
case lir_shl: case lir_shl:
......
...@@ -217,7 +217,7 @@ class LIR_Assembler: public CompilationResourceObj { ...@@ -217,7 +217,7 @@ class LIR_Assembler: public CompilationResourceObj {
void volatile_move_op(LIR_Opr src, LIR_Opr result, BasicType type, CodeEmitInfo* info); void volatile_move_op(LIR_Opr src, LIR_Opr result, BasicType type, CodeEmitInfo* info);
void comp_mem_op(LIR_Opr src, LIR_Opr result, BasicType type, CodeEmitInfo* info); // info set for null exceptions void comp_mem_op(LIR_Opr src, LIR_Opr result, BasicType type, CodeEmitInfo* info); // info set for null exceptions
void comp_fl2i(LIR_Code code, LIR_Opr left, LIR_Opr right, LIR_Opr result, LIR_Op2* op); void comp_fl2i(LIR_Code code, LIR_Opr left, LIR_Opr right, LIR_Opr result, LIR_Op2* op);
void cmove(LIR_Condition code, LIR_Opr left, LIR_Opr right, LIR_Opr result); void cmove(LIR_Condition code, LIR_Opr left, LIR_Opr right, LIR_Opr result, BasicType type);
void call( LIR_OpJavaCall* op, relocInfo::relocType rtype); void call( LIR_OpJavaCall* op, relocInfo::relocType rtype);
void ic_call( LIR_OpJavaCall* op); void ic_call( LIR_OpJavaCall* op);
......
...@@ -856,7 +856,7 @@ void LIRGenerator::profile_branch(If* if_instr, If::Condition cond) { ...@@ -856,7 +856,7 @@ void LIRGenerator::profile_branch(If* if_instr, If::Condition cond) {
__ cmove(lir_cond(cond), __ cmove(lir_cond(cond),
LIR_OprFact::intptrConst(taken_count_offset), LIR_OprFact::intptrConst(taken_count_offset),
LIR_OprFact::intptrConst(not_taken_count_offset), LIR_OprFact::intptrConst(not_taken_count_offset),
data_offset_reg); data_offset_reg, as_BasicType(if_instr->x()->type()));
// MDO cells are intptr_t, so the data_reg width is arch-dependent. // MDO cells are intptr_t, so the data_reg width is arch-dependent.
LIR_Opr data_reg = new_pointer_register(); LIR_Opr data_reg = new_pointer_register();
...@@ -2591,7 +2591,7 @@ void LIRGenerator::do_IfOp(IfOp* x) { ...@@ -2591,7 +2591,7 @@ void LIRGenerator::do_IfOp(IfOp* x) {
LIR_Opr reg = rlock_result(x); LIR_Opr reg = rlock_result(x);
__ cmp(lir_cond(x->cond()), left.result(), right.result()); __ cmp(lir_cond(x->cond()), left.result(), right.result());
__ cmove(lir_cond(x->cond()), t_val.result(), f_val.result(), reg); __ cmove(lir_cond(x->cond()), t_val.result(), f_val.result(), reg, as_BasicType(x->x()->type()));
} }
......
/*
* Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* 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.
*
*/
/**
* @test
* @bug 7009231
* @summary C1: Incorrect CAS code for longs on SPARC 32bit
*
* @run main/othervm -Xbatch Test7009231
*
*/
import java.util.Random;
import java.util.concurrent.atomic.AtomicLong;
public class Test7009231 {
public static void main(String[] args) throws InterruptedException {
doTest(8);
}
private static void doTest(int nThreads) throws InterruptedException {
Thread[] aThreads = new Thread[nThreads];
final AtomicLong atl = new AtomicLong();
for (int i = 0; i < nThreads; i++) {
aThreads[i] = new RunnerThread(atl, 1L << (8 * i));
}
for (int i = 0; i < nThreads; i++) {
aThreads[i].start();
}
for (int i = 0; i < nThreads; i++) {
aThreads[i].join();
}
}
public static class RunnerThread extends Thread {
public RunnerThread(AtomicLong atomic, long lMask) {
m_lMask = lMask;
m_atomic = atomic;
}
public void run() {
AtomicLong atomic = m_atomic;
long lMask = m_lMask;
for (int i = 0; i < 100000; i++) {
setBit(atomic, lMask);
clearBit(atomic, lMask);
}
}
protected void setBit(AtomicLong atomic, long lMask) {
long lWord;
do {
lWord = atomic.get();
} while (!atomic.compareAndSet(lWord, lWord | lMask));
if ((atomic.get() & lMask) == 0L) {
throw new InternalError();
}
}
protected void clearBit(AtomicLong atomic, long lMask) {
long lWord;
do {
lWord = atomic.get();
} while (!atomic.compareAndSet(lWord, lWord & ~lMask));
if ((atomic.get() & lMask) != 0L) {
throw new InternalError();
}
}
private long m_lMask;
private AtomicLong m_atomic;
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册