X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mono%2Fmetadata%2Fmarshal.c;h=18f93d260e3897cc70f53bbfde9b45a0229526fb;hb=56ad8f4e5dfb8198e4671f631a3103b1e8b83dd3;hp=0ba52be2b9e3622c97b5de9b9ca93d1cd872962f;hpb=9ed6d805bbcd8b60ea28f8bfa5e707059dcef342;p=mono.git diff --git a/mono/metadata/marshal.c b/mono/metadata/marshal.c index 0ba52be2b9e..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" @@ -211,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* @@ -237,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) { @@ -284,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); @@ -352,7 +362,7 @@ 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; @@ -450,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; @@ -459,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; @@ -515,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); @@ -1839,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); } } } @@ -2201,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 @@ -3167,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; @@ -4411,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; @@ -4443,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); @@ -4940,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 */ @@ -5021,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); @@ -7215,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; @@ -7251,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); } @@ -7261,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 */ /* @@ -7281,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) @@ -7290,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); @@ -7340,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 */ @@ -7354,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: @@ -7401,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. @@ -7438,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 */ @@ -7873,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 (); @@ -7965,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) { @@ -8131,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; @@ -8141,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 @@ -8195,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) { @@ -8501,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) @@ -9404,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: */ @@ -9518,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 */ @@ -9844,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));