Пример #1
0
        public void EmitEncode(ILGenerator il, ILocalVariableCollection locals, Action <ILGenerator> emitLoad)
        {
            var valueIsNotNullLabel = il.DefineLabel();
            var endOfMethodLabel    = il.DefineLabel();

            var elemVar = il.DeclareLocal(elementType);                 // TElement elem

            emitLoad(il);                                               // if (value)
            il.Emit(OpCodes.Brtrue, valueIsNotNullLabel);               //     goto valueIsNotNullLabel

            // value is null branch
            il.Emit(OpCodes.Ldloc, locals.DataPointer);                 // *(int*) data = -1
            il.Emit_Ldc_I4(-1);
            il.Emit(OpCodes.Stind_I4);
            il.Emit_IncreasePointer(locals.DataPointer, sizeof(int));   // data += sizeof(int)
            il.Emit(OpCodes.Br, endOfMethodLabel);                      // goto endOfMethodLabel

            // value is not null branch
            il.MarkLabel(valueIsNotNullLabel);                          // label valueIsNotNullLabel
            il.Emit(OpCodes.Ldloc, locals.DataPointer);                 // *(int*) data = (int)value.Count
            EmitLoadCount(il, emitLoad);
            il.Emit(OpCodes.Stind_I4);
            il.Emit_IncreasePointer(locals.DataPointer, sizeof(int));   // data += sizeof(int)
            EmitEnumerateCollection(il, emitLoad, emitLoadCurrent =>    // foreach (current in value)
            {
                emitLoadCurrent();                                      //     elem = current
                il.Emit(OpCodes.Stloc, elemVar);
                elementCodec.EmitEncode(il, locals, elemVar);           //     encode(data, elem)
            });
            il.MarkLabel(endOfMethodLabel);                             // label endOfMethodLabel
        }
Пример #2
0
        public void EmitEncode(IEmittingContext context, Action <MyILGenerator> emitLoad)
        {
            var il = context.IL;
            var valueIsNotNullLabel = il.DefineLabel();
            var endOfMethodLabel    = il.DefineLabel();

            var elemVar = il.DeclareLocal(elementType);                     // TElement elem

            emitLoad(il);                                                   // if (value)
            il.Brtrue(valueIsNotNullLabel);                                 //     goto valueIsNotNullLabel

            // value is null branch
            il.Ldloc(context.DataPointerVar);                               // *(int*) data = -1
            il.Ldc_I4(-1);
            il.Stind_I4();
            il.IncreasePointer(context.DataPointerVar, sizeof(int));        // data += sizeof(int)
            il.Br(endOfMethodLabel);                                        // goto endOfMethodLabel

            // value is not null branch
            il.MarkLabel(valueIsNotNullLabel);                              // label valueIsNotNullLabel
            il.Ldloc(context.DataPointerVar);                               // *(int*) data = (int)value.Count
            EmitLoadCount(il, emitLoad);
            il.Stind_I4();
            il.IncreasePointer(context.DataPointerVar, sizeof(int));        // data += sizeof(int)
            using (var loop = il.EmitForeachLoop(elementType, emitLoad))    // foreach (current in value)
            {
                loop.LoadCurrent();                                         //     elem = current
                il.Stloc(elemVar);
                elementCodec.EmitEncode(context, elemVar);                  //     encode(data, elem)
            }
            il.MarkLabel(endOfMethodLabel);                                 // label endOfMethodLabel
        }
Пример #3
0
 public static void EmitEncode(this IEmittingCodec codec, ILGenerator il, ILocalVariableCollection locals, Action <ILGenerator> emitLoadParent, MethodInfo propertyGetter)
 {
     codec.EmitEncode(il, locals, lil =>
     {
         emitLoadParent(lil);
         lil.Emit(OpCodes.Call, propertyGetter);
     });
 }
Пример #4
0
        private DynamicMethod EmitEncode()
        {
            var dynamicMethod = new DynamicMethod("_encode_manual_" + type.FullName,
                                                  typeof(void), new[] { typeof(byte *).MakeByRefType(), type }, Assembly.GetExecutingAssembly().ManifestModule, true);
            var il     = dynamicMethod.GetILGenerator();
            var locals = new LocalVariableCollection(il, false);

            il.Emit(OpCodes.Ldarg_0);
            il.Emit(OpCodes.Ldind_I);
            il.Emit(OpCodes.Stloc, locals.DataPointer);
            emittingCodec.EmitEncode(il, locals, 1);
            il.Emit(OpCodes.Ldarg_0);
            il.Emit(OpCodes.Ldloc, locals.DataPointer);
            il.Emit(OpCodes.Stind_I);
            il.Emit(OpCodes.Ret);
            return(dynamicMethod);
        }
Пример #5
0
        private DynamicMethod EmitEncode()
        {
            const int codecContainerArgIndex = 0;
            const int dataArgIndex           = 1;
            const int valueArgIndex          = 2;

            var dynamicMethod = new DynamicMethod("_encode_manual_" + type.FullName,
                                                  typeof(void), new[] { typeof(ICodecContainer), typeof(byte *).MakeByRefType(), type }, Assembly.GetExecutingAssembly().ManifestModule, true);
            var il      = new MyILGenerator(dynamicMethod.GetILGenerator());
            var context = new ManualCodecEmittingContext(il, codecContainerArgIndex);

            il.Ldarg(dataArgIndex);
            il.Ldind_I();
            il.Stloc(context.DataPointerVar);
            emittingCodec.EmitEncode(context, valueArgIndex);
            il.Ldarg(dataArgIndex);
            il.Ldloc(context.DataPointerVar);
            il.Stind_I();
            il.Ret();
            return(dynamicMethod);
        }
 public void EmitEncode(IEmittingContext emittingContext)
 {
     codec.EmitEncode(emittingContext, emitLoad);
 }
Пример #7
0
 public static void EmitEncode(this IEmittingCodec codec, IEmittingContext context, Action <MyILGenerator> emitLoadParent, MethodInfo propertyGetter)
 {
     codec.EmitEncode(context, il => { emitLoadParent(il); il.Call(propertyGetter); });
 }
Пример #8
0
 public static void EmitEncode(this IEmittingCodec codec, IEmittingContext context, LocalBuilder localVar)
 {
     codec.EmitEncode(context, il => il.Ldloc(localVar));
 }
Пример #9
0
 public static void EmitEncodeIndirect(this IEmittingCodec codec, IEmittingContext context, int argIndex, Type type)
 {
     codec.EmitEncode(context, il => { il.Ldarg(argIndex); il.Ldobj(type); });
 }
Пример #10
0
 public static void EmitEncode(this IEmittingCodec codec, IEmittingContext context, int argIndex)
 {
     codec.EmitEncode(context, il => il.Ldarg(argIndex));
 }
Пример #11
0
        public ServiceMethodHandler CreateMethodHandler(ServiceImplementationInfo serviceImplementationInfo, ServicePath servicePath)
        {
            var serviceInterface = serviceImplementationInfo.Description.Type;

            var dynamicMethod = new DynamicMethod(
                "__srpc__handle__" + serviceInterface.FullName + "__" + string.Join("_", servicePath),
                typeof(byte[]), ParameterTypes, Assembly.GetExecutingAssembly().ManifestModule, true);
            var il     = dynamicMethod.GetILGenerator();
            var locals = new LocalVariableCollection(il, true);

            il.Emit(OpCodes.Ldarg_0);                                           // stack_0 = (TServiceImplementation) arg_0
            il.Emit(OpCodes.Castclass, serviceInterface);

            var serviceDesc = serviceImplementationInfo.Description;

            for (int i = 1; i < servicePath.Length - 1; i++)
            {
                var propertyInfo = serviceDesc.Type.GetProperty(servicePath[i]);
                il.Emit(OpCodes.Callvirt, propertyInfo.GetGetMethod());         // stack_0 = stack_0.Property
                SubserviceDescription subserviceDescription;
                if (!serviceDesc.TryGetSubservice(servicePath[i], out subserviceDescription))
                {
                    throw new InvalidPathException();
                }
                serviceDesc = subserviceDescription.Service;
            }

            var methodName = servicePath.MethodName;
            MethodDescription methodDesc;

            if (!serviceDesc.TryGetMethod(methodName, out methodDesc))
            {
                throw new InvalidPathException();
            }

            bool hasRetval  = methodDesc.ReturnType != typeof(void);
            var  parameters = methodDesc.Parameters.Select((x, i) => new ParameterNecessity
            {
                Description   = x,
                Codec         = codecContainer.GetEmittingCodecFor(x.Type),
                LocalVariable = x.Way != MethodParameterWay.Val ? il.DeclareLocal(x.Type) : null,
                ArgumentIndex = i
            })
                              .ToArray();

            var requestParameters = parameters
                                    .Where(x => x.Description.Way == MethodParameterWay.Val || x.Description.Way == MethodParameterWay.Ref)
                                    .ToArray();

            var responseParameters = parameters
                                     .Where(x => x.Description.Way == MethodParameterWay.Ref || x.Description.Way == MethodParameterWay.Out)
                                     .ToArray();

            LocalBuilder requestDataPointerVar = null;

            if (requestParameters.Any())
            {
                il.Emit(OpCodes.Ldarg_1);                                   // remainingBytes = arg_1.Length
                il.Emit(OpCodes.Ldlen);
                il.Emit(OpCodes.Stloc, locals.RemainingBytes);
                requestDataPointerVar =                                     // var pinned dataPointer = pin(arg_1)
                                        il.Emit_PinArray(typeof(byte), 1);
                il.Emit(OpCodes.Ldloc, requestDataPointerVar);              // data = dataPointer
                il.Emit(OpCodes.Stloc, locals.DataPointer);
            }

            foreach (var parameter in parameters)
            {
                switch (parameter.Description.Way)
                {
                case MethodParameterWay.Val:
                    parameter.Codec.EmitDecode(il, locals, false);          // stack_i = decode(data, remainingBytes, false)
                    break;

                case MethodParameterWay.Ref:
                    parameter.Codec.EmitDecode(il, locals, false);          // param_i = decode(data, remainingBytes, false)
                    il.Emit(OpCodes.Stloc, parameter.LocalVariable);
                    il.Emit(OpCodes.Ldloca, parameter.LocalVariable);       // stack_i = *param_i
                    break;

                case MethodParameterWay.Out:
                    il.Emit(OpCodes.Ldloca, parameter.LocalVariable);       // stack_i = *param_i
                    break;

                default:
                    throw new ArgumentOutOfRangeException();
                }
            }

            if (requestParameters.Any())
            {
                il.Emit_UnpinArray(requestDataPointerVar);                  // unpin(dataPointer)
            }

            il.Emit(OpCodes.Callvirt, methodDesc.MethodInfo);                          // stack_0 = stack_0.Method(stack_1, stack_2, ...)

            if (hasRetval || responseParameters.Any())
            {
                IEmittingCodec retvalCodec = null;
                LocalBuilder   retvalVar   = null;

                if (hasRetval)
                {
                    retvalCodec = codecContainer.GetEmittingCodecFor(methodDesc.ReturnType);
                    retvalVar   = il.DeclareLocal(methodDesc.ReturnType);           // var ret = stack_0
                    il.Emit(OpCodes.Stloc, retvalVar);
                    retvalCodec.EmitCalculateSize(il, retvalVar);                   // stack_0 = calculateSize(ret)
                }

                bool hasSizeOnStack = hasRetval;
                foreach (var parameter in responseParameters)
                {
                    parameter.Codec.EmitCalculateSize(il, parameter.LocalVariable); // stack_0 += calculateSize(param_i)
                    if (hasSizeOnStack)
                    {
                        il.Emit(OpCodes.Add);
                    }
                    else
                    {
                        hasSizeOnStack = true;
                    }
                }

                var dataArrayVar = il.DeclareLocal(typeof(byte[]));                 // var dataArray = new byte[size of retval]
                il.Emit(OpCodes.Newarr, typeof(byte));
                il.Emit(OpCodes.Stloc, dataArrayVar);

                var responseDataPointerVar =                                        // var pinned dataPointer = pin(dataArrayVar)
                                             il.Emit_PinArray(typeof(byte), dataArrayVar);
                il.Emit(OpCodes.Ldloc, responseDataPointerVar);                     // data = dataPointer
                il.Emit(OpCodes.Stloc, locals.DataPointer);

                foreach (var parameter in responseParameters)
                {
                    parameter.Codec.EmitEncode(il, locals, parameter.LocalVariable);// encode(data, param_i)
                }
                if (hasRetval)
                {
                    retvalCodec.EmitEncode(il, locals, retvalVar);                  // encode(data, ret)
                }
                il.Emit_UnpinArray(responseDataPointerVar);                         // unpin(dataPointer)
                il.Emit(OpCodes.Ldloc, dataArrayVar);                               // stack_0 = dataArray
            }
            else
            {
                il.Emit(OpCodes.Ldc_I4, 0);                                         // stack_0 = new byte[0]
                il.Emit(OpCodes.Newarr, typeof(byte));
            }

            il.Emit(OpCodes.Ret);
            return((ServiceMethodHandler)dynamicMethod.CreateDelegate(typeof(ServiceMethodHandler)));
        }
 public void EmitEncode(IEmittingContext emittingContext)
 {
     typeCodec.EmitEncode(emittingContext, Loaders.TypeOf(type));
 }
Пример #13
0
 public void EmitEncode()
 {
     codec.EmitEncode(emittingContext, Loaders.Local(local));
 }
Пример #14
0
 public static void EmitEncode(this IEmittingCodec codec, ILGenerator il, ILocalVariableCollection locals, LocalBuilder localVar)
 {
     codec.EmitEncode(il, locals, lil => lil.Emit(OpCodes.Ldloc, localVar));
 }
Пример #15
0
 public static void EmitEncodeIndirect(this IEmittingCodec codec, ILGenerator il, ILocalVariableCollection locals, int argIndex, Type type)
 {
     codec.EmitEncode(il, locals, lil => { lil.Emit_Ldarg(argIndex); lil.Emit(OpCodes.Ldobj, type); });
 }
Пример #16
0
 public static void EmitEncode(this IEmittingCodec codec, ILGenerator il, ILocalVariableCollection locals, int argIndex)
 {
     codec.EmitEncode(il, locals, lil => lil.Emit_Ldarg(argIndex));
 }