Merge pull request #205 from m3rlinez/master
[mono.git] / mono / metadata / object.c
index dfb2a3016631f7a62ba57fc7d8084be3449f3b66..7d562d98e23b48c2b1f3e80ddd4cb5f2b1f7930d 100644 (file)
@@ -6,7 +6,8 @@
  *   Paolo Molaro (lupus@ximian.com)
  *
  * Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
- * Copyright 2004-2009 Novell, Inc (http://www.novell.com)
+ * Copyright 2004-2011 Novell, Inc (http://www.novell.com)
+ * Copyright 2001 Xamarin Inc (http://www.xamarin.com)
  */
 #include <config.h>
 #ifdef HAVE_ALLOCA_H
@@ -79,6 +80,13 @@ get_default_field_value (MonoDomain* domain, MonoClassField *field, void *value)
 static MonoString*
 mono_ldstr_metadata_sig (MonoDomain *domain, const char* sig);
 
+static void
+free_main_args (void);
+
+static char *
+mono_string_to_utf8_internal (MonoMemPool *mp, MonoImage *image, MonoString *s, gboolean ignore_error, MonoError *error);
+
+
 #define ldstr_lock() EnterCriticalSection (&ldstr_section)
 #define ldstr_unlock() LeaveCriticalSection (&ldstr_section)
 static CRITICAL_SECTION ldstr_section;
@@ -159,6 +167,13 @@ static MonoRuntimeCallbacks callbacks;
 void
 mono_thread_set_main (MonoThread *thread)
 {
+       static gboolean registered = FALSE;
+
+       if (!registered) {
+               MONO_GC_REGISTER_ROOT_SINGLE (main_thread);
+               registered = TRUE;
+       }
+
        main_thread = thread;
 }
 
@@ -185,8 +200,14 @@ mono_type_initialization_cleanup (void)
         * mono_release_type_locks
         */
        DeleteCriticalSection (&type_initialization_section);
+       g_hash_table_destroy (type_initialization_hash);
+       type_initialization_hash = NULL;
 #endif
        DeleteCriticalSection (&ldstr_section);
+       g_hash_table_destroy (blocked_thread_hash);
+       blocked_thread_hash = NULL;
+
+       free_main_args ();
 }
 
 /**
@@ -267,7 +288,9 @@ mono_runtime_class_init_full (MonoVTable *vtable, gboolean raise_exception)
                        MonoVTable *module_vtable = mono_class_vtable_full (vtable->domain, module_klass, raise_exception);
                        if (!module_vtable)
                                return NULL;
-                       mono_runtime_class_init (module_vtable);
+                       exc = mono_runtime_class_init_full (module_vtable, raise_exception);
+                       if (exc)
+                               return exc;
                }
        }
        method = mono_class_get_cctor (klass);
@@ -394,6 +417,7 @@ mono_runtime_class_init_full (MonoVTable *vtable, gboolean raise_exception)
                        g_hash_table_remove (type_initialization_hash, vtable);
                        g_free (lock);
                }
+               mono_memory_barrier ();
                if (!vtable->init_failed)
                        vtable->initialized = 1;
                mono_type_initialization_unlock ();
@@ -466,7 +490,7 @@ default_remoting_trampoline (MonoDomain *domain, MonoMethod *method, MonoRemotin
 }
 
 static gpointer
-default_delegate_trampoline (MonoClass *klass)
+default_delegate_trampoline (MonoDomain *domain, MonoClass *klass)
 {
        g_assert_not_reached ();
        return NULL;
@@ -563,7 +587,7 @@ mono_runtime_create_jump_trampoline (MonoDomain *domain, MonoMethod *method, gbo
 gpointer
 mono_runtime_create_delegate_trampoline (MonoClass *klass)
 {
-       return arch_create_delegate_trampoline (klass);
+       return arch_create_delegate_trampoline (mono_domain_get (), klass);
 }
 
 static MonoFreeMethodFunc default_mono_free_method = NULL;
@@ -633,6 +657,15 @@ compute_class_bitmap (MonoClass *class, gsize *bitmap, int size, int offset, int
                size = max_size;
        }
 
+#ifdef HAVE_SGEN_GC
+       /*An Ephemeron cannot be marked by sgen*/
+       if (!static_fields && class->image == mono_defaults.corlib && !strcmp ("Ephemeron", class->name)) {
+               *max_set = 0;
+               memset (bitmap, 0, size / 8);
+               return bitmap;
+       }
+#endif
+
        for (p = class; p != NULL; p = p->parent) {
                gpointer iter = NULL;
                while ((field = mono_class_get_fields (p, &iter))) {
@@ -725,6 +758,17 @@ compute_class_bitmap (MonoClass *class, gsize *bitmap, int size, int offset, int
        return bitmap;
 }
 
+/**
+ * mono_class_compute_bitmap:
+ *
+ * Mono internal function to compute a bitmap of reference fields in a class.
+ */
+gsize*
+mono_class_compute_bitmap (MonoClass *class, gsize *bitmap, int size, int offset, int *max_set, gboolean static_fields)
+{
+       return compute_class_bitmap (class, bitmap, size, offset, max_set, static_fields);
+}
+
 #if 0
 /* 
  * similar to the above, but sets the bits in the bitmap for any non-ref field
@@ -924,13 +968,13 @@ mono_class_compute_gc_descriptor (MonoClass *class)
                mono_class_compute_gc_descriptor (class->element_class);
                if (!class->element_class->valuetype) {
                        gsize abm = 1;
-                       class->gc_descr = mono_gc_make_descr_for_array (TRUE, &abm, 1, sizeof (gpointer));
+                       class->gc_descr = mono_gc_make_descr_for_array (class->byval_arg.type == MONO_TYPE_SZARRAY, &abm, 1, sizeof (gpointer));
                        /*printf ("new array descriptor: 0x%x for %s.%s\n", class->gc_descr,
                                class->name_space, class->name);*/
                } else {
                        /* remove the object header */
                        bitmap = compute_class_bitmap (class->element_class, default_bitmap, sizeof (default_bitmap) * 8, - (int)(sizeof (MonoObject) / sizeof (gpointer)), &max_set, FALSE);
-                       class->gc_descr = mono_gc_make_descr_for_array (TRUE, bitmap, mono_array_element_size (class) / sizeof (gpointer), mono_array_element_size (class));
+                       class->gc_descr = mono_gc_make_descr_for_array (class->byval_arg.type == MONO_TYPE_SZARRAY, bitmap, mono_array_element_size (class) / sizeof (gpointer), mono_array_element_size (class));
                        /*printf ("new vt array descriptor: 0x%x for %s.%s\n", class->gc_descr,
                                class->name_space, class->name);*/
                        if (bitmap != default_bitmap)
@@ -985,14 +1029,6 @@ field_is_special_static (MonoClass *fklass, MonoClassField *field)
        return SPECIAL_STATIC_NONE;
 }
 
-static gpointer imt_trampoline = NULL;
-
-void
-mono_install_imt_trampoline (gpointer tramp_code)
-{
-       imt_trampoline = tramp_code;
-}
-
 #define rot(x,k) (((x)<<(k)) | ((x)>>(32-(k))))
 #define mix(a,b,c) { \
        a -= c;  a ^= rot(c, 4);  c += b; \
@@ -1346,7 +1382,7 @@ build_imt_slots (MonoClass *klass, MonoVTable *vt, MonoDomain *domain, gpointer*
                                 * The IMT thunk might be called with an instance of one of the 
                                 * generic virtual methods, so has to fallback to the IMT trampoline.
                                 */
-                               imt [i] = initialize_imt_slot (vt, domain, imt_builder [i], imt_trampoline);
+                               imt [i] = initialize_imt_slot (vt, domain, imt_builder [i], callbacks.get_imt_trampoline ? callbacks.get_imt_trampoline (i) : NULL);
                        } else {
                                imt [i] = initialize_imt_slot (vt, domain, imt_builder [i], NULL);
                        }
@@ -1414,7 +1450,7 @@ mono_vtable_build_imt_slot (MonoVTable* vtable, int imt_slot)
        mono_loader_lock (); /*FIXME build_imt_slots requires the loader lock.*/
        mono_domain_lock (vtable->domain);
        /* we change the slot only if it wasn't changed from the generic imt trampoline already */
-       if (imt [imt_slot] == imt_trampoline)
+       if (imt [imt_slot] == callbacks.get_imt_trampoline (imt_slot))
                build_imt_slots (vtable->klass, vtable, vtable->domain, imt, NULL, imt_slot);
        mono_domain_unlock (vtable->domain);
        mono_loader_unlock ();
@@ -1518,6 +1554,12 @@ mono_method_alloc_generic_virtual_thunk (MonoDomain *domain, int size)
        p = mono_domain_code_reserve (domain, size);
        *p = size;
 
+       mono_domain_lock (domain);
+       if (!domain->generic_virtual_thunks)
+               domain->generic_virtual_thunks = g_hash_table_new (NULL, NULL);
+       g_hash_table_insert (domain->generic_virtual_thunks, p, p);
+       mono_domain_unlock (domain);
+
        return p + 1;
 }
 
@@ -1529,7 +1571,18 @@ invalidate_generic_virtual_thunk (MonoDomain *domain, gpointer code)
 {
        guint32 *p = code;
        MonoThunkFreeList *l = (MonoThunkFreeList*)(p - 1);
+       gboolean found = FALSE;
 
+       mono_domain_lock (domain);
+       if (!domain->generic_virtual_thunks)
+               domain->generic_virtual_thunks = g_hash_table_new (NULL, NULL);
+       if (g_hash_table_lookup (domain->generic_virtual_thunks, l))
+               found = TRUE;
+       mono_domain_unlock (domain);
+
+       if (!found)
+               /* Not allocated by mono_method_alloc_generic_virtual_thunk (), i.e. AOT */
+               return;
        init_thunk_free_lists (domain);
 
        while (domain->thunk_free_lists [0] && domain->thunk_free_lists [0]->length >= MAX_WAIT_LENGTH) {
@@ -1666,12 +1719,19 @@ mono_method_add_generic_virtual_invocation (MonoDomain *domain, MonoVTable *vtab
 
        if (++gvc->count == THUNK_THRESHOLD) {
                gpointer *old_thunk = *vtable_slot;
-               gpointer vtable_trampoline = callbacks.get_vtable_trampoline ? callbacks.get_vtable_trampoline ((gpointer*)vtable_slot - (gpointer*)vtable) : NULL;
+               gpointer vtable_trampoline = NULL;
+               gpointer imt_trampoline = NULL;
+
+               if ((gpointer)vtable_slot < (gpointer)vtable) {
+                       int displacement = (gpointer*)vtable_slot - (gpointer*)vtable;
+                       int imt_slot = MONO_IMT_SIZE + displacement;
 
-               if ((gpointer)vtable_slot < (gpointer)vtable)
                        /* Force the rebuild of the thunk at the next call */
+                       imt_trampoline = callbacks.get_imt_trampoline (imt_slot);
                        *vtable_slot = imt_trampoline;
-               else {
+               } else {
+                       vtable_trampoline = callbacks.get_vtable_trampoline ? callbacks.get_vtable_trampoline ((gpointer*)vtable_slot - (gpointer*)vtable->vtable) : NULL;
+
                        entries = get_generic_virtual_entries (domain, vtable_slot);
 
                        sorted = imt_sort_slot_entries (entries);
@@ -1690,8 +1750,12 @@ mono_method_add_generic_virtual_invocation (MonoDomain *domain, MonoVTable *vtab
                        g_ptr_array_free (sorted, TRUE);
                }
 
+#ifndef __native_client__
+               /* We don't re-use any thunks as there is a lot of overhead */
+               /* to deleting and re-using code in Native Client.          */
                if (old_thunk != vtable_trampoline && old_thunk != imt_trampoline)
                        invalidate_generic_virtual_thunk (domain, old_thunk);
+#endif
        }
 
        mono_domain_unlock (domain);
@@ -1771,8 +1835,9 @@ mono_class_create_runtime_vtable (MonoDomain *domain, MonoClass *class, gboolean
        MonoClassRuntimeInfo *runtime_info, *old_info;
        MonoClassField *field;
        char *t;
-       int i;
+       int i, vtable_slots;
        int imt_table_bytes = 0;
+       int gc_bits;
        guint32 vtable_size, class_size;
        guint32 cindex;
        gpointer iter;
@@ -1825,6 +1890,12 @@ mono_class_create_runtime_vtable (MonoDomain *domain, MonoClass *class, gboolean
        if (!class->vtable_size)
                mono_class_setup_vtable (class);
 
+       if (class->generic_class && !class->vtable)
+               mono_class_check_vtable_constraints (class, NULL);
+
+       /* Initialize klass->has_finalize */
+       mono_class_has_finalizer (class);
+
        if (class->exception_type) {
                mono_domain_unlock (domain);
                mono_loader_unlock ();
@@ -1833,8 +1904,14 @@ mono_class_create_runtime_vtable (MonoDomain *domain, MonoClass *class, gboolean
                return NULL;
        }
 
+       vtable_slots = class->vtable_size;
+       /* we add an additional vtable slot to store the pointer to static field data only when needed */
+       class_size = mono_class_data_size (class);
+       if (class_size)
+               vtable_slots++;
+
        if (ARCH_USE_IMT) {
-               vtable_size = MONO_SIZEOF_VTABLE + class->vtable_size * sizeof (gpointer);
+               vtable_size = MONO_SIZEOF_VTABLE + vtable_slots * sizeof (gpointer);
                if (class->interface_offsets_count) {
                        imt_table_bytes = sizeof (gpointer) * (MONO_IMT_SIZE);
                        vtable_size += sizeof (gpointer) * (MONO_IMT_SIZE);
@@ -1843,7 +1920,7 @@ mono_class_create_runtime_vtable (MonoDomain *domain, MonoClass *class, gboolean
                }
        } else {
                vtable_size = sizeof (gpointer) * (class->max_interface_id + 1) +
-                       MONO_SIZEOF_VTABLE + class->vtable_size * sizeof (gpointer);
+                       MONO_SIZEOF_VTABLE + vtable_slots * sizeof (gpointer);
        }
 
        mono_stats.used_class_count++;
@@ -1878,7 +1955,13 @@ mono_class_create_runtime_vtable (MonoDomain *domain, MonoClass *class, gboolean
 #endif
                vt->gc_descr = class->gc_descr;
 
-       if ((class_size = mono_class_data_size (class))) {
+       gc_bits = mono_gc_get_vtable_bits (class);
+       g_assert (!(gc_bits & ~((1 << MONO_VTABLE_AVAILABLE_GC_BITS) - 1)));
+
+       vt->gc_bits = gc_bits;
+
+       if (class_size) {
+               /* we store the static field pointer at the end of the vtable: vt->vtable [class->vtable_size] */
                if (class->has_static_refs) {
                        gpointer statics_gc_descr;
                        int max_set = 0;
@@ -1888,13 +1971,14 @@ mono_class_create_runtime_vtable (MonoDomain *domain, MonoClass *class, gboolean
                        bitmap = compute_class_bitmap (class, default_bitmap, sizeof (default_bitmap) * 8, 0, &max_set, TRUE);
                        /*g_print ("bitmap 0x%x for %s.%s (size: %d)\n", bitmap [0], class->name_space, class->name, class_size);*/
                        statics_gc_descr = mono_gc_make_descr_from_bitmap (bitmap, max_set + 1);
-                       vt->data = mono_gc_alloc_fixed (class_size, statics_gc_descr);
-                       mono_domain_add_class_static_data (domain, class, vt->data, NULL);
+                       vt->vtable [class->vtable_size] = mono_gc_alloc_fixed (class_size, statics_gc_descr);
+                       mono_domain_add_class_static_data (domain, class, vt->vtable [class->vtable_size], NULL);
                        if (bitmap != default_bitmap)
                                g_free (bitmap);
                } else {
-                       vt->data = mono_domain_alloc0 (domain, class_size);
+                       vt->vtable [class->vtable_size] = mono_domain_alloc0 (domain, class_size);
                }
+               vt->has_static_fields = TRUE;
                mono_stats.class_static_data_size += class_size;
        }
 
@@ -1910,11 +1994,29 @@ mono_class_create_runtime_vtable (MonoDomain *domain, MonoClass *class, gboolean
                        if (special_static != SPECIAL_STATIC_NONE) {
                                guint32 size, offset;
                                gint32 align;
+                               gsize default_bitmap [4] = {0};
+                               gsize *bitmap;
+                               int max_set = 0;
+                               MonoClass *fclass;
+                               if (mono_type_is_reference (field->type)) {
+                                       default_bitmap [0] = 1;
+                                       max_set = 1;
+                                       bitmap = default_bitmap;
+                               } else if (mono_type_is_struct (field->type)) {
+                                       fclass = mono_class_from_mono_type (field->type);
+                                       bitmap = compute_class_bitmap (fclass, default_bitmap, sizeof (default_bitmap) * 8, 0, &max_set, FALSE);
+                               } else {
+                                       default_bitmap [0] = 0;
+                                       max_set = 0;
+                                       bitmap = default_bitmap;
+                               }
                                size = mono_type_size (field->type, &align);
-                               offset = mono_alloc_special_static_data (special_static, size, align);
+                               offset = mono_alloc_special_static_data (special_static, size, align, (uintptr_t*)bitmap, max_set);
                                if (!domain->special_static_fields)
                                        domain->special_static_fields = g_hash_table_new (NULL, NULL);
                                g_hash_table_insert (domain->special_static_fields, field, GUINT_TO_POINTER (offset));
+                               if (bitmap != default_bitmap)
+                                       g_free (bitmap);
                                /* 
                                 * This marks the field as special static to speed up the
                                 * checks in mono_field_static_get/set_value ().
@@ -1928,7 +2030,7 @@ mono_class_create_runtime_vtable (MonoDomain *domain, MonoClass *class, gboolean
                        const char *data = mono_field_get_data (field);
 
                        g_assert (!(field->type->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT));
-                       t = (char*)vt->data + field->offset;
+                       t = (char*)mono_vtable_get_static_field_data (vt) + field->offset;
                        /* some fields don't really have rva, they are just zeroed (bss? bug #343083) */
                        if (!data)
                                continue;
@@ -2014,10 +2116,10 @@ mono_class_create_runtime_vtable (MonoDomain *domain, MonoClass *class, gboolean
 
        if (ARCH_USE_IMT && imt_table_bytes) {
                /* Now that the vtable is full, we can actually fill up the IMT */
-               if (imt_trampoline) {
+               if (callbacks.get_imt_trampoline) {
                        /* lazy construction of the IMT entries enabled */
                        for (i = 0; i < MONO_IMT_SIZE; ++i)
-                               interface_offsets [i] = imt_trampoline;
+                               interface_offsets [i] = callbacks.get_imt_trampoline (i);
                } else {
                        build_imt (class, vt, domain, interface_offsets, NULL);
                }
@@ -2037,21 +2139,11 @@ mono_class_create_runtime_vtable (MonoDomain *domain, MonoClass *class, gboolean
 
        /*FIXME check for OOM*/
        vt->type = mono_type_get_object (domain, &class->byval_arg);
-#if HAVE_SGEN_GC
-       if (mono_object_get_class (vt->type) != mono_defaults.monotype_class) {
-               static void *type_desc = NULL;
-
-               if (!type_desc) {
-                       gsize bmap = 1;
-                       type_desc = mono_gc_make_descr_from_bitmap (&bmap, 1);
-               }
-
+       if (mono_object_get_class (vt->type) != mono_defaults.monotype_class)
                /* This is unregistered in
                   unregister_vtable_reflection_type() in
                   domain.c. */
-               mono_gc_register_root ((char*)&vt->type, sizeof (gpointer), type_desc);
-       }
-#endif
+               MONO_GC_REGISTER_ROOT_IF_MOVING(vt->type);
        if (class->contextbound)
                vt->remote = 1;
        else
@@ -2080,6 +2172,12 @@ mono_class_proxy_vtable (MonoDomain *domain, MonoRemoteClass *remote_class, Mono
        GSList *extra_interfaces = NULL;
        MonoClass *class = remote_class->proxy_class;
        gpointer *interface_offsets;
+       uint8_t *bitmap;
+       int bsize;
+       
+#ifdef COMPRESSED_INTERFACE_BITMAP
+       int bcsize;
+#endif
 
        vt = mono_class_vtable (domain, class);
        g_assert (vt); /*FIXME property handle failure*/
@@ -2167,7 +2265,12 @@ mono_class_proxy_vtable (MonoDomain *domain, MonoRemoteClass *remote_class, Mono
        }
 
        pvt->max_interface_id = max_interface_id;
-       pvt->interface_bitmap = mono_domain_alloc0 (domain, sizeof (guint8) * (max_interface_id/8 + 1 ));
+       bsize = sizeof (guint8) * (max_interface_id/8 + 1 );
+#ifdef COMPRESSED_INTERFACE_BITMAP
+       bitmap = g_malloc0 (bsize);
+#else
+       bitmap = mono_domain_alloc0 (domain, bsize);
+#endif
 
        if (! ARCH_USE_IMT) {
                /* initialize interface offsets */
@@ -2179,7 +2282,7 @@ mono_class_proxy_vtable (MonoDomain *domain, MonoRemoteClass *remote_class, Mono
        }
        for (i = 0; i < class->interface_offsets_count; ++i) {
                int interface_id = class->interfaces_packed [i]->interface_id;
-               pvt->interface_bitmap [interface_id >> 3] |= (1 << (interface_id & 7));
+               bitmap [interface_id >> 3] |= (1 << (interface_id & 7));
        }
 
        if (extra_interfaces) {
@@ -2196,7 +2299,7 @@ mono_class_proxy_vtable (MonoDomain *domain, MonoRemoteClass *remote_class, Mono
                        if (! ARCH_USE_IMT) {
                                interface_offsets [max_interface_id - interf->interface_id] = &pvt->vtable [slot];
                        }
-                       pvt->interface_bitmap [interf->interface_id >> 3] |= (1 << (interf->interface_id & 7));
+                       bitmap [interf->interface_id >> 3] |= (1 << (interf->interface_id & 7));
 
                        iter = NULL;
                        j = 0;
@@ -2218,6 +2321,14 @@ mono_class_proxy_vtable (MonoDomain *domain, MonoRemoteClass *remote_class, Mono
                }
        }
 
+#ifdef COMPRESSED_INTERFACE_BITMAP
+       bcsize = mono_compress_bitmap (NULL, bitmap, bsize);
+       pvt->interface_bitmap = mono_domain_alloc0 (domain, bcsize);
+       mono_compress_bitmap (pvt->interface_bitmap, bitmap, bsize);
+       g_free (bitmap);
+#else
+       pvt->interface_bitmap = bitmap;
+#endif
        return pvt;
 }
 
@@ -2240,6 +2351,25 @@ mono_class_field_is_special_static (MonoClassField *field)
        return FALSE;
 }
 
+/**
+ * mono_class_field_get_special_static_type:
+ * @field: The MonoClassField describing the field.
+ *
+ * Returns: SPECIAL_STATIC_THREAD if the field is thread static, SPECIAL_STATIC_CONTEXT if it is context static,
+ * SPECIAL_STATIC_NONE otherwise.
+ */
+guint32
+mono_class_field_get_special_static_type (MonoClassField *field)
+{
+       if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC))
+               return SPECIAL_STATIC_NONE;
+       if (mono_field_is_deleted (field))
+               return SPECIAL_STATIC_NONE;
+       if (!(field->type->attrs & FIELD_ATTRIBUTE_LITERAL))
+               return field_is_special_static (field->parent, field);
+       return SPECIAL_STATIC_NONE;
+}
+
 /**
  * mono_class_has_special_static_fields:
  * 
@@ -2797,7 +2927,7 @@ handle_enum:
                        MonoClass *class = mono_class_from_mono_type (type);
                        int size = mono_class_value_size (class, NULL);
                        if (value == NULL)
-                               memset (dest, 0, size);
+                               mono_gc_bzero (dest, size);
                        else
                                mono_gc_wbarrier_value_copy (dest, value, 1, class);
                }
@@ -2855,19 +2985,31 @@ mono_field_static_set_value (MonoVTable *vt, MonoClassField *field, void *value)
 
        if (field->offset == -1) {
                /* Special static */
-               gpointer addr = g_hash_table_lookup (vt->domain->special_static_fields, field);
+               gpointer addr;
+
+               mono_domain_lock (vt->domain);
+               addr = g_hash_table_lookup (vt->domain->special_static_fields, field);
+               mono_domain_unlock (vt->domain);
                dest = mono_get_special_static_data (GPOINTER_TO_UINT (addr));
        } else {
-               dest = (char*)vt->data + field->offset;
+               dest = (char*)mono_vtable_get_static_field_data (vt) + field->offset;
        }
        set_value (field->type, dest, value, FALSE);
 }
 
-/* Used by the debugger */
+/**
+ * mono_vtable_get_static_field_data:
+ *
+ * Internal use function: return a pointer to the memory holding the static fields
+ * for a class or NULL if there are no static fields.
+ * This is exported only for use by the debugger.
+ */
 void *
 mono_vtable_get_static_field_data (MonoVTable *vt)
 {
-       return vt->data;
+       if (!vt->has_static_fields)
+               return NULL;
+       return vt->vtable [vt->klass->vtable_size];
 }
 
 static guint8*
@@ -2878,10 +3020,14 @@ mono_field_get_addr (MonoObject *obj, MonoVTable *vt, MonoClassField *field)
        if (field->type->attrs & FIELD_ATTRIBUTE_STATIC) {
                if (field->offset == -1) {
                        /* Special static */
-                       gpointer addr = g_hash_table_lookup (vt->domain->special_static_fields, field);
+                       gpointer addr;
+
+                       mono_domain_lock (vt->domain);
+                       addr = g_hash_table_lookup (vt->domain->special_static_fields, field);
+                       mono_domain_unlock (vt->domain);
                        src = mono_get_special_static_data (GPOINTER_TO_UINT (addr));
                } else {
-                       src = (guint8*)vt->data + field->offset;
+                       src = (guint8*)mono_vtable_get_static_field_data (vt) + field->offset;
                }
        } else {
                src = (guint8*)obj + field->offset;
@@ -2912,6 +3058,8 @@ mono_field_get_value (MonoObject *obj, MonoClassField *field, void *value)
 {
        void *src;
 
+       g_assert (obj);
+
        g_return_if_fail (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC));
 
        src = (char*)obj + field->offset;
@@ -2937,8 +3085,15 @@ mono_field_get_value_object (MonoDomain *domain, MonoClassField *field, MonoObje
        gchar *v;
        gboolean is_static = FALSE;
        gboolean is_ref = FALSE;
+       gboolean is_literal = FALSE;
+       gboolean is_ptr = FALSE;
+       MonoError error;
+       MonoType *type = mono_field_get_type_checked (field, &error);
+
+       if (!mono_error_ok (&error))
+               mono_error_raise_exception (&error);
 
-       switch (field->type->type) {
+       switch (type->type) {
        case MONO_TYPE_STRING:
        case MONO_TYPE_OBJECT:
        case MONO_TYPE_CLASS:
@@ -2961,32 +3116,46 @@ mono_field_get_value_object (MonoDomain *domain, MonoClassField *field, MonoObje
        case MONO_TYPE_I8:
        case MONO_TYPE_R8:
        case MONO_TYPE_VALUETYPE:
-               is_ref = field->type->byref;
+               is_ref = type->byref;
                break;
        case MONO_TYPE_GENERICINST:
-               is_ref = !field->type->data.generic_class->container_class->valuetype;
+               is_ref = !mono_type_generic_inst_is_valuetype (type);
+               break;
+       case MONO_TYPE_PTR:
+               is_ptr = TRUE;
                break;
        default:
                g_error ("type 0x%x not handled in "
-                        "mono_field_get_value_object", field->type->type);
+                        "mono_field_get_value_object", type->type);
                return NULL;
        }
 
-       if (field->type->attrs & FIELD_ATTRIBUTE_STATIC) {
+       if (type->attrs & FIELD_ATTRIBUTE_LITERAL)
+               is_literal = TRUE;
+
+       if (type->attrs & FIELD_ATTRIBUTE_STATIC) {
                is_static = TRUE;
-               vtable = mono_class_vtable (domain, field->parent);
-               if (!vtable) {
-                       char *name = mono_type_get_full_name (field->parent);
-                       g_warning ("Could not retrieve the vtable for type %s in mono_field_get_value_object", name);
-                       g_free (name);
-                       return NULL;
+
+               if (!is_literal) {
+                       vtable = mono_class_vtable (domain, field->parent);
+                       if (!vtable) {
+                               char *name = mono_type_get_full_name (field->parent);
+                               /*FIXME extend this to use the MonoError api*/
+                               g_warning ("Could not retrieve the vtable for type %s in mono_field_get_value_object", name);
+                               g_free (name);
+                               return NULL;
+                       }
+                       if (!vtable->initialized)
+                               mono_runtime_class_init (vtable);
                }
-               if (!vtable->initialized)
-                       mono_runtime_class_init (vtable);
+       } else {
+               g_assert (obj);
        }
        
        if (is_ref) {
-               if (is_static) {
+               if (is_literal) {
+                       get_default_field_value (domain, field, &o);
+               } else if (is_static) {
                        mono_field_static_get_value (vtable, field, &o);
                } else {
                        mono_field_get_value (obj, field, &o);
@@ -2994,15 +3163,46 @@ mono_field_get_value_object (MonoDomain *domain, MonoClassField *field, MonoObje
                return o;
        }
 
+       if (is_ptr) {
+               static MonoMethod *m;
+               gpointer args [2];
+               gpointer *ptr;
+               gpointer v;
+
+               if (!m) {
+                       MonoClass *ptr_klass = mono_class_from_name_cached (mono_defaults.corlib, "System.Reflection", "Pointer");
+                       m = mono_class_get_method_from_name_flags (ptr_klass, "Box", 2, METHOD_ATTRIBUTE_STATIC);
+                       g_assert (m);
+               }
+
+               v = &ptr;
+               if (is_literal) {
+                       get_default_field_value (domain, field, v);
+               } else if (is_static) {
+                       mono_field_static_get_value (vtable, field, v);
+               } else {
+                       mono_field_get_value (obj, field, v);
+               }
+
+               /* MONO_TYPE_PTR is passed by value to runtime_invoke () */
+               args [0] = *ptr;
+               args [1] = mono_type_get_object (mono_domain_get (), type);
+
+               return mono_runtime_invoke (m, NULL, args, NULL);
+       }
+
        /* boxed value type */
-       klass = mono_class_from_mono_type (field->type);
+       klass = mono_class_from_mono_type (type);
 
        if (mono_class_is_nullable (klass))
                return mono_nullable_box (mono_field_get_addr (obj, vtable, field), klass);
 
        o = mono_object_new (domain, klass);
        v = ((gchar *) o) + sizeof (MonoObject);
-       if (is_static) {
+
+       if (is_literal) {
+               get_default_field_value (domain, field, v);
+       } else if (is_static) {
                mono_field_static_get_value (vtable, field, v);
        } else {
                mono_field_get_value (obj, field, v);
@@ -3066,6 +3266,28 @@ get_default_field_value (MonoDomain* domain, MonoClassField *field, void *value)
        mono_get_constant_value_from_blob (domain, def_type, data, value);
 }
 
+void
+mono_field_static_get_value_for_thread (MonoInternalThread *thread, MonoVTable *vt, MonoClassField *field, void *value)
+{
+       void *src;
+
+       g_return_if_fail (field->type->attrs & FIELD_ATTRIBUTE_STATIC);
+       
+       if (field->type->attrs & FIELD_ATTRIBUTE_LITERAL) {
+               get_default_field_value (vt->domain, field, value);
+               return;
+       }
+
+       if (field->offset == -1) {
+               /* Special static */
+               gpointer addr = g_hash_table_lookup (vt->domain->special_static_fields, field);
+               src = mono_get_special_static_data_for_thread (thread, GPOINTER_TO_UINT (addr));
+       } else {
+               src = (char*)mono_vtable_get_static_field_data (vt) + field->offset;
+       }
+       set_value (field->type, value, src, TRUE);
+}
+
 /**
  * mono_field_static_get_value:
  * @vt: vtable to the object
@@ -3085,23 +3307,7 @@ get_default_field_value (MonoDomain* domain, MonoClassField *field, void *value)
 void
 mono_field_static_get_value (MonoVTable *vt, MonoClassField *field, void *value)
 {
-       void *src;
-
-       g_return_if_fail (field->type->attrs & FIELD_ATTRIBUTE_STATIC);
-       
-       if (field->type->attrs & FIELD_ATTRIBUTE_LITERAL) {
-               get_default_field_value (vt->domain, field, value);
-               return;
-       }
-
-       if (field->offset == -1) {
-               /* Special static */
-               gpointer addr = g_hash_table_lookup (vt->domain->special_static_fields, field);
-               src = mono_get_special_static_data (GPOINTER_TO_UINT (addr));
-       } else {
-               src = (char*)vt->data + field->offset;
-       }
-       set_value (field->type, value, src, TRUE);
+       return mono_field_static_get_value_for_thread (mono_thread_internal_current (), vt, field, value);
 }
 
 /**
@@ -3175,9 +3381,9 @@ mono_nullable_init (guint8 *buf, MonoObject *value, MonoClass *klass)
                if (param_class->has_references)
                        mono_gc_wbarrier_value_copy (buf + klass->fields [0].offset - sizeof (MonoObject), mono_object_unbox (value), 1, param_class);
                else
-                       memcpy (buf + klass->fields [0].offset - sizeof (MonoObject), mono_object_unbox (value), mono_class_value_size (param_class, NULL));
+                       mono_gc_memmove (buf + klass->fields [0].offset - sizeof (MonoObject), mono_object_unbox (value), mono_class_value_size (param_class, NULL));
        } else {
-               memset (buf + klass->fields [0].offset - sizeof (MonoObject), 0, mono_class_value_size (param_class, NULL));
+               mono_gc_bzero (buf + klass->fields [0].offset - sizeof (MonoObject), mono_class_value_size (param_class, NULL));
        }
 }
 
@@ -3202,7 +3408,7 @@ mono_nullable_box (guint8 *buf, MonoClass *klass)
                if (param_class->has_references)
                        mono_gc_wbarrier_value_copy (mono_object_unbox (o), buf + klass->fields [0].offset - sizeof (MonoObject), 1, param_class);
                else
-                       memcpy (mono_object_unbox (o), buf + klass->fields [0].offset - sizeof (MonoObject), mono_class_value_size (param_class, NULL));
+                       mono_gc_memmove (mono_object_unbox (o), buf + klass->fields [0].offset - sizeof (MonoObject), mono_class_value_size (param_class, NULL));
                return o;
        }
        else
@@ -3213,7 +3419,7 @@ mono_nullable_box (guint8 *buf, MonoClass *klass)
  * mono_get_delegate_invoke:
  * @klass: The delegate class
  *
- * Returns: the MonoMethod for the "Invoke" method in the delegate klass
+ * Returns: the MonoMethod for the "Invoke" method in the delegate klass or NULL if @klass is a broken delegate type
  */
 MonoMethod *
 mono_get_delegate_invoke (MonoClass *klass)
@@ -3225,8 +3431,6 @@ mono_get_delegate_invoke (MonoClass *klass)
        if (klass->exception_type)
                return NULL;
        im = mono_class_get_method_from_name (klass, "Invoke", -1);
-       g_assert (im);
-
        return im;
 }
 
@@ -3281,26 +3485,13 @@ mono_runtime_get_main_args (void)
 }
 
 static void
-fire_process_exit_event (void)
+free_main_args (void)
 {
-       MonoClassField *field;
-       MonoDomain *domain = mono_domain_get ();
-       gpointer pa [2];
-       MonoObject *delegate, *exc;
-       
-       field = mono_class_get_field_from_name (mono_defaults.appdomain_class, "ProcessExit");
-       g_assert (field);
-
-       if (domain != mono_get_root_domain ())
-               return;
-
-       delegate = *(MonoObject **)(((char *)domain->domain) + field->offset); 
-       if (delegate == NULL)
-               return;
+       int i;
 
-       pa [0] = domain;
-       pa [1] = NULL;
-       mono_runtime_delegate_invoke (delegate, pa, &exc);
+       for (i = 0; i < num_main_args; ++i)
+               g_free (main_args [i]);
+       g_free (main_args);
 }
 
 /**
@@ -3324,7 +3515,7 @@ mono_runtime_run_main (MonoMethod *method, int argc, char* argv[],
        MonoArray *args = NULL;
        MonoDomain *domain = mono_domain_get ();
        gchar *utf8_fullpath;
-       int result;
+       MonoMethodSignature *sig;
 
        g_assert (method != NULL);
        
@@ -3379,7 +3570,14 @@ mono_runtime_run_main (MonoMethod *method, int argc, char* argv[],
        }
        argc--;
        argv++;
-       if (mono_method_signature (method)->param_count) {
+
+       sig = mono_method_signature (method);
+       if (!sig) {
+               g_print ("Unable to load Main method.\n");
+               exit (-1);
+       }
+
+       if (sig->param_count) {
                args = (MonoArray*)mono_array_new (domain, mono_defaults.string_class, argc);
                for (i = 0; i < argc; ++i) {
                        /* The encodings should all work, given that
@@ -3397,9 +3595,7 @@ mono_runtime_run_main (MonoMethod *method, int argc, char* argv[],
        
        mono_assembly_set_main (method->klass->image->assembly);
 
-       result = mono_runtime_exec_main (method, args, exc);
-       fire_process_exit_event ();
-       return result;
+       return mono_runtime_exec_main (method, args, exc);
 }
 
 static MonoObject*
@@ -3667,9 +3863,9 @@ mono_unhandled_exception (MonoObject *exc)
                }
 
                /* set exitcode only if we will abort the process */
-               if (abort_process)
-                       mono_environment_exitcode_set (1);
                if ((current_appdomain_delegate == NULL) && (root_appdomain_delegate == NULL)) {
+                       if (abort_process)
+                               mono_environment_exitcode_set (1);
                        mono_print_unhandled_exception (exc);
                } else {
                        if (root_appdomain_delegate) {
@@ -3682,7 +3878,12 @@ mono_unhandled_exception (MonoObject *exc)
        }
 }
 
-/*
+/**
+ * mono_runtime_exec_managed_code:
+ * @domain: Application domain
+ * @main_func: function to invoke from the execution thread
+ * @main_args: parameter to the main_func
+ *
  * Launch a new thread to execute a function
  *
  * main_func is called back from the thread with main_args as the
@@ -3950,6 +4151,7 @@ mono_runtime_invoke_array (MonoMethod *method, void *obj, MonoArray *params,
 
                if (!obj) {
                        obj = mono_object_new (mono_domain_get (), method->klass);
+                       g_assert (obj); /*maybe we should raise a TLE instead?*/
                        if (mono_object_class(obj) == mono_defaults.transparent_proxy_class) {
                                method = mono_marshal_get_remoting_invoke (method->slot == -1 ? method : method->klass->vtable [method->slot]);
                        }
@@ -4090,6 +4292,29 @@ mono_object_new (MonoDomain *domain, MonoClass *klass)
        return mono_object_new_specific (vtable);
 }
 
+/**
+ * mono_object_new_pinned:
+ *
+ *   Same as mono_object_new, but the returned object will be pinned.
+ * For SGEN, these objects will only be freed at appdomain unload.
+ */
+MonoObject *
+mono_object_new_pinned (MonoDomain *domain, MonoClass *klass)
+{
+       MonoVTable *vtable;
+
+       MONO_ARCH_SAVE_REGS;
+       vtable = mono_class_vtable (domain, klass);
+       if (!vtable)
+               return NULL;
+
+#ifdef HAVE_SGEN_GC
+       return mono_gc_alloc_pinned_obj (vtable, mono_class_instance_size (klass));
+#else
+       return mono_object_new_specific (vtable);
+#endif
+}
+
 /**
  * mono_object_new_specific:
  * @vtable: the vtable of the object that we want to create
@@ -4209,7 +4434,7 @@ mono_class_get_allocation_ftn (MonoVTable *vtable, gboolean for_box, gboolean *p
        if (!(mono_profiler_get_events () & MONO_PROFILE_ALLOCATIONS))
                profile_allocs = FALSE;
 
-       if (vtable->klass->has_finalize || vtable->klass->marshalbyref || (mono_profiler_get_events () & MONO_PROFILE_ALLOCATIONS))
+       if (mono_class_has_finalizer (vtable->klass) || vtable->klass->marshalbyref || (mono_profiler_get_events () & MONO_PROFILE_ALLOCATIONS))
                return mono_object_new_specific;
 
        if (!vtable->klass->has_references) {
@@ -4271,6 +4496,9 @@ mono_object_clone (MonoObject *obj)
        MonoObject *o;
        int size = obj->vtable->klass->instance_size;
 
+       if (obj->vtable->klass->rank)
+               return (MonoObject*)mono_array_clone ((MonoArray*)obj);
+
        o = mono_object_allocate (size, obj->vtable);
 
        if (obj->vtable->klass->has_references) {
@@ -4278,7 +4506,7 @@ mono_object_clone (MonoObject *obj)
        } else {
                int size = obj->vtable->klass->instance_size;
                /* do not copy the sync state */
-               memcpy ((char*)o + sizeof (MonoObject), (char*)obj + sizeof (MonoObject), size - sizeof (MonoObject));
+               mono_gc_memmove ((char*)o + sizeof (MonoObject), (char*)obj + sizeof (MonoObject), size - sizeof (MonoObject));
        }
        if (G_UNLIKELY (profile_allocs))
                mono_profiler_allocation (o, obj->vtable->klass);
@@ -4298,7 +4526,7 @@ mono_object_clone (MonoObject *obj)
 void
 mono_array_full_copy (MonoArray *src, MonoArray *dest)
 {
-       mono_array_size_t size;
+       uintptr_t size;
        MonoClass *klass = src->obj.vtable->klass;
 
        MONO_ARCH_SAVE_REGS;
@@ -4313,12 +4541,12 @@ mono_array_full_copy (MonoArray *src, MonoArray *dest)
                if (klass->element_class->has_references)
                        mono_value_copy_array (dest, 0, mono_array_addr_with_size (src, 0, 0), mono_array_length (src));
                else
-                       memcpy (&dest->vector, &src->vector, size);
+                       mono_gc_memmove (&dest->vector, &src->vector, size);
        } else {
                mono_array_memcpy_refs (dest, 0, src, 0, mono_array_length (src));
        }
 #else
-       memcpy (&dest->vector, &src->vector, size);
+       mono_gc_memmove (&dest->vector, &src->vector, size);
 #endif
 }
 
@@ -4334,8 +4562,8 @@ MonoArray*
 mono_array_clone_in_domain (MonoDomain *domain, MonoArray *array)
 {
        MonoArray *o;
-       mono_array_size_t size, i;
-       mono_array_size_t *sizes;
+       uintptr_t size, i;
+       uintptr_t *sizes;
        MonoClass *klass = array->obj.vtable->klass;
 
        MONO_ARCH_SAVE_REGS;
@@ -4350,35 +4578,35 @@ mono_array_clone_in_domain (MonoDomain *domain, MonoArray *array)
                        if (klass->element_class->has_references)
                                mono_value_copy_array (o, 0, mono_array_addr_with_size (array, 0, 0), mono_array_length (array));
                        else
-                               memcpy (&o->vector, &array->vector, size);
+                               mono_gc_memmove (&o->vector, &array->vector, size);
                } else {
                        mono_array_memcpy_refs (o, 0, array, 0, mono_array_length (array));
                }
 #else
-               memcpy (&o->vector, &array->vector, size);
+               mono_gc_memmove (&o->vector, &array->vector, size);
 #endif
                return o;
        }
        
-       sizes = alloca (klass->rank * sizeof(mono_array_size_t) * 2);
+       sizes = alloca (klass->rank * sizeof(intptr_t) * 2);
        size = mono_array_element_size (klass);
        for (i = 0; i < klass->rank; ++i) {
                sizes [i] = array->bounds [i].length;
                size *= array->bounds [i].length;
                sizes [i + klass->rank] = array->bounds [i].lower_bound;
        }
-       o = mono_array_new_full (domain, klass, sizes, sizes + klass->rank);
+       o = mono_array_new_full (domain, klass, sizes, (intptr_t*)sizes + klass->rank);
 #ifdef HAVE_SGEN_GC
        if (klass->element_class->valuetype) {
                if (klass->element_class->has_references)
                        mono_value_copy_array (o, 0, mono_array_addr_with_size (array, 0, 0), mono_array_length (array));
                else
-                       memcpy (&o->vector, &array->vector, size);
+                       mono_gc_memmove (&o->vector, &array->vector, size);
        } else {
                mono_array_memcpy_refs (o, 0, array, 0, mono_array_length (array));
        }
 #else
-       memcpy (&o->vector, &array->vector, size);
+       mono_gc_memmove (&o->vector, &array->vector, size);
 #endif
 
        return o;
@@ -4416,9 +4644,9 @@ mono_array_clone (MonoArray *array)
 #endif
 
 gboolean
-mono_array_calc_byte_len (MonoClass *class, mono_array_size_t len, mono_array_size_t *res)
+mono_array_calc_byte_len (MonoClass *class, uintptr_t len, uintptr_t *res)
 {
-       mono_array_size_t byte_len;
+       uintptr_t byte_len;
 
        byte_len = mono_array_element_size (class);
        if (CHECK_MUL_OVERFLOW_UN (byte_len, len))
@@ -4444,9 +4672,9 @@ mono_array_calc_byte_len (MonoClass *class, mono_array_size_t len, mono_array_si
  * lower bounds and type.
  */
 MonoArray*
-mono_array_new_full (MonoDomain *domain, MonoClass *array_class, mono_array_size_t *lengths, mono_array_size_t *lower_bounds)
+mono_array_new_full (MonoDomain *domain, MonoClass *array_class, uintptr_t *lengths, intptr_t *lower_bounds)
 {
-       mono_array_size_t byte_len, len, bounds_size;
+       uintptr_t byte_len, len, bounds_size;
        MonoObject *o;
        MonoArray *array;
        MonoArrayBounds *bounds;
@@ -4546,7 +4774,7 @@ mono_array_new_full (MonoDomain *domain, MonoClass *array_class, mono_array_size
  * This routine creates a new szarray with @n elements of type @eclass.
  */
 MonoArray *
-mono_array_new (MonoDomain *domain, MonoClass *eclass, mono_array_size_t n)
+mono_array_new (MonoDomain *domain, MonoClass *eclass, uintptr_t n)
 {
        MonoClass *ac;
 
@@ -4567,11 +4795,11 @@ mono_array_new (MonoDomain *domain, MonoClass *eclass, mono_array_size_t n)
  * can be sure about the domain it operates in.
  */
 MonoArray *
-mono_array_new_specific (MonoVTable *vtable, mono_array_size_t n)
+mono_array_new_specific (MonoVTable *vtable, uintptr_t n)
 {
        MonoObject *o;
        MonoArray *ao;
-       guint32 byte_len;
+       uintptr_t byte_len;
 
        MONO_ARCH_SAVE_REGS;
 
@@ -4795,7 +5023,7 @@ mono_value_box (MonoDomain *domain, MonoClass *class, gpointer value)
        mono_gc_wbarrier_value_copy ((char *)res + sizeof (MonoObject), value, 1, class);
 #else
 #if NO_UNALIGNED_ACCESS
-       memcpy ((char *)res + sizeof (MonoObject), value, size);
+       mono_gc_memmove ((char *)res + sizeof (MonoObject), value, size);
 #else
        switch (size) {
        case 1:
@@ -4811,7 +5039,7 @@ mono_value_box (MonoDomain *domain, MonoClass *class, gpointer value)
                *(guint64 *)((guint8 *) res + sizeof (MonoObject)) = *(guint64 *) value;
                break;
        default:
-               memcpy ((char *)res + sizeof (MonoObject), value, size);
+               mono_gc_memmove ((char *)res + sizeof (MonoObject), value, size);
        }
 #endif
 #endif
@@ -4963,9 +5191,10 @@ mono_object_isinst_mbyref (MonoObject *obj, MonoClass *klass)
                        return obj;
        } else {
                MonoClass *oklass = vt->klass;
-               if ((oklass == mono_defaults.transparent_proxy_class))
+               if (oklass == mono_defaults.transparent_proxy_class)
                        oklass = ((MonoTransparentProxy *)obj)->remote_class->proxy_class;
-       
+
+               mono_class_setup_supertypes (klass);    
                if ((oklass->idepth >= klass->idepth) && (oklass->supertypes [klass->idepth - 1] == klass))
                        return obj;
        }
@@ -5041,8 +5270,10 @@ mono_string_get_pinned (MonoString *str)
        MonoString *news;
        size = sizeof (MonoString) + 2 * (mono_string_length (str) + 1);
        news = mono_gc_alloc_pinned_obj (((MonoObject*)str)->vtable, size);
-       memcpy (mono_string_chars (news), mono_string_chars (str), mono_string_length (str) * 2);
-       news->length = mono_string_length (str);
+       if (news) {
+               memcpy (mono_string_chars (news), mono_string_chars (str), mono_string_length (str) * 2);
+               news->length = mono_string_length (str);
+       }
        return news;
 }
 
@@ -5066,7 +5297,8 @@ mono_string_is_interned_lookup (MonoString *str, int insert)
        }
        if (insert) {
                str = mono_string_get_pinned (str);
-               mono_g_hash_table_insert (ldstr_table, str, str);
+               if (str)
+                       mono_g_hash_table_insert (ldstr_table, str, str);
                ldstr_unlock ();
                return str;
        } else {
@@ -5175,7 +5407,8 @@ mono_ldstr_metadata_sig (MonoDomain *domain, const char* sig)
        }
 
        o = mono_string_get_pinned (o);
-       mono_g_hash_table_insert (domain->ldstr_table, o, o);
+       if (o)
+               mono_g_hash_table_insert (domain->ldstr_table, o, o);
        ldstr_unlock ();
 
        return o;
@@ -5185,8 +5418,8 @@ mono_ldstr_metadata_sig (MonoDomain *domain, const char* sig)
  * mono_string_to_utf8:
  * @s: a System.String
  *
- * Return the UTF8 representation for @s.
- * the resulting buffer nedds to be freed with g_free().
+ * Returns the UTF8 representation for @s.
+ * The resulting buffer needs to be freed with mono_free().
  *
  * @deprecated Use mono_string_to_utf8_checked to avoid having an exception arbritraly raised.
  */
@@ -5201,6 +5434,15 @@ mono_string_to_utf8 (MonoString *s)
        return result;
 }
 
+/**
+ * mono_string_to_utf8_checked:
+ * @s: a System.String
+ * @error: a MonoError.
+ * 
+ * Converts a MonoString to its UTF8 representation. May fail; check 
+ * @error to determine whether the conversion was successful.
+ * The resulting buffer should be freed with mono_free().
+ */
 char *
 mono_string_to_utf8_checked (MonoString *s, MonoError *error)
 {
@@ -5234,6 +5476,66 @@ mono_string_to_utf8_checked (MonoString *s, MonoError *error)
        return as;
 }
 
+/**
+ * mono_string_to_utf8_ignore:
+ * @s: a MonoString
+ *
+ * Converts a MonoString to its UTF8 representation. Will ignore
+ * invalid surrogate pairs.
+ * The resulting buffer should be freed with mono_free().
+ * 
+ */
+char *
+mono_string_to_utf8_ignore (MonoString *s)
+{
+       long written = 0;
+       char *as;
+
+       if (s == NULL)
+               return NULL;
+
+       if (!s->length)
+               return g_strdup ("");
+
+       as = g_utf16_to_utf8 (mono_string_chars (s), s->length, NULL, &written, NULL);
+
+       /* g_utf16_to_utf8  may not be able to complete the convertion (e.g. NULL values were found, #335488) */
+       if (s->length > written) {
+               /* allocate the total length and copy the part of the string that has been converted */
+               char *as2 = g_malloc0 (s->length);
+               memcpy (as2, as, written);
+               g_free (as);
+               as = as2;
+       }
+
+       return as;
+}
+
+/**
+ * mono_string_to_utf8_image_ignore:
+ * @s: a System.String
+ *
+ * Same as mono_string_to_utf8_ignore, but allocate the string from the image mempool.
+ */
+char *
+mono_string_to_utf8_image_ignore (MonoImage *image, MonoString *s)
+{
+       return mono_string_to_utf8_internal (NULL, image, s, TRUE, NULL);
+}
+
+/**
+ * mono_string_to_utf8_mp_ignore:
+ * @s: a System.String
+ *
+ * Same as mono_string_to_utf8_ignore, but allocate the string from a mempool.
+ */
+char *
+mono_string_to_utf8_mp_ignore (MonoMemPool *mp, MonoString *s)
+{
+       return mono_string_to_utf8_internal (mp, NULL, s, TRUE, NULL);
+}
+
+
 /**
  * mono_string_to_utf16:
  * @s: a MonoString
@@ -5243,7 +5545,7 @@ mono_string_to_utf8_checked (MonoString *s, MonoError *error)
  * This is a temporary helper until our string implementation
  * is reworked to always include the null terminating char.
  */
-gunichar2 *
+mono_unichar2*
 mono_string_to_utf16 (MonoString *s)
 {
        char *as;
@@ -5287,15 +5589,19 @@ mono_string_from_utf16 (gunichar2 *data)
 
 
 static char *
-mono_string_to_utf8_internal (MonoMemPool *mp, MonoImage *image, MonoString *s, MonoError *error)
+mono_string_to_utf8_internal (MonoMemPool *mp, MonoImage *image, MonoString *s, gboolean ignore_error, MonoError *error)
 {
        char *r;
        char *mp_s;
        int len;
 
-       r = mono_string_to_utf8_checked (s, error);
-       if (!mono_error_ok (error))
-               return NULL;
+       if (ignore_error) {
+               r = mono_string_to_utf8_ignore (s);
+       } else {
+               r = mono_string_to_utf8_checked (s, error);
+               if (!mono_error_ok (error))
+                       return NULL;
+       }
 
        if (!mp && !image)
                return r;
@@ -5322,7 +5628,7 @@ mono_string_to_utf8_internal (MonoMemPool *mp, MonoImage *image, MonoString *s,
 char *
 mono_string_to_utf8_image (MonoImage *image, MonoString *s, MonoError *error)
 {
-       return mono_string_to_utf8_internal (NULL, image, s, error);
+       return mono_string_to_utf8_internal (NULL, image, s, FALSE, error);
 }
 
 /**
@@ -5334,30 +5640,22 @@ mono_string_to_utf8_image (MonoImage *image, MonoString *s, MonoError *error)
 char *
 mono_string_to_utf8_mp (MonoMemPool *mp, MonoString *s, MonoError *error)
 {
-       return mono_string_to_utf8_internal (mp, NULL, s, error);
+       return mono_string_to_utf8_internal (mp, NULL, s, FALSE, error);
 }
 
-static void
-default_ex_handler (MonoException *ex)
-{
-       MonoObject *o = (MonoObject*)ex;
-       g_error ("Exception %s.%s raised in C code", o->vtable->klass->name_space, o->vtable->klass->name);
-       exit (1);
-}
 
-static MonoExceptionFunc ex_handler = default_ex_handler;
+static MonoRuntimeExceptionHandlingCallbacks eh_callbacks;
 
-/**
- * mono_install_handler:
- * @func: exception handler
- *
- * This is an internal JIT routine used to install the handler for exceptions
- * being throwh.
- */
 void
-mono_install_handler (MonoExceptionFunc func)
+mono_install_eh_callbacks (MonoRuntimeExceptionHandlingCallbacks *cbs)
 {
-       ex_handler = func? func: default_ex_handler;
+       eh_callbacks = *cbs;
+}
+
+MonoRuntimeExceptionHandlingCallbacks *
+mono_get_eh_callbacks (void)
+{
+       return &eh_callbacks;
 }
 
 /**
@@ -5382,7 +5680,19 @@ mono_raise_exception (MonoException *ex)
                MONO_OBJECT_SETREF (thread, abort_exc, ex);
        }
        
-       ex_handler (ex);
+       eh_callbacks.mono_raise_exception (ex);
+}
+
+void
+mono_raise_exception_with_context (MonoException *ex, MonoContext *ctx) 
+{
+       if (((MonoObject*)ex)->vtable->klass == mono_defaults.threadabortexception_class) {
+               MonoInternalThread *thread = mono_thread_internal_current ();
+               g_assert (ex->object.vtable->domain == mono_domain_get ());
+               MONO_OBJECT_SETREF (thread, abort_exc, ex);
+       }
+       
+       eh_callbacks.mono_raise_exception_with_ctx (ex, ctx);
 }
 
 /**
@@ -5655,6 +5965,29 @@ mono_message_invoke (MonoObject *target, MonoMethodMessage *msg,
        return ret;
 }
 
+/**
+ * mono_object_to_string:
+ * @obj: The object
+ * @exc: Any exception thrown by ToString (). May be NULL.
+ *
+ * Returns: the result of calling ToString () on an object.
+ */
+MonoString *
+mono_object_to_string (MonoObject *obj, MonoObject **exc)
+{
+       static MonoMethod *to_string = NULL;
+       MonoMethod *method;
+
+       g_assert (obj);
+
+       if (!to_string)
+               to_string = mono_class_get_method_from_name_flags (mono_get_object_class (), "ToString", 0, METHOD_ATTRIBUTE_VIRTUAL | METHOD_ATTRIBUTE_PUBLIC);
+
+       method = mono_object_get_virtual_method (obj, to_string);
+
+       return (MonoString *) mono_runtime_invoke (method, obj, NULL, exc);
+}
+
 /**
  * mono_print_unhandled_exception:
  * @exc: The exception
@@ -5664,35 +5997,25 @@ mono_message_invoke (MonoObject *target, MonoMethodMessage *msg,
 void
 mono_print_unhandled_exception (MonoObject *exc)
 {
-       MonoError error;
-       char *message = (char *) "";
-       MonoString *str; 
-       MonoMethod *method;
-       MonoClass *klass;
+       MonoString * str;
+       char *message = (char*)"";
        gboolean free_message = FALSE;
+       MonoError error;
 
-       if (mono_object_isinst (exc, mono_defaults.exception_class)) {
-               klass = exc->vtable->klass;
-               method = NULL;
-               while (klass && method == NULL) {
-                       method = mono_class_get_method_from_name_flags (klass, "ToString", 0, METHOD_ATTRIBUTE_VIRTUAL | METHOD_ATTRIBUTE_PUBLIC);
-                       if (method == NULL)
-                               klass = klass->parent;
-               }
-
-               g_assert (method);
-
-               str = (MonoString *) mono_runtime_invoke (method, exc, NULL, NULL);
+       if (exc == (MonoObject*)mono_object_domain (exc)->out_of_memory_ex) {
+               message = g_strdup ("OutOfMemoryException");
+       } else {
+               str = mono_object_to_string (exc, NULL);
                if (str) {
                        message = mono_string_to_utf8_checked (str, &error);
                        if (!mono_error_ok (&error)) {
                                mono_error_cleanup (&error);
-                               message = (char *)"";
+                               message = (char *) "";
                        } else {
                                free_message = TRUE;
                        }
                }
-       }                               
+       }
 
        /*
         * g_printerr ("\nUnhandled Exception: %s.%s: %s\n", exc->vtable->klass->name_space, 
@@ -5745,7 +6068,7 @@ mono_delegate_ctor_with_method (MonoObject *this, MonoObject *target, gpointer a
                MONO_OBJECT_SETREF (delegate, target, target);
        }
 
-       delegate->invoke_impl = arch_create_delegate_trampoline (delegate->object.vtable->klass);
+       delegate->invoke_impl = arch_create_delegate_trampoline (delegate->object.vtable->domain, delegate->object.vtable->klass);
 }
 
 /**
@@ -5765,7 +6088,11 @@ mono_delegate_ctor (MonoObject *this, MonoObject *target, gpointer addr)
 
        g_assert (addr);
 
-       if ((ji = mono_jit_info_table_find (domain, mono_get_addr_from_ftnptr (addr)))) {
+       ji = mono_jit_info_table_find (domain, mono_get_addr_from_ftnptr (addr));
+       /* Shared code */
+       if (!ji && domain != mono_get_root_domain ())
+               ji = mono_jit_info_table_find (mono_get_root_domain (), mono_get_addr_from_ftnptr (addr));
+       if (ji) {
                method = ji->method;
                g_assert (!method->klass->generic_container);
        }
@@ -5871,10 +6198,10 @@ mono_method_return_message_restore (MonoMethod *method, gpointer *params, MonoAr
                                        if (class->has_references)
                                                mono_gc_wbarrier_value_copy (*((gpointer *)params [i]), arg + sizeof (MonoObject), 1, class);
                                        else
-                                               memcpy (*((gpointer *)params [i]), arg + sizeof (MonoObject), size);
+                                               mono_gc_memmove (*((gpointer *)params [i]), arg + sizeof (MonoObject), size);
                                } else {
                                        size = mono_class_value_size (mono_class_from_mono_type (pt), NULL);
-                                       memset (*((gpointer *)params [i]), 0, size);
+                                       mono_gc_bzero (*((gpointer *)params [i]), size);
                                }
                        }
 
@@ -6144,7 +6471,6 @@ mono_get_addr_from_ftnptr (gpointer descr)
        return callbacks.get_addr_from_ftnptr (descr);
 }      
 
-#if 0
 /**
  * mono_string_chars:
  * @s: a MonoString
@@ -6152,9 +6478,9 @@ mono_get_addr_from_ftnptr (gpointer descr)
  * Returns a pointer to the UCS16 characters stored in the MonoString
  */
 gunichar2 *
-mono_string_chars(MonoString *s)
+mono_string_chars (MonoString *s)
 {
-       /* This method is here only for documentation extraction, this is a macro */
+       return s->chars;
 }
 
 /**
@@ -6166,7 +6492,33 @@ mono_string_chars(MonoString *s)
 int
 mono_string_length (MonoString *s)
 {
-       /* This method is here only for documentation extraction, this is a macro */
+       return s->length;
+}
+
+/**
+ * mono_array_length:
+ * @array: a MonoArray*
+ *
+ * Returns the total number of elements in the array. This works for
+ * both vectors and multidimensional arrays.
+ */
+uintptr_t
+mono_array_length (MonoArray *array)
+{
+       return array->max_length;
+}
+
+/**
+ * mono_array_addr_with_size:
+ * @array: a MonoArray*
+ * @size: size of the array elements
+ * @idx: index into the array
+ *
+ * Returns the address of the @idx element in the array.
+ */
+char*
+mono_array_addr_with_size (MonoArray *array, int size, uintptr_t idx)
+{
+       return ((char*)(array)->vector) + size * idx;
 }
 
-#endif