2010-06-21 Atsushi Enomoto <atsushi@ximian.com>
[mcs.git] / class / corlib / System.Reflection.Emit / DynamicMethod.cs
blob44d4f374665d031a3e0736f551016bd10adecf0d
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 //
12 // Copyright (C) 2004 Novell, Inc (http://www.novell.com)
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.
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;
42 namespace System.Reflection.Emit {
44 [ComVisible (true)]
45 public sealed class DynamicMethod : MethodInfo {
47 #pragma warning disable 169, 414
48 #region Sync with reflection.h
49 private RuntimeMethodHandle mhandle;
50 private string name;
51 private Type returnType;
52 private Type[] parameters;
53 private MethodAttributes attributes;
54 private CallingConventions callingConvention;
55 private Module module;
56 private bool skipVisibility;
57 private bool init_locals = true;
58 private ILGenerator ilgen;
59 private int nrefs;
60 private object[] refs;
61 private IntPtr referenced_by;
62 private Type owner;
63 #endregion
64 #pragma warning restore 169, 414
66 private Delegate deleg;
67 private MonoMethod method;
68 private ParameterBuilder[] pinfo;
69 internal bool creating;
71 public DynamicMethod (string name, Type returnType, Type[] parameterTypes, Module m) : this (name, returnType, parameterTypes, m, false) {
74 public DynamicMethod (string name, Type returnType, Type[] parameterTypes, Type owner) : this (name, returnType, parameterTypes, owner, false) {
77 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 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 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 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 public DynamicMethod (string name, Type returnType, Type[] parameterTypes) : this (name, returnType, parameterTypes, false) {
92 [MonoTODO ("Visibility is not restricted")]
93 public DynamicMethod (string name, Type returnType, Type[] parameterTypes, bool restrictedSkipVisibility)
94 : this (name, MethodAttributes.Public | MethodAttributes.Static, CallingConventions.Standard, returnType, parameterTypes, null, null, restrictedSkipVisibility, true)
98 DynamicMethod (string name, MethodAttributes attributes, CallingConventions callingConvention, Type returnType, Type [] parameterTypes, Type owner, Module m, bool skipVisibility, bool anonHosted)
100 if (name == null)
101 throw new ArgumentNullException ("name");
102 if (returnType == null)
103 returnType = typeof (void);
104 if ((m == null) && !anonHosted)
105 throw new ArgumentNullException ("m");
106 if (returnType.IsByRef)
107 throw new ArgumentException ("Return type can't be a byref type", "returnType");
108 if (parameterTypes != null) {
109 for (int i = 0; i < parameterTypes.Length; ++i)
110 if (parameterTypes [i] == null)
111 throw new ArgumentException ("Parameter " + i + " is null", "parameterTypes");
114 if (m == null)
115 m = AnonHostModuleHolder.anon_host_module;
117 this.name = name;
118 this.attributes = attributes | MethodAttributes.Static;
119 this.callingConvention = callingConvention;
120 this.returnType = returnType;
121 this.parameters = parameterTypes;
122 this.owner = owner;
123 this.module = m;
124 this.skipVisibility = skipVisibility;
127 [MethodImplAttribute(MethodImplOptions.InternalCall)]
128 private extern void create_dynamic_method (DynamicMethod m);
130 [MethodImplAttribute(MethodImplOptions.InternalCall)]
131 private extern void destroy_dynamic_method (DynamicMethod m);
133 private void CreateDynMethod () {
134 if (mhandle.Value == IntPtr.Zero) {
135 if (ilgen == null || ilgen.ILOffset == 0)
136 throw new InvalidOperationException ("Method '" + name + "' does not have a method body.");
138 ilgen.label_fixup ();
140 // Have to create all DynamicMethods referenced by this one
141 try {
142 // Used to avoid cycles
143 creating = true;
144 if (refs != null) {
145 for (int i = 0; i < refs.Length; ++i) {
146 if (refs [i] is DynamicMethod) {
147 DynamicMethod m = (DynamicMethod)refs [i];
148 if (!m.creating)
149 m.CreateDynMethod ();
153 } finally {
154 creating = false;
157 create_dynamic_method (this);
161 ~DynamicMethod ()
163 destroy_dynamic_method (this);
166 [ComVisible (true)]
167 public Delegate CreateDelegate (Type delegateType)
169 if (delegateType == null)
170 throw new ArgumentNullException ("delegateType");
171 if (deleg != null)
172 return deleg;
174 CreateDynMethod ();
176 deleg = Delegate.CreateDelegate (delegateType, this);
177 return deleg;
180 [ComVisible (true)]
181 public Delegate CreateDelegate (Type delegateType, object target)
183 if (delegateType == null)
184 throw new ArgumentNullException ("delegateType");
186 CreateDynMethod ();
188 /* Can't cache the delegate since it is different for each target */
189 return Delegate.CreateDelegate (delegateType, target, this);
192 public ParameterBuilder DefineParameter (int position, ParameterAttributes attributes, string parameterName)
195 // Extension: Mono allows position == 0 for the return attribute
197 if ((position < 0) || (position > parameters.Length))
198 throw new ArgumentOutOfRangeException ("position");
200 RejectIfCreated ();
202 ParameterBuilder pb = new ParameterBuilder (this, position, attributes, parameterName);
203 if (pinfo == null)
204 pinfo = new ParameterBuilder [parameters.Length + 1];
205 pinfo [position] = pb;
206 return pb;
209 public override MethodInfo GetBaseDefinition () {
210 return this;
213 [MonoTODO("Not implemented")]
214 public override object[] GetCustomAttributes (bool inherit) {
215 throw new NotImplementedException ();
218 [MonoTODO("Not implemented")]
219 public override object[] GetCustomAttributes (Type attributeType,
220 bool inherit) {
221 throw new NotImplementedException ();
224 [MonoTODO("Not implemented")]
225 public DynamicILInfo GetDynamicILInfo () {
226 throw new NotImplementedException ();
229 public ILGenerator GetILGenerator () {
230 return GetILGenerator (64);
233 public ILGenerator GetILGenerator (int streamSize) {
234 if (((GetMethodImplementationFlags () & MethodImplAttributes.CodeTypeMask) !=
235 MethodImplAttributes.IL) ||
236 ((GetMethodImplementationFlags () & MethodImplAttributes.ManagedMask) !=
237 MethodImplAttributes.Managed))
238 throw new InvalidOperationException ("Method body should not exist.");
239 if (ilgen != null)
240 return ilgen;
241 ilgen = new ILGenerator (Module, new DynamicMethodTokenGenerator (this), streamSize);
242 return ilgen;
245 public override MethodImplAttributes GetMethodImplementationFlags () {
246 return MethodImplAttributes.IL | MethodImplAttributes.Managed;
249 public override ParameterInfo[] GetParameters () {
250 if (parameters == null)
251 return new ParameterInfo [0];
253 ParameterInfo[] retval = new ParameterInfo [parameters.Length];
254 for (int i = 0; i < parameters.Length; i++) {
255 retval [i] = new ParameterInfo (pinfo == null ? null : pinfo [i + 1], parameters [i], this, i + 1);
257 return retval;
260 internal override int GetParameterCount ()
262 return parameters == null ? 0 : parameters.Length;
266 public override object Invoke (object obj, object[] parameters) {
267 CreateDynMethod ();
268 if (method == null)
269 method = new MonoMethod (mhandle);
270 return method.Invoke (obj, parameters);
274 public override object Invoke (object obj, BindingFlags invokeAttr,
275 Binder binder, object[] parameters,
276 CultureInfo culture)
278 try {
279 CreateDynMethod ();
280 if (method == null)
281 method = new MonoMethod (mhandle);
283 return method.Invoke (obj, parameters);
285 catch (MethodAccessException mae) {
286 throw new TargetInvocationException ("Method cannot be invoked.", mae);
290 [MonoTODO("Not implemented")]
291 public override bool IsDefined (Type attributeType, bool inherit) {
292 throw new NotImplementedException ();
295 public override string ToString () {
296 string parms = String.Empty;
297 ParameterInfo[] p = GetParameters ();
298 for (int i = 0; i < p.Length; ++i) {
299 if (i > 0)
300 parms = parms + ", ";
301 parms = parms + p [i].ParameterType.Name;
303 return ReturnType.Name+" "+Name+"("+parms+")";
306 public override MethodAttributes Attributes {
307 get {
308 return attributes;
312 public override CallingConventions CallingConvention {
313 get {
314 return callingConvention;
318 public override Type DeclaringType {
319 get {
320 return null;
324 public bool InitLocals {
325 get {
326 return init_locals;
328 set {
329 init_locals = value;
333 public override RuntimeMethodHandle MethodHandle {
334 get {
335 return mhandle;
339 public override Module Module {
340 get {
341 return module;
345 public override string Name {
346 get {
347 return name;
351 public override Type ReflectedType {
352 get {
353 return null;
357 [MonoTODO("Not implemented")]
358 public override ParameterInfo ReturnParameter {
359 get {
360 throw new NotImplementedException ();
364 public override Type ReturnType {
365 get {
366 return returnType;
370 [MonoTODO("Not implemented")]
371 public override ICustomAttributeProvider ReturnTypeCustomAttributes {
372 get {
373 throw new NotImplementedException ();
378 public override int MetadataToken {
379 get {
380 return 0;
385 private void RejectIfCreated () {
386 if (mhandle.Value != IntPtr.Zero)
387 throw new InvalidOperationException ("Type definition of the method is complete.");
390 internal int AddRef (object reference) {
391 if (refs == null)
392 refs = new object [4];
393 if (nrefs >= refs.Length - 1) {
394 object [] new_refs = new object [refs.Length * 2];
395 System.Array.Copy (refs, new_refs, refs.Length);
396 refs = new_refs;
398 refs [nrefs] = reference;
399 /* Reserved by the runtime */
400 refs [nrefs + 1] = null;
401 nrefs += 2;
402 return nrefs - 1;
405 // This class takes care of constructing the module in a thread safe manner
406 class AnonHostModuleHolder {
407 public static Module anon_host_module;
409 static AnonHostModuleHolder () {
410 AssemblyName aname = new AssemblyName ();
411 aname.Name = "Anonymously Hosted DynamicMethods Assembly";
412 AssemblyBuilder ab = AppDomain.CurrentDomain.DefineDynamicAssembly (aname, AssemblyBuilderAccess.Run);
414 anon_host_module = ab.GetManifestModule ();
419 internal class DynamicMethodTokenGenerator : TokenGenerator {
421 private DynamicMethod m;
423 public DynamicMethodTokenGenerator (DynamicMethod m) {
424 this.m = m;
427 public int GetToken (string str) {
428 return m.AddRef (str);
431 public int GetToken (MethodInfo method, Type[] opt_param_types) {
432 throw new InvalidOperationException ();
435 public int GetToken (MemberInfo member) {
436 return m.AddRef (member);
439 public int GetToken (SignatureHelper helper) {
440 return m.AddRef (helper);