X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mono%2Fmetadata%2Fmarshal.c;h=0e622038db80c04f7079df339dfe1027970c8b0f;hb=0be4b9d8f775612c61487226ba0f1a721b9779fa;hp=e52181c4c50610109c2e2040cb1e240f06f48c4c;hpb=c630b50e05a65e5945205fd979eb152da74192b0;p=mono.git diff --git a/mono/metadata/marshal.c b/mono/metadata/marshal.c index e52181c4c50..0e622038db8 100644 --- a/mono/metadata/marshal.c +++ b/mono/metadata/marshal.c @@ -50,13 +50,6 @@ typedef enum { MONO_MARSHAL_SERIALIZE /* Value needs to be serialized into the new domain */ } MonoXDomainMarshalType; -typedef enum { - MONO_COM_DEFAULT, - MONO_COM_MS -} MonoCOMProvider; - -static MonoCOMProvider com_provider = MONO_COM_DEFAULT; - enum { #include "mono/cil/opcode.def" LAST = 0xff @@ -104,12 +97,6 @@ mono_marshal_string_to_utf16_copy (MonoString *s); static gpointer mono_string_to_lpstr (MonoString *string_obj); -static MonoString * -mono_string_from_bstr (gpointer bstr); - -static void -mono_free_bstr (gpointer bstr); - static MonoStringBuilder * mono_string_utf8_to_builder2 (char *text); @@ -217,9 +204,6 @@ mono_marshal_init (void) register_icall (mono_string_new_wrapper, "mono_string_new_wrapper", "obj ptr", FALSE); register_icall (mono_string_to_utf8, "mono_string_to_utf8", "ptr obj", FALSE); register_icall (mono_string_to_lpstr, "mono_string_to_lpstr", "ptr obj", FALSE); - register_icall (mono_string_to_bstr, "mono_string_to_bstr", "ptr obj", FALSE); - register_icall (mono_string_from_bstr, "mono_string_from_bstr", "obj ptr", FALSE); - register_icall (mono_free_bstr, "mono_free_bstr", "void ptr", FALSE); register_icall (mono_string_to_ansibstr, "mono_string_to_ansibstr", "ptr object", FALSE); register_icall (mono_string_builder_to_utf8, "mono_string_builder_to_utf8", "ptr object", FALSE); register_icall (mono_string_builder_to_utf16, "mono_string_builder_to_utf16", "ptr object", FALSE); @@ -330,6 +314,18 @@ mono_delegate_to_ftnptr (MonoDelegate *delegate) method = delegate->method; + if (mono_method_signature (method)->pinvoke) { + 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)); + } + return ftnptr; + } + wrapper = mono_marshal_get_managed_wrapper (method, klass, delegate->target); delegate->delegate_trampoline = mono_compile_method (wrapper); @@ -399,6 +395,9 @@ mono_ftnptr_to_delegate (MonoClass *klass, gpointer ftn) #endif MonoDelegate *d; + if (ftn == NULL) + return NULL; + mono_marshal_lock (); if (delegate_hash_table == NULL) delegate_hash_table = delegate_hash_table_new (); @@ -769,137 +768,6 @@ mono_string_to_ansibstr (MonoString *string_obj) return NULL; } -typedef gpointer (*SysAllocStringLenFunc)(gunichar* str, guint32 len); -typedef guint32 (*SysStringLenFunc)(gpointer bstr); -typedef void (*SysFreeStringFunc)(gunichar* str); - -static SysAllocStringLenFunc sys_alloc_string_len_ms = NULL; -static SysStringLenFunc sys_string_len_ms = NULL; -static SysFreeStringFunc sys_free_string_ms = NULL; - -static gboolean -init_com_provider_ms (void) -{ - static gboolean initialized = FALSE; - char *error_msg; - MonoDl *module = NULL; - const char* scope = "liboleaut32.so"; - - if (initialized) - return TRUE; - - module = mono_dl_open(scope, MONO_DL_LAZY, &error_msg); - if (error_msg) { - g_warning ("Error loading COM support library '%s': %s", scope, error_msg); - g_assert_not_reached (); - return FALSE; - } - error_msg = mono_dl_symbol (module, "SysAllocStringLen", (gpointer*)&sys_alloc_string_len_ms); - if (error_msg) { - g_warning ("Error loading entry point '%s' in COM support library '%s': %s", "SysAllocStringLen", scope, error_msg); - g_assert_not_reached (); - return FALSE; - } - - error_msg = mono_dl_symbol (module, "SysStringLen", (gpointer*)&sys_string_len_ms); - if (error_msg) { - g_warning ("Error loading entry point '%s' in COM support library '%s': %s", "SysStringLen", scope, error_msg); - g_assert_not_reached (); - return FALSE; - } - - error_msg = mono_dl_symbol (module, "SysFreeString", (gpointer*)&sys_free_string_ms); - if (error_msg) { - g_warning ("Error loading entry point '%s' in COM support library '%s': %s", "SysFreeString", scope, error_msg); - g_assert_not_reached (); - return FALSE; - } - - initialized = TRUE; - return TRUE; -} - -gpointer -mono_string_to_bstr (MonoString *string_obj) -{ - if (!string_obj) - return NULL; -#ifdef PLATFORM_WIN32 - return SysAllocStringLen (mono_string_chars (string_obj), mono_string_length (string_obj)); -#else - if (com_provider == MONO_COM_DEFAULT) { - int slen = mono_string_length (string_obj); - /* allocate len + 1 utf16 characters plus 4 byte integer for length*/ - char *ret = g_malloc ((slen + 1) * sizeof(gunichar2) + sizeof(guint32)); - if (ret == NULL) - return NULL; - memcpy (ret + sizeof(guint32), mono_string_chars (string_obj), slen * sizeof(gunichar2)); - * ((guint32 *) ret) = slen * sizeof(gunichar2); - ret [4 + slen * sizeof(gunichar2)] = 0; - ret [5 + slen * sizeof(gunichar2)] = 0; - - return ret + 4; - } else if (com_provider == MONO_COM_MS && init_com_provider_ms ()) { - gpointer ret = NULL; - gunichar* str = NULL; - guint32 len; - len = mono_string_length (string_obj); - str = g_utf16_to_ucs4 (mono_string_chars (string_obj), len, - NULL, NULL, NULL); - ret = sys_alloc_string_len_ms (str, len); - g_free(str); - return ret; - } else { - g_assert_not_reached (); - } -#endif -} - -MonoString * -mono_string_from_bstr (gpointer bstr) -{ - if (!bstr) - return NULL; -#ifdef PLATFORM_WIN32 - return mono_string_new_utf16 (mono_domain_get (), bstr, SysStringLen (bstr)); -#else - if (com_provider == MONO_COM_DEFAULT) { - return mono_string_new_utf16 (mono_domain_get (), bstr, *((guint32 *)bstr - 1) / sizeof(gunichar2)); - } else if (com_provider == MONO_COM_MS && init_com_provider_ms ()) { - MonoString* str = NULL; - glong written = 0; - gunichar2* utf16 = NULL; - - utf16 = g_ucs4_to_utf16 (bstr, sys_string_len_ms (bstr), NULL, &written, NULL); - str = mono_string_new_utf16 (mono_domain_get (), utf16, written); - g_free (utf16); - return str; - } else { - g_assert_not_reached (); - } - -#endif -} - -void -mono_free_bstr (gpointer bstr) -{ - if (!bstr) - return; -#ifdef PLATFORM_WIN32 - SysFreeString ((BSTR)bstr); -#else - if (com_provider == MONO_COM_DEFAULT) { - g_free (((char *)bstr) - 4); - } else if (com_provider == MONO_COM_MS && init_com_provider_ms ()) { - sys_free_string_ms (bstr); - } else { - g_assert_not_reached (); - } - -#endif -} - /** * mono_string_to_byvalstr: * @dst: Where to store the null-terminated utf8 decoded string. @@ -3971,9 +3839,13 @@ runtime_invoke_signature_equal (MonoMethodSignature *sig1, MonoMethodSignature * * MonoObject *runtime_invoke (MonoObject *this, void **params, MonoObject **exc, void* method) * * we also catch exceptions if exc != null + * If VIRTUAL is TRUE, then METHOD is invoked virtually on THIS. This is useful since + * it means that the compiled code for METHOD does not have to be looked up + * before calling the runtime invoke wrapper. In this case, the wrapper ignores + * its METHOD argument. */ MonoMethod * -mono_marshal_get_runtime_invoke (MonoMethod *method) +mono_marshal_get_runtime_invoke (MonoMethod *method, gboolean virtual) { MonoMethodSignature *sig, *csig, *callsig; MonoExceptionClause *clause; @@ -4001,11 +3873,17 @@ mono_marshal_get_runtime_invoke (MonoMethod *method) 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. */ - cache = get_cache (&method->klass->image->runtime_invoke_direct_cache, mono_aligned_addr_hash, NULL); + if (virtual) + cache = get_cache (&method->klass->image->runtime_invoke_vcall_cache, mono_aligned_addr_hash, NULL); + else + cache = get_cache (&method->klass->image->runtime_invoke_direct_cache, mono_aligned_addr_hash, NULL); res = mono_marshal_find_in_cache (cache, method); if (res) return res; @@ -4023,6 +3901,8 @@ mono_marshal_get_runtime_invoke (MonoMethod *method) 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->klass->valuetype && mono_method_signature (method)->hasthis) { /* @@ -4118,7 +3998,7 @@ mono_marshal_get_runtime_invoke (MonoMethod *method) csig->params [2] = &mono_defaults.int_class->byval_arg; csig->params [3] = &mono_defaults.int_class->byval_arg; - name = mono_signature_to_name (callsig, "runtime_invoke"); + name = mono_signature_to_name (callsig, virtual ? "runtime_invoke_virtual" : "runtime_invoke"); mb = mono_mb_new (target_klass, name, MONO_WRAPPER_RUNTIME_INVOKE); g_free (name); @@ -4137,6 +4017,11 @@ mono_marshal_get_runtime_invoke (MonoMethod *method) emit_thread_force_interrupt_checkpoint (mb); + if (virtual) { + g_assert (sig->hasthis); + g_assert (method->flags & METHOD_ATTRIBUTE_VIRTUAL); + } + if (sig->hasthis) { if (method->string_ctor) { mono_mb_emit_ptr (mb, string_dummy); @@ -4226,7 +4111,9 @@ handle_enum: } } - if (need_direct_wrapper) { + if (virtual) { + mono_mb_emit_op (mb, CEE_CALLVIRT, method); + } else if (need_direct_wrapper) { mono_mb_emit_op (mb, CEE_CALL, method); } else { mono_mb_emit_ldarg (mb, 3); @@ -4414,7 +4301,7 @@ mono_marshal_get_static_rgctx_invoke (MonoMethod *method) return res; if (!inited) { - mono_counters_register ("static rgctx invoke wrappers", + mono_counters_register ("Static rgctx invoke wrappers", MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &num_wrappers); inited = TRUE; } @@ -5971,17 +5858,19 @@ emit_marshal_object (EmitMarshalContext *m, int argnum, MonoType *t, MonoClass *klass = mono_class_from_mono_type (t); int pos, pos2, loc; - if (mono_class_from_mono_type (t) == mono_defaults.object_class) { - mono_raise_exception (mono_get_exception_not_implemented ("Marshalling of type object is not implemented")); - } - switch (action) { case MARSHAL_ACTION_CONV_IN: *conv_arg_type = &mono_defaults.int_class->byval_arg; conv_arg = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg); m->orig_conv_args [argnum] = 0; - + + if (mono_class_from_mono_type (t) == mono_defaults.object_class) { + char *msg = g_strdup_printf ("Marshalling of type object is not implemented"); + mono_mb_emit_exception_marshal_directive (mb, msg); + break; + } + if (klass->delegate) { if (t->byref) { if (!(t->attrs & PARAM_ATTRIBUTE_OUT)) { @@ -7263,6 +7152,8 @@ emit_marshal_boolean (EmitMarshalContext *m, int argnum, MonoType *t, case MARSHAL_ACTION_MANAGED_CONV_IN: { gint variant_bool = 0; guint8 ldop = CEE_LDIND_I4; + int label1; + if (!t->byref) break; @@ -7288,6 +7179,10 @@ emit_marshal_boolean (EmitMarshalContext *m, int argnum, MonoType *t, g_warning ("marshalling bool as native type %x is currently not supported", spec->native); } } + + /* Check null */ + mono_mb_emit_ldarg (mb, argnum); + label1 = mono_mb_emit_branch (mb, CEE_BRFALSE); mono_mb_emit_ldarg (mb, argnum); mono_mb_emit_byte (mb, ldop); @@ -7295,11 +7190,15 @@ emit_marshal_boolean (EmitMarshalContext *m, int argnum, MonoType *t, if (variant_bool) mono_mb_emit_byte (mb, CEE_NEG); mono_mb_emit_stloc (mb, conv_arg); + + mono_mb_patch_branch (mb, label1); break; } case MARSHAL_ACTION_MANAGED_CONV_OUT: { guint8 stop = CEE_STIND_I4; + int label1; + if (!t->byref) break; if (spec) { @@ -7315,12 +7214,18 @@ emit_marshal_boolean (EmitMarshalContext *m, int argnum, MonoType *t, break; } } + + /* Check null */ + mono_mb_emit_ldarg (mb, argnum); + label1 = mono_mb_emit_branch (mb, CEE_BRFALSE); mono_mb_emit_ldarg (mb, argnum); mono_mb_emit_ldloc (mb, conv_arg); if (spec != NULL && spec->native == MONO_NATIVE_VARIANTBOOL) mono_mb_emit_byte (mb, CEE_NEG); mono_mb_emit_byte (mb, stop); + + mono_mb_patch_branch (mb, label1); break; } @@ -7447,7 +7352,7 @@ emit_marshal (EmitMarshalContext *m, int argnum, MonoType *t, return mono_cominterop_emit_marshal_com_interface (m, argnum, t, spec, conv_arg, conv_arg_type, action); #endif - if (mono_defaults.safehandle_class != NULL && + if (mono_defaults.safehandle_class != NULL && t->data.klass && mono_class_is_subclass_of (t->data.klass, mono_defaults.safehandle_class, FALSE)) return emit_marshal_safehandle (m, argnum, t, spec, conv_arg, conv_arg_type, action); @@ -9473,30 +9378,6 @@ ves_icall_System_Runtime_InteropServices_Marshal_PtrToStringUni_len (guint16 *pt } } -MonoString * -ves_icall_System_Runtime_InteropServices_Marshal_PtrToStringBSTR (gpointer ptr) -{ - MONO_ARCH_SAVE_REGS; - - return mono_string_from_bstr(ptr); -} - -gpointer -ves_icall_System_Runtime_InteropServices_Marshal_StringToBSTR (MonoString* ptr) -{ - MONO_ARCH_SAVE_REGS; - - return mono_string_to_bstr(ptr); -} - -void -ves_icall_System_Runtime_InteropServices_Marshal_FreeBSTR (gpointer ptr) -{ - MONO_ARCH_SAVE_REGS; - - mono_free_bstr (ptr); -} - guint32 ves_icall_System_Runtime_InteropServices_Marshal_GetLastWin32Error (void) {