protected override void ReadNotEmpty(ReaderMethodBuilderContext context) { context.IncreaseIndexBy1(); context.AssertTypeCode(GroBufTypeCode.DateTimeOffset); // Assert typeCode == TypeCode.DateTimeOffset var il = context.Il; context.LoadResultByRef(); // stack: [ref result] il.Dup(); // stack: [ref result, ref result] il.Initobj(Type); // result = default(DateTimeOffset); stack: [ref result] context.LoadData(); // stack: [ref result, data] context.LoadIndexByRef(); // stack: [ref result, data, ref index] var dateTime = il.DeclareLocal(typeof(DateTime)); il.Ldloca(dateTime); // stack: [ref result, data, ref index, ref dateTime] context.LoadContext(); // stack: [ref result, data, ref index, ref dateTime, context] context.CallReader(typeof(DateTime)); // reader(pinnedData, ref index, ref dateTime, context); stack: [ref result] il.Dup(); // stack: [ref result, ref result] il.Ldloc(dateTime); // stack: [ref result, ref result, dateTime] il.Stfld(Type.GetField("m_dateTime", BindingFlags.Instance | BindingFlags.NonPublic)); // result.m_dateTime = dateTime; stack: [ref result] context.LoadData(); // stack: [ref result, data] context.LoadIndexByRef(); // stack: [ref result, data, ref index] var offset = il.DeclareLocal(typeof(short)); il.Ldloca(offset); // stack: [ref result, data, ref index, ref offset] context.LoadContext(); // stack: [ref result, data, ref index, ref offset, context] context.CallReader(typeof(short)); // reader(pinnedData, ref index, ref offset, context); stack: [ref result] il.Ldloc(offset); // stack: [ref result, ref result, offset] il.Stfld(Type.GetField("m_offsetMinutes", BindingFlags.Instance | BindingFlags.NonPublic)); // result.m_offsetMinutes = offset; stack: [ref result] }
private static KeyValuePair <Delegate, IntPtr> GetReader(ReaderMethodBuilderContext context, Type type) { var method = new DynamicMethod("Read_" + type.Name + "_AndCastToObject_" + Guid.NewGuid(), typeof(void), new[] { typeof(IntPtr), typeof(int).MakeByRefType(), typeof(object).MakeByRefType(), typeof(ReaderContext) }, context.Context.Module, true); using (var il = new GroboIL(method)) { il.Ldarg(2); // stack: [ref result] il.Ldarg(0); // stack: [ref result, data] il.Ldarg(1); // stack: [ref result, data, ref index] var value = il.DeclareLocal(type); il.Ldloca(value); // stack: [ref result, data, ref index, ref value] il.Ldarg(3); // stack: [ref result, data, ref index, ref value, context] ReaderMethodBuilderContext.CallReader(il, type, context.Context); il.Ldloc(value); // stack: [ref result, value] if (type.IsValueType) { il.Box(type); // stack: [ref result, (object)value] } else { il.Castclass(type); } il.Stind(typeof(object)); // result = (object)value il.Ret(); } var @delegate = method.CreateDelegate(typeof(ReaderDelegate)); return(new KeyValuePair <Delegate, IntPtr>(@delegate, GroBufHelpers.ExtractDynamicMethodPointer(method))); }
protected override void ReadNotEmpty(ReaderMethodBuilderContext context) { var il = context.Il; context.LoadResultByRef(); // stack: [ref result] context.LoadData(); // stack: [ref result, data] context.LoadIndexByRef(); // stack: [ref result, data, ref index] var value = il.DeclareLocal(typeof(byte[])); il.Ldloca(value); // stack: [ref result, data, ref index, ref value] context.LoadContext(); // stack: [ref result, data, ref index, ref value, context] context.CallReader(typeof(byte[])); // reader(pinnedData, ref index, ref value, context); stack: [ref result] il.Ldloc(value); // stack: [ref result, value] var constructor = Type.GetConstructor(new[] { typeof(byte[]) }); if (constructor == null) { throw new MissingConstructorException(Type, typeof(byte[])); } il.Newobj(constructor); // stack: [ref result, new IPAddress(value)] il.Stind(Type); // result = new IPAddress(value) }
protected override void ReadNotEmpty(ReaderMethodBuilderContext context) { var il = context.Il; context.AssertTypeCode(GroBufTypeCode.Tuple); context.IncreaseIndexBy1(); var length = context.Length; il.Ldc_I4(4); context.AssertLength(); context.GoToCurrentLocation(); // stack: [&data[index]] il.Ldind(typeof(uint)); // stack: [data length] context.IncreaseIndexBy4(); // index = index + 4; stack: [array length] il.Stloc(length); // length = array length; stack: [] context.LoadResultByRef(); // stack: [ref result] var genericArguments = Type.GetGenericArguments(); // stack: [ref result, args] for (int i = 0; i < genericArguments.Length; ++i) { context.LoadData(); // stack: [ref result, args, data] context.LoadIndexByRef(); // stack: [ref result, args, data, ref index] var arg = il.DeclareLocal(genericArguments[i]); il.Ldloca(arg); // stack: [ref result, args, data, ref index, ref arg] context.LoadContext(); // stack: [ref result, args, data, ref index, ref arg, context] context.CallReader(genericArguments[i]); // reader(pinnedData, ref index, ref arg, context); stack: [ref result, args] il.Ldloc(arg); // stack: [ref result, {args, arg} => args] } il.Newobj(Type.GetConstructor(genericArguments)); // stack: [ref result, new Tuple(args)] il.Stind(Type); // result = new Tuple(args); stack: [] context.StoreObject(Type); }
protected override void ReadNotEmpty(ReaderMethodBuilderContext context) { var il = context.Il; context.LoadResultByRef(); // stack: [ref result] context.LoadData(); // stack: [ref result, data] context.LoadIndexByRef(); // stack: [ref result, data, ref index] var argumentType = Type.GetGenericArguments()[0]; var value = il.DeclareLocal(argumentType); il.Ldloca(value); // stack: [ref result, data, ref index, ref value] context.LoadContext(); // stack: [ref result, data, ref index, ref value, context] context.CallReader(argumentType); // reader(pinnedData, ref index, ref value, context); stack: [ref result] il.Ldloc(value); // stack: [ref result, value] var constructor = Type.GetConstructor(new[] { argumentType }); if (constructor == null) { throw new MissingConstructorException(Type, argumentType); } il.Newobj(constructor); // stack: [ref result, new elementType?(value)] il.Stobj(Type); // result = new elementType?(value) }
protected override void ReadNotEmpty(ReaderMethodBuilderContext context) { var il = context.Il; il.Ldloc(context.TypeCode); // stack: [type code] il.Ldc_I4((int)GroBufTypeCode.Array); // stack: [type code, GroBufTypeCode.Array] var tryReadArrayElementLabel = il.DefineLabel("tryReadArrayElement"); il.Bne_Un(tryReadArrayElementLabel); // if(type code != GroBufTypeCode.Array) goto tryReadArrayElement; stack: [] context.IncreaseIndexBy1(); var length = context.Length; il.Ldc_I4(4); context.AssertLength(); context.GoToCurrentLocation(); // stack: [&data[index]] il.Ldind(typeof(uint)); // stack: [data length] context.IncreaseIndexBy4(); // index = index + 4; stack: [data length] context.AssertLength(); il.Ldc_I4(4); context.AssertLength(); context.GoToCurrentLocation(); // stack: [&data[index]] il.Ldind(typeof(uint)); // stack: [array length] context.IncreaseIndexBy4(); // index = index + 4; stack: [array length] il.Stloc(length); // length = array length; stack: [] if (context.Context.GroBufReader.Options.HasFlag(GroBufOptions.MergeOnRead)) { var createArrayLabel = il.DefineLabel("createArray"); context.LoadResult(Type); // stack: [result] il.Brfalse(createArrayLabel); // if(result == null) goto createArray; context.LoadResult(Type); // stack: [result] il.Ldlen(); // stack: [result.Length] il.Ldloc(length); // stack: [result.Length, length] var arrayCreatedLabel = il.DefineLabel("arrayCreated"); il.Bge(arrayCreatedLabel, false); // if(result.Length >= length) goto arrayCreated; context.LoadResultByRef(); // stack: [ref result] il.Ldloc(length); // stack: [ref result, length] il.Call(resizeMethod.MakeGenericMethod(elementType)); // Array.Resize(ref result, length) il.Br(arrayCreatedLabel); // goto arrayCreated il.MarkLabel(createArrayLabel); context.LoadResultByRef(); // stack: [ref result] il.Ldloc(length); // stack: [ref result, length] il.Newarr(elementType); // stack: [ref result, new type[length]] il.Stind(Type); // result = new type[length]; stack: [] il.MarkLabel(arrayCreatedLabel); } else { context.LoadResultByRef(); // stack: [ref result] il.Ldloc(length); // stack: [ref result, length] il.Newarr(elementType); // stack: [ref result, new type[length]] il.Stind(Type); // result = new type[length]; stack: [] } context.StoreObject(Type); il.Ldloc(length); // stack: [length] var doneLabel = il.DefineLabel("done"); il.Brfalse(doneLabel); // if(length == 0) goto allDone; stack: [] var i = il.DeclareLocal(typeof(uint)); il.Ldc_I4(0); // stack: [0] il.Stloc(i); // i = 0; stack: [] var cycleStartLabel = il.DefineLabel("cycleStart"); il.MarkLabel(cycleStartLabel); context.LoadData(); // stack: [pinnedData] context.LoadIndexByRef(); // stack: [pinnedData, ref index] context.LoadResult(Type); // stack: [pinnedData, ref index, result] il.Ldloc(i); // stack: [pinnedData, ref index, result, i] il.Ldelema(elementType); // stack: [pinnedData, ref index, ref result[i]] context.LoadContext(); // stack: [pinnedData, ref index, ref result[i], context] context.CallReader(elementType); // reader(pinnedData, ref index, ref result[i], context); stack: [] il.Ldloc(i); // stack: [i] il.Ldc_I4(1); // stack: [i, 1] il.Add(); // stack: [i + 1] il.Dup(); // stack: [i + 1, i + 1] il.Stloc(i); // i = i + 1; stack: [i] il.Ldloc(length); // stack: [i, length] il.Blt(cycleStartLabel, true); // if(i < length) goto cycleStart il.Br(doneLabel); il.MarkLabel(tryReadArrayElementLabel); if (context.Context.GroBufReader.Options.HasFlag(GroBufOptions.MergeOnRead)) { var createArrayLabel = il.DefineLabel("createArray"); context.LoadResult(Type); // stack: [result] il.Brfalse(createArrayLabel); // if(result == null) goto createArray; context.LoadResult(Type); // stack: [result] il.Ldlen(); // stack: [result.Length] il.Ldc_I4(1); // stack: [result.Length, 1] var arrayCreatedLabel = il.DefineLabel("arrayCreated"); il.Bge(arrayCreatedLabel, false); // if(result.Length >= 1) goto arrayCreated; context.LoadResultByRef(); // stack: [ref result] il.Ldc_I4(1); // stack: [ref result, 1] il.Call(resizeMethod.MakeGenericMethod(elementType)); // Array.Resize(ref result, length) il.Br(arrayCreatedLabel); // goto arrayCreated il.MarkLabel(createArrayLabel); context.LoadResultByRef(); // stack: [ref result] il.Ldc_I4(1); // stack: [ref result, 1] il.Newarr(elementType); // stack: [ref result, new type[1]] il.Stind(Type); // result = new type[1]; stack: [] il.MarkLabel(arrayCreatedLabel); } else { context.LoadResultByRef(); // stack: [ref result] il.Ldc_I4(1); // stack: [ref result, 1] il.Newarr(elementType); // stack: [ref result, new type[1]] il.Stind(Type); // result = new type[1]; stack: [] } context.StoreObject(Type); context.LoadData(); // stack: [pinnedData] context.LoadIndexByRef(); // stack: [pinnedData, ref index] context.LoadResult(Type); // stack: [pinnedData, ref index, result] il.Ldc_I4(0); // stack: [pinnedData, ref index, result, 0] il.Ldelema(elementType); // stack: [pinnedData, ref index, ref result[0]] context.LoadContext(); // stack: [pinnedData, ref index, ref result[0], context] context.CallReader(elementType); // reader(pinnedData, ref index, ref result[0], context); stack: [] il.MarkLabel(doneLabel); // stack: [] }
private KeyValuePair <Delegate, IntPtr> GetMemberSetter(ReaderTypeBuilderContext context, MemberInfo member) { var method = new DynamicMethod("Set_" + Type.Name + "_" + member.Name + "_" + Guid.NewGuid(), typeof(void), new[] { typeof(IntPtr), typeof(int).MakeByRefType(), Type.MakeByRefType(), typeof(ReaderContext) }, context.Module, true); using (var il = new GroboIL(method)) { il.Ldarg(0); // stack: [data] il.Ldarg(1); // stack: [data, ref index] switch (member.MemberType) { case MemberTypes.Field: var field = (FieldInfo)member; var done = false; if (member.GetCustomAttributes(typeof(IgnoreDefaultOnMergeAttribute), false).Length > 0 && field.FieldType.IsValueType) { var equalityOperator = field.FieldType.GetMethod("op_Equality", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static); if (field.FieldType.IsPrimitive || equalityOperator != null) { var fieldValue = il.DeclareLocal(field.FieldType); il.Ldarg(2); // stack: [data, ref index, ref result] if (!Type.IsValueType) { il.Ldind(Type); // stack: [data, ref index, result] } il.Ldfld(field); il.Stloc(fieldValue); il.Ldloca(fieldValue); il.Ldarg(3); // stack: [data, ref index, ref result.field, context] ReaderMethodBuilderContext.CallReader(il, field.FieldType, context); // reader(data, ref index, ref result.field, context); stack: [] var temp = il.DeclareLocal(field.FieldType); il.Ldloca(temp); il.Initobj(field.FieldType); il.Ldloc(temp); il.Ldloc(fieldValue); if (field.FieldType.IsPrimitive) { il.Ceq(); } else { il.Call(equalityOperator); } var notDefaultLabel = il.DefineLabel("notDefault"); il.Brfalse(notDefaultLabel); il.Ret(); il.MarkLabel(notDefaultLabel); il.Ldarg(2); if (!Type.IsValueType) { il.Ldind(Type); // stack: [data, ref index, result] } il.Ldloc(fieldValue); il.Stfld(field); done = true; } } if (!done) { il.Ldarg(2); // stack: [data, ref index, ref result] if (!Type.IsValueType) { il.Ldind(Type); // stack: [data, ref index, result] } il.Ldflda(field); // stack: [data, ref index, ref result.field] il.Ldarg(3); // stack: [data, ref index, ref result.field, context] ReaderMethodBuilderContext.CallReader(il, field.FieldType, context); // reader(data, ref index, ref result.field, context); stack: [] } break; case MemberTypes.Property: var property = (PropertyInfo)member; var propertyValue = il.DeclareLocal(property.PropertyType); if (context.GroBufReader.Options.HasFlag(GroBufOptions.MergeOnRead)) { var getter = property.GetGetMethod(true); if (getter == null) { throw new MissingMethodException(Type.Name, property.Name + "_get"); } il.Ldarg(2); // stack: [data, ref index, ref result] if (!Type.IsValueType) { il.Ldind(Type); // stack: [data, ref index, result] } il.Call(getter, Type); // stack: [ data, ref index, result.property] il.Stloc(propertyValue); // propertyValue = result.property; stack: [data, ref index] } il.Ldloca(propertyValue); // stack: [data, ref index, ref propertyValue] il.Ldarg(3); // stack: [data, ref index, ref propertyValue, context] ReaderMethodBuilderContext.CallReader(il, property.PropertyType, context); // reader(data, ref index, ref propertyValue, context); stack: [] if (member.GetCustomAttributes(typeof(IgnoreDefaultOnMergeAttribute), false).Length > 0 && property.PropertyType.IsValueType) { var equalityOperator = property.PropertyType.GetMethod("op_Equality", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static); if (property.PropertyType.IsPrimitive || equalityOperator != null) { var temp = il.DeclareLocal(property.PropertyType); il.Ldloca(temp); il.Initobj(property.PropertyType); il.Ldloc(temp); il.Ldloc(propertyValue); if (property.PropertyType.IsPrimitive) { il.Ceq(); } else { il.Call(equalityOperator); } var notDefaultLabel = il.DefineLabel("notDefault"); il.Brfalse(notDefaultLabel); il.Ret(); il.MarkLabel(notDefaultLabel); } } il.Ldarg(2); // stack: [ref result] if (!Type.IsValueType) { il.Ldind(Type); // stack: [result] } il.Ldloc(propertyValue); // stack: [result, propertyValue] var setter = property.GetSetMethod(true); if (setter == null) { throw new MissingMethodException(Type.Name, property.Name + "_set"); } il.Call(setter, Type); // result.property = propertyValue break; default: throw new NotSupportedException("Data member of type '" + member.MemberType + "' is not supported"); } il.Ret(); } var @delegate = method.CreateDelegate(typeof(ReaderDelegate <>).MakeGenericType(Type)); return(new KeyValuePair <Delegate, IntPtr>(@delegate, GroBufHelpers.ExtractDynamicMethodPointer(method))); }
protected override void ReadNotEmpty(ReaderMethodBuilderContext context) { context.IncreaseIndexBy1(); context.AssertTypeCode(GroBufTypeCode.Array); var il = context.Il; var length = context.Length; il.Ldc_I4(4); context.AssertLength(); context.GoToCurrentLocation(); // stack: [&data[index]] il.Ldind(typeof(uint)); // stack: [data length] context.IncreaseIndexBy4(); // index = index + 4; stack: [data length] context.AssertLength(); il.Ldc_I4(4); context.AssertLength(); context.GoToCurrentLocation(); // stack: [&data[index]] il.Ldind(typeof(uint)); // stack: [array length] context.IncreaseIndexBy4(); // index = index + 4; stack: [array length] il.Stloc(length); // length = array length; stack: [] if (context.Context.GroBufReader.Options.HasFlag(GroBufOptions.MergeOnRead)) { var createArrayLabel = il.DefineLabel("createArray"); context.LoadResult(Type); // stack: [result] il.Brfalse(createArrayLabel); // if(result == null) goto createArray; context.LoadResult(Type); // stack: [result] il.Ldfld(Type.GetField("_items", BindingFlags.Instance | BindingFlags.NonPublic)); // stack: [result._items] il.Ldlen(); // stack: [result._items.Length] il.Ldloc(length); // stack: [result._items.Length, length] var arrayCreatedLabel = il.DefineLabel("arrayCreated"); il.Bge(arrayCreatedLabel, false); // if(result._items.Length >= length) goto arrayCreated; context.LoadResult(Type); // stack: [result] il.Ldflda(Type.GetField("_items", BindingFlags.Instance | BindingFlags.NonPublic)); // stack: [ref result._items] il.Ldloc(length); // stack: [ref result, length] il.Call(resizeMethod.MakeGenericMethod(elementType)); // Array.Resize(ref result._items, length) il.Br(arrayCreatedLabel); // goto arrayCreated il.MarkLabel(createArrayLabel); context.LoadResultByRef(); // stack: [ref result] il.Ldloc(length); // stack: [ref result, length] il.Newobj(Type.GetConstructor(new[] { typeof(int) })); // stack: [ref result, new List(length)] il.Stind(Type); // result = new List(length); stack: [] il.MarkLabel(arrayCreatedLabel); } else { context.LoadResultByRef(); // stack: [ref result] il.Ldloc(length); // stack: [ref result, length] il.Newobj(Type.GetConstructor(new[] { typeof(int) })); // stack: [ref result, new List(length)] il.Stind(Type); // result = new List(length); stack: [] } context.StoreObject(Type); il.Ldloc(length); // stack: [length] var doneLabel = il.DefineLabel("done"); il.Brfalse(doneLabel); // if(length == 0) goto allDone; stack: [] context.LoadResult(Type); // stack: [result] il.Ldfld(Type.GetField("_items", BindingFlags.Instance | BindingFlags.NonPublic)); // stack: [result._items] var items = il.DeclareLocal(elementType.MakeArrayType()); il.Stloc(items); // items = result._items; stack: [] var i = il.DeclareLocal(typeof(uint)); il.Ldc_I4(0); // stack: [0] il.Stloc(i); // i = 0; stack: [] var cycleStartLabel = il.DefineLabel("cycleStart"); il.MarkLabel(cycleStartLabel); context.LoadData(); // stack: [pinnedData] context.LoadIndexByRef(); // stack: [pinnedData, ref index] il.Ldloc(items); // stack: [pinnedData, ref index, items] il.Ldloc(i); // stack: [pinnedData, ref index, items, i] il.Ldelema(elementType); // stack: [pinnedData, ref index, ref items[i]] context.LoadContext(); // stack: [pinnedData, ref index, ref items[i], context] context.CallReader(elementType); // reader(pinnedData, ref index, ref result[i], context); stack: [] il.Ldloc(i); // stack: [i] il.Ldc_I4(1); // stack: [i, 1] il.Add(); // stack: [i + 1] il.Dup(); // stack: [i + 1, i + 1] il.Stloc(i); // i = i + 1; stack: [i] il.Ldloc(length); // stack: [i, length] il.Blt(cycleStartLabel, true); // if(i < length) goto cycleStart if (context.Context.GroBufReader.Options.HasFlag(GroBufOptions.MergeOnRead)) { context.LoadResult(Type); // stack: [result] il.Ldfld(Type.GetField("_size", BindingFlags.Instance | BindingFlags.NonPublic)); // stack: [result.Count] il.Ldloc(length); // stack: [result.Count, length] il.Bge(doneLabel, false); // if(result.Count >= length) goto done; stack: [] } context.LoadResult(Type); // stack: [result] il.Ldloc(length); // stack: [result.Count, length] il.Stfld(Type.GetField("_size", BindingFlags.Instance | BindingFlags.NonPublic)); // result._size = length; stack: [] il.MarkLabel(doneLabel); // stack: [] }
public void BuildReader(ReaderTypeBuilderContext readerTypeBuilderContext) { var method = new DynamicMethod("Read_" + Type.Name + "_" + Guid.NewGuid(), typeof(void), new[] { typeof(IntPtr), typeof(int).MakeByRefType(), Type.MakeByRefType(), typeof(ReaderContext) }, readerTypeBuilderContext.Module, true); readerTypeBuilderContext.SetReaderMethod(Type, method); using (var il = new GroboIL(method)) { var context = new ReaderMethodBuilderContext(readerTypeBuilderContext, il, !Type.IsValueType && IsReference); ReadTypeCodeAndCheck(context); // Read TypeCode and check if (!Type.IsValueType && IsReference) { // Read reference context.LoadContext(); // stack: [context] il.Ldfld(ReaderContext.ObjectsField); // stack: [context.objects] var notReadLabel = il.DefineLabel("notRead"); il.Brfalse(notReadLabel); context.LoadIndex(); // stack: [external index] context.LoadContext(); // stack: [external index, context] il.Ldfld(ReaderContext.StartField); // stack: [external index, context.start] il.Sub(); // stack: [external index - context.start] il.Stloc(context.Index); // index = external index - context.start; stack: [] context.LoadContext(); // stack: [context] il.Ldfld(ReaderContext.ObjectsField); // stack: [context.objects] il.Ldloc(context.Index); // stack: [context.objects, index] var obj = il.DeclareLocal(typeof(object)); il.Ldloca(obj); object dummy; il.Call(HackHelpers.GetMethodDefinition <Dictionary <int, object> >(dict => dict.TryGetValue(0, out dummy))); // stack: [context.objects.TryGetValue(index, out obj)] il.Brfalse(notReadLabel); // if(!context.objects.TryGetValue(index, out obj)) goto notRead; context.LoadResultByRef(); // stack: [ref result] il.Ldloc(obj); // stack: [ref result, obj] il.Castclass(Type); // stack: [ref result, (Type)obj] il.Stind(Type); // result = (Type)obj; stack: [] context.IncreaseIndexBy1(); // Skip type code context.SkipValue(); // Skip value - it has already been read il.Ret(); il.MarkLabel(notReadLabel); il.Ldloc(context.TypeCode); // stack: [typeCode] il.Ldc_I4((int)GroBufTypeCode.Reference); // stack: [typeCode, GroBufTypeCode.Reference] var readUsualLabel = il.DefineLabel("readUsual"); il.Bne_Un(readUsualLabel); // if(typeCode != GroBufTypeCode.Reference) goto readUsual; stack: [] context.LoadContext(); // stack: [context] il.Ldfld(ReaderContext.ObjectsField); // stack: [context.objects] var objectsIsNotNullLabel = il.DefineLabel("objectsIsNotNull"); il.Brtrue(objectsIsNotNullLabel); // if(context.objects != null) goto objectsIsNotNull; stack: [context.objects] il.Ldstr("Reference is not valid at this point"); il.Newobj(typeof(DataCorruptedException).GetConstructor(new[] { typeof(string) })); il.Throw(); il.MarkLabel(objectsIsNotNullLabel); context.IncreaseIndexBy1(); // index = index + 1; stack: [] il.Ldc_I4(4); context.AssertLength(); context.GoToCurrentLocation(); var reference = il.DeclareLocal(typeof(int)); il.Ldind(typeof(int)); // stack: [*(int*)data[index]] il.Stloc(reference); // reference = *(int*)data[index]; stack: [] context.IncreaseIndexBy4(); // index = index + 4; stack: [] il.Ldloc(context.Index); // stack: [index] il.Ldloc(reference); // stack: [index, reference] var goodReferenceLabel = il.DefineLabel("goodReference"); il.Bgt(goodReferenceLabel, false); // if(index > reference) goto goodReference; stack: [] il.Ldstr("Bad reference"); il.Newobj(typeof(DataCorruptedException).GetConstructor(new[] { typeof(string) })); il.Throw(); il.MarkLabel(goodReferenceLabel); context.LoadContext(); // stack: [context] il.Ldfld(ReaderContext.ObjectsField); // stack: [context.objects] il.Ldloc(reference); // stack: [context.objects, reference] il.Ldloca(obj); // stack: [context.objects, reference, ref obj] il.Call(HackHelpers.GetMethodDefinition <Dictionary <int, object> >(dict => dict.TryGetValue(0, out dummy))); // stack: [context.objects.TryGetValue(reference, out obj)] var readObjectLabel = il.DefineLabel("readObject"); il.Brfalse(readObjectLabel); // if(!context.objects.TryGetValue(reference, out obj)) goto readObjects; stack: [] context.LoadResultByRef(); // stack: [ref result] il.Ldloc(obj); // stack: [ref result, obj] il.Castclass(Type); // stack: [ref result, (Type)obj] il.Stind(Type); // result = (Type)obj; stack: [] il.Ret(); il.MarkLabel(readObjectLabel); // Referenced object has not been read - this means that the object reference belongs to is a property that had been deleted context.LoadData(); // stack: [data] il.Ldloc(reference); // stack: [data, reference] context.LoadContext(); // stack: [data, reference, context] il.Ldfld(ReaderContext.StartField); // stack: [data, reference, context.start] il.Add(); // stack: [data, reference + context.start] il.Stloc(reference); // reference += context.start; stack: [data] il.Ldloca(reference); // stack: [data, ref reference] context.LoadResultByRef(); // stack: [data, ref reference, ref result] context.LoadContext(); // stack: [data, ref reference, ref result, context] context.CallReader(Type); il.Ret(); il.MarkLabel(readUsualLabel); } ReadNotEmpty(context); // Read obj il.Ret(); } var @delegate = method.CreateDelegate(typeof(ReaderDelegate <>).MakeGenericType(Type)); var pointer = GroBufHelpers.ExtractDynamicMethodPointer(method); readerTypeBuilderContext.SetReaderPointer(Type, pointer, @delegate); }
protected override void ReadNotEmpty(ReaderMethodBuilderContext context) { context.IncreaseIndexBy1(); context.AssertTypeCode(GroBufTypeCode.Array); var il = context.Il; var length = context.Length; il.Ldc_I4(4); context.AssertLength(); context.GoToCurrentLocation(); // stack: [&data[index]] il.Ldind(typeof(uint)); // stack: [data length] context.IncreaseIndexBy4(); // index = index + 4; stack: [data length] context.AssertLength(); il.Ldc_I4(4); context.AssertLength(); context.GoToCurrentLocation(); // stack: [&data[index]] il.Ldind(typeof(uint)); // stack: [array length] context.IncreaseIndexBy4(); // index = index + 4; stack: [array length] il.Stloc(length); // length = array length; stack: [] context.LoadResultByRef(); // stack: [ref result] il.Newobj(Type.GetConstructor(Type.EmptyTypes)); // stack: [ref result, new HashSet() = hashSet] il.Dup(); // stack: [ref result, hashSet, hashSet] il.Ldloc(length); // stack: [ref result, hashSet, hashSet, length] var initializeMethod = Type.GetMethod("Initialize", BindingFlags.Instance | BindingFlags.NonPublic); il.Call(initializeMethod); // hashSet.Initialize(length); stack: [ref result, hashSet] or [ref result, hashSet, actualHashSetSize] if (initializeMethod.ReturnType != typeof(void)) { il.Pop(); // stack: [ref result, hashSet] } il.Stind(Type); // result = hashSet; stack: [] context.StoreObject(Type); il.Ldloc(length); // stack: [length] var doneLabel = il.DefineLabel("done"); il.Brfalse(doneLabel); // if(length == 0) goto allDone; stack: [] var i = il.DeclareLocal(typeof(uint)); il.Ldc_I4(0); // stack: [0] il.Stloc(i); // i = 0; stack: [] var cycleStartLabel = il.DefineLabel("cycleStart"); il.MarkLabel(cycleStartLabel); context.LoadData(); // stack: [pinnedData] context.LoadIndexByRef(); // stack: [pinnedData, ref index] var value = il.DeclareLocal(elementType); il.Ldloca(value); // stack: [pinnedData, ref index, ref value] context.LoadContext(); // stack: [pinnedData, ref index, ref value, context] context.CallReader(elementType); // reader(pinnedData, ref index, ref value, context); stack: [] context.LoadResult(Type); // stack: [result] il.Ldloc(value); // stack: [result, value] il.Call(Type.GetMethod("Add")); // stack: [result.Add(value)] il.Pop(); // stack: [] if (!elementType.IsValueType) { il.Ldnull(); il.Stloc(value); } il.Ldloc(i); // stack: [i] il.Ldc_I4(1); // stack: [i, 1] il.Add(); // stack: [i + 1] il.Dup(); // stack: [i + 1, i + 1] il.Stloc(i); // i = i + 1; stack: [i] il.Ldloc(length); // stack: [i, length] il.Blt(cycleStartLabel, true); // if(i < length) goto cycleStart il.MarkLabel(doneLabel); // stack: [] }
protected override unsafe void ReadNotEmpty(ReaderMethodBuilderContext context) { var il = context.Il; il.Ldloc(context.TypeCode); // stack: [type code] il.Ldc_I4((int)GroBufTypeCodeMap.GetTypeCode(Type)); // stack: [type code, GroBufTypeCode(Type)] var tryReadArrayElementLabel = il.DefineLabel("tryReadArrayElement"); il.Bne_Un(tryReadArrayElementLabel); // if(type code != GroBufTypeCode(Type)) goto tryReadArrayElement; stack: [] context.IncreaseIndexBy1(); var size = il.DeclareLocal(typeof(int)); il.Ldc_I4(4); context.AssertLength(); context.GoToCurrentLocation(); // stack: [&data[index]] il.Ldind(typeof(uint)); // stack: [data length] il.Dup(); // stack: [data length, data length] il.Stloc(size); // size = data length; stack: [data length] context.IncreaseIndexBy4(); // index = index + 4; stack: [data length] context.AssertLength(); var length = context.Length; il.Ldloc(size); // stack: [size] CountArrayLength(elementType, il); // stack: [array length] il.Stloc(length); // length = array length var array = il.DeclareLocal(elementType.MakeArrayType()); context.LoadResultByRef(); // stack: [ref result] il.Dup(); // stack: [ref result, ref result] il.Ldc_I4(0); // stack: [ref result, ref result, 0] il.Stfld(offsetField); // result._offset = 0; stack: [ref result] il.Dup(); // stack: [ref result, ref result] il.Ldloc(length); // stack: [ref result, ref result, length] il.Stfld(countField); // result._count = length; stack: [ref result] il.Ldloc(length); // stack: [ref result, length] il.Newarr(elementType); // stack: [ref result, new type[length]] il.Dup(); il.Stloc(array); // array = new type[length]; stack: [ref result] il.Stfld(arrayField); // result._array = array; stack: [] il.Ldloc(length); var doneLabel = il.DefineLabel("done"); il.Brfalse(doneLabel); // if(length == 0) goto allDone; stack: [] var arr = il.DeclareLocal(elementType.MakeByRefType(), true); il.Ldloc(array); // stack: [array] il.Ldc_I4(0); // stack: [array, 0] il.Ldelema(elementType); // stack: [&array[0]] il.Stloc(arr); // arr = &array[0]; stack: [] il.Ldloc(arr); // stack: [arr] context.GoToCurrentLocation(); // stack: [arr, &data[index]] il.Ldloc(length); // stack: [arr, &data[index], length] CountArraySize(elementType, il); // stack: [arr, &data[index], size] il.Cpblk(); // arr = &data[index] il.FreePinnedLocal(arr); // arr = null; stack: [] context.LoadIndexByRef(); // stack: [ref index] context.LoadIndex(); // stack: [ref index, index] il.Ldloc(size); // stack: [ref index, index, size] il.Add(); // stack: [ref index, index + size] il.Stind(typeof(int)); // index = index + size il.Br(doneLabel); il.MarkLabel(tryReadArrayElementLabel); context.LoadResultByRef(); // stack: [ref result] il.Dup(); // stack: [ref result, ref result] il.Ldc_I4(0); // stack: [ref result, ref result, 0] il.Stfld(offsetField); // result._offset = 0; stack: [ref result] il.Dup(); // stack: [ref result, ref result] il.Ldc_I4(1); // stack: [ref result, ref result, 1] il.Stfld(countField); // result._count = 1; stack: [ref result] il.Ldc_I4(1); // stack: [ref result, 1] il.Newarr(elementType); // stack: [ref result, new type[1]] il.Dup(); il.Stloc(array); // array = new type[1]; stack: [ref result] il.Stfld(arrayField); // result._array = array; stack: [] context.LoadData(); // stack: [pinnedData] context.LoadIndexByRef(); // stack: [pinnedData, ref index] il.Ldloc(array); // stack: [pinnedData, ref index, array] il.Ldc_I4(0); // stack: [pinnedData, ref index, array, 0] il.Ldelema(elementType); // stack: [pinnedData, ref index, ref array[0]] context.LoadContext(); // stack: [pinnedData, ref index, ref array[0], context] context.CallReader(elementType); // reader(pinnedData, ref index, ref array[0], context); stack: [] il.MarkLabel(doneLabel); // stack: [] }
protected override void ReadNotEmpty(ReaderMethodBuilderContext context) { int[] values; ulong[] hashCodes; EnumHelpers.BuildValuesTable(Type, out values, out hashCodes); var valuesField = context.Context.InitConstField(Type, 0, values); var hashCodesField = context.Context.InitConstField(Type, 1, hashCodes); var il = context.Il; il.Ldloc(context.TypeCode); // stack: [typeCode] il.Ldc_I4((int)GroBufTypeCode.Enum); var tryParseLabel = il.DefineLabel("tryParse"); il.Bne_Un(tryParseLabel); // if(typeCode != GroBufTypeCode.Enum) goto tryParse; context.IncreaseIndexBy1(); il.Ldc_I4(8); // stack: [8] context.AssertLength(); context.LoadResultByRef(); // stack: [ref result] context.GoToCurrentLocation(); // stack: [ref result, &result[index]] il.Ldind(typeof(long)); // stack: [ref result, *(int64*)result[index] = hashCode] context.IncreaseIndexBy8(); // index = index + 8; stack: [ref result, hashCode] var parseByHashCodeLabel = il.DefineLabel("parseByHashCode"); il.MarkLabel(parseByHashCodeLabel); il.Dup(); // stack: [ref result, hashCode, hashCode] il.Ldc_I8(hashCodes.Length); // stack: [ref result, hashCode, hashCode, (int64)hashCodes.Length] il.Rem(true); // stack: [ref result, hashCode, hashCode % hashCodes.Length = idx] il.Conv <int>(); // stack: [ref result, hashCode, (int)(hashCode % hashCodes.Length)] var idx = context.Length; il.Stloc(idx); // idx = (int)(hashCode % hashCodes.Length); stack: [ref result, hashCode] context.LoadField(hashCodesField); // stack: [ref result, hashCode, hashCodes] il.Ldloc(idx); // stack: [ref result, hashCode, hashCodes, idx] il.Ldelem(typeof(long)); // stack: [ref result, hashCode, hashCodes[idx]] var returnDefaultLabel = il.DefineLabel("returnDefault"); il.Bne_Un(returnDefaultLabel); // if(hashCode != hashCodes[idx]) goto returnDefault; stack: [ref result] context.LoadField(valuesField); // stack: [ref result, values] il.Ldloc(idx); // stack: [ref result, values, idx] il.Ldelem(typeof(int)); // stack: [ref result, values[idx]] il.Stind(typeof(int)); // result = values[idx]; stack: [] il.Ret(); il.MarkLabel(returnDefaultLabel); il.Ldc_I4(0); // stack: [0] il.Stind(typeof(int)); // result = 0 il.Ret(); il.MarkLabel(tryParseLabel); il.Ldloc(context.TypeCode); // stack: [typeCode] il.Ldc_I4((int)GroBufTypeCode.String); // stack: [typeCode, GroBufTypeCode.String] var readAsIntLabel = il.DefineLabel("readAsInt"); il.Bne_Un(readAsIntLabel); // if(typeCode != GroBufTypeCode.String) goto readAsInt; var str = il.DeclareLocal(typeof(string)); context.LoadData(); // stack: [pinnedData] context.LoadIndexByRef(); // stack: [pinnedData, ref index] il.Ldloca(str); // stack: [pinnedData, ref index, ref str] context.LoadContext(); // stack: [pinnedData, ref index, ref str, context] context.CallReader(typeof(string)); // reader<string>(pinnedData, ref index, ref str, context); stack: [] context.LoadResultByRef(); // stack: [ref result] il.Ldloc(str); // stack: [ref result, str] il.Call(typeof(GroBufHelpers).GetMethod("CalcHash", BindingFlags.Public | BindingFlags.Static)); // stack: [ref result, GroBufHelpers.CalcHash(str)] il.Br(parseByHashCodeLabel); il.MarkLabel(readAsIntLabel); context.LoadData(); // stack: [pinnedData] context.LoadIndexByRef(); // stack: [pinnedData, ref index] context.LoadResultByRef(); // stack: [pinnedData, ref index, ref result] context.LoadContext(); // stack: [pinnedData, ref index, ref result, context] context.CallReader(typeof(int)); // reader<int>(pinnedData, ref index, ref result, context) }
protected override void ReadNotEmpty(ReaderMethodBuilderContext context) { var il = context.Il; il.Ldloc(context.TypeCode); // stack: [type code] il.Ldc_I4((int)GroBufTypeCode.Array); // stack: [type code, GroBufTypeCode.Array] var tryReadArrayElementLabel = il.DefineLabel("tryReadArrayElement"); il.Bne_Un(tryReadArrayElementLabel); // if(type code != GroBufTypeCode.Array) goto tryReadArrayElement; stack: [] context.IncreaseIndexBy1(); var length = context.Length; il.Ldc_I4(4); context.AssertLength(); context.GoToCurrentLocation(); // stack: [&data[index]] il.Ldind(typeof(uint)); // stack: [data length] context.IncreaseIndexBy4(); // index = index + 4; stack: [data length] context.AssertLength(); il.Ldc_I4(4); context.AssertLength(); context.GoToCurrentLocation(); // stack: [&data[index]] il.Ldind(typeof(uint)); // stack: [array length] context.IncreaseIndexBy4(); // index = index + 4; stack: [array length] il.Stloc(length); // length = array length; stack: [] var array = il.DeclareLocal(elementType.MakeArrayType()); context.LoadResultByRef(); // stack: [ref result] il.Dup(); // stack: [ref result, ref result] il.Ldc_I4(0); // stack: [ref result, ref result, 0] il.Stfld(offsetField); // result._offset = 0; stack: [ref result] il.Dup(); // stack: [ref result, ref result] il.Ldloc(length); // stack: [ref result, ref result, length] il.Stfld(countField); // result._count = length; stack: [ref result] il.Ldloc(length); // stack: [ref result, length] il.Newarr(elementType); // stack: [ref result, new type[length]] il.Dup(); il.Stloc(array); // array = new type[length]; stack: [ref result] il.Stfld(arrayField); // result._array = array; stack: [] il.Ldloc(length); // stack: [length] var doneLabel = il.DefineLabel("done"); il.Brfalse(doneLabel); // if(length == 0) goto allDone; stack: [] var i = il.DeclareLocal(typeof(uint)); il.Ldc_I4(0); // stack: [0] il.Stloc(i); // i = 0; stack: [] var cycleStartLabel = il.DefineLabel("cycleStart"); il.MarkLabel(cycleStartLabel); context.LoadData(); // stack: [pinnedData] context.LoadIndexByRef(); // stack: [pinnedData, ref index] il.Ldloc(array); // stack: [pinnedData, ref index, array] il.Ldloc(i); // stack: [pinnedData, ref index, array, i] il.Ldelema(elementType); // stack: [pinnedData, ref index, ref array[i]] context.LoadContext(); // stack: [pinnedData, ref index, ref array[i], context] context.CallReader(elementType); // reader(pinnedData, ref index, ref array[i], context); stack: [] il.Ldloc(i); // stack: [i] il.Ldc_I4(1); // stack: [i, 1] il.Add(); // stack: [i + 1] il.Dup(); // stack: [i + 1, i + 1] il.Stloc(i); // i = i + 1; stack: [i] il.Ldloc(length); // stack: [i, length] il.Blt(cycleStartLabel, true); // if(i < length) goto cycleStart il.Br(doneLabel); il.MarkLabel(tryReadArrayElementLabel); context.LoadResultByRef(); // stack: [ref result] il.Dup(); // stack: [ref result, ref result] il.Ldc_I4(0); // stack: [ref result, ref result, 0] il.Stfld(offsetField); // result._offset = 0; stack: [ref result] il.Dup(); // stack: [ref result, ref result] il.Ldc_I4(1); // stack: [ref result, ref result, 1] il.Stfld(countField); // result._count = 1; stack: [ref result] il.Ldc_I4(1); // stack: [ref result, 1] il.Newarr(elementType); // stack: [ref result, new type[1]] il.Dup(); il.Stloc(array); // array = new type[1]; stack: [ref result] il.Stfld(arrayField); // result._array = array; stack: [] context.LoadData(); // stack: [pinnedData] context.LoadIndexByRef(); // stack: [pinnedData, ref index] il.Ldloc(array); // stack: [pinnedData, ref index, array] il.Ldc_I4(0); // stack: [pinnedData, ref index, array, 0] il.Ldelema(elementType); // stack: [pinnedData, ref index, ref array[0]] context.LoadContext(); // stack: [pinnedData, ref index, ref array[0], context] context.CallReader(elementType); // reader(pinnedData, ref index, ref array[0], context); stack: [] il.MarkLabel(doneLabel); // stack: [] }
protected override void ReadNotEmpty(ReaderMethodBuilderContext context) { context.IncreaseIndexBy1(); context.AssertTypeCode(GroBufTypeCode.Dictionary); var il = context.Il; var length = context.Length; il.Ldc_I4(4); context.AssertLength(); context.GoToCurrentLocation(); // stack: [&data[index]] il.Ldind(typeof(uint)); // stack: [data length] context.IncreaseIndexBy4(); // index = index + 4; stack: [data length] context.AssertLength(); il.Ldc_I4(4); context.AssertLength(); context.GoToCurrentLocation(); // stack: [&data[index]] il.Ldind(typeof(uint)); // stack: [array length] context.IncreaseIndexBy4(); // index = index + 4; stack: [array length] il.Stloc(length); // length = array length; stack: [] context.LoadResultByRef(); // stack: [ref result] il.Ldloc(length); // stack: [ref result, length] il.Newobj(Type.GetConstructor(new[] { typeof(int) })); // stack: [ref result, new Dictionary(length)] il.Stind(Type); // result = new Dictionary(length); stack: [] context.StoreObject(Type); il.Ldloc(length); // stack: [length] var doneLabel = il.DefineLabel("done"); il.Brfalse(doneLabel); // if(length == 0) goto allDone; stack: [] var i = il.DeclareLocal(typeof(uint)); il.Ldc_I4(0); // stack: [0] il.Stloc(i); // i = 0; stack: [] var cycleStartLabel = il.DefineLabel("cycleStart"); il.MarkLabel(cycleStartLabel); context.LoadData(); // stack: [pinnedData] context.LoadIndexByRef(); // stack: [pinnedData, ref index] var key = il.DeclareLocal(Type.GetGenericArguments()[0]); var value = il.DeclareLocal(Type.GetGenericArguments()[1]); il.Ldloca(key); // stack: [pinnedData, ref index, ref key] context.LoadContext(); // stack: [pinnedData, ref index, ref key, context] context.CallReader(keyType); // reader(pinnedData, ref index, ref key, context); stack: [] context.LoadData(); // stack: [pinnedData] context.LoadIndexByRef(); // stack: [pinnedData, ref index] il.Ldloca(value); // stack: [pinnedData, ref index, ref value] context.LoadContext(); // stack: [pinnedData, ref index, ref value, context] context.CallReader(valueType); // reader(pinnedData, ref index, ref value, context); stack: [] context.LoadResult(Type); il.Ldloc(key); il.Ldloc(value); il.Call(Type.GetMethod("Add")); if (!keyType.IsValueType) { il.Ldnull(); il.Stloc(key); } if (!valueType.IsValueType) { il.Ldnull(); il.Stloc(value); } il.Ldloc(i); // stack: [i] il.Ldc_I4(1); // stack: [i, 1] il.Add(); // stack: [i + 1] il.Dup(); // stack: [i + 1, i + 1] il.Stloc(i); // i = i + 1; stack: [i] il.Ldloc(length); // stack: [i, length] il.Blt(cycleStartLabel, true); // if(i < length) goto cycleStart il.MarkLabel(doneLabel); // stack: [] }
protected override unsafe void ReadNotEmpty(ReaderMethodBuilderContext context) { var il = context.Il; il.Ldloc(context.TypeCode); // stack: [type code] il.Ldc_I4((int)GroBufTypeCodeMap.GetTypeCode(Type)); // stack: [type code, GroBufTypeCode(Type)] var tryReadArrayElementLabel = il.DefineLabel("tryReadArrayElement"); il.Bne_Un(tryReadArrayElementLabel); // if(type code != GroBufTypeCode(Type)) goto tryReadArrayElement; stack: [] context.IncreaseIndexBy1(); var size = il.DeclareLocal(typeof(int)); il.Ldc_I4(4); context.AssertLength(); context.GoToCurrentLocation(); // stack: [&data[index]] il.Ldind(typeof(uint)); // stack: [data length] il.Dup(); // stack: [data length, data length] il.Stloc(size); // size = data length; stack: [data length] context.IncreaseIndexBy4(); // index = index + 4; stack: [data length] context.AssertLength(); var length = context.Length; il.Ldloc(size); // stack: [size] CountArrayLength(elementType, il); // stack: [array length] il.Stloc(length); // length = array length if (context.Context.GroBufReader.Options.HasFlag(GroBufOptions.MergeOnRead)) { var createArrayLabel = il.DefineLabel("createArray"); context.LoadResult(Type); // stack: [result] il.Brfalse(createArrayLabel); // if(result == null) goto createArray; context.LoadResult(Type); // stack: [result] il.Ldlen(); // stack: [result.Length] il.Ldloc(length); // stack: [result.Length, length] var arrayCreatedLabel = il.DefineLabel("arrayCreated"); il.Bge(arrayCreatedLabel, false); // if(result.Length >= length) goto arrayCreated; context.LoadResultByRef(); // stack: [ref result] il.Ldloc(length); // stack: [ref result, length] il.Call(resizeMethod.MakeGenericMethod(elementType)); // Array.Resize(ref result, length) il.Br(arrayCreatedLabel); // goto arrayCreated il.MarkLabel(createArrayLabel); context.LoadResultByRef(); // stack: [ref result] il.Ldloc(length); // stack: [ref result, length] il.Newarr(elementType); // stack: [ref result, new type[length]] il.Stind(Type); // result = new type[length]; stack: [] il.MarkLabel(arrayCreatedLabel); } else { context.LoadResultByRef(); // stack: [ref result] il.Ldloc(length); // stack: [ref result, length] il.Newarr(elementType); // stack: [ref result, new type[length]] il.Stind(Type); // result = new type[length]; stack: [] } il.Ldloc(length); var doneLabel = il.DefineLabel("done"); il.Brfalse(doneLabel); // if(length == 0) goto allDone; stack: [] var arr = il.DeclareLocal(elementType.MakeByRefType(), true); context.LoadResult(Type); // stack: [result] il.Ldc_I4(0); // stack: [result, 0] il.Ldelema(elementType); // stack: [&result[0]] il.Stloc(arr); // arr = &result[0]; stack: [] il.Ldloc(arr); // stack: [arr] context.GoToCurrentLocation(); // stack: [arr, &data[index]] il.Ldloc(length); // stack: [arr, &data[index], length] CountArraySize(elementType, il); // stack: [arr, &data[index], size] il.Cpblk(); // arr = &data[index] il.FreePinnedLocal(arr); // arr = null; stack: [] context.LoadIndexByRef(); // stack: [ref index] context.LoadIndex(); // stack: [ref index, index] il.Ldloc(size); // stack: [ref index, index, size] il.Add(); // stack: [ref index, index + size] il.Stind(typeof(int)); // index = index + size il.Br(doneLabel); il.MarkLabel(tryReadArrayElementLabel); if (context.Context.GroBufReader.Options.HasFlag(GroBufOptions.MergeOnRead)) { var createArrayLabel = il.DefineLabel("createArray"); context.LoadResult(Type); // stack: [result] il.Brfalse(createArrayLabel); // if(result == null) goto createArray; context.LoadResult(Type); // stack: [result] il.Ldlen(); // stack: [result.Length] il.Ldc_I4(1); // stack: [result.Length, 1] var arrayCreatedLabel = il.DefineLabel("arrayCreated"); il.Bge(arrayCreatedLabel, false); // if(result.Length >= 1) goto arrayCreated; context.LoadResultByRef(); // stack: [ref result] il.Ldc_I4(1); // stack: [ref result, 1] il.Call(resizeMethod.MakeGenericMethod(elementType)); // Array.Resize(ref result, 1) il.Br(arrayCreatedLabel); // goto arrayCreated il.MarkLabel(createArrayLabel); context.LoadResultByRef(); // stack: [ref result] il.Ldc_I4(1); // stack: [ref result, 1] il.Newarr(elementType); // stack: [ref result, new type[1]] il.Stind(Type); // result = new type[1]; stack: [] il.MarkLabel(arrayCreatedLabel); } else { context.LoadResultByRef(); // stack: [ref result] il.Ldc_I4(1); // stack: [ref result, 1] il.Newarr(elementType); // stack: [ref result, new type[1]] il.Stind(Type); // result = new type[1]; stack: [] } context.LoadData(); // stack: [pinnedData] context.LoadIndexByRef(); // stack: [pinnedData, ref index] context.LoadResult(Type); // stack: [pinnedData, ref index, result] il.Ldc_I4(0); // stack: [pinnedData, ref index, result, 0] il.Ldelema(elementType); // stack: [pinnedData, ref index, ref result[0]] context.LoadContext(); // stack: [pinnedData, ref index, ref result[0], context] context.CallReader(elementType); // reader(pinnedData, ref index, ref result[0], context); stack: [] il.MarkLabel(doneLabel); // stack: [] }