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

    Implement a reference queue API.

        * gc.c: A reference queue allows one to queue
        callbcks for when objects are collected.
        It allows for safe cleanup of objects that can
        only be done when it is effectively collected.
        The major difference with regular finalization
        is that the collector makes sure the object
        was collected - and can't be resurrected.

        * gc-internal.h: Export entrypoints for the
        new API.
  • Loading branch information
kumpera committed Feb 1, 2011
1 parent a3422f4 commit 3f8ee42
Show file tree
Hide file tree
Showing 4 changed files with 50 additions and 20 deletions.
8 changes: 0 additions & 8 deletions mcs/class/corlib/System.Reflection.Emit/DynamicMethod.cs
Expand Up @@ -130,9 +130,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 || (ILGenerator.Mono_GetCurrentOffset (ilgen) == 0))
Expand Down Expand Up @@ -161,11 +158,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 @@ -513,7 +513,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 @@ -1448,6 +1448,9 @@ mono_string_to_utf8_checked (MonoString *s, MonoError *error) MONO_INTERNAL;
gboolean
mono_class_is_reflection_method_or_constructor (MonoClass *class) 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 @@ -11064,15 +11064,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 @@ -11130,7 +11171,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 @@ -11156,16 +11202,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

0 comments on commit 3f8ee42

Please sign in to comment.