[corlib] Rewrite RuntimeType.GetGenericParameterConstraints (#3260)
authorAleksey Kliger (λgeek) <akliger@gmail.com>
Tue, 12 Jul 2016 15:16:59 +0000 (11:16 -0400)
committerGitHub <noreply@github.com>
Tue, 12 Jul 2016 15:16:59 +0000 (11:16 -0400)
* [corlib] Rewrite RuntimeType.GetGenericParameterConstraints

using managed code for managed object manipulation by surfacing the
native MonoGenericParamInfo struct to managed code as Mono.RuntimeStructs.GenericParamInfo

* [corlib] RuntimeType::GetGenericParameterAttributes can be managed code now.

* [corlib] Fix x86 breakage

RuntimeTypeHandle.GetGenericParameterInfo returns a pointer
Not a struct that's the same size as a pointer.  On the x86 Linux
calling convention they behave differently.

mcs/class/corlib/Mono/RuntimeHandles.cs
mcs/class/corlib/Mono/RuntimeStructs.cs
mcs/class/corlib/ReferenceSources/RuntimeType.cs
mcs/class/corlib/System/RuntimeTypeHandle.cs
mono/metadata/class-internals.h
mono/metadata/icall-def.h
mono/metadata/icall.c

index f6d0827bab3b3538e96f96b75f246eaff419b271..b83ff68550b6b352edfb3242c3d8c2b9b5bad80e 100644 (file)
@@ -10,6 +10,7 @@
 //
 
 using System;
+using System.Reflection;
 using System.Runtime.CompilerServices;
 
 namespace Mono {
@@ -92,4 +93,52 @@ namespace Mono {
                        }
                }
        }
+
+       internal struct RuntimeGenericParamInfoHandle {
+               unsafe RuntimeStructs.GenericParamInfo* value;
+
+               internal unsafe RuntimeGenericParamInfoHandle (RuntimeStructs.GenericParamInfo* value)
+               {
+                       this.value = value;
+               }
+
+               internal unsafe RuntimeGenericParamInfoHandle (IntPtr ptr)
+               {
+                       this.value = (RuntimeStructs.GenericParamInfo*) ptr;
+               }
+
+
+               internal Type[] Constraints { get { return GetConstraints (); } }
+
+               internal GenericParameterAttributes Attributes {
+                       get {
+                               unsafe {
+                                       return (GenericParameterAttributes) value->flags;
+                               }
+                       }
+               }
+
+               Type[] GetConstraints () {
+                       int n = GetConstraintsCount ();
+                       var a = new Type[n];
+                       for (int i = 0; i < n; i++) {
+                               unsafe {
+                                       RuntimeClassHandle c = new RuntimeClassHandle (value->constraints[i]);
+                                       a[i] = Type.GetTypeFromHandle (c.GetTypeHandle ());
+                               }
+                       }
+                       return a;
+               }
+
+               int GetConstraintsCount () {
+                       int i = 0;
+                       unsafe {
+                               RuntimeStructs.MonoClass** p = value->constraints;
+                               while (p != null && *p != null)  {
+                                       p++; i++;
+                               }
+                       }
+                       return i;
+               }
+       }
 }
index c445346326295671e245ae4e25d9f50e83948734..29b75c077d3660938f38e503f2ea558f3043cc4f 100644 (file)
@@ -28,6 +28,15 @@ namespace Mono {
 
                internal struct MonoClass {
                }
+
+               // class-internals.h MonoGenericParamInfo
+               internal unsafe struct GenericParamInfo {
+                       internal MonoClass* pklass;
+                       internal IntPtr name;
+                       internal ushort flags;
+                       internal uint token;
+                       internal MonoClass** constraints; /* NULL terminated */
+               }
        }
 
 }
index f577efcd5ca871464b7ed8ca65b028a35086fd98..4981f4175a15c4b1846a98a2bf2f75e4815864e8 100644 (file)
@@ -452,7 +452,8 @@ namespace System
                                throw new InvalidOperationException(Environment.GetResourceString("Arg_NotGenericParameter"));
                        Contract.EndContractBlock();
 
-                       Type[] constraints = GetGenericParameterConstraints_impl ();
+                       var paramInfo = new Mono.RuntimeGenericParamInfoHandle (RuntimeTypeHandle.GetGenericParameterInfo (this));
+                       Type[] constraints = paramInfo.Constraints;
 
                        if (constraints == null)
                                constraints = EmptyArray<Type>.Value;
@@ -618,11 +619,9 @@ namespace System
                [MethodImplAttribute(MethodImplOptions.InternalCall)]
                extern Type[] GetGenericArgumentsInternal (bool runtimeArray);
 
-               [MethodImplAttribute(MethodImplOptions.InternalCall)]
-               extern GenericParameterAttributes GetGenericParameterAttributes ();
-
-               [MethodImplAttribute(MethodImplOptions.InternalCall)]
-               extern Type[] GetGenericParameterConstraints_impl ();
+               GenericParameterAttributes GetGenericParameterAttributes () {
+                       return (new Mono.RuntimeGenericParamInfoHandle (RuntimeTypeHandle.GetGenericParameterInfo (this))).Attributes;
+               }
 
                [MethodImplAttribute(MethodImplOptions.InternalCall)]
                extern int GetGenericParameterPosition ();
index eb6c42f097648ff77d290c66f24e2a600768da87..cd51c87a2a87a63a70d98b04df3233279ef5a170 100644 (file)
@@ -243,5 +243,9 @@ namespace System
 
                [MethodImplAttribute(MethodImplOptions.InternalCall)]
                internal extern static bool IsGenericTypeDefinition (RuntimeType type);
+
+               [MethodImplAttribute(MethodImplOptions.InternalCall)]
+               internal extern static IntPtr GetGenericParameterInfo (RuntimeType type);
+
        }
 }
index b72657fda72f1e55b2195782581692a490447c74..3ce27a7119e6a207fac4d44e920e91de9d12e9f4 100644 (file)
@@ -573,6 +573,7 @@ struct _MonoGenericParam {
 };
 
 /* Additional details about a MonoGenericParam */
+/* Keep in sync with managed Mono.RuntimeStructs.GenericParamInfo */
 typedef struct {
        MonoClass *pklass;              /* The corresponding `MonoClass'. */
        const char *name;
index 9da2c8308df60fff663c26e1bd506914d954bf1b..1998506166145621b55257c4afbbb9b258f7ffb4 100644 (file)
@@ -739,8 +739,6 @@ ICALL(RT_31, "GetCorrespondingInflatedMethod", ves_icall_RuntimeType_GetCorrespo
 ICALL(RT_3, "GetEvents_internal", ves_icall_RuntimeType_GetEvents_internal)
 ICALL(RT_5, "GetFields_internal", ves_icall_RuntimeType_GetFields_internal)
 ICALL(RT_6, "GetGenericArgumentsInternal", ves_icall_RuntimeType_GetGenericArguments)
-ICALL(RT_7, "GetGenericParameterAttributes", ves_icall_RuntimeType_GetGenericParameterAttributes)
-ICALL(RT_8, "GetGenericParameterConstraints_impl", ves_icall_RuntimeType_GetGenericParameterConstraints)
 ICALL(RT_9, "GetGenericParameterPosition", ves_icall_RuntimeType_GetGenericParameterPosition)
 ICALL(RT_10, "GetInterfaceMapData", ves_icall_RuntimeType_GetInterfaceMapData)
 ICALL(RT_11, "GetInterfaces", ves_icall_RuntimeType_GetInterfaces)
@@ -768,6 +766,7 @@ ICALL(RTH_2, "GetAssembly", ves_icall_RuntimeTypeHandle_GetAssembly)
 ICALL(RTH_3, "GetAttributes", ves_icall_RuntimeTypeHandle_GetAttributes)
 ICALL(RTH_4, "GetBaseType", ves_icall_RuntimeTypeHandle_GetBaseType)
 ICALL(RTH_5, "GetElementType", ves_icall_RuntimeTypeHandle_GetElementType)
+ICALL(RTH_19, "GetGenericParameterInfo", ves_icall_RuntimeTypeHandle_GetGenericParameterInfo)
 ICALL(RTH_6, "GetGenericTypeDefinition_impl", ves_icall_RuntimeTypeHandle_GetGenericTypeDefinition_impl)
 ICALL(RTH_7, "GetMetadataToken", ves_icall_reflection_get_token)
 ICALL(RTH_8, "GetModule", ves_icall_RuntimeTypeHandle_GetModule)
index 73d2491a35beca078d7b476b7ea50658067b04a8..94081c73fd39db09f93646f3441788a9892b25ff 100644 (file)
@@ -2881,45 +2881,10 @@ ves_icall_RuntimeType_GetGenericParameterPosition (MonoReflectionType *type)
        return -1;
 }
 
-ICALL_EXPORT GenericParameterAttributes
-ves_icall_RuntimeType_GetGenericParameterAttributes (MonoReflectionType *type)
+ICALL_EXPORT MonoGenericParamInfo *
+ves_icall_RuntimeTypeHandle_GetGenericParameterInfo (MonoReflectionType *type)
 {
-       g_assert (IS_MONOTYPE (type));
-       g_assert (is_generic_parameter (type->type));
-       return (GenericParameterAttributes)mono_generic_param_info (type->type->data.generic_param)->flags;
-}
-
-ICALL_EXPORT MonoArray *
-ves_icall_RuntimeType_GetGenericParameterConstraints (MonoReflectionType *type)
-{
-       MonoError error;
-       MonoReflectionType *rt;
-       MonoGenericParamInfo *param_info;
-       MonoDomain *domain;
-       MonoClass **ptr;
-       MonoArray *res;
-       int i, count;
-
-       g_assert (IS_MONOTYPE (type));
-
-       domain = mono_object_domain (type);
-       param_info = mono_generic_param_info (type->type->data.generic_param);
-       for (count = 0, ptr = param_info->constraints; ptr && *ptr; ptr++, count++)
-               ;
-
-       res = mono_array_new_checked (domain, mono_defaults.runtimetype_class, count, &error);
-       if (mono_error_set_pending_exception (&error))
-               return NULL;
-       for (i = 0; i < count; i++) {
-               rt = mono_type_get_object_checked (domain, &param_info->constraints [i]->byval_arg, &error);
-               if (mono_error_set_pending_exception (&error))
-                       return NULL;
-
-               mono_array_setref (res, i, rt);
-       }
-
-
-       return res;
+       return mono_generic_param_info (type->type->data.generic_param);
 }
 
 ICALL_EXPORT MonoBoolean