private static void EmitInvokeMapUnpackToHelper(Type targetType, SerializerEmitter emitter, CollectionTraits traits, TracingILGenerator il, int unpackerArgumentIndex, Action <TracingILGenerator> loadCollectionEmitting) { il.EmitAnyLdarg(unpackerArgumentIndex); if (traits.ElementType.IsGenericType) { var keyType = traits.ElementType.GetGenericArguments()[0]; var valueType = traits.ElementType.GetGenericArguments()[1]; var keySerializerGetting = emitter.RegisterSerializer(keyType); var valueSerializerGetting = emitter.RegisterSerializer(valueType); keySerializerGetting(il, 0); valueSerializerGetting(il, 0); loadCollectionEmitting(il); if (targetType.IsValueType) { il.EmitBox(targetType); } il.EmitAnyCall(Metadata._UnpackHelpers.UnpackMapTo_2.MakeGenericMethod(keyType, valueType)); } else { loadCollectionEmitting(il); if (targetType.IsValueType) { il.EmitBox(targetType); } il.EmitAnyCall(Metadata._UnpackHelpers.UnpackNonGenericMapTo); } }
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(); }
private static void EmitNilImplicationForPrimitive(TracingILGenerator il, SerializingMember member, LocalBuilder value, Label endOfDeserialization) { Label targetIfNotNull = il.DefineLabel("END_IF_NULL"); EmitCompareNull(il, value, targetIfNotNull); switch (member.Contract.NilImplication) { case NilImplication.MemberDefault: il.EmitBr(endOfDeserialization); break; case NilImplication.Null: if (member.Member.GetMemberValueType().GetIsValueType() && (Nullable.GetUnderlyingType(member.Member.GetMemberValueType()) == null)) { il.EmitLdstr(member.Contract.Name); il.EmitLdtoken(member.Member.GetMemberValueType()); il.EmitAnyCall(_Type.GetTypeFromHandle); il.EmitLdtoken(member.Member.DeclaringType); il.EmitAnyCall(_Type.GetTypeFromHandle); il.EmitAnyCall(SerializationExceptions.NewValueTypeCannotBeNull3Method); il.EmitThrow(); } break; case NilImplication.Prohibit: il.EmitLdstr(member.Contract.Name); il.EmitAnyCall(SerializationExceptions.NewNullIsProhibitedMethod); il.EmitThrow(); break; } il.MarkLabel(targetIfNotNull); }
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); } }
/// <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")); }
public static void EmitGeneralRead(TracingILGenerator il, int unpackerArgumentIndex) { il.EmitAnyLdarg(unpackerArgumentIndex); il.EmitAnyCall(_Unpacker.Read); Label target = il.DefineLabel("END_IF"); il.EmitBrtrue_S(target); il.EmitAnyCall(SerializationExceptions.NewUnexpectedEndOfStreamMethod); il.EmitThrow(); il.MarkLabel(target); }
private static void CreatePacking(SerializerEmitter emitter) { Action <TracingILGenerator> loadValueEmitter = null; TracingILGenerator il = emitter.GetPackToMethodILGenerator(); try { Label target = il.DefineLabel("END_IF"); Label label2 = il.DefineLabel("END_METHOD"); il.EmitAnyLdarga(2); il.EmitGetProperty(NullableMessagePackSerializer <T> ._nullableTHasValueProperty); il.EmitBrtrue_S(target); il.EmitAnyLdarg(1); il.EmitAnyCall(NullableMessagePackSerializer.PackerPackNull); il.EmitPop(); il.EmitBr_S(label2); il.MarkLabel(target); if (loadValueEmitter == null) { loadValueEmitter = delegate(TracingILGenerator il0) { il0.EmitAnyLdarga(2); il.EmitGetProperty(NullableMessagePackSerializer <T> ._nullableTValueProperty); }; } Emittion.EmitSerializeValue(emitter, il, 1, NullableMessagePackSerializer <T> ._nullableTValueProperty.PropertyType, null, NilImplication.MemberDefault, loadValueEmitter, new LocalVariableHolder(il)); il.MarkLabel(label2); il.EmitRet(); } finally { il.FlushTrace(); emitter.FlushTrace(); } }
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); }
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(); }
protected override void EmitPackMembers(SerializerEmitter emitter, TracingILGenerator packerIL, SerializingMember[] entries) { var localHolder = new LocalVariableHolder(packerIL); packerIL.EmitAnyLdarg(1); packerIL.EmitAnyLdc_I4(entries.Length); packerIL.EmitAnyCall(Metadata._Packer.PackArrayHeader); packerIL.EmitPop(); foreach (var member in entries) { if (member.Member == null) { // missing member, always nil packerIL.EmitAnyLdarg(1); packerIL.EmitAnyCall(Metadata._Packer.PackNull); packerIL.EmitPop(); } else { Emittion.EmitSerializeValue( emitter, packerIL, 1, member.Member.GetMemberValueType(), member.Member.Name, member.Contract.NilImplication, il => { if (typeof(TObject).IsValueType) { il.EmitAnyLdarga(2); } else { il.EmitAnyLdarg(2); } Emittion.EmitLoadValue(il, member.Member); }, localHolder ); } } packerIL.EmitRet(); }
protected sealed override void EmitPackMembers(SerializerEmitter emitter, TracingILGenerator packerIL, SerializingMember[] entries) { var localHolder = new LocalVariableHolder(packerIL); packerIL.EmitAnyLdarg(1); packerIL.EmitAnyLdc_I4(entries.Length); packerIL.EmitAnyCall(Metadata._Packer.PackMapHeader); packerIL.EmitPop(); foreach (var entry in entries) { if (entry.Member == null) { // skip undefined member. continue; } packerIL.EmitAnyLdarg(1); packerIL.EmitLdstr(entry.Contract.Name); packerIL.EmitAnyCall(Metadata._Packer.PackString); packerIL.EmitPop(); Emittion.EmitSerializeValue( emitter, packerIL, 1, entry.Member.GetMemberValueType(), entry.Contract.Name, entry.Contract.NilImplication, il0 => { if (typeof(TObject).IsValueType) { il0.EmitAnyLdarga(2); } else { il0.EmitAnyLdarg(2); } Emittion.EmitLoadValue(il0, entry.Member); }, localHolder ); } packerIL.EmitRet(); }
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); }
/// <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(); }
/// <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); }
public static void EmitUnpackerBeginReadSubtree(TracingILGenerator il, int unpackerArgumentIndex, LocalBuilder subtreeUnpacker) { Contract.Requires(il != null); Contract.Requires(unpackerArgumentIndex >= 0); Contract.Requires(subtreeUnpacker != null); il.EmitAnyLdarg(unpackerArgumentIndex); il.EmitAnyCall(_Unpacker.ReadSubtree); il.EmitAnyStloc(subtreeUnpacker); il.BeginExceptionBlock(); }
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)); } }
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")); }
protected override void EmitPackMembers(SerializerEmitter emitter, TracingILGenerator packerIL, SerializingMember[] entries) { LocalVariableHolder localHolder = new LocalVariableHolder(packerIL); packerIL.EmitAnyLdarg(1); packerIL.EmitAnyLdc_I4(entries.Length); packerIL.EmitAnyCall(_Packer.PackArrayHeader); packerIL.EmitPop(); SerializingMember[] memberArray = entries; for (int i = 0; i < memberArray.Length; i++) { Action <TracingILGenerator> loadValueEmitter = null; SerializingMember member = memberArray[i]; if (member.Member == null) { packerIL.EmitAnyLdarg(1); packerIL.EmitAnyCall(_Packer.PackNull); packerIL.EmitPop(); } else { if (loadValueEmitter == null) { loadValueEmitter = delegate(TracingILGenerator il) { if (typeof(TObject).IsValueType) { il.EmitAnyLdarga(2); } else { il.EmitAnyLdarg(2); } Emittion.EmitLoadValue(il, member.Member); }; } Emittion.EmitSerializeValue(emitter, packerIL, 1, member.Member.GetMemberValueType(), member.Member.Name, member.Contract.NilImplication, loadValueEmitter, localHolder); } } packerIL.EmitRet(); }
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(); } }
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(); }
public static void EmitNilImplication(TracingILGenerator il, int unpackerArgumentIndex, string memberName, NilImplication nilImplication, Label endOfDeserialization, LocalVariableHolder localHolder) { LocalBuilder unpackedData; LocalBuilder unpackedDataValue; 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(endOfDeserialization); break; 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); Label target = il.DefineLabel("END_IF0"); il.EmitBrfalse_S(target); il.EmitLdstr(memberName); il.EmitAnyCall(SerializationExceptions.NewNullIsProhibitedMethod); il.EmitThrow(); il.MarkLabel(target); break; } } }
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(); } }
/// <summary> /// Emits the nil implication. /// </summary> /// <param name="il">The il generator.</param> /// <param name="unpackerArgumentIndex">Index of the unpacker argument.</param> /// <param name="memberName">Name of the deserializing member.</param> /// <param name="nilImplication">The nil implication.</param> /// <param name="endOfDeserialization">The label to the end of deserialization.</param> /// <param name="localHolder">The <see cref="LocalVariableHolder"/> which holds shared local variable information.</param> public static void EmitNilImplication( TracingILGenerator il, int unpackerArgumentIndex, string memberName, NilImplication nilImplication, Label endOfDeserialization, LocalVariableHolder localHolder ) { switch (nilImplication) { case NilImplication.MemberDefault: { // TODO: This should be empty for extra items. /* * 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.Prohibit: { /* * if( unpacker.Data.Value.IsNil ) * { * throw SerializationEceptions.NewProhibitNullException( "..." ); * } */ 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(memberName); il.EmitAnyCall(SerializationExceptions.NewNullIsProhibitedMethod); il.EmitThrow(); il.MarkLabel(endIf0); break; } } }
/// <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(); }
/// <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(); } }
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); }
/// <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); }
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(); } }
/// <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); } }
private static void EmitNilImplicationForPrimitive(TracingILGenerator il, SerializingMember member, LocalBuilder value, Label endOfDeserialization) { var endIf = il.DefineLabel("END_IF_NULL"); EmitCompareNull(il, value, endIf); switch (member.Contract.NilImplication) { case NilImplication.MemberDefault: { /* * if( value == null ) * { * // Skip current. * goto END_OF_DESERIALIZATION; * } */ il.EmitBr(endOfDeserialization); break; } case NilImplication.Null: { // Throw exception for non-nullable value type. // Nop for nullables. if (member.Member.GetMemberValueType().GetIsValueType() && Nullable.GetUnderlyingType(member.Member.GetMemberValueType()) == null) { /* * if( value == null ) * { * throw SerializationEceptions.NewValueTypeCannotBeNull( "...", typeof( MEMBER ), typeof( TYPE ) ); * } */ il.EmitLdstr(member.Contract.Name); il.EmitLdtoken(member.Member.GetMemberValueType()); il.EmitAnyCall(Metadata._Type.GetTypeFromHandle); il.EmitLdtoken(member.Member.DeclaringType); il.EmitAnyCall(Metadata._Type.GetTypeFromHandle); il.EmitAnyCall(SerializationExceptions.NewValueTypeCannotBeNull3Method); il.EmitThrow(); } break; } case NilImplication.Prohibit: { /* * if( value == null ) * { * throw SerializationEceptions.NewProhibitNullException( "..." ); * } */ il.EmitLdstr(member.Contract.Name); il.EmitAnyCall(SerializationExceptions.NewNullIsProhibitedMethod); il.EmitThrow(); break; } } il.MarkLabel(endIf); }