Skip to content

Commit a297498

Browse files
committed
[mono][aot] Emit a list of exported methods into the AOT image and load them when the image is loaded.
If there is a runtime attach function specified, these methods can call into the runtime before its initialized. In order for this to work, the runtime attach function needs to load all the AOT images containing such methods, and load_aot_module () will load and initialize these methods using the newly emitted table.
1 parent 3e05fa1 commit a297498

File tree

4 files changed

+55
-2
lines changed

4 files changed

+55
-2
lines changed

src/mono/mono/mini/aot-compiler.c

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -403,6 +403,9 @@ typedef struct MonoAotCompile {
403403
GHashTable *gshared_instances;
404404
/* Hash of gshared methods where specific instances are preferred */
405405
GHashTable *prefer_instances;
406+
GPtrArray *exported_methods;
407+
guint32 n_exported_methods;
408+
guint32 exported_methods_offset;
406409
#ifdef EMIT_WIN32_UNWIND_INFO
407410
GList *unwind_info_section_cache;
408411
#endif
@@ -5303,6 +5306,8 @@ MONO_RESTORE_WARNING
53035306
export_name = (char *)g_malloc (slen + 1);
53045307
sprintf (export_name, "%s%s", acfg->user_symbol_prefix, named);
53055308
export_name [slen] = 0;
5309+
5310+
g_ptr_array_add (acfg->exported_methods, method);
53065311
}
53075312
}
53085313
mono_reflection_free_custom_attr_data_args_noalloc (decoded_args);
@@ -10874,6 +10879,24 @@ emit_method_info_table (MonoAotCompile *acfg)
1087410879
method_flags [acfg->cfgs [i]->method_index] = GUINT32_TO_UINT8 (acfg->cfgs [i]->aot_method_flags);
1087510880
}
1087610881
emit_aot_data (acfg, MONO_AOT_TABLE_METHOD_FLAGS_TABLE, "method_flags_table", method_flags, acfg->nmethods);
10882+
10883+
/*
10884+
* If there is a runtime init callback, emit a table of exported methods.
10885+
* These methods can be called before the runtime is initialized, so they need to
10886+
* be inited when their AOT image is loaded.
10887+
*/
10888+
if (acfg->aot_opts.runtime_init_callback) {
10889+
acfg->n_exported_methods = acfg->exported_methods->len;
10890+
if (acfg->exported_methods->len) {
10891+
guint32 *arr = g_new0 (guint32, acfg->exported_methods->len);
10892+
for (i = 0; i < acfg->exported_methods->len; ++i) {
10893+
MonoMethod *m = (MonoMethod*)g_ptr_array_index (acfg->exported_methods, i);
10894+
arr [i] = mono_method_get_token (m);
10895+
}
10896+
acfg->exported_methods_offset = add_to_blob_aligned (acfg, (guint8*)arr, acfg->exported_methods->len * sizeof (guint32), 4);
10897+
g_free (arr);
10898+
}
10899+
}
1087710900
}
1087810901

1087910902
#endif /* #if !defined(DISABLE_AOT) && !defined(DISABLE_JIT) */
@@ -11860,6 +11883,9 @@ init_aot_file_info (MonoAotCompile *acfg, MonoAotFileInfo *info)
1186011883
info->simd_opts = acfg->simd_opts;
1186111884
info->gc_name_index = acfg->gc_name_offset;
1186211885
info->datafile_size = acfg->datafile_offset;
11886+
info->n_exported_methods = acfg->n_exported_methods;
11887+
info->exported_methods = acfg->exported_methods_offset;
11888+
1186311889
for (i = 0; i < MONO_AOT_TABLE_NUM; ++i)
1186411890
info->table_offsets [i] = acfg->table_offsets [i];
1186511891
for (i = 0; i < MONO_AOT_TRAMP_NUM; ++i)
@@ -12029,6 +12055,8 @@ emit_aot_file_info (MonoAotCompile *acfg, MonoAotFileInfo *info)
1202912055
emit_int32 (acfg, info->datafile_size);
1203012056
emit_int32 (acfg, 0);
1203112057
emit_int32 (acfg, 0);
12058+
emit_int32 (acfg, info->n_exported_methods);
12059+
emit_int32 (acfg, info->exported_methods);
1203212060

1203312061
for (i = 0; i < MONO_AOT_TABLE_NUM; ++i)
1203412062
emit_int32 (acfg, info->table_offsets [i]);
@@ -13867,6 +13895,7 @@ acfg_create (MonoAssembly *ass, guint32 jit_opts)
1386713895
acfg->profile_methods = g_hash_table_new (NULL, NULL);
1386813896
acfg->gshared_instances = g_hash_table_new (NULL, NULL);
1386913897
acfg->prefer_instances = g_hash_table_new (NULL, NULL);
13898+
acfg->exported_methods = g_ptr_array_new ();
1387013899
mono_os_mutex_init_recursive (&acfg->mutex);
1387113900

1387213901
init_got_info (&acfg->got_info);
@@ -13947,6 +13976,7 @@ acfg_free (MonoAotCompile *acfg)
1394713976
g_ptr_array_free (acfg->image_table, TRUE);
1394813977
g_ptr_array_free (acfg->globals, TRUE);
1394913978
g_ptr_array_free (acfg->unwind_ops, TRUE);
13979+
g_ptr_array_free (acfg->exported_methods, TRUE);
1395013980
g_hash_table_destroy (acfg->method_indexes);
1395113981
g_hash_table_destroy (acfg->method_depth);
1395213982
g_hash_table_destroy (acfg->plt_offset_to_entry);

src/mono/mono/mini/aot-runtime.c

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2346,6 +2346,25 @@ load_aot_module (MonoAssemblyLoadContext *alc, MonoAssembly *assembly, gpointer
23462346
} else {
23472347
mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_AOT, "AOT: image '%s' found.", found_aot_name);
23482348
}
2349+
2350+
/* Initialize exported methods since they can be called without being loaded */
2351+
if (!amodule->out_of_date && info->n_exported_methods) {
2352+
guint32 *exported = (guint32*)(amodule->blob + info->exported_methods);
2353+
2354+
for (guint32 i = 0; i < info->n_exported_methods; ++i) {
2355+
ERROR_DECL (load_error);
2356+
guint32 token = exported [i];
2357+
MonoMethod *m = mono_get_method_checked (assembly->image, token, NULL, NULL, load_error);
2358+
mono_error_cleanup (load_error); /* FIXME don't swallow the error */
2359+
error_init (load_error);
2360+
if (m) {
2361+
mono_class_init_internal (m->klass);
2362+
mono_aot_get_method (m, load_error);
2363+
mono_error_cleanup (load_error); /* FIXME don't swallow the error */
2364+
error_init (load_error);
2365+
}
2366+
}
2367+
}
23492368
}
23502369

23512370
/*

src/mono/mono/mini/aot-runtime.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
#include "mini.h"
1212

1313
/* Version number of the AOT file format */
14-
#define MONO_AOT_FILE_VERSION 184
14+
#define MONO_AOT_FILE_VERSION 185
1515

1616
#define MONO_AOT_TRAMP_PAGE_SIZE 16384
1717

@@ -221,6 +221,8 @@ typedef struct MonoAotFileInfo
221221
guint32 llvm_unbox_tramp_num;
222222
/* Size of entries in llvm_unbox_tramp_indexes (2/4) */
223223
guint32 llvm_unbox_tramp_elemsize;
224+
guint32 n_exported_methods;
225+
guint32 exported_methods;
224226

225227
/* Arrays */
226228
/* Offsets for tables inside the data file if MONO_AOT_FILE_FLAG_SEPARATE_DATA is set */

src/mono/mono/mini/mini-llvm.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13405,7 +13405,7 @@ AddJitGlobal (MonoLLVMModule *module, LLVMTypeRef type, const char *name)
1340513405
return v;
1340613406
}
1340713407
#define FILE_INFO_NUM_HEADER_FIELDS 2
13408-
#define FILE_INFO_NUM_SCALAR_FIELDS 23
13408+
#define FILE_INFO_NUM_SCALAR_FIELDS 25
1340913409
#define FILE_INFO_NUM_ARRAY_FIELDS 5
1341013410
#define FILE_INFO_NUM_AOTID_FIELDS 1
1341113411
#define FILE_INFO_NFIELDS (FILE_INFO_NUM_HEADER_FIELDS + MONO_AOT_FILE_INFO_NUM_SYMBOLS + FILE_INFO_NUM_SCALAR_FIELDS + FILE_INFO_NUM_ARRAY_FIELDS + FILE_INFO_NUM_AOTID_FIELDS)
@@ -13603,6 +13603,8 @@ emit_aot_file_info (MonoLLVMModule *module)
1360313603
fields [tindex ++] = const_int32 (info->datafile_size);
1360413604
fields [tindex ++] = const_int32 (module->unbox_tramp_num);
1360513605
fields [tindex ++] = const_int32 (module->unbox_tramp_elemsize);
13606+
fields [tindex ++] = const_int32 (info->n_exported_methods);
13607+
fields [tindex ++] = const_int32 (info->exported_methods);
1360613608
/* Arrays */
1360713609
fields [tindex ++] = llvm_array_from_uints (LLVMInt32Type (), info->table_offsets, MONO_AOT_TABLE_NUM);
1360813610
fields [tindex ++] = llvm_array_from_uints (LLVMInt32Type (), info->num_trampolines, MONO_AOT_TRAMP_NUM);

0 commit comments

Comments
 (0)