X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mono%2Fmetadata%2Fmarshal.c;h=559ecc4cfe4fd1719890485054ac87c112628831;hb=032a79f8a2ba11382cb8c027bd5c979acd0c4a6a;hp=3c6768041b2089b6eba1d60a518d8464943ad3e5;hpb=2002994d0c06860d22253edbb7bae0ddcda7df44;p=mono.git diff --git a/mono/metadata/marshal.c b/mono/metadata/marshal.c index 3c6768041b2..559ecc4cfe4 100644 --- a/mono/metadata/marshal.c +++ b/mono/metadata/marshal.c @@ -143,18 +143,71 @@ 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 @@ -277,9 +330,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; @@ -304,7 +359,8 @@ mono_delegate_to_ftnptr (MonoDelegate *delegate) 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; } @@ -322,7 +378,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; } @@ -390,23 +450,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 { @@ -421,9 +481,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; @@ -478,12 +540,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; } @@ -539,9 +607,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; @@ -550,7 +621,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 @@ -672,6 +748,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) { @@ -683,9 +760,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)); @@ -707,6 +784,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) @@ -716,7 +795,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); @@ -730,12 +809,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); @@ -830,6 +910,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) @@ -840,7 +922,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); @@ -850,7 +931,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; @@ -858,7 +939,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); @@ -880,6 +962,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) @@ -897,7 +980,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'; @@ -924,6 +1010,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) { @@ -945,7 +1032,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); @@ -1794,7 +1881,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)); @@ -1824,7 +1911,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. @@ -2060,24 +2147,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. */ @@ -2097,9 +2186,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; } } @@ -2775,9 +2868,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; @@ -2791,7 +2886,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) @@ -2808,12 +2908,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; } @@ -2821,11 +2921,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 { @@ -2841,7 +2949,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); @@ -3063,11 +3171,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; @@ -4319,7 +4429,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; @@ -4671,7 +4781,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: @@ -7053,8 +7163,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); @@ -7739,9 +7849,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; @@ -7768,30 +7879,46 @@ mono_marshal_emit_managed_wrapper (MonoMethodBuilder *mb, MonoMethodSignature *i mono_mb_add_local (mb, sig->ret); } + /* + * 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); @@ -7815,8 +7942,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); @@ -7843,6 +7968,7 @@ 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 (mspecs [0] && mspecs [0]->native == MONO_NATIVE_CUSTOM) { @@ -7922,15 +8048,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); @@ -7942,6 +8084,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 @@ -7991,7 +8137,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; @@ -8046,12 +8192,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; @@ -8060,12 +8202,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; } @@ -10081,12 +10224,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; } @@ -10120,6 +10267,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) { @@ -10128,7 +10276,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; @@ -10251,6 +10402,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; @@ -10261,20 +10414,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 @@ -10320,6 +10486,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]; @@ -10332,27 +10499,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,); @@ -10371,12 +10543,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; @@ -10391,9 +10566,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; } @@ -10576,8 +10759,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; } @@ -10589,7 +10774,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; } @@ -10598,8 +10783,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; } @@ -10628,8 +10815,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; } @@ -10653,8 +10842,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; } @@ -10676,6 +10867,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: * @@ -11052,6 +11249,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) { @@ -11109,7 +11307,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); @@ -11118,7 +11319,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; @@ -11126,13 +11331,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; @@ -11167,7 +11374,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))) {