X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mono%2Fmetadata%2Fmarshal.c;h=cd99b0d01dcc4b7fc0c9a168e743437715ccb40d;hb=3e69ff3ae72acec33c471236da49ed6c78b26dc4;hp=c2fec3272256a31ea4cfafa36edf4210a0cdeb18;hpb=748d01ce2a52bd6487fbb5fa770740abed302e58;p=mono.git diff --git a/mono/metadata/marshal.c b/mono/metadata/marshal.c index c2fec327225..9b7eca1ffce 100644 --- a/mono/metadata/marshal.c +++ b/mono/metadata/marshal.c @@ -44,6 +44,7 @@ #include "mono/utils/mono-memory-model.h" #include "mono/utils/atomic.h" #include +#include #include #include @@ -139,26 +140,82 @@ mono_marshal_isinst_with_cache (MonoObject *obj, MonoClass *klass, uintptr_t *ca 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) +static GENERATE_TRY_GET_CLASS_WITH_CACHE (unmanaged_function_pointer_attribute, System.Runtime.InteropServices, UnmanagedFunctionPointerAttribute) +static GENERATE_TRY_GET_CLASS_WITH_CACHE (icustom_marshaler, System.Runtime.InteropServices, ICustomMarshaler) + /* MonoMethod pointers to SafeHandle::DangerousAddRef and ::DangerousRelease */ static MonoMethod *sh_dangerous_add_ref; static MonoMethod *sh_dangerous_release; - static void init_safe_handle () { sh_dangerous_add_ref = mono_class_get_method_from_name ( - mono_defaults.safehandle_class, "DangerousAddRef", 1); + mono_class_try_get_safehandle_class (), "DangerousAddRef", 1); sh_dangerous_release = mono_class_get_method_from_name ( - mono_defaults.safehandle_class, "DangerousRelease", 0); + mono_class_try_get_safehandle_class (), "DangerousRelease", 0); } 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* @@ -180,6 +237,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) { @@ -215,7 +281,7 @@ mono_marshal_init (void) register_icall (mono_ftnptr_to_delegate, "mono_ftnptr_to_delegate", "object ptr ptr", FALSE); register_icall (mono_marshal_asany, "mono_marshal_asany", "ptr object int32 int32", FALSE); register_icall (mono_marshal_free_asany, "mono_marshal_free_asany", "void object ptr int32 int32", FALSE); - register_icall (mono_marshal_alloc, "mono_marshal_alloc", "ptr int32", FALSE); + register_icall (ves_icall_marshal_alloc, "ves_icall_marshal_alloc", "ptr int32", FALSE); register_icall (mono_marshal_free, "mono_marshal_free", "void ptr", FALSE); register_icall (mono_marshal_set_last_error, "mono_marshal_set_last_error", "void", FALSE); register_icall (mono_marshal_set_last_error_windows, "mono_marshal_set_last_error_windows", "void int32", FALSE); @@ -227,7 +293,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); @@ -273,9 +339,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; @@ -293,14 +361,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; } @@ -318,7 +387,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; } @@ -386,23 +459,23 @@ mono_marshal_use_aot_wrappers (gboolean use) static void parse_unmanaged_function_pointer_attr (MonoClass *klass, MonoMethodPInvoke *piinfo) { - static MonoClass *UnmanagedFunctionPointerAttribute; + MonoError error; MonoCustomAttrInfo *cinfo; MonoReflectionUnmanagedFunctionPointerAttribute *attr; - if (!UnmanagedFunctionPointerAttribute) - UnmanagedFunctionPointerAttribute = mono_class_from_name (mono_defaults.corlib, "System.Runtime.InteropServices", "UnmanagedFunctionPointerAttribute"); - /* The attribute is only available in Net 2.0 */ - if (UnmanagedFunctionPointerAttribute) { + if (mono_class_try_get_unmanaged_function_pointer_attribute_class ()) { /* * 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, UnmanagedFunctionPointerAttribute, &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; } else { @@ -417,9 +490,11 @@ 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) { + MonoError error; guint32 gchandle; MonoDelegate *d; @@ -453,7 +528,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); @@ -474,12 +553,18 @@ mono_ftnptr_to_delegate (MonoClass *klass, gpointer ftn) g_free (sig); } - d = (MonoDelegate*)mono_object_new (mono_domain_get (), klass); + d = (MonoDelegate*)mono_object_new_checked (mono_domain_get (), klass, &error); + 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; } @@ -535,9 +620,12 @@ 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) { + MonoError error; + MonoString *res = NULL; MonoDomain *domain = mono_domain_get (); int len = 0; @@ -546,7 +634,12 @@ mono_string_from_byvalwstr (gunichar2 *data, int max_len) while (data [len]) len++; - return mono_string_new_utf16 (domain, data, MIN (len, max_len)); + res = mono_string_new_utf16_checked (domain, data, MIN (len, max_len), &error); + if (!mono_error_ok (&error)) { + mono_error_set_pending_exception (&error); + return NULL; + } + return res; } gpointer @@ -668,6 +761,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) { @@ -679,9 +773,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)); @@ -703,6 +797,8 @@ mono_string_builder_new (int starting_string_length) static MonoClass *string_builder_class; static MonoMethod *sb_ctor; static void *args [1]; + + MonoError error; int initial_len = starting_string_length; if (initial_len < 0) @@ -712,7 +808,7 @@ mono_string_builder_new (int starting_string_length) MonoMethodDesc *desc; MonoMethod *m; - string_builder_class = mono_class_from_name (mono_defaults.corlib, "System.Text", "StringBuilder"); + string_builder_class = mono_class_get_string_builder_class (); g_assert (string_builder_class); desc = mono_method_desc_new (":.ctor(int)", FALSE); m = mono_method_desc_search_in_class (desc, string_builder_class); @@ -726,12 +822,13 @@ mono_string_builder_new (int starting_string_length) // array will always be garbage collected. args [0] = &initial_len; - MonoStringBuilder *sb = (MonoStringBuilder*)mono_object_new (mono_domain_get (), string_builder_class); - MonoObject *exc; - g_assert (sb); + MonoStringBuilder *sb = (MonoStringBuilder*)mono_object_new_checked (mono_domain_get (), string_builder_class, &error); + mono_error_assert_ok (&error); - mono_runtime_invoke (sb_ctor, sb, args, &exc); - g_assert (!exc); + MonoObject *exc; + mono_runtime_try_invoke (sb_ctor, sb, args, &exc, &error); + g_assert (exc == NULL); + mono_error_assert_ok (&error); g_assert (sb->chunkChars->max_length >= initial_len); @@ -826,35 +923,43 @@ 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) { - GError *error = NULL; + MonoError error; + GError *gerror = NULL; if (!sb) return NULL; - gunichar2 *str_utf16 = mono_string_builder_to_utf16 (sb); guint str_len = mono_string_builder_string_length (sb); - gchar *tmp = g_utf16_to_utf8 (str_utf16, str_len, NULL, NULL, &error); + gchar *tmp = g_utf16_to_utf8 (str_utf16, str_len, NULL, NULL, &gerror); - if (error) { - g_error_free (error); + 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; - gchar *res = (gchar *)mono_marshal_alloc (len * sizeof (gchar)); + gchar *res = (gchar *)mono_marshal_alloc (len * sizeof (gchar), &error); + if (!mono_error_ok (&error)) { + g_free (str_utf16); + g_free (tmp); + mono_error_set_pending_exception (&error); + return NULL; + } + g_assert (str_len < len); memcpy (res, tmp, str_len * sizeof (gchar)); res[str_len] = '\0'; - g_free (str_utf16); g_free (tmp); return res; @@ -870,10 +975,13 @@ 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) { + MonoError error; + if (!sb) return NULL; @@ -884,7 +992,12 @@ mono_string_builder_to_utf16 (MonoStringBuilder *sb) if (len == 0) len = 1; - gunichar2 *str = (gunichar2 *)mono_marshal_alloc ((len + 1) * sizeof (gunichar2)); + gunichar2 *str = (gunichar2 *)mono_marshal_alloc ((len + 1) * sizeof (gunichar2), &error); + if (!mono_error_ok (&error)) { + mono_error_set_pending_exception (&error); + return NULL; + } + str[len] = '\0'; if (len == 0) @@ -910,6 +1023,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) { @@ -931,7 +1045,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); @@ -1742,11 +1856,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); } } } @@ -1780,7 +1890,7 @@ emit_struct_conv_full (MonoMethodBuilder *mb, MonoClass *klass, gboolean to_obje return; } - if (klass != mono_defaults.safehandle_class) { + if (klass != mono_class_try_get_safehandle_class ()) { if ((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_AUTO_LAYOUT) { char *msg = g_strdup_printf ("Type %s which is passed to unmanaged code must have a StructLayout attribute.", mono_type_full_name (&klass->byval_arg)); @@ -1810,7 +1920,7 @@ emit_struct_conv_full (MonoMethodBuilder *mb, MonoClass *klass, gboolean to_obje usize = info->fields [i + 1].offset - info->fields [i].offset; } - if (klass != mono_defaults.safehandle_class){ + if (klass != mono_class_try_get_safehandle_class ()){ /* * FIXME: Should really check for usize==0 and msize>0, but we apply * the layout to the managed structure as well. @@ -2046,24 +2156,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. */ @@ -2083,9 +2195,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; } } @@ -2098,7 +2214,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 @@ -2761,9 +2879,11 @@ 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) { + MonoError error; MonoDomain *domain = mono_domain_get (); MonoAsyncResult *ares; MonoMethod *method = NULL; @@ -2777,7 +2897,12 @@ mono_delegate_end_invoke (MonoDelegate *delegate, gpointer *params) if (!delegate->method_info) { g_assert (delegate->method); - MONO_OBJECT_SETREF (delegate, method_info, mono_method_get_object (domain, delegate->method, NULL)); + MonoReflectionMethod *rm = mono_method_get_object_checked (domain, delegate->method, NULL, &error); + if (!mono_error_ok (&error)) { + mono_error_set_pending_exception (&error); + return NULL; + } + MONO_OBJECT_SETREF (delegate, method_info, rm); } if (!delegate->method_info || !delegate->method_info->method) @@ -2794,12 +2919,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; } @@ -2807,11 +2932,19 @@ mono_delegate_end_invoke (MonoDelegate *delegate, gpointer *params) #ifndef DISABLE_REMOTING if (delegate->target && mono_object_is_transparent_proxy (delegate->target)) { MonoTransparentProxy* tp = (MonoTransparentProxy *)delegate->target; - msg = (MonoMethodMessage *)mono_object_new (domain, mono_defaults.mono_method_message_class); + msg = (MonoMethodMessage *)mono_object_new_checked (domain, mono_defaults.mono_method_message_class, &error); + 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 { @@ -2827,7 +2960,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); @@ -3049,11 +3182,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; @@ -3216,7 +3351,7 @@ mono_marshal_get_delegate_invoke_internal (MonoMethod *method, gboolean callvirt for (i = 0; i < sig->param_count; ++i) mono_mb_emit_ldarg (mb, i + 1); mono_mb_emit_ldarg (mb, 0); - mono_mb_emit_ldflda (mb, MONO_STRUCT_OFFSET (MonoDelegate, rgctx)); + mono_mb_emit_ldflda (mb, MONO_STRUCT_OFFSET (MonoDelegate, extra_arg)); mono_mb_emit_byte (mb, CEE_LDIND_I); mono_mb_emit_ldarg (mb, 0); mono_mb_emit_ldflda (mb, MONO_STRUCT_OFFSET (MonoDelegate, method_ptr)); @@ -3259,7 +3394,7 @@ mono_marshal_get_delegate_invoke_internal (MonoMethod *method, gboolean callvirt for (i = 0; i < sig->param_count; ++i) mono_mb_emit_ldarg (mb, i + 1); mono_mb_emit_ldarg (mb, 0); - mono_mb_emit_ldflda (mb, MONO_STRUCT_OFFSET (MonoDelegate, rgctx)); + mono_mb_emit_ldflda (mb, MONO_STRUCT_OFFSET (MonoDelegate, extra_arg)); mono_mb_emit_byte (mb, CEE_LDIND_I); mono_mb_emit_ldarg (mb, 0); mono_mb_emit_ldflda (mb, MONO_STRUCT_OFFSET (MonoDelegate, method_ptr)); @@ -4293,6 +4428,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; @@ -4305,7 +4441,7 @@ emit_marshal_custom (EmitMarshalContext *m, int argnum, MonoType *t, int pos2; if (!ICustomMarshaler) { - MonoClass *klass = mono_class_from_name (mono_defaults.corlib, "System.Runtime.InteropServices", "ICustomMarshaler"); + MonoClass *klass = mono_class_try_get_icustom_marshaler_class (); if (!klass) { exception_msg = g_strdup ("Current profile doesn't support ICustomMarshaler"); goto handle_exception; @@ -4325,10 +4461,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); @@ -4657,7 +4794,7 @@ emit_marshal_vtype (EmitMarshalContext *m, int argnum, MonoType *t, klass = mono_class_from_mono_type (t); - date_time_class = mono_class_from_name_cached (mono_defaults.corlib, "System", "DateTime"); + date_time_class = mono_class_get_date_time_class (); switch (action) { case MARSHAL_ACTION_CONV_IN: @@ -4822,8 +4959,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 */ @@ -4903,8 +5040,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); @@ -4915,7 +5052,7 @@ emit_marshal_vtype (EmitMarshalContext *m, int argnum, MonoType *t, g_assert (m->retobj_var); mono_mb_emit_icon (mb, mono_class_native_size (klass, NULL)); mono_mb_emit_byte (mb, CEE_CONV_I); - mono_mb_emit_icall (mb, mono_marshal_alloc); + mono_mb_emit_icall (mb, ves_icall_marshal_alloc); mono_mb_emit_stloc (mb, 1); mono_mb_emit_ldloc (mb, 1); mono_mb_emit_stloc (mb, m->retobj_var); @@ -5758,7 +5895,7 @@ emit_marshal_object (EmitMarshalContext *m, int argnum, MonoType *t, /* Allocate and set dest */ mono_mb_emit_icon (mb, mono_class_native_size (klass, NULL)); mono_mb_emit_byte (mb, CEE_CONV_I); - mono_mb_emit_icall (mb, mono_marshal_alloc); + mono_mb_emit_icall (mb, ves_icall_marshal_alloc); mono_mb_emit_stloc (mb, 1); /* Update argument pointer */ @@ -5822,7 +5959,7 @@ emit_marshal_object (EmitMarshalContext *m, int argnum, MonoType *t, /* Allocate and set dest */ mono_mb_emit_icon (mb, mono_class_native_size (klass, NULL)); mono_mb_emit_byte (mb, CEE_CONV_I); - mono_mb_emit_icall (mb, mono_marshal_alloc); + mono_mb_emit_icall (mb, ves_icall_marshal_alloc); mono_mb_emit_byte (mb, CEE_DUP); mono_mb_emit_stloc (mb, 1); mono_mb_emit_stloc (mb, 3); @@ -6644,7 +6781,7 @@ emit_marshal_array (EmitMarshalContext *m, int argnum, MonoType *t, mono_mb_emit_byte (mb, CEE_ADD); } mono_mb_emit_byte (mb, CEE_MUL); - mono_mb_emit_icall (mb, mono_marshal_alloc); + mono_mb_emit_icall (mb, ves_icall_marshal_alloc); mono_mb_emit_stloc (mb, dest); mono_mb_emit_ldloc (mb, dest); mono_mb_emit_stloc (mb, 3); @@ -7039,8 +7176,8 @@ emit_marshal (EmitMarshalContext *m, int argnum, MonoType *t, return mono_cominterop_emit_marshal_safearray (m, argnum, t, spec, conv_arg, conv_arg_type, action); #endif - if (mono_defaults.safehandle_class != NULL && t->data.klass && - mono_class_is_subclass_of (t->data.klass, mono_defaults.safehandle_class, FALSE)) + if (mono_class_try_get_safehandle_class () != NULL && t->data.klass && + mono_class_is_subclass_of (t->data.klass, mono_class_try_get_safehandle_class (), FALSE)) return emit_marshal_safehandle (m, argnum, t, spec, conv_arg, conv_arg_type, action); return emit_marshal_object (m, argnum, t, spec, conv_arg, conv_arg_type, action); @@ -7097,10 +7234,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; @@ -7133,7 +7272,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); } @@ -7143,8 +7282,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 */ /* @@ -7163,6 +7309,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) @@ -7172,12 +7335,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); @@ -7222,10 +7379,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 */ @@ -7236,7 +7407,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: @@ -7283,6 +7453,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. @@ -7320,6 +7515,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 */ @@ -7725,9 +7924,10 @@ mono_marshal_emit_managed_wrapper (MonoMethodBuilder *mb, MonoMethodSignature *i } #else MonoMethodSignature *sig, *csig; + MonoExceptionClause *clause; int i, *tmp_locals; + int leave_pos; gboolean closed = FALSE; - int coop_gc_var, coop_gc_dummy_local; sig = m->sig; csig = m->csig; @@ -7754,30 +7954,49 @@ 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 (); + * + * + * + * ret = method (...); + * } finally { + * mono_jit_detach (); + * } + * + * return 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); + clause = g_new0 (MonoExceptionClause, 1); + clause->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); + } + /* * 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 ()) { - /* XXX can we merge reset_blocking_start with JIT_ATTACH above and save one call? */ - 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); - } + /* */ + emit_thread_interrupt_checkpoint (mb); /* we first do all conversions */ tmp_locals = (int *)alloca (sizeof (int) * sig->param_count); @@ -7801,8 +8020,6 @@ mono_marshal_emit_managed_wrapper (MonoMethodBuilder *mb, MonoMethodSignature *i } } - emit_thread_interrupt_checkpoint (mb); - if (sig->hasthis) { if (target_handle) { mono_mb_emit_icon (mb, (gint32)target_handle); @@ -7829,8 +8046,20 @@ mono_marshal_emit_managed_wrapper (MonoMethodBuilder *mb, MonoMethodSignature *i mono_mb_emit_ldarg (mb, 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) { @@ -7908,15 +8137,31 @@ mono_marshal_emit_managed_wrapper (MonoMethodBuilder *mb, MonoMethodSignature *i } 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); + leave_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); } + /* + * 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, CEE_ENDFINALLY); + + /* } [endfinally] */ + clause->handler_len = mono_mb_get_pos (mb) - clause->handler_offset; + + mono_mb_patch_branch (mb, leave_pos); + } + + /* return ret; */ if (m->retobj_var) { mono_mb_emit_ldloc (mb, m->retobj_var); mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX); @@ -7928,6 +8173,10 @@ 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); + } + if (closed) g_free (sig); #endif @@ -7977,7 +8226,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) { - static MonoClass *UnmanagedFunctionPointerAttribute; + MonoError error; MonoMethodSignature *sig, *csig, *invoke_sig; MonoMethodBuilder *mb; MonoMethod *res, *invoke; @@ -7988,7 +8237,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 @@ -8032,12 +8281,8 @@ mono_marshal_get_managed_wrapper (MonoMethod *method, MonoClass *delegate_klass, mono_marshal_set_callconv_from_modopt (invoke, csig); - /* Handle the UnmanagedFunctionPointerAttribute */ - if (!UnmanagedFunctionPointerAttribute) - UnmanagedFunctionPointerAttribute = mono_class_from_name (mono_defaults.corlib, "System.Runtime.InteropServices", "UnmanagedFunctionPointerAttribute"); - /* The attribute is only available in Net 2.0 */ - if (UnmanagedFunctionPointerAttribute) { + if (mono_class_try_get_unmanaged_function_pointer_attribute_class ()) { MonoCustomAttrInfo *cinfo; MonoCustomAttrEntry *attr; @@ -8046,12 +8291,13 @@ 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) { MonoClass *ctor_class = cinfo->attrs [i].ctor->klass; - if (mono_class_has_parent (ctor_class, UnmanagedFunctionPointerAttribute)) { + if (mono_class_has_parent (ctor_class, mono_class_try_get_unmanaged_function_pointer_attribute_class ())) { attr = &cinfo->attrs [i]; break; } @@ -8141,6 +8387,7 @@ mono_marshal_get_managed_wrapper (MonoMethod *method, MonoClass *delegate_klass, gpointer mono_marshal_get_vtfixup_ftnptr (MonoImage *image, guint32 token, guint16 type) { + MonoError error; MonoMethod *method; MonoMethodSignature *sig; MonoMethodBuilder *mb; @@ -8148,7 +8395,9 @@ mono_marshal_get_vtfixup_ftnptr (MonoImage *image, guint32 token, guint16 type) g_assert (token); - method = mono_get_method (image, token, NULL); + method = mono_get_method_checked (image, token, NULL, NULL, &error); + if (!method) + g_error ("Could not load vtfixup token 0x%x due to %s", token, mono_error_get_message (&error)); g_assert (method); if (type & (VTFIXUP_TYPE_FROM_UNMANAGED | VTFIXUP_TYPE_FROM_UNMANAGED_RETAIN_APPDOMAIN)) { @@ -8349,7 +8598,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) @@ -9252,7 +9503,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: */ @@ -9366,7 +9617,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 */ @@ -9692,7 +9943,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)); @@ -10048,20 +10299,36 @@ mono_marshal_get_array_accessor_wrapper (MonoMethod *method) } void* -mono_marshal_alloc (gulong size) +mono_marshal_alloc (gulong size, MonoError *error) { gpointer res; + mono_error_init (error); + #ifdef HOST_WIN32 res = CoTaskMemAlloc (size); #else res = g_try_malloc ((gulong)size); if (!res) - mono_gc_out_of_memory ((gulong)size); + mono_error_set_out_of_memory (error, "Could not allocate %i bytes", size); #endif 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); + if (!mono_error_ok (&error)) { + mono_error_set_pending_exception (&error); + return NULL; + } + + return ret; +} + void mono_marshal_free (gpointer ptr) { @@ -10091,13 +10358,19 @@ 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) { if (s == NULL) { return NULL; } else { - gunichar2 *res = (gunichar2 *)mono_marshal_alloc ((mono_string_length (s) * 2) + 2); + MonoError error; + gunichar2 *res = (gunichar2 *)mono_marshal_alloc ((mono_string_length (s) * 2) + 2, &error); + 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; @@ -10220,6 +10493,8 @@ ves_icall_System_Runtime_InteropServices_Marshal_PtrToStringAnsi_len (char *ptr, MonoString * ves_icall_System_Runtime_InteropServices_Marshal_PtrToStringUni (guint16 *ptr) { + MonoError error; + MonoString *res = NULL; MonoDomain *domain = mono_domain_get (); int len = 0; guint16 *t = ptr; @@ -10230,20 +10505,33 @@ ves_icall_System_Runtime_InteropServices_Marshal_PtrToStringUni (guint16 *ptr) while (*t++) len++; - return mono_string_new_utf16 (domain, ptr, len); + res = mono_string_new_utf16_checked (domain, ptr, len, &error); + if (!mono_error_ok (&error)) { + mono_error_set_pending_exception (&error); + return NULL; + } + return res; } MonoString * ves_icall_System_Runtime_InteropServices_Marshal_PtrToStringUni_len (guint16 *ptr, gint32 len) { + MonoError error; + MonoString *res = NULL; MonoDomain *domain = mono_domain_get (); + mono_error_init (&error); + if (ptr == NULL) { - mono_set_pending_exception (mono_get_exception_argument_null ("ptr")); - return NULL; + res = NULL; + mono_error_set_argument_null (&error, "ptr", ""); } else { - return mono_string_new_utf16 (domain, ptr, len); + res = mono_string_new_utf16_checked (domain, ptr, len, &error); } + + if (!mono_error_ok (&error)) + mono_error_set_pending_exception (&error); + return res; } guint32 @@ -10289,6 +10577,7 @@ ves_icall_System_Runtime_InteropServices_Marshal_SizeOf (MonoReflectionType *rty void ves_icall_System_Runtime_InteropServices_Marshal_StructureToPtr (MonoObject *obj, gpointer dst, MonoBoolean delete_old) { + MonoError error; MonoMethod *method; gpointer pa [3]; @@ -10301,27 +10590,32 @@ ves_icall_System_Runtime_InteropServices_Marshal_StructureToPtr (MonoObject *obj pa [1] = &dst; pa [2] = &delete_old; - mono_runtime_invoke (method, NULL, pa, NULL); + mono_runtime_invoke_checked (method, NULL, pa, &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) { 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 (method, NULL, pa, NULL); + 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,); @@ -10340,12 +10634,15 @@ 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 * ves_icall_System_Runtime_InteropServices_Marshal_PtrToStructure_type (gpointer src, MonoReflectionType *type) { + MonoError error; MonoClass *klass; MonoDomain *domain = mono_domain_get (); MonoObject *res; @@ -10360,9 +10657,17 @@ ves_icall_System_Runtime_InteropServices_Marshal_PtrToStructure_type (gpointer s return NULL; } - res = mono_object_new (domain, klass); + res = mono_object_new_checked (domain, klass, &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; } @@ -10545,8 +10850,10 @@ ves_icall_System_Runtime_InteropServices_Marshal_AllocHGlobal (gpointer size) #else res = g_try_malloc (s); #endif - if (!res) - mono_gc_out_of_memory (s); + if (!res) { + mono_set_pending_exception (mono_domain_get ()->out_of_memory_ex); + return NULL; + } return res; } @@ -10558,7 +10865,7 @@ ves_icall_System_Runtime_InteropServices_Marshal_ReAllocHGlobal (gpointer ptr, g size_t s = (size_t)size; if (ptr == NULL) { - mono_gc_out_of_memory (s); + mono_set_pending_exception (mono_domain_get ()->out_of_memory_ex); return NULL; } @@ -10567,8 +10874,10 @@ ves_icall_System_Runtime_InteropServices_Marshal_ReAllocHGlobal (gpointer ptr, g #else res = g_try_realloc (ptr, s); #endif - if (!res) - mono_gc_out_of_memory (s); + if (!res) { + mono_set_pending_exception (mono_domain_get ()->out_of_memory_ex); + return NULL; + } return res; } @@ -10597,8 +10906,10 @@ ves_icall_System_Runtime_InteropServices_Marshal_AllocCoTaskMem (int size) res = g_try_malloc ((gulong)size); #endif - if (!res) - mono_gc_out_of_memory ((gulong)size); + if (!res) { + mono_set_pending_exception (mono_domain_get ()->out_of_memory_ex); + return NULL; + } return res; } @@ -10622,8 +10933,10 @@ ves_icall_System_Runtime_InteropServices_Marshal_ReAllocCoTaskMem (gpointer ptr, #else res = g_try_realloc (ptr, (gulong)size); #endif - if (!res) - mono_gc_out_of_memory ((gulong)size); + if (!res) { + mono_set_pending_exception (mono_domain_get ()->out_of_memory_ex); + return NULL; + } return res; } @@ -10645,6 +10958,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: * @@ -11021,9 +11340,11 @@ 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) { + MonoError error; MonoType *t; MonoClass *klass; @@ -11076,7 +11397,11 @@ mono_marshal_asany (MonoObject *o, MonoMarshalNative string_encoding, int param_ klass->blittable || klass->enumtype)) return mono_object_unbox (o); - res = mono_marshal_alloc (mono_class_native_size (klass, NULL)); + res = mono_marshal_alloc (mono_class_native_size (klass, NULL), &error); + 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); @@ -11085,7 +11410,11 @@ mono_marshal_asany (MonoObject *o, MonoMarshalNative string_encoding, int param_ pa [1] = &res; pa [2] = &delete_old; - mono_runtime_invoke (method, NULL, pa, NULL); + mono_runtime_invoke_checked (method, NULL, pa, &error); + if (!mono_error_ok (&error)) { + mono_error_set_pending_exception (&error); + return NULL; + } } return res; @@ -11093,13 +11422,15 @@ 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) { + MonoError error; MonoType *t; MonoClass *klass; @@ -11134,7 +11465,11 @@ mono_marshal_free_asany (MonoObject *o, gpointer ptr, MonoMarshalNative string_e pa [0] = &ptr; pa [1] = o; - mono_runtime_invoke (method, NULL, pa, NULL); + mono_runtime_invoke_checked (method, NULL, pa, &error); + if (!mono_error_ok (&error)) { + mono_error_set_pending_exception (&error); + return; + } } if (!((param_attrs & PARAM_ATTRIBUTE_OUT) && !(param_attrs & PARAM_ATTRIBUTE_IN))) {