Team Ai
Datasetpublic

MegaBites-AI/Windows-powershell

sourceHugging Facemitupdated 6mo agoView on Hugging Face
0likes372downloads
InstructionList.cs1222 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// Enables instruction counting and displaying stats at process exit.16// #define STATS17 18using System.Collections.Generic;19using System.Diagnostics;20using System.Reflection;21using System.Runtime.CompilerServices;22 23namespace System.Management.Automation.Interpreter24{25    [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1815:OverrideEqualsAndOperatorEqualsOnValueTypes")]26    [DebuggerTypeProxy(typeof(InstructionArray.DebugView))]27    internal readonly struct InstructionArray28    {29        internal readonly int MaxStackDepth;30        internal readonly int MaxContinuationDepth;31        internal readonly Instruction[] Instructions;32        internal readonly object[] Objects;33        internal readonly RuntimeLabel[] Labels;34 35        // list of (instruction index, cookie) sorted by instruction index:36        internal readonly List<KeyValuePair<int, object>> DebugCookies;37 38        internal InstructionArray(int maxStackDepth, int maxContinuationDepth, Instruction[] instructions,39            object[] objects, RuntimeLabel[] labels, List<KeyValuePair<int, object>> debugCookies)40        {41            MaxStackDepth = maxStackDepth;42            MaxContinuationDepth = maxContinuationDepth;43            Instructions = instructions;44            DebugCookies = debugCookies;45            Objects = objects;46            Labels = labels;47        }48 49        internal int Length50        {51            get { return Instructions.Length; }52        }53 54        #region Debug View55 56        internal sealed class DebugView57        {58            private readonly InstructionArray _array;59 60            public DebugView(InstructionArray array)61            {62                _array = array;63            }64 65            [DebuggerBrowsable(DebuggerBrowsableState.RootHidden)]66            public InstructionList.DebugView.InstructionView[] A067            {68                get69                {70                    return InstructionList.DebugView.GetInstructionViews(71                        _array.Instructions,72                        _array.Objects,73                        (index) => _array.Labels[index].Index,74                        _array.DebugCookies75                    );76                }77            }78        }79 80        #endregion81    }82 83    [DebuggerTypeProxy(typeof(InstructionList.DebugView))]84    [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Maintainability", "CA1506:AvoidExcessiveClassCoupling")]85    internal sealed class InstructionList86    {87        private readonly List<Instruction> _instructions = new List<Instruction>();88        private List<object> _objects;89 90        private int _currentStackDepth;91        private int _maxStackDepth;92        private int _currentContinuationsDepth;93        private int _maxContinuationDepth;94        private int _runtimeLabelCount;95        private List<BranchLabel> _labels;96 97        // list of (instruction index, cookie) sorted by instruction index:98#pragma warning disable IDE0044 // Add readonly modifier99        private List<KeyValuePair<int, object>> _debugCookies = null;100#pragma warning restore IDE0044 // Variable is assigned when DEBUG is defined.101 102        #region Debug View103 104        internal sealed class DebugView105        {106            private readonly InstructionList _list;107 108            public DebugView(InstructionList list)109            {110                _list = list;111            }112 113            [DebuggerBrowsable(DebuggerBrowsableState.RootHidden)]114            public InstructionView[] A0115            {116                get117                {118                    return GetInstructionViews(119                        _list._instructions,120                        _list._objects,121                        (index) => _list._labels[index].TargetIndex,122                        _list._debugCookies123                    );124                }125            }126 127            internal static InstructionView[] GetInstructionViews(IList<Instruction> instructions, IList<object> objects,128                Func<int, int> labelIndexer, IList<KeyValuePair<int, object>> debugCookies)129            {130                var result = new List<InstructionView>();131                int index = 0;132                int stackDepth = 0;133                int continuationsDepth = 0;134 135                var cookieEnumerator = (debugCookies ?? Array.Empty<KeyValuePair<int, object>>()).GetEnumerator();136                var hasCookie = cookieEnumerator.MoveNext();137 138                for (int i = 0; i < instructions.Count; i++)139                {140                    object cookie = null;141                    while (hasCookie && cookieEnumerator.Current.Key == i)142                    {143                        cookie = cookieEnumerator.Current.Value;144                        hasCookie = cookieEnumerator.MoveNext();145                    }146 147                    int stackDiff = instructions[i].StackBalance;148                    int contDiff = instructions[i].ContinuationsBalance;149                    string name = instructions[i].ToDebugString(i, cookie, labelIndexer, objects);150                    result.Add(new InstructionView(instructions[i], name, i, stackDepth, continuationsDepth));151 152                    index++;153                    stackDepth += stackDiff;154                    continuationsDepth += contDiff;155                }156 157                return result.ToArray();158            }159 160            [DebuggerDisplay("{GetValue(),nq}", Name = "{GetName(),nq}", Type = "{GetDisplayType(), nq}")]161            internal readonly struct InstructionView162            {163                private readonly int _index;164                private readonly int _stackDepth;165                private readonly int _continuationsDepth;166                private readonly string _name;167                private readonly Instruction _instruction;168 169                internal string GetName()170                {171                    return _index +172                        (_continuationsDepth == 0 ? string.Empty : " C(" + _continuationsDepth + ")") +173                        (_stackDepth == 0 ? string.Empty : " S(" + _stackDepth + ")");174                }175 176                internal string GetValue()177                {178                    return _name;179                }180 181                internal string GetDisplayType()182                {183                    return _instruction.ContinuationsBalance + "/" + _instruction.StackBalance;184                }185 186                public InstructionView(Instruction instruction, string name, int index, int stackDepth, int continuationsDepth)187                {188                    _instruction = instruction;189                    _name = name;190                    _index = index;191                    _stackDepth = stackDepth;192                    _continuationsDepth = continuationsDepth;193                }194            }195        }196 197        #endregion198 199        #region Core Emit Ops200 201        public void Emit(Instruction instruction)202        {203            _instructions.Add(instruction);204            UpdateStackDepth(instruction);205        }206 207        private void UpdateStackDepth(Instruction instruction)208        {209            Debug.Assert(instruction.ConsumedStack >= 0 && instruction.ProducedStack >= 0 &&210                instruction.ConsumedContinuations >= 0 && instruction.ProducedContinuations >= 0);211 212            _currentStackDepth -= instruction.ConsumedStack;213            Debug.Assert(_currentStackDepth >= 0);214            _currentStackDepth += instruction.ProducedStack;215            if (_currentStackDepth > _maxStackDepth)216            {217                _maxStackDepth = _currentStackDepth;218            }219 220            _currentContinuationsDepth -= instruction.ConsumedContinuations;221            Debug.Assert(_currentContinuationsDepth >= 0);222            _currentContinuationsDepth += instruction.ProducedContinuations;223            if (_currentContinuationsDepth > _maxContinuationDepth)224            {225                _maxContinuationDepth = _currentContinuationsDepth;226            }227        }228 229        /// <summary>230        /// Attaches a cookie to the last emitted instruction.231        /// </summary>232        [Conditional("DEBUG")]233        public void SetDebugCookie(object cookie)234        {235#if DEBUG236            _debugCookies ??= new List<KeyValuePair<int, object>>();237 238            Debug.Assert(Count > 0);239            _debugCookies.Add(new KeyValuePair<int, object>(Count - 1, cookie));240#endif241        }242 243        public int Count244        {245            get { return _instructions.Count; }246        }247 248        public int CurrentStackDepth249        {250            get { return _currentStackDepth; }251        }252 253        public int CurrentContinuationsDepth254        {255            get { return _currentContinuationsDepth; }256        }257 258        public int MaxStackDepth259        {260            get { return _maxStackDepth; }261        }262 263        internal Instruction GetInstruction(int index)264        {265            return _instructions[index];266        }267 268#if STATS269        private static Dictionary<string, int> _executedInstructions = new Dictionary<string, int>();270        private static Dictionary<string, Dictionary<object, bool>> _instances = new Dictionary<string, Dictionary<object, bool>>();271 272        static InstructionList() {273            AppDomain.CurrentDomain.ProcessExit += new EventHandler((_, __) => {274                PerfTrack.DumpHistogram(_executedInstructions);275                Console.WriteLine("-- Total executed: {0}", _executedInstructions.Values.Aggregate(0, static (sum, value) => sum + value));276                Console.WriteLine("-----");277 278                var referenced = new Dictionary<string, int>();279                int total = 0;280                foreach (var entry in _instances) {281                    referenced[entry.Key] = entry.Value.Count;282                    total += entry.Value.Count;283                }284 285                PerfTrack.DumpHistogram(referenced);286                Console.WriteLine("-- Total referenced: {0}", total);287                Console.WriteLine("-----");288            });289        }290#endif291        public InstructionArray ToArray()292        {293#if STATS294            lock (_executedInstructions) {295                _instructions.ForEach((instr) => {296                    int value = 0;297                    var name = instr.GetType().Name;298                    _executedInstructions.TryGetValue(name, out value);299                    _executedInstructions[name] = value + 1;300 301                    Dictionary<object, bool> dict;302                    if (!_instances.TryGetValue(name, out dict)) {303                        _instances[name] = dict = new Dictionary<object, bool>();304                    }305 306                    dict[instr] = true;307                });308            }309#endif310            return new InstructionArray(311                _maxStackDepth,312                _maxContinuationDepth,313                _instructions.ToArray(),314                _objects?.ToArray(),315                BuildRuntimeLabels(),316                _debugCookies317            );318        }319 320        #endregion321 322        #region Stack Operations323 324        private const int PushIntMinCachedValue = -100;325        private const int PushIntMaxCachedValue = 100;326        private const int CachedObjectCount = 256;327 328        private static Instruction s_null;329        private static Instruction s_true;330        private static Instruction s_false;331        private static Instruction[] s_ints;332        private static Instruction[] s_loadObjectCached;333 334        public void EmitLoad(object value)335        {336            EmitLoad(value, null);337        }338 339        public void EmitLoad(bool value)340        {341            if ((bool)value)342            {343                Emit(s_true ??= new LoadObjectInstruction(value));344            }345            else346            {347                Emit(s_false ??= new LoadObjectInstruction(value));348            }349        }350 351        public void EmitLoad(object value, Type type)352        {353            if (value == null)354            {355                Emit(s_null ??= new LoadObjectInstruction(null));356                return;357            }358 359            if (type == null || type.IsValueType)360            {361                if (value is bool)362                {363                    EmitLoad((bool)value);364                    return;365                }366 367                if (value is int)368                {369                    int i = (int)value;370                    if (i >= PushIntMinCachedValue && i <= PushIntMaxCachedValue)371                    {372                        s_ints ??= new Instruction[PushIntMaxCachedValue - PushIntMinCachedValue + 1];373 374                        i -= PushIntMinCachedValue;375                        Emit(s_ints[i] ?? (s_ints[i] = new LoadObjectInstruction(value)));376                        return;377                    }378                }379            }380 381            if (_objects == null)382            {383                _objects = new List<object>();384                s_loadObjectCached ??= new Instruction[CachedObjectCount];385            }386 387            if (_objects.Count < s_loadObjectCached.Length)388            {389                uint index = (uint)_objects.Count;390                _objects.Add(value);391                Emit(s_loadObjectCached[index] ?? (s_loadObjectCached[index] = new LoadCachedObjectInstruction(index)));392            }393            else394            {395                Emit(new LoadObjectInstruction(value));396            }397        }398 399        public void EmitDup()400        {401            Emit(DupInstruction.Instance);402        }403 404        public void EmitPop()405        {406            Emit(PopInstruction.Instance);407        }408 409        #endregion410 411        #region Locals412 413        internal void SwitchToBoxed(int index, int instructionIndex)414        {415            var instruction = _instructions[instructionIndex] as IBoxableInstruction;416 417            if (instruction != null)418            {419                var newInstruction = instruction.BoxIfIndexMatches(index);420                if (newInstruction != null)421                {422                    _instructions[instructionIndex] = newInstruction;423                }424            }425        }426 427        private const int LocalInstrCacheSize = 64;428 429        private static Instruction[] s_loadLocal;430        private static Instruction[] s_loadLocalBoxed;431        private static Instruction[] s_loadLocalFromClosure;432        private static Instruction[] s_loadLocalFromClosureBoxed;433        private static Instruction[] s_assignLocal;434        private static Instruction[] s_storeLocal;435        private static Instruction[] s_assignLocalBoxed;436        private static Instruction[] s_storeLocalBoxed;437        private static Instruction[] s_assignLocalToClosure;438        private static Instruction[] s_initReference;439        private static Instruction[] s_initImmutableRefBox;440        private static Instruction[] s_parameterBox;441        private static Instruction[] s_parameter;442 443        public void EmitLoadLocal(int index)444        {445            s_loadLocal ??= new Instruction[LocalInstrCacheSize];446 447            if (index < s_loadLocal.Length)448            {449                Emit(s_loadLocal[index] ?? (s_loadLocal[index] = new LoadLocalInstruction(index)));450            }451            else452            {453                Emit(new LoadLocalInstruction(index));454            }455        }456 457        public void EmitLoadLocalBoxed(int index)458        {459            Emit(LoadLocalBoxed(index));460        }461 462        internal static Instruction LoadLocalBoxed(int index)463        {464            s_loadLocalBoxed ??= new Instruction[LocalInstrCacheSize];465 466            if (index < s_loadLocalBoxed.Length)467            {468                return s_loadLocalBoxed[index] ?? (s_loadLocalBoxed[index] = new LoadLocalBoxedInstruction(index));469            }470            else471            {472                return new LoadLocalBoxedInstruction(index);473            }474        }475 476        public void EmitLoadLocalFromClosure(int index)477        {478            s_loadLocalFromClosure ??= new Instruction[LocalInstrCacheSize];479 480            if (index < s_loadLocalFromClosure.Length)481            {482                Emit(s_loadLocalFromClosure[index] ?? (s_loadLocalFromClosure[index] = new LoadLocalFromClosureInstruction(index)));483            }484            else485            {486                Emit(new LoadLocalFromClosureInstruction(index));487            }488        }489 490        public void EmitLoadLocalFromClosureBoxed(int index)491        {492            s_loadLocalFromClosureBoxed ??= new Instruction[LocalInstrCacheSize];493 494            if (index < s_loadLocalFromClosureBoxed.Length)495            {496                Emit(s_loadLocalFromClosureBoxed[index] ?? (s_loadLocalFromClosureBoxed[index] = new LoadLocalFromClosureBoxedInstruction(index)));497            }498            else499            {500                Emit(new LoadLocalFromClosureBoxedInstruction(index));501            }502        }503 504        public void EmitAssignLocal(int index)505        {506            s_assignLocal ??= new Instruction[LocalInstrCacheSize];507 508            if (index < s_assignLocal.Length)509            {510                Emit(s_assignLocal[index] ?? (s_assignLocal[index] = new AssignLocalInstruction(index)));511            }512            else513            {514                Emit(new AssignLocalInstruction(index));515            }516        }517 518        public void EmitStoreLocal(int index)519        {520            s_storeLocal ??= new Instruction[LocalInstrCacheSize];521 522            if (index < s_storeLocal.Length)523            {524                Emit(s_storeLocal[index] ?? (s_storeLocal[index] = new StoreLocalInstruction(index)));525            }526            else527            {528                Emit(new StoreLocalInstruction(index));529            }530        }531 532        public void EmitAssignLocalBoxed(int index)533        {534            Emit(AssignLocalBoxed(index));535        }536 537        internal static Instruction AssignLocalBoxed(int index)538        {539            s_assignLocalBoxed ??= new Instruction[LocalInstrCacheSize];540 541            if (index < s_assignLocalBoxed.Length)542            {543                return s_assignLocalBoxed[index] ?? (s_assignLocalBoxed[index] = new AssignLocalBoxedInstruction(index));544            }545            else546            {547                return new AssignLocalBoxedInstruction(index);548            }549        }550 551        public void EmitStoreLocalBoxed(int index)552        {553            Emit(StoreLocalBoxed(index));554        }555 556        internal static Instruction StoreLocalBoxed(int index)557        {558            s_storeLocalBoxed ??= new Instruction[LocalInstrCacheSize];559 560            if (index < s_storeLocalBoxed.Length)561            {562                return s_storeLocalBoxed[index] ?? (s_storeLocalBoxed[index] = new StoreLocalBoxedInstruction(index));563            }564            else565            {566                return new StoreLocalBoxedInstruction(index);567            }568        }569 570        public void EmitAssignLocalToClosure(int index)571        {572            s_assignLocalToClosure ??= new Instruction[LocalInstrCacheSize];573 574            if (index < s_assignLocalToClosure.Length)575            {576                Emit(s_assignLocalToClosure[index] ?? (s_assignLocalToClosure[index] = new AssignLocalToClosureInstruction(index)));577            }578            else579            {580                Emit(new AssignLocalToClosureInstruction(index));581            }582        }583 584        public void EmitStoreLocalToClosure(int index)585        {586            EmitAssignLocalToClosure(index);587            EmitPop();588        }589 590        public void EmitInitializeLocal(int index, Type type)591        {592            object value = ScriptingRuntimeHelpers.GetPrimitiveDefaultValue(type);593            if (value != null)594            {595                Emit(new InitializeLocalInstruction.ImmutableValue(index, value));596            }597            else if (type.IsValueType)598            {599                Emit(new InitializeLocalInstruction.MutableValue(index, type));600            }601            else602            {603                Emit(InitReference(index));604            }605        }606 607        internal void EmitInitializeParameter(int index)608        {609            Emit(Parameter(index));610        }611 612        internal static Instruction Parameter(int index)613        {614            s_parameter ??= new Instruction[LocalInstrCacheSize];615 616            if (index < s_parameter.Length)617            {618                return s_parameter[index] ?? (s_parameter[index] = new InitializeLocalInstruction.Parameter(index));619            }620 621            return new InitializeLocalInstruction.Parameter(index);622        }623 624        internal static Instruction ParameterBox(int index)625        {626            s_parameterBox ??= new Instruction[LocalInstrCacheSize];627 628            if (index < s_parameterBox.Length)629            {630                return s_parameterBox[index] ?? (s_parameterBox[index] = new InitializeLocalInstruction.ParameterBox(index));631            }632 633            return new InitializeLocalInstruction.ParameterBox(index);634        }635 636        internal static Instruction InitReference(int index)637        {638            s_initReference ??= new Instruction[LocalInstrCacheSize];639 640            if (index < s_initReference.Length)641            {642                return s_initReference[index] ?? (s_initReference[index] = new InitializeLocalInstruction.Reference(index));643            }644 645            return new InitializeLocalInstruction.Reference(index);646        }647 648        internal static Instruction InitImmutableRefBox(int index)649        {650            s_initImmutableRefBox ??= new Instruction[LocalInstrCacheSize];651 652            if (index < s_initImmutableRefBox.Length)653            {654                return s_initImmutableRefBox[index] ?? (s_initImmutableRefBox[index] = new InitializeLocalInstruction.ImmutableBox(index, null));655            }656 657            return new InitializeLocalInstruction.ImmutableBox(index, null);658        }659 660        public void EmitNewRuntimeVariables(int count)661        {662            Emit(new RuntimeVariablesInstruction(count));663        }664 665        #endregion666 667        #region Array Operations668 669        public void EmitGetArrayItem(Type arrayType)670        {671            var elementType = arrayType.GetElementType();672            if (elementType.IsClass || elementType.IsInterface)673            {674                Emit(InstructionFactory<object>.Factory.GetArrayItem());675            }676            else677            {678                Emit(InstructionFactory.GetFactory(elementType).GetArrayItem());679            }680        }681 682        public void EmitSetArrayItem(Type arrayType)683        {684            var elementType = arrayType.GetElementType();685            if (elementType.IsClass || elementType.IsInterface)686            {687                Emit(InstructionFactory<object>.Factory.SetArrayItem());688            }689            else690            {691                Emit(InstructionFactory.GetFactory(elementType).SetArrayItem());692            }693        }694 695        public void EmitNewArray(Type elementType)696        {697            Emit(InstructionFactory.GetFactory(elementType).NewArray());698        }699 700        public void EmitNewArrayBounds(Type elementType, int rank)701        {702            Emit(new NewArrayBoundsInstruction(elementType, rank));703        }704 705        public void EmitNewArrayInit(Type elementType, int elementCount)706        {707            // To avoid lock contention in InstructionFactory.GetFactory, we special case the most common708            // types of arrays that the compiler creates.709            if (elementType == typeof(CommandParameterInternal))710            {711                Emit(InstructionFactory<CommandParameterInternal>.Factory.NewArrayInit(elementCount));712            }713            else if (elementType == typeof(CommandParameterInternal[]))714            {715                Emit(InstructionFactory<CommandParameterInternal[]>.Factory.NewArrayInit(elementCount));716            }717            else if (elementType == typeof(object))718            {719                Emit(InstructionFactory<object>.Factory.NewArrayInit(elementCount));720            }721            else if (elementType == typeof(string))722            {723                Emit(InstructionFactory<string>.Factory.NewArrayInit(elementCount));724            }725            else726            {727                Emit(InstructionFactory.GetFactory(elementType).NewArrayInit(elementCount));728            }729        }730 731        #endregion732 733        #region Arithmetic Operations734 735        public void EmitAdd(Type type, bool @checked)736        {737            if (@checked)738            {739                Emit(AddOvfInstruction.Create(type));740            }741            else742            {743                Emit(AddInstruction.Create(type));744            }745        }746 747        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters")]748        public void EmitSub(Type type, bool @checked)749        {750            if (@checked)751            {752                Emit(SubOvfInstruction.Create(type));753            }754            else755            {756                Emit(SubInstruction.Create(type));757            }758        }759 760        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters")]761        public void EmitMul(Type type, bool @checked)762        {763            if (@checked)764            {765                Emit(MulOvfInstruction.Create(type));766            }767            else768            {769                Emit(MulInstruction.Create(type));770            }771        }772 773        public void EmitDiv(Type type)774        {775            Emit(DivInstruction.Create(type));776        }777 778        #endregion779 780        #region Comparisons781 782        public void EmitEqual(Type type)783        {784            Emit(EqualInstruction.Create(type));785        }786 787        public void EmitNotEqual(Type type)788        {789            Emit(NotEqualInstruction.Create(type));790        }791 792        public void EmitLessThan(Type type)793        {794            Emit(LessThanInstruction.Create(type));795        }796 797        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters")]798        public void EmitLessThanOrEqual(Type type)799        {800            throw new NotSupportedException();801        }802 803        public void EmitGreaterThan(Type type)804        {805            Emit(GreaterThanInstruction.Create(type));806        }807 808        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters")]809        public void EmitGreaterThanOrEqual(Type type)810        {811            throw new NotSupportedException();812        }813 814        #endregion815 816        #region Conversions817 818        public void EmitNumericConvertChecked(TypeCode from, TypeCode to)819        {820            Emit(new NumericConvertInstruction.Checked(from, to));821        }822 823        public void EmitNumericConvertUnchecked(TypeCode from, TypeCode to)824        {825            Emit(new NumericConvertInstruction.Unchecked(from, to));826        }827 828        #endregion829 830        #region Boolean Operators831 832        public void EmitNot()833        {834            Emit(NotInstruction.Instance);835        }836 837        #endregion838 839        #region Types840 841        public void EmitDefaultValue(Type type)842        {843            Emit(InstructionFactory.GetFactory(type).DefaultValue());844        }845 846        public void EmitNew(ConstructorInfo constructorInfo)847        {848            Emit(new NewInstruction(constructorInfo));849        }850 851        internal void EmitCreateDelegate(LightDelegateCreator creator)852        {853            Emit(new CreateDelegateInstruction(creator));854        }855 856        public void EmitTypeEquals()857        {858            Emit(TypeEqualsInstruction.Instance);859        }860 861        public void EmitTypeIs(Type type)862        {863            Emit(InstructionFactory.GetFactory(type).TypeIs());864        }865 866        public void EmitTypeAs(Type type)867        {868            Emit(InstructionFactory.GetFactory(type).TypeAs());869        }870 871        #endregion872 873        #region Fields and Methods874 875        private static readonly Dictionary<FieldInfo, Instruction> s_loadFields = new Dictionary<FieldInfo, Instruction>();876 877        public void EmitLoadField(FieldInfo field)878        {879            Emit(GetLoadField(field));880        }881 882        private static Instruction GetLoadField(FieldInfo field)883        {884            lock (s_loadFields)885            {886                Instruction instruction;887                if (!s_loadFields.TryGetValue(field, out instruction))888                {889                    if (field.IsStatic)890                    {891                        instruction = new LoadStaticFieldInstruction(field);892                    }893                    else894                    {895                        instruction = new LoadFieldInstruction(field);896                    }897 898                    s_loadFields.Add(field, instruction);899                }900 901                return instruction;902            }903        }904 905        public void EmitStoreField(FieldInfo field)906        {907            if (field.IsStatic)908            {909                Emit(new StoreStaticFieldInstruction(field));910            }911            else912            {913                Emit(new StoreFieldInstruction(field));914            }915        }916 917        public void EmitCall(MethodInfo method)918        {919            EmitCall(method, method.GetParameters());920        }921 922        public void EmitCall(MethodInfo method, ParameterInfo[] parameters)923        {924            Emit(CallInstruction.Create(method, parameters));925        }926 927        #endregion928 929        #region Dynamic930 931        public void EmitDynamic(Type type, CallSiteBinder binder)932        {933            Emit(CreateDynamicInstruction(type, binder));934        }935 936        #region Generated Dynamic InstructionList Factory937 938        // *** BEGIN GENERATED CODE ***939        // generated by function: gen_instructionlist_factory from: generate_dynamic_instructions.py940 941        public void EmitDynamic<T0, TRet>(CallSiteBinder binder)942        {943            Emit(DynamicInstruction<T0, TRet>.Factory(binder));944        }945 946        public void EmitDynamic<T0, T1, TRet>(CallSiteBinder binder)947        {948            Emit(DynamicInstruction<T0, T1, TRet>.Factory(binder));949        }950 951        public void EmitDynamic<T0, T1, T2, TRet>(CallSiteBinder binder)952        {953            Emit(DynamicInstruction<T0, T1, T2, TRet>.Factory(binder));954        }955 956        public void EmitDynamic<T0, T1, T2, T3, TRet>(CallSiteBinder binder)957        {958            Emit(DynamicInstruction<T0, T1, T2, T3, TRet>.Factory(binder));959        }960 961        public void EmitDynamic<T0, T1, T2, T3, T4, TRet>(CallSiteBinder binder)962        {963            Emit(DynamicInstruction<T0, T1, T2, T3, T4, TRet>.Factory(binder));964        }965 966        public void EmitDynamic<T0, T1, T2, T3, T4, T5, TRet>(CallSiteBinder binder)967        {968            Emit(DynamicInstruction<T0, T1, T2, T3, T4, T5, TRet>.Factory(binder));969        }970 971        public void EmitDynamic<T0, T1, T2, T3, T4, T5, T6, TRet>(CallSiteBinder binder)972        {973            Emit(DynamicInstruction<T0, T1, T2, T3, T4, T5, T6, TRet>.Factory(binder));974        }975 976        public void EmitDynamic<T0, T1, T2, T3, T4, T5, T6, T7, TRet>(CallSiteBinder binder)977        {978            Emit(DynamicInstruction<T0, T1, T2, T3, T4, T5, T6, T7, TRet>.Factory(binder));979        }980 981        public void EmitDynamic<T0, T1, T2, T3, T4, T5, T6, T7, T8, TRet>(CallSiteBinder binder)982        {983            Emit(DynamicInstruction<T0, T1, T2, T3, T4, T5, T6, T7, T8, TRet>.Factory(binder));984        }985 986        public void EmitDynamic<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, TRet>(CallSiteBinder binder)987        {988            Emit(DynamicInstruction<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, TRet>.Factory(binder));989        }990 991        public void EmitDynamic<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, TRet>(CallSiteBinder binder)992        {993            Emit(DynamicInstruction<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, TRet>.Factory(binder));994        }995 996        public void EmitDynamic<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, TRet>(CallSiteBinder binder)997        {998            Emit(DynamicInstruction<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, TRet>.Factory(binder));999        }1000 1001        public void EmitDynamic<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, TRet>(CallSiteBinder binder)1002        {1003            Emit(DynamicInstruction<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, TRet>.Factory(binder));1004        }1005 1006        public void EmitDynamic<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, TRet>(CallSiteBinder binder)1007        {1008            Emit(DynamicInstruction<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, TRet>.Factory(binder));1009        }1010 1011        public void EmitDynamic<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, TRet>(CallSiteBinder binder)1012        {1013            Emit(DynamicInstruction<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, TRet>.Factory(binder));1014        }1015 1016        // *** END GENERATED CODE ***1017 1018        #endregion1019 1020        private static readonly Dictionary<Type, Func<CallSiteBinder, Instruction>> s_factories =1021            new Dictionary<Type, Func<CallSiteBinder, Instruction>>();1022 1023        internal static Instruction CreateDynamicInstruction(Type delegateType, CallSiteBinder binder)1024        {1025            Func<CallSiteBinder, Instruction> factory;1026            lock (s_factories)1027            {1028                if (!s_factories.TryGetValue(delegateType, out factory))1029                {1030                    if (delegateType.GetMethod("Invoke").ReturnType == typeof(void))1031                    {1032                        // TODO: We should generally support void returning binders but the only1033                        // ones that exist are delete index/member who's perf isn't that critical.1034                        return new DynamicInstructionN(delegateType, CallSite.Create(delegateType, binder), true);1035                    }1036 1037                    Type instructionType = DynamicInstructionN.GetDynamicInstructionType(delegateType);1038                    if (instructionType == null)1039                    {1040                        return new DynamicInstructionN(delegateType, CallSite.Create(delegateType, binder));1041                    }1042 1043                    factory = (Func<CallSiteBinder, Instruction>)instructionType1044                        .GetMethod("Factory")1045                        .CreateDelegate(typeof(Func<CallSiteBinder, Instruction>));1046 1047                    s_factories[delegateType] = factory;1048                }1049            }1050 1051            return factory(binder);1052        }1053 1054        #endregion1055 1056        #region Control Flow1057 1058        private static readonly RuntimeLabel[] s_emptyRuntimeLabels = new RuntimeLabel[] { new RuntimeLabel(Interpreter.RethrowOnReturn, 0, 0) };1059 1060        private RuntimeLabel[] BuildRuntimeLabels()1061        {1062            if (_runtimeLabelCount == 0)1063            {1064                return s_emptyRuntimeLabels;1065            }1066 1067            var result = new RuntimeLabel[_runtimeLabelCount + 1];1068            foreach (BranchLabel label in _labels)1069            {1070                if (label.HasRuntimeLabel)1071                {1072                    result[label.LabelIndex] = label.ToRuntimeLabel();1073                }1074            }1075            // "return and rethrow" label:1076            result[result.Length - 1] = new RuntimeLabel(Interpreter.RethrowOnReturn, 0, 0);1077            return result;1078        }1079 1080        public BranchLabel MakeLabel()1081        {1082            _labels ??= new List<BranchLabel>();1083 1084            var label = new BranchLabel();1085            _labels.Add(label);1086            return label;1087        }1088 1089        internal void FixupBranch(int branchIndex, int offset)1090        {1091            _instructions[branchIndex] = ((OffsetInstruction)_instructions[branchIndex]).Fixup(offset);1092        }1093 1094        private int EnsureLabelIndex(BranchLabel label)1095        {1096            if (label.HasRuntimeLabel)1097            {1098                return label.LabelIndex;1099            }1100 1101            label.LabelIndex = _runtimeLabelCount;1102            _runtimeLabelCount++;1103            return label.LabelIndex;1104        }1105 1106        public int MarkRuntimeLabel()1107        {1108            BranchLabel handlerLabel = MakeLabel();1109            MarkLabel(handlerLabel);1110            return EnsureLabelIndex(handlerLabel);1111        }1112 1113        public void MarkLabel(BranchLabel label)1114        {1115            label.Mark(this);1116        }1117 1118        public void EmitGoto(BranchLabel label, bool hasResult, bool hasValue)1119        {1120            Emit(GotoInstruction.Create(EnsureLabelIndex(label), hasResult, hasValue));1121        }1122 1123        private void EmitBranch(OffsetInstruction instruction, BranchLabel label)1124        {1125            Emit(instruction);1126            label.AddBranch(this, Count - 1);1127        }1128 1129        public void EmitBranch(BranchLabel label)1130        {1131            EmitBranch(new BranchInstruction(), label);1132        }1133 1134        public void EmitBranch(BranchLabel label, bool hasResult, bool hasValue)1135        {1136            EmitBranch(new BranchInstruction(hasResult, hasValue), label);1137        }1138 1139        public void EmitCoalescingBranch(BranchLabel leftNotNull)1140        {1141            EmitBranch(new CoalescingBranchInstruction(), leftNotNull);1142        }1143 1144        public void EmitBranchTrue(BranchLabel elseLabel)1145        {1146            EmitBranch(new BranchTrueInstruction(), elseLabel);1147        }1148 1149        public void EmitBranchFalse(BranchLabel elseLabel)1150        {1151            EmitBranch(new BranchFalseInstruction(), elseLabel);1152        }1153 1154        public void EmitThrow()1155        {1156            Emit(ThrowInstruction.Throw);1157        }1158 1159        public void EmitThrowVoid()1160        {1161            Emit(ThrowInstruction.VoidThrow);1162        }1163 1164        public void EmitRethrow()1165        {1166            Emit(ThrowInstruction.Rethrow);1167        }1168 1169        public void EmitRethrowVoid()1170        {1171            Emit(ThrowInstruction.VoidRethrow);1172        }1173 1174        public void EmitEnterTryFinally(BranchLabel finallyStartLabel)1175        {1176            Emit(EnterTryCatchFinallyInstruction.CreateTryFinally(EnsureLabelIndex(finallyStartLabel)));1177        }1178 1179        public void EmitEnterTryCatch()1180        {1181            Emit(EnterTryCatchFinallyInstruction.CreateTryCatch());1182        }1183 1184        public void EmitEnterFinally(BranchLabel finallyStartLabel)1185        {1186            Emit(EnterFinallyInstruction.Create(EnsureLabelIndex(finallyStartLabel)));1187        }1188 1189        public void EmitLeaveFinally()1190        {1191            Emit(LeaveFinallyInstruction.Instance);1192        }1193 1194        public void EmitLeaveFault(bool hasValue)1195        {1196            Emit(hasValue ? LeaveFaultInstruction.NonVoid : LeaveFaultInstruction.Void);1197        }1198 1199        public void EmitEnterExceptionHandlerNonVoid()1200        {

Showing the first 1,200 of 1222 lines. Download the file for the rest.