private static void EmitUnpackMembers(SerializerEmitter emitter, TracingILGenerator unpackerIL, SerializingMember[] entries, LocalBuilder result) { /* * #if T is IUnpackable * result.UnpackFromMessage( unpacker ); * #else * if( unpacker.IsArrayHeader ) * { * ... * } * else * { * ... * } * #endif */ var localHolder = new LocalVariableHolder(unpackerIL); unpackerIL.EmitAnyLdarg(1); unpackerIL.EmitGetProperty(Metadata._Unpacker.IsArrayHeader); var @else = unpackerIL.DefineLabel("ELSE"); var endif = unpackerIL.DefineLabel("END_IF"); unpackerIL.EmitBrfalse(@else); EmitUnpackMembersFromArray(emitter, unpackerIL, entries, result, localHolder, endif); unpackerIL.EmitBr(endif); unpackerIL.MarkLabel(@else); EmitUnpackMembersFromMap(emitter, unpackerIL, entries, result, localHolder); unpackerIL.MarkLabel(endif); }
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(); } }
/// <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); }
private void DoConditionalInstruction( TracingILGenerator il, Action onThen, Action onElse ) { if (this._elseExpression != null) { var @else = il.DefineLabel("ELSE"); var endIf = il.DefineLabel("END_IF"); this._condition.Branch(il, @else); onThen(); if (!this._thenExpression.IsTerminating) { il.EmitBr(endIf); } il.MarkLabel(@else); onElse(); il.MarkLabel(endIf); } else { var endIf = il.DefineLabel("END_IF"); this._condition.Branch(il, endIf); onThen(); il.MarkLabel(endIf); } }
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); }
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")); }
/// <summary> /// Emits deserializing value instructions. /// </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="memberName">The name of the member.</param> /// <param name="localHolder">The <see cref="LocalVariableHolder"/> which holds shared local variable information.</param> public static void EmitDeserializeValueWithoutNilImplication(SerializerEmitter emitter, TracingILGenerator il, int unpackerArgumentIndex, LocalBuilder value, Type targetType, string memberName, LocalVariableHolder localHolder) { Contract.Requires(emitter != null); Contract.Requires(il != null); Contract.Requires(unpackerArgumentIndex >= 0); Contract.Requires(value != 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: */ // Nil implication is not needed. EmitDeserializeValueCore(emitter, il, unpackerArgumentIndex, value, targetType, null, memberName, endOfDeserialization, localHolder); il.MarkLabel(endOfDeserialization); }
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(); }
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); }
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 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); }
private static void EmitUnpackMembers(SerializerEmitter emitter, TracingILGenerator unpackerIL, SerializingMember[] entries, LocalBuilder result) { LocalVariableHolder localHolder = new LocalVariableHolder(unpackerIL); unpackerIL.EmitAnyLdarg(1); unpackerIL.EmitGetProperty(_Unpacker.IsArrayHeader); Label target = unpackerIL.DefineLabel("ELSE"); Label label2 = unpackerIL.DefineLabel("END_IF"); unpackerIL.EmitBrfalse(target); EmittingSerializerBuilder <TObject> .EmitUnpackMembersFromArray(emitter, unpackerIL, entries, result, localHolder); unpackerIL.EmitBr(label2); unpackerIL.MarkLabel(target); EmittingSerializerBuilder <TObject> .EmitUnpackMembersFromMap(emitter, unpackerIL, entries, result, localHolder); unpackerIL.MarkLabel(label2); }
public static void EmitDeserializeValueWithoutNilImplication(SerializerEmitter emitter, TracingILGenerator il, int unpackerArgumentIndex, LocalBuilder value, Type targetType, string memberName, LocalVariableHolder localHolder) { Contract.Requires(emitter != null); Contract.Requires(il != null); Contract.Requires(unpackerArgumentIndex >= 0); Contract.Requires(value != null); Label endOfDeserialization = il.DefineLabel("END_OF_DESERIALIZATION"); EmitDeserializeValueCore(emitter, il, unpackerArgumentIndex, value, targetType, null, memberName, endOfDeserialization, localHolder); il.MarkLabel(endOfDeserialization); }
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); }
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")); }
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 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(); } }
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); }
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(); }
/// <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(); }
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 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(); } }
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); }
/// <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); } }
/// <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); }
/// <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; } } }
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(); } }
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 '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(); } }