Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Mono] Implement eager finalization of WeakReference #76173

Merged
merged 3 commits into from
Sep 29, 2022
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 0 additions & 17 deletions src/libraries/System.Private.CoreLib/src/System/WeakReference.T.cs
Original file line number Diff line number Diff line change
Expand Up @@ -130,8 +130,6 @@ private T? Target
}
}

// eager finalization is NYI on Mono
#if !MONO
// Note: While WeakReference<T> is formally a finalizable type, the finalizer does not actually run.
// Instead the instances are treated specially in GC when scanning for no longer strongly-reachable
// finalizable objects.
Expand All @@ -142,21 +140,6 @@ private T? Target
}
#pragma warning restore CA1821 // Remove empty Finalizers

#else
// Free all system resources associated with this reference.
~WeakReference()
{
IntPtr handle = Handle;
if (handle != default(IntPtr))
{
GCHandle.InternalFree(handle);

// keep the bit that indicates whether this reference was tracking resurrection
_handleAndKind &= TracksResurrectionBit;
}
}
#endif

#endif
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -150,10 +150,7 @@ public virtual object? Target
// Unlike WeakReference<T> case, the instance could be of a derived type and
// in such case it is finalized via a finalizer.

// eager finalization is NYI on Mono
#if !MONO
Debug.Assert(this.GetType() != typeof(WeakReference));
#endif

IntPtr handle = Handle;
if (handle != default(IntPtr))
Expand Down
2 changes: 2 additions & 0 deletions src/mono/mono/metadata/class-internals.h
Original file line number Diff line number Diff line change
Expand Up @@ -921,6 +921,8 @@ typedef struct {
MonoClass *generic_ienumerator_class;
MonoClass *alc_class;
MonoClass *appcontext_class;
MonoClass *weakreference_class;
MonoClass *generic_weakreference_class;
lambdageek marked this conversation as resolved.
Show resolved Hide resolved
} MonoDefaults;

/* If you need a MonoType, use one of the mono_get_*_type () functions in class-inlines.h */
Expand Down
5 changes: 5 additions & 0 deletions src/mono/mono/metadata/domain.c
Original file line number Diff line number Diff line change
Expand Up @@ -290,6 +290,11 @@ mono_init_internal (const char *root_domain_name)
mono_defaults.alc_class = mono_class_get_assembly_load_context_class ();
mono_defaults.appcontext_class = mono_class_try_load_from_name (mono_defaults.corlib, "System", "AppContext");

mono_defaults.weakreference_class = mono_class_try_load_from_name (
mono_defaults.corlib, "System", "WeakReference");
mono_defaults.generic_weakreference_class = mono_class_try_load_from_name (
mono_defaults.corlib, "System", "WeakReference`1");

// in the past we got a filename as the root_domain_name so try to get the basename
domain->friendly_name = g_path_get_basename (root_domain_name);

Expand Down
9 changes: 9 additions & 0 deletions src/mono/mono/metadata/gc.c
Original file line number Diff line number Diff line change
Expand Up @@ -249,6 +249,15 @@ mono_gc_run_finalize (void *obj, void *data)
return;
}

if (o->vtable->klass == mono_defaults.weakreference_class ||
o->vtable->klass == mono_defaults.generic_weakreference_class) {
MonoWeakReference *wr = (MonoWeakReference*)o;
MonoGCHandle gc_handle = (MonoGCHandle)(wr->handleAndKind & ~(gsize)1);
mono_gchandle_free_internal (gc_handle);
wr->handleAndKind &= (gsize)1;
return;
}
filipnavara marked this conversation as resolved.
Show resolved Hide resolved

if (m_class_get_image (mono_object_class (o)) == mono_defaults.corlib && !strcmp (o_name, "DynamicMethod") && finalizing_root_domain) {
/*
* These can't be finalized during unloading/shutdown, since that would
Expand Down
5 changes: 5 additions & 0 deletions src/mono/mono/metadata/object-internals.h
Original file line number Diff line number Diff line change
Expand Up @@ -651,6 +651,11 @@ typedef struct {
guint32 intType;
} MonoClassInterfaceAttribute;

typedef struct {
MonoObject object;
gsize handleAndKind;
} MonoWeakReference;

/* Safely access System.Delegate from native code */
TYPED_HANDLE_DECL (MonoDelegate);

Expand Down