Skip to content

Commit

Permalink
[mono] Clean up the delegate ctor code. (#83288)
Browse files Browse the repository at this point in the history
* [mono] Clean up the delegate ctor code.

* Merge the virtual and non-virtual cases.
* Reorder the code in handle_delegate_ctor () to reduce the llvm_only conditionals.
* Name variables etc. delegate info instead of delegate trampoline.
* Avoid setting the del->is_virtual field if its FALSE.

* Remove some code which is already done by mono_resolve_patch_target_ext ().

* Remove some dead code.

* Unify the virtual/non-virtual case for llvmonly as well.
  • Loading branch information
vargaz authored Mar 13, 2023
1 parent 02a7695 commit bbc7e06
Show file tree
Hide file tree
Showing 12 changed files with 130 additions and 183 deletions.
8 changes: 4 additions & 4 deletions src/mono/mono/mini/aot-compiler.c
Original file line number Diff line number Diff line change
Expand Up @@ -7039,7 +7039,7 @@ encode_patch (MonoAotCompile *acfg, MonoJumpInfo *patch_info, guint8 *buf, guint
case MONO_PATCH_INFO_ADJUSTED_IID:
encode_klass_ref (acfg, patch_info->data.klass, p, &p);
break;
case MONO_PATCH_INFO_DELEGATE_TRAMPOLINE:
case MONO_PATCH_INFO_DELEGATE_INFO:
encode_klass_ref (acfg, patch_info->data.del_tramp->klass, p, &p);
if (patch_info->data.del_tramp->method) {
encode_value (1, p, &p);
Expand Down Expand Up @@ -7142,7 +7142,7 @@ encode_patch (MonoAotCompile *acfg, MonoJumpInfo *patch_info, guint8 *buf, guint
break;
case MONO_PATCH_INFO_FIELD:
case MONO_PATCH_INFO_METHOD:
case MONO_PATCH_INFO_DELEGATE_TRAMPOLINE:
case MONO_PATCH_INFO_DELEGATE_INFO:
case MONO_PATCH_INFO_VIRT_METHOD:
case MONO_PATCH_INFO_GSHAREDVT_METHOD:
case MONO_PATCH_INFO_GSHAREDVT_CALL: {
Expand Down Expand Up @@ -8952,7 +8952,7 @@ can_encode_patch (MonoAotCompile *acfg, MonoJumpInfo *patch_info)
return FALSE;
}
break;
case MONO_PATCH_INFO_DELEGATE_TRAMPOLINE: {
case MONO_PATCH_INFO_DELEGATE_INFO: {
if (!can_encode_class (acfg, patch_info->data.del_tramp->klass)) {
//printf ("Skip: %s\n", mono_type_full_name (m_class_get_byval_arg (patch_info->data.klass)));
return FALSE;
Expand Down Expand Up @@ -9188,7 +9188,7 @@ add_referenced_patch (MonoAotCompile *acfg, MonoJumpInfo *patch_info, int depth)
break;
case MONO_PATCH_INFO_FIELD:
case MONO_PATCH_INFO_METHOD:
case MONO_PATCH_INFO_DELEGATE_TRAMPOLINE:
case MONO_PATCH_INFO_DELEGATE_INFO:
case MONO_PATCH_INFO_VIRT_METHOD:
case MONO_PATCH_INFO_GSHAREDVT_METHOD:
case MONO_PATCH_INFO_GSHAREDVT_CALL:
Expand Down
4 changes: 2 additions & 2 deletions src/mono/mono/mini/aot-runtime.c
Original file line number Diff line number Diff line change
Expand Up @@ -3803,7 +3803,7 @@ decode_patch (MonoAotModule *aot_module, MonoMemPool *mp, MonoJumpInfo *ji, guin
if (!ji->data.klass)
goto cleanup;
break;
case MONO_PATCH_INFO_DELEGATE_TRAMPOLINE:
case MONO_PATCH_INFO_DELEGATE_INFO:
ji->data.del_tramp = (MonoDelegateClassMethodPair *)mono_mempool_alloc0 (mp, sizeof (MonoDelegateClassMethodPair));
ji->data.del_tramp->klass = decode_klass_ref (aot_module, p, &p, error);
mono_error_cleanup (error); /* FIXME don't swallow the error */
Expand Down Expand Up @@ -4052,7 +4052,7 @@ decode_patch (MonoAotModule *aot_module, MonoMemPool *mp, MonoJumpInfo *ji, guin
entry->data = decode_resolve_method_ref (aot_module, p, &p, error);
mono_error_assert_ok (error);
break;
case MONO_PATCH_INFO_DELEGATE_TRAMPOLINE:
case MONO_PATCH_INFO_DELEGATE_INFO:
case MONO_PATCH_INFO_VIRT_METHOD:
case MONO_PATCH_INFO_GSHAREDVT_METHOD:
case MONO_PATCH_INFO_GSHAREDVT_CALL: {
Expand Down
2 changes: 1 addition & 1 deletion src/mono/mono/mini/interp/interp.c
Original file line number Diff line number Diff line change
Expand Up @@ -1853,7 +1853,7 @@ interp_init_delegate (MonoDelegate *del, MonoDelegateTrampInfo **out_info, MonoE
if (imethod->del_info && imethod->del_info->klass == del->object.vtable->klass) {
*out_info = imethod->del_info;
} else if (!imethod->del_info) {
imethod->del_info = mono_create_delegate_trampoline_info (del->object.vtable->klass, method);
imethod->del_info = mono_create_delegate_trampoline_info (del->object.vtable->klass, method, FALSE);
*out_info = imethod->del_info;
}
}
Expand Down
18 changes: 7 additions & 11 deletions src/mono/mono/mini/llvmonly-runtime.c
Original file line number Diff line number Diff line change
Expand Up @@ -757,6 +757,12 @@ mini_llvmonly_init_delegate (MonoDelegate *del, MonoDelegateTrampInfo *info)
ERROR_DECL (error);
MonoFtnDesc *ftndesc;

if (info && info->is_virtual) {
del->method = mono_object_get_virtual_method_internal (del->target, info->method);
/* Create a new one below for the new class+method pair */
info = NULL;
}

if (!info && !del->method) {
// Multicast delegate init
// Have to set the invoke_impl field
Expand All @@ -771,7 +777,7 @@ mini_llvmonly_init_delegate (MonoDelegate *del, MonoDelegateTrampInfo *info)

if (G_UNLIKELY (!info)) {
g_assert (del->method);
info = mono_create_delegate_trampoline_info (del->object.vtable->klass, del->method);
info = mono_create_delegate_trampoline_info (del->object.vtable->klass, del->method, FALSE);
}

del->method = info->method;
Expand Down Expand Up @@ -823,16 +829,6 @@ mini_llvmonly_init_delegate (MonoDelegate *del, MonoDelegateTrampInfo *info)
del->invoke_impl = ftndesc;
}

void
mini_llvmonly_init_delegate_virtual (MonoDelegate *del, MonoObject *target, MonoMethod *method)
{
g_assert (target);

del->method = mono_object_get_virtual_method_internal (target, method);

mini_llvmonly_init_delegate (del, NULL);
}

/*
* resolve_iface_call:
*
Expand Down
1 change: 0 additions & 1 deletion src/mono/mono/mini/llvmonly-runtime.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@ G_EXTERN_C MonoFtnDesc* mini_llvmonly_resolve_generic_virtual_call (MonoVTable *
G_EXTERN_C MonoFtnDesc* mini_llvmonly_resolve_generic_virtual_iface_call (MonoVTable *vt, int imt_slot, MonoMethod *imt_method);
G_EXTERN_C MonoFtnDesc* mini_llvmonly_resolve_vcall_gsharedvt_fast (MonoObject *this_obj, int slot);
G_EXTERN_C void mini_llvmonly_init_delegate (MonoDelegate *del, MonoDelegateTrampInfo *info);
G_EXTERN_C void mini_llvmonly_init_delegate_virtual (MonoDelegate *del, MonoObject *target, MonoMethod *method);

/* Used for regular llvm as well */
G_EXTERN_C void mini_llvm_init_method (MonoAotFileInfo *info, gpointer aot_module, gpointer method_info, MonoVTable *vtable);
Expand Down
141 changes: 54 additions & 87 deletions src/mono/mono/mini/method-to-ir.c
Original file line number Diff line number Diff line change
Expand Up @@ -2595,7 +2595,7 @@ get_gshared_info_slot (MonoCompile *cfg, MonoJumpInfo *patch_info, MonoRgctxInfo
case MONO_PATCH_INFO_METHODCONST:
case MONO_PATCH_INFO_FIELD:
case MONO_PATCH_INFO_VIRT_METHOD:
case MONO_PATCH_INFO_DELEGATE_TRAMPOLINE:
case MONO_PATCH_INFO_DELEGATE_INFO:
case MONO_PATCH_INFO_GSHAREDVT_METHOD:
case MONO_PATCH_INFO_GSHAREDVT_CALL:
data = (gpointer)patch_info->data.target;
Expand Down Expand Up @@ -3610,18 +3610,31 @@ emit_set_deopt_il_offset (MonoCompile *cfg, int offset)
}

static MonoInst*
emit_get_rgctx_dele_tramp (MonoCompile *cfg, int context_used,
MonoClass *klass, MonoMethod *virt_method, gboolean _virtual, MonoRgctxInfoType rgctx_type)
emit_get_rgctx_dele_tramp_info (MonoCompile *cfg, int context_used,
MonoClass *klass, MonoMethod *method, gboolean is_virtual, MonoRgctxInfoType rgctx_type)
{
MonoDelegateClassMethodPair *info;
MonoJumpInfoRgctxEntry *entry;

info = (MonoDelegateClassMethodPair *)mono_mempool_alloc0 (cfg->mempool, sizeof (MonoDelegateClassMethodPair));
info->klass = klass;
info->method = virt_method;
info->is_virtual = _virtual;
info->method = method;
info->is_virtual = is_virtual;

entry = mono_patch_info_rgctx_entry_new (cfg->mempool, cfg->method, context_used_is_mrgctx (cfg, context_used), MONO_PATCH_INFO_DELEGATE_TRAMPOLINE, info, rgctx_type);
if (!context_used) {
MonoInst *ins;

g_assert (rgctx_type == MONO_RGCTX_INFO_DELEGATE_TRAMP_INFO);
if (cfg->compile_aot) {
EMIT_NEW_AOTCONST (cfg, ins, MONO_PATCH_INFO_DELEGATE_INFO, info);
} else {
MonoDelegateTrampInfo *tramp_info = mono_create_delegate_trampoline_info (klass, method, is_virtual);
EMIT_NEW_PCONST (cfg, ins, tramp_info);
}
return ins;
}

entry = mono_patch_info_rgctx_entry_new (cfg->mempool, cfg->method, context_used_is_mrgctx (cfg, context_used), MONO_PATCH_INFO_DELEGATE_INFO, info, rgctx_type);

return emit_rgctx_fetch (cfg, context_used, entry);
}
Expand All @@ -3630,15 +3643,13 @@ emit_get_rgctx_dele_tramp (MonoCompile *cfg, int context_used,
* Returns NULL and set the cfg exception on error.
*/
static G_GNUC_UNUSED MonoInst*
handle_delegate_ctor (MonoCompile *cfg, MonoClass *klass, MonoInst *target, MonoMethod *method, int target_method_context_used, int invoke_context_used, gboolean virtual_)
handle_delegate_ctor (MonoCompile *cfg, MonoClass *klass, MonoInst *target, MonoMethod *method, int target_method_context_used, int invoke_context_used, gboolean is_virtual)
{
MonoInst *ptr;
int dreg;
gpointer trampoline;
MonoInst *obj, *tramp_ins;
guint8 **code_slot;
MonoInst *obj, *info_ins;

if (virtual_ && !cfg->llvm_only) {
if (is_virtual && !cfg->llvm_only) {
MonoMethod *invoke = mono_get_delegate_invoke_internal (klass);
g_assert (invoke);

Expand All @@ -3651,7 +3662,7 @@ handle_delegate_ctor (MonoCompile *cfg, MonoClass *klass, MonoInst *target, Mono
if (!obj)
return NULL;

/* Inline the contents of mono_delegate_ctor */
/* Inline the contents of mini_init_delegate */

/* Set target field */
/* Optimize away setting of NULL target */
Expand All @@ -3670,104 +3681,60 @@ handle_delegate_ctor (MonoCompile *cfg, MonoClass *klass, MonoInst *target, Mono
}
}

info_ins = emit_get_rgctx_dele_tramp_info (cfg, target_method_context_used | invoke_context_used, klass, method, is_virtual, MONO_RGCTX_INFO_DELEGATE_TRAMP_INFO);

if (cfg->llvm_only) {
MonoInst *args [] = {
obj,
info_ins
};
mono_emit_jit_icall (cfg, mini_llvmonly_init_delegate, args);
return obj;
}

/* Set method field */
if (!(target_method_context_used || invoke_context_used) && !cfg->llvm_only) {
//If compiling with gsharing enabled, it's faster to load method the delegate trampoline info than to use a rgctx slot
if (target_method_context_used || invoke_context_used) {
// We copy from the delegate trampoline info as it's faster than a rgctx fetch
dreg = alloc_preg (cfg);
MONO_EMIT_NEW_LOAD_MEMBASE (cfg, dreg, info_ins->dreg, MONO_STRUCT_OFFSET (MonoDelegateTrampInfo, method));
MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STORE_MEMBASE_REG, obj->dreg, MONO_STRUCT_OFFSET (MonoDelegate, method), dreg);
} else {
// This is emitted as a constant store for the non-shared case.
MonoInst *method_ins = emit_get_rgctx_method (cfg, target_method_context_used, method, MONO_RGCTX_INFO_METHOD);
MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STORE_MEMBASE_REG, obj->dreg, MONO_STRUCT_OFFSET (MonoDelegate, method), method_ins->dreg);
}

if (cfg->llvm_only) {
if (virtual_) {
MonoInst *args [ ] = {
obj,
target,
emit_get_rgctx_method (cfg, target_method_context_used, method, MONO_RGCTX_INFO_METHOD)
};
mono_emit_jit_icall (cfg, mini_llvmonly_init_delegate_virtual, args);
return obj;
}
}

/*
* To avoid looking up the compiled code belonging to the target method
* in mono_delegate_trampoline (), we allocate a per-domain memory slot to
* store it, and we fill it after the method has been compiled.
*/
if (!method->dynamic && !cfg->llvm_only) {
if (!method->dynamic) {
MonoInst *code_slot_ins;

if (target_method_context_used) {
if (target_method_context_used)
code_slot_ins = emit_get_rgctx_method (cfg, target_method_context_used, method, MONO_RGCTX_INFO_METHOD_DELEGATE_CODE);
} else {
MonoJitMemoryManager *jit_mm = (MonoJitMemoryManager*)cfg->jit_mm;

jit_mm_lock (jit_mm);
if (!jit_mm->method_code_hash)
jit_mm->method_code_hash = g_hash_table_new (NULL, NULL);
code_slot = (guint8 **)g_hash_table_lookup (jit_mm->method_code_hash, method);
if (!code_slot) {
code_slot = (guint8 **)mono_mem_manager_alloc0 (jit_mm->mem_manager, sizeof (gpointer));
g_hash_table_insert (jit_mm->method_code_hash, method, code_slot);
}
jit_mm_unlock (jit_mm);

else
code_slot_ins = mini_emit_runtime_constant (cfg, MONO_PATCH_INFO_METHOD_CODE_SLOT, method);
}
MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STORE_MEMBASE_REG, obj->dreg, MONO_STRUCT_OFFSET (MonoDelegate, method_code), code_slot_ins->dreg);
}

if (target_method_context_used || invoke_context_used) {
tramp_ins = emit_get_rgctx_dele_tramp (cfg, target_method_context_used | invoke_context_used, klass, method, virtual_, MONO_RGCTX_INFO_DELEGATE_TRAMP_INFO);

//This is emitted as a constant store for the non-shared case.
//We copy from the delegate trampoline info as it's faster than a rgctx fetch
dreg = alloc_preg (cfg);
if (!cfg->llvm_only) {
MONO_EMIT_NEW_LOAD_MEMBASE (cfg, dreg, tramp_ins->dreg, MONO_STRUCT_OFFSET (MonoDelegateTrampInfo, method));
MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STORE_MEMBASE_REG, obj->dreg, MONO_STRUCT_OFFSET (MonoDelegate, method), dreg);
}
} else if (cfg->compile_aot) {
MonoDelegateClassMethodPair *del_tramp;

del_tramp = (MonoDelegateClassMethodPair *)mono_mempool_alloc0 (cfg->mempool, sizeof (MonoDelegateClassMethodPair));
del_tramp->klass = klass;
del_tramp->method = method;
del_tramp->is_virtual = virtual_;
EMIT_NEW_AOTCONST (cfg, tramp_ins, MONO_PATCH_INFO_DELEGATE_TRAMPOLINE, del_tramp);
} else {
if (virtual_)
trampoline = mono_create_delegate_virtual_trampoline (klass, method);
else
trampoline = mono_create_delegate_trampoline_info (klass, method);
EMIT_NEW_PCONST (cfg, tramp_ins, trampoline);
}

if (cfg->llvm_only) {
MonoInst *args [ ] = {
obj,
tramp_ins
};
mono_emit_jit_icall (cfg, mini_llvmonly_init_delegate, args);
return obj;
}

/* Set invoke_impl field */
if (virtual_) {
MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STORE_MEMBASE_REG, obj->dreg, MONO_STRUCT_OFFSET (MonoDelegate, invoke_impl), tramp_ins->dreg);
} else {
dreg = alloc_preg (cfg);
MONO_EMIT_NEW_LOAD_MEMBASE (cfg, dreg, tramp_ins->dreg, MONO_STRUCT_OFFSET (MonoDelegateTrampInfo, invoke_impl));
MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STORE_MEMBASE_REG, obj->dreg, MONO_STRUCT_OFFSET (MonoDelegate, invoke_impl), dreg);
dreg = alloc_preg (cfg);
MONO_EMIT_NEW_LOAD_MEMBASE (cfg, dreg, info_ins->dreg, MONO_STRUCT_OFFSET (MonoDelegateTrampInfo, invoke_impl));
MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STORE_MEMBASE_REG, obj->dreg, MONO_STRUCT_OFFSET (MonoDelegate, invoke_impl), dreg);

if (!is_virtual) {
dreg = alloc_preg (cfg);
MONO_EMIT_NEW_LOAD_MEMBASE (cfg, dreg, tramp_ins->dreg, MONO_STRUCT_OFFSET (MonoDelegateTrampInfo, method_ptr));
MONO_EMIT_NEW_LOAD_MEMBASE (cfg, dreg, info_ins->dreg, MONO_STRUCT_OFFSET (MonoDelegateTrampInfo, method_ptr));
MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STORE_MEMBASE_REG, obj->dreg, MONO_STRUCT_OFFSET (MonoDelegate, method_ptr), dreg);
}

dreg = alloc_preg (cfg);
MONO_EMIT_NEW_ICONST (cfg, dreg, virtual_ ? 1 : 0);
MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STOREI1_MEMBASE_REG, obj->dreg, MONO_STRUCT_OFFSET (MonoDelegate, method_is_virtual), dreg);
if (is_virtual) {
dreg = alloc_preg (cfg);
MONO_EMIT_NEW_ICONST (cfg, dreg, 1);
MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STOREI1_MEMBASE_REG, obj->dreg, MONO_STRUCT_OFFSET (MonoDelegate, method_is_virtual), dreg);
}

/* All the checks which are in mono_delegate_ctor () are done by the delegate trampoline */

Expand Down
15 changes: 5 additions & 10 deletions src/mono/mono/mini/mini-generic-sharing.c
Original file line number Diff line number Diff line change
Expand Up @@ -2616,14 +2616,9 @@ instantiate_info (MonoMemoryManager *mem_manager, MonoRuntimeGenericContextInfoT
return res;
}
case MONO_RGCTX_INFO_DELEGATE_TRAMP_INFO: {
MonoDelegateClassMethodPair *dele_info = (MonoDelegateClassMethodPair*)data;
gpointer trampoline;

if (dele_info->is_virtual)
trampoline = mono_create_delegate_virtual_trampoline (dele_info->klass, dele_info->method);
else
trampoline = mono_create_delegate_trampoline_info (dele_info->klass, dele_info->method);
MonoDelegateClassMethodPair *del_info = (MonoDelegateClassMethodPair*)data;

gpointer trampoline = mono_create_delegate_trampoline_info (del_info->klass, del_info->method, del_info->is_virtual);
g_assert (trampoline);
return trampoline;
}
Expand Down Expand Up @@ -2950,7 +2945,7 @@ mini_rgctx_info_type_to_patch_info_type (MonoRgctxInfoType info_type)
case MONO_RGCTX_INFO_METHOD_DELEGATE_CODE:
return MONO_PATCH_INFO_METHOD;
case MONO_RGCTX_INFO_DELEGATE_TRAMP_INFO:
return MONO_PATCH_INFO_DELEGATE_TRAMPOLINE;
return MONO_PATCH_INFO_DELEGATE_INFO;
case MONO_RGCTX_INFO_VIRT_METHOD:
case MONO_RGCTX_INFO_VIRT_METHOD_CODE:
case MONO_RGCTX_INFO_VIRT_METHOD_BOX_TYPE:
Expand Down Expand Up @@ -4505,7 +4500,7 @@ mini_get_rgctx_entry_slot (MonoJumpInfoRgctxEntry *entry)
entry_data = info;
break;
}
case MONO_PATCH_INFO_DELEGATE_TRAMPOLINE: {
case MONO_PATCH_INFO_DELEGATE_INFO: {
MonoDelegateClassMethodPair *info;
MonoDelegateClassMethodPair *oinfo = entry->data->data.del_tramp;

Expand All @@ -4532,7 +4527,7 @@ mini_get_rgctx_entry_slot (MonoJumpInfoRgctxEntry *entry)
switch (entry->data->type) {
case MONO_PATCH_INFO_GSHAREDVT_CALL:
case MONO_PATCH_INFO_VIRT_METHOD:
case MONO_PATCH_INFO_DELEGATE_TRAMPOLINE:
case MONO_PATCH_INFO_DELEGATE_INFO:
g_free (entry_data);
break;
case MONO_PATCH_INFO_GSHAREDVT_METHOD: {
Expand Down
Loading

0 comments on commit bbc7e06

Please sign in to comment.