Merge pull request #3281 from lambdageek/dev/g-ptr-array
authorAleksey Kliger (λgeek) <akliger@gmail.com>
Thu, 14 Jul 2016 15:32:58 +0000 (11:32 -0400)
committerGitHub <noreply@github.com>
Thu, 14 Jul 2016 15:32:58 +0000 (11:32 -0400)
[reflection] RuntimeType Field and Method search partly in managed

mcs/class/corlib/Mono/RuntimeHandles.cs
mcs/class/corlib/Mono/RuntimeStructs.cs
mcs/class/corlib/Mono/SafeGPtrArrayHandle.cs [new file with mode: 0644]
mcs/class/corlib/ReferenceSources/MethodBase.cs
mcs/class/corlib/ReferenceSources/RuntimeType.cs
mcs/class/corlib/corlib.dll.sources
mono/metadata/class-internals.h
mono/metadata/icall-def.h
mono/metadata/icall.c

index b83ff68550b6b352edfb3242c3d8c2b9b5bad80e..e916332db325aa43d11951dc39d38fabbbe65dac 100644 (file)
@@ -141,4 +141,48 @@ namespace Mono {
                        return i;
                }
        }
+
+       internal struct RuntimeGPtrArrayHandle {
+               unsafe RuntimeStructs.GPtrArray* value;
+
+               internal unsafe RuntimeGPtrArrayHandle (RuntimeStructs.GPtrArray* value)
+               {
+                       this.value = value;
+               }
+
+               internal unsafe RuntimeGPtrArrayHandle (IntPtr ptr)
+               {
+                       this.value = (RuntimeStructs.GPtrArray*) ptr;
+               }
+
+               internal int Length {
+                       get {
+                               unsafe {
+                                       return value->len;
+                               }
+                       }
+               }
+
+               internal IntPtr this[int i] => Lookup (i);
+
+               internal IntPtr Lookup (int i)
+               {
+                       if (i >= 0 && i < Length) {
+                               unsafe {
+                                       return value->data[i];
+                               }
+                       } else
+                               throw new IndexOutOfRangeException ();
+               }
+
+               [MethodImpl(MethodImplOptions.InternalCall)]
+               unsafe extern static void GPtrArrayFree (RuntimeStructs.GPtrArray* value, bool freeSeg);
+
+               internal static void DestroyAndFree (ref RuntimeGPtrArrayHandle h, bool freeSeg) {
+                       unsafe {
+                               GPtrArrayFree (h.value, freeSeg);
+                               h.value = null;
+                       }
+               }
+       }
 }
index 29b75c077d3660938f38e503f2ea558f3043cc4f..20cd93fdaecfa0c70be0f1ae84d492588b1b41aa 100644 (file)
@@ -37,6 +37,12 @@ namespace Mono {
                        internal uint token;
                        internal MonoClass** constraints; /* NULL terminated */
                }
+
+               // glib.h GPtrArray
+               internal unsafe struct GPtrArray {
+                       internal IntPtr* data;
+                       internal int len;
+               }
        }
 
 }
diff --git a/mcs/class/corlib/Mono/SafeGPtrArrayHandle.cs b/mcs/class/corlib/Mono/SafeGPtrArrayHandle.cs
new file mode 100644 (file)
index 0000000..e681ff4
--- /dev/null
@@ -0,0 +1,42 @@
+//
+// Safe handle class for Mono.RuntimeGPtrArrayHandle
+//
+// Authors:
+//   Aleksey Kliger <aleksey@xamarin.com>
+//   Rodrigo Kumpera <kumpera@xamarin.com>
+//
+// Copyright 2016 Dot net foundation.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+//
+
+using System;
+using System.Runtime.CompilerServices;
+
+namespace Mono {
+       internal sealed class SafeGPtrArrayHandle : IDisposable {
+               RuntimeGPtrArrayHandle handle;
+               bool freeSeg;
+
+               internal SafeGPtrArrayHandle (IntPtr ptr, bool freeSeg)
+               {
+                       handle = new RuntimeGPtrArrayHandle (ptr);
+                       this.freeSeg = freeSeg;
+               }
+
+               public void Dispose ()
+               {
+                       RuntimeGPtrArrayHandle.DestroyAndFree (ref handle, freeSeg);
+                       GC.SuppressFinalize (this);
+               }
+
+               internal int Length {
+                       get {
+                               return handle.Length;
+                       }
+               }
+
+               internal IntPtr this[int i] => handle[i];
+       }
+
+
+}
index 2fb847a6ef9638ec4aae614a2358d7ef59c8d913..8cd000563288e73fec2c2cce006fe964df4a6f7a 100644 (file)
@@ -46,7 +46,12 @@ namespace System.Reflection
 
                internal static MethodBase GetMethodFromHandleNoGenericCheck (RuntimeMethodHandle handle)
                {
-                       return GetMethodFromHandleInternalType (handle.Value, IntPtr.Zero);
+                       return GetMethodFromHandleInternalType_native (handle.Value, IntPtr.Zero, false);
+               }
+
+               internal static MethodBase GetMethodFromHandleNoGenericCheck (RuntimeMethodHandle handle, RuntimeTypeHandle reflectedType)
+               {
+                       return GetMethodFromHandleInternalType_native (handle.Value, reflectedType.Value, false);
                }
 
                [MethodImplAttribute (MethodImplOptions.InternalCall)]
@@ -57,7 +62,12 @@ namespace System.Reflection
                        return GetMethodBodyInternal (handle);
                }
 
+               static MethodBase GetMethodFromHandleInternalType (IntPtr method_handle, IntPtr type_handle) {
+                       return GetMethodFromHandleInternalType_native (method_handle, type_handle, true);
+               }
+
                [MethodImplAttribute (MethodImplOptions.InternalCall)]
-               extern static MethodBase GetMethodFromHandleInternalType (IntPtr method_handle, IntPtr type_handle);            
+               internal extern static MethodBase GetMethodFromHandleInternalType_native (IntPtr method_handle, IntPtr type_handle, bool genericCheck);
+
        }
-}
\ No newline at end of file
+}
index 4981f4175a15c4b1846a98a2bf2f75e4815864e8..3710350e09e52df9447076dce26d89bf23a0d59c 100644 (file)
@@ -472,13 +472,42 @@ namespace System
                static extern Type MakeGenericType (Type gt, Type [] types);
 
                [MethodImplAttribute(MethodImplOptions.InternalCall)]
-               internal extern RuntimeMethodInfo[] GetMethodsByName (string name, BindingFlags bindingAttr, bool ignoreCase, Type reflected_type);
+               internal extern IntPtr GetMethodsByName_native (string name, BindingFlags bindingAttr, bool ignoreCase);
+
+               internal RuntimeMethodInfo[] GetMethodsByName (string name, BindingFlags bindingAttr, bool ignoreCase, RuntimeType reflectedType)
+               {
+                       var refh = new RuntimeTypeHandle (reflectedType);
+                       using (var h = new Mono.SafeGPtrArrayHandle (GetMethodsByName_native (name, bindingAttr, ignoreCase), false)) {
+                               var n = h.Length;
+                               var a = new RuntimeMethodInfo [n];
+                               for (int i = 0; i < n; i++) {
+                                       var mh = new RuntimeMethodHandle (h[i]);
+                                       a[i] = (RuntimeMethodInfo) MethodBase.GetMethodFromHandleNoGenericCheck (mh, refh);
+                               }
+                               return a;
+                       }
+               }
 
                [MethodImplAttribute(MethodImplOptions.InternalCall)]
                extern RuntimePropertyInfo[] GetPropertiesByName (string name, BindingFlags bindingAttr, bool icase, Type reflected_type);              
 
                [MethodImplAttribute(MethodImplOptions.InternalCall)]
-               extern RuntimeConstructorInfo[] GetConstructors_internal (BindingFlags bindingAttr, Type reflected_type);
+               extern IntPtr GetConstructors_native (BindingFlags bindingAttr);
+
+               RuntimeConstructorInfo[] GetConstructors_internal (BindingFlags bindingAttr, RuntimeType reflectedType)
+               {
+                       var refh = new RuntimeTypeHandle (reflectedType);
+                       using (var h = new Mono.SafeGPtrArrayHandle (GetConstructors_native (bindingAttr), false)) {
+                               var n = h.Length;
+                               var a = new RuntimeConstructorInfo [n];
+                               for (int i = 0; i < n; i++) {
+                                       var mh = new RuntimeMethodHandle (h[i]);
+                                       a[i] = (RuntimeConstructorInfo) MethodBase.GetMethodFromHandleNoGenericCheck (mh, refh);
+                               }
+                               return a;
+                       }
+               }
+
 
                public override InterfaceMapping GetInterfaceMap (Type ifaceType)
                {
@@ -630,7 +659,21 @@ namespace System
                extern RuntimeEventInfo[] GetEvents_internal (string name, BindingFlags bindingAttr, Type reflected_type);
 
                [MethodImplAttribute(MethodImplOptions.InternalCall)]
-               extern RuntimeFieldInfo[] GetFields_internal (string name, BindingFlags bindingAttr, Type reflected_type);
+               extern IntPtr GetFields_native (string name, BindingFlags bindingAttr);
+
+               RuntimeFieldInfo[] GetFields_internal (string name, BindingFlags bindingAttr, RuntimeType reflectedType)
+               {
+                       var refh = new RuntimeTypeHandle (reflectedType);
+                       using (var h = new Mono.SafeGPtrArrayHandle (GetFields_native (name, bindingAttr), false)) {
+                               int n = h.Length;
+                               var a = new RuntimeFieldInfo[n];
+                               for (int i = 0; i < n; i++) {
+                                       var fh = new RuntimeFieldHandle (h[i]);
+                                       a[i] = (RuntimeFieldInfo) FieldInfo.GetFieldFromHandle (fh, refh);
+                               }
+                               return a;
+                       }
+               }
 
                [MethodImplAttribute(MethodImplOptions.InternalCall)]
                public extern override Type[] GetInterfaces();
index 199eb737b899b8eb3d35a6529f6476c17c4079b4..b36d3d446bc4cea25a3674a2ca7ffe6724df5484 100644 (file)
@@ -25,6 +25,7 @@ Mono.Globalization.Unicode/NormalizationTableUtil.cs
 Mono/Runtime.cs
 Mono/RuntimeStructs.cs
 Mono/RuntimeHandles.cs
+Mono/SafeGPtrArrayHandle.cs
 Mono/DataConverter.cs
 Mono.Interop/ComInteropProxy.cs
 Mono.Interop/IDispatch.cs
index 3ce27a7119e6a207fac4d44e920e91de9d12e9f4..f51c979a50fab8ab5d230010e483867b188a7ed5 100644 (file)
@@ -1403,7 +1403,7 @@ void
 mono_unload_interface_id (MonoClass *klass);
 
 GPtrArray*
-mono_class_get_methods_by_name (MonoClass *klass, const char *name, guint32 bflags, gboolean ignore_case, gboolean allow_ctors, MonoException **ex);
+mono_class_get_methods_by_name (MonoClass *klass, const char *name, guint32 bflags, gboolean ignore_case, gboolean allow_ctors, MonoError *error);
 
 char*
 mono_class_full_name (MonoClass *klass);
index 1998506166145621b55257c4afbbb9b258f7ffb4..f27705f32182c169244da0d3b2686a5dcdc3fff0 100644 (file)
@@ -65,6 +65,9 @@ ICALL(RUNTIME_12, "GetNativeStackTrace", ves_icall_Mono_Runtime_GetNativeStackTr
 ICALL_TYPE(RTCLASS, "Mono.RuntimeClassHandle", RTCLASS_1)
 ICALL(RTCLASS_1, "GetTypeFromClass", ves_icall_Mono_RuntimeClassHandle_GetTypeFromClass)
 
+ICALL_TYPE(RTPTRARRAY, "Mono.RuntimeGPtrArrayHandle", RTPTRARRAY_1)
+ICALL(RTPTRARRAY_1, "GPtrArrayFree", ves_icall_Mono_RuntimeGPtrArrayHandle_GPtrArrayFree)
+
 #ifndef PLATFORM_RO_FS
 ICALL_TYPE(KPAIR, "Mono.Security.Cryptography.KeyPairPersistence", KPAIR_1)
 ICALL(KPAIR_1, "_CanSecure", ves_icall_Mono_Security_Cryptography_KeyPairPersistence_CanSecure)
@@ -556,7 +559,7 @@ ICALL(MEMBERI_1, "get_MetadataToken", ves_icall_reflection_get_token)
 ICALL_TYPE(MBASE, "System.Reflection.MethodBase", MBASE_1)
 ICALL(MBASE_1, "GetCurrentMethod", ves_icall_GetCurrentMethod)
 ICALL(MBASE_2, "GetMethodBodyInternal", ves_icall_System_Reflection_MethodBase_GetMethodBodyInternal)
-ICALL(MBASE_4, "GetMethodFromHandleInternalType", ves_icall_System_Reflection_MethodBase_GetMethodFromHandleInternalType)
+ICALL(MBASE_4, "GetMethodFromHandleInternalType_native", ves_icall_System_Reflection_MethodBase_GetMethodFromHandleInternalType_native)
 
 ICALL_TYPE(MODULE, "System.Reflection.Module", MODULE_1)
 ICALL(MODULE_1, "Close", ves_icall_System_Reflection_Module_Close)
@@ -733,16 +736,16 @@ ICALL(MHAN_1, "GetFunctionPointer", ves_icall_RuntimeMethodHandle_GetFunctionPoi
 
 ICALL_TYPE(RT, "System.RuntimeType", RT_1)
 ICALL(RT_1, "CreateInstanceInternal", ves_icall_System_Activator_CreateInstanceInternal)
-ICALL(RT_2, "GetConstructors_internal", ves_icall_RuntimeType_GetConstructors_internal)
+ICALL(RT_2, "GetConstructors_native", ves_icall_RuntimeType_GetConstructors_native)
 ICALL(RT_30, "GetCorrespondingInflatedConstructor", ves_icall_RuntimeType_GetCorrespondingInflatedMethod)
 ICALL(RT_31, "GetCorrespondingInflatedMethod", ves_icall_RuntimeType_GetCorrespondingInflatedMethod)
 ICALL(RT_3, "GetEvents_internal", ves_icall_RuntimeType_GetEvents_internal)
-ICALL(RT_5, "GetFields_internal", ves_icall_RuntimeType_GetFields_internal)
+ICALL(RT_5, "GetFields_native", ves_icall_RuntimeType_GetFields_native)
 ICALL(RT_6, "GetGenericArgumentsInternal", ves_icall_RuntimeType_GetGenericArguments)
 ICALL(RT_9, "GetGenericParameterPosition", ves_icall_RuntimeType_GetGenericParameterPosition)
 ICALL(RT_10, "GetInterfaceMapData", ves_icall_RuntimeType_GetInterfaceMapData)
 ICALL(RT_11, "GetInterfaces", ves_icall_RuntimeType_GetInterfaces)
-ICALL(RT_12, "GetMethodsByName", ves_icall_RuntimeType_GetMethodsByName)
+ICALL(RT_12, "GetMethodsByName_native", ves_icall_RuntimeType_GetMethodsByName_native)
 ICALL(RT_13, "GetNestedTypes_internal", ves_icall_RuntimeType_GetNestedTypes)
 ICALL(RT_14, "GetPacking", ves_icall_RuntimeType_GetPacking)
 ICALL(RT_15, "GetPropertiesByName", ves_icall_RuntimeType_GetPropertiesByName)
index 94081c73fd39db09f93646f3441788a9892b25ff..c3dd869958e1016950ab9aca78095f8756117700 100644 (file)
@@ -1535,6 +1535,12 @@ ves_icall_Mono_RuntimeClassHandle_GetTypeFromClass (MonoClass *klass)
        return mono_class_get_type (klass);
 }
 
+ICALL_EXPORT void
+ves_icall_Mono_RuntimeGPtrArrayHandle_GPtrArrayFree (GPtrArray *ptr_array, MonoBoolean freeSeg)
+{
+       g_ptr_array_free (ptr_array, freeSeg);
+}
+
 /* System.TypeCode */
 typedef enum {
        TYPECODE_EMPTY,
@@ -3741,38 +3747,32 @@ enum {
        BFLAGS_OptionalParamBinding = 0x40000
 };
 
-ICALL_EXPORT MonoArray*
-ves_icall_RuntimeType_GetFields_internal (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoReflectionType *reftype)
+ICALL_EXPORT GPtrArray*
+ves_icall_RuntimeType_GetFields_native (MonoReflectionType *type, MonoString *name, guint32 bflags)
 {
        MonoError error;
        MonoDomain *domain; 
-       MonoClass *startklass, *klass, *refklass;
-       MonoArray *res;
-       MonoObject *member;
-       int i, match;
+       MonoClass *startklass, *klass;
+       int match;
        gpointer iter;
        char *utf8_name = NULL;
        int (*compare_func) (const char *s1, const char *s2) = NULL;    
        MonoClassField *field;
-       MonoPtrArray tmp_array;
 
        domain = ((MonoObject *)type)->vtable->domain;
        if (type->type->byref) {
-               MonoArray *result = mono_array_new_checked (domain, mono_defaults.field_info_class, 0, &error);
-               mono_error_set_pending_exception (&error);
-               return result;
+               return g_ptr_array_new ();
        }
 
        klass = startklass = mono_class_from_mono_type (type->type);
-       refklass = mono_class_from_mono_type (reftype->type);
 
-       mono_ptr_array_init (tmp_array, 2, MONO_ROOT_SOURCE_REFLECTION, "temporary reflection fields list");
+       GPtrArray *ptr_array = g_ptr_array_sized_new (16);
        
 handle_parent: 
        if (mono_class_has_failure (klass)) {
-               mono_ptr_array_destroy (tmp_array);
-               mono_set_pending_exception (mono_class_get_exception_for_failure (klass));
-               return NULL;
+               mono_error_init (&error);
+               mono_error_set_for_class_failure (&error, klass);
+               goto fail;
        }
 
        iter = NULL;
@@ -3816,29 +3816,17 @@ handle_parent:
                                continue;
                }
 
-               member = (MonoObject*)mono_field_get_object_checked (domain, refklass, field, &error);
-               if (!mono_error_ok (&error))
-                   goto fail;
-               mono_ptr_array_append (tmp_array, member);
+               g_ptr_array_add (ptr_array, field);
        }
        if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
                goto handle_parent;
 
-       res = mono_array_new_cached (domain, mono_defaults.field_info_class, mono_ptr_array_size (tmp_array), &error);
-       if (!is_ok (&error))
-               goto fail;
-
-       for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
-               mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
-
-       mono_ptr_array_destroy (tmp_array);
-
        if (utf8_name != NULL)
                g_free (utf8_name);
+       return ptr_array;
 
-       return res;
 fail:
-       mono_ptr_array_destroy (tmp_array);
+       g_ptr_array_free (ptr_array, FALSE);
        mono_error_set_pending_exception (&error);
        return NULL;
 }
@@ -3859,7 +3847,7 @@ method_nonpublic (MonoMethod* method, gboolean start_klass)
 }
 
 GPtrArray*
-mono_class_get_methods_by_name (MonoClass *klass, const char *name, guint32 bflags, gboolean ignore_case, gboolean allow_ctors, MonoException **ex)
+mono_class_get_methods_by_name (MonoClass *klass, const char *name, guint32 bflags, gboolean ignore_case, gboolean allow_ctors, MonoError *error)
 {
        GPtrArray *array;
        MonoClass *startklass;
@@ -3873,7 +3861,7 @@ mono_class_get_methods_by_name (MonoClass *klass, const char *name, guint32 bfla
 
        array = g_ptr_array_new ();
        startklass = klass;
-       *ex = NULL;
+       mono_error_init (error);
 
        if (name != NULL)
                compare_func = (ignore_case) ? mono_utf8_strcasecmp : strcmp;
@@ -3962,49 +3950,24 @@ loader_error:
                g_free (method_slots);
        g_ptr_array_free (array, TRUE);
 
-       if (mono_class_has_failure (klass)) {
-               *ex = mono_class_get_exception_for_failure (klass);
-       } else {
-               *ex = mono_get_exception_execution_engine ("Unknown error");
-       }
+       g_assert (mono_class_has_failure (klass));
+       mono_error_set_for_class_failure (error, klass);
        return NULL;
 }
 
-ICALL_EXPORT MonoArray*
-ves_icall_RuntimeType_GetMethodsByName (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoBoolean ignore_case, MonoReflectionType *reftype)
+ICALL_EXPORT GPtrArray*
+ves_icall_RuntimeType_GetMethodsByName_native (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoBoolean ignore_case)
 {
-       static MonoClass *MethodInfo_array;
        MonoError error;
        MonoDomain *domain; 
-       MonoArray *res;
-       MonoVTable *array_vtable;
-       MonoException *ex = NULL;
        const char *mname = NULL;
        GPtrArray *method_array;
-       MonoClass *klass, *refklass;
-       int i;
-
-       mono_error_init (&error);
-
-       if (!MethodInfo_array) {
-               MonoClass *klass = mono_array_class_get (mono_defaults.method_info_class, 1);
-               mono_memory_barrier ();
-               MethodInfo_array = klass;
-       }
+       MonoClass *klass;
 
        klass = mono_class_from_mono_type (type->type);
-       refklass = mono_class_from_mono_type (reftype->type);
        domain = ((MonoObject *)type)->vtable->domain;
-       array_vtable = mono_class_vtable_full (domain, MethodInfo_array, &error);
-       if (!is_ok (&error)) {
-               mono_error_set_pending_exception (&error);
-               return NULL;
-       }
        if (type->type->byref) {
-               res = mono_array_new_specific_checked (array_vtable, 0, &error);
-               mono_error_set_pending_exception (&error);
-
-               return res;
+               return g_ptr_array_new ();
        }
 
        if (name) {
@@ -4013,66 +3976,38 @@ ves_icall_RuntimeType_GetMethodsByName (MonoReflectionType *type, MonoString *na
                    return NULL;
        }
 
-       method_array = mono_class_get_methods_by_name (klass, mname, bflags, ignore_case, FALSE, &ex);
+       method_array = mono_class_get_methods_by_name (klass, mname, bflags, ignore_case, FALSE, &error);
        g_free ((char*)mname);
-       if (ex) {
-               mono_set_pending_exception (ex);
-               return NULL;
-       }
-
-       res = mono_array_new_specific_checked (array_vtable, method_array->len, &error);
-       if (!mono_error_ok (&error)) {
-               mono_error_set_pending_exception (&error);
-               return NULL;
-       }
-
-       for (i = 0; i < method_array->len; ++i) {
-               MonoMethod *method = (MonoMethod *)g_ptr_array_index (method_array, i);
-               MonoReflectionMethod *rm = mono_method_get_object_checked (domain, method, refklass, &error);
-               if (!mono_error_ok (&error))
-                       goto failure;
-               mono_array_setref (res, i, rm);
-       }
-
-failure:
-       g_ptr_array_free (method_array, TRUE);
-       if (!mono_error_ok (&error))
-               mono_set_pending_exception (mono_error_convert_to_exception (&error));
-       return res;
+       mono_error_set_pending_exception (&error);
+       return method_array;
 }
 
-ICALL_EXPORT MonoArray*
-ves_icall_RuntimeType_GetConstructors_internal (MonoReflectionType *type, guint32 bflags, MonoReflectionType *reftype)
+ICALL_EXPORT GPtrArray*
+ves_icall_RuntimeType_GetConstructors_native (MonoReflectionType *type, guint32 bflags)
 {
-       MonoDomain *domain; 
-       MonoClass *startklass, *klass, *refklass;
-       MonoArray *res = NULL;
+       MonoClass *startklass, *klass;
        MonoMethod *method;
-       MonoObject *member;
-       int i, match;
+       int match;
        gpointer iter = NULL;
-       MonoPtrArray tmp_array;
+       GPtrArray *res_array;
        MonoError error;
        
-       domain = ((MonoObject *)type)->vtable->domain;
        if (type->type->byref) {
-               res = mono_array_new_cached (domain, mono_defaults.method_info_class, 0, &error);
-               mono_error_set_pending_exception (&error);
-               return res;
+               return g_ptr_array_new ();
        }
 
-       mono_ptr_array_init (tmp_array, 4, MONO_ROOT_SOURCE_REFLECTION, "temporary reflection constructors list"); /*FIXME, guestimating*/
-
-
        klass = startklass = mono_class_from_mono_type (type->type);
-       refklass = mono_class_from_mono_type (reftype->type);
 
        mono_class_setup_methods (klass);
        if (mono_class_has_failure (klass)) {
-               mono_set_pending_exception (mono_class_get_exception_for_failure (klass));
-               goto leave;
+               mono_error_init (&error);
+               mono_error_set_for_class_failure (&error, klass);
+               mono_error_set_pending_exception (&error);
+               return NULL;
        }
 
+       res_array = g_ptr_array_sized_new (4); /* FIXME, guestimating */
+
        iter = NULL;
        while ((method = mono_class_get_methods (klass, &iter))) {
                match = 0;
@@ -4099,24 +4034,10 @@ ves_icall_RuntimeType_GetConstructors_internal (MonoReflectionType *type, guint3
 
                if (!match)
                        continue;
-               member = (MonoObject*)mono_method_get_object_checked (domain, method, refklass, &error);
-               if (mono_error_set_pending_exception (&error))
-                       goto leave;
-
-               mono_ptr_array_append (tmp_array, member);
+               g_ptr_array_add (res_array, method);
        }
 
-       res = mono_array_new_cached (domain, mono_class_get_constructor_info_class (), mono_ptr_array_size (tmp_array), &error);
-       if (mono_error_set_pending_exception (&error))
-               goto leave;
-
-       for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
-               mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
-
-leave:
-       mono_ptr_array_destroy (tmp_array);
-
-       return res;
+       return res_array;
 }
 
 static guint
@@ -5349,21 +5270,24 @@ mono_method_get_equivalent_method (MonoMethod *method, MonoClass *klass)
 }
 
 ICALL_EXPORT MonoReflectionMethod*
-ves_icall_System_Reflection_MethodBase_GetMethodFromHandleInternalType (MonoMethod *method, MonoType *type)
+ves_icall_System_Reflection_MethodBase_GetMethodFromHandleInternalType_native (MonoMethod *method, MonoType *type, MonoBoolean generic_check)
 {
        MonoReflectionMethod *res = NULL;
        MonoError error;
        MonoClass *klass;
-       if (type) {
+       if (type && generic_check) {
                klass = mono_class_from_mono_type (type);
-               if (mono_class_get_generic_type_definition (method->klass) != mono_class_get_generic_type_definition (klass)) 
+               if (mono_class_get_generic_type_definition (method->klass) != mono_class_get_generic_type_definition (klass))
                        return NULL;
+
                if (method->klass != klass) {
                        method = mono_method_get_equivalent_method (method, klass);
                        if (!method)
                                return NULL;
                }
-       } else
+       } else if (type)
+               klass = mono_class_from_mono_type (type);
+       else
                klass = method->klass;
        res = mono_method_get_object_checked (mono_domain_get (), method, klass, &error);
        mono_error_set_pending_exception (&error);