Team Ai
Datasetpublic

MegaBites-AI/Windows-powershell

sourceHugging Facemitupdated 6mo agoView on Hugging Face
0likes372downloads
LightLambda.cs304 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#else19using Microsoft.Scripting.Ast;20#endif21using System.Reflection;22using System.Reflection.Emit;23using System.Runtime.CompilerServices;24using System.Security;25using System.Threading;26 27//using Microsoft.Scripting.Generation;28 29using AstUtils = System.Management.Automation.Interpreter.Utils;30 31namespace System.Management.Automation.Interpreter32{33    internal sealed class LightLambdaCompileEventArgs : EventArgs34    {35        public Delegate Compiled { get; }36 37        internal LightLambdaCompileEventArgs(Delegate compiled)38        {39            Compiled = compiled;40        }41    }42 43    internal partial class LightLambda44    {45        private readonly StrongBox<object>[] _closure;46        private readonly Interpreter _interpreter;47        private static readonly CacheDict<Type, Func<LightLambda, Delegate>> s_runCache = new CacheDict<Type, Func<LightLambda, Delegate>>(100);48 49        // Adaptive compilation support50        private readonly LightDelegateCreator _delegateCreator;51        private Delegate _compiled;52        private int _compilationThreshold;53 54        /// <summary>55        /// Provides notification that the LightLambda has been compiled.56        /// </summary>57        public event EventHandler<LightLambdaCompileEventArgs> Compile;58 59        internal LightLambda(LightDelegateCreator delegateCreator, StrongBox<object>[] closure, int compilationThreshold)60        {61            _delegateCreator = delegateCreator;62            _closure = closure;63            _interpreter = delegateCreator.Interpreter;64            _compilationThreshold = compilationThreshold;65        }66 67        private static Func<LightLambda, Delegate> GetRunDelegateCtor(Type delegateType)68        {69            lock (s_runCache)70            {71                Func<LightLambda, Delegate> fastCtor;72                if (s_runCache.TryGetValue(delegateType, out fastCtor))73                {74                    return fastCtor;75                }76 77                return MakeRunDelegateCtor(delegateType);78            }79        }80 81        private static Func<LightLambda, Delegate> MakeRunDelegateCtor(Type delegateType)82        {83            var method = delegateType.GetMethod("Invoke");84            var paramInfos = method.GetParameters();85            Type[] paramTypes;86            string name = "Run";87 88            if (paramInfos.Length >= MaxParameters)89            {90                return null;91            }92 93            if (method.ReturnType == typeof(void))94            {95                name += "Void";96                paramTypes = new Type[paramInfos.Length];97            }98            else99            {100                paramTypes = new Type[paramInfos.Length + 1];101                paramTypes[paramTypes.Length - 1] = method.ReturnType;102            }103 104            MethodInfo runMethod;105 106            if (method.ReturnType == typeof(void) && paramTypes.Length == 2 &&107                paramInfos[0].ParameterType.IsByRef && paramInfos[1].ParameterType.IsByRef)108            {109                runMethod = typeof(LightLambda).GetMethod("RunVoidRef2", BindingFlags.NonPublic | BindingFlags.Instance);110                paramTypes[0] = paramInfos[0].ParameterType.GetElementType();111                paramTypes[1] = paramInfos[1].ParameterType.GetElementType();112            }113            else if (method.ReturnType == typeof(void) && paramTypes.Length == 0)114            {115                runMethod = typeof(LightLambda).GetMethod("RunVoid0", BindingFlags.NonPublic | BindingFlags.Instance);116            }117            else118            {119                for (int i = 0; i < paramInfos.Length; i++)120                {121                    paramTypes[i] = paramInfos[i].ParameterType;122                    if (paramTypes[i].IsByRef)123                    {124                        return null;125                    }126                }127 128                if (DelegateHelpers.MakeDelegate(paramTypes) == delegateType)129                {130                    name = "Make" + name + paramInfos.Length;131 132                    MethodInfo ctorMethod = typeof(LightLambda).GetMethod(name, BindingFlags.NonPublic | BindingFlags.Static).MakeGenericMethod(paramTypes);133                    return s_runCache[delegateType] = (Func<LightLambda, Delegate>)ctorMethod.CreateDelegate(typeof(Func<LightLambda, Delegate>));134                }135 136                runMethod = typeof(LightLambda).GetMethod(name + paramInfos.Length, BindingFlags.NonPublic | BindingFlags.Instance);137            }138 139#if !SILVERLIGHT140            try141            {142                DynamicMethod dm = new DynamicMethod("FastCtor", typeof(Delegate), new[] { typeof(LightLambda) }, typeof(LightLambda), true);143                var ilgen = dm.GetILGenerator();144                ilgen.Emit(OpCodes.Ldarg_0);145                ilgen.Emit(OpCodes.Ldftn, runMethod.IsGenericMethodDefinition ? runMethod.MakeGenericMethod(paramTypes) : runMethod);146                ilgen.Emit(OpCodes.Newobj, delegateType.GetConstructor(new[] { typeof(object), typeof(IntPtr) }));147                ilgen.Emit(OpCodes.Ret);148                return s_runCache[delegateType] = (Func<LightLambda, Delegate>)dm.CreateDelegate(typeof(Func<LightLambda, Delegate>));149            }150            catch (SecurityException)151            {152            }153#endif154 155            // we don't have permission for restricted skip visibility dynamic methods, use the slower Delegate.CreateDelegate.156            var targetMethod = runMethod.IsGenericMethodDefinition ? runMethod.MakeGenericMethod(paramTypes) : runMethod;157            return s_runCache[delegateType] = lambda => targetMethod.CreateDelegate(delegateType, lambda);158        }159 160        // TODO enable sharing of these custom delegates161        private Delegate CreateCustomDelegate(Type delegateType)162        {163            // PerfTrack.NoteEvent(PerfTrack.Categories.Compiler, "Synchronously compiling a custom delegate");164 165            var method = delegateType.GetMethod("Invoke");166            var paramInfos = method.GetParameters();167            var parameters = new ParameterExpression[paramInfos.Length];168            var parametersAsObject = new Expression[paramInfos.Length];169            for (int i = 0; i < paramInfos.Length; i++)170            {171                ParameterExpression parameter = Expression.Parameter(paramInfos[i].ParameterType, paramInfos[i].Name);172                parameters[i] = parameter;173                parametersAsObject[i] = Expression.Convert(parameter, typeof(object));174            }175 176            var data = Expression.NewArrayInit(typeof(object), parametersAsObject);177            var self = AstUtils.Constant(this);178            var runMethod = typeof(LightLambda).GetMethod("Run");179            var body = Expression.Convert(Expression.Call(self, runMethod, data), method.ReturnType);180            var lambda = Expression.Lambda(delegateType, body, parameters);181            return lambda.Compile();182        }183 184        internal Delegate MakeDelegate(Type delegateType)185        {186            Func<LightLambda, Delegate> fastCtor = GetRunDelegateCtor(delegateType);187            if (fastCtor != null)188            {189                return fastCtor(this);190            }191            else192            {193                return CreateCustomDelegate(delegateType);194            }195        }196 197        private bool TryGetCompiled()198        {199            // Use the compiled delegate if available.200            if (_delegateCreator.HasCompiled)201            {202                _compiled = _delegateCreator.CreateCompiledDelegate(_closure);203 204                // Send it to anyone who's interested.205                var compileEvent = Compile;206                if (compileEvent != null && _delegateCreator.SameDelegateType)207                {208                    compileEvent(this, new LightLambdaCompileEventArgs(_compiled));209                }210 211                return true;212            }213 214            // Don't lock here, it's a frequently hit path.215            //216            // There could be multiple threads racing, but that is okay.217            // Two bad things can happen:218            //   * We miss decrements (some thread sets the counter forward)219            //   * We might enter the "if" branch more than once.220            //221            // The first is okay, it just means we take longer to compile.222            // The second we explicitly guard against inside of Compile().223            //224            // We can't miss 0. The first thread that writes -1 must have read 0 and hence start compilation.225            if (unchecked(_compilationThreshold--) == 0)226            {227#if SILVERLIGHT228                if (PlatformAdaptationLayer.IsCompactFramework) {229                    _compilationThreshold = Int32.MaxValue;230                    return false;231                }232#endif233                if (_interpreter.CompileSynchronously)234                {235                    _delegateCreator.Compile(null);236                    return TryGetCompiled();237                }238                else239                {240                    // Kick off the compile on another thread so this one can keep going241                    ThreadPool.QueueUserWorkItem(_delegateCreator.Compile, null);242                }243            }244 245            return false;246        }247 248        private InterpretedFrame MakeFrame()249        {250            return new InterpretedFrame(_interpreter, _closure);251        }252 253        internal void RunVoidRef2<T0, T1>(ref T0 arg0, ref T1 arg1)254        {255            // if (_compiled != null || TryGetCompiled()) {256            //    ((ActionRef<T0, T1>)_compiled)(ref arg0, ref arg1);257            //    return;258            // }259 260            // copy in and copy out for today...261            var frame = MakeFrame();262            frame.Data[0] = arg0;263            frame.Data[1] = arg1;264            var currentFrame = frame.Enter();265            try266            {267                _interpreter.Run(frame);268            }269            finally270            {271                frame.Leave(currentFrame);272                arg0 = (T0)frame.Data[0];273                arg1 = (T1)frame.Data[1];274            }275        }276 277        public object Run(params object[] arguments)278        {279            if (_compiled != null || TryGetCompiled())280            {281                return _compiled.DynamicInvoke(arguments);282            }283 284            var frame = MakeFrame();285            for (int i = 0; i < arguments.Length; i++)286            {287                frame.Data[i] = arguments[i];288            }289 290            var currentFrame = frame.Enter();291            try292            {293                _interpreter.Run(frame);294            }295            finally296            {297                frame.Leave(currentFrame);298            }299 300            return frame.Pop();301        }302    }303}304