diff --git a/src/mono/System.Private.CoreLib/src/ILLink/ILLink.Descriptors.xml b/src/mono/System.Private.CoreLib/src/ILLink/ILLink.Descriptors.xml index 7ddd23d78de8ed..2e8bace4a47d8b 100644 --- a/src/mono/System.Private.CoreLib/src/ILLink/ILLink.Descriptors.xml +++ b/src/mono/System.Private.CoreLib/src/ILLink/ILLink.Descriptors.xml @@ -278,6 +278,12 @@ + + + + + + diff --git a/src/mono/System.Private.CoreLib/src/System/GC.Mono.cs b/src/mono/System.Private.CoreLib/src/System/GC.Mono.cs index 21eba8223fd0f9..77a4ac8b75d107 100644 --- a/src/mono/System.Private.CoreLib/src/System/GC.Mono.cs +++ b/src/mono/System.Private.CoreLib/src/System/GC.Mono.cs @@ -4,6 +4,7 @@ using System.Diagnostics.Tracing; using System.Runtime; using System.Runtime.CompilerServices; +using System.Runtime.ExceptionServices; namespace System { @@ -149,6 +150,20 @@ public static void ReRegisterForFinalize(object obj) _ReRegisterForFinalize(obj); } + [UnsafeAccessor(UnsafeAccessorKind.Method, Name = nameof(Finalize))] + private static extern void CallFinalize(object o); + private static void GuardedFinalize(object o) + { + try + { + CallFinalize(o); + } + catch (Exception ex) when (ExceptionHandling.IsHandledByGlobalHandler(ex)) + { + // the handler returned "true" means the exception is now "handled" and we should continue. + } + } + [MethodImplAttribute(MethodImplOptions.InternalCall)] public static extern long GetTotalMemory(bool forceFullCollection); diff --git a/src/mono/mono/metadata/class-internals.h b/src/mono/mono/metadata/class-internals.h index 5fa79bcca9c6e7..ba56a62ad6b818 100644 --- a/src/mono/mono/metadata/class-internals.h +++ b/src/mono/mono/metadata/class-internals.h @@ -889,6 +889,7 @@ typedef struct { MonoClass *threadabortexception_class; MonoClass *thread_class; MonoClass *internal_thread_class; + MonoClass *gc_class; MonoClass *autoreleasepool_class; MonoClass *mono_method_message_class; MonoClass *field_info_class; diff --git a/src/mono/mono/metadata/domain.c b/src/mono/mono/metadata/domain.c index 967e33f28df61c..13bb7a408564f7 100644 --- a/src/mono/mono/metadata/domain.c +++ b/src/mono/mono/metadata/domain.c @@ -238,6 +238,9 @@ mono_init_internal (const char *root_domain_name) /* There is only one thread class */ mono_defaults.internal_thread_class = mono_defaults.thread_class; + mono_defaults.gc_class = mono_class_load_from_name ( + mono_defaults.corlib, "System", "GC"); + #if defined(HOST_DARWIN) mono_defaults.autoreleasepool_class = mono_class_try_load_from_name ( mono_defaults.corlib, "System.Threading", "AutoreleasePool"); diff --git a/src/mono/mono/metadata/gc.c b/src/mono/mono/metadata/gc.c index 9c49d2803cd95a..7065b6fe85fabd 100644 --- a/src/mono/mono/metadata/gc.c +++ b/src/mono/mono/metadata/gc.c @@ -81,9 +81,8 @@ static gboolean finalizer_thread_exited; static MonoCoopCond exited_cond; static MonoInternalThread *gc_thread; -#ifndef HOST_WASM -static RuntimeInvokeFunction finalize_runtime_invoke; -#endif + +static MonoMethod *finalize_helper; /* * This must be a GHashTable, since these objects can't be finalized @@ -280,31 +279,14 @@ mono_gc_run_finalize (void *obj, void *data) return; } - - /* - * To avoid the locking plus the other overhead of mono_runtime_invoke_checked (), - * create and precompile a wrapper which calls the finalize method using - * a CALLVIRT. - */ if (mono_log_finalizers) g_log ("mono-gc-finalizers", G_LOG_LEVEL_MESSAGE, "<%s at %p> Compiling finalizer.", o_name, o); -#ifndef HOST_WASM - if (!finalize_runtime_invoke) { - MonoMethod *finalize_method = mono_class_get_method_from_name_checked (mono_defaults.object_class, "Finalize", 0, 0, error); + if (!finalize_helper) { + finalize_helper = mono_class_get_method_from_name_checked (mono_defaults.gc_class, "GuardedFinalize", 1, 0, error); mono_error_assert_ok (error); - MonoMethod *invoke = mono_marshal_get_runtime_invoke (finalize_method, TRUE); - - finalize_runtime_invoke = (RuntimeInvokeFunction)mono_compile_method_checked (invoke, error); - mono_error_assert_ok (error); /* expect this not to fail */ } - RuntimeInvokeFunction runtime_invoke = finalize_runtime_invoke; -#endif - - mono_runtime_class_init_full (o->vtable, error); - goto_if_nok (error, unhandled_error); - if (G_UNLIKELY (MONO_GC_FINALIZE_INVOKE_ENABLED ())) { MONO_GC_FINALIZE_INVOKE ((unsigned long)o, mono_object_get_size_internal (o), o_ns, o_name); @@ -315,23 +297,15 @@ mono_gc_run_finalize (void *obj, void *data) MONO_PROFILER_RAISE (gc_finalizing_object, (o)); -#ifdef HOST_WASM - MonoMethod* finalizer = mono_class_get_finalizer (o->vtable->klass); - if (finalizer) { // null finalizers work fine when using the vcall invoke as Object has an empty one - gpointer params [1]; - params [0] = NULL; - mono_runtime_try_invoke (finalizer, o, params, &exc, error); - } -#else - runtime_invoke (o, NULL, &exc, NULL); -#endif + gpointer params [1]; + params [0] = o; + mono_runtime_try_invoke (finalize_helper, NULL, params, &exc, error); MONO_PROFILER_RAISE (gc_finalized_object, (o)); if (mono_log_finalizers) g_log ("mono-gc-finalizers", G_LOG_LEVEL_MESSAGE, "<%s at %p> Returned from finalizer.", o_name, o); -unhandled_error: if (!is_ok (error)) exc = (MonoObject*)mono_error_convert_to_exception (error); if (exc) diff --git a/src/mono/mono/mini/aot-compiler.c b/src/mono/mono/mini/aot-compiler.c index 033ef0d96b94b3..67c4daaa835ca9 100644 --- a/src/mono/mono/mini/aot-compiler.c +++ b/src/mono/mono/mini/aot-compiler.c @@ -4977,7 +4977,7 @@ add_full_aot_wrappers (MonoAotCompile *acfg) add_method (acfg, get_runtime_invoke_sig (csig)); /* runtime-invoke used by finalizers */ - add_method (acfg, get_runtime_invoke (acfg, get_method_nofail (mono_defaults.object_class, "Finalize", 0, 0), TRUE)); + add_method (acfg, get_runtime_invoke (acfg, get_method_nofail (mono_defaults.gc_class, "GuardedFinalize", 1, 0), FALSE)); /* This is used by mono_runtime_capture_context () */ method = mono_get_context_capture_method (); diff --git a/src/mono/mono/mini/mini-runtime.c b/src/mono/mono/mini/mini-runtime.c index ddb1bfb6201bc2..468534bc16ba41 100644 --- a/src/mono/mono/mini/mini-runtime.c +++ b/src/mono/mono/mini/mini-runtime.c @@ -5363,7 +5363,7 @@ mono_precompile_assembly (MonoAssembly *ass, void *user_data) mono_error_cleanup (error); /* FIXME don't swallow the error */ continue; } - if (strcmp (method->name, "Finalize") == 0) { + if (strcmp (method->name, "GuardedFinalize") == 0) { invoke = mono_marshal_get_runtime_invoke (method, FALSE); mono_compile_method_checked (invoke, error); mono_error_assert_ok (error); diff --git a/src/tests/issues.targets b/src/tests/issues.targets index 591eb79f0fd68e..53cdc97de4306e 100644 --- a/src/tests/issues.targets +++ b/src/tests/issues.targets @@ -1732,8 +1732,11 @@ https://github.com/dotnet/runtime/issues/98628 - - NYI on Mono + + https://github.com/dotnet/runtime/issues/47624 + + + Test issue. The test relies on overriding the process return code.