Skip to content
Permalink
Browse files Browse the repository at this point in the history
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
  • Loading branch information
kumpera committed Feb 1, 2011
1 parent 8eb1189 commit 89d1455
Show file tree
Hide file tree
Showing 5 changed files with 53 additions and 20 deletions.
8 changes: 0 additions & 8 deletions mcs/class/corlib/System.Reflection.Emit/DynamicMethod.cs
Expand Up @@ -127,9 +127,6 @@ public DynamicMethod (string name, Type returnType, Type[] parameterTypes, bool
[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)
Expand Down Expand Up @@ -158,11 +155,6 @@ public DynamicMethod (string name, Type returnType, Type[] parameterTypes, bool
}
}

~DynamicMethod ()
{
destroy_dynamic_method (this);
}

[ComVisible (true)]
public Delegate CreateDelegate (Type delegateType)
{
Expand Down
1 change: 0 additions & 1 deletion mono/metadata/icall-def.h
Expand Up @@ -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)
Expand Down
3 changes: 3 additions & 0 deletions mono/metadata/object-internals.h
Expand Up @@ -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__ */


58 changes: 47 additions & 11 deletions mono/metadata/reflection.c
Expand Up @@ -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);
Expand Down Expand Up @@ -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) {
Expand All @@ -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:
Expand Down
3 changes: 3 additions & 0 deletions mono/metadata/runtime.c
Expand Up @@ -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 ();
}

0 comments on commit 89d1455

Please sign in to comment.