Skip to content

Commit 47c09fa

Browse files
authored
[mono] Optimize generic sharing for generic methods. (#64129)
* [mono] Optimize generic sharing for generic methods. Previously, rgctx entries where stored either in the class rgctx or the method rgctx in linked structures, and accessed using rgctx trampolines (for non-llvmonly configuration), or inline code and fallback C code (for llvmonly configuration). However, if a method has an mrgctx parameter, all the rgctx entries can be stored as an array in the mrgctx and accessed using a simple load. One complication is that the mrgctx might need to be allocated before the method is compiled/loaded, so the rgctx entries need to be stored in a separate array, and the array needs to be initialized on demand. * Add an 'entries' field to MonoMethodRuntimeGenericContext which stores the rgctx entries. * Add a MonoGSharedMethodInfo structure which stores the information needed to initialize a MonoMethodRuntimeGenericContext, i.e. the number of rgctx entries and their contents. * Add a MONO_PATCH_INFO_GSHARED_METHOD_INFO patch type to refer to the previous structure. * Add a mini_init_method_rgctx () JIT icall, which initializes an mrgctx if needed and generate code in the prolog of gshared methods to call it. * [mono] Pass an mrgctx to static/valuetype gshared methods. Previously, these methods were passed a vtable. Passing the mrgctx instead simplifies some runtime code and allows smaller/faster access to rgctx entries. * Add rgctx trampolines in get_ftnptr_for_method (). * [mono][wasm] Avoid AOTing Microsoft.CodeAnalysis.dll as well.
1 parent 475554d commit 47c09fa

File tree

17 files changed

+419
-154
lines changed

17 files changed

+419
-154
lines changed

src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Unit.Tests/System.Text.Json.SourceGeneration.Roslyn3.11.Unit.Tests.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
</PropertyGroup>
66

77
<ItemGroup>
8+
<HighAotMemoryUsageAssembly Include="Microsoft.CodeAnalysis.dll" />
89
<HighAotMemoryUsageAssembly Include="Microsoft.CodeAnalysis.CSharp.dll" />
910
</ItemGroup>
1011

src/mono/mono/metadata/jit-icall-reg.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -316,6 +316,7 @@ MONO_JIT_ICALL (mono_value_copy_internal) \
316316
MONO_JIT_ICALL (mono_x86_start_gsharedvt_call) \
317317
MONO_JIT_ICALL (mono_x86_throw_corlib_exception) \
318318
MONO_JIT_ICALL (mono_x86_throw_exception) \
319+
MONO_JIT_ICALL (mini_init_method_rgctx) \
319320
MONO_JIT_ICALL (native_to_interp_trampoline) \
320321
MONO_JIT_ICALL (personality) \
321322
MONO_JIT_ICALL (pthread_getspecific) \

src/mono/mono/metadata/object-offsets.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,8 @@ DECL_OFFSET(MonoMethodILState, il_offset)
163163
DECL_OFFSET(MonoMethodILState, data)
164164

165165
DECL_OFFSET(MonoMethodRuntimeGenericContext, class_vtable)
166+
DECL_OFFSET(MonoMethodRuntimeGenericContext, entries)
167+
DECL_OFFSET(MonoMethodRuntimeGenericContext, infos)
166168

167169
DECL_OFFSET(MonoJitTlsData, lmf)
168170
DECL_OFFSET(MonoJitTlsData, class_cast_from)

src/mono/mono/mini/aot-compiler.c

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6953,6 +6953,44 @@ encode_patch (MonoAotCompile *acfg, MonoJumpInfo *patch_info, guint8 *buf, guint
69536953
}
69546954
break;
69556955
}
6956+
case MONO_PATCH_INFO_GSHARED_METHOD_INFO: {
6957+
MonoGSharedMethodInfo *info = (MonoGSharedMethodInfo*)patch_info->data.target;
6958+
6959+
encode_method_ref (acfg, info->method, p, &p);
6960+
encode_value (info->num_entries, p, &p);
6961+
6962+
for (int i = 0; i < info->num_entries; ++i) {
6963+
MonoRuntimeGenericContextInfoTemplate *entry = &info->entries [i];
6964+
MonoRgctxInfoType info_type = entry->info_type;
6965+
gpointer data = entry->data;
6966+
MonoJumpInfo tmp;
6967+
MonoJumpInfoType patch_type;
6968+
6969+
encode_value (info_type, p, &p);
6970+
6971+
patch_type = mini_rgctx_info_type_to_patch_info_type (info_type);
6972+
switch (patch_type) {
6973+
case MONO_PATCH_INFO_CLASS:
6974+
encode_klass_ref (acfg, mono_class_from_mono_type_internal ((MonoType*)data), p, &p);
6975+
break;
6976+
case MONO_PATCH_INFO_FIELD:
6977+
case MONO_PATCH_INFO_METHOD:
6978+
case MONO_PATCH_INFO_DELEGATE_TRAMPOLINE:
6979+
case MONO_PATCH_INFO_VIRT_METHOD:
6980+
case MONO_PATCH_INFO_GSHAREDVT_METHOD:
6981+
case MONO_PATCH_INFO_GSHAREDVT_CALL: {
6982+
tmp.type = patch_type;
6983+
tmp.data.target = data;
6984+
encode_patch (acfg, &tmp, p, &p);
6985+
break;
6986+
}
6987+
default:
6988+
g_assert_not_reached ();
6989+
break;
6990+
}
6991+
}
6992+
break;
6993+
}
69566994
case MONO_PATCH_INFO_VIRT_METHOD:
69576995
encode_klass_ref (acfg, patch_info->data.virt_method->klass, p, &p);
69586996
encode_method_ref (acfg, patch_info->data.virt_method->method, p, &p);

src/mono/mono/mini/aot-runtime.c

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3930,6 +3930,58 @@ decode_patch (MonoAotModule *aot_module, MonoMemPool *mp, MonoJumpInfo *ji, guin
39303930
ji->data.target = info;
39313931
break;
39323932
}
3933+
case MONO_PATCH_INFO_GSHARED_METHOD_INFO: {
3934+
MonoGSharedMethodInfo *info = (MonoGSharedMethodInfo *)mono_mempool_alloc0 (mp, sizeof (MonoGSharedMethodInfo));
3935+
3936+
info->method = decode_resolve_method_ref (aot_module, p, &p, error);
3937+
mono_error_assert_ok (error);
3938+
3939+
info->num_entries = decode_value (p, &p);
3940+
info->count_entries = info->num_entries;
3941+
info->entries = (MonoRuntimeGenericContextInfoTemplate *)mono_mempool_alloc0 (mp, sizeof (MonoRuntimeGenericContextInfoTemplate) * info->num_entries);
3942+
for (int i = 0; i < info->num_entries; ++i) {
3943+
MonoRuntimeGenericContextInfoTemplate *entry = &info->entries [i];
3944+
MonoJumpInfoType patch_type;
3945+
3946+
entry->info_type = (MonoRgctxInfoType)decode_value (p, &p);
3947+
patch_type = mini_rgctx_info_type_to_patch_info_type (entry->info_type);
3948+
switch (patch_type) {
3949+
case MONO_PATCH_INFO_CLASS: {
3950+
MonoClass *klass = decode_klass_ref (aot_module, p, &p, error);
3951+
mono_error_cleanup (error); /* FIXME don't swallow the error */
3952+
if (!klass)
3953+
goto cleanup;
3954+
entry->data = m_class_get_byval_arg (klass);
3955+
break;
3956+
}
3957+
case MONO_PATCH_INFO_FIELD:
3958+
entry->data = decode_field_info (aot_module, p, &p);
3959+
if (!entry->data)
3960+
goto cleanup;
3961+
break;
3962+
case MONO_PATCH_INFO_METHOD:
3963+
entry->data = decode_resolve_method_ref (aot_module, p, &p, error);
3964+
mono_error_assert_ok (error);
3965+
break;
3966+
case MONO_PATCH_INFO_DELEGATE_TRAMPOLINE:
3967+
case MONO_PATCH_INFO_VIRT_METHOD:
3968+
case MONO_PATCH_INFO_GSHAREDVT_METHOD:
3969+
case MONO_PATCH_INFO_GSHAREDVT_CALL: {
3970+
MonoJumpInfo tmp;
3971+
tmp.type = patch_type;
3972+
if (!decode_patch (aot_module, mp, &tmp, p, &p))
3973+
goto cleanup;
3974+
entry->data = (gpointer)tmp.data.target;
3975+
break;
3976+
}
3977+
default:
3978+
g_assert_not_reached ();
3979+
break;
3980+
}
3981+
}
3982+
ji->data.target = info;
3983+
break;
3984+
}
39333985
case MONO_PATCH_INFO_VIRT_METHOD: {
39343986
MonoJumpInfoVirtMethod *info = (MonoJumpInfoVirtMethod *)mono_mempool_alloc0 (mp, sizeof (MonoJumpInfoVirtMethod));
39353987

src/mono/mono/mini/jit-icalls.c

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1658,3 +1658,30 @@ void
16581658
mono_dummy_jit_icall_val (gpointer val)
16591659
{
16601660
}
1661+
1662+
void
1663+
mini_init_method_rgctx (MonoMethodRuntimeGenericContext *mrgctx, MonoGSharedMethodInfo *info)
1664+
{
1665+
if (G_LIKELY (mrgctx->entries))
1666+
return;
1667+
1668+
MonoMethod *m = mrgctx->method;
1669+
int ninline = mono_class_rgctx_get_array_size (0, TRUE);
1670+
1671+
// The +1 is for the NULL check at the beginning
1672+
// FIXME: memory management
1673+
gpointer *entries = mono_mem_manager_alloc0 (get_default_mem_manager (), (sizeof (gpointer) * (info->num_entries + 1)));
1674+
for (int i = 0; i < info->num_entries; ++i) {
1675+
gpointer data = mini_instantiate_gshared_info (&info->entries [i],
1676+
mono_method_get_context (m), m->klass);
1677+
g_assert (data);
1678+
1679+
/* The first few entries are stored inline, the rest are stored in mrgctx->entries */
1680+
if (i < ninline)
1681+
mrgctx->infos [i] = data;
1682+
else
1683+
entries [i - ninline] = data;
1684+
}
1685+
mono_memory_barrier ();
1686+
mrgctx->entries = entries;
1687+
}

src/mono/mono/mini/jit-icalls.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -233,4 +233,6 @@ ICALL_EXPORT void mono_dummy_jit_icall (void);
233233

234234
ICALL_EXPORT void mono_dummy_jit_icall_val (gpointer ptr);
235235

236+
ICALL_EXPORT void mini_init_method_rgctx (MonoMethodRuntimeGenericContext *mrgctx, MonoGSharedMethodInfo *info);
237+
236238
#endif /* __MONO_JIT_ICALLS_H__ */

0 commit comments

Comments
 (0)