#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"
emit_struct_conv (MonoMethodBuilder *mb, MonoClass *klass, gboolean to_object);
static void
-emit_struct_conv_full (MonoMethodBuilder *mb, MonoClass *klass, gboolean to_object, MonoMarshalNative string_encoding);
+emit_struct_conv_full (MonoMethodBuilder *mb, MonoClass *klass, gboolean to_object, int offset_of_first_child_field, MonoMarshalNative string_encoding);
static void
mono_struct_delete_old (MonoClass *klass, char *ptr);
static void *
mono_marshal_string_to_utf16_copy (MonoString *s);
+#ifndef HOST_WIN32
static gpointer
mono_string_to_lpstr (MonoString *string_obj);
+#endif
static MonoStringBuilder *
mono_string_utf8_to_builder2 (char *text);
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));
- free(nativeArray);
+ g_free (nativeArray);
}
#endif
}
}
/* This is a JIT icall, it sets the pending exception and returns NULL on error. */
+#ifndef HOST_WIN32
static gpointer
mono_string_to_lpstr (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
-}
+}
+#endif /* HOST_WIN32 */
gpointer
mono_string_to_ansibstr (MonoString *string_obj)
}
}
+static int offset_of_first_nonstatic_field(MonoClass *klass)
+{
+ int i;
+ for (i = 0; i < klass->field.count; i++) {
+ if (!(klass->fields[i].type->attrs & FIELD_ATTRIBUTE_STATIC) && !mono_field_is_deleted (&klass->fields[i]))
+ return klass->fields[i].offset - sizeof (MonoObject);
+ }
+
+ return 0;
+}
+
static void
emit_struct_conv_full (MonoMethodBuilder *mb, MonoClass *klass, gboolean to_object,
- MonoMarshalNative string_encoding)
+ int offset_of_first_child_field, MonoMarshalNative string_encoding)
{
MonoMarshalType *info;
int i;
if (klass->parent)
- emit_struct_conv(mb, klass->parent, to_object);
+ emit_struct_conv_full (mb, klass->parent, to_object, offset_of_first_nonstatic_field (klass), string_encoding);
info = mono_marshal_load_type_info (klass);
return;
if (klass->blittable) {
- int msize = mono_class_value_size (klass, NULL);
- g_assert (msize == info->native_size);
+ int usize = mono_class_value_size (klass, NULL);
+ g_assert (usize == info->native_size);
mono_mb_emit_ldloc (mb, 1);
mono_mb_emit_ldloc (mb, 0);
- mono_mb_emit_icon (mb, msize);
+ mono_mb_emit_icon (mb, usize);
mono_mb_emit_byte (mb, CEE_PREFIX1);
mono_mb_emit_byte (mb, CEE_CPBLK);
- mono_mb_emit_add_to_local (mb, 0, msize);
- mono_mb_emit_add_to_local (mb, 1, msize);
+ if (to_object) {
+ mono_mb_emit_add_to_local (mb, 0, usize);
+ mono_mb_emit_add_to_local (mb, 1, offset_of_first_child_field);
+ } else {
+ mono_mb_emit_add_to_local (mb, 0, offset_of_first_child_field);
+ mono_mb_emit_add_to_local (mb, 1, usize);
+ }
return;
}
static void
emit_struct_conv (MonoMethodBuilder *mb, MonoClass *klass, gboolean to_object)
{
- emit_struct_conv_full (mb, klass, to_object, (MonoMarshalNative)-1);
+ emit_struct_conv_full (mb, klass, to_object, 0, (MonoMarshalNative)-1);
}
static void
return info->d.runtime_invoke.method;
else
return NULL;
+ case MONO_WRAPPER_DELEGATE_INVOKE:
+ if (info)
+ return info->d.delegate_invoke.method;
+ else
+ return NULL;
default:
return NULL;
}
gboolean closed_over_null = FALSE;
MonoGenericContext *ctx = NULL;
MonoGenericContainer *container = NULL;
- MonoMethod *orig_method = NULL;
+ MonoMethod *orig_method = method;
WrapperInfo *info;
WrapperSubtype subtype = WRAPPER_SUBTYPE_NONE;
gboolean found;
* For generic delegates, create a generic wrapper, and return an instance to help AOT.
*/
if (method->is_inflated && subtype == WRAPPER_SUBTYPE_NONE) {
- orig_method = method;
ctx = &((MonoMethodInflated*)method)->context;
method = ((MonoMethodInflated*)method)->declaring;
mono_mb_emit_byte (mb, CEE_LDIND_REF);
mono_mb_emit_stloc (mb, local_delegates);
-
/* if (delegates == null) */
mono_mb_emit_ldloc (mb, local_delegates);
pos2 = mono_mb_emit_branch (mb, CEE_BRTRUE);
#endif /* DISABLE_JIT */
info = mono_wrapper_info_create (mb, subtype);
+ info->d.delegate_invoke.method = orig_method;
if (ctx) {
MonoMethod *def;
mono_mb_emit_stloc (mb, 1);
/* emit valuetype conversion code */
- emit_struct_conv_full (mb, eklass, FALSE, eklass == mono_defaults.char_class ? encoding : (MonoMarshalNative)-1);
+ emit_struct_conv_full (mb, eklass, FALSE, 0, eklass == mono_defaults.char_class ? encoding : (MonoMarshalNative)-1);
}
mono_mb_emit_add_to_local (mb, index_var, 1);
mono_mb_emit_stloc (mb, 1);
/* emit valuetype conversion code */
- emit_struct_conv_full (mb, eklass, TRUE, eklass == mono_defaults.char_class ? encoding : (MonoMarshalNative)-1);
+ emit_struct_conv_full (mb, eklass, TRUE, 0, eklass == mono_defaults.char_class ? encoding : (MonoMarshalNative)-1);
}
if (need_free) {
}
#endif /* DISABLE_JIT */
-/*
- * icall_uses_handles:
- *
- * Return whenever the icall METHOD uses the object handles infrastructure in handle.h.
- */
-static gboolean
-icall_uses_handles (MonoMethod *method)
-{
- if (!strcmp (method->klass->name, "RuntimeType")) {
- if (!strcmp (method->name, "getFullName"))
- return TRUE;
- return FALSE;
- } else {
- return FALSE;
- }
-}
-
/**
* mono_marshal_get_native_wrapper:
* @method: The MonoMethod to wrap.
MonoClass *error_class;
int thread_info_var = -1, stack_mark_var = -1, error_var = -1;
MonoMethodSignature *call_sig = csig;
- gboolean uses_handles = icall_uses_handles (method);
+ gboolean uses_handles = FALSE;
+ (void) mono_lookup_internal_call_full (method, &uses_handles);
+
+
+ /* If it uses handles and MonoError, it had better check exceptions */
+ g_assert (!uses_handles || check_exceptions);
if (uses_handles) {
MonoMethodSignature *ret;
ret->param_count = csig->param_count + 1;
ret->ret = csig->ret;
- for (int i = 0; i < csig->param_count; ++i)
+ for (int i = 0; i < csig->param_count; ++i) {
+ // FIXME: TODO implement handle wrapping for out and inout params.
+ g_assert (!mono_signature_param_is_out (csig, i));
ret->params [i] = csig->params [i];
+ }
ret->params [csig->param_count] = &mono_get_intptr_class ()->byval_arg;
call_sig = ret;
}
mono_mb_emit_byte (mb, CEE_LDARG_0);
mono_mb_emit_icall (mb, mono_handle_new);
}
- for (i = 0; i < sig->param_count; i++)
+ for (i = 0; i < sig->param_count; i++) {
mono_mb_emit_ldarg (mb, i + sig->hasthis);
+ if (MONO_TYPE_IS_REFERENCE (sig->params [i])) {
+ mono_mb_emit_icall (mb, mono_handle_new);
+ }
+ }
mono_mb_emit_ldloc_addr (mb, error_var);
} else {
if (sig->hasthis)
if (uses_handles) {
if (MONO_TYPE_IS_REFERENCE (sig->ret)) {
// if (ret != NULL_HANDLE) {
- // ret = *ret
+ // ret = MONO_HANDLE_RAW(ret)
// }
- // FIXME: Do this properly
mono_mb_emit_byte (mb, CEE_DUP);
int pos = mono_mb_emit_branch (mb, CEE_BRFALSE);
- mono_mb_emit_byte (mb, CEE_CONV_I);
+ mono_mb_emit_ldflda (mb, MONO_HANDLE_PAYLOAD_OFFSET (MonoObject));
mono_mb_emit_byte (mb, CEE_LDIND_REF);
mono_mb_patch_branch (mb, pos);
}
#endif
if (method->klass->valuetype && !(method->flags & MONO_METHOD_ATTR_STATIC)) {
- mono_class_set_failure (method->klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
+ /* FIXME Is this really the best way to signal an error here? Isn't this called much later after class setup? -AK */
+ mono_class_set_type_load_failure (method->klass, "");
#ifndef DISABLE_JIT
/* This will throw the type load exception when the wrapper is compiled */
mono_mb_emit_byte (mb, CEE_LDNULL);
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 %i bytes", size);
-#endif
+ mono_error_set_out_of_memory (error, "Could not allocate %lu bytes", size);
+
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;
-
- len = strlen (tres) + 1;
- 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)
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;
-
-#ifdef HOST_WIN32
- res = CoTaskMemAlloc (size);
-#else
- if ((gulong)size == 0)
- /* This returns a valid pointer for size 0 on MS.NET */
- size = 4;
+ 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);
/*