示例#1
0
        protected override unsafe void WriteNotEmpty(WriterMethodBuilderContext context)
        {
            var length = context.LocalInt;

            context.LoadObj(); // stack: [obj]
            var il = context.Il;

            il.Call(lengthPropertyGetter); // stack: [obj.Length]
            il.Ldc_I4(1);                  // stack: [obj.Length, 1]
            il.Shl();                      // stack: [obj.Length << 1]
            il.Stloc(length);              // length = obj.Length << 1
            context.WriteTypeCode(GroBufTypeCode.String);
            il.Ldc_I4(4);
            context.AssertLength();
            context.GoToCurrentLocation(); // stack: [&result[index]]
            il.Ldloc(length);              // stack: [&result[index], length]
            il.Stind(typeof(int));         // result[index] = length
            context.IncreaseIndexBy4();    // index = index + 4

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

            il.Ldloc(length); // stack: [length]
            il.Brfalse(doneLabel);

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

            context.GoToCurrentLocation(); // stack: [&result[index]]
            var str = il.DeclareLocal(typeof(string), true);

            context.LoadObj();                            // stack: [&result[index], obj]
            il.Stloc(str);                                // str = obj
            il.Ldloc(str);                                // stack: [&result[index], str]
            il.Conv <IntPtr>();                           // stack: [&result[index], (IntPtr)str]
            il.Ldc_I4(RuntimeHelpers.OffsetToStringData); // stack: [&result[index], (IntPtr)str, offset]
            il.Add();                                     // stack: [&result[index], (IntPtr)str + offset]
            il.Ldloc(length);                             // stack: [&result[index], (IntPtr)str + offset, length]
            il.Cpblk();                                   // &result[index] = str
            il.FreePinnedLocal(str);                      // str = null; stack: []

            context.LoadIndexByRef();                     // stack: [ref index]
            context.LoadIndex();                          // stack: [ref index, index]
            il.Ldloc(length);                             // stack: [ref index, index, length]
            il.Add();                                     // stack: [ref index, index + length]
            il.Stind(typeof(int));                        // index = index + length

            il.MarkLabel(doneLabel);
        }
示例#2
0
        protected override void WriteNotEmpty(WriterMethodBuilderContext 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 writeIntLabel = il.DefineLabel("writeInt");

            il.Brfalse(writeIntLabel);         // if(values[obj % values.Length] != obj) goto writeInt

            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]
            var hashCode = il.DeclareLocal(typeof(ulong));

            il.Dup();           // stack: [hashCode, hashCode]
            il.Stloc(hashCode); // hashCode = hashCodes[obj % hashCodes.Length]; stack: [hashCode]
            il.Brfalse(writeIntLabel);
            context.WriteTypeCode(GroBufTypeCode.Enum);
            il.Ldc_I4(8);
            context.AssertLength();
            context.GoToCurrentLocation(); // stack: [&result[index]]
            il.Ldloc(hashCode);            // stack: [&result[index], hashCode]
            il.Stind(typeof(long));        // *(int64*)&result[index] = hashCode
            context.IncreaseIndexBy8();    // index = index + 8;
            il.Ret();
            il.MarkLabel(writeIntLabel);
            context.WriteTypeCode(GroBufTypeCode.Int32);
            il.Ldc_I4(4);
            context.AssertLength();
            context.GoToCurrentLocation(); // stack: [&result[index]]
            context.LoadObj();             // stack: [&result[index], obj]
            il.Stind(typeof(int));         // result[index] = obj
            context.IncreaseIndexBy4();    // index = index + 4
        }
        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);
        }
        protected override unsafe void WriteNotEmpty(WriterMethodBuilderContext context)
        {
            var il = context.Il;

            context.WriteTypeCode(GroBufTypeCodeMap.GetTypeCode(elementType.MakeArrayType()));
            il.Ldc_I4(4);
            context.AssertLength();
            var size = il.DeclareLocal(typeof(int));

            context.GoToCurrentLocation();                                                    // stack: [&result[index]]
            context.LoadObj();                                                                // stack: [&result[index], obj]
            il.Ldfld(Type.GetField("_size", BindingFlags.Instance | BindingFlags.NonPublic)); // 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: []

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

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

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

            context.GoToCurrentLocation();                                                     // stack: [&result[index]]
            context.LoadObj();                                                                 // stack: [&result[index], obj]
            il.Ldfld(Type.GetField("_items", BindingFlags.Instance | BindingFlags.NonPublic)); // stack: [&result[index], obj._items]
            il.Ldc_I4(0);                                                                      // stack: [&result[index], obj._items, 0]
            il.Ldelema(elementType);                                                           // stack: [&result[index], &obj._items[0]]
            var arr = il.DeclareLocal(elementType.MakeByRefType(), true);

            il.Stloc(arr);            // arr = &obj._items[0]; stack: [&result[index]]
            il.Ldloc(arr);            // stack: [&result[index], arr]
            il.Ldloc(size);           // stack: [&result[index], arr, 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);
        }
        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
        }
        protected override void WriteNotEmpty(WriterMethodBuilderContext context)
        {
            var il = context.Il;

            context.WriteTypeCode(GroBufTypeCodeMap.GetTypeCode(elementType.MakeArrayType()));
            var size = il.DeclareLocal(typeof(int));

            il.Ldc_I4(4);
            context.AssertLength();
            context.LoadObj();                                                                              // stack: [obj]
            il.Call(Type.GetProperty("Count", BindingFlags.Instance | BindingFlags.Public).GetGetMethod()); // stack: [obj.Count]
            CountArraySize(elementType, il);                                                                // stack: [obj size]
            il.Stloc(size);                                                                                 // size = obj size; stack: []
            context.GoToCurrentLocation();                                                                  // stack: [&result[index]]
            il.Ldloc(size);                                                                                 // stack: [&result[index], size]
            il.Stind(typeof(int));                                                                          // result[index] = size; stack: []
            context.IncreaseIndexBy4();                                                                     // index = index + 4; stack: []

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

            context.LoadObj(); // stack: [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);

            context.LoadObj();                                                              // stack: [obj]
            il.Ldfld(Type.GetPrivateInstanceField(PlatformHelpers.HashSetCountFieldNames)); // stack: [obj.m_lastIndex]
            il.Dup();
            var count = context.LocalInt;

            il.Stloc(count); // count = obj.m_lastIndex; stack: [count]
            var writeDataLengthLabel = il.DefineLabel("writeDataLength");

            il.Brfalse(writeDataLengthLabel);

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

            il.Ldc_I4(0);                  // stack: [0]
            il.Stloc(i);                   // i = 0; stack: []
            context.GoToCurrentLocation(); // stack: [&result[index]]
            var cycleStartLabel = il.DefineLabel("cycleStart");

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

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

            il.Blt(nextLabel, false);                                                                                                                     // if(slot.hashCode < 0) goto next; stack: [current]
            il.Dup();                                                                                                                                     // stack: [current, current]
            il.Ldloc(slot);                                                                                                                               // stack: [current, current, slot]
            il.Ldfld(slotType.GetField(PlatformHelpers.HashSetSlotValueFieldName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)); // stack: [current, current, slot.value]
            il.Stind(elementType);                                                                                                                        // *current = slot.value; stack: [current]
            LoadItemSize(elementType, il);                                                                                                                // stack: [current, item size]
            il.Add();                                                                                                                                     // stack: [current + item size]
            il.MarkLabel(nextLabel);
            il.Ldloc(count);                                                                                                                              // stack: [current, count]
            il.Ldloc(i);                                                                                                                                  // stack: [current, count, i]
            il.Ldc_I4(1);                                                                                                                                 // stack: [current, count, i, 1]
            il.Add();                                                                                                                                     // stack: [current, count, i + 1]
            il.Dup();                                                                                                                                     // stack: [current, count, i + 1, i + 1]
            il.Stloc(i);                                                                                                                                  // i = i + 1; stack: [current, count, i]
            il.Bgt(cycleStartLabel, false);                                                                                                               // if(count > i) goto cycleStart; stack: [current]
            il.Pop();                                                                                                                                     // stack: []

            il.MarkLabel(writeDataLengthLabel);
            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
        }
示例#7
0
        protected override void WriteNotEmpty(WriterMethodBuilderContext context)
        {
            var il = context.Il;

            context.WriteTypeCode(GroBufTypeCode.Dictionary);
            context.LoadIndex(); // stack: [index]
            var start = context.LocalInt;

            il.Stloc(start);                                                                                // start = index
            il.Ldc_I4(8);                                                                                   // data length + dict size = 8
            context.AssertLength();
            context.IncreaseIndexBy4();                                                                     // index = index + 4
            context.GoToCurrentLocation();                                                                  // stack: [&result[index]]
            context.LoadObj();                                                                              // stack: [&result[index], obj]
            il.Call(Type.GetProperty("Count", BindingFlags.Instance | BindingFlags.Public).GetGetMethod()); // stack: [&result[index], obj.Count]
            il.Stind(typeof(int));                                                                          // *(int*)&result[index] = obj.Count; stack: []
            context.IncreaseIndexBy4();                                                                     // index = index + 4; stack: []

            context.LoadObj();                                                                              // stack: [obj]
            // traverse all buckets
            il.Ldfld(Type.GetPrivateInstanceField(PlatformHelpers.DictionaryCountFieldNames));              // stack: [obj.count]
            var count = il.DeclareLocal(typeof(int));

            il.Stloc(count); // count = obj.count; stack: []

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

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

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

            il.Ldfld(Type.GetPrivateInstanceField(PlatformHelpers.DictionaryEntriesFieldNames)); // stack: [obj.entries]
            il.Stloc(entries);                                                                   // entries = obj.entries; stack: []

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

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

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

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

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

            il.Ldloc(entry);                       // stack: [entry]
            il.Ldfld(entryType.GetField("key"));   // stack: [entry.key]
            il.Ldc_I4(1);                          // stack: [obj[i].key, true]
            context.LoadResult();                  // stack: [obj[i].key, true, result]
            context.LoadIndexByRef();              // stack: [obj[i].key, true, result, ref index]
            context.LoadContext();                 // stack: [obj[i].key, true, result, ref index, context]
            context.CallWriter(keyType);           // write<keyType>(obj[i].key, true, result, ref index, context); stack: []

            il.Ldloc(entry);                       // stack: [entry]
            il.Ldfld(entryType.GetField("value")); // stack: [entry.value]
            il.Ldc_I4(1);                          // stack: [obj[i].value, true]
            context.LoadResult();                  // stack: [obj[i].value, true, result]
            context.LoadIndexByRef();              // stack: [obj[i].value, true, result, ref index]
            context.LoadContext();                 // stack: [obj[i].value, true, result, ref index, context]
            context.CallWriter(valueType);         // writer<valueType>(obj[i].value, true, result, ref index, context); stack: []

            il.MarkLabel(nextLabel);
            il.Ldloc(count);                // stack: [ count]
            il.Ldloc(i);                    // stack: [count, i]
            il.Ldc_I4(1);                   // stack: [count, i, 1]
            il.Add();                       // stack: [count, i + 1]
            il.Dup();                       // stack: [count, i + 1, i + 1]
            il.Stloc(i);                    // i = i + 1; stack: [count, i]
            il.Bgt(cycleStartLabel, false); // if(count > 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
        }
示例#8
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();
            }
        }
示例#9
0
        protected override void WriteNotEmpty(WriterMethodBuilderContext context)
        {
            var il = context.Il;

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

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

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

            context.LoadObj();                                                                 // stack: [obj]
            il.Ldfld(Type.GetField("_items", BindingFlags.Instance | BindingFlags.NonPublic)); // stack: [obj._items]
            il.Stloc(items);                                                                   // items = obj._items; stack: []
            context.LoadIndex();                                                               // stack: [index]
            var start = context.LocalInt;

            il.Stloc(start); // start = index

            il.Ldc_I4(8);
            context.AssertLength();        // data length + list size = 8

            context.IncreaseIndexBy4();    // index = index + 4
            context.GoToCurrentLocation(); // stack: [&result[index]]
            il.Ldloc(count);               // stack: [&result[index], count]
            il.Stind(typeof(int));         // *(int*)&result[index] = count; stack: []
            context.IncreaseIndexBy4();    // index = index + 4

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

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

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

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

            il.MarkLabel(cycleStart);

            il.Ldloc(items);                 // stack: [items]
            il.Ldloc(i);                     // stack: [items, i]
            il.Ldelem(elementType);
            il.Ldc_I4(1);                    // stack: [obj[i], true]
            context.LoadResult();            // stack: [obj[i], true, result]
            context.LoadIndexByRef();        // stack: [obj[i], true, result, ref index]
            context.LoadContext();           // stack: [obj[i], true, result, ref index, context]
            context.CallWriter(elementType); // write<elementType>(obj[i], true, result, ref index, context); stack: []
            il.Ldloc(count);                 // stack: [count]
            il.Ldloc(i);                     // stack: [count, i]
            il.Ldc_I4(1);                    // stack: [count, i, 1]
            il.Add();                        // stack: [count, i + 1]
            il.Dup();                        // stack: [count, i + 1, i + 1]
            il.Stloc(i);                     // i = i + 1; stack: [count, i]
            il.Bgt(cycleStart, false);       // if(count > 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
        }
示例#10
0
        protected override void WriteNotEmpty(WriterMethodBuilderContext context)
        {
            var il = context.Il;

            context.WriteTypeCode(GroBufTypeCode.Array);
            context.LoadIndex(); // stack: [index]
            var start = context.LocalInt;

            il.Stloc(start);                                                                                // start = index
            il.Ldc_I4(8);
            context.AssertLength();                                                                         // data length + hashset size = 8
            context.IncreaseIndexBy4();                                                                     // index = index + 4
            context.GoToCurrentLocation();                                                                  // stack: [&result[index]]
            context.LoadObj();                                                                              // stack: [&result[index], obj]
            il.Call(Type.GetProperty("Count", BindingFlags.Instance | BindingFlags.Public).GetGetMethod()); // stack: [&result[index], obj.Count]
            il.Stind(typeof(int));                                                                          // *(int*)&result[index] = obj.Count; stack: []
            context.IncreaseIndexBy4();                                                                     // index = index + 4; stack: []

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

            il.Ldfld(Type.GetPrivateInstanceField(PlatformHelpers.HashSetLastIndexFieldNames)); // stack: [obj.m_lastIndex]
            il.Dup();
            il.Stloc(count);                                                                    // count = obj.m_lastIndex; stack: []
            var writeDataLengthLabel = il.DefineLabel("writeDataLength");

            il.Brfalse(writeDataLengthLabel);

            context.LoadObj(); // stack: [obj]
            var slotType = Type.GetNestedType("Slot", 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: [0]
            il.Stloc(i);  // i = 0; stack: []
            var cycleStartLabel = il.DefineLabel("cycleStart");

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

            il.Stloc(slot);                                                                          // slot = &slots[i]; stack: [slot]
            il.Ldfld(slotType.GetField("hashCode", BindingFlags.Instance | BindingFlags.NonPublic)); // stack: [slot.hashCode]

            il.Ldc_I4(0);                                                                            // stack: [slot.hashCode, 0]
            var nextLabel = il.DefineLabel("next");

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

            il.Ldloc(slot);                                                                       // stack: [slot]
            il.Ldfld(slotType.GetField("value", BindingFlags.Instance | BindingFlags.NonPublic)); // stack: [slot.value]
            il.Ldc_I4(1);                                                                         // stack: [obj[i], true]
            context.LoadResult();                                                                 // stack: [obj[i], true, result]
            context.LoadIndexByRef();                                                             // stack: [obj[i], true, result, ref index]
            context.LoadContext();                                                                // stack: [obj[i], true, result, ref index, context]
            context.CallWriter(elementType);                                                      // write<elementType>(obj[i], true, result, ref index, context)

            il.MarkLabel(nextLabel);
            il.Ldloc(count);                // stack: [count]
            il.Ldloc(i);                    // stack: [count, i]
            il.Ldc_I4(1);                   // stack: [count, i, 1]
            il.Add();                       // stack: [count, i + 1]
            il.Dup();                       // stack: [count, i + 1, i + 1]
            il.Stloc(i);                    // i = i + 1; stack: [count, i]
            il.Bgt(cycleStartLabel, false); // if(count > 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
        }
示例#11
0
        protected override void WriteNotEmpty(WriterMethodBuilderContext context)
        {
            var il = context.Il;

            context.WriteTypeCode(GroBufTypeCode.Dictionary);
            context.LoadIndex(); // stack: [index]
            var start = context.LocalInt;

            il.Stloc(start);                                                                  // start = index
            il.Ldc_I4(8);                                                                     // data length + dict size = 8
            context.AssertLength();
            context.IncreaseIndexBy4();                                                       // index = index + 4
            context.GoToCurrentLocation();                                                    // stack: [&result[index]]
            context.LoadObj();                                                                // stack: [&result[index], obj]
            il.Ldfld(Type.GetPrivateInstanceField(PlatformHelpers.HashtableCountFieldNames)); // stack: [&result[index], obj.Count]
            il.Dup();
            var count = il.DeclareLocal(typeof(int));

            il.Stloc(count);            // count = obj.Count; stack: [&result[index], obj.Count]
            il.Stind(typeof(int));      // *(int*)&result[index] = count; stack: []
            context.IncreaseIndexBy4(); // index = index + 4; stack: []

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

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

            context.LoadObj();                // stack: [obj]
            var bucketType   = Type.GetNestedType("bucket", BindingFlags.NonPublic);
            var buckets      = il.DeclareLocal(bucketType.MakeArrayType());
            var bucketsField = Type.GetPrivateInstanceField(PlatformHelpers.HashtableBucketsFieldNames);

            il.Ldfld(bucketsField); // stack: [obj.buckets]
            il.Stloc(buckets);      // buckets = obj.buckets; stack: []
            il.Ldloc(buckets);      // stack: [buckets]
            il.Ldlen();             // stack: [buckets.Length]
            il.Stloc(count);        // count = buckets.Length; stack: []

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

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

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

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

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

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

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

            il.Ldloc(key);                        // stack: [obj[i].key]
            il.Ldc_I4(1);                         // stack: [obj[i].key, true]
            context.LoadResult();                 // stack: [obj[i].key, true, result]
            context.LoadIndexByRef();             // stack: [obj[i].key, true, result, ref index]
            context.LoadContext();                // stack: [obj[i].key, true, result, ref index, context]
            context.CallWriter(typeof(object));   // write<object>(obj[i].key, true, result, ref index, context); stack: []

            il.Ldloc(bucket);                     // stack: [bucket]
            il.Ldfld(bucketType.GetField("val")); // stack: [bucket.val]
            il.Ldc_I4(1);                         // stack: [obj[i].value, true]
            context.LoadResult();                 // stack: [obj[i].value, true, result]
            context.LoadIndexByRef();             // stack: [obj[i].value, true, result, ref index]
            context.LoadContext();                // stack: [obj[i].value, true, result, ref index, context]
            context.CallWriter(typeof(object));   // writer<object>(obj[i].value, true, result, ref index, context); stack: []

            il.MarkLabel(nextLabel);
            il.Ldloc(count);                // stack: [ count]
            il.Ldloc(i);                    // stack: [count, i]
            il.Ldc_I4(1);                   // stack: [count, i, 1]
            il.Add();                       // stack: [count, i + 1]
            il.Dup();                       // stack: [count, i + 1, i + 1]
            il.Stloc(i);                    // i = i + 1; stack: [count, i]
            il.Bgt(cycleStartLabel, false); // if(count > 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
        }
示例#12
0
        public void BuildWriter(WriterTypeBuilderContext writerTypeBuilderContext)
        {
            var method = new DynamicMethod("Write_" + Type.Name + "_" + Guid.NewGuid(), typeof(void),
                                           new[]
            {
                Type, typeof(bool), typeof(IntPtr), typeof(int).MakeByRefType(), typeof(WriterContext)
            }, writerTypeBuilderContext.Module, true);

            writerTypeBuilderContext.SetWriterMethod(Type, method);
            using (var il = new GroboIL(method))
            {
                var context = new WriterMethodBuilderContext(writerTypeBuilderContext, il);

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

                if (!Type.IsValueType && IsReference && writerTypeBuilderContext.GroBufWriter.Options.HasFlag(GroBufOptions.PackReferences))
                {
                    // Pack reference
                    var index = il.DeclareLocal(typeof(int));
                    context.LoadIndex();                                                                                             // stack: [external index]
                    context.LoadContext();                                                                                           // stack: [external index, context]
                    il.Ldfld(WriterContext.StartField);                                                                              // stack: [external index, context.start]
                    il.Sub();                                                                                                        // stack: [external index - context.start]
                    il.Stloc(index);                                                                                                 // index = external index - context.start; stack: []
                    context.LoadContext();                                                                                           // stack: [context]
                    il.Ldfld(typeof(WriterContext).GetField("objects", BindingFlags.Public | BindingFlags.Instance));                // stack: [context.objects]
                    context.LoadObj();                                                                                               // stack: [context.objects, obj]
                    var reference = il.DeclareLocal(typeof(int));
                    il.Ldloca(reference);                                                                                            // stack: [context.objects, obj, ref reference]
                    int dummy;
                    il.Call(HackHelpers.GetMethodDefinition <Dictionary <object, int> >(dict => dict.TryGetValue(null, out dummy))); // stack: [context.object.TryGetValue(obj, out reference)]
                    var storeLocationLabel = il.DefineLabel("storeLocation");
                    il.Brfalse(storeLocationLabel);
                    // Current object is in dict
                    il.Ldloc(index);
                    il.Ldloc(reference);                             // stack: [index, reference]
                    var skipSelfLabel = il.DefineLabel("skipSelf");
                    il.Beq(skipSelfLabel);                           // if(index == reference) goto skipSelf; stack: []
                    il.Ldloc(index);                                 // stack: [index]
                    il.Ldloc(reference);                             // stack: [index, reference]
                    var badReferenceLabel = il.DefineLabel("badReference");
                    il.Blt(badReferenceLabel, false);                // if(index < reference) goto badReference; stack: []
                    context.WriteTypeCode(GroBufTypeCode.Reference); // result[index++] = GroBufTypeCode.Reference
                    context.GoToCurrentLocation();                   // stack: [&result[index]]
                    il.Ldloc(reference);                             // stack: [&result[index], reference]
                    il.Stind(typeof(int));                           // *(int *)&result[index] = reference
                    context.IncreaseIndexBy4();                      // index += 4
                    il.Ret();
                    il.MarkLabel(badReferenceLabel);
                    il.Ldstr("Bad reference");
                    il.Newobj(typeof(DataCorruptedException).GetConstructor(new[] { typeof(string) }));
                    il.Throw();
                    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);
                    il.MarkLabel(skipSelfLabel);
                }

                WriteNotEmpty(context); // Write obj
                il.Ret();
            }
            var @delegate = method.CreateDelegate(typeof(WriterDelegate <>).MakeGenericType(Type));
            var pointer   = GroBufHelpers.ExtractDynamicMethodPointer(method);

            writerTypeBuilderContext.SetWriterPointer(Type, pointer, @delegate);
        }