Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
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
Original file line number Diff line number Diff line change
Expand Up @@ -278,6 +278,12 @@
<method name="GetHashCode" />
</type>

<!-- domain.c: mono_defaults.gc_class -->
<type fullname="System.GC">
<!-- gc.c: mono_gc_run_finalize -->
<method name="GuardedFinalize" />
</type>

<!-- appdomain.c (create_domain_objects) domain->out_of_memory_ex -->
<type fullname="System.OutOfMemoryException">
<!-- mono_exception_from_name_two_strings (only one string in the signature since NULL is used as the 2nd parameter) -->
Expand Down
15 changes: 15 additions & 0 deletions src/mono/System.Private.CoreLib/src/System/GC.Mono.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
using System.Diagnostics.Tracing;
using System.Runtime;
using System.Runtime.CompilerServices;
using System.Runtime.ExceptionServices;

namespace System
{
Expand Down Expand Up @@ -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);

Expand Down
1 change: 1 addition & 0 deletions src/mono/mono/metadata/class-internals.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
3 changes: 3 additions & 0 deletions src/mono/mono/metadata/domain.c
Original file line number Diff line number Diff line change
Expand Up @@ -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");
Expand Down
40 changes: 7 additions & 33 deletions src/mono/mono/metadata/gc.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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);
Expand All @@ -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)
Expand Down
2 changes: 1 addition & 1 deletion src/mono/mono/mini/aot-compiler.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 ();
Expand Down
2 changes: 1 addition & 1 deletion src/mono/mono/mini/mini-runtime.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
7 changes: 5 additions & 2 deletions src/tests/issues.targets
Original file line number Diff line number Diff line change
Expand Up @@ -1732,8 +1732,11 @@
<ExcludeList Include="$(XunitTestBinBase)/JIT/opt/Structs/MemsetMemcpyNullref/*">
<Issue>https://github.com/dotnet/runtime/issues/98628</Issue>
</ExcludeList>
<ExcludeList Include="$(XunitTestBinBase)/baseservices/exceptions/UnhandledExceptionHandler/**">
<Issue>NYI on Mono</Issue>
<ExcludeList Include="$(XunitTestBinBase)/baseservices/exceptions/UnhandledExceptionHandler/HandlerThrows/*">
<Issue>https://github.com/dotnet/runtime/issues/47624</Issue>
</ExcludeList>
<ExcludeList Include="$(XunitTestBinBase)/baseservices/exceptions/UnhandledExceptionHandler/NoEffectInMainThread/*">
<Issue>Test issue. The test relies on overriding the process return code.</Issue>
</ExcludeList>
</ItemGroup>

Expand Down
Loading