[hybrid] Ensure gsharedvt isn't disabled once it's been enabled
[mono.git] / mono / mini / mini-generic-sharing.c
index 3b55b58689c3eec7ce46bff99fe168499a063582..687249e0939c186124a5fceea4c7f5b6cde75cb6 100644 (file)
@@ -76,7 +76,7 @@ type_check_context_used (MonoType *type, gboolean recursive)
                if (recursive) {
                        MonoGenericClass *gclass = type->data.generic_class;
 
-                       g_assert (gclass->container_class->generic_container);
+                       g_assert (mono_class_is_gtd (gclass->container_class));
                        return mono_generic_context_check_used (&gclass->context);
                } else {
                        return 0;
@@ -137,10 +137,10 @@ mono_class_check_context_used (MonoClass *klass)
        context_used |= type_check_context_used (&klass->this_arg, FALSE);
        context_used |= type_check_context_used (&klass->byval_arg, FALSE);
 
-       if (klass->generic_class)
-               context_used |= mono_generic_context_check_used (&klass->generic_class->context);
-       else if (klass->generic_container)
-               context_used |= mono_generic_context_check_used (&klass->generic_container->context);
+       if (mono_class_is_ginst (klass))
+               context_used |= mono_generic_context_check_used (&mono_class_get_generic_class (klass)->context);
+       else if (mono_class_is_gtd (klass))
+               context_used |= mono_generic_context_check_used (&mono_class_get_generic_container (klass)->context);
 
        return context_used;
 }
@@ -274,8 +274,8 @@ register_generic_subclass (MonoClass *klass)
 
        g_assert (rgctx_template);
 
-       if (parent->generic_class)
-               parent = parent->generic_class->container_class;
+       if (mono_class_is_ginst (parent))
+               parent = mono_class_get_generic_class (parent)->container_class;
 
        if (!generic_subclass_hash)
                generic_subclass_hash = g_hash_table_new (mono_aligned_addr_hash, NULL);
@@ -475,21 +475,22 @@ mono_class_get_method_generic (MonoClass *klass, MonoMethod *method)
                declaring = method;
 
        m = NULL;
-       if (klass->generic_class)
+       if (mono_class_is_ginst (klass))
                m = mono_class_get_inflated_method (klass, declaring);
 
        if (!m) {
                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;
        }
 
@@ -607,6 +608,7 @@ inflate_info (MonoRuntimeGenericContextInfoTemplate *oti, MonoGenericContext *co
                MonoMethod *inflated_method;
                MonoType *inflated_type = mono_class_inflate_generic_type_checked (&method->klass->byval_arg, context, &error);
                mono_error_assert_ok (&error); /* FIXME don't swallow the error */
+               WrapperInfo *winfo = NULL;
 
                MonoClass *inflated_class = mono_class_from_mono_type (inflated_type);
                MonoJumpInfoGSharedVtCall *res;
@@ -620,7 +622,13 @@ inflate_info (MonoRuntimeGenericContextInfoTemplate *oti, MonoGenericContext *co
 
                mono_class_init (inflated_class);
 
-               g_assert (!method->wrapper_type);
+               if (method->wrapper_type) {
+                       winfo = mono_marshal_get_wrapper_info (method);
+
+                       g_assert (winfo);
+                       g_assert (winfo->subtype == WRAPPER_SUBTYPE_SYNCHRONIZED_INNER);
+                       method = winfo->d.synchronized_inner.method;
+               }
 
                if (inflated_class->byval_arg.type == MONO_TYPE_ARRAY ||
                                inflated_class->byval_arg.type == MONO_TYPE_SZARRAY) {
@@ -633,6 +641,12 @@ inflate_info (MonoRuntimeGenericContextInfoTemplate *oti, MonoGenericContext *co
                }
                mono_class_init (inflated_method->klass);
                g_assert (inflated_method->klass == inflated_class);
+
+               if (winfo) {
+                       g_assert (winfo->subtype == WRAPPER_SUBTYPE_SYNCHRONIZED_INNER);
+                       inflated_method = mono_marshal_get_synchronized_inner_wrapper (inflated_method);
+               }
+
                res->method = inflated_method;
 
                return res;
@@ -721,8 +735,8 @@ class_get_rgctx_template_oti (MonoClass *klass, int type_argc, guint32 slot, gbo
 static MonoClass*
 class_uninstantiated (MonoClass *klass)
 {
-       if (klass->generic_class)
-               return klass->generic_class->container_class;
+       if (mono_class_is_ginst (klass))
+               return mono_class_get_generic_class (klass)->container_class;
        return klass;
 }
 
@@ -822,15 +836,15 @@ class_get_rgctx_template_oti (MonoClass *klass, int type_argc, guint32 slot, gbo
 
        DEBUG (printf ("get slot: %s %d\n", mono_type_full_name (&class->byval_arg), slot));
 
-       if (klass->generic_class && !shared) {
+       if (mono_class_is_ginst (klass) && !shared) {
                MonoRuntimeGenericContextInfoTemplate oti;
                gboolean tmp_do_free;
 
-               oti = class_get_rgctx_template_oti (klass->generic_class->container_class,
+               oti = class_get_rgctx_template_oti (mono_class_get_generic_class (klass)->container_class,
                                                                                        type_argc, slot, TRUE, FALSE, &tmp_do_free);
                if (oti.data) {
                        gpointer info = oti.data;
-                       oti.data = inflate_info (&oti, &klass->generic_class->context, klass, temporary);
+                       oti.data = inflate_info (&oti, &mono_class_get_generic_class (klass)->context, klass, temporary);
                        if (tmp_do_free)
                                free_inflated_info (oti.info_type, info);
                }
@@ -862,7 +876,7 @@ class_type_info (MonoDomain *domain, MonoClass *klass, MonoRgctxInfoType info_ty
        case MONO_RGCTX_INFO_STATIC_DATA: {
                MonoVTable *vtable = mono_class_vtable (domain, klass);
                if (!vtable) {
-                       mono_error_set_exception_instance (error, mono_class_get_exception_for_failure (klass));
+                       mono_error_set_for_class_failure (error, klass);
                        return NULL;
                }
                return mono_vtable_get_static_field_data (vtable);
@@ -874,7 +888,7 @@ class_type_info (MonoDomain *domain, MonoClass *klass, MonoRgctxInfoType info_ty
        case MONO_RGCTX_INFO_VTABLE: {
                MonoVTable *vtable = mono_class_vtable (domain, klass);
                if (!vtable) {
-                       mono_error_set_exception_instance (error, mono_class_get_exception_for_failure (klass));
+                       mono_error_set_for_class_failure (error, klass);
                        return NULL;
                }
                return vtable;
@@ -936,9 +950,10 @@ class_type_info (MonoDomain *domain, MonoClass *klass, MonoRgctxInfoType info_ty
                                memcpy_method [size] = m;
                        }
                        if (!domain_info->memcpy_addr [size]) {
-                               gpointer addr = mono_compile_method (memcpy_method [size]);
+                               gpointer addr = mono_compile_method_checked (memcpy_method [size], error);
                                mono_memory_barrier ();
                                domain_info->memcpy_addr [size] = (gpointer *)addr;
+                               mono_error_assert_ok (error);
                        }
                        return domain_info->memcpy_addr [size];
                } else {
@@ -956,9 +971,10 @@ class_type_info (MonoDomain *domain, MonoClass *klass, MonoRgctxInfoType info_ty
                                bzero_method [size] = m;
                        }
                        if (!domain_info->bzero_addr [size]) {
-                               gpointer addr = mono_compile_method (bzero_method [size]);
+                               gpointer addr = mono_compile_method_checked (bzero_method [size], error);
                                mono_memory_barrier ();
                                domain_info->bzero_addr [size] = (gpointer *)addr;
+                               mono_error_assert_ok (error);
                        }
                        return domain_info->bzero_addr [size];
                }
@@ -1100,10 +1116,10 @@ get_wrapper_shared_type (MonoType *t)
                int i;
 
                if (!MONO_TYPE_ISSTRUCT (t))
-                       return &mono_defaults.int_class->byval_arg;
+                       return get_wrapper_shared_type (&mono_defaults.object_class->byval_arg);
 
                klass = mono_class_from_mono_type (t);
-               orig_ctx = &klass->generic_class->context;
+               orig_ctx = &mono_class_get_generic_class (klass)->context;
 
                memset (&ctx, 0, sizeof (MonoGenericContext));
 
@@ -1121,7 +1137,7 @@ get_wrapper_shared_type (MonoType *t)
                                args [i] = get_wrapper_shared_type (inst->type_argv [i]);
                        ctx.method_inst = mono_metadata_get_generic_inst (inst->type_argc, args);
                }
-               klass = mono_class_inflate_generic_class_checked (klass->generic_class->container_class, &ctx, &error);
+               klass = mono_class_inflate_generic_class_checked (mono_class_get_generic_class (klass)->container_class, &ctx, &error);
                mono_error_assert_ok (&error); /* FIXME don't swallow the error */
                return &klass->byval_arg;
        }
@@ -1168,7 +1184,7 @@ mini_get_gsharedvt_in_sig_wrapper (MonoMethodSignature *sig)
        MonoMethod *res, *cached;
        WrapperInfo *info;
        MonoMethodSignature *csig, *gsharedvt_sig;
-       int i, pindex, retval_var;
+       int i, pindex, retval_var = 0;
        static GHashTable *cache;
 
        // FIXME: Memory management
@@ -1418,6 +1434,7 @@ mini_get_gsharedvt_wrapper (gboolean gsharedvt_in, gpointer addr, MonoMethodSign
 {
        static gboolean inited = FALSE;
        static int num_trampolines;
+       MonoError error;
        gpointer res, info;
        MonoDomain *domain = mono_domain_get ();
        MonoJitDomainInfo *domain_info;
@@ -1436,7 +1453,8 @@ mini_get_gsharedvt_wrapper (gboolean gsharedvt_in, gpointer addr, MonoMethodSign
                        wrapper = mini_get_gsharedvt_in_sig_wrapper (normal_sig);
                else
                        wrapper = mini_get_gsharedvt_out_sig_wrapper (normal_sig);
-               res = mono_compile_method (wrapper);
+               res = mono_compile_method_checked (wrapper, &error);
+               mono_error_assert_ok (&error);
                return res;
        }
 
@@ -1469,8 +1487,9 @@ mini_get_gsharedvt_wrapper (gboolean gsharedvt_in, gpointer addr, MonoMethodSign
 
                if (!tramp_addr) {
                        wrapper = mono_marshal_get_gsharedvt_in_wrapper ();
-                       addr = mono_compile_method (wrapper);
+                       addr = mono_compile_method_checked (wrapper, &error);
                        mono_memory_barrier ();
+                       mono_error_assert_ok (&error);
                        tramp_addr = addr;
                }
                addr = tramp_addr;
@@ -1480,8 +1499,9 @@ mini_get_gsharedvt_wrapper (gboolean gsharedvt_in, gpointer addr, MonoMethodSign
 
                if (!tramp_addr) {
                        wrapper = mono_marshal_get_gsharedvt_out_wrapper ();
-                       addr = mono_compile_method (wrapper);
+                       addr = mono_compile_method_checked (wrapper, &error);
                        mono_memory_barrier ();
+                       mono_error_assert_ok (&error);
                        tramp_addr = addr;
                }
                addr = tramp_addr;
@@ -1578,13 +1598,15 @@ instantiate_info (MonoDomain *domain, MonoRuntimeGenericContextInfoTemplate *oti
                gpointer arg = NULL;
 
                if (mono_llvm_only) {
-                       addr = mono_compile_method (m);
+                       addr = mono_compile_method_checked (m, error);
+                       return_val_if_nok (error, NULL);
                        addr = mini_add_method_wrappers_llvmonly (m, addr, FALSE, FALSE, &arg);
 
                        /* Returns an ftndesc */
                        return mini_create_llvmonly_ftndesc (domain, addr, arg);
                } else {
-                       addr = mono_compile_method ((MonoMethod *)data);
+                       addr = mono_compile_method_checked ((MonoMethod *)data, error);
+                       return_val_if_nok (error, NULL);
                        return mini_add_method_trampoline ((MonoMethod *)data, addr, mono_method_needs_static_rgctx_invoke ((MonoMethod *)data, FALSE), FALSE);
                }
        }
@@ -1595,7 +1617,8 @@ instantiate_info (MonoDomain *domain, MonoRuntimeGenericContextInfoTemplate *oti
 
                g_assert (mono_llvm_only);
 
-               addr = mono_compile_method (m);
+               addr = mono_compile_method_checked (m, error);
+               return_val_if_nok (error, NULL);
 
                MonoJitInfo *ji;
                gboolean callee_gsharedvt;
@@ -1624,7 +1647,7 @@ instantiate_info (MonoDomain *domain, MonoRuntimeGenericContextInfoTemplate *oti
 
                mono_class_setup_vtable (info->klass);
                // FIXME: Check type load
-               if (iface_class->flags & TYPE_ATTRIBUTE_INTERFACE) {
+               if (mono_class_is_interface (iface_class)) {
                        ioffset = mono_class_interface_offset (info->klass, iface_class);
                        g_assert (ioffset != -1);
                } else {
@@ -1636,9 +1659,9 @@ instantiate_info (MonoDomain *domain, MonoRuntimeGenericContextInfoTemplate *oti
                method = info->klass->vtable [ioffset + slot];
 
                method = mono_class_inflate_generic_method_checked (method, context, error);
-               if (!mono_error_ok (error))
-                       return NULL;
-               addr = mono_compile_method (method);
+               return_val_if_nok (error, NULL);
+               addr = mono_compile_method_checked (method, error);
+               return_val_if_nok (error, NULL);
                return mini_add_method_trampoline (method, addr, mono_method_needs_static_rgctx_invoke (method, FALSE), FALSE);
        }
        case MONO_RGCTX_INFO_VIRT_METHOD_BOX_TYPE: {
@@ -1650,7 +1673,7 @@ instantiate_info (MonoDomain *domain, MonoRuntimeGenericContextInfoTemplate *oti
 
                mono_class_setup_vtable (info->klass);
                // FIXME: Check type load
-               if (iface_class->flags & TYPE_ATTRIBUTE_INTERFACE) {
+               if (mono_class_is_interface (iface_class)) {
                        ioffset = mono_class_interface_offset (info->klass, iface_class);
                        g_assert (ioffset != -1);
                } else {
@@ -1671,7 +1694,7 @@ instantiate_info (MonoDomain *domain, MonoRuntimeGenericContextInfoTemplate *oti
        }
 #ifndef DISABLE_REMOTING
        case MONO_RGCTX_INFO_REMOTING_INVOKE_WITH_CHECK:
-               return mono_compile_method (mono_marshal_get_remoting_invoke_with_check ((MonoMethod *)data));
+               return mono_compile_method_checked (mono_marshal_get_remoting_invoke_with_check ((MonoMethod *)data), error);
 #endif
        case MONO_RGCTX_INFO_METHOD_DELEGATE_CODE:
                return mono_domain_alloc0 (domain, sizeof (gpointer));
@@ -1695,7 +1718,7 @@ instantiate_info (MonoDomain *domain, MonoRuntimeGenericContextInfoTemplate *oti
 
                vtable = mono_class_vtable (domain, method->method.method.klass);
                if (!vtable) {
-                       mono_error_set_exception_instance (error, mono_class_get_exception_for_failure (method->method.method.klass));
+                       mono_error_set_for_class_failure (error, method->method.method.klass);
                        return NULL;
                }
 
@@ -1749,9 +1772,13 @@ instantiate_info (MonoDomain *domain, MonoRuntimeGenericContextInfoTemplate *oti
 
                g_assert (method->is_inflated);
 
-               if (!virtual_)
-                       addr = mono_compile_method (method);
-               else
+               if (mono_llvm_only && (method->iflags & METHOD_IMPL_ATTRIBUTE_SYNCHRONIZED))
+                       method = mono_marshal_get_synchronized_wrapper (method);
+
+               if (!virtual_) {
+                       addr = mono_compile_method_checked (method, error);
+                       return_val_if_nok (error, NULL);
+               } else
                        addr = NULL;
 
                if (virtual_) {
@@ -1760,7 +1787,7 @@ instantiate_info (MonoDomain *domain, MonoRuntimeGenericContextInfoTemplate *oti
                                /* See mono_emit_method_call_full () */
                                /* The gsharedvt trampoline will recognize this constant */
                                vcall_offset = MONO_GSHAREDVT_DEL_INVOKE_VT_OFFSET;
-                       } else if (method->klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
+                       } else if (mono_class_is_interface (method->klass)) {
                                guint32 imt_slot = mono_method_get_imt_slot (method);
                                vcall_offset = ((gint32)imt_slot - MONO_IMT_SIZE) * SIZEOF_VOID_P;
                        } else {
@@ -2032,8 +2059,8 @@ register_info (MonoClass *klass, int type_argc, gpointer data, MonoRgctxInfoType
                MonoRuntimeGenericContextTemplate *parent_template;
                MonoRuntimeGenericContextInfoTemplate *oti;
 
-               if (parent->generic_class)
-                       parent = parent->generic_class->container_class;
+               if (mono_class_is_ginst (parent))
+                       parent = mono_class_get_generic_class (parent)->container_class;
 
                parent_template = mono_class_get_runtime_generic_context_template (parent);
                oti = rgctx_template_get_other_slot (parent_template, type_argc, i);
@@ -2287,7 +2314,7 @@ fill_runtime_generic_context (MonoVTable *class_vtable, MonoRuntimeGenericContex
        int i, first_slot, size;
        MonoDomain *domain = class_vtable->domain;
        MonoClass *klass = class_vtable->klass;
-       MonoGenericContext *class_context = klass->generic_class ? &klass->generic_class->context : NULL;
+       MonoGenericContext *class_context = mono_class_is_ginst (klass) ? &mono_class_get_generic_class (klass)->context : NULL;
        MonoRuntimeGenericContextInfoTemplate oti;
        MonoGenericContext context = { class_context ? class_context->class_inst : NULL, method_inst };
        int rgctx_index;
@@ -2338,6 +2365,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);
 
        /*
@@ -2457,7 +2485,7 @@ mono_method_lookup_rgctx (MonoVTable *class_vtable, MonoGenericInst *method_inst
        MonoMethodRuntimeGenericContext *mrgctx;
        MonoMethodRuntimeGenericContext key;
 
-       g_assert (!class_vtable->klass->generic_container);
+       g_assert (!mono_class_is_gtd (class_vtable->klass));
        g_assert (!method_inst->is_open);
 
        mono_domain_lock (domain);
@@ -2608,7 +2636,7 @@ mono_method_is_generic_impl (MonoMethod *method)
           if not compiled with sharing. */
        if (method->wrapper_type != MONO_WRAPPER_NONE)
                return FALSE;
-       if (method->klass->generic_container)
+       if (mono_class_is_gtd (method->klass))
                return TRUE;
        return FALSE;
 }
@@ -2760,18 +2788,18 @@ mono_method_is_generic_sharable_full (MonoMethod *method, gboolean allow_type_va
                }
        }
 
-       if (method->klass->generic_class) {
-               if (!mono_generic_context_is_sharable_full (&method->klass->generic_class->context, allow_type_vars, allow_partial))
+       if (mono_class_is_ginst (method->klass)) {
+               if (!mono_generic_context_is_sharable_full (&mono_class_get_generic_class (method->klass)->context, allow_type_vars, allow_partial))
                        return FALSE;
 
-               g_assert (method->klass->generic_class->container_class &&
-                               method->klass->generic_class->container_class->generic_container);
+               g_assert (mono_class_get_generic_class (method->klass)->container_class &&
+                               mono_class_is_gtd (mono_class_get_generic_class (method->klass)->container_class));
 
-               if (has_constraints (method->klass->generic_class->container_class->generic_container))
+               if (has_constraints (mono_class_get_generic_container (mono_class_get_generic_class (method->klass)->container_class)))
                        return FALSE;
        }
 
-       if (method->klass->generic_container && !allow_type_vars)
+       if (mono_class_is_gtd (method->klass) && !allow_type_vars)
                return FALSE;
 
        /* This does potentially expensive cattr checks, so do it at the end */
@@ -2812,7 +2840,7 @@ mono_method_needs_static_rgctx_invoke (MonoMethod *method, gboolean allow_type_v
 
        return ((method->flags & METHOD_ATTRIBUTE_STATIC) ||
                        method->klass->valuetype) &&
-               (method->klass->generic_class || method->klass->generic_container);
+               (mono_class_is_ginst (method->klass) || mono_class_is_gtd (method->klass));
 }
 
 static MonoGenericInst*
@@ -2841,9 +2869,9 @@ mono_method_construct_object_context (MonoMethod *method)
 {
        MonoGenericContext object_context;
 
-       g_assert (!method->klass->generic_class);
-       if (method->klass->generic_container) {
-               int type_argc = method->klass->generic_container->type_argc;
+       g_assert (!mono_class_is_ginst (method->klass));
+       if (mono_class_is_gtd (method->klass)) {
+               int type_argc = mono_class_get_generic_container (method->klass)->type_argc;
 
                object_context.class_inst = get_object_generic_inst (type_argc);
        } else {
@@ -2977,10 +3005,10 @@ mono_generic_context_equal_deep (MonoGenericContext *context1, MonoGenericContex
 MonoClass*
 mini_class_get_container_class (MonoClass *klass)
 {
-       if (klass->generic_class)
-               return klass->generic_class->container_class;
+       if (mono_class_is_ginst (klass))
+               return mono_class_get_generic_class (klass)->container_class;
 
-       g_assert (klass->generic_container);
+       g_assert (mono_class_is_gtd (klass));
        return klass;
 }
 
@@ -2993,11 +3021,11 @@ mini_class_get_container_class (MonoClass *klass)
 MonoGenericContext*
 mini_class_get_context (MonoClass *klass)
 {
-       if (klass->generic_class)
-               return &klass->generic_class->context;
+       if (mono_class_is_ginst (klass))
+               return &mono_class_get_generic_class (klass)->context;
 
-       g_assert (klass->generic_container);
-       return &klass->generic_container->context;
+       g_assert (mono_class_is_gtd (klass));
+       return &mono_class_get_generic_container (klass)->context;
 }
 
 /*
@@ -3179,10 +3207,10 @@ mini_type_is_vtype (MonoType *t)
 gboolean
 mini_class_is_generic_sharable (MonoClass *klass)
 {
-       if (klass->generic_class && is_async_state_machine_class (klass))
+       if (mono_class_is_ginst (klass) && is_async_state_machine_class (klass))
                return FALSE;
 
-       return (klass->generic_class && mono_generic_context_is_sharable (&klass->generic_class->context, FALSE));
+       return (mono_class_is_ginst (klass) && mono_generic_context_is_sharable (&mono_class_get_generic_class (klass)->context, FALSE));
 }
 
 gboolean
@@ -3325,9 +3353,9 @@ get_shared_type (MonoType *t, MonoType *type)
 
                memset (&context, 0, sizeof (context));
                if (gclass->context.class_inst)
-                       context.class_inst = get_shared_inst (gclass->context.class_inst, gclass->container_class->generic_container->context.class_inst, NULL, FALSE, FALSE, TRUE);
+                       context.class_inst = get_shared_inst (gclass->context.class_inst, mono_class_get_generic_container (gclass->container_class)->context.class_inst, NULL, FALSE, FALSE, TRUE);
                if (gclass->context.method_inst)
-                       context.method_inst = get_shared_inst (gclass->context.method_inst, gclass->container_class->generic_container->context.method_inst, NULL, FALSE, FALSE, TRUE);
+                       context.method_inst = get_shared_inst (gclass->context.method_inst, mono_class_get_generic_container (gclass->container_class)->context.method_inst, NULL, FALSE, FALSE, TRUE);
 
                k = mono_class_inflate_generic_class_checked (gclass->container_class, &context, &error);
                mono_error_assert_ok (&error); /* FIXME don't swallow the error */
@@ -3410,7 +3438,27 @@ mini_get_shared_method_full (MonoMethod *method, gboolean all_vt, gboolean is_gs
        MonoGenericContext *context = mono_method_get_context (method);
        MonoGenericInst *inst;
 
-       if (method->is_generic || (method->klass->generic_container && !method->is_inflated)) {
+       /*
+        * Instead of creating a shared version of the wrapper, create a shared version of the original
+        * method and construct a wrapper for it. Otherwise, we could end up with two copies of the
+        * same wrapper, breaking AOT which assumes wrappers are unique.
+        * FIXME: Add other cases.
+        */
+       if (method->wrapper_type == MONO_WRAPPER_SYNCHRONIZED) {
+               MonoMethod *wrapper = mono_marshal_method_from_wrapper (method);
+
+               return mono_marshal_get_synchronized_wrapper (mini_get_shared_method_full (wrapper, all_vt, is_gsharedvt));
+       }
+       if (method->wrapper_type == MONO_WRAPPER_DELEGATE_INVOKE) {
+               WrapperInfo *info = mono_marshal_get_wrapper_info (method);
+
+               if (info->subtype == WRAPPER_SUBTYPE_NONE) {
+                       MonoMethod *m = mono_marshal_get_delegate_invoke (mini_get_shared_method_full (info->d.delegate_invoke.method, all_vt, is_gsharedvt), NULL);
+                       return m;
+               }
+       }
+
+       if (method->is_generic || (mono_class_is_gtd (method->klass) && !method->is_inflated)) {
                declaring_method = method;
        } else {
                declaring_method = mono_method_get_declaring_generic_method (method);
@@ -3420,14 +3468,14 @@ mini_get_shared_method_full (MonoMethod *method, gboolean all_vt, gboolean is_gs
        if (declaring_method->is_generic)
                shared_context = mono_method_get_generic_container (declaring_method)->context;
        else
-               shared_context = declaring_method->klass->generic_container->context;
+               shared_context = mono_class_get_generic_container (declaring_method->klass)->context;
 
        if (!is_gsharedvt)
                partial = mono_method_is_generic_sharable_full (method, FALSE, TRUE, FALSE);
 
        gsharedvt = is_gsharedvt || (!partial && mini_is_gsharedvt_sharable_method (method));
 
-       class_container = declaring_method->klass->generic_container;
+       class_container = mono_class_try_get_generic_container (declaring_method->klass); //FIXME is this a case for a try_get?
        method_container = mono_method_get_generic_container (declaring_method);
 
        /*
@@ -3529,7 +3577,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