コード例 #1
0
 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);
 }
コード例 #2
0
        protected override void CountSizeNotEmpty(SizeCounterMethodBuilderContext context)
        {
            int[]   values;
            ulong[] hashCodes;
            EnumHelpers.BuildHashCodesTable(Type, out values, out hashCodes);
            var hashCodesField = context.Context.InitConstField(Type, 0, hashCodes);
            var valuesField    = context.Context.InitConstField(Type, 1, values);

            var il = context.Il;

            context.LoadField(valuesField); // stack: [values]
            context.LoadObj();              // stack: [values, obj]
            il.Ldc_I4(values.Length);       // stack: [values, obj, values.Length]
            il.Rem(true);                   // stack: [values, obj % values.Length]
            il.Ldelem(typeof(int));         // stack: [values[obj % values.Length]]
            context.LoadObj();              // stack: [values[obj % values.Length], obj]
            il.Ceq();                       // stack: [values[obj % values.Length] == obj]
            var countAsIntLabel = il.DefineLabel("countAsInt");

            il.Brfalse(countAsIntLabel);       // if(values[obj % values.Length] != obj) goto countAsInt
            context.LoadField(hashCodesField); // stack: [hashCodes]
            context.LoadObj();                 // stack: [hashCodes, obj]
            il.Ldc_I4(hashCodes.Length);       // stack: [hashCodes, obj, hashCodes.Length]
            il.Rem(true);                      // stack: [hashCodes, obj % hashCodes.Length]
            il.Ldelem(typeof(long));           // stack: [hashCodes[obj % hashCodes.Length] = hashCode]
            il.Brfalse(countAsIntLabel);       // if(hashCode == 0) goto countAsInt;
            il.Ldc_I4(9);                      // stack: [9]
            il.Ret();                          // return 9;
            il.MarkLabel(countAsIntLabel);
            il.Ldc_I4(5);                      // stack: [5]
        }
コード例 #3
0
        protected override void CountSizeNotEmpty(SizeCounterMethodBuilderContext context)
        {
            var customSerializerField = context.Context.InitConstField(Type, 0, customSerializer);
            var il = context.Il;

            context.LoadField(customSerializerField); // stack: [customSerializer]
            context.LoadObj();                        // stack: [customSerializer, obj]
            if (Type.IsValueType)
            {
                il.Box(Type);                                                                                                          // stack: [customSerializer, (object)obj]
            }
            context.LoadWriteEmpty();                                                                                                  // stack: [customSerializer, (object)obj, writeEmpty]
            context.LoadContext();                                                                                                     // stack: [customSerializer, (object)obj, writeEmpty, context]
            il.Call(HackHelpers.GetMethodDefinition <IGroBufCustomSerializer>(serializer => serializer.CountSize(null, false, null))); // stack: [customSerializer.CountSize((object)obj, writeEmpty, context)]

            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]
        }
コード例 #4
0
        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)]
        }
コード例 #5
0
 /// <summary>
 ///     Checks whether <c>obj</c> is empty
 /// </summary>
 /// <param name="context">Current context</param>
 /// <param name="notEmptyLabel">Label where to go if <c>obj</c> is not empty</param>
 /// <returns>true if <c>obj</c> can be empty</returns>
 protected virtual bool CheckEmpty(SizeCounterMethodBuilderContext context, GroboIL.Label notEmptyLabel)
 {
     if (Type.IsValueType)
     {
         return(false);
     }
     context.LoadObj();                // stack: [obj]
     context.Il.Brtrue(notEmptyLabel); // if(obj != null) goto notEmpty;
     return(true);
 }
コード例 #6
0
        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]
        }
コード例 #7
0
        protected override void CountSizeNotEmpty(SizeCounterMethodBuilderContext context)
        {
            var il = context.Il;

            il.Ldc_I4(5);                                                                     // stack: [5 = size] 5 = type code + data length
            context.LoadObj();                                                                // stack: [5, obj]
            il.Ldfld(Type.GetField("_size", BindingFlags.Instance | BindingFlags.NonPublic)); // stack: [5, obj.Count]
            CountArraySize(elementType, il);                                                  // stack: [5, obj length]
            il.Add();                                                                         // stack: [5 + obj length]
        }
コード例 #8
0
        protected override void CountSizeNotEmpty(SizeCounterMethodBuilderContext context)
        {
            var il = context.Il;

            context.LoadObj();             // stack: [obj]
            il.Call(lengthPropertyGetter); // stack: [obj.Length]
            il.Ldc_I4(1);                  // stack: [obj.Length, 1]
            il.Shl();                      // stack: [obj.Length << 1]
            il.Ldc_I4(5);                  // stack: [obj.Length << 1, 5]
            il.Add();                      // stack: [obj.Length << 1 + 5]
        }
コード例 #9
0
        public void BuildSizeCounter(SizeCounterBuilderContext sizeCounterBuilderContext)
        {
            var method = new DynamicMethod("Count_" + Type.Name + "_" + Guid.NewGuid(), typeof(int), new[] { Type, typeof(bool), typeof(WriterContext) }, sizeCounterBuilderContext.Module, true);

            sizeCounterBuilderContext.SetSizeCounterMethod(Type, method);
            using (var il = new GroboIL(method))
            {
                var context = new SizeCounterMethodBuilderContext(sizeCounterBuilderContext, il);

                var notEmptyLabel = il.DefineLabel("notEmpty");
                if (CheckEmpty(context, notEmptyLabel)) // Check if obj is empty
                {
                    context.ReturnForNull();            // return for null
                }
                il.MarkLabel(notEmptyLabel);            // Now we know that obj is not empty

                if (!Type.IsValueType && IsReference && sizeCounterBuilderContext.GroBufWriter.Options.HasFlag(GroBufOptions.PackReferences))
                {
                    // Pack reference
                    var index = il.DeclareLocal(typeof(int));
                    context.LoadContext();                                                                                // stack: [context]
                    il.Dup();                                                                                             // stack: [context, context]
                    il.Ldfld(WriterContext.IndexField);                                                                   // stack: [context, context.index]
                    il.Stloc(index);                                                                                      // index = context.index; stack: [context]
                    il.Ldfld(WriterContext.ObjectsField);                                                                 // stack: [context.objects]
                    context.LoadObj();                                                                                    // stack: [context.objects, obj]
                    il.Call(HackHelpers.GetMethodDefinition <Dictionary <object, int> >(dict => dict.ContainsKey(null))); // stack: [context.object.ContainsKey(obj)]
                    var storeLocationLabel = il.DefineLabel("storeLocation");
                    il.Brfalse(storeLocationLabel);                                                                       // if(!context.objects.ContainsKey(obj)) goto storeLocation; stack: []
                    context.LoadContext();                                                                                // stack: [context]
                    il.Dup();                                                                                             // stack: [context, context]
                    il.Ldfld(WriterContext.ReferencesField);                                                              // stack: [context, context.references]
                    il.Ldc_I4(1);                                                                                         // stack: [context, context.references, 1]
                    il.Add();                                                                                             // stack: [context, context.references + 1]
                    il.Stfld(WriterContext.ReferencesField);                                                              // context.references += 1; stack: []
                    il.Ldc_I4(5);                                                                                         // stack: [5]
                    il.Ret();                                                                                             // return 5
                    il.MarkLabel(storeLocationLabel);
                    context.LoadContext();                                                                                // stack: [context]
                    il.Ldfld(typeof(WriterContext).GetField("objects", BindingFlags.Public | BindingFlags.Instance));     // stack: [context.objects]
                    context.LoadObj();                                                                                    // stack: [context.objects, obj]
                    il.Ldloc(index);                                                                                      // stack: [context.objects, obj, index]
                    il.Call(HackHelpers.GetMethodDefinition <Dictionary <object, int> >(dict => dict.Add(null, 0)));      // context.objects.Add(obj, index);
                }

                CountSizeNotEmpty(context); // Count size
                il.Ret();
            }
            var @delegate = method.CreateDelegate(typeof(SizeCounterDelegate <>).MakeGenericType(Type));
            var pointer   = GroBufHelpers.ExtractDynamicMethodPointer(method);

            sizeCounterBuilderContext.SetSizeCounterPointer(Type, pointer, @delegate);
        }
コード例 #10
0
        protected override void CountSizeNotEmpty(SizeCounterMethodBuilderContext context)
        {
            var il = context.Il;

            il.Ldc_I4(4);                                                                        // stack: [4]
            context.LoadObj();                                                                   // stack: [4, obj]
            il.Ldfld(Type.GetField("m_Family", BindingFlags.Instance | BindingFlags.NonPublic)); // stack: [4, obj.m_Family]
            il.Ldc_I4((int)AddressFamily.InterNetworkV6);                                        // stack: [4, obj.m_Family, AddressFamily.InterNetworkV6]
            il.Ceq();                                                                            // stack: [4, obj.m_Family == AddressFamily.InterNetworkV6]
            il.Ldc_I4(1);                                                                        // stack: [4, obj.m_Family == AddressFamily.InterNetworkV6, 1]
            il.Shl();                                                                            // stack: [4, (obj.m_Family == AddressFamily.InterNetworkV6) << 1]
            il.Shl();                                                                            // stack: [4 << ((obj.m_Family == AddressFamily.InterNetworkV6) << 1)]
            il.Ldc_I4(5);                                                                        // stack: [4 << ((obj.m_Family == AddressFamily.InterNetworkV6) << 1), 5]
            il.Add();                                                                            // stack: [4 << ((obj.m_Family == AddressFamily.InterNetworkV6) << 1) + 5]
        }
コード例 #11
0
        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 count = il.DeclareLocal(typeof(int));

            context.LoadObj();                                                                // stack: [9, obj]
            il.Ldfld(Type.GetField("_size", BindingFlags.Instance | BindingFlags.NonPublic)); // stack: [9, obj.Count]
            il.Stloc(count);                                                                  // count = obj.Count; stack: [9]

            il.Ldloc(count);                                                                  // stack: [9, count]
            var doneLabel = il.DefineLabel("done");

            il.Brfalse(doneLabel); // if(count == 0) goto done; stack: [9]

            var items = il.DeclareLocal(elementType.MakeArrayType());

            context.LoadObj();                                                                 // stack: [9, obj]
            il.Ldfld(Type.GetField("_items", BindingFlags.Instance | BindingFlags.NonPublic)); // stack: [9, obj._items]
            il.Stloc(items);                                                                   // items = obj._items; stack: [9]
            var i = il.DeclareLocal(typeof(int));

            il.Ldc_I4(0); // stack: [9, 0]
            il.Stloc(i);  // i = 0; stack: [9]
            var cycleStartLabel = il.DefineLabel("cycleStart");

            il.MarkLabel(cycleStartLabel);

            il.Ldloc(items);                      // stack: [size, items]
            il.Ldloc(i);                          // stack: [size, items, i]
            il.Ldelem(elementType);
            il.Ldc_I4(1);                         // stack: [size, obj[i], true]
            context.LoadContext();                // stack: [size, obj[i], true, context]
            context.CallSizeCounter(elementType); // stack: [size, writer(obj[i], true, context) = itemSize]
            il.Add();                             // stack: [size + itemSize]
            il.Ldloc(count);                      // stack: [size, length]
            il.Ldloc(i);                          // stack: [size, length, i]
            il.Ldc_I4(1);                         // stack: [size, length, i, 1]
            il.Add();                             // stack: [size, length, i + 1]
            il.Dup();                             // stack: [size, length, i + 1, i + 1]
            il.Stloc(i);                          // i = i + 1; stack: [size, length, i]
            il.Bgt(cycleStartLabel, false);       // if(length > i) goto cycleStart; stack: [size]

            il.MarkLabel(doneLabel);
        }
コード例 #12
0
        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);
        }
コード例 #13
0
 protected override bool CheckEmpty(SizeCounterMethodBuilderContext context, GroboIL.Label notEmptyLabel)
 {
     context.LoadObj(); // stack: [obj]
     if (context.Context.GroBufWriter.Options.HasFlag(GroBufOptions.WriteEmptyObjects))
     {
         context.Il.Brtrue(notEmptyLabel); // if(obj != null) goto notEmpty;
     }
     else
     {
         var emptyLabel = context.Il.DefineLabel("empty");
         context.Il.Brfalse(emptyLabel);                                                           // if(obj == null) goto empty;
         context.LoadObj();                                                                        // stack: [obj]
         context.Il.Ldfld(Type.GetField("_size", BindingFlags.Instance | BindingFlags.NonPublic)); // stack: [obj.Count]
         context.Il.Brtrue(notEmptyLabel);                                                         // if(obj.Count != 0) goto notEmpty;
         context.Il.MarkLabel(emptyLabel);
     }
     return(true);
 }
コード例 #14
0
 protected override bool CheckEmpty(SizeCounterMethodBuilderContext context, GroboIL.Label notEmptyLabel)
 {
     context.LoadObj(); // stack: [obj]
     if (context.Context.GroBufWriter.Options.HasFlag(GroBufOptions.WriteEmptyObjects))
     {
         context.Il.Brtrue(notEmptyLabel); // if(obj != null) goto notEmpty;
     }
     else
     {
         var emptyLabel = context.Il.DefineLabel("empty");
         context.Il.Brfalse(emptyLabel);   // if(obj == null) goto empty;
         context.LoadObj();                // stack: [obj]
         context.Il.Ldlen();               // stack: [obj.Length]
         context.Il.Brtrue(notEmptyLabel); // if(obj.Length != 0) goto notEmpty;
         context.Il.MarkLabel(emptyLabel);
     }
     return(true);
 }
コード例 #15
0
 protected override bool CheckEmpty(SizeCounterMethodBuilderContext context, GroboIL.Label notEmptyLabel)
 {
     context.LoadObj(); // stack: [obj]
     if (context.Context.GroBufWriter.Options.HasFlag(GroBufOptions.WriteEmptyObjects))
     {
         context.Il.Brtrue(notEmptyLabel); // if(obj != null) goto notEmpty;
     }
     else
     {
         var emptyLabel = context.Il.DefineLabel("empty");
         context.Il.Brfalse(emptyLabel);                                                           // if(obj == null) goto empty;
         context.LoadObj();                                                                        // stack: [obj]
         context.Il.Ldfld(Type.GetPrivateInstanceField(PlatformHelpers.HashtableCountFieldNames)); // stack: [obj.Count]
         context.Il.Brtrue(notEmptyLabel);                                                         // if(obj.Count != 0) goto notEmpty;
         context.Il.MarkLabel(emptyLabel);
     }
     return(true);
 }
コード例 #16
0
        protected override void CountSizeNotEmpty(SizeCounterMethodBuilderContext context)
        {
            var typeCode = GroBufTypeCodeMap.GetTypeCode(Type);
            var il       = context.Il;

            switch (typeCode)
            {
            case GroBufTypeCode.Int8:
            case GroBufTypeCode.UInt8:
            case GroBufTypeCode.Boolean:
                il.Ldc_I4(2);
                break;

            case GroBufTypeCode.Int16:
            case GroBufTypeCode.UInt16:
                il.Ldc_I4(3);
                break;

            case GroBufTypeCode.Int32:
            case GroBufTypeCode.UInt32:
                il.Ldc_I4(5);
                break;

            case GroBufTypeCode.Int64:
            case GroBufTypeCode.UInt64:
                il.Ldc_I4(9);
                break;

            case GroBufTypeCode.Single:
                il.Ldc_I4(5);
                break;

            case GroBufTypeCode.Double:
                il.Ldc_I4(9);
                break;

            case GroBufTypeCode.Decimal:
                il.Ldc_I4(17);
                break;

            default:
                throw new NotSupportedException("Type '" + Type + "' is not supported");
            }
        }
コード例 #17
0
        protected override void CountSizeNotEmpty(SizeCounterMethodBuilderContext context)
        {
            var il       = context.Il;
            var argument = Type.GetGenericArguments()[0];

            context.LoadObj(); // stack: [obj]
            var factoryField = Type.GetField("m_valueFactory", BindingFlags.Instance | BindingFlags.NonPublic);

            il.Ldfld(factoryField); // stack: [obj.m_valueFactory]
            var factory = il.DeclareLocal(typeof(Func <>).MakeGenericType(argument));

            il.Dup();
            il.Stloc(factory); // factory = obj.m_valueFactory; stack: [factory]
            var countUsual = il.DefineLabel("countUsual");

            il.Brfalse(countUsual); // if(factory == null) goto countUsual; stack: []
            il.Ldloc(factory);      // stack: [factory]
            string targetFieldName = GroBufHelpers.IsMono ? "m_target" : "_target";

            il.Ldfld(typeof(Delegate).GetField(targetFieldName, BindingFlags.Instance | BindingFlags.NonPublic)); // stack: [factory.target]
            var rawData = il.DeclareLocal(typeof(RawData <>).MakeGenericType(Type.GetGenericArguments()));

            il.Isinst(rawData.Type);                                                                         // stack: [factory.target as RawData]
            il.Dup();
            il.Stloc(rawData);                                                                               // rawData = factory.target as RawData; stack: [rawData]
            il.Brfalse(countUsual);                                                                          // if(!(rawData is RawData)) goto countUsual; stack: []
            il.Ldloc(rawData);                                                                               // stack: [rawData]
            il.Ldfld(rawData.Type.GetField("serializerId", BindingFlags.Instance | BindingFlags.NonPublic)); // stack: [rawData.serializerId]
            context.LoadSerializerId();                                                                      // stack: [rawData.serializerId, context.serializerId]
            il.Bne_Un(countUsual);                                                                           // if(rawData.serializerId != context.serializerId) goto countUsual; stack: []
            il.Ldloc(rawData);                                                                               // stack: [rawData]
            il.Ldfld(rawData.Type.GetField("data", BindingFlags.Instance | BindingFlags.NonPublic));         // stack: [rawData.data]
            il.Ldlen();                                                                                      // stack: [rawData.data.Length]
            il.Ret();

            il.MarkLabel(countUsual);
            context.LoadObj();                                                                              // stack: [obj]
            il.Call(Type.GetProperty("Value", BindingFlags.Instance | BindingFlags.Public).GetGetMethod()); // stack: [obj.Value]
            context.LoadWriteEmpty();                                                                       // stack: [obj.Value, writeEmpty]
            context.LoadContext();                                                                          // stack: [obj.Value, writeEmpty, context]
            context.CallSizeCounter(argument);                                                              // stack: [counter(obj.Value, writeEmpty, context)]
        }
コード例 #18
0
        protected override void CountSizeNotEmpty(SizeCounterMethodBuilderContext context)
        {
            var il = context.Il;

            il.Ldc_I4(5); // stack: [5 = size]

            var genericArguments = Type.GetGenericArguments();

            for (int i = 0; i < genericArguments.Length; ++i)
            {
                var property = Type.GetProperty(i == 7 ? "Rest" : "Item" + (i + 1));
                var getter   = property.GetGetMethod();
                context.LoadObj();                            // stack: [size, obj]
                il.Call(getter);                              // stack: [size, obj.Item{i}]
                il.Ldc_I4(1);                                 // stack: [size, obj.Item{i}, true]
                context.LoadContext();                        // stack: [size, obj.Item{i}, true, context]
                context.CallSizeCounter(genericArguments[i]); // stack: [size, writers[i](obj.Item{i}, true, context) = memberSize]
                il.Add();                                     // stack: [size + memberSize => size]
            }
        }
コード例 #19
0
        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);
        }
コード例 #20
0
        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 length = il.DeclareLocal(typeof(int));

            context.LoadObj(); // stack: [9, obj]
            il.Ldlen();        // stack: [9, obj.Length]
            il.Stloc(length);  // length = obj.Length; stack: [9]
            var doneLabel = il.DefineLabel("done");

            il.Ldloc(length);      // stack: [size, length]
            il.Brfalse(doneLabel); // if(length == 0) goto done; stack: [size]
            var i = il.DeclareLocal(typeof(int));

            il.Ldc_I4(0); // stack: [size, 0]
            il.Stloc(i);  // i = 0; stack: [size]
            var cycleStartLabel = il.DefineLabel("cycleStart");

            il.MarkLabel(cycleStartLabel);
            context.LoadObj();                    // stack: [size, obj]
            il.Ldloc(i);                          // stack: [size, obj, i]
            il.Ldelem(elementType);
            il.Ldc_I4(1);                         // stack: [size, obj[i], true]
            context.LoadContext();                // stack: [size, obj[i], true, context]
            context.CallSizeCounter(elementType); // stack: [size, writer(obj[i], true, context) = itemSize]
            il.Add();                             // stack: [size + itemSize]
            il.Ldloc(length);                     // stack: [size, length]
            il.Ldloc(i);                          // stack: [size, length, i]
            il.Ldc_I4(1);                         // stack: [size, length, i, 1]
            il.Add();                             // stack: [size, length, i + 1]
            il.Dup();                             // stack: [size, length, i + 1, i + 1]
            il.Stloc(i);                          // i = i + 1; stack: [size, length, i]
            il.Bgt(cycleStartLabel, false);       // if(length > i) goto cycleStart; stack: [size]
            il.MarkLabel(doneLabel);
        }
コード例 #21
0
        private static KeyValuePair <Delegate, IntPtr> GetCounter(SizeCounterMethodBuilderContext context, Type type)
        {
            var method = new DynamicMethod("CastTo_" + type.Name + "_AndCount_" + Guid.NewGuid(), typeof(int), new[] { typeof(object), typeof(bool), typeof(WriterContext) }, context.Context.Module, true);

            using (var il = new GroboIL(method))
            {
                il.Ldarg(0); // stack: [obj]
                if (type.IsValueType)
                {
                    il.Unbox_Any(type); // stack: [(type)obj]
                }
                else
                {
                    il.Castclass(type); // stack: [(type)obj]
                }
                il.Ldarg(1);            // stack: [(type)obj, writeEmpty]
                il.Ldarg(2);            // stack: [(type)obj, writeEmpty, context]
                context.CallSizeCounter(il, type);
                il.Ret();
            }
            var @delegate = method.CreateDelegate(typeof(SizeCounterDelegate <object>));

            return(new KeyValuePair <Delegate, IntPtr>(@delegate, GroBufHelpers.ExtractDynamicMethodPointer(method)));
        }
コード例 #22
0
        protected override void CountSizeNotEmpty(SizeCounterMethodBuilderContext context)
        {
            var il = context.Il;

            il.Ldc_I4(9);      // stack: [9 = size] 9 = type code + data length + hashset count

            context.LoadObj(); // stack: [size, obj]
            var count = il.DeclareLocal(typeof(int));

            il.Ldfld(Type.GetPrivateInstanceField(PlatformHelpers.HashSetCountFieldNames)); // stack: [size, obj.m_lastIndex]
            il.Dup();
            il.Stloc(count);                                                                // count = obj.m_lastIndex; stack: [size, count]
            var doneLabel = il.DefineLabel("done");

            il.Brfalse(doneLabel); // if(!count) goto done; stack: [size]

            context.LoadObj();     // stack: [size, obj]
            var slotType = Type.GetNestedType(PlatformHelpers.HashSetSlotTypeName, BindingFlags.NonPublic).MakeGenericType(Type.GetGenericArguments());
            var slots    = il.DeclareLocal(slotType.MakeArrayType());

            il.Ldfld(Type.GetPrivateInstanceField(PlatformHelpers.HashSetSlotsFieldNames));
            il.Stloc(slots);

            var i = il.DeclareLocal(typeof(int));

            il.Ldc_I4(0); // stack: [9, 0]
            il.Stloc(i);  // i = 0; stack: [9]
            var cycleStartLabel = il.DefineLabel("cycleStart");

            il.MarkLabel(cycleStartLabel);
            il.Ldloc(slots);      // stack: [size, slots]
            il.Ldloc(i);          // stack: [size, slots, i]
            il.Ldelema(slotType); // stack: [size, &slots[i]]
            il.Dup();             // stack: [size, &slots[i], &slots[i]]
            var slot = il.DeclareLocal(slotType.MakeByRefType());

            il.Stloc(slot); // slot = &slots[i]; stack: [size, slot]
            if (PlatformHelpers.IsDotNet50OrGreater)
            {
                il.Ldfld(slotType.GetField("Next")); // stack: [size, slot.Next]
                il.Ldc_I4(-1);                       // stack: [size, slot.Next, -1]
            }
            else
            {
                il.Ldfld(slotType.GetField("hashCode", BindingFlags.Instance | BindingFlags.NonPublic)); // stack: [size, slot.hashCode]
                il.Ldc_I4(0);                                                                            // stack: [size, slot.hashCode, 0]
            }
            var nextLabel = il.DefineLabel("next");

            il.Blt(nextLabel, false);                                                                                                                     // if(slot.hashCode < 0) goto next; stack: [size]

            il.Ldloc(slot);                                                                                                                               // stack: [size, slot]
            il.Ldfld(slotType.GetField(PlatformHelpers.HashSetSlotValueFieldName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)); // stack: [size, slot.value]
            il.Ldc_I4(1);                                                                                                                                 // stack: [size, slot.value, true]
            context.LoadContext();                                                                                                                        // stack: [size, slot.value, true, context]
            context.CallSizeCounter(elementType);                                                                                                         // stack: [size, writer(slot.value, true, context) = valueSize]
            il.Add();                                                                                                                                     // stack: [size + valueSize]

            il.MarkLabel(nextLabel);

            il.Ldloc(count);                // stack: [size, count]
            il.Ldloc(i);                    // stack: [size, count, i]
            il.Ldc_I4(1);                   // stack: [size, count, i, 1]
            il.Add();                       // stack: [size, count, i + 1]
            il.Dup();                       // stack: [size, count, i + 1, i + 1]
            il.Stloc(i);                    // i = i + 1; stack: [size, count, i]
            il.Bgt(cycleStartLabel, false); // if(count > i) goto cycleStart; stack: [size]

            il.MarkLabel(doneLabel);
        }
コード例 #23
0
        protected override void CountSizeNotEmpty(SizeCounterMethodBuilderContext context)
        {
            var il = context.Il;

            il.Ldc_I4(9);                                                                     // stack: [9 = size] 9 = type code + data length + dictionary count
            context.LoadObj();                                                                // stack: [size, obj]
            il.Ldfld(Type.GetField("count", BindingFlags.Instance | BindingFlags.NonPublic)); // stack: [size, obj.Count]

            var doneLabel = il.DefineLabel("done");

            il.Brfalse(doneLabel); // if(count == 0) goto done; stack: [size]

            context.LoadObj();     // stack: [size, obj]
            var bucketType   = Type.GetNestedType("bucket", BindingFlags.NonPublic);
            var buckets      = il.DeclareLocal(bucketType.MakeArrayType());
            var bucketsField = Type.GetField("buckets", BindingFlags.Instance | BindingFlags.NonPublic);

            il.Ldfld(bucketsField); // stack: [size, obj.buckets]
            il.Stloc(buckets);      // buckets = obj.buckets; stack: [size]
            var length = il.DeclareLocal(typeof(int));

            il.Ldloc(buckets); // stack: [size, buckets]
            il.Ldlen();        // stack: [size, buckets.Length]
            il.Stloc(length);  // length = buckets.Length

            var i = il.DeclareLocal(typeof(int));

            il.Ldc_I4(0); // stack: [9, 0]
            il.Stloc(i);  // i = 0; stack: [9]
            var cycleStartLabel = il.DefineLabel("cycleStart");

            il.MarkLabel(cycleStartLabel);
            il.Ldloc(buckets);      // stack: [size, buckets]
            il.Ldloc(i);            // stack: [size, buckets, i]
            il.Ldelema(bucketType); // stack: [size, &buckets[i]]
            il.Dup();               // stack: [size, &entries[i], &buckets[i]]
            var bucket = il.DeclareLocal(bucketType.MakeByRefType());

            il.Stloc(bucket);                                                                  // bucket = &buckets[i]; stack: [size, bucket]
            il.Ldfld(bucketType.GetField("key", BindingFlags.Public | BindingFlags.Instance)); // stack: [size, bucket.key]
            il.Dup();                                                                          // stack: [size, bucket.key, bucket.key]
            var key = il.DeclareLocal(typeof(object));

            il.Stloc(key); // key = bucket.key; stack: [size, key]

            var nextLabel = il.DefineLabel("next");

            il.Brfalse(nextLabel);                                                             // if(bucket.key == null) goto next; stack: [size]

            il.Ldloc(key);                                                                     // stack: [size, key]
            context.LoadObj();                                                                 // stack: [size, key, obj]
            il.Ldfld(bucketsField);                                                            // stack: [size, key, obj.buckets]
            il.Beq(nextLabel);                                                                 // if(key == obj.buckets) goto next; stack: [size]

            il.Ldloc(key);                                                                     // stack: [size, key]
            il.Ldc_I4(1);                                                                      // stack: [size, key, true]
            context.LoadContext();                                                             // stack: [size, key, true, context]
            context.CallSizeCounter(typeof(object));                                           // stack: [size, writer(key, true, context) = keySize]
            il.Add();                                                                          // stack: [size + keySize]

            il.Ldloc(bucket);                                                                  // stack: [size, bucket]
            il.Ldfld(bucketType.GetField("val", BindingFlags.Public | BindingFlags.Instance)); // stack: [size, bucket.val]
            il.Ldc_I4(1);                                                                      // stack: [size, bucket.val, true]
            context.LoadContext();                                                             // stack: [size, bucket.val, true, context]
            context.CallSizeCounter(typeof(object));                                           // stack: [size, writer(bucket.val, true, context) = valueSize]
            il.Add();                                                                          // stack: [size + valueSize]

            il.MarkLabel(nextLabel);
            il.Ldloc(length);               // stack: [size, length]
            il.Ldloc(i);                    // stack: [size, length, i]
            il.Ldc_I4(1);                   // stack: [size, length, i, 1]
            il.Add();                       // stack: [size, length, i + 1]
            il.Dup();                       // stack: [size, length, i + 1, i + 1]
            il.Stloc(i);                    // i = i + 1; stack: [size, length, i]
            il.Bgt(cycleStartLabel, false); // if(length > i) goto cycleStart; stack: [size]

            il.MarkLabel(doneLabel);
        }
コード例 #24
0
        protected override void CountSizeNotEmpty(SizeCounterMethodBuilderContext context)
        {
            var il = context.Il;

            il.Ldc_I4(9); // stack: [9]
        }
コード例 #25
0
        protected override void CountSizeNotEmpty(SizeCounterMethodBuilderContext context)
        {
            var il = context.Il;

            il.Ldc_I4(9);      // stack: [9 = size] 9 = type code + data length + dictionary count
            context.LoadObj(); // stack: [size, obj]
            var count = il.DeclareLocal(typeof(int));

            // traverse all buckets
            il.Ldfld(Type.GetField("count", BindingFlags.Instance | BindingFlags.NonPublic)); // stack: [size, obj.Count]
            il.Stloc(count);                                                                  // count = obj.Count; stack: [size]

            var doneLabel = il.DefineLabel("done");

            il.Ldloc(count);       // stack: [size, count]
            il.Brfalse(doneLabel); // if(count == 0) goto done; stack: [size]

            context.LoadObj();     // stack: [size, obj]
            var entryType = Type.GetNestedType("Entry", BindingFlags.NonPublic).MakeGenericType(Type.GetGenericArguments());
            var entries   = il.DeclareLocal(entryType.MakeArrayType());

            il.Ldfld(Type.GetField("entries", BindingFlags.Instance | BindingFlags.NonPublic));
            il.Stloc(entries);

            var i = il.DeclareLocal(typeof(int));

            il.Ldc_I4(0); // stack: [9, 0]
            il.Stloc(i);  // i = 0; stack: [9]
            var cycleStartLabel = il.DefineLabel("cycleStart");

            il.MarkLabel(cycleStartLabel);
            il.Ldloc(entries);     // stack: [size, entries]
            il.Ldloc(i);           // stack: [size, entries, i]
            il.Ldelema(entryType); // stack: [size, &entries[i]]
            il.Dup();              // stack: [size, &entries[i], &entries[i]]
            var entry = il.DeclareLocal(entryType.MakeByRefType());

            il.Stloc(entry);                          // entry = &entries[i]; stack: [size, entry]
            il.Ldfld(entryType.GetField("hashCode")); // stack: [size, entry.hashCode]
            il.Ldc_I4(0);                             // stack: [size, entry.hashCode, 0]
            var nextLabel = il.DefineLabel("next");

            il.Blt(nextLabel, false);              // if(entry.hashCode < 0) goto next; stack: [size]

            il.Ldloc(entry);                       // stack: [size, entry]
            il.Ldfld(entryType.GetField("key"));   // stack: [size, entry.key]
            il.Ldc_I4(1);                          // stack: [size, entry.key, true]
            context.LoadContext();                 // stack: [size, entry.key, true, context]
            context.CallSizeCounter(keyType);      // stack: [size, writer(entry.key, true, context) = keySize]
            il.Add();                              // stack: [size + keySize]

            il.Ldloc(entry);                       // stack: [size, entry]
            il.Ldfld(entryType.GetField("value")); // stack: [size, entry.value]
            il.Ldc_I4(1);                          // stack: [size, entry.value, true]
            context.LoadContext();                 // stack: [size, entry.value, true, context]
            context.CallSizeCounter(valueType);    // stack: [size, writer(entry.value, true, context) = valueSize]
            il.Add();                              // stack: [size + valueSize]

            il.MarkLabel(nextLabel);
            il.Ldloc(count);                // stack: [size, count]
            il.Ldloc(i);                    // stack: [size, count, i]
            il.Ldc_I4(1);                   // stack: [size, count, i, 1]
            il.Add();                       // stack: [size, count, i + 1]
            il.Dup();                       // stack: [size, count, i + 1, i + 1]
            il.Stloc(i);                    // i = i + 1; stack: [size, count, i]
            il.Bgt(cycleStartLabel, false); // if(count > i) goto cycleStart; stack: [size]

            il.MarkLabel(doneLabel);
        }
コード例 #26
0
 protected override void CountSizeNotEmpty(SizeCounterMethodBuilderContext context)
 {
     // TODO call sub size counters
     context.Il.Ldc_I4(1 + 9 + 3); // stack: [13]
 }
コード例 #27
0
 protected abstract void CountSizeNotEmpty(SizeCounterMethodBuilderContext context);
コード例 #28
0
        protected override void CountSizeNotEmpty(SizeCounterMethodBuilderContext context)
        {
            var il = context.Il;

            var counters      = GroBufHelpers.LeafTypes.Select(type1 => type1 == null ? new KeyValuePair <Delegate, IntPtr>(null, IntPtr.Zero) : GetCounter(context, type1)).ToArray();
            var countersField = context.Context.InitConstField(Type, 0, counters.Select(pair => pair.Value).ToArray());

            context.Context.InitConstField(Type, 1, counters.Select(pair => pair.Key).ToArray());

            il.Ldfld(typeof(GroBufHelpers).GetField("LeafTypeHandles", BindingFlags.Public | BindingFlags.Static)); // stack: [LeafTypeHandles]
            context.LoadObj();                                                                                      // stack: [LeafTypeHandles, obj]
            il.Call(getTypeMethod);                                                                                 // stack: [LeafTypeHandles, obj.GetType()]
            var type = il.DeclareLocal(typeof(Type));

            il.Dup();                                       // stack: [LeafTypeHandles, obj.GetType(), obj.GetType()]
            il.Stloc(type);                                 // type = obj.GetType(); stack: [LeafTypeHandles, obj.GetType()]
            il.Call(typeTypeHandleProperty.GetGetMethod()); // stack: [LeafTypeHandles, obj.GetType().TypeHandle]
            var typeHandle = il.DeclareLocal(typeof(RuntimeTypeHandle));

            il.Stloc(typeHandle);                                                              // typeHandle = obj.GetType().TypeHandle; stack: [LeafTypeHandles]
            il.Ldloca(typeHandle);                                                             // stack: [LeafTypeHandles, ref typeHandle]
            il.Call(runtimeTypeHandleValueProperty.GetGetMethod(), typeof(RuntimeTypeHandle)); // stack: [LeafTypeHandles, obj.GetType().TypeHandle.Value]
            var handle = il.DeclareLocal(typeof(IntPtr));

            il.Dup();                   // stack: [LeafTypeHandles, obj.GetType().TypeHandle.Value, obj.GetType().TypeHandle.Value]
            il.Stloc(handle);           // handle = obj.GetType().TypeHandle.Value; stack: [LeafTypeHandles, handle]
            il.Ldc_I4(counters.Length); // stack: [LeafTypeHandles, handle, LeafTypeHandles.Length]
            il.Rem(true);               // stack: [LeafTypeHandles, handle % LeafTypeHandles.Length]
            var index = il.DeclareLocal(typeof(int));

            il.Conv <int>();           // stack: [LeafTypeHandles, (int)(handle % LeafTypeHandles.Length)]
            il.Dup();                  // stack: [LeafTypeHandles, (int)(handle % LeafTypeHandles.Length), (int)(handle % LeafTypeHandles.Length)]
            il.Stloc(index);           // index = (int)(handle % LeafTypeHandles.Length); stack: [LeafTypeHandles, index]
            il.Ldelem(typeof(IntPtr)); // stack: [LeafTypeHandles[index]]
            il.Ldloc(handle);          // stack: [LeafTypeHandles[index], handle]
            var tryAsArrayLabel = il.DefineLabel("tryAsArray");

            il.Bne_Un(tryAsArrayLabel);       // if(LeafTypeHandles[index] != handle) goto tryAsArray; stack: []
            context.LoadObj();                // stack: [obj]
            context.LoadWriteEmpty();         // stack: [obj, writeEmpty]
            context.LoadContext();            // stack: [obj, writeEmpty, context]
            context.LoadField(countersField); // stack: [obj, writeEmpty, context, counters]
            il.Ldloc(index);                  // stack: [obj, writeEmpty, context, counters, index]
            il.Ldelem(typeof(IntPtr));        // stack: [obj, writeEmpty, context, counters[index]]
            var parameterTypes = new[] { typeof(object), typeof(bool), typeof(WriterContext) };

            il.Calli(CallingConventions.Standard, typeof(int), parameterTypes); // stack: [counters[index](obj, writeEmpty)]
            il.Ret();

            il.MarkLabel(tryAsArrayLabel);
            il.Ldloc(type);                              // stack: [obj.GetType()]
            il.Call(typeIsArrayProperty.GetGetMethod()); // stack: [obj.GetType().IsArray]
            var returnForNullLabel = il.DefineLabel("returnForNull");

            il.Brfalse(returnForNullLabel);
            context.LoadObj();                                                   // stack: [obj]
            context.LoadWriteEmpty();                                            // stack: [obj, writeEmpty]
            context.LoadContext();                                               // stack: [obj, writeEmpty, context]
            context.LoadField(countersField);                                    // stack: [obj, writeEmpty, context, counters]
            il.Ldc_I4(Array.IndexOf(GroBufHelpers.LeafTypes, typeof(object[]))); // stack: [obj, writeEmpty, context, counters, index of typeof(object[])]
            il.Ldelem(typeof(IntPtr));                                           // stack: [obj, writeEmpty, context, counters[index of typeof(object[])]]
            parameterTypes = new[] { typeof(object), typeof(bool), typeof(WriterContext) };
            il.Calli(CallingConventions.Standard, typeof(int), parameterTypes);  // stack: [counters[index of typeof(object[])](obj, writeEmpty)]
            il.Ret();

            il.MarkLabel(returnForNullLabel);
            context.ReturnForNull();
        }
コード例 #29
0
        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]
        }
コード例 #30
0
 protected override void CountSizeNotEmpty(SizeCounterMethodBuilderContext context)
 {
     context.Il.Ldc_I4(17); // stack: [17]
 }