Make nested type loading lazier.
[mono.git] / mono / metadata / marshal.c
index 9d814406af930fedc556c9ef2aece3bbb7f201fe..2b66637c2bf6c5368ed6039407034fd3a918e68b 100644 (file)
@@ -81,7 +81,7 @@ static guint32 last_error_tls_id;
 static guint32 load_type_info_tls_id;
 
 static void
-delegate_hash_table_add (MonoDelegate *d, MonoObject **target_loc);
+delegate_hash_table_add (MonoDelegate *d);
 
 static void
 emit_struct_conv (MonoMethodBuilder *mb, MonoClass *klass, gboolean to_object);
@@ -245,6 +245,7 @@ mono_marshal_init (void)
                register_icall (mono_upgrade_remote_class_wrapper, "mono_upgrade_remote_class_wrapper", "void object object", FALSE);
                register_icall (type_from_handle, "type_from_handle", "object ptr", FALSE);
                register_icall (mono_gc_wbarrier_generic_nostore, "wb_generic", "void ptr", FALSE);
+               register_icall (mono_gchandle_get_target, "mono_gchandle_get_target", "object int32", TRUE);
 
                mono_cominterop_init ();
        }
@@ -307,7 +308,7 @@ mono_delegate_to_ftnptr (MonoDelegate *delegate)
 {
        MonoMethod *method, *wrapper;
        MonoClass *klass;
-       MonoObject **target_loc;
+       uint32_t target_handle = 0;
 
        if (!delegate)
                return NULL;
@@ -334,18 +335,15 @@ mono_delegate_to_ftnptr (MonoDelegate *delegate)
 
        if (delegate->target) {
                /* Produce a location which can be embedded in JITted code */
-               target_loc = mono_gc_alloc_fixed (sizeof (MonoObject*), NULL);
-               *target_loc = delegate->target;
-       } else {
-               target_loc = NULL;
+               target_handle = mono_gchandle_new_weakref (delegate->target, FALSE);
        }
 
-       wrapper = mono_marshal_get_managed_wrapper (method, klass, target_loc);
+       wrapper = mono_marshal_get_managed_wrapper (method, klass, target_handle);
 
        delegate->delegate_trampoline = mono_compile_method (wrapper);
 
        // Add the delegate to the delegate hash table
-       delegate_hash_table_add (delegate, target_loc);
+       delegate_hash_table_add (delegate);
 
        /* when the object is collected, collect the dynamic method, too */
        mono_object_register_finalizer ((MonoObject*)delegate);
@@ -359,8 +357,6 @@ mono_delegate_to_ftnptr (MonoDelegate *delegate)
  * object pointer itself, otherwise we use a GC handle.
  */
 static GHashTable *delegate_hash_table;
-/* Contains root locations pointing to the this arguments of delegates */
-static MonoGHashTable *delegate_target_locations;
 
 static GHashTable *
 delegate_hash_table_new (void) {
@@ -370,7 +366,6 @@ delegate_hash_table_new (void) {
 static void 
 delegate_hash_table_remove (MonoDelegate *d)
 {
-       MonoObject **target_loc;
 #ifdef HAVE_MOVING_COLLECTOR
        guint32 gchandle;
 #endif
@@ -381,23 +376,14 @@ delegate_hash_table_remove (MonoDelegate *d)
        gchandle = GPOINTER_TO_UINT (g_hash_table_lookup (delegate_hash_table, d->delegate_trampoline));
 #endif
        g_hash_table_remove (delegate_hash_table, d->delegate_trampoline);
-       if (delegate_target_locations)
-               target_loc = mono_g_hash_table_lookup (delegate_target_locations, d->delegate_trampoline);
-       else
-               target_loc = NULL;
-       if (target_loc)
-               mono_g_hash_table_remove (delegate_target_locations, d->delegate_trampoline);
        mono_marshal_unlock ();
-       if (target_loc) {
-               mono_gc_free_fixed (target_loc);
-       }
 #ifdef HAVE_MOVING_COLLECTOR
        mono_gchandle_free (gchandle);
 #endif
 }
 
 static void
-delegate_hash_table_add (MonoDelegate *d, MonoObject **target_loc) 
+delegate_hash_table_add (MonoDelegate *d)
 {
 #ifdef HAVE_MOVING_COLLECTOR
        guint32 gchandle = mono_gchandle_new_weakref ((MonoObject*)d, FALSE);
@@ -406,11 +392,6 @@ delegate_hash_table_add (MonoDelegate *d, MonoObject **target_loc)
        mono_marshal_lock ();
        if (delegate_hash_table == NULL)
                delegate_hash_table = delegate_hash_table_new ();
-       if (delegate_target_locations == NULL) {
-               /* Has to be conservative as the values are not object references */
-               delegate_target_locations = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_CONSERVATIVE_GC);
-               MONO_GC_REGISTER_ROOT (delegate_target_locations);
-       }
 #ifdef HAVE_MOVING_COLLECTOR
        old_gchandle = GPOINTER_TO_UINT (g_hash_table_lookup (delegate_hash_table, d->delegate_trampoline));
        g_hash_table_insert (delegate_hash_table, d->delegate_trampoline, GUINT_TO_POINTER (gchandle));
@@ -419,9 +400,6 @@ delegate_hash_table_add (MonoDelegate *d, MonoObject **target_loc)
 #else
        g_hash_table_insert (delegate_hash_table, d->delegate_trampoline, d);
 #endif
-       if (target_loc)
-               /* This keeps target_loc alive for Boehm */
-               mono_g_hash_table_insert (delegate_target_locations, d->delegate_trampoline, target_loc);
        mono_marshal_unlock ();
 }
 
@@ -524,9 +502,19 @@ mono_delegate_free_ftnptr (MonoDelegate *delegate)
        }
 
        if (ptr) {
+               uint32_t gchandle;
+               void **method_data;
                ji = mono_jit_info_table_find (mono_domain_get (), mono_get_addr_from_ftnptr (ptr));
                g_assert (ji);
 
+               method_data = ((MonoMethodWrapper*)ji->method)->method_data;
+
+               /*the target gchandle is the first entry after size and the wrapper itself.*/
+               gchandle = GPOINTER_TO_UINT (method_data [2]);
+
+               if (gchandle)
+                       mono_gchandle_free (gchandle);
+
                mono_runtime_free_method (mono_object_domain (delegate), ji->method);
        }
 }
@@ -583,10 +571,10 @@ mono_array_to_lparray (MonoArray *array)
        case MONO_TYPE_R4:
        case MONO_TYPE_R8:
        case MONO_TYPE_VALUETYPE:
+       case MONO_TYPE_PTR:
                /* nothing to do */
                break;
        case MONO_TYPE_GENERICINST:
-       case MONO_TYPE_PTR:
        case MONO_TYPE_OBJECT:
        case MONO_TYPE_ARRAY: 
        case MONO_TYPE_SZARRAY:
@@ -2327,18 +2315,6 @@ mono_marshal_find_in_cache (GHashTable *cache, gpointer key)
        return res;
 }
 
-static void
-mono_marshal_method_set_wrapper_data (MonoMethod *method, gpointer data)
-{
-       void **datav;
-       /* assert */
-       if (method->wrapper_type == MONO_WRAPPER_NONE || method->wrapper_type == MONO_WRAPPER_DYNAMIC_METHOD)
-               return;
-
-       datav = ((MonoMethodWrapper *)method)->method_data;
-       datav [1] = data;
-}
-
 /* Create the method from the builder and place it in the cache */
 MonoMethod*
 mono_mb_create_and_cache (GHashTable *cache, gpointer key,
@@ -2358,7 +2334,7 @@ mono_mb_create_and_cache (GHashTable *cache, gpointer key,
                if (!res) {
                        res = newm;
                        g_hash_table_insert (cache, key, res);
-                       mono_marshal_method_set_wrapper_data (res, key);
+                       mono_marshal_set_wrapper_info (res, key);
                        mono_marshal_unlock ();
                } else {
                        mono_marshal_unlock ();
@@ -2431,7 +2407,7 @@ mono_remoting_mb_create_and_cache (MonoMethod *key, MonoMethodBuilder *mb,
                mono_marshal_lock ();
                if (!*res) {
                        *res = newm;
-                       mono_marshal_method_set_wrapper_data (*res, key);
+                       mono_marshal_set_wrapper_info (*res, key);
                        mono_marshal_unlock ();
                } else {
                        mono_marshal_unlock ();
@@ -2446,22 +2422,59 @@ MonoMethod *
 mono_marshal_method_from_wrapper (MonoMethod *wrapper)
 {
        gpointer res;
+       int wrapper_type = wrapper->wrapper_type;
 
-       if (wrapper->wrapper_type == MONO_WRAPPER_NONE || wrapper->wrapper_type == MONO_WRAPPER_DYNAMIC_METHOD)
+       if (wrapper_type == MONO_WRAPPER_NONE || wrapper_type == MONO_WRAPPER_DYNAMIC_METHOD)
                return wrapper;
 
-       res = mono_method_get_wrapper_data (wrapper, 1);
-       if (res == NULL)
-               return wrapper;
-       return res;
+       switch (wrapper_type) {
+       case MONO_WRAPPER_REMOTING_INVOKE:
+       case MONO_WRAPPER_REMOTING_INVOKE_WITH_CHECK:
+       case MONO_WRAPPER_XDOMAIN_INVOKE:
+       case MONO_WRAPPER_SYNCHRONIZED:
+       case MONO_WRAPPER_MANAGED_TO_NATIVE:
+       case MONO_WRAPPER_RUNTIME_INVOKE:
+               res = mono_method_get_wrapper_data (wrapper, 1);
+               if (res == NULL)
+                       return wrapper;
+               return res;
+       default:
+               return NULL;
+       }
 }
 
+/*
+ * mono_marshal_get_wrapper_info:
+ *
+ *   Retrieve the pointer stored by mono_marshal_set_wrapper_info.
+ */
 gpointer
-mono_marshal_wrapper_info_from_wrapper (MonoMethod *wrapper)
+mono_marshal_get_wrapper_info (MonoMethod *wrapper)
 {
+       g_assert (wrapper->wrapper_type);
+
        return mono_method_get_wrapper_data (wrapper, 1);
 }
 
+/*
+ * mono_marshal_set_wrapper_info:
+ *
+ *   Store an arbitrary pointer inside the wrapper which is retrievable by 
+ * mono_marshal_get_wrapper_info. The format of the data depends on the type of the
+ * wrapper (method->wrapper_type).
+ */
+void
+mono_marshal_set_wrapper_info (MonoMethod *method, gpointer data)
+{
+       void **datav;
+       /* assert */
+       if (method->wrapper_type == MONO_WRAPPER_NONE || method->wrapper_type == MONO_WRAPPER_DYNAMIC_METHOD)
+               return;
+
+       datav = ((MonoMethodWrapper *)method)->method_data;
+       datav [1] = data;
+}
+
 /*
  * get_wrapper_target_class:
  *
@@ -2570,7 +2583,7 @@ mono_delegate_end_invoke (MonoDelegate *delegate, gpointer *params)
                return NULL;
        }
 
-       if (ares->async_delegate != (MonoObject*)delegate && mono_framework_version () >= 2) {
+       if (ares->async_delegate != (MonoObject*)delegate) {
                mono_raise_exception (mono_get_exception_invalid_operation (
                        "The IAsyncResult object provided does not match this delegate."));
                return NULL;
@@ -3752,6 +3765,7 @@ mono_marshal_get_delegate_invoke (MonoMethod *method, MonoDelegate *del)
        MonoMethod *target_method = NULL;
        MonoClass *target_class = NULL;
        gboolean callvirt = FALSE;
+       gboolean closed_over_null = FALSE;
 
        /*
         * If the delegate target is null, and the target method is not static, a virtual 
@@ -3778,6 +3792,9 @@ mono_marshal_get_delegate_invoke (MonoMethod *method, MonoDelegate *del)
                
        sig = mono_signature_no_pinvoke (method);
 
+       if (callvirt)
+               closed_over_null = sig->param_count == mono_method_signature (del->method)->param_count;
+
        if (callvirt) {
                /* We need to cache the signature+method pair */
                mono_marshal_lock ();
@@ -3875,11 +3892,18 @@ mono_marshal_get_delegate_invoke (MonoMethod *method, MonoDelegate *del)
        mono_mb_patch_branch (mb, pos0);
 
        if (callvirt) {
-               mono_mb_emit_ldarg (mb, 1);
-               mono_mb_emit_op (mb, CEE_CASTCLASS, target_class);
-               for (i = 1; i < sig->param_count; ++i)
-                       mono_mb_emit_ldarg (mb, i + 1);
-               mono_mb_emit_op (mb, CEE_CALLVIRT, target_method);
+               if (!closed_over_null) {
+                       mono_mb_emit_ldarg (mb, 1);
+                       mono_mb_emit_op (mb, CEE_CASTCLASS, target_class);
+                       for (i = 1; i < sig->param_count; ++i)
+                               mono_mb_emit_ldarg (mb, i + 1);
+                       mono_mb_emit_op (mb, CEE_CALLVIRT, target_method);
+               } else {
+                       mono_mb_emit_byte (mb, CEE_LDNULL);
+                       for (i = 0; i < sig->param_count; ++i)
+                               mono_mb_emit_ldarg (mb, i + 1);
+                       mono_mb_emit_op (mb, CEE_CALL, target_method);
+               }
        } else {
                for (i = 0; i < sig->param_count; ++i)
                        mono_mb_emit_ldarg (mb, i + 1);
@@ -3905,7 +3929,7 @@ mono_marshal_get_delegate_invoke (MonoMethod *method, MonoDelegate *del)
                        new_key->sig = sig;
                        new_key->method = target_method;
                        g_hash_table_insert (cache, new_key, res);
-                       mono_marshal_method_set_wrapper_data (res, new_key);
+                       mono_marshal_set_wrapper_info (res, new_key);
                        mono_marshal_unlock ();
                } else {
                        mono_marshal_unlock ();
@@ -4010,12 +4034,9 @@ mono_marshal_get_string_ctor_signature (MonoMethod *method)
 static MonoType*
 get_runtime_invoke_type (MonoType *t, gboolean ret)
 {
-       if (t->byref) {
-               if (t->type == MONO_TYPE_GENERICINST)
-                       return t;
-               else
-                       return &mono_defaults.int_class->byval_arg;
-       }
+       if (t->byref)
+               /* Can't share this with 'I' as that needs another indirection */
+               return t;
 
        if (MONO_TYPE_IS_REFERENCE (t))
                return &mono_defaults.object_class->byval_arg;
@@ -4166,41 +4187,15 @@ mono_marshal_get_runtime_invoke (MonoMethod *method, gboolean virtual)
                }
        }
 
-#if 0
-       /* Vtypes/nullables/Byrefs cause too many problems */
-       for (i = 0; i < callsig->param_count; ++i) {
-               if (MONO_TYPE_ISSTRUCT (callsig->params [i]) || callsig->params [i]->byref)
-                       need_direct_wrapper = TRUE;
-       }
-#endif
+       target_klass = get_wrapper_target_class (method->klass->image);
 
-       /*
-        * We try to share runtime invoke wrappers between different methods but have to
-        * be careful about methods whose klass has a type cctor, since putting the wrapper
-        * into that klass would mean that calling a method of klass A might invoke the
-        * type initializer of class B, or throw an exception if the type initializer 
-        * was called before and failed. See #349621 for an example. 
-        * We avoid that for mscorlib methods by putting every wrapper into the object class.
-        */
-       if (method->klass->image == mono_defaults.corlib)
+       /* Try to share wrappers for non-corlib methods with simple signatures */
+       if (mono_metadata_signature_equal (callsig, cctor_signature)) {
+               callsig = cctor_signature;
+               target_klass = mono_defaults.object_class;
+       } else if (mono_metadata_signature_equal (callsig, finalize_signature)) {
+               callsig = finalize_signature;
                target_klass = mono_defaults.object_class;
-       else {
-               /* Try to share wrappers for non-corlib methods with simple signatures */
-               if (mono_metadata_signature_equal (callsig, cctor_signature)) {
-                       callsig = cctor_signature;
-                       target_klass = mono_defaults.object_class;
-               } else if (mono_metadata_signature_equal (callsig, finalize_signature)) {
-                       callsig = finalize_signature;
-                       target_klass = mono_defaults.object_class;
-               } else {
-                       // FIXME: This breaks too many things
-                       /*
-                       if (mono_class_get_cctor (method->klass))
-                               need_direct_wrapper = TRUE;
-                       */
-
-                       target_klass = get_wrapper_target_class (method->klass->image);
-               }
        }
 
        if (need_direct_wrapper) {
@@ -4258,14 +4253,6 @@ mono_marshal_get_runtime_invoke (MonoMethod *method, gboolean virtual)
        /* allocate local 1 (object) exc */
        mono_mb_add_local (mb, &mono_defaults.object_class->byval_arg);
 
-       /* cond set *exc to null */
-       mono_mb_emit_byte (mb, CEE_LDARG_2);
-       mono_mb_emit_byte (mb, CEE_BRFALSE_S);
-       mono_mb_emit_byte (mb, 3);      
-       mono_mb_emit_byte (mb, CEE_LDARG_2);
-       mono_mb_emit_byte (mb, CEE_LDNULL);
-       mono_mb_emit_byte (mb, CEE_STIND_REF);
-
        emit_thread_force_interrupt_checkpoint (mb);
 
        if (virtual) {
@@ -7620,11 +7607,11 @@ emit_marshal_boolean (EmitMarshalContext *m, int argnum, MonoType *t,
                
                /* Check null */
                if (t->byref) {
-                       
                        label_null = mono_mb_emit_branch (mb, CEE_BRFALSE);
                        mono_mb_emit_ldarg (mb, argnum);
                        mono_mb_emit_byte (mb, ldop);
-               }
+               } else
+                       label_null = 0;
 
                label_false = mono_mb_emit_branch (mb, CEE_BRFALSE);
                mono_mb_emit_byte (mb, CEE_LDC_I4_1);
@@ -8049,6 +8036,12 @@ mono_marshal_emit_native_wrapper (MonoImage *image, MonoMethodBuilder *mb, MonoM
        mono_mb_emit_byte (mb, CEE_RET);
 }
 
+G_GNUC_UNUSED static void
+code_for (MonoMethod *method) {
+       MonoMethodHeader *header = mono_method_get_header (method);
+       printf ("CODE FOR %s: \n%s.\n", mono_method_full_name (method, TRUE), mono_disasm_code (0, method, header->code, header->code + header->code_size));
+}
+
 /**
  * mono_marshal_get_native_wrapper:
  * @method: The MonoMethod to wrap.
@@ -8178,8 +8171,20 @@ mono_marshal_get_native_wrapper (MonoMethod *method, gboolean check_exceptions,
                if (method->string_ctor)
                        csig->ret = &mono_defaults.string_class->byval_arg;
 
-               if (sig->hasthis)
+               if (sig->hasthis) {
+                       int pos;
+
+                       /*
+                        * Add a null check since public icalls can be called with 'call' which
+                        * does no such check.
+                        */
+                       mono_mb_emit_byte (mb, CEE_LDARG_0);                    
+                       pos = mono_mb_emit_branch (mb, CEE_BRTRUE);
+                       mono_mb_emit_exception (mb, "NullReferenceException", NULL);
+                       mono_mb_patch_branch (mb, pos);
+
                        mono_mb_emit_byte (mb, CEE_LDARG_0);
+               }
 
                for (i = 0; i < sig->param_count; i++)
                        mono_mb_emit_ldarg (mb, i + sig->hasthis);
@@ -8224,7 +8229,7 @@ mono_marshal_get_native_wrapper (MonoMethod *method, gboolean check_exceptions,
                        mono_metadata_free_marshal_spec (mspecs [i]);
        g_free (mspecs);
 
-       /* printf ("CODE FOR %s: \n%s.\n", mono_method_full_name (res, TRUE), mono_disasm_code (0, res, ((MonoMethodNormal*)res)->header->code, ((MonoMethodNormal*)res)->header->code + ((MonoMethodNormal*)res)->header->code_size)); */ 
+       /* code_for (res); */
 
        return res;
 }
@@ -8265,7 +8270,9 @@ mono_marshal_get_native_func_wrapper (MonoImage *image, MonoMethodSignature *sig
                                                                        mb, csig, csig->param_count + 16);
        mono_mb_free (mb);
 
-       /* printf ("CODE FOR %s: \n%s.\n", mono_method_full_name (res, TRUE), mono_disasm_code (0, res, ((MonoMethodNormal*)res)->header->code, ((MonoMethodNormal*)res)->header->code + ((MonoMethodNormal*)res)->header->code_size)); */ 
+       mono_marshal_set_wrapper_info (res, NULL);
+
+       /* code_for (res); */
 
        return res;
 }
@@ -8279,7 +8286,7 @@ mono_marshal_get_native_func_wrapper (MonoImage *image, MonoMethodSignature *sig
  * THIS_LOC is the memory location where the target of the delegate is stored.
  */
 void
-mono_marshal_emit_managed_wrapper (MonoMethodBuilder *mb, MonoMethodSignature *invoke_sig, MonoMarshalSpec **mspecs, EmitMarshalContext* m, MonoMethod *method, MonoObject** this_loc)
+mono_marshal_emit_managed_wrapper (MonoMethodBuilder *mb, MonoMethodSignature *invoke_sig, MonoMarshalSpec **mspecs, EmitMarshalContext* m, MonoMethod *method, uint32_t target_handle)
 {
        MonoMethodSignature *sig, *csig;
        int i, *tmp_locals;
@@ -8338,16 +8345,16 @@ mono_marshal_emit_managed_wrapper (MonoMethodBuilder *mb, MonoMethodSignature *i
        emit_thread_interrupt_checkpoint (mb);
 
        if (sig->hasthis) {
-               if (this_loc) {
-                       mono_mb_emit_ptr (mb, this_loc);
-                       mono_mb_emit_byte (mb, CEE_LDIND_REF);
+               if (target_handle) {
+                       mono_mb_emit_icon (mb, (gint32)target_handle);
+                       mono_mb_emit_icall (mb, mono_gchandle_get_target);
                } else {
                        /* fixme: */
                        g_assert_not_reached ();
                }
        } else if (closed) {
-               mono_mb_emit_ptr (mb, this_loc);
-               mono_mb_emit_byte (mb, CEE_LDIND_REF);
+               mono_mb_emit_icon (mb, (gint32)target_handle);
+               mono_mb_emit_icall (mb, mono_gchandle_get_target);
        }
 
        for (i = 0; i < sig->param_count; i++) {
@@ -8495,7 +8502,7 @@ mono_marshal_set_callconv_from_modopt (MonoMethod *method, MonoMethodSignature *
  * generates IL code to call managed methods from unmanaged code 
  */
 MonoMethod *
-mono_marshal_get_managed_wrapper (MonoMethod *method, MonoClass *delegate_klass, MonoObject **this_loc)
+mono_marshal_get_managed_wrapper (MonoMethod *method, MonoClass *delegate_klass, uint32_t target_handle)
 {
        static MonoClass *UnmanagedFunctionPointerAttribute;
        MonoMethodSignature *sig, *csig, *invoke_sig;
@@ -8516,7 +8523,7 @@ mono_marshal_get_managed_wrapper (MonoMethod *method, MonoClass *delegate_klass,
         * options.
         */
        cache = get_cache (&method->klass->image->managed_wrapper_cache, mono_aligned_addr_hash, NULL);
-       if (!this_loc && (res = mono_marshal_find_in_cache (cache, method)))
+       if (!target_handle && (res = mono_marshal_find_in_cache (cache, method)))
                return res;
 
        invoke = mono_get_delegate_invoke (delegate_klass);
@@ -8529,8 +8536,11 @@ mono_marshal_get_managed_wrapper (MonoMethod *method, MonoClass *delegate_klass,
 
        mb = mono_mb_new (method->klass, method->name, MONO_WRAPPER_NATIVE_TO_MANAGED);
 
+       /*the target gchandle must be the first entry after size and the wrapper itself.*/
+       mono_mb_add_data (mb, GUINT_TO_POINTER (target_handle));
+
        /* we copy the signature, so that we can modify it */
-       if (this_loc)
+       if (target_handle)
                /* Need to free this later */
                csig = mono_metadata_signature_dup (invoke_sig);
        else
@@ -8622,9 +8632,9 @@ mono_marshal_get_managed_wrapper (MonoMethod *method, MonoClass *delegate_klass,
                        mono_custom_attrs_free (cinfo);
        }
 
-       mono_marshal_emit_managed_wrapper (mb, invoke_sig, mspecs, &m, method, this_loc);
+       mono_marshal_emit_managed_wrapper (mb, invoke_sig, mspecs, &m, method, target_handle);
 
-       if (!this_loc)
+       if (!target_handle)
                res = mono_mb_create_and_cache (cache, method,
                                                                                         mb, csig, sig->param_count + 16);
        else {
@@ -8638,7 +8648,7 @@ mono_marshal_get_managed_wrapper (MonoMethod *method, MonoClass *delegate_klass,
                        mono_metadata_free_marshal_spec (mspecs [i]);
        g_free (mspecs);
 
-       /* printf ("CODE FOR %s: \n%s.\n", mono_method_full_name (res, TRUE), mono_disasm_code (0, res, ((MonoMethodNormal*)res)->header->code, ((MonoMethodNormal*)res)->header->code + ((MonoMethodNormal*)res)->header->code_size)); */
+       /* code_for (res); */
 
        return res;
 }
@@ -8683,7 +8693,7 @@ mono_marshal_get_vtfixup_ftnptr (MonoImage *image, guint32 token, guint16 type)
 
                /* FIXME: Implement VTFIXUP_TYPE_FROM_UNMANAGED_RETAIN_APPDOMAIN. */
 
-               mono_marshal_emit_managed_wrapper (mb, sig, mspecs, &m, method, NULL);
+               mono_marshal_emit_managed_wrapper (mb, sig, mspecs, &m, method, 0);
 
                mb->dynamic = 1;
                method = mono_mb_create_method (mb, csig, sig->param_count + 16);
@@ -9273,7 +9283,7 @@ mono_marshal_get_unbox_wrapper (MonoMethod *method)
                                                                                 mb, sig, sig->param_count + 16);
        mono_mb_free (mb);
 
-       /* printf ("CODE FOR %s: \n%s.\n", mono_method_full_name (res, TRUE), mono_disasm_code (0, res, ((MonoMethodNormal*)res)->header->code, ((MonoMethodNormal*)res)->header->code + ((MonoMethodNormal*)res)->header->code_size)); */
+       /* code_for (res); */
 
        return res;     
 }
@@ -9587,7 +9597,7 @@ mono_marshal_get_array_address (int rank, int elem_size)
                info->rank = rank;
                info->elem_size = elem_size;
 
-               mono_marshal_method_set_wrapper_data (ret, info);
+               mono_marshal_set_wrapper_info (ret, info);
        }
        mono_marshal_unlock ();
        return ret;
@@ -9928,6 +9938,9 @@ ves_icall_System_Runtime_InteropServices_Marshal_SizeOf (MonoReflectionType *rty
 
        type = rtype->type;
        klass = mono_class_from_mono_type (type);
+       if (!mono_class_init (klass))
+               mono_raise_exception (mono_class_get_exception_for_failure (klass));
+
        layout = (klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK);
 
        if (layout == TYPE_ATTRIBUTE_AUTO_LAYOUT) {
@@ -10008,6 +10021,7 @@ ves_icall_System_Runtime_InteropServices_Marshal_PtrToStructure (gpointer src, M
 MonoObject *
 ves_icall_System_Runtime_InteropServices_Marshal_PtrToStructure_type (gpointer src, MonoReflectionType *type)
 {
+       MonoClass *klass;
        MonoDomain *domain = mono_domain_get (); 
        MonoObject *res;
 
@@ -10016,7 +10030,11 @@ ves_icall_System_Runtime_InteropServices_Marshal_PtrToStructure_type (gpointer s
        MONO_CHECK_ARG_NULL (src);
        MONO_CHECK_ARG_NULL (type);
 
-       res = mono_object_new (domain, mono_class_from_mono_type (type->type));
+       klass = mono_class_from_mono_type (type->type);
+       if (!mono_class_init (klass))
+               mono_raise_exception (mono_class_get_exception_for_failure (klass));
+
+       res = mono_object_new (domain, klass);
 
        ptr_to_structure (src, res);
 
@@ -10038,6 +10056,8 @@ ves_icall_System_Runtime_InteropServices_Marshal_OffsetOf (MonoReflectionType *t
 
        fname = mono_string_to_utf8 (field_name);
        klass = mono_class_from_mono_type (type->type);
+       if (!mono_class_init (klass))
+               mono_raise_exception (mono_class_get_exception_for_failure (klass));
 
        while (klass && match_index == -1) {
                MonoClassField* field;
@@ -10180,6 +10200,8 @@ ves_icall_System_Runtime_InteropServices_Marshal_DestroyStructure (gpointer src,
        MONO_CHECK_ARG_NULL (type);
 
        klass = mono_class_from_mono_type (type->type);
+       if (!mono_class_init (klass))
+               mono_raise_exception (mono_class_get_exception_for_failure (klass));
 
        mono_struct_delete_old (klass, (char *)src);
 }
@@ -10284,7 +10306,11 @@ ves_icall_System_Runtime_InteropServices_Marshal_UnsafeAddrOfPinnedArrayElement
 MonoDelegate*
 ves_icall_System_Runtime_InteropServices_Marshal_GetDelegateForFunctionPointerInternal (void *ftn, MonoReflectionType *type)
 {
-       return mono_ftnptr_to_delegate (mono_type_get_class (type->type), ftn);
+       MonoClass *klass = mono_type_get_class (type->type);
+       if (!mono_class_init (klass))
+               mono_raise_exception (mono_class_get_exception_for_failure (klass));
+
+       return mono_ftnptr_to_delegate (klass, ftn);
 }
 
 /**
@@ -10690,7 +10716,7 @@ mono_marshal_asany (MonoObject *o, MonoMarshalNative string_encoding, int param_
        case MONO_TYPE_STRING:
                switch (string_encoding) {
                case MONO_NATIVE_LPWSTR:
-                       return mono_string_to_utf16 ((MonoString*)o);
+                       return mono_marshal_string_to_utf16_copy ((MonoString*)o);
                        break;
                case MONO_NATIVE_LPSTR:
                        return mono_string_to_lpstr ((MonoString*)o);
@@ -11036,14 +11062,17 @@ mono_marshal_free_dynamic_wrappers (MonoMethod *method)
 {
        g_assert (method->dynamic);
 
-       mono_marshal_lock ();
+       /* This could be called during shutdown */
+       if (marshal_mutex_initialized)
+               mono_marshal_lock ();
        /* 
         * FIXME: We currently leak the wrappers. Freeing them would be tricky as
         * they could be shared with other methods ?
         */
        if (method->klass->image->runtime_invoke_direct_cache)
                g_hash_table_remove (method->klass->image->runtime_invoke_direct_cache, method);
-       mono_marshal_unlock ();
+       if (marshal_mutex_initialized)
+               mono_marshal_unlock ();
 }
 
 /*