@@ -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 );
0 commit comments