Jelajahi Sumber

Lazy load custom attribute data arguments.

in mcs/class/corlib/System.Reflection:

	* CustomAttributeData.cs: This now receives only the information
	required to later load argument data. This information is stored
	in a new field that is later discarded.

in mono/mono/metadata:

	* icall-def.h: Add new icall from CustomAttributeData.

	* object-internals.h: Add new reflection.c function.

	* reflection.c (mono_reflection_get_custom_attrs_info): Don't
	init the class when retrieving custom attributes since we must
	handle broken types.

	* reflection.c (create_custom_attr_data): Don't resolve cattr
	arguments eagerly. Instead pass enough information to
	CustomAttributeData so it can later on create them.

	* reflection.c (mono_reflection_resolve_custom_attribute_data):
	new icall used to create the cattr data arguments.

	This is required to match MS behavior and fix some of the issues
	triggered by trying to compile MD.

	Fixes #630074
Rodrigo Kumpera 15 tahun lalu
induk
melakukan
2913acfc8f

+ 34 - 7
mcs/class/corlib/System.Reflection/CustomAttributeData.cs

@@ -43,9 +43,17 @@ namespace System.Reflection {
 	public sealed
 #endif
 	class CustomAttributeData {
+		class LazyCAttrData {
+			internal Assembly assembly;
+			internal IntPtr data;
+			internal uint data_length;
+		}
+
 		ConstructorInfo ctorInfo;
 		IList<CustomAttributeTypedArgument> ctorArgs;
 		IList<CustomAttributeNamedArgument> namedArgs;
+		LazyCAttrData lazyData;
+
 
 #if NET_4_0
 		protected CustomAttributeData ()
@@ -53,17 +61,34 @@ namespace System.Reflection {
 		}
 #endif
 
-		internal CustomAttributeData (ConstructorInfo ctorInfo, object [] ctorArgs, object [] namedArgs)
+		internal CustomAttributeData (ConstructorInfo ctorInfo, Assembly assembly, IntPtr data, uint data_length)
 		{
 			this.ctorInfo = ctorInfo;
-			
-			this.ctorArgs = Array.AsReadOnly<CustomAttributeTypedArgument> 
-				(ctorArgs != null ? UnboxValues<CustomAttributeTypedArgument> (ctorArgs) : new CustomAttributeTypedArgument [0]);
-			
-			this.namedArgs = Array.AsReadOnly<CustomAttributeNamedArgument> 
-				(namedArgs != null ? UnboxValues<CustomAttributeNamedArgument> (namedArgs) : new CustomAttributeNamedArgument [0]);
+			this.lazyData = new LazyCAttrData ();
+			this.lazyData.assembly = assembly;
+			this.lazyData.data = data;
+			this.lazyData.data_length = data_length;
 		}
 
+		[MethodImplAttribute (MethodImplOptions.InternalCall)]
+		static extern void ResolveArgumentsInternal (ConstructorInfo ctor, Assembly assembly, IntPtr data, uint data_length, out object[] ctorArgs, out object[] namedArgs); 
+
+		void ResolveArguments ()
+		{
+			object[] ctor_args, named_args;
+			if (lazyData == null)
+				return;
+
+			ResolveArgumentsInternal (ctorInfo, lazyData.assembly, lazyData.data, lazyData.data_length, out ctor_args, out named_args);
+
+			this.ctorArgs = Array.AsReadOnly<CustomAttributeTypedArgument>
+				(ctor_args != null ? UnboxValues<CustomAttributeTypedArgument> (ctor_args) : new CustomAttributeTypedArgument [0]);
+			this.namedArgs = Array.AsReadOnly<CustomAttributeNamedArgument> 
+				(named_args != null ? UnboxValues<CustomAttributeNamedArgument> (named_args) : new CustomAttributeNamedArgument [0]);
+			
+			lazyData = null;
+		}
+		
 		[ComVisible (true)]
 		public
 #if NET_4_0
@@ -82,6 +107,7 @@ namespace System.Reflection {
 #endif
 		IList<CustomAttributeTypedArgument> ConstructorArguments {
 			get {
+				ResolveArguments ();
 				return ctorArgs;
 			}
 		}
@@ -92,6 +118,7 @@ namespace System.Reflection {
 #endif
 		IList<CustomAttributeNamedArgument> NamedArguments {
 			get {
+				ResolveArguments ();
 				return namedArgs;
 			}
 		}

+ 3 - 0
mono/metadata/icall-def.h

@@ -506,6 +506,9 @@ ICALL(ASSEM_26, "load_with_partial_name", ves_icall_System_Reflection_Assembly_l
 ICALL_TYPE(ASSEMN, "System.Reflection.AssemblyName", ASSEMN_1)
 ICALL(ASSEMN_1, "ParseName", ves_icall_System_Reflection_AssemblyName_ParseName)
 
+ICALL_TYPE(CATTR_DATA, "System.Reflection.CustomAttributeData", CATTR_DATA_1)
+ICALL(CATTR_DATA_1, "ResolveArgumentsInternal", mono_reflection_resolve_custom_attribute_data)
+
 ICALL_TYPE(ASSEMB, "System.Reflection.Emit.AssemblyBuilder", ASSEMB_1)
 ICALL(ASSEMB_1, "InternalAddModule", mono_image_load_module_dynamic)
 ICALL(ASSEMB_2, "basic_init", mono_image_basic_init)

+ 3 - 0
mono/metadata/object-internals.h

@@ -1376,6 +1376,9 @@ mono_reflection_call_is_assignable_to (MonoClass *klass, MonoClass *oklass) MONO
 gboolean
 mono_reflection_is_valid_dynamic_token (MonoDynamicImage *image, guint32 token) MONO_INTERNAL;
 
+void
+mono_reflection_resolve_custom_attribute_data (MonoReflectionMethod *method, MonoReflectionAssembly *assembly, gpointer data, guint32 data_length, MonoArray **ctor_args, MonoArray ** named_args) MONO_INTERNAL;
+
 MonoType*
 mono_reflection_type_get_handle (MonoReflectionType *ref) MONO_INTERNAL;
 

+ 37 - 25
mono/metadata/reflection.c

@@ -8356,35 +8356,29 @@ mono_reflection_create_custom_attr_data_args (MonoImage *image, MonoMethod *meth
 	*named_args = namedargs;
 }
 
-static MonoObject*
-create_custom_attr_data (MonoImage *image, MonoMethod *method, const guchar *data, guint32 len)
+void
+mono_reflection_resolve_custom_attribute_data (MonoReflectionMethod *ref_method, MonoReflectionAssembly *assembly, gpointer data, guint32 len, MonoArray **ctor_args, MonoArray **named_args)
 {
-	MonoArray *typedargs, *namedargs;
-	static MonoMethod *ctor;
 	MonoDomain *domain;
-	MonoObject *attr;
-	void *params [3];
+	MonoArray *typedargs, *namedargs;
+	MonoImage *image;
+	MonoMethod *method;
 	CattrNamedArg *arginfo;
 	int i;
 
-	mono_class_init (method->klass);
+	*ctor_args = NULL;
+	*named_args = NULL;
 
-	if (!ctor)
-		ctor = mono_class_get_method_from_name (mono_defaults.customattribute_data_class, ".ctor", 3);
+	if (len == 0)
+		return;
 
-	domain = mono_domain_get ();
-	if (len == 0) {
-		/* This is for Attributes with no parameters */
-		attr = mono_object_new (domain, mono_defaults.customattribute_data_class);
-		params [0] = mono_method_get_object (domain, method, NULL);
-		params [1] = params [2] = NULL;
-		mono_runtime_invoke (method, attr, params, NULL);
-		return attr;
-	}
+	image = assembly->assembly->image;
+	method = ref_method->method;
+	domain = mono_object_domain (ref_method);
 
 	mono_reflection_create_custom_attr_data_args (image, method, data, len, &typedargs, &namedargs, &arginfo);
 	if (!typedargs || !namedargs)
-		return NULL;
+		return;
 
 	for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
 		MonoObject *obj = mono_array_get (typedargs, MonoObject*, i);
@@ -8409,10 +8403,29 @@ create_custom_attr_data (MonoImage *image, MonoMethod *method, const guchar *dat
 		mono_array_setref (namedargs, i, namedarg);
 	}
 
+	*ctor_args = typedargs;
+	*named_args = namedargs;
+}
+
+static MonoObject*
+create_custom_attr_data (MonoImage *image, MonoCustomAttrEntry *cattr)
+{
+	static MonoMethod *ctor;
+	MonoDomain *domain;
+	MonoObject *attr;
+	void *params [4];
+
+	g_assert (image->assembly);
+
+	if (!ctor)
+		ctor = mono_class_get_method_from_name (mono_defaults.customattribute_data_class, ".ctor", 4);
+
+	domain = mono_domain_get ();
 	attr = mono_object_new (domain, mono_defaults.customattribute_data_class);
-	params [0] = mono_method_get_object (domain, method, NULL);
-	params [1] = typedargs;
-	params [2] = namedargs;
+	params [0] = mono_method_get_object (domain, cattr->ctor, NULL);
+	params [1] = mono_assembly_get_object (domain, image->assembly);
+	params [2] = (gpointer)&cattr->data;
+	params [3] = &cattr->data_size;
 	mono_runtime_invoke (ctor, attr, params, NULL);
 	return attr;
 }
@@ -8470,7 +8483,7 @@ mono_custom_attrs_data_construct (MonoCustomAttrInfo *cinfo)
 	
 	result = mono_array_new (mono_domain_get (), mono_defaults.customattribute_data_class, cinfo->num_attrs);
 	for (i = 0; i < cinfo->num_attrs; ++i) {
-		attr = create_custom_attr_data (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size);
+		attr = create_custom_attr_data (cinfo->image, &cinfo->attrs [i]);
 		mono_array_setref (result, i, attr);
 	}
 	return result;
@@ -8790,8 +8803,7 @@ mono_reflection_get_custom_attrs_info (MonoObject *obj)
 	if (klass == mono_defaults.monotype_class) {
 		MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
 		klass = mono_class_from_mono_type (type);
-		if (!mono_class_init (klass))
-			mono_raise_exception (mono_class_get_exception_for_failure (klass));
+		/*We cannot mono_class_init the class from which we'll load the custom attributes since this must work with broken types.*/
 		cinfo = mono_custom_attrs_from_class (klass);
 	} else if (strcmp ("Assembly", klass->name) == 0 || strcmp ("MonoAssembly", klass->name) == 0) {
 		MonoReflectionAssembly *rassembly = (MonoReflectionAssembly*)obj;