[threadpool] Split domain and worker management (#4117)
[mono.git] / mono / metadata / marshal.c
index a725148ad78c8b9aef410fb93b77ee9bca0e011c..e376d860f8566e58a06dbbdd3d3be273362e4ad9 100644 (file)
@@ -40,7 +40,7 @@
 #include "mono/metadata/cominterop.h"
 #include "mono/metadata/remoting.h"
 #include "mono/metadata/reflection-internals.h"
-#include "mono/metadata/threadpool-ms.h"
+#include "mono/metadata/threadpool.h"
 #include "mono/metadata/handle.h"
 #include "mono/utils/mono-counters.h"
 #include "mono/utils/mono-tls.h"
@@ -82,6 +82,8 @@ static MonoNativeTlsKey load_type_info_tls_id;
 
 static gboolean use_aot_wrappers;
 
+static int class_marshal_info_count;
+
 static void ftnptr_eh_callback_default (guint32 gchandle);
 
 static MonoFtnPtrEHCallback ftnptr_eh_callback = ftnptr_eh_callback_default;
@@ -109,7 +111,7 @@ mono_marshal_string_to_utf16_copy (MonoString *s);
 
 #ifndef HOST_WIN32
 static gpointer
-mono_string_to_lpstr (MonoString *string_obj);
+mono_string_to_utf8str (MonoString *string_obj);
 #endif
 
 static MonoStringBuilder *
@@ -214,10 +216,11 @@ static void
 mono_icall_end (MonoThreadInfo *info, HandleStackMark *stackmark, MonoError *error);
 
 /* Lazy class loading functions */
-static GENERATE_GET_CLASS_WITH_CACHE (string_builder, System.Text, StringBuilder)
-static GENERATE_GET_CLASS_WITH_CACHE (date_time, System, DateTime)
-static GENERATE_TRY_GET_CLASS_WITH_CACHE (unmanaged_function_pointer_attribute, System.Runtime.InteropServices, UnmanagedFunctionPointerAttribute)
-static GENERATE_TRY_GET_CLASS_WITH_CACHE (icustom_marshaler, System.Runtime.InteropServices, ICustomMarshaler)
+static GENERATE_GET_CLASS_WITH_CACHE (string_builder, System.Text, StringBuilder);
+static GENERATE_GET_CLASS_WITH_CACHE (date_time, System, DateTime);
+static GENERATE_GET_CLASS_WITH_CACHE (fixed_buffer_attribute, System.Runtime.CompilerServices, FixedBufferAttribute);
+static GENERATE_TRY_GET_CLASS_WITH_CACHE (unmanaged_function_pointer_attribute, System.Runtime.InteropServices, UnmanagedFunctionPointerAttribute);
+static GENERATE_TRY_GET_CLASS_WITH_CACHE (icustom_marshaler, System.Runtime.InteropServices, ICustomMarshaler);
 
 /* MonoMethod pointers to SafeHandle::DangerousAddRef and ::DangerousRelease */
 static MonoMethod *sh_dangerous_add_ref;
@@ -306,7 +309,7 @@ mono_marshal_init (void)
                register_icall (mono_string_new_wrapper, "mono_string_new_wrapper", "obj ptr", FALSE);
                register_icall (mono_string_new_len_wrapper, "mono_string_new_len_wrapper", "obj ptr int", FALSE);
                register_icall (ves_icall_mono_string_to_utf8, "ves_icall_mono_string_to_utf8", "ptr obj", FALSE);
-               register_icall (mono_string_to_lpstr, "mono_string_to_lpstr", "ptr obj", FALSE);
+               register_icall (mono_string_to_utf8str, "mono_string_to_utf8str", "ptr obj", FALSE);
                register_icall (mono_string_to_ansibstr, "mono_string_to_ansibstr", "ptr object", FALSE);
                register_icall (mono_string_builder_to_utf8, "mono_string_builder_to_utf8", "ptr object", FALSE);
                register_icall (mono_string_builder_to_utf16, "mono_string_builder_to_utf16", "ptr object", FALSE);
@@ -354,6 +357,10 @@ mono_marshal_init (void)
 
                mono_cominterop_init ();
                mono_remoting_init ();
+
+               mono_counters_register ("MonoClass::class_marshal_info_count count",
+                                                               MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_marshal_info_count);
+
        }
 }
 
@@ -922,13 +929,13 @@ mono_string_utf8_to_builder (MonoStringBuilder *sb, char *text)
        if (!sb || !text)
                return;
 
-       int len = strlen (text);
-       if (len > mono_string_builder_capacity (sb))
-               len = mono_string_builder_capacity (sb);
-
        GError *error = NULL;
        glong copied;
-       gunichar2* ut = g_utf8_to_utf16 (text, len, NULL, &copied, &error);
+       gunichar2* ut = g_utf8_to_utf16 (text, strlen (text), NULL, &copied, &error);
+       int capacity = mono_string_builder_capacity (sb);
+
+       if (copied > capacity)
+               copied = capacity;
 
        if (!error) {
                MONO_OBJECT_SETREF (sb, chunkPrevious, NULL);
@@ -952,7 +959,6 @@ mono_string_utf8_to_builder2 (char *text)
        return sb;
 }
 
-
 void
 mono_string_utf16_to_builder (MonoStringBuilder *sb, gunichar2 *text)
 {
@@ -985,7 +991,7 @@ mono_string_builder_to_utf8 (MonoStringBuilder *sb)
 {
        MonoError error;
        GError *gerror = NULL;
-
+       glong byte_count;
        if (!sb)
                return NULL;
 
@@ -993,7 +999,7 @@ mono_string_builder_to_utf8 (MonoStringBuilder *sb)
 
        guint str_len = mono_string_builder_string_length (sb);
 
-       gchar *tmp = g_utf16_to_utf8 (str_utf16, str_len, NULL, NULL, &gerror);
+       gchar *tmp = g_utf16_to_utf8 (str_utf16, str_len, NULL, &byte_count, &gerror);
 
        if (gerror) {
                g_error_free (gerror);
@@ -1002,7 +1008,7 @@ mono_string_builder_to_utf8 (MonoStringBuilder *sb)
                return NULL;
        } else {
                guint len = mono_string_builder_capacity (sb) + 1;
-               gchar *res = (gchar *)mono_marshal_alloc (len * sizeof (gchar), &error);
+               gchar *res = (gchar *)mono_marshal_alloc (MAX (byte_count+1, len * sizeof (gchar)), &error);
                if (!mono_error_ok (&error)) {
                        mono_marshal_free (str_utf16);
                        g_free (tmp);
@@ -1010,9 +1016,8 @@ mono_string_builder_to_utf8 (MonoStringBuilder *sb)
                        return NULL;
                }
 
-               g_assert (str_len < len);
-               memcpy (res, tmp, str_len * sizeof (gchar));
-               res[str_len] = '\0';
+               memcpy (res, tmp, byte_count);
+               res[byte_count] = '\0';
 
                mono_marshal_free (str_utf16);
                g_free (tmp);
@@ -1078,17 +1083,17 @@ mono_string_builder_to_utf16 (MonoStringBuilder *sb)
        return str;
 }
 
-/* This is a JIT icall, it sets the pending exception and returns NULL on error. */
 #ifndef HOST_WIN32
+/* This is a JIT icall, it sets the pending exception and returns NULL on error. */
 static gpointer
-mono_string_to_lpstr (MonoString *s)
+mono_string_to_utf8str (MonoString *s)
 {
        MonoError error;
        char *result = mono_string_to_utf8_checked (s, &error);
        mono_error_set_pending_exception (&error);
        return result;
 }
-#endif /* HOST_WIN32 */
+#endif
 
 gpointer
 mono_string_to_ansibstr (MonoString *string_obj)
@@ -1134,7 +1139,7 @@ mono_string_to_byvalstr (gpointer dst, MonoString *src, int size)
  * mono_string_to_byvalwstr:
  * @dst: Where to store the null-terminated utf16 decoded string.
  * @src: the MonoString to copy.
- * @size: the maximum number of bytes to copy.
+ * @size: the maximum number of wide characters to copy (each consumes 2 bytes)
  *
  * Copies the MonoString pointed to by @src as a utf16 string into
  * @dst, it copies at most @size bytes into the destination (including
@@ -1154,7 +1159,7 @@ mono_string_to_byvalwstr (gpointer dst, MonoString *src, int size)
        }
 
        len = MIN (size, (mono_string_length (src)));
-       memcpy (dst, mono_string_chars (src), size * 2);
+       memcpy (dst, mono_string_chars (src), len * 2);
        if (size <= mono_string_length (src))
                len--;
        *((gunichar2 *) dst + len) = 0;
@@ -1476,7 +1481,10 @@ emit_ptr_to_object_conv (MonoMethodBuilder *mb, MonoType *type, MonoMarshalConv
 #endif
                mono_mb_emit_byte (mb, CEE_STIND_REF);  
                break;
+
+               // In Mono historically LPSTR was treated as a UTF8STR
        case MONO_MARSHAL_CONV_STR_LPSTR:
+       case MONO_MARSHAL_CONV_STR_UTF8STR:
                mono_mb_emit_ldloc (mb, 1);
                mono_mb_emit_ldloc (mb, 0);
                mono_mb_emit_byte (mb, CEE_LDIND_I);
@@ -1604,6 +1612,7 @@ conv_to_icall (MonoMarshalConv conv, int *ind_store_type)
        case MONO_MARSHAL_CONV_LPTSTR_STR:
                *ind_store_type = CEE_STIND_REF;
                return mono_string_new_wrapper;
+       case MONO_MARSHAL_CONV_UTF8STR_STR:
        case MONO_MARSHAL_CONV_LPSTR_STR:
                *ind_store_type = CEE_STIND_REF;
                return mono_string_new_wrapper;
@@ -1611,10 +1620,12 @@ conv_to_icall (MonoMarshalConv conv, int *ind_store_type)
 #ifdef TARGET_WIN32
                return mono_marshal_string_to_utf16;
 #else
-               return mono_string_to_lpstr;
+               return mono_string_to_utf8str;
 #endif
+               // In Mono historically LPSTR was treated as a UTF8STR
+       case MONO_MARSHAL_CONV_STR_UTF8STR:
        case MONO_MARSHAL_CONV_STR_LPSTR:
-               return mono_string_to_lpstr;
+               return mono_string_to_utf8str;
        case MONO_MARSHAL_CONV_STR_BSTR:
                return mono_string_to_bstr;
        case MONO_MARSHAL_CONV_BSTR_STR:
@@ -1623,6 +1634,7 @@ conv_to_icall (MonoMarshalConv conv, int *ind_store_type)
        case MONO_MARSHAL_CONV_STR_TBSTR:
        case MONO_MARSHAL_CONV_STR_ANSIBSTR:
                return mono_string_to_ansibstr;
+       case MONO_MARSHAL_CONV_SB_UTF8STR:
        case MONO_MARSHAL_CONV_SB_LPSTR:
                return mono_string_builder_to_utf8;
        case MONO_MARSHAL_CONV_SB_LPTSTR:
@@ -1644,6 +1656,7 @@ conv_to_icall (MonoMarshalConv conv, int *ind_store_type)
        case MONO_MARSHAL_CONV_FTN_DEL:
                *ind_store_type = CEE_STIND_REF;
                return mono_ftnptr_to_delegate;
+       case MONO_MARSHAL_CONV_UTF8STR_SB:
        case MONO_MARSHAL_CONV_LPSTR_SB:
                *ind_store_type = CEE_STIND_REF;
                return mono_string_utf8_to_builder;
@@ -1690,6 +1703,8 @@ emit_object_to_ptr_conv (MonoMethodBuilder *mb, MonoType *type, MonoMarshalConv
                mono_mb_emit_byte (mb, CEE_NEG);
                mono_mb_emit_byte (mb, CEE_STIND_I2);
                break;
+       // In Mono historically LPSTR was treated as a UTF8STR
+       case MONO_MARSHAL_CONV_STR_UTF8STR:
        case MONO_MARSHAL_CONV_STR_LPWSTR:
        case MONO_MARSHAL_CONV_STR_LPSTR:
        case MONO_MARSHAL_CONV_STR_LPTSTR:
@@ -1914,10 +1929,13 @@ emit_object_to_ptr_conv (MonoMethodBuilder *mb, MonoType *type, MonoMarshalConv
        }
 }
 
-static int offset_of_first_nonstatic_field(MonoClass *klass)
+static int
+offset_of_first_nonstatic_field (MonoClass *klass)
 {
        int i;
-       for (i = 0; i < klass->field.count; i++) {
+       int fcount = mono_class_get_field_count (klass);
+       mono_class_setup_fields (klass);
+       for (i = 0; i < fcount; i++) {
                if (!(klass->fields[i].type->attrs & FIELD_ATTRIBUTE_STATIC) && !mono_field_is_deleted (&klass->fields[i]))
                        return klass->fields[i].offset - sizeof (MonoObject);
        }
@@ -1925,6 +1943,145 @@ static int offset_of_first_nonstatic_field(MonoClass *klass)
        return 0;
 }
 
+static gboolean
+get_fixed_buffer_attr (MonoClassField *field, MonoType **out_etype, int *out_len)
+{
+       MonoError error;
+       MonoCustomAttrInfo *cinfo;
+       MonoCustomAttrEntry *attr;
+       int aindex;
+
+       cinfo = mono_custom_attrs_from_field_checked (field->parent, field, &error);
+       if (!is_ok (&error))
+               return FALSE;
+       attr = NULL;
+       if (cinfo) {
+               for (aindex = 0; aindex < cinfo->num_attrs; ++aindex) {
+                       MonoClass *ctor_class = cinfo->attrs [aindex].ctor->klass;
+                       if (mono_class_has_parent (ctor_class, mono_class_get_fixed_buffer_attribute_class ())) {
+                               attr = &cinfo->attrs [aindex];
+                               break;
+                       }
+               }
+       }
+       if (attr) {
+               MonoArray *typed_args, *named_args;
+               CattrNamedArg *arginfo;
+               MonoObject *o;
+
+               mono_reflection_create_custom_attr_data_args (mono_defaults.corlib, attr->ctor, attr->data, attr->data_size, &typed_args, &named_args, &arginfo, &error);
+               if (!is_ok (&error))
+                       return FALSE;
+               g_assert (mono_array_length (typed_args) == 2);
+
+               /* typed args */
+               o = mono_array_get (typed_args, MonoObject*, 0);
+               *out_etype = monotype_cast (o)->type;
+               o = mono_array_get (typed_args, MonoObject*, 1);
+               g_assert (o->vtable->klass == mono_defaults.int32_class);
+               *out_len = *(gint32*)mono_object_unbox (o);
+               g_free (arginfo);
+       }
+       if (cinfo && !cinfo->cached)
+               mono_custom_attrs_free (cinfo);
+       return attr != NULL;
+}
+
+static void
+emit_fixed_buf_conv (MonoMethodBuilder *mb, MonoType *type, MonoType *etype, int len, gboolean to_object, int *out_usize)
+{
+       MonoClass *klass = mono_class_from_mono_type (type);
+       MonoClass *eklass = mono_class_from_mono_type (etype);
+       int esize;
+
+       esize = mono_class_native_size (eklass, NULL);
+
+       MonoMarshalNative string_encoding = klass->unicode ? MONO_NATIVE_LPWSTR : MONO_NATIVE_LPSTR;
+       int usize = mono_class_value_size (eklass, NULL);
+       int msize = mono_class_value_size (eklass, NULL);
+
+       //printf ("FIXED: %s %d %d\n", mono_type_full_name (type), eklass->blittable, string_encoding);
+
+       if (eklass->blittable) {
+               /* copy the elements */
+               mono_mb_emit_ldloc (mb, 1);
+               mono_mb_emit_ldloc (mb, 0);
+               mono_mb_emit_icon (mb, len * esize);
+               mono_mb_emit_byte (mb, CEE_PREFIX1);
+               mono_mb_emit_byte (mb, CEE_CPBLK);
+       } else {
+               int index_var;
+               guint32 label2, label3;
+
+               /* Emit marshalling loop */
+               index_var = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
+               mono_mb_emit_byte (mb, CEE_LDC_I4_0);
+               mono_mb_emit_stloc (mb, index_var);
+
+               /* Loop header */
+               label2 = mono_mb_get_label (mb);
+               mono_mb_emit_ldloc (mb, index_var);
+               mono_mb_emit_icon (mb, len);
+               label3 = mono_mb_emit_branch (mb, CEE_BGE);
+
+               /* src/dst is already set */
+
+               /* Do the conversion */
+               MonoTypeEnum t = etype->type;
+               switch (t) {
+               case MONO_TYPE_I4:
+               case MONO_TYPE_U4:
+               case MONO_TYPE_I1:
+               case MONO_TYPE_U1:
+               case MONO_TYPE_BOOLEAN:
+               case MONO_TYPE_I2:
+               case MONO_TYPE_U2:
+               case MONO_TYPE_CHAR:
+               case MONO_TYPE_I8:
+               case MONO_TYPE_U8:
+               case MONO_TYPE_PTR:
+               case MONO_TYPE_R4:
+               case MONO_TYPE_R8:
+                       mono_mb_emit_ldloc (mb, 1);
+                       mono_mb_emit_ldloc (mb, 0);
+                       if (t == MONO_TYPE_CHAR && string_encoding != MONO_NATIVE_LPWSTR) {
+                               if (to_object) {
+                                       mono_mb_emit_byte (mb, CEE_LDIND_U1);
+                                       mono_mb_emit_byte (mb, CEE_STIND_I2);
+                               } else {
+                                       mono_mb_emit_byte (mb, CEE_LDIND_U2);
+                                       mono_mb_emit_byte (mb, CEE_STIND_I1);
+                               }
+                               usize = 1;
+                       } else {
+                               mono_mb_emit_byte (mb, mono_type_to_ldind (etype));
+                               mono_mb_emit_byte (mb, mono_type_to_stind (etype));
+                       }
+                       break;
+               default:
+                       g_assert_not_reached ();
+                       break;
+               }
+
+               if (to_object) {
+                       mono_mb_emit_add_to_local (mb, 0, usize);
+                       mono_mb_emit_add_to_local (mb, 1, msize);
+               } else {
+                       mono_mb_emit_add_to_local (mb, 0, msize);
+                       mono_mb_emit_add_to_local (mb, 1, usize);
+               }
+
+               /* Loop footer */
+               mono_mb_emit_add_to_local (mb, index_var, 1);
+
+               mono_mb_emit_branch_label (mb, CEE_BR, label2);
+
+               mono_mb_patch_branch (mb, label3);
+       }
+
+       *out_usize = usize * len;
+}
+
 static void
 emit_struct_conv_full (MonoMethodBuilder *mb, MonoClass *klass, gboolean to_object,
                                                int offset_of_first_child_field, MonoMarshalNative string_encoding)
@@ -1960,7 +2117,7 @@ emit_struct_conv_full (MonoMethodBuilder *mb, MonoClass *klass, gboolean to_obje
        }
 
        if (klass != mono_class_try_get_safehandle_class ()) {
-               if ((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_AUTO_LAYOUT) {
+               if (mono_class_is_auto_layout (klass)) {
                        char *msg = g_strdup_printf ("Type %s which is passed to unmanaged code must have a StructLayout attribute.",
                                                                                 mono_type_full_name (&klass->byval_arg));
                        mono_mb_emit_exception_marshal_directive (mb, msg);
@@ -1995,7 +2152,7 @@ emit_struct_conv_full (MonoMethodBuilder *mb, MonoClass *klass, gboolean to_obje
                         * the layout to the managed structure as well.
                         */
                        
-                       if (((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) && (usize == 0)) {
+                       if (mono_class_is_explicit_layout (klass) && (usize == 0)) {
                                if (MONO_TYPE_IS_REFERENCE (info->fields [i].field->type) ||
                                    ((!last_field && MONO_TYPE_IS_REFERENCE (info->fields [i + 1].field->type))))
                                        g_error ("Type %s which has an [ExplicitLayout] attribute cannot have a "
@@ -2051,6 +2208,8 @@ emit_struct_conv_full (MonoMethodBuilder *mb, MonoClass *klass, gboolean to_obje
                                break;
                        case MONO_TYPE_VALUETYPE: {
                                int src_var, dst_var;
+                               MonoType *etype;
+                               int len;
 
                                if (ftype->data.klass->enumtype) {
                                        ftype = mono_class_enum_basetype (ftype->data.klass);
@@ -2067,7 +2226,11 @@ emit_struct_conv_full (MonoMethodBuilder *mb, MonoClass *klass, gboolean to_obje
                                mono_mb_emit_ldloc (mb, 1);
                                mono_mb_emit_stloc (mb, dst_var);
 
-                               emit_struct_conv (mb, ftype->data.klass, to_object);
+                               if (get_fixed_buffer_attr (info->fields [i].field, &etype, &len)) {
+                                       emit_fixed_buf_conv (mb, ftype, etype, len, to_object, &usize);
+                               } else {
+                                       emit_struct_conv (mb, ftype->data.klass, to_object);
+                               }
 
                                /* restore the old src pointer */
                                mono_mb_emit_ldloc (mb, src_var);
@@ -2288,7 +2451,7 @@ mono_delegate_begin_invoke (MonoDelegate *delegate, gpointer *params)
                method = mono_get_delegate_invoke (klass);
        g_assert (method);
 
-       MonoAsyncResult *result = mono_threadpool_ms_begin_invoke (mono_domain_get (), (MonoObject*) delegate, method, params, &error);
+       MonoAsyncResult *result = mono_threadpool_begin_invoke (mono_domain_get (), (MonoObject*) delegate, method, params, &error);
        mono_error_set_pending_exception (&error);
        return result;
 }
@@ -2418,6 +2581,8 @@ mono_marshal_get_string_to_ptr_conv (MonoMethodPInvoke *piinfo, MonoMarshalSpec
                return MONO_MARSHAL_CONV_STR_LPTSTR;
        case MONO_NATIVE_BSTR:
                return MONO_MARSHAL_CONV_STR_BSTR;
+       case MONO_NATIVE_UTF8STR:
+               return MONO_MARSHAL_CONV_STR_UTF8STR;
        default:
                return MONO_MARSHAL_CONV_INVALID;
        }
@@ -2431,13 +2596,12 @@ mono_marshal_get_stringbuilder_to_ptr_conv (MonoMethodPInvoke *piinfo, MonoMarsh
        switch (encoding) {
        case MONO_NATIVE_LPWSTR:
                return MONO_MARSHAL_CONV_SB_LPWSTR;
-               break;
        case MONO_NATIVE_LPSTR:
                return MONO_MARSHAL_CONV_SB_LPSTR;
-               break;
+       case MONO_NATIVE_UTF8STR:
+               return MONO_MARSHAL_CONV_SB_UTF8STR;
        case MONO_NATIVE_LPTSTR:
                return MONO_MARSHAL_CONV_SB_LPTSTR;
-               break;
        default:
                return MONO_MARSHAL_CONV_INVALID;
        }
@@ -2454,6 +2618,8 @@ mono_marshal_get_ptr_to_string_conv (MonoMethodPInvoke *piinfo, MonoMarshalSpec
        case MONO_NATIVE_LPWSTR:
                *need_free = FALSE;
                return MONO_MARSHAL_CONV_LPWSTR_STR;
+       case MONO_NATIVE_UTF8STR:
+               return MONO_MARSHAL_CONV_UTF8STR_STR;
        case MONO_NATIVE_LPSTR:
        case MONO_NATIVE_VBBYREFSTR:
                return MONO_MARSHAL_CONV_LPSTR_STR;
@@ -2481,6 +2647,8 @@ mono_marshal_get_ptr_to_stringbuilder_conv (MonoMethodPInvoke *piinfo, MonoMarsh
                 */
                *need_free = FALSE;
                return MONO_MARSHAL_CONV_LPWSTR_SB;
+       case MONO_NATIVE_UTF8STR:
+               return MONO_MARSHAL_CONV_UTF8STR_SB;
        case MONO_NATIVE_LPSTR:
                return MONO_MARSHAL_CONV_LPSTR_SB;
                break;
@@ -2868,6 +3036,7 @@ cache_generic_delegate_wrapper (GHashTable *cache, MonoMethod *orig_method, Mono
 {
        MonoError error;
        MonoMethod *inst, *res;
+       WrapperInfo *ginfo, *info;
 
        /*
         * We use the same cache for the generic definition and the instances.
@@ -2875,6 +3044,16 @@ cache_generic_delegate_wrapper (GHashTable *cache, MonoMethod *orig_method, Mono
        inst = mono_class_inflate_generic_method_checked (def, ctx, &error);
        g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
 
+       ginfo = mono_marshal_get_wrapper_info (def);
+       if (ginfo) {
+               info = (WrapperInfo *)mono_image_alloc0 (def->klass->image, sizeof (WrapperInfo));
+               info->subtype = ginfo->subtype;
+               if (info->subtype == WRAPPER_SUBTYPE_NONE) {
+                       info->d.delegate_invoke.method = mono_class_inflate_generic_method_checked (ginfo->d.delegate_invoke.method, ctx, &error);
+                       mono_error_assert_ok (&error);
+               }
+       }
+
        mono_memory_barrier ();
        mono_marshal_lock ();
        res = (MonoMethod *)g_hash_table_lookup (cache, orig_method->klass);
@@ -3031,7 +3210,7 @@ mono_delegate_end_invoke (MonoDelegate *delegate, gpointer *params)
        } else
 #endif
        {
-               res = mono_threadpool_ms_end_invoke (ares, &out_args, &exc, &error);
+               res = mono_threadpool_end_invoke (ares, &out_args, &exc, &error);
                if (mono_error_set_pending_exception (&error))
                        return NULL;
        }
@@ -3244,7 +3423,7 @@ mono_marshal_get_delegate_invoke_internal (MonoMethod *method, gboolean callvirt
        MonoMethod *res;
        GHashTable *cache;
        gpointer cache_key = NULL;
-       SignaturePointerPair key;
+       SignaturePointerPair key = { NULL, NULL };
        SignaturePointerPair *new_key;
        int local_i, local_len, local_delegates, local_d, local_target, local_res;
        int pos0, pos1, pos2;
@@ -3302,7 +3481,7 @@ mono_marshal_get_delegate_invoke_internal (MonoMethod *method, gboolean callvirt
 
                container = mono_method_get_generic_container (method);
                if (!container)
-                       container = method->klass->generic_container;
+                       container = mono_class_try_get_generic_container (method->klass); //FIXME is this a case of a try?
                g_assert (container);
 
                invoke_sig = sig = mono_signature_no_pinvoke (method);
@@ -3545,7 +3724,7 @@ mono_marshal_get_delegate_invoke_internal (MonoMethod *method, gboolean callvirt
 #endif /* DISABLE_JIT */
 
        info = mono_wrapper_info_create (mb, subtype);
-       info->d.delegate_invoke.method = orig_method;
+       info->d.delegate_invoke.method = method;
 
        if (ctx) {
                MonoMethod *def;
@@ -4918,8 +5097,7 @@ emit_marshal_vtype (EmitMarshalContext *m, int argnum, MonoType *t,
                        break;
                }
 
-               if (((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) ||
-                       klass->blittable || klass->enumtype)
+               if (mono_class_is_explicit_layout (klass) || klass->blittable || klass->enumtype)
                        break;
 
                conv_arg = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
@@ -4965,8 +5143,7 @@ emit_marshal_vtype (EmitMarshalContext *m, int argnum, MonoType *t,
                        /* Have to change the signature since the vtype is passed byref */
                        m->csig->params [argnum - m->csig->hasthis] = &mono_defaults.int_class->byval_arg;
 
-                       if (((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) ||
-                               klass->blittable || klass->enumtype)
+                       if (mono_class_is_explicit_layout (klass) || klass->blittable || klass->enumtype)
                                mono_mb_emit_ldarg_addr (mb, argnum);
                        else
                                mono_mb_emit_ldloc (mb, conv_arg);
@@ -4981,8 +5158,7 @@ emit_marshal_vtype (EmitMarshalContext *m, int argnum, MonoType *t,
                        break;
                }
 
-               if (((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) ||
-                       klass->blittable || klass->enumtype) {
+               if (mono_class_is_explicit_layout (klass) || klass->blittable || klass->enumtype) {
                        mono_mb_emit_ldarg (mb, argnum);
                        break;
                }                       
@@ -5014,8 +5190,7 @@ emit_marshal_vtype (EmitMarshalContext *m, int argnum, MonoType *t,
                        break;
                }
 
-               if (((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) ||
-                       klass->blittable || klass->enumtype)
+               if (mono_class_is_explicit_layout (klass) || klass->blittable || klass->enumtype)
                        break;
 
                if (t->byref) {
@@ -5043,8 +5218,7 @@ emit_marshal_vtype (EmitMarshalContext *m, int argnum, MonoType *t,
                break;
 
        case MARSHAL_ACTION_CONV_RESULT:
-               if (((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) ||
-                       klass->blittable) {
+               if (mono_class_is_explicit_layout (klass) || klass->blittable) {
                        mono_mb_emit_stloc (mb, 3);
                        break;
                }
@@ -5063,8 +5237,7 @@ emit_marshal_vtype (EmitMarshalContext *m, int argnum, MonoType *t,
                break;
 
        case MARSHAL_ACTION_MANAGED_CONV_IN:
-               if (((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) ||
-                       klass->blittable || klass->enumtype) {
+               if (mono_class_is_explicit_layout (klass) || klass->blittable || klass->enumtype) {
                        conv_arg = 0;
                        break;
                }
@@ -5096,11 +5269,8 @@ emit_marshal_vtype (EmitMarshalContext *m, int argnum, MonoType *t,
                break;
 
        case MARSHAL_ACTION_MANAGED_CONV_OUT:
-               if (((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) ||
-                       klass->blittable || klass->enumtype) {
+               if (mono_class_is_explicit_layout (klass) || klass->blittable || klass->enumtype)
                        break;
-               }
-
                if (t->byref && (t->attrs & PARAM_ATTRIBUTE_IN) && !(t->attrs & PARAM_ATTRIBUTE_OUT))
                        break;
 
@@ -5123,8 +5293,7 @@ emit_marshal_vtype (EmitMarshalContext *m, int argnum, MonoType *t,
                break;
 
        case MARSHAL_ACTION_MANAGED_CONV_RESULT:
-               if (((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) ||
-                       klass->blittable || klass->enumtype) {
+               if (mono_class_is_explicit_layout (klass) || klass->blittable || klass->enumtype) {
                        mono_mb_emit_stloc (mb, 3);
                        m->retobj_var = 0;
                        break;
@@ -5456,7 +5625,7 @@ emit_marshal_safehandle (EmitMarshalContext *m, int argnum, MonoType *t,
                MonoMethod *ctor = NULL;
                int intptr_handle_slot;
                
-               if (t->data.klass->flags & TYPE_ATTRIBUTE_ABSTRACT){
+               if (mono_class_is_abstract (t->data.klass)) {
                        mono_mb_emit_byte (mb, CEE_POP);
                        mono_mb_emit_exception_marshal_directive (mb, g_strdup ("Returned SafeHandles should not be abstract"));
                        break;
@@ -5729,6 +5898,9 @@ emit_marshal_object (EmitMarshalContext *m, int argnum, MonoType *t,
                                case MONO_NATIVE_LPSTR:
                                        mono_mb_emit_icall (mb, mono_string_utf8_to_builder2);
                                        break;
+                               case MONO_NATIVE_UTF8STR:
+                                       mono_mb_emit_icall (mb, mono_string_utf8_to_builder2);
+                                       break;
                                default:
                                        g_assert_not_reached ();
                                }
@@ -5839,6 +6011,8 @@ emit_marshal_object (EmitMarshalContext *m, int argnum, MonoType *t,
                        mono_mb_emit_ldloc (mb, 0);
                        mono_mb_emit_icall (mb, conv_to_icall (MONO_MARSHAL_CONV_FTN_DEL, NULL));
                        mono_mb_emit_stloc (mb, 3);
+               } else if (klass == mono_defaults.stringbuilder_class){
+                       // FIXME: implement
                } else {
                        /* set src */
                        mono_mb_emit_stloc (mb, 0);
@@ -5898,7 +6072,7 @@ emit_marshal_object (EmitMarshalContext *m, int argnum, MonoType *t,
                        encoding = mono_marshal_get_string_encoding (m->piinfo, spec);
 
                        // FIXME:
-                       g_assert (encoding == MONO_NATIVE_LPSTR);
+                       g_assert (encoding == MONO_NATIVE_LPSTR || encoding == MONO_NATIVE_UTF8STR);
 
                        g_assert (!t->byref);
                        g_assert (encoding != -1);
@@ -5910,7 +6084,7 @@ emit_marshal_object (EmitMarshalContext *m, int argnum, MonoType *t,
                }
 
                /* The class can not have an automatic layout */
-               if ((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_AUTO_LAYOUT) {
+               if (mono_class_is_auto_layout (klass)) {
                        mono_mb_emit_auto_layout_exception (mb, klass);
                        break;
                }
@@ -6030,7 +6204,7 @@ emit_marshal_object (EmitMarshalContext *m, int argnum, MonoType *t,
                }
 
                /* The class can not have an automatic layout */
-               if ((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_AUTO_LAYOUT) {
+               if (mono_class_is_auto_layout (klass)) {
                        mono_mb_emit_auto_layout_exception (mb, klass);
                        break;
                }
@@ -6664,7 +6838,8 @@ emit_marshal_array (EmitMarshalContext *m, int argnum, MonoType *t,
                        mono_mb_emit_icon (mb, esize);
                        mono_mb_emit_byte (mb, CEE_MUL);
                        mono_mb_emit_byte (mb, CEE_PREFIX1);
-                       mono_mb_emit_byte (mb, CEE_CPBLK);                      
+                       mono_mb_emit_byte (mb, CEE_CPBLK);
+                       mono_mb_patch_branch (mb, label1);
                        break;
                }
 
@@ -7490,7 +7665,7 @@ mono_marshal_emit_native_wrapper (MonoImage *image, MonoMethodBuilder *mb, MonoM
        if (MONO_TYPE_ISSTRUCT (sig->ret)) {
                MonoClass *klass = mono_class_from_mono_type (sig->ret);
                mono_class_init (klass);
-               if (!(((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) || klass->blittable)) {
+               if (!(mono_class_is_explicit_layout (klass) || klass->blittable)) {
                        /* This is used by emit_marshal_vtype (), but it needs to go right before the call */
                        mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
                        mono_mb_emit_byte (mb, CEE_MONO_VTADDR);
@@ -7765,6 +7940,8 @@ mono_marshal_get_native_wrapper (MonoMethod *method, gboolean check_exceptions,
                int thread_info_var = -1, stack_mark_var = -1, error_var = -1;
                MonoMethodSignature *call_sig = csig;
                gboolean uses_handles = FALSE;
+               gboolean has_outarg_handles = FALSE;
+               int *outarg_handle = NULL;
                (void) mono_lookup_internal_call_full (method, &uses_handles);
 
 
@@ -7781,9 +7958,13 @@ mono_marshal_get_native_wrapper (MonoMethod *method, gboolean check_exceptions,
                        ret->param_count = csig->param_count + 1;
                        ret->ret = csig->ret;
                        for (int i = 0; i < csig->param_count; ++i) {
-                               // FIXME: TODO implement handle wrapping for out and inout params.
-                               g_assert (!mono_signature_param_is_out (csig, i));
-                               ret->params [i] = csig->params [i];
+                               if (MONO_TYPE_IS_REFERENCE (csig->params[i])) {
+                                       ret->params [i] = mono_class_get_byref_type (mono_class_from_mono_type(csig->params[i]));
+                                       if (mono_signature_param_is_out (csig, i)) {
+                                               has_outarg_handles = TRUE;
+                                       }
+                               } else
+                                       ret->params [i] = csig->params [i];
                        }
                        ret->params [csig->param_count] = &mono_get_intptr_class ()->byval_arg;
                        call_sig = ret;
@@ -7797,7 +7978,17 @@ mono_marshal_get_native_wrapper (MonoMethod *method, gboolean check_exceptions,
                        stack_mark_var = mono_mb_add_local (mb, &handle_stack_mark_class->byval_arg);
                        error_var = mono_mb_add_local (mb, &error_class->byval_arg);
 
-                       // FIXME: Change csig so it passes a handle not an objref
+                       if (has_outarg_handles) {
+                               outarg_handle = g_new0 (int, sig->param_count);
+
+                               /* add a local var to hold the handles for each out arg */
+                               for (int i = 0; i < sig->param_count; ++i) {
+                                       if (mono_signature_param_is_out (sig, i) && MONO_TYPE_IS_REFERENCE (sig->params[i])) {
+                                               outarg_handle[i] = mono_mb_add_local (mb, sig->params[i]);
+                                       } else if (outarg_handle != NULL)
+                                               outarg_handle[i] = -1;
+                               }
+                       }
                }
 
                if (sig->hasthis) {
@@ -7824,9 +8015,24 @@ mono_marshal_get_native_wrapper (MonoMethod *method, gboolean check_exceptions,
                                mono_mb_emit_icall (mb, mono_handle_new);
                        }
                        for (i = 0; i < sig->param_count; i++) {
-                               mono_mb_emit_ldarg (mb, i + sig->hasthis);
-                               if (MONO_TYPE_IS_REFERENCE (sig->params [i])) {
-                                       mono_mb_emit_icall (mb, mono_handle_new);
+                               /* load each argument. object reference arguments get wrapped in handles */
+
+                               if (!MONO_TYPE_IS_REFERENCE (sig->params [i])) {
+                                       mono_mb_emit_ldarg (mb, i + sig->hasthis);
+                               } else {
+                                       if (outarg_handle && outarg_handle[i] != -1) {
+                                               /* handleI = argI = mono_handle_new (NULL) */
+                                               mono_mb_emit_byte (mb, CEE_LDNULL);
+                                               mono_mb_emit_icall (mb, mono_handle_new);
+                                               /* tmp = argI */
+                                               mono_mb_emit_byte (mb, CEE_DUP);
+                                               /* handleI = tmp */
+                                               mono_mb_emit_stloc (mb, outarg_handle[i]);
+                                       } else {
+                                               /* argI = mono_handle_new (argI_raw) */
+                                               mono_mb_emit_ldarg (mb, i + sig->hasthis);
+                                               mono_mb_emit_icall (mb, mono_handle_new);
+                                       }
                                }
                        }
                        mono_mb_emit_ldloc_addr (mb, error_var);
@@ -7857,6 +8063,25 @@ mono_marshal_get_native_wrapper (MonoMethod *method, gboolean check_exceptions,
                                mono_mb_emit_byte (mb, CEE_LDIND_REF);
                                mono_mb_patch_branch (mb, pos);
                        }
+                       if (outarg_handle != NULL) {
+                               for (i = 0; i < sig->param_count; i++) {
+                                       if (outarg_handle[i] != -1) {
+                                               /* *argI_raw = MONO_HANDLE_RAW (handleI) */
+
+                                               /* argI_raw */
+                                               mono_mb_emit_ldarg (mb, i + sig->hasthis);
+                                               /* handleI */
+                                               mono_mb_emit_ldloc (mb, outarg_handle[i]);
+                                               /* MONO_HANDLE_RAW(handleI) */
+                                               mono_mb_emit_ldflda (mb, MONO_HANDLE_PAYLOAD_OFFSET (MonoObject));
+                                               mono_mb_emit_byte (mb, CEE_LDIND_REF);
+                                               /* *argI_raw = MONO_HANDLE_RAW(handleI) */
+                                               mono_mb_emit_byte (mb, CEE_STIND_REF);
+                                       }
+                               }
+                               g_free (outarg_handle);
+                               outarg_handle = NULL;
+                       }
                        mono_mb_emit_ldloc (mb, thread_info_var);
                        mono_mb_emit_ldloc_addr (mb, stack_mark_var);
                        mono_mb_emit_ldloc_addr (mb, error_var);
@@ -8229,7 +8454,7 @@ mono_marshal_emit_managed_wrapper (MonoMethodBuilder *mb, MonoMethodSignature *i
        if (MONO_TYPE_ISSTRUCT (sig->ret)) {
                MonoClass *klass = mono_class_from_mono_type (sig->ret);
                mono_class_init (klass);
-               if (!(((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) || klass->blittable)) {
+               if (!(mono_class_is_explicit_layout (klass) || klass->blittable)) {
                        /* This is used by emit_marshal_vtype (), but it needs to go right before the call */
                        mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
                        mono_mb_emit_byte (mb, CEE_MONO_VTADDR);
@@ -8889,199 +9114,6 @@ mono_marshal_get_isinst_with_cache (void)
        return cached;
 }
 
-/*
- * mono_marshal_get_isinst:
- * @klass: the type of the field
- *
- * This method generates a function which can be used to check if an object is
- * an instance of the given type, icluding the case where the object is a proxy.
- * The generated function has the following signature:
- * MonoObject* __isinst_wrapper_ (MonoObject *obj)
- */
-MonoMethod *
-mono_marshal_get_isinst (MonoClass *klass)
-{
-       static MonoMethodSignature *isint_sig = NULL;
-       GHashTable *cache;
-       MonoMethod *res;
-       WrapperInfo *info;
-       int pos_was_ok, pos_end;
-#ifndef DISABLE_REMOTING
-       int pos_end2, pos_failed;
-#endif
-       char *name;
-       MonoMethodBuilder *mb;
-
-       cache = get_cache (&klass->image->isinst_cache, mono_aligned_addr_hash, NULL);
-       if ((res = mono_marshal_find_in_cache (cache, klass)))
-               return res;
-
-       if (!isint_sig) {
-               isint_sig = mono_metadata_signature_alloc (mono_defaults.corlib, 1);
-               isint_sig->params [0] = &mono_defaults.object_class->byval_arg;
-               isint_sig->ret = &mono_defaults.object_class->byval_arg;
-               isint_sig->pinvoke = 0;
-       }
-       
-       name = g_strdup_printf ("__isinst_wrapper_%s", klass->name); 
-       mb = mono_mb_new (mono_defaults.object_class, name, MONO_WRAPPER_ISINST);
-       g_free (name);
-       
-       mb->method->save_lmf = 1;
-
-#ifndef DISABLE_JIT
-       /* check if the object is a proxy that needs special cast */
-       mono_mb_emit_ldarg (mb, 0);
-       mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
-       mono_mb_emit_op (mb, CEE_MONO_CISINST, klass);
-
-       /* The result of MONO_CISINST can be:
-               0) the type check succeeded
-               1) the type check did not succeed
-               2) a CanCastTo call is needed */
-#ifndef DISABLE_REMOTING
-       mono_mb_emit_byte (mb, CEE_DUP);
-       pos_was_ok = mono_mb_emit_branch (mb, CEE_BRFALSE);
-
-       mono_mb_emit_byte (mb, CEE_LDC_I4_2);
-       pos_failed = mono_mb_emit_branch (mb, CEE_BNE_UN);
-       
-       /* get the real proxy from the transparent proxy*/
-
-       mono_mb_emit_ldarg (mb, 0);
-       mono_mb_emit_managed_call (mb, mono_marshal_get_proxy_cancast (klass), NULL);
-       pos_end = mono_mb_emit_branch (mb, CEE_BR);
-       
-       /* fail */
-       
-       mono_mb_patch_branch (mb, pos_failed);
-       mono_mb_emit_byte (mb, CEE_LDNULL);
-       pos_end2 = mono_mb_emit_branch (mb, CEE_BR);
-       
-       /* success */
-       
-       mono_mb_patch_branch (mb, pos_was_ok);
-       mono_mb_emit_byte (mb, CEE_POP);
-       mono_mb_emit_ldarg (mb, 0);
-       
-       /* the end */
-       
-       mono_mb_patch_branch (mb, pos_end);
-       mono_mb_patch_branch (mb, pos_end2);
-       mono_mb_emit_byte (mb, CEE_RET);
-#else
-       pos_was_ok = mono_mb_emit_branch (mb, CEE_BRFALSE);
-
-       /* fail */
-
-       mono_mb_emit_byte (mb, CEE_LDNULL);
-       pos_end = mono_mb_emit_branch (mb, CEE_BR);
-
-       /* success */
-
-       mono_mb_patch_branch (mb, pos_was_ok);
-       mono_mb_emit_ldarg (mb, 0);
-
-       /* the end */
-
-       mono_mb_patch_branch (mb, pos_end);
-       mono_mb_emit_byte (mb, CEE_RET);
-#endif /* DISABLE_REMOTING */
-#endif /* DISABLE_JIT */
-
-       info = mono_wrapper_info_create (mb, WRAPPER_SUBTYPE_NONE);
-       info->d.proxy.klass = klass;
-       res = mono_mb_create_and_cache_full (cache, klass, mb, isint_sig, isint_sig->param_count + 16, info, NULL);
-       mono_mb_free (mb);
-
-       return res;
-}
-
-/*
- * mono_marshal_get_castclass:
- * @klass: the type of the field
- *
- * This method generates a function which can be used to cast an object to
- * an instance of the given type, icluding the case where the object is a proxy.
- * The generated function has the following signature:
- * MonoObject* __castclass_wrapper_ (MonoObject *obj)
- */
-MonoMethod *
-mono_marshal_get_castclass (MonoClass *klass)
-{
-       static MonoMethodSignature *castclass_sig = NULL;
-       GHashTable *cache;
-       MonoMethod *res;
-#ifndef DISABLE_REMOTING
-       int pos_was_ok, pos_was_ok2;
-#endif
-       char *name;
-       MonoMethodBuilder *mb;
-       WrapperInfo *info;
-
-       cache = get_cache (&klass->image->castclass_cache, mono_aligned_addr_hash, NULL);
-       if ((res = mono_marshal_find_in_cache (cache, klass)))
-               return res;
-
-       if (!castclass_sig) {
-               castclass_sig = mono_metadata_signature_alloc (mono_defaults.corlib, 1);
-               castclass_sig->params [0] = &mono_defaults.object_class->byval_arg;
-               castclass_sig->ret = &mono_defaults.object_class->byval_arg;
-               castclass_sig->pinvoke = 0;
-       }
-       
-       name = g_strdup_printf ("__castclass_wrapper_%s", klass->name); 
-       mb = mono_mb_new (mono_defaults.object_class, name, MONO_WRAPPER_CASTCLASS);
-       g_free (name);
-       
-       mb->method->save_lmf = 1;
-
-#ifndef DISABLE_JIT
-       /* check if the object is a proxy that needs special cast */
-       mono_mb_emit_ldarg (mb, 0);
-       mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
-       mono_mb_emit_op (mb, CEE_MONO_CCASTCLASS, klass);
-
-       /* The result of MONO_CCASTCLASS can be:
-               0) the cast is valid
-               1) cast of unknown proxy type
-               or an exception if the cast is is invalid
-       */
-#ifndef DISABLE_REMOTING
-       pos_was_ok = mono_mb_emit_branch (mb, CEE_BRFALSE);
-
-       /* get the real proxy from the transparent proxy*/
-
-       mono_mb_emit_ldarg (mb, 0);
-       mono_mb_emit_managed_call (mb, mono_marshal_get_proxy_cancast (klass), NULL);
-       pos_was_ok2 = mono_mb_emit_branch (mb, CEE_BRTRUE);
-       
-       /* fail */
-       mono_mb_emit_exception (mb, "InvalidCastException", NULL);
-       
-       /* success */
-       mono_mb_patch_branch (mb, pos_was_ok);
-       mono_mb_patch_branch (mb, pos_was_ok2);
-#else
-       /* MONO_CCASTCLASS leaves an int in the stack with the result, pop it. */
-       mono_mb_emit_byte (mb, CEE_POP);
-#endif /* DISABLE_REMOTING */
-
-       mono_mb_emit_ldarg (mb, 0);
-       
-       /* the end */
-       mono_mb_emit_byte (mb, CEE_RET);
-#endif /* DISABLE_JIT */
-
-       info = mono_wrapper_info_create (mb, WRAPPER_SUBTYPE_NONE);
-
-       res = mono_mb_create_and_cache_full (cache, klass, mb, castclass_sig, castclass_sig->param_count + 16,
-                                                                                info, NULL);
-       mono_mb_free (mb);
-
-       return res;
-}
-
 /**
  * mono_marshal_get_struct_to_ptr:
  * @klass:
@@ -9100,8 +9132,9 @@ mono_marshal_get_struct_to_ptr (MonoClass *klass)
 
        mono_marshal_load_type_info (klass);
 
-       if (klass->marshal_info->str_to_ptr)
-               return klass->marshal_info->str_to_ptr;
+       MonoMarshalType *marshal_info = mono_class_get_marshal_info (klass);
+       if (marshal_info->str_to_ptr)
+               return marshal_info->str_to_ptr;
 
        if (!stoptr) 
                stoptr = mono_class_get_method_from_name (mono_defaults.marshal_class, "StructureToPtr", 3);
@@ -9147,10 +9180,10 @@ mono_marshal_get_struct_to_ptr (MonoClass *klass)
        mono_mb_free (mb);
 
        mono_marshal_lock ();
-       if (!klass->marshal_info->str_to_ptr)
-               klass->marshal_info->str_to_ptr = res;
+       if (!marshal_info->str_to_ptr)
+               marshal_info->str_to_ptr = res;
        else
-               res = klass->marshal_info->str_to_ptr;
+               res = marshal_info->str_to_ptr;
        mono_marshal_unlock ();
        return res;
 }
@@ -9173,8 +9206,9 @@ mono_marshal_get_ptr_to_struct (MonoClass *klass)
 
        mono_marshal_load_type_info (klass);
 
-       if (klass->marshal_info->ptr_to_str)
-               return klass->marshal_info->ptr_to_str;
+       MonoMarshalType *marshal_info = mono_class_get_marshal_info (klass);
+       if (marshal_info->ptr_to_str)
+               return marshal_info->ptr_to_str;
 
        if (!ptostr) {
                MonoMethodSignature *sig;
@@ -9225,10 +9259,10 @@ mono_marshal_get_ptr_to_struct (MonoClass *klass)
        mono_mb_free (mb);
 
        mono_marshal_lock ();
-       if (!klass->marshal_info->ptr_to_str)
-               klass->marshal_info->ptr_to_str = res;
+       if (!marshal_info->ptr_to_str)
+               marshal_info->ptr_to_str = res;
        else
-               res = klass->marshal_info->ptr_to_str;
+               res = marshal_info->ptr_to_str;
        mono_marshal_unlock ();
        return res;
 }
@@ -9254,7 +9288,7 @@ mono_marshal_get_synchronized_inner_wrapper (MonoMethod *method)
                method = ((MonoMethodInflated*)method)->declaring;
                container = mono_method_get_generic_container (method);
                if (!container)
-                       container = method->klass->generic_container;
+                       container = mono_class_try_get_generic_container (method->klass); //FIXME is this a case of a try?
                g_assert (container);
        }
 
@@ -9308,7 +9342,7 @@ mono_marshal_get_synchronized_wrapper (MonoMethod *method)
                method = ((MonoMethodInflated*)method)->declaring;
                container = mono_method_get_generic_container (method);
                if (!container)
-                       container = method->klass->generic_container;
+                       container = mono_class_try_get_generic_container (method->klass); //FIXME is this a case of a try?
                g_assert (container);
        }
 
@@ -9535,7 +9569,7 @@ is_monomorphic_array (MonoClass *klass)
                return FALSE;
 
        element_class = klass->element_class;
-       return (element_class->flags & TYPE_ATTRIBUTE_SEALED) || element_class->valuetype;
+       return mono_class_is_sealed (element_class) || element_class->valuetype;
 }
 
 static int
@@ -9555,7 +9589,7 @@ get_virtual_stelemref_kind (MonoClass *element_class)
        /*Arrays are sealed but are covariant on their element type, We can't use any of the fast paths.*/
        if (mono_class_is_marshalbyref (element_class) || element_class->rank || mono_class_has_variant_generic_params (element_class))
                return STELEMREF_COMPLEX;
-       if (element_class->flags & TYPE_ATTRIBUTE_SEALED)
+       if (mono_class_is_sealed (element_class))
                return STELEMREF_SEALED_CLASS;
        return STELEMREF_CLASS;
 }
@@ -9914,14 +9948,14 @@ get_virtual_stelemref_wrapper (int kind)
                /* uiid = klass->interface_id; */
                mono_mb_emit_ldloc (mb, aklass);
                mono_mb_emit_ldflda (mb, MONO_STRUCT_OFFSET (MonoClass, interface_id));
-               mono_mb_emit_byte (mb, CEE_LDIND_U2);
+               mono_mb_emit_byte (mb, CEE_LDIND_U4);
                mono_mb_emit_stloc (mb, uiid);
 
                /*if (uiid > vt->max_interface_id)*/
                mono_mb_emit_ldloc (mb, uiid);
                mono_mb_emit_ldloc (mb, vtable);
                mono_mb_emit_ldflda (mb, MONO_STRUCT_OFFSET (MonoVTable, max_interface_id));
-               mono_mb_emit_byte (mb, CEE_LDIND_U2);
+               mono_mb_emit_byte (mb, CEE_LDIND_U4);
                b2 = mono_mb_emit_branch (mb, CEE_BGT_UN);
 
                /* if (!(vt->interface_bitmap [(uiid) >> 3] & (1 << ((uiid)&7)))) */
@@ -10772,7 +10806,7 @@ ves_icall_System_Runtime_InteropServices_Marshal_SizeOf (MonoReflectionType *rty
                return 0;
        }
 
-       layout = (klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK);
+       layout = (mono_class_get_flags (klass) & TYPE_ATTRIBUTE_LAYOUT_MASK);
 
        if (type->type == MONO_TYPE_PTR || type->type == MONO_TYPE_FNPTR) {
                return sizeof (gpointer);
@@ -11014,6 +11048,7 @@ mono_struct_delete_old (MonoClass *klass, char *ptr)
                case MONO_MARSHAL_CONV_STR_BSTR:
                case MONO_MARSHAL_CONV_STR_ANSIBSTR:
                case MONO_MARSHAL_CONV_STR_TBSTR:
+               case MONO_MARSHAL_CONV_STR_UTF8STR:
                        mono_marshal_free (*(gpointer *)cpos);
                        break;
 
@@ -11124,6 +11159,18 @@ ves_icall_System_Runtime_InteropServices_Marshal_AllocCoTaskMem (int size)
        return res;
 }
 
+void*
+ves_icall_System_Runtime_InteropServices_Marshal_AllocCoTaskMemSize (gulong size)
+{
+       void *res = mono_marshal_alloc_co_task_mem (size);
+
+       if (!res) {
+               mono_set_pending_exception (mono_domain_get ()->out_of_memory_ex);
+               return NULL;
+       }
+       return res;
+}
+
 void
 ves_icall_System_Runtime_InteropServices_Marshal_FreeCoTaskMem (void *ptr)
 {
@@ -11192,7 +11239,7 @@ mono_marshal_is_loading_type_info (MonoClass *klass)
 /**
  * mono_marshal_load_type_info:
  *
- *  Initialize klass->marshal_info using information from metadata. This function can
+ *  Initialize klass::marshal_info using information from metadata. This function can
  * recursively call itself, and the caller is responsible to avoid that by calling 
  * mono_marshal_is_loading_type_info () beforehand.
  *
@@ -11211,14 +11258,16 @@ mono_marshal_load_type_info (MonoClass* klass)
 
        g_assert (klass != NULL);
 
-       if (klass->marshal_info)
-               return klass->marshal_info;
+       info = mono_class_get_marshal_info (klass);
+       if (info)
+               return info;
 
        if (!klass->inited)
                mono_class_init (klass);
 
-       if (klass->marshal_info)
-               return klass->marshal_info;
+       info = mono_class_get_marshal_info (klass);
+       if (info)
+               return info;
 
        /*
         * This function can recursively call itself, so we keep the list of classes which are
@@ -11238,7 +11287,7 @@ mono_marshal_load_type_info (MonoClass* klass)
                count++;
        }
 
-       layout = klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK;
+       layout = mono_class_get_flags (klass) & TYPE_ATTRIBUTE_LAYOUT_MASK;
 
        /* The mempool is protected by the loader lock */
        info = (MonoMarshalType *)mono_image_alloc0 (klass->image, MONO_SIZEOF_MARSHAL_TYPE + sizeof (MonoMarshalField) * count);
@@ -11340,14 +11389,17 @@ mono_marshal_load_type_info (MonoClass* klass)
        mono_native_tls_set_value (load_type_info_tls_id, loads_list);
 
        mono_marshal_lock ();
-       if (!klass->marshal_info) {
+       MonoMarshalType *info2 = mono_class_get_marshal_info (klass);
+       if (!info2) {
                /*We do double-checking locking on marshal_info */
                mono_memory_barrier ();
-               klass->marshal_info = info;
+               mono_class_set_marshal_info (klass, info);
+               ++class_marshal_info_count;
+               info2 = info;
        }
        mono_marshal_unlock ();
 
-       return klass->marshal_info;
+       return info2;
 }
 
 /**
@@ -11359,8 +11411,9 @@ mono_marshal_load_type_info (MonoClass* klass)
  */
 gint32
 mono_class_native_size (MonoClass *klass, guint32 *align)
-{      
-       if (!klass->marshal_info) {
+{
+       MonoMarshalType *info = mono_class_get_marshal_info (klass);
+       if (!info) {
                if (mono_marshal_is_loading_type_info (klass)) {
                        if (align)
                                *align = 0;
@@ -11368,12 +11421,13 @@ mono_class_native_size (MonoClass *klass, guint32 *align)
                } else {
                        mono_marshal_load_type_info (klass);
                }
+               info = mono_class_get_marshal_info (klass);
        }
 
        if (align)
-               *align = klass->marshal_info->min_align;
+               *align = info->min_align;
 
-       return klass->marshal_info->native_size;
+       return info->native_size;
 }
 
 /*
@@ -11503,6 +11557,7 @@ mono_marshal_type_size (MonoType *type, MonoMarshalSpec *mspec, guint32 *align,
        case MONO_NATIVE_BSTR:
        case MONO_NATIVE_ANSIBSTR:
        case MONO_NATIVE_TBSTR:
+       case MONO_NATIVE_UTF8STR:
        case MONO_NATIVE_LPARRAY:
        case MONO_NATIVE_SAFEARRAY:
        case MONO_NATIVE_IUNKNOWN:
@@ -11586,10 +11641,10 @@ mono_marshal_asany (MonoObject *o, MonoMarshalNative string_encoding, int param_
                switch (string_encoding) {
                case MONO_NATIVE_LPWSTR:
                        return mono_marshal_string_to_utf16_copy ((MonoString*)o);
-                       break;
                case MONO_NATIVE_LPSTR:
-                       return mono_string_to_lpstr ((MonoString*)o);
-                       break;
+               case MONO_NATIVE_UTF8STR:
+                       // Same code path, because in Mono, we treated strings as Utf8
+                       return mono_string_to_utf8str ((MonoString*)o);
                default:
                        g_warning ("marshaling conversion %d not implemented", string_encoding);
                        g_assert_not_reached ();
@@ -11604,11 +11659,10 @@ mono_marshal_asany (MonoObject *o, MonoMarshalNative string_encoding, int param_
 
                klass = t->data.klass;
 
-               if ((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_AUTO_LAYOUT)
+               if (mono_class_is_auto_layout (klass))
                        break;
 
-               if (klass->valuetype && (((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) ||
-                       klass->blittable || klass->enumtype))
+               if (klass->valuetype && (mono_class_is_explicit_layout (klass) || klass->blittable || klass->enumtype))
                        return mono_object_unbox (o);
 
                res = mono_marshal_alloc (mono_class_native_size (klass, NULL), &error);
@@ -11657,6 +11711,7 @@ mono_marshal_free_asany (MonoObject *o, gpointer ptr, MonoMarshalNative string_e
                switch (string_encoding) {
                case MONO_NATIVE_LPWSTR:
                case MONO_NATIVE_LPSTR:
+               case MONO_NATIVE_UTF8STR:
                        mono_marshal_free (ptr);
                        break;
                default:
@@ -11668,8 +11723,7 @@ mono_marshal_free_asany (MonoObject *o, gpointer ptr, MonoMarshalNative string_e
        case MONO_TYPE_VALUETYPE: {
                klass = t->data.klass;
 
-               if (klass->valuetype && (((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) ||
-                                                                klass->blittable || klass->enumtype))
+               if (klass->valuetype && (mono_class_is_explicit_layout (klass) || klass->blittable || klass->enumtype))
                        break;
 
                if (param_attrs & PARAM_ATTRIBUTE_OUT) {