return;
klass = array->obj.vtable->klass;
- switch (klass->element_class->byval_arg.type) {
- case MONO_TYPE_CLASS:
- for(i = 0; i < array->max_length; ++i)
- mono_marshal_free_ccw(nativeArray[i]);
- free(nativeArray);
- break;
- }
+ 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);
+ }
#endif
}
mono_array_to_byvalarray (native_arr, arr, mono_defaults.byte_class, elnum);
}
-void
-mono_string_utf8_to_builder (MonoStringBuilder *sb, char *text)
-{
- GError *error = NULL;
- guint16 *ut;
- glong items_written;
- int l;
-
- if (!sb || !text)
- return;
-
- l = strlen (text);
-
- ut = g_utf8_to_utf16 (text, l, NULL, &items_written, &error);
-
- if (items_written > mono_stringbuilder_capacity (sb))
- items_written = mono_stringbuilder_capacity (sb);
-
- if (!error) {
- if (! sb->str || sb->str == sb->cached_str)
- MONO_OBJECT_SETREF (sb, str, mono_string_new_size (mono_domain_get (), items_written));
-
- memcpy (mono_string_chars (sb->str), ut, items_written * 2);
- sb->length = items_written;
- sb->cached_str = NULL;
- } else
- g_error_free (error);
-
- g_free (ut);
-}
-
-MonoStringBuilder *
-mono_string_utf8_to_builder2 (char *text)
+static MonoStringBuilder *
+mono_string_builder_new (int starting_string_length)
{
- int l;
- MonoStringBuilder *sb;
static MonoClass *string_builder_class;
static MonoMethod *sb_ctor;
- void *args [1];
- MonoObject *exc;
+ static void *args [1];
+ int initial_len = starting_string_length;
- if (!text)
- return NULL;
+ if (initial_len < 0)
+ initial_len = 0;
if (!string_builder_class) {
MonoMethodDesc *desc;
sb_ctor = mono_method_desc_search_in_class (desc, string_builder_class);
g_assert (sb_ctor);
mono_method_desc_free (desc);
- }
- l = strlen (text);
+ // We make a new array in the _to_builder function, so this
+ // array will always be garbage collected.
+ args [0] = &initial_len;
+ }
- sb = (MonoStringBuilder*)mono_object_new (mono_domain_get (), string_builder_class);
+ MonoStringBuilder *sb = (MonoStringBuilder*)mono_object_new (mono_domain_get (), string_builder_class);
+ MonoObject *exc;
g_assert (sb);
- args [0] = &l;
+
mono_runtime_invoke (sb_ctor, sb, args, &exc);
+
+ g_assert (sb->chunkChars->max_length >= initial_len);
g_assert (!exc);
- mono_string_utf8_to_builder (sb, text);
+ return sb;
+}
+
+static void
+mono_string_utf16_to_builder_copy (MonoStringBuilder *sb, gunichar2 *text, size_t string_len)
+{
+ gunichar2 *charDst = (gunichar2 *)sb->chunkChars->vector;
+ gunichar2 *charSrc = (gunichar2 *)text;
+ memcpy (charDst, charSrc, sizeof (gunichar2) * string_len);
+
+ sb->chunkLength = string_len;
+
+ return;
+}
+
+MonoStringBuilder *
+mono_string_utf16_to_builder2 (gunichar2 *text)
+{
+ if (!text)
+ return NULL;
+
+ int len;
+ for (len = 0; text [len] != 0; ++len);
+
+ MonoStringBuilder *sb = mono_string_builder_new (len);
+ mono_string_utf16_to_builder (sb, text);
return sb;
}
-/*
- * FIXME: This routine does not seem to do what it seems to do
- * the @text is never copied into the string builder
- */
void
-mono_string_utf16_to_builder (MonoStringBuilder *sb, gunichar2 *text)
+mono_string_utf8_to_builder (MonoStringBuilder *sb, char *text)
{
- guint32 len;
-
if (!sb || !text)
return;
- g_assert (mono_string_chars (sb->str) == text);
+ int len = strlen (text);
+ if (len > mono_string_builder_capacity (sb))
+ len = mono_string_builder_capacity (sb);
- for (len = 0; text [len] != 0; ++len)
- ;
+ GError *error = NULL;
+ glong copied;
+ gunichar2* ut = g_utf8_to_utf16 (text, len, NULL, &copied, &error);
- sb->length = len;
+ if (!error) {
+ MONO_OBJECT_SETREF (sb, chunkPrevious, NULL);
+ mono_string_utf16_to_builder_copy (sb, ut, copied);
+ } else
+ g_error_free (error);
+
+ g_free (ut);
}
MonoStringBuilder *
-mono_string_utf16_to_builder2 (gunichar2 *text)
+mono_string_utf8_to_builder2 (char *text)
{
- int len;
- MonoStringBuilder *sb;
- static MonoClass *string_builder_class;
- static MonoMethod *sb_ctor;
- void *args [1];
- MonoObject *exc;
-
if (!text)
return NULL;
- if (!string_builder_class) {
- MonoMethodDesc *desc;
+ int len = strlen (text);
+ MonoStringBuilder *sb = mono_string_builder_new (len);
+ mono_string_utf8_to_builder (sb, text);
- string_builder_class = mono_class_from_name (mono_defaults.corlib, "System.Text", "StringBuilder");
- g_assert (string_builder_class);
- desc = mono_method_desc_new (":.ctor(int)", FALSE);
- sb_ctor = mono_method_desc_search_in_class (desc, string_builder_class);
- g_assert (sb_ctor);
- mono_method_desc_free (desc);
- }
+ return sb;
+}
- for (len = 0; text [len] != 0; ++len)
- ;
- sb = (MonoStringBuilder*)mono_object_new (mono_domain_get (), string_builder_class);
- g_assert (sb);
- args [0] = &len;
- mono_runtime_invoke (sb_ctor, sb, args, &exc);
- g_assert (!exc);
+void
+mono_string_utf16_to_builder (MonoStringBuilder *sb, gunichar2 *text)
+{
+ if (!sb || !text)
+ return;
- sb->length = len;
- memcpy (mono_string_chars (sb->str), text, len * 2);
+ guint32 len;
+ for (len = 0; text [len] != 0; ++len);
+
+ if (len > mono_string_builder_capacity (sb))
+ len = mono_string_builder_capacity (sb);
- return sb;
+ mono_string_utf16_to_builder_copy (sb, text, len);
}
/**
*
* The return value must be released with g_free.
*/
-gpointer
+gchar*
mono_string_builder_to_utf8 (MonoStringBuilder *sb)
{
GError *error = NULL;
- gchar *tmp, *res = NULL;
if (!sb)
return NULL;
- if ((sb->str == sb->cached_str) && (sb->str->length == 0)) {
- /*
- * The sb could have been allocated with the default capacity and be empty.
- * we need to alloc a buffer of the default capacity in this case.
- */
- MONO_OBJECT_SETREF (sb, str, mono_string_new_size (mono_domain_get (), 16));
- sb->cached_str = NULL;
- }
- tmp = g_utf16_to_utf8 (mono_string_chars (sb->str), sb->length, NULL, NULL, &error);
+ gunichar2 *str_utf16 = mono_string_builder_to_utf16 (sb);
+
+ guint str_len = mono_string_builder_string_length (sb);
+
+ gchar *tmp = g_utf16_to_utf8 (str_utf16, str_len, NULL, NULL, &error);
+
if (error) {
g_error_free (error);
+ g_free (str_utf16);
mono_raise_exception (mono_get_exception_execution_engine ("Failed to convert StringBuilder from utf16 to utf8"));
+ return NULL;
} else {
- res = mono_marshal_alloc (mono_stringbuilder_capacity (sb) + 1);
- memcpy (res, tmp, sb->length + 1);
+ guint len = mono_string_builder_capacity (sb) + 1;
+ gchar *res = mono_marshal_alloc (len * sizeof (gchar));
+ g_assert (str_len < len);
+ memcpy (res, tmp, str_len * sizeof (gchar));
+ res[str_len] = '\0';
+
+
+ g_free (str_utf16);
g_free (tmp);
+ return res;
}
-
- return res;
}
/**
*
* The return value must not be freed.
*/
-gpointer
+gunichar2*
mono_string_builder_to_utf16 (MonoStringBuilder *sb)
{
if (!sb)
return NULL;
- g_assert (sb->str);
+ g_assert (sb->chunkChars);
- /*
- * The stringbuilder might not have ownership of this string. If this is
- * the case, we must duplicate the string, so that we don't munge immutable
- * strings
- */
- if (sb->str == sb->cached_str) {
- /*
- * The sb could have been allocated with the default capacity and be empty.
- * we need to alloc a buffer of the default capacity in this case.
- */
- if (sb->str->length == 0)
- MONO_OBJECT_SETREF (sb, str, mono_string_new_size (mono_domain_get (), 16));
- else
- MONO_OBJECT_SETREF (sb, str, mono_string_new_utf16 (mono_domain_get (), mono_string_chars (sb->str), mono_stringbuilder_capacity (sb)));
- sb->cached_str = NULL;
- }
-
- if (sb->length == 0)
- *(mono_string_chars (sb->str)) = '\0';
+ guint len = mono_string_builder_capacity (sb);
+
+ if (len == 0)
+ len = 1;
+
+ gunichar2 *str = mono_marshal_alloc ((len + 1) * sizeof (gunichar2));
+ str[len] = '\0';
- return mono_string_chars (sb->str);
+ if (len == 0)
+ return str;
+
+ MonoStringBuilder* chunk = sb;
+ do {
+ if (chunk->chunkLength > 0) {
+ // Check that we will not overrun our boundaries.
+ gunichar2 *source = (gunichar2 *)chunk->chunkChars->vector;
+
+ if (chunk->chunkLength <= len) {
+ memcpy (str + chunk->chunkOffset, source, chunk->chunkLength * sizeof(gunichar2));
+ } else {
+ g_error ("A chunk in the StringBuilder had a length longer than expected from the offset.");
+ }
+
+ len -= chunk->chunkLength;
+ }
+ chunk = chunk->chunkPrevious;
+ } while (chunk != NULL);
+
+ return str;
}
static gpointer
#endif /* DISABLE_COM */
case MONO_MARSHAL_CONV_SAFEHANDLE: {
- int dar_release_slot, pos;
+ int pos;
- dar_release_slot = mono_mb_add_local (mb, &mono_defaults.boolean_class->byval_arg);
-
- /*
- * The following is ifdefed-out, because I have no way of doing the
- * DangerousRelease when destroying the structure
- */
-#if 0
- /* set release = false */
- mono_mb_emit_icon (mb, 0);
- mono_mb_emit_stloc (mb, dar_release_slot);
- if (!sh_dangerous_add_ref)
- init_safe_handle ();
-
- /* safehandle.DangerousAddRef (ref release) */
- mono_mb_emit_ldloc (mb, 0); /* the source */
- mono_mb_emit_byte (mb, CEE_LDIND_I);
- mono_mb_emit_ldloc_addr (mb, dar_release_slot);
- mono_mb_emit_managed_call (mb, sh_dangerous_add_ref, NULL);
-#endif
mono_mb_emit_ldloc (mb, 0);
mono_mb_emit_byte (mb, CEE_LDIND_I);
pos = mono_mb_emit_branch (mb, CEE_BRTRUE);
static void
emit_thread_interrupt_checkpoint_call (MonoMethodBuilder *mb, gpointer checkpoint_func)
{
- int pos_noabort;
+ int pos_noabort, pos_noex;
- mono_mb_emit_ptr (mb, (gpointer) mono_thread_interruption_request_flag ());
+ mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
+ mono_mb_emit_byte (mb, CEE_MONO_LDPTR_INT_REQ_FLAG);
mono_mb_emit_byte (mb, CEE_LDIND_U4);
pos_noabort = mono_mb_emit_branch (mb, CEE_BRFALSE);
mono_mb_emit_byte (mb, CEE_MONO_NOT_TAKEN);
mono_mb_emit_icall (mb, checkpoint_func);
+ /* Throw the exception returned by the checkpoint function, if any */
+ mono_mb_emit_byte (mb, CEE_DUP);
+ pos_noex = mono_mb_emit_branch (mb, CEE_BRFALSE);
+ mono_mb_emit_byte (mb, CEE_THROW);
+ mono_mb_patch_branch (mb, pos_noex);
+ mono_mb_emit_byte (mb, CEE_POP);
mono_mb_patch_branch (mb, pos_noabort);
}
static void
emit_thread_force_interrupt_checkpoint (MonoMethodBuilder *mb)
{
- emit_thread_interrupt_checkpoint_call (mb, mono_thread_force_interruption_checkpoint);
+ emit_thread_interrupt_checkpoint_call (mb, mono_thread_force_interruption_checkpoint_noraise);
}
void
mono_marshal_need_free (MonoType *t, MonoMethodPInvoke *piinfo, MonoMarshalSpec *spec)
{
MonoMarshalNative encoding;
- MonoMarshalConv conv;
switch (t->type) {
case MONO_TYPE_VALUETYPE:
case MONO_TYPE_CLASS:
if (t->data.klass == mono_defaults.stringbuilder_class) {
gboolean need_free;
- conv = mono_marshal_get_ptr_to_stringbuilder_conv (piinfo, spec, &need_free);
+ mono_marshal_get_ptr_to_stringbuilder_conv (piinfo, spec, &need_free);
return need_free;
}
return FALSE;
return *var;
}
-static GHashTable*
-get_cache_full (GHashTable **var, GHashFunc hash_func, GCompareFunc equal_func, GDestroyNotify key_destroy_func, GDestroyNotify value_destroy_func)
-{
- if (!(*var)) {
- mono_marshal_lock ();
- if (!(*var)) {
- GHashTable *cache =
- g_hash_table_new_full (hash_func, equal_func, key_destroy_func, value_destroy_func);
- mono_memory_barrier ();
- *var = cache;
- }
- mono_marshal_unlock ();
- }
- return *var;
-}
-
GHashTable*
mono_marshal_get_cache (GHashTable **var, GHashFunc hash_func, GCompareFunc equal_func)
{
res = mono_marshal_get_wrapper_info (wrapper);
if (res == NULL)
return wrapper;
- if (wrapper->is_inflated)
+ if (wrapper->is_inflated) {
+ MonoError error;
+ MonoMethod *result;
/*
* A method cannot be inflated and a wrapper at the same time, so the wrapper info
* contains an uninflated method.
*/
- return mono_class_inflate_generic_method (res, mono_method_get_context (wrapper));
- else
- return res;
+ result = mono_class_inflate_generic_method_checked (res, mono_method_get_context (wrapper), &error);
+ g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
+ return result;
+ }
+ return res;
case MONO_WRAPPER_MANAGED_TO_NATIVE:
info = mono_marshal_get_wrapper_info (wrapper);
if (info && (info->subtype == WRAPPER_SUBTYPE_NONE || info->subtype == WRAPPER_SUBTYPE_NATIVE_FUNC_AOT || info->subtype == WRAPPER_SUBTYPE_PINVOKE))
MonoMethod *res;
MonoMethod *inst, *def;
MonoGenericContext *ctx;
- MonoMethod *def_method;
g_assert (orig_method->is_inflated);
- def_method = ((MonoMethodInflated*)orig_method)->declaring;
ctx = mono_method_get_context (orig_method);
/*
*/
def = mono_marshal_find_in_cache (cache, def_key);
if (def) {
- inst = mono_class_inflate_generic_method (def, ctx);
+ MonoError error;
+ inst = mono_class_inflate_generic_method_checked (def, ctx, &error);
+ g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
/* Cache it */
mono_memory_barrier ();
mono_marshal_lock ();
static MonoMethod*
cache_generic_wrapper (GHashTable *cache, MonoMethod *orig_method, MonoMethod *def, MonoGenericContext *ctx, gpointer key)
{
+ MonoError error;
MonoMethod *inst, *res;
/*
* We use the same cache for the generic definition and the instances.
*/
- inst = mono_class_inflate_generic_method (def, ctx);
+ inst = mono_class_inflate_generic_method_checked (def, ctx, &error);
+ g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
mono_memory_barrier ();
mono_marshal_lock ();
res = g_hash_table_lookup (cache, key);
static MonoMethod*
check_generic_delegate_wrapper_cache (GHashTable *cache, MonoMethod *orig_method, MonoMethod *def_method, MonoGenericContext *ctx)
{
+ MonoError error;
MonoMethod *res;
MonoMethod *inst, *def;
*/
def = mono_marshal_find_in_cache (cache, def_method->klass);
if (def) {
- inst = mono_class_inflate_generic_method (def, ctx);
+ inst = mono_class_inflate_generic_method_checked (def, ctx, &error);
+ g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
+
/* Cache it */
mono_memory_barrier ();
mono_marshal_lock ();
static MonoMethod*
cache_generic_delegate_wrapper (GHashTable *cache, MonoMethod *orig_method, MonoMethod *def, MonoGenericContext *ctx)
{
+ MonoError error;
MonoMethod *inst, *res;
/*
* We use the same cache for the generic definition and the instances.
*/
- inst = mono_class_inflate_generic_method (def, ctx);
+ inst = mono_class_inflate_generic_method_checked (def, ctx, &error);
+ g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
+
mono_memory_barrier ();
mono_marshal_lock ();
res = g_hash_table_lookup (cache, orig_method->klass);
typedef struct
{
MonoMethodSignature *sig;
- MonoMethod *method;
-} SignatureMethodPair;
+ gpointer pointer;
+} SignaturePointerPair;
static guint
-signature_method_pair_hash (gconstpointer data)
+signature_pointer_pair_hash (gconstpointer data)
{
- SignatureMethodPair *pair = (SignatureMethodPair*)data;
+ SignaturePointerPair *pair = (SignaturePointerPair*)data;
- return mono_signature_hash (pair->sig) ^ mono_aligned_addr_hash (pair->method);
+ return mono_signature_hash (pair->sig) ^ mono_aligned_addr_hash (pair->pointer);
}
static gboolean
-signature_method_pair_equal (SignatureMethodPair *pair1, SignatureMethodPair *pair2)
+signature_pointer_pair_equal (gconstpointer data1, gconstpointer data2)
{
- return mono_metadata_signature_equal (pair1->sig, pair2->sig) && (pair1->method == pair2->method);
+ SignaturePointerPair *pair1 = (SignaturePointerPair*) data1, *pair2 = (SignaturePointerPair*) data2;
+ return mono_metadata_signature_equal (pair1->sig, pair2->sig) && (pair1->pointer == pair2->pointer);
}
static gboolean
-signature_method_pair_matches_method (gpointer key, gpointer value, gpointer user_data)
+signature_pointer_pair_matches_pointer (gpointer key, gpointer value, gpointer user_data)
{
- SignatureMethodPair *pair = (SignatureMethodPair*)key;
- MonoMethod *method = (MonoMethod*)user_data;
+ SignaturePointerPair *pair = (SignaturePointerPair*)key;
- return pair->method == method;
+ return pair->pointer == user_data;
}
static void
-free_signature_method_pair (SignatureMethodPair *pair)
+free_signature_pointer_pair (SignaturePointerPair *pair)
{
g_free (pair);
}
MonoMethod *res;
GHashTable *cache;
gpointer cache_key = NULL;
- SignatureMethodPair key;
- SignatureMethodPair *new_key;
+ SignaturePointerPair key;
+ SignaturePointerPair *new_key;
int local_prev, local_target;
int pos0;
char *name;
/* We need to cache the signature+method pair */
mono_marshal_lock ();
if (!*cache_ptr)
- *cache_ptr = g_hash_table_new_full (signature_method_pair_hash, (GEqualFunc)signature_method_pair_equal, (GDestroyNotify)free_signature_method_pair, NULL);
+ *cache_ptr = g_hash_table_new_full (signature_pointer_pair_hash, (GEqualFunc)signature_pointer_pair_equal, (GDestroyNotify)free_signature_pointer_pair, NULL);
cache = *cache_ptr;
key.sig = invoke_sig;
- key.method = target_method;
+ key.pointer = target_method;
res = g_hash_table_lookup (cache, &key);
mono_marshal_unlock ();
if (res)
mono_mb_emit_ldloc (mb, local_prev);
for (i = 0; i < sig->param_count; i++)
mono_mb_emit_ldarg (mb, i + 1);
- if (ctx)
- mono_mb_emit_op (mb, CEE_CALLVIRT, mono_class_inflate_generic_method (method, &container->context));
- else
+ if (ctx) {
+ MonoError error;
+ mono_mb_emit_op (mb, CEE_CALLVIRT, mono_class_inflate_generic_method_checked (method, &container->context, &error));
+ g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
+ } else {
mono_mb_emit_op (mb, CEE_CALLVIRT, method);
+ }
if (sig->ret->type != MONO_TYPE_VOID)
mono_mb_emit_byte (mb, CEE_POP);
def = mono_mb_create_and_cache (cache, cache_key, mb, sig, sig->param_count + 16);
res = cache_generic_delegate_wrapper (cache, orig_method, def, ctx);
} else if (callvirt) {
- new_key = g_new0 (SignatureMethodPair, 1);
+ new_key = g_new0 (SignaturePointerPair, 1);
*new_key = key;
info = mono_wrapper_info_create (mb, subtype);
int pos2;
if (!ICustomMarshaler) {
- ICustomMarshaler = mono_class_from_name (mono_defaults.corlib, "System.Runtime.InteropServices", "ICustomMarshaler");
- if (!ICustomMarshaler) {
+ MonoClass *klass = mono_class_from_name (mono_defaults.corlib, "System.Runtime.InteropServices", "ICustomMarshaler");
+ if (!klass) {
exception_msg = g_strdup ("Current profile doesn't support ICustomMarshaler");
goto handle_exception;
}
- cleanup_native = mono_class_get_method_from_name (ICustomMarshaler, "CleanUpNativeData", 1);
+ cleanup_native = mono_class_get_method_from_name (klass, "CleanUpNativeData", 1);
g_assert (cleanup_native);
- cleanup_managed = mono_class_get_method_from_name (ICustomMarshaler, "CleanUpManagedData", 1);
+ cleanup_managed = mono_class_get_method_from_name (klass, "CleanUpManagedData", 1);
g_assert (cleanup_managed);
- marshal_managed_to_native = mono_class_get_method_from_name (ICustomMarshaler, "MarshalManagedToNative", 1);
+ marshal_managed_to_native = mono_class_get_method_from_name (klass, "MarshalManagedToNative", 1);
g_assert (marshal_managed_to_native);
- marshal_native_to_managed = mono_class_get_method_from_name (ICustomMarshaler, "MarshalNativeToManaged", 1);
+ marshal_native_to_managed = mono_class_get_method_from_name (klass, "MarshalNativeToManaged", 1);
g_assert (marshal_native_to_managed);
+
+ mono_memory_barrier ();
+ ICustomMarshaler = klass;
}
if (spec->data.custom_data.image)
need_free = mono_marshal_need_free (&klass->element_class->byval_arg,
m->piinfo, spec);
+ if ((t->attrs & PARAM_ATTRIBUTE_OUT) && spec && spec->native == MONO_NATIVE_LPARRAY && spec->data.array_data.param_num != -1) {
+ int param_num = spec->data.array_data.param_num;
+ MonoType *param_type;
+
+ param_type = m->sig->params [param_num];
+
+ if (param_type->byref && param_type->type != MONO_TYPE_I4) {
+ char *msg = g_strdup ("Not implemented.");
+ mono_mb_emit_exception_marshal_directive (mb, msg);
+ break;
+ }
+
+ mono_mb_emit_ldarg (mb, argnum);
+
+ /* Create the managed array */
+ mono_mb_emit_ldarg (mb, param_num);
+ if (m->sig->params [param_num]->byref)
+ // FIXME: Support other types
+ mono_mb_emit_byte (mb, CEE_LDIND_I4);
+ mono_mb_emit_byte (mb, CEE_CONV_OVF_I);
+ mono_mb_emit_op (mb, CEE_NEWARR, klass->element_class);
+ /* Store into argument */
+ mono_mb_emit_byte (mb, CEE_STIND_I);
+ }
+
if (need_convert || need_free) {
/* FIXME: Optimize blittable case */
MonoClass *eklass;
/* free memory allocated (if any) by MONO_MARSHAL_CONV_ARRAY_LPARRAY */
mono_mb_emit_ldarg (mb, argnum);
+ if (t->byref)
+ mono_mb_emit_byte (mb, CEE_LDIND_REF);
mono_mb_emit_ldloc (mb, conv_arg);
mono_mb_emit_icall (mb, conv_to_icall (MONO_MARSHAL_FREE_LPARRAY));
}
case MARSHAL_ACTION_MANAGED_CONV_IN: {
MonoClass *eklass;
guint32 label1, label2, label3;
- int index_var, src_ptr, loc, esize, param_num, num_elem;
+ int index_var, src_ptr, esize, param_num, num_elem;
MonoMarshalConv conv;
gboolean is_string = FALSE;
else
esize = mono_class_native_size (eklass, NULL);
src_ptr = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
- loc = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
mono_mb_emit_byte (mb, CEE_LDNULL);
mono_mb_emit_stloc (mb, conv_arg);
case MARSHAL_ACTION_MANAGED_CONV_OUT: {
MonoClass *eklass;
guint32 label1, label2, label3;
- int index_var, dest_ptr, loc, esize, param_num, num_elem;
+ int index_var, dest_ptr, esize, param_num, num_elem;
MonoMarshalConv conv;
gboolean is_string = FALSE;
esize = mono_class_native_size (eklass, NULL);
dest_ptr = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
- loc = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
/* Check null */
mono_mb_emit_ldloc (mb, conv_arg);
return emit_marshal_vtype (m, argnum, t, spec, conv_arg, conv_arg_type, action);
else
return emit_marshal_object (m, argnum, t, spec, conv_arg, conv_arg_type, action);
+ default:
+ return conv_arg;
}
- return conv_arg;
}
#ifndef DISABLE_JIT
int type, param_shift = 0;
static MonoMethodSignature *get_last_error_sig = NULL;
+ memset (&m, 0, sizeof (m));
m.mb = mb;
+ m.sig = sig;
m.piinfo = piinfo;
/* we copy the signature, so that we can set pinvoke to 0 */
case MONO_TYPE_BOOLEAN:
emit_marshal (&m, argnum, t, spec, tmp_locals [i], NULL, MARSHAL_ACTION_CONV_OUT);
break;
+ default:
+ break;
}
}
{
MonoMethodSignature *csig;
+ SignaturePointerPair key, *new_key;
MonoMethodBuilder *mb;
MonoMethod *res;
GHashTable *cache;
+ gboolean found;
char *name;
- cache = get_cache (&image->native_wrapper_cache, mono_aligned_addr_hash, NULL);
- if ((res = mono_marshal_find_in_cache (cache, func)))
+ key.sig = sig;
+ key.pointer = func;
+
+ cache = get_cache (&image->native_func_wrapper_cache, signature_pointer_pair_hash, signature_pointer_pair_equal);
+ if ((res = mono_marshal_find_in_cache (cache, &key)))
return res;
name = g_strdup_printf ("wrapper_native_%p", func);
csig = signature_dup (image, sig);
csig->pinvoke = 0;
- res = mono_mb_create_and_cache (cache, func,
- mb, csig, csig->param_count + 16);
+
+ new_key = g_new (SignaturePointerPair,1);
+ new_key->sig = csig;
+ new_key->pointer = func;
+
+ res = mono_mb_create_and_cache_full (cache, new_key, mb, csig, csig->param_count + 16, NULL, &found);
+ if (found)
+ g_free (new_key);
+
mono_mb_free (mb);
mono_marshal_set_wrapper_info (res, NULL);
case MONO_TYPE_BOOLEAN:
emit_marshal (m, i, t, mspecs [i + 1], tmp_locals [i], NULL, MARSHAL_ACTION_MANAGED_CONV_OUT);
break;
+ default:
+ break;
}
}
else if (invoke_sig->params [i]->attrs & PARAM_ATTRIBUTE_OUT) {
csig->hasthis = 0;
csig->pinvoke = 1;
+ memset (&m, 0, sizeof (m));
m.mb = mb;
m.sig = sig;
m.piinfo = NULL;
gint32 call_conv;
gint32 charset = 0;
MonoBoolean set_last_error = 0;
- MonoBoolean best_fit_mapping = 0;
- MonoBoolean throw_on_unmappable = 0;
MonoError error;
mono_reflection_create_custom_attr_data_args (mono_defaults.corlib, attr->ctor, attr->data, attr->data_size, &typed_args, &named_args, &arginfo, &error);
} else if (!strcmp (narg->field->name, "SetLastError")) {
set_last_error = *(MonoBoolean*)mono_object_unbox (o);
} else if (!strcmp (narg->field->name, "BestFitMapping")) {
- best_fit_mapping = *(MonoBoolean*)mono_object_unbox (o);
+ // best_fit_mapping = *(MonoBoolean*)mono_object_unbox (o);
} else if (!strcmp (narg->field->name, "ThrowOnUnmappableChar")) {
- throw_on_unmappable = *(MonoBoolean*)mono_object_unbox (o);
+ // throw_on_unmappable = *(MonoBoolean*)mono_object_unbox (o);
} else {
g_assert_not_reached ();
}
csig->hasthis = 0;
csig->pinvoke = 1;
+ memset (&m, 0, sizeof (m));
m.mb = mb;
m.sig = sig;
m.piinfo = NULL;
mono_mb_emit_ldloc (mb, 1);
mono_mb_emit_byte (mb, CEE_LDC_I4);
mono_mb_emit_i4 (mb, ~0x1);
- mono_mb_emit_byte (mb, CEE_CONV_U);
+ mono_mb_emit_byte (mb, CEE_CONV_I);
mono_mb_emit_byte (mb, CEE_AND);
mono_mb_emit_ldloc (mb, 0);
/*if ((cached_vtable & ~0x1)== obj_vtable)*/
MonoMethodSignature *sig;
MonoMethod *res;
MonoGenericContext *ctx = NULL;
- MonoMethod *orig_method = NULL;
MonoGenericContainer *container = NULL;
if (method->is_inflated && !mono_method_get_context (method)->method_inst) {
- orig_method = method;
ctx = &((MonoMethodInflated*)method)->context;
method = ((MonoMethodInflated*)method)->declaring;
container = mono_method_get_generic_container (method);
info->d.synchronized_inner.method = method;
res = mono_mb_create (mb, sig, 0, info);
mono_mb_free (mb);
- if (ctx)
- res = mono_class_inflate_generic_method (res, ctx);
+ if (ctx) {
+ MonoError error;
+ res = mono_class_inflate_generic_method_checked (res, ctx, &error);
+ g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
+ }
return res;
}
for (i = 0; i < sig->param_count; i++)
mono_mb_emit_ldarg (mb, i + (sig->hasthis == TRUE));
- if (ctx)
- mono_mb_emit_managed_call (mb, mono_class_inflate_generic_method (method, &container->context), NULL);
- else
+ if (ctx) {
+ MonoError error;
+ mono_mb_emit_managed_call (mb, mono_class_inflate_generic_method_checked (method, &container->context, &error), NULL);
+ g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
+ } else {
mono_mb_emit_managed_call (mb, method, NULL);
+ }
if (!MONO_TYPE_IS_VOID (sig->ret))
mono_mb_emit_stloc (mb, ret_local);
* @rank: rank of the array type
* @elem_size: size in bytes of an element of an array.
*
- * Returns a MonoMethd that implements the code to get the address
+ * Returns a MonoMethod that implements the code to get the address
* of an element in a multi-dimenasional array of @rank dimensions.
* The returned method takes an array as the first argument and then
* @rank indexes for the @rank dimensions.
+ * If ELEM_SIZE is 0, read the array size from the array object.
*/
MonoMethod*
mono_marshal_get_array_address (int rank, int elem_size)
MonoMethodBuilder *mb;
MonoMethodSignature *sig;
WrapperInfo *info;
+ char *name;
int i, bounds, ind, realidx;
int branch_pos, *branch_positions;
int cached;
sig->params [i + 1] = &mono_defaults.int32_class->byval_arg;
}
- mb = mono_mb_new (mono_defaults.object_class, "ElementAddr", MONO_WRAPPER_MANAGED_TO_MANAGED);
+ name = g_strdup_printf ("ElementAddr_%d", elem_size);
+ mb = mono_mb_new (mono_defaults.object_class, name, MONO_WRAPPER_MANAGED_TO_MANAGED);
+ g_free (name);
#ifndef DISABLE_JIT
bounds = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
mono_mb_emit_ldarg (mb, 0);
mono_mb_emit_ldflda (mb, MONO_STRUCT_OFFSET (MonoArray, vector));
mono_mb_emit_ldloc (mb, ind);
- mono_mb_emit_icon (mb, elem_size);
- mono_mb_emit_byte (mb, CEE_MUL);
+ if (elem_size) {
+ mono_mb_emit_icon (mb, elem_size);
+ } else {
+ /* Load arr->vtable->klass->sizes.element_class */
+ mono_mb_emit_ldarg (mb, 0);
+ mono_mb_emit_byte (mb, CEE_CONV_I);
+ mono_mb_emit_icon (mb, MONO_STRUCT_OFFSET (MonoObject, vtable));
+ mono_mb_emit_byte (mb, CEE_ADD);
+ mono_mb_emit_byte (mb, CEE_LDIND_I);
+ mono_mb_emit_icon (mb, MONO_STRUCT_OFFSET (MonoVTable, klass));
+ mono_mb_emit_byte (mb, CEE_ADD);
+ mono_mb_emit_byte (mb, CEE_LDIND_I);
+ /* sizes is an union, so this reads sizes.element_size */
+ mono_mb_emit_icon (mb, MONO_STRUCT_OFFSET (MonoClass, sizes));
+ mono_mb_emit_byte (mb, CEE_ADD);
+ mono_mb_emit_byte (mb, CEE_LDIND_I4);
+ }
+ mono_mb_emit_byte (mb, CEE_MUL);
mono_mb_emit_byte (mb, CEE_ADD);
mono_mb_emit_byte (mb, CEE_RET);
for (i = 0; i < sig->param_count; i++)
mono_mb_emit_ldarg (mb, i + (sig->hasthis == TRUE));
- if (ctx)
- mono_mb_emit_managed_call (mb, mono_class_inflate_generic_method (method, &container->context), NULL);
- else
+ if (ctx) {
+ MonoError error;
+ mono_mb_emit_managed_call (mb, mono_class_inflate_generic_method_checked (method, &container->context, &error), NULL);
+ g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
+ } else {
mono_mb_emit_managed_call (mb, method, NULL);
+ }
mono_mb_emit_byte (mb, CEE_RET);
#endif
int element_size;
void *source_addr;
- MONO_ARCH_SAVE_REGS;
-
- MONO_CHECK_ARG_NULL (src);
- MONO_CHECK_ARG_NULL (dest);
+ MONO_CHECK_ARG_NULL (src,);
+ MONO_CHECK_ARG_NULL (dest,);
- if (src->obj.vtable->klass->rank != 1)
- mono_raise_exception (mono_get_exception_argument ("array", "array is multi-dimensional"));
- if (start_index < 0)
- mono_raise_exception (mono_get_exception_argument ("startIndex", "Must be >= 0"));
- if (length < 0)
- mono_raise_exception (mono_get_exception_argument ("length", "Must be >= 0"));
- if (start_index + length > mono_array_length (src))
- mono_raise_exception (mono_get_exception_argument ("length", "start_index + length > array length"));
+ if (src->obj.vtable->klass->rank != 1) {
+ mono_set_pending_exception (mono_get_exception_argument ("array", "array is multi-dimensional"));
+ return;
+ }
+ if (start_index < 0) {
+ mono_set_pending_exception (mono_get_exception_argument ("startIndex", "Must be >= 0"));
+ return;
+ }
+ if (length < 0) {
+ mono_set_pending_exception (mono_get_exception_argument ("length", "Must be >= 0"));
+ return;
+ }
+ if (start_index + length > mono_array_length (src)) {
+ mono_set_pending_exception (mono_get_exception_argument ("length", "start_index + length > array length"));
+ return;
+ }
element_size = mono_array_element_size (src->obj.vtable->klass);
int element_size;
void *dest_addr;
- MONO_ARCH_SAVE_REGS;
-
- MONO_CHECK_ARG_NULL (src);
- MONO_CHECK_ARG_NULL (dest);
-
- if (dest->obj.vtable->klass->rank != 1)
- mono_raise_exception (mono_get_exception_argument ("array", "array is multi-dimensional"));
- if (start_index < 0)
- mono_raise_exception (mono_get_exception_argument ("startIndex", "Must be >= 0"));
- if (length < 0)
- mono_raise_exception (mono_get_exception_argument ("length", "Must be >= 0"));
- if (start_index + length > mono_array_length (dest))
- mono_raise_exception (mono_get_exception_argument ("length", "start_index + length > array length"));
+ MONO_CHECK_ARG_NULL (src,);
+ MONO_CHECK_ARG_NULL (dest,);
+ if (dest->obj.vtable->klass->rank != 1) {
+ mono_set_pending_exception (mono_get_exception_argument ("array", "array is multi-dimensional"));
+ return;
+ }
+ if (start_index < 0) {
+ mono_set_pending_exception (mono_get_exception_argument ("startIndex", "Must be >= 0"));
+ return;
+ }
+ if (length < 0) {
+ mono_set_pending_exception (mono_get_exception_argument ("length", "Must be >= 0"));
+ return;
+ }
+ if (start_index + length > mono_array_length (dest)) {
+ mono_set_pending_exception (mono_get_exception_argument ("length", "start_index + length > array length"));
+ return;
+ }
element_size = mono_array_element_size (dest->obj.vtable->klass);
/* no references should be involved */
MonoString *
ves_icall_System_Runtime_InteropServices_Marshal_PtrToStringAnsi (char *ptr)
{
- MONO_ARCH_SAVE_REGS;
-
if (ptr == NULL)
return NULL;
else
MonoString *
ves_icall_System_Runtime_InteropServices_Marshal_PtrToStringAnsi_len (char *ptr, gint32 len)
{
- MONO_ARCH_SAVE_REGS;
-
if (ptr == NULL) {
- mono_raise_exception (mono_get_exception_argument_null ("ptr"));
- g_assert_not_reached ();
+ mono_set_pending_exception (mono_get_exception_argument_null ("ptr"));
return NULL;
} else {
return mono_string_new_len (mono_domain_get (), ptr, len);
int len = 0;
guint16 *t = ptr;
- MONO_ARCH_SAVE_REGS;
-
if (ptr == NULL)
return NULL;
{
MonoDomain *domain = mono_domain_get ();
- MONO_ARCH_SAVE_REGS;
-
if (ptr == NULL) {
- mono_raise_exception (mono_get_exception_argument_null ("ptr"));
- g_assert_not_reached ();
+ mono_set_pending_exception (mono_get_exception_argument_null ("ptr"));
return NULL;
} else {
return mono_string_new_utf16 (domain, ptr, len);
guint32
ves_icall_System_Runtime_InteropServices_Marshal_GetLastWin32Error (void)
{
- MONO_ARCH_SAVE_REGS;
-
return (GPOINTER_TO_INT (mono_native_tls_get_value (last_error_tls_id)));
}
MonoType *type;
guint32 layout;
- MONO_ARCH_SAVE_REGS;
-
- MONO_CHECK_ARG_NULL (rtype);
+ MONO_CHECK_ARG_NULL (rtype, 0);
type = rtype->type;
klass = mono_class_from_mono_type (type);
- if (!mono_class_init (klass))
- mono_raise_exception (mono_class_get_exception_for_failure (klass));
+ if (!mono_class_init (klass)) {
+ mono_set_pending_exception (mono_class_get_exception_for_failure (klass));
+ return 0;
+ }
layout = (klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK);
msg = g_strdup_printf ("Type %s cannot be marshaled as an unmanaged structure.", klass->name);
exc = mono_get_exception_argument ("t", msg);
g_free (msg);
- mono_raise_exception (exc);
+ mono_set_pending_exception (exc);
+ return 0;
}
-
return mono_class_native_size (klass, NULL);
}
MonoMethod *method;
gpointer pa [3];
- MONO_ARCH_SAVE_REGS;
-
- MONO_CHECK_ARG_NULL (obj);
- MONO_CHECK_ARG_NULL (dst);
+ MONO_CHECK_ARG_NULL (obj,);
+ MONO_CHECK_ARG_NULL (dst,);
method = mono_marshal_get_struct_to_ptr (obj->vtable->klass);
{
MonoType *t;
- MONO_ARCH_SAVE_REGS;
-
- MONO_CHECK_ARG_NULL (src);
- MONO_CHECK_ARG_NULL (dst);
+ MONO_CHECK_ARG_NULL (src,);
+ MONO_CHECK_ARG_NULL (dst,);
t = mono_type_get_underlying_type (mono_class_get_type (dst->vtable->klass));
exc = mono_get_exception_argument ("dst", tmp);
g_free (tmp);
- mono_raise_exception (exc);
+ mono_set_pending_exception (exc);
return;
}
MonoDomain *domain = mono_domain_get ();
MonoObject *res;
- MONO_ARCH_SAVE_REGS;
-
if (src == NULL)
return NULL;
- MONO_CHECK_ARG_NULL (type);
+ MONO_CHECK_ARG_NULL (type, NULL);
klass = mono_class_from_mono_type (type->type);
- if (!mono_class_init (klass))
- mono_raise_exception (mono_class_get_exception_for_failure (klass));
+ if (!mono_class_init (klass)) {
+ mono_set_pending_exception (mono_class_get_exception_for_failure (klass));
+ return NULL;
+ }
res = mono_object_new (domain, klass);
char *fname;
int match_index = -1;
- MONO_ARCH_SAVE_REGS;
-
- MONO_CHECK_ARG_NULL (type);
- MONO_CHECK_ARG_NULL (field_name);
+ MONO_CHECK_ARG_NULL (type, 0);
+ MONO_CHECK_ARG_NULL (field_name, 0);
fname = mono_string_to_utf8 (field_name);
klass = mono_class_from_mono_type (type->type);
- if (!mono_class_init (klass))
- mono_raise_exception (mono_class_get_exception_for_failure (klass));
+ if (!mono_class_init (klass)) {
+ mono_set_pending_exception (mono_class_get_exception_for_failure (klass));
+ return 0;
+ }
while (klass && match_index == -1) {
MonoClassField* field;
exc = mono_get_exception_argument ("fieldName", tmp);
g_free (tmp);
- mono_raise_exception ((MonoException*)exc);
+ mono_set_pending_exception ((MonoException*)exc);
+ return 0;
}
info = mono_marshal_load_type_info (klass);
gpointer
ves_icall_System_Runtime_InteropServices_Marshal_StringToHGlobalUni (MonoString *string)
{
- MONO_ARCH_SAVE_REGS;
-
if (string == NULL)
return NULL;
else {
info = mono_marshal_load_type_info (klass);
for (i = 0; i < info->num_fields; i++) {
- MonoMarshalNative ntype;
MonoMarshalConv conv;
MonoType *ftype = info->fields [i].field->type;
char *cpos;
if (ftype->attrs & FIELD_ATTRIBUTE_STATIC)
continue;
- ntype = mono_type_to_unmanaged (ftype, info->fields [i].mspec, TRUE,
- klass->unicode, &conv);
+ mono_type_to_unmanaged (ftype, info->fields [i].mspec, TRUE,
+ klass->unicode, &conv);
cpos = ptr + info->fields [i].offset;
{
MonoClass *klass;
- MONO_ARCH_SAVE_REGS;
-
- MONO_CHECK_ARG_NULL (src);
- MONO_CHECK_ARG_NULL (type);
+ MONO_CHECK_ARG_NULL (src,);
+ MONO_CHECK_ARG_NULL (type,);
klass = mono_class_from_mono_type (type->type);
- if (!mono_class_init (klass))
- mono_raise_exception (mono_class_get_exception_for_failure (klass));
+ if (!mono_class_init (klass)) {
+ mono_set_pending_exception (mono_class_get_exception_for_failure (klass));
+ return;
+ }
mono_struct_delete_old (klass, (char *)src);
}
{
gpointer res;
- MONO_ARCH_SAVE_REGS;
-
if ((gulong)size == 0)
/* This returns a valid pointer for size 0 on MS.NET */
size = 4;
void
ves_icall_System_Runtime_InteropServices_Marshal_FreeHGlobal (void *ptr)
{
- MONO_ARCH_SAVE_REGS;
-
#ifdef HOST_WIN32
GlobalFree (ptr);
#else
void*
ves_icall_System_Runtime_InteropServices_Marshal_AllocCoTaskMem (int size)
{
- MONO_ARCH_SAVE_REGS;
+ void *res;
#ifdef HOST_WIN32
- return CoTaskMemAlloc (size);
+ res = CoTaskMemAlloc (size);
#else
- return g_try_malloc ((gulong)size);
+ if ((gulong)size == 0)
+ /* This returns a valid pointer for size 0 on MS.NET */
+ size = 4;
+
+ res = g_try_malloc ((gulong)size);
#endif
+ if (!res)
+ mono_gc_out_of_memory ((gulong)size);
+ return res;
}
void
ves_icall_System_Runtime_InteropServices_Marshal_FreeCoTaskMem (void *ptr)
{
- MONO_ARCH_SAVE_REGS;
-
#ifdef HOST_WIN32
CoTaskMemFree (ptr);
#else
gpointer
ves_icall_System_Runtime_InteropServices_Marshal_ReAllocCoTaskMem (gpointer ptr, int size)
{
- MONO_ARCH_SAVE_REGS;
+ void *res;
#ifdef HOST_WIN32
- return CoTaskMemRealloc (ptr, size);
+ res = CoTaskMemRealloc (ptr, size);
#else
- return g_try_realloc (ptr, (gulong)size);
+ res = g_try_realloc (ptr, (gulong)size);
#endif
+ if (!res)
+ mono_gc_out_of_memory ((gulong)size);
+ return res;
}
void*
ves_icall_System_Runtime_InteropServices_Marshal_GetDelegateForFunctionPointerInternal (void *ftn, MonoReflectionType *type)
{
MonoClass *klass = mono_type_get_class (type->type);
- if (!mono_class_init (klass))
- mono_raise_exception (mono_class_get_exception_for_failure (klass));
+ if (!mono_class_init (klass)) {
+ mono_set_pending_exception (mono_class_get_exception_for_failure (klass));
+ return NULL;
+ }
return mono_ftnptr_to_delegate (klass, ftn);
}
return res;
}
+ default:
+ break;
}
-
mono_raise_exception (mono_get_exception_argument ("", "No PInvoke conversion exists for value passed to Object-typed parameter."));
-
return NULL;
}
if (image->runtime_invoke_direct_cache)
g_hash_table_remove (image->runtime_invoke_direct_cache, method);
if (image->delegate_abstract_invoke_cache)
- g_hash_table_foreach_remove (image->delegate_abstract_invoke_cache, signature_method_pair_matches_method, method);
+ g_hash_table_foreach_remove (image->delegate_abstract_invoke_cache, signature_pointer_pair_matches_pointer, method);
// FIXME: Need to clear the caches in other images as well
if (image->delegate_bound_static_invoke_cache)
g_hash_table_remove (image->delegate_bound_static_invoke_cache, mono_method_signature (method));
}
static gboolean
-signature_method_pair_matches_signature (gpointer key, gpointer value, gpointer user_data)
+signature_pointer_pair_matches_signature (gpointer key, gpointer value, gpointer user_data)
{
- SignatureMethodPair *pair = (SignatureMethodPair*)key;
+ SignaturePointerPair *pair = (SignaturePointerPair*)key;
MonoMethodSignature *sig = (MonoMethodSignature*)user_data;
return mono_metadata_signature_equal (pair->sig, sig);
g_hash_table_remove (method->klass->image->runtime_invoke_vtype_cache, sig);
/*
- * indexed by SignatureMethodPair
+ * indexed by SignaturePointerPair
*/
if (sig && method->klass->image->delegate_abstract_invoke_cache)
g_hash_table_foreach_remove (method->klass->image->delegate_abstract_invoke_cache,
- signature_method_pair_matches_signature, (gpointer)sig);
+ signature_pointer_pair_matches_signature, (gpointer)sig);
/*
* indexed by MonoMethod pointers