X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mono%2Fmetadata%2Fmarshal.c;h=9b7eca1ffce41cca0086710387a74c9d10f9157c;hb=e097ce511153036b9146ee9ca32b766b260e6d1e;hp=559ecc4cfe4fd1719890485054ac87c112628831;hpb=1f34699221d2b08cf6c4e648505d3cce227d2500;p=mono.git diff --git a/mono/metadata/marshal.c b/mono/metadata/marshal.c index 559ecc4cfe4..9b7eca1ffce 100644 --- a/mono/metadata/marshal.c +++ b/mono/metadata/marshal.c @@ -211,11 +211,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 +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) { @@ -284,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); @@ -352,7 +361,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; @@ -519,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); @@ -1843,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); } } } @@ -2205,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 @@ -4417,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; @@ -4449,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); @@ -4946,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 */ @@ -5027,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); @@ -7221,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; @@ -7257,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); } @@ -7267,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 */ /* @@ -7287,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) @@ -7296,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); @@ -7346,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 */ @@ -7360,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: @@ -7407,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. @@ -7444,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 */ @@ -7879,6 +7954,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 (); @@ -7971,6 +8049,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) { @@ -8148,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 @@ -8509,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) @@ -9412,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: */ @@ -9526,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 */ @@ -9852,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));