protected override unsafe void WriteNotEmpty(WriterMethodBuilderContext context)
        {
            var il       = context.Il;
            var typeCode = GroBufTypeCodeMap.GetTypeCode(Type);

            context.WriteTypeCode(typeCode);
            var size = il.DeclareLocal(typeof(int));

            il.Ldc_I4(4);
            context.AssertLength();

            context.GoToCurrentLocation();   // stack: [&result[index]]
            context.LoadObjByRef();          // stack: [&result[index], ref obj]
            il.Ldfld(countField);            // stack: [&result[index], obj._count]
            CountArraySize(elementType, il); // stack: [&result[index], obj size]
            il.Dup();                        // stack: [&result[index], obj size, obj size]
            il.Stloc(size);                  // size = obj size; stack: [&result[index], obj size]
            il.Stind(typeof(int));           // result[index] = size; stack: []
            context.IncreaseIndexBy4();      // index = index + 4; stack: []

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

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

            il.Ldloc(size);
            context.AssertLength();

            context.GoToCurrentLocation(); // stack: [&result[index]]
            context.LoadObjByRef();        // stack: [&result[index], ref obj]
            il.Ldfld(arrayField);          // stack: [&result[index], obj._array]
            context.LoadObjByRef();        // stack: [&result[index], obj._array, ref obj]
            il.Ldfld(offsetField);         // stack: [&result[index], obj._array, obj._offset]
            il.Ldelema(elementType);       // stack: [&result[index], &obj._array[obj._offset]]
            var arr = il.DeclareLocal(elementType.MakeByRefType(), true);

            il.Stloc(arr);            // arr = &obj._array[obj._offset]; stack: [&result[index]]
            il.Ldloc(arr);            // stack: [&result[index], arr]
            il.Ldloc(size);           // stack: [&result[index], arr + obj._offset, size]
            il.Cpblk();               // &result[index] = arr
            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.MarkLabel(doneLabel);
        }
Beispiel #2
0
 protected override bool CheckEmpty(WriterMethodBuilderContext 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 WriteNotEmpty(WriterMethodBuilderContext context)
        {
            var il = context.Il;

            context.WriteTypeCode(GroBufTypeCode.Guid);
            il.Ldc_I4(16);
            context.AssertLength();
            context.GoToCurrentLocation(); // stack: [&result[index]]
            context.LoadObjByRef();        // stack: [&result[index], &obj]
            il.Ldind(typeof(long));        // stack: [&result[index], (int64)*obj]
            il.Stind(typeof(long));        // result[index] = (int64)*obj
            context.IncreaseIndexBy8();    // index = index + 8
            context.GoToCurrentLocation(); // stack: [&result[index]]
            context.LoadObjByRef();        // stack: [&result[index], &obj]
            il.Ldc_I4(8);                  // stack: [&result[index], &obj, 8]
            il.Add();                      // stack: [&result[index], &obj + 8]
            il.Ldind(typeof(long));        // stack: [&result[index], *(&obj+8)]
            il.Stind(typeof(long));        // result[index] = (int64)*(obj + 8)
            context.IncreaseIndexBy8();    // index = index + 8
        }
        protected override bool CheckEmpty(WriterMethodBuilderContext 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 WriteNotEmpty(WriterMethodBuilderContext context)
        {
            var il = context.Il;

            context.LoadObjByRef();                                                            // stack: [obj]
            il.Ldfld(Type.GetField("_ticks", BindingFlags.Instance | BindingFlags.NonPublic)); // stack: [obj._ticks]
            context.LoadWriteEmpty();                                                          // stack: [obj._ticks, writeEmpty]
            context.LoadResult();                                                              // stack: [obj._ticks, writeEmpty, result]
            context.LoadIndexByRef();                                                          // stack: [obj._ticks, writeEmpty, result, ref index]
            context.LoadContext();                                                             // stack: [obj._ticks, writeEmpty, result, ref index, context]
            context.CallWriter(typeof(long));                                                  // writer(obj._ticks, writeEmpty, result, ref index, context)
        }
        protected override void WriteNotEmpty(WriterMethodBuilderContext context)
        {
            var il = context.Il;

            context.WriteTypeCode(GroBufTypeCode.DateTimeOffset);
            context.LoadObjByRef();                                                                        // stack: [obj]
            il.Ldfld(Type.GetPrivateInstanceField(PlatformHelpers.DateTimeOffsetDateTimeFieldNames));      // stack: [obj.m_dateTime]
            context.LoadWriteEmpty();                                                                      // stack: [obj.m_dateTime, writeEmpty]
            context.LoadResult();                                                                          // stack: [obj.m_dateTime, writeEmpty, result]
            context.LoadIndexByRef();                                                                      // stack: [obj.m_dateTime, writeEmpty, result, ref index]
            context.LoadContext();                                                                         // stack: [obj.m_dateTime, writeEmpty, result, ref index, context]
            context.CallWriter(typeof(DateTime));                                                          // writer(obj.m_dateTime, writeEmpty, result, ref index, context)

            context.LoadObjByRef();                                                                        // stack: [obj]
            il.Ldfld(Type.GetPrivateInstanceField(PlatformHelpers.DateTimeOffsetOffsetMinutesFieldNames)); // stack: [obj.m_offsetMinutes]
            context.LoadWriteEmpty();                                                                      // stack: [obj.m_offsetMinutes, writeEmpty]
            context.LoadResult();                                                                          // stack: [obj.m_offsetMinutes, writeEmpty, result]
            context.LoadIndexByRef();                                                                      // stack: [obj.m_offsetMinutes, writeEmpty, result, ref index]
            context.LoadContext();                                                                         // stack: [obj.m_offsetMinutes, writeEmpty, result, ref index, context]
            context.CallWriter(typeof(short));                                                             // writer(obj.m_offsetMinutes, writeEmpty, result, ref index, context)
        }
Beispiel #7
0
        protected override void WriteNotEmpty(WriterMethodBuilderContext 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.LoadResult();                              // stack: [obj.Value, writeEmpty, result]
            context.LoadIndexByRef();                          // stack: [obj.Value, writeEmpty, result, ref index]
            context.LoadContext();                             // stack: [obj.Value, writeEmpty, result, ref index, context]
            context.CallWriter(Type.GetGenericArguments()[0]); // writer(obj.Value, writeEmpty, result, ref index, context)
        }
Beispiel #8
0
        protected override void WriteNotEmpty(WriterMethodBuilderContext context)
        {
            var il = context.Il;

            context.WriteTypeCode(GroBufTypeCode.DateTimeOffset);
            context.LoadObjByRef();                                                                     // stack: [obj]
            il.Ldfld(Type.GetField("m_dateTime", BindingFlags.Instance | BindingFlags.NonPublic));      // stack: [obj.m_dateTime]
            context.LoadWriteEmpty();                                                                   // stack: [obj.m_dateTime, writeEmpty]
            context.LoadResult();                                                                       // stack: [obj.m_dateTime, writeEmpty, result]
            context.LoadIndexByRef();                                                                   // stack: [obj.m_dateTime, writeEmpty, result, ref index]
            context.LoadContext();                                                                      // stack: [obj.m_dateTime, writeEmpty, result, ref index, context]
            context.CallWriter(typeof(DateTime));                                                       // writer(obj.m_dateTime, writeEmpty, result, ref index, context)

            context.LoadObjByRef();                                                                     // stack: [obj]
            il.Ldfld(Type.GetField("m_offsetMinutes", BindingFlags.Instance | BindingFlags.NonPublic)); // stack: [obj.m_offsetMinutes]
            context.LoadWriteEmpty();                                                                   // stack: [obj.m_offsetMinutes, writeEmpty]
            context.LoadResult();                                                                       // stack: [obj.m_offsetMinutes, writeEmpty, result]
            context.LoadIndexByRef();                                                                   // stack: [obj.m_offsetMinutes, writeEmpty, result, ref index]
            context.LoadContext();                                                                      // stack: [obj.m_offsetMinutes, writeEmpty, result, ref index, context]
            context.CallWriter(typeof(short));                                                          // writer(obj.m_offsetMinutes, writeEmpty, result, ref index, context)
        }
Beispiel #9
0
        protected override void WriteNotEmpty(WriterMethodBuilderContext context)
        {
            var il = context.Il;

            context.WriteTypeCode(GroBufTypeCode.DateTimeNew);
            il.Ldc_I4(8);
            context.AssertLength();
            context.GoToCurrentLocation();         // stack: [&result[index]]
            context.LoadObjByRef();                // stack: [&result[index], &obj]
            il.Call(dateTimeToBinaryMethod, Type); // stack: [&result[index], obj.ToBinary()]
            il.Stind(typeof(long));                // result[index] = obj.ToBinary()
            context.IncreaseIndexBy8();            // index = index + 8
        }
        protected override void WriteNotEmpty(WriterMethodBuilderContext context)
        {
            var il = context.Il;

            context.WriteTypeCode(GroBufTypeCode.Array);
            var length = il.DeclareLocal(typeof(int));

            context.LoadObjByRef(); // stack: [ref obj]
            il.Ldfld(countField);   // stack: [obj._count]
            il.Stloc(length);       // length = obj._count
            context.LoadIndex();    // stack: [index]
            var start = context.LocalInt;

            il.Stloc(start);               // start = index
            il.Ldc_I4(8);
            context.AssertLength();        // 8 = data size + array length
            context.IncreaseIndexBy4();    // index = index + 4
            context.GoToCurrentLocation(); // stack: [&result[index]]
            il.Ldloc(length);              // stack: [&result[index], length]
            il.Stind(typeof(int));         // *(int*)&result[index] = length; stack: []
            context.IncreaseIndexBy4();    // index = index + 4

            var writeDataLengthLabel = il.DefineLabel("writeDataLength");

            il.Ldloc(length);                 // stack: [length]
            il.Brfalse(writeDataLengthLabel); // if(length == 0) goto writeDataLength; stack: []

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

            context.LoadObjByRef(); // stack: [ref obj]
            il.Ldfld(offsetField);  // stack: [obj._offset]
            il.Dup();               // stack: [obj._offset, obj._offset]
            il.Stloc(i);            // i = obj._offset; stack: [obj._offset]
            il.Ldloc(length);       // stack: [obj._offset, length]
            il.Add();               // stack: [obj._offset + length]
            il.Stloc(length);       // length = obj._offset + length; stack: []
            var array = il.DeclareLocal(elementType.MakeArrayType());

            context.LoadObjByRef(); // stack: [ref obj]
            il.Ldfld(arrayField);   // stack: [obj._array]
            il.Stloc(array);        // array = obj._array; stack: []
            var cycleStart = il.DefineLabel("cycleStart");

            il.MarkLabel(cycleStart);

            il.Ldloc(array);                 // stack: [array]
            il.Ldloc(i);                     // stack: [array, i]
            il.Ldelem(elementType);
            il.Ldc_I4(1);                    // stack: [array[i], true]
            context.LoadResult();            // stack: [array[i], true, result]
            context.LoadIndexByRef();        // stack: [array[i], true, result, ref index]
            context.LoadContext();           // stack: [array[i], true, result, ref index, context]
            context.CallWriter(elementType); // writer(array[i], true, result, ref index, context); stack: []
            il.Ldloc(length);                // stack: [length]
            il.Ldloc(i);                     // stack: [length, i]
            il.Ldc_I4(1);                    // stack: [length, i, 1]
            il.Add();                        // stack: [length, i + 1]
            il.Dup();                        // stack: [length, i + 1, i + 1]
            il.Stloc(i);                     // i = i + 1; stack: [length, i]
            il.Bgt(cycleStart, false);       // if(length > i) goto cycleStart; stack: []

            il.MarkLabel(writeDataLengthLabel);
            context.LoadResult();  // stack: [result]
            il.Ldloc(start);       // stack: [result, start]
            il.Add();              // stack: [result + start]
            context.LoadIndex();   // stack: [result + start, index]
            il.Ldloc(start);       // stack: [result + start, index, start]
            il.Sub();              // stack: [result + start, index - start]
            il.Ldc_I4(4);          // stack: [result + start, index - start, 4]
            il.Sub();              // stack: [result + start, index - start - 4]
            il.Stind(typeof(int)); // *(int*)(result + start) = index - start - 4
        }
Beispiel #11
0
        protected override void WriteNotEmpty(WriterMethodBuilderContext context)
        {
            var typeCode = GroBufTypeCodeMap.GetTypeCode(Type);

            context.WriteTypeCode(typeCode);
            context.GoToCurrentLocation(); // stack: [&result[index]]
            var il = context.Il;

            switch (typeCode)
            {
            case GroBufTypeCode.Int8:
            case GroBufTypeCode.UInt8:
            case GroBufTypeCode.Boolean:
                il.Ldc_I4(1);
                context.AssertLength();
                context.LoadObj();          // stack: [&result[index], obj]
                il.Stind(typeof(byte));     // result[index] = obj
                context.IncreaseIndexBy1(); // index = index + 1
                break;

            case GroBufTypeCode.Int16:
            case GroBufTypeCode.UInt16:
                il.Ldc_I4(2);
                context.AssertLength();
                context.LoadObj();          // stack: [&result[index], obj]
                il.Stind(typeof(short));    // result[index] = obj
                context.IncreaseIndexBy2(); // index = index + 2
                break;

            case GroBufTypeCode.Int32:
            case GroBufTypeCode.UInt32:
                il.Ldc_I4(4);
                context.AssertLength();
                context.LoadObj();          // stack: [&result[index], obj]
                il.Stind(typeof(int));      // result[index] = obj
                context.IncreaseIndexBy4(); // index = index + 4
                break;

            case GroBufTypeCode.Int64:
            case GroBufTypeCode.UInt64:
                il.Ldc_I4(8);
                context.AssertLength();
                context.LoadObj();          // stack: [&result[index], obj]
                il.Stind(typeof(long));     // result[index] = obj
                context.IncreaseIndexBy8(); // index = index + 8
                break;

            case GroBufTypeCode.Single:
                il.Ldc_I4(4);
                context.AssertLength();
                context.LoadObj();          // stack: [&result[index], obj]
                il.Stind(typeof(float));    // result[index] = obj
                context.IncreaseIndexBy4(); // index = index + 4
                break;

            case GroBufTypeCode.Double:
                il.Ldc_I4(8);
                context.AssertLength();
                context.LoadObj();          // stack: [&result[index], obj]
                il.Stind(typeof(double));   // result[index] = obj
                context.IncreaseIndexBy8(); // index = index + 8
                break;

            case GroBufTypeCode.Decimal:
                il.Ldc_I4(16);
                context.AssertLength();
                context.LoadObjByRef();        // stack: [&result[index], &obj]
                il.Ldind(typeof(long));        // stack: [&result[index], (int64)*obj]
                il.Stind(typeof(long));        // result[index] = (int64)*obj
                context.IncreaseIndexBy8();    // index = index + 8
                context.GoToCurrentLocation(); // stack: [&result[index]]
                context.LoadObjByRef();        // stack: [&result[index], &obj]
                il.Ldc_I4(8);                  // stack: [&result[index], &obj, 8]
                il.Add();                      // stack: [&result[index], &obj + 8]
                il.Ldind(typeof(long));        // stack: [&result[index], *(&obj+8)]
                il.Stind(typeof(long));        // result[index] = (int64)*(obj + 8)
                context.IncreaseIndexBy8();    // index = index + 8
                break;

            default:
                throw new NotSupportedException();
            }
        }
Beispiel #12
0
        protected override void WriteNotEmpty(WriterMethodBuilderContext context)
        {
            var il     = context.Il;
            var length = context.LocalInt;
            var start  = il.DeclareLocal(typeof(int));

            context.LoadIndexByRef(); // stack: [ref index]
            context.LoadIndex();      // stack: [ref index, index]
            il.Dup();                 // stack: [ref index, index, index]
            il.Stloc(start);          // start = index; stack: [ref index, index]
            il.Ldc_I4(5);             // stack: [ref index, index, 5]
            il.Add();                 // stack: [ref index, index + 5]
            il.Stind(typeof(int));    // index = index + 5; stack: []

            var dataMembers = context.Context.GetDataMembers(Type);
            var hashCodes   = GroBufHelpers.CalcHashesAndCheck(dataMembers);
            var prev        = il.DeclareLocal(typeof(int));

            for (var i = 0; i < dataMembers.Length; i++)
            {
                var member = dataMembers[i];

                if (Type.IsValueType)
                {
                    context.LoadObjByRef(); // stack: [ref obj]
                }
                else
                {
                    context.LoadObj(); // stack: [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: [obj.prop]
                    memberType = property.PropertyType;
                    break;

                case MemberTypes.Field:
                    var field = (FieldInfo)member.Member;
                    il.Ldfld(field); // stack: [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: [obj.prop, false]
                context.LoadResult();              // stack: [obj.prop, false, result]
                context.LoadIndexByRef();          // stack: [obj.prop, false, result, ref index]
                il.Dup();                          // stack: [obj.prop, false, result, ref index, ref index]
                context.LoadIndex();               // stack: [obj.prop, false, result, ref index, ref index, index]
                il.Dup();                          // stack: [obj.prop, false, result, ref index, ref index, index, index]
                il.Stloc(prev);                    // prev = index; stack: [obj.prop, false, result, ref index, ref index, index]
                il.Ldc_I4(8);                      // stack: [obj.prop, false, result, ref index, ref index, index, 8]
                il.Add();                          // stack: [obj.prop, false, result, ref index, ref index, index + 8]
                il.Stind(typeof(int));             // index = index + 8; stack: [obj.prop, false, result, ref index]
                context.LoadContext();             // stack: [obj.prop, false, result, ref index, context]
                context.CallWriter(memberType);    // writers[i](obj.prop, false, result, ref index, ref result, context)
                context.LoadIndex();               // stack: [index]
                il.Ldc_I4(8);                      // stack: [index, 8]
                il.Sub();                          // stack: [index - 8]
                il.Ldloc(prev);                    // stack: [index - 8, prev]
                var writeHashCodeLabel = il.DefineLabel("writeHashCode");
                il.Bgt(writeHashCodeLabel, false); // if(index - 8 > prev) goto writeHashCode;
                context.LoadIndexByRef();          // stack: [ref index]
                il.Ldloc(prev);                    // stack: [ref index, prev]
                il.Stind(typeof(int));             // index = prev;
                var nextLabel = il.DefineLabel("next");
                il.Br(nextLabel);                  // goto next;

                il.MarkLabel(writeHashCodeLabel);

                context.LoadResult();          // stack: [result]
                il.Ldloc(prev);                // stack: [result, prev]
                il.Add();                      // stack: [result + prev]
                il.Ldc_I8((long)hashCodes[i]); // stack: [&result[index], prop.Name.HashCode]
                il.Stind(typeof(long));        // *(long*)(result + prev) = prop.Name.HashCode; stack: []

                il.MarkLabel(nextLabel);
            }

            context.LoadIndex(); // stack: [index]
            il.Ldloc(start);     // stack: [index, start]
            il.Sub();            // stack: [index - start]
            il.Ldc_I4(5);        // stack: [index - start, 5]
            il.Sub();            // stack: [index - start - 5]

            il.Stloc(length);    // length = index - start - 5; stack: []

            if (!context.Context.GroBufWriter.Options.HasFlag(GroBufOptions.WriteEmptyObjects))
            {
                var writeLengthLabel = il.DefineLabel("writeLength");
                il.Ldloc(length);            // stack: [length]
                il.Brtrue(writeLengthLabel); // if(length != 0) goto writeLength;

                context.LoadIndexByRef();    // stack: [ref index]
                il.Ldloc(start);             // stack: [ref index, start]
                il.Stind(typeof(int));       // index = start
                context.WriteNull();

                il.MarkLabel(writeLengthLabel);
            }
            context.LoadResult();                  // stack: [result]
            il.Ldloc(start);                       // stack: [result, start]
            il.Add();                              // stack: [result + start]
            il.Dup();                              // stack: [result + start, result + start]
            il.Ldc_I4((int)GroBufTypeCode.Object); // stack: [result + start, result + start, TypeCode.Object]
            il.Stind(typeof(byte));                // *(result + start) = TypeCode.Object; stack: [result + start]
            il.Ldc_I4(1);                          // stack: [result + start, 1]
            il.Add();                              // stack: [result + start + 1]
            il.Ldloc(length);                      // stack: [result + start + 1, length]
            il.Stind(typeof(int));                 // *(int*)(result + start + 1) = length
        }