| File: System\Linq\Expressions\Interpreter\ArrayOperations.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.Diagnostics.CodeAnalysis; namespace System.Linq.Expressions.Interpreter { [RequiresDynamicCode(Expression.NewArrayRequiresDynamicCode)] internal sealed class NewArrayInitInstruction : Instruction { private readonly Type _elementType; private readonly int _elementCount; internal NewArrayInitInstruction(Type elementType, int elementCount) { _elementType = elementType; _elementCount = elementCount; } public override int ConsumedStack => _elementCount; public override int ProducedStack => 1; public override string InstructionName => "NewArrayInit"; public override int Run(InterpretedFrame frame) { Array array = Array.CreateInstance(_elementType, _elementCount); for (int i = _elementCount - 1; i >= 0; i--) { array.SetValue(frame.Pop(), i); } frame.Push(array); return 1; } } [RequiresDynamicCode(Expression.NewArrayRequiresDynamicCode)] internal sealed class NewArrayInstruction : Instruction { private readonly Type _elementType; internal NewArrayInstruction(Type elementType) { _elementType = elementType; } public override int ConsumedStack => 1; public override int ProducedStack => 1; public override string InstructionName => "NewArray"; public override int Run(InterpretedFrame frame) { int length = ConvertHelper.ToInt32NoNull(frame.Pop()); // To make behavior aligned with array creation emitted by C# compiler if length is less than // zero we try to use it to create an array, which will throw an OverflowException with the // correct localized error message. frame.Push(length < 0 ? new int[length] : Array.CreateInstance(_elementType, length)); return 1; } } [RequiresDynamicCode(Expression.NewArrayRequiresDynamicCode)] internal sealed class NewArrayBoundsInstruction : Instruction { private readonly Type _elementType; private readonly int _rank; internal NewArrayBoundsInstruction(Type elementType, int rank) { _elementType = elementType; _rank = rank; } public override int ConsumedStack => _rank; public override int ProducedStack => 1; public override string InstructionName => "NewArrayBounds"; public override int Run(InterpretedFrame frame) { var lengths = new int[_rank]; for (int i = _rank - 1; i >= 0; i--) { int length = ConvertHelper.ToInt32NoNull(frame.Pop()); if (length < 0) { // to make behavior aligned with array creation emitted by C# compiler throw new OverflowException(); } lengths[i] = length; } Array array = Array.CreateInstance(_elementType, lengths); frame.Push(array); return 1; } } internal sealed class GetArrayItemInstruction : Instruction { internal static readonly GetArrayItemInstruction Instance = new GetArrayItemInstruction(); private GetArrayItemInstruction() { } public override int ConsumedStack => 2; public override int ProducedStack => 1; public override string InstructionName => "GetArrayItem"; public override int Run(InterpretedFrame frame) { int index = ConvertHelper.ToInt32NoNull(frame.Pop()); Array array = (Array)frame.Pop()!; frame.Push(array.GetValue(index)); return 1; } } internal sealed class SetArrayItemInstruction : Instruction { internal static readonly SetArrayItemInstruction Instance = new SetArrayItemInstruction(); private SetArrayItemInstruction() { } public override int ConsumedStack => 3; public override string InstructionName => "SetArrayItem"; public override int Run(InterpretedFrame frame) { object? value = frame.Pop(); int index = ConvertHelper.ToInt32NoNull(frame.Pop()); Array array = (Array)frame.Pop()!; array.SetValue(value, index); return 1; } } internal sealed class ArrayLengthInstruction : Instruction { public static readonly ArrayLengthInstruction Instance = new ArrayLengthInstruction(); public override int ConsumedStack => 1; public override int ProducedStack => 1; public override string InstructionName => "ArrayLength"; private ArrayLengthInstruction() { } public override int Run(InterpretedFrame frame) { object obj = frame.Pop()!; frame.Push(((Array)obj).Length); return 1; } } internal static class ConvertHelper { public static int ToInt32NoNull(object? val) { // If the value is null, unbox and cast to throw an InvalidOperationException // that .NET Framework throws. return (val == null) ? (int)(int?)val! : Convert.ToInt32(val); } } }