File: system\reflection\emit\dynamicmethod.cs
Project: ndp\clr\src\bcl\mscorlib.csproj (mscorlib)
// ==++==
// 
//   Copyright (c) Microsoft Corporation.  All rights reserved.
// 
// ==--==
// <OWNER>Microsoft</OWNER>
// 
 
namespace System.Reflection.Emit
{
    using System;
    using System.Collections.Generic;
    using CultureInfo = System.Globalization.CultureInfo;
    using System.Reflection;
    using System.Security;
    using System.Security.Permissions;
    using System.Threading;
    using System.Runtime.CompilerServices;
    using System.Runtime.Versioning;
    using System.Diagnostics.Contracts;
    using System.Runtime.InteropServices;
 
    [System.Runtime.InteropServices.ComVisible(true)]
    public sealed class DynamicMethod : MethodInfo
    {
        private RuntimeType[] m_parameterTypes;
        internal IRuntimeMethodInfo m_methodHandle;
        private RuntimeType m_returnType;
        private DynamicILGenerator m_ilGenerator;
        #if FEATURE_CORECLR
        [System.Security.SecurityCritical] // auto-generated
        #endif
        private DynamicILInfo m_DynamicILInfo;
        private bool m_fInitLocals;
        private RuntimeModule m_module;
        internal bool m_skipVisibility;
        internal RuntimeType m_typeOwner; // can be null
 
        // We want the creator of the DynamicMethod to control who has access to the
        // DynamicMethod (just like we do for delegates). However, a user can get to
        // the corresponding RTDynamicMethod using Exception.TargetSite, StackFrame.GetMethod, etc.
        // If we allowed use of RTDynamicMethod, the creator of the DynamicMethod would
        // not be able to bound access to the DynamicMethod. Hence, we need to ensure that 
        // we do not allow direct use of RTDynamicMethod.
        private RTDynamicMethod m_dynMethod;
 
        // needed to keep the object alive during jitting
        // assigned by the DynamicResolver ctor
        internal DynamicResolver m_resolver;
 
        // Always false unless we are in an immersive (non dev mode) process.
#if FEATURE_APPX
        private bool m_profileAPICheck;
 
        private RuntimeAssembly m_creatorAssembly;
#endif
 
        internal bool m_restrictedSkipVisibility;
        // The context when the method was created. We use this to do the RestrictedMemberAccess checks.
        // These checks are done when the method is compiled. This can happen at an arbitrary time,
        // when CreateDelegate or Invoke is called, or when another DynamicMethod executes OpCodes.Call.
        // We capture the creation context so that we can do the checks against the same context,
        // irrespective of when the method gets compiled. Note that the DynamicMethod does not know when
        // it is ready for use since there is not API which indictates that IL generation has completed.
#if FEATURE_COMPRESSEDSTACK
        internal CompressedStack m_creationContext;
#endif // FEATURE_COMPRESSEDSTACK
        private static volatile InternalModuleBuilder s_anonymouslyHostedDynamicMethodsModule;
        private static readonly object s_anonymouslyHostedDynamicMethodsModuleLock = new object();
        
        //
        // class initialization (ctor and init)
        //
 
        private DynamicMethod() { }
 
        [System.Security.SecuritySafeCritical]  // auto-generated
        [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable
        public DynamicMethod(string name,
                             Type returnType,
                             Type[] parameterTypes)
        {
            StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
 
            Init(name, 
                MethodAttributes.Public | MethodAttributes.Static, 
                CallingConventions.Standard, 
                returnType, 
                parameterTypes,
                null,   // owner
                null,   // m
                false,  // skipVisibility
                true,
                ref stackMark);  // transparentMethod
        }
 
        [System.Security.SecuritySafeCritical]  // auto-generated
        [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable
        public DynamicMethod(string name,
                             Type returnType,
                             Type[] parameterTypes,
                             bool restrictedSkipVisibility)
        {
            StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
 
            Init(name,
                MethodAttributes.Public | MethodAttributes.Static,
                CallingConventions.Standard,
                returnType,
                parameterTypes,
                null,   // owner
                null,   // m
                restrictedSkipVisibility,
                true,
                ref stackMark);  // transparentMethod
        }
 
        #if FEATURE_CORECLR
        [System.Security.SecurityCritical] // auto-generated
        #else
        [System.Security.SecuritySafeCritical]
        #endif
        [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable
        public DynamicMethod(string name, 
                             Type returnType, 
                             Type[] parameterTypes, 
                             Module m) {
            StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
            PerformSecurityCheck(m, ref stackMark, false);
            Init(name,
                MethodAttributes.Public | MethodAttributes.Static,
                CallingConventions.Standard,
                returnType,
                parameterTypes,
                null,   // owner
                m,      // m
                false,  // skipVisibility
                false,
                ref stackMark);  // transparentMethod
        }
 
        #if FEATURE_CORECLR
        [System.Security.SecurityCritical] // auto-generated
        #else
        [System.Security.SecuritySafeCritical]
        #endif
        [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable
        public DynamicMethod(string name, 
                             Type returnType, 
                             Type[] parameterTypes, 
                             Module m, 
                             bool skipVisibility) {
            StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
            PerformSecurityCheck(m, ref stackMark, skipVisibility);
            Init(name,
                MethodAttributes.Public | MethodAttributes.Static,
                CallingConventions.Standard,
                returnType,
                parameterTypes,
                null,   // owner
                m,      // m
                skipVisibility,
                false,
                ref stackMark); // transparentMethod
        }
 
        #if FEATURE_CORECLR
        [System.Security.SecurityCritical] // auto-generated
        #else
        [System.Security.SecuritySafeCritical]
        #endif
        [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable
        public DynamicMethod(string name, 
                             MethodAttributes attributes, 
                             CallingConventions callingConvention, 
                             Type returnType, 
                             Type[] parameterTypes, 
                             Module m, 
                             bool skipVisibility) {
            StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
            PerformSecurityCheck(m, ref stackMark, skipVisibility);
            Init(name,
                attributes,
                callingConvention,
                returnType,
                parameterTypes,
                null,   // owner
                m,      // m
                skipVisibility,
                false,
                ref stackMark); // transparentMethod
        }
 
        #if FEATURE_CORECLR
        [System.Security.SecurityCritical] // auto-generated
        #else
        [System.Security.SecuritySafeCritical]
        #endif
        [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable
        public DynamicMethod(string name, 
                             Type returnType, 
                             Type[] parameterTypes, 
                             Type owner) {
            StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
            PerformSecurityCheck(owner, ref stackMark, false);
            Init(name, 
                MethodAttributes.Public | MethodAttributes.Static, 
                CallingConventions.Standard, 
                returnType, 
                parameterTypes,
                owner,  // owner
                null,   // m
                false,  // skipVisibility
                false,
                ref stackMark); // transparentMethod
        }
        
        #if FEATURE_CORECLR
        [System.Security.SecurityCritical] // auto-generated
        #else
        [System.Security.SecuritySafeCritical]
        #endif
        [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable
        public DynamicMethod(string name, 
                             Type returnType, 
                             Type[] parameterTypes, 
                             Type owner, 
                             bool skipVisibility) {
            StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
            PerformSecurityCheck(owner, ref stackMark, skipVisibility);
            Init(name, 
                MethodAttributes.Public | MethodAttributes.Static, 
                CallingConventions.Standard, 
                returnType, 
                parameterTypes, 
                owner,  // owner
                null,   // m
                skipVisibility,
                false,
                ref stackMark); // transparentMethod
        }
        
        #if FEATURE_CORECLR
        [System.Security.SecurityCritical] // auto-generated
        #else
        [System.Security.SecuritySafeCritical]
        #endif
        [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable
        public DynamicMethod(string name, 
                             MethodAttributes attributes, 
                             CallingConventions callingConvention, 
                             Type returnType, 
                             Type[] parameterTypes, 
                             Type owner, 
                             bool skipVisibility) {
            StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
            PerformSecurityCheck(owner, ref stackMark, skipVisibility);
            Init(name, 
                attributes, 
                callingConvention, 
                returnType, 
                parameterTypes, 
                owner,  // owner
                null,   // m
                skipVisibility, 
                false,
                ref stackMark); // transparentMethod
        }
 
        // helpers for intialization
 
        static private void CheckConsistency(MethodAttributes attributes, CallingConventions callingConvention) {
            // only static public for method attributes
            if ((attributes & ~MethodAttributes.MemberAccessMask) != MethodAttributes.Static)
                throw new NotSupportedException(Environment.GetResourceString("NotSupported_DynamicMethodFlags"));
            if ((attributes & MethodAttributes.MemberAccessMask) != MethodAttributes.Public)
                throw new NotSupportedException(Environment.GetResourceString("NotSupported_DynamicMethodFlags"));
            Contract.EndContractBlock();
 
            // only standard or varargs supported
            if (callingConvention != CallingConventions.Standard && callingConvention != CallingConventions.VarArgs)
                throw new NotSupportedException(Environment.GetResourceString("NotSupported_DynamicMethodFlags"));
            
            // vararg is not supported at the moment
            if (callingConvention == CallingConventions.VarArgs)
                throw new NotSupportedException(Environment.GetResourceString("NotSupported_DynamicMethodFlags"));
        }
 
        // We create a transparent assembly to host DynamicMethods. Since the assembly does not have any
        // non-public fields (or any fields at all), it is a safe anonymous assembly to host DynamicMethods
        [System.Security.SecurityCritical]  // auto-generated
        [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable
        private static RuntimeModule GetDynamicMethodsModule()
        {
            if (s_anonymouslyHostedDynamicMethodsModule != null)
                return s_anonymouslyHostedDynamicMethodsModule;
 
            lock (s_anonymouslyHostedDynamicMethodsModuleLock)
            {
                if (s_anonymouslyHostedDynamicMethodsModule != null)
                    return s_anonymouslyHostedDynamicMethodsModule;
 
                ConstructorInfo transparencyCtor = typeof(SecurityTransparentAttribute).GetConstructor(Type.EmptyTypes);
                CustomAttributeBuilder transparencyAttribute = new CustomAttributeBuilder(transparencyCtor, EmptyArray<Object>.Value);
                List<CustomAttributeBuilder> assemblyAttributes = new List<CustomAttributeBuilder>();
                assemblyAttributes.Add(transparencyAttribute);
#if !FEATURE_CORECLR
                // On the desktop, we need to use the security rule set level 1 for anonymously hosted
                // dynamic methods.  In level 2, transparency rules are strictly enforced, which leads to
                // errors when a fully trusted application causes a dynamic method to be generated that tries
                // to call a method with a LinkDemand or a SecurityCritical method.  To retain compatibility
                // with the v2.0 and v3.x frameworks, these calls should be allowed.
                //
                // If this rule set was not explicitly called out, then the anonymously hosted dynamic methods
                // assembly would inherit the rule set from the creating assembly - which would cause it to
                // be level 2 because mscorlib.dll is using the level 2 rules.
                ConstructorInfo securityRulesCtor = typeof(SecurityRulesAttribute).GetConstructor(new Type[] { typeof(SecurityRuleSet) });
                CustomAttributeBuilder securityRulesAttribute =
                    new CustomAttributeBuilder(securityRulesCtor, new object[] { SecurityRuleSet.Level1 });
                assemblyAttributes.Add(securityRulesAttribute);
#endif // !FEATURE_CORECLR
 
                AssemblyName assemblyName = new AssemblyName("Anonymously Hosted DynamicMethods Assembly");
                StackCrawlMark stackMark = StackCrawlMark.LookForMe;
 
                AssemblyBuilder assembly = AssemblyBuilder.InternalDefineDynamicAssembly(
                    assemblyName,
                    AssemblyBuilderAccess.Run,
                    null, null, null, null, null,
                    ref stackMark,
                    assemblyAttributes,
                    SecurityContextSource.CurrentAssembly);
 
                AppDomain.PublishAnonymouslyHostedDynamicMethodsAssembly(assembly.GetNativeHandle());
 
                // this always gets the internal module.
                s_anonymouslyHostedDynamicMethodsModule = (InternalModuleBuilder)assembly.ManifestModule;
            }
 
            return s_anonymouslyHostedDynamicMethodsModule;
        }
 
        [System.Security.SecurityCritical]  // auto-generated
        private unsafe void Init(String name, 
                                 MethodAttributes attributes, 
                                 CallingConventions callingConvention, 
                                 Type returnType, 
                                 Type[] signature, 
                                 Type owner, 
                                 Module m, 
                                 bool skipVisibility,
                                 bool transparentMethod,
                                 ref StackCrawlMark stackMark)
        {
            DynamicMethod.CheckConsistency(attributes, callingConvention);
 
            // check and store the signature
            if (signature != null) {
                m_parameterTypes = new RuntimeType[signature.Length];
                for (int i = 0; i < signature.Length; i++) {
                    if (signature[i] == null) 
                        throw new ArgumentException(Environment.GetResourceString("Arg_InvalidTypeInSignature"));
                    m_parameterTypes[i] = signature[i].UnderlyingSystemType as RuntimeType;
                    if ( m_parameterTypes[i] == null || !(m_parameterTypes[i] is RuntimeType) || m_parameterTypes[i] == (RuntimeType)typeof(void) ) 
                        throw new ArgumentException(Environment.GetResourceString("Arg_InvalidTypeInSignature"));
                }
            }
            else {
                m_parameterTypes = new RuntimeType[0];
            }
            
            // check and store the return value
            m_returnType = (returnType == null) ? (RuntimeType)typeof(void) : returnType.UnderlyingSystemType as RuntimeType;
            if ( (m_returnType == null) || !(m_returnType is RuntimeType) || m_returnType.IsByRef ) 
                throw new NotSupportedException(Environment.GetResourceString("Arg_InvalidTypeInRetType"));
 
            if (transparentMethod)
            {
                Contract.Assert(owner == null && m == null, "owner and m cannot be set for transparent methods");
                m_module = GetDynamicMethodsModule();
                if (skipVisibility)
                {
                    m_restrictedSkipVisibility = true;
                }
 
#if FEATURE_COMPRESSEDSTACK
                m_creationContext = CompressedStack.Capture();
#endif // FEATURE_COMPRESSEDSTACK
            }
            else
            {
                Contract.Assert(m != null || owner != null, "PerformSecurityCheck should ensure that either m or owner is set");
                Contract.Assert(m == null || !m.Equals(s_anonymouslyHostedDynamicMethodsModule), "The user cannot explicitly use this assembly");
                Contract.Assert(m == null || owner == null, "m and owner cannot both be set");
 
                if (m != null)
                    m_module = m.ModuleHandle.GetRuntimeModule(); // this returns the underlying module for all RuntimeModule and ModuleBuilder objects.
                else
                {
                    RuntimeType rtOwner = null;
                    if (owner != null)
                        rtOwner = owner.UnderlyingSystemType as RuntimeType;
 
                    if (rtOwner != null)
                    {
                        if (rtOwner.HasElementType || rtOwner.ContainsGenericParameters
                            || rtOwner.IsGenericParameter || rtOwner.IsInterface)
                            throw new ArgumentException(Environment.GetResourceString("Argument_InvalidTypeForDynamicMethod"));
 
                        m_typeOwner = rtOwner;
                        m_module = rtOwner.GetRuntimeModule();
                    }
                }
 
                m_skipVisibility = skipVisibility;
            }
 
            // initialize remaining fields
            m_ilGenerator = null;
            m_fInitLocals = true;
            m_methodHandle = null;
 
            if (name == null) 
                throw new ArgumentNullException("name");
 
#if FEATURE_APPX
            if (AppDomain.ProfileAPICheck)
            {
                if (m_creatorAssembly == null)
                    m_creatorAssembly = RuntimeAssembly.GetExecutingAssembly(ref stackMark);
 
                if (m_creatorAssembly != null && !m_creatorAssembly.IsFrameworkAssembly())
                    m_profileAPICheck = true;
            }
#endif // FEATURE_APPX
 
            m_dynMethod = new RTDynamicMethod(this, name, attributes, callingConvention);
        }
 
        [System.Security.SecurityCritical]  // auto-generated
        private void PerformSecurityCheck(Module m, ref StackCrawlMark stackMark, bool skipVisibility)
        {
            if (m == null) 
                throw new ArgumentNullException("m");
            Contract.EndContractBlock();
 
            RuntimeModule rtModule;
            ModuleBuilder mb = m as ModuleBuilder;
            if (mb != null)
                rtModule = mb.InternalModule;
            else
                rtModule = m as RuntimeModule;
 
            if (rtModule == null)
            {
                throw new ArgumentException(Environment.GetResourceString("Argument_MustBeRuntimeModule"), "m");
            }
 
            // The user cannot explicitly use this assembly
            if (rtModule == s_anonymouslyHostedDynamicMethodsModule)
                throw new ArgumentException(Environment.GetResourceString("Argument_InvalidValue"), "m");
 
            // ask for member access if skip visibility
            if (skipVisibility) 
                new ReflectionPermission(ReflectionPermissionFlag.MemberAccess).Demand();
 
#if !FEATURE_CORECLR
            // ask for control evidence if outside of the caller assembly
            RuntimeType callingType = RuntimeMethodHandle.GetCallerType(ref stackMark);
            m_creatorAssembly = callingType.GetRuntimeAssembly();
            if (m.Assembly != m_creatorAssembly)
            {
                // Demand the permissions of the assembly where the DynamicMethod will live
                CodeAccessSecurityEngine.ReflectionTargetDemandHelper(PermissionType.SecurityControlEvidence,
                                                                      m.Assembly.PermissionSet);
            }
#else //FEATURE_CORECLR
#pragma warning disable 618
                new SecurityPermission(SecurityPermissionFlag.ControlEvidence).Demand();
#pragma warning restore 618
#endif //FEATURE_CORECLR
        }
 
        [System.Security.SecurityCritical]  // auto-generated
        private void PerformSecurityCheck(Type owner, ref StackCrawlMark stackMark, bool skipVisibility)
        {
            if (owner == null)
                throw new ArgumentNullException("owner");
 
            RuntimeType rtOwner = owner as RuntimeType;
            if (rtOwner == null)
                rtOwner = owner.UnderlyingSystemType as RuntimeType;
 
            if (rtOwner == null)
                throw new ArgumentNullException("owner", Environment.GetResourceString("Argument_MustBeRuntimeType"));
 
            // get the type the call is coming from
            RuntimeType callingType = RuntimeMethodHandle.GetCallerType(ref stackMark);
 
            // ask for member access if skip visibility
            if (skipVisibility) 
                new ReflectionPermission(ReflectionPermissionFlag.MemberAccess).Demand();
            else
            {
                // if the call is not coming from the same class ask for member access
                if (callingType != rtOwner)
                    new ReflectionPermission(ReflectionPermissionFlag.MemberAccess).Demand();
            }
#if !FEATURE_CORECLR
            m_creatorAssembly = callingType.GetRuntimeAssembly();
 
            // ask for control evidence if outside of the caller module
            if (rtOwner.Assembly != m_creatorAssembly)
            {
                // Demand the permissions of the assembly where the DynamicMethod will live
                CodeAccessSecurityEngine.ReflectionTargetDemandHelper(PermissionType.SecurityControlEvidence,
                                                                      owner.Assembly.PermissionSet);
            }
#else //FEATURE_CORECLR
#pragma warning disable 618
                new SecurityPermission(SecurityPermissionFlag.ControlEvidence).Demand();
#pragma warning restore 618
#endif //FEATURE_CORECLR
        }
 
        //
        // Delegate and method creation
        //
 
        [System.Security.SecuritySafeCritical]  // auto-generated
        [System.Runtime.InteropServices.ComVisible(true)]
        public sealed override Delegate CreateDelegate(Type delegateType) {
            if (m_restrictedSkipVisibility)
            {
                // Compile the method since accessibility checks are done as part of compilation.
                GetMethodDescriptor();
                System.Runtime.CompilerServices.RuntimeHelpers._CompileMethod(m_methodHandle);
            }
 
            MulticastDelegate d = (MulticastDelegate)Delegate.CreateDelegateNoSecurityCheck(delegateType, null, GetMethodDescriptor());
            // stash this MethodInfo by brute force.  
            d.StoreDynamicMethod(GetMethodInfo());
            return d;
        }
 
        [System.Security.SecuritySafeCritical]  // auto-generated
        [System.Runtime.InteropServices.ComVisible(true)]
        public sealed override Delegate CreateDelegate(Type delegateType, Object target) {
            if (m_restrictedSkipVisibility)
            {
                // Compile the method since accessibility checks are done as part of compilation
                GetMethodDescriptor();
                System.Runtime.CompilerServices.RuntimeHelpers._CompileMethod(m_methodHandle);
            }
 
            MulticastDelegate d = (MulticastDelegate)Delegate.CreateDelegateNoSecurityCheck(delegateType, target, GetMethodDescriptor());
            // stash this MethodInfo by brute force. 
            d.StoreDynamicMethod(GetMethodInfo());
            return d;
        }
 
#if FEATURE_APPX
        internal bool ProfileAPICheck
        {
            get
            {
                return m_profileAPICheck;
            }
 
            [FriendAccessAllowed]
            set
            {
                m_profileAPICheck = value;
            }
        }
#endif
 
        // This is guaranteed to return a valid handle
        [System.Security.SecurityCritical]  // auto-generated
        internal unsafe RuntimeMethodHandle GetMethodDescriptor() {
            if (m_methodHandle == null) {
                lock (this) {
                    if (m_methodHandle == null) {
                        if (m_DynamicILInfo != null)
                            m_DynamicILInfo.GetCallableMethod(m_module, this);
                        else {
                            if (m_ilGenerator == null || m_ilGenerator.ILOffset == 0)
                                throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_BadEmptyMethodBody", Name));
    
                            m_ilGenerator.GetCallableMethod(m_module, this);
                        }
                    }
                }
            }
            return new RuntimeMethodHandle(m_methodHandle);
        }
 
        //
        // MethodInfo api. They mostly forward to RTDynamicMethod
        //
 
        public override String ToString() { return m_dynMethod.ToString(); }
 
        public override String Name { get { return m_dynMethod.Name; } }
 
        public override Type DeclaringType { get { return m_dynMethod.DeclaringType; } }
 
        public override Type ReflectedType { get { return m_dynMethod.ReflectedType; } }
 
        public override Module Module { get { return m_dynMethod.Module; } }
 
        // we cannot return a MethodHandle because we cannot track it via GC so this method is off limits
        public override RuntimeMethodHandle MethodHandle { get { throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_NotAllowedInDynamicMethod")); } }
 
        public override MethodAttributes Attributes { get { return m_dynMethod.Attributes; } }
 
        public override CallingConventions CallingConvention { get { return m_dynMethod.CallingConvention; } }
 
        public override MethodInfo GetBaseDefinition() { return this; }
 
        [Pure]
        public override ParameterInfo[] GetParameters() { return m_dynMethod.GetParameters(); }
 
        public override MethodImplAttributes GetMethodImplementationFlags() { return m_dynMethod.GetMethodImplementationFlags(); }
 
        //
        // Security transparency accessors
        //
        // Since the dynamic method may not be JITed yet, we don't always have the runtime method handle
        // which is needed to determine the official runtime transparency status of the dynamic method.  We
        // fall back to saying that the dynamic method matches the transparency of its containing module
        // until we get a JITed version, since dynamic methods cannot have attributes of their own.
        //
 
        public override bool IsSecurityCritical
        {
            [SecuritySafeCritical]
            get
            {
                if (m_methodHandle != null)
                {
                    return RuntimeMethodHandle.IsSecurityCritical(m_methodHandle);
                }
                else if (m_typeOwner != null)
                {
                    RuntimeAssembly assembly = m_typeOwner.Assembly as RuntimeAssembly;
                    Contract.Assert(assembly != null);
 
                    return assembly.IsAllSecurityCritical();
                }
                else
                {
                    RuntimeAssembly assembly = m_module.Assembly as RuntimeAssembly;
                    Contract.Assert(assembly != null);
 
                    return assembly.IsAllSecurityCritical();
                }
            }
        }
 
        public override bool IsSecuritySafeCritical
        {
            [SecuritySafeCritical]
            get
            {
                if (m_methodHandle != null)
                {
                    return RuntimeMethodHandle.IsSecuritySafeCritical(m_methodHandle);
                }
                else if (m_typeOwner != null)
                {
                    RuntimeAssembly assembly = m_typeOwner.Assembly as RuntimeAssembly;
                    Contract.Assert(assembly != null);
 
                    return assembly.IsAllPublicAreaSecuritySafeCritical();
                }
                else
                {
                    RuntimeAssembly assembly = m_module.Assembly as RuntimeAssembly;
                    Contract.Assert(assembly != null);
 
                    return assembly.IsAllSecuritySafeCritical();
                }
            }
        }
 
        public override bool IsSecurityTransparent
        {
            [SecuritySafeCritical]
            get
            {
                if (m_methodHandle != null)
                {
                    return RuntimeMethodHandle.IsSecurityTransparent(m_methodHandle);
                }
                else if (m_typeOwner != null)
                {
                    RuntimeAssembly assembly = m_typeOwner.Assembly as RuntimeAssembly;
                    Contract.Assert(assembly != null);
 
                    return !assembly.IsAllSecurityCritical();
                }
                else
                {
                    RuntimeAssembly assembly = m_module.Assembly as RuntimeAssembly;
                    Contract.Assert(assembly != null);
 
                    return !assembly.IsAllSecurityCritical();
                }
            }
        }
 
        [System.Security.SecuritySafeCritical]  // auto-generated
        public override Object Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture) {
            if ((CallingConvention & CallingConventions.VarArgs) == CallingConventions.VarArgs)
                throw new NotSupportedException(Environment.GetResourceString("NotSupported_CallToVarArg"));
            Contract.EndContractBlock();
 
            //
            // 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.
            //
 
            RuntimeMethodHandle method = GetMethodDescriptor();
            // ignore obj since it's a static method
 
            // create a signature object
            Signature sig = new Signature(
                this.m_methodHandle, m_parameterTypes, m_returnType, CallingConvention);
 
 
            // verify arguments
            int formalCount = sig.Arguments.Length;
            int actualCount = (parameters != null) ? parameters.Length : 0;
            if (formalCount != actualCount)
                throw new TargetParameterCountException(Environment.GetResourceString("Arg_ParmCnt"));
 
            // if we are here we passed all the previous checks. Time to look at the arguments
            Object retValue = null;
            if (actualCount > 0)
            {
                Object[] arguments = CheckArguments(parameters, binder, invokeAttr, culture, sig);
                retValue = RuntimeMethodHandle.InvokeMethod(null, arguments, sig, false);
                // copy out. This should be made only if ByRef are present.
                for (int index = 0; index < arguments.Length; index++)
                    parameters[index] = arguments[index];
            }
            else
            {
                retValue = RuntimeMethodHandle.InvokeMethod(null, null, sig, false);
            }
 
            GC.KeepAlive(this);
            return retValue;
        }
 
        public override Object[] GetCustomAttributes(Type attributeType, bool inherit)
        {
            return m_dynMethod.GetCustomAttributes(attributeType, inherit); 
        }
 
        public override Object[] GetCustomAttributes(bool inherit) { return m_dynMethod.GetCustomAttributes(inherit); }
 
        public override bool IsDefined(Type attributeType, bool inherit) { return m_dynMethod.IsDefined(attributeType, inherit); }
 
        public override Type ReturnType { get { return m_dynMethod.ReturnType; } }
 
        public override ParameterInfo ReturnParameter { get { return m_dynMethod.ReturnParameter; } }
 
        public override ICustomAttributeProvider ReturnTypeCustomAttributes { get { return m_dynMethod.ReturnTypeCustomAttributes; } }
 
        //
        // DynamicMethod specific methods
        //
 
        public ParameterBuilder DefineParameter(int position, ParameterAttributes attributes, String parameterName) {
            if (position < 0 || position > m_parameterTypes.Length)
                throw new ArgumentOutOfRangeException(Environment.GetResourceString("ArgumentOutOfRange_ParamSequence"));
            position--; // it's 1 based. 0 is the return value
        
            if (position >= 0) {
                ParameterInfo[] parameters = m_dynMethod.LoadParameters();
                parameters[position].SetName(parameterName);
                parameters[position].SetAttributes(attributes);
            }
            return null;
        }
 
        [System.Security.SecuritySafeCritical]  // auto-generated
        public DynamicILInfo GetDynamicILInfo()
        {
#pragma warning disable 618
            new SecurityPermission(SecurityPermissionFlag.UnmanagedCode).Demand();
#pragma warning restore 618
 
            if (m_DynamicILInfo != null)
                return m_DynamicILInfo;
 
            return GetDynamicILInfo(new DynamicScope());
        }
 
        [System.Security.SecurityCritical]  // auto-generated
        internal DynamicILInfo GetDynamicILInfo(DynamicScope scope)
        {
            if (m_DynamicILInfo == null)
            {
                byte[] methodSignature = SignatureHelper.GetMethodSigHelper(
                        null, CallingConvention, ReturnType, null, null, m_parameterTypes, null, null).GetSignature(true);
                m_DynamicILInfo = new DynamicILInfo(scope, this, methodSignature);
            }
 
            return m_DynamicILInfo;
        }
 
        public ILGenerator GetILGenerator() {
            return GetILGenerator(64);
        }
 
       [System.Security.SecuritySafeCritical]  // auto-generated
       public ILGenerator GetILGenerator(int streamSize) 
        {
            if (m_ilGenerator == null)
            {
                byte[] methodSignature = SignatureHelper.GetMethodSigHelper(
                    null, CallingConvention, ReturnType, null, null, m_parameterTypes, null, null).GetSignature(true);
                m_ilGenerator = new DynamicILGenerator(this, methodSignature, streamSize);
            }
            return m_ilGenerator;
        }
 
        public bool InitLocals {
            get {return m_fInitLocals;}
            set {m_fInitLocals = value;}
        }
 
        //
        // Internal API
        //
         
        internal MethodInfo GetMethodInfo() {
            return m_dynMethod;
        }
 
        //////////////////////////////////////////////////////////////////////////////////////////////
        // RTDynamicMethod
        //
        // this is actually the real runtime instance of a method info that gets used for invocation
        // We need this so we never leak the DynamicMethod out via an exception.
        // This way the DynamicMethod creator is the only one responsible for DynamicMethod access,
        // and can control exactly who gets access to it.
        //
        internal class RTDynamicMethod : MethodInfo {
 
            internal DynamicMethod m_owner;
            ParameterInfo[] m_parameters;
            String m_name;
            MethodAttributes m_attributes;
            CallingConventions m_callingConvention;
 
            //
            // ctors
            //
            private RTDynamicMethod() {}
 
            internal RTDynamicMethod(DynamicMethod owner, String name, MethodAttributes attributes, CallingConventions callingConvention) {
                m_owner = owner;
                m_name = name;
                m_attributes = attributes;
                m_callingConvention = callingConvention;
            }
            
            //
            // MethodInfo api
            //
            public override String ToString() {
                return ReturnType.FormatTypeName() + " " + FormatNameAndSig();
            }
 
            public override String Name { 
                get { return m_name; }
            }
 
            public override Type DeclaringType { 
                get { return null; }
            }
 
            public override Type ReflectedType { 
                get { return null; }
            }
 
            public override Module Module { 
                get { return m_owner.m_module; }
            }
 
            public override RuntimeMethodHandle MethodHandle { 
                get { throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_NotAllowedInDynamicMethod")); }   
            }
 
            public override MethodAttributes Attributes { 
                get { return m_attributes; }
            }    
 
            public override CallingConventions CallingConvention { 
                get { return m_callingConvention; }
            }
            
            public override MethodInfo GetBaseDefinition() {
                return this;
            }
            
            [Pure]
            public override ParameterInfo[] GetParameters() {
                ParameterInfo[] privateParameters = LoadParameters();
                ParameterInfo[] parameters = new ParameterInfo[privateParameters.Length];
                Array.Copy(privateParameters, parameters, privateParameters.Length);
                return parameters;
            }
            
            public override MethodImplAttributes GetMethodImplementationFlags() {
                return MethodImplAttributes.IL | MethodImplAttributes.NoInlining;
            }
 
            public override Object Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture) {
                // We want the creator of the DynamicMethod to control who has access to the
                // DynamicMethod (just like we do for delegates). However, a user can get to
                // the corresponding RTDynamicMethod using Exception.TargetSite, StackFrame.GetMethod, etc.
                // If we allowed use of RTDynamicMethod, the creator of the DynamicMethod would
                // not be able to bound access to the DynamicMethod. Hence, we do not allow
                // direct use of RTDynamicMethod.
                throw new ArgumentException(Environment.GetResourceString("Argument_MustBeRuntimeMethodInfo"), "this");
            }
 
            public override Object[] GetCustomAttributes(Type attributeType, bool inherit) {
                if (attributeType == null)
                    throw new ArgumentNullException("attributeType");
                Contract.EndContractBlock();
 
                if (attributeType.IsAssignableFrom(typeof(MethodImplAttribute))) 
                    return new Object[] { new MethodImplAttribute(GetMethodImplementationFlags()) };
                else
                    return EmptyArray<Object>.Value;
            }
 
            public override Object[] GetCustomAttributes(bool inherit) {
                // support for MethodImplAttribute PCA
                return new Object[] { new MethodImplAttribute(GetMethodImplementationFlags()) };
            }
            
            public override bool IsDefined(Type attributeType, bool inherit) {
                if (attributeType == null)
                    throw new ArgumentNullException("attributeType");
                Contract.EndContractBlock();
 
                if (attributeType.IsAssignableFrom(typeof(MethodImplAttribute))) 
                    return true;
                else
                    return false;
            }
 
            public override bool IsSecurityCritical
            {
                get { return m_owner.IsSecurityCritical; }
            }
 
            public override bool IsSecuritySafeCritical
            {
                get { return m_owner.IsSecuritySafeCritical; }
            }
 
            public override bool IsSecurityTransparent
            {
                get { return m_owner.IsSecurityTransparent; }
            }
 
            public override Type ReturnType
            {
                get
                {
                    return m_owner.m_returnType;
                }
            }
 
            public override ParameterInfo ReturnParameter { 
                get { return null; } 
            }
 
            public override ICustomAttributeProvider ReturnTypeCustomAttributes {
                get { return GetEmptyCAHolder(); }
            }
 
            //
            // private implementation
            //
 
            internal ParameterInfo[] LoadParameters() {
                if (m_parameters == null) {
                    Type[] parameterTypes = m_owner.m_parameterTypes;
                    ParameterInfo[] parameters = new ParameterInfo[parameterTypes.Length];
                    for (int i = 0; i < parameterTypes.Length; i++) 
                        parameters[i] = new RuntimeParameterInfo(this, null, parameterTypes[i], i);
                    if (m_parameters == null) 
                        // should we interlockexchange?
                        m_parameters = parameters;
                }
                return m_parameters;
            }
            
            // private implementation of CA for the return type
            private ICustomAttributeProvider GetEmptyCAHolder() {
                return new EmptyCAHolder();
            }
 
            ///////////////////////////////////////////////////
            // EmptyCAHolder
            private class EmptyCAHolder : ICustomAttributeProvider {
                internal EmptyCAHolder() {}
 
                Object[] ICustomAttributeProvider.GetCustomAttributes(Type attributeType, bool inherit) {
                    return EmptyArray<Object>.Value;
                }
 
                Object[] ICustomAttributeProvider.GetCustomAttributes(bool inherit) {
                    return EmptyArray<Object>.Value;
                }
 
                bool ICustomAttributeProvider.IsDefined (Type attributeType, bool inherit) {
                    return false;
                }
            }
 
        }
    
    }
 
}