示例#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
        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));
        }
示例#4
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);
        }
        public override void Evaluate(TracingILGenerator il)
        {
            if (this._isLocal && this._index < 0)
            {
                il.TraceWriteLine("// Eval->: {0}", this);

                this._index = il.DeclareLocal(this.ContextType.ResolveRuntimeType(), this._name).LocalIndex;

                il.TraceWriteLine("// ->Eval: {0}", this);
            }
        }
示例#6
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 EmitExceptionHandling(
            TracingILGenerator il,
            Type returnType,
            Label endOfMethod,
            Action <TracingILGenerator, LocalBuilder> exceptionHandlerInvocation
            )
        {
            il.BeginCatchBlock(typeof(Exception));
            var exception = il.DeclareLocal(typeof(Exception), "exception");

            il.EmitAnyStloc(exception);
            exceptionHandlerInvocation(il, exception);
            il.EmitLeave(endOfMethod);
            il.EndExceptionBlock();
        }
示例#8
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 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);
            }
        }
        /// <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();
        }
示例#11
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();
            }
        }
示例#12
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();
            }
        }
示例#13
0
        private static void EmitUnpackMembersFromArray(SerializerEmitter emitter, TracingILGenerator unpackerIL, SerializingMember[] entries, LocalBuilder result, LocalVariableHolder localHolder, Label endOfDeserialization)
        {
            /*
             *  int unpacked = 0;
             *  int itemsCount = unpacker.ItemsCount;
             *
             *  :
             *  if( unpacked >= itemsCount )
             *  {
             *		HandleNilImplication(...);
             *  }
             *  else
             *  {
             *  #if PRIMITIVE
             *		if( !unpacker.ReadT( out local1 ) )
             *		{
             *			throw SerializationExceptions.NewUnexpectedEndOfStreamMethod();
             *		}
             *  #else
             *		if( !unpacker.Read() )
             *		{
             *			throw SerializationExceptions.NewUnexpectedEndOfStreamMethod();
             *		}
             *
             *		local1 = this._serializer1.Unpack
             *	#endif
             *		unpacked++;
             *	}
             *	:
             */

            // TODO: Supports ExtensionObject like round-tripping.

            var itemsCount = localHolder.ItemsCount;
            var unpacked   = unpackerIL.DeclareLocal(typeof(int), "unpacked");

            Emittion.EmitGetUnpackerItemsCountAsInt32(unpackerIL, 1, localHolder);
            unpackerIL.EmitAnyStloc(itemsCount);

            for (int i = 0; i < entries.Length; i++)
            {
                var endIf0 = unpackerIL.DefineLabel("END_IF");
                var else0  = unpackerIL.DefineLabel("ELSE");

                unpackerIL.EmitAnyLdloc(unpacked);
                unpackerIL.EmitAnyLdloc(itemsCount);
                unpackerIL.EmitBge(else0);

                if (entries[i].Member == null)
                {
                    Emittion.EmitGeneralRead(unpackerIL, 1);
                    // Ignore undefined member -- Nop.
                }
                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(unpacked);
                unpackerIL.EmitLdc_I4_1();
                unpackerIL.EmitAdd();
                unpackerIL.EmitAnyStloc(unpacked);

                unpackerIL.EmitBr(endIf0);

                unpackerIL.MarkLabel(else0);

                if (entries[i].Member != null)
                {
                    // Respect nil implication.
                    switch (entries[i].Contract.NilImplication)
                    {
                    case NilImplication.MemberDefault:
                    {
                        unpackerIL.EmitBr(endOfDeserialization);
                        break;
                    }

                    case NilImplication.Null:
                    {
                        if (entries[i].Member.GetMemberValueType().GetIsValueType())
                        {
                            if (Nullable.GetUnderlyingType(entries[i].Member.GetMemberValueType()) == null)
                            {
                                // val type

                                /*
                                 * if( value == null )
                                 * {
                                 *		throw SerializationEceptions.NewValueTypeCannotBeNull( "...", typeof( MEMBER ), typeof( TYPE ) );
                                 * }
                                 */
                                unpackerIL.EmitLdstr(entries[i].Contract.Name);
                                unpackerIL.EmitLdtoken(entries[i].Member.GetMemberValueType());
                                unpackerIL.EmitAnyCall(Metadata._Type.GetTypeFromHandle);
                                unpackerIL.EmitLdtoken(entries[i].Member.DeclaringType);
                                unpackerIL.EmitAnyCall(Metadata._Type.GetTypeFromHandle);
                                unpackerIL.EmitAnyCall(SerializationExceptions.NewValueTypeCannotBeNull3Method);
                                unpackerIL.EmitThrow();
                            }
                            else
                            {
                                // nullable
                                unpackerIL.EmitAnyLdloca(localHolder.GetDeserializedValue(entries[i].Member.GetMemberValueType()));
                                unpackerIL.EmitInitobj(entries[i].Member.GetMemberValueType());
                                unpackerIL.EmitAnyLdloc(result);
                                unpackerIL.EmitAnyLdloc(localHolder.GetDeserializedValue(entries[i].Member.GetMemberValueType()));
                                Emittion.EmitStoreValue(unpackerIL, entries[i].Member);
                            }
                        }
                        else
                        {
                            // ref type
                            unpackerIL.EmitAnyLdloc(result);
                            unpackerIL.EmitLdnull();
                            Emittion.EmitStoreValue(unpackerIL, entries[i].Member);
                        }

                        break;
                    }

                    case NilImplication.Prohibit:
                    {
                        unpackerIL.EmitLdstr(entries[i].Contract.Name);
                        unpackerIL.EmitAnyCall(SerializationExceptions.NewNullIsProhibitedMethod);
                        unpackerIL.EmitThrow();
                        break;
                    }
                    }
                }

                unpackerIL.MarkLabel(endIf0);
            }
        }
        protected sealed override MessagePackSerializer <TObject> CreateSerializer(SerializingMember[] entries)
        {
            MessagePackSerializer <TObject> serializer;

            using (SerializerEmitter emitter = this._generatorManager.CreateEmitter(typeof(TObject), this._emitterFlavor))
            {
                try
                {
                    TracingILGenerator packToMethodILGenerator = emitter.GetPackToMethodILGenerator();
                    try
                    {
                        if (typeof(IPackable).IsAssignableFrom(typeof(TObject)))
                        {
                            if (typeof(TObject).IsValueType)
                            {
                                packToMethodILGenerator.EmitAnyLdarga(2);
                            }
                            else
                            {
                                packToMethodILGenerator.EmitAnyLdarg(2);
                            }
                            packToMethodILGenerator.EmitAnyLdarg(1);
                            packToMethodILGenerator.EmitLdnull();
                            packToMethodILGenerator.EmitCall(typeof(TObject).GetInterfaceMap(typeof(IPackable)).TargetMethods.Single <MethodInfo>());
                            packToMethodILGenerator.EmitRet();
                        }
                        else
                        {
                            this.EmitPackMembers(emitter, packToMethodILGenerator, entries);
                        }
                    }
                    finally
                    {
                        packToMethodILGenerator.FlushTrace();
                    }
                    TracingILGenerator unpackFromMethodILGenerator = emitter.GetUnpackFromMethodILGenerator();
                    try
                    {
                        LocalBuilder target = unpackFromMethodILGenerator.DeclareLocal(typeof(TObject), "result");
                        Emittion.EmitConstruction(unpackFromMethodILGenerator, target, null);
                        if (typeof(IUnpackable).IsAssignableFrom(typeof(TObject)))
                        {
                            if (typeof(TObject).GetIsValueType())
                            {
                                unpackFromMethodILGenerator.EmitAnyLdloca(target);
                            }
                            else
                            {
                                unpackFromMethodILGenerator.EmitAnyLdloc(target);
                            }
                            unpackFromMethodILGenerator.EmitAnyLdarg(1);
                            unpackFromMethodILGenerator.EmitCall(typeof(TObject).GetInterfaceMap(typeof(IUnpackable)).TargetMethods.Single <MethodInfo>());
                        }
                        else
                        {
                            EmittingSerializerBuilder <TObject> .EmitUnpackMembers(emitter, unpackFromMethodILGenerator, entries, target);
                        }
                        unpackFromMethodILGenerator.EmitAnyLdloc(target);
                        unpackFromMethodILGenerator.EmitRet();
                    }
                    finally
                    {
                        unpackFromMethodILGenerator.FlushTrace();
                    }
                    serializer = emitter.CreateInstance <TObject>(base.Context);
                }
                finally
                {
                    emitter.FlushTrace();
                }
            }
            return(serializer);
        }
示例#15
0
        private static void EmitUnpackMembersFromArray(SerializerEmitter emitter, TracingILGenerator unpackerIL, SerializingMember[] entries, LocalBuilder result, LocalVariableHolder localHolder)
        {
            /*
             *  int unpacked = 0;
             *  int itemsCount = unpacker.ItemsCount;
             *
             *  :
             *  if( unpacked == itemsCount )
             *  {
             *		HandleNilImplication(...);
             *  }
             *  else
             *  {
             *  #if PRIMITIVE
             *		if( !unpacker.ReadT( out local1 ) )
             *		{
             *			throw SerializationExceptions.NewUnexpectedEndOfStreamMethod();
             *		}
             *  #else
             *		if( !unpacker.Read() )
             *		{
             *			throw SerializationExceptions.NewUnexpectedEndOfStreamMethod();
             *		}
             *
             *		local1 = this._serializer1.Unpack
             *	#endif
             *		unpacked++;
             *	}
             *	:
             */

            // TODO: Supports ExtensionObject like round-tripping.

            var itemsCount = localHolder.ItemsCount;
            var unpacked   = unpackerIL.DeclareLocal(typeof(int), "unpacked");

            Emittion.EmitGetUnpackerItemsCountAsInt32(unpackerIL, 1, localHolder);
            unpackerIL.EmitAnyStloc(itemsCount);

            for (int i = 0; i < entries.Length; i++)
            {
                var endIf0 = unpackerIL.DefineLabel("END_IF");
                var else0  = unpackerIL.DefineLabel("ELSE");

                unpackerIL.EmitAnyLdloc(unpacked);
                unpackerIL.EmitAnyLdloc(itemsCount);
                unpackerIL.EmitBlt(else0);
                // Tail missing member handling.
                if (entries[i].Member != null)
                {
                    // Respect nil implication.
                    Emittion.EmitNilImplication(unpackerIL, 1, entries[i].Contract.Name, entries[i].Contract.NilImplication, endIf0, localHolder);
                }

                unpackerIL.EmitBr(endIf0);

                unpackerIL.MarkLabel(else0);

                if (entries[i].Member == null)
                {
                    Emittion.EmitGeneralRead(unpackerIL, 1);
                    // Ignore undefined member -- Nop.
                }
                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(unpacked);
                unpackerIL.EmitLdc_I4_1();
                unpackerIL.EmitAdd();
                unpackerIL.EmitAnyStloc(unpacked);

                unpackerIL.MarkLabel(endIf0);
            }
        }