+ if (constrained_class) {
+ if (constrained_class->enumtype && !strcmp (target_method->name, "GetHashCode")) {
+ /* Use the corresponding method from the base type to avoid boxing */
+ MonoType *base_type = mono_class_enum_basetype (constrained_class);
+ g_assert (base_type);
+ constrained_class = mono_class_from_mono_type (base_type);
+ target_method = mono_class_get_method_from_name (constrained_class, target_method->name, 0);
+ g_assert (target_method);
+ }
+ }
+
+ if (constrained_class) {
+ mono_class_setup_vtable (constrained_class);
+#if DEBUG_INTERP
+ g_print ("CONSTRAINED.CALLVIRT: %s::%s. %s (%p) ->\n", target_method->klass->name, target_method->name, mono_signature_full_name (target_method->signature), target_method);
+#endif
+ target_method = mono_get_method_constrained_with_method (image, target_method, constrained_class, generic_context, &error);
+#if DEBUG_INTERP
+ g_print (" : %s::%s. %s (%p)\n", target_method->klass->name, target_method->name, mono_signature_full_name (target_method->signature), target_method);
+#endif
+ mono_error_cleanup (&error); /* FIXME: don't swallow the error */
+ mono_class_setup_vtable (target_method->klass);
+
+ if (constrained_class->valuetype && (target_method->klass == mono_defaults.object_class || target_method->klass == mono_defaults.enum_class->parent || target_method->klass == mono_defaults.enum_class)) {
+ ADD_CODE (td, MINT_BOX);
+ ADD_CODE (td, get_data_item_index (td, constrained_class));
+ ADD_CODE (td, csignature->param_count);
+ } else if (!constrained_class->valuetype) {
+ /* managed pointer on the stack, we need to deref that puppy */
+ ADD_CODE (td, MINT_LDIND_I);
+ ADD_CODE (td, csignature->param_count);
+ } else {
+ g_assert (target_method->klass->valuetype);
+ virtual = FALSE;
+ }
+ }
+
+ if (target_method)
+ mono_class_init (target_method->klass);
+