From 16ef9c0452d728d0a878a2d8159ceb8a7c6c9bc3 Mon Sep 17 00:00:00 2001 From: lateralusX Date: Thu, 16 Feb 2023 19:22:03 +0100 Subject: [PATCH 1/6] Add support for runtime init in native-to-managed wrapper. NativeAOT supports library mode, building all needed runtime and managed code into a static or shared library that can be loaded and used by embedding applications. NativeAOT exports managed functiond marked with UnmanagedCallersOnly attribute that can be called by embedder to run managed code. NativeAOT runtime doesn't need any initialization, meaning that calling the managed method exported using UnmanagedCallersOnly attribute will perform lazy runtime initialization on first call. This commit add similar support to MonoVM giving it possibilities to include a call to a runtime init function as part of native-to-managed wrapper used for methods marked with UnmanagedCallersOnly attribute + entry point. AOT compiler accepts a new argument, runtime-init-callback, if used like that, the native-to-managed wrapper will get a call to a default invoke callback method implemented by runtime, that will call a set callback once (thread safe). It is also possible to pass runtime-init-callback= to AOT compiler, and in that case native-to-managed wrapper will call that function and its up to implementor to do a thread safe implementation of runtime init. This capability could be used in case where the library can't set the callback before consumer of the library class the exported function. Two new runtime API's have been added in this commit, one to set the callback called by default runtime init implementation and the other is the implementation of that function used in native-to-managed wrapper if user doesn't use a custom runtime init callback function. Since this integration scenario is mainly for library build scenarios (we control the library builder), these methods are marked as MONO_COMPONENT_API and not something that should be part of the public API surface. --- src/mono/mono/metadata/icall.c | 2 +- src/mono/mono/metadata/jit-icall-reg.h | 1 + src/mono/mono/metadata/marshal-lightweight.c | 11 ++++- src/mono/mono/metadata/marshal.c | 12 ++--- src/mono/mono/metadata/marshal.h | 6 +-- src/mono/mono/mini/aot-compiler.c | 47 ++++++++++++++++---- src/mono/mono/mini/aot-runtime.c | 2 +- src/mono/mono/mini/interp/interp.c | 2 +- src/mono/mono/mini/interp/transform.c | 2 +- src/mono/mono/mini/jit-icalls.c | 10 +++++ src/mono/mono/mini/jit-icalls.h | 2 + src/mono/mono/mini/method-to-ir.c | 2 +- src/mono/mono/mini/mini-runtime.c | 36 +++++++++++++++ src/mono/mono/mini/mini-runtime.h | 8 ++++ src/mono/mono/mini/mini.c | 4 +- src/mono/mono/mini/monovm.c | 2 +- 16 files changed, 122 insertions(+), 27 deletions(-) diff --git a/src/mono/mono/metadata/icall.c b/src/mono/mono/metadata/icall.c index 66bdb62a52cf8b..059552da7299c6 100644 --- a/src/mono/mono/metadata/icall.c +++ b/src/mono/mono/metadata/icall.c @@ -6169,7 +6169,7 @@ mono_method_get_unmanaged_wrapper_ftnptr_internal (MonoMethod *method, gboolean { /* WISH: we should do this in managed */ if (G_UNLIKELY (mono_method_has_unmanaged_callers_only_attribute (method))) { - method = mono_marshal_get_managed_wrapper (method, NULL, (MonoGCHandle)0, error); + method = mono_marshal_get_managed_wrapper (method, NULL, (MonoGCHandle)0, FALSE, error); return_val_if_nok (error, NULL); } else { g_assert (!only_unmanaged_callers_only); diff --git a/src/mono/mono/metadata/jit-icall-reg.h b/src/mono/mono/metadata/jit-icall-reg.h index a3aac59f4d458b..984c26721eec57 100644 --- a/src/mono/mono/metadata/jit-icall-reg.h +++ b/src/mono/mono/metadata/jit-icall-reg.h @@ -339,6 +339,7 @@ MONO_JIT_ICALL (ves_icall_string_new_wrapper) \ MONO_JIT_ICALL (ves_icall_thread_finish_async_abort) \ MONO_JIT_ICALL (mono_marshal_lookup_pinvoke) \ MONO_JIT_ICALL (mono_gsharedvt_constrained_call_fast) \ +MONO_JIT_ICALL (mono_dummy_runtime_init_callback) \ \ MONO_JIT_ICALL (count) \ diff --git a/src/mono/mono/metadata/marshal-lightweight.c b/src/mono/mono/metadata/marshal-lightweight.c index 9d43d0b124d52e..54e37d2036d998 100644 --- a/src/mono/mono/metadata/marshal-lightweight.c +++ b/src/mono/mono/metadata/marshal-lightweight.c @@ -2491,7 +2491,7 @@ emit_managed_wrapper_validate_signature (MonoMethodSignature* sig, MonoMarshalSp } static void -emit_managed_wrapper_ilgen (MonoMethodBuilder *mb, MonoMethodSignature *invoke_sig, MonoMarshalSpec **mspecs, EmitMarshalContext* m, MonoMethod *method, MonoGCHandle target_handle, MonoError *error) +emit_managed_wrapper_ilgen (MonoMethodBuilder *mb, MonoMethodSignature *invoke_sig, MonoMarshalSpec **mspecs, EmitMarshalContext* m, MonoMethod *method, MonoGCHandle target_handle, gboolean runtime_init_callback, MonoError *error) { MonoMethodSignature *sig, *csig; int i, *tmp_locals; @@ -2550,9 +2550,18 @@ emit_managed_wrapper_ilgen (MonoMethodBuilder *mb, MonoMethodSignature *invoke_s * return ret; */ + /* delete_old = FALSE */ mono_mb_emit_icon (mb, 0); mono_mb_emit_stloc (mb, 2); + /* + * Transformed into a direct icall when runtime init callback is enabled for a native-to-managed wrapper. + * This icall is special cased in the JIT so it can be called in native-to-managed wrapper before + * runtime has been initialized. On return, runtime must be fully initialized. + */ + if (runtime_init_callback) + mono_mb_emit_icall (mb, mono_dummy_runtime_init_callback); + gc_unsafe_transition_builder_emit_enter(&gc_unsafe_builder); /* we first do all conversions */ diff --git a/src/mono/mono/metadata/marshal.c b/src/mono/mono/metadata/marshal.c index 5ab899e032d0eb..e8cfbed4faddda 100644 --- a/src/mono/mono/metadata/marshal.c +++ b/src/mono/mono/metadata/marshal.c @@ -403,7 +403,7 @@ mono_delegate_to_ftnptr_impl (MonoDelegateHandle delegate, MonoError *error) target_handle = mono_gchandle_new_weakref_from_handle (delegate_target); } - wrapper = mono_marshal_get_managed_wrapper (method, klass, target_handle, error); + wrapper = mono_marshal_get_managed_wrapper (method, klass, target_handle, FALSE, error); goto_if_nok (error, leave); MONO_HANDLE_SETVAL (delegate, delegate_trampoline, gpointer, mono_compile_method_checked (wrapper, error)); @@ -3916,9 +3916,9 @@ mono_marshal_get_native_func_wrapper_indirect (MonoClass *caller_class, MonoMeth * THIS_LOC is the memory location where the target of the delegate is stored. */ void -mono_marshal_emit_managed_wrapper (MonoMethodBuilder *mb, MonoMethodSignature *invoke_sig, MonoMarshalSpec **mspecs, EmitMarshalContext* m, MonoMethod *method, MonoGCHandle target_handle, MonoError *error) +mono_marshal_emit_managed_wrapper (MonoMethodBuilder *mb, MonoMethodSignature *invoke_sig, MonoMarshalSpec **mspecs, EmitMarshalContext* m, MonoMethod *method, MonoGCHandle target_handle, gboolean runtime_init_callback, MonoError *error) { - get_marshal_cb ()->emit_managed_wrapper (mb, invoke_sig, mspecs, m, method, target_handle, error); + get_marshal_cb ()->emit_managed_wrapper (mb, invoke_sig, mspecs, m, method, target_handle, runtime_init_callback, error); } static gboolean @@ -4026,7 +4026,7 @@ method_signature_is_usable_when_marshalling_disabled (MonoMethodSignature *sig) * UnamangedCallersOnlyAttribute. */ MonoMethod * -mono_marshal_get_managed_wrapper (MonoMethod *method, MonoClass *delegate_klass, MonoGCHandle target_handle, MonoError *error) +mono_marshal_get_managed_wrapper (MonoMethod *method, MonoClass *delegate_klass, MonoGCHandle target_handle, gboolean runtime_init_callback, MonoError *error) { MonoMethodSignature *sig, *csig, *invoke_sig; MonoMethodBuilder *mb; @@ -4192,7 +4192,7 @@ mono_marshal_get_managed_wrapper (MonoMethod *method, MonoClass *delegate_klass, mono_custom_attrs_free (cinfo); } - mono_marshal_emit_managed_wrapper (mb, invoke_sig, mspecs, &m, method, target_handle, error); + mono_marshal_emit_managed_wrapper (mb, invoke_sig, mspecs, &m, method, target_handle, runtime_init_callback, error); res = NULL; if (is_ok (error)) { @@ -4273,7 +4273,7 @@ mono_marshal_get_vtfixup_ftnptr (MonoImage *image, guint32 token, guint16 type) /* FIXME: Implement VTFIXUP_TYPE_FROM_UNMANAGED_RETAIN_APPDOMAIN. */ - mono_marshal_emit_managed_wrapper (mb, sig, mspecs, &m, method, 0, error); + mono_marshal_emit_managed_wrapper (mb, sig, mspecs, &m, method, 0, FALSE, error); mono_error_assert_ok (error); get_marshal_cb ()->mb_set_dynamic (mb); diff --git a/src/mono/mono/metadata/marshal.h b/src/mono/mono/metadata/marshal.h index 89b306d7def0c3..7e11863627462d 100644 --- a/src/mono/mono/metadata/marshal.h +++ b/src/mono/mono/metadata/marshal.h @@ -323,7 +323,7 @@ typedef struct { void (*emit_stelemref) (MonoMethodBuilder *mb); void (*emit_array_address) (MonoMethodBuilder *mb, int rank, int elem_size); void (*emit_native_wrapper) (MonoImage *image, MonoMethodBuilder *mb, MonoMethodSignature *sig, MonoMethodPInvoke *piinfo, MonoMarshalSpec **mspecs, gpointer func, MonoNativeWrapperFlags flags); - void (*emit_managed_wrapper) (MonoMethodBuilder *mb, MonoMethodSignature *invoke_sig, MonoMarshalSpec **mspecs, EmitMarshalContext* m, MonoMethod *method, MonoGCHandle target_handle, MonoError *error); + void (*emit_managed_wrapper) (MonoMethodBuilder *mb, MonoMethodSignature *invoke_sig, MonoMarshalSpec **mspecs, EmitMarshalContext* m, MonoMethod *method, MonoGCHandle target_handle, gboolean runtime_init_callback, MonoError *error); void (*emit_runtime_invoke_body) (MonoMethodBuilder *mb, const char **param_names, MonoImage *image, MonoMethod *method, MonoMethodSignature *sig, MonoMethodSignature *callsig, gboolean virtual_, gboolean need_direct_wrapper); void (*emit_runtime_invoke_dynamic) (MonoMethodBuilder *mb); void (*emit_delegate_begin_invoke) (MonoMethodBuilder *mb, MonoMethodSignature *sig); @@ -504,7 +504,7 @@ MonoMethodSignature* mono_marshal_get_string_ctor_signature (MonoMethod *method); MonoMethod * -mono_marshal_get_managed_wrapper (MonoMethod *method, MonoClass *delegate_klass, MonoGCHandle this_loc, MonoError *exernal_error); +mono_marshal_get_managed_wrapper (MonoMethod *method, MonoClass *delegate_klass, MonoGCHandle this_loc, gboolean runtime_init_callback, MonoError *exernal_error); gpointer mono_marshal_get_vtfixup_ftnptr (MonoImage *image, guint32 token, guint16 type); @@ -724,7 +724,7 @@ void mono_marshal_emit_native_wrapper (MonoImage *image, MonoMethodBuilder *mb, MonoMethodSignature *sig, MonoMethodPInvoke *piinfo, MonoMarshalSpec **mspecs, gpointer func, MonoNativeWrapperFlags flags); void -mono_marshal_emit_managed_wrapper (MonoMethodBuilder *mb, MonoMethodSignature *invoke_sig, MonoMarshalSpec **mspecs, EmitMarshalContext* m, MonoMethod *method, MonoGCHandle target_handle, MonoError *error); +mono_marshal_emit_managed_wrapper (MonoMethodBuilder *mb, MonoMethodSignature *invoke_sig, MonoMarshalSpec **mspecs, EmitMarshalContext* m, MonoMethod *method, MonoGCHandle target_handle, gboolean runtime_init_callback, MonoError *error); GHashTable* mono_marshal_get_cache (GHashTable **var, GHashFunc hash_func, GCompareFunc equal_func); diff --git a/src/mono/mono/mini/aot-compiler.c b/src/mono/mono/mini/aot-compiler.c index fb7ed565a7c372..57bee950dd2920 100644 --- a/src/mono/mono/mini/aot-compiler.c +++ b/src/mono/mono/mini/aot-compiler.c @@ -255,6 +255,7 @@ typedef struct MonoAotOptions { gboolean no_opt; char *clangxx; char *depfile; + char *runtime_init_callback; } MonoAotOptions; typedef enum { @@ -5266,7 +5267,7 @@ MONO_RESTORE_WARNING named += slen; } - wrapper = mono_marshal_get_managed_wrapper (method, klass, 0, error); + wrapper = mono_marshal_get_managed_wrapper (method, klass, 0, FALSE, error); mono_error_assert_ok (error); add_method (acfg, wrapper); @@ -5303,7 +5304,7 @@ MONO_RESTORE_WARNING } mono_reflection_free_custom_attr_data_args_noalloc (decoded_args); - wrapper = mono_marshal_get_managed_wrapper (method, NULL, 0, error); + wrapper = mono_marshal_get_managed_wrapper (method, NULL, 0, acfg->aot_opts.runtime_init_callback != NULL && export_name != NULL, error); if (!is_ok (error)) { report_loader_error (acfg, error, FALSE, "Unable to generate native entry point '%s' due to '%s'.", mono_method_get_full_name (method), mono_error_get_message (error)); continue; @@ -6625,13 +6626,24 @@ emit_and_reloc_code (MonoAotCompile *acfg, MonoMethod *method, guint8 *code, gui } } else if (patch_info->type == MONO_PATCH_INFO_JIT_ICALL_ID) { MonoJitICallInfo * const info = mono_find_jit_icall_info (patch_info->data.jit_icall_id); - const char * const sym = info->c_symbol; - if (!got_only && sym && acfg->aot_opts.direct_icalls && info->func == info->wrapper) { - /* Call to a jit icall without a wrapper */ - direct_call = TRUE; - external_call = TRUE; - g_assert (strlen (sym) < 1000); - direct_call_target = g_strdup_printf ("%s%s", acfg->user_symbol_prefix, sym); + if (!got_only && info->func == info->wrapper) { + const char * sym = NULL; + if (patch_info->data.jit_icall_id == MONO_JIT_ICALL_mono_dummy_runtime_init_callback) { + g_assert (acfg->aot_opts.static_link && acfg->aot_opts.runtime_init_callback != NULL); + sym = acfg->aot_opts.runtime_init_callback; + direct_call = TRUE; + external_call = TRUE; + } else if (info->c_symbol && acfg->aot_opts.direct_icalls) { + sym = info->c_symbol; + direct_call = TRUE; + external_call = TRUE; + } + + if (sym) { + /* Call to a jit icall without a wrapper */ + g_assert (strlen (sym) < 1000); + direct_call_target = g_strdup_printf ("%s%s", acfg->user_symbol_prefix, sym); + } } } if (direct_call) { @@ -8749,6 +8761,14 @@ mono_aot_parse_options (const char *aot_options, MonoAotOptions *opts) } } else if (str_begins_with (arg, "depfile=")) { opts->depfile = g_strdup (arg + strlen ("depfile=")); + } else if (str_begins_with (arg, "runtime-init-callback=")) { + opts->runtime_init_callback = g_strdup (arg + strlen ("runtime-init-callback=")); + if (opts->runtime_init_callback [0] == '\0') { + printf ("Missing runtime-init-callback symbol.\n"); + exit (0); + } + } else if (str_begins_with (arg, "runtime-init-callback")) { + opts->runtime_init_callback = g_strdup ("mono_invoke_runtime_init_callback"); } else if (str_begins_with (arg, "help") || str_begins_with (arg, "?")) { printf ("Supported options for --aot:\n"); printf (" asmonly - \n"); @@ -8786,6 +8806,8 @@ mono_aot_parse_options (const char *aot_options, MonoAotOptions *opts) printf (" mibc-profile= - \n"); printf (" print-skipped-methods - \n"); printf (" readonly-value= - \n"); + printf (" runtime-init-callback - \n"); + printf (" runtime-init-callback= - \n"); printf (" save-temps - \n"); printf (" soft-debug - \n"); printf (" static - \n"); @@ -13890,6 +13912,7 @@ aot_opts_free (MonoAotOptions *aot_opts) g_free (aot_opts->llvm_cpu_attr); g_free (aot_opts->clangxx); g_free (aot_opts->depfile); + g_free (aot_opts->runtime_init_callback); } static void @@ -15190,6 +15213,12 @@ mono_aot_assemblies (MonoAssembly **assemblies, int nassemblies, guint32 jit_opt goto early_exit; } + if (aot_opts.runtime_init_callback != NULL && !aot_opts.static_link) { + fprintf (stderr, "The 'runtime-init-callback' option requires the 'static' option.\n"); + res = 1; + goto early_exit; + } + if (aot_opts.dedup_include) { /* Find the assembly which will contain the dedup-ed code */ int dedup_aindex = -1; diff --git a/src/mono/mono/mini/aot-runtime.c b/src/mono/mono/mini/aot-runtime.c index 683fee00852e75..7486bc12bb250e 100644 --- a/src/mono/mono/mini/aot-runtime.c +++ b/src/mono/mono/mini/aot-runtime.c @@ -1308,7 +1308,7 @@ decode_method_ref_with_target (MonoAotModule *module, MethodRef *ref, MonoMethod return FALSE; } else klass = NULL; - ref->method = mono_marshal_get_managed_wrapper (m, klass, 0, error); + ref->method = mono_marshal_get_managed_wrapper (m, klass, 0, FALSE, error); if (!is_ok (error)) return FALSE; break; diff --git a/src/mono/mono/mini/interp/interp.c b/src/mono/mono/mini/interp/interp.c index b52c706cf480b9..55373351c53180 100644 --- a/src/mono/mono/mini/interp/interp.c +++ b/src/mono/mono/mini/interp/interp.c @@ -7298,7 +7298,7 @@ MINT_IN_CASE(MINT_BRTRUE_I8_SP) ZEROP_SP(gint64, !=); MINT_IN_BREAK; // FIXME push/pop LMF if (G_UNLIKELY (mono_method_has_unmanaged_callers_only_attribute (local_cmethod))) { - local_cmethod = mono_marshal_get_managed_wrapper (local_cmethod, NULL, (MonoGCHandle)0, error); + local_cmethod = mono_marshal_get_managed_wrapper (local_cmethod, NULL, (MonoGCHandle)0, FALSE, error); mono_error_assert_ok (error); gpointer addr = mini_get_interp_callbacks ()->create_method_pointer (local_cmethod, TRUE, error); LOCAL_VAR (ip [1], gpointer) = addr; diff --git a/src/mono/mono/mini/interp/transform.c b/src/mono/mono/mini/interp/transform.c index ee6c9bf6337a38..774b6d0a852ca5 100644 --- a/src/mono/mono/mini/interp/transform.c +++ b/src/mono/mono/mini/interp/transform.c @@ -7730,7 +7730,7 @@ generate_code (TransformData *td, MonoMethod *method, MonoMethodHeader *header, MonoClass *delegate_klass = NULL; MonoGCHandle target_handle = 0; ERROR_DECL (wrapper_error); - m = mono_marshal_get_managed_wrapper (m, delegate_klass, target_handle, wrapper_error); + m = mono_marshal_get_managed_wrapper (m, delegate_klass, target_handle, FALSE, wrapper_error); if (!is_ok (wrapper_error)) { /* Generate a call that will throw an exception if the * UnmanagedCallersOnly attribute is used incorrectly */ diff --git a/src/mono/mono/mini/jit-icalls.c b/src/mono/mono/mini/jit-icalls.c index a22a36ea98f5bb..c26e104a09d92b 100644 --- a/src/mono/mono/mini/jit-icalls.c +++ b/src/mono/mono/mini/jit-icalls.c @@ -1708,6 +1708,16 @@ mono_dummy_jit_icall_val (gpointer val) { } +/* Dummy icall place holder function representing runtime init call. */ +/* When used, function will be replaced with a direct icall to a custom */ +/* runtime init function called from start of native-to-managed wrapper. */ +/* This function should never end up being called. */ +void +mono_dummy_runtime_init_callback (void) +{ + g_assert (!"Runtime incorrectly configured to support runtime init callback from native-to-managed wrapper."); +} + void mini_init_method_rgctx (MonoMethodRuntimeGenericContext *mrgctx, MonoGSharedMethodInfo *info) { diff --git a/src/mono/mono/mini/jit-icalls.h b/src/mono/mono/mini/jit-icalls.h index afd10935c5dc44..db59a7608c8da7 100644 --- a/src/mono/mono/mini/jit-icalls.h +++ b/src/mono/mono/mini/jit-icalls.h @@ -238,6 +238,8 @@ ICALL_EXPORT void mono_dummy_jit_icall (void); ICALL_EXPORT void mono_dummy_jit_icall_val (gpointer ptr); +ICALL_EXPORT void mono_dummy_runtime_init_callback (void); + ICALL_EXPORT void mini_init_method_rgctx (MonoMethodRuntimeGenericContext *mrgctx, MonoGSharedMethodInfo *info); #endif /* __MONO_JIT_ICALLS_H__ */ diff --git a/src/mono/mono/mini/method-to-ir.c b/src/mono/mono/mini/method-to-ir.c index adad6ae20b3b65..daaa6495ed06b4 100644 --- a/src/mono/mono/mini/method-to-ir.c +++ b/src/mono/mono/mini/method-to-ir.c @@ -11743,7 +11743,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b MonoGCHandle target_handle = 0; ERROR_DECL (wrapper_error); MonoMethod *wrapped_cmethod; - wrapped_cmethod = mono_marshal_get_managed_wrapper (cmethod, delegate_klass, target_handle, wrapper_error); + wrapped_cmethod = mono_marshal_get_managed_wrapper (cmethod, delegate_klass, target_handle, FALSE, wrapper_error); if (!is_ok (wrapper_error)) { /* if we couldn't create a wrapper because cmethod isn't supposed to have an UnmanagedCallersOnly attribute, follow CoreCLR behavior and throw when the diff --git a/src/mono/mono/mini/mini-runtime.c b/src/mono/mono/mini/mini-runtime.c index 235774701cdd95..1fd4116bee6145 100644 --- a/src/mono/mono/mini/mini-runtime.c +++ b/src/mono/mono/mini/mini-runtime.c @@ -157,6 +157,9 @@ static GPtrArray *profile_options; static GSList *tramp_infos; GSList *mono_interp_only_classes; +static MonoRuntimeInitCallback runtime_init_callback; +static guint64 runtime_init_thread_id = G_MAXUINT64; + static void register_icalls (void); static void runtime_cleanup (MonoDomain *domain, gpointer user_data); static void mini_invalidate_transformed_interp_methods (MonoAssemblyLoadContext *alc, uint32_t generation); @@ -5036,6 +5039,9 @@ register_icalls (void) register_icall_no_wrapper (mono_interp_entry_from_trampoline, mono_icall_sig_void_ptr_ptr); register_icall_no_wrapper (mono_interp_to_native_trampoline, mono_icall_sig_void_ptr_ptr); + /* Register dummy icall placeholder for runtime init callback support in native-to-managed wrapper */ + register_icall_no_wrapper (mono_dummy_runtime_init_callback, mono_icall_sig_void); + #ifdef MONO_ARCH_HAS_REGISTER_ICALL mono_arch_register_icall (); #endif @@ -5395,3 +5401,33 @@ mini_alloc_jinfo (MonoJitMemoryManager *jit_mm, int size) return (MonoJitInfo*)mono_mem_manager_alloc0 (jit_mm->mem_manager, size); } } + +void +mono_set_runtime_init_callback (MonoRuntimeInitCallback callback) +{ + runtime_init_callback = callback; +} + +/* +* Default implementation invoking runtime init callback in native-to-managed wrapper. +*/ +void +mono_invoke_runtime_init_callback (void) +{ + if (G_UNLIKELY (runtime_init_callback)) { + guint64 thread_id = mono_native_thread_os_id_get (); + if (runtime_init_callback && (runtime_init_thread_id == thread_id)) + return; + + while (mono_atomic_cas_i64 ((volatile gint64 *)&runtime_init_thread_id, (gint64)thread_id, (gint64)G_MAXUINT64) != (gint64)G_MAXUINT64) + g_usleep (1000); + + if (runtime_init_callback) { + if (!mono_thread_info_current_unchecked ()) + runtime_init_callback (); + runtime_init_callback = NULL; + } + + mono_atomic_xchg_i64 ((volatile gint64 *)&runtime_init_thread_id, (gint64)G_MAXUINT64); + } +} diff --git a/src/mono/mono/mini/mini-runtime.h b/src/mono/mono/mini/mini-runtime.h index 0abd8e4332334b..16299ff4020527 100644 --- a/src/mono/mono/mini/mini-runtime.h +++ b/src/mono/mono/mini/mini-runtime.h @@ -718,4 +718,12 @@ void mini_register_sigterm_handler (void); MONO_RESTORE_WARNING \ } while (0) +typedef void (*MonoRuntimeInitCallback) (void); + +MONO_COMPONENT_API void +mono_set_runtime_init_callback (MonoRuntimeInitCallback callback); + +MONO_COMPONENT_API void +mono_invoke_runtime_init_callback (void); + #endif /* __MONO_MINI_RUNTIME_H__ */ diff --git a/src/mono/mono/mini/mini.c b/src/mono/mono/mini/mini.c index 098712ff609b81..c6dd66921ccf5b 100644 --- a/src/mono/mono/mini/mini.c +++ b/src/mono/mono/mini/mini.c @@ -3178,8 +3178,8 @@ mini_method_compile (MonoMethod *method, guint32 opts, JitFlags flags, int parts cfg->jit_mm = jit_mm_for_method (cfg->method); cfg->mem_manager = m_method_get_mem_manager (cfg->method); - if (cfg->method->wrapper_type == MONO_WRAPPER_ALLOC) { - /* We can't have seq points inside gc critical regions */ + if (cfg->method->wrapper_type == MONO_WRAPPER_ALLOC || cfg->method->wrapper_type == MONO_WRAPPER_NATIVE_TO_MANAGED) { + /* We can't have seq points inside gc critical regions or native-to-managed wrapper */ cfg->gen_seq_points = FALSE; cfg->gen_sdb_seq_points = FALSE; } diff --git a/src/mono/mono/mini/monovm.c b/src/mono/mono/mini/monovm.c index 3730d6b256da56..a9d2c54a33c6de 100644 --- a/src/mono/mono/mini/monovm.c +++ b/src/mono/mono/mini/monovm.c @@ -368,7 +368,7 @@ monovm_create_delegate_impl (const char* assemblyName, const char* typeName, con MonoClass *delegate_klass = NULL; MonoGCHandle target_handle = 0; - MonoMethod *wrapper = mono_marshal_get_managed_wrapper (method, delegate_klass, target_handle, error); + MonoMethod *wrapper = mono_marshal_get_managed_wrapper (method, delegate_klass, target_handle, FALSE, error); goto_if_nok (error, fail); gpointer addr = mono_compile_method_checked (wrapper, error); From 5a5e35bf575621f07123b5fd03c944d439f3f7db Mon Sep 17 00:00:00 2001 From: lateralusX Date: Fri, 17 Feb 2023 10:08:56 +0100 Subject: [PATCH 2/6] Split mono_marshal_get_managed_wrapper into two functions. --- src/mono/mono/metadata/icall.c | 2 +- src/mono/mono/metadata/marshal.c | 42 ++++++++++++++++++++------- src/mono/mono/metadata/marshal.h | 5 +++- src/mono/mono/mini/aot-compiler.c | 8 +++-- src/mono/mono/mini/aot-runtime.c | 2 +- src/mono/mono/mini/interp/interp.c | 2 +- src/mono/mono/mini/interp/transform.c | 2 +- src/mono/mono/mini/method-to-ir.c | 2 +- src/mono/mono/mini/monovm.c | 2 +- 9 files changed, 47 insertions(+), 20 deletions(-) diff --git a/src/mono/mono/metadata/icall.c b/src/mono/mono/metadata/icall.c index 059552da7299c6..66bdb62a52cf8b 100644 --- a/src/mono/mono/metadata/icall.c +++ b/src/mono/mono/metadata/icall.c @@ -6169,7 +6169,7 @@ mono_method_get_unmanaged_wrapper_ftnptr_internal (MonoMethod *method, gboolean { /* WISH: we should do this in managed */ if (G_UNLIKELY (mono_method_has_unmanaged_callers_only_attribute (method))) { - method = mono_marshal_get_managed_wrapper (method, NULL, (MonoGCHandle)0, FALSE, error); + method = mono_marshal_get_managed_wrapper (method, NULL, (MonoGCHandle)0, error); return_val_if_nok (error, NULL); } else { g_assert (!only_unmanaged_callers_only); diff --git a/src/mono/mono/metadata/marshal.c b/src/mono/mono/metadata/marshal.c index e8cfbed4faddda..d38704c4ded2c7 100644 --- a/src/mono/mono/metadata/marshal.c +++ b/src/mono/mono/metadata/marshal.c @@ -403,7 +403,7 @@ mono_delegate_to_ftnptr_impl (MonoDelegateHandle delegate, MonoError *error) target_handle = mono_gchandle_new_weakref_from_handle (delegate_target); } - wrapper = mono_marshal_get_managed_wrapper (method, klass, target_handle, FALSE, error); + wrapper = mono_marshal_get_managed_wrapper (method, klass, target_handle, error); goto_if_nok (error, leave); MONO_HANDLE_SETVAL (delegate, delegate_trampoline, gpointer, mono_compile_method_checked (wrapper, error)); @@ -4017,16 +4017,8 @@ method_signature_is_usable_when_marshalling_disabled (MonoMethodSignature *sig) return check_all_types_in_method_signature (sig, &type_is_usable_when_marshalling_disabled); } -/** - * mono_marshal_get_managed_wrapper: - * Generates IL code to call managed methods from unmanaged code - * If \p target_handle is \c 0, the wrapper info will be a \c WrapperInfo structure. - * - * If \p delegate_klass is \c NULL, we're creating a wrapper for a function pointer to a method marked with - * UnamangedCallersOnlyAttribute. - */ -MonoMethod * -mono_marshal_get_managed_wrapper (MonoMethod *method, MonoClass *delegate_klass, MonoGCHandle target_handle, gboolean runtime_init_callback, MonoError *error) +static MonoMethod * +marshal_get_managed_wrapper (MonoMethod *method, MonoClass *delegate_klass, MonoGCHandle target_handle, gboolean runtime_init_callback, MonoError *error) { MonoMethodSignature *sig, *csig, *invoke_sig; MonoMethodBuilder *mb; @@ -4225,6 +4217,34 @@ mono_marshal_get_managed_wrapper (MonoMethod *method, MonoClass *delegate_klass, return res; } +/** + * mono_marshal_get_managed_wrapper: + * Generates IL code to call managed methods from unmanaged code + * If \p target_handle is \c 0, the wrapper info will be a \c WrapperInfo structure. + * + * If \p delegate_klass is \c NULL, we're creating a wrapper for a function pointer to a method marked with + * UnamangedCallersOnlyAttribute. + */ +MonoMethod * +mono_marshal_get_managed_wrapper (MonoMethod *method, MonoClass *delegate_klass, MonoGCHandle target_handle, MonoError *error) +{ + return marshal_get_managed_wrapper (method, delegate_klass, target_handle, FALSE, error); +} + +/** + * mono_marshal_get_runtime_init_managed_wrapper: + * Generates IL code to call managed methods from unmanaged code with lazy runtime init support + * If \p target_handle is \c 0, the wrapper info will be a \c WrapperInfo structure. + * + * If \p delegate_klass is \c NULL, we're creating a wrapper for a function pointer to a method marked with + * UnamangedCallersOnlyAttribute. + */ +MonoMethod * +mono_marshal_get_runtime_init_managed_wrapper (MonoMethod *method, MonoClass *delegate_klass, MonoGCHandle target_handle, MonoError *error) +{ + return marshal_get_managed_wrapper (method, delegate_klass, target_handle, TRUE, error); +} + gpointer mono_marshal_get_vtfixup_ftnptr (MonoImage *image, guint32 token, guint16 type) { diff --git a/src/mono/mono/metadata/marshal.h b/src/mono/mono/metadata/marshal.h index 7e11863627462d..c832163172a99c 100644 --- a/src/mono/mono/metadata/marshal.h +++ b/src/mono/mono/metadata/marshal.h @@ -504,7 +504,10 @@ MonoMethodSignature* mono_marshal_get_string_ctor_signature (MonoMethod *method); MonoMethod * -mono_marshal_get_managed_wrapper (MonoMethod *method, MonoClass *delegate_klass, MonoGCHandle this_loc, gboolean runtime_init_callback, MonoError *exernal_error); +mono_marshal_get_managed_wrapper (MonoMethod *method, MonoClass *delegate_klass, MonoGCHandle this_loc, MonoError *exernal_error); + +MonoMethod * +mono_marshal_get_runtime_init_managed_wrapper (MonoMethod *method, MonoClass *delegate_klass, MonoGCHandle this_loc, MonoError *exernal_error); gpointer mono_marshal_get_vtfixup_ftnptr (MonoImage *image, guint32 token, guint16 type); diff --git a/src/mono/mono/mini/aot-compiler.c b/src/mono/mono/mini/aot-compiler.c index 57bee950dd2920..5ef2fe099b0bd6 100644 --- a/src/mono/mono/mini/aot-compiler.c +++ b/src/mono/mono/mini/aot-compiler.c @@ -5267,7 +5267,7 @@ MONO_RESTORE_WARNING named += slen; } - wrapper = mono_marshal_get_managed_wrapper (method, klass, 0, FALSE, error); + wrapper = mono_marshal_get_managed_wrapper (method, klass, 0, error); mono_error_assert_ok (error); add_method (acfg, wrapper); @@ -5304,7 +5304,11 @@ MONO_RESTORE_WARNING } mono_reflection_free_custom_attr_data_args_noalloc (decoded_args); - wrapper = mono_marshal_get_managed_wrapper (method, NULL, 0, acfg->aot_opts.runtime_init_callback != NULL && export_name != NULL, error); + if (acfg->aot_opts.runtime_init_callback != NULL && export_name != NULL) + wrapper = mono_marshal_get_runtime_init_managed_wrapper (method, NULL, 0, error); + else + wrapper = mono_marshal_get_managed_wrapper (method, NULL, 0, error); + if (!is_ok (error)) { report_loader_error (acfg, error, FALSE, "Unable to generate native entry point '%s' due to '%s'.", mono_method_get_full_name (method), mono_error_get_message (error)); continue; diff --git a/src/mono/mono/mini/aot-runtime.c b/src/mono/mono/mini/aot-runtime.c index 7486bc12bb250e..683fee00852e75 100644 --- a/src/mono/mono/mini/aot-runtime.c +++ b/src/mono/mono/mini/aot-runtime.c @@ -1308,7 +1308,7 @@ decode_method_ref_with_target (MonoAotModule *module, MethodRef *ref, MonoMethod return FALSE; } else klass = NULL; - ref->method = mono_marshal_get_managed_wrapper (m, klass, 0, FALSE, error); + ref->method = mono_marshal_get_managed_wrapper (m, klass, 0, error); if (!is_ok (error)) return FALSE; break; diff --git a/src/mono/mono/mini/interp/interp.c b/src/mono/mono/mini/interp/interp.c index 55373351c53180..b52c706cf480b9 100644 --- a/src/mono/mono/mini/interp/interp.c +++ b/src/mono/mono/mini/interp/interp.c @@ -7298,7 +7298,7 @@ MINT_IN_CASE(MINT_BRTRUE_I8_SP) ZEROP_SP(gint64, !=); MINT_IN_BREAK; // FIXME push/pop LMF if (G_UNLIKELY (mono_method_has_unmanaged_callers_only_attribute (local_cmethod))) { - local_cmethod = mono_marshal_get_managed_wrapper (local_cmethod, NULL, (MonoGCHandle)0, FALSE, error); + local_cmethod = mono_marshal_get_managed_wrapper (local_cmethod, NULL, (MonoGCHandle)0, error); mono_error_assert_ok (error); gpointer addr = mini_get_interp_callbacks ()->create_method_pointer (local_cmethod, TRUE, error); LOCAL_VAR (ip [1], gpointer) = addr; diff --git a/src/mono/mono/mini/interp/transform.c b/src/mono/mono/mini/interp/transform.c index 774b6d0a852ca5..ee6c9bf6337a38 100644 --- a/src/mono/mono/mini/interp/transform.c +++ b/src/mono/mono/mini/interp/transform.c @@ -7730,7 +7730,7 @@ generate_code (TransformData *td, MonoMethod *method, MonoMethodHeader *header, MonoClass *delegate_klass = NULL; MonoGCHandle target_handle = 0; ERROR_DECL (wrapper_error); - m = mono_marshal_get_managed_wrapper (m, delegate_klass, target_handle, FALSE, wrapper_error); + m = mono_marshal_get_managed_wrapper (m, delegate_klass, target_handle, wrapper_error); if (!is_ok (wrapper_error)) { /* Generate a call that will throw an exception if the * UnmanagedCallersOnly attribute is used incorrectly */ diff --git a/src/mono/mono/mini/method-to-ir.c b/src/mono/mono/mini/method-to-ir.c index daaa6495ed06b4..adad6ae20b3b65 100644 --- a/src/mono/mono/mini/method-to-ir.c +++ b/src/mono/mono/mini/method-to-ir.c @@ -11743,7 +11743,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b MonoGCHandle target_handle = 0; ERROR_DECL (wrapper_error); MonoMethod *wrapped_cmethod; - wrapped_cmethod = mono_marshal_get_managed_wrapper (cmethod, delegate_klass, target_handle, FALSE, wrapper_error); + wrapped_cmethod = mono_marshal_get_managed_wrapper (cmethod, delegate_klass, target_handle, wrapper_error); if (!is_ok (wrapper_error)) { /* if we couldn't create a wrapper because cmethod isn't supposed to have an UnmanagedCallersOnly attribute, follow CoreCLR behavior and throw when the diff --git a/src/mono/mono/mini/monovm.c b/src/mono/mono/mini/monovm.c index a9d2c54a33c6de..3730d6b256da56 100644 --- a/src/mono/mono/mini/monovm.c +++ b/src/mono/mono/mini/monovm.c @@ -368,7 +368,7 @@ monovm_create_delegate_impl (const char* assemblyName, const char* typeName, con MonoClass *delegate_klass = NULL; MonoGCHandle target_handle = 0; - MonoMethod *wrapper = mono_marshal_get_managed_wrapper (method, delegate_klass, target_handle, FALSE, error); + MonoMethod *wrapper = mono_marshal_get_managed_wrapper (method, delegate_klass, target_handle, error); goto_if_nok (error, fail); gpointer addr = mono_compile_method_checked (wrapper, error); From d7a63d33ca99d69b61280cb6448bfc78054c327b Mon Sep 17 00:00:00 2001 From: lateralusX Date: Fri, 17 Feb 2023 10:19:20 +0100 Subject: [PATCH 3/6] Drop runtime init for mono_marshal_emit_managed_wrapper. --- src/mono/mono/metadata/marshal.c | 10 +++++----- src/mono/mono/metadata/marshal.h | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/mono/mono/metadata/marshal.c b/src/mono/mono/metadata/marshal.c index d38704c4ded2c7..e7aff60aee5e24 100644 --- a/src/mono/mono/metadata/marshal.c +++ b/src/mono/mono/metadata/marshal.c @@ -3910,15 +3910,15 @@ mono_marshal_get_native_func_wrapper_indirect (MonoClass *caller_class, MonoMeth /* * mono_marshal_emit_managed_wrapper: * - * Emit the body of a native-to-managed wrapper. INVOKE_SIG is the signature of + * Emit the body of a native-to-managed wrapper. INVOKE_SIG is the signature of * the delegate which wraps the managed method to be called. For closed delegates, * it could have fewer parameters than the method it wraps. * THIS_LOC is the memory location where the target of the delegate is stored. */ void -mono_marshal_emit_managed_wrapper (MonoMethodBuilder *mb, MonoMethodSignature *invoke_sig, MonoMarshalSpec **mspecs, EmitMarshalContext* m, MonoMethod *method, MonoGCHandle target_handle, gboolean runtime_init_callback, MonoError *error) +mono_marshal_emit_managed_wrapper (MonoMethodBuilder *mb, MonoMethodSignature *invoke_sig, MonoMarshalSpec **mspecs, EmitMarshalContext* m, MonoMethod *method, MonoGCHandle target_handle, MonoError *error) { - get_marshal_cb ()->emit_managed_wrapper (mb, invoke_sig, mspecs, m, method, target_handle, runtime_init_callback, error); + get_marshal_cb ()->emit_managed_wrapper (mb, invoke_sig, mspecs, m, method, target_handle, FALSE, error); } static gboolean @@ -4184,7 +4184,7 @@ marshal_get_managed_wrapper (MonoMethod *method, MonoClass *delegate_klass, Mono mono_custom_attrs_free (cinfo); } - mono_marshal_emit_managed_wrapper (mb, invoke_sig, mspecs, &m, method, target_handle, runtime_init_callback, error); + get_marshal_cb ()->emit_managed_wrapper (mb, invoke_sig, mspecs, &m, method, target_handle, runtime_init_callback, error); res = NULL; if (is_ok (error)) { @@ -4293,7 +4293,7 @@ mono_marshal_get_vtfixup_ftnptr (MonoImage *image, guint32 token, guint16 type) /* FIXME: Implement VTFIXUP_TYPE_FROM_UNMANAGED_RETAIN_APPDOMAIN. */ - mono_marshal_emit_managed_wrapper (mb, sig, mspecs, &m, method, 0, FALSE, error); + mono_marshal_emit_managed_wrapper (mb, sig, mspecs, &m, method, 0, error); mono_error_assert_ok (error); get_marshal_cb ()->mb_set_dynamic (mb); diff --git a/src/mono/mono/metadata/marshal.h b/src/mono/mono/metadata/marshal.h index c832163172a99c..6cd33778301f93 100644 --- a/src/mono/mono/metadata/marshal.h +++ b/src/mono/mono/metadata/marshal.h @@ -727,7 +727,7 @@ void mono_marshal_emit_native_wrapper (MonoImage *image, MonoMethodBuilder *mb, MonoMethodSignature *sig, MonoMethodPInvoke *piinfo, MonoMarshalSpec **mspecs, gpointer func, MonoNativeWrapperFlags flags); void -mono_marshal_emit_managed_wrapper (MonoMethodBuilder *mb, MonoMethodSignature *invoke_sig, MonoMarshalSpec **mspecs, EmitMarshalContext* m, MonoMethod *method, MonoGCHandle target_handle, gboolean runtime_init_callback, MonoError *error); +mono_marshal_emit_managed_wrapper (MonoMethodBuilder *mb, MonoMethodSignature *invoke_sig, MonoMarshalSpec **mspecs, EmitMarshalContext* m, MonoMethod *method, MonoGCHandle target_handle, MonoError *error); GHashTable* mono_marshal_get_cache (GHashTable **var, GHashFunc hash_func, GCompareFunc equal_func); From 60dfa5b7719fbcf0506e3c8adeb62acf4b659554 Mon Sep 17 00:00:00 2001 From: lateralusX Date: Mon, 20 Feb 2023 18:06:01 +0100 Subject: [PATCH 4/6] aquire/release semantics around runtime_init_callback. --- src/mono/mono/mini/mini-runtime.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/src/mono/mono/mini/mini-runtime.c b/src/mono/mono/mini/mini-runtime.c index 1fd4116bee6145..cd7117dde4143e 100644 --- a/src/mono/mono/mini/mini-runtime.c +++ b/src/mono/mono/mini/mini-runtime.c @@ -5414,18 +5414,21 @@ mono_set_runtime_init_callback (MonoRuntimeInitCallback callback) void mono_invoke_runtime_init_callback (void) { - if (G_UNLIKELY (runtime_init_callback)) { + MonoRuntimeInitCallback callback = NULL; + mono_atomic_load_acquire (callback, MonoRuntimeInitCallback, &runtime_init_callback); + if (G_UNLIKELY (callback)) { guint64 thread_id = mono_native_thread_os_id_get (); - if (runtime_init_callback && (runtime_init_thread_id == thread_id)) + if (callback && (mono_atomic_load_i64 ((volatile gint64 *)&runtime_init_thread_id) == thread_id)) return; while (mono_atomic_cas_i64 ((volatile gint64 *)&runtime_init_thread_id, (gint64)thread_id, (gint64)G_MAXUINT64) != (gint64)G_MAXUINT64) g_usleep (1000); - if (runtime_init_callback) { + mono_atomic_load_acquire (callback, MonoRuntimeInitCallback, &runtime_init_callback); + if (callback) { if (!mono_thread_info_current_unchecked ()) - runtime_init_callback (); - runtime_init_callback = NULL; + callback (); + mono_atomic_store_release (&runtime_init_callback, NULL); } mono_atomic_xchg_i64 ((volatile gint64 *)&runtime_init_thread_id, (gint64)G_MAXUINT64); From 5ff138ff34d6fc0fba8fa21b269ce1a3a96ab3bf Mon Sep 17 00:00:00 2001 From: lateralusX Date: Mon, 20 Feb 2023 18:07:45 +0100 Subject: [PATCH 5/6] Detect MONO_JIT_ICALL_mono_dummy_runtime_init_callback in more places. --- src/mono/mono/mini/aot-compiler.c | 38 ++++++++++++++++--------------- 1 file changed, 20 insertions(+), 18 deletions(-) diff --git a/src/mono/mono/mini/aot-compiler.c b/src/mono/mono/mini/aot-compiler.c index 5ef2fe099b0bd6..1e9b4a924e87ad 100644 --- a/src/mono/mono/mini/aot-compiler.c +++ b/src/mono/mono/mini/aot-compiler.c @@ -10316,28 +10316,30 @@ mono_aot_mark_unused_llvm_plt_entry (MonoJumpInfo *patch_info) char* mono_aot_get_direct_call_symbol (MonoJumpInfoType type, gconstpointer data) { + gboolean direct_calls = llvm_acfg->aot_opts.direct_icalls; const char *sym = NULL; - if (llvm_acfg->aot_opts.direct_icalls) { - if (type == MONO_PATCH_INFO_JIT_ICALL_ADDR) { - /* Call to a C function implementing a jit icall */ - sym = mono_find_jit_icall_info ((MonoJitICallId)(gsize)data)->c_symbol; - } else if (type == MONO_PATCH_INFO_ICALL_ADDR_CALL) { - MonoMethod *method = (MonoMethod *)data; - if (!(method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL)) - sym = lookup_icall_symbol_name_aot (method); - else if (is_direct_pinvoke_specified_for_method (llvm_acfg, method)) - get_pinvoke_import (llvm_acfg, method, NULL, &sym); - } else if (type == MONO_PATCH_INFO_JIT_ICALL_ID) { - MonoJitICallInfo const * const info = mono_find_jit_icall_info ((MonoJitICallId)(gsize)data); - char const * const name = info->c_symbol; - if (name && info->func == info->wrapper) - sym = name; + if (direct_calls && type == MONO_PATCH_INFO_JIT_ICALL_ADDR) { + /* Call to a C function implementing a jit icall */ + sym = mono_find_jit_icall_info ((MonoJitICallId)(gsize)data)->c_symbol; + } else if (direct_calls && type == MONO_PATCH_INFO_ICALL_ADDR_CALL) { + MonoMethod *method = (MonoMethod *)data; + if (!(method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL)) + sym = lookup_icall_symbol_name_aot (method); + else if (is_direct_pinvoke_specified_for_method (llvm_acfg, method)) + get_pinvoke_import (llvm_acfg, method, NULL, &sym); + } else if (type == MONO_PATCH_INFO_JIT_ICALL_ID && (direct_calls || (MonoJitICallId)(gsize)data == MONO_JIT_ICALL_mono_dummy_runtime_init_callback)) { + MonoJitICallInfo const * const info = mono_find_jit_icall_info ((MonoJitICallId)(gsize)data); + if (info->func == info->wrapper) { + if ((MonoJitICallId)(gsize)data == MONO_JIT_ICALL_mono_dummy_runtime_init_callback) { + sym = llvm_acfg->aot_opts.runtime_init_callback; + } else { + sym = info->c_symbol ? info->c_symbol : NULL; + } } - if (sym) - return g_strdup (sym); } - return NULL; + + return sym ? g_strdup (sym) : NULL; } char* From f6fe400bf281043ca0968004c86d635cb63b410b Mon Sep 17 00:00:00 2001 From: lateralusX Date: Tue, 21 Feb 2023 12:04:40 +0100 Subject: [PATCH 6/6] Add description of new AOT compiler options. --- src/mono/mono/mini/aot-compiler.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/mono/mono/mini/aot-compiler.c b/src/mono/mono/mini/aot-compiler.c index 1e9b4a924e87ad..4481c694d36c81 100644 --- a/src/mono/mono/mini/aot-compiler.c +++ b/src/mono/mono/mini/aot-compiler.c @@ -8810,8 +8810,8 @@ mono_aot_parse_options (const char *aot_options, MonoAotOptions *opts) printf (" mibc-profile= - \n"); printf (" print-skipped-methods - \n"); printf (" readonly-value= - \n"); - printf (" runtime-init-callback - \n"); - printf (" runtime-init-callback= - \n"); + printf (" runtime-init-callback - Enable default runtime init callback support for UnmanagedCallersOnly+EntryPoint native-to-managed wrappers. Requires 'static' option.\n"); + printf (" runtime-init-callback= - Enable custom runtime init callback support for UnmanagedCallersOnly+EntryPoint native-to-managed wrappers. Requires 'static' option. Wrapper makes a direct call to symbol, initializing runtime.\n"); printf (" save-temps - \n"); printf (" soft-debug - \n"); printf (" static - \n");