Ejemplo n.º 1
0
        protected override void WriteNotEmpty(WriterMethodBuilderContext 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 writeUsual = il.DefineLabel("writeUsual");

            il.Brfalse(writeUsual); // if(factory == null) goto writeUsual; stack: []
            il.Ldloc(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(writeUsual);                                                                          // if(!(rawData is RawData)) goto writeUsual; 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(writeUsual);                                                                           // if(rawData.serializerId != context.serializerId) goto writeUsual; stack: []

            var data   = il.DeclareLocal(typeof(byte).MakeByRefType(), true);
            var length = il.DeclareLocal(typeof(int));

            il.Ldloc(rawData);                                                                       // stack: [rawData]
            il.Ldfld(rawData.Type.GetField("data", BindingFlags.Instance | BindingFlags.NonPublic)); // stack: [rawData.data]

            il.Dup();                                                                                // stack: [rawData.data, rawData.data]
            il.Ldlen();                                                                              // stack: [rawData.data, rawData.data.Length]
            il.Stloc(length);                                                                        // length = rawData.data.Length; stack: [rawData.data]
            il.Ldc_I4(0);                                                                            // stack: [rawData.data, 0]
            il.Ldelema(typeof(byte));                                                                // stack: [&rawData.data[0]]
            il.Stloc(data);                                                                          // data = &rawData.data; stack: []
            il.Ldloc(length);
            context.AssertLength();

            context.GoToCurrentLocation(); // stack: [&result[index]]
            il.Ldloc(data);                // stack: [&result[index], data]
            il.Ldloc(length);              // stack: [&result[index], data, data.Length]
            il.Cpblk();                    // result[index] = data; stack: []
            context.LoadIndexByRef();      // stack: [ref index]
            context.LoadIndex();           // stack: [ref index, index]
            il.Ldloc(length);              // stack: [ref index, index, data.Length]
            il.Add();                      // stack: [ref index, index + data.Length]
            il.Stind(typeof(int));         // index = index + data.Length; stack: []
            il.FreePinnedLocal(data);      // data = null; stack: []
            il.Ret();

            il.MarkLabel(writeUsual);
            context.LoadObj();                                                                              // stack: [obj]
            il.Call(Type.GetProperty("Value", BindingFlags.Instance | BindingFlags.Public).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(argument);                                                                   // writer(obj.Value, writeEmpty, result, ref index, context)
        }