private static bool Unsafe_compareAndSwapObject(EmitIntrinsicContext eic) { TypeWrapper tw = eic.GetStackTypeWrapper(0, 3); if (IsSupportedArrayTypeForUnsafeOperation(tw) && eic.GetStackTypeWrapper(0, 0).IsAssignableTo(tw.ElementTypeWrapper) && eic.GetStackTypeWrapper(0, 1).IsAssignableTo(tw.ElementTypeWrapper)) { Type type = tw.TypeAsLocalOrStackType.GetElementType(); CodeEmitterLocal update = eic.Emitter.AllocTempLocal(type); CodeEmitterLocal expect = eic.Emitter.AllocTempLocal(type); CodeEmitterLocal index = eic.Emitter.AllocTempLocal(Types.Int32); CodeEmitterLocal obj = eic.Emitter.AllocTempLocal(tw.TypeAsLocalOrStackType); eic.Emitter.Emit(OpCodes.Stloc, update); eic.Emitter.Emit(OpCodes.Stloc, expect); eic.Emitter.Emit(OpCodes.Conv_Ovf_I4); eic.Emitter.Emit(OpCodes.Stloc, index); eic.Emitter.Emit(OpCodes.Stloc, obj); EmitConsumeUnsafe(eic); eic.Emitter.Emit(OpCodes.Ldloc, obj); eic.Emitter.Emit(OpCodes.Ldloc, index); eic.Emitter.Emit(OpCodes.Ldelema, type); eic.Emitter.Emit(OpCodes.Ldloc, update); eic.Emitter.Emit(OpCodes.Ldloc, expect); eic.Emitter.Emit(OpCodes.Call, AtomicReferenceFieldUpdaterEmitter.MakeCompareExchange(type)); eic.Emitter.Emit(OpCodes.Ldloc, expect); eic.Emitter.Emit(OpCodes.Ceq); eic.Emitter.ReleaseTempLocal(obj); eic.Emitter.ReleaseTempLocal(index); eic.Emitter.ReleaseTempLocal(expect); eic.Emitter.ReleaseTempLocal(update); eic.NonLeaf = false; return(true); } if ((eic.Flags[eic.OpcodeIndex] & InstructionFlags.BranchTarget) != 0 || (eic.Flags[eic.OpcodeIndex - 1] & InstructionFlags.BranchTarget) != 0 || (eic.Flags[eic.OpcodeIndex - 2] & InstructionFlags.BranchTarget) != 0) { return(false); } if ((eic.Match(-1, NormalizedByteCode.__aload) || eic.Match(-1, NormalizedByteCode.__aconst_null)) && (eic.Match(-2, NormalizedByteCode.__aload) || eic.Match(-2, NormalizedByteCode.__aconst_null)) && eic.Match(-3, NormalizedByteCode.__getstatic)) { FieldWrapper fw = GetUnsafeField(eic, eic.GetFieldref(-3)); if (fw != null && fw.IsAccessibleFrom(fw.DeclaringType, eic.Caller.DeclaringType, fw.DeclaringType) && eic.GetStackTypeWrapper(0, 0).IsAssignableTo(fw.FieldTypeWrapper) && eic.GetStackTypeWrapper(0, 1).IsAssignableTo(fw.FieldTypeWrapper) && (fw.IsStatic || fw.DeclaringType == eic.GetStackTypeWrapper(0, 3))) { Type type = fw.FieldTypeWrapper.TypeAsLocalOrStackType; CodeEmitterLocal update = eic.Emitter.AllocTempLocal(type); CodeEmitterLocal expect = eic.Emitter.AllocTempLocal(type); eic.Emitter.Emit(OpCodes.Stloc, update); eic.Emitter.Emit(OpCodes.Stloc, expect); eic.Emitter.Emit(OpCodes.Pop); // discard index if (fw.IsStatic) { eic.Emitter.Emit(OpCodes.Pop); // discard obj EmitConsumeUnsafe(eic); eic.Emitter.Emit(OpCodes.Ldsflda, fw.GetField()); } else { CodeEmitterLocal obj = eic.Emitter.AllocTempLocal(eic.Caller.DeclaringType.TypeAsLocalOrStackType); eic.Emitter.Emit(OpCodes.Stloc, obj); EmitConsumeUnsafe(eic); eic.Emitter.Emit(OpCodes.Ldloc, obj); eic.Emitter.ReleaseTempLocal(obj); eic.Emitter.Emit(OpCodes.Ldflda, fw.GetField()); } eic.Emitter.Emit(OpCodes.Ldloc, update); eic.Emitter.Emit(OpCodes.Ldloc, expect); eic.Emitter.Emit(OpCodes.Call, AtomicReferenceFieldUpdaterEmitter.MakeCompareExchange(type)); eic.Emitter.Emit(OpCodes.Ldloc, expect); eic.Emitter.Emit(OpCodes.Ceq); eic.Emitter.ReleaseTempLocal(expect); eic.Emitter.ReleaseTempLocal(update); eic.NonLeaf = false; return(true); } } return(false); }
private static bool AtomicReferenceFieldUpdater_newUpdater(EmitIntrinsicContext eic) { return(AtomicReferenceFieldUpdaterEmitter.Emit(eic.Context, eic.Caller.DeclaringType, eic.Emitter, eic.ClassFile, eic.OpcodeIndex, eic.Code, eic.Flags)); }
private static bool AtomicReferenceFieldUpdater_newUpdater(DynamicTypeWrapper.FinishContext context, CodeEmitter ilgen, MethodWrapper method, MethodAnalyzer ma, int opcodeIndex, MethodWrapper caller, ClassFile classFile, Instruction[] code, InstructionFlags[] flags) { return(AtomicReferenceFieldUpdaterEmitter.Emit(context, caller.DeclaringType, ilgen, classFile, opcodeIndex, code, flags)); }