Пример #1
0
        protected override Expression VisitDynamic(DynamicExpression node)
        {
            Type siteType = typeof(CallSite <>).MakeGenericType(node.DelegateType);

            // Rewite call site as constant
            var siteExpr = VisitConstant(Expression.Constant(DynamicSiteHelpers.MakeSite(node.Binder, siteType)));

            // Rewrite all of the arguments
            var args = Visit(node.Arguments);

            var siteVar = Expression.Variable(siteExpr.Type, "$site");

            // ($site = siteExpr).Target.Invoke($site, *args)
            return(Expression.Block(
                       new [] { siteVar },
                       Expression.Call(
                           Expression.Field(
                               Expression.Assign(siteVar, siteExpr),
                               siteType.GetField("Target")
                               ),
                           node.DelegateType.GetMethod("Invoke"),
                           ArrayUtils.Insert(siteVar, args)
                           )
                       ));
        }
Пример #2
0
        public Delegate CreateDelegate(Type delegateType, object dynamicObject)
        {
            Assert.NotNull(delegateType, dynamicObject);

            object[] closure;
            lock (_closureMap) {
                if (!_closureMap.TryGetValue(dynamicObject, out WeakReference weakClosure) || (closure = (object[])weakClosure.Target) == null)
                {
                    closure = new[] { TargetPlaceHolder, CallSitePlaceHolder, ConvertSitePlaceHolder };
                    _closureMap[dynamicObject] = new WeakReference(closure);

                    Type[] siteTypes = MakeSiteSignature(_parameterTypes);

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

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

                    closure[TargetIndex]      = dynamicObject;
                    closure[CallSiteIndex]    = callSite;
                    closure[ConvertSiteIndex] = convertSite;
                }
            }

            return(_method.CreateDelegate(delegateType, closure));
        }
Пример #3
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));
        }
Пример #4
0
        private static IEnumerable <DynamicStackFrame> GetStackFrames(StackTrace trace, List <DynamicStackFrame> dynamicFrames, bool reverseOrder)
        {
            StackFrame[] frames = trace.GetFrames();
            if (frames == null)
            {
                yield break;
            }

            foreach (StackFrame frame in WalkList(frames, reverseOrder))
            {
                MethodBase method     = frame.GetMethod();
                Type       parentType = method.DeclaringType;

                if (dynamicFrames.Count > 0 && frame.GetMethod() == dynamicFrames[dynamicFrames.Count - 1].GetMethod())
                {
                    yield return(dynamicFrames[dynamicFrames.Count - 1]);

                    dynamicFrames.RemoveAt(dynamicFrames.Count - 1);
                    continue;
                }

                if (parentType != null)
                {
                    if (parentType == typeof(LambdaExpression) && method.Name == "DoExecute")
                    {
                        // Evaluated frame -- Replace with dynamic frame
                        Debug.Assert(dynamicFrames.Count > 0);
                        //if (dynamicFrames.Count == 0) continue;
                        yield return(dynamicFrames[dynamicFrames.Count - 1]);

                        dynamicFrames.RemoveAt(dynamicFrames.Count - 1);
                        continue;
                    }
                }

                if (DynamicSiteHelpers.IsInvisibleDlrStackFrame(method))
                {
                    continue;
                }

                if (method.DeclaringType != null && Snippets.Shared.IsSnippetsAssembly(method.DeclaringType.Assembly))
                {
                    yield return(GetStackFrame(frame));
                }
            }
        }
Пример #5
0
        private static MSA.LambdaExpression /*!*/ CreateLambda(string /*!*/ name, MSA.ParameterExpression /*!*/[] /*!*/ parameters, MSA.Expression /*!*/ body)
        {
            Type lambdaType = DynamicSiteHelpers.GetStandardDelegateType(AstFactory.GetSignature(parameters, typeof(object)));

            if (lambdaType == null)
            {
                // to many parameters for Func<> delegate -> use object[]:
                MSA.ParameterExpression array = Ast.Parameter(typeof(object[]), "#params");
                var actualParameters          = new MSA.ParameterExpression[] { parameters[0], parameters[1], array };
                parameters = ArrayUtils.ShiftLeft(parameters, 2);

                var bodyWithParamInit = new MSA.Expression[parameters.Length + 1];
                for (int i = 0; i < parameters.Length; i++)
                {
                    bodyWithParamInit[i] = Ast.Assign(parameters[i], Ast.ArrayIndex(array, Ast.Constant(i)));
                }
                bodyWithParamInit[parameters.Length] = body;

                return(Ast.Lambda(
                           RubyMethodInfo.ParamsArrayDelegateType,
                           Ast.Block(
                               new ReadOnlyCollection <MSA.ParameterExpression>(parameters),
                               new ReadOnlyCollection <MSA.Expression>(bodyWithParamInit)
                               ),
                           name,
                           new ReadOnlyCollection <MSA.ParameterExpression>(actualParameters)
                           ));
            }
            else
            {
                return(Ast.Lambda(
                           lambdaType,
                           body,
                           name,
                           new ReadOnlyCollection <MSA.ParameterExpression>(parameters)
                           ));
            }
        }
Пример #6
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());
        }
Пример #7
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);
        }
Пример #8
0
        /// <summary>
        /// Generates stub to receive the CLR call and then call the dynamic language code.
        /// </summary>
        public static void  EmitClrCallStub(CodeGen cg, Slot callTarget, int firstArg, CallType functionAttributes)
        {
            List <ReturnFixer> fixers = new List <ReturnFixer>(0);
            IList <Slot>       args   = cg.ArgumentSlots;
            int nargs = args.Count - firstArg;

            CallAction action;

            if ((functionAttributes & CallType.ArgumentList) != 0)
            {
                ArgumentInfo[] infos = CompilerHelpers.MakeRepeatedArray(ArgumentInfo.Simple, nargs);
                infos[nargs - 1] = new ArgumentInfo(ArgumentKind.List);

                action = CallAction.Make(new CallSignature(infos));
            }
            else
            {
                action = CallAction.Make(nargs);
            }

            bool fast;
            Slot site = cg.CreateDynamicSite(action,
                                             CompilerHelpers.MakeRepeatedArray(typeof(object), nargs + 2),
                                             out fast);

            site.EmitGet(cg);
            if (!fast)
            {
                cg.EmitCodeContext();
            }

            if (DynamicSiteHelpers.IsBigTarget(site.Type))
            {
                cg.EmitTuple(site.Type.GetGenericArguments()[0], args.Count + 1, delegate(int index) {
                    if (index == 0)
                    {
                        callTarget.EmitGet(cg);
                    }
                    else
                    {
                        ReturnFixer rf = ReturnFixer.EmitArgument(cg, args[index - 1]);
                        if (rf != null)
                        {
                            fixers.Add(rf);
                        }
                    }
                });
            }
            else
            {
                callTarget.EmitGet(cg);

                for (int i = firstArg; i < args.Count; i++)
                {
                    ReturnFixer rf = ReturnFixer.EmitArgument(cg, args[i]);
                    if (rf != null)
                    {
                        fixers.Add(rf);
                    }
                }
            }

            cg.EmitCall(site.Type, "Invoke");

            foreach (ReturnFixer rf in fixers)
            {
                rf.FixReturn(cg);
            }
            cg.EmitReturnFromObject();
        }
Пример #9
0
        /// <summary>
        /// Generates stub to receive the CLR call and then call the dynamic language code.
        /// </summary>
        private object[] EmitClrCallStub(ILGen cg)
        {
            List <ReturnFixer> fixers = new List <ReturnFixer>(0);

            ArgumentInfo[] args = new ArgumentInfo[_parameters.Length];
            for (int i = 0; i < args.Length; i++)
            {
                args[i] = Expression.PositionalArg(i);
            }
            ConvertBinder convert = _context.CreateConvertBinder(_returnType, true);
            InvokeBinder  action  = _context.CreateInvokeBinder(args);


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

            Type     siteType = DynamicSiteHelpers.MakeCallSiteType(siteTypes);
            CallSite callSite = DynamicSiteHelpers.MakeSite(action, siteType);

            Type     convertSiteType = null;
            CallSite convertSite     = null;

            if (_returnType != typeof(void))
            {
                convertSiteType = DynamicSiteHelpers.MakeCallSiteType(typeof(object), _returnType);
                convertSite     = DynamicSiteHelpers.MakeSite(convert, convertSiteType);
            }

            // build up constants array
            object[]  constants = new object[] { TargetPlaceHolder, callSite, convertSite };
            const int TargetIndex = 0, CallSiteIndex = 1, ConvertSiteIndex = 2;

            LocalBuilder convertSiteLocal = null;
            FieldInfo    convertTarget    = null;

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

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

                convertTarget = convertSiteType.GetField("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.GetField("Target");

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

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

            for (int i = 0; i < _parameters.Length; i++)
            {
                if (_parameters[i].ParameterType.IsByRef)
                {
                    ReturnFixer rf = ReturnFixer.EmitArgument(cg, i + 1, _parameters[i].ParameterType);
                    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);
            return(constants);
        }