Optimize Activator path used by new() constraint to run less code
[mono.git] / mcs / class / corlib / System.Reflection / MonoMethod.cs
index 4d1c13986f3004c830367325c990c52060cb6deb..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
 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 //
 
+using System.Collections.Generic;
 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 {
        
        internal struct MonoMethodInfo 
        {
-               internal Type parent;
-               internal Type ret;
+#pragma warning disable 649    
+               private Type parent;
+               private Type ret;
                internal MethodAttributes attrs;
                internal MethodImplAttributes iattrs;
-               internal CallingConventions callconv;
+               private CallingConventions callconv;
+#pragma warning restore 649            
 
                [MethodImplAttribute(MethodImplOptions.InternalCall)]
-               internal static extern void get_method_info (IntPtr handle, out MonoMethodInfo info);
+               static extern void get_method_info (IntPtr handle, out MonoMethodInfo info);
+               
+               [MethodImplAttribute(MethodImplOptions.InternalCall)]
+               static extern int get_method_attributes (IntPtr handle);
                
+               internal static MonoMethodInfo GetMethodInfo (IntPtr handle)
+               {
+                       MonoMethodInfo info;
+                       MonoMethodInfo.get_method_info (handle, out info);
+                       return info;
+               }
+
+               internal static Type GetDeclaringType (IntPtr handle)
+               {
+                       return GetMethodInfo (handle).parent;
+               }
+
+               internal static Type GetReturnType (IntPtr handle)
+               {
+                       return GetMethodInfo (handle).ret;
+               }
+
+               internal static MethodAttributes GetAttributes (IntPtr handle)
+               {
+                       return (MethodAttributes)get_method_attributes (handle);
+               }
+
+               internal static CallingConventions GetCallingConvention (IntPtr handle)
+               {
+                       return GetMethodInfo (handle).callconv;
+               }
+
+               internal static MethodImplAttributes GetMethodImplementationFlags (IntPtr handle)
+               {
+                       return GetMethodInfo (handle).iattrs;
+               }
+
                [MethodImplAttribute(MethodImplOptions.InternalCall)]
-               internal static extern ParameterInfo[] get_parameter_info (IntPtr handle);
+               static extern ParameterInfo[] get_parameter_info (IntPtr handle, MemberInfo member);
+
+               static internal ParameterInfo[] GetParametersInfo (IntPtr handle, MemberInfo member)
+               {
+                       return get_parameter_info (handle, member);
+               }
 
                [MethodImplAttribute(MethodImplOptions.InternalCall)]
-               internal static extern UnmanagedMarshal get_retval_marshal (IntPtr handle);
+               static extern MarshalAsAttribute get_retval_marshal (IntPtr handle);
+
+               static internal ParameterInfo GetReturnParameterInfo (MonoMethod method)
+               {
+                       return new ParameterInfo (GetReturnType (method.mhandle), method, get_retval_marshal (method.mhandle));
+               }
        };
        
        /*
@@ -63,11 +114,14 @@ namespace System.Reflection {
         * the .NET reflection class hierarchy is so broken.
         */
        [Serializable()]
+       [StructLayout (LayoutKind.Sequential)]
        internal class MonoMethod : MethodInfo, ISerializable
        {
+#pragma warning disable 649
                internal IntPtr mhandle;
                string name;
                Type reftype;
+#pragma warning restore 649
 
                internal MonoMethod () {
                }
@@ -80,42 +134,60 @@ namespace System.Reflection {
                internal static extern string get_name (MethodBase method);
 
                [MethodImplAttribute(MethodImplOptions.InternalCall)]
-               internal static extern MonoMethod get_base_definition (MonoMethod method);
+               internal static extern MonoMethod get_base_method (MonoMethod method, bool definition);
 
                public override MethodInfo GetBaseDefinition ()
                {
-                       return get_base_definition (this);
+                       return get_base_method (this, true);
+               }
+
+               internal override MethodInfo GetBaseMethod ()
+               {
+                       return get_base_method (this, false);
                }
 
-#if NET_2_0 || BOOTSTRAP_NET_2_0
                public override ParameterInfo ReturnParameter {
                        get {
-                               return new ParameterInfo (ReturnType, this, MonoMethodInfo.get_retval_marshal (mhandle));
+                               return MonoMethodInfo.GetReturnParameterInfo (this);
                        }
                }
-#endif
 
                public override Type ReturnType {
                        get {
-                               MonoMethodInfo info;
-                               MonoMethodInfo.get_method_info (mhandle, out info);
-                               return info.ret;
+                               return MonoMethodInfo.GetReturnType (mhandle);
                        }
                }
                public override ICustomAttributeProvider ReturnTypeCustomAttributes { 
                        get {
-                               return new ParameterInfo (ReturnType, this, MonoMethodInfo.get_retval_marshal (mhandle));
+                               return MonoMethodInfo.GetReturnParameterInfo (this);
                        }
                }
                
-               public override MethodImplAttributes GetMethodImplementationFlags() {
-                       MonoMethodInfo info;
-                       MonoMethodInfo.get_method_info (mhandle, out info);
-                       return info.iattrs;
+               public override MethodImplAttributes GetMethodImplementationFlags ()
+               {
+                       return MonoMethodInfo.GetMethodImplementationFlags (mhandle);
+               }
+
+               public override ParameterInfo[] GetParameters ()
+               {
+                       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;
                }
 
-               public override ParameterInfo[] GetParameters() {
-                       return MonoMethodInfo.get_parameter_info (mhandle);
+               internal override ParameterInfo[] GetParametersInternal ()
+               {
+                       return MonoMethodInfo.GetParametersInfo (mhandle, this);
+               }
+               
+               internal override int GetParametersCount ()
+               {
+                       return MonoMethodInfo.GetParametersInfo (mhandle, this).Length;
                }
 
                /*
@@ -124,26 +196,29 @@ 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;
-                       ParameterInfo[] pinfo = GetParameters ();
-                       if (!Binder.ConvertArgs (binder, parameters, pinfo, culture))
-                               throw new ArgumentException ("parameters");
 
+                       /*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) {
                                // sadly Attributes doesn't tell us which kind of security action this is so
                                // we must do it the hard way - and it also means that we can skip calling
                                // Attribute (which is another an icall)
                                SecurityManager.ReflectedLinkDemandInvoke (this);
                        }
+#endif
 
-#if NET_2_0
                        if (ContainsGenericParameters)
                                throw new InvalidOperationException ("Late bound operations cannot be performed on types or methods for which ContainsGenericParameters is true.");
-#endif
 
                        Exception exc;
                        object o = null;
@@ -153,10 +228,8 @@ namespace System.Reflection {
                                // from the exceptions thrown by the called method (which need to be
                                // wrapped in TargetInvocationException).
                                o = InternalInvoke (obj, parameters, out exc);
-#if NET_2_0
                        } catch (ThreadAbortException) {
                                throw;
-#endif
 #if NET_2_1
                        } catch (MethodAccessException) {
                                throw;
@@ -171,21 +244,20 @@ namespace System.Reflection {
                }
 
                public override RuntimeMethodHandle MethodHandle { 
-                       get {return new RuntimeMethodHandle (mhandle);} 
+                       get {
+                               return new RuntimeMethodHandle (mhandle);
+                       } 
                }
+               
                public override MethodAttributes Attributes { 
                        get {
-                               MonoMethodInfo info;
-                               MonoMethodInfo.get_method_info (mhandle, out info);
-                               return info.attrs;
+                               return MonoMethodInfo.GetAttributes (mhandle);
                        } 
                }
 
                public override CallingConventions CallingConvention { 
                        get {
-                               MonoMethodInfo info;
-                               MonoMethodInfo.get_method_info (mhandle, out info);
-                               return info.callconv;
+                               return MonoMethodInfo.GetCallingConvention (mhandle);
                        }
                }
                
@@ -196,9 +268,7 @@ namespace System.Reflection {
                }
                public override Type DeclaringType {
                        get {
-                               MonoMethodInfo info;
-                               MonoMethodInfo.get_method_info (mhandle, out info);
-                               return info.parent;
+                               return MonoMethodInfo.GetDeclaringType (mhandle);
                        }
                }
                public override string Name {
@@ -229,8 +299,7 @@ namespace System.Reflection {
 
                        /* MS.NET doesn't report MethodImplAttribute */
 
-                       MonoMethodInfo info;
-                       MonoMethodInfo.get_method_info (mhandle, out info);
+                       MonoMethodInfo info = MonoMethodInfo.GetMethodInfo (mhandle);
                        if ((info.iattrs & MethodImplAttributes.PreserveSig) != 0)
                                count ++;
                        if ((info.attrs & MethodAttributes.PinvokeImpl) != 0)
@@ -253,15 +322,20 @@ namespace System.Reflection {
                        return attrs;
                }
 
+               static bool ShouldPrintFullName (Type type) {
+                       return type.IsClass && (!type.IsPointer ||
+                               (!type.GetElementType ().IsPrimitive && !type.GetElementType ().IsNested));
+               }
+
                public override string ToString () {
                        StringBuilder sb = new StringBuilder ();
-                       if (ReturnType.IsClass)
-                               sb.Append (ReturnType.ToString ());
+                       Type retType = ReturnType;
+                       if (ShouldPrintFullName (retType))
+                               sb.Append (retType.ToString ());
                        else
-                               sb.Append (ReturnType.Name);
+                               sb.Append (retType.Name);
                        sb.Append (" ");
                        sb.Append (Name);
-#if NET_2_0 || BOOTSTRAP_NET_2_0
                        if (IsGenericMethod) {
                                Type[] gen_params = GetGenericArguments ();
                                sb.Append ("[");
@@ -272,9 +346,8 @@ namespace System.Reflection {
                                }
                                sb.Append ("]");
                        }
-#endif
                        sb.Append ("(");
-                       ParameterInfo[] p = GetParameters ();
+                       ParameterInfo[] p = GetParametersInternal ();
                        for (int i = 0; i < p.Length; ++i) {
                                if (i > 0)
                                        sb.Append (", ");
@@ -282,7 +355,7 @@ namespace System.Reflection {
                                bool byref = pt.IsByRef;
                                if (byref)
                                        pt = pt.GetElementType ();
-                               if (pt.IsClass)
+                               if (ShouldPrintFullName (pt))
                                        sb.Append (pt.ToString ());
                                else
                                        sb.Append (pt.Name);
@@ -303,23 +376,37 @@ namespace System.Reflection {
                // ISerializable
                public void GetObjectData(SerializationInfo info, StreamingContext context) 
                {
-#if NET_2_0
                        Type[] genericArguments = IsGenericMethod && !IsGenericMethodDefinition
                                ? GetGenericArguments () : null;
                        MemberInfoSerializationHolder.Serialize ( info, Name, ReflectedType, ToString(), MemberTypes.Method, genericArguments);
-#else
-                       MemberInfoSerializationHolder.Serialize ( info, Name, ReflectedType, ToString(), MemberTypes.Method);
-#endif
                }
 
-#if NET_2_0 || BOOTSTRAP_NET_2_0
                public override MethodInfo MakeGenericMethod (Type [] methodInstantiation)
                {
                        if (methodInstantiation == null)
                                throw new ArgumentNullException ("methodInstantiation");
-                       foreach (Type type in methodInstantiation)
+
+                       if (!IsGenericMethodDefinition)
+                               throw new InvalidOperationException ("not a generic method definition");
+
+                       /*FIXME add GetGenericArgumentsLength() internal vcall to speed this up*/
+                       if (GetGenericArguments ().Length != methodInstantiation.Length)
+                               throw new ArgumentException ("Incorrect length");
+
+                       bool hasUserType = false;
+                       foreach (Type type in methodInstantiation) {
                                if (type == null)
                                        throw new ArgumentNullException ();
+                               if (!(type is MonoType))
+                                       hasUserType = true;
+                       }
+
+                       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)
@@ -365,54 +452,100 @@ namespace System.Reflection {
                                return DeclaringType.ContainsGenericParameters;
                        }
                }
-#endif
 
-#if NET_2_0
                public override MethodBody GetMethodBody () {
                        return GetMethodBody (mhandle);
                }
+
+#if NET_4_0
+               public override IList<CustomAttributeData> GetCustomAttributesData () {
+                       return CustomAttributeData.GetCustomAttributes (this);
+               }
 #endif
        }
        
+       [StructLayout (LayoutKind.Sequential)]
        internal class MonoCMethod : ConstructorInfo, ISerializable
        {
+#pragma warning disable 649            
                internal IntPtr mhandle;
                string name;
                Type reftype;
+#pragma warning restore 649            
                
-               public override MethodImplAttributes GetMethodImplementationFlags() {
-                       MonoMethodInfo info;
-                       MonoMethodInfo.get_method_info (mhandle, out info);
-                       return info.iattrs;
+               public override MethodImplAttributes GetMethodImplementationFlags ()
+               {
+                       return MonoMethodInfo.GetMethodImplementationFlags (mhandle);
                }
 
-               public override ParameterInfo[] GetParameters() {
-                       return MonoMethodInfo.get_parameter_info (mhandle);
+               public override ParameterInfo[] GetParameters ()
+               {
+                       return MonoMethodInfo.GetParametersInfo (mhandle, this);
+               }
+
+               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 ();
-                       if (!Binder.ConvertArgs (binder, parameters, pinfo, culture))
-                               throw new ArgumentException ("parameters");
 
+                       ParameterInfo[] pinfo = MonoMethodInfo.GetParametersInfo (mhandle, this);
+
+                       binder.ConvertValues (parameters, pinfo, culture, (invokeAttr & BindingFlags.ExactBinding) != 0);
+
+#if !NET_2_1
                        if (SecurityManager.SecurityEnabled) {
                                // sadly Attributes doesn't tell us which kind of security action this is so
                                // we must do it the hard way - and it also means that we can skip calling
                                // Attribute (which is another an icall)
                                SecurityManager.ReflectedLinkDemandInvoke (this);
                        }
+#endif
+
+                       if (obj == null && DeclaringType.ContainsGenericParameters)
+                               throw new MemberAccessException ("Cannot create an instance of " + DeclaringType + " because Type.ContainsGenericParameters is true.");
+
+                       if ((invokeAttr & BindingFlags.CreateInstance) != 0 && DeclaringType.IsAbstract) {
+                               throw new MemberAccessException (String.Format ("Cannot create an instance of {0} because it is an abstract class", DeclaringType));
+                       }
+
+                       return InternalInvoke (obj, parameters);
+               }
 
-                       Exception exc = null;
+               public object InternalInvoke (object obj, object[] parameters)
+               {
+                       Exception exc;
                        object o = null;
 
                        try {
@@ -427,29 +560,32 @@ namespace System.Reflection {
 
                        if (exc != null)
                                throw exc;
-                       return o;
+
+                       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 {
-                               MonoMethodInfo info;
-                               MonoMethodInfo.get_method_info (mhandle, out info);
-                               return info.attrs;
+                               return MonoMethodInfo.GetAttributes (mhandle);
                        } 
                }
 
                public override CallingConventions CallingConvention { 
                        get {
-                               MonoMethodInfo info;
-                               MonoMethodInfo.get_method_info (mhandle, out info);
-                               return info.callconv;
+                               return MonoMethodInfo.GetCallingConvention (mhandle);
                        }
                }
                
@@ -460,9 +596,7 @@ namespace System.Reflection {
                }
                public override Type DeclaringType {
                        get {
-                               MonoMethodInfo info;
-                               MonoMethodInfo.get_method_info (mhandle, out info);
-                               return info.parent;
+                               return MonoMethodInfo.GetDeclaringType (mhandle);
                        }
                }
                public override string Name {
@@ -485,11 +619,9 @@ namespace System.Reflection {
                        return MonoCustomAttrs.GetCustomAttributes (this, attributeType, inherit);
                }
 
-#if NET_2_0
                public override MethodBody GetMethodBody () {
                        return GetMethodBody (mhandle);
                }
-#endif
 
                public override string ToString () {
                        StringBuilder sb = new StringBuilder ();
@@ -502,6 +634,8 @@ namespace System.Reflection {
                                        sb.Append (", ");
                                sb.Append (p[i].ParameterType.Name);
                        }
+                       if (CallingConvention == CallingConventions.Any)
+                               sb.Append (", ...");
                        sb.Append (")");
                        return sb.ToString ();
                }
@@ -511,5 +645,11 @@ namespace System.Reflection {
                {
                        MemberInfoSerializationHolder.Serialize ( info, Name, ReflectedType, ToString(), MemberTypes.Constructor);
                }
+
+#if NET_4_0
+               public override IList<CustomAttributeData> GetCustomAttributesData () {
+                       return CustomAttributeData.GetCustomAttributes (this);
+               }
+#endif
        }
 }