Skip to content

Commit

Permalink
[mono][aot] Optimize constrained calls made from gsharedvt methods.
Browse files Browse the repository at this point in the history
The calls are of the form:
.constrained T_GSHAREDVT
callvirt <method>

Whenever T_GSHAREDVT is a reference or value type is only known at runtime.

Previously these were handled by passing the arguments to a JIT icall which
computed the target method and did a runtime invoke.

Added 2 optimizations:
* Precompute the data which depends only on the type and the method,
  store it in an rgctx slot and pass it to the JIT icall.
* Add a fastpath for simpler cases which makes an indirect call
  from generated code.
  • Loading branch information
vargaz committed Feb 7, 2023
1 parent b45ee2b commit 0033318
Show file tree
Hide file tree
Showing 8 changed files with 321 additions and 103 deletions.
1 change: 1 addition & 0 deletions src/mono/mono/metadata/icall-signatures.h
Original file line number Diff line number Diff line change
Expand Up @@ -275,6 +275,7 @@ ICALL_SIG (6, (ptr, ptr, ptr, ptr, ptr, ptr)) \
ICALL_SIG (7, (int32, ptr, ptr, ptr, ptr, ptr, int32)) \
ICALL_SIG (7, (void, ptr, ptr, ptr, ptr, ptr, ptr)) \
ICALL_SIG (7, (ptr, ptr, ptr, ptr, ptr, ptr, ptr)) \
ICALL_SIG (7, (object, ptr, ptr, ptr, ptr, ptr, ptr)) \
ICALL_SIG (8, (void, ptr, ptr, int32, ptr, ptrref, ptr, ptrref)) \

// ICALL_SIG_NAME: mono_icall_sig pasted with its parameters with underscores between each.
Expand Down
1 change: 1 addition & 0 deletions src/mono/mono/metadata/jit-icall-reg.h
Original file line number Diff line number Diff line change
Expand Up @@ -338,6 +338,7 @@ MONO_JIT_ICALL (ves_icall_string_alloc) \
MONO_JIT_ICALL (ves_icall_string_new_wrapper) \
MONO_JIT_ICALL (ves_icall_thread_finish_async_abort) \
MONO_JIT_ICALL (mono_marshal_lookup_pinvoke) \
MONO_JIT_ICALL (mono_gsharedvt_constrained_call_fast) \
\
MONO_JIT_ICALL (count) \

Expand Down
66 changes: 52 additions & 14 deletions src/mono/mono/mini/jit-icalls.c
Original file line number Diff line number Diff line change
Expand Up @@ -1348,6 +1348,29 @@ mono_get_native_calli_wrapper (MonoImage *image, MonoMethodSignature *sig, gpoin
return compiled_ptr;
}

gpointer
mono_gsharedvt_constrained_call_fast (gpointer mp, MonoGsharedvtConstrainedCallInfo *info, gpointer *out_receiver)
{
switch (info->call_type) {
case MONO_GSHAREDVT_CONSTRAINT_CALL_TYPE_VTYPE:
/* Calling a vtype method with a vtype receiver */
*out_receiver = mp;
return info->code;
case MONO_GSHAREDVT_CONSTRAINT_CALL_TYPE_REF:
/* Calling a ref method with a ref receiver */
*out_receiver = *(gpointer*)mp;
return info->code;
case MONO_GSHAREDVT_CONSTRAINT_CALL_TYPE_BOX: {
ERROR_DECL (error);
*out_receiver = mono_value_box_checked (info->klass, mp, error);
mono_error_assert_ok (error);
return info->code;
}
default:
return NULL;
}
}

static MonoMethod*
constrained_gsharedvt_call_setup (gpointer mp, MonoMethod *cmethod, MonoClass *klass, gpointer *this_arg, MonoError *error)
{
Expand Down Expand Up @@ -1427,34 +1450,49 @@ constrained_gsharedvt_call_setup (gpointer mp, MonoMethod *cmethod, MonoClass *k
* MP is NULL if CMETHOD is a static virtual method.
*/
MonoObject*
mono_gsharedvt_constrained_call (gpointer mp, MonoMethod *cmethod, MonoClass *klass, guint8 *deref_args, gpointer *args)
mono_gsharedvt_constrained_call (gpointer mp, MonoMethod *cmethod, MonoClass *klass,
MonoGsharedvtConstrainedCallInfo *info, guint8 *deref_args, gpointer *args)
{
ERROR_DECL (error);
MonoObject *o;
MonoMethod *m;
gpointer this_arg;
gpointer new_args [16];

/* Object.GetType () is an intrinsic under netcore */
if (!mono_class_is_ginst (cmethod->klass) && !cmethod->is_inflated && !strcmp (cmethod->name, "GetType")) {
MonoVTable *vt;
switch (info->call_type) {
case MONO_GSHAREDVT_CONSTRAINT_CALL_TYPE_VTYPE:
/* Calling a vtype method with a vtype receiver */
this_arg = mp;
m = info->method;
break;
case MONO_GSHAREDVT_CONSTRAINT_CALL_TYPE_REF:
/* Calling a ref method with a ref receiver */
this_arg = *(gpointer*)mp;
m = info->method;
break;
default:
/* Object.GetType () is an intrinsic under netcore */
if (!mono_class_is_ginst (cmethod->klass) && !cmethod->is_inflated && !strcmp (cmethod->name, "GetType")) {
MonoVTable *vt;

vt = mono_class_vtable_checked (klass, error);
if (!is_ok (error)) {
mono_error_set_pending_exception (error);
return NULL;
}
return vt->type;
}

vt = mono_class_vtable_checked (klass, error);
m = constrained_gsharedvt_call_setup (mp, cmethod, klass, &this_arg, error);
if (!is_ok (error)) {
mono_error_set_pending_exception (error);
return NULL;
}
return vt->type;
}

m = constrained_gsharedvt_call_setup (mp, cmethod, klass, &this_arg, error);
if (!is_ok (error)) {
mono_error_set_pending_exception (error);
return NULL;
if (!m)
return NULL;
break;
}

if (!m)
return NULL;
if (deref_args) {
/* Have to deref gsharedvt ref arguments since the runtime invoke expects it */
MonoMethodSignature *fsig = mono_method_signature_internal (m);
Expand Down
5 changes: 4 additions & 1 deletion src/mono/mono/mini/jit-icalls.h
Original file line number Diff line number Diff line change
Expand Up @@ -205,7 +205,10 @@ ICALL_EXPORT
void
ves_icall_mono_delegate_ctor_interp (MonoObject *this_obj, MonoObject *target, gpointer addr);

ICALL_EXPORT MonoObject* mono_gsharedvt_constrained_call (gpointer mp, MonoMethod *cmethod, MonoClass *klass, guint8 *deref_args, gpointer *args);
ICALL_EXPORT gpointer mono_gsharedvt_constrained_call_fast (gpointer mp, MonoGsharedvtConstrainedCallInfo *info, gpointer *out_receiver);

ICALL_EXPORT MonoObject* mono_gsharedvt_constrained_call (gpointer mp, MonoMethod *cmethod, MonoClass *klass,
MonoGsharedvtConstrainedCallInfo *info, guint8 *deref_args, gpointer *args);

ICALL_EXPORT void mono_gsharedvt_value_copy (gpointer dest, gpointer src, MonoClass *klass);

Expand Down
Loading

0 comments on commit 0033318

Please sign in to comment.