Merge pull request #4503 from BrzVlad/fix-appdomain-unload
[mono.git] / mono / metadata / object.c
index 422b9a21a27866b418777cc1f748800d3fcc0ac5..41c481d41097c862b4a715f246f4fd922af40c62 100644 (file)
 #include <mono/metadata/assembly.h>
 #include <mono/metadata/marshal.h>
 #include "mono/metadata/debug-helpers.h"
-#include "mono/metadata/marshal.h"
 #include <mono/metadata/threads.h>
 #include <mono/metadata/threads-types.h>
 #include <mono/metadata/environment.h>
 #include "mono/metadata/profiler-private.h"
 #include "mono/metadata/security-manager.h"
-#include "mono/metadata/mono-debug-debugger.h"
-#include <mono/metadata/gc-internals.h>
 #include <mono/metadata/verify-internals.h>
 #include <mono/metadata/reflection-internals.h>
 #include <mono/metadata/w32event.h>
@@ -50,7 +47,7 @@
 #include <mono/utils/mono-threads.h>
 #include <mono/utils/mono-threads-coop.h>
 #include "cominterop.h"
-#include <mono/io-layer/io-layer.h>
+#include <mono/utils/w32api.h>
 
 static void
 get_default_field_value (MonoDomain* domain, MonoClassField *field, void *value, MonoError *error);
@@ -64,15 +61,18 @@ free_main_args (void);
 static char *
 mono_string_to_utf8_internal (MonoMemPool *mp, MonoImage *image, MonoString *s, gboolean ignore_error, MonoError *error);
 
+static void
+array_full_copy_unchecked_size (MonoArray *src, MonoArray *dest, MonoClass *klass, uintptr_t size);
+
 static MonoMethod*
 class_get_virtual_method (MonoClass *klass, MonoMethod *method, gboolean is_proxy, MonoError *error);
 
 /* Class lazy loading functions */
-static GENERATE_GET_CLASS_WITH_CACHE (pointer, System.Reflection, Pointer)
-static GENERATE_GET_CLASS_WITH_CACHE (remoting_services, System.Runtime.Remoting, RemotingServices)
-static GENERATE_GET_CLASS_WITH_CACHE (unhandled_exception_event_args, System, UnhandledExceptionEventArgs)
-static GENERATE_GET_CLASS_WITH_CACHE (sta_thread_attribute, System, STAThreadAttribute)
-static GENERATE_GET_CLASS_WITH_CACHE (activation_services, System.Runtime.Remoting.Activation, ActivationServices)
+static GENERATE_GET_CLASS_WITH_CACHE (pointer, "System.Reflection", "Pointer")
+static GENERATE_GET_CLASS_WITH_CACHE (remoting_services, "System.Runtime.Remoting", "RemotingServices")
+static GENERATE_GET_CLASS_WITH_CACHE (unhandled_exception_event_args, "System", "UnhandledExceptionEventArgs")
+static GENERATE_GET_CLASS_WITH_CACHE (sta_thread_attribute, "System", "STAThreadAttribute")
+static GENERATE_GET_CLASS_WITH_CACHE (activation_services, "System.Runtime.Remoting.Activation", "ActivationServices")
 
 
 #define ldstr_lock() mono_os_mutex_lock (&ldstr_section)
@@ -112,7 +112,7 @@ mono_runtime_object_init_checked (MonoObject *this_obj, MonoError *error)
        MonoMethod *method = NULL;
        MonoClass *klass = this_obj->vtable->klass;
 
-       mono_error_init (error);
+       error_init (error);
        method = mono_class_get_method_from_name (klass, ".ctor", 0);
        if (!method)
                g_error ("Could not lookup zero argument constructor for class %s", mono_type_get_full_name (klass));
@@ -152,7 +152,9 @@ typedef struct
        MonoNativeThreadId initializing_tid;
        guint32 waiting_count;
        gboolean done;
-       MonoCoopMutex initialization_section;
+       MonoCoopMutex mutex;
+       /* condvar used to wait for 'done' becoming TRUE */
+       MonoCoopCond cond;
 } TypeInitializationLock;
 
 /* for locking access to type_initialization_hash and blocked_thread_hash */
@@ -176,13 +178,13 @@ mono_type_init_lock (TypeInitializationLock *lock)
 {
        MONO_REQ_GC_NEUTRAL_MODE;
 
-       mono_coop_mutex_lock (&lock->initialization_section);
+       mono_coop_mutex_lock (&lock->mutex);
 }
 
 static void
 mono_type_init_unlock (TypeInitializationLock *lock)
 {
-       mono_coop_mutex_unlock (&lock->initialization_section);
+       mono_coop_mutex_unlock (&lock->mutex);
 }
 
 /* from vtable to lock */
@@ -314,6 +316,24 @@ mono_runtime_class_init (MonoVTable *vtable)
        mono_error_assert_ok (&error);
 }
 
+/*
+ * Returns TRUE if the lock was freed.
+ * LOCKING: Caller should hold type_initialization_lock.
+ */
+static gboolean
+unref_type_lock (TypeInitializationLock *lock)
+{
+       --lock->waiting_count;
+       if (lock->waiting_count == 0) {
+               mono_coop_mutex_destroy (&lock->mutex);
+               mono_coop_cond_destroy (&lock->cond);
+               g_free (lock);
+               return TRUE;
+       } else {
+               return FALSE;
+       }
+}
+
 /**
  * mono_runtime_class_init_full:
  * @vtable that neeeds to be initialized
@@ -335,9 +355,9 @@ mono_runtime_class_init_full (MonoVTable *vtable, MonoError *error)
        MonoNativeThreadId tid;
        int do_initialization = 0;
        MonoDomain *last_domain = NULL;
-       MonoException * pending_tae = NULL;
+       gboolean pending_tae = FALSE;
 
-       mono_error_init (error);
+       error_init (error);
 
        if (vtable->initialized)
                return TRUE;
@@ -370,6 +390,13 @@ mono_runtime_class_init_full (MonoVTable *vtable, MonoError *error)
 
        tid = mono_native_thread_id_get ();
 
+       /*
+        * Due some preprocessing inside a global lock. If we are the first thread
+        * trying to initialize this class, create a separate lock+cond var, and
+        * acquire it before leaving the global lock. The other threads will wait
+        * on this cond var.
+        */
+
        mono_type_initialization_lock ();
        /* double check... */
        if (vtable->initialized) {
@@ -396,25 +423,24 @@ mono_runtime_class_init_full (MonoVTable *vtable, MonoError *error)
                                return FALSE;
                        }
                }
-               lock = (TypeInitializationLock *)g_malloc (sizeof (TypeInitializationLock));
-               mono_coop_mutex_init_recursive (&lock->initialization_section);
+               lock = (TypeInitializationLock *)g_malloc0 (sizeof (TypeInitializationLock));
+               mono_coop_mutex_init_recursive (&lock->mutex);
+               mono_coop_cond_init (&lock->cond);
                lock->initializing_tid = tid;
                lock->waiting_count = 1;
                lock->done = FALSE;
-               /* grab the vtable lock while this thread still owns type_initialization_section */
-               /* This is why type_initialization_lock needs to enter blocking mode */
-               mono_type_init_lock (lock);
                g_hash_table_insert (type_initialization_hash, vtable, lock);
                do_initialization = 1;
        } else {
                gpointer blocked;
                TypeInitializationLock *pending_lock;
 
-               if (mono_native_thread_id_equals (lock->initializing_tid, tid) || lock->done) {
+               if (mono_native_thread_id_equals (lock->initializing_tid, tid)) {
                        mono_type_initialization_unlock ();
                        return TRUE;
                }
                /* see if the thread doing the initialization is already blocked on this thread */
+               gboolean is_blocked = TRUE;
                blocked = GUINT_TO_POINTER (MONO_NATIVE_THREAD_ID_TO_UINT (lock->initializing_tid));
                while ((pending_lock = (TypeInitializationLock*) g_hash_table_lookup (blocked_thread_hash, blocked))) {
                        if (mono_native_thread_id_equals (pending_lock->initializing_tid, tid)) {
@@ -425,6 +451,7 @@ mono_runtime_class_init_full (MonoVTable *vtable, MonoError *error)
                                        /* the thread doing the initialization is blocked on this thread,
                                           but on a lock that has already been freed. It just hasn't got
                                           time to awake */
+                                       is_blocked = FALSE;
                                        break;
                                }
                        }
@@ -432,13 +459,16 @@ mono_runtime_class_init_full (MonoVTable *vtable, MonoError *error)
                }
                ++lock->waiting_count;
                /* record the fact that we are waiting on the initializing thread */
-               g_hash_table_insert (blocked_thread_hash, GUINT_TO_POINTER (tid), lock);
+               if (is_blocked)
+                       g_hash_table_insert (blocked_thread_hash, GUINT_TO_POINTER (tid), lock);
        }
        mono_type_initialization_unlock ();
 
        if (do_initialization) {
                MonoException *exc = NULL;
 
+               /* We are holding the per-vtable lock, do the actual initialization */
+
                mono_threads_begin_abort_protected_block ();
                mono_runtime_try_invoke (method, NULL, NULL, (MonoObject**) &exc, error);
                mono_threads_end_abort_protected_block ();
@@ -449,7 +479,7 @@ mono_runtime_class_init_full (MonoVTable *vtable, MonoError *error)
                else
                        mono_error_cleanup (error);
 
-               mono_error_init (error);
+               error_init (error);
 
                /* If the initialization failed, mark the class as unusable. */
                /* Avoid infinite loops */
@@ -482,37 +512,44 @@ mono_runtime_class_init_full (MonoVTable *vtable, MonoError *error)
 
                if (last_domain)
                        mono_domain_set (last_domain, TRUE);
+
+               /* Signal to the other threads that we are done */
+               mono_type_init_lock (lock);
                lock->done = TRUE;
+               mono_coop_cond_broadcast (&lock->cond);
                mono_type_init_unlock (lock);
-               if (exc && mono_object_class (exc) == mono_defaults.threadabortexception_class)
-                       pending_tae = exc;
-               //TAEs are blocked around .cctors, they must escape as soon as no cctor is left to run.
-               if (!pending_tae && mono_get_eh_callbacks ()->mono_above_abort_threshold ())
-                       pending_tae = mono_thread_try_resume_interruption ();
+
+               /*
+                * This can happen if the cctor self-aborts. We need to reactivate tae
+                * (next interruption checkpoint will throw it) and make sure we won't
+                * throw tie for the type.
+                */
+               if (exc && mono_object_class (exc) == mono_defaults.threadabortexception_class) {
+                       pending_tae = TRUE;
+                       mono_thread_resume_interruption (FALSE);
+               }
        } else {
                /* this just blocks until the initializing thread is done */
                mono_type_init_lock (lock);
+               while (!lock->done)
+                       mono_coop_cond_wait (&lock->cond, &lock->mutex);
                mono_type_init_unlock (lock);
        }
 
+       /* Do cleanup and setting vtable->initialized inside the global lock again */
        mono_type_initialization_lock ();
-       if (!mono_native_thread_id_equals (lock->initializing_tid, tid))
+       if (!do_initialization)
                g_hash_table_remove (blocked_thread_hash, GUINT_TO_POINTER (tid));
-       --lock->waiting_count;
-       if (lock->waiting_count == 0) {
-               mono_coop_mutex_destroy (&lock->initialization_section);
+       gboolean deleted = unref_type_lock (lock);
+       if (deleted)
                g_hash_table_remove (type_initialization_hash, vtable);
-               g_free (lock);
-       }
-       mono_memory_barrier ();
-       if (!vtable->init_failed)
+       /* Have to set this here since we check it inside the global lock */
+       if (do_initialization && !vtable->init_failed)
                vtable->initialized = 1;
        mono_type_initialization_unlock ();
 
-       //TAE wins over TIE
-       if (pending_tae)
-               mono_error_set_exception_instance (error, pending_tae);
-       else if (vtable->init_failed) {
+       /* If vtable init fails because of TAE, we don't throw TIE, only the TAE */
+       if (vtable->init_failed && !pending_tae) {
                /* Either we were the initializing thread or we waited for the initialization */
                mono_error_set_exception_instance (error, get_type_init_exception_for_vtable (vtable));
                return FALSE;
@@ -535,14 +572,13 @@ gboolean release_type_locks (gpointer key, gpointer value, gpointer user)
                 * mono_runtime_class_init (). In this case, the exception object is not stored,
                 * and get_type_init_exception_for_class () needs to be aware of this.
                 */
+               mono_type_init_lock (lock);
                vtable->init_failed = 1;
+               mono_coop_cond_broadcast (&lock->cond);
                mono_type_init_unlock (lock);
-               --lock->waiting_count;
-               if (lock->waiting_count == 0) {
-                       mono_coop_mutex_destroy (&lock->initialization_section);
-                       g_free (lock);
+               gboolean deleted = unref_type_lock (lock);
+               if (deleted)
                        return TRUE;
-               }
        }
        return FALSE;
 }
@@ -631,7 +667,7 @@ mono_compile_method_checked (MonoMethod *method, MonoError *error)
 
        MONO_REQ_GC_NEUTRAL_MODE
 
-       mono_error_init (error);
+       error_init (error);
 
        g_assert (callbacks.compile_method);
        res = callbacks.compile_method (method, error);
@@ -645,7 +681,7 @@ mono_runtime_create_jump_trampoline (MonoDomain *domain, MonoMethod *method, gbo
 
        MONO_REQ_GC_NEUTRAL_MODE;
 
-       mono_error_init (error);
+       error_init (error);
        res = callbacks.create_jump_trampoline (domain, method, add_sync_wrapper, error);
        return res;
 }
@@ -748,18 +784,11 @@ compute_class_bitmap (MonoClass *klass, gsize *bitmap, int size, int offset, int
 
                        type = mono_type_get_underlying_type (field->type);
                        switch (type->type) {
+                       case MONO_TYPE_U:
                        case MONO_TYPE_I:
                        case MONO_TYPE_PTR:
                        case MONO_TYPE_FNPTR:
                                break;
-                       /* only UIntPtr is allowed to be GC-tracked and only in mscorlib */
-                       case MONO_TYPE_U:
-#ifdef HAVE_SGEN_GC
-                               break;
-#else
-                               if (klass->image != mono_defaults.corlib)
-                                       break;
-#endif
                        case MONO_TYPE_STRING:
                        case MONO_TYPE_SZARRAY:
                        case MONO_TYPE_CLASS:
@@ -1751,7 +1780,7 @@ mono_class_vtable_full (MonoDomain *domain, MonoClass *klass, MonoError *error)
 
        MonoClassRuntimeInfo *runtime_info;
 
-       mono_error_init (error);
+       error_init (error);
 
        g_assert (klass);
 
@@ -1829,7 +1858,7 @@ mono_class_create_runtime_vtable (MonoDomain *domain, MonoClass *klass, MonoErro
        gpointer iter;
        gpointer *interface_offsets;
 
-       mono_error_init (error);
+       error_init (error);
 
        mono_loader_lock (); /*FIXME mono_class_init acquires it*/
        mono_domain_lock (domain);
@@ -2187,7 +2216,7 @@ mono_class_proxy_vtable (MonoDomain *domain, MonoRemoteClass *remote_class, Mono
        int bcsize;
 #endif
 
-       mono_error_init (error);
+       error_init (error);
 
        vt = mono_class_vtable (domain, klass);
        g_assert (vt); /*FIXME property handle failure*/
@@ -2496,7 +2525,7 @@ mono_remote_class (MonoDomain *domain, MonoStringHandle class_name, MonoClass *p
        gpointer* key, *mp_key;
        char *name;
        
-       mono_error_init (error);
+       error_init (error);
 
        key = create_remote_class_key (NULL, proxy_class);
        
@@ -2605,7 +2634,7 @@ mono_remote_class_vtable (MonoDomain *domain, MonoRemoteClass *remote_class, Mon
 {
        MONO_REQ_GC_UNSAFE_MODE;
 
-       mono_error_init (error);
+       error_init (error);
 
        mono_loader_lock (); /*FIXME mono_class_from_mono_type and mono_class_proxy_vtable take it*/
        mono_domain_lock (domain);
@@ -2659,7 +2688,7 @@ mono_upgrade_remote_class (MonoDomain *domain, MonoObjectHandle proxy_object, Mo
 {
        MONO_REQ_GC_UNSAFE_MODE;
 
-       mono_error_init (error);
+       error_init (error);
 
        MonoTransparentProxyHandle tproxy = MONO_HANDLE_CAST (MonoTransparentProxy, proxy_object);
        MonoRemoteClass *remote_class = MONO_HANDLE_GETVAL (tproxy, remote_class);
@@ -2727,24 +2756,22 @@ mono_object_get_virtual_method (MonoObject *obj_raw, MonoMethod *method)
 MonoMethod*
 mono_object_handle_get_virtual_method (MonoObjectHandle obj, MonoMethod *method, MonoError *error)
 {
-       mono_error_init (error);
+       error_init (error);
 
        gboolean is_proxy = FALSE;
        MonoClass *klass = mono_handle_class (obj);
-#ifndef DISABLE_REMOTING
-       if (klass == mono_defaults.transparent_proxy_class) {
+       if (mono_class_is_transparent_proxy (klass)) {
                MonoRemoteClass *remote_class = MONO_HANDLE_GETVAL (MONO_HANDLE_CAST (MonoTransparentProxy, obj), remote_class);
                klass = remote_class->proxy_class;
                is_proxy = TRUE;
        }
-#endif
        return class_get_virtual_method (klass, method, is_proxy, error);
 }
 
 static MonoMethod*
 class_get_virtual_method (MonoClass *klass, MonoMethod *method, gboolean is_proxy, MonoError *error)
 {
-       mono_error_init (error);
+       error_init (error);
 
 
        if (!is_proxy && ((method->flags & METHOD_ATTRIBUTE_FINAL) || !(method->flags & METHOD_ATTRIBUTE_VIRTUAL)))
@@ -2817,7 +2844,7 @@ do_runtime_invoke (MonoMethod *method, void *obj, void **params, MonoObject **ex
 
        g_assert (callbacks.runtime_invoke);
 
-       mono_error_init (error);
+       error_init (error);
        
        if (mono_profiler_get_events () & MONO_PROFILE_METHOD_EVENTS)
                mono_profiler_method_start_invoke (method);
@@ -3318,7 +3345,7 @@ mono_field_get_value_object_checked (MonoDomain *domain, MonoClassField *field,
 {
        MONO_REQ_GC_UNSAFE_MODE;
 
-       mono_error_init (error);
+       error_init (error);
 
        MonoObject *o;
        MonoClass *klass;
@@ -3463,7 +3490,7 @@ mono_get_constant_value_from_blob (MonoDomain* domain, MonoTypeEnum type, const
 {
        MONO_REQ_GC_UNSAFE_MODE;
 
-       mono_error_init (error);
+       error_init (error);
        int retval = 0;
        const char *p = blob;
        mono_metadata_decode_blob_size (p, &p);
@@ -3514,7 +3541,7 @@ get_default_field_value (MonoDomain* domain, MonoClassField *field, void *value,
        MonoTypeEnum def_type;
        const char* data;
 
-       mono_error_init (error);
+       error_init (error);
        
        data = mono_class_get_field_default_value (field, &def_type);
        mono_get_constant_value_from_blob (domain, def_type, data, value, error);
@@ -3527,7 +3554,7 @@ mono_field_static_get_value_for_thread (MonoInternalThread *thread, MonoVTable *
 
        void *src;
 
-       mono_error_init (error);
+       error_init (error);
 
        g_return_if_fail (field->type->attrs & FIELD_ATTRIBUTE_STATIC);
        
@@ -3649,7 +3676,7 @@ mono_property_set_value_checked (MonoProperty *prop, void *obj, void **params, M
 
        MonoObject *exc;
 
-       mono_error_init (error);
+       error_init (error);
        do_runtime_invoke (prop->set, obj, params, &exc, error);
        if (exc != NULL && is_ok (error))
                mono_error_set_exception_instance (error, (MonoException*)exc);
@@ -3772,7 +3799,7 @@ mono_nullable_box (guint8 *buf, MonoClass *klass, MonoError *error)
 {
        MONO_REQ_GC_UNSAFE_MODE;
 
-       mono_error_init (error);
+       error_init (error);
        MonoClass *param_class = klass->cast_class;
 
        mono_class_setup_fields (klass);
@@ -3913,7 +3940,7 @@ mono_runtime_delegate_try_invoke (MonoObject *delegate, void **params, MonoObjec
 {
        MONO_REQ_GC_UNSAFE_MODE;
 
-       mono_error_init (error);
+       error_init (error);
        MonoMethod *im;
        MonoClass *klass = delegate->vtable->klass;
        MonoObject *o;
@@ -3945,7 +3972,7 @@ mono_runtime_delegate_try_invoke (MonoObject *delegate, void **params, MonoObjec
 MonoObject*
 mono_runtime_delegate_invoke_checked (MonoObject *delegate, void **params, MonoError *error)
 {
-       mono_error_init (error);
+       error_init (error);
        return mono_runtime_delegate_try_invoke (delegate, params, NULL, error);
 }
 
@@ -3981,7 +4008,7 @@ mono_runtime_get_main_args_checked (MonoError *error)
        int i;
        MonoDomain *domain = mono_domain_get ();
 
-       mono_error_init (error);
+       error_init (error);
 
        res = (MonoArray*)mono_array_new_checked (domain, mono_defaults.string_class, num_main_args, error);
        return_val_if_nok (error, NULL);
@@ -4190,7 +4217,7 @@ int
 mono_runtime_run_main_checked (MonoMethod *method, int argc, char* argv[],
                               MonoError *error)
 {
-       mono_error_init (error);
+       error_init (error);
        MonoArray *args = prepare_run_main (method, argc, argv);
        return mono_runtime_exec_main_checked (method, args, error);
 }
@@ -4304,7 +4331,7 @@ make_transparent_proxy (MonoObject *obj, MonoError *error)
        MonoReflectionType *reflection_type;
        MonoTransparentProxy *transparent_proxy;
 
-       mono_error_init (error);
+       error_init (error);
 
        if (!get_proxy_method)
                get_proxy_method = mono_class_get_method_from_name (mono_defaults.real_proxy_class, "GetTransparentProxy", 0);
@@ -4348,7 +4375,7 @@ mono_object_xdomain_representation (MonoObject *obj, MonoDomain *target_domain,
 {
        MONO_REQ_GC_UNSAFE_MODE;
 
-       mono_error_init (error);
+       error_init (error);
        MonoObject *deserialized = NULL;
 
 #ifndef DISABLE_REMOTING
@@ -4383,7 +4410,7 @@ create_unhandled_exception_eventargs (MonoObject *exc, MonoError *error)
 {
        MONO_REQ_GC_UNSAFE_MODE;
 
-       mono_error_init (error);
+       error_init (error);
        MonoClass *klass;
        gpointer args [2];
        MonoMethod *method = NULL;
@@ -4634,7 +4661,7 @@ do_exec_main_checked (MonoMethod *method, MonoArray *args, MonoError *error)
        gpointer pa [1];
        int rval;
 
-       mono_error_init (error);
+       error_init (error);
        g_assert (args);
 
        pa [0] = args;
@@ -4741,7 +4768,7 @@ mono_runtime_exec_main (MonoMethod *method, MonoArray *args, MonoObject **exc)
 int
 mono_runtime_exec_main_checked (MonoMethod *method, MonoArray *args, MonoError *error)
 {
-       mono_error_init (error);
+       error_init (error);
        prepare_thread_to_exec_main (mono_object_domain (args), method);
        return do_exec_main_checked (method, args, error);
 }
@@ -4778,7 +4805,7 @@ invoke_array_extract_argument (MonoArray *params, int i, MonoType *t, gboolean*
 {
        MonoType *t_orig = t;
        gpointer result = NULL;
-       mono_error_init (error);
+       error_init (error);
                again:
                        switch (t->type) {
                        case MONO_TYPE_U1:
@@ -4803,10 +4830,12 @@ invoke_array_extract_argument (MonoArray *params, int i, MonoType *t, gboolean*
                                                *has_byref_nullables = TRUE;
                                } else {
                                        /* MS seems to create the objects if a null is passed in */
+                                       gboolean was_null = FALSE;
                                        if (!mono_array_get (params, MonoObject*, i)) {
                                                MonoObject *o = mono_object_new_checked (mono_domain_get (), mono_class_from_mono_type (t_orig), error);
                                                return_val_if_nok (error, NULL);
                                                mono_array_setref (params, i, o); 
+                                               was_null = TRUE;
                                        }
 
                                        if (t->byref) {
@@ -4824,6 +4853,8 @@ invoke_array_extract_argument (MonoArray *params, int i, MonoType *t, gboolean*
                                        }
                                                
                                        result = mono_object_unbox (mono_array_get (params, MonoObject*, i));
+                                       if (!t->byref && was_null)
+                                               mono_array_setref (params, i, NULL);
                                }
                                break;
                        case MONO_TYPE_STRING:
@@ -4959,7 +4990,7 @@ MonoObject*
 mono_runtime_invoke_array_checked (MonoMethod *method, void *obj, MonoArray *params,
                                   MonoError *error)
 {
-       mono_error_init (error);
+       error_init (error);
        return mono_runtime_try_invoke_array (method, obj, params, NULL, error);
 }
 
@@ -5008,7 +5039,7 @@ mono_runtime_try_invoke_array (MonoMethod *method, void *obj, MonoArray *params,
 {
        MONO_REQ_GC_UNSAFE_MODE;
 
-       mono_error_init (error);
+       error_init (error);
 
        MonoMethodSignature *sig = mono_method_signature (method);
        gpointer *pa = NULL;
@@ -5044,7 +5075,7 @@ mono_runtime_try_invoke_array (MonoMethod *method, void *obj, MonoArray *params,
                        mono_error_assert_ok (error);
                        g_assert (obj); /*maybe we should raise a TLE instead?*/
 #ifndef DISABLE_REMOTING
-                       if (mono_object_class(obj) == mono_defaults.transparent_proxy_class) {
+                       if (mono_object_is_transparent_proxy (obj)) {
                                method = mono_marshal_get_remoting_invoke (method->slot == -1 ? method : method->klass->vtable [method->slot]);
                        }
 #endif
@@ -5204,7 +5235,7 @@ mono_object_new_pinned (MonoDomain *domain, MonoClass *klass, MonoError *error)
 
        MonoVTable *vtable;
 
-       mono_error_init (error);
+       error_init (error);
 
        vtable = mono_class_vtable (domain, klass);
        g_assert (vtable); /* FIXME don't swallow the error */
@@ -5243,7 +5274,7 @@ mono_object_new_specific_checked (MonoVTable *vtable, MonoError *error)
 
        MonoObject *o;
 
-       mono_error_init (error);
+       error_init (error);
 
        /* check for is_com_object for COM Interop */
        if (mono_vtable_is_remote (vtable) || mono_class_is_com_object (vtable->klass))
@@ -5337,7 +5368,7 @@ mono_object_new_alloc_specific_checked (MonoVTable *vtable, MonoError *error)
 
        MonoObject *o;
 
-       mono_error_init (error);
+       error_init (error);
 
        o = (MonoObject *)mono_gc_alloc_obj (vtable, vtable->klass->instance_size);
 
@@ -5398,7 +5429,7 @@ mono_object_new_fast_checked (MonoVTable *vtable, MonoError *error)
 
        MonoObject *o;
 
-       mono_error_init (error);
+       error_init (error);
 
        o = mono_gc_alloc_obj (vtable, vtable->klass->instance_size);
 
@@ -5425,7 +5456,7 @@ mono_object_new_mature (MonoVTable *vtable, MonoError *error)
 
        MonoObject *o;
 
-       mono_error_init (error);
+       error_init (error);
 
        o = mono_gc_alloc_mature (vtable, vtable->klass->instance_size);
 
@@ -5529,7 +5560,7 @@ mono_object_clone_checked (MonoObject *obj, MonoError *error)
        MonoObject *o;
        int size;
 
-       mono_error_init (error);
+       error_init (error);
 
        size = obj->vtable->klass->instance_size;
 
@@ -5571,6 +5602,13 @@ mono_array_full_copy (MonoArray *src, MonoArray *dest)
        size = mono_array_length (src);
        g_assert (size == mono_array_length (dest));
        size *= mono_array_element_size (klass);
+
+       array_full_copy_unchecked_size (src, dest, klass, size);
+}
+
+static void
+array_full_copy_unchecked_size (MonoArray *src, MonoArray *dest, MonoClass *klass, uintptr_t size)
+{
 #ifdef HAVE_SGEN_GC
        if (klass->element_class->valuetype) {
                if (klass->element_class->has_references)
@@ -5594,62 +5632,51 @@ mono_array_full_copy (MonoArray *src, MonoArray *dest)
  * This routine returns a copy of the array that is hosted on the
  * specified MonoDomain.  On failure returns NULL and sets @error.
  */
-MonoArray*
-mono_array_clone_in_domain (MonoDomain *domain, MonoArray *array, MonoError *error)
+MonoArrayHandle
+mono_array_clone_in_domain (MonoDomain *domain, MonoArrayHandle array_handle, MonoError *error)
 {
        MONO_REQ_GC_UNSAFE_MODE;
 
-       MonoArray *o;
-       uintptr_t size, i;
-       uintptr_t *sizes;
-       MonoClass *klass = array->obj.vtable->klass;
-
-       mono_error_init (error);
+       MonoArrayHandle result = MONO_HANDLE_NEW (MonoArray, NULL);
+       uintptr_t size = 0;
+       MonoClass *klass = mono_handle_class (array_handle);
 
-       if (array->bounds == NULL) {
-               size = mono_array_length (array);
-               o = mono_array_new_full_checked (domain, klass, &size, NULL, error);
-               return_val_if_nok (error, NULL);
+       error_init (error);
 
-               size *= mono_array_element_size (klass);
-#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_fast (array, 0, 0), mono_array_length (array));
-                       else
-                               mono_gc_memmove_atomic (&o->vector, &array->vector, size);
-               } else {
-                       mono_array_memcpy_refs (o, 0, array, 0, mono_array_length (array));
-               }
-#else
-               mono_gc_memmove_atomic (&o->vector, &array->vector, size);
-#endif
-               return o;
-       }
+       /* Pin source array here - if bounds is non-NULL, it's a pointer into the object data */
+       uint32_t src_handle = mono_gchandle_from_handle (MONO_HANDLE_CAST (MonoObject, array_handle), TRUE);
        
-       sizes = (uintptr_t *)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_checked (domain, klass, sizes, (intptr_t*)sizes + klass->rank, error);
-       return_val_if_nok (error, NULL);
-#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_fast (array, 0, 0), mono_array_length (array));
-               else
-                       mono_gc_memmove_atomic (&o->vector, &array->vector, size);
+       MonoArrayBounds *array_bounds = MONO_HANDLE_GETVAL (array_handle, bounds);
+       MonoArrayHandle o;
+       if (array_bounds == NULL) {
+               size = mono_array_handle_length (array_handle);
+               o = mono_array_new_full_handle (domain, klass, &size, NULL, error);
+               if (!is_ok (error))
+                       goto leave;
+               size *= mono_array_element_size (klass);
        } else {
-               mono_array_memcpy_refs (o, 0, array, 0, mono_array_length (array));
+               uintptr_t *sizes = (uintptr_t *)alloca (klass->rank * sizeof (uintptr_t));
+               intptr_t *lower_bounds = (intptr_t *)alloca (klass->rank * sizeof (intptr_t));
+               size = mono_array_element_size (klass);
+               for (int i = 0; i < klass->rank; ++i) {
+                       sizes [i] = array_bounds [i].length;
+                       size *= array_bounds [i].length;
+                       lower_bounds [i] = array_bounds [i].lower_bound;
+               }
+               o = mono_array_new_full_handle (domain, klass, sizes, lower_bounds, error);
+               if (!is_ok (error))
+                       goto leave;
        }
-#else
-       mono_gc_memmove_atomic (&o->vector, &array->vector, size);
-#endif
 
-       return o;
+       uint32_t dst_handle = mono_gchandle_from_handle (MONO_HANDLE_CAST (MonoObject, o), TRUE);
+       array_full_copy_unchecked_size (MONO_HANDLE_RAW (array_handle), MONO_HANDLE_RAW (o), klass, size);
+       mono_gchandle_free (dst_handle);
+
+       MONO_HANDLE_ASSIGN (result, o);
+
+leave:
+       mono_gchandle_free (src_handle);
+       return result;
 }
 
 /**
@@ -5678,11 +5705,15 @@ mono_array_clone (MonoArray *array)
  * failure returns NULL and sets @error.
  */
 MonoArray*
-mono_array_clone_checked (MonoArray *array, MonoError *error)
+mono_array_clone_checked (MonoArray *array_raw, MonoError *error)
 {
-
        MONO_REQ_GC_UNSAFE_MODE;
-       return mono_array_clone_in_domain (((MonoObject *)array)->vtable->domain, array, error);
+       HANDLE_FUNCTION_ENTER ();
+       /* FIXME: callers of mono_array_clone_checked should use handles */
+       error_init (error);
+       MONO_HANDLE_DCL (MonoArray, array);
+       MonoArrayHandle result = mono_array_clone_in_domain (MONO_HANDLE_DOMAIN (array), array, error);
+       HANDLE_FUNCTION_RETURN_OBJ (result);
 }
 
 /* helper macros to check for overflow when calculating the size of arrays */
@@ -5756,7 +5787,7 @@ mono_array_new_full_checked (MonoDomain *domain, MonoClass *array_class, uintptr
        MonoVTable *vtable;
        int i;
 
-       mono_error_init (error);
+       error_init (error);
 
        if (!array_class->inited)
                mono_class_init (array_class);
@@ -5871,7 +5902,7 @@ mono_array_new_checked (MonoDomain *domain, MonoClass *eclass, uintptr_t n, Mono
 {
        MonoClass *ac;
 
-       mono_error_init (error);
+       error_init (error);
 
        ac = mono_array_class_get (eclass, 1);
        g_assert (ac);
@@ -5918,7 +5949,7 @@ mono_array_new_specific_checked (MonoVTable *vtable, uintptr_t n, MonoError *err
        MonoObject *o;
        uintptr_t byte_len;
 
-       mono_error_init (error);
+       error_init (error);
 
        if (G_UNLIKELY (n > MONO_ARRAY_MAX_INDEX)) {
                mono_error_set_generic_error (error, "System", "OverflowException", "");
@@ -6010,7 +6041,7 @@ mono_string_new_utf16_checked (MonoDomain *domain, const guint16 *text, gint32 l
 
        MonoString *s;
        
-       mono_error_init (error);
+       error_init (error);
        
        s = mono_string_new_size_checked (domain, len, error);
        if (s != NULL)
@@ -6019,6 +6050,21 @@ mono_string_new_utf16_checked (MonoDomain *domain, const guint16 *text, gint32 l
        return s;
 }
 
+/**
+ * mono_string_new_utf16_handle:
+ * @text: a pointer to an utf16 string
+ * @len: the length of the string
+ * @error: written on error.
+ *
+ * Returns: A newly created string object which contains @text.
+ * On error, returns NULL and sets @error.
+ */
+MonoStringHandle
+mono_string_new_utf16_handle (MonoDomain *domain, const guint16 *text, gint32 len, MonoError *error)
+{
+       return MONO_HANDLE_NEW (MonoString, mono_string_new_utf16_checked (domain, text, len, error));
+}
+
 /**
  * mono_string_new_utf32:
  * @text: a pointer to an utf32 string
@@ -6038,7 +6084,7 @@ mono_string_new_utf32_checked (MonoDomain *domain, const mono_unichar4 *text, gi
        GError *gerror = NULL;
        glong items_written;
        
-       mono_error_init (error);
+       error_init (error);
        utf16_output = g_ucs4_to_utf16 (text, len, NULL, &items_written, &gerror);
        
        if (gerror)
@@ -6098,7 +6144,7 @@ mono_string_new_size_checked (MonoDomain *domain, gint32 len, MonoError *error)
        MonoVTable *vtable;
        size_t size;
 
-       mono_error_init (error);
+       error_init (error);
 
        /* check for overflow */
        if (len < 0 || len > ((SIZE_MAX - G_STRUCT_OFFSET (MonoString, chars) - 8) / 2)) {
@@ -6154,7 +6200,7 @@ mono_string_new_len_checked (MonoDomain *domain, const char *text, guint length,
 {
        MONO_REQ_GC_UNSAFE_MODE;
 
-       mono_error_init (error);
+       error_init (error);
 
        GError *eg_error = NULL;
        MonoString *o = NULL;
@@ -6212,7 +6258,7 @@ mono_string_new_checked (MonoDomain *domain, const char *text, MonoError *error)
     glong items_written;
     int l;
 
-    mono_error_init (error);
+    error_init (error);
 
     l = strlen (text);
    
@@ -6306,7 +6352,7 @@ mono_value_box_checked (MonoDomain *domain, MonoClass *klass, gpointer value, Mo
        int size;
        MonoVTable *vtable;
 
-       mono_error_init (error);
+       error_init (error);
 
        g_assert (klass->valuetype);
        if (mono_class_is_nullable (klass))
@@ -6504,7 +6550,7 @@ mono_object_isinst_checked (MonoObject *obj_raw, MonoClass *klass, MonoError *er
        MONO_REQ_GC_UNSAFE_MODE;
 
        HANDLE_FUNCTION_ENTER ();
-       mono_error_init (error);
+       error_init (error);
        MONO_HANDLE_DCL (MonoObject, obj);
        MonoObjectHandle result = mono_object_handle_isinst (obj, klass, error);
        HANDLE_FUNCTION_RETURN_OBJ (result);
@@ -6522,7 +6568,7 @@ mono_object_isinst_checked (MonoObject *obj_raw, MonoClass *klass, MonoError *er
 MonoObjectHandle
 mono_object_handle_isinst (MonoObjectHandle obj, MonoClass *klass, MonoError *error)
 {
-       mono_error_init (error);
+       error_init (error);
        
        if (!klass->inited)
                mono_class_init (klass);
@@ -6554,7 +6600,7 @@ mono_object_isinst_mbyref (MonoObject *obj_raw, MonoClass *klass)
 MonoObjectHandle
 mono_object_handle_isinst_mbyref (MonoObjectHandle obj, MonoClass *klass, MonoError *error)
 {
-       mono_error_init (error);
+       error_init (error);
 
        MonoObjectHandle result = MONO_HANDLE_NEW (MonoObject, NULL);
 
@@ -6596,7 +6642,7 @@ mono_object_handle_isinst_mbyref (MonoObjectHandle obj, MonoClass *klass, MonoEr
                }
        }
 #ifndef DISABLE_REMOTING
-       if (vt->klass == mono_defaults.transparent_proxy_class
+       if (mono_class_is_transparent_proxy (vt->klass)
        {
                MonoBoolean custom_type_info =  MONO_HANDLE_GETVAL (MONO_HANDLE_CAST (MonoTransparentProxy, obj), custom_type_info);
                if (!custom_type_info)
@@ -6686,7 +6732,7 @@ mono_string_get_pinned (MonoString *str, MonoError *error)
 {
        MONO_REQ_GC_UNSAFE_MODE;
 
-       mono_error_init (error);
+       error_init (error);
 
        /* We only need to make a pinned version of a string if this is a moving GC */
        if (!mono_gc_is_moving ())
@@ -6713,7 +6759,7 @@ mono_string_is_interned_lookup (MonoString *str, int insert, MonoError *error)
        MonoString *s, *res;
        MonoDomain *domain;
        
-       mono_error_init (error);
+       error_init (error);
 
        domain = ((MonoObject *)str)->vtable->domain;
        ldstr_table = domain->ldstr_table;
@@ -6805,7 +6851,7 @@ mono_string_intern_checked (MonoString *str, MonoError *error)
 {
        MONO_REQ_GC_UNSAFE_MODE;
 
-       mono_error_init (error);
+       error_init (error);
 
        return mono_string_is_interned_lookup (str, TRUE, error);
 }
@@ -6843,7 +6889,7 @@ MonoString*
 mono_ldstr_checked (MonoDomain *domain, MonoImage *image, guint32 idx, MonoError *error)
 {
        MONO_REQ_GC_UNSAFE_MODE;
-       mono_error_init (error);
+       error_init (error);
 
        if (image->dynamic) {
                MonoString *str = (MonoString *)mono_lookup_dynamic_token (image, MONO_TOKEN_STRING | idx, NULL, error);
@@ -6870,7 +6916,7 @@ mono_ldstr_metadata_sig (MonoDomain *domain, const char* sig, MonoError *error)
 {
        MONO_REQ_GC_UNSAFE_MODE;
 
-       mono_error_init (error);
+       error_init (error);
        const char *str = sig;
        MonoString *o, *interned;
        size_t len2;
@@ -6925,7 +6971,7 @@ mono_ldstr_utf8 (MonoImage *image, guint32 idx, MonoError *error)
        char *as;
        GError *gerror = NULL;
 
-       mono_error_init (error);
+       error_init (error);
 
        if (!mono_verifier_verify_string_signature (image, idx, NULL))
                return NULL; /*FIXME we should probably be raising an exception here*/
@@ -6994,7 +7040,7 @@ mono_string_to_utf8_checked (MonoString *s, MonoError *error)
        char *as;
        GError *gerror = NULL;
 
-       mono_error_init (error);
+       error_init (error);
 
        if (s == NULL)
                return NULL;
@@ -7182,7 +7228,7 @@ mono_string_from_utf16_checked (gunichar2 *data, MonoError *error)
 
        MONO_REQ_GC_UNSAFE_MODE;
 
-       mono_error_init (error);
+       error_init (error);
        MonoDomain *domain = mono_domain_get ();
        int len = 0;
 
@@ -7225,7 +7271,7 @@ mono_string_from_utf32_checked (mono_unichar4 *data, MonoError *error)
 {
        MONO_REQ_GC_UNSAFE_MODE;
 
-       mono_error_init (error);
+       error_init (error);
        MonoString* result = NULL;
        mono_unichar2 *utf16_output = NULL;
        GError *gerror = NULL;
@@ -7287,11 +7333,11 @@ mono_string_to_utf8_internal (MonoMemPool *mp, MonoImage *image, MonoString *s,
  * Same as mono_string_to_utf8, but allocate the string from the image mempool.
  */
 char *
-mono_string_to_utf8_image (MonoImage *image, MonoString *s, MonoError *error)
+mono_string_to_utf8_image (MonoImage *image, MonoStringHandle s, MonoError *error)
 {
        MONO_REQ_GC_UNSAFE_MODE;
 
-       return mono_string_to_utf8_internal (NULL, image, s, FALSE, error);
+       return mono_string_to_utf8_internal (NULL, image, MONO_HANDLE_RAW (s), FALSE, error); /* FIXME pin the string */
 }
 
 /**
@@ -7369,7 +7415,7 @@ mono_wait_handle_new (MonoDomain *domain, HANDLE handle, MonoError *error)
        gpointer params [1];
        static MonoMethod *handle_set;
 
-       mono_error_init (error);
+       error_init (error);
        res = (MonoWaitHandle *)mono_object_new_checked (domain, mono_defaults.manualresetevent_class, error);
        return_val_if_nok (error, NULL);
 
@@ -7408,7 +7454,7 @@ mono_runtime_capture_context (MonoDomain *domain, MonoError *error)
 
        RuntimeInvokeFunction runtime_invoke;
 
-       mono_error_init (error);
+       error_init (error);
 
        if (!domain->capture_context_runtime_invoke || !domain->capture_context_method) {
                MonoMethod *method = mono_get_context_capture_method ();
@@ -7444,7 +7490,7 @@ mono_async_result_new (MonoDomain *domain, HANDLE handle, MonoObject *state, gpo
 {
        MONO_REQ_GC_UNSAFE_MODE;
 
-       mono_error_init (error);
+       error_init (error);
        MonoAsyncResult *res = (MonoAsyncResult *)mono_object_new_checked (domain, mono_defaults.asyncresult_class, error);
        return_val_if_nok (error, NULL);
        MonoObject *context = mono_runtime_capture_context (domain, error);
@@ -7514,7 +7560,7 @@ ves_icall_System_Runtime_Remoting_Messaging_AsyncResult_Invoke (MonoAsyncResult
                if (wait_event != NULL)
                        mono_w32event_set (wait_event);
 
-               mono_error_init (&error); //the else branch would leave it in an undefined state
+               error_init (&error); //the else branch would leave it in an undefined state
                if (ac->cb_method)
                        mono_runtime_invoke_checked (ac->cb_method, ac->cb_target, (gpointer*) &ares, &error);
 
@@ -7543,7 +7589,7 @@ mono_message_init (MonoDomain *domain,
                g_assert (init_message_method != NULL);
        }
 
-       mono_error_init (error);
+       error_init (error);
        /* FIXME set domain instead? */
        g_assert (domain == mono_domain_get ());
        
@@ -7582,7 +7628,7 @@ mono_remoting_invoke (MonoObject *real_proxy, MonoMethodMessage *msg, MonoObject
 
        g_assert (exc);
 
-       mono_error_init (error);
+       error_init (error);
 
        /*static MonoObject *(*invoke) (gpointer, gpointer, MonoObject **, MonoArray **) = NULL;*/
 
@@ -7614,7 +7660,7 @@ mono_message_invoke (MonoObject *target, MonoMethodMessage *msg,
        MONO_REQ_GC_UNSAFE_MODE;
 
        static MonoClass *object_array_klass;
-       mono_error_init (error);
+       error_init (error);
 
        MonoDomain *domain; 
        MonoMethod *method;
@@ -7744,7 +7790,7 @@ mono_object_to_string (MonoObject *obj, MonoObject **exc)
 MonoString *
 mono_object_to_string_checked (MonoObject *obj, MonoError *error)
 {
-       mono_error_init (error);
+       error_init (error);
        void *target;
        MonoMethod *method = prepare_to_string_method (obj, &target);
        return (MonoString*) mono_runtime_invoke_checked (method, target, NULL, error);
@@ -7764,7 +7810,7 @@ MonoString *
 mono_object_try_to_string (MonoObject *obj, MonoObject **exc, MonoError *error)
 {
        g_assert (exc);
-       mono_error_init (error);
+       error_init (error);
        void *target;
        MonoMethod *method = prepare_to_string_method (obj, &target);
        return (MonoString*) mono_runtime_try_invoke (method, target, NULL, exc, error);
@@ -7866,7 +7912,7 @@ mono_delegate_ctor_with_method (MonoObject *this_obj, MonoObject *target, gpoint
 {
        MONO_REQ_GC_UNSAFE_MODE;
 
-       mono_error_init (error);
+       error_init (error);
        MonoDelegate *delegate = (MonoDelegate *)this_obj;
 
        g_assert (this_obj);
@@ -7880,9 +7926,12 @@ mono_delegate_ctor_with_method (MonoObject *this_obj, MonoObject *target, gpoint
        mono_stats.delegate_creations++;
 
 #ifndef DISABLE_REMOTING
-       if (target && target->vtable->klass == mono_defaults.transparent_proxy_class) {
+       if (target && mono_object_is_transparent_proxy (target)) {
                g_assert (method);
                method = mono_marshal_get_remoting_invoke (method);
+#ifdef ENABLE_INTERPRETER
+               g_error ("need RuntimeMethod in method_ptr when using interpreter");
+#endif
                delegate->method_ptr = mono_compile_method_checked (method, error);
                return_val_if_nok (error, FALSE);
                MONO_OBJECT_SETREF (delegate, target, target);
@@ -7914,7 +7963,7 @@ mono_delegate_ctor (MonoObject *this_obj, MonoObject *target, gpointer addr, Mon
 {
        MONO_REQ_GC_UNSAFE_MODE;
 
-       mono_error_init (error);
+       error_init (error);
        MonoDomain *domain = mono_domain_get ();
        MonoJitInfo *ji;
        MonoMethod *method = NULL;
@@ -7951,7 +8000,7 @@ mono_method_call_message_new (MonoMethod *method, gpointer *params, MonoMethod *
 {
        MONO_REQ_GC_UNSAFE_MODE;
 
-       mono_error_init (error);
+       error_init (error);
 
        MonoDomain *domain = mono_domain_get ();
        MonoMethodSignature *sig = mono_method_signature (method);
@@ -8015,7 +8064,7 @@ mono_method_return_message_restore (MonoMethod *method, gpointer *params, MonoAr
 {
        MONO_REQ_GC_UNSAFE_MODE;
 
-       mono_error_init (error);
+       error_init (error);
 
        MonoMethodSignature *sig = mono_method_signature (method);
        int i, j, type, size, out_len;
@@ -8109,7 +8158,7 @@ mono_load_remote_field_checked (MonoObject *this_obj, MonoClass *klass, MonoClas
 
        static MonoMethod *getter = NULL;
 
-       mono_error_init (error);
+       error_init (error);
 
        MonoDomain *domain = mono_domain_get ();
        MonoTransparentProxy *tp = (MonoTransparentProxy *) this_obj;
@@ -8206,7 +8255,7 @@ mono_load_remote_field_new_checked (MonoObject *this_obj, MonoClass *klass, Mono
 {
        MONO_REQ_GC_UNSAFE_MODE;
 
-       mono_error_init (error);
+       error_init (error);
 
        static MonoMethod *tp_load = NULL;
 
@@ -8268,7 +8317,7 @@ mono_store_remote_field_checked (MonoObject *this_obj, MonoClass *klass, MonoCla
        
        MONO_REQ_GC_UNSAFE_MODE;
 
-       mono_error_init (error);
+       error_init (error);
 
        MonoDomain *domain = mono_domain_get ();
        MonoClass *field_class;
@@ -8322,7 +8371,7 @@ mono_store_remote_field_new_checked (MonoObject *this_obj, MonoClass *klass, Mon
 
        static MonoMethod *tp_store = NULL;
 
-       mono_error_init (error);
+       error_init (error);
 
        g_assert (mono_object_is_transparent_proxy (this_obj));
 
@@ -8396,6 +8445,21 @@ mono_string_length (MonoString *s)
        return s->length;
 }
 
+/**
+ * mono_string_handle_length:
+ * @s: MonoString
+ *
+ * Returns the lenght in characters of the string
+ */
+int
+mono_string_handle_length (MonoStringHandle s)
+{
+       MONO_REQ_GC_UNSAFE_MODE;
+
+       return MONO_HANDLE_GETVAL (s, length);
+}
+
+
 /**
  * mono_array_length:
  * @array: a MonoArray*
@@ -8440,7 +8504,7 @@ mono_glist_to_array (GList *list, MonoClass *eclass, MonoError *error)
        MonoArray *res;
        int len, i;
 
-       mono_error_init (error);
+       error_init (error);
        if (!list)
                return NULL;