Beispiel #1
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 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);
        }
        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 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 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);
        }
Beispiel #6
0
        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);
        }
        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);
        }
        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);
        }
        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);
        }
        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);
        }
        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);
        }