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 #if !FULL_AOT_RUNTIME 35 36 using System; 37 using System.Reflection; 38 using System.Reflection.Emit; 39 using System.Globalization; 40 using System.Runtime.CompilerServices; 41 using System.Runtime.InteropServices; 42 43 namespace System.Reflection.Emit { 44 45 [ComVisible (true)] 46 [StructLayout (LayoutKind.Sequential)] 47 public sealed class DynamicMethod : MethodInfo { 48 49 #pragma warning disable 169, 414, 649 50 #region Sync with reflection.h 51 private RuntimeMethodHandle mhandle; 52 private string name; 53 private Type returnType; 54 private Type[] parameters; 55 private MethodAttributes attributes; 56 private CallingConventions callingConvention; 57 private Module module; 58 private bool skipVisibility; 59 private bool init_locals = true; 60 private ILGenerator ilgen; 61 private int nrefs; 62 private object[] refs; 63 private IntPtr referenced_by; 64 private Type owner; 65 #endregion 66 #pragma warning restore 169, 414, 649 67 68 private Delegate deleg; 69 private MonoMethod method; 70 private ParameterBuilder[] pinfo; 71 internal bool creating; 72 private DynamicILInfo il_info; 73 DynamicMethod(string name, Type returnType, Type[] parameterTypes, Module m)74 public DynamicMethod (string name, Type returnType, Type[] parameterTypes, Module m) : this (name, returnType, parameterTypes, m, false) { 75 } 76 DynamicMethod(string name, Type returnType, Type[] parameterTypes, Type owner)77 public DynamicMethod (string name, Type returnType, Type[] parameterTypes, Type owner) : this (name, returnType, parameterTypes, owner, false) { 78 } 79 DynamicMethod(string name, Type returnType, Type[] parameterTypes, Module m, bool skipVisibility)80 public DynamicMethod (string name, Type returnType, Type[] parameterTypes, Module m, bool skipVisibility) : this (name, MethodAttributes.Public | MethodAttributes.Static, CallingConventions.Standard, returnType, parameterTypes, m, skipVisibility) { 81 } 82 DynamicMethod(string name, Type returnType, Type[] parameterTypes, Type owner, bool skipVisibility)83 public DynamicMethod (string name, Type returnType, Type[] parameterTypes, Type owner, bool skipVisibility) : this (name, MethodAttributes.Public | MethodAttributes.Static, CallingConventions.Standard, returnType, parameterTypes, owner, skipVisibility) { 84 } 85 DynamicMethod(string name, MethodAttributes attributes, CallingConventions callingConvention, Type returnType, Type[] parameterTypes, Type owner, bool skipVisibility)86 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) { 87 } 88 DynamicMethod(string name, MethodAttributes attributes, CallingConventions callingConvention, Type returnType, Type[] parameterTypes, Module m, bool skipVisibility)89 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) { 90 } 91 DynamicMethod(string name, Type returnType, Type[] parameterTypes)92 public DynamicMethod (string name, Type returnType, Type[] parameterTypes) : this (name, returnType, parameterTypes, false) { 93 } 94 95 [MonoTODO ("Visibility is not restricted")] DynamicMethod(string name, Type returnType, Type[] parameterTypes, bool restrictedSkipVisibility)96 public DynamicMethod (string name, Type returnType, Type[] parameterTypes, bool restrictedSkipVisibility) 97 : this (name, MethodAttributes.Public | MethodAttributes.Static, CallingConventions.Standard, returnType, parameterTypes, null, null, restrictedSkipVisibility, true) 98 { 99 } 100 DynamicMethod(string name, MethodAttributes attributes, CallingConventions callingConvention, Type returnType, Type [] parameterTypes, Type owner, Module m, bool skipVisibility, bool anonHosted)101 DynamicMethod (string name, MethodAttributes attributes, CallingConventions callingConvention, Type returnType, Type [] parameterTypes, Type owner, Module m, bool skipVisibility, bool anonHosted) 102 { 103 if (name == null) 104 throw new ArgumentNullException ("name"); 105 if (returnType == null) 106 returnType = typeof (void); 107 if ((m == null) && !anonHosted) 108 throw new ArgumentNullException ("m"); 109 if (returnType.IsByRef) 110 throw new ArgumentException ("Return type can't be a byref type", "returnType"); 111 if (parameterTypes != null) { 112 for (int i = 0; i < parameterTypes.Length; ++i) 113 if (parameterTypes [i] == null) 114 throw new ArgumentException ("Parameter " + i + " is null", "parameterTypes"); 115 } 116 if (owner != null && (owner.IsArray || owner.IsInterface)) { 117 throw new ArgumentException ("Owner can't be an array or an interface."); 118 } 119 120 if (m == null) 121 m = AnonHostModuleHolder.AnonHostModule; 122 123 this.name = name; 124 this.attributes = attributes | MethodAttributes.Static; 125 this.callingConvention = callingConvention; 126 this.returnType = returnType; 127 this.parameters = parameterTypes; 128 this.owner = owner; 129 this.module = m; 130 this.skipVisibility = skipVisibility; 131 } 132 133 [MethodImplAttribute(MethodImplOptions.InternalCall)] create_dynamic_method(DynamicMethod m)134 private static extern void create_dynamic_method (DynamicMethod m); 135 CreateDynMethod()136 private void CreateDynMethod () { 137 if (mhandle.Value == IntPtr.Zero) { 138 if (ilgen == null || ilgen.ILOffset == 0) 139 throw new InvalidOperationException ("Method '" + name + "' does not have a method body."); 140 141 ilgen.label_fixup (this); 142 143 // Have to create all DynamicMethods referenced by this one 144 try { 145 // Used to avoid cycles 146 creating = true; 147 if (refs != null) { 148 for (int i = 0; i < refs.Length; ++i) { 149 if (refs [i] is DynamicMethod) { 150 DynamicMethod m = (DynamicMethod)refs [i]; 151 if (!m.creating) 152 m.CreateDynMethod (); 153 } 154 } 155 } 156 } finally { 157 creating = false; 158 } 159 160 create_dynamic_method (this); 161 } 162 } 163 164 [ComVisible (true)] 165 sealed override CreateDelegate(Type delegateType)166 public Delegate CreateDelegate (Type delegateType) 167 { 168 if (delegateType == null) 169 throw new ArgumentNullException ("delegateType"); 170 if (deleg != null) 171 return deleg; 172 173 CreateDynMethod (); 174 175 deleg = Delegate.CreateDelegate (delegateType, this); 176 return deleg; 177 } 178 179 [ComVisible (true)] 180 sealed override CreateDelegate(Type delegateType, object target)181 public Delegate CreateDelegate (Type delegateType, object target) 182 { 183 if (delegateType == null) 184 throw new ArgumentNullException ("delegateType"); 185 186 CreateDynMethod (); 187 188 /* Can't cache the delegate since it is different for each target */ 189 return Delegate.CreateDelegate (delegateType, target, this); 190 } 191 DefineParameter(int position, ParameterAttributes attributes, string parameterName)192 public ParameterBuilder DefineParameter (int position, ParameterAttributes attributes, string parameterName) 193 { 194 // 195 // Extension: Mono allows position == 0 for the return attribute 196 // 197 if ((position < 0) || (position > parameters.Length)) 198 throw new ArgumentOutOfRangeException ("position"); 199 200 RejectIfCreated (); 201 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; 207 } 208 GetBaseDefinition()209 public override MethodInfo GetBaseDefinition () { 210 return this; 211 } 212 GetCustomAttributes(bool inherit)213 public override object[] GetCustomAttributes (bool inherit) { 214 // support for MethodImplAttribute PCA 215 return new Object[] { new MethodImplAttribute(GetMethodImplementationFlags()) }; 216 } 217 GetCustomAttributes(Type attributeType, bool inherit)218 public override object[] GetCustomAttributes (Type attributeType, 219 bool inherit) { 220 if (attributeType == null) 221 throw new ArgumentNullException ("attributeType"); 222 223 if (attributeType.IsAssignableFrom (typeof (MethodImplAttribute))) 224 return new Object[] { new MethodImplAttribute (GetMethodImplementationFlags()) }; 225 else 226 return EmptyArray<Object>.Value; 227 } 228 GetDynamicILInfo()229 public DynamicILInfo GetDynamicILInfo () { 230 if (il_info == null) 231 il_info = new DynamicILInfo (this); 232 return il_info; 233 } 234 GetILGenerator()235 public ILGenerator GetILGenerator () { 236 return GetILGenerator (64); 237 } 238 GetILGenerator(int streamSize)239 public ILGenerator GetILGenerator (int streamSize) { 240 if (((GetMethodImplementationFlags () & MethodImplAttributes.CodeTypeMask) != 241 MethodImplAttributes.IL) || 242 ((GetMethodImplementationFlags () & MethodImplAttributes.ManagedMask) != 243 MethodImplAttributes.Managed)) 244 throw new InvalidOperationException ("Method body should not exist."); 245 if (ilgen != null) 246 return ilgen; 247 ilgen = new ILGenerator (Module, new DynamicMethodTokenGenerator (this), streamSize); 248 return ilgen; 249 } 250 GetMethodImplementationFlags()251 public override MethodImplAttributes GetMethodImplementationFlags () { 252 return MethodImplAttributes.IL | MethodImplAttributes.Managed | MethodImplAttributes.NoInlining; 253 } 254 GetParameters()255 public override ParameterInfo[] GetParameters () 256 { 257 return GetParametersInternal (); 258 } 259 GetParametersInternal()260 internal override ParameterInfo[] GetParametersInternal () 261 { 262 if (parameters == null) 263 return EmptyArray<ParameterInfo>.Value; 264 265 ParameterInfo[] retval = new ParameterInfo [parameters.Length]; 266 for (int i = 0; i < parameters.Length; i++) { 267 retval [i] = ParameterInfo.New (pinfo == null ? null : pinfo [i + 1], parameters [i], this, i + 1); 268 } 269 return retval; 270 } 271 GetParametersCount()272 internal override int GetParametersCount () 273 { 274 return parameters == null ? 0 : parameters.Length; 275 } 276 GetParameterType(int pos)277 internal override Type GetParameterType (int pos) { 278 return parameters [pos]; 279 } 280 281 /* 282 public override object Invoke (object obj, object[] parameters) { 283 CreateDynMethod (); 284 if (method == null) 285 method = new MonoMethod (mhandle); 286 return method.Invoke (obj, parameters); 287 } 288 */ 289 Invoke(object obj, BindingFlags invokeAttr, Binder binder, object[] parameters, CultureInfo culture)290 public override object Invoke (object obj, BindingFlags invokeAttr, 291 Binder binder, object[] parameters, 292 CultureInfo culture) 293 { 294 try { 295 CreateDynMethod (); 296 if (method == null) 297 method = new MonoMethod (mhandle); 298 299 return method.Invoke (obj, parameters); 300 } 301 catch (MethodAccessException mae) { 302 throw new TargetInvocationException ("Method cannot be invoked.", mae); 303 } 304 } 305 IsDefined(Type attributeType, bool inherit)306 public override bool IsDefined (Type attributeType, bool inherit) { 307 if (attributeType == null) 308 throw new ArgumentNullException ("attributeType"); 309 310 if (attributeType.IsAssignableFrom (typeof (MethodImplAttribute))) 311 return true; 312 else 313 return false; 314 } 315 ToString()316 public override string ToString () { 317 string parms = String.Empty; 318 ParameterInfo[] p = GetParametersInternal (); 319 for (int i = 0; i < p.Length; ++i) { 320 if (i > 0) 321 parms = parms + ", "; 322 parms = parms + p [i].ParameterType.Name; 323 } 324 return ReturnType.Name+" "+Name+"("+parms+")"; 325 } 326 327 public override MethodAttributes Attributes { 328 get { 329 return attributes; 330 } 331 } 332 333 public override CallingConventions CallingConvention { 334 get { 335 return callingConvention; 336 } 337 } 338 339 public override Type DeclaringType { 340 get { 341 return null; 342 } 343 } 344 345 public bool InitLocals { 346 get { 347 return init_locals; 348 } 349 set { 350 init_locals = value; 351 } 352 } 353 354 public override RuntimeMethodHandle MethodHandle { 355 get { 356 return mhandle; 357 } 358 } 359 360 public override Module Module { 361 get { 362 return module; 363 } 364 } 365 366 public override string Name { 367 get { 368 return name; 369 } 370 } 371 372 public override Type ReflectedType { 373 get { 374 return null; 375 } 376 } 377 378 [MonoTODO("Not implemented")] 379 public override ParameterInfo ReturnParameter { 380 get { 381 throw new NotImplementedException (); 382 } 383 } 384 385 public override Type ReturnType { 386 get { 387 return returnType; 388 } 389 } 390 391 [MonoTODO("Not implemented")] 392 public override ICustomAttributeProvider ReturnTypeCustomAttributes { 393 get { 394 throw new NotImplementedException (); 395 } 396 } 397 398 /* 399 public override int MetadataToken { 400 get { 401 return 0; 402 } 403 } 404 */ 405 RejectIfCreated()406 private void RejectIfCreated () { 407 if (mhandle.Value != IntPtr.Zero) 408 throw new InvalidOperationException ("Type definition of the method is complete."); 409 } 410 AddRef(object reference)411 internal int AddRef (object reference) { 412 if (refs == null) 413 refs = new object [4]; 414 if (nrefs >= refs.Length - 1) { 415 object [] new_refs = new object [refs.Length * 2]; 416 System.Array.Copy (refs, new_refs, refs.Length); 417 refs = new_refs; 418 } 419 refs [nrefs] = reference; 420 /* Reserved by the runtime */ 421 refs [nrefs + 1] = null; 422 nrefs += 2; 423 return nrefs - 1; 424 } 425 426 // This class takes care of constructing the module in a thread safe manner 427 class AnonHostModuleHolder { 428 public static Module anon_host_module; 429 AnonHostModuleHolder()430 static AnonHostModuleHolder () { 431 AssemblyName aname = new AssemblyName (); 432 aname.Name = "Anonymously Hosted DynamicMethods Assembly"; 433 AssemblyBuilder ab = AppDomain.CurrentDomain.DefineDynamicAssembly (aname, AssemblyBuilderAccess.Run); 434 435 anon_host_module = ab.GetManifestModule (); 436 } 437 438 public static Module AnonHostModule { 439 get { 440 return anon_host_module; 441 } 442 } 443 } 444 } 445 446 internal class DynamicMethodTokenGenerator : TokenGenerator { 447 448 private DynamicMethod m; 449 DynamicMethodTokenGenerator(DynamicMethod m)450 public DynamicMethodTokenGenerator (DynamicMethod m) { 451 this.m = m; 452 } 453 GetToken(string str)454 public int GetToken (string str) { 455 return m.AddRef (str); 456 } 457 GetToken(MethodBase method, Type[] opt_param_types)458 public int GetToken (MethodBase method, Type[] opt_param_types) { 459 throw new InvalidOperationException (); 460 } 461 GetToken(MemberInfo member, bool create_open_instance)462 public int GetToken (MemberInfo member, bool create_open_instance) { 463 return m.AddRef (member); 464 } 465 GetToken(SignatureHelper helper)466 public int GetToken (SignatureHelper helper) { 467 return m.AddRef (helper); 468 } 469 } 470 } 471 472 #endif 473