[jit] Implement RuntimeHelpers.IsReferenceOrContainsReferences intrinsic. Fixes ...
[mono.git] / mono / mini / mini-generic-sharing.c
index 07174330eb2ae3c8d85f8eb6122e605f6827a9fc..58fcaac9c82d59ae4b4317013f16d5531c6c2202 100644 (file)
@@ -482,14 +482,15 @@ mono_class_get_method_generic (MonoClass *klass, MonoMethod *method)
                mono_class_setup_methods (klass);
                if (mono_class_has_failure (klass))
                        return NULL;
-               for (i = 0; i < klass->method.count; ++i) {
+               int mcount = mono_class_get_method_count (klass);
+               for (i = 0; i < mcount; ++i) {
                        m = klass->methods [i];
                        if (m == declaring)
                                break;
                        if (m->is_inflated && mono_method_get_declaring_generic_method (m) == declaring)
                                break;
                }
-               if (i >= klass->method.count)
+               if (i >= mcount)
                        return NULL;
        }
 
@@ -531,6 +532,7 @@ inflate_info (MonoRuntimeGenericContextInfoTemplate *oti, MonoGenericContext *co
        case MONO_RGCTX_INFO_ARRAY_ELEMENT_SIZE:
        case MONO_RGCTX_INFO_VALUE_SIZE:
        case MONO_RGCTX_INFO_CLASS_BOX_TYPE:
+       case MONO_RGCTX_INFO_CLASS_IS_REF_OR_CONTAINS_REFS:
        case MONO_RGCTX_INFO_MEMCPY:
        case MONO_RGCTX_INFO_BZERO:
        case MONO_RGCTX_INFO_LOCAL_OFFSET:
@@ -869,7 +871,7 @@ class_get_rgctx_template_oti (MonoClass *klass, int type_argc, guint32 slot, gbo
 static gpointer
 class_type_info (MonoDomain *domain, MonoClass *klass, MonoRgctxInfoType info_type, MonoError *error)
 {
-       mono_error_init (error);
+       error_init (error);
 
        switch (info_type) {
        case MONO_RGCTX_INFO_STATIC_DATA: {
@@ -912,6 +914,13 @@ class_type_info (MonoDomain *domain, MonoClass *klass, MonoRgctxInfoType info_ty
                        return GUINT_TO_POINTER (MONO_GSHAREDVT_BOX_TYPE_NULLABLE);
                else
                        return GUINT_TO_POINTER (MONO_GSHAREDVT_BOX_TYPE_VTYPE);
+       case MONO_RGCTX_INFO_CLASS_IS_REF_OR_CONTAINS_REFS:
+               mono_class_init (klass);
+               /* Can't return 0 */
+               if (MONO_TYPE_IS_REFERENCE (&klass->byval_arg) || klass->has_references)
+                       return GUINT_TO_POINTER (2);
+               else
+                       return GUINT_TO_POINTER (1);
        case MONO_RGCTX_INFO_MEMCPY:
        case MONO_RGCTX_INFO_BZERO: {
                static MonoMethod *memcpy_method [17];
@@ -1537,7 +1546,7 @@ instantiate_info (MonoDomain *domain, MonoRuntimeGenericContextInfoTemplate *oti
        gpointer data;
        gboolean temporary;
 
-       mono_error_init (error);
+       error_init (error);
 
        if (!oti->data)
                return NULL;
@@ -1565,6 +1574,7 @@ instantiate_info (MonoDomain *domain, MonoRuntimeGenericContextInfoTemplate *oti
        case MONO_RGCTX_INFO_ARRAY_ELEMENT_SIZE:
        case MONO_RGCTX_INFO_VALUE_SIZE:
        case MONO_RGCTX_INFO_CLASS_BOX_TYPE:
+       case MONO_RGCTX_INFO_CLASS_IS_REF_OR_CONTAINS_REFS:
        case MONO_RGCTX_INFO_MEMCPY:
        case MONO_RGCTX_INFO_BZERO:
        case MONO_RGCTX_INFO_NULLABLE_CLASS_BOX:
@@ -2006,6 +2016,7 @@ mono_rgctx_info_type_to_str (MonoRgctxInfoType type)
        case MONO_RGCTX_INFO_ARRAY_ELEMENT_SIZE: return "ARRAY_ELEMENT_SIZE";
        case MONO_RGCTX_INFO_VALUE_SIZE: return "VALUE_SIZE";
        case MONO_RGCTX_INFO_CLASS_BOX_TYPE: return "CLASS_BOX_TYPE";
+       case MONO_RGCTX_INFO_CLASS_IS_REF_OR_CONTAINS_REFS: return "CLASS_IS_REF_OR_CONTAINS_REFS";
        case MONO_RGCTX_INFO_FIELD_OFFSET: return "FIELD_OFFSET";
        case MONO_RGCTX_INFO_METHOD_GSHAREDVT_OUT_TRAMPOLINE: return "METHOD_GSHAREDVT_OUT_TRAMPOLINE";
        case MONO_RGCTX_INFO_METHOD_GSHAREDVT_OUT_TRAMPOLINE_VIRT: return "METHOD_GSHAREDVT_OUT_TRAMPOLINE_VIRT";
@@ -2094,6 +2105,7 @@ info_equal (gpointer data1, gpointer data2, MonoRgctxInfoType info_type)
        case MONO_RGCTX_INFO_ARRAY_ELEMENT_SIZE:
        case MONO_RGCTX_INFO_VALUE_SIZE:
        case MONO_RGCTX_INFO_CLASS_BOX_TYPE:
+       case MONO_RGCTX_INFO_CLASS_IS_REF_OR_CONTAINS_REFS:
        case MONO_RGCTX_INFO_MEMCPY:
        case MONO_RGCTX_INFO_BZERO:
        case MONO_RGCTX_INFO_NULLABLE_CLASS_BOX:
@@ -2147,6 +2159,7 @@ mini_rgctx_info_type_to_patch_info_type (MonoRgctxInfoType info_type)
        case MONO_RGCTX_INFO_ARRAY_ELEMENT_SIZE:
        case MONO_RGCTX_INFO_VALUE_SIZE:
        case MONO_RGCTX_INFO_CLASS_BOX_TYPE:
+       case MONO_RGCTX_INFO_CLASS_IS_REF_OR_CONTAINS_REFS:
        case MONO_RGCTX_INFO_MEMCPY:
        case MONO_RGCTX_INFO_BZERO:
        case MONO_RGCTX_INFO_NULLABLE_CLASS_BOX:
@@ -2319,7 +2332,7 @@ fill_runtime_generic_context (MonoVTable *class_vtable, MonoRuntimeGenericContex
        int rgctx_index;
        gboolean do_free;
 
-       mono_error_init (error);
+       error_init (error);
 
        g_assert (rgctx);
 
@@ -2364,6 +2377,7 @@ fill_runtime_generic_context (MonoVTable *class_vtable, MonoRuntimeGenericContex
                                                                                method_inst ? method_inst->type_argc : 0, slot, TRUE, TRUE, &do_free);
        /* This might take the loader lock */
        info = instantiate_info (domain, &oti, &context, klass, error);
+       return_val_if_nok (error, NULL);
        g_assert (info);
 
        /*
@@ -2406,7 +2420,7 @@ mono_class_fill_runtime_generic_context (MonoVTable *class_vtable, guint32 slot,
        MonoRuntimeGenericContext *rgctx;
        gpointer info;
 
-       mono_error_init (error);
+       error_init (error);
 
        mono_domain_lock (domain);
 
@@ -2671,7 +2685,7 @@ mini_method_is_open (MonoMethod *method)
 }
 
 /* Lazy class loading functions */
-static GENERATE_TRY_GET_CLASS_WITH_CACHE (iasync_state_machine, System.Runtime.CompilerServices, IAsyncStateMachine)
+static GENERATE_TRY_GET_CLASS_WITH_CACHE (iasync_state_machine, "System.Runtime.CompilerServices", "IAsyncStateMachine")
 
 static G_GNUC_UNUSED gboolean
 is_async_state_machine_class (MonoClass *klass)
@@ -3575,7 +3589,9 @@ static gboolean gsharedvt_supported;
 void
 mono_set_generic_sharing_vt_supported (gboolean supported)
 {
-       gsharedvt_supported = supported;
+       /* ensure we do not disable gsharedvt once it's been enabled */
+       if (!gsharedvt_supported  && supported)
+               gsharedvt_supported = TRUE;
 }
 
 #ifdef MONO_ARCH_GSHAREDVT_SUPPORTED