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 void GenerateWriterMethod(Type type, CodeGenContext ctx, ILGenerator il)
        {
            // arg0: Serializer, arg1: Stream, arg2: value

            var fields = Helpers.GetFieldInfos(type);

            foreach (var field in fields)
            {
                // Note: the user defined value type is not passed as reference. could cause perf problems with big structs

                var fieldType = field.FieldType;

                var data = ctx.GetTypeDataForCall(fieldType);

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

                il.Emit(OpCodes.Ldarg_1);
                if (type.IsValueType)
                    il.Emit(OpCodes.Ldarga_S, 2);
                else
                    il.Emit(OpCodes.Ldarg_2);
                il.Emit(OpCodes.Ldfld, field);

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

            il.Emit(OpCodes.Ret);
        }
Example #3
0
        static void GenDeserializerBody(CodeGenContext ctx, Type type, ILGenerator il)
        {
            if (type.IsClass)
            {
                // instantiate empty class
                il.Emit(OpCodes.Ldarg_1);

                var gtfh = typeof(Type).GetMethod("GetTypeFromHandle", BindingFlags.Public | BindingFlags.Static);
                var guo = typeof(System.Runtime.Serialization.FormatterServices).GetMethod("GetUninitializedObject", BindingFlags.Public | BindingFlags.Static);
                il.Emit(OpCodes.Ldtoken, type);
                il.Emit(OpCodes.Call, gtfh);
                il.Emit(OpCodes.Call, guo);
                il.Emit(OpCodes.Castclass, type);

                il.Emit(OpCodes.Stind_Ref);
            }

            var fields = GetFieldInfos(type);

            foreach (var field in fields)
            {
                il.Emit(OpCodes.Ldarg_0);
                il.Emit(OpCodes.Ldarg_1);
                if (type.IsClass)
                    il.Emit(OpCodes.Ldind_Ref);
                il.Emit(OpCodes.Ldflda, field);

                GenDeserializerCall(ctx, il, field.FieldType);
            }

            il.Emit(OpCodes.Ret);
        }
        public static void GenerateDeserializerBody(CodeGenContext ctx, Type type, ILGenerator il)
        {
            // arg0: stream, arg1: out value

            if (type.IsArray)
                GenDeserializerBodyForArray(ctx, type, il);
            else
                GenDeserializerBody(ctx, type, il);
        }
Example #5
0
        static void GenerateSerializerBody(CodeGenContext ctx, Type type, ILGenerator il) {
            // arg0: Stream, arg1: value

            D(il, "ser {0}", type.Name);

            if (type.IsArray)
                GenSerializerBodyForArray(ctx, type, il);
            else
                GenSerializerBody(ctx, type, il);
        }
        public void GenerateReaderMethod(Type type, CodeGenContext ctx, ILGenerator il)
        {
            // arg0: Serializer, arg1: stream, arg2: out value

            if (type.IsClass)
            {
                // instantiate empty class
                il.Emit(OpCodes.Ldarg_2);

                var gtfh = typeof(Type).GetMethod("GetTypeFromHandle", BindingFlags.Public | BindingFlags.Static);
                var guo = typeof(System.Runtime.Serialization.FormatterServices).GetMethod("GetUninitializedObject", BindingFlags.Public | BindingFlags.Static);
                il.Emit(OpCodes.Ldtoken, type);
                il.Emit(OpCodes.Call, gtfh);
                il.Emit(OpCodes.Call, guo);
                il.Emit(OpCodes.Castclass, type);

                il.Emit(OpCodes.Stind_Ref);
            }

            var fields = Helpers.GetFieldInfos(type);

            foreach (var field in fields)
            {
                var fieldType = field.FieldType;

                var data = ctx.GetTypeDataForCall(fieldType);

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

                il.Emit(OpCodes.Ldarg_1);
                il.Emit(OpCodes.Ldarg_2);
                if (type.IsClass)
                    il.Emit(OpCodes.Ldind_Ref);
                il.Emit(OpCodes.Ldflda, field);

                il.Emit(OpCodes.Call, data.ReaderMethodInfo);
            }

            if (typeof(System.Runtime.Serialization.IDeserializationCallback).IsAssignableFrom(type))
            {
                var miOnDeserialization = typeof(System.Runtime.Serialization.IDeserializationCallback).GetMethod("OnDeserialization",
                                        BindingFlags.Instance | BindingFlags.Public,
                                        null, new[] { typeof(Object) }, null);

                il.Emit(OpCodes.Ldarg_2);
                il.Emit(OpCodes.Ldnull);
                il.Emit(OpCodes.Constrained, type);
                il.Emit(OpCodes.Callvirt, miOnDeserialization);
            }

            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);
            }
        }
Example #8
0
        static void GenSerializerBody(CodeGenContext ctx, Type type, ILGenerator il) {
            var fields = GetFieldInfos(type);

            foreach (var field in fields) {
                // Note: the user defined value type is not passed as reference. could cause perf problems with big structs

                il.Emit(OpCodes.Ldarg_0);
                if (type.IsValueType)
                    il.Emit(OpCodes.Ldarga_S, 1);
                else
                    il.Emit(OpCodes.Ldarg_1);
                il.Emit(OpCodes.Ldfld, field);

                GenSerializerCall(ctx, il, field.FieldType);
            }

            il.Emit(OpCodes.Ret);
        }
        public void GenerateReaderMethod(Type type, CodeGenContext ctx, ILGenerator il)
        {
            var valueType = type.GetGenericArguments()[0];

            var hasValueLocal = il.DeclareLocal(typeof(bool));
            var valueLocal = il.DeclareLocal(valueType);

            var notNullLabel = il.DefineLabel();

            var data = ctx.GetTypeDataForCall(valueType);

            // read array len
            il.Emit(OpCodes.Ldarg_1);                   // Stream
            il.Emit(OpCodes.Ldloca_S, hasValueLocal);   // &hasValue
            il.Emit(OpCodes.Call, ctx.GetReaderMethodInfo(typeof(bool)));

            // if hasValue == 0, return null
            il.Emit(OpCodes.Ldloc_S, hasValueLocal);
            il.Emit(OpCodes.Brtrue_S, notNullLabel);

            il.Emit(OpCodes.Ldarg_2);       // &value
            il.Emit(OpCodes.Initobj, type);
            il.Emit(OpCodes.Ret);

            // hasValue == 1
            il.MarkLabel(notNullLabel);

            if (data.NeedsInstanceParameter)
                il.Emit(OpCodes.Ldarg_0);   // Serializer
            il.Emit(OpCodes.Ldarg_1);       // Stream
            il.Emit(OpCodes.Ldloca_S, valueLocal);
            il.Emit(OpCodes.Call, data.ReaderMethodInfo);

            il.Emit(OpCodes.Ldarg_2);       // &value

            il.Emit(OpCodes.Ldloc_S, valueLocal);
            var constr = type.GetConstructor(new[] { valueType });
            il.Emit(OpCodes.Newobj, constr);    // new Nullable<T>(valueLocal)

            il.Emit(OpCodes.Stobj, type);       // store to &value

            il.Emit(OpCodes.Ret);
        }
Example #10
0
		public static void GenDeserializerCall(CodeGenContext ctx, ILGenerator il, Type type)
		{
			// We can call the Deserializer method directly for:
			// - Value types
			// - Array types
			// - Sealed types with static Deserializer method, as the method will handle null
			// Other reference types go through the DeserializesSwitch

			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.GetReaderMethodInfo(type) : ctx.DeserializerSwitchMethodInfo;

			il.EmitCall(OpCodes.Call, method, null);
		}
        static void GenSerializerBody(CodeGenContext ctx, Type type, ILGenerator il)
        {
            if (type.IsClass)
            {
                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);
            }

            var fields = Helpers.GetFieldInfos(type);

            foreach (var field in fields)
            {
                // Note: the user defined value type is not passed as reference. could cause perf problems with big structs

                il.Emit(OpCodes.Ldarg_0);
                if (type.IsValueType)
                    il.Emit(OpCodes.Ldarga_S, 1);
                else
                    il.Emit(OpCodes.Ldarg_1);
                il.Emit(OpCodes.Ldfld, field);
                il.Emit(OpCodes.Ldarg_2);

                GenSerializerCall(ctx, il, field.FieldType);
            }

            il.Emit(OpCodes.Ret);
        }
		public void GenerateWriterMethod(Type type, CodeGenContext ctx, ILGenerator il)
		{
			// arg0: Stream, arg1: value

			var fields = Helpers.GetFieldInfos(type);

			foreach (var field in fields)
			{
				// Note: the user defined value type is not passed as reference. could cause perf problems with big structs

				il.Emit(OpCodes.Ldarg_0);
				if (type.IsValueType)
					il.Emit(OpCodes.Ldarga_S, 1);
				else
					il.Emit(OpCodes.Ldarg_1);
				il.Emit(OpCodes.Ldfld, field);

				Helpers.GenSerializerCall(ctx, il, field.FieldType);
			}

			il.Emit(OpCodes.Ret);
		}
        public void GenerateReaderMethod(Type type, CodeGenContext ctx, ILGenerator il)
        {
            var elemType = type.GetElementType();

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

            // read array len
            il.Emit(OpCodes.Ldarg_1);
            il.Emit(OpCodes.Ldloca_S, lenLocal);
            il.Emit(OpCodes.Call, ctx.GetReaderMethodInfo(typeof(uint)));

            var notNullLabel = il.DefineLabel();

            /* if len == 0, return null */
            il.Emit(OpCodes.Ldloc_S, lenLocal);
            il.Emit(OpCodes.Brtrue_S, notNullLabel);

            il.Emit(OpCodes.Ldarg_2);
            il.Emit(OpCodes.Ldnull);
            il.Emit(OpCodes.Stind_Ref);
            il.Emit(OpCodes.Ret);

            il.MarkLabel(notNullLabel);

            var arrLocal = il.DeclareLocal(type);

            // create new array with len - 1
            il.Emit(OpCodes.Ldloc_S, lenLocal);
            il.Emit(OpCodes.Ldc_I4_1);
            il.Emit(OpCodes.Sub);
            il.Emit(OpCodes.Newarr, elemType);
            il.Emit(OpCodes.Stloc_S, arrLocal);

            // 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);

            // read element to arr[i]

            var data = ctx.GetTypeDataForCall(elemType);

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

            il.Emit(OpCodes.Ldarg_1);
            il.Emit(OpCodes.Ldloc_S, arrLocal);
            il.Emit(OpCodes.Ldloc_S, idxLocal);
            il.Emit(OpCodes.Ldelema, elemType);

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

            // 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.Ldloc_S, arrLocal);
            il.Emit(OpCodes.Ldlen);
            il.Emit(OpCodes.Conv_I4);
            il.Emit(OpCodes.Blt_S, loopBodyLabel);


            // store new array to the out value
            il.Emit(OpCodes.Ldarg_2);
            il.Emit(OpCodes.Ldloc_S, arrLocal);
            il.Emit(OpCodes.Stind_Ref);

            il.Emit(OpCodes.Ret);
        }
        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);
        }
Example #15
0
        static void GenerateDeserializerSwitch(CodeGenContext ctx, ILGenerator il, IDictionary<Type, TypeData> map) {
            // arg0: stream, arg1: out object

            D(il, "deser switch");

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

            // read typeID
            il.Emit(OpCodes.Ldarg_0);
            il.Emit(OpCodes.Ldloca_S, idLocal);
            il.EmitCall(OpCodes.Call, ctx.GetReaderMethodInfo(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.Ldarg_1);
            il.Emit(OpCodes.Ldnull);
            il.Emit(OpCodes.Stind_Ref);
            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]);

                var local = il.DeclareLocal(type);

                // call deserializer for this typeID
                il.Emit(OpCodes.Ldarg_0);
                il.Emit(OpCodes.Ldloca_S, local);
                if (data.WriterMethodInfo.IsGenericMethodDefinition) {
                    Debug.Assert(type.IsGenericType);

                    var genArgs = type.GetGenericArguments();

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

                // write result object to out object
                il.Emit(OpCodes.Ldarg_1);
                il.Emit(OpCodes.Ldloc_S, local);
                if (type.IsValueType)
                    il.Emit(OpCodes.Box, type);
                il.Emit(OpCodes.Stind_Ref);

                D(il, "deser switch done");

                il.Emit(OpCodes.Ret);
            }
        }
        static void GenDeserializerBody(CodeGenContext ctx, Type type, ILGenerator il)
        {
            if (type.IsClass)
            {
                // instantiate empty class
                il.Emit(OpCodes.Ldarg_1);

                var gtfh = typeof(Type).GetMethod("GetTypeFromHandle", BindingFlags.Public | BindingFlags.Static);
                var guo = typeof(System.Runtime.Serialization.FormatterServices).GetMethod("GetUninitializedObject", BindingFlags.Public | BindingFlags.Static);
                il.Emit(OpCodes.Ldtoken, type);
                il.Emit(OpCodes.Call, gtfh);
                il.Emit(OpCodes.Call, guo);
                il.Emit(OpCodes.Castclass, type);

                il.Emit(OpCodes.Stind_Ref);

                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);
            }

            var fields = Helpers.GetFieldInfos(type);

            foreach (var field in fields)
            {
                il.Emit(OpCodes.Ldarg_0);
                il.Emit(OpCodes.Ldarg_1);
                if (type.IsClass)
                    il.Emit(OpCodes.Ldind_Ref);
                il.Emit(OpCodes.Ldflda, field);
                il.Emit(OpCodes.Ldarg_2);

                GenDeserializerCall(ctx, il, field.FieldType);
            }

            if (typeof(IDeserializationCallback).IsAssignableFrom(type))
            {
                var miOnDeserialization = typeof(IDeserializationCallback).GetMethod("OnDeserialization",
                                        BindingFlags.Instance | BindingFlags.Public,
                                        null, new[] { typeof(Object) }, null);

                il.Emit(OpCodes.Ldarg_1);
                il.Emit(OpCodes.Ldnull);
                il.Emit(OpCodes.Constrained, type);
                il.Emit(OpCodes.Callvirt, miOnDeserialization);
            }

            il.Emit(OpCodes.Ret);
        }
Example #17
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);
        }
        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);
            }
        }
        static void GenDeserializerCall(CodeGenContext ctx, ILGenerator il, Type type)
        {
            // We can call the Deserializer method directly for:
            // - Value types
            // - Array types
            // - Sealed types with static Deserializer method, as the method will handle null
            // Other reference types go through the DeserializesSwitch

            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.GetReaderMethodInfo(type) : ctx.DeserializerSwitchMethodInfo;
            #else
            var method = direct ? ctx.GetReaderMethodInfo(type) : typeof(NetSerializer.Serializer).GetMethod("_DeserializerSwitch");
            #endif

            il.EmitCall(OpCodes.Call, method, null);
        }
Example #20
0
        static Dictionary <Type, ushort> GenerateDynamic(Type[] types)
        {
            Dictionary <Type, TypeData> map = GenerateTypeData(types);

            var nonStaticTypes = map.Where(kvp => kvp.Value.IsDynamic).Select(kvp => kvp.Key);

            /* generate stubs */
            foreach (var type in nonStaticTypes)
            {
                var dm = SerializerCodegen.GenerateDynamicSerializerStub(type);
                map[type].WriterMethodInfo = dm;
                map[type].WriterILGen      = dm.GetILGenerator();
            }

            foreach (var type in nonStaticTypes)
            {
                var dm = DeserializerCodegen.GenerateDynamicDeserializerStub(type);
                map[type].ReaderMethodInfo = dm;
                map[type].ReaderILGen      = dm.GetILGenerator();
            }

            var serializerSwitchMethod = new DynamicMethod("SerializerSwitch", null,
                                                           new Type[] { typeof(Stream), typeof(object) },
                                                           typeof(Serializer), true);

            serializerSwitchMethod.DefineParameter(1, ParameterAttributes.None, "stream");
            serializerSwitchMethod.DefineParameter(2, ParameterAttributes.None, "value");
            var serializerSwitchMethodInfo = serializerSwitchMethod;

            var deserializerSwitchMethod = new DynamicMethod("DeserializerSwitch", null,
                                                             new Type[] { typeof(Stream), typeof(object).MakeByRefType() },
                                                             typeof(Serializer), true);

            deserializerSwitchMethod.DefineParameter(1, ParameterAttributes.None, "stream");
            deserializerSwitchMethod.DefineParameter(2, ParameterAttributes.Out, "value");
            var deserializerSwitchMethodInfo = deserializerSwitchMethod;

            var ctx = new CodeGenContext(map, serializerSwitchMethodInfo, deserializerSwitchMethodInfo);

            /* generate bodies */
            foreach (var type in nonStaticTypes)
            {
                SerializerCodegen.GenerateSerializerBody(ctx, type, map[type].WriterILGen);
            }

            foreach (var type in nonStaticTypes)
            {
                DeserializerCodegen.GenerateDeserializerBody(ctx, type, map[type].ReaderILGen);
            }

            var ilGen = serializerSwitchMethod.GetILGenerator();

            SerializerCodegen.GenerateSerializerSwitch(ctx, ilGen, map);
            s_serializerSwitch = (SerializerSwitch)serializerSwitchMethod.CreateDelegate(typeof(SerializerSwitch));

            ilGen = deserializerSwitchMethod.GetILGenerator();
            DeserializerCodegen.GenerateDeserializerSwitch(ctx, ilGen, map);
            s_deserializerSwitch = (DeserializerSwitch)deserializerSwitchMethod.CreateDelegate(typeof(DeserializerSwitch));

            return(map.ToDictionary(kvp => kvp.Key, kvp => kvp.Value.TypeID));
        }
        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);
        }
Example #22
0
        static void GenerateDebugAssembly(Dictionary <Type, TypeData> map)
        {
            var ab   = AppDomain.CurrentDomain.DefineDynamicAssembly(new AssemblyName("NetSerializerDebug"), AssemblyBuilderAccess.RunAndSave);
            var modb = ab.DefineDynamicModule("NetSerializerDebug.dll");
            var tb   = modb.DefineType("NetSerializer", TypeAttributes.Public);

            /* generate stubs */
            foreach (var kvp in map)
            {
                var type = kvp.Key;
                var td   = kvp.Value;

                if (!td.IsGenerated)
                {
                    continue;
                }

                var mb = SerializerCodegen.GenerateStaticSerializerStub(tb, type);
                td.WriterMethodInfo = mb;
                td.WriterILGen      = mb.GetILGenerator();

                var dm = DeserializerCodegen.GenerateStaticDeserializerStub(tb, type);
                td.ReaderMethodInfo = dm;
                td.ReaderILGen      = dm.GetILGenerator();
            }

            var serializerSwitchMethod = tb.DefineMethod("SerializerSwitch", MethodAttributes.Public | MethodAttributes.Static, null, new Type[] { typeof(Stream), typeof(object) });

            serializerSwitchMethod.DefineParameter(1, ParameterAttributes.None, "stream");
            serializerSwitchMethod.DefineParameter(2, ParameterAttributes.None, "value");
            var serializerSwitchMethodInfo = serializerSwitchMethod;

            var deserializerSwitchMethod = tb.DefineMethod("DeserializerSwitch", MethodAttributes.Public | MethodAttributes.Static, null, new Type[] { typeof(Stream), typeof(object).MakeByRefType() });

            deserializerSwitchMethod.DefineParameter(1, ParameterAttributes.None, "stream");
            deserializerSwitchMethod.DefineParameter(2, ParameterAttributes.Out, "value");
            var deserializerSwitchMethodInfo = deserializerSwitchMethod;

            var ctx = new CodeGenContext(map, serializerSwitchMethodInfo, deserializerSwitchMethodInfo);

            /* generate bodies */

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

                if (!td.IsGenerated)
                {
                    continue;
                }

                td.TypeSerializer.GenerateWriterMethod(type, ctx, td.WriterILGen);
                td.TypeSerializer.GenerateReaderMethod(type, ctx, td.ReaderILGen);
            }

            var ilGen = serializerSwitchMethod.GetILGenerator();

            SerializerCodegen.GenerateSerializerSwitch(ctx, ilGen, map);

            ilGen = deserializerSwitchMethod.GetILGenerator();
            DeserializerCodegen.GenerateDeserializerSwitch(ctx, ilGen, map);

            tb.CreateType();
            ab.Save("NetSerializerDebug.dll");
        }
Example #23
0
        static 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;
                }

                var writerDm = SerializerCodegen.GenerateDynamicSerializerStub(type);
                td.WriterMethodInfo = writerDm;
                td.WriterILGen      = writerDm.GetILGenerator();

                var readerDm = DeserializerCodegen.GenerateDynamicDeserializerStub(type);
                td.ReaderMethodInfo = readerDm;
                td.ReaderILGen      = readerDm.GetILGenerator();
            }

            var serializerSwitchMethod = new DynamicMethod("SerializerSwitch", null,
                                                           new Type[] { typeof(Stream), typeof(object) },
                                                           typeof(Serializer), true);

            serializerSwitchMethod.DefineParameter(1, ParameterAttributes.None, "stream");
            serializerSwitchMethod.DefineParameter(2, ParameterAttributes.None, "value");
            var serializerSwitchMethodInfo = serializerSwitchMethod;

            var deserializerSwitchMethod = new DynamicMethod("DeserializerSwitch", null,
                                                             new Type[] { typeof(Stream), typeof(object).MakeByRefType() },
                                                             typeof(Serializer), true);

            deserializerSwitchMethod.DefineParameter(1, ParameterAttributes.None, "stream");
            deserializerSwitchMethod.DefineParameter(2, ParameterAttributes.Out, "value");
            var deserializerSwitchMethodInfo = deserializerSwitchMethod;

            var ctx = new CodeGenContext(map, serializerSwitchMethodInfo, deserializerSwitchMethodInfo);

            /* generate bodies */

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

                if (!td.IsGenerated)
                {
                    continue;
                }

                td.TypeSerializer.GenerateWriterMethod(type, ctx, td.WriterILGen);
                td.TypeSerializer.GenerateReaderMethod(type, ctx, td.ReaderILGen);
            }

            var ilGen = serializerSwitchMethod.GetILGenerator();

            SerializerCodegen.GenerateSerializerSwitch(ctx, ilGen, map);
            s_serializerSwitch = (SerializerSwitch)serializerSwitchMethod.CreateDelegate(typeof(SerializerSwitch));

            ilGen = deserializerSwitchMethod.GetILGenerator();
            DeserializerCodegen.GenerateDeserializerSwitch(ctx, ilGen, map);
            s_deserializerSwitch = (DeserializerSwitch)deserializerSwitchMethod.CreateDelegate(typeof(DeserializerSwitch));
        }
        public static void GenerateDeserializerSwitch(CodeGenContext ctx, ILGenerator il, IDictionary <Type, TypeData> map)
        {
            // arg0: stream, arg1: out object

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

            // read typeID
            il.Emit(OpCodes.Ldarg_0);
            il.Emit(OpCodes.Ldloca_S, idLocal);
            il.EmitCall(OpCodes.Call, ctx.GetReaderMethodInfo(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);

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

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

            il.Emit(OpCodes.Ldarg_1);
            il.Emit(OpCodes.Ldnull);
            il.Emit(OpCodes.Stind_Ref);
            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]);

                var local = il.DeclareLocal(type);

                // call deserializer for this typeID
                il.Emit(OpCodes.Ldarg_0);
                if (local.LocalIndex < 256)
                {
                    il.Emit(OpCodes.Ldloca_S, local);
                }
                else
                {
                    il.Emit(OpCodes.Ldloca, local);
                }

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

                // write result object to out object
                il.Emit(OpCodes.Ldarg_1);
                if (local.LocalIndex < 256)
                {
                    il.Emit(OpCodes.Ldloc_S, local);
                }
                else
                {
                    il.Emit(OpCodes.Ldloc, local);
                }
                if (type.IsValueType)
                {
                    il.Emit(OpCodes.Box, type);
                }
                il.Emit(OpCodes.Stind_Ref);

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

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

            // read typeID
            il.Emit(OpCodes.Ldarg_0);
            il.Emit(OpCodes.Ldloca_S, idLocal);
            il.EmitCall(OpCodes.Call, ctx.GetReaderMethodInfo(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.Ldarg_1);
            il.Emit(OpCodes.Ldnull);
            il.Emit(OpCodes.Stind_Ref);
            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]);

                var local = il.DeclareLocal(type);

                // call deserializer for this typeID
                il.Emit(OpCodes.Ldarg_0);
                if (local.LocalIndex < 256)
                    il.Emit(OpCodes.Ldloca_S, local);
                else
                    il.Emit(OpCodes.Ldloca, local);

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

                // write result object to out object
                il.Emit(OpCodes.Ldarg_1);
                if (local.LocalIndex < 256)
                    il.Emit(OpCodes.Ldloc_S, local);
                else
                    il.Emit(OpCodes.Ldloc, local);
                if (type.IsValueType)
                    il.Emit(OpCodes.Box, type);
                il.Emit(OpCodes.Stind_Ref);

                il.Emit(OpCodes.Ret);
            }
        }
Example #26
0
        static void GenerateAssembly(Type[] types)
        {
            Dictionary<Type, TypeData> map = GenerateTypeData(types);

            var nonStaticTypes = map.Where(kvp => kvp.Value.IsDynamic).Select(kvp => kvp.Key);

            var ab = AppDomain.CurrentDomain.DefineDynamicAssembly(new AssemblyName("NetSerializerDebug"), AssemblyBuilderAccess.RunAndSave);
            var modb = ab.DefineDynamicModule("NetSerializerDebug.dll");
            var tb = modb.DefineType("NetSerializer", TypeAttributes.Public);

            /* generate stubs */
            foreach (var type in nonStaticTypes)
            {
                var mb = GenerateStaticSerializerStub(tb, type);
                map[type].WriterMethodInfo = mb;
                map[type].WriterILGen = mb.GetILGenerator();
            }

            foreach (var type in nonStaticTypes)
            {
                var dm = GenerateStaticDeserializerStub(tb, type);
                map[type].ReaderMethodInfo = dm;
                map[type].ReaderILGen = dm.GetILGenerator();
            }

            var serializerSwitchMethod = tb.DefineMethod("SerializerSwitch", MethodAttributes.Public | MethodAttributes.Static, null, new Type[] { typeof(Stream), typeof(object) });
            serializerSwitchMethod.DefineParameter(1, ParameterAttributes.None, "stream");
            serializerSwitchMethod.DefineParameter(2, ParameterAttributes.None, "value");
            var serializerSwitchMethodInfo = serializerSwitchMethod;

            var deserializerSwitchMethod = tb.DefineMethod("DeserializerSwitch", MethodAttributes.Public | MethodAttributes.Static, null, new Type[] { typeof(Stream), typeof(object).MakeByRefType() });
            deserializerSwitchMethod.DefineParameter(1, ParameterAttributes.None, "stream");
            deserializerSwitchMethod.DefineParameter(2, ParameterAttributes.Out, "value");
            var deserializerSwitchMethodInfo = deserializerSwitchMethod;

            var ctx = new CodeGenContext(map, serializerSwitchMethodInfo, deserializerSwitchMethodInfo);

            /* generate bodies */
            foreach (var type in nonStaticTypes)
                GenerateSerializerBody(ctx, type, map[type].WriterILGen);

            foreach (var type in nonStaticTypes)
                GenerateDeserializerBody(ctx, type, map[type].ReaderILGen);

            var ilGen = serializerSwitchMethod.GetILGenerator();
            GenerateSerializerSwitch(ctx, ilGen, map);

            ilGen = deserializerSwitchMethod.GetILGenerator();
            GenerateDeserializerSwitch(ctx, ilGen, map);

            tb.CreateType();
            ab.Save("NetSerializerDebug.dll");
        }
        static void GenDeserializerBodyForArray(CodeGenContext ctx, Type type, ILGenerator il)
        {
            var elemType = type.GetElementType();

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

            // read array len
            il.Emit(OpCodes.Ldarg_0);
            il.Emit(OpCodes.Ldloca_S, lenLocal);
            il.Emit(OpCodes.Ldarg_2);
            il.EmitCall(OpCodes.Call, ctx.GetReaderMethodInfo(typeof(uint)), null);

            var notNullLabel = il.DefineLabel();
            var dataLabel = il.DefineLabel();
            var refLabel = il.DefineLabel();

            /* if len == 0, return null */
            il.Emit(OpCodes.Ldloc_S, lenLocal);
            il.Emit(OpCodes.Brtrue_S, notNullLabel);

            il.Emit(OpCodes.Ldarg_1);
            il.Emit(OpCodes.Ldnull);
            il.Emit(OpCodes.Stind_Ref);
            il.Emit(OpCodes.Ret);

            il.MarkLabel(notNullLabel);

            var arrLocal = il.DeclareLocal(type);

            // create new array with len - 1
            il.Emit(OpCodes.Ldloc_S, lenLocal);
            il.Emit(OpCodes.Ldc_I4_1);
            il.Emit(OpCodes.Sub);
            il.Emit(OpCodes.Newarr, elemType);
            il.Emit(OpCodes.Stloc_S, arrLocal);

            // 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);

            // read element to arr[i]
            il.Emit(OpCodes.Ldarg_0);
            il.Emit(OpCodes.Ldloc_S, arrLocal);
            il.Emit(OpCodes.Ldloc_S, idxLocal);
            il.Emit(OpCodes.Ldelema, elemType);
            il.Emit(OpCodes.Ldarg_2);

            GenDeserializerCall(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.Ldloc_S, arrLocal);
            il.Emit(OpCodes.Ldlen);
            il.Emit(OpCodes.Conv_I4);
            il.Emit(OpCodes.Clt);
            il.Emit(OpCodes.Brtrue_S, loopBodyLabel);

            // store new array to the out value
            il.Emit(OpCodes.Ldarg_1);
            il.Emit(OpCodes.Ldloc_S, arrLocal);
            il.Emit(OpCodes.Stind_Ref);

            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);

            il.Emit(OpCodes.Ret);
        }
Example #28
0
        static void GenDeserializerBodyForArray(CodeGenContext ctx, Type type, ILGenerator il)
        {
            var elemType = type.GetElementType();

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

            // read array len
            il.Emit(OpCodes.Ldarg_0);
            il.Emit(OpCodes.Ldloca_S, lenLocal);
            il.EmitCall(OpCodes.Call, ctx.GetReaderMethodInfo(typeof(uint)), null);

            var notNullLabel = il.DefineLabel();

            /* if len == 0, return null */
            il.Emit(OpCodes.Ldloc_S, lenLocal);
            il.Emit(OpCodes.Brtrue_S, notNullLabel);

            il.Emit(OpCodes.Ldarg_1);
            il.Emit(OpCodes.Ldnull);
            il.Emit(OpCodes.Stind_Ref);
            il.Emit(OpCodes.Ret);

            il.MarkLabel(notNullLabel);

            var arrLocal = il.DeclareLocal(type);

            // create new array with len - 1
            il.Emit(OpCodes.Ldloc_S, lenLocal);
            il.Emit(OpCodes.Ldc_I4_1);
            il.Emit(OpCodes.Sub);
            il.Emit(OpCodes.Newarr, elemType);
            il.Emit(OpCodes.Stloc_S, arrLocal);

            // 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);

            // read element to arr[i]
            il.Emit(OpCodes.Ldarg_0);
            il.Emit(OpCodes.Ldloc_S, arrLocal);
            il.Emit(OpCodes.Ldloc_S, idxLocal);
            il.Emit(OpCodes.Ldelema, elemType);

            GenDeserializerCall(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.Ldloc_S, arrLocal);
            il.Emit(OpCodes.Ldlen);
            il.Emit(OpCodes.Conv_I4);
            il.Emit(OpCodes.Clt);
            il.Emit(OpCodes.Brtrue_S, loopBodyLabel);


            // store new array to the out value
            il.Emit(OpCodes.Ldarg_1);
            il.Emit(OpCodes.Ldloc_S, arrLocal);
            il.Emit(OpCodes.Stind_Ref);

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

            //--			D(il, "deser switch");

            var idLocal_typeID = il.DeclareLocal(typeof(ushort));
            var idLocal_caseID = il.DeclareLocal(typeof(ushort));

            // read typeID
            il.Emit(OpCodes.Ldarg_0);
            il.Emit(OpCodes.Ldloca_S, idLocal_typeID);
            il.Emit(OpCodes.Ldarg_2);
            il.EmitCall(OpCodes.Call, ctx.GetReaderMethodInfo(typeof(ushort)), null);

            // get CaseID from  TypeID
            var getCaseIDMethod = typeof(Serializer).GetMethod("GetCaseID", BindingFlags.NonPublic | BindingFlags.Static, null, new Type[] { typeof(ushort) }, null);
            il.Emit(OpCodes.Ldloc_S, idLocal_typeID);
            il.EmitCall(OpCodes.Call, getCaseIDMethod, null);
            il.Emit(OpCodes.Stloc_S, idLocal_caseID);

            // +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_caseID);
            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.Ldarg_1);
            il.Emit(OpCodes.Ldnull);
            il.Emit(OpCodes.Stind_Ref);
            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]);

                var local = il.DeclareLocal(type);

                // call deserializer for this typeID
                il.Emit(OpCodes.Ldarg_0);
                if (local.LocalIndex < 256)
                    il.Emit(OpCodes.Ldloca_S, local);
                else
                    il.Emit(OpCodes.Ldloca, local);
                il.Emit(OpCodes.Ldarg_2);

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

                if (type == typeof(ObjectRef))
                {
                    // get Object by Ref and write found object to out object
                    var getGetAt = typeof(ObjectList).GetMethod("GetAt", BindingFlags.Public | BindingFlags.Instance, null, new Type[] { typeof(ObjectRef) }, null);

                    var nullLabel = il.DefineLabel();

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

                    //== value = objList.GetAt(obj.obj_ref);
                    il.Emit(OpCodes.Ldarg_1);
                    il.Emit(OpCodes.Ldarg_2);
                    il.Emit(OpCodes.Ldloc_S, local);
                    il.EmitCall(OpCodes.Call, getGetAt, null);
                    il.Emit(OpCodes.Stind_Ref);
                    il.Emit(OpCodes.Ret);

                    il.MarkLabel(nullLabel);

                    //== value = null;
                    il.Emit(OpCodes.Ldarg_1);
                    il.Emit(OpCodes.Ldnull);
                    il.Emit(OpCodes.Stind_Ref);

                }
                else
                {
                    // write result object to out object
                    il.Emit(OpCodes.Ldarg_1);
                    if (local.LocalIndex < 256)
                        il.Emit(OpCodes.Ldloc_S, local);
                    else
                        il.Emit(OpCodes.Ldloc, local);

                    if (type.IsValueType)
                        il.Emit(OpCodes.Box, type);
                    il.Emit(OpCodes.Stind_Ref);
                }

                //--				D(il, "deser switch done");

                il.Emit(OpCodes.Ret);
            }
        }
Example #30
0
		static void GenerateDebugAssembly(Dictionary<Type, TypeData> map)
		{
			var ab = AppDomain.CurrentDomain.DefineDynamicAssembly(new AssemblyName("NetSerializerDebug"), AssemblyBuilderAccess.RunAndSave);
			var modb = ab.DefineDynamicModule("NetSerializerDebug.dll");
			var tb = modb.DefineType("NetSerializer", TypeAttributes.Public);

			/* generate stubs */
			foreach (var kvp in map)
			{
				var type = kvp.Key;
				var td = kvp.Value;

				if (!td.IsGenerated)
					continue;

				var mb = SerializerCodegen.GenerateStaticSerializerStub(tb, type);
				td.WriterMethodInfo = mb;
				td.WriterILGen = mb.GetILGenerator();

				var dm = DeserializerCodegen.GenerateStaticDeserializerStub(tb, type);
				td.ReaderMethodInfo = dm;
				td.ReaderILGen = dm.GetILGenerator();
			}

			var serializerSwitchMethod = tb.DefineMethod("SerializerSwitch", MethodAttributes.Public | MethodAttributes.Static, null, new Type[] { typeof(Stream), typeof(object) });
			serializerSwitchMethod.DefineParameter(1, ParameterAttributes.None, "stream");
			serializerSwitchMethod.DefineParameter(2, ParameterAttributes.None, "value");
			var serializerSwitchMethodInfo = serializerSwitchMethod;

			var deserializerSwitchMethod = tb.DefineMethod("DeserializerSwitch", MethodAttributes.Public | MethodAttributes.Static, null, new Type[] { typeof(Stream), typeof(object).MakeByRefType() });
			deserializerSwitchMethod.DefineParameter(1, ParameterAttributes.None, "stream");
			deserializerSwitchMethod.DefineParameter(2, ParameterAttributes.Out, "value");
			var deserializerSwitchMethodInfo = deserializerSwitchMethod;

			var ctx = new CodeGenContext(map, serializerSwitchMethodInfo, deserializerSwitchMethodInfo);

			/* generate bodies */

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

				if (!td.IsGenerated)
					continue;

				td.TypeSerializer.GenerateWriterMethod(type, ctx, td.WriterILGen);
				td.TypeSerializer.GenerateReaderMethod(type, ctx, td.ReaderILGen);
			}

			var ilGen = serializerSwitchMethod.GetILGenerator();
			SerializerCodegen.GenerateSerializerSwitch(ctx, ilGen, map);

			ilGen = deserializerSwitchMethod.GetILGenerator();
			DeserializerCodegen.GenerateDeserializerSwitch(ctx, ilGen, map);

			tb.CreateType();
			ab.Save("NetSerializerDebug.dll");
		}
Example #31
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");
            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);

                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);
            }
        }
Example #32
0
        static Dictionary<Type, TypeData> GenerateDynamic(Type[] types, Dictionary<Type, TypeData> typeMap)
        {
            Dictionary<Type, TypeData> _map = GenerateTypeData(types);
            Dictionary<Type, TypeData> map = typeMap.Concat(_map).ToDictionary(kvp => kvp.Key, kvp => kvp.Value);

            var nonStaticTypes = map.Where(kvp => kvp.Value.IsDynamic).Select(kvp => kvp.Key);

            /* generate stubs */
            foreach (var type in nonStaticTypes)
            {
                var s_dm = SerializerCodegen.GenerateDynamicSerializerStub(type);
                var typeData = map[type];
                typeData.WriterMethodInfo = s_dm;
                typeData.WriterILGen = s_dm.GetILGenerator();

                var d_dm = DeserializerCodegen.GenerateDynamicDeserializerStub(type);
                typeData.ReaderMethodInfo = d_dm;
                typeData.ReaderILGen = d_dm.GetILGenerator();
            }

            #if GENERATE_SWITCH
            var serializerSwitchMethod = new DynamicMethod("SerializerSwitch", null,
                new Type[] { typeof(Stream), typeof(object), typeof(ObjectList) },
                typeof(Serializer), true);
            serializerSwitchMethod.DefineParameter(1, ParameterAttributes.None, "stream");
            serializerSwitchMethod.DefineParameter(2, ParameterAttributes.None, "value");
            serializerSwitchMethod.DefineParameter(3, ParameterAttributes.None, "objList");
            var serializerSwitchMethodInfo = serializerSwitchMethod;

            var deserializerSwitchMethod = new DynamicMethod("DeserializerSwitch", null,
                new Type[] { typeof(Stream), typeof(object).MakeByRefType(), typeof(ObjectList) },
                typeof(Serializer), true);
            deserializerSwitchMethod.DefineParameter(1, ParameterAttributes.None, "stream");
            deserializerSwitchMethod.DefineParameter(2, ParameterAttributes.Out, "value");
            deserializerSwitchMethod.DefineParameter(3, ParameterAttributes.Out, "objList");
            var deserializerSwitchMethodInfo = deserializerSwitchMethod;

            var ctx = new CodeGenContext(map, serializerSwitchMethodInfo, deserializerSwitchMethodInfo);
            #else
            var ctx = new CodeGenContext(map);
            #endif

            /* generate bodies */
            foreach (var type in nonStaticTypes)
            {
                SerializerCodegen.GenerateSerializerBody(ctx, type, map[type].WriterILGen);
                DeserializerCodegen.GenerateDeserializerBody(ctx, type, map[type].ReaderILGen);
            }

            #if GENERATE_SWITCH
            var ilGen = serializerSwitchMethod.GetILGenerator();
            SerializerCodegen.GenerateSerializerSwitch(ctx, ilGen, map);
            s_serializerSwitch = (SerializerSwitch)serializerSwitchMethod.CreateDelegate(typeof(SerializerSwitch));

            ilGen = deserializerSwitchMethod.GetILGenerator();
            DeserializerCodegen.GenerateDeserializerSwitch(ctx, ilGen, map);
            s_deserializerSwitch = (DeserializerSwitch)deserializerSwitchMethod.CreateDelegate(typeof(DeserializerSwitch));
            #else
            foreach (var kvp in map)
            {
                kvp.Value.serializer = GetSerializationInvoker(null, kvp.Value.WriterMethodInfo, kvp.Key, (int)kvp.Value.TypeID);
                kvp.Value.deserializer = GetDeserializationInvoker(null, kvp.Value.ReaderMethodInfo, kvp.Key, (int)kvp.Value.TypeID);
            }
            #endif

            return map;
        }
Example #33
0
        static void GenerateDeserializerSwitch(CodeGenContext ctx, ILGenerator il, IDictionary <Type, TypeData> map)
        {
            // arg0: stream, arg1: out object

            D(il, "deser switch");

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

            // read typeID
            il.Emit(OpCodes.Ldarg_0);
            il.Emit(OpCodes.Ldloca_S, idLocal);
            il.EmitCall(OpCodes.Call, ctx.GetReaderMethodInfo(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.Ldarg_1);
            il.Emit(OpCodes.Ldnull);
            il.Emit(OpCodes.Stind_Ref);
            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]);

                var local = il.DeclareLocal(type);

                // call deserializer for this typeID
                il.Emit(OpCodes.Ldarg_0);
                il.Emit(OpCodes.Ldloca_S, local);
                if (data.WriterMethodInfo.IsGenericMethodDefinition)
                {
                    Debug.Assert(type.IsGenericType);

                    var genArgs = type.GetGenericArguments();

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

                // write result object to out object
                il.Emit(OpCodes.Ldarg_1);
                il.Emit(OpCodes.Ldloc_S, local);
                if (type.IsValueType)
                {
                    il.Emit(OpCodes.Box, type);
                }
                il.Emit(OpCodes.Stind_Ref);

                D(il, "deser switch done");

                il.Emit(OpCodes.Ret);
            }
        }
Example #34
0
        static Dictionary<Type, uint> s_Type_caseIDtypeIDMap; // Type => (typeID | (caseID << 16))

        #endif

        #if GENERATE_DEBUGGING_ASSEMBLY

        static void GenerateAssembly(Type[] types, Dictionary<Type, TypeData> typeMap)
        {
            Dictionary<Type, TypeData> _map = GenerateTypeData(types);
            Dictionary<Type, TypeData> map = typeMap.Concat(_map).ToDictionary(kvp => kvp.Key, kvp => kvp.Value);

            var nonStaticTypes = map.Where(kvp => kvp.Value.IsDynamic).Select(kvp => kvp.Key);

            var ab = AppDomain.CurrentDomain.DefineDynamicAssembly(new AssemblyName("NetSerializerDebug"), AssemblyBuilderAccess.RunAndSave);
            var modb = ab.DefineDynamicModule("NetSerializerDebug.dll");
            var tb = modb.DefineType("NetSerializer", TypeAttributes.Public);

            /* generate stubs */
            foreach (var type in nonStaticTypes)
            {
                var mb = SerializerCodegen.GenerateStaticSerializerStub(tb, type);
                map[type].WriterMethodInfo = mb;
                map[type].WriterILGen = mb.GetILGenerator();
            }

            foreach (var type in nonStaticTypes)
            {
                var dm = DeserializerCodegen.GenerateStaticDeserializerStub(tb, type);
                map[type].ReaderMethodInfo = dm;
                map[type].ReaderILGen = dm.GetILGenerator();
            }

            #if GENERATE_SWITCH
            var serializerSwitchMethod = tb.DefineMethod("SerializerSwitch", MethodAttributes.Public | MethodAttributes.Static, null, new Type[] { typeof(Stream), typeof(object), typeof(ObjectList) });
            serializerSwitchMethod.DefineParameter(1, ParameterAttributes.None, "stream");
            serializerSwitchMethod.DefineParameter(2, ParameterAttributes.None, "value");
            serializerSwitchMethod.DefineParameter(3, ParameterAttributes.None, "objList");
            var serializerSwitchMethodInfo = serializerSwitchMethod;

            var deserializerSwitchMethod = tb.DefineMethod("DeserializerSwitch", MethodAttributes.Public | MethodAttributes.Static, null, new Type[] { typeof(Stream), typeof(object).MakeByRefType(), typeof(ObjectList) });
            deserializerSwitchMethod.DefineParameter(1, ParameterAttributes.None, "stream");
            deserializerSwitchMethod.DefineParameter(2, ParameterAttributes.Out, "value");
            deserializerSwitchMethod.DefineParameter(3, ParameterAttributes.None, "objList");
            var deserializerSwitchMethodInfo = deserializerSwitchMethod;

            var ctx = new CodeGenContext(map, serializerSwitchMethodInfo, deserializerSwitchMethodInfo);
            #else
            var ctx = new CodeGenContext(map);
            #endif

            /* generate bodies */
            foreach (var type in nonStaticTypes)
            {
                SerializerCodegen.GenerateSerializerBody(ctx, type, map[type].WriterILGen);
                DeserializerCodegen.GenerateDeserializerBody(ctx, type, map[type].ReaderILGen);
            }

            #if GENERATE_SWITCH
            var ilGen = serializerSwitchMethod.GetILGenerator();
            SerializerCodegen.GenerateSerializerSwitch(ctx, ilGen, map);

            ilGen = deserializerSwitchMethod.GetILGenerator();
            DeserializerCodegen.GenerateDeserializerSwitch(ctx, ilGen, map);
            #else
            foreach (var kvp in map)
            {
                GetSerializationInvoker(tb, kvp.Value.WriterMethodInfo, kvp.Key, (int)kvp.Value.TypeID);
                GetDeserializationInvoker(tb, kvp.Value.ReaderMethodInfo, kvp.Key, (int)kvp.Value.TypeID);
            }
            #endif
            tb.CreateType();
            ab.Save("NetSerializerDebug.dll");
            SerializationID.userID = SerializationID.userIDstart;
        }
        public void GenerateReaderMethod(Type type, CodeGenContext ctx, ILGenerator il)
        {
            var elemType = type.GetElementType();

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

            // read array len
            il.Emit(OpCodes.Ldarg_1);
            il.Emit(OpCodes.Ldloca_S, lenLocal);
            il.Emit(OpCodes.Call, ctx.GetReaderMethodInfo(typeof(uint)));

            var notNullLabel = il.DefineLabel();

            /* if len == 0, return null */
            il.Emit(OpCodes.Ldloc_S, lenLocal);
            il.Emit(OpCodes.Brtrue_S, notNullLabel);

            il.Emit(OpCodes.Ldarg_2);
            il.Emit(OpCodes.Ldnull);
            il.Emit(OpCodes.Stind_Ref);
            il.Emit(OpCodes.Ret);

            il.MarkLabel(notNullLabel);

            var arrLocal = il.DeclareLocal(type);

            // create new array with len - 1
            il.Emit(OpCodes.Ldloc_S, lenLocal);
            il.Emit(OpCodes.Ldc_I4_1);
            il.Emit(OpCodes.Sub);
            il.Emit(OpCodes.Newarr, elemType);
            il.Emit(OpCodes.Stloc_S, arrLocal);

            // 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);

            // read element to arr[i]

            var data = ctx.GetTypeDataForCall(elemType);

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

            il.Emit(OpCodes.Ldarg_1);
            il.Emit(OpCodes.Ldloc_S, arrLocal);
            il.Emit(OpCodes.Ldloc_S, idxLocal);
            il.Emit(OpCodes.Ldelema, elemType);

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

            // 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.Ldloc_S, arrLocal);
            il.Emit(OpCodes.Ldlen);
            il.Emit(OpCodes.Conv_I4);
            il.Emit(OpCodes.Blt_S, loopBodyLabel);

            // store new array to the out value
            il.Emit(OpCodes.Ldarg_2);
            il.Emit(OpCodes.Ldloc_S, arrLocal);
            il.Emit(OpCodes.Stind_Ref);

            il.Emit(OpCodes.Ret);
        }
        static void GenDeserializerBody(CodeGenContext ctx, Type type, ILGenerator il)
        {
            if (type.IsClass)
            {
                // instantiate empty class
                il.Emit(OpCodes.Ldarg_1);

                var gtfh = typeof(Type).GetMethod("GetTypeFromHandle", BindingFlags.Public | BindingFlags.Static);
                var guo = typeof(System.Runtime.Serialization.FormatterServices).GetMethod("GetUninitializedObject", BindingFlags.Public | BindingFlags.Static);
                il.Emit(OpCodes.Ldtoken, type);
                il.Emit(OpCodes.Call, gtfh);
                il.Emit(OpCodes.Call, guo);
                il.Emit(OpCodes.Castclass, type);

                il.Emit(OpCodes.Stind_Ref);
            }

            var fields = Helpers.GetFieldInfos(type);

            foreach (var field in fields)
            {
                il.Emit(OpCodes.Ldarg_0);
                il.Emit(OpCodes.Ldarg_1);
                if (type.IsClass)
                    il.Emit(OpCodes.Ldind_Ref);
                il.Emit(OpCodes.Ldflda, field);

                GenDeserializerCall(ctx, il, field.FieldType);
            }

            if (typeof(IDeserializationCallback).IsAssignableFrom(type))
            {
                var miOnDeserialization = typeof(IDeserializationCallback).GetMethod("OnDeserialization",
                                        BindingFlags.Instance | BindingFlags.Public,
                                        null, new[] { typeof(Object) }, null);

                il.Emit(OpCodes.Ldarg_1);
                il.Emit(OpCodes.Ldnull);
                il.Emit(OpCodes.Constrained, type);
                il.Emit(OpCodes.Callvirt, miOnDeserialization);
            }

            il.Emit(OpCodes.Ret);
        }
Example #37
0
        static void GenDeserializerBodyForArray(CodeGenContext ctx, Type type, ILGenerator il) {
            var elemType = type.GetElementType();

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

            // read array len
            il.Emit(OpCodes.Ldarg_0);
            il.Emit(OpCodes.Ldloca_S, lenLocal);
            il.EmitCall(OpCodes.Call, ctx.GetReaderMethodInfo(typeof(uint)), null);

            var notNullLabel = il.DefineLabel();

            /* if len == 0, return null */
            il.Emit(OpCodes.Ldloc_S, lenLocal);
            il.Emit(OpCodes.Brtrue_S, notNullLabel);

            il.Emit(OpCodes.Ldarg_1);
            il.Emit(OpCodes.Ldnull);
            il.Emit(OpCodes.Stind_Ref);
            il.Emit(OpCodes.Ret);

            il.MarkLabel(notNullLabel);

            var arrLocal = il.DeclareLocal(type);

            // create new array with len - 1
            il.Emit(OpCodes.Ldloc_S, lenLocal);
            il.Emit(OpCodes.Ldc_I4_1);
            il.Emit(OpCodes.Sub);
            il.Emit(OpCodes.Newarr, elemType);
            il.Emit(OpCodes.Stloc_S, arrLocal);

            // 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);

            // read element to arr[i]
            il.Emit(OpCodes.Ldarg_0);
            il.Emit(OpCodes.Ldloc_S, arrLocal);
            il.Emit(OpCodes.Ldloc_S, idxLocal);
            il.Emit(OpCodes.Ldelema, elemType);

            GenDeserializerCall(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.Ldloc_S, arrLocal);
            il.Emit(OpCodes.Ldlen);
            il.Emit(OpCodes.Conv_I4);
            il.Emit(OpCodes.Clt);
            il.Emit(OpCodes.Brtrue_S, loopBodyLabel);


            // store new array to the out value
            il.Emit(OpCodes.Ldarg_1);
            il.Emit(OpCodes.Ldloc_S, arrLocal);
            il.Emit(OpCodes.Stind_Ref);

            il.Emit(OpCodes.Ret);
        }
        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);
        }
Example #39
0
        static Dictionary<Type, ushort> GenerateDynamic(Type[] types)
        {
            Dictionary<Type, TypeData> map = GenerateTypeData(types);

            var nonStaticTypes = map.Where(kvp => kvp.Value.IsDynamic).Select(kvp => kvp.Key);

            /* generate stubs */
            foreach (var type in nonStaticTypes)
            {
                var dm = GenerateDynamicSerializerStub(type);
                map[type].WriterMethodInfo = dm;
                map[type].WriterILGen = dm.GetILGenerator();
            }

            foreach (var type in nonStaticTypes)
            {
                var dm = GenerateDynamicDeserializerStub(type);
                map[type].ReaderMethodInfo = dm;
                map[type].ReaderILGen = dm.GetILGenerator();
            }

            var serializerSwitchMethod = new DynamicMethod("SerializerSwitch", null,
                new Type[] { typeof(Stream), typeof(object) },
                typeof(Serializer), true);
            serializerSwitchMethod.DefineParameter(1, ParameterAttributes.None, "stream");
            serializerSwitchMethod.DefineParameter(2, ParameterAttributes.None, "value");
            var serializerSwitchMethodInfo = serializerSwitchMethod;

            var deserializerSwitchMethod = new DynamicMethod("DeserializerSwitch", null,
                new Type[] { typeof(Stream), typeof(object).MakeByRefType() },
                typeof(Serializer), true);
            deserializerSwitchMethod.DefineParameter(1, ParameterAttributes.None, "stream");
            deserializerSwitchMethod.DefineParameter(2, ParameterAttributes.Out, "value");
            var deserializerSwitchMethodInfo = deserializerSwitchMethod;

            var ctx = new CodeGenContext(map, serializerSwitchMethodInfo, deserializerSwitchMethodInfo);

            /* generate bodies */
            foreach (var type in nonStaticTypes)
                GenerateSerializerBody(ctx, type, map[type].WriterILGen);

            foreach (var type in nonStaticTypes)
                GenerateDeserializerBody(ctx, type, map[type].ReaderILGen);

            var ilGen = serializerSwitchMethod.GetILGenerator();
            GenerateSerializerSwitch(ctx, ilGen, map);
            s_serializerSwitch = (SerializerSwitch)serializerSwitchMethod.CreateDelegate(typeof(SerializerSwitch));

            ilGen = deserializerSwitchMethod.GetILGenerator();
            GenerateDeserializerSwitch(ctx, ilGen, map);
            s_deserializerSwitch = (DeserializerSwitch)deserializerSwitchMethod.CreateDelegate(typeof(DeserializerSwitch));

            return map.ToDictionary(kvp => kvp.Key, kvp => kvp.Value.TypeID);
        }
Example #40
0
		static 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;

				var writerDm = SerializerCodegen.GenerateDynamicSerializerStub(type);
				td.WriterMethodInfo = writerDm;
				td.WriterILGen = writerDm.GetILGenerator();

				var readerDm = DeserializerCodegen.GenerateDynamicDeserializerStub(type);
				td.ReaderMethodInfo = readerDm;
				td.ReaderILGen = readerDm.GetILGenerator();
			}

			var serializerSwitchMethod = new DynamicMethod("SerializerSwitch", null,
				new Type[] { typeof(Stream), typeof(object) },
				typeof(Serializer), true);
			serializerSwitchMethod.DefineParameter(1, ParameterAttributes.None, "stream");
			serializerSwitchMethod.DefineParameter(2, ParameterAttributes.None, "value");
			var serializerSwitchMethodInfo = serializerSwitchMethod;

			var deserializerSwitchMethod = new DynamicMethod("DeserializerSwitch", null,
				new Type[] { typeof(Stream), typeof(object).MakeByRefType() },
				typeof(Serializer), true);
			deserializerSwitchMethod.DefineParameter(1, ParameterAttributes.None, "stream");
			deserializerSwitchMethod.DefineParameter(2, ParameterAttributes.Out, "value");
			var deserializerSwitchMethodInfo = deserializerSwitchMethod;

			var ctx = new CodeGenContext(map, serializerSwitchMethodInfo, deserializerSwitchMethodInfo);

			/* generate bodies */

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

				if (!td.IsGenerated)
					continue;

				td.TypeSerializer.GenerateWriterMethod(type, ctx, td.WriterILGen);
				td.TypeSerializer.GenerateReaderMethod(type, ctx, td.ReaderILGen);
			}

			var ilGen = serializerSwitchMethod.GetILGenerator();
			SerializerCodegen.GenerateSerializerSwitch(ctx, ilGen, map);
			s_serializerSwitch = (SerializerSwitch)serializerSwitchMethod.CreateDelegate(typeof(SerializerSwitch));

			ilGen = deserializerSwitchMethod.GetILGenerator();
			DeserializerCodegen.GenerateDeserializerSwitch(ctx, ilGen, map);
			s_deserializerSwitch = (DeserializerSwitch)deserializerSwitchMethod.CreateDelegate(typeof(DeserializerSwitch));
		}