Skip to content

Commit 8574ce9

Browse files
authored
[mono][jit] Optimize constrained calls to object.GetHashCode () where the receiver is a gshared type constrained to a primitive type/enum. (#61513)
1 parent e7600e0 commit 8574ce9

File tree

1 file changed

+23
-0
lines changed

1 file changed

+23
-0
lines changed

src/mono/mono/mini/method-to-ir.c

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5680,12 +5680,17 @@ handle_constrained_call (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignat
56805680
gboolean constrained_is_generic_param =
56815681
m_class_get_byval_arg (constrained_class)->type == MONO_TYPE_VAR ||
56825682
m_class_get_byval_arg (constrained_class)->type == MONO_TYPE_MVAR;
5683+
MonoType *gshared_constraint = NULL;
56835684

56845685
if (constrained_is_generic_param && cfg->gshared) {
56855686
if (!mini_is_gsharedvt_klass (constrained_class)) {
56865687
g_assert (!m_class_is_valuetype (cmethod->klass));
56875688
if (!mini_type_is_reference (m_class_get_byval_arg (constrained_class)))
56885689
constrained_partial_call = TRUE;
5690+
5691+
MonoType *t = m_class_get_byval_arg (constrained_class);
5692+
MonoGenericParam *gparam = t->data.generic_param;
5693+
gshared_constraint = gparam->gshared_constraint;
56895694
}
56905695
}
56915696

@@ -5727,6 +5732,24 @@ handle_constrained_call (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignat
57275732
need_box = FALSE;
57285733
}
57295734

5735+
if (gshared_constraint && MONO_TYPE_IS_PRIMITIVE (gshared_constraint) && cmethod->klass == mono_defaults.object_class &&
5736+
!strcmp (cmethod->name, "GetHashCode")) {
5737+
/*
5738+
* The receiver is constrained to a primitive type or an enum with the same basetype.
5739+
* Enum.GetHashCode () returns the hash code of the underlying type (see comments in Enum.cs),
5740+
* so the constrained call can be replaced with a normal call to the basetype GetHashCode ()
5741+
* method.
5742+
*/
5743+
MonoClass *gshared_constraint_class = mono_class_from_mono_type_internal (gshared_constraint);
5744+
cmethod = get_method_nofail (gshared_constraint_class, cmethod->name, 0, 0);
5745+
g_assert (cmethod);
5746+
*ref_cmethod = cmethod;
5747+
*ref_virtual = FALSE;
5748+
if (cfg->verbose_level)
5749+
printf (" -> %s\n", mono_method_get_full_name (cmethod));
5750+
return NULL;
5751+
}
5752+
57305753
if (!(cmethod->flags & METHOD_ATTRIBUTE_VIRTUAL) && (cmethod->klass == mono_defaults.object_class || cmethod->klass == m_class_get_parent (mono_defaults.enum_class) || cmethod->klass == mono_defaults.enum_class)) {
57315754
/* The called method is not virtual, i.e. Object:GetType (), the receiver is a vtype, has to box */
57325755
EMIT_NEW_LOAD_MEMBASE_TYPE (cfg, ins, m_class_get_byval_arg (constrained_class), sp [0]->dreg, 0);

0 commit comments

Comments
 (0)