[mono] Clean up the delegate ctor code. (#83288)
authorZoltan Varga <vargaz@gmail.com>
Mon, 13 Mar 2023 13:43:33 +0000 (09:43 -0400)
committerGitHub <noreply@github.com>
Mon, 13 Mar 2023 13:43:33 +0000 (09:43 -0400)
* [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.

12 files changed:
src/mono/mono/mini/aot-compiler.c
src/mono/mono/mini/aot-runtime.c
src/mono/mono/mini/interp/interp.c
src/mono/mono/mini/llvmonly-runtime.c
src/mono/mono/mini/llvmonly-runtime.h
src/mono/mono/mini/method-to-ir.c
src/mono/mono/mini/mini-generic-sharing.c
src/mono/mono/mini/mini-runtime.c
src/mono/mono/mini/mini-runtime.h
src/mono/mono/mini/mini-trampolines.c
src/mono/mono/mini/mini.h
src/mono/mono/mini/patch-info.h

index cfe88c2..f4713c8 100644 (file)
@@ -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);
@@ -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: {
@@ -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;
@@ -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:
index 4d92418..f7ebef5 100644 (file)
@@ -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 */
@@ -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: {
index cf33661..d792e0b 100644 (file)
@@ -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;
                }
        }
index 60c3e93..4cf1908 100644 (file)
@@ -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
@@ -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;
@@ -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:
  *
index c7ab646..0c9cff5 100644 (file)
@@ -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);
index c099d5c..caf7e1b 100644 (file)
@@ -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;
@@ -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);
 }
@@ -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);
 
@@ -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 */
@@ -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 */
 
index 3f48234..54ea2a8 100644 (file)
@@ -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;
        }
@@ -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:
@@ -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;
 
@@ -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: {
index cd7117d..339b1bd 100644 (file)
@@ -1155,7 +1155,7 @@ mono_patch_info_dup_mp (MonoMemPool *mp, MonoJumpInfo *patch_info)
                memcpy (res->data.rgctx_entry, patch_info->data.rgctx_entry, sizeof (MonoJumpInfoRgctxEntry));
                res->data.rgctx_entry->data = mono_patch_info_dup_mp (mp, res->data.rgctx_entry->data);
                break;
-       case MONO_PATCH_INFO_DELEGATE_TRAMPOLINE:
+       case MONO_PATCH_INFO_DELEGATE_INFO:
                res->data.del_tramp = (MonoDelegateClassMethodPair *)mono_mempool_alloc0 (mp, sizeof (MonoDelegateClassMethodPair));
                memcpy (res->data.del_tramp, patch_info->data.del_tramp, sizeof (MonoDelegateClassMethodPair));
                break;
@@ -1275,7 +1275,7 @@ mono_patch_info_hash (gconstpointer data)
                return hash | ji->data.table->table_size;
        case MONO_PATCH_INFO_GSHAREDVT_METHOD:
                return hash | GPOINTER_TO_UINT (ji->data.gsharedvt_method->method);
-       case MONO_PATCH_INFO_DELEGATE_TRAMPOLINE:
+       case MONO_PATCH_INFO_DELEGATE_INFO:
                return (guint)(hash | (gsize)ji->data.del_tramp->klass | (gsize)ji->data.del_tramp->method | (gsize)ji->data.del_tramp->is_virtual);
        case MONO_PATCH_INFO_VIRT_METHOD: {
                MonoJumpInfoVirtMethod *info = ji->data.virt_method;
@@ -1347,7 +1347,7 @@ mono_patch_info_equal (gconstpointer ka, gconstpointer kb)
        }
        case MONO_PATCH_INFO_GSHAREDVT_METHOD:
                return ji1->data.gsharedvt_method->method == ji2->data.gsharedvt_method->method;
-       case MONO_PATCH_INFO_DELEGATE_TRAMPOLINE:
+       case MONO_PATCH_INFO_DELEGATE_INFO:
                return ji1->data.del_tramp->klass == ji2->data.del_tramp->klass && ji1->data.del_tramp->method == ji2->data.del_tramp->method && ji1->data.del_tramp->is_virtual == ji2->data.del_tramp->is_virtual;
        case MONO_PATCH_INFO_SPECIFIC_TRAMPOLINE_LAZY_FETCH_ADDR:
                return ji1->data.uindex == ji2->data.uindex;
@@ -1386,7 +1386,7 @@ mini_gshared_method_info_dup (MonoMemoryManager *mem_manager, MonoGSharedMethodI
                MonoRuntimeGenericContextInfoTemplate *entry = &info->entries [i];
                MonoRuntimeGenericContextInfoTemplate *new_entry = &res->entries [i];
                switch (mini_rgctx_info_type_to_patch_info_type (entry->info_type)) {
-               case MONO_PATCH_INFO_DELEGATE_TRAMPOLINE: {
+               case MONO_PATCH_INFO_DELEGATE_INFO: {
                        MonoDelegateClassMethodPair *old_info = (MonoDelegateClassMethodPair*)entry->data;
                        MonoDelegateClassMethodPair *new_info = mono_mem_manager_alloc0 (mem_manager, sizeof (MonoDelegateClassMethodPair));
                        memcpy (new_info, old_info, sizeof (MonoDelegateClassMethodPair));
@@ -1565,13 +1565,10 @@ mono_resolve_patch_target_ext (MonoMemoryManager *mem_manager, MonoMethod *metho
                target = mono_class_vtable_checked (patch_info->data.klass, error);
                mono_error_assert_ok (error);
                break;
-       case MONO_PATCH_INFO_DELEGATE_TRAMPOLINE: {
+       case MONO_PATCH_INFO_DELEGATE_INFO: {
                MonoDelegateClassMethodPair *del_tramp = patch_info->data.del_tramp;
 
-               if (del_tramp->is_virtual)
-                       target = mono_create_delegate_virtual_trampoline (del_tramp->klass, del_tramp->method);
-               else
-                       target = mono_create_delegate_trampoline_info (del_tramp->klass, del_tramp->method);
+               target = mono_create_delegate_trampoline_info (del_tramp->klass, del_tramp->method, del_tramp->is_virtual);
                break;
        }
        case MONO_PATCH_INFO_SFLDA: {
@@ -4214,20 +4211,20 @@ register_counters (void)
 static void runtime_invoke_info_free (gpointer value);
 
 static gint
-class_method_pair_equal (gconstpointer ka, gconstpointer kb)
+delegate_class_method_pair_equal (gconstpointer ka, gconstpointer kb)
 {
-       const MonoClassMethodPair *apair = (const MonoClassMethodPair *)ka;
-       const MonoClassMethodPair *bpair = (const MonoClassMethodPair *)kb;
+       const MonoDelegateClassMethodPair *apair = (const MonoDelegateClassMethodPair *)ka;
+       const MonoDelegateClassMethodPair *bpair = (const MonoDelegateClassMethodPair *)kb;
 
-       return apair->klass == bpair->klass && apair->method == bpair->method ? 1 : 0;
+       return apair->klass == bpair->klass && apair->method == bpair->method && apair->is_virtual == bpair->is_virtual ? 1 : 0;
 }
 
 static guint
-class_method_pair_hash (gconstpointer data)
+delegate_class_method_pair_hash (gconstpointer data)
 {
-       const MonoClassMethodPair *pair = (const MonoClassMethodPair *)data;
+       const MonoDelegateClassMethodPair *pair = (const MonoDelegateClassMethodPair *)data;
 
-       return (guint)((gsize)pair->klass ^ (gsize)pair->method);
+       return (guint)((gsize)pair->klass ^ (gsize)pair->method ^ (gsize)pair->is_virtual);
 }
 
 static void
@@ -4239,7 +4236,7 @@ init_jit_mem_manager (MonoMemoryManager *mem_manager)
        info->jump_trampoline_hash = g_hash_table_new (mono_aligned_addr_hash, NULL);
        info->jump_target_hash = g_hash_table_new (NULL, NULL);
        info->jit_trampoline_hash = g_hash_table_new (mono_aligned_addr_hash, NULL);
-       info->delegate_trampoline_hash = g_hash_table_new (class_method_pair_hash, class_method_pair_equal);
+       info->delegate_info_hash = g_hash_table_new (delegate_class_method_pair_hash, delegate_class_method_pair_equal);
        info->seq_points = g_hash_table_new_full (mono_aligned_addr_hash, NULL, NULL, mono_seq_point_info_free);
        info->runtime_invoke_hash = mono_conc_hashtable_new_full (mono_aligned_addr_hash, NULL, NULL, runtime_invoke_info_free);
        info->arch_seq_points = g_hash_table_new (mono_aligned_addr_hash, NULL);
@@ -4308,7 +4305,7 @@ free_jit_mem_manager (MonoMemoryManager *mem_manager)
        g_hash_table_destroy (info->method_code_hash);
        g_hash_table_destroy (info->jump_trampoline_hash);
        g_hash_table_destroy (info->jit_trampoline_hash);
-       g_hash_table_destroy (info->delegate_trampoline_hash);
+       g_hash_table_destroy (info->delegate_info_hash);
        g_hash_table_destroy (info->static_rgctx_trampoline_hash);
        g_hash_table_destroy (info->mrgctx_hash);
        g_hash_table_destroy (info->interp_method_pointer_hash);
@@ -5004,7 +5001,6 @@ register_icalls (void)
        /* This needs a wrapper so it can have a preserveall cconv */
        register_icall (mini_llvmonly_init_vtable_slot, mono_icall_sig_ptr_ptr_int, FALSE);
        register_icall (mini_llvmonly_init_delegate, mono_icall_sig_void_object_ptr, TRUE);
-       register_icall (mini_llvmonly_init_delegate_virtual, mono_icall_sig_void_object_object_ptr, TRUE);
        register_icall (mini_llvmonly_throw_nullref_exception, mono_icall_sig_void, TRUE);
        register_icall (mini_llvmonly_throw_aot_failed_exception, mono_icall_sig_void_ptr, TRUE);
        register_icall (mini_llvmonly_interp_entry_gsharedvt, mono_icall_sig_void_ptr_ptr_ptr, TRUE);
index 16299ff..266eb2e 100644 (file)
@@ -27,7 +27,7 @@ typedef struct {
        /* Maps methods/klasses to the address of the given type of trampoline */
        GHashTable *jump_trampoline_hash;
        GHashTable *jit_trampoline_hash;
-       GHashTable *delegate_trampoline_hash;
+       GHashTable *delegate_info_hash;
        /* Maps ClassMethodPair -> MonoDelegateTrampInfo */
        GHashTable *static_rgctx_trampoline_hash;
        /* maps MonoMethod -> MonoJitDynamicMethodInfo */
index 2dda92a..ebb2187 100644 (file)
@@ -977,10 +977,8 @@ mono_delegate_trampoline (host_mgreg_t *regs, guint8 *code, gpointer *arg, guint
        MonoMethod *invoke = tramp_info->invoke;
        guint8 *impl_this = (guint8 *)tramp_info->impl_this;
        guint8 *impl_nothis = (guint8 *)tramp_info->impl_nothis;
-       ERROR_DECL (err);
        MonoMethodSignature *sig;
        gpointer addr, compiled_method;
-       gboolean is_remote = FALSE;
 
        UnlockedIncrement (&trampoline_calls);
 
@@ -998,29 +996,26 @@ mono_delegate_trampoline (host_mgreg_t *regs, guint8 *code, gpointer *arg, guint
                 * (ctor_with_method () does this, but it doesn't store the wrapper back into
                 * delegate->method).
                 */
-               if (!is_remote) {
-                       sig = tramp_info->sig;
-                       if (!(sig && method == tramp_info->method)) {
-                               error_init (err);
-                               sig = mono_method_signature_checked (method, err);
-                               if (!sig) {
-                                       mono_error_set_pending_exception (err);
-                                       return NULL;
-                               }
+               sig = tramp_info->sig;
+               if (!(sig && method == tramp_info->method)) {
+                       sig = mono_method_signature_checked (method, error);
+                       if (!sig) {
+                               mono_error_set_pending_exception (error);
+                               return NULL;
                        }
+               }
 
-                       if (sig->hasthis && m_class_is_valuetype (method->klass)) {
-                               gboolean need_unbox = TRUE;
+               if (sig->hasthis && m_class_is_valuetype (method->klass)) {
+                       gboolean need_unbox = TRUE;
 
-                               if (tramp_info->invoke_sig->param_count > sig->param_count && m_type_is_byref (tramp_info->invoke_sig->params [0]))
-                                       need_unbox = FALSE;
+                       if (tramp_info->invoke_sig->param_count > sig->param_count && m_type_is_byref (tramp_info->invoke_sig->params [0]))
+                               need_unbox = FALSE;
 
-                               if (need_unbox) {
-                                       if (mono_aot_only)
-                                               need_unbox_tramp = TRUE;
-                                       else
-                                               method = mono_marshal_get_unbox_wrapper (method);
-                               }
+                       if (need_unbox) {
+                               if (mono_aot_only)
+                                       need_unbox_tramp = TRUE;
+                               else
+                                       method = mono_marshal_get_unbox_wrapper (method);
                        }
                }
        // If "delegate->method_ptr" is null mono_get_addr_from_ftnptr will fail if
@@ -1035,10 +1030,9 @@ mono_delegate_trampoline (host_mgreg_t *regs, guint8 *code, gpointer *arg, guint
        if (method) {
                sig = tramp_info->sig;
                if (!(sig && method == tramp_info->method)) {
-                       error_init (err);
-                       sig = mono_method_signature_checked (method, err);
+                       sig = mono_method_signature_checked (method, error);
                        if (!sig) {
-                               mono_error_set_pending_exception (err);
+                               mono_error_set_pending_exception (error);
                                return NULL;
                        }
                }
@@ -1372,19 +1366,22 @@ mono_create_jit_trampoline_from_token (MonoImage *image, guint32 token)
  * mono_create_delegate_trampoline_info:
  *
  *  Create a trampoline info structure for the KLASS+METHOD pair.
+ * If VIRTUAL is true, the delegate was created using ldvirtftn, so invoking it needs
+ * to either do a virtual call or do a virtual method lookup.
  */
 MonoDelegateTrampInfo*
-mono_create_delegate_trampoline_info (MonoClass *klass, MonoMethod *method)
+mono_create_delegate_trampoline_info (MonoClass *klass, MonoMethod *method, gboolean is_virtual)
 {
        MonoMethod *invoke;
        ERROR_DECL (error);
        MonoDelegateTrampInfo *tramp_info;
-       MonoClassMethodPair pair, *dpair;
+       MonoDelegateClassMethodPair pair, *dpair;
        MonoMemoryManager *mm_class, *mm_method, *mm;
        MonoJitMemoryManager *jit_mm;
 
        pair.klass = klass;
        pair.method = method;
+       pair.is_virtual = is_virtual;
 
        if (method) {
                mm_class = m_class_get_mem_manager (klass);
@@ -1396,7 +1393,7 @@ mono_create_delegate_trampoline_info (MonoClass *klass, MonoMethod *method)
        }
 
        jit_mm_lock (jit_mm);
-       tramp_info = (MonoDelegateTrampInfo *)g_hash_table_lookup (jit_mm->delegate_trampoline_hash, &pair);
+       tramp_info = (MonoDelegateTrampInfo *)g_hash_table_lookup (jit_mm->delegate_info_hash, &pair);
        jit_mm_unlock (jit_mm);
        if (tramp_info)
                return tramp_info;
@@ -1408,6 +1405,7 @@ mono_create_delegate_trampoline_info (MonoClass *klass, MonoMethod *method)
        tramp_info->klass = klass;
        tramp_info->invoke = invoke;
        tramp_info->invoke_sig = mono_method_signature_internal (invoke);
+       tramp_info->is_virtual = is_virtual;
        // FIXME: Use a different conditional
 #ifndef HOST_WASM
        if (!mono_llvm_only) {
@@ -1421,20 +1419,25 @@ mono_create_delegate_trampoline_info (MonoClass *klass, MonoMethod *method)
                tramp_info->sig = mono_method_signature_checked (method, error);
                tramp_info->need_rgctx_tramp = mono_method_needs_static_rgctx_invoke (method, FALSE);
        }
+
 #ifndef HOST_WASM
-       if (!mono_llvm_only) {
-               guint32 code_size = 0;
-               tramp_info->invoke_impl = mono_create_specific_trampoline (jit_mm->mem_manager, tramp_info, MONO_TRAMPOLINE_DELEGATE, &code_size);
-               g_assert (code_size);
+       if (is_virtual) {
+               tramp_info->invoke_impl = mono_get_delegate_virtual_invoke_impl (mono_method_signature_internal (invoke), method);
+       } else {
+               if (!mono_llvm_only) {
+                       guint32 code_size = 0;
+                       tramp_info->invoke_impl = mono_create_specific_trampoline (jit_mm->mem_manager, tramp_info, MONO_TRAMPOLINE_DELEGATE, &code_size);
+                       g_assert (code_size);
+               }
        }
 #endif
 
-       dpair = (MonoClassMethodPair *)mono_mem_manager_alloc0 (jit_mm->mem_manager, sizeof (MonoClassMethodPair));
-       memcpy (dpair, &pair, sizeof (MonoClassMethodPair));
+       dpair = (MonoDelegateClassMethodPair *)mono_mem_manager_alloc0 (jit_mm->mem_manager, sizeof (MonoDelegateClassMethodPair));
+       memcpy (dpair, &pair, sizeof (MonoDelegateClassMethodPair));
 
        /* store trampoline address */
        jit_mm_lock (jit_mm);
-       g_hash_table_insert (jit_mm->delegate_trampoline_hash, dpair, tramp_info);
+       g_hash_table_insert (jit_mm->delegate_info_hash, dpair, tramp_info);
        jit_mm_unlock (jit_mm);
 
        return tramp_info;
@@ -1452,16 +1455,7 @@ mono_create_delegate_trampoline (MonoClass *klass)
        if (mono_llvm_only || (mono_use_interpreter && !mono_aot_only))
                return (gpointer)no_delegate_trampoline;
 
-       return mono_create_delegate_trampoline_info (klass, NULL)->invoke_impl;
-}
-
-gpointer
-mono_create_delegate_virtual_trampoline (MonoClass *klass, MonoMethod *method)
-{
-       MonoMethod *invoke = mono_get_delegate_invoke_internal (klass);
-       g_assert (invoke);
-
-       return mono_get_delegate_virtual_invoke_impl (mono_method_signature_internal (invoke), method);
+       return mono_create_delegate_trampoline_info (klass, NULL, FALSE)->invoke_impl;
 }
 
 gpointer
index 666c973..6a46807 100644 (file)
@@ -1164,6 +1164,7 @@ typedef struct
        gpointer impl_this;
        gpointer impl_nothis;
        gboolean need_rgctx_tramp;
+       gboolean is_virtual;
 } MonoDelegateTrampInfo;
 
 /*
@@ -2263,8 +2264,7 @@ gpointer          mono_create_jump_trampoline (MonoMethod *method,
 gpointer mono_create_jit_trampoline (MonoMethod *method, MonoError *error);
 gpointer          mono_create_jit_trampoline_from_token (MonoImage *image, guint32 token);
 gpointer          mono_create_delegate_trampoline (MonoClass *klass);
-MonoDelegateTrampInfo* mono_create_delegate_trampoline_info (MonoClass *klass, MonoMethod *method);
-gpointer          mono_create_delegate_virtual_trampoline (MonoClass *klass, MonoMethod *method);
+MonoDelegateTrampInfo* mono_create_delegate_trampoline_info (MonoClass *klass, MonoMethod *method, gboolean is_virtual);
 gpointer          mono_create_rgctx_lazy_fetch_trampoline (guint32 offset);
 gpointer          mono_create_static_rgctx_trampoline (MonoMethod *m, gpointer addr);
 gpointer          mono_create_ftnptr_arg_trampoline (gpointer arg, gpointer addr);
index 9d8ab94..5d70400 100644 (file)
@@ -28,7 +28,7 @@ PATCH_INFO(EXC_OVF, "exc_ovf")
 PATCH_INFO(GOT_OFFSET, "got_offset")
 PATCH_INFO(DECLSEC, "declsec")
 PATCH_INFO(RVA, "rva")
-PATCH_INFO(DELEGATE_TRAMPOLINE, "delegate_trampoline")
+PATCH_INFO(DELEGATE_INFO, "delegate_info")
 PATCH_INFO(ICALL_ADDR, "icall_addr")
 /* The address of a C function implementing a JIT icall */
 PATCH_INFO(JIT_ICALL_ADDR, "jit_icall_addr")