Exemplo n.º 1
0
        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);
        }
Exemplo n.º 2
0
 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));
 }
Exemplo n.º 3
0
 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));
 }