Make GetGenericTypeDefinitionImpl not init the class.
[mono-project.git] / mono / metadata / icall.c
blob72435c5de00df7f795a61d1d52d8b5ec41c6f8fc
1 /*
2 * icall.c:
4 * Authors:
5 * Dietmar Maurer (dietmar@ximian.com)
6 * Paolo Molaro (lupus@ximian.com)
7 * Patrik Torstensson (patrik.torstensson@labs2.com)
9 * Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
10 * Copyright 2004-2009 Novell, Inc (http://www.novell.com)
13 #include <config.h>
14 #include <glib.h>
15 #include <stdarg.h>
16 #include <string.h>
17 #include <ctype.h>
18 #ifdef HAVE_ALLOCA_H
19 #include <alloca.h>
20 #endif
21 #ifdef HAVE_SYS_TIME_H
22 #include <sys/time.h>
23 #endif
24 #ifdef HAVE_UNISTD_H
25 #include <unistd.h>
26 #endif
27 #if defined (HOST_WIN32)
28 #include <stdlib.h>
29 #endif
31 #include "mono/utils/mono-membar.h"
32 #include <mono/metadata/object.h>
33 #include <mono/metadata/threads.h>
34 #include <mono/metadata/threads-types.h>
35 #include <mono/metadata/threadpool.h>
36 #include <mono/metadata/monitor.h>
37 #include <mono/metadata/reflection.h>
38 #include <mono/metadata/assembly.h>
39 #include <mono/metadata/tabledefs.h>
40 #include <mono/metadata/exception.h>
41 #include <mono/metadata/file-io.h>
42 #include <mono/metadata/console-io.h>
43 #include <mono/metadata/socket-io.h>
44 #include <mono/metadata/mono-endian.h>
45 #include <mono/metadata/tokentype.h>
46 #include <mono/metadata/domain-internals.h>
47 #include <mono/metadata/metadata-internals.h>
48 #include <mono/metadata/class-internals.h>
49 #include <mono/metadata/marshal.h>
50 #include <mono/metadata/gc-internal.h>
51 #include <mono/metadata/mono-gc.h>
52 #include <mono/metadata/rand.h>
53 #include <mono/metadata/sysmath.h>
54 #include <mono/metadata/string-icalls.h>
55 #include <mono/metadata/debug-helpers.h>
56 #include <mono/metadata/process.h>
57 #include <mono/metadata/environment.h>
58 #include <mono/metadata/profiler-private.h>
59 #include <mono/metadata/locales.h>
60 #include <mono/metadata/filewatcher.h>
61 #include <mono/metadata/char-conversions.h>
62 #include <mono/metadata/security.h>
63 #include <mono/metadata/mono-config.h>
64 #include <mono/metadata/cil-coff.h>
65 #include <mono/metadata/number-formatter.h>
66 #include <mono/metadata/security-manager.h>
67 #include <mono/metadata/security-core-clr.h>
68 #include <mono/metadata/mono-perfcounters.h>
69 #include <mono/metadata/mono-debug.h>
70 #include <mono/metadata/mono-ptr-array.h>
71 #include <mono/io-layer/io-layer.h>
72 #include <mono/utils/strtod.h>
73 #include <mono/utils/monobitset.h>
74 #include <mono/utils/mono-time.h>
75 #include <mono/utils/mono-proclib.h>
76 #include <mono/utils/mono-string.h>
77 #include <mono/utils/mono-error-internals.h>
78 #include <mono/utils/mono-mmap.h>
80 #if defined (HOST_WIN32)
81 #include <windows.h>
82 #include <shlobj.h>
83 #endif
84 #include "decimal.h"
86 extern MonoString* ves_icall_System_Environment_GetOSVersionString (void) MONO_INTERNAL;
88 static MonoReflectionAssembly* ves_icall_System_Reflection_Assembly_GetCallingAssembly (void);
90 static MonoArray*
91 type_array_from_modifiers (MonoImage *image, MonoType *type, int optional);
93 static inline MonoBoolean
94 is_generic_parameter (MonoType *type)
96 return !type->byref && (type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR);
99 static void
100 mono_class_init_or_throw (MonoClass *klass)
102 if (!mono_class_init (klass))
103 mono_raise_exception (mono_class_get_exception_for_failure (klass));
107 * We expect a pointer to a char, not a string
109 static gboolean
110 mono_double_ParseImpl (char *ptr, double *result)
112 gchar *endptr = NULL;
113 *result = 0.0;
115 MONO_ARCH_SAVE_REGS;
117 #ifdef __arm__
118 if (*ptr)
119 *result = strtod (ptr, &endptr);
120 #else
121 if (*ptr){
122 /* mono_strtod () is not thread-safe */
123 EnterCriticalSection (&mono_strtod_mutex);
124 *result = mono_strtod (ptr, &endptr);
125 LeaveCriticalSection (&mono_strtod_mutex);
127 #endif
129 if (!*ptr || (endptr && *endptr))
130 return FALSE;
132 return TRUE;
135 static MonoObject *
136 ves_icall_System_Array_GetValueImpl (MonoObject *this, guint32 pos)
138 MonoClass *ac;
139 MonoArray *ao;
140 gint32 esize;
141 gpointer *ea;
143 MONO_ARCH_SAVE_REGS;
145 ao = (MonoArray *)this;
146 ac = (MonoClass *)ao->obj.vtable->klass;
148 esize = mono_array_element_size (ac);
149 ea = (gpointer*)((char*)ao->vector + (pos * esize));
151 if (ac->element_class->valuetype)
152 return mono_value_box (this->vtable->domain, ac->element_class, ea);
153 else
154 return *ea;
157 static MonoObject *
158 ves_icall_System_Array_GetValue (MonoObject *this, MonoObject *idxs)
160 MonoClass *ac, *ic;
161 MonoArray *ao, *io;
162 gint32 i, pos, *ind;
164 MONO_ARCH_SAVE_REGS;
166 MONO_CHECK_ARG_NULL (idxs);
168 io = (MonoArray *)idxs;
169 ic = (MonoClass *)io->obj.vtable->klass;
171 ao = (MonoArray *)this;
172 ac = (MonoClass *)ao->obj.vtable->klass;
174 g_assert (ic->rank == 1);
175 if (io->bounds != NULL || io->max_length != ac->rank)
176 mono_raise_exception (mono_get_exception_argument (NULL, NULL));
178 ind = (gint32 *)io->vector;
180 if (ao->bounds == NULL) {
181 if (*ind < 0 || *ind >= ao->max_length)
182 mono_raise_exception (mono_get_exception_index_out_of_range ());
184 return ves_icall_System_Array_GetValueImpl (this, *ind);
187 for (i = 0; i < ac->rank; i++)
188 if ((ind [i] < ao->bounds [i].lower_bound) ||
189 (ind [i] >= (mono_array_lower_bound_t)ao->bounds [i].length + ao->bounds [i].lower_bound))
190 mono_raise_exception (mono_get_exception_index_out_of_range ());
192 pos = ind [0] - ao->bounds [0].lower_bound;
193 for (i = 1; i < ac->rank; i++)
194 pos = pos*ao->bounds [i].length + ind [i] -
195 ao->bounds [i].lower_bound;
197 return ves_icall_System_Array_GetValueImpl (this, pos);
200 static void
201 ves_icall_System_Array_SetValueImpl (MonoArray *this, MonoObject *value, guint32 pos)
203 MonoClass *ac, *vc, *ec;
204 gint32 esize, vsize;
205 gpointer *ea, *va;
206 int et, vt;
208 guint64 u64 = 0;
209 gint64 i64 = 0;
210 gdouble r64 = 0;
212 MONO_ARCH_SAVE_REGS;
214 if (value)
215 vc = value->vtable->klass;
216 else
217 vc = NULL;
219 ac = this->obj.vtable->klass;
220 ec = ac->element_class;
222 esize = mono_array_element_size (ac);
223 ea = (gpointer*)((char*)this->vector + (pos * esize));
224 va = (gpointer*)((char*)value + sizeof (MonoObject));
226 if (mono_class_is_nullable (ec)) {
227 mono_nullable_init ((guint8*)ea, value, ec);
228 return;
231 if (!value) {
232 memset (ea, 0, esize);
233 return;
236 #define NO_WIDENING_CONVERSION G_STMT_START{\
237 mono_raise_exception (mono_get_exception_argument ( \
238 "value", "not a widening conversion")); \
239 }G_STMT_END
241 #define CHECK_WIDENING_CONVERSION(extra) G_STMT_START{\
242 if (esize < vsize + (extra)) \
243 mono_raise_exception (mono_get_exception_argument ( \
244 "value", "not a widening conversion")); \
245 }G_STMT_END
247 #define INVALID_CAST G_STMT_START{\
248 mono_raise_exception (mono_get_exception_invalid_cast ()); \
249 }G_STMT_END
251 /* Check element (destination) type. */
252 switch (ec->byval_arg.type) {
253 case MONO_TYPE_STRING:
254 switch (vc->byval_arg.type) {
255 case MONO_TYPE_STRING:
256 break;
257 default:
258 INVALID_CAST;
260 break;
261 case MONO_TYPE_BOOLEAN:
262 switch (vc->byval_arg.type) {
263 case MONO_TYPE_BOOLEAN:
264 break;
265 case MONO_TYPE_CHAR:
266 case MONO_TYPE_U1:
267 case MONO_TYPE_U2:
268 case MONO_TYPE_U4:
269 case MONO_TYPE_U8:
270 case MONO_TYPE_I1:
271 case MONO_TYPE_I2:
272 case MONO_TYPE_I4:
273 case MONO_TYPE_I8:
274 case MONO_TYPE_R4:
275 case MONO_TYPE_R8:
276 NO_WIDENING_CONVERSION;
277 default:
278 INVALID_CAST;
280 break;
283 if (!ec->valuetype) {
284 if (!mono_object_isinst (value, ec))
285 INVALID_CAST;
286 mono_gc_wbarrier_set_arrayref (this, ea, (MonoObject*)value);
287 return;
290 if (mono_object_isinst (value, ec)) {
291 if (ec->has_references)
292 mono_value_copy (ea, (char*)value + sizeof (MonoObject), ec);
293 else
294 memcpy (ea, (char *)value + sizeof (MonoObject), esize);
295 return;
298 if (!vc->valuetype)
299 INVALID_CAST;
301 vsize = mono_class_instance_size (vc) - sizeof (MonoObject);
303 et = ec->byval_arg.type;
304 if (et == MONO_TYPE_VALUETYPE && ec->byval_arg.data.klass->enumtype)
305 et = mono_class_enum_basetype (ec->byval_arg.data.klass)->type;
307 vt = vc->byval_arg.type;
308 if (vt == MONO_TYPE_VALUETYPE && vc->byval_arg.data.klass->enumtype)
309 vt = mono_class_enum_basetype (vc->byval_arg.data.klass)->type;
311 #define ASSIGN_UNSIGNED(etype) G_STMT_START{\
312 switch (vt) { \
313 case MONO_TYPE_U1: \
314 case MONO_TYPE_U2: \
315 case MONO_TYPE_U4: \
316 case MONO_TYPE_U8: \
317 case MONO_TYPE_CHAR: \
318 CHECK_WIDENING_CONVERSION(0); \
319 *(etype *) ea = (etype) u64; \
320 return; \
321 /* You can't assign a signed value to an unsigned array. */ \
322 case MONO_TYPE_I1: \
323 case MONO_TYPE_I2: \
324 case MONO_TYPE_I4: \
325 case MONO_TYPE_I8: \
326 /* You can't assign a floating point number to an integer array. */ \
327 case MONO_TYPE_R4: \
328 case MONO_TYPE_R8: \
329 NO_WIDENING_CONVERSION; \
331 }G_STMT_END
333 #define ASSIGN_SIGNED(etype) G_STMT_START{\
334 switch (vt) { \
335 case MONO_TYPE_I1: \
336 case MONO_TYPE_I2: \
337 case MONO_TYPE_I4: \
338 case MONO_TYPE_I8: \
339 CHECK_WIDENING_CONVERSION(0); \
340 *(etype *) ea = (etype) i64; \
341 return; \
342 /* You can assign an unsigned value to a signed array if the array's */ \
343 /* element size is larger than the value size. */ \
344 case MONO_TYPE_U1: \
345 case MONO_TYPE_U2: \
346 case MONO_TYPE_U4: \
347 case MONO_TYPE_U8: \
348 case MONO_TYPE_CHAR: \
349 CHECK_WIDENING_CONVERSION(1); \
350 *(etype *) ea = (etype) u64; \
351 return; \
352 /* You can't assign a floating point number to an integer array. */ \
353 case MONO_TYPE_R4: \
354 case MONO_TYPE_R8: \
355 NO_WIDENING_CONVERSION; \
357 }G_STMT_END
359 #define ASSIGN_REAL(etype) G_STMT_START{\
360 switch (vt) { \
361 case MONO_TYPE_R4: \
362 case MONO_TYPE_R8: \
363 CHECK_WIDENING_CONVERSION(0); \
364 *(etype *) ea = (etype) r64; \
365 return; \
366 /* All integer values fit into a floating point array, so we don't */ \
367 /* need to CHECK_WIDENING_CONVERSION here. */ \
368 case MONO_TYPE_I1: \
369 case MONO_TYPE_I2: \
370 case MONO_TYPE_I4: \
371 case MONO_TYPE_I8: \
372 *(etype *) ea = (etype) i64; \
373 return; \
374 case MONO_TYPE_U1: \
375 case MONO_TYPE_U2: \
376 case MONO_TYPE_U4: \
377 case MONO_TYPE_U8: \
378 case MONO_TYPE_CHAR: \
379 *(etype *) ea = (etype) u64; \
380 return; \
382 }G_STMT_END
384 switch (vt) {
385 case MONO_TYPE_U1:
386 u64 = *(guint8 *) va;
387 break;
388 case MONO_TYPE_U2:
389 u64 = *(guint16 *) va;
390 break;
391 case MONO_TYPE_U4:
392 u64 = *(guint32 *) va;
393 break;
394 case MONO_TYPE_U8:
395 u64 = *(guint64 *) va;
396 break;
397 case MONO_TYPE_I1:
398 i64 = *(gint8 *) va;
399 break;
400 case MONO_TYPE_I2:
401 i64 = *(gint16 *) va;
402 break;
403 case MONO_TYPE_I4:
404 i64 = *(gint32 *) va;
405 break;
406 case MONO_TYPE_I8:
407 i64 = *(gint64 *) va;
408 break;
409 case MONO_TYPE_R4:
410 r64 = *(gfloat *) va;
411 break;
412 case MONO_TYPE_R8:
413 r64 = *(gdouble *) va;
414 break;
415 case MONO_TYPE_CHAR:
416 u64 = *(guint16 *) va;
417 break;
418 case MONO_TYPE_BOOLEAN:
419 /* Boolean is only compatible with itself. */
420 switch (et) {
421 case MONO_TYPE_CHAR:
422 case MONO_TYPE_U1:
423 case MONO_TYPE_U2:
424 case MONO_TYPE_U4:
425 case MONO_TYPE_U8:
426 case MONO_TYPE_I1:
427 case MONO_TYPE_I2:
428 case MONO_TYPE_I4:
429 case MONO_TYPE_I8:
430 case MONO_TYPE_R4:
431 case MONO_TYPE_R8:
432 NO_WIDENING_CONVERSION;
433 default:
434 INVALID_CAST;
436 break;
439 /* If we can't do a direct copy, let's try a widening conversion. */
440 switch (et) {
441 case MONO_TYPE_CHAR:
442 ASSIGN_UNSIGNED (guint16);
443 case MONO_TYPE_U1:
444 ASSIGN_UNSIGNED (guint8);
445 case MONO_TYPE_U2:
446 ASSIGN_UNSIGNED (guint16);
447 case MONO_TYPE_U4:
448 ASSIGN_UNSIGNED (guint32);
449 case MONO_TYPE_U8:
450 ASSIGN_UNSIGNED (guint64);
451 case MONO_TYPE_I1:
452 ASSIGN_SIGNED (gint8);
453 case MONO_TYPE_I2:
454 ASSIGN_SIGNED (gint16);
455 case MONO_TYPE_I4:
456 ASSIGN_SIGNED (gint32);
457 case MONO_TYPE_I8:
458 ASSIGN_SIGNED (gint64);
459 case MONO_TYPE_R4:
460 ASSIGN_REAL (gfloat);
461 case MONO_TYPE_R8:
462 ASSIGN_REAL (gdouble);
465 INVALID_CAST;
466 /* Not reached, INVALID_CAST does not return. Just to avoid a compiler warning ... */
467 return;
469 #undef INVALID_CAST
470 #undef NO_WIDENING_CONVERSION
471 #undef CHECK_WIDENING_CONVERSION
472 #undef ASSIGN_UNSIGNED
473 #undef ASSIGN_SIGNED
474 #undef ASSIGN_REAL
477 static void
478 ves_icall_System_Array_SetValue (MonoArray *this, MonoObject *value,
479 MonoArray *idxs)
481 MonoClass *ac, *ic;
482 gint32 i, pos, *ind;
484 MONO_ARCH_SAVE_REGS;
486 MONO_CHECK_ARG_NULL (idxs);
488 ic = idxs->obj.vtable->klass;
489 ac = this->obj.vtable->klass;
491 g_assert (ic->rank == 1);
492 if (idxs->bounds != NULL || idxs->max_length != ac->rank)
493 mono_raise_exception (mono_get_exception_argument (NULL, NULL));
495 ind = (gint32 *)idxs->vector;
497 if (this->bounds == NULL) {
498 if (*ind < 0 || *ind >= this->max_length)
499 mono_raise_exception (mono_get_exception_index_out_of_range ());
501 ves_icall_System_Array_SetValueImpl (this, value, *ind);
502 return;
505 for (i = 0; i < ac->rank; i++)
506 if ((ind [i] < this->bounds [i].lower_bound) ||
507 (ind [i] >= (mono_array_lower_bound_t)this->bounds [i].length + this->bounds [i].lower_bound))
508 mono_raise_exception (mono_get_exception_index_out_of_range ());
510 pos = ind [0] - this->bounds [0].lower_bound;
511 for (i = 1; i < ac->rank; i++)
512 pos = pos * this->bounds [i].length + ind [i] -
513 this->bounds [i].lower_bound;
515 ves_icall_System_Array_SetValueImpl (this, value, pos);
518 static MonoArray *
519 ves_icall_System_Array_CreateInstanceImpl (MonoReflectionType *type, MonoArray *lengths, MonoArray *bounds)
521 MonoClass *aklass, *klass;
522 MonoArray *array;
523 uintptr_t *sizes, i;
524 gboolean bounded = FALSE;
526 MONO_ARCH_SAVE_REGS;
528 MONO_CHECK_ARG_NULL (type);
529 MONO_CHECK_ARG_NULL (lengths);
531 MONO_CHECK_ARG (lengths, mono_array_length (lengths) > 0);
532 if (bounds)
533 MONO_CHECK_ARG (bounds, mono_array_length (lengths) == mono_array_length (bounds));
535 for (i = 0; i < mono_array_length (lengths); i++)
536 if (mono_array_get (lengths, gint32, i) < 0)
537 mono_raise_exception (mono_get_exception_argument_out_of_range (NULL));
539 klass = mono_class_from_mono_type (type->type);
540 mono_class_init_or_throw (klass);
542 if (bounds && (mono_array_length (bounds) == 1) && (mono_array_get (bounds, gint32, 0) != 0))
543 /* vectors are not the same as one dimensional arrays with no-zero bounds */
544 bounded = TRUE;
545 else
546 bounded = FALSE;
548 aklass = mono_bounded_array_class_get (klass, mono_array_length (lengths), bounded);
550 sizes = alloca (aklass->rank * sizeof(intptr_t) * 2);
551 for (i = 0; i < aklass->rank; ++i) {
552 sizes [i] = mono_array_get (lengths, guint32, i);
553 if (bounds)
554 sizes [i + aklass->rank] = mono_array_get (bounds, guint32, i);
555 else
556 sizes [i + aklass->rank] = 0;
559 array = mono_array_new_full (mono_object_domain (type), aklass, sizes, (intptr_t*)sizes + aklass->rank);
561 return array;
564 static MonoArray *
565 ves_icall_System_Array_CreateInstanceImpl64 (MonoReflectionType *type, MonoArray *lengths, MonoArray *bounds)
567 MonoClass *aklass, *klass;
568 MonoArray *array;
569 uintptr_t *sizes, i;
570 gboolean bounded = FALSE;
572 MONO_ARCH_SAVE_REGS;
574 MONO_CHECK_ARG_NULL (type);
575 MONO_CHECK_ARG_NULL (lengths);
577 MONO_CHECK_ARG (lengths, mono_array_length (lengths) > 0);
578 if (bounds)
579 MONO_CHECK_ARG (bounds, mono_array_length (lengths) == mono_array_length (bounds));
581 for (i = 0; i < mono_array_length (lengths); i++)
582 if ((mono_array_get (lengths, gint64, i) < 0) ||
583 (mono_array_get (lengths, gint64, i) > MONO_ARRAY_MAX_INDEX))
584 mono_raise_exception (mono_get_exception_argument_out_of_range (NULL));
586 klass = mono_class_from_mono_type (type->type);
587 mono_class_init_or_throw (klass);
589 if (bounds && (mono_array_length (bounds) == 1) && (mono_array_get (bounds, gint64, 0) != 0))
590 /* vectors are not the same as one dimensional arrays with no-zero bounds */
591 bounded = TRUE;
592 else
593 bounded = FALSE;
595 aklass = mono_bounded_array_class_get (klass, mono_array_length (lengths), bounded);
597 sizes = alloca (aklass->rank * sizeof(intptr_t) * 2);
598 for (i = 0; i < aklass->rank; ++i) {
599 sizes [i] = mono_array_get (lengths, guint64, i);
600 if (bounds)
601 sizes [i + aklass->rank] = (mono_array_size_t) mono_array_get (bounds, guint64, i);
602 else
603 sizes [i + aklass->rank] = 0;
606 array = mono_array_new_full (mono_object_domain (type), aklass, sizes, (intptr_t*)sizes + aklass->rank);
608 return array;
611 static gint32
612 ves_icall_System_Array_GetRank (MonoObject *this)
614 MONO_ARCH_SAVE_REGS;
616 return this->vtable->klass->rank;
619 static gint32
620 ves_icall_System_Array_GetLength (MonoArray *this, gint32 dimension)
622 gint32 rank = ((MonoObject *)this)->vtable->klass->rank;
623 uintptr_t length;
625 MONO_ARCH_SAVE_REGS;
627 if ((dimension < 0) || (dimension >= rank))
628 mono_raise_exception (mono_get_exception_index_out_of_range ());
630 if (this->bounds == NULL)
631 length = this->max_length;
632 else
633 length = this->bounds [dimension].length;
635 #ifdef MONO_BIG_ARRAYS
636 if (length > G_MAXINT32)
637 mono_raise_exception (mono_get_exception_overflow ());
638 #endif
639 return length;
642 static gint64
643 ves_icall_System_Array_GetLongLength (MonoArray *this, gint32 dimension)
645 gint32 rank = ((MonoObject *)this)->vtable->klass->rank;
647 MONO_ARCH_SAVE_REGS;
649 if ((dimension < 0) || (dimension >= rank))
650 mono_raise_exception (mono_get_exception_index_out_of_range ());
652 if (this->bounds == NULL)
653 return this->max_length;
655 return this->bounds [dimension].length;
658 static gint32
659 ves_icall_System_Array_GetLowerBound (MonoArray *this, gint32 dimension)
661 gint32 rank = ((MonoObject *)this)->vtable->klass->rank;
663 MONO_ARCH_SAVE_REGS;
665 if ((dimension < 0) || (dimension >= rank))
666 mono_raise_exception (mono_get_exception_index_out_of_range ());
668 if (this->bounds == NULL)
669 return 0;
671 return this->bounds [dimension].lower_bound;
674 static void
675 ves_icall_System_Array_ClearInternal (MonoArray *arr, int idx, int length)
677 int sz = mono_array_element_size (mono_object_class (arr));
678 memset (mono_array_addr_with_size (arr, sz, idx), 0, length * sz);
681 static gboolean
682 ves_icall_System_Array_FastCopy (MonoArray *source, int source_idx, MonoArray* dest, int dest_idx, int length)
684 int element_size;
685 void * dest_addr;
686 void * source_addr;
687 MonoClass *src_class;
688 MonoClass *dest_class;
689 int i;
691 MONO_ARCH_SAVE_REGS;
693 if (source->obj.vtable->klass->rank != dest->obj.vtable->klass->rank)
694 return FALSE;
696 if (source->bounds || dest->bounds)
697 return FALSE;
699 /* there's no integer overflow since mono_array_length returns an unsigned integer */
700 if ((dest_idx + length > mono_array_length (dest)) ||
701 (source_idx + length > mono_array_length (source)))
702 return FALSE;
704 src_class = source->obj.vtable->klass->element_class;
705 dest_class = dest->obj.vtable->klass->element_class;
708 * Handle common cases.
711 /* Case1: object[] -> valuetype[] (ArrayList::ToArray) */
712 if (src_class == mono_defaults.object_class && dest_class->valuetype) {
713 int has_refs = dest_class->has_references;
714 for (i = source_idx; i < source_idx + length; ++i) {
715 MonoObject *elem = mono_array_get (source, MonoObject*, i);
716 if (elem && !mono_object_isinst (elem, dest_class))
717 return FALSE;
720 element_size = mono_array_element_size (dest->obj.vtable->klass);
721 memset (mono_array_addr_with_size (dest, element_size, dest_idx), 0, element_size * length);
722 for (i = 0; i < length; ++i) {
723 MonoObject *elem = mono_array_get (source, MonoObject*, source_idx + i);
724 void *addr = mono_array_addr_with_size (dest, element_size, dest_idx + i);
725 if (!elem)
726 continue;
727 if (has_refs)
728 mono_value_copy (addr, (char *)elem + sizeof (MonoObject), dest_class);
729 else
730 memcpy (addr, (char *)elem + sizeof (MonoObject), element_size);
732 return TRUE;
735 /* Check if we're copying a char[] <==> (u)short[] */
736 if (src_class != dest_class) {
737 if (dest_class->valuetype || dest_class->enumtype || src_class->valuetype || src_class->enumtype)
738 return FALSE;
740 if (mono_class_is_subclass_of (src_class, dest_class, FALSE))
742 /* Case2: object[] -> reftype[] (ArrayList::ToArray) */
743 else if (mono_class_is_subclass_of (dest_class, src_class, FALSE))
744 for (i = source_idx; i < source_idx + length; ++i) {
745 MonoObject *elem = mono_array_get (source, MonoObject*, i);
746 if (elem && !mono_object_isinst (elem, dest_class))
747 return FALSE;
749 else
750 return FALSE;
753 if (dest_class->valuetype) {
754 element_size = mono_array_element_size (source->obj.vtable->klass);
755 source_addr = mono_array_addr_with_size (source, element_size, source_idx);
756 if (dest_class->has_references) {
757 mono_value_copy_array (dest, dest_idx, source_addr, length);
758 } else {
759 dest_addr = mono_array_addr_with_size (dest, element_size, dest_idx);
760 memmove (dest_addr, source_addr, element_size * length);
762 } else {
763 mono_array_memcpy_refs (dest, dest_idx, source, source_idx, length);
766 return TRUE;
769 static void
770 ves_icall_System_Array_GetGenericValueImpl (MonoObject *this, guint32 pos, gpointer value)
772 MonoClass *ac;
773 MonoArray *ao;
774 gint32 esize;
775 gpointer *ea;
777 MONO_ARCH_SAVE_REGS;
779 ao = (MonoArray *)this;
780 ac = (MonoClass *)ao->obj.vtable->klass;
782 esize = mono_array_element_size (ac);
783 ea = (gpointer*)((char*)ao->vector + (pos * esize));
785 memcpy (value, ea, esize);
788 static void
789 ves_icall_System_Array_SetGenericValueImpl (MonoObject *this, guint32 pos, gpointer value)
791 MonoClass *ac, *ec;
792 MonoArray *ao;
793 gint32 esize;
794 gpointer *ea;
796 MONO_ARCH_SAVE_REGS;
798 ao = (MonoArray *)this;
799 ac = (MonoClass *)ao->obj.vtable->klass;
800 ec = ac->element_class;
802 esize = mono_array_element_size (ac);
803 ea = (gpointer*)((char*)ao->vector + (pos * esize));
805 if (MONO_TYPE_IS_REFERENCE (&ec->byval_arg)) {
806 g_assert (esize == sizeof (gpointer));
807 mono_gc_wbarrier_generic_store (ea, *(gpointer*)value);
808 } else {
809 g_assert (ec->inited);
810 g_assert (esize == mono_class_value_size (ec, NULL));
811 if (ec->has_references)
812 mono_gc_wbarrier_value_copy (ea, value, 1, ec);
813 else
814 memcpy (ea, value, esize);
818 static void
819 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_InitializeArray (MonoArray *array, MonoClassField *field_handle)
821 MonoClass *klass = array->obj.vtable->klass;
822 guint32 size = mono_array_element_size (klass);
823 MonoType *type = mono_type_get_underlying_type (&klass->element_class->byval_arg);
824 int align;
825 const char *field_data;
827 if (MONO_TYPE_IS_REFERENCE (type) ||
828 (type->type == MONO_TYPE_VALUETYPE &&
829 (!mono_type_get_class (type) ||
830 mono_type_get_class (type)->has_references))) {
831 MonoException *exc = mono_get_exception_argument("array",
832 "Cannot initialize array containing references");
833 mono_raise_exception (exc);
836 if (!(field_handle->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA)) {
837 MonoException *exc = mono_get_exception_argument("field_handle",
838 "Field doesn't have an RVA");
839 mono_raise_exception (exc);
842 size *= array->max_length;
843 field_data = mono_field_get_data (field_handle);
845 if (size > mono_type_size (field_handle->type, &align)) {
846 MonoException *exc = mono_get_exception_argument("field_handle",
847 "Field not large enough to fill array");
848 mono_raise_exception (exc);
851 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
852 #define SWAP(n) {\
853 guint ## n *data = (guint ## n *) mono_array_addr (array, char, 0); \
854 guint ## n *src = (guint ## n *) field_data; \
855 guint ## n *end = (guint ## n *)((char*)src + size); \
857 for (; src < end; data++, src++) { \
858 *data = read ## n (src); \
862 /* printf ("Initialize array with elements of %s type\n", klass->element_class->name); */
864 switch (type->type) {
865 case MONO_TYPE_CHAR:
866 case MONO_TYPE_I2:
867 case MONO_TYPE_U2:
868 SWAP (16);
869 break;
870 case MONO_TYPE_I4:
871 case MONO_TYPE_U4:
872 case MONO_TYPE_R4:
873 SWAP (32);
874 break;
875 case MONO_TYPE_I8:
876 case MONO_TYPE_U8:
877 case MONO_TYPE_R8:
878 SWAP (64);
879 break;
880 default:
881 memcpy (mono_array_addr (array, char, 0), field_data, size);
882 break;
884 #else
885 memcpy (mono_array_addr (array, char, 0), field_data, size);
886 #ifdef ARM_FPU_FPA
887 if (klass->element_class->byval_arg.type == MONO_TYPE_R8) {
888 gint i;
889 double tmp;
890 double *data = (double*)mono_array_addr (array, double, 0);
892 for (i = 0; i < size; i++, data++) {
893 readr8 (data, &tmp);
894 *data = tmp;
897 #endif
898 #endif
901 static gint
902 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_GetOffsetToStringData (void)
904 MONO_ARCH_SAVE_REGS;
906 return offsetof (MonoString, chars);
909 static MonoObject *
910 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_GetObjectValue (MonoObject *obj)
912 MONO_ARCH_SAVE_REGS;
914 if ((obj == NULL) || (! (obj->vtable->klass->valuetype)))
915 return obj;
916 else
917 return mono_object_clone (obj);
920 static void
921 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_RunClassConstructor (MonoType *handle)
923 MonoClass *klass;
924 MonoVTable *vtable;
926 MONO_CHECK_ARG_NULL (handle);
928 klass = mono_class_from_mono_type (handle);
929 MONO_CHECK_ARG (handle, klass);
931 vtable = mono_class_vtable_full (mono_domain_get (), klass, TRUE);
933 /* This will call the type constructor */
934 mono_runtime_class_init (vtable);
937 static void
938 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_RunModuleConstructor (MonoImage *image)
940 MONO_ARCH_SAVE_REGS;
942 mono_image_check_for_module_cctor (image);
943 if (image->has_module_cctor) {
944 MonoClass *module_klass = mono_class_get (image, MONO_TOKEN_TYPE_DEF | 1);
945 /*It's fine to raise the exception here*/
946 mono_runtime_class_init (mono_class_vtable_full (mono_domain_get (), module_klass, TRUE));
950 static MonoBoolean
951 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_SufficientExecutionStack (void)
953 guint8 *stack_addr;
954 guint8 *current;
955 size_t stack_size;
956 /* later make this configurable and per-arch */
957 int min_size = 4096 * 4 * sizeof (void*);
958 mono_thread_get_stack_bounds (&stack_addr, &stack_size);
959 /* if we have no info we are optimistic and assume there is enough room */
960 if (!stack_addr)
961 return TRUE;
962 current = (guint8 *)&stack_addr;
963 if (current > stack_addr) {
964 if ((current - stack_addr) < min_size)
965 return FALSE;
966 } else {
967 if (current - (stack_addr - stack_size) < min_size)
968 return FALSE;
970 return TRUE;
973 static MonoObject *
974 ves_icall_System_Object_MemberwiseClone (MonoObject *this)
976 MONO_ARCH_SAVE_REGS;
978 return mono_object_clone (this);
981 static gint32
982 ves_icall_System_ValueType_InternalGetHashCode (MonoObject *this, MonoArray **fields)
984 MonoClass *klass;
985 MonoObject **values = NULL;
986 MonoObject *o;
987 int count = 0;
988 gint32 result = 0;
989 MonoClassField* field;
990 gpointer iter;
992 MONO_ARCH_SAVE_REGS;
994 klass = mono_object_class (this);
996 if (mono_class_num_fields (klass) == 0)
997 return mono_object_hash (this);
1000 * Compute the starting value of the hashcode for fields of primitive
1001 * types, and return the remaining fields in an array to the managed side.
1002 * This way, we can avoid costly reflection operations in managed code.
1004 iter = NULL;
1005 while ((field = mono_class_get_fields (klass, &iter))) {
1006 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1007 continue;
1008 if (mono_field_is_deleted (field))
1009 continue;
1010 /* FIXME: Add more types */
1011 switch (field->type->type) {
1012 case MONO_TYPE_I4:
1013 result ^= *(gint32*)((guint8*)this + field->offset);
1014 break;
1015 case MONO_TYPE_STRING: {
1016 MonoString *s;
1017 s = *(MonoString**)((guint8*)this + field->offset);
1018 if (s != NULL)
1019 result ^= mono_string_hash (s);
1020 break;
1022 default:
1023 if (!values)
1024 values = g_newa (MonoObject*, mono_class_num_fields (klass));
1025 o = mono_field_get_value_object (mono_object_domain (this), field, this);
1026 values [count++] = o;
1030 if (values) {
1031 int i;
1032 mono_gc_wbarrier_generic_store (fields, (MonoObject*) mono_array_new (mono_domain_get (), mono_defaults.object_class, count));
1033 for (i = 0; i < count; ++i)
1034 mono_array_setref (*fields, i, values [i]);
1035 } else {
1036 *fields = NULL;
1038 return result;
1041 static MonoBoolean
1042 ves_icall_System_ValueType_Equals (MonoObject *this, MonoObject *that, MonoArray **fields)
1044 MonoClass *klass;
1045 MonoObject **values = NULL;
1046 MonoObject *o;
1047 MonoClassField* field;
1048 gpointer iter;
1049 int count = 0;
1051 MONO_ARCH_SAVE_REGS;
1053 MONO_CHECK_ARG_NULL (that);
1055 if (this->vtable != that->vtable)
1056 return FALSE;
1058 klass = mono_object_class (this);
1060 if (klass->enumtype && mono_class_enum_basetype (klass) && mono_class_enum_basetype (klass)->type == MONO_TYPE_I4)
1061 return (*(gint32*)((guint8*)this + sizeof (MonoObject)) == *(gint32*)((guint8*)that + sizeof (MonoObject)));
1064 * Do the comparison for fields of primitive type and return a result if
1065 * possible. Otherwise, return the remaining fields in an array to the
1066 * managed side. This way, we can avoid costly reflection operations in
1067 * managed code.
1069 *fields = NULL;
1070 iter = NULL;
1071 while ((field = mono_class_get_fields (klass, &iter))) {
1072 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1073 continue;
1074 if (mono_field_is_deleted (field))
1075 continue;
1076 /* FIXME: Add more types */
1077 switch (field->type->type) {
1078 case MONO_TYPE_U1:
1079 case MONO_TYPE_I1:
1080 case MONO_TYPE_BOOLEAN:
1081 if (*((guint8*)this + field->offset) != *((guint8*)that + field->offset))
1082 return FALSE;
1083 break;
1084 case MONO_TYPE_U2:
1085 case MONO_TYPE_I2:
1086 case MONO_TYPE_CHAR:
1087 if (*(gint16*)((guint8*)this + field->offset) != *(gint16*)((guint8*)that + field->offset))
1088 return FALSE;
1089 break;
1090 case MONO_TYPE_U4:
1091 case MONO_TYPE_I4:
1092 if (*(gint32*)((guint8*)this + field->offset) != *(gint32*)((guint8*)that + field->offset))
1093 return FALSE;
1094 break;
1095 case MONO_TYPE_U8:
1096 case MONO_TYPE_I8:
1097 if (*(gint64*)((guint8*)this + field->offset) != *(gint64*)((guint8*)that + field->offset))
1098 return FALSE;
1099 break;
1100 case MONO_TYPE_R4:
1101 if (*(float*)((guint8*)this + field->offset) != *(float*)((guint8*)that + field->offset))
1102 return FALSE;
1103 break;
1104 case MONO_TYPE_R8:
1105 if (*(double*)((guint8*)this + field->offset) != *(double*)((guint8*)that + field->offset))
1106 return FALSE;
1107 break;
1110 case MONO_TYPE_STRING: {
1111 MonoString *s1, *s2;
1112 guint32 s1len, s2len;
1113 s1 = *(MonoString**)((guint8*)this + field->offset);
1114 s2 = *(MonoString**)((guint8*)that + field->offset);
1115 if (s1 == s2)
1116 break;
1117 if ((s1 == NULL) || (s2 == NULL))
1118 return FALSE;
1119 s1len = mono_string_length (s1);
1120 s2len = mono_string_length (s2);
1121 if (s1len != s2len)
1122 return FALSE;
1124 if (memcmp (mono_string_chars (s1), mono_string_chars (s2), s1len * sizeof (gunichar2)) != 0)
1125 return FALSE;
1126 break;
1128 default:
1129 if (!values)
1130 values = g_newa (MonoObject*, mono_class_num_fields (klass) * 2);
1131 o = mono_field_get_value_object (mono_object_domain (this), field, this);
1132 values [count++] = o;
1133 o = mono_field_get_value_object (mono_object_domain (this), field, that);
1134 values [count++] = o;
1137 if (klass->enumtype)
1138 /* enums only have one non-static field */
1139 break;
1142 if (values) {
1143 int i;
1144 mono_gc_wbarrier_generic_store (fields, (MonoObject*) mono_array_new (mono_domain_get (), mono_defaults.object_class, count));
1145 for (i = 0; i < count; ++i)
1146 mono_array_setref (*fields, i, values [i]);
1147 return FALSE;
1148 } else {
1149 return TRUE;
1153 static MonoReflectionType *
1154 ves_icall_System_Object_GetType (MonoObject *obj)
1156 MONO_ARCH_SAVE_REGS;
1158 if (obj->vtable->klass != mono_defaults.transparent_proxy_class)
1159 return mono_type_get_object (mono_object_domain (obj), &obj->vtable->klass->byval_arg);
1160 else
1161 return mono_type_get_object (mono_object_domain (obj), &((MonoTransparentProxy*)obj)->remote_class->proxy_class->byval_arg);
1164 static void
1165 mono_type_type_from_obj (MonoReflectionType *mtype, MonoObject *obj)
1167 MONO_ARCH_SAVE_REGS;
1169 mtype->type = &obj->vtable->klass->byval_arg;
1170 g_assert (mtype->type->type);
1173 static gint32
1174 ves_icall_ModuleBuilder_getToken (MonoReflectionModuleBuilder *mb, MonoObject *obj, gboolean create_open_instance)
1176 MONO_ARCH_SAVE_REGS;
1178 MONO_CHECK_ARG_NULL (obj);
1180 return mono_image_create_token (mb->dynamic_image, obj, create_open_instance, TRUE);
1183 static gint32
1184 ves_icall_ModuleBuilder_getMethodToken (MonoReflectionModuleBuilder *mb,
1185 MonoReflectionMethod *method,
1186 MonoArray *opt_param_types)
1188 MONO_ARCH_SAVE_REGS;
1190 MONO_CHECK_ARG_NULL (method);
1192 return mono_image_create_method_token (
1193 mb->dynamic_image, (MonoObject *) method, opt_param_types);
1196 static void
1197 ves_icall_ModuleBuilder_WriteToFile (MonoReflectionModuleBuilder *mb, HANDLE file)
1199 MONO_ARCH_SAVE_REGS;
1201 mono_image_create_pefile (mb, file);
1204 static void
1205 ves_icall_ModuleBuilder_build_metadata (MonoReflectionModuleBuilder *mb)
1207 MONO_ARCH_SAVE_REGS;
1209 mono_image_build_metadata (mb);
1212 static void
1213 ves_icall_ModuleBuilder_RegisterToken (MonoReflectionModuleBuilder *mb, MonoObject *obj, guint32 token)
1215 MONO_ARCH_SAVE_REGS;
1217 mono_image_register_token (mb->dynamic_image, token, obj);
1220 static gboolean
1221 get_caller (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1223 MonoMethod **dest = data;
1225 /* skip unmanaged frames */
1226 if (!managed)
1227 return FALSE;
1229 if (m == *dest) {
1230 *dest = NULL;
1231 return FALSE;
1233 if (!(*dest)) {
1234 *dest = m;
1235 return TRUE;
1237 return FALSE;
1240 static gboolean
1241 get_executing (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1243 MonoMethod **dest = data;
1245 /* skip unmanaged frames */
1246 if (!managed)
1247 return FALSE;
1249 if (!(*dest)) {
1250 if (!strcmp (m->klass->name_space, "System.Reflection"))
1251 return FALSE;
1252 *dest = m;
1253 return TRUE;
1255 return FALSE;
1258 static gboolean
1259 get_caller_no_reflection (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1261 MonoMethod **dest = data;
1263 /* skip unmanaged frames */
1264 if (!managed)
1265 return FALSE;
1267 if (m->wrapper_type != MONO_WRAPPER_NONE)
1268 return FALSE;
1270 if (m->klass->image == mono_defaults.corlib && !strcmp (m->klass->name_space, "System.Reflection"))
1271 return FALSE;
1273 if (m == *dest) {
1274 *dest = NULL;
1275 return FALSE;
1277 if (!(*dest)) {
1278 *dest = m;
1279 return TRUE;
1281 return FALSE;
1284 static MonoReflectionType *
1285 type_from_name (const char *str, MonoBoolean ignoreCase)
1287 MonoType *type = NULL;
1288 MonoAssembly *assembly = NULL;
1289 MonoTypeNameParse info;
1290 char *temp_str = g_strdup (str);
1291 gboolean type_resolve = FALSE;
1293 MONO_ARCH_SAVE_REGS;
1295 /* mono_reflection_parse_type() mangles the string */
1296 if (!mono_reflection_parse_type (temp_str, &info)) {
1297 mono_reflection_free_type_info (&info);
1298 g_free (temp_str);
1299 return NULL;
1302 if (info.assembly.name) {
1303 assembly = mono_assembly_load (&info.assembly, NULL, NULL);
1304 } else {
1305 MonoMethod *m = mono_method_get_last_managed ();
1306 MonoMethod *dest = m;
1308 mono_stack_walk_no_il (get_caller_no_reflection, &dest);
1309 if (!dest)
1310 dest = m;
1313 * FIXME: mono_method_get_last_managed() sometimes returns NULL, thus
1314 * causing ves_icall_System_Reflection_Assembly_GetCallingAssembly()
1315 * to crash. This only seems to happen in some strange remoting
1316 * scenarios and I was unable to figure out what's happening there.
1317 * Dec 10, 2005 - Martin.
1320 if (dest) {
1321 assembly = dest->klass->image->assembly;
1322 type_resolve = TRUE;
1323 } else {
1324 g_warning (G_STRLOC);
1328 if (assembly) {
1329 /* When loading from the current assembly, AppDomain.TypeResolve will not be called yet */
1330 type = mono_reflection_get_type (assembly->image, &info, ignoreCase, &type_resolve);
1333 if (!info.assembly.name && !type) /* try mscorlib */
1334 type = mono_reflection_get_type (NULL, &info, ignoreCase, &type_resolve);
1336 if (assembly && !type && type_resolve) {
1337 type_resolve = FALSE; /* This will invoke TypeResolve if not done in the first 'if' */
1338 type = mono_reflection_get_type (assembly->image, &info, ignoreCase, &type_resolve);
1341 mono_reflection_free_type_info (&info);
1342 g_free (temp_str);
1344 if (!type)
1345 return NULL;
1347 return mono_type_get_object (mono_domain_get (), type);
1350 #ifdef UNUSED
1351 MonoReflectionType *
1352 mono_type_get (const char *str)
1354 char *copy = g_strdup (str);
1355 MonoReflectionType *type = type_from_name (copy, FALSE);
1357 g_free (copy);
1358 return type;
1360 #endif
1362 static MonoReflectionType*
1363 ves_icall_type_from_name (MonoString *name,
1364 MonoBoolean throwOnError,
1365 MonoBoolean ignoreCase)
1367 char *str = mono_string_to_utf8 (name);
1368 MonoReflectionType *type;
1370 type = type_from_name (str, ignoreCase);
1371 g_free (str);
1372 if (type == NULL){
1373 MonoException *e = NULL;
1375 if (throwOnError)
1376 e = mono_get_exception_type_load (name, NULL);
1378 mono_loader_clear_error ();
1379 if (e != NULL)
1380 mono_raise_exception (e);
1383 return type;
1387 static MonoReflectionType*
1388 ves_icall_type_from_handle (MonoType *handle)
1390 MonoDomain *domain = mono_domain_get ();
1392 MONO_ARCH_SAVE_REGS;
1394 return mono_type_get_object (domain, handle);
1397 static MonoBoolean
1398 ves_icall_System_Type_EqualsInternal (MonoReflectionType *type, MonoReflectionType *c)
1400 MONO_ARCH_SAVE_REGS;
1402 if (c && type->type && c->type)
1403 return mono_metadata_type_equal (type->type, c->type);
1404 else
1405 return (type == c) ? TRUE : FALSE;
1408 /* System.TypeCode */
1409 typedef enum {
1410 TYPECODE_EMPTY,
1411 TYPECODE_OBJECT,
1412 TYPECODE_DBNULL,
1413 TYPECODE_BOOLEAN,
1414 TYPECODE_CHAR,
1415 TYPECODE_SBYTE,
1416 TYPECODE_BYTE,
1417 TYPECODE_INT16,
1418 TYPECODE_UINT16,
1419 TYPECODE_INT32,
1420 TYPECODE_UINT32,
1421 TYPECODE_INT64,
1422 TYPECODE_UINT64,
1423 TYPECODE_SINGLE,
1424 TYPECODE_DOUBLE,
1425 TYPECODE_DECIMAL,
1426 TYPECODE_DATETIME,
1427 TYPECODE_STRING = 18
1428 } TypeCode;
1430 static guint32
1431 ves_icall_type_GetTypeCodeInternal (MonoReflectionType *type)
1433 int t = type->type->type;
1435 MONO_ARCH_SAVE_REGS;
1437 if (type->type->byref)
1438 return TYPECODE_OBJECT;
1440 handle_enum:
1441 switch (t) {
1442 case MONO_TYPE_VOID:
1443 return TYPECODE_OBJECT;
1444 case MONO_TYPE_BOOLEAN:
1445 return TYPECODE_BOOLEAN;
1446 case MONO_TYPE_U1:
1447 return TYPECODE_BYTE;
1448 case MONO_TYPE_I1:
1449 return TYPECODE_SBYTE;
1450 case MONO_TYPE_U2:
1451 return TYPECODE_UINT16;
1452 case MONO_TYPE_I2:
1453 return TYPECODE_INT16;
1454 case MONO_TYPE_CHAR:
1455 return TYPECODE_CHAR;
1456 case MONO_TYPE_PTR:
1457 case MONO_TYPE_U:
1458 case MONO_TYPE_I:
1459 return TYPECODE_OBJECT;
1460 case MONO_TYPE_U4:
1461 return TYPECODE_UINT32;
1462 case MONO_TYPE_I4:
1463 return TYPECODE_INT32;
1464 case MONO_TYPE_U8:
1465 return TYPECODE_UINT64;
1466 case MONO_TYPE_I8:
1467 return TYPECODE_INT64;
1468 case MONO_TYPE_R4:
1469 return TYPECODE_SINGLE;
1470 case MONO_TYPE_R8:
1471 return TYPECODE_DOUBLE;
1472 case MONO_TYPE_VALUETYPE: {
1473 MonoClass *klass = type->type->data.klass;
1475 if (klass->enumtype) {
1476 t = mono_class_enum_basetype (klass)->type;
1477 goto handle_enum;
1478 } else if (mono_is_corlib_image (klass->image)) {
1479 if (strcmp (klass->name_space, "System") == 0) {
1480 if (strcmp (klass->name, "Decimal") == 0)
1481 return TYPECODE_DECIMAL;
1482 else if (strcmp (klass->name, "DateTime") == 0)
1483 return TYPECODE_DATETIME;
1486 return TYPECODE_OBJECT;
1488 case MONO_TYPE_STRING:
1489 return TYPECODE_STRING;
1490 case MONO_TYPE_SZARRAY:
1491 case MONO_TYPE_ARRAY:
1492 case MONO_TYPE_OBJECT:
1493 case MONO_TYPE_VAR:
1494 case MONO_TYPE_MVAR:
1495 case MONO_TYPE_TYPEDBYREF:
1496 return TYPECODE_OBJECT;
1497 case MONO_TYPE_CLASS:
1499 MonoClass *klass = type->type->data.klass;
1500 if (klass->image == mono_defaults.corlib && strcmp (klass->name_space, "System") == 0) {
1501 if (strcmp (klass->name, "DBNull") == 0)
1502 return TYPECODE_DBNULL;
1505 return TYPECODE_OBJECT;
1506 case MONO_TYPE_GENERICINST:
1507 return TYPECODE_OBJECT;
1508 default:
1509 g_error ("type 0x%02x not handled in GetTypeCode()", t);
1511 return 0;
1514 static guint32
1515 ves_icall_type_is_subtype_of (MonoReflectionType *type, MonoReflectionType *c, MonoBoolean check_interfaces)
1517 MonoDomain *domain;
1518 MonoClass *klass;
1519 MonoClass *klassc;
1521 MONO_ARCH_SAVE_REGS;
1523 g_assert (type != NULL);
1525 domain = ((MonoObject *)type)->vtable->domain;
1527 if (!c) /* FIXME: dont know what do do here */
1528 return 0;
1530 klass = mono_class_from_mono_type (type->type);
1531 klassc = mono_class_from_mono_type (c->type);
1533 /* Interface check requires a more complex setup so we
1534 * only do for them. Otherwise we simply avoid mono_class_init.
1536 if (check_interfaces) {
1537 mono_class_init_or_throw (klass);
1538 mono_class_init_or_throw (klassc);
1539 } else if (!klass->supertypes || !klassc->supertypes) {
1540 mono_loader_lock ();
1541 mono_class_setup_supertypes (klass);
1542 mono_class_setup_supertypes (klassc);
1543 mono_loader_unlock ();
1546 if (type->type->byref)
1547 return klassc == mono_defaults.object_class;
1549 return mono_class_is_subclass_of (klass, klassc, check_interfaces);
1552 static gboolean
1553 mono_type_is_primitive (MonoType *type)
1555 return (type->type >= MONO_TYPE_BOOLEAN && type->type <= MONO_TYPE_R8) ||
1556 type-> type == MONO_TYPE_I || type->type == MONO_TYPE_U;
1559 static MonoType*
1560 mono_type_get_underlying_type_ignore_byref (MonoType *type)
1562 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype)
1563 return mono_class_enum_basetype (type->data.klass);
1564 if (type->type == MONO_TYPE_GENERICINST && type->data.generic_class->container_class->enumtype)
1565 return mono_class_enum_basetype (type->data.generic_class->container_class);
1566 return type;
1569 static guint32
1570 ves_icall_type_is_assignable_from (MonoReflectionType *type, MonoReflectionType *c)
1572 MonoDomain *domain;
1573 MonoClass *klass;
1574 MonoClass *klassc;
1576 MONO_ARCH_SAVE_REGS;
1578 g_assert (type != NULL);
1580 domain = ((MonoObject *)type)->vtable->domain;
1582 klass = mono_class_from_mono_type (type->type);
1583 klassc = mono_class_from_mono_type (c->type);
1585 mono_class_init_or_throw (klass);
1586 mono_class_init_or_throw (klassc);
1588 if (type->type->byref ^ c->type->byref)
1589 return FALSE;
1591 if (type->type->byref) {
1592 MonoType *t = mono_type_get_underlying_type_ignore_byref (type->type);
1593 MonoType *ot = mono_type_get_underlying_type_ignore_byref (c->type);
1595 klass = mono_class_from_mono_type (t);
1596 klassc = mono_class_from_mono_type (ot);
1598 if (mono_type_is_primitive (t)) {
1599 return mono_type_is_primitive (ot) && klass->instance_size == klassc->instance_size;
1600 } else if (t->type == MONO_TYPE_VAR || t->type == MONO_TYPE_MVAR) {
1601 return t->type == ot->type && t->data.generic_param->num == ot->data.generic_param->num;
1602 } else if (t->type == MONO_TYPE_PTR || t->type == MONO_TYPE_FNPTR) {
1603 return t->type == ot->type;
1604 } else {
1605 if (ot->type == MONO_TYPE_VAR || ot->type == MONO_TYPE_MVAR)
1606 return FALSE;
1608 if (klass->valuetype)
1609 return klass == klassc;
1610 return klass->valuetype == klassc->valuetype;
1613 return mono_class_is_assignable_from (klass, klassc);
1616 static guint32
1617 ves_icall_type_IsInstanceOfType (MonoReflectionType *type, MonoObject *obj)
1619 MonoClass *klass = mono_class_from_mono_type (type->type);
1620 mono_class_init_or_throw (klass);
1621 return mono_object_isinst (obj, klass) != NULL;
1624 static guint32
1625 ves_icall_get_attributes (MonoReflectionType *type)
1627 MonoClass *klass = mono_class_from_mono_type (type->type);
1628 return klass->flags;
1631 static MonoReflectionMarshal*
1632 ves_icall_System_Reflection_FieldInfo_GetUnmanagedMarshal (MonoReflectionField *field)
1634 MonoClass *klass = field->field->parent;
1635 MonoMarshalType *info;
1636 int i;
1638 if (klass->generic_container ||
1639 (klass->generic_class && klass->generic_class->context.class_inst->is_open))
1640 return NULL;
1642 info = mono_marshal_load_type_info (klass);
1644 for (i = 0; i < info->num_fields; ++i) {
1645 if (info->fields [i].field == field->field) {
1646 if (!info->fields [i].mspec)
1647 return NULL;
1648 else
1649 return mono_reflection_marshal_from_marshal_spec (field->object.vtable->domain, klass, info->fields [i].mspec);
1653 return NULL;
1656 static MonoReflectionField*
1657 ves_icall_System_Reflection_FieldInfo_internal_from_handle_type (MonoClassField *handle, MonoType *type)
1659 gboolean found = FALSE;
1660 MonoClass *klass;
1661 MonoClass *k;
1663 g_assert (handle);
1665 if (!type) {
1666 klass = handle->parent;
1667 } else {
1668 klass = mono_class_from_mono_type (type);
1670 /* Check that the field belongs to the class */
1671 for (k = klass; k; k = k->parent) {
1672 if (k == handle->parent) {
1673 found = TRUE;
1674 break;
1678 if (!found)
1679 /* The managed code will throw the exception */
1680 return NULL;
1683 return mono_field_get_object (mono_domain_get (), klass, handle);
1686 static MonoArray*
1687 ves_icall_System_Reflection_FieldInfo_GetTypeModifiers (MonoReflectionField *field, MonoBoolean optional)
1689 MonoError error;
1690 MonoType *type = mono_field_get_type_checked (field->field, &error);
1691 if (!mono_error_ok (&error))
1692 mono_error_raise_exception (&error);
1694 return type_array_from_modifiers (field->field->parent->image, type, optional);
1697 static int
1698 vell_icall_get_method_attributes (MonoMethod *method)
1700 return method->flags;
1703 static void
1704 ves_icall_get_method_info (MonoMethod *method, MonoMethodInfo *info)
1706 MonoError error;
1707 MonoDomain *domain = mono_domain_get ();
1708 MonoMethodSignature* sig;
1709 MONO_ARCH_SAVE_REGS;
1711 sig = mono_method_signature_checked (method, &error);
1712 if (!mono_error_ok (&error))
1713 mono_error_raise_exception (&error);
1716 MONO_STRUCT_SETREF (info, parent, mono_type_get_object (domain, &method->klass->byval_arg));
1717 MONO_STRUCT_SETREF (info, ret, mono_type_get_object (domain, sig->ret));
1718 info->attrs = method->flags;
1719 info->implattrs = method->iflags;
1720 if (sig->call_convention == MONO_CALL_DEFAULT)
1721 info->callconv = sig->sentinelpos >= 0 ? 2 : 1;
1722 else {
1723 if (sig->call_convention == MONO_CALL_VARARG || sig->sentinelpos >= 0)
1724 info->callconv = 2;
1725 else
1726 info->callconv = 1;
1728 info->callconv |= (sig->hasthis << 5) | (sig->explicit_this << 6);
1731 static MonoArray*
1732 ves_icall_get_parameter_info (MonoMethod *method, MonoReflectionMethod *member)
1734 MonoDomain *domain = mono_domain_get ();
1736 return mono_param_get_objects_internal (domain, method, member->reftype ? mono_class_from_mono_type (member->reftype->type) : NULL);
1739 static MonoReflectionMarshal*
1740 ves_icall_System_MonoMethodInfo_get_retval_marshal (MonoMethod *method)
1742 MonoDomain *domain = mono_domain_get ();
1743 MonoReflectionMarshal* res = NULL;
1744 MonoMarshalSpec **mspecs;
1745 int i;
1747 mspecs = g_new (MonoMarshalSpec*, mono_method_signature (method)->param_count + 1);
1748 mono_method_get_marshal_info (method, mspecs);
1750 if (mspecs [0])
1751 res = mono_reflection_marshal_from_marshal_spec (domain, method->klass, mspecs [0]);
1753 for (i = mono_method_signature (method)->param_count; i >= 0; i--)
1754 if (mspecs [i])
1755 mono_metadata_free_marshal_spec (mspecs [i]);
1756 g_free (mspecs);
1758 return res;
1761 static gint32
1762 ves_icall_MonoField_GetFieldOffset (MonoReflectionField *field)
1764 MonoClass *parent = field->field->parent;
1765 if (!parent->size_inited)
1766 mono_class_init (parent);
1768 return field->field->offset - sizeof (MonoObject);
1771 static MonoReflectionType*
1772 ves_icall_MonoField_GetParentType (MonoReflectionField *field, MonoBoolean declaring)
1774 MonoClass *parent;
1775 MONO_ARCH_SAVE_REGS;
1777 parent = declaring? field->field->parent: field->klass;
1779 return mono_type_get_object (mono_object_domain (field), &parent->byval_arg);
1782 static MonoObject *
1783 ves_icall_MonoField_GetValueInternal (MonoReflectionField *field, MonoObject *obj)
1785 MonoClass *fklass = field->klass;
1786 MonoClassField *cf = field->field;
1787 MonoDomain *domain = mono_object_domain (field);
1789 if (fklass->image->assembly->ref_only)
1790 mono_raise_exception (mono_get_exception_invalid_operation (
1791 "It is illegal to get the value on a field on a type loaded using the ReflectionOnly methods."));
1793 if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR)
1794 mono_security_core_clr_ensure_reflection_access_field (cf);
1796 return mono_field_get_value_object (domain, cf, obj);
1799 static void
1800 ves_icall_MonoField_SetValueInternal (MonoReflectionField *field, MonoObject *obj, MonoObject *value)
1802 MonoClassField *cf = field->field;
1803 gchar *v;
1805 MONO_ARCH_SAVE_REGS;
1807 if (field->klass->image->assembly->ref_only)
1808 mono_raise_exception (mono_get_exception_invalid_operation (
1809 "It is illegal to set the value on a field on a type loaded using the ReflectionOnly methods."));
1811 if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR)
1812 mono_security_core_clr_ensure_reflection_access_field (cf);
1814 v = (gchar *) value;
1815 if (!cf->type->byref) {
1816 switch (cf->type->type) {
1817 case MONO_TYPE_U1:
1818 case MONO_TYPE_I1:
1819 case MONO_TYPE_BOOLEAN:
1820 case MONO_TYPE_U2:
1821 case MONO_TYPE_I2:
1822 case MONO_TYPE_CHAR:
1823 case MONO_TYPE_U:
1824 case MONO_TYPE_I:
1825 case MONO_TYPE_U4:
1826 case MONO_TYPE_I4:
1827 case MONO_TYPE_R4:
1828 case MONO_TYPE_U8:
1829 case MONO_TYPE_I8:
1830 case MONO_TYPE_R8:
1831 case MONO_TYPE_VALUETYPE:
1832 case MONO_TYPE_PTR:
1833 if (v != NULL)
1834 v += sizeof (MonoObject);
1835 break;
1836 case MONO_TYPE_STRING:
1837 case MONO_TYPE_OBJECT:
1838 case MONO_TYPE_CLASS:
1839 case MONO_TYPE_ARRAY:
1840 case MONO_TYPE_SZARRAY:
1841 /* Do nothing */
1842 break;
1843 case MONO_TYPE_GENERICINST: {
1844 MonoGenericClass *gclass = cf->type->data.generic_class;
1845 g_assert (!gclass->context.class_inst->is_open);
1847 if (mono_class_is_nullable (mono_class_from_mono_type (cf->type))) {
1848 MonoClass *nklass = mono_class_from_mono_type (cf->type);
1849 MonoObject *nullable;
1852 * Convert the boxed vtype into a Nullable structure.
1853 * This is complicated by the fact that Nullables have
1854 * a variable structure.
1856 nullable = mono_object_new (mono_domain_get (), nklass);
1858 mono_nullable_init (mono_object_unbox (nullable), value, nklass);
1860 v = mono_object_unbox (nullable);
1862 else
1863 if (gclass->container_class->valuetype && (v != NULL))
1864 v += sizeof (MonoObject);
1865 break;
1867 default:
1868 g_error ("type 0x%x not handled in "
1869 "ves_icall_FieldInfo_SetValueInternal", cf->type->type);
1870 return;
1874 if (cf->type->attrs & FIELD_ATTRIBUTE_STATIC) {
1875 MonoVTable *vtable = mono_class_vtable_full (mono_object_domain (field), cf->parent, TRUE);
1876 if (!vtable->initialized)
1877 mono_runtime_class_init (vtable);
1878 mono_field_static_set_value (vtable, cf, v);
1879 } else {
1880 mono_field_set_value (obj, cf, v);
1884 static MonoObject *
1885 ves_icall_MonoField_GetRawConstantValue (MonoReflectionField *this)
1887 MonoObject *o = NULL;
1888 MonoClassField *field = this->field;
1889 MonoClass *klass;
1890 MonoDomain *domain = mono_object_domain (this);
1891 gchar *v;
1892 MonoTypeEnum def_type;
1893 const char *def_value;
1895 MONO_ARCH_SAVE_REGS;
1897 mono_class_init (field->parent);
1899 if (!(field->type->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT))
1900 mono_raise_exception (mono_get_exception_invalid_operation (NULL));
1902 if (field->parent->image->dynamic) {
1903 /* FIXME: */
1904 g_assert_not_reached ();
1907 def_value = mono_class_get_field_default_value (field, &def_type);
1909 /*FIXME unify this with reflection.c:mono_get_object_from_blob*/
1910 switch (def_type) {
1911 case MONO_TYPE_U1:
1912 case MONO_TYPE_I1:
1913 case MONO_TYPE_BOOLEAN:
1914 case MONO_TYPE_U2:
1915 case MONO_TYPE_I2:
1916 case MONO_TYPE_CHAR:
1917 case MONO_TYPE_U:
1918 case MONO_TYPE_I:
1919 case MONO_TYPE_U4:
1920 case MONO_TYPE_I4:
1921 case MONO_TYPE_R4:
1922 case MONO_TYPE_U8:
1923 case MONO_TYPE_I8:
1924 case MONO_TYPE_R8: {
1925 MonoType *t;
1927 /* boxed value type */
1928 t = g_new0 (MonoType, 1);
1929 t->type = def_type;
1930 klass = mono_class_from_mono_type (t);
1931 g_free (t);
1932 o = mono_object_new (domain, klass);
1933 v = ((gchar *) o) + sizeof (MonoObject);
1934 mono_get_constant_value_from_blob (domain, def_type, def_value, v);
1935 break;
1937 case MONO_TYPE_STRING:
1938 case MONO_TYPE_CLASS:
1939 mono_get_constant_value_from_blob (domain, def_type, def_value, &o);
1940 break;
1941 default:
1942 g_assert_not_reached ();
1945 return o;
1948 static MonoReflectionType*
1949 ves_icall_MonoField_ResolveType (MonoReflectionField *ref_field)
1951 MonoError error;
1952 MonoClassField *field = ref_field->field;
1953 MonoType *type = mono_field_get_type_checked (field, &error);
1954 if (!mono_error_ok (&error))
1955 mono_error_raise_exception (&error);
1956 return mono_type_get_object (mono_object_domain (ref_field), type);
1959 static MonoReflectionType*
1960 ves_icall_MonoGenericMethod_get_ReflectedType (MonoReflectionGenericMethod *rmethod)
1962 MonoMethod *method = rmethod->method.method;
1964 return mono_type_get_object (mono_object_domain (rmethod), &method->klass->byval_arg);
1967 /* From MonoProperty.cs */
1968 typedef enum {
1969 PInfo_Attributes = 1,
1970 PInfo_GetMethod = 1 << 1,
1971 PInfo_SetMethod = 1 << 2,
1972 PInfo_ReflectedType = 1 << 3,
1973 PInfo_DeclaringType = 1 << 4,
1974 PInfo_Name = 1 << 5
1975 } PInfo;
1977 static void
1978 ves_icall_get_property_info (MonoReflectionProperty *property, MonoPropertyInfo *info, PInfo req_info)
1980 MonoDomain *domain = mono_object_domain (property);
1982 MONO_ARCH_SAVE_REGS;
1984 if ((req_info & PInfo_ReflectedType) != 0)
1985 MONO_STRUCT_SETREF (info, parent, mono_type_get_object (domain, &property->klass->byval_arg));
1986 if ((req_info & PInfo_DeclaringType) != 0)
1987 MONO_STRUCT_SETREF (info, declaring_type, mono_type_get_object (domain, &property->property->parent->byval_arg));
1989 if ((req_info & PInfo_Name) != 0)
1990 MONO_STRUCT_SETREF (info, name, mono_string_new (domain, property->property->name));
1992 if ((req_info & PInfo_Attributes) != 0)
1993 info->attrs = property->property->attrs;
1995 if ((req_info & PInfo_GetMethod) != 0)
1996 MONO_STRUCT_SETREF (info, get, property->property->get ?
1997 mono_method_get_object (domain, property->property->get, property->klass): NULL);
1999 if ((req_info & PInfo_SetMethod) != 0)
2000 MONO_STRUCT_SETREF (info, set, property->property->set ?
2001 mono_method_get_object (domain, property->property->set, property->klass): NULL);
2003 * There may be other methods defined for properties, though, it seems they are not exposed
2004 * in the reflection API
2008 static void
2009 ves_icall_get_event_info (MonoReflectionMonoEvent *event, MonoEventInfo *info)
2011 MonoDomain *domain = mono_object_domain (event);
2013 MONO_ARCH_SAVE_REGS;
2015 MONO_STRUCT_SETREF (info, reflected_type, mono_type_get_object (domain, &event->klass->byval_arg));
2016 MONO_STRUCT_SETREF (info, declaring_type, mono_type_get_object (domain, &event->event->parent->byval_arg));
2018 MONO_STRUCT_SETREF (info, name, mono_string_new (domain, event->event->name));
2019 info->attrs = event->event->attrs;
2020 MONO_STRUCT_SETREF (info, add_method, event->event->add ? mono_method_get_object (domain, event->event->add, NULL): NULL);
2021 MONO_STRUCT_SETREF (info, remove_method, event->event->remove ? mono_method_get_object (domain, event->event->remove, NULL): NULL);
2022 MONO_STRUCT_SETREF (info, raise_method, event->event->raise ? mono_method_get_object (domain, event->event->raise, NULL): NULL);
2024 #ifndef MONO_SMALL_CONFIG
2025 if (event->event->other) {
2026 int i, n = 0;
2027 while (event->event->other [n])
2028 n++;
2029 MONO_STRUCT_SETREF (info, other_methods, mono_array_new (domain, mono_defaults.method_info_class, n));
2031 for (i = 0; i < n; i++)
2032 mono_array_setref (info->other_methods, i, mono_method_get_object (domain, event->event->other [i], NULL));
2034 #endif
2037 static void
2038 collect_interfaces (MonoClass *klass, GHashTable *ifaces, MonoError *error)
2040 int i;
2041 MonoClass *ic;
2043 mono_class_setup_interfaces (klass, error);
2044 if (!mono_error_ok (error))
2045 return;
2047 for (i = 0; i < klass->interface_count; i++) {
2048 ic = klass->interfaces [i];
2049 g_hash_table_insert (ifaces, ic, ic);
2051 collect_interfaces (ic, ifaces, error);
2052 if (!mono_error_ok (error))
2053 return;
2057 typedef struct {
2058 MonoArray *iface_array;
2059 MonoGenericContext *context;
2060 MonoError *error;
2061 MonoDomain *domain;
2062 int next_idx;
2063 } FillIfaceArrayData;
2065 static void
2066 fill_iface_array (gpointer key, gpointer value, gpointer user_data)
2068 FillIfaceArrayData *data = user_data;
2069 MonoClass *ic = key;
2070 MonoType *ret = &ic->byval_arg, *inflated = NULL;
2072 if (!mono_error_ok (data->error))
2073 return;
2075 if (data->context && ic->generic_class && ic->generic_class->context.class_inst->is_open) {
2076 inflated = ret = mono_class_inflate_generic_type_checked (ret, data->context, data->error);
2077 if (!mono_error_ok (data->error))
2078 return;
2081 mono_array_setref (data->iface_array, data->next_idx++, mono_type_get_object (data->domain, ret));
2083 if (inflated)
2084 mono_metadata_free_type (inflated);
2087 static MonoArray*
2088 ves_icall_Type_GetInterfaces (MonoReflectionType* type)
2090 MonoError error;
2091 MonoClass *class = mono_class_from_mono_type (type->type);
2092 MonoClass *parent;
2093 FillIfaceArrayData data = { 0 };
2094 int len;
2096 GHashTable *iface_hash = g_hash_table_new (NULL, NULL);
2098 if (class->generic_class && class->generic_class->context.class_inst->is_open) {
2099 data.context = mono_class_get_context (class);
2100 class = class->generic_class->container_class;
2103 for (parent = class; parent; parent = parent->parent) {
2104 mono_class_setup_interfaces (parent, &error);
2105 if (!mono_error_ok (&error))
2106 goto fail;
2107 collect_interfaces (parent, iface_hash, &error);
2108 if (!mono_error_ok (&error))
2109 goto fail;
2112 data.error = &error;
2113 data.domain = mono_object_domain (type);
2115 len = g_hash_table_size (iface_hash);
2116 if (len == 0) {
2117 g_hash_table_destroy (iface_hash);
2118 if (!data.domain->empty_types)
2119 data.domain->empty_types = mono_array_new_cached (data.domain, mono_defaults.monotype_class, 0);
2120 return data.domain->empty_types;
2123 data.iface_array = mono_array_new_cached (data.domain, mono_defaults.monotype_class, len);
2124 g_hash_table_foreach (iface_hash, fill_iface_array, &data);
2125 if (!mono_error_ok (&error))
2126 goto fail;
2128 g_hash_table_destroy (iface_hash);
2129 return data.iface_array;
2131 fail:
2132 g_hash_table_destroy (iface_hash);
2133 mono_error_raise_exception (&error);
2134 return NULL;
2137 static void
2138 ves_icall_Type_GetInterfaceMapData (MonoReflectionType *type, MonoReflectionType *iface, MonoArray **targets, MonoArray **methods)
2140 gboolean variance_used;
2141 MonoClass *class = mono_class_from_mono_type (type->type);
2142 MonoClass *iclass = mono_class_from_mono_type (iface->type);
2143 MonoReflectionMethod *member;
2144 MonoMethod* method;
2145 gpointer iter;
2146 int i = 0, len, ioffset;
2147 MonoDomain *domain;
2149 MONO_ARCH_SAVE_REGS;
2150 mono_class_init_or_throw (class);
2151 mono_class_init_or_throw (iclass);
2153 mono_class_setup_vtable (class);
2155 ioffset = mono_class_interface_offset_with_variance (class, iclass, &variance_used);
2156 if (ioffset == -1)
2157 return;
2159 len = mono_class_num_methods (iclass);
2160 domain = mono_object_domain (type);
2161 mono_gc_wbarrier_generic_store (targets, (MonoObject*) mono_array_new (domain, mono_defaults.method_info_class, len));
2162 mono_gc_wbarrier_generic_store (methods, (MonoObject*) mono_array_new (domain, mono_defaults.method_info_class, len));
2163 iter = NULL;
2164 while ((method = mono_class_get_methods (iclass, &iter))) {
2165 member = mono_method_get_object (domain, method, iclass);
2166 mono_array_setref (*methods, i, member);
2167 member = mono_method_get_object (domain, class->vtable [i + ioffset], class);
2168 mono_array_setref (*targets, i, member);
2170 i ++;
2174 static void
2175 ves_icall_Type_GetPacking (MonoReflectionType *type, guint32 *packing, guint32 *size)
2177 MonoClass *klass = mono_class_from_mono_type (type->type);
2178 mono_class_init_or_throw (klass);
2180 if (klass->image->dynamic) {
2181 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)type;
2182 *packing = tb->packing_size;
2183 *size = tb->class_size;
2184 } else {
2185 mono_metadata_packing_from_typedef (klass->image, klass->type_token, packing, size);
2189 static MonoReflectionType*
2190 ves_icall_MonoType_GetElementType (MonoReflectionType *type)
2192 MonoClass *class;
2194 MONO_ARCH_SAVE_REGS;
2196 if (!type->type->byref && type->type->type == MONO_TYPE_SZARRAY)
2197 return mono_type_get_object (mono_object_domain (type), &type->type->data.klass->byval_arg);
2199 class = mono_class_from_mono_type (type->type);
2200 mono_class_init_or_throw (class);
2202 // GetElementType should only return a type for:
2203 // Array Pointer PassedByRef
2204 if (type->type->byref)
2205 return mono_type_get_object (mono_object_domain (type), &class->byval_arg);
2206 else if (class->element_class && MONO_CLASS_IS_ARRAY (class))
2207 return mono_type_get_object (mono_object_domain (type), &class->element_class->byval_arg);
2208 else if (class->element_class && type->type->type == MONO_TYPE_PTR)
2209 return mono_type_get_object (mono_object_domain (type), &class->element_class->byval_arg);
2210 else
2211 return NULL;
2214 static MonoReflectionType*
2215 ves_icall_get_type_parent (MonoReflectionType *type)
2217 MonoClass *class = mono_class_from_mono_type (type->type);
2218 return class->parent ? mono_type_get_object (mono_object_domain (type), &class->parent->byval_arg): NULL;
2221 static MonoBoolean
2222 ves_icall_type_ispointer (MonoReflectionType *type)
2224 MONO_ARCH_SAVE_REGS;
2226 return type->type->type == MONO_TYPE_PTR;
2229 static MonoBoolean
2230 ves_icall_type_isprimitive (MonoReflectionType *type)
2232 MONO_ARCH_SAVE_REGS;
2234 return (!type->type->byref && (((type->type->type >= MONO_TYPE_BOOLEAN) && (type->type->type <= MONO_TYPE_R8)) || (type->type->type == MONO_TYPE_I) || (type->type->type == MONO_TYPE_U)));
2237 static MonoBoolean
2238 ves_icall_type_isbyref (MonoReflectionType *type)
2240 MONO_ARCH_SAVE_REGS;
2242 return type->type->byref;
2245 static MonoBoolean
2246 ves_icall_type_iscomobject (MonoReflectionType *type)
2248 MonoClass *klass = mono_class_from_mono_type (type->type);
2249 mono_class_init_or_throw (klass);
2251 return (klass && klass->is_com_object);
2254 static MonoReflectionModule*
2255 ves_icall_MonoType_get_Module (MonoReflectionType *type)
2257 MonoClass *class = mono_class_from_mono_type (type->type);
2258 return mono_module_get_object (mono_object_domain (type), class->image);
2261 static MonoReflectionAssembly*
2262 ves_icall_MonoType_get_Assembly (MonoReflectionType *type)
2264 MonoDomain *domain = mono_domain_get ();
2265 MonoClass *class = mono_class_from_mono_type (type->type);
2266 return mono_assembly_get_object (domain, class->image->assembly);
2269 static MonoReflectionType*
2270 ves_icall_MonoType_get_DeclaringType (MonoReflectionType *type)
2272 MonoDomain *domain = mono_domain_get ();
2273 MonoClass *class;
2275 MONO_ARCH_SAVE_REGS;
2277 if (type->type->byref)
2278 return NULL;
2279 if (type->type->type == MONO_TYPE_VAR)
2280 class = mono_type_get_generic_param_owner (type->type)->owner.klass;
2281 else if (type->type->type == MONO_TYPE_MVAR)
2282 class = mono_type_get_generic_param_owner (type->type)->owner.method->klass;
2283 else
2284 class = mono_class_from_mono_type (type->type)->nested_in;
2286 return class ? mono_type_get_object (domain, &class->byval_arg) : NULL;
2289 static MonoString*
2290 ves_icall_MonoType_get_Name (MonoReflectionType *type)
2292 MonoDomain *domain = mono_domain_get ();
2293 MonoClass *class = mono_class_from_mono_type (type->type);
2295 if (type->type->byref) {
2296 char *n = g_strdup_printf ("%s&", class->name);
2297 MonoString *res = mono_string_new (domain, n);
2299 g_free (n);
2301 return res;
2302 } else {
2303 return mono_string_new (domain, class->name);
2307 static MonoString*
2308 ves_icall_MonoType_get_Namespace (MonoReflectionType *type)
2310 MonoDomain *domain = mono_domain_get ();
2311 MonoClass *class = mono_class_from_mono_type (type->type);
2313 while (class->nested_in)
2314 class = class->nested_in;
2316 if (class->name_space [0] == '\0')
2317 return NULL;
2318 else
2319 return mono_string_new (domain, class->name_space);
2322 static gint32
2323 ves_icall_MonoType_GetArrayRank (MonoReflectionType *type)
2325 MonoClass *class;
2327 if (type->type->type != MONO_TYPE_ARRAY && type->type->type != MONO_TYPE_SZARRAY)
2328 mono_raise_exception (mono_get_exception_argument ("type", "Type must be an array type"));
2330 class = mono_class_from_mono_type (type->type);
2332 return class->rank;
2335 static MonoArray*
2336 ves_icall_MonoType_GetGenericArguments (MonoReflectionType *type)
2338 MonoArray *res;
2339 MonoClass *klass, *pklass;
2340 MonoDomain *domain = mono_object_domain (type);
2341 MonoVTable *array_vtable = mono_class_vtable_full (domain, mono_array_class_get_cached (mono_defaults.systemtype_class, 1), TRUE);
2342 int i;
2343 MONO_ARCH_SAVE_REGS;
2345 klass = mono_class_from_mono_type (type->type);
2347 if (klass->generic_container) {
2348 MonoGenericContainer *container = klass->generic_container;
2349 res = mono_array_new_specific (array_vtable, container->type_argc);
2350 for (i = 0; i < container->type_argc; ++i) {
2351 pklass = mono_class_from_generic_parameter (mono_generic_container_get_param (container, i), klass->image, FALSE);
2352 mono_array_setref (res, i, mono_type_get_object (domain, &pklass->byval_arg));
2354 } else if (klass->generic_class) {
2355 MonoGenericInst *inst = klass->generic_class->context.class_inst;
2356 res = mono_array_new_specific (array_vtable, inst->type_argc);
2357 for (i = 0; i < inst->type_argc; ++i)
2358 mono_array_setref (res, i, mono_type_get_object (domain, inst->type_argv [i]));
2359 } else {
2360 res = mono_array_new_specific (array_vtable, 0);
2362 return res;
2365 static gboolean
2366 ves_icall_Type_get_IsGenericTypeDefinition (MonoReflectionType *type)
2368 MonoClass *klass;
2369 MONO_ARCH_SAVE_REGS;
2371 if (!IS_MONOTYPE (type))
2372 return FALSE;
2374 if (type->type->byref)
2375 return FALSE;
2377 klass = mono_class_from_mono_type (type->type);
2378 return klass->generic_container != NULL;
2381 static MonoReflectionType*
2382 ves_icall_Type_GetGenericTypeDefinition_impl (MonoReflectionType *type)
2384 MonoClass *klass;
2385 MONO_ARCH_SAVE_REGS;
2387 if (type->type->byref)
2388 return NULL;
2390 klass = mono_class_from_mono_type (type->type);
2392 if (klass->generic_container) {
2393 return type; /* check this one */
2395 if (klass->generic_class) {
2396 MonoClass *generic_class = klass->generic_class->container_class;
2397 gpointer tb;
2399 tb = mono_class_get_ref_info (generic_class);
2401 if (generic_class->wastypebuilder && tb)
2402 return tb;
2403 else
2404 return mono_type_get_object (mono_object_domain (type), &generic_class->byval_arg);
2406 return NULL;
2409 static MonoReflectionType*
2410 ves_icall_Type_MakeGenericType (MonoReflectionType *type, MonoArray *type_array)
2412 MonoType *geninst, **types;
2413 int i, count;
2415 g_assert (IS_MONOTYPE (type));
2416 mono_class_init_or_throw (mono_class_from_mono_type (type->type));
2418 count = mono_array_length (type_array);
2419 types = g_new0 (MonoType *, count);
2421 for (i = 0; i < count; i++) {
2422 MonoReflectionType *t = mono_array_get (type_array, gpointer, i);
2423 types [i] = t->type;
2426 geninst = mono_reflection_bind_generic_parameters (type, count, types);
2427 g_free (types);
2428 if (!geninst)
2429 return NULL;
2431 return mono_type_get_object (mono_object_domain (type), geninst);
2434 static gboolean
2435 ves_icall_Type_get_IsGenericInstance (MonoReflectionType *type)
2437 MonoClass *klass;
2438 MONO_ARCH_SAVE_REGS;
2440 if (type->type->byref)
2441 return FALSE;
2443 klass = mono_class_from_mono_type (type->type);
2445 return klass->generic_class != NULL;
2448 static gboolean
2449 ves_icall_Type_get_IsGenericType (MonoReflectionType *type)
2451 MonoClass *klass;
2452 MONO_ARCH_SAVE_REGS;
2454 if (!IS_MONOTYPE (type))
2455 return FALSE;
2457 if (type->type->byref)
2458 return FALSE;
2460 klass = mono_class_from_mono_type (type->type);
2461 return klass->generic_class != NULL || klass->generic_container != NULL;
2464 static gint32
2465 ves_icall_Type_GetGenericParameterPosition (MonoReflectionType *type)
2467 MONO_ARCH_SAVE_REGS;
2469 if (!IS_MONOTYPE (type))
2470 return -1;
2472 if (is_generic_parameter (type->type))
2473 return mono_type_get_generic_param_num (type->type);
2474 return -1;
2477 static GenericParameterAttributes
2478 ves_icall_Type_GetGenericParameterAttributes (MonoReflectionType *type)
2480 MONO_ARCH_SAVE_REGS;
2482 g_assert (IS_MONOTYPE (type));
2483 g_assert (is_generic_parameter (type->type));
2484 return mono_generic_param_info (type->type->data.generic_param)->flags;
2487 static MonoArray *
2488 ves_icall_Type_GetGenericParameterConstraints (MonoReflectionType *type)
2490 MonoGenericParamInfo *param_info;
2491 MonoDomain *domain;
2492 MonoClass **ptr;
2493 MonoArray *res;
2494 int i, count;
2496 MONO_ARCH_SAVE_REGS;
2498 g_assert (IS_MONOTYPE (type));
2500 domain = mono_object_domain (type);
2501 param_info = mono_generic_param_info (type->type->data.generic_param);
2502 for (count = 0, ptr = param_info->constraints; ptr && *ptr; ptr++, count++)
2505 res = mono_array_new (domain, mono_defaults.monotype_class, count);
2506 for (i = 0; i < count; i++)
2507 mono_array_setref (res, i, mono_type_get_object (domain, &param_info->constraints [i]->byval_arg));
2510 return res;
2513 static MonoBoolean
2514 ves_icall_MonoType_get_IsGenericParameter (MonoReflectionType *type)
2516 MONO_ARCH_SAVE_REGS;
2517 return is_generic_parameter (type->type);
2520 static MonoBoolean
2521 ves_icall_TypeBuilder_get_IsGenericParameter (MonoReflectionTypeBuilder *tb)
2523 MONO_ARCH_SAVE_REGS;
2524 return is_generic_parameter (tb->type.type);
2527 static void
2528 ves_icall_EnumBuilder_setup_enum_type (MonoReflectionType *enumtype,
2529 MonoReflectionType *t)
2531 enumtype->type = t->type;
2534 static MonoReflectionMethod*
2535 ves_icall_MonoType_GetCorrespondingInflatedMethod (MonoReflectionType *type,
2536 MonoReflectionMethod* generic)
2538 MonoDomain *domain;
2539 MonoClass *klass;
2540 MonoMethod *method;
2541 gpointer iter;
2543 MONO_ARCH_SAVE_REGS;
2545 domain = ((MonoObject *)type)->vtable->domain;
2547 klass = mono_class_from_mono_type (type->type);
2548 mono_class_init_or_throw (klass);
2550 iter = NULL;
2551 while ((method = mono_class_get_methods (klass, &iter))) {
2552 if (method->token == generic->method->token)
2553 return mono_method_get_object (domain, method, klass);
2556 return NULL;
2561 static MonoReflectionMethod *
2562 ves_icall_MonoType_get_DeclaringMethod (MonoReflectionType *ref_type)
2564 MonoMethod *method;
2565 MonoType *type = ref_type->type;
2567 MONO_ARCH_SAVE_REGS;
2569 if (type->byref || (type->type != MONO_TYPE_MVAR && type->type != MONO_TYPE_VAR))
2570 mono_raise_exception (mono_get_exception_invalid_operation ("DeclaringMethod can only be used on generic arguments"));
2571 if (type->type == MONO_TYPE_VAR)
2572 return NULL;
2574 method = mono_type_get_generic_param_owner (type)->owner.method;
2575 g_assert (method);
2576 return mono_method_get_object (mono_object_domain (ref_type), method, method->klass);
2579 static MonoReflectionDllImportAttribute*
2580 ves_icall_MonoMethod_GetDllImportAttribute (MonoMethod *method)
2582 static MonoClass *DllImportAttributeClass = NULL;
2583 MonoDomain *domain = mono_domain_get ();
2584 MonoReflectionDllImportAttribute *attr;
2585 MonoImage *image = method->klass->image;
2586 MonoMethodPInvoke *piinfo = (MonoMethodPInvoke *)method;
2587 MonoTableInfo *tables = image->tables;
2588 MonoTableInfo *im = &tables [MONO_TABLE_IMPLMAP];
2589 MonoTableInfo *mr = &tables [MONO_TABLE_MODULEREF];
2590 guint32 im_cols [MONO_IMPLMAP_SIZE];
2591 guint32 scope_token;
2592 const char *import = NULL;
2593 const char *scope = NULL;
2594 guint32 flags;
2596 if (!(method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
2597 return NULL;
2599 if (!DllImportAttributeClass) {
2600 DllImportAttributeClass =
2601 mono_class_from_name (mono_defaults.corlib,
2602 "System.Runtime.InteropServices", "DllImportAttribute");
2603 g_assert (DllImportAttributeClass);
2606 if (method->klass->image->dynamic) {
2607 MonoReflectionMethodAux *method_aux =
2608 g_hash_table_lookup (
2609 ((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
2610 if (method_aux) {
2611 import = method_aux->dllentry;
2612 scope = method_aux->dll;
2615 if (!import || !scope) {
2616 mono_raise_exception (mono_get_exception_argument ("method", "System.Reflection.Emit method with invalid pinvoke information"));
2617 return NULL;
2620 else {
2621 if (piinfo->implmap_idx) {
2622 mono_metadata_decode_row (im, piinfo->implmap_idx - 1, im_cols, MONO_IMPLMAP_SIZE);
2624 piinfo->piflags = im_cols [MONO_IMPLMAP_FLAGS];
2625 import = mono_metadata_string_heap (image, im_cols [MONO_IMPLMAP_NAME]);
2626 scope_token = mono_metadata_decode_row_col (mr, im_cols [MONO_IMPLMAP_SCOPE] - 1, MONO_MODULEREF_NAME);
2627 scope = mono_metadata_string_heap (image, scope_token);
2630 flags = piinfo->piflags;
2632 attr = (MonoReflectionDllImportAttribute*)mono_object_new (domain, DllImportAttributeClass);
2634 MONO_OBJECT_SETREF (attr, dll, mono_string_new (domain, scope));
2635 MONO_OBJECT_SETREF (attr, entry_point, mono_string_new (domain, import));
2636 attr->call_conv = (flags & 0x700) >> 8;
2637 attr->charset = ((flags & 0x6) >> 1) + 1;
2638 if (attr->charset == 1)
2639 attr->charset = 2;
2640 attr->exact_spelling = (flags & 0x1) != 0;
2641 attr->set_last_error = (flags & 0x40) != 0;
2642 attr->best_fit_mapping = (flags & 0x30) == 0x10;
2643 attr->throw_on_unmappable = (flags & 0x3000) == 0x1000;
2644 attr->preserve_sig = FALSE;
2646 return attr;
2649 static MonoReflectionMethod *
2650 ves_icall_MonoMethod_GetGenericMethodDefinition (MonoReflectionMethod *method)
2652 MonoMethodInflated *imethod;
2653 MonoMethod *result;
2655 MONO_ARCH_SAVE_REGS;
2657 if (method->method->is_generic)
2658 return method;
2660 if (!method->method->is_inflated)
2661 return NULL;
2663 imethod = (MonoMethodInflated *) method->method;
2665 result = imethod->declaring;
2666 /* Not a generic method. */
2667 if (!result->is_generic)
2668 return NULL;
2670 if (method->method->klass->image->dynamic) {
2671 MonoDynamicImage *image = (MonoDynamicImage*)method->method->klass->image;
2672 MonoReflectionMethod *res;
2675 * FIXME: Why is this stuff needed at all ? Why can't the code below work for
2676 * the dynamic case as well ?
2678 mono_loader_lock ();
2679 res = mono_g_hash_table_lookup (image->generic_def_objects, imethod);
2680 mono_loader_unlock ();
2682 if (res)
2683 return res;
2686 if (imethod->context.class_inst) {
2687 MonoClass *klass = ((MonoMethod *) imethod)->klass;
2688 /*Generic methods gets the context of the GTD.*/
2689 if (mono_class_get_context (klass))
2690 result = mono_class_inflate_generic_method_full (result, klass, mono_class_get_context (klass));
2693 return mono_method_get_object (mono_object_domain (method), result, NULL);
2696 static gboolean
2697 ves_icall_MonoMethod_get_IsGenericMethod (MonoReflectionMethod *method)
2699 MONO_ARCH_SAVE_REGS;
2701 return mono_method_signature (method->method)->generic_param_count != 0;
2704 static gboolean
2705 ves_icall_MonoMethod_get_IsGenericMethodDefinition (MonoReflectionMethod *method)
2707 MONO_ARCH_SAVE_REGS;
2709 return method->method->is_generic;
2712 static MonoArray*
2713 ves_icall_MonoMethod_GetGenericArguments (MonoReflectionMethod *method)
2715 MonoArray *res;
2716 MonoDomain *domain;
2717 int count, i;
2718 MONO_ARCH_SAVE_REGS;
2720 domain = mono_object_domain (method);
2722 if (method->method->is_inflated) {
2723 MonoGenericInst *inst = mono_method_get_context (method->method)->method_inst;
2725 if (inst) {
2726 count = inst->type_argc;
2727 res = mono_array_new (domain, mono_defaults.systemtype_class, count);
2729 for (i = 0; i < count; i++)
2730 mono_array_setref (res, i, mono_type_get_object (domain, inst->type_argv [i]));
2732 return res;
2736 count = mono_method_signature (method->method)->generic_param_count;
2737 res = mono_array_new (domain, mono_defaults.systemtype_class, count);
2739 for (i = 0; i < count; i++) {
2740 MonoGenericContainer *container = mono_method_get_generic_container (method->method);
2741 MonoGenericParam *param = mono_generic_container_get_param (container, i);
2742 MonoClass *pklass = mono_class_from_generic_parameter (
2743 param, method->method->klass->image, TRUE);
2744 mono_array_setref (res, i,
2745 mono_type_get_object (domain, &pklass->byval_arg));
2748 return res;
2751 static MonoObject *
2752 ves_icall_InternalInvoke (MonoReflectionMethod *method, MonoObject *this, MonoArray *params, MonoException **exc)
2755 * Invoke from reflection is supposed to always be a virtual call (the API
2756 * is stupid), mono_runtime_invoke_*() calls the provided method, allowing
2757 * greater flexibility.
2759 MonoMethod *m = method->method;
2760 int pcount;
2761 void *obj = this;
2763 MONO_ARCH_SAVE_REGS;
2765 *exc = NULL;
2767 if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR)
2768 mono_security_core_clr_ensure_reflection_access_method (m);
2770 if (!(m->flags & METHOD_ATTRIBUTE_STATIC)) {
2771 if (!mono_class_vtable_full (mono_object_domain (method), m->klass, FALSE)) {
2772 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_class_get_exception_for_failure (m->klass));
2773 return NULL;
2776 if (this) {
2777 if (!mono_object_isinst (this, m->klass)) {
2778 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", "Object does not match target type."));
2779 return NULL;
2781 m = mono_object_get_virtual_method (this, m);
2782 /* must pass the pointer to the value for valuetype methods */
2783 if (m->klass->valuetype)
2784 obj = mono_object_unbox (this);
2785 } else if (strcmp (m->name, ".ctor") && !m->wrapper_type) {
2786 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", "Non-static method requires a target."));
2787 return NULL;
2791 pcount = params? mono_array_length (params): 0;
2792 if (pcount != mono_method_signature (m)->param_count) {
2793 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name (mono_defaults.corlib, "System.Reflection", "TargetParameterCountException"));
2794 return NULL;
2797 if ((m->klass->flags & TYPE_ATTRIBUTE_ABSTRACT) && !strcmp (m->name, ".ctor") && !this) {
2798 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", "Cannot invoke constructor of an abstract class."));
2799 return NULL;
2802 if (m->klass->image->assembly->ref_only) {
2803 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_get_exception_invalid_operation ("It is illegal to invoke a method on a type loaded using the ReflectionOnly api."));
2804 return NULL;
2807 if (m->klass->rank && !strcmp (m->name, ".ctor")) {
2808 int i;
2809 uintptr_t *lengths;
2810 intptr_t *lower_bounds;
2811 pcount = mono_array_length (params);
2812 lengths = alloca (sizeof (uintptr_t) * pcount);
2813 /* Note: the synthetized array .ctors have int32 as argument type */
2814 for (i = 0; i < pcount; ++i)
2815 lengths [i] = *(int32_t*) ((char*)mono_array_get (params, gpointer, i) + sizeof (MonoObject));
2817 if (m->klass->rank == pcount) {
2818 /* Only lengths provided. */
2819 lower_bounds = NULL;
2820 } else {
2821 g_assert (pcount == (m->klass->rank * 2));
2822 /* lower bounds are first. */
2823 lower_bounds = (intptr_t*)lengths;
2824 lengths += m->klass->rank;
2827 return (MonoObject*)mono_array_new_full (mono_object_domain (params), m->klass, lengths, lower_bounds);
2829 return mono_runtime_invoke_array (m, obj, params, NULL);
2832 static MonoObject *
2833 ves_icall_InternalExecute (MonoReflectionMethod *method, MonoObject *this, MonoArray *params, MonoArray **outArgs)
2835 MonoDomain *domain = mono_object_domain (method);
2836 MonoMethod *m = method->method;
2837 MonoMethodSignature *sig = mono_method_signature (m);
2838 MonoArray *out_args;
2839 MonoObject *result;
2840 int i, j, outarg_count = 0;
2842 MONO_ARCH_SAVE_REGS;
2844 if (m->klass == mono_defaults.object_class) {
2846 if (!strcmp (m->name, "FieldGetter")) {
2847 MonoClass *k = this->vtable->klass;
2848 MonoString *name;
2849 char *str;
2851 /* If this is a proxy, then it must be a CBO */
2852 if (k == mono_defaults.transparent_proxy_class) {
2853 MonoTransparentProxy *tp = (MonoTransparentProxy*) this;
2854 this = tp->rp->unwrapped_server;
2855 g_assert (this);
2856 k = this->vtable->klass;
2859 name = mono_array_get (params, MonoString *, 1);
2860 str = mono_string_to_utf8 (name);
2862 do {
2863 MonoClassField* field = mono_class_get_field_from_name (k, str);
2864 if (field) {
2865 MonoClass *field_klass = mono_class_from_mono_type (field->type);
2866 if (field_klass->valuetype)
2867 result = mono_value_box (domain, field_klass, (char *)this + field->offset);
2868 else
2869 result = *((gpointer *)((char *)this + field->offset));
2871 out_args = mono_array_new (domain, mono_defaults.object_class, 1);
2872 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
2873 mono_array_setref (out_args, 0, result);
2874 g_free (str);
2875 return NULL;
2877 k = k->parent;
2878 } while (k);
2880 g_free (str);
2881 g_assert_not_reached ();
2883 } else if (!strcmp (m->name, "FieldSetter")) {
2884 MonoClass *k = this->vtable->klass;
2885 MonoString *name;
2886 guint32 size;
2887 gint32 align;
2888 char *str;
2890 /* If this is a proxy, then it must be a CBO */
2891 if (k == mono_defaults.transparent_proxy_class) {
2892 MonoTransparentProxy *tp = (MonoTransparentProxy*) this;
2893 this = tp->rp->unwrapped_server;
2894 g_assert (this);
2895 k = this->vtable->klass;
2898 name = mono_array_get (params, MonoString *, 1);
2899 str = mono_string_to_utf8 (name);
2901 do {
2902 MonoClassField* field = mono_class_get_field_from_name (k, str);
2903 if (field) {
2904 MonoClass *field_klass = mono_class_from_mono_type (field->type);
2905 MonoObject *val = mono_array_get (params, gpointer, 2);
2907 if (field_klass->valuetype) {
2908 size = mono_type_size (field->type, &align);
2909 g_assert (size == mono_class_value_size (field_klass, NULL));
2910 mono_gc_wbarrier_value_copy ((char *)this + field->offset, (char*)val + sizeof (MonoObject), 1, field_klass);
2911 } else {
2912 mono_gc_wbarrier_set_field (this, (char*)this + field->offset, val);
2915 out_args = mono_array_new (domain, mono_defaults.object_class, 0);
2916 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
2918 g_free (str);
2919 return NULL;
2922 k = k->parent;
2923 } while (k);
2925 g_free (str);
2926 g_assert_not_reached ();
2931 for (i = 0; i < mono_array_length (params); i++) {
2932 if (sig->params [i]->byref)
2933 outarg_count++;
2936 out_args = mono_array_new (domain, mono_defaults.object_class, outarg_count);
2938 /* handle constructors only for objects already allocated */
2939 if (!strcmp (method->method->name, ".ctor"))
2940 g_assert (this);
2942 /* This can be called only on MBR objects, so no need to unbox for valuetypes. */
2943 g_assert (!method->method->klass->valuetype);
2944 result = mono_runtime_invoke_array (method->method, this, params, NULL);
2946 for (i = 0, j = 0; i < mono_array_length (params); i++) {
2947 if (sig->params [i]->byref) {
2948 gpointer arg;
2949 arg = mono_array_get (params, gpointer, i);
2950 mono_array_setref (out_args, j, arg);
2951 j++;
2955 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
2957 return result;
2960 static guint64
2961 read_enum_value (char *mem, int type)
2963 switch (type) {
2964 case MONO_TYPE_U1:
2965 return *(guint8*)mem;
2966 case MONO_TYPE_I1:
2967 return *(gint8*)mem;
2968 case MONO_TYPE_U2:
2969 return *(guint16*)mem;
2970 case MONO_TYPE_I2:
2971 return *(gint16*)mem;
2972 case MONO_TYPE_U4:
2973 return *(guint32*)mem;
2974 case MONO_TYPE_I4:
2975 return *(gint32*)mem;
2976 case MONO_TYPE_U8:
2977 return *(guint64*)mem;
2978 case MONO_TYPE_I8:
2979 return *(gint64*)mem;
2980 default:
2981 g_assert_not_reached ();
2983 return 0;
2986 static void
2987 write_enum_value (char *mem, int type, guint64 value)
2989 switch (type) {
2990 case MONO_TYPE_U1:
2991 case MONO_TYPE_I1: {
2992 guint8 *p = (guint8*)mem;
2993 *p = value;
2994 break;
2996 case MONO_TYPE_U2:
2997 case MONO_TYPE_I2: {
2998 guint16 *p = (void*)mem;
2999 *p = value;
3000 break;
3002 case MONO_TYPE_U4:
3003 case MONO_TYPE_I4: {
3004 guint32 *p = (void*)mem;
3005 *p = value;
3006 break;
3008 case MONO_TYPE_U8:
3009 case MONO_TYPE_I8: {
3010 guint64 *p = (void*)mem;
3011 *p = value;
3012 break;
3014 default:
3015 g_assert_not_reached ();
3017 return;
3020 static MonoObject *
3021 ves_icall_System_Enum_ToObject (MonoReflectionType *enumType, MonoObject *value)
3023 MonoDomain *domain;
3024 MonoClass *enumc, *objc;
3025 MonoObject *res;
3026 MonoType *etype;
3027 guint64 val;
3029 MONO_ARCH_SAVE_REGS;
3031 MONO_CHECK_ARG_NULL (enumType);
3032 MONO_CHECK_ARG_NULL (value);
3034 domain = mono_object_domain (enumType);
3035 enumc = mono_class_from_mono_type (enumType->type);
3037 mono_class_init_or_throw (enumc);
3039 objc = value->vtable->klass;
3041 if (!enumc->enumtype)
3042 mono_raise_exception (mono_get_exception_argument ("enumType", "Type provided must be an Enum."));
3043 if (!((objc->enumtype) || (objc->byval_arg.type >= MONO_TYPE_I1 && objc->byval_arg.type <= MONO_TYPE_U8)))
3044 mono_raise_exception (mono_get_exception_argument ("value", "The value passed in must be an enum base or an underlying type for an enum, such as an Int32."));
3046 etype = mono_class_enum_basetype (enumc);
3047 if (!etype)
3048 /* MS throws this for typebuilders */
3049 mono_raise_exception (mono_get_exception_argument ("Type must be a type provided by the runtime.", "enumType"));
3051 res = mono_object_new (domain, enumc);
3052 val = read_enum_value ((char *)value + sizeof (MonoObject), objc->enumtype? mono_class_enum_basetype (objc)->type: objc->byval_arg.type);
3053 write_enum_value ((char *)res + sizeof (MonoObject), etype->type, val);
3055 return res;
3058 static MonoObject *
3059 ves_icall_System_Enum_get_value (MonoObject *this)
3061 MonoObject *res;
3062 MonoClass *enumc;
3063 gpointer dst;
3064 gpointer src;
3065 int size;
3067 MONO_ARCH_SAVE_REGS;
3069 if (!this)
3070 return NULL;
3072 g_assert (this->vtable->klass->enumtype);
3074 enumc = mono_class_from_mono_type (mono_class_enum_basetype (this->vtable->klass));
3075 res = mono_object_new (mono_object_domain (this), enumc);
3076 dst = (char *)res + sizeof (MonoObject);
3077 src = (char *)this + sizeof (MonoObject);
3078 size = mono_class_value_size (enumc, NULL);
3080 memcpy (dst, src, size);
3082 return res;
3085 static MonoReflectionType *
3086 ves_icall_System_Enum_get_underlying_type (MonoReflectionType *type)
3088 MonoType *etype;
3089 MonoClass *klass;
3091 MONO_ARCH_SAVE_REGS;
3093 klass = mono_class_from_mono_type (type->type);
3094 mono_class_init_or_throw (klass);
3096 etype = mono_class_enum_basetype (klass);
3097 if (!etype)
3098 /* MS throws this for typebuilders */
3099 mono_raise_exception (mono_get_exception_argument ("Type must be a type provided by the runtime.", "enumType"));
3101 return mono_type_get_object (mono_object_domain (type), etype);
3104 static int
3105 ves_icall_System_Enum_compare_value_to (MonoObject *this, MonoObject *other)
3107 gpointer tdata = (char *)this + sizeof (MonoObject);
3108 gpointer odata = (char *)other + sizeof (MonoObject);
3109 MonoType *basetype = mono_class_enum_basetype (this->vtable->klass);
3110 g_assert (basetype);
3112 #define COMPARE_ENUM_VALUES(ENUM_TYPE) do { \
3113 ENUM_TYPE me = *((ENUM_TYPE*)tdata); \
3114 ENUM_TYPE other = *((ENUM_TYPE*)odata); \
3115 if (me == other) \
3116 return 0; \
3117 return me > other ? 1 : -1; \
3118 } while (0)
3120 #define COMPARE_ENUM_VALUES_RANGE(ENUM_TYPE) do { \
3121 ENUM_TYPE me = *((ENUM_TYPE*)tdata); \
3122 ENUM_TYPE other = *((ENUM_TYPE*)odata); \
3123 if (me == other) \
3124 return 0; \
3125 return me - other; \
3126 } while (0)
3128 switch (basetype->type) {
3129 case MONO_TYPE_U1:
3130 COMPARE_ENUM_VALUES (guint8);
3131 case MONO_TYPE_I1:
3132 COMPARE_ENUM_VALUES (gint8);
3133 case MONO_TYPE_CHAR:
3134 case MONO_TYPE_U2:
3135 COMPARE_ENUM_VALUES_RANGE (guint16);
3136 case MONO_TYPE_I2:
3137 COMPARE_ENUM_VALUES (gint16);
3138 case MONO_TYPE_U4:
3139 COMPARE_ENUM_VALUES (guint32);
3140 case MONO_TYPE_I4:
3141 COMPARE_ENUM_VALUES (gint32);
3142 case MONO_TYPE_U8:
3143 COMPARE_ENUM_VALUES (guint64);
3144 case MONO_TYPE_I8:
3145 COMPARE_ENUM_VALUES (gint64);
3146 default:
3147 g_error ("Implement type 0x%02x in get_hashcode", basetype->type);
3149 #undef COMPARE_ENUM_VALUES_RANGE
3150 #undef COMPARE_ENUM_VALUES
3151 return 0;
3154 static int
3155 ves_icall_System_Enum_get_hashcode (MonoObject *this)
3157 gpointer data = (char *)this + sizeof (MonoObject);
3158 MonoType *basetype = mono_class_enum_basetype (this->vtable->klass);
3159 g_assert (basetype);
3161 switch (basetype->type) {
3162 case MONO_TYPE_I1:
3163 return *((gint8*)data);
3164 case MONO_TYPE_U1:
3165 return *((guint8*)data);
3166 case MONO_TYPE_CHAR:
3167 case MONO_TYPE_U2:
3168 return *((guint16*)data);
3170 case MONO_TYPE_I2:
3171 return *((gint16*)data);
3172 case MONO_TYPE_U4:
3173 return *((guint32*)data);
3174 case MONO_TYPE_I4:
3175 return *((gint32*)data);
3176 case MONO_TYPE_U8:
3177 case MONO_TYPE_I8: {
3178 gint64 value = *((gint64*)data);
3179 return (gint)(value & 0xffffffff) ^ (int)(value >> 32);
3181 default:
3182 g_error ("Implement type 0x%02x in get_hashcode", basetype->type);
3184 return 0;
3187 static void
3188 ves_icall_get_enum_info (MonoReflectionType *type, MonoEnumInfo *info)
3190 MonoDomain *domain = mono_object_domain (type);
3191 MonoClass *enumc = mono_class_from_mono_type (type->type);
3192 guint j = 0, nvalues, crow;
3193 gpointer iter;
3194 MonoClassField *field;
3196 MONO_ARCH_SAVE_REGS;
3198 mono_class_init_or_throw (enumc);
3200 MONO_STRUCT_SETREF (info, utype, mono_type_get_object (domain, mono_class_enum_basetype (enumc)));
3201 nvalues = mono_class_num_fields (enumc) ? mono_class_num_fields (enumc) - 1 : 0;
3202 MONO_STRUCT_SETREF (info, names, mono_array_new (domain, mono_defaults.string_class, nvalues));
3203 MONO_STRUCT_SETREF (info, values, mono_array_new (domain, enumc, nvalues));
3205 crow = -1;
3206 iter = NULL;
3207 while ((field = mono_class_get_fields (enumc, &iter))) {
3208 const char *p;
3209 int len;
3210 MonoTypeEnum def_type;
3212 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC))
3213 continue;
3214 if (strcmp ("value__", mono_field_get_name (field)) == 0)
3215 continue;
3216 if (mono_field_is_deleted (field))
3217 continue;
3218 mono_array_setref (info->names, j, mono_string_new (domain, mono_field_get_name (field)));
3220 p = mono_class_get_field_default_value (field, &def_type);
3221 len = mono_metadata_decode_blob_size (p, &p);
3222 switch (mono_class_enum_basetype (enumc)->type) {
3223 case MONO_TYPE_U1:
3224 case MONO_TYPE_I1:
3225 mono_array_set (info->values, gchar, j, *p);
3226 break;
3227 case MONO_TYPE_CHAR:
3228 case MONO_TYPE_U2:
3229 case MONO_TYPE_I2:
3230 mono_array_set (info->values, gint16, j, read16 (p));
3231 break;
3232 case MONO_TYPE_U4:
3233 case MONO_TYPE_I4:
3234 mono_array_set (info->values, gint32, j, read32 (p));
3235 break;
3236 case MONO_TYPE_U8:
3237 case MONO_TYPE_I8:
3238 mono_array_set (info->values, gint64, j, read64 (p));
3239 break;
3240 default:
3241 g_error ("Implement type 0x%02x in get_enum_info", mono_class_enum_basetype (enumc)->type);
3243 ++j;
3247 enum {
3248 BFLAGS_IgnoreCase = 1,
3249 BFLAGS_DeclaredOnly = 2,
3250 BFLAGS_Instance = 4,
3251 BFLAGS_Static = 8,
3252 BFLAGS_Public = 0x10,
3253 BFLAGS_NonPublic = 0x20,
3254 BFLAGS_FlattenHierarchy = 0x40,
3255 BFLAGS_InvokeMethod = 0x100,
3256 BFLAGS_CreateInstance = 0x200,
3257 BFLAGS_GetField = 0x400,
3258 BFLAGS_SetField = 0x800,
3259 BFLAGS_GetProperty = 0x1000,
3260 BFLAGS_SetProperty = 0x2000,
3261 BFLAGS_ExactBinding = 0x10000,
3262 BFLAGS_SuppressChangeType = 0x20000,
3263 BFLAGS_OptionalParamBinding = 0x40000
3266 static MonoReflectionField *
3267 ves_icall_Type_GetField (MonoReflectionType *type, MonoString *name, guint32 bflags)
3269 MonoDomain *domain;
3270 MonoClass *startklass, *klass;
3271 int match;
3272 MonoClassField *field;
3273 gpointer iter;
3274 char *utf8_name;
3275 int (*compare_func) (const char *s1, const char *s2) = NULL;
3276 domain = ((MonoObject *)type)->vtable->domain;
3277 klass = startklass = mono_class_from_mono_type (type->type);
3279 if (!name)
3280 mono_raise_exception (mono_get_exception_argument_null ("name"));
3281 if (type->type->byref)
3282 return NULL;
3284 compare_func = (bflags & BFLAGS_IgnoreCase) ? mono_utf8_strcasecmp : strcmp;
3286 handle_parent:
3287 if (klass->exception_type != MONO_EXCEPTION_NONE)
3288 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3290 iter = NULL;
3291 while ((field = mono_class_get_fields_lazy (klass, &iter))) {
3292 guint32 flags = mono_field_get_flags (field);
3293 match = 0;
3295 if (mono_field_is_deleted_with_flags (field, flags))
3296 continue;
3297 if ((flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) == FIELD_ATTRIBUTE_PUBLIC) {
3298 if (bflags & BFLAGS_Public)
3299 match++;
3300 } else if ((klass == startklass) || (flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) != FIELD_ATTRIBUTE_PRIVATE) {
3301 if (bflags & BFLAGS_NonPublic) {
3302 match++;
3305 if (!match)
3306 continue;
3307 match = 0;
3308 if (flags & FIELD_ATTRIBUTE_STATIC) {
3309 if (bflags & BFLAGS_Static)
3310 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3311 match++;
3312 } else {
3313 if (bflags & BFLAGS_Instance)
3314 match++;
3317 if (!match)
3318 continue;
3320 utf8_name = mono_string_to_utf8 (name);
3322 if (compare_func (mono_field_get_name (field), utf8_name)) {
3323 g_free (utf8_name);
3324 continue;
3326 g_free (utf8_name);
3328 return mono_field_get_object (domain, klass, field);
3330 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3331 goto handle_parent;
3333 return NULL;
3336 static MonoArray*
3337 ves_icall_Type_GetFields_internal (MonoReflectionType *type, guint32 bflags, MonoReflectionType *reftype)
3339 MonoDomain *domain;
3340 MonoClass *startklass, *klass, *refklass;
3341 MonoArray *res;
3342 MonoObject *member;
3343 int i, match;
3344 gpointer iter;
3345 MonoClassField *field;
3346 MonoPtrArray tmp_array;
3348 MONO_ARCH_SAVE_REGS;
3350 domain = ((MonoObject *)type)->vtable->domain;
3351 if (type->type->byref)
3352 return mono_array_new (domain, mono_defaults.field_info_class, 0);
3353 klass = startklass = mono_class_from_mono_type (type->type);
3354 refklass = mono_class_from_mono_type (reftype->type);
3356 mono_ptr_array_init (tmp_array, 2);
3358 handle_parent:
3359 if (klass->exception_type != MONO_EXCEPTION_NONE) {
3360 mono_ptr_array_destroy (tmp_array);
3361 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3364 iter = NULL;
3365 while ((field = mono_class_get_fields_lazy (klass, &iter))) {
3366 guint32 flags = mono_field_get_flags (field);
3367 match = 0;
3368 if (mono_field_is_deleted_with_flags (field, flags))
3369 continue;
3370 if ((flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) == FIELD_ATTRIBUTE_PUBLIC) {
3371 if (bflags & BFLAGS_Public)
3372 match++;
3373 } else if ((klass == startklass) || (flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) != FIELD_ATTRIBUTE_PRIVATE) {
3374 if (bflags & BFLAGS_NonPublic) {
3375 match++;
3378 if (!match)
3379 continue;
3380 match = 0;
3381 if (flags & FIELD_ATTRIBUTE_STATIC) {
3382 if (bflags & BFLAGS_Static)
3383 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3384 match++;
3385 } else {
3386 if (bflags & BFLAGS_Instance)
3387 match++;
3390 if (!match)
3391 continue;
3392 member = (MonoObject*)mono_field_get_object (domain, refklass, field);
3393 mono_ptr_array_append (tmp_array, member);
3395 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3396 goto handle_parent;
3398 res = mono_array_new_cached (domain, mono_defaults.field_info_class, mono_ptr_array_size (tmp_array));
3400 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3401 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3403 mono_ptr_array_destroy (tmp_array);
3405 return res;
3408 static gboolean
3409 method_nonpublic (MonoMethod* method, gboolean start_klass)
3411 switch (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) {
3412 case METHOD_ATTRIBUTE_ASSEM:
3413 return (start_klass || mono_defaults.generic_ilist_class);
3414 case METHOD_ATTRIBUTE_PRIVATE:
3415 return start_klass;
3416 case METHOD_ATTRIBUTE_PUBLIC:
3417 return FALSE;
3418 default:
3419 return TRUE;
3423 static MonoArray*
3424 ves_icall_Type_GetMethodsByName (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoBoolean ignore_case, MonoReflectionType *reftype)
3426 static MonoClass *MethodInfo_array;
3427 MonoDomain *domain;
3428 MonoClass *startklass, *klass, *refklass;
3429 MonoArray *res;
3430 MonoMethod *method;
3431 gpointer iter;
3432 MonoObject *member;
3433 int i, len, match, nslots;
3434 /*FIXME, use MonoBitSet*/
3435 guint32 method_slots_default [8];
3436 guint32 *method_slots = NULL;
3437 gchar *mname = NULL;
3438 int (*compare_func) (const char *s1, const char *s2) = NULL;
3439 MonoVTable *array_vtable;
3440 MonoException *ex;
3441 MonoPtrArray tmp_array;
3443 mono_ptr_array_init (tmp_array, 4);
3445 if (!MethodInfo_array) {
3446 MonoClass *klass = mono_array_class_get (mono_defaults.method_info_class, 1);
3447 mono_memory_barrier ();
3448 MethodInfo_array = klass;
3451 domain = ((MonoObject *)type)->vtable->domain;
3452 array_vtable = mono_class_vtable_full (domain, MethodInfo_array, TRUE);
3453 if (type->type->byref)
3454 return mono_array_new_specific (array_vtable, 0);
3455 klass = startklass = mono_class_from_mono_type (type->type);
3456 refklass = mono_class_from_mono_type (reftype->type);
3458 len = 0;
3459 if (name != NULL) {
3460 mname = mono_string_to_utf8 (name);
3461 compare_func = (ignore_case) ? mono_utf8_strcasecmp : strcmp;
3464 /* An optimization for calls made from Delegate:CreateDelegate () */
3465 if (klass->delegate && mname && !strcmp (mname, "Invoke") && (bflags == (BFLAGS_Public | BFLAGS_Static | BFLAGS_Instance))) {
3466 method = mono_get_delegate_invoke (klass);
3467 if (mono_loader_get_last_error ())
3468 goto loader_error;
3470 member = (MonoObject*)mono_method_get_object (domain, method, refklass);
3472 res = mono_array_new_specific (array_vtable, 1);
3473 mono_array_setref (res, 0, member);
3474 g_free (mname);
3475 return res;
3478 mono_class_setup_vtable (klass);
3479 if (klass->exception_type != MONO_EXCEPTION_NONE || mono_loader_get_last_error ())
3480 goto loader_error;
3482 if (is_generic_parameter (type->type))
3483 nslots = mono_class_get_vtable_size (klass->parent);
3484 else
3485 nslots = MONO_CLASS_IS_INTERFACE (klass) ? mono_class_num_methods (klass) : mono_class_get_vtable_size (klass);
3486 if (nslots >= sizeof (method_slots_default) * 8) {
3487 method_slots = g_new0 (guint32, nslots / 32 + 1);
3488 } else {
3489 method_slots = method_slots_default;
3490 memset (method_slots, 0, sizeof (method_slots_default));
3492 handle_parent:
3493 mono_class_setup_vtable (klass);
3494 if (klass->exception_type != MONO_EXCEPTION_NONE || mono_loader_get_last_error ())
3495 goto loader_error;
3497 iter = NULL;
3498 while ((method = mono_class_get_methods (klass, &iter))) {
3499 match = 0;
3500 if (method->slot != -1) {
3501 g_assert (method->slot < nslots);
3502 if (method_slots [method->slot >> 5] & (1 << (method->slot & 0x1f)))
3503 continue;
3504 if (!(method->flags & METHOD_ATTRIBUTE_NEW_SLOT))
3505 method_slots [method->slot >> 5] |= 1 << (method->slot & 0x1f);
3508 if (method->name [0] == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0))
3509 continue;
3510 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3511 if (bflags & BFLAGS_Public)
3512 match++;
3513 } else if ((bflags & BFLAGS_NonPublic) && method_nonpublic (method, (klass == startklass))) {
3514 match++;
3516 if (!match)
3517 continue;
3518 match = 0;
3519 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3520 if (bflags & BFLAGS_Static)
3521 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3522 match++;
3523 } else {
3524 if (bflags & BFLAGS_Instance)
3525 match++;
3528 if (!match)
3529 continue;
3531 if (name != NULL) {
3532 if (compare_func (mname, method->name))
3533 continue;
3536 match = 0;
3538 member = (MonoObject*)mono_method_get_object (domain, method, refklass);
3540 mono_ptr_array_append (tmp_array, member);
3542 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3543 goto handle_parent;
3545 g_free (mname);
3546 if (method_slots != method_slots_default)
3547 g_free (method_slots);
3549 res = mono_array_new_specific (array_vtable, mono_ptr_array_size (tmp_array));
3551 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3552 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3554 mono_ptr_array_destroy (tmp_array);
3555 return res;
3557 loader_error:
3558 g_free (mname);
3559 if (method_slots != method_slots_default)
3560 g_free (method_slots);
3561 mono_ptr_array_destroy (tmp_array);
3562 if (klass->exception_type != MONO_EXCEPTION_NONE) {
3563 ex = mono_class_get_exception_for_failure (klass);
3564 } else {
3565 ex = mono_loader_error_prepare_exception (mono_loader_get_last_error ());
3566 mono_loader_clear_error ();
3568 mono_raise_exception (ex);
3569 return NULL;
3572 static MonoArray*
3573 ves_icall_Type_GetConstructors_internal (MonoReflectionType *type, guint32 bflags, MonoReflectionType *reftype)
3575 MonoDomain *domain;
3576 static MonoClass *System_Reflection_ConstructorInfo;
3577 MonoClass *startklass, *klass, *refklass;
3578 MonoArray *res;
3579 MonoMethod *method;
3580 MonoObject *member;
3581 int i, match;
3582 gpointer iter = NULL;
3583 MonoPtrArray tmp_array;
3585 MONO_ARCH_SAVE_REGS;
3587 mono_ptr_array_init (tmp_array, 4); /*FIXME, guestimating*/
3589 domain = ((MonoObject *)type)->vtable->domain;
3590 if (type->type->byref)
3591 return mono_array_new_cached (domain, mono_defaults.method_info_class, 0);
3592 klass = startklass = mono_class_from_mono_type (type->type);
3593 refklass = mono_class_from_mono_type (reftype->type);
3595 if (!System_Reflection_ConstructorInfo)
3596 System_Reflection_ConstructorInfo = mono_class_from_name (
3597 mono_defaults.corlib, "System.Reflection", "ConstructorInfo");
3599 iter = NULL;
3600 while ((method = mono_class_get_methods (klass, &iter))) {
3601 match = 0;
3602 if (strcmp (method->name, ".ctor") && strcmp (method->name, ".cctor"))
3603 continue;
3604 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3605 if (bflags & BFLAGS_Public)
3606 match++;
3607 } else {
3608 if (bflags & BFLAGS_NonPublic)
3609 match++;
3611 if (!match)
3612 continue;
3613 match = 0;
3614 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3615 if (bflags & BFLAGS_Static)
3616 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3617 match++;
3618 } else {
3619 if (bflags & BFLAGS_Instance)
3620 match++;
3623 if (!match)
3624 continue;
3625 member = (MonoObject*)mono_method_get_object (domain, method, refklass);
3627 mono_ptr_array_append (tmp_array, member);
3630 res = mono_array_new_cached (domain, System_Reflection_ConstructorInfo, mono_ptr_array_size (tmp_array));
3632 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3633 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3635 mono_ptr_array_destroy (tmp_array);
3637 return res;
3640 static guint
3641 property_hash (gconstpointer data)
3643 MonoProperty *prop = (MonoProperty*)data;
3645 return g_str_hash (prop->name);
3648 static gboolean
3649 property_equal (MonoProperty *prop1, MonoProperty *prop2)
3651 // Properties are hide-by-name-and-signature
3652 if (!g_str_equal (prop1->name, prop2->name))
3653 return FALSE;
3655 if (prop1->get && prop2->get && !mono_metadata_signature_equal (mono_method_signature (prop1->get), mono_method_signature (prop2->get)))
3656 return FALSE;
3657 if (prop1->set && prop2->set && !mono_metadata_signature_equal (mono_method_signature (prop1->set), mono_method_signature (prop2->set)))
3658 return FALSE;
3659 return TRUE;
3662 static gboolean
3663 property_accessor_nonpublic (MonoMethod* accessor, gboolean start_klass)
3665 if (!accessor)
3666 return FALSE;
3668 return method_nonpublic (accessor, start_klass);
3671 static MonoArray*
3672 ves_icall_Type_GetPropertiesByName (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoBoolean ignore_case, MonoReflectionType *reftype)
3674 MonoException *ex;
3675 MonoDomain *domain;
3676 static MonoClass *System_Reflection_PropertyInfo;
3677 MonoClass *startklass, *klass;
3678 MonoArray *res;
3679 MonoMethod *method;
3680 MonoProperty *prop;
3681 int i, match;
3682 guint32 flags;
3683 gchar *propname = NULL;
3684 int (*compare_func) (const char *s1, const char *s2) = NULL;
3685 gpointer iter;
3686 GHashTable *properties = NULL;
3687 MonoPtrArray tmp_array;
3689 MONO_ARCH_SAVE_REGS;
3691 mono_ptr_array_init (tmp_array, 8); /*This the average for ASP.NET types*/
3693 if (!System_Reflection_PropertyInfo)
3694 System_Reflection_PropertyInfo = mono_class_from_name (
3695 mono_defaults.corlib, "System.Reflection", "PropertyInfo");
3697 domain = ((MonoObject *)type)->vtable->domain;
3698 if (type->type->byref)
3699 return mono_array_new_cached (domain, System_Reflection_PropertyInfo, 0);
3700 klass = startklass = mono_class_from_mono_type (type->type);
3702 if (name != NULL) {
3703 propname = mono_string_to_utf8 (name);
3704 compare_func = (ignore_case) ? mono_utf8_strcasecmp : strcmp;
3707 properties = g_hash_table_new (property_hash, (GEqualFunc)property_equal);
3708 handle_parent:
3709 mono_class_setup_vtable (klass);
3710 if (klass->exception_type != MONO_EXCEPTION_NONE || mono_loader_get_last_error ())
3711 goto loader_error;
3713 iter = NULL;
3714 while ((prop = mono_class_get_properties (klass, &iter))) {
3715 match = 0;
3716 method = prop->get;
3717 if (!method)
3718 method = prop->set;
3719 if (method)
3720 flags = method->flags;
3721 else
3722 flags = 0;
3723 if ((prop->get && ((prop->get->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC)) ||
3724 (prop->set && ((prop->set->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC))) {
3725 if (bflags & BFLAGS_Public)
3726 match++;
3727 } else if (bflags & BFLAGS_NonPublic) {
3728 if (property_accessor_nonpublic(prop->get, startklass == klass) ||
3729 property_accessor_nonpublic(prop->set, startklass == klass)) {
3730 match++;
3733 if (!match)
3734 continue;
3735 match = 0;
3736 if (flags & METHOD_ATTRIBUTE_STATIC) {
3737 if (bflags & BFLAGS_Static)
3738 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3739 match++;
3740 } else {
3741 if (bflags & BFLAGS_Instance)
3742 match++;
3745 if (!match)
3746 continue;
3747 match = 0;
3749 if (name != NULL) {
3750 if (compare_func (propname, prop->name))
3751 continue;
3754 if (g_hash_table_lookup (properties, prop))
3755 continue;
3757 mono_ptr_array_append (tmp_array, mono_property_get_object (domain, startklass, prop));
3759 g_hash_table_insert (properties, prop, prop);
3761 if ((!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent)))
3762 goto handle_parent;
3764 g_hash_table_destroy (properties);
3765 g_free (propname);
3767 res = mono_array_new_cached (domain, System_Reflection_PropertyInfo, mono_ptr_array_size (tmp_array));
3768 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3769 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3771 mono_ptr_array_destroy (tmp_array);
3773 return res;
3775 loader_error:
3776 if (properties)
3777 g_hash_table_destroy (properties);
3778 if (name)
3779 g_free (propname);
3780 mono_ptr_array_destroy (tmp_array);
3782 if (klass->exception_type != MONO_EXCEPTION_NONE) {
3783 ex = mono_class_get_exception_for_failure (klass);
3784 } else {
3785 ex = mono_loader_error_prepare_exception (mono_loader_get_last_error ());
3786 mono_loader_clear_error ();
3788 mono_raise_exception (ex);
3789 return NULL;
3792 static MonoReflectionEvent *
3793 ves_icall_MonoType_GetEvent (MonoReflectionType *type, MonoString *name, guint32 bflags)
3795 MonoDomain *domain;
3796 MonoClass *klass, *startklass;
3797 gpointer iter;
3798 MonoEvent *event;
3799 MonoMethod *method;
3800 gchar *event_name;
3801 int (*compare_func) (const char *s1, const char *s2);
3803 MONO_ARCH_SAVE_REGS;
3805 event_name = mono_string_to_utf8 (name);
3806 if (type->type->byref)
3807 return NULL;
3808 klass = startklass = mono_class_from_mono_type (type->type);
3809 domain = mono_object_domain (type);
3811 mono_class_init_or_throw (klass);
3813 compare_func = (bflags & BFLAGS_IgnoreCase) ? mono_utf8_strcasecmp : strcmp;
3814 handle_parent:
3815 if (klass->exception_type != MONO_EXCEPTION_NONE)
3816 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3818 iter = NULL;
3819 while ((event = mono_class_get_events (klass, &iter))) {
3820 if (compare_func (event->name, event_name))
3821 continue;
3823 method = event->add;
3824 if (!method)
3825 method = event->remove;
3826 if (!method)
3827 method = event->raise;
3828 if (method) {
3829 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3830 if (!(bflags & BFLAGS_Public))
3831 continue;
3832 } else {
3833 if (!(bflags & BFLAGS_NonPublic))
3834 continue;
3835 if ((klass != startklass) && (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PRIVATE)
3836 continue;
3839 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3840 if (!(bflags & BFLAGS_Static))
3841 continue;
3842 if (!(bflags & BFLAGS_FlattenHierarchy) && (klass != startklass))
3843 continue;
3844 } else {
3845 if (!(bflags & BFLAGS_Instance))
3846 continue;
3848 } else
3849 if (!(bflags & BFLAGS_NonPublic))
3850 continue;
3852 g_free (event_name);
3853 return mono_event_get_object (domain, startklass, event);
3856 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3857 goto handle_parent;
3859 g_free (event_name);
3860 return NULL;
3863 static MonoArray*
3864 ves_icall_Type_GetEvents_internal (MonoReflectionType *type, guint32 bflags, MonoReflectionType *reftype)
3866 MonoException *ex;
3867 MonoDomain *domain;
3868 static MonoClass *System_Reflection_EventInfo;
3869 MonoClass *startklass, *klass;
3870 MonoArray *res;
3871 MonoMethod *method;
3872 MonoEvent *event;
3873 int i, match;
3874 gpointer iter;
3876 MonoPtrArray tmp_array;
3878 MONO_ARCH_SAVE_REGS;
3880 mono_ptr_array_init (tmp_array, 4);
3882 if (!System_Reflection_EventInfo)
3883 System_Reflection_EventInfo = mono_class_from_name (
3884 mono_defaults.corlib, "System.Reflection", "EventInfo");
3886 domain = mono_object_domain (type);
3887 if (type->type->byref)
3888 return mono_array_new_cached (domain, System_Reflection_EventInfo, 0);
3889 klass = startklass = mono_class_from_mono_type (type->type);
3891 handle_parent:
3892 mono_class_setup_vtable (klass);
3893 if (klass->exception_type != MONO_EXCEPTION_NONE || mono_loader_get_last_error ())
3894 goto loader_error;
3896 iter = NULL;
3897 while ((event = mono_class_get_events (klass, &iter))) {
3898 match = 0;
3899 method = event->add;
3900 if (!method)
3901 method = event->remove;
3902 if (!method)
3903 method = event->raise;
3904 if (method) {
3905 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3906 if (bflags & BFLAGS_Public)
3907 match++;
3908 } else if ((klass == startklass) || (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) != METHOD_ATTRIBUTE_PRIVATE) {
3909 if (bflags & BFLAGS_NonPublic)
3910 match++;
3913 else
3914 if (bflags & BFLAGS_NonPublic)
3915 match ++;
3916 if (!match)
3917 continue;
3918 match = 0;
3919 if (method) {
3920 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3921 if (bflags & BFLAGS_Static)
3922 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3923 match++;
3924 } else {
3925 if (bflags & BFLAGS_Instance)
3926 match++;
3929 else
3930 if (bflags & BFLAGS_Instance)
3931 match ++;
3932 if (!match)
3933 continue;
3934 mono_ptr_array_append (tmp_array, mono_event_get_object (domain, startklass, event));
3936 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3937 goto handle_parent;
3939 res = mono_array_new_cached (domain, System_Reflection_EventInfo, mono_ptr_array_size (tmp_array));
3941 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3942 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3944 mono_ptr_array_destroy (tmp_array);
3946 return res;
3948 loader_error:
3949 mono_ptr_array_destroy (tmp_array);
3950 if (klass->exception_type != MONO_EXCEPTION_NONE) {
3951 ex = mono_class_get_exception_for_failure (klass);
3952 } else {
3953 ex = mono_loader_error_prepare_exception (mono_loader_get_last_error ());
3954 mono_loader_clear_error ();
3956 mono_raise_exception (ex);
3957 return NULL;
3960 static MonoReflectionType *
3961 ves_icall_Type_GetNestedType (MonoReflectionType *type, MonoString *name, guint32 bflags)
3963 MonoDomain *domain;
3964 MonoClass *klass;
3965 MonoClass *nested;
3966 char *str;
3967 gpointer iter;
3969 MONO_ARCH_SAVE_REGS;
3971 if (name == NULL)
3972 mono_raise_exception (mono_get_exception_argument_null ("name"));
3974 domain = ((MonoObject *)type)->vtable->domain;
3975 if (type->type->byref)
3976 return NULL;
3977 klass = mono_class_from_mono_type (type->type);
3979 str = mono_string_to_utf8 (name);
3981 handle_parent:
3982 if (klass->exception_type != MONO_EXCEPTION_NONE)
3983 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3986 * If a nested type is generic, return its generic type definition.
3987 * Note that this means that the return value is essentially a
3988 * nested type of the generic type definition of @klass.
3990 * A note in MSDN claims that a generic type definition can have
3991 * nested types that aren't generic. In any case, the container of that
3992 * nested type would be the generic type definition.
3994 if (klass->generic_class)
3995 klass = klass->generic_class->container_class;
3997 iter = NULL;
3998 while ((nested = mono_class_get_nested_types (klass, &iter))) {
3999 int match = 0;
4000 if ((nested->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK) == TYPE_ATTRIBUTE_NESTED_PUBLIC) {
4001 if (bflags & BFLAGS_Public)
4002 match++;
4003 } else {
4004 if (bflags & BFLAGS_NonPublic)
4005 match++;
4007 if (!match)
4008 continue;
4009 if (strcmp (nested->name, str) == 0){
4010 g_free (str);
4011 return mono_type_get_object (domain, &nested->byval_arg);
4014 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
4015 goto handle_parent;
4016 g_free (str);
4017 return NULL;
4020 static MonoArray*
4021 ves_icall_Type_GetNestedTypes (MonoReflectionType *type, guint32 bflags)
4023 MonoDomain *domain;
4024 MonoClass *klass;
4025 MonoArray *res;
4026 MonoObject *member;
4027 int i, match;
4028 MonoClass *nested;
4029 gpointer iter;
4030 MonoPtrArray tmp_array;
4032 MONO_ARCH_SAVE_REGS;
4034 domain = ((MonoObject *)type)->vtable->domain;
4035 if (type->type->byref)
4036 return mono_array_new (domain, mono_defaults.monotype_class, 0);
4037 klass = mono_class_from_mono_type (type->type);
4040 * If a nested type is generic, return its generic type definition.
4041 * Note that this means that the return value is essentially the set
4042 * of nested types of the generic type definition of @klass.
4044 * A note in MSDN claims that a generic type definition can have
4045 * nested types that aren't generic. In any case, the container of that
4046 * nested type would be the generic type definition.
4048 if (klass->generic_class)
4049 klass = klass->generic_class->container_class;
4051 mono_ptr_array_init (tmp_array, 1);
4052 iter = NULL;
4053 while ((nested = mono_class_get_nested_types (klass, &iter))) {
4054 match = 0;
4055 if ((nested->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK) == TYPE_ATTRIBUTE_NESTED_PUBLIC) {
4056 if (bflags & BFLAGS_Public)
4057 match++;
4058 } else {
4059 if (bflags & BFLAGS_NonPublic)
4060 match++;
4062 if (!match)
4063 continue;
4064 member = (MonoObject*)mono_type_get_object (domain, &nested->byval_arg);
4065 mono_ptr_array_append (tmp_array, member);
4068 res = mono_array_new_cached (domain, mono_defaults.monotype_class, mono_ptr_array_size (tmp_array));
4070 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
4071 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
4073 mono_ptr_array_destroy (tmp_array);
4075 return res;
4078 static MonoReflectionType*
4079 ves_icall_System_Reflection_Assembly_InternalGetType (MonoReflectionAssembly *assembly, MonoReflectionModule *module, MonoString *name, MonoBoolean throwOnError, MonoBoolean ignoreCase)
4081 gchar *str;
4082 MonoType *type = NULL;
4083 MonoTypeNameParse info;
4084 gboolean type_resolve;
4086 MONO_ARCH_SAVE_REGS;
4088 /* On MS.NET, this does not fire a TypeResolve event */
4089 type_resolve = TRUE;
4090 str = mono_string_to_utf8 (name);
4091 /*g_print ("requested type %s in %s\n", str, assembly->assembly->aname.name);*/
4092 if (!mono_reflection_parse_type (str, &info)) {
4093 g_free (str);
4094 mono_reflection_free_type_info (&info);
4095 if (throwOnError) /* uhm: this is a parse error, though... */
4096 mono_raise_exception (mono_get_exception_type_load (name, NULL));
4097 /*g_print ("failed parse\n");*/
4098 return NULL;
4101 if (info.assembly.name) {
4102 g_free (str);
4103 mono_reflection_free_type_info (&info);
4104 if (throwOnError) {
4105 /* 1.0 and 2.0 throw different exceptions */
4106 if (mono_defaults.generic_ilist_class)
4107 mono_raise_exception (mono_get_exception_argument (NULL, "Type names passed to Assembly.GetType() must not specify an assembly."));
4108 else
4109 mono_raise_exception (mono_get_exception_type_load (name, NULL));
4111 return NULL;
4114 if (module != NULL) {
4115 if (module->image)
4116 type = mono_reflection_get_type (module->image, &info, ignoreCase, &type_resolve);
4117 else
4118 type = NULL;
4120 else
4121 if (assembly->assembly->dynamic) {
4122 /* Enumerate all modules */
4123 MonoReflectionAssemblyBuilder *abuilder = (MonoReflectionAssemblyBuilder*)assembly;
4124 int i;
4126 type = NULL;
4127 if (abuilder->modules) {
4128 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
4129 MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
4130 type = mono_reflection_get_type (&mb->dynamic_image->image, &info, ignoreCase, &type_resolve);
4131 if (type)
4132 break;
4136 if (!type && abuilder->loaded_modules) {
4137 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
4138 MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
4139 type = mono_reflection_get_type (mod->image, &info, ignoreCase, &type_resolve);
4140 if (type)
4141 break;
4145 else
4146 type = mono_reflection_get_type (assembly->assembly->image, &info, ignoreCase, &type_resolve);
4147 g_free (str);
4148 mono_reflection_free_type_info (&info);
4149 if (!type) {
4150 MonoException *e = NULL;
4152 if (throwOnError)
4153 e = mono_get_exception_type_load (name, NULL);
4155 if (mono_loader_get_last_error () && mono_defaults.generic_ilist_class)
4156 e = mono_loader_error_prepare_exception (mono_loader_get_last_error ());
4158 mono_loader_clear_error ();
4160 if (e != NULL)
4161 mono_raise_exception (e);
4163 return NULL;
4164 } else if (mono_loader_get_last_error ()) {
4165 if (throwOnError)
4166 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
4167 mono_loader_clear_error ();
4170 if (type->type == MONO_TYPE_CLASS) {
4171 MonoClass *klass = mono_type_get_class (type);
4173 if (mono_is_security_manager_active () && !klass->exception_type)
4174 /* Some security problems are detected during generic vtable construction */
4175 mono_class_setup_vtable (klass);
4176 /* need to report exceptions ? */
4177 if (throwOnError && klass->exception_type) {
4178 /* report SecurityException (or others) that occured when loading the assembly */
4179 MonoException *exc = mono_class_get_exception_for_failure (klass);
4180 mono_loader_clear_error ();
4181 mono_raise_exception (exc);
4182 } else if (klass->exception_type == MONO_EXCEPTION_SECURITY_INHERITANCEDEMAND) {
4183 return NULL;
4187 /* g_print ("got it\n"); */
4188 return mono_type_get_object (mono_object_domain (assembly), type);
4191 static gboolean
4192 replace_shadow_path (MonoDomain *domain, gchar *dirname, gchar **filename)
4194 gchar *content;
4195 gchar *shadow_ini_file;
4196 gsize len;
4198 /* Check for shadow-copied assembly */
4199 if (mono_is_shadow_copy_enabled (domain, dirname)) {
4200 shadow_ini_file = g_build_filename (dirname, "__AssemblyInfo__.ini", NULL);
4201 content = NULL;
4202 if (!g_file_get_contents (shadow_ini_file, &content, &len, NULL) ||
4203 !g_file_test (content, G_FILE_TEST_IS_REGULAR)) {
4204 if (content) {
4205 g_free (content);
4206 content = NULL;
4209 g_free (shadow_ini_file);
4210 if (content != NULL) {
4211 if (*filename)
4212 g_free (*filename);
4213 *filename = content;
4214 return TRUE;
4217 return FALSE;
4220 static MonoString *
4221 ves_icall_System_Reflection_Assembly_get_code_base (MonoReflectionAssembly *assembly, MonoBoolean escaped)
4223 MonoDomain *domain = mono_object_domain (assembly);
4224 MonoAssembly *mass = assembly->assembly;
4225 MonoString *res = NULL;
4226 gchar *uri;
4227 gchar *absolute;
4228 gchar *dirname;
4230 MONO_ARCH_SAVE_REGS;
4232 if (g_path_is_absolute (mass->image->name)) {
4233 absolute = g_strdup (mass->image->name);
4234 dirname = g_path_get_dirname (absolute);
4235 } else {
4236 absolute = g_build_filename (mass->basedir, mass->image->name, NULL);
4237 dirname = g_strdup (mass->basedir);
4240 replace_shadow_path (domain, dirname, &absolute);
4241 g_free (dirname);
4242 #if HOST_WIN32
4244 gint i;
4245 for (i = strlen (absolute) - 1; i >= 0; i--)
4246 if (absolute [i] == '\\')
4247 absolute [i] = '/';
4249 #endif
4250 if (escaped) {
4251 uri = g_filename_to_uri (absolute, NULL, NULL);
4252 } else {
4253 const char *prepend = "file://";
4254 #if HOST_WIN32
4255 if (*absolute == '/' && *(absolute + 1) == '/') {
4256 prepend = "file:";
4257 } else {
4258 prepend = "file:///";
4260 #endif
4261 uri = g_strconcat (prepend, absolute, NULL);
4264 if (uri) {
4265 res = mono_string_new (domain, uri);
4266 g_free (uri);
4268 g_free (absolute);
4269 return res;
4272 static MonoBoolean
4273 ves_icall_System_Reflection_Assembly_get_global_assembly_cache (MonoReflectionAssembly *assembly)
4275 MonoAssembly *mass = assembly->assembly;
4277 MONO_ARCH_SAVE_REGS;
4279 return mass->in_gac;
4282 static MonoReflectionAssembly*
4283 ves_icall_System_Reflection_Assembly_load_with_partial_name (MonoString *mname, MonoObject *evidence)
4285 gchar *name;
4286 MonoAssembly *res;
4287 MonoImageOpenStatus status;
4289 MONO_ARCH_SAVE_REGS;
4291 name = mono_string_to_utf8 (mname);
4292 res = mono_assembly_load_with_partial_name (name, &status);
4294 g_free (name);
4296 if (res == NULL)
4297 return NULL;
4298 return mono_assembly_get_object (mono_domain_get (), res);
4301 static MonoString *
4302 ves_icall_System_Reflection_Assembly_get_location (MonoReflectionAssembly *assembly)
4304 MonoDomain *domain = mono_object_domain (assembly);
4305 MonoString *res;
4307 MONO_ARCH_SAVE_REGS;
4309 res = mono_string_new (domain, mono_image_get_filename (assembly->assembly->image));
4311 return res;
4314 static MonoBoolean
4315 ves_icall_System_Reflection_Assembly_get_ReflectionOnly (MonoReflectionAssembly *assembly)
4317 MONO_ARCH_SAVE_REGS;
4319 return assembly->assembly->ref_only;
4322 static MonoString *
4323 ves_icall_System_Reflection_Assembly_InternalImageRuntimeVersion (MonoReflectionAssembly *assembly)
4325 MonoDomain *domain = mono_object_domain (assembly);
4327 MONO_ARCH_SAVE_REGS;
4329 return mono_string_new (domain, assembly->assembly->image->version);
4332 static MonoReflectionMethod*
4333 ves_icall_System_Reflection_Assembly_get_EntryPoint (MonoReflectionAssembly *assembly)
4335 guint32 token = mono_image_get_entry_point (assembly->assembly->image);
4337 MONO_ARCH_SAVE_REGS;
4339 if (!token)
4340 return NULL;
4341 return mono_method_get_object (mono_object_domain (assembly), mono_get_method (assembly->assembly->image, token, NULL), NULL);
4344 static MonoReflectionModule*
4345 ves_icall_System_Reflection_Assembly_GetManifestModuleInternal (MonoReflectionAssembly *assembly)
4347 return mono_module_get_object (mono_object_domain (assembly), assembly->assembly->image);
4350 static MonoArray*
4351 ves_icall_System_Reflection_Assembly_GetManifestResourceNames (MonoReflectionAssembly *assembly)
4353 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4354 MonoArray *result = mono_array_new (mono_object_domain (assembly), mono_defaults.string_class, table->rows);
4355 int i;
4356 const char *val;
4358 MONO_ARCH_SAVE_REGS;
4360 for (i = 0; i < table->rows; ++i) {
4361 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_MANIFEST_NAME));
4362 mono_array_setref (result, i, mono_string_new (mono_object_domain (assembly), val));
4364 return result;
4367 static MonoObject*
4368 create_version (MonoDomain *domain, guint32 major, guint32 minor, guint32 build, guint32 revision)
4370 static MonoClass *System_Version = NULL;
4371 static MonoMethod *create_version = NULL;
4372 MonoObject *result;
4373 gpointer args [4];
4375 if (!System_Version) {
4376 System_Version = mono_class_from_name (mono_defaults.corlib, "System", "Version");
4377 g_assert (System_Version);
4380 if (!create_version) {
4381 MonoMethodDesc *desc = mono_method_desc_new (":.ctor(int,int,int,int)", FALSE);
4382 create_version = mono_method_desc_search_in_class (desc, System_Version);
4383 g_assert (create_version);
4384 mono_method_desc_free (desc);
4387 args [0] = &major;
4388 args [1] = &minor;
4389 args [2] = &build;
4390 args [3] = &revision;
4391 result = mono_object_new (domain, System_Version);
4392 mono_runtime_invoke (create_version, result, args, NULL);
4394 return result;
4397 static MonoArray*
4398 ves_icall_System_Reflection_Assembly_GetReferencedAssemblies (MonoReflectionAssembly *assembly)
4400 static MonoClass *System_Reflection_AssemblyName;
4401 MonoArray *result;
4402 MonoDomain *domain = mono_object_domain (assembly);
4403 int i, count = 0;
4404 static MonoMethod *create_culture = NULL;
4405 MonoImage *image = assembly->assembly->image;
4406 MonoTableInfo *t;
4408 MONO_ARCH_SAVE_REGS;
4410 if (!System_Reflection_AssemblyName)
4411 System_Reflection_AssemblyName = mono_class_from_name (
4412 mono_defaults.corlib, "System.Reflection", "AssemblyName");
4414 t = &assembly->assembly->image->tables [MONO_TABLE_ASSEMBLYREF];
4415 count = t->rows;
4417 result = mono_array_new (domain, System_Reflection_AssemblyName, count);
4419 if (count > 0 && !create_culture) {
4420 MonoMethodDesc *desc = mono_method_desc_new (
4421 "System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE);
4422 create_culture = mono_method_desc_search_in_image (desc, mono_defaults.corlib);
4423 g_assert (create_culture);
4424 mono_method_desc_free (desc);
4427 for (i = 0; i < count; i++) {
4428 MonoReflectionAssemblyName *aname;
4429 guint32 cols [MONO_ASSEMBLYREF_SIZE];
4431 mono_metadata_decode_row (t, i, cols, MONO_ASSEMBLYREF_SIZE);
4433 aname = (MonoReflectionAssemblyName *) mono_object_new (
4434 domain, System_Reflection_AssemblyName);
4436 MONO_OBJECT_SETREF (aname, name, mono_string_new (domain, mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_NAME])));
4438 aname->major = cols [MONO_ASSEMBLYREF_MAJOR_VERSION];
4439 aname->minor = cols [MONO_ASSEMBLYREF_MINOR_VERSION];
4440 aname->build = cols [MONO_ASSEMBLYREF_BUILD_NUMBER];
4441 aname->revision = cols [MONO_ASSEMBLYREF_REV_NUMBER];
4442 aname->flags = cols [MONO_ASSEMBLYREF_FLAGS];
4443 aname->versioncompat = 1; /* SameMachine (default) */
4444 aname->hashalg = ASSEMBLY_HASH_SHA1; /* SHA1 (default) */
4445 MONO_OBJECT_SETREF (aname, version, create_version (domain, aname->major, aname->minor, aname->build, aname->revision));
4447 if (create_culture) {
4448 gpointer args [2];
4449 MonoBoolean assembly_ref = 1;
4450 args [0] = mono_string_new (domain, mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_CULTURE]));
4451 args [1] = &assembly_ref;
4452 MONO_OBJECT_SETREF (aname, cultureInfo, mono_runtime_invoke (create_culture, NULL, args, NULL));
4455 if (cols [MONO_ASSEMBLYREF_PUBLIC_KEY]) {
4456 const gchar *pkey_ptr = mono_metadata_blob_heap (image, cols [MONO_ASSEMBLYREF_PUBLIC_KEY]);
4457 guint32 pkey_len = mono_metadata_decode_blob_size (pkey_ptr, &pkey_ptr);
4459 if ((cols [MONO_ASSEMBLYREF_FLAGS] & ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG)) {
4460 /* public key token isn't copied - the class library will
4461 automatically generate it from the public key if required */
4462 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
4463 memcpy (mono_array_addr (aname->publicKey, guint8, 0), pkey_ptr, pkey_len);
4464 } else {
4465 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
4466 memcpy (mono_array_addr (aname->keyToken, guint8, 0), pkey_ptr, pkey_len);
4468 } else {
4469 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 0));
4472 /* note: this function doesn't return the codebase on purpose (i.e. it can
4473 be used under partial trust as path information isn't present). */
4475 mono_array_setref (result, i, aname);
4477 return result;
4480 typedef struct {
4481 MonoArray *res;
4482 int idx;
4483 } NameSpaceInfo;
4485 static void
4486 foreach_namespace (const char* key, gconstpointer val, NameSpaceInfo *info)
4488 MonoString *name = mono_string_new (mono_object_domain (info->res), key);
4490 mono_array_setref (info->res, info->idx, name);
4491 info->idx++;
4494 static MonoArray*
4495 ves_icall_System_Reflection_Assembly_GetNamespaces (MonoReflectionAssembly *assembly)
4497 MonoImage *img = assembly->assembly->image;
4498 MonoArray *res;
4499 NameSpaceInfo info;
4500 int len;
4502 MONO_ARCH_SAVE_REGS;
4504 mono_image_lock (img);
4505 mono_image_init_name_cache (img);
4507 RETRY_LEN:
4508 len = g_hash_table_size (img->name_cache);
4509 mono_image_unlock (img);
4511 /*we can't create objects holding the image lock */
4512 res = mono_array_new (mono_object_domain (assembly), mono_defaults.string_class, len);
4514 mono_image_lock (img);
4515 /*len might have changed, create a new array*/
4516 if (len != g_hash_table_size (img->name_cache))
4517 goto RETRY_LEN;
4519 info.res = res;
4520 info.idx = 0;
4521 g_hash_table_foreach (img->name_cache, (GHFunc)foreach_namespace, &info);
4522 mono_image_unlock (img);
4524 return res;
4527 /* move this in some file in mono/util/ */
4528 static char *
4529 g_concat_dir_and_file (const char *dir, const char *file)
4531 g_return_val_if_fail (dir != NULL, NULL);
4532 g_return_val_if_fail (file != NULL, NULL);
4535 * If the directory name doesn't have a / on the end, we need
4536 * to add one so we get a proper path to the file
4538 if (dir [strlen(dir) - 1] != G_DIR_SEPARATOR)
4539 return g_strconcat (dir, G_DIR_SEPARATOR_S, file, NULL);
4540 else
4541 return g_strconcat (dir, file, NULL);
4544 static void *
4545 ves_icall_System_Reflection_Assembly_GetManifestResourceInternal (MonoReflectionAssembly *assembly, MonoString *name, gint32 *size, MonoReflectionModule **ref_module)
4547 char *n = mono_string_to_utf8 (name);
4548 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4549 guint32 i;
4550 guint32 cols [MONO_MANIFEST_SIZE];
4551 guint32 impl, file_idx;
4552 const char *val;
4553 MonoImage *module;
4555 MONO_ARCH_SAVE_REGS;
4557 for (i = 0; i < table->rows; ++i) {
4558 mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
4559 val = mono_metadata_string_heap (assembly->assembly->image, cols [MONO_MANIFEST_NAME]);
4560 if (strcmp (val, n) == 0)
4561 break;
4563 g_free (n);
4564 if (i == table->rows)
4565 return NULL;
4566 /* FIXME */
4567 impl = cols [MONO_MANIFEST_IMPLEMENTATION];
4568 if (impl) {
4570 * this code should only be called after obtaining the
4571 * ResourceInfo and handling the other cases.
4573 g_assert ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_FILE);
4574 file_idx = impl >> MONO_IMPLEMENTATION_BITS;
4576 module = mono_image_load_file_for_image (assembly->assembly->image, file_idx);
4577 if (!module)
4578 return NULL;
4580 else
4581 module = assembly->assembly->image;
4583 mono_gc_wbarrier_generic_store (ref_module, (MonoObject*) mono_module_get_object (mono_domain_get (), module));
4585 return (void*)mono_image_get_resource (module, cols [MONO_MANIFEST_OFFSET], (guint32*)size);
4588 static gboolean
4589 ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (MonoReflectionAssembly *assembly, MonoString *name, MonoManifestResourceInfo *info)
4591 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4592 int i;
4593 guint32 cols [MONO_MANIFEST_SIZE];
4594 guint32 file_cols [MONO_FILE_SIZE];
4595 const char *val;
4596 char *n;
4598 MONO_ARCH_SAVE_REGS;
4600 n = mono_string_to_utf8 (name);
4601 for (i = 0; i < table->rows; ++i) {
4602 mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
4603 val = mono_metadata_string_heap (assembly->assembly->image, cols [MONO_MANIFEST_NAME]);
4604 if (strcmp (val, n) == 0)
4605 break;
4607 g_free (n);
4608 if (i == table->rows)
4609 return FALSE;
4611 if (!cols [MONO_MANIFEST_IMPLEMENTATION]) {
4612 info->location = RESOURCE_LOCATION_EMBEDDED | RESOURCE_LOCATION_IN_MANIFEST;
4614 else {
4615 switch (cols [MONO_MANIFEST_IMPLEMENTATION] & MONO_IMPLEMENTATION_MASK) {
4616 case MONO_IMPLEMENTATION_FILE:
4617 i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
4618 table = &assembly->assembly->image->tables [MONO_TABLE_FILE];
4619 mono_metadata_decode_row (table, i - 1, file_cols, MONO_FILE_SIZE);
4620 val = mono_metadata_string_heap (assembly->assembly->image, file_cols [MONO_FILE_NAME]);
4621 MONO_OBJECT_SETREF (info, filename, mono_string_new (mono_object_domain (assembly), val));
4622 if (file_cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA)
4623 info->location = 0;
4624 else
4625 info->location = RESOURCE_LOCATION_EMBEDDED;
4626 break;
4628 case MONO_IMPLEMENTATION_ASSEMBLYREF:
4629 i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
4630 mono_assembly_load_reference (assembly->assembly->image, i - 1);
4631 if (assembly->assembly->image->references [i - 1] == (gpointer)-1) {
4632 char *msg = g_strdup_printf ("Assembly %d referenced from assembly %s not found ", i - 1, assembly->assembly->image->name);
4633 MonoException *ex = mono_get_exception_file_not_found2 (msg, NULL);
4634 g_free (msg);
4635 mono_raise_exception (ex);
4637 MONO_OBJECT_SETREF (info, assembly, mono_assembly_get_object (mono_domain_get (), assembly->assembly->image->references [i - 1]));
4639 /* Obtain info recursively */
4640 ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (info->assembly, name, info);
4641 info->location |= RESOURCE_LOCATION_ANOTHER_ASSEMBLY;
4642 break;
4644 case MONO_IMPLEMENTATION_EXP_TYPE:
4645 g_assert_not_reached ();
4646 break;
4650 return TRUE;
4653 static MonoObject*
4654 ves_icall_System_Reflection_Assembly_GetFilesInternal (MonoReflectionAssembly *assembly, MonoString *name, MonoBoolean resource_modules)
4656 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_FILE];
4657 MonoArray *result = NULL;
4658 int i, count;
4659 const char *val;
4660 char *n;
4662 MONO_ARCH_SAVE_REGS;
4664 /* check hash if needed */
4665 if (name) {
4666 n = mono_string_to_utf8 (name);
4667 for (i = 0; i < table->rows; ++i) {
4668 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_FILE_NAME));
4669 if (strcmp (val, n) == 0) {
4670 MonoString *fn;
4671 g_free (n);
4672 n = g_concat_dir_and_file (assembly->assembly->basedir, val);
4673 fn = mono_string_new (mono_object_domain (assembly), n);
4674 g_free (n);
4675 return (MonoObject*)fn;
4678 g_free (n);
4679 return NULL;
4682 count = 0;
4683 for (i = 0; i < table->rows; ++i) {
4684 if (resource_modules || !(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA))
4685 count ++;
4688 result = mono_array_new (mono_object_domain (assembly), mono_defaults.string_class, count);
4690 count = 0;
4691 for (i = 0; i < table->rows; ++i) {
4692 if (resource_modules || !(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
4693 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_FILE_NAME));
4694 n = g_concat_dir_and_file (assembly->assembly->basedir, val);
4695 mono_array_setref (result, count, mono_string_new (mono_object_domain (assembly), n));
4696 g_free (n);
4697 count ++;
4700 return (MonoObject*)result;
4703 static MonoArray*
4704 ves_icall_System_Reflection_Assembly_GetModulesInternal (MonoReflectionAssembly *assembly)
4706 MonoDomain *domain = mono_domain_get();
4707 MonoArray *res;
4708 MonoClass *klass;
4709 int i, j, file_count = 0;
4710 MonoImage **modules;
4711 guint32 module_count, real_module_count;
4712 MonoTableInfo *table;
4713 guint32 cols [MONO_FILE_SIZE];
4714 MonoImage *image = assembly->assembly->image;
4716 g_assert (image != NULL);
4717 g_assert (!assembly->assembly->dynamic);
4719 table = &image->tables [MONO_TABLE_FILE];
4720 file_count = table->rows;
4722 modules = image->modules;
4723 module_count = image->module_count;
4725 real_module_count = 0;
4726 for (i = 0; i < module_count; ++i)
4727 if (modules [i])
4728 real_module_count ++;
4730 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Module");
4731 res = mono_array_new (domain, klass, 1 + real_module_count + file_count);
4733 mono_array_setref (res, 0, mono_module_get_object (domain, image));
4734 j = 1;
4735 for (i = 0; i < module_count; ++i)
4736 if (modules [i]) {
4737 mono_array_setref (res, j, mono_module_get_object (domain, modules[i]));
4738 ++j;
4741 for (i = 0; i < file_count; ++i, ++j) {
4742 mono_metadata_decode_row (table, i, cols, MONO_FILE_SIZE);
4743 if (cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA)
4744 mono_array_setref (res, j, mono_module_file_get_object (domain, image, i));
4745 else {
4746 MonoImage *m = mono_image_load_file_for_image (image, i + 1);
4747 if (!m) {
4748 MonoString *fname = mono_string_new (mono_domain_get (), mono_metadata_string_heap (image, cols [MONO_FILE_NAME]));
4749 mono_raise_exception (mono_get_exception_file_not_found2 (NULL, fname));
4751 mono_array_setref (res, j, mono_module_get_object (domain, m));
4755 return res;
4758 static MonoReflectionMethod*
4759 ves_icall_GetCurrentMethod (void)
4761 MonoMethod *m = mono_method_get_last_managed ();
4763 while (m->is_inflated)
4764 m = ((MonoMethodInflated*)m)->declaring;
4766 return mono_method_get_object (mono_domain_get (), m, NULL);
4770 static MonoMethod*
4771 mono_method_get_equivalent_method (MonoMethod *method, MonoClass *klass)
4773 int offset = -1, i;
4774 if (method->is_inflated && ((MonoMethodInflated*)method)->context.method_inst) {
4775 MonoMethodInflated *inflated = (MonoMethodInflated*)method;
4776 //method is inflated, we should inflate it on the other class
4777 MonoGenericContext ctx;
4778 ctx.method_inst = inflated->context.method_inst;
4779 ctx.class_inst = inflated->context.class_inst;
4780 if (klass->generic_class)
4781 ctx.class_inst = klass->generic_class->context.class_inst;
4782 else if (klass->generic_container)
4783 ctx.class_inst = klass->generic_container->context.class_inst;
4784 return mono_class_inflate_generic_method_full (inflated->declaring, klass, &ctx);
4787 mono_class_setup_methods (method->klass);
4788 if (method->klass->exception_type)
4789 return NULL;
4790 for (i = 0; i < method->klass->method.count; ++i) {
4791 if (method->klass->methods [i] == method) {
4792 offset = i;
4793 break;
4796 mono_class_setup_methods (klass);
4797 if (klass->exception_type)
4798 return NULL;
4799 g_assert (offset >= 0 && offset < klass->method.count);
4800 return klass->methods [offset];
4803 static MonoReflectionMethod*
4804 ves_icall_System_Reflection_MethodBase_GetMethodFromHandleInternalType (MonoMethod *method, MonoType *type)
4806 MonoClass *klass;
4807 if (type) {
4808 klass = mono_class_from_mono_type (type);
4809 if (mono_class_get_generic_type_definition (method->klass) != mono_class_get_generic_type_definition (klass))
4810 return NULL;
4811 if (method->klass != klass) {
4812 method = mono_method_get_equivalent_method (method, klass);
4813 if (!method)
4814 return NULL;
4816 } else
4817 klass = method->klass;
4818 return mono_method_get_object (mono_domain_get (), method, klass);
4821 static MonoReflectionMethod*
4822 ves_icall_System_Reflection_MethodBase_GetMethodFromHandleInternal (MonoMethod *method)
4824 return mono_method_get_object (mono_domain_get (), method, NULL);
4827 static MonoReflectionMethodBody*
4828 ves_icall_System_Reflection_MethodBase_GetMethodBodyInternal (MonoMethod *method)
4830 return mono_method_body_get_object (mono_domain_get (), method);
4833 static MonoReflectionAssembly*
4834 ves_icall_System_Reflection_Assembly_GetExecutingAssembly (void)
4836 MonoMethod *dest = NULL;
4838 MONO_ARCH_SAVE_REGS;
4840 mono_stack_walk_no_il (get_executing, &dest);
4841 return mono_assembly_get_object (mono_domain_get (), dest->klass->image->assembly);
4845 static MonoReflectionAssembly*
4846 ves_icall_System_Reflection_Assembly_GetEntryAssembly (void)
4848 MonoDomain* domain = mono_domain_get ();
4850 MONO_ARCH_SAVE_REGS;
4852 if (!domain->entry_assembly)
4853 return NULL;
4855 return mono_assembly_get_object (domain, domain->entry_assembly);
4858 static MonoReflectionAssembly*
4859 ves_icall_System_Reflection_Assembly_GetCallingAssembly (void)
4861 MonoMethod *m;
4862 MonoMethod *dest;
4864 MONO_ARCH_SAVE_REGS;
4866 dest = NULL;
4867 mono_stack_walk_no_il (get_executing, &dest);
4868 m = dest;
4869 mono_stack_walk_no_il (get_caller, &dest);
4870 if (!dest)
4871 dest = m;
4872 return mono_assembly_get_object (mono_domain_get (), dest->klass->image->assembly);
4875 static MonoString *
4876 ves_icall_System_MonoType_getFullName (MonoReflectionType *object, gboolean full_name,
4877 gboolean assembly_qualified)
4879 MonoDomain *domain = mono_object_domain (object);
4880 MonoTypeNameFormat format;
4881 MonoString *res;
4882 gchar *name;
4884 if (full_name)
4885 format = assembly_qualified ?
4886 MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED :
4887 MONO_TYPE_NAME_FORMAT_FULL_NAME;
4888 else
4889 format = MONO_TYPE_NAME_FORMAT_REFLECTION;
4891 name = mono_type_get_name_full (object->type, format);
4892 if (!name)
4893 return NULL;
4895 if (full_name && (object->type->type == MONO_TYPE_VAR || object->type->type == MONO_TYPE_MVAR)) {
4896 g_free (name);
4897 return NULL;
4900 res = mono_string_new (domain, name);
4901 g_free (name);
4903 return res;
4906 static int
4907 vell_icall_MonoType_get_core_clr_security_level (MonoReflectionType *this)
4909 MonoClass *klass = mono_class_from_mono_type (this->type);
4910 mono_class_init_or_throw (klass);
4911 return mono_security_core_clr_class_level (klass);
4914 static void
4915 fill_reflection_assembly_name (MonoDomain *domain, MonoReflectionAssemblyName *aname, MonoAssemblyName *name, const char *absolute, gboolean by_default_version, gboolean default_publickey, gboolean default_token)
4917 static MonoMethod *create_culture = NULL;
4918 gpointer args [2];
4919 guint32 pkey_len;
4920 const char *pkey_ptr;
4921 gchar *codebase;
4922 MonoBoolean assembly_ref = 0;
4924 MONO_ARCH_SAVE_REGS;
4926 MONO_OBJECT_SETREF (aname, name, mono_string_new (domain, name->name));
4927 aname->major = name->major;
4928 aname->minor = name->minor;
4929 aname->build = name->build;
4930 aname->flags = name->flags;
4931 aname->revision = name->revision;
4932 aname->hashalg = name->hash_alg;
4933 aname->versioncompat = 1; /* SameMachine (default) */
4935 if (by_default_version)
4936 MONO_OBJECT_SETREF (aname, version, create_version (domain, name->major, name->minor, name->build, name->revision));
4938 codebase = NULL;
4939 if (absolute != NULL && *absolute != '\0') {
4940 const gchar *prepend = "file://";
4941 gchar *result;
4943 codebase = g_strdup (absolute);
4945 #if HOST_WIN32
4947 gint i;
4948 for (i = strlen (codebase) - 1; i >= 0; i--)
4949 if (codebase [i] == '\\')
4950 codebase [i] = '/';
4952 if (*codebase == '/' && *(codebase + 1) == '/') {
4953 prepend = "file:";
4954 } else {
4955 prepend = "file:///";
4958 #endif
4959 result = g_strconcat (prepend, codebase, NULL);
4960 g_free (codebase);
4961 codebase = result;
4964 if (codebase) {
4965 MONO_OBJECT_SETREF (aname, codebase, mono_string_new (domain, codebase));
4966 g_free (codebase);
4969 if (!create_culture) {
4970 MonoMethodDesc *desc = mono_method_desc_new ("System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE);
4971 create_culture = mono_method_desc_search_in_image (desc, mono_defaults.corlib);
4972 g_assert (create_culture);
4973 mono_method_desc_free (desc);
4976 if (name->culture) {
4977 args [0] = mono_string_new (domain, name->culture);
4978 args [1] = &assembly_ref;
4979 MONO_OBJECT_SETREF (aname, cultureInfo, mono_runtime_invoke (create_culture, NULL, args, NULL));
4982 if (name->public_key) {
4983 pkey_ptr = (char*)name->public_key;
4984 pkey_len = mono_metadata_decode_blob_size (pkey_ptr, &pkey_ptr);
4986 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
4987 memcpy (mono_array_addr (aname->publicKey, guint8, 0), pkey_ptr, pkey_len);
4988 aname->flags |= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG;
4989 } else if (default_publickey) {
4990 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, 0));
4991 aname->flags |= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG;
4994 /* MonoAssemblyName keeps the public key token as an hexadecimal string */
4995 if (name->public_key_token [0]) {
4996 int i, j;
4997 char *p;
4999 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 8));
5000 p = mono_array_addr (aname->keyToken, char, 0);
5002 for (i = 0, j = 0; i < 8; i++) {
5003 *p = g_ascii_xdigit_value (name->public_key_token [j++]) << 4;
5004 *p |= g_ascii_xdigit_value (name->public_key_token [j++]);
5005 p++;
5007 } else if (default_token) {
5008 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 0));
5012 static MonoString *
5013 ves_icall_System_Reflection_Assembly_get_fullName (MonoReflectionAssembly *assembly)
5015 MonoDomain *domain = mono_object_domain (assembly);
5016 MonoAssembly *mass = assembly->assembly;
5017 MonoString *res;
5018 gchar *name;
5020 name = mono_stringify_assembly_name (&mass->aname);
5021 res = mono_string_new (domain, name);
5022 g_free (name);
5024 return res;
5027 static void
5028 ves_icall_System_Reflection_Assembly_FillName (MonoReflectionAssembly *assembly, MonoReflectionAssemblyName *aname)
5030 gchar *absolute;
5031 MonoAssembly *mass = assembly->assembly;
5033 MONO_ARCH_SAVE_REGS;
5035 if (g_path_is_absolute (mass->image->name)) {
5036 fill_reflection_assembly_name (mono_object_domain (assembly),
5037 aname, &mass->aname, mass->image->name, TRUE,
5038 TRUE, TRUE);
5039 return;
5041 absolute = g_build_filename (mass->basedir, mass->image->name, NULL);
5043 fill_reflection_assembly_name (mono_object_domain (assembly),
5044 aname, &mass->aname, absolute, TRUE, TRUE,
5045 TRUE);
5047 g_free (absolute);
5050 static void
5051 ves_icall_System_Reflection_Assembly_InternalGetAssemblyName (MonoString *fname, MonoReflectionAssemblyName *aname)
5053 char *filename;
5054 MonoImageOpenStatus status = MONO_IMAGE_OK;
5055 gboolean res;
5056 MonoImage *image;
5057 MonoAssemblyName name;
5058 char *dirname
5060 MONO_ARCH_SAVE_REGS;
5062 filename = mono_string_to_utf8 (fname);
5064 dirname = g_path_get_dirname (filename);
5065 replace_shadow_path (mono_domain_get (), dirname, &filename);
5066 g_free (dirname);
5068 image = mono_image_open (filename, &status);
5070 if (!image){
5071 MonoException *exc;
5073 g_free (filename);
5074 if (status == MONO_IMAGE_IMAGE_INVALID)
5075 exc = mono_get_exception_bad_image_format2 (NULL, fname);
5076 else
5077 exc = mono_get_exception_file_not_found2 (NULL, fname);
5078 mono_raise_exception (exc);
5081 res = mono_assembly_fill_assembly_name (image, &name);
5082 if (!res) {
5083 mono_image_close (image);
5084 g_free (filename);
5085 mono_raise_exception (mono_get_exception_argument ("assemblyFile", "The file does not contain a manifest"));
5088 fill_reflection_assembly_name (mono_domain_get (), aname, &name, filename,
5089 TRUE, FALSE, TRUE);
5091 g_free (filename);
5092 mono_image_close (image);
5095 static MonoBoolean
5096 ves_icall_System_Reflection_Assembly_LoadPermissions (MonoReflectionAssembly *assembly,
5097 char **minimum, guint32 *minLength, char **optional, guint32 *optLength, char **refused, guint32 *refLength)
5099 MonoBoolean result = FALSE;
5100 MonoDeclSecurityEntry entry;
5102 /* SecurityAction.RequestMinimum */
5103 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQMIN, &entry)) {
5104 *minimum = entry.blob;
5105 *minLength = entry.size;
5106 result = TRUE;
5108 /* SecurityAction.RequestOptional */
5109 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQOPT, &entry)) {
5110 *optional = entry.blob;
5111 *optLength = entry.size;
5112 result = TRUE;
5114 /* SecurityAction.RequestRefuse */
5115 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQREFUSE, &entry)) {
5116 *refused = entry.blob;
5117 *refLength = entry.size;
5118 result = TRUE;
5121 return result;
5124 static MonoArray*
5125 mono_module_get_types (MonoDomain *domain, MonoImage *image, MonoArray **exceptions, MonoBoolean exportedOnly)
5127 MonoArray *res;
5128 MonoClass *klass;
5129 MonoTableInfo *tdef = &image->tables [MONO_TABLE_TYPEDEF];
5130 int i, count;
5131 guint32 attrs, visibility;
5133 /* we start the count from 1 because we skip the special type <Module> */
5134 if (exportedOnly) {
5135 count = 0;
5136 for (i = 1; i < tdef->rows; ++i) {
5137 attrs = mono_metadata_decode_row_col (tdef, i, MONO_TYPEDEF_FLAGS);
5138 visibility = attrs & TYPE_ATTRIBUTE_VISIBILITY_MASK;
5139 if (visibility == TYPE_ATTRIBUTE_PUBLIC || visibility == TYPE_ATTRIBUTE_NESTED_PUBLIC)
5140 count++;
5142 } else {
5143 count = tdef->rows - 1;
5145 res = mono_array_new (domain, mono_defaults.monotype_class, count);
5146 *exceptions = mono_array_new (domain, mono_defaults.exception_class, count);
5147 count = 0;
5148 for (i = 1; i < tdef->rows; ++i) {
5149 attrs = mono_metadata_decode_row_col (tdef, i, MONO_TYPEDEF_FLAGS);
5150 visibility = attrs & TYPE_ATTRIBUTE_VISIBILITY_MASK;
5151 if (!exportedOnly || (visibility == TYPE_ATTRIBUTE_PUBLIC || visibility == TYPE_ATTRIBUTE_NESTED_PUBLIC)) {
5152 klass = mono_class_get (image, (i + 1) | MONO_TOKEN_TYPE_DEF);
5153 if (klass) {
5154 mono_array_setref (res, count, mono_type_get_object (domain, &klass->byval_arg));
5155 } else {
5156 MonoLoaderError *error;
5157 MonoException *ex;
5159 error = mono_loader_get_last_error ();
5160 g_assert (error != NULL);
5162 ex = mono_loader_error_prepare_exception (error);
5163 mono_array_setref (*exceptions, count, ex);
5165 if (mono_loader_get_last_error ())
5166 mono_loader_clear_error ();
5167 count++;
5171 return res;
5174 static MonoArray*
5175 ves_icall_System_Reflection_Assembly_GetTypes (MonoReflectionAssembly *assembly, MonoBoolean exportedOnly)
5177 MonoArray *res = NULL;
5178 MonoArray *exceptions = NULL;
5179 MonoImage *image = NULL;
5180 MonoTableInfo *table = NULL;
5181 MonoDomain *domain;
5182 GList *list = NULL;
5183 int i, len, ex_count;
5185 MONO_ARCH_SAVE_REGS;
5187 domain = mono_object_domain (assembly);
5189 g_assert (!assembly->assembly->dynamic);
5190 image = assembly->assembly->image;
5191 table = &image->tables [MONO_TABLE_FILE];
5192 res = mono_module_get_types (domain, image, &exceptions, exportedOnly);
5194 /* Append data from all modules in the assembly */
5195 for (i = 0; i < table->rows; ++i) {
5196 if (!(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
5197 MonoImage *loaded_image = mono_assembly_load_module (image->assembly, i + 1);
5198 if (loaded_image) {
5199 MonoArray *ex2;
5200 MonoArray *res2 = mono_module_get_types (domain, loaded_image, &ex2, exportedOnly);
5201 /* Append the new types to the end of the array */
5202 if (mono_array_length (res2) > 0) {
5203 guint32 len1, len2;
5204 MonoArray *res3, *ex3;
5206 len1 = mono_array_length (res);
5207 len2 = mono_array_length (res2);
5209 res3 = mono_array_new (domain, mono_defaults.monotype_class, len1 + len2);
5210 mono_array_memcpy_refs (res3, 0, res, 0, len1);
5211 mono_array_memcpy_refs (res3, len1, res2, 0, len2);
5212 res = res3;
5214 ex3 = mono_array_new (domain, mono_defaults.monotype_class, len1 + len2);
5215 mono_array_memcpy_refs (ex3, 0, exceptions, 0, len1);
5216 mono_array_memcpy_refs (ex3, len1, ex2, 0, len2);
5217 exceptions = ex3;
5223 /* the ReflectionTypeLoadException must have all the types (Types property),
5224 * NULL replacing types which throws an exception. The LoaderException must
5225 * contain all exceptions for NULL items.
5228 len = mono_array_length (res);
5230 ex_count = 0;
5231 for (i = 0; i < len; i++) {
5232 MonoReflectionType *t = mono_array_get (res, gpointer, i);
5233 MonoClass *klass;
5235 if (t) {
5236 klass = mono_type_get_class (t->type);
5237 if ((klass != NULL) && klass->exception_type) {
5238 /* keep the class in the list */
5239 list = g_list_append (list, klass);
5240 /* and replace Type with NULL */
5241 mono_array_setref (res, i, NULL);
5243 } else {
5244 ex_count ++;
5248 if (list || ex_count) {
5249 GList *tmp = NULL;
5250 MonoException *exc = NULL;
5251 MonoArray *exl = NULL;
5252 int j, length = g_list_length (list) + ex_count;
5254 mono_loader_clear_error ();
5256 exl = mono_array_new (domain, mono_defaults.exception_class, length);
5257 /* Types for which mono_class_get () succeeded */
5258 for (i = 0, tmp = list; tmp; i++, tmp = tmp->next) {
5259 MonoException *exc = mono_class_get_exception_for_failure (tmp->data);
5260 mono_array_setref (exl, i, exc);
5262 /* Types for which it don't */
5263 for (j = 0; j < mono_array_length (exceptions); ++j) {
5264 MonoException *exc = mono_array_get (exceptions, MonoException*, j);
5265 if (exc) {
5266 g_assert (i < length);
5267 mono_array_setref (exl, i, exc);
5268 i ++;
5271 g_list_free (list);
5272 list = NULL;
5274 exc = mono_get_exception_reflection_type_load (res, exl);
5275 mono_loader_clear_error ();
5276 mono_raise_exception (exc);
5279 return res;
5282 static gboolean
5283 ves_icall_System_Reflection_AssemblyName_ParseName (MonoReflectionAssemblyName *name, MonoString *assname)
5285 MonoAssemblyName aname;
5286 MonoDomain *domain = mono_object_domain (name);
5287 char *val;
5288 gboolean is_version_defined;
5289 gboolean is_token_defined;
5291 aname.public_key = NULL;
5292 val = mono_string_to_utf8 (assname);
5293 if (!mono_assembly_name_parse_full (val, &aname, TRUE, &is_version_defined, &is_token_defined)) {
5294 g_free ((guint8*) aname.public_key);
5295 g_free (val);
5296 return FALSE;
5299 fill_reflection_assembly_name (domain, name, &aname, "", is_version_defined,
5300 FALSE, is_token_defined);
5302 mono_assembly_name_free (&aname);
5303 g_free ((guint8*) aname.public_key);
5304 g_free (val);
5306 return TRUE;
5309 static MonoReflectionType*
5310 ves_icall_System_Reflection_Module_GetGlobalType (MonoReflectionModule *module)
5312 MonoDomain *domain = mono_object_domain (module);
5313 MonoClass *klass;
5315 MONO_ARCH_SAVE_REGS;
5317 g_assert (module->image);
5319 if (module->image->dynamic && ((MonoDynamicImage*)(module->image))->initial_image)
5320 /* These images do not have a global type */
5321 return NULL;
5323 klass = mono_class_get (module->image, 1 | MONO_TOKEN_TYPE_DEF);
5324 return mono_type_get_object (domain, &klass->byval_arg);
5327 static void
5328 ves_icall_System_Reflection_Module_Close (MonoReflectionModule *module)
5330 /*if (module->image)
5331 mono_image_close (module->image);*/
5334 static MonoString*
5335 ves_icall_System_Reflection_Module_GetGuidInternal (MonoReflectionModule *module)
5337 MonoDomain *domain = mono_object_domain (module);
5339 MONO_ARCH_SAVE_REGS;
5341 g_assert (module->image);
5342 return mono_string_new (domain, module->image->guid);
5345 static gpointer
5346 ves_icall_System_Reflection_Module_GetHINSTANCE (MonoReflectionModule *module)
5348 #ifdef HOST_WIN32
5349 if (module->image && module->image->is_module_handle)
5350 return module->image->raw_data;
5351 #endif
5353 return (gpointer) (-1);
5356 static void
5357 ves_icall_System_Reflection_Module_GetPEKind (MonoImage *image, gint32 *pe_kind, gint32 *machine)
5359 if (image->dynamic) {
5360 MonoDynamicImage *dyn = (MonoDynamicImage*)image;
5361 *pe_kind = dyn->pe_kind;
5362 *machine = dyn->machine;
5364 else {
5365 *pe_kind = ((MonoCLIImageInfo*)(image->image_info))->cli_cli_header.ch_flags & 0x3;
5366 *machine = ((MonoCLIImageInfo*)(image->image_info))->cli_header.coff.coff_machine;
5370 static gint32
5371 ves_icall_System_Reflection_Module_GetMDStreamVersion (MonoImage *image)
5373 return (image->md_version_major << 16) | (image->md_version_minor);
5376 static MonoArray*
5377 ves_icall_System_Reflection_Module_InternalGetTypes (MonoReflectionModule *module)
5379 MonoArray *exceptions;
5380 int i;
5382 MONO_ARCH_SAVE_REGS;
5384 if (!module->image)
5385 return mono_array_new (mono_object_domain (module), mono_defaults.monotype_class, 0);
5386 else {
5387 MonoArray *res = mono_module_get_types (mono_object_domain (module), module->image, &exceptions, FALSE);
5388 for (i = 0; i < mono_array_length (exceptions); ++i) {
5389 MonoException *ex = mono_array_get (exceptions, MonoException *, i);
5390 if (ex)
5391 mono_raise_exception (ex);
5393 return res;
5397 static gboolean
5398 mono_memberref_is_method (MonoImage *image, guint32 token)
5400 if (!image->dynamic) {
5401 guint32 cols [MONO_MEMBERREF_SIZE];
5402 const char *sig;
5403 mono_metadata_decode_row (&image->tables [MONO_TABLE_MEMBERREF], mono_metadata_token_index (token) - 1, cols, MONO_MEMBERREF_SIZE);
5404 sig = mono_metadata_blob_heap (image, cols [MONO_MEMBERREF_SIGNATURE]);
5405 mono_metadata_decode_blob_size (sig, &sig);
5406 return (*sig != 0x6);
5407 } else {
5408 MonoClass *handle_class;
5410 if (!mono_lookup_dynamic_token_class (image, token, FALSE, &handle_class, NULL))
5411 return FALSE;
5413 return mono_defaults.methodhandle_class == handle_class;
5417 static void
5418 init_generic_context_from_args (MonoGenericContext *context, MonoArray *type_args, MonoArray *method_args)
5420 if (type_args)
5421 context->class_inst = mono_metadata_get_generic_inst (mono_array_length (type_args),
5422 mono_array_addr (type_args, MonoType*, 0));
5423 else
5424 context->class_inst = NULL;
5425 if (method_args)
5426 context->method_inst = mono_metadata_get_generic_inst (mono_array_length (method_args),
5427 mono_array_addr (method_args, MonoType*, 0));
5428 else
5429 context->method_inst = NULL;
5432 static MonoType*
5433 ves_icall_System_Reflection_Module_ResolveTypeToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5435 MonoClass *klass;
5436 int table = mono_metadata_token_table (token);
5437 int index = mono_metadata_token_index (token);
5438 MonoGenericContext context;
5440 *error = ResolveTokenError_Other;
5442 /* Validate token */
5443 if ((table != MONO_TABLE_TYPEDEF) && (table != MONO_TABLE_TYPEREF) &&
5444 (table != MONO_TABLE_TYPESPEC)) {
5445 *error = ResolveTokenError_BadTable;
5446 return NULL;
5449 if (image->dynamic) {
5450 if ((table == MONO_TABLE_TYPEDEF) || (table == MONO_TABLE_TYPEREF)) {
5451 klass = mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5452 return klass ? &klass->byval_arg : NULL;
5455 init_generic_context_from_args (&context, type_args, method_args);
5456 klass = mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context);
5457 return klass ? &klass->byval_arg : NULL;
5460 if ((index <= 0) || (index > image->tables [table].rows)) {
5461 *error = ResolveTokenError_OutOfRange;
5462 return NULL;
5465 init_generic_context_from_args (&context, type_args, method_args);
5466 klass = mono_class_get_full (image, token, &context);
5468 if (mono_loader_get_last_error ())
5469 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
5471 if (klass)
5472 return &klass->byval_arg;
5473 else
5474 return NULL;
5477 static MonoMethod*
5478 ves_icall_System_Reflection_Module_ResolveMethodToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5480 int table = mono_metadata_token_table (token);
5481 int index = mono_metadata_token_index (token);
5482 MonoGenericContext context;
5483 MonoMethod *method;
5485 *error = ResolveTokenError_Other;
5487 /* Validate token */
5488 if ((table != MONO_TABLE_METHOD) && (table != MONO_TABLE_METHODSPEC) &&
5489 (table != MONO_TABLE_MEMBERREF)) {
5490 *error = ResolveTokenError_BadTable;
5491 return NULL;
5494 if (image->dynamic) {
5495 if (table == MONO_TABLE_METHOD)
5496 return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5498 if ((table == MONO_TABLE_MEMBERREF) && !(mono_memberref_is_method (image, token))) {
5499 *error = ResolveTokenError_BadTable;
5500 return NULL;
5503 init_generic_context_from_args (&context, type_args, method_args);
5504 return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context);
5507 if ((index <= 0) || (index > image->tables [table].rows)) {
5508 *error = ResolveTokenError_OutOfRange;
5509 return NULL;
5511 if ((table == MONO_TABLE_MEMBERREF) && (!mono_memberref_is_method (image, token))) {
5512 *error = ResolveTokenError_BadTable;
5513 return NULL;
5516 init_generic_context_from_args (&context, type_args, method_args);
5517 method = mono_get_method_full (image, token, NULL, &context);
5519 if (mono_loader_get_last_error ())
5520 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
5522 return method;
5525 static MonoString*
5526 ves_icall_System_Reflection_Module_ResolveStringToken (MonoImage *image, guint32 token, MonoResolveTokenError *error)
5528 int index = mono_metadata_token_index (token);
5530 *error = ResolveTokenError_Other;
5532 /* Validate token */
5533 if (mono_metadata_token_code (token) != MONO_TOKEN_STRING) {
5534 *error = ResolveTokenError_BadTable;
5535 return NULL;
5538 if (image->dynamic)
5539 return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5541 if ((index <= 0) || (index >= image->heap_us.size)) {
5542 *error = ResolveTokenError_OutOfRange;
5543 return NULL;
5546 /* FIXME: What to do if the index points into the middle of a string ? */
5548 return mono_ldstr (mono_domain_get (), image, index);
5551 static MonoClassField*
5552 ves_icall_System_Reflection_Module_ResolveFieldToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5554 MonoClass *klass;
5555 int table = mono_metadata_token_table (token);
5556 int index = mono_metadata_token_index (token);
5557 MonoGenericContext context;
5558 MonoClassField *field;
5560 *error = ResolveTokenError_Other;
5562 /* Validate token */
5563 if ((table != MONO_TABLE_FIELD) && (table != MONO_TABLE_MEMBERREF)) {
5564 *error = ResolveTokenError_BadTable;
5565 return NULL;
5568 if (image->dynamic) {
5569 if (table == MONO_TABLE_FIELD)
5570 return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5572 if (mono_memberref_is_method (image, token)) {
5573 *error = ResolveTokenError_BadTable;
5574 return NULL;
5577 init_generic_context_from_args (&context, type_args, method_args);
5578 return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context);
5581 if ((index <= 0) || (index > image->tables [table].rows)) {
5582 *error = ResolveTokenError_OutOfRange;
5583 return NULL;
5585 if ((table == MONO_TABLE_MEMBERREF) && (mono_memberref_is_method (image, token))) {
5586 *error = ResolveTokenError_BadTable;
5587 return NULL;
5590 init_generic_context_from_args (&context, type_args, method_args);
5591 field = mono_field_from_token (image, token, &klass, &context);
5593 if (mono_loader_get_last_error ())
5594 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
5596 return field;
5600 static MonoObject*
5601 ves_icall_System_Reflection_Module_ResolveMemberToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5603 int table = mono_metadata_token_table (token);
5605 *error = ResolveTokenError_Other;
5607 switch (table) {
5608 case MONO_TABLE_TYPEDEF:
5609 case MONO_TABLE_TYPEREF:
5610 case MONO_TABLE_TYPESPEC: {
5611 MonoType *t = ves_icall_System_Reflection_Module_ResolveTypeToken (image, token, type_args, method_args, error);
5612 if (t)
5613 return (MonoObject*)mono_type_get_object (mono_domain_get (), t);
5614 else
5615 return NULL;
5617 case MONO_TABLE_METHOD:
5618 case MONO_TABLE_METHODSPEC: {
5619 MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
5620 if (m)
5621 return (MonoObject*)mono_method_get_object (mono_domain_get (), m, m->klass);
5622 else
5623 return NULL;
5625 case MONO_TABLE_FIELD: {
5626 MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
5627 if (f)
5628 return (MonoObject*)mono_field_get_object (mono_domain_get (), f->parent, f);
5629 else
5630 return NULL;
5632 case MONO_TABLE_MEMBERREF:
5633 if (mono_memberref_is_method (image, token)) {
5634 MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
5635 if (m)
5636 return (MonoObject*)mono_method_get_object (mono_domain_get (), m, m->klass);
5637 else
5638 return NULL;
5640 else {
5641 MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
5642 if (f)
5643 return (MonoObject*)mono_field_get_object (mono_domain_get (), f->parent, f);
5644 else
5645 return NULL;
5647 break;
5649 default:
5650 *error = ResolveTokenError_BadTable;
5653 return NULL;
5656 static MonoArray*
5657 ves_icall_System_Reflection_Module_ResolveSignature (MonoImage *image, guint32 token, MonoResolveTokenError *error)
5659 int table = mono_metadata_token_table (token);
5660 int idx = mono_metadata_token_index (token);
5661 MonoTableInfo *tables = image->tables;
5662 guint32 sig, len;
5663 const char *ptr;
5664 MonoArray *res;
5666 *error = ResolveTokenError_OutOfRange;
5668 /* FIXME: Support other tables ? */
5669 if (table != MONO_TABLE_STANDALONESIG)
5670 return NULL;
5672 if (image->dynamic)
5673 return NULL;
5675 if ((idx == 0) || (idx > tables [MONO_TABLE_STANDALONESIG].rows))
5676 return NULL;
5678 sig = mono_metadata_decode_row_col (&tables [MONO_TABLE_STANDALONESIG], idx - 1, 0);
5680 ptr = mono_metadata_blob_heap (image, sig);
5681 len = mono_metadata_decode_blob_size (ptr, &ptr);
5683 res = mono_array_new (mono_domain_get (), mono_defaults.byte_class, len);
5684 memcpy (mono_array_addr (res, guint8, 0), ptr, len);
5685 return res;
5688 static MonoReflectionType*
5689 ves_icall_ModuleBuilder_create_modified_type (MonoReflectionTypeBuilder *tb, MonoString *smodifiers)
5691 MonoClass *klass;
5692 int isbyref = 0, rank;
5693 char *str = mono_string_to_utf8 (smodifiers);
5694 char *p;
5696 MONO_ARCH_SAVE_REGS;
5698 klass = mono_class_from_mono_type (tb->type.type);
5699 p = str;
5700 /* logic taken from mono_reflection_parse_type(): keep in sync */
5701 while (*p) {
5702 switch (*p) {
5703 case '&':
5704 if (isbyref) { /* only one level allowed by the spec */
5705 g_free (str);
5706 return NULL;
5708 isbyref = 1;
5709 p++;
5710 g_free (str);
5711 return mono_type_get_object (mono_object_domain (tb), &klass->this_arg);
5712 break;
5713 case '*':
5714 klass = mono_ptr_class_get (&klass->byval_arg);
5715 mono_class_init (klass);
5716 p++;
5717 break;
5718 case '[':
5719 rank = 1;
5720 p++;
5721 while (*p) {
5722 if (*p == ']')
5723 break;
5724 if (*p == ',')
5725 rank++;
5726 else if (*p != '*') { /* '*' means unknown lower bound */
5727 g_free (str);
5728 return NULL;
5730 ++p;
5732 if (*p != ']') {
5733 g_free (str);
5734 return NULL;
5736 p++;
5737 klass = mono_array_class_get (klass, rank);
5738 mono_class_init (klass);
5739 break;
5740 default:
5741 break;
5744 g_free (str);
5745 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
5748 static MonoBoolean
5749 ves_icall_Type_IsArrayImpl (MonoReflectionType *t)
5751 MonoType *type;
5752 MonoBoolean res;
5754 MONO_ARCH_SAVE_REGS;
5756 type = t->type;
5757 res = !type->byref && (type->type == MONO_TYPE_ARRAY || type->type == MONO_TYPE_SZARRAY);
5759 return res;
5762 static void
5763 check_for_invalid_type (MonoClass *klass)
5765 char *name;
5766 MonoString *str;
5767 if (klass->byval_arg.type != MONO_TYPE_TYPEDBYREF)
5768 return;
5770 name = mono_type_get_full_name (klass);
5771 str = mono_string_new (mono_domain_get (), name);
5772 g_free (name);
5773 mono_raise_exception ((MonoException*)mono_get_exception_type_load (str, NULL));
5776 static MonoReflectionType *
5777 ves_icall_Type_make_array_type (MonoReflectionType *type, int rank)
5779 MonoClass *klass, *aklass;
5781 MONO_ARCH_SAVE_REGS;
5783 klass = mono_class_from_mono_type (type->type);
5784 check_for_invalid_type (klass);
5786 if (rank == 0) //single dimentional array
5787 aklass = mono_array_class_get (klass, 1);
5788 else
5789 aklass = mono_bounded_array_class_get (klass, rank, TRUE);
5791 return mono_type_get_object (mono_object_domain (type), &aklass->byval_arg);
5794 static MonoReflectionType *
5795 ves_icall_Type_make_byref_type (MonoReflectionType *type)
5797 MonoClass *klass;
5799 MONO_ARCH_SAVE_REGS;
5801 klass = mono_class_from_mono_type (type->type);
5802 mono_class_init_or_throw (klass);
5803 check_for_invalid_type (klass);
5805 return mono_type_get_object (mono_object_domain (type), &klass->this_arg);
5808 static MonoReflectionType *
5809 ves_icall_Type_MakePointerType (MonoReflectionType *type)
5811 MonoClass *klass, *pklass;
5813 klass = mono_class_from_mono_type (type->type);
5814 mono_class_init_or_throw (klass);
5815 check_for_invalid_type (klass);
5817 pklass = mono_ptr_class_get (type->type);
5819 return mono_type_get_object (mono_object_domain (type), &pklass->byval_arg);
5822 static MonoObject *
5823 ves_icall_System_Delegate_CreateDelegate_internal (MonoReflectionType *type, MonoObject *target,
5824 MonoReflectionMethod *info, MonoBoolean throwOnBindFailure)
5826 MonoClass *delegate_class = mono_class_from_mono_type (type->type);
5827 MonoObject *delegate;
5828 gpointer func;
5829 MonoMethod *method = info->method;
5831 MONO_ARCH_SAVE_REGS;
5833 mono_class_init_or_throw (delegate_class);
5835 mono_assert (delegate_class->parent == mono_defaults.multicastdelegate_class);
5837 if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR) {
5838 if (!mono_security_core_clr_ensure_delegate_creation (method, throwOnBindFailure))
5839 return NULL;
5842 delegate = mono_object_new (mono_object_domain (type), delegate_class);
5844 if (method->dynamic) {
5845 /* Creating a trampoline would leak memory */
5846 func = mono_compile_method (method);
5847 } else {
5848 func = mono_create_ftnptr (mono_domain_get (),
5849 mono_runtime_create_jump_trampoline (mono_domain_get (), method, TRUE));
5852 mono_delegate_ctor_with_method (delegate, target, func, method);
5854 return delegate;
5857 static void
5858 ves_icall_System_Delegate_SetMulticastInvoke (MonoDelegate *this)
5860 /* Reset the invoke impl to the default one */
5861 this->invoke_impl = mono_runtime_create_delegate_trampoline (this->object.vtable->klass);
5865 * Magic number to convert a time which is relative to
5866 * Jan 1, 1970 into a value which is relative to Jan 1, 0001.
5868 #define EPOCH_ADJUST ((guint64)62135596800LL)
5871 * Magic number to convert FILETIME base Jan 1, 1601 to DateTime - base Jan, 1, 0001
5873 #define FILETIME_ADJUST ((guint64)504911232000000000LL)
5875 #ifdef HOST_WIN32
5876 /* convert a SYSTEMTIME which is of the form "last thursday in october" to a real date */
5877 static void
5878 convert_to_absolute_date(SYSTEMTIME *date)
5880 #define IS_LEAP(y) ((y % 4) == 0 && ((y % 100) != 0 || (y % 400) == 0))
5881 static int days_in_month[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
5882 static int leap_days_in_month[] = { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
5883 /* from the calendar FAQ */
5884 int a = (14 - date->wMonth) / 12;
5885 int y = date->wYear - a;
5886 int m = date->wMonth + 12 * a - 2;
5887 int d = (1 + y + y/4 - y/100 + y/400 + (31*m)/12) % 7;
5889 /* d is now the day of the week for the first of the month (0 == Sunday) */
5891 int day_of_week = date->wDayOfWeek;
5893 /* set day_in_month to the first day in the month which falls on day_of_week */
5894 int day_in_month = 1 + (day_of_week - d);
5895 if (day_in_month <= 0)
5896 day_in_month += 7;
5898 /* wDay is 1 for first weekday in month, 2 for 2nd ... 5 means last - so work that out allowing for days in the month */
5899 date->wDay = day_in_month + (date->wDay - 1) * 7;
5900 if (date->wDay > (IS_LEAP(date->wYear) ? leap_days_in_month[date->wMonth - 1] : days_in_month[date->wMonth - 1]))
5901 date->wDay -= 7;
5903 #endif
5905 #ifndef HOST_WIN32
5907 * Return's the offset from GMT of a local time.
5909 * tm is a local time
5910 * t is the same local time as seconds.
5912 static int
5913 gmt_offset(struct tm *tm, time_t t)
5915 #if defined (HAVE_TM_GMTOFF)
5916 return tm->tm_gmtoff;
5917 #else
5918 struct tm g;
5919 time_t t2;
5920 g = *gmtime(&t);
5921 g.tm_isdst = tm->tm_isdst;
5922 t2 = mktime(&g);
5923 return (int)difftime(t, t2);
5924 #endif
5926 #endif
5928 * This is heavily based on zdump.c from glibc 2.2.
5930 * * data[0]: start of daylight saving time (in DateTime ticks).
5931 * * data[1]: end of daylight saving time (in DateTime ticks).
5932 * * data[2]: utcoffset (in TimeSpan ticks).
5933 * * data[3]: additional offset when daylight saving (in TimeSpan ticks).
5934 * * name[0]: name of this timezone when not daylight saving.
5935 * * name[1]: name of this timezone when daylight saving.
5937 * FIXME: This only works with "standard" Unix dates (years between 1900 and 2100) while
5938 * the class library allows years between 1 and 9999.
5940 * Returns true on success and zero on failure.
5942 static guint32
5943 ves_icall_System_CurrentSystemTimeZone_GetTimeZoneData (guint32 year, MonoArray **data, MonoArray **names)
5945 #ifndef HOST_WIN32
5946 MonoDomain *domain = mono_domain_get ();
5947 struct tm start, tt;
5948 time_t t;
5950 long int gmtoff;
5951 int is_daylight = 0, day;
5952 char tzone [64];
5954 MONO_ARCH_SAVE_REGS;
5956 MONO_CHECK_ARG_NULL (data);
5957 MONO_CHECK_ARG_NULL (names);
5959 mono_gc_wbarrier_generic_store (data, (MonoObject*) mono_array_new (domain, mono_defaults.int64_class, 4));
5960 mono_gc_wbarrier_generic_store (names, (MonoObject*) mono_array_new (domain, mono_defaults.string_class, 2));
5963 * no info is better than crashing: we'll need our own tz data
5964 * to make this work properly, anyway. The range is probably
5965 * reduced to 1970 .. 2037 because that is what mktime is
5966 * guaranteed to support (we get into an infinite loop
5967 * otherwise).
5970 memset (&start, 0, sizeof (start));
5972 start.tm_mday = 1;
5973 start.tm_year = year-1900;
5975 t = mktime (&start);
5977 if ((year < 1970) || (year > 2037) || (t == -1)) {
5978 t = time (NULL);
5979 tt = *localtime (&t);
5980 strftime (tzone, sizeof (tzone), "%Z", &tt);
5981 mono_array_setref ((*names), 0, mono_string_new (domain, tzone));
5982 mono_array_setref ((*names), 1, mono_string_new (domain, tzone));
5983 return 1;
5986 gmtoff = gmt_offset (&start, t);
5988 /* For each day of the year, calculate the tm_gmtoff. */
5989 for (day = 0; day < 365; day++) {
5991 t += 3600*24;
5992 tt = *localtime (&t);
5994 /* Daylight saving starts or ends here. */
5995 if (gmt_offset (&tt, t) != gmtoff) {
5996 struct tm tt1;
5997 time_t t1;
5999 /* Try to find the exact hour when daylight saving starts/ends. */
6000 t1 = t;
6001 do {
6002 t1 -= 3600;
6003 tt1 = *localtime (&t1);
6004 } while (gmt_offset (&tt1, t1) != gmtoff);
6006 /* Try to find the exact minute when daylight saving starts/ends. */
6007 do {
6008 t1 += 60;
6009 tt1 = *localtime (&t1);
6010 } while (gmt_offset (&tt1, t1) == gmtoff);
6011 t1+=gmtoff;
6012 strftime (tzone, sizeof (tzone), "%Z", &tt);
6014 /* Write data, if we're already in daylight saving, we're done. */
6015 if (is_daylight) {
6016 mono_array_setref ((*names), 0, mono_string_new (domain, tzone));
6017 mono_array_set ((*data), gint64, 1, ((gint64)t1 + EPOCH_ADJUST) * 10000000L);
6018 return 1;
6019 } else {
6020 mono_array_setref ((*names), 1, mono_string_new (domain, tzone));
6021 mono_array_set ((*data), gint64, 0, ((gint64)t1 + EPOCH_ADJUST) * 10000000L);
6022 is_daylight = 1;
6025 /* This is only set once when we enter daylight saving. */
6026 mono_array_set ((*data), gint64, 2, (gint64)gmtoff * 10000000L);
6027 mono_array_set ((*data), gint64, 3, (gint64)(gmt_offset (&tt, t) - gmtoff) * 10000000L);
6029 gmtoff = gmt_offset (&tt, t);
6033 if (!is_daylight) {
6034 strftime (tzone, sizeof (tzone), "%Z", &tt);
6035 mono_array_setref ((*names), 0, mono_string_new (domain, tzone));
6036 mono_array_setref ((*names), 1, mono_string_new (domain, tzone));
6037 mono_array_set ((*data), gint64, 0, 0);
6038 mono_array_set ((*data), gint64, 1, 0);
6039 mono_array_set ((*data), gint64, 2, (gint64) gmtoff * 10000000L);
6040 mono_array_set ((*data), gint64, 3, 0);
6043 return 1;
6044 #else
6045 MonoDomain *domain = mono_domain_get ();
6046 TIME_ZONE_INFORMATION tz_info;
6047 FILETIME ft;
6048 int i;
6049 int err, tz_id;
6051 tz_id = GetTimeZoneInformation (&tz_info);
6052 if (tz_id == TIME_ZONE_ID_INVALID)
6053 return 0;
6055 MONO_CHECK_ARG_NULL (data);
6056 MONO_CHECK_ARG_NULL (names);
6058 mono_gc_wbarrier_generic_store (data, mono_array_new (domain, mono_defaults.int64_class, 4));
6059 mono_gc_wbarrier_generic_store (names, mono_array_new (domain, mono_defaults.string_class, 2));
6061 for (i = 0; i < 32; ++i)
6062 if (!tz_info.DaylightName [i])
6063 break;
6064 mono_array_setref ((*names), 1, mono_string_new_utf16 (domain, tz_info.DaylightName, i));
6065 for (i = 0; i < 32; ++i)
6066 if (!tz_info.StandardName [i])
6067 break;
6068 mono_array_setref ((*names), 0, mono_string_new_utf16 (domain, tz_info.StandardName, i));
6070 if ((year <= 1601) || (year > 30827)) {
6072 * According to MSDN, the MS time functions can't handle dates outside
6073 * this interval.
6075 return 1;
6078 /* even if the timezone has no daylight savings it may have Bias (e.g. GMT+13 it seems) */
6079 if (tz_id != TIME_ZONE_ID_UNKNOWN) {
6080 tz_info.StandardDate.wYear = year;
6081 convert_to_absolute_date(&tz_info.StandardDate);
6082 err = SystemTimeToFileTime (&tz_info.StandardDate, &ft);
6083 //g_assert(err);
6084 if (err == 0)
6085 return 0;
6087 mono_array_set ((*data), gint64, 1, FILETIME_ADJUST + (((guint64)ft.dwHighDateTime<<32) | ft.dwLowDateTime));
6088 tz_info.DaylightDate.wYear = year;
6089 convert_to_absolute_date(&tz_info.DaylightDate);
6090 err = SystemTimeToFileTime (&tz_info.DaylightDate, &ft);
6091 //g_assert(err);
6092 if (err == 0)
6093 return 0;
6095 mono_array_set ((*data), gint64, 0, FILETIME_ADJUST + (((guint64)ft.dwHighDateTime<<32) | ft.dwLowDateTime));
6097 mono_array_set ((*data), gint64, 2, (tz_info.Bias + tz_info.StandardBias) * -600000000LL);
6098 mono_array_set ((*data), gint64, 3, (tz_info.DaylightBias - tz_info.StandardBias) * -600000000LL);
6100 return 1;
6101 #endif
6104 static gpointer
6105 ves_icall_System_Object_obj_address (MonoObject *this)
6107 MONO_ARCH_SAVE_REGS;
6109 return this;
6112 /* System.Buffer */
6114 static inline gint32
6115 mono_array_get_byte_length (MonoArray *array)
6117 MonoClass *klass;
6118 int length;
6119 int i;
6121 klass = array->obj.vtable->klass;
6123 if (array->bounds == NULL)
6124 length = array->max_length;
6125 else {
6126 length = 1;
6127 for (i = 0; i < klass->rank; ++ i)
6128 length *= array->bounds [i].length;
6131 switch (klass->element_class->byval_arg.type) {
6132 case MONO_TYPE_I1:
6133 case MONO_TYPE_U1:
6134 case MONO_TYPE_BOOLEAN:
6135 return length;
6136 case MONO_TYPE_I2:
6137 case MONO_TYPE_U2:
6138 case MONO_TYPE_CHAR:
6139 return length << 1;
6140 case MONO_TYPE_I4:
6141 case MONO_TYPE_U4:
6142 case MONO_TYPE_R4:
6143 return length << 2;
6144 case MONO_TYPE_I:
6145 case MONO_TYPE_U:
6146 return length * sizeof (gpointer);
6147 case MONO_TYPE_I8:
6148 case MONO_TYPE_U8:
6149 case MONO_TYPE_R8:
6150 return length << 3;
6151 default:
6152 return -1;
6156 static gint32
6157 ves_icall_System_Buffer_ByteLengthInternal (MonoArray *array)
6159 MONO_ARCH_SAVE_REGS;
6161 return mono_array_get_byte_length (array);
6164 static gint8
6165 ves_icall_System_Buffer_GetByteInternal (MonoArray *array, gint32 idx)
6167 MONO_ARCH_SAVE_REGS;
6169 return mono_array_get (array, gint8, idx);
6172 static void
6173 ves_icall_System_Buffer_SetByteInternal (MonoArray *array, gint32 idx, gint8 value)
6175 MONO_ARCH_SAVE_REGS;
6177 mono_array_set (array, gint8, idx, value);
6180 static MonoBoolean
6181 ves_icall_System_Buffer_BlockCopyInternal (MonoArray *src, gint32 src_offset, MonoArray *dest, gint32 dest_offset, gint32 count)
6183 guint8 *src_buf, *dest_buf;
6185 MONO_ARCH_SAVE_REGS;
6187 /* watch out for integer overflow */
6188 if ((src_offset > mono_array_get_byte_length (src) - count) || (dest_offset > mono_array_get_byte_length (dest) - count))
6189 return FALSE;
6191 src_buf = (guint8 *)src->vector + src_offset;
6192 dest_buf = (guint8 *)dest->vector + dest_offset;
6194 if (src != dest)
6195 memcpy (dest_buf, src_buf, count);
6196 else
6197 memmove (dest_buf, src_buf, count); /* Source and dest are the same array */
6199 return TRUE;
6202 static MonoObject *
6203 ves_icall_Remoting_RealProxy_GetTransparentProxy (MonoObject *this, MonoString *class_name)
6205 MonoDomain *domain = mono_object_domain (this);
6206 MonoObject *res;
6207 MonoRealProxy *rp = ((MonoRealProxy *)this);
6208 MonoTransparentProxy *tp;
6209 MonoType *type;
6210 MonoClass *klass;
6212 MONO_ARCH_SAVE_REGS;
6214 res = mono_object_new (domain, mono_defaults.transparent_proxy_class);
6215 tp = (MonoTransparentProxy*) res;
6217 MONO_OBJECT_SETREF (tp, rp, rp);
6218 type = ((MonoReflectionType *)rp->class_to_proxy)->type;
6219 klass = mono_class_from_mono_type (type);
6221 tp->custom_type_info = (mono_object_isinst (this, mono_defaults.iremotingtypeinfo_class) != NULL);
6222 tp->remote_class = mono_remote_class (domain, class_name, klass);
6224 res->vtable = mono_remote_class_vtable (domain, tp->remote_class, rp);
6225 return res;
6228 static MonoReflectionType *
6229 ves_icall_Remoting_RealProxy_InternalGetProxyType (MonoTransparentProxy *tp)
6231 return mono_type_get_object (mono_object_domain (tp), &tp->remote_class->proxy_class->byval_arg);
6234 /* System.Environment */
6236 MonoString*
6237 ves_icall_System_Environment_get_UserName (void)
6239 MONO_ARCH_SAVE_REGS;
6241 /* using glib is more portable */
6242 return mono_string_new (mono_domain_get (), g_get_user_name ());
6246 static MonoString *
6247 ves_icall_System_Environment_get_MachineName (void)
6249 #if defined (HOST_WIN32)
6250 gunichar2 *buf;
6251 guint32 len;
6252 MonoString *result;
6254 len = MAX_COMPUTERNAME_LENGTH + 1;
6255 buf = g_new (gunichar2, len);
6257 result = NULL;
6258 if (GetComputerName (buf, (PDWORD) &len))
6259 result = mono_string_new_utf16 (mono_domain_get (), buf, len);
6261 g_free (buf);
6262 return result;
6263 #elif !defined(DISABLE_SOCKETS)
6264 gchar buf [256];
6265 MonoString *result;
6267 if (gethostname (buf, sizeof (buf)) == 0)
6268 result = mono_string_new (mono_domain_get (), buf);
6269 else
6270 result = NULL;
6272 return result;
6273 #else
6274 return mono_string_new (mono_domain_get (), "mono");
6275 #endif
6278 static int
6279 ves_icall_System_Environment_get_Platform (void)
6281 #if defined (TARGET_WIN32)
6282 /* Win32NT */
6283 return 2;
6284 #elif defined(__MACH__)
6285 /* OSX */
6287 // For compatibility with our client code, this will be 4 for a while.
6288 // We will eventually move to 6 to match .NET, but it requires all client
6289 // code to be updated and the documentation everywhere to be updated
6290 // first.
6292 return 4;
6293 #else
6294 /* Unix */
6295 return 4;
6296 #endif
6299 static MonoString *
6300 ves_icall_System_Environment_get_NewLine (void)
6302 MONO_ARCH_SAVE_REGS;
6304 #if defined (HOST_WIN32)
6305 return mono_string_new (mono_domain_get (), "\r\n");
6306 #else
6307 return mono_string_new (mono_domain_get (), "\n");
6308 #endif
6311 static MonoString *
6312 ves_icall_System_Environment_GetEnvironmentVariable (MonoString *name)
6314 const gchar *value;
6315 gchar *utf8_name;
6317 MONO_ARCH_SAVE_REGS;
6319 if (name == NULL)
6320 return NULL;
6322 utf8_name = mono_string_to_utf8 (name); /* FIXME: this should be ascii */
6323 value = g_getenv (utf8_name);
6325 g_free (utf8_name);
6327 if (value == 0)
6328 return NULL;
6330 return mono_string_new (mono_domain_get (), value);
6334 * There is no standard way to get at environ.
6336 #ifndef _MSC_VER
6337 #ifndef __MINGW32_VERSION
6338 #if defined(__APPLE__) && !defined (__arm__)
6339 /* Apple defines this in crt_externs.h but doesn't provide that header for
6340 * arm-apple-darwin9. We'll manually define the symbol on Apple as it does
6341 * in fact exist on all implementations (so far)
6343 gchar ***_NSGetEnviron(void);
6344 #define environ (*_NSGetEnviron())
6345 #else
6346 extern
6347 char **environ;
6348 #endif
6349 #endif
6350 #endif
6352 static MonoArray *
6353 ves_icall_System_Environment_GetEnvironmentVariableNames (void)
6355 #ifdef HOST_WIN32
6356 MonoArray *names;
6357 MonoDomain *domain;
6358 MonoString *str;
6359 WCHAR* env_strings;
6360 WCHAR* env_string;
6361 WCHAR* equal_str;
6362 int n = 0;
6364 env_strings = GetEnvironmentStrings();
6366 if (env_strings) {
6367 env_string = env_strings;
6368 while (*env_string != '\0') {
6369 /* weird case that MS seems to skip */
6370 if (*env_string != '=')
6371 n++;
6372 while (*env_string != '\0')
6373 env_string++;
6374 env_string++;
6378 domain = mono_domain_get ();
6379 names = mono_array_new (domain, mono_defaults.string_class, n);
6381 if (env_strings) {
6382 n = 0;
6383 env_string = env_strings;
6384 while (*env_string != '\0') {
6385 /* weird case that MS seems to skip */
6386 if (*env_string != '=') {
6387 equal_str = wcschr(env_string, '=');
6388 g_assert(equal_str);
6389 str = mono_string_new_utf16 (domain, env_string, equal_str-env_string);
6390 mono_array_setref (names, n, str);
6391 n++;
6393 while (*env_string != '\0')
6394 env_string++;
6395 env_string++;
6398 FreeEnvironmentStrings (env_strings);
6401 return names;
6403 #else
6404 MonoArray *names;
6405 MonoDomain *domain;
6406 MonoString *str;
6407 gchar **e, **parts;
6408 int n;
6410 MONO_ARCH_SAVE_REGS;
6412 n = 0;
6413 for (e = environ; *e != 0; ++ e)
6414 ++ n;
6416 domain = mono_domain_get ();
6417 names = mono_array_new (domain, mono_defaults.string_class, n);
6419 n = 0;
6420 for (e = environ; *e != 0; ++ e) {
6421 parts = g_strsplit (*e, "=", 2);
6422 if (*parts != 0) {
6423 str = mono_string_new (domain, *parts);
6424 mono_array_setref (names, n, str);
6427 g_strfreev (parts);
6429 ++ n;
6432 return names;
6433 #endif
6437 * If your platform lacks setenv/unsetenv, you must upgrade your glib.
6439 #if !GLIB_CHECK_VERSION(2,4,0)
6440 #define g_setenv(a,b,c) setenv(a,b,c)
6441 #define g_unsetenv(a) unsetenv(a)
6442 #endif
6444 static void
6445 ves_icall_System_Environment_InternalSetEnvironmentVariable (MonoString *name, MonoString *value)
6447 MonoError error;
6448 #ifdef HOST_WIN32
6450 gunichar2 *utf16_name, *utf16_value;
6451 #else
6452 gchar *utf8_name, *utf8_value;
6453 #endif
6455 MONO_ARCH_SAVE_REGS;
6457 #ifdef HOST_WIN32
6458 utf16_name = mono_string_to_utf16 (name);
6459 if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
6460 SetEnvironmentVariable (utf16_name, NULL);
6461 g_free (utf16_name);
6462 return;
6465 utf16_value = mono_string_to_utf16 (value);
6467 SetEnvironmentVariable (utf16_name, utf16_value);
6469 g_free (utf16_name);
6470 g_free (utf16_value);
6471 #else
6472 utf8_name = mono_string_to_utf8 (name); /* FIXME: this should be ascii */
6474 if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
6475 g_unsetenv (utf8_name);
6476 g_free (utf8_name);
6477 return;
6480 utf8_value = mono_string_to_utf8_checked (value, &error);
6481 if (!mono_error_ok (&error)) {
6482 g_free (utf8_name);
6483 mono_error_raise_exception (&error);
6485 g_setenv (utf8_name, utf8_value, TRUE);
6487 g_free (utf8_name);
6488 g_free (utf8_value);
6489 #endif
6492 static void
6493 ves_icall_System_Environment_Exit (int result)
6495 MONO_ARCH_SAVE_REGS;
6497 mono_threads_set_shutting_down ();
6499 mono_runtime_set_shutting_down ();
6501 /* This will kill the tp threads which cannot be suspended */
6502 mono_thread_pool_cleanup ();
6504 /* Suspend all managed threads since the runtime is going away */
6505 mono_thread_suspend_all_other_threads ();
6507 mono_runtime_quit ();
6509 /* we may need to do some cleanup here... */
6510 exit (result);
6513 static MonoString*
6514 ves_icall_System_Environment_GetGacPath (void)
6516 return mono_string_new (mono_domain_get (), mono_assembly_getrootdir ());
6519 static MonoString*
6520 ves_icall_System_Environment_GetWindowsFolderPath (int folder)
6522 #if defined (HOST_WIN32)
6523 #ifndef CSIDL_FLAG_CREATE
6524 #define CSIDL_FLAG_CREATE 0x8000
6525 #endif
6527 WCHAR path [MAX_PATH];
6528 /* Create directory if no existing */
6529 if (SUCCEEDED (SHGetFolderPathW (NULL, folder | CSIDL_FLAG_CREATE, NULL, 0, path))) {
6530 int len = 0;
6531 while (path [len])
6532 ++ len;
6533 return mono_string_new_utf16 (mono_domain_get (), path, len);
6535 #else
6536 g_warning ("ves_icall_System_Environment_GetWindowsFolderPath should only be called on Windows!");
6537 #endif
6538 return mono_string_new (mono_domain_get (), "");
6541 static MonoArray *
6542 ves_icall_System_Environment_GetLogicalDrives (void)
6544 gunichar2 buf [256], *ptr, *dname;
6545 gunichar2 *u16;
6546 guint initial_size = 127, size = 128;
6547 gint ndrives;
6548 MonoArray *result;
6549 MonoString *drivestr;
6550 MonoDomain *domain = mono_domain_get ();
6551 gint len;
6553 MONO_ARCH_SAVE_REGS;
6555 buf [0] = '\0';
6556 ptr = buf;
6558 while (size > initial_size) {
6559 size = (guint) GetLogicalDriveStrings (initial_size, ptr);
6560 if (size > initial_size) {
6561 if (ptr != buf)
6562 g_free (ptr);
6563 ptr = g_malloc0 ((size + 1) * sizeof (gunichar2));
6564 initial_size = size;
6565 size++;
6569 /* Count strings */
6570 dname = ptr;
6571 ndrives = 0;
6572 do {
6573 while (*dname++);
6574 ndrives++;
6575 } while (*dname);
6577 dname = ptr;
6578 result = mono_array_new (domain, mono_defaults.string_class, ndrives);
6579 ndrives = 0;
6580 do {
6581 len = 0;
6582 u16 = dname;
6583 while (*u16) { u16++; len ++; }
6584 drivestr = mono_string_new_utf16 (domain, dname, len);
6585 mono_array_setref (result, ndrives++, drivestr);
6586 while (*dname++);
6587 } while (*dname);
6589 if (ptr != buf)
6590 g_free (ptr);
6592 return result;
6595 static MonoString *
6596 ves_icall_System_Environment_InternalGetHome (void)
6598 MONO_ARCH_SAVE_REGS;
6600 return mono_string_new (mono_domain_get (), g_get_home_dir ());
6603 static const char *encodings [] = {
6604 (char *) 1,
6605 "ascii", "us_ascii", "us", "ansi_x3.4_1968",
6606 "ansi_x3.4_1986", "cp367", "csascii", "ibm367",
6607 "iso_ir_6", "iso646_us", "iso_646.irv:1991",
6608 (char *) 2,
6609 "utf_7", "csunicode11utf7", "unicode_1_1_utf_7",
6610 "unicode_2_0_utf_7", "x_unicode_1_1_utf_7",
6611 "x_unicode_2_0_utf_7",
6612 (char *) 3,
6613 "utf_8", "unicode_1_1_utf_8", "unicode_2_0_utf_8",
6614 "x_unicode_1_1_utf_8", "x_unicode_2_0_utf_8",
6615 (char *) 4,
6616 "utf_16", "UTF_16LE", "ucs_2", "unicode",
6617 "iso_10646_ucs2",
6618 (char *) 5,
6619 "unicodefffe", "utf_16be",
6620 (char *) 6,
6621 "iso_8859_1",
6622 (char *) 0
6626 * Returns the internal codepage, if the value of "int_code_page" is
6627 * 1 at entry, and we can not compute a suitable code page number,
6628 * returns the code page as a string
6630 static MonoString*
6631 ves_icall_System_Text_Encoding_InternalCodePage (gint32 *int_code_page)
6633 const char *cset;
6634 const char *p;
6635 char *c;
6636 char *codepage = NULL;
6637 int code;
6638 int want_name = *int_code_page;
6639 int i;
6641 *int_code_page = -1;
6642 MONO_ARCH_SAVE_REGS;
6644 g_get_charset (&cset);
6645 c = codepage = strdup (cset);
6646 for (c = codepage; *c; c++){
6647 if (isascii (*c) && isalpha (*c))
6648 *c = tolower (*c);
6649 if (*c == '-')
6650 *c = '_';
6652 /* g_print ("charset: %s\n", cset); */
6654 /* handle some common aliases */
6655 p = encodings [0];
6656 code = 0;
6657 for (i = 0; p != 0; ){
6658 if ((gssize) p < 7){
6659 code = (gssize) p;
6660 p = encodings [++i];
6661 continue;
6663 if (strcmp (p, codepage) == 0){
6664 *int_code_page = code;
6665 break;
6667 p = encodings [++i];
6670 if (strstr (codepage, "utf_8") != NULL)
6671 *int_code_page |= 0x10000000;
6672 free (codepage);
6674 if (want_name && *int_code_page == -1)
6675 return mono_string_new (mono_domain_get (), cset);
6676 else
6677 return NULL;
6680 static MonoBoolean
6681 ves_icall_System_Environment_get_HasShutdownStarted (void)
6683 if (mono_runtime_is_shutting_down ())
6684 return TRUE;
6686 if (mono_domain_is_unloading (mono_domain_get ()))
6687 return TRUE;
6689 return FALSE;
6692 static void
6693 ves_icall_System_Environment_BroadcastSettingChange (void)
6695 #ifdef HOST_WIN32
6696 SendMessageTimeout (HWND_BROADCAST, WM_SETTINGCHANGE, NULL, L"Environment", SMTO_ABORTIFHUNG, 2000, 0);
6697 #endif
6700 static void
6701 ves_icall_MonoMethodMessage_InitMessage (MonoMethodMessage *this,
6702 MonoReflectionMethod *method,
6703 MonoArray *out_args)
6705 MONO_ARCH_SAVE_REGS;
6707 mono_message_init (mono_object_domain (this), this, method, out_args);
6710 static MonoBoolean
6711 ves_icall_IsTransparentProxy (MonoObject *proxy)
6713 MONO_ARCH_SAVE_REGS;
6715 if (!proxy)
6716 return 0;
6718 if (proxy->vtable->klass == mono_defaults.transparent_proxy_class)
6719 return 1;
6721 return 0;
6724 static MonoReflectionMethod *
6725 ves_icall_Remoting_RemotingServices_GetVirtualMethod (
6726 MonoReflectionType *rtype, MonoReflectionMethod *rmethod)
6728 MonoClass *klass;
6729 MonoMethod *method;
6730 MonoMethod **vtable;
6731 MonoMethod *res = NULL;
6733 MONO_CHECK_ARG_NULL (rtype);
6734 MONO_CHECK_ARG_NULL (rmethod);
6736 method = rmethod->method;
6737 klass = mono_class_from_mono_type (rtype->type);
6738 mono_class_init_or_throw (klass);
6740 if (MONO_CLASS_IS_INTERFACE (klass))
6741 return NULL;
6743 if (method->flags & METHOD_ATTRIBUTE_STATIC)
6744 return NULL;
6746 if ((method->flags & METHOD_ATTRIBUTE_FINAL) || !(method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
6747 if (klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE))
6748 return rmethod;
6749 else
6750 return NULL;
6753 mono_class_setup_vtable (klass);
6754 vtable = klass->vtable;
6756 if (method->klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
6757 gboolean variance_used = FALSE;
6758 /*MS fails with variant interfaces but it's the right thing to do anyway.*/
6759 int offs = mono_class_interface_offset_with_variance (klass, method->klass, &variance_used);
6760 if (offs >= 0)
6761 res = vtable [offs + method->slot];
6762 } else {
6763 if (!(klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE)))
6764 return NULL;
6766 if (method->slot != -1)
6767 res = vtable [method->slot];
6770 if (!res)
6771 return NULL;
6773 return mono_method_get_object (mono_domain_get (), res, NULL);
6776 static void
6777 ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (MonoReflectionType *type, MonoBoolean enable)
6779 MonoClass *klass;
6780 MonoVTable* vtable;
6782 MONO_ARCH_SAVE_REGS;
6784 klass = mono_class_from_mono_type (type->type);
6785 vtable = mono_class_vtable_full (mono_domain_get (), klass, TRUE);
6787 if (enable) vtable->remote = 1;
6788 else vtable->remote = 0;
6791 static MonoObject *
6792 ves_icall_System_Runtime_Activation_ActivationServices_AllocateUninitializedClassInstance (MonoReflectionType *type)
6794 MonoClass *klass;
6795 MonoDomain *domain;
6797 MONO_ARCH_SAVE_REGS;
6799 domain = mono_object_domain (type);
6800 klass = mono_class_from_mono_type (type->type);
6801 mono_class_init_or_throw (klass);
6803 if (klass->rank >= 1) {
6804 g_assert (klass->rank == 1);
6805 return (MonoObject *) mono_array_new (domain, klass->element_class, 0);
6806 } else {
6807 /* Bypass remoting object creation check */
6808 return mono_object_new_alloc_specific (mono_class_vtable_full (domain, klass, TRUE));
6812 static MonoString *
6813 ves_icall_System_IO_get_temp_path (void)
6815 MONO_ARCH_SAVE_REGS;
6817 return mono_string_new (mono_domain_get (), g_get_tmp_dir ());
6820 #ifndef PLATFORM_NO_DRIVEINFO
6821 static MonoBoolean
6822 ves_icall_System_IO_DriveInfo_GetDiskFreeSpace (MonoString *path_name, guint64 *free_bytes_avail,
6823 guint64 *total_number_of_bytes, guint64 *total_number_of_free_bytes,
6824 gint32 *error)
6826 gboolean result;
6827 ULARGE_INTEGER wapi_free_bytes_avail;
6828 ULARGE_INTEGER wapi_total_number_of_bytes;
6829 ULARGE_INTEGER wapi_total_number_of_free_bytes;
6831 MONO_ARCH_SAVE_REGS;
6833 *error = ERROR_SUCCESS;
6834 result = GetDiskFreeSpaceEx (mono_string_chars (path_name), &wapi_free_bytes_avail, &wapi_total_number_of_bytes,
6835 &wapi_total_number_of_free_bytes);
6837 if (result) {
6838 *free_bytes_avail = wapi_free_bytes_avail.QuadPart;
6839 *total_number_of_bytes = wapi_total_number_of_bytes.QuadPart;
6840 *total_number_of_free_bytes = wapi_total_number_of_free_bytes.QuadPart;
6841 } else {
6842 *free_bytes_avail = 0;
6843 *total_number_of_bytes = 0;
6844 *total_number_of_free_bytes = 0;
6845 *error = GetLastError ();
6848 return result;
6851 static guint32
6852 ves_icall_System_IO_DriveInfo_GetDriveType (MonoString *root_path_name)
6854 MONO_ARCH_SAVE_REGS;
6856 return GetDriveType (mono_string_chars (root_path_name));
6858 #endif
6860 static gpointer
6861 ves_icall_RuntimeMethod_GetFunctionPointer (MonoMethod *method)
6863 MONO_ARCH_SAVE_REGS;
6865 return mono_compile_method (method);
6868 static MonoString *
6869 ves_icall_System_Configuration_DefaultConfig_get_machine_config_path (void)
6871 MonoString *mcpath;
6872 gchar *path;
6874 MONO_ARCH_SAVE_REGS;
6876 path = g_build_path (G_DIR_SEPARATOR_S, mono_get_config_dir (), "mono", mono_get_runtime_info ()->framework_version, "machine.config", NULL);
6878 #if defined (HOST_WIN32)
6879 /* Avoid mixing '/' and '\\' */
6881 gint i;
6882 for (i = strlen (path) - 1; i >= 0; i--)
6883 if (path [i] == '/')
6884 path [i] = '\\';
6886 #endif
6887 mcpath = mono_string_new (mono_domain_get (), path);
6888 g_free (path);
6890 return mcpath;
6893 static MonoString *
6894 get_bundled_app_config (void)
6896 const gchar *app_config;
6897 MonoDomain *domain;
6898 MonoString *file;
6899 gchar *config_file;
6900 gsize len;
6901 gchar *module;
6903 MONO_ARCH_SAVE_REGS;
6905 domain = mono_domain_get ();
6906 file = domain->setup->configuration_file;
6907 if (!file)
6908 return NULL;
6910 // Retrieve config file and remove the extension
6911 config_file = mono_string_to_utf8 (file);
6912 len = strlen (config_file) - strlen (".config");
6913 module = g_malloc0 (len + 1);
6914 memcpy (module, config_file, len);
6915 // Get the config file from the module name
6916 app_config = mono_config_string_for_assembly_file (module);
6917 // Clean-up
6918 g_free (module);
6919 g_free (config_file);
6921 if (!app_config)
6922 return NULL;
6924 return mono_string_new (mono_domain_get (), app_config);
6927 static MonoString *
6928 get_bundled_machine_config (void)
6930 const gchar *machine_config;
6932 MONO_ARCH_SAVE_REGS;
6934 machine_config = mono_get_machine_config ();
6936 if (!machine_config)
6937 return NULL;
6939 return mono_string_new (mono_domain_get (), machine_config);
6942 static MonoString *
6943 ves_icall_System_Web_Util_ICalls_get_machine_install_dir (void)
6945 MonoString *ipath;
6946 gchar *path;
6948 MONO_ARCH_SAVE_REGS;
6950 path = g_path_get_dirname (mono_get_config_dir ());
6952 #if defined (HOST_WIN32)
6953 /* Avoid mixing '/' and '\\' */
6955 gint i;
6956 for (i = strlen (path) - 1; i >= 0; i--)
6957 if (path [i] == '/')
6958 path [i] = '\\';
6960 #endif
6961 ipath = mono_string_new (mono_domain_get (), path);
6962 g_free (path);
6964 return ipath;
6967 static gboolean
6968 ves_icall_get_resources_ptr (MonoReflectionAssembly *assembly, gpointer *result, gint32 *size)
6970 MonoPEResourceDataEntry *entry;
6971 MonoImage *image;
6973 MONO_ARCH_SAVE_REGS;
6975 if (!assembly || !result || !size)
6976 return FALSE;
6978 *result = NULL;
6979 *size = 0;
6980 image = assembly->assembly->image;
6981 entry = mono_image_lookup_resource (image, MONO_PE_RESOURCE_ID_ASPNET_STRING, 0, NULL);
6982 if (!entry)
6983 return FALSE;
6985 *result = mono_image_rva_map (image, entry->rde_data_offset);
6986 if (!(*result)) {
6987 g_free (entry);
6988 return FALSE;
6990 *size = entry->rde_size;
6991 g_free (entry);
6992 return TRUE;
6995 static MonoBoolean
6996 ves_icall_System_Diagnostics_Debugger_IsAttached_internal (void)
6998 return mono_debug_using_mono_debugger () || mono_is_debugger_attached ();
7001 static void
7002 ves_icall_System_Diagnostics_DefaultTraceListener_WriteWindowsDebugString (MonoString *message)
7004 #if defined (HOST_WIN32)
7005 OutputDebugString (mono_string_chars (message));
7006 #else
7007 g_warning ("WriteWindowsDebugString called and HOST_WIN32 not defined!\n");
7008 #endif
7011 /* Only used for value types */
7012 static MonoObject *
7013 ves_icall_System_Activator_CreateInstanceInternal (MonoReflectionType *type)
7015 MonoClass *klass;
7016 MonoDomain *domain;
7018 MONO_ARCH_SAVE_REGS;
7020 domain = mono_object_domain (type);
7021 klass = mono_class_from_mono_type (type->type);
7022 mono_class_init_or_throw (klass);
7024 if (mono_class_is_nullable (klass))
7025 /* No arguments -> null */
7026 return NULL;
7028 return mono_object_new (domain, klass);
7031 static MonoReflectionMethod *
7032 ves_icall_MonoMethod_get_base_method (MonoReflectionMethod *m, gboolean definition)
7034 MonoClass *klass, *parent;
7035 MonoMethod *method = m->method;
7036 MonoMethod *result = NULL;
7038 MONO_ARCH_SAVE_REGS;
7040 if (method->klass == NULL)
7041 return m;
7043 if (!(method->flags & METHOD_ATTRIBUTE_VIRTUAL) ||
7044 MONO_CLASS_IS_INTERFACE (method->klass) ||
7045 method->flags & METHOD_ATTRIBUTE_NEW_SLOT)
7046 return m;
7048 klass = method->klass;
7049 if (klass->generic_class)
7050 klass = klass->generic_class->container_class;
7052 if (definition) {
7053 /* At the end of the loop, klass points to the eldest class that has this virtual function slot. */
7054 for (parent = klass->parent; parent != NULL; parent = parent->parent) {
7055 mono_class_setup_vtable (parent);
7056 if (parent->vtable_size <= method->slot)
7057 break;
7058 klass = parent;
7060 } else {
7061 klass = klass->parent;
7062 if (!klass)
7063 return m;
7066 if (klass == method->klass)
7067 return m;
7069 /*This is possible if definition == FALSE.
7070 * Do it here to be really sure we don't read invalid memory.
7072 if (method->slot >= klass->vtable_size)
7073 return m;
7075 result = klass->vtable [method->slot];
7076 if (result == NULL) {
7077 /* It is an abstract method */
7078 gpointer iter = NULL;
7079 while ((result = mono_class_get_methods (klass, &iter)))
7080 if (result->slot == method->slot)
7081 break;
7084 if (result == NULL)
7085 return m;
7087 return mono_method_get_object (mono_domain_get (), result, NULL);
7090 static MonoString*
7091 ves_icall_MonoMethod_get_name (MonoReflectionMethod *m)
7093 MonoMethod *method = m->method;
7095 MONO_OBJECT_SETREF (m, name, mono_string_new (mono_object_domain (m), method->name));
7096 return m->name;
7099 static void
7100 mono_ArgIterator_Setup (MonoArgIterator *iter, char* argsp, char* start)
7102 MONO_ARCH_SAVE_REGS;
7104 iter->sig = *(MonoMethodSignature**)argsp;
7106 g_assert (iter->sig->sentinelpos <= iter->sig->param_count);
7107 g_assert (iter->sig->call_convention == MONO_CALL_VARARG);
7109 iter->next_arg = 0;
7110 /* FIXME: it's not documented what start is exactly... */
7111 if (start) {
7112 iter->args = start;
7113 } else {
7114 iter->args = argsp + sizeof (gpointer);
7116 iter->num_args = iter->sig->param_count - iter->sig->sentinelpos;
7118 /* g_print ("sig %p, param_count: %d, sent: %d\n", iter->sig, iter->sig->param_count, iter->sig->sentinelpos); */
7121 static MonoTypedRef
7122 mono_ArgIterator_IntGetNextArg (MonoArgIterator *iter)
7124 guint32 i, arg_size;
7125 gint32 align;
7126 MonoTypedRef res;
7127 MONO_ARCH_SAVE_REGS;
7129 i = iter->sig->sentinelpos + iter->next_arg;
7131 g_assert (i < iter->sig->param_count);
7133 res.type = iter->sig->params [i];
7134 res.klass = mono_class_from_mono_type (res.type);
7135 res.value = iter->args;
7136 arg_size = mono_type_stack_size (res.type, &align);
7137 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
7138 if (arg_size <= sizeof (gpointer)) {
7139 int dummy;
7140 int padding = arg_size - mono_type_size (res.type, &dummy);
7141 res.value = (guint8*)res.value + padding;
7143 #endif
7144 iter->args = (char*)iter->args + arg_size;
7145 iter->next_arg++;
7147 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7149 return res;
7152 static MonoTypedRef
7153 mono_ArgIterator_IntGetNextArgT (MonoArgIterator *iter, MonoType *type)
7155 guint32 i, arg_size;
7156 gint32 align;
7157 MonoTypedRef res;
7158 MONO_ARCH_SAVE_REGS;
7160 i = iter->sig->sentinelpos + iter->next_arg;
7162 g_assert (i < iter->sig->param_count);
7164 while (i < iter->sig->param_count) {
7165 if (!mono_metadata_type_equal (type, iter->sig->params [i]))
7166 continue;
7167 res.type = iter->sig->params [i];
7168 res.klass = mono_class_from_mono_type (res.type);
7169 /* FIXME: endianess issue... */
7170 res.value = iter->args;
7171 arg_size = mono_type_stack_size (res.type, &align);
7172 iter->args = (char*)iter->args + arg_size;
7173 iter->next_arg++;
7174 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7175 return res;
7177 /* g_print ("arg type 0x%02x not found\n", res.type->type); */
7179 res.type = NULL;
7180 res.value = NULL;
7181 res.klass = NULL;
7182 return res;
7185 static MonoType*
7186 mono_ArgIterator_IntGetNextArgType (MonoArgIterator *iter)
7188 gint i;
7189 MONO_ARCH_SAVE_REGS;
7191 i = iter->sig->sentinelpos + iter->next_arg;
7193 g_assert (i < iter->sig->param_count);
7195 return iter->sig->params [i];
7198 static MonoObject*
7199 mono_TypedReference_ToObject (MonoTypedRef tref)
7201 MONO_ARCH_SAVE_REGS;
7203 if (MONO_TYPE_IS_REFERENCE (tref.type)) {
7204 MonoObject** objp = tref.value;
7205 return *objp;
7208 return mono_value_box (mono_domain_get (), tref.klass, tref.value);
7211 static MonoObject*
7212 mono_TypedReference_ToObjectInternal (MonoType *type, gpointer value, MonoClass *klass)
7214 MONO_ARCH_SAVE_REGS;
7216 if (MONO_TYPE_IS_REFERENCE (type)) {
7217 MonoObject** objp = value;
7218 return *objp;
7221 return mono_value_box (mono_domain_get (), klass, value);
7224 static void
7225 prelink_method (MonoMethod *method)
7227 const char *exc_class, *exc_arg;
7228 if (!(method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
7229 return;
7230 mono_lookup_pinvoke_call (method, &exc_class, &exc_arg);
7231 if (exc_class) {
7232 mono_raise_exception(
7233 mono_exception_from_name_msg (mono_defaults.corlib, "System", exc_class, exc_arg ) );
7235 /* create the wrapper, too? */
7238 static void
7239 ves_icall_System_Runtime_InteropServices_Marshal_Prelink (MonoReflectionMethod *method)
7241 MONO_ARCH_SAVE_REGS;
7242 prelink_method (method->method);
7245 static void
7246 ves_icall_System_Runtime_InteropServices_Marshal_PrelinkAll (MonoReflectionType *type)
7248 MonoClass *klass = mono_class_from_mono_type (type->type);
7249 MonoMethod* m;
7250 gpointer iter = NULL;
7251 MONO_ARCH_SAVE_REGS;
7253 mono_class_init_or_throw (klass);
7255 while ((m = mono_class_get_methods (klass, &iter)))
7256 prelink_method (m);
7259 /* These parameters are "readonly" in corlib/System/NumberFormatter.cs */
7260 static void
7261 ves_icall_System_NumberFormatter_GetFormatterTables (guint64 const **mantissas,
7262 gint32 const **exponents,
7263 gunichar2 const **digitLowerTable,
7264 gunichar2 const **digitUpperTable,
7265 gint64 const **tenPowersList,
7266 gint32 const **decHexDigits)
7268 *mantissas = Formatter_MantissaBitsTable;
7269 *exponents = Formatter_TensExponentTable;
7270 *digitLowerTable = Formatter_DigitLowerTable;
7271 *digitUpperTable = Formatter_DigitUpperTable;
7272 *tenPowersList = Formatter_TenPowersList;
7273 *decHexDigits = Formatter_DecHexDigits;
7276 /* These parameters are "readonly" in corlib/System/Char.cs */
7277 static void
7278 ves_icall_System_Char_GetDataTablePointers (guint8 const **category_data,
7279 guint8 const **numeric_data,
7280 gdouble const **numeric_data_values,
7281 guint16 const **to_lower_data_low,
7282 guint16 const **to_lower_data_high,
7283 guint16 const **to_upper_data_low,
7284 guint16 const **to_upper_data_high)
7286 *category_data = CategoryData;
7287 *numeric_data = NumericData;
7288 *numeric_data_values = NumericDataValues;
7289 *to_lower_data_low = ToLowerDataLow;
7290 *to_lower_data_high = ToLowerDataHigh;
7291 *to_upper_data_low = ToUpperDataLow;
7292 *to_upper_data_high = ToUpperDataHigh;
7295 static gint32
7296 ves_icall_MonoDebugger_GetMethodToken (MonoReflectionMethod *method)
7298 return method->method->token;
7302 * We return NULL for no modifiers so the corlib code can return Type.EmptyTypes
7303 * and avoid useless allocations.
7305 static MonoArray*
7306 type_array_from_modifiers (MonoImage *image, MonoType *type, int optional)
7308 MonoArray *res;
7309 int i, count = 0;
7310 for (i = 0; i < type->num_mods; ++i) {
7311 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required))
7312 count++;
7314 if (!count)
7315 return NULL;
7316 res = mono_array_new (mono_domain_get (), mono_defaults.systemtype_class, count);
7317 count = 0;
7318 for (i = 0; i < type->num_mods; ++i) {
7319 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required)) {
7320 MonoClass *klass = mono_class_get (image, type->modifiers [i].token);
7321 mono_array_setref (res, count, mono_type_get_object (mono_domain_get (), &klass->byval_arg));
7322 count++;
7325 return res;
7328 static MonoArray*
7329 param_info_get_type_modifiers (MonoReflectionParameter *param, MonoBoolean optional)
7331 MonoType *type = param->ClassImpl->type;
7332 MonoClass *member_class = mono_object_class (param->MemberImpl);
7333 MonoMethod *method = NULL;
7334 MonoImage *image;
7335 int pos;
7336 MonoMethodSignature *sig;
7338 if (mono_class_is_reflection_method_or_constructor (member_class)) {
7339 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
7340 method = rmethod->method;
7341 } else if (member_class->image == mono_defaults.corlib && !strcmp ("MonoProperty", member_class->name)) {
7342 MonoReflectionProperty *prop = (MonoReflectionProperty *)param->MemberImpl;
7343 if (!(method = prop->property->get))
7344 method = prop->property->set;
7345 g_assert (method);
7346 } else {
7347 char *type_name = mono_type_get_full_name (member_class);
7348 char *msg = g_strdup_printf ("Custom modifiers on a ParamInfo with member %s are not supported", type_name);
7349 MonoException *ex = mono_get_exception_not_supported (msg);
7350 g_free (type_name);
7351 g_free (msg);
7352 mono_raise_exception (ex);
7355 image = method->klass->image;
7356 pos = param->PositionImpl;
7357 sig = mono_method_signature (method);
7358 if (pos == -1)
7359 type = sig->ret;
7360 else
7361 type = sig->params [pos];
7363 return type_array_from_modifiers (image, type, optional);
7366 static MonoType*
7367 get_property_type (MonoProperty *prop)
7369 MonoMethodSignature *sig;
7370 if (prop->get) {
7371 sig = mono_method_signature (prop->get);
7372 return sig->ret;
7373 } else if (prop->set) {
7374 sig = mono_method_signature (prop->set);
7375 return sig->params [sig->param_count - 1];
7377 return NULL;
7380 static MonoArray*
7381 property_info_get_type_modifiers (MonoReflectionProperty *property, MonoBoolean optional)
7383 MonoType *type = get_property_type (property->property);
7384 MonoImage *image = property->klass->image;
7386 if (!type)
7387 return NULL;
7388 return type_array_from_modifiers (image, type, optional);
7392 *Construct a MonoType suited to be used to decode a constant blob object.
7394 * @type is the target type which will be constructed
7395 * @blob_type is the blob type, for example, that comes from the constant table
7396 * @real_type is the expected constructed type.
7398 static void
7399 mono_type_from_blob_type (MonoType *type, MonoTypeEnum blob_type, MonoType *real_type)
7401 type->type = blob_type;
7402 type->data.klass = NULL;
7403 if (blob_type == MONO_TYPE_CLASS)
7404 type->data.klass = mono_defaults.object_class;
7405 else if (real_type->type == MONO_TYPE_VALUETYPE && real_type->data.klass->enumtype) {
7406 /* For enums, we need to use the base type */
7407 type->type = MONO_TYPE_VALUETYPE;
7408 type->data.klass = mono_class_from_mono_type (real_type);
7409 } else
7410 type->data.klass = mono_class_from_mono_type (real_type);
7413 static MonoObject*
7414 property_info_get_default_value (MonoReflectionProperty *property)
7416 MonoType blob_type;
7417 MonoProperty *prop = property->property;
7418 MonoType *type = get_property_type (prop);
7419 MonoDomain *domain = mono_object_domain (property);
7420 MonoTypeEnum def_type;
7421 const char *def_value;
7422 MonoObject *o;
7424 mono_class_init (prop->parent);
7426 if (!(prop->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT))
7427 mono_raise_exception (mono_get_exception_invalid_operation (NULL));
7429 def_value = mono_class_get_property_default_value (prop, &def_type);
7431 mono_type_from_blob_type (&blob_type, def_type, type);
7432 o = mono_get_object_from_blob (domain, &blob_type, def_value);
7434 return o;
7437 static MonoBoolean
7438 custom_attrs_defined_internal (MonoObject *obj, MonoReflectionType *attr_type)
7440 MonoClass *attr_class = mono_class_from_mono_type (attr_type->type);
7441 MonoCustomAttrInfo *cinfo;
7442 gboolean found;
7444 mono_class_init_or_throw (attr_class);
7446 cinfo = mono_reflection_get_custom_attrs_info (obj);
7447 if (!cinfo)
7448 return FALSE;
7449 found = mono_custom_attrs_has_attr (cinfo, attr_class);
7450 if (!cinfo->cached)
7451 mono_custom_attrs_free (cinfo);
7452 return found;
7455 static MonoArray*
7456 custom_attrs_get_by_type (MonoObject *obj, MonoReflectionType *attr_type)
7458 MonoClass *attr_class = attr_type ? mono_class_from_mono_type (attr_type->type) : NULL;
7459 MonoArray *res;
7461 if (attr_class)
7462 mono_class_init_or_throw (attr_class);
7464 res = mono_reflection_get_custom_attrs_by_type (obj, attr_class);
7466 if (mono_loader_get_last_error ()) {
7467 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
7468 g_assert_not_reached ();
7469 /* Not reached */
7470 return NULL;
7471 } else {
7472 return res;
7476 static MonoString*
7477 ves_icall_Mono_Runtime_GetDisplayName (void)
7479 char *info;
7480 MonoString *display_name;
7482 info = mono_get_runtime_callbacks ()->get_runtime_build_info ();
7483 display_name = mono_string_new (mono_domain_get (), info);
7484 g_free (info);
7485 return display_name;
7488 static MonoString*
7489 ves_icall_System_ComponentModel_Win32Exception_W32ErrorMessage (guint32 code)
7491 MonoString *message;
7492 guint32 ret;
7493 gunichar2 buf[256];
7495 ret = FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM |
7496 FORMAT_MESSAGE_IGNORE_INSERTS, NULL, code, 0,
7497 buf, 255, NULL);
7498 if (ret == 0) {
7499 message = mono_string_new (mono_domain_get (), "Error looking up error string");
7500 } else {
7501 message = mono_string_new_utf16 (mono_domain_get (), buf, ret);
7504 return message;
7507 const static guchar
7508 dbase64 [] = {
7509 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
7510 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
7511 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 62, 128, 128, 128, 63,
7512 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 128, 128, 128, 0, 128, 128,
7513 128, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
7514 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 128, 128, 128, 128, 128,
7515 128, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
7516 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51
7519 static MonoArray *
7520 base64_to_byte_array (gunichar2 *start, gint ilength, MonoBoolean allowWhitespaceOnly)
7522 gint ignored;
7523 gint i;
7524 gunichar2 c;
7525 gunichar2 last, prev_last, prev2_last;
7526 gint olength;
7527 MonoArray *result;
7528 guchar *res_ptr;
7529 gint a [4], b [4];
7530 MonoException *exc;
7532 ignored = 0;
7533 last = prev_last = 0, prev2_last = 0;
7534 for (i = 0; i < ilength; i++) {
7535 c = start [i];
7536 if (c >= sizeof (dbase64)) {
7537 exc = mono_exception_from_name_msg (mono_get_corlib (),
7538 "System", "FormatException",
7539 "Invalid character found.");
7540 mono_raise_exception (exc);
7541 } else if (isspace (c)) {
7542 ignored++;
7543 } else {
7544 prev2_last = prev_last;
7545 prev_last = last;
7546 last = c;
7550 olength = ilength - ignored;
7552 if (allowWhitespaceOnly && olength == 0) {
7553 return mono_array_new (mono_domain_get (), mono_defaults.byte_class, 0);
7556 if ((olength & 3) != 0 || olength <= 0) {
7557 exc = mono_exception_from_name_msg (mono_get_corlib (), "System",
7558 "FormatException", "Invalid length.");
7559 mono_raise_exception (exc);
7562 if (prev2_last == '=') {
7563 exc = mono_exception_from_name_msg (mono_get_corlib (), "System", "FormatException", "Invalid format.");
7564 mono_raise_exception (exc);
7567 olength = (olength * 3) / 4;
7568 if (last == '=')
7569 olength--;
7571 if (prev_last == '=')
7572 olength--;
7574 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, olength);
7575 res_ptr = mono_array_addr (result, guchar, 0);
7576 for (i = 0; i < ilength; ) {
7577 int k;
7579 for (k = 0; k < 4 && i < ilength;) {
7580 c = start [i++];
7581 if (isspace (c))
7582 continue;
7584 a [k] = (guchar) c;
7585 if (((b [k] = dbase64 [c]) & 0x80) != 0) {
7586 exc = mono_exception_from_name_msg (mono_get_corlib (),
7587 "System", "FormatException",
7588 "Invalid character found.");
7589 mono_raise_exception (exc);
7591 k++;
7594 *res_ptr++ = (b [0] << 2) | (b [1] >> 4);
7595 if (a [2] != '=')
7596 *res_ptr++ = (b [1] << 4) | (b [2] >> 2);
7597 if (a [3] != '=')
7598 *res_ptr++ = (b [2] << 6) | b [3];
7600 while (i < ilength && isspace (start [i]))
7601 i++;
7604 return result;
7607 static MonoArray *
7608 InternalFromBase64String (MonoString *str, MonoBoolean allowWhitespaceOnly)
7610 MONO_ARCH_SAVE_REGS;
7612 return base64_to_byte_array (mono_string_chars (str),
7613 mono_string_length (str), allowWhitespaceOnly);
7616 static MonoArray *
7617 InternalFromBase64CharArray (MonoArray *input, gint offset, gint length)
7619 MONO_ARCH_SAVE_REGS;
7621 return base64_to_byte_array (mono_array_addr (input, gunichar2, offset),
7622 length, FALSE);
7625 #define ICALL_TYPE(id,name,first)
7626 #define ICALL(id,name,func) Icall_ ## id,
7628 enum {
7629 #include "metadata/icall-def.h"
7630 Icall_last
7633 #undef ICALL_TYPE
7634 #undef ICALL
7635 #define ICALL_TYPE(id,name,first) Icall_type_ ## id,
7636 #define ICALL(id,name,func)
7637 enum {
7638 #include "metadata/icall-def.h"
7639 Icall_type_num
7642 #undef ICALL_TYPE
7643 #undef ICALL
7644 #define ICALL_TYPE(id,name,firstic) {(Icall_ ## firstic)},
7645 #define ICALL(id,name,func)
7646 typedef struct {
7647 guint16 first_icall;
7648 } IcallTypeDesc;
7650 static const IcallTypeDesc
7651 icall_type_descs [] = {
7652 #include "metadata/icall-def.h"
7653 {Icall_last}
7656 #define icall_desc_num_icalls(desc) ((desc) [1].first_icall - (desc) [0].first_icall)
7658 #undef ICALL_TYPE
7659 #define ICALL_TYPE(id,name,first)
7660 #undef ICALL
7662 #ifdef HAVE_ARRAY_ELEM_INIT
7663 #define MSGSTRFIELD(line) MSGSTRFIELD1(line)
7664 #define MSGSTRFIELD1(line) str##line
7666 static const struct msgstrtn_t {
7667 #define ICALL(id,name,func)
7668 #undef ICALL_TYPE
7669 #define ICALL_TYPE(id,name,first) char MSGSTRFIELD(__LINE__) [sizeof (name)];
7670 #include "metadata/icall-def.h"
7671 #undef ICALL_TYPE
7672 } icall_type_names_str = {
7673 #define ICALL_TYPE(id,name,first) (name),
7674 #include "metadata/icall-def.h"
7675 #undef ICALL_TYPE
7677 static const guint16 icall_type_names_idx [] = {
7678 #define ICALL_TYPE(id,name,first) [Icall_type_ ## id] = offsetof (struct msgstrtn_t, MSGSTRFIELD(__LINE__)),
7679 #include "metadata/icall-def.h"
7680 #undef ICALL_TYPE
7682 #define icall_type_name_get(id) ((const char*)&icall_type_names_str + icall_type_names_idx [(id)])
7684 static const struct msgstr_t {
7685 #undef ICALL
7686 #define ICALL_TYPE(id,name,first)
7687 #define ICALL(id,name,func) char MSGSTRFIELD(__LINE__) [sizeof (name)];
7688 #include "metadata/icall-def.h"
7689 #undef ICALL
7690 } icall_names_str = {
7691 #define ICALL(id,name,func) (name),
7692 #include "metadata/icall-def.h"
7693 #undef ICALL
7695 static const guint16 icall_names_idx [] = {
7696 #define ICALL(id,name,func) [Icall_ ## id] = offsetof (struct msgstr_t, MSGSTRFIELD(__LINE__)),
7697 #include "metadata/icall-def.h"
7698 #undef ICALL
7700 #define icall_name_get(id) ((const char*)&icall_names_str + icall_names_idx [(id)])
7702 #else
7704 #undef ICALL_TYPE
7705 #undef ICALL
7706 #define ICALL_TYPE(id,name,first) name,
7707 #define ICALL(id,name,func)
7708 static const char* const
7709 icall_type_names [] = {
7710 #include "metadata/icall-def.h"
7711 NULL
7714 #define icall_type_name_get(id) (icall_type_names [(id)])
7716 #undef ICALL_TYPE
7717 #undef ICALL
7718 #define ICALL_TYPE(id,name,first)
7719 #define ICALL(id,name,func) name,
7720 static const char* const
7721 icall_names [] = {
7722 #include "metadata/icall-def.h"
7723 NULL
7725 #define icall_name_get(id) icall_names [(id)]
7727 #endif /* !HAVE_ARRAY_ELEM_INIT */
7729 #undef ICALL_TYPE
7730 #undef ICALL
7731 #define ICALL_TYPE(id,name,first)
7732 #define ICALL(id,name,func) func,
7733 static const gconstpointer
7734 icall_functions [] = {
7735 #include "metadata/icall-def.h"
7736 NULL
7739 static GHashTable *icall_hash = NULL;
7740 static GHashTable *jit_icall_hash_name = NULL;
7741 static GHashTable *jit_icall_hash_addr = NULL;
7743 void
7744 mono_icall_init (void)
7746 int i = 0;
7748 /* check that tables are sorted: disable in release */
7749 if (TRUE) {
7750 int j;
7751 const char *prev_class = NULL;
7752 const char *prev_method;
7754 for (i = 0; i < Icall_type_num; ++i) {
7755 const IcallTypeDesc *desc;
7756 int num_icalls;
7757 prev_method = NULL;
7758 if (prev_class && strcmp (prev_class, icall_type_name_get (i)) >= 0)
7759 g_print ("class %s should come before class %s\n", icall_type_name_get (i), prev_class);
7760 prev_class = icall_type_name_get (i);
7761 desc = &icall_type_descs [i];
7762 num_icalls = icall_desc_num_icalls (desc);
7763 /*g_print ("class %s has %d icalls starting at %d\n", prev_class, num_icalls, desc->first_icall);*/
7764 for (j = 0; j < num_icalls; ++j) {
7765 const char *methodn = icall_name_get (desc->first_icall + j);
7766 if (prev_method && strcmp (prev_method, methodn) >= 0)
7767 g_print ("method %s should come before method %s\n", methodn, prev_method);
7768 prev_method = methodn;
7773 icall_hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
7776 void
7777 mono_icall_cleanup (void)
7779 g_hash_table_destroy (icall_hash);
7780 g_hash_table_destroy (jit_icall_hash_name);
7781 g_hash_table_destroy (jit_icall_hash_addr);
7784 void
7785 mono_add_internal_call (const char *name, gconstpointer method)
7787 mono_loader_lock ();
7789 g_hash_table_insert (icall_hash, g_strdup (name), (gpointer) method);
7791 mono_loader_unlock ();
7794 #ifdef HAVE_ARRAY_ELEM_INIT
7795 static int
7796 compare_method_imap (const void *key, const void *elem)
7798 const char* method_name = (const char*)&icall_names_str + (*(guint16*)elem);
7799 return strcmp (key, method_name);
7802 static gpointer
7803 find_method_icall (const IcallTypeDesc *imap, const char *name)
7805 const guint16 *nameslot = bsearch (name, icall_names_idx + imap->first_icall, icall_desc_num_icalls (imap), sizeof (icall_names_idx [0]), compare_method_imap);
7806 if (!nameslot)
7807 return NULL;
7808 return (gpointer)icall_functions [(nameslot - &icall_names_idx [0])];
7811 static int
7812 compare_class_imap (const void *key, const void *elem)
7814 const char* class_name = (const char*)&icall_type_names_str + (*(guint16*)elem);
7815 return strcmp (key, class_name);
7818 static const IcallTypeDesc*
7819 find_class_icalls (const char *name)
7821 const guint16 *nameslot = bsearch (name, icall_type_names_idx, Icall_type_num, sizeof (icall_type_names_idx [0]), compare_class_imap);
7822 if (!nameslot)
7823 return NULL;
7824 return &icall_type_descs [nameslot - &icall_type_names_idx [0]];
7827 #else
7828 static int
7829 compare_method_imap (const void *key, const void *elem)
7831 const char** method_name = (const char**)elem;
7832 return strcmp (key, *method_name);
7835 static gpointer
7836 find_method_icall (const IcallTypeDesc *imap, const char *name)
7838 const char **nameslot = bsearch (name, icall_names + imap->first_icall, icall_desc_num_icalls (imap), sizeof (icall_names [0]), compare_method_imap);
7839 if (!nameslot)
7840 return NULL;
7841 return (gpointer)icall_functions [(nameslot - icall_names)];
7844 static int
7845 compare_class_imap (const void *key, const void *elem)
7847 const char** class_name = (const char**)elem;
7848 return strcmp (key, *class_name);
7851 static const IcallTypeDesc*
7852 find_class_icalls (const char *name)
7854 const char **nameslot = bsearch (name, icall_type_names, Icall_type_num, sizeof (icall_type_names [0]), compare_class_imap);
7855 if (!nameslot)
7856 return NULL;
7857 return &icall_type_descs [nameslot - icall_type_names];
7860 #endif
7863 * we should probably export this as an helper (handle nested types).
7864 * Returns the number of chars written in buf.
7866 static int
7867 concat_class_name (char *buf, int bufsize, MonoClass *klass)
7869 int nspacelen, cnamelen;
7870 nspacelen = strlen (klass->name_space);
7871 cnamelen = strlen (klass->name);
7872 if (nspacelen + cnamelen + 2 > bufsize)
7873 return 0;
7874 if (nspacelen) {
7875 memcpy (buf, klass->name_space, nspacelen);
7876 buf [nspacelen ++] = '.';
7878 memcpy (buf + nspacelen, klass->name, cnamelen);
7879 buf [nspacelen + cnamelen] = 0;
7880 return nspacelen + cnamelen;
7883 gpointer
7884 mono_lookup_internal_call (MonoMethod *method)
7886 char *sigstart;
7887 char *tmpsig;
7888 char mname [2048];
7889 int typelen = 0, mlen, siglen;
7890 gpointer res;
7891 const IcallTypeDesc *imap;
7893 g_assert (method != NULL);
7895 if (method->is_inflated)
7896 method = ((MonoMethodInflated *) method)->declaring;
7898 if (method->klass->nested_in) {
7899 int pos = concat_class_name (mname, sizeof (mname)-2, method->klass->nested_in);
7900 if (!pos)
7901 return NULL;
7903 mname [pos++] = '/';
7904 mname [pos] = 0;
7906 typelen = concat_class_name (mname+pos, sizeof (mname)-pos-1, method->klass);
7907 if (!typelen)
7908 return NULL;
7910 typelen += pos;
7911 } else {
7912 typelen = concat_class_name (mname, sizeof (mname), method->klass);
7913 if (!typelen)
7914 return NULL;
7917 imap = find_class_icalls (mname);
7919 mname [typelen] = ':';
7920 mname [typelen + 1] = ':';
7922 mlen = strlen (method->name);
7923 memcpy (mname + typelen + 2, method->name, mlen);
7924 sigstart = mname + typelen + 2 + mlen;
7925 *sigstart = 0;
7927 tmpsig = mono_signature_get_desc (mono_method_signature (method), TRUE);
7928 siglen = strlen (tmpsig);
7929 if (typelen + mlen + siglen + 6 > sizeof (mname))
7930 return NULL;
7931 sigstart [0] = '(';
7932 memcpy (sigstart + 1, tmpsig, siglen);
7933 sigstart [siglen + 1] = ')';
7934 sigstart [siglen + 2] = 0;
7935 g_free (tmpsig);
7937 mono_loader_lock ();
7939 res = g_hash_table_lookup (icall_hash, mname);
7940 if (res) {
7941 mono_loader_unlock ();
7942 return res;
7944 /* try without signature */
7945 *sigstart = 0;
7946 res = g_hash_table_lookup (icall_hash, mname);
7947 if (res) {
7948 mono_loader_unlock ();
7949 return res;
7952 /* it wasn't found in the static call tables */
7953 if (!imap) {
7954 mono_loader_unlock ();
7955 return NULL;
7957 res = find_method_icall (imap, sigstart - mlen);
7958 if (res) {
7959 mono_loader_unlock ();
7960 return res;
7962 /* try _with_ signature */
7963 *sigstart = '(';
7964 res = find_method_icall (imap, sigstart - mlen);
7965 if (res) {
7966 mono_loader_unlock ();
7967 return res;
7970 g_warning ("cant resolve internal call to \"%s\" (tested without signature also)", mname);
7971 g_print ("\nYour mono runtime and class libraries are out of sync.\n");
7972 g_print ("The out of sync library is: %s\n", method->klass->image->name);
7973 g_print ("\nWhen you update one from svn you need to update, compile and install\nthe other too.\n");
7974 g_print ("Do not report this as a bug unless you're sure you have updated correctly:\nyou probably have a broken mono install.\n");
7975 g_print ("If you see other errors or faults after this message they are probably related\n");
7976 g_print ("and you need to fix your mono install first.\n");
7978 mono_loader_unlock ();
7980 return NULL;
7983 static MonoType*
7984 type_from_typename (char *typename)
7986 MonoClass *klass = NULL; /* assignment to shut GCC warning up */
7988 if (!strcmp (typename, "int"))
7989 klass = mono_defaults.int_class;
7990 else if (!strcmp (typename, "ptr"))
7991 klass = mono_defaults.int_class;
7992 else if (!strcmp (typename, "void"))
7993 klass = mono_defaults.void_class;
7994 else if (!strcmp (typename, "int32"))
7995 klass = mono_defaults.int32_class;
7996 else if (!strcmp (typename, "uint32"))
7997 klass = mono_defaults.uint32_class;
7998 else if (!strcmp (typename, "int8"))
7999 klass = mono_defaults.sbyte_class;
8000 else if (!strcmp (typename, "uint8"))
8001 klass = mono_defaults.byte_class;
8002 else if (!strcmp (typename, "int16"))
8003 klass = mono_defaults.int16_class;
8004 else if (!strcmp (typename, "uint16"))
8005 klass = mono_defaults.uint16_class;
8006 else if (!strcmp (typename, "long"))
8007 klass = mono_defaults.int64_class;
8008 else if (!strcmp (typename, "ulong"))
8009 klass = mono_defaults.uint64_class;
8010 else if (!strcmp (typename, "float"))
8011 klass = mono_defaults.single_class;
8012 else if (!strcmp (typename, "double"))
8013 klass = mono_defaults.double_class;
8014 else if (!strcmp (typename, "object"))
8015 klass = mono_defaults.object_class;
8016 else if (!strcmp (typename, "obj"))
8017 klass = mono_defaults.object_class;
8018 else if (!strcmp (typename, "string"))
8019 klass = mono_defaults.string_class;
8020 else if (!strcmp (typename, "bool"))
8021 klass = mono_defaults.boolean_class;
8022 else if (!strcmp (typename, "boolean"))
8023 klass = mono_defaults.boolean_class;
8024 else {
8025 g_error ("%s", typename);
8026 g_assert_not_reached ();
8028 return &klass->byval_arg;
8031 MonoMethodSignature*
8032 mono_create_icall_signature (const char *sigstr)
8034 gchar **parts;
8035 int i, len;
8036 gchar **tmp;
8037 MonoMethodSignature *res;
8039 mono_loader_lock ();
8040 res = g_hash_table_lookup (mono_defaults.corlib->helper_signatures, sigstr);
8041 if (res) {
8042 mono_loader_unlock ();
8043 return res;
8046 parts = g_strsplit (sigstr, " ", 256);
8048 tmp = parts;
8049 len = 0;
8050 while (*tmp) {
8051 len ++;
8052 tmp ++;
8055 res = mono_metadata_signature_alloc (mono_defaults.corlib, len - 1);
8056 res->pinvoke = 1;
8058 #ifdef HOST_WIN32
8060 * Under windows, the default pinvoke calling convention is STDCALL but
8061 * we need CDECL.
8063 res->call_convention = MONO_CALL_C;
8064 #endif
8066 res->ret = type_from_typename (parts [0]);
8067 for (i = 1; i < len; ++i) {
8068 res->params [i - 1] = type_from_typename (parts [i]);
8071 g_strfreev (parts);
8073 g_hash_table_insert (mono_defaults.corlib->helper_signatures, (gpointer)sigstr, res);
8075 mono_loader_unlock ();
8077 return res;
8080 MonoJitICallInfo *
8081 mono_find_jit_icall_by_name (const char *name)
8083 MonoJitICallInfo *info;
8084 g_assert (jit_icall_hash_name);
8086 mono_loader_lock ();
8087 info = g_hash_table_lookup (jit_icall_hash_name, name);
8088 mono_loader_unlock ();
8089 return info;
8092 MonoJitICallInfo *
8093 mono_find_jit_icall_by_addr (gconstpointer addr)
8095 MonoJitICallInfo *info;
8096 g_assert (jit_icall_hash_addr);
8098 mono_loader_lock ();
8099 info = g_hash_table_lookup (jit_icall_hash_addr, (gpointer)addr);
8100 mono_loader_unlock ();
8102 return info;
8106 * mono_get_jit_icall_info:
8108 * Return the hashtable mapping JIT icall names to MonoJitICallInfo structures. The
8109 * caller should access it while holding the loader lock.
8111 GHashTable*
8112 mono_get_jit_icall_info (void)
8114 return jit_icall_hash_name;
8117 void
8118 mono_register_jit_icall_wrapper (MonoJitICallInfo *info, gconstpointer wrapper)
8120 mono_loader_lock ();
8121 g_hash_table_insert (jit_icall_hash_addr, (gpointer)wrapper, info);
8122 mono_loader_unlock ();
8125 MonoJitICallInfo *
8126 mono_register_jit_icall (gconstpointer func, const char *name, MonoMethodSignature *sig, gboolean is_save)
8128 MonoJitICallInfo *info;
8130 g_assert (func);
8131 g_assert (name);
8133 mono_loader_lock ();
8135 if (!jit_icall_hash_name) {
8136 jit_icall_hash_name = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_free);
8137 jit_icall_hash_addr = g_hash_table_new (NULL, NULL);
8140 if (g_hash_table_lookup (jit_icall_hash_name, name)) {
8141 g_warning ("jit icall already defined \"%s\"\n", name);
8142 g_assert_not_reached ();
8145 info = g_new0 (MonoJitICallInfo, 1);
8147 info->name = name;
8148 info->func = func;
8149 info->sig = sig;
8151 if (is_save) {
8152 info->wrapper = func;
8153 } else {
8154 info->wrapper = NULL;
8157 g_hash_table_insert (jit_icall_hash_name, (gpointer)info->name, info);
8158 g_hash_table_insert (jit_icall_hash_addr, (gpointer)func, info);
8160 mono_loader_unlock ();
8161 return info;