예제 #1
0
        /// <summary>
        ///		Emits 'for' statement on current IL stream.
        /// </summary>
        /// <param name="il">IL generator to be emitted to.</param>
        /// <param name="count">'count' local variable which is <see cref="Int32"/> type and holds maximum loop count.</param>
        /// <param name="bodyEmitter">Delegate to emit for statement body.</param>
        public static void EmitFor(TracingILGenerator il, LocalBuilder count, Action <TracingILGenerator, LocalBuilder> bodyEmitter)
        {
            Contract.Requires(il != null);
            Contract.Requires(count != null);
            Contract.Requires(bodyEmitter != null);

            var i = il.DeclareLocal(typeof(int), "i");

            il.EmitLdc_I4_0();
            il.EmitAnyStloc(i);
            var forCond = il.DefineLabel("FOR_COND");

            il.EmitBr(forCond);
            var body = il.DefineLabel("BODY");

            il.MarkLabel(body);
            bodyEmitter(il, i);
            // increment
            il.EmitAnyLdloc(i);
            il.EmitLdc_I4_1();
            il.EmitAdd();
            il.EmitAnyStloc(i);
            // cond
            il.MarkLabel(forCond);
            il.EmitAnyLdloc(i);
            il.EmitAnyLdloc(count);
            il.EmitBlt(body);
        }
예제 #2
0
        public static void EmitFor(TracingILGenerator il, LocalBuilder count, Action <TracingILGenerator, LocalBuilder> bodyEmitter)
        {
            Contract.Requires(il != null);
            Contract.Requires(count != null);
            Contract.Requires(bodyEmitter != null);
            LocalBuilder local = il.DeclareLocal(typeof(int), "i");

            il.EmitLdc_I4_0();
            il.EmitAnyStloc(local);
            Label target = il.DefineLabel("FOR_COND");

            il.EmitBr(target);
            Label label = il.DefineLabel("BODY");

            il.MarkLabel(label);
            bodyEmitter(il, local);
            il.EmitAnyLdloc(local);
            il.EmitLdc_I4_1();
            il.EmitAdd();
            il.EmitAnyStloc(local);
            il.MarkLabel(target);
            il.EmitAnyLdloc(local);
            il.EmitAnyLdloc(count);
            il.EmitBlt(label);
        }
예제 #3
0
        public static void EmitGetUnpackerItemsCountAsInt32(TracingILGenerator il, int unpackerArgumentIndex, LocalVariableHolder localHolder)
        {
            Contract.Requires(il != null);
            Contract.Requires(unpackerArgumentIndex >= 0);
            il.EmitAnyLdloca(localHolder.RawItemsCount);
            il.EmitInitobj(typeof(long));
            il.BeginExceptionBlock();
            il.EmitAnyLdarg(unpackerArgumentIndex);
            il.EmitGetProperty(_Unpacker.ItemsCount);
            il.EmitAnyStloc(localHolder.RawItemsCount);
            il.BeginCatchBlock(typeof(InvalidOperationException));
            il.EmitAnyCall(SerializationExceptions.NewIsIncorrectStreamMethod);
            il.EmitThrow();
            il.EndExceptionBlock();
            il.EmitAnyLdloc(localHolder.RawItemsCount);
            il.EmitLdc_I8(0x7fffffffL);
            Label target = il.DefineLabel();

            il.EmitBle_S(target);
            il.EmitAnyCall(SerializationExceptions.NewIsTooLargeCollectionMethod);
            il.EmitThrow();
            il.MarkLabel(target);
            il.EmitAnyLdloc(localHolder.RawItemsCount);
            il.EmitConv_I4();
        }
예제 #4
0
        public static void EmitUnpackerEndReadSubtree(TracingILGenerator il, LocalBuilder subtreeUnpacker)
        {
            Contract.Requires(il != null);
            Contract.Requires(subtreeUnpacker != null);

            /*
             *	finally
             *	{
             *		if( subtreeUnpacker != null )
             *		{
             *			subtreeUnpacker.Dispose();
             *		}
             *	}
             */

            il.BeginFinallyBlock();
            il.EmitAnyLdloc(subtreeUnpacker);
            var endIf = il.DefineLabel("END_IF");

            il.EmitBrfalse_S(endIf);
            il.EmitAnyLdloc(subtreeUnpacker);
            il.EmitAnyCall(Metadata._IDisposable.Dispose);
            il.MarkLabel(endIf);
            il.EndExceptionBlock();
        }
예제 #5
0
        private static void EmitDeserializeValueCore(SerializerEmitter emitter, TracingILGenerator il, int unpackerArgumentIndex, LocalBuilder value, Type targetType, SerializingMember?member, string memberName, Label endOfDeserialization, LocalVariableHolder localHolder)
        {
            MethodInfo directReadMethod = _Unpacker.GetDirectReadMethod(value.LocalType);

            if ((directReadMethod != null) && (!member.HasValue || !UnpackHelpers.IsReadOnlyAppendableCollectionMember(member.Value.Member)))
            {
                LocalBuilder isDeserializationSucceeded = localHolder.IsDeserializationSucceeded;
                il.EmitLdc_I4_0();
                il.EmitAnyStloc(isDeserializationSucceeded);
                il.BeginExceptionBlock();
                il.EmitAnyLdarg(unpackerArgumentIndex);
                il.EmitAnyLdloca(value);
                il.EmitAnyCall(directReadMethod);
                il.EmitAnyStloc(isDeserializationSucceeded);
                il.BeginCatchBlock(typeof(MessageTypeException));
                LocalBuilder catchedException = localHolder.GetCatchedException(typeof(MessageTypeException));
                il.EmitAnyStloc(catchedException);
                il.EmitTypeOf(targetType);
                il.EmitLdstr(memberName);
                il.EmitAnyLdloc(catchedException);
                il.EmitAnyCall(SerializationExceptions.NewFailedToDeserializeMemberMethod);
                il.EmitThrow();
                il.EndExceptionBlock();
                Label target = il.DefineLabel("END_IF");
                il.EmitAnyLdloc(isDeserializationSucceeded);
                il.EmitBrtrue_S(target);
                il.EmitAnyCall(SerializationExceptions.NewUnexpectedEndOfStreamMethod);
                il.EmitThrow();
                il.MarkLabel(target);
                if (member.HasValue)
                {
                    EmitNilImplicationForPrimitive(il, member.Value, value, endOfDeserialization);
                }
            }
            else
            {
                EmitGeneralRead(il, unpackerArgumentIndex);
                if (member.HasValue)
                {
                    EmitNilImplication(il, unpackerArgumentIndex, member.Value.Contract.Name, member.Value.Contract.NilImplication, endOfDeserialization, localHolder);
                }
                Label label2 = il.DefineLabel("THEN_IF_COLLECTION");
                Label label3 = il.DefineLabel("END_IF_COLLECTION");
                il.EmitAnyLdarg(unpackerArgumentIndex);
                il.EmitGetProperty(_Unpacker.IsArrayHeader);
                il.EmitAnyLdarg(unpackerArgumentIndex);
                il.EmitGetProperty(_Unpacker.IsMapHeader);
                il.EmitOr();
                il.EmitBrtrue_S(label2);
                EmitUnpackFrom(emitter, il, value, unpackerArgumentIndex);
                il.EmitBr_S(label3);
                LocalBuilder subtreeUnpacker = localHolder.SubtreeUnpacker;
                il.MarkLabel(label2);
                EmitUnpackerBeginReadSubtree(il, unpackerArgumentIndex, subtreeUnpacker);
                EmitUnpackFrom(emitter, il, value, subtreeUnpacker);
                EmitUnpackerEndReadSubtree(il, subtreeUnpacker);
                il.MarkLabel(label3);
            }
        }
예제 #6
0
        /// <summary>
        ///		Emits the serializing value instructions.
        /// </summary>
        /// <param name="emitter">The emitter.</param>
        /// <param name="il">The il generator.</param>
        /// <param name="packerArgumentIndex">Index of the packer argument.</param>
        /// <param name="valueType">Type of the current member value.</param>
        /// <param name="memberName">Name of the current member.</param>
        /// <param name="nilImplication">The nil implication of the current member.</param>
        /// <param name="loadValueEmitter">The delegate which emits case specific value loading instructions.</param>
        /// <param name="localHolder">The <see cref="LocalVariableHolder"/> which holds shared local variable information.</param>
        public static void EmitSerializeValue(SerializerEmitter emitter, TracingILGenerator il, int packerArgumentIndex, Type valueType, string memberName, NilImplication nilImplication, Action <TracingILGenerator> loadValueEmitter, LocalVariableHolder localHolder)
        {
            Contract.Requires(emitter != null);
            Contract.Requires(il != null);
            Contract.Requires(packerArgumentIndex >= 0);
            Contract.Requires(valueType != null);
            Contract.Requires(loadValueEmitter != null);

            /*
             * var serializingValue = LOAD_VALUE;
             * NULL_PROHIBIT_HANDLING
             * GET_SERIALIZER.PackTo( packer, serializingValue );
             */
            var value = localHolder.GetSerializingValue(valueType);

            loadValueEmitter(il);
            il.EmitAnyStloc(value);

            if (memberName != null && nilImplication == NilImplication.Prohibit)
            {
                /*
                 *	if( serializingValue == null )(
                 *	{
                 *		throw SerializationExceptions.NewNullIsProhibited();
                 *	}
                 */

                if (!valueType.IsValueType)
                {
                    il.EmitAnyLdloc(value);
                    var endIf = il.DefineLabel("END_IF");
                    il.EmitBrtrue_S(endIf);
                    il.EmitLdstr(memberName);
                    il.EmitAnyCall(SerializationExceptions.NewNullIsProhibitedMethod);
                    il.EmitThrow();
                    il.MarkLabel(endIf);
                }
                else if (Nullable.GetUnderlyingType(valueType) != null)
                {
                    il.EmitAnyLdloca(value);
                    il.EmitGetProperty(typeof(Nullable <>).MakeGenericType(Nullable.GetUnderlyingType(valueType)).GetProperty("HasValue"));
                    var endIf = il.DefineLabel("END_IF");
                    il.EmitBrtrue_S(endIf);
                    il.EmitLdstr(memberName);
                    il.EmitAnyCall(SerializationExceptions.NewNullIsProhibitedMethod);
                    il.EmitThrow();
                    il.MarkLabel(endIf);
                }
            }

            var serializerGetter = emitter.RegisterSerializer(valueType);

            serializerGetter(il, 0);
            il.EmitAnyLdarg(packerArgumentIndex);
            il.EmitAnyLdloc(value);
            il.EmitAnyCall(typeof(MessagePackSerializer <>).MakeGenericType(valueType).GetMethod("PackTo"));
        }
예제 #7
0
        public static void EmitDeserializeValue(SerializerEmitter emitter, TracingILGenerator il, int unpackerArgumentIndex, LocalBuilder result, SerializingMember member, LocalVariableHolder localHolder)
        {
            LocalBuilder deserializedValue;

            Contract.Requires(emitter != null);
            Contract.Requires(il != null);
            Contract.Requires(unpackerArgumentIndex >= 0);
            Contract.Requires(result != null);
            Label endOfDeserialization = il.DefineLabel("END_OF_DESERIALIZATION");
            bool  flag = false;

            if (member.Member.GetMemberValueType().GetIsValueType() && (Nullable.GetUnderlyingType(member.Member.GetMemberValueType()) == null))
            {
                deserializedValue = localHolder.GetDeserializedValue(typeof(Nullable <>).MakeGenericType(new Type[] { member.Member.GetMemberValueType() }));
                flag = true;
            }
            else
            {
                deserializedValue = localHolder.GetDeserializedValue(member.Member.GetMemberValueType());
            }
            if (deserializedValue.LocalType.GetIsValueType())
            {
                il.EmitAnyLdloca(deserializedValue);
                il.EmitInitobj(deserializedValue.LocalType);
            }
            else
            {
                il.EmitLdnull();
                il.EmitAnyStloc(deserializedValue);
            }
            EmitDeserializeValueCore(emitter, il, unpackerArgumentIndex, deserializedValue, result.LocalType, new SerializingMember?(member), member.Contract.Name, endOfDeserialization, localHolder);
            if (result.LocalType.IsValueType)
            {
                il.EmitAnyLdloca(result);
            }
            else
            {
                il.EmitAnyLdloc(result);
            }
            if (flag)
            {
                il.EmitAnyLdloca(deserializedValue);
                il.EmitGetProperty(typeof(Nullable <>).MakeGenericType(new Type[] { member.Member.GetMemberValueType() }).GetProperty("Value"));
            }
            else
            {
                il.EmitAnyLdloc(deserializedValue);
            }
            EmitStoreValue(il, member.Member);
            il.MarkLabel(endOfDeserialization);
        }
예제 #8
0
        public static void EmitUnpackerEndReadSubtree(TracingILGenerator il, LocalBuilder subtreeUnpacker)
        {
            Contract.Requires(il != null);
            Contract.Requires(subtreeUnpacker != null);
            il.BeginFinallyBlock();
            il.EmitAnyLdloc(subtreeUnpacker);
            Label target = il.DefineLabel("END_IF");

            il.EmitBrfalse_S(target);
            il.EmitAnyLdloc(subtreeUnpacker);
            il.EmitAnyCall(_IDisposable.Dispose);
            il.MarkLabel(target);
            il.EndExceptionBlock();
        }
예제 #9
0
 public static void EmitUnpackFrom(SerializerEmitter emitter, TracingILGenerator il, LocalBuilder result, LocalBuilder unpacker)
 {
     emitter.RegisterSerializer(result.LocalType)(il, 0);
     il.EmitAnyLdloc(unpacker);
     il.EmitAnyCall(_UnpackHelpers.InvokeUnpackFrom_1Method.MakeGenericMethod(new Type[] { result.LocalType }));
     il.EmitAnyStloc(result);
 }
예제 #10
0
 public override void LoadValue(TracingILGenerator il, bool shouldBeAddress)
 {
     this.Evaluate(il);
     il.TraceWriteLine("// Load->: {0}", this);
     if (this.ContextType.ResolveRuntimeType().GetIsValueType() && shouldBeAddress)
     {
         if (this._isLocal)
         {
             il.EmitAnyLdloca(this._index);
         }
         else
         {
             il.EmitAnyLdarga(this._index);
         }
     }
     else
     {
         if (this._isLocal)
         {
             il.EmitAnyLdloc(this._index);
         }
         else
         {
             il.EmitAnyLdarg(this._index);
         }
     }
     il.TraceWriteLine("// ->Load: {0}", this);
 }
예제 #11
0
        private static object CreateDelegate(Type delegateType, Type targetType, ConstructorInfo constructor, Type[] parameterTypes)
        {
            var dynamicMethod =
#if !SILVERLIGHT
                new DynamicMethod("Create" + targetType.Name, targetType, parameterTypes, restrictedSkipVisibility: true);
#else
                new DynamicMethod("Create" + targetType.Name, targetType, parameterTypes);
#endif // !SILVERLIGHT
            var il = new TracingILGenerator(dynamicMethod, NullTextWriter.Instance, isDebuggable: false);
            if (constructor == null)
            {
                // Value type's init.
                il.DeclareLocal(targetType);
                il.EmitAnyLdloca(0);
                il.EmitInitobj(targetType);
                il.EmitAnyLdloc(0);
            }
            else
            {
                for (var i = 0; i < parameterTypes.Length; i++)
                {
                    il.EmitAnyLdarg(i);
                }

                il.EmitNewobj(constructor);
            }

            il.EmitRet();
            return(dynamicMethod.CreateDelegate(delegateType));
        }
예제 #12
0
        public static void EmitConstruction(TracingILGenerator il, LocalBuilder target, Action <TracingILGenerator> initialCountLoadingEmitter)
        {
            Contract.Requires(il != null);
            Contract.Requires(target != null);

            // TODO: For collection, supports .ctor(IEnumerable<> other)

            if (target.LocalType.IsAbstract || target.LocalType.IsInterface)
            {
                throw SerializationExceptions.NewNotSupportedBecauseCannotInstanciateAbstractType(target.LocalType);
            }

            if (target.LocalType.IsArray)
            {
                Contract.Assert(initialCountLoadingEmitter != null);
                initialCountLoadingEmitter(il);
                il.EmitNewarr(target.LocalType.GetElementType());
                il.EmitAnyStloc(target);
                return;
            }

            ConstructorInfo ctor = target.LocalType.GetConstructor(_ctor_Int32_ParameterTypes);

            if (ctor != null && initialCountLoadingEmitter != null && typeof(IEnumerable).IsAssignableFrom(target.LocalType))
            {
                if (target.LocalType.IsValueType)
                {
                    // Same as general method call
                    var capacity = il.DeclareLocal(typeof(int), "capacity");
                    initialCountLoadingEmitter(il);
                    il.EmitAnyStloc(capacity);
                    il.EmitAnyLdloca(target);
                    il.EmitAnyLdloc(capacity);
                    il.EmitCallConstructor(ctor);
                }
                else
                {
                    initialCountLoadingEmitter(il);
                    il.EmitNewobj(ctor);
                    il.EmitAnyStloc(target);
                }
                return;
            }

            if (target.LocalType.IsValueType)
            {
                // ValueType instance has been initialized by the runtime.
                return;
            }

            ctor = target.LocalType.GetConstructor(Type.EmptyTypes);
            if (ctor == null)
            {
                throw SerializationExceptions.NewTargetDoesNotHavePublicDefaultConstructorNorInitialCapacity(target.LocalType);
            }

            il.EmitNewobj(ctor);
            il.EmitAnyStloc(target);
        }
예제 #13
0
        /// <summary>
        /// Emits gets <see cref="Unpacker.ItemsCount"/> with exception handling.
        /// Note that final state is the value is pushed top of the evaluation stack.
        /// </summary>
        /// <param name="il">IL generator.</param>
        /// <param name="unpackerArgumentIndex">Argument index of the unpacker.</param>
        /// <param name="localHolder">The <see cref="LocalVariableHolder"/> which holds shared local variable information.</param>
        public static void EmitGetUnpackerItemsCountAsInt32(TracingILGenerator il, int unpackerArgumentIndex, LocalVariableHolder localHolder)
        {
            Contract.Requires(il != null);
            Contract.Requires(unpackerArgumentIndex >= 0);

            /*
             *	long rawItemsCount;
             *	try
             *	{
             *		rawItemsCount = unpacker.ItemsCount;
             *	}
             *	catch ( InvalidOperationException ex )
             *	{
             *		throw SerializationExceptions.NewIsIncorrectStream( ex );
             *	}
             *
             *	if( rawItemsCount > Int32.MaxValue )
             *	{
             *		throw SerializationException.NewIsTooLargeCollection();
             *	}
             *
             *	... unchecked( ( int )rawItemsCount );
             */
            il.EmitAnyLdloca(localHolder.RawItemsCount);
            il.EmitInitobj(typeof(long));
            il.BeginExceptionBlock();
            il.EmitAnyLdarg(unpackerArgumentIndex);
            il.EmitGetProperty(Metadata._Unpacker.ItemsCount);
            il.EmitAnyStloc(localHolder.RawItemsCount);
            il.BeginCatchBlock(typeof(InvalidOperationException));
            il.EmitAnyCall(SerializationExceptions.NewIsIncorrectStreamMethod);
            il.EmitThrow();
            il.EndExceptionBlock();

            il.EmitAnyLdloc(localHolder.RawItemsCount);
            il.EmitLdc_I8(Int32.MaxValue);
            var endIf = il.DefineLabel();

            il.EmitBle_S(endIf);
            il.EmitAnyCall(SerializationExceptions.NewIsTooLargeCollectionMethod);
            il.EmitThrow();
            il.MarkLabel(endIf);
            il.EmitAnyLdloc(localHolder.RawItemsCount);
            il.EmitConv_I4();
        }
예제 #14
0
        /// <summary>
        ///		Emits unpacking method with flavor specific getter.
        /// </summary>
        /// <param name="emitter">SerializerEmitter which knows the emittion flavor.</param>
        /// <param name="il">The il generator.</param>
        /// <param name="result">A variable wich stores unpacked result.</param>
        /// <param name="unpacker">The local variable which stores current Unpacker.</param>
        public static void EmitUnpackFrom(SerializerEmitter emitter, TracingILGenerator il, LocalBuilder result, LocalBuilder unpacker)
        {
            var serializerGetter = emitter.RegisterSerializer(result.LocalType);

            serializerGetter(il, 0);
            il.EmitAnyLdloc(unpacker);
            il.EmitAnyCall(Metadata._UnpackHelpers.InvokeUnpackFrom_1Method.MakeGenericMethod(result.LocalType));
            il.EmitAnyStloc(result);
        }
        private static void EmitWrapperInvocation(ServiceInvokerEmitter emitter, TracingILGenerator il, LocalBuilder service, MethodInfo targetOperation, LocalBuilder[] unpackedArguments)
        {
            /*
             * returnValue = Task.Factory.StartNew( this.PrivateInvokeCore( state as Tuple<...> ), new Tuple<...>(...) );
             */
            var itemTypes  = Enumerable.Repeat(service, 1).Concat(unpackedArguments).Select(item => item.LocalType).ToArray();
            var tupleTypes = TupleItems.CreateTupleTypeList(itemTypes);

            EmitPrivateInvoke(emitter.GetPrivateInvokeMethodILGenerator(targetOperation.ReturnType), targetOperation, tupleTypes, itemTypes);

            il.EmitGetProperty(_taskFactoryProperty);

            // new DELEGATE( PrivateInvoke ) ->new DELGATE( null, funcof( PrivateInvoke ) )
            il.EmitLdarg_0();
            il.EmitLdftn(emitter.PrivateInvokeMethod);
            il.EmitNewobj(
                targetOperation.ReturnType == typeof(void)
                                ? typeof(Action <object>).GetConstructor(_delegateConstructorParameterTypes)
                                : typeof(Func <,>).MakeGenericType(typeof(object), targetOperation.ReturnType).GetConstructor(_delegateConstructorParameterTypes)
                );

            il.EmitAnyLdloc(service);

            foreach (var item in unpackedArguments)
            {
                il.EmitAnyLdloc(item);
            }

            foreach (var tupleType in tupleTypes)
            {
                il.EmitNewobj(tupleType.GetConstructors().Single());
            }

            if (targetOperation.ReturnType == typeof(void))
            {
                il.EmitAnyCall(_taskFactoryStartNew_Action_1_Object_Object);
            }
            else
            {
                il.EmitAnyCall(_taskFactoryStartNew_Func_1_Object_T_Object.MakeGenericMethod(targetOperation.ReturnType));
            }
        }
예제 #16
0
 private static void EmitLoadTarget(Type targetType, TracingILGenerator il, LocalBuilder local)
 {
     if (targetType.IsValueType)
     {
         il.EmitAnyLdloca(local);
     }
     else
     {
         il.EmitAnyLdloc(local);
     }
 }
예제 #17
0
        public static void EmitSerializeValue(SerializerEmitter emitter, TracingILGenerator il, int packerArgumentIndex, Type valueType, string memberName, NilImplication nilImplication, Action <TracingILGenerator> loadValueEmitter, LocalVariableHolder localHolder)
        {
            Contract.Requires(emitter != null);
            Contract.Requires(il != null);
            Contract.Requires(packerArgumentIndex >= 0);
            Contract.Requires(valueType != null);
            Contract.Requires(loadValueEmitter != null);
            LocalBuilder serializingValue = localHolder.GetSerializingValue(valueType);

            loadValueEmitter(il);
            il.EmitAnyStloc(serializingValue);
            if ((memberName != null) && (nilImplication == NilImplication.Prohibit))
            {
                Label label;
                if (!valueType.IsValueType)
                {
                    il.EmitAnyLdloc(serializingValue);
                    label = il.DefineLabel("END_IF");
                    il.EmitBrtrue_S(label);
                    il.EmitLdstr(memberName);
                    il.EmitAnyCall(SerializationExceptions.NewNullIsProhibitedMethod);
                    il.EmitThrow();
                    il.MarkLabel(label);
                }
                else if (Nullable.GetUnderlyingType(valueType) != null)
                {
                    il.EmitAnyLdloca(serializingValue);
                    il.EmitGetProperty(typeof(Nullable <>).MakeGenericType(new Type[] { Nullable.GetUnderlyingType(valueType) }).GetProperty("HasValue"));
                    label = il.DefineLabel("END_IF");
                    il.EmitBrtrue_S(label);
                    il.EmitLdstr(memberName);
                    il.EmitAnyCall(SerializationExceptions.NewNullIsProhibitedMethod);
                    il.EmitThrow();
                    il.MarkLabel(label);
                }
            }
            emitter.RegisterSerializer(valueType)(il, 0);
            il.EmitAnyLdarg(packerArgumentIndex);
            il.EmitAnyLdloc(serializingValue);
            il.EmitAnyCall(typeof(MessagePackSerializer <>).MakeGenericType(new Type[] { valueType }).GetMethod("PackTo"));
        }
예제 #18
0
        private static void CreateUnpacking(SerializerEmitter emitter)
        {
            TracingILGenerator unpackFromMethodILGenerator = emitter.GetUnpackFromMethodILGenerator();

            try
            {
                LocalBuilder local    = unpackFromMethodILGenerator.DeclareLocal(typeof(MessagePackObject?), "mayBeNullData");
                LocalBuilder builder2 = unpackFromMethodILGenerator.DeclareLocal(typeof(MessagePackObject), "data");
                LocalBuilder builder3 = unpackFromMethodILGenerator.DeclareLocal(typeof(T), "result");
                LocalBuilder result   = unpackFromMethodILGenerator.DeclareLocal(NullableMessagePackSerializer <T> ._nullableTValueProperty.PropertyType, "value");
                Label        target   = unpackFromMethodILGenerator.DefineLabel("END_IF");
                Label        label2   = unpackFromMethodILGenerator.DefineLabel("END_METHOD");
                unpackFromMethodILGenerator.EmitAnyLdarg(1);
                unpackFromMethodILGenerator.EmitGetProperty(NullableMessagePackSerializer.UnpackerDataProperty);
                unpackFromMethodILGenerator.EmitAnyStloc(local);
                unpackFromMethodILGenerator.EmitAnyLdloca(local);
                unpackFromMethodILGenerator.EmitGetProperty(NullableMessagePackSerializer.Nullable_MessagePackObject_ValueProperty);
                unpackFromMethodILGenerator.EmitAnyStloc(builder2);
                unpackFromMethodILGenerator.EmitAnyLdloca(builder2);
                unpackFromMethodILGenerator.EmitGetProperty(NullableMessagePackSerializer.MessagePackObject_IsNilProperty);
                unpackFromMethodILGenerator.EmitBrfalse_S(target);
                unpackFromMethodILGenerator.EmitAnyLdloca(builder3);
                unpackFromMethodILGenerator.EmitInitobj(builder3.LocalType);
                unpackFromMethodILGenerator.EmitBr_S(label2);
                unpackFromMethodILGenerator.MarkLabel(target);
                Emittion.EmitUnpackFrom(emitter, unpackFromMethodILGenerator, result, 1);
                unpackFromMethodILGenerator.EmitAnyLdloc(result);
                unpackFromMethodILGenerator.EmitAnyCall(NullableMessagePackSerializer <T> ._nullableTImplicitOperator);
                unpackFromMethodILGenerator.EmitAnyStloc(builder3);
                unpackFromMethodILGenerator.MarkLabel(label2);
                unpackFromMethodILGenerator.EmitAnyLdloc(builder3);
                unpackFromMethodILGenerator.EmitRet();
            }
            finally
            {
                unpackFromMethodILGenerator.FlushTrace();
                emitter.FlushTrace();
            }
        }
        private static void EmitUnpackMembersFromArray(SerializerEmitter emitter, TracingILGenerator unpackerIL, SerializingMember[] entries, LocalBuilder result, LocalVariableHolder localHolder)
        {
            LocalBuilder itemsCount = localHolder.ItemsCount;
            LocalBuilder local      = unpackerIL.DeclareLocal(typeof(int), "unpacked");

            Emittion.EmitGetUnpackerItemsCountAsInt32(unpackerIL, 1, localHolder);
            unpackerIL.EmitAnyStloc(itemsCount);
            for (int i = 0; i < entries.Length; i++)
            {
                Label endOfDeserialization = unpackerIL.DefineLabel("END_IF");
                Label target = unpackerIL.DefineLabel("ELSE");
                unpackerIL.EmitAnyLdloc(local);
                unpackerIL.EmitAnyLdloc(itemsCount);
                unpackerIL.EmitBlt(target);
                if (entries[i].Member != null)
                {
                    Emittion.EmitNilImplication(unpackerIL, 1, entries[i].Contract.Name, entries[i].Contract.NilImplication, endOfDeserialization, localHolder);
                }
                unpackerIL.EmitBr(endOfDeserialization);
                unpackerIL.MarkLabel(target);
                if (entries[i].Member == null)
                {
                    Emittion.EmitGeneralRead(unpackerIL, 1);
                }
                else if (UnpackHelpers.IsReadOnlyAppendableCollectionMember(entries[i].Member))
                {
                    Emittion.EmitDeserializeCollectionValue(emitter, unpackerIL, 1, result, entries[i].Member, entries[i].Member.GetMemberValueType(), entries[i].Contract.NilImplication, localHolder);
                }
                else
                {
                    Emittion.EmitDeserializeValue(emitter, unpackerIL, 1, result, entries[i], localHolder);
                }
                unpackerIL.EmitAnyLdloc(local);
                unpackerIL.EmitLdc_I4_1();
                unpackerIL.EmitAdd();
                unpackerIL.EmitAnyStloc(local);
                unpackerIL.MarkLabel(endOfDeserialization);
            }
        }
        private static void EmitUnpackMembersFromMap(SerializerEmitter emitter, TracingILGenerator unpackerIL, SerializingMember[] entries, LocalBuilder result, LocalVariableHolder localHolder)
        {
            Label label  = unpackerIL.DefineLabel("BEGIN_LOOP");
            Label target = unpackerIL.DefineLabel("END_LOOP");

            unpackerIL.MarkLabel(label);
            LocalBuilder memberName = localHolder.MemberName;

            unpackerIL.EmitAnyLdarg(1);
            unpackerIL.EmitAnyLdloca(memberName);
            unpackerIL.EmitAnyCall(_Unpacker.ReadString);
            unpackerIL.EmitBrfalse(target);
            LocalBuilder unpackedData      = localHolder.UnpackedData;
            LocalBuilder unpackedDataValue = localHolder.UnpackedDataValue;

            for (int i = 0; i < entries.Length; i++)
            {
                if (entries[i].Contract.Name != null)
                {
                    unpackerIL.EmitAnyLdloc(memberName);
                    unpackerIL.EmitLdstr(entries[i].Contract.Name);
                    unpackerIL.EmitAnyCall(_String.op_Equality);
                    Label label3 = unpackerIL.DefineLabel("END_IF_MEMBER_" + i);
                    unpackerIL.EmitBrfalse(label3);
                    if (entries[i].Member == null)
                    {
                        Emittion.EmitGeneralRead(unpackerIL, 1);
                    }
                    else if (UnpackHelpers.IsReadOnlyAppendableCollectionMember(entries[i].Member))
                    {
                        Emittion.EmitDeserializeCollectionValue(emitter, unpackerIL, 1, result, entries[i].Member, entries[i].Member.GetMemberValueType(), entries[i].Contract.NilImplication, localHolder);
                    }
                    else
                    {
                        Emittion.EmitDeserializeValue(emitter, unpackerIL, 1, result, entries[i], localHolder);
                    }
                    unpackerIL.EmitBr(label);
                    unpackerIL.MarkLabel(label3);
                }
            }
            unpackerIL.EmitAnyLdarg(1);
            unpackerIL.EmitCallvirt(_Unpacker.Read);
            unpackerIL.EmitPop();
            unpackerIL.EmitBr(label);
            unpackerIL.MarkLabel(target);
        }
예제 #21
0
 public static void EmitConstruction(TracingILGenerator il, LocalBuilder target, Action <TracingILGenerator> initialCountLoadingEmitter)
 {
     Contract.Requires(il != null);
     Contract.Requires(target != null);
     if (target.LocalType.IsArray)
     {
         Contract.Assert(initialCountLoadingEmitter != null);
         initialCountLoadingEmitter(il);
         il.EmitNewarr(target.LocalType.GetElementType());
         il.EmitAnyStloc(target);
     }
     else
     {
         ConstructorInfo constructor = target.LocalType.GetConstructor(_ctor_Int32_ParameterTypes);
         if (((constructor != null) && (initialCountLoadingEmitter != null)) && typeof(IEnumerable).IsAssignableFrom(target.LocalType))
         {
             if (target.LocalType.IsValueType)
             {
                 LocalBuilder local = il.DeclareLocal(typeof(int), "capacity");
                 initialCountLoadingEmitter(il);
                 il.EmitAnyStloc(local);
                 il.EmitAnyLdloca(target);
                 il.EmitAnyLdloc(local);
                 il.EmitCallConstructor(constructor);
             }
             else
             {
                 initialCountLoadingEmitter(il);
                 il.EmitNewobj(constructor);
                 il.EmitAnyStloc(target);
             }
         }
         else if (!target.LocalType.IsValueType)
         {
             constructor = target.LocalType.GetConstructor(Type.EmptyTypes);
             if (constructor == null)
             {
                 throw SerializationExceptions.NewTargetDoesNotHavePublicDefaultConstructorNorInitialCapacity(target.LocalType);
             }
             il.EmitNewobj(constructor);
             il.EmitAnyStloc(target);
         }
     }
 }
        private static void CreateArrayUnpackFrom(Type targetType, SerializerEmitter emitter, CollectionTraits traits)
        {
            Action <TracingILGenerator> initialCountLoadingEmitter  = null;
            TracingILGenerator          unpackFromMethodILGenerator = emitter.GetUnpackFromMethodILGenerator();
            LocalVariableHolder         localHolder = new LocalVariableHolder(unpackFromMethodILGenerator);

            try
            {
                LocalBuilder collection;
                if (targetType.IsInterface || targetType.IsAbstract)
                {
                    unpackFromMethodILGenerator.EmitTypeOf(targetType);
                    unpackFromMethodILGenerator.EmitAnyCall(SerializationExceptions.NewNotSupportedBecauseCannotInstanciateAbstractTypeMethod);
                    unpackFromMethodILGenerator.EmitThrow();
                }
                else
                {
                    unpackFromMethodILGenerator.EmitAnyLdarg(1);
                    unpackFromMethodILGenerator.EmitGetProperty(_Unpacker.IsArrayHeader);
                    Label target = unpackFromMethodILGenerator.DefineLabel("END_IF");
                    unpackFromMethodILGenerator.EmitBrtrue_S(target);
                    unpackFromMethodILGenerator.EmitAnyCall(SerializationExceptions.NewIsNotArrayHeaderMethod);
                    unpackFromMethodILGenerator.EmitThrow();
                    unpackFromMethodILGenerator.MarkLabel(target);
                    collection = localHolder.GetDeserializingCollection(targetType);
                    if (initialCountLoadingEmitter == null)
                    {
                        initialCountLoadingEmitter = il0 => Emittion.EmitGetUnpackerItemsCountAsInt32(il0, 1, localHolder);
                    }
                    Emittion.EmitConstruction(unpackFromMethodILGenerator, collection, initialCountLoadingEmitter);
                    EmitInvokeArrayUnpackToHelper(targetType, emitter, traits, unpackFromMethodILGenerator, 1, il0 => il0.EmitAnyLdloc(collection));
                    unpackFromMethodILGenerator.EmitAnyLdloc(collection);
                    unpackFromMethodILGenerator.EmitRet();
                }
            }
            finally
            {
                unpackFromMethodILGenerator.FlushTrace();
            }
        }
예제 #23
0
 private static void EmitCompareNull(TracingILGenerator il, LocalBuilder value, Label targetIfNotNull)
 {
     if (value.LocalType == typeof(MessagePackObject))
     {
         il.EmitAnyLdloca(value);
         il.EmitGetProperty(_MessagePackObject.IsNil);
         il.EmitBrfalse_S(targetIfNotNull);
     }
     else if (value.LocalType.GetIsValueType())
     {
         Contract.Assert(Nullable.GetUnderlyingType(value.LocalType) != null, value.LocalType.FullName);
         il.EmitAnyLdloca(value);
         il.EmitGetProperty(value.LocalType.GetProperty("HasValue"));
         il.EmitBrtrue_S(targetIfNotNull);
     }
     else
     {
         il.EmitAnyLdloc(value);
         il.EmitLdnull();
         il.EmitBne_Un_S(targetIfNotNull);
     }
 }
        /// <summary>
        ///		Emits helper function to avoid lexical closure emitting.
        /// </summary>
        /// <param name="il"><see cref="TracingILGenerator"/>.</param>
        /// <param name="targetOperation"><see cref="MethodInfo"/> of the method to be invoked.</param>
        /// <param name="tupleTypes">The array of <see cref="Type"/> of nested tuples. The outermost is the first, innermost is the last.</param>
        /// <param name="itemTypes">The array of <see cref="Type"/> of flatten tuple items.</param>
        private static void EmitPrivateInvoke(TracingILGenerator il, MethodInfo targetOperation, IList <Type> tupleTypes, Type[] itemTypes)
        {
            /*
             * private void/T PrivateInvoke( object state )
             * {
             *		T result;
             *		Dispatcher.BeginOperation();
             *		try
             *		{
             *			var tuple = state as Tuple<...>;
             *			result =
             *				tuple.Item1.Target(
             *					tuple.Item2,
             *						:
             *					tuple.Rest.Rest....ItemN
             *				);
             *		}
             *		catch( TheradAbortException )
             *		{
             *			Dispatcher.HandleThreadAbortException( ex );
             *		}
             *		finally
             *		{
             *			Dispatcher.EndOperation();
             *		}
             *
             *		return result;
             * }
             */
            var tuple  = il.DeclareLocal(tupleTypes.First(), "tuple");
            var result = targetOperation.ReturnType == typeof(void) ? null : il.DeclareLocal(targetOperation.ReturnType, "result");

            il.EmitAnyLdarg(0);
            il.EmitCall(_dispatcherBeginOperationMethod);
            il.BeginExceptionBlock();

            il.EmitAnyLdarg(1);
            il.EmitIsinst(tupleTypes.First());
            il.EmitAnyStloc(tuple);

            int depth = -1;

            for (int i = 0; i < itemTypes.Length; i++)
            {
                if (i % 7 == 0)
                {
                    depth++;
                }

                il.EmitAnyLdloc(tuple);

                for (int j = 0; j < depth; j++)
                {
                    // .TRest.TRest ...
                    var rest = tupleTypes[j].GetProperty("Rest");
                    il.EmitGetProperty(rest);
                }

                var itemn = tupleTypes[depth].GetProperty("Item" + ((i % 7) + 1));
                il.EmitGetProperty(itemn);
            }

            il.EmitAnyCall(targetOperation);
            if (targetOperation.ReturnType != typeof(void))
            {
                il.EmitAnyStloc(result);
            }

            il.BeginCatchBlock(typeof(ThreadAbortException));
            var ex = il.DeclareLocal(typeof(ThreadAbortException), "ex");

            il.EmitAnyStloc(ex);
            il.EmitAnyLdarg(0);
            il.EmitAnyLdloc(ex);
            il.EmitCall(_dispatcherHandleThreadAbortExceptionMethod);

            il.BeginFinallyBlock();
            il.EmitAnyLdarg(0);
            il.EmitCall(_dispatcherEndOperationMethod);
            il.EndExceptionBlock();

            if (targetOperation.ReturnType != typeof(void))
            {
                il.EmitAnyLdloc(result);
            }

            il.EmitRet();
        }
예제 #25
0
        /// <summary>
        /// Emits the deserialize value.
        /// </summary>
        /// <param name="emitter">The emitter.</param>
        /// <param name="il">The il generator.</param>
        /// <param name="unpackerArgumentIndex">Index of the unpacker argument.</param>
        /// <param name="result">The result local variable which represents the result of deserialization.</param>
        /// <param name="member">The metadata for nil implication. Specify <c>null</c> if nil implication is not needed.</param>
        /// <param name="localHolder">The <see cref="LocalVariableHolder"/> which holds shared local variable information.</param>
        public static void EmitDeserializeValue(SerializerEmitter emitter, TracingILGenerator il, int unpackerArgumentIndex, LocalBuilder result, SerializingMember member, LocalVariableHolder localHolder)
        {
            Contract.Requires(emitter != null);
            Contract.Requires(il != null);
            Contract.Requires(unpackerArgumentIndex >= 0);
            Contract.Requires(result != null);

            var endOfDeserialization = il.DefineLabel("END_OF_DESERIALIZATION");

            /*
             *
             * if( !unpacker.IsArrayHeader && !unpacker.IsMapHeader )
             * {
             *		valueN = GET_SERIALIZER.UnpackFrom( unpacker );
             * }
             * else
             * {
             *		using( var subtreeUnpacker = unpacker.ReadSubtree )
             *		{
             *			valueN = GET_SERIALIZER.UnpackFrom( unpacker );
             *		}
             * }
             *
             * isValueNUnpacked = true;
             * END_OF_DESERIALIZATION:
             */
            LocalBuilder value;
            bool         useDummyNullableValue = false;

            if (member.Member.GetMemberValueType().GetIsValueType() &&
                Nullable.GetUnderlyingType(member.Member.GetMemberValueType()) == null)
            {
                // Use temporary nullable value for nil implication.
                value = localHolder.GetDeserializedValue(
                    typeof(Nullable <>).MakeGenericType(member.Member.GetMemberValueType()));
                useDummyNullableValue = true;
            }
            else
            {
                value = localHolder.GetDeserializedValue(member.Member.GetMemberValueType());
            }

            if (value.LocalType.GetIsValueType())
            {
                il.EmitAnyLdloca(value);
                il.EmitInitobj(value.LocalType);
            }
            else
            {
                il.EmitLdnull();
                il.EmitAnyStloc(value);
            }

            EmitDeserializeValueCore(emitter, il, unpackerArgumentIndex, value, result.LocalType, member, member.Contract.Name, endOfDeserialization, localHolder);

            if (result.LocalType.IsValueType)
            {
                il.EmitAnyLdloca(result);
            }
            else
            {
                il.EmitAnyLdloc(result);
            }

            if (useDummyNullableValue)
            {
                il.EmitAnyLdloca(value);
                il.EmitGetProperty(typeof(Nullable <>).MakeGenericType(member.Member.GetMemberValueType()).GetProperty("Value"));
            }
            else
            {
                il.EmitAnyLdloc(value);
            }

            EmitStoreValue(il, member.Member);

            il.MarkLabel(endOfDeserialization);
        }
예제 #26
0
        public static void EmitDeserializeCollectionValue(SerializerEmitter emitter, TracingILGenerator il, int unpackerArgumentIndex, LocalBuilder target, MemberInfo member, Type memberType, NilImplication nilImplication, LocalVariableHolder localHolder)
        {
            LocalBuilder unpackedData;
            LocalBuilder unpackedDataValue;
            Label        label2;
            Label        label3;

            Contract.Requires(emitter != null);
            Contract.Requires(il != null);
            Contract.Requires(unpackerArgumentIndex >= 0);
            Contract.Requires(target != null);
            Contract.Requires(member != null);
            Contract.Requires(memberType != null);
            Contract.Requires(localHolder != null);
            Label label = il.DefineLabel("END_OF_DESERIALIZATION");

            EmitGeneralRead(il, unpackerArgumentIndex);
            switch (nilImplication)
            {
            case NilImplication.MemberDefault:
                il.EmitAnyLdarg(unpackerArgumentIndex);
                il.EmitGetProperty(_Unpacker.Data);
                unpackedData = localHolder.UnpackedData;
                il.EmitAnyStloc(unpackedData);
                il.EmitAnyLdloca(unpackedData);
                il.EmitGetProperty(_Nullable <MessagePackObject> .Value);
                unpackedDataValue = localHolder.UnpackedDataValue;
                il.EmitAnyStloc(unpackedDataValue);
                il.EmitAnyLdloca(unpackedDataValue);
                il.EmitGetProperty(_MessagePackObject.IsNil);
                il.EmitBrtrue(label);
                goto Label_01B5;

            case NilImplication.Null:
            case NilImplication.Prohibit:
                il.EmitAnyLdarg(unpackerArgumentIndex);
                il.EmitGetProperty(_Unpacker.Data);
                unpackedData = localHolder.UnpackedData;
                il.EmitAnyStloc(unpackedData);
                il.EmitAnyLdloca(unpackedData);
                il.EmitGetProperty(_Nullable <MessagePackObject> .Value);
                unpackedDataValue = localHolder.UnpackedDataValue;
                il.EmitAnyStloc(unpackedDataValue);
                il.EmitAnyLdloca(unpackedDataValue);
                il.EmitGetProperty(_MessagePackObject.IsNil);
                label2 = il.DefineLabel("END_IF0");
                il.EmitBrfalse_S(label2);
                il.EmitLdstr(member.Name);
                if (nilImplication != NilImplication.Prohibit)
                {
                    il.EmitAnyCall(SerializationExceptions.NewReadOnlyMemberItemsMustNotBeNullMethod);
                    break;
                }
                il.EmitAnyCall(SerializationExceptions.NewNullIsProhibitedMethod);
                break;

            default:
                goto Label_01B5;
            }
            il.EmitThrow();
            il.MarkLabel(label2);
Label_01B5:
            label3 = il.DefineLabel("THEN");
            Action <TracingILGenerator, int> action = emitter.RegisterSerializer(memberType);

            il.EmitAnyLdarg(unpackerArgumentIndex);
            il.EmitGetProperty(_Unpacker.IsArrayHeader);
            il.EmitBrtrue_S(label3);
            il.EmitAnyLdarg(unpackerArgumentIndex);
            il.EmitGetProperty(_Unpacker.IsMapHeader);
            il.EmitBrtrue_S(label3);
            il.EmitLdstr(member.Name);
            il.EmitAnyCall(SerializationExceptions.NewStreamDoesNotContainCollectionForMemberMethod);
            il.EmitThrow();
            LocalBuilder subtreeUnpacker = localHolder.SubtreeUnpacker;

            il.MarkLabel(label3);
            EmitUnpackerBeginReadSubtree(il, unpackerArgumentIndex, subtreeUnpacker);
            action(il, 0);
            il.EmitAnyLdloc(subtreeUnpacker);
            il.EmitAnyLdloc(target);
            EmitLoadValue(il, member);
            il.EmitAnyCall(typeof(MessagePackSerializer <>).MakeGenericType(new Type[] { memberType }).GetMethod("UnpackTo", new Type[] { typeof(Unpacker), memberType }));
            EmitUnpackerEndReadSubtree(il, subtreeUnpacker);
            il.MarkLabel(label);
        }
예제 #27
0
        /// <summary>
        /// Emits the deserialize value.
        /// </summary>
        /// <param name="emitter">The emitter.</param>
        /// <param name="il">The il generator.</param>
        /// <param name="unpackerArgumentIndex">Index of the unpacker argument.</param>
        /// <param name="value">The value local variable which stores unpacked value.</param>
        /// <param name="targetType">The type of deserialzing type.</param>
        /// <param name="member">The metadata for nil implication. Specify <c>null</c> if nil implication is not needed.</param>
        /// <param name="memberName">The name of the member.</param>
        /// <param name="endOfDeserialization">The end of deserialization label for nil implication.</param>
        /// <param name="localHolder">The <see cref="LocalVariableHolder"/> which holds shared local variable information.</param>
        private static void EmitDeserializeValueCore(SerializerEmitter emitter, TracingILGenerator il, int unpackerArgumentIndex, LocalBuilder value, Type targetType, SerializingMember?member, string memberName, Label endOfDeserialization, LocalVariableHolder localHolder)
        {
            var directUnpacking = Metadata._Unpacker.GetDirectReadMethod(value.LocalType);

            if (directUnpacking != null && (member == null || !UnpackHelpers.IsReadOnlyAppendableCollectionMember(member.Value.Member)))
            {
                var isSuccess = localHolder.IsDeserializationSucceeded;
                il.EmitLdc_I4_0();
                il.EmitAnyStloc(isSuccess);

                il.BeginExceptionBlock();
                il.EmitAnyLdarg(unpackerArgumentIndex);
                il.EmitAnyLdloca(value);
                il.EmitAnyCall(directUnpacking);
                il.EmitAnyStloc(isSuccess);
                il.BeginCatchBlock(typeof(MessageTypeException));
                var ex = localHolder.GetCatchedException(typeof(MessageTypeException));
                il.EmitAnyStloc(ex);
                il.EmitTypeOf(targetType);
                il.EmitLdstr(memberName);
                il.EmitAnyLdloc(ex);
                il.EmitAnyCall(SerializationExceptions.NewFailedToDeserializeMemberMethod);
                il.EmitThrow();
                il.EndExceptionBlock();
                var endIf0 = il.DefineLabel("END_IF");
                il.EmitAnyLdloc(isSuccess);
                il.EmitBrtrue_S(endIf0);
                il.EmitAnyCall(SerializationExceptions.NewUnexpectedEndOfStreamMethod);
                il.EmitThrow();
                il.MarkLabel(endIf0);
                if (member != null)
                {
                    // If null, nil implication is NOT needed.
                    EmitNilImplicationForPrimitive(il, member.Value, value, endOfDeserialization);
                }
            }
            else
            {
                EmitGeneralRead(il, unpackerArgumentIndex);
                if (member != null)
                {
                    // If null, nil implication is NOT needed.
                    EmitNilImplication(
                        il,
                        unpackerArgumentIndex,
                        member.Value.Contract.Name,
                        member.Value.Contract.NilImplication,
                        endOfDeserialization,
                        localHolder
                        );
                }

                var thenIffCollection = il.DefineLabel("THEN_IF_COLLECTION");
                var endIfCollection   = il.DefineLabel("END_IF_COLLECTION");

                /*
                 *	if( !unpacker.IsArrayHeader && !unpacker.IsMapHeader )
                 *	{
                 *		value = GET_SERIALIZER().UnpackFrom( unpacker );
                 *	}
                 *	else
                 *	{
                 *		using( var subtreeUnpacker = unpacker.ReadSubtree() )
                 *		{
                 *			value = GET_SERIALIZER().UnpackFrom( subtreeUnpacker );
                 *		}
                 *	}
                 */

                il.EmitAnyLdarg(unpackerArgumentIndex);
                il.EmitGetProperty(Metadata._Unpacker.IsArrayHeader);
                il.EmitAnyLdarg(unpackerArgumentIndex);
                il.EmitGetProperty(Metadata._Unpacker.IsMapHeader);
                il.EmitOr();
                il.EmitBrtrue_S(thenIffCollection);
                EmitUnpackFrom(emitter, il, value, unpackerArgumentIndex);
                il.EmitBr_S(endIfCollection);
                var subtreeUnpacker = localHolder.SubtreeUnpacker;
                il.MarkLabel(thenIffCollection);
                EmitUnpackerBeginReadSubtree(il, unpackerArgumentIndex, subtreeUnpacker);
                EmitUnpackFrom(emitter, il, value, subtreeUnpacker);
                EmitUnpackerEndReadSubtree(il, subtreeUnpacker);
                il.MarkLabel(endIfCollection);
            }
        }
예제 #28
0
        /// <summary>
        ///		Emits 'foreach' statement on the IL stream.
        /// </summary>
        /// <param name="il">IL generator to be emitted to.</param>
        /// <param name="traits"><see cref="CollectionTraits"/> which contains traits of the iterating collection.</param>
        /// <param name="collection">'collection' argument index.</param>
        /// <param name="bodyEmitter">Delegate to emit body statement.</param>
        public static void EmitForEach(TracingILGenerator il, CollectionTraits traits, LocalBuilder collection, Action <TracingILGenerator, Action> bodyEmitter)
        {
            Contract.Requires(il != null);
            Contract.Requires(collection != null);
            Contract.Requires(bodyEmitter != null);

            var enumerator = il.DeclareLocal(traits.GetEnumeratorMethod.ReturnType, "enumerator");

            // gets enumerator
            if (collection.LocalType.IsValueType)
            {
                il.EmitAnyLdloca(collection);
            }
            else
            {
                il.EmitAnyLdloc(collection);
            }

            il.EmitAnyCall(traits.GetEnumeratorMethod);
            il.EmitAnyStloc(enumerator);

            if (typeof(IDisposable).IsAssignableFrom(traits.GetEnumeratorMethod.ReturnType))
            {
                il.BeginExceptionBlock();
            }

            var startLoop = il.DefineLabel("START_LOOP");

            il.MarkLabel(startLoop);
            var          endLoop         = il.DefineLabel("END_LOOP");
            var          enumeratorType  = traits.GetEnumeratorMethod.ReturnType;
            MethodInfo   moveNextMethod  = enumeratorType.GetMethod("MoveNext", Type.EmptyTypes);
            PropertyInfo currentProperty = traits.GetEnumeratorMethod.ReturnType.GetProperty("Current");

            if (moveNextMethod == null)
            {
                moveNextMethod = Metadata._IEnumerator.MoveNext;
            }

            if (currentProperty == null)
            {
                if (enumeratorType == typeof(IDictionaryEnumerator))
                {
                    currentProperty = Metadata._IDictionaryEnumerator.Current;
                }
                else if (enumeratorType.IsInterface)
                {
                    if (enumeratorType.IsGenericType && enumeratorType.GetGenericTypeDefinition() == typeof(IEnumerator <>))
                    {
                        currentProperty = typeof(IEnumerator <>).MakeGenericType(traits.ElementType).GetProperty("Current");
                    }
                    else
                    {
                        currentProperty = Metadata._IEnumerator.Current;
                    }
                }
            }

            Contract.Assert(currentProperty != null, enumeratorType.ToString());

            // iterates
            if (traits.GetEnumeratorMethod.ReturnType.IsValueType)
            {
                il.EmitAnyLdloca(enumerator);
            }
            else
            {
                il.EmitAnyLdloc(enumerator);
            }

            il.EmitAnyCall(moveNextMethod);
            il.EmitBrfalse(endLoop);

            bodyEmitter(
                il,
                () =>
            {
                if (traits.GetEnumeratorMethod.ReturnType.IsValueType)
                {
                    il.EmitAnyLdloca(enumerator);
                }
                else
                {
                    il.EmitAnyLdloc(enumerator);
                }
                il.EmitGetProperty(currentProperty);
            }
                );

            il.EmitBr(startLoop);
            il.MarkLabel(endLoop);

            // Dispose
            if (typeof(IDisposable).IsAssignableFrom(traits.GetEnumeratorMethod.ReturnType))
            {
                il.BeginFinallyBlock();

                if (traits.GetEnumeratorMethod.ReturnType.IsValueType)
                {
                    var disposeMethod = traits.GetEnumeratorMethod.ReturnType.GetMethod("Dispose");
                    if (disposeMethod != null && disposeMethod.GetParameters().Length == 0 && disposeMethod.ReturnType == typeof(void))
                    {
                        il.EmitAnyLdloca(enumerator);
                        il.EmitAnyCall(disposeMethod);
                    }
                    else
                    {
                        il.EmitAnyLdloc(enumerator);
                        il.EmitBox(traits.GetEnumeratorMethod.ReturnType);
                        il.EmitAnyCall(Metadata._IDisposable.Dispose);
                    }
                }
                else
                {
                    il.EmitAnyLdloc(enumerator);
                    il.EmitAnyCall(Metadata._IDisposable.Dispose);
                }

                il.EndExceptionBlock();
            }
        }
예제 #29
0
        /// <summary>
        /// Emits the deserialize collection value.
        /// </summary>
        /// <param name="emitter">The emitter.</param>
        /// <param name="il">The il generator.</param>
        /// <param name="unpackerArgumentIndex">Index of the unpacker argument.</param>
        /// <param name="target">The target collection variable.</param>
        /// <param name="member">The deserializing member metadata which holds the collection.</param>
        /// <param name="memberType">Type of the deserializing member.</param>
        /// <param name="nilImplication">The nil implication.</param>
        /// <param name="localHolder">The <see cref="LocalVariableHolder"/> which holds shared local variable information.</param>
        public static void EmitDeserializeCollectionValue(SerializerEmitter emitter, TracingILGenerator il, int unpackerArgumentIndex, LocalBuilder target, MemberInfo member, Type memberType, NilImplication nilImplication, LocalVariableHolder localHolder)
        {
            Contract.Requires(emitter != null);
            Contract.Requires(il != null);
            Contract.Requires(unpackerArgumentIndex >= 0);
            Contract.Requires(target != null);
            Contract.Requires(member != null);
            Contract.Requires(memberType != null);
            Contract.Requires(localHolder != null);

            var endOfDeserialization = il.DefineLabel("END_OF_DESERIALIZATION");

            EmitGeneralRead(il, unpackerArgumentIndex);

            switch (nilImplication)
            {
            case NilImplication.MemberDefault:
            {
                /*
                 * if( unpacker.Data.Value.IsNil )
                 * {
                 *		// Skip current.
                 *		goto END_OF_DESERIALIZATION;
                 * }
                 */
                il.EmitAnyLdarg(unpackerArgumentIndex);
                il.EmitGetProperty(Metadata._Unpacker.Data);
                var data = localHolder.UnpackedData;
                il.EmitAnyStloc(data);
                il.EmitAnyLdloca(data);
                il.EmitGetProperty(Metadata._Nullable <MessagePackObject> .Value);
                var dataValue = localHolder.UnpackedDataValue;
                il.EmitAnyStloc(dataValue);
                il.EmitAnyLdloca(dataValue);
                il.EmitGetProperty(Metadata._MessagePackObject.IsNil);
                il.EmitBrtrue(endOfDeserialization);

                break;
            }

            case NilImplication.Null:
            case NilImplication.Prohibit:
            {
                /*
                 * // for Prohibit
                 * if( unpacker.Data.Value.IsNil )
                 * {
                 *		throw SerializationEceptions.NewProhibitNullException( "..." );
                 * }
                 *
                 * // for Null, and
                 * if( unpacker.Data.Value.IsNil )
                 * {
                 *		throw SerializationEceptions.NewReadOnlyMemberItemsMustNotBeNullMethod( "..." );
                 * }
                 */
                il.EmitAnyLdarg(unpackerArgumentIndex);
                il.EmitGetProperty(Metadata._Unpacker.Data);
                var data = localHolder.UnpackedData;
                il.EmitAnyStloc(data);
                il.EmitAnyLdloca(data);
                il.EmitGetProperty(Metadata._Nullable <MessagePackObject> .Value);
                var dataValue = localHolder.UnpackedDataValue;
                il.EmitAnyStloc(dataValue);
                il.EmitAnyLdloca(dataValue);
                il.EmitGetProperty(Metadata._MessagePackObject.IsNil);
                var endIf0 = il.DefineLabel("END_IF0");
                il.EmitBrfalse_S(endIf0);
                il.EmitLdstr(member.Name);
                if (nilImplication == NilImplication.Prohibit)
                {
                    il.EmitAnyCall(SerializationExceptions.NewNullIsProhibitedMethod);
                }
                else
                {
                    // Because result member is readonly collection, so the member will not be null if packed value was nil.
                    il.EmitAnyCall(SerializationExceptions.NewReadOnlyMemberItemsMustNotBeNullMethod);
                }
                il.EmitThrow();
                il.MarkLabel(endIf0);

                break;
            }
            }

            /*
             *	if( !unpacker.IsArrayHeader && !unpacker.IsMapHeader )
             *	{
             *		throw new SerializatonException( "Cannot deserialize..." );
             *	}
             *
             *	using( var subtreeUnpacker = unpacker.ReadSubtree() )
             *	{
             *		GET_SERIALIZER.UnpackTo( unpacker, result ) )
             *	}
             *
             *	END_OF_DESERIALIZATION:
             */

            var endIf            = il.DefineLabel("THEN");
            var serializerGetter = emitter.RegisterSerializer(memberType);

            il.EmitAnyLdarg(unpackerArgumentIndex);
            il.EmitGetProperty(Metadata._Unpacker.IsArrayHeader);
            il.EmitBrtrue_S(endIf);
            il.EmitAnyLdarg(unpackerArgumentIndex);
            il.EmitGetProperty(Metadata._Unpacker.IsMapHeader);
            il.EmitBrtrue_S(endIf);
            // else
            il.EmitLdstr(member.Name);
            il.EmitAnyCall(SerializationExceptions.NewStreamDoesNotContainCollectionForMemberMethod);
            il.EmitThrow();
            // then
            var subtreeUnpacker = localHolder.SubtreeUnpacker;

            il.MarkLabel(endIf);
            EmitUnpackerBeginReadSubtree(il, unpackerArgumentIndex, subtreeUnpacker);
            serializerGetter(il, 0);
            il.EmitAnyLdloc(subtreeUnpacker);
            il.EmitAnyLdloc(target);
            Emittion.EmitLoadValue(il, member);
            il.EmitAnyCall(typeof(MessagePackSerializer <>).MakeGenericType(memberType).GetMethod("UnpackTo", new[] { typeof(Unpacker), memberType }));
            EmitUnpackerEndReadSubtree(il, subtreeUnpacker);
            il.MarkLabel(endOfDeserialization);
        }
예제 #30
0
        public static void EmitForEach(TracingILGenerator il, CollectionTraits traits, LocalBuilder collection, Action <TracingILGenerator, Action> bodyEmitter)
        {
            Contract.Requires(il != null);
            Contract.Requires(collection != null);
            Contract.Requires(bodyEmitter != null);
            LocalBuilder enumerator = il.DeclareLocal(traits.GetEnumeratorMethod.ReturnType, "enumerator");

            if (collection.LocalType.IsValueType)
            {
                il.EmitAnyLdloca(collection);
            }
            else
            {
                il.EmitAnyLdloc(collection);
            }
            il.EmitAnyCall(traits.GetEnumeratorMethod);
            il.EmitAnyStloc(enumerator);
            if (typeof(IDisposable).IsAssignableFrom(traits.GetEnumeratorMethod.ReturnType))
            {
                il.BeginExceptionBlock();
            }
            Label label = il.DefineLabel("START_LOOP");

            il.MarkLabel(label);
            Label        target          = il.DefineLabel("END_LOOP");
            Type         returnType      = traits.GetEnumeratorMethod.ReturnType;
            MethodInfo   method          = returnType.GetMethod("MoveNext", Type.EmptyTypes);
            PropertyInfo currentProperty = traits.GetEnumeratorMethod.ReturnType.GetProperty("Current");

            if (method == null)
            {
                method = _IEnumerator.MoveNext;
            }
            if (currentProperty == null)
            {
                if (returnType == typeof(IDictionaryEnumerator))
                {
                    currentProperty = _IDictionaryEnumerator.Current;
                }
                else if (returnType.IsInterface)
                {
                    if (returnType.IsGenericType && (returnType.GetGenericTypeDefinition() == typeof(IEnumerator <>)))
                    {
                        currentProperty = typeof(IEnumerator <>).MakeGenericType(new Type[] { traits.ElementType }).GetProperty("Current");
                    }
                    else
                    {
                        currentProperty = _IEnumerator.Current;
                    }
                }
            }
            Contract.Assert(currentProperty != null, returnType.ToString());
            if (traits.GetEnumeratorMethod.ReturnType.IsValueType)
            {
                il.EmitAnyLdloca(enumerator);
            }
            else
            {
                il.EmitAnyLdloc(enumerator);
            }
            il.EmitAnyCall(method);
            il.EmitBrfalse(target);
            bodyEmitter(il, delegate {
                if (traits.GetEnumeratorMethod.ReturnType.IsValueType)
                {
                    il.EmitAnyLdloca(enumerator);
                }
                else
                {
                    il.EmitAnyLdloc(enumerator);
                }
                il.EmitGetProperty(currentProperty);
            });
            il.EmitBr(label);
            il.MarkLabel(target);
            if (typeof(IDisposable).IsAssignableFrom(traits.GetEnumeratorMethod.ReturnType))
            {
                il.BeginFinallyBlock();
                if (traits.GetEnumeratorMethod.ReturnType.IsValueType)
                {
                    MethodInfo info2 = traits.GetEnumeratorMethod.ReturnType.GetMethod("Dispose");
                    if (((info2 != null) && (info2.GetParameters().Length == 0)) && (info2.ReturnType == typeof(void)))
                    {
                        il.EmitAnyLdloca(enumerator);
                        il.EmitAnyCall(info2);
                    }
                    else
                    {
                        il.EmitAnyLdloc(enumerator);
                        il.EmitBox(traits.GetEnumeratorMethod.ReturnType);
                        il.EmitAnyCall(_IDisposable.Dispose);
                    }
                }
                else
                {
                    il.EmitAnyLdloc(enumerator);
                    il.EmitAnyCall(_IDisposable.Dispose);
                }
                il.EndExceptionBlock();
            }
        }