#include "mono/utils/mono-memory-model.h"
#include "mono/utils/atomic.h"
#include <mono/utils/mono-threads.h>
+#include <mono/utils/mono-threads-coop.h>
#include <mono/utils/mono-error-internals.h>
#include <string.h>
static gboolean use_aot_wrappers;
-static MonoFtnPtrEHCallback ftnptr_eh_callback;
+static void ftnptr_eh_callback_default (guint32 gchandle);
+
+static MonoFtnPtrEHCallback ftnptr_eh_callback = ftnptr_eh_callback_default;
static void
delegate_hash_table_add (MonoDelegate *d);
+static void
+delegate_hash_table_remove (MonoDelegate *d);
+
static void
emit_struct_conv (MonoMethodBuilder *mb, MonoClass *klass, gboolean to_object);
void
mono_free_lparray (MonoArray *array, gpointer* nativeArray);
-static gint32
-mono_marshal_has_ftnptr_eh_callback (void);
-
static void
mono_marshal_ftnptr_eh_callback (guint32 gchandle);
return result;
}
+static MonoString*
+ves_icall_mono_string_from_utf16 (gunichar2 *data)
+{
+ MonoError error;
+ MonoString *result = mono_string_from_utf16_checked (data, &error);
+ mono_error_set_pending_exception (&error);
+ return result;
+}
+
+static char*
+ves_icall_mono_string_to_utf8 (MonoString *str)
+{
+ MonoError error;
+ char *result = mono_string_to_utf8_checked (str, &error);
+ mono_error_set_pending_exception (&error);
+ return result;
+}
+
void
mono_marshal_init (void)
{
register_icall (mono_marshal_string_to_utf16, "mono_marshal_string_to_utf16", "ptr obj", FALSE);
register_icall (mono_marshal_string_to_utf16_copy, "mono_marshal_string_to_utf16_copy", "ptr obj", FALSE);
register_icall (mono_string_to_utf16, "mono_string_to_utf16", "ptr obj", FALSE);
- register_icall (mono_string_from_utf16, "mono_string_from_utf16", "obj ptr", FALSE);
+ register_icall (ves_icall_mono_string_from_utf16, "ves_icall_mono_string_from_utf16", "obj ptr", FALSE);
register_icall (mono_string_from_byvalstr, "mono_string_from_byvalstr", "obj ptr int", FALSE);
register_icall (mono_string_from_byvalwstr, "mono_string_from_byvalwstr", "obj ptr int", FALSE);
register_icall (mono_string_new_wrapper, "mono_string_new_wrapper", "obj ptr", FALSE);
register_icall (mono_string_new_len_wrapper, "mono_string_new_len_wrapper", "obj ptr int", FALSE);
- register_icall (mono_string_to_utf8, "mono_string_to_utf8", "ptr obj", FALSE);
+ register_icall (ves_icall_mono_string_to_utf8, "ves_icall_mono_string_to_utf8", "ptr obj", FALSE);
register_icall (mono_string_to_lpstr, "mono_string_to_lpstr", "ptr obj", FALSE);
register_icall (mono_string_to_ansibstr, "mono_string_to_ansibstr", "ptr object", FALSE);
register_icall (mono_string_builder_to_utf8, "mono_string_builder_to_utf8", "ptr object", FALSE);
register_icall (mono_struct_delete_old, "mono_struct_delete_old", "void ptr ptr", FALSE);
register_icall (mono_delegate_begin_invoke, "mono_delegate_begin_invoke", "object object ptr", FALSE);
register_icall (mono_delegate_end_invoke, "mono_delegate_end_invoke", "object object ptr", FALSE);
- register_icall (mono_compile_method, "mono_compile_method", "ptr ptr", FALSE);
register_icall (mono_context_get, "mono_context_get", "object", FALSE);
register_icall (mono_context_set, "mono_context_set", "void object", FALSE);
register_icall (mono_gc_wbarrier_generic_nostore, "wb_generic", "void ptr", FALSE);
register_icall (mono_gchandle_get_target, "mono_gchandle_get_target", "object int32", TRUE);
register_icall (mono_gchandle_new, "mono_gchandle_new", "uint32 object bool", TRUE);
register_icall (mono_marshal_isinst_with_cache, "mono_marshal_isinst_with_cache", "object object ptr ptr", FALSE);
- register_icall (mono_marshal_has_ftnptr_eh_callback, "mono_marshal_has_ftnptr_eh_callback", "int32", TRUE);
register_icall (mono_marshal_ftnptr_eh_callback, "mono_marshal_ftnptr_eh_callback", "void uint32", TRUE);
+ register_icall (mono_threads_enter_gc_safe_region_unbalanced, "mono_threads_enter_gc_safe_region_unbalanced", "ptr ptr", TRUE);
+ register_icall (mono_threads_exit_gc_safe_region_unbalanced, "mono_threads_exit_gc_safe_region_unbalanced", "void ptr ptr", TRUE);
+ register_icall (mono_threads_attach_coop, "mono_threads_attach_coop", "ptr ptr ptr", TRUE);
+ register_icall (mono_threads_detach_coop, "mono_threads_detach_coop", "void ptr ptr", TRUE);
mono_cominterop_init ();
mono_remoting_init ();
-
- if (mono_threads_is_coop_enabled ()) {
- register_icall (mono_threads_prepare_blocking, "mono_threads_prepare_blocking", "ptr ptr", FALSE);
- register_icall (mono_threads_finish_blocking, "mono_threads_finish_blocking", "void ptr ptr", FALSE);
- register_icall (mono_threads_reset_blocking_start, "mono_threads_reset_blocking_start","ptr ptr", TRUE);
- register_icall (mono_threads_reset_blocking_end, "mono_threads_reset_blocking_end","void ptr ptr", TRUE);
- }
}
}
wrapper = mono_marshal_get_managed_wrapper (method, klass, target_handle);
- delegate->delegate_trampoline = mono_compile_method (wrapper);
+ delegate->delegate_trampoline = mono_compile_method_checked (wrapper, &error);
+ if (!is_ok (&error))
+ goto fail;
// Add the delegate to the delegate hash table
delegate_hash_table_add (delegate);
/* when the object is collected, collect the dynamic method, too */
- mono_object_register_finalizer ((MonoObject*)delegate, &error);
- if (!mono_error_ok (&error)) {
- mono_error_set_pending_exception (&error);
- return NULL;
- }
+ mono_object_register_finalizer ((MonoObject*)delegate);
return delegate->delegate_trampoline;
+
+fail:
+ mono_gchandle_free (target_handle);
+ mono_error_set_pending_exception (&error);
+ return NULL;
}
/*
mono_error_set_pending_exception (&error);
return NULL;
}
- mono_delegate_ctor_with_method ((MonoObject*)d, this_obj, mono_compile_method (wrapper), wrapper);
+ gpointer compiled_ptr = mono_compile_method_checked (wrapper, &error);
+ if (mono_error_set_pending_exception (&error))
+ return NULL;
+ mono_delegate_ctor_with_method ((MonoObject*)d, this_obj, compiled_ptr, wrapper, &error);
+ if (mono_error_set_pending_exception (&error))
+ return NULL;
}
if (d->object.vtable->domain != mono_domain_get ()) {
return as;
}
#else
- return mono_string_to_utf8 (s);
+ MonoError error;
+ char *result = mono_string_to_utf8_checked (s, &error);
+ mono_error_set_pending_exception (&error);
+ return result;
#endif
}
void
mono_string_to_byvalstr (gpointer dst, MonoString *src, int size)
{
+ MonoError error;
char *s;
int len;
if (!src)
return;
- s = mono_string_to_utf8 (src);
+ s = mono_string_to_utf8_checked (src, &error);
+ if (mono_error_set_pending_exception (&error))
+ return;
len = MIN (size, strlen (s));
if (len >= size)
len--;
} else {
mono_mb_emit_ldloc (mb, 1);
mono_mb_emit_ldloc (mb, 0);
- mono_mb_emit_icall (mb, mono_string_from_utf16);
+ mono_mb_emit_icall (mb, ves_icall_mono_string_from_utf16);
}
mono_mb_emit_byte (mb, CEE_STIND_REF);
break;
mono_mb_emit_ldloc (mb, 0);
mono_mb_emit_byte (mb, CEE_LDIND_I);
#ifdef TARGET_WIN32
- mono_mb_emit_icall (mb, mono_string_from_utf16);
+ mono_mb_emit_icall (mb, ves_icall_mono_string_from_utf16);
#else
mono_mb_emit_icall (mb, mono_string_new_wrapper);
#endif
mono_mb_emit_ldloc (mb, 1);
mono_mb_emit_ldloc (mb, 0);
mono_mb_emit_byte (mb, CEE_LDIND_I);
- mono_mb_emit_icall (mb, mono_string_from_utf16);
+ mono_mb_emit_icall (mb, ves_icall_mono_string_from_utf16);
mono_mb_emit_byte (mb, CEE_STIND_REF);
break;
case MONO_MARSHAL_CONV_OBJECT_STRUCT: {
return mono_marshal_string_to_utf16;
case MONO_MARSHAL_CONV_LPWSTR_STR:
*ind_store_type = CEE_STIND_REF;
- return mono_string_from_utf16;
+ return ves_icall_mono_string_from_utf16;
case MONO_MARSHAL_CONV_LPTSTR_STR:
*ind_store_type = CEE_STIND_REF;
return mono_string_new_wrapper;
return mono_string_to_bstr;
case MONO_MARSHAL_CONV_BSTR_STR:
*ind_store_type = CEE_STIND_REF;
- return mono_string_from_bstr;
+ return mono_string_from_bstr_icall;
case MONO_MARSHAL_CONV_STR_TBSTR:
case MONO_MARSHAL_CONV_STR_ANSIBSTR:
return mono_string_to_ansibstr;
MonoArray *out_args;
method = delegate->method;
- msg = mono_method_call_message_new (mono_marshal_method_from_wrapper (method), params, NULL, &async_callback, &state);
- ares = mono_async_result_new (mono_domain_get (), NULL, state, NULL, NULL);
+ msg = mono_method_call_message_new (mono_marshal_method_from_wrapper (method), params, NULL, &async_callback, &state, &error);
+ if (mono_error_set_pending_exception (&error))
+ return NULL;
+ ares = mono_async_result_new (mono_domain_get (), NULL, state, NULL, NULL, &error);
+ if (mono_error_set_pending_exception (&error))
+ return NULL;
MONO_OBJECT_SETREF (ares, async_delegate, (MonoObject *)delegate);
MONO_OBJECT_SETREF (ares, async_callback, (MonoObject *)async_callback);
MONO_OBJECT_SETREF (msg, async_result, ares);
sig = mono_signature_no_pinvoke (method);
- msg = mono_method_call_message_new (method, params, NULL, NULL, NULL);
+ msg = mono_method_call_message_new (method, params, NULL, NULL, NULL, &error);
+ if (mono_error_set_pending_exception (&error))
+ return NULL;
ares = (MonoAsyncResult *)mono_array_get (msg->args, gpointer, sig->param_count - 1);
if (ares == NULL) {
mono_error_set_pending_exception (&error);
return NULL;
}
- mono_message_init (domain, msg, delegate->method_info, NULL);
+ mono_message_init (domain, msg, delegate->method_info, NULL, &error);
+ if (mono_error_set_pending_exception (&error))
+ return NULL;
msg->call_type = CallType_EndInvoke;
MONO_OBJECT_SETREF (msg, async_result, ares);
res = mono_remoting_invoke ((MonoObject *)tp->rp, msg, &exc, &out_args, &error);
} else
#endif
{
- res = mono_threadpool_ms_end_invoke (ares, &out_args, &exc);
+ res = mono_threadpool_ms_end_invoke (ares, &out_args, &exc, &error);
+ if (mono_error_set_pending_exception (&error))
+ return NULL;
}
if (exc) {
if (((MonoException*)exc)->stack_trace) {
- char *strace = mono_string_to_utf8 (((MonoException*)exc)->stack_trace);
- char *tmp;
- tmp = g_strdup_printf ("%s\nException Rethrown at:\n", strace);
- g_free (strace);
- MONO_OBJECT_SETREF (((MonoException*)exc), stack_trace, mono_string_new (domain, tmp));
- g_free (tmp);
+ MonoError inner_error;
+ char *strace = mono_string_to_utf8_checked (((MonoException*)exc)->stack_trace, &inner_error);
+ if (is_ok (&inner_error)) {
+ char *tmp;
+ tmp = g_strdup_printf ("%s\nException Rethrown at:\n", strace);
+ g_free (strace);
+ MONO_OBJECT_SETREF (((MonoException*)exc), stack_trace, mono_string_new (domain, tmp));
+ g_free (tmp);
+ } else
+ mono_error_cleanup (&inner_error); /* no stack trace, but at least throw the original exception */
}
mono_set_pending_exception ((MonoException*)exc);
}
EmitMarshalContext m;
MonoMethodSignature *csig;
MonoClass *klass;
- MonoExceptionClause *clause;
int i, argnum, *tmp_locals;
int type, param_shift = 0;
- static MonoMethodSignature *get_last_error_sig = NULL;
- int coop_gc_stack_dummy, coop_gc_var, coop_unblocked_var;
- int leave_pos;
+ int coop_gc_stack_dummy, coop_gc_var;
memset (&m, 0, sizeof (m));
m.mb = mb;
coop_gc_stack_dummy = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
/* local 5, the local to be used when calling the suspend funcs */
coop_gc_var = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
- coop_unblocked_var = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
-
- clause = (MonoExceptionClause *)mono_image_alloc0 (image, sizeof (MonoExceptionClause));
- clause->flags = MONO_EXCEPTION_CLAUSE_FINALLY;
}
+ /*
+ * cookie = mono_threads_enter_gc_safe_region_unbalanced (ref dummy);
+ *
+ * ret = method (...);
+ *
+ * mono_threads_exit_gc_safe_region_unbalanced (cookie, ref dummy);
+ *
+ * <interrupt check>
+ *
+ * return ret;
+ */
+
if (MONO_TYPE_ISSTRUCT (sig->ret))
m.vtaddr_var = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
mono_mb_emit_byte (mb, CEE_POP); // Result not needed yet
}
- clause->try_offset = mono_mb_get_label (mb);
-
mono_mb_emit_ldloc_addr (mb, coop_gc_stack_dummy);
- mono_mb_emit_icall (mb, mono_threads_prepare_blocking);
+ mono_mb_emit_icall (mb, mono_threads_enter_gc_safe_region_unbalanced);
mono_mb_emit_stloc (mb, coop_gc_var);
}
#else
g_assert_not_reached ();
#endif
- }
- else {
+ } else {
if (aot) {
/* Reuse the ICALL_ADDR opcode for pinvokes too */
mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
/* Set LastError if needed */
if (piinfo->piflags & PINVOKE_ATTRIBUTE_SUPPORTS_LAST_ERROR) {
+#ifdef TARGET_WIN32
+ static MonoMethodSignature *get_last_error_sig = NULL;
if (!get_last_error_sig) {
get_last_error_sig = mono_metadata_signature_alloc (mono_defaults.corlib, 0);
get_last_error_sig->ret = &mono_defaults.int_class->byval_arg;
get_last_error_sig->pinvoke = 1;
}
-#ifdef TARGET_WIN32
- /*
+ /*
* Have to call GetLastError () early and without a wrapper, since various runtime components could
* clobber its value.
*/
#else
mono_mb_emit_icall (mb, mono_marshal_set_last_error);
#endif
- }
+ }
if (MONO_TYPE_ISSTRUCT (sig->ret)) {
MonoClass *klass = mono_class_from_mono_type (sig->ret);
if (mono_threads_is_coop_enabled ()) {
mono_mb_emit_ldloc (mb, coop_gc_var);
mono_mb_emit_ldloc_addr (mb, coop_gc_stack_dummy);
- mono_mb_emit_icall (mb, mono_threads_finish_blocking);
- mono_mb_emit_icon (mb, 1);
- mono_mb_emit_stloc (mb, coop_unblocked_var);
+ mono_mb_emit_icall (mb, mono_threads_exit_gc_safe_region_unbalanced);
}
/* convert the result */
mono_mb_emit_stloc (mb, 3);
}
- if (mono_threads_is_coop_enabled ()) {
- int pos;
-
- leave_pos = mono_mb_emit_branch (mb, CEE_LEAVE);
-
- clause->try_len = mono_mb_get_label (mb) - clause->try_offset;
- clause->handler_offset = mono_mb_get_label (mb);
-
- mono_mb_emit_ldloc (mb, coop_unblocked_var);
- mono_mb_emit_icon (mb, 1);
- pos = mono_mb_emit_branch (mb, CEE_BEQ);
-
- mono_mb_emit_ldloc (mb, coop_gc_var);
- mono_mb_emit_ldloc_addr (mb, coop_gc_stack_dummy);
- mono_mb_emit_icall (mb, mono_threads_finish_blocking);
-
- mono_mb_patch_branch (mb, pos);
-
- mono_mb_emit_byte (mb, CEE_ENDFINALLY);
-
- clause->handler_len = mono_mb_get_pos (mb) - clause->handler_offset;
-
- mono_mb_patch_branch (mb, leave_pos);
- }
-
/*
* Need to call this after converting the result since MONO_VTADDR needs
* to be adjacent to the call instruction.
mono_mb_emit_ldloc (mb, 3);
mono_mb_emit_byte (mb, CEE_RET);
-
- if (mono_threads_is_coop_enabled ()) {
- mono_mb_set_clauses (mb, 1, clause);
- }
}
#endif /* DISABLE_JIT */
#else
MonoMethodSignature *sig, *csig;
MonoExceptionClause *clauses, *clause_finally, *clause_catch;
- int i, *tmp_locals, ex_local, e_local;
- int leave_try_pos, leave_catch_pos, ex_m1_pos, rethrow_pos;
+ int i, *tmp_locals, ex_local, e_local, attach_cookie_local, attach_dummy_local;
+ int leave_try_pos, leave_catch_pos, ex_m1_pos;
gboolean closed = FALSE;
sig = m->sig;
ex_local = mono_mb_add_local (mb, &mono_defaults.uint32_class->byval_arg);
e_local = mono_mb_add_local (mb, &mono_defaults.exception_class->byval_arg);
+ attach_cookie_local = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
+ attach_dummy_local = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
+
/*
* guint32 ex = -1;
* try {
- * mono_jit_attach ();
+ * // does (STARTING|RUNNING|BLOCKING) -> RUNNING + set/switch domain
+ * mono_threads_attach_coop ();
*
* <interrupt check>
*
* ret = method (...);
* } catch (Exception e) {
- * if (!mono_marshal_has_ftnptr_eh_callback ())
- * throw e;
* ex = mono_gchandle_new (e, false);
* } finally {
- * mono_jit_detach ();
+ * // does RUNNING -> (RUNNING|BLOCKING) + unset/switch domain
+ * mono_threads_detach_coop ();
+ *
+ * if (ex != -1)
+ * mono_marshal_ftnptr_eh_callback (ex);
* }
- * if (ex != -1)
- * mono_marshal_ftnptr_eh_callback (ex);
*
* return ret;
*/
/* try { */
clause_catch->try_offset = clause_finally->try_offset = mono_mb_get_label (mb);
- /*
- * Might need to attach the thread to the JIT or change the
- * domain for the callback.
- *
- * Also does the (STARTING|BLOCKING|RUNNING) -> RUNNING thread state transtion
- *
- * mono_jit_attach ();
- */
- mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
- mono_mb_emit_byte (mb, CEE_MONO_JIT_ATTACH);
+ if (!mono_threads_is_coop_enabled ()) {
+ mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
+ mono_mb_emit_byte (mb, CEE_MONO_JIT_ATTACH);
+ } else {
+ /* mono_threads_attach_coop (); */
+ mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
+ mono_mb_emit_byte (mb, CEE_MONO_LDDOMAIN);
+ mono_mb_emit_ldloc_addr (mb, attach_dummy_local);
+ mono_mb_emit_icall (mb, mono_threads_attach_coop);
+ mono_mb_emit_stloc (mb, attach_cookie_local);
+ }
/* <interrupt check> */
emit_thread_interrupt_checkpoint (mb);
leave_try_pos = mono_mb_emit_branch (mb, CEE_LEAVE);
- /* } catch (Exception e) { */
+ /* } [endtry] */
+
+ /* catch (Exception e) { */
clause_catch->try_len = mono_mb_get_label (mb) - clause_catch->try_offset;
clause_catch->handler_offset = mono_mb_get_label (mb);
mono_mb_emit_stloc (mb, e_local);
- /* if (!mono_marshal_has_ftnptr_eh_callback ()) { */
- mono_mb_emit_icall (mb, mono_marshal_has_ftnptr_eh_callback);
- rethrow_pos = mono_mb_emit_branch (mb, CEE_BRTRUE);
-
- /* throw e; */
- mono_mb_emit_ldloc (mb, e_local);
- mono_mb_emit_byte (mb, CEE_THROW);
-
- /* } [endif] */
- mono_mb_patch_branch (mb, rethrow_pos);
-
/* ex = mono_gchandle_new (e, false); */
mono_mb_emit_ldloc (mb, e_local);
mono_mb_emit_icon (mb, 0);
/* } [endcatch] */
clause_catch->handler_len = mono_mb_get_pos (mb) - clause_catch->handler_offset;
- /* } finally { */
+ /* finally { */
clause_finally->try_len = mono_mb_get_label (mb) - clause_finally->try_offset;
clause_finally->handler_offset = mono_mb_get_label (mb);
- /*
- * Also does the RUNNING -> (BLOCKING|RUNNING) thread state transition
- *
- * mono_jit_detach ();
- */
- mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
- mono_mb_emit_byte (mb, CEE_MONO_JIT_DETACH);
-
- mono_mb_emit_byte (mb, CEE_ENDFINALLY);
-
- /* } [endfinally] */
- clause_finally->handler_len = mono_mb_get_pos (mb) - clause_finally->handler_offset;
-
- mono_mb_patch_branch (mb, leave_try_pos);
- mono_mb_patch_branch (mb, leave_catch_pos);
+ if (!mono_threads_is_coop_enabled ()) {
+ mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
+ mono_mb_emit_byte (mb, CEE_MONO_JIT_DETACH);
+ } else {
+ /* mono_threads_detach_coop (); */
+ mono_mb_emit_ldloc (mb, attach_cookie_local);
+ mono_mb_emit_ldloc_addr (mb, attach_dummy_local);
+ mono_mb_emit_icall (mb, mono_threads_detach_coop);
+ }
/* if (ex != -1) */
mono_mb_emit_ldloc (mb, ex_local);
/* [ex == -1] */
mono_mb_patch_branch (mb, ex_m1_pos);
+ mono_mb_emit_byte (mb, CEE_ENDFINALLY);
+
+ /* } [endfinally] */
+ clause_finally->handler_len = mono_mb_get_pos (mb) - clause_finally->handler_offset;
+
+ mono_mb_patch_branch (mb, leave_try_pos);
+ mono_mb_patch_branch (mb, leave_catch_pos);
+
/* return ret; */
if (m->retobj_var) {
mono_mb_emit_ldloc (mb, m->retobj_var);
mono_metadata_free_marshal_spec (mspecs [i]);
g_free (mspecs);
- return mono_compile_method (method);
+ gpointer compiled_ptr = mono_compile_method_checked (method, &error);
+ mono_error_assert_ok (&error);
+ return compiled_ptr;
}
sig = mono_method_signature (method);
method = mono_mb_create (mb, sig, param_count, NULL);
mono_mb_free (mb);
- return mono_compile_method (method);
+ gpointer compiled_ptr = mono_compile_method_checked (method, &error);
+ mono_error_assert_ok (&error);
+ return compiled_ptr;
}
#ifndef DISABLE_JIT
return cached;
}
+/* this is an icall */
static MonoObject *
mono_marshal_isinst_with_cache (MonoObject *obj, MonoClass *klass, uintptr_t *cache)
{
MonoError error;
MonoObject *isinst = mono_object_isinst_checked (obj, klass, &error);
- mono_error_raise_exception (&error); /* FIXME don't raise here */
+ if (mono_error_set_pending_exception (&error))
+ return NULL;
#ifndef DISABLE_REMOTING
if (obj->vtable->klass == mono_defaults.transparent_proxy_class)
int
ves_icall_System_Runtime_InteropServices_Marshal_OffsetOf (MonoReflectionType *type, MonoString *field_name)
{
+ MonoError error;
MonoMarshalType *info;
MonoClass *klass;
char *fname;
MONO_CHECK_ARG_NULL (type, 0);
MONO_CHECK_ARG_NULL (field_name, 0);
- fname = mono_string_to_utf8 (field_name);
+ fname = mono_string_to_utf8_checked (field_name, &error);
+ if (mono_error_set_pending_exception (&error))
+ return 0;
klass = mono_class_from_mono_type (type->type);
if (!mono_class_init (klass)) {
mono_set_pending_exception (mono_class_get_exception_for_failure (klass));
gpointer
ves_icall_System_Runtime_InteropServices_Marshal_StringToHGlobalAnsi (MonoString *string)
{
+ MonoError error;
#ifdef HOST_WIN32
char* tres, *ret;
size_t len;
- tres = mono_string_to_utf8 (string);
+ tres = mono_string_to_utf8_checked (string, &error);
+ if (mono_error_set_pending_exception (&error))
+ return NULL;
if (!tres)
return tres;
return ret;
#else
- return mono_string_to_utf8 (string);
+ char *ret = mono_string_to_utf8_checked (string, &error);
+ mono_error_set_pending_exception (&error);
+ return ret;
#endif
}
GHashTable *cache;
MonoMethod *res;
int i, param_count, sig_size, pos_leave;
- int coop_gc_var, coop_gc_dummy_local;
g_assert (method);
+ // FIXME: we need to store the exception into a MonoHandle
+ g_assert (!mono_threads_is_coop_enabled ());
+
klass = method->klass;
image = method->klass->image;
if (!MONO_TYPE_IS_VOID (sig->ret))
mono_mb_add_local (mb, sig->ret);
- if (mono_threads_is_coop_enabled ()) {
- /* local 4, the local to be used when calling the reset_blocking funcs */
- /* tons of code hardcode 3 to be the return var */
- coop_gc_var = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
- /* local 5, the local used to get a stack address for suspend funcs */
- coop_gc_dummy_local = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
- }
-
/* clear exception arg */
mono_mb_emit_ldarg (mb, param_count - 1);
mono_mb_emit_byte (mb, CEE_LDNULL);
mono_mb_emit_byte (mb, CEE_STIND_REF);
- if (mono_threads_is_coop_enabled ()) {
- /* FIXME this is technically wrong as the callback itself must be executed in gc unsafe context. */
- mono_mb_emit_ldloc_addr (mb, coop_gc_dummy_local);
- mono_mb_emit_icall (mb, mono_threads_reset_blocking_start);
- mono_mb_emit_stloc (mb, coop_gc_var);
- }
-
/* try */
clause = (MonoExceptionClause *)mono_image_alloc0 (image, sizeof (MonoExceptionClause));
clause->try_offset = mono_mb_get_label (mb);
mono_mb_emit_op (mb, CEE_BOX, mono_class_from_mono_type (sig->ret));
}
- if (mono_threads_is_coop_enabled ()) {
- /* XXX merge reset_blocking_end with detach */
- mono_mb_emit_ldloc (mb, coop_gc_var);
- mono_mb_emit_ldloc_addr (mb, coop_gc_dummy_local);
- mono_mb_emit_icall (mb, mono_threads_reset_blocking_end);
- }
-
mono_mb_emit_byte (mb, CEE_RET);
#endif
mono_marshal_unlock ();
}
-static gint32
-mono_marshal_has_ftnptr_eh_callback (void)
-{
- return ftnptr_eh_callback != NULL;
-}
-
static void
mono_marshal_ftnptr_eh_callback (guint32 gchandle)
{
ftnptr_eh_callback (gchandle);
}
+static void
+ftnptr_eh_callback_default (guint32 gchandle)
+{
+ MonoException *exc;
+ gpointer stackdata;
+
+ g_assert (gchandle >= 0);
+
+ mono_threads_enter_gc_unsafe_region_unbalanced (&stackdata);
+
+ exc = (MonoException*) mono_gchandle_get_target (gchandle);
+
+ mono_gchandle_free (gchandle);
+
+ mono_raise_exception (exc);
+}
+
/*
* mono_install_ftnptr_eh_callback:
*