File: src\System\Reflection\Emit\DynamicMethod.CoreCLR.cs
Web Access
Project: src\src\coreclr\System.Private.CoreLib\System.Private.CoreLib.csproj (System.Private.CoreLib)
// 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.Diagnostics.CodeAnalysis;
using System.Globalization;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Loader;
using System.Text;
using System.Threading;
using static System.Runtime.CompilerServices.RuntimeHelpers;
 
namespace System.Reflection.Emit
{
    public sealed partial class DynamicMethod : MethodInfo
    {
        private RuntimeType[] _parameterTypes;
        internal IRuntimeMethodInfo? _methodHandle;
        private RuntimeType _returnType;
        private DynamicILGenerator? _ilGenerator;
        private DynamicILInfo? _dynamicILInfo;
        private bool _initLocals;
        private Module _module;
        internal bool _skipVisibility;
        internal RuntimeType? _typeOwner;
        private MethodBaseInvoker? _invoker;
        private Signature? _signature;
        private string _name;
        private MethodAttributes _attributes;
        private CallingConventions _callingConvention;
        private RuntimeParameterInfo[]? _parameters;
 
        // needed to keep the object alive during jitting
        // assigned by the DynamicResolver ctor
        internal DynamicResolver? _resolver;
 
        internal bool _restrictedSkipVisibility;
 
        //
        // Delegate and method creation
        //
 
        public sealed override Delegate CreateDelegate(Type delegateType) =>
            CreateDelegate(delegateType, target: null);
 
        public sealed override Delegate CreateDelegate(Type delegateType, object? target)
        {
            if (_restrictedSkipVisibility)
            {
                // Compile the method since accessibility checks are done as part of compilation
                GetMethodDescriptor();
                IRuntimeMethodInfo? methodHandle = _methodHandle;
                CompileMethod(methodHandle != null ? methodHandle.Value : RuntimeMethodHandleInternal.EmptyHandle);
                GC.KeepAlive(methodHandle);
            }
 
            MulticastDelegate d = (MulticastDelegate)Delegate.CreateDelegateNoSecurityCheck(delegateType, target, GetMethodDescriptor());
            // stash this MethodInfo by brute force.
            d.StoreDynamicMethod(this);
            return d;
        }
 
        // This is guaranteed to return a valid handle
        internal RuntimeMethodHandle GetMethodDescriptor()
        {
            if (_methodHandle == null)
            {
                lock (this)
                {
                    if (_methodHandle == null)
                    {
                        if (_dynamicILInfo != null)
                            _dynamicILInfo.GetCallableMethod((RuntimeModule)_module, this);
                        else
                        {
                            if (_ilGenerator == null || _ilGenerator.ILOffset == 0)
                                throw new InvalidOperationException(SR.Format(SR.InvalidOperation_BadEmptyMethodBody, Name));
 
                            _ilGenerator.GetCallableMethod((RuntimeModule)_module, this);
                        }
                    }
                }
            }
            return new RuntimeMethodHandle(_methodHandle!);
        }
 
        private MethodBaseInvoker Invoker
        {
            [MethodImpl(MethodImplOptions.AggressiveInlining)]
            get
            {
                return _invoker ??= new MethodBaseInvoker(this, Signature);
            }
        }
 
        internal Signature Signature
        {
            [MethodImpl(MethodImplOptions.AggressiveInlining)]
            get
            {
                [MethodImpl(MethodImplOptions.NoInlining)] // move lazy sig generation out of the hot path
                Signature LazyCreateSignature()
                {
                    Debug.Assert(_methodHandle != null);
                    Debug.Assert(_parameterTypes != null);
 
                    Signature newSig = new Signature(_methodHandle, _parameterTypes, _returnType, CallingConvention);
                    Volatile.Write(ref _signature, newSig);
                    return newSig;
                }
 
                return _signature ?? LazyCreateSignature();
            }
        }
 
        public override object? Invoke(object? obj, BindingFlags invokeAttr, Binder? binder, object?[]? parameters, CultureInfo? culture)
        {
            if ((CallingConvention & CallingConventions.VarArgs) == CallingConventions.VarArgs)
                throw new NotSupportedException(SR.NotSupported_CallToVarArg);
 
            //
            // We do not demand any permission here because the caller already has access
            // to the current DynamicMethod object, and it could just as easily emit another
            // Transparent DynamicMethod to call the current DynamicMethod.
            //
 
            _ = GetMethodDescriptor();
            // ignore obj since it's a static method
 
            // verify arguments
            int argCount = (parameters != null) ? parameters.Length : 0;
            if (Signature.Arguments.Length != argCount)
                throw new TargetParameterCountException(SR.Arg_ParmCnt);
            object? retValue = argCount switch
            {
                0 => Invoker.InvokeWithNoArgs(obj, invokeAttr),
                1 => Invoker.InvokeWithOneArg(obj, invokeAttr, binder, parameters!, culture),
                2 or 3 or 4 => Invoker.InvokeWithFewArgs(obj, invokeAttr, binder, parameters!, culture),
                _ => Invoker.InvokeWithManyArgs(obj, invokeAttr, binder, parameters!, culture),
            };
            GC.KeepAlive(this);
            return retValue;
        }
 
        public DynamicILInfo GetDynamicILInfo()
        {
            if (_dynamicILInfo == null)
            {
                byte[] methodSignature = SignatureHelper.GetMethodSigHelper(
                        null, CallingConvention, ReturnType, null, null, _parameterTypes, null, null).GetSignature(true);
                _dynamicILInfo = new DynamicILInfo(this, methodSignature);
            }
            return _dynamicILInfo;
        }
 
        public ILGenerator GetILGenerator(int streamSize)
        {
            if (_ilGenerator == null)
            {
                byte[] methodSignature = SignatureHelper.GetMethodSigHelper(
                    null, CallingConvention, ReturnType, null, null, _parameterTypes, null, null).GetSignature(true);
                _ilGenerator = new DynamicILGenerator(this, methodSignature, streamSize);
            }
            return _ilGenerator;
        }
    }
}