gpointer pa [2];
im = mono_class_get_method_from_name (rpklass, "CanCastTo", -1);
- if (!im)
- mono_raise_exception (mono_get_exception_not_supported ("Linked away."));
+ if (!im) {
+ mono_error_set_not_supported (error, "Linked away.");
+ return NULL;
+ }
im = mono_object_get_virtual_method (rp, im);
g_assert (im);
* Restore results from message based processing back to arguments pointers
*/
void
-mono_method_return_message_restore (MonoMethod *method, gpointer *params, MonoArray *out_args)
+mono_method_return_message_restore (MonoMethod *method, gpointer *params, MonoArray *out_args, MonoError *error)
{
MONO_REQ_GC_UNSAFE_MODE;
+ mono_error_init (error);
+
MonoMethodSignature *sig = mono_method_signature (method);
int i, j, type, size, out_len;
if (pt->byref) {
char *arg;
- if (j >= out_len)
- mono_raise_exception (mono_get_exception_execution_engine ("The proxy call returned an incorrect number of output arguments"));
+ if (j >= out_len) {
+ mono_error_set_execution_engine (error, "The proxy call returned an incorrect number of output arguments");
+ return;
+ }
arg = (char *)mono_array_get (out_args, gpointer, j);
type = pt->type;
gpointer
mono_load_remote_field (MonoObject *this_obj, MonoClass *klass, MonoClassField *field, gpointer *res)
{
- MONO_REQ_GC_UNSAFE_MODE;
-
MonoError error;
+ gpointer result = mono_load_remote_field_checked (this_obj, klass, field, res, &error);
+ mono_error_cleanup (&error);
+ return result;
+}
+
+/**
+ * mono_load_remote_field_checked:
+ * @this: pointer to an object
+ * @klass: klass of the object containing @field
+ * @field: the field to load
+ * @res: a storage to store the result
+ * @error: set on error
+ *
+ * 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. @res is a storage location which can be
+ * used to store the result.
+ *
+ * Returns: an address pointing to the value of field. On failure returns NULL and sets @error.
+ */
+gpointer
+mono_load_remote_field_checked (MonoObject *this_obj, MonoClass *klass, MonoClassField *field, gpointer *res, MonoError *error)
+{
+ MONO_REQ_GC_UNSAFE_MODE;
static MonoMethod *getter = NULL;
+
+ mono_error_init (error);
+
MonoDomain *domain = mono_domain_get ();
MonoTransparentProxy *tp = (MonoTransparentProxy *) this_obj;
MonoClass *field_class;
if (!getter) {
getter = mono_class_get_method_from_name (mono_defaults.object_class, "FieldGetter", -1);
- if (!getter)
- mono_raise_exception (mono_get_exception_not_supported ("Linked away."));
+ if (!getter) {
+ mono_error_set_not_supported (error, "Linked away.");
+ return NULL;
+ }
}
field_class = mono_class_from_mono_type (field->type);
- msg = (MonoMethodMessage *)mono_object_new_checked (domain, mono_defaults.mono_method_message_class, &error);
- mono_error_raise_exception (&error); /* FIXME don't raise here */
+ 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 (domain, mono_defaults.object_class, 1);
- MonoReflectionMethod *rm = mono_method_get_object_checked (domain, getter, NULL, &error);
- mono_error_raise_exception (&error); /* FIXME don't raise here */
+ 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);
full_name = mono_type_get_full_name (klass);
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);
- mono_error_raise_exception (&error); /* FIXME don't raise here */
+ mono_remoting_invoke ((MonoObject *)(tp->rp), msg, &exc, &out_args, error);
+ return_val_if_nok (error, NULL);
- if (exc) mono_raise_exception ((MonoException *)exc);
+ if (exc) {
+ mono_error_set_exception_instance (error, (MonoException *)exc);
+ return NULL;
+ }
if (mono_array_length (out_args) == 0)
return NULL;
- *res = mono_array_get (out_args, MonoObject *, 0); /* FIXME: GC write abrrier for res */
+ mono_gc_wbarrier_generic_store (res, mono_array_get (out_args, MonoObject *, 0));
if (field_class->valuetype) {
return ((char *)*res) + sizeof (MonoObject);
MonoObject *
mono_load_remote_field_new (MonoObject *this_obj, MonoClass *klass, MonoClassField *field)
{
- MONO_REQ_GC_UNSAFE_MODE;
+ MonoError error;
+ MonoObject *result = mono_load_remote_field_new_checked (this_obj, klass, field, &error);
+ mono_error_cleanup (&error);
+ 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
+ * @klass: klass of the object containing @field
+ * @field: the field to load
+ * @error: set on error.
+ *
+ * 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 sets @error.
+ */
+MonoObject *
+mono_load_remote_field_new_checked (MonoObject *this_obj, MonoClass *klass, MonoClassField *field, MonoError *error)
+{
+ MONO_REQ_GC_UNSAFE_MODE;
+
+ mono_error_init (error);
static MonoMethod *getter = NULL;
MonoDomain *domain = mono_domain_get ();
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);
- mono_error_raise_exception (&error); /* FIXME don't raise here */
+ res = mono_object_new_checked (domain, field_class, error);
+ return_val_if_nok (error, NULL);
val = ((gchar *) res) + sizeof (MonoObject);
} else {
val = &res;
if (!getter) {
getter = mono_class_get_method_from_name (mono_defaults.object_class, "FieldGetter", -1);
- if (!getter)
- mono_raise_exception (mono_get_exception_not_supported ("Linked away."));
+ if (!getter) {
+ mono_error_set_not_supported (error, "Linked away.");
+ return NULL;
+ }
}
- msg = (MonoMethodMessage *)mono_object_new_checked (domain, mono_defaults.mono_method_message_class, &error);
- mono_error_raise_exception (&error); /* FIXME don't raise here */
+ 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 (domain, mono_defaults.object_class, 1);
- MonoReflectionMethod *rm = mono_method_get_object_checked (domain, getter, NULL, &error);
- mono_error_raise_exception (&error); /* FIXME don't raise here */
+ 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);
full_name = mono_type_get_full_name (klass);
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);
- mono_error_raise_exception (&error); /* FIXME don't raise here */
+ mono_remoting_invoke ((MonoObject *)(tp->rp), msg, &exc, &out_args, error);
+ return_val_if_nok (error, NULL);
- if (exc) mono_raise_exception ((MonoException *)exc);
+ if (exc) {
+ mono_error_set_exception_instance (error, (MonoException *)exc);
+ return NULL;
+ }
if (mono_array_length (out_args) == 0)
res = NULL;
void
mono_store_remote_field (MonoObject *this_obj, MonoClass *klass, MonoClassField *field, gpointer val)
{
- MONO_REQ_GC_UNSAFE_MODE;
-
MonoError error;
+ (void) mono_store_remote_field_checked (this_obj, klass, field, val, &error);
+ mono_error_cleanup (&error);
+}
+
+/**
+ * mono_store_remote_field_checked:
+ * @this_obj: pointer to an object
+ * @klass: klass of the object containing @field
+ * @field: the field to load
+ * @val: the value/object to store
+ * @error: set on error
+ *
+ * This method is called by the runtime on attempts to store fields of
+ * transparent proxy objects. @this_obj points to such TP, @klass is the class of
+ * the object containing @field. @val is the new value to store in @field.
+ *
+ * Returns: on success returns TRUE, on failure returns FALSE and sets @error.
+ */
+gboolean
+mono_store_remote_field_checked (MonoObject *this_obj, MonoClass *klass, MonoClassField *field, gpointer val, MonoError *error)
+{
+
+ MONO_REQ_GC_UNSAFE_MODE;
static MonoMethod *setter = NULL;
+
MonoDomain *domain = mono_domain_get ();
MonoTransparentProxy *tp = (MonoTransparentProxy *) this_obj;
MonoClass *field_class;
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;
+ return TRUE;
}
if (!setter) {
setter = mono_class_get_method_from_name (mono_defaults.object_class, "FieldSetter", -1);
- if (!setter)
- mono_raise_exception (mono_get_exception_not_supported ("Linked away."));
+ 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);
- mono_error_raise_exception (&error); /* FIXME don't raise here */
+ 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);
- mono_error_raise_exception (&error); /* FIXME don't raise here */
- MonoReflectionMethod *rm = mono_method_get_object_checked (domain, setter, NULL, &error);
- mono_error_raise_exception (&error); /* FIXME don't raise here */
+ 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);
full_name = mono_type_get_full_name (klass);
mono_array_setref (msg->args, 2, arg);
g_free (full_name);
- mono_remoting_invoke ((MonoObject *)(tp->rp), msg, &exc, &out_args, &error);
- mono_error_raise_exception (&error); /* FIXME don't raise here */
+ mono_remoting_invoke ((MonoObject *)(tp->rp), msg, &exc, &out_args, error);
+ return_val_if_nok (error, FALSE);
- if (exc) mono_raise_exception ((MonoException *)exc);
+ if (exc) {
+ mono_error_set_exception_instance (error, (MonoException *)exc);
+ return FALSE;
+ }
+ return TRUE;
}
/**
void
mono_store_remote_field_new (MonoObject *this_obj, MonoClass *klass, MonoClassField *field, MonoObject *arg)
{
- MONO_REQ_GC_UNSAFE_MODE;
+ MonoError error;
+ (void) mono_store_remote_field_new_checked (this_obj, klass, field, arg, &error);
+ 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:
+ * @klass:
+ * @field:
+ * @arg:
+ * @error:
+ *
+ * Missing documentation
+ */
+gboolean
+mono_store_remote_field_new_checked (MonoObject *this_obj, MonoClass *klass, MonoClassField *field, MonoObject *arg, MonoError *error)
+{
+ MONO_REQ_GC_UNSAFE_MODE;
static MonoMethod *setter = NULL;
MonoDomain *domain = mono_domain_get ();
MonoObject *exc;
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, ((gchar *) arg) + sizeof (MonoObject));
else mono_field_set_value (tp->rp->unwrapped_server, field, arg);
- return;
+ return TRUE;
}
if (!setter) {
setter = mono_class_get_method_from_name (mono_defaults.object_class, "FieldSetter", -1);
- if (!setter)
- mono_raise_exception (mono_get_exception_not_supported ("Linked away."));
+ if (!setter) {
+ mono_error_set_not_supported (error, "Linked away.");
+ return FALSE;
+ }
}
- msg = (MonoMethodMessage *)mono_object_new_checked (domain, mono_defaults.mono_method_message_class, &error);
- mono_error_raise_exception (&error); /* FIXME don't raise here */
- MonoReflectionMethod *rm = mono_method_get_object_checked (domain, setter, NULL, &error);
- mono_error_raise_exception (&error); /* FIXME don't raise here */
+ 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);
full_name = mono_type_get_full_name (klass);
mono_array_setref (msg->args, 2, arg);
g_free (full_name);
- mono_remoting_invoke ((MonoObject *)(tp->rp), msg, &exc, &out_args, &error);
- mono_error_raise_exception (&error); /* FIXME don't raise here */
+ mono_remoting_invoke ((MonoObject *)(tp->rp), msg, &exc, &out_args, error);
+ return_val_if_nok (error, FALSE);
- if (exc) mono_raise_exception ((MonoException *)exc);
+ if (exc) {
+ mono_error_set_exception_instance (error, (MonoException *)exc);
+ return FALSE;
+ }
+ return TRUE;
}
#endif
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);
+ /* 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;
/* 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);
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);
+ 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) {
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);
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