Skip to content

Commit 3f8ee42

Browse files
committed
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.
1 parent a3422f4 commit 3f8ee42

File tree

4 files changed

+50
-20
lines changed

4 files changed

+50
-20
lines changed

Diff for: mcs/class/corlib/System.Reflection.Emit/DynamicMethod.cs

-8
Original file line numberDiff line numberDiff line change
@@ -130,9 +130,6 @@ public DynamicMethod (string name, Type returnType, Type[] parameterTypes, bool
130130
[MethodImplAttribute(MethodImplOptions.InternalCall)]
131131
private extern void create_dynamic_method (DynamicMethod m);
132132

133-
[MethodImplAttribute(MethodImplOptions.InternalCall)]
134-
private extern void destroy_dynamic_method (DynamicMethod m);
135-
136133
private void CreateDynMethod () {
137134
if (mhandle.Value == IntPtr.Zero) {
138135
if (ilgen == null || (ILGenerator.Mono_GetCurrentOffset (ilgen) == 0))
@@ -161,11 +158,6 @@ private void CreateDynMethod () {
161158
}
162159
}
163160

164-
~DynamicMethod ()
165-
{
166-
destroy_dynamic_method (this);
167-
}
168-
169161
[ComVisible (true)]
170162
public Delegate CreateDelegate (Type delegateType)
171163
{

Diff for: mono/metadata/icall-def.h

-1
Original file line numberDiff line numberDiff line change
@@ -513,7 +513,6 @@ ICALL(DERIVEDTYPE_1, "create_unmanaged_type", mono_reflection_create_unmanaged_t
513513

514514
ICALL_TYPE(DYNM, "System.Reflection.Emit.DynamicMethod", DYNM_1)
515515
ICALL(DYNM_1, "create_dynamic_method", mono_reflection_create_dynamic_method)
516-
ICALL(DYNM_2, "destroy_dynamic_method", mono_reflection_destroy_dynamic_method)
517516

518517
ICALL_TYPE(ENUMB, "System.Reflection.Emit.EnumBuilder", ENUMB_1)
519518
ICALL(ENUMB_1, "setup_enum_type", ves_icall_EnumBuilder_setup_enum_type)

Diff for: mono/metadata/object-internals.h

+3
Original file line numberDiff line numberDiff line change
@@ -1448,6 +1448,9 @@ mono_string_to_utf8_checked (MonoString *s, MonoError *error) MONO_INTERNAL;
14481448
gboolean
14491449
mono_class_is_reflection_method_or_constructor (MonoClass *class) MONO_INTERNAL;
14501450

1451+
void
1452+
mono_reflection_shutdown (void) MONO_INTERNAL;
1453+
14511454
#endif /* __MONO_OBJECT_INTERNALS_H__ */
14521455

14531456

Diff for: mono/metadata/reflection.c

+47-11
Original file line numberDiff line numberDiff line change
@@ -11064,15 +11064,56 @@ mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
1106411064
return result;
1106511065
}
1106611066

11067+
typedef struct {
11068+
MonoMethod *handle;
11069+
MonoDomain *domain;
11070+
} DynamicMethodReleaseData;
11071+
11072+
static MonoReferenceQueue *dynamic_method_queue;
11073+
11074+
void
11075+
mono_reflection_shutdown (void)
11076+
{
11077+
MonoReferenceQueue *queue;
11078+
mono_loader_lock ();
11079+
queue = dynamic_method_queue;
11080+
dynamic_method_queue = NULL;
11081+
if (queue)
11082+
mono_gc_reference_queue_free (queue);
11083+
mono_loader_unlock ();
11084+
}
11085+
11086+
static void
11087+
free_dynamic_method (void *dynamic_method)
11088+
{
11089+
DynamicMethodReleaseData *data = dynamic_method;
11090+
11091+
mono_runtime_free_method (data->domain, data->handle);
11092+
g_free (data);
11093+
}
11094+
1106711095
void
1106811096
mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
1106911097
{
11098+
MonoReferenceQueue *queue;
11099+
MonoMethod *handle;
11100+
DynamicMethodReleaseData *release_data;
1107011101
ReflectionMethodBuilder rmb;
1107111102
MonoMethodSignature *sig;
1107211103
MonoClass *klass;
1107311104
GSList *l;
1107411105
int i;
1107511106

11107+
if (mono_runtime_is_shutting_down ())
11108+
mono_raise_exception (mono_get_exception_invalid_operation (""));
11109+
11110+
if (!(queue = dynamic_method_queue)) {
11111+
mono_loader_lock ();
11112+
if (!(queue = dynamic_method_queue))
11113+
queue = dynamic_method_queue = mono_gc_reference_queue_new (free_dynamic_method);
11114+
mono_loader_unlock ();
11115+
}
11116+
1107611117
sig = dynamic_method_to_signature (mb);
1107711118

1107811119
reflection_methodbuilder_from_dynamic_method (&rmb, mb);
@@ -11130,7 +11171,12 @@ mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
1113011171

1113111172
klass = mb->owner ? mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)mb->owner)) : mono_defaults.object_class;
1113211173

11133-
mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
11174+
mb->mhandle = handle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
11175+
release_data = g_new (DynamicMethodReleaseData, 1);
11176+
release_data->handle = handle;
11177+
release_data->domain = mono_object_get_domain ((MonoObject*)mb);
11178+
if (!mono_gc_reference_queue_add (queue, (MonoObject*)mb, release_data))
11179+
g_free (release_data);
1113411180

1113511181
/* Fix up refs entries pointing at us */
1113611182
for (l = mb->referenced_by; l; l = l->next) {
@@ -11156,16 +11202,6 @@ mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
1115611202

1115711203
#endif /* DISABLE_REFLECTION_EMIT */
1115811204

11159-
void
11160-
mono_reflection_destroy_dynamic_method (MonoReflectionDynamicMethod *mb)
11161-
{
11162-
g_assert (mb);
11163-
11164-
if (mb->mhandle)
11165-
mono_runtime_free_method (
11166-
mono_object_get_domain ((MonoObject*)mb), mb->mhandle);
11167-
}
11168-
1116911205
/**
1117011206
*
1117111207
* mono_reflection_is_valid_dynamic_token:

0 commit comments

Comments
 (0)