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);
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_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 ();
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 ()) {
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) {
#else
MonoMethodSignature *sig, *csig;
MonoExceptionClause *clauses, *clause_finally, *clause_catch;
- int i, *tmp_locals, ex_local, e_local;
+ 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;
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>
*
* } catch (Exception 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);
/* 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);
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);
+ 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);
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)