#include "loader.h"
#include "cil-coff.h"
#include "metadata/marshal.h"
+#include "metadata/marshal-internals.h"
#include "metadata/method-builder.h"
#include "metadata/tabledefs.h"
#include "metadata/exception.h"
#include <string.h>
#include <errno.h>
-#if defined(HOST_WIN32)
-#include <objbase.h>
-#endif
-
/* #define DEBUG_RUNTIME_CODE */
#define OPDEF(a,b,c,d,e,f,g,h,i,j) \
mono_marshal_string_to_utf16_copy (MonoString *s);
static gpointer
-mono_string_to_lpstr (MonoString *string_obj);
+mono_string_to_utf8str (MonoString *string_obj);
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_new_len_wrapper, "mono_string_new_len_wrapper", "obj ptr int", FALSE);
register_icall (ves_icall_mono_string_to_utf8, "ves_icall_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_utf8str, "mono_string_to_utf8str", "ptr obj", 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);
if (!sb || !text)
return;
- int len = strlen (text);
- if (len > mono_string_builder_capacity (sb))
- len = mono_string_builder_capacity (sb);
-
GError *error = NULL;
glong copied;
- gunichar2* ut = g_utf8_to_utf16 (text, len, NULL, &copied, &error);
+ gunichar2* ut = g_utf8_to_utf16 (text, strlen (text), NULL, &copied, &error);
+ int capacity = mono_string_builder_capacity (sb);
+
+ if (copied > capacity)
+ copied = capacity;
if (!error) {
MONO_OBJECT_SETREF (sb, chunkPrevious, NULL);
return sb;
}
-
void
mono_string_utf16_to_builder (MonoStringBuilder *sb, gunichar2 *text)
{
{
MonoError error;
GError *gerror = NULL;
-
+ glong byte_count;
if (!sb)
return NULL;
guint str_len = mono_string_builder_string_length (sb);
- gchar *tmp = g_utf16_to_utf8 (str_utf16, str_len, NULL, NULL, &gerror);
+ gchar *tmp = g_utf16_to_utf8 (str_utf16, str_len, NULL, &byte_count, &gerror);
if (gerror) {
g_error_free (gerror);
return NULL;
} else {
guint len = mono_string_builder_capacity (sb) + 1;
- gchar *res = (gchar *)mono_marshal_alloc (len * sizeof (gchar), &error);
+ gchar *res = (gchar *)mono_marshal_alloc (MAX (byte_count+1, len * sizeof (gchar)), &error);
if (!mono_error_ok (&error)) {
mono_marshal_free (str_utf16);
g_free (tmp);
return NULL;
}
- g_assert (str_len < len);
- memcpy (res, tmp, str_len * sizeof (gchar));
- res[str_len] = '\0';
+ memcpy (res, tmp, byte_count);
+ res[byte_count] = '\0';
mono_marshal_free (str_utf16);
g_free (tmp);
/* This is a JIT icall, it sets the pending exception and returns NULL on error. */
static gpointer
-mono_string_to_lpstr (MonoString *s)
+mono_string_to_utf8str (MonoString *s)
{
-#ifdef TARGET_WIN32
- char *as, *tmp;
- glong len;
- GError *error = NULL;
-
- if (s == NULL)
- return NULL;
-
- if (!s->length) {
- as = CoTaskMemAlloc (1);
- as [0] = '\0';
- return as;
- }
-
- tmp = g_utf16_to_utf8 (mono_string_chars (s), s->length, NULL, &len, &error);
- if (error) {
- MonoException *exc = mono_get_exception_argument ("string", error->message);
- g_error_free (error);
- mono_set_pending_exception (exc);
- return NULL;
- } else {
- as = CoTaskMemAlloc (len + 1);
- memcpy (as, tmp, len + 1);
- g_free (tmp);
- return as;
- }
-#else
MonoError error;
char *result = mono_string_to_utf8_checked (s, &error);
mono_error_set_pending_exception (&error);
return result;
-#endif
-}
+}
gpointer
mono_string_to_ansibstr (MonoString *string_obj)
#endif
mono_mb_emit_byte (mb, CEE_STIND_REF);
break;
+
+ // In Mono historically LPSTR was treated as a UTF8STR
case MONO_MARSHAL_CONV_STR_LPSTR:
+ case MONO_MARSHAL_CONV_STR_UTF8STR:
mono_mb_emit_ldloc (mb, 1);
mono_mb_emit_ldloc (mb, 0);
mono_mb_emit_byte (mb, CEE_LDIND_I);
case MONO_MARSHAL_CONV_LPTSTR_STR:
*ind_store_type = CEE_STIND_REF;
return mono_string_new_wrapper;
+ case MONO_MARSHAL_CONV_UTF8STR_STR:
case MONO_MARSHAL_CONV_LPSTR_STR:
*ind_store_type = CEE_STIND_REF;
return mono_string_new_wrapper;
#ifdef TARGET_WIN32
return mono_marshal_string_to_utf16;
#else
- return mono_string_to_lpstr;
+ return mono_string_to_utf8str;
#endif
+ // In Mono historically LPSTR was treated as a UTF8STR
+ case MONO_MARSHAL_CONV_STR_UTF8STR:
case MONO_MARSHAL_CONV_STR_LPSTR:
- return mono_string_to_lpstr;
+ return mono_string_to_utf8str;
case MONO_MARSHAL_CONV_STR_BSTR:
return mono_string_to_bstr;
case MONO_MARSHAL_CONV_BSTR_STR:
case MONO_MARSHAL_CONV_STR_TBSTR:
case MONO_MARSHAL_CONV_STR_ANSIBSTR:
return mono_string_to_ansibstr;
+ case MONO_MARSHAL_CONV_SB_UTF8STR:
case MONO_MARSHAL_CONV_SB_LPSTR:
return mono_string_builder_to_utf8;
case MONO_MARSHAL_CONV_SB_LPTSTR:
case MONO_MARSHAL_CONV_FTN_DEL:
*ind_store_type = CEE_STIND_REF;
return mono_ftnptr_to_delegate;
+ case MONO_MARSHAL_CONV_UTF8STR_SB:
case MONO_MARSHAL_CONV_LPSTR_SB:
*ind_store_type = CEE_STIND_REF;
return mono_string_utf8_to_builder;
mono_mb_emit_byte (mb, CEE_NEG);
mono_mb_emit_byte (mb, CEE_STIND_I2);
break;
+ // In Mono historically LPSTR was treated as a UTF8STR
+ case MONO_MARSHAL_CONV_STR_UTF8STR:
case MONO_MARSHAL_CONV_STR_LPWSTR:
case MONO_MARSHAL_CONV_STR_LPSTR:
case MONO_MARSHAL_CONV_STR_LPTSTR:
return MONO_MARSHAL_CONV_STR_LPTSTR;
case MONO_NATIVE_BSTR:
return MONO_MARSHAL_CONV_STR_BSTR;
+ case MONO_NATIVE_UTF8STR:
+ return MONO_MARSHAL_CONV_STR_UTF8STR;
default:
return MONO_MARSHAL_CONV_INVALID;
}
switch (encoding) {
case MONO_NATIVE_LPWSTR:
return MONO_MARSHAL_CONV_SB_LPWSTR;
- break;
case MONO_NATIVE_LPSTR:
return MONO_MARSHAL_CONV_SB_LPSTR;
- break;
+ case MONO_NATIVE_UTF8STR:
+ return MONO_MARSHAL_CONV_SB_UTF8STR;
case MONO_NATIVE_LPTSTR:
return MONO_MARSHAL_CONV_SB_LPTSTR;
- break;
default:
return MONO_MARSHAL_CONV_INVALID;
}
case MONO_NATIVE_LPWSTR:
*need_free = FALSE;
return MONO_MARSHAL_CONV_LPWSTR_STR;
+ case MONO_NATIVE_UTF8STR:
+ return MONO_MARSHAL_CONV_UTF8STR_STR;
case MONO_NATIVE_LPSTR:
case MONO_NATIVE_VBBYREFSTR:
return MONO_MARSHAL_CONV_LPSTR_STR;
*/
*need_free = FALSE;
return MONO_MARSHAL_CONV_LPWSTR_SB;
+ case MONO_NATIVE_UTF8STR:
+ return MONO_MARSHAL_CONV_UTF8STR_SB;
case MONO_NATIVE_LPSTR:
return MONO_MARSHAL_CONV_LPSTR_SB;
break;
{
MonoError error;
MonoMethod *inst, *res;
+ WrapperInfo *ginfo, *info;
/*
* We use the same cache for the generic definition and the instances.
inst = mono_class_inflate_generic_method_checked (def, ctx, &error);
g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
+ ginfo = mono_marshal_get_wrapper_info (def);
+ if (ginfo) {
+ info = (WrapperInfo *)mono_image_alloc0 (def->klass->image, sizeof (WrapperInfo));
+ info->subtype = ginfo->subtype;
+ if (info->subtype == WRAPPER_SUBTYPE_NONE) {
+ info->d.delegate_invoke.method = mono_class_inflate_generic_method_checked (ginfo->d.delegate_invoke.method, ctx, &error);
+ mono_error_assert_ok (&error);
+ }
+ }
+
mono_memory_barrier ();
mono_marshal_lock ();
res = (MonoMethod *)g_hash_table_lookup (cache, orig_method->klass);
MonoMethod *res;
GHashTable *cache;
gpointer cache_key = NULL;
- SignaturePointerPair key;
+ SignaturePointerPair key = { NULL, NULL };
SignaturePointerPair *new_key;
int local_i, local_len, local_delegates, local_d, local_target, local_res;
int pos0, pos1, pos2;
#endif /* DISABLE_JIT */
info = mono_wrapper_info_create (mb, subtype);
- info->d.delegate_invoke.method = orig_method;
+ info->d.delegate_invoke.method = method;
if (ctx) {
MonoMethod *def;
case MONO_NATIVE_LPSTR:
mono_mb_emit_icall (mb, mono_string_utf8_to_builder2);
break;
+ case MONO_NATIVE_UTF8STR:
+ mono_mb_emit_icall (mb, mono_string_utf8_to_builder2);
+ break;
default:
g_assert_not_reached ();
}
mono_mb_emit_ldloc (mb, 0);
mono_mb_emit_icall (mb, conv_to_icall (MONO_MARSHAL_CONV_FTN_DEL, NULL));
mono_mb_emit_stloc (mb, 3);
+ } else if (klass == mono_defaults.stringbuilder_class){
+ // FIXME: implement
} else {
/* set src */
mono_mb_emit_stloc (mb, 0);
encoding = mono_marshal_get_string_encoding (m->piinfo, spec);
// FIXME:
- g_assert (encoding == MONO_NATIVE_LPSTR);
+ g_assert (encoding == MONO_NATIVE_LPSTR || encoding == MONO_NATIVE_UTF8STR);
g_assert (!t->byref);
g_assert (encoding != -1);
mono_mb_emit_icon (mb, esize);
mono_mb_emit_byte (mb, CEE_MUL);
mono_mb_emit_byte (mb, CEE_PREFIX1);
- mono_mb_emit_byte (mb, CEE_CPBLK);
+ mono_mb_emit_byte (mb, CEE_CPBLK);
+ mono_mb_patch_branch (mb, label1);
break;
}
return res;
}
+#ifndef HOST_WIN32
+static inline void*
+mono_marshal_alloc_co_task_mem (size_t size)
+{
+ if ((gulong)size == 0)
+ /* This returns a valid pointer for size 0 on MS.NET */
+ size = 4;
+
+ return g_try_malloc ((gulong)size);
+}
+#endif
+
void*
mono_marshal_alloc (gulong size, MonoError *error)
{
mono_error_init (error);
-#ifdef HOST_WIN32
- res = CoTaskMemAlloc (size);
-#else
- res = g_try_malloc ((gulong)size);
+ res = mono_marshal_alloc_co_task_mem (size);
if (!res)
mono_error_set_out_of_memory (error, "Could not allocate %lu bytes", size);
-#endif
+
return res;
}
return ret;
}
-void
-mono_marshal_free (gpointer ptr)
+#ifndef HOST_WIN32
+static inline void
+mono_marshal_free_co_task_mem (void *ptr)
{
-#ifdef HOST_WIN32
- CoTaskMemFree (ptr);
-#else
g_free (ptr);
+ return;
+}
#endif
+
+void
+mono_marshal_free (gpointer ptr)
+{
+ mono_marshal_free_co_task_mem (ptr);
}
void
return info->fields [match_index].offset;
}
+#ifndef HOST_WIN32
gpointer
ves_icall_System_Runtime_InteropServices_Marshal_StringToHGlobalAnsi (MonoString *string)
{
MonoError error;
-#ifdef HOST_WIN32
- char* tres, *ret;
- size_t len;
- tres = mono_string_to_utf8_checked (string, &error);
- if (mono_error_set_pending_exception (&error))
- return NULL;
- if (!tres)
- return tres;
-
- /*
- * mono_string_to_utf8_checked() returns a memory area at least as large as the size of the
- * MonoString, even if it contains NULL characters. The copy we allocate here has to be equally
- * large.
- */
- len = MAX (strlen (tres) + 1, string->length);
- ret = ves_icall_System_Runtime_InteropServices_Marshal_AllocHGlobal (len);
- memcpy (ret, tres, len);
- g_free (tres);
- return ret;
-
-#else
char *ret = mono_string_to_utf8_checked (string, &error);
mono_error_set_pending_exception (&error);
return ret;
-#endif
}
gpointer
if (string == NULL)
return NULL;
else {
-#ifdef TARGET_WIN32
- gunichar2 *res = ves_icall_System_Runtime_InteropServices_Marshal_AllocHGlobal
- ((mono_string_length (string) + 1) * 2);
-#else
gunichar2 *res = (gunichar2 *)g_malloc ((mono_string_length (string) + 1) * 2);
-#endif
+
memcpy (res, mono_string_chars (string), mono_string_length (string) * 2);
res [mono_string_length (string)] = 0;
return res;
}
}
+#endif /* !HOST_WIN32 */
static void
mono_struct_delete_old (MonoClass *klass, char *ptr)
case MONO_MARSHAL_CONV_STR_BSTR:
case MONO_MARSHAL_CONV_STR_ANSIBSTR:
case MONO_MARSHAL_CONV_STR_TBSTR:
+ case MONO_MARSHAL_CONV_STR_UTF8STR:
mono_marshal_free (*(gpointer *)cpos);
break;
mono_struct_delete_old (klass, (char *)src);
}
+#ifndef HOST_WIN32
+static inline void *
+mono_marshal_alloc_hglobal (size_t size)
+{
+ return g_try_malloc (size);
+}
+#endif
+
void*
ves_icall_System_Runtime_InteropServices_Marshal_AllocHGlobal (gpointer size)
{
/* This returns a valid pointer for size 0 on MS.NET */
s = 4;
-#ifdef HOST_WIN32
- res = GlobalAlloc (GMEM_FIXED, s);
-#else
- res = g_try_malloc (s);
-#endif
+ res = mono_marshal_alloc_hglobal (s);
+
if (!res) {
mono_set_pending_exception (mono_domain_get ()->out_of_memory_ex);
return NULL;
return res;
}
+#ifndef HOST_WIN32
+static inline gpointer
+mono_marshal_realloc_hglobal (gpointer ptr, size_t size)
+{
+ return g_try_realloc (ptr, size);
+}
+#endif
+
gpointer
ves_icall_System_Runtime_InteropServices_Marshal_ReAllocHGlobal (gpointer ptr, gpointer size)
{
return NULL;
}
-#ifdef HOST_WIN32
- res = GlobalReAlloc (ptr, s, GMEM_MOVEABLE);
-#else
- res = g_try_realloc (ptr, s);
-#endif
+ res = mono_marshal_realloc_hglobal (ptr, s);
+
if (!res) {
mono_set_pending_exception (mono_domain_get ()->out_of_memory_ex);
return NULL;
return res;
}
-void
-ves_icall_System_Runtime_InteropServices_Marshal_FreeHGlobal (void *ptr)
+#ifndef HOST_WIN32
+static inline void
+mono_marshal_free_hglobal (gpointer ptr)
{
-#ifdef HOST_WIN32
- GlobalFree (ptr);
-#else
g_free (ptr);
+ return;
+}
#endif
+
+void
+ves_icall_System_Runtime_InteropServices_Marshal_FreeHGlobal (void *ptr)
+{
+ mono_marshal_free_hglobal (ptr);
}
void*
ves_icall_System_Runtime_InteropServices_Marshal_AllocCoTaskMem (int size)
{
- void *res;
+ void *res = mono_marshal_alloc_co_task_mem (size);
-#ifdef HOST_WIN32
- res = CoTaskMemAlloc (size);
-#else
- if ((gulong)size == 0)
- /* This returns a valid pointer for size 0 on MS.NET */
- size = 4;
+ if (!res) {
+ mono_set_pending_exception (mono_domain_get ()->out_of_memory_ex);
+ return NULL;
+ }
+ return res;
+}
+
+void*
+ves_icall_System_Runtime_InteropServices_Marshal_AllocCoTaskMemSize (gulong size)
+{
+ void *res = mono_marshal_alloc_co_task_mem (size);
- res = g_try_malloc ((gulong)size);
-#endif
if (!res) {
mono_set_pending_exception (mono_domain_get ()->out_of_memory_ex);
return NULL;
void
ves_icall_System_Runtime_InteropServices_Marshal_FreeCoTaskMem (void *ptr)
{
-#ifdef HOST_WIN32
- CoTaskMemFree (ptr);
-#else
- g_free (ptr);
-#endif
+ mono_marshal_free_co_task_mem (ptr);
+ return;
+}
+
+#ifndef HOST_WIN32
+static inline gpointer
+mono_marshal_realloc_co_task_mem (gpointer ptr, size_t size)
+{
+ return g_try_realloc (ptr, (gulong)size);
}
+#endif
gpointer
ves_icall_System_Runtime_InteropServices_Marshal_ReAllocCoTaskMem (gpointer ptr, int size)
{
- void *res;
+ void *res = mono_marshal_realloc_co_task_mem (ptr, size);
-#ifdef HOST_WIN32
- res = CoTaskMemRealloc (ptr, size);
-#else
- res = g_try_realloc (ptr, (gulong)size);
-#endif
if (!res) {
mono_set_pending_exception (mono_domain_get ()->out_of_memory_ex);
return NULL;
j++;
}
+ if (klass->byval_arg.type == MONO_TYPE_PTR)
+ info->native_size = sizeof (gpointer);
+
if (layout != TYPE_ATTRIBUTE_AUTO_LAYOUT) {
info->native_size = MAX (native_size, info->native_size);
/*
case MONO_NATIVE_BSTR:
case MONO_NATIVE_ANSIBSTR:
case MONO_NATIVE_TBSTR:
+ case MONO_NATIVE_UTF8STR:
case MONO_NATIVE_LPARRAY:
case MONO_NATIVE_SAFEARRAY:
case MONO_NATIVE_IUNKNOWN:
switch (string_encoding) {
case MONO_NATIVE_LPWSTR:
return mono_marshal_string_to_utf16_copy ((MonoString*)o);
- break;
case MONO_NATIVE_LPSTR:
- return mono_string_to_lpstr ((MonoString*)o);
- break;
+ case MONO_NATIVE_UTF8STR:
+ // Same code path, because in Mono, we treated strings as Utf8
+ return mono_string_to_utf8str ((MonoString*)o);
default:
g_warning ("marshaling conversion %d not implemented", string_encoding);
g_assert_not_reached ();
switch (string_encoding) {
case MONO_NATIVE_LPWSTR:
case MONO_NATIVE_LPSTR:
+ case MONO_NATIVE_UTF8STR:
mono_marshal_free (ptr);
break;
default: