@@ -86,6 +86,8 @@ static gboolean mono_class_set_failure (MonoClass *klass, MonoErrorBoxed *boxed_
86
86
87
87
static gboolean class_kind_may_contain_generic_instances (MonoTypeKind kind );
88
88
89
+ GENERATE_GET_CLASS_WITH_CACHE (valuetype , "System" , "ValueType" );
90
+
89
91
90
92
/*
91
93
We use gclass recording to allow recursive system f types to be referenced by a parent.
@@ -1760,6 +1762,59 @@ type_has_references (MonoClass *klass, MonoType *ftype)
1760
1762
return FALSE;
1761
1763
}
1762
1764
1765
+ /**
1766
+ * mono_class_is_gparam_with_nonblittable_parent:
1767
+ * \param klass a generic parameter
1768
+ *
1769
+ * \returns TRUE if \p klass is definitely not blittable.
1770
+ *
1771
+ * A parameter is definitely not blittable if it has the IL 'reference'
1772
+ * constraint, or if it has a class specified as a parent. If it has an IL
1773
+ * 'valuetype' constraint or no constraint at all or only interfaces as
1774
+ * constraints, we return FALSE because the parameter may be instantiated both
1775
+ * with blittable and non-blittable types.
1776
+ *
1777
+ * If the paramter is a generic sharing parameter, we look at its gshared_constraint->blittable bit.
1778
+ */
1779
+ static gboolean
1780
+ mono_class_is_gparam_with_nonblittable_parent (MonoClass * klass )
1781
+ {
1782
+ MonoType * type = & klass -> byval_arg ;
1783
+ g_assert (mono_type_is_generic_parameter (type ));
1784
+ MonoGenericParam * gparam = type -> data .generic_param ;
1785
+ if (mono_generic_param_info (gparam ) != NULL )
1786
+ {
1787
+ if ((mono_generic_param_info (gparam )-> flags & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT ) != 0 )
1788
+ return TRUE;
1789
+ if ((mono_generic_param_info (gparam )-> flags & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT ) != 0 )
1790
+ return FALSE;
1791
+ }
1792
+
1793
+ if (gparam -> gshared_constraint ) {
1794
+ MonoClass * constraint_class = mono_class_from_mono_type (gparam -> gshared_constraint );
1795
+ return !constraint_class -> blittable ;
1796
+ }
1797
+
1798
+ if (mono_generic_param_owner (gparam )-> is_anonymous )
1799
+ return FALSE;
1800
+
1801
+ /* We could have: T : U, U : Base. So have to follow the constraints. */
1802
+ MonoClass * parent_class = mono_generic_param_get_base_type (klass );
1803
+ g_assert (!MONO_CLASS_IS_INTERFACE_INTERNAL (parent_class ));
1804
+ /* Parent can only be: System.Object, System.ValueType or some specific base class.
1805
+ *
1806
+ * If the parent_class is ValueType, the valuetype constraint would be set, above, so
1807
+ * we wouldn't get here.
1808
+ *
1809
+ * If there was a reference constraint, the parent_class would be System.Object,
1810
+ * but we would have returned early above.
1811
+ *
1812
+ * So if we get here, there is either no base class constraint at all,
1813
+ * in which case parent_class would be set to System.Object, or there is none at all.
1814
+ */
1815
+ return parent_class != mono_defaults .object_class ;
1816
+ }
1817
+
1763
1818
/*
1764
1819
* mono_class_layout_fields:
1765
1820
* @class: a class
@@ -1877,6 +1932,9 @@ mono_class_layout_fields (MonoClass *klass, int base_instance_size, int packing_
1877
1932
if (blittable ) {
1878
1933
if (field -> type -> byref || MONO_TYPE_IS_REFERENCE (field -> type )) {
1879
1934
blittable = FALSE;
1935
+ } else if (mono_type_is_generic_parameter (field -> type ) &&
1936
+ mono_class_is_gparam_with_nonblittable_parent (mono_class_from_mono_type (field -> type ))) {
1937
+ blittable = FALSE;
1880
1938
} else {
1881
1939
MonoClass * field_class = mono_class_from_mono_type (field -> type );
1882
1940
if (field_class ) {
@@ -8645,6 +8703,60 @@ mono_class_is_assignable_from_slow (MonoClass *target, MonoClass *candidate)
8645
8703
return FALSE;
8646
8704
}
8647
8705
8706
+ /**
8707
+ * mono_generic_param_get_base_type:
8708
+ *
8709
+ * Return the base type of the given generic parameter from its constraints.
8710
+ *
8711
+ * Could be another generic parameter, or it could be Object or ValueType.
8712
+ */
8713
+ MonoClass *
8714
+ mono_generic_param_get_base_type (MonoClass * klass )
8715
+ {
8716
+ MonoType * type = & klass -> byval_arg ;
8717
+ g_assert (mono_type_is_generic_argument (type ));
8718
+
8719
+ MonoGenericParam * gparam = type -> data .generic_param ;
8720
+
8721
+ g_assert (gparam -> owner && !gparam -> owner -> is_anonymous );
8722
+
8723
+ MonoClass * * constraints = mono_generic_container_get_param_info (gparam -> owner , gparam -> num )-> constraints ;
8724
+
8725
+ MonoClass * base_class = mono_defaults .object_class ;
8726
+
8727
+ if (constraints ) {
8728
+ int i ;
8729
+ for (i = 0 ; constraints [i ]; ++ i ) {
8730
+ MonoClass * constraint = constraints [i ];
8731
+
8732
+ if (MONO_CLASS_IS_INTERFACE_INTERNAL (constraint ))
8733
+ continue ;
8734
+
8735
+ MonoType * constraint_type = & constraint -> byval_arg ;
8736
+ if (mono_type_is_generic_argument (constraint_type )) {
8737
+ MonoGenericParam * constraint_param = constraint_type -> data .generic_param ;
8738
+ MonoGenericParamInfo * constraint_info = mono_generic_param_info (constraint_param );
8739
+ if ((constraint_info -> flags & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT ) == 0 &&
8740
+ (constraint_info -> flags & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT ) == 0 )
8741
+ continue ;
8742
+ }
8743
+
8744
+ base_class = constraint ;
8745
+ }
8746
+
8747
+ }
8748
+
8749
+ if (base_class == mono_defaults .object_class )
8750
+ {
8751
+ MonoGenericParamInfo * gparam_info = mono_generic_param_info (gparam );
8752
+ if ((gparam_info -> flags & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT ) != 0 ) {
8753
+ base_class = mono_class_get_valuetype_class ();
8754
+ }
8755
+ }
8756
+
8757
+ return base_class ;
8758
+ }
8759
+
8648
8760
/**
8649
8761
* mono_class_get_cctor:
8650
8762
* \param klass A MonoClass pointer
0 commit comments