@@ -396,6 +396,10 @@ typedef struct MonoAotCompile {
396
396
GList * profile_data ;
397
397
GHashTable * profile_methods ;
398
398
GHashTable * blob_hash ;
399
+ /* Maps MonoMethod*->GPtrArray* */
400
+ GHashTable * gshared_instances ;
401
+ /* Hash of gshared methods where specific instances are preferred */
402
+ GHashTable * prefer_instances ;
399
403
#ifdef EMIT_WIN32_UNWIND_INFO
400
404
GList * unwind_info_section_cache ;
401
405
#endif
@@ -4302,8 +4306,23 @@ mono_dedup_cache_method (MonoAotCompile *acfg, MonoMethod *method)
4302
4306
g_hash_table_insert (acfg -> dedup_stats , stats_name , GUINT_TO_POINTER (count ));
4303
4307
}
4304
4308
4309
+ static gboolean
4310
+ is_open_method (MonoMethod * method )
4311
+ {
4312
+ MonoGenericContext * context ;
4313
+
4314
+ if (!method -> is_inflated )
4315
+ return FALSE;
4316
+ context = mono_method_get_context (method );
4317
+ if (context -> class_inst && context -> class_inst -> is_open )
4318
+ return TRUE;
4319
+ if (context -> method_inst && context -> method_inst -> is_open )
4320
+ return TRUE;
4321
+ return FALSE;
4322
+ }
4323
+
4305
4324
static void
4306
- add_extra_method_with_depth (MonoAotCompile * acfg , MonoMethod * method , int depth )
4325
+ add_extra_method_full (MonoAotCompile * acfg , MonoMethod * method , gboolean prefer_gshared , int depth )
4307
4326
{
4308
4327
ERROR_DECL (error );
4309
4328
@@ -4315,7 +4334,7 @@ add_extra_method_with_depth (MonoAotCompile *acfg, MonoMethod *method, int depth
4315
4334
return ;
4316
4335
}
4317
4336
4318
- if (mono_method_is_generic_sharable_full (method , TRUE, TRUE, FALSE)) {
4337
+ if (prefer_gshared && mono_method_is_generic_sharable_full (method , TRUE, TRUE, FALSE)) {
4319
4338
MonoMethod * orig = method ;
4320
4339
4321
4340
method = mini_get_shared_method_full (method , SHARE_MODE_NONE , error );
@@ -4325,10 +4344,23 @@ add_extra_method_with_depth (MonoAotCompile *acfg, MonoMethod *method, int depth
4325
4344
return ;
4326
4345
}
4327
4346
4347
+ if (g_hash_table_lookup (acfg -> prefer_instances , method ))
4348
+ /* Compile an instance as well */
4349
+ add_extra_method_full (acfg , orig , FALSE, depth );
4350
+
4328
4351
/* Add it to profile_methods so its not skipped later */
4329
4352
if (acfg -> aot_opts .profile_only && g_hash_table_lookup (acfg -> profile_methods , orig ))
4330
4353
g_hash_table_insert (acfg -> profile_methods , method , method );
4331
- } else if ((acfg -> jit_opts & MONO_OPT_GSHAREDVT ) && prefer_gsharedvt_method (acfg , method ) && mono_method_is_generic_sharable_full (method , FALSE, FALSE, TRUE)) {
4354
+
4355
+ if (!is_open_method (orig ) && !mono_method_is_generic_sharable_full (orig , TRUE, FALSE, FALSE)) {
4356
+ GPtrArray * instances = g_hash_table_lookup (acfg -> gshared_instances , method );
4357
+ if (!instances ) {
4358
+ instances = g_ptr_array_new ();
4359
+ g_hash_table_insert (acfg -> gshared_instances , method , instances );
4360
+ }
4361
+ g_ptr_array_add (instances , orig );
4362
+ }
4363
+ } else if ((acfg -> jit_opts & MONO_OPT_GSHAREDVT ) && prefer_gshared && prefer_gsharedvt_method (acfg , method ) && mono_method_is_generic_sharable_full (method , FALSE, FALSE, TRUE)) {
4332
4364
/* Use the gsharedvt version */
4333
4365
method = mini_get_shared_method_full (method , SHARE_MODE_GSHAREDVT , error );
4334
4366
mono_error_assert_ok (error );
@@ -4347,6 +4379,12 @@ add_extra_method_with_depth (MonoAotCompile *acfg, MonoMethod *method, int depth
4347
4379
add_method_full (acfg , method , TRUE, depth );
4348
4380
}
4349
4381
4382
+ static void
4383
+ add_extra_method_with_depth (MonoAotCompile * acfg , MonoMethod * method , int depth )
4384
+ {
4385
+ add_extra_method_full (acfg , method , TRUE, depth );
4386
+ }
4387
+
4350
4388
static void
4351
4389
add_extra_method (MonoAotCompile * acfg , MonoMethod * method )
4352
4390
{
@@ -9209,6 +9247,22 @@ compile_method (MonoAotCompile *acfg, MonoMethod *method)
9209
9247
printf ("%s ### %d\n" , mono_method_get_full_name (method ), cfg -> code_size );
9210
9248
}
9211
9249
9250
+ if (cfg -> prefer_instances ) {
9251
+ /*
9252
+ * Compile the original specific instances in addition to the gshared method
9253
+ * for performance reasons, since gshared methods cannot implement some
9254
+ * features like static virtual methods efficiently.
9255
+ */
9256
+ g_hash_table_insert (acfg -> prefer_instances , method , method );
9257
+ GPtrArray * instances = g_hash_table_lookup (acfg -> gshared_instances , method );
9258
+ if (instances ) {
9259
+ for (guint i = 0 ; i < instances -> len ; ++ i ) {
9260
+ MonoMethod * instance = (MonoMethod * )g_ptr_array_index (instances , i );
9261
+ add_extra_method_full (acfg , instance , FALSE, 0 );
9262
+ }
9263
+ }
9264
+ }
9265
+
9212
9266
/* Adds generic instances referenced by this method */
9213
9267
/*
9214
9268
* The depth is used to avoid infinite loops when generic virtual recursion is
@@ -13631,6 +13685,8 @@ acfg_create (MonoAssembly *ass, guint32 jit_opts)
13631
13685
acfg -> gsharedvt_in_signatures = g_hash_table_new ((GHashFunc )mono_signature_hash , (GEqualFunc )mono_metadata_signature_equal );
13632
13686
acfg -> gsharedvt_out_signatures = g_hash_table_new ((GHashFunc )mono_signature_hash , (GEqualFunc )mono_metadata_signature_equal );
13633
13687
acfg -> profile_methods = g_hash_table_new (NULL , NULL );
13688
+ acfg -> gshared_instances = g_hash_table_new (NULL , NULL );
13689
+ acfg -> prefer_instances = g_hash_table_new (NULL , NULL );
13634
13690
mono_os_mutex_init_recursive (& acfg -> mutex );
13635
13691
13636
13692
init_got_info (& acfg -> got_info );
0 commit comments