Fix null sessions in HttpContextWrapper.Session
[mono.git] / mcs / class / corlib / System.Reflection.Emit / DynamicMethod.cs
1 //
2 // System.Reflection.Emit.DynamicMethod.cs
3 //
4 // Author:
5 //   Paolo Molaro (lupus@ximian.com)
6 //   Zoltan Varga (vargaz@freemail.hu)
7 //
8 // (C) 2003 Ximian, Inc.  http://www.ximian.com
9 //
10
11 //
12 // Copyright (C) 2004 Novell, Inc (http://www.novell.com)
13 //
14 // Permission is hereby granted, free of charge, to any person obtaining
15 // a copy of this software and associated documentation files (the
16 // "Software"), to deal in the Software without restriction, including
17 // without limitation the rights to use, copy, modify, merge, publish,
18 // distribute, sublicense, and/or sell copies of the Software, and to
19 // permit persons to whom the Software is furnished to do so, subject to
20 // the following conditions:
21 // 
22 // The above copyright notice and this permission notice shall be
23 // included in all copies or substantial portions of the Software.
24 // 
25 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
26 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
27 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
28 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
29 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
30 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
31 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
32 //
33
34
35 using System;
36 using System.Reflection;
37 using System.Reflection.Emit;
38 using System.Globalization;
39 using System.Runtime.CompilerServices;
40 using System.Runtime.InteropServices;
41
42 namespace System.Reflection.Emit {
43
44         [ComVisible (true)]
45         [StructLayout (LayoutKind.Sequential)]
46         public sealed class DynamicMethod : MethodInfo {
47
48 #pragma warning disable 169, 414, 649
49                 #region Sync with reflection.h
50                 private RuntimeMethodHandle mhandle;
51                 private string name;
52                 private Type returnType;
53                 private Type[] parameters;
54                 private MethodAttributes attributes;
55                 private CallingConventions callingConvention;
56                 private Module module;
57                 private bool skipVisibility;
58                 private bool init_locals = true;
59                 private ILGenerator ilgen;
60                 private int nrefs;
61                 private object[] refs;
62                 private IntPtr referenced_by;
63                 private Type owner;
64                 #endregion
65 #pragma warning restore 169, 414, 649
66                 
67                 private Delegate deleg;
68                 private MonoMethod method;
69                 private ParameterBuilder[] pinfo;
70                 internal bool creating;
71                 private DynamicILInfo il_info;
72
73                 public DynamicMethod (string name, Type returnType, Type[] parameterTypes, Module m) : this (name, returnType, parameterTypes, m, false) {
74                 }
75
76                 public DynamicMethod (string name, Type returnType, Type[] parameterTypes, Type owner) : this (name, returnType, parameterTypes, owner, false) {
77                 }
78
79                 public DynamicMethod (string name, Type returnType, Type[] parameterTypes, Module m, bool skipVisibility) : this (name, MethodAttributes.Public | MethodAttributes.Static, CallingConventions.Standard, returnType, parameterTypes, m, skipVisibility) {
80                 }
81
82                 public DynamicMethod (string name, Type returnType, Type[] parameterTypes, Type owner, bool skipVisibility) : this (name, MethodAttributes.Public | MethodAttributes.Static, CallingConventions.Standard, returnType, parameterTypes, owner, skipVisibility) {
83                 }
84
85                 public DynamicMethod (string name, MethodAttributes attributes, CallingConventions callingConvention, Type returnType, Type[] parameterTypes, Type owner, bool skipVisibility) : this (name, attributes, callingConvention, returnType, parameterTypes, owner, owner.Module, skipVisibility, false) {
86                 }
87
88                 public DynamicMethod (string name, MethodAttributes attributes, CallingConventions callingConvention, Type returnType, Type[] parameterTypes, Module m, bool skipVisibility) : this (name, attributes, callingConvention, returnType, parameterTypes, null, m, skipVisibility, false) {
89                 }
90
91                 public DynamicMethod (string name, Type returnType, Type[] parameterTypes) : this (name, returnType, parameterTypes, false) {
92                 }
93
94                 [MonoTODO ("Visibility is not restricted")]
95                 public DynamicMethod (string name, Type returnType, Type[] parameterTypes, bool restrictedSkipVisibility)
96                         : this (name, MethodAttributes.Public | MethodAttributes.Static, CallingConventions.Standard, returnType, parameterTypes, null, null, restrictedSkipVisibility, true)
97                 {
98                 }
99
100                 DynamicMethod (string name, MethodAttributes attributes, CallingConventions callingConvention, Type returnType, Type [] parameterTypes, Type owner, Module m, bool skipVisibility, bool anonHosted)
101                 {
102                         if (name == null)
103                                 throw new ArgumentNullException ("name");
104                         if (returnType == null)
105                                 returnType = typeof (void);
106                         if ((m == null) && !anonHosted)
107                                 throw new ArgumentNullException ("m");
108                         if (returnType.IsByRef)
109                                 throw new ArgumentException ("Return type can't be a byref type", "returnType");
110                         if (parameterTypes != null) {
111                                 for (int i = 0; i < parameterTypes.Length; ++i)
112                                         if (parameterTypes [i] == null)
113                                                 throw new ArgumentException ("Parameter " + i + " is null", "parameterTypes");
114                         }
115                         if (owner != null && (owner.IsArray || owner.IsInterface)) {
116                                 throw new ArgumentException ("Owner can't be an array or an interface.");
117                         }
118
119                         if (m == null)
120                                 m = AnonHostModuleHolder.AnonHostModule;
121
122                         this.name = name;
123                         this.attributes = attributes | MethodAttributes.Static;
124                         this.callingConvention = callingConvention;
125                         this.returnType = returnType;
126                         this.parameters = parameterTypes;
127                         this.owner = owner;
128                         this.module = m;
129                         this.skipVisibility = skipVisibility;
130                 }
131
132                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
133                 private extern void create_dynamic_method (DynamicMethod m);
134
135                 private void CreateDynMethod () {
136                         if (mhandle.Value == IntPtr.Zero) {
137                                 if (ilgen == null || ilgen.ILOffset == 0)
138                                         throw new InvalidOperationException ("Method '" + name + "' does not have a method body.");
139
140                                 ilgen.label_fixup ();
141
142                                 // Have to create all DynamicMethods referenced by this one
143                                 try {
144                                         // Used to avoid cycles
145                                         creating = true;
146                                         if (refs != null) {
147                                                 for (int i = 0; i < refs.Length; ++i) {
148                                                         if (refs [i] is DynamicMethod) {
149                                                                 DynamicMethod m = (DynamicMethod)refs [i];
150                                                                 if (!m.creating)
151                                                                         m.CreateDynMethod ();
152                                                         }
153                                                 }
154                                         }
155                                 } finally {
156                                         creating = false;
157                                 }
158
159                                 create_dynamic_method (this);
160                         }
161                 }
162
163                 [ComVisible (true)]
164                 public Delegate CreateDelegate (Type delegateType)
165                 {
166                         if (delegateType == null)
167                                 throw new ArgumentNullException ("delegateType");
168                         if (deleg != null)
169                                 return deleg;
170
171                         CreateDynMethod ();
172
173                         deleg = Delegate.CreateDelegate (delegateType, this);
174                         return deleg;
175                 }
176
177                 [ComVisible (true)]
178                 public Delegate CreateDelegate (Type delegateType, object target)
179                 {
180                         if (delegateType == null)
181                                 throw new ArgumentNullException ("delegateType");
182
183                         CreateDynMethod ();
184
185                         /* Can't cache the delegate since it is different for each target */
186                         return Delegate.CreateDelegate (delegateType, target, this);
187                 }
188                 
189                 public ParameterBuilder DefineParameter (int position, ParameterAttributes attributes, string parameterName)
190                 {
191                         //
192                         // Extension: Mono allows position == 0 for the return attribute
193                         //
194                         if ((position < 0) || (position > parameters.Length))
195                                 throw new ArgumentOutOfRangeException ("position");
196
197                         RejectIfCreated ();
198
199                         ParameterBuilder pb = new ParameterBuilder (this, position, attributes, parameterName);
200                         if (pinfo == null)
201                                 pinfo = new ParameterBuilder [parameters.Length + 1];
202                         pinfo [position] = pb;
203                         return pb;
204                 }
205
206                 public override MethodInfo GetBaseDefinition () {
207                         return this;
208                 }
209
210                 [MonoTODO("Not implemented")]
211                 public override object[] GetCustomAttributes (bool inherit) {
212                         throw new NotImplementedException ();
213                 }
214
215                 [MonoTODO("Not implemented")]
216                 public override object[] GetCustomAttributes (Type attributeType,
217                                                                                                           bool inherit) {
218                         throw new NotImplementedException ();
219                 }
220
221                 public DynamicILInfo GetDynamicILInfo () {
222                         if (il_info == null)
223                                 il_info = new DynamicILInfo (this);
224                         return il_info;
225                 }
226
227                 public ILGenerator GetILGenerator () {
228                         return GetILGenerator (64);
229                 }
230
231                 public ILGenerator GetILGenerator (int streamSize) {
232                         if (((GetMethodImplementationFlags () & MethodImplAttributes.CodeTypeMask) != 
233                                  MethodImplAttributes.IL) ||
234                                 ((GetMethodImplementationFlags () & MethodImplAttributes.ManagedMask) != 
235                                  MethodImplAttributes.Managed))
236                                 throw new InvalidOperationException ("Method body should not exist.");
237                         if (ilgen != null)
238                                 return ilgen;
239                         ilgen = new ILGenerator (Module, new DynamicMethodTokenGenerator (this), streamSize);
240                         return ilgen;
241                 }               
242
243                 public override MethodImplAttributes GetMethodImplementationFlags () {
244                         return MethodImplAttributes.IL | MethodImplAttributes.Managed;
245                 }
246
247                 public override ParameterInfo[] GetParameters () {
248                         if (parameters == null)
249                                 return new ParameterInfo [0];
250
251                         ParameterInfo[] retval = new ParameterInfo [parameters.Length];
252                         for (int i = 0; i < parameters.Length; i++) {
253                                 retval [i] = new ParameterInfo (pinfo == null ? null : pinfo [i + 1], parameters [i], this, i + 1);
254                         }
255                         return retval;
256                 }
257                 
258                 internal override int GetParameterCount ()
259                 {
260                         return parameters == null ? 0 : parameters.Length;
261                 }               
262
263                 internal override Type GetParameterType (int pos) {
264                         return parameters [pos];
265                 }
266
267                 /*
268                 public override object Invoke (object obj, object[] parameters) {
269                         CreateDynMethod ();
270                         if (method == null)
271                                 method = new MonoMethod (mhandle);
272                         return method.Invoke (obj, parameters);
273                 }
274                 */
275
276                 public override object Invoke (object obj, BindingFlags invokeAttr,
277                                                                            Binder binder, object[] parameters,
278                                                                            CultureInfo culture)
279                 {
280                         try {
281                                 CreateDynMethod ();
282                                 if (method == null)
283                                         method = new MonoMethod (mhandle);
284
285                                 return method.Invoke (obj, parameters);
286                         }
287                         catch (MethodAccessException mae) {
288                                 throw new TargetInvocationException ("Method cannot be invoked.", mae);
289                         }
290                 }
291
292                 [MonoTODO("Not implemented")]
293                 public override bool IsDefined (Type attributeType, bool inherit) {
294                         throw new NotImplementedException ();
295                 }
296
297                 public override string ToString () {
298                         string parms = String.Empty;
299                         ParameterInfo[] p = GetParameters ();
300                         for (int i = 0; i < p.Length; ++i) {
301                                 if (i > 0)
302                                         parms = parms + ", ";
303                                 parms = parms + p [i].ParameterType.Name;
304                         }
305                         return ReturnType.Name+" "+Name+"("+parms+")";
306                 }
307
308                 public override MethodAttributes Attributes {
309                         get {
310                                 return attributes;
311                         }
312                 }
313
314                 public override CallingConventions CallingConvention {
315                         get {
316                                 return callingConvention;
317                         }
318                 }
319
320                 public override Type DeclaringType {
321                         get {
322                                 return null;
323                         }
324                 }
325
326                 public bool InitLocals {
327                         get {
328                                 return init_locals;
329                         }
330                         set {
331                                 init_locals = value;
332                         }
333                 }
334
335                 public override RuntimeMethodHandle MethodHandle {
336                         get {
337                                 return mhandle;
338                         }
339                 }
340
341                 public override Module Module {
342                         get {
343                                 return module;
344                         }
345                 }
346
347                 public override string Name {
348                         get {
349                                 return name;
350                         }
351                 }
352
353                 public override Type ReflectedType {
354                         get {
355                                 return null;
356                         }
357                 }
358
359                 [MonoTODO("Not implemented")]
360                 public override ParameterInfo ReturnParameter {
361                         get {
362                                 throw new NotImplementedException ();
363                         }
364                 }
365
366                 public override Type ReturnType {
367                         get {
368                                 return returnType;
369                         }
370                 }
371
372                 [MonoTODO("Not implemented")]
373                 public override ICustomAttributeProvider ReturnTypeCustomAttributes {
374                         get {
375                                 throw new NotImplementedException ();
376                         }
377                 }
378
379 /*
380                 public override int MetadataToken {
381                         get {
382                                 return 0;
383                         }
384                 }
385 */
386
387                 private void RejectIfCreated () {
388                         if (mhandle.Value != IntPtr.Zero)
389                                 throw new InvalidOperationException ("Type definition of the method is complete.");
390                 }
391
392                 internal int AddRef (object reference) {
393                         if (refs == null)
394                                 refs = new object [4];
395                         if (nrefs >= refs.Length - 1) {
396                                 object [] new_refs = new object [refs.Length * 2];
397                                 System.Array.Copy (refs, new_refs, refs.Length);
398                                 refs = new_refs;
399                         }
400                         refs [nrefs] = reference;
401                         /* Reserved by the runtime */
402                         refs [nrefs + 1] = null;
403                         nrefs += 2;
404                         return nrefs - 1;
405                 }
406
407                 // This class takes care of constructing the module in a thread safe manner
408                 class AnonHostModuleHolder {
409                         public static Module anon_host_module;
410
411                         static AnonHostModuleHolder () {
412                                 AssemblyName aname = new AssemblyName ();
413                                 aname.Name = "Anonymously Hosted DynamicMethods Assembly";
414                                 AssemblyBuilder ab = AppDomain.CurrentDomain.DefineDynamicAssembly (aname, AssemblyBuilderAccess.Run);
415
416                                 anon_host_module = ab.GetManifestModule ();
417                         }
418
419                         public static Module AnonHostModule {
420                                 get {
421                                         return anon_host_module;
422                                 }
423                         }
424                 }
425         }
426
427         internal class DynamicMethodTokenGenerator : TokenGenerator {
428
429                 private DynamicMethod m;
430
431                 public DynamicMethodTokenGenerator (DynamicMethod m) {
432                         this.m = m;
433                 }
434
435                 public int GetToken (string str) {
436                         return m.AddRef (str);
437                 }
438
439                 public int GetToken (MethodInfo method, Type[] opt_param_types) {
440                         throw new InvalidOperationException ();
441                 }
442
443                 public int GetToken (MemberInfo member, bool create_open_instance) {
444                         return m.AddRef (member);
445                 }
446
447                 public int GetToken (SignatureHelper helper) {
448                         return m.AddRef (helper);
449                 }
450         }
451 }
452