File: System\Linq\Expressions\Interpreter\NewInstruction.cs
Web Access
Project: src\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;
using System.Dynamic.Utils;
using System.Reflection;
 
namespace System.Linq.Expressions.Interpreter
{
    internal class NewInstruction : Instruction
    {
        protected readonly ConstructorInfo _constructor;
        protected readonly int _argumentCount;
 
        public NewInstruction(ConstructorInfo constructor, int argumentCount)
        {
            _constructor = constructor;
            _argumentCount = argumentCount;
        }
 
        public override int ConsumedStack => _argumentCount;
        public override int ProducedStack => 1;
        public override string InstructionName => "New";
 
        public override int Run(InterpretedFrame frame)
        {
            int first = frame.StackIndex - _argumentCount;
 
            object?[] args = GetArgs(frame, first);
 
            object ret;
            try
            {
                ret = _constructor.Invoke(args);
            }
            catch (TargetInvocationException e)
            {
                ExceptionHelpers.UnwrapAndRethrow(e);
                throw ContractUtils.Unreachable;
            }
 
            frame.Data[first] = ret;
            frame.StackIndex = first + 1;
 
            return 1;
        }
 
        protected object?[] GetArgs(InterpretedFrame frame, int first)
        {
            if (_argumentCount > 0)
            {
                var args = new object?[_argumentCount];
 
                for (int i = 0; i < args.Length; i++)
                {
                    args[i] = frame.Data[first + i];
                }
 
                return args;
            }
            else
            {
                return Array.Empty<object>();
            }
        }
 
        public override string ToString() => "New " + _constructor.DeclaringType!.Name + "(" + _constructor + ")";
    }
 
    internal sealed class ByRefNewInstruction : NewInstruction
    {
        private readonly ByRefUpdater[] _byrefArgs;
 
        internal ByRefNewInstruction(ConstructorInfo target, int argumentCount, ByRefUpdater[] byrefArgs)
            : base(target, argumentCount)
        {
            _byrefArgs = byrefArgs;
        }
 
        public override string InstructionName => "ByRefNew";
 
        public sealed override int Run(InterpretedFrame frame)
        {
            int first = frame.StackIndex - _argumentCount;
 
            object?[] args = GetArgs(frame, first);
 
            try
            {
                object ret;
                try
                {
                    ret = _constructor.Invoke(args);
                }
                catch (TargetInvocationException e)
                {
                    ExceptionHelpers.UnwrapAndRethrow(e);
                    throw ContractUtils.Unreachable;
                }
 
                frame.Data[first] = ret;
                frame.StackIndex = first + 1;
            }
            finally
            {
                foreach (ByRefUpdater arg in _byrefArgs)
                {
                    arg.Update(frame, args[arg.ArgumentIndex]);
                }
            }
 
            return 1;
        }
    }
}