/**
* \file
* Routines for marshaling complex types in P/Invoke methods.
- *
+ *
* Author:
* Paolo Molaro (lupus@ximian.com)
*
};
#undef OPDEF
-/*
+/*
* This mutex protects the various marshalling related caches in MonoImage
* and a few other data structures static to this file.
*
sig = mono_metadata_signature_dup_full (get_method_image (method), sig);
sig->pinvoke = FALSE;
}
-
+
return sig;
}
return result;
}
-/*
+/*
* this hash table maps from a delegate trampoline object to a weak reference
* of the delegate. As an optimizations with a non-moving GC we store the
* object pointer itself, otherwise we use a GC handle.
return g_hash_table_new (NULL, NULL);
}
-static void
+static void
delegate_hash_table_remove (MonoDelegate *d)
{
MonoGCHandle gchandle = NULL;
/* The attribute is only available in Net 2.0 */
if (mono_class_try_get_unmanaged_function_pointer_attribute_class ()) {
- /*
+ /*
* The pinvoke attributes are stored in a real custom attribute so we have to
* construct it.
*/
break;
case MONO_TYPE_GENERICINST:
case MONO_TYPE_OBJECT:
- case MONO_TYPE_ARRAY:
+ case MONO_TYPE_ARRAY:
case MONO_TYPE_SZARRAY:
case MONO_TYPE_STRING:
default:
case MONO_TYPE_STRING:
case MONO_TYPE_OBJECT:
case MONO_TYPE_SZARRAY:
- case MONO_TYPE_ARRAY:
+ case MONO_TYPE_ARRAY:
return CEE_LDIND_REF;
case MONO_TYPE_I8:
case MONO_TYPE_U8:
case MONO_TYPE_STRING:
case MONO_TYPE_OBJECT:
case MONO_TYPE_SZARRAY:
- case MONO_TYPE_ARRAY:
+ case MONO_TYPE_ARRAY:
return CEE_STIND_REF;
case MONO_TYPE_I8:
case MONO_TYPE_U8:
}
/*
- * Return whenever a field of a native structure or an array member needs to
+ * Return whenever a field of a native structure or an array member needs to
* be freed.
*/
gboolean
if (!(*var)) {
mono_marshal_lock ();
if (!(*var)) {
- GHashTable *cache =
+ GHashTable *cache =
g_hash_table_new (hash_func, equal_func);
mono_memory_barrier ();
*var = cache;
}
return res;
-}
+}
MonoMethod*
mono_mb_create_and_cache (GHashTable *cache, gpointer key,
/*
* Notes:
* - can't put all wrappers into an mscorlib class, because they reference
- * metadata (signature) so they should be put into the same image as the
+ * metadata (signature) so they should be put into the same image as the
* method they wrap, so they are unloaded together.
- * - putting them into a class with a type initalizer could cause the
- * initializer to be executed which can be a problem if the wrappers are
+ * - putting them into a class with a type initalizer could cause the
+ * initializer to be executed which can be a problem if the wrappers are
* shared.
- * - putting them into an inflated class can cause problems if the the
+ * - putting them into an inflated class can cause problems if the the
* class is deleted because it references an image which is unloaded.
- * To avoid these problems, we put the wrappers into the <Module> class of
+ * To avoid these problems, we put the wrappers into the <Module> class of
* the image.
*/
if (image_is_dynamic (image)) {
return res;
} else {
cache = get_cache (&get_method_image (method)->wrapper_caches.delegate_begin_invoke_cache,
- (GHashFunc)mono_signature_hash,
+ (GHashFunc)mono_signature_hash,
(GCompareFunc)mono_metadata_signature_equal);
if ((res = mono_marshal_find_in_cache (cache, sig)))
return res;
return res;
} else {
cache = get_cache (&get_method_image (method)->wrapper_caches.delegate_end_invoke_cache,
- (GHashFunc)mono_signature_hash,
+ (GHashFunc)mono_signature_hash,
(GCompareFunc)mono_metadata_signature_equal);
if ((res = mono_marshal_find_in_cache (cache, sig)))
return res;
invoke_sig = sig = mono_signature_no_pinvoke (method);
/*
- * If the delegate target is null, and the target method is not static, a virtual
- * call is made to that method with the first delegate argument as this. This is
+ * If the delegate target is null, and the target method is not static, a virtual
+ * call is made to that method with the first delegate argument as this. This is
* a non-documented .NET feature.
*/
if (callvirt) {
cache_ptr = &mono_method_get_wrapper_cache (target_method)->delegate_bound_static_invoke_cache;
cache = get_cache (cache_ptr,
- (GHashFunc)mono_signature_hash,
+ (GHashFunc)mono_signature_hash,
(GCompareFunc)mono_metadata_signature_equal);
/*
* The wrapper is based on sig+invoke_sig, but sig can be derived from invoke_sig.
// Inflated methods should not be in this cache because it's not stored on the imageset.
g_assert (!method->is_inflated);
cache = get_cache (&get_method_image (method)->wrapper_caches.delegate_invoke_cache,
- (GHashFunc)mono_signature_hash,
+ (GHashFunc)mono_signature_hash,
(GCompareFunc)mono_metadata_signature_equal);
res = mono_marshal_find_in_cache (cache, sig);
if (res)
/* mono_method_print_code (res); */
- return res;
+ return res;
}
/**
*
* We also catch exceptions if \p exc is not NULL.
* If \p virtual is TRUE, then \p method is invoked virtually on \p this. This is useful since
- * it means that the compiled code for \p method does not have to be looked up
+ * it means that the compiled code for \p method does not have to be looked up
* before calling the runtime invoke wrapper. In this case, the wrapper ignores
* its \p method argument.
*/
mono_mb_free (mb);
- return res;
+ return res;
}
MonoMethod *
* dynamically.
* The signature of the returned method is given by RuntimeInvokeDynamicFunction:
* void runtime_invoke (void *args, MonoObject **exc, void *compiled_method)
- * ARGS should point to an architecture specific structure containing
+ * ARGS should point to an architecture specific structure containing
* the arguments and space for the return value.
* The other arguments are the same as for runtime_invoke (), except that
* ARGS should contain the this argument too.
WrapperInfo *info;
gconstpointer const func = callinfo->func;
-
+
GHashTable *cache = get_cache (& m_class_get_image (mono_defaults.object_class)->icall_wrapper_cache, mono_aligned_addr_hash, NULL);
if ((res = mono_marshal_find_in_cache (cache, (gpointer) func)))
return res;
}
int
-mono_emit_marshal (EmitMarshalContext *m, int argnum, MonoType *t,
- MonoMarshalSpec *spec, int conv_arg,
+mono_emit_marshal (EmitMarshalContext *m, int argnum, MonoType *t,
+ MonoMarshalSpec *spec, int conv_arg,
MonoType **conv_arg_type, MarshalAction action)
{
/* Ensure that we have marshalling info for this param */
if (spec && spec->native == MONO_NATIVE_ASANY)
return get_marshal_cb ()->emit_marshal_asany (m, argnum, t, spec, conv_arg, conv_arg_type, action);
-
+
switch (t->type) {
case MONO_TYPE_VALUETYPE:
if (t->data.klass == mono_class_try_get_handleref_class ())
return get_marshal_cb ()->emit_marshal_handleref (m, argnum, t, spec, conv_arg, conv_arg_type, action);
-
+
return get_marshal_cb ()->emit_marshal_vtype (m, argnum, t, spec, conv_arg, conv_arg_type, action);
case MONO_TYPE_STRING:
return get_marshal_cb ()->emit_marshal_string (m, argnum, t, spec, conv_arg, conv_arg_type, action);
spec->native == MONO_NATIVE_INTERFACE)) ||
(t->type == MONO_TYPE_CLASS && mono_cominterop_is_interface(t->data.klass)))
return mono_cominterop_emit_marshal_com_interface (m, argnum, t, spec, conv_arg, conv_arg_type, action);
- if (spec && (spec->native == MONO_NATIVE_SAFEARRAY) &&
- (spec->data.safearray_data.elem_type == MONO_VARIANT_VARIANT) &&
+ if (spec && (spec->native == MONO_NATIVE_SAFEARRAY) &&
+ (spec->data.safearray_data.elem_type == MONO_VARIANT_VARIANT) &&
((action == MARSHAL_ACTION_CONV_OUT) || (action == MARSHAL_ACTION_CONV_IN) || (action == MARSHAL_ACTION_PUSH)))
return mono_cominterop_emit_marshal_safearray (m, argnum, t, spec, conv_arg, conv_arg_type, action);
#endif
if (mono_class_try_get_safehandle_class () != NULL && t->data.klass &&
mono_class_is_subclass_of_internal (t->data.klass, mono_class_try_get_safehandle_class (), FALSE))
return get_marshal_cb ()->emit_marshal_safehandle (m, argnum, t, spec, conv_arg, conv_arg_type, action);
-
+
return get_marshal_cb ()->emit_marshal_object (m, argnum, t, spec, conv_arg, conv_arg_type, action);
case MONO_TYPE_ARRAY:
case MONO_TYPE_SZARRAY:
* wrapper.
*/
MonoMethod *
-mono_marshal_get_native_func_wrapper (MonoImage *image, MonoMethodSignature *sig,
+mono_marshal_get_native_func_wrapper (MonoImage *image, MonoMethodSignature *sig,
MonoMethodPInvoke *piinfo, MonoMarshalSpec **mspecs, gpointer func)
{
MonoMethodSignature *csig;
#endif
GHashTable *cache = get_cache (&image->wrapper_caches.native_func_wrapper_indirect_cache,
- (GHashFunc)mono_signature_hash,
+ (GHashFunc)mono_signature_hash,
(GCompareFunc)mono_metadata_signature_equal);
-
+
MonoMethod *res;
if ((res = mono_marshal_find_in_cache (cache, sig)))
return res;
-
+
#if 0
fprintf (stderr, "generating wrapper for signature %s\n", mono_signature_full_name (sig));
#endif
-
+
/* FIXME: better wrapper name */
char * name = g_strdup_printf ("wrapper_native_indirect_%p", sig);
MonoMethodBuilder *mb = mono_mb_new (caller_class, name, MONO_WRAPPER_MANAGED_TO_NATIVE);
/**
* mono_marshal_get_managed_wrapper:
- * Generates IL code to call managed methods from unmanaged code
+ * Generates IL code to call managed methods from unmanaged code
* If \p target_handle is \c 0, the wrapper info will be a \c WrapperInfo structure.
*
* If \p delegate_klass is \c NULL, we're creating a wrapper for a function pointer to a method marked with
return NULL;
}
- /*
+ /*
* FIXME: Should cache the method+delegate type pair, since the same method
* could be called with different delegates, thus different marshalling
* options.
MonoCustomAttrInfo *cinfo;
MonoCustomAttrEntry *attr;
- /*
+ /*
* The pinvoke attributes are stored in a real custom attribute. Obtain the
* contents of the attribute without constructing it, as that might not be
* possible when running in cross-compiling mode.
}
mono_mb_free (mb);
- return res;
+ return res;
}
/**
mb = mono_mb_new (method->klass, method->name, MONO_WRAPPER_UNBOX);
g_assert (sig->hasthis);
-
+
get_marshal_cb ()->emit_unbox_wrapper (mb, method);
info = mono_wrapper_info_create (mb, WRAPPER_SUBTYPE_NONE);
/* mono_method_print_code (res); */
- return res;
+ return res;
}
static gboolean
WrapperInfo *info;
MONO_STATIC_POINTER_INIT (MonoMethod, ret)
-
+
mb = mono_mb_new (mono_defaults.object_class, "stelemref", MONO_WRAPPER_STELEMREF);
sig = mono_metadata_signature_alloc (mono_defaults.corlib, 3);
MonoMethodSignature *sig;
MonoMethodBuilder *mb;
WrapperInfo *info;
-
+
mb = mono_mb_new (mono_defaults.object_class, "gsharedvt_in", MONO_WRAPPER_OTHER);
-
+
sig = mono_metadata_signature_alloc (mono_defaults.corlib, 0);
sig->ret = mono_get_void_type ();
MonoMethodSignature *sig;
MonoMethodBuilder *mb;
WrapperInfo *info;
-
+
mb = mono_mb_new (mono_defaults.object_class, "gsharedvt_out", MONO_WRAPPER_OTHER);
-
+
sig = mono_metadata_signature_alloc (mono_defaults.corlib, 0);
sig->ret = mono_get_void_type ();
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);
-
+
get_marshal_cb ()->emit_array_address (mb, rank, elem_size);
info = mono_wrapper_info_create (mb, WRAPPER_SUBTYPE_ELEMENT_ADDR);
}
mono_mb_free (mb);
- return res;
+ return res;
}
#ifndef HOST_WIN32
* mono_marshal_free_array:
*/
void
-mono_marshal_free_array (gpointer *ptr, int size)
+mono_marshal_free_array (gpointer *ptr, int size)
{
int i;
if (ftype->attrs & FIELD_ATTRIBUTE_STATIC)
continue;
- mono_type_to_unmanaged (ftype, info->fields [i].mspec, TRUE,
+ mono_type_to_unmanaged (ftype, info->fields [i].mspec, TRUE,
m_class_is_unicode (klass), &conv);
-
+
cpos = ptr + info->fields [i].offset;
switch (conv) {
break;
case MONO_MARSHAL_CONV_STR_LPTSTR:
#ifdef TARGET_WIN32
- /* We assume this field points inside a MonoString
+ /* We assume this field points inside a MonoString
* on Win32 */
break;
#endif
if (m_class_get_rank (klass)) {
MonoClass *eklass = m_class_get_element_class (klass);
if (m_class_is_primitive (eklass))
- return TRUE;
+ return TRUE;
return eklass != mono_defaults.object_class && m_class_is_blittable (eklass);
} else
return m_class_is_blittable (klass);
* mono_marshal_load_type_info:
*
* Initialize \c klass::marshal_info using information from metadata. This function can
- * recursively call itself, and the caller is responsible to avoid that by calling
+ * recursively call itself, and the caller is responsible to avoid that by calling
* \c mono_marshal_is_loading_type_info beforehand.
*
* LOCKING: Acquires the loader lock.
loads_list = (GSList *)mono_native_tls_get_value (load_type_info_tls_id);
loads_list = g_slist_prepend (loads_list, klass);
mono_native_tls_set_value (load_type_info_tls_id, loads_list);
-
+
iter = NULL;
while ((field = mono_class_get_fields_internal (klass, &iter))) {
if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
info = (MonoMarshalType *)mono_image_alloc0 (m_class_get_image (klass), MONO_SIZEOF_MARSHAL_TYPE + sizeof (MonoMarshalField) * count);
info->num_fields = count;
-
+
/* Try to find a size for this type in metadata */
mono_metadata_packing_from_typedef (m_class_get_image (klass), m_class_get_type_token (klass), NULL, &native_size);
while ((field = mono_class_get_fields_internal (klass, &iter))) {
int size;
guint32 align;
-
+
if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
continue;
if (mono_field_is_deleted (field))
continue;
if (field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_MARSHAL)
- mono_metadata_field_info_with_mempool (m_class_get_image (klass), mono_metadata_token_index (mono_class_get_field_token (field)) - 1,
+ mono_metadata_field_info_with_mempool (m_class_get_image (klass), mono_metadata_token_index (mono_class_get_field_token (field)) - 1,
NULL, NULL, &info->fields [j].mspec);
info->fields [j].field = field;
switch (layout) {
case TYPE_ATTRIBUTE_AUTO_LAYOUT:
case TYPE_ATTRIBUTE_SEQUENTIAL_LAYOUT:
- size = mono_marshal_type_size (field->type, info->fields [j].mspec,
+ size = mono_marshal_type_size (field->type, info->fields [j].mspec,
&align, TRUE, m_class_is_unicode (klass));
align = m_class_get_packing_size (klass) ? MIN (m_class_get_packing_size (klass), align): align;
min_align = MAX (align, min_align);
info->native_size = info->fields [j].offset + size;
break;
case TYPE_ATTRIBUTE_EXPLICIT_LAYOUT:
- size = mono_marshal_type_size (field->type, info->fields [j].mspec,
+ size = mono_marshal_type_size (field->type, info->fields [j].mspec,
&align, TRUE, m_class_is_unicode (klass));
min_align = MAX (align, min_align);
info->fields [j].offset = field->offset - MONO_ABI_SIZEOF (MonoObject);
info->native_size = MAX (info->native_size, info->fields [j].offset + size);
break;
- }
+ }
j++;
}
/**
* mono_class_native_size:
- * \param klass a class
- * \returns the native size of an object instance (when marshaled
- * to unmanaged code)
+ * \param klass a class
+ * \returns the native size of an object instance (when marshaled
+ * to unmanaged code)
*/
gint32
mono_class_native_size (MonoClass *klass, guint32 *align)
if (!mono_type_generic_inst_is_valuetype (t)) {
*align = TARGET_SIZEOF_VOID_P;
return TARGET_SIZEOF_VOID_P;
- }
+ }
/* Fall through */
case MONO_TYPE_TYPEDBYREF:
case MONO_TYPE_VALUETYPE: {
size = mono_class_native_size (klass, align);
*align = *align + 3;
*align &= ~3;
-
+
size += 3;
size &= ~3;
case MONO_NATIVE_LPSTRUCT:
*align = MONO_ABI_ALIGNOF (gpointer);
return TARGET_SIZEOF_VOID_P;
- case MONO_NATIVE_STRUCT:
+ case MONO_NATIVE_STRUCT:
klass = mono_class_from_mono_type_internal (type);
if (klass == mono_defaults.object_class &&
(mspec && mspec->native == MONO_NATIVE_STRUCT)) {
*align = 16;
return 16;
- } else if (strcmp (m_class_get_name_space (klass), "System") == 0 &&
- strcmp (m_class_get_name (klass), "Decimal") == 0) {
-
- // Special case: Managed Decimal consists of 4 int32 fields, the alignment should be 8 on x64 to follow
- // https://github.com/dotnet/coreclr/blob/4450e5ca663b9e66c20e6f9751c941efa3716fde/src/vm/methodtablebuilder.cpp#L9753
- *align = MONO_ABI_ALIGNOF (gpointer);
- return mono_class_native_size (klass, NULL);
}
padded_size = mono_class_native_size (klass, align);
if (padded_size == 0)
case MONO_NATIVE_CURRENCY:
case MONO_NATIVE_VBBYREFSTR:
default:
- g_error ("native type %02x not implemented", native_type);
+ g_error ("native type %02x not implemented", native_type);
break;
}
g_assert_not_reached ();
return res;
}
case MONO_TYPE_SZARRAY: {
- //TODO: Implement structs and in-params for all value types
+ //TODO: Implement structs and in-params for all value types
MonoClass *klass = t->data.klass;
MonoClass *eklass = m_class_get_element_class (klass);
MonoArray *arr = (MonoArray *) MONO_HANDLE_RAW (o);
/* This could be called during shutdown */
if (marshal_mutex_initialized)
mono_marshal_lock ();
- /*
+ /*
* FIXME: We currently leak the wrappers. Freeing them would be tricky as
* they could be shared with other methods ?
*/