Merge pull request #2487 from alexanderkyte/wrapper_type_mismatch
[mono.git] / mono / mini / mini-runtime.c
index a11f89d5c3a0ee37a174d1ff6ba2261c66e1d3aa..c73c19ffcef9b013900144ce5da667272a6ec2c1 100644 (file)
@@ -1262,6 +1262,8 @@ mono_patch_info_hash (gconstpointer data)
        }
        case MONO_PATCH_INFO_JIT_ICALL_ADDR:
                return (ji->type << 8) | g_str_hash (ji->data.target);
+       case MONO_PATCH_INFO_GSHAREDVT_IN_WRAPPER:
+               return (ji->type << 8) | mono_signature_hash (ji->data.sig);
        default:
                printf ("info type: %d\n", ji->type);
                mono_print_ji (ji); printf ("\n");
@@ -1326,6 +1328,8 @@ mono_patch_info_equal (gconstpointer ka, gconstpointer kb)
                if (ji1->data.target == ji2->data.target)
                        return 1;
                return strcmp (ji1->data.target, ji2->data.target) == 0 ? 1 : 0;
+       case MONO_PATCH_INFO_GSHAREDVT_IN_WRAPPER:
+               return mono_metadata_signature_equal (ji1->data.sig, ji2->data.sig) ? 1 : 0;
        default:
                if (ji1->data.target != ji2->data.target)
                        return 0;
@@ -1698,6 +1702,9 @@ mono_resolve_patch_target (MonoMethod *method, MonoDomain *domain, guint8 *code,
 
                break;
        }
+       case MONO_PATCH_INFO_GSHAREDVT_IN_WRAPPER:
+               target = mini_get_gsharedvt_wrapper (TRUE, NULL, patch_info->data.sig, NULL, -1, FALSE);
+               break;
        default:
                g_assert_not_reached ();
        }
@@ -2280,15 +2287,14 @@ create_runtime_invoke_info (MonoDomain *domain, MonoMethod *method, gpointer com
 #ifndef ENABLE_GSHAREDVT
                        g_assert_not_reached ();
 #endif
+                       info->gsharedvt_invoke = TRUE;
                        if (!callee_gsharedvt) {
                                /* Invoke a gsharedvt out wrapper instead */
                                MonoMethod *wrapper = mini_get_gsharedvt_out_sig_wrapper (sig);
                                MonoMethodSignature *wrapper_sig = mini_get_gsharedvt_out_sig_wrapper_signature (sig->hasthis, sig->ret->type != MONO_TYPE_VOID, sig->param_count);
 
-                               info->gsharedvt_invoke = TRUE;
                                info->wrapper_arg = g_malloc0 (2 * sizeof (gpointer));
-                               info->wrapper_arg [0] = info->compiled_method;
-                               info->wrapper_arg [1] = mono_method_needs_static_rgctx_invoke (method, TRUE) ? mini_method_get_rgctx (method) : NULL;
+                               info->wrapper_arg [0] = mini_add_method_wrappers_llvmonly (method, info->compiled_method, FALSE, FALSE, &(info->wrapper_arg [1]));
 
                                /* Pass has_rgctx == TRUE since the wrapper has an extra arg */
                                invoke = mono_marshal_get_runtime_invoke_for_sig (wrapper_sig);
@@ -2300,7 +2306,6 @@ create_runtime_invoke_info (MonoDomain *domain, MonoMethod *method, gpointer com
                                /* The out wrapper has the same signature as the compiled gsharedvt method */
                                MonoMethodSignature *wrapper_sig = mini_get_gsharedvt_out_sig_wrapper_signature (sig->hasthis, sig->ret->type != MONO_TYPE_VOID, sig->param_count);
 
-                               info->gsharedvt_invoke = TRUE;
                                info->wrapper_arg = mono_method_needs_static_rgctx_invoke (method, TRUE) ? mini_method_get_rgctx (method) : NULL;
 
                                invoke = mono_marshal_get_runtime_invoke_for_sig (wrapper_sig);
@@ -2365,7 +2370,7 @@ mono_llvmonly_runtime_invoke (MonoMethod *method, RuntimeInvokeInfo *info, void
                        params [i] = nullable_buf;
                }
 
-               if (MONO_TYPE_IS_REFERENCE (t)) {
+               if (!t->byref && (MONO_TYPE_IS_REFERENCE (t) || t->type == MONO_TYPE_PTR)) {
                        param_refs [i] = params [i];
                        params [i] = &(param_refs [i]);
                }
@@ -2468,6 +2473,8 @@ mono_jit_runtime_invoke (MonoMethod *method, void *obj, void **params, MonoObjec
                        if (mono_llvm_only) {
                                ji = mini_jit_info_table_find (mono_domain_get (), (char *)mono_get_addr_from_ftnptr (compiled_method), NULL);
                                callee_gsharedvt = mini_jit_info_is_gsharedvt (ji);
+                               if (callee_gsharedvt)
+                                       callee_gsharedvt = mini_is_gsharedvt_variable_signature (mono_method_signature (jinfo_get_method (ji)));
                        }
 
                        if (!callee_gsharedvt)
@@ -2680,9 +2687,6 @@ mono_llvmonly_get_imt_thunk (MonoVTable *vtable, MonoDomain *domain, MonoIMTChec
                        virtual_generic = TRUE;
        }
 
-       if (virtual_generic)
-               g_assert (fail_tramp);
-
        /*
         * Initialize all vtable entries reachable from this imt slot, so the compiled
         * code doesn't have to check it.
@@ -2736,7 +2740,7 @@ mono_llvmonly_get_imt_thunk (MonoVTable *vtable, MonoDomain *domain, MonoIMTChec
                res [0] = mono_llvmonly_imt_thunk;
                break;
        }
-       if (fail_tramp)
+       if (virtual_generic || fail_tramp)
                res [0] = mono_llvmonly_fallback_imt_thunk;
        res [1] = buf;
 
@@ -3011,6 +3015,42 @@ mini_imt_entry_inited (MonoVTable *vt, int imt_slot_index)
        return (imt [imt_slot_index] != mini_get_imt_trampoline (vt, imt_slot_index));
 }
 
+static gboolean
+is_callee_gsharedvt_variable (gpointer addr)
+{
+       MonoJitInfo *ji;
+       gboolean callee_gsharedvt;
+
+       ji = mini_jit_info_table_find (mono_domain_get (), (char *)mono_get_addr_from_ftnptr (addr), NULL);
+       g_assert (ji);
+       callee_gsharedvt = mini_jit_info_is_gsharedvt (ji);
+       if (callee_gsharedvt)
+               callee_gsharedvt = mini_is_gsharedvt_variable_signature (mono_method_signature (jinfo_get_method (ji)));
+       return callee_gsharedvt;
+}
+
+void
+mini_init_delegate (MonoDelegate *del)
+{
+       if (mono_llvm_only) {
+               MonoMethod *method = del->method;
+
+               if (mono_method_needs_static_rgctx_invoke (method, FALSE))
+                       del->rgctx = mini_method_get_rgctx (method);
+
+               /*
+                * Avoid adding gsharedvt in wrappers since they might not exist if
+                * this delegate is called through a gsharedvt delegate invoke wrapper.
+                * Instead, encode that the method is gsharedvt in del->rgctx,
+                * the CEE_MONO_CALLI_EXTRA_ARG implementation in the JIT depends on this.
+                */
+               if (is_callee_gsharedvt_variable (del->method_ptr)) {
+                       g_assert ((((mgreg_t)del->rgctx) & 1) == 0);
+                       del->rgctx = (gpointer)(((mgreg_t)del->rgctx) | 1);
+               }
+       }
+}
+
 gpointer
 mono_get_delegate_virtual_invoke_impl (MonoMethodSignature *sig, MonoMethod *method)
 {
@@ -3439,10 +3479,10 @@ mini_init (const char *filename, const char *runtime_version)
        callbacks.debug_log = mono_debugger_agent_debug_log;
        callbacks.debug_log_is_enabled = mono_debugger_agent_debug_log_is_enabled;
        callbacks.tls_key_supported = mini_tls_key_supported;
-
        callbacks.get_vtable_trampoline = mini_get_vtable_trampoline;
        callbacks.get_imt_trampoline = mini_get_imt_trampoline;
        callbacks.imt_entry_inited = mini_imt_entry_inited;
+       callbacks.init_delegate = mini_init_delegate;
 
        mono_install_callbacks (&callbacks);
 
@@ -3819,7 +3859,7 @@ register_icalls (void)
        register_icall (mono_ldstr, "mono_ldstr", "object ptr ptr int32", FALSE);
        register_icall (mono_helper_stelem_ref_check, "mono_helper_stelem_ref_check", "void object object", FALSE);
        register_icall (mono_object_new, "mono_object_new", "object ptr ptr", FALSE);
-       register_icall (mono_object_new_specific, "mono_object_new_specific", "object ptr", FALSE);
+       register_icall (ves_icall_object_new_specific, "ves_icall_object_new_specific", "object ptr", FALSE);
        register_icall (mono_array_new, "mono_array_new", "object ptr ptr int32", FALSE);
        register_icall (mono_array_new_specific, "mono_array_new_specific", "object ptr int32", FALSE);
        register_icall (mono_runtime_class_init, "mono_runtime_class_init", "void ptr", FALSE);
@@ -3857,17 +3897,21 @@ register_icalls (void)
 
        register_icall (mono_aot_init_llvm_method, "mono_aot_init_llvm_method", "void ptr int", TRUE);
        register_icall (mono_aot_init_gshared_method_this, "mono_aot_init_gshared_method_this", "void ptr int object", TRUE);
-       register_icall (mono_aot_init_gshared_method_rgctx, "mono_aot_init_gshared_method_rgctx", "void ptr int ptr", TRUE);
+       register_icall (mono_aot_init_gshared_method_mrgctx, "mono_aot_init_gshared_method_mrgctx", "void ptr int ptr", TRUE);
+       register_icall (mono_aot_init_gshared_method_vtable, "mono_aot_init_gshared_method_vtable", "void ptr int ptr", TRUE);
 
        register_icall_no_wrapper (mono_resolve_iface_call_gsharedvt, "mono_resolve_iface_call_gsharedvt", "ptr object int ptr ptr");
        register_icall_no_wrapper (mono_resolve_vcall_gsharedvt, "mono_resolve_vcall_gsharedvt", "ptr object int ptr ptr");
        register_icall_no_wrapper (mono_resolve_generic_virtual_call, "mono_resolve_generic_virtual_call", "ptr ptr int ptr");
        register_icall_no_wrapper (mono_resolve_generic_virtual_iface_call, "mono_resolve_generic_virtual_iface_call", "ptr ptr int ptr");
+       register_icall_no_wrapper (mono_llvmonly_set_calling_assembly, "mono_llvmonly_set_calling_assembly", "void ptr");
+       register_icall_no_wrapper (mono_llvmonly_get_calling_assembly, "mono_llvmonly_get_calling_assembly", "object");
        /* This needs a wrapper so it can have a preserveall cconv */
        register_icall (mono_init_vtable_slot, "mono_init_vtable_slot", "ptr ptr int", FALSE);
-       register_icall (mono_init_delegate, "mono_init_delegate", "void object object ptr", TRUE);
-       register_icall (mono_init_delegate_virtual, "mono_init_delegate_virtual", "void object object ptr", TRUE);
+       register_icall (mono_llvmonly_init_delegate, "mono_llvmonly_init_delegate", "void object object ptr", TRUE);
+       register_icall (mono_llvmonly_init_delegate_virtual, "mono_llvmonly_init_delegate_virtual", "void object object ptr", TRUE);
        register_icall (mono_get_assembly_object, "mono_get_assembly_object", "object ptr", TRUE);
+       register_icall (mono_get_method_object, "mono_get_method_object", "object ptr", TRUE);
 
 #ifdef TARGET_IOS
        register_icall (pthread_getspecific, "pthread_getspecific", "ptr ptr", TRUE);