* Copyright 2004-2009 Novell, Inc (http://www.novell.com)
* Copyright 2011 Xamarin, Inc (http://www.xamarin.com)
*
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
*/
#include "config.h"
#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 "mono/metadata/remoting.h"
#include "mono/metadata/reflection-internals.h"
#include "mono/metadata/threadpool-ms.h"
+#include "mono/metadata/handle.h"
#include "mono/utils/mono-counters.h"
#include "mono/utils/mono-tls.h"
#include "mono/utils/mono-memory-model.h"
#include "mono/utils/atomic.h"
#include <mono/utils/mono-threads.h>
+#include <mono/utils/mono-threads-coop.h>
+#include <mono/utils/mono-error-internals.h>
#include <string.h>
#include <errno.h>
static gboolean use_aot_wrappers;
+static int class_marshal_info_count;
+
+static void ftnptr_eh_callback_default (guint32 gchandle);
+
+static MonoFtnPtrEHCallback ftnptr_eh_callback = ftnptr_eh_callback_default;
+
static void
delegate_hash_table_add (MonoDelegate *d);
+static void
+delegate_hash_table_remove (MonoDelegate *d);
+
static void
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);
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);
static void init_safe_handle (void);
+static void*
+ves_icall_marshal_alloc (gulong size);
+
+void
+mono_string_utf8_to_builder (MonoStringBuilder *sb, char *text);
+
+void
+mono_string_utf16_to_builder (MonoStringBuilder *sb, gunichar2 *text);
+
+gchar*
+mono_string_builder_to_utf8 (MonoStringBuilder *sb);
+
+gunichar2*
+mono_string_builder_to_utf16 (MonoStringBuilder *sb);
+
+void
+mono_string_to_byvalstr (gpointer dst, MonoString *src, int size);
+
+void
+mono_string_to_byvalwstr (gpointer dst, MonoString *src, int size);
+
+gpointer
+mono_delegate_to_ftnptr (MonoDelegate *delegate);
+
+MonoDelegate*
+mono_ftnptr_to_delegate (MonoClass *klass, gpointer ftn);
+
+gpointer
+mono_array_to_savearray (MonoArray *array);
+
+gpointer
+mono_array_to_lparray (MonoArray *array);
+
+void
+mono_free_lparray (MonoArray *array, gpointer* nativeArray);
+
+gpointer
+mono_marshal_asany (MonoObject *obj, MonoMarshalNative string_encoding, int param_attrs);
+
+void
+mono_marshal_free_asany (MonoObject *o, gpointer ptr, MonoMarshalNative string_encoding, int param_attrs);
+
+gpointer
+mono_array_to_savearray (MonoArray *array);
+
+gpointer
+mono_array_to_lparray (MonoArray *array);
+
+void
+mono_free_lparray (MonoArray *array, gpointer* nativeArray);
+
+static void
+mono_marshal_ftnptr_eh_callback (guint32 gchandle);
+
+static MonoThreadInfo*
+mono_icall_start (HandleStackMark *stackmark, MonoError *error);
+
+static void
+mono_icall_end (MonoThreadInfo *info, HandleStackMark *stackmark, MonoError *error);
+
+/* Lazy class loading functions */
+static GENERATE_GET_CLASS_WITH_CACHE (string_builder, System.Text, StringBuilder)
+static GENERATE_GET_CLASS_WITH_CACHE (date_time, System, DateTime)
+static GENERATE_TRY_GET_CLASS_WITH_CACHE (unmanaged_function_pointer_attribute, System.Runtime.InteropServices, UnmanagedFunctionPointerAttribute)
+static GENERATE_TRY_GET_CLASS_WITH_CACHE (icustom_marshaler, System.Runtime.InteropServices, ICustomMarshaler)
+
/* MonoMethod pointers to SafeHandle::DangerousAddRef and ::DangerousRelease */
static MonoMethod *sh_dangerous_add_ref;
static MonoMethod *sh_dangerous_release;
-
static void
init_safe_handle ()
{
sh_dangerous_add_ref = mono_class_get_method_from_name (
- mono_defaults.safehandle_class, "DangerousAddRef", 1);
+ mono_class_try_get_safehandle_class (), "DangerousAddRef", 1);
sh_dangerous_release = mono_class_get_method_from_name (
- mono_defaults.safehandle_class, "DangerousRelease", 0);
+ mono_class_try_get_safehandle_class (), "DangerousRelease", 0);
}
static void
-register_icall (gpointer func, const char *name, const char *sigstr, gboolean save)
+register_icall (gpointer func, const char *name, const char *sigstr, gboolean no_wrapper)
{
MonoMethodSignature *sig = mono_create_icall_signature (sigstr);
- mono_register_jit_icall (func, name, sig, save);
+ mono_register_jit_icall (func, name, sig, no_wrapper);
}
MonoMethodSignature*
mono_native_tls_alloc (&load_type_info_tls_id, NULL);
}
+static MonoObject*
+mono_object_isinst_icall (MonoObject *obj, MonoClass *klass)
+{
+ MonoError error;
+ MonoObject *result = mono_object_isinst_checked (obj, klass, &error);
+ mono_error_set_pending_exception (&error);
+ return result;
+}
+
+static MonoString*
+ves_icall_mono_string_from_utf16 (gunichar2 *data)
+{
+ MonoError error;
+ MonoString *result = mono_string_from_utf16_checked (data, &error);
+ mono_error_set_pending_exception (&error);
+ return result;
+}
+
+static char*
+ves_icall_mono_string_to_utf8 (MonoString *str)
+{
+ MonoError error;
+ char *result = mono_string_to_utf8_checked (str, &error);
+ mono_error_set_pending_exception (&error);
+ return result;
+}
+
void
mono_marshal_init (void)
{
register_icall (mono_marshal_string_to_utf16, "mono_marshal_string_to_utf16", "ptr obj", FALSE);
register_icall (mono_marshal_string_to_utf16_copy, "mono_marshal_string_to_utf16_copy", "ptr obj", FALSE);
register_icall (mono_string_to_utf16, "mono_string_to_utf16", "ptr obj", FALSE);
- register_icall (mono_string_from_utf16, "mono_string_from_utf16", "obj ptr", FALSE);
+ register_icall (ves_icall_mono_string_from_utf16, "ves_icall_mono_string_from_utf16", "obj ptr", FALSE);
register_icall (mono_string_from_byvalstr, "mono_string_from_byvalstr", "obj ptr int", FALSE);
register_icall (mono_string_from_byvalwstr, "mono_string_from_byvalwstr", "obj ptr int", FALSE);
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 (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 (ves_icall_mono_string_to_utf8, "ves_icall_mono_string_to_utf8", "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);
register_icall (mono_ftnptr_to_delegate, "mono_ftnptr_to_delegate", "object ptr ptr", FALSE);
register_icall (mono_marshal_asany, "mono_marshal_asany", "ptr object int32 int32", FALSE);
register_icall (mono_marshal_free_asany, "mono_marshal_free_asany", "void object ptr int32 int32", FALSE);
- register_icall (mono_marshal_alloc, "mono_marshal_alloc", "ptr int32", FALSE);
+ register_icall (ves_icall_marshal_alloc, "ves_icall_marshal_alloc", "ptr int32", FALSE);
register_icall (mono_marshal_free, "mono_marshal_free", "void ptr", FALSE);
register_icall (mono_marshal_set_last_error, "mono_marshal_set_last_error", "void", FALSE);
register_icall (mono_marshal_set_last_error_windows, "mono_marshal_set_last_error_windows", "void int32", FALSE);
register_icall (mono_string_to_byvalstr, "mono_string_to_byvalstr", "void ptr ptr int32", FALSE);
register_icall (mono_string_to_byvalwstr, "mono_string_to_byvalwstr", "void ptr ptr int32", FALSE);
register_icall (g_free, "g_free", "void ptr", FALSE);
- register_icall (mono_object_isinst, "mono_object_isinst", "object object ptr", FALSE);
+ register_icall (mono_object_isinst_icall, "mono_object_isinst_icall", "object object ptr", FALSE);
register_icall (mono_struct_delete_old, "mono_struct_delete_old", "void ptr ptr", FALSE);
register_icall (mono_delegate_begin_invoke, "mono_delegate_begin_invoke", "object object ptr", FALSE);
register_icall (mono_delegate_end_invoke, "mono_delegate_end_invoke", "object object ptr", FALSE);
- register_icall (mono_compile_method, "mono_compile_method", "ptr ptr", FALSE);
register_icall (mono_context_get, "mono_context_get", "object", FALSE);
register_icall (mono_context_set, "mono_context_set", "void object", FALSE);
register_icall (mono_gc_wbarrier_generic_nostore, "wb_generic", "void ptr", FALSE);
register_icall (mono_gchandle_get_target, "mono_gchandle_get_target", "object int32", TRUE);
+ register_icall (mono_gchandle_new, "mono_gchandle_new", "uint32 object bool", TRUE);
register_icall (mono_marshal_isinst_with_cache, "mono_marshal_isinst_with_cache", "object object ptr ptr", FALSE);
+ register_icall (mono_marshal_ftnptr_eh_callback, "mono_marshal_ftnptr_eh_callback", "void uint32", TRUE);
+ register_icall (mono_threads_enter_gc_safe_region_unbalanced, "mono_threads_enter_gc_safe_region_unbalanced", "ptr ptr", TRUE);
+ register_icall (mono_threads_exit_gc_safe_region_unbalanced, "mono_threads_exit_gc_safe_region_unbalanced", "void ptr ptr", TRUE);
+ register_icall (mono_threads_attach_coop, "mono_threads_attach_coop", "ptr ptr ptr", TRUE);
+ register_icall (mono_threads_detach_coop, "mono_threads_detach_coop", "void ptr ptr", TRUE);
+ register_icall (mono_icall_start, "mono_icall_start", "ptr ptr ptr", TRUE);
+ register_icall (mono_icall_end, "mono_icall_end", "void ptr ptr ptr", TRUE);
+ register_icall (mono_handle_new, "mono_handle_new", "ptr ptr", TRUE);
mono_cominterop_init ();
mono_remoting_init ();
- if (mono_threads_is_coop_enabled ()) {
- register_icall (mono_threads_prepare_blocking, "mono_threads_prepare_blocking", "ptr ptr", FALSE);
- register_icall (mono_threads_finish_blocking, "mono_threads_finish_blocking", "void ptr ptr", FALSE);
- register_icall (mono_threads_reset_blocking_start, "mono_threads_reset_blocking_start","ptr ptr", TRUE);
- register_icall (mono_threads_reset_blocking_end, "mono_threads_reset_blocking_end","void ptr ptr", TRUE);
- }
+ mono_counters_register ("MonoClass::class_marshal_info_count count",
+ MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_marshal_info_count);
+
}
}
mono_marshal_unlock ();
}
+/* This is a JIT icall, it sets the pending exception and return NULL on error */
gpointer
mono_delegate_to_ftnptr (MonoDelegate *delegate)
{
+ MonoError error;
MonoMethod *method, *wrapper;
MonoClass *klass;
uint32_t target_handle = 0;
g_assert (klass->delegate);
method = delegate->method;
+ if (delegate->method_is_virtual)
+ method = mono_object_get_virtual_method (delegate->target, method);
- if (mono_method_signature (method)->pinvoke) {
+ if (method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
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));
+ mono_set_pending_exception (mono_exception_from_name_msg (mono_defaults.corlib, "System", exc_class, exc_arg));
+ return NULL;
}
return ftnptr;
}
wrapper = mono_marshal_get_managed_wrapper (method, klass, target_handle);
- delegate->delegate_trampoline = mono_compile_method (wrapper);
+ delegate->delegate_trampoline = mono_compile_method_checked (wrapper, &error);
+ if (!is_ok (&error))
+ goto fail;
// Add the delegate to the delegate hash table
delegate_hash_table_add (delegate);
mono_object_register_finalizer ((MonoObject*)delegate);
return delegate->delegate_trampoline;
+
+fail:
+ if (target_handle != 0)
+ mono_gchandle_free (target_handle);
+ mono_error_set_pending_exception (&error);
+ return NULL;
}
/*
static void
parse_unmanaged_function_pointer_attr (MonoClass *klass, MonoMethodPInvoke *piinfo)
{
- static MonoClass *UnmanagedFunctionPointerAttribute;
+ MonoError error;
MonoCustomAttrInfo *cinfo;
MonoReflectionUnmanagedFunctionPointerAttribute *attr;
- if (!UnmanagedFunctionPointerAttribute)
- UnmanagedFunctionPointerAttribute = mono_class_from_name (mono_defaults.corlib, "System.Runtime.InteropServices", "UnmanagedFunctionPointerAttribute");
-
/* The attribute is only available in Net 2.0 */
- if (UnmanagedFunctionPointerAttribute) {
+ 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.
*/
- cinfo = mono_custom_attrs_from_class (klass);
+ cinfo = mono_custom_attrs_from_class_checked (klass, &error);
+ if (!mono_error_ok (&error)) {
+ g_warning ("Could not load UnmanagedFunctionPointerAttribute due to %s", mono_error_get_message (&error));
+ mono_error_cleanup (&error);
+ }
if (cinfo && !mono_runtime_get_no_exec ()) {
- MonoError error;
- attr = (MonoReflectionUnmanagedFunctionPointerAttribute*)mono_custom_attrs_get_attr_checked (cinfo, UnmanagedFunctionPointerAttribute, &error);
+ attr = (MonoReflectionUnmanagedFunctionPointerAttribute*)mono_custom_attrs_get_attr_checked (cinfo, mono_class_try_get_unmanaged_function_pointer_attribute_class (), &error);
if (attr) {
piinfo->piflags = (attr->call_conv << 8) | (attr->charset ? (attr->charset - 1) * 2 : 1) | attr->set_last_error;
} else {
}
}
+/* This is a JIT icall, it sets the pending exception and returns NULL on error */
MonoDelegate*
mono_ftnptr_to_delegate (MonoClass *klass, gpointer ftn)
{
+ MonoError error;
guint32 gchandle;
MonoDelegate *d;
if (use_aot_wrappers) {
wrapper = mono_marshal_get_native_func_wrapper_aot (klass);
- this_obj = mono_value_box (mono_domain_get (), mono_defaults.int_class, &ftn);
+ this_obj = mono_value_box_checked (mono_domain_get (), mono_defaults.int_class, &ftn, &error);
+ if (!is_ok (&error)) {
+ mono_error_set_pending_exception (&error);
+ return NULL;
+ }
} else {
memset (&piinfo, 0, sizeof (piinfo));
parse_unmanaged_function_pointer_attr (klass, &piinfo);
g_free (sig);
}
- d = (MonoDelegate*)mono_object_new (mono_domain_get (), klass);
- mono_delegate_ctor_with_method ((MonoObject*)d, this_obj, mono_compile_method (wrapper), wrapper);
+ d = (MonoDelegate*)mono_object_new_checked (mono_domain_get (), klass, &error);
+ if (!mono_error_ok (&error)) {
+ mono_error_set_pending_exception (&error);
+ return NULL;
+ }
+ gpointer compiled_ptr = mono_compile_method_checked (wrapper, &error);
+ if (mono_error_set_pending_exception (&error))
+ return NULL;
+ mono_delegate_ctor_with_method ((MonoObject*)d, this_obj, compiled_ptr, wrapper, &error);
+ if (mono_error_set_pending_exception (&error))
+ return NULL;
}
- if (d->object.vtable->domain != mono_domain_get ())
- mono_raise_exception (mono_get_exception_not_supported ("Delegates cannot be marshalled from native code into a domain other than their home domain"));
+ if (d->object.vtable->domain != mono_domain_get ()) {
+ mono_set_pending_exception (mono_get_exception_not_supported ("Delegates cannot be marshalled from native code into a domain other than their home domain"));
+ return NULL;
+ }
return d;
}
}
}
+/* This is a JIT icall, it sets the pending exception and returns NULL on error */
static MonoString *
mono_string_from_byvalstr (const char *data, int max_len)
{
+ MonoError error;
MonoDomain *domain = mono_domain_get ();
int len = 0;
while (len < max_len - 1 && data [len])
len++;
- return mono_string_new_len (domain, data, len);
+ MonoString *result = mono_string_new_len_checked (domain, data, len, &error);
+ mono_error_set_pending_exception (&error);
+ return result;
}
+/* This is a JIT icall, it sets the pending exception and return NULL on error */
static MonoString *
mono_string_from_byvalwstr (gunichar2 *data, int max_len)
{
+ MonoError error;
+ MonoString *res = NULL;
MonoDomain *domain = mono_domain_get ();
int len = 0;
while (data [len]) len++;
- return mono_string_new_utf16 (domain, data, MIN (len, max_len));
+ res = mono_string_new_utf16_checked (domain, data, MIN (len, max_len), &error);
+ if (!mono_error_ok (&error)) {
+ mono_error_set_pending_exception (&error);
+ return NULL;
+ }
+ return res;
}
gpointer
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
}
mono_byvalarray_to_array (arr, native_arr, mono_defaults.byte_class, elnum);
}
+/* This is a JIT icall, it sets the pending exception and returns on error */
static void
mono_array_to_byvalarray (gpointer native_arr, MonoArray *arr, MonoClass *elclass, guint32 elnum)
{
as = g_utf16_to_utf8 (mono_array_addr (arr, gunichar2, 0), mono_array_length (arr), NULL, NULL, &error);
if (error) {
- MonoException *exc = mono_get_exception_argument ("string", error->message);
+ mono_set_pending_exception (mono_get_exception_argument ("string", error->message));
g_error_free (error);
- mono_raise_exception (exc);
+ return;
}
memcpy (native_arr, as, MIN (strlen (as), elnum));
static MonoClass *string_builder_class;
static MonoMethod *sb_ctor;
static void *args [1];
+
+ MonoError error;
int initial_len = starting_string_length;
if (initial_len < 0)
MonoMethodDesc *desc;
MonoMethod *m;
- string_builder_class = mono_class_from_name (mono_defaults.corlib, "System.Text", "StringBuilder");
+ string_builder_class = mono_class_get_string_builder_class ();
g_assert (string_builder_class);
desc = mono_method_desc_new (":.ctor(int)", FALSE);
m = mono_method_desc_search_in_class (desc, string_builder_class);
// array will always be garbage collected.
args [0] = &initial_len;
- MonoStringBuilder *sb = (MonoStringBuilder*)mono_object_new (mono_domain_get (), string_builder_class);
- MonoObject *exc;
- g_assert (sb);
+ MonoStringBuilder *sb = (MonoStringBuilder*)mono_object_new_checked (mono_domain_get (), string_builder_class, &error);
+ mono_error_assert_ok (&error);
- mono_runtime_invoke (sb_ctor, sb, args, &exc);
- g_assert (!exc);
+ MonoObject *exc;
+ mono_runtime_try_invoke (sb_ctor, sb, args, &exc, &error);
+ g_assert (exc == NULL);
+ mono_error_assert_ok (&error);
g_assert (sb->chunkChars->max_length >= initial_len);
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)
{
*
* Returns: a utf8 string with the contents of the StringBuilder.
*
- * The return value must be released with g_free.
+ * The return value must be released with mono_marshal_free.
+ *
+ * This is a JIT icall, it sets the pending exception and returns NULL on error.
*/
gchar*
mono_string_builder_to_utf8 (MonoStringBuilder *sb)
{
- GError *error = NULL;
-
+ MonoError error;
+ GError *gerror = NULL;
+ glong byte_count;
if (!sb)
return NULL;
-
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);
+ gchar *tmp = g_utf16_to_utf8 (str_utf16, str_len, NULL, &byte_count, &gerror);
- 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"));
+ if (gerror) {
+ g_error_free (gerror);
+ mono_marshal_free (str_utf16);
+ mono_set_pending_exception (mono_get_exception_execution_engine ("Failed to convert StringBuilder from utf16 to utf8"));
return NULL;
} else {
guint len = mono_string_builder_capacity (sb) + 1;
- gchar *res = (gchar *)mono_marshal_alloc (len * sizeof (gchar));
- g_assert (str_len < len);
- memcpy (res, tmp, str_len * sizeof (gchar));
- res[str_len] = '\0';
+ 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);
+ mono_error_set_pending_exception (&error);
+ return NULL;
+ }
+ memcpy (res, tmp, byte_count);
+ res[byte_count] = '\0';
- g_free (str_utf16);
+ mono_marshal_free (str_utf16);
g_free (tmp);
return res;
}
*
* Returns: a utf16 string with the contents of the StringBuilder.
*
- * The return value must not be freed.
+ * The return value must be released with mono_marshal_free.
+ *
+ * This is a JIT icall, it sets the pending exception and returns NULL on error.
*/
gunichar2*
mono_string_builder_to_utf16 (MonoStringBuilder *sb)
{
+ MonoError error;
+
if (!sb)
return NULL;
if (len == 0)
len = 1;
- gunichar2 *str = (gunichar2 *)mono_marshal_alloc ((len + 1) * sizeof (gunichar2));
+ gunichar2 *str = (gunichar2 *)mono_marshal_alloc ((len + 1) * sizeof (gunichar2), &error);
+ if (!mono_error_ok (&error)) {
+ mono_error_set_pending_exception (&error);
+ return NULL;
+ }
+
str[len] = '\0';
if (len == 0)
return str;
}
+/* 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_raise_exception(exc);
- return NULL;
- } else {
- as = CoTaskMemAlloc (len + 1);
- memcpy (as, tmp, len + 1);
- g_free (tmp);
- return as;
- }
-#else
- return mono_string_to_utf8 (s);
-#endif
-}
+ MonoError error;
+ char *result = mono_string_to_utf8_checked (s, &error);
+ mono_error_set_pending_exception (&error);
+ return result;
+}
gpointer
mono_string_to_ansibstr (MonoString *string_obj)
void
mono_string_to_byvalstr (gpointer dst, MonoString *src, int size)
{
+ MonoError error;
char *s;
int len;
if (!src)
return;
- s = mono_string_to_utf8 (src);
+ s = mono_string_to_utf8_checked (src, &error);
+ if (mono_error_set_pending_exception (&error))
+ return;
len = MIN (size, strlen (s));
if (len >= size)
len--;
*((gunichar2 *) dst + len) = 0;
}
+/* this is an icall, it sets the pending exception and returns NULL on error */
static MonoString*
mono_string_new_len_wrapper (const char *text, guint length)
{
- return mono_string_new_len (mono_domain_get (), text, length);
+ MonoError error;
+ MonoString *result = mono_string_new_len_checked (mono_domain_get (), text, length, &error);
+ mono_error_set_pending_exception (&error);
+ return result;
}
#ifndef DISABLE_JIT
mono_type_to_stind (MonoType *type)
{
if (type->byref)
- return CEE_STIND_I;
+ return MONO_TYPE_IS_REFERENCE (type) ? CEE_STIND_REF : CEE_STIND_I;
+
handle_enum:
switch (type->type) {
mono_mb_emit_ldloc (mb, 1);
mono_mb_emit_icon (mb, mspec->data.array_data.num_elem);
mono_mb_emit_op (mb, CEE_NEWARR, eklass);
- mono_mb_emit_byte (mb, CEE_STIND_I);
+ mono_mb_emit_byte (mb, CEE_STIND_REF);
if (eklass->blittable) {
/* copy the elements */
} else {
mono_mb_emit_ldloc (mb, 1);
mono_mb_emit_ldloc (mb, 0);
- mono_mb_emit_icall (mb, mono_string_from_utf16);
+ mono_mb_emit_icall (mb, ves_icall_mono_string_from_utf16);
}
mono_mb_emit_byte (mb, CEE_STIND_REF);
break;
mono_mb_emit_ldloc (mb, 0);
mono_mb_emit_byte (mb, CEE_LDIND_I);
#ifdef TARGET_WIN32
- mono_mb_emit_icall (mb, mono_string_from_utf16);
+ mono_mb_emit_icall (mb, ves_icall_mono_string_from_utf16);
#else
mono_mb_emit_icall (mb, mono_string_new_wrapper);
#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);
mono_mb_emit_ldloc (mb, 1);
mono_mb_emit_ldloc (mb, 0);
mono_mb_emit_byte (mb, CEE_LDIND_I);
- mono_mb_emit_icall (mb, mono_string_from_utf16);
+ mono_mb_emit_icall (mb, ves_icall_mono_string_from_utf16);
mono_mb_emit_byte (mb, CEE_STIND_REF);
break;
case MONO_MARSHAL_CONV_OBJECT_STRUCT: {
}
static gpointer
-conv_to_icall (MonoMarshalConv conv)
+conv_to_icall (MonoMarshalConv conv, int *ind_store_type)
{
+ int dummy;
+ if (!ind_store_type)
+ ind_store_type = &dummy;
+ *ind_store_type = CEE_STIND_I;
switch (conv) {
case MONO_MARSHAL_CONV_STR_LPWSTR:
return mono_marshal_string_to_utf16;
case MONO_MARSHAL_CONV_LPWSTR_STR:
- return mono_string_from_utf16;
+ *ind_store_type = CEE_STIND_REF;
+ return ves_icall_mono_string_from_utf16;
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;
case MONO_MARSHAL_CONV_STR_LPTSTR:
#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:
- return mono_string_from_bstr;
+ *ind_store_type = CEE_STIND_REF;
+ return mono_string_from_bstr_icall;
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_DEL_FTN:
return mono_delegate_to_ftnptr;
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;
case MONO_MARSHAL_CONV_LPTSTR_SB:
+ *ind_store_type = CEE_STIND_REF;
#ifdef TARGET_WIN32
return mono_string_utf16_to_builder;
#else
return mono_string_utf8_to_builder;
#endif
case MONO_MARSHAL_CONV_LPWSTR_SB:
+ *ind_store_type = CEE_STIND_REF;
return mono_string_utf16_to_builder;
case MONO_MARSHAL_FREE_ARRAY:
return mono_marshal_free_array;
emit_object_to_ptr_conv (MonoMethodBuilder *mb, MonoType *type, MonoMarshalConv conv, MonoMarshalSpec *mspec)
{
int pos;
+ int stind_op;
switch (conv) {
case MONO_MARSHAL_CONV_BOOL_I4:
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:
mono_mb_emit_ldloc (mb, 1);
mono_mb_emit_ldloc (mb, 0);
mono_mb_emit_byte (mb, CEE_LDIND_REF);
- mono_mb_emit_icall (mb, conv_to_icall (conv));
- mono_mb_emit_byte (mb, CEE_STIND_I);
+ mono_mb_emit_icall (mb, conv_to_icall (conv, &stind_op));
+ mono_mb_emit_byte (mb, stind_op);
break;
}
case MONO_MARSHAL_CONV_ARRAY_SAVEARRAY:
mono_mb_emit_ldloc (mb, 1);
mono_mb_emit_ldloc (mb, 0);
mono_mb_emit_byte (mb, CEE_LDIND_REF);
- mono_mb_emit_icall (mb, conv_to_icall (conv));
- mono_mb_emit_byte (mb, CEE_STIND_I);
+ mono_mb_emit_icall (mb, conv_to_icall (conv, &stind_op));
+ mono_mb_emit_byte (mb, stind_op);
break;
case MONO_MARSHAL_CONV_STR_BYVALSTR:
case MONO_MARSHAL_CONV_STR_BYVALWSTR: {
mono_mb_emit_ldloc (mb, 0);
mono_mb_emit_byte (mb, CEE_LDIND_REF); /* src String */
mono_mb_emit_icon (mb, mspec->data.array_data.num_elem);
- mono_mb_emit_icall (mb, conv_to_icall (conv));
+ mono_mb_emit_icall (mb, conv_to_icall (conv, NULL));
break;
}
case MONO_MARSHAL_CONV_ARRAY_BYVALARRAY: {
}
default: {
- char *msg = g_strdup_printf ("marshalling conversion %d not implemented", conv);
- MonoException *exc = mono_get_exception_not_implemented (msg);
- g_warning ("%s", msg);
- g_free (msg);
- mono_raise_exception (exc);
+ g_error ("marshalling conversion %d not implemented", conv);
+ }
}
+}
+
+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;
}
- if (klass != mono_defaults.safehandle_class) {
- if ((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_AUTO_LAYOUT) {
+ if (klass != mono_class_try_get_safehandle_class ()) {
+ if (mono_class_is_auto_layout (klass)) {
char *msg = g_strdup_printf ("Type %s which is passed to unmanaged code must have a StructLayout attribute.",
mono_type_full_name (&klass->byval_arg));
mono_mb_emit_exception_marshal_directive (mb, msg);
usize = info->fields [i + 1].offset - info->fields [i].offset;
}
- if (klass != mono_defaults.safehandle_class){
+ if (klass != mono_class_try_get_safehandle_class ()){
/*
* FIXME: Should really check for usize==0 and msize>0, but we apply
* the layout to the managed structure as well.
*/
- if (((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) && (usize == 0)) {
+ if (mono_class_is_explicit_layout (klass) && (usize == 0)) {
if (MONO_TYPE_IS_REFERENCE (info->fields [i].field->type) ||
((!last_field && MONO_TYPE_IS_REFERENCE (info->fields [i + 1].field->type))))
g_error ("Type %s which has an [ExplicitLayout] attribute cannot have a "
case MONO_MARSHAL_CONV_NONE: {
int t;
- if (ftype->byref || ftype->type == MONO_TYPE_I ||
- ftype->type == MONO_TYPE_U) {
+ //XXX a byref field!?!? that's not allowed! and worse, it might miss a WB
+ g_assert (!ftype->byref);
+ if (ftype->type == MONO_TYPE_I || ftype->type == MONO_TYPE_U) {
mono_mb_emit_ldloc (mb, 1);
mono_mb_emit_ldloc (mb, 0);
mono_mb_emit_byte (mb, CEE_LDIND_I);
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
#endif /* DISABLE_JIT */
+/* This is a JIT icall, it sets the pending exception and returns NULL on error. */
static MonoAsyncResult *
mono_delegate_begin_invoke (MonoDelegate *delegate, gpointer *params)
{
+ MonoError error;
MonoMulticastDelegate *mcast_delegate;
MonoClass *klass;
MonoMethod *method;
g_assert (delegate);
mcast_delegate = (MonoMulticastDelegate *) delegate;
- if (mcast_delegate->delegates != NULL)
- mono_raise_exception (mono_get_exception_argument (NULL, "The delegate must have only one target"));
+ if (mcast_delegate->delegates != NULL) {
+ mono_set_pending_exception (mono_get_exception_argument (NULL, "The delegate must have only one target"));
+ return NULL;
+ }
#ifndef DISABLE_REMOTING
if (delegate->target && mono_object_class (delegate->target) == mono_defaults.transparent_proxy_class) {
-
MonoTransparentProxy* tp = (MonoTransparentProxy *)delegate->target;
if (!mono_class_is_contextbound (tp->remote_class->proxy_class) || tp->rp->context != (MonoObject *) mono_context_get ()) {
-
/* If the target is a proxy, make a direct call. Is proxy's work
// to make the call asynchronous.
*/
MonoArray *out_args;
method = delegate->method;
- msg = mono_method_call_message_new (mono_marshal_method_from_wrapper (method), params, NULL, &async_callback, &state);
- ares = mono_async_result_new (mono_domain_get (), NULL, state, NULL, NULL);
+ msg = mono_method_call_message_new (mono_marshal_method_from_wrapper (method), params, NULL, &async_callback, &state, &error);
+ if (mono_error_set_pending_exception (&error))
+ return NULL;
+ ares = mono_async_result_new (mono_domain_get (), NULL, state, NULL, NULL, &error);
+ if (mono_error_set_pending_exception (&error))
+ return NULL;
MONO_OBJECT_SETREF (ares, async_delegate, (MonoObject *)delegate);
MONO_OBJECT_SETREF (ares, async_callback, (MonoObject *)async_callback);
MONO_OBJECT_SETREF (msg, async_result, ares);
msg->call_type = CallType_BeginInvoke;
exc = NULL;
- mono_remoting_invoke ((MonoObject *)tp->rp, msg, &exc, &out_args);
+ mono_remoting_invoke ((MonoObject *)tp->rp, msg, &exc, &out_args, &error);
+ if (!mono_error_ok (&error)) {
+ mono_error_set_pending_exception (&error);
+ return NULL;
+ }
if (exc)
- mono_raise_exception ((MonoException *) exc);
+ mono_set_pending_exception ((MonoException *) exc);
return ares;
}
}
method = mono_get_delegate_invoke (klass);
g_assert (method);
- return mono_threadpool_ms_begin_invoke (mono_domain_get (), (MonoObject*) delegate, method, params);
+ MonoAsyncResult *result = mono_threadpool_ms_begin_invoke (mono_domain_get (), (MonoObject*) delegate, method, params, &error);
+ mono_error_set_pending_exception (&error);
+ return result;
}
#ifndef DISABLE_JIT
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 (MonoMarshalConv)-1;
+ 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 (MonoMarshalConv)-1;
+ 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;
case MONO_NATIVE_BSTR:
return MONO_MARSHAL_CONV_BSTR_STR;
default:
- return (MonoMarshalConv)-1;
+ return MONO_MARSHAL_CONV_INVALID;
}
}
*/
*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;
return MONO_MARSHAL_CONV_LPTSTR_SB;
break;
default:
- return (MonoMarshalConv)-1;
+ return MONO_MARSHAL_CONV_INVALID;
}
}
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;
}
{
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);
return res;
}
+/* This is a JIT icall, it sets the pending exception and returns NULL on error. */
static MonoObject *
mono_delegate_end_invoke (MonoDelegate *delegate, gpointer *params)
{
+ MonoError error;
MonoDomain *domain = mono_domain_get ();
MonoAsyncResult *ares;
MonoMethod *method = NULL;
if (!delegate->method_info) {
g_assert (delegate->method);
- MONO_OBJECT_SETREF (delegate, method_info, mono_method_get_object (domain, delegate->method, NULL));
+ MonoReflectionMethod *rm = mono_method_get_object_checked (domain, delegate->method, NULL, &error);
+ if (!mono_error_ok (&error)) {
+ mono_error_set_pending_exception (&error);
+ return NULL;
+ }
+ MONO_OBJECT_SETREF (delegate, method_info, rm);
}
if (!delegate->method_info || !delegate->method_info->method)
sig = mono_signature_no_pinvoke (method);
- msg = mono_method_call_message_new (method, params, NULL, NULL, NULL);
+ msg = mono_method_call_message_new (method, params, NULL, NULL, NULL, &error);
+ if (mono_error_set_pending_exception (&error))
+ return NULL;
ares = (MonoAsyncResult *)mono_array_get (msg->args, gpointer, sig->param_count - 1);
if (ares == NULL) {
- mono_raise_exception (mono_exception_from_name_msg (mono_defaults.corlib, "System.Runtime.Remoting", "RemotingException", "The async result object is null or of an unexpected type."));
+ mono_set_pending_exception (mono_exception_from_name_msg (mono_defaults.corlib, "System.Runtime.Remoting", "RemotingException", "The async result object is null or of an unexpected type."));
return NULL;
}
if (ares->async_delegate != (MonoObject*)delegate) {
- mono_raise_exception (mono_get_exception_invalid_operation (
+ mono_set_pending_exception (mono_get_exception_invalid_operation (
"The IAsyncResult object provided does not match this delegate."));
return NULL;
}
#ifndef DISABLE_REMOTING
if (delegate->target && mono_object_is_transparent_proxy (delegate->target)) {
MonoTransparentProxy* tp = (MonoTransparentProxy *)delegate->target;
- msg = (MonoMethodMessage *)mono_object_new (domain, mono_defaults.mono_method_message_class);
- mono_message_init (domain, msg, delegate->method_info, NULL);
+ msg = (MonoMethodMessage *)mono_object_new_checked (domain, mono_defaults.mono_method_message_class, &error);
+ if (!mono_error_ok (&error)) {
+ mono_error_set_pending_exception (&error);
+ return NULL;
+ }
+ mono_message_init (domain, msg, delegate->method_info, NULL, &error);
+ if (mono_error_set_pending_exception (&error))
+ return NULL;
msg->call_type = CallType_EndInvoke;
MONO_OBJECT_SETREF (msg, async_result, ares);
- res = mono_remoting_invoke ((MonoObject *)tp->rp, msg, &exc, &out_args);
+ res = mono_remoting_invoke ((MonoObject *)tp->rp, msg, &exc, &out_args, &error);
+ if (!mono_error_ok (&error)) {
+ mono_error_set_pending_exception (&error);
+ return NULL;
+ }
} else
#endif
{
- res = mono_threadpool_ms_end_invoke (ares, &out_args, &exc);
+ res = mono_threadpool_ms_end_invoke (ares, &out_args, &exc, &error);
+ if (mono_error_set_pending_exception (&error))
+ return NULL;
}
if (exc) {
if (((MonoException*)exc)->stack_trace) {
- char *strace = mono_string_to_utf8 (((MonoException*)exc)->stack_trace);
- char *tmp;
- tmp = g_strdup_printf ("%s\nException Rethrown at:\n", strace);
- g_free (strace);
- MONO_OBJECT_SETREF (((MonoException*)exc), stack_trace, mono_string_new (domain, tmp));
- g_free (tmp);
+ MonoError inner_error;
+ char *strace = mono_string_to_utf8_checked (((MonoException*)exc)->stack_trace, &inner_error);
+ if (is_ok (&inner_error)) {
+ char *tmp;
+ tmp = g_strdup_printf ("%s\nException Rethrown at:\n", strace);
+ g_free (strace);
+ MONO_OBJECT_SETREF (((MonoException*)exc), stack_trace, mono_string_new (domain, tmp));
+ g_free (tmp);
+ } else
+ mono_error_cleanup (&inner_error); /* no stack trace, but at least throw the original exception */
}
- mono_raise_exception ((MonoException*)exc);
+ mono_set_pending_exception ((MonoException*)exc);
}
- mono_method_return_message_restore (method, params, out_args);
+ mono_method_return_message_restore (method, params, out_args, &error);
+ mono_error_set_pending_exception (&error);
return res;
}
g_free (pair);
}
-static MonoMethodSignature*
-sig_to_rgctx_sig (MonoMethodSignature *sig)
-{
- // FIXME: memory allocation
- MonoMethodSignature *res;
- int i;
-
- res = (MonoMethodSignature *)g_malloc (MONO_SIZEOF_METHOD_SIGNATURE + (sig->param_count + 1) * sizeof (MonoType*));
- memcpy (res, sig, MONO_SIZEOF_METHOD_SIGNATURE);
- res->param_count = sig->param_count + 1;
- for (i = 0; i < sig->param_count; ++i)
- res->params [i] = sig->params [i];
- res->params [sig->param_count] = &mono_defaults.int_class->byval_arg;
- return res;
-}
-
MonoMethod *
mono_marshal_get_delegate_invoke_internal (MonoMethod *method, gboolean callvirt, gboolean static_method_with_first_arg_bound, MonoMethod *target_method)
{
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, pos3, pos4;
+ int pos0, pos1, pos2;
char *name;
MonoClass *target_class = 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;
if (callvirt) {
subtype = WRAPPER_SUBTYPE_DELEGATE_INVOKE_VIRTUAL;
if (target_method->is_inflated) {
+ MonoError error;
MonoType *target_type;
g_assert (method->signature->hasthis);
- target_type = mono_class_inflate_generic_type (method->signature->params [0],
- mono_method_get_context (method));
+ target_type = mono_class_inflate_generic_type_checked (method->signature->params [0],
+ mono_method_get_context (method), &error);
+ mono_error_assert_ok (&error); /* FIXME don't swallow the error */
target_class = mono_class_from_mono_type (target_type);
} else {
target_class = target_method->klass;
* 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;
container = mono_method_get_generic_container (method);
if (!container)
- container = method->klass->generic_container;
+ container = mono_class_try_get_generic_container (method->klass); //FIXME is this a case of a try?
g_assert (container);
invoke_sig = sig = mono_signature_no_pinvoke (method);
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);
// FIXME:
mono_mb_emit_exception_full (mb, "System", "NotImplementedException", "");
} else {
- MonoMethodSignature *rgctx_sig;
-
- // FIXME: Support this for the other cases as well
- mono_mb_emit_ldarg (mb, 0);
- mono_mb_emit_ldflda (mb, MONO_STRUCT_OFFSET (MonoDelegate, rgctx));
- mono_mb_emit_byte (mb, CEE_LDIND_I);
- pos3 = mono_mb_emit_branch (mb, CEE_BRFALSE);
-
- /* Rgctx case */
- rgctx_sig = sig_to_rgctx_sig (sig);
-
mono_mb_emit_ldloc (mb, local_target);
for (i = 0; i < sig->param_count; ++i)
mono_mb_emit_ldarg (mb, i + 1);
mono_mb_emit_ldarg (mb, 0);
- mono_mb_emit_ldflda (mb, MONO_STRUCT_OFFSET (MonoDelegate, rgctx));
+ mono_mb_emit_ldflda (mb, MONO_STRUCT_OFFSET (MonoDelegate, extra_arg));
mono_mb_emit_byte (mb, CEE_LDIND_I);
mono_mb_emit_ldarg (mb, 0);
mono_mb_emit_ldflda (mb, MONO_STRUCT_OFFSET (MonoDelegate, method_ptr));
mono_mb_emit_byte (mb, CEE_LDIND_I);
- mono_mb_emit_op (mb, CEE_CALLI, rgctx_sig);
- pos4 = mono_mb_emit_branch (mb, CEE_BR);
-
- /* Non-rgctx case */
- mono_mb_patch_branch (mb, pos3);
- mono_mb_emit_ldloc (mb, local_target);
- for (i = 0; i < sig->param_count; ++i)
- mono_mb_emit_ldarg (mb, i + 1);
- mono_mb_emit_ldarg (mb, 0);
- mono_mb_emit_ldflda (mb, MONO_STRUCT_OFFSET (MonoDelegate, method_ptr));
- mono_mb_emit_byte (mb, CEE_LDIND_I );
- mono_mb_emit_op (mb, CEE_CALLI, sig);
-
- mono_mb_patch_branch (mb, pos4);
-
+ mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
+ mono_mb_emit_op (mb, CEE_MONO_CALLI_EXTRA_ARG, sig);
mono_mb_emit_byte (mb, CEE_RET);
}
mono_mb_emit_op (mb, CEE_CALL, target_method);
}
} else {
- MonoMethodSignature *rgctx_sig;
-
- mono_mb_emit_ldarg (mb, 0);
- mono_mb_emit_ldflda (mb, MONO_STRUCT_OFFSET (MonoDelegate, rgctx));
- mono_mb_emit_byte (mb, CEE_LDIND_I);
- pos3 = mono_mb_emit_branch (mb, CEE_BRFALSE);
-
- /* Rgctx case */
- rgctx_sig = sig_to_rgctx_sig (invoke_sig);
-
if (static_method_with_first_arg_bound) {
mono_mb_emit_ldloc (mb, local_target);
if (!MONO_TYPE_IS_REFERENCE (invoke_sig->params[0]))
for (i = 0; i < sig->param_count; ++i)
mono_mb_emit_ldarg (mb, i + 1);
mono_mb_emit_ldarg (mb, 0);
- mono_mb_emit_ldflda (mb, MONO_STRUCT_OFFSET (MonoDelegate, rgctx));
- mono_mb_emit_byte (mb, CEE_LDIND_I);
- mono_mb_emit_ldarg (mb, 0);
- mono_mb_emit_ldflda (mb, MONO_STRUCT_OFFSET (MonoDelegate, method_ptr));
+ mono_mb_emit_ldflda (mb, MONO_STRUCT_OFFSET (MonoDelegate, extra_arg));
mono_mb_emit_byte (mb, CEE_LDIND_I);
- mono_mb_emit_op (mb, CEE_CALLI, rgctx_sig);
- pos4 = mono_mb_emit_branch (mb, CEE_BR);
-
- /* Non-rgctx case */
- mono_mb_patch_branch (mb, pos3);
- if (static_method_with_first_arg_bound) {
- mono_mb_emit_ldloc (mb, local_target);
- if (!MONO_TYPE_IS_REFERENCE (invoke_sig->params[0]))
- mono_mb_emit_op (mb, CEE_UNBOX_ANY, mono_class_from_mono_type (invoke_sig->params[0]));
- }
- for (i = 0; i < sig->param_count; ++i)
- mono_mb_emit_ldarg (mb, i + 1);
mono_mb_emit_ldarg (mb, 0);
mono_mb_emit_ldflda (mb, MONO_STRUCT_OFFSET (MonoDelegate, method_ptr));
mono_mb_emit_byte (mb, CEE_LDIND_I);
- mono_mb_emit_op (mb, CEE_CALLI, invoke_sig);
-
- mono_mb_patch_branch (mb, pos4);
+ mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
+ mono_mb_emit_op (mb, CEE_MONO_CALLI_EXTRA_ARG, invoke_sig);
}
mono_mb_emit_byte (mb, CEE_RET);
mb->skip_visibility = 1;
#endif /* DISABLE_JIT */
+ info = mono_wrapper_info_create (mb, subtype);
+ info->d.delegate_invoke.method = method;
+
if (ctx) {
MonoMethod *def;
- def = mono_mb_create_and_cache (cache, cache_key, mb, sig, sig->param_count + 16);
+ def = mono_mb_create_and_cache_full (cache, cache_key, mb, sig, sig->param_count + 16, info, NULL);
res = cache_generic_delegate_wrapper (cache, orig_method, def, ctx);
} else if (callvirt) {
new_key = g_new0 (SignaturePointerPair, 1);
*new_key = key;
- info = mono_wrapper_info_create (mb, subtype);
-
res = mono_mb_create_and_cache_full (cache, new_key, mb, sig, sig->param_count + 16, info, &found);
if (found)
g_free (new_key);
} else {
- info = mono_wrapper_info_create (mb, subtype);
-
res = mono_mb_create_and_cache_full (cache, cache_key, mb, sig, sig->param_count + 16, info, NULL);
}
mono_mb_free (mb);
case MONO_TYPE_CHAR:
return &mono_defaults.uint16_class->byval_arg;
case MONO_TYPE_U:
- case MONO_TYPE_PTR:
return &mono_defaults.int_class->byval_arg;
case MONO_TYPE_VALUETYPE:
if (t->data.klass->enumtype) {
* 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.
- * If PASS_RGCTX is TRUE, the signature of the called method is changed to include a 'gpointer rgctx' as the
- * last argument (after 'this').
*/
MonoMethod *
-mono_marshal_get_runtime_invoke (MonoMethod *method, gboolean virtual_, gboolean pass_rgctx)
+mono_marshal_get_runtime_invoke (MonoMethod *method, gboolean virtual_)
{
MonoMethodSignature *sig, *csig, *callsig;
MonoMethodBuilder *mb;
sig = mono_method_signature (method);
- if (pass_rgctx) {
- sig = sig_to_rgctx_sig (sig);
- callsig = sig_to_rgctx_sig (callsig);
- }
-
target_klass = get_wrapper_target_class (method->klass->image);
/* Try to share wrappers for non-corlib methods with simple signatures */
csig->call_convention = MONO_CALL_C;
#endif
- name = mono_signature_to_name (callsig, pass_rgctx ? (virtual_ ? "runtime_invoke_virtual_rgctx" : "runtime_invoke_rgctx") : (virtual_ ? "runtime_invoke_virtual" : "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);
info = mono_wrapper_info_create (mb, WRAPPER_SUBTYPE_RUNTIME_INVOKE_NORMAL);
info->d.runtime_invoke.sig = callsig;
- info->d.runtime_invoke.pass_rgctx = pass_rgctx;
/* Somebody may have created it before us */
if (!res) {
* ARGS should contain the this argument too.
* This wrapper serves the same purpose as the runtime-invoke wrappers, but there
* is only one copy of it, which is useful in full-aot.
- * The wrapper info for the wrapper is a WrapperInfo structure.
*/
MonoMethod*
mono_marshal_get_runtime_invoke_dynamic (void)
/*
* generates IL code for the icall wrapper (the generated method
* calls the unmanaged code in func)
- * The wrapper info for the wrapper is a WrapperInfo structure.
*/
MonoMethod *
mono_marshal_get_icall_wrapper (MonoMethodSignature *sig, const char *name, gconstpointer func, gboolean check_exceptions)
int i;
WrapperInfo *info;
+ GHashTable *cache = get_cache (&mono_defaults.object_class->image->icall_wrapper_cache, mono_aligned_addr_hash, NULL);
+ if ((res = mono_marshal_find_in_cache (cache, (gpointer) func)))
+ return res;
+
g_assert (sig->pinvoke);
mb = mono_mb_new (mono_defaults.object_class, name, MONO_WRAPPER_MANAGED_TO_NATIVE);
info = mono_wrapper_info_create (mb, WRAPPER_SUBTYPE_ICALL_WRAPPER);
info->d.icall.func = (gpointer)func;
- res = mono_mb_create (mb, csig, csig->param_count + 16, info);
+ res = mono_mb_create_and_cache_full (cache, (gpointer) func, mb, csig, csig->param_count + 16, info, NULL);
mono_mb_free (mb);
return res;
*conv_arg_type = &mono_defaults.int_class->byval_arg;
return conv_arg;
#else
+ MonoError error;
MonoType *mtype;
MonoClass *mklass;
static MonoClass *ICustomMarshaler = NULL;
int pos2;
if (!ICustomMarshaler) {
- MonoClass *klass = mono_class_from_name (mono_defaults.corlib, "System.Runtime.InteropServices", "ICustomMarshaler");
+ MonoClass *klass = mono_class_try_get_icustom_marshaler_class ();
if (!klass) {
exception_msg = g_strdup ("Current profile doesn't support ICustomMarshaler");
goto handle_exception;
}
if (spec->data.custom_data.image)
- mtype = mono_reflection_type_from_name (spec->data.custom_data.custom_name, spec->data.custom_data.image);
+ mtype = mono_reflection_type_from_name_checked (spec->data.custom_data.custom_name, spec->data.custom_data.image, &error);
else
- mtype = mono_reflection_type_from_name (spec->data.custom_data.custom_name, m->image);
+ mtype = mono_reflection_type_from_name_checked (spec->data.custom_data.custom_name, m->image, &error);
g_assert (mtype != NULL);
+ mono_error_assert_ok (&error);
mklass = mono_class_from_mono_type (mtype);
g_assert (mklass != NULL);
klass = mono_class_from_mono_type (t);
- date_time_class = mono_class_from_name_cached (mono_defaults.corlib, "System", "DateTime");
+ date_time_class = mono_class_get_date_time_class ();
switch (action) {
case MARSHAL_ACTION_CONV_IN:
break;
}
- if (((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) ||
- klass->blittable || klass->enumtype)
+ if (mono_class_is_explicit_layout (klass) || klass->blittable || klass->enumtype)
break;
conv_arg = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
/* Have to change the signature since the vtype is passed byref */
m->csig->params [argnum - m->csig->hasthis] = &mono_defaults.int_class->byval_arg;
- if (((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) ||
- klass->blittable || klass->enumtype)
+ if (mono_class_is_explicit_layout (klass) || klass->blittable || klass->enumtype)
mono_mb_emit_ldarg_addr (mb, argnum);
else
mono_mb_emit_ldloc (mb, conv_arg);
break;
}
- if (((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) ||
- klass->blittable || klass->enumtype) {
+ if (mono_class_is_explicit_layout (klass) || klass->blittable || klass->enumtype) {
mono_mb_emit_ldarg (mb, argnum);
break;
}
break;
}
- if (((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) ||
- klass->blittable || klass->enumtype)
+ if (mono_class_is_explicit_layout (klass) || klass->blittable || klass->enumtype)
break;
if (t->byref) {
break;
case MARSHAL_ACTION_CONV_RESULT:
- if (((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) ||
- klass->blittable) {
+ if (mono_class_is_explicit_layout (klass) || klass->blittable) {
mono_mb_emit_stloc (mb, 3);
break;
}
/* load pointer to returned value type */
- mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
- mono_mb_emit_byte (mb, CEE_MONO_VTADDR);
+ g_assert (m->vtaddr_var);
+ mono_mb_emit_ldloc (mb, m->vtaddr_var);
/* store the address of the source into local variable 0 */
mono_mb_emit_stloc (mb, 0);
/* set dst_ptr */
break;
case MARSHAL_ACTION_MANAGED_CONV_IN:
- if (((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) ||
- klass->blittable || klass->enumtype) {
+ if (mono_class_is_explicit_layout (klass) || klass->blittable || klass->enumtype) {
conv_arg = 0;
break;
}
break;
case MARSHAL_ACTION_MANAGED_CONV_OUT:
- if (((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) ||
- klass->blittable || klass->enumtype) {
+ if (mono_class_is_explicit_layout (klass) || klass->blittable || klass->enumtype)
break;
- }
-
if (t->byref && (t->attrs & PARAM_ATTRIBUTE_IN) && !(t->attrs & PARAM_ATTRIBUTE_OUT))
break;
break;
case MARSHAL_ACTION_MANAGED_CONV_RESULT:
- if (((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) ||
- klass->blittable || klass->enumtype) {
+ if (mono_class_is_explicit_layout (klass) || klass->blittable || klass->enumtype) {
mono_mb_emit_stloc (mb, 3);
m->retobj_var = 0;
break;
}
/* load pointer to returned value type */
- mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
- mono_mb_emit_byte (mb, CEE_MONO_VTADDR);
+ g_assert (m->vtaddr_var);
+ mono_mb_emit_ldloc (mb, m->vtaddr_var);
/* store the address of the source into local variable 0 */
mono_mb_emit_stloc (mb, 0);
g_assert (m->retobj_var);
mono_mb_emit_icon (mb, mono_class_native_size (klass, NULL));
mono_mb_emit_byte (mb, CEE_CONV_I);
- mono_mb_emit_icall (mb, mono_marshal_alloc);
+ mono_mb_emit_icall (mb, ves_icall_marshal_alloc);
mono_mb_emit_stloc (mb, 1);
mono_mb_emit_ldloc (mb, 1);
mono_mb_emit_stloc (mb, m->retobj_var);
mono_mb_emit_ldarg (mb, argnum);
}
- if (conv == -1) {
+ if (conv == MONO_MARSHAL_CONV_INVALID) {
char *msg = g_strdup_printf ("string marshalling conversion %d not implemented", encoding);
mono_mb_emit_exception_marshal_directive (mb, msg);
} else {
- mono_mb_emit_icall (mb, conv_to_icall (conv));
+ mono_mb_emit_icall (mb, conv_to_icall (conv, NULL));
mono_mb_emit_stloc (mb, conv_arg);
}
case MARSHAL_ACTION_CONV_OUT:
conv = mono_marshal_get_ptr_to_string_conv (m->piinfo, spec, &need_free);
- if (conv == -1) {
+ if (conv == MONO_MARSHAL_CONV_INVALID) {
char *msg = g_strdup_printf ("string marshalling conversion %d not implemented", encoding);
mono_mb_emit_exception_marshal_directive (mb, msg);
break;
mono_mb_emit_icall (mb, mono_string_new_len_wrapper);
mono_mb_emit_byte (mb, CEE_STIND_REF);
} else if (t->byref && (t->attrs & PARAM_ATTRIBUTE_OUT || !(t->attrs & PARAM_ATTRIBUTE_IN))) {
+ int stind_op;
mono_mb_emit_ldarg (mb, argnum);
mono_mb_emit_ldloc (mb, conv_arg);
- mono_mb_emit_icall (mb, conv_to_icall (conv));
- mono_mb_emit_byte (mb, CEE_STIND_REF);
+ mono_mb_emit_icall (mb, conv_to_icall (conv, &stind_op));
+ mono_mb_emit_byte (mb, stind_op);
need_free = TRUE;
}
mono_mb_emit_stloc (mb, 0);
conv = mono_marshal_get_ptr_to_string_conv (m->piinfo, spec, &need_free);
- if (conv == -1) {
+ if (conv == MONO_MARSHAL_CONV_INVALID) {
char *msg = g_strdup_printf ("string marshalling conversion %d not implemented", encoding);
mono_mb_emit_exception_marshal_directive (mb, msg);
break;
}
mono_mb_emit_ldloc (mb, 0);
- mono_mb_emit_icall (mb, conv_to_icall (conv));
+ mono_mb_emit_icall (mb, conv_to_icall (conv, NULL));
mono_mb_emit_stloc (mb, 3);
/* free the string */
}
conv = mono_marshal_get_ptr_to_string_conv (m->piinfo, spec, &need_free);
- if (conv == -1) {
+ if (conv == MONO_MARSHAL_CONV_INVALID) {
char *msg = g_strdup_printf ("string marshalling conversion %d not implemented", encoding);
mono_mb_emit_exception_marshal_directive (mb, msg);
break;
mono_mb_emit_ldarg (mb, argnum);
if (t->byref)
mono_mb_emit_byte (mb, CEE_LDIND_I);
- mono_mb_emit_icall (mb, conv_to_icall (conv));
+ mono_mb_emit_icall (mb, conv_to_icall (conv, NULL));
mono_mb_emit_stloc (mb, conv_arg);
break;
case MARSHAL_ACTION_MANAGED_CONV_OUT:
if (t->byref) {
if (conv_arg) {
+ int stind_op;
mono_mb_emit_ldarg (mb, argnum);
mono_mb_emit_ldloc (mb, conv_arg);
- mono_mb_emit_icall (mb, conv_to_icall (conv));
- mono_mb_emit_byte (mb, CEE_STIND_I);
+ mono_mb_emit_icall (mb, conv_to_icall (conv, &stind_op));
+ mono_mb_emit_byte (mb, stind_op);
}
}
break;
case MARSHAL_ACTION_MANAGED_CONV_RESULT:
- if (conv_to_icall (conv) == mono_marshal_string_to_utf16)
+ if (conv_to_icall (conv, NULL) == mono_marshal_string_to_utf16)
/* We need to make a copy so the caller is able to free it */
mono_mb_emit_icall (mb, mono_marshal_string_to_utf16_copy);
else
- mono_mb_emit_icall (mb, conv_to_icall (conv));
+ mono_mb_emit_icall (mb, conv_to_icall (conv, NULL));
mono_mb_emit_stloc (mb, 3);
break;
MonoMethod *ctor = NULL;
int intptr_handle_slot;
- if (t->data.klass->flags & TYPE_ATTRIBUTE_ABSTRACT){
+ if (mono_class_is_abstract (t->data.klass)) {
mono_mb_emit_byte (mb, CEE_POP);
mono_mb_emit_exception_marshal_directive (mb, g_strdup ("Returned SafeHandles should not be abstract"));
break;
mono_mb_emit_stloc (mb, conv_arg);
} else {
mono_mb_emit_ldarg (mb, argnum);
- mono_mb_emit_icall (mb, conv_to_icall (MONO_MARSHAL_CONV_DEL_FTN));
+ mono_mb_emit_icall (mb, conv_to_icall (MONO_MARSHAL_CONV_DEL_FTN, NULL));
mono_mb_emit_stloc (mb, conv_arg);
}
} else if (klass == mono_defaults.stringbuilder_class) {
if (t->byref && !(t->attrs & PARAM_ATTRIBUTE_IN) && (t->attrs & PARAM_ATTRIBUTE_OUT))
break;
- if (conv == -1) {
+ if (conv == MONO_MARSHAL_CONV_INVALID) {
char *msg = g_strdup_printf ("stringbuilder marshalling conversion %d not implemented", encoding);
mono_mb_emit_exception_marshal_directive (mb, msg);
break;
if (t->byref)
mono_mb_emit_byte (mb, CEE_LDIND_I);
- mono_mb_emit_icall (mb, conv_to_icall (conv));
+ mono_mb_emit_icall (mb, conv_to_icall (conv, NULL));
mono_mb_emit_stloc (mb, conv_arg);
} else if (klass->blittable) {
mono_mb_emit_byte (mb, CEE_LDNULL);
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_ldarg (mb, argnum);
mono_mb_emit_ldloc (mb, conv_arg);
- mono_mb_emit_icall (mb, conv_to_icall (conv));
+ mono_mb_emit_icall (mb, conv_to_icall (conv, NULL));
}
if (need_free) {
mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
mono_mb_emit_op (mb, CEE_MONO_CLASSCONST, klass);
mono_mb_emit_ldloc (mb, conv_arg);
- mono_mb_emit_icall (mb, conv_to_icall (MONO_MARSHAL_CONV_FTN_DEL));
+ mono_mb_emit_icall (mb, conv_to_icall (MONO_MARSHAL_CONV_FTN_DEL, NULL));
mono_mb_emit_byte (mb, CEE_STIND_REF);
}
break;
mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
mono_mb_emit_op (mb, CEE_MONO_CLASSCONST, klass);
mono_mb_emit_ldloc (mb, 0);
- mono_mb_emit_icall (mb, conv_to_icall (MONO_MARSHAL_CONV_FTN_DEL));
+ 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);
mono_mb_emit_ldarg (mb, argnum);
if (t->byref)
mono_mb_emit_byte (mb, CEE_LDIND_I);
- mono_mb_emit_icall (mb, conv_to_icall (MONO_MARSHAL_CONV_FTN_DEL));
+ mono_mb_emit_icall (mb, conv_to_icall (MONO_MARSHAL_CONV_FTN_DEL, NULL));
mono_mb_emit_stloc (mb, conv_arg);
break;
}
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);
}
/* The class can not have an automatic layout */
- if ((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_AUTO_LAYOUT) {
+ if (mono_class_is_auto_layout (klass)) {
mono_mb_emit_auto_layout_exception (mb, klass);
break;
}
case MARSHAL_ACTION_MANAGED_CONV_OUT:
if (klass->delegate) {
if (t->byref) {
+ int stind_op;
mono_mb_emit_ldarg (mb, argnum);
mono_mb_emit_ldloc (mb, conv_arg);
- mono_mb_emit_icall (mb, conv_to_icall (MONO_MARSHAL_CONV_DEL_FTN));
- mono_mb_emit_byte (mb, CEE_STIND_I);
+ mono_mb_emit_icall (mb, conv_to_icall (MONO_MARSHAL_CONV_DEL_FTN, &stind_op));
+ mono_mb_emit_byte (mb, stind_op);
break;
}
}
/* Allocate and set dest */
mono_mb_emit_icon (mb, mono_class_native_size (klass, NULL));
mono_mb_emit_byte (mb, CEE_CONV_I);
- mono_mb_emit_icall (mb, mono_marshal_alloc);
+ mono_mb_emit_icall (mb, ves_icall_marshal_alloc);
mono_mb_emit_stloc (mb, 1);
/* Update argument pointer */
case MARSHAL_ACTION_MANAGED_CONV_RESULT:
if (klass->delegate) {
- mono_mb_emit_icall (mb, conv_to_icall (MONO_MARSHAL_CONV_DEL_FTN));
+ mono_mb_emit_icall (mb, conv_to_icall (MONO_MARSHAL_CONV_DEL_FTN, NULL));
mono_mb_emit_stloc (mb, 3);
break;
}
/* The class can not have an automatic layout */
- if ((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_AUTO_LAYOUT) {
+ if (mono_class_is_auto_layout (klass)) {
mono_mb_emit_auto_layout_exception (mb, klass);
break;
}
/* Allocate and set dest */
mono_mb_emit_icon (mb, mono_class_native_size (klass, NULL));
mono_mb_emit_byte (mb, CEE_CONV_I);
- mono_mb_emit_icall (mb, mono_marshal_alloc);
+ mono_mb_emit_icall (mb, ves_icall_marshal_alloc);
mono_mb_emit_byte (mb, CEE_DUP);
mono_mb_emit_stloc (mb, 1);
mono_mb_emit_stloc (mb, 3);
mono_mb_emit_ldarg (mb, argnum);
if (t->byref)
mono_mb_emit_byte (mb, CEE_LDIND_I);
- mono_mb_emit_icall (mb, conv_to_icall (MONO_MARSHAL_CONV_ARRAY_LPARRAY));
+ mono_mb_emit_icall (mb, conv_to_icall (MONO_MARSHAL_CONV_ARRAY_LPARRAY, NULL));
mono_mb_emit_stloc (mb, conv_arg);
} else {
MonoClass *eklass;
conv = mono_marshal_get_stringbuilder_to_ptr_conv (m->piinfo, spec);
}
else
- conv = (MonoMarshalConv)-1;
+ conv = MONO_MARSHAL_CONV_INVALID;
- if (is_string && conv == -1) {
+ if (is_string && conv == MONO_MARSHAL_CONV_INVALID) {
char *msg = g_strdup_printf ("string/stringbuilder marshalling conversion %d not implemented", encoding);
mono_mb_emit_exception_marshal_directive (mb, msg);
break;
/* Emit marshalling code */
if (is_string) {
+ int stind_op;
mono_mb_emit_ldloc (mb, dest_ptr);
mono_mb_emit_ldloc (mb, src_var);
mono_mb_emit_ldloc (mb, index_var);
mono_mb_emit_byte (mb, CEE_LDELEM_REF);
- mono_mb_emit_icall (mb, conv_to_icall (conv));
- mono_mb_emit_byte (mb, CEE_STIND_I);
+ mono_mb_emit_icall (mb, conv_to_icall (conv, &stind_op));
+ mono_mb_emit_byte (mb, stind_op);
} else {
/* set the src_ptr */
mono_mb_emit_ldloc (mb, src_var);
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_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);
+ mono_mb_emit_byte (mb, CEE_STIND_REF);
}
}
gboolean need_free2;
MonoMarshalConv conv = mono_marshal_get_ptr_to_stringbuilder_conv (m->piinfo, spec, &need_free2);
- g_assert (conv != -1);
+ g_assert (conv != MONO_MARSHAL_CONV_INVALID);
/* dest */
mono_mb_emit_ldarg (mb, argnum);
mono_mb_emit_ldloc (mb, src_ptr);
mono_mb_emit_byte (mb, CEE_LDIND_I);
- mono_mb_emit_icall (mb, conv_to_icall (conv));
+ mono_mb_emit_icall (mb, conv_to_icall (conv, NULL));
if (need_free) {
/* src */
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) {
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));
+ mono_mb_emit_icall (mb, conv_to_icall (MONO_MARSHAL_FREE_LPARRAY, NULL));
}
break;
conv = mono_marshal_get_ptr_to_stringbuilder_conv (m->piinfo, spec, &need_free);
}
else
- conv = (MonoMarshalConv)-1;
+ conv = MONO_MARSHAL_CONV_INVALID;
mono_marshal_load_type_info (eklass);
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;
}
/* Emit marshalling code */
if (is_string) {
- g_assert (conv != -1);
+ g_assert (conv != MONO_MARSHAL_CONV_INVALID);
mono_mb_emit_ldloc (mb, conv_arg);
mono_mb_emit_ldloc (mb, index_var);
mono_mb_emit_ldloc (mb, src_ptr);
mono_mb_emit_byte (mb, CEE_LDIND_I);
- mono_mb_emit_icall (mb, conv_to_icall (conv));
+ mono_mb_emit_icall (mb, conv_to_icall (conv, NULL));
mono_mb_emit_byte (mb, CEE_STELEM_REF);
}
else {
conv = mono_marshal_get_stringbuilder_to_ptr_conv (m->piinfo, spec);
}
else
- conv = (MonoMarshalConv)-1;
+ conv = MONO_MARSHAL_CONV_INVALID;
mono_marshal_load_type_info (eklass);
/* Emit marshalling code */
if (is_string) {
- g_assert (conv != -1);
+ int stind_op;
+ g_assert (conv != MONO_MARSHAL_CONV_INVALID);
/* dest */
mono_mb_emit_ldloc (mb, dest_ptr);
mono_mb_emit_byte (mb, CEE_LDELEM_REF);
- mono_mb_emit_icall (mb, conv_to_icall (conv));
- mono_mb_emit_byte (mb, CEE_STIND_I);
+ mono_mb_emit_icall (mb, conv_to_icall (conv, &stind_op));
+ mono_mb_emit_byte (mb, stind_op);
}
else {
char *msg = g_strdup ("Marshalling of non-string and non-blittable arrays to managed code is not implemented.");
MonoClass *eklass;
guint32 label1, label2, label3;
int index_var, src, dest, esize;
- MonoMarshalConv conv = (MonoMarshalConv)-1;
+ MonoMarshalConv conv = MONO_MARSHAL_CONV_INVALID;
gboolean is_string = FALSE;
g_assert (!t->byref);
mono_mb_emit_byte (mb, CEE_ADD);
}
mono_mb_emit_byte (mb, CEE_MUL);
- mono_mb_emit_icall (mb, mono_marshal_alloc);
+ mono_mb_emit_icall (mb, ves_icall_marshal_alloc);
mono_mb_emit_stloc (mb, dest);
mono_mb_emit_ldloc (mb, dest);
mono_mb_emit_stloc (mb, 3);
/* Emit marshalling code */
if (is_string) {
- g_assert (conv != -1);
+ int stind_op;
+ g_assert (conv != MONO_MARSHAL_CONV_INVALID);
/* dest */
mono_mb_emit_ldloc (mb, dest);
mono_mb_emit_byte (mb, CEE_LDELEM_REF);
- mono_mb_emit_icall (mb, conv_to_icall (conv));
- mono_mb_emit_byte (mb, CEE_STIND_I);
+ mono_mb_emit_icall (mb, conv_to_icall (conv, &stind_op));
+ mono_mb_emit_byte (mb, stind_op);
}
else {
char *msg = g_strdup ("Marshalling of non-string arrays to managed code is not implemented.");
return emit_marshal_string (m, argnum, t, spec, conv_arg, conv_arg_type, action);
case MONO_TYPE_CLASS:
case MONO_TYPE_OBJECT:
-#ifndef DISABLE_COM
+#if !defined(DISABLE_COM) && !defined(DISABLE_JIT)
if (spec && spec->native == MONO_NATIVE_STRUCT)
return emit_marshal_variant (m, argnum, t, spec, conv_arg, conv_arg_type, action);
+#endif
+#if !defined(DISABLE_COM)
if (spec && (spec->native == MONO_NATIVE_IUNKNOWN ||
spec->native == MONO_NATIVE_IDISPATCH ||
spec->native == MONO_NATIVE_INTERFACE))
return mono_cominterop_emit_marshal_safearray (m, argnum, t, spec, conv_arg, conv_arg_type, action);
#endif
- if (mono_defaults.safehandle_class != NULL && t->data.klass &&
- mono_class_is_subclass_of (t->data.klass, mono_defaults.safehandle_class, FALSE))
+ if (mono_class_try_get_safehandle_class () != NULL && t->data.klass &&
+ mono_class_is_subclass_of (t->data.klass, mono_class_try_get_safehandle_class (), FALSE))
return emit_marshal_safehandle (m, argnum, t, spec, conv_arg, conv_arg_type, action);
return emit_marshal_object (m, argnum, t, spec, conv_arg, conv_arg_type, action);
MonoClass *klass;
int i, argnum, *tmp_locals;
int type, param_shift = 0;
- static MonoMethodSignature *get_last_error_sig = NULL;
int coop_gc_stack_dummy, coop_gc_var;
memset (&m, 0, sizeof (m));
mono_mb_emit_icon (mb, 0);
mono_mb_emit_stloc (mb, 2);
- if (!MONO_TYPE_IS_VOID(sig->ret)) {
+ if (!MONO_TYPE_IS_VOID (sig->ret)) {
/* allocate local 3 to store the return value */
mono_mb_add_local (mb, sig->ret);
}
coop_gc_var = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
}
- if (mspecs [0] && mspecs [0]->native == MONO_NATIVE_CUSTOM) {
- /* Return type custom marshaling */
- /*
- * Since we can't determine the return type of the unmanaged function,
+ /*
+ * cookie = mono_threads_enter_gc_safe_region_unbalanced (ref dummy);
+ *
+ * ret = method (...);
+ *
+ * mono_threads_exit_gc_safe_region_unbalanced (cookie, ref dummy);
+ *
+ * <interrupt check>
+ *
+ * return ret;
+ */
+
+ if (MONO_TYPE_ISSTRUCT (sig->ret))
+ m.vtaddr_var = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
+
+ if (mspecs [0] && mspecs [0]->native == MONO_NATIVE_CUSTOM) {
+ /* Return type custom marshaling */
+ /*
+ * Since we can't determine the return type of the unmanaged function,
* we assume it returns a pointer, and pass that pointer to
* MarshalNativeToManaged.
*/
tmp_locals [i] = emit_marshal (&m, i + param_shift, sig->params [i], mspecs [i + 1], 0, &csig->params [i], MARSHAL_ACTION_CONV_IN);
}
+ // In coop mode need to register blocking state during native call
+ if (mono_threads_is_coop_enabled ()) {
+ // Perform an extra, early lookup of the function address, so any exceptions
+ // potentially resulting from the lookup occur before entering blocking mode.
+ if (!func_param && !MONO_CLASS_IS_IMPORT (mb->method->klass) && aot) {
+ mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
+ mono_mb_emit_op (mb, CEE_MONO_ICALL_ADDR, &piinfo->method);
+ mono_mb_emit_byte (mb, CEE_POP); // Result not needed yet
+ }
+
+ mono_mb_emit_ldloc_addr (mb, coop_gc_stack_dummy);
+ mono_mb_emit_icall (mb, mono_threads_enter_gc_safe_region_unbalanced);
+ mono_mb_emit_stloc (mb, coop_gc_var);
+ }
+
/* push all arguments */
if (sig->hasthis)
emit_marshal (&m, i + param_shift, sig->params [i], mspecs [i + 1], tmp_locals [i], NULL, MARSHAL_ACTION_PUSH);
}
- if (mono_threads_is_coop_enabled ()) {
- mono_mb_emit_ldloc_addr (mb, coop_gc_stack_dummy);
- mono_mb_emit_icall (mb, mono_threads_prepare_blocking);
- mono_mb_emit_stloc (mb, coop_gc_var);
- }
-
/* call the native method */
if (func_param) {
mono_mb_emit_byte (mb, CEE_LDARG_0);
#else
g_assert_not_reached ();
#endif
- }
- else {
+ } else {
if (aot) {
/* Reuse the ICALL_ADDR opcode for pinvokes too */
mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
/* Set LastError if needed */
if (piinfo->piflags & PINVOKE_ATTRIBUTE_SUPPORTS_LAST_ERROR) {
- if (!get_last_error_sig) {
- get_last_error_sig = mono_metadata_signature_alloc (mono_defaults.corlib, 0);
- get_last_error_sig->ret = &mono_defaults.int_class->byval_arg;
- get_last_error_sig->pinvoke = 1;
- }
-
#ifdef TARGET_WIN32
- /*
- * Have to call GetLastError () early and without a wrapper, since various runtime components could
- * clobber its value.
- */
- mono_mb_emit_native_call (mb, get_last_error_sig, GetLastError);
- mono_mb_emit_icall (mb, mono_marshal_set_last_error_windows);
+ if (!aot) {
+ static MonoMethodSignature *get_last_error_sig = NULL;
+ if (!get_last_error_sig) {
+ get_last_error_sig = mono_metadata_signature_alloc (mono_defaults.corlib, 0);
+ get_last_error_sig->ret = &mono_defaults.int_class->byval_arg;
+ get_last_error_sig->pinvoke = 1;
+ }
+
+ /*
+ * Have to call GetLastError () early and without a wrapper, since various runtime components could
+ * clobber its value.
+ */
+ mono_mb_emit_native_call (mb, get_last_error_sig, GetLastError);
+ mono_mb_emit_icall (mb, mono_marshal_set_last_error_windows);
+ } else {
+ mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
+ mono_mb_emit_byte (mb, CEE_MONO_GET_LAST_ERROR);
+ mono_mb_emit_icall (mb, mono_marshal_set_last_error_windows);
+ }
#else
mono_mb_emit_icall (mb, mono_marshal_set_last_error);
#endif
- }
+ }
+
+ if (MONO_TYPE_ISSTRUCT (sig->ret)) {
+ MonoClass *klass = mono_class_from_mono_type (sig->ret);
+ mono_class_init (klass);
+ if (!(mono_class_is_explicit_layout (klass) || klass->blittable)) {
+ /* This is used by emit_marshal_vtype (), but it needs to go right before the call */
+ mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
+ mono_mb_emit_byte (mb, CEE_MONO_VTADDR);
+ mono_mb_emit_stloc (mb, m.vtaddr_var);
+ }
+ }
+ /* Unblock before converting the result, since that can involve calls into the runtime */
if (mono_threads_is_coop_enabled ()) {
mono_mb_emit_ldloc (mb, coop_gc_var);
mono_mb_emit_ldloc_addr (mb, coop_gc_stack_dummy);
- mono_mb_emit_icall (mb, mono_threads_finish_blocking);
+ mono_mb_emit_icall (mb, mono_threads_exit_gc_safe_region_unbalanced);
}
/* convert the result */
if (spec && spec->native == MONO_NATIVE_CUSTOM) {
emit_marshal (&m, 0, sig->ret, spec, 0, NULL, MARSHAL_ACTION_CONV_RESULT);
} else {
-
handle_enum:
switch (type) {
case MONO_TYPE_VOID:
*
* generates IL code for the pinvoke wrapper (the generated method
* calls the unmanaged code in piinfo->addr)
- * The wrapper info for the wrapper is a WrapperInfo structure.
*/
MonoMethod *
mono_marshal_get_native_wrapper (MonoMethod *method, gboolean check_exceptions, gboolean aot)
else
csig = mono_metadata_signature_dup_full (method->klass->image, sig);
+ //printf ("%s\n", mono_method_full_name (method, 1));
+
/* hack - string constructors returns a value */
if (method->string_ctor)
csig->ret = &mono_defaults.string_class->byval_arg;
#ifndef DISABLE_JIT
+ // FIXME:
+ MonoClass *handle_stack_mark_class;
+ MonoClass *error_class;
+ int thread_info_var = -1, stack_mark_var = -1, error_var = -1;
+ MonoMethodSignature *call_sig = csig;
+ 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;
+
+ /* Add a MonoError argument */
+ // FIXME: The stuff from mono_metadata_signature_dup_internal_with_padding ()
+ ret = mono_metadata_signature_alloc (method->klass->image, csig->param_count + 1);
+
+ ret->param_count = csig->param_count + 1;
+ ret->ret = csig->ret;
+ 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;
+ }
+
+ if (uses_handles) {
+ handle_stack_mark_class = mono_class_load_from_name (mono_get_corlib (), "Mono", "RuntimeStructs/HandleStackMark");
+ error_class = mono_class_load_from_name (mono_get_corlib (), "Mono", "RuntimeStructs/MonoError");
+
+ thread_info_var = mono_mb_add_local (mb, &mono_get_intptr_class ()->byval_arg);
+ stack_mark_var = mono_mb_add_local (mb, &handle_stack_mark_class->byval_arg);
+ error_var = mono_mb_add_local (mb, &error_class->byval_arg);
+
+ // FIXME: Change csig so it passes a handle not an objref
+ }
+
if (sig->hasthis) {
int pos;
pos = mono_mb_emit_branch (mb, CEE_BRTRUE);
mono_mb_emit_exception (mb, "NullReferenceException", NULL);
mono_mb_patch_branch (mb, pos);
-
- mono_mb_emit_byte (mb, CEE_LDARG_0);
}
- for (i = 0; i < sig->param_count; i++)
- mono_mb_emit_ldarg (mb, i + sig->hasthis);
+ if (uses_handles) {
+ mono_mb_emit_ldloc_addr (mb, stack_mark_var);
+ mono_mb_emit_ldloc_addr (mb, error_var);
+ mono_mb_emit_icall (mb, mono_icall_start);
+ mono_mb_emit_stloc (mb, thread_info_var);
+
+ if (sig->hasthis) {
+ mono_mb_emit_byte (mb, CEE_LDARG_0);
+ mono_mb_emit_icall (mb, mono_handle_new);
+ }
+ 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)
+ mono_mb_emit_byte (mb, CEE_LDARG_0);
+ for (i = 0; i < sig->param_count; i++)
+ mono_mb_emit_ldarg (mb, i + sig->hasthis);
+ }
if (aot) {
mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
mono_mb_emit_op (mb, CEE_MONO_ICALL_ADDR, &piinfo->method);
- mono_mb_emit_calli (mb, csig);
+ mono_mb_emit_calli (mb, call_sig);
} else {
g_assert (piinfo->addr);
- mono_mb_emit_native_call (mb, csig, piinfo->addr);
+ mono_mb_emit_native_call (mb, call_sig, piinfo->addr);
}
+
+ if (uses_handles) {
+ if (MONO_TYPE_IS_REFERENCE (sig->ret)) {
+ // if (ret != NULL_HANDLE) {
+ // ret = MONO_HANDLE_RAW(ret)
+ // }
+ mono_mb_emit_byte (mb, CEE_DUP);
+ int pos = mono_mb_emit_branch (mb, CEE_BRFALSE);
+ mono_mb_emit_ldflda (mb, MONO_HANDLE_PAYLOAD_OFFSET (MonoObject));
+ mono_mb_emit_byte (mb, CEE_LDIND_REF);
+ mono_mb_patch_branch (mb, pos);
+ }
+ mono_mb_emit_ldloc (mb, thread_info_var);
+ mono_mb_emit_ldloc_addr (mb, stack_mark_var);
+ mono_mb_emit_ldloc_addr (mb, error_var);
+ mono_mb_emit_icall (mb, mono_icall_end);
+ }
+
if (check_exceptions)
emit_thread_interrupt_checkpoint (mb);
mono_mb_emit_byte (mb, CEE_RET);
}
#else
MonoMethodSignature *sig, *csig;
- int i, *tmp_locals;
+ MonoExceptionClause *clauses, *clause_finally, *clause_catch;
+ int i, *tmp_locals, ex_local, e_local, attach_cookie_local, attach_dummy_local;
+ int leave_try_pos, leave_catch_pos, ex_m1_pos;
gboolean closed = FALSE;
- int coop_gc_var, coop_gc_dummy_local;
sig = m->sig;
csig = m->csig;
mono_mb_add_local (mb, sig->ret);
}
- if (mono_threads_is_coop_enabled ()) {
- /* local 4, the local to be used when calling the reset_blocking funcs */
- /* tons of code hardcode 3 to be the return var */
- coop_gc_var = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
- /* local 5, the local used to get a stack address for suspend funcs */
- coop_gc_dummy_local = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
- }
+ if (MONO_TYPE_ISSTRUCT (sig->ret))
+ m->vtaddr_var = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
- mono_mb_emit_icon (mb, 0);
- mono_mb_emit_stloc (mb, 2);
+ ex_local = mono_mb_add_local (mb, &mono_defaults.uint32_class->byval_arg);
+ e_local = mono_mb_add_local (mb, &mono_defaults.exception_class->byval_arg);
+
+ attach_cookie_local = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
+ attach_dummy_local = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
/*
- * Might need to attach the thread to the JIT or change the
- * domain for the callback.
+ * guint32 ex = -1;
+ * try {
+ * // does (STARTING|RUNNING|BLOCKING) -> RUNNING + set/switch domain
+ * mono_threads_attach_coop ();
+ *
+ * <interrupt check>
+ *
+ * ret = method (...);
+ * } catch (Exception e) {
+ * ex = mono_gchandle_new (e, false);
+ * } finally {
+ * // does RUNNING -> (RUNNING|BLOCKING) + unset/switch domain
+ * mono_threads_detach_coop ();
+ *
+ * if (ex != -1)
+ * mono_marshal_ftnptr_eh_callback (ex);
+ * }
+ *
+ * return ret;
*/
- mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
- mono_mb_emit_byte (mb, CEE_MONO_JIT_ATTACH);
- if (mono_threads_is_coop_enabled ()) {
- /* XXX can we merge reset_blocking_start with JIT_ATTACH above and save one call? */
- mono_mb_emit_ldloc_addr (mb, coop_gc_dummy_local);
- mono_mb_emit_icall (mb, mono_threads_reset_blocking_start);
- mono_mb_emit_stloc (mb, coop_gc_var);
+ clauses = g_new0 (MonoExceptionClause, 2);
+
+ clause_catch = &clauses [0];
+ clause_catch->flags = MONO_EXCEPTION_CLAUSE_NONE;
+ clause_catch->data.catch_class = mono_defaults.exception_class;
+
+ clause_finally = &clauses [1];
+ clause_finally->flags = MONO_EXCEPTION_CLAUSE_FINALLY;
+
+ mono_mb_emit_icon (mb, 0);
+ mono_mb_emit_stloc (mb, 2);
+
+ mono_mb_emit_icon (mb, -1);
+ mono_mb_emit_byte (mb, CEE_CONV_U4);
+ mono_mb_emit_stloc (mb, ex_local);
+
+ /* try { */
+ clause_catch->try_offset = clause_finally->try_offset = mono_mb_get_label (mb);
+
+ if (!mono_threads_is_coop_enabled ()) {
+ mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
+ mono_mb_emit_byte (mb, CEE_MONO_JIT_ATTACH);
+ } else {
+ /* mono_threads_attach_coop (); */
+ mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
+ mono_mb_emit_byte (mb, CEE_MONO_LDDOMAIN);
+ mono_mb_emit_ldloc_addr (mb, attach_dummy_local);
+ mono_mb_emit_icall (mb, mono_threads_attach_coop);
+ mono_mb_emit_stloc (mb, attach_cookie_local);
}
+ /* <interrupt check> */
+ emit_thread_interrupt_checkpoint (mb);
+
/* we first do all conversions */
tmp_locals = (int *)alloca (sizeof (int) * sig->param_count);
for (i = 0; i < sig->param_count; i ++) {
}
}
- emit_thread_interrupt_checkpoint (mb);
-
if (sig->hasthis) {
if (target_handle) {
mono_mb_emit_icon (mb, (gint32)target_handle);
mono_mb_emit_ldarg (mb, i);
}
+ /* ret = method (...) */
mono_mb_emit_managed_call (mb, method, NULL);
+ if (MONO_TYPE_ISSTRUCT (sig->ret)) {
+ MonoClass *klass = mono_class_from_mono_type (sig->ret);
+ mono_class_init (klass);
+ if (!(mono_class_is_explicit_layout (klass) || klass->blittable)) {
+ /* This is used by emit_marshal_vtype (), but it needs to go right before the call */
+ mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
+ mono_mb_emit_byte (mb, CEE_MONO_VTADDR);
+ mono_mb_emit_stloc (mb, m->vtaddr_var);
+ }
+ }
+
if (mspecs [0] && mspecs [0]->native == MONO_NATIVE_CUSTOM) {
emit_marshal (m, 0, sig->ret, mspecs [0], 0, NULL, MARSHAL_ACTION_MANAGED_CONV_RESULT);
} else if (!sig->ret->byref) {
}
}
- if (mono_threads_is_coop_enabled ()) {
- /* XXX merge reset_blocking_end with detach */
- mono_mb_emit_ldloc (mb, coop_gc_var);
- mono_mb_emit_ldloc_addr (mb, coop_gc_dummy_local);
- mono_mb_emit_icall (mb, mono_threads_reset_blocking_end);
+ leave_try_pos = mono_mb_emit_branch (mb, CEE_LEAVE);
+
+ /* } [endtry] */
+
+ /* catch (Exception e) { */
+ clause_catch->try_len = mono_mb_get_label (mb) - clause_catch->try_offset;
+ clause_catch->handler_offset = mono_mb_get_label (mb);
+
+ mono_mb_emit_stloc (mb, e_local);
+
+ /* ex = mono_gchandle_new (e, false); */
+ mono_mb_emit_ldloc (mb, e_local);
+ mono_mb_emit_icon (mb, 0);
+ mono_mb_emit_icall (mb, mono_gchandle_new);
+ mono_mb_emit_stloc (mb, ex_local);
+
+ leave_catch_pos = mono_mb_emit_branch (mb, CEE_LEAVE);
+
+ /* } [endcatch] */
+ clause_catch->handler_len = mono_mb_get_pos (mb) - clause_catch->handler_offset;
+
+ /* finally { */
+ clause_finally->try_len = mono_mb_get_label (mb) - clause_finally->try_offset;
+ clause_finally->handler_offset = mono_mb_get_label (mb);
+
+ if (!mono_threads_is_coop_enabled ()) {
+ mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
+ mono_mb_emit_byte (mb, CEE_MONO_JIT_DETACH);
+ } else {
+ /* mono_threads_detach_coop (); */
+ mono_mb_emit_ldloc (mb, attach_cookie_local);
+ mono_mb_emit_ldloc_addr (mb, attach_dummy_local);
+ mono_mb_emit_icall (mb, mono_threads_detach_coop);
}
- mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
- mono_mb_emit_byte (mb, CEE_MONO_JIT_DETACH);
+ /* if (ex != -1) */
+ mono_mb_emit_ldloc (mb, ex_local);
+ mono_mb_emit_icon (mb, -1);
+ mono_mb_emit_byte (mb, CEE_CONV_U4);
+ ex_m1_pos = mono_mb_emit_branch (mb, CEE_BEQ);
+
+ /* mono_marshal_ftnptr_eh_callback (ex) */
+ mono_mb_emit_ldloc (mb, ex_local);
+ mono_mb_emit_icall (mb, mono_marshal_ftnptr_eh_callback);
+ /* [ex == -1] */
+ mono_mb_patch_branch (mb, ex_m1_pos);
+
+ mono_mb_emit_byte (mb, CEE_ENDFINALLY);
+
+ /* } [endfinally] */
+ clause_finally->handler_len = mono_mb_get_pos (mb) - clause_finally->handler_offset;
+
+ mono_mb_patch_branch (mb, leave_try_pos);
+ mono_mb_patch_branch (mb, leave_catch_pos);
+
+ /* return ret; */
if (m->retobj_var) {
mono_mb_emit_ldloc (mb, m->retobj_var);
mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
mono_mb_emit_byte (mb, CEE_RET);
}
+ mono_mb_set_clauses (mb, 2, clauses);
+
if (closed)
g_free (sig);
#endif
MonoMethod *
mono_marshal_get_managed_wrapper (MonoMethod *method, MonoClass *delegate_klass, uint32_t target_handle)
{
- static MonoClass *UnmanagedFunctionPointerAttribute;
+ MonoError error;
MonoMethodSignature *sig, *csig, *invoke_sig;
MonoMethodBuilder *mb;
MonoMethod *res, *invoke;
EmitMarshalContext m;
g_assert (method != NULL);
- g_assert (!mono_method_signature (method)->pinvoke);
+ g_assert (!(method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL));
/*
* FIXME: Should cache the method+delegate type pair, since the same method
mono_marshal_set_callconv_from_modopt (invoke, csig);
- /* Handle the UnmanagedFunctionPointerAttribute */
- if (!UnmanagedFunctionPointerAttribute)
- UnmanagedFunctionPointerAttribute = mono_class_from_name (mono_defaults.corlib, "System.Runtime.InteropServices", "UnmanagedFunctionPointerAttribute");
-
/* The attribute is only available in Net 2.0 */
- if (UnmanagedFunctionPointerAttribute) {
+ if (mono_class_try_get_unmanaged_function_pointer_attribute_class ()) {
MonoCustomAttrInfo *cinfo;
MonoCustomAttrEntry *attr;
* contents of the attribute without constructing it, as that might not be
* possible when running in cross-compiling mode.
*/
- cinfo = mono_custom_attrs_from_class (delegate_klass);
+ cinfo = mono_custom_attrs_from_class_checked (delegate_klass, &error);
+ mono_error_assert_ok (&error);
attr = NULL;
if (cinfo) {
for (i = 0; i < cinfo->num_attrs; ++i) {
MonoClass *ctor_class = cinfo->attrs [i].ctor->klass;
- if (mono_class_has_parent (ctor_class, UnmanagedFunctionPointerAttribute)) {
+ if (mono_class_has_parent (ctor_class, mono_class_try_get_unmanaged_function_pointer_attribute_class ())) {
attr = &cinfo->attrs [i];
break;
}
gpointer
mono_marshal_get_vtfixup_ftnptr (MonoImage *image, guint32 token, guint16 type)
{
+ MonoError error;
MonoMethod *method;
MonoMethodSignature *sig;
MonoMethodBuilder *mb;
g_assert (token);
- method = mono_get_method (image, token, NULL);
+ method = mono_get_method_checked (image, token, NULL, NULL, &error);
+ if (!method)
+ g_error ("Could not load vtfixup token 0x%x due to %s", token, mono_error_get_message (&error));
g_assert (method);
if (type & (VTFIXUP_TYPE_FROM_UNMANAGED | VTFIXUP_TYPE_FROM_UNMANAGED_RETAIN_APPDOMAIN)) {
mono_metadata_free_marshal_spec (mspecs [i]);
g_free (mspecs);
- return mono_compile_method (method);
+ gpointer compiled_ptr = mono_compile_method_checked (method, &error);
+ mono_error_assert_ok (&error);
+ return compiled_ptr;
}
sig = mono_method_signature (method);
method = mono_mb_create (mb, sig, param_count, NULL);
mono_mb_free (mb);
- return mono_compile_method (method);
+ gpointer compiled_ptr = mono_compile_method_checked (method, &error);
+ mono_error_assert_ok (&error);
+ return compiled_ptr;
}
#ifndef DISABLE_JIT
/*
* This does the equivalent of mono_object_castclass_with_cache.
- * The wrapper info for the wrapper is a WrapperInfo structure.
*/
MonoMethod *
mono_marshal_get_castclass_with_cache (void)
return cached;
}
+/* this is an icall */
static MonoObject *
mono_marshal_isinst_with_cache (MonoObject *obj, MonoClass *klass, uintptr_t *cache)
{
- MonoObject *isinst = mono_object_isinst (obj, klass);
+ MonoError error;
+ MonoObject *isinst = mono_object_isinst_checked (obj, klass, &error);
+ if (mono_error_set_pending_exception (&error))
+ return NULL;
#ifndef DISABLE_REMOTING
if (obj->vtable->klass == mono_defaults.transparent_proxy_class)
/*
* This does the equivalent of mono_object_isinst_with_cache.
- * The wrapper info for the wrapper is a WrapperInfo structure.
*/
MonoMethod *
mono_marshal_get_isinst_with_cache (void)
// return obj
mono_mb_patch_branch (mb, positive_cache_hit_pos);
- mono_mb_emit_ldarg (mb, 0);
+ mono_mb_emit_ldarg (mb, obj_arg_position);
mono_mb_emit_byte (mb, CEE_RET);
#endif
* an instance of the given type, icluding the case where the object is a proxy.
* The generated function has the following signature:
* MonoObject* __castclass_wrapper_ (MonoObject *obj)
- * The wrapper info for the wrapper is a WrapperInfo structure.
*/
MonoMethod *
mono_marshal_get_castclass (MonoClass *klass)
* @klass:
*
* generates IL code for StructureToPtr (object structure, IntPtr ptr, bool fDeleteOld)
- * The wrapper info for the wrapper is a WrapperInfo structure.
*/
MonoMethod *
mono_marshal_get_struct_to_ptr (MonoClass *klass)
res = mono_mb_create (mb, mono_signature_no_pinvoke (stoptr), 0, info);
mono_mb_free (mb);
- klass->marshal_info->str_to_ptr = res;
+ mono_marshal_lock ();
+ if (!klass->marshal_info->str_to_ptr)
+ klass->marshal_info->str_to_ptr = res;
+ else
+ res = klass->marshal_info->str_to_ptr;
+ mono_marshal_unlock ();
return res;
}
* @klass:
*
* generates IL code for PtrToStructure (IntPtr src, object structure)
- * The wrapper info for the wrapper is a WrapperInfo structure.
*/
MonoMethod *
mono_marshal_get_ptr_to_struct (MonoClass *klass)
res = mono_mb_create (mb, ptostr, 0, info);
mono_mb_free (mb);
- klass->marshal_info->ptr_to_str = res;
+ mono_marshal_lock ();
+ if (!klass->marshal_info->ptr_to_str)
+ klass->marshal_info->ptr_to_str = res;
+ else
+ res = klass->marshal_info->ptr_to_str;
+ mono_marshal_unlock ();
return res;
}
* This is used to avoid infinite recursion since it is hard to determine where to
* replace a method with its synchronized wrapper, and where not.
* The runtime should execute METHOD instead of the wrapper.
- * The wrapper info for the wrapper is a WrapperInfo structure.
*/
MonoMethod *
mono_marshal_get_synchronized_inner_wrapper (MonoMethod *method)
method = ((MonoMethodInflated*)method)->declaring;
container = mono_method_get_generic_container (method);
if (!container)
- container = method->klass->generic_container;
+ container = mono_class_try_get_generic_container (method->klass); //FIXME is this a case of a try?
g_assert (container);
}
method = ((MonoMethodInflated*)method)->declaring;
container = mono_method_get_generic_container (method);
if (!container)
- container = method->klass->generic_container;
+ container = mono_class_try_get_generic_container (method->klass); //FIXME is this a case of a try?
g_assert (container);
}
#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);
if (!enter_method) {
MonoMethodDesc *desc;
- desc = mono_method_desc_new ("Monitor:enter_with_atomic_var(object,bool&)", FALSE);
+ desc = mono_method_desc_new ("Monitor:Enter(object,bool&)", FALSE);
enter_method = mono_method_desc_search_in_class (desc, mono_defaults.monitor_class);
g_assert (enter_method);
mono_method_desc_free (desc);
return FALSE;
element_class = klass->element_class;
- return (element_class->flags & TYPE_ATTRIBUTE_SEALED) || element_class->valuetype;
+ return mono_class_is_sealed (element_class) || element_class->valuetype;
}
static int
/*Arrays are sealed but are covariant on their element type, We can't use any of the fast paths.*/
if (mono_class_is_marshalbyref (element_class) || element_class->rank || mono_class_has_variant_generic_params (element_class))
return STELEMREF_COMPLEX;
- if (element_class->flags & TYPE_ATTRIBUTE_SEALED)
+ if (mono_class_is_sealed (element_class))
return STELEMREF_SEALED_CLASS;
return STELEMREF_CLASS;
}
#endif
/*
- * The wrapper info for the wrapper is a WrapperInfo structure.
- *
* TODO:
* - Separate simple interfaces from variant interfaces or mbr types. This way we can avoid the icall for them.
* - Emit a (new) mono bytecode that produces OP_COND_EXC_NE_UN to raise ArrayTypeMismatch
MonoMethod *res;
char *name;
const char *param_names [16];
- guint32 b1, b2, b3;
+ guint32 b1, b2, b3, b4;
int aklass, vklass, vtable, uiid;
int array_slot_addr;
WrapperInfo *info;
/*if (mono_object_isinst (value, aklass)) */
mono_mb_emit_ldarg (mb, 2);
mono_mb_emit_ldloc (mb, aklass);
- mono_mb_emit_icall (mb, mono_object_isinst);
+ mono_mb_emit_icall (mb, mono_object_isinst_icall);
b2 = mono_mb_emit_branch (mb, CEE_BRFALSE);
/* do_store: */
/*if (mono_object_isinst (value, aklass)) */
mono_mb_emit_ldarg (mb, 2);
mono_mb_emit_ldloc (mb, aklass);
- mono_mb_emit_icall (mb, mono_object_isinst);
+ mono_mb_emit_icall (mb, mono_object_isinst_icall);
b2 = mono_mb_emit_branch (mb, CEE_BRFALSE);
/* if (vklass->idepth < aklass->idepth) goto failue */
mono_mb_emit_ldflda (mb, MONO_STRUCT_OFFSET (MonoClass, idepth));
mono_mb_emit_byte (mb, CEE_LDIND_U2);
- b2 = mono_mb_emit_branch (mb, CEE_BLT_UN);
+ b3 = mono_mb_emit_branch (mb, CEE_BLT_UN);
/* if (vklass->supertypes [aklass->idepth - 1] != aklass) goto failure */
mono_mb_emit_ldloc (mb, vklass);
mono_mb_emit_byte (mb, CEE_LDIND_I);
mono_mb_emit_ldloc (mb, aklass);
- b3 = mono_mb_emit_branch (mb, CEE_BNE_UN);
+ b4 = mono_mb_emit_branch (mb, CEE_BNE_UN);
/* do_store: */
mono_mb_patch_branch (mb, b1);
/* do_exception: */
mono_mb_patch_branch (mb, b2);
mono_mb_patch_branch (mb, b3);
+ mono_mb_patch_branch (mb, b4);
mono_mb_emit_exception (mb, "ArrayTypeMismatchException", NULL);
break;
return res;
}
-/*
- * The wrapper info for the wrapper is a WrapperInfo structure.
- */
MonoMethod*
mono_marshal_get_stelemref (void)
{
mono_mb_emit_ldarg (mb, 2);
mono_mb_emit_ldloc (mb, aklass);
- mono_mb_emit_icall (mb, mono_object_isinst);
+ mono_mb_emit_icall (mb, mono_object_isinst_icall);
b4 = mono_mb_emit_branch (mb, CEE_BRTRUE);
mono_mb_patch_addr (mb, b4, copy_pos - (b4 + 4));
* mono_marshal_get_gsharedvt_in_wrapper:
*
* This wrapper handles calls from normal code to gsharedvt code.
- *
- * The wrapper info for the wrapper is a WrapperInfo structure.
*/
MonoMethod*
mono_marshal_get_gsharedvt_in_wrapper (void)
* mono_marshal_get_gsharedvt_out_wrapper:
*
* This wrapper handles calls from gsharedvt code to normal code.
- *
- * The wrapper info for the wrapper is a WrapperInfo structure.
*/
MonoMethod*
mono_marshal_get_gsharedvt_out_wrapper (void)
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)
+mono_marshal_alloc (gulong size, MonoError *error)
{
gpointer res;
-#ifdef HOST_WIN32
- res = CoTaskMemAlloc (size);
-#else
- res = g_try_malloc ((gulong)size);
+ mono_error_init (error);
+
+ res = mono_marshal_alloc_co_task_mem (size);
if (!res)
- mono_gc_out_of_memory ((gulong)size);
-#endif
+ mono_error_set_out_of_memory (error, "Could not allocate %lu bytes", size);
+
return res;
}
-void
-mono_marshal_free (gpointer ptr)
+/* This is a JIT icall, it sets the pending exception and returns NULL on error. */
+static void*
+ves_icall_marshal_alloc (gulong size)
+{
+ MonoError error;
+ void *ret = mono_marshal_alloc (size, &error);
+ if (!mono_error_ok (&error)) {
+ mono_error_set_pending_exception (&error);
+ return NULL;
+ }
+
+ return ret;
+}
+
+#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 s ? mono_string_chars (s) : NULL;
}
+/* This is a JIT icall, it sets the pending exception and returns NULL on error. */
static void *
mono_marshal_string_to_utf16_copy (MonoString *s)
{
if (s == NULL) {
return NULL;
} else {
- gunichar2 *res = (gunichar2 *)mono_marshal_alloc ((mono_string_length (s) * 2) + 2);
+ MonoError error;
+ gunichar2 *res = (gunichar2 *)mono_marshal_alloc ((mono_string_length (s) * 2) + 2, &error);
+ if (!mono_error_ok (&error)) {
+ mono_error_set_pending_exception (&error);
+ return NULL;
+ }
memcpy (res, mono_string_chars (s), mono_string_length (s) * 2);
res [mono_string_length (s)] = 0;
return res;
MonoString *
ves_icall_System_Runtime_InteropServices_Marshal_PtrToStringAnsi_len (char *ptr, gint32 len)
{
- if (ptr == NULL) {
- mono_set_pending_exception (mono_get_exception_argument_null ("ptr"));
- return NULL;
- } else {
- return mono_string_new_len (mono_domain_get (), ptr, len);
- }
+ MonoError error;
+ MonoString *result = NULL;
+ mono_error_init (&error);
+ if (ptr == NULL)
+ mono_error_set_argument_null (&error, "ptr", "");
+ else
+ result = mono_string_new_len_checked (mono_domain_get (), ptr, len, &error);
+ mono_error_set_pending_exception (&error);
+ return result;
}
MonoString *
ves_icall_System_Runtime_InteropServices_Marshal_PtrToStringUni (guint16 *ptr)
{
+ MonoError error;
+ MonoString *res = NULL;
MonoDomain *domain = mono_domain_get ();
int len = 0;
guint16 *t = ptr;
while (*t++)
len++;
- return mono_string_new_utf16 (domain, ptr, len);
+ res = mono_string_new_utf16_checked (domain, ptr, len, &error);
+ if (!mono_error_ok (&error)) {
+ mono_error_set_pending_exception (&error);
+ return NULL;
+ }
+ return res;
}
MonoString *
ves_icall_System_Runtime_InteropServices_Marshal_PtrToStringUni_len (guint16 *ptr, gint32 len)
{
+ MonoError error;
+ MonoString *res = NULL;
MonoDomain *domain = mono_domain_get ();
+ mono_error_init (&error);
+
if (ptr == NULL) {
- mono_set_pending_exception (mono_get_exception_argument_null ("ptr"));
- return NULL;
+ res = NULL;
+ mono_error_set_argument_null (&error, "ptr", "");
} else {
- return mono_string_new_utf16 (domain, ptr, len);
+ res = mono_string_new_utf16_checked (domain, ptr, len, &error);
}
+
+ if (!mono_error_ok (&error))
+ mono_error_set_pending_exception (&error);
+ return res;
}
guint32
return 0;
}
- layout = (klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK);
+ layout = (mono_class_get_flags (klass) & TYPE_ATTRIBUTE_LAYOUT_MASK);
if (type->type == MONO_TYPE_PTR || type->type == MONO_TYPE_FNPTR) {
return sizeof (gpointer);
void
ves_icall_System_Runtime_InteropServices_Marshal_StructureToPtr (MonoObject *obj, gpointer dst, MonoBoolean delete_old)
{
+ MonoError error;
MonoMethod *method;
gpointer pa [3];
pa [1] = &dst;
pa [2] = &delete_old;
- mono_runtime_invoke (method, NULL, pa, NULL);
+ mono_runtime_invoke_checked (method, NULL, pa, &error);
+ if (!mono_error_ok (&error))
+ mono_error_set_pending_exception (&error);
}
static void
-ptr_to_structure (gpointer src, MonoObject *dst)
+ptr_to_structure (gpointer src, MonoObject *dst, MonoError *error)
{
MonoMethod *method;
gpointer pa [2];
+ mono_error_init (error);
+
method = mono_marshal_get_ptr_to_struct (dst->vtable->klass);
pa [0] = &src;
pa [1] = dst;
- mono_runtime_invoke (method, NULL, pa, NULL);
+ mono_runtime_invoke_checked (method, NULL, pa, error);
}
void
ves_icall_System_Runtime_InteropServices_Marshal_PtrToStructure (gpointer src, MonoObject *dst)
{
MonoType *t;
+ MonoError error;
MONO_CHECK_ARG_NULL (src,);
MONO_CHECK_ARG_NULL (dst,);
return;
}
- ptr_to_structure (src, dst);
+ ptr_to_structure (src, dst, &error);
+ if (!mono_error_ok (&error))
+ mono_error_set_pending_exception (&error);
}
MonoObject *
ves_icall_System_Runtime_InteropServices_Marshal_PtrToStructure_type (gpointer src, MonoReflectionType *type)
{
+ MonoError error;
MonoClass *klass;
MonoDomain *domain = mono_domain_get ();
MonoObject *res;
return NULL;
}
- res = mono_object_new (domain, klass);
+ res = mono_object_new_checked (domain, klass, &error);
+ if (!mono_error_ok (&error)) {
+ mono_error_set_pending_exception (&error);
+ return NULL;
+ }
- ptr_to_structure (src, res);
+ ptr_to_structure (src, res, &error);
+ if (!mono_error_ok (&error)) {
+ mono_error_set_pending_exception (&error);
+ return NULL;
+ }
return res;
}
int
ves_icall_System_Runtime_InteropServices_Marshal_OffsetOf (MonoReflectionType *type, MonoString *field_name)
{
+ MonoError error;
MonoMarshalType *info;
MonoClass *klass;
char *fname;
MONO_CHECK_ARG_NULL (type, 0);
MONO_CHECK_ARG_NULL (field_name, 0);
- fname = mono_string_to_utf8 (field_name);
+ fname = mono_string_to_utf8_checked (field_name, &error);
+ if (mono_error_set_pending_exception (&error))
+ return 0;
klass = mono_class_from_mono_type (type->type);
if (!mono_class_init (klass)) {
mono_set_pending_exception (mono_class_get_exception_for_failure (klass));
return info->fields [match_index].offset;
}
+#ifndef HOST_WIN32
gpointer
ves_icall_System_Runtime_InteropServices_Marshal_StringToHGlobalAnsi (MonoString *string)
{
-#ifdef HOST_WIN32
- char* tres, *ret;
- size_t len;
- tres = mono_string_to_utf8 (string);
- if (!tres)
- return tres;
-
- len = strlen (tres) + 1;
- ret = ves_icall_System_Runtime_InteropServices_Marshal_AllocHGlobal (len);
- memcpy (ret, tres, len);
- g_free (tres);
+ MonoError error;
+ char *ret = mono_string_to_utf8_checked (string, &error);
+ mono_error_set_pending_exception (&error);
return ret;
-
-#else
- return mono_string_to_utf8 (string);
-#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
- if (!res)
- mono_gc_out_of_memory (s);
+ 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)
{
size_t s = (size_t)size;
if (ptr == NULL) {
- mono_gc_out_of_memory (s);
+ mono_set_pending_exception (mono_domain_get ()->out_of_memory_ex);
return NULL;
}
-#ifdef HOST_WIN32
- res = GlobalReAlloc (ptr, s, GMEM_MOVEABLE);
-#else
- res = g_try_realloc (ptr, s);
-#endif
- if (!res)
- mono_gc_out_of_memory (s);
+ 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;
+}
- res = g_try_malloc ((gulong)size);
-#endif
- if (!res)
- mono_gc_out_of_memory ((gulong)size);
+void*
+ves_icall_System_Runtime_InteropServices_Marshal_AllocCoTaskMemSize (gulong size)
+{
+ void *res = mono_marshal_alloc_co_task_mem (size);
+
+ if (!res) {
+ mono_set_pending_exception (mono_domain_get ()->out_of_memory_ex);
+ return NULL;
+ }
return res;
}
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_gc_out_of_memory ((gulong)size);
+ if (!res) {
+ mono_set_pending_exception (mono_domain_get ()->out_of_memory_ex);
+ return NULL;
+ }
return res;
}
return mono_ftnptr_to_delegate (klass, ftn);
}
+gpointer
+ves_icall_System_Runtime_InteropServices_Marshal_GetFunctionPointerForDelegateInternal (MonoDelegate *delegate)
+{
+ return mono_delegate_to_ftnptr (delegate);
+}
+
/**
* mono_marshal_is_loading_type_info:
*
count++;
}
- layout = klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK;
+ layout = mono_class_get_flags (klass) & TYPE_ATTRIBUTE_LAYOUT_MASK;
/* The mempool is protected by the loader lock */
info = (MonoMarshalType *)mono_image_alloc0 (klass->image, MONO_SIZEOF_MARSHAL_TYPE + sizeof (MonoMarshalField) * count);
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);
/*
/*We do double-checking locking on marshal_info */
mono_memory_barrier ();
klass->marshal_info = info;
+ ++class_marshal_info_count;
}
mono_marshal_unlock ();
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:
return 0;
}
+/* This is a JIT icall, it sets the pending exception and return NULL on error */
gpointer
mono_marshal_asany (MonoObject *o, MonoMarshalNative string_encoding, int param_attrs)
{
+ MonoError error;
MonoType *t;
MonoClass *klass;
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 ();
klass = t->data.klass;
- if ((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_AUTO_LAYOUT)
+ if (mono_class_is_auto_layout (klass))
break;
- if (klass->valuetype && (((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) ||
- klass->blittable || klass->enumtype))
+ if (klass->valuetype && (mono_class_is_explicit_layout (klass) || klass->blittable || klass->enumtype))
return mono_object_unbox (o);
- res = mono_marshal_alloc (mono_class_native_size (klass, NULL));
+ res = mono_marshal_alloc (mono_class_native_size (klass, NULL), &error);
+ if (!mono_error_ok (&error)) {
+ mono_error_set_pending_exception (&error);
+ return NULL;
+ }
if (!((param_attrs & PARAM_ATTRIBUTE_OUT) && !(param_attrs & PARAM_ATTRIBUTE_IN))) {
method = mono_marshal_get_struct_to_ptr (o->vtable->klass);
pa [1] = &res;
pa [2] = &delete_old;
- mono_runtime_invoke (method, NULL, pa, NULL);
+ mono_runtime_invoke_checked (method, NULL, pa, &error);
+ if (!mono_error_ok (&error)) {
+ mono_error_set_pending_exception (&error);
+ return NULL;
+ }
}
return res;
default:
break;
}
- mono_raise_exception (mono_get_exception_argument ("", "No PInvoke conversion exists for value passed to Object-typed parameter."));
+ mono_set_pending_exception (mono_get_exception_argument ("", "No PInvoke conversion exists for value passed to Object-typed parameter."));
return NULL;
}
+/* This is a JIT icall, it sets the pending exception */
void
mono_marshal_free_asany (MonoObject *o, gpointer ptr, MonoMarshalNative string_encoding, int param_attrs)
{
+ MonoError error;
MonoType *t;
MonoClass *klass;
switch (string_encoding) {
case MONO_NATIVE_LPWSTR:
case MONO_NATIVE_LPSTR:
+ case MONO_NATIVE_UTF8STR:
mono_marshal_free (ptr);
break;
default:
case MONO_TYPE_VALUETYPE: {
klass = t->data.klass;
- if (klass->valuetype && (((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) ||
- klass->blittable || klass->enumtype))
+ if (klass->valuetype && (mono_class_is_explicit_layout (klass) || klass->blittable || klass->enumtype))
break;
if (param_attrs & PARAM_ATTRIBUTE_OUT) {
pa [0] = &ptr;
pa [1] = o;
- mono_runtime_invoke (method, NULL, pa, NULL);
+ mono_runtime_invoke_checked (method, NULL, pa, &error);
+ if (!mono_error_ok (&error)) {
+ mono_error_set_pending_exception (&error);
+ return;
+ }
}
if (!((param_attrs & PARAM_ATTRIBUTE_OUT) && !(param_attrs & PARAM_ATTRIBUTE_IN))) {
GHashTable *cache;
MonoMethod *res;
int i, param_count, sig_size, pos_leave;
- int coop_gc_var, coop_gc_dummy_local;
g_assert (method);
+ // FIXME: we need to store the exception into a MonoHandle
+ g_assert (!mono_threads_is_coop_enabled ());
+
klass = method->klass;
image = method->klass->image;
if (!MONO_TYPE_IS_VOID (sig->ret))
mono_mb_add_local (mb, sig->ret);
- if (mono_threads_is_coop_enabled ()) {
- /* local 4, the local to be used when calling the reset_blocking funcs */
- /* tons of code hardcode 3 to be the return var */
- coop_gc_var = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
- /* local 5, the local used to get a stack address for suspend funcs */
- coop_gc_dummy_local = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
- }
-
/* clear exception arg */
mono_mb_emit_ldarg (mb, param_count - 1);
mono_mb_emit_byte (mb, CEE_LDNULL);
mono_mb_emit_byte (mb, CEE_STIND_REF);
- if (mono_threads_is_coop_enabled ()) {
- /* FIXME this is technically wrong as the callback itself must be executed in gc unsafe context. */
- mono_mb_emit_ldloc_addr (mb, coop_gc_dummy_local);
- mono_mb_emit_icall (mb, mono_threads_reset_blocking_start);
- mono_mb_emit_stloc (mb, coop_gc_var);
- }
-
/* try */
clause = (MonoExceptionClause *)mono_image_alloc0 (image, sizeof (MonoExceptionClause));
clause->try_offset = mono_mb_get_label (mb);
mono_mb_emit_op (mb, CEE_BOX, mono_class_from_mono_type (sig->ret));
}
- if (mono_threads_is_coop_enabled ()) {
- /* XXX merge reset_blocking_end with detach */
- mono_mb_emit_ldloc (mb, coop_gc_var);
- mono_mb_emit_ldloc_addr (mb, coop_gc_dummy_local);
- mono_mb_emit_icall (mb, mono_threads_reset_blocking_end);
- }
-
mono_mb_emit_byte (mb, CEE_RET);
#endif
if (marshal_mutex_initialized)
mono_marshal_unlock ();
}
+
+static void
+mono_marshal_ftnptr_eh_callback (guint32 gchandle)
+{
+ g_assert (ftnptr_eh_callback);
+ ftnptr_eh_callback (gchandle);
+}
+
+static void
+ftnptr_eh_callback_default (guint32 gchandle)
+{
+ MonoException *exc;
+ gpointer stackdata;
+
+ mono_threads_enter_gc_unsafe_region_unbalanced (&stackdata);
+
+ exc = (MonoException*) mono_gchandle_get_target (gchandle);
+
+ mono_gchandle_free (gchandle);
+
+ mono_raise_exception (exc);
+}
+
+/*
+ * mono_install_ftnptr_eh_callback:
+ *
+ * Install a callback that should be called when there is a managed exception
+ * in a native-to-managed wrapper. This is mainly used by iOS to convert a
+ * managed exception to a native exception, to properly unwind the native
+ * stack; this native exception will then be converted back to a managed
+ * exception in their managed-to-native wrapper.
+ */
+void
+mono_install_ftnptr_eh_callback (MonoFtnPtrEHCallback callback)
+{
+ ftnptr_eh_callback = callback;
+}
+
+static MonoThreadInfo*
+mono_icall_start (HandleStackMark *stackmark, MonoError *error)
+{
+ MonoThreadInfo *info = mono_thread_info_current ();
+
+ mono_stack_mark_init (info, stackmark);
+ mono_error_init (error);
+ return info;
+}
+
+static void
+mono_icall_end (MonoThreadInfo *info, HandleStackMark *stackmark, MonoError *error)
+{
+ mono_stack_mark_pop (info, stackmark);
+ mono_error_set_pending_exception (error);
+}