예제 #1
0
        private static KeyValuePair <Delegate, IntPtr> GetReader(ReaderMethodBuilderContext context, Type type)
        {
            var method = new DynamicMethod("Read_" + type.Name + "_AndCastToObject_" + Guid.NewGuid(), typeof(void),
                                           new[]
            {
                typeof(IntPtr), typeof(int).MakeByRefType(), typeof(object).MakeByRefType(), typeof(ReaderContext)
            }, context.Context.Module, true);

            using (var il = new GroboIL(method))
            {
                il.Ldarg(2);      // stack: [ref result]
                il.Ldarg(0);      // stack: [ref result, data]
                il.Ldarg(1);      // stack: [ref result, data, ref index]
                var value = il.DeclareLocal(type);
                il.Ldloca(value); // stack: [ref result, data, ref index, ref value]
                il.Ldarg(3);      // stack: [ref result, data, ref index, ref value, context]

                ReaderMethodBuilderContext.CallReader(il, type, context.Context);

                il.Ldloc(value); // stack: [ref result, value]
                if (type.IsValueType)
                {
                    il.Box(type); // stack: [ref result, (object)value]
                }
                else
                {
                    il.Castclass(type);
                }
                il.Stind(typeof(object)); // result = (object)value
                il.Ret();
            }
            var @delegate = method.CreateDelegate(typeof(ReaderDelegate));

            return(new KeyValuePair <Delegate, IntPtr>(@delegate, GroBufHelpers.ExtractDynamicMethodPointer(method)));
        }
예제 #2
0
        private static Func <object, object> BuildExtractor(FieldInfo field)
        {
            var methodName = "FieldExtractor$";

            if (field.IsStatic)
            {
                methodName += field.DeclaringType + "$";
            }
            methodName += field.Name + "$" + Guid.NewGuid();
            var dynamicMethod = new DynamicMethod(methodName, typeof(object), new[] { typeof(object) }, typeof(FieldsExtractor), true);

            using (var il = new GroboIL(dynamicMethod))
            {
                if (!field.IsStatic)
                {
                    il.Ldarg(0);
                    il.Castclass(field.DeclaringType);
                }
                il.Ldfld(field);
                if (field.FieldType.IsValueType)
                {
                    il.Box(field.FieldType);
                }
                il.Ret();
            }
            return((Func <object, object>)dynamicMethod.CreateDelegate(typeof(Func <object, object>)));
        }
예제 #3
0
 private void LoadTupleField(GroboIL il, ValueTupleField tupleFiled)
 {
     il.Ldstr(tupleFiled.NameInUserCode);
     il.Ldarga(0);
     il.Ldfld(tupleFiled.FieldInfo);
     if (tupleFiled.FieldInfo.FieldType.IsValueType)
     {
         il.Box(tupleFiled.FieldInfo.FieldType);
     }
 }
예제 #4
0
        private static void EmitNullableEquals(GroboIL il, MethodInfo getMethod, GroboIL.Label returnFalse)
        {
            // a.Equals(b)
            var type  = getMethod.ReturnType;
            var local = il.DeclareLocal(type);

            il.Ldarg(0);
            il.Call(getMethod);
            il.Stloc(local);
            il.Ldloca(local);
            il.Ldarg(1);
            il.Call(getMethod);
            il.Box(type);
            il.Call(ObjectEquals, type);
            il.Brfalse(returnFalse);
        }
        protected override bool EmitInternal(UnaryExpression node, EmittingContext context, GroboIL.Label returnDefaultValueLabel, ResultType whatReturn, bool extend, out Type resultType)
        {
            Type    operandType;
            var     result = ExpressionEmittersCollection.Emit(node.Operand, context, returnDefaultValueLabel, ResultType.Value, extend, out operandType);
            GroboIL il     = context.Il;

            if (operandType.IsValueType)
            {
                il.Box(operandType);
            }
            il.Isinst(node.Type);
            if (node.Type.IsValueType)
            {
                il.Unbox_Any(node.Type);
            }
            resultType = node.Type;
            return(result);
        }
예제 #6
0
 private static void EmitNullableEquals(GroboIL il, MethodInfo getMethod, GroboIL.Label returnFalse)
 {
     // a.Equals(b)
     var type = getMethod.ReturnType;
     var local = il.DeclareLocal(type);
     il.Ldarg(0);
     il.Call(getMethod);
     il.Stloc(local);
     il.Ldloca(local);
     il.Ldarg(1);
     il.Call(getMethod);
     il.Box(type);
     il.Call(ObjectEquals, type);
     il.Brfalse(returnFalse);
 }
예제 #7
0
        private static MethodBuilder GenerateOverloadedMethodDelegate(MethodInfo methodToIntercept,
                                                                      TypeBuilder typeBuilder,
                                                                      FieldInfo concrete)
        {
            // Define the method
            var method = typeBuilder.DefineMethod(methodToIntercept.Name + "-Delegate",
                                                  MethodAttributes.Private | MethodAttributes.HideBySig,
                                                  methodToIntercept.ReturnType,
                                                  new[] { typeof(ParamInfo[]) });

            SetupGenericMethodArguments(methodToIntercept, method);

            // Local for each out/ref parameter
            var parameters = methodToIntercept.GetParameters();

            var locals = new Dictionary <string, Local>();

            using (var il = new GroboIL(method))
            {
                foreach (ParameterInfo parameter in parameters)
                {
                    if (parameter.IsOut || parameter.ParameterType.IsByRef)
                    {
                        locals.Add(parameter.Name, il.DeclareLocal(parameter.ParameterType.GetElementType(), parameter.Name));
                    }
                }

                var paramInfoType     = typeof(ParamInfo);
                var paramInfoGetValue = paramInfoType.GetProperty("Value").GetGetMethod();

                // Initialize out parameters to default values
                for (var i = 0; i < parameters.Length; i++)
                {
                    if (parameters[i].ParameterType.IsByRef && !parameters[i].IsOut)
                    {
                        il.Ldarg(1);
                        il.Ldc_I4(i);
                        il.Ldelem(paramInfoType);
                        il.Call(paramInfoGetValue);

                        if (parameters[i].ParameterType.GetElementType().IsValueType)
                        {
                            il.Unbox_Any(parameters[i].ParameterType.GetElementType());
                        }
                        else
                        {
                            il.Castclass(parameters[i].ParameterType.GetElementType());
                        }

                        il.Stloc(locals[parameters[i].Name]);
                    }
                }

                // Load target
                il.Ldarg(0);
                il.Ldfld(concrete);

                // Push call values onto stack
                for (var i = 0; i < parameters.Length; i++)
                {
                    if (parameters[i].IsOut || parameters[i].ParameterType.IsByRef)
                    {
                        il.Ldloca(locals[parameters[i].Name]);
                    }
                    else
                    {
                        il.Ldarg(1);
                        il.Ldc_I4(i);
                        il.Ldelem(paramInfoType);
                        il.Call(paramInfoGetValue);

                        if (parameters[i].ParameterType.IsValueType || parameters[i].ParameterType.IsGenericParameter)
                        {
                            il.Unbox_Any(parameters[i].ParameterType);
                        }
                        else
                        {
                            il.Castclass(parameters[i].ParameterType);
                        }
                    }
                }

                // Call intercepted method
                il.Call(methodToIntercept);

                var paramInfoSetValue = paramInfoType.GetProperty("Value").GetSetMethod();

                // Copy out/ref parameter values back into passed-in parameters array
                for (var i = 0; i < parameters.Length; i++)
                {
                    if (parameters[i].IsOut || parameters[i].ParameterType.IsByRef)
                    {
                        il.Ldarg(1);
                        il.Ldc_I4(i);
                        il.Ldelem(paramInfoType);
                        il.Ldloc(locals[parameters[i].Name]);

                        if (parameters[i].ParameterType.GetElementType().IsValueType)
                        {
                            il.Box(parameters[i].ParameterType.GetElementType());
                        }

                        il.Call(paramInfoSetValue);
                    }
                }

                il.Ret();

                LogIlCode(il);
            }

            return(method);
        }
예제 #8
0
        private static void DefineMethodOverrideWithInterception(TypeBuilder typeBuilder, MethodBuilder methodBuilder, MethodInfo overridedMethod, Dictionary <Type, FieldInfo> interceptorFields, MethodInfo genericInterceptionAction, MethodInfo voidInterceptionAction, FieldBuilder concreteInstance, ParameterInfo[] methodParams, Type[] genericParameterTypes, Type[] interceptors)
        {
            var @delegate = GenerateOverloadedMethodDelegate(overridedMethod, typeBuilder, concreteInstance);

            for (var i = 0; i < interceptors.Length; i++)
            {
                var interceptor = interceptors[i];

                @delegate = DefineMethodInterceptingDelegate(typeBuilder, overridedMethod, interceptorFields, genericInterceptionAction, voidInterceptionAction, genericParameterTypes, @delegate, i, interceptor);
            }

            using (var il = new GroboIL(methodBuilder))
            {
                var paramInfoType  = typeof(ParamInfo);
                var paramsInfoType = typeof(ParamInfo[]);
                var paramsInfo     = il.DeclareLocal(paramsInfoType);
                var paramInfo      = il.DeclareLocal(paramInfoType);

                il.Nop();

                il.Ldc_I4(methodParams.Length);
                il.Newarr(typeof(ParamInfo));
                il.Stloc(paramsInfo);

                var paramInfoConstructor = paramInfoType.GetConstructor(new[] { typeof(string), typeof(Type), typeof(bool), typeof(bool) });
                var paramInfoValueSetter = paramInfoType.GetProperty("Value").GetSetMethod();
                var getTypeMethod        = typeof(Type).GetMethod("GetTypeFromHandle", new[] { typeof(RuntimeTypeHandle) });

                var idx = 0;
                foreach (var parameter in methodParams)
                {
                    // load array at index
                    il.Ldloc(paramsInfo);
                    il.Ldc_I4(idx++);

                    // Load ParamInfo.Name
                    il.Ldstr(parameter.Name);

                    // Load ParamInfo.Type
                    if (parameter.IsOut || parameter.ParameterType.IsByRef)
                    {
                        il.Ldtoken(parameter.ParameterType.GetElementType());
                    }
                    else
                    {
                        il.Ldtoken(parameter.ParameterType);
                    }

                    il.Call(getTypeMethod);

                    // Load ParamInfo.IsByRef
                    if (parameter.ParameterType.IsByRef)
                    {
                        il.Ldc_I4(1);
                    }
                    else
                    {
                        il.Ldc_I4(0);
                    }

                    // Load ParamInfo.IsOut
                    if (parameter.IsOut)
                    {
                        il.Ldc_I4(1);
                    }
                    else
                    {
                        il.Ldc_I4(0);
                    }

                    // instantiate ParamInfo
                    il.Newobj(paramInfoConstructor);
                    il.Stloc(paramInfo);

                    // Set ParamInfo.Value
                    il.Ldloc(paramInfo);
                    il.Ldarg(parameter.Position + 1);
                    if (parameter.IsOut || parameter.ParameterType.IsByRef)
                    {
                        il.Ldobj(parameter.ParameterType.GetElementType());

                        if (parameter.ParameterType.GetElementType().IsValueType || parameter.ParameterType.GetElementType().IsGenericParameter)
                        {
                            il.Box(parameter.ParameterType.GetElementType());
                        }
                    }
                    else
                    {
                        if (parameter.ParameterType.IsValueType || parameter.ParameterType.IsGenericParameter)
                        {
                            il.Box(parameter.ParameterType);
                        }
                    }

                    il.Call(paramInfoValueSetter);
                    il.Nop();

                    // push to array
                    il.Ldloc(paramInfo);
                    il.Stelem(paramInfoType);
                }

                il.Ldarg(0);
                il.Ldloc(paramsInfo);
                if (overridedMethod.IsGenericMethodDefinition)
                {
                    il.Call(@delegate.MakeGenericMethod(genericParameterTypes));
                }
                else
                {
                    il.Call(@delegate);
                }

                idx = 1;
                var paramInfoValueGetter = paramInfoType.GetProperty("Value").GetGetMethod();
                foreach (var parameter in methodParams)
                {
                    if (parameter.IsOut || parameter.ParameterType.IsByRef)
                    {
                        il.Ldarg(idx);
                        il.Ldloc(paramsInfo);
                        il.Ldc_I4(idx - 1);
                        il.Ldelem(paramInfoType);
                        il.Call(paramInfoValueGetter);

                        if (parameter.ParameterType.GetElementType().IsValueType)
                        {
                            il.Unbox_Any(parameter.ParameterType.GetElementType());
                        }

                        il.Stobj(parameter.ParameterType.GetElementType());
                    }

                    idx++;
                }

                il.Ret();

                LogIlCode(il);
            }
        }