예제 #1
0
        /// <summary>
        /// Reduces the provided DynamicExpression into site.Target(site, *args).
        /// </summary>
        public Expression ReduceDyn(DynamicExpression node, out SiteInfo siteInfo)
        {
            MaybeInit();

            if (RewriteDelegate(node.DelegateType, out Type delegateType))
            {
                node = Expression.MakeDynamic(delegateType, node.Binder, node.Arguments);
            }

            CallSite cs = CallSite.Create(node.DelegateType, node.Binder);
            // TODO: fix this eventually to return the SiteInfo and not the Expression

            Expression access = RewriteCallSite(cs, _typeGen, delegateType ?? node.DelegateType, out siteInfo);

            // ($site = siteExpr).Target.Invoke($site, *args)
            ParameterExpression site = Expression.Variable(cs.GetType(), "$site");

            return(Expression.Block(
                       new[] { site },
                       Expression.Call(
                           Expression.Field(
                               Expression.Assign(site, access),
                               cs.GetType().GetField("Target")
                               ),
                           node.DelegateType.GetMethod("Invoke"),
                           ClrExtensions.ArrayInsert(site, node.Arguments)
                           )
                       ));
        }
예제 #2
0
        private Expression RewriteCallSite(CallSite site)
        {
            IExpressionSerializable serializer = site.Binder as IExpressionSerializable;

            if (serializer == null)
            {
                throw Error.GenNonSerializableBinder();
            }

            // add the initialization code that we'll generate later into the outermost
            // lambda and then return an index into the array we'll be creating.
            if (_constantPool == null)
            {
                _constantPool = Expression.Variable(typeof(object[]), "$constantPool");
                _constants    = new List <Expression>();
            }

            Type siteType = site.GetType();

            _constants.Add(Expression.Call(siteType.GetMethod("Create"), serializer.CreateExpression()));

            // rewrite the node...
            return(Visit(
                       AstUtils.Convert(
                           Expression.ArrayAccess(_constantPool, Expression.Constant(_constants.Count - 1)),
                           siteType
                           )
                       ));
        }
예제 #3
0
        private Expression RewriteCallSite(CallSite site, TypeGen tg)
        {
            IExpressionSerializable serializer = site.Binder as IExpressionSerializable;

            if (serializer == null)
            {
                throw new ArgumentException("Generating code from non-serializable CallSiteBinder.");
            }

            Type siteType = site.GetType();

            FieldBuilder fb   = tg.AddStaticField(siteType, "sf" + (_id++).ToString());
            Expression   init = Expression.Call(siteType.GetMethod("Create"), serializer.CreateExpression());

            _fieldBuilders.Add(fb);
            _fieldInits.Add(init);


            //Type t = init.Type;
            //if (t.IsGenericType)
            //{
            //    Type[] args = t.GetGenericArguments()[0].GetGenericArguments(); ;
            //    // skip the first one, it is the site.
            //    for (int k = 1; k < args.Length; k++)
            //    {
            //        Type p = args[k];
            //        //if (!p.Assembly.GetName().Name.Equals("mscorlib") && !p.Assembly.GetName().Name.Equals("Clojure"))
            //        //    Console.WriteLine("Found {0}", p.ToString());
            //    }
            //}

            // rewrite the node...
            return(Expression.Field(null, fb));
        }
예제 #4
0
        public DynamicInstructionN(Type delegateType, CallSite site)
        {
            MethodInfo method = delegateType.GetMethod("Invoke");

            ParameterInfo[] parameters = method.GetParameters();
            this._target         = CallInstruction.Create(method, parameters);
            this._site           = site;
            this._argumentCount  = parameters.Length - 1;
            this._targetDelegate = site.GetType().GetField("Target").GetValue(site);
        }
예제 #5
0
        public DynamicInstructionN(Type delegateType, CallSite site)
        {
            var methodInfo = delegateType.GetMethod("Invoke");
            var parameters = methodInfo.GetParameters();

            _target         = CallInstruction.Create(methodInfo, parameters);
            _site           = site;
            _argumentCount  = parameters.Length - 1;
            _targetDelegate = site.GetType().GetField("Target").GetValue(site);
        }
예제 #6
0
        public DynamicInstructionN(Type delegateType, CallSite site)
        {
            var methodInfo = delegateType.GetMethod("Invoke");
            var parameters = methodInfo.GetParameters();

            // <Delegate>.Invoke is ok to target by a delegate in partial trust (SecurityException is not thrown):
            _targetInvocationInstruction = CallInstruction.Create(methodInfo, parameters);
            _site           = site;
            _argumentCount  = parameters.Length - 1;
            _targetDelegate = site.GetType().GetInheritedFields("Target").First().GetValue(site);
        }
예제 #7
0
        internal Delegate CreateDelegate(Type delegateType, object target)
        {
            Assert.NotNull(delegateType, target);

            // to enable:
            // function x() { }
            // someClass.someEvent += delegateType(x)
            // someClass.someEvent -= delegateType(x)
            //
            // we need to avoid re-creating the object array because they won't
            // be compare equal when removing the delegate if they're difference
            // instances.  Therefore we use a weak hashtable to get back the
            // original object array.  The values also need to be weak to avoid
            // creating a circular reference from the constants target back to the
            // target.  This is fine because as long as the delegate is referenced
            // the object array will stay alive.  Once the delegate is gone it's not
            // wired up anywhere and -= will never be used again.

            object[] clone;
            lock (_constantMap) {
                WeakReference cloneRef;

                if (!_constantMap.TryGetValue(target, out cloneRef) ||
                    (clone = (object[])cloneRef.Target) == null)
                {
                    _constantMap[target] = new WeakReference(clone = (object[])_constants.Clone());

                    Type[] siteTypes = MakeSiteSignature();

                    CallSite callSite = CallSite.Create(DynamicSiteHelpers.MakeCallSiteDelegate(siteTypes), _invokeBinder);
                    Type     siteType = callSite.GetType();

                    Type     convertSiteType = null;
                    CallSite convertSite     = null;

                    if (_returnType != typeof(void))
                    {
                        convertSite     = CallSite.Create(DynamicSiteHelpers.MakeCallSiteDelegate(typeof(object), _returnType), _convertBinder);
                        convertSiteType = convertSite.GetType();
                    }

                    Debug.Assert(clone[0] == TargetPlaceHolder);
                    Debug.Assert(clone[1] == CallSitePlaceHolder);
                    Debug.Assert(clone[2] == ConvertSitePlaceHolder);

                    clone[0] = target;
                    clone[1] = callSite;
                    clone[2] = convertSite;
                }
            }

            return(ReflectionUtils.CreateDelegate(_method, delegateType, clone));
        }
예제 #8
0
        private Expression RewriteCallSite(CallSite site, TypeGen tg, Type delegateType, out SiteInfo siteInfo)
        {
            if (!(site.Binder is IExpressionSerializable serializer))
            {
                throw new ArgumentException("Generating code from non-serializable CallSiteBinder.");
            }

            Type         siteType = site.GetType();
            FieldBuilder fb       = tg.AddStaticField(siteType, "sf" + (_id++).ToString());

            siteInfo = new SiteInfo(fb, siteType, site.Binder, delegateType);
            _siteInfos.Add(siteInfo);

            // rewrite the node...
            return(Expression.Field(null, fb));
        }
        public object AccessValueElementTest(string elementName, object value, Type type)
        {
            XElement       element        = new XElement(elementName, value);
            dynamic        dynamicElement = element.AsDynamic();
            CallSiteBinder callsiteBinder = Binder.Convert(CSharpBinderFlags.None, type,
                                                           typeof(DynamicXElementReader));

            //-----------------------------------------------------------------------------------//
            // Creating Func<CallSite, object, Type>
            //-----------------------------------------------------------------------------------//
            // For type "int" this code is equivalent to:
            // Type constructedFuncType = typeof(Func<CallSite, object, int);

            Type openFuncType        = typeof(Func <, ,>);
            Type constructedFuncType = openFuncType.MakeGenericType(
                typeof(CallSite), typeof(object), type);

            //-----------------------------------------------------------------------------------//
            // Creating CallSite<Func<CallSite, object, Type>>
            //-----------------------------------------------------------------------------------//
            // For type "int" this code is equivalent to:
            // Type constructedCallSiteType = typeof(CallSite<Func<CallSite, object, int>>);
            Type callSiteType            = typeof(CallSite <>);
            Type constructedCallSiteType = callSiteType.MakeGenericType(constructedFuncType);

            //-----------------------------------------------------------------------------------//
            // var callSite = CallSite<Func<CallSite, object, int>>.Create(callSiteBinder);
            //-----------------------------------------------------------------------------------//
            var method = constructedCallSiteType.GetMethod("Create",
                                                           BindingFlags.Static | BindingFlags.Public);
            CallSite callSite = (CallSite)method.Invoke(null, new object[] { callsiteBinder });

            //-----------------------------------------------------------------------------------//
            // int actual = callSite.Target(callSite, dynamicElement);
            //-----------------------------------------------------------------------------------//
            FieldInfo targetFieldInfo = callSite.GetType().GetField("Target");
            object    target          = targetFieldInfo.GetValue(callSite);

            // target is underlying delegate instance of type: Func<CallSite, object, int>
            var targetMethod = target.GetType().GetMethod("Invoke",
                                                          BindingFlags.Instance | BindingFlags.Public);
            object actual = targetMethod.Invoke(target, new object[] { callSite, dynamicElement });

            Console.WriteLine("Name: {0}, Value: {1}, Type: {2}", elementName, value, type);
            Console.WriteLine("Actual value: {0}", actual);
            return(actual);
        }
예제 #10
0
        public static object CreateConvertCallSiteAndInvoke(ConvertBinder Action, object Instance)
        {
            object   obj2;
            CallSite site = CallSite.Create(Expression.GetFuncType(new Type[] { typeof(CallSite), typeof(object), Action.Type }), GetCachedBinder(Action));

            object[] args      = new object[] { site, Instance };
            Delegate delegate2 = (Delegate)site.GetType().GetField("Target").GetValue(site);

            try
            {
                obj2 = delegate2.DynamicInvoke(args);
            }
            catch (TargetInvocationException exception)
            {
                throw exception.InnerException;
            }
            return(obj2);
        }
예제 #11
0
        private Expression RewriteCallSite(CallSite site, TypeGen tg)
        {
            IExpressionSerializable serializer = site.Binder as IExpressionSerializable;

            if (serializer == null)
            {
                throw new ArgumentException("Generating code from non-serializable CallSiteBinder.");
            }

            Type siteType = site.GetType();

            FieldBuilder fb   = tg.AddStaticField(siteType, "sf" + (_id++).ToString());
            Expression   init = Expression.Call(siteType.GetMethod("Create"), serializer.CreateExpression());

            _fieldBuilders.Add(fb);
            _fieldInits.Add(init);

            // rewrite the node...
            return(Expression.Field(null, fb));
        }
예제 #12
0
        /// <summary>
        /// Uses LCG to create method such as this:
        ///
        /// object SplatCaller(CallSite{T} site, object[] args) {
        ///      return site.Target(site, args[0], args[1], args[2], ...);
        /// }
        ///
        /// where the CallSite is bound to the delegate
        /// </summary>
        /// <param name="args">the number of arguments</param>
        /// <returns>a SplatCaller delegate.</returns>
        private SplatCaller MakeBigCaller(int args)
        {
            // Get the dynamic site type
            var siteDelegateTypeArgs = new Type[args + 2];

            siteDelegateTypeArgs[0] = typeof(CallSite);
            for (int i = 1, n = siteDelegateTypeArgs.Length; i < n; i++)
            {
                siteDelegateTypeArgs[i] = typeof(object);
            }
            Type siteDelegateType = Expression.GetDelegateType(siteDelegateTypeArgs);

            // Create the callsite and get its type
            CallSite callSite = CallSite.Create(siteDelegateType, _binder);
            Type     siteType = callSite.GetType();

            var method = new DynamicMethod("_stub_SplatCaller", typeof(object), new Type[] { siteType, typeof(object[]) }, true);
            var gen    = method.GetILGenerator();

            // Emit the site's target
            gen.Emit(OpCodes.Ldarg_0);
            gen.Emit(OpCodes.Ldfld, siteType.GetField("Target"));

            // Emit the site
            gen.Emit(OpCodes.Ldarg_0);

            // Emit the arguments
            for (int i = 0; i < args; i++)
            {
                gen.Emit(OpCodes.Ldarg_1);
                gen.EmitInt(i);
                gen.Emit(OpCodes.Ldelem_Ref);
            }

            // Invoke the target
            gen.Emit(OpCodes.Callvirt, siteDelegateType.GetMethod("Invoke"));
            gen.Emit(OpCodes.Ret);

            // Create the delegate
            return(method.CreateDelegate <SplatCaller>(callSite));
        }
예제 #13
0
        private Expression RewriteCallSite(CallSite site)
        {
            IExpressionSerializable serializer = site.Binder as IExpressionSerializable;

            if (serializer == null)
            {
                throw Error.GenNonSerializableBinder();
            }

            EnsureConstantPool();

            Type siteType = site.GetType();

            _constants.Add(Expression.Call(siteType.GetMethod("Create"), serializer.CreateExpression()));

            // rewrite the node...
            return(Visit(
                       AstUtils.Convert(
                           Expression.ArrayAccess(_constantPool, AstUtils.Constant(_constants.Count - 1)),
                           siteType
                           )
                       ));
        }
예제 #14
0
            private void MakeReverseDelegateWorker(CodeContext context)
            {
                Type[] sigTypes;
                Type[] callSiteType;
                Type   retType;

                GetSignatureInfo(out sigTypes, out callSiteType, out retType);

                DynamicMethod dm    = new DynamicMethod("ReverseInteropInvoker", retType, ArrayUtils.RemoveLast(sigTypes), DynamicModule);
                ILGenerator   ilGen = dm.GetILGenerator();
                PythonContext pc    = context.LanguageContext;

                Type     callDelegateSiteType = CompilerHelpers.MakeCallSiteDelegateType(callSiteType);
                CallSite site = CallSite.Create(callDelegateSiteType, pc.Invoke(new CallSignature(_argtypes.Length)));

                List <object> constantPool = new List <object>();

                constantPool.Add(null); // 1st item is the target object, will be put in later.
                constantPool.Add(site);

                ilGen.BeginExceptionBlock();

                //CallSite<Func<CallSite, object, object>> mySite;
                //mySite.Target(mySite, target, ...);

                LocalBuilder siteLocal = ilGen.DeclareLocal(site.GetType());

                ilGen.Emit(OpCodes.Ldarg_0);
                ilGen.Emit(OpCodes.Ldc_I4, constantPool.Count - 1);
                ilGen.Emit(OpCodes.Ldelem_Ref);
                ilGen.Emit(OpCodes.Castclass, site.GetType());
                ilGen.Emit(OpCodes.Stloc, siteLocal);
                ilGen.Emit(OpCodes.Ldloc, siteLocal);
                ilGen.Emit(OpCodes.Ldfld, site.GetType().GetField("Target"));
                ilGen.Emit(OpCodes.Ldloc, siteLocal);

                // load code context
                int contextIndex = constantPool.Count;

                Debug.Assert(pc.SharedContext != null);
                constantPool.Add(pc.SharedContext);
                ilGen.Emit(OpCodes.Ldarg_0);
                ilGen.Emit(OpCodes.Ldc_I4, contextIndex);
                ilGen.Emit(OpCodes.Ldelem_Ref);

                // load function target, in constant pool slot 0
                ilGen.Emit(OpCodes.Ldarg_0);
                ilGen.Emit(OpCodes.Ldc_I4_0);
                ilGen.Emit(OpCodes.Ldelem_Ref);

                // load arguments
                for (int i = 0; i < _argtypes.Length; i++)
                {
                    INativeType nativeType = _argtypes[i];
                    nativeType.EmitReverseMarshalling(ilGen, new Arg(i + 1, sigTypes[i + 1]), constantPool, 0);
                }

                ilGen.Emit(OpCodes.Call, callDelegateSiteType.GetMethod("Invoke"));

                LocalBuilder finalRes = null;

                // emit forward marshaling for return value
                if (_restype != null)
                {
                    LocalBuilder tmpRes = ilGen.DeclareLocal(typeof(object));
                    ilGen.Emit(OpCodes.Stloc, tmpRes);
                    finalRes = ilGen.DeclareLocal(retType);

                    ((INativeType)_restype).EmitMarshalling(ilGen, new Local(tmpRes), constantPool, 0);
                    ilGen.Emit(OpCodes.Stloc, finalRes);
                }
                else
                {
                    ilGen.Emit(OpCodes.Pop);
                }

                // } catch(Exception e) {
                // emit the cleanup code

                ilGen.BeginCatchBlock(typeof(Exception));

                ilGen.Emit(OpCodes.Ldarg_0);
                ilGen.Emit(OpCodes.Ldc_I4, contextIndex);
                ilGen.Emit(OpCodes.Ldelem_Ref);
                ilGen.Emit(OpCodes.Call, typeof(ModuleOps).GetMethod("CallbackException"));

                ilGen.EndExceptionBlock();

                if (_restype != null)
                {
                    ilGen.Emit(OpCodes.Ldloc, finalRes);
                }
                ilGen.Emit(OpCodes.Ret);

                _reverseDelegateConstants = constantPool;
                _reverseDelegateType      = GetReverseDelegateType(ArrayUtils.RemoveFirst(sigTypes), CallingConvention);
                _reverseDelegate          = dm;
            }
예제 #15
0
        public static object CreateFuncCallSiteAndInvoke(CallSiteBinder Action, object Instance, object[] Arguments)
        {
            object obj2;

            Action = GetCachedBinder(Action);
            switch (Arguments.Length)
            {
            case 0:
            {
                CallSite <Func <CallSite, object, object> > site = CallSite <Func <CallSite, object, object> > .Create(Action);

                return(site.Target(site, Instance));
            }

            case 1:
            {
                CallSite <Func <CallSite, object, object, object> > site2 = CallSite <Func <CallSite, object, object, object> > .Create(Action);

                return(site2.Target(site2, Instance, Arguments[0]));
            }

            case 2:
            {
                CallSite <Func <CallSite, object, object, object, object> > site3 = CallSite <Func <CallSite, object, object, object, object> > .Create(Action);

                return(site3.Target(site3, Instance, Arguments[0], Arguments[1]));
            }

            case 3:
            {
                CallSite <Func <CallSite, object, object, object, object, object> > site4 = CallSite <Func <CallSite, object, object, object, object, object> > .Create(Action);

                return(site4.Target(site4, Instance, Arguments[0], Arguments[1], Arguments[2]));
            }

            case 4:
            {
                CallSite <Func <CallSite, object, object, object, object, object, object> > site5 = CallSite <Func <CallSite, object, object, object, object, object, object> > .Create(Action);

                return(site5.Target(site5, Instance, Arguments[0], Arguments[1], Arguments[2], Arguments[3]));
            }

            case 5:
            {
                CallSite <Func <CallSite, object, object, object, object, object, object, object> > site6 = CallSite <Func <CallSite, object, object, object, object, object, object, object> > .Create(Action);

                return(site6.Target(site6, Instance, Arguments[0], Arguments[1], Arguments[2], Arguments[3], Arguments[4]));
            }

            case 6:
            {
                CallSite <Func <CallSite, object, object, object, object, object, object, object, object> > site7 = CallSite <Func <CallSite, object, object, object, object, object, object, object, object> > .Create(Action);

                return(site7.Target(site7, Instance, Arguments[0], Arguments[1], Arguments[2], Arguments[3], Arguments[4], Arguments[5]));
            }

            case 7:
            {
                CallSite <Func <CallSite, object, object, object, object, object, object, object, object, object> > site8 = CallSite <Func <CallSite, object, object, object, object, object, object, object, object, object> > .Create(Action);

                return(site8.Target(site8, Instance, Arguments[0], Arguments[1], Arguments[2], Arguments[3], Arguments[4], Arguments[5], Arguments[6]));
            }
            }
            Type[] typeArgs = new Type[(Arguments.Length + 2) + 1];
            typeArgs[0] = typeof(CallSite);
            int num3 = typeArgs.Length - 1;

            for (int i = 1; i <= num3; i++)
            {
                typeArgs[i] = typeof(object);
            }
            CallSite site9 = CallSite.Create(Expression.GetDelegateType(typeArgs), Action);

            object[] array = new object[(Arguments.Length + 1) + 1];
            array[0] = site9;
            array[1] = Instance;
            Arguments.CopyTo(array, 2);
            Delegate delegate2 = (Delegate)site9.GetType().GetField("Target").GetValue(site9);

            try
            {
                obj2 = delegate2.DynamicInvoke(array);
            }
            catch (TargetInvocationException exception)
            {
                throw exception.InnerException;
            }
            return(obj2);
        }
예제 #16
0
        internal static Delegate CreateDelegateForDynamicObject(LanguageContext context, object dynamicObject, Type delegateType, MethodInfo invoke)
        {
            PerfTrack.NoteEvent(PerfTrack.Categories.DelegateCreate, delegateType.ToString());

            Type returnType = invoke.ReturnType;

            ParameterInfo[] parameterInfos = invoke.GetParameters();

            var parameters = new List <ParameterExpression>();

            for (int i = 0; i < parameterInfos.Length; i++)
            {
                parameters.Add(Expression.Parameter(parameterInfos[i].ParameterType, "p" + i));
            }

            InvokeBinder  invokeBinder  = context.CreateInvokeBinder(new CallInfo(parameterInfos.Length));
            ConvertBinder convertBinder = (returnType != typeof(void)) ? context.CreateConvertBinder(returnType, explicitCast: true) : null;

            CallSite invokeSite     = CallSite.Create(DynamicSiteHelpers.MakeCallSiteDelegate(MakeSiteSignature(parameterInfos)), invokeBinder);
            Type     invokeSiteType = invokeSite.GetType();

            Type     convertSiteType;
            CallSite convertSite;

            if (convertBinder != null)
            {
                convertSite     = CallSite.Create(DynamicSiteHelpers.MakeCallSiteDelegate(typeof(object), returnType), convertBinder);
                convertSiteType = convertSite.GetType();
            }
            else
            {
                convertSiteType = null;
                convertSite     = null;
            }

            var locals = new List <ParameterExpression>();

            ParameterExpression invokeSiteVar  = Expression.Parameter(invokeSiteType, "site");
            ParameterExpression convertSiteVar = null;

            var args = new List <Expression>();

            args.Add(invokeSiteVar);
            args.Add(Expression.Constant(dynamicObject));

            int strongBoxVarsStart = locals.Count;

            for (int i = 0; i < parameterInfos.Length; i++)
            {
                if (parameterInfos[i].ParameterType.IsByRef)
                {
                    var argType = parameterInfos[i].ParameterType;

                    Type elementType  = argType.GetElementType();
                    Type concreteType = typeof(StrongBox <>).MakeGenericType(elementType);

                    var strongBox = Expression.Parameter(concreteType, "box" + i);
                    locals.Add(strongBox);

                    args.Add(
                        Expression.Assign(
                            strongBox,
                            Expression.New(
                                concreteType.GetConstructor(new Type[] { elementType }),
                                parameters[i]
                                )
                            )
                        );
                }
                else
                {
                    args.Add(parameters[i]);
                }
            }

            int strongBoxVarsEnd = locals.Count;

            Expression invocation = Expression.Invoke(
                Expression.Field(
                    Expression.Assign(
                        invokeSiteVar,
                        Expression.Convert(Expression.Constant(invokeSite), invokeSiteType)
                        ),
                    invokeSiteType.GetDeclaredField("Target")
                    ),
                args
                );

            if (convertBinder != null)
            {
                convertSiteVar = Expression.Parameter(convertSiteType, "convertSite");

                invocation = Expression.Invoke(
                    Expression.Field(
                        Expression.Assign(
                            convertSiteVar,
                            Expression.Convert(Expression.Constant(convertSite), convertSiteType)
                            ),
                        convertSiteType.GetDeclaredField("Target")
                        ),
                    convertSiteVar,
                    invocation
                    );
            }

            locals.Add(invokeSiteVar);
            if (convertSiteVar != null)
            {
                locals.Add(convertSiteVar);
            }

            Expression body;

            // copy back from StrongBox.Value
            if (strongBoxVarsEnd > strongBoxVarsStart)
            {
                var block = new Expression[1 + strongBoxVarsEnd - strongBoxVarsStart + 1];

                var resultVar = Expression.Parameter(invocation.Type, "result");
                locals.Add(resultVar);

                int b = 0;
                int l = strongBoxVarsStart;

                // values of strong boxes are initialized in invocation expression:
                block[b++] = Expression.Assign(resultVar, invocation);

                for (int i = 0; i < parameterInfos.Length; i++)
                {
                    if (parameterInfos[i].ParameterType.IsByRef)
                    {
                        var local = locals[l++];
                        block[b++] = Expression.Assign(
                            parameters[i],
                            Expression.Field(local, local.Type.GetDeclaredField("Value"))
                            );
                    }
                }

                block[b++] = resultVar;

                Debug.Assert(l == strongBoxVarsEnd);
                Debug.Assert(b == block.Length);

                body = Expression.Block(locals, block);
            }
            else
            {
                body = Expression.Block(locals, invocation);
            }

            var lambda = Expression.Lambda(delegateType, body, "_Scripting_", parameters);

            return(lambda.Compile());
        }
예제 #17
0
        /// <summary>
        /// Generates stub to receive the CLR call and then call the dynamic language code.
        /// </summary>
        private void EmitClrCallStub(ILGen cg)
        {
            List <ReturnFixer> fixers = new List <ReturnFixer>(0);

            // Create strongly typed return type from the site.
            // This will, among other things, generate tighter code.
            Type[] siteTypes = MakeSiteSignature(_parameterTypes);

            CallSite callSite = CallSite.Create(DynamicSiteHelpers.MakeCallSiteDelegate(siteTypes), _invokeBinder);
            Type     siteType = callSite.GetType();

            Type     convertSiteType = null;
            CallSite convertSite     = null;

            if (_returnType != typeof(void))
            {
                convertSite     = CallSite.Create(DynamicSiteHelpers.MakeCallSiteDelegate(typeof(object), _returnType), _convertBinder);
                convertSiteType = convertSite.GetType();
            }

            LocalBuilder convertSiteLocal = null;
            FieldInfo    convertTarget    = null;

            if (_returnType != typeof(void))
            {
                // load up the conversion logic on the stack
                convertSiteLocal = cg.DeclareLocal(convertSiteType);
                EmitConstantGet(cg, ConvertSiteIndex, convertSiteType);

                cg.Emit(OpCodes.Dup);
                cg.Emit(OpCodes.Stloc, convertSiteLocal);

                convertTarget = convertSiteType.GetDeclaredField("Target");
                cg.EmitFieldGet(convertTarget);
                cg.Emit(OpCodes.Ldloc, convertSiteLocal);
            }

            // load up the invoke logic on the stack
            LocalBuilder site = cg.DeclareLocal(siteType);

            EmitConstantGet(cg, CallSiteIndex, siteType);
            cg.Emit(OpCodes.Dup);
            cg.Emit(OpCodes.Stloc, site);

            FieldInfo target = siteType.GetDeclaredField("Target");

            cg.EmitFieldGet(target);
            cg.Emit(OpCodes.Ldloc, site);

            EmitConstantGet(cg, TargetIndex, typeof(object));

            for (int i = 0; i < _parameterTypes.Length; i++)
            {
                if (_parameterTypes[i].IsByRef)
                {
                    ReturnFixer rf = ReturnFixer.EmitArgument(cg, i + 1, _parameterTypes[i]);
                    if (rf != null)
                    {
                        fixers.Add(rf);
                    }
                }
                else
                {
                    cg.EmitLoadArg(i + 1);
                }
            }

            // emit the invoke for the call
            cg.EmitCall(target.FieldType, "Invoke");

            // emit the invoke for the convert
            if (_returnType == typeof(void))
            {
                cg.Emit(OpCodes.Pop);
            }
            else
            {
                cg.EmitCall(convertTarget.FieldType, "Invoke");
            }

            // fixup any references
            foreach (ReturnFixer rf in fixers)
            {
                rf.FixReturn(cg);
            }

            cg.Emit(OpCodes.Ret);
        }