X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mono%2Fmetadata%2Fmarshal.c;h=18f93d260e3897cc70f53bbfde9b45a0229526fb;hb=56ad8f4e5dfb8198e4671f631a3103b1e8b83dd3;hp=82e0b9b69fb17d61e6f69e1cc8fed412c2c1e2db;hpb=c153626bdf923ef47b48eaf119423b39dfb8184a;p=mono.git diff --git a/mono/metadata/marshal.c b/mono/metadata/marshal.c index 82e0b9b69fb..18f93d260e3 100644 --- a/mono/metadata/marshal.c +++ b/mono/metadata/marshal.c @@ -8,6 +8,7 @@ * Copyright 2004-2009 Novell, Inc (http://www.novell.com) * Copyright 2011 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" @@ -143,6 +144,54 @@ static void init_safe_handle (void); static void* ves_icall_marshal_alloc (gulong size); +void +mono_string_utf8_to_builder (MonoStringBuilder *sb, char *text); + +void +mono_string_utf16_to_builder (MonoStringBuilder *sb, gunichar2 *text); + +gchar* +mono_string_builder_to_utf8 (MonoStringBuilder *sb); + +gunichar2* +mono_string_builder_to_utf16 (MonoStringBuilder *sb); + +void +mono_string_to_byvalstr (gpointer dst, MonoString *src, int size); + +void +mono_string_to_byvalwstr (gpointer dst, MonoString *src, int size); + +gpointer +mono_delegate_to_ftnptr (MonoDelegate *delegate); + +MonoDelegate* +mono_ftnptr_to_delegate (MonoClass *klass, gpointer ftn); + +gpointer +mono_array_to_savearray (MonoArray *array); + +gpointer +mono_array_to_lparray (MonoArray *array); + +void +mono_free_lparray (MonoArray *array, gpointer* nativeArray); + +gpointer +mono_marshal_asany (MonoObject *obj, MonoMarshalNative string_encoding, int param_attrs); + +void +mono_marshal_free_asany (MonoObject *o, gpointer ptr, MonoMarshalNative string_encoding, int param_attrs); + +gpointer +mono_array_to_savearray (MonoArray *array); + +gpointer +mono_array_to_lparray (MonoArray *array); + +void +mono_free_lparray (MonoArray *array, gpointer* nativeArray); + /* 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) @@ -153,7 +202,6 @@ static GENERATE_TRY_GET_CLASS_WITH_CACHE (icustom_marshaler, System.Runtime.Inte static MonoMethod *sh_dangerous_add_ref; static MonoMethod *sh_dangerous_release; - static void init_safe_handle () { @@ -164,11 +212,11 @@ init_safe_handle () } static void -register_icall (gpointer func, const char *name, const char *sigstr, gboolean save) +register_icall (gpointer func, const char *name, const char *sigstr, gboolean no_wrapper) { MonoMethodSignature *sig = mono_create_icall_signature (sigstr); - mono_register_jit_icall (func, name, sig, save); + mono_register_jit_icall (func, name, sig, no_wrapper); } MonoMethodSignature* @@ -190,6 +238,15 @@ mono_marshal_init_tls (void) mono_native_tls_alloc (&load_type_info_tls_id, NULL); } +static MonoObject* +mono_object_isinst_icall (MonoObject *obj, MonoClass *klass) +{ + MonoError error; + MonoObject *result = mono_object_isinst_checked (obj, klass, &error); + mono_error_set_pending_exception (&error); + return result; +} + void mono_marshal_init (void) { @@ -237,7 +294,7 @@ mono_marshal_init (void) register_icall (mono_string_to_byvalstr, "mono_string_to_byvalstr", "void ptr ptr int32", FALSE); register_icall (mono_string_to_byvalwstr, "mono_string_to_byvalwstr", "void ptr ptr int32", FALSE); register_icall (g_free, "g_free", "void ptr", FALSE); - register_icall (mono_object_isinst, "mono_object_isinst", "object object ptr", FALSE); + register_icall (mono_object_isinst_icall, "mono_object_isinst_icall", "object object ptr", 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); @@ -283,9 +340,11 @@ mono_marshal_unlock_internal (void) mono_marshal_unlock (); } +/* This is a JIT icall, it sets the pending exception and return NULL on error */ gpointer mono_delegate_to_ftnptr (MonoDelegate *delegate) { + MonoError error; MonoMethod *method, *wrapper; MonoClass *klass; uint32_t target_handle = 0; @@ -303,14 +362,15 @@ mono_delegate_to_ftnptr (MonoDelegate *delegate) if (delegate->method_is_virtual) method = mono_object_get_virtual_method (delegate->target, method); - if (mono_method_signature (method)->pinvoke) { + if (method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) { const char *exc_class, *exc_arg; gpointer ftnptr; ftnptr = mono_lookup_pinvoke_call (method, &exc_class, &exc_arg); if (!ftnptr) { g_assert (exc_class); - mono_raise_exception (mono_exception_from_name_msg (mono_defaults.corlib, "System", exc_class, exc_arg)); + mono_set_pending_exception (mono_exception_from_name_msg (mono_defaults.corlib, "System", exc_class, exc_arg)); + return NULL; } return ftnptr; } @@ -328,7 +388,11 @@ mono_delegate_to_ftnptr (MonoDelegate *delegate) delegate_hash_table_add (delegate); /* when the object is collected, collect the dynamic method, too */ - mono_object_register_finalizer ((MonoObject*)delegate); + mono_object_register_finalizer ((MonoObject*)delegate, &error); + if (!mono_error_ok (&error)) { + mono_error_set_pending_exception (&error); + return NULL; + } return delegate->delegate_trampoline; } @@ -396,6 +460,7 @@ mono_marshal_use_aot_wrappers (gboolean use) static void parse_unmanaged_function_pointer_attr (MonoClass *klass, MonoMethodPInvoke *piinfo) { + MonoError error; MonoCustomAttrInfo *cinfo; MonoReflectionUnmanagedFunctionPointerAttribute *attr; @@ -405,9 +470,12 @@ parse_unmanaged_function_pointer_attr (MonoClass *klass, MonoMethodPInvoke *piin * The pinvoke attributes are stored in a real custom attribute so we have to * construct it. */ - cinfo = mono_custom_attrs_from_class (klass); + cinfo = mono_custom_attrs_from_class_checked (klass, &error); + if (!mono_error_ok (&error)) { + g_warning ("Could not load UnmanagedFunctionPointerAttribute due to %s", mono_error_get_message (&error)); + mono_error_cleanup (&error); + } if (cinfo && !mono_runtime_get_no_exec ()) { - MonoError error; attr = (MonoReflectionUnmanagedFunctionPointerAttribute*)mono_custom_attrs_get_attr_checked (cinfo, mono_class_try_get_unmanaged_function_pointer_attribute_class (), &error); if (attr) { piinfo->piflags = (attr->call_conv << 8) | (attr->charset ? (attr->charset - 1) * 2 : 1) | attr->set_last_error; @@ -423,6 +491,7 @@ parse_unmanaged_function_pointer_attr (MonoClass *klass, MonoMethodPInvoke *piin } } +/* This is a JIT icall, it sets the pending exception and returns NULL on error */ MonoDelegate* mono_ftnptr_to_delegate (MonoClass *klass, gpointer ftn) { @@ -460,7 +529,11 @@ mono_ftnptr_to_delegate (MonoClass *klass, gpointer ftn) if (use_aot_wrappers) { wrapper = mono_marshal_get_native_func_wrapper_aot (klass); - this_obj = mono_value_box (mono_domain_get (), mono_defaults.int_class, &ftn); + this_obj = mono_value_box_checked (mono_domain_get (), mono_defaults.int_class, &ftn, &error); + if (!is_ok (&error)) { + mono_error_set_pending_exception (&error); + return NULL; + } } else { memset (&piinfo, 0, sizeof (piinfo)); parse_unmanaged_function_pointer_attr (klass, &piinfo); @@ -482,12 +555,17 @@ mono_ftnptr_to_delegate (MonoClass *klass, gpointer ftn) } d = (MonoDelegate*)mono_object_new_checked (mono_domain_get (), klass, &error); - mono_error_raise_exception (&error); /* FIXME don't raise here */ + if (!mono_error_ok (&error)) { + mono_error_set_pending_exception (&error); + return NULL; + } mono_delegate_ctor_with_method ((MonoObject*)d, this_obj, mono_compile_method (wrapper), wrapper); } - if (d->object.vtable->domain != mono_domain_get ()) - mono_raise_exception (mono_get_exception_not_supported ("Delegates cannot be marshalled from native code into a domain other than their home domain")); + if (d->object.vtable->domain != mono_domain_get ()) { + mono_set_pending_exception (mono_get_exception_not_supported ("Delegates cannot be marshalled from native code into a domain other than their home domain")); + return NULL; + } return d; } @@ -543,6 +621,7 @@ mono_string_from_byvalstr (const char *data, int max_len) return mono_string_new_len (domain, data, len); } +/* This is a JIT icall, it sets the pending exception and return NULL on error */ static MonoString * mono_string_from_byvalwstr (gunichar2 *data, int max_len) { @@ -557,7 +636,10 @@ mono_string_from_byvalwstr (gunichar2 *data, int max_len) while (data [len]) len++; res = mono_string_new_utf16_checked (domain, data, MIN (len, max_len), &error); - mono_error_raise_exception (&error); + if (!mono_error_ok (&error)) { + mono_error_set_pending_exception (&error); + return NULL; + } return res; } @@ -680,6 +762,7 @@ mono_byvalarray_to_byte_array (MonoArray *arr, gpointer native_arr, guint32 elnu mono_byvalarray_to_array (arr, native_arr, mono_defaults.byte_class, elnum); } +/* This is a JIT icall, it sets the pending exception and returns on error */ static void mono_array_to_byvalarray (gpointer native_arr, MonoArray *arr, MonoClass *elclass, guint32 elnum) { @@ -691,9 +774,9 @@ mono_array_to_byvalarray (gpointer native_arr, MonoArray *arr, MonoClass *elclas as = g_utf16_to_utf8 (mono_array_addr (arr, gunichar2, 0), mono_array_length (arr), NULL, NULL, &error); if (error) { - MonoException *exc = mono_get_exception_argument ("string", error->message); + mono_set_pending_exception (mono_get_exception_argument ("string", error->message)); g_error_free (error); - mono_raise_exception (exc); + return; } memcpy (native_arr, as, MIN (strlen (as), elnum)); @@ -841,6 +924,8 @@ mono_string_utf16_to_builder (MonoStringBuilder *sb, gunichar2 *text) * Returns: a utf8 string with the contents of the StringBuilder. * * The return value must be released with g_free. + * + * This is a JIT icall, it sets the pending exception and returns NULL on error. */ gchar* mono_string_builder_to_utf8 (MonoStringBuilder *sb) @@ -851,7 +936,6 @@ mono_string_builder_to_utf8 (MonoStringBuilder *sb) if (!sb) return NULL; - gunichar2 *str_utf16 = mono_string_builder_to_utf16 (sb); guint str_len = mono_string_builder_string_length (sb); @@ -861,7 +945,7 @@ mono_string_builder_to_utf8 (MonoStringBuilder *sb) if (gerror) { g_error_free (gerror); g_free (str_utf16); - mono_raise_exception (mono_get_exception_execution_engine ("Failed to convert StringBuilder from utf16 to utf8")); + mono_set_pending_exception (mono_get_exception_execution_engine ("Failed to convert StringBuilder from utf16 to utf8")); return NULL; } else { guint len = mono_string_builder_capacity (sb) + 1; @@ -869,7 +953,8 @@ mono_string_builder_to_utf8 (MonoStringBuilder *sb) if (!mono_error_ok (&error)) { g_free (str_utf16); g_free (tmp); - mono_error_raise_exception (&error); + mono_error_set_pending_exception (&error); + return NULL; } g_assert (str_len < len); @@ -891,6 +976,7 @@ mono_string_builder_to_utf8 (MonoStringBuilder *sb) * Returns: a utf16 string with the contents of the StringBuilder. * * The return value must not be freed. + * This is a JIT icall, it sets the pending exception and returns NULL on error. */ gunichar2* mono_string_builder_to_utf16 (MonoStringBuilder *sb) @@ -908,7 +994,10 @@ mono_string_builder_to_utf16 (MonoStringBuilder *sb) len = 1; gunichar2 *str = (gunichar2 *)mono_marshal_alloc ((len + 1) * sizeof (gunichar2), &error); - mono_error_raise_exception (&error); + if (!mono_error_ok (&error)) { + mono_error_set_pending_exception (&error); + return NULL; + } str[len] = '\0'; @@ -935,6 +1024,7 @@ mono_string_builder_to_utf16 (MonoStringBuilder *sb) return str; } +/* This is a JIT icall, it sets the pending exception and returns NULL on error. */ static gpointer mono_string_to_lpstr (MonoString *s) { @@ -956,7 +1046,7 @@ mono_string_to_lpstr (MonoString *s) if (error) { MonoException *exc = mono_get_exception_argument ("string", error->message); g_error_free (error); - mono_raise_exception(exc); + mono_set_pending_exception (exc); return NULL; } else { as = CoTaskMemAlloc (len + 1); @@ -1767,11 +1857,7 @@ emit_object_to_ptr_conv (MonoMethodBuilder *mb, MonoType *type, MonoMarshalConv } default: { - char *msg = g_strdup_printf ("marshalling conversion %d not implemented", conv); - MonoException *exc = mono_get_exception_not_implemented (msg); - g_warning ("%s", msg); - g_free (msg); - mono_raise_exception (exc); + g_error ("marshalling conversion %d not implemented", conv); } } } @@ -2071,24 +2157,26 @@ mono_marshal_emit_thread_force_interrupt_checkpoint (MonoMethodBuilder *mb) #endif /* DISABLE_JIT */ +/* This is a JIT icall, it sets the pending exception and returns NULL on error. */ static MonoAsyncResult * mono_delegate_begin_invoke (MonoDelegate *delegate, gpointer *params) { + MonoError error; MonoMulticastDelegate *mcast_delegate; MonoClass *klass; MonoMethod *method; g_assert (delegate); mcast_delegate = (MonoMulticastDelegate *) delegate; - if (mcast_delegate->delegates != NULL) - mono_raise_exception (mono_get_exception_argument (NULL, "The delegate must have only one target")); + if (mcast_delegate->delegates != NULL) { + mono_set_pending_exception (mono_get_exception_argument (NULL, "The delegate must have only one target")); + return NULL; + } #ifndef DISABLE_REMOTING if (delegate->target && mono_object_class (delegate->target) == mono_defaults.transparent_proxy_class) { - MonoTransparentProxy* tp = (MonoTransparentProxy *)delegate->target; if (!mono_class_is_contextbound (tp->remote_class->proxy_class) || tp->rp->context != (MonoObject *) mono_context_get ()) { - /* If the target is a proxy, make a direct call. Is proxy's work // to make the call asynchronous. */ @@ -2108,9 +2196,13 @@ mono_delegate_begin_invoke (MonoDelegate *delegate, gpointer *params) msg->call_type = CallType_BeginInvoke; exc = NULL; - mono_remoting_invoke ((MonoObject *)tp->rp, msg, &exc, &out_args); + mono_remoting_invoke ((MonoObject *)tp->rp, msg, &exc, &out_args, &error); + if (!mono_error_ok (&error)) { + mono_error_set_pending_exception (&error); + return NULL; + } if (exc) - mono_raise_exception ((MonoException *) exc); + mono_set_pending_exception ((MonoException *) exc); return ares; } } @@ -2123,7 +2215,9 @@ mono_delegate_begin_invoke (MonoDelegate *delegate, gpointer *params) method = mono_get_delegate_invoke (klass); g_assert (method); - return mono_threadpool_ms_begin_invoke (mono_domain_get (), (MonoObject*) delegate, method, params); + MonoAsyncResult *result = mono_threadpool_ms_begin_invoke (mono_domain_get (), (MonoObject*) delegate, method, params, &error); + mono_error_set_pending_exception (&error); + return result; } #ifndef DISABLE_JIT @@ -2786,6 +2880,7 @@ mono_marshal_get_delegate_begin_invoke (MonoMethod *method) return res; } +/* This is a JIT icall, it sets the pending exception and returns NULL on error. */ static MonoObject * mono_delegate_end_invoke (MonoDelegate *delegate, gpointer *params) { @@ -2804,7 +2899,10 @@ mono_delegate_end_invoke (MonoDelegate *delegate, gpointer *params) if (!delegate->method_info) { g_assert (delegate->method); MonoReflectionMethod *rm = mono_method_get_object_checked (domain, delegate->method, NULL, &error); - mono_error_raise_exception (&error); /* FIXME don't raise here */ + if (!mono_error_ok (&error)) { + mono_error_set_pending_exception (&error); + return NULL; + } MONO_OBJECT_SETREF (delegate, method_info, rm); } @@ -2822,12 +2920,12 @@ mono_delegate_end_invoke (MonoDelegate *delegate, gpointer *params) ares = (MonoAsyncResult *)mono_array_get (msg->args, gpointer, sig->param_count - 1); if (ares == NULL) { - mono_raise_exception (mono_exception_from_name_msg (mono_defaults.corlib, "System.Runtime.Remoting", "RemotingException", "The async result object is null or of an unexpected type.")); + mono_set_pending_exception (mono_exception_from_name_msg (mono_defaults.corlib, "System.Runtime.Remoting", "RemotingException", "The async result object is null or of an unexpected type.")); return NULL; } if (ares->async_delegate != (MonoObject*)delegate) { - mono_raise_exception (mono_get_exception_invalid_operation ( + mono_set_pending_exception (mono_get_exception_invalid_operation ( "The IAsyncResult object provided does not match this delegate.")); return NULL; } @@ -2836,11 +2934,18 @@ mono_delegate_end_invoke (MonoDelegate *delegate, gpointer *params) if (delegate->target && mono_object_is_transparent_proxy (delegate->target)) { MonoTransparentProxy* tp = (MonoTransparentProxy *)delegate->target; msg = (MonoMethodMessage *)mono_object_new_checked (domain, mono_defaults.mono_method_message_class, &error); - mono_error_raise_exception (&error); /* FIXME don't raise here */ + if (!mono_error_ok (&error)) { + mono_error_set_pending_exception (&error); + return NULL; + } mono_message_init (domain, msg, delegate->method_info, NULL); msg->call_type = CallType_EndInvoke; MONO_OBJECT_SETREF (msg, async_result, ares); - res = mono_remoting_invoke ((MonoObject *)tp->rp, msg, &exc, &out_args); + res = mono_remoting_invoke ((MonoObject *)tp->rp, msg, &exc, &out_args, &error); + if (!mono_error_ok (&error)) { + mono_error_set_pending_exception (&error); + return NULL; + } } else #endif { @@ -2856,7 +2961,7 @@ mono_delegate_end_invoke (MonoDelegate *delegate, gpointer *params) MONO_OBJECT_SETREF (((MonoException*)exc), stack_trace, mono_string_new (domain, tmp)); g_free (tmp); } - mono_raise_exception ((MonoException*)exc); + mono_set_pending_exception ((MonoException*)exc); } mono_method_return_message_restore (method, params, out_args); @@ -3078,11 +3183,13 @@ mono_marshal_get_delegate_invoke_internal (MonoMethod *method, gboolean callvirt if (callvirt) { subtype = WRAPPER_SUBTYPE_DELEGATE_INVOKE_VIRTUAL; if (target_method->is_inflated) { + MonoError error; MonoType *target_type; g_assert (method->signature->hasthis); - target_type = mono_class_inflate_generic_type (method->signature->params [0], - mono_method_get_context (method)); + target_type = mono_class_inflate_generic_type_checked (method->signature->params [0], + mono_method_get_context (method), &error); + mono_error_assert_ok (&error); /* FIXME don't swallow the error */ target_class = mono_class_from_mono_type (target_type); } else { target_class = target_method->klass; @@ -4322,6 +4429,7 @@ emit_marshal_custom (EmitMarshalContext *m, int argnum, MonoType *t, *conv_arg_type = &mono_defaults.int_class->byval_arg; return conv_arg; #else + MonoError error; MonoType *mtype; MonoClass *mklass; static MonoClass *ICustomMarshaler = NULL; @@ -4354,10 +4462,11 @@ emit_marshal_custom (EmitMarshalContext *m, int argnum, MonoType *t, } if (spec->data.custom_data.image) - mtype = mono_reflection_type_from_name (spec->data.custom_data.custom_name, spec->data.custom_data.image); + mtype = mono_reflection_type_from_name_checked (spec->data.custom_data.custom_name, spec->data.custom_data.image, &error); else - mtype = mono_reflection_type_from_name (spec->data.custom_data.custom_name, m->image); + mtype = mono_reflection_type_from_name_checked (spec->data.custom_data.custom_name, m->image, &error); g_assert (mtype != NULL); + mono_error_assert_ok (&error); mklass = mono_class_from_mono_type (mtype); g_assert (mklass != NULL); @@ -4851,8 +4960,8 @@ emit_marshal_vtype (EmitMarshalContext *m, int argnum, MonoType *t, } /* load pointer to returned value type */ - mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX); - mono_mb_emit_byte (mb, CEE_MONO_VTADDR); + g_assert (m->vtaddr_var); + mono_mb_emit_ldloc (mb, m->vtaddr_var); /* store the address of the source into local variable 0 */ mono_mb_emit_stloc (mb, 0); /* set dst_ptr */ @@ -4932,8 +5041,8 @@ emit_marshal_vtype (EmitMarshalContext *m, int argnum, MonoType *t, } /* load pointer to returned value type */ - mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX); - mono_mb_emit_byte (mb, CEE_MONO_VTADDR); + g_assert (m->vtaddr_var); + mono_mb_emit_ldloc (mb, m->vtaddr_var); /* store the address of the source into local variable 0 */ mono_mb_emit_stloc (mb, 0); @@ -7126,10 +7235,12 @@ 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; + int coop_gc_stack_dummy, coop_gc_var, coop_unblocked_var; + int leave_pos; memset (&m, 0, sizeof (m)); m.mb = mb; @@ -7162,7 +7273,7 @@ mono_marshal_emit_native_wrapper (MonoImage *image, MonoMethodBuilder *mb, MonoM mono_mb_emit_icon (mb, 0); mono_mb_emit_stloc (mb, 2); - if (!MONO_TYPE_IS_VOID(sig->ret)) { + if (!MONO_TYPE_IS_VOID (sig->ret)) { /* allocate local 3 to store the return value */ mono_mb_add_local (mb, sig->ret); } @@ -7172,8 +7283,15 @@ 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; } + if (MONO_TYPE_ISSTRUCT (sig->ret)) + m.vtaddr_var = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg); + if (mspecs [0] && mspecs [0]->native == MONO_NATIVE_CUSTOM) { /* Return type custom marshaling */ /* @@ -7192,6 +7310,23 @@ mono_marshal_emit_native_wrapper (MonoImage *image, MonoMethodBuilder *mb, MonoM tmp_locals [i] = emit_marshal (&m, i + param_shift, sig->params [i], mspecs [i + 1], 0, &csig->params [i], MARSHAL_ACTION_CONV_IN); } + // In coop mode need to register blocking state during native call + if (mono_threads_is_coop_enabled ()) { + // Perform an extra, early lookup of the function address, so any exceptions + // potentially resulting from the lookup occur before entering blocking mode. + if (!func_param && !MONO_CLASS_IS_IMPORT (mb->method->klass) && aot) { + mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX); + mono_mb_emit_op (mb, CEE_MONO_ICALL_ADDR, &piinfo->method); + 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_stloc (mb, coop_gc_var); + } + /* push all arguments */ if (sig->hasthis) @@ -7201,12 +7336,6 @@ mono_marshal_emit_native_wrapper (MonoImage *image, MonoMethodBuilder *mb, MonoM emit_marshal (&m, i + param_shift, sig->params [i], mspecs [i + 1], tmp_locals [i], NULL, MARSHAL_ACTION_PUSH); } - if (mono_threads_is_coop_enabled ()) { - mono_mb_emit_ldloc_addr (mb, coop_gc_stack_dummy); - mono_mb_emit_icall (mb, mono_threads_prepare_blocking); - mono_mb_emit_stloc (mb, coop_gc_var); - } - /* call the native method */ if (func_param) { mono_mb_emit_byte (mb, CEE_LDARG_0); @@ -7251,10 +7380,24 @@ mono_marshal_emit_native_wrapper (MonoImage *image, MonoMethodBuilder *mb, MonoM #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 */ @@ -7265,7 +7408,6 @@ mono_marshal_emit_native_wrapper (MonoImage *image, MonoMethodBuilder *mb, MonoM if (spec && spec->native == MONO_NATIVE_CUSTOM) { emit_marshal (&m, 0, sig->ret, spec, 0, NULL, MARSHAL_ACTION_CONV_RESULT); } else { - handle_enum: switch (type) { case MONO_TYPE_VOID: @@ -7312,6 +7454,31 @@ 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. @@ -7349,6 +7516,10 @@ 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 */ @@ -7784,6 +7955,9 @@ mono_marshal_emit_managed_wrapper (MonoMethodBuilder *mb, MonoMethodSignature *i mono_mb_add_local (mb, sig->ret); } + if (MONO_TYPE_ISSTRUCT (sig->ret)) + m->vtaddr_var = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg); + /* * try { * mono_jit_attach (); @@ -7876,6 +8050,17 @@ mono_marshal_emit_managed_wrapper (MonoMethodBuilder *mb, MonoMethodSignature *i /* ret = method (...) */ mono_mb_emit_managed_call (mb, method, NULL); + 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); + } + } + if (mspecs [0] && mspecs [0]->native == MONO_NATIVE_CUSTOM) { emit_marshal (m, 0, sig->ret, mspecs [0], 0, NULL, MARSHAL_ACTION_MANAGED_CONV_RESULT); } else if (!sig->ret->byref) { @@ -8042,6 +8227,7 @@ mono_marshal_set_callconv_from_modopt (MonoMethod *method, MonoMethodSignature * MonoMethod * mono_marshal_get_managed_wrapper (MonoMethod *method, MonoClass *delegate_klass, uint32_t target_handle) { + MonoError error; MonoMethodSignature *sig, *csig, *invoke_sig; MonoMethodBuilder *mb; MonoMethod *res, *invoke; @@ -8052,7 +8238,7 @@ mono_marshal_get_managed_wrapper (MonoMethod *method, MonoClass *delegate_klass, EmitMarshalContext m; g_assert (method != NULL); - g_assert (!mono_method_signature (method)->pinvoke); + g_assert (!(method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL)); /* * FIXME: Should cache the method+delegate type pair, since the same method @@ -8106,7 +8292,8 @@ mono_marshal_get_managed_wrapper (MonoMethod *method, MonoClass *delegate_klass, * contents of the attribute without constructing it, as that might not be * possible when running in cross-compiling mode. */ - cinfo = mono_custom_attrs_from_class (delegate_klass); + cinfo = mono_custom_attrs_from_class_checked (delegate_klass, &error); + mono_error_assert_ok (&error); attr = NULL; if (cinfo) { for (i = 0; i < cinfo->num_attrs; ++i) { @@ -8412,7 +8599,9 @@ mono_marshal_get_castclass_with_cache (void) static MonoObject * mono_marshal_isinst_with_cache (MonoObject *obj, MonoClass *klass, uintptr_t *cache) { - MonoObject *isinst = mono_object_isinst (obj, klass); + MonoError error; + MonoObject *isinst = mono_object_isinst_checked (obj, klass, &error); + mono_error_raise_exception (&error); /* FIXME don't raise here */ #ifndef DISABLE_REMOTING if (obj->vtable->klass == mono_defaults.transparent_proxy_class) @@ -9315,7 +9504,7 @@ get_virtual_stelemref_wrapper (int kind) /*if (mono_object_isinst (value, aklass)) */ mono_mb_emit_ldarg (mb, 2); mono_mb_emit_ldloc (mb, aklass); - mono_mb_emit_icall (mb, mono_object_isinst); + mono_mb_emit_icall (mb, mono_object_isinst_icall); b2 = mono_mb_emit_branch (mb, CEE_BRFALSE); /* do_store: */ @@ -9429,7 +9618,7 @@ get_virtual_stelemref_wrapper (int kind) /*if (mono_object_isinst (value, aklass)) */ mono_mb_emit_ldarg (mb, 2); mono_mb_emit_ldloc (mb, aklass); - mono_mb_emit_icall (mb, mono_object_isinst); + mono_mb_emit_icall (mb, mono_object_isinst_icall); b2 = mono_mb_emit_branch (mb, CEE_BRFALSE); /* if (vklass->idepth < aklass->idepth) goto failue */ @@ -9755,7 +9944,7 @@ mono_marshal_get_stelemref (void) mono_mb_emit_ldarg (mb, 2); mono_mb_emit_ldloc (mb, aklass); - mono_mb_emit_icall (mb, mono_object_isinst); + mono_mb_emit_icall (mb, mono_object_isinst_icall); b4 = mono_mb_emit_branch (mb, CEE_BRTRUE); mono_mb_patch_addr (mb, b4, copy_pos - (b4 + 4)); @@ -10127,12 +10316,16 @@ mono_marshal_alloc (gulong size, MonoError *error) return res; } +/* This is a JIT icall, it sets the pending exception and returns NULL on error. */ static void* ves_icall_marshal_alloc (gulong size) { MonoError error; void *ret = mono_marshal_alloc (size, &error); - mono_error_raise_exception (&error); + if (!mono_error_ok (&error)) { + mono_error_set_pending_exception (&error); + return NULL; + } return ret; } @@ -10166,6 +10359,7 @@ mono_marshal_string_to_utf16 (MonoString *s) return s ? mono_string_chars (s) : NULL; } +/* This is a JIT icall, it sets the pending exception and returns NULL on error. */ static void * mono_marshal_string_to_utf16_copy (MonoString *s) { @@ -10174,7 +10368,10 @@ mono_marshal_string_to_utf16_copy (MonoString *s) } else { MonoError error; gunichar2 *res = (gunichar2 *)mono_marshal_alloc ((mono_string_length (s) * 2) + 2, &error); - mono_error_raise_exception (&error); /* FIXME don't raise here */ + if (!mono_error_ok (&error)) { + mono_error_set_pending_exception (&error); + return NULL; + } memcpy (res, mono_string_chars (s), mono_string_length (s) * 2); res [mono_string_length (s)] = 0; return res; @@ -10310,7 +10507,10 @@ ves_icall_System_Runtime_InteropServices_Marshal_PtrToStringUni (guint16 *ptr) len++; res = mono_string_new_utf16_checked (domain, ptr, len, &error); - mono_error_raise_exception (&error); + if (!mono_error_ok (&error)) { + mono_error_set_pending_exception (&error); + return NULL; + } return res; } @@ -10392,29 +10592,31 @@ ves_icall_System_Runtime_InteropServices_Marshal_StructureToPtr (MonoObject *obj pa [2] = &delete_old; mono_runtime_invoke_checked (method, NULL, pa, &error); - mono_error_raise_exception (&error); + if (!mono_error_ok (&error)) + mono_error_set_pending_exception (&error); } static void -ptr_to_structure (gpointer src, MonoObject *dst) +ptr_to_structure (gpointer src, MonoObject *dst, MonoError *error) { - MonoError error; MonoMethod *method; gpointer pa [2]; + mono_error_init (error); + method = mono_marshal_get_ptr_to_struct (dst->vtable->klass); pa [0] = &src; pa [1] = dst; - mono_runtime_invoke_checked (method, NULL, pa, &error); - mono_error_raise_exception (&error); /* FIXME don't raise here */ + mono_runtime_invoke_checked (method, NULL, pa, error); } void ves_icall_System_Runtime_InteropServices_Marshal_PtrToStructure (gpointer src, MonoObject *dst) { MonoType *t; + MonoError error; MONO_CHECK_ARG_NULL (src,); MONO_CHECK_ARG_NULL (dst,); @@ -10433,7 +10635,9 @@ ves_icall_System_Runtime_InteropServices_Marshal_PtrToStructure (gpointer src, M return; } - ptr_to_structure (src, dst); + ptr_to_structure (src, dst, &error); + if (!mono_error_ok (&error)) + mono_error_set_pending_exception (&error); } MonoObject * @@ -10455,9 +10659,16 @@ ves_icall_System_Runtime_InteropServices_Marshal_PtrToStructure_type (gpointer s } res = mono_object_new_checked (domain, klass, &error); - mono_error_raise_exception (&error); + if (!mono_error_ok (&error)) { + mono_error_set_pending_exception (&error); + return NULL; + } - ptr_to_structure (src, res); + ptr_to_structure (src, res, &error); + if (!mono_error_ok (&error)) { + mono_error_set_pending_exception (&error); + return NULL; + } return res; } @@ -10640,8 +10851,10 @@ ves_icall_System_Runtime_InteropServices_Marshal_AllocHGlobal (gpointer size) #else res = g_try_malloc (s); #endif - if (!res) - mono_raise_exception (mono_domain_get ()->out_of_memory_ex); + if (!res) { + mono_set_pending_exception (mono_domain_get ()->out_of_memory_ex); + return NULL; + } return res; } @@ -10653,7 +10866,7 @@ ves_icall_System_Runtime_InteropServices_Marshal_ReAllocHGlobal (gpointer ptr, g size_t s = (size_t)size; if (ptr == NULL) { - mono_raise_exception (mono_domain_get ()->out_of_memory_ex); + mono_set_pending_exception (mono_domain_get ()->out_of_memory_ex); return NULL; } @@ -10662,8 +10875,10 @@ ves_icall_System_Runtime_InteropServices_Marshal_ReAllocHGlobal (gpointer ptr, g #else res = g_try_realloc (ptr, s); #endif - if (!res) - mono_raise_exception (mono_domain_get ()->out_of_memory_ex); + if (!res) { + mono_set_pending_exception (mono_domain_get ()->out_of_memory_ex); + return NULL; + } return res; } @@ -10692,8 +10907,10 @@ ves_icall_System_Runtime_InteropServices_Marshal_AllocCoTaskMem (int size) res = g_try_malloc ((gulong)size); #endif - if (!res) - mono_raise_exception (mono_domain_get ()->out_of_memory_ex); + if (!res) { + mono_set_pending_exception (mono_domain_get ()->out_of_memory_ex); + return NULL; + } return res; } @@ -10717,8 +10934,10 @@ ves_icall_System_Runtime_InteropServices_Marshal_ReAllocCoTaskMem (gpointer ptr, #else res = g_try_realloc (ptr, (gulong)size); #endif - if (!res) - mono_raise_exception (mono_domain_get ()->out_of_memory_ex); + if (!res) { + mono_set_pending_exception (mono_domain_get ()->out_of_memory_ex); + return NULL; + } return res; } @@ -10740,6 +10959,12 @@ ves_icall_System_Runtime_InteropServices_Marshal_GetDelegateForFunctionPointerIn return mono_ftnptr_to_delegate (klass, ftn); } +gpointer +ves_icall_System_Runtime_InteropServices_Marshal_GetFunctionPointerForDelegateInternal (MonoDelegate *delegate) +{ + return mono_delegate_to_ftnptr (delegate); +} + /** * mono_marshal_is_loading_type_info: * @@ -11116,6 +11341,7 @@ mono_marshal_type_size (MonoType *type, MonoMarshalSpec *mspec, guint32 *align, return 0; } +/* This is a JIT icall, it sets the pending exception and return NULL on error */ gpointer mono_marshal_asany (MonoObject *o, MonoMarshalNative string_encoding, int param_attrs) { @@ -11173,7 +11399,10 @@ mono_marshal_asany (MonoObject *o, MonoMarshalNative string_encoding, int param_ return mono_object_unbox (o); res = mono_marshal_alloc (mono_class_native_size (klass, NULL), &error); - mono_error_raise_exception (&error); /* FIXME don't raise here */ + if (!mono_error_ok (&error)) { + mono_error_set_pending_exception (&error); + return NULL; + } if (!((param_attrs & PARAM_ATTRIBUTE_OUT) && !(param_attrs & PARAM_ATTRIBUTE_IN))) { method = mono_marshal_get_struct_to_ptr (o->vtable->klass); @@ -11183,7 +11412,10 @@ mono_marshal_asany (MonoObject *o, MonoMarshalNative string_encoding, int param_ pa [2] = &delete_old; mono_runtime_invoke_checked (method, NULL, pa, &error); - mono_error_raise_exception (&error); /* FIXME don't raise here */ + if (!mono_error_ok (&error)) { + mono_error_set_pending_exception (&error); + return NULL; + } } return res; @@ -11191,10 +11423,11 @@ mono_marshal_asany (MonoObject *o, MonoMarshalNative string_encoding, int param_ default: break; } - mono_raise_exception (mono_get_exception_argument ("", "No PInvoke conversion exists for value passed to Object-typed parameter.")); + mono_set_pending_exception (mono_get_exception_argument ("", "No PInvoke conversion exists for value passed to Object-typed parameter.")); return NULL; } +/* This is a JIT icall, it sets the pending exception */ void mono_marshal_free_asany (MonoObject *o, gpointer ptr, MonoMarshalNative string_encoding, int param_attrs) { @@ -11234,7 +11467,10 @@ mono_marshal_free_asany (MonoObject *o, gpointer ptr, MonoMarshalNative string_e pa [1] = o; mono_runtime_invoke_checked (method, NULL, pa, &error); - mono_error_raise_exception (&error); /* FIXME don't raise here */ + if (!mono_error_ok (&error)) { + mono_error_set_pending_exception (&error); + return; + } } if (!((param_attrs & PARAM_ATTRIBUTE_OUT) && !(param_attrs & PARAM_ATTRIBUTE_IN))) {