X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mono%2Fmetadata%2Fmarshal.c;h=05b23fddf3feae116697913694a6033b94c022df;hb=HEAD;hp=29d03b8d7ac91338b11248723bbc155f3214c27d;hpb=a0bf70a140b4b6eb96273b2f7cfab7423dc6940b;p=mono.git diff --git a/mono/metadata/marshal.c b/mono/metadata/marshal.c index 29d03b8d7ac..05b23fddf3f 100644 --- a/mono/metadata/marshal.c +++ b/mono/metadata/marshal.c @@ -375,8 +375,8 @@ mono_marshal_init (void) register_icall (mono_marshal_free_asany, "mono_marshal_free_asany", "void object ptr int32 int32", FALSE); register_icall (ves_icall_marshal_alloc, "ves_icall_marshal_alloc", "ptr ptr", 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); + register_icall (mono_marshal_set_last_error, "mono_marshal_set_last_error", "void", TRUE); + register_icall (mono_marshal_set_last_error_windows, "mono_marshal_set_last_error_windows", "void int32", TRUE); register_icall (mono_string_utf8_to_builder, "mono_string_utf8_to_builder", "void ptr ptr", FALSE); register_icall (mono_string_utf8_to_builder2, "mono_string_utf8_to_builder2", "object ptr", FALSE); register_icall (mono_string_utf16_to_builder, "mono_string_utf16_to_builder", "void ptr ptr", FALSE); @@ -799,12 +799,13 @@ mono_array_to_lparray (MonoArray *array) int i = 0; MonoClass *klass; + MonoError error; #endif if (!array) return NULL; #ifndef DISABLE_COM - + error_init (&error); klass = array->obj.vtable->klass; switch (klass->element_class->byval_arg.type) { @@ -813,9 +814,12 @@ mono_array_to_lparray (MonoArray *array) break; case MONO_TYPE_CLASS: nativeArraySize = array->max_length; - nativeArray = (void **)malloc(sizeof(gpointer) * nativeArraySize); - for(i = 0; i < nativeArraySize; ++i) - nativeArray[i] = ves_icall_System_Runtime_InteropServices_Marshal_GetIUnknownForObjectInternal(((MonoObject **)array->vector)[i]); + nativeArray = (void **)g_malloc (sizeof(gpointer) * nativeArraySize); + for(i = 0; i < nativeArraySize; ++i) { + nativeArray[i] = mono_cominterop_get_com_interface (((MonoObject **)array->vector)[i], klass->element_class, &error); + if (mono_error_set_pending_exception (&error)) + break; + } return nativeArray; case MONO_TYPE_U1: case MONO_TYPE_BOOLEAN: @@ -853,7 +857,6 @@ mono_free_lparray (MonoArray *array, gpointer* nativeArray) { #ifndef DISABLE_COM MonoClass *klass; - int i = 0; if (!array) return; @@ -862,11 +865,8 @@ mono_free_lparray (MonoArray *array, gpointer* nativeArray) return; klass = array->obj.vtable->klass; - if (klass->element_class->byval_arg.type == MONO_TYPE_CLASS) { - for(i = 0; i < array->max_length; ++i) - mono_marshal_free_ccw (mono_array_get (array, MonoObject*, i)); + if (klass->element_class->byval_arg.type == MONO_TYPE_CLASS) g_free (nativeArray); - } #endif } @@ -4306,7 +4306,7 @@ emit_runtime_invoke_body (MonoMethodBuilder *mb, MonoImage *image, MonoMethod *m * its \p method argument. */ MonoMethod * -mono_marshal_get_runtime_invoke (MonoMethod *method, gboolean virtual_) +mono_marshal_get_runtime_invoke_full (MonoMethod *method, gboolean virtual_, gboolean need_direct_wrapper) { MonoMethodSignature *sig, *csig, *callsig; MonoMethodBuilder *mb; @@ -4317,7 +4317,6 @@ mono_marshal_get_runtime_invoke (MonoMethod *method, gboolean virtual_) static MonoMethodSignature *finalize_signature = NULL; char *name; const char *param_names [16]; - gboolean need_direct_wrapper = FALSE; WrapperInfo *info; g_assert (method); @@ -4332,9 +4331,6 @@ mono_marshal_get_runtime_invoke (MonoMethod *method, gboolean virtual_) finalize_signature->hasthis = 1; } - if (virtual_) - need_direct_wrapper = TRUE; - /* * Use a separate cache indexed by methods to speed things up and to avoid the * boundless mempool growth caused by the signature_dup stuff below. @@ -4348,21 +4344,10 @@ mono_marshal_get_runtime_invoke (MonoMethod *method, gboolean virtual_) if (res) return res; - if (method->klass->rank && (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) && - (method->iflags & METHOD_IMPL_ATTRIBUTE_NATIVE)) { - /* - * Array Get/Set/Address methods. The JIT implements them using inline code - * so we need to create an invoke wrapper which calls the method directly. - */ - need_direct_wrapper = TRUE; - } - if (method->string_ctor) { callsig = lookup_string_ctor_signature (mono_method_signature (method)); if (!callsig) callsig = add_string_ctor_signature (method); - /* Can't share this as we push a string as this */ - need_direct_wrapper = TRUE; } else { if (method_is_dynamic (method)) callsig = mono_metadata_signature_dup_full (method->klass->image, mono_method_signature (method)); @@ -4431,7 +4416,7 @@ mono_marshal_get_runtime_invoke (MonoMethod *method, gboolean virtual_) csig->call_convention = MONO_CALL_C; #endif - name = mono_signature_to_name (callsig, virtual_ ? "runtime_invoke_virtual" : "runtime_invoke"); + name = mono_signature_to_name (callsig, virtual_ ? "runtime_invoke_virtual" : (need_direct_wrapper ? "runtime_invoke_direct" : "runtime_invoke")); mb = mono_mb_new (target_klass, name, MONO_WRAPPER_RUNTIME_INVOKE); g_free (name); @@ -4490,6 +4475,34 @@ mono_marshal_get_runtime_invoke (MonoMethod *method, gboolean virtual_) return res; } +MonoMethod * +mono_marshal_get_runtime_invoke (MonoMethod *method, gboolean virtual_) +{ + gboolean need_direct_wrapper = FALSE; + + if (virtual_) + need_direct_wrapper = TRUE; + + if (method->dynamic) + need_direct_wrapper = TRUE; + + if (method->klass->rank && (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) && + (method->iflags & METHOD_IMPL_ATTRIBUTE_NATIVE)) { + /* + * Array Get/Set/Address methods. The JIT implements them using inline code + * so we need to create an invoke wrapper which calls the method directly. + */ + need_direct_wrapper = TRUE; + } + + if (method->string_ctor) { + /* Can't share this as we push a string as this */ + need_direct_wrapper = TRUE; + } + + return mono_marshal_get_runtime_invoke_full (method, virtual_, need_direct_wrapper); +} + /* * mono_marshal_get_runtime_invoke_dynamic: * @@ -7645,6 +7658,9 @@ mono_marshal_emit_native_wrapper (MonoImage *image, MonoMethodBuilder *mb, MonoM int i, argnum, *tmp_locals; int type, param_shift = 0; int coop_gc_stack_dummy, coop_gc_var; +#ifndef DISABLE_COM + int coop_cominterop_fnptr; +#endif memset (&m, 0, sizeof (m)); m.mb = mb; @@ -7682,11 +7698,16 @@ mono_marshal_emit_native_wrapper (MonoImage *image, MonoMethodBuilder *mb, MonoM mono_mb_add_local (mb, sig->ret); } - if (mono_threads_is_coop_enabled ()) { + if (mono_threads_is_blocking_transition_enabled ()) { /* local 4, dummy local used to get a stack address for suspend funcs */ 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); +#ifndef DISABLE_COM + if (!func_param && MONO_CLASS_IS_IMPORT (mb->method->klass)) { + coop_cominterop_fnptr = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg); + } +#endif } /* @@ -7723,7 +7744,7 @@ mono_marshal_emit_native_wrapper (MonoImage *image, MonoMethodBuilder *mb, MonoM } // In coop mode need to register blocking state during native call - if (mono_threads_is_coop_enabled ()) { + if (mono_threads_is_blocking_transition_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) { @@ -7732,6 +7753,13 @@ mono_marshal_emit_native_wrapper (MonoImage *image, MonoMethodBuilder *mb, MonoM mono_mb_emit_byte (mb, CEE_POP); // Result not needed yet } +#ifndef DISABLE_COM + if (!func_param && MONO_CLASS_IS_IMPORT (mb->method->klass)) { + mono_mb_emit_cominterop_get_function_pointer (mb, &piinfo->method); + mono_mb_emit_stloc (mb, coop_cominterop_fnptr); + } +#endif + mono_mb_emit_ldloc_addr (mb, coop_gc_stack_dummy); mono_mb_emit_icall (mb, mono_threads_enter_gc_safe_region_unbalanced); mono_mb_emit_stloc (mb, coop_gc_var); @@ -7754,7 +7782,12 @@ mono_marshal_emit_native_wrapper (MonoImage *image, MonoMethodBuilder *mb, MonoM mono_mb_emit_calli (mb, csig); } else if (MONO_CLASS_IS_IMPORT (mb->method->klass)) { #ifndef DISABLE_COM - mono_mb_emit_cominterop_call (mb, csig, &piinfo->method); + if (!mono_threads_is_blocking_transition_enabled ()) { + mono_mb_emit_cominterop_call (mb, csig, &piinfo->method); + } else { + mono_mb_emit_ldloc (mb, coop_cominterop_fnptr); + mono_mb_emit_cominterop_call_function_pointer (mb, csig); + } #else g_assert_not_reached (); #endif @@ -7808,7 +7841,7 @@ mono_marshal_emit_native_wrapper (MonoImage *image, MonoMethodBuilder *mb, MonoM } /* Unblock before converting the result, since that can involve calls into the runtime */ - if (mono_threads_is_coop_enabled ()) { + if (mono_threads_is_blocking_transition_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_exit_gc_safe_region_unbalanced); @@ -8577,7 +8610,7 @@ mono_marshal_emit_managed_wrapper (MonoMethodBuilder *mb, MonoMethodSignature *i /* try { */ clause_catch->try_offset = clause_finally->try_offset = mono_mb_get_label (mb); - if (!mono_threads_is_coop_enabled ()) { + if (!mono_threads_is_blocking_transition_enabled ()) { mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX); mono_mb_emit_byte (mb, CEE_MONO_JIT_ATTACH); } else { @@ -8585,6 +8618,10 @@ mono_marshal_emit_managed_wrapper (MonoMethodBuilder *mb, MonoMethodSignature *i mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX); mono_mb_emit_byte (mb, CEE_MONO_LDDOMAIN); mono_mb_emit_ldloc_addr (mb, attach_dummy_local); + /* + * This icall is special cased in the JIT so it works in native-to-managed wrappers in unattached threads. + * Keep this in sync with the CEE_JIT_ICALL code in the JIT. + */ mono_mb_emit_icall (mb, mono_threads_attach_coop); mono_mb_emit_stloc (mb, attach_cookie_local); } @@ -8755,7 +8792,7 @@ mono_marshal_emit_managed_wrapper (MonoMethodBuilder *mb, MonoMethodSignature *i clause_finally->try_len = mono_mb_get_label (mb) - clause_finally->try_offset; clause_finally->handler_offset = mono_mb_get_label (mb); - if (!mono_threads_is_coop_enabled ()) { + if (!mono_threads_is_blocking_transition_enabled ()) { mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX); mono_mb_emit_byte (mb, CEE_MONO_JIT_DETACH); } else { @@ -10919,6 +10956,9 @@ mono_marshal_string_to_utf16_copy (MonoString *s) void mono_marshal_set_last_error (void) { + /* This icall is called just after a P/Invoke call before the P/Invoke + * wrapper transitions the runtime back to running mode. */ + MONO_REQ_GC_SAFE_MODE; #ifdef WIN32 mono_native_tls_set_value (last_error_tls_id, GINT_TO_POINTER (GetLastError ())); #else @@ -10930,6 +10970,9 @@ static void mono_marshal_set_last_error_windows (int error) { #ifdef WIN32 + /* This icall is called just after a P/Invoke call before the P/Invoke + * wrapper transitions the runtime back to running mode. */ + MONO_REQ_GC_SAFE_MODE; mono_native_tls_set_value (last_error_tls_id, GINT_TO_POINTER (error)); #endif } @@ -11573,7 +11616,6 @@ mono_marshal_load_type_info (MonoClass* klass) layout = mono_class_get_flags (klass) & TYPE_ATTRIBUTE_LAYOUT_MASK; - /* The mempool is protected by the loader lock */ info = (MonoMarshalType *)mono_image_alloc0 (klass->image, MONO_SIZEOF_MARSHAL_TYPE + sizeof (MonoMarshalField) * count); info->num_fields = count; @@ -11660,8 +11702,11 @@ mono_marshal_load_type_info (MonoClass* klass) info->min_align = min_align; /* Update the class's blittable info, if the layouts don't match */ - if (info->native_size != mono_class_value_size (klass, NULL)) + if (info->native_size != mono_class_value_size (klass, NULL)) { + mono_loader_lock (); klass->blittable = FALSE; + mono_loader_unlock (); + } /* If this is an array type, ensure that we have element info */ if (klass->rank && !mono_marshal_is_loading_type_info (klass->element_class)) { @@ -12347,7 +12392,7 @@ ftnptr_eh_callback_default (guint32 gchandle) mono_gchandle_free (gchandle); - mono_raise_exception (exc); + mono_reraise_exception (exc); } /*