| File: System\Linq\Expressions\Interpreter\Interpreter.cs | Web Access |
| Project: src\runtime\src\libraries\System.Linq.Expressions\src\System.Linq.Expressions.csproj (System.Linq.Expressions) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. using System.Collections.Generic; using System.Runtime.CompilerServices; namespace System.Linq.Expressions.Interpreter { /// <summary> /// A simple forth-style stack machine for executing Expression trees /// without the need to compile to IL and then invoke the JIT. This trades /// off much faster compilation time for a slower execution performance. /// For code that is only run a small number of times this can be a /// sweet spot. /// /// The core loop in the interpreter is the <see cref="Run(InterpretedFrame)"/> method. /// </summary> internal sealed class Interpreter { internal static readonly object NoValue = new object(); internal const int RethrowOnReturn = int.MaxValue; private readonly InstructionArray _instructions; internal readonly object[]? _objects; internal readonly RuntimeLabel[] _labels; internal readonly DebugInfo[] _debugInfos; internal Interpreter(string? name, LocalVariables locals, InstructionArray instructions, DebugInfo[] debugInfos) { Name = name; LocalCount = locals.LocalCount; ClosureVariables = locals.ClosureVariables; _instructions = instructions; _objects = instructions.Objects; _labels = instructions.Labels; _debugInfos = debugInfos; } internal string? Name { get; } internal int LocalCount { get; } internal int ClosureSize => ClosureVariables?.Count ?? 0; internal InstructionArray Instructions => _instructions; internal Dictionary<ParameterExpression, LocalVariable>? ClosureVariables { get; } /// <summary> /// Runs instructions within the given frame. /// </summary> /// <remarks> /// Interpreted stack frames are linked via Parent reference so that each CLR frame of this method corresponds /// to an interpreted stack frame in the chain. It is therefore possible to combine CLR stack traces with /// interpreted stack traces by aligning interpreted frames to the frames of this method. /// Each group of subsequent frames of Run method corresponds to a single interpreted frame. /// </remarks> [MethodImpl(MethodImplOptions.NoInlining)] public void Run(InterpretedFrame frame) { Instruction[] instructions = _instructions.Instructions; int index = frame.InstructionIndex; while (index < instructions.Length) { index += instructions[index].Run(frame); frame.InstructionIndex = index; } } } }