Merge pull request #5714 from alexischr/update_bockbuild
[mono.git] / mono / metadata / icall.c
index 79329f935382f75dd2d2ba9e3be1e2825d17d45e..f55ed1f1847600caf96c9aced596651945e01320 100644 (file)
@@ -118,6 +118,9 @@ static GENERATE_GET_CLASS_WITH_CACHE (property_info, "System.Reflection", "Prope
 static GENERATE_GET_CLASS_WITH_CACHE (event_info, "System.Reflection", "EventInfo")
 static GENERATE_GET_CLASS_WITH_CACHE (module, "System.Reflection", "Module")
 
+static void
+array_set_value_impl (MonoArrayHandle arr, MonoObjectHandle value, guint32 pos, MonoError *error);
+
 static MonoArrayHandle
 type_array_from_modifiers (MonoImage *image, MonoType *type, int optional, MonoError *error);
 
@@ -220,9 +223,15 @@ ves_icall_System_Array_GetValue (MonoArray *arr, MonoArray *idxs)
 }
 
 ICALL_EXPORT void
-ves_icall_System_Array_SetValueImpl (MonoArray *arr, MonoObject *value, guint32 pos)
+ves_icall_System_Array_SetValueImpl (MonoArrayHandle arr, MonoObjectHandle value, guint32 pos, MonoError *error)
+{
+       error_init (error);
+       array_set_value_impl (arr, value, pos, error);
+}
+
+static void
+array_set_value_impl (MonoArrayHandle arr, MonoObjectHandle value, guint32 pos, MonoError *error)
 {
-       MonoError error;
        MonoClass *ac, *vc, *ec;
        gint32 esize, vsize;
        gpointer *ea, *va;
@@ -232,49 +241,49 @@ ves_icall_System_Array_SetValueImpl (MonoArray *arr, MonoObject *value, guint32
        gint64 i64 = 0;
        gdouble r64 = 0;
 
-       error_init (&error);
+       uint32_t arr_gchandle = 0;
+       uint32_t value_gchandle = 0;
 
-       if (value)
-               vc = value->vtable->klass;
+       error_init (error);
+
+       if (!MONO_HANDLE_IS_NULL (value))
+               vc = mono_handle_class (value);
        else
                vc = NULL;
 
-       ac = arr->obj.vtable->klass;
+       ac = mono_handle_class (arr);
        ec = ac->element_class;
 
        esize = mono_array_element_size (ac);
-       ea = (gpointer*)((char*)arr->vector + (pos * esize));
-       va = (gpointer*)((char*)value + sizeof (MonoObject));
+       ea = mono_array_handle_pin_with_size (arr, esize, pos, &arr_gchandle);
 
        if (mono_class_is_nullable (ec)) {
-               mono_nullable_init ((guint8*)ea, value, ec);
-               return;
+               mono_nullable_init_from_handle ((guint8*)ea, value, ec);
+               goto leave;
        }
 
-       if (!value) {
+       if (MONO_HANDLE_IS_NULL (value)) {
                mono_gc_bzero_atomic (ea, esize);
-               return;
+               goto leave;
        }
 
-#define NO_WIDENING_CONVERSION G_STMT_START{\
-       mono_set_pending_exception (mono_get_exception_argument ( \
-               "value", "not a widening conversion")); \
-       return; \
-}G_STMT_END
+#define NO_WIDENING_CONVERSION G_STMT_START{                           \
+               mono_error_set_argument (error, "value", "not a widening conversion"); \
+               goto leave;                                                     \
+       }G_STMT_END
 
-#define CHECK_WIDENING_CONVERSION(extra) G_STMT_START{\
-               if (esize < vsize + (extra)) {                                                    \
-                       mono_set_pending_exception (mono_get_exception_argument (       \
-                       "value", "not a widening conversion")); \
-                       return;                                                                 \
-               } \
-}G_STMT_END
+#define CHECK_WIDENING_CONVERSION(extra) G_STMT_START{                 \
+               if (esize < vsize + (extra)) {                          \
+                       mono_error_set_argument (error, "value", "not a widening conversion"); \
+                       goto leave;                                             \
+               }                                                       \
+       }G_STMT_END
 
-#define INVALID_CAST G_STMT_START{ \
+#define INVALID_CAST G_STMT_START{                                     \
                mono_get_runtime_callbacks ()->set_cast_details (vc, ec); \
-       mono_set_pending_exception (mono_get_exception_invalid_cast ()); \
-       return; \
-}G_STMT_END
+               mono_error_set_invalid_cast (error);                    \
+               goto leave;                                                     \
+       }G_STMT_END
 
        /* Check element (destination) type. */
        switch (ec->byval_arg.type) {
@@ -310,29 +319,34 @@ ves_icall_System_Array_SetValueImpl (MonoArray *arr, MonoObject *value, guint32
                break;
        }
 
+       MonoObjectHandle inst = mono_object_handle_isinst (value, ec, error);
+       if (!is_ok (error))
+               goto leave;
+       gboolean castOk = !MONO_HANDLE_IS_NULL (inst);
+
        if (!ec->valuetype) {
-               gboolean castOk = (NULL != mono_object_isinst_checked (value, ec, &error));
-               if (mono_error_set_pending_exception (&error))
-                       return;
                if (!castOk)
                        INVALID_CAST;
-               mono_gc_wbarrier_set_arrayref (arr, ea, (MonoObject*)value);
-               return;
+               MONO_HANDLE_ARRAY_SETREF (arr, pos, value);
+               goto leave;
        }
 
-       if (mono_object_isinst_checked (value, ec, &error)) {
+       if (castOk) {
+               va = mono_object_handle_pin_unbox (value, &value_gchandle);
                if (ec->has_references)
-                       mono_value_copy (ea, (char*)value + sizeof (MonoObject), ec);
+                       mono_value_copy (ea, va, ec);
                else
-                       mono_gc_memmove_atomic (ea, (char *)value + sizeof (MonoObject), esize);
-               return;
+                       mono_gc_memmove_atomic (ea, va, esize);
+               mono_gchandle_free (value_gchandle);
+               value_gchandle = 0;
+               goto leave;
        }
-       if (mono_error_set_pending_exception (&error))
-               return;
 
        if (!vc->valuetype)
                INVALID_CAST;
 
+       va = mono_object_handle_pin_unbox (value, &value_gchandle);
+
        vsize = mono_class_instance_size (vc) - sizeof (MonoObject);
 
        et = ec->byval_arg.type;
@@ -352,7 +366,7 @@ ves_icall_System_Array_SetValueImpl (MonoArray *arr, MonoObject *value, guint32
        case MONO_TYPE_CHAR: \
                CHECK_WIDENING_CONVERSION(0); \
                *(etype *) ea = (etype) u64; \
-               return; \
+               goto leave; \
        /* You can't assign a signed value to an unsigned array. */ \
        case MONO_TYPE_I1: \
        case MONO_TYPE_I2: \
@@ -373,7 +387,7 @@ ves_icall_System_Array_SetValueImpl (MonoArray *arr, MonoObject *value, guint32
        case MONO_TYPE_I8: \
                CHECK_WIDENING_CONVERSION(0); \
                *(etype *) ea = (etype) i64; \
-               return; \
+               goto leave; \
        /* You can assign an unsigned value to a signed array if the array's */ \
        /* element size is larger than the value size. */ \
        case MONO_TYPE_U1: \
@@ -383,7 +397,7 @@ ves_icall_System_Array_SetValueImpl (MonoArray *arr, MonoObject *value, guint32
        case MONO_TYPE_CHAR: \
                CHECK_WIDENING_CONVERSION(1); \
                *(etype *) ea = (etype) u64; \
-               return; \
+               goto leave; \
        /* You can't assign a floating point number to an integer array. */ \
        case MONO_TYPE_R4: \
        case MONO_TYPE_R8: \
@@ -397,7 +411,7 @@ ves_icall_System_Array_SetValueImpl (MonoArray *arr, MonoObject *value, guint32
        case MONO_TYPE_R8: \
                CHECK_WIDENING_CONVERSION(0); \
                *(etype *) ea = (etype) r64; \
-               return; \
+               goto leave; \
        /* All integer values fit into a floating point array, so we don't */ \
        /* need to CHECK_WIDENING_CONVERSION here. */ \
        case MONO_TYPE_I1: \
@@ -405,14 +419,14 @@ ves_icall_System_Array_SetValueImpl (MonoArray *arr, MonoObject *value, guint32
        case MONO_TYPE_I4: \
        case MONO_TYPE_I8: \
                *(etype *) ea = (etype) i64; \
-               return; \
+               goto leave; \
        case MONO_TYPE_U1: \
        case MONO_TYPE_U2: \
        case MONO_TYPE_U4: \
        case MONO_TYPE_U8: \
        case MONO_TYPE_CHAR: \
                *(etype *) ea = (etype) u64; \
-               return; \
+               goto leave; \
        } \
 }G_STMT_END
 
@@ -498,8 +512,8 @@ ves_icall_System_Array_SetValueImpl (MonoArray *arr, MonoObject *value, guint32
        }
 
        INVALID_CAST;
-       /* Not reached, INVALID_CAST does not return. Just to avoid a compiler warning ... */
-       return;
+       /* Not reached, INVALID_CAST does fall thru. */
+       g_assert_not_reached ();
 
 #undef INVALID_CAST
 #undef NO_WIDENING_CONVERSION
@@ -507,51 +521,71 @@ ves_icall_System_Array_SetValueImpl (MonoArray *arr, MonoObject *value, guint32
 #undef ASSIGN_UNSIGNED
 #undef ASSIGN_SIGNED
 #undef ASSIGN_REAL
+leave:
+       if (arr_gchandle)
+               mono_gchandle_free (arr_gchandle);
+       if (value_gchandle)
+               mono_gchandle_free (value_gchandle);
+       return;
 }
 
 ICALL_EXPORT void 
-ves_icall_System_Array_SetValue (MonoArray *arr, MonoObject *value,
-                                MonoArray *idxs)
+ves_icall_System_Array_SetValue (MonoArrayHandle arr, MonoObjectHandle value,
+                                MonoArrayHandle idxs, MonoError *error)
 {
+       MonoArrayBounds dim;
        MonoClass *ac, *ic;
-       gint32 i, pos, *ind;
+       gint32 idx;
+       gint32 i, pos;
 
-       MONO_CHECK_ARG_NULL (idxs,);
+       error_init (error);
 
-       ic = idxs->obj.vtable->klass;
-       ac = arr->obj.vtable->klass;
+       if (MONO_HANDLE_IS_NULL (idxs)) {
+               mono_error_set_argument_null (error, "idxs", "");
+               return;
+       }
+
+       ic = mono_handle_class (idxs);
+       ac = mono_handle_class (arr);
 
        g_assert (ic->rank == 1);
-       if (idxs->bounds != NULL || idxs->max_length != ac->rank) {
-               mono_set_pending_exception (mono_get_exception_argument (NULL, NULL));
+       if (mono_handle_array_has_bounds (idxs) || MONO_HANDLE_GETVAL (idxs, max_length) != ac->rank) {
+               mono_error_set_argument (error, "idxs", "");
                return;
        }
 
-       ind = (gint32 *)idxs->vector;
-
-       if (arr->bounds == NULL) {
-               if (*ind < 0 || *ind >= arr->max_length) {
-                       mono_set_pending_exception (mono_get_exception_index_out_of_range ());
+       if (!mono_handle_array_has_bounds (arr)) {
+               MONO_HANDLE_ARRAY_GETVAL (idx, idxs, gint32, 0);
+               if (idx < 0 || idx >= MONO_HANDLE_GETVAL (arr, max_length)) {
+                       mono_error_set_exception_instance (error, mono_get_exception_index_out_of_range ());
                        return;
                }
 
-               ves_icall_System_Array_SetValueImpl (arr, value, *ind);
+               array_set_value_impl (arr, value, idx, error);
                return;
        }
        
-       for (i = 0; i < ac->rank; i++)
-               if ((ind [i] < arr->bounds [i].lower_bound) ||
-                   (ind [i] >= (mono_array_lower_bound_t)arr->bounds [i].length + arr->bounds [i].lower_bound)) {
-                       mono_set_pending_exception (mono_get_exception_index_out_of_range ());
+       for (i = 0; i < ac->rank; i++) {
+               mono_handle_array_get_bounds_dim (arr, i, &dim);
+               MONO_HANDLE_ARRAY_GETVAL (idx, idxs, gint32, i);
+               if ((idx < dim.lower_bound) ||
+                   (idx >= (mono_array_lower_bound_t)dim.length + dim.lower_bound)) {
+                       mono_error_set_exception_instance (error, mono_get_exception_index_out_of_range ());
                        return;
                }
+       }
 
-       pos = ind [0] - arr->bounds [0].lower_bound;
-       for (i = 1; i < ac->rank; i++)
-               pos = pos * arr->bounds [i].length + ind [i] - 
-                       arr->bounds [i].lower_bound;
 
-       ves_icall_System_Array_SetValueImpl (arr, value, pos);
+       MONO_HANDLE_ARRAY_GETVAL  (idx, idxs, gint32, 0);
+       mono_handle_array_get_bounds_dim (arr, 0, &dim);
+       pos = idx - dim.lower_bound;
+       for (i = 1; i < ac->rank; i++) {
+               mono_handle_array_get_bounds_dim (arr, i, &dim);
+               MONO_HANDLE_ARRAY_GETVAL (idx, idxs, gint32, i);
+               pos = pos * dim.length + idx - dim.lower_bound;
+       }
+
+       array_set_value_impl (arr, value, pos, error);
 }
 
 ICALL_EXPORT MonoArray *
@@ -980,7 +1014,7 @@ ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_SufficientExecutionStac
 {
 #if defined(TARGET_WIN32) || defined(HOST_WIN32)
        // It does not work on win32
-#elif defined(TARGET_ANDROID)
+#elif defined(TARGET_ANDROID) || defined(__linux__)
        // No need for now
 #else
        guint8 *stack_addr;
@@ -1222,7 +1256,13 @@ ves_icall_System_Object_GetType (MonoObjectHandle obj, MonoError *error)
        if (mono_class_is_transparent_proxy (klass)) {
                MonoTransparentProxyHandle proxy_obj = MONO_HANDLE_CAST (MonoTransparentProxy, obj);
                MonoRemoteClass *remote_class = MONO_HANDLE_GETVAL (proxy_obj, remote_class);
-               MonoType *proxy_type = &remote_class->proxy_class->byval_arg;
+               /* If it's a transparent proxy for an interface, return the
+                * interface type, not the unhelpful proxy_class class (which
+                * is just MarshalByRefObject). */
+               MonoType *proxy_type =
+                       mono_remote_class_is_interface_proxy (remote_class) ?
+                       &remote_class->interfaces[0]->byval_arg :
+                       &remote_class->proxy_class->byval_arg;
                return mono_type_get_object_handle (domain, proxy_type, error);
        } else
 #endif
@@ -1915,32 +1955,27 @@ ves_icall_MonoField_GetValueInternal (MonoReflectionField *field, MonoObject *ob
 }
 
 ICALL_EXPORT void
-ves_icall_MonoField_SetValueInternal (MonoReflectionField *field, MonoObject *obj, MonoObject *value)
+ves_icall_MonoField_SetValueInternal (MonoReflectionFieldHandle field, MonoObjectHandle obj, MonoObjectHandle value, MonoError  *error)
 {
-       MonoError error;
-       MonoClassField *cf = field->field;
-       MonoType *type;
-       gchar *v;
+       MonoClassField *cf = MONO_HANDLE_GETVAL (field, field);
 
-       if (field->klass->image->assembly->ref_only) {
-               mono_set_pending_exception (mono_get_exception_invalid_operation (
-                                       "It is illegal to set the value on a field on a type loaded using the ReflectionOnly methods."));
+       MonoClass *field_klass = MONO_HANDLE_GETVAL (field, klass);
+       if (field_klass->image->assembly->ref_only) {
+               mono_error_set_invalid_operation (error, "It is illegal to set the value on a field on a type loaded using the ReflectionOnly methods.");
                return;
        }
 
        if (mono_security_core_clr_enabled () &&
-           !mono_security_core_clr_ensure_reflection_access_field (cf, &error)) {
-               mono_error_set_pending_exception (&error);
+           !mono_security_core_clr_ensure_reflection_access_field (cf, error)) {
                return;
        }
 
-       type = mono_field_get_type_checked (cf, &error);
-       if (!mono_error_ok (&error)) {
-               mono_error_set_pending_exception (&error);
-               return;
-       }
+       MonoType *type = mono_field_get_type_checked (cf, error);
+       return_if_nok (error);
 
-       v = (gchar *) value;
+       gboolean isref = FALSE;
+       uint32_t value_gchandle = 0;
+       gchar *v = NULL;
        if (!type->byref) {
                switch (type->type) {
                case MONO_TYPE_U1:
@@ -1959,8 +1994,9 @@ ves_icall_MonoField_SetValueInternal (MonoReflectionField *field, MonoObject *ob
                case MONO_TYPE_R8:
                case MONO_TYPE_VALUETYPE:
                case MONO_TYPE_PTR:
-                       if (v != NULL)
-                               v += sizeof (MonoObject);
+                       isref = FALSE;
+                       if (!MONO_HANDLE_IS_NULL (value))
+                               v = mono_object_handle_pin_unbox (value, &value_gchandle);
                        break;
                case MONO_TYPE_STRING:
                case MONO_TYPE_OBJECT:
@@ -1968,6 +2004,7 @@ ves_icall_MonoField_SetValueInternal (MonoReflectionField *field, MonoObject *ob
                case MONO_TYPE_ARRAY:
                case MONO_TYPE_SZARRAY:
                        /* Do nothing */
+                       isref = TRUE;
                        break;
                case MONO_TYPE_GENERICINST: {
                        MonoGenericClass *gclass = type->data.generic_class;
@@ -1975,26 +2012,29 @@ ves_icall_MonoField_SetValueInternal (MonoReflectionField *field, MonoObject *ob
 
                        if (mono_class_is_nullable (mono_class_from_mono_type (type))) {
                                MonoClass *nklass = mono_class_from_mono_type (type);
-                               MonoObject *nullable;
 
                                /* 
                                 * Convert the boxed vtype into a Nullable structure.
                                 * This is complicated by the fact that Nullables have
                                 * a variable structure.
                                 */
-                               nullable = mono_object_new_checked (mono_domain_get (), nklass, &error);
-                               if (!mono_error_ok (&error)) {
-                                       mono_error_set_pending_exception (&error);
-                                       return;
-                               }
+                               MonoObjectHandle nullable = MONO_HANDLE_NEW (MonoObject, mono_object_new_checked (mono_domain_get (), nklass, error));
+                               return_if_nok (error);
 
-                               mono_nullable_init ((guint8 *)mono_object_unbox (nullable), value, nklass);
+                               uint32_t nullable_gchandle = 0;
+                               guint8 *nval = mono_object_handle_pin_unbox (nullable, &nullable_gchandle);
+                               mono_nullable_init_from_handle (nval, value, nklass);
 
-                               v = (gchar *)mono_object_unbox (nullable);
+                               isref = FALSE;
+                               value_gchandle = nullable_gchandle;
+                               v = (gchar*)nval;
+                       }
+                       else {
+                               isref = !gclass->container_class->valuetype;
+                               if (!isref && !MONO_HANDLE_IS_NULL (value)) {
+                                       v = mono_object_handle_pin_unbox (value, &value_gchandle);
+                               };
                        }
-                       else 
-                               if (gclass->container_class->valuetype && (v != NULL))
-                                       v += sizeof (MonoObject);
                        break;
                }
                default:
@@ -2004,22 +2044,35 @@ ves_icall_MonoField_SetValueInternal (MonoReflectionField *field, MonoObject *ob
                }
        }
 
+       /* either value is a reference type, or it's a value type and we pinned
+        * it and v points to the payload. */
+       g_assert ((isref && v == NULL && value_gchandle == 0) ||
+                 (!isref && v != NULL && value_gchandle != 0) ||
+                 (!isref && v == NULL && value_gchandle == 0));
+
        if (type->attrs & FIELD_ATTRIBUTE_STATIC) {
-               MonoVTable *vtable = mono_class_vtable_full (mono_object_domain (field), cf->parent, &error);
-               if (!is_ok (&error)) {
-                       mono_error_set_pending_exception (&error);
-                       return;
-               }
+               MonoVTable *vtable = mono_class_vtable_full (MONO_HANDLE_DOMAIN (field), cf->parent, error);
+               if (!is_ok (error))
+                       goto leave;
+
                if (!vtable->initialized) {
-                       if (!mono_runtime_class_init_full (vtable, &error)) {
-                               mono_error_set_pending_exception (&error);
-                               return;
-                       }
+                       if (!mono_runtime_class_init_full (vtable, error))
+                               goto leave;
                }
-               mono_field_static_set_value (vtable, cf, v);
+               if (isref)
+                       mono_field_static_set_value (vtable, cf, MONO_HANDLE_RAW (value)); /* FIXME make mono_field_static_set_value work with handles for value */
+               else
+                       mono_field_static_set_value (vtable, cf, v);
        } else {
-               mono_field_set_value (obj, cf, v);
+
+               if (isref)
+                       MONO_HANDLE_SET_FIELD_REF (obj, cf, value);
+               else
+                       mono_field_set_value (MONO_HANDLE_RAW (obj), cf, v); /* FIXME: make mono_field_set_value take a handle for obj */
        }
+leave:
+       if (value_gchandle)
+               mono_gchandle_free (value_gchandle);
 }
 
 ICALL_EXPORT void
@@ -3295,110 +3348,123 @@ ves_icall_InternalInvoke (MonoReflectionMethod *method, MonoObject *this_arg, Mo
 }
 
 #ifndef DISABLE_REMOTING
-ICALL_EXPORT MonoObject *
-ves_icall_InternalExecute (MonoReflectionMethod *method, MonoObject *this_arg, MonoArray *params, MonoArray **outArgs) 
+static void
+internal_execute_field_getter (MonoDomain *domain, MonoObject *this_arg, MonoArray *params, MonoArray **outArgs, MonoError *error)
 {
-       MonoError error;
-       MonoDomain *domain = mono_object_domain (method); 
-       MonoMethod *m = method->method;
-       MonoMethodSignature *sig = mono_method_signature (m);
+       error_init (error);
        MonoArray *out_args;
-       MonoObject *result;
-       int i, j, outarg_count = 0;
-
-       if (m->klass == mono_defaults.object_class) {
-               if (!strcmp (m->name, "FieldGetter")) {
-                       MonoClass *k = mono_object_class (this_arg);
-                       MonoString *name;
-                       char *str;
+       MonoClass *k = mono_object_class (this_arg);
+       MonoString *name;
+       char *str;
                        
-                       /* If this is a proxy, then it must be a CBO */
-                       if (mono_class_is_transparent_proxy (k)) {
-                               MonoTransparentProxy *tp = (MonoTransparentProxy*) this_arg;
-                               this_arg = tp->rp->unwrapped_server;
-                               g_assert (this_arg);
-                               k = mono_object_class (this_arg);
-                       }
+       /* If this is a proxy, then it must be a CBO */
+       if (mono_class_is_transparent_proxy (k)) {
+               MonoTransparentProxy *tp = (MonoTransparentProxy*) this_arg;
+               this_arg = tp->rp->unwrapped_server;
+               g_assert (this_arg);
+               k = mono_object_class (this_arg);
+       }
                        
-                       name = mono_array_get (params, MonoString *, 1);
-                       str = mono_string_to_utf8_checked (name, &error);
-                       if (mono_error_set_pending_exception (&error))
-                               return NULL;
+       name = mono_array_get (params, MonoString *, 1);
+       str = mono_string_to_utf8_checked (name, error);
+       return_if_nok (error);
                
-                       do {
-                               MonoClassField* field = mono_class_get_field_from_name (k, str);
-                               if (field) {
-                                       g_free (str);
-                                       MonoClass *field_klass =  mono_class_from_mono_type (field->type);
-                                       if (field_klass->valuetype) {
-                                               result = mono_value_box_checked (domain, field_klass, (char *)this_arg + field->offset, &error);
-                                               if (mono_error_set_pending_exception (&error))
-                                                       return NULL;
-                                       } else 
-                                               result = (MonoObject *)*((gpointer *)((char *)this_arg + field->offset));
-                               
-                                       out_args = mono_array_new_checked (domain, mono_defaults.object_class, 1, &error);
-                                       if (mono_error_set_pending_exception (&error))
-                                               return NULL;
-                                       mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
-                                       mono_array_setref (out_args, 0, result);
-                                       return NULL;
-                               }
-                               k = k->parent;
-                       } while (k);
-
+       do {
+               MonoClassField* field = mono_class_get_field_from_name (k, str);
+               if (field) {
                        g_free (str);
-                       g_assert_not_reached ();
+                       MonoClass *field_klass =  mono_class_from_mono_type (field->type);
+                       MonoObject *result;
+                       if (field_klass->valuetype) {
+                               result = mono_value_box_checked (domain, field_klass, (char *)this_arg + field->offset, error);
+                               return_if_nok (error);
+                       } else 
+                               result = (MonoObject *)*((gpointer *)((char *)this_arg + field->offset));
+
+                       out_args = mono_array_new_checked (domain, mono_defaults.object_class, 1, error);
+                       return_if_nok (error);
+                       mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
+                       mono_array_setref (out_args, 0, result);
+                       return;
+               }
+               k = k->parent;
+       } while (k);
 
-               } else if (!strcmp (m->name, "FieldSetter")) {
-                       MonoClass *k = mono_object_class (this_arg);
-                       MonoString *name;
-                       guint32 size;
-                       gint32 align;
-                       char *str;
+       g_free (str);
+       g_assert_not_reached ();
+}
+
+static void
+internal_execute_field_setter (MonoDomain *domain, MonoObject *this_arg, MonoArray *params, MonoArray **outArgs, MonoError *error)
+{
+       error_init (error);
+       MonoArray *out_args;
+       MonoClass *k = mono_object_class (this_arg);
+       MonoString *name;
+       guint32 size;
+       gint32 align;
+       char *str;
                        
-                       /* If this is a proxy, then it must be a CBO */
-                       if (mono_class_is_transparent_proxy (k)) {
-                               MonoTransparentProxy *tp = (MonoTransparentProxy*) this_arg;
-                               this_arg = tp->rp->unwrapped_server;
-                               g_assert (this_arg);
-                               k = mono_object_class (this_arg);
-                       }
+       /* If this is a proxy, then it must be a CBO */
+       if (mono_class_is_transparent_proxy (k)) {
+               MonoTransparentProxy *tp = (MonoTransparentProxy*) this_arg;
+               this_arg = tp->rp->unwrapped_server;
+               g_assert (this_arg);
+               k = mono_object_class (this_arg);
+       }
                        
-                       name = mono_array_get (params, MonoString *, 1);
-                       str = mono_string_to_utf8_checked (name, &error);
-                       if (mono_error_set_pending_exception (&error))
-                               return NULL;
+       name = mono_array_get (params, MonoString *, 1);
+       str = mono_string_to_utf8_checked (name, error);
+       return_if_nok (error);
                
-                       do {
-                               MonoClassField* field = mono_class_get_field_from_name (k, str);
-                               if (field) {
-                                       g_free (str);
-                                       MonoClass *field_klass =  mono_class_from_mono_type (field->type);
-                                       MonoObject *val = (MonoObject *)mono_array_get (params, gpointer, 2);
-
-                                       if (field_klass->valuetype) {
-                                               size = mono_type_size (field->type, &align);
-                                               g_assert (size == mono_class_value_size (field_klass, NULL));
-                                               mono_gc_wbarrier_value_copy ((char *)this_arg + field->offset, (char*)val + sizeof (MonoObject), 1, field_klass);
-                                       } else {
-                                               mono_gc_wbarrier_set_field (this_arg, (char*)this_arg + field->offset, val);
-                                       }
-                               
-                                       out_args = mono_array_new_checked (domain, mono_defaults.object_class, 0, &error);
-                                       if (mono_error_set_pending_exception (&error))
-                                               return NULL;
-                                       mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
+       do {
+               MonoClassField* field = mono_class_get_field_from_name (k, str);
+               if (field) {
+                       g_free (str);
+                       MonoClass *field_klass =  mono_class_from_mono_type (field->type);
+                       MonoObject *val = (MonoObject *)mono_array_get (params, gpointer, 2);
 
-                                       return NULL;
-                               }
+                       if (field_klass->valuetype) {
+                               size = mono_type_size (field->type, &align);
+                               g_assert (size == mono_class_value_size (field_klass, NULL));
+                               mono_gc_wbarrier_value_copy ((char *)this_arg + field->offset, (char*)val + sizeof (MonoObject), 1, field_klass);
+                       } else {
+                               mono_gc_wbarrier_set_field (this_arg, (char*)this_arg + field->offset, val);
+                       }
+
+                       out_args = mono_array_new_checked (domain, mono_defaults.object_class, 0, error);
+                       return_if_nok (error);
+                       mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
+                       return;
+               }
                                
-                               k = k->parent;
-                       } while (k);
+               k = k->parent;
+       } while (k);
 
-                       g_free (str);
-                       g_assert_not_reached ();
+       g_free (str);
+       g_assert_not_reached ();
+}
 
+ICALL_EXPORT MonoObject *
+ves_icall_InternalExecute (MonoReflectionMethod *method, MonoObject *this_arg, MonoArray *params, MonoArray **outArgs) 
+{
+       MonoError error;
+       MonoDomain *domain = mono_object_domain (method); 
+       MonoMethod *m = method->method;
+       MonoMethodSignature *sig = mono_method_signature (m);
+       MonoArray *out_args;
+       MonoObject *result;
+       int i, j, outarg_count = 0;
+
+       if (m->klass == mono_defaults.object_class) {
+               if (!strcmp (m->name, "FieldGetter")) {
+                       internal_execute_field_getter (domain, this_arg, params, outArgs, &error);
+                       mono_error_set_pending_exception (&error);
+                       return NULL;
+               } else if (!strcmp (m->name, "FieldSetter")) {
+                       internal_execute_field_setter (domain, this_arg, params, outArgs, &error);
+                       mono_error_set_pending_exception (&error);
+                       return NULL;
                }
        }
 
@@ -5405,7 +5471,7 @@ image_get_type (MonoDomain *domain, MonoImage *image, MonoTableInfo *tdef, int t
 
                MONO_HANDLE_ARRAY_SETREF (res, count, rt);
        } else {
-               MonoException *ex = mono_error_convert_to_exception (error);
+               MonoException *ex = mono_error_convert_to_exception (&klass_error);
                MONO_HANDLE_ARRAY_SETRAW (exceptions, count, ex);
        }
        HANDLE_FUNCTION_RETURN ();
@@ -6663,11 +6729,6 @@ ves_icall_System_Environment_Exit (int result)
 {
        mono_environment_exitcode_set (result);
 
-/* FIXME: There are some cleanup hangs that should be worked out, but
- * if the program is going to exit, everything will be cleaned up when
- * NaCl exits anyway.
- */
-#ifndef __native_client__
        if (!mono_runtime_try_shutdown ())
                mono_thread_exit ();
 
@@ -6675,7 +6736,6 @@ ves_icall_System_Environment_Exit (int result)
        mono_thread_suspend_all_other_threads ();
 
        mono_runtime_quit ();
-#endif
 
        /* we may need to do some cleanup here... */
        exit (result);
@@ -6911,54 +6971,56 @@ ves_icall_System_Runtime_Versioning_VersioningHelper_GetRuntimeId (void)
 
 #ifndef DISABLE_REMOTING
 ICALL_EXPORT MonoBoolean
-ves_icall_IsTransparentProxy (MonoObject *proxy)
+ves_icall_IsTransparentProxy (MonoObjectHandle proxy, MonoError *error)
 {
-       if (!proxy)
+       error_init (error);
+       if (MONO_HANDLE_IS_NULL (proxy))
                return 0;
 
-       if (mono_object_is_transparent_proxy (proxy))
+       if (mono_class_is_transparent_proxy (mono_handle_class (proxy)))
                return 1;
 
        return 0;
 }
 
-ICALL_EXPORT MonoReflectionMethod *
+ICALL_EXPORT MonoReflectionMethodHandle
 ves_icall_Remoting_RemotingServices_GetVirtualMethod (
-       MonoReflectionType *rtype, MonoReflectionMethod *rmethod)
+       MonoReflectionTypeHandle rtype, MonoReflectionMethodHandle rmethod, MonoError *error)
 {
-       MonoReflectionMethod *ret = NULL;
-       MonoError error;
-
-       MonoClass *klass;
-       MonoMethod *method;
-       MonoMethod **vtable;
-       MonoMethod *res = NULL;
+       MonoReflectionMethodHandle ret = MONO_HANDLE_CAST (MonoReflectionMethod, NULL_HANDLE);
 
-       MONO_CHECK_ARG_NULL (rtype, NULL);
-       MONO_CHECK_ARG_NULL (rmethod, NULL);
+       error_init (error);
+       if (MONO_HANDLE_IS_NULL (rtype)) {
+               mono_error_set_argument_null (error, "type", "");
+               return ret;
+       }
+       if (MONO_HANDLE_IS_NULL (rmethod)) {
+               mono_error_set_argument_null (error, "method", "");
+               return ret;
+       }
 
-       method = rmethod->method;
-       klass = mono_class_from_mono_type (rtype->type);
-       mono_class_init_checked (klass, &error);
-       if (mono_error_set_pending_exception (&error))
-               return NULL;
+       MonoMethod *method = MONO_HANDLE_GETVAL (rmethod, method);
+       MonoType *type = MONO_HANDLE_GETVAL (rtype, type);
+       MonoClass *klass = mono_class_from_mono_type (type);
+       mono_class_init_checked (klass, error);
+       return_val_if_nok (error, ret);
 
        if (MONO_CLASS_IS_INTERFACE (klass))
-               return NULL;
+               return ret;
 
        if (method->flags & METHOD_ATTRIBUTE_STATIC)
-               return NULL;
+               return ret;
 
        if ((method->flags & METHOD_ATTRIBUTE_FINAL) || !(method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
                if (klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE))
-                       return rmethod;
-               else
-                       return NULL;
+                       ret = rmethod;
+               return ret;
        }
 
        mono_class_setup_vtable (klass);
-       vtable = klass->vtable;
+       MonoMethod **vtable = klass->vtable;
 
+       MonoMethod *res = NULL;
        if (mono_class_is_interface (method->klass)) {
                gboolean variance_used = FALSE;
                /*MS fails with variant interfaces but it's the right thing to do anyway.*/
@@ -6967,33 +7029,27 @@ ves_icall_Remoting_RemotingServices_GetVirtualMethod (
                        res = vtable [offs + method->slot];
        } else {
                if (!(klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE)))
-                       return NULL;
+                       return ret;
 
                if (method->slot != -1)
                        res = vtable [method->slot];
        }
 
        if (!res)
-               return NULL;
+               return ret;
 
-       ret = mono_method_get_object_checked (mono_domain_get (), res, NULL, &error);
-       mono_error_set_pending_exception (&error);
+       ret = mono_method_get_object_handle (mono_domain_get (), res, NULL, error);
        return ret;
 }
 
 ICALL_EXPORT void
-ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (MonoReflectionType *type, MonoBoolean enable)
+ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (MonoReflectionTypeHandle type, MonoBoolean enable, MonoError *error)
 {
-       MonoError error;
-       MonoClass *klass;
-       MonoVTable* vtable;
+       error_init (error);
 
-       klass = mono_class_from_mono_type (type->type);
-       vtable = mono_class_vtable_full (mono_domain_get (), klass, &error);
-       if (!is_ok (&error)) {
-               mono_error_set_pending_exception (&error);
-               return;
-       }
+       MonoClass *klass = mono_class_from_mono_type (MONO_HANDLE_GETVAL (type, type));
+       MonoVTable *vtable = mono_class_vtable_full (mono_domain_get (), klass, error);
+       return_if_nok (error);
 
        mono_vtable_set_is_remote (vtable, enable);
 }
@@ -7001,48 +7057,38 @@ ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (Mo
 #else /* DISABLE_REMOTING */
 
 ICALL_EXPORT void
-ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (MonoReflectionType *type, MonoBoolean enable)
+ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (MonoReflectionTypeHandle type, MonoBoolean enable, MonoError *error)
 {
+       error_init (error);
        g_assert_not_reached ();
 }
 
 #endif
 
-ICALL_EXPORT MonoObject *
-ves_icall_System_Runtime_Activation_ActivationServices_AllocateUninitializedClassInstance (MonoReflectionType *type)
+ICALL_EXPORT MonoObjectHandle
+ves_icall_System_Runtime_Activation_ActivationServices_AllocateUninitializedClassInstance (MonoReflectionTypeHandle type, MonoError *error)
 {
-       MonoError error;
-       MonoClass *klass;
-       MonoDomain *domain;
-       MonoObject *ret;
+       error_init (error);
        
-       domain = mono_object_domain (type);
-       klass = mono_class_from_mono_type (type->type);
-       mono_class_init_checked (klass, &error);
-       if (mono_error_set_pending_exception (&error))
-               return NULL;
+       MonoDomain *domain = MONO_HANDLE_DOMAIN (type);
+       MonoClass *klass = mono_class_from_mono_type (MONO_HANDLE_GETVAL (type, type));
+       mono_class_init_checked (klass, error);
+       return_val_if_nok (error, NULL_HANDLE);
 
        if (MONO_CLASS_IS_INTERFACE (klass) || mono_class_is_abstract (klass)) {
-               mono_set_pending_exception (mono_get_exception_argument ("type", "Type cannot be instantiated"));
-               return NULL;
+               mono_error_set_argument (error, "type", "Type cannot be instantiated");
+               return NULL_HANDLE;
        }
 
        if (klass->rank >= 1) {
                g_assert (klass->rank == 1);
-               ret = (MonoObject *) mono_array_new_checked (domain, klass->element_class, 0, &error);
-               mono_error_set_pending_exception (&error);
-               return ret;
+               return MONO_HANDLE_CAST (MonoObject, mono_array_new_handle (domain, klass->element_class, 0, error));
        } else {
-               MonoVTable *vtable = mono_class_vtable_full (domain, klass, &error);
-               if (!is_ok (&error)) {
-                       mono_error_set_pending_exception (&error);
-                       return NULL;
-               }
-               /* Bypass remoting object creation check */
-               ret = mono_object_new_alloc_specific_checked (vtable, &error);
-               mono_error_set_pending_exception (&error);
+               MonoVTable *vtable = mono_class_vtable_full (domain, klass, error);
+               return_val_if_nok (error, NULL_HANDLE);
 
-               return ret;
+               /* Bypass remoting object creation check */
+               return MONO_HANDLE_NEW (MonoObject, mono_object_new_alloc_specific_checked (vtable, error));
        }
 }
 
@@ -7366,12 +7412,6 @@ mono_ArgIterator_IntGetNextArg (MonoArgIterator *iter)
        iter->args = (guint8*)(((gsize)iter->args + (align) - 1) & ~(align - 1));
 #endif
        res.value = iter->args;
-#if defined(__native_client__) && SIZEOF_REGISTER == 8
-       /* Values are stored as 8 byte register sized objects, but 'value'
-        * is dereferenced as a pointer in other routines.
-        */
-       res.value = (char*)res.value + 4;
-#endif
 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
        if (arg_size <= sizeof (gpointer)) {
                int dummy;
@@ -7832,7 +7872,7 @@ ves_icall_System_Runtime_InteropServices_Marshal_GetRawIUnknownForComObjectNoAdd
 }
 
 ICALL_EXPORT MonoObject*
-ves_icall_System_Runtime_InteropServices_WindowsRuntime_UnsafeNativeMethods_GetRestrictedErrorInfo()
+ves_icall_System_Runtime_InteropServices_WindowsRuntime_UnsafeNativeMethods_GetRestrictedErrorInfo(void)
 {
        mono_set_pending_exception(mono_get_exception_not_implemented("System.Runtime.InteropServices.WindowsRuntime.UnsafeNativeMethods.GetRestrictedErrorInfo internal call is not implemented."));
        return NULL;