Skip to content

Commit 89d1455

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
1 parent 8eb1189 commit 89d1455

File tree

5 files changed

+53
-20
lines changed

5 files changed

+53
-20
lines changed

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

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

130-
[MethodImplAttribute(MethodImplOptions.InternalCall)]
131-
private extern void destroy_dynamic_method (DynamicMethod m);
132-
133130
private void CreateDynMethod () {
134131
if (mhandle.Value == IntPtr.Zero) {
135132
if (ilgen == null || ilgen.ILOffset == 0)
@@ -158,11 +155,6 @@ private void CreateDynMethod () {
158155
}
159156
}
160157

161-
~DynamicMethod ()
162-
{
163-
destroy_dynamic_method (this);
164-
}
165-
166158
[ComVisible (true)]
167159
public Delegate CreateDelegate (Type delegateType)
168160
{

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

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

525525
ICALL_TYPE(DYNM, "System.Reflection.Emit.DynamicMethod", DYNM_1)
526526
ICALL(DYNM_1, "create_dynamic_method", mono_reflection_create_dynamic_method)
527-
ICALL(DYNM_2, "destroy_dynamic_method", mono_reflection_destroy_dynamic_method)
528527

529528
ICALL_TYPE(ENUMB, "System.Reflection.Emit.EnumBuilder", ENUMB_1)
530529
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
@@ -1539,6 +1539,9 @@ mono_object_new_pinned (MonoDomain *domain, MonoClass *klass) MONO_INTERNAL;
15391539
void
15401540
mono_field_static_get_value_for_thread (MonoInternalThread *thread, MonoVTable *vt, MonoClassField *field, void *value) MONO_INTERNAL;
15411541

1542+
void
1543+
mono_reflection_shutdown (void) MONO_INTERNAL;
1544+
15421545
#endif /* __MONO_OBJECT_INTERNALS_H__ */
15431546

15441547

Diff for: mono/metadata/reflection.c

+47-11
Original file line numberDiff line numberDiff line change
@@ -11441,15 +11441,56 @@ mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
1144111441
return result;
1144211442
}
1144311443

11444+
typedef struct {
11445+
MonoMethod *handle;
11446+
MonoDomain *domain;
11447+
} DynamicMethodReleaseData;
11448+
11449+
static MonoReferenceQueue *dynamic_method_queue;
11450+
11451+
void
11452+
mono_reflection_shutdown (void)
11453+
{
11454+
MonoReferenceQueue *queue;
11455+
mono_loader_lock ();
11456+
queue = dynamic_method_queue;
11457+
dynamic_method_queue = NULL;
11458+
if (queue)
11459+
mono_gc_reference_queue_free (queue);
11460+
mono_loader_unlock ();
11461+
}
11462+
11463+
static void
11464+
free_dynamic_method (void *dynamic_method)
11465+
{
11466+
DynamicMethodReleaseData *data = dynamic_method;
11467+
11468+
mono_runtime_free_method (data->domain, data->handle);
11469+
g_free (data);
11470+
}
11471+
1144411472
void
1144511473
mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
1144611474
{
11475+
MonoReferenceQueue *queue;
11476+
MonoMethod *handle;
11477+
DynamicMethodReleaseData *release_data;
1144711478
ReflectionMethodBuilder rmb;
1144811479
MonoMethodSignature *sig;
1144911480
MonoClass *klass;
1145011481
GSList *l;
1145111482
int i;
1145211483

11484+
if (mono_runtime_is_shutting_down ())
11485+
mono_raise_exception (mono_get_exception_invalid_operation (""));
11486+
11487+
if (!(queue = dynamic_method_queue)) {
11488+
mono_loader_lock ();
11489+
if (!(queue = dynamic_method_queue))
11490+
queue = dynamic_method_queue = mono_gc_reference_queue_new (free_dynamic_method);
11491+
mono_loader_unlock ();
11492+
}
11493+
1145311494
sig = dynamic_method_to_signature (mb);
1145411495

1145511496
reflection_methodbuilder_from_dynamic_method (&rmb, mb);
@@ -11507,7 +11548,12 @@ mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
1150711548

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

11510-
mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
11551+
mb->mhandle = handle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
11552+
release_data = g_new (DynamicMethodReleaseData, 1);
11553+
release_data->handle = handle;
11554+
release_data->domain = mono_object_get_domain ((MonoObject*)mb);
11555+
if (!mono_gc_reference_queue_add (queue, (MonoObject*)mb, release_data))
11556+
g_free (release_data);
1151111557

1151211558
/* Fix up refs entries pointing at us */
1151311559
for (l = mb->referenced_by; l; l = l->next) {
@@ -11533,16 +11579,6 @@ mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
1153311579

1153411580
#endif /* DISABLE_REFLECTION_EMIT */
1153511581

11536-
void
11537-
mono_reflection_destroy_dynamic_method (MonoReflectionDynamicMethod *mb)
11538-
{
11539-
g_assert (mb);
11540-
11541-
if (mb->mhandle)
11542-
mono_runtime_free_method (
11543-
mono_object_get_domain ((MonoObject*)mb), mb->mhandle);
11544-
}
11545-
1154611582
/**
1154711583
*
1154811584
* mono_reflection_is_valid_dynamic_token:

Diff for: mono/metadata/runtime.c

+3
Original file line numberDiff line numberDiff line change
@@ -39,5 +39,8 @@ void
3939
mono_runtime_shutdown (void)
4040
{
4141
mono_domain_foreach (fire_process_exit_event, NULL);
42+
43+
/*From this point on, no more DM methods can be created. */
44+
mono_reflection_shutdown ();
4245
}
4346

0 commit comments

Comments
 (0)