void LIRGenerator::do_ArrayCopy(Intrinsic* x) { assert(x->number_of_arguments() == 5, "wrong type"); // Note: spill caller save before setting the item LIRItem src (x->argument_at(0), this); LIRItem src_pos (x->argument_at(1), this); LIRItem dst (x->argument_at(2), this); LIRItem dst_pos (x->argument_at(3), this); LIRItem length (x->argument_at(4), this); // load all values in callee_save_registers, as this makes the // parameter passing to the fast case simpler src.load_item_force (rlock_callee_saved(T_OBJECT)); src_pos.load_item_force (rlock_callee_saved(T_INT)); dst.load_item_force (rlock_callee_saved(T_OBJECT)); dst_pos.load_item_force (rlock_callee_saved(T_INT)); length.load_item_force (rlock_callee_saved(T_INT)); int flags; ciArrayKlass* expected_type; arraycopy_helper(x, &flags, &expected_type); CodeEmitInfo* info = state_for(x, x->state()); __ arraycopy(src.result(), src_pos.result(), dst.result(), dst_pos.result(), length.result(), rlock_callee_saved(T_INT), expected_type, flags, info); set_no_result(x); }
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()); } }