@@ -2779,6 +2779,9 @@ interp_method_check_inlining (TransformData *td, MonoMethod *method, MonoMethodS
27792779{
27802780 MonoMethodHeaderSummary header ;
27812781
2782+ if (td -> disable_inlining )
2783+ return FALSE;
2784+
27822785 if (method -> flags & METHOD_ATTRIBUTE_REQSECOBJ )
27832786 /* Used to mark methods containing StackCrawlMark locals */
27842787 return FALSE;
@@ -8292,6 +8295,42 @@ cprop_sreg (TransformData *td, InterpInst *ins, int *psreg, LocalValue *local_de
82928295 }
82938296}
82948297
8298+ static void
8299+ foreach_local_var (TransformData * td , InterpInst * ins , gpointer data , void (* callback )(TransformData * , int , gpointer ))
8300+ {
8301+ int opcode = ins -> opcode ;
8302+ if (mono_interp_op_sregs [opcode ]) {
8303+ for (int i = 0 ; i < mono_interp_op_sregs [opcode ]; i ++ ) {
8304+ int sreg = ins -> sregs [i ];
8305+
8306+ if (sreg == MINT_CALL_ARGS_SREG ) {
8307+ int * call_args = ins -> info .call_args ;
8308+ if (call_args ) {
8309+ int var = * call_args ;
8310+ while (var != -1 ) {
8311+ callback (td , var , data );
8312+ call_args ++ ;
8313+ var = * call_args ;
8314+ }
8315+ }
8316+ } else {
8317+ callback (td , sreg , data );
8318+ }
8319+ }
8320+ }
8321+
8322+ if (mono_interp_op_dregs [opcode ])
8323+ callback (td , ins -> dreg , data );
8324+ }
8325+
8326+ static void
8327+ clear_local_defs (TransformData * td , int var , void * data )
8328+ {
8329+ LocalValue * local_defs = (LocalValue * ) data ;
8330+ local_defs [var ].type = LOCAL_VALUE_NONE ;
8331+ local_defs [var ].ins = NULL ;
8332+ }
8333+
82958334static void
82968335interp_cprop (TransformData * td )
82978336{
@@ -8316,8 +8355,8 @@ interp_cprop (TransformData *td)
83168355 // Set cbb since we do some instruction inserting below
83178356 td -> cbb = bb ;
83188357
8319- // FIXME This is excessive. Remove this once we have SSA
8320- memset ( local_defs , 0 , td -> locals_size * sizeof ( LocalValue ) );
8358+ for ( ins = bb -> first_ins ; ins != NULL ; ins = ins -> next )
8359+ foreach_local_var ( td , ins , local_defs , clear_local_defs );
83218360
83228361 if (td -> verbose_level )
83238362 g_print ("BB%d\n" , bb -> index );
@@ -8947,34 +8986,6 @@ interp_optimize_code (TransformData *td)
89478986 MONO_TIME_TRACK (mono_interp_stats .super_instructions_time , interp_super_instructions (td ));
89488987}
89498988
8950- static void
8951- foreach_local_var (TransformData * td , InterpInst * ins , int data , void (* callback )(TransformData * , int , int ))
8952- {
8953- int opcode = ins -> opcode ;
8954- if (mono_interp_op_sregs [opcode ]) {
8955- for (int i = 0 ; i < mono_interp_op_sregs [opcode ]; i ++ ) {
8956- int sreg = ins -> sregs [i ];
8957-
8958- if (sreg == MINT_CALL_ARGS_SREG ) {
8959- int * call_args = ins -> info .call_args ;
8960- if (call_args ) {
8961- int var = * call_args ;
8962- while (var != -1 ) {
8963- callback (td , var , data );
8964- call_args ++ ;
8965- var = * call_args ;
8966- }
8967- }
8968- } else {
8969- callback (td , sreg , data );
8970- }
8971- }
8972- }
8973-
8974- if (mono_interp_op_dregs [opcode ])
8975- callback (td , ins -> dreg , data );
8976- }
8977-
89788989static void
89798990set_var_live_range (TransformData * td , int var , int ins_index )
89808991{
@@ -8986,6 +8997,12 @@ set_var_live_range (TransformData *td, int var, int ins_index)
89868997 td -> locals [var ].live_end = ins_index ;
89878998}
89888999
9000+ static void
9001+ set_var_live_range_cb (TransformData * td , int var , gpointer data )
9002+ {
9003+ set_var_live_range (td , var , (int )(gsize )data );
9004+ }
9005+
89899006static void
89909007initialize_global_var (TransformData * td , int var , int bb_index )
89919008{
@@ -9002,6 +9019,12 @@ initialize_global_var (TransformData *td, int var, int bb_index)
90029019 alloc_global_var_offset (td , var );
90039020 td -> locals [var ].flags |= INTERP_LOCAL_FLAG_GLOBAL ;
90049021 }
9022+ }
9023+
9024+ static void
9025+ initialize_global_var_cb (TransformData * td , int var , gpointer data )
9026+ {
9027+ initialize_global_var (td , var , (int )(gsize )data );
90059028}
90069029
90079030static void
@@ -9026,7 +9049,7 @@ initialize_global_vars (TransformData *td)
90269049 td -> locals [var ].flags |= INTERP_LOCAL_FLAG_GLOBAL ;
90279050 }
90289051 }
9029- foreach_local_var (td , ins , bb -> index , initialize_global_var );
9052+ foreach_local_var (td , ins , ( gpointer )( gsize ) bb -> index , initialize_global_var_cb );
90309053 }
90319054 }
90329055}
@@ -9296,7 +9319,7 @@ interp_alloc_offsets (TransformData *td)
92969319 // The arg of the call is no longer global
92979320 * call_args = new_var ;
92989321 // Also update liveness for this instruction
9299- foreach_local_var (td , new_inst , ins_index , set_var_live_range );
9322+ foreach_local_var (td , new_inst , ( gpointer )( gsize ) ins_index , set_var_live_range_cb );
93009323 ins_index ++ ;
93019324 }
93029325 } else {
@@ -9334,7 +9357,7 @@ interp_alloc_offsets (TransformData *td)
93349357 }
93359358 }
93369359 // Set live_start and live_end for every referenced local that is not global
9337- foreach_local_var (td , ins , ins_index , set_var_live_range );
9360+ foreach_local_var (td , ins , ( gpointer )( gsize ) ins_index , set_var_live_range_cb );
93389361 ins_index ++ ;
93399362 }
93409363 gint32 current_offset = td -> total_locals_size ;
@@ -9448,6 +9471,7 @@ generate (MonoMethod *method, MonoMethodHeader *header, InterpMethod *rtm, MonoG
94489471 int i ;
94499472 TransformData transform_data ;
94509473 TransformData * td ;
9474+ gboolean retry_compilation = FALSE;
94519475 static gboolean verbose_method_inited ;
94529476 static char * verbose_method_name ;
94539477
@@ -9456,6 +9480,7 @@ generate (MonoMethod *method, MonoMethodHeader *header, InterpMethod *rtm, MonoG
94569480 verbose_method_inited = TRUE;
94579481 }
94589482
9483+ retry :
94599484 memset (& transform_data , 0 , sizeof (transform_data ));
94609485 td = & transform_data ;
94619486
@@ -9480,6 +9505,8 @@ generate (MonoMethod *method, MonoMethodHeader *header, InterpMethod *rtm, MonoG
94809505 td -> seq_points = g_ptr_array_new ();
94819506 td -> verbose_level = mono_interp_traceopt ;
94829507 td -> prof_coverage = mono_profiler_coverage_instrumentation_enabled (method );
9508+ if (retry_compilation )
9509+ td -> disable_inlining = TRUE;
94839510 rtm -> data_items = td -> data_items ;
94849511
94859512 if (td -> prof_coverage )
@@ -9527,12 +9554,21 @@ generate (MonoMethod *method, MonoMethodHeader *header, InterpMethod *rtm, MonoG
95279554 generate_compacted_code (td );
95289555
95299556 if (td -> total_locals_size >= G_MAXUINT16 ) {
9530- char * name = mono_method_get_full_name (method );
9531- char * msg = g_strdup_printf ("Unable to run method '%s': locals size too big." , name );
9532- g_free (name );
9533- mono_error_set_generic_error (error , "System" , "InvalidProgramException" , "%s" , msg );
9534- g_free (msg );
9535- goto exit ;
9557+ if (td -> disable_inlining ) {
9558+ char * name = mono_method_get_full_name (method );
9559+ char * msg = g_strdup_printf ("Unable to run method '%s': locals size too big." , name );
9560+ g_free (name );
9561+ mono_error_set_generic_error (error , "System" , "InvalidProgramException" , "%s" , msg );
9562+ g_free (msg );
9563+ retry_compilation = FALSE;
9564+ goto exit ;
9565+ } else {
9566+ // We give the method another chance to compile with inlining disabled
9567+ retry_compilation = TRUE;
9568+ goto exit ;
9569+ }
9570+ } else {
9571+ retry_compilation = FALSE;
95369572 }
95379573
95389574 if (td -> verbose_level ) {
@@ -9623,6 +9659,8 @@ generate (MonoMethod *method, MonoMethodHeader *header, InterpMethod *rtm, MonoG
96239659 if (td -> line_numbers )
96249660 g_array_free (td -> line_numbers , TRUE);
96259661 mono_mempool_destroy (td -> mempool );
9662+ if (retry_compilation )
9663+ goto retry ;
96269664}
96279665
96289666gboolean
0 commit comments