@@ -217,7 +217,7 @@ typedef struct MonoAotOptions {
217217 gboolean use_trampolines_page ;
218218 gboolean no_instances ;
219219 // We are collecting inflated methods and emitting non-inflated
220- gboolean dedup ;
220+ gboolean dedup_skip ;
221221 // The name of the assembly for which the AOT module is going to have all deduped methods moved to.
222222 // When set, we are emitting inflated methods only
223223 char * dedup_include ;
@@ -295,6 +295,13 @@ typedef struct _UnwindInfoSectionCacheItem {
295295} UnwindInfoSectionCacheItem ;
296296#endif
297297
298+ typedef enum {
299+ DEDUP_NONE , // dedup is turned off
300+ DEDUP_SKIP , // dedup is on, dedup assembly is not provided
301+ DEDUP_COLLECT , // dedup is on, this assembly is not the dedup image, so just collect the methods
302+ DEDUP_EMIT // dedup is on, this assembly is the dedup image, emit collected methods
303+ } DedupPhase ;
304+
298305typedef struct MonoAotCompile {
299306 MonoImage * image ;
300307 GPtrArray * methods ;
@@ -381,7 +388,6 @@ typedef struct MonoAotCompile {
381388 gboolean llvm ;
382389 gboolean has_jitted_code ;
383390 gboolean is_full_aot ;
384- gboolean dedup_collect_only ;
385391 MonoAotFileFlags flags ;
386392 MonoDynamicStream blob ;
387393 gboolean blob_closed ;
@@ -416,8 +422,8 @@ typedef struct MonoAotCompile {
416422 FILE * compiled_methods_outfile ;
417423 int datafile_offset ;
418424 int gc_name_offset ;
419- // In this mode, we are emitting dedupable methods that we encounter
420- gboolean dedup_emit_mode ;
425+
426+ DedupPhase dedup_phase ;
421427} MonoAotCompile ;
422428
423429typedef struct {
@@ -519,6 +525,12 @@ mono_aot_mode_is_hybrid (MonoAotOptions *opts)
519525 return opts -> mode == MONO_AOT_MODE_HYBRID ;
520526}
521527
528+ static void
529+ dedup_change_phase (MonoAotCompile * acfg , int next_phase )
530+ {
531+ acfg -> dedup_phase = next_phase ;
532+ }
533+
522534static void
523535aot_printf (MonoAotCompile * acfg , const gchar * format , ...)
524536{
@@ -4300,6 +4312,22 @@ get_method_index (MonoAotCompile *acfg, MonoMethod *method)
43004312 return index - 1 ;
43014313}
43024314
4315+ static gboolean
4316+ collect_dedup_method (MonoAotCompile * acfg , MonoMethod * method )
4317+ {
4318+ // Check if the dedup is enabled, and if the current method can be deduplicated
4319+ if ((acfg -> dedup_phase == DEDUP_SKIP || acfg -> dedup_phase == DEDUP_COLLECT ) && mono_aot_can_dedup (method )) {
4320+ if (acfg -> dedup_phase == DEDUP_SKIP )
4321+ return TRUE;
4322+ // Remember for later
4323+ if (acfg -> dedup_phase == DEDUP_COLLECT && !g_hash_table_lookup (dedup_methods , method ))
4324+ g_hash_table_insert (dedup_methods , method , method );
4325+ }
4326+ return FALSE;
4327+ }
4328+
4329+
4330+
43034331static int
43044332add_method_full (MonoAotCompile * acfg , MonoMethod * method , gboolean extra , int depth )
43054333{
@@ -4389,16 +4417,8 @@ add_extra_method_full (MonoAotCompile *acfg, MonoMethod *method, gboolean prefer
43894417 mono_error_assert_ok (error );
43904418 }
43914419
4392- if ((acfg -> aot_opts .dedup || acfg -> aot_opts .dedup_include ) && mono_aot_can_dedup (method )) {
4393- if (acfg -> aot_opts .dedup ) {
4394- /* Don't emit instances */
4395- return ;
4396- } else if (!acfg -> dedup_emit_mode ) {
4397- /* Remember for later */
4398- if (!g_hash_table_lookup (dedup_methods , method ))
4399- g_hash_table_insert (dedup_methods , method , method );
4400- }
4401- }
4420+ if (collect_dedup_method (acfg , method ))
4421+ return ;
44024422
44034423 if (acfg -> aot_opts .log_generics )
44044424 aot_printf (acfg , "%*sAdding method %s.\n" , depth , "" , mono_method_get_full_name (method ));
@@ -6390,7 +6410,7 @@ is_direct_callable (MonoAotCompile *acfg, MonoMethod *method, MonoJumpInfo *patc
63906410 if (callee_cfg ) {
63916411 gboolean direct_callable = TRUE;
63926412
6393- if (direct_callable && ( acfg -> aot_opts . dedup || acfg -> aot_opts . dedup_include ) && mono_aot_can_dedup (patch_info -> data .method ))
6413+ if (direct_callable && acfg -> dedup_phase != DEDUP_NONE && mono_aot_can_dedup (patch_info -> data .method ))
63946414 direct_callable = FALSE;
63956415
63966416 if (direct_callable && !acfg -> llvm && !(!callee_cfg -> has_got_slots && mono_class_is_before_field_init (callee_cfg -> method -> klass )))
@@ -8794,7 +8814,7 @@ mono_aot_parse_options (const char *aot_options, MonoAotOptions *opts)
87948814 } else if (str_begins_with (arg , "internal-logfile=" )) {
87958815 opts -> logfile = g_strdup (arg + strlen ("internal-logfile=" ));
87968816 } else if (str_begins_with (arg , "dedup-skip" )) {
8797- opts -> dedup = TRUE;
8817+ opts -> dedup_skip = TRUE;
87988818 } else if (str_begins_with (arg , "dedup-include=" )) {
87998819 opts -> dedup_include = g_strdup (arg + strlen ("dedup-include=" ));
88008820 } else if (str_begins_with (arg , "mtriple=" )) {
@@ -14061,6 +14081,7 @@ acfg_create (MonoAssembly *ass, guint32 jit_opts)
1406114081 acfg -> gshared_instances = g_hash_table_new (NULL , NULL );
1406214082 acfg -> prefer_instances = g_hash_table_new (NULL , NULL );
1406314083 acfg -> exported_methods = g_ptr_array_new ();
14084+ acfg -> dedup_phase = DEDUP_NONE ;
1406414085 mono_os_mutex_init_recursive (& acfg -> mutex );
1406514086
1406614087 init_got_info (& acfg -> got_info );
@@ -14707,15 +14728,20 @@ aot_assembly (MonoAssembly *ass, guint32 jit_opts, MonoAotOptions *aot_options)
1470714728
1470814729 acfg = acfg_create (ass , jit_opts );
1470914730 memcpy (& acfg -> aot_opts , aot_options , sizeof (MonoAotOptions ));
14710-
14711- if (acfg -> aot_opts .dedup_include && ass != dedup_assembly )
14712- acfg -> dedup_collect_only = TRUE;
14731+ if (acfg -> aot_opts .dedup_skip || acfg -> aot_opts .dedup_include ) {
14732+ if (acfg -> aot_opts .dedup_skip )
14733+ dedup_change_phase (acfg , DEDUP_SKIP );
14734+ else if (acfg -> aot_opts .dedup_include && ass != dedup_assembly )
14735+ dedup_change_phase (acfg , DEDUP_COLLECT );
14736+ else
14737+ dedup_change_phase (acfg , DEDUP_EMIT );
14738+ }
1471314739
1471414740 if (acfg -> aot_opts .logfile ) {
1471514741 acfg -> logfile = fopen (acfg -> aot_opts .logfile , "a+" );
1471614742 }
1471714743
14718- if (acfg -> aot_opts .compiled_methods_outfile && ! acfg -> dedup_collect_only ) {
14744+ if (acfg -> aot_opts .compiled_methods_outfile && acfg -> dedup_phase != DEDUP_COLLECT ) {
1471914745 acfg -> compiled_methods_outfile = fopen (acfg -> aot_opts .compiled_methods_outfile , "w+" );
1472014746 if (!acfg -> compiled_methods_outfile )
1472114747 aot_printerrf (acfg , "Unable to open compiled-methods-outfile specified file %s\n" , acfg -> aot_opts .compiled_methods_outfile );
@@ -14766,14 +14792,14 @@ aot_assembly (MonoAssembly *ass, guint32 jit_opts, MonoAotOptions *aot_options)
1476614792 if (acfg -> jit_opts & MONO_OPT_GSHAREDVT )
1476714793 mono_set_generic_sharing_vt_supported (TRUE);
1476814794
14769- if (! acfg -> dedup_collect_only )
14795+ if (acfg -> dedup_phase != DEDUP_COLLECT )
1477014796 aot_printf (acfg , "Mono Ahead of Time compiler - compiling assembly %s\n" , image -> name );
1477114797
1477214798 if (!acfg -> aot_opts .deterministic )
1477314799 generate_aotid ((guint8 * ) & acfg -> image -> aotid );
1477414800
1477514801 char * aotid = mono_guid_to_string (acfg -> image -> aotid );
14776- if (! acfg -> dedup_collect_only && !acfg -> aot_opts .deterministic )
14802+ if (acfg -> dedup_phase != DEDUP_COLLECT && !acfg -> aot_opts .deterministic )
1477714803 aot_printf (acfg , "AOTID %s\n" , aotid );
1477814804 g_free (aotid );
1477914805
@@ -14879,9 +14905,9 @@ aot_assembly (MonoAssembly *ass, guint32 jit_opts, MonoAotOptions *aot_options)
1487914905 if (mini_safepoints_enabled ())
1488014906 acfg -> flags = (MonoAotFileFlags )(acfg -> flags | MONO_AOT_FILE_FLAG_SAFEPOINTS );
1488114907
14882- // The methods in dedup-emit amodules must be available on runtime startup
14908+ // The methods in dedup AOT module must be available on runtime startup
1488314909 // Note: Only one such amodule can have this attribute
14884- if (ass == dedup_assembly )
14910+ if (acfg -> dedup_phase == DEDUP_EMIT )
1488514911 acfg -> flags = (MonoAotFileFlags )(acfg -> flags | MONO_AOT_FILE_FLAG_EAGER_LOAD );
1488614912
1488714913 if (acfg -> aot_opts .instances_logfile_path ) {
@@ -14973,16 +14999,14 @@ aot_assembly (MonoAssembly *ass, guint32 jit_opts, MonoAotOptions *aot_options)
1497314999 return 1 ;
1497415000 }
1497515001
14976- if (ass == dedup_assembly ) {
15002+ if (acfg -> dedup_phase == DEDUP_EMIT ) {
1497715003 /* Add collected dedup-able methods */
1497815004 aot_printf (acfg , "Adding %d dedup-ed methods.\n" , g_hash_table_size (dedup_methods ));
1497915005
1498015006 GHashTableIter iter ;
1498115007 MonoMethod * key ;
1498215008 MonoMethod * method ;
1498315009
14984- acfg -> dedup_emit_mode = TRUE;
14985-
1498615010 g_hash_table_iter_init (& iter , dedup_methods );
1498715011 while (g_hash_table_iter_next (& iter , (gpointer * )& key , (gpointer * )& method ))
1498815012 add_method_full (acfg , method , TRUE, 0 );
@@ -15065,7 +15089,7 @@ aot_assembly (MonoAssembly *ass, guint32 jit_opts, MonoAotOptions *aot_options)
1506515089 TV_GETTIME (btv );
1506615090
1506715091 acfg -> stats .jit_time = GINT64_TO_INT (TV_ELAPSED (atv , btv ));
15068- if (acfg -> dedup_collect_only ) {
15092+ if (acfg -> dedup_phase == DEDUP_COLLECT ) {
1506915093 /* We only collected methods from this assembly */
1507015094 acfg_free (acfg );
1507115095 return 0 ;
0 commit comments