Răsfoiți Sursa

Don't use finalization to cleanup dynamic methods.

	* reflection.c: Use a reference queue to cleanup
	dynamic methods instead of finalization.

	* runtime.c: Shutdown the dynamic method queue
	before runtime cleanup begins.

	* DynamicMethod.cs: No longer finalizable.

	* icall-def.h: Remove unused dynamic method icall.

	Fixes #660422
Rodrigo Kumpera 15 ani în urmă
părinte
comite
89d1455a80

+ 0 - 8
mcs/class/corlib/System.Reflection.Emit/DynamicMethod.cs

@@ -127,9 +127,6 @@ namespace System.Reflection.Emit {
 		[MethodImplAttribute(MethodImplOptions.InternalCall)]
 		private extern void create_dynamic_method (DynamicMethod m);
 
-		[MethodImplAttribute(MethodImplOptions.InternalCall)]
-		private extern void destroy_dynamic_method (DynamicMethod m);
-
 		private void CreateDynMethod () {
 			if (mhandle.Value == IntPtr.Zero) {
 				if (ilgen == null || ilgen.ILOffset == 0)
@@ -158,11 +155,6 @@ namespace System.Reflection.Emit {
 			}
 		}
 
-		~DynamicMethod ()
-		{
-			destroy_dynamic_method (this);
-		}
-
 		[ComVisible (true)]
 		public Delegate CreateDelegate (Type delegateType)
 		{

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

@@ -524,7 +524,6 @@ ICALL(DERIVEDTYPE_1, "create_unmanaged_type", mono_reflection_create_unmanaged_t
 
 ICALL_TYPE(DYNM, "System.Reflection.Emit.DynamicMethod", DYNM_1)
 ICALL(DYNM_1, "create_dynamic_method", mono_reflection_create_dynamic_method)
-ICALL(DYNM_2, "destroy_dynamic_method", mono_reflection_destroy_dynamic_method)
 
 ICALL_TYPE(ENUMB, "System.Reflection.Emit.EnumBuilder", ENUMB_1)
 ICALL(ENUMB_1, "setup_enum_type", ves_icall_EnumBuilder_setup_enum_type)

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

@@ -1539,6 +1539,9 @@ mono_object_new_pinned (MonoDomain *domain, MonoClass *klass) MONO_INTERNAL;
 void
 mono_field_static_get_value_for_thread (MonoInternalThread *thread, MonoVTable *vt, MonoClassField *field, void *value) MONO_INTERNAL;
 
+void
+mono_reflection_shutdown (void) MONO_INTERNAL;
+
 #endif /* __MONO_OBJECT_INTERNALS_H__ */
 
 

+ 47 - 11
mono/metadata/reflection.c

@@ -11441,15 +11441,56 @@ mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
 	return result;
 }
 
+typedef struct {
+	MonoMethod *handle;
+	MonoDomain *domain;
+} DynamicMethodReleaseData;
+	
+static MonoReferenceQueue *dynamic_method_queue;
+
+void
+mono_reflection_shutdown (void)
+{
+	MonoReferenceQueue *queue;
+	mono_loader_lock ();
+	queue = dynamic_method_queue;
+	dynamic_method_queue = NULL;
+	if (queue)
+		mono_gc_reference_queue_free (queue);
+	mono_loader_unlock ();
+}
+
+static void
+free_dynamic_method (void *dynamic_method)
+{
+	DynamicMethodReleaseData *data = dynamic_method;
+
+	mono_runtime_free_method (data->domain, data->handle);
+	g_free (data);
+}
+
 void 
 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
 {
+	MonoReferenceQueue *queue;
+	MonoMethod *handle;
+	DynamicMethodReleaseData *release_data;
 	ReflectionMethodBuilder rmb;
 	MonoMethodSignature *sig;
 	MonoClass *klass;
 	GSList *l;
 	int i;
 
+	if (mono_runtime_is_shutting_down ())
+		mono_raise_exception (mono_get_exception_invalid_operation (""));
+
+	if (!(queue = dynamic_method_queue)) {
+		mono_loader_lock ();
+		if (!(queue = dynamic_method_queue))
+			queue = dynamic_method_queue = mono_gc_reference_queue_new (free_dynamic_method);
+		mono_loader_unlock ();
+	}
+
 	sig = dynamic_method_to_signature (mb);
 
 	reflection_methodbuilder_from_dynamic_method (&rmb, mb);
@@ -11507,7 +11548,12 @@ mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
 
 	klass = mb->owner ? mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)mb->owner)) : mono_defaults.object_class;
 
-	mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
+	mb->mhandle = handle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
+	release_data = g_new (DynamicMethodReleaseData, 1);
+	release_data->handle = handle;
+	release_data->domain = mono_object_get_domain ((MonoObject*)mb);
+	if (!mono_gc_reference_queue_add (queue, (MonoObject*)mb, release_data))
+		g_free (release_data);
 
 	/* Fix up refs entries pointing at us */
 	for (l = mb->referenced_by; l; l = l->next) {
@@ -11533,16 +11579,6 @@ mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
 
 #endif /* DISABLE_REFLECTION_EMIT */
 
-void
-mono_reflection_destroy_dynamic_method (MonoReflectionDynamicMethod *mb)
-{
-	g_assert (mb);
-
-	if (mb->mhandle)
-		mono_runtime_free_method (
-			mono_object_get_domain ((MonoObject*)mb), mb->mhandle);
-}
-
 /**
  * 
  * mono_reflection_is_valid_dynamic_token:

+ 3 - 0
mono/metadata/runtime.c

@@ -39,5 +39,8 @@ void
 mono_runtime_shutdown (void)
 {
 	mono_domain_foreach (fire_process_exit_event, NULL);
+
+	/*From this point on, no more DM methods can be created. */
+	mono_reflection_shutdown ();
 }