Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mono/mono.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorZoltan Varga <vargaz@gmail.com>2022-05-06 21:34:26 +0300
committerGitHub <noreply@github.com>2022-05-06 21:34:26 +0300
commit4a5ffcabd58d6439e60126f46e0063bcf30e7a47 (patch)
tree6d66f78afb18ac182eef419b6f55601456dd3c65
parent3d11ccdce6df39bb63c783af28ec9756d1b32db1 (diff)
[mono] Remove some of the restrictions on constrained calls from gsharevt methods. (#21470)
This is a backport of https://github.com/dotnet/runtime/pull/59182.
-rw-r--r--mono/mini/jit-icalls.c13
-rw-r--r--mono/mini/jit-icalls.h2
-rw-r--r--mono/mini/method-to-ir.c52
3 files changed, 43 insertions, 24 deletions
diff --git a/mono/mini/jit-icalls.c b/mono/mini/jit-icalls.c
index 3104418350c..dd63bc68ed7 100644
--- a/mono/mini/jit-icalls.c
+++ b/mono/mini/jit-icalls.c
@@ -1412,7 +1412,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;
@@ -1429,8 +1429,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) {
diff --git a/mono/mini/jit-icalls.h b/mono/mini/jit-icalls.h
index 7de1133c0e4..72af13f2640 100644
--- a/mono/mini/jit-icalls.h
+++ b/mono/mini/jit-icalls.h
@@ -205,7 +205,7 @@ ICALL_EXPORT
void
ves_icall_mono_delegate_ctor_interp (MonoObject *this_obj, MonoObject *target, gpointer addr);
-ICALL_EXTERN_C MonoObject* mono_gsharedvt_constrained_call (gpointer mp, MonoMethod *cmethod, MonoClass *klass, gboolean deref_arg, gpointer *args);
+ICALL_EXTERN_C MonoObject* mono_gsharedvt_constrained_call (gpointer mp, MonoMethod *cmethod, MonoClass *klass, guint8 *deref_args, gpointer *args);
ICALL_EXTERN_C void mono_gsharedvt_value_copy (gpointer dest, gpointer src, MonoClass *klass);
diff --git a/mono/mini/method-to-ir.c b/mono/mini/method-to-ir.c
index 0944915708b..6e3a4860ded 100644
--- a/mono/mini/method-to-ir.c
+++ b/mono/mini/method-to-ir.c
@@ -3729,13 +3729,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;
}
}
}
@@ -3756,7 +3753,22 @@ 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);
@@ -3764,21 +3776,21 @@ handle_constrained_gsharedvt_call (MonoCompile *cfg, MonoMethod *cmethod, MonoMe
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;