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
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);
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);
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);
#endif
MonoDelegate *d;
+ if (ftn == NULL)
+ return NULL;
+
mono_marshal_lock ();
if (delegate_hash_table == NULL)
delegate_hash_table = delegate_hash_table_new ();
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.
* 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;
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;
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) {
/*
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);
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);
}
}
- 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);
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;
}
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)) {
case MARSHAL_ACTION_MANAGED_CONV_IN: {
gint variant_bool = 0;
guint8 ldop = CEE_LDIND_I4;
+ int label1;
+
if (!t->byref)
break;
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);
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) {
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;
}
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);
}
}
-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)
{