Merge pull request #1659 from alexanderkyte/stringbuilder-referencesource
[mono.git] / mono / metadata / marshal.c
index adb955b4699e59c874d3aa2a929fdd1a6cad0fae..f688ff41b8da4eac788cfccd4bf6aa08ddbdb384 100644 (file)
@@ -628,13 +628,11 @@ mono_free_lparray (MonoArray *array, gpointer* nativeArray)
                return;
        klass = array->obj.vtable->klass;
 
-       switch (klass->element_class->byval_arg.type) {
-               case MONO_TYPE_CLASS:
-                       for(i = 0; i < array->max_length; ++i)  
-                               mono_marshal_free_ccw(nativeArray[i]);
-                       free(nativeArray);
-               break;
-       }               
+       if (klass->element_class->byval_arg.type == MONO_TYPE_CLASS) {
+               for(i = 0; i < array->max_length; ++i)
+                       mono_marshal_free_ccw (mono_array_get (array, MonoObject*, i));
+               free(nativeArray);
+       }
 #endif
 }
 
@@ -696,49 +694,16 @@ mono_array_to_byte_byvalarray (gpointer native_arr, MonoArray *arr, guint32 elnu
        mono_array_to_byvalarray (native_arr, arr, mono_defaults.byte_class, elnum);
 }
 
-void
-mono_string_utf8_to_builder (MonoStringBuilder *sb, char *text)
-{
-       GError *error = NULL;
-       guint16 *ut;
-       glong items_written;
-       int l;
-
-       if (!sb || !text)
-               return;
-
-       l = strlen (text);
-
-       ut = g_utf8_to_utf16 (text, l, NULL, &items_written, &error);
-       
-       if (items_written > mono_stringbuilder_capacity (sb))
-               items_written = mono_stringbuilder_capacity (sb);
-       
-       if (!error) {
-               if (! sb->str || sb->str == sb->cached_str)
-                       MONO_OBJECT_SETREF (sb, str, mono_string_new_size (mono_domain_get (), items_written));
-               
-               memcpy (mono_string_chars (sb->str), ut, items_written * 2);
-               sb->length = items_written;
-               sb->cached_str = NULL;
-       } else 
-               g_error_free (error);
-
-       g_free (ut);
-}
-
-MonoStringBuilder *
-mono_string_utf8_to_builder2 (char *text)
+static MonoStringBuilder *
+mono_string_builder_new (int starting_string_length)
 {
-       int l;
-       MonoStringBuilder *sb;
        static MonoClass *string_builder_class;
        static MonoMethod *sb_ctor;
-       void *args [1];
-       MonoObject *exc;
+       static void *args [1];
+       int initial_len = starting_string_length;
 
-       if (!text)
-               return NULL;
+       if (initial_len < 0)
+               initial_len = 0;
 
        if (!string_builder_class) {
                MonoMethodDesc *desc;
@@ -749,78 +714,101 @@ mono_string_utf8_to_builder2 (char *text)
                sb_ctor = mono_method_desc_search_in_class (desc, string_builder_class);
                g_assert (sb_ctor);
                mono_method_desc_free (desc);
-       }
 
-       l = strlen (text);
+               // We make a new array in the _to_builder function, so this
+               // array will always be garbage collected.
+               args [0] = &initial_len;
+       }
 
-       sb = (MonoStringBuilder*)mono_object_new (mono_domain_get (), string_builder_class);
+       MonoStringBuilder *sb = (MonoStringBuilder*)mono_object_new (mono_domain_get (), string_builder_class);
+       MonoObject *exc;
        g_assert (sb);
-       args [0] = &l;
+
        mono_runtime_invoke (sb_ctor, sb, args, &exc);
+
+       g_assert (sb->chunkChars->max_length >= initial_len);
        g_assert (!exc);
 
-       mono_string_utf8_to_builder (sb, text);
+       return sb;
+}
+
+static void
+mono_string_utf16_to_builder_copy (MonoStringBuilder *sb, gunichar2 *text, size_t string_len)
+{
+       gunichar2 *charDst = (gunichar2 *)sb->chunkChars->vector;
+       gunichar2 *charSrc = (gunichar2 *)text;
+       memcpy (charDst, charSrc, sizeof (gunichar2) * string_len);
+
+       sb->chunkLength = string_len;
+
+       return;
+}
+
+MonoStringBuilder *
+mono_string_utf16_to_builder2 (gunichar2 *text)
+{
+       if (!text)
+               return NULL;
+
+       int len;
+       for (len = 0; text [len] != 0; ++len);
+
+       MonoStringBuilder *sb = mono_string_builder_new (len);
+       mono_string_utf16_to_builder (sb, text);
 
        return sb;
 }
 
-/*
- * FIXME: This routine does not seem to do what it seems to do
- * the @text is never copied into the string builder
- */
 void
-mono_string_utf16_to_builder (MonoStringBuilder *sb, gunichar2 *text)
+mono_string_utf8_to_builder (MonoStringBuilder *sb, char *text)
 {
-       guint32 len;
-
        if (!sb || !text)
                return;
 
-       g_assert (mono_string_chars (sb->str) == text);
+       int len = strlen (text);
+       if (len > mono_string_builder_capacity (sb))
+               len = mono_string_builder_capacity (sb);
 
-       for (len = 0; text [len] != 0; ++len)
-               ;
+       GError *error = NULL;
+       glong copied;
+       gunichar2* ut = g_utf8_to_utf16 (text, len, NULL, &copied, &error);
 
-       sb->length = len;
+       if (!error) {
+               MONO_OBJECT_SETREF (sb, chunkPrevious, NULL);
+               mono_string_utf16_to_builder_copy (sb, ut, copied);
+       } else
+               g_error_free (error);
+
+       g_free (ut);
 }
 
 MonoStringBuilder *
-mono_string_utf16_to_builder2 (gunichar2 *text)
+mono_string_utf8_to_builder2 (char *text)
 {
-       int len;
-       MonoStringBuilder *sb;
-       static MonoClass *string_builder_class;
-       static MonoMethod *sb_ctor;
-       void *args [1];
-       MonoObject *exc;
-
        if (!text)
                return NULL;
 
-       if (!string_builder_class) {
-               MonoMethodDesc *desc;
+       int len = strlen (text);
+       MonoStringBuilder *sb = mono_string_builder_new (len);
+       mono_string_utf8_to_builder (sb, text);
 
-               string_builder_class = mono_class_from_name (mono_defaults.corlib, "System.Text", "StringBuilder");
-               g_assert (string_builder_class);
-               desc = mono_method_desc_new (":.ctor(int)", FALSE);
-               sb_ctor = mono_method_desc_search_in_class (desc, string_builder_class);
-               g_assert (sb_ctor);
-               mono_method_desc_free (desc);
-       }
+       return sb;
+}
 
-       for (len = 0; text [len] != 0; ++len)
-               ;
 
-       sb = (MonoStringBuilder*)mono_object_new (mono_domain_get (), string_builder_class);
-       g_assert (sb);
-       args [0] = &len;
-       mono_runtime_invoke (sb_ctor, sb, args, &exc);
-       g_assert (!exc);
+void
+mono_string_utf16_to_builder (MonoStringBuilder *sb, gunichar2 *text)
+{
+       if (!sb || !text)
+               return;
 
-       sb->length = len;
-       memcpy (mono_string_chars (sb->str), text, len * 2);
+       guint32 len;
+       for (len = 0; text [len] != 0; ++len);
+       
+       if (len > mono_string_builder_capacity (sb))
+               len = mono_string_builder_capacity (sb);
 
-       return sb;
+       mono_string_utf16_to_builder_copy (sb, text, len);
 }
 
 /**
@@ -833,35 +821,38 @@ mono_string_utf16_to_builder2 (gunichar2 *text)
  *
  * The return value must be released with g_free.
  */
-gpointer
+gchar*
 mono_string_builder_to_utf8 (MonoStringBuilder *sb)
 {
        GError *error = NULL;
-       gchar *tmp, *res = NULL;
 
        if (!sb)
                return NULL;
 
-       if ((sb->str == sb->cached_str) && (sb->str->length == 0)) {
-               /* 
-                * The sb could have been allocated with the default capacity and be empty.
-                * we need to alloc a buffer of the default capacity in this case.
-                */
-               MONO_OBJECT_SETREF (sb, str, mono_string_new_size (mono_domain_get (), 16));
-               sb->cached_str = NULL;
-       }
 
-       tmp = g_utf16_to_utf8 (mono_string_chars (sb->str), sb->length, NULL, NULL, &error);
+       gunichar2 *str_utf16 = mono_string_builder_to_utf16 (sb);
+
+       guint str_len = mono_string_builder_string_length (sb);
+
+       gchar *tmp = g_utf16_to_utf8 (str_utf16, str_len, NULL, NULL, &error);
+
        if (error) {
                g_error_free (error);
+               g_free (str_utf16);
                mono_raise_exception (mono_get_exception_execution_engine ("Failed to convert StringBuilder from utf16 to utf8"));
+               return NULL;
        } else {
-               res = mono_marshal_alloc (mono_stringbuilder_capacity (sb) + 1);
-               memcpy (res, tmp, sb->length + 1);
+               guint len = mono_string_builder_capacity (sb) + 1;
+               gchar *res = mono_marshal_alloc (len * sizeof (gchar));
+               g_assert (str_len < len);
+               memcpy (res, tmp, str_len * sizeof (gchar));
+               res[str_len] = '\0';
+
+
+               g_free (str_utf16);
                g_free (tmp);
+               return res;
        }
-
-       return res;
 }
 
 /**
@@ -874,35 +865,43 @@ mono_string_builder_to_utf8 (MonoStringBuilder *sb)
  *
  * The return value must not be freed.
  */
-gpointer
+gunichar2*
 mono_string_builder_to_utf16 (MonoStringBuilder *sb)
 {
        if (!sb)
                return NULL;
 
-       g_assert (sb->str);
+       g_assert (sb->chunkChars);
 
-       /*
-        * The stringbuilder might not have ownership of this string. If this is
-        * the case, we must duplicate the string, so that we don't munge immutable
-        * strings
-        */
-       if (sb->str == sb->cached_str) {
-               /* 
-                * The sb could have been allocated with the default capacity and be empty.
-                * we need to alloc a buffer of the default capacity in this case.
-                */
-               if (sb->str->length == 0)
-                       MONO_OBJECT_SETREF (sb, str, mono_string_new_size (mono_domain_get (), 16));
-               else
-                       MONO_OBJECT_SETREF (sb, str, mono_string_new_utf16 (mono_domain_get (), mono_string_chars (sb->str), mono_stringbuilder_capacity (sb)));
-               sb->cached_str = NULL;
-       }
-       
-       if (sb->length == 0)
-               *(mono_string_chars (sb->str)) = '\0';
+       guint len = mono_string_builder_capacity (sb);
+
+       if (len == 0)
+               len = 1;
 
-       return mono_string_chars (sb->str);
+       gunichar2 *str = mono_marshal_alloc ((len + 1) * sizeof (gunichar2));
+       str[len] = '\0';
+
+       if (len == 0)
+               return str;
+
+       MonoStringBuilder* chunk = sb;
+       do {
+               if (chunk->chunkLength > 0) {
+                       // Check that we will not overrun our boundaries.
+                       gunichar2 *source = (gunichar2 *)chunk->chunkChars->vector;
+
+                       if (chunk->chunkLength <= len) {
+                               memcpy (str + chunk->chunkOffset, source, chunk->chunkLength * sizeof(gunichar2));
+                       } else {
+                               g_error ("A chunk in the StringBuilder had a length longer than expected from the offset.");
+                       }
+
+                       len -= chunk->chunkLength;
+               }
+               chunk = chunk->chunkPrevious;
+       } while (chunk != NULL);
+
+       return str;
 }
 
 static gpointer
@@ -1708,27 +1707,8 @@ emit_object_to_ptr_conv (MonoMethodBuilder *mb, MonoType *type, MonoMarshalConv
 #endif /* DISABLE_COM */
 
        case MONO_MARSHAL_CONV_SAFEHANDLE: {
-               int dar_release_slot, pos;
+               int pos;
                
-               dar_release_slot = mono_mb_add_local (mb, &mono_defaults.boolean_class->byval_arg);
-
-               /*
-                * The following is ifdefed-out, because I have no way of doing the
-                * DangerousRelease when destroying the structure
-                */
-#if 0
-               /* set release = false */
-               mono_mb_emit_icon (mb, 0);
-               mono_mb_emit_stloc (mb, dar_release_slot);
-               if (!sh_dangerous_add_ref)
-                       init_safe_handle ();
-
-               /* safehandle.DangerousAddRef (ref release) */
-               mono_mb_emit_ldloc (mb, 0); /* the source */
-               mono_mb_emit_byte (mb, CEE_LDIND_I);
-               mono_mb_emit_ldloc_addr (mb, dar_release_slot);
-               mono_mb_emit_managed_call (mb, sh_dangerous_add_ref, NULL);
-#endif
                mono_mb_emit_ldloc (mb, 0);
                mono_mb_emit_byte (mb, CEE_LDIND_I);
                pos = mono_mb_emit_branch (mb, CEE_BRTRUE);
@@ -2010,9 +1990,10 @@ emit_struct_free (MonoMethodBuilder *mb, MonoClass *klass, int struct_var)
 static void
 emit_thread_interrupt_checkpoint_call (MonoMethodBuilder *mb, gpointer checkpoint_func)
 {
-       int pos_noabort;
+       int pos_noabort, pos_noex;
 
-       mono_mb_emit_ptr (mb, (gpointer) mono_thread_interruption_request_flag ());
+       mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
+       mono_mb_emit_byte (mb, CEE_MONO_LDPTR_INT_REQ_FLAG);
        mono_mb_emit_byte (mb, CEE_LDIND_U4);
        pos_noabort = mono_mb_emit_branch (mb, CEE_BRFALSE);
 
@@ -2020,6 +2001,12 @@ emit_thread_interrupt_checkpoint_call (MonoMethodBuilder *mb, gpointer checkpoin
        mono_mb_emit_byte (mb, CEE_MONO_NOT_TAKEN);
 
        mono_mb_emit_icall (mb, checkpoint_func);
+       /* Throw the exception returned by the checkpoint function, if any */
+       mono_mb_emit_byte (mb, CEE_DUP);
+       pos_noex = mono_mb_emit_branch (mb, CEE_BRFALSE);
+       mono_mb_emit_byte (mb, CEE_THROW);
+       mono_mb_patch_branch (mb, pos_noex);
+       mono_mb_emit_byte (mb, CEE_POP);
        
        mono_mb_patch_branch (mb, pos_noabort);
 }
@@ -2036,7 +2023,7 @@ emit_thread_interrupt_checkpoint (MonoMethodBuilder *mb)
 static void
 emit_thread_force_interrupt_checkpoint (MonoMethodBuilder *mb)
 {
-       emit_thread_interrupt_checkpoint_call (mb, mono_thread_force_interruption_checkpoint);
+       emit_thread_interrupt_checkpoint_call (mb, mono_thread_force_interruption_checkpoint_noraise);
 }
 
 void
@@ -2320,7 +2307,6 @@ static gboolean
 mono_marshal_need_free (MonoType *t, MonoMethodPInvoke *piinfo, MonoMarshalSpec *spec)
 {
        MonoMarshalNative encoding;
-       MonoMarshalConv conv;
 
        switch (t->type) {
        case MONO_TYPE_VALUETYPE:
@@ -2330,7 +2316,7 @@ mono_marshal_need_free (MonoType *t, MonoMethodPInvoke *piinfo, MonoMarshalSpec
        case MONO_TYPE_CLASS:
                if (t->data.klass == mono_defaults.stringbuilder_class) {
                        gboolean need_free;
-                       conv = mono_marshal_get_ptr_to_stringbuilder_conv (piinfo, spec, &need_free);
+                       mono_marshal_get_ptr_to_stringbuilder_conv (piinfo, spec, &need_free);
                        return need_free;
                }
                return FALSE;
@@ -2460,14 +2446,18 @@ mono_marshal_method_from_wrapper (MonoMethod *wrapper)
                res = mono_marshal_get_wrapper_info (wrapper);
                if (res == NULL)
                        return wrapper;
-               if (wrapper->is_inflated)
+               if (wrapper->is_inflated) {
+                       MonoError error;
+                       MonoMethod *result;
                        /*
                         * A method cannot be inflated and a wrapper at the same time, so the wrapper info
                         * contains an uninflated method.
                         */
-                       return mono_class_inflate_generic_method (res, mono_method_get_context (wrapper));
-               else
-                       return res;
+                       result = mono_class_inflate_generic_method_checked (res, mono_method_get_context (wrapper), &error);
+                       g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
+                       return result;
+               }
+               return res;
        case MONO_WRAPPER_MANAGED_TO_NATIVE:
                info = mono_marshal_get_wrapper_info (wrapper);
                if (info && (info->subtype == WRAPPER_SUBTYPE_NONE || info->subtype == WRAPPER_SUBTYPE_NATIVE_FUNC_AOT || info->subtype == WRAPPER_SUBTYPE_PINVOKE))
@@ -2582,10 +2572,8 @@ check_generic_wrapper_cache (GHashTable *cache, MonoMethod *orig_method, gpointe
        MonoMethod *res;
        MonoMethod *inst, *def;
        MonoGenericContext *ctx;
-       MonoMethod *def_method;
 
        g_assert (orig_method->is_inflated);
-       def_method = ((MonoMethodInflated*)orig_method)->declaring;
        ctx = mono_method_get_context (orig_method);
 
        /*
@@ -2600,7 +2588,9 @@ check_generic_wrapper_cache (GHashTable *cache, MonoMethod *orig_method, gpointe
         */
        def = mono_marshal_find_in_cache (cache, def_key);
        if (def) {
-               inst = mono_class_inflate_generic_method (def, ctx);
+               MonoError error;
+               inst = mono_class_inflate_generic_method_checked (def, ctx, &error);
+               g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
                /* Cache it */
                mono_memory_barrier ();
                mono_marshal_lock ();
@@ -2618,12 +2608,14 @@ check_generic_wrapper_cache (GHashTable *cache, MonoMethod *orig_method, gpointe
 static MonoMethod*
 cache_generic_wrapper (GHashTable *cache, MonoMethod *orig_method, MonoMethod *def, MonoGenericContext *ctx, gpointer key)
 {
+       MonoError error;
        MonoMethod *inst, *res;
 
        /*
         * We use the same cache for the generic definition and the instances.
         */
-       inst = mono_class_inflate_generic_method (def, ctx);
+       inst = mono_class_inflate_generic_method_checked (def, ctx, &error);
+       g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
        mono_memory_barrier ();
        mono_marshal_lock ();
        res = g_hash_table_lookup (cache, key);
@@ -2638,6 +2630,7 @@ cache_generic_wrapper (GHashTable *cache, MonoMethod *orig_method, MonoMethod *d
 static MonoMethod*
 check_generic_delegate_wrapper_cache (GHashTable *cache, MonoMethod *orig_method, MonoMethod *def_method, MonoGenericContext *ctx)
 {
+       MonoError error;
        MonoMethod *res;
        MonoMethod *inst, *def;
 
@@ -2653,7 +2646,9 @@ check_generic_delegate_wrapper_cache (GHashTable *cache, MonoMethod *orig_method
         */
        def = mono_marshal_find_in_cache (cache, def_method->klass);
        if (def) {
-               inst = mono_class_inflate_generic_method (def, ctx);
+               inst = mono_class_inflate_generic_method_checked (def, ctx, &error);
+               g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
+
                /* Cache it */
                mono_memory_barrier ();
                mono_marshal_lock ();
@@ -2671,12 +2666,15 @@ check_generic_delegate_wrapper_cache (GHashTable *cache, MonoMethod *orig_method
 static MonoMethod*
 cache_generic_delegate_wrapper (GHashTable *cache, MonoMethod *orig_method, MonoMethod *def, MonoGenericContext *ctx)
 {
+       MonoError error;
        MonoMethod *inst, *res;
 
        /*
         * We use the same cache for the generic definition and the instances.
         */
-       inst = mono_class_inflate_generic_method (def, ctx);
+       inst = mono_class_inflate_generic_method_checked (def, ctx, &error);
+       g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
+
        mono_memory_barrier ();
        mono_marshal_lock ();
        res = g_hash_table_lookup (cache, orig_method->klass);
@@ -2979,34 +2977,34 @@ mono_marshal_get_delegate_end_invoke (MonoMethod *method)
 typedef struct
 {
        MonoMethodSignature *sig;
-       MonoMethod *method;
-} SignatureMethodPair;
+       gpointer pointer;
+} SignaturePointerPair;
 
 static guint
-signature_method_pair_hash (gconstpointer data)
+signature_pointer_pair_hash (gconstpointer data)
 {
-       SignatureMethodPair *pair = (SignatureMethodPair*)data;
+       SignaturePointerPair *pair = (SignaturePointerPair*)data;
 
-       return mono_signature_hash (pair->sig) ^ mono_aligned_addr_hash (pair->method);
+       return mono_signature_hash (pair->sig) ^ mono_aligned_addr_hash (pair->pointer);
 }
 
 static gboolean
-signature_method_pair_equal (SignatureMethodPair *pair1, SignatureMethodPair *pair2)
+signature_pointer_pair_equal (gconstpointer data1, gconstpointer data2)
 {
-       return mono_metadata_signature_equal (pair1->sig, pair2->sig) && (pair1->method == pair2->method);
+       SignaturePointerPair *pair1 = (SignaturePointerPair*) data1, *pair2 = (SignaturePointerPair*) data2;
+       return mono_metadata_signature_equal (pair1->sig, pair2->sig) && (pair1->pointer == pair2->pointer);
 }
 
 static gboolean
-signature_method_pair_matches_method (gpointer key, gpointer value, gpointer user_data)
+signature_pointer_pair_matches_pointer (gpointer key, gpointer value, gpointer user_data)
 {
-       SignatureMethodPair *pair = (SignatureMethodPair*)key;
-       MonoMethod *method = (MonoMethod*)user_data;
+       SignaturePointerPair *pair = (SignaturePointerPair*)key;
 
-       return pair->method == method;
+       return pair->pointer == user_data;
 }
 
 static void
-free_signature_method_pair (SignatureMethodPair *pair)
+free_signature_pointer_pair (SignaturePointerPair *pair)
 {
        g_free (pair);
 }
@@ -3020,8 +3018,8 @@ mono_marshal_get_delegate_invoke_internal (MonoMethod *method, gboolean callvirt
        MonoMethod *res;
        GHashTable *cache;
        gpointer cache_key = NULL;
-       SignatureMethodPair key;
-       SignatureMethodPair *new_key;
+       SignaturePointerPair key;
+       SignaturePointerPair *new_key;
        int local_prev, local_target;
        int pos0;
        char *name;
@@ -3110,10 +3108,10 @@ mono_marshal_get_delegate_invoke_internal (MonoMethod *method, gboolean callvirt
                /* We need to cache the signature+method pair */
                mono_marshal_lock ();
                if (!*cache_ptr)
-                       *cache_ptr = g_hash_table_new_full (signature_method_pair_hash, (GEqualFunc)signature_method_pair_equal, (GDestroyNotify)free_signature_method_pair, NULL);
+                       *cache_ptr = g_hash_table_new_full (signature_pointer_pair_hash, (GEqualFunc)signature_pointer_pair_equal, (GDestroyNotify)free_signature_pointer_pair, NULL);
                cache = *cache_ptr;
                key.sig = invoke_sig;
-               key.method = target_method;
+               key.pointer = target_method;
                res = g_hash_table_lookup (cache, &key);
                mono_marshal_unlock ();
                if (res)
@@ -3181,10 +3179,13 @@ mono_marshal_get_delegate_invoke_internal (MonoMethod *method, gboolean callvirt
        mono_mb_emit_ldloc (mb, local_prev);
        for (i = 0; i < sig->param_count; i++)
                mono_mb_emit_ldarg (mb, i + 1);
-       if (ctx)
-               mono_mb_emit_op (mb, CEE_CALLVIRT, mono_class_inflate_generic_method (method, &container->context));
-       else
+       if (ctx) {
+               MonoError error;
+               mono_mb_emit_op (mb, CEE_CALLVIRT, mono_class_inflate_generic_method_checked (method, &container->context, &error));
+               g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
+       } else {
                mono_mb_emit_op (mb, CEE_CALLVIRT, method);
+       }
        if (sig->ret->type != MONO_TYPE_VOID)
                mono_mb_emit_byte (mb, CEE_POP);
 
@@ -3261,7 +3262,7 @@ mono_marshal_get_delegate_invoke_internal (MonoMethod *method, gboolean callvirt
                def = mono_mb_create_and_cache (cache, cache_key, mb, sig, sig->param_count + 16);
                res = cache_generic_delegate_wrapper (cache, orig_method, def, ctx);
        } else if (callvirt) {
-               new_key = g_new0 (SignatureMethodPair, 1);
+               new_key = g_new0 (SignaturePointerPair, 1);
                *new_key = key;
 
                info = mono_wrapper_info_create (mb, subtype);
@@ -4159,20 +4160,23 @@ emit_marshal_custom (EmitMarshalContext *m, int argnum, MonoType *t,
        int pos2;
 
        if (!ICustomMarshaler) {
-               ICustomMarshaler = mono_class_from_name (mono_defaults.corlib, "System.Runtime.InteropServices", "ICustomMarshaler");
-               if (!ICustomMarshaler) {
+               MonoClass *klass = mono_class_from_name (mono_defaults.corlib, "System.Runtime.InteropServices", "ICustomMarshaler");
+               if (!klass) {
                        exception_msg = g_strdup ("Current profile doesn't support ICustomMarshaler");
                        goto handle_exception;
                }
 
-               cleanup_native = mono_class_get_method_from_name (ICustomMarshaler, "CleanUpNativeData", 1);
+               cleanup_native = mono_class_get_method_from_name (klass, "CleanUpNativeData", 1);
                g_assert (cleanup_native);
-               cleanup_managed = mono_class_get_method_from_name (ICustomMarshaler, "CleanUpManagedData", 1);
+               cleanup_managed = mono_class_get_method_from_name (klass, "CleanUpManagedData", 1);
                g_assert (cleanup_managed);
-               marshal_managed_to_native = mono_class_get_method_from_name (ICustomMarshaler, "MarshalManagedToNative", 1);
+               marshal_managed_to_native = mono_class_get_method_from_name (klass, "MarshalManagedToNative", 1);
                g_assert (marshal_managed_to_native);
-               marshal_native_to_managed = mono_class_get_method_from_name (ICustomMarshaler, "MarshalNativeToManaged", 1);
+               marshal_native_to_managed = mono_class_get_method_from_name (klass, "MarshalNativeToManaged", 1);
                g_assert (marshal_native_to_managed);
+
+               mono_memory_barrier ();
+               ICustomMarshaler = klass;
        }
 
        if (spec->data.custom_data.image)
@@ -5974,6 +5978,31 @@ emit_marshal_array (EmitMarshalContext *m, int argnum, MonoType *t,
                need_free = mono_marshal_need_free (&klass->element_class->byval_arg, 
                                                                                        m->piinfo, spec);
 
+               if ((t->attrs & PARAM_ATTRIBUTE_OUT) && spec && spec->native == MONO_NATIVE_LPARRAY && spec->data.array_data.param_num != -1) {
+                       int param_num = spec->data.array_data.param_num;
+                       MonoType *param_type;
+
+                       param_type = m->sig->params [param_num];
+
+                       if (param_type->byref && param_type->type != MONO_TYPE_I4) {
+                               char *msg = g_strdup ("Not implemented.");
+                               mono_mb_emit_exception_marshal_directive (mb, msg);
+                               break;
+                       }
+
+                       mono_mb_emit_ldarg (mb, argnum);
+
+                       /* Create the managed array */
+                       mono_mb_emit_ldarg (mb, param_num);
+                       if (m->sig->params [param_num]->byref)
+                               // FIXME: Support other types
+                               mono_mb_emit_byte (mb, CEE_LDIND_I4);
+                       mono_mb_emit_byte (mb, CEE_CONV_OVF_I);
+                       mono_mb_emit_op (mb, CEE_NEWARR, klass->element_class);
+                       /* Store into argument */
+                       mono_mb_emit_byte (mb, CEE_STIND_I);
+               }
+
                if (need_convert || need_free) {
                        /* FIXME: Optimize blittable case */
                        MonoClass *eklass;
@@ -6089,6 +6118,8 @@ emit_marshal_array (EmitMarshalContext *m, int argnum, MonoType *t,
                        /* free memory allocated (if any) by MONO_MARSHAL_CONV_ARRAY_LPARRAY */
 
                        mono_mb_emit_ldarg (mb, argnum);
+                       if (t->byref)
+                               mono_mb_emit_byte (mb, CEE_LDIND_REF);
                        mono_mb_emit_ldloc (mb, conv_arg);
                        mono_mb_emit_icall (mb, conv_to_icall (MONO_MARSHAL_FREE_LPARRAY));
                }
@@ -6110,7 +6141,7 @@ emit_marshal_array (EmitMarshalContext *m, int argnum, MonoType *t,
        case MARSHAL_ACTION_MANAGED_CONV_IN: {
                MonoClass *eklass;
                guint32 label1, label2, label3;
-               int index_var, src_ptr, loc, esize, param_num, num_elem;
+               int index_var, src_ptr, esize, param_num, num_elem;
                MonoMarshalConv conv;
                gboolean is_string = FALSE;
                
@@ -6171,7 +6202,6 @@ emit_marshal_array (EmitMarshalContext *m, int argnum, MonoType *t,
                else
                        esize = mono_class_native_size (eklass, NULL);
                src_ptr = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
-               loc = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
 
                mono_mb_emit_byte (mb, CEE_LDNULL);
                mono_mb_emit_stloc (mb, conv_arg);
@@ -6288,7 +6318,7 @@ emit_marshal_array (EmitMarshalContext *m, int argnum, MonoType *t,
        case MARSHAL_ACTION_MANAGED_CONV_OUT: {
                MonoClass *eklass;
                guint32 label1, label2, label3;
-               int index_var, dest_ptr, loc, esize, param_num, num_elem;
+               int index_var, dest_ptr, esize, param_num, num_elem;
                MonoMarshalConv conv;
                gboolean is_string = FALSE;
 
@@ -6336,7 +6366,6 @@ emit_marshal_array (EmitMarshalContext *m, int argnum, MonoType *t,
                        esize = mono_class_native_size (eklass, NULL);
 
                dest_ptr = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
-               loc = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
 
                /* Check null */
                mono_mb_emit_ldloc (mb, conv_arg);
@@ -6883,8 +6912,9 @@ emit_marshal (EmitMarshalContext *m, int argnum, MonoType *t,
                        return emit_marshal_vtype (m, argnum, t, spec, conv_arg, conv_arg_type, action);
                else
                        return emit_marshal_object (m, argnum, t, spec, conv_arg, conv_arg_type, action);
+       default:
+               return conv_arg;
        }
-       return conv_arg;
 }
 
 #ifndef DISABLE_JIT
@@ -6911,7 +6941,9 @@ mono_marshal_emit_native_wrapper (MonoImage *image, MonoMethodBuilder *mb, MonoM
        int type, param_shift = 0;
        static MonoMethodSignature *get_last_error_sig = NULL;
 
+       memset (&m, 0, sizeof (m));
        m.mb = mb;
+       m.sig = sig;
        m.piinfo = piinfo;
 
        /* we copy the signature, so that we can set pinvoke to 0 */
@@ -7099,6 +7131,8 @@ mono_marshal_emit_native_wrapper (MonoImage *image, MonoMethodBuilder *mb, MonoM
                case MONO_TYPE_BOOLEAN:
                        emit_marshal (&m, argnum, t, spec, tmp_locals [i], NULL, MARSHAL_ACTION_CONV_OUT);
                        break;
+               default:
+                       break;
                }
        }
 
@@ -7351,13 +7385,18 @@ mono_marshal_get_native_func_wrapper (MonoImage *image, MonoMethodSignature *sig
 {
        MonoMethodSignature *csig;
 
+       SignaturePointerPair key, *new_key;
        MonoMethodBuilder *mb;
        MonoMethod *res;
        GHashTable *cache;
+       gboolean found;
        char *name;
 
-       cache = get_cache (&image->native_wrapper_cache, mono_aligned_addr_hash, NULL);
-       if ((res = mono_marshal_find_in_cache (cache, func)))
+       key.sig = sig;
+       key.pointer = func;
+
+       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;
 
        name = g_strdup_printf ("wrapper_native_%p", func);
@@ -7370,8 +7409,15 @@ mono_marshal_get_native_func_wrapper (MonoImage *image, MonoMethodSignature *sig
 
        csig = signature_dup (image, sig);
        csig->pinvoke = 0;
-       res = mono_mb_create_and_cache (cache, func,
-                                                                       mb, csig, csig->param_count + 16);
+
+       new_key = g_new (SignaturePointerPair,1);
+       new_key->sig = csig;
+       new_key->pointer = func;
+
+       res = mono_mb_create_and_cache_full (cache, new_key, mb, csig, csig->param_count + 16, NULL, &found);
+       if (found)
+               g_free (new_key);
+
        mono_mb_free (mb);
 
        mono_marshal_set_wrapper_info (res, NULL);
@@ -7638,6 +7684,8 @@ mono_marshal_emit_managed_wrapper (MonoMethodBuilder *mb, MonoMethodSignature *i
                        case MONO_TYPE_BOOLEAN:
                                emit_marshal (m, i, t, mspecs [i + 1], tmp_locals [i], NULL, MARSHAL_ACTION_MANAGED_CONV_OUT);
                                break;
+                       default:
+                               break;
                        }
                }
                else if (invoke_sig->params [i]->attrs & PARAM_ATTRIBUTE_OUT) {
@@ -7761,6 +7809,7 @@ mono_marshal_get_managed_wrapper (MonoMethod *method, MonoClass *delegate_klass,
        csig->hasthis = 0;
        csig->pinvoke = 1;
 
+       memset (&m, 0, sizeof (m));
        m.mb = mb;
        m.sig = sig;
        m.piinfo = NULL;
@@ -7802,8 +7851,6 @@ mono_marshal_get_managed_wrapper (MonoMethod *method, MonoClass *delegate_klass,
                        gint32 call_conv;
                        gint32 charset = 0;
                        MonoBoolean set_last_error = 0;
-                       MonoBoolean best_fit_mapping = 0;
-                       MonoBoolean throw_on_unmappable = 0;
                        MonoError error;
 
                        mono_reflection_create_custom_attr_data_args (mono_defaults.corlib, attr->ctor, attr->data, attr->data_size, &typed_args, &named_args, &arginfo, &error);
@@ -7826,9 +7873,9 @@ mono_marshal_get_managed_wrapper (MonoMethod *method, MonoClass *delegate_klass,
                                } else if (!strcmp (narg->field->name, "SetLastError")) {
                                        set_last_error = *(MonoBoolean*)mono_object_unbox (o);
                                } else if (!strcmp (narg->field->name, "BestFitMapping")) {
-                                       best_fit_mapping = *(MonoBoolean*)mono_object_unbox (o);
+                                       // best_fit_mapping = *(MonoBoolean*)mono_object_unbox (o);
                                } else if (!strcmp (narg->field->name, "ThrowOnUnmappableChar")) {
-                                       throw_on_unmappable = *(MonoBoolean*)mono_object_unbox (o);
+                                       // throw_on_unmappable = *(MonoBoolean*)mono_object_unbox (o);
                                } else {
                                        g_assert_not_reached ();
                                }
@@ -7907,6 +7954,7 @@ mono_marshal_get_vtfixup_ftnptr (MonoImage *image, guint32 token, guint16 type)
                csig->hasthis = 0;
                csig->pinvoke = 1;
 
+               memset (&m, 0, sizeof (m));
                m.mb = mb;
                m.sig = sig;
                m.piinfo = NULL;
@@ -8096,7 +8144,7 @@ mono_marshal_get_isinst_with_cache (void)
        mono_mb_emit_ldloc (mb, 1);
        mono_mb_emit_byte (mb, CEE_LDC_I4);
        mono_mb_emit_i4 (mb, ~0x1);
-       mono_mb_emit_byte (mb, CEE_CONV_U);
+       mono_mb_emit_byte (mb, CEE_CONV_I);
        mono_mb_emit_byte (mb, CEE_AND);
        mono_mb_emit_ldloc (mb, 0);
        /*if ((cached_vtable & ~0x1)== obj_vtable)*/
@@ -8520,11 +8568,9 @@ mono_marshal_get_synchronized_inner_wrapper (MonoMethod *method)
        MonoMethodSignature *sig;
        MonoMethod *res;
        MonoGenericContext *ctx = NULL;
-       MonoMethod *orig_method = NULL;
        MonoGenericContainer *container = NULL;
 
        if (method->is_inflated && !mono_method_get_context (method)->method_inst) {
-               orig_method = method;
                ctx = &((MonoMethodInflated*)method)->context;
                method = ((MonoMethodInflated*)method)->declaring;
                container = mono_method_get_generic_container (method);
@@ -8544,8 +8590,11 @@ mono_marshal_get_synchronized_inner_wrapper (MonoMethod *method)
        info->d.synchronized_inner.method = method;
        res = mono_mb_create (mb, sig, 0, info);
        mono_mb_free (mb);
-       if (ctx)
-               res = mono_class_inflate_generic_method (res, ctx);
+       if (ctx) {
+               MonoError error;
+               res = mono_class_inflate_generic_method_checked (res, ctx, &error);
+               g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
+       }
        return res;
 }
 
@@ -8686,10 +8735,13 @@ mono_marshal_get_synchronized_wrapper (MonoMethod *method)
        for (i = 0; i < sig->param_count; i++)
                mono_mb_emit_ldarg (mb, i + (sig->hasthis == TRUE));
 
-       if (ctx)
-               mono_mb_emit_managed_call (mb, mono_class_inflate_generic_method (method, &container->context), NULL);
-       else
+       if (ctx) {
+               MonoError error;
+               mono_mb_emit_managed_call (mb, mono_class_inflate_generic_method_checked (method, &container->context, &error), NULL);
+               g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
+       } else {
                mono_mb_emit_managed_call (mb, method, NULL);
+       }
 
        if (!MONO_TYPE_IS_VOID (sig->ret))
                mono_mb_emit_stloc (mb, ret_local);
@@ -9506,10 +9558,11 @@ static int elem_addr_cache_next = 0;
  * @rank: rank of the array type
  * @elem_size: size in bytes of an element of an array.
  *
- * Returns a MonoMethd that implements the code to get the address
+ * Returns a MonoMethod that implements the code to get the address
  * of an element in a multi-dimenasional array of @rank dimensions.
  * The returned method takes an array as the first argument and then
  * @rank indexes for the @rank dimensions.
+ * If ELEM_SIZE is 0, read the array size from the array object.
  */
 MonoMethod*
 mono_marshal_get_array_address (int rank, int elem_size)
@@ -9518,6 +9571,7 @@ mono_marshal_get_array_address (int rank, int elem_size)
        MonoMethodBuilder *mb;
        MonoMethodSignature *sig;
        WrapperInfo *info;
+       char *name;
        int i, bounds, ind, realidx;
        int branch_pos, *branch_positions;
        int cached;
@@ -9545,7 +9599,9 @@ mono_marshal_get_array_address (int rank, int elem_size)
                sig->params [i + 1] = &mono_defaults.int32_class->byval_arg;
        }
 
-       mb = mono_mb_new (mono_defaults.object_class, "ElementAddr", MONO_WRAPPER_MANAGED_TO_MANAGED);
+       name = g_strdup_printf ("ElementAddr_%d", elem_size);
+       mb = mono_mb_new (mono_defaults.object_class, name, MONO_WRAPPER_MANAGED_TO_MANAGED);
+       g_free (name);
        
 #ifndef DISABLE_JIT
        bounds = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
@@ -9613,8 +9669,24 @@ mono_marshal_get_array_address (int rank, int elem_size)
        mono_mb_emit_ldarg (mb, 0);
        mono_mb_emit_ldflda (mb, MONO_STRUCT_OFFSET (MonoArray, vector));
        mono_mb_emit_ldloc (mb, ind);
-       mono_mb_emit_icon (mb, elem_size);
-       mono_mb_emit_byte (mb, CEE_MUL);
+       if (elem_size) {
+               mono_mb_emit_icon (mb, elem_size);
+       } else {
+               /* Load arr->vtable->klass->sizes.element_class */
+               mono_mb_emit_ldarg (mb, 0);
+               mono_mb_emit_byte (mb, CEE_CONV_I);
+               mono_mb_emit_icon (mb, MONO_STRUCT_OFFSET (MonoObject, vtable));
+               mono_mb_emit_byte (mb, CEE_ADD);
+               mono_mb_emit_byte (mb, CEE_LDIND_I);
+               mono_mb_emit_icon (mb, MONO_STRUCT_OFFSET (MonoVTable, klass));
+               mono_mb_emit_byte (mb, CEE_ADD);
+               mono_mb_emit_byte (mb, CEE_LDIND_I);
+               /* sizes is an union, so this reads sizes.element_size */
+               mono_mb_emit_icon (mb, MONO_STRUCT_OFFSET (MonoClass, sizes));
+               mono_mb_emit_byte (mb, CEE_ADD);
+               mono_mb_emit_byte (mb, CEE_LDIND_I4);
+       }
+               mono_mb_emit_byte (mb, CEE_MUL);
        mono_mb_emit_byte (mb, CEE_ADD);
        mono_mb_emit_byte (mb, CEE_RET);
 
@@ -9711,10 +9783,13 @@ mono_marshal_get_array_accessor_wrapper (MonoMethod *method)
        for (i = 0; i < sig->param_count; i++)
                mono_mb_emit_ldarg (mb, i + (sig->hasthis == TRUE));
 
-       if (ctx)
-               mono_mb_emit_managed_call (mb, mono_class_inflate_generic_method (method, &container->context), NULL);
-       else
+       if (ctx) {
+               MonoError error;
+               mono_mb_emit_managed_call (mb, mono_class_inflate_generic_method_checked (method, &container->context, &error), NULL);
+               g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
+       } else {
                mono_mb_emit_managed_call (mb, method, NULL);
+       }
        mono_mb_emit_byte (mb, CEE_RET);
 #endif
 
@@ -9823,19 +9898,25 @@ ves_icall_System_Runtime_InteropServices_Marshal_copy_to_unmanaged (MonoArray *s
        int element_size;
        void *source_addr;
 
-       MONO_ARCH_SAVE_REGS;
+       MONO_CHECK_ARG_NULL (src,);
+       MONO_CHECK_ARG_NULL (dest,);
 
-       MONO_CHECK_ARG_NULL (src);
-       MONO_CHECK_ARG_NULL (dest);
-
-       if (src->obj.vtable->klass->rank != 1)
-               mono_raise_exception (mono_get_exception_argument ("array", "array is multi-dimensional"));
-       if (start_index < 0)
-               mono_raise_exception (mono_get_exception_argument ("startIndex", "Must be >= 0"));
-       if (length < 0)
-               mono_raise_exception (mono_get_exception_argument ("length", "Must be >= 0"));
-       if (start_index + length > mono_array_length (src))
-               mono_raise_exception (mono_get_exception_argument ("length", "start_index + length > array length"));
+       if (src->obj.vtable->klass->rank != 1) {
+               mono_set_pending_exception (mono_get_exception_argument ("array", "array is multi-dimensional"));
+               return;
+       }
+       if (start_index < 0) {
+               mono_set_pending_exception (mono_get_exception_argument ("startIndex", "Must be >= 0"));
+               return;
+       }
+       if (length < 0) {
+               mono_set_pending_exception (mono_get_exception_argument ("length", "Must be >= 0"));
+               return;
+       }
+       if (start_index + length > mono_array_length (src)) {
+               mono_set_pending_exception (mono_get_exception_argument ("length", "start_index + length > array length"));
+               return;
+       }
 
        element_size = mono_array_element_size (src->obj.vtable->klass);
 
@@ -9852,20 +9933,25 @@ ves_icall_System_Runtime_InteropServices_Marshal_copy_from_unmanaged (gpointer s
        int element_size;
        void *dest_addr;
 
-       MONO_ARCH_SAVE_REGS;
-
-       MONO_CHECK_ARG_NULL (src);
-       MONO_CHECK_ARG_NULL (dest);
-
-       if (dest->obj.vtable->klass->rank != 1)
-               mono_raise_exception (mono_get_exception_argument ("array", "array is multi-dimensional"));
-       if (start_index < 0)
-               mono_raise_exception (mono_get_exception_argument ("startIndex", "Must be >= 0"));
-       if (length < 0)
-               mono_raise_exception (mono_get_exception_argument ("length", "Must be >= 0"));
-       if (start_index + length > mono_array_length (dest))
-               mono_raise_exception (mono_get_exception_argument ("length", "start_index + length > array length"));
+       MONO_CHECK_ARG_NULL (src,);
+       MONO_CHECK_ARG_NULL (dest,);
 
+       if (dest->obj.vtable->klass->rank != 1) {
+               mono_set_pending_exception (mono_get_exception_argument ("array", "array is multi-dimensional"));
+               return;
+       }
+       if (start_index < 0) {
+               mono_set_pending_exception (mono_get_exception_argument ("startIndex", "Must be >= 0"));
+               return;
+       }
+       if (length < 0) {
+               mono_set_pending_exception (mono_get_exception_argument ("length", "Must be >= 0"));
+               return;
+       }
+       if (start_index + length > mono_array_length (dest)) {
+               mono_set_pending_exception (mono_get_exception_argument ("length", "start_index + length > array length"));
+               return;
+       }
        element_size = mono_array_element_size (dest->obj.vtable->klass);
          
        /* no references should be involved */
@@ -9877,8 +9963,6 @@ ves_icall_System_Runtime_InteropServices_Marshal_copy_from_unmanaged (gpointer s
 MonoString *
 ves_icall_System_Runtime_InteropServices_Marshal_PtrToStringAnsi (char *ptr)
 {
-       MONO_ARCH_SAVE_REGS;
-
        if (ptr == NULL)
                return NULL;
        else
@@ -9888,11 +9972,8 @@ ves_icall_System_Runtime_InteropServices_Marshal_PtrToStringAnsi (char *ptr)
 MonoString *
 ves_icall_System_Runtime_InteropServices_Marshal_PtrToStringAnsi_len (char *ptr, gint32 len)
 {
-       MONO_ARCH_SAVE_REGS;
-
        if (ptr == NULL) {
-               mono_raise_exception (mono_get_exception_argument_null ("ptr"));
-               g_assert_not_reached ();
+               mono_set_pending_exception (mono_get_exception_argument_null ("ptr"));
                return NULL;
        } else {
                return mono_string_new_len (mono_domain_get (), ptr, len);
@@ -9906,8 +9987,6 @@ ves_icall_System_Runtime_InteropServices_Marshal_PtrToStringUni (guint16 *ptr)
        int len = 0;
        guint16 *t = ptr;
 
-       MONO_ARCH_SAVE_REGS;
-
        if (ptr == NULL)
                return NULL;
 
@@ -9922,11 +10001,8 @@ ves_icall_System_Runtime_InteropServices_Marshal_PtrToStringUni_len (guint16 *pt
 {
        MonoDomain *domain = mono_domain_get (); 
 
-       MONO_ARCH_SAVE_REGS;
-
        if (ptr == NULL) {
-               mono_raise_exception (mono_get_exception_argument_null ("ptr"));
-               g_assert_not_reached ();
+               mono_set_pending_exception (mono_get_exception_argument_null ("ptr"));
                return NULL;
        } else {
                return mono_string_new_utf16 (domain, ptr, len);
@@ -9936,8 +10012,6 @@ ves_icall_System_Runtime_InteropServices_Marshal_PtrToStringUni_len (guint16 *pt
 guint32 
 ves_icall_System_Runtime_InteropServices_Marshal_GetLastWin32Error (void)
 {
-       MONO_ARCH_SAVE_REGS;
-
        return (GPOINTER_TO_INT (mono_native_tls_get_value (last_error_tls_id)));
 }
 
@@ -9948,14 +10022,14 @@ ves_icall_System_Runtime_InteropServices_Marshal_SizeOf (MonoReflectionType *rty
        MonoType *type;
        guint32 layout;
 
-       MONO_ARCH_SAVE_REGS;
-
-       MONO_CHECK_ARG_NULL (rtype);
+       MONO_CHECK_ARG_NULL (rtype, 0);
 
        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));
+       if (!mono_class_init (klass)) {
+               mono_set_pending_exception (mono_class_get_exception_for_failure (klass));
+               return 0;
+       }
 
        layout = (klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK);
 
@@ -9968,10 +10042,10 @@ ves_icall_System_Runtime_InteropServices_Marshal_SizeOf (MonoReflectionType *rty
                msg = g_strdup_printf ("Type %s cannot be marshaled as an unmanaged structure.", klass->name);
                exc = mono_get_exception_argument ("t", msg);
                g_free (msg);
-               mono_raise_exception (exc);
+               mono_set_pending_exception (exc);
+               return 0;
        }
 
-
        return mono_class_native_size (klass, NULL);
 }
 
@@ -9981,10 +10055,8 @@ ves_icall_System_Runtime_InteropServices_Marshal_StructureToPtr (MonoObject *obj
        MonoMethod *method;
        gpointer pa [3];
 
-       MONO_ARCH_SAVE_REGS;
-
-       MONO_CHECK_ARG_NULL (obj);
-       MONO_CHECK_ARG_NULL (dst);
+       MONO_CHECK_ARG_NULL (obj,);
+       MONO_CHECK_ARG_NULL (dst,);
 
        method = mono_marshal_get_struct_to_ptr (obj->vtable->klass);
 
@@ -10014,10 +10086,8 @@ ves_icall_System_Runtime_InteropServices_Marshal_PtrToStructure (gpointer src, M
 {
        MonoType *t;
 
-       MONO_ARCH_SAVE_REGS;
-
-       MONO_CHECK_ARG_NULL (src);
-       MONO_CHECK_ARG_NULL (dst);
+       MONO_CHECK_ARG_NULL (src,);
+       MONO_CHECK_ARG_NULL (dst,);
        
        t = mono_type_get_underlying_type (mono_class_get_type (dst->vtable->klass));
 
@@ -10029,7 +10099,7 @@ ves_icall_System_Runtime_InteropServices_Marshal_PtrToStructure (gpointer src, M
                exc = mono_get_exception_argument ("dst", tmp);
                g_free (tmp);  
 
-               mono_raise_exception (exc);
+               mono_set_pending_exception (exc);
                return;
        }
 
@@ -10043,15 +10113,15 @@ ves_icall_System_Runtime_InteropServices_Marshal_PtrToStructure_type (gpointer s
        MonoDomain *domain = mono_domain_get (); 
        MonoObject *res;
 
-       MONO_ARCH_SAVE_REGS;
-
        if (src == NULL)
                return NULL;
-       MONO_CHECK_ARG_NULL (type);
+       MONO_CHECK_ARG_NULL (type, NULL);
 
        klass = mono_class_from_mono_type (type->type);
-       if (!mono_class_init (klass))
-               mono_raise_exception (mono_class_get_exception_for_failure (klass));
+       if (!mono_class_init (klass)) {
+               mono_set_pending_exception (mono_class_get_exception_for_failure (klass));
+               return NULL;
+       }
 
        res = mono_object_new (domain, klass);
 
@@ -10068,15 +10138,15 @@ ves_icall_System_Runtime_InteropServices_Marshal_OffsetOf (MonoReflectionType *t
        char *fname;
        int match_index = -1;
        
-       MONO_ARCH_SAVE_REGS;
-
-       MONO_CHECK_ARG_NULL (type);
-       MONO_CHECK_ARG_NULL (field_name);
+       MONO_CHECK_ARG_NULL (type, 0);
+       MONO_CHECK_ARG_NULL (field_name, 0);
 
        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));
+       if (!mono_class_init (klass)) {
+               mono_set_pending_exception (mono_class_get_exception_for_failure (klass));
+               return 0;
+       }
 
        while (klass && match_index == -1) {
                MonoClassField* field;
@@ -10109,7 +10179,8 @@ ves_icall_System_Runtime_InteropServices_Marshal_OffsetOf (MonoReflectionType *t
                exc = mono_get_exception_argument ("fieldName", tmp);
                g_free (tmp);
  
-               mono_raise_exception ((MonoException*)exc);
+               mono_set_pending_exception ((MonoException*)exc);
+               return 0;
        }
 
        info = mono_marshal_load_type_info (klass);     
@@ -10140,8 +10211,6 @@ ves_icall_System_Runtime_InteropServices_Marshal_StringToHGlobalAnsi (MonoString
 gpointer
 ves_icall_System_Runtime_InteropServices_Marshal_StringToHGlobalUni (MonoString *string)
 {
-       MONO_ARCH_SAVE_REGS;
-
        if (string == NULL)
                return NULL;
        else {
@@ -10166,7 +10235,6 @@ mono_struct_delete_old (MonoClass *klass, char *ptr)
        info = mono_marshal_load_type_info (klass);
 
        for (i = 0; i < info->num_fields; i++) {
-               MonoMarshalNative ntype;
                MonoMarshalConv conv;
                MonoType *ftype = info->fields [i].field->type;
                char *cpos;
@@ -10174,8 +10242,8 @@ mono_struct_delete_old (MonoClass *klass, char *ptr)
                if (ftype->attrs & FIELD_ATTRIBUTE_STATIC)
                        continue;
 
-               ntype = mono_type_to_unmanaged (ftype, info->fields [i].mspec, TRUE, 
-                                               klass->unicode, &conv);
+               mono_type_to_unmanaged (ftype, info->fields [i].mspec, TRUE, 
+                               klass->unicode, &conv);
                        
                cpos = ptr + info->fields [i].offset;
 
@@ -10213,14 +10281,14 @@ ves_icall_System_Runtime_InteropServices_Marshal_DestroyStructure (gpointer src,
 {
        MonoClass *klass;
 
-       MONO_ARCH_SAVE_REGS;
-
-       MONO_CHECK_ARG_NULL (src);
-       MONO_CHECK_ARG_NULL (type);
+       MONO_CHECK_ARG_NULL (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));
+       if (!mono_class_init (klass)) {
+               mono_set_pending_exception (mono_class_get_exception_for_failure (klass));
+               return;
+       }
 
        mono_struct_delete_old (klass, (char *)src);
 }
@@ -10230,8 +10298,6 @@ ves_icall_System_Runtime_InteropServices_Marshal_AllocHGlobal (int size)
 {
        gpointer res;
 
-       MONO_ARCH_SAVE_REGS;
-
        if ((gulong)size == 0)
                /* This returns a valid pointer for size 0 on MS.NET */
                size = 4;
@@ -10271,8 +10337,6 @@ ves_icall_System_Runtime_InteropServices_Marshal_ReAllocHGlobal (gpointer ptr, i
 void
 ves_icall_System_Runtime_InteropServices_Marshal_FreeHGlobal (void *ptr)
 {
-       MONO_ARCH_SAVE_REGS;
-
 #ifdef HOST_WIN32
        GlobalFree (ptr);
 #else
@@ -10283,20 +10347,25 @@ ves_icall_System_Runtime_InteropServices_Marshal_FreeHGlobal (void *ptr)
 void*
 ves_icall_System_Runtime_InteropServices_Marshal_AllocCoTaskMem (int size)
 {
-       MONO_ARCH_SAVE_REGS;
+       void *res;
 
 #ifdef HOST_WIN32
-       return CoTaskMemAlloc (size);
+       res = CoTaskMemAlloc (size);
 #else
-       return g_try_malloc ((gulong)size);
+       if ((gulong)size == 0)
+               /* This returns a valid pointer for size 0 on MS.NET */
+               size = 4;
+
+       res = g_try_malloc ((gulong)size);
 #endif
+       if (!res)
+               mono_gc_out_of_memory ((gulong)size);
+       return res;
 }
 
 void
 ves_icall_System_Runtime_InteropServices_Marshal_FreeCoTaskMem (void *ptr)
 {
-       MONO_ARCH_SAVE_REGS;
-
 #ifdef HOST_WIN32
        CoTaskMemFree (ptr);
 #else
@@ -10307,13 +10376,16 @@ ves_icall_System_Runtime_InteropServices_Marshal_FreeCoTaskMem (void *ptr)
 gpointer
 ves_icall_System_Runtime_InteropServices_Marshal_ReAllocCoTaskMem (gpointer ptr, int size)
 {
-       MONO_ARCH_SAVE_REGS;
+       void *res;
 
 #ifdef HOST_WIN32
-       return CoTaskMemRealloc (ptr, size);
+       res = CoTaskMemRealloc (ptr, size);
 #else
-       return g_try_realloc (ptr, (gulong)size);
+       res = g_try_realloc (ptr, (gulong)size);
 #endif
+       if (!res)
+               mono_gc_out_of_memory ((gulong)size);
+       return res;
 }
 
 void*
@@ -10326,8 +10398,10 @@ MonoDelegate*
 ves_icall_System_Runtime_InteropServices_Marshal_GetDelegateForFunctionPointerInternal (void *ftn, MonoReflectionType *type)
 {
        MonoClass *klass = mono_type_get_class (type->type);
-       if (!mono_class_init (klass))
-               mono_raise_exception (mono_class_get_exception_for_failure (klass));
+       if (!mono_class_init (klass)) {
+               mono_set_pending_exception (mono_class_get_exception_for_failure (klass));
+               return NULL;
+       }
 
        return mono_ftnptr_to_delegate (klass, ftn);
 }
@@ -10777,10 +10851,10 @@ mono_marshal_asany (MonoObject *o, MonoMarshalNative string_encoding, int param_
 
                return res;
        }
+       default:
+               break;
        }
-
        mono_raise_exception (mono_get_exception_argument ("", "No PInvoke conversion exists for value passed to Object-typed parameter."));
-
        return NULL;
 }
 
@@ -11101,7 +11175,7 @@ mono_marshal_free_dynamic_wrappers (MonoMethod *method)
        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_method_pair_matches_method, method);
+               g_hash_table_foreach_remove (image->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));
@@ -11111,9 +11185,9 @@ mono_marshal_free_dynamic_wrappers (MonoMethod *method)
 }
 
 static gboolean
-signature_method_pair_matches_signature (gpointer key, gpointer value, gpointer user_data)
+signature_pointer_pair_matches_signature (gpointer key, gpointer value, gpointer user_data)
 {
-       SignatureMethodPair *pair = (SignatureMethodPair*)key;
+       SignaturePointerPair *pair = (SignaturePointerPair*)key;
        MonoMethodSignature *sig = (MonoMethodSignature*)user_data;
 
        return mono_metadata_signature_equal (pair->sig, sig);
@@ -11157,11 +11231,11 @@ mono_marshal_free_inflated_wrappers (MonoMethod *method)
                g_hash_table_remove (method->klass->image->runtime_invoke_vtype_cache, sig);
 
         /*
-         * indexed by SignatureMethodPair
+         * 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_method_pair_matches_signature, (gpointer)sig);
+                                            signature_pointer_pair_matches_signature, (gpointer)sig);
 
         /*
          * indexed by MonoMethod pointers