コード例 #1
0
ファイル: ManualCodecBase.cs プロジェクト: yonglehou/SharpRPC
        private DynamicMethod EmitDecode(bool doNoCheckBounds)
        {
            const int codecContainerArgIndex = 0;
            const int dataArgIndex           = 1;
            const int remainingBytesArgIndex = 2;

            var dynamicMethod = new DynamicMethod("_decode_manual_" + type.FullName + (doNoCheckBounds ? "_dncb_" : ""),
                                                  type, new[] { typeof(ICodecContainer), typeof(byte *).MakeByRefType(), typeof(int).MakeByRefType() }, 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);
            il.Ldarg(remainingBytesArgIndex);
            il.Ldind_I4();
            il.Stloc(context.RemainingBytesVar);
            emittingCodec.EmitDecode(context, doNoCheckBounds);
            il.Ldarg(dataArgIndex);
            il.Ldloc(context.DataPointerVar);
            il.Stind_I();
            il.Ldarg(remainingBytesArgIndex);
            il.Ldloc(context.RemainingBytesVar);
            il.Stind_I4();
            il.Ret();
            return(dynamicMethod);
        }
コード例 #2
0
        private static void CreateConstructor(HandlerClassBuildingContext classContext)
        {
            const int thisArgIndex           = 0;
            const int codecContainerArgIndex = 1;

            var constructorBuilder = classContext.Builder.DefineConstructor(
                MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.SpecialName | MethodAttributes.RTSpecialName,
                CallingConventions.Standard, new[] { typeof(ICodecContainer) });
            var baseConstructor = typeof(object).GetConstructor(Type.EmptyTypes);
            var il = new MyILGenerator(constructorBuilder.GetILGenerator());

            il.Ldarg(thisArgIndex);
            il.Call(baseConstructor);
            il.Ldarg(thisArgIndex);
            il.Ldarg(codecContainerArgIndex);
            il.Stfld(classContext.Fields.CodecContainer);

            foreach (var manualCodecField in classContext.Fields.GetAllManualCodecFields())
            {
                il.Ldarg(thisArgIndex);
                il.Ldarg(codecContainerArgIndex);
                il.Call(CodecContainerMethods.GetManualCodecFor(manualCodecField.FieldType.GenericTypeArguments[0]));
                il.Stfld(manualCodecField);
            }

            il.Ret();
        }
コード例 #3
0
ファイル: ProxyFactory.cs プロジェクト: yonglehou/SharpRPC
        private MethodInfo CreateDecodeDeferredMethod(ProxyClassBuildingContext classContext, string parentMethodName, IReadOnlyList <Type> genericTypeArguments, Type pureRetvalType)
        {
            var methodBuilder = classContext.Builder.DefineMethod("__rpc_decode_deferred_" + parentMethodName,
                                                                  MethodAttributes.Private | MethodAttributes.HideBySig);

            var genericTypeParameterBuilders = genericTypeArguments.Any()
                ? methodBuilder.DefineGenericParameters(genericTypeArguments.Select(x => x.Name).ToArray())
                : new GenericTypeParameterBuilder[0];
            var genericArgumentMap = genericTypeParameterBuilders.ToDictionary(x => x.Name, x => (Type)x);

            var retvalType = pureRetvalType.DeepSubstituteGenerics(genericArgumentMap);

            methodBuilder.SetParameters(DecodeDeferredParameterTypes);
            methodBuilder.SetReturnType(retvalType);
            methodBuilder.SetImplementationFlags(MethodImplAttributes.Managed);

            var il = new MyILGenerator(methodBuilder.GetILGenerator());
            var emittingContext = new ProxyMethodEmittingContext(il, classContext.Fields);

            il.Ldarg(1);
            il.Call(TaskMethods.GetResult(typeof(byte[])));
            EmitPrepareToDecode(emittingContext);

            var retvalCodec = new ProxyMethodRetvalCodec(retvalType);

            retvalCodec.EmitDecode(emittingContext);
            il.Ret();

            return(methodBuilder);
        }
コード例 #4
0
ファイル: ManualCodecBase.cs プロジェクト: yonglehou/SharpRPC
        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);
        }
コード例 #5
0
        private static Func <Type, string, string, Exception> CreateExceptionCreator()
        {
            var dynamicMethod = new DynamicMethod(
                "__srpc__CreateException",
                typeof(Exception), new[] { typeof(Type), typeof(string), typeof(string) },
                Assembly.GetExecutingAssembly().ManifestModule, true);
            var il = new MyILGenerator(dynamicMethod.GetILGenerator());

            il.Ldarg(0);                            // stack_0 = (Exception)FormatterServices.GetUninitializedObject(typeof(T))
            il.Call(GetUninitializedObject);
            il.Castclass(typeof(Exception));

            il.Dup();                               // stack_0.Init()
            il.Call(InitMethod);
            il.Dup();                               // stack_0._message = message
            il.Ldarg(1);
            il.Stfld(MessageField);
            il.Dup();                               // stack_0._message = message
            il.Ldarg(2);
            il.Stfld(RemoteStackTraceStringField);
            il.Ret();
            return((Func <Type, string, string, Exception>)dynamicMethod.CreateDelegate(typeof(Func <Type, string, string, Exception>)));
        }
コード例 #6
0
        private static MethodBuilder CreateEncodeDeferredMethod(HandlerClassBuildingContext classContext, Type pureRetvalType)
        {
            const int taskArgIndex = 1;

            var methodBuilder = classContext.Builder.DefineMethod("EncodeDeferred",
                                                                  MethodAttributes.Private | MethodAttributes.Final | MethodAttributes.HideBySig | MethodAttributes.NewSlot,
                                                                  typeof(byte[]), new[] { typeof(Task <>).MakeGenericType(pureRetvalType) });

            var il = new MyILGenerator(methodBuilder.GetILGenerator());
            var emittingContext = new HandlerMethodEmittingContext(il, classContext.Fields);

            il.Ldarg(taskArgIndex);
            il.Call(TaskMethods.GetResult(pureRetvalType));
            EmitEncodeDirect(emittingContext, new HandlerParameterCodec[0], pureRetvalType);
            il.Ret();
            return(methodBuilder);
        }
コード例 #7
0
ファイル: ProxyFactory.cs プロジェクト: yonglehou/SharpRPC
        private static void CreateSubserviceProperty(ProxyClassBuildingContext classContext, ServiceDescription subserviceDescription, FieldBuilder fieldBuilder)
        {
            var methodBuilder = classContext.Builder.DefineMethod("get_" + subserviceDescription.Name,
                                                                  MethodAttributes.Public | MethodAttributes.Final | MethodAttributes.HideBySig |
                                                                  MethodAttributes.SpecialName | MethodAttributes.NewSlot | MethodAttributes.Virtual,
                                                                  subserviceDescription.Type, Type.EmptyTypes);

            methodBuilder.SetImplementationFlags(MethodImplAttributes.Managed);
            var il = new MyILGenerator(methodBuilder.GetILGenerator());

            il.Ldarg(0);
            il.Ldfld(fieldBuilder);
            il.Ret();

            var propertyBuilder = classContext.Builder.DefineProperty(subserviceDescription.Name,
                                                                      PropertyAttributes.None, subserviceDescription.Type, Type.EmptyTypes);

            propertyBuilder.SetGetMethod(methodBuilder);
        }
コード例 #8
0
        private static void CreateMethodDelegate(HandlerClassBuildingContext classContext)
        {
            const int implementationArgIndex = 1;
            const int dataArgIndex           = 2;
            const int offsetArgIndex         = 3;

            var methodBuilder = classContext.Builder.DefineMethod("Handle",
                                                                  MethodAttributes.Public | MethodAttributes.Final | MethodAttributes.HideBySig |
                                                                  MethodAttributes.NewSlot | MethodAttributes.Virtual,
                                                                  typeof(Task <byte[]>), new[] { typeof(object), typeof(byte[]), typeof(int) });

            var il = new MyILGenerator(methodBuilder.GetILGenerator());
            var emittingContext = new HandlerMethodEmittingContext(il, classContext.Fields);

            var serviceDescriptionChain = classContext.ServiceDescriptionChain;

            il.Ldarg(implementationArgIndex);                                       // stack_0 = (TServiceImplementation) arg_1
            il.Castclass(serviceDescriptionChain.First().Type);

            for (int i = 0; i < serviceDescriptionChain.Count - 1; i++)
            {
                var current = serviceDescriptionChain[i];
                var next    = serviceDescriptionChain[i + 1];
                il.Callvirt(current.Type.GetProperty(next.Name).GetGetMethod());    // stack_0 = stack_0.Property
            }

            var methodDescription = classContext.MethodDescription;

            var genericArgumentMap = methodDescription.GenericParameters
                                     .Zip(classContext.GenericTypeParameterBuilders, (p, a) => new KeyValuePair <string, Type>(p.Name, a))
                                     .ToDictionary(x => x.Key, x => x.Value);

            var parameterDescriptions = methodDescription.Parameters.Select(x => x.DeepSubstituteGenerics(genericArgumentMap)).ToArray();
            var retvalType            = methodDescription.ReturnType.DeepSubstituteGenerics(genericArgumentMap);

            var allParameterCodecs      = parameterDescriptions.Select((x, i) => new HandlerParameterCodec(emittingContext, x)).ToArray();
            var requestParameterCodecs  = allParameterCodecs.Where(x => x.IsRequestParameter).ToArray();
            var responseParameterCodecs = allParameterCodecs.Where(x => x.IsResponseParameter).ToArray();

            if (requestParameterCodecs.Any())
            {
                il.Ldarg(dataArgIndex);                                 // remainingBytes = dataArray.Length - offset
                il.Ldlen();
                il.Ldarg(offsetArgIndex);
                il.Sub();
                il.Stloc(emittingContext.RemainingBytesVar);
                var pinnedVar = il.PinArray(typeof(byte), 2);           // var pinned dataPointer = pin(dataArray)
                il.Ldloc(pinnedVar);                                    // data = dataPointer + offset
                il.Ldarg(offsetArgIndex);
                il.Add();
                il.Stloc(emittingContext.DataPointerVar);
            }

            foreach (var codec in allParameterCodecs)
            {
                codec.EmitDecodeAndPrepare();
            }

            // ReSharper disable CoVariantArrayConversion
            var resolvedMethodInfo = classContext.GenericTypeParameterBuilders.Any()
                ? methodDescription.MethodInfo.MakeGenericMethod(classContext.GenericTypeParameterBuilders)
                : methodDescription.MethodInfo;

            il.Callvirt(resolvedMethodInfo);                            // stack_0 = stack_0.Method(stack_1, stack_2, ...)
            // ReSharper restore CoVariantArrayConversion

            switch (methodDescription.RemotingType)
            {
            case MethodRemotingType.Direct:
                EmitProcessAndEncodeDirect(emittingContext, responseParameterCodecs, retvalType);
                break;

            case MethodRemotingType.AsyncVoid:
                EmitProcessAndEncodeAsyncVoid(emittingContext);
                break;

            case MethodRemotingType.AsyncWithRetval:
                EmitProcessAndEncodeAsyncWithRetval(classContext, emittingContext, retvalType.GetGenericArguments()[0]);
                break;

            default:
                throw new ArgumentOutOfRangeException();
            }

            il.Ret();
        }
コード例 #9
0
ファイル: ProxyFactory.cs プロジェクト: yonglehou/SharpRPC
        private void CreateMethod(ProxyClassBuildingContext classContext, string path, MethodDescription methodDesc)
        {
            var methodBuilder = classContext.Builder.DefineMethod(methodDesc.Name,
                                                                  MethodAttributes.Public | MethodAttributes.Final | MethodAttributes.HideBySig |
                                                                  MethodAttributes.NewSlot | MethodAttributes.Virtual);

            var genericTypeParameterBuilders = methodDesc.GenericParameters.Any()
                ? methodBuilder.DefineGenericParameters(methodDesc.GenericParameters.Select(x => x.Name).ToArray())
                : new GenericTypeParameterBuilder[0];
            var genericTypeParameterCodecs = genericTypeParameterBuilders.Select(x => new ProxyMethodGenericArgumentCodec(x)).ToArray();
            var genericArgumentMap         = genericTypeParameterBuilders.ToDictionary(x => x.Name, x => (Type)x);

            var parameterDescriptions         = methodDesc.Parameters.Select(x => x.DeepSubstituteGenerics(genericArgumentMap)).ToArray();
            var parameterTypesAdjustedForRefs = parameterDescriptions.Select(x => x.Way == MethodParameterWay.Val ? x.Type : x.Type.MakeByRefType()).ToArray();
            var allParameterCodecs            = parameterDescriptions.Select(x => new ProxyMethodParameterCodec(x)).ToArray();

            var retvalType = methodDesc.ReturnType.DeepSubstituteGenerics(genericArgumentMap);

            methodBuilder.SetParameters(parameterTypesAdjustedForRefs);
            methodBuilder.SetReturnType(retvalType);
            methodBuilder.SetImplementationFlags(MethodImplAttributes.Managed);

            var il = new MyILGenerator(methodBuilder.GetILGenerator());
            var emittingContext = new ProxyMethodEmittingContext(il, classContext.Fields);

            var requestDataArrayVar = il.DeclareLocal(typeof(byte[]));                      // byte[] dataArray

            var requestParametersCodecs = allParameterCodecs.Where(x => x.IsRequestParameter).ToArray();

            if (requestParametersCodecs.Any() || genericTypeParameterBuilders.Any())
            {
                bool haveSizeOnStack = false;
                foreach (var codec in genericTypeParameterCodecs)
                {
                    codec.EmitCalculateSize(emittingContext);                               // stack_0 += CalculateSize(T_i)
                    EmitAddIf(il, ref haveSizeOnStack);
                }
                foreach (var parameter in requestParametersCodecs)
                {
                    parameter.EmitCalculateSize(emittingContext);                           // stack_0 += CalculateSize(arg_i)
                    EmitAddIf(il, ref haveSizeOnStack);
                }

                il.Newarr(typeof(byte));                                                    // dataArray = new byte[stack_0]
                il.Stloc(requestDataArrayVar);
                var pinnedVar = il.PinArray(typeof(byte), requestDataArrayVar);             // var pinned dataPointer = pin(dataArray)
                il.Ldloc(pinnedVar);                                                        // data = dataPointer
                il.Stloc(emittingContext.DataPointerVar);

                foreach (var codec in genericTypeParameterCodecs)
                {
                    codec.EmitEncode(emittingContext);                                      // Encode(T_i, data)
                }
                foreach (var codec in requestParametersCodecs)
                {
                    codec.EmitEncode(emittingContext);                                      // Encode(arg_i, data)
                }
            }
            else
            {
                il.Ldnull();                                                                // dataArray = null
                il.Stloc(requestDataArrayVar);
            }

            il.Ldarg(0);                                                                    // stack_0 = methodCallProcessor
            il.Ldfld(classContext.Fields.Processor);
            il.Ldtoken(classContext.InterfaceType);                                         // stack_1 = typeof(T)
            il.Call(TypeMethods.GetTypeFromHandle);
            il.Ldstr(string.Format("{0}/{1}", path, methodDesc.Name));                      // stack_2 = SuperServicePath/ServiceName/MethodName
            il.Ldarg(0);                                                                    // stack_3 = scope
            il.Ldfld(classContext.Fields.Scope);
            il.Ldloc(requestDataArrayVar);                                                  // stack_4 = dataArray
            il.Ldarg(0);                                                                    // stack_5 = timeoutSettings
            il.Ldfld(classContext.Fields.TimeoutSettings);

            var responseParameterCodecs = allParameterCodecs.Where(x => x.IsResponseParameter).ToArray();

            if (responseParameterCodecs.Any() && methodDesc.RemotingType != MethodRemotingType.Direct)
            {
                throw new ArgumentException(string.Format("Error processing {0} method: only direct methods can have Ref or Out parameters", path));
            }

            switch (methodDesc.RemotingType)
            {
            case MethodRemotingType.Direct:
                EmitProcessDirect(emittingContext, responseParameterCodecs, retvalType);
                break;

            case MethodRemotingType.AsyncVoid:
                EmitProcessAsyncVoid(il);
                break;

            case MethodRemotingType.AsyncWithRetval:
                EmitProcessAsyncWithRetval(classContext, emittingContext, methodDesc.Name, genericTypeParameterBuilders, retvalType);
                break;

            default:
                throw new ArgumentOutOfRangeException();
            }

            il.Ret();
        }
コード例 #10
0
ファイル: ProxyFactory.cs プロジェクト: yonglehou/SharpRPC
        private void CreateConstructor(ProxyClassBuildingContext classContext, string path, ServiceDescription serviceDescription)
        {
            const int thisArgIndex            = 0;
            const int processorArgIndex       = 1;
            const int scopeArgIndex           = 2;
            const int timeoutSettingsArgIndex = 3;
            const int codecContainerArgIndex  = 4;

            var constructorBuilder = classContext.Builder.DefineConstructor(
                MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.SpecialName | MethodAttributes.RTSpecialName,
                CallingConventions.Standard, ConstructorParameterTypes);
            var baseConstructor = typeof(object).GetConstructor(Type.EmptyTypes);
            var il = new MyILGenerator(constructorBuilder.GetILGenerator());

            il.Ldarg(thisArgIndex);
            il.Call(baseConstructor);
            il.Ldarg(thisArgIndex);
            il.Ldarg(processorArgIndex);
            il.Stfld(classContext.Fields.Processor);
            il.Ldarg(thisArgIndex);
            il.Ldarg(scopeArgIndex);
            il.Stfld(classContext.Fields.Scope);
            il.Ldarg(thisArgIndex);
            il.Ldarg(timeoutSettingsArgIndex);
            il.Stfld(classContext.Fields.TimeoutSettings);
            il.Ldarg(thisArgIndex);
            il.Ldarg(codecContainerArgIndex);
            il.Stfld(classContext.Fields.CodecContainer);

            foreach (var manualCodecField in classContext.Fields.GetAllManualCodecFields())
            {
                var type = manualCodecField.FieldType.GenericTypeArguments[0];
                ValidateManualCodecType(type);

                il.Ldarg(thisArgIndex);
                il.Ldarg(codecContainerArgIndex);
                il.Call(CodecContainerMethods.GetManualCodecFor(type));
                il.Stfld(manualCodecField);
            }

            foreach (var subserviceDesc in serviceDescription.Subservices)
            {
                var proxyClass   = CreateProxyClass(classContext.InterfaceType, subserviceDesc.Type, path + "/" + subserviceDesc.Name);
                var fieldBuilder = CreateSubserviceField(classContext, subserviceDesc, proxyClass);
                CreateSubserviceProperty(classContext, subserviceDesc, fieldBuilder);

                il.Ldarg(thisArgIndex);
                il.Ldarg(processorArgIndex);
                il.Ldarg(scopeArgIndex);
                il.Ldarg(timeoutSettingsArgIndex);
                il.Ldarg(codecContainerArgIndex);
                il.Newobj(proxyClass.GetConstructor(ConstructorParameterTypes));
                il.Stfld(fieldBuilder);
            }

            il.Ret();
        }