-
Notifications
You must be signed in to change notification settings - Fork 4.7k
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] Extend mono_gsharedvt_constrained_call for static calls and handle nullable value types #94787
[mono] Extend mono_gsharedvt_constrained_call for static calls and handle nullable value types #94787
Conversation
…haredvt ref arguments if it is a nullable vtype.
Tagging subscribers to 'os-ios': @steveisok, @akoeplinger, @kotlarmilos Issue DetailsDescriptionThis PR extends Fixes #94467
|
src/mono/mono/mini/jit-icalls.c
Outdated
@@ -1482,7 +1483,9 @@ mono_gsharedvt_constrained_call (gpointer mp, MonoMethod *cmethod, MonoClass *kl | |||
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]) | |||
// If the argument is a ref or nullable non-vtype, deref it |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@vargaz Please confirm this is correct.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Isn't this information already known at the callsite in handle_constrained_gsharedvt_call
and can be passed through deref_args
? Also isn't deref_args
supposed to be set only for valuetype args, why the check below?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there a testcase which fails for this case ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The case we want handle here is handler.Test<bool?>(true);
.
Isn't this information already known at the callsite in
handle_constrained_gsharedvt_call
and can be passed throughderef_args
?
Yes, this information already known at the callsite:
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, is_gsharedvt_ins->dreg, i, is_deref->dreg);
}
Also isn't
deref_args
supposed to be set only for valuetype args, why the check below?
It appears that an argument is being dereferenced if the BOX_TYPE != MONO_GSHAREDVT_BOX_TYPE_VTYPE
. However, if the argument is a nullable value type, deref_args [i]
is set because mono_class_is_nullable
is checked first:
if (MONO_TYPE_IS_REFERENCE (m_class_get_byval_arg (impl_class)))
return GUINT_TO_POINTER (MONO_GSHAREDVT_BOX_TYPE_REF);
else if (mono_class_is_nullable (impl_class))
return GUINT_TO_POINTER (MONO_GSHAREDVT_BOX_TYPE_NULLABLE);
else
return GUINT_TO_POINTER (MONO_GSHAREDVT_BOX_TYPE_VTYPE);
Then, during runtime, a nullable value type is dereferenced, leading to a runtime crash. Perhaps this check (if not nullable vtype) can be moved to the handle_constrained_gsharedvt_call
, which might result in larger codegen.
Is there a testcase which fails for this case ?
The fullAOT tests are not currently running on the CI. Once the job is enabled, we will check if this case is already covered. If it is not covered, we will add a runtime test. You can currently verify this by using the following sample: #94467 (comment).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would suggest this fix instead:
diff --git a/src/mono/mono/mini/jit-icalls.c b/src/mono/mono/mini/jit-icalls.c
index 21f3252c814..442cb9a65aa 100644
--- a/src/mono/mono/mini/jit-icalls.c
+++ b/src/mono/mono/mini/jit-icalls.c
@@ -1482,7 +1482,7 @@ mono_gsharedvt_constrained_call (gpointer mp, MonoMethod *cmethod, MonoClass *kl
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])
+ if (deref_args [i] != MONO_GSHAREDVT_BOX_TYPE_VTYPE && deref_args [i] != MONO_GSHAREDVT_BOX_TYPE_NULLABLE)
new_args [i] = *(gpointer*)new_args [i];
}
args = new_args;
diff --git a/src/mono/mono/mini/method-to-ir.c b/src/mono/mono/mini/method-to-ir.c
index 99a11126b62..1f359e31cc6 100644
--- a/src/mono/mono/mini/method-to-ir.c
+++ b/src/mono/mono/mini/method-to-ir.c
@@ -3896,13 +3896,8 @@ handle_constrained_gsharedvt_call (MonoCompile *cfg, MonoMethod *cmethod, MonoMe
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, is_gsharedvt_ins->dreg, i, is_deref->dreg);
+ MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STOREI1_MEMBASE_REG, is_gsharedvt_ins->dreg, i, ins->dreg);
} else if (has_gsharedvt) {
MONO_EMIT_NEW_STORE_MEMBASE_IMM (cfg, OP_STOREI1_MEMBASE_IMM, is_gsharedvt_ins->dreg, i, 0);
}
/azp run runtime-extra-platforms |
Azure Pipelines successfully started running 1 pipeline(s). |
/azp run runtime-extra-platforms |
Azure Pipelines successfully started running 1 pipeline(s). |
/backport to release/8.0-staging |
Started backporting to release/8.0-staging: https://github.com/dotnet/runtime/actions/runs/7140806171 |
Would be nice to have some CI tests before a backport. |
Agreed. Postponing this backport until we enable fullAOT CI tests: #92057. |
/backport to release/8.0-staging |
Started backporting to release/8.0-staging: https://github.com/dotnet/runtime/actions/runs/8815796126 |
@kotlarmilos backporting to release/8.0-staging failed, the patch most likely resulted in conflicts: $ git am --3way --ignore-whitespace --keep-non-patch changes.patch
Applying: [mono] Don't use this_arg in static constrained calls. Don't deref gsharedvt ref arguments if it is a nullable vtype.
Using index info to reconstruct a base tree...
M src/mono/mono/mini/jit-icalls.c
Falling back to patching base and 3-way merge...
Auto-merging src/mono/mono/mini/jit-icalls.c
CONFLICT (content): Merge conflict in src/mono/mono/mini/jit-icalls.c
error: Failed to merge in the changes.
hint: Use 'git am --show-current-patch=diff' to see the failed patch
Patch failed at 0001 [mono] Don't use this_arg in static constrained calls. Don't deref gsharedvt ref arguments if it is a nullable vtype.
When you have resolved this problem, run "git am --continue".
If you prefer to skip this patch, run "git am --skip" instead.
To restore the original branch and stop patching, run "git am --abort".
Error: The process '/usr/bin/git' failed with exit code 128 Please backport manually! |
@kotlarmilos an error occurred while backporting to release/8.0-staging, please check the run log for details! Error: git am failed, most likely due to a merge conflict. |
Description
This PR extends
mono_gsharedvt_constrained_call
to handle staticMONO_GSHAREDVT_CONSTRAINT_CALL_TYPE_REF
calls. If the cmethod is a static method,this_arg
should beNULL
. Also, it skips dereferencing sharedvt ref arguments if they are nullable value types.Fixes #94467