Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mono/mono.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorZoltan Varga <vargaz@gmail.com>2020-01-31 19:41:49 +0300
committerGitHub <noreply@github.com>2020-01-31 19:41:49 +0300
commita475b84a3eec7c6e1824ab2ad32de34ecb34f7aa (patch)
treeb0d4b909d042f61c568c38a7bad3526889a0d13c
parent4ef40a91ed602a0a13730ee4103cfb5d1d300b9a (diff)
[aot] Add support for making direct cross-assembly calls in llvm mode. (#18505)
* [aot] Handle '|' during symbol mangling. * [aot] Clean up the construction of the linker command line. * [aot] Pass -Wl,-install_name to the linker on osx, otherwise the shared object will be named based on the output file name i.e. <assembly>.dylib.tmp. * [llvm] Pass the MonoAotFileInfo pointer to the init functions, not used yet. * [jit] Add support for direct calls between methods in different AOT images in LLVM mode. * Add a 'direct-extern-calls' AOT option. * Initialize the PLT/GOT during method initialization, this normally happens in load_method () but that is not called when a method is directly called. * Add self initialization support for JITted methods, they can be called directly since they are fallbacks if LLVM fails. * Fix the build. * Avoid calling BeginInvoke etc. directly, its implemented by the runtime. * Unify some cases. * Init PLT at image load time since directly called methods without initializers might make calls through it. * Fix a startup problem. * Make the mono_is_corlib_image () check for during startup. * Check for is_inited in the init icall wrappers, since they might be called from JITted code which doesn't check it. * Address review comments.
-rw-r--r--mono/metadata/icall-signatures.h2
-rw-r--r--mono/mini/aot-compiler.c162
-rw-r--r--mono/mini/aot-compiler.h1
-rw-r--r--mono/mini/aot-runtime.c47
-rw-r--r--mono/mini/aot-runtime.h2
-rw-r--r--mono/mini/llvmonly-runtime.c8
-rw-r--r--mono/mini/llvmonly-runtime.h9
-rw-r--r--mono/mini/method-to-ir.c22
-rw-r--r--mono/mini/mini-llvm.c170
-rw-r--r--mono/mini/mini-runtime.c8
-rw-r--r--mono/mini/mini.c2
-rw-r--r--mono/mini/mini.h3
12 files changed, 337 insertions, 99 deletions
diff --git a/mono/metadata/icall-signatures.h b/mono/metadata/icall-signatures.h
index aa15e211bc1..876c427c314 100644
--- a/mono/metadata/icall-signatures.h
+++ b/mono/metadata/icall-signatures.h
@@ -257,6 +257,8 @@ ICALL_SIG (5, (void, object, ptr, int32, int32)) \
ICALL_SIG (5, (void, object, ptr, ptr, ptr)) \
ICALL_SIG (5, (void, ptr, int, int, object)) \
ICALL_SIG (5, (void, ptr, ptr, ptr, ptr)) \
+ICALL_SIG (5, (void, ptr, ptr, int, object)) \
+ICALL_SIG (5, (void, ptr, ptr, int, ptr)) \
ICALL_SIG (5, (ptr, ptr, ptr, ptr, ptr)) \
ICALL_SIG (6, (int, int, int, ptr, ptr, ptr)) \
ICALL_SIG (6, (int, ptr, int, int, ptr, object)) \
diff --git a/mono/mini/aot-compiler.c b/mono/mini/aot-compiler.c
index 6c43e33611f..d194a35afec 100644
--- a/mono/mini/aot-compiler.c
+++ b/mono/mini/aot-compiler.c
@@ -203,6 +203,7 @@ typedef struct MonoAotOptions {
char *gen_msym_dir_path;
gboolean direct_pinvoke;
gboolean direct_icalls;
+ gboolean direct_extern_calls;
gboolean no_direct_calls;
gboolean use_trampolines_page;
gboolean no_instances;
@@ -5800,6 +5801,63 @@ mono_aot_direct_icalls_enabled_for_method (MonoCompile *cfg, MonoMethod *method)
}
/*
+ * method_is_externally_callable:
+ *
+ * Return whenever METHOD can be directly called from other AOT images
+ * without going through a PLT.
+ */
+static gboolean
+method_is_externally_callable (MonoAotCompile *acfg, MonoMethod *method)
+{
+ // FIXME: Unify
+ if (acfg->aot_opts.llvm_only) {
+ if (!acfg->aot_opts.static_link)
+ return FALSE;
+ if (method->wrapper_type == MONO_WRAPPER_ALLOC)
+ return TRUE;
+ if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE)
+ return TRUE;
+ if (method->string_ctor)
+ return FALSE;
+ if (method->wrapper_type)
+ return FALSE;
+ if ((method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) || (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
+ return FALSE;
+ if (method->is_inflated)
+ return FALSE;
+ if (!((mono_class_get_flags (method->klass) & TYPE_ATTRIBUTE_PUBLIC) && (method->flags & METHOD_ATTRIBUTE_PUBLIC)))
+ return FALSE;
+ /* Can't enable this as the callee might fail llvm compilation */
+ //return TRUE;
+ return FALSE;
+ } else {
+ if (!acfg->aot_opts.direct_extern_calls)
+ return FALSE;
+ if (!acfg->llvm || acfg->aot_opts.llvm_disable_self_init)
+ return FALSE;
+ if (acfg->aot_opts.soft_debug || acfg->aot_opts.no_direct_calls)
+ return FALSE;
+ if (method->wrapper_type == MONO_WRAPPER_ALLOC)
+ return FALSE;
+ if (method->string_ctor)
+ return FALSE;
+ if (method->wrapper_type)
+ return FALSE;
+ if ((method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) || (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
+ return FALSE;
+ if (method->iflags & METHOD_IMPL_ATTRIBUTE_SYNCHRONIZED)
+ return FALSE;
+ if (method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME)
+ return FALSE;
+ if (method->is_inflated)
+ return FALSE;
+ if (!((mono_class_get_flags (method->klass) & TYPE_ATTRIBUTE_PUBLIC) && (method->flags & METHOD_ATTRIBUTE_PUBLIC)))
+ return FALSE;
+ return TRUE;
+ }
+}
+
+/*
* is_direct_callable:
*
* Return whenever the method identified by JI is directly callable without
@@ -5851,6 +5909,9 @@ is_direct_callable (MonoAotCompile *acfg, MonoMethod *method, MonoJumpInfo *patc
if (direct_callable)
return TRUE;
}
+ } else if ((patch_info->type == MONO_PATCH_INFO_METHOD) && (m_class_get_image (patch_info->data.method->klass) != acfg->image)) {
+ /* Cross assembly calls */
+ return method_is_externally_callable (acfg, patch_info->data.method);
} else if ((patch_info->type == MONO_PATCH_INFO_ICALL_ADDR_CALL && patch_info->data.method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL)) {
if (acfg->aot_opts.direct_pinvoke)
return TRUE;
@@ -6132,13 +6193,28 @@ emit_and_reloc_code (MonoAotCompile *acfg, MonoMethod *method, guint8 *code, gui
*/
direct_call = FALSE;
external_call = FALSE;
- if ((patch_info->type == MONO_PATCH_INFO_METHOD) && (m_class_get_image (patch_info->data.method->klass) == acfg->image)) {
- if (!got_only && is_direct_callable (acfg, method, patch_info)) {
- MonoCompile *callee_cfg = (MonoCompile *)g_hash_table_lookup (acfg->method_to_cfg, patch_info->data.method);
+ if (patch_info->type == MONO_PATCH_INFO_METHOD) {
+ MonoMethod *cmethod = patch_info->data.method;
+ if (cmethod->wrapper_type == MONO_WRAPPER_OTHER && mono_marshal_get_wrapper_info (cmethod)->subtype == WRAPPER_SUBTYPE_AOT_INIT) {
+ WrapperInfo *info = mono_marshal_get_wrapper_info (cmethod);
+
+ /*
+ * This is a call from a JITted method to the init wrapper emitted by LLVM.
+ */
+ g_assert (acfg->aot_opts.llvm && acfg->aot_opts.direct_extern_calls);
+
+ const char *init_name = mono_marshal_get_aot_init_wrapper_name (info->d.aot_init.subtype);
+ char *symbol = g_strdup_printf ("%s%s_%s", acfg->user_symbol_prefix, acfg->global_prefix, init_name);
+
+ direct_call = TRUE;
+ direct_call_target = symbol;
+ patch_info->type = MONO_PATCH_INFO_NONE;
+ } else if ((m_class_get_image (patch_info->data.method->klass) == acfg->image) && !got_only && is_direct_callable (acfg, method, patch_info)) {
+ MonoCompile *callee_cfg = (MonoCompile *)g_hash_table_lookup (acfg->method_to_cfg, cmethod);
// Don't compile inflated methods if we're doing dedup
- if (acfg->aot_opts.dedup && !mono_aot_can_dedup (patch_info->data.method)) {
- char *name = mono_aot_get_mangled_method_name (patch_info->data.method);
+ if (acfg->aot_opts.dedup && !mono_aot_can_dedup (cmethod)) {
+ char *name = mono_aot_get_mangled_method_name (cmethod);
mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_AOT, "DIRECT CALL: %s by %s", name, method ? mono_method_full_name (method, TRUE) : "");
g_free (name);
@@ -8091,6 +8167,8 @@ mono_aot_parse_options (const char *aot_options, MonoAotOptions *opts)
opts->direct_pinvoke = TRUE;
} else if (str_begins_with (arg, "direct-icalls")) {
opts->direct_icalls = TRUE;
+ } else if (str_begins_with (arg, "direct-extern-calls")) {
+ opts->direct_extern_calls = TRUE;
} else if (str_begins_with (arg, "no-direct-calls")) {
opts->no_direct_calls = TRUE;
} else if (str_begins_with (arg, "print-skipped")) {
@@ -8609,6 +8687,8 @@ compile_method (MonoAotCompile *acfg, MonoMethod *method)
flags = (JitFlags)(flags | JIT_FLAG_INTERP);
if (acfg->aot_opts.use_current_cpu)
flags = (JitFlags)(flags | JIT_FLAG_USE_CURRENT_CPU);
+ if (method_is_externally_callable (acfg, method))
+ flags = (JitFlags)(flags | JIT_FLAG_SELF_INIT);
jit_time_start = mono_time_track_start ();
cfg = mini_method_compile (method, acfg->opts, mono_get_root_domain (), flags, 0, index);
@@ -8839,6 +8919,16 @@ compile_method (MonoAotCompile *acfg, MonoMethod *method)
if (cfg->llvm_only)
acfg->stats.llvm_count ++;
+ if (acfg->llvm && !cfg->compile_llvm && method_is_externally_callable (acfg, cfg->method)) {
+ /*
+ * This is a JITted fallback method for a method which failed LLVM compilation, emit a global
+ * symbol for it with the same name the LLVM method would get.
+ */
+ char *name = mono_aot_get_mangled_method_name (cfg->method);
+ char *export_name = g_strdup_printf ("%s%s", acfg->user_symbol_prefix, name);
+ g_hash_table_insert (acfg->export_names, cfg->method, export_name);
+ }
+
/*
* FIXME: Instead of this mess, allocate the patches from the aot mempool.
*/
@@ -8964,6 +9054,12 @@ mono_aot_is_shared_got_offset (int offset)
return offset < llvm_acfg->nshared_got_entries;
}
+gboolean
+mono_aot_is_externally_callable (MonoMethod *cmethod)
+{
+ return method_is_externally_callable (llvm_acfg, cmethod);
+}
+
char*
mono_aot_get_method_name (MonoCompile *cfg)
{
@@ -9330,6 +9426,9 @@ sanitize_mangled_string (const char *input)
case ':':
g_string_append (s, "_colon_");
break;
+ case '|':
+ g_string_append (s, "_verbar_");
+ break;
default:
g_string_append_c (s, c);
}
@@ -12186,29 +12285,32 @@ compile_asm (MonoAotCompile *acfg)
g_assert (objfile != NULL);
command = g_strdup_printf ("\"%s%s\" %s %s /OUT:%s %s %s", tool_prefix, LD_NAME,
acfg->aot_opts.nodebug ? LD_OPTIONS : LD_DEBUG_OPTIONS, ld_flags, wrap_path (tmp_outfile_name), wrap_path (objfile), wrap_path (llvm_ofile));
-#elif defined(LD_NAME)
- command = g_strdup_printf ("%s%s %s -o %s %s %s %s", tool_prefix, LD_NAME, LD_OPTIONS,
- wrap_path (tmp_outfile_name), wrap_path (llvm_ofile),
- wrap_path (g_strdup_printf ("%s." AS_OBJECT_FILE_SUFFIX, acfg->tmpfname)), ld_flags);
+#else
+ GString *str;
+
+ str = g_string_new ("");
+#if defined(LD_NAME)
+ g_string_append_printf (str, "%s%s %s", tool_prefix, LD_NAME, LD_OPTIONS);
#else
// Default (linux)
- if (acfg->aot_opts.tool_prefix) {
+ if (acfg->aot_opts.tool_prefix)
/* Cross compiling */
- command = g_strdup_printf ("\"%sld\" %s -shared -o %s %s %s %s", tool_prefix, LD_OPTIONS,
- wrap_path (tmp_outfile_name), wrap_path (llvm_ofile),
- wrap_path (g_strdup_printf ("%s." AS_OBJECT_FILE_SUFFIX, acfg->tmpfname)), ld_flags);
- } else {
- char *args = g_strdup_printf ("%s -shared -o %s %s %s %s", LD_OPTIONS,
- wrap_path (tmp_outfile_name), wrap_path (llvm_ofile),
- wrap_path (g_strdup_printf ("%s." AS_OBJECT_FILE_SUFFIX, acfg->tmpfname)), ld_flags);
+ g_string_append_printf (str, "\"%sld\" %s", tool_prefix, LD_OPTIONS);
+ else if (acfg->aot_opts.llvm_only)
+ g_string_append_printf (str, "%s", acfg->aot_opts.clangxx);
+ else
+ g_string_append_printf (str, "\"%sld\"", tool_prefix);
+ g_string_append_printf (str, " -shared");
+#endif
+ g_string_append_printf (str, " -o %s %s %s %s",
+ wrap_path (tmp_outfile_name), wrap_path (llvm_ofile),
+ wrap_path (g_strdup_printf ("%s." AS_OBJECT_FILE_SUFFIX, acfg->tmpfname)), ld_flags);
- if (acfg->aot_opts.llvm_only) {
- command = g_strdup_printf ("%s %s", acfg->aot_opts.clangxx, args);
- } else {
- command = g_strdup_printf ("\"%sld\" %s", tool_prefix, args);
- }
- g_free (args);
- }
+#if defined(TARGET_MACH)
+ g_string_append_printf (str, " -Wl,-install_name,%s%s", g_path_get_basename (acfg->image->name), MONO_SOLIB_EXT);
+#endif
+
+ command = g_string_free (str, FALSE);
#endif
aot_printf (acfg, "Executing the native linker: %s\n", command);
if (execute_system (command) != 0) {
@@ -13026,7 +13128,6 @@ add_preinit_got_slots (MonoAotCompile *acfg)
* Allocate the first few GOT entries to information which is needed frequently, or it is needed
* during method initialization etc.
*/
-
ji = (MonoJumpInfo *)mono_mempool_alloc0 (acfg->mempool, sizeof (MonoJumpInfo));
ji->type = MONO_PATCH_INFO_IMAGE;
ji->data.image = acfg->image;
@@ -13471,6 +13572,11 @@ mono_compile_assembly (MonoAssembly *ass, guint32 opts, const char *aot_options,
mono_aot_parse_options (aot_options, &acfg->aot_opts);
+ if (acfg->aot_opts.direct_extern_calls && !(acfg->aot_opts.llvm && acfg->aot_opts.static_link)) {
+ aot_printerrf (acfg, "The 'direct-extern-calls' option requires the 'llvm' and 'static' options.\n");
+ return 1;
+ }
+
// start dedup
MonoAotState *astate = NULL;
gboolean is_dedup_dummy = FALSE;
@@ -14131,6 +14237,12 @@ mono_aot_is_shared_got_offset (int offset)
return FALSE;
}
+gboolean
+mono_aot_is_externally_callable (MonoMethod *cmethod)
+{
+ return FALSE;
+}
+
int
mono_compile_deferred_assemblies (guint32 opts, const char *aot_options, gpointer **aot_state)
{
diff --git a/mono/mini/aot-compiler.h b/mono/mini/aot-compiler.h
index 2b789a65426..69090e695fa 100644
--- a/mono/mini/aot-compiler.h
+++ b/mono/mini/aot-compiler.h
@@ -17,6 +17,7 @@ MONO_LLVM_INTERNAL guint32 mono_aot_get_got_offset (MonoJumpInfo *ji
MONO_LLVM_INTERNAL char* mono_aot_get_method_name (MonoCompile *cfg);
MONO_LLVM_INTERNAL char* mono_aot_get_mangled_method_name (MonoMethod *method);
MONO_LLVM_INTERNAL gboolean mono_aot_is_direct_callable (MonoJumpInfo *patch_info);
+MONO_LLVM_INTERNAL gboolean mono_aot_is_externally_callable (MonoMethod *cmethod);
MONO_LLVM_INTERNAL void mono_aot_mark_unused_llvm_plt_entry(MonoJumpInfo *patch_info);
MONO_LLVM_INTERNAL char* mono_aot_get_plt_symbol (MonoJumpInfoType type, gconstpointer data);
MONO_LLVM_INTERNAL char* mono_aot_get_direct_call_symbol (MonoJumpInfoType type, gconstpointer data);
diff --git a/mono/mini/aot-runtime.c b/mono/mini/aot-runtime.c
index ca8747e78ab..c4b9484cf63 100644
--- a/mono/mini/aot-runtime.c
+++ b/mono/mini/aot-runtime.c
@@ -61,6 +61,7 @@
#include <mono/utils/mono-digest.h>
#include <mono/utils/mono-threads-coop.h>
#include <mono/utils/bsearch.h>
+#include <mono/utils/mono-tls-inline.h>
#include "mini.h"
#include "seq-points.h"
@@ -70,7 +71,7 @@
#include "aot-runtime.h"
#include "jit-icalls.h"
#include "mini-runtime.h"
-#include "mono/utils/mono-tls-inline.h"
+#include "llvmonly-runtime.h"
#ifndef DISABLE_AOT
@@ -78,9 +79,6 @@
#define ENABLE_AOT_CACHE
#endif
-/* Number of got entries shared between the JIT and LLVM GOT */
-#define N_COMMON_GOT_ENTRIES 10
-
#define ROUND_DOWN(VALUE,SIZE) ((VALUE) & ~((SIZE) - 1))
typedef struct {
@@ -1985,7 +1983,7 @@ get_call_table_entry (void *table, int index, int entry_size)
* Initialize the shared got entries for AMODULE.
*/
static void
-init_amodule_got (MonoAotModule *amodule)
+init_amodule_got (MonoAotModule *amodule, gboolean preinit)
{
MonoJumpInfo *ji;
MonoMemPool *mp;
@@ -2010,7 +2008,8 @@ init_amodule_got (MonoAotModule *amodule)
return;
}
- amodule->got_initialized = GOT_INITIALIZING;
+ if (!preinit)
+ amodule->got_initialized = GOT_INITIALIZING;
mp = mono_mempool_new ();
npatches = amodule->info.nshared_got_entries;
@@ -2024,7 +2023,19 @@ init_amodule_got (MonoAotModule *amodule)
for (i = 0; i < npatches; ++i) {
ji = &patches [i];
- if (ji->type == MONO_PATCH_INFO_GC_CARD_TABLE_ADDR && !mono_gc_is_moving ()) {
+ if (amodule->shared_got [i]) {
+ } else if (ji->type == MONO_PATCH_INFO_AOT_MODULE) {
+ amodule->shared_got [i] = amodule;
+ } else if (preinit) {
+ /*
+ * This is called from init_amodule () during startup, so some things might not
+ * be setup. Initialize just the slots needed to make method initialization work.
+ */
+ if (ji->type == MONO_PATCH_INFO_JIT_ICALL_ID) {
+ if (ji->data.jit_icall_id == MONO_JIT_ICALL_mini_llvm_init_method)
+ amodule->shared_got [i] = (gpointer)mini_llvm_init_method;
+ }
+ } else if (ji->type == MONO_PATCH_INFO_GC_CARD_TABLE_ADDR && !mono_gc_is_moving ()) {
amodule->shared_got [i] = NULL;
} else if (ji->type == MONO_PATCH_INFO_GC_NURSERY_START && !mono_gc_is_moving ()) {
amodule->shared_got [i] = NULL;
@@ -2061,8 +2072,10 @@ init_amodule_got (MonoAotModule *amodule)
mono_mempool_destroy (mp);
- mono_memory_barrier ();
- amodule->got_initialized = GOT_INITIALIZED;
+ if (!preinit) {
+ mono_memory_barrier ();
+ amodule->got_initialized = GOT_INITIALIZED;
+ }
mono_loader_unlock ();
}
@@ -2346,7 +2359,7 @@ load_aot_module (MonoAssemblyLoadContext *alc, MonoAssembly *assembly, gpointer
amodule->trampolines [MONO_AOT_TRAMP_FTNPTR_ARG] = (guint8 *)info->ftnptr_arg_trampolines;
amodule->trampolines [MONO_AOT_TRAMP_UNBOX_ARBITRARY] = (guint8 *)info->unbox_arbitrary_trampolines;
- if (mono_is_corlib_image (assembly->image))
+ if (mono_is_corlib_image (assembly->image) || !strcmp (assembly->aname.name, "mscorlib") || !strcmp (assembly->aname.name, "System.Private.CoreLib"))
mscorlib_aot_module = amodule;
/* Compute method addresses */
@@ -2411,6 +2424,12 @@ load_aot_module (MonoAssemblyLoadContext *alc, MonoAssembly *assembly, gpointer
g_hash_table_insert (aot_modules, assembly, amodule);
mono_aot_unlock ();
+ init_amodule_got (amodule, TRUE);
+
+ if (info->flags & MONO_AOT_FILE_FLAG_WITH_LLVM)
+ /* Directly called methods might make calls through the PLT */
+ init_plt (amodule);
+
if (amodule->jit_code_start)
mono_jit_info_add_aot_module (assembly->image, amodule->jit_code_start, amodule->jit_code_end);
if (amodule->llvm_code_start)
@@ -4141,7 +4160,7 @@ load_method (MonoDomain *domain, MonoAotModule *amodule, MonoImage *image, MonoM
error_init (error);
- init_amodule_got (amodule);
+ init_amodule_got (amodule, FALSE);
if (domain != mono_get_root_domain ())
/* Non shared AOT code can't be used in other appdomains */
@@ -4537,6 +4556,10 @@ init_method (MonoAotModule *amodule, guint32 method_index, MonoMethod *method, M
MonoGenericContext *context;
MonoGenericContext ctx;
+ /* Might be needed if the method is externally called */
+ init_plt (amodule);
+ init_amodule_got (amodule, FALSE);
+
memset (&ctx, 0, sizeof (ctx));
error_init (error);
@@ -5422,7 +5445,7 @@ get_mscorlib_aot_module (void)
MonoAotModule *amodule;
image = mono_defaults.corlib;
- if (image)
+ if (image && image->aot_module)
amodule = image->aot_module;
else
amodule = mscorlib_aot_module;
diff --git a/mono/mini/aot-runtime.h b/mono/mini/aot-runtime.h
index 31940084c2f..e774a6ca26c 100644
--- a/mono/mini/aot-runtime.h
+++ b/mono/mini/aot-runtime.h
@@ -11,7 +11,7 @@
#include "mini.h"
/* Version number of the AOT file format */
-#define MONO_AOT_FILE_VERSION 171
+#define MONO_AOT_FILE_VERSION 172
#define MONO_AOT_TRAMP_PAGE_SIZE 16384
diff --git a/mono/mini/llvmonly-runtime.c b/mono/mini/llvmonly-runtime.c
index c9fbb253589..39fcb2d2888 100644
--- a/mono/mini/llvmonly-runtime.c
+++ b/mono/mini/llvmonly-runtime.c
@@ -790,7 +790,7 @@ init_llvmonly_method (MonoAotModule *amodule, guint32 method_index, MonoClass *i
/* Called from generated code to initialize a method */
void
-mini_llvm_init_method (gpointer aot_module, guint32 method_index)
+mini_llvm_init_method (MonoAotFileInfo *info, gpointer aot_module, guint32 method_index)
{
MonoAotModule *amodule = (MonoAotModule *)aot_module;
@@ -799,7 +799,7 @@ mini_llvm_init_method (gpointer aot_module, guint32 method_index)
/* Same for gshared methods with a this pointer */
void
-mini_llvm_init_gshared_method_this (gpointer aot_module, guint32 method_index, MonoObject *this_obj)
+mini_llvm_init_gshared_method_this (MonoAotFileInfo *info, gpointer aot_module, guint32 method_index, MonoObject *this_obj)
{
MonoAotModule *amodule = (MonoAotModule *)aot_module;
MonoClass *klass;
@@ -813,7 +813,7 @@ mini_llvm_init_gshared_method_this (gpointer aot_module, guint32 method_index, M
/* Same for gshared methods with an mrgctx arg */
void
-mini_llvm_init_gshared_method_mrgctx (gpointer aot_module, guint32 method_index, MonoMethodRuntimeGenericContext *rgctx)
+mini_llvm_init_gshared_method_mrgctx (MonoAotFileInfo *info, gpointer aot_module, guint32 method_index, MonoMethodRuntimeGenericContext *rgctx)
{
MonoAotModule *amodule = (MonoAotModule *)aot_module;
@@ -822,7 +822,7 @@ mini_llvm_init_gshared_method_mrgctx (gpointer aot_module, guint32 method_index,
/* Same for gshared methods with a vtable arg */
void
-mini_llvm_init_gshared_method_vtable (gpointer aot_module, guint32 method_index, MonoVTable *vtable)
+mini_llvm_init_gshared_method_vtable (MonoAotFileInfo *info, gpointer aot_module, guint32 method_index, MonoVTable *vtable)
{
MonoAotModule *amodule = (MonoAotModule *)aot_module;
MonoClass *klass;
diff --git a/mono/mini/llvmonly-runtime.h b/mono/mini/llvmonly-runtime.h
index d6e38cbba7c..55c4ed464e9 100644
--- a/mono/mini/llvmonly-runtime.h
+++ b/mono/mini/llvmonly-runtime.h
@@ -9,6 +9,7 @@
#define __MONO_LLVMONLY_RUNTIME_H__
#include "mini-runtime.h"
+#include "aot-runtime.h"
gpointer mini_llvmonly_load_method (MonoMethod *method, gboolean caller_gsharedvt, gboolean need_unbox, gpointer *out_arg, MonoError *error);
MonoFtnDesc* mini_llvmonly_load_method_ftndesc (MonoMethod *method, gboolean caller_gsharedvt, gboolean need_unbox, MonoError *error);
@@ -27,10 +28,10 @@ G_EXTERN_C MonoFtnDesc* mini_llvmonly_resolve_generic_virtual_iface_call (MonoVT
G_EXTERN_C void mini_llvmonly_init_delegate (MonoDelegate *del);
G_EXTERN_C void mini_llvmonly_init_delegate_virtual (MonoDelegate *del, MonoObject *target, MonoMethod *method);
-G_EXTERN_C void mini_llvm_init_method (gpointer aot_module, guint32 method_index);
-G_EXTERN_C void mini_llvm_init_gshared_method_this (gpointer aot_module, guint32 method_index, MonoObject *this_ins);
-G_EXTERN_C void mini_llvm_init_gshared_method_mrgctx (gpointer aot_module, guint32 method_index, MonoMethodRuntimeGenericContext *rgctx);
-G_EXTERN_C void mini_llvm_init_gshared_method_vtable (gpointer aot_module, guint32 method_index, MonoVTable *vtable);
+G_EXTERN_C void mini_llvm_init_method (MonoAotFileInfo *info, gpointer aot_module, guint32 method_index);
+G_EXTERN_C void mini_llvm_init_gshared_method_this (MonoAotFileInfo *info, gpointer aot_module, guint32 method_index, MonoObject *this_ins);
+G_EXTERN_C void mini_llvm_init_gshared_method_mrgctx (MonoAotFileInfo *info, gpointer aot_module, guint32 method_index, MonoMethodRuntimeGenericContext *rgctx);
+G_EXTERN_C void mini_llvm_init_gshared_method_vtable (MonoAotFileInfo *info, gpointer aot_module, guint32 method_index, MonoVTable *vtable);
G_EXTERN_C void mini_llvmonly_throw_nullref_exception (void);
diff --git a/mono/mini/method-to-ir.c b/mono/mini/method-to-ir.c
index 78a1ba847c4..1f3fc7ca606 100644
--- a/mono/mini/method-to-ir.c
+++ b/mono/mini/method-to-ir.c
@@ -6292,6 +6292,28 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
mono_save_args (cfg, sig, inline_args);
}
+ if (cfg->method == method && cfg->self_init && cfg->compile_aot && !COMPILE_LLVM (cfg)) {
+ MonoMethod *wrapper;
+ MonoInst *args [2];
+ int idx;
+
+ /*
+ * Emit code to initialize this method by calling the init wrapper emitted by LLVM.
+ * This is not efficient right now, but its only used for the methods which fail
+ * LLVM compilation.
+ * FIXME: Optimize this
+ */
+ g_assert (!cfg->gshared);
+ wrapper = mono_marshal_get_aot_init_wrapper (AOT_INIT_METHOD);
+ /* Emit this into the entry bb so it comes before the GC safe point which depends on an inited GOT */
+ cfg->cbb = cfg->bb_entry;
+ idx = mono_aot_get_method_index (cfg->method);
+ EMIT_NEW_ICONST (cfg, args [0], idx);
+ /* Dummy */
+ EMIT_NEW_ICONST (cfg, args [1], 0);
+ mono_emit_method_call (cfg, wrapper, args, NULL);
+ }
+
/* FIRST CODE BLOCK */
NEW_BBLOCK (cfg, tblock);
tblock->cil_code = ip;
diff --git a/mono/mini/mini-llvm.c b/mono/mini/mini-llvm.c
index 00cd31913b9..5f4813a5a10 100644
--- a/mono/mini/mini-llvm.c
+++ b/mono/mini/mini-llvm.c
@@ -95,6 +95,8 @@ typedef struct {
LLVMValueRef unbox_tramp_indexes;
LLVMValueRef unbox_trampolines;
LLVMValueRef gc_poll_cold_wrapper;
+ LLVMValueRef info_var;
+ LLVMTypeRef *info_var_eltypes;
int max_inited_idx, max_method_idx;
gboolean has_jitted_code;
gboolean static_link;
@@ -423,6 +425,7 @@ static LLVMValueRef get_intrins_from_module (LLVMModuleRef lmodule, int id);
static void llvm_jit_finalize_method (EmitContext *ctx);
static void mono_llvm_nonnull_state_update (EmitContext *ctx, LLVMValueRef lcall, MonoMethod *call_method, LLVMValueRef *args, int num_params);
static void mono_llvm_propagate_nonnull_final (GHashTable *all_specializable, MonoLLVMModule *module);
+static void create_aot_info_var (MonoLLVMModule *module);
static inline void
set_failure (EmitContext *ctx, const char *message)
@@ -1783,6 +1786,24 @@ LLVMFunctionType3 (LLVMTypeRef ReturnType,
}
static G_GNUC_UNUSED LLVMTypeRef
+LLVMFunctionType4 (LLVMTypeRef ReturnType,
+ LLVMTypeRef ParamType1,
+ LLVMTypeRef ParamType2,
+ LLVMTypeRef ParamType3,
+ LLVMTypeRef ParamType4,
+ int IsVarArg)
+{
+ LLVMTypeRef param_types [4];
+
+ param_types [0] = ParamType1;
+ param_types [1] = ParamType2;
+ param_types [2] = ParamType3;
+ param_types [3] = ParamType4;
+
+ return LLVMFunctionType (ReturnType, param_types, 4, IsVarArg);
+}
+
+static G_GNUC_UNUSED LLVMTypeRef
LLVMFunctionType5 (LLVMTypeRef ReturnType,
LLVMTypeRef ParamType1,
LLVMTypeRef ParamType2,
@@ -1961,25 +1982,6 @@ typedef struct {
LLVMTypeRef type;
} CallSite;
-static gboolean
-method_is_direct_callable (MonoMethod *method)
-{
- if (method->wrapper_type == MONO_WRAPPER_ALLOC)
- return TRUE;
- if (method->string_ctor)
- return FALSE;
- if (method->wrapper_type)
- return FALSE;
- if ((method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) || (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
- return FALSE;
- /* Can't enable this as the callee might fail llvm compilation */
- /*
- if (!method->is_inflated && (mono_class_get_flags (method->klass) & TYPE_ATTRIBUTE_PUBLIC) && (method->flags & METHOD_ATTRIBUTE_PUBLIC))
- return TRUE;
- */
- return FALSE;
-}
-
static LLVMValueRef
get_callee_llvmonly (EmitContext *ctx, LLVMTypeRef llvm_sig, MonoJumpInfoType type, gconstpointer data)
{
@@ -1997,7 +1999,7 @@ get_callee_llvmonly (EmitContext *ctx, LLVMTypeRef llvm_sig, MonoJumpInfoType ty
}
} else if (type == MONO_PATCH_INFO_METHOD) {
MonoMethod *method = (MonoMethod*)data;
- if (m_class_get_image (method->klass) != ctx->module->assembly->image && method_is_direct_callable (method))
+ if (m_class_get_image (method->klass) != ctx->module->assembly->image && mono_aot_is_externally_callable (method))
callee_name = mono_aot_get_mangled_method_name (method);
}
}
@@ -2107,6 +2109,49 @@ get_callee (EmitContext *ctx, LLVMTypeRef llvm_sig, MonoJumpInfoType type, gcons
if (ctx->llvm_only)
return get_callee_llvmonly (ctx, llvm_sig, type, data);
+ callee_name = NULL;
+ /* Cross-assembly direct calls */
+ if (type == MONO_PATCH_INFO_METHOD) {
+ MonoMethod *cmethod = (MonoMethod*)data;
+
+ if (m_class_get_image (cmethod->klass) != ctx->module->assembly->image) {
+ MonoJumpInfo tmp_ji;
+
+ memset (&tmp_ji, 0, sizeof (MonoJumpInfo));
+ tmp_ji.type = type;
+ tmp_ji.data.target = data;
+ if (mono_aot_is_direct_callable (&tmp_ji)) {
+ /*
+ * This will add a reference to cmethod's image so it will
+ * be loaded when the current AOT image is loaded, so
+ * the GOT slots used by the init method code are initialized.
+ */
+ tmp_ji.type = MONO_PATCH_INFO_IMAGE;
+ tmp_ji.data.image = m_class_get_image (cmethod->klass);
+ ji = mono_aot_patch_info_dup (&tmp_ji);
+ mono_aot_get_got_offset (ji);
+
+ callee_name = mono_aot_get_mangled_method_name (cmethod);
+
+ callee = (LLVMValueRef)g_hash_table_lookup (ctx->module->direct_callables, callee_name);
+ if (!callee) {
+ callee = LLVMAddFunction (ctx->lmodule, callee_name, llvm_sig);
+
+ LLVMSetLinkage (callee, LLVMExternalLinkage);
+
+ g_hash_table_insert (ctx->module->direct_callables, callee_name, callee);
+ } else {
+ /* LLVMTypeRef's are uniqued */
+ if (LLVMGetElementType (LLVMTypeOf (callee)) != llvm_sig)
+ callee = LLVMConstBitCast (callee, LLVMPointerType (llvm_sig, 0));
+
+ g_free (callee_name);
+ }
+ return callee;
+ }
+ }
+ }
+
callee_name = mono_aot_get_plt_symbol (type, data);
if (!callee_name)
return NULL;
@@ -3009,21 +3054,21 @@ static LLVMValueRef
emit_init_icall_wrapper (MonoLLVMModule *module, MonoAotInitSubtype subtype)
{
LLVMModuleRef lmodule = module->lmodule;
- LLVMValueRef func, indexes [2], got_entry_addr, args [16], callee;
- LLVMBasicBlockRef entry_bb;
+ LLVMValueRef func, indexes [2], got_entry_addr, args [16], callee, inited_var, cmp;
+ LLVMBasicBlockRef entry_bb, inited_bb, notinited_bb;
LLVMBuilderRef builder;
LLVMTypeRef sig;
MonoJumpInfo *ji;
int got_offset;
const char *wrapper_name = mono_marshal_get_aot_init_wrapper_name (subtype);
- char *name = g_strdup_printf ("%s%s", module->global_prefix, wrapper_name);
+ char *name = g_strdup_printf ("%s_%s", module->global_prefix, wrapper_name);
MonoJitICallId icall_id = MONO_JIT_ICALL_ZeroIsReserved;
switch (subtype) {
case AOT_INIT_METHOD:
icall_id = MONO_JIT_ICALL_mini_llvm_init_method;
func = LLVMAddFunction (lmodule, name, LLVMFunctionType1 (LLVMVoidType (), LLVMInt32Type (), FALSE));
- sig = LLVMFunctionType2 (LLVMVoidType (), IntPtrType (), LLVMInt32Type (), FALSE);
+ sig = LLVMFunctionType3 (LLVMVoidType (), IntPtrType (), IntPtrType (), LLVMInt32Type (), FALSE);
break;
case AOT_INIT_METHOD_GSHARED_MRGCTX:
icall_id = MONO_JIT_ICALL_mini_llvm_init_gshared_method_mrgctx; // Deliberate fall-through
@@ -3032,12 +3077,12 @@ emit_init_icall_wrapper (MonoLLVMModule *module, MonoAotInitSubtype subtype)
if (!icall_id)
icall_id = MONO_JIT_ICALL_mini_llvm_init_gshared_method_vtable;
func = LLVMAddFunction (lmodule, name, LLVMFunctionType2 (LLVMVoidType (), LLVMInt32Type (), IntPtrType (), FALSE));
- sig = LLVMFunctionType3 (LLVMVoidType (), IntPtrType (), LLVMInt32Type (), IntPtrType (), FALSE);
+ sig = LLVMFunctionType4 (LLVMVoidType (), IntPtrType (), IntPtrType (), LLVMInt32Type (), IntPtrType (), FALSE);
break;
case AOT_INIT_METHOD_GSHARED_THIS:
icall_id = MONO_JIT_ICALL_mini_llvm_init_gshared_method_this;
func = LLVMAddFunction (lmodule, name, LLVMFunctionType2 (LLVMVoidType (), LLVMInt32Type (), ObjRefType (), FALSE));
- sig = LLVMFunctionType3 (LLVMVoidType (), IntPtrType (), LLVMInt32Type (), ObjRefType (), FALSE);
+ sig = LLVMFunctionType4 (LLVMVoidType (), IntPtrType (), IntPtrType (), LLVMInt32Type (), ObjRefType (), FALSE);
break;
default:
g_assert_not_reached ();
@@ -3051,9 +3096,24 @@ emit_init_icall_wrapper (MonoLLVMModule *module, MonoAotInitSubtype subtype)
set_cold_cconv (func);
entry_bb = LLVMAppendBasicBlock (func, "ENTRY");
+
builder = LLVMCreateBuilder ();
LLVMPositionBuilderAtEnd (builder, entry_bb);
+ /* Check for is_inited here as well, since this can be called from JITted code which might not check it */
+ indexes [0] = LLVMConstInt (LLVMInt32Type (), 0, FALSE);
+ indexes [1] = LLVMGetParam (func, 0);
+ inited_var = LLVMBuildLoad (builder, LLVMBuildGEP (builder, module->inited_var, indexes, 2, ""), "is_inited");
+
+ cmp = LLVMBuildICmp (builder, LLVMIntEQ, inited_var, LLVMConstInt (LLVMTypeOf (inited_var), 0, FALSE), "");
+
+ inited_bb = LLVMAppendBasicBlock (func, "INITED");
+ notinited_bb = LLVMAppendBasicBlock (func, "NOT_INITED");
+
+ LLVMBuildCondBr (builder, cmp, notinited_bb, inited_bb);
+
+ LLVMPositionBuilderAtEnd (builder, notinited_bb);
+
/* get_aotconst */
ji = g_new0 (MonoJumpInfo, 1);
ji->type = MONO_PATCH_INFO_AOT_MODULE;
@@ -3063,10 +3123,11 @@ emit_init_icall_wrapper (MonoLLVMModule *module, MonoAotInitSubtype subtype)
indexes [0] = LLVMConstInt (LLVMInt32Type (), 0, FALSE);
indexes [1] = LLVMConstInt (LLVMInt32Type (), got_offset, FALSE);
got_entry_addr = LLVMBuildGEP (builder, module->got_var, indexes, 2, "");
- args [0] = LLVMBuildPtrToInt (builder, LLVMBuildLoad (builder, got_entry_addr, ""), IntPtrType (), "");
- args [1] = LLVMGetParam (func, 0);
+ args [0] = LLVMBuildPtrToInt (builder, module->info_var, IntPtrType (), "");
+ args [1] = LLVMBuildPtrToInt (builder, LLVMBuildLoad (builder, got_entry_addr, ""), IntPtrType (), "");
+ args [2] = LLVMGetParam (func, 0);
if (subtype)
- args [2] = LLVMGetParam (func, 1);
+ args [3] = LLVMGetParam (func, 1);
ji = g_new0 (MonoJumpInfo, 1);
ji->type = MONO_PATCH_INFO_JIT_ICALL_ID;
@@ -3086,6 +3147,9 @@ emit_init_icall_wrapper (MonoLLVMModule *module, MonoAotInitSubtype subtype)
indexes [1] = LLVMGetParam (func, 0);
LLVMBuildStore (builder, LLVMConstInt (LLVMInt8Type (), 1, FALSE), LLVMBuildGEP (builder, module->inited_var, indexes, 2, ""));
+ LLVMBuildBr (builder, inited_bb);
+
+ LLVMPositionBuilderAtEnd (builder, inited_bb);
LLVMBuildRetVoid (builder);
LLVMVerifyFunction(func, LLVMAbortProcessAction);
@@ -8281,14 +8345,6 @@ free_ctx (EmitContext *ctx)
g_free (ctx);
}
-static gboolean
-is_externally_callable (EmitContext *ctx, MonoMethod *method)
-{
- if (ctx->module->llvm_only && ctx->module->static_link && (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method_is_direct_callable (method)))
- return TRUE;
- return FALSE;
-}
-
/*
* mono_llvm_emit_method:
*
@@ -8343,7 +8399,7 @@ mono_llvm_emit_method (MonoCompile *cfg)
if (cfg->compile_aot) {
ctx->module = &aot_module;
- if (is_externally_callable (ctx, cfg->method))
+ if (mono_aot_is_externally_callable (cfg->method))
method_name = mono_aot_get_mangled_method_name (cfg->method);
else
method_name = mono_aot_get_method_name (cfg);
@@ -8477,7 +8533,7 @@ emit_method_inner (EmitContext *ctx)
ctx->module->max_method_idx = MAX (ctx->module->max_method_idx, cfg->method_index);
const char *init_name = mono_marshal_get_aot_init_wrapper_name (info->d.aot_init.subtype);
- ctx->method_name = g_strdup_printf ("%s%s", ctx->module->global_prefix, init_name);
+ ctx->method_name = g_strdup_printf ("%s_%s", ctx->module->global_prefix, init_name);
ctx->cfg->asm_symbol = g_strdup (ctx->method_name);
if (!cfg->llvm_only && ctx->module->external_symbols) {
@@ -8563,7 +8619,7 @@ emit_method_inner (EmitContext *ctx)
mono_llvm_add_func_attr_nv (method, "no-frame-pointer-elim", "true");
if (cfg->compile_aot) {
- if (is_externally_callable (ctx, cfg->method)) {
+ if (mono_aot_is_externally_callable (cfg->method)) {
LLVMSetLinkage (method, LLVMExternalLinkage);
} else {
LLVMSetLinkage (method, LLVMInternalLinkage);
@@ -9977,6 +10033,7 @@ mono_llvm_create_aot_module (MonoAssembly *assembly, const char *global_prefix,
module->inited_var = LLVMAddGlobal (aot_module.lmodule, inited_type, "mono_inited_tmp");
LLVMSetInitializer (module->inited_var, LLVMConstNull (inited_type));
+ create_aot_info_var (module);
emit_gc_safepoint_poll (module, module->lmodule, NULL);
@@ -10178,22 +10235,19 @@ AddJitGlobal (MonoLLVMModule *module, LLVMTypeRef type, const char *name)
g_free (s);
return v;
}
+#define FILE_INFO_NFIELDS (2 + MONO_AOT_FILE_INFO_NUM_SYMBOLS + 22 + 5)
static void
-emit_aot_file_info (MonoLLVMModule *module)
+create_aot_info_var (MonoLLVMModule *module)
{
LLVMTypeRef file_info_type;
- LLVMTypeRef *eltypes, eltype;
+ LLVMTypeRef *eltypes;
LLVMValueRef info_var;
- LLVMValueRef *fields;
int i, nfields, tindex;
- MonoAotFileInfo *info;
LLVMModuleRef lmodule = module->lmodule;
- info = &module->aot_info;
-
/* Create an LLVM type to represent MonoAotFileInfo */
- nfields = 2 + MONO_AOT_FILE_INFO_NUM_SYMBOLS + 22 + 5;
+ nfields = FILE_INFO_NFIELDS;
eltypes = g_new (LLVMTypeRef, nfields);
tindex = 0;
eltypes [tindex ++] = LLVMInt32Type ();
@@ -10214,6 +10268,26 @@ emit_aot_file_info (MonoLLVMModule *module)
LLVMStructSetBody (file_info_type, eltypes, nfields, FALSE);
info_var = LLVMAddGlobal (lmodule, file_info_type, "mono_aot_file_info");
+
+ module->info_var = info_var;
+ module->info_var_eltypes = eltypes;
+}
+
+static void
+emit_aot_file_info (MonoLLVMModule *module)
+{
+ LLVMTypeRef *eltypes, eltype;
+ LLVMValueRef info_var;
+ LLVMValueRef *fields;
+ int i, nfields, tindex;
+ MonoAotFileInfo *info;
+ LLVMModuleRef lmodule = module->lmodule;
+
+ info = &module->aot_info;
+ info_var = module->info_var;
+ eltypes = module->info_var_eltypes;
+ nfields = FILE_INFO_NFIELDS;
+
if (module->static_link) {
LLVMSetVisibility (info_var, LLVMHiddenVisibility);
LLVMSetLinkage (info_var, LLVMInternalLinkage);
@@ -10362,7 +10436,7 @@ emit_aot_file_info (MonoLLVMModule *module)
fields [tindex ++] = llvm_array_from_bytes (info->aotid, 16);
g_assert (tindex == nfields);
- LLVMSetInitializer (info_var, LLVMConstNamedStruct (file_info_type, fields, nfields));
+ LLVMSetInitializer (info_var, LLVMConstNamedStruct (LLVMGetElementType (LLVMTypeOf (info_var)), fields, nfields));
if (module->static_link) {
char *s, *p;
diff --git a/mono/mini/mini-runtime.c b/mono/mini/mini-runtime.c
index 4da03218ad6..6b4d396c9d9 100644
--- a/mono/mini/mini-runtime.c
+++ b/mono/mini/mini-runtime.c
@@ -4646,10 +4646,10 @@ register_icalls (void)
register_dyn_icall (mini_get_dbg_callbacks ()->user_break, mono_debugger_agent_user_break, mono_icall_sig_void, FALSE);
- register_icall (mini_llvm_init_method, mono_icall_sig_void_ptr_int, TRUE);
- register_icall (mini_llvm_init_gshared_method_this, mono_icall_sig_void_ptr_int_object, TRUE);
- register_icall (mini_llvm_init_gshared_method_mrgctx, mono_icall_sig_void_ptr_int_ptr, TRUE);
- register_icall (mini_llvm_init_gshared_method_vtable, mono_icall_sig_void_ptr_int_ptr, TRUE);
+ register_icall (mini_llvm_init_method, mono_icall_sig_void_ptr_ptr_int, TRUE);
+ register_icall (mini_llvm_init_gshared_method_this, mono_icall_sig_void_ptr_ptr_int_object, TRUE);
+ register_icall (mini_llvm_init_gshared_method_mrgctx, mono_icall_sig_void_ptr_ptr_int_ptr, TRUE);
+ register_icall (mini_llvm_init_gshared_method_vtable, mono_icall_sig_void_ptr_ptr_int_ptr, TRUE);
register_icall_no_wrapper (mini_llvmonly_resolve_iface_call_gsharedvt, mono_icall_sig_ptr_object_int_ptr_ptr);
register_icall_no_wrapper (mini_llvmonly_resolve_vcall_gsharedvt, mono_icall_sig_ptr_object_int_ptr_ptr);
diff --git a/mono/mini/mini.c b/mono/mini/mini.c
index 75c3eef0312..cb6a8f7737f 100644
--- a/mono/mini/mini.c
+++ b/mono/mini/mini.c
@@ -2844,7 +2844,6 @@ insert_safepoint (MonoCompile *cfg, MonoBasicBlock *bblock)
} else if (bblock == cfg->bb_entry) {
mono_bblock_insert_after_ins (bblock, bblock->last_ins, poll_addr);
mono_bblock_insert_after_ins (bblock, poll_addr, ins);
-
} else {
mono_bblock_insert_before_ins (bblock, NULL, poll_addr);
mono_bblock_insert_after_ins (bblock, poll_addr, ins);
@@ -3177,6 +3176,7 @@ mini_method_compile (MonoMethod *method, guint32 opts, MonoDomain *domain, JitFl
cfg->llvm_only = (flags & JIT_FLAG_LLVM_ONLY) != 0;
cfg->interp = (flags & JIT_FLAG_INTERP) != 0;
cfg->use_current_cpu = (flags & JIT_FLAG_USE_CURRENT_CPU) != 0;
+ cfg->self_init = (flags & JIT_FLAG_SELF_INIT) != 0;
cfg->backend = current_backend;
if (cfg->method->wrapper_type == MONO_WRAPPER_ALLOC) {
diff --git a/mono/mini/mini.h b/mono/mini/mini.h
index 41f50916a5e..44e9e099ee6 100644
--- a/mono/mini/mini.h
+++ b/mono/mini/mini.h
@@ -1228,6 +1228,8 @@ typedef enum {
JIT_FLAG_INTERP = (1 << 9),
/* Allow AOT to use all current CPU instructions */
JIT_FLAG_USE_CURRENT_CPU = (1 << 10),
+ /* Generate code to self-init the method for AOT */
+ JIT_FLAG_SELF_INIT = (1 << 11)
} JitFlags;
/* Bit-fields in the MonoBasicBlock.region */
@@ -1443,6 +1445,7 @@ typedef struct {
guint llvm_only : 1;
guint interp : 1;
guint use_current_cpu : 1;
+ guint self_init : 1;
guint domainvar_inited : 1;
guint8 uses_simd_intrinsics;
int r4_stack_type;