protected override bool CheckEmpty(SizeCounterMethodBuilderContext context, GroboIL.Label notEmptyLabel) { context.LoadObjByRef(); // stack: [&obj] context.Il.Call(Type.GetProperty("HasValue").GetGetMethod()); // stack: obj.HasValue context.Il.Brtrue(notEmptyLabel); // if(obj.HasValue) goto notEmpty; return(true); }
protected override void CountSizeNotEmpty(SizeCounterMethodBuilderContext context) { var il = context.Il; il.Ldc_I4(9); // stack: [9 = size] 9 = type code + data length + array length var doneLabel = il.DefineLabel("done"); context.LoadObjByRef(); // stack: [size, ref obj] il.Ldfld(countField); // stack: [size, obj._count] il.Brfalse(doneLabel); // if(obj._count == 0) goto done; stack: [size] var i = il.DeclareLocal(typeof(int)); var end = il.DeclareLocal(typeof(int)); context.LoadObjByRef(); // stack: [size, ref obj] il.Dup(); // stack: [size, ref obj, ref obj] il.Ldfld(offsetField); // stack: [size, ref obj, obj._offset] il.Stloc(i); // i = obj._offset; stack: [size, ref obj] il.Ldfld(countField); // stack: [size, obj._count] il.Ldloc(i); // stack: [size, obj._count, obj._offset] il.Add(); // stack: [size, obj._count + obj._offset] il.Stloc(end); // end = obj._count + obj._offset; stack: [size] var array = il.DeclareLocal(elementType.MakeArrayType()); context.LoadObjByRef(); // stack: [size, ref obj] il.Ldfld(arrayField); // stack: [size, obj._array] il.Stloc(array); // array = obj._array; stack: [size] var cycleStartLabel = il.DefineLabel("cycleStart"); il.MarkLabel(cycleStartLabel); il.Ldloc(array); // stack: [size, array] il.Ldloc(i); // stack: [size, array, i] il.Ldelem(elementType); // stack: [size, array[i]] il.Ldc_I4(1); // stack: [size, array[i], true] context.LoadContext(); // stack: [size, array[i], true, context] context.CallSizeCounter(elementType); // stack: [size, writer(array[i], true, context) = itemSize] il.Add(); // stack: [size + itemSize] il.Ldloc(end); // stack: [size, end] il.Ldloc(i); // stack: [size, end, i] il.Ldc_I4(1); // stack: [size, end, i, 1] il.Add(); // stack: [size, end, i + 1] il.Dup(); // stack: [size, end, i + 1, i + 1] il.Stloc(i); // i = i + 1; stack: [size, end, i] il.Bgt(cycleStartLabel, false); // if(end > i) goto cycleStart; stack: [size] il.MarkLabel(doneLabel); }
protected override void CountSizeNotEmpty(SizeCounterMethodBuilderContext context) { var il = context.Il; il.Ldc_I4(5); // stack: [5 = size] 5 = type code + data length context.LoadObjByRef(); // stack: [5, ref obj] il.Ldfld(countField); // stack: [5, obj._count] CountArraySize(elementType, il); // stack: [5, obj length] il.Add(); // stack: [5 + obj length] }
protected override void CountSizeNotEmpty(SizeCounterMethodBuilderContext context) { var il = context.Il; context.LoadObjByRef(); // stack: [&obj] il.Call(Type.GetProperty("Value").GetGetMethod()); // stack: [obj.Value] context.LoadWriteEmpty(); // stack: [obj.Value, writeEmpty] context.LoadContext(); // stack: [obj.Value, writeEmpty, context] context.CallSizeCounter(Type.GetGenericArguments()[0]); // stack: [counter(obj.Value, writeEmpty, context)] }
protected override bool CheckEmpty(SizeCounterMethodBuilderContext context, GroboIL.Label notEmptyLabel) { var il = context.Il; context.LoadObjByRef(); // stack: [ref obj] il.Ldfld(arrayField); // stack: [obj._array] if (context.Context.GroBufWriter.Options.HasFlag(GroBufOptions.WriteEmptyObjects)) { il.Brtrue(notEmptyLabel); // if(obj._array != null) goto notEmpty; } else { var emptyLabel = il.DefineLabel("empty"); il.Brfalse(emptyLabel); // if(obj._array == null) goto empty; context.LoadObjByRef(); // stack: [ref obj] il.Ldfld(countField); // stack: [obj._count] il.Brtrue(notEmptyLabel); // if(obj._count != 0) goto notEmpty; il.MarkLabel(emptyLabel); } return(true); }
protected override void CountSizeNotEmpty(SizeCounterMethodBuilderContext context) { var il = context.Il; il.Ldc_I4(0); // stack: [0 = size] var dataMembers = context.Context.GetDataMembers(Type); foreach (var member in dataMembers) { if (Type.IsValueType) { context.LoadObjByRef(); // stack: [size, ref obj] } else { context.LoadObj(); // stack: [size, obj] } Type memberType; switch (member.Member.MemberType) { case MemberTypes.Property: var property = (PropertyInfo)member.Member; var getter = property.GetGetMethod(true); if (getter == null) { throw new MissingMethodException(Type.Name, property.Name + "_get"); } il.Call(getter, Type); // stack: [size, obj.prop] memberType = property.PropertyType; break; case MemberTypes.Field: var field = (FieldInfo)member.Member; il.Ldfld(field); // stack: [size, obj.field] memberType = field.FieldType; break; default: throw new NotSupportedException("Data member of type " + member.Member.MemberType + " is not supported"); } il.Ldc_I4(0); // stack: [size, obj.member, false] context.LoadContext(); // stack: [size, obj.member, false, context] context.CallSizeCounter(memberType); // stack: [size, writers[i](obj.member, false, context) = memberSize] il.Dup(); // stack: [size, memberSize, memberSize] var nextLabel = il.DefineLabel("next"); il.Brfalse(nextLabel); // if(memberSize = 0) goto next; stack: [size, memberSize] il.Ldc_I4(8); // stack: [size, memberSize, 8] il.Add(); // stack: [size, memberSize + 8] il.MarkLabel(nextLabel); il.Add(); // stack: [size + curSize] } if (!context.Context.GroBufWriter.Options.HasFlag(GroBufOptions.WriteEmptyObjects)) { var countLengthLabel = il.DefineLabel("countLength"); il.Dup(); // stack: [size, size] il.Brtrue(countLengthLabel); // if(size != 0) goto countLength; stack: [size] il.Pop(); // stack: [] context.ReturnForNull(); il.Ret(); il.MarkLabel(countLengthLabel); } il.Ldc_I4(5); // stack: [size, 5] il.Add(); // stack: [size + 5] }