Merge pull request #1936 from esdrubal/DotNetRelativeOrAbsolute
[mono.git] / mono / metadata / marshal.c
index 9292a1f14d206875dd19b3483d61333eedaa2207..4c6ae67820d24b42774f5805cb50cda488060a20 100644 (file)
@@ -27,6 +27,7 @@
 #include "mono/metadata/debug-helpers.h"
 #include "mono/metadata/threads.h"
 #include "mono/metadata/monitor.h"
+#include "mono/metadata/class-internals.h"
 #include "mono/metadata/metadata-internals.h"
 #include "mono/metadata/domain-internals.h"
 #include "mono/metadata/gc-internal.h"
@@ -160,25 +161,12 @@ register_icall (gpointer func, const char *name, const char *sigstr, gboolean sa
        mono_register_jit_icall (func, name, sig, save);
 }
 
-static MonoMethodSignature*
-signature_dup (MonoImage *image, MonoMethodSignature *sig)
-{
-       MonoMethodSignature *res;
-       int sigsize;
-
-       res = mono_metadata_signature_alloc (image, sig->param_count);
-       sigsize = MONO_SIZEOF_METHOD_SIGNATURE + sig->param_count * sizeof (MonoType *);
-       memcpy (res, sig, sigsize);
-
-       return res;
-}
-
 MonoMethodSignature*
 mono_signature_no_pinvoke (MonoMethod *method)
 {
        MonoMethodSignature *sig = mono_method_signature (method);
        if (sig->pinvoke) {
-               sig = signature_dup (method->klass->image, sig);
+               sig = mono_metadata_signature_dup_full (method->klass->image, sig);
                sig->pinvoke = FALSE;
        }
        
@@ -256,8 +244,8 @@ mono_marshal_init (void)
 #ifdef USE_COOP_GC
                register_icall (mono_threads_prepare_blocking, "mono_threads_prepare_blocking", "int", FALSE);
                register_icall (mono_threads_finish_blocking, "mono_threads_finish_blocking", "void int", FALSE);
-               register_icall (mono_threads_reset_blocking_start, "mono_threads_reset_blocking_start","int", FALSE);
-               register_icall (mono_threads_reset_blocking_end, "mono_threads_reset_blocking_end","void int", FALSE);
+               register_icall (mono_threads_reset_blocking_start, "mono_threads_reset_blocking_start","int", TRUE);
+               register_icall (mono_threads_reset_blocking_end, "mono_threads_reset_blocking_end","void int", TRUE);
 #endif
        }
 }
@@ -458,12 +446,12 @@ mono_ftnptr_to_delegate (MonoClass *klass, gpointer ftn)
                MonoMarshalSpec **mspecs;
                MonoMethod *invoke = mono_get_delegate_invoke (klass);
                MonoMethodPInvoke piinfo;
-               MonoObject *this;
+               MonoObject *this_obj;
                int i;
 
                if (use_aot_wrappers) {
                        wrapper = mono_marshal_get_native_func_wrapper_aot (klass);
-                       this = mono_value_box (mono_domain_get (), mono_defaults.int_class, &ftn);
+                       this_obj = mono_value_box (mono_domain_get (), mono_defaults.int_class, &ftn);
                } else {
                        memset (&piinfo, 0, sizeof (piinfo));
                        parse_unmanaged_function_pointer_attr (klass, &piinfo);
@@ -475,7 +463,7 @@ mono_ftnptr_to_delegate (MonoClass *klass, gpointer ftn)
                        sig->hasthis = 0;
 
                        wrapper = mono_marshal_get_native_func_wrapper (klass->image, sig, &piinfo, mspecs, ftn);
-                       this = NULL;
+                       this_obj = NULL;
 
                        for (i = mono_method_signature (invoke)->param_count; i >= 0; i--)
                                if (mspecs [i])
@@ -485,7 +473,7 @@ mono_ftnptr_to_delegate (MonoClass *klass, gpointer ftn)
                }
 
                d = (MonoDelegate*)mono_object_new (mono_domain_get (), klass);
-               mono_delegate_ctor_with_method ((MonoObject*)d, this, mono_compile_method (wrapper), wrapper);
+               mono_delegate_ctor_with_method ((MonoObject*)d, this_obj, mono_compile_method (wrapper), wrapper);
        }
 
        if (d->object.vtable->domain != mono_domain_get ())
@@ -2727,12 +2715,12 @@ mono_marshal_get_delegate_begin_invoke (MonoMethod *method)
         * Check cache
         */
        if (ctx) {
-               cache = get_cache (&method->klass->image->delegate_begin_invoke_generic_cache, mono_aligned_addr_hash, NULL);
+               cache = get_cache (&((MonoMethodInflated*)orig_method)->owner->wrapper_caches.delegate_begin_invoke_cache, mono_aligned_addr_hash, NULL);
                res = check_generic_delegate_wrapper_cache (cache, orig_method, method, ctx);
                if (res)
                        return res;
        } else {
-               cache = get_cache (&method->klass->image->delegate_begin_invoke_cache,
+               cache = get_cache (&method->klass->image->wrapper_caches.delegate_begin_invoke_cache,
                                                   (GHashFunc)mono_signature_hash, 
                                                   (GCompareFunc)mono_metadata_signature_equal);
                if ((res = mono_marshal_find_in_cache (cache, sig)))
@@ -2937,12 +2925,12 @@ mono_marshal_get_delegate_end_invoke (MonoMethod *method)
         * Check cache
         */
        if (ctx) {
-               cache = get_cache (&method->klass->image->delegate_end_invoke_generic_cache, mono_aligned_addr_hash, NULL);
+               cache = get_cache (&((MonoMethodInflated*)orig_method)->owner->wrapper_caches.delegate_end_invoke_cache, mono_aligned_addr_hash, NULL);
                res = check_generic_delegate_wrapper_cache (cache, orig_method, method, ctx);
                if (res)
                        return res;
        } else {
-               cache = get_cache (&method->klass->image->delegate_end_invoke_cache,
+               cache = get_cache (&method->klass->image->wrapper_caches.delegate_end_invoke_cache,
                                                   (GHashFunc)mono_signature_hash, 
                                                   (GCompareFunc)mono_metadata_signature_equal);
                if ((res = mono_marshal_find_in_cache (cache, sig)))
@@ -3096,7 +3084,7 @@ mono_marshal_get_delegate_invoke_internal (MonoMethod *method, gboolean callvirt
         * Check cache
         */
        if (ctx) {
-               cache = get_cache (&method->klass->image->delegate_invoke_generic_cache, mono_aligned_addr_hash, NULL);
+               cache = get_cache (&((MonoMethodInflated*)orig_method)->owner->wrapper_caches.delegate_invoke_cache, mono_aligned_addr_hash, NULL);
                res = check_generic_delegate_wrapper_cache (cache, orig_method, method, ctx);
                if (res)
                        return res;
@@ -3115,7 +3103,7 @@ mono_marshal_get_delegate_invoke_internal (MonoMethod *method, gboolean callvirt
        } else if (callvirt) {
                GHashTable **cache_ptr;
 
-               cache_ptr = &method->klass->image->delegate_abstract_invoke_cache;
+               cache_ptr = &mono_method_get_wrapper_cache (method)->delegate_abstract_invoke_cache;
 
                /* We need to cache the signature+method pair */
                mono_marshal_lock ();
@@ -3129,7 +3117,9 @@ mono_marshal_get_delegate_invoke_internal (MonoMethod *method, gboolean callvirt
                if (res)
                        return res;
        } else {
-               cache = get_cache (&method->klass->image->delegate_invoke_cache,
+               // Inflated methods should not be in this cache because it's not stored on the imageset.
+               g_assert (!method->is_inflated);
+               cache = get_cache (&method->klass->image->wrapper_caches.delegate_invoke_cache,
                                                   (GHashFunc)mono_signature_hash, 
                                                   (GCompareFunc)mono_metadata_signature_equal);
                res = mono_marshal_find_in_cache (cache, sig);
@@ -3138,7 +3128,7 @@ mono_marshal_get_delegate_invoke_internal (MonoMethod *method, gboolean callvirt
                cache_key = sig;
        }
 
-       static_sig = signature_dup (method->klass->image, sig);
+       static_sig = mono_metadata_signature_dup_full (method->klass->image, sig);
        static_sig->hasthis = 0;
        if (!static_method_with_first_arg_bound)
                invoke_sig = static_sig;
@@ -3372,28 +3362,6 @@ mono_marshal_get_delegate_invoke (MonoMethod *method, MonoDelegate *del)
        return mono_marshal_get_delegate_invoke_internal (method, callvirt, static_method_with_first_arg_bound, target_method);
 }
 
-/*
- * signature_dup_add_this:
- *
- *  Make a copy of @sig, adding an explicit this argument.
- */
-static MonoMethodSignature*
-signature_dup_add_this (MonoImage *image, MonoMethodSignature *sig, MonoClass *klass)
-{
-       MonoMethodSignature *res;
-       int i;
-
-       res = mono_metadata_signature_alloc (image, sig->param_count + 1);
-       memcpy (res, sig, MONO_SIZEOF_METHOD_SIGNATURE);
-       res->param_count = sig->param_count + 1;
-       res->hasthis = FALSE;
-       for (i = sig->param_count - 1; i >= 0; i --)
-               res->params [i + 1] = sig->params [i];
-       res->params [0] = klass->valuetype ? &klass->this_arg : &klass->byval_arg;
-
-       return res;
-}
-
 typedef struct {
        MonoMethodSignature *ctor_sig;
        MonoMethodSignature *sig;
@@ -3431,7 +3399,7 @@ add_string_ctor_signature (MonoMethod *method)
        MonoMethodSignature *callsig;
        CtorSigPair *cs;
 
-       callsig = signature_dup (method->klass->image, mono_method_signature (method));
+       callsig = mono_metadata_signature_dup_full (method->klass->image, mono_method_signature (method));
        callsig->ret = &mono_defaults.string_class->byval_arg;
        cs = g_new (CtorSigPair, 1);
        cs->sig = callsig;
@@ -3866,7 +3834,8 @@ mono_marshal_get_runtime_invoke (MonoMethod *method, gboolean virtual)
        if (virtual)
                cache = get_cache (&method->klass->image->runtime_invoke_vcall_cache, mono_aligned_addr_hash, NULL);
        else
-               cache = get_cache (&method->klass->image->runtime_invoke_direct_cache, mono_aligned_addr_hash, NULL);
+               cache = get_cache (&mono_method_get_wrapper_cache (method)->runtime_invoke_direct_cache, mono_aligned_addr_hash, NULL);
+
        res = mono_marshal_find_in_cache (cache, method);
        if (res)
                return res;
@@ -3888,7 +3857,7 @@ mono_marshal_get_runtime_invoke (MonoMethod *method, gboolean virtual)
                need_direct_wrapper = TRUE;
        } else {
                if (method_is_dynamic (method))
-                       callsig = signature_dup (method->klass->image, mono_method_signature (method));
+                       callsig = mono_metadata_signature_dup_full (method->klass->image, mono_method_signature (method));
                else
                        callsig = mono_method_signature (method);
        }
@@ -3910,15 +3879,14 @@ mono_marshal_get_runtime_invoke (MonoMethod *method, gboolean virtual)
                MonoMethodSignature *tmp_sig;
 
                callsig = mono_marshal_get_runtime_invoke_sig (callsig);
+               GHashTable **cache_table = NULL;
 
                if (method->klass->valuetype && mono_method_signature (method)->hasthis)
-                       /* These have a different csig */
-                       cache = get_cache (&target_klass->image->runtime_invoke_vtype_cache,
-                                                          (GHashFunc)mono_signature_hash,
-                                                          (GCompareFunc)runtime_invoke_signature_equal);
+                       cache_table = &mono_method_get_wrapper_cache (method)->runtime_invoke_vtype_cache;
                else
-                       cache = get_cache (&target_klass->image->runtime_invoke_cache,
-                                                          (GHashFunc)mono_signature_hash,
+                       cache_table = &mono_method_get_wrapper_cache (method)->runtime_invoke_cache;
+
+               cache = get_cache (cache_table, (GHashFunc)mono_signature_hash,
                                                           (GCompareFunc)runtime_invoke_signature_equal);
 
                /* from mono_marshal_find_in_cache */
@@ -3993,10 +3961,13 @@ mono_marshal_get_runtime_invoke (MonoMethod *method, gboolean virtual)
                        mono_marshal_lock ();
                        res = g_hash_table_lookup (cache, callsig);
                        if (!res) {
+                               GHashTable *direct_cache;
                                res = newm;
                                g_hash_table_insert (cache, callsig, res);
                                /* Can't insert it into wrapper_hash since the key is a signature */
-                               g_hash_table_insert (method->klass->image->runtime_invoke_direct_cache, method, res);
+                               direct_cache = mono_method_get_wrapper_cache (method)->runtime_invoke_direct_cache;
+
+                               g_hash_table_insert (direct_cache, method, res);
                        } else {
                                mono_free_method (newm);
                        }
@@ -4171,9 +4142,9 @@ mono_marshal_get_icall_wrapper (MonoMethodSignature *sig, const char *name, gcon
 
        /* Add an explicit this argument */
        if (sig->hasthis)
-               csig2 = signature_dup_add_this (mono_defaults.corlib, sig, mono_defaults.object_class);
+               csig2 = mono_metadata_signature_dup_add_this (mono_defaults.corlib, sig, mono_defaults.object_class);
        else
-               csig2 = signature_dup (mono_defaults.corlib, sig);
+               csig2 = mono_metadata_signature_dup_full (mono_defaults.corlib, sig);
 
 #ifndef DISABLE_JIT
        if (sig->hasthis)
@@ -4190,7 +4161,7 @@ mono_marshal_get_icall_wrapper (MonoMethodSignature *sig, const char *name, gcon
        mono_mb_emit_byte (mb, CEE_RET);
 #endif
 
-       csig = signature_dup (mono_defaults.corlib, sig);
+       csig = mono_metadata_signature_dup_full (mono_defaults.corlib, sig);
        csig->pinvoke = 0;
        if (csig->call_convention == MONO_CALL_VARARG)
                csig->call_convention = 0;
@@ -7023,7 +6994,7 @@ mono_marshal_emit_native_wrapper (MonoImage *image, MonoMethodBuilder *mb, MonoM
                g_assert (!sig->hasthis);
                param_shift += 1;
        }
-       csig = signature_dup (mb->method->klass->image, sig);
+       csig = mono_metadata_signature_dup_full (mb->method->klass->image, sig);
        csig->pinvoke = 1;
        m.csig = csig;
        m.image = image;
@@ -7257,17 +7228,22 @@ mono_marshal_get_native_wrapper (MonoMethod *method, gboolean check_exceptions,
        g_assert (method != NULL);
        g_assert (mono_method_signature (method)->pinvoke);
 
+       GHashTable **cache_ptr;
+
        if (aot) {
                if (check_exceptions)
-                       cache = get_cache (&method->klass->image->native_wrapper_aot_check_cache, mono_aligned_addr_hash, NULL);
+                       cache_ptr = &mono_method_get_wrapper_cache (method)->native_wrapper_aot_check_cache;
                else
-                       cache = get_cache (&method->klass->image->native_wrapper_aot_cache, mono_aligned_addr_hash, NULL);
+                       cache_ptr = &mono_method_get_wrapper_cache (method)->native_wrapper_aot_cache;
        } else {
                if (check_exceptions)
-                       cache = get_cache (&method->klass->image->native_wrapper_check_cache, mono_aligned_addr_hash, NULL);
+                       cache_ptr = &mono_method_get_wrapper_cache (method)->native_wrapper_check_cache;
                else
-                       cache = get_cache (&method->klass->image->native_wrapper_cache, mono_aligned_addr_hash, NULL);
+                       cache_ptr = &mono_method_get_wrapper_cache (method)->native_wrapper_cache;
        }
+
+       cache = get_cache (cache_ptr, mono_aligned_addr_hash, NULL);
+
        if ((res = mono_marshal_find_in_cache (cache, method)))
                return res;
 
@@ -7306,7 +7282,7 @@ mono_marshal_get_native_wrapper (MonoMethod *method, gboolean check_exceptions,
                g_assert (sig->hasthis);
 
                /* CreateString returns a value */
-               csig = signature_dup (method->klass->image, sig);
+               csig = mono_metadata_signature_dup_full (method->klass->image, sig);
                csig->ret = &mono_defaults.string_class->byval_arg;
                csig->pinvoke = 0;
 
@@ -7362,7 +7338,7 @@ mono_marshal_get_native_wrapper (MonoMethod *method, gboolean check_exceptions,
                info = mono_wrapper_info_create (mb, WRAPPER_SUBTYPE_NONE);
                info->d.managed_to_native.method = method;
 
-               csig = signature_dup (method->klass->image, sig);
+               csig = mono_metadata_signature_dup_full (method->klass->image, sig);
                csig->pinvoke = 0;
                res = mono_mb_create_and_cache_full (cache, method, mb, csig,
                                                                                         csig->param_count + 16, info, NULL);
@@ -7374,9 +7350,9 @@ mono_marshal_get_native_wrapper (MonoMethod *method, gboolean check_exceptions,
        /* internal calls: we simply push all arguments and call the method (no conversions) */
        if (method->iflags & (METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL | METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
                if (sig->hasthis)
-                       csig = signature_dup_add_this (method->klass->image, sig, method->klass);
+                       csig = mono_metadata_signature_dup_add_this (method->klass->image, sig, method->klass);
                else
-                       csig = signature_dup (method->klass->image, sig);
+                       csig = mono_metadata_signature_dup_full (method->klass->image, sig);
 
                /* hack - string constructors returns a value */
                if (method->string_ctor)
@@ -7416,7 +7392,7 @@ mono_marshal_get_native_wrapper (MonoMethod *method, gboolean check_exceptions,
                info = mono_wrapper_info_create (mb, WRAPPER_SUBTYPE_NONE);
                info->d.managed_to_native.method = method;
 
-               csig = signature_dup (method->klass->image, csig);
+               csig = mono_metadata_signature_dup_full (method->klass->image, csig);
                csig->pinvoke = 0;
                res = mono_mb_create_and_cache_full (cache, method, mb, csig, csig->param_count + 16,
                                                                                         info, NULL);
@@ -7438,7 +7414,7 @@ mono_marshal_get_native_wrapper (MonoMethod *method, gboolean check_exceptions,
        info = mono_wrapper_info_create (mb, WRAPPER_SUBTYPE_PINVOKE);
        info->d.managed_to_native.method = method;
 
-       csig = signature_dup (method->klass->image, sig);
+       csig = mono_metadata_signature_dup_full (method->klass->image, sig);
        csig->pinvoke = 0;
        res = mono_mb_create_and_cache_full (cache, method, mb, csig, csig->param_count + 16,
                                                                                 info, NULL);
@@ -7481,6 +7457,9 @@ mono_marshal_get_native_func_wrapper (MonoImage *image, MonoMethodSignature *sig
        key.sig = sig;
        key.pointer = func;
 
+       // Generic types are not safe to place in MonoImage caches.
+       g_assert (!sig->is_inflated);
+
        cache = get_cache (&image->native_func_wrapper_cache, signature_pointer_pair_hash, signature_pointer_pair_equal);
        if ((res = mono_marshal_find_in_cache (cache, &key)))
                return res;
@@ -7493,7 +7472,7 @@ mono_marshal_get_native_func_wrapper (MonoImage *image, MonoMethodSignature *sig
        mono_marshal_emit_native_wrapper (image, mb, sig, piinfo, mspecs, func, FALSE, TRUE, FALSE);
 #endif
 
-       csig = signature_dup (image, sig);
+       csig = mono_metadata_signature_dup_full (image, sig);
        csig->pinvoke = 0;
 
        new_key = g_new (SignaturePointerPair,1);
@@ -7536,7 +7515,8 @@ mono_marshal_get_native_func_wrapper_aot (MonoClass *klass)
        /*
         * The wrapper is associated with the delegate type, to pick up the marshalling info etc.
         */
-       cache = get_cache (&image->native_func_wrapper_aot_cache, mono_aligned_addr_hash, NULL);
+       cache = get_cache (&mono_method_get_wrapper_cache (invoke)->native_func_wrapper_aot_cache, mono_aligned_addr_hash, NULL);
+
        if ((res = mono_marshal_find_in_cache (cache, invoke)))
                return res;
 
@@ -7561,7 +7541,7 @@ mono_marshal_get_native_func_wrapper_aot (MonoClass *klass)
        info->d.managed_to_native.method = invoke;
 
        g_assert (!sig->hasthis);
-       csig = signature_dup_add_this (image, sig, mono_defaults.object_class);
+       csig = mono_metadata_signature_dup_add_this (image, sig, mono_defaults.object_class);
        csig->pinvoke = 0;
        res = mono_mb_create_and_cache_full (cache, invoke,
                                                                                 mb, csig, csig->param_count + 16,
@@ -7889,7 +7869,8 @@ mono_marshal_get_managed_wrapper (MonoMethod *method, MonoClass *delegate_klass,
         * could be called with different delegates, thus different marshalling
         * options.
         */
-       cache = get_cache (&method->klass->image->managed_wrapper_cache, mono_aligned_addr_hash, NULL);
+       cache = get_cache (&mono_method_get_wrapper_cache (method)->managed_wrapper_cache, mono_aligned_addr_hash, NULL);
+
        if (!target_handle && (res = mono_marshal_find_in_cache (cache, method)))
                return res;
 
@@ -7911,7 +7892,7 @@ mono_marshal_get_managed_wrapper (MonoMethod *method, MonoClass *delegate_klass,
                /* Need to free this later */
                csig = mono_metadata_signature_dup (invoke_sig);
        else
-               csig = signature_dup (method->klass->image, invoke_sig);
+               csig = mono_metadata_signature_dup_full (method->klass->image, invoke_sig);
        csig->hasthis = 0;
        csig->pinvoke = 1;
 
@@ -8015,7 +7996,7 @@ mono_marshal_get_managed_wrapper (MonoMethod *method, MonoClass *delegate_klass,
                                                                                         info, NULL);
        } else {
 #ifndef DISABLE_JIT
-               mb->dynamic = 1;
+               mb->dynamic = TRUE;
 #endif
                res = mono_mb_create (mb, csig, sig->param_count + 16, NULL);
        }
@@ -8056,7 +8037,7 @@ mono_marshal_get_vtfixup_ftnptr (MonoImage *image, guint32 token, guint16 type)
                mono_method_get_marshal_info (method, mspecs);
 
                mb = mono_mb_new (method->klass, method->name, MONO_WRAPPER_NATIVE_TO_MANAGED);
-               csig = signature_dup (image, sig);
+               csig = mono_metadata_signature_dup_full (image, sig);
                csig->hasthis = 0;
                csig->pinvoke = 1;
 
@@ -8075,7 +8056,7 @@ mono_marshal_get_vtfixup_ftnptr (MonoImage *image, guint32 token, guint16 type)
                mono_marshal_emit_managed_wrapper (mb, sig, mspecs, &m, method, 0);
 
 #ifndef DISABLE_JIT
-               mb->dynamic = 1;
+               mb->dynamic = TRUE;
 #endif
                method = mono_mb_create (mb, csig, sig->param_count + 16, NULL);
                mono_mb_free (mb);
@@ -8102,7 +8083,7 @@ mono_marshal_get_vtfixup_ftnptr (MonoImage *image, guint32 token, guint16 type)
                mono_mb_emit_op (mb, CEE_CALL, method);
        mono_mb_emit_byte (mb, CEE_RET);
 
-       mb->dynamic = 1;
+       mb->dynamic = TRUE;
 #endif
 
        method = mono_mb_create (mb, sig, param_count, NULL);
@@ -8613,7 +8594,7 @@ mono_marshal_get_ptr_to_struct (MonoClass *klass)
                          static void PtrToStructure (IntPtr ptr, object structure);
                   defined in class/corlib/System.Runtime.InteropServices/Marshal.cs */
                sig = mono_create_icall_signature ("void ptr object");
-               sig = signature_dup (mono_defaults.corlib, sig);
+               sig = mono_metadata_signature_dup_full (mono_defaults.corlib, sig);
                sig->pinvoke = 0;
                mono_memory_barrier ();
                ptostr = sig;
@@ -8689,7 +8670,7 @@ mono_marshal_get_synchronized_inner_wrapper (MonoMethod *method)
        mono_mb_emit_exception_full (mb, "System", "ExecutionEngineException", "Shouldn't be called.");
        mono_mb_emit_byte (mb, CEE_RET);
 #endif
-       sig = signature_dup (method->klass->image, mono_method_signature (method));
+       sig = mono_metadata_signature_dup_full (method->klass->image, mono_method_signature (method));
 
        info = mono_wrapper_info_create (mb, WRAPPER_SUBTYPE_SYNCHRONIZED_INNER);
        info->d.synchronized_inner.method = method;
@@ -8716,7 +8697,7 @@ mono_marshal_get_synchronized_wrapper (MonoMethod *method)
        MonoMethodBuilder *mb;
        MonoMethod *res;
        GHashTable *cache;
-       int i, pos, this_local, ret_local = 0;
+       int i, pos, pos2, this_local, taken_local, ret_local = 0;
        MonoGenericContext *ctx = NULL;
        MonoMethod *orig_method = NULL;
        MonoGenericContainer *container = NULL;
@@ -8741,22 +8722,23 @@ mono_marshal_get_synchronized_wrapper (MonoMethod *method)
         * Check cache
         */
        if (ctx) {
-               cache = get_cache (&method->klass->image->synchronized_generic_cache, mono_aligned_addr_hash, NULL);
+               cache = get_cache (&((MonoMethodInflated*)orig_method)->owner->wrapper_caches.synchronized_cache, mono_aligned_addr_hash, NULL);
                res = check_generic_wrapper_cache (cache, orig_method, orig_method, method);
                if (res)
                        return res;
        } else {
-               cache = get_cache (&method->klass->image->synchronized_cache, mono_aligned_addr_hash, NULL);
+               cache = get_cache (&method->klass->image->wrapper_caches.synchronized_cache, mono_aligned_addr_hash, NULL);
                if ((res = mono_marshal_find_in_cache (cache, method)))
                        return res;
        }
 
-       sig = signature_dup (method->klass->image, mono_method_signature (method));
+       sig = mono_metadata_signature_dup_full (method->klass->image, mono_method_signature (method));
        sig->pinvoke = 0;
 
        mb = mono_mb_new (method->klass, method->name, MONO_WRAPPER_SYNCHRONIZED);
 
 #ifndef DISABLE_JIT
+       mb->skip_visibility = 1;
        /* result */
        if (!MONO_TYPE_IS_VOID (sig->ret))
                ret_local = mono_mb_add_local (mb, sig->ret);
@@ -8785,6 +8767,7 @@ mono_marshal_get_synchronized_wrapper (MonoMethod *method)
 #ifndef DISABLE_JIT
        /* this */
        this_local = mono_mb_add_local (mb, &mono_defaults.object_class->byval_arg);
+       taken_local = mono_mb_add_local (mb, &mono_defaults.boolean_class->byval_arg);
 
        clause = mono_image_alloc0 (method->klass->image, sizeof (MonoExceptionClause));
        clause->flags = MONO_EXCEPTION_CLAUSE_FINALLY;
@@ -8795,7 +8778,7 @@ mono_marshal_get_synchronized_wrapper (MonoMethod *method)
        if (!enter_method) {
                MonoMethodDesc *desc;
 
-               desc = mono_method_desc_new ("Monitor:Enter", FALSE);
+               desc = mono_method_desc_new ("Monitor:enter_with_atomic_var(object,bool&)", FALSE);
                enter_method = mono_method_desc_search_in_class (desc, mono_defaults.monitor_class);
                g_assert (enter_method);
                mono_method_desc_free (desc);
@@ -8830,6 +8813,7 @@ mono_marshal_get_synchronized_wrapper (MonoMethod *method)
 
        /* Call Monitor::Enter() */
        mono_mb_emit_ldloc (mb, this_local);
+       mono_mb_emit_ldloc_addr (mb, taken_local);
        mono_mb_emit_managed_call (mb, enter_method, NULL);
 
        clause->try_offset = mono_mb_get_label (mb);
@@ -8856,9 +8840,12 @@ mono_marshal_get_synchronized_wrapper (MonoMethod *method)
        clause->try_len = mono_mb_get_pos (mb) - clause->try_offset;
        clause->handler_offset = mono_mb_get_label (mb);
 
-       /* Call Monitor::Exit() */
+       /* Call Monitor::Exit() if needed */
+       mono_mb_emit_ldloc (mb, taken_local);
+       pos2 = mono_mb_emit_branch (mb, CEE_BRFALSE);
        mono_mb_emit_ldloc (mb, this_local);
        mono_mb_emit_managed_call (mb, exit_method, NULL);
+       mono_mb_patch_branch (mb, pos2);
        mono_mb_emit_byte (mb, CEE_ENDFINALLY);
 
        clause->handler_len = mono_mb_get_pos (mb) - clause->handler_offset;
@@ -8897,7 +8884,8 @@ mono_marshal_get_unbox_wrapper (MonoMethod *method)
        MonoMethod *res;
        GHashTable *cache;
 
-       cache = get_cache (&method->klass->image->unbox_wrapper_cache, mono_aligned_addr_hash, NULL);
+       cache = get_cache (&mono_method_get_wrapper_cache (method)->unbox_wrapper_cache, mono_aligned_addr_hash, NULL);
+
        if ((res = mono_marshal_find_in_cache (cache, method)))
                return res;
 
@@ -9876,7 +9864,7 @@ mono_marshal_get_array_accessor_wrapper (MonoMethod *method)
                        return res;
        }
 
-       sig = signature_dup (method->klass->image, mono_method_signature (method));
+       sig = mono_metadata_signature_dup_full (method->klass->image, mono_method_signature (method));
        sig->pinvoke = 0;
 
        mb = mono_mb_new (method->klass, method->name, MONO_WRAPPER_UNKNOWN);
@@ -11031,7 +11019,7 @@ mono_marshal_get_generic_array_helper (MonoClass *class, MonoClass *iface, gchar
                METHOD_ATTRIBUTE_NEW_SLOT | METHOD_ATTRIBUTE_HIDE_BY_SIG | METHOD_ATTRIBUTE_FINAL;
 
        sig = mono_method_signature (method);
-       csig = signature_dup (method->klass->image, sig);
+       csig = mono_metadata_signature_dup_full (method->klass->image, sig);
        csig->generic_param_count = 0;
 
 #ifndef DISABLE_JIT
@@ -11124,12 +11112,17 @@ mono_marshal_get_thunk_invoke_wrapper (MonoMethod *method)
        GHashTable *cache;
        MonoMethod *res;
        int i, param_count, sig_size, pos_leave;
+#ifdef USE_COOP_GC
+       int coop_gc_var;
+#endif
 
        g_assert (method);
 
        klass = method->klass;
        image = method->klass->image;
-       cache = get_cache (&image->thunk_invoke_cache, mono_aligned_addr_hash, NULL);
+
+       cache = get_cache (&mono_method_get_wrapper_cache (method)->thunk_invoke_cache, mono_aligned_addr_hash, NULL);
+
 
        if ((res = mono_marshal_find_in_cache (cache, method)))
                return res;
@@ -11175,11 +11168,23 @@ mono_marshal_get_thunk_invoke_wrapper (MonoMethod *method)
        if (!MONO_TYPE_IS_VOID (sig->ret))
                mono_mb_add_local (mb, sig->ret);
 
+#ifdef USE_COOP_GC
+       /* local 4, the local to be used when calling the reset_blocking funcs */
+       /* tons of code hardcode 3 to be the return var */
+       coop_gc_var = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
+#endif
+
        /* clear exception arg */
        mono_mb_emit_ldarg (mb, param_count - 1);
        mono_mb_emit_byte (mb, CEE_LDNULL);
        mono_mb_emit_byte (mb, CEE_STIND_REF);
 
+#ifdef USE_COOP_GC
+       /* FIXME this is technically wrong as the callback itself must be executed in gc unsafe context. */
+       mono_mb_emit_icall (mb, mono_threads_reset_blocking_start);
+       mono_mb_emit_stloc (mb, coop_gc_var);
+#endif
+
        /* try */
        clause = mono_image_alloc0 (image, sizeof (MonoExceptionClause));
        clause->try_offset = mono_mb_get_label (mb);
@@ -11249,6 +11254,12 @@ mono_marshal_get_thunk_invoke_wrapper (MonoMethod *method)
                        mono_mb_emit_op (mb, CEE_BOX, mono_class_from_mono_type (sig->ret));
        }
 
+#ifdef USE_COOP_GC
+       /* XXX merge reset_blocking_end with detach */
+       mono_mb_emit_ldloc (mb, coop_gc_var);
+       mono_mb_emit_icall (mb, mono_threads_reset_blocking_end);
+#endif
+
        mono_mb_emit_byte (mb, CEE_RET);
 #endif
 
@@ -11277,10 +11288,10 @@ mono_marshal_free_dynamic_wrappers (MonoMethod *method)
         * FIXME: We currently leak the wrappers. Freeing them would be tricky as
         * they could be shared with other methods ?
         */
-       if (image->runtime_invoke_direct_cache)
-               g_hash_table_remove (image->runtime_invoke_direct_cache, method);
-       if (image->delegate_abstract_invoke_cache)
-               g_hash_table_foreach_remove (image->delegate_abstract_invoke_cache, signature_pointer_pair_matches_pointer, method);
+       if (image->wrapper_caches.runtime_invoke_direct_cache)
+               g_hash_table_remove (image->wrapper_caches.runtime_invoke_direct_cache, method);
+       if (image->wrapper_caches.delegate_abstract_invoke_cache)
+               g_hash_table_foreach_remove (image->wrapper_caches.delegate_abstract_invoke_cache, signature_pointer_pair_matches_pointer, method);
        // FIXME: Need to clear the caches in other images as well
        if (image->delegate_bound_static_invoke_cache)
                g_hash_table_remove (image->delegate_bound_static_invoke_cache, mono_method_signature (method));
@@ -11288,83 +11299,3 @@ mono_marshal_free_dynamic_wrappers (MonoMethod *method)
        if (marshal_mutex_initialized)
                mono_marshal_unlock ();
 }
-
-static gboolean
-signature_pointer_pair_matches_signature (gpointer key, gpointer value, gpointer user_data)
-{
-       SignaturePointerPair *pair = (SignaturePointerPair*)key;
-       MonoMethodSignature *sig = (MonoMethodSignature*)user_data;
-
-       return mono_metadata_signature_equal (pair->sig, sig);
-}
-
-/*
- * mono_marshal_free_inflated_wrappers:
- *
- *   Free wrappers of the inflated method METHOD.
- */
-void
-mono_marshal_free_inflated_wrappers (MonoMethod *method)
-{
-       MonoMethodSignature *sig = method->signature;
-
-       g_assert (method->is_inflated);
-
-       /* Ignore calls occuring late during cleanup.  */
-       if (!marshal_mutex_initialized)
-               return;
-
-       mono_marshal_lock ();
-       /*
-        * FIXME: We currently leak the wrappers. Freeing them would be tricky as
-        * they could be shared with other methods ?
-        */
-
-        /*
-         * indexed by MonoMethodSignature
-         */
-          /* FIXME: This could remove unrelated wrappers as well */
-       if (sig && method->klass->image->delegate_begin_invoke_cache)
-               g_hash_table_remove (method->klass->image->delegate_begin_invoke_cache, sig);
-       if (sig && method->klass->image->delegate_end_invoke_cache)
-               g_hash_table_remove (method->klass->image->delegate_end_invoke_cache, sig);
-       if (sig && method->klass->image->delegate_invoke_cache)
-               g_hash_table_remove (method->klass->image->delegate_invoke_cache, sig);
-       if (sig && method->klass->image->runtime_invoke_cache)
-               g_hash_table_remove (method->klass->image->runtime_invoke_cache, sig);
-       if (sig && method->klass->image->runtime_invoke_vtype_cache)
-               g_hash_table_remove (method->klass->image->runtime_invoke_vtype_cache, sig);
-
-        /*
-         * indexed by SignaturePointerPair
-         */
-       if (sig && method->klass->image->delegate_abstract_invoke_cache)
-               g_hash_table_foreach_remove (method->klass->image->delegate_abstract_invoke_cache,
-                                            signature_pointer_pair_matches_signature, (gpointer)sig);
-
-        /*
-         * indexed by MonoMethod pointers
-         */
-       if (method->klass->image->runtime_invoke_direct_cache)
-               g_hash_table_remove (method->klass->image->runtime_invoke_direct_cache, method);
-       if (method->klass->image->managed_wrapper_cache)
-               g_hash_table_remove (method->klass->image->managed_wrapper_cache, method);
-       if (method->klass->image->native_wrapper_cache)
-               g_hash_table_remove (method->klass->image->native_wrapper_cache, method);
-       if (method->klass->image->remoting_invoke_cache)
-               g_hash_table_remove (method->klass->image->remoting_invoke_cache, method);
-       if (method->klass->image->synchronized_cache)
-               g_hash_table_remove (method->klass->image->synchronized_cache, method);
-       if (method->klass->image->unbox_wrapper_cache)
-               g_hash_table_remove (method->klass->image->unbox_wrapper_cache, method);
-       if (method->klass->image->cominterop_invoke_cache)
-               g_hash_table_remove (method->klass->image->cominterop_invoke_cache, method);
-       if (method->klass->image->cominterop_wrapper_cache)
-               g_hash_table_remove (method->klass->image->cominterop_wrapper_cache, method);
-       if (method->klass->image->thunk_invoke_cache)
-               g_hash_table_remove (method->klass->image->thunk_invoke_cache, method);
-       if (method->klass->image->native_func_wrapper_aot_cache)
-               g_hash_table_remove (method->klass->image->native_func_wrapper_aot_cache, method);
-
-       mono_marshal_unlock ();
-}