X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mono%2Fmetadata%2Fmarshal.c;h=91fc1d62ac0bc0c1b17df7835eaec559d6f44f31;hb=875d3f6c5de16d96b5976f3b48079d43b5d57a10;hp=3d4e8146decc3263d8a87bbba9a445e391fcfb57;hpb=3e81958f1dd4cecb97167c5b3cb5541bda31c444;p=mono.git diff --git a/mono/metadata/marshal.c b/mono/metadata/marshal.c index 3d4e8146dec..91fc1d62ac0 100644 --- a/mono/metadata/marshal.c +++ b/mono/metadata/marshal.c @@ -79,9 +79,16 @@ static MonoNativeTlsKey load_type_info_tls_id; static gboolean use_aot_wrappers; +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); @@ -192,6 +199,9 @@ mono_array_to_lparray (MonoArray *array); void mono_free_lparray (MonoArray *array, gpointer* nativeArray); +static void +mono_marshal_ftnptr_eh_callback (guint32 gchandle); + /* Lazy class loading functions */ static GENERATE_GET_CLASS_WITH_CACHE (string_builder, System.Text, StringBuilder) static GENERATE_GET_CLASS_WITH_CACHE (date_time, System, DateTime) @@ -247,6 +257,15 @@ mono_object_isinst_icall (MonoObject *obj, MonoClass *klass) 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; +} + void mono_marshal_init (void) { @@ -261,7 +280,7 @@ 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); @@ -298,22 +317,20 @@ mono_marshal_init (void) 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_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); - } } } @@ -382,19 +399,22 @@ mono_delegate_to_ftnptr (MonoDelegate *delegate) 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; } /* @@ -559,7 +579,12 @@ mono_ftnptr_to_delegate (MonoClass *klass, gpointer ftn) 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 ()) { @@ -606,9 +631,11 @@ mono_delegate_free_ftnptr (MonoDelegate *delegate) } } +/* This is a JIT icall, it sets the pending exception and returns NULL on error */ static MonoString * mono_string_from_byvalstr (const char *data, int max_len) { + MonoError error; MonoDomain *domain = mono_domain_get (); int len = 0; @@ -618,7 +645,9 @@ mono_string_from_byvalstr (const char *data, int max_len) while (len < max_len - 1 && data [len]) len++; - return mono_string_new_len (domain, data, len); + MonoString *result = mono_string_new_len_checked (domain, data, len, &error); + mono_error_set_pending_exception (&error); + return result; } /* This is a JIT icall, it sets the pending exception and return NULL on error */ @@ -1126,10 +1155,14 @@ mono_string_to_byvalwstr (gpointer dst, MonoString *src, int size) *((gunichar2 *) dst + len) = 0; } +/* this is an icall, it sets the pending exception and returns NULL on error */ static MonoString* mono_string_new_len_wrapper (const char *text, guint length) { - return mono_string_new_len (mono_domain_get (), text, length); + MonoError error; + MonoString *result = mono_string_new_len_checked (mono_domain_get (), text, length, &error); + mono_error_set_pending_exception (&error); + return result; } #ifndef DISABLE_JIT @@ -1216,7 +1249,8 @@ guint mono_type_to_stind (MonoType *type) { if (type->byref) - return CEE_STIND_I; + return MONO_TYPE_IS_REFERENCE (type) ? CEE_STIND_REF : CEE_STIND_I; + handle_enum: switch (type->type) { @@ -1312,7 +1346,7 @@ emit_ptr_to_object_conv (MonoMethodBuilder *mb, MonoType *type, MonoMarshalConv mono_mb_emit_ldloc (mb, 1); mono_mb_emit_icon (mb, mspec->data.array_data.num_elem); mono_mb_emit_op (mb, CEE_NEWARR, eklass); - mono_mb_emit_byte (mb, CEE_STIND_I); + mono_mb_emit_byte (mb, CEE_STIND_REF); if (eklass->blittable) { /* copy the elements */ @@ -1422,7 +1456,7 @@ emit_ptr_to_object_conv (MonoMethodBuilder *mb, MonoType *type, MonoMarshalConv } 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; @@ -1431,7 +1465,7 @@ emit_ptr_to_object_conv (MonoMethodBuilder *mb, MonoType *type, MonoMarshalConv 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 @@ -1448,7 +1482,7 @@ emit_ptr_to_object_conv (MonoMethodBuilder *mb, MonoType *type, MonoMarshalConv 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: { @@ -1550,16 +1584,23 @@ emit_ptr_to_object_conv (MonoMethodBuilder *mb, MonoType *type, MonoMarshalConv } static gpointer -conv_to_icall (MonoMarshalConv conv) +conv_to_icall (MonoMarshalConv conv, int *ind_store_type) { + int dummy; + if (!ind_store_type) + ind_store_type = &dummy; + *ind_store_type = CEE_STIND_I; switch (conv) { case MONO_MARSHAL_CONV_STR_LPWSTR: return mono_marshal_string_to_utf16; case MONO_MARSHAL_CONV_LPWSTR_STR: - return mono_string_from_utf16; + *ind_store_type = CEE_STIND_REF; + return ves_icall_mono_string_from_utf16; case MONO_MARSHAL_CONV_LPTSTR_STR: + *ind_store_type = CEE_STIND_REF; return mono_string_new_wrapper; case MONO_MARSHAL_CONV_LPSTR_STR: + *ind_store_type = CEE_STIND_REF; return mono_string_new_wrapper; case MONO_MARSHAL_CONV_STR_LPTSTR: #ifdef TARGET_WIN32 @@ -1572,7 +1613,8 @@ conv_to_icall (MonoMarshalConv conv) case MONO_MARSHAL_CONV_STR_BSTR: return mono_string_to_bstr; case MONO_MARSHAL_CONV_BSTR_STR: - return mono_string_from_bstr; + *ind_store_type = CEE_STIND_REF; + return mono_string_from_bstr_icall; case MONO_MARSHAL_CONV_STR_TBSTR: case MONO_MARSHAL_CONV_STR_ANSIBSTR: return mono_string_to_ansibstr; @@ -1595,16 +1637,20 @@ conv_to_icall (MonoMarshalConv conv) case MONO_MARSHAL_CONV_DEL_FTN: return mono_delegate_to_ftnptr; case MONO_MARSHAL_CONV_FTN_DEL: + *ind_store_type = CEE_STIND_REF; return mono_ftnptr_to_delegate; case MONO_MARSHAL_CONV_LPSTR_SB: + *ind_store_type = CEE_STIND_REF; return mono_string_utf8_to_builder; case MONO_MARSHAL_CONV_LPTSTR_SB: + *ind_store_type = CEE_STIND_REF; #ifdef TARGET_WIN32 return mono_string_utf16_to_builder; #else return mono_string_utf8_to_builder; #endif case MONO_MARSHAL_CONV_LPWSTR_SB: + *ind_store_type = CEE_STIND_REF; return mono_string_utf16_to_builder; case MONO_MARSHAL_FREE_ARRAY: return mono_marshal_free_array; @@ -1623,6 +1669,7 @@ static void emit_object_to_ptr_conv (MonoMethodBuilder *mb, MonoType *type, MonoMarshalConv conv, MonoMarshalSpec *mspec) { int pos; + int stind_op; switch (conv) { case MONO_MARSHAL_CONV_BOOL_I4: @@ -1657,8 +1704,8 @@ emit_object_to_ptr_conv (MonoMethodBuilder *mb, MonoType *type, MonoMarshalConv mono_mb_emit_ldloc (mb, 1); mono_mb_emit_ldloc (mb, 0); mono_mb_emit_byte (mb, CEE_LDIND_REF); - mono_mb_emit_icall (mb, conv_to_icall (conv)); - mono_mb_emit_byte (mb, CEE_STIND_I); + mono_mb_emit_icall (mb, conv_to_icall (conv, &stind_op)); + mono_mb_emit_byte (mb, stind_op); break; } case MONO_MARSHAL_CONV_ARRAY_SAVEARRAY: @@ -1667,8 +1714,8 @@ emit_object_to_ptr_conv (MonoMethodBuilder *mb, MonoType *type, MonoMarshalConv mono_mb_emit_ldloc (mb, 1); mono_mb_emit_ldloc (mb, 0); mono_mb_emit_byte (mb, CEE_LDIND_REF); - mono_mb_emit_icall (mb, conv_to_icall (conv)); - mono_mb_emit_byte (mb, CEE_STIND_I); + mono_mb_emit_icall (mb, conv_to_icall (conv, &stind_op)); + mono_mb_emit_byte (mb, stind_op); break; case MONO_MARSHAL_CONV_STR_BYVALSTR: case MONO_MARSHAL_CONV_STR_BYVALWSTR: { @@ -1678,7 +1725,7 @@ emit_object_to_ptr_conv (MonoMethodBuilder *mb, MonoType *type, MonoMarshalConv mono_mb_emit_ldloc (mb, 0); mono_mb_emit_byte (mb, CEE_LDIND_REF); /* src String */ mono_mb_emit_icon (mb, mspec->data.array_data.num_elem); - mono_mb_emit_icall (mb, conv_to_icall (conv)); + mono_mb_emit_icall (mb, conv_to_icall (conv, NULL)); break; } case MONO_MARSHAL_CONV_ARRAY_BYVALARRAY: { @@ -1940,8 +1987,9 @@ emit_struct_conv_full (MonoMethodBuilder *mb, MonoClass *klass, gboolean to_obje case MONO_MARSHAL_CONV_NONE: { int t; - if (ftype->byref || ftype->type == MONO_TYPE_I || - ftype->type == MONO_TYPE_U) { + //XXX a byref field!?!? that's not allowed! and worse, it might miss a WB + g_assert (!ftype->byref); + if (ftype->type == MONO_TYPE_I || ftype->type == MONO_TYPE_U) { mono_mb_emit_ldloc (mb, 1); mono_mb_emit_ldloc (mb, 0); mono_mb_emit_byte (mb, CEE_LDIND_I); @@ -2188,8 +2236,12 @@ mono_delegate_begin_invoke (MonoDelegate *delegate, gpointer *params) 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); @@ -2916,7 +2968,9 @@ mono_delegate_end_invoke (MonoDelegate *delegate, gpointer *params) 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) { @@ -2938,7 +2992,9 @@ mono_delegate_end_invoke (MonoDelegate *delegate, gpointer *params) 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); @@ -2949,7 +3005,9 @@ mono_delegate_end_invoke (MonoDelegate *delegate, gpointer *params) } 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) { @@ -2964,7 +3022,8 @@ mono_delegate_end_invoke (MonoDelegate *delegate, gpointer *params) mono_set_pending_exception ((MonoException*)exc); } - mono_method_return_message_restore (method, params, out_args); + mono_method_return_message_restore (method, params, out_args, &error); + mono_error_set_pending_exception (&error); return res; } @@ -5109,7 +5168,7 @@ emit_marshal_string (EmitMarshalContext *m, int argnum, MonoType *t, char *msg = g_strdup_printf ("string marshalling conversion %d not implemented", encoding); mono_mb_emit_exception_marshal_directive (mb, msg); } else { - mono_mb_emit_icall (mb, conv_to_icall (conv)); + mono_mb_emit_icall (mb, conv_to_icall (conv, NULL)); mono_mb_emit_stloc (mb, conv_arg); } @@ -5150,10 +5209,11 @@ emit_marshal_string (EmitMarshalContext *m, int argnum, MonoType *t, mono_mb_emit_icall (mb, mono_string_new_len_wrapper); mono_mb_emit_byte (mb, CEE_STIND_REF); } else if (t->byref && (t->attrs & PARAM_ATTRIBUTE_OUT || !(t->attrs & PARAM_ATTRIBUTE_IN))) { + int stind_op; mono_mb_emit_ldarg (mb, argnum); mono_mb_emit_ldloc (mb, conv_arg); - mono_mb_emit_icall (mb, conv_to_icall (conv)); - mono_mb_emit_byte (mb, CEE_STIND_REF); + mono_mb_emit_icall (mb, conv_to_icall (conv, &stind_op)); + mono_mb_emit_byte (mb, stind_op); need_free = TRUE; } @@ -5184,7 +5244,7 @@ emit_marshal_string (EmitMarshalContext *m, int argnum, MonoType *t, } mono_mb_emit_ldloc (mb, 0); - mono_mb_emit_icall (mb, conv_to_icall (conv)); + mono_mb_emit_icall (mb, conv_to_icall (conv, NULL)); mono_mb_emit_stloc (mb, 3); /* free the string */ @@ -5215,27 +5275,28 @@ emit_marshal_string (EmitMarshalContext *m, int argnum, MonoType *t, mono_mb_emit_ldarg (mb, argnum); if (t->byref) mono_mb_emit_byte (mb, CEE_LDIND_I); - mono_mb_emit_icall (mb, conv_to_icall (conv)); + mono_mb_emit_icall (mb, conv_to_icall (conv, NULL)); mono_mb_emit_stloc (mb, conv_arg); break; case MARSHAL_ACTION_MANAGED_CONV_OUT: if (t->byref) { if (conv_arg) { + int stind_op; mono_mb_emit_ldarg (mb, argnum); mono_mb_emit_ldloc (mb, conv_arg); - mono_mb_emit_icall (mb, conv_to_icall (conv)); - mono_mb_emit_byte (mb, CEE_STIND_I); + mono_mb_emit_icall (mb, conv_to_icall (conv, &stind_op)); + mono_mb_emit_byte (mb, stind_op); } } break; case MARSHAL_ACTION_MANAGED_CONV_RESULT: - if (conv_to_icall (conv) == mono_marshal_string_to_utf16) + if (conv_to_icall (conv, NULL) == mono_marshal_string_to_utf16) /* We need to make a copy so the caller is able to free it */ mono_mb_emit_icall (mb, mono_marshal_string_to_utf16_copy); else - mono_mb_emit_icall (mb, conv_to_icall (conv)); + mono_mb_emit_icall (mb, conv_to_icall (conv, NULL)); mono_mb_emit_stloc (mb, 3); break; @@ -5514,7 +5575,7 @@ emit_marshal_object (EmitMarshalContext *m, int argnum, MonoType *t, mono_mb_emit_stloc (mb, conv_arg); } else { mono_mb_emit_ldarg (mb, argnum); - mono_mb_emit_icall (mb, conv_to_icall (MONO_MARSHAL_CONV_DEL_FTN)); + mono_mb_emit_icall (mb, conv_to_icall (MONO_MARSHAL_CONV_DEL_FTN, NULL)); mono_mb_emit_stloc (mb, conv_arg); } } else if (klass == mono_defaults.stringbuilder_class) { @@ -5544,7 +5605,7 @@ emit_marshal_object (EmitMarshalContext *m, int argnum, MonoType *t, if (t->byref) mono_mb_emit_byte (mb, CEE_LDIND_I); - mono_mb_emit_icall (mb, conv_to_icall (conv)); + mono_mb_emit_icall (mb, conv_to_icall (conv, NULL)); mono_mb_emit_stloc (mb, conv_arg); } else if (klass->blittable) { mono_mb_emit_byte (mb, CEE_LDNULL); @@ -5646,7 +5707,7 @@ emit_marshal_object (EmitMarshalContext *m, int argnum, MonoType *t, mono_mb_emit_ldarg (mb, argnum); mono_mb_emit_ldloc (mb, conv_arg); - mono_mb_emit_icall (mb, conv_to_icall (conv)); + mono_mb_emit_icall (mb, conv_to_icall (conv, NULL)); } if (need_free) { @@ -5662,7 +5723,7 @@ emit_marshal_object (EmitMarshalContext *m, int argnum, MonoType *t, mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX); mono_mb_emit_op (mb, CEE_MONO_CLASSCONST, klass); mono_mb_emit_ldloc (mb, conv_arg); - mono_mb_emit_icall (mb, conv_to_icall (MONO_MARSHAL_CONV_FTN_DEL)); + mono_mb_emit_icall (mb, conv_to_icall (MONO_MARSHAL_CONV_FTN_DEL, NULL)); mono_mb_emit_byte (mb, CEE_STIND_REF); } break; @@ -5745,7 +5806,7 @@ emit_marshal_object (EmitMarshalContext *m, int argnum, MonoType *t, mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX); mono_mb_emit_op (mb, CEE_MONO_CLASSCONST, klass); mono_mb_emit_ldloc (mb, 0); - mono_mb_emit_icall (mb, conv_to_icall (MONO_MARSHAL_CONV_FTN_DEL)); + mono_mb_emit_icall (mb, conv_to_icall (MONO_MARSHAL_CONV_FTN_DEL, NULL)); mono_mb_emit_stloc (mb, 3); } else { /* set src */ @@ -5795,7 +5856,7 @@ emit_marshal_object (EmitMarshalContext *m, int argnum, MonoType *t, mono_mb_emit_ldarg (mb, argnum); if (t->byref) mono_mb_emit_byte (mb, CEE_LDIND_I); - mono_mb_emit_icall (mb, conv_to_icall (MONO_MARSHAL_CONV_FTN_DEL)); + mono_mb_emit_icall (mb, conv_to_icall (MONO_MARSHAL_CONV_FTN_DEL, NULL)); mono_mb_emit_stloc (mb, conv_arg); break; } @@ -5869,10 +5930,11 @@ emit_marshal_object (EmitMarshalContext *m, int argnum, MonoType *t, case MARSHAL_ACTION_MANAGED_CONV_OUT: if (klass->delegate) { if (t->byref) { + int stind_op; mono_mb_emit_ldarg (mb, argnum); mono_mb_emit_ldloc (mb, conv_arg); - mono_mb_emit_icall (mb, conv_to_icall (MONO_MARSHAL_CONV_DEL_FTN)); - mono_mb_emit_byte (mb, CEE_STIND_I); + mono_mb_emit_icall (mb, conv_to_icall (MONO_MARSHAL_CONV_DEL_FTN, &stind_op)); + mono_mb_emit_byte (mb, stind_op); break; } } @@ -5931,7 +5993,7 @@ emit_marshal_object (EmitMarshalContext *m, int argnum, MonoType *t, case MARSHAL_ACTION_MANAGED_CONV_RESULT: if (klass->delegate) { - mono_mb_emit_icall (mb, conv_to_icall (MONO_MARSHAL_CONV_DEL_FTN)); + mono_mb_emit_icall (mb, conv_to_icall (MONO_MARSHAL_CONV_DEL_FTN, NULL)); mono_mb_emit_stloc (mb, 3); break; } @@ -6148,7 +6210,7 @@ emit_marshal_array (EmitMarshalContext *m, int argnum, MonoType *t, mono_mb_emit_ldarg (mb, argnum); if (t->byref) mono_mb_emit_byte (mb, CEE_LDIND_I); - mono_mb_emit_icall (mb, conv_to_icall (MONO_MARSHAL_CONV_ARRAY_LPARRAY)); + mono_mb_emit_icall (mb, conv_to_icall (MONO_MARSHAL_CONV_ARRAY_LPARRAY, NULL)); mono_mb_emit_stloc (mb, conv_arg); } else { MonoClass *eklass; @@ -6228,12 +6290,13 @@ emit_marshal_array (EmitMarshalContext *m, int argnum, MonoType *t, /* Emit marshalling code */ if (is_string) { + int stind_op; mono_mb_emit_ldloc (mb, dest_ptr); mono_mb_emit_ldloc (mb, src_var); mono_mb_emit_ldloc (mb, index_var); mono_mb_emit_byte (mb, CEE_LDELEM_REF); - mono_mb_emit_icall (mb, conv_to_icall (conv)); - mono_mb_emit_byte (mb, CEE_STIND_I); + mono_mb_emit_icall (mb, conv_to_icall (conv, &stind_op)); + mono_mb_emit_byte (mb, stind_op); } else { /* set the src_ptr */ mono_mb_emit_ldloc (mb, src_var); @@ -6297,7 +6360,7 @@ emit_marshal_array (EmitMarshalContext *m, int argnum, MonoType *t, mono_mb_emit_byte (mb, CEE_CONV_OVF_I); mono_mb_emit_op (mb, CEE_NEWARR, klass->element_class); /* Store into argument */ - mono_mb_emit_byte (mb, CEE_STIND_I); + mono_mb_emit_byte (mb, CEE_STIND_REF); } } @@ -6357,7 +6420,7 @@ emit_marshal_array (EmitMarshalContext *m, int argnum, MonoType *t, mono_mb_emit_ldloc (mb, src_ptr); mono_mb_emit_byte (mb, CEE_LDIND_I); - mono_mb_emit_icall (mb, conv_to_icall (conv)); + mono_mb_emit_icall (mb, conv_to_icall (conv, NULL)); if (need_free) { /* src */ @@ -6419,7 +6482,7 @@ emit_marshal_array (EmitMarshalContext *m, int argnum, MonoType *t, if (t->byref) mono_mb_emit_byte (mb, CEE_LDIND_REF); mono_mb_emit_ldloc (mb, conv_arg); - mono_mb_emit_icall (mb, conv_to_icall (MONO_MARSHAL_FREE_LPARRAY)); + mono_mb_emit_icall (mb, conv_to_icall (MONO_MARSHAL_FREE_LPARRAY, NULL)); } break; @@ -6594,7 +6657,7 @@ emit_marshal_array (EmitMarshalContext *m, int argnum, MonoType *t, mono_mb_emit_ldloc (mb, src_ptr); mono_mb_emit_byte (mb, CEE_LDIND_I); - mono_mb_emit_icall (mb, conv_to_icall (conv)); + mono_mb_emit_icall (mb, conv_to_icall (conv, NULL)); mono_mb_emit_byte (mb, CEE_STELEM_REF); } else { @@ -6702,6 +6765,7 @@ emit_marshal_array (EmitMarshalContext *m, int argnum, MonoType *t, /* Emit marshalling code */ if (is_string) { + int stind_op; g_assert (conv != MONO_MARSHAL_CONV_INVALID); /* dest */ @@ -6713,8 +6777,8 @@ emit_marshal_array (EmitMarshalContext *m, int argnum, MonoType *t, mono_mb_emit_byte (mb, CEE_LDELEM_REF); - mono_mb_emit_icall (mb, conv_to_icall (conv)); - mono_mb_emit_byte (mb, CEE_STIND_I); + mono_mb_emit_icall (mb, conv_to_icall (conv, &stind_op)); + mono_mb_emit_byte (mb, stind_op); } else { char *msg = g_strdup ("Marshalling of non-string and non-blittable arrays to managed code is not implemented."); @@ -6799,6 +6863,7 @@ emit_marshal_array (EmitMarshalContext *m, int argnum, MonoType *t, /* Emit marshalling code */ if (is_string) { + int stind_op; g_assert (conv != MONO_MARSHAL_CONV_INVALID); /* dest */ @@ -6810,8 +6875,8 @@ emit_marshal_array (EmitMarshalContext *m, int argnum, MonoType *t, mono_mb_emit_byte (mb, CEE_LDELEM_REF); - mono_mb_emit_icall (mb, conv_to_icall (conv)); - mono_mb_emit_byte (mb, CEE_STIND_I); + mono_mb_emit_icall (mb, conv_to_icall (conv, &stind_op)); + mono_mb_emit_byte (mb, stind_op); } else { char *msg = g_strdup ("Marshalling of non-string arrays to managed code is not implemented."); @@ -7237,12 +7302,10 @@ mono_marshal_emit_native_wrapper (MonoImage *image, MonoMethodBuilder *mb, MonoM 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; @@ -7285,12 +7348,20 @@ mono_marshal_emit_native_wrapper (MonoImage *image, MonoMethodBuilder *mb, MonoM 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); + * + * + * + * return ret; + */ + if (MONO_TYPE_ISSTRUCT (sig->ret)) m.vtaddr_var = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg); @@ -7322,10 +7393,8 @@ mono_marshal_emit_native_wrapper (MonoImage *image, MonoMethodBuilder *mb, MonoM 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); } @@ -7350,8 +7419,7 @@ mono_marshal_emit_native_wrapper (MonoImage *image, MonoMethodBuilder *mb, MonoM #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); @@ -7362,6 +7430,24 @@ mono_marshal_emit_native_wrapper (MonoImage *image, MonoMethodBuilder *mb, MonoM } } + if (MONO_TYPE_ISSTRUCT (sig->ret)) { + MonoClass *klass = mono_class_from_mono_type (sig->ret); + mono_class_init (klass); + if (!(((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) || klass->blittable)) { + /* This is used by emit_marshal_vtype (), but it needs to go right before the call */ + mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX); + mono_mb_emit_byte (mb, CEE_MONO_VTADDR); + mono_mb_emit_stloc (mb, m.vtaddr_var); + } + } + + /* Unblock before converting the result, since that can involve calls into the runtime */ + 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_exit_gc_safe_region_unbalanced); + } + /* Set LastError if needed */ if (piinfo->piflags & PINVOKE_ATTRIBUTE_SUPPORTS_LAST_ERROR) { if (!get_last_error_sig) { @@ -7371,7 +7457,7 @@ mono_marshal_emit_native_wrapper (MonoImage *image, MonoMethodBuilder *mb, MonoM } #ifdef TARGET_WIN32 - /* + /* * Have to call GetLastError () early and without a wrapper, since various runtime components could * clobber its value. */ @@ -7380,26 +7466,6 @@ mono_marshal_emit_native_wrapper (MonoImage *image, MonoMethodBuilder *mb, MonoM #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); - mono_class_init (klass); - if (!(((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) || klass->blittable)) { - /* This is used by emit_marshal_vtype (), but it needs to go right before the call */ - mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX); - mono_mb_emit_byte (mb, CEE_MONO_VTADDR); - mono_mb_emit_stloc (mb, m.vtaddr_var); - } - } - - /* Unblock before converting the result, since that can involve calls into the runtime */ - 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); } /* convert the result */ @@ -7456,31 +7522,6 @@ mono_marshal_emit_native_wrapper (MonoImage *image, MonoMethodBuilder *mb, MonoM 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. @@ -7518,10 +7559,6 @@ mono_marshal_emit_native_wrapper (MonoImage *image, MonoMethodBuilder *mb, MonoM 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 */ @@ -7927,9 +7964,9 @@ mono_marshal_emit_managed_wrapper (MonoMethodBuilder *mb, MonoMethodSignature *i } #else MonoMethodSignature *sig, *csig; - MonoExceptionClause *clause; - int i, *tmp_locals; - int leave_pos; + MonoExceptionClause *clauses, *clause_finally, *clause_catch; + 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; @@ -7960,43 +7997,64 @@ mono_marshal_emit_managed_wrapper (MonoMethodBuilder *mb, MonoMethodSignature *i if (MONO_TYPE_ISSTRUCT (sig->ret)) m->vtaddr_var = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg); + 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 (); * * * * ret = method (...); + * } 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); * } * * return ret; */ - if (mono_threads_is_coop_enabled ()) { - clause = g_new0 (MonoExceptionClause, 1); - clause->flags = MONO_EXCEPTION_CLAUSE_FINALLY; - } + clauses = g_new0 (MonoExceptionClause, 2); + + clause_catch = &clauses [0]; + clause_catch->flags = MONO_EXCEPTION_CLAUSE_NONE; + clause_catch->data.catch_class = mono_defaults.exception_class; + + clause_finally = &clauses [1]; + clause_finally->flags = MONO_EXCEPTION_CLAUSE_FINALLY; mono_mb_emit_icon (mb, 0); mono_mb_emit_stloc (mb, 2); - if (mono_threads_is_coop_enabled ()) { - /* try { */ - clause->try_offset = mono_mb_get_label (mb); - } + mono_mb_emit_icon (mb, -1); + mono_mb_emit_byte (mb, CEE_CONV_U4); + mono_mb_emit_stloc (mb, ex_local); - /* - * 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); + /* try { */ + clause_catch->try_offset = clause_finally->try_offset = mono_mb_get_label (mb); + + 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); + } /* */ emit_thread_interrupt_checkpoint (mb); @@ -8139,31 +8197,62 @@ mono_marshal_emit_managed_wrapper (MonoMethodBuilder *mb, MonoMethodSignature *i } } - if (mono_threads_is_coop_enabled ()) { - leave_pos = mono_mb_emit_branch (mb, CEE_LEAVE); + leave_try_pos = mono_mb_emit_branch (mb, CEE_LEAVE); - /* } finally { */ - clause->try_len = mono_mb_get_label (mb) - clause->try_offset; - clause->handler_offset = mono_mb_get_label (mb); - } + /* } [endtry] */ - /* - * 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); + /* 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); - if (mono_threads_is_coop_enabled ()) { - mono_mb_emit_byte (mb, CEE_ENDFINALLY); + mono_mb_emit_stloc (mb, e_local); + + /* ex = mono_gchandle_new (e, false); */ + mono_mb_emit_ldloc (mb, e_local); + mono_mb_emit_icon (mb, 0); + mono_mb_emit_icall (mb, mono_gchandle_new); + mono_mb_emit_stloc (mb, ex_local); + + leave_catch_pos = mono_mb_emit_branch (mb, CEE_LEAVE); - /* } [endfinally] */ - clause->handler_len = mono_mb_get_pos (mb) - clause->handler_offset; + /* } [endcatch] */ + clause_catch->handler_len = mono_mb_get_pos (mb) - clause_catch->handler_offset; - mono_mb_patch_branch (mb, leave_pos); + /* finally { */ + clause_finally->try_len = mono_mb_get_label (mb) - clause_finally->try_offset; + clause_finally->handler_offset = mono_mb_get_label (mb); + + 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_mb_emit_icon (mb, -1); + mono_mb_emit_byte (mb, CEE_CONV_U4); + ex_m1_pos = mono_mb_emit_branch (mb, CEE_BEQ); + + /* mono_marshal_ftnptr_eh_callback (ex) */ + mono_mb_emit_ldloc (mb, ex_local); + mono_mb_emit_icall (mb, mono_marshal_ftnptr_eh_callback); + + /* [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); @@ -8176,9 +8265,7 @@ mono_marshal_emit_managed_wrapper (MonoMethodBuilder *mb, MonoMethodSignature *i mono_mb_emit_byte (mb, CEE_RET); } - if (mono_threads_is_coop_enabled ()) { - mono_mb_set_clauses (mb, 1, clause); - } + mono_mb_set_clauses (mb, 2, clauses); if (closed) g_free (sig); @@ -8444,7 +8531,9 @@ mono_marshal_get_vtfixup_ftnptr (MonoImage *image, guint32 token, guint16 type) 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); @@ -8467,7 +8556,9 @@ mono_marshal_get_vtfixup_ftnptr (MonoImage *image, guint32 token, guint16 type) 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 @@ -8598,12 +8689,14 @@ mono_marshal_get_castclass_with_cache (void) 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) @@ -8665,7 +8758,7 @@ mono_marshal_get_isinst_with_cache (void) // return obj mono_mb_patch_branch (mb, positive_cache_hit_pos); - mono_mb_emit_ldarg (mb, 0); + mono_mb_emit_ldarg (mb, obj_arg_position); mono_mb_emit_byte (mb, CEE_RET); #endif @@ -9172,7 +9265,7 @@ mono_marshal_get_synchronized_wrapper (MonoMethod *method) if (!enter_method) { MonoMethodDesc *desc; - desc = mono_method_desc_new ("Monitor:enter_with_atomic_var(object,bool&)", FALSE); + desc = mono_method_desc_new ("Monitor:Enter(object,bool&)", FALSE); enter_method = mono_method_desc_search_in_class (desc, mono_defaults.monitor_class); g_assert (enter_method); mono_method_desc_free (desc); @@ -10485,12 +10578,15 @@ ves_icall_System_Runtime_InteropServices_Marshal_PtrToStringAnsi (char *ptr) MonoString * ves_icall_System_Runtime_InteropServices_Marshal_PtrToStringAnsi_len (char *ptr, gint32 len) { - if (ptr == NULL) { - mono_set_pending_exception (mono_get_exception_argument_null ("ptr")); - return NULL; - } else { - return mono_string_new_len (mono_domain_get (), ptr, len); - } + MonoError error; + MonoString *result = NULL; + mono_error_init (&error); + if (ptr == NULL) + mono_error_set_argument_null (&error, "ptr", ""); + else + result = mono_string_new_len_checked (mono_domain_get (), ptr, len, &error); + mono_error_set_pending_exception (&error); + return result; } MonoString * @@ -11596,10 +11692,12 @@ mono_marshal_get_thunk_invoke_wrapper (MonoMethod *method) 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; @@ -11649,26 +11747,11 @@ mono_marshal_get_thunk_invoke_wrapper (MonoMethod *method) 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); @@ -11738,13 +11821,6 @@ mono_marshal_get_thunk_invoke_wrapper (MonoMethod *method) 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 @@ -11784,3 +11860,42 @@ mono_marshal_free_dynamic_wrappers (MonoMethod *method) if (marshal_mutex_initialized) mono_marshal_unlock (); } + +static void +mono_marshal_ftnptr_eh_callback (guint32 gchandle) +{ + g_assert (ftnptr_eh_callback); + 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: + * + * Install a callback that should be called when there is a managed exception + * in a native-to-managed wrapper. This is mainly used by iOS to convert a + * managed exception to a native exception, to properly unwind the native + * stack; this native exception will then be converted back to a managed + * exception in their managed-to-native wrapper. + */ +void +mono_install_ftnptr_eh_callback (MonoFtnPtrEHCallback callback) +{ + ftnptr_eh_callback = callback; +}