Team Ai
Datasetpublic

MegaBites-AI/Windows-powershell

sourceHugging Facemitupdated 6mo agoView on Hugging Face
0likes372downloads
LightDelegateCreator.cs221 linesDownload Raw Back to interpreter
1/* ****************************************************************************2 *3 * Copyright (c) Microsoft Corporation.4 *5 * This source code is subject to terms and conditions of the Apache License, Version 2.0. A6 * copy of the license can be found in the License.html file at the root of this distribution. If7 * you cannot locate the Apache License, Version 2.0, please send an email to8 * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound9 * by the terms of the Apache License, Version 2.0.10 *11 * You must not remove this notice, or any other, from this software.12 *13 *14 * ***************************************************************************/15 16#if !CLR217using System.Linq.Expressions;18#endif19using System.Diagnostics;20using System.Runtime.CompilerServices;21 22//using Microsoft.Scripting.Generation;23 24namespace System.Management.Automation.Interpreter25{26    /// <summary>27    /// Manages creation of interpreted delegates. These delegates will get28    /// compiled if they are executed often enough.29    /// </summary>30    internal sealed class LightDelegateCreator31    {32        // null if we are forced to compile33        private readonly Interpreter _interpreter;34        private readonly Expression _lambda;35 36        // Adaptive compilation support:37        private Type _compiledDelegateType;38        private Delegate _compiled;39        private readonly object _compileLock = new object();40 41        internal LightDelegateCreator(Interpreter interpreter, LambdaExpression lambda)42        {43            Assert.NotNull(lambda);44            _interpreter = interpreter;45            _lambda = lambda;46        }47 48        // internal LightDelegateCreator(Interpreter interpreter, LightLambdaExpression lambda) {49        //    Assert.NotNull(lambda);50        //    _interpreter = interpreter;51        //    _lambda = lambda;52        // }53 54        internal Interpreter Interpreter55        {56            get { return _interpreter; }57        }58 59        private bool HasClosure60        {61            get { return _interpreter != null && _interpreter.ClosureSize > 0; }62        }63 64        internal bool HasCompiled65        {66            get { return _compiled != null; }67        }68 69        /// <summary>70        /// True if the compiled delegate has the same type as the lambda;71        /// false if the type was changed for interpretation.72        /// </summary>73        internal bool SameDelegateType74        {75            get { return _compiledDelegateType == DelegateType; }76        }77 78        public Delegate CreateDelegate()79        {80            return CreateDelegate(null);81        }82 83        internal Delegate CreateDelegate(StrongBox<object>[] closure)84        {85            if (_compiled != null)86            {87                // If the delegate type we want is not a Func/Action, we can't88                // use the compiled code directly. So instead just fall through89                // and create an interpreted LightLambda, which will pick up90                // the compiled delegate on its first run.91                //92                // Ideally, we would just rebind the compiled delegate using93                // Delegate.CreateDelegate. Unfortunately, it doesn't work on94                // dynamic methods.95                if (SameDelegateType)96                {97                    return CreateCompiledDelegate(closure);98                }99            }100 101            if (_interpreter == null)102            {103                // We can't interpret, so force a compile104                Compile(null);105                Delegate compiled = CreateCompiledDelegate(closure);106                Debug.Assert(compiled.GetType() == DelegateType);107                return compiled;108            }109 110            // Otherwise, we'll create an interpreted LightLambda111            return new LightLambda(this, closure, _interpreter._compilationThreshold).MakeDelegate(DelegateType);112        }113 114        private Type DelegateType115        {116            get117            {118                LambdaExpression le = _lambda as LambdaExpression;119                if (le != null)120                {121                    return le.Type;122                }123 124                return null;125                // return ((LightLambdaExpression)_lambda).Type;126            }127        }128 129        /// <summary>130        /// Used by LightLambda to get the compiled delegate.131        /// </summary>132        internal Delegate CreateCompiledDelegate(StrongBox<object>[] closure)133        {134            Debug.Assert(HasClosure == (closure != null));135 136            if (HasClosure)137            {138                // We need to apply the closure to get the actual delegate.139                var applyClosure = (Func<StrongBox<object>[], Delegate>)_compiled;140                return applyClosure(closure);141            }142 143            return _compiled;144        }145 146        /// <summary>147        /// Create a compiled delegate for the LightLambda, and saves it so148        /// future calls to Run will execute the compiled code instead of149        /// interpreting.150        /// </summary>151        internal void Compile(object state)152        {153            if (_compiled != null)154            {155                return;156            }157 158            // Compilation is expensive, we only want to do it once.159            lock (_compileLock)160            {161                if (_compiled != null)162                {163                    return;164                }165 166                // PerfTrack.NoteEvent(PerfTrack.Categories.Compiler, "Interpreted lambda compiled");167 168                // Interpreter needs a standard delegate type.169                // So change the lambda's delegate type to Func<...> or170                // Action<...> so it can be called from the LightLambda.Run171                // methods.172                LambdaExpression lambda = (_lambda as LambdaExpression); // ?? (LambdaExpression)((LightLambdaExpression)_lambda).Reduce();173                if (_interpreter != null)174                {175                    _compiledDelegateType = GetFuncOrAction(lambda);176                    lambda = Expression.Lambda(_compiledDelegateType, lambda.Body, lambda.Name, lambda.Parameters);177                }178 179                if (HasClosure)180                {181                    _compiled = LightLambdaClosureVisitor.BindLambda(lambda, _interpreter.ClosureVariables);182                }183                else184                {185                    _compiled = lambda.Compile();186                }187            }188        }189 190        private static Type GetFuncOrAction(LambdaExpression lambda)191        {192            Type delegateType;193            bool isVoid = lambda.ReturnType == typeof(void);194 195            // if (isVoid && lambda.Parameters.Count == 2 &&196            //    lambda.Parameters[0].IsByRef && lambda.Parameters[1].IsByRef) {197            //    return typeof(ActionRef<,>).MakeGenericType(lambda.Parameters.Map(p => p.Type));198            // } else {199            Type[] types = lambda.Parameters.Map(static p => p.IsByRef ? p.Type.MakeByRefType() : p.Type);200            if (isVoid)201            {202                if (Expression.TryGetActionType(types, out delegateType))203                {204                    return delegateType;205                }206            }207            else208            {209                types = types.AddLast(lambda.ReturnType);210                if (Expression.TryGetFuncType(types, out delegateType))211                {212                    return delegateType;213                }214            }215 216            return lambda.Type;217            // }218        }219    }220}221