PushPrimitiveWriterOntoStack() public method

public PushPrimitiveWriterOntoStack ( ) : void
return void
Beispiel #1
0
        private static void GenerateWriteValue(WriterGenerationContext context, Variable valueLocal, Type formalType)
        {
            ObjectWriter.CheckLegality(formalType);
            if (formalType.IsEnum)
            {
                formalType = Enum.GetUnderlyingType(formalType);
            }
            var writeMethod = typeof(PrimitiveWriter).GetMethod("Write", new[] { formalType });

            // if this method is null, then it is a non-primitive (i.e. custom) struct
            if (writeMethod != null)
            {
                context.PushPrimitiveWriterOntoStack();
                context.Generator.PushVariableOntoStack(valueLocal);
                context.Generator.Emit(OpCodes.Call, writeMethod);
                return;
            }
            var nullableUnderlyingType = Nullable.GetUnderlyingType(formalType);

            if (nullableUnderlyingType != null)
            {
                var hasValueLabel = context.Generator.DefineLabel();
                var finishLabel   = context.Generator.DefineLabel();

                var underlyingValueLocal = context.Generator.DeclareLocal(nullableUnderlyingType);
                var underlyingVariable   = new Variable(underlyingValueLocal);

                context.PushPrimitiveWriterOntoStack();
                context.Generator.PushVariableAddressOntoStack(valueLocal);
                context.Generator.Emit(OpCodes.Call, formalType.GetProperty("HasValue").GetGetMethod());
                context.Generator.Emit(OpCodes.Brtrue_S, hasValueLabel);
                context.Generator.PushIntegerOntoStack(0);
                context.Generator.Call <PrimitiveWriter>(x => x.Write(false));
                context.Generator.Emit(OpCodes.Br_S, finishLabel);

                context.Generator.MarkLabel(hasValueLabel);
                context.Generator.PushIntegerOntoStack(1);
                context.Generator.Call <PrimitiveWriter>(x => x.Write(false));

                context.Generator.PushVariableAddressOntoStack(valueLocal);
                context.Generator.Emit(OpCodes.Call, formalType.GetProperty("Value").GetGetMethod());
                context.Generator.StoreLocalValueFromStack(underlyingValueLocal);

                GenerateWriteValue(context, underlyingVariable, nullableUnderlyingType);

                context.Generator.MarkLabel(finishLabel);
                return;
            }

            GenerateWriteFields(context, valueLocal, formalType);
        }
Beispiel #2
0
        internal static bool GenerateTryWriteObjectInline(WriterGenerationContext context, bool generatePreSerializationCallback, bool generatePostSerializationCallback, Variable valueLocal, Type actualType)
        {
            if (actualType.IsArray)
            {
                var rank = actualType.GetArrayRank();

                // write rank
                context.PushPrimitiveWriterOntoStack();
                context.Generator.PushIntegerOntoStack(rank);
                context.Generator.Call <PrimitiveWriter>(x => x.Write(0));

                if (rank == 1)
                {
                    // write length
                    context.PushPrimitiveWriterOntoStack();
                    context.Generator.PushVariableOntoStack(valueLocal);
                    context.Generator.Emit(OpCodes.Castclass, actualType);
                    context.Generator.Emit(OpCodes.Ldlen);
                    context.Generator.Call <PrimitiveWriter>(x => x.Write(0));
                }
                else
                {
                    // write lengths in loop
                    for (var i = 0; i < rank; i++)
                    {
                        context.PushPrimitiveWriterOntoStack();
                        context.Generator.PushVariableOntoStack(valueLocal);
                        context.Generator.PushIntegerOntoStack(i);
                        context.Generator.Call <Array>(x => x.GetLength(0));
                        context.Generator.Call <PrimitiveWriter>(x => x.Write(0));
                    }
                }
                return(false);
            }
            if (actualType == typeof(string))
            {
                GenerateInvokeCallbacksAndExecute(context, generatePreSerializationCallback, generatePostSerializationCallback, valueLocal, actualType, c =>
                {
                    c.PushPrimitiveWriterOntoStack();
                    c.Generator.PushVariableOntoStack(valueLocal);
                    c.Generator.Call <PrimitiveWriter>(x => x.Write((string)null));
                });

                return(true);
            }

            return(GenerateSpecialWrite(context, actualType, valueLocal, false));
        }
Beispiel #3
0
        protected override bool InnerGenerate(WriterGenerationContext context)
        {
            Variable value;

            if (type.IsValueType)
            {
                var valueLocal = context.Generator.DeclareLocal(type);
                context.Generator.Emit(OpCodes.Ldarg_1);
                context.Generator.Emit(OpCodes.Unbox_Any, type);
                context.Generator.StoreLocalValueFromStack(valueLocal);

                value = new Variable(valueLocal);
            }
            else
            {
                value = new Variable(1);
            }

            var objectForSurrogatesIndex = objectsForSurrogates == null ? -1 : objectsForSurrogates.FindMatchingIndex(type);

            context.PushPrimitiveWriterOntoStack();
            context.Generator.PushIntegerOntoStack(objectForSurrogatesIndex != -1 ? 1 : 0);
            context.Generator.Call <PrimitiveWriter>(x => x.Write(false));

            if (objectForSurrogatesIndex != -1)
            {
                context.PushObjectWriterOntoStack();
                context.Generator.Emit(OpCodes.Dup);
                context.Generator.PushFieldValueOntoStack <ObjectWriter, SwapList>(x => x.objectsForSurrogates);
                context.Generator.PushIntegerOntoStack(objectForSurrogatesIndex);
                context.Generator.Call <SwapList>(x => x.GetByIndex(0));

                var delegateType = typeof(Func <,>).MakeGenericType(type, typeof(object));
                context.Generator.Emit(OpCodes.Castclass, delegateType);
                context.Generator.Emit(OpCodes.Ldarg_1);
                context.Generator.Emit(OpCodes.Call, delegateType.GetMethod("Invoke"));

                // here should be a primitive writer on a stack
                context.Generator.Call <object>(x => x.GetType());
                context.Generator.Call <ObjectWriter>(x => x.TouchAndWriteTypeId(typeof(void)));
                context.Generator.Emit(OpCodes.Pop);
            }

            if (WriteMethodGenerator.GenerateTryWriteObjectInline(context, generatePreSerializationCallback, generatePostSerializationCallback, value, type))
            {
                context.PushObjectWriterOntoStack();
                context.Generator.PushFieldValueOntoStack <ObjectWriter, HashSet <int> >(x => x.objectsWrittenInline);
                context.Generator.Emit(OpCodes.Ldarg_2); // reference identifier
                context.Generator.Call <HashSet <int> >(x => x.Add(0));
                context.Generator.Emit(OpCodes.Pop);
            }

            return(true);
        }
Beispiel #4
0
        private static void GenerateWriteDelegate(WriterGenerationContext context, Variable valueLocal)
        {
            var array                  = context.Generator.DeclareLocal(typeof(Delegate[]));
            var loopLength             = context.Generator.DeclareLocal(typeof(int));
            var element                = context.Generator.DeclareLocal(typeof(Delegate));
            var delegateTargetLocal    = context.Generator.DeclareLocal(typeof(object));
            var delegateTargetVariable = new Variable(delegateTargetLocal);

            context.PushPrimitiveWriterOntoStack();

            context.PushObjectWriterOntoStack();
            context.Generator.PushVariableOntoStack(valueLocal);
            context.Generator.Call <ObjectWriter>(x => x.GetDelegatesWithNonTransientTargets(null));
            context.Generator.Emit(OpCodes.Castclass, typeof(Delegate[]));
            context.Generator.Emit(OpCodes.Dup);
            context.Generator.StoreLocalValueFromStack(array);

            // array refrence should be on the top of stack here
            context.Generator.Emit(OpCodes.Ldlen);
            context.Generator.Emit(OpCodes.Dup);
            context.Generator.StoreLocalValueFromStack(loopLength);

            // primitive writer should be on the stack
            // array length should be on the stack
            context.Generator.Call <PrimitiveWriter>(x => x.Write(0));

            GeneratorHelper.GenerateLoop(context, loopLength, c =>
            {
                context.Generator.PushLocalValueOntoStack(array);
                context.Generator.PushLocalValueOntoStack(c);
                context.Generator.Emit(OpCodes.Ldelem, element.LocalType);
                context.Generator.Emit(OpCodes.Dup);
                context.Generator.StoreLocalValueFromStack(element);

                // element reference should be on the stack
                context.Generator.PushPropertyValueOntoStack <MulticastDelegate, object>(x => x.Target);
                context.Generator.StoreLocalValueFromStack(delegateTargetLocal);

                GenerateWriteDeferredReference(context, delegateTargetVariable, typeof(object));

                context.PushObjectWriterOntoStack();
                context.Generator.PushPropertyValueOntoStack <ObjectWriter, IdentifiedElementsDictionary <MethodDescriptor> >(x => x.Methods);
                context.Generator.PushLocalValueOntoStack(element);
                context.Generator.PushPropertyValueOntoStack <MulticastDelegate, MethodInfo>(x => x.Method);
                context.Generator.Emit(OpCodes.Newobj, Helpers.GetConstructorInfo <MethodDescriptor>(typeof(MethodInfo)));
                context.Generator.Call <IdentifiedElementsDictionary <MethodDescriptor> >(x => x.TouchAndWriteId(null));
                context.Generator.Emit(OpCodes.Pop);
            });
        }
Beispiel #5
0
        private static void GenerateWriteEnumerable(WriterGenerationContext context, Variable valueLocal, CollectionMetaToken token)
        {
            var genericTypes   = new[] { token.FormalElementType };
            var enumerableType = token.IsGeneric ? typeof(IEnumerable <>).MakeGenericType(genericTypes) : typeof(IEnumerable);
            var enumeratorType = token.IsGeneric ? typeof(IEnumerator <>).MakeGenericType(genericTypes) : typeof(IEnumerator);

            var iteratorLocal       = context.Generator.DeclareLocal(enumeratorType);
            var currentElementLocal = context.Generator.DeclareLocal(token.FormalElementType);
            var elementVariable     = new Variable(currentElementLocal);

            var loopBegin = context.Generator.DefineLabel();
            var finish    = context.Generator.DefineLabel();

            context.PushPrimitiveWriterOntoStack();
            context.Generator.PushVariableOntoStack(valueLocal);
            context.Generator.Emit(token.CountMethod.IsStatic ? OpCodes.Call : OpCodes.Callvirt, token.CountMethod);
            context.Generator.Call <PrimitiveWriter>(x => x.Write(0));

            var getEnumeratorMethod = enumerableType.GetMethod("GetEnumerator");

            context.Generator.PushVariableOntoStack(valueLocal);
            context.Generator.Emit(OpCodes.Callvirt, getEnumeratorMethod);
            context.Generator.StoreLocalValueFromStack(iteratorLocal);

            context.Generator.MarkLabel(loopBegin);
            context.Generator.PushLocalValueOntoStack(iteratorLocal);
            context.Generator.Callvirt <IEnumerator>(x => x.MoveNext());
            context.Generator.Emit(OpCodes.Brfalse, finish);

            context.Generator.PushLocalValueOntoStack(iteratorLocal);
            context.Generator.Emit(OpCodes.Callvirt, enumeratorType.GetProperty("Current").GetGetMethod());
            context.Generator.StoreLocalValueFromStack(currentElementLocal);

            GenerateWriteField(context, elementVariable, token.FormalElementType);
            context.Generator.Emit(OpCodes.Br, loopBegin);

            context.Generator.MarkLabel(finish);
        }