void LIRGenerator::do_AttemptUpdate(Intrinsic* x) { assert(x->number_of_arguments() == 3, "wrong type"); LIRItem obj (x->argument_at(0), this); // AtomicLong object LIRItem cmp_value (x->argument_at(1), this); // value to compare with field LIRItem new_value (x->argument_at(2), this); // replace field with new_value if it matches cmp_value // compare value must be in rdx,eax (hi,lo); may be destroyed by cmpxchg8 instruction cmp_value.load_item_force(FrameMap::long0_opr); // new value must be in rcx,ebx (hi,lo) new_value.load_item_force(FrameMap::long1_opr); // object pointer register is overwritten with field address obj.load_item(); // generate compare-and-swap; produces zero condition if swap occurs int value_offset = sun_misc_AtomicLongCSImpl::value_offset(); LIR_Opr addr = new_pointer_register(); __ leal(LIR_OprFact::address(new LIR_Address(obj.result(), value_offset, T_LONG)), addr); LIR_Opr t1 = LIR_OprFact::illegalOpr; // no temp needed LIR_Opr t2 = LIR_OprFact::illegalOpr; // no temp needed __ cas_long(addr, cmp_value.result(), new_value.result(), t1, t2); // generate conditional move of boolean result LIR_Opr result = rlock_result(x); __ cmove(lir_cond_equal, LIR_OprFact::intConst(1), LIR_OprFact::intConst(0), result, T_LONG); }
void LIRGenerator::do_CompareAndSwap(Intrinsic* x, ValueType* type) { assert(x->number_of_arguments() == 4, "wrong type"); LIRItem obj (x->argument_at(0), this); // object LIRItem offset(x->argument_at(1), this); // offset of field LIRItem cmp (x->argument_at(2), this); // value to compare with field LIRItem val (x->argument_at(3), this); // replace field with val if matches cmp // Use temps to avoid kills LIR_Opr t1 = FrameMap::G1_opr; LIR_Opr t2 = FrameMap::G3_opr; LIR_Opr addr = new_pointer_register(); // get address of field obj.load_item(); offset.load_item(); cmp.load_item(); val.load_item(); __ add(obj.result(), offset.result(), addr); if (type == objectType) { // Write-barrier needed for Object fields. pre_barrier(obj.result(), false, NULL); } if (type == objectType) __ cas_obj(addr, cmp.result(), val.result(), t1, t2); else if (type == intType) __ cas_int(addr, cmp.result(), val.result(), t1, t2); else if (type == longType) __ cas_long(addr, cmp.result(), val.result(), t1, t2); else { ShouldNotReachHere(); } // generate conditional move of boolean result LIR_Opr result = rlock_result(x); __ cmove(lir_cond_equal, LIR_OprFact::intConst(1), LIR_OprFact::intConst(0), result); if (type == objectType) { // Write-barrier needed for Object fields. #ifdef PRECISE_CARDMARK post_barrier(addr, val.result()); #else post_barrier(obj.result(), val.result()); #endif // PRECISE_CARDMARK } }
void LIRGenerator::do_AttemptUpdate(Intrinsic* x) { assert(x->number_of_arguments() == 3, "wrong type"); LIRItem obj (x->argument_at(0), this); // AtomicLong object LIRItem cmp_value (x->argument_at(1), this); // value to compare with field LIRItem new_value (x->argument_at(2), this); // replace field with new_value if it matches cmp_value obj.load_item(); cmp_value.load_item(); new_value.load_item(); // generate compare-and-swap and produce zero condition if swap occurs int value_offset = sun_misc_AtomicLongCSImpl::value_offset(); LIR_Opr addr = FrameMap::O7_opr; __ add(obj.result(), LIR_OprFact::intConst(value_offset), addr); LIR_Opr t1 = FrameMap::G1_opr; // temp for 64-bit value LIR_Opr t2 = FrameMap::G3_opr; // temp for 64-bit value __ cas_long(addr, cmp_value.result(), new_value.result(), t1, t2); // generate conditional move of boolean result LIR_Opr result = rlock_result(x); __ cmove(lir_cond_equal, LIR_OprFact::intConst(1), LIR_OprFact::intConst(0), result); }
void LIRGenerator::do_CompareAndSwap(Intrinsic* x, ValueType* type) { assert(x->number_of_arguments() == 4, "wrong type"); LIRItem obj (x->argument_at(0), this); // object LIRItem offset(x->argument_at(1), this); // offset of field LIRItem cmp (x->argument_at(2), this); // value to compare with field LIRItem val (x->argument_at(3), this); // replace field with val if matches cmp assert(obj.type()->tag() == objectTag, "invalid type"); // In 64bit the type can be long, sparc doesn't have this assert // assert(offset.type()->tag() == intTag, "invalid type"); assert(cmp.type()->tag() == type->tag(), "invalid type"); assert(val.type()->tag() == type->tag(), "invalid type"); // get address of field obj.load_item(); offset.load_nonconstant(); if (type == objectType) { cmp.load_item_force(FrameMap::rax_oop_opr); val.load_item(); } else if (type == intType) { cmp.load_item_force(FrameMap::rax_opr); val.load_item(); } else if (type == longType) { cmp.load_item_force(FrameMap::long0_opr); val.load_item_force(FrameMap::long1_opr); } else { ShouldNotReachHere(); } LIR_Opr addr = new_pointer_register(); LIR_Address* a; if(offset.result()->is_constant()) { a = new LIR_Address(obj.result(), NOT_LP64(offset.result()->as_constant_ptr()->as_jint()) LP64_ONLY((int)offset.result()->as_constant_ptr()->as_jlong()), as_BasicType(type)); } else { a = new LIR_Address(obj.result(), offset.result(), LIR_Address::times_1, 0, as_BasicType(type)); } __ leal(LIR_OprFact::address(a), addr); if (type == objectType) { // Write-barrier needed for Object fields. // Do the pre-write barrier, if any. pre_barrier(addr, false, NULL); } LIR_Opr ill = LIR_OprFact::illegalOpr; // for convenience if (type == objectType) __ cas_obj(addr, cmp.result(), val.result(), ill, ill); else if (type == intType) __ cas_int(addr, cmp.result(), val.result(), ill, ill); else if (type == longType) __ cas_long(addr, cmp.result(), val.result(), ill, ill); else { ShouldNotReachHere(); } // generate conditional move of boolean result LIR_Opr result = rlock_result(x); __ 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. // Seems to be precise post_barrier(addr, val.result()); } }