Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[mono] Clean up the delegate ctor code. #83288

Merged
merged 4 commits into from
Mar 13, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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