* Copyright 2004-2009 Novell, Inc (http://www.novell.com)
* Copyright 2011-2014 Xamarin, Inc (http://www.xamarin.com)
*
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
*/
#include "config.h"
static MonoMethod *method_set_call_context, *method_needs_context_sink, *method_rs_serialize_exc;
#endif
+static gpointer
+mono_compile_method_icall (MonoMethod *method);
+
static void
register_icall (gpointer func, const char *name, const char *sigstr, gboolean save)
{
register_icall (type_from_handle, "type_from_handle", "object ptr", FALSE);
register_icall (mono_marshal_set_domain_by_id, "mono_marshal_set_domain_by_id", "int32 int32 int32", FALSE);
register_icall (mono_marshal_check_domain_image, "mono_marshal_check_domain_image", "int32 int32 ptr", FALSE);
- register_icall (mono_marshal_xdomain_copy_value, "mono_marshal_xdomain_copy_value", "object object", FALSE);
+ register_icall (ves_icall_mono_marshal_xdomain_copy_value, "ves_icall_mono_marshal_xdomain_copy_value", "object object", FALSE);
register_icall (mono_marshal_xdomain_copy_out_value, "mono_marshal_xdomain_copy_out_value", "void object object", FALSE);
register_icall (mono_remoting_wrapper, "mono_remoting_wrapper", "object ptr ptr", FALSE);
register_icall (mono_upgrade_remote_class_wrapper, "mono_upgrade_remote_class_wrapper", "void object object", FALSE);
+ register_icall (mono_compile_method_icall, "mono_compile_method_icall", "ptr ptr", FALSE);
+ /* mono_load_remote_field_new_icall registered by mini-runtime.c */
+ /* mono_store_remote_field_new_icall registered by mini-runtime.c */
+
}
icalls_registered = TRUE;
module_initialized = TRUE;
}
+/* This is an icall, it will return NULL and set pending exception on failure */
static MonoReflectionType *
type_from_handle (MonoType *handle)
{
mono_class_init (klass);
ret = mono_type_get_object_checked (domain, handle, &error);
- mono_error_raise_exception (&error); /* FIXME don't raise here */
+ mono_error_set_pending_exception (&error);
return ret;
}
/* runtime_invoke expects a boxed instance */
if (mono_class_is_nullable (mono_class_from_mono_type (sig->params [i]))) {
mparams[i] = mono_nullable_box ((guint8 *)params [i], klass, &error);
- mono_error_raise_exception (&error); /* FIXME don't raise here */
+ if (!is_ok (&error))
+ goto fail;
} else
mparams[i] = params [i];
}
}
res = mono_runtime_invoke_checked (method, method->klass->valuetype? mono_object_unbox ((MonoObject*)this_obj): this_obj, mparams, &error);
- mono_error_raise_exception (&error); /* FIXME don't raise here */
+ if (!is_ok (&error))
+ goto fail;
return res;
}
- msg = mono_method_call_message_new (method, params, NULL, NULL, NULL);
+ msg = mono_method_call_message_new (method, params, NULL, NULL, NULL, &error);
+ if (!is_ok (&error))
+ goto fail;
res = mono_remoting_invoke ((MonoObject *)this_obj->rp, msg, &exc, &out_args, &error);
- mono_error_raise_exception (&error); /* FIXME don't raise here */
+ if (!is_ok (&error))
+ goto fail;
- if (exc)
- mono_raise_exception ((MonoException *)exc);
+ if (exc) {
+ mono_error_init (&error);
+ mono_error_set_exception_instance (&error, (MonoException *)exc);
+ goto fail;
+ }
- mono_method_return_message_restore (method, params, out_args);
+ mono_method_return_message_restore (method, params, out_args, &error);
+ if (!is_ok (&error)) goto fail;
return res;
+fail:
+ /* This icall will be called from managed code, and more over
+ * from a protected wrapper so interruptions such as pending
+ * exceptions will not be honored. (See
+ * is_running_protected_wrapper () in threads.c and
+ * mono_marshal_get_remoting_invoke () in remoting.c)
+ */
+ mono_error_raise_exception (&error); /* OK to throw, see note */
+ return NULL;
}
+
MonoMethod *
mono_marshal_get_remoting_invoke (MonoMethod *method)
{
mono_mb_emit_ptr (mb, method);
mono_mb_emit_ldloc (mb, params_var);
mono_mb_emit_icall (mb, mono_remoting_wrapper);
+ // FIXME: this interrupt checkpoint code is a no-op since 'mb'
+ // is a MONO_WRAPPER_REMOTING_INVOKE, and
+ // mono_thread_interruption_checkpoint_request (FALSE)
+ // considers such wrappers "protected" and always returns
+ // NULL as if there's no pending interruption.
mono_marshal_emit_thread_interrupt_checkpoint (mb);
if (sig->ret->type == MONO_TYPE_VOID) {
/* mono_marshal_xdomain_copy_out_value()
* Copies the contents of the src instance into the dst instance. src and dst
* must have the same type, and if they are arrays, the same size.
+ *
+ * This is an icall, it may use mono_error_set_pending_exception
*/
static void
mono_marshal_xdomain_copy_out_value (MonoObject *src, MonoObject *dst)
{
+ MonoError error;
if (src == NULL || dst == NULL) return;
g_assert (mono_object_class (src) == mono_object_class (dst));
int i, len = mono_array_length ((MonoArray *)dst);
for (i = 0; i < len; i++) {
MonoObject *item = (MonoObject *)mono_array_get ((MonoArray *)src, gpointer, i);
- mono_array_setref ((MonoArray *)dst, i, mono_marshal_xdomain_copy_value (item));
+ MonoObject *item_copy = mono_marshal_xdomain_copy_value (item, &error);
+ if (mono_error_set_pending_exception (&error))
+ return;
+ mono_array_setref ((MonoArray *)dst, i, item_copy);
}
} else {
mono_array_full_copy ((MonoArray *)src, (MonoArray *)dst);
static void
mono_marshal_emit_xdomain_copy_value (MonoMethodBuilder *mb, MonoClass *pclass)
{
- mono_mb_emit_icall (mb, mono_marshal_xdomain_copy_value);
+ mono_mb_emit_icall (mb, ves_icall_mono_marshal_xdomain_copy_value);
mono_mb_emit_op (mb, CEE_CASTCLASS, pclass);
}
MonoDomain *current_domain = mono_domain_get ();
MonoDomain *domain = mono_domain_get_by_id (id);
- if (!domain || !mono_domain_set (domain, FALSE))
- mono_raise_exception (mono_get_exception_appdomain_unloaded ());
+ if (!domain || !mono_domain_set (domain, FALSE)) {
+ mono_set_pending_exception (mono_get_exception_appdomain_unloaded ());
+ return 0;
+ }
if (push)
mono_thread_push_appdomain_ref (domain);
mono_mb_emit_icall (mb, mono_marshal_set_domain_by_id);
}
+gpointer
+mono_compile_method_icall (MonoMethod *method)
+{
+ MonoError error;
+ gpointer result = mono_compile_method_checked (method, &error);
+ mono_error_set_pending_exception (&error);
+ return result;
+}
+
/* mono_marshal_emit_load_domain_method ()
* Loads into the stack a pointer to the code of the provided method for
* the current domain.
* that compiles the method).
*/
mono_mb_emit_ptr (mb, method);
- mono_mb_emit_icall (mb, mono_compile_method);
+ mono_mb_emit_icall (mb, mono_compile_method_icall);
}
#endif
G_GNUC_UNUSED static gpointer
mono_marshal_load_remoting_wrapper (MonoRealProxy *rp, MonoMethod *method)
{
+ MonoError error;
+ MonoMethod *marshal_method = NULL;
if (rp->target_domain_id != -1)
- return mono_compile_method (mono_marshal_get_xappdomain_invoke (method));
+ marshal_method = mono_marshal_get_xappdomain_invoke (method);
else
- return mono_compile_method (mono_marshal_get_remoting_invoke (method));
+ marshal_method = mono_marshal_get_remoting_invoke (method);
+ gpointer compiled_ptr = mono_compile_method_checked (marshal_method, &error);
+ mono_error_assert_ok (&error);
+ return compiled_ptr;
}
MonoMethod *
MonoMethod *
mono_marshal_get_ldfld_remote_wrapper (MonoClass *klass)
{
- MonoMethodSignature *sig, *csig;
+ MonoMethodSignature *sig;
MonoMethodBuilder *mb;
MonoMethod *res;
static MonoMethod* cached = NULL;
mono_mb_emit_ldarg (mb, 1);
mono_mb_emit_ldarg (mb, 2);
- csig = mono_metadata_signature_alloc (mono_defaults.corlib, 3);
- csig->params [0] = &mono_defaults.object_class->byval_arg;
- csig->params [1] = &mono_defaults.int_class->byval_arg;
- csig->params [2] = &mono_defaults.int_class->byval_arg;
- csig->ret = &mono_defaults.object_class->byval_arg;
- csig->pinvoke = 1;
-
- mono_mb_emit_native_call (mb, csig, mono_load_remote_field_new);
- mono_marshal_emit_thread_interrupt_checkpoint (mb);
+ mono_mb_emit_icall (mb, mono_load_remote_field_new_icall);
mono_mb_emit_byte (mb, CEE_RET);
#endif
MonoMethod *
mono_marshal_get_stfld_remote_wrapper (MonoClass *klass)
{
- MonoMethodSignature *sig, *csig;
+ MonoMethodSignature *sig;
MonoMethodBuilder *mb;
MonoMethod *res;
static MonoMethod *cached = NULL;
mono_mb_emit_ldarg (mb, 2);
mono_mb_emit_ldarg (mb, 3);
- csig = mono_metadata_signature_alloc (mono_defaults.corlib, 4);
- csig->params [0] = &mono_defaults.object_class->byval_arg;
- csig->params [1] = &mono_defaults.int_class->byval_arg;
- csig->params [2] = &mono_defaults.int_class->byval_arg;
- csig->params [3] = &mono_defaults.object_class->byval_arg;
- csig->ret = &mono_defaults.void_class->byval_arg;
- csig->pinvoke = 1;
-
- mono_mb_emit_native_call (mb, csig, mono_store_remote_field_new);
- mono_marshal_emit_thread_interrupt_checkpoint (mb);
+ mono_mb_emit_icall (mb, mono_store_remote_field_new_icall);
mono_mb_emit_byte (mb, CEE_RET);
#endif
void
mono_upgrade_remote_class_wrapper (MonoReflectionType *rtype, MonoTransparentProxy *tproxy)
{
+ MonoError error;
MonoClass *klass;
MonoDomain *domain = ((MonoObject*)tproxy)->vtable->domain;
klass = mono_class_from_mono_type (rtype->type);
- mono_upgrade_remote_class (domain, (MonoObject*)tproxy, klass);
+ mono_upgrade_remote_class (domain, (MonoObject*)tproxy, klass, &error);
+ mono_error_set_pending_exception (&error);
}
#else /* DISABLE_REMOTING */
* Makes a copy of "val" suitable for the current domain.
*/
MonoObject *
-mono_marshal_xdomain_copy_value (MonoObject *val)
+mono_marshal_xdomain_copy_value (MonoObject *val, MonoError *error)
{
- MonoError error;
+ mono_error_init (error);
MonoDomain *domain;
if (val == NULL) return NULL;
case MONO_TYPE_U8:
case MONO_TYPE_R4:
case MONO_TYPE_R8: {
- MonoObject *res = mono_value_box_checked (domain, mono_object_class (val), ((char*)val) + sizeof(MonoObject), &error);
- mono_error_raise_exception (&error); /* FIXME don't raise here */
+ MonoObject *res = mono_value_box_checked (domain, mono_object_class (val), ((char*)val) + sizeof(MonoObject), error);
return res;
}
case MONO_TYPE_STRING: {
MonoString *str = (MonoString *) val;
MonoObject *res = NULL;
- res = (MonoObject *) mono_string_new_utf16_checked (domain, mono_string_chars (str), mono_string_length (str), &error);
- mono_error_raise_exception (&error); /* FIXME don't raise here */
+ res = (MonoObject *) mono_string_new_utf16_checked (domain, mono_string_chars (str), mono_string_length (str), error);
return res;
}
case MONO_TYPE_ARRAY:
MonoArray *acopy;
MonoXDomainMarshalType mt = mono_get_xdomain_marshal_type (&(mono_object_class (val)->element_class->byval_arg));
if (mt == MONO_MARSHAL_SERIALIZE) return NULL;
- acopy = mono_array_clone_in_domain (domain, (MonoArray *) val);
+ acopy = mono_array_clone_in_domain (domain, (MonoArray *) val, error);
+ return_val_if_nok (error, NULL);
+
if (mt == MONO_MARSHAL_COPY) {
int i, len = mono_array_length (acopy);
for (i = 0; i < len; i++) {
MonoObject *item = (MonoObject *)mono_array_get (acopy, gpointer, i);
- mono_array_setref (acopy, i, mono_marshal_xdomain_copy_value (item));
+ MonoObject *item_copy = mono_marshal_xdomain_copy_value (item, error);
+ return_val_if_nok (error, NULL);
+ mono_array_setref (acopy, i, item_copy);
}
}
return (MonoObject *) acopy;
return NULL;
}
+
+/* mono_marshal_xdomain_copy_value
+ * Makes a copy of "val" suitable for the current domain.
+ */
+MonoObject *
+ves_icall_mono_marshal_xdomain_copy_value (MonoObject *val)
+{
+ MonoError error;
+ MonoObject *result = mono_marshal_xdomain_copy_value (val, &error);
+ mono_error_set_pending_exception (&error);
+ return result;
+}