Updates referencesource to .NET 4.7
[mono.git] / mcs / class / referencesource / mscorlib / system / reflection / emit / dynamicmethod.cs
1 // ==++==
2 // 
3 //   Copyright (c) Microsoft Corporation.  All rights reserved.
4 // 
5 // ==--==
6 // <OWNER>Microsoft</OWNER>
7 // 
8
9 namespace System.Reflection.Emit
10 {
11     using System;
12     using System.Collections.Generic;
13     using CultureInfo = System.Globalization.CultureInfo;
14     using System.Reflection;
15     using System.Security;
16     using System.Security.Permissions;
17     using System.Threading;
18     using System.Runtime.CompilerServices;
19     using System.Runtime.Versioning;
20     using System.Diagnostics.Contracts;
21     using System.Runtime.InteropServices;
22
23     [System.Runtime.InteropServices.ComVisible(true)]
24     public sealed class DynamicMethod : MethodInfo
25     {
26         private RuntimeType[] m_parameterTypes;
27         internal IRuntimeMethodInfo m_methodHandle;
28         private RuntimeType m_returnType;
29         private DynamicILGenerator m_ilGenerator;
30         #if FEATURE_CORECLR
31         [System.Security.SecurityCritical] // auto-generated
32         #endif
33         private DynamicILInfo m_DynamicILInfo;
34         private bool m_fInitLocals;
35         private RuntimeModule m_module;
36         internal bool m_skipVisibility;
37         internal RuntimeType m_typeOwner; // can be null
38
39         // We want the creator of the DynamicMethod to control who has access to the
40         // DynamicMethod (just like we do for delegates). However, a user can get to
41         // the corresponding RTDynamicMethod using Exception.TargetSite, StackFrame.GetMethod, etc.
42         // If we allowed use of RTDynamicMethod, the creator of the DynamicMethod would
43         // not be able to bound access to the DynamicMethod. Hence, we need to ensure that 
44         // we do not allow direct use of RTDynamicMethod.
45         private RTDynamicMethod m_dynMethod;
46
47         // needed to keep the object alive during jitting
48         // assigned by the DynamicResolver ctor
49         internal DynamicResolver m_resolver;
50
51         // Always false unless we are in an immersive (non dev mode) process.
52 #if FEATURE_APPX
53         private bool m_profileAPICheck;
54
55         private RuntimeAssembly m_creatorAssembly;
56 #endif
57
58         internal bool m_restrictedSkipVisibility;
59         // The context when the method was created. We use this to do the RestrictedMemberAccess checks.
60         // These checks are done when the method is compiled. This can happen at an arbitrary time,
61         // when CreateDelegate or Invoke is called, or when another DynamicMethod executes OpCodes.Call.
62         // We capture the creation context so that we can do the checks against the same context,
63         // irrespective of when the method gets compiled. Note that the DynamicMethod does not know when
64         // it is ready for use since there is not API which indictates that IL generation has completed.
65 #if FEATURE_COMPRESSEDSTACK
66         internal CompressedStack m_creationContext;
67 #endif // FEATURE_COMPRESSEDSTACK
68         private static volatile InternalModuleBuilder s_anonymouslyHostedDynamicMethodsModule;
69         private static readonly object s_anonymouslyHostedDynamicMethodsModuleLock = new object();
70         
71         //
72         // class initialization (ctor and init)
73         //
74
75         private DynamicMethod() { }
76
77         [System.Security.SecuritySafeCritical]  // auto-generated
78         [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable
79         public DynamicMethod(string name,
80                              Type returnType,
81                              Type[] parameterTypes)
82         {
83             StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
84
85             Init(name, 
86                 MethodAttributes.Public | MethodAttributes.Static, 
87                 CallingConventions.Standard, 
88                 returnType, 
89                 parameterTypes,
90                 null,   // owner
91                 null,   // m
92                 false,  // skipVisibility
93                 true,
94                 ref stackMark);  // transparentMethod
95         }
96
97         [System.Security.SecuritySafeCritical]  // auto-generated
98         [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable
99         public DynamicMethod(string name,
100                              Type returnType,
101                              Type[] parameterTypes,
102                              bool restrictedSkipVisibility)
103         {
104             StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
105
106             Init(name,
107                 MethodAttributes.Public | MethodAttributes.Static,
108                 CallingConventions.Standard,
109                 returnType,
110                 parameterTypes,
111                 null,   // owner
112                 null,   // m
113                 restrictedSkipVisibility,
114                 true,
115                 ref stackMark);  // transparentMethod
116         }
117
118         #if FEATURE_CORECLR
119         [System.Security.SecurityCritical] // auto-generated
120         #else
121         [System.Security.SecuritySafeCritical]
122         #endif
123         [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable
124         public DynamicMethod(string name, 
125                              Type returnType, 
126                              Type[] parameterTypes, 
127                              Module m) {
128             StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
129             PerformSecurityCheck(m, ref stackMark, false);
130             Init(name,
131                 MethodAttributes.Public | MethodAttributes.Static,
132                 CallingConventions.Standard,
133                 returnType,
134                 parameterTypes,
135                 null,   // owner
136                 m,      // m
137                 false,  // skipVisibility
138                 false,
139                 ref stackMark);  // transparentMethod
140         }
141
142         #if FEATURE_CORECLR
143         [System.Security.SecurityCritical] // auto-generated
144         #else
145         [System.Security.SecuritySafeCritical]
146         #endif
147         [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable
148         public DynamicMethod(string name, 
149                              Type returnType, 
150                              Type[] parameterTypes, 
151                              Module m, 
152                              bool skipVisibility) {
153             StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
154             PerformSecurityCheck(m, ref stackMark, skipVisibility);
155             Init(name,
156                 MethodAttributes.Public | MethodAttributes.Static,
157                 CallingConventions.Standard,
158                 returnType,
159                 parameterTypes,
160                 null,   // owner
161                 m,      // m
162                 skipVisibility,
163                 false,
164                 ref stackMark); // transparentMethod
165         }
166
167         #if FEATURE_CORECLR
168         [System.Security.SecurityCritical] // auto-generated
169         #else
170         [System.Security.SecuritySafeCritical]
171         #endif
172         [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable
173         public DynamicMethod(string name, 
174                              MethodAttributes attributes, 
175                              CallingConventions callingConvention, 
176                              Type returnType, 
177                              Type[] parameterTypes, 
178                              Module m, 
179                              bool skipVisibility) {
180             StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
181             PerformSecurityCheck(m, ref stackMark, skipVisibility);
182             Init(name,
183                 attributes,
184                 callingConvention,
185                 returnType,
186                 parameterTypes,
187                 null,   // owner
188                 m,      // m
189                 skipVisibility,
190                 false,
191                 ref stackMark); // transparentMethod
192         }
193
194         #if FEATURE_CORECLR
195         [System.Security.SecurityCritical] // auto-generated
196         #else
197         [System.Security.SecuritySafeCritical]
198         #endif
199         [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable
200         public DynamicMethod(string name, 
201                              Type returnType, 
202                              Type[] parameterTypes, 
203                              Type owner) {
204             StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
205             PerformSecurityCheck(owner, ref stackMark, false);
206             Init(name, 
207                 MethodAttributes.Public | MethodAttributes.Static, 
208                 CallingConventions.Standard, 
209                 returnType, 
210                 parameterTypes,
211                 owner,  // owner
212                 null,   // m
213                 false,  // skipVisibility
214                 false,
215                 ref stackMark); // transparentMethod
216         }
217         
218         #if FEATURE_CORECLR
219         [System.Security.SecurityCritical] // auto-generated
220         #else
221         [System.Security.SecuritySafeCritical]
222         #endif
223         [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable
224         public DynamicMethod(string name, 
225                              Type returnType, 
226                              Type[] parameterTypes, 
227                              Type owner, 
228                              bool skipVisibility) {
229             StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
230             PerformSecurityCheck(owner, ref stackMark, skipVisibility);
231             Init(name, 
232                 MethodAttributes.Public | MethodAttributes.Static, 
233                 CallingConventions.Standard, 
234                 returnType, 
235                 parameterTypes, 
236                 owner,  // owner
237                 null,   // m
238                 skipVisibility,
239                 false,
240                 ref stackMark); // transparentMethod
241         }
242         
243         #if FEATURE_CORECLR
244         [System.Security.SecurityCritical] // auto-generated
245         #else
246         [System.Security.SecuritySafeCritical]
247         #endif
248         [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable
249         public DynamicMethod(string name, 
250                              MethodAttributes attributes, 
251                              CallingConventions callingConvention, 
252                              Type returnType, 
253                              Type[] parameterTypes, 
254                              Type owner, 
255                              bool skipVisibility) {
256             StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
257             PerformSecurityCheck(owner, ref stackMark, skipVisibility);
258             Init(name, 
259                 attributes, 
260                 callingConvention, 
261                 returnType, 
262                 parameterTypes, 
263                 owner,  // owner
264                 null,   // m
265                 skipVisibility, 
266                 false,
267                 ref stackMark); // transparentMethod
268         }
269
270         // helpers for intialization
271
272         static private void CheckConsistency(MethodAttributes attributes, CallingConventions callingConvention) {
273             // only static public for method attributes
274             if ((attributes & ~MethodAttributes.MemberAccessMask) != MethodAttributes.Static)
275                 throw new NotSupportedException(Environment.GetResourceString("NotSupported_DynamicMethodFlags"));
276             if ((attributes & MethodAttributes.MemberAccessMask) != MethodAttributes.Public)
277                 throw new NotSupportedException(Environment.GetResourceString("NotSupported_DynamicMethodFlags"));
278             Contract.EndContractBlock();
279
280             // only standard or varargs supported
281             if (callingConvention != CallingConventions.Standard && callingConvention != CallingConventions.VarArgs)
282                 throw new NotSupportedException(Environment.GetResourceString("NotSupported_DynamicMethodFlags"));
283             
284             // vararg is not supported at the moment
285             if (callingConvention == CallingConventions.VarArgs)
286                 throw new NotSupportedException(Environment.GetResourceString("NotSupported_DynamicMethodFlags"));
287         }
288
289         // We create a transparent assembly to host DynamicMethods. Since the assembly does not have any
290         // non-public fields (or any fields at all), it is a safe anonymous assembly to host DynamicMethods
291         [System.Security.SecurityCritical]  // auto-generated
292         [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable
293         private static RuntimeModule GetDynamicMethodsModule()
294         {
295             if (s_anonymouslyHostedDynamicMethodsModule != null)
296                 return s_anonymouslyHostedDynamicMethodsModule;
297
298             lock (s_anonymouslyHostedDynamicMethodsModuleLock)
299             {
300                 if (s_anonymouslyHostedDynamicMethodsModule != null)
301                     return s_anonymouslyHostedDynamicMethodsModule;
302
303                 ConstructorInfo transparencyCtor = typeof(SecurityTransparentAttribute).GetConstructor(Type.EmptyTypes);
304                 CustomAttributeBuilder transparencyAttribute = new CustomAttributeBuilder(transparencyCtor, EmptyArray<Object>.Value);
305                 List<CustomAttributeBuilder> assemblyAttributes = new List<CustomAttributeBuilder>();
306                 assemblyAttributes.Add(transparencyAttribute);
307 #if !FEATURE_CORECLR
308                 // On the desktop, we need to use the security rule set level 1 for anonymously hosted
309                 // dynamic methods.  In level 2, transparency rules are strictly enforced, which leads to
310                 // errors when a fully trusted application causes a dynamic method to be generated that tries
311                 // to call a method with a LinkDemand or a SecurityCritical method.  To retain compatibility
312                 // with the v2.0 and v3.x frameworks, these calls should be allowed.
313                 //
314                 // If this rule set was not explicitly called out, then the anonymously hosted dynamic methods
315                 // assembly would inherit the rule set from the creating assembly - which would cause it to
316                 // be level 2 because mscorlib.dll is using the level 2 rules.
317                 ConstructorInfo securityRulesCtor = typeof(SecurityRulesAttribute).GetConstructor(new Type[] { typeof(SecurityRuleSet) });
318                 CustomAttributeBuilder securityRulesAttribute =
319                     new CustomAttributeBuilder(securityRulesCtor, new object[] { SecurityRuleSet.Level1 });
320                 assemblyAttributes.Add(securityRulesAttribute);
321 #endif // !FEATURE_CORECLR
322
323                 AssemblyName assemblyName = new AssemblyName("Anonymously Hosted DynamicMethods Assembly");
324                 StackCrawlMark stackMark = StackCrawlMark.LookForMe;
325
326                 AssemblyBuilder assembly = AssemblyBuilder.InternalDefineDynamicAssembly(
327                     assemblyName,
328                     AssemblyBuilderAccess.Run,
329                     null, null, null, null, null,
330                     ref stackMark,
331                     assemblyAttributes,
332                     SecurityContextSource.CurrentAssembly);
333
334                 AppDomain.PublishAnonymouslyHostedDynamicMethodsAssembly(assembly.GetNativeHandle());
335
336                 // this always gets the internal module.
337                 s_anonymouslyHostedDynamicMethodsModule = (InternalModuleBuilder)assembly.ManifestModule;
338             }
339
340             return s_anonymouslyHostedDynamicMethodsModule;
341         }
342
343         [System.Security.SecurityCritical]  // auto-generated
344         private unsafe void Init(String name, 
345                                  MethodAttributes attributes, 
346                                  CallingConventions callingConvention, 
347                                  Type returnType, 
348                                  Type[] signature, 
349                                  Type owner, 
350                                  Module m, 
351                                  bool skipVisibility,
352                                  bool transparentMethod,
353                                  ref StackCrawlMark stackMark)
354         {
355             DynamicMethod.CheckConsistency(attributes, callingConvention);
356
357             // check and store the signature
358             if (signature != null) {
359                 m_parameterTypes = new RuntimeType[signature.Length];
360                 for (int i = 0; i < signature.Length; i++) {
361                     if (signature[i] == null) 
362                         throw new ArgumentException(Environment.GetResourceString("Arg_InvalidTypeInSignature"));
363                     m_parameterTypes[i] = signature[i].UnderlyingSystemType as RuntimeType;
364                     if ( m_parameterTypes[i] == null || !(m_parameterTypes[i] is RuntimeType) || m_parameterTypes[i] == (RuntimeType)typeof(void) ) 
365                         throw new ArgumentException(Environment.GetResourceString("Arg_InvalidTypeInSignature"));
366                 }
367             }
368             else {
369                 m_parameterTypes = new RuntimeType[0];
370             }
371             
372             // check and store the return value
373             m_returnType = (returnType == null) ? (RuntimeType)typeof(void) : returnType.UnderlyingSystemType as RuntimeType;
374             if ( (m_returnType == null) || !(m_returnType is RuntimeType) || m_returnType.IsByRef ) 
375                 throw new NotSupportedException(Environment.GetResourceString("Arg_InvalidTypeInRetType"));
376
377             if (transparentMethod)
378             {
379                 Contract.Assert(owner == null && m == null, "owner and m cannot be set for transparent methods");
380                 m_module = GetDynamicMethodsModule();
381                 if (skipVisibility)
382                 {
383                     m_restrictedSkipVisibility = true;
384                 }
385
386 #if FEATURE_COMPRESSEDSTACK
387                 m_creationContext = CompressedStack.Capture();
388 #endif // FEATURE_COMPRESSEDSTACK
389             }
390             else
391             {
392                 Contract.Assert(m != null || owner != null, "PerformSecurityCheck should ensure that either m or owner is set");
393                 Contract.Assert(m == null || !m.Equals(s_anonymouslyHostedDynamicMethodsModule), "The user cannot explicitly use this assembly");
394                 Contract.Assert(m == null || owner == null, "m and owner cannot both be set");
395
396                 if (m != null)
397                     m_module = m.ModuleHandle.GetRuntimeModule(); // this returns the underlying module for all RuntimeModule and ModuleBuilder objects.
398                 else
399                 {
400                     RuntimeType rtOwner = null;
401                     if (owner != null)
402                         rtOwner = owner.UnderlyingSystemType as RuntimeType;
403
404                     if (rtOwner != null)
405                     {
406                         if (rtOwner.HasElementType || rtOwner.ContainsGenericParameters
407                             || rtOwner.IsGenericParameter || rtOwner.IsInterface)
408                             throw new ArgumentException(Environment.GetResourceString("Argument_InvalidTypeForDynamicMethod"));
409
410                         m_typeOwner = rtOwner;
411                         m_module = rtOwner.GetRuntimeModule();
412                     }
413                 }
414
415                 m_skipVisibility = skipVisibility;
416             }
417
418             // initialize remaining fields
419             m_ilGenerator = null;
420             m_fInitLocals = true;
421             m_methodHandle = null;
422
423             if (name == null) 
424                 throw new ArgumentNullException("name");
425
426 #if FEATURE_APPX
427             if (AppDomain.ProfileAPICheck)
428             {
429                 if (m_creatorAssembly == null)
430                     m_creatorAssembly = RuntimeAssembly.GetExecutingAssembly(ref stackMark);
431
432                 if (m_creatorAssembly != null && !m_creatorAssembly.IsFrameworkAssembly())
433                     m_profileAPICheck = true;
434             }
435 #endif // FEATURE_APPX
436
437             m_dynMethod = new RTDynamicMethod(this, name, attributes, callingConvention);
438         }
439
440         [System.Security.SecurityCritical]  // auto-generated
441         private void PerformSecurityCheck(Module m, ref StackCrawlMark stackMark, bool skipVisibility)
442         {
443             if (m == null) 
444                 throw new ArgumentNullException("m");
445             Contract.EndContractBlock();
446
447             RuntimeModule rtModule;
448             ModuleBuilder mb = m as ModuleBuilder;
449             if (mb != null)
450                 rtModule = mb.InternalModule;
451             else
452                 rtModule = m as RuntimeModule;
453
454             if (rtModule == null)
455             {
456                 throw new ArgumentException(Environment.GetResourceString("Argument_MustBeRuntimeModule"), "m");
457             }
458
459             // The user cannot explicitly use this assembly
460             if (rtModule == s_anonymouslyHostedDynamicMethodsModule)
461                 throw new ArgumentException(Environment.GetResourceString("Argument_InvalidValue"), "m");
462
463             // ask for member access if skip visibility
464             if (skipVisibility) 
465                 new ReflectionPermission(ReflectionPermissionFlag.MemberAccess).Demand();
466
467 #if !FEATURE_CORECLR
468             // ask for control evidence if outside of the caller assembly
469             RuntimeType callingType = RuntimeMethodHandle.GetCallerType(ref stackMark);
470             m_creatorAssembly = callingType.GetRuntimeAssembly();
471             if (m.Assembly != m_creatorAssembly)
472             {
473                 // Demand the permissions of the assembly where the DynamicMethod will live
474                 CodeAccessSecurityEngine.ReflectionTargetDemandHelper(PermissionType.SecurityControlEvidence,
475                                                                       m.Assembly.PermissionSet);
476             }
477 #else //FEATURE_CORECLR
478 #pragma warning disable 618
479                 new SecurityPermission(SecurityPermissionFlag.ControlEvidence).Demand();
480 #pragma warning restore 618
481 #endif //FEATURE_CORECLR
482         }
483
484         [System.Security.SecurityCritical]  // auto-generated
485         private void PerformSecurityCheck(Type owner, ref StackCrawlMark stackMark, bool skipVisibility)
486         {
487             if (owner == null)
488                 throw new ArgumentNullException("owner");
489
490             RuntimeType rtOwner = owner as RuntimeType;
491             if (rtOwner == null)
492                 rtOwner = owner.UnderlyingSystemType as RuntimeType;
493
494             if (rtOwner == null)
495                 throw new ArgumentNullException("owner", Environment.GetResourceString("Argument_MustBeRuntimeType"));
496
497             // get the type the call is coming from
498             RuntimeType callingType = RuntimeMethodHandle.GetCallerType(ref stackMark);
499
500             // ask for member access if skip visibility
501             if (skipVisibility) 
502                 new ReflectionPermission(ReflectionPermissionFlag.MemberAccess).Demand();
503             else
504             {
505                 // if the call is not coming from the same class ask for member access
506                 if (callingType != rtOwner)
507                     new ReflectionPermission(ReflectionPermissionFlag.MemberAccess).Demand();
508             }
509 #if !FEATURE_CORECLR
510             m_creatorAssembly = callingType.GetRuntimeAssembly();
511
512             // ask for control evidence if outside of the caller module
513             if (rtOwner.Assembly != m_creatorAssembly)
514             {
515                 // Demand the permissions of the assembly where the DynamicMethod will live
516                 CodeAccessSecurityEngine.ReflectionTargetDemandHelper(PermissionType.SecurityControlEvidence,
517                                                                       owner.Assembly.PermissionSet);
518             }
519 #else //FEATURE_CORECLR
520 #pragma warning disable 618
521                 new SecurityPermission(SecurityPermissionFlag.ControlEvidence).Demand();
522 #pragma warning restore 618
523 #endif //FEATURE_CORECLR
524         }
525
526         //
527         // Delegate and method creation
528         //
529
530         [System.Security.SecuritySafeCritical]  // auto-generated
531         [System.Runtime.InteropServices.ComVisible(true)]
532         public sealed override Delegate CreateDelegate(Type delegateType) {
533             if (m_restrictedSkipVisibility)
534             {
535                 // Compile the method since accessibility checks are done as part of compilation.
536                 GetMethodDescriptor();
537                 System.Runtime.CompilerServices.RuntimeHelpers._CompileMethod(m_methodHandle);
538             }
539
540             MulticastDelegate d = (MulticastDelegate)Delegate.CreateDelegateNoSecurityCheck(delegateType, null, GetMethodDescriptor());
541             // stash this MethodInfo by brute force.  
542             d.StoreDynamicMethod(GetMethodInfo());
543             return d;
544         }
545
546         [System.Security.SecuritySafeCritical]  // auto-generated
547         [System.Runtime.InteropServices.ComVisible(true)]
548         public sealed override Delegate CreateDelegate(Type delegateType, Object target) {
549             if (m_restrictedSkipVisibility)
550             {
551                 // Compile the method since accessibility checks are done as part of compilation
552                 GetMethodDescriptor();
553                 System.Runtime.CompilerServices.RuntimeHelpers._CompileMethod(m_methodHandle);
554             }
555
556             MulticastDelegate d = (MulticastDelegate)Delegate.CreateDelegateNoSecurityCheck(delegateType, target, GetMethodDescriptor());
557             // stash this MethodInfo by brute force. 
558             d.StoreDynamicMethod(GetMethodInfo());
559             return d;
560         }
561
562 #if FEATURE_APPX
563         internal bool ProfileAPICheck
564         {
565             get
566             {
567                 return m_profileAPICheck;
568             }
569
570             [FriendAccessAllowed]
571             set
572             {
573                 m_profileAPICheck = value;
574             }
575         }
576 #endif
577
578         // This is guaranteed to return a valid handle
579         [System.Security.SecurityCritical]  // auto-generated
580         internal unsafe RuntimeMethodHandle GetMethodDescriptor() {
581             if (m_methodHandle == null) {
582                 lock (this) {
583                     if (m_methodHandle == null) {
584                         if (m_DynamicILInfo != null)
585                             m_DynamicILInfo.GetCallableMethod(m_module, this);
586                         else {
587                             if (m_ilGenerator == null || m_ilGenerator.ILOffset == 0)
588                                 throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_BadEmptyMethodBody", Name));
589     
590                             m_ilGenerator.GetCallableMethod(m_module, this);
591                         }
592                     }
593                 }
594             }
595             return new RuntimeMethodHandle(m_methodHandle);
596         }
597
598         //
599         // MethodInfo api. They mostly forward to RTDynamicMethod
600         //
601
602         public override String ToString() { return m_dynMethod.ToString(); }
603
604         public override String Name { get { return m_dynMethod.Name; } }
605
606         public override Type DeclaringType { get { return m_dynMethod.DeclaringType; } }
607
608         public override Type ReflectedType { get { return m_dynMethod.ReflectedType; } }
609
610         public override Module Module { get { return m_dynMethod.Module; } }
611
612         // we cannot return a MethodHandle because we cannot track it via GC so this method is off limits
613         public override RuntimeMethodHandle MethodHandle { get { throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_NotAllowedInDynamicMethod")); } }
614
615         public override MethodAttributes Attributes { get { return m_dynMethod.Attributes; } }
616
617         public override CallingConventions CallingConvention { get { return m_dynMethod.CallingConvention; } }
618
619         public override MethodInfo GetBaseDefinition() { return this; }
620
621         [Pure]
622         public override ParameterInfo[] GetParameters() { return m_dynMethod.GetParameters(); }
623
624         public override MethodImplAttributes GetMethodImplementationFlags() { return m_dynMethod.GetMethodImplementationFlags(); }
625
626         //
627         // Security transparency accessors
628         //
629         // Since the dynamic method may not be JITed yet, we don't always have the runtime method handle
630         // which is needed to determine the official runtime transparency status of the dynamic method.  We
631         // fall back to saying that the dynamic method matches the transparency of its containing module
632         // until we get a JITed version, since dynamic methods cannot have attributes of their own.
633         //
634
635         public override bool IsSecurityCritical
636         {
637             [SecuritySafeCritical]
638             get
639             {
640                 if (m_methodHandle != null)
641                 {
642                     return RuntimeMethodHandle.IsSecurityCritical(m_methodHandle);
643                 }
644                 else if (m_typeOwner != null)
645                 {
646                     RuntimeAssembly assembly = m_typeOwner.Assembly as RuntimeAssembly;
647                     Contract.Assert(assembly != null);
648
649                     return assembly.IsAllSecurityCritical();
650                 }
651                 else
652                 {
653                     RuntimeAssembly assembly = m_module.Assembly as RuntimeAssembly;
654                     Contract.Assert(assembly != null);
655
656                     return assembly.IsAllSecurityCritical();
657                 }
658             }
659         }
660
661         public override bool IsSecuritySafeCritical
662         {
663             [SecuritySafeCritical]
664             get
665             {
666                 if (m_methodHandle != null)
667                 {
668                     return RuntimeMethodHandle.IsSecuritySafeCritical(m_methodHandle);
669                 }
670                 else if (m_typeOwner != null)
671                 {
672                     RuntimeAssembly assembly = m_typeOwner.Assembly as RuntimeAssembly;
673                     Contract.Assert(assembly != null);
674
675                     return assembly.IsAllPublicAreaSecuritySafeCritical();
676                 }
677                 else
678                 {
679                     RuntimeAssembly assembly = m_module.Assembly as RuntimeAssembly;
680                     Contract.Assert(assembly != null);
681
682                     return assembly.IsAllSecuritySafeCritical();
683                 }
684             }
685         }
686
687         public override bool IsSecurityTransparent
688         {
689             [SecuritySafeCritical]
690             get
691             {
692                 if (m_methodHandle != null)
693                 {
694                     return RuntimeMethodHandle.IsSecurityTransparent(m_methodHandle);
695                 }
696                 else if (m_typeOwner != null)
697                 {
698                     RuntimeAssembly assembly = m_typeOwner.Assembly as RuntimeAssembly;
699                     Contract.Assert(assembly != null);
700
701                     return !assembly.IsAllSecurityCritical();
702                 }
703                 else
704                 {
705                     RuntimeAssembly assembly = m_module.Assembly as RuntimeAssembly;
706                     Contract.Assert(assembly != null);
707
708                     return !assembly.IsAllSecurityCritical();
709                 }
710             }
711         }
712
713         [System.Security.SecuritySafeCritical]  // auto-generated
714         public override Object Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture) {
715             if ((CallingConvention & CallingConventions.VarArgs) == CallingConventions.VarArgs)
716                 throw new NotSupportedException(Environment.GetResourceString("NotSupported_CallToVarArg"));
717             Contract.EndContractBlock();
718
719             //
720             // We do not demand any permission here because the caller already has access
721             // to the current DynamicMethod object, and it could just as easily emit another 
722             // Transparent DynamicMethod to call the current DynamicMethod.
723             //
724
725             RuntimeMethodHandle method = GetMethodDescriptor();
726             // ignore obj since it's a static method
727
728             // create a signature object
729             Signature sig = new Signature(
730                 this.m_methodHandle, m_parameterTypes, m_returnType, CallingConvention);
731
732
733             // verify arguments
734             int formalCount = sig.Arguments.Length;
735             int actualCount = (parameters != null) ? parameters.Length : 0;
736             if (formalCount != actualCount)
737                 throw new TargetParameterCountException(Environment.GetResourceString("Arg_ParmCnt"));
738
739             // if we are here we passed all the previous checks. Time to look at the arguments
740             Object retValue = null;
741             if (actualCount > 0)
742             {
743                 Object[] arguments = CheckArguments(parameters, binder, invokeAttr, culture, sig);
744                 retValue = RuntimeMethodHandle.InvokeMethod(null, arguments, sig, false);
745                 // copy out. This should be made only if ByRef are present.
746                 for (int index = 0; index < arguments.Length; index++)
747                     parameters[index] = arguments[index];
748             }
749             else
750             {
751                 retValue = RuntimeMethodHandle.InvokeMethod(null, null, sig, false);
752             }
753
754             GC.KeepAlive(this);
755             return retValue;
756         }
757
758         public override Object[] GetCustomAttributes(Type attributeType, bool inherit)
759         {
760             return m_dynMethod.GetCustomAttributes(attributeType, inherit); 
761         }
762
763         public override Object[] GetCustomAttributes(bool inherit) { return m_dynMethod.GetCustomAttributes(inherit); }
764
765         public override bool IsDefined(Type attributeType, bool inherit) { return m_dynMethod.IsDefined(attributeType, inherit); }
766
767         public override Type ReturnType { get { return m_dynMethod.ReturnType; } }
768
769         public override ParameterInfo ReturnParameter { get { return m_dynMethod.ReturnParameter; } }
770
771         public override ICustomAttributeProvider ReturnTypeCustomAttributes { get { return m_dynMethod.ReturnTypeCustomAttributes; } }
772
773         //
774         // DynamicMethod specific methods
775         //
776
777         public ParameterBuilder DefineParameter(int position, ParameterAttributes attributes, String parameterName) {
778             if (position < 0 || position > m_parameterTypes.Length)
779                 throw new ArgumentOutOfRangeException(Environment.GetResourceString("ArgumentOutOfRange_ParamSequence"));
780             position--; // it's 1 based. 0 is the return value
781         
782             if (position >= 0) {
783                 ParameterInfo[] parameters = m_dynMethod.LoadParameters();
784                 parameters[position].SetName(parameterName);
785                 parameters[position].SetAttributes(attributes);
786             }
787             return null;
788         }
789
790         [System.Security.SecuritySafeCritical]  // auto-generated
791         public DynamicILInfo GetDynamicILInfo()
792         {
793 #pragma warning disable 618
794             new SecurityPermission(SecurityPermissionFlag.UnmanagedCode).Demand();
795 #pragma warning restore 618
796
797             if (m_DynamicILInfo != null)
798                 return m_DynamicILInfo;
799
800             return GetDynamicILInfo(new DynamicScope());
801         }
802
803         [System.Security.SecurityCritical]  // auto-generated
804         internal DynamicILInfo GetDynamicILInfo(DynamicScope scope)
805         {
806             if (m_DynamicILInfo == null)
807             {
808                 byte[] methodSignature = SignatureHelper.GetMethodSigHelper(
809                         null, CallingConvention, ReturnType, null, null, m_parameterTypes, null, null).GetSignature(true);
810                 m_DynamicILInfo = new DynamicILInfo(scope, this, methodSignature);
811             }
812
813             return m_DynamicILInfo;
814         }
815
816         public ILGenerator GetILGenerator() {
817             return GetILGenerator(64);
818         }
819
820        [System.Security.SecuritySafeCritical]  // auto-generated
821        public ILGenerator GetILGenerator(int streamSize) 
822         {
823             if (m_ilGenerator == null)
824             {
825                 byte[] methodSignature = SignatureHelper.GetMethodSigHelper(
826                     null, CallingConvention, ReturnType, null, null, m_parameterTypes, null, null).GetSignature(true);
827                 m_ilGenerator = new DynamicILGenerator(this, methodSignature, streamSize);
828             }
829             return m_ilGenerator;
830         }
831
832         public bool InitLocals {
833             get {return m_fInitLocals;}
834             set {m_fInitLocals = value;}
835         }
836
837         //
838         // Internal API
839         //
840          
841         internal MethodInfo GetMethodInfo() {
842             return m_dynMethod;
843         }
844
845         //////////////////////////////////////////////////////////////////////////////////////////////
846         // RTDynamicMethod
847         //
848         // this is actually the real runtime instance of a method info that gets used for invocation
849         // We need this so we never leak the DynamicMethod out via an exception.
850         // This way the DynamicMethod creator is the only one responsible for DynamicMethod access,
851         // and can control exactly who gets access to it.
852         //
853         internal class RTDynamicMethod : MethodInfo {
854
855             internal DynamicMethod m_owner;
856             ParameterInfo[] m_parameters;
857             String m_name;
858             MethodAttributes m_attributes;
859             CallingConventions m_callingConvention;
860
861             //
862             // ctors
863             //
864             private RTDynamicMethod() {}
865
866             internal RTDynamicMethod(DynamicMethod owner, String name, MethodAttributes attributes, CallingConventions callingConvention) {
867                 m_owner = owner;
868                 m_name = name;
869                 m_attributes = attributes;
870                 m_callingConvention = callingConvention;
871             }
872             
873             //
874             // MethodInfo api
875             //
876             public override String ToString() {
877                 return ReturnType.FormatTypeName() + " " + FormatNameAndSig();
878             }
879
880             public override String Name { 
881                 get { return m_name; }
882             }
883
884             public override Type DeclaringType { 
885                 get { return null; }
886             }
887
888             public override Type ReflectedType { 
889                 get { return null; }
890             }
891
892             public override Module Module { 
893                 get { return m_owner.m_module; }
894             }
895
896             public override RuntimeMethodHandle MethodHandle { 
897                 get { throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_NotAllowedInDynamicMethod")); }   
898             }
899
900             public override MethodAttributes Attributes { 
901                 get { return m_attributes; }
902             }    
903
904             public override CallingConventions CallingConvention { 
905                 get { return m_callingConvention; }
906             }
907             
908             public override MethodInfo GetBaseDefinition() {
909                 return this;
910             }
911             
912             [Pure]
913             public override ParameterInfo[] GetParameters() {
914                 ParameterInfo[] privateParameters = LoadParameters();
915                 ParameterInfo[] parameters = new ParameterInfo[privateParameters.Length];
916                 Array.Copy(privateParameters, parameters, privateParameters.Length);
917                 return parameters;
918             }
919             
920             public override MethodImplAttributes GetMethodImplementationFlags() {
921                 return MethodImplAttributes.IL | MethodImplAttributes.NoInlining;
922             }
923
924             public override Object Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture) {
925                 // We want the creator of the DynamicMethod to control who has access to the
926                 // DynamicMethod (just like we do for delegates). However, a user can get to
927                 // the corresponding RTDynamicMethod using Exception.TargetSite, StackFrame.GetMethod, etc.
928                 // If we allowed use of RTDynamicMethod, the creator of the DynamicMethod would
929                 // not be able to bound access to the DynamicMethod. Hence, we do not allow
930                 // direct use of RTDynamicMethod.
931                 throw new ArgumentException(Environment.GetResourceString("Argument_MustBeRuntimeMethodInfo"), "this");
932             }
933
934             public override Object[] GetCustomAttributes(Type attributeType, bool inherit) {
935                 if (attributeType == null)
936                     throw new ArgumentNullException("attributeType");
937                 Contract.EndContractBlock();
938
939                 if (attributeType.IsAssignableFrom(typeof(MethodImplAttribute))) 
940                     return new Object[] { new MethodImplAttribute(GetMethodImplementationFlags()) };
941                 else
942                     return EmptyArray<Object>.Value;
943             }
944
945             public override Object[] GetCustomAttributes(bool inherit) {
946                 // support for MethodImplAttribute PCA
947                 return new Object[] { new MethodImplAttribute(GetMethodImplementationFlags()) };
948             }
949             
950             public override bool IsDefined(Type attributeType, bool inherit) {
951                 if (attributeType == null)
952                     throw new ArgumentNullException("attributeType");
953                 Contract.EndContractBlock();
954
955                 if (attributeType.IsAssignableFrom(typeof(MethodImplAttribute))) 
956                     return true;
957                 else
958                     return false;
959             }
960
961             public override bool IsSecurityCritical
962             {
963                 get { return m_owner.IsSecurityCritical; }
964             }
965
966             public override bool IsSecuritySafeCritical
967             {
968                 get { return m_owner.IsSecuritySafeCritical; }
969             }
970
971             public override bool IsSecurityTransparent
972             {
973                 get { return m_owner.IsSecurityTransparent; }
974             }
975
976             public override Type ReturnType
977             {
978                 get
979                 {
980                     return m_owner.m_returnType;
981                 }
982             }
983
984             public override ParameterInfo ReturnParameter { 
985                 get { return null; } 
986             }
987
988             public override ICustomAttributeProvider ReturnTypeCustomAttributes {
989                 get { return GetEmptyCAHolder(); }
990             }
991
992             //
993             // private implementation
994             //
995
996             internal ParameterInfo[] LoadParameters() {
997                 if (m_parameters == null) {
998                     Type[] parameterTypes = m_owner.m_parameterTypes;
999                     ParameterInfo[] parameters = new ParameterInfo[parameterTypes.Length];
1000                     for (int i = 0; i < parameterTypes.Length; i++) 
1001                         parameters[i] = new RuntimeParameterInfo(this, null, parameterTypes[i], i);
1002                     if (m_parameters == null) 
1003                         // should we interlockexchange?
1004                         m_parameters = parameters;
1005                 }
1006                 return m_parameters;
1007             }
1008             
1009             // private implementation of CA for the return type
1010             private ICustomAttributeProvider GetEmptyCAHolder() {
1011                 return new EmptyCAHolder();
1012             }
1013
1014             ///////////////////////////////////////////////////
1015             // EmptyCAHolder
1016             private class EmptyCAHolder : ICustomAttributeProvider {
1017                 internal EmptyCAHolder() {}
1018
1019                 Object[] ICustomAttributeProvider.GetCustomAttributes(Type attributeType, bool inherit) {
1020                     return EmptyArray<Object>.Value;
1021                 }
1022
1023                 Object[] ICustomAttributeProvider.GetCustomAttributes(bool inherit) {
1024                     return EmptyArray<Object>.Value;
1025                 }
1026
1027                 bool ICustomAttributeProvider.IsDefined (Type attributeType, bool inherit) {
1028                     return false;
1029                 }
1030             }
1031
1032         }
1033     
1034     }
1035
1036 }
1037