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] Remove some of the restrictions on constrained calls from #59182

Merged
merged 2 commits into from
Sep 17, 2021
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
24 changes: 14 additions & 10 deletions src/mono/mono/mini/gshared.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1472,15 +1472,16 @@ public static int test_0_nullable_unbox () {

interface IConstrained {
void foo ();
void foo_ref_arg (string s);
void foo_ref_arg (string s, string s2);
}

interface IConstrained<T3> {
void foo_gsharedvt_arg (T3 s);
void foo_gsharedvt_arg (T3 s, T3 s2);
T3 foo_gsharedvt_ret (T3 s);
}

static object constrained_res;
static object constrained_res2;

struct ConsStruct : IConstrained {
public int i;
Expand All @@ -1489,8 +1490,8 @@ public void foo () {
constrained_res = i;
}

public void foo_ref_arg (string s) {
constrained_res = s == "A" ? 42 : 0;
public void foo_ref_arg (string s, string s2) {
constrained_res = (s == "A" && s2 == "B") ? 42 : 0;
}
}

Expand All @@ -1501,14 +1502,15 @@ public void foo () {
constrained_res = i;
}

public void foo_ref_arg (string s) {
constrained_res = s == "A" ? 43 : 0;
public void foo_ref_arg (string s, string s2) {
constrained_res = (s == "A" && s2 == "B") ? 43 : 0;
}
}

struct ConsStruct<T> : IConstrained<T> {
public void foo_gsharedvt_arg (T s) {
public void foo_gsharedvt_arg (T s, T s2) {
constrained_res = s;
constrained_res2 = s2;
}

public T foo_gsharedvt_ret (T s) {
Expand All @@ -1521,7 +1523,7 @@ public void foo () {
throw new Exception ();
}

public void foo_ref_arg (string s) {
public void foo_ref_arg (string s, string s2) {
}
}

Expand All @@ -1541,12 +1543,12 @@ public void constrained_void_iface_call<T, T2>(T t, T2 t2) where T2 : IConstrain

[MethodImplAttribute (MethodImplOptions.NoInlining)]
public void constrained_void_iface_call_ref_arg<T, T2>(T t, T2 t2) where T2 : IConstrained {
t2.foo_ref_arg ("A");
t2.foo_ref_arg ("A", "B");
}

[MethodImplAttribute (MethodImplOptions.NoInlining)]
public void constrained_void_iface_call_gsharedvt_arg<T, T2, T3>(T t, T2 t2, T3 t3) where T2 : IConstrained<T> {
t2.foo_gsharedvt_arg (t);
t2.foo_gsharedvt_arg (t, t);
}

[MethodImplAttribute (MethodImplOptions.NoInlining)]
Expand Down Expand Up @@ -1616,6 +1618,8 @@ public static int test_0_constrained_void_iface_call_gsharedvt_arg () {
c.constrained_void_iface_call_gsharedvt_arg<string, ConsStruct<string>, int> ("A", s2, 55);
if (!(constrained_res is string) || ((string)constrained_res) != "A")
return 2;
if (!(constrained_res2 is string) || ((string)constrained_res2) != "A")
return 3;

return 0;
}
Expand Down
13 changes: 10 additions & 3 deletions src/mono/mono/mini/jit-icalls.c
Original file line number Diff line number Diff line change
Expand Up @@ -1396,7 +1396,7 @@ constrained_gsharedvt_call_setup (gpointer mp, MonoMethod *cmethod, MonoClass *k
* the arguments to the method in the format used by mono_runtime_invoke_checked ().
*/
MonoObject*
mono_gsharedvt_constrained_call (gpointer mp, MonoMethod *cmethod, MonoClass *klass, gboolean deref_arg, gpointer *args)
mono_gsharedvt_constrained_call (gpointer mp, MonoMethod *cmethod, MonoClass *klass, guint8 *deref_args, gpointer *args)
{
ERROR_DECL (error);
MonoObject *o;
Expand Down Expand Up @@ -1424,8 +1424,15 @@ mono_gsharedvt_constrained_call (gpointer mp, MonoMethod *cmethod, MonoClass *kl

if (!m)
return NULL;
if (args && deref_arg) {
new_args [0] = *(gpointer*)args [0];
if (deref_args) {
/* Have to deref gsharedvt ref arguments since the runtime invoke expects it */
MonoMethodSignature *fsig = mono_method_signature_internal (m);
g_assert (fsig->param_count < 16);
memcpy (new_args, args, fsig->param_count * sizeof (gpointer));
for (int i = 0; i < fsig->param_count; ++i) {
if (deref_args [i])
new_args [i] = *(gpointer*)new_args [i];
}
args = new_args;
}
if (m->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE) {
Expand Down
2 changes: 1 addition & 1 deletion src/mono/mono/mini/jit-icalls.h
Original file line number Diff line number Diff line change
Expand Up @@ -203,7 +203,7 @@ 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, gboolean deref_arg, gpointer *args);
ICALL_EXPORT MonoObject* mono_gsharedvt_constrained_call (gpointer mp, MonoMethod *cmethod, MonoClass *klass, guint8 *deref_args, gpointer *args);

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

Expand Down
52 changes: 32 additions & 20 deletions src/mono/mono/mini/method-to-ir.c
Original file line number Diff line number Diff line change
Expand Up @@ -3676,13 +3676,10 @@ handle_constrained_gsharedvt_call (MonoCompile *cfg, MonoMethod *cmethod, MonoMe
if (fsig->param_count == 0 || (!fsig->hasthis && fsig->param_count == 1)) {
supported = TRUE;
} else {
/* Allow scalar parameters and a gsharedvt first parameter */
supported = MONO_TYPE_IS_PRIMITIVE (fsig->params [0]) || MONO_TYPE_IS_REFERENCE (fsig->params [0]) || fsig->params [0]->byref || mini_is_gsharedvt_type (fsig->params [0]);
if (supported) {
for (int i = 1; i < fsig->param_count; ++i) {
if (!(fsig->params [i]->byref || MONO_TYPE_IS_PRIMITIVE (fsig->params [i]) || MONO_TYPE_IS_REFERENCE (fsig->params [i]) || MONO_TYPE_ISSTRUCT (fsig->params [i])))
supported = FALSE;
}
supported = TRUE;
for (int i = 0; i < fsig->param_count; ++i) {
if (!(fsig->params [i]->byref || MONO_TYPE_IS_PRIMITIVE (fsig->params [i]) || MONO_TYPE_IS_REFERENCE (fsig->params [i]) || MONO_TYPE_ISSTRUCT (fsig->params [i]) || mini_is_gsharedvt_type (fsig->params [i])))
supported = FALSE;
}
}
}
Expand All @@ -3703,29 +3700,44 @@ handle_constrained_gsharedvt_call (MonoCompile *cfg, MonoMethod *cmethod, MonoMe

/* !fsig->hasthis is for the wrapper for the Object.GetType () icall */
if (fsig->hasthis && fsig->param_count) {
/* Call mono_gsharedvt_constrained_call (gpointer mp, MonoMethod *cmethod, MonoClass *klass, gboolean deref_arg, gpointer *args) */
/* Call mono_gsharedvt_constrained_call (gpointer mp, MonoMethod *cmethod, MonoClass *klass, gboolean *deref_args, gpointer *args) */
gboolean has_gsharedvt = FALSE;
for (int i = 0; i < fsig->param_count; ++i) {
if (mini_is_gsharedvt_type (fsig->params [i]))
has_gsharedvt = TRUE;
}
/* Pass an array of bools which signal whenever the corresponding argument is a gsharedvt ref type */
if (has_gsharedvt) {
MONO_INST_NEW (cfg, ins, OP_LOCALLOC_IMM);
ins->dreg = alloc_preg (cfg);
ins->inst_imm = fsig->param_count;
MONO_ADD_INS (cfg->cbb, ins);
args [3] = ins;
} else {
EMIT_NEW_PCONST (cfg, args [3], 0);
}
/* Pass the arguments using a localloc-ed array using the format expected by runtime_invoke () */
MONO_INST_NEW (cfg, ins, OP_LOCALLOC_IMM);
ins->dreg = alloc_preg (cfg);
ins->inst_imm = fsig->param_count * sizeof (target_mgreg_t);
MONO_ADD_INS (cfg->cbb, ins);
args [4] = ins;

/* Only the first argument is allowed to be gsharedvt */
/* args [3] = deref_arg */
if (mini_is_gsharedvt_type (fsig->params [0])) {
int deref_arg_reg;
ins = mini_emit_get_gsharedvt_info_klass (cfg, mono_class_from_mono_type_internal (fsig->params [0]), MONO_RGCTX_INFO_CLASS_BOX_TYPE);
deref_arg_reg = alloc_preg (cfg);
/* deref_arg = BOX_TYPE != MONO_GSHAREDVT_BOX_TYPE_VTYPE */
EMIT_NEW_BIALU_IMM (cfg, args [3], OP_ISUB_IMM, deref_arg_reg, ins->dreg, 1);
} else {
EMIT_NEW_ICONST (cfg, args [3], 0);
}

for (int i = 0; i < fsig->param_count; ++i) {
int addr_reg;

if (mini_is_gsharedvt_type (fsig->params [i])) {
MonoInst *is_deref;
int deref_arg_reg;
ins = mini_emit_get_gsharedvt_info_klass (cfg, mono_class_from_mono_type_internal (fsig->params [i]), MONO_RGCTX_INFO_CLASS_BOX_TYPE);
deref_arg_reg = alloc_preg (cfg);
/* deref_arg = BOX_TYPE != MONO_GSHAREDVT_BOX_TYPE_VTYPE */
EMIT_NEW_BIALU_IMM (cfg, is_deref, OP_ISUB_IMM, deref_arg_reg, ins->dreg, 1);
MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STOREI1_MEMBASE_REG, args [3]->dreg, i, is_deref->dreg);
} else if (has_gsharedvt) {
MONO_EMIT_NEW_STORE_MEMBASE_IMM (cfg, OP_STOREI1_MEMBASE_IMM, args [3]->dreg, i, 0);
}

if (mini_is_gsharedvt_type (fsig->params [i]) || MONO_TYPE_IS_PRIMITIVE (fsig->params [i]) || MONO_TYPE_ISSTRUCT (fsig->params [i])) {
EMIT_NEW_VARLOADA_VREG (cfg, ins, sp [i + 1]->dreg, fsig->params [i]);
addr_reg = ins->dreg;
Expand Down