Skip to content

Commit

Permalink
[mono][mini] Prefer calling llvmaot compiled method instead of inlini…
Browse files Browse the repository at this point in the history
…ng it with JIT (#107401)

* [mono][mini] Prefer llvmaot compiled method instead of inlining it with JIT

The motivation for this is to fix crashes due to different HW intrinsics support between llvm and JIT. For example, a llvmaot compiled method might check if we have a set of HW intrinsics available and proceed with a code path that will end up calling a method that assumes intrinsics support that is not present in the aot image (because the gsharedvt version is not emitted for example). In this scenario, the called method will end up being compiled with JIT where we would crash due to missing HW intrinsics support.

* [mono][mini] Prefer llvm compiled method only if it uses simd intrinsics

We include a new flag when compiling aot method. When loading aot method, we will include mapping from code to flags so we can look it up later.
  • Loading branch information
BrzVlad committed Sep 16, 2024
1 parent ad7b02a commit cdc8418
Show file tree
Hide file tree
Showing 4 changed files with 39 additions and 10 deletions.
2 changes: 2 additions & 0 deletions src/mono/mono/mini/aot-compiler.c
Original file line number Diff line number Diff line change
Expand Up @@ -7607,6 +7607,8 @@ emit_method_info (MonoAotCompile *acfg, MonoCompile *cfg)
flags |= MONO_AOT_METHOD_FLAG_HAS_CTX;
if (cfg->interp_entry_only)
flags |= MONO_AOT_METHOD_FLAG_INTERP_ENTRY_ONLY;
if (cfg->uses_simd_intrinsics && cfg->compile_llvm)
flags |= MONO_AOT_METHOD_FLAG_HAS_LLVM_INTRINSICS;
/* Saved into another table so it can be accessed without having access to this data */
cfg->aot_method_flags = flags;

Expand Down
31 changes: 21 additions & 10 deletions src/mono/mono/mini/aot-runtime.c
Original file line number Diff line number Diff line change
Expand Up @@ -4441,16 +4441,15 @@ load_method (MonoAotModule *amodule, MonoImage *image, MonoMethod *method, guint
g_free (full_name);
}

if (mono_llvm_only) {
guint8 flags = amodule->method_flags_table [method_index];
/* The caller needs to looks this up, but its hard to do without constructing the full MonoJitInfo, so save it here */
if (flags & (MONO_AOT_METHOD_FLAG_GSHAREDVT_VARIABLE | MONO_AOT_METHOD_FLAG_INTERP_ENTRY_ONLY)) {
mono_aot_lock ();
if (!code_to_method_flags)
code_to_method_flags = g_hash_table_new (NULL, NULL);
g_hash_table_insert (code_to_method_flags, code, GUINT_TO_POINTER (flags));
mono_aot_unlock ();
}
guint8 flags = amodule->method_flags_table [method_index];
/* The caller needs to looks this up, but its hard to do without constructing the full MonoJitInfo, so save it here */
if ((mono_llvm_only && (flags & (MONO_AOT_METHOD_FLAG_GSHAREDVT_VARIABLE | MONO_AOT_METHOD_FLAG_INTERP_ENTRY_ONLY))) ||
(flags & MONO_AOT_METHOD_FLAG_HAS_LLVM_INTRINSICS)) {
mono_aot_lock ();
if (!code_to_method_flags)
code_to_method_flags = g_hash_table_new (NULL, NULL);
g_hash_table_insert (code_to_method_flags, code, GUINT_TO_POINTER (flags));
mono_aot_unlock ();
}

init_plt (amodule);
Expand Down Expand Up @@ -6547,6 +6546,12 @@ mono_aot_get_method_flags (guint8 *code)
return (MonoAotMethodFlags)flags;
}

MonoAotFileFlags
mono_aot_get_module_flags (gpointer aot_module)
{
return ((MonoAotModule*)aot_module)->info.flags;
}

#else
/* AOT disabled */

Expand Down Expand Up @@ -6747,4 +6752,10 @@ mono_aot_get_method_flags (guint8 *code)
return MONO_AOT_METHOD_FLAG_NONE;
}

MonoAotFileFlags
mono_aot_get_module_flags (gpointer aot_module)
{
return 0;
}

#endif
2 changes: 2 additions & 0 deletions src/mono/mono/mini/aot-runtime.h
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ typedef enum {
MONO_AOT_METHOD_FLAG_HAS_PATCHES = 4,
MONO_AOT_METHOD_FLAG_HAS_CTX = 8,
MONO_AOT_METHOD_FLAG_INTERP_ENTRY_ONLY = 16,
MONO_AOT_METHOD_FLAG_HAS_LLVM_INTRINSICS = 32,
} MonoAotMethodFlags;

#undef DEBUG_AOT_NAME_TABLE
Expand Down Expand Up @@ -282,6 +283,7 @@ guint32 mono_aot_find_method_index (MonoMethod *method);
gboolean mono_aot_init_llvm_method (gpointer aot_module, gpointer method_info, MonoClass *init_class, MonoError *error);
GHashTable *mono_aot_get_weak_field_indexes (MonoImage *image);
MonoAotMethodFlags mono_aot_get_method_flags (guint8 *code);
MonoAotFileFlags mono_aot_get_module_flags (gpointer aot_module);

#ifdef MONO_ARCH_CODE_EXEC_ONLY
typedef guint32 (*MonoAotResolvePltInfoOffset)(gpointer amodule, guint32 plt_entry_index);
Expand Down
14 changes: 14 additions & 0 deletions src/mono/mono/mini/method-to-ir.c
Original file line number Diff line number Diff line change
Expand Up @@ -4179,6 +4179,20 @@ mono_method_check_inlining (MonoCompile *cfg, MonoMethod *method)
if (method_does_not_return (method))
return FALSE;

MonoAotModule *amodule = m_class_get_image (method->klass)->aot_module;
// If method is present in aot image compiled with llvm and it uses hw intrinsics we don't inline it,
// since we might not have support for those intrinsics with JIT
if (amodule && (amodule != AOT_MODULE_NOT_FOUND) && (mono_aot_get_module_flags (amodule) & MONO_AOT_FILE_FLAG_WITH_LLVM)) {
ERROR_DECL (error);
mono_class_init_internal (method->klass);
gpointer addr = mono_aot_get_method (method, error);
if (addr && is_ok (error)) {
MonoAotMethodFlags flags = mono_aot_get_method_flags (addr);
if (flags & MONO_AOT_METHOD_FLAG_HAS_LLVM_INTRINSICS)
return FALSE;
}
}

return TRUE;
}

Expand Down

0 comments on commit cdc8418

Please sign in to comment.