Пример #1
0
        public static void GenSerializerCall(CodeGenContext ctx, ILGenerator il, Type type)
        {
            // We can call the Serializer method directly for:
            // - Value types
            // - Array types
            // - Sealed types with static Serializer method, as the method will handle null
            // Other reference types go through the SerializesSwitch

            bool direct;

            if (type.IsValueType || type.IsArray)
            {
                direct = true;
            }
            else if (type.IsSealed && ctx.IsGenerated(type) == false)
            {
                direct = true;
            }
            else
            {
                direct = false;
            }

            var method = direct ? ctx.GetWriterMethodInfo(type) : ctx.SerializerSwitchMethodInfo;

            il.EmitCall(OpCodes.Call, method, null);
        }
Пример #2
0
        public void GenerateWriterMethod(Type type, CodeGenContext ctx, ILGenerator il)
        {
            var valueType = type.GetGenericArguments()[0];

            var noValueLabel = il.DefineLabel();

            MethodInfo getHasValue = type.GetProperty("HasValue").GetGetMethod();
            MethodInfo getValue = type.GetProperty("Value").GetGetMethod();

            var data = ctx.GetTypeDataForCall(valueType);

            il.Emit(OpCodes.Ldarg_1);       // Stream
            il.Emit(OpCodes.Ldarga_S, 2);   // &value
            il.Emit(OpCodes.Call, getHasValue);
            il.Emit(OpCodes.Call, ctx.GetWriterMethodInfo(typeof(bool)));

            il.Emit(OpCodes.Ldarga_S, 2);   // &value
            il.Emit(OpCodes.Call, getHasValue);
            il.Emit(OpCodes.Brfalse_S, noValueLabel);

            if (data.NeedsInstanceParameter)
                il.Emit(OpCodes.Ldarg_0);   // Serializer
            il.Emit(OpCodes.Ldarg_1);       // Stream
            il.Emit(OpCodes.Ldarga_S, 2);   // &value
            il.Emit(OpCodes.Call, getValue);

            // XXX for some reason Tailcall causes huge slowdown, at least with "decimal?"
            //il.Emit(OpCodes.Tailcall);
            il.Emit(OpCodes.Call, data.WriterMethodInfo);

            il.MarkLabel(noValueLabel);
            il.Emit(OpCodes.Ret);
        }
Пример #3
0
        public void GenerateWriterMethod(Type type, CodeGenContext ctx, ILGenerator il)
        {
            var valueType = type.GetGenericArguments()[0];

            var noValueLabel = il.DefineLabel();

            MethodInfo getHasValue = type.GetProperty("HasValue").GetGetMethod();
            MethodInfo getValue    = type.GetProperty("Value").GetGetMethod();

            var data = ctx.GetTypeDataForCall(valueType);

            il.Emit(OpCodes.Ldarg_1);                   // Stream
            il.Emit(OpCodes.Ldarga_S, 2);               // &value
            il.Emit(OpCodes.Call, getHasValue);
            il.Emit(OpCodes.Call, ctx.GetWriterMethodInfo(typeof(bool)));

            il.Emit(OpCodes.Ldarga_S, 2);               // &value
            il.Emit(OpCodes.Call, getHasValue);
            il.Emit(OpCodes.Brfalse_S, noValueLabel);

            if (data.NeedsInstanceParameter)
            {
                il.Emit(OpCodes.Ldarg_0);               // Serializer
            }
            il.Emit(OpCodes.Ldarg_1);                   // Stream
            il.Emit(OpCodes.Ldarga_S, 2);               // &value
            il.Emit(OpCodes.Call, getValue);

            // XXX for some reason Tailcall causes huge slowdown, at least with "decimal?"
            //il.Emit(OpCodes.Tailcall);
            il.Emit(OpCodes.Call, data.WriterMethodInfo);

            il.MarkLabel(noValueLabel);
            il.Emit(OpCodes.Ret);
        }
        public static void GenerateSerializerSwitch(CodeGenContext ctx, ILGenerator il, IDictionary <Type, TypeData> map)
        {
            // arg0: Stream, arg1: object

            var idLocal = il.DeclareLocal(typeof(ushort));

            // get TypeID from object's Type
            var getTypeIDMethod = typeof(Serializer).GetMethod("GetTypeID", BindingFlags.NonPublic | BindingFlags.Static, null, new Type[] { typeof(object) }, null);

            il.Emit(OpCodes.Ldarg_1);
            il.EmitCall(OpCodes.Call, getTypeIDMethod, null);
            il.Emit(OpCodes.Stloc_S, idLocal);

            // write typeID
            il.Emit(OpCodes.Ldarg_0);
            il.Emit(OpCodes.Ldloc_S, idLocal);
            il.EmitCall(OpCodes.Call, ctx.GetWriterMethodInfo(typeof(ushort)), null);

            // +1 for 0 (null)
            var jumpTable = new Label[map.Count + 1];

            jumpTable[0] = il.DefineLabel();
            foreach (var kvp in map)
            {
                jumpTable[kvp.Value.TypeID] = il.DefineLabel();
            }

            il.Emit(OpCodes.Ldloc_S, idLocal);
            il.Emit(OpCodes.Switch, jumpTable);

            ConstructorInfo exceptionCtor = typeof(Exception).GetConstructor(BindingFlags.Public | BindingFlags.Instance, null, new Type[0], null);

            il.Emit(OpCodes.Newobj, exceptionCtor);
            il.Emit(OpCodes.Throw);

            /* null case */
            il.MarkLabel(jumpTable[0]);
            il.Emit(OpCodes.Ret);

            /* cases for types */
            foreach (var kvp in map)
            {
                var type = kvp.Key;
                var data = kvp.Value;

                il.MarkLabel(jumpTable[data.TypeID]);

                il.Emit(OpCodes.Ldarg_0);
                il.Emit(OpCodes.Ldarg_1);
                il.Emit(type.IsValueType ? OpCodes.Unbox_Any : OpCodes.Castclass, type);

                il.EmitCall(OpCodes.Call, data.WriterMethodInfo, null);

                il.Emit(OpCodes.Ret);
            }
        }
        public static void GenerateSerializerSwitch(CodeGenContext ctx, ILGenerator il, IDictionary<Type, TypeData> map)
        {
            // arg0: Stream, arg1: object

            var idLocal = il.DeclareLocal(typeof(ushort));

            // get TypeID from object's Type
            var getTypeIDMethod = typeof(Serializer).GetMethod("GetTypeID", BindingFlags.NonPublic | BindingFlags.Static, null, new Type[] { typeof(object) }, null);
            il.Emit(OpCodes.Ldarg_1);
            il.EmitCall(OpCodes.Call, getTypeIDMethod, null);
            il.Emit(OpCodes.Stloc_S, idLocal);

            // write typeID
            il.Emit(OpCodes.Ldarg_0);
            il.Emit(OpCodes.Ldloc_S, idLocal);
            il.EmitCall(OpCodes.Call, ctx.GetWriterMethodInfo(typeof(ushort)), null);

            // +1 for 0 (null)
            var jumpTable = new Label[map.Count + 1];
            jumpTable[0] = il.DefineLabel();
            foreach (var kvp in map)
                jumpTable[kvp.Value.TypeID] = il.DefineLabel();

            il.Emit(OpCodes.Ldloc_S, idLocal);
            il.Emit(OpCodes.Switch, jumpTable);

            ConstructorInfo exceptionCtor = typeof(Exception).GetConstructor(BindingFlags.Public | BindingFlags.Instance, null, new Type[0], null);
            il.Emit(OpCodes.Newobj, exceptionCtor);
            il.Emit(OpCodes.Throw);

            /* null case */
            il.MarkLabel(jumpTable[0]);
            il.Emit(OpCodes.Ret);

            /* cases for types */
            foreach (var kvp in map)
            {
                var type = kvp.Key;
                var data = kvp.Value;

                il.MarkLabel(jumpTable[data.TypeID]);

                il.Emit(OpCodes.Ldarg_0);
                il.Emit(OpCodes.Ldarg_1);
                il.Emit(type.IsValueType ? OpCodes.Unbox_Any : OpCodes.Castclass, type);

                il.EmitCall(OpCodes.Call, data.WriterMethodInfo, null);

                il.Emit(OpCodes.Ret);
            }
        }
Пример #6
0
		public static void GenSerializerCall(CodeGenContext ctx, ILGenerator il, Type type)
		{
			// We can call the Serializer method directly for:
			// - Value types
			// - Array types
			// - Sealed types with static Serializer method, as the method will handle null
			// Other reference types go through the SerializesSwitch

			bool direct;

			if (type.IsValueType || type.IsArray)
				direct = true;
			else if (type.IsSealed && ctx.IsGenerated(type) == false)
				direct = true;
			else
				direct = false;

			var method = direct ? ctx.GetWriterMethodInfo(type) : ctx.SerializerSwitchMethodInfo;

			il.EmitCall(OpCodes.Call, method, null);
		}
Пример #7
0
        public void GenerateWriterMethod(Type type, CodeGenContext ctx, ILGenerator il)
        {
            var elemType = type.GetElementType();

            var notNullLabel = il.DefineLabel();

            il.Emit(OpCodes.Ldarg_2);
            il.Emit(OpCodes.Brtrue_S, notNullLabel);

            // if value == null, write 0
            il.Emit(OpCodes.Ldarg_1);
            il.Emit(OpCodes.Ldc_I4_0);
            il.Emit(OpCodes.Tailcall);
            il.Emit(OpCodes.Call, ctx.GetWriterMethodInfo(typeof(uint)));
            il.Emit(OpCodes.Ret);

            il.MarkLabel(notNullLabel);

            // write array len + 1
            il.Emit(OpCodes.Ldarg_1);
            il.Emit(OpCodes.Ldarg_2);
            il.Emit(OpCodes.Ldlen);
            il.Emit(OpCodes.Ldc_I4_1);
            il.Emit(OpCodes.Add);
            il.Emit(OpCodes.Call, ctx.GetWriterMethodInfo(typeof(uint)));

            // declare i
            var idxLocal = il.DeclareLocal(typeof(int));

            // i = 0
            il.Emit(OpCodes.Ldc_I4_0);
            il.Emit(OpCodes.Stloc_S, idxLocal);

            var loopBodyLabel = il.DefineLabel();
            var loopCheckLabel = il.DefineLabel();

            il.Emit(OpCodes.Br_S, loopCheckLabel);

            // loop body
            il.MarkLabel(loopBodyLabel);

            var data = ctx.GetTypeDataForCall(elemType);

            if (data.NeedsInstanceParameter)
                il.Emit(OpCodes.Ldarg_0);

            // write element at index i
            il.Emit(OpCodes.Ldarg_1);
            il.Emit(OpCodes.Ldarg_2);
            il.Emit(OpCodes.Ldloc_S, idxLocal);
            il.Emit(OpCodes.Ldelem, elemType);

            il.Emit(OpCodes.Call, data.WriterMethodInfo);

            // i = i + 1
            il.Emit(OpCodes.Ldloc_S, idxLocal);
            il.Emit(OpCodes.Ldc_I4_1);
            il.Emit(OpCodes.Add);
            il.Emit(OpCodes.Stloc_S, idxLocal);

            il.MarkLabel(loopCheckLabel);

            // loop condition
            il.Emit(OpCodes.Ldloc_S, idxLocal);
            il.Emit(OpCodes.Ldarg_2);
            il.Emit(OpCodes.Ldlen);
            il.Emit(OpCodes.Conv_I4);
            il.Emit(OpCodes.Blt_S, loopBodyLabel);

            il.Emit(OpCodes.Ret);
        }
Пример #8
0
        static void GenSerializerBodyForArray(CodeGenContext ctx, Type type, ILGenerator il)
        {
            var elemType = type.GetElementType();

            var notNullLabel = il.DefineLabel();

            il.Emit(OpCodes.Ldarg_1);
            il.Emit(OpCodes.Brtrue_S, notNullLabel);

            // if value == null, write 0
            il.Emit(OpCodes.Ldarg_0);
            il.Emit(OpCodes.Ldc_I4_0);
            il.EmitCall(OpCodes.Call, ctx.GetWriterMethodInfo(typeof(uint)), null);
            il.Emit(OpCodes.Ret);

            il.MarkLabel(notNullLabel);

            // write array len + 1
            il.Emit(OpCodes.Ldarg_0);
            il.Emit(OpCodes.Ldarg_1);
            il.Emit(OpCodes.Ldlen);
            il.Emit(OpCodes.Ldc_I4_1);
            il.Emit(OpCodes.Add);
            il.EmitCall(OpCodes.Call, ctx.GetWriterMethodInfo(typeof(uint)), null);

            // declare i
            var idxLocal = il.DeclareLocal(typeof(int));

            // i = 0
            il.Emit(OpCodes.Ldc_I4_0);
            il.Emit(OpCodes.Stloc_S, idxLocal);

            var loopBodyLabel  = il.DefineLabel();
            var loopCheckLabel = il.DefineLabel();

            il.Emit(OpCodes.Br_S, loopCheckLabel);

            // loop body
            il.MarkLabel(loopBodyLabel);

            // write element at index i
            il.Emit(OpCodes.Ldarg_0);
            il.Emit(OpCodes.Ldarg_1);
            il.Emit(OpCodes.Ldloc_S, idxLocal);
            il.Emit(OpCodes.Ldelem, elemType);

            GenSerializerCall(ctx, il, elemType);

            // i = i + 1
            il.Emit(OpCodes.Ldloc_S, idxLocal);
            il.Emit(OpCodes.Ldc_I4_1);
            il.Emit(OpCodes.Add);
            il.Emit(OpCodes.Stloc_S, idxLocal);

            il.MarkLabel(loopCheckLabel);

            // loop condition
            il.Emit(OpCodes.Ldloc_S, idxLocal);
            il.Emit(OpCodes.Ldarg_1);
            il.Emit(OpCodes.Ldlen);
            il.Emit(OpCodes.Conv_I4);
            il.Emit(OpCodes.Clt);
            il.Emit(OpCodes.Brtrue_S, loopBodyLabel);

            il.Emit(OpCodes.Ret);
        }
Пример #9
0
        public static void GenerateSerializerSwitch(CodeGenContext ctx, ILGenerator il, IDictionary<Type, TypeData> map)
        {
            // arg0: Stream, arg1: object, arg2: objList

            //================
            Type objStackType = typeof(ObjectList);
            Type objRefType = typeof(NetSerializer.ObjectRef);
            MethodInfo getIndexOfMethod = objStackType.GetMethod("IndexOf", BindingFlags.Public | BindingFlags.Instance, null, new Type[] { typeof(object) }, null);

            var endLabel = il.DefineLabel();

            //==if(objList==null)  goto endLabel;
            il.Emit(OpCodes.Ldarg_2);
            il.Emit(OpCodes.Brfalse_S, endLabel);

            var id = il.DeclareLocal(typeof(int));

            //int id = list.IdentityIndexOf(value);
            il.Emit(OpCodes.Ldarg_2);
            il.Emit(OpCodes.Ldarg_1);
            il.EmitCall(OpCodes.Call, getIndexOfMethod, null);
            il.Emit(OpCodes.Stloc_S, id);

            //if (id == -1) goto endLabel;
            il.Emit(OpCodes.Ldloc_S, id);
            il.Emit(OpCodes.Ldc_I4_M1);
            il.Emit(OpCodes.Beq, endLabel);

            //== value = new ObjectRef(id);
            ConstructorInfo obj_ref_const = objRefType.GetConstructor(BindingFlags.Public | BindingFlags.Instance, null, new Type[] { typeof(int) }, null);
            il.Emit(OpCodes.Ldloc_S, id);
            il.Emit(OpCodes.Newobj, obj_ref_const);
            il.Emit(OpCodes.Box, typeof(ObjectRef));
            il.Emit(OpCodes.Starg, 1);

            il.MarkLabel(endLabel);
            //===============

            var idLocal_typeID = il.DeclareLocal(typeof(uint));

            // get TypeID from object's Type
            var getTypeIDcaseIDMethod = typeof(Serializer).GetMethod("GetTypeIDcaseID", BindingFlags.NonPublic | BindingFlags.Static, null, new Type[] { typeof(object) }, null);
            il.Emit(OpCodes.Ldarg_1);
            il.EmitCall(OpCodes.Call, getTypeIDcaseIDMethod, null);
            il.Emit(OpCodes.Stloc_S, idLocal_typeID);

            // write typeID
            il.Emit(OpCodes.Ldarg_0);
            il.Emit(OpCodes.Ldloc_S, idLocal_typeID);
            il.Emit(OpCodes.Ldc_I4, 0xFFFF);
            il.Emit(OpCodes.And);
            il.Emit(OpCodes.Conv_U2);
            il.Emit(OpCodes.Ldarg_2);
            il.EmitCall(OpCodes.Call, ctx.GetWriterMethodInfo(typeof(ushort)), null);

            // +1 for 0 (null)
            var jumpTable = new Label[map.Count + 1];
            jumpTable[0] = il.DefineLabel();
            foreach (var kvp in map)
                jumpTable[kvp.Value.CaseID] = il.DefineLabel();

            il.Emit(OpCodes.Ldloc_S, idLocal_typeID);
            il.Emit(OpCodes.Ldc_I4, 16);
            il.Emit(OpCodes.Shr_Un);
            il.Emit(OpCodes.Ldc_I4, 0xFFFF);
            il.Emit(OpCodes.And);
            il.Emit(OpCodes.Conv_U2);

            il.Emit(OpCodes.Switch, jumpTable);

            //--			D(il, "eihx");
            ConstructorInfo exceptionCtor = typeof(Exception).GetConstructor(BindingFlags.Public | BindingFlags.Instance, null, new Type[0], null);
            il.Emit(OpCodes.Newobj, exceptionCtor);
            il.Emit(OpCodes.Throw);

            /* null case */
            il.MarkLabel(jumpTable[0]);
            il.Emit(OpCodes.Ret);

            /* cases for types */
            foreach (var kvp in map)
            {
                var type = kvp.Key;
                var data = kvp.Value;

                il.MarkLabel(jumpTable[data.CaseID]);

                il.Emit(OpCodes.Ldarg_0);
                il.Emit(OpCodes.Ldarg_1);
                il.Emit(type.IsValueType ? OpCodes.Unbox_Any : OpCodes.Castclass, type);
                il.Emit(OpCodes.Ldarg_2);

                if (data.WriterMethodInfo.IsGenericMethodDefinition)
                {
                    Debug.Assert(type.IsGenericType);
                    var genArgs = type.GetGenericArguments();
                    il.EmitCall(OpCodes.Call, data.WriterMethodInfo.MakeGenericMethod(genArgs), null);
                }
                else
                {
                    il.EmitCall(OpCodes.Call, data.WriterMethodInfo, null);
                }

                il.Emit(OpCodes.Ret);
            }
        }
Пример #10
0
        static void GenSerializerCall(CodeGenContext ctx, ILGenerator il, Type type)
        {
            // We can call the Serializer method directly for:
            // - Value types
            // - Array types
            // - Sealed types with static Serializer method, as the method will handle null
            // Other reference types go through the SerializesSwitch

            bool direct;

            if (type.IsValueType || type.IsArray)
                direct = true;
            else if (type.IsSealed && ctx.IsDynamic(type) == false)
                direct = true;
            else
                direct = false;

            #if GENERATE_SWITCH
            var method = direct ? ctx.GetWriterMethodInfo(type) : ctx.SerializerSwitchMethodInfo;
            #else
            var method = direct ? ctx.GetWriterMethodInfo(type) : typeof(NetSerializer.Serializer).GetMethod("_SerializerSwitch");
            #endif

            il.EmitCall(OpCodes.Call, method, null);
        }
Пример #11
0
        static void GenSerializerBodyForArray(CodeGenContext ctx, Type type, ILGenerator il)
        {
            var elemType = type.GetElementType();

            var notNullLabel = il.DefineLabel();

            il.Emit(OpCodes.Ldarg_1);
            il.Emit(OpCodes.Brtrue_S, notNullLabel);

            // if value == null, write 0
            il.Emit(OpCodes.Ldarg_0);
            il.Emit(OpCodes.Ldc_I4_0);
            il.Emit(OpCodes.Ldarg_2);
            il.EmitCall(OpCodes.Call, ctx.GetWriterMethodInfo(typeof(uint)), null);
            il.Emit(OpCodes.Ret);

            il.MarkLabel(notNullLabel);

            //==============
            Type objStackType = typeof(ObjectList);
            MethodInfo getAddMethod = objStackType.GetMethod("Add", BindingFlags.Public | BindingFlags.Instance, null, new Type[] { typeof(object) }, null);

            var endLabel = il.DefineLabel();

            //==if(objList==null)  goto endLabel;
            il.Emit(OpCodes.Ldarg_2);
            il.Emit(OpCodes.Brfalse_S, endLabel);

            //== objList.Add(value);
            il.Emit(OpCodes.Ldarg_2);
            il.Emit(OpCodes.Ldarg_1);
            il.EmitCall(OpCodes.Call, getAddMethod, null);

            il.MarkLabel(endLabel);

            //==============
            // write array len + 1
            il.Emit(OpCodes.Ldarg_0);
            il.Emit(OpCodes.Ldarg_1);
            il.Emit(OpCodes.Ldlen);
            il.Emit(OpCodes.Ldc_I4_1);
            il.Emit(OpCodes.Add);
            il.Emit(OpCodes.Ldarg_2);
            il.EmitCall(OpCodes.Call, ctx.GetWriterMethodInfo(typeof(uint)), null);

            // declare i
            var idxLocal = il.DeclareLocal(typeof(int));

            // i = 0
            il.Emit(OpCodes.Ldc_I4_0);
            il.Emit(OpCodes.Stloc_S, idxLocal);

            var loopBodyLabel = il.DefineLabel();
            var loopCheckLabel = il.DefineLabel();

            il.Emit(OpCodes.Br_S, loopCheckLabel);

            // loop body
            il.MarkLabel(loopBodyLabel);

            // write element at index i
            il.Emit(OpCodes.Ldarg_0);
            il.Emit(OpCodes.Ldarg_1);
            il.Emit(OpCodes.Ldloc_S, idxLocal);
            il.Emit(OpCodes.Ldelem, elemType);
            il.Emit(OpCodes.Ldarg_2);

            GenSerializerCall(ctx, il, elemType);

            // i = i + 1
            il.Emit(OpCodes.Ldloc_S, idxLocal);
            il.Emit(OpCodes.Ldc_I4_1);
            il.Emit(OpCodes.Add);
            il.Emit(OpCodes.Stloc_S, idxLocal);

            il.MarkLabel(loopCheckLabel);

            // loop condition
            il.Emit(OpCodes.Ldloc_S, idxLocal);
            il.Emit(OpCodes.Ldarg_1);
            il.Emit(OpCodes.Ldlen);
            il.Emit(OpCodes.Conv_I4);
            il.Emit(OpCodes.Clt);
            il.Emit(OpCodes.Brtrue_S, loopBodyLabel);

            il.Emit(OpCodes.Ret);
        }
Пример #12
0
		public void GenerateWriterMethod(Type type, CodeGenContext ctx, ILGenerator il)
		{
			var elemType = type.GetElementType();

			var notNullLabel = il.DefineLabel();

			il.Emit(OpCodes.Ldarg_1);
			il.Emit(OpCodes.Brtrue_S, notNullLabel);

			// if value == null, write 0
			il.Emit(OpCodes.Ldarg_0);
			il.Emit(OpCodes.Ldc_I4_0);
			il.EmitCall(OpCodes.Call, ctx.GetWriterMethodInfo(typeof(uint)), null);
			il.Emit(OpCodes.Ret);

			il.MarkLabel(notNullLabel);

			// write array len + 1
			il.Emit(OpCodes.Ldarg_0);
			il.Emit(OpCodes.Ldarg_1);
			il.Emit(OpCodes.Ldlen);
			il.Emit(OpCodes.Ldc_I4_1);
			il.Emit(OpCodes.Add);
			il.EmitCall(OpCodes.Call, ctx.GetWriterMethodInfo(typeof(uint)), null);

			// declare i
			var idxLocal = il.DeclareLocal(typeof(int));

			// i = 0
			il.Emit(OpCodes.Ldc_I4_0);
			il.Emit(OpCodes.Stloc_S, idxLocal);

			var loopBodyLabel = il.DefineLabel();
			var loopCheckLabel = il.DefineLabel();

			il.Emit(OpCodes.Br_S, loopCheckLabel);

			// loop body
			il.MarkLabel(loopBodyLabel);

			// write element at index i
			il.Emit(OpCodes.Ldarg_0);
			il.Emit(OpCodes.Ldarg_1);
			il.Emit(OpCodes.Ldloc_S, idxLocal);
			il.Emit(OpCodes.Ldelem, elemType);

			Helpers.GenSerializerCall(ctx, il, elemType);

			// i = i + 1
			il.Emit(OpCodes.Ldloc_S, idxLocal);
			il.Emit(OpCodes.Ldc_I4_1);
			il.Emit(OpCodes.Add);
			il.Emit(OpCodes.Stloc_S, idxLocal);

			il.MarkLabel(loopCheckLabel);

			// loop condition
			il.Emit(OpCodes.Ldloc_S, idxLocal);
			il.Emit(OpCodes.Ldarg_1);
			il.Emit(OpCodes.Ldlen);
			il.Emit(OpCodes.Conv_I4);
			il.Emit(OpCodes.Clt);
			il.Emit(OpCodes.Brtrue_S, loopBodyLabel);

			il.Emit(OpCodes.Ret);
		}
Пример #13
0
        public void GenerateWriterMethod(Type type, CodeGenContext ctx, ILGenerator il)
        {
            var elemType = type.GetElementType();

            var notNullLabel = il.DefineLabel();

            il.Emit(OpCodes.Ldarg_2);
            il.Emit(OpCodes.Brtrue_S, notNullLabel);

            // if value == null, write 0
            il.Emit(OpCodes.Ldarg_1);
            il.Emit(OpCodes.Ldc_I4_0);
            il.Emit(OpCodes.Tailcall);
            il.Emit(OpCodes.Call, ctx.GetWriterMethodInfo(typeof(uint)));
            il.Emit(OpCodes.Ret);

            il.MarkLabel(notNullLabel);

            // write array len + 1
            il.Emit(OpCodes.Ldarg_1);
            il.Emit(OpCodes.Ldarg_2);
            il.Emit(OpCodes.Ldlen);
            il.Emit(OpCodes.Ldc_I4_1);
            il.Emit(OpCodes.Add);
            il.Emit(OpCodes.Call, ctx.GetWriterMethodInfo(typeof(uint)));

            // declare i
            var idxLocal = il.DeclareLocal(typeof(int));

            // i = 0
            il.Emit(OpCodes.Ldc_I4_0);
            il.Emit(OpCodes.Stloc_S, idxLocal);

            var loopBodyLabel  = il.DefineLabel();
            var loopCheckLabel = il.DefineLabel();

            il.Emit(OpCodes.Br_S, loopCheckLabel);

            // loop body
            il.MarkLabel(loopBodyLabel);

            var data = ctx.GetTypeDataForCall(elemType);

            if (data.NeedsInstanceParameter)
            {
                il.Emit(OpCodes.Ldarg_0);
            }

            // write element at index i
            il.Emit(OpCodes.Ldarg_1);
            il.Emit(OpCodes.Ldarg_2);
            il.Emit(OpCodes.Ldloc_S, idxLocal);
            il.Emit(OpCodes.Ldelem, elemType);

            il.Emit(OpCodes.Call, data.WriterMethodInfo);

            // i = i + 1
            il.Emit(OpCodes.Ldloc_S, idxLocal);
            il.Emit(OpCodes.Ldc_I4_1);
            il.Emit(OpCodes.Add);
            il.Emit(OpCodes.Stloc_S, idxLocal);

            il.MarkLabel(loopCheckLabel);

            // loop condition
            il.Emit(OpCodes.Ldloc_S, idxLocal);
            il.Emit(OpCodes.Ldarg_2);
            il.Emit(OpCodes.Ldlen);
            il.Emit(OpCodes.Conv_I4);
            il.Emit(OpCodes.Blt_S, loopBodyLabel);

            il.Emit(OpCodes.Ret);
        }
Пример #14
0
        public void GenerateWriterMethod(Type obtype, CodeGenContext ctx, ILGenerator il)
        {
            var getTypeIDMethodInfo = typeof(Serializer).GetMethod("GetTypeID", BindingFlags.NonPublic | BindingFlags.Instance, null,
                new Type[] { typeof(object) }, null);

            var map = ctx.TypeMap;

            // arg0: Serializer, arg1: Stream, arg2: object

            var idLocal = il.DeclareLocal(typeof(ushort));

            // get TypeID from object's Type
            il.Emit(OpCodes.Ldarg_0);
            il.Emit(OpCodes.Ldarg_2);
            il.Emit(OpCodes.Call, getTypeIDMethodInfo);
            il.Emit(OpCodes.Stloc_S, idLocal);

            // write typeID
            il.Emit(OpCodes.Ldarg_1);
            il.Emit(OpCodes.Ldloc_S, idLocal);
            il.Emit(OpCodes.Call, ctx.GetWriterMethodInfo(typeof(ushort)));

            // +1 for 0 (null)
            var jumpTable = new Label[map.Count + 1];
            jumpTable[0] = il.DefineLabel();
            foreach (var kvp in map)
                jumpTable[kvp.Value.TypeID] = il.DefineLabel();

            il.Emit(OpCodes.Ldloc_S, idLocal);
            il.Emit(OpCodes.Switch, jumpTable);

            il.Emit(OpCodes.Newobj, Helpers.ExceptionCtorInfo);
            il.Emit(OpCodes.Throw);

            /* null case */
            il.MarkLabel(jumpTable[0]);
            il.Emit(OpCodes.Ret);

            /* cases for types */
            foreach (var kvp in map)
            {
                var type = kvp.Key;
                var data = kvp.Value;

                il.MarkLabel(jumpTable[data.TypeID]);

                if (data.NeedsInstanceParameter)
                    il.Emit(OpCodes.Ldarg_0);

                il.Emit(OpCodes.Ldarg_1);
                il.Emit(OpCodes.Ldarg_2);
                il.Emit(type.IsValueType ? OpCodes.Unbox_Any : OpCodes.Castclass, type);

                il.Emit(OpCodes.Tailcall);
                il.Emit(OpCodes.Call, data.WriterMethodInfo);

                il.Emit(OpCodes.Ret);
            }
        }
Пример #15
0
        static void GenerateSerializerSwitch(CodeGenContext ctx, ILGenerator il, IDictionary<Type, TypeData> map)
        {
            // arg0: Stream, arg1: object

            var idLocal = il.DeclareLocal(typeof(ushort));

            // get TypeID from object's Type
            var getTypeIDMethod = typeof(Serializer).GetMethod("GetTypeID", BindingFlags.NonPublic | BindingFlags.Static, null, new Type[] { typeof(object) }, null);
            il.Emit(OpCodes.Ldarg_1);
            il.EmitCall(OpCodes.Call, getTypeIDMethod, null);
            il.Emit(OpCodes.Stloc_S, idLocal);

            // write typeID
            il.Emit(OpCodes.Ldarg_0);
            il.Emit(OpCodes.Ldloc_S, idLocal);
            il.EmitCall(OpCodes.Call, ctx.GetWriterMethodInfo(typeof(ushort)), null);

            // +1 for 0 (null)
            var jumpTable = new Label[map.Count + 1];
            jumpTable[0] = il.DefineLabel();
            foreach (var kvp in map)
                jumpTable[kvp.Value.TypeID] = il.DefineLabel();

            il.Emit(OpCodes.Ldloc_S, idLocal);
            il.Emit(OpCodes.Switch, jumpTable);

            D(il, "eihx");
            il.ThrowException(typeof(Exception));

            /* null case */
            il.MarkLabel(jumpTable[0]);
            il.Emit(OpCodes.Ret);

            /* cases for types */
            foreach (var kvp in map)
            {
                var type = kvp.Key;
                var data = kvp.Value;

                il.MarkLabel(jumpTable[data.TypeID]);

                il.Emit(OpCodes.Ldarg_0);
                il.Emit(OpCodes.Ldarg_1);
                il.Emit(type.IsValueType ? OpCodes.Unbox_Any : OpCodes.Castclass, type);

                if (data.WriterMethodInfo.IsGenericMethodDefinition)
                {
                    Debug.Assert(type.IsGenericType);

                    var genArgs = type.GetGenericArguments();

                    il.EmitCall(OpCodes.Call, data.WriterMethodInfo.MakeGenericMethod(genArgs), null);
                }
                else
                {
                    il.EmitCall(OpCodes.Call, data.WriterMethodInfo, null);
                }

                il.Emit(OpCodes.Ret);
            }
        }
Пример #16
0
        void GenerateDynamic(Dictionary<Type, TypeData> map)
        {
            /* generate stubs */
            foreach (var kvp in map)
            {
                var type = kvp.Key;
                var td = kvp.Value;

                if (!td.IsGenerated)
                    continue;

                td.WriterMethodInfo = Helpers.GenerateDynamicSerializerStub(type);
                td.ReaderMethodInfo = Helpers.GenerateDynamicDeserializerStub(type);
            }

            var ctx = new CodeGenContext(map);

            /* generate bodies */

            foreach (var kvp in map)
            {
                var type = kvp.Key;
                var td = kvp.Value;

                if (!td.IsGenerated)
                    continue;

                var writerDm = (DynamicMethod)td.WriterMethodInfo;
                td.TypeSerializer.GenerateWriterMethod(type, ctx, writerDm.GetILGenerator());

                var readerDm = (DynamicMethod)td.ReaderMethodInfo;
                td.TypeSerializer.GenerateReaderMethod(type, ctx, readerDm.GetILGenerator());
            }

            var writer = (DynamicMethod)ctx.GetWriterMethodInfo(typeof(object));
            var reader = (DynamicMethod)ctx.GetReaderMethodInfo(typeof(object));

            m_serializerSwitch = (SerializerSwitch)writer.CreateDelegate(typeof(SerializerSwitch));
            m_deserializerSwitch = (DeserializerSwitch)reader.CreateDelegate(typeof(DeserializerSwitch));
        }