@@ -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