/src/libraries/System.Linq.Expressions/src/System/Linq/Expressions/Interpreter/LocalAccess.cs
https://github.com/dotnet/runtime · C# · 465 lines · 372 code · 88 blank · 5 comment · 12 complexity · 7a70f1525a77961814e5174f33787cae MD5 · raw file
- // 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.Diagnostics;
- using System.Dynamic.Utils;
- using System.Reflection;
- using System.Runtime.CompilerServices;
- namespace System.Linq.Expressions.Interpreter
- {
- internal interface IBoxableInstruction
- {
- Instruction? BoxIfIndexMatches(int index);
- }
- internal abstract class LocalAccessInstruction : Instruction
- {
- internal readonly int _index;
- protected LocalAccessInstruction(int index)
- {
- _index = index;
- }
- public override string ToDebugString(int instructionIndex, object? cookie, Func<int, int> labelIndexer, IReadOnlyList<object>? objects)
- {
- return cookie == null ?
- InstructionName + "(" + _index + ")" :
- InstructionName + "(" + cookie + ": " + _index + ")";
- }
- }
- #region Load
- internal sealed class LoadLocalInstruction : LocalAccessInstruction, IBoxableInstruction
- {
- internal LoadLocalInstruction(int index)
- : base(index)
- {
- }
- public override int ProducedStack => 1;
- public override string InstructionName => "LoadLocal";
- public override int Run(InterpretedFrame frame)
- {
- frame.Data[frame.StackIndex++] = frame.Data[_index];
- return 1;
- }
- public Instruction? BoxIfIndexMatches(int index)
- {
- return (index == _index) ? InstructionList.LoadLocalBoxed(index) : null;
- }
- }
- internal sealed class LoadLocalBoxedInstruction : LocalAccessInstruction
- {
- internal LoadLocalBoxedInstruction(int index)
- : base(index)
- {
- }
- public override int ProducedStack => 1;
- public override string InstructionName => "LoadLocalBox";
- public override int Run(InterpretedFrame frame)
- {
- var box = (IStrongBox)frame.Data[_index]!;
- frame.Data[frame.StackIndex++] = box.Value;
- return 1;
- }
- }
- internal sealed class LoadLocalFromClosureInstruction : LocalAccessInstruction
- {
- internal LoadLocalFromClosureInstruction(int index)
- : base(index)
- {
- }
- public override int ProducedStack => 1;
- public override string InstructionName => "LoadLocalClosure";
- public override int Run(InterpretedFrame frame)
- {
- IStrongBox box = frame.Closure![_index];
- frame.Data[frame.StackIndex++] = box.Value;
- return 1;
- }
- }
- internal sealed class LoadLocalFromClosureBoxedInstruction : LocalAccessInstruction
- {
- internal LoadLocalFromClosureBoxedInstruction(int index)
- : base(index)
- {
- }
- public override int ProducedStack => 1;
- public override string InstructionName => "LoadLocal";
- public override int Run(InterpretedFrame frame)
- {
- IStrongBox box = frame.Closure![_index];
- frame.Data[frame.StackIndex++] = box;
- return 1;
- }
- }
- #endregion
- #region Store, Assign
- internal sealed class AssignLocalInstruction : LocalAccessInstruction, IBoxableInstruction
- {
- internal AssignLocalInstruction(int index)
- : base(index)
- {
- }
- public override int ConsumedStack => 1;
- public override int ProducedStack => 1;
- public override string InstructionName => "AssignLocal";
- public override int Run(InterpretedFrame frame)
- {
- frame.Data[_index] = frame.Peek();
- return 1;
- }
- public Instruction? BoxIfIndexMatches(int index)
- {
- return (index == _index) ? InstructionList.AssignLocalBoxed(index) : null;
- }
- }
- internal sealed class StoreLocalInstruction : LocalAccessInstruction, IBoxableInstruction
- {
- internal StoreLocalInstruction(int index)
- : base(index)
- {
- }
- public override int ConsumedStack => 1;
- public override string InstructionName => "StoreLocal";
- public override int Run(InterpretedFrame frame)
- {
- frame.Data[_index] = frame.Pop();
- return 1;
- }
- public Instruction? BoxIfIndexMatches(int index)
- {
- return (index == _index) ? InstructionList.StoreLocalBoxed(index) : null;
- }
- }
- internal sealed class AssignLocalBoxedInstruction : LocalAccessInstruction
- {
- internal AssignLocalBoxedInstruction(int index)
- : base(index)
- {
- }
- public override int ConsumedStack => 1;
- public override int ProducedStack => 1;
- public override string InstructionName => "AssignLocalBox";
- public override int Run(InterpretedFrame frame)
- {
- var box = (IStrongBox)frame.Data[_index]!;
- box.Value = frame.Peek();
- return 1;
- }
- }
- internal sealed class StoreLocalBoxedInstruction : LocalAccessInstruction
- {
- internal StoreLocalBoxedInstruction(int index)
- : base(index)
- {
- }
- public override int ConsumedStack => 1;
- public override string InstructionName => "StoreLocalBox";
- public override int Run(InterpretedFrame frame)
- {
- var box = (IStrongBox)frame.Data[_index]!;
- box.Value = frame.Data[--frame.StackIndex];
- return 1;
- }
- }
- internal sealed class AssignLocalToClosureInstruction : LocalAccessInstruction
- {
- internal AssignLocalToClosureInstruction(int index)
- : base(index)
- {
- }
- public override int ConsumedStack => 1;
- public override int ProducedStack => 1;
- public override string InstructionName => "AssignLocalClosure";
- public override int Run(InterpretedFrame frame)
- {
- IStrongBox box = frame.Closure![_index];
- box.Value = frame.Peek();
- return 1;
- }
- }
- internal sealed class ValueTypeCopyInstruction : Instruction
- {
- public static readonly ValueTypeCopyInstruction Instruction = new ValueTypeCopyInstruction();
- public override int ConsumedStack => 1;
- public override int ProducedStack => 1;
- public override string InstructionName => "ValueTypeCopy";
- public override int Run(InterpretedFrame frame)
- {
- object? o = frame.Pop();
- frame.Push(o == null ? o : RuntimeHelpers.GetObjectValue(o));
- return 1;
- }
- }
- #endregion
- #region Initialize
- internal abstract class InitializeLocalInstruction : LocalAccessInstruction
- {
- internal InitializeLocalInstruction(int index)
- : base(index)
- {
- }
- internal sealed class Reference : InitializeLocalInstruction, IBoxableInstruction
- {
- internal Reference(int index)
- : base(index)
- {
- }
- public override int Run(InterpretedFrame frame)
- {
- frame.Data[_index] = null;
- return 1;
- }
- public Instruction? BoxIfIndexMatches(int index)
- {
- return (index == _index) ? InstructionList.InitImmutableRefBox(index) : null;
- }
- public override string InstructionName => "InitRef";
- }
- internal sealed class ImmutableValue : InitializeLocalInstruction, IBoxableInstruction
- {
- private readonly object _defaultValue;
- internal ImmutableValue(int index, object defaultValue)
- : base(index)
- {
- Debug.Assert(defaultValue != null);
- _defaultValue = defaultValue;
- }
- public override int Run(InterpretedFrame frame)
- {
- frame.Data[_index] = _defaultValue;
- return 1;
- }
- public Instruction? BoxIfIndexMatches(int index)
- {
- return (index == _index) ? new ImmutableBox(index, _defaultValue) : null;
- }
- public override string InstructionName => "InitImmutableValue";
- }
- internal sealed class ImmutableBox : InitializeLocalInstruction
- {
- // immutable value:
- private readonly object _defaultValue;
- internal ImmutableBox(int index, object defaultValue)
- : base(index)
- {
- _defaultValue = defaultValue;
- }
- public override int Run(InterpretedFrame frame)
- {
- frame.Data[_index] = new StrongBox<object>(_defaultValue);
- return 1;
- }
- public override string InstructionName => "InitImmutableBox";
- }
- internal sealed class ImmutableRefBox : InitializeLocalInstruction
- {
- // immutable value:
- internal ImmutableRefBox(int index)
- : base(index)
- {
- }
- public override int Run(InterpretedFrame frame)
- {
- frame.Data[_index] = new StrongBox<object>();
- return 1;
- }
- public override string InstructionName => "InitImmutableBox";
- }
- internal sealed class ParameterBox : InitializeLocalInstruction
- {
- public ParameterBox(int index)
- : base(index)
- {
- }
- public override int Run(InterpretedFrame frame)
- {
- frame.Data[_index] = new StrongBox<object?>(frame.Data[_index]);
- return 1;
- }
- public override string InstructionName => "InitParameterBox";
- }
- internal sealed class Parameter : InitializeLocalInstruction, IBoxableInstruction
- {
- internal Parameter(int index)
- : base(index)
- {
- }
- public override int Run(InterpretedFrame frame)
- {
- // nop
- return 1;
- }
- public Instruction? BoxIfIndexMatches(int index)
- {
- if (index == _index)
- {
- return InstructionList.ParameterBox(index);
- }
- return null;
- }
- public override string InstructionName => "InitParameter";
- }
- internal sealed class MutableValue : InitializeLocalInstruction, IBoxableInstruction
- {
- private readonly Type _type;
- internal MutableValue(int index, Type type)
- : base(index)
- {
- _type = type;
- }
- public override int Run(InterpretedFrame frame)
- {
- try
- {
- frame.Data[_index] = Activator.CreateInstance(_type);
- }
- catch (TargetInvocationException e)
- {
- ExceptionHelpers.UnwrapAndRethrow(e);
- throw ContractUtils.Unreachable;
- }
- return 1;
- }
- public Instruction? BoxIfIndexMatches(int index)
- {
- return (index == _index) ? new MutableBox(index, _type) : null;
- }
- public override string InstructionName => "InitMutableValue";
- }
- internal sealed class MutableBox : InitializeLocalInstruction
- {
- private readonly Type _type;
- internal MutableBox(int index, Type type)
- : base(index)
- {
- _type = type;
- }
- public override int Run(InterpretedFrame frame)
- {
- object? value;
- try
- {
- value = Activator.CreateInstance(_type);
- }
- catch (TargetInvocationException e)
- {
- ExceptionHelpers.UnwrapAndRethrow(e);
- throw ContractUtils.Unreachable;
- }
- frame.Data[_index] = new StrongBox<object?>(value);
- return 1;
- }
- public override string InstructionName => "InitMutableBox";
- }
- }
- #endregion
- #region RuntimeVariables
- internal sealed class RuntimeVariablesInstruction : Instruction
- {
- private readonly int _count;
- public RuntimeVariablesInstruction(int count)
- {
- _count = count;
- }
- public override int ProducedStack => 1;
- public override int ConsumedStack => _count;
- public override string InstructionName => "GetRuntimeVariables";
- public override int Run(InterpretedFrame frame)
- {
- var ret = new IStrongBox[_count];
- for (int i = ret.Length - 1; i >= 0; i--)
- {
- ret[i] = (IStrongBox)frame.Pop()!;
- }
- frame.Push(RuntimeVariables.Create(ret));
- return 1;
- }
- }
- #endregion
- }