Merge pull request #3335 from lambdageek/dev/system-reflection-assembly
[mono.git] / mono / metadata / object.c
index 5da5f6bbf33833dae7f001d288074a710f02b6ae..7bb2b43beaf795a85ecf1bcd9c94fb7804a30c98 100644 (file)
@@ -1905,7 +1905,7 @@ mono_class_vtable_full (MonoDomain *domain, MonoClass *klass, MonoError *error)
        g_assert (klass);
 
        if (mono_class_has_failure (klass)) {
-               mono_error_set_exception_instance (error, mono_class_get_exception_for_failure (klass));
+               mono_error_set_for_class_failure (error, klass);
                return NULL;
        }
 
@@ -1992,7 +1992,7 @@ mono_class_create_runtime_vtable (MonoDomain *domain, MonoClass *klass, MonoErro
                if (!mono_class_init (klass) || mono_class_has_failure (klass)) {
                        mono_domain_unlock (domain);
                        mono_loader_unlock ();
-                       mono_error_set_exception_instance (error, mono_class_get_exception_for_failure (klass));
+                       mono_error_set_for_class_failure (error, klass);
                        return NULL;
                }
        }
@@ -2013,7 +2013,7 @@ mono_class_create_runtime_vtable (MonoDomain *domain, MonoClass *klass, MonoErro
                                mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
                        mono_domain_unlock (domain);
                        mono_loader_unlock ();
-                       mono_error_set_exception_instance (error, mono_class_get_exception_for_failure (klass));
+                       mono_error_set_for_class_failure (error, klass);
                        return NULL;
                }
        }
@@ -2034,7 +2034,7 @@ mono_class_create_runtime_vtable (MonoDomain *domain, MonoClass *klass, MonoErro
        if (mono_class_has_failure (klass)) {
                mono_domain_unlock (domain);
                mono_loader_unlock ();
-               mono_error_set_exception_instance (error, mono_class_get_exception_for_failure (klass));
+               mono_error_set_for_class_failure (error, klass);
                return NULL;
        }
 
@@ -4165,22 +4165,14 @@ mono_runtime_set_main_args (int argc, char* argv[])
        return 0;
 }
 
-/**
- * mono_runtime_run_main:
- * @method: the method to start the application with (usually Main)
- * @argc: number of arguments from the command line
- * @argv: array of strings from the command line
- * @exc: excetption results
- *
- * Execute a standard Main() method (argc/argv contains the
- * executable name). This method also sets the command line argument value
- * needed by System.Environment.
- *
+/*
+ * Prepare an array of arguments in order to execute a standard Main()
+ * method (argc/argv contains the executable name). This method also
+ * sets the command line argument value needed by System.Environment.
  * 
  */
-int
-mono_runtime_run_main (MonoMethod *method, int argc, char* argv[],
-                      MonoObject **exc)
+static MonoArray*
+prepare_run_main (MonoMethod *method, int argc, char *argv[])
 {
        MONO_REQ_GC_UNSAFE_MODE;
 
@@ -4271,9 +4263,87 @@ mono_runtime_run_main (MonoMethod *method, int argc, char* argv[],
        
        mono_assembly_set_main (method->klass->image->assembly);
 
-       return mono_runtime_exec_main (method, args, exc);
+       return args;
+}
+
+/**
+ * mono_runtime_run_main:
+ * @method: the method to start the application with (usually Main)
+ * @argc: number of arguments from the command line
+ * @argv: array of strings from the command line
+ * @exc: excetption results
+ *
+ * Execute a standard Main() method (argc/argv contains the
+ * executable name). This method also sets the command line argument value
+ * needed by System.Environment.
+ *
+ * 
+ */
+int
+mono_runtime_run_main (MonoMethod *method, int argc, char* argv[],
+                      MonoObject **exc)
+{
+       MONO_REQ_GC_UNSAFE_MODE;
+
+       MonoError error;
+       MonoArray *args = prepare_run_main (method, argc, argv);
+       int res;
+       if (exc) {
+               res = mono_runtime_try_exec_main (method, args, exc);
+       } else {
+               res = mono_runtime_exec_main_checked (method, args, &error);
+               mono_error_raise_exception (&error); /* OK to throw, external only without a better alternative */
+       }
+       return res;
+}
+
+/**
+ * mono_runtime_run_main_checked:
+ * @method: the method to start the application with (usually Main)
+ * @argc: number of arguments from the command line
+ * @argv: array of strings from the command line
+ * @error: set on error
+ *
+ * Execute a standard Main() method (argc/argv contains the
+ * executable name). This method also sets the command line argument value
+ * needed by System.Environment.  On failure sets @error.
+ *
+ * 
+ */
+int
+mono_runtime_run_main_checked (MonoMethod *method, int argc, char* argv[],
+                              MonoError *error)
+{
+       mono_error_init (error);
+       MonoArray *args = prepare_run_main (method, argc, argv);
+       return mono_runtime_exec_main_checked (method, args, error);
+}
+
+/**
+ * mono_runtime_try_run_main:
+ * @method: the method to start the application with (usually Main)
+ * @argc: number of arguments from the command line
+ * @argv: array of strings from the command line
+ * @exc: set if Main throws an exception
+ * @error: set if Main can't be executed
+ *
+ * Execute a standard Main() method (argc/argv contains the executable
+ * name). This method also sets the command line argument value needed
+ * by System.Environment.  On failure sets @error if Main can't be
+ * executed or @exc if it threw and exception.
+ *
+ * 
+ */
+int
+mono_runtime_try_run_main (MonoMethod *method, int argc, char* argv[],
+                          MonoObject **exc)
+{
+       g_assert (exc);
+       MonoArray *args = prepare_run_main (method, argc, argv);
+       return mono_runtime_try_exec_main (method, args, exc);
 }
 
+
 static MonoObject*
 serialize_object (MonoObject *obj, gboolean *failure, MonoObject **exc)
 {
@@ -4632,28 +4702,13 @@ mono_runtime_exec_managed_code (MonoDomain *domain,
        mono_thread_manage ();
 }
 
-/*
- * Execute a standard Main() method (args doesn't contain the
- * executable name).
- */
-int
-mono_runtime_exec_main (MonoMethod *method, MonoArray *args, MonoObject **exc)
+static void
+prepare_thread_to_exec_main (MonoDomain *domain, MonoMethod *method)
 {
-       MONO_REQ_GC_UNSAFE_MODE;
-
-       MonoError error;
-       MonoDomain *domain;
-       gpointer pa [1];
-       int rval;
+       MonoInternalThread* thread = mono_thread_internal_current ();
        MonoCustomAttrInfo* cinfo;
        gboolean has_stathread_attribute;
-       MonoInternalThread* thread = mono_thread_internal_current ();
-
-       g_assert (args);
-
-       pa [0] = args;
 
-       domain = mono_object_domain (args);
        if (!domain->entry_assembly) {
                gchar *str;
                MonoAssembly *assembly;
@@ -4673,8 +4728,9 @@ mono_runtime_exec_main (MonoMethod *method, MonoArray *args, MonoObject **exc)
                }
        }
 
-       cinfo = mono_custom_attrs_from_method_checked (method, &error);
-       mono_error_cleanup (&error); /* FIXME warn here? */
+       MonoError cattr_error;
+       cinfo = mono_custom_attrs_from_method_checked (method, &cattr_error);
+       mono_error_cleanup (&cattr_error); /* FIXME warn here? */
        if (cinfo) {
                has_stathread_attribute = mono_custom_attrs_has_attr (cinfo, mono_class_get_sta_thread_attribute_class ());
                if (!cinfo->cached)
@@ -4689,39 +4745,80 @@ mono_runtime_exec_main (MonoMethod *method, MonoArray *args, MonoObject **exc)
        }
        mono_thread_init_apartment_state ();
 
+}
+
+static int
+do_exec_main_checked (MonoMethod *method, MonoArray *args, MonoError *error)
+{
+       MONO_REQ_GC_UNSAFE_MODE;
+
+       gpointer pa [1];
+       int rval;
+
+       mono_error_init (error);
+       g_assert (args);
+
+       pa [0] = args;
+
        /* FIXME: check signature of method */
        if (mono_method_signature (method)->ret->type == MONO_TYPE_I4) {
                MonoObject *res;
-               if (exc) {
-                       res = mono_runtime_try_invoke (method, NULL, pa, exc, &error);
-                       if (*exc == NULL && !mono_error_ok (&error))
-                               *exc = (MonoObject*) mono_error_convert_to_exception (&error);
-                       else
-                               mono_error_cleanup (&error);
-               } else {
-                       res = mono_runtime_invoke_checked (method, NULL, pa, &error);
-                       mono_error_raise_exception (&error); /* FIXME don't raise here */
+               res = mono_runtime_invoke_checked (method, NULL, pa, error);
+               if (is_ok (error))
+                       rval = *(guint32 *)((char *)res + sizeof (MonoObject));
+               else
+                       rval = -1;
+               mono_environment_exitcode_set (rval);
+       } else {
+               mono_runtime_invoke_checked (method, NULL, pa, error);
+
+               if (is_ok (error))
+                       rval = 0;
+               else {
+                       rval = -1;
                }
+       }
+       return rval;
+}
+
+static int
+do_try_exec_main (MonoMethod *method, MonoArray *args, MonoObject **exc)
+{
+       MONO_REQ_GC_UNSAFE_MODE;
+
+       gpointer pa [1];
+       int rval;
+
+       g_assert (args);
+       g_assert (exc);
+
+       pa [0] = args;
+
+       /* FIXME: check signature of method */
+       if (mono_method_signature (method)->ret->type == MONO_TYPE_I4) {
+               MonoError inner_error;
+               MonoObject *res;
+               res = mono_runtime_try_invoke (method, NULL, pa, exc, &inner_error);
+               if (*exc == NULL && !mono_error_ok (&inner_error))
+                       *exc = (MonoObject*) mono_error_convert_to_exception (&inner_error);
+               else
+                       mono_error_cleanup (&inner_error);
 
-               if (!exc || !*exc)
+               if (*exc == NULL)
                        rval = *(guint32 *)((char *)res + sizeof (MonoObject));
                else
                        rval = -1;
 
                mono_environment_exitcode_set (rval);
        } else {
-               if (exc) {
-                       mono_runtime_try_invoke (method, NULL, pa, exc, &error);
-                       if (*exc == NULL && !mono_error_ok (&error))
-                               *exc = (MonoObject*) mono_error_convert_to_exception (&error);
-                       else
-                               mono_error_cleanup (&error);
-               } else {
-                       mono_runtime_invoke_checked (method, NULL, pa, &error);
-                       mono_error_raise_exception (&error); /* FIXME don't raise here */
-               }
+               MonoError inner_error;
+               mono_runtime_try_invoke (method, NULL, pa, exc, &inner_error);
+               if (*exc == NULL && !mono_error_ok (&inner_error))
+                       *exc = (MonoObject*) mono_error_convert_to_exception (&inner_error);
+               else
+                       mono_error_cleanup (&inner_error);
 
-               if (!exc || !*exc)
+               if (*exc == NULL)
                        rval = 0;
                else {
                        /* If the return type of Main is void, only
@@ -4737,6 +4834,54 @@ mono_runtime_exec_main (MonoMethod *method, MonoArray *args, MonoObject **exc)
        return rval;
 }
 
+/*
+ * Execute a standard Main() method (args doesn't contain the
+ * executable name).
+ */
+int
+mono_runtime_exec_main (MonoMethod *method, MonoArray *args, MonoObject **exc)
+{
+       MonoError error;
+       prepare_thread_to_exec_main (mono_object_domain (args), method);
+       if (exc) {
+               int rval = do_try_exec_main (method, args, exc);
+               return rval;
+       } else {
+               int rval = do_exec_main_checked (method, args, &error);
+               mono_error_raise_exception (&error); /* OK to throw, external only with no better option */
+               return rval;
+       }
+}
+
+/*
+ * Execute a standard Main() method (args doesn't contain the
+ * executable name).
+ *
+ * On failure sets @error
+ */
+int
+mono_runtime_exec_main_checked (MonoMethod *method, MonoArray *args, MonoError *error)
+{
+       mono_error_init (error);
+       prepare_thread_to_exec_main (mono_object_domain (args), method);
+       return do_exec_main_checked (method, args, error);
+}
+
+/*
+ * Execute a standard Main() method (args doesn't contain the
+ * executable name).
+ *
+ * On failure sets @error if Main couldn't be executed, or @exc if it threw an exception.
+ */
+int
+mono_runtime_try_exec_main (MonoMethod *method, MonoArray *args, MonoObject **exc)
+{
+       prepare_thread_to_exec_main (mono_object_domain (args), method);
+       return do_try_exec_main (method, args, exc);
+}
+
+
+
 /** invoke_array_extract_argument:
  * @params: array of arguments to the method.
  * @i: the index of the argument to extract.
@@ -4891,7 +5036,7 @@ mono_runtime_invoke_array (MonoMethod *method, void *obj, MonoArray *params,
                }
        } else {
                MonoObject *result = mono_runtime_try_invoke_array (method, obj, params, NULL, &error);
-               mono_error_raise_exception (&error); /* FIXME don't raise here */
+               mono_error_raise_exception (&error); /* OK to throw, external only without a good alternative */
                return result;
        }
 }
@@ -6813,6 +6958,48 @@ mono_ldstr_metadata_sig (MonoDomain *domain, const char* sig, MonoError *error)
        return interned;
 }
 
+/*
+ * mono_ldstr_utf8:
+ *
+ *   Same as mono_ldstr, but return a NULL terminated utf8 string instead
+ * of an object.
+ */
+char*
+mono_ldstr_utf8 (MonoImage *image, guint32 idx, MonoError *error)
+{
+       const char *str;
+       size_t len2;
+       long written = 0;
+       char *as;
+       GError *gerror = NULL;
+
+       mono_error_init (error);
+
+       if (!mono_verifier_verify_string_signature (image, idx, NULL))
+               return NULL; /*FIXME we should probably be raising an exception here*/
+       str = mono_metadata_user_string (image, idx);
+
+       len2 = mono_metadata_decode_blob_size (str, &str);
+       len2 >>= 1;
+
+       as = g_utf16_to_utf8 ((guint16*)str, len2, NULL, &written, &gerror);
+       if (gerror) {
+               mono_error_set_argument (error, "string", "%s", gerror->message);
+               g_error_free (gerror);
+               return NULL;
+       }
+       /* g_utf16_to_utf8  may not be able to complete the convertion (e.g. NULL values were found, #335488) */
+       if (len2 > written) {
+               /* allocate the total length and copy the part of the string that has been converted */
+               char *as2 = (char *)g_malloc0 (len2);
+               memcpy (as2, as, written);
+               g_free (as);
+               as = as2;
+       }
+
+       return as;
+}
+
 /**
  * mono_string_to_utf8:
  * @s: a System.String
@@ -7378,88 +7565,24 @@ mono_message_init (MonoDomain *domain,
 {
        MONO_REQ_GC_UNSAFE_MODE;
 
-       static MonoClass *object_array_klass;
-       static MonoClass *byte_array_klass;
-       static MonoClass *string_array_klass;
-       mono_error_init (error);
-       MonoMethodSignature *sig = mono_method_signature (method->method);
-       MonoString *name;
-       MonoArray *arr;
-       int i, j;
-       char **names;
-       guint8 arg_type;
-
-       if (!object_array_klass) {
-               MonoClass *klass;
-
-               klass = mono_array_class_get (mono_defaults.byte_class, 1);
-               g_assert (klass);
-               byte_array_klass = klass;
-
-               klass = mono_array_class_get (mono_defaults.string_class, 1);
-               g_assert (klass);
-               string_array_klass = klass;
-
-               klass = mono_array_class_get (mono_defaults.object_class, 1);
-               g_assert (klass);
+       static MonoMethod *init_message_method = NULL;
 
-               mono_atomic_store_release (&object_array_klass, klass);
+       if (!init_message_method) {
+               init_message_method = mono_class_get_method_from_name (mono_defaults.mono_method_message_class, "InitMessage", 2);
+               g_assert (init_message_method != NULL);
        }
 
-       MONO_OBJECT_SETREF (this_obj, method, method);
-
-       arr = mono_array_new_specific_checked (mono_class_vtable (domain, object_array_klass), sig->param_count, error);
-       return_val_if_nok (error, FALSE);
-
-       MONO_OBJECT_SETREF (this_obj, args, arr);
-
-       arr = mono_array_new_specific_checked (mono_class_vtable (domain, byte_array_klass), sig->param_count, error);
-       return_val_if_nok (error, FALSE);
-
-       MONO_OBJECT_SETREF (this_obj, arg_types, arr);
-
-       this_obj->async_result = NULL;
-       this_obj->call_type = CallType_Sync;
-
-       names = g_new (char *, sig->param_count);
-       mono_method_get_param_names (method->method, (const char **) names);
-
-       arr = mono_array_new_specific_checked (mono_class_vtable (domain, string_array_klass), sig->param_count, error);
-       if (!is_ok (error))
-               goto fail;
-
-       MONO_OBJECT_SETREF (this_obj, names, arr);
+       mono_error_init (error);
+       /* FIXME set domain instead? */
+       g_assert (domain == mono_domain_get ());
        
-       for (i = 0; i < sig->param_count; i++) {
-               name = mono_string_new_checked (domain, names [i], error);
-               if (!is_ok (error))
-                       goto fail;
-               mono_array_setref (this_obj->names, i, name);   
-       }
+       gpointer args[2];
 
-       g_free (names);
-       for (i = 0, j = 0; i < sig->param_count; i++) {
-               if (sig->params [i]->byref) {
-                       if (out_args) {
-                               MonoObject* arg = (MonoObject *)mono_array_get (out_args, gpointer, j);
-                               mono_array_setref (this_obj->args, i, arg);
-                               j++;
-                       }
-                       arg_type = 2;
-                       if (!(sig->params [i]->attrs & PARAM_ATTRIBUTE_OUT))
-                               arg_type |= 1;
-               } else {
-                       arg_type = 1;
-                       if (sig->params [i]->attrs & PARAM_ATTRIBUTE_OUT)
-                               arg_type |= 4;
-               }
-               mono_array_set (this_obj->arg_types, guint8, i, arg_type);
-       }
+       args[0] = method;
+       args[1] = out_args;
 
-       return TRUE;
-fail:
-       g_free (names);
-       return FALSE;
+       mono_runtime_invoke_checked (init_message_method, this_obj, args, error);
+       return is_ok (error);
 }
 
 #ifndef DISABLE_REMOTING
@@ -8085,28 +8208,6 @@ mono_load_remote_field_new (MonoObject *this_obj, MonoClass *klass, MonoClassFie
        return result;
 }
 
-/**
- * mono_load_remote_field_new_icall:
- * @this: pointer to an object
- * @klass: klass of the object containing @field
- * @field: the field to load
- *
- * This method is called by the runtime on attempts to load fields of
- * transparent proxy objects. @this points to such TP, @klass is the class of
- * the object containing @field.
- * 
- * Returns: a freshly allocated object containing the value of the
- * field.  On failure returns NULL and throws an exception.
- */
-MonoObject *
-mono_load_remote_field_new_icall (MonoObject *this_obj, MonoClass *klass, MonoClassField *field)
-{
-       MonoError error;
-       MonoObject *result = mono_load_remote_field_new_checked (this_obj, klass, field, &error);
-       mono_error_set_pending_exception (&error);
-       return result;
-}
-
 /**
  * mono_load_remote_field_new_checked:
  * @this: pointer to an object
@@ -8127,69 +8228,25 @@ mono_load_remote_field_new_checked (MonoObject *this_obj, MonoClass *klass, Mono
 
        mono_error_init (error);
 
-       static MonoMethod *getter = NULL;
-       MonoDomain *domain = mono_domain_get ();
-       MonoTransparentProxy *tp = (MonoTransparentProxy *) this_obj;
-       MonoClass *field_class;
-       MonoMethodMessage *msg;
-       MonoArray *out_args;
-       MonoObject *exc, *res;
-       char* full_name;
+       static MonoMethod *tp_load = NULL;
 
        g_assert (mono_object_is_transparent_proxy (this_obj));
 
-       field_class = mono_class_from_mono_type (field->type);
-
-       if (mono_class_is_contextbound (tp->remote_class->proxy_class) && tp->rp->context == (MonoObject *) mono_context_get ()) {
-               gpointer val;
-               if (field_class->valuetype) {
-                       res = mono_object_new_checked (domain, field_class, error);
-                       return_val_if_nok (error, NULL);
-                       val = ((gchar *) res) + sizeof (MonoObject);
-               } else {
-                       val = &res;
-               }
-               mono_field_get_value (tp->rp->unwrapped_server, field, val);
-               return res;
-       }
-
-       if (!getter) {
-               getter = mono_class_get_method_from_name (mono_defaults.object_class, "FieldGetter", -1);
-               if (!getter) {
+       if (!tp_load) {
+               tp_load = mono_class_get_method_from_name (mono_defaults.transparent_proxy_class, "LoadRemoteFieldNew", -1);
+               if (!tp_load) {
                        mono_error_set_not_supported (error, "Linked away.");
                        return NULL;
                }
        }
        
-       msg = (MonoMethodMessage *)mono_object_new_checked (domain, mono_defaults.mono_method_message_class, error);
-       return_val_if_nok (error, NULL);
-       out_args = mono_array_new_checked (domain, mono_defaults.object_class, 1, error);
-       return_val_if_nok (error, NULL);
-
-       MonoReflectionMethod *rm = mono_method_get_object_checked (domain, getter, NULL, error);
-       return_val_if_nok (error, NULL);
-       mono_message_init (domain, msg, rm, out_args, error);
-       return_val_if_nok (error, NULL);
-
-       full_name = mono_type_get_full_name (klass);
-       mono_array_setref (msg->args, 0, mono_string_new (domain, full_name));
-       mono_array_setref (msg->args, 1, mono_string_new (domain, mono_field_get_name (field)));
-       g_free (full_name);
-
-       mono_remoting_invoke ((MonoObject *)(tp->rp), msg, &exc, &out_args, error);
-       return_val_if_nok (error, NULL);
+       /* MonoType *type = mono_class_get_type (klass); */
 
-       if (exc) {
-               mono_error_set_exception_instance (error, (MonoException *)exc);
-               return NULL;
-       }
-
-       if (mono_array_length (out_args) == 0)
-               res = NULL;
-       else
-               res = mono_array_get (out_args, MonoObject *, 0);
+       gpointer args[2];
+       args [0] = &klass;
+       args [1] = &field;
 
-       return res;
+       return mono_runtime_invoke_checked (tp_load, this_obj, args, error);
 }
 
 /**
@@ -8231,65 +8288,24 @@ mono_store_remote_field_checked (MonoObject *this_obj, MonoClass *klass, MonoCla
        
        MONO_REQ_GC_UNSAFE_MODE;
 
-       static MonoMethod *setter = NULL;
+       mono_error_init (error);
 
        MonoDomain *domain = mono_domain_get ();
-       MonoTransparentProxy *tp = (MonoTransparentProxy *) this_obj;
        MonoClass *field_class;
-       MonoMethodMessage *msg;
-       MonoArray *out_args;
-       MonoObject *exc;
        MonoObject *arg;
-       char* full_name;
-
-       mono_error_init (error);
 
        g_assert (mono_object_is_transparent_proxy (this_obj));
 
        field_class = mono_class_from_mono_type (field->type);
 
-       if (mono_class_is_contextbound (tp->remote_class->proxy_class) && tp->rp->context == (MonoObject *) mono_context_get ()) {
-               if (field_class->valuetype) mono_field_set_value (tp->rp->unwrapped_server, field, val);
-               else mono_field_set_value (tp->rp->unwrapped_server, field, *((MonoObject **)val));
-               return TRUE;
-       }
-
-       if (!setter) {
-               setter = mono_class_get_method_from_name (mono_defaults.object_class, "FieldSetter", -1);
-               if (!setter) {
-                       mono_error_set_not_supported (error, "Linked away.");
-                       return FALSE;
-               }
-       }
-
        if (field_class->valuetype) {
                arg = mono_value_box_checked (domain, field_class, val, error);
                return_val_if_nok (error, FALSE);
-       } else 
-               arg = *((MonoObject **)val);
-               
-
-       msg = (MonoMethodMessage *)mono_object_new_checked (domain, mono_defaults.mono_method_message_class, error);
-       return_val_if_nok (error, FALSE);
-       MonoReflectionMethod *rm = mono_method_get_object_checked (domain, setter, NULL, error);
-       return_val_if_nok (error, FALSE);
-       mono_message_init (domain, msg, rm, NULL, error);
-       return_val_if_nok (error, FALSE);
-
-       full_name = mono_type_get_full_name (klass);
-       mono_array_setref (msg->args, 0, mono_string_new (domain, full_name));
-       mono_array_setref (msg->args, 1, mono_string_new (domain, mono_field_get_name (field)));
-       mono_array_setref (msg->args, 2, arg);
-       g_free (full_name);
-
-       mono_remoting_invoke ((MonoObject *)(tp->rp), msg, &exc, &out_args, error);
-       return_val_if_nok (error, FALSE);
-
-       if (exc) {
-               mono_error_set_exception_instance (error, (MonoException *)exc);
-               return FALSE;
+       } else {
+               arg = *((MonoObject**)val);
        }
-       return TRUE;
+
+       return mono_store_remote_field_new_checked (this_obj, klass, field, arg, error);
 }
 
 /**
@@ -8309,23 +8325,6 @@ mono_store_remote_field_new (MonoObject *this_obj, MonoClass *klass, MonoClassFi
        mono_error_cleanup (&error);
 }
 
-/**
- * mono_store_remote_field_new_icall:
- * @this_obj:
- * @klass:
- * @field:
- * @arg:
- *
- * Missing documentation
- */
-void
-mono_store_remote_field_new_icall (MonoObject *this_obj, MonoClass *klass, MonoClassField *field, MonoObject *arg)
-{
-       MonoError error;
-       (void) mono_store_remote_field_new_checked (this_obj, klass, field, arg, &error);
-       mono_error_set_pending_exception (&error);
-}
-
 /**
  * mono_store_remote_field_new_checked:
  * @this_obj:
@@ -8341,56 +8340,27 @@ mono_store_remote_field_new_checked (MonoObject *this_obj, MonoClass *klass, Mon
 {
        MONO_REQ_GC_UNSAFE_MODE;
 
-       static MonoMethod *setter = NULL;
-       MonoDomain *domain = mono_domain_get ();
-       MonoTransparentProxy *tp = (MonoTransparentProxy *) this_obj;
-       MonoClass *field_class;
-       MonoMethodMessage *msg;
-       MonoArray *out_args;
-       MonoObject *exc;
-       char* full_name;
+       static MonoMethod *tp_store = NULL;
 
        mono_error_init (error);
 
        g_assert (mono_object_is_transparent_proxy (this_obj));
 
-       field_class = mono_class_from_mono_type (field->type);
-
-       if (mono_class_is_contextbound (tp->remote_class->proxy_class) && tp->rp->context == (MonoObject *) mono_context_get ()) {
-               if (field_class->valuetype) mono_field_set_value (tp->rp->unwrapped_server, field, ((gchar *) arg) + sizeof (MonoObject));
-               else mono_field_set_value (tp->rp->unwrapped_server, field, arg);
-               return TRUE;
-       }
-
-       if (!setter) {
-               setter = mono_class_get_method_from_name (mono_defaults.object_class, "FieldSetter", -1);
-               if (!setter) {
+       if (!tp_store) {
+               tp_store = mono_class_get_method_from_name (mono_defaults.transparent_proxy_class, "StoreRemoteField", -1);
+               if (!tp_store) {
                        mono_error_set_not_supported (error, "Linked away.");
                        return FALSE;
                }
        }
 
-       msg = (MonoMethodMessage *)mono_object_new_checked (domain, mono_defaults.mono_method_message_class, error);
-       return_val_if_nok (error, FALSE);
-       MonoReflectionMethod *rm = mono_method_get_object_checked (domain, setter, NULL, error);
-       return_val_if_nok (error, FALSE);
-       mono_message_init (domain, msg, rm, NULL, error);
-       return_val_if_nok (error, FALSE);
-
-       full_name = mono_type_get_full_name (klass);
-       mono_array_setref (msg->args, 0, mono_string_new (domain, full_name));
-       mono_array_setref (msg->args, 1, mono_string_new (domain, mono_field_get_name (field)));
-       mono_array_setref (msg->args, 2, arg);
-       g_free (full_name);
-
-       mono_remoting_invoke ((MonoObject *)(tp->rp), msg, &exc, &out_args, error);
-       return_val_if_nok (error, FALSE);
+       gpointer args[3];
+       args [0] = &klass;
+       args [1] = &field;
+       args [2] = arg;
 
-       if (exc) {
-               mono_error_set_exception_instance (error, (MonoException *)exc);
-               return FALSE;
-       }
-       return TRUE;
+       mono_runtime_invoke_checked (tp_store, this_obj, args, error);
+       return is_ok (error);
 }
 #endif