MonoClass *ret_box_class;
gboolean needs_rgctx;
MonoMethodSignature *sig;
+ gboolean gsharedvt_invoke;
gpointer *wrapper_arg;
} RuntimeInvokeInfo;
mini_gsharedvt_runtime_invoke_supported (MonoMethodSignature *sig)
{
gboolean supported = TRUE;
- int i;
- for (i = 0; i < sig->param_count; ++i) {
- MonoType *t = sig->params [i];
-
- if (t->byref && t->type == MONO_TYPE_GENERICINST && mono_class_is_nullable (mono_class_from_mono_type (t)))
- supported = FALSE;
- }
+ if (sig->ret->type == MONO_TYPE_GENERICINST && mono_class_is_nullable (mono_class_from_mono_type (sig->ret)))
+ supported = FALSE;
return supported;
}
static RuntimeInvokeInfo*
-create_runtime_invoke_info (MonoDomain *domain, MonoMethod *method, gpointer compiled_method)
+create_runtime_invoke_info (MonoDomain *domain, MonoMethod *method, gpointer compiled_method, gboolean callee_gsharedvt)
{
MonoMethod *invoke;
RuntimeInvokeInfo *info;
#ifndef ENABLE_GSHAREDVT
supported = FALSE;
#endif
-
- if (supported) {
+ if (supported && !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;
g_free (wrapper_sig);
info->compiled_method = mono_jit_compile_method (wrapper);
+ } else if (supported) {
+ /* Gsharedvt methods can be invoked the same way */
+ /* 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);
+ g_free (wrapper_sig);
}
}
info->runtime_invoke = mono_jit_compile_method (invoke);
MonoDomain *domain = mono_domain_get ();
MonoJitDomainInfo *domain_info;
RuntimeInvokeInfo *info, *info2;
+ MonoJitInfo *ji = NULL;
+ gboolean callee_gsharedvt = FALSE;
if (obj == NULL && !(method->flags & METHOD_ATTRIBUTE_STATIC) && !method->string_ctor && (method->wrapper_type == 0)) {
g_warning ("Ignoring invocation of an instance method on a NULL instance.\n");
}
}
- compiled_method = mini_add_method_trampoline (callee, compiled_method, mono_method_needs_static_rgctx_invoke (callee, TRUE), FALSE);
+ 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)
+ compiled_method = mini_add_method_trampoline (callee, compiled_method, mono_method_needs_static_rgctx_invoke (callee, TRUE), FALSE);
} else {
compiled_method = NULL;
}
- info = create_runtime_invoke_info (domain, method, compiled_method);
+ info = create_runtime_invoke_info (domain, method, compiled_method, callee_gsharedvt);
mono_domain_lock (domain);
info2 = (RuntimeInvokeInfo *)mono_conc_hashtable_insert (domain_info->runtime_invoke_hash, method, info);
runtime_invoke = (MonoObject *(*)(MonoObject *, void **, MonoObject **, void *))info->runtime_invoke;
- if (info->wrapper_arg) {
+ if (info->gsharedvt_invoke) {
MonoMethodSignature *sig = mono_method_signature (method);
gpointer *args;
gpointer retval_ptr;
* The advantage of this is the gsharedvt out wrappers have a reduced set of
* signatures, so we only have to generate runtime invoke wrappers for these
* signatures.
+ * This code also handles invocation of gsharedvt methods directly, no
+ * out wrappers are used in that case.
*/
args = (void **)g_alloca ((sig->param_count + sig->hasthis + 2) * sizeof (gpointer));
param_refs = (gpointer*)g_alloca ((sig->param_count + sig->hasthis + 2) * sizeof (gpointer));
for (i = 0; i < sig->param_count; ++i) {
MonoType *t = sig->params [i];
+ if (t->type == MONO_TYPE_GENERICINST && mono_class_is_nullable (mono_class_from_mono_type (t))) {
+ MonoClass *klass = mono_class_from_mono_type (t);
+ guint8 *nullable_buf;
+ int size;
+
+ size = mono_class_value_size (klass, NULL);
+ nullable_buf = g_alloca (size);
+ g_assert (nullable_buf);
+
+ /* The argument pointed to by params [i] is either a boxed vtype or null */
+ mono_nullable_init (nullable_buf, (MonoObject*)params [i], klass);
+ params [i] = nullable_buf;
+ }
+
if (MONO_TYPE_IS_REFERENCE (t)) {
param_refs [i] = params [i];
params [i] = &(param_refs [i]);
runtime_invoke (NULL, args, exc, info->compiled_method);
if (sig->ret->type != MONO_TYPE_VOID && info->ret_box_class)
- return mono_value_box (domain, info->ret_box_class, retval);
+ return mono_value_box (domain, info->ret_box_class, retval);
else
return *(MonoObject**)retval;
}
is_interface = method->klass->flags & TYPE_ATTRIBUTE_INTERFACE ? TRUE : FALSE;
load_imt_reg = is_virtual_generic || is_interface;
- if (is_interface && !is_virtual_generic)
+ if (is_interface)
offset = ((gint32)mono_method_get_imt_slot (method) - MONO_IMT_SIZE) * SIZEOF_VOID_P;
else
offset = G_STRUCT_OFFSET (MonoVTable, vtable) + ((mono_method_get_vtable_index (method)) * (SIZEOF_VOID_P));