Beispiel #1
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);
        }
Beispiel #2
0
        private DynamicMethod EmitDecode(bool doNoCheckBounds)
        {
            var dynamicMethod = new DynamicMethod("_decode_manual_" + type.FullName + (doNoCheckBounds ? "_dncb_" : ""),
                                                  type, new[] { typeof(byte *).MakeByRefType(), typeof(int).MakeByRefType() }, Assembly.GetExecutingAssembly().ManifestModule, true);
            var il     = dynamicMethod.GetILGenerator();
            var locals = new LocalVariableCollection(il, true);

            il.Emit(OpCodes.Ldarg_0);
            il.Emit(OpCodes.Ldind_I);
            il.Emit(OpCodes.Stloc, locals.DataPointer);
            il.Emit(OpCodes.Ldarg_1);
            il.Emit(OpCodes.Ldind_I4);
            il.Emit(OpCodes.Stloc, locals.RemainingBytes);
            emittingCodec.EmitDecode(il, locals, doNoCheckBounds);
            il.Emit(OpCodes.Ldarg_0);
            il.Emit(OpCodes.Ldloc, locals.DataPointer);
            il.Emit(OpCodes.Stind_I);
            il.Emit(OpCodes.Ldarg_1);
            il.Emit(OpCodes.Ldloc, locals.RemainingBytes);
            il.Emit(OpCodes.Stind_I4);
            il.Emit(OpCodes.Ret);
            return(dynamicMethod);
        }
Beispiel #3
0
 private DynamicMethod EmitEncode()
 {
     var dynamicMethod = new DynamicMethod("_encode_manual_" + type.FullName,
                                           typeof(void), new[] { typeof(byte*).MakeByRefType(), type }, Assembly.GetExecutingAssembly().ManifestModule, !forceVisibilityChecks);
     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;
 }
Beispiel #4
0
 private DynamicMethod EmitDecode(bool doNoCheckBounds)
 {
     var dynamicMethod = new DynamicMethod("_decode_manual_" + type.FullName + (doNoCheckBounds ? "_dncb_" : ""),
                                           type, new[] { typeof(byte*).MakeByRefType(), typeof(int).MakeByRefType() }, Assembly.GetExecutingAssembly().ManifestModule, !forceVisibilityChecks);
     var il = dynamicMethod.GetILGenerator();
     var locals = new LocalVariableCollection(il, true);
     il.Emit(OpCodes.Ldarg_0);
     il.Emit(OpCodes.Ldind_I);
     il.Emit(OpCodes.Stloc, locals.DataPointer);
     il.Emit(OpCodes.Ldarg_1);
     il.Emit(OpCodes.Ldind_I4);
     il.Emit(OpCodes.Stloc, locals.RemainingBytes);
     emittingCodec.EmitDecode(il, locals, doNoCheckBounds);
     il.Emit(OpCodes.Ldarg_0);
     il.Emit(OpCodes.Ldloc, locals.DataPointer);
     il.Emit(OpCodes.Stind_I);
     il.Emit(OpCodes.Ldarg_1);
     il.Emit(OpCodes.Ldloc, locals.RemainingBytes);
     il.Emit(OpCodes.Stind_I4);
     il.Emit(OpCodes.Ret);
     return dynamicMethod;
 }
        public ServiceMethodHandler CreateMethodHandler(ServiceImplementationInfo serviceImplementationInfo, ServicePath servicePath)
        {
            var serviceInterface = serviceImplementationInfo.Interface;

            var dynamicMethod = new DynamicMethod(
                "__srpc__handle__" + serviceInterface.FullName + "__" + string.Join("_", servicePath),
                typeof(byte[]), ParameterTypes, Assembly.GetExecutingAssembly().ManifestModule);
            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;
            var methodInfo = serviceDesc.Type.GetMethod(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), locals, 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, 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), locals, 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));
        }