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