/mono/metadata/icall.c
C | 8423 lines | 6671 code | 1380 blank | 372 comment | 1506 complexity | c832cf30aabe58006a1dd66b6c1be0bc MD5 | raw file
Possible License(s): Unlicense, Apache-2.0, LGPL-2.0, MPL-2.0-no-copyleft-exception, CC-BY-SA-3.0, GPL-2.0
Large files files are truncated, but you can click here to view the full file
- /*
- * icall.c:
- *
- * Authors:
- * Dietmar Maurer (dietmar@ximian.com)
- * Paolo Molaro (lupus@ximian.com)
- * Patrik Torstensson (patrik.torstensson@labs2.com)
- *
- * Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
- * Copyright 2004-2009 Novell, Inc (http://www.novell.com)
- * Copyright 2011-2012 Xamarin Inc (http://www.xamarin.com).
- */
- #include <config.h>
- #include <glib.h>
- #include <stdarg.h>
- #include <string.h>
- #include <ctype.h>
- #ifdef HAVE_ALLOCA_H
- #include <alloca.h>
- #endif
- #ifdef HAVE_SYS_TIME_H
- #include <sys/time.h>
- #endif
- #ifdef HAVE_UNISTD_H
- #include <unistd.h>
- #endif
- #if defined (HOST_WIN32)
- #include <stdlib.h>
- #endif
- #if defined (HAVE_WCHAR_H)
- #include <wchar.h>
- #endif
- #include "mono/utils/mono-membar.h"
- #include <mono/metadata/object.h>
- #include <mono/metadata/threads.h>
- #include <mono/metadata/threads-types.h>
- #include <mono/metadata/threadpool.h>
- #include <mono/metadata/monitor.h>
- #include <mono/metadata/reflection.h>
- #include <mono/metadata/assembly.h>
- #include <mono/metadata/tabledefs.h>
- #include <mono/metadata/exception.h>
- #include <mono/metadata/file-io.h>
- #include <mono/metadata/console-io.h>
- #include <mono/metadata/socket-io.h>
- #include <mono/metadata/mono-endian.h>
- #include <mono/metadata/tokentype.h>
- #include <mono/metadata/domain-internals.h>
- #include <mono/metadata/metadata-internals.h>
- #include <mono/metadata/class-internals.h>
- #include <mono/metadata/marshal.h>
- #include <mono/metadata/gc-internal.h>
- #include <mono/metadata/mono-gc.h>
- #include <mono/metadata/rand.h>
- #include <mono/metadata/sysmath.h>
- #include <mono/metadata/string-icalls.h>
- #include <mono/metadata/debug-helpers.h>
- #include <mono/metadata/process.h>
- #include <mono/metadata/environment.h>
- #include <mono/metadata/profiler-private.h>
- #include <mono/metadata/locales.h>
- #include <mono/metadata/filewatcher.h>
- #include <mono/metadata/char-conversions.h>
- #include <mono/metadata/security.h>
- #include <mono/metadata/mono-config.h>
- #include <mono/metadata/cil-coff.h>
- #include <mono/metadata/number-formatter.h>
- #include <mono/metadata/security-manager.h>
- #include <mono/metadata/security-core-clr.h>
- #include <mono/metadata/mono-perfcounters.h>
- #include <mono/metadata/mono-debug.h>
- #include <mono/metadata/mono-ptr-array.h>
- #include <mono/metadata/verify-internals.h>
- #include <mono/io-layer/io-layer.h>
- #include <mono/utils/strtod.h>
- #include <mono/utils/monobitset.h>
- #include <mono/utils/mono-time.h>
- #include <mono/utils/mono-proclib.h>
- #include <mono/utils/mono-string.h>
- #include <mono/utils/mono-error-internals.h>
- #include <mono/utils/mono-mmap.h>
- #include <mono/utils/mono-io-portability.h>
- #include <mono/utils/mono-digest.h>
- #if defined (HOST_WIN32)
- #include <windows.h>
- #include <shlobj.h>
- #endif
- #include "decimal.h"
- extern MonoString* ves_icall_System_Environment_GetOSVersionString (void) MONO_INTERNAL;
- ICALL_EXPORT MonoReflectionAssembly* ves_icall_System_Reflection_Assembly_GetCallingAssembly (void);
- static MonoArray*
- type_array_from_modifiers (MonoImage *image, MonoType *type, int optional);
- static inline MonoBoolean
- is_generic_parameter (MonoType *type)
- {
- return !type->byref && (type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR);
- }
- static void
- mono_class_init_or_throw (MonoClass *klass)
- {
- if (!mono_class_init (klass))
- mono_raise_exception (mono_class_get_exception_for_failure (klass));
- }
- /*
- * We expect a pointer to a char, not a string
- */
- ICALL_EXPORT gboolean
- mono_double_ParseImpl (char *ptr, double *result)
- {
- gchar *endptr = NULL;
- *result = 0.0;
- MONO_ARCH_SAVE_REGS;
- #ifdef __arm__
- if (*ptr)
- *result = strtod (ptr, &endptr);
- #else
- if (*ptr){
- /* mono_strtod () is not thread-safe */
- EnterCriticalSection (&mono_strtod_mutex);
- *result = mono_strtod (ptr, &endptr);
- LeaveCriticalSection (&mono_strtod_mutex);
- }
- #endif
- if (!*ptr || (endptr && *endptr))
- return FALSE;
-
- return TRUE;
- }
- ICALL_EXPORT MonoObject *
- ves_icall_System_Array_GetValueImpl (MonoObject *this, guint32 pos)
- {
- MonoClass *ac;
- MonoArray *ao;
- gint32 esize;
- gpointer *ea;
- MONO_ARCH_SAVE_REGS;
- ao = (MonoArray *)this;
- ac = (MonoClass *)ao->obj.vtable->klass;
- esize = mono_array_element_size (ac);
- ea = (gpointer*)((char*)ao->vector + (pos * esize));
- if (ac->element_class->valuetype)
- return mono_value_box (this->vtable->domain, ac->element_class, ea);
- else
- return *ea;
- }
- ICALL_EXPORT MonoObject *
- ves_icall_System_Array_GetValue (MonoObject *this, MonoObject *idxs)
- {
- MonoClass *ac, *ic;
- MonoArray *ao, *io;
- gint32 i, pos, *ind;
- MONO_ARCH_SAVE_REGS;
- MONO_CHECK_ARG_NULL (idxs);
- io = (MonoArray *)idxs;
- ic = (MonoClass *)io->obj.vtable->klass;
-
- ao = (MonoArray *)this;
- ac = (MonoClass *)ao->obj.vtable->klass;
- g_assert (ic->rank == 1);
- if (io->bounds != NULL || io->max_length != ac->rank)
- mono_raise_exception (mono_get_exception_argument (NULL, NULL));
- ind = (gint32 *)io->vector;
- if (ao->bounds == NULL) {
- if (*ind < 0 || *ind >= ao->max_length)
- mono_raise_exception (mono_get_exception_index_out_of_range ());
- return ves_icall_System_Array_GetValueImpl (this, *ind);
- }
-
- for (i = 0; i < ac->rank; i++)
- if ((ind [i] < ao->bounds [i].lower_bound) ||
- (ind [i] >= (mono_array_lower_bound_t)ao->bounds [i].length + ao->bounds [i].lower_bound))
- mono_raise_exception (mono_get_exception_index_out_of_range ());
- pos = ind [0] - ao->bounds [0].lower_bound;
- for (i = 1; i < ac->rank; i++)
- pos = pos*ao->bounds [i].length + ind [i] -
- ao->bounds [i].lower_bound;
- return ves_icall_System_Array_GetValueImpl (this, pos);
- }
- ICALL_EXPORT void
- ves_icall_System_Array_SetValueImpl (MonoArray *this, MonoObject *value, guint32 pos)
- {
- MonoClass *ac, *vc, *ec;
- gint32 esize, vsize;
- gpointer *ea, *va;
- int et, vt;
- guint64 u64 = 0;
- gint64 i64 = 0;
- gdouble r64 = 0;
- MONO_ARCH_SAVE_REGS;
- if (value)
- vc = value->vtable->klass;
- else
- vc = NULL;
- ac = this->obj.vtable->klass;
- ec = ac->element_class;
- esize = mono_array_element_size (ac);
- ea = (gpointer*)((char*)this->vector + (pos * esize));
- va = (gpointer*)((char*)value + sizeof (MonoObject));
- if (mono_class_is_nullable (ec)) {
- mono_nullable_init ((guint8*)ea, value, ec);
- return;
- }
- if (!value) {
- mono_gc_bzero (ea, esize);
- return;
- }
- #define NO_WIDENING_CONVERSION G_STMT_START{\
- mono_raise_exception (mono_get_exception_argument ( \
- "value", "not a widening conversion")); \
- }G_STMT_END
- #define CHECK_WIDENING_CONVERSION(extra) G_STMT_START{\
- if (esize < vsize + (extra)) \
- mono_raise_exception (mono_get_exception_argument ( \
- "value", "not a widening conversion")); \
- }G_STMT_END
- #define INVALID_CAST G_STMT_START{ \
- mono_get_runtime_callbacks ()->set_cast_details (vc, ec); \
- mono_raise_exception (mono_get_exception_invalid_cast ()); \
- }G_STMT_END
- /* Check element (destination) type. */
- switch (ec->byval_arg.type) {
- case MONO_TYPE_STRING:
- switch (vc->byval_arg.type) {
- case MONO_TYPE_STRING:
- break;
- default:
- INVALID_CAST;
- }
- break;
- case MONO_TYPE_BOOLEAN:
- switch (vc->byval_arg.type) {
- case MONO_TYPE_BOOLEAN:
- break;
- case MONO_TYPE_CHAR:
- case MONO_TYPE_U1:
- case MONO_TYPE_U2:
- case MONO_TYPE_U4:
- case MONO_TYPE_U8:
- case MONO_TYPE_I1:
- case MONO_TYPE_I2:
- case MONO_TYPE_I4:
- case MONO_TYPE_I8:
- case MONO_TYPE_R4:
- case MONO_TYPE_R8:
- NO_WIDENING_CONVERSION;
- default:
- INVALID_CAST;
- }
- break;
- }
- if (!ec->valuetype) {
- if (!mono_object_isinst (value, ec))
- INVALID_CAST;
- mono_gc_wbarrier_set_arrayref (this, ea, (MonoObject*)value);
- return;
- }
- if (mono_object_isinst (value, ec)) {
- if (ec->has_references)
- mono_value_copy (ea, (char*)value + sizeof (MonoObject), ec);
- else
- mono_gc_memmove (ea, (char *)value + sizeof (MonoObject), esize);
- return;
- }
- if (!vc->valuetype)
- INVALID_CAST;
- vsize = mono_class_instance_size (vc) - sizeof (MonoObject);
- et = ec->byval_arg.type;
- if (et == MONO_TYPE_VALUETYPE && ec->byval_arg.data.klass->enumtype)
- et = mono_class_enum_basetype (ec->byval_arg.data.klass)->type;
- vt = vc->byval_arg.type;
- if (vt == MONO_TYPE_VALUETYPE && vc->byval_arg.data.klass->enumtype)
- vt = mono_class_enum_basetype (vc->byval_arg.data.klass)->type;
- #define ASSIGN_UNSIGNED(etype) G_STMT_START{\
- switch (vt) { \
- case MONO_TYPE_U1: \
- case MONO_TYPE_U2: \
- case MONO_TYPE_U4: \
- case MONO_TYPE_U8: \
- case MONO_TYPE_CHAR: \
- CHECK_WIDENING_CONVERSION(0); \
- *(etype *) ea = (etype) u64; \
- return; \
- /* You can't assign a signed value to an unsigned array. */ \
- case MONO_TYPE_I1: \
- case MONO_TYPE_I2: \
- case MONO_TYPE_I4: \
- case MONO_TYPE_I8: \
- /* You can't assign a floating point number to an integer array. */ \
- case MONO_TYPE_R4: \
- case MONO_TYPE_R8: \
- NO_WIDENING_CONVERSION; \
- } \
- }G_STMT_END
- #define ASSIGN_SIGNED(etype) G_STMT_START{\
- switch (vt) { \
- case MONO_TYPE_I1: \
- case MONO_TYPE_I2: \
- case MONO_TYPE_I4: \
- case MONO_TYPE_I8: \
- CHECK_WIDENING_CONVERSION(0); \
- *(etype *) ea = (etype) i64; \
- return; \
- /* You can assign an unsigned value to a signed array if the array's */ \
- /* element size is larger than the value size. */ \
- case MONO_TYPE_U1: \
- case MONO_TYPE_U2: \
- case MONO_TYPE_U4: \
- case MONO_TYPE_U8: \
- case MONO_TYPE_CHAR: \
- CHECK_WIDENING_CONVERSION(1); \
- *(etype *) ea = (etype) u64; \
- return; \
- /* You can't assign a floating point number to an integer array. */ \
- case MONO_TYPE_R4: \
- case MONO_TYPE_R8: \
- NO_WIDENING_CONVERSION; \
- } \
- }G_STMT_END
- #define ASSIGN_REAL(etype) G_STMT_START{\
- switch (vt) { \
- case MONO_TYPE_R4: \
- case MONO_TYPE_R8: \
- CHECK_WIDENING_CONVERSION(0); \
- *(etype *) ea = (etype) r64; \
- return; \
- /* All integer values fit into a floating point array, so we don't */ \
- /* need to CHECK_WIDENING_CONVERSION here. */ \
- case MONO_TYPE_I1: \
- case MONO_TYPE_I2: \
- case MONO_TYPE_I4: \
- case MONO_TYPE_I8: \
- *(etype *) ea = (etype) i64; \
- return; \
- case MONO_TYPE_U1: \
- case MONO_TYPE_U2: \
- case MONO_TYPE_U4: \
- case MONO_TYPE_U8: \
- case MONO_TYPE_CHAR: \
- *(etype *) ea = (etype) u64; \
- return; \
- } \
- }G_STMT_END
- switch (vt) {
- case MONO_TYPE_U1:
- u64 = *(guint8 *) va;
- break;
- case MONO_TYPE_U2:
- u64 = *(guint16 *) va;
- break;
- case MONO_TYPE_U4:
- u64 = *(guint32 *) va;
- break;
- case MONO_TYPE_U8:
- u64 = *(guint64 *) va;
- break;
- case MONO_TYPE_I1:
- i64 = *(gint8 *) va;
- break;
- case MONO_TYPE_I2:
- i64 = *(gint16 *) va;
- break;
- case MONO_TYPE_I4:
- i64 = *(gint32 *) va;
- break;
- case MONO_TYPE_I8:
- i64 = *(gint64 *) va;
- break;
- case MONO_TYPE_R4:
- r64 = *(gfloat *) va;
- break;
- case MONO_TYPE_R8:
- r64 = *(gdouble *) va;
- break;
- case MONO_TYPE_CHAR:
- u64 = *(guint16 *) va;
- break;
- case MONO_TYPE_BOOLEAN:
- /* Boolean is only compatible with itself. */
- switch (et) {
- case MONO_TYPE_CHAR:
- case MONO_TYPE_U1:
- case MONO_TYPE_U2:
- case MONO_TYPE_U4:
- case MONO_TYPE_U8:
- case MONO_TYPE_I1:
- case MONO_TYPE_I2:
- case MONO_TYPE_I4:
- case MONO_TYPE_I8:
- case MONO_TYPE_R4:
- case MONO_TYPE_R8:
- NO_WIDENING_CONVERSION;
- default:
- INVALID_CAST;
- }
- break;
- }
- /* If we can't do a direct copy, let's try a widening conversion. */
- switch (et) {
- case MONO_TYPE_CHAR:
- ASSIGN_UNSIGNED (guint16);
- case MONO_TYPE_U1:
- ASSIGN_UNSIGNED (guint8);
- case MONO_TYPE_U2:
- ASSIGN_UNSIGNED (guint16);
- case MONO_TYPE_U4:
- ASSIGN_UNSIGNED (guint32);
- case MONO_TYPE_U8:
- ASSIGN_UNSIGNED (guint64);
- case MONO_TYPE_I1:
- ASSIGN_SIGNED (gint8);
- case MONO_TYPE_I2:
- ASSIGN_SIGNED (gint16);
- case MONO_TYPE_I4:
- ASSIGN_SIGNED (gint32);
- case MONO_TYPE_I8:
- ASSIGN_SIGNED (gint64);
- case MONO_TYPE_R4:
- ASSIGN_REAL (gfloat);
- case MONO_TYPE_R8:
- ASSIGN_REAL (gdouble);
- }
- INVALID_CAST;
- /* Not reached, INVALID_CAST does not return. Just to avoid a compiler warning ... */
- return;
- #undef INVALID_CAST
- #undef NO_WIDENING_CONVERSION
- #undef CHECK_WIDENING_CONVERSION
- #undef ASSIGN_UNSIGNED
- #undef ASSIGN_SIGNED
- #undef ASSIGN_REAL
- }
- ICALL_EXPORT void
- ves_icall_System_Array_SetValue (MonoArray *this, MonoObject *value,
- MonoArray *idxs)
- {
- MonoClass *ac, *ic;
- gint32 i, pos, *ind;
- MONO_ARCH_SAVE_REGS;
- MONO_CHECK_ARG_NULL (idxs);
- ic = idxs->obj.vtable->klass;
- ac = this->obj.vtable->klass;
- g_assert (ic->rank == 1);
- if (idxs->bounds != NULL || idxs->max_length != ac->rank)
- mono_raise_exception (mono_get_exception_argument (NULL, NULL));
- ind = (gint32 *)idxs->vector;
- if (this->bounds == NULL) {
- if (*ind < 0 || *ind >= this->max_length)
- mono_raise_exception (mono_get_exception_index_out_of_range ());
- ves_icall_System_Array_SetValueImpl (this, value, *ind);
- return;
- }
-
- for (i = 0; i < ac->rank; i++)
- if ((ind [i] < this->bounds [i].lower_bound) ||
- (ind [i] >= (mono_array_lower_bound_t)this->bounds [i].length + this->bounds [i].lower_bound))
- mono_raise_exception (mono_get_exception_index_out_of_range ());
- pos = ind [0] - this->bounds [0].lower_bound;
- for (i = 1; i < ac->rank; i++)
- pos = pos * this->bounds [i].length + ind [i] -
- this->bounds [i].lower_bound;
- ves_icall_System_Array_SetValueImpl (this, value, pos);
- }
- ICALL_EXPORT MonoArray *
- ves_icall_System_Array_CreateInstanceImpl (MonoReflectionType *type, MonoArray *lengths, MonoArray *bounds)
- {
- MonoClass *aklass, *klass;
- MonoArray *array;
- uintptr_t *sizes, i;
- gboolean bounded = FALSE;
- MONO_ARCH_SAVE_REGS;
- MONO_CHECK_ARG_NULL (type);
- MONO_CHECK_ARG_NULL (lengths);
- MONO_CHECK_ARG (lengths, mono_array_length (lengths) > 0);
- if (bounds)
- MONO_CHECK_ARG (bounds, mono_array_length (lengths) == mono_array_length (bounds));
- for (i = 0; i < mono_array_length (lengths); i++)
- if (mono_array_get (lengths, gint32, i) < 0)
- mono_raise_exception (mono_get_exception_argument_out_of_range (NULL));
- klass = mono_class_from_mono_type (type->type);
- mono_class_init_or_throw (klass);
- if (bounds && (mono_array_length (bounds) == 1) && (mono_array_get (bounds, gint32, 0) != 0))
- /* vectors are not the same as one dimensional arrays with no-zero bounds */
- bounded = TRUE;
- else
- bounded = FALSE;
- aklass = mono_bounded_array_class_get (klass, mono_array_length (lengths), bounded);
- sizes = alloca (aklass->rank * sizeof(intptr_t) * 2);
- for (i = 0; i < aklass->rank; ++i) {
- sizes [i] = mono_array_get (lengths, guint32, i);
- if (bounds)
- sizes [i + aklass->rank] = mono_array_get (bounds, gint32, i);
- else
- sizes [i + aklass->rank] = 0;
- }
- array = mono_array_new_full (mono_object_domain (type), aklass, sizes, (intptr_t*)sizes + aklass->rank);
- return array;
- }
- ICALL_EXPORT MonoArray *
- ves_icall_System_Array_CreateInstanceImpl64 (MonoReflectionType *type, MonoArray *lengths, MonoArray *bounds)
- {
- MonoClass *aklass, *klass;
- MonoArray *array;
- uintptr_t *sizes, i;
- gboolean bounded = FALSE;
- MONO_ARCH_SAVE_REGS;
- MONO_CHECK_ARG_NULL (type);
- MONO_CHECK_ARG_NULL (lengths);
- MONO_CHECK_ARG (lengths, mono_array_length (lengths) > 0);
- if (bounds)
- MONO_CHECK_ARG (bounds, mono_array_length (lengths) == mono_array_length (bounds));
- for (i = 0; i < mono_array_length (lengths); i++)
- if ((mono_array_get (lengths, gint64, i) < 0) ||
- (mono_array_get (lengths, gint64, i) > MONO_ARRAY_MAX_INDEX))
- mono_raise_exception (mono_get_exception_argument_out_of_range (NULL));
- klass = mono_class_from_mono_type (type->type);
- mono_class_init_or_throw (klass);
- if (bounds && (mono_array_length (bounds) == 1) && (mono_array_get (bounds, gint64, 0) != 0))
- /* vectors are not the same as one dimensional arrays with no-zero bounds */
- bounded = TRUE;
- else
- bounded = FALSE;
- aklass = mono_bounded_array_class_get (klass, mono_array_length (lengths), bounded);
- sizes = alloca (aklass->rank * sizeof(intptr_t) * 2);
- for (i = 0; i < aklass->rank; ++i) {
- sizes [i] = mono_array_get (lengths, guint64, i);
- if (bounds)
- sizes [i + aklass->rank] = (mono_array_size_t) mono_array_get (bounds, guint64, i);
- else
- sizes [i + aklass->rank] = 0;
- }
- array = mono_array_new_full (mono_object_domain (type), aklass, sizes, (intptr_t*)sizes + aklass->rank);
- return array;
- }
- ICALL_EXPORT gint32
- ves_icall_System_Array_GetRank (MonoObject *this)
- {
- MONO_ARCH_SAVE_REGS;
- return this->vtable->klass->rank;
- }
- ICALL_EXPORT gint32
- ves_icall_System_Array_GetLength (MonoArray *this, gint32 dimension)
- {
- gint32 rank = ((MonoObject *)this)->vtable->klass->rank;
- uintptr_t length;
- MONO_ARCH_SAVE_REGS;
- if ((dimension < 0) || (dimension >= rank))
- mono_raise_exception (mono_get_exception_index_out_of_range ());
-
- if (this->bounds == NULL)
- length = this->max_length;
- else
- length = this->bounds [dimension].length;
- #ifdef MONO_BIG_ARRAYS
- if (length > G_MAXINT32)
- mono_raise_exception (mono_get_exception_overflow ());
- #endif
- return length;
- }
- ICALL_EXPORT gint64
- ves_icall_System_Array_GetLongLength (MonoArray *this, gint32 dimension)
- {
- gint32 rank = ((MonoObject *)this)->vtable->klass->rank;
- MONO_ARCH_SAVE_REGS;
- if ((dimension < 0) || (dimension >= rank))
- mono_raise_exception (mono_get_exception_index_out_of_range ());
-
- if (this->bounds == NULL)
- return this->max_length;
-
- return this->bounds [dimension].length;
- }
- ICALL_EXPORT gint32
- ves_icall_System_Array_GetLowerBound (MonoArray *this, gint32 dimension)
- {
- gint32 rank = ((MonoObject *)this)->vtable->klass->rank;
- MONO_ARCH_SAVE_REGS;
- if ((dimension < 0) || (dimension >= rank))
- mono_raise_exception (mono_get_exception_index_out_of_range ());
-
- if (this->bounds == NULL)
- return 0;
-
- return this->bounds [dimension].lower_bound;
- }
- ICALL_EXPORT void
- ves_icall_System_Array_ClearInternal (MonoArray *arr, int idx, int length)
- {
- int sz = mono_array_element_size (mono_object_class (arr));
- mono_gc_bzero (mono_array_addr_with_size (arr, sz, idx), length * sz);
- }
- ICALL_EXPORT gboolean
- ves_icall_System_Array_FastCopy (MonoArray *source, int source_idx, MonoArray* dest, int dest_idx, int length)
- {
- int element_size;
- void * dest_addr;
- void * source_addr;
- MonoClass *src_class;
- MonoClass *dest_class;
- MONO_ARCH_SAVE_REGS;
- if (source->obj.vtable->klass->rank != dest->obj.vtable->klass->rank)
- return FALSE;
- if (source->bounds || dest->bounds)
- return FALSE;
- /* there's no integer overflow since mono_array_length returns an unsigned integer */
- if ((dest_idx + length > mono_array_length (dest)) ||
- (source_idx + length > mono_array_length (source)))
- return FALSE;
- src_class = source->obj.vtable->klass->element_class;
- dest_class = dest->obj.vtable->klass->element_class;
- /*
- * Handle common cases.
- */
- /* Case1: object[] -> valuetype[] (ArrayList::ToArray) */
- if (src_class == mono_defaults.object_class && dest_class->valuetype) {
- // FIXME: This is racy
- return FALSE;
- /*
- int i;
- int has_refs = dest_class->has_references;
- for (i = source_idx; i < source_idx + length; ++i) {
- MonoObject *elem = mono_array_get (source, MonoObject*, i);
- if (elem && !mono_object_isinst (elem, dest_class))
- return FALSE;
- }
- element_size = mono_array_element_size (dest->obj.vtable->klass);
- memset (mono_array_addr_with_size (dest, element_size, dest_idx), 0, element_size * length);
- for (i = 0; i < length; ++i) {
- MonoObject *elem = mono_array_get (source, MonoObject*, source_idx + i);
- void *addr = mono_array_addr_with_size (dest, element_size, dest_idx + i);
- if (!elem)
- continue;
- if (has_refs)
- mono_value_copy (addr, (char *)elem + sizeof (MonoObject), dest_class);
- else
- memcpy (addr, (char *)elem + sizeof (MonoObject), element_size);
- }
- return TRUE;
- */
- }
- /* Check if we're copying a char[] <==> (u)short[] */
- if (src_class != dest_class) {
- if (dest_class->valuetype || dest_class->enumtype || src_class->valuetype || src_class->enumtype)
- return FALSE;
- if (mono_class_is_subclass_of (src_class, dest_class, FALSE))
- ;
- /* Case2: object[] -> reftype[] (ArrayList::ToArray) */
- else if (mono_class_is_subclass_of (dest_class, src_class, FALSE)) {
- // FIXME: This is racy
- return FALSE;
- /*
- int i;
- for (i = source_idx; i < source_idx + length; ++i) {
- MonoObject *elem = mono_array_get (source, MonoObject*, i);
- if (elem && !mono_object_isinst (elem, dest_class))
- return FALSE;
- }
- */
- } else
- return FALSE;
- }
- if (dest_class->valuetype) {
- element_size = mono_array_element_size (source->obj.vtable->klass);
- source_addr = mono_array_addr_with_size (source, element_size, source_idx);
- if (dest_class->has_references) {
- mono_value_copy_array (dest, dest_idx, source_addr, length);
- } else {
- dest_addr = mono_array_addr_with_size (dest, element_size, dest_idx);
- mono_gc_memmove (dest_addr, source_addr, element_size * length);
- }
- } else {
- mono_array_memcpy_refs (dest, dest_idx, source, source_idx, length);
- }
- return TRUE;
- }
- ICALL_EXPORT void
- ves_icall_System_Array_GetGenericValueImpl (MonoObject *this, guint32 pos, gpointer value)
- {
- MonoClass *ac;
- MonoArray *ao;
- gint32 esize;
- gpointer *ea;
- MONO_ARCH_SAVE_REGS;
- ao = (MonoArray *)this;
- ac = (MonoClass *)ao->obj.vtable->klass;
- esize = mono_array_element_size (ac);
- ea = (gpointer*)((char*)ao->vector + (pos * esize));
- mono_gc_memmove (value, ea, esize);
- }
- ICALL_EXPORT void
- ves_icall_System_Array_SetGenericValueImpl (MonoObject *this, guint32 pos, gpointer value)
- {
- MonoClass *ac, *ec;
- MonoArray *ao;
- gint32 esize;
- gpointer *ea;
- MONO_ARCH_SAVE_REGS;
- ao = (MonoArray *)this;
- ac = (MonoClass *)ao->obj.vtable->klass;
- ec = ac->element_class;
- esize = mono_array_element_size (ac);
- ea = (gpointer*)((char*)ao->vector + (pos * esize));
- if (MONO_TYPE_IS_REFERENCE (&ec->byval_arg)) {
- g_assert (esize == sizeof (gpointer));
- mono_gc_wbarrier_generic_store (ea, *(gpointer*)value);
- } else {
- g_assert (ec->inited);
- g_assert (esize == mono_class_value_size (ec, NULL));
- if (ec->has_references)
- mono_gc_wbarrier_value_copy (ea, value, 1, ec);
- else
- mono_gc_memmove (ea, value, esize);
- }
- }
- ICALL_EXPORT void
- ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_InitializeArray (MonoArray *array, MonoClassField *field_handle)
- {
- MonoClass *klass = array->obj.vtable->klass;
- guint32 size = mono_array_element_size (klass);
- MonoType *type = mono_type_get_underlying_type (&klass->element_class->byval_arg);
- int align;
- const char *field_data;
- if (MONO_TYPE_IS_REFERENCE (type) || type->type == MONO_TYPE_VALUETYPE) {
- MonoException *exc = mono_get_exception_argument("array",
- "Cannot initialize array of non-primitive type.");
- mono_raise_exception (exc);
- }
- if (!(field_handle->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA)) {
- MonoException *exc = mono_get_exception_argument("field_handle",
- "Field doesn't have an RVA");
- mono_raise_exception (exc);
- }
- size *= array->max_length;
- field_data = mono_field_get_data (field_handle);
- if (size > mono_type_size (field_handle->type, &align)) {
- MonoException *exc = mono_get_exception_argument("field_handle",
- "Field not large enough to fill array");
- mono_raise_exception (exc);
- }
- #if G_BYTE_ORDER != G_LITTLE_ENDIAN
- #define SWAP(n) {\
- guint ## n *data = (guint ## n *) mono_array_addr (array, char, 0); \
- guint ## n *src = (guint ## n *) field_data; \
- guint ## n *end = (guint ## n *)((char*)src + size); \
- \
- for (; src < end; data++, src++) { \
- *data = read ## n (src); \
- } \
- }
- /* printf ("Initialize array with elements of %s type\n", klass->element_class->name); */
- switch (type->type) {
- case MONO_TYPE_CHAR:
- case MONO_TYPE_I2:
- case MONO_TYPE_U2:
- SWAP (16);
- break;
- case MONO_TYPE_I4:
- case MONO_TYPE_U4:
- case MONO_TYPE_R4:
- SWAP (32);
- break;
- case MONO_TYPE_I8:
- case MONO_TYPE_U8:
- case MONO_TYPE_R8:
- SWAP (64);
- break;
- default:
- memcpy (mono_array_addr (array, char, 0), field_data, size);
- break;
- }
- #else
- memcpy (mono_array_addr (array, char, 0), field_data, size);
- #ifdef ARM_FPU_FPA
- if (klass->element_class->byval_arg.type == MONO_TYPE_R8) {
- gint i;
- double tmp;
- double *data = (double*)mono_array_addr (array, double, 0);
- for (i = 0; i < size; i++, data++) {
- readr8 (data, &tmp);
- *data = tmp;
- }
- }
- #endif
- #endif
- }
- ICALL_EXPORT gint
- ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_GetOffsetToStringData (void)
- {
- MONO_ARCH_SAVE_REGS;
- return offsetof (MonoString, chars);
- }
- ICALL_EXPORT MonoObject *
- ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_GetObjectValue (MonoObject *obj)
- {
- MONO_ARCH_SAVE_REGS;
- if ((obj == NULL) || (! (obj->vtable->klass->valuetype)))
- return obj;
- else
- return mono_object_clone (obj);
- }
- ICALL_EXPORT void
- ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_RunClassConstructor (MonoType *handle)
- {
- MonoClass *klass;
- MonoVTable *vtable;
- MONO_CHECK_ARG_NULL (handle);
- klass = mono_class_from_mono_type (handle);
- MONO_CHECK_ARG (handle, klass);
- vtable = mono_class_vtable_full (mono_domain_get (), klass, TRUE);
- /* This will call the type constructor */
- mono_runtime_class_init (vtable);
- }
- ICALL_EXPORT void
- ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_RunModuleConstructor (MonoImage *image)
- {
- MONO_ARCH_SAVE_REGS;
- mono_image_check_for_module_cctor (image);
- if (image->has_module_cctor) {
- MonoClass *module_klass = mono_class_get (image, MONO_TOKEN_TYPE_DEF | 1);
- /*It's fine to raise the exception here*/
- mono_runtime_class_init (mono_class_vtable_full (mono_domain_get (), module_klass, TRUE));
- }
- }
- ICALL_EXPORT MonoBoolean
- ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_SufficientExecutionStack (void)
- {
- guint8 *stack_addr;
- guint8 *current;
- size_t stack_size;
- /* later make this configurable and per-arch */
- int min_size = 4096 * 4 * sizeof (void*);
- mono_thread_get_stack_bounds (&stack_addr, &stack_size);
- /* if we have no info we are optimistic and assume there is enough room */
- if (!stack_addr)
- return TRUE;
- current = (guint8 *)&stack_addr;
- if (current > stack_addr) {
- if ((current - stack_addr) < min_size)
- return FALSE;
- } else {
- if (current - (stack_addr - stack_size) < min_size)
- return FALSE;
- }
- return TRUE;
- }
- ICALL_EXPORT MonoObject *
- ves_icall_System_Object_MemberwiseClone (MonoObject *this)
- {
- MONO_ARCH_SAVE_REGS;
- return mono_object_clone (this);
- }
- ICALL_EXPORT gint32
- ves_icall_System_ValueType_InternalGetHashCode (MonoObject *this, MonoArray **fields)
- {
- MonoClass *klass;
- MonoObject **values = NULL;
- MonoObject *o;
- int count = 0;
- gint32 result = 0;
- MonoClassField* field;
- gpointer iter;
- MONO_ARCH_SAVE_REGS;
- klass = mono_object_class (this);
- if (mono_class_num_fields (klass) == 0)
- return mono_object_hash (this);
- /*
- * Compute the starting value of the hashcode for fields of primitive
- * types, and return the remaining fields in an array to the managed side.
- * This way, we can avoid costly reflection operations in managed code.
- */
- iter = NULL;
- while ((field = mono_class_get_fields (klass, &iter))) {
- if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
- continue;
- if (mono_field_is_deleted (field))
- continue;
- /* FIXME: Add more types */
- switch (field->type->type) {
- case MONO_TYPE_I4:
- result ^= *(gint32*)((guint8*)this + field->offset);
- break;
- case MONO_TYPE_STRING: {
- MonoString *s;
- s = *(MonoString**)((guint8*)this + field->offset);
- if (s != NULL)
- result ^= mono_string_hash (s);
- break;
- }
- default:
- if (!values)
- values = g_newa (MonoObject*, mono_class_num_fields (klass));
- o = mono_field_get_value_object (mono_object_domain (this), field, this);
- values [count++] = o;
- }
- }
- if (values) {
- int i;
- mono_gc_wbarrier_generic_store (fields, (MonoObject*) mono_array_new (mono_domain_get (), mono_defaults.object_class, count));
- for (i = 0; i < count; ++i)
- mono_array_setref (*fields, i, values [i]);
- } else {
- *fields = NULL;
- }
- return result;
- }
- ICALL_EXPORT MonoBoolean
- ves_icall_System_ValueType_Equals (MonoObject *this, MonoObject *that, MonoArray **fields)
- {
- MonoClass *klass;
- MonoObject **values = NULL;
- MonoObject *o;
- MonoClassField* field;
- gpointer iter;
- int count = 0;
- MONO_ARCH_SAVE_REGS;
- MONO_CHECK_ARG_NULL (that);
- if (this->vtable != that->vtable)
- return FALSE;
- klass = mono_object_class (this);
- if (klass->enumtype && mono_class_enum_basetype (klass) && mono_class_enum_basetype (klass)->type == MONO_TYPE_I4)
- return (*(gint32*)((guint8*)this + sizeof (MonoObject)) == *(gint32*)((guint8*)that + sizeof (MonoObject)));
- /*
- * Do the comparison for fields of primitive type and return a result if
- * possible. Otherwise, return the remaining fields in an array to the
- * managed side. This way, we can avoid costly reflection operations in
- * managed code.
- */
- *fields = NULL;
- iter = NULL;
- while ((field = mono_class_get_fields (klass, &iter))) {
- if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
- continue;
- if (mono_field_is_deleted (field))
- continue;
- /* FIXME: Add more types */
- switch (field->type->type) {
- case MONO_TYPE_U1:
- case MONO_TYPE_I1:
- case MONO_TYPE_BOOLEAN:
- if (*((guint8*)this + field->offset) != *((guint8*)that + field->offset))
- return FALSE;
- break;
- case MONO_TYPE_U2:
- case MONO_TYPE_I2:
- case MONO_TYPE_CHAR:
- if (*(gint16*)((guint8*)this + field->offset) != *(gint16*)((guint8*)that + field->offset))
- return FALSE;
- break;
- case MONO_TYPE_U4:
- case MONO_TYPE_I4:
- if (*(gint32*)((guint8*)this + field->offset) != *(gint32*)((guint8*)that + field->offset))
- return FALSE;
- break;
- case MONO_TYPE_U8:
- case MONO_TYPE_I8:
- if (*(gint64*)((guint8*)this + field->offset) != *(gint64*)((guint8*)that + field->offset))
- return FALSE;
- break;
- case MONO_TYPE_R4:
- if (*(float*)((guint8*)this + field->offset) != *(float*)((guint8*)that + field->offset))
- return FALSE;
- break;
- case MONO_TYPE_R8:
- if (*(double*)((guint8*)this + field->offset) != *(double*)((guint8*)that + field->offset))
- return FALSE;
- break;
- case MONO_TYPE_STRING: {
- MonoString *s1, *s2;
- guint32 s1len, s2len;
- s1 = *(MonoString**)((guint8*)this + field->offset);
- s2 = *(MonoString**)((guint8*)that + field->offset);
- if (s1 == s2)
- break;
- if ((s1 == NULL) || (s2 == NULL))
- return FALSE;
- s1len = mono_string_length (s1);
- s2len = mono_string_length (s2);
- if (s1len != s2len)
- return FALSE;
- if (memcmp (mono_string_chars (s1), mono_string_chars (s2), s1len * sizeof (gunichar2)) != 0)
- return FALSE;
- break;
- }
- default:
- if (!values)
- values = g_newa (MonoObject*, mono_class_num_fields (klass) * 2);
- o = mono_field_get_value_object (mono_object_domain (this), field, this);
- values [count++] = o;
- o = mono_field_get_value_object (mono_object_domain (this), field, that);
- values [count++] = o;
- }
- if (klass->enumtype)
- /* enums only have one non-static field */
- break;
- }
- if (values) {
- int i;
- mono_gc_wbarrier_generic_store (fields, (MonoObject*) mono_array_new (mono_domain_get (), mono_defaults.object_class, count));
- for (i = 0; i < count; ++i)
- mono_array_setref (*fields, i, values [i]);
- return FALSE;
- } else {
- return TRUE;
- }
- }
- ICALL_EXPORT MonoReflectionType *
- ves_icall_System_Object_GetType (MonoObject *obj)
- {
- MONO_ARCH_SAVE_REGS;
- #ifndef DISABLE_REMOTING
- if (obj->vtable->klass == mono_defaults.transparent_proxy_class)
- return mono_type_get_object (mono_object_domain (obj), &((MonoTransparentProxy*)obj)->remote_class->proxy_class->byval_arg);
- else
- #endif
- return mono_type_get_object (mono_object_domain (obj), &obj->vtable->klass->byval_arg);
- }
- ICALL_EXPORT void
- mono_type_type_from_obj (MonoReflectionType *mtype, MonoObject *obj)
- {
- MONO_ARCH_SAVE_REGS;
- mtype->type = &obj->vtable->klass->byval_arg;
- g_assert (mtype->type->type);
- }
- ICALL_EXPORT gint32
- ves_icall_ModuleBuilder_getToken (MonoReflectionModuleBuilder *mb, MonoObject *obj, gboolean create_open_instance)
- {
- MONO_ARCH_SAVE_REGS;
-
- MONO_CHECK_ARG_NULL (obj);
-
- return mono_image_create_token (mb->dynamic_image, obj, create_open_instance, TRUE);
- }
- ICALL_EXPORT gint32
- ves_icall_ModuleBuilder_getMethodToken (MonoReflectionModuleBuilder *mb,
- MonoReflectionMethod *method,
- MonoArray *opt_param_types)
- {
- MONO_ARCH_SAVE_REGS;
- MONO_CHECK_ARG_NULL (method);
-
- return mono_image_create_method_token (
- mb->dynamic_image, (MonoObject *) method, opt_param_types);
- }
- ICALL_EXPORT void
- ves_icall_ModuleBuilder_WriteToFile (MonoReflectionModuleBuilder *mb, HANDLE file)
- {
- MONO_ARCH_SAVE_REGS;
- mono_image_create_pefile (mb, file);
- }
- ICALL_EXPORT void
- ves_icall_ModuleBuilder_build_metadata (MonoReflectionModuleBuilder *mb)
- {
- MONO_ARCH_SAVE_REGS;
- mono_image_build_metadata (mb);
- }
- ICALL_EXPORT void
- ves_icall_ModuleBuilder_RegisterToken (MonoReflectionModuleBuilder *mb, MonoObject *obj, guint32 token)
- {
- MONO_ARCH_SAVE_REGS;
- mono_image_register_token (mb->dynamic_image, token, obj);
- }
- static gboolean
- get_caller (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
- {
- MonoMethod **dest = data;
- /* skip unmanaged frames */
- if (!managed)
- return FALSE;
- if (m == *dest) {
- *dest = NULL;
- return FALSE;
- }
- if (!(*dest)) {
- *dest = m;
- return TRUE;
- }
- return FALSE;
- }
- static gboolean
- get_executing (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
- {
- MonoMethod **dest = data;
- /* skip unmanaged frames */
- if (!managed)
- return FALSE;
- if (!(*dest)) {
- if (!strcmp (m->klass->name_space, "System.Reflection"))
- return FALSE;
- *dest = m;
- return TRUE;
- }
- return FALSE;
- }
- static gboolean
- get_caller_no_reflection (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
- {
- MonoMethod **dest = data;
- /* skip unmanaged frames */
- if (!managed)
- return FALSE;
- if (m->wrapper_type != MONO_WRAPPER_NONE)
- return FALSE;
- if (m->klass->image == mono_defaults.corlib && !strcmp (m->klass->name_space, "System.Reflection"))
- return FALSE;
- if (m == *dest) {
- *dest = NULL;
- return FALSE;
- }
- if (!(*dest)) {
- *dest = m;
- return TRUE;
- }
- return FALSE;
- }
- static MonoReflectionType *
- type_from_name (const char *str, MonoBoolean ignoreCase)
- {
- MonoType *type = NULL;
- MonoAssembly *assembly = NULL;
- MonoTypeNameParse info;
- char *temp_str = g_strdup (str);
- gboolean type_resolve = FALSE;
- MONO_ARCH_SAVE_REGS;
- /* mono_reflection_parse_type() mangles the string */
- if (!mono_reflection_parse_type (temp_str, &info)) {
- mono_reflection_free_type_info (&info);
- g_free (temp_str);
- return NULL;
- }
- if (info.assembly.name) {
- assembly = mono_assembly_load (&info.assembly, NULL, NULL);
- } else {
- MonoMethod *m = mono_method_get_last_managed ();
- MonoMethod *dest = m;
- mono_stack_walk_no_il (get_caller_no_reflection, &dest);
- if (!dest)
- dest = m;
- /*
- * FIXME: mono_method_get_last_managed() sometimes returns NULL, thus
- * causing ves_icall_System_Reflection_Assembly_GetCallingAssembly()
- * to crash. This only seems to happen in some strange remoting
- * scenarios and I was unable to figure out what's happening there.
- * Dec 10, 2005 - Martin.
- */
- if (dest) {
- assembly = dest->klass->image->assembly;
- type_resolve = TRUE;
- } else {
- g_warning (G_STRLOC);
- }
- }
- if (assembly) {
- /* When loading from the current assembly, AppDomain.TypeResolve will not be called yet */
- type = mono_reflection_get_type (assembly->image, &info, ignoreCase, &type_resolve);
- }
- if (!info.assembly.name && !type) /* try mscorlib */
- type = mono_reflection_get_type (NULL, &info, ignoreCase, &type_resolve);
- if (assembly && !type && type_resolve) {
- type_resolve = FALSE; /* This will invoke TypeResolve if not done in the first 'if' */
- type = mono_reflection_get_type (assembly->image, &info, ignoreCase, &type_resolve);
- }
- mono_reflection_free_type_info (&info);
- g_free (temp_str);
- if (!type)
- return NULL;
- return mono_type_get_object (mono_domain_get (), type);
- }
- #ifdef UNUSED
- MonoReflectionType *
- mono_type_get (const char *str)
- {
- char *copy = g_strdup (str);
- MonoReflectionType *type = type_from_name (copy, FALSE);
- g_free (copy);
- return type;
- }
- #endif
- ICALL_EXPORT MonoReflectionType*
- ves_icall_type_from_name (MonoString *name,
- MonoBoolean throwOnError,
- MonoBoolean ignoreCase)
- {
- char *str = mono_string_to_utf8 (name);
- MonoReflectionType *type;
- type = type_from_name (str, ignoreCase);
- g_free (str);
- if (type == NULL){
- MonoException *e = NULL;
-
- if (throwOnError)
- e = mono_get_exception_type_load (name, NULL);
- mono_loader_clear_error ();
- if (e != NULL)
- mono_raise_exception (e);
- }
-
- return type;
- }
- ICALL_EXPORT MonoReflectionType*
- ves_icall_type_from_handle (MonoType *handle)
- {
- MonoDomain *domain = mono_domain_get ();
- MONO_ARCH_SAVE_REGS;
- return mono_type_get_object (domain, handle);
- }
- ICALL_EXPORT MonoBoolean
- ves_icall_System_Type_EqualsInternal (MonoReflectionType *type, MonoReflectionType *c)
- {
- MONO_ARCH_SAVE_REGS;
- if (c && type->type && c->type)
- return mono_metadata_type_equal (type->type, c->type);
- else
- return (type == c) ? TRUE : FALSE;
- }
- /* System.TypeCode */
- typedef enum {
- TYPECODE_EMPTY,
- TYPECODE_OBJECT,
- TYPECODE_DBNULL,
- TYPECODE_BOOLEAN,
- TYPECODE_CHAR,
- TYPECODE_SBYTE,
- TYPECODE_BYTE,
- TYPECODE_INT16,
- TYPECODE_UINT16,
- TYPECODE_INT32,
- TYPECODE_UINT32,
- TYPECODE_INT64,
- TYPECODE_UINT64,
- TYPECODE_SINGLE,
- TYPECODE_DOUBLE,
- TYPECODE_DECIMAL,
- TYPECODE_DATETIME,
- TYPECODE_STRING = 18
- } TypeCode;
- ICALL_EXPORT guint32
- ves_icall_type_GetTypeCodeInternal (MonoReflectionType *type)
- {
- int t = type->type->type;
- MONO_ARCH_SAVE_REGS;
- if (type->type->byref)
- return TYPECODE_OBJECT;
- handle_enum:
- switch (t) {
- case MONO_TYPE_VOID:
- return TYPECODE_OBJECT;
- case MONO_TYPE_BOOLEAN:
- return TYPECODE_BOOLEAN;
- case MONO_TYPE_U1:
- return TYPECODE_BYTE;
- case MONO_TYPE_I1:
- return TYPECODE_SBYTE;
- case MONO_TYPE_U2:
- return TYPECODE_UINT16;
- case MONO_TYPE_I2:
- return TYPECODE_INT16;
- case MONO_TYPE_CHAR:
- return TYPECODE_CHAR;
- case MONO_TYPE_PTR:
- case MONO_TYPE_U:
- case MONO_TYPE_I:
- return TYPECODE_OBJECT;
- case MONO_TYPE_U4:
- return TYPECODE_UINT32;
- case MONO_TYPE_I4:
- return TYPECODE_INT32;
- case MONO_TYPE_U8:
- return TYPECODE_UINT64;
- case MONO_TYPE_I8:
- return TYPECODE_INT64;
- case MONO_TYPE_R4:
- return TYPECODE_SINGLE;
- case MONO_TYPE_R8:
- return TYPECODE_DOUBLE;
- case MONO_TYPE_VALUETYPE: {
- MonoClass *klass = type->type->data.klass;
-
- if (klass->enumtype) {
- t = mono_class_enum_basetype (klass)->type;
- goto handle_enum;
- } else if (mono_is_corlib_image (klass->image)) {
- if (strcmp (klass->name_space, "System") == 0) {
- if (strcmp (klass->name, "Decimal") == 0)
- return TYPECODE_DECIMAL;
- else if (strcmp (klass->name, "DateTime") == 0)
- return TYPECODE_DATETIME;
- }
- }
- return TYPECODE_OBJECT;
- }
- case MONO_TYPE_STRING:
- return TYPECODE_STRING;
- case MONO_TYPE_SZARRAY:
- case MONO_TYPE_ARRAY:
- case MONO_TYPE_OBJECT:
- case MONO_TYPE_VAR:
- case MONO_TYPE_MVAR:
- case MONO_TYPE_TYPEDBYREF:
- return TYPECODE_OBJECT;
- case MONO_TYPE_CLASS:
- {
- MonoClass *klass = type->type->data.klass;
- if (klass->image == mono_defaults.corlib && strcmp (klass->name_space, "System") == 0) {
- if (strcmp (klass->name, "DBNull") == 0)
- return TYPECODE_DBNULL;
- }
- }
- return TYPECODE_OBJECT;
- case MONO_TYPE_GENERICINST:
- return TYPECODE_OBJECT;
- default:
- g_error ("type 0x%02x not handled in GetTypeCode()", t);
- }
- return 0;
- }
- ICALL_EXPORT guint32
- ves_icall_type_is_subtype_of (MonoReflectionType *type, MonoReflectionType *c, MonoBoolean check_interfaces)
- {
- MonoDomain *domain;
- MonoClass *klass;
- MonoClass *klassc;
- MONO_ARCH_SAVE_REGS;
- g_assert (type != NULL);
-
- domain = ((MonoObject *)type)->vtable->domain;
- if (!c) /* FIXME: dont know what do do here */
- return 0;
- klass = mono_class_from_mono_type (type->type);
- klassc = mono_class_from_mono_type (c->type);
- /* Interface check requires a more complex setup so we
- * only do for them. Otherwise we simply avoid mono_class_init.
- */
- if (check_interfaces) {
- mono_class_init_or_throw (klass);
- mono_class_init_or_throw (klassc);
- } else if (!klass->supertypes || !klassc->supertypes) {
- mono_loader_lock ();
- mono_class_setup_supertypes (klass);
- mono_class_setup_supertypes (klassc);
- mono_loader_unlock ();
- }
- if (type->type->byref)
- return klassc == mono_defaults.object_class;
- return mono_class_is_subclass_of (klass, klassc, check_interfaces);
- }
- static gboolean
- mono_type_is_primitive (MonoType *type)
- {
- return (type->type >= MONO_TYPE_BOOLEAN && type->type <= MONO_TYPE_R8) ||
- type-> type == MONO_TYPE_I || type->type == MONO_TYPE_U;
- }
- static MonoType*
- mono_type_get_underlying_type_ignore_byref (MonoType *type)
- {
- if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype)
- return mono_class_enum_basetype (type->data.klass);
- if (type->type == MONO_TYPE_GENERICINST && type->data.generic_class->container_class->enumtype)
- return mono_class_enum_basetype (type->data.generic_class->container_class);
- return type;
- }
- ICALL_EXPORT guint32
- ves_icall_type_is_assignable_from (MonoReflectionType *type, MonoReflectionType *c)
- {
- MonoDomain *domain;
- MonoClass *klass;
- MonoClass *klassc;
- MONO_ARCH_SAVE_REGS;
- g_assert (type != NULL);
-
- domain = ((MonoObject *)type)->vtable->domain;
- klass = mono_class_from_mono_type (type->type);
- klassc = mono_class_from_mono_type (c->type);
- mono_class_init_or_throw (klass);
- mono_class_init_or_throw (klassc);
- if (type->type->byref ^ c->type->byref)
- return FALSE;
- if (type->type->byref) {
- MonoType *t = mono_type_get_underlying_type_ignore_byref (type->type);
- MonoType *ot = mono_type_get_underlying_type_ignore_byref (c->type);
- klass = mono_class_from_mono_type (t);
- klassc = mono_class_from_mono_type (ot);
- if (mono_type_is_primitive (t)) {
- return mono_type_is_primitive (ot) && klass->instance_size == klassc->instance_size;
- } else if (t->type == MONO_TYPE_VAR || t->type == MONO_TYPE_MVAR) {
- return t->type == ot->type && t->data.generic_param->num == ot->data.generic_param->num;
- } else if (t->type == MONO_TYPE_PTR || t->type == MONO_TYPE_FNPTR) {
- return t->type == ot->type;
- } else {
- if (ot->type == MONO_TYPE_VAR || ot->type == MONO_TYPE_MVAR)
- return FALSE;
- if (klass->valuetype)
- return klass == klassc;
- return klass->valuetype == klassc->valuetype;
- }
- }
- return mono_class_is_assignable_from (klass, klassc);
- }
- ICALL_EXPORT guint32
- ves_icall_type_IsInstanceOfType (MonoReflectionType *type, MonoObject *obj)
- {
- MonoClass *klass = mono_class_from_mono_type (type->type);
- mono_class_init_or_throw (klass);
- return mono_object_isinst (obj, klass) != NULL;
- }
- ICALL_EXPORT guint32
- ves_icall_get_attributes (MonoReflectionType *type)
- {
- MonoClass *klass = mono_class_from_mono_type (type->type);
- return klass->flags;
- }
- ICALL_EXPORT MonoReflectionMarshalAsAttribute*
- ves_icall_System_Reflection_FieldInfo_get_marshal_info (MonoReflectionField *field)
- {
- MonoClass *klass = field->field->parent;
- MonoMarshalType *info;
- int i;
- if (klass->generic_container ||
- (klass->generic_class && klass->generic_class->context.class_inst->is_open))
- return NULL;
- info = mono_marshal_load_type_info (klass);
- for (i = 0; i < info->num_fields; ++i) {
- if (info->fields [i].field == field->field) {
- if (!info->fields [i].mspec)
- return NULL;
- else
- return mono_reflection_marshal_as_attribute_from_marshal_spec (field->object.vtable->domain, klass, info->fields [i].mspec);
- }
- }
- return NULL;
- }
- ICALL_EXPORT MonoReflectionField*
- ves_icall_System_Reflection_FieldInfo_internal_from_handle_type (MonoClassField *handle, MonoType *type)
- {
- gboolean found = FALSE;
- MonoClass *klass;
- MonoClass *k;
- g_assert (handle);
- if (!type) {
- klass = handle->parent;
- } else {
- klass = mono_class_from_mono_type (type);
- /* Check that the field belongs to the class */
- for (k = klass; k; k = k->parent) {
- if (k == handle->parent) {
- found = TRUE;
- break;
- }
- }
- if (!found)
- /* The managed code will throw the exception */
- return NULL;
- }
- return mono_field_get_object (mono_domain_get (), klass, handle);
- }
- ICALL_EXPORT MonoArray*
- ves_icall_System_Reflection_FieldInfo_GetTypeModifiers (MonoReflectionField *field, MonoBoolean optional)
- {
- MonoError error;
- MonoType *type = mono_field_get_type_checked (field->field, &error);
- if (!mono_error_ok (&error))
- mono_error_raise_exception (&error);
- return type_array_from_modifiers (field->field->parent->image, type, optional);
- }
- ICALL_EXPORT int
- vell_icall_get_method_attributes (MonoMethod *method)
- {
- return method->flags;
- }
- ICALL_EXPORT void
- ves_icall_get_method_info (MonoMethod *method, MonoMethodInfo *info)
- {
- MonoError error;
- MonoDomain *domain = mono_domain_get ();
- MonoMethodSignature* sig;
- MONO_ARCH_SAVE_REGS;
- sig = mono_method_signature_checked (method, &error);
- if (!mono_error_ok (&error))
- mono_error_raise_exception (&error);
- MONO_STRUCT_SETREF (info, parent, mono_type_get_object (domain, &method->klass->byval_arg));
- MONO_STRUCT_SETREF (info, ret, mono_type_get_object (domain, sig->ret));
- info->attrs = method->flags;
- info->implattrs = method->iflags;
- if (sig->call_convention == MONO_CALL_DEFAULT)
- info->callconv = sig->sentinelpos >= 0 ? 2 : 1;
- else {
- if (sig->call_convention == MONO_CALL_VARARG || sig->sentinelpos >= 0)
- info->callconv = 2;
- else
- info->callconv = 1;
- }
- info->callconv |= (sig->hasthis << 5) | (sig->explicit_this << 6);
- }
- ICALL_EXPORT MonoArray*
- ves_icall_get_parameter_info (MonoMethod *method, MonoReflectionMethod *member)
- {
- MonoDomain *domain = mono_domain_get ();
- return mono_param_get_objects_internal (domain, method, member->reftype ? mono_class_from_mono_type (member->reftype->type) : NULL);
- }
- ICALL_EXPORT MonoReflectionMarshalAsAttribute*
- ves_icall_System_MonoMethodInfo_get_retval_marshal (MonoMethod *method)
- {
- MonoDomain *domain = mono_domain_get ();
- MonoReflectionMarshalAsAttribute* res = NULL;
- MonoMarshalSpec **mspecs;
- int i;
- mspecs = g_new (MonoMarshalSpec*, mono_method_signature (method)->param_count + 1);
- mono_method_get_marshal_info (method, mspecs);
- if (mspecs [0])
- res = mono_reflection_marshal_as_attribute_from_marshal_spec (domain, method->klass, mspecs [0]);
-
- for (i = mono_method_signature (method)->param_count; i >= 0; i--)
- if (mspecs [i])
- mono_metadata_free_marshal_spec (mspecs [i]);
- g_free (mspecs);
- return res;
- }
- ICALL_EXPORT gint32
- ves_icall_MonoField_GetFieldOffset (MonoReflectionField *field)
- {
- MonoClass *parent = field->field->parent;
- if (!parent->size_inited)
- mono_class_init (parent);
- return field->field->offset - sizeof (MonoObject);
- }
- ICALL_EXPORT MonoReflectionType*
- ves_icall_MonoField_GetParentType (MonoReflectionField *field, MonoBoolean declaring)
- {
- MonoClass *parent;
- MONO_ARCH_SAVE_REGS;
- parent = declaring? field->field->parent: field->klass;
- return mono_type_get_object (mono_object_domain (field), &parent->byval_arg);
- }
- ICALL_EXPORT MonoObject *
- ves_icall_MonoField_GetValueInternal (MonoReflectionField *field, MonoObject *obj)
- {
- MonoClass *fklass = field->klass;
- MonoClassField *cf = field->field;
- MonoDomain *domain = mono_object_domain (field);
- if (fklass->image->assembly->ref_only)
- mono_raise_exception (mono_get_exception_invalid_operation (
- "It is illegal to get the value on a field on a type loaded using the ReflectionOnly methods."));
- if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR)
- mono_security_core_clr_ensure_reflection_access_field (cf);
- return mono_field_get_value_object (domain, cf, obj);
- }
- ICALL_EXPORT void
- ves_icall_MonoField_SetValueInternal (MonoReflectionField *field, MonoObject *obj, MonoObject *value)
- {
- MonoError error;
- MonoClassField *cf = field->field;
- MonoType *type;
- gchar *v;
- MONO_ARCH_SAVE_REGS;
- if (field->klass->image->assembly->ref_only)
- mono_raise_exception (mono_get_exception_invalid_operation (
- "It is illegal to set the value on a field on a type loaded using the ReflectionOnly methods."));
- if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR)
- mono_security_core_clr_ensure_reflection_access_field (cf);
- type = mono_field_get_type_checked (cf, &error);
- if (!mono_error_ok (&error))
- mono_error_raise_exception (&error);
- v = (gchar *) value;
- if (!type->byref) {
- switch (type->type) {
- case MONO_TYPE_U1:
- case MONO_TYPE_I1:
- case MONO_TYPE_BOOLEAN:
- case MONO_TYPE_U2:
- case MONO_TYPE_I2:
- case MONO_TYPE_CHAR:
- case MONO_TYPE_U:
- case MONO_TYPE_I:
- case MONO_TYPE_U4:
- case MONO_TYPE_I4:
- case MONO_TYPE_R4:
- case MONO_TYPE_U8:
- case MONO_TYPE_I8:
- case MONO_TYPE_R8:
- case MONO_TYPE_VALUETYPE:
- case MONO_TYPE_PTR:
- if (v != NULL)
- v += sizeof (MonoObject);
- break;
- case MONO_TYPE_STRING:
- case MONO_TYPE_OBJECT:
- case MONO_TYPE_CLASS:
- case MONO_TYPE_ARRAY:
- case MONO_TYPE_SZARRAY:
- /* Do nothing */
- break;
- case MONO_TYPE_GENERICINST: {
- MonoGenericClass *gclass = type->data.generic_class;
- g_assert (!gclass->context.class_inst->is_open);
- if (mono_class_is_nullable (mono_class_from_mono_type (type))) {
- MonoClass *nklass = mono_class_from_mono_type (type);
- MonoObject *nullable;
- /*
- * Convert the boxed vtype into a Nullable structure.
- * This is complicated by the fact that Nullables have
- * a variable structure.
- */
- nullable = mono_object_new (mono_domain_get (), nklass);
- mono_nullable_init (mono_object_unbox (nullable), value, nklass);
- v = mono_object_unbox (nullable);
- }
- else
- if (gclass->container_class->valuetype && (v != NULL))
- v += sizeof (MonoObject);
- break;
- }
- default:
- g_error ("type 0x%x not handled in "
- "ves_icall_FieldInfo_SetValueInternal", type->type);
- return;
- }
- }
- if (type->attrs & FIELD_ATTRIBUTE_STATIC) {
- MonoVTable *vtable = mono_class_vtable_full (mono_object_domain (field), cf->parent, TRUE);
- if (!vtable->initialized)
- mono_runtime_class_init (vtable);
- mono_field_static_set_value (vtable, cf, v);
- } else {
- m…
Large files files are truncated, but you can click here to view the full file