Optimize Activator path used by new() constraint to run less code
[mono.git] / mcs / class / corlib / System.Reflection / MonoMethod.cs
index 31d23b1cb9ac1863ed51de9891bd17c84ad6b3f9..f46c01a226d083de05a8f7cb9a741f2511e56347 100644 (file)
@@ -1,12 +1,13 @@
 //
-// System.Reflection/MonoMethod.cs
-// The class used to represent methods from the mono runtime.
+// MonoMethod.cs: The class used to represent methods from the mono runtime.
 //
-// Author:
+// Authors:
 //   Paolo Molaro (lupus@ximian.com)
+//   Marek Safar (marek.safar@gmail.com)
 //
 // (C) 2001 Ximian, Inc.  http://www.ximian.com
 // Copyright (C) 2004-2005 Novell, Inc (http://www.novell.com)
+// Copyright (C) 2012 Xamarin Inc (http://www.xamarin.com)
 //
 // Permission is hereby granted, free of charge, to any person obtaining
 // a copy of this software and associated documentation files (the
@@ -33,11 +34,13 @@ using System.Globalization;
 using System.Runtime.CompilerServices;
 using System.Runtime.InteropServices;
 using System.Runtime.Serialization;
+#if !FULL_AOT_RUNTIME
 using System.Reflection.Emit;
+#endif
 using System.Security;
 using System.Threading;
 using System.Text;
-
+using System.Diagnostics;
 
 namespace System.Reflection {
        
@@ -98,7 +101,7 @@ namespace System.Reflection {
                }
 
                [MethodImplAttribute(MethodImplOptions.InternalCall)]
-               static extern UnmanagedMarshal get_retval_marshal (IntPtr handle);
+               static extern MarshalAsAttribute get_retval_marshal (IntPtr handle);
 
                static internal ParameterInfo GetReturnParameterInfo (MonoMethod method)
                {
@@ -167,16 +170,24 @@ namespace System.Reflection {
 
                public override ParameterInfo[] GetParameters ()
                {
-                       ParameterInfo[] src = MonoMethodInfo.GetParametersInfo (mhandle, this);
-                       ParameterInfo[] res = new ParameterInfo [src.Length];
-                       src.CopyTo (res, 0);
-                       return res;
+                       var src = MonoMethodInfo.GetParametersInfo (mhandle, this);
+                       if (src.Length == 0)
+                               return src;
+
+                       // Have to clone because GetParametersInfo icall returns cached value
+                       var dest = new ParameterInfo [src.Length];
+                       Array.FastCopy (src, 0, dest, 0, src.Length);
+                       return dest;
+               }
+
+               internal override ParameterInfo[] GetParametersInternal ()
+               {
+                       return MonoMethodInfo.GetParametersInfo (mhandle, this);
                }
                
-               internal override int GetParameterCount ()
+               internal override int GetParametersCount ()
                {
-                       var pi = MonoMethodInfo.GetParametersInfo (mhandle, this);
-                       return pi == null ? 0 : pi.Length;
+                       return MonoMethodInfo.GetParametersInfo (mhandle, this).Length;
                }
 
                /*
@@ -186,24 +197,16 @@ namespace System.Reflection {
                [MethodImplAttribute(MethodImplOptions.InternalCall)]
                internal extern Object InternalInvoke (Object obj, Object[] parameters, out Exception exc);
 
+               [DebuggerHidden]
+               [DebuggerStepThrough]
                public override Object Invoke (Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture) 
                {
                        if (binder == null)
                                binder = Binder.DefaultBinder;
-                       /*Avoid allocating an array every time*/
-                       ParameterInfo[] pinfo = MonoMethodInfo.GetParametersInfo (mhandle, this);
 
-                       if ((parameters == null && pinfo.Length != 0) || (parameters != null && parameters.Length != pinfo.Length))
-                               throw new TargetParameterCountException ("parameters do not match signature");
-                       
-                       if ((invokeAttr & BindingFlags.ExactBinding) == 0) {
-                               if (!Binder.ConvertArgs (binder, parameters, pinfo, culture))
-                                       throw new ArgumentException ("failed to convert parameters");
-                       } else {
-                               for (int i = 0; i < pinfo.Length; i++)
-                                       if (parameters[i].GetType() != pinfo[i].ParameterType)
-                                               throw new ArgumentException ("parameters do not match signature");
-                       }
+                       /*Avoid allocating an array every time*/
+                       ParameterInfo[] pinfo = GetParametersInternal ();
+                       binder.ConvertValues (parameters, pinfo, culture, (invokeAttr & BindingFlags.ExactBinding) != 0);
 
 #if !NET_2_1
                        if (SecurityManager.SecurityEnabled) {
@@ -241,8 +244,11 @@ namespace System.Reflection {
                }
 
                public override RuntimeMethodHandle MethodHandle { 
-                       get {return new RuntimeMethodHandle (mhandle);} 
+                       get {
+                               return new RuntimeMethodHandle (mhandle);
+                       } 
                }
+               
                public override MethodAttributes Attributes { 
                        get {
                                return MonoMethodInfo.GetAttributes (mhandle);
@@ -341,7 +347,7 @@ namespace System.Reflection {
                                sb.Append ("]");
                        }
                        sb.Append ("(");
-                       ParameterInfo[] p = GetParameters ();
+                       ParameterInfo[] p = GetParametersInternal ();
                        for (int i = 0; i < p.Length; ++i) {
                                if (i > 0)
                                        sb.Append (", ");
@@ -396,7 +402,11 @@ namespace System.Reflection {
                        }
 
                        if (hasUserType)
+#if FULL_AOT_RUNTIME
+                               throw new NotSupportedException ("User types are not supported under full aot");
+#else
                                return new MethodOnTypeBuilderInst (this, methodInstantiation);
+#endif
 
                        MethodInfo ret = MakeGenericMethod_impl (methodInstantiation);
                        if (ret == null)
@@ -473,37 +483,46 @@ namespace System.Reflection {
                        return MonoMethodInfo.GetParametersInfo (mhandle, this);
                }
 
-               internal override int GetParameterCount ()
+               internal override ParameterInfo[] GetParametersInternal ()
+               {
+                       return MonoMethodInfo.GetParametersInfo (mhandle, this);
+               }               
+
+               internal override int GetParametersCount ()
                {
                        var pi = MonoMethodInfo.GetParametersInfo (mhandle, this);
                        return pi == null ? 0 : pi.Length;
                }
 
                /*
-                * InternalInvoke() receives the parameters corretcly converted by the binder
+                * InternalInvoke() receives the parameters correctly converted by the binder
                 * to match the types of the method signature.
                 */
                [MethodImplAttribute(MethodImplOptions.InternalCall)]
                internal extern Object InternalInvoke (Object obj, Object[] parameters, out Exception exc);
 
-               public override Object Invoke (Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture) 
+               [DebuggerHidden]
+               [DebuggerStepThrough]
+               public override object Invoke (object obj, BindingFlags invokeAttr, Binder binder, object[] parameters, CultureInfo culture) 
+               {
+                       if (obj == null) {
+                               if (!IsStatic)
+                                       throw new TargetException ("Instance constructor requires a target");
+                       } else if (!DeclaringType.IsInstanceOfType (obj)) {
+                               throw new TargetException ("Constructor does not match target type");                           
+                       }
+
+                       return DoInvoke (obj, invokeAttr, binder, parameters, culture);
+               }
+
+               object DoInvoke (object obj, BindingFlags invokeAttr, Binder binder, object[] parameters, CultureInfo culture) 
                {
                        if (binder == null)
                                binder = Binder.DefaultBinder;
 
-                       ParameterInfo[] pinfo = GetParameters ();
+                       ParameterInfo[] pinfo = MonoMethodInfo.GetParametersInfo (mhandle, this);
 
-                       if ((parameters == null && pinfo.Length != 0) || (parameters != null && parameters.Length != pinfo.Length))
-                               throw new TargetParameterCountException ("parameters do not match signature");
-                       
-                       if ((invokeAttr & BindingFlags.ExactBinding) == 0) {
-                               if (!Binder.ConvertArgs (binder, parameters, pinfo, culture))
-                                       throw new ArgumentException ("failed to convert parameters");
-                       } else {
-                               for (int i = 0; i < pinfo.Length; i++)
-                                       if (parameters[i].GetType() != pinfo[i].ParameterType)
-                                               throw new ArgumentException ("parameters do not match signature");
-                       }
+                       binder.ConvertValues (parameters, pinfo, culture, (invokeAttr & BindingFlags.ExactBinding) != 0);
 
 #if !NET_2_1
                        if (SecurityManager.SecurityEnabled) {
@@ -521,7 +540,12 @@ namespace System.Reflection {
                                throw new MemberAccessException (String.Format ("Cannot create an instance of {0} because it is an abstract class", DeclaringType));
                        }
 
-                       Exception exc = null;
+                       return InternalInvoke (obj, parameters);
+               }
+
+               public object InternalInvoke (object obj, object[] parameters)
+               {
+                       Exception exc;
                        object o = null;
 
                        try {
@@ -536,16 +560,23 @@ namespace System.Reflection {
 
                        if (exc != null)
                                throw exc;
-                       return (obj == null) ? o : null;
+
+                       return obj == null ? o : null;
                }
 
-               public override Object Invoke (BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture) {
-                       return Invoke (null, invokeAttr, binder, parameters, culture);
+               [DebuggerHidden]
+               [DebuggerStepThrough]
+               public override Object Invoke (BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
+               {
+                       return DoInvoke (null, invokeAttr, binder, parameters, culture);
                }
 
                public override RuntimeMethodHandle MethodHandle { 
-                       get {return new RuntimeMethodHandle (mhandle);} 
+                       get {
+                               return new RuntimeMethodHandle (mhandle);
+                       } 
                }
+               
                public override MethodAttributes Attributes { 
                        get {
                                return MonoMethodInfo.GetAttributes (mhandle);