e1539de106cd4bb92eaa32c27f30e5795facc6cd
[mono.git] / mono / metadata / class.c
1 /**
2  * \file
3  * Class management for the Mono runtime
4  *
5  * Author:
6  *   Miguel de Icaza (miguel@ximian.com)
7  *
8  * Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
9  * Copyright 2004-2009 Novell, Inc (http://www.novell.com)
10  * Copyright 2012 Xamarin Inc (http://www.xamarin.com)
11  * Licensed under the MIT license. See LICENSE file in the project root for full license information.
12  */
13 #include <config.h>
14 #ifdef HAVE_ALLOCA_H
15 #include <alloca.h>
16 #endif
17 #include <glib.h>
18 #include <stdio.h>
19 #include <string.h>
20 #include <stdlib.h>
21 #include <mono/metadata/image.h>
22 #include <mono/metadata/image-internals.h>
23 #include <mono/metadata/assembly.h>
24 #include <mono/metadata/assembly-internals.h>
25 #include <mono/metadata/metadata.h>
26 #include <mono/metadata/metadata-internals.h>
27 #include <mono/metadata/profiler-private.h>
28 #include <mono/metadata/tabledefs.h>
29 #include <mono/metadata/tokentype.h>
30 #include <mono/metadata/class-internals.h>
31 #include <mono/metadata/object.h>
32 #include <mono/metadata/appdomain.h>
33 #include <mono/metadata/mono-endian.h>
34 #include <mono/metadata/debug-helpers.h>
35 #include <mono/metadata/reflection.h>
36 #include <mono/metadata/exception.h>
37 #include <mono/metadata/security-manager.h>
38 #include <mono/metadata/security-core-clr.h>
39 #include <mono/metadata/attrdefs.h>
40 #include <mono/metadata/gc-internals.h>
41 #include <mono/metadata/verify-internals.h>
42 #include <mono/metadata/mono-debug.h>
43 #include <mono/utils/mono-counters.h>
44 #include <mono/utils/mono-string.h>
45 #include <mono/utils/mono-error-internals.h>
46 #include <mono/utils/mono-logger-internals.h>
47 #include <mono/utils/mono-memory-model.h>
48 #include <mono/utils/atomic.h>
49 #include <mono/utils/unlocked.h>
50 #include <mono/utils/bsearch.h>
51 #include <mono/utils/checked-build.h>
52
53 MonoStats mono_stats;
54
55 gboolean mono_print_vtable = FALSE;
56 gboolean mono_align_small_structs = FALSE;
57
58 /* Statistics */
59 gint32 inflated_classes_size, inflated_methods_size;
60 gint32 classes_size;
61 gint32 class_def_count, class_gtd_count, class_ginst_count, class_gparam_count, class_array_count, class_pointer_count;
62
63 /* Low level lock which protects data structures in this module */
64 static mono_mutex_t classes_mutex;
65
66 /* Function supplied by the runtime to find classes by name using information from the AOT file */
67 static MonoGetClassFromName get_class_from_name = NULL;
68
69 static MonoClass * mono_class_create_from_typedef (MonoImage *image, guint32 type_token, MonoError *error);
70 static gboolean mono_class_get_cached_class_info (MonoClass *klass, MonoCachedClassInfo *res);
71 static gboolean can_access_type (MonoClass *access_klass, MonoClass *member_klass);
72 static MonoMethod* find_method_in_metadata (MonoClass *klass, const char *name, int param_count, int flags);
73 static int generic_array_methods (MonoClass *klass);
74 static void setup_generic_array_ifaces (MonoClass *klass, MonoClass *iface, MonoMethod **methods, int pos, GHashTable *cache);
75
76 static MonoMethod* mono_class_get_virtual_methods (MonoClass* klass, gpointer *iter);
77 static char* mono_assembly_name_from_token (MonoImage *image, guint32 type_token);
78 static void mono_field_resolve_type (MonoClassField *field, MonoError *error);
79 static guint32 mono_field_resolve_flags (MonoClassField *field);
80 static void mono_class_setup_vtable_full (MonoClass *klass, GList *in_setup);
81 static void mono_generic_class_setup_parent (MonoClass *klass, MonoClass *gklass);
82
83 static gboolean mono_class_set_failure (MonoClass *klass, MonoErrorBoxed *boxed_error);
84
85
86 /*
87 We use gclass recording to allow recursive system f types to be referenced by a parent.
88
89 Given the following type hierarchy:
90
91 class TextBox : TextBoxBase<TextBox> {}
92 class TextBoxBase<T> : TextInput<TextBox> where T : TextBoxBase<T> {}
93 class TextInput<T> : Input<T> where T: TextInput<T> {}
94 class Input<T> {}
95
96 The runtime tries to load TextBoxBase<>.
97 To load TextBoxBase<> to do so it must resolve the parent which is TextInput<TextBox>.
98 To instantiate TextInput<TextBox> it must resolve TextInput<> and TextBox.
99 To load TextBox it must resolve the parent which is TextBoxBase<TextBox>.
100
101 At this point the runtime must instantiate TextBoxBase<TextBox>. Both types are partially loaded 
102 at this point, iow, both are registered in the type map and both and a NULL parent. This means
103 that the resulting generic instance will have a NULL parent, which is wrong and will cause breakage.
104
105 To fix that what we do is to record all generic instantes created while resolving the parent of
106 any generic type definition and, after resolved, correct the parent field if needed.
107
108 */
109 static int record_gclass_instantiation;
110 static GSList *gclass_recorded_list;
111 typedef gboolean (*gclass_record_func) (MonoClass*, void*);
112
113 /* This TLS variable points to a GSList of classes which have setup_fields () executing */
114 static MonoNativeTlsKey setup_fields_tls_id;
115
116 static MonoNativeTlsKey init_pending_tls_id;
117
118 static inline void
119 classes_lock (void)
120 {
121         mono_locks_os_acquire (&classes_mutex, ClassesLock);
122 }
123
124 static inline void
125 classes_unlock (void)
126 {
127         mono_locks_os_release (&classes_mutex, ClassesLock);
128 }
129
130 /* 
131  * LOCKING: loader lock must be held until pairing disable_gclass_recording is called.
132 */
133 static void
134 enable_gclass_recording (void)
135 {
136         ++record_gclass_instantiation;
137 }
138
139 /* 
140  * LOCKING: loader lock must be held since pairing enable_gclass_recording was called.
141 */
142 static void
143 disable_gclass_recording (gclass_record_func func, void *user_data)
144 {
145         GSList **head = &gclass_recorded_list;
146
147         g_assert (record_gclass_instantiation > 0);
148         --record_gclass_instantiation;
149
150         while (*head) {
151                 GSList *node = *head;
152                 if (func ((MonoClass*)node->data, user_data)) {
153                         *head = node->next;
154                         g_slist_free_1 (node);
155                 } else {
156                         head = &node->next;
157                 }
158         }
159
160         /* We automatically discard all recorded gclasses when disabled. */
161         if (!record_gclass_instantiation && gclass_recorded_list) {
162                 g_slist_free (gclass_recorded_list);
163                 gclass_recorded_list = NULL;
164         }
165 }
166
167 /**
168  * mono_class_from_typeref:
169  * \param image a MonoImage
170  * \param type_token a TypeRef token
171  *
172  * Creates the \c MonoClass* structure representing the type defined by
173  * the typeref token valid inside \p image.
174  * \returns The \c MonoClass* representing the typeref token, or NULL if it could
175  * not be loaded.
176  */
177 MonoClass *
178 mono_class_from_typeref (MonoImage *image, guint32 type_token)
179 {
180         MonoError error;
181         MonoClass *klass = mono_class_from_typeref_checked (image, type_token, &error);
182         g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
183         return klass;
184 }
185
186 /**
187  * mono_class_from_typeref_checked:
188  * \param image a MonoImage
189  * \param type_token a TypeRef token
190  * \param error error return code, if any.
191  *
192  * Creates the \c MonoClass* structure representing the type defined by
193  * the typeref token valid inside \p image.
194  *
195  * \returns The \c MonoClass* representing the typeref token, NULL if it could
196  * not be loaded with the \p error value filled with the information about the
197  * error.
198  */
199 MonoClass *
200 mono_class_from_typeref_checked (MonoImage *image, guint32 type_token, MonoError *error)
201 {
202         guint32 cols [MONO_TYPEREF_SIZE];
203         MonoTableInfo  *t = &image->tables [MONO_TABLE_TYPEREF];
204         guint32 idx;
205         const char *name, *nspace;
206         MonoClass *res = NULL;
207         MonoImage *module;
208
209         error_init (error);
210
211         if (!mono_verifier_verify_typeref_row (image, (type_token & 0xffffff) - 1, error))
212                 return NULL;
213
214         mono_metadata_decode_row (t, (type_token&0xffffff)-1, cols, MONO_TYPEREF_SIZE);
215
216         name = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAME]);
217         nspace = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAMESPACE]);
218
219         idx = cols [MONO_TYPEREF_SCOPE] >> MONO_RESOLUTION_SCOPE_BITS;
220         switch (cols [MONO_TYPEREF_SCOPE] & MONO_RESOLUTION_SCOPE_MASK) {
221         case MONO_RESOLUTION_SCOPE_MODULE:
222                 /*
223                 LAMESPEC The spec says that a null module resolution scope should go through the exported type table.
224                 This is not the observed behavior of existing implementations.
225                 The defacto behavior is that it's just a typedef in disguise.
226                 */
227                 /* a typedef in disguise */
228                 res = mono_class_from_name_checked (image, nspace, name, error);
229                 goto done;
230
231         case MONO_RESOLUTION_SCOPE_MODULEREF:
232                 module = mono_image_load_module_checked (image, idx, error);
233                 if (module)
234                         res = mono_class_from_name_checked (module, nspace, name, error);
235                 goto done;
236
237         case MONO_RESOLUTION_SCOPE_TYPEREF: {
238                 MonoClass *enclosing;
239                 GList *tmp;
240
241                 if (idx == mono_metadata_token_index (type_token)) {
242                         mono_error_set_bad_image (error, image, "Image with self-referencing typeref token %08x.", type_token);
243                         return NULL;
244                 }
245
246                 enclosing = mono_class_from_typeref_checked (image, MONO_TOKEN_TYPE_REF | idx, error); 
247                 return_val_if_nok (error, NULL);
248
249                 GList *nested_classes = mono_class_get_nested_classes_property (enclosing);
250                 if (enclosing->nested_classes_inited && nested_classes) {
251                         /* Micro-optimization: don't scan the metadata tables if enclosing is already inited */
252                         for (tmp = nested_classes; tmp; tmp = tmp->next) {
253                                 res = (MonoClass *)tmp->data;
254                                 if (strcmp (res->name, name) == 0)
255                                         return res;
256                         }
257                 } else {
258                         /* Don't call mono_class_init as we might've been called by it recursively */
259                         int i = mono_metadata_nesting_typedef (enclosing->image, enclosing->type_token, 1);
260                         while (i) {
261                                 guint32 class_nested = mono_metadata_decode_row_col (&enclosing->image->tables [MONO_TABLE_NESTEDCLASS], i - 1, MONO_NESTED_CLASS_NESTED);
262                                 guint32 string_offset = mono_metadata_decode_row_col (&enclosing->image->tables [MONO_TABLE_TYPEDEF], class_nested - 1, MONO_TYPEDEF_NAME);
263                                 const char *nname = mono_metadata_string_heap (enclosing->image, string_offset);
264
265                                 if (strcmp (nname, name) == 0)
266                                         return mono_class_create_from_typedef (enclosing->image, MONO_TOKEN_TYPE_DEF | class_nested, error);
267
268                                 i = mono_metadata_nesting_typedef (enclosing->image, enclosing->type_token, i + 1);
269                         }
270                 }
271                 g_warning ("TypeRef ResolutionScope not yet handled (%d) for %s.%s in image %s", idx, nspace, name, image->name);
272                 goto done;
273         }
274         case MONO_RESOLUTION_SCOPE_ASSEMBLYREF:
275                 break;
276         }
277
278         if (idx > image->tables [MONO_TABLE_ASSEMBLYREF].rows) {
279                 mono_error_set_bad_image (error, image, "Image with invalid assemblyref token %08x.", idx);
280                 return NULL;
281         }
282
283         if (!image->references || !image->references [idx - 1])
284                 mono_assembly_load_reference (image, idx - 1);
285         g_assert (image->references [idx - 1]);
286
287         /* If the assembly did not load, register this as a type load exception */
288         if (image->references [idx - 1] == REFERENCE_MISSING){
289                 MonoAssemblyName aname;
290                 char *human_name;
291                 
292                 mono_assembly_get_assemblyref (image, idx - 1, &aname);
293                 human_name = mono_stringify_assembly_name (&aname);
294                 mono_error_set_assembly_load_simple (error, human_name, image->assembly ? image->assembly->ref_only : FALSE);
295                 return NULL;
296         }
297
298         res = mono_class_from_name_checked (image->references [idx - 1]->image, nspace, name, error);
299
300 done:
301         /* Generic case, should be avoided for when a better error is possible. */
302         if (!res && mono_error_ok (error)) {
303                 char *name = mono_class_name_from_token (image, type_token);
304                 char *assembly = mono_assembly_name_from_token (image, type_token);
305                 mono_error_set_type_load_name (error, name, assembly, "Could not resolve type with token %08x (from typeref, class/assembly %s, %s)", type_token, name, assembly);
306         }
307         return res;
308 }
309
310
311 static void *
312 mono_image_memdup (MonoImage *image, void *data, guint size)
313 {
314         void *res = mono_image_alloc (image, size);
315         memcpy (res, data, size);
316         return res;
317 }
318         
319 /* Copy everything mono_metadata_free_array free. */
320 MonoArrayType *
321 mono_dup_array_type (MonoImage *image, MonoArrayType *a)
322 {
323         if (image) {
324                 a = (MonoArrayType *)mono_image_memdup (image, a, sizeof (MonoArrayType));
325                 if (a->sizes)
326                         a->sizes = (int *)mono_image_memdup (image, a->sizes, a->numsizes * sizeof (int));
327                 if (a->lobounds)
328                         a->lobounds = (int *)mono_image_memdup (image, a->lobounds, a->numlobounds * sizeof (int));
329         } else {
330                 a = (MonoArrayType *)g_memdup (a, sizeof (MonoArrayType));
331                 if (a->sizes)
332                         a->sizes = (int *)g_memdup (a->sizes, a->numsizes * sizeof (int));
333                 if (a->lobounds)
334                         a->lobounds = (int *)g_memdup (a->lobounds, a->numlobounds * sizeof (int));
335         }
336         return a;
337 }
338
339 /* Copy everything mono_metadata_free_method_signature free. */
340 MonoMethodSignature*
341 mono_metadata_signature_deep_dup (MonoImage *image, MonoMethodSignature *sig)
342 {
343         int i;
344         
345         sig = mono_metadata_signature_dup_full (image, sig);
346         
347         sig->ret = mono_metadata_type_dup (image, sig->ret);
348         for (i = 0; i < sig->param_count; ++i)
349                 sig->params [i] = mono_metadata_type_dup (image, sig->params [i]);
350         
351         return sig;
352 }
353
354 static void
355 _mono_type_get_assembly_name (MonoClass *klass, GString *str)
356 {
357         MonoAssembly *ta = klass->image->assembly;
358         char *name;
359
360         name = mono_stringify_assembly_name (&ta->aname);
361         g_string_append_printf (str, ", %s", name);
362         g_free (name);
363 }
364
365 static inline void
366 mono_type_name_check_byref (MonoType *type, GString *str)
367 {
368         if (type->byref)
369                 g_string_append_c (str, '&');
370 }
371
372 /**
373  * mono_identifier_escape_type_name_chars:
374  * \param str a destination string
375  * \param identifier an IDENTIFIER in internal form
376  *
377  * \returns \p str
378  *
379  * The displayed form of the identifier is appended to str.
380  *
381  * The displayed form of an identifier has the characters ,+&*[]\
382  * that have special meaning in type names escaped with a preceeding
383  * backslash (\) character.
384  */
385 static GString*
386 mono_identifier_escape_type_name_chars (GString* str, const char* identifier)
387 {
388         if (!identifier)
389                 return str;
390
391         size_t n = str->len;
392         // reserve space for common case: there will be no escaped characters.
393         g_string_set_size(str, n + strlen(identifier));
394         g_string_set_size(str, n);
395
396         for (const char* s = identifier; *s != 0 ; s++) {
397                 switch (*s) {
398                 case ',':
399                 case '+':
400                 case '&':
401                 case '*':
402                 case '[':
403                 case ']':
404                 case '\\':
405                         g_string_append_c (str, '\\');
406                         g_string_append_c (str, *s);
407                         break;
408                 default:
409                         g_string_append_c (str, *s);
410                         break;
411                 }
412         }
413         return str;
414 }
415
416 static void
417 mono_type_get_name_recurse (MonoType *type, GString *str, gboolean is_recursed,
418                             MonoTypeNameFormat format)
419 {
420         MonoClass *klass;
421         
422         switch (type->type) {
423         case MONO_TYPE_ARRAY: {
424                 int i, rank = type->data.array->rank;
425                 MonoTypeNameFormat nested_format;
426
427                 nested_format = format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED ?
428                         MONO_TYPE_NAME_FORMAT_FULL_NAME : format;
429
430                 mono_type_get_name_recurse (
431                         &type->data.array->eklass->byval_arg, str, FALSE, nested_format);
432                 g_string_append_c (str, '[');
433                 if (rank == 1)
434                         g_string_append_c (str, '*');
435                 for (i = 1; i < rank; i++)
436                         g_string_append_c (str, ',');
437                 g_string_append_c (str, ']');
438                 
439                 mono_type_name_check_byref (type, str);
440
441                 if (format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED)
442                         _mono_type_get_assembly_name (type->data.array->eklass, str);
443                 break;
444         }
445         case MONO_TYPE_SZARRAY: {
446                 MonoTypeNameFormat nested_format;
447
448                 nested_format = format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED ?
449                         MONO_TYPE_NAME_FORMAT_FULL_NAME : format;
450
451                 mono_type_get_name_recurse (
452                         &type->data.klass->byval_arg, str, FALSE, nested_format);
453                 g_string_append (str, "[]");
454                 
455                 mono_type_name_check_byref (type, str);
456
457                 if (format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED)
458                         _mono_type_get_assembly_name (type->data.klass, str);
459                 break;
460         }
461         case MONO_TYPE_PTR: {
462                 MonoTypeNameFormat nested_format;
463
464                 nested_format = format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED ?
465                         MONO_TYPE_NAME_FORMAT_FULL_NAME : format;
466
467                 mono_type_get_name_recurse (
468                         type->data.type, str, FALSE, nested_format);
469                 g_string_append_c (str, '*');
470
471                 mono_type_name_check_byref (type, str);
472
473                 if (format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED)
474                         _mono_type_get_assembly_name (mono_class_from_mono_type (type->data.type), str);
475                 break;
476         }
477         case MONO_TYPE_VAR:
478         case MONO_TYPE_MVAR:
479                 if (!mono_generic_param_info (type->data.generic_param))
480                         g_string_append_printf (str, "%s%d", type->type == MONO_TYPE_VAR ? "!" : "!!", type->data.generic_param->num);
481                 else
482                         g_string_append (str, mono_generic_param_info (type->data.generic_param)->name);
483
484                 mono_type_name_check_byref (type, str);
485
486                 break;
487         default:
488                 klass = mono_class_from_mono_type (type);
489                 if (klass->nested_in) {
490                         mono_type_get_name_recurse (
491                                 &klass->nested_in->byval_arg, str, TRUE, format);
492                         if (format == MONO_TYPE_NAME_FORMAT_IL)
493                                 g_string_append_c (str, '.');
494                         else
495                                 g_string_append_c (str, '+');
496                 } else if (*klass->name_space) {
497                         if (format == MONO_TYPE_NAME_FORMAT_IL)
498                                 g_string_append (str, klass->name_space);
499                         else
500                                 mono_identifier_escape_type_name_chars (str, klass->name_space);
501                         g_string_append_c (str, '.');
502                 }
503                 if (format == MONO_TYPE_NAME_FORMAT_IL) {
504                         char *s = strchr (klass->name, '`');
505                         int len = s ? s - klass->name : strlen (klass->name);
506                         g_string_append_len (str, klass->name, len);
507                 } else {
508                         mono_identifier_escape_type_name_chars (str, klass->name);
509                 }
510                 if (is_recursed)
511                         break;
512                 if (mono_class_is_ginst (klass)) {
513                         MonoGenericClass *gclass = mono_class_get_generic_class (klass);
514                         MonoGenericInst *inst = gclass->context.class_inst;
515                         MonoTypeNameFormat nested_format;
516                         int i;
517
518                         nested_format = format == MONO_TYPE_NAME_FORMAT_FULL_NAME ?
519                                 MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED : format;
520
521                         if (format == MONO_TYPE_NAME_FORMAT_IL)
522                                 g_string_append_c (str, '<');
523                         else
524                                 g_string_append_c (str, '[');
525                         for (i = 0; i < inst->type_argc; i++) {
526                                 MonoType *t = inst->type_argv [i];
527
528                                 if (i)
529                                         g_string_append_c (str, ',');
530                                 if ((nested_format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED) &&
531                                     (t->type != MONO_TYPE_VAR) && (type->type != MONO_TYPE_MVAR))
532                                         g_string_append_c (str, '[');
533                                 mono_type_get_name_recurse (inst->type_argv [i], str, FALSE, nested_format);
534                                 if ((nested_format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED) &&
535                                     (t->type != MONO_TYPE_VAR) && (type->type != MONO_TYPE_MVAR))
536                                         g_string_append_c (str, ']');
537                         }
538                         if (format == MONO_TYPE_NAME_FORMAT_IL) 
539                                 g_string_append_c (str, '>');
540                         else
541                                 g_string_append_c (str, ']');
542                 } else if (mono_class_is_gtd (klass) &&
543                            (format != MONO_TYPE_NAME_FORMAT_FULL_NAME) &&
544                            (format != MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED)) {
545                         int i;
546
547                         if (format == MONO_TYPE_NAME_FORMAT_IL) 
548                                 g_string_append_c (str, '<');
549                         else
550                                 g_string_append_c (str, '[');
551                         for (i = 0; i < mono_class_get_generic_container (klass)->type_argc; i++) {
552                                 if (i)
553                                         g_string_append_c (str, ',');
554                                 g_string_append (str, mono_generic_container_get_param_info (mono_class_get_generic_container (klass), i)->name);
555                         }
556                         if (format == MONO_TYPE_NAME_FORMAT_IL) 
557                                 g_string_append_c (str, '>');
558                         else
559                                 g_string_append_c (str, ']');
560                 }
561
562                 mono_type_name_check_byref (type, str);
563
564                 if ((format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED) &&
565                     (type->type != MONO_TYPE_VAR) && (type->type != MONO_TYPE_MVAR))
566                         _mono_type_get_assembly_name (klass, str);
567                 break;
568         }
569 }
570
571 /**
572  * mono_type_get_name_full:
573  * \param type a type
574  * \param format the format for the return string.
575  *
576  * 
577  * \returns The string representation in a number of formats:
578  *
579  * if \p format is \c MONO_TYPE_NAME_FORMAT_REFLECTION, the return string is
580  * returned in the format required by \c System.Reflection, this is the
581  * inverse of mono_reflection_parse_type().
582  *
583  * if \p format is \c MONO_TYPE_NAME_FORMAT_IL, it returns a syntax that can
584  * be used by the IL assembler.
585  *
586  * if \p format is \c MONO_TYPE_NAME_FORMAT_FULL_NAME
587  *
588  * if \p format is \c MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED
589  */
590 char*
591 mono_type_get_name_full (MonoType *type, MonoTypeNameFormat format)
592 {
593         GString* result;
594
595         result = g_string_new ("");
596
597         mono_type_get_name_recurse (type, result, FALSE, format);
598
599         return g_string_free (result, FALSE);
600 }
601
602 /**
603  * mono_type_get_full_name:
604  * \param class a class
605  *
606  * \returns The string representation for type as required by System.Reflection.
607  * The inverse of mono_reflection_parse_type().
608  */
609 char *
610 mono_type_get_full_name (MonoClass *klass)
611 {
612         return mono_type_get_name_full (mono_class_get_type (klass), MONO_TYPE_NAME_FORMAT_REFLECTION);
613 }
614
615 /**
616  * mono_type_get_name:
617  * \param type a type
618  * \returns The string representation for type as it would be represented in IL code.
619  */
620 char*
621 mono_type_get_name (MonoType *type)
622 {
623         return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_IL);
624 }
625
626 /**
627  * mono_type_get_underlying_type:
628  * \param type a type
629  * \returns The \c MonoType for the underlying integer type if \p type
630  * is an enum and byref is false, otherwise the type itself.
631  */
632 MonoType*
633 mono_type_get_underlying_type (MonoType *type)
634 {
635         if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype && !type->byref)
636                 return mono_class_enum_basetype (type->data.klass);
637         if (type->type == MONO_TYPE_GENERICINST && type->data.generic_class->container_class->enumtype && !type->byref)
638                 return mono_class_enum_basetype (type->data.generic_class->container_class);
639         return type;
640 }
641
642 /**
643  * mono_class_is_open_constructed_type:
644  * \param type a type
645  *
646  * \returns TRUE if type represents a generics open constructed type.
647  * IOW, not all type parameters required for the instantiation have
648  * been provided or it's a generic type definition.
649  *
650  * An open constructed type means it's a non realizable type. Not to
651  * be mixed up with an abstract type - we can't cast or dispatch to
652  * an open type, for example.
653  */
654 gboolean
655 mono_class_is_open_constructed_type (MonoType *t)
656 {
657         switch (t->type) {
658         case MONO_TYPE_VAR:
659         case MONO_TYPE_MVAR:
660                 return TRUE;
661         case MONO_TYPE_SZARRAY:
662                 return mono_class_is_open_constructed_type (&t->data.klass->byval_arg);
663         case MONO_TYPE_ARRAY:
664                 return mono_class_is_open_constructed_type (&t->data.array->eklass->byval_arg);
665         case MONO_TYPE_PTR:
666                 return mono_class_is_open_constructed_type (t->data.type);
667         case MONO_TYPE_GENERICINST:
668                 return t->data.generic_class->context.class_inst->is_open;
669         case MONO_TYPE_CLASS:
670         case MONO_TYPE_VALUETYPE:
671                 return mono_class_is_gtd (t->data.klass);
672         default:
673                 return FALSE;
674         }
675 }
676
677 /*
678 This is a simple function to catch the most common bad instances of generic types.
679 Specially those that might lead to further failures in the runtime.
680 */
681 static gboolean
682 is_valid_generic_argument (MonoType *type)
683 {
684         switch (type->type) {
685         case MONO_TYPE_VOID:
686         //case MONO_TYPE_TYPEDBYREF:
687                 return FALSE;
688         default:
689                 return TRUE;
690         }
691 }
692
693 static MonoType*
694 inflate_generic_type (MonoImage *image, MonoType *type, MonoGenericContext *context, MonoError *error)
695 {
696         error_init (error);
697
698         switch (type->type) {
699         case MONO_TYPE_MVAR: {
700                 MonoType *nt;
701                 int num = mono_type_get_generic_param_num (type);
702                 MonoGenericInst *inst = context->method_inst;
703                 if (!inst)
704                         return NULL;
705                 if (num >= inst->type_argc) {
706                         MonoGenericParamInfo *info = mono_generic_param_info (type->data.generic_param);
707                         mono_error_set_bad_image (error, image, "MVAR %d (%s) cannot be expanded in this context with %d instantiations",
708                                 num, info ? info->name : "", inst->type_argc);
709                         return NULL;
710                 }
711
712                 if (!is_valid_generic_argument (inst->type_argv [num])) {
713                         MonoGenericParamInfo *info = mono_generic_param_info (type->data.generic_param);
714                         mono_error_set_bad_image (error, image, "MVAR %d (%s) cannot be expanded with type 0x%x",
715                                 num, info ? info->name : "", inst->type_argv [num]->type);
716                         return NULL;                    
717                 }
718                 /*
719                  * Note that the VAR/MVAR cases are different from the rest.  The other cases duplicate @type,
720                  * while the VAR/MVAR duplicates a type from the context.  So, we need to ensure that the
721                  * ->byref and ->attrs from @type are propagated to the returned type.
722                  */
723                 nt = mono_metadata_type_dup (image, inst->type_argv [num]);
724                 nt->byref = type->byref;
725                 nt->attrs = type->attrs;
726                 return nt;
727         }
728         case MONO_TYPE_VAR: {
729                 MonoType *nt;
730                 int num = mono_type_get_generic_param_num (type);
731                 MonoGenericInst *inst = context->class_inst;
732                 if (!inst)
733                         return NULL;
734                 if (num >= inst->type_argc) {
735                         MonoGenericParamInfo *info = mono_generic_param_info (type->data.generic_param);
736                         mono_error_set_bad_image (error, image, "VAR %d (%s) cannot be expanded in this context with %d instantiations",
737                                 num, info ? info->name : "", inst->type_argc);
738                         return NULL;
739                 }
740                 if (!is_valid_generic_argument (inst->type_argv [num])) {
741                         MonoGenericParamInfo *info = mono_generic_param_info (type->data.generic_param);
742                         mono_error_set_bad_image (error, image, "VAR %d (%s) cannot be expanded with type 0x%x",
743                                 num, info ? info->name : "", inst->type_argv [num]->type);
744                         return NULL;                    
745                 }
746                 nt = mono_metadata_type_dup (image, inst->type_argv [num]);
747                 nt->byref = type->byref;
748                 nt->attrs = type->attrs;
749                 return nt;
750         }
751         case MONO_TYPE_SZARRAY: {
752                 MonoClass *eclass = type->data.klass;
753                 MonoType *nt, *inflated = inflate_generic_type (NULL, &eclass->byval_arg, context, error);
754                 if (!inflated || !mono_error_ok (error))
755                         return NULL;
756                 nt = mono_metadata_type_dup (image, type);
757                 nt->data.klass = mono_class_from_mono_type (inflated);
758                 mono_metadata_free_type (inflated);
759                 return nt;
760         }
761         case MONO_TYPE_ARRAY: {
762                 MonoClass *eclass = type->data.array->eklass;
763                 MonoType *nt, *inflated = inflate_generic_type (NULL, &eclass->byval_arg, context, error);
764                 if (!inflated || !mono_error_ok (error))
765                         return NULL;
766                 nt = mono_metadata_type_dup (image, type);
767                 nt->data.array->eklass = mono_class_from_mono_type (inflated);
768                 mono_metadata_free_type (inflated);
769                 return nt;
770         }
771         case MONO_TYPE_GENERICINST: {
772                 MonoGenericClass *gclass = type->data.generic_class;
773                 MonoGenericInst *inst;
774                 MonoType *nt;
775                 if (!gclass->context.class_inst->is_open)
776                         return NULL;
777
778                 inst = mono_metadata_inflate_generic_inst (gclass->context.class_inst, context, error);
779                 return_val_if_nok (error, NULL);
780
781                 if (inst != gclass->context.class_inst)
782                         gclass = mono_metadata_lookup_generic_class (gclass->container_class, inst, gclass->is_dynamic);
783
784                 if (gclass == type->data.generic_class)
785                         return NULL;
786
787                 nt = mono_metadata_type_dup (image, type);
788                 nt->data.generic_class = gclass;
789                 return nt;
790         }
791         case MONO_TYPE_CLASS:
792         case MONO_TYPE_VALUETYPE: {
793                 MonoClass *klass = type->data.klass;
794                 MonoGenericContainer *container = mono_class_try_get_generic_container (klass);
795                 MonoGenericInst *inst;
796                 MonoGenericClass *gclass = NULL;
797                 MonoType *nt;
798
799                 if (!container)
800                         return NULL;
801
802                 /* We can't use context->class_inst directly, since it can have more elements */
803                 inst = mono_metadata_inflate_generic_inst (container->context.class_inst, context, error);
804                 return_val_if_nok (error, NULL);
805
806                 if (inst == container->context.class_inst)
807                         return NULL;
808
809                 gclass = mono_metadata_lookup_generic_class (klass, inst, image_is_dynamic (klass->image));
810
811                 nt = mono_metadata_type_dup (image, type);
812                 nt->type = MONO_TYPE_GENERICINST;
813                 nt->data.generic_class = gclass;
814                 return nt;
815         }
816         default:
817                 return NULL;
818         }
819         return NULL;
820 }
821
822 MonoGenericContext *
823 mono_generic_class_get_context (MonoGenericClass *gclass)
824 {
825         return &gclass->context;
826 }
827
828 MonoGenericContext *
829 mono_class_get_context (MonoClass *klass)
830 {
831         MonoGenericClass *gklass = mono_class_try_get_generic_class (klass);
832         return gklass ? mono_generic_class_get_context (gklass) : NULL;
833 }
834
835 /*
836  * mono_class_inflate_generic_type_with_mempool:
837  * @mempool: a mempool
838  * @type: a type
839  * @context: a generics context
840  * @error: error context
841  *
842  * The same as mono_class_inflate_generic_type, but allocates the MonoType
843  * from mempool if it is non-NULL.  If it is NULL, the MonoType is
844  * allocated on the heap and is owned by the caller.
845  * The returned type can potentially be the same as TYPE, so it should not be
846  * modified by the caller, and it should be freed using mono_metadata_free_type ().
847  */
848 MonoType*
849 mono_class_inflate_generic_type_with_mempool (MonoImage *image, MonoType *type, MonoGenericContext *context, MonoError *error)
850 {
851         MonoType *inflated = NULL;
852         error_init (error);
853
854         if (context)
855                 inflated = inflate_generic_type (image, type, context, error);
856         return_val_if_nok (error, NULL);
857
858         if (!inflated) {
859                 MonoType *shared = mono_metadata_get_shared_type (type);
860
861                 if (shared) {
862                         return shared;
863                 } else {
864                         return mono_metadata_type_dup (image, type);
865                 }
866         }
867
868         UnlockedIncrement (&mono_stats.inflated_type_count);
869         return inflated;
870 }
871
872 /**
873  * mono_class_inflate_generic_type:
874  * \param type a type
875  * \param context a generics context
876  * \deprecated Please use \c mono_class_inflate_generic_type_checked instead
877  *
878  * If \p type is a generic type and \p context is not NULL, instantiate it using the 
879  * generics context \p context.
880  *
881  * \returns The instantiated type or a copy of \p type. The returned \c MonoType is allocated
882  * on the heap and is owned by the caller. Returns NULL on error.
883  */
884 MonoType*
885 mono_class_inflate_generic_type (MonoType *type, MonoGenericContext *context)
886 {
887         MonoError error;
888         MonoType *result;
889         result = mono_class_inflate_generic_type_checked (type, context, &error);
890         mono_error_cleanup (&error);
891         return result;
892 }
893
894 /*
895  * mono_class_inflate_generic_type:
896  * @type: a type
897  * @context: a generics context
898  * @error: error context to use
899  *
900  * If @type is a generic type and @context is not NULL, instantiate it using the 
901  * generics context @context.
902  *
903  * Returns: The instantiated type or a copy of @type. The returned MonoType is allocated
904  * on the heap and is owned by the caller.
905  */
906 MonoType*
907 mono_class_inflate_generic_type_checked (MonoType *type, MonoGenericContext *context, MonoError *error)
908 {
909         return mono_class_inflate_generic_type_with_mempool (NULL, type, context, error);
910 }
911
912 /*
913  * mono_class_inflate_generic_type_no_copy:
914  *
915  *   Same as inflate_generic_type_with_mempool, but return TYPE if no inflation
916  * was done.
917  */
918 static MonoType*
919 mono_class_inflate_generic_type_no_copy (MonoImage *image, MonoType *type, MonoGenericContext *context, MonoError *error)
920 {
921         MonoType *inflated = NULL; 
922
923         error_init (error);
924         if (context) {
925                 inflated = inflate_generic_type (image, type, context, error);
926                 return_val_if_nok (error, NULL);
927         }
928
929         if (!inflated)
930                 return type;
931
932         UnlockedIncrement (&mono_stats.inflated_type_count);
933         return inflated;
934 }
935
936 /*
937  * mono_class_inflate_generic_class:
938  *
939  *   Inflate the class @gklass with @context. Set @error on failure.
940  */
941 MonoClass*
942 mono_class_inflate_generic_class_checked (MonoClass *gklass, MonoGenericContext *context, MonoError *error)
943 {
944         MonoClass *res;
945         MonoType *inflated;
946
947         inflated = mono_class_inflate_generic_type_checked (&gklass->byval_arg, context, error);
948         return_val_if_nok (error, NULL);
949
950         res = mono_class_from_mono_type (inflated);
951         mono_metadata_free_type (inflated);
952
953         return res;
954 }
955
956 static MonoGenericContext
957 inflate_generic_context (MonoGenericContext *context, MonoGenericContext *inflate_with, MonoError *error)
958 {
959         MonoGenericInst *class_inst = NULL;
960         MonoGenericInst *method_inst = NULL;
961         MonoGenericContext res = { NULL, NULL };
962
963         error_init (error);
964
965         if (context->class_inst) {
966                 class_inst = mono_metadata_inflate_generic_inst (context->class_inst, inflate_with, error);
967                 if (!mono_error_ok (error))
968                         goto fail;
969         }
970
971         if (context->method_inst) {
972                 method_inst = mono_metadata_inflate_generic_inst (context->method_inst, inflate_with, error);
973                 if (!mono_error_ok (error))
974                         goto fail;
975         }
976
977         res.class_inst = class_inst;
978         res.method_inst = method_inst;
979 fail:
980         return res;
981 }
982
983 /**
984  * mono_class_inflate_generic_method:
985  * \param method a generic method
986  * \param context a generics context
987  *
988  * Instantiate the generic method \p method using the generics context \p context.
989  *
990  * \returns The new instantiated method
991  */
992 MonoMethod *
993 mono_class_inflate_generic_method (MonoMethod *method, MonoGenericContext *context)
994 {
995         return mono_class_inflate_generic_method_full (method, NULL, context);
996 }
997
998 MonoMethod *
999 mono_class_inflate_generic_method_checked (MonoMethod *method, MonoGenericContext *context, MonoError *error)
1000 {
1001         return mono_class_inflate_generic_method_full_checked (method, NULL, context, error);
1002 }
1003
1004 /**
1005  * mono_class_inflate_generic_method_full:
1006  *
1007  * Instantiate method \p method with the generic context \p context.
1008  * BEWARE: All non-trivial fields are invalid, including klass, signature, and header.
1009  *         Use mono_method_signature() and mono_method_get_header() to get the correct values.
1010  */
1011 MonoMethod*
1012 mono_class_inflate_generic_method_full (MonoMethod *method, MonoClass *klass_hint, MonoGenericContext *context)
1013 {
1014         MonoError error;
1015         MonoMethod *res = mono_class_inflate_generic_method_full_checked (method, klass_hint, context, &error);
1016         if (!mono_error_ok (&error))
1017                 /*FIXME do proper error handling - on this case, kill this function. */
1018                 g_error ("Could not inflate generic method due to %s", mono_error_get_message (&error)); 
1019
1020         return res;
1021 }
1022
1023 /**
1024  * mono_class_inflate_generic_method_full_checked:
1025  * Same as mono_class_inflate_generic_method_full but return failure using \p error.
1026  */
1027 MonoMethod*
1028 mono_class_inflate_generic_method_full_checked (MonoMethod *method, MonoClass *klass_hint, MonoGenericContext *context, MonoError *error)
1029 {
1030         MonoMethod *result;
1031         MonoMethodInflated *iresult, *cached;
1032         MonoMethodSignature *sig;
1033         MonoGenericContext tmp_context;
1034
1035         error_init (error);
1036
1037         /* The `method' has already been instantiated before => we need to peel out the instantiation and create a new context */
1038         while (method->is_inflated) {
1039                 MonoGenericContext *method_context = mono_method_get_context (method);
1040                 MonoMethodInflated *imethod = (MonoMethodInflated *) method;
1041
1042                 tmp_context = inflate_generic_context (method_context, context, error);
1043                 return_val_if_nok (error, NULL);
1044
1045                 context = &tmp_context;
1046
1047                 if (mono_metadata_generic_context_equal (method_context, context))
1048                         return method;
1049
1050                 method = imethod->declaring;
1051         }
1052
1053         /*
1054          * A method only needs to be inflated if the context has argument for which it is
1055          * parametric. Eg:
1056          * 
1057          * class Foo<T> { void Bar(); } - doesn't need to be inflated if only mvars' are supplied
1058          * class Foo { void Bar<T> (); } - doesn't need to be if only vars' are supplied
1059          * 
1060          */
1061         if (!((method->is_generic && context->method_inst) || 
1062                 (mono_class_is_gtd (method->klass) && context->class_inst)))
1063                 return method;
1064
1065         iresult = g_new0 (MonoMethodInflated, 1);
1066         iresult->context = *context;
1067         iresult->declaring = method;
1068
1069         if (!context->method_inst && method->is_generic)
1070                 iresult->context.method_inst = mono_method_get_generic_container (method)->context.method_inst;
1071
1072         if (!context->class_inst) {
1073                 g_assert (!mono_class_is_ginst (iresult->declaring->klass));
1074                 if (mono_class_is_gtd (iresult->declaring->klass))
1075                         iresult->context.class_inst = mono_class_get_generic_container (iresult->declaring->klass)->context.class_inst;
1076         }
1077         /* This can happen with some callers like mono_object_get_virtual_method () */
1078         if (!mono_class_is_gtd (iresult->declaring->klass) && !mono_class_is_ginst (iresult->declaring->klass))
1079                 iresult->context.class_inst = NULL;
1080
1081         MonoImageSet *set = mono_metadata_get_image_set_for_method (iresult);
1082
1083         // check cache
1084         mono_image_set_lock (set);
1085         cached = (MonoMethodInflated *)g_hash_table_lookup (set->gmethod_cache, iresult);
1086         mono_image_set_unlock (set);
1087
1088         if (cached) {
1089                 g_free (iresult);
1090                 return (MonoMethod*)cached;
1091         }
1092
1093         UnlockedIncrement (&mono_stats.inflated_method_count);
1094
1095         UnlockedAdd (&inflated_methods_size,  sizeof (MonoMethodInflated));
1096
1097         sig = mono_method_signature (method);
1098         if (!sig) {
1099                 char *name = mono_type_get_full_name (method->klass);
1100                 mono_error_set_bad_image (error, method->klass->image, "Could not resolve signature of method %s:%s", name, method->name);
1101                 g_free (name);
1102                 goto fail;
1103         }
1104
1105         if (sig->pinvoke) {
1106                 memcpy (&iresult->method.pinvoke, method, sizeof (MonoMethodPInvoke));
1107         } else {
1108                 memcpy (&iresult->method.method, method, sizeof (MonoMethod));
1109         }
1110
1111         result = (MonoMethod *) iresult;
1112         result->is_inflated = TRUE;
1113         result->is_generic = FALSE;
1114         result->sre_method = FALSE;
1115         result->signature = NULL;
1116
1117         if (method->wrapper_type) {
1118                 MonoMethodWrapper *mw = (MonoMethodWrapper*)method;
1119                 MonoMethodWrapper *resw = (MonoMethodWrapper*)result;
1120                 int len = GPOINTER_TO_INT (((void**)mw->method_data) [0]);
1121
1122                 resw->method_data = (void **)g_malloc (sizeof (gpointer) * (len + 1));
1123                 memcpy (resw->method_data, mw->method_data, sizeof (gpointer) * (len + 1));
1124         }
1125
1126         if (iresult->context.method_inst) {
1127                 /* Set the generic_container of the result to the generic_container of method */
1128                 MonoGenericContainer *generic_container = mono_method_get_generic_container (method);
1129
1130                 if (generic_container && iresult->context.method_inst == generic_container->context.method_inst) {
1131                         result->is_generic = 1;
1132                         mono_method_set_generic_container (result, generic_container);
1133                 }
1134         }
1135
1136         if (klass_hint) {
1137                 MonoGenericClass *gklass_hint = mono_class_try_get_generic_class (klass_hint);
1138                 if (gklass_hint && (gklass_hint->container_class != method->klass || gklass_hint->context.class_inst != context->class_inst))
1139                         klass_hint = NULL;
1140         }
1141
1142         if (mono_class_is_gtd (method->klass))
1143                 result->klass = klass_hint;
1144
1145         if (!result->klass) {
1146                 MonoType *inflated = inflate_generic_type (NULL, &method->klass->byval_arg, context, error);
1147                 if (!mono_error_ok (error)) 
1148                         goto fail;
1149
1150                 result->klass = inflated ? mono_class_from_mono_type (inflated) : method->klass;
1151                 if (inflated)
1152                         mono_metadata_free_type (inflated);
1153         }
1154
1155         /*
1156          * FIXME: This should hold, but it doesn't:
1157          *
1158          * if (result->is_inflated && mono_method_get_context (result)->method_inst &&
1159          *              mono_method_get_context (result)->method_inst == mono_method_get_generic_container (((MonoMethodInflated*)result)->declaring)->context.method_inst) {
1160          *      g_assert (result->is_generic);
1161          * }
1162          *
1163          * Fixing this here causes other things to break, hence a very
1164          * ugly hack in mini-trampolines.c - see
1165          * is_generic_method_definition().
1166          */
1167
1168         // check cache
1169         mono_image_set_lock (set);
1170         cached = (MonoMethodInflated *)g_hash_table_lookup (set->gmethod_cache, iresult);
1171         if (!cached) {
1172                 g_hash_table_insert (set->gmethod_cache, iresult, iresult);
1173                 iresult->owner = set;
1174                 cached = iresult;
1175         }
1176         mono_image_set_unlock (set);
1177
1178         return (MonoMethod*)cached;
1179
1180 fail:
1181         g_free (iresult);
1182         return NULL;
1183 }
1184
1185 /**
1186  * mono_get_inflated_method:
1187  *
1188  * Obsolete.  We keep it around since it's mentioned in the public API.
1189  */
1190 MonoMethod*
1191 mono_get_inflated_method (MonoMethod *method)
1192 {
1193         return method;
1194 }
1195
1196 /*
1197  * mono_method_get_context_general:
1198  * @method: a method
1199  * @uninflated: handle uninflated methods?
1200  *
1201  * Returns the generic context of a method or NULL if it doesn't have
1202  * one.  For an inflated method that's the context stored in the
1203  * method.  Otherwise it's in the method's generic container or in the
1204  * generic container of the method's class.
1205  */
1206 MonoGenericContext*
1207 mono_method_get_context_general (MonoMethod *method, gboolean uninflated)
1208 {
1209         if (method->is_inflated) {
1210                 MonoMethodInflated *imethod = (MonoMethodInflated *) method;
1211                 return &imethod->context;
1212         }
1213         if (!uninflated)
1214                 return NULL;
1215         if (method->is_generic)
1216                 return &(mono_method_get_generic_container (method)->context);
1217         if (mono_class_is_gtd (method->klass))
1218                 return &mono_class_get_generic_container (method->klass)->context;
1219         return NULL;
1220 }
1221
1222 /*
1223  * mono_method_get_context:
1224  * @method: a method
1225  *
1226  * Returns the generic context for method if it's inflated, otherwise
1227  * NULL.
1228  */
1229 MonoGenericContext*
1230 mono_method_get_context (MonoMethod *method)
1231 {
1232         return mono_method_get_context_general (method, FALSE);
1233 }
1234
1235 /*
1236  * mono_method_get_generic_container:
1237  *
1238  *   Returns the generic container of METHOD, which should be a generic method definition.
1239  * Returns NULL if METHOD is not a generic method definition.
1240  * LOCKING: Acquires the loader lock.
1241  */
1242 MonoGenericContainer*
1243 mono_method_get_generic_container (MonoMethod *method)
1244 {
1245         MonoGenericContainer *container;
1246
1247         if (!method->is_generic)
1248                 return NULL;
1249
1250         container = (MonoGenericContainer *)mono_image_property_lookup (method->klass->image, method, MONO_METHOD_PROP_GENERIC_CONTAINER);
1251         g_assert (container);
1252
1253         return container;
1254 }
1255
1256 /*
1257  * mono_method_set_generic_container:
1258  *
1259  *   Sets the generic container of METHOD to CONTAINER.
1260  * LOCKING: Acquires the image lock.
1261  */
1262 void
1263 mono_method_set_generic_container (MonoMethod *method, MonoGenericContainer* container)
1264 {
1265         g_assert (method->is_generic);
1266
1267         mono_image_property_insert (method->klass->image, method, MONO_METHOD_PROP_GENERIC_CONTAINER, container);
1268 }
1269
1270 /** 
1271  * mono_class_find_enum_basetype:
1272  * \param class The enum class
1273  *
1274  *   Determine the basetype of an enum by iterating through its fields. We do this
1275  * in a separate function since it is cheaper than calling mono_class_setup_fields.
1276  */
1277 static MonoType*
1278 mono_class_find_enum_basetype (MonoClass *klass, MonoError *error)
1279 {
1280         MonoGenericContainer *container = NULL;
1281         MonoImage *m = klass->image;
1282         const int top = mono_class_get_field_count (klass);
1283         int i, first_field_idx;
1284
1285         g_assert (klass->enumtype);
1286
1287         error_init (error);
1288
1289         container = mono_class_try_get_generic_container (klass);
1290         if (mono_class_is_ginst (klass)) {
1291                 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
1292
1293                 container = mono_class_get_generic_container (gklass);
1294                 g_assert (container);
1295         }
1296
1297         /*
1298          * Fetch all the field information.
1299          */
1300         first_field_idx = mono_class_get_first_field_idx (klass);
1301         for (i = 0; i < top; i++){
1302                 const char *sig;
1303                 guint32 cols [MONO_FIELD_SIZE];
1304                 int idx = first_field_idx + i;
1305                 MonoType *ftype;
1306
1307                 /* first_field_idx and idx points into the fieldptr table */
1308                 mono_metadata_decode_table_row (m, MONO_TABLE_FIELD, idx, cols, MONO_FIELD_SIZE);
1309
1310                 if (cols [MONO_FIELD_FLAGS] & FIELD_ATTRIBUTE_STATIC) //no need to decode static fields
1311                         continue;
1312
1313                 if (!mono_verifier_verify_field_signature (klass->image, cols [MONO_FIELD_SIGNATURE], NULL)) {
1314                         mono_error_set_bad_image (error, klass->image, "Invalid field signature %x", cols [MONO_FIELD_SIGNATURE]);
1315                         goto fail;
1316                 }
1317
1318                 sig = mono_metadata_blob_heap (m, cols [MONO_FIELD_SIGNATURE]);
1319                 mono_metadata_decode_value (sig, &sig);
1320                 /* FIELD signature == 0x06 */
1321                 if (*sig != 0x06) {
1322                         mono_error_set_bad_image (error, klass->image, "Invalid field signature %x, expected 0x6 but got %x", cols [MONO_FIELD_SIGNATURE], *sig);
1323                         goto fail;
1324                 }
1325
1326                 ftype = mono_metadata_parse_type_checked (m, container, cols [MONO_FIELD_FLAGS], FALSE, sig + 1, &sig, error);
1327                 if (!ftype)
1328                         goto fail;
1329
1330                 if (mono_class_is_ginst (klass)) {
1331                         //FIXME do we leak here?
1332                         ftype = mono_class_inflate_generic_type_checked (ftype, mono_class_get_context (klass), error);
1333                         if (!mono_error_ok (error))
1334                                 goto fail;
1335                         ftype->attrs = cols [MONO_FIELD_FLAGS];
1336                 }
1337
1338                 return ftype;
1339         }
1340         mono_error_set_type_load_class (error, klass, "Could not find base type");
1341
1342 fail:
1343         return NULL;
1344 }
1345
1346 /*
1347  * Checks for MonoClass::has_failure without resolving all MonoType's into MonoClass'es
1348  */
1349 static gboolean
1350 mono_type_has_exceptions (MonoType *type)
1351 {
1352         switch (type->type) {
1353         case MONO_TYPE_CLASS:
1354         case MONO_TYPE_VALUETYPE:
1355         case MONO_TYPE_SZARRAY:
1356                 return mono_class_has_failure (type->data.klass);
1357         case MONO_TYPE_ARRAY:
1358                 return mono_class_has_failure (type->data.array->eklass);
1359         case MONO_TYPE_GENERICINST:
1360                 return mono_class_has_failure (mono_generic_class_get_class (type->data.generic_class));
1361         default:
1362                 return FALSE;
1363         }
1364 }
1365
1366 void
1367 mono_error_set_for_class_failure (MonoError *oerror, const MonoClass *klass)
1368 {
1369         g_assert (mono_class_has_failure (klass));
1370         MonoErrorBoxed *box = mono_class_get_exception_data ((MonoClass*)klass);
1371         mono_error_set_from_boxed (oerror, box);
1372 }
1373
1374 /*
1375  * mono_class_alloc:
1376  *
1377  *   Allocate memory for some data belonging to CLASS, either from its image's mempool,
1378  * or from the heap.
1379  */
1380 gpointer
1381 mono_class_alloc (MonoClass *klass, int size)
1382 {
1383         MonoGenericClass *gklass = mono_class_try_get_generic_class (klass);
1384         if (gklass)
1385                 return mono_image_set_alloc (gklass->owner, size);
1386         else
1387                 return mono_image_alloc (klass->image, size);
1388 }
1389
1390 gpointer
1391 mono_class_alloc0 (MonoClass *klass, int size)
1392 {
1393         gpointer res;
1394
1395         res = mono_class_alloc (klass, size);
1396         memset (res, 0, size);
1397         return res;
1398 }
1399
1400 #define mono_class_new0(klass,struct_type, n_structs)           \
1401     ((struct_type *) mono_class_alloc0 ((klass), ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
1402
1403 /**
1404  * mono_class_setup_basic_field_info:
1405  * \param class The class to initialize
1406  *
1407  * Initializes the following fields in MonoClass:
1408  * * klass->fields (only field->parent and field->name)
1409  * * klass->field.count
1410  * * klass->first_field_idx
1411  * LOCKING: Acquires the loader lock
1412  */
1413 static void
1414 mono_class_setup_basic_field_info (MonoClass *klass)
1415 {
1416         MonoGenericClass *gklass;
1417         MonoClassField *field;
1418         MonoClassField *fields;
1419         MonoClass *gtd;
1420         MonoImage *image;
1421         int i, top;
1422
1423         if (klass->fields)
1424                 return;
1425
1426         gklass = mono_class_try_get_generic_class (klass);
1427         gtd = gklass ? mono_class_get_generic_type_definition (klass) : NULL;
1428         image = klass->image;
1429
1430
1431         if (gklass && image_is_dynamic (gklass->container_class->image) && !gklass->container_class->wastypebuilder) {
1432                 /*
1433                  * This happens when a generic instance of an unfinished generic typebuilder
1434                  * is used as an element type for creating an array type. We can't initialize
1435                  * the fields of this class using the fields of gklass, since gklass is not
1436                  * finished yet, fields could be added to it later.
1437                  */
1438                 return;
1439         }
1440
1441         if (gtd) {
1442                 mono_class_setup_basic_field_info (gtd);
1443
1444                 mono_loader_lock ();
1445                 mono_class_set_field_count (klass, mono_class_get_field_count (gtd));
1446                 mono_loader_unlock ();
1447         }
1448
1449         top = mono_class_get_field_count (klass);
1450
1451         fields = (MonoClassField *)mono_class_alloc0 (klass, sizeof (MonoClassField) * top);
1452
1453         /*
1454          * Fetch all the field information.
1455          */
1456         int first_field_idx = mono_class_has_static_metadata (klass) ? mono_class_get_first_field_idx (klass) : 0;
1457         for (i = 0; i < top; i++) {
1458                 field = &fields [i];
1459                 field->parent = klass;
1460
1461                 if (gtd) {
1462                         field->name = mono_field_get_name (&gtd->fields [i]);
1463                 } else {
1464                         int idx = first_field_idx + i;
1465                         /* first_field_idx and idx points into the fieldptr table */
1466                         guint32 name_idx = mono_metadata_decode_table_row_col (image, MONO_TABLE_FIELD, idx, MONO_FIELD_NAME);
1467                         /* The name is needed for fieldrefs */
1468                         field->name = mono_metadata_string_heap (image, name_idx);
1469                 }
1470         }
1471
1472         mono_memory_barrier ();
1473
1474         mono_loader_lock ();
1475         if (!klass->fields)
1476                 klass->fields = fields;
1477         mono_loader_unlock ();
1478 }
1479
1480 /**
1481  * mono_class_set_failure_causedby_class:
1482  * \param klass the class that is failing
1483  * \param caused_by the class that caused the failure
1484  * \param msg Why \p klass is failing.
1485  * 
1486  * If \p caused_by has a failure, sets a TypeLoadException failure on
1487  * \p klass with message "\p msg, due to: {\p caused_by message}".
1488  *
1489  * \returns TRUE if a failiure was set, or FALSE if \p caused_by doesn't have a failure.
1490  */
1491 static gboolean
1492 mono_class_set_type_load_failure_causedby_class (MonoClass *klass, const MonoClass *caused_by, const gchar* msg)
1493 {
1494         if (mono_class_has_failure (caused_by)) {
1495                 MonoError cause_error;
1496                 error_init (&cause_error);
1497                 mono_error_set_for_class_failure (&cause_error, caused_by);
1498                 mono_class_set_type_load_failure (klass, "%s, due to: %s", msg, mono_error_get_message (&cause_error));
1499                 mono_error_cleanup (&cause_error);
1500                 return TRUE;
1501         } else {
1502                 return FALSE;
1503         }
1504 }
1505
1506
1507 /** 
1508  * mono_class_setup_fields:
1509  * \p klass The class to initialize
1510  *
1511  * Initializes klass->fields, computes class layout and sizes.
1512  * typebuilder_setup_fields () is the corresponding function for dynamic classes.
1513  * Sets the following fields in \p klass:
1514  *  - all the fields initialized by mono_class_init_sizes ()
1515  *  - element_class/cast_class (for enums)
1516  *  - sizes:element_size (for arrays)
1517  *  - field->type/offset for all fields
1518  *  - fields_inited
1519  *
1520  * LOCKING: Acquires the loader lock.
1521  */
1522 void
1523 mono_class_setup_fields (MonoClass *klass)
1524 {
1525         MonoError error;
1526         MonoImage *m = klass->image;
1527         int top;
1528         guint32 layout = mono_class_get_flags (klass) & TYPE_ATTRIBUTE_LAYOUT_MASK;
1529         int i;
1530         guint32 real_size = 0;
1531         guint32 packing_size = 0;
1532         int instance_size;
1533         gboolean explicit_size;
1534         MonoClassField *field;
1535         MonoGenericClass *gklass = mono_class_try_get_generic_class (klass);
1536         MonoClass *gtd = gklass ? mono_class_get_generic_type_definition (klass) : NULL;
1537
1538         if (klass->fields_inited)
1539                 return;
1540
1541         if (gklass && image_is_dynamic (gklass->container_class->image) && !gklass->container_class->wastypebuilder) {
1542                 /*
1543                  * This happens when a generic instance of an unfinished generic typebuilder
1544                  * is used as an element type for creating an array type. We can't initialize
1545                  * the fields of this class using the fields of gklass, since gklass is not
1546                  * finished yet, fields could be added to it later.
1547                  */
1548                 return;
1549         }
1550
1551         mono_class_setup_basic_field_info (klass);
1552         top = mono_class_get_field_count (klass);
1553
1554         if (gtd) {
1555                 mono_class_setup_fields (gtd);
1556                 if (mono_class_set_type_load_failure_causedby_class (klass, gtd, "Generic type definition failed"))
1557                         return;
1558         }
1559
1560         instance_size = 0;
1561         if (klass->parent) {
1562                 /* For generic instances, klass->parent might not have been initialized */
1563                 mono_class_init (klass->parent);
1564                 mono_class_setup_fields (klass->parent);
1565                 if (mono_class_set_type_load_failure_causedby_class (klass, klass->parent, "Could not set up parent class"))
1566                         return;
1567                 instance_size = klass->parent->instance_size;
1568         } else {
1569                 instance_size = sizeof (MonoObject);
1570         }
1571
1572         /* Get the real size */
1573         explicit_size = mono_metadata_packing_from_typedef (klass->image, klass->type_token, &packing_size, &real_size);
1574         if (explicit_size)
1575                 instance_size += real_size;
1576
1577         /*
1578          * This function can recursively call itself.
1579          * Prevent infinite recursion by using a list in TLS.
1580          */
1581         GSList *init_list = (GSList *)mono_native_tls_get_value (setup_fields_tls_id);
1582         if (g_slist_find (init_list, klass))
1583                 return;
1584         init_list = g_slist_prepend (init_list, klass);
1585         mono_native_tls_set_value (setup_fields_tls_id, init_list);
1586
1587         /*
1588          * Fetch all the field information.
1589          */
1590         int first_field_idx = mono_class_has_static_metadata (klass) ? mono_class_get_first_field_idx (klass) : 0;
1591         for (i = 0; i < top; i++) {
1592                 int idx = first_field_idx + i;
1593                 field = &klass->fields [i];
1594
1595                 if (!field->type) {
1596                         mono_field_resolve_type (field, &error);
1597                         if (!mono_error_ok (&error)) {
1598                                 /*mono_field_resolve_type already failed class*/
1599                                 mono_error_cleanup (&error);
1600                                 break;
1601                         }
1602                         if (!field->type)
1603                                 g_error ("could not resolve %s:%s\n", mono_type_get_full_name(klass), field->name);
1604                         g_assert (field->type);
1605                 }
1606
1607                 if (!mono_type_get_underlying_type (field->type)) {
1608                         mono_class_set_type_load_failure (klass, "Field '%s' is an enum type with a bad underlying type", field->name);
1609                         break;
1610                 }
1611
1612                 if (mono_field_is_deleted (field))
1613                         continue;
1614                 if (layout == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) {
1615                         guint32 uoffset;
1616                         mono_metadata_field_info (m, idx, &uoffset, NULL, NULL);
1617                         int offset = uoffset;
1618
1619                         if (offset == (guint32)-1 && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
1620                                 mono_class_set_type_load_failure (klass, "Missing field layout info for %s", field->name);
1621                                 break;
1622                         }
1623                         if (offset < -1) { /*-1 is used to encode special static fields */
1624                                 mono_class_set_type_load_failure (klass, "Field '%s' has a negative offset %d", field->name, offset);
1625                                 break;
1626                         }
1627                         if (mono_class_is_gtd (klass)) {
1628                                 mono_class_set_type_load_failure (klass, "Generic class cannot have explicit layout.");
1629                                 break;
1630                         }
1631                 }
1632                 if (mono_type_has_exceptions (field->type)) {
1633                         char *class_name = mono_type_get_full_name (klass);
1634                         char *type_name = mono_type_full_name (field->type);
1635
1636                         mono_class_set_type_load_failure (klass, "Invalid type %s for instance field %s:%s", type_name, class_name, field->name);
1637                         g_free (class_name);
1638                         g_free (type_name);
1639                         break;
1640                 }
1641                 /* The def_value of fields is compute lazily during vtable creation */
1642         }
1643
1644         if (!mono_class_has_failure (klass)) {
1645                 mono_loader_lock ();
1646                 mono_class_layout_fields (klass, instance_size, packing_size, FALSE);
1647                 mono_loader_unlock ();
1648         }
1649
1650         init_list = g_slist_remove (init_list, klass);
1651         mono_native_tls_set_value (setup_fields_tls_id, init_list);
1652 }
1653
1654 static void
1655 init_sizes_with_info (MonoClass *klass, MonoCachedClassInfo *cached_info)
1656 {
1657         if (cached_info) {
1658                 mono_loader_lock ();
1659                 klass->instance_size = cached_info->instance_size;
1660                 klass->sizes.class_size = cached_info->class_size;
1661                 klass->packing_size = cached_info->packing_size;
1662                 klass->min_align = cached_info->min_align;
1663                 klass->blittable = cached_info->blittable;
1664                 klass->has_references = cached_info->has_references;
1665                 klass->has_static_refs = cached_info->has_static_refs;
1666                 klass->no_special_static_fields = cached_info->no_special_static_fields;
1667                 mono_loader_unlock ();
1668         }
1669         else {
1670                 if (!klass->size_inited)
1671                         mono_class_setup_fields (klass);
1672         }
1673 }
1674 /*
1675
1676  * mono_class_init_sizes:
1677  *
1678  *   Initializes the size related fields of @klass without loading all field data if possible.
1679  * Sets the following fields in @klass:
1680  * - instance_size
1681  * - sizes.class_size
1682  * - packing_size
1683  * - min_align
1684  * - blittable
1685  * - has_references
1686  * - has_static_refs
1687  * - size_inited
1688  * Can fail the class.
1689  *
1690  * LOCKING: Acquires the loader lock.
1691  */
1692 static void
1693 mono_class_init_sizes (MonoClass *klass)
1694 {
1695         MonoCachedClassInfo cached_info;
1696         gboolean has_cached_info;
1697
1698         if (klass->size_inited)
1699                 return;
1700
1701         has_cached_info = mono_class_get_cached_class_info (klass, &cached_info);
1702
1703         init_sizes_with_info (klass, has_cached_info ? &cached_info : NULL);
1704 }
1705
1706 /*
1707  * mono_type_get_basic_type_from_generic:
1708  * @type: a type
1709  *
1710  * Returns a closed type corresponding to the possibly open type
1711  * passed to it.
1712  */
1713 MonoType*
1714 mono_type_get_basic_type_from_generic (MonoType *type)
1715 {
1716         /* When we do generic sharing we let type variables stand for reference/primitive types. */
1717         if (!type->byref && (type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR) &&
1718                 (!type->data.generic_param->gshared_constraint || type->data.generic_param->gshared_constraint->type == MONO_TYPE_OBJECT))
1719                 return &mono_defaults.object_class->byval_arg;
1720         return type;
1721 }
1722
1723 static gboolean
1724 class_has_references (MonoClass *klass)
1725 {
1726         mono_class_init_sizes (klass);
1727
1728         /*
1729          * has_references is not set if this is called recursively, but this is not a problem since this is only used
1730          * during field layout, and instance fields are initialized before static fields, and instance fields can't
1731          * embed themselves.
1732          */
1733         return klass->has_references;
1734 }
1735
1736 static gboolean
1737 type_has_references (MonoClass *klass, MonoType *ftype)
1738 {
1739         if (MONO_TYPE_IS_REFERENCE (ftype) || IS_GC_REFERENCE (klass, ftype) || ((MONO_TYPE_ISSTRUCT (ftype) && class_has_references (mono_class_from_mono_type (ftype)))))
1740                 return TRUE;
1741         if (!ftype->byref && (ftype->type == MONO_TYPE_VAR || ftype->type == MONO_TYPE_MVAR)) {
1742                 MonoGenericParam *gparam = ftype->data.generic_param;
1743
1744                 if (gparam->gshared_constraint)
1745                         return class_has_references (mono_class_from_mono_type (gparam->gshared_constraint));
1746         }
1747         return FALSE;
1748 }
1749
1750 /*
1751  * mono_class_layout_fields:
1752  * @class: a class
1753  * @base_instance_size: base instance size
1754  * @packing_size:
1755  *
1756  * This contains the common code for computing the layout of classes and sizes.
1757  * This should only be called from mono_class_setup_fields () and
1758  * typebuilder_setup_fields ().
1759  *
1760  * LOCKING: Acquires the loader lock
1761  */
1762 void
1763 mono_class_layout_fields (MonoClass *klass, int base_instance_size, int packing_size, gboolean sre)
1764 {
1765         int i;
1766         const int top = mono_class_get_field_count (klass);
1767         guint32 layout = mono_class_get_flags (klass) & TYPE_ATTRIBUTE_LAYOUT_MASK;
1768         guint32 pass, passes, real_size;
1769         gboolean gc_aware_layout = FALSE;
1770         gboolean has_static_fields = FALSE;
1771         gboolean has_references = FALSE;
1772         gboolean has_static_refs = FALSE;
1773         MonoClassField *field;
1774         gboolean blittable;
1775         int instance_size = base_instance_size;
1776         int element_size = -1;
1777         int class_size, min_align;
1778         int *field_offsets;
1779         gboolean *fields_has_references;
1780
1781         /*
1782          * We want to avoid doing complicated work inside locks, so we compute all the required
1783          * information and write it to @klass inside a lock.
1784          */
1785         if (klass->fields_inited)
1786                 return;
1787
1788         if ((packing_size & 0xffffff00) != 0) {
1789                 mono_class_set_type_load_failure (klass, "Could not load struct '%s' with packing size %d >= 256", klass->name, packing_size);
1790                 return;
1791         }
1792
1793         if (klass->parent) {
1794                 min_align = klass->parent->min_align;
1795                 /* we use | since it may have been set already */
1796                 has_references = klass->has_references | klass->parent->has_references;
1797         } else {
1798                 min_align = 1;
1799         }
1800         /* We can't really enable 16 bytes alignment until the GC supports it.
1801         The whole layout/instance size code must be reviewed because we do alignment calculation in terms of the
1802         boxed instance, which leads to unexplainable holes at the beginning of an object embedding a simd type.
1803         Bug #506144 is an example of this issue.
1804
1805          if (klass->simd_type)
1806                 min_align = 16;
1807          */
1808
1809         /*
1810          * When we do generic sharing we need to have layout
1811          * information for open generic classes (either with a generic
1812          * context containing type variables or with a generic
1813          * container), so we don't return in that case anymore.
1814          */
1815
1816         if (klass->enumtype) {
1817                 for (i = 0; i < top; i++) {
1818                         field = &klass->fields [i];
1819                         if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
1820                                 klass->cast_class = klass->element_class = mono_class_from_mono_type (field->type);
1821                                 break;
1822                         }
1823                 }
1824
1825                 if (!mono_class_enum_basetype (klass)) {
1826                         mono_class_set_type_load_failure (klass, "The enumeration's base type is invalid.");
1827                         return;
1828                 }
1829         }
1830
1831         /*
1832          * Enable GC aware auto layout: in this mode, reference
1833          * fields are grouped together inside objects, increasing collector 
1834          * performance.
1835          * Requires that all classes whose layout is known to native code be annotated
1836          * with [StructLayout (LayoutKind.Sequential)]
1837          * Value types have gc_aware_layout disabled by default, as per
1838          * what the default is for other runtimes.
1839          */
1840          /* corlib is missing [StructLayout] directives in many places */
1841         if (layout == TYPE_ATTRIBUTE_AUTO_LAYOUT) {
1842                 if (!klass->valuetype)
1843                         gc_aware_layout = TRUE;
1844         }
1845
1846         /* Compute klass->blittable */
1847         blittable = TRUE;
1848         if (klass->parent)
1849                 blittable = klass->parent->blittable;
1850         if (layout == TYPE_ATTRIBUTE_AUTO_LAYOUT && !(mono_is_corlib_image (klass->image) && !strcmp (klass->name_space, "System") && !strcmp (klass->name, "ValueType")) && top)
1851                 blittable = FALSE;
1852         for (i = 0; i < top; i++) {
1853                 field = &klass->fields [i];
1854
1855                 if (mono_field_is_deleted (field))
1856                         continue;
1857                 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1858                         continue;
1859                 if (blittable) {
1860                         if (field->type->byref || MONO_TYPE_IS_REFERENCE (field->type)) {
1861                                 blittable = FALSE;
1862                         } else {
1863                                 MonoClass *field_class = mono_class_from_mono_type (field->type);
1864                                 if (field_class) {
1865                                         mono_class_setup_fields (field_class);
1866                                         if (mono_class_has_failure (field_class)) {
1867                                                 MonoError field_error;
1868                                                 error_init (&field_error);
1869                                                 mono_error_set_for_class_failure (&field_error, field_class);
1870                                                 mono_class_set_type_load_failure (klass, "Could not set up field '%s' due to: %s", field->name, mono_error_get_message (&field_error));
1871                                                 mono_error_cleanup (&field_error);
1872                                                 break;
1873                                         }
1874                                 }
1875                                 if (!field_class || !field_class->blittable)
1876                                         blittable = FALSE;
1877                         }
1878                 }
1879                 if (klass->enumtype)
1880                         blittable = klass->element_class->blittable;
1881         }
1882         if (mono_class_has_failure (klass))
1883                 return;
1884         if (klass == mono_defaults.string_class)
1885                 blittable = FALSE;
1886
1887         /* Compute klass->has_references */
1888         /* 
1889          * Process non-static fields first, since static fields might recursively
1890          * refer to the class itself.
1891          */
1892         for (i = 0; i < top; i++) {
1893                 MonoType *ftype;
1894
1895                 field = &klass->fields [i];
1896
1897                 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
1898                         ftype = mono_type_get_underlying_type (field->type);
1899                         ftype = mono_type_get_basic_type_from_generic (ftype);
1900                         if (type_has_references (klass, ftype))
1901                                 has_references = TRUE;
1902                 }
1903         }
1904
1905         /*
1906          * Compute field layout and total size (not considering static fields)
1907          */
1908         field_offsets = g_new0 (int, top);
1909         fields_has_references = g_new0 (gboolean, top);
1910         int first_field_idx = mono_class_has_static_metadata (klass) ? mono_class_get_first_field_idx (klass) : 0;
1911         switch (layout) {
1912         case TYPE_ATTRIBUTE_AUTO_LAYOUT:
1913         case TYPE_ATTRIBUTE_SEQUENTIAL_LAYOUT:
1914                 if (gc_aware_layout)
1915                         passes = 2;
1916                 else
1917                         passes = 1;
1918
1919                 if (layout != TYPE_ATTRIBUTE_AUTO_LAYOUT)
1920                         passes = 1;
1921
1922                 if (klass->parent) {
1923                         mono_class_setup_fields (klass->parent);
1924                         if (mono_class_set_type_load_failure_causedby_class (klass, klass->parent, "Cannot initialize parent class"))
1925                                 return;
1926                         real_size = klass->parent->instance_size;
1927                 } else {
1928                         real_size = sizeof (MonoObject);
1929                 }
1930
1931                 for (pass = 0; pass < passes; ++pass) {
1932                         for (i = 0; i < top; i++){
1933                                 gint32 align;
1934                                 guint32 size;
1935                                 MonoType *ftype;
1936
1937                                 field = &klass->fields [i];
1938
1939                                 if (mono_field_is_deleted (field))
1940                                         continue;
1941                                 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1942                                         continue;
1943
1944                                 ftype = mono_type_get_underlying_type (field->type);
1945                                 ftype = mono_type_get_basic_type_from_generic (ftype);
1946                                 if (gc_aware_layout) {
1947                                         fields_has_references [i] = type_has_references (klass, ftype);
1948                                         if (fields_has_references [i]) {
1949                                                 if (pass == 1)
1950                                                         continue;
1951                                         } else {
1952                                                 if (pass == 0)
1953                                                         continue;
1954                                         }
1955                                 }
1956
1957                                 if ((top == 1) && (instance_size == sizeof (MonoObject)) &&
1958                                         (strcmp (mono_field_get_name (field), "$PRIVATE$") == 0)) {
1959                                         /* This field is a hack inserted by MCS to empty structures */
1960                                         continue;
1961                                 }
1962
1963                                 size = mono_type_size (field->type, &align);
1964                         
1965                                 /* FIXME (LAMESPEC): should we also change the min alignment according to pack? */
1966                                 align = packing_size ? MIN (packing_size, align): align;
1967                                 /* if the field has managed references, we need to force-align it
1968                                  * see bug #77788
1969                                  */
1970                                 if (type_has_references (klass, ftype))
1971                                         align = MAX (align, sizeof (gpointer));
1972
1973                                 min_align = MAX (align, min_align);
1974                                 field_offsets [i] = real_size;
1975                                 if (align) {
1976                                         field_offsets [i] += align - 1;
1977                                         field_offsets [i] &= ~(align - 1);
1978                                 }
1979                                 /*TypeBuilders produce all sort of weird things*/
1980                                 g_assert (image_is_dynamic (klass->image) || field_offsets [i] > 0);
1981                                 real_size = field_offsets [i] + size;
1982                         }
1983
1984                         /* Make SIMD types as big as a SIMD register since they can be stored into using simd stores */
1985                         if (klass->simd_type)
1986                                 real_size = MAX (real_size, sizeof (MonoObject) + 16);
1987                         instance_size = MAX (real_size, instance_size);
1988        
1989                         if (instance_size & (min_align - 1)) {
1990                                 instance_size += min_align - 1;
1991                                 instance_size &= ~(min_align - 1);
1992                         }
1993                 }
1994                 break;
1995         case TYPE_ATTRIBUTE_EXPLICIT_LAYOUT: {
1996                 guint8 *ref_bitmap;
1997
1998                 real_size = 0;
1999                 for (i = 0; i < top; i++) {
2000                         gint32 align;
2001                         guint32 size;
2002                         MonoType *ftype;
2003
2004                         field = &klass->fields [i];
2005
2006                         /*
2007                          * There must be info about all the fields in a type if it
2008                          * uses explicit layout.
2009                          */
2010                         if (mono_field_is_deleted (field))
2011                                 continue;
2012                         if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
2013                                 continue;
2014
2015                         size = mono_type_size (field->type, &align);
2016                         align = packing_size ? MIN (packing_size, align): align;
2017                         min_align = MAX (align, min_align);
2018
2019                         if (sre) {
2020                                 /* Already set by typebuilder_setup_fields () */
2021                                 field_offsets [i] = field->offset + sizeof (MonoObject);
2022                         } else {
2023                                 int idx = first_field_idx + i;
2024                                 guint32 offset;
2025                                 mono_metadata_field_info (klass->image, idx, &offset, NULL, NULL);
2026                                 field_offsets [i] = offset + sizeof (MonoObject);
2027                         }
2028                         ftype = mono_type_get_underlying_type (field->type);
2029                         ftype = mono_type_get_basic_type_from_generic (ftype);
2030                         if (type_has_references (klass, ftype)) {
2031                                 if (field_offsets [i] % sizeof (gpointer)) {
2032                                         mono_class_set_type_load_failure (klass, "Reference typed field '%s' has explicit offset that is not pointer-size aligned.", field->name);
2033                                 }
2034                         }
2035
2036                         /*
2037                          * Calc max size.
2038                          */
2039                         real_size = MAX (real_size, size + field_offsets [i]);
2040                 }
2041
2042                 if (klass->has_references) {
2043                         ref_bitmap = g_new0 (guint8, real_size / sizeof (gpointer));
2044
2045                         /* Check for overlapping reference and non-reference fields */
2046                         for (i = 0; i < top; i++) {
2047                                 MonoType *ftype;
2048
2049                                 field = &klass->fields [i];
2050
2051                                 if (mono_field_is_deleted (field))
2052                                         continue;
2053                                 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
2054                                         continue;
2055                                 ftype = mono_type_get_underlying_type (field->type);
2056                                 if (MONO_TYPE_IS_REFERENCE (ftype))
2057                                         ref_bitmap [field_offsets [i] / sizeof (gpointer)] = 1;
2058                         }
2059                         for (i = 0; i < top; i++) {
2060                                 field = &klass->fields [i];
2061
2062                                 if (mono_field_is_deleted (field))
2063                                         continue;
2064                                 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
2065                                         continue;
2066
2067                                 // FIXME: Too much code does this
2068 #if 0
2069                                 if (!MONO_TYPE_IS_REFERENCE (field->type) && ref_bitmap [field_offsets [i] / sizeof (gpointer)]) {
2070                                         mono_class_set_type_load_failure (klass, "Could not load type '%s' because it contains an object field at offset %d that is incorrectly aligned or overlapped by a non-object field.", klass->name, field_offsets [i]);
2071                                 }
2072 #endif
2073                         }
2074                         g_free (ref_bitmap);
2075                 }
2076
2077                 instance_size = MAX (real_size, instance_size);
2078                 if (instance_size & (min_align - 1)) {
2079                         instance_size += min_align - 1;
2080                         instance_size &= ~(min_align - 1);
2081                 }
2082                 break;
2083         }
2084         }
2085
2086         if (layout != TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) {
2087                 /*
2088                  * This leads to all kinds of problems with nested structs, so only
2089                  * enable it when a MONO_DEBUG property is set.
2090                  *
2091                  * For small structs, set min_align to at least the struct size to improve
2092                  * performance, and since the JIT memset/memcpy code assumes this and generates 
2093                  * unaligned accesses otherwise. See #78990 for a testcase.
2094                  */
2095                 if (mono_align_small_structs && top) {
2096                         if (instance_size <= sizeof (MonoObject) + sizeof (gpointer))
2097                                 min_align = MAX (min_align, instance_size - sizeof (MonoObject));
2098                 }
2099         }
2100
2101         if (klass->byval_arg.type == MONO_TYPE_VAR || klass->byval_arg.type == MONO_TYPE_MVAR)
2102                 instance_size = sizeof (MonoObject) + mono_type_stack_size_internal (&klass->byval_arg, NULL, TRUE);
2103         else if (klass->byval_arg.type == MONO_TYPE_PTR)
2104                 instance_size = sizeof (MonoObject) + sizeof (gpointer);
2105
2106         if (klass->byval_arg.type == MONO_TYPE_SZARRAY || klass->byval_arg.type == MONO_TYPE_ARRAY)
2107                 element_size = mono_class_array_element_size (klass->element_class);
2108
2109         /* Publish the data */
2110         mono_loader_lock ();
2111         if (klass->instance_size && !klass->image->dynamic) {
2112                 /* Might be already set using cached info */
2113                 if (klass->instance_size != instance_size) {
2114                         /* Emit info to help debugging */
2115                         g_print ("%s\n", mono_class_full_name (klass));
2116                         g_print ("%d %d %d %d\n", klass->instance_size, instance_size, klass->blittable, blittable);
2117                         g_print ("%d %d %d %d\n", klass->has_references, has_references, klass->packing_size, packing_size);
2118                         g_print ("%d %d\n", klass->min_align, min_align);
2119                         for (i = 0; i < top; ++i) {
2120                                 field = &klass->fields [i];
2121                                 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC))
2122                                         printf ("  %s %d %d %d\n", klass->fields [i].name, klass->fields [i].offset, field_offsets [i], fields_has_references [i]);
2123                         }
2124                 }
2125                 g_assert (klass->instance_size == instance_size);
2126         } else {
2127                 klass->instance_size = instance_size;
2128         }
2129         klass->blittable = blittable;
2130         klass->has_references = has_references;
2131         klass->packing_size = packing_size;
2132         klass->min_align = min_align;
2133         for (i = 0; i < top; ++i) {
2134                 field = &klass->fields [i];
2135                 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC))
2136                         klass->fields [i].offset = field_offsets [i];
2137         }
2138
2139         if (klass->byval_arg.type == MONO_TYPE_SZARRAY || klass->byval_arg.type == MONO_TYPE_ARRAY)
2140                 klass->sizes.element_size = element_size;
2141
2142         mono_memory_barrier ();
2143         klass->size_inited = 1;
2144         mono_loader_unlock ();
2145
2146         /*
2147          * Compute static field layout and size
2148          * Static fields can reference the class itself, so this has to be
2149          * done after instance_size etc. are initialized.
2150          */
2151         class_size = 0;
2152         for (i = 0; i < top; i++) {
2153                 gint32 align;
2154                 guint32 size;
2155
2156                 field = &klass->fields [i];
2157                         
2158                 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC) || field->type->attrs & FIELD_ATTRIBUTE_LITERAL)
2159                         continue;
2160                 if (mono_field_is_deleted (field))
2161                         continue;
2162
2163                 if (mono_type_has_exceptions (field->type)) {
2164                         mono_class_set_type_load_failure (klass, "Field '%s' has an invalid type.", field->name);
2165                         break;
2166                 }
2167
2168                 has_static_fields = TRUE;
2169
2170                 size = mono_type_size (field->type, &align);
2171                 field_offsets [i] = class_size;
2172                 /*align is always non-zero here*/
2173                 field_offsets [i] += align - 1;
2174                 field_offsets [i] &= ~(align - 1);
2175                 class_size = field_offsets [i] + size;
2176         }
2177
2178         if (has_static_fields && class_size == 0)
2179                 /* Simplify code which depends on class_size != 0 if the class has static fields */
2180                 class_size = 8;
2181
2182         /* Compute klass->has_static_refs */
2183         has_static_refs = FALSE;
2184         for (i = 0; i < top; i++) {
2185                 MonoType *ftype;
2186
2187                 field = &klass->fields [i];
2188
2189                 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC) {
2190                         ftype = mono_type_get_underlying_type (field->type);
2191                         ftype = mono_type_get_basic_type_from_generic (ftype);
2192                         if (type_has_references (klass, ftype))
2193                                 has_static_refs = TRUE;
2194                 }
2195         }
2196
2197         /*valuetypes can't be neither bigger than 1Mb or empty. */
2198         if (klass->valuetype && (klass->instance_size <= 0 || klass->instance_size > (0x100000 + sizeof (MonoObject))))
2199                 mono_class_set_type_load_failure (klass, "Value type instance size (%d) cannot be zero, negative, or bigger than 1Mb", klass->instance_size);
2200
2201         /* Publish the data */
2202         mono_loader_lock ();
2203         if (!klass->rank)
2204                 klass->sizes.class_size = class_size;
2205         klass->has_static_refs = has_static_refs;
2206         for (i = 0; i < top; ++i) {
2207                 field = &klass->fields [i];
2208
2209                 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
2210                         field->offset = field_offsets [i];
2211         }
2212
2213         mono_memory_barrier ();
2214         klass->fields_inited = 1;
2215         mono_loader_unlock ();
2216
2217         g_free (field_offsets);
2218         g_free (fields_has_references);
2219 }
2220
2221 static MonoMethod*
2222 create_array_method (MonoClass *klass, const char *name, MonoMethodSignature *sig)
2223 {
2224         MonoMethod *method;
2225
2226         method = (MonoMethod *) mono_image_alloc0 (klass->image, sizeof (MonoMethodPInvoke));
2227         method->klass = klass;
2228         method->flags = METHOD_ATTRIBUTE_PUBLIC;
2229         method->iflags = METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL;
2230         method->signature = sig;
2231         method->name = name;
2232         method->slot = -1;
2233         /* .ctor */
2234         if (name [0] == '.') {
2235                 method->flags |= METHOD_ATTRIBUTE_RT_SPECIAL_NAME | METHOD_ATTRIBUTE_SPECIAL_NAME;
2236         } else {
2237                 method->iflags |= METHOD_IMPL_ATTRIBUTE_RUNTIME;
2238         }
2239         return method;
2240 }
2241
2242 /*
2243  * mono_class_setup_methods:
2244  * @class: a class
2245  *
2246  *   Initializes the 'methods' array in CLASS.
2247  * Calling this method should be avoided if possible since it allocates a lot 
2248  * of long-living MonoMethod structures.
2249  * Methods belonging to an interface are assigned a sequential slot starting
2250  * from 0.
2251  *
2252  * On failure this function sets klass->has_failure and stores a MonoErrorBoxed with details
2253  */
2254 void
2255 mono_class_setup_methods (MonoClass *klass)
2256 {
2257         int i, count;
2258         MonoMethod **methods;
2259
2260         if (klass->methods)
2261                 return;
2262
2263         if (mono_class_is_ginst (klass)) {
2264                 MonoError error;
2265                 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
2266
2267                 mono_class_init (gklass);
2268                 if (!mono_class_has_failure (gklass))
2269                         mono_class_setup_methods (gklass);
2270                 if (mono_class_set_type_load_failure_causedby_class (klass, gklass, "Generic type definition failed to load"))
2271                         return;
2272
2273                 /* The + 1 makes this always non-NULL to pass the check in mono_class_setup_methods () */
2274                 count = mono_class_get_method_count (gklass);
2275                 methods = (MonoMethod **)mono_class_alloc0 (klass, sizeof (MonoMethod*) * (count + 1));
2276
2277                 for (i = 0; i < count; i++) {
2278                         methods [i] = mono_class_inflate_generic_method_full_checked (
2279                                 gklass->methods [i], klass, mono_class_get_context (klass), &error);
2280                         if (!mono_error_ok (&error)) {
2281                                 char *method = mono_method_full_name (gklass->methods [i], TRUE);
2282                                 mono_class_set_type_load_failure (klass, "Could not inflate method %s due to %s", method, mono_error_get_message (&error));
2283
2284                                 g_free (method);
2285                                 mono_error_cleanup (&error);
2286                                 return;                         
2287                         }
2288                 }
2289         } else if (klass->rank) {
2290                 MonoError error;
2291                 MonoMethod *amethod;
2292                 MonoMethodSignature *sig;
2293                 int count_generic = 0, first_generic = 0;
2294                 int method_num = 0;
2295                 gboolean jagged_ctor = FALSE;
2296
2297                 count = 3 + (klass->rank > 1? 2: 1);
2298
2299                 mono_class_setup_interfaces (klass, &error);
2300                 g_assert (mono_error_ok (&error)); /*FIXME can this fail for array types?*/
2301
2302                 if (klass->rank == 1 && klass->element_class->rank) {
2303                         jagged_ctor = TRUE;
2304                         count ++;
2305                 }
2306
2307                 if (klass->interface_count) {
2308                         count_generic = generic_array_methods (klass);
2309                         first_generic = count;
2310                         count += klass->interface_count * count_generic;
2311                 }
2312
2313                 methods = (MonoMethod **)mono_class_alloc0 (klass, sizeof (MonoMethod*) * count);
2314
2315                 sig = mono_metadata_signature_alloc (klass->image, klass->rank);
2316                 sig->ret = &mono_defaults.void_class->byval_arg;
2317                 sig->pinvoke = TRUE;
2318                 sig->hasthis = TRUE;
2319                 for (i = 0; i < klass->rank; ++i)
2320                         sig->params [i] = &mono_defaults.int32_class->byval_arg;
2321
2322                 amethod = create_array_method (klass, ".ctor", sig);
2323                 methods [method_num++] = amethod;
2324                 if (klass->rank > 1) {
2325                         sig = mono_metadata_signature_alloc (klass->image, klass->rank * 2);
2326                         sig->ret = &mono_defaults.void_class->byval_arg;
2327                         sig->pinvoke = TRUE;
2328                         sig->hasthis = TRUE;
2329                         for (i = 0; i < klass->rank * 2; ++i)
2330                                 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2331
2332                         amethod = create_array_method (klass, ".ctor", sig);
2333                         methods [method_num++] = amethod;
2334                 }
2335
2336                 if (jagged_ctor) {
2337                         /* Jagged arrays have an extra ctor in .net which creates an array of arrays */
2338                         sig = mono_metadata_signature_alloc (klass->image, klass->rank + 1);
2339                         sig->ret = &mono_defaults.void_class->byval_arg;
2340                         sig->pinvoke = TRUE;
2341                         sig->hasthis = TRUE;
2342                         for (i = 0; i < klass->rank + 1; ++i)
2343                                 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2344                         amethod = create_array_method (klass, ".ctor", sig);
2345                         methods [method_num++] = amethod;
2346                 }
2347
2348                 /* element Get (idx11, [idx2, ...]) */
2349                 sig = mono_metadata_signature_alloc (klass->image, klass->rank);
2350                 sig->ret = &klass->element_class->byval_arg;
2351                 sig->pinvoke = TRUE;
2352                 sig->hasthis = TRUE;
2353                 for (i = 0; i < klass->rank; ++i)
2354                         sig->params [i] = &mono_defaults.int32_class->byval_arg;
2355                 amethod = create_array_method (klass, "Get", sig);
2356                 methods [method_num++] = amethod;
2357                 /* element& Address (idx11, [idx2, ...]) */
2358                 sig = mono_metadata_signature_alloc (klass->image, klass->rank);
2359                 sig->ret = &klass->element_class->this_arg;
2360                 sig->pinvoke = TRUE;
2361                 sig->hasthis = TRUE;
2362                 for (i = 0; i < klass->rank; ++i)
2363                         sig->params [i] = &mono_defaults.int32_class->byval_arg;
2364                 amethod = create_array_method (klass, "Address", sig);
2365                 methods [method_num++] = amethod;
2366                 /* void Set (idx11, [idx2, ...], element) */
2367                 sig = mono_metadata_signature_alloc (klass->image, klass->rank + 1);
2368                 sig->ret = &mono_defaults.void_class->byval_arg;
2369                 sig->pinvoke = TRUE;
2370                 sig->hasthis = TRUE;
2371                 for (i = 0; i < klass->rank; ++i)
2372                         sig->params [i] = &mono_defaults.int32_class->byval_arg;
2373                 sig->params [i] = &klass->element_class->byval_arg;
2374                 amethod = create_array_method (klass, "Set", sig);
2375                 methods [method_num++] = amethod;
2376
2377                 GHashTable *cache = g_hash_table_new (NULL, NULL);
2378                 for (i = 0; i < klass->interface_count; i++)
2379                         setup_generic_array_ifaces (klass, klass->interfaces [i], methods, first_generic + i * count_generic, cache);
2380                 g_hash_table_destroy (cache);
2381         } else if (mono_class_has_static_metadata (klass)) {
2382                 MonoError error;
2383                 int first_idx = mono_class_get_first_method_idx (klass);
2384
2385                 count = mono_class_get_method_count (klass);
2386                 methods = (MonoMethod **)mono_class_alloc (klass, sizeof (MonoMethod*) * count);
2387                 for (i = 0; i < count; ++i) {
2388                         int idx = mono_metadata_translate_token_index (klass->image, MONO_TABLE_METHOD, first_idx + i + 1);
2389                         methods [i] = mono_get_method_checked (klass->image, MONO_TOKEN_METHOD_DEF | idx, klass, NULL, &error);
2390                         if (!methods [i]) {
2391                                 mono_class_set_type_load_failure (klass, "Could not load method %d due to %s", i, mono_error_get_message (&error));
2392                                 mono_error_cleanup (&error);
2393                         }
2394                 }
2395         } else {
2396                 methods = (MonoMethod **)mono_class_alloc (klass, sizeof (MonoMethod*) * 1);
2397                 count = 0;
2398         }
2399
2400         if (MONO_CLASS_IS_INTERFACE (klass)) {
2401                 int slot = 0;
2402                 /*Only assign slots to virtual methods as interfaces are allowed to have static methods.*/
2403                 for (i = 0; i < count; ++i) {
2404                         if (methods [i]->flags & METHOD_ATTRIBUTE_VIRTUAL)
2405                                 methods [i]->slot = slot++;
2406                 }
2407         }
2408
2409         mono_image_lock (klass->image);
2410
2411         if (!klass->methods) {
2412                 mono_class_set_method_count (klass, count);
2413
2414                 /* Needed because of the double-checking locking pattern */
2415                 mono_memory_barrier ();
2416
2417                 klass->methods = methods;
2418         }
2419
2420         mono_image_unlock (klass->image);
2421 }
2422
2423 /*
2424  * mono_class_get_method_by_index:
2425  *
2426  *   Returns klass->methods [index], initializing klass->methods if neccesary.
2427  *
2428  * LOCKING: Acquires the loader lock.
2429  */
2430 MonoMethod*
2431 mono_class_get_method_by_index (MonoClass *klass, int index)
2432 {
2433         MonoError error;
2434
2435         MonoGenericClass *gklass = mono_class_try_get_generic_class (klass);
2436         /* Avoid calling setup_methods () if possible */
2437         if (gklass && !klass->methods) {
2438                 MonoMethod *m;
2439
2440                 m = mono_class_inflate_generic_method_full_checked (
2441                                 gklass->container_class->methods [index], klass, mono_class_get_context (klass), &error);
2442                 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
2443                 /*
2444                  * If setup_methods () is called later for this class, no duplicates are created,
2445                  * since inflate_generic_method guarantees that only one instance of a method
2446                  * is created for each context.
2447                  */
2448                 /*
2449                 mono_class_setup_methods (klass);
2450                 g_assert (m == klass->methods [index]);
2451                 */
2452                 return m;
2453         } else {
2454                 mono_class_setup_methods (klass);
2455                 if (mono_class_has_failure (klass)) /*FIXME do proper error handling*/
2456                         return NULL;
2457                 g_assert (index >= 0 && index < mono_class_get_method_count (klass));
2458                 return klass->methods [index];
2459         }
2460 }       
2461
2462 /*
2463  * mono_class_get_inflated_method:
2464  *
2465  *   Given an inflated class CLASS and a method METHOD which should be a method of
2466  * CLASS's generic definition, return the inflated method corresponding to METHOD.
2467  */
2468 MonoMethod*
2469 mono_class_get_inflated_method (MonoClass *klass, MonoMethod *method)
2470 {
2471         MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
2472         int i, mcount;
2473
2474         g_assert (method->klass == gklass);
2475
2476         mono_class_setup_methods (gklass);
2477         g_assert (!mono_class_has_failure (gklass)); /*FIXME do proper error handling*/
2478
2479         mcount = mono_class_get_method_count (gklass);
2480         for (i = 0; i < mcount; ++i) {
2481                 if (gklass->methods [i] == method) {
2482                         if (klass->methods) {
2483                                 return klass->methods [i];
2484                         } else {
2485                                 MonoError error;
2486                                 MonoMethod *result = mono_class_inflate_generic_method_full_checked (gklass->methods [i], klass, mono_class_get_context (klass), &error);
2487                                 g_assert (mono_error_ok (&error)); /* FIXME don't swallow this error */
2488                                 return result;
2489                         }
2490                 }
2491         }
2492
2493         return NULL;
2494 }       
2495
2496 /*
2497  * mono_class_get_vtable_entry:
2498  *
2499  *   Returns klass->vtable [offset], computing it if neccesary. Returns NULL on failure.
2500  * LOCKING: Acquires the loader lock.
2501  */
2502 MonoMethod*
2503 mono_class_get_vtable_entry (MonoClass *klass, int offset)
2504 {
2505         MonoMethod *m;
2506
2507         if (klass->rank == 1) {
2508                 /* 
2509                  * szarrays do not overwrite any methods of Array, so we can avoid
2510                  * initializing their vtables in some cases.
2511                  */
2512                 mono_class_setup_vtable (klass->parent);
2513                 if (offset < klass->parent->vtable_size)
2514                         return klass->parent->vtable [offset];
2515         }
2516
2517         if (mono_class_is_ginst (klass)) {
2518                 MonoError error;
2519                 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
2520                 mono_class_setup_vtable (gklass);
2521                 m = gklass->vtable [offset];
2522
2523                 m = mono_class_inflate_generic_method_full_checked (m, klass, mono_class_get_context (klass), &error);
2524                 g_assert (mono_error_ok (&error)); /* FIXME don't swallow this error */
2525         } else {
2526                 mono_class_setup_vtable (klass);
2527                 if (mono_class_has_failure (klass))
2528                         return NULL;
2529                 m = klass->vtable [offset];
2530         }
2531
2532         return m;
2533 }
2534
2535 /*
2536  * mono_class_get_vtable_size:
2537  *
2538  *   Return the vtable size for KLASS.
2539  */
2540 int
2541 mono_class_get_vtable_size (MonoClass *klass)
2542 {
2543         mono_class_setup_vtable (klass);
2544
2545         return klass->vtable_size;
2546 }
2547
2548 /*
2549  * mono_class_setup_properties:
2550  *
2551  *   Initialize klass->ext.property and klass->ext.properties.
2552  *
2553  * This method can fail the class.
2554  */
2555 static void
2556 mono_class_setup_properties (MonoClass *klass)
2557 {
2558         guint startm, endm, i, j;
2559         guint32 cols [MONO_PROPERTY_SIZE];
2560         MonoTableInfo *msemt = &klass->image->tables [MONO_TABLE_METHODSEMANTICS];
2561         MonoProperty *properties;
2562         guint32 last;
2563         int first, count;
2564         MonoClassPropertyInfo *info;
2565
2566         info = mono_class_get_property_info (klass);
2567         if (info)
2568                 return;
2569
2570         if (mono_class_is_ginst (klass)) {
2571                 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
2572
2573                 mono_class_init (gklass);
2574                 mono_class_setup_properties (gklass);
2575                 if (mono_class_set_type_load_failure_causedby_class (klass, gklass, "Generic type definition failed to load"))
2576                         return;
2577
2578                 MonoClassPropertyInfo *ginfo = mono_class_get_property_info (gklass);
2579                 properties = mono_class_new0 (klass, MonoProperty, ginfo->count + 1);
2580
2581                 for (i = 0; i < ginfo->count; i++) {
2582                         MonoError error;
2583                         MonoProperty *prop = &properties [i];
2584
2585                         *prop = ginfo->properties [i];
2586
2587                         if (prop->get)
2588                                 prop->get = mono_class_inflate_generic_method_full_checked (
2589                                         prop->get, klass, mono_class_get_context (klass), &error);
2590                         if (prop->set)
2591                                 prop->set = mono_class_inflate_generic_method_full_checked (
2592                                         prop->set, klass, mono_class_get_context (klass), &error);
2593
2594                         g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
2595                         prop->parent = klass;
2596                 }
2597
2598                 first = ginfo->first;
2599                 count = ginfo->count;
2600         } else {
2601                 first = mono_metadata_properties_from_typedef (klass->image, mono_metadata_token_index (klass->type_token) - 1, &last);
2602                 count = last - first;
2603
2604                 if (count) {
2605                         mono_class_setup_methods (klass);
2606                         if (mono_class_has_failure (klass))
2607                                 return;
2608                 }
2609
2610                 properties = (MonoProperty *)mono_class_alloc0 (klass, sizeof (MonoProperty) * count);
2611                 for (i = first; i < last; ++i) {
2612                         mono_metadata_decode_table_row (klass->image, MONO_TABLE_PROPERTY, i, cols, MONO_PROPERTY_SIZE);
2613                         properties [i - first].parent = klass;
2614                         properties [i - first].attrs = cols [MONO_PROPERTY_FLAGS];
2615                         properties [i - first].name = mono_metadata_string_heap (klass->image, cols [MONO_PROPERTY_NAME]);
2616
2617                         startm = mono_metadata_methods_from_property (klass->image, i, &endm);
2618                         int first_idx = mono_class_get_first_method_idx (klass);
2619                         for (j = startm; j < endm; ++j) {
2620                                 MonoMethod *method;
2621
2622                                 mono_metadata_decode_row (msemt, j, cols, MONO_METHOD_SEMA_SIZE);
2623
2624                                 if (klass->image->uncompressed_metadata) {
2625                                         MonoError error;
2626                                         /* It seems like the MONO_METHOD_SEMA_METHOD column needs no remapping */
2627                                         method = mono_get_method_checked (klass->image, MONO_TOKEN_METHOD_DEF | cols [MONO_METHOD_SEMA_METHOD], klass, NULL, &error);
2628                                         mono_error_cleanup (&error); /* FIXME don't swallow this error */
2629                                 } else {
2630                                         method = klass->methods [cols [MONO_METHOD_SEMA_METHOD] - 1 - first_idx];
2631                                 }
2632
2633                                 switch (cols [MONO_METHOD_SEMA_SEMANTICS]) {
2634                                 case METHOD_SEMANTIC_SETTER:
2635                                         properties [i - first].set = method;
2636                                         break;
2637                                 case METHOD_SEMANTIC_GETTER:
2638                                         properties [i - first].get = method;
2639                                         break;
2640                                 default:
2641                                         break;
2642                                 }
2643                         }
2644                 }
2645         }
2646
2647         info = mono_class_alloc0 (klass, sizeof (MonoClassPropertyInfo));
2648         info->first = first;
2649         info->count = count;
2650         info->properties = properties;
2651         mono_memory_barrier ();
2652
2653         /* This might leak 'info' which was allocated from the image mempool */
2654         mono_class_set_property_info (klass, info);
2655 }
2656
2657 static MonoMethod**
2658 inflate_method_listz (MonoMethod **methods, MonoClass *klass, MonoGenericContext *context)
2659 {
2660         MonoMethod **om, **retval;
2661         int count;
2662
2663         for (om = methods, count = 0; *om; ++om, ++count)
2664                 ;
2665
2666         retval = g_new0 (MonoMethod*, count + 1);
2667         count = 0;
2668         for (om = methods, count = 0; *om; ++om, ++count) {
2669                 MonoError error;
2670                 retval [count] = mono_class_inflate_generic_method_full_checked (*om, klass, context, &error);
2671                 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
2672         }
2673
2674         return retval;
2675 }
2676
2677 /*This method can fail the class.*/
2678 static void
2679 mono_class_setup_events (MonoClass *klass)
2680 {
2681         int first, count;
2682         guint startm, endm, i, j;
2683         guint32 cols [MONO_EVENT_SIZE];
2684         MonoTableInfo *msemt = &klass->image->tables [MONO_TABLE_METHODSEMANTICS];
2685         guint32 last;
2686         MonoEvent *events;
2687
2688         MonoClassEventInfo *info = mono_class_get_event_info (klass);
2689         if (info)
2690                 return;
2691
2692         if (mono_class_is_ginst (klass)) {
2693                 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
2694                 MonoGenericContext *context = NULL;
2695
2696                 mono_class_setup_events (gklass);
2697                 if (mono_class_set_type_load_failure_causedby_class (klass, gklass, "Generic type definition failed to load"))
2698                         return;
2699
2700                 MonoClassEventInfo *ginfo = mono_class_get_event_info (gklass);
2701                 first = ginfo->first;
2702                 count = ginfo->count;
2703
2704                 events = mono_class_new0 (klass, MonoEvent, count);
2705
2706                 if (count)
2707                         context = mono_class_get_context (klass);
2708
2709                 for (i = 0; i < count; i++) {
2710                         MonoError error;
2711                         MonoEvent *event = &events [i];
2712                         MonoEvent *gevent = &ginfo->events [i];
2713
2714                         error_init (&error); //since we do conditional calls, we must ensure the default value is ok
2715
2716                         event->parent = klass;
2717                         event->name = gevent->name;
2718                         event->add = gevent->add ? mono_class_inflate_generic_method_full_checked (gevent->add, klass, context, &error) : NULL;
2719                         g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
2720                         event->remove = gevent->remove ? mono_class_inflate_generic_method_full_checked (gevent->remove, klass, context, &error) : NULL;
2721                         g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
2722                         event->raise = gevent->raise ? mono_class_inflate_generic_method_full_checked (gevent->raise, klass, context, &error) : NULL;
2723                         g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
2724
2725 #ifndef MONO_SMALL_CONFIG
2726                         event->other = gevent->other ? inflate_method_listz (gevent->other, klass, context) : NULL;
2727 #endif
2728                         event->attrs = gevent->attrs;
2729                 }
2730         } else {
2731                 first = mono_metadata_events_from_typedef (klass->image, mono_metadata_token_index (klass->type_token) - 1, &last);
2732                 count = last - first;
2733
2734                 if (count) {
2735                         mono_class_setup_methods (klass);
2736                         if (mono_class_has_failure (klass)) {
2737                                 return;
2738                         }
2739                 }
2740
2741                 events = (MonoEvent *)mono_class_alloc0 (klass, sizeof (MonoEvent) * count);
2742                 for (i = first; i < last; ++i) {
2743                         MonoEvent *event = &events [i - first];
2744
2745                         mono_metadata_decode_table_row (klass->image, MONO_TABLE_EVENT, i, cols, MONO_EVENT_SIZE);
2746                         event->parent = klass;
2747                         event->attrs = cols [MONO_EVENT_FLAGS];
2748                         event->name = mono_metadata_string_heap (klass->image, cols [MONO_EVENT_NAME]);
2749
2750                         startm = mono_metadata_methods_from_event (klass->image, i, &endm);
2751                         int first_idx = mono_class_get_first_method_idx (klass);
2752                         for (j = startm; j < endm; ++j) {
2753                                 MonoMethod *method;
2754
2755                                 mono_metadata_decode_row (msemt, j, cols, MONO_METHOD_SEMA_SIZE);
2756
2757                                 if (klass->image->uncompressed_metadata) {
2758                                         MonoError error;
2759                                         /* It seems like the MONO_METHOD_SEMA_METHOD column needs no remapping */
2760                                         method = mono_get_method_checked (klass->image, MONO_TOKEN_METHOD_DEF | cols [MONO_METHOD_SEMA_METHOD], klass, NULL, &error);
2761                                         mono_error_cleanup (&error); /* FIXME don't swallow this error */
2762                                 } else {
2763                                         method = klass->methods [cols [MONO_METHOD_SEMA_METHOD] - 1 - first_idx];
2764                                 }
2765
2766                                 switch (cols [MONO_METHOD_SEMA_SEMANTICS]) {
2767                                 case METHOD_SEMANTIC_ADD_ON:
2768                                         event->add = method;
2769                                         break;
2770                                 case METHOD_SEMANTIC_REMOVE_ON:
2771                                         event->remove = method;
2772                                         break;
2773                                 case METHOD_SEMANTIC_FIRE:
2774                                         event->raise = method;
2775                                         break;
2776                                 case METHOD_SEMANTIC_OTHER: {
2777 #ifndef MONO_SMALL_CONFIG
2778                                         int n = 0;
2779
2780                                         if (event->other == NULL) {
2781                                                 event->other = g_new0 (MonoMethod*, 2);
2782                                         } else {
2783                                                 while (event->other [n])
2784                                                         n++;
2785                                                 event->other = (MonoMethod **)g_realloc (event->other, (n + 2) * sizeof (MonoMethod*));
2786                                         }
2787                                         event->other [n] = method;
2788                                         /* NULL terminated */
2789                                         event->other [n + 1] = NULL;
2790 #endif
2791                                         break;
2792                                 }
2793                                 default:
2794                                         break;
2795                                 }
2796                         }
2797                 }
2798         }
2799
2800         info = mono_class_alloc0 (klass, sizeof (MonoClassEventInfo));
2801         info->events = events;
2802         info->first = first;
2803         info->count = count;
2804
2805         mono_memory_barrier ();
2806
2807         mono_class_set_event_info (klass, info);
2808 }
2809
2810 /*
2811  * Global pool of interface IDs, represented as a bitset.
2812  * LOCKING: Protected by the classes lock.
2813  */
2814 static MonoBitSet *global_interface_bitset = NULL;
2815
2816 /*
2817  * mono_unload_interface_ids:
2818  * @bitset: bit set of interface IDs
2819  *
2820  * When an image is unloaded, the interface IDs associated with
2821  * the image are put back in the global pool of IDs so the numbers
2822  * can be reused.
2823  */
2824 void
2825 mono_unload_interface_ids (MonoBitSet *bitset)
2826 {
2827         classes_lock ();
2828         mono_bitset_sub (global_interface_bitset, bitset);
2829         classes_unlock ();
2830 }
2831
2832 void
2833 mono_unload_interface_id (MonoClass *klass)
2834 {
2835         if (global_interface_bitset && klass->interface_id) {
2836                 classes_lock ();
2837                 mono_bitset_clear (global_interface_bitset, klass->interface_id);
2838                 classes_unlock ();
2839         }
2840 }
2841
2842 /**
2843  * mono_get_unique_iid:
2844  * \param klass interface
2845  *
2846  * Assign a unique integer ID to the interface represented by \p klass.
2847  * The ID will positive and as small as possible.
2848  * LOCKING: Acquires the classes lock.
2849  * \returns The new ID.
2850  */
2851 static guint32
2852 mono_get_unique_iid (MonoClass *klass)
2853 {
2854         int iid;
2855         
2856         g_assert (MONO_CLASS_IS_INTERFACE (klass));
2857
2858         classes_lock ();
2859
2860         if (!global_interface_bitset) {
2861                 global_interface_bitset = mono_bitset_new (128, 0);
2862         }
2863
2864         iid = mono_bitset_find_first_unset (global_interface_bitset, -1);
2865         if (iid < 0) {
2866                 int old_size = mono_bitset_size (global_interface_bitset);
2867                 MonoBitSet *new_set = mono_bitset_clone (global_interface_bitset, old_size * 2);
2868                 mono_bitset_free (global_interface_bitset);
2869                 global_interface_bitset = new_set;
2870                 iid = old_size;
2871         }
2872         mono_bitset_set (global_interface_bitset, iid);
2873         /* set the bit also in the per-image set */
2874         if (!mono_class_is_ginst (klass)) {
2875                 if (klass->image->interface_bitset) {
2876                         if (iid >= mono_bitset_size (klass->image->interface_bitset)) {
2877                                 MonoBitSet *new_set = mono_bitset_clone (klass->image->interface_bitset, iid + 1);
2878                                 mono_bitset_free (klass->image->interface_bitset);
2879                                 klass->image->interface_bitset = new_set;
2880                         }
2881                 } else {
2882                         klass->image->interface_bitset = mono_bitset_new (iid + 1, 0);
2883                 }
2884                 mono_bitset_set (klass->image->interface_bitset, iid);
2885         }
2886
2887         classes_unlock ();
2888
2889 #ifndef MONO_SMALL_CONFIG
2890         if (mono_print_vtable) {
2891                 int generic_id;
2892                 char *type_name = mono_type_full_name (&klass->byval_arg);
2893                 MonoGenericClass *gklass = mono_class_try_get_generic_class (klass);
2894                 if (gklass && !gklass->context.class_inst->is_open) {
2895                         generic_id = gklass->context.class_inst->id;
2896                         g_assert (generic_id != 0);
2897                 } else {
2898                         generic_id = 0;
2899                 }
2900                 printf ("Interface: assigned id %d to %s|%s|%d\n", iid, klass->image->name, type_name, generic_id);
2901                 g_free (type_name);
2902         }
2903 #endif
2904
2905         /* I've confirmed iids safe past 16 bits, however bitset code uses a signed int while testing.
2906          * Once this changes, it should be safe for us to allow 2^32-1 interfaces, until then 2^31-2 is the max. */
2907         g_assert (iid < INT_MAX);
2908         return iid;
2909 }
2910
2911 static void
2912 collect_implemented_interfaces_aux (MonoClass *klass, GPtrArray **res, GHashTable **ifaces, MonoError *error)
2913 {
2914         int i;
2915         MonoClass *ic;
2916
2917         mono_class_setup_interfaces (klass, error);
2918         return_if_nok (error);
2919
2920         for (i = 0; i < klass->interface_count; i++) {
2921                 ic = klass->interfaces [i];
2922
2923                 if (*res == NULL)
2924                         *res = g_ptr_array_new ();
2925                 if (*ifaces == NULL)
2926                         *ifaces = g_hash_table_new (NULL, NULL);
2927                 if (g_hash_table_lookup (*ifaces, ic))
2928                         continue;
2929                 /* A gparam is not an implemented interface for the purposes of
2930                  * mono_class_get_implemented_interfaces */
2931                 if (mono_class_is_gparam (ic))
2932                         continue;
2933                 g_ptr_array_add (*res, ic);
2934                 g_hash_table_insert (*ifaces, ic, ic);
2935                 mono_class_init (ic);
2936                 if (mono_class_has_failure (ic)) {
2937                         mono_error_set_type_load_class (error, ic, "Error Loading class");
2938                         return;
2939                 }
2940
2941                 collect_implemented_interfaces_aux (ic, res, ifaces, error);
2942                 return_if_nok (error);
2943         }
2944 }
2945
2946 GPtrArray*
2947 mono_class_get_implemented_interfaces (MonoClass *klass, MonoError *error)
2948 {
2949         GPtrArray *res = NULL;
2950         GHashTable *ifaces = NULL;
2951
2952         collect_implemented_interfaces_aux (klass, &res, &ifaces, error);
2953         if (ifaces)
2954                 g_hash_table_destroy (ifaces);
2955         if (!mono_error_ok (error)) {
2956                 if (res)
2957                         g_ptr_array_free (res, TRUE);
2958                 return NULL;
2959         }
2960         return res;
2961 }
2962
2963 static int
2964 compare_interface_ids (const void *p_key, const void *p_element)
2965 {
2966         const MonoClass *key = (const MonoClass *)p_key;
2967         const MonoClass *element = *(const MonoClass **)p_element;
2968         
2969         return (key->interface_id - element->interface_id);
2970 }
2971
2972 /*FIXME verify all callers if they should switch to mono_class_interface_offset_with_variance*/
2973 int
2974 mono_class_interface_offset (MonoClass *klass, MonoClass *itf)
2975 {
2976         MonoClass **result = (MonoClass **)mono_binary_search (
2977                         itf,
2978                         klass->interfaces_packed,
2979                         klass->interface_offsets_count,
2980                         sizeof (MonoClass *),
2981                         compare_interface_ids);
2982         if (result) {
2983                 return klass->interface_offsets_packed [result - (klass->interfaces_packed)];
2984         } else {
2985                 return -1;
2986         }
2987 }
2988
2989 /**
2990  * mono_class_interface_offset_with_variance:
2991  * 
2992  * Return the interface offset of \p itf in \p klass. Sets \p non_exact_match to TRUE if the match required variance check
2993  * If \p itf is an interface with generic variant arguments, try to find the compatible one.
2994  *
2995  * Note that this function is responsible for resolving ambiguities. Right now we use whatever ordering interfaces_packed gives us.
2996  *
2997  * FIXME figure out MS disambiguation rules and fix this function.
2998  */
2999 int
3000 mono_class_interface_offset_with_variance (MonoClass *klass, MonoClass *itf, gboolean *non_exact_match)
3001 {
3002         int i = mono_class_interface_offset (klass, itf);
3003         *non_exact_match = FALSE;
3004         if (i >= 0)
3005                 return i;
3006         
3007         if (itf->is_array_special_interface && klass->rank < 2) {
3008                 MonoClass *gtd = mono_class_get_generic_type_definition (itf);
3009
3010                 for (i = 0; i < klass->interface_offsets_count; i++) {
3011                         // printf ("\t%s\n", mono_type_get_full_name (klass->interfaces_packed [i]));
3012                         if (mono_class_get_generic_type_definition (klass->interfaces_packed [i]) == gtd) {
3013                                 *non_exact_match = TRUE;
3014                                 return klass->interface_offsets_packed [i];
3015                         }
3016                 }
3017         }
3018
3019         if (!mono_class_has_variant_generic_params (itf))
3020                 return -1;
3021
3022         for (i = 0; i < klass->interface_offsets_count; i++) {
3023                 if (mono_class_is_variant_compatible (itf, klass->interfaces_packed [i], FALSE)) {
3024                         *non_exact_match = TRUE;
3025                         return klass->interface_offsets_packed [i];
3026                 }
3027         }
3028
3029         return -1;
3030 }
3031
3032 static void
3033 print_implemented_interfaces (MonoClass *klass)
3034 {
3035         char *name;
3036         MonoError error;
3037         GPtrArray *ifaces = NULL;
3038         int i;
3039         int ancestor_level = 0;
3040
3041         name = mono_type_get_full_name (klass);
3042         printf ("Packed interface table for class %s has size %d\n", name, klass->interface_offsets_count);
3043         g_free (name);
3044
3045         for (i = 0; i < klass->interface_offsets_count; i++)
3046                 printf ("  [%03d][UUID %03d][SLOT %03d][SIZE  %03d] interface %s.%s\n", i,
3047                                 klass->interfaces_packed [i]->interface_id,
3048                                 klass->interface_offsets_packed [i],
3049                                 mono_class_get_method_count (klass->interfaces_packed [i]),
3050                                 klass->interfaces_packed [i]->name_space,
3051                                 klass->interfaces_packed [i]->name );
3052         printf ("Interface flags: ");
3053         for (i = 0; i <= klass->max_interface_id; i++)
3054                 if (MONO_CLASS_IMPLEMENTS_INTERFACE (klass, i))
3055                         printf ("(%d,T)", i);
3056                 else
3057                         printf ("(%d,F)", i);
3058         printf ("\n");
3059         printf ("Dump interface flags:");
3060 #ifdef COMPRESSED_INTERFACE_BITMAP
3061         {
3062                 const uint8_t* p = klass->interface_bitmap;
3063                 i = klass->max_interface_id;
3064                 while (i > 0) {
3065                         printf (" %d x 00 %02X", p [0], p [1]);
3066                         i -= p [0] * 8;
3067                         i -= 8;
3068                 }
3069         }
3070 #else
3071         for (i = 0; i < ((((klass->max_interface_id + 1) >> 3)) + (((klass->max_interface_id + 1) & 7)? 1 :0)); i++)
3072                 printf (" %02X", klass->interface_bitmap [i]);
3073 #endif
3074         printf ("\n");
3075         while (klass != NULL) {
3076                 printf ("[LEVEL %d] Implemented interfaces by class %s:\n", ancestor_level, klass->name);
3077                 ifaces = mono_class_get_implemented_interfaces (klass, &error);
3078                 if (!mono_error_ok (&error)) {
3079                         printf ("  Type failed due to %s\n", mono_error_get_message (&error));
3080                         mono_error_cleanup (&error);
3081                 } else if (ifaces) {
3082                         for (i = 0; i < ifaces->len; i++) {
3083                                 MonoClass *ic = (MonoClass *)g_ptr_array_index (ifaces, i);
3084                                 printf ("  [UIID %d] interface %s\n", ic->interface_id, ic->name);
3085                                 printf ("  [%03d][UUID %03d][SLOT %03d][SIZE  %03d] interface %s.%s\n", i,
3086                                                 ic->interface_id,
3087                                                 mono_class_interface_offset (klass, ic),
3088                                                 mono_class_get_method_count (ic),
3089                                                 ic->name_space,
3090                                                 ic->name );
3091                         }
3092                         g_ptr_array_free (ifaces, TRUE);
3093                 }
3094                 ancestor_level ++;
3095                 klass = klass->parent;
3096         }
3097 }
3098
3099 /*
3100  * Return the number of virtual methods.
3101  * Even for interfaces we can't simply return the number of methods as all CLR types are allowed to have static methods.
3102  * Return -1 on failure.
3103  * FIXME It would be nice if this information could be cached somewhere.
3104  */
3105 static int
3106 count_virtual_methods (MonoClass *klass)
3107 {
3108         int i, mcount, vcount = 0;
3109         guint32 flags;
3110         klass = mono_class_get_generic_type_definition (klass); /*We can find this information by looking at the GTD*/
3111
3112         if (klass->methods || !MONO_CLASS_HAS_STATIC_METADATA (klass)) {
3113                 mono_class_setup_methods (klass);
3114                 if (mono_class_has_failure (klass))
3115                         return -1;
3116
3117                 mcount = mono_class_get_method_count (klass);
3118                 for (i = 0; i < mcount; ++i) {
3119                         flags = klass->methods [i]->flags;
3120                         if (flags & METHOD_ATTRIBUTE_VIRTUAL)
3121                                 ++vcount;
3122                 }
3123         } else {
3124                 int first_idx = mono_class_get_first_method_idx (klass);
3125                 mcount = mono_class_get_method_count (klass);
3126                 for (i = 0; i < mcount; ++i) {
3127                         flags = mono_metadata_decode_table_row_col (klass->image, MONO_TABLE_METHOD, first_idx + i, MONO_METHOD_FLAGS);
3128
3129                         if (flags & METHOD_ATTRIBUTE_VIRTUAL)
3130                                 ++vcount;
3131                 }
3132         }
3133         return vcount;
3134 }
3135
3136 static int
3137 find_interface (int num_ifaces, MonoClass **interfaces_full, MonoClass *ic)
3138 {
3139         int m, l = 0;
3140         if (!num_ifaces)
3141                 return -1;
3142         while (1) {
3143                 if (l > num_ifaces)
3144                         return -1;
3145                 m = (l + num_ifaces) / 2;
3146                 if (interfaces_full [m] == ic)
3147                         return m;
3148                 if (l == num_ifaces)
3149                         return -1;
3150                 if (!interfaces_full [m] || interfaces_full [m]->interface_id > ic->interface_id) {
3151                         num_ifaces = m - 1;
3152                 } else {
3153                         l =  m + 1;
3154                 }
3155         }
3156 }
3157
3158 static mono_bool
3159 set_interface_and_offset (int num_ifaces, MonoClass **interfaces_full, int *interface_offsets_full, MonoClass *ic, int offset, mono_bool force_set)
3160 {
3161         int i = find_interface (num_ifaces, interfaces_full, ic);
3162         if (i >= 0) {
3163                 if (!force_set)
3164                         return TRUE;
3165                 interface_offsets_full [i] = offset;
3166                 return FALSE;
3167         }
3168         for (i = 0; i < num_ifaces; ++i) {
3169                 if (interfaces_full [i]) {
3170                         int end;
3171                         if (interfaces_full [i]->interface_id < ic->interface_id)
3172                                 continue;
3173                         end = i + 1;
3174                         while (end < num_ifaces && interfaces_full [end]) end++;
3175                         memmove (interfaces_full + i + 1, interfaces_full + i, sizeof (MonoClass*) * (end - i));
3176                         memmove (interface_offsets_full + i + 1, interface_offsets_full + i, sizeof (int) * (end - i));
3177                 }
3178                 interfaces_full [i] = ic;
3179                 interface_offsets_full [i] = offset;
3180                 break;
3181         }
3182         return FALSE;
3183 }
3184
3185 #ifdef COMPRESSED_INTERFACE_BITMAP
3186
3187 /*
3188  * Compressed interface bitmap design.
3189  *
3190  * Interface bitmaps take a large amount of memory, because their size is
3191  * linear with the maximum interface id assigned in the process (each interface
3192  * is assigned a unique id as it is loaded). The number of interface classes
3193  * is high because of the many implicit interfaces implemented by arrays (we'll
3194  * need to lazy-load them in the future).
3195  * Most classes implement a very small number of interfaces, so the bitmap is
3196  * sparse. This bitmap needs to be checked by interface casts, so access to the
3197  * needed bit must be fast and doable with few jit instructions.
3198  *
3199  * The current compression format is as follows:
3200  * *) it is a sequence of one or more two-byte elements
3201  * *) the first byte in the element is the count of empty bitmap bytes
3202  * at the current bitmap position
3203  * *) the second byte in the element is an actual bitmap byte at the current
3204  * bitmap position
3205  *
3206  * As an example, the following compressed bitmap bytes:
3207  *      0x07 0x01 0x00 0x7
3208  * correspond to the following bitmap:
3209  *      0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x01 0x07
3210  *
3211  * Each two-byte element can represent up to 2048 bitmap bits, but as few as a single
3212  * bitmap byte for non-sparse sequences. In practice the interface bitmaps created
3213  * during a gmcs bootstrap are reduced to less tha 5% of the original size.
3214  */
3215
3216 /**
3217  * mono_compress_bitmap:
3218  * \param dest destination buffer
3219  * \param bitmap bitmap buffer
3220  * \param size size of \p bitmap in bytes
3221  *
3222  * This is a mono internal function.
3223  * The \p bitmap data is compressed into a format that is small but
3224  * still searchable in few instructions by the JIT and runtime.
3225  * The compressed data is stored in the buffer pointed to by the
3226  * \p dest array. Passing a NULL value for \p dest allows to just compute
3227  * the size of the buffer.
3228  * This compression algorithm assumes the bits set in the bitmap are
3229  * few and far between, like in interface bitmaps.
3230  * \returns The size of the compressed bitmap in bytes.
3231  */
3232 int
3233 mono_compress_bitmap (uint8_t *dest, const uint8_t *bitmap, int size)
3234 {
3235         int numz = 0;
3236         int res = 0;
3237         const uint8_t *end = bitmap + size;
3238         while (bitmap < end) {
3239                 if (*bitmap || numz == 255) {
3240                         if (dest) {
3241                                 *dest++ = numz;
3242                                 *dest++ = *bitmap;
3243                         }
3244                         res += 2;
3245                         numz = 0;
3246                         bitmap++;
3247                         continue;
3248                 }
3249                 bitmap++;
3250                 numz++;
3251         }
3252         if (numz) {
3253                 res += 2;
3254                 if (dest) {
3255                         *dest++ = numz;
3256                         *dest++ = 0;
3257                 }
3258         }
3259         return res;
3260 }
3261
3262 /**
3263  * mono_class_interface_match:
3264  * \param bitmap a compressed bitmap buffer
3265  * \param id the index to check in the bitmap
3266  *
3267  * This is a mono internal function.
3268  * Checks if a bit is set in a compressed interface bitmap. \p id must
3269  * be already checked for being smaller than the maximum id encoded in the
3270  * bitmap.
3271  *
3272  * \returns A non-zero value if bit \p id is set in the bitmap \p bitmap,
3273  * FALSE otherwise.
3274  */
3275 int
3276 mono_class_interface_match (const uint8_t *bitmap, int id)
3277 {
3278         while (TRUE) {
3279                 id -= bitmap [0] * 8;
3280                 if (id < 8) {
3281                         if (id < 0)
3282                                 return 0;
3283                         return bitmap [1] & (1 << id);
3284                 }
3285                 bitmap += 2;
3286                 id -= 8;
3287         }
3288 }
3289 #endif
3290
3291 /*
3292  * Return -1 on failure and set klass->has_failure and store a MonoErrorBoxed with the details.
3293  * LOCKING: Acquires the loader lock.
3294  */
3295 static int
3296 setup_interface_offsets (MonoClass *klass, int cur_slot, gboolean overwrite)
3297 {
3298         MonoError error;
3299         MonoClass *k, *ic;
3300         int i, j, num_ifaces;
3301         guint32 max_iid;
3302         MonoClass **interfaces_full = NULL;
3303         int *interface_offsets_full = NULL;
3304         GPtrArray *ifaces;
3305         GPtrArray **ifaces_array = NULL;
3306         int interface_offsets_count;
3307
3308         mono_loader_lock ();
3309
3310         mono_class_setup_supertypes (klass);
3311
3312         /* compute maximum number of slots and maximum interface id */
3313         max_iid = 0;
3314         num_ifaces = 0; /* this can include duplicated ones */
3315         ifaces_array = g_new0 (GPtrArray *, klass->idepth);
3316         for (j = 0; j < klass->idepth; j++) {
3317                 k = klass->supertypes [j];
3318                 g_assert (k);
3319                 num_ifaces += k->interface_count;
3320                 for (i = 0; i < k->interface_count; i++) {
3321                         ic = k->interfaces [i];
3322
3323                         /* A gparam does not have any interface_id set. */
3324                         if (! mono_class_is_gparam (ic))
3325                                 mono_class_init (ic);
3326
3327                         if (max_iid < ic->interface_id)
3328                                 max_iid = ic->interface_id;
3329                 }
3330                 ifaces = mono_class_get_implemented_interfaces (k, &error);
3331                 if (!mono_error_ok (&error)) {
3332                         char *name = mono_type_get_full_name (k);
3333                         mono_class_set_type_load_failure (klass, "Error getting the interfaces of %s due to %s", name, mono_error_get_message (&error));
3334                         g_free (name);
3335                         mono_error_cleanup (&error);
3336                         cur_slot = -1;
3337                         goto end;
3338                 }
3339                 if (ifaces) {
3340                         num_ifaces += ifaces->len;
3341                         for (i = 0; i < ifaces->len; ++i) {
3342                                 ic = (MonoClass *)g_ptr_array_index (ifaces, i);
3343                                 if (max_iid < ic->interface_id)
3344                                         max_iid = ic->interface_id;
3345                         }
3346                         ifaces_array [j] = ifaces;
3347                 }
3348         }
3349
3350         if (MONO_CLASS_IS_INTERFACE (klass)) {
3351                 num_ifaces++;
3352                 if (max_iid < klass->interface_id)
3353                         max_iid = klass->interface_id;
3354         }
3355
3356         /* compute vtable offset for interfaces */
3357         interfaces_full = (MonoClass **)g_malloc0 (sizeof (MonoClass*) * num_ifaces);
3358         interface_offsets_full = (int *)g_malloc (sizeof (int) * num_ifaces);
3359
3360         for (i = 0; i < num_ifaces; i++)
3361                 interface_offsets_full [i] = -1;
3362
3363         /* skip the current class */
3364         for (j = 0; j < klass->idepth - 1; j++) {
3365                 k = klass->supertypes [j];
3366                 ifaces = ifaces_array [j];
3367
3368                 if (ifaces) {
3369                         for (i = 0; i < ifaces->len; ++i) {
3370                                 int io;
3371                                 ic = (MonoClass *)g_ptr_array_index (ifaces, i);
3372                                 
3373                                 /*Force the sharing of interface offsets between parent and subtypes.*/
3374                                 io = mono_class_interface_offset (k, ic);
3375                                 g_assert (io >= 0);
3376                                 set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, io, TRUE);
3377                         }
3378                 }
3379         }
3380
3381         g_assert (klass == klass->supertypes [klass->idepth - 1]);
3382         ifaces = ifaces_array [klass->idepth - 1];
3383         if (ifaces) {
3384                 for (i = 0; i < ifaces->len; ++i) {
3385                         int count;
3386                         ic = (MonoClass *)g_ptr_array_index (ifaces, i);
3387                         if (set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, cur_slot, FALSE))
3388                                 continue;
3389                         count = count_virtual_methods (ic);
3390                         if (count == -1) {
3391                                 char *name = mono_type_get_full_name (ic);
3392                                 mono_class_set_type_load_failure (klass, "Error calculating interface offset of %s", name);
3393                                 g_free (name);
3394                                 cur_slot = -1;
3395                                 goto end;
3396                         }
3397                         cur_slot += count;
3398                 }
3399         }
3400
3401         if (MONO_CLASS_IS_INTERFACE (klass))
3402                 set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, klass, cur_slot, TRUE);
3403
3404         for (interface_offsets_count = 0, i = 0; i < num_ifaces; i++) {
3405                 if (interface_offsets_full [i] != -1)
3406                         interface_offsets_count ++;
3407         }
3408
3409         /* Publish the data */
3410         klass->max_interface_id = max_iid;
3411         /*
3412          * We might get called multiple times:
3413          * - mono_class_init ()
3414          * - mono_class_setup_vtable ().
3415          * - mono_class_setup_interface_offsets ().
3416          * mono_class_setup_interface_offsets () passes 0 as CUR_SLOT, so the computed interface offsets will be invalid. This
3417          * means we have to overwrite those when called from other places (#4440).
3418          */
3419         if (klass->interfaces_packed) {
3420                 if (!overwrite)
3421                         g_assert (klass->interface_offsets_count == interface_offsets_count);
3422         } else {
3423                 uint8_t *bitmap;
3424                 int bsize;
3425                 klass->interface_offsets_count = interface_offsets_count;
3426                 klass->interfaces_packed = (MonoClass **)mono_class_alloc (klass, sizeof (MonoClass*) * interface_offsets_count);
3427                 klass->interface_offsets_packed = (guint16 *)mono_class_alloc (klass, sizeof (guint16) * interface_offsets_count);
3428                 bsize = (sizeof (guint8) * ((max_iid + 1) >> 3)) + (((max_iid + 1) & 7)? 1 :0);
3429 #ifdef COMPRESSED_INTERFACE_BITMAP
3430                 bitmap = g_malloc0 (bsize);
3431 #else
3432                 bitmap = (uint8_t *)mono_class_alloc0 (klass, bsize);
3433 #endif
3434                 for (i = 0; i < interface_offsets_count; i++) {
3435                         guint32 id = interfaces_full [i]->interface_id;
3436                         bitmap [id >> 3] |= (1 << (id & 7));
3437                         klass->interfaces_packed [i] = interfaces_full [i];
3438                         klass->interface_offsets_packed [i] = interface_offsets_full [i];
3439                 }
3440 #ifdef COMPRESSED_INTERFACE_BITMAP
3441                 i = mono_compress_bitmap (NULL, bitmap, bsize);
3442                 klass->interface_bitmap = mono_class_alloc0 (klass, i);
3443                 mono_compress_bitmap (klass->interface_bitmap, bitmap, bsize);
3444                 g_free (bitmap);
3445 #else
3446                 klass->interface_bitmap = bitmap;
3447 #endif
3448         }
3449 end:
3450         mono_loader_unlock ();
3451
3452         g_free (interfaces_full);
3453         g_free (interface_offsets_full);
3454         for (i = 0; i < klass->idepth; i++) {
3455                 ifaces = ifaces_array [i];
3456                 if (ifaces)
3457                         g_ptr_array_free (ifaces, TRUE);
3458         }
3459         g_free (ifaces_array);
3460         
3461         //printf ("JUST DONE: ");
3462         //print_implemented_interfaces (klass);
3463
3464         return cur_slot;
3465 }
3466
3467 /*
3468  * Setup interface offsets for interfaces. 
3469  * Initializes:
3470  * - klass->max_interface_id
3471  * - klass->interface_offsets_count
3472  * - klass->interfaces_packed
3473  * - klass->interface_offsets_packed
3474  * - klass->interface_bitmap
3475  *
3476  * This function can fail @class.
3477  */
3478 void
3479 mono_class_setup_interface_offsets (MonoClass *klass)
3480 {
3481         setup_interface_offsets (klass, 0, FALSE);
3482 }
3483
3484 /*Checks if @klass has @parent as one of it's parents type gtd
3485  *
3486  * For example:
3487  *      Foo<T>
3488  *      Bar<T> : Foo<Bar<Bar<T>>>
3489  *
3490  */
3491 static gboolean
3492 mono_class_has_gtd_parent (MonoClass *klass, MonoClass *parent)
3493 {
3494         klass = mono_class_get_generic_type_definition (klass);
3495         parent = mono_class_get_generic_type_definition (parent);
3496         mono_class_setup_supertypes (klass);
3497         mono_class_setup_supertypes (parent);
3498
3499         return klass->idepth >= parent->idepth &&
3500                 mono_class_get_generic_type_definition (klass->supertypes [parent->idepth - 1]) == parent;
3501 }
3502
3503 gboolean
3504 mono_class_check_vtable_constraints (MonoClass *klass, GList *in_setup)
3505 {
3506         MonoGenericInst *ginst;
3507         int i;
3508
3509         if (!mono_class_is_ginst (klass)) {
3510                 mono_class_setup_vtable_full (klass, in_setup);
3511                 return !mono_class_has_failure (klass);
3512         }
3513
3514         mono_class_setup_vtable_full (mono_class_get_generic_type_definition (klass), in_setup);
3515         if (mono_class_set_type_load_failure_causedby_class (klass, mono_class_get_generic_class (klass)->container_class, "Failed to load generic definition vtable"))
3516                 return FALSE;
3517
3518         ginst = mono_class_get_generic_class (klass)->context.class_inst;
3519         for (i = 0; i < ginst->type_argc; ++i) {
3520                 MonoClass *arg;
3521                 if (ginst->type_argv [i]->type != MONO_TYPE_GENERICINST)
3522                         continue;
3523                 arg = mono_class_from_mono_type (ginst->type_argv [i]);
3524                 /*Those 2 will be checked by mono_class_setup_vtable itself*/
3525                 if (mono_class_has_gtd_parent (klass, arg) || mono_class_has_gtd_parent (arg, klass))
3526                         continue;
3527                 if (!mono_class_check_vtable_constraints (arg, in_setup)) {
3528                         mono_class_set_type_load_failure (klass, "Failed to load generic parameter %d", i);
3529                         return FALSE;
3530                 }
3531         }
3532         return TRUE;
3533 }
3534  
3535 /*
3536  * mono_class_setup_vtable:
3537  *
3538  *   Creates the generic vtable of CLASS.
3539  * Initializes the following fields in MonoClass:
3540  * - vtable
3541  * - vtable_size
3542  * Plus all the fields initialized by setup_interface_offsets ().
3543  * If there is an error during vtable construction, klass->has_failure
3544  * is set and details are stored in a MonoErrorBoxed.
3545  *
3546  * LOCKING: Acquires the loader lock.
3547  */
3548 void
3549 mono_class_setup_vtable (MonoClass *klass)
3550 {
3551         mono_class_setup_vtable_full (klass, NULL);
3552 }
3553
3554 static void
3555 mono_class_setup_vtable_full (MonoClass *klass, GList *in_setup)
3556 {
3557         MonoError error;
3558         MonoMethod **overrides;
3559         MonoGenericContext *context;
3560         guint32 type_token;
3561         int onum = 0;
3562         gboolean ok = TRUE;
3563
3564         if (klass->vtable)
3565                 return;
3566
3567         if (MONO_CLASS_IS_INTERFACE (klass)) {
3568                 /* This sets method->slot for all methods if this is an interface */
3569                 mono_class_setup_methods (klass);
3570                 return;
3571         }
3572
3573         if (mono_class_has_failure (klass))
3574                 return;
3575
3576         if (g_list_find (in_setup, klass))
3577                 return;
3578
3579         mono_loader_lock ();
3580
3581         if (klass->vtable) {
3582                 mono_loader_unlock ();
3583                 return;
3584         }
3585
3586         UnlockedIncrement (&mono_stats.generic_vtable_count);
3587         in_setup = g_list_prepend (in_setup, klass);
3588
3589         if (mono_class_is_ginst (klass)) {
3590                 if (!mono_class_check_vtable_constraints (klass, in_setup)) {
3591                         mono_loader_unlock ();
3592                         g_list_remove (in_setup, klass);
3593                         return;
3594                 }
3595
3596                 context = mono_class_get_context (klass);
3597                 type_token = mono_class_get_generic_class (klass)->container_class->type_token;
3598         } else {
3599                 context = (MonoGenericContext *) mono_class_try_get_generic_container (klass); //FIXME is this a case of a try?
3600                 type_token = klass->type_token;
3601         }
3602
3603         if (image_is_dynamic (klass->image)) {
3604                 /* Generic instances can have zero method overrides without causing any harm.
3605                  * This is true since we don't do layout all over again for them, we simply inflate
3606                  * the layout of the parent.
3607                  */
3608                 mono_reflection_get_dynamic_overrides (klass, &overrides, &onum, &error);
3609                 if (!is_ok (&error)) {
3610                         mono_loader_unlock ();
3611                         g_list_remove (in_setup, klass);
3612                         mono_class_set_type_load_failure (klass, "Could not load list of method overrides due to %s", mono_error_get_message (&error));
3613                         mono_error_cleanup (&error);
3614                         return;
3615                 }
3616         } else {
3617                 /* The following call fails if there are missing methods in the type */
3618                 /* FIXME it's probably a good idea to avoid this for generic instances. */
3619                 ok = mono_class_get_overrides_full (klass->image, type_token, &overrides, &onum, context);
3620         }
3621
3622         if (ok)
3623                 mono_class_setup_vtable_general (klass, overrides, onum, in_setup);
3624         else
3625                 mono_class_set_type_load_failure (klass, "Could not load list of method overrides");
3626                 
3627         g_free (overrides);
3628
3629         mono_loader_unlock ();
3630         g_list_remove (in_setup, klass);
3631
3632         return;
3633 }
3634
3635 #define DEBUG_INTERFACE_VTABLE_CODE 0
3636 #define TRACE_INTERFACE_VTABLE_CODE 0
3637 #define VERIFY_INTERFACE_VTABLE_CODE 0
3638 #define VTABLE_SELECTOR (1)
3639
3640 #if (TRACE_INTERFACE_VTABLE_CODE|DEBUG_INTERFACE_VTABLE_CODE)
3641 #define DEBUG_INTERFACE_VTABLE(stmt) do {\
3642         if (!(VTABLE_SELECTOR)) break; \
3643         stmt;\
3644 } while (0)
3645 #else
3646 #define DEBUG_INTERFACE_VTABLE(stmt)
3647 #endif
3648
3649 #if TRACE_INTERFACE_VTABLE_CODE
3650 #define TRACE_INTERFACE_VTABLE(stmt) do {\
3651         if (!(VTABLE_SELECTOR)) break; \
3652         stmt;\
3653 } while (0)
3654 #else
3655 #define TRACE_INTERFACE_VTABLE(stmt)
3656 #endif
3657
3658 #if VERIFY_INTERFACE_VTABLE_CODE
3659 #define VERIFY_INTERFACE_VTABLE(stmt) do {\
3660         if (!(VTABLE_SELECTOR)) break; \
3661         stmt;\
3662 } while (0)
3663 #else
3664 #define VERIFY_INTERFACE_VTABLE(stmt)
3665 #endif
3666
3667
3668 #if (TRACE_INTERFACE_VTABLE_CODE|DEBUG_INTERFACE_VTABLE_CODE)
3669 static char*
3670 mono_signature_get_full_desc (MonoMethodSignature *sig, gboolean include_namespace)
3671 {
3672         int i;
3673         char *result;
3674         GString *res = g_string_new ("");
3675         
3676         g_string_append_c (res, '(');
3677         for (i = 0; i < sig->param_count; ++i) {
3678                 if (i > 0)
3679                         g_string_append_c (res, ',');
3680                 mono_type_get_desc (res, sig->params [i], include_namespace);
3681         }
3682         g_string_append (res, ")=>");
3683         if (sig->ret != NULL) {
3684                 mono_type_get_desc (res, sig->ret, include_namespace);
3685         } else {
3686                 g_string_append (res, "NULL");
3687         }
3688         result = res->str;
3689         g_string_free (res, FALSE);
3690         return result;
3691 }
3692 static void
3693 print_method_signatures (MonoMethod *im, MonoMethod *cm) {
3694         char *im_sig = mono_signature_get_full_desc (mono_method_signature (im), TRUE);
3695         char *cm_sig = mono_signature_get_full_desc (mono_method_signature (cm), TRUE);
3696         printf ("(IM \"%s\", CM \"%s\")", im_sig, cm_sig);
3697         g_free (im_sig);
3698         g_free (cm_sig);
3699         
3700 }
3701
3702 #endif
3703 static gboolean
3704 is_wcf_hack_disabled (void)
3705 {
3706         static gboolean disabled;
3707         static gboolean inited = FALSE;
3708         if (!inited) {
3709                 disabled = g_hasenv ("MONO_DISABLE_WCF_HACK");
3710                 inited = TRUE;
3711         }
3712         return disabled;
3713 }
3714
3715 static gboolean
3716 check_interface_method_override (MonoClass *klass, MonoMethod *im, MonoMethod *cm, gboolean require_newslot, gboolean interface_is_explicitly_implemented_by_class, gboolean slot_is_empty)
3717 {
3718         MonoMethodSignature *cmsig, *imsig;
3719         if (strcmp (im->name, cm->name) == 0) {
3720                 if (! (cm->flags & METHOD_ATTRIBUTE_PUBLIC)) {
3721                         TRACE_INTERFACE_VTABLE (printf ("[PUBLIC CHECK FAILED]"));
3722                         return FALSE;
3723                 }
3724                 if (! slot_is_empty) {
3725                         if (require_newslot) {
3726                                 if (! interface_is_explicitly_implemented_by_class) {
3727                                         TRACE_INTERFACE_VTABLE (printf ("[NOT EXPLICIT IMPLEMENTATION IN FULL SLOT REFUSED]"));
3728                                         return FALSE;
3729                                 }
3730                                 if (! (cm->flags & METHOD_ATTRIBUTE_NEW_SLOT)) {
3731                                         TRACE_INTERFACE_VTABLE (printf ("[NEWSLOT CHECK FAILED]"));
3732                                         return FALSE;
3733                                 }
3734                         } else {
3735                                 TRACE_INTERFACE_VTABLE (printf ("[FULL SLOT REFUSED]"));
3736                         }
3737                 }
3738                 cmsig = mono_method_signature (cm);
3739                 imsig = mono_method_signature (im);
3740                 if (!cmsig || !imsig) {
3741                         mono_class_set_type_load_failure (klass, "Could not resolve the signature of a virtual method");
3742                         return FALSE;
3743                 }
3744
3745                 if (! mono_metadata_signature_equal (cmsig, imsig)) {
3746                         TRACE_INTERFACE_VTABLE (printf ("[SIGNATURE CHECK FAILED  "));
3747                         TRACE_INTERFACE_VTABLE (print_method_signatures (im, cm));
3748                         TRACE_INTERFACE_VTABLE (printf ("]"));
3749                         return FALSE;
3750                 }
3751                 TRACE_INTERFACE_VTABLE (printf ("[SECURITY CHECKS]"));
3752                 if (mono_security_core_clr_enabled ())
3753                         mono_security_core_clr_check_override (klass, cm, im);
3754
3755                 TRACE_INTERFACE_VTABLE (printf ("[NAME CHECK OK]"));
3756                 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (cm, im, NULL)) {
3757                         char *body_name = mono_method_full_name (cm, TRUE);
3758                         char *decl_name = mono_method_full_name (im, TRUE);
3759                         mono_class_set_type_load_failure (klass, "Method %s overrides method '%s' which is not accessible", body_name, decl_name);
3760                         g_free (body_name);
3761                         g_free (decl_name);
3762                         return FALSE;
3763                 }
3764
3765                 return TRUE;
3766         } else {
3767                 MonoClass *ic = im->klass;
3768                 const char *ic_name_space = ic->name_space;
3769                 const char *ic_name = ic->name;
3770                 char *subname;
3771                 
3772                 if (! require_newslot) {
3773                         TRACE_INTERFACE_VTABLE (printf ("[INJECTED METHOD REFUSED]"));
3774                         return FALSE;
3775                 }
3776                 if (cm->klass->rank == 0) {
3777                         TRACE_INTERFACE_VTABLE (printf ("[RANK CHECK FAILED]"));
3778                         return FALSE;
3779                 }
3780                 cmsig = mono_method_signature (cm);
3781                 imsig = mono_method_signature (im);
3782                 if (!cmsig || !imsig) {
3783                         mono_class_set_type_load_failure (klass, "Could not resolve the signature of a virtual method");
3784                         return FALSE;
3785                 }
3786
3787                 if (! mono_metadata_signature_equal (cmsig, imsig)) {
3788                         TRACE_INTERFACE_VTABLE (printf ("[(INJECTED) SIGNATURE CHECK FAILED  "));
3789                         TRACE_INTERFACE_VTABLE (print_method_signatures (im, cm));
3790                         TRACE_INTERFACE_VTABLE (printf ("]"));
3791                         return FALSE;
3792                 }
3793                 if (mono_class_get_image (ic) != mono_defaults.corlib) {
3794                         TRACE_INTERFACE_VTABLE (printf ("[INTERFACE CORLIB CHECK FAILED]"));
3795                         return FALSE;
3796                 }
3797                 if ((ic_name_space == NULL) || (strcmp (ic_name_space, "System.Collections.Generic") != 0)) {
3798                         TRACE_INTERFACE_VTABLE (printf ("[INTERFACE NAMESPACE CHECK FAILED]"));
3799                         return FALSE;
3800                 }
3801                 if ((ic_name == NULL) || ((strcmp (ic_name, "IEnumerable`1") != 0) && (strcmp (ic_name, "ICollection`1") != 0) && (strcmp (ic_name, "IList`1") != 0) && (strcmp (ic_name, "IReadOnlyList`1") != 0) && (strcmp (ic_name, "IReadOnlyCollection`1") != 0))) {
3802                         TRACE_INTERFACE_VTABLE (printf ("[INTERFACE NAME CHECK FAILED]"));
3803                         return FALSE;
3804                 }
3805                 
3806                 subname = strstr (cm->name, ic_name_space);
3807                 if (subname != cm->name) {
3808                         TRACE_INTERFACE_VTABLE (printf ("[ACTUAL NAMESPACE CHECK FAILED]"));
3809                         return FALSE;
3810                 }
3811                 subname += strlen (ic_name_space);
3812                 if (subname [0] != '.') {
3813                         TRACE_INTERFACE_VTABLE (printf ("[FIRST DOT CHECK FAILED]"));
3814                         return FALSE;
3815                 }
3816                 subname ++;
3817                 if (strstr (subname, ic_name) != subname) {
3818                         TRACE_INTERFACE_VTABLE (printf ("[ACTUAL CLASS NAME CHECK FAILED]"));
3819                         return FALSE;
3820                 }
3821                 subname += strlen (ic_name);
3822                 if (subname [0] != '.') {
3823                         TRACE_INTERFACE_VTABLE (printf ("[SECOND DOT CHECK FAILED]"));
3824                         return FALSE;
3825                 }
3826                 subname ++;
3827                 if (strcmp (subname, im->name) != 0) {
3828                         TRACE_INTERFACE_VTABLE (printf ("[METHOD NAME CHECK FAILED]"));
3829                         return FALSE;
3830                 }
3831                 
3832                 TRACE_INTERFACE_VTABLE (printf ("[SECURITY CHECKS (INJECTED CASE)]"));
3833                 if (mono_security_core_clr_enabled ())
3834                         mono_security_core_clr_check_override (klass, cm, im);
3835
3836                 TRACE_INTERFACE_VTABLE (printf ("[INJECTED INTERFACE CHECK OK]"));
3837                 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (cm, im, NULL)) {
3838                         char *body_name = mono_method_full_name (cm, TRUE);
3839                         char *decl_name = mono_method_full_name (im, TRUE);
3840                         mono_class_set_type_load_failure (klass, "Method %s overrides method '%s' which is not accessible", body_name, decl_name);
3841                         g_free (body_name);
3842                         g_free (decl_name);
3843                         return FALSE;
3844                 }
3845                 
3846                 return TRUE;
3847         }
3848 }
3849
3850 #if (TRACE_INTERFACE_VTABLE_CODE|DEBUG_INTERFACE_VTABLE_CODE)
3851 static void
3852 foreach_override (gpointer key, gpointer value, gpointer user_data) {
3853         MonoMethod *method = key;
3854         MonoMethod *override = value;
3855         MonoClass *method_class = mono_method_get_class (method);
3856         MonoClass *override_class = mono_method_get_class (override);
3857         
3858         printf ("  Method '%s.%s:%s' has override '%s.%s:%s'\n",
3859                         mono_class_get_namespace (method_class), mono_class_get_name (method_class), mono_method_get_name (method),
3860                         mono_class_get_namespace (override_class), mono_class_get_name (override_class), mono_method_get_name (override));
3861 }
3862 static void
3863 print_overrides (GHashTable *override_map, const char *message) {
3864         if (override_map) {
3865                 printf ("Override map \"%s\" START:\n", message);
3866                 g_hash_table_foreach (override_map, foreach_override, NULL);
3867                 printf ("Override map \"%s\" END.\n", message);
3868         } else {
3869                 printf ("Override map \"%s\" EMPTY.\n", message);
3870         }
3871 }
3872 static void
3873 print_vtable_full (MonoClass *klass, MonoMethod** vtable, int size, int first_non_interface_slot, const char *message, gboolean print_interfaces) {
3874         char *full_name = mono_type_full_name (&klass->byval_arg);
3875         int i;
3876         int parent_size;
3877         
3878         printf ("*** Vtable for class '%s' at \"%s\" (size %d)\n", full_name, message, size);
3879         
3880         if (print_interfaces) {
3881                 print_implemented_interfaces (klass);
3882                 printf ("* Interfaces for class '%s' done.\nStarting vtable (size %d):\n", full_name, size);
3883         }
3884         
3885         if (klass->parent) {
3886                 parent_size = klass->parent->vtable_size;
3887         } else {
3888                 parent_size = 0;
3889         }
3890         for (i = 0; i < size; ++i) {
3891                 MonoMethod *cm = vtable [i];
3892                 char *cm_name = cm ? mono_method_full_name (cm, TRUE) : g_strdup ("nil");
3893                 char newness = (i < parent_size) ? 'O' : ((i < first_non_interface_slot) ? 'I' : 'N');
3894
3895                 printf ("  [%c][%03d][INDEX %03d] %s [%p]\n", newness, i, cm ? cm->slot : - 1, cm_name, cm);
3896                 g_free (cm_name);
3897         }
3898
3899         g_free (full_name);
3900 }
3901 #endif
3902
3903 #if VERIFY_INTERFACE_VTABLE_CODE
3904 static int
3905 mono_method_try_get_vtable_index (MonoMethod *method)
3906 {
3907         if (method->is_inflated && (method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
3908                 MonoMethodInflated *imethod = (MonoMethodInflated*)method;
3909                 if (imethod->declaring->is_generic)
3910                         return imethod->declaring->slot;
3911         }
3912         return method->slot;
3913 }
3914
3915 static void
3916 mono_class_verify_vtable (MonoClass *klass)
3917 {
3918         int i, count;
3919         char *full_name = mono_type_full_name (&klass->byval_arg);
3920
3921         printf ("*** Verifying VTable of class '%s' \n", full_name);
3922         g_free (full_name);
3923         full_name = NULL;
3924         
3925         if (!klass->methods)
3926                 return;
3927
3928         count = mono_class_method_count (klass);
3929         for (i = 0; i < count; ++i) {
3930                 MonoMethod *cm = klass->methods [i];
3931                 int slot;
3932
3933                 if (!(cm->flags & METHOD_ATTRIBUTE_VIRTUAL))
3934                         continue;
3935
3936                 g_free (full_name);
3937                 full_name = mono_method_full_name (cm, TRUE);
3938
3939                 slot = mono_method_try_get_vtable_index (cm);
3940                 if (slot >= 0) {
3941                         if (slot >= klass->vtable_size) {
3942                                 printf ("\tInvalid method %s at index %d with vtable of length %d\n", full_name, slot, klass->vtable_size);
3943                                 continue;
3944                         }
3945
3946                         if (slot >= 0 && klass->vtable [slot] != cm && (klass->vtable [slot])) {
3947                                 char *other_name = klass->vtable [slot] ? mono_method_full_name (klass->vtable [slot], TRUE) : g_strdup ("[null value]");
3948                                 printf ("\tMethod %s has slot %d but vtable has %s on it\n", full_name, slot, other_name);
3949                                 g_free (other_name);
3950                         }
3951                 } else
3952                         printf ("\tVirtual method %s does n't have an assigned slot\n", full_name);
3953         }
3954         g_free (full_name);
3955 }
3956 #endif
3957
3958 static void
3959 print_unimplemented_interface_method_info (MonoClass *klass, MonoClass *ic, MonoMethod *im, int im_slot, MonoMethod **overrides, int onum)
3960 {
3961         int index, mcount;
3962         char *method_signature;
3963         char *type_name;
3964         
3965         for (index = 0; index < onum; ++index) {
3966                 mono_trace_warning (MONO_TRACE_TYPE, " at slot %d: %s (%d) overrides %s (%d)", im_slot, overrides [index*2+1]->name,
3967                          overrides [index*2+1]->slot, overrides [index*2]->name, overrides [index*2]->slot);
3968         }
3969         method_signature = mono_signature_get_desc (mono_method_signature (im), FALSE);
3970         type_name = mono_type_full_name (&klass->byval_arg);
3971         mono_trace_warning (MONO_TRACE_TYPE, "no implementation for interface method %s::%s(%s) in class %s",
3972                 mono_type_get_name (&ic->byval_arg), im->name, method_signature, type_name);
3973         g_free (method_signature);
3974         g_free (type_name);
3975         mono_class_setup_methods (klass);
3976         if (mono_class_has_failure (klass)) {
3977                 char *name = mono_type_get_full_name (klass);
3978                 mono_trace_warning (MONO_TRACE_TYPE, "CLASS %s failed to resolve methods", name);
3979                 g_free (name);
3980                 return;
3981         }
3982         mcount = mono_class_get_method_count (klass);
3983         for (index = 0; index < mcount; ++index) {
3984                 MonoMethod *cm = klass->methods [index];
3985                 method_signature = mono_signature_get_desc (mono_method_signature (cm), TRUE);
3986
3987                 mono_trace_warning (MONO_TRACE_TYPE, "METHOD %s(%s)", cm->name, method_signature);
3988                 g_free (method_signature);
3989         }
3990 }
3991
3992 static MonoMethod*
3993 mono_method_get_method_definition (MonoMethod *method)
3994 {
3995         while (method->is_inflated)
3996                 method = ((MonoMethodInflated*)method)->declaring;
3997         return method;
3998 }
3999
4000 static gboolean
4001 verify_class_overrides (MonoClass *klass, MonoMethod **overrides, int onum)
4002 {
4003         int i;
4004
4005         for (i = 0; i < onum; ++i) {
4006                 MonoMethod *decl = overrides [i * 2];
4007                 MonoMethod *body = overrides [i * 2 + 1];
4008
4009                 if (mono_class_get_generic_type_definition (body->klass) != mono_class_get_generic_type_definition (klass)) {
4010                         mono_class_set_type_load_failure (klass, "Method belongs to a different class than the declared one");
4011                         return FALSE;
4012                 }
4013
4014                 if (!(body->flags & METHOD_ATTRIBUTE_VIRTUAL) || (body->flags & METHOD_ATTRIBUTE_STATIC)) {
4015                         if (body->flags & METHOD_ATTRIBUTE_STATIC)
4016                                 mono_class_set_type_load_failure (klass, "Method must not be static to override a base type");
4017                         else
4018                                 mono_class_set_type_load_failure (klass, "Method must be virtual to override a base type");
4019                         return FALSE;
4020                 }
4021
4022                 if (!(decl->flags & METHOD_ATTRIBUTE_VIRTUAL) || (decl->flags & METHOD_ATTRIBUTE_STATIC)) {
4023                         if (body->flags & METHOD_ATTRIBUTE_STATIC)
4024                                 mono_class_set_type_load_failure (klass, "Cannot override a static method in a base type");
4025                         else
4026                                 mono_class_set_type_load_failure (klass, "Cannot override a non virtual method in a base type");
4027                         return FALSE;
4028                 }
4029
4030                 if (!mono_class_is_assignable_from_slow (decl->klass, klass)) {
4031                         mono_class_set_type_load_failure (klass, "Method overrides a class or interface that is not extended or implemented by this type");
4032                         return FALSE;
4033                 }
4034
4035                 body = mono_method_get_method_definition (body);
4036                 decl = mono_method_get_method_definition (decl);
4037
4038                 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (body, decl, NULL)) {
4039                         char *body_name = mono_method_full_name (body, TRUE);
4040                         char *decl_name = mono_method_full_name (decl, TRUE);
4041                         mono_class_set_type_load_failure (klass, "Method %s overrides method '%s' which is not accessible", body_name, decl_name);
4042                         g_free (body_name);
4043                         g_free (decl_name);
4044                         return FALSE;
4045                 }
4046         }
4047         return TRUE;
4048 }
4049
4050 static gboolean
4051 mono_class_need_stelemref_method (MonoClass *klass)
4052 {
4053         return klass->rank == 1 && MONO_TYPE_IS_REFERENCE (&klass->element_class->byval_arg);
4054 }
4055
4056 static int
4057 apply_override (MonoClass *klass, MonoMethod **vtable, MonoMethod *decl, MonoMethod *override)
4058 {
4059         int dslot;
4060         dslot = mono_method_get_vtable_slot (decl);
4061         if (dslot == -1) {
4062                 mono_class_set_type_load_failure (klass, "");
4063                 return FALSE;
4064         }
4065
4066         dslot += mono_class_interface_offset (klass, decl->klass);
4067         vtable [dslot] = override;
4068         if (!MONO_CLASS_IS_INTERFACE (override->klass)) {
4069                 /*
4070                  * If override from an interface, then it is an override of a default interface method,
4071                  * don't override its slot.
4072                  */
4073                 vtable [dslot]->slot = dslot;
4074         }
4075
4076         if (mono_security_core_clr_enabled ())
4077                 mono_security_core_clr_check_override (klass, vtable [dslot], decl);
4078
4079         return TRUE;
4080 }
4081
4082 /*
4083  * LOCKING: this is supposed to be called with the loader lock held.
4084  */
4085 void
4086 mono_class_setup_vtable_general (MonoClass *klass, MonoMethod **overrides, int onum, GList *in_setup)
4087 {
4088         MonoError error;
4089         MonoClass *k, *ic;
4090         MonoMethod **vtable = NULL;
4091         int i, max_vtsize = 0, cur_slot = 0;
4092         guint32 max_iid;
4093         GPtrArray *ifaces = NULL;
4094         GHashTable *override_map = NULL;
4095         MonoMethod *cm;
4096 #if (DEBUG_INTERFACE_VTABLE_CODE|TRACE_INTERFACE_VTABLE_CODE)
4097         int first_non_interface_slot;
4098 #endif
4099         GSList *virt_methods = NULL, *l;
4100         int stelemref_slot = 0;
4101
4102         if (klass->vtable)
4103                 return;
4104
4105         if (overrides && !verify_class_overrides (klass, overrides, onum))
4106                 return;
4107
4108         ifaces = mono_class_get_implemented_interfaces (klass, &error);
4109         if (!mono_error_ok (&error)) {
4110                 char *name = mono_type_get_full_name (klass);
4111                 mono_class_set_type_load_failure (klass, "Could not resolve %s interfaces due to %s", name, mono_error_get_message (&error));
4112                 g_free (name);
4113                 mono_error_cleanup (&error);
4114                 return;
4115         } else if (ifaces) {
4116                 for (i = 0; i < ifaces->len; i++) {
4117                         MonoClass *ic = (MonoClass *)g_ptr_array_index (ifaces, i);
4118                         max_vtsize += mono_class_get_method_count (ic);
4119                 }
4120                 g_ptr_array_free (ifaces, TRUE);
4121                 ifaces = NULL;
4122         }
4123         
4124         if (klass->parent) {
4125                 mono_class_init (klass->parent);
4126                 mono_class_setup_vtable_full (klass->parent, in_setup);
4127
4128                 if (mono_class_set_type_load_failure_causedby_class (klass, klass->parent, "Parent class failed to load"))
4129                         return;
4130
4131                 max_vtsize += klass->parent->vtable_size;
4132                 cur_slot = klass->parent->vtable_size;
4133         }
4134
4135         max_vtsize += mono_class_get_method_count (klass);
4136
4137         /*Array have a slot for stelemref*/
4138         if (mono_class_need_stelemref_method (klass)) {
4139                 stelemref_slot = cur_slot;
4140                 ++max_vtsize;
4141                 ++cur_slot;
4142         }
4143
4144         /* printf ("METAINIT %s.%s\n", klass->name_space, klass->name); */
4145
4146         cur_slot = setup_interface_offsets (klass, cur_slot, TRUE);
4147         if (cur_slot == -1) /*setup_interface_offsets fails the type.*/
4148                 return;
4149
4150         max_iid = klass->max_interface_id;
4151         DEBUG_INTERFACE_VTABLE (first_non_interface_slot = cur_slot);
4152
4153         /* Optimized version for generic instances */
4154         if (mono_class_is_ginst (klass)) {
4155                 MonoError error;
4156                 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
4157                 MonoMethod **tmp;
4158
4159                 mono_class_setup_vtable_full (gklass, in_setup);
4160                 if (mono_class_set_type_load_failure_causedby_class (klass, gklass, "Could not load generic definition"))
4161                         return;
4162
4163                 tmp = (MonoMethod **)mono_class_alloc0 (klass, sizeof (gpointer) * gklass->vtable_size);
4164                 klass->vtable_size = gklass->vtable_size;
4165                 for (i = 0; i < gklass->vtable_size; ++i)
4166                         if (gklass->vtable [i]) {
4167                                 MonoMethod *inflated = mono_class_inflate_generic_method_full_checked (gklass->vtable [i], klass, mono_class_get_context (klass), &error);
4168                                 if (!mono_error_ok (&error)) {
4169                                         mono_class_set_type_load_failure (klass, "Could not inflate method due to %s", mono_error_get_message (&error));
4170                                         mono_error_cleanup (&error);
4171                                         return;
4172                                 }
4173                                 tmp [i] = inflated;
4174                                 tmp [i]->slot = gklass->vtable [i]->slot;
4175                         }
4176                 mono_memory_barrier ();
4177                 klass->vtable = tmp;
4178
4179                 /* Have to set method->slot for abstract virtual methods */
4180                 if (klass->methods && gklass->methods) {
4181                         int mcount = mono_class_get_method_count (klass);
4182                         for (i = 0; i < mcount; ++i)
4183                                 if (klass->methods [i]->slot == -1)
4184                                         klass->methods [i]->slot = gklass->methods [i]->slot;
4185                 }
4186
4187                 return;
4188         }
4189
4190         vtable = (MonoMethod **)g_malloc0 (sizeof (gpointer) * max_vtsize);
4191
4192         if (klass->parent && klass->parent->vtable_size) {
4193                 MonoClass *parent = klass->parent;
4194                 int i;
4195                 
4196                 memcpy (vtable, parent->vtable,  sizeof (gpointer) * parent->vtable_size);
4197                 
4198                 // Also inherit parent interface vtables, just as a starting point.
4199                 // This is needed otherwise bug-77127.exe fails when the property methods
4200                 // have different names in the iterface and the class, because for child
4201                 // classes the ".override" information is not used anymore.
4202                 for (i = 0; i < parent->interface_offsets_count; i++) {
4203                         MonoClass *parent_interface = parent->interfaces_packed [i];
4204                         int interface_offset = mono_class_interface_offset (klass, parent_interface);
4205                         /*FIXME this is now dead code as this condition will never hold true.
4206                         Since interface offsets are inherited then the offset of an interface implemented
4207                         by a parent will never be the out of it's vtable boundary.
4208                         */
4209                         if (interface_offset >= parent->vtable_size) {
4210                                 int parent_interface_offset = mono_class_interface_offset (parent, parent_interface);
4211                                 int j;
4212                                 
4213                                 mono_class_setup_methods (parent_interface); /*FIXME Just kill this whole chunk of dead code*/
4214                                 TRACE_INTERFACE_VTABLE (printf ("    +++ Inheriting interface %s.%s\n", parent_interface->name_space, parent_interface->name));
4215                                 int mcount = mono_class_get_method_count (parent_interface);
4216                                 for (j = 0; j < mcount && !mono_class_has_failure (klass); j++) {
4217                                         vtable [interface_offset + j] = parent->vtable [parent_interface_offset + j];
4218                                         TRACE_INTERFACE_VTABLE (printf ("    --- Inheriting: [%03d][(%03d)+(%03d)] => [%03d][(%03d)+(%03d)]\n",
4219                                                         parent_interface_offset + j, parent_interface_offset, j,
4220                                                         interface_offset + j, interface_offset, j));
4221                                 }
4222                         }
4223                         
4224                 }
4225         }
4226
4227         /*Array have a slot for stelemref*/
4228         if (mono_class_need_stelemref_method (klass)) {
4229                 MonoMethod *method = mono_marshal_get_virtual_stelemref (klass);
4230                 if (!method->slot)
4231                         method->slot = stelemref_slot;
4232                 else
4233                         g_assert (method->slot == stelemref_slot);
4234
4235                 vtable [stelemref_slot] = method;
4236         }
4237
4238         TRACE_INTERFACE_VTABLE (print_vtable_full (klass, vtable, cur_slot, first_non_interface_slot, "AFTER INHERITING PARENT VTABLE", TRUE));
4239
4240         /* Process overrides from interface default methods */
4241         // FIXME: Ordering between interfaces
4242         for (int ifindex = 0; ifindex < klass->interface_offsets_count; ifindex++) {
4243                 ic = klass->interfaces_packed [ifindex];
4244
4245                 mono_class_setup_methods (ic);
4246                 if (mono_class_has_failure (ic))
4247                         goto fail;
4248
4249                 MonoMethod **iface_overrides;
4250                 int iface_onum;
4251                 gboolean ok = mono_class_get_overrides_full (ic->image, ic->type_token, &iface_overrides, &iface_onum, mono_class_get_context (ic));
4252                 if (ok) {
4253                         for (int i = 0; i < iface_onum; i++) {
4254                                 MonoMethod *decl = iface_overrides [i*2];
4255                                 MonoMethod *override = iface_overrides [i*2 + 1];
4256                                 if (!apply_override (klass, vtable, decl, override))
4257                                         goto fail;
4258
4259                                 if (!override_map)
4260                                         override_map = g_hash_table_new (mono_aligned_addr_hash, NULL);
4261                                 g_hash_table_insert (override_map, decl, override);
4262                         }
4263                         g_free (iface_overrides);
4264                 }
4265         }
4266
4267         /* override interface methods */
4268         for (i = 0; i < onum; i++) {
4269                 MonoMethod *decl = overrides [i*2];
4270                 MonoMethod *override = overrides [i*2 + 1];
4271                 if (MONO_CLASS_IS_INTERFACE (decl->klass)) {
4272                         if (!apply_override (klass, vtable, decl, override))
4273                                 goto fail;
4274
4275                         if (!override_map)
4276                                 override_map = g_hash_table_new (mono_aligned_addr_hash, NULL);
4277                         g_hash_table_insert (override_map, decl, override);
4278                 }
4279         }
4280
4281         TRACE_INTERFACE_VTABLE (print_overrides (override_map, "AFTER OVERRIDING INTERFACE METHODS"));
4282         TRACE_INTERFACE_VTABLE (print_vtable_full (klass, vtable, cur_slot, first_non_interface_slot, "AFTER OVERRIDING INTERFACE METHODS", FALSE));
4283
4284         /*
4285          * Create a list of virtual methods to avoid calling 
4286          * mono_class_get_virtual_methods () which is slow because of the metadata
4287          * optimization.
4288          */
4289         {
4290                 gpointer iter = NULL;
4291                 MonoMethod *cm;
4292
4293                 virt_methods = NULL;
4294                 while ((cm = mono_class_get_virtual_methods (klass, &iter))) {
4295                         virt_methods = g_slist_prepend (virt_methods, cm);
4296                 }
4297                 if (mono_class_has_failure (klass))
4298                         goto fail;
4299         }
4300         
4301         // Loop on all implemented interfaces...
4302         for (i = 0; i < klass->interface_offsets_count; i++) {
4303                 MonoClass *parent = klass->parent;
4304                 int ic_offset;
4305                 gboolean interface_is_explicitly_implemented_by_class;
4306                 int im_index;
4307                 
4308                 ic = klass->interfaces_packed [i];
4309                 ic_offset = mono_class_interface_offset (klass, ic);
4310
4311                 mono_class_setup_methods (ic);
4312                 if (mono_class_has_failure (ic))
4313                         goto fail;
4314                 
4315                 // Check if this interface is explicitly implemented (instead of just inherited)
4316                 if (parent != NULL) {
4317                         int implemented_interfaces_index;
4318                         interface_is_explicitly_implemented_by_class = FALSE;
4319                         for (implemented_interfaces_index = 0; implemented_interfaces_index < klass->interface_count; implemented_interfaces_index++) {
4320                                 if (ic == klass->interfaces [implemented_interfaces_index]) {
4321                                         interface_is_explicitly_implemented_by_class = TRUE;
4322                                         break;
4323                                 }
4324                         }
4325                 } else {
4326                         interface_is_explicitly_implemented_by_class = TRUE;
4327                 }
4328                 
4329                 // Loop on all interface methods...
4330                 int mcount = mono_class_get_method_count (ic);
4331                 for (im_index = 0; im_index < mcount; im_index++) {
4332                         MonoMethod *im = ic->methods [im_index];
4333                         int im_slot = ic_offset + im->slot;
4334                         MonoMethod *override_im = (override_map != NULL) ? (MonoMethod *)g_hash_table_lookup (override_map, im) : NULL;
4335                         
4336                         if (im->flags & METHOD_ATTRIBUTE_STATIC)
4337                                 continue;
4338
4339                         TRACE_INTERFACE_VTABLE (printf ("\tchecking iface method %s\n", mono_method_full_name (im,1)));
4340
4341                         // If there is an explicit implementation, just use it right away,
4342                         // otherwise look for a matching method
4343                         if (override_im == NULL) {
4344                                 int cm_index;
4345                                 MonoMethod *cm;
4346
4347                                 // First look for a suitable method among the class methods
4348                                 for (l = virt_methods; l; l = l->next) {
4349                                         cm = (MonoMethod *)l->data;
4350                                         TRACE_INTERFACE_VTABLE (printf ("    For slot %d ('%s'.'%s':'%s'), trying method '%s'.'%s':'%s'... [EXPLICIT IMPLEMENTATION = %d][SLOT IS NULL = %d]", im_slot, ic->name_space, ic->name, im->name, cm->klass->name_space, cm->klass->name, cm->name, interface_is_explicitly_implemented_by_class, (vtable [im_slot] == NULL)));
4351                                         if (check_interface_method_override (klass, im, cm, TRUE, interface_is_explicitly_implemented_by_class, (vtable [im_slot] == NULL))) {
4352                                                 TRACE_INTERFACE_VTABLE (printf ("[check ok]: ASSIGNING"));
4353                                                 vtable [im_slot] = cm;
4354                                                 /* Why do we need this? */
4355                                                 if (cm->slot < 0) {
4356                                                         cm->slot = im_slot;
4357                                                 }
4358                                         }
4359                                         TRACE_INTERFACE_VTABLE (printf ("\n"));
4360                                         if (mono_class_has_failure (klass))  /*Might be set by check_interface_method_override*/
4361                                                 goto fail;
4362                                 }
4363                                 
4364                                 // If the slot is still empty, look in all the inherited virtual methods...
4365                                 if ((vtable [im_slot] == NULL) && klass->parent != NULL) {
4366                                         MonoClass *parent = klass->parent;
4367                                         // Reverse order, so that last added methods are preferred
4368                                         for (cm_index = parent->vtable_size - 1; cm_index >= 0; cm_index--) {
4369                                                 MonoMethod *cm = parent->vtable [cm_index];
4370                                                 
4371                                                 TRACE_INTERFACE_VTABLE ((cm != NULL) && printf ("    For slot %d ('%s'.'%s':'%s'), trying (ancestor) method '%s'.'%s':'%s'... ", im_slot, ic->name_space, ic->name, im->name, cm->klass->name_space, cm->klass->name, cm->name));
4372                                                 if ((cm != NULL) && check_interface_method_override (klass, im, cm, FALSE, FALSE, TRUE)) {
4373                                                         TRACE_INTERFACE_VTABLE (printf ("[everything ok]: ASSIGNING"));
4374                                                         vtable [im_slot] = cm;
4375                                                         /* Why do we need this? */
4376                                                         if (cm->slot < 0) {
4377                                                                 cm->slot = im_slot;
4378                                                         }
4379                                                         break;
4380                                                 }
4381                                                 if (mono_class_has_failure (klass)) /*Might be set by check_interface_method_override*/
4382                                                         goto fail;
4383                                                 TRACE_INTERFACE_VTABLE ((cm != NULL) && printf ("\n"));
4384                                         }
4385                                 }
4386
4387                                 if (vtable [im_slot] == NULL) {
4388                                         if (!(im->flags & METHOD_ATTRIBUTE_ABSTRACT)) {
4389                                                 TRACE_INTERFACE_VTABLE (printf ("    Using default iface method %s.\n", mono_method_full_name (im, 1)));
4390                                                 vtable [im_slot] = im;
4391                                         }
4392                                 }
4393                         } else {
4394                                 g_assert (vtable [im_slot] == override_im);
4395                         }
4396                 }
4397         }
4398         
4399         // If the class is not abstract, check that all its interface slots are full.
4400         // The check is done here and not directly at the end of the loop above because
4401         // it can happen (for injected generic array interfaces) that the same slot is
4402         // processed multiple times (those interfaces have overlapping slots), and it
4403         // will not always be the first pass the one that fills the slot.
4404         if (!mono_class_is_abstract (klass)) {
4405                 for (i = 0; i < klass->interface_offsets_count; i++) {
4406                         int ic_offset;
4407                         int im_index;
4408                         
4409                         ic = klass->interfaces_packed [i];
4410                         ic_offset = mono_class_interface_offset (klass, ic);
4411                         
4412                         int mcount = mono_class_get_method_count (ic);
4413                         for (im_index = 0; im_index < mcount; im_index++) {
4414                                 MonoMethod *im = ic->methods [im_index];
4415                                 int im_slot = ic_offset + im->slot;
4416                                 
4417                                 if (im->flags & METHOD_ATTRIBUTE_STATIC)
4418                                         continue;
4419
4420                                 TRACE_INTERFACE_VTABLE (printf ("      [class is not abstract, checking slot %d for interface '%s'.'%s', method %s, slot check is %d]\n",
4421                                                 im_slot, ic->name_space, ic->name, im->name, (vtable [im_slot] == NULL)));
4422                                 if (vtable [im_slot] == NULL) {
4423                                         print_unimplemented_interface_method_info (klass, ic, im, im_slot, overrides, onum);
4424                                         goto fail;
4425                                 }
4426                         }
4427                 }
4428         }
4429
4430         TRACE_INTERFACE_VTABLE (print_vtable_full (klass, vtable, cur_slot, first_non_interface_slot, "AFTER SETTING UP INTERFACE METHODS", FALSE));
4431         for (l = virt_methods; l; l = l->next) {
4432                 cm = (MonoMethod *)l->data;
4433                 /*
4434                  * If the method is REUSE_SLOT, we must check in the
4435                  * base class for a method to override.
4436                  */
4437                 if (!(cm->flags & METHOD_ATTRIBUTE_NEW_SLOT)) {
4438                         int slot = -1;
4439                         for (k = klass->parent; k ; k = k->parent) {
4440                                 gpointer k_iter;
4441                                 MonoMethod *m1;
4442
4443                                 k_iter = NULL;
4444                                 while ((m1 = mono_class_get_virtual_methods (k, &k_iter))) {
4445                                         MonoMethodSignature *cmsig, *m1sig;
4446
4447                                         cmsig = mono_method_signature (cm);
4448                                         m1sig = mono_method_signature (m1);
4449
4450                                         if (!cmsig || !m1sig) {
4451                                                 /* FIXME proper error message */
4452                                                 mono_class_set_type_load_failure (klass, "");
4453                                                 return;
4454                                         }
4455
4456                                         if (!strcmp(cm->name, m1->name) && 
4457                                             mono_metadata_signature_equal (cmsig, m1sig)) {
4458
4459                                                 if (mono_security_core_clr_enabled ())
4460                                                         mono_security_core_clr_check_override (klass, cm, m1);
4461
4462                                                 slot = mono_method_get_vtable_slot (m1);
4463                                                 if (slot == -1)
4464                                                         goto fail;
4465
4466                                                 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (cm, m1, NULL)) {
4467                                                         char *body_name = mono_method_full_name (cm, TRUE);
4468                                                         char *decl_name = mono_method_full_name (m1, TRUE);
4469                                                         mono_class_set_type_load_failure (klass, "Method %s overrides method '%s' which is not accessible", body_name, decl_name);
4470                                                         g_free (body_name);
4471                                                         g_free (decl_name);
4472                                                         goto fail;
4473                                                 }
4474
4475                                                 g_assert (cm->slot < max_vtsize);
4476                                                 if (!override_map)
4477                                                         override_map = g_hash_table_new (mono_aligned_addr_hash, NULL);
4478                                                 TRACE_INTERFACE_VTABLE (printf ("adding iface override from %s [%p] to %s [%p]\n",
4479                                                         mono_method_full_name (m1, 1), m1,
4480                                                         mono_method_full_name (cm, 1), cm));
4481                                                 g_hash_table_insert (override_map, m1, cm);
4482                                                 break;
4483                                         }
4484                                 }
4485                                 if (mono_class_has_failure (k))
4486                                         goto fail;
4487                                 
4488                                 if (slot >= 0) 
4489                                         break;
4490                         }
4491                         if (slot >= 0)
4492                                 cm->slot = slot;
4493                 }
4494
4495                 /*Non final newslot methods must be given a non-interface vtable slot*/
4496                 if ((cm->flags & METHOD_ATTRIBUTE_NEW_SLOT) && !(cm->flags & METHOD_ATTRIBUTE_FINAL) && cm->slot >= 0)
4497                         cm->slot = -1;
4498
4499                 if (cm->slot < 0)
4500                         cm->slot = cur_slot++;
4501
4502                 if (!(cm->flags & METHOD_ATTRIBUTE_ABSTRACT))
4503                         vtable [cm->slot] = cm;
4504         }
4505
4506         /* override non interface methods */
4507         for (i = 0; i < onum; i++) {
4508                 MonoMethod *decl = overrides [i*2];
4509                 if (!MONO_CLASS_IS_INTERFACE (decl->klass)) {
4510                         g_assert (decl->slot != -1);
4511                         vtable [decl->slot] = overrides [i*2 + 1];
4512                         overrides [i * 2 + 1]->slot = decl->slot;
4513                         if (!override_map)
4514                                 override_map = g_hash_table_new (mono_aligned_addr_hash, NULL);
4515                         TRACE_INTERFACE_VTABLE (printf ("adding explicit override from %s [%p] to %s [%p]\n", 
4516                                 mono_method_full_name (decl, 1), decl,
4517                                 mono_method_full_name (overrides [i * 2 + 1], 1), overrides [i * 2 + 1]));
4518                         g_hash_table_insert (override_map, decl, overrides [i * 2 + 1]);
4519
4520                         if (mono_security_core_clr_enabled ())
4521                                 mono_security_core_clr_check_override (klass, vtable [decl->slot], decl);
4522                 }
4523         }
4524
4525         /*
4526          * If a method occupies more than one place in the vtable, and it is
4527          * overriden, then change the other occurances too.
4528          */
4529         if (override_map) {
4530                 MonoMethod *cm;
4531
4532                 for (i = 0; i < max_vtsize; ++i)
4533                         if (vtable [i]) {
4534                                 TRACE_INTERFACE_VTABLE (printf ("checking slot %d method %s[%p] for overrides\n", i, mono_method_full_name (vtable [i], 1), vtable [i]));
4535
4536                                 cm = (MonoMethod *)g_hash_table_lookup (override_map, vtable [i]);
4537                                 if (cm)
4538                                         vtable [i] = cm;
4539                         }
4540
4541                 g_hash_table_destroy (override_map);
4542                 override_map = NULL;
4543         }
4544
4545         g_slist_free (virt_methods);
4546         virt_methods = NULL;
4547
4548         g_assert (cur_slot <= max_vtsize);
4549
4550         /* Ensure that all vtable slots are filled with concrete instance methods */
4551         if (!mono_class_is_abstract (klass)) {
4552                 for (i = 0; i < cur_slot; ++i) {
4553                         if (vtable [i] == NULL || (vtable [i]->flags & (METHOD_ATTRIBUTE_ABSTRACT | METHOD_ATTRIBUTE_STATIC))) {
4554                                 char *type_name = mono_type_get_full_name (klass);
4555                                 char *method_name = vtable [i] ? mono_method_full_name (vtable [i], TRUE) : g_strdup ("none");
4556                                 mono_class_set_type_load_failure (klass, "Type %s has invalid vtable method slot %d with method %s", type_name, i, method_name);
4557                                 g_free (type_name);
4558                                 g_free (method_name);
4559                                 g_free (vtable);
4560                                 return;
4561                         }
4562                 }
4563         }
4564
4565         if (mono_class_is_ginst (klass)) {
4566                 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
4567
4568                 mono_class_init (gklass);
4569
4570                 klass->vtable_size = MAX (gklass->vtable_size, cur_slot);
4571         } else {
4572                 /* Check that the vtable_size value computed in mono_class_init () is correct */
4573                 if (klass->vtable_size)
4574                         g_assert (cur_slot == klass->vtable_size);
4575                 klass->vtable_size = cur_slot;
4576         }
4577
4578         /* Try to share the vtable with our parent. */
4579         if (klass->parent && (klass->parent->vtable_size == klass->vtable_size) && (memcmp (klass->parent->vtable, vtable, sizeof (gpointer) * klass->vtable_size) == 0)) {
4580                 mono_memory_barrier ();
4581                 klass->vtable = klass->parent->vtable;
4582         } else {
4583                 MonoMethod **tmp = (MonoMethod **)mono_class_alloc0 (klass, sizeof (gpointer) * klass->vtable_size);
4584                 memcpy (tmp, vtable,  sizeof (gpointer) * klass->vtable_size);
4585                 mono_memory_barrier ();
4586                 klass->vtable = tmp;
4587         }
4588
4589         DEBUG_INTERFACE_VTABLE (print_vtable_full (klass, klass->vtable, klass->vtable_size, first_non_interface_slot, "FINALLY", FALSE));
4590         if (mono_print_vtable) {
4591                 int icount = 0;
4592
4593                 print_implemented_interfaces (klass);
4594                 
4595                 for (i = 0; i <= max_iid; i++)
4596                         if (MONO_CLASS_IMPLEMENTS_INTERFACE (klass, i))
4597                                 icount++;
4598
4599                 printf ("VTable %s (vtable entries = %d, interfaces = %d)\n", mono_type_full_name (&klass->byval_arg),
4600                         klass->vtable_size, icount);
4601
4602                 for (i = 0; i < cur_slot; ++i) {
4603                         MonoMethod *cm;
4604                
4605                         cm = vtable [i];
4606                         if (cm) {
4607                                 printf ("  slot assigned: %03d, slot index: %03d %s\n", i, cm->slot,
4608                                         mono_method_full_name (cm, TRUE));
4609                         }
4610                 }
4611
4612
4613                 if (icount) {
4614                         printf ("Interfaces %s.%s (max_iid = %d)\n", klass->name_space,
4615                                 klass->name, max_iid);
4616         
4617                         for (i = 0; i < klass->interface_count; i++) {
4618                                 ic = klass->interfaces [i];
4619                                 printf ("  slot offset: %03d, method count: %03d, iid: %03d %s\n",  
4620                                         mono_class_interface_offset (klass, ic),
4621                                         count_virtual_methods (ic), ic->interface_id, mono_type_full_name (&ic->byval_arg));
4622                         }
4623
4624                         for (k = klass->parent; k ; k = k->parent) {
4625                                 for (i = 0; i < k->interface_count; i++) {
4626                                         ic = k->interfaces [i]; 
4627                                         printf ("  parent slot offset: %03d, method count: %03d, iid: %03d %s\n",  
4628                                                 mono_class_interface_offset (klass, ic),
4629                                                 count_virtual_methods (ic), ic->interface_id, mono_type_full_name (&ic->byval_arg));
4630                                 }
4631                         }
4632                 }
4633         }
4634
4635         g_free (vtable);
4636
4637         VERIFY_INTERFACE_VTABLE (mono_class_verify_vtable (klass));
4638         return;
4639
4640 fail:
4641         {
4642         char *name = mono_type_get_full_name (klass);
4643         mono_class_set_type_load_failure (klass, "VTable setup of type %s failed", name);
4644         g_free (name);
4645         g_free (vtable);
4646         if (override_map)
4647                 g_hash_table_destroy (override_map);
4648         if (virt_methods)
4649                 g_slist_free (virt_methods);
4650         }
4651 }
4652
4653 /*
4654  * mono_method_get_vtable_slot:
4655  *
4656  *   Returns method->slot, computing it if neccesary. Return -1 on failure.
4657  * LOCKING: Acquires the loader lock.
4658  *
4659  * FIXME Use proper MonoError machinery here.
4660  */
4661 int
4662 mono_method_get_vtable_slot (MonoMethod *method)
4663 {
4664         if (method->slot == -1) {
4665                 mono_class_setup_vtable (method->klass);
4666                 if (mono_class_has_failure (method->klass))
4667                         return -1;
4668                 if (method->slot == -1) {
4669                         MonoClass *gklass;
4670                         int i, mcount;
4671
4672                         if (!mono_class_is_ginst (method->klass)) {
4673                                 g_assert (method->is_inflated);
4674                                 return mono_method_get_vtable_slot (((MonoMethodInflated*)method)->declaring);
4675                         }
4676
4677                         /* This can happen for abstract methods of generic instances due to the shortcut code in mono_class_setup_vtable_general (). */
4678                         g_assert (mono_class_is_ginst (method->klass));
4679                         gklass = mono_class_get_generic_class (method->klass)->container_class;
4680                         mono_class_setup_methods (method->klass);
4681                         g_assert (method->klass->methods);
4682                         mcount = mono_class_get_method_count (method->klass);
4683                         for (i = 0; i < mcount; ++i) {
4684                                 if (method->klass->methods [i] == method)
4685                                         break;
4686                         }
4687                         g_assert (i < mcount);
4688                         g_assert (gklass->methods);
4689                         method->slot = gklass->methods [i]->slot;
4690                 }
4691                 g_assert (method->slot != -1);
4692         }
4693         return method->slot;
4694 }
4695
4696 /**
4697  * mono_method_get_vtable_index:
4698  * \param method a method
4699  *
4700  * Returns the index into the runtime vtable to access the method or,
4701  * in the case of a virtual generic method, the virtual generic method
4702  * thunk. Returns -1 on failure.
4703  *
4704  * FIXME Use proper MonoError machinery here.
4705  */
4706 int
4707 mono_method_get_vtable_index (MonoMethod *method)
4708 {
4709         if (method->is_inflated && (method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
4710                 MonoMethodInflated *imethod = (MonoMethodInflated*)method;
4711                 if (imethod->declaring->is_generic)
4712                         return mono_method_get_vtable_slot (imethod->declaring);
4713         }
4714         return mono_method_get_vtable_slot (method);
4715 }
4716
4717 static MonoMethod *default_ghc = NULL;
4718 static MonoMethod *default_finalize = NULL;
4719 static int finalize_slot = -1;
4720 static int ghc_slot = -1;
4721
4722 static void
4723 initialize_object_slots (MonoClass *klass)
4724 {
4725         int i;
4726         if (default_ghc)
4727                 return;
4728         if (klass == mono_defaults.object_class) {
4729                 mono_class_setup_vtable (klass);
4730                 for (i = 0; i < klass->vtable_size; ++i) {
4731                         MonoMethod *cm = klass->vtable [i];
4732        
4733                         if (!strcmp (cm->name, "GetHashCode"))
4734                                 ghc_slot = i;
4735                         else if (!strcmp (cm->name, "Finalize"))
4736                                 finalize_slot = i;
4737                 }
4738
4739                 g_assert (ghc_slot > 0);
4740                 default_ghc = klass->vtable [ghc_slot];
4741
4742                 g_assert (finalize_slot > 0);
4743                 default_finalize = klass->vtable [finalize_slot];
4744         }
4745 }
4746
4747 typedef struct {
4748         MonoMethod *array_method;
4749         char *name;
4750 } GenericArrayMethodInfo;
4751
4752 static int generic_array_method_num = 0;
4753 static GenericArrayMethodInfo *generic_array_method_info = NULL;
4754
4755 static int
4756 generic_array_methods (MonoClass *klass)
4757 {
4758         int i, count_generic = 0, mcount;
4759         GList *list = NULL, *tmp;
4760         if (generic_array_method_num)
4761                 return generic_array_method_num;
4762         mono_class_setup_methods (klass->parent); /*This is setting up System.Array*/
4763         g_assert (!mono_class_has_failure (klass->parent)); /*So hitting this assert is a huge problem*/
4764         mcount = mono_class_get_method_count (klass->parent);
4765         for (i = 0; i < mcount; i++) {
4766                 MonoMethod *m = klass->parent->methods [i];
4767                 if (!strncmp (m->name, "InternalArray__", 15)) {
4768                         count_generic++;
4769                         list = g_list_prepend (list, m);
4770                 }
4771         }
4772         list = g_list_reverse (list);
4773         generic_array_method_info = (GenericArrayMethodInfo *)mono_image_alloc (mono_defaults.corlib, sizeof (GenericArrayMethodInfo) * count_generic);
4774         i = 0;
4775         for (tmp = list; tmp; tmp = tmp->next) {
4776                 const char *mname, *iname;
4777                 gchar *name;
4778                 MonoMethod *m = (MonoMethod *)tmp->data;
4779                 const char *ireadonlylist_prefix = "InternalArray__IReadOnlyList_";
4780                 const char *ireadonlycollection_prefix = "InternalArray__IReadOnlyCollection_";
4781
4782                 generic_array_method_info [i].array_method = m;
4783                 if (!strncmp (m->name, "InternalArray__ICollection_", 27)) {
4784                         iname = "System.Collections.Generic.ICollection`1.";
4785                         mname = m->name + 27;
4786                 } else if (!strncmp (m->name, "InternalArray__IEnumerable_", 27)) {
4787                         iname = "System.Collections.Generic.IEnumerable`1.";
4788                         mname = m->name + 27;
4789                 } else if (!strncmp (m->name, ireadonlylist_prefix, strlen (ireadonlylist_prefix))) {
4790                         iname = "System.Collections.Generic.IReadOnlyList`1.";
4791                         mname = m->name + strlen (ireadonlylist_prefix);
4792                 } else if (!strncmp (m->name, ireadonlycollection_prefix, strlen (ireadonlycollection_prefix))) {
4793                         iname = "System.Collections.Generic.IReadOnlyCollection`1.";
4794                         mname = m->name + strlen (ireadonlycollection_prefix);
4795                 } else if (!strncmp (m->name, "InternalArray__", 15)) {
4796                         iname = "System.Collections.Generic.IList`1.";
4797                         mname = m->name + 15;
4798                 } else {
4799                         g_assert_not_reached ();
4800                 }
4801
4802                 name = (gchar *)mono_image_alloc (mono_defaults.corlib, strlen (iname) + strlen (mname) + 1);
4803                 strcpy (name, iname);
4804                 strcpy (name + strlen (iname), mname);
4805                 generic_array_method_info [i].name = name;
4806                 i++;
4807         }
4808         /*g_print ("array generic methods: %d\n", count_generic);*/
4809
4810         generic_array_method_num = count_generic;
4811         g_list_free (list);
4812         return generic_array_method_num;
4813 }
4814
4815 static void
4816 setup_generic_array_ifaces (MonoClass *klass, MonoClass *iface, MonoMethod **methods, int pos, GHashTable *cache)
4817 {
4818         MonoGenericContext tmp_context;
4819         int i;
4820
4821         tmp_context.class_inst = NULL;
4822         tmp_context.method_inst = mono_class_get_generic_class (iface)->context.class_inst;
4823         //g_print ("setting up array interface: %s\n", mono_type_get_name_full (&iface->byval_arg, 0));
4824
4825         for (i = 0; i < generic_array_method_num; i++) {
4826                 MonoError error;
4827                 MonoMethod *m = generic_array_method_info [i].array_method;
4828                 MonoMethod *inflated, *helper;
4829
4830                 inflated = mono_class_inflate_generic_method_checked (m, &tmp_context, &error);
4831                 mono_error_assert_ok (&error);
4832                 helper = g_hash_table_lookup (cache, inflated);
4833                 if (!helper) {
4834                         helper = mono_marshal_get_generic_array_helper (klass, generic_array_method_info [i].name, inflated);
4835                         g_hash_table_insert (cache, inflated, helper);
4836                 }
4837                 methods [pos ++] = helper;
4838         }
4839 }
4840
4841 static char*
4842 concat_two_strings_with_zero (MonoImage *image, const char *s1, const char *s2)
4843 {
4844         int null_length = strlen ("(null)");
4845         int len = (s1 ? strlen (s1) : null_length) + (s2 ? strlen (s2) : null_length) + 2;
4846         char *s = (char *)mono_image_alloc (image, len);
4847         int result;
4848
4849         result = g_snprintf (s, len, "%s%c%s", s1 ? s1 : "(null)", '\0', s2 ? s2 : "(null)");
4850         g_assert (result == len - 1);
4851
4852         return s;
4853 }
4854
4855 /**
4856  * mono_class_init:
4857  * \param klass the class to initialize
4858  *
4859  * Compute the \c instance_size, \c class_size and other infos that cannot be 
4860  * computed at \c mono_class_get time. Also compute vtable_size if possible. 
4861  * Initializes the following fields in \p klass:
4862  * - all the fields initialized by \c mono_class_init_sizes
4863  * - has_cctor
4864  * - ghcimpl
4865  * - inited
4866  *
4867  * LOCKING: Acquires the loader lock.
4868  *
4869  * \returns TRUE on success or FALSE if there was a problem in loading
4870  * the type (incorrect assemblies, missing assemblies, methods, etc).
4871  */
4872 gboolean
4873 mono_class_init (MonoClass *klass)
4874 {
4875         int i, vtable_size = 0, array_method_count = 0;
4876         MonoCachedClassInfo cached_info;
4877         gboolean has_cached_info;
4878         gboolean locked = FALSE;
4879         gboolean ghcimpl = FALSE;
4880         gboolean has_cctor = FALSE;
4881         int first_iface_slot = 0;
4882         
4883         g_assert (klass);
4884
4885         /* Double-checking locking pattern */
4886         if (klass->inited || mono_class_has_failure (klass))
4887                 return !mono_class_has_failure (klass);
4888
4889         /*g_print ("Init class %s\n", mono_type_get_full_name (klass));*/
4890
4891         /*
4892          * This function can recursively call itself.
4893          */
4894         GSList *init_list = (GSList *)mono_native_tls_get_value (init_pending_tls_id);
4895         if (g_slist_find (init_list, klass)) {
4896                 mono_class_set_type_load_failure (klass, "Recursive type definition detected");
4897                 goto leave_no_init_pending;
4898         }
4899         init_list = g_slist_prepend (init_list, klass);
4900         mono_native_tls_set_value (init_pending_tls_id, init_list);
4901
4902         /*
4903          * We want to avoid doing complicated work inside locks, so we compute all the required
4904          * information and write it to @klass inside a lock.
4905          */
4906
4907         if (mono_verifier_is_enabled_for_class (klass) && !mono_verifier_verify_class (klass)) {
4908                 mono_class_set_type_load_failure (klass, "%s", concat_two_strings_with_zero (klass->image, klass->name, klass->image->assembly_name));
4909                 goto leave;
4910         }
4911
4912         if (klass->byval_arg.type == MONO_TYPE_ARRAY || klass->byval_arg.type == MONO_TYPE_SZARRAY) {
4913                 MonoClass *element_class = klass->element_class;
4914                 if (!element_class->inited) 
4915                         mono_class_init (element_class);
4916                 if (mono_class_set_type_load_failure_causedby_class (klass, element_class, "Could not load array element class"))
4917                         goto leave;
4918         }
4919
4920         UnlockedIncrement (&mono_stats.initialized_class_count);
4921
4922         if (mono_class_is_ginst (klass) && !mono_class_get_generic_class (klass)->is_dynamic) {
4923                 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
4924
4925                 mono_class_init (gklass);
4926                 if (mono_class_set_type_load_failure_causedby_class (klass, gklass, "Generic Type Definition failed to init"))
4927                         goto leave;
4928
4929                 mono_class_setup_interface_id (klass);
4930         }
4931
4932         if (klass->parent && !klass->parent->inited)
4933                 mono_class_init (klass->parent);
4934
4935         has_cached_info = mono_class_get_cached_class_info (klass, &cached_info);
4936
4937         /* Compute instance size etc. */
4938         init_sizes_with_info (klass, has_cached_info ? &cached_info : NULL);
4939         if (mono_class_has_failure (klass))
4940                 goto leave;
4941
4942         mono_class_setup_supertypes (klass);
4943
4944         if (!default_ghc)
4945                 initialize_object_slots (klass);
4946
4947         /* 
4948          * Initialize the rest of the data without creating a generic vtable if possible.
4949          * If possible, also compute vtable_size, so mono_class_create_runtime_vtable () can
4950          * also avoid computing a generic vtable.
4951          */
4952         if (has_cached_info) {
4953                 /* AOT case */
4954                 vtable_size = cached_info.vtable_size;
4955                 ghcimpl = cached_info.ghcimpl;
4956                 has_cctor = cached_info.has_cctor;
4957         } else if (klass->rank == 1 && klass->byval_arg.type == MONO_TYPE_SZARRAY) {
4958                 /* SZARRAY can have 2 vtable layouts, with and without the stelemref method.
4959                  * The first slot if for array with.
4960                  */
4961                 static int szarray_vtable_size[2] = { 0 };
4962
4963                 int slot = MONO_TYPE_IS_REFERENCE (&klass->element_class->byval_arg) ? 0 : 1;
4964
4965                 /* SZARRAY case */
4966                 if (!szarray_vtable_size [slot]) {
4967                         mono_class_setup_vtable (klass);
4968                         szarray_vtable_size [slot] = klass->vtable_size;
4969                         vtable_size = klass->vtable_size;
4970                 } else {
4971                         vtable_size = szarray_vtable_size[slot];
4972                 }
4973         } else if (mono_class_is_ginst (klass) && !MONO_CLASS_IS_INTERFACE (klass)) {
4974                 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
4975
4976                 /* Generic instance case */
4977                 ghcimpl = gklass->ghcimpl;
4978                 has_cctor = gklass->has_cctor;
4979
4980                 mono_class_setup_vtable (gklass);
4981                 if (mono_class_set_type_load_failure_causedby_class (klass, gklass, "Generic type definition failed to init"))
4982                         goto leave;
4983
4984                 vtable_size = gklass->vtable_size;
4985         } else {
4986                 /* General case */
4987
4988                 /* ghcimpl is not currently used
4989                 klass->ghcimpl = 1;
4990                 if (klass->parent) {
4991                         MonoMethod *cmethod = klass->vtable [ghc_slot];
4992                         if (cmethod->is_inflated)
4993                                 cmethod = ((MonoMethodInflated*)cmethod)->declaring;
4994                         if (cmethod == default_ghc) {
4995                                 klass->ghcimpl = 0;
4996                         }
4997                 }
4998                 */
4999
5000                 /* C# doesn't allow interfaces to have cctors */
5001                 if (!MONO_CLASS_IS_INTERFACE (klass) || klass->image != mono_defaults.corlib) {
5002                         MonoMethod *cmethod = NULL;
5003
5004                         if (mono_class_is_ginst (klass)) {
5005                                 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
5006
5007                                 /* Generic instance case */
5008                                 ghcimpl = gklass->ghcimpl;
5009                                 has_cctor = gklass->has_cctor;
5010                         } else if (klass->type_token && !image_is_dynamic(klass->image)) {
5011                                 cmethod = find_method_in_metadata (klass, ".cctor", 0, METHOD_ATTRIBUTE_SPECIAL_NAME);
5012                                 /* The find_method function ignores the 'flags' argument */
5013                                 if (cmethod && (cmethod->flags & METHOD_ATTRIBUTE_SPECIAL_NAME))
5014                                         has_cctor = 1;
5015                         } else {
5016                                 mono_class_setup_methods (klass);
5017                                 if (mono_class_has_failure (klass))
5018                                         goto leave;
5019
5020                                 int mcount = mono_class_get_method_count (klass);
5021                                 for (i = 0; i < mcount; ++i) {
5022                                         MonoMethod *method = klass->methods [i];
5023                                         if ((method->flags & METHOD_ATTRIBUTE_SPECIAL_NAME) && 
5024                                                 (strcmp (".cctor", method->name) == 0)) {
5025                                                 has_cctor = 1;
5026                                                 break;
5027                                         }
5028                                 }
5029                         }
5030                 }
5031         }
5032
5033         if (klass->rank) {
5034                 array_method_count = 3 + (klass->rank > 1? 2: 1);
5035
5036                 if (klass->interface_count) {
5037                         int count_generic = generic_array_methods (klass);
5038                         array_method_count += klass->interface_count * count_generic;
5039                 }
5040         }
5041
5042         if (klass->parent) {
5043                 if (!klass->parent->vtable_size)
5044                         mono_class_setup_vtable (klass->parent);
5045                 if (mono_class_set_type_load_failure_causedby_class (klass, klass->parent, "Parent class vtable failed to initialize"))
5046                         goto leave;
5047                 g_assert (klass->parent->vtable_size);
5048                 first_iface_slot = klass->parent->vtable_size;
5049                 if (mono_class_need_stelemref_method (klass))
5050                         ++first_iface_slot;
5051         }
5052
5053         /*
5054          * Do the actual changes to @klass inside the loader lock
5055          */
5056         mono_loader_lock ();
5057         locked = TRUE;
5058
5059         if (klass->inited || mono_class_has_failure (klass)) {
5060                 mono_loader_unlock ();
5061                 /* Somebody might have gotten in before us */
5062                 return !mono_class_has_failure (klass);
5063         }
5064
5065         UnlockedIncrement (&mono_stats.initialized_class_count);
5066
5067         if (mono_class_is_ginst (klass) && !mono_class_get_generic_class (klass)->is_dynamic)
5068                 UnlockedIncrement (&mono_stats.generic_class_count);
5069
5070         if (mono_class_is_ginst (klass) || image_is_dynamic (klass->image) || !klass->type_token || (has_cached_info && !cached_info.has_nested_classes))
5071                 klass->nested_classes_inited = TRUE;
5072         klass->ghcimpl = ghcimpl;
5073         klass->has_cctor = has_cctor;
5074         if (vtable_size)
5075                 klass->vtable_size = vtable_size;
5076         if (has_cached_info) {
5077                 klass->has_finalize = cached_info.has_finalize;
5078                 klass->has_finalize_inited = TRUE;
5079         }
5080         if (klass->rank)
5081                 mono_class_set_method_count (klass, array_method_count);
5082
5083         mono_loader_unlock ();
5084         locked = FALSE;
5085
5086         setup_interface_offsets (klass, first_iface_slot, TRUE);
5087
5088         if (mono_security_core_clr_enabled ())
5089                 mono_security_core_clr_check_inheritance (klass);
5090
5091         if (mono_class_is_ginst (klass) && !mono_verifier_class_is_valid_generic_instantiation (klass))
5092                 mono_class_set_type_load_failure (klass, "Invalid generic instantiation");
5093
5094         goto leave;
5095
5096 leave:
5097         init_list = mono_native_tls_get_value (init_pending_tls_id);
5098         init_list = g_slist_remove (init_list, klass);
5099         mono_native_tls_set_value (init_pending_tls_id, init_list);
5100
5101 leave_no_init_pending:
5102         if (locked)
5103                 mono_loader_unlock ();
5104
5105         /* Leave this for last */
5106         mono_loader_lock ();
5107         klass->inited = 1;
5108         mono_loader_unlock ();
5109
5110         return !mono_class_has_failure (klass);
5111 }
5112
5113 /*
5114  * mono_class_has_finalizer:
5115  *
5116  *   Return whenever KLASS has a finalizer, initializing klass->has_finalizer in the
5117  * process.
5118  */
5119 gboolean
5120 mono_class_has_finalizer (MonoClass *klass)
5121 {
5122         gboolean has_finalize = FALSE;
5123
5124         if (klass->has_finalize_inited)
5125                 return klass->has_finalize;
5126
5127         /* Interfaces and valuetypes are not supposed to have finalizers */
5128         if (!(MONO_CLASS_IS_INTERFACE (klass) || klass->valuetype)) {
5129                 MonoMethod *cmethod = NULL;
5130
5131                 if (klass->rank == 1 && klass->byval_arg.type == MONO_TYPE_SZARRAY) {
5132                 } else if (mono_class_is_ginst (klass)) {
5133                         MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
5134
5135                         has_finalize = mono_class_has_finalizer (gklass);
5136                 } else if (klass->parent && klass->parent->has_finalize) {
5137                         has_finalize = TRUE;
5138                 } else {
5139                         if (klass->parent) {
5140                                 /*
5141                                  * Can't search in metadata for a method named Finalize, because that
5142                                  * ignores overrides.
5143                                  */
5144                                 mono_class_setup_vtable (klass);
5145                                 if (mono_class_has_failure (klass))
5146                                         cmethod = NULL;
5147                                 else
5148                                         cmethod = klass->vtable [finalize_slot];
5149                         }
5150
5151                         if (cmethod) {
5152                                 g_assert (klass->vtable_size > finalize_slot);
5153
5154                                 if (klass->parent) {
5155                                         if (cmethod->is_inflated)
5156                                                 cmethod = ((MonoMethodInflated*)cmethod)->declaring;
5157                                         if (cmethod != default_finalize)
5158                                                 has_finalize = TRUE;
5159                                 }
5160                         }
5161                 }
5162         }
5163
5164         mono_loader_lock ();
5165         if (!klass->has_finalize_inited) {
5166                 klass->has_finalize = has_finalize ? 1 : 0;
5167
5168                 mono_memory_barrier ();
5169                 klass->has_finalize_inited = TRUE;
5170         }
5171         mono_loader_unlock ();
5172
5173         return klass->has_finalize;
5174 }
5175
5176 gboolean
5177 mono_is_corlib_image (MonoImage *image)
5178 {
5179         return image == mono_defaults.corlib;
5180 }
5181
5182 /*
5183  * LOCKING: this assumes the loader lock is held
5184  */
5185 void
5186 mono_class_setup_mono_type (MonoClass *klass)
5187 {
5188         const char *name = klass->name;
5189         const char *nspace = klass->name_space;
5190         gboolean is_corlib = mono_is_corlib_image (klass->image);
5191
5192         klass->this_arg.byref = 1;
5193         klass->this_arg.data.klass = klass;
5194         klass->this_arg.type = MONO_TYPE_CLASS;
5195         klass->byval_arg.data.klass = klass;
5196         klass->byval_arg.type = MONO_TYPE_CLASS;
5197
5198         if (is_corlib && !strcmp (nspace, "System")) {
5199                 if (!strcmp (name, "ValueType")) {
5200                         /*
5201                          * do not set the valuetype bit for System.ValueType.
5202                          * klass->valuetype = 1;
5203                          */
5204                         klass->blittable = TRUE;
5205                 } else if (!strcmp (name, "Enum")) {
5206                         /*
5207                          * do not set the valuetype bit for System.Enum.
5208                          * klass->valuetype = 1;
5209                          */
5210                         klass->valuetype = 0;
5211                         klass->enumtype = 0;
5212                 } else if (!strcmp (name, "Object")) {
5213                         klass->byval_arg.type = MONO_TYPE_OBJECT;
5214                         klass->this_arg.type = MONO_TYPE_OBJECT;
5215                 } else if (!strcmp (name, "String")) {
5216                         klass->byval_arg.type = MONO_TYPE_STRING;
5217                         klass->this_arg.type = MONO_TYPE_STRING;
5218                 } else if (!strcmp (name, "TypedReference")) {
5219                         klass->byval_arg.type = MONO_TYPE_TYPEDBYREF;
5220                         klass->this_arg.type = MONO_TYPE_TYPEDBYREF;
5221                 }
5222         }
5223
5224         if (klass->valuetype) {
5225                 int t = MONO_TYPE_VALUETYPE;
5226
5227                 if (is_corlib && !strcmp (nspace, "System")) {
5228                         switch (*name) {
5229                         case 'B':
5230                                 if (!strcmp (name, "Boolean")) {
5231                                         t = MONO_TYPE_BOOLEAN;
5232                                 } else if (!strcmp(name, "Byte")) {
5233                                         t = MONO_TYPE_U1;
5234                                         klass->blittable = TRUE;                                                
5235                                 }
5236                                 break;
5237                         case 'C':
5238                                 if (!strcmp (name, "Char")) {
5239                                         t = MONO_TYPE_CHAR;
5240                                 }
5241                                 break;
5242                         case 'D':
5243                                 if (!strcmp (name, "Double")) {
5244                                         t = MONO_TYPE_R8;
5245                                         klass->blittable = TRUE;                                                
5246                                 }
5247                                 break;
5248                         case 'I':
5249                                 if (!strcmp (name, "Int32")) {
5250                                         t = MONO_TYPE_I4;
5251                                         klass->blittable = TRUE;
5252                                 } else if (!strcmp(name, "Int16")) {
5253                                         t = MONO_TYPE_I2;
5254                                         klass->blittable = TRUE;
5255                                 } else if (!strcmp(name, "Int64")) {
5256                                         t = MONO_TYPE_I8;
5257                                         klass->blittable = TRUE;
5258                                 } else if (!strcmp(name, "IntPtr")) {
5259                                         t = MONO_TYPE_I;
5260                                         klass->blittable = TRUE;
5261                                 }
5262                                 break;
5263                         case 'S':
5264                                 if (!strcmp (name, "Single")) {
5265                                         t = MONO_TYPE_R4;
5266                                         klass->blittable = TRUE;                                                
5267                                 } else if (!strcmp(name, "SByte")) {
5268                                         t = MONO_TYPE_I1;
5269                                         klass->blittable = TRUE;
5270                                 }
5271                                 break;
5272                         case 'U':
5273                                 if (!strcmp (name, "UInt32")) {
5274                                         t = MONO_TYPE_U4;
5275                                         klass->blittable = TRUE;
5276                                 } else if (!strcmp(name, "UInt16")) {
5277                                         t = MONO_TYPE_U2;
5278                                         klass->blittable = TRUE;
5279                                 } else if (!strcmp(name, "UInt64")) {
5280                                         t = MONO_TYPE_U8;
5281                                         klass->blittable = TRUE;
5282                                 } else if (!strcmp(name, "UIntPtr")) {
5283                                         t = MONO_TYPE_U;
5284                                         klass->blittable = TRUE;
5285                                 }
5286                                 break;
5287                         case 'T':
5288                                 if (!strcmp (name, "TypedReference")) {
5289                                         t = MONO_TYPE_TYPEDBYREF;
5290                                         klass->blittable = TRUE;
5291                                 }
5292                                 break;
5293                         case 'V':
5294                                 if (!strcmp (name, "Void")) {
5295                                         t = MONO_TYPE_VOID;
5296                                 }
5297                                 break;
5298                         default:
5299                                 break;
5300                         }
5301                 }
5302                 klass->byval_arg.type = (MonoTypeEnum)t;
5303                 klass->this_arg.type = (MonoTypeEnum)t;
5304         }
5305
5306         if (MONO_CLASS_IS_INTERFACE (klass)) {
5307                 klass->interface_id = mono_get_unique_iid (klass);
5308
5309                 if (is_corlib && !strcmp (nspace, "System.Collections.Generic")) {
5310                         //FIXME IEnumerator needs to be special because GetEnumerator uses magic under the hood
5311                     /* FIXME: System.Array/InternalEnumerator don't need all this interface fabrication machinery.
5312                     * MS returns diferrent types based on which instance is called. For example:
5313                     *   object obj = new byte[10][];
5314                     *   Type a = ((IEnumerable<byte[]>)obj).GetEnumerator ().GetType ();
5315                     *   Type b = ((IEnumerable<IList<byte>>)obj).GetEnumerator ().GetType ();
5316                     *   a != b ==> true
5317                         */
5318                         if (!strcmp (name, "IList`1") || !strcmp (name, "ICollection`1") || !strcmp (name, "IEnumerable`1") || !strcmp (name, "IEnumerator`1"))
5319                                 klass->is_array_special_interface = 1;
5320                 }
5321         }
5322 }
5323
5324 #ifndef DISABLE_COM
5325 /*
5326  * COM initialization is delayed until needed.
5327  * However when a [ComImport] attribute is present on a type it will trigger
5328  * the initialization. This is not a problem unless the BCL being executed 
5329  * lacks the types that COM depends on (e.g. Variant on Silverlight).
5330  */
5331 static void
5332 init_com_from_comimport (MonoClass *klass)
5333 {
5334         /* we don't always allow COM initialization under the CoreCLR (e.g. Moonlight does not require it) */
5335         if (mono_security_core_clr_enabled ()) {
5336                 /* but some other CoreCLR user could requires it for their platform (i.e. trusted) code */
5337                 if (!mono_security_core_clr_determine_platform_image (klass->image)) {
5338                         /* but it can not be made available for application (i.e. user code) since all COM calls
5339                          * are considered native calls. In this case we fail with a TypeLoadException (just like
5340                          * Silverlight 2 does */
5341                         mono_class_set_type_load_failure (klass, "");
5342                         return;
5343                 }
5344         }
5345
5346         /* FIXME : we should add an extra checks to ensure COM can be initialized properly before continuing */
5347 }
5348 #endif /*DISABLE_COM*/
5349
5350 /*
5351  * LOCKING: this assumes the loader lock is held
5352  */
5353 void
5354 mono_class_setup_parent (MonoClass *klass, MonoClass *parent)
5355 {
5356         gboolean system_namespace;
5357         gboolean is_corlib = mono_is_corlib_image (klass->image);
5358
5359         system_namespace = !strcmp (klass->name_space, "System") && is_corlib;
5360
5361         /* if root of the hierarchy */
5362         if (system_namespace && !strcmp (klass->name, "Object")) {
5363                 klass->parent = NULL;
5364                 klass->instance_size = sizeof (MonoObject);
5365                 return;
5366         }
5367         if (!strcmp (klass->name, "<Module>")) {
5368                 klass->parent = NULL;
5369                 klass->instance_size = 0;
5370                 return;
5371         }
5372
5373         if (!MONO_CLASS_IS_INTERFACE (klass)) {
5374                 /* Imported COM Objects always derive from __ComObject. */
5375 #ifndef DISABLE_COM
5376                 if (MONO_CLASS_IS_IMPORT (klass)) {
5377                         init_com_from_comimport (klass);
5378                         if (parent == mono_defaults.object_class)
5379                                 parent = mono_class_get_com_object_class ();
5380                 }
5381 #endif
5382                 if (!parent) {
5383                         /* set the parent to something useful and safe, but mark the type as broken */
5384                         parent = mono_defaults.object_class;
5385                         mono_class_set_type_load_failure (klass, "");
5386                         g_assert (parent);
5387                 }
5388
5389                 klass->parent = parent;
5390
5391                 if (mono_class_is_ginst (parent) && !parent->name) {
5392                         /*
5393                          * If the parent is a generic instance, we may get
5394                          * called before it is fully initialized, especially
5395                          * before it has its name.
5396                          */
5397                         return;
5398                 }
5399
5400 #ifndef DISABLE_REMOTING
5401                 klass->marshalbyref = parent->marshalbyref;
5402                 klass->contextbound  = parent->contextbound;
5403 #endif
5404
5405                 klass->delegate  = parent->delegate;
5406
5407                 if (MONO_CLASS_IS_IMPORT (klass) || mono_class_is_com_object (parent))
5408                         mono_class_set_is_com_object (klass);
5409                 
5410                 if (system_namespace) {
5411 #ifndef DISABLE_REMOTING
5412                         if (klass->name [0] == 'M' && !strcmp (klass->name, "MarshalByRefObject"))
5413                                 klass->marshalbyref = 1;
5414
5415                         if (klass->name [0] == 'C' && !strcmp (klass->name, "ContextBoundObject")) 
5416                                 klass->contextbound  = 1;
5417 #endif
5418                         if (klass->name [0] == 'D' && !strcmp (klass->name, "Delegate")) 
5419                                 klass->delegate  = 1;
5420                 }
5421
5422                 if (klass->parent->enumtype || (mono_is_corlib_image (klass->parent->image) && (strcmp (klass->parent->name, "ValueType") == 0) && 
5423                                                 (strcmp (klass->parent->name_space, "System") == 0)))
5424                         klass->valuetype = 1;
5425                 if (mono_is_corlib_image (klass->parent->image) && ((strcmp (klass->parent->name, "Enum") == 0) && (strcmp (klass->parent->name_space, "System") == 0))) {
5426                         klass->valuetype = klass->enumtype = 1;
5427                 }
5428                 /*klass->enumtype = klass->parent->enumtype; */
5429         } else {
5430                 /* initialize com types if COM interfaces are present */
5431 #ifndef DISABLE_COM
5432                 if (MONO_CLASS_IS_IMPORT (klass))
5433                         init_com_from_comimport (klass);
5434 #endif
5435                 klass->parent = NULL;
5436         }
5437
5438 }
5439
5440 /*
5441  * mono_class_setup_supertypes:
5442  * @class: a class
5443  *
5444  * Build the data structure needed to make fast type checks work.
5445  * This currently sets two fields in @class:
5446  *  - idepth: distance between @class and System.Object in the type
5447  *    hierarchy + 1
5448  *  - supertypes: array of classes: each element has a class in the hierarchy
5449  *    starting from @class up to System.Object
5450  * 
5451  * LOCKING: Acquires the loader lock.
5452  */
5453 void
5454 mono_class_setup_supertypes (MonoClass *klass)
5455 {
5456         int ms, idepth;
5457         MonoClass **supertypes;
5458
5459         mono_atomic_load_acquire (supertypes, MonoClass **, &klass->supertypes);
5460         if (supertypes)
5461                 return;
5462
5463         if (klass->parent && !klass->parent->supertypes)
5464                 mono_class_setup_supertypes (klass->parent);
5465         if (klass->parent)
5466                 idepth = klass->parent->idepth + 1;
5467         else
5468                 idepth = 1;
5469
5470         ms = MAX (MONO_DEFAULT_SUPERTABLE_SIZE, idepth);
5471         supertypes = (MonoClass **)mono_class_alloc0 (klass, sizeof (MonoClass *) * ms);
5472
5473         if (klass->parent) {
5474                 CHECKED_METADATA_WRITE_PTR ( supertypes [idepth - 1] , klass );
5475
5476                 int supertype_idx;
5477                 for (supertype_idx = 0; supertype_idx < klass->parent->idepth; supertype_idx++)
5478                         CHECKED_METADATA_WRITE_PTR ( supertypes [supertype_idx] , klass->parent->supertypes [supertype_idx] );
5479         } else {
5480                 CHECKED_METADATA_WRITE_PTR ( supertypes [0] , klass );
5481         }
5482
5483         mono_memory_barrier ();
5484
5485         mono_loader_lock ();
5486         klass->idepth = idepth;
5487         /* Needed so idepth is visible before supertypes is set */
5488         mono_memory_barrier ();
5489         klass->supertypes = supertypes;
5490         mono_loader_unlock ();
5491 }
5492
5493 static gboolean
5494 discard_gclass_due_to_failure (MonoClass *gclass, void *user_data)
5495 {
5496         return mono_class_get_generic_class (gclass)->container_class == user_data;
5497 }
5498
5499 static gboolean
5500 fix_gclass_incomplete_instantiation (MonoClass *gclass, void *user_data)
5501 {
5502         MonoClass *gtd = (MonoClass*)user_data;
5503         /* Only try to fix generic instances of @gtd */
5504         if (mono_class_get_generic_class (gclass)->container_class != gtd)
5505                 return FALSE;
5506
5507         /* Check if the generic instance has no parent. */
5508         if (gtd->parent && !gclass->parent)
5509                 mono_generic_class_setup_parent (gclass, gtd);
5510
5511         return TRUE;
5512 }
5513
5514 static void
5515 mono_class_set_failure_and_error (MonoClass *klass, MonoError *error, const char *msg)
5516 {
5517         mono_class_set_type_load_failure (klass, "%s", msg);
5518         mono_error_set_type_load_class (error, klass, "%s", msg);
5519 }
5520
5521 /**
5522  * mono_class_create_from_typedef:
5523  * \param image: image where the token is valid
5524  * \param type_token:  typedef token
5525  * \param error:  used to return any error found while creating the type
5526  *
5527  * Create the MonoClass* representing the specified type token.
5528  * \p type_token must be a TypeDef token.
5529  *
5530  * FIXME: don't return NULL on failure, just let the caller figure it out.
5531  */
5532 static MonoClass *
5533 mono_class_create_from_typedef (MonoImage *image, guint32 type_token, MonoError *error)
5534 {
5535         MonoTableInfo *tt = &image->tables [MONO_TABLE_TYPEDEF];
5536         MonoClass *klass, *parent = NULL;
5537         guint32 cols [MONO_TYPEDEF_SIZE];
5538         guint32 cols_next [MONO_TYPEDEF_SIZE];
5539         guint tidx = mono_metadata_token_index (type_token);
5540         MonoGenericContext *context = NULL;
5541         const char *name, *nspace;
5542         guint icount = 0; 
5543         MonoClass **interfaces;
5544         guint32 field_last, method_last;
5545         guint32 nesting_tokeen;
5546
5547         error_init (error);
5548
5549         if (mono_metadata_token_table (type_token) != MONO_TABLE_TYPEDEF || tidx > tt->rows) {
5550                 mono_error_set_bad_image (error, image, "Invalid typedef token %x", type_token);
5551                 return NULL;
5552         }
5553
5554         mono_loader_lock ();
5555
5556         if ((klass = (MonoClass *)mono_internal_hash_table_lookup (&image->class_cache, GUINT_TO_POINTER (type_token)))) {
5557                 mono_loader_unlock ();
5558                 return klass;
5559         }
5560
5561         mono_metadata_decode_row (tt, tidx - 1, cols, MONO_TYPEDEF_SIZE);
5562         
5563         name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
5564         nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
5565
5566         if (mono_metadata_has_generic_params (image, type_token)) {
5567                 klass = mono_image_alloc0 (image, sizeof (MonoClassGtd));
5568                 klass->class_kind = MONO_CLASS_GTD;
5569                 UnlockedAdd (&classes_size, sizeof (MonoClassGtd));
5570                 ++class_gtd_count;
5571         } else {
5572                 klass = mono_image_alloc0 (image, sizeof (MonoClassDef));
5573                 klass->class_kind = MONO_CLASS_DEF;
5574                 UnlockedAdd (&classes_size, sizeof (MonoClassDef));
5575                 ++class_def_count;
5576         }
5577
5578         klass->name = name;
5579         klass->name_space = nspace;
5580
5581         MONO_PROFILER_RAISE (class_loading, (klass));
5582
5583         klass->image = image;
5584         klass->type_token = type_token;
5585         mono_class_set_flags (klass, cols [MONO_TYPEDEF_FLAGS]);
5586
5587         mono_internal_hash_table_insert (&image->class_cache, GUINT_TO_POINTER (type_token), klass);
5588
5589         /*
5590          * Check whether we're a generic type definition.
5591          */
5592         if (mono_class_is_gtd (klass)) {
5593                 MonoGenericContainer *generic_container = mono_metadata_load_generic_params (image, klass->type_token, NULL);
5594                 generic_container->owner.klass = klass;
5595                 generic_container->is_anonymous = FALSE; // Owner class is now known, container is no longer anonymous
5596                 context = &generic_container->context;
5597                 mono_class_set_generic_container (klass, generic_container);
5598                 MonoType *canonical_inst = &((MonoClassGtd*)klass)->canonical_inst;
5599                 canonical_inst->type = MONO_TYPE_GENERICINST;
5600                 canonical_inst->data.generic_class = mono_metadata_lookup_generic_class (klass, context->class_inst, FALSE);
5601                 enable_gclass_recording ();
5602         }
5603
5604         if (cols [MONO_TYPEDEF_EXTENDS]) {
5605                 MonoClass *tmp;
5606                 guint32 parent_token = mono_metadata_token_from_dor (cols [MONO_TYPEDEF_EXTENDS]);
5607
5608                 if (mono_metadata_token_table (parent_token) == MONO_TABLE_TYPESPEC) {
5609                         /*WARNING: this must satisfy mono_metadata_type_hash*/
5610                         klass->this_arg.byref = 1;
5611                         klass->this_arg.data.klass = klass;
5612                         klass->this_arg.type = MONO_TYPE_CLASS;
5613                         klass->byval_arg.data.klass = klass;
5614                         klass->byval_arg.type = MONO_TYPE_CLASS;
5615                 }
5616                 parent = mono_class_get_checked (image, parent_token, error);
5617                 if (parent && context) /* Always inflate */
5618                         parent = mono_class_inflate_generic_class_checked (parent, context, error);
5619
5620                 if (parent == NULL) {
5621                         mono_class_set_type_load_failure (klass, "%s", mono_error_get_message (error));
5622                         goto parent_failure;
5623                 }
5624
5625                 for (tmp = parent; tmp; tmp = tmp->parent) {
5626                         if (tmp == klass) {
5627                                 mono_class_set_failure_and_error (klass, error, "Cycle found while resolving parent");
5628                                 goto parent_failure;
5629                         }
5630                         if (mono_class_is_gtd (klass) && mono_class_is_ginst (tmp) && mono_class_get_generic_class (tmp)->container_class == klass) {
5631                                 mono_class_set_failure_and_error (klass, error, "Parent extends generic instance of this type");
5632                                 goto parent_failure;
5633                         }
5634                 }
5635         }
5636
5637         mono_class_setup_parent (klass, parent);
5638
5639         /* uses ->valuetype, which is initialized by mono_class_setup_parent above */
5640         mono_class_setup_mono_type (klass);
5641
5642         if (mono_class_is_gtd (klass))
5643                 disable_gclass_recording (fix_gclass_incomplete_instantiation, klass);
5644
5645         /* 
5646          * This might access klass->byval_arg for recursion generated by generic constraints,
5647          * so it has to come after setup_mono_type ().
5648          */
5649         if ((nesting_tokeen = mono_metadata_nested_in_typedef (image, type_token))) {
5650                 klass->nested_in = mono_class_create_from_typedef (image, nesting_tokeen, error);
5651                 if (!mono_error_ok (error)) {
5652                         /*FIXME implement a mono_class_set_failure_from_mono_error */
5653                         mono_class_set_type_load_failure (klass, "%s",  mono_error_get_message (error));
5654                         mono_loader_unlock ();
5655                         MONO_PROFILER_RAISE (class_failed, (klass));
5656                         return NULL;
5657                 }
5658         }
5659
5660         if ((mono_class_get_flags (klass) & TYPE_ATTRIBUTE_STRING_FORMAT_MASK) == TYPE_ATTRIBUTE_UNICODE_CLASS)
5661                 klass->unicode = 1;
5662
5663 #ifdef HOST_WIN32
5664         if ((mono_class_get_flags (klass) & TYPE_ATTRIBUTE_STRING_FORMAT_MASK) == TYPE_ATTRIBUTE_AUTO_CLASS)
5665                 klass->unicode = 1;
5666 #endif
5667
5668         klass->cast_class = klass->element_class = klass;
5669         if (mono_is_corlib_image (klass->image)) {
5670                 switch (klass->byval_arg.type) {
5671                         case MONO_TYPE_I1:
5672                                 if (mono_defaults.byte_class)
5673                                         klass->cast_class = mono_defaults.byte_class;
5674                                 break;
5675                         case MONO_TYPE_U1:
5676                                 if (mono_defaults.sbyte_class)
5677                                         mono_defaults.sbyte_class = klass;
5678                                 break;
5679                         case MONO_TYPE_I2:
5680                                 if (mono_defaults.uint16_class)
5681                                         mono_defaults.uint16_class = klass;
5682                                 break;
5683                         case MONO_TYPE_U2:
5684                                 if (mono_defaults.int16_class)
5685                                         klass->cast_class = mono_defaults.int16_class;
5686                                 break;
5687                         case MONO_TYPE_I4:
5688                                 if (mono_defaults.uint32_class)
5689                                         mono_defaults.uint32_class = klass;
5690                                 break;
5691                         case MONO_TYPE_U4:
5692                                 if (mono_defaults.int32_class)
5693                                         klass->cast_class = mono_defaults.int32_class;
5694                                 break;
5695                         case MONO_TYPE_I8:
5696                                 if (mono_defaults.uint64_class)
5697                                         mono_defaults.uint64_class = klass;
5698                                 break;
5699                         case MONO_TYPE_U8:
5700                                 if (mono_defaults.int64_class)
5701                                         klass->cast_class = mono_defaults.int64_class;
5702                                 break;
5703                 }
5704         }
5705
5706         if (!klass->enumtype) {
5707                 if (!mono_metadata_interfaces_from_typedef_full (
5708                             image, type_token, &interfaces, &icount, FALSE, context, error)){
5709
5710                         mono_class_set_type_load_failure (klass, "%s", mono_error_get_message (error));
5711                         mono_loader_unlock ();
5712                         MONO_PROFILER_RAISE (class_failed, (klass));
5713                         return NULL;
5714                 }
5715
5716                 /* This is required now that it is possible for more than 2^16 interfaces to exist. */
5717                 g_assert(icount <= 65535);
5718
5719                 klass->interfaces = interfaces;
5720                 klass->interface_count = icount;
5721                 klass->interfaces_inited = 1;
5722         }
5723
5724         /*g_print ("Load class %s\n", name);*/
5725
5726         /*
5727          * Compute the field and method lists
5728          */
5729         int first_field_idx = cols [MONO_TYPEDEF_FIELD_LIST] - 1;
5730         mono_class_set_first_field_idx (klass, first_field_idx);
5731         int first_method_idx = cols [MONO_TYPEDEF_METHOD_LIST] - 1;
5732         mono_class_set_first_method_idx (klass, first_method_idx);
5733
5734         if (tt->rows > tidx){           
5735                 mono_metadata_decode_row (tt, tidx, cols_next, MONO_TYPEDEF_SIZE);
5736                 field_last  = cols_next [MONO_TYPEDEF_FIELD_LIST] - 1;
5737                 method_last = cols_next [MONO_TYPEDEF_METHOD_LIST] - 1;
5738         } else {
5739                 field_last  = image->tables [MONO_TABLE_FIELD].rows;
5740                 method_last = image->tables [MONO_TABLE_METHOD].rows;
5741         }
5742
5743         if (cols [MONO_TYPEDEF_FIELD_LIST] && 
5744             cols [MONO_TYPEDEF_FIELD_LIST] <= image->tables [MONO_TABLE_FIELD].rows)
5745                 mono_class_set_field_count (klass, field_last - first_field_idx);
5746         if (cols [MONO_TYPEDEF_METHOD_LIST] <= image->tables [MONO_TABLE_METHOD].rows)
5747                 mono_class_set_method_count (klass, method_last - first_method_idx);
5748
5749         /* reserve space to store vector pointer in arrays */
5750         if (mono_is_corlib_image (image) && !strcmp (nspace, "System") && !strcmp (name, "Array")) {
5751                 klass->instance_size += 2 * sizeof (gpointer);
5752                 g_assert (mono_class_get_field_count (klass) == 0);
5753         }
5754
5755         if (klass->enumtype) {
5756                 MonoType *enum_basetype = mono_class_find_enum_basetype (klass, error);
5757                 if (!enum_basetype) {
5758                         /*set it to a default value as the whole runtime can't handle this to be null*/
5759                         klass->cast_class = klass->element_class = mono_defaults.int32_class;
5760                         mono_class_set_type_load_failure (klass, "%s", mono_error_get_message (error));
5761                         mono_loader_unlock ();
5762                         MONO_PROFILER_RAISE (class_failed, (klass));
5763                         return NULL;
5764                 }
5765                 klass->cast_class = klass->element_class = mono_class_from_mono_type (enum_basetype);
5766         }
5767
5768         /*
5769          * If we're a generic type definition, load the constraints.
5770          * We must do this after the class has been constructed to make certain recursive scenarios
5771          * work.
5772          */
5773         if (mono_class_is_gtd (klass) && !mono_metadata_load_generic_param_constraints_checked (image, type_token, mono_class_get_generic_container (klass), error)) {
5774                 mono_class_set_type_load_failure (klass, "Could not load generic parameter constrains due to %s", mono_error_get_message (error));
5775                 mono_loader_unlock ();
5776                 MONO_PROFILER_RAISE (class_failed, (klass));
5777                 return NULL;
5778         }
5779
5780         if (klass->image->assembly_name && !strcmp (klass->image->assembly_name, "Mono.Simd") && !strcmp (nspace, "Mono.Simd")) {
5781                 if (!strncmp (name, "Vector", 6))
5782                         klass->simd_type = !strcmp (name + 6, "2d") || !strcmp (name + 6, "2ul") || !strcmp (name + 6, "2l") || !strcmp (name + 6, "4f") || !strcmp (name + 6, "4ui") || !strcmp (name + 6, "4i") || !strcmp (name + 6, "8s") || !strcmp (name + 6, "8us") || !strcmp (name + 6, "16b") || !strcmp (name + 6, "16sb");
5783         } else if (klass->image->assembly_name && !strcmp (klass->image->assembly_name, "System.Numerics") && !strcmp (nspace, "System.Numerics")) {
5784                 if (!strcmp (name, "Vector2") || !strcmp (name, "Vector3") || !strcmp (name, "Vector4"))
5785                         klass->simd_type = 1;
5786         }
5787
5788         mono_loader_unlock ();
5789
5790         MONO_PROFILER_RAISE (class_loaded, (klass));
5791
5792         return klass;
5793
5794 parent_failure:
5795         if (mono_class_is_gtd (klass))
5796                 disable_gclass_recording (discard_gclass_due_to_failure, klass);
5797
5798         mono_class_setup_mono_type (klass);
5799         mono_loader_unlock ();
5800         MONO_PROFILER_RAISE (class_failed, (klass));
5801         return NULL;
5802 }
5803
5804 /** Is klass a Nullable<T> ginst? */
5805 gboolean
5806 mono_class_is_nullable (MonoClass *klass)
5807 {
5808         MonoGenericClass *gklass = mono_class_try_get_generic_class (klass);
5809         return gklass && gklass->container_class == mono_defaults.generic_nullable_class;
5810 }
5811
5812
5813 /** if klass is T? return T */
5814 MonoClass*
5815 mono_class_get_nullable_param (MonoClass *klass)
5816 {
5817        g_assert (mono_class_is_nullable (klass));
5818        return mono_class_from_mono_type (mono_class_get_generic_class (klass)->context.class_inst->type_argv [0]);
5819 }
5820
5821 static void
5822 mono_generic_class_setup_parent (MonoClass *klass, MonoClass *gtd)
5823 {
5824         if (gtd->parent) {
5825                 MonoError error;
5826                 MonoGenericClass *gclass = mono_class_get_generic_class (klass);
5827
5828                 klass->parent = mono_class_inflate_generic_class_checked (gtd->parent, mono_generic_class_get_context (gclass), &error);
5829                 if (!mono_error_ok (&error)) {
5830                         /*Set parent to something safe as the runtime doesn't handle well this kind of failure.*/
5831                         klass->parent = mono_defaults.object_class;
5832                         mono_class_set_type_load_failure (klass, "Parent is a generic type instantiation that failed due to: %s", mono_error_get_message (&error));
5833                         mono_error_cleanup (&error);
5834                 }
5835         }
5836         mono_loader_lock ();
5837         if (klass->parent)
5838                 mono_class_setup_parent (klass, klass->parent);
5839
5840         if (klass->enumtype) {
5841                 klass->cast_class = gtd->cast_class;
5842                 klass->element_class = gtd->element_class;
5843         }
5844         mono_loader_unlock ();
5845 }
5846
5847 gboolean
5848 mono_type_is_primitive (MonoType *type)
5849 {
5850         return (type->type >= MONO_TYPE_BOOLEAN && type->type <= MONO_TYPE_R8) ||
5851                         type-> type == MONO_TYPE_I || type->type == MONO_TYPE_U;
5852 }
5853
5854 /*
5855  * Create the `MonoClass' for an instantiation of a generic type.
5856  * We only do this if we actually need it.
5857  */
5858 MonoClass*
5859 mono_generic_class_get_class (MonoGenericClass *gclass)
5860 {
5861         MonoClass *klass, *gklass;
5862
5863         if (gclass->cached_class)
5864                 return gclass->cached_class;
5865
5866         klass = (MonoClass *)mono_image_set_alloc0 (gclass->owner, sizeof (MonoClassGenericInst));
5867
5868         gklass = gclass->container_class;
5869
5870         if (gklass->nested_in) {
5871                 /* The nested_in type should not be inflated since it's possible to produce a nested type with less generic arguments*/
5872                 klass->nested_in = gklass->nested_in;
5873         }
5874
5875         klass->name = gklass->name;
5876         klass->name_space = gklass->name_space;
5877         
5878         klass->image = gklass->image;
5879         klass->type_token = gklass->type_token;
5880
5881         klass->class_kind = MONO_CLASS_GINST;
5882         //FIXME add setter
5883         ((MonoClassGenericInst*)klass)->generic_class = gclass;
5884
5885         klass->byval_arg.type = MONO_TYPE_GENERICINST;
5886         klass->this_arg.type = klass->byval_arg.type;
5887         klass->this_arg.data.generic_class = klass->byval_arg.data.generic_class = gclass;
5888         klass->this_arg.byref = TRUE;
5889         klass->enumtype = gklass->enumtype;
5890         klass->valuetype = gklass->valuetype;
5891
5892
5893         if (gklass->image->assembly_name && !strcmp (gklass->image->assembly_name, "System.Numerics.Vectors") && !strcmp (gklass->name_space, "System.Numerics") && !strcmp (gklass->name, "Vector`1")) {
5894                 g_assert (gclass->context.class_inst);
5895                 g_assert (gclass->context.class_inst->type_argc > 0);
5896                 if (mono_type_is_primitive (gclass->context.class_inst->type_argv [0]))
5897                         klass->simd_type = 1;
5898         }
5899         klass->is_array_special_interface = gklass->is_array_special_interface;
5900
5901         klass->cast_class = klass->element_class = klass;
5902
5903         if (gclass->is_dynamic) {
5904                 /*
5905                  * We don't need to do any init workf with unbaked typebuilders. Generic instances created at this point will be later unregistered and/or fixed.
5906                  * This is to avoid work that would probably give wrong results as fields change as we build the TypeBuilder.
5907                  * See remove_instantiations_of_and_ensure_contents in reflection.c and its usage in reflection.c to understand the fixup stage of SRE banking.
5908                 */
5909                 if (!gklass->wastypebuilder)
5910                         klass->inited = 1;
5911
5912                 if (klass->enumtype) {
5913                         /*
5914                          * For enums, gklass->fields might not been set, but instance_size etc. is 
5915                          * already set in mono_reflection_create_internal_class (). For non-enums,
5916                          * these will be computed normally in mono_class_layout_fields ().
5917                          */
5918                         klass->instance_size = gklass->instance_size;
5919                         klass->sizes.class_size = gklass->sizes.class_size;
5920                         klass->size_inited = 1;
5921                 }
5922         }
5923
5924         mono_loader_lock ();
5925
5926         if (gclass->cached_class) {
5927                 mono_loader_unlock ();
5928                 return gclass->cached_class;
5929         }
5930
5931         if (record_gclass_instantiation > 0)
5932                 gclass_recorded_list = g_slist_append (gclass_recorded_list, klass);
5933
5934         if (mono_class_is_nullable (klass))
5935                 klass->cast_class = klass->element_class = mono_class_get_nullable_param (klass);
5936
5937         MONO_PROFILER_RAISE (class_loading, (klass));
5938
5939         mono_generic_class_setup_parent (klass, gklass);
5940
5941         if (gclass->is_dynamic)
5942                 mono_class_setup_supertypes (klass);
5943
5944         mono_memory_barrier ();
5945         gclass->cached_class = klass;
5946
5947         MONO_PROFILER_RAISE (class_loaded, (klass));
5948
5949         ++class_ginst_count;
5950         inflated_classes_size += sizeof (MonoClassGenericInst);
5951         
5952         mono_loader_unlock ();
5953
5954         return klass;
5955 }
5956
5957 static MonoImage *
5958 get_image_for_container (MonoGenericContainer *container)
5959 {
5960         MonoImage *result;
5961         if (container->is_anonymous) {
5962                 result = container->owner.image;
5963         } else {
5964                 MonoClass *klass;
5965                 if (container->is_method) {
5966                         MonoMethod *method = container->owner.method;
5967                         g_assert_checked (method);
5968                         klass = method->klass;
5969                 } else {
5970                         klass = container->owner.klass;
5971                 }
5972                 g_assert_checked (klass);
5973                 result = klass->image;
5974         }
5975         g_assert (result);
5976         return result;
5977 }
5978
5979 MonoImage *
5980 get_image_for_generic_param (MonoGenericParam *param)
5981 {
5982         MonoGenericContainer *container = mono_generic_param_owner (param);
5983         g_assert_checked (container);
5984         return get_image_for_container (container);
5985 }
5986
5987 // Make a string in the designated image consisting of a single integer.
5988 #define INT_STRING_SIZE 16
5989 char *
5990 make_generic_name_string (MonoImage *image, int num)
5991 {
5992         char *name = (char *)mono_image_alloc0 (image, INT_STRING_SIZE);
5993         g_snprintf (name, INT_STRING_SIZE, "%d", num);
5994         return name;
5995 }
5996
5997 // This is called by mono_class_from_generic_parameter_internal when a new class must be created.
5998 // pinfo is derived from param by the caller for us.
5999 static MonoClass*
6000 make_generic_param_class (MonoGenericParam *param, MonoGenericParamInfo *pinfo)
6001 {
6002         MonoClass *klass, **ptr;
6003         int count, pos, i;
6004         MonoGenericContainer *container = mono_generic_param_owner (param);
6005         g_assert_checked (container);
6006
6007         MonoImage *image = get_image_for_container (container);
6008         gboolean is_mvar = container->is_method;
6009         gboolean is_anonymous = container->is_anonymous;
6010
6011         klass = (MonoClass *)mono_image_alloc0 (image, sizeof (MonoClassGenericParam));
6012         klass->class_kind = MONO_CLASS_GPARAM;
6013         UnlockedAdd (&classes_size, sizeof (MonoClassGenericParam));
6014         UnlockedIncrement (&class_gparam_count);
6015
6016         if (pinfo) {
6017                 CHECKED_METADATA_WRITE_PTR_EXEMPT ( klass->name , pinfo->name );
6018         } else {
6019                 int n = mono_generic_param_num (param);
6020                 CHECKED_METADATA_WRITE_PTR_LOCAL ( klass->name , make_generic_name_string (image, n) );
6021         }
6022
6023         if (is_anonymous) {
6024                 CHECKED_METADATA_WRITE_PTR_EXEMPT ( klass->name_space ,  "" );
6025         } else if (is_mvar) {
6026                 MonoMethod *omethod = container->owner.method;
6027                 CHECKED_METADATA_WRITE_PTR_EXEMPT ( klass->name_space , (omethod && omethod->klass) ? omethod->klass->name_space : "" );
6028         } else {
6029                 MonoClass *oklass = container->owner.klass;
6030                 CHECKED_METADATA_WRITE_PTR_EXEMPT ( klass->name_space , oklass ? oklass->name_space : "" );
6031         }
6032
6033         MONO_PROFILER_RAISE (class_loading, (klass));
6034
6035         // Count non-NULL items in pinfo->constraints
6036         count = 0;
6037         if (pinfo)
6038                 for (ptr = pinfo->constraints; ptr && *ptr; ptr++, count++)
6039                         ;
6040
6041         pos = 0;
6042         if ((count > 0) && !MONO_CLASS_IS_INTERFACE (pinfo->constraints [0])) {
6043                 CHECKED_METADATA_WRITE_PTR ( klass->parent , pinfo->constraints [0] );
6044                 pos++;
6045         } else if (pinfo && pinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT) {
6046                 CHECKED_METADATA_WRITE_PTR ( klass->parent , mono_class_load_from_name (mono_defaults.corlib, "System", "ValueType") );
6047         } else {
6048                 CHECKED_METADATA_WRITE_PTR ( klass->parent , mono_defaults.object_class );
6049         }
6050
6051         if (count - pos > 0) {
6052                 klass->interface_count = count - pos;
6053                 CHECKED_METADATA_WRITE_PTR_LOCAL ( klass->interfaces , (MonoClass **)mono_image_alloc0 (image, sizeof (MonoClass *) * (count - pos)) );
6054                 klass->interfaces_inited = TRUE;
6055                 for (i = pos; i < count; i++)
6056                         CHECKED_METADATA_WRITE_PTR ( klass->interfaces [i - pos] , pinfo->constraints [i] );
6057         }
6058
6059         CHECKED_METADATA_WRITE_PTR_EXEMPT ( klass->image , image );
6060
6061         klass->inited = TRUE;
6062         CHECKED_METADATA_WRITE_PTR_LOCAL ( klass->cast_class ,    klass );
6063         CHECKED_METADATA_WRITE_PTR_LOCAL ( klass->element_class , klass );
6064
6065         klass->byval_arg.type = is_mvar ? MONO_TYPE_MVAR : MONO_TYPE_VAR;
6066         klass->this_arg.type = klass->byval_arg.type;
6067         CHECKED_METADATA_WRITE_PTR ( klass->this_arg.data.generic_param ,  param );
6068         CHECKED_METADATA_WRITE_PTR ( klass->byval_arg.data.generic_param , param );
6069         klass->this_arg.byref = TRUE;
6070
6071         /* We don't use type_token for VAR since only classes can use it (not arrays, pointer, VARs, etc) */
6072         klass->sizes.generic_param_token = pinfo ? pinfo->token : 0;
6073
6074         /*Init these fields to sane values*/
6075         klass->min_align = 1;
6076         /*
6077          * This makes sure the the value size of this class is equal to the size of the types the gparam is
6078          * constrained to, the JIT depends on this.
6079          */
6080         klass->instance_size = sizeof (MonoObject) + mono_type_stack_size_internal (&klass->byval_arg, NULL, TRUE);
6081         mono_memory_barrier ();
6082         klass->size_inited = 1;
6083
6084         mono_class_setup_supertypes (klass);
6085
6086         if (count - pos > 0) {
6087                 mono_class_setup_vtable (klass->parent);
6088                 if (mono_class_has_failure (klass->parent))
6089                         mono_class_set_type_load_failure (klass, "Failed to setup parent interfaces");
6090                 else
6091                         setup_interface_offsets (klass, klass->parent->vtable_size, TRUE);
6092         }
6093
6094         return klass;
6095 }
6096
6097 #define FAST_CACHE_SIZE 16
6098
6099 /*
6100  * get_anon_gparam_class and set_anon_gparam_class are helpers for mono_class_from_generic_parameter_internal.
6101  * The latter will sometimes create MonoClasses for anonymous generic params. To prevent this being wasteful,
6102  * we cache the MonoClasses.
6103  * FIXME: It would be better to instead cache anonymous MonoGenericParams, and allow anonymous params to point directly to classes using the pklass field.
6104  * LOCKING: Takes the image lock depending on @take_lock.
6105  */
6106 static MonoClass *
6107 get_anon_gparam_class (MonoGenericParam *param, gboolean take_lock)
6108 {
6109         int n = mono_generic_param_num (param);
6110         MonoImage *image = get_image_for_generic_param (param);
6111         gboolean is_mvar = mono_generic_param_owner (param)->is_method;
6112         MonoClass *klass = NULL;
6113         GHashTable *ht;
6114
6115         g_assert (image);
6116
6117         // For params with a small num and no constraints, we use a "fast" cache which does simple num lookup in an array.
6118         // For high numbers or constraints we have to use pointer hashes.
6119         if (param->gshared_constraint) {
6120                 ht = is_mvar ? image->mvar_cache_constrained : image->var_cache_constrained;
6121                 if (ht) {
6122                         if (take_lock)
6123                                 mono_image_lock (image);
6124                         klass = (MonoClass *)g_hash_table_lookup (ht, param);
6125                         if (take_lock)
6126                                 mono_image_unlock (image);
6127                 }
6128                 return klass;
6129         }
6130
6131         if (n < FAST_CACHE_SIZE) {
6132                 if (is_mvar)
6133                         return image->mvar_cache_fast ? image->mvar_cache_fast [n] : NULL;
6134                 else
6135                         return image->var_cache_fast ? image->var_cache_fast [n] : NULL;
6136         } else {
6137                 ht = is_mvar ? image->mvar_cache_slow : image->var_cache_slow;
6138                 if (ht) {
6139                         if (take_lock)
6140                                 mono_image_lock (image);
6141                         klass = (MonoClass *)g_hash_table_lookup (ht, GINT_TO_POINTER (n));
6142                         if (take_lock)
6143                                 mono_image_unlock (image);
6144                 }
6145                 return klass;
6146         }
6147 }
6148
6149 /*
6150  * LOCKING: Image lock (param->image) must be held
6151  */
6152 static void
6153 set_anon_gparam_class (MonoGenericParam *param, MonoClass *klass)
6154 {
6155         int n = mono_generic_param_num (param);
6156         MonoImage *image = get_image_for_generic_param (param);
6157         gboolean is_mvar = mono_generic_param_owner (param)->is_method;
6158
6159         g_assert (image);
6160
6161         if (param->gshared_constraint) {
6162                 GHashTable *ht = is_mvar ? image->mvar_cache_constrained : image->var_cache_constrained;
6163                 if (!ht) {
6164                         ht = g_hash_table_new ((GHashFunc)mono_metadata_generic_param_hash, (GEqualFunc)mono_metadata_generic_param_equal);
6165                         mono_memory_barrier ();
6166                         if (is_mvar)
6167                                 image->mvar_cache_constrained = ht;
6168                         else
6169                                 image->var_cache_constrained = ht;
6170                 }
6171                 g_hash_table_insert (ht, param, klass);
6172         } else if (n < FAST_CACHE_SIZE) {
6173                 if (is_mvar) {
6174                         /* Requires locking to avoid droping an already published class */
6175                         if (!image->mvar_cache_fast)
6176                                 image->mvar_cache_fast = (MonoClass **)mono_image_alloc0 (image, sizeof (MonoClass*) * FAST_CACHE_SIZE);
6177                         image->mvar_cache_fast [n] = klass;
6178                 } else {
6179                         if (!image->var_cache_fast)
6180                                 image->var_cache_fast = (MonoClass **)mono_image_alloc0 (image, sizeof (MonoClass*) * FAST_CACHE_SIZE);
6181                         image->var_cache_fast [n] = klass;
6182                 }
6183         } else {
6184                 GHashTable *ht = is_mvar ? image->mvar_cache_slow : image->var_cache_slow;
6185                 if (!ht) {
6186                         ht = is_mvar ? image->mvar_cache_slow : image->var_cache_slow;
6187                         if (!ht) {
6188                                 ht = g_hash_table_new (NULL, NULL);
6189                                 mono_memory_barrier ();
6190                                 if (is_mvar)
6191                                         image->mvar_cache_slow = ht;
6192                                 else
6193                                         image->var_cache_slow = ht;
6194                         }
6195                 }
6196                 g_hash_table_insert (ht, GINT_TO_POINTER (n), klass);
6197         }
6198 }
6199
6200 /*
6201  * LOCKING: Acquires the image lock (@image).
6202  */
6203 MonoClass *
6204 mono_class_from_generic_parameter_internal (MonoGenericParam *param)
6205 {
6206         MonoImage *image = get_image_for_generic_param (param);
6207         MonoGenericParamInfo *pinfo = mono_generic_param_info (param);
6208         MonoClass *klass, *klass2;
6209
6210         // If a klass already exists for this object and is cached, return it.
6211         if (pinfo) // Non-anonymous
6212                 klass = pinfo->pklass;
6213         else     // Anonymous
6214                 klass = get_anon_gparam_class (param, TRUE);
6215
6216         if (klass)
6217                 return klass;
6218
6219         // Create a new klass
6220         klass = make_generic_param_class (param, pinfo);
6221
6222         // Now we need to cache the klass we created.
6223         // But since we wait to grab the lock until after creating the klass, we need to check to make sure
6224         // another thread did not get in and cache a klass ahead of us. In that case, return their klass
6225         // and allow our newly-created klass object to just leak.
6226         mono_memory_barrier ();
6227
6228         mono_image_lock (image);
6229
6230     // Here "klass2" refers to the klass potentially created by the other thread.
6231         if (pinfo) // Repeat check from above
6232                 klass2 = pinfo->pklass;
6233         else
6234                 klass2 = get_anon_gparam_class (param, FALSE);
6235
6236         if (klass2) {
6237                 klass = klass2;
6238         } else {
6239                 // Cache here
6240                 if (pinfo)
6241                         pinfo->pklass = klass;
6242                 else
6243                         set_anon_gparam_class (param, klass);
6244         }
6245         mono_image_unlock (image);
6246
6247         /* FIXME: Should this go inside 'make_generic_param_klass'? */
6248         if (klass2)
6249                 MONO_PROFILER_RAISE (class_failed, (klass2));
6250         else
6251                 MONO_PROFILER_RAISE (class_loaded, (klass));
6252
6253         return klass;
6254 }
6255
6256 /**
6257  * mono_class_from_generic_parameter:
6258  * \param param Parameter to find/construct a class for.
6259  * \param arg2 Is ignored.
6260  * \param arg3 Is ignored.
6261  */
6262 MonoClass *
6263 mono_class_from_generic_parameter (MonoGenericParam *param, MonoImage *arg2 G_GNUC_UNUSED, gboolean arg3 G_GNUC_UNUSED)
6264 {
6265         return mono_class_from_generic_parameter_internal (param);
6266 }
6267
6268 /**
6269  * mono_ptr_class_get:
6270  */
6271 MonoClass *
6272 mono_ptr_class_get (MonoType *type)
6273 {
6274         MonoClass *result;
6275         MonoClass *el_class;
6276         MonoImage *image;
6277         char *name;
6278
6279         el_class = mono_class_from_mono_type (type);
6280         image = el_class->image;
6281
6282         mono_image_lock (image);
6283         if (image->ptr_cache) {
6284                 if ((result = (MonoClass *)g_hash_table_lookup (image->ptr_cache, el_class))) {
6285                         mono_image_unlock (image);
6286                         return result;
6287                 }
6288         }
6289         mono_image_unlock (image);
6290         
6291         result = (MonoClass *)mono_image_alloc0 (image, sizeof (MonoClassPointer));
6292
6293         UnlockedAdd (&classes_size, sizeof (MonoClassPointer));
6294         ++class_pointer_count;
6295
6296         result->parent = NULL; /* no parent for PTR types */
6297         result->name_space = el_class->name_space;
6298         name = g_strdup_printf ("%s*", el_class->name);
6299         result->name = mono_image_strdup (image, name);
6300         result->class_kind = MONO_CLASS_POINTER;
6301         g_free (name);
6302
6303         MONO_PROFILER_RAISE (class_loading, (result));
6304
6305         result->image = el_class->image;
6306         result->inited = TRUE;
6307         result->instance_size = sizeof (MonoObject) + sizeof (gpointer);
6308         result->cast_class = result->element_class = el_class;
6309         result->blittable = TRUE;
6310
6311         result->byval_arg.type = MONO_TYPE_PTR;
6312         result->this_arg.type = result->byval_arg.type;
6313         result->this_arg.data.type = result->byval_arg.data.type = &result->element_class->byval_arg;
6314         result->this_arg.byref = TRUE;
6315
6316         mono_class_setup_supertypes (result);
6317
6318         mono_image_lock (image);
6319         if (image->ptr_cache) {
6320                 MonoClass *result2;
6321                 if ((result2 = (MonoClass *)g_hash_table_lookup (image->ptr_cache, el_class))) {
6322                         mono_image_unlock (image);
6323                         MONO_PROFILER_RAISE (class_failed, (result));
6324                         return result2;
6325                 }
6326         } else {
6327                 image->ptr_cache = g_hash_table_new (mono_aligned_addr_hash, NULL);
6328         }
6329         g_hash_table_insert (image->ptr_cache, el_class, result);
6330         mono_image_unlock (image);
6331
6332         MONO_PROFILER_RAISE (class_loaded, (result));
6333
6334         return result;
6335 }
6336
6337 static MonoClass *
6338 mono_fnptr_class_get (MonoMethodSignature *sig)
6339 {
6340         MonoClass *result, *cached;
6341         static GHashTable *ptr_hash = NULL;
6342
6343         /* FIXME: These should be allocate from a mempool as well, but which one ? */
6344
6345         mono_loader_lock ();
6346         if (!ptr_hash)
6347                 ptr_hash = g_hash_table_new (mono_aligned_addr_hash, NULL);
6348         cached = (MonoClass *)g_hash_table_lookup (ptr_hash, sig);
6349         mono_loader_unlock ();
6350         if (cached)
6351                 return cached;
6352
6353         result = g_new0 (MonoClass, 1);
6354
6355         result->parent = NULL; /* no parent for PTR types */
6356         result->name_space = "System";
6357         result->name = "MonoFNPtrFakeClass";
6358         result->class_kind = MONO_CLASS_POINTER;
6359
6360         result->image = mono_defaults.corlib; /* need to fix... */
6361         result->instance_size = sizeof (MonoObject) + sizeof (gpointer);
6362         result->cast_class = result->element_class = result;
6363         result->byval_arg.type = MONO_TYPE_FNPTR;
6364         result->this_arg.type = result->byval_arg.type;
6365         result->this_arg.data.method = result->byval_arg.data.method = sig;
6366         result->this_arg.byref = TRUE;
6367         result->blittable = TRUE;
6368         result->inited = TRUE;
6369
6370         mono_class_setup_supertypes (result);
6371
6372         mono_loader_lock ();
6373
6374         cached = (MonoClass *)g_hash_table_lookup (ptr_hash, sig);
6375         if (cached) {
6376                 g_free (result);
6377                 mono_loader_unlock ();
6378                 return cached;
6379         }
6380
6381         MONO_PROFILER_RAISE (class_loading, (result));
6382
6383         UnlockedAdd (&classes_size, sizeof (MonoClassPointer));
6384         ++class_pointer_count;
6385
6386         g_hash_table_insert (ptr_hash, sig, result);
6387
6388         mono_loader_unlock ();
6389
6390         MONO_PROFILER_RAISE (class_loaded, (result));
6391
6392         return result;
6393 }
6394
6395 /**
6396  * mono_class_from_mono_type:
6397  * \param type describes the type to return
6398  * \returns a \c MonoClass for the specified \c MonoType, the value is never NULL.
6399  */
6400 MonoClass *
6401 mono_class_from_mono_type (MonoType *type)
6402 {
6403         switch (type->type) {
6404         case MONO_TYPE_OBJECT:
6405                 return type->data.klass? type->data.klass: mono_defaults.object_class;
6406         case MONO_TYPE_VOID:
6407                 return type->data.klass? type->data.klass: mono_defaults.void_class;
6408         case MONO_TYPE_BOOLEAN:
6409                 return type->data.klass? type->data.klass: mono_defaults.boolean_class;
6410         case MONO_TYPE_CHAR:
6411                 return type->data.klass? type->data.klass: mono_defaults.char_class;
6412         case MONO_TYPE_I1:
6413                 return type->data.klass? type->data.klass: mono_defaults.sbyte_class;
6414         case MONO_TYPE_U1:
6415                 return type->data.klass? type->data.klass: mono_defaults.byte_class;
6416         case MONO_TYPE_I2:
6417                 return type->data.klass? type->data.klass: mono_defaults.int16_class;
6418         case MONO_TYPE_U2:
6419                 return type->data.klass? type->data.klass: mono_defaults.uint16_class;
6420         case MONO_TYPE_I4:
6421                 return type->data.klass? type->data.klass: mono_defaults.int32_class;
6422         case MONO_TYPE_U4:
6423                 return type->data.klass? type->data.klass: mono_defaults.uint32_class;
6424         case MONO_TYPE_I:
6425                 return type->data.klass? type->data.klass: mono_defaults.int_class;
6426         case MONO_TYPE_U:
6427                 return type->data.klass? type->data.klass: mono_defaults.uint_class;
6428         case MONO_TYPE_I8:
6429                 return type->data.klass? type->data.klass: mono_defaults.int64_class;
6430         case MONO_TYPE_U8:
6431                 return type->data.klass? type->data.klass: mono_defaults.uint64_class;
6432         case MONO_TYPE_R4:
6433                 return type->data.klass? type->data.klass: mono_defaults.single_class;
6434         case MONO_TYPE_R8:
6435                 return type->data.klass? type->data.klass: mono_defaults.double_class;
6436         case MONO_TYPE_STRING:
6437                 return type->data.klass? type->data.klass: mono_defaults.string_class;
6438         case MONO_TYPE_TYPEDBYREF:
6439                 return type->data.klass? type->data.klass: mono_defaults.typed_reference_class;
6440         case MONO_TYPE_ARRAY:
6441                 return mono_bounded_array_class_get (type->data.array->eklass, type->data.array->rank, TRUE);
6442         case MONO_TYPE_PTR:
6443                 return mono_ptr_class_get (type->data.type);
6444         case MONO_TYPE_FNPTR:
6445                 return mono_fnptr_class_get (type->data.method);
6446         case MONO_TYPE_SZARRAY:
6447                 return mono_array_class_get (type->data.klass, 1);
6448         case MONO_TYPE_CLASS:
6449         case MONO_TYPE_VALUETYPE:
6450                 return type->data.klass;
6451         case MONO_TYPE_GENERICINST:
6452                 return mono_generic_class_get_class (type->data.generic_class);
6453         case MONO_TYPE_MVAR:
6454         case MONO_TYPE_VAR:
6455                 return mono_class_from_generic_parameter_internal (type->data.generic_param);
6456         default:
6457                 g_warning ("mono_class_from_mono_type: implement me 0x%02x\n", type->type);
6458                 g_assert_not_reached ();
6459         }
6460
6461         // Yes, this returns NULL, even if it is documented as not doing so, but there
6462         // is no way for the code to make it this far, due to the assert above.
6463         return NULL;
6464 }
6465
6466 /**
6467  * mono_type_retrieve_from_typespec
6468  * \param image context where the image is created
6469  * \param type_spec  typespec token
6470  * \param context the generic context used to evaluate generic instantiations in
6471  */
6472 static MonoType *
6473 mono_type_retrieve_from_typespec (MonoImage *image, guint32 type_spec, MonoGenericContext *context, gboolean *did_inflate, MonoError *error)
6474 {
6475         MonoType *t = mono_type_create_from_typespec_checked (image, type_spec, error);
6476
6477         *did_inflate = FALSE;
6478
6479         if (!t)
6480                 return NULL;
6481
6482         if (context && (context->class_inst || context->method_inst)) {
6483                 MonoType *inflated = inflate_generic_type (NULL, t, context, error);
6484
6485                 if (!mono_error_ok (error)) {
6486                         return NULL;
6487                 }
6488
6489                 if (inflated) {
6490                         t = inflated;
6491                         *did_inflate = TRUE;
6492                 }
6493         }
6494         return t;
6495 }
6496
6497 /**
6498  * mono_class_create_from_typespec
6499  * \param image context where the image is created
6500  * \param type_spec typespec token
6501  * \param context the generic context used to evaluate generic instantiations in
6502  */
6503 static MonoClass *
6504 mono_class_create_from_typespec (MonoImage *image, guint32 type_spec, MonoGenericContext *context, MonoError *error)
6505 {
6506         MonoClass *ret;
6507         gboolean inflated = FALSE;
6508         MonoType *t = mono_type_retrieve_from_typespec (image, type_spec, context, &inflated, error);
6509         return_val_if_nok (error, NULL);
6510         ret = mono_class_from_mono_type (t);
6511         if (inflated)
6512                 mono_metadata_free_type (t);
6513         return ret;
6514 }
6515
6516 /**
6517  * mono_bounded_array_class_get:
6518  * \param element_class element class 
6519  * \param rank the dimension of the array class
6520  * \param bounded whenever the array has non-zero bounds
6521  * \returns A class object describing the array with element type \p element_type and 
6522  * dimension \p rank.
6523  */
6524 MonoClass *
6525 mono_bounded_array_class_get (MonoClass *eclass, guint32 rank, gboolean bounded)
6526 {
6527         MonoImage *image;
6528         MonoClass *klass, *cached, *k;
6529         MonoClass *parent = NULL;
6530         GSList *list, *rootlist = NULL;
6531         int nsize;
6532         char *name;
6533
6534         g_assert (rank <= 255);
6535
6536         if (rank > 1)
6537                 /* bounded only matters for one-dimensional arrays */
6538                 bounded = FALSE;
6539
6540         image = eclass->image;
6541
6542         /* Check cache */
6543         cached = NULL;
6544         if (rank == 1 && !bounded) {
6545                 /*
6546                  * This case is very frequent not just during compilation because of calls
6547                  * from mono_class_from_mono_type (), mono_array_new (),
6548                  * Array:CreateInstance (), etc, so use a separate cache + a separate lock.
6549                  */
6550                 mono_os_mutex_lock (&image->szarray_cache_lock);
6551                 if (!image->szarray_cache)
6552                         image->szarray_cache = g_hash_table_new (mono_aligned_addr_hash, NULL);
6553                 cached = (MonoClass *)g_hash_table_lookup (image->szarray_cache, eclass);
6554                 mono_os_mutex_unlock (&image->szarray_cache_lock);
6555         } else {
6556                 mono_loader_lock ();
6557                 if (!image->array_cache)
6558                         image->array_cache = g_hash_table_new (mono_aligned_addr_hash, NULL);
6559                 rootlist = (GSList *)g_hash_table_lookup (image->array_cache, eclass);
6560                 for (list = rootlist; list; list = list->next) {
6561                         k = (MonoClass *)list->data;
6562                         if ((k->rank == rank) && (k->byval_arg.type == (((rank > 1) || bounded) ? MONO_TYPE_ARRAY : MONO_TYPE_SZARRAY))) {
6563                                 cached = k;
6564                                 break;
6565                         }
6566                 }
6567                 mono_loader_unlock ();
6568         }
6569         if (cached)
6570                 return cached;
6571
6572         parent = mono_defaults.array_class;
6573         if (!parent->inited)
6574                 mono_class_init (parent);
6575
6576         klass = (MonoClass *)mono_image_alloc0 (image, sizeof (MonoClassArray));
6577
6578         klass->image = image;
6579         klass->name_space = eclass->name_space;
6580         klass->class_kind = MONO_CLASS_ARRAY;
6581
6582         nsize = strlen (eclass->name);
6583         name = (char *)g_malloc (nsize + 2 + rank + 1);
6584         memcpy (name, eclass->name, nsize);
6585         name [nsize] = '[';
6586         if (rank > 1)
6587                 memset (name + nsize + 1, ',', rank - 1);
6588         if (bounded)
6589                 name [nsize + rank] = '*';
6590         name [nsize + rank + bounded] = ']';
6591         name [nsize + rank + bounded + 1] = 0;
6592         klass->name = mono_image_strdup (image, name);
6593         g_free (name);
6594
6595         klass->type_token = 0;
6596         klass->parent = parent;
6597         klass->instance_size = mono_class_instance_size (klass->parent);
6598
6599         if (eclass->byval_arg.type == MONO_TYPE_TYPEDBYREF) {
6600                 /*Arrays of those two types are invalid.*/
6601                 MonoError prepared_error;
6602                 error_init (&prepared_error);
6603                 mono_error_set_invalid_program (&prepared_error, "Arrays of System.TypedReference types are invalid.");
6604                 mono_class_set_failure (klass, mono_error_box (&prepared_error, klass->image));
6605                 mono_error_cleanup (&prepared_error);
6606         } else if (eclass->enumtype && !mono_class_enum_basetype (eclass)) {
6607                 guint32 ref_info_handle = mono_class_get_ref_info_handle (eclass);
6608                 if (!ref_info_handle || eclass->wastypebuilder) {
6609                         g_warning ("Only incomplete TypeBuilder objects are allowed to be an enum without base_type");
6610                         g_assert (ref_info_handle && !eclass->wastypebuilder);
6611                 }
6612                 /* element_size -1 is ok as this is not an instantitable type*/
6613                 klass->sizes.element_size = -1;
6614         } else
6615                 klass->sizes.element_size = -1;
6616
6617         mono_class_setup_supertypes (klass);
6618
6619         if (mono_class_is_ginst (eclass))
6620                 mono_class_init (eclass);
6621         if (!eclass->size_inited)
6622                 mono_class_setup_fields (eclass);
6623         mono_class_set_type_load_failure_causedby_class (klass, eclass, "Could not load array element type");
6624         /*FIXME we fail the array type, but we have to let other fields be set.*/
6625
6626         klass->has_references = MONO_TYPE_IS_REFERENCE (&eclass->byval_arg) || eclass->has_references? TRUE: FALSE;
6627
6628         klass->rank = rank;
6629         
6630         if (eclass->enumtype)
6631                 klass->cast_class = eclass->element_class;
6632         else
6633                 klass->cast_class = eclass;
6634
6635         switch (klass->cast_class->byval_arg.type) {
6636         case MONO_TYPE_I1:
6637                 klass->cast_class = mono_defaults.byte_class;
6638                 break;
6639         case MONO_TYPE_U2:
6640                 klass->cast_class = mono_defaults.int16_class;
6641                 break;
6642         case MONO_TYPE_U4:
6643 #if SIZEOF_VOID_P == 4
6644         case MONO_TYPE_I:
6645         case MONO_TYPE_U:
6646 #endif
6647                 klass->cast_class = mono_defaults.int32_class;
6648                 break;
6649         case MONO_TYPE_U8:
6650 #if SIZEOF_VOID_P == 8
6651         case MONO_TYPE_I:
6652         case MONO_TYPE_U:
6653 #endif
6654                 klass->cast_class = mono_defaults.int64_class;
6655                 break;
6656         default:
6657                 break;
6658         }
6659
6660         klass->element_class = eclass;
6661
6662         if ((rank > 1) || bounded) {
6663                 MonoArrayType *at = (MonoArrayType *)mono_image_alloc0 (image, sizeof (MonoArrayType));
6664                 klass->byval_arg.type = MONO_TYPE_ARRAY;
6665                 klass->byval_arg.data.array = at;
6666                 at->eklass = eclass;
6667                 at->rank = rank;
6668                 /* FIXME: complete.... */
6669         } else {
6670                 klass->byval_arg.type = MONO_TYPE_SZARRAY;
6671                 klass->byval_arg.data.klass = eclass;
6672         }
6673         klass->this_arg = klass->byval_arg;
6674         klass->this_arg.byref = 1;
6675
6676         if (rank > 32) {
6677                 MonoError prepared_error;
6678                 error_init (&prepared_error);
6679                 name = mono_type_get_full_name (klass);
6680                 mono_error_set_type_load_class (&prepared_error, klass, "%s has too many dimensions.", name);
6681                 mono_class_set_failure (klass, mono_error_box (&prepared_error, klass->image));
6682                 mono_error_cleanup (&prepared_error);
6683                 g_free (name);
6684         }
6685
6686         mono_loader_lock ();
6687
6688         /* Check cache again */
6689         cached = NULL;
6690         if (rank == 1 && !bounded) {
6691                 mono_os_mutex_lock (&image->szarray_cache_lock);
6692                 cached = (MonoClass *)g_hash_table_lookup (image->szarray_cache, eclass);
6693                 mono_os_mutex_unlock (&image->szarray_cache_lock);
6694         } else {
6695                 rootlist = (GSList *)g_hash_table_lookup (image->array_cache, eclass);
6696                 for (list = rootlist; list; list = list->next) {
6697                         k = (MonoClass *)list->data;
6698                         if ((k->rank == rank) && (k->byval_arg.type == (((rank > 1) || bounded) ? MONO_TYPE_ARRAY : MONO_TYPE_SZARRAY))) {
6699                                 cached = k;
6700                                 break;
6701                         }
6702                 }
6703         }
6704         if (cached) {
6705                 mono_loader_unlock ();
6706                 return cached;
6707         }
6708
6709         MONO_PROFILER_RAISE (class_loading, (klass));
6710
6711         UnlockedAdd (&classes_size, sizeof (MonoClassArray));
6712         ++class_array_count;
6713
6714         if (rank == 1 && !bounded) {
6715                 mono_os_mutex_lock (&image->szarray_cache_lock);
6716                 g_hash_table_insert (image->szarray_cache, eclass, klass);
6717                 mono_os_mutex_unlock (&image->szarray_cache_lock);
6718         } else {
6719                 list = g_slist_append (rootlist, klass);
6720                 g_hash_table_insert (image->array_cache, eclass, list);
6721         }
6722
6723         mono_loader_unlock ();
6724
6725         MONO_PROFILER_RAISE (class_loaded, (klass));
6726
6727         return klass;
6728 }
6729
6730 /**
6731  * mono_array_class_get:
6732  * \param element_class element class 
6733  * \param rank the dimension of the array class
6734  * \returns A class object describing the array with element type \p element_type and 
6735  * dimension \p rank.
6736  */
6737 MonoClass *
6738 mono_array_class_get (MonoClass *eclass, guint32 rank)
6739 {
6740         return mono_bounded_array_class_get (eclass, rank, FALSE);
6741 }
6742
6743 /**
6744  * mono_class_instance_size:
6745  * \param klass a class
6746  *
6747  * Use to get the size of a class in bytes.
6748  *
6749  * \returns The size of an object instance
6750  */
6751 gint32
6752 mono_class_instance_size (MonoClass *klass)
6753 {       
6754         if (!klass->size_inited)
6755                 mono_class_init (klass);
6756
6757         return klass->instance_size;
6758 }
6759
6760 /**
6761  * mono_class_min_align:
6762  * \param klass a class 
6763  *
6764  * Use to get the computed minimum alignment requirements for the specified class.
6765  *
6766  * Returns: minimum alignment requirements
6767  */
6768 gint32
6769 mono_class_min_align (MonoClass *klass)
6770 {       
6771         if (!klass->size_inited)
6772                 mono_class_init (klass);
6773
6774         return klass->min_align;
6775 }
6776
6777 /**
6778  * mono_class_value_size:
6779  * \param klass a class 
6780  *
6781  * This function is used for value types, and return the
6782  * space and the alignment to store that kind of value object.
6783  *
6784  * \returns the size of a value of kind \p klass
6785  */
6786 gint32
6787 mono_class_value_size (MonoClass *klass, guint32 *align)
6788 {
6789         gint32 size;
6790
6791         /* fixme: check disable, because we still have external revereces to
6792          * mscorlib and Dummy Objects 
6793          */
6794         /*g_assert (klass->valuetype);*/
6795
6796         size = mono_class_instance_size (klass) - sizeof (MonoObject);
6797
6798         if (align)
6799                 *align = klass->min_align;
6800
6801         return size;
6802 }
6803
6804 /**
6805  * mono_class_data_size:
6806  * \param klass a class 
6807  * 
6808  * \returns The size of the static class data
6809  */
6810 gint32
6811 mono_class_data_size (MonoClass *klass)
6812 {       
6813         if (!klass->inited)
6814                 mono_class_init (klass);
6815         /* This can happen with dynamically created types */
6816         if (!klass->fields_inited)
6817                 mono_class_setup_fields (klass);
6818
6819         /* in arrays, sizes.class_size is unioned with element_size
6820          * and arrays have no static fields
6821          */
6822         if (klass->rank)
6823                 return 0;
6824         return klass->sizes.class_size;
6825 }
6826
6827 /*
6828  * Auxiliary routine to mono_class_get_field
6829  *
6830  * Takes a field index instead of a field token.
6831  */
6832 static MonoClassField *
6833 mono_class_get_field_idx (MonoClass *klass, int idx)
6834 {
6835         mono_class_setup_fields (klass);
6836         if (mono_class_has_failure (klass))
6837                 return NULL;
6838
6839         while (klass) {
6840                 int first_field_idx = mono_class_get_first_field_idx (klass);
6841                 int fcount = mono_class_get_field_count (klass);
6842                 if (klass->image->uncompressed_metadata) {
6843                         /* 
6844                          * first_field_idx points to the FieldPtr table, while idx points into the
6845                          * Field table, so we have to do a search.
6846                          */
6847                         /*FIXME this is broken for types with multiple fields with the same name.*/
6848                         const char *name = mono_metadata_string_heap (klass->image, mono_metadata_decode_row_col (&klass->image->tables [MONO_TABLE_FIELD], idx, MONO_FIELD_NAME));
6849                         int i;
6850
6851                         for (i = 0; i < fcount; ++i)
6852                                 if (mono_field_get_name (&klass->fields [i]) == name)
6853                                         return &klass->fields [i];
6854                         g_assert_not_reached ();
6855                 } else {                        
6856                         if (fcount) {
6857                                 if ((idx >= first_field_idx) && (idx < first_field_idx + fcount)){
6858                                         return &klass->fields [idx - first_field_idx];
6859                                 }
6860                         }
6861                 }
6862                 klass = klass->parent;
6863         }
6864         return NULL;
6865 }
6866
6867 /**
6868  * mono_class_get_field:
6869  * \param class the class to lookup the field.
6870  * \param field_token the field token
6871  *
6872  * \returns A \c MonoClassField representing the type and offset of
6873  * the field, or a NULL value if the field does not belong to this
6874  * class.
6875  */
6876 MonoClassField *
6877 mono_class_get_field (MonoClass *klass, guint32 field_token)
6878 {
6879         int idx = mono_metadata_token_index (field_token);
6880
6881         g_assert (mono_metadata_token_code (field_token) == MONO_TOKEN_FIELD_DEF);
6882
6883         return mono_class_get_field_idx (klass, idx - 1);
6884 }
6885
6886 /**
6887  * mono_class_get_field_from_name:
6888  * \param klass the class to lookup the field.
6889  * \param name the field name
6890  *
6891  * Search the class \p klass and its parents for a field with the name \p name.
6892  * 
6893  * \returns The \c MonoClassField pointer of the named field or NULL
6894  */
6895 MonoClassField *
6896 mono_class_get_field_from_name (MonoClass *klass, const char *name)
6897 {
6898         return mono_class_get_field_from_name_full (klass, name, NULL);
6899 }
6900
6901 /**
6902  * mono_class_get_field_from_name_full:
6903  * \param klass the class to lookup the field.
6904  * \param name the field name
6905  * \param type the type of the fields. This optional.
6906  *
6907  * Search the class \p klass and it's parents for a field with the name \p name and type \p type.
6908  *
6909  * If \p klass is an inflated generic type, the type comparison is done with the equivalent field
6910  * of its generic type definition.
6911  *
6912  * \returns The MonoClassField pointer of the named field or NULL
6913  */
6914 MonoClassField *
6915 mono_class_get_field_from_name_full (MonoClass *klass, const char *name, MonoType *type)
6916 {
6917         int i;
6918
6919         mono_class_setup_fields (klass);
6920         if (mono_class_has_failure (klass))
6921                 return NULL;
6922
6923         while (klass) {
6924                 int fcount = mono_class_get_field_count (klass);
6925                 for (i = 0; i < fcount; ++i) {
6926                         MonoClassField *field = &klass->fields [i];
6927
6928                         if (strcmp (name, mono_field_get_name (field)) != 0)
6929                                 continue;
6930
6931                         if (type) {
6932                                 MonoType *field_type = mono_metadata_get_corresponding_field_from_generic_type_definition (field)->type;
6933                                 if (!mono_metadata_type_equal_full (type, field_type, TRUE))
6934                                         continue;
6935                         }
6936                         return field;
6937                 }
6938                 klass = klass->parent;
6939         }
6940         return NULL;
6941 }
6942
6943 /**
6944  * mono_class_get_field_token:
6945  * \param field the field we need the token of
6946  *
6947  * Get the token of a field. Note that the tokesn is only valid for the image
6948  * the field was loaded from. Don't use this function for fields in dynamic types.
6949  * 
6950  * \returns The token representing the field in the image it was loaded from.
6951  */
6952 guint32
6953 mono_class_get_field_token (MonoClassField *field)
6954 {
6955         MonoClass *klass = field->parent;
6956         int i;
6957
6958         mono_class_setup_fields (klass);
6959
6960         while (klass) {
6961                 if (!klass->fields)
6962                         return 0;
6963                 int first_field_idx = mono_class_get_first_field_idx (klass);
6964                 int fcount = mono_class_get_field_count (klass);
6965                 for (i = 0; i < fcount; ++i) {
6966                         if (&klass->fields [i] == field) {
6967                                 int idx = first_field_idx + i + 1;
6968
6969                                 if (klass->image->uncompressed_metadata)
6970                                         idx = mono_metadata_translate_token_index (klass->image, MONO_TABLE_FIELD, idx);
6971                                 return mono_metadata_make_token (MONO_TABLE_FIELD, idx);
6972                         }
6973                 }
6974                 klass = klass->parent;
6975         }
6976
6977         g_assert_not_reached ();
6978         return 0;
6979 }
6980
6981 static int
6982 mono_field_get_index (MonoClassField *field)
6983 {
6984         int index = field - field->parent->fields;
6985         g_assert (index >= 0 && index < mono_class_get_field_count (field->parent));
6986
6987         return index;
6988 }
6989
6990 /*
6991  * mono_class_get_field_default_value:
6992  *
6993  * Return the default value of the field as a pointer into the metadata blob.
6994  */
6995 const char*
6996 mono_class_get_field_default_value (MonoClassField *field, MonoTypeEnum *def_type)
6997 {
6998         guint32 cindex;
6999         guint32 constant_cols [MONO_CONSTANT_SIZE];
7000         int field_index;
7001         MonoClass *klass = field->parent;
7002         MonoFieldDefaultValue *def_values;
7003
7004         g_assert (field->type->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT);
7005
7006         def_values = mono_class_get_field_def_values (klass);
7007         if (!def_values) {
7008                 def_values = (MonoFieldDefaultValue *)mono_class_alloc0 (klass, sizeof (MonoFieldDefaultValue) * mono_class_get_field_count (klass));
7009
7010                 mono_class_set_field_def_values (klass, def_values);
7011         }
7012
7013         field_index = mono_field_get_index (field);
7014                 
7015         if (!def_values [field_index].data) {
7016                 cindex = mono_metadata_get_constant_index (field->parent->image, mono_class_get_field_token (field), 0);
7017                 if (!cindex)
7018                         return NULL;
7019
7020                 g_assert (!(field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA));
7021
7022                 mono_metadata_decode_row (&field->parent->image->tables [MONO_TABLE_CONSTANT], cindex - 1, constant_cols, MONO_CONSTANT_SIZE);
7023                 def_values [field_index].def_type = (MonoTypeEnum)constant_cols [MONO_CONSTANT_TYPE];
7024                 mono_memory_barrier ();
7025                 def_values [field_index].data = (const char *)mono_metadata_blob_heap (field->parent->image, constant_cols [MONO_CONSTANT_VALUE]);
7026         }
7027
7028         *def_type = def_values [field_index].def_type;
7029         return def_values [field_index].data;
7030 }
7031
7032 static int
7033 mono_property_get_index (MonoProperty *prop)
7034 {
7035         MonoClassPropertyInfo *info = mono_class_get_property_info (prop->parent);
7036         int index = prop - info->properties;
7037
7038         g_assert (index >= 0 && index < info->count);
7039
7040         return index;
7041 }
7042
7043 /*
7044  * mono_class_get_property_default_value:
7045  *
7046  * Return the default value of the field as a pointer into the metadata blob.
7047  */
7048 const char*
7049 mono_class_get_property_default_value (MonoProperty *property, MonoTypeEnum *def_type)
7050 {
7051         guint32 cindex;
7052         guint32 constant_cols [MONO_CONSTANT_SIZE];
7053         MonoClass *klass = property->parent;
7054
7055         g_assert (property->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT);
7056         /*
7057          * We don't cache here because it is not used by C# so it's quite rare, but
7058          * we still do the lookup in klass->ext because that is where the data
7059          * is stored for dynamic assemblies.
7060          */
7061
7062         if (image_is_dynamic (klass->image)) {
7063                 MonoClassPropertyInfo *info = mono_class_get_property_info (klass);
7064                 int prop_index = mono_property_get_index (property);
7065                 if (info->def_values && info->def_values [prop_index].data) {
7066                         *def_type = info->def_values [prop_index].def_type;
7067                         return info->def_values [prop_index].data;
7068                 }
7069                 return NULL;
7070         }
7071         cindex = mono_metadata_get_constant_index (klass->image, mono_class_get_property_token (property), 0);
7072         if (!cindex)
7073                 return NULL;
7074
7075         mono_metadata_decode_row (&klass->image->tables [MONO_TABLE_CONSTANT], cindex - 1, constant_cols, MONO_CONSTANT_SIZE);
7076         *def_type = (MonoTypeEnum)constant_cols [MONO_CONSTANT_TYPE];
7077         return (const char *)mono_metadata_blob_heap (klass->image, constant_cols [MONO_CONSTANT_VALUE]);
7078 }
7079
7080 /**
7081  * mono_class_get_event_token:
7082  */
7083 guint32
7084 mono_class_get_event_token (MonoEvent *event)
7085 {
7086         MonoClass *klass = event->parent;
7087         int i;
7088
7089         while (klass) {
7090                 MonoClassEventInfo *info = mono_class_get_event_info (klass);
7091                 if (info) {
7092                         for (i = 0; i < info->count; ++i) {
7093                                 if (&info->events [i] == event)
7094                                         return mono_metadata_make_token (MONO_TABLE_EVENT, info->first + i + 1);
7095                         }
7096                 }
7097                 klass = klass->parent;
7098         }
7099
7100         g_assert_not_reached ();
7101         return 0;
7102 }
7103
7104 /**
7105  * mono_class_get_property_from_name:
7106  * \param klass a class
7107  * \param name name of the property to lookup in the specified class
7108  *
7109  * Use this method to lookup a property in a class
7110  * \returns the \c MonoProperty with the given name, or NULL if the property
7111  * does not exist on the \p klass.
7112  */
7113 MonoProperty*
7114 mono_class_get_property_from_name (MonoClass *klass, const char *name)
7115 {
7116         while (klass) {
7117                 MonoProperty* p;
7118                 gpointer iter = NULL;
7119                 while ((p = mono_class_get_properties (klass, &iter))) {
7120                         if (! strcmp (name, p->name))
7121                                 return p;
7122                 }
7123                 klass = klass->parent;
7124         }
7125         return NULL;
7126 }
7127
7128 /**
7129  * mono_class_get_property_token:
7130  * \param prop MonoProperty to query
7131  *
7132  * \returns The ECMA token for the specified property.
7133  */
7134 guint32
7135 mono_class_get_property_token (MonoProperty *prop)
7136 {
7137         MonoClass *klass = prop->parent;
7138         while (klass) {
7139                 MonoProperty* p;
7140                 int i = 0;
7141                 gpointer iter = NULL;
7142                 MonoClassPropertyInfo *info = mono_class_get_property_info (klass);
7143                 while ((p = mono_class_get_properties (klass, &iter))) {
7144                         if (&info->properties [i] == prop)
7145                                 return mono_metadata_make_token (MONO_TABLE_PROPERTY, info->first + i + 1);
7146                         
7147                         i ++;
7148                 }
7149                 klass = klass->parent;
7150         }
7151
7152         g_assert_not_reached ();
7153         return 0;
7154 }
7155
7156 /**
7157  * mono_class_name_from_token:
7158  */
7159 char *
7160 mono_class_name_from_token (MonoImage *image, guint32 type_token)
7161 {
7162         const char *name, *nspace;
7163         if (image_is_dynamic (image))
7164                 return g_strdup_printf ("DynamicType 0x%08x", type_token);
7165         
7166         switch (type_token & 0xff000000){
7167         case MONO_TOKEN_TYPE_DEF: {
7168                 guint32 cols [MONO_TYPEDEF_SIZE];
7169                 MonoTableInfo *tt = &image->tables [MONO_TABLE_TYPEDEF];
7170                 guint tidx = mono_metadata_token_index (type_token);
7171
7172                 if (tidx > tt->rows)
7173                         return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7174
7175                 mono_metadata_decode_row (tt, tidx - 1, cols, MONO_TYPEDEF_SIZE);
7176                 name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
7177                 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
7178                 if (strlen (nspace) == 0)
7179                         return g_strdup_printf ("%s", name);
7180                 else
7181                         return g_strdup_printf ("%s.%s", nspace, name);
7182         }
7183
7184         case MONO_TOKEN_TYPE_REF: {
7185                 MonoError error;
7186                 guint32 cols [MONO_TYPEREF_SIZE];
7187                 MonoTableInfo  *t = &image->tables [MONO_TABLE_TYPEREF];
7188                 guint tidx = mono_metadata_token_index (type_token);
7189
7190                 if (tidx > t->rows)
7191                         return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7192
7193                 if (!mono_verifier_verify_typeref_row (image, tidx - 1, &error)) {
7194                         char *msg = g_strdup_printf ("Invalid type token 0x%08x due to '%s'", type_token, mono_error_get_message (&error));
7195                         mono_error_cleanup (&error);
7196                         return msg;
7197                 }
7198
7199                 mono_metadata_decode_row (t, tidx-1, cols, MONO_TYPEREF_SIZE);
7200                 name = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAME]);
7201                 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAMESPACE]);
7202                 if (strlen (nspace) == 0)
7203                         return g_strdup_printf ("%s", name);
7204                 else
7205                         return g_strdup_printf ("%s.%s", nspace, name);
7206         }
7207                 
7208         case MONO_TOKEN_TYPE_SPEC:
7209                 return g_strdup_printf ("Typespec 0x%08x", type_token);
7210         default:
7211                 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7212         }
7213 }
7214
7215 static char *
7216 mono_assembly_name_from_token (MonoImage *image, guint32 type_token)
7217 {
7218         if (image_is_dynamic (image))
7219                 return g_strdup_printf ("DynamicAssembly %s", image->name);
7220         
7221         switch (type_token & 0xff000000){
7222         case MONO_TOKEN_TYPE_DEF:
7223                 if (image->assembly)
7224                         return mono_stringify_assembly_name (&image->assembly->aname);
7225                 else if (image->assembly_name)
7226                         return g_strdup (image->assembly_name);
7227                 return g_strdup_printf ("%s", image->name ? image->name : "[Could not resolve assembly name");
7228         case MONO_TOKEN_TYPE_REF: {
7229                 MonoError error;
7230                 MonoAssemblyName aname;
7231                 guint32 cols [MONO_TYPEREF_SIZE];
7232                 MonoTableInfo  *t = &image->tables [MONO_TABLE_TYPEREF];
7233                 guint32 idx = mono_metadata_token_index (type_token);
7234
7235                 if (idx > t->rows)
7236                         return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7237         
7238                 if (!mono_verifier_verify_typeref_row (image, idx - 1, &error)) {
7239                         char *msg = g_strdup_printf ("Invalid type token 0x%08x due to '%s'", type_token, mono_error_get_message (&error));
7240                         mono_error_cleanup (&error);
7241                         return msg;
7242                 }
7243                 mono_metadata_decode_row (t, idx-1, cols, MONO_TYPEREF_SIZE);
7244
7245                 idx = cols [MONO_TYPEREF_SCOPE] >> MONO_RESOLUTION_SCOPE_BITS;
7246                 switch (cols [MONO_TYPEREF_SCOPE] & MONO_RESOLUTION_SCOPE_MASK) {
7247                 case MONO_RESOLUTION_SCOPE_MODULE:
7248                         /* FIXME: */
7249                         return g_strdup ("");
7250                 case MONO_RESOLUTION_SCOPE_MODULEREF:
7251                         /* FIXME: */
7252                         return g_strdup ("");
7253                 case MONO_RESOLUTION_SCOPE_TYPEREF:
7254                         /* FIXME: */
7255                         return g_strdup ("");
7256                 case MONO_RESOLUTION_SCOPE_ASSEMBLYREF:
7257                         mono_assembly_get_assemblyref (image, idx - 1, &aname);
7258                         return mono_stringify_assembly_name (&aname);
7259                 default:
7260                         g_assert_not_reached ();
7261                 }
7262                 break;
7263         }
7264         case MONO_TOKEN_TYPE_SPEC:
7265                 /* FIXME: */
7266                 return g_strdup ("");
7267         default:
7268                 g_assert_not_reached ();
7269         }
7270
7271         return NULL;
7272 }
7273
7274 /**
7275  * mono_class_get_full:
7276  * \param image the image where the class resides
7277  * \param type_token the token for the class
7278  * \param context the generic context used to evaluate generic instantiations in
7279  * \deprecated Functions that expose \c MonoGenericContext are going away in mono 4.0
7280  * \returns The \c MonoClass that represents \p type_token in \p image
7281  */
7282 MonoClass *
7283 mono_class_get_full (MonoImage *image, guint32 type_token, MonoGenericContext *context)
7284 {
7285         MonoError error;
7286         MonoClass *klass;
7287         klass = mono_class_get_checked (image, type_token, &error);
7288
7289         if (klass && context && mono_metadata_token_table (type_token) == MONO_TABLE_TYPESPEC)
7290                 klass = mono_class_inflate_generic_class_checked (klass, context, &error);
7291
7292         g_assert (mono_error_ok (&error)); /* FIXME deprecate this function and forbit the runtime from using it. */
7293         return klass;
7294 }
7295
7296
7297 MonoClass *
7298 mono_class_get_and_inflate_typespec_checked (MonoImage *image, guint32 type_token, MonoGenericContext *context, MonoError *error)
7299 {
7300         MonoClass *klass;
7301
7302         error_init (error);
7303         klass = mono_class_get_checked (image, type_token, error);
7304
7305         if (klass && context && mono_metadata_token_table (type_token) == MONO_TABLE_TYPESPEC)
7306                 klass = mono_class_inflate_generic_class_checked (klass, context, error);
7307
7308         return klass;
7309 }
7310 /**
7311  * mono_class_get_checked:
7312  * \param image the image where the class resides
7313  * \param type_token the token for the class
7314  * \param error error object to return any error
7315  *
7316  * \returns The MonoClass that represents \p type_token in \p image, or NULL on error.
7317  */
7318 MonoClass *
7319 mono_class_get_checked (MonoImage *image, guint32 type_token, MonoError *error)
7320 {
7321         MonoClass *klass = NULL;
7322
7323         error_init (error);
7324
7325         if (image_is_dynamic (image)) {
7326                 int table = mono_metadata_token_table (type_token);
7327
7328                 if (table != MONO_TABLE_TYPEDEF && table != MONO_TABLE_TYPEREF && table != MONO_TABLE_TYPESPEC) {
7329                         mono_error_set_bad_image (error, image,"Bad token table for dynamic image: %x", table);
7330                         return NULL;
7331                 }
7332                 klass = (MonoClass *)mono_lookup_dynamic_token (image, type_token, NULL, error);
7333                 goto done;
7334         }
7335
7336         switch (type_token & 0xff000000){
7337         case MONO_TOKEN_TYPE_DEF:
7338                 klass = mono_class_create_from_typedef (image, type_token, error);
7339                 break;          
7340         case MONO_TOKEN_TYPE_REF:
7341                 klass = mono_class_from_typeref_checked (image, type_token, error);
7342                 break;
7343         case MONO_TOKEN_TYPE_SPEC:
7344                 klass = mono_class_create_from_typespec (image, type_token, NULL, error);
7345                 break;
7346         default:
7347                 mono_error_set_bad_image (error, image, "Unknown type token %x", type_token & 0xff000000);
7348         }
7349
7350 done:
7351         /* Generic case, should be avoided for when a better error is possible. */
7352         if (!klass && mono_error_ok (error)) {
7353                 char *name = mono_class_name_from_token (image, type_token);
7354                 char *assembly = mono_assembly_name_from_token (image, type_token);
7355                 mono_error_set_type_load_name (error, name, assembly, "Could not resolve type with token %08x (class/assembly %s, %s)", type_token, name, assembly);
7356         }
7357
7358         return klass;
7359 }
7360
7361
7362 /**
7363  * mono_type_get_checked:
7364  * \param image the image where the type resides
7365  * \param type_token the token for the type
7366  * \param context the generic context used to evaluate generic instantiations in
7367  * \param error Error handling context
7368  *
7369  * This functions exists to fullfill the fact that sometimes it's desirable to have access to the 
7370  * 
7371  * \returns The MonoType that represents \p type_token in \p image
7372  */
7373 MonoType *
7374 mono_type_get_checked (MonoImage *image, guint32 type_token, MonoGenericContext *context, MonoError *error)
7375 {
7376         MonoType *type = NULL;
7377         gboolean inflated = FALSE;
7378
7379         error_init (error);
7380
7381         //FIXME: this will not fix the very issue for which mono_type_get_full exists -but how to do it then?
7382         if (image_is_dynamic (image)) {
7383                 MonoClass *klass = (MonoClass *)mono_lookup_dynamic_token (image, type_token, context, error);
7384                 return_val_if_nok (error, NULL);
7385                 return mono_class_get_type (klass);
7386         }
7387
7388         if ((type_token & 0xff000000) != MONO_TOKEN_TYPE_SPEC) {
7389                 MonoClass *klass = mono_class_get_checked (image, type_token, error);
7390
7391                 if (!klass) {
7392                         return NULL;
7393                 }
7394
7395                 g_assert (klass);
7396                 return mono_class_get_type (klass);
7397         }
7398
7399         type = mono_type_retrieve_from_typespec (image, type_token, context, &inflated, error);
7400
7401         if (!type) {
7402                 return NULL;
7403         }
7404
7405         if (inflated) {
7406                 MonoType *tmp = type;
7407                 type = mono_class_get_type (mono_class_from_mono_type (type));
7408                 /* FIXME: This is a workaround fo the fact that a typespec token sometimes reference to the generic type definition.
7409                  * A MonoClass::byval_arg of a generic type definion has type CLASS.
7410                  * Some parts of mono create a GENERICINST to reference a generic type definition and this generates confict with byval_arg.
7411                  *
7412                  * The long term solution is to chaise this places and make then set MonoType::type correctly.
7413                  * */
7414                 if (type->type != tmp->type)
7415                         type = tmp;
7416                 else
7417                         mono_metadata_free_type (tmp);
7418         }
7419         return type;
7420 }
7421
7422 /**
7423  * mono_class_get:
7424  * \param image image where the class token will be looked up.
7425  * \param type_token a type token from the image
7426  * \returns the \c MonoClass with the given \p type_token on the \p image
7427  */
7428 MonoClass *
7429 mono_class_get (MonoImage *image, guint32 type_token)
7430 {
7431         return mono_class_get_full (image, type_token, NULL);
7432 }
7433
7434 /**
7435  * mono_image_init_name_cache:
7436  *
7437  *  Initializes the class name cache stored in image->name_cache.
7438  *
7439  * LOCKING: Acquires the corresponding image lock.
7440  */
7441 void
7442 mono_image_init_name_cache (MonoImage *image)
7443 {
7444         MonoTableInfo  *t = &image->tables [MONO_TABLE_TYPEDEF];
7445         guint32 cols [MONO_TYPEDEF_SIZE];
7446         const char *name;
7447         const char *nspace;
7448         guint32 i, visib, nspace_index;
7449         GHashTable *name_cache2, *nspace_table, *the_name_cache;
7450
7451         if (image->name_cache)
7452                 return;
7453
7454         the_name_cache = g_hash_table_new (g_str_hash, g_str_equal);
7455
7456         if (image_is_dynamic (image)) {
7457                 mono_image_lock (image);
7458                 if (image->name_cache) {
7459                         /* Somebody initialized it before us */
7460                         g_hash_table_destroy (the_name_cache);
7461                 } else {
7462                         mono_atomic_store_release (&image->name_cache, the_name_cache);
7463                 }
7464                 mono_image_unlock (image);
7465                 return;
7466         }
7467
7468         /* Temporary hash table to avoid lookups in the nspace_table */
7469         name_cache2 = g_hash_table_new (NULL, NULL);
7470
7471         for (i = 1; i <= t->rows; ++i) {
7472                 mono_metadata_decode_row (t, i - 1, cols, MONO_TYPEDEF_SIZE);
7473                 visib = cols [MONO_TYPEDEF_FLAGS] & TYPE_ATTRIBUTE_VISIBILITY_MASK;
7474                 /*
7475                  * Nested types are accessed from the nesting name.  We use the fact that nested types use different visibility flags
7476                  * than toplevel types, thus avoiding the need to grovel through the NESTED_TYPE table
7477                  */
7478                 if (visib >= TYPE_ATTRIBUTE_NESTED_PUBLIC && visib <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM)
7479                         continue;
7480                 name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
7481                 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
7482
7483                 nspace_index = cols [MONO_TYPEDEF_NAMESPACE];
7484                 nspace_table = (GHashTable *)g_hash_table_lookup (name_cache2, GUINT_TO_POINTER (nspace_index));
7485                 if (!nspace_table) {
7486                         nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
7487                         g_hash_table_insert (the_name_cache, (char*)nspace, nspace_table);
7488                         g_hash_table_insert (name_cache2, GUINT_TO_POINTER (nspace_index),
7489                                                                  nspace_table);
7490                 }
7491                 g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (i));
7492         }
7493
7494         /* Load type names from EXPORTEDTYPES table */
7495         {
7496                 MonoTableInfo  *t = &image->tables [MONO_TABLE_EXPORTEDTYPE];
7497                 guint32 cols [MONO_EXP_TYPE_SIZE];
7498                 int i;
7499
7500                 for (i = 0; i < t->rows; ++i) {
7501                         mono_metadata_decode_row (t, i, cols, MONO_EXP_TYPE_SIZE);
7502
7503                         guint32 impl = cols [MONO_EXP_TYPE_IMPLEMENTATION];
7504                         if ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_EXP_TYPE)
7505                                 /* Nested type */
7506                                 continue;
7507
7508                         name = mono_metadata_string_heap (image, cols [MONO_EXP_TYPE_NAME]);
7509                         nspace = mono_metadata_string_heap (image, cols [MONO_EXP_TYPE_NAMESPACE]);
7510
7511                         nspace_index = cols [MONO_EXP_TYPE_NAMESPACE];
7512                         nspace_table = (GHashTable *)g_hash_table_lookup (name_cache2, GUINT_TO_POINTER (nspace_index));
7513                         if (!nspace_table) {
7514                                 nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
7515                                 g_hash_table_insert (the_name_cache, (char*)nspace, nspace_table);
7516                                 g_hash_table_insert (name_cache2, GUINT_TO_POINTER (nspace_index),
7517                                                                          nspace_table);
7518                         }
7519                         g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (mono_metadata_make_token (MONO_TABLE_EXPORTEDTYPE, i + 1)));
7520                 }
7521         }
7522
7523         g_hash_table_destroy (name_cache2);
7524
7525         mono_image_lock (image);
7526         if (image->name_cache) {
7527                 /* Somebody initialized it before us */
7528                 g_hash_table_destroy (the_name_cache);
7529         } else {
7530                 mono_atomic_store_release (&image->name_cache, the_name_cache);
7531         }
7532         mono_image_unlock (image);
7533 }
7534
7535 /*FIXME Only dynamic assemblies should allow this operation.*/
7536 /**
7537  * mono_image_add_to_name_cache:
7538  */
7539 void
7540 mono_image_add_to_name_cache (MonoImage *image, const char *nspace, 
7541                                                           const char *name, guint32 index)
7542 {
7543         GHashTable *nspace_table;
7544         GHashTable *name_cache;
7545         guint32 old_index;
7546
7547         mono_image_init_name_cache (image);
7548         mono_image_lock (image);
7549
7550         name_cache = image->name_cache;
7551         if (!(nspace_table = (GHashTable *)g_hash_table_lookup (name_cache, nspace))) {
7552                 nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
7553                 g_hash_table_insert (name_cache, (char *)nspace, (char *)nspace_table);
7554         }
7555
7556         if ((old_index = GPOINTER_TO_UINT (g_hash_table_lookup (nspace_table, (char*) name))))
7557                 g_error ("overrwritting old token %x on image %s for type %s::%s", old_index, image->name, nspace, name);
7558
7559         g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (index));
7560
7561         mono_image_unlock (image);
7562 }
7563
7564 typedef struct {
7565         gconstpointer key;
7566         gpointer value;
7567 } FindUserData;
7568
7569 static void
7570 find_nocase (gpointer key, gpointer value, gpointer user_data)
7571 {
7572         char *name = (char*)key;
7573         FindUserData *data = (FindUserData*)user_data;
7574
7575         if (!data->value && (mono_utf8_strcasecmp (name, (char*)data->key) == 0))
7576                 data->value = value;
7577 }
7578
7579 /**
7580  * mono_class_from_name_case:
7581  * \param image The MonoImage where the type is looked up in
7582  * \param name_space the type namespace
7583  * \param name the type short name.
7584  * \deprecated use the mono_class_from_name_case_checked variant instead.
7585  *
7586  * Obtains a \c MonoClass with a given namespace and a given name which
7587  * is located in the given \c MonoImage.   The namespace and name
7588  * lookups are case insensitive.
7589  */
7590 MonoClass *
7591 mono_class_from_name_case (MonoImage *image, const char* name_space, const char *name)
7592 {
7593         MonoError error;
7594         MonoClass *res = mono_class_from_name_case_checked (image, name_space, name, &error);
7595         mono_error_cleanup (&error);
7596
7597         return res;
7598 }
7599
7600 /**
7601  * mono_class_from_name_case_checked:
7602  * \param image The MonoImage where the type is looked up in
7603  * \param name_space the type namespace
7604  * \param name the type short name.
7605  * \param error if 
7606  *
7607  * Obtains a MonoClass with a given namespace and a given name which
7608  * is located in the given MonoImage.   The namespace and name
7609  * lookups are case insensitive.
7610  *
7611  * \returns The MonoClass if the given namespace and name were found, or NULL if it
7612  * was not found.   The \p error object will contain information about the problem
7613  * in that case.
7614  */
7615 MonoClass *
7616 mono_class_from_name_case_checked (MonoImage *image, const char *name_space, const char *name, MonoError *error)
7617 {
7618         MonoTableInfo  *t = &image->tables [MONO_TABLE_TYPEDEF];
7619         guint32 cols [MONO_TYPEDEF_SIZE];
7620         const char *n;
7621         const char *nspace;
7622         guint32 i, visib;
7623
7624         error_init (error);
7625
7626         if (image_is_dynamic (image)) {
7627                 guint32 token = 0;
7628                 FindUserData user_data;
7629
7630                 mono_image_init_name_cache (image);
7631                 mono_image_lock (image);
7632
7633                 user_data.key = name_space;
7634                 user_data.value = NULL;
7635                 g_hash_table_foreach (image->name_cache, find_nocase, &user_data);
7636
7637                 if (user_data.value) {
7638                         GHashTable *nspace_table = (GHashTable*)user_data.value;
7639
7640                         user_data.key = name;
7641                         user_data.value = NULL;
7642
7643                         g_hash_table_foreach (nspace_table, find_nocase, &user_data);
7644                         
7645                         if (user_data.value)
7646                                 token = GPOINTER_TO_UINT (user_data.value);
7647                 }
7648
7649                 mono_image_unlock (image);
7650                 
7651                 if (token)
7652                         return mono_class_get_checked (image, MONO_TOKEN_TYPE_DEF | token, error);
7653                 else
7654                         return NULL;
7655
7656         }
7657
7658         /* add a cache if needed */
7659         for (i = 1; i <= t->rows; ++i) {
7660                 mono_metadata_decode_row (t, i - 1, cols, MONO_TYPEDEF_SIZE);
7661                 visib = cols [MONO_TYPEDEF_FLAGS] & TYPE_ATTRIBUTE_VISIBILITY_MASK;
7662                 /*
7663                  * Nested types are accessed from the nesting name.  We use the fact that nested types use different visibility flags
7664                  * than toplevel types, thus avoiding the need to grovel through the NESTED_TYPE table
7665                  */
7666                 if (visib >= TYPE_ATTRIBUTE_NESTED_PUBLIC && visib <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM)
7667                         continue;
7668                 n = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
7669                 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
7670                 if (mono_utf8_strcasecmp (n, name) == 0 && mono_utf8_strcasecmp (nspace, name_space) == 0)
7671                         return mono_class_get_checked (image, MONO_TOKEN_TYPE_DEF | i, error);
7672         }
7673         return NULL;
7674 }
7675
7676 static MonoClass*
7677 return_nested_in (MonoClass *klass, char *nested)
7678 {
7679         MonoClass *found;
7680         char *s = strchr (nested, '/');
7681         gpointer iter = NULL;
7682
7683         if (s) {
7684                 *s = 0;
7685                 s++;
7686         }
7687
7688         while ((found = mono_class_get_nested_types (klass, &iter))) {
7689                 if (strcmp (found->name, nested) == 0) {
7690                         if (s)
7691                                 return return_nested_in (found, s);
7692                         return found;
7693                 }
7694         }
7695         return NULL;
7696 }
7697
7698 static MonoClass*
7699 search_modules (MonoImage *image, const char *name_space, const char *name, MonoError *error)
7700 {
7701         MonoTableInfo *file_table = &image->tables [MONO_TABLE_FILE];
7702         MonoImage *file_image;
7703         MonoClass *klass;
7704         int i;
7705
7706         error_init (error);
7707
7708         /* 
7709          * The EXPORTEDTYPES table only contains public types, so have to search the
7710          * modules as well.
7711          * Note: image->modules contains the contents of the MODULEREF table, while
7712          * the real module list is in the FILE table.
7713          */
7714         for (i = 0; i < file_table->rows; i++) {
7715                 guint32 cols [MONO_FILE_SIZE];
7716                 mono_metadata_decode_row (file_table, i, cols, MONO_FILE_SIZE);
7717                 if (cols [MONO_FILE_FLAGS] == FILE_CONTAINS_NO_METADATA)
7718                         continue;
7719
7720                 file_image = mono_image_load_file_for_image_checked (image, i + 1, error);
7721                 if (file_image) {
7722                         klass = mono_class_from_name_checked (file_image, name_space, name, error);
7723                         if (klass || !is_ok (error))
7724                                 return klass;
7725                 }
7726         }
7727
7728         return NULL;
7729 }
7730
7731 static MonoClass *
7732 mono_class_from_name_checked_aux (MonoImage *image, const char* name_space, const char *name, GHashTable* visited_images, MonoError *error)
7733 {
7734         GHashTable *nspace_table;
7735         MonoImage *loaded_image;
7736         guint32 token = 0;
7737         int i;
7738         MonoClass *klass;
7739         char *nested;
7740         char buf [1024];
7741
7742         error_init (error);
7743
7744         // Checking visited images avoids stack overflows when cyclic references exist.
7745         if (g_hash_table_lookup (visited_images, image))
7746                 return NULL;
7747
7748         g_hash_table_insert (visited_images, image, GUINT_TO_POINTER(1));
7749
7750         if ((nested = strchr (name, '/'))) {
7751                 int pos = nested - name;
7752                 int len = strlen (name);
7753                 if (len > 1023)
7754                         return NULL;
7755                 memcpy (buf, name, len + 1);
7756                 buf [pos] = 0;
7757                 nested = buf + pos + 1;
7758                 name = buf;
7759         }
7760
7761         /* FIXME: get_class_from_name () can't handle types in the EXPORTEDTYPE table */
7762         if (get_class_from_name && image->tables [MONO_TABLE_EXPORTEDTYPE].rows == 0) {
7763                 gboolean res = get_class_from_name (image, name_space, name, &klass);
7764                 if (res) {
7765                         if (!klass) {
7766                                 klass = search_modules (image, name_space, name, error);
7767                                 if (!is_ok (error))
7768                                         return NULL;
7769                         }
7770                         if (nested)
7771                                 return klass ? return_nested_in (klass, nested) : NULL;
7772                         else
7773                                 return klass;
7774                 }
7775         }
7776
7777         mono_image_init_name_cache (image);
7778         mono_image_lock (image);
7779
7780         nspace_table = (GHashTable *)g_hash_table_lookup (image->name_cache, name_space);
7781
7782         if (nspace_table)
7783                 token = GPOINTER_TO_UINT (g_hash_table_lookup (nspace_table, name));
7784
7785         mono_image_unlock (image);
7786
7787         if (!token && image_is_dynamic (image) && image->modules) {
7788                 /* Search modules as well */
7789                 for (i = 0; i < image->module_count; ++i) {
7790                         MonoImage *module = image->modules [i];
7791
7792                         klass = mono_class_from_name_checked (module, name_space, name, error);
7793                         if (klass || !is_ok (error))
7794                                 return klass;
7795                 }
7796         }
7797
7798         if (!token) {
7799                 klass = search_modules (image, name_space, name, error);
7800                 if (klass || !is_ok (error))
7801                         return klass;
7802                 return NULL;
7803         }
7804
7805         if (mono_metadata_token_table (token) == MONO_TABLE_EXPORTEDTYPE) {
7806                 MonoTableInfo  *t = &image->tables [MONO_TABLE_EXPORTEDTYPE];
7807                 guint32 cols [MONO_EXP_TYPE_SIZE];
7808                 guint32 idx, impl;
7809
7810                 idx = mono_metadata_token_index (token);
7811
7812                 mono_metadata_decode_row (t, idx - 1, cols, MONO_EXP_TYPE_SIZE);
7813
7814                 impl = cols [MONO_EXP_TYPE_IMPLEMENTATION];
7815                 if ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_FILE) {
7816                         loaded_image = mono_assembly_load_module_checked (image->assembly, impl >> MONO_IMPLEMENTATION_BITS, error);
7817                         if (!loaded_image)
7818                                 return NULL;
7819                         klass = mono_class_from_name_checked_aux (loaded_image, name_space, name, visited_images, error);
7820                         if (nested)
7821                                 return klass ? return_nested_in (klass, nested) : NULL;
7822                         return klass;
7823                 } else if ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_ASSEMBLYREF) {
7824                         guint32 assembly_idx;
7825
7826                         assembly_idx = impl >> MONO_IMPLEMENTATION_BITS;
7827
7828                         mono_assembly_load_reference (image, assembly_idx - 1);
7829                         g_assert (image->references [assembly_idx - 1]);
7830                         if (image->references [assembly_idx - 1] == (gpointer)-1)
7831                                 return NULL;                    
7832                         klass = mono_class_from_name_checked_aux (image->references [assembly_idx - 1]->image, name_space, name, visited_images, error);
7833                         if (nested)
7834                                 return klass ? return_nested_in (klass, nested) : NULL;
7835                         return klass;
7836                 } else {
7837                         g_assert_not_reached ();
7838                 }
7839         }
7840
7841         token = MONO_TOKEN_TYPE_DEF | token;
7842
7843         klass = mono_class_get_checked (image, token, error);
7844         if (nested)
7845                 return return_nested_in (klass, nested);
7846         return klass;
7847 }
7848
7849 /**
7850  * mono_class_from_name_checked:
7851  * \param image The MonoImage where the type is looked up in
7852  * \param name_space the type namespace
7853  * \param name the type short name.
7854  *
7855  * Obtains a MonoClass with a given namespace and a given name which
7856  * is located in the given MonoImage.
7857  *
7858  * Works like mono_class_from_name, but error handling is tricky. It can return NULL and have no error
7859  * set if the class was not found or it will return NULL and set the error if there was a loading error.
7860  */
7861 MonoClass *
7862 mono_class_from_name_checked (MonoImage *image, const char* name_space, const char *name, MonoError *error)
7863 {
7864         MonoClass *klass;
7865         GHashTable *visited_images;
7866
7867         visited_images = g_hash_table_new (g_direct_hash, g_direct_equal);
7868
7869         klass = mono_class_from_name_checked_aux (image, name_space, name, visited_images, error);
7870
7871         g_hash_table_destroy (visited_images);
7872
7873         return klass;
7874 }
7875
7876 /**
7877  * mono_class_from_name:
7878  * \param image The \c MonoImage where the type is looked up in
7879  * \param name_space the type namespace
7880  * \param name the type short name.
7881  *
7882  * Obtains a \c MonoClass with a given namespace and a given name which
7883  * is located in the given \c MonoImage.
7884  *
7885  * To reference nested classes, use the "/" character as a separator.
7886  * For example use \c "Foo/Bar" to reference the class \c Bar that is nested
7887  * inside \c Foo, like this: "class Foo { class Bar {} }".
7888  */
7889 MonoClass *
7890 mono_class_from_name (MonoImage *image, const char* name_space, const char *name)
7891 {
7892         MonoError error;
7893         MonoClass *klass;
7894
7895         klass = mono_class_from_name_checked (image, name_space, name, &error);
7896         mono_error_cleanup (&error); /* FIXME Don't swallow the error */
7897
7898         return klass;
7899 }
7900
7901 /**
7902  * mono_class_load_from_name:
7903  * \param image The MonoImage where the type is looked up in
7904  * \param name_space the type namespace
7905  * \param name the type short name.
7906  *
7907  * This function works exactly like mono_class_from_name but it will abort if the class is not found.
7908  * This function should be used by the runtime for critical types to which there's no way to recover but crash
7909  * If they are missing. Thing of System.Object or System.String.
7910  */
7911 MonoClass *
7912 mono_class_load_from_name (MonoImage *image, const char* name_space, const char *name)
7913 {
7914         MonoError error;
7915         MonoClass *klass;
7916
7917         klass = mono_class_from_name_checked (image, name_space, name, &error);
7918         if (!klass)
7919                 g_error ("Runtime critical type %s.%s not found", name_space, name);
7920         if (!mono_error_ok (&error))
7921                 g_error ("Could not load runtime critical type %s.%s due to %s", name_space, name, mono_error_get_message (&error));
7922         return klass;
7923 }
7924
7925 /**
7926  * mono_class_try_load_from_name:
7927  * \param image The MonoImage where the type is looked up in
7928  * \param name_space the type namespace
7929  * \param name the type short name.
7930  *
7931  * This function tries to load a type, returning the class was found or NULL otherwise.
7932  * This function should be used by the runtime when probing for optional types, those that could have being linked out.
7933  *
7934  * Big design consideration. This function aborts if there was an error loading the type. This prevents us from missing
7935  * a type that we would otherwise assume to be available but was not due some error.
7936  *
7937  */
7938 MonoClass*
7939 mono_class_try_load_from_name (MonoImage *image, const char* name_space, const char *name)
7940 {
7941         MonoError error;
7942         MonoClass *klass;
7943
7944         klass = mono_class_from_name_checked (image, name_space, name, &error);
7945         if (!mono_error_ok (&error))
7946                 g_error ("Could not load runtime critical type %s.%s due to %s", name_space, name, mono_error_get_message (&error));
7947         return klass;
7948 }
7949
7950
7951 /**
7952  * mono_class_is_subclass_of:
7953  * \param klass class to probe if it is a subclass of another one
7954  * \param klassc the class we suspect is the base class
7955  * \param check_interfaces whether we should perform interface checks
7956  *
7957  * This method determines whether \p klass is a subclass of \p klassc.
7958  *
7959  * If the \p check_interfaces flag is set, then if \p klassc is an interface
7960  * this method return TRUE if the \p klass implements the interface or
7961  * if \p klass is an interface, if one of its base classes is \p klass.
7962  *
7963  * If \p check_interfaces is false, then if \p klass is not an interface,
7964  * it returns TRUE if the \p klass is a subclass of \p klassc.
7965  *
7966  * if \p klass is an interface and \p klassc is \c System.Object, then this function
7967  * returns TRUE.
7968  *
7969  */
7970 gboolean
7971 mono_class_is_subclass_of (MonoClass *klass, MonoClass *klassc, 
7972                            gboolean check_interfaces)
7973 {
7974         /* FIXME test for interfaces with variant generic arguments */
7975         mono_class_init (klass);
7976         mono_class_init (klassc);
7977         
7978         if (check_interfaces && MONO_CLASS_IS_INTERFACE (klassc) && !MONO_CLASS_IS_INTERFACE (klass)) {
7979                 if (MONO_CLASS_IMPLEMENTS_INTERFACE (klass, klassc->interface_id))
7980                         return TRUE;
7981         } else if (check_interfaces && MONO_CLASS_IS_INTERFACE (klassc) && MONO_CLASS_IS_INTERFACE (klass)) {
7982                 int i;
7983
7984                 for (i = 0; i < klass->interface_count; i ++) {
7985                         MonoClass *ic =  klass->interfaces [i];
7986                         if (ic == klassc)
7987                                 return TRUE;
7988                 }
7989         } else {
7990                 if (!MONO_CLASS_IS_INTERFACE (klass) && mono_class_has_parent (klass, klassc))
7991                         return TRUE;
7992         }
7993
7994         /* 
7995          * MS.NET thinks interfaces are a subclass of Object, so we think it as
7996          * well.
7997          */
7998         if (klassc == mono_defaults.object_class)
7999                 return TRUE;
8000
8001         return FALSE;
8002 }
8003
8004 static gboolean
8005 mono_type_is_generic_argument (MonoType *type)
8006 {
8007         return type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR;
8008 }
8009
8010 gboolean
8011 mono_class_has_variant_generic_params (MonoClass *klass)
8012 {
8013         int i;
8014         MonoGenericContainer *container;
8015
8016         if (!mono_class_is_ginst (klass))
8017                 return FALSE;
8018
8019         container = mono_class_get_generic_container (mono_class_get_generic_class (klass)->container_class);
8020
8021         for (i = 0; i < container->type_argc; ++i)
8022                 if (mono_generic_container_get_param_info (container, i)->flags & (MONO_GEN_PARAM_VARIANT|MONO_GEN_PARAM_COVARIANT))
8023                         return TRUE;
8024
8025         return FALSE;
8026 }
8027
8028 static gboolean
8029 mono_gparam_is_reference_conversible (MonoClass *target, MonoClass *candidate, gboolean check_for_reference_conv)
8030 {
8031         if (target == candidate)
8032                 return TRUE;
8033
8034         if (check_for_reference_conv &&
8035                 mono_type_is_generic_argument (&target->byval_arg) &&
8036                 mono_type_is_generic_argument (&candidate->byval_arg)) {
8037                 MonoGenericParam *gparam = candidate->byval_arg.data.generic_param;
8038                 MonoGenericParamInfo *pinfo = mono_generic_param_info (gparam);
8039
8040                 if (!pinfo || (pinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) == 0)
8041                         return FALSE;
8042         }
8043         if (!mono_class_is_assignable_from (target, candidate))
8044                 return FALSE;
8045         return TRUE;
8046 }
8047
8048 /**
8049  * @container the generic container from the GTD
8050  * @klass: the class to be assigned to
8051  * @oklass: the source class
8052  * 
8053  * Both @klass and @oklass must be instances of the same generic interface.
8054  *
8055  * Returns: TRUE if @klass can be assigned to a @klass variable
8056  */
8057 gboolean
8058 mono_class_is_variant_compatible (MonoClass *klass, MonoClass *oklass, gboolean check_for_reference_conv)
8059 {
8060         int j;
8061         MonoType **klass_argv, **oklass_argv;
8062         MonoClass *klass_gtd = mono_class_get_generic_type_definition (klass);
8063         MonoGenericContainer *container = mono_class_get_generic_container (klass_gtd);
8064
8065         if (klass == oklass)
8066                 return TRUE;
8067
8068         /*Viable candidates are instances of the same generic interface*/
8069         if (mono_class_get_generic_type_definition (oklass) != klass_gtd || oklass == klass_gtd)
8070                 return FALSE;
8071
8072         klass_argv = &mono_class_get_generic_class (klass)->context.class_inst->type_argv [0];
8073         oklass_argv = &mono_class_get_generic_class (oklass)->context.class_inst->type_argv [0];
8074
8075         for (j = 0; j < container->type_argc; ++j) {
8076                 MonoClass *param1_class = mono_class_from_mono_type (klass_argv [j]);
8077                 MonoClass *param2_class = mono_class_from_mono_type (oklass_argv [j]);
8078
8079                 if (param1_class->valuetype != param2_class->valuetype || (param1_class->valuetype && param1_class != param2_class))
8080                         return FALSE;
8081
8082                 /*
8083                  * The _VARIANT and _COVARIANT constants should read _COVARIANT and
8084                  * _CONTRAVARIANT, but they are in a public header so we can't fix it.
8085                  */
8086                 if (param1_class != param2_class) {
8087                         if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_VARIANT) {
8088                                 if (!mono_gparam_is_reference_conversible (param1_class, param2_class, check_for_reference_conv))
8089                                         return FALSE;
8090                         } else if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_COVARIANT) {
8091                                 if (!mono_gparam_is_reference_conversible (param2_class, param1_class, check_for_reference_conv))
8092                                         return FALSE;
8093                         } else
8094                                 return FALSE;
8095                 }
8096         }
8097         return TRUE;
8098 }
8099
8100 static gboolean
8101 mono_gparam_is_assignable_from (MonoClass *target, MonoClass *candidate)
8102 {
8103         MonoGenericParam *gparam, *ogparam;
8104         MonoGenericParamInfo *tinfo, *cinfo;
8105         MonoClass **candidate_class;
8106         gboolean class_constraint_satisfied, valuetype_constraint_satisfied;
8107         int tmask, cmask;
8108
8109         if (target == candidate)
8110                 return TRUE;
8111         if (target->byval_arg.type != candidate->byval_arg.type)
8112                 return FALSE;
8113
8114         gparam = target->byval_arg.data.generic_param;
8115         ogparam = candidate->byval_arg.data.generic_param;
8116         tinfo = mono_generic_param_info (gparam);
8117         cinfo = mono_generic_param_info (ogparam);
8118
8119         class_constraint_satisfied = FALSE;
8120         valuetype_constraint_satisfied = FALSE;
8121
8122         /*candidate must have a super set of target's special constraints*/
8123         tmask = tinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_SPECIAL_CONSTRAINTS_MASK;
8124         cmask = cinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_SPECIAL_CONSTRAINTS_MASK;
8125
8126         if (cinfo->constraints) {
8127                 for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
8128                         MonoClass *cc = *candidate_class;
8129
8130                         if (mono_type_is_reference (&cc->byval_arg) && !MONO_CLASS_IS_INTERFACE (cc))
8131                                 class_constraint_satisfied = TRUE;
8132                         else if (!mono_type_is_reference (&cc->byval_arg) && !MONO_CLASS_IS_INTERFACE (cc))
8133                                 valuetype_constraint_satisfied = TRUE;
8134                 }
8135         }
8136         class_constraint_satisfied |= (cmask & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) != 0;
8137         valuetype_constraint_satisfied |= (cmask & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT) != 0;
8138
8139         if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) && !class_constraint_satisfied)
8140                 return FALSE;
8141         if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT) && !valuetype_constraint_satisfied)
8142                 return FALSE;
8143         if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_CONSTRUCTOR_CONSTRAINT) && !((cmask & GENERIC_PARAMETER_ATTRIBUTE_CONSTRUCTOR_CONSTRAINT) ||
8144                 valuetype_constraint_satisfied)) {
8145                 return FALSE;
8146         }
8147
8148
8149         /*candidate type constraints must be a superset of target's*/
8150         if (tinfo->constraints) {
8151                 MonoClass **target_class;
8152                 for (target_class = tinfo->constraints; *target_class; ++target_class) {
8153                         MonoClass *tc = *target_class;
8154
8155                         /*
8156                          * A constraint from @target might inflate into @candidate itself and in that case we don't need
8157                          * check it's constraints since it satisfy the constraint by itself.
8158                          */
8159                         if (mono_metadata_type_equal (&tc->byval_arg, &candidate->byval_arg))
8160                                 continue;
8161
8162                         if (!cinfo->constraints)
8163                                 return FALSE;
8164
8165                         for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
8166                                 MonoClass *cc = *candidate_class;
8167
8168                                 if (mono_class_is_assignable_from (tc, cc))
8169                                         break;
8170
8171                                 /*
8172                                  * This happens when we have the following:
8173                                  *
8174                                  * Bar<K> where K : IFace
8175                                  * Foo<T, U> where T : U where U : IFace
8176                                  *      ...
8177                                  *      Bar<T> <- T here satisfy K constraint transitively through to U's constraint
8178                                  *
8179                                  */
8180                                 if (mono_type_is_generic_argument (&cc->byval_arg)) {
8181                                         if (mono_gparam_is_assignable_from (target, cc))
8182                                                 break;
8183                                 }
8184                         }
8185                         if (!*candidate_class)
8186                                 return FALSE;
8187                 }
8188         }
8189
8190         /*candidate itself must have a constraint that satisfy target*/
8191         if (cinfo->constraints) {
8192                 for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
8193                         MonoClass *cc = *candidate_class;
8194                         if (mono_class_is_assignable_from (target, cc))
8195                                 return TRUE;
8196                 }
8197         }
8198         return FALSE;
8199 }
8200
8201 /**
8202  * mono_class_is_assignable_from:
8203  * \param klass the class to be assigned to
8204  * \param oklass the source class
8205  *
8206  * \returns TRUE if an instance of class \p oklass can be assigned to an
8207  * instance of class \p klass
8208  */
8209 gboolean
8210 mono_class_is_assignable_from (MonoClass *klass, MonoClass *oklass)
8211 {
8212         MonoError error;
8213         /*FIXME this will cause a lot of irrelevant stuff to be loaded.*/
8214         if (!klass->inited)
8215                 mono_class_init (klass);
8216
8217         if (!oklass->inited)
8218                 mono_class_init (oklass);
8219
8220         if (mono_class_has_failure (klass) || mono_class_has_failure  (oklass))
8221                 return FALSE;
8222
8223         if (mono_type_is_generic_argument (&klass->byval_arg)) {
8224                 if (!mono_type_is_generic_argument (&oklass->byval_arg))
8225                         return FALSE;
8226                 return mono_gparam_is_assignable_from (klass, oklass);
8227         }
8228
8229         /* This can happen if oklass is a tyvar that has a constraint which is another tyvar which in turn
8230          * has a constraint which is a class type:
8231          *
8232          *  class Foo { }
8233          *  class G<T1, T2> where T1 : T2 where T2 : Foo { }
8234          *
8235          * In this case, Foo is assignable from T1.
8236          */
8237         if ((oklass->byval_arg.type == MONO_TYPE_VAR) || (oklass->byval_arg.type == MONO_TYPE_MVAR)) {
8238                 MonoGenericParam *gparam = oklass->byval_arg.data.generic_param;
8239                 MonoClass **constraints = mono_generic_container_get_param_info (gparam->owner, gparam->num)->constraints;
8240                 int i;
8241
8242                 if (constraints) {
8243                         for (i = 0; constraints [i]; ++i) {
8244                                 if (mono_class_is_assignable_from (klass, constraints [i]))
8245                                         return TRUE;
8246                         }
8247                 }
8248
8249                 return mono_class_has_parent (oklass, klass);
8250         }
8251
8252         if (MONO_CLASS_IS_INTERFACE (klass)) {
8253
8254                 /* interface_offsets might not be set for dynamic classes */
8255                 if (mono_class_get_ref_info_handle (oklass) && !oklass->interface_bitmap) {
8256                         /* 
8257                          * oklass might be a generic type parameter but they have 
8258                          * interface_offsets set.
8259                          */
8260                         gboolean result = mono_reflection_call_is_assignable_to (oklass, klass, &error);
8261                         if (!is_ok (&error)) {
8262                                 mono_error_cleanup (&error);
8263                                 return FALSE;
8264                         }
8265                         return result;
8266                 }
8267                 if (!oklass->interface_bitmap)
8268                         /* Happens with generic instances of not-yet created dynamic types */
8269                         return FALSE;
8270                 if (MONO_CLASS_IMPLEMENTS_INTERFACE (oklass, klass->interface_id))
8271                         return TRUE;
8272
8273                 if (klass->is_array_special_interface && oklass->rank == 1) {
8274                         //XXX we could offset this by having the cast target computed at JIT time
8275                         //XXX we could go even further and emit a wrapper that would do the extra type check
8276                         MonoClass *iface_klass = mono_class_from_mono_type (mono_class_get_generic_class (klass)->context.class_inst->type_argv [0]);
8277                         MonoClass *obj_klass = oklass->cast_class; //This gets us the cast class of element type of the array
8278
8279                         // If the target we're trying to cast to is a valuetype, we must account of weird valuetype equivalences such as IntEnum <> int or uint <> int
8280                         // We can't apply it for ref types as this would go wrong with arrays - IList<byte[]> would have byte tested
8281                         if (iface_klass->valuetype)
8282                                 iface_klass = iface_klass->cast_class;
8283
8284                         //array covariant casts only operates on scalar to scalar
8285                         //This is so int[] can't be casted to IComparable<int>[]
8286                         if (!(obj_klass->valuetype && !iface_klass->valuetype) && mono_class_is_assignable_from (iface_klass, obj_klass))
8287                                 return TRUE;
8288                 }
8289
8290                 if (mono_class_has_variant_generic_params (klass)) {
8291                         int i;
8292                         mono_class_setup_interfaces (oklass, &error);
8293                         if (!mono_error_ok (&error)) {
8294                                 mono_error_cleanup (&error);
8295                                 return FALSE;
8296                         }
8297
8298                         /*klass is a generic variant interface, We need to extract from oklass a list of ifaces which are viable candidates.*/
8299                         for (i = 0; i < oklass->interface_offsets_count; ++i) {
8300                                 MonoClass *iface = oklass->interfaces_packed [i];
8301
8302                                 if (mono_class_is_variant_compatible (klass, iface, FALSE))
8303                                         return TRUE;
8304                         }
8305                 }
8306                 return FALSE;
8307         } else if (klass->delegate) {
8308                 if (mono_class_has_variant_generic_params (klass) && mono_class_is_variant_compatible (klass, oklass, FALSE))
8309                         return TRUE;
8310         }else if (klass->rank) {
8311                 MonoClass *eclass, *eoclass;
8312
8313                 if (oklass->rank != klass->rank)
8314                         return FALSE;
8315
8316                 /* vectors vs. one dimensional arrays */
8317                 if (oklass->byval_arg.type != klass->byval_arg.type)
8318                         return FALSE;
8319
8320                 eclass = klass->cast_class;
8321                 eoclass = oklass->cast_class;
8322
8323                 /* 
8324                  * a is b does not imply a[] is b[] when a is a valuetype, and
8325                  * b is a reference type.
8326                  */
8327
8328                 if (eoclass->valuetype) {
8329                         if ((eclass == mono_defaults.enum_class) || 
8330                                 (eclass == mono_defaults.enum_class->parent) ||
8331                                 (eclass == mono_defaults.object_class))
8332                                 return FALSE;
8333                 }
8334
8335                 return mono_class_is_assignable_from (klass->cast_class, oklass->cast_class);
8336         } else if (mono_class_is_nullable (klass)) {
8337                 if (mono_class_is_nullable (oklass))
8338                         return mono_class_is_assignable_from (klass->cast_class, oklass->cast_class);
8339                 else
8340                         return mono_class_is_assignable_from (klass->cast_class, oklass);
8341         } else if (klass == mono_defaults.object_class)
8342                 return TRUE;
8343
8344         return mono_class_has_parent (oklass, klass);
8345 }       
8346
8347 /*Check if @oklass is variant compatible with @klass.*/
8348 static gboolean
8349 mono_class_is_variant_compatible_slow (MonoClass *klass, MonoClass *oklass)
8350 {
8351         int j;
8352         MonoType **klass_argv, **oklass_argv;
8353         MonoClass *klass_gtd = mono_class_get_generic_type_definition (klass);
8354         MonoGenericContainer *container = mono_class_get_generic_container (klass_gtd);
8355
8356         /*Viable candidates are instances of the same generic interface*/
8357         if (mono_class_get_generic_type_definition (oklass) != klass_gtd || oklass == klass_gtd)
8358                 return FALSE;
8359
8360         klass_argv = &mono_class_get_generic_class (klass)->context.class_inst->type_argv [0];
8361         oklass_argv = &mono_class_get_generic_class (oklass)->context.class_inst->type_argv [0];
8362
8363         for (j = 0; j < container->type_argc; ++j) {
8364                 MonoClass *param1_class = mono_class_from_mono_type (klass_argv [j]);
8365                 MonoClass *param2_class = mono_class_from_mono_type (oklass_argv [j]);
8366
8367                 if (param1_class->valuetype != param2_class->valuetype)
8368                         return FALSE;
8369
8370                 /*
8371                  * The _VARIANT and _COVARIANT constants should read _COVARIANT and
8372                  * _CONTRAVARIANT, but they are in a public header so we can't fix it.
8373                  */
8374                 if (param1_class != param2_class) {
8375                         if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_VARIANT) {
8376                                 if (!mono_class_is_assignable_from_slow (param1_class, param2_class))
8377                                         return FALSE;
8378                         } else if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_COVARIANT) {
8379                                 if (!mono_class_is_assignable_from_slow (param2_class, param1_class))
8380                                         return FALSE;
8381                         } else
8382                                 return FALSE;
8383                 }
8384         }
8385         return TRUE;
8386 }
8387 /*Check if @candidate implements the interface @target*/
8388 static gboolean
8389 mono_class_implement_interface_slow (MonoClass *target, MonoClass *candidate)
8390 {
8391         MonoError error;
8392         int i;
8393         gboolean is_variant = mono_class_has_variant_generic_params (target);
8394
8395         if (is_variant && MONO_CLASS_IS_INTERFACE (candidate)) {
8396                 if (mono_class_is_variant_compatible_slow (target, candidate))
8397                         return TRUE;
8398         }
8399
8400         do {
8401                 if (candidate == target)
8402                         return TRUE;
8403
8404                 /*A TypeBuilder can have more interfaces on tb->interfaces than on candidate->interfaces*/
8405                 if (image_is_dynamic (candidate->image) && !candidate->wastypebuilder) {
8406                         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info_raw (candidate); /* FIXME use handles */
8407                         int j;
8408                         if (tb && tb->interfaces) {
8409                                 for (j = mono_array_length (tb->interfaces) - 1; j >= 0; --j) {
8410                                         MonoReflectionType *iface = mono_array_get (tb->interfaces, MonoReflectionType*, j);
8411                                         MonoClass *iface_class;
8412
8413                                         /* we can't realize the type here since it can do pretty much anything. */
8414                                         if (!iface->type)
8415                                                 continue;
8416                                         iface_class = mono_class_from_mono_type (iface->type);
8417                                         if (iface_class == target)
8418                                                 return TRUE;
8419                                         if (is_variant && mono_class_is_variant_compatible_slow (target, iface_class))
8420                                                 return TRUE;
8421                                         if (mono_class_implement_interface_slow (target, iface_class))
8422                                                 return TRUE;
8423                                 }
8424                         }
8425                 } else {
8426                         /*setup_interfaces don't mono_class_init anything*/
8427                         /*FIXME this doesn't handle primitive type arrays.
8428                         ICollection<sbyte> x byte [] won't work because candidate->interfaces, for byte[], won't have IList<sbyte>.
8429                         A possible way to fix this would be to move that to setup_interfaces from setup_interface_offsets.
8430                         */
8431                         mono_class_setup_interfaces (candidate, &error);
8432                         if (!mono_error_ok (&error)) {
8433                                 mono_error_cleanup (&error);
8434                                 return FALSE;
8435                         }
8436
8437                         for (i = 0; i < candidate->interface_count; ++i) {
8438                                 if (candidate->interfaces [i] == target)
8439                                         return TRUE;
8440                                 
8441                                 if (is_variant && mono_class_is_variant_compatible_slow (target, candidate->interfaces [i]))
8442                                         return TRUE;
8443
8444                                  if (mono_class_implement_interface_slow (target, candidate->interfaces [i]))
8445                                         return TRUE;
8446                         }
8447                 }
8448                 candidate = candidate->parent;
8449         } while (candidate);
8450
8451         return FALSE;
8452 }
8453
8454 /*
8455  * Check if @oklass can be assigned to @klass.
8456  * This function does the same as mono_class_is_assignable_from but is safe to be used from mono_class_init context.
8457  */
8458 gboolean
8459 mono_class_is_assignable_from_slow (MonoClass *target, MonoClass *candidate)
8460 {
8461         if (candidate == target)
8462                 return TRUE;
8463         if (target == mono_defaults.object_class)
8464                 return TRUE;
8465
8466         if (mono_class_has_parent (candidate, target))
8467                 return TRUE;
8468
8469         /*If target is not an interface there is no need to check them.*/
8470         if (MONO_CLASS_IS_INTERFACE (target))
8471                 return mono_class_implement_interface_slow (target, candidate);
8472
8473         if (target->delegate && mono_class_has_variant_generic_params (target))
8474                 return mono_class_is_variant_compatible (target, candidate, FALSE);
8475
8476         if (target->rank) {
8477                 MonoClass *eclass, *eoclass;
8478
8479                 if (target->rank != candidate->rank)
8480                         return FALSE;
8481
8482                 /* vectors vs. one dimensional arrays */
8483                 if (target->byval_arg.type != candidate->byval_arg.type)
8484                         return FALSE;
8485
8486                 eclass = target->cast_class;
8487                 eoclass = candidate->cast_class;
8488
8489                 /*
8490                  * a is b does not imply a[] is b[] when a is a valuetype, and
8491                  * b is a reference type.
8492                  */
8493
8494                 if (eoclass->valuetype) {
8495                         if ((eclass == mono_defaults.enum_class) ||
8496                                 (eclass == mono_defaults.enum_class->parent) ||
8497                                 (eclass == mono_defaults.object_class))
8498                                 return FALSE;
8499                 }
8500
8501                 return mono_class_is_assignable_from_slow (target->cast_class, candidate->cast_class);
8502         }
8503         /*FIXME properly handle nullables */
8504         /*FIXME properly handle (M)VAR */
8505         return FALSE;
8506 }
8507
8508 /**
8509  * mono_class_get_cctor:
8510  * \param klass A MonoClass pointer
8511  *
8512  * \returns The static constructor of \p klass if it exists, NULL otherwise.
8513  */
8514 MonoMethod*
8515 mono_class_get_cctor (MonoClass *klass)
8516 {
8517         MonoCachedClassInfo cached_info;
8518
8519         if (image_is_dynamic (klass->image)) {
8520                 /* 
8521                  * has_cctor is not set for these classes because mono_class_init () is
8522                  * not run for them.
8523                  */
8524                 return mono_class_get_method_from_name_flags (klass, ".cctor", -1, METHOD_ATTRIBUTE_SPECIAL_NAME);
8525         }
8526
8527         mono_class_init (klass);
8528
8529         if (!klass->has_cctor)
8530                 return NULL;
8531
8532         if (mono_class_is_ginst (klass) && !klass->methods)
8533                 return mono_class_get_inflated_method (klass, mono_class_get_cctor (mono_class_get_generic_class (klass)->container_class));
8534
8535         if (mono_class_get_cached_class_info (klass, &cached_info)) {
8536                 MonoError error;
8537                 MonoMethod *result = mono_get_method_checked (klass->image, cached_info.cctor_token, klass, NULL, &error);
8538                 if (!mono_error_ok (&error))
8539                         g_error ("Could not lookup class cctor from cached metadata due to %s", mono_error_get_message (&error));
8540                 return result;
8541         }
8542
8543         return mono_class_get_method_from_name_flags (klass, ".cctor", -1, METHOD_ATTRIBUTE_SPECIAL_NAME);
8544 }
8545
8546 /**
8547  * mono_class_get_finalizer:
8548  * \param klass: The MonoClass pointer
8549  *
8550  * \returns The finalizer method of \p klass if it exists, NULL otherwise.
8551  */
8552 MonoMethod*
8553 mono_class_get_finalizer (MonoClass *klass)
8554 {
8555         MonoCachedClassInfo cached_info;
8556
8557         if (!klass->inited)
8558                 mono_class_init (klass);
8559         if (!mono_class_has_finalizer (klass))
8560                 return NULL;
8561
8562         if (mono_class_get_cached_class_info (klass, &cached_info)) {
8563                 MonoError error;
8564                 MonoMethod *result = mono_get_method_checked (cached_info.finalize_image, cached_info.finalize_token, NULL, NULL, &error);
8565                 if (!mono_error_ok (&error))
8566                         g_error ("Could not lookup finalizer from cached metadata due to %s", mono_error_get_message (&error));
8567                 return result;
8568         }else {
8569                 mono_class_setup_vtable (klass);
8570                 return klass->vtable [finalize_slot];
8571         }
8572 }
8573
8574 /**
8575  * mono_class_needs_cctor_run:
8576  * \param klass the MonoClass pointer
8577  * \param caller a MonoMethod describing the caller
8578  *
8579  * Determines whenever the class has a static constructor and whenever it
8580  * needs to be called when executing CALLER.
8581  */
8582 gboolean
8583 mono_class_needs_cctor_run (MonoClass *klass, MonoMethod *caller)
8584 {
8585         MonoMethod *method;
8586
8587         method = mono_class_get_cctor (klass);
8588         if (method)
8589                 return (method == caller) ? FALSE : TRUE;
8590         else
8591                 return FALSE;
8592 }
8593
8594 /**
8595  * mono_class_array_element_size:
8596  * \param klass
8597  *
8598  * \returns The number of bytes an element of type \p klass uses when stored into an array.
8599  */
8600 gint32
8601 mono_class_array_element_size (MonoClass *klass)
8602 {
8603         MonoType *type = &klass->byval_arg;
8604         
8605 handle_enum:
8606         switch (type->type) {
8607         case MONO_TYPE_I1:
8608         case MONO_TYPE_U1:
8609         case MONO_TYPE_BOOLEAN:
8610                 return 1;
8611         case MONO_TYPE_I2:
8612         case MONO_TYPE_U2:
8613         case MONO_TYPE_CHAR:
8614                 return 2;
8615         case MONO_TYPE_I4:
8616         case MONO_TYPE_U4:
8617         case MONO_TYPE_R4:
8618                 return 4;
8619         case MONO_TYPE_I:
8620         case MONO_TYPE_U:
8621         case MONO_TYPE_PTR:
8622         case MONO_TYPE_CLASS:
8623         case MONO_TYPE_STRING:
8624         case MONO_TYPE_OBJECT:
8625         case MONO_TYPE_SZARRAY:
8626         case MONO_TYPE_ARRAY: 
8627                 return sizeof (gpointer);
8628         case MONO_TYPE_I8:
8629         case MONO_TYPE_U8:
8630         case MONO_TYPE_R8:
8631                 return 8;
8632         case MONO_TYPE_VALUETYPE:
8633                 if (type->data.klass->enumtype) {
8634                         type = mono_class_enum_basetype (type->data.klass);
8635                         klass = klass->element_class;
8636                         goto handle_enum;
8637                 }
8638                 return mono_class_instance_size (klass) - sizeof (MonoObject);
8639         case MONO_TYPE_GENERICINST:
8640                 type = &type->data.generic_class->container_class->byval_arg;
8641                 goto handle_enum;
8642         case MONO_TYPE_VAR:
8643         case MONO_TYPE_MVAR: {
8644                 int align;
8645
8646                 return mono_type_size (type, &align);
8647         }
8648         case MONO_TYPE_VOID:
8649                 return 0;
8650                 
8651         default:
8652                 g_error ("unknown type 0x%02x in mono_class_array_element_size", type->type);
8653         }
8654         return -1;
8655 }
8656
8657 /**
8658  * mono_array_element_size:
8659  * \param ac pointer to a \c MonoArrayClass
8660  *
8661  * \returns The size of single array element.
8662  *
8663  * LOCKING: Acquires the loader lock.
8664  */
8665 gint32
8666 mono_array_element_size (MonoClass *ac)
8667 {
8668         g_assert (ac->rank);
8669         if (G_UNLIKELY (!ac->size_inited)) {
8670                 mono_class_setup_fields (ac);
8671         }
8672         return ac->sizes.element_size;
8673 }
8674
8675 /**
8676  * mono_ldtoken:
8677  */
8678 gpointer
8679 mono_ldtoken (MonoImage *image, guint32 token, MonoClass **handle_class,
8680               MonoGenericContext *context)
8681 {
8682         MonoError error;
8683         gpointer res = mono_ldtoken_checked (image, token, handle_class, context, &error);
8684         g_assert (mono_error_ok (&error));
8685         return res;
8686 }
8687
8688 gpointer
8689 mono_ldtoken_checked (MonoImage *image, guint32 token, MonoClass **handle_class,
8690               MonoGenericContext *context, MonoError *error)
8691 {
8692         error_init (error);
8693
8694         if (image_is_dynamic (image)) {
8695                 MonoClass *tmp_handle_class;
8696                 gpointer obj = mono_lookup_dynamic_token_class (image, token, TRUE, &tmp_handle_class, context, error);
8697
8698                 mono_error_assert_ok (error);
8699                 g_assert (tmp_handle_class);
8700                 if (handle_class)
8701                         *handle_class = tmp_handle_class;
8702
8703                 if (tmp_handle_class == mono_defaults.typehandle_class)
8704                         return &((MonoClass*)obj)->byval_arg;
8705                 else
8706                         return obj;
8707         }
8708
8709         switch (token & 0xff000000) {
8710         case MONO_TOKEN_TYPE_DEF:
8711         case MONO_TOKEN_TYPE_REF:
8712         case MONO_TOKEN_TYPE_SPEC: {
8713                 MonoType *type;
8714                 if (handle_class)
8715                         *handle_class = mono_defaults.typehandle_class;
8716                 type = mono_type_get_checked (image, token, context, error);
8717                 if (!type)
8718                         return NULL;
8719
8720                 mono_class_init (mono_class_from_mono_type (type));
8721                 /* We return a MonoType* as handle */
8722                 return type;
8723         }
8724         case MONO_TOKEN_FIELD_DEF: {
8725                 MonoClass *klass;
8726                 guint32 type = mono_metadata_typedef_from_field (image, mono_metadata_token_index (token));
8727                 if (!type) {
8728                         mono_error_set_bad_image (error, image, "Bad ldtoken %x", token);
8729                         return NULL;
8730                 }
8731                 if (handle_class)
8732                         *handle_class = mono_defaults.fieldhandle_class;
8733                 klass = mono_class_get_and_inflate_typespec_checked (image, MONO_TOKEN_TYPE_DEF | type, context, error);
8734                 if (!klass)
8735                         return NULL;
8736
8737                 mono_class_init (klass);
8738                 return mono_class_get_field (klass, token);
8739         }
8740         case MONO_TOKEN_METHOD_DEF:
8741         case MONO_TOKEN_METHOD_SPEC: {
8742                 MonoMethod *meth;
8743                 meth = mono_get_method_checked (image, token, NULL, context, error);
8744                 if (handle_class)
8745                         *handle_class = mono_defaults.methodhandle_class;
8746                 if (!meth)
8747                         return NULL;
8748
8749                 return meth;
8750         }
8751         case MONO_TOKEN_MEMBER_REF: {
8752                 guint32 cols [MONO_MEMBERREF_SIZE];
8753                 const char *sig;
8754                 mono_metadata_decode_row (&image->tables [MONO_TABLE_MEMBERREF], mono_metadata_token_index (token) - 1, cols, MONO_MEMBERREF_SIZE);
8755                 sig = mono_metadata_blob_heap (image, cols [MONO_MEMBERREF_SIGNATURE]);
8756                 mono_metadata_decode_blob_size (sig, &sig);
8757                 if (*sig == 0x6) { /* it's a field */
8758                         MonoClass *klass;
8759                         MonoClassField *field;
8760                         field = mono_field_from_token_checked (image, token, &klass, context, error);
8761                         if (handle_class)
8762                                 *handle_class = mono_defaults.fieldhandle_class;
8763                         return field;
8764                 } else {
8765                         MonoMethod *meth;
8766                         meth = mono_get_method_checked (image, token, NULL, context, error);
8767                         if (handle_class)
8768                                 *handle_class = mono_defaults.methodhandle_class;
8769                         return meth;
8770                 }
8771         }
8772         default:
8773                 mono_error_set_bad_image (error, image, "Bad ldtoken %x", token);
8774         }
8775         return NULL;
8776 }
8777
8778 gpointer
8779 mono_lookup_dynamic_token (MonoImage *image, guint32 token, MonoGenericContext *context, MonoError *error)
8780 {
8781         MonoClass *handle_class;
8782         error_init (error);
8783         return mono_reflection_lookup_dynamic_token (image, token, TRUE, &handle_class, context, error);
8784 }
8785
8786 gpointer
8787 mono_lookup_dynamic_token_class (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context, MonoError *error)
8788 {
8789         return mono_reflection_lookup_dynamic_token (image, token, valid_token, handle_class, context, error);
8790 }
8791
8792 static MonoGetCachedClassInfo get_cached_class_info = NULL;
8793
8794 void
8795 mono_install_get_cached_class_info (MonoGetCachedClassInfo func)
8796 {
8797         get_cached_class_info = func;
8798 }
8799
8800 static gboolean
8801 mono_class_get_cached_class_info (MonoClass *klass, MonoCachedClassInfo *res)
8802 {
8803         if (!get_cached_class_info)
8804                 return FALSE;
8805         else
8806                 return get_cached_class_info (klass, res);
8807 }
8808
8809 void
8810 mono_install_get_class_from_name (MonoGetClassFromName func)
8811 {
8812         get_class_from_name = func;
8813 }
8814
8815 /**
8816  * mono_class_get_image:
8817  *
8818  * Use this method to get the \c MonoImage* where this class came from.
8819  *
8820  * \returns The image where this class is defined.
8821  */
8822 MonoImage*
8823 mono_class_get_image (MonoClass *klass)
8824 {
8825         return klass->image;
8826 }
8827
8828 /**
8829  * mono_class_get_element_class:
8830  * \param klass the \c MonoClass to act on
8831  *
8832  * Use this function to get the element class of an array.
8833  *
8834  * \returns The element class of an array.
8835  */
8836 MonoClass*
8837 mono_class_get_element_class (MonoClass *klass)
8838 {
8839         return klass->element_class;
8840 }
8841
8842 /**
8843  * mono_class_is_valuetype:
8844  * \param klass the \c MonoClass to act on
8845  *
8846  * Use this method to determine if the provided \c MonoClass* represents a value type,
8847  * or a reference type.
8848  *
8849  * \returns TRUE if the \c MonoClass represents a \c ValueType, FALSE if it represents a reference type.
8850  */
8851 gboolean
8852 mono_class_is_valuetype (MonoClass *klass)
8853 {
8854         return klass->valuetype;
8855 }
8856
8857 /**
8858  * mono_class_is_enum:
8859  * \param klass the \c MonoClass to act on
8860  *
8861  * Use this function to determine if the provided \c MonoClass* represents an enumeration.
8862  *
8863  * \returns TRUE if the \c MonoClass represents an enumeration.
8864  */
8865 gboolean
8866 mono_class_is_enum (MonoClass *klass)
8867 {
8868         return klass->enumtype;
8869 }
8870
8871 /**
8872  * mono_class_enum_basetype:
8873  * \param klass the \c MonoClass to act on
8874  *
8875  * Use this function to get the underlying type for an enumeration value.
8876  * 
8877  * \returns The underlying type representation for an enumeration.
8878  */
8879 MonoType*
8880 mono_class_enum_basetype (MonoClass *klass)
8881 {
8882         if (klass->element_class == klass)
8883                 /* SRE or broken types */
8884                 return NULL;
8885         else
8886                 return &klass->element_class->byval_arg;
8887 }
8888
8889 /**
8890  * mono_class_get_parent
8891  * \param klass the \c MonoClass to act on
8892  *
8893  * \returns The parent class for this class.
8894  */
8895 MonoClass*
8896 mono_class_get_parent (MonoClass *klass)
8897 {
8898         return klass->parent;
8899 }
8900
8901 /**
8902  * mono_class_get_nesting_type:
8903  * \param klass the \c MonoClass to act on
8904  *
8905  * Use this function to obtain the class that the provided \c MonoClass* is nested on.
8906  *
8907  * If the return is NULL, this indicates that this class is not nested.
8908  *
8909  * \returns The container type where this type is nested or NULL if this type is not a nested type.
8910  */
8911 MonoClass*
8912 mono_class_get_nesting_type (MonoClass *klass)
8913 {
8914         return klass->nested_in;
8915 }
8916
8917 /**
8918  * mono_class_get_rank:
8919  * \param klass the MonoClass to act on
8920  *
8921  * \returns The rank for the array (the number of dimensions).
8922  */
8923 int
8924 mono_class_get_rank (MonoClass *klass)
8925 {
8926         return klass->rank;
8927 }
8928
8929 /**
8930  * mono_class_get_name
8931  * \param klass the \c MonoClass to act on
8932  *
8933  * \returns The name of the class.
8934  */
8935 const char*
8936 mono_class_get_name (MonoClass *klass)
8937 {
8938         return klass->name;
8939 }
8940
8941 /**
8942  * mono_class_get_namespace:
8943  * \param klass the \c MonoClass to act on
8944  *
8945  * \returns The namespace of the class.
8946  */
8947 const char*
8948 mono_class_get_namespace (MonoClass *klass)
8949 {
8950         return klass->name_space;
8951 }
8952
8953 /**
8954  * mono_class_get_type:
8955  * \param klass the \c MonoClass to act on
8956  *
8957  * This method returns the internal \c MonoType representation for the class.
8958  *
8959  * \returns The \c MonoType from the class.
8960  */
8961 MonoType*
8962 mono_class_get_type (MonoClass *klass)
8963 {
8964         return &klass->byval_arg;
8965 }
8966
8967 /**
8968  * mono_class_get_type_token:
8969  * \param klass the \c MonoClass to act on
8970  *
8971  * This method returns type token for the class.
8972  *
8973  * \returns The type token for the class.
8974  */
8975 guint32
8976 mono_class_get_type_token (MonoClass *klass)
8977 {
8978   return klass->type_token;
8979 }
8980
8981 /**
8982  * mono_class_get_byref_type:
8983  * \param klass the \c MonoClass to act on
8984  *
8985  * 
8986  */
8987 MonoType*
8988 mono_class_get_byref_type (MonoClass *klass)
8989 {
8990         return &klass->this_arg;
8991 }
8992
8993 /**
8994  * mono_class_num_fields:
8995  * \param klass the \c MonoClass to act on
8996  *
8997  * \returns The number of static and instance fields in the class.
8998  */
8999 int
9000 mono_class_num_fields (MonoClass *klass)
9001 {
9002         return mono_class_get_field_count (klass);
9003 }
9004
9005 /**
9006  * mono_class_num_methods:
9007  * \param klass the \c MonoClass to act on
9008  *
9009  * \returns The number of methods in the class.
9010  */
9011 int
9012 mono_class_num_methods (MonoClass *klass)
9013 {
9014         return mono_class_get_method_count (klass);
9015 }
9016
9017 /**
9018  * mono_class_num_properties
9019  * \param klass the \c MonoClass to act on
9020  *
9021  * \returns The number of properties in the class.
9022  */
9023 int
9024 mono_class_num_properties (MonoClass *klass)
9025 {
9026         mono_class_setup_properties (klass);
9027
9028         return mono_class_get_property_info (klass)->count;
9029 }
9030
9031 /**
9032  * mono_class_num_events:
9033  * \param klass the \c MonoClass to act on
9034  *
9035  * \returns The number of events in the class.
9036  */
9037 int
9038 mono_class_num_events (MonoClass *klass)
9039 {
9040         mono_class_setup_events (klass);
9041
9042         return mono_class_get_event_info (klass)->count;
9043 }
9044
9045 /**
9046  * mono_class_get_fields:
9047  * \param klass the \c MonoClass to act on
9048  *
9049  * This routine is an iterator routine for retrieving the fields in a class.
9050  *
9051  * You must pass a \c gpointer that points to zero and is treated as an opaque handle to
9052  * iterate over all of the elements.  When no more values are
9053  * available, the return value is NULL.
9054  *
9055  * \returns a \c MonoClassField* on each iteration, or NULL when no more fields are available.
9056  */
9057 MonoClassField*
9058 mono_class_get_fields (MonoClass* klass, gpointer *iter)
9059 {
9060         MonoClassField* field;
9061         if (!iter)
9062                 return NULL;
9063         if (!*iter) {
9064                 mono_class_setup_fields (klass);
9065                 if (mono_class_has_failure (klass))
9066                         return NULL;
9067                 /* start from the first */
9068                 if (mono_class_get_field_count (klass)) {
9069                         *iter = &klass->fields [0];
9070                         return &klass->fields [0];
9071                 } else {
9072                         /* no fields */
9073                         return NULL;
9074                 }
9075         }
9076         field = (MonoClassField *)*iter;
9077         field++;
9078         if (field < &klass->fields [mono_class_get_field_count (klass)]) {
9079                 *iter = field;
9080                 return field;
9081         }
9082         return NULL;
9083 }
9084
9085 /**
9086  * mono_class_get_methods:
9087  * \param klass the \c MonoClass to act on
9088  *
9089  * This routine is an iterator routine for retrieving the fields in a class.
9090  *
9091  * You must pass a \c gpointer that points to zero and is treated as an opaque handle to
9092  * iterate over all of the elements.  When no more values are
9093  * available, the return value is NULL.
9094  *
9095  * \returns a \c MonoMethod on each iteration or NULL when no more methods are available.
9096  */
9097 MonoMethod*
9098 mono_class_get_methods (MonoClass* klass, gpointer *iter)
9099 {
9100         MonoMethod** method;
9101         if (!iter)
9102                 return NULL;
9103         if (!*iter) {
9104                 mono_class_setup_methods (klass);
9105
9106                 /*
9107                  * We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
9108                  * FIXME we should better report this error to the caller
9109                  */
9110                 if (!klass->methods)
9111                         return NULL;
9112                 /* start from the first */
9113                 if (mono_class_get_method_count (klass)) {
9114                         *iter = &klass->methods [0];
9115                         return klass->methods [0];
9116                 } else {
9117                         /* no method */
9118                         return NULL;
9119                 }
9120         }
9121         method = (MonoMethod **)*iter;
9122         method++;
9123         if (method < &klass->methods [mono_class_get_method_count (klass)]) {
9124                 *iter = method;
9125                 return *method;
9126         }
9127         return NULL;
9128 }
9129
9130 /*
9131  * mono_class_get_virtual_methods:
9132  *
9133  *   Iterate over the virtual methods of KLASS.
9134  *
9135  * LOCKING: Assumes the loader lock is held (because of the klass->methods check).
9136  */
9137 static MonoMethod*
9138 mono_class_get_virtual_methods (MonoClass* klass, gpointer *iter)
9139 {
9140         gboolean static_iter = FALSE;
9141
9142         if (!iter)
9143                 return NULL;
9144
9145         /*
9146          * If the lowest bit of the iterator is 1, this is an iterator for static metadata,
9147          * and the upper bits contain an index. Otherwise, the iterator is a pointer into
9148          * klass->methods.
9149          */
9150         if ((gsize)(*iter) & 1)
9151                 static_iter = TRUE;
9152         /* Use the static metadata only if klass->methods is not yet initialized */
9153         if (!static_iter && !(klass->methods || !MONO_CLASS_HAS_STATIC_METADATA (klass)))
9154                 static_iter = TRUE;
9155
9156         if (!static_iter) {
9157                 MonoMethod** methodptr;
9158
9159                 if (!*iter) {
9160                         mono_class_setup_methods (klass);
9161                         /*
9162                          * We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
9163                          * FIXME we should better report this error to the caller
9164                          */
9165                         if (!klass->methods)
9166                                 return NULL;
9167                         /* start from the first */
9168                         methodptr = &klass->methods [0];
9169                 } else {
9170                         methodptr = (MonoMethod **)*iter;
9171                         methodptr++;
9172                 }
9173                 if (*iter)
9174                         g_assert ((guint64)(*iter) > 0x100);
9175                 int mcount = mono_class_get_method_count (klass);
9176                 while (methodptr < &klass->methods [mcount]) {
9177                         if (*methodptr && ((*methodptr)->flags & METHOD_ATTRIBUTE_VIRTUAL))
9178                                 break;
9179                         methodptr ++;
9180                 }
9181                 if (methodptr < &klass->methods [mcount]) {
9182                         *iter = methodptr;
9183                         return *methodptr;
9184                 } else {
9185                         return NULL;
9186                 }
9187         } else {
9188                 /* Search directly in metadata to avoid calling setup_methods () */
9189                 MonoMethod *res = NULL;
9190                 int i, start_index;
9191
9192                 if (!*iter) {
9193                         start_index = 0;
9194                 } else {
9195                         start_index = GPOINTER_TO_UINT (*iter) >> 1;
9196                 }
9197
9198                 int first_idx = mono_class_get_first_method_idx (klass);
9199                 int mcount = mono_class_get_method_count (klass);
9200                 for (i = start_index; i < mcount; ++i) {
9201                         guint32 flags;
9202
9203                         /* first_idx points into the methodptr table */
9204                         flags = mono_metadata_decode_table_row_col (klass->image, MONO_TABLE_METHOD, first_idx + i, MONO_METHOD_FLAGS);
9205
9206                         if (flags & METHOD_ATTRIBUTE_VIRTUAL)
9207                                 break;
9208                 }
9209
9210                 if (i < mcount) {
9211                         MonoError error;
9212                         res = mono_get_method_checked (klass->image, MONO_TOKEN_METHOD_DEF | (first_idx + i + 1), klass, NULL, &error);
9213                         mono_error_cleanup (&error); /* FIXME don't swallow the error */
9214
9215                         /* Add 1 here so the if (*iter) check fails */
9216                         *iter  = GUINT_TO_POINTER (((i + 1) << 1) | 1);
9217                         return res;
9218                 } else {
9219                         return NULL;
9220                 }
9221         }
9222 }
9223
9224 /**
9225  * mono_class_get_properties:
9226  * \param klass the \c MonoClass to act on
9227  *
9228  * This routine is an iterator routine for retrieving the properties in a class.
9229  *
9230  * You must pass a gpointer that points to zero and is treated as an opaque handle to
9231  * iterate over all of the elements.  When no more values are
9232  * available, the return value is NULL.
9233  *
9234  * Returns: a \c MonoProperty* on each invocation, or NULL when no more are available.
9235  */
9236 MonoProperty*
9237 mono_class_get_properties (MonoClass* klass, gpointer *iter)
9238 {
9239         MonoProperty* property;
9240         if (!iter)
9241                 return NULL;
9242         if (!*iter) {
9243                 mono_class_setup_properties (klass);
9244                 MonoClassPropertyInfo *info = mono_class_get_property_info (klass);
9245                 /* start from the first */
9246                 if (info->count) {
9247                         *iter = &info->properties [0];
9248                         return (MonoProperty *)*iter;
9249                 } else {
9250                         /* no fields */
9251                         return NULL;
9252                 }
9253         }
9254         property = (MonoProperty *)*iter;
9255         property++;
9256         MonoClassPropertyInfo *info = mono_class_get_property_info (klass);
9257         if (property < &info->properties [info->count]) {
9258                 *iter = property;
9259                 return (MonoProperty *)*iter;
9260         }
9261         return NULL;
9262 }
9263
9264 /**
9265  * mono_class_get_events:
9266  * \param klass the \c MonoClass to act on
9267  *
9268  * This routine is an iterator routine for retrieving the properties in a class.
9269  *
9270  * You must pass a \c gpointer that points to zero and is treated as an opaque handle to
9271  * iterate over all of the elements.  When no more values are
9272  * available, the return value is NULL.
9273  *
9274  * \returns a \c MonoEvent* on each invocation, or NULL when no more are available.
9275  */
9276 MonoEvent*
9277 mono_class_get_events (MonoClass* klass, gpointer *iter)
9278 {
9279         MonoEvent* event;
9280         if (!iter)
9281                 return NULL;
9282         if (!*iter) {
9283                 mono_class_setup_events (klass);
9284                 MonoClassEventInfo *info = mono_class_get_event_info (klass);
9285                 /* start from the first */
9286                 if (info->count) {
9287                         *iter = &info->events [0];
9288                         return (MonoEvent *)*iter;
9289                 } else {
9290                         /* no fields */
9291                         return NULL;
9292                 }
9293         }
9294         event = (MonoEvent *)*iter;
9295         event++;
9296         MonoClassEventInfo *info = mono_class_get_event_info (klass);
9297         if (event < &info->events [info->count]) {
9298                 *iter = event;
9299                 return (MonoEvent *)*iter;
9300         }
9301         return NULL;
9302 }
9303
9304 /**
9305  * mono_class_get_interfaces
9306  * \param klass the \c MonoClass to act on
9307  *
9308  * This routine is an iterator routine for retrieving the interfaces implemented by this class.
9309  *
9310  * You must pass a \c gpointer that points to zero and is treated as an opaque handle to
9311  * iterate over all of the elements.  When no more values are
9312  * available, the return value is NULL.
9313  *
9314  * \returns a \c MonoClass* on each invocation, or NULL when no more are available.
9315  */
9316 MonoClass*
9317 mono_class_get_interfaces (MonoClass* klass, gpointer *iter)
9318 {
9319         MonoError error;
9320         MonoClass** iface;
9321         if (!iter)
9322                 return NULL;
9323         if (!*iter) {
9324                 if (!klass->inited)
9325                         mono_class_init (klass);
9326                 if (!klass->interfaces_inited) {
9327                         mono_class_setup_interfaces (klass, &error);
9328                         if (!mono_error_ok (&error)) {
9329                                 mono_error_cleanup (&error);
9330                                 return NULL;
9331                         }
9332                 }
9333                 /* start from the first */
9334                 if (klass->interface_count) {
9335                         *iter = &klass->interfaces [0];
9336                         return klass->interfaces [0];
9337                 } else {
9338                         /* no interface */
9339                         return NULL;
9340                 }
9341         }
9342         iface = (MonoClass **)*iter;
9343         iface++;
9344         if (iface < &klass->interfaces [klass->interface_count]) {
9345                 *iter = iface;
9346                 return *iface;
9347         }
9348         return NULL;
9349 }
9350
9351 static void
9352 setup_nested_types (MonoClass *klass)
9353 {
9354         MonoError error;
9355         GList *classes, *nested_classes, *l;
9356         int i;
9357
9358         if (klass->nested_classes_inited)
9359                 return;
9360
9361         if (!klass->type_token) {
9362                 mono_loader_lock ();
9363                 klass->nested_classes_inited = TRUE;
9364                 mono_loader_unlock ();
9365                 return;
9366         }
9367
9368         i = mono_metadata_nesting_typedef (klass->image, klass->type_token, 1);
9369         classes = NULL;
9370         while (i) {
9371                 MonoClass* nclass;
9372                 guint32 cols [MONO_NESTED_CLASS_SIZE];
9373                 mono_metadata_decode_row (&klass->image->tables [MONO_TABLE_NESTEDCLASS], i - 1, cols, MONO_NESTED_CLASS_SIZE);
9374                 nclass = mono_class_create_from_typedef (klass->image, MONO_TOKEN_TYPE_DEF | cols [MONO_NESTED_CLASS_NESTED], &error);
9375                 if (!mono_error_ok (&error)) {
9376                         /*FIXME don't swallow the error message*/
9377                         mono_error_cleanup (&error);
9378
9379                         i = mono_metadata_nesting_typedef (klass->image, klass->type_token, i + 1);
9380                         continue;
9381                 }
9382
9383                 classes = g_list_prepend (classes, nclass);
9384
9385                 i = mono_metadata_nesting_typedef (klass->image, klass->type_token, i + 1);
9386         }
9387
9388         nested_classes = NULL;
9389         for (l = classes; l; l = l->next)
9390                 nested_classes = g_list_prepend_image (klass->image, nested_classes, l->data);
9391         g_list_free (classes);
9392
9393         mono_loader_lock ();
9394         if (!klass->nested_classes_inited) {
9395                 mono_class_set_nested_classes_property (klass, nested_classes);
9396                 mono_memory_barrier ();
9397                 klass->nested_classes_inited = TRUE;
9398         }
9399         mono_loader_unlock ();
9400 }
9401
9402 /**
9403  * mono_class_get_nested_types
9404  * \param klass the \c MonoClass to act on
9405  *
9406  * This routine is an iterator routine for retrieving the nested types of a class.
9407  * This works only if \p klass is non-generic, or a generic type definition.
9408  *
9409  * You must pass a \c gpointer that points to zero and is treated as an opaque handle to
9410  * iterate over all of the elements.  When no more values are
9411  * available, the return value is NULL.
9412  *
9413  * \returns a \c Monoclass* on each invocation, or NULL when no more are available.
9414  */
9415 MonoClass*
9416 mono_class_get_nested_types (MonoClass* klass, gpointer *iter)
9417 {
9418         GList *item;
9419
9420         if (!iter)
9421                 return NULL;
9422         if (!klass->nested_classes_inited)
9423                 setup_nested_types (klass);
9424
9425         if (!*iter) {
9426                 GList *nested_classes = mono_class_get_nested_classes_property (klass);
9427                 /* start from the first */
9428                 if (nested_classes) {
9429                         *iter = nested_classes;
9430                         return (MonoClass *)nested_classes->data;
9431                 } else {
9432                         /* no nested types */
9433                         return NULL;
9434                 }
9435         }
9436         item = (GList *)*iter;
9437         item = item->next;
9438         if (item) {
9439                 *iter = item;
9440                 return (MonoClass *)item->data;
9441         }
9442         return NULL;
9443 }
9444
9445
9446 /**
9447  * mono_class_is_delegate
9448  * \param klass the \c MonoClass to act on
9449  *
9450  * \returns TRUE if the \c MonoClass represents a \c System.Delegate.
9451  */
9452 mono_bool
9453 mono_class_is_delegate (MonoClass *klass)
9454 {
9455         return klass->delegate;
9456 }
9457
9458 /**
9459  * mono_class_implements_interface
9460  * \param klass The MonoClass to act on
9461  * \param interface The interface to check if \p klass implements.
9462  *
9463  * \returns TRUE if \p klass implements \p interface.
9464  */
9465 mono_bool
9466 mono_class_implements_interface (MonoClass* klass, MonoClass* iface)
9467 {
9468         return mono_class_is_assignable_from (iface, klass);
9469 }
9470
9471 /**
9472  * mono_field_get_name:
9473  * \param field the \c MonoClassField to act on
9474  *
9475  * \returns The name of the field.
9476  */
9477 const char*
9478 mono_field_get_name (MonoClassField *field)
9479 {
9480         return field->name;
9481 }
9482
9483 /**
9484  * mono_field_get_type:
9485  * \param field the \c MonoClassField to act on
9486  * \returns \c MonoType of the field.
9487  */
9488 MonoType*
9489 mono_field_get_type (MonoClassField *field)
9490 {
9491         MonoError error;
9492         MonoType *type = mono_field_get_type_checked (field, &error);
9493         if (!mono_error_ok (&error)) {
9494                 mono_trace_warning (MONO_TRACE_TYPE, "Could not load field's type due to %s", mono_error_get_message (&error));
9495                 mono_error_cleanup (&error);
9496         }
9497         return type;
9498 }
9499
9500
9501 /**
9502  * mono_field_get_type_checked:
9503  * \param field the \c MonoClassField to act on
9504  * \param error used to return any error found while retrieving \p field type
9505  *
9506  * \returns \c MonoType of the field.
9507  */
9508 MonoType*
9509 mono_field_get_type_checked (MonoClassField *field, MonoError *error)
9510 {
9511         error_init (error);
9512         if (!field->type)
9513                 mono_field_resolve_type (field, error);
9514         return field->type;
9515 }
9516
9517 /**
9518  * mono_field_get_parent:
9519  * \param field the \c MonoClassField to act on
9520  *
9521  * \returns \c MonoClass where the field was defined.
9522  */
9523 MonoClass*
9524 mono_field_get_parent (MonoClassField *field)
9525 {
9526         return field->parent;
9527 }
9528
9529 /**
9530  * mono_field_get_flags;
9531  * \param field the \c MonoClassField to act on
9532  *
9533  * The metadata flags for a field are encoded using the
9534  * \c FIELD_ATTRIBUTE_* constants.  See the \c tabledefs.h file for details.
9535  *
9536  * \returns The flags for the field.
9537  */
9538 guint32
9539 mono_field_get_flags (MonoClassField *field)
9540 {
9541         if (!field->type)
9542                 return mono_field_resolve_flags (field);
9543         return field->type->attrs;
9544 }
9545
9546 /**
9547  * mono_field_get_offset:
9548  * \param field the \c MonoClassField to act on
9549  *
9550  * \returns The field offset.
9551  */
9552 guint32
9553 mono_field_get_offset (MonoClassField *field)
9554 {
9555         return field->offset;
9556 }
9557
9558 static const char *
9559 mono_field_get_rva (MonoClassField *field)
9560 {
9561         guint32 rva;
9562         int field_index;
9563         MonoClass *klass = field->parent;
9564         MonoFieldDefaultValue *def_values;
9565
9566         g_assert (field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA);
9567
9568         def_values = mono_class_get_field_def_values (klass);
9569         if (!def_values) {
9570                 def_values = (MonoFieldDefaultValue *)mono_class_alloc0 (klass, sizeof (MonoFieldDefaultValue) * mono_class_get_field_count (klass));
9571
9572                 mono_class_set_field_def_values (klass, def_values);
9573         }
9574
9575         field_index = mono_field_get_index (field);
9576                 
9577         if (!def_values [field_index].data && !image_is_dynamic (klass->image)) {
9578                 int first_field_idx = mono_class_get_first_field_idx (klass);
9579                 mono_metadata_field_info (field->parent->image, first_field_idx + field_index, NULL, &rva, NULL);
9580                 if (!rva)
9581                         g_warning ("field %s in %s should have RVA data, but hasn't", mono_field_get_name (field), field->parent->name);
9582                 def_values [field_index].data = mono_image_rva_map (field->parent->image, rva);
9583         }
9584
9585         return def_values [field_index].data;
9586 }
9587
9588 /**
9589  * mono_field_get_data:
9590  * \param field the \c MonoClassField to act on
9591  *
9592  * \returns A pointer to the metadata constant value or to the field
9593  * data if it has an RVA flag.
9594  */
9595 const char *
9596 mono_field_get_data (MonoClassField *field)
9597 {
9598         if (field->type->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT) {
9599                 MonoTypeEnum def_type;
9600
9601                 return mono_class_get_field_default_value (field, &def_type);
9602         } else if (field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) {
9603                 return mono_field_get_rva (field);
9604         } else {
9605                 return NULL;
9606         }
9607 }
9608
9609 /**
9610  * mono_property_get_name: 
9611  * \param prop the \c MonoProperty to act on
9612  * \returns The name of the property
9613  */
9614 const char*
9615 mono_property_get_name (MonoProperty *prop)
9616 {
9617         return prop->name;
9618 }
9619
9620 /**
9621  * mono_property_get_set_method
9622  * \param prop the \c MonoProperty to act on.
9623  * \returns The setter method of the property, a \c MonoMethod.
9624  */
9625 MonoMethod*
9626 mono_property_get_set_method (MonoProperty *prop)
9627 {
9628         return prop->set;
9629 }
9630
9631 /**
9632  * mono_property_get_get_method
9633  * \param prop the MonoProperty to act on.
9634  * \returns The getter method of the property (A \c MonoMethod)
9635  */
9636 MonoMethod*
9637 mono_property_get_get_method (MonoProperty *prop)
9638 {
9639         return prop->get;
9640 }
9641
9642 /**
9643  * mono_property_get_parent:
9644  * \param prop the \c MonoProperty to act on.
9645  * \returns The \c MonoClass where the property was defined.
9646  */
9647 MonoClass*
9648 mono_property_get_parent (MonoProperty *prop)
9649 {
9650         return prop->parent;
9651 }
9652
9653 /**
9654  * mono_property_get_flags:
9655  * \param prop the \c MonoProperty to act on.
9656  *
9657  * The metadata flags for a property are encoded using the
9658  * \c PROPERTY_ATTRIBUTE_* constants.  See the \c tabledefs.h file for details.
9659  *
9660  * \returns The flags for the property.
9661  */
9662 guint32
9663 mono_property_get_flags (MonoProperty *prop)
9664 {
9665         return prop->attrs;
9666 }
9667
9668 /**
9669  * mono_event_get_name:
9670  * \param event the MonoEvent to act on
9671  * \returns The name of the event.
9672  */
9673 const char*
9674 mono_event_get_name (MonoEvent *event)
9675 {
9676         return event->name;
9677 }
9678
9679 /**
9680  * mono_event_get_add_method:
9681  * \param event The \c MonoEvent to act on.
9682  * \returns The \c add method for the event, a \c MonoMethod.
9683  */
9684 MonoMethod*
9685 mono_event_get_add_method (MonoEvent *event)
9686 {
9687         return event->add;
9688 }
9689
9690 /**
9691  * mono_event_get_remove_method:
9692  * \param event The \c MonoEvent to act on.
9693  * \returns The \c remove method for the event, a \c MonoMethod.
9694  */
9695 MonoMethod*
9696 mono_event_get_remove_method (MonoEvent *event)
9697 {
9698         return event->remove;
9699 }
9700
9701 /**
9702  * mono_event_get_raise_method:
9703  * \param event The \c MonoEvent to act on.
9704  * \returns The \c raise method for the event, a \c MonoMethod.
9705  */
9706 MonoMethod*
9707 mono_event_get_raise_method (MonoEvent *event)
9708 {
9709         return event->raise;
9710 }
9711
9712 /**
9713  * mono_event_get_parent:
9714  * \param event the MonoEvent to act on.
9715  * \returns The \c MonoClass where the event is defined.
9716  */
9717 MonoClass*
9718 mono_event_get_parent (MonoEvent *event)
9719 {
9720         return event->parent;
9721 }
9722
9723 /**
9724  * mono_event_get_flags
9725  * \param event the \c MonoEvent to act on.
9726  *
9727  * The metadata flags for an event are encoded using the
9728  * \c EVENT_* constants.  See the \c tabledefs.h file for details.
9729  *
9730  * \returns The flags for the event.
9731  */
9732 guint32
9733 mono_event_get_flags (MonoEvent *event)
9734 {
9735         return event->attrs;
9736 }
9737
9738 /**
9739  * mono_class_get_method_from_name:
9740  * \param klass where to look for the method
9741  * \param name name of the method
9742  * \param param_count number of parameters. -1 for any number.
9743  *
9744  * Obtains a \c MonoMethod with a given name and number of parameters.
9745  * It only works if there are no multiple signatures for any given method name.
9746  */
9747 MonoMethod *
9748 mono_class_get_method_from_name (MonoClass *klass, const char *name, int param_count)
9749 {
9750         return mono_class_get_method_from_name_flags (klass, name, param_count, 0);
9751 }
9752
9753 static MonoMethod*
9754 find_method_in_metadata (MonoClass *klass, const char *name, int param_count, int flags)
9755 {
9756         MonoMethod *res = NULL;
9757         int i;
9758
9759         /* Search directly in the metadata to avoid calling setup_methods () */
9760         int first_idx = mono_class_get_first_method_idx (klass);
9761         int mcount = mono_class_get_method_count (klass);
9762         for (i = 0; i < mcount; ++i) {
9763                 MonoError error;
9764                 guint32 cols [MONO_METHOD_SIZE];
9765                 MonoMethod *method;
9766                 MonoMethodSignature *sig;
9767
9768                 /* first_idx points into the methodptr table */
9769                 mono_metadata_decode_table_row (klass->image, MONO_TABLE_METHOD, first_idx + i, cols, MONO_METHOD_SIZE);
9770
9771                 if (!strcmp (mono_metadata_string_heap (klass->image, cols [MONO_METHOD_NAME]), name)) {
9772                         method = mono_get_method_checked (klass->image, MONO_TOKEN_METHOD_DEF | (first_idx + i + 1), klass, NULL, &error);
9773                         if (!method) {
9774                                 mono_error_cleanup (&error); /* FIXME don't swallow the error */
9775                                 continue;
9776                         }
9777                         if (param_count == -1) {
9778                                 res = method;
9779                                 break;
9780                         }
9781                         sig = mono_method_signature_checked (method, &error);
9782                         if (!sig) {
9783                                 mono_error_cleanup (&error); /* FIXME don't swallow the error */
9784                                 continue;
9785                         }
9786                         if (sig->param_count == param_count) {
9787                                 res = method;
9788                                 break;
9789                         }
9790                 }
9791         }
9792
9793         return res;
9794 }
9795
9796 /**
9797  * mono_class_get_method_from_name_flags:
9798  * \param klass where to look for the method
9799  * \param name_space name of the method
9800  * \param param_count number of parameters. -1 for any number.
9801  * \param flags flags which must be set in the method
9802  *
9803  * Obtains a \c MonoMethod with a given name and number of parameters.
9804  * It only works if there are no multiple signatures for any given method name.
9805  */
9806 MonoMethod *
9807 mono_class_get_method_from_name_flags (MonoClass *klass, const char *name, int param_count, int flags)
9808 {
9809         MonoMethod *res = NULL;
9810         int i;
9811
9812         mono_class_init (klass);
9813
9814         if (mono_class_is_ginst (klass) && !klass->methods) {
9815                 res = mono_class_get_method_from_name_flags (mono_class_get_generic_class (klass)->container_class, name, param_count, flags);
9816                 if (res) {
9817                         MonoError error;
9818                         res = mono_class_inflate_generic_method_full_checked (res, klass, mono_class_get_context (klass), &error);
9819                         if (!mono_error_ok (&error))
9820                                 mono_error_cleanup (&error); /*FIXME don't swallow the error */
9821                 }
9822                 return res;
9823         }
9824
9825         if (klass->methods || !MONO_CLASS_HAS_STATIC_METADATA (klass)) {
9826                 mono_class_setup_methods (klass);
9827                 /*
9828                 We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
9829                 See mono/tests/array_load_exception.il
9830                 FIXME we should better report this error to the caller
9831                  */
9832                 if (!klass->methods)
9833                         return NULL;
9834                 int mcount = mono_class_get_method_count (klass);
9835                 for (i = 0; i < mcount; ++i) {
9836                         MonoMethod *method = klass->methods [i];
9837
9838                         if (method->name[0] == name [0] && 
9839                                 !strcmp (name, method->name) &&
9840                                 (param_count == -1 || mono_method_signature (method)->param_count == param_count) &&
9841                                 ((method->flags & flags) == flags)) {
9842                                 res = method;
9843                                 break;
9844                         }
9845                 }
9846         }
9847         else {
9848             res = find_method_in_metadata (klass, name, param_count, flags);
9849         }
9850
9851         return res;
9852 }
9853
9854 /**
9855  * mono_class_set_failure:
9856  * \param klass class in which the failure was detected
9857  * \param ex_type the kind of exception/error to be thrown (later)
9858  * \param ex_data exception data (specific to each type of exception/error)
9859  *
9860  * Keep a detected failure informations in the class for later processing.
9861  * Note that only the first failure is kept.
9862  *
9863  * LOCKING: Acquires the loader lock.
9864  */
9865 static gboolean
9866 mono_class_set_failure (MonoClass *klass, MonoErrorBoxed *boxed_error)
9867 {
9868         g_assert (boxed_error != NULL);
9869
9870         if (mono_class_has_failure (klass))
9871                 return FALSE;
9872
9873         mono_loader_lock ();
9874         klass->has_failure = 1;
9875         mono_class_set_exception_data (klass, boxed_error);
9876         mono_loader_unlock ();
9877
9878         return TRUE;
9879 }
9880
9881 gboolean
9882 mono_class_has_failure (const MonoClass *klass)
9883 {
9884         g_assert (klass != NULL);
9885         return klass->has_failure != 0;
9886 }
9887
9888
9889 /**
9890  * mono_class_set_type_load_failure:
9891  * \param klass class in which the failure was detected
9892  * \param fmt \c printf -style error message string.
9893  *
9894  * Collect detected failure informaion in the class for later processing.
9895  * The error is stored as a MonoErrorBoxed as with mono_error_set_type_load_class()
9896  * Note that only the first failure is kept.
9897  *
9898  * LOCKING: Acquires the loader lock.
9899  *
9900  * \returns FALSE if a failure was already set on the class, or TRUE otherwise.
9901  */
9902 gboolean
9903 mono_class_set_type_load_failure (MonoClass *klass, const char * fmt, ...)
9904 {
9905         MonoError prepare_error;
9906         va_list args;
9907
9908         if (mono_class_has_failure (klass))
9909                 return FALSE;
9910         
9911         error_init (&prepare_error);
9912         
9913         va_start (args, fmt);
9914         mono_error_vset_type_load_class (&prepare_error, klass, fmt, args);
9915         va_end (args);
9916
9917         MonoErrorBoxed *box = mono_error_box (&prepare_error, klass->image);
9918         mono_error_cleanup (&prepare_error);
9919         return mono_class_set_failure (klass, box);
9920 }
9921
9922 /**
9923  * mono_classes_init:
9924  *
9925  * Initialize the resources used by this module.
9926  * Known racy counters: `class_gparam_count`, `classes_size` and `inflated_methods_size`
9927  */
9928 MONO_NO_SANITIZE_THREAD
9929 void
9930 mono_classes_init (void)
9931 {
9932         mono_os_mutex_init (&classes_mutex);
9933
9934         mono_native_tls_alloc (&setup_fields_tls_id, NULL);
9935         mono_native_tls_alloc (&init_pending_tls_id, NULL);
9936
9937         mono_counters_register ("MonoClassDef count",
9938                                                         MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_def_count);
9939         mono_counters_register ("MonoClassGtd count",
9940                                                         MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_gtd_count);
9941         mono_counters_register ("MonoClassGenericInst count",
9942                                                         MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_ginst_count);
9943         mono_counters_register ("MonoClassGenericParam count",
9944                                                         MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_gparam_count);
9945         mono_counters_register ("MonoClassArray count",
9946                                                         MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_array_count);
9947         mono_counters_register ("MonoClassPointer count",
9948                                                         MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_pointer_count);
9949         mono_counters_register ("Inflated methods size",
9950                                                         MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &inflated_methods_size);
9951         mono_counters_register ("Inflated classes size",
9952                                                         MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &inflated_classes_size);
9953         mono_counters_register ("MonoClass size",
9954                                                         MONO_COUNTER_METADATA | MONO_COUNTER_INT, &classes_size);
9955 }
9956
9957 /**
9958  * mono_classes_cleanup:
9959  *
9960  * Free the resources used by this module.
9961  */
9962 void
9963 mono_classes_cleanup (void)
9964 {
9965         mono_native_tls_free (setup_fields_tls_id);
9966         mono_native_tls_free (init_pending_tls_id);
9967
9968         if (global_interface_bitset)
9969                 mono_bitset_free (global_interface_bitset);
9970         global_interface_bitset = NULL;
9971         mono_os_mutex_destroy (&classes_mutex);
9972 }
9973
9974 /**
9975  * mono_class_get_exception_for_failure:
9976  * \param klass class in which the failure was detected
9977  *
9978  * \returns a constructed MonoException than the caller can then throw
9979  * using mono_raise_exception - or NULL if no failure is present (or
9980  * doesn't result in an exception).
9981  */
9982 MonoException*
9983 mono_class_get_exception_for_failure (MonoClass *klass)
9984 {
9985         if (!mono_class_has_failure (klass))
9986                 return NULL;
9987         MonoError unboxed_error;
9988         error_init (&unboxed_error);
9989         mono_error_set_for_class_failure (&unboxed_error, klass);
9990         return mono_error_convert_to_exception (&unboxed_error);
9991 }
9992
9993 static gboolean
9994 is_nesting_type (MonoClass *outer_klass, MonoClass *inner_klass)
9995  {
9996         outer_klass = mono_class_get_generic_type_definition (outer_klass);
9997         inner_klass = mono_class_get_generic_type_definition (inner_klass);
9998         do {
9999                 if (outer_klass == inner_klass)
10000                         return TRUE;
10001                 inner_klass = inner_klass->nested_in;
10002         } while (inner_klass);
10003         return FALSE;
10004 }
10005
10006 MonoClass *
10007 mono_class_get_generic_type_definition (MonoClass *klass)
10008 {
10009         MonoGenericClass *gklass =  mono_class_try_get_generic_class (klass);
10010         return gklass ? gklass->container_class : klass;
10011 }
10012
10013 /*
10014  * Check if @klass is a subtype of @parent ignoring generic instantiations.
10015  * 
10016  * Generic instantiations are ignored for all super types of @klass.
10017  * 
10018  * Visibility checks ignoring generic instantiations.  
10019  */
10020 gboolean
10021 mono_class_has_parent_and_ignore_generics (MonoClass *klass, MonoClass *parent)
10022 {
10023         int i;
10024         klass = mono_class_get_generic_type_definition (klass);
10025         parent = mono_class_get_generic_type_definition (parent);
10026         mono_class_setup_supertypes (klass);
10027
10028         for (i = 0; i < klass->idepth; ++i) {
10029                 if (parent == mono_class_get_generic_type_definition (klass->supertypes [i]))
10030                         return TRUE;
10031         }
10032         return FALSE;
10033 }
10034 /*
10035  * Subtype can only access parent members with family protection if the site object
10036  * is subclass of Subtype. For example:
10037  * class A { protected int x; }
10038  * class B : A {
10039  *      void valid_access () {
10040  *              B b;
10041  *              b.x = 0;
10042  *  }
10043  *  void invalid_access () {
10044  *              A a;
10045  *              a.x = 0;
10046  *  }
10047  * }
10048  * */
10049 static gboolean
10050 is_valid_family_access (MonoClass *access_klass, MonoClass *member_klass, MonoClass *context_klass)
10051 {
10052         if (!mono_class_has_parent_and_ignore_generics (access_klass, member_klass))
10053                 return FALSE;
10054
10055         if (context_klass == NULL)
10056                 return TRUE;
10057         /*if access_klass is not member_klass context_klass must be type compat*/
10058         if (access_klass != member_klass && !mono_class_has_parent_and_ignore_generics (context_klass, access_klass))
10059                 return FALSE;
10060         return TRUE;
10061 }
10062
10063 static gboolean
10064 can_access_internals (MonoAssembly *accessing, MonoAssembly* accessed)
10065 {
10066         GSList *tmp;
10067         if (accessing == accessed)
10068                 return TRUE;
10069         if (!accessed || !accessing)
10070                 return FALSE;
10071
10072         /* extra safety under CoreCLR - the runtime does not verify the strongname signatures
10073          * anywhere so untrusted friends are not safe to access platform's code internals */
10074         if (mono_security_core_clr_enabled ()) {
10075                 if (!mono_security_core_clr_can_access_internals (accessing->image, accessed->image))
10076                         return FALSE;
10077         }
10078
10079         mono_assembly_load_friends (accessed);
10080         for (tmp = accessed->friend_assembly_names; tmp; tmp = tmp->next) {
10081                 MonoAssemblyName *friend_ = (MonoAssemblyName *)tmp->data;
10082                 /* Be conservative with checks */
10083                 if (!friend_->name)
10084                         continue;
10085                 if (g_ascii_strcasecmp (accessing->aname.name, friend_->name))
10086                         continue;
10087                 if (friend_->public_key_token [0]) {
10088                         if (!accessing->aname.public_key_token [0])
10089                                 continue;
10090                         if (!mono_public_tokens_are_equal (friend_->public_key_token, accessing->aname.public_key_token))
10091                                 continue;
10092                 }
10093                 return TRUE;
10094         }
10095         return FALSE;
10096 }
10097
10098 /*
10099  * If klass is a generic type or if it is derived from a generic type, return the
10100  * MonoClass of the generic definition
10101  * Returns NULL if not found
10102  */
10103 static MonoClass*
10104 get_generic_definition_class (MonoClass *klass)
10105 {
10106         while (klass) {
10107                 MonoGenericClass *gklass = mono_class_try_get_generic_class (klass);
10108                 if (gklass && gklass->container_class)
10109                         return gklass->container_class;
10110                 klass = klass->parent;
10111         }
10112         return NULL;
10113 }
10114
10115 static gboolean
10116 can_access_instantiation (MonoClass *access_klass, MonoGenericInst *ginst)
10117 {
10118         int i;
10119         for (i = 0; i < ginst->type_argc; ++i) {
10120                 MonoType *type = ginst->type_argv[i];
10121                 switch (type->type) {
10122                 case MONO_TYPE_SZARRAY:
10123                         if (!can_access_type (access_klass, type->data.klass))
10124                                 return FALSE;
10125                         break;
10126                 case MONO_TYPE_ARRAY:
10127                         if (!can_access_type (access_klass, type->data.array->eklass))
10128                                 return FALSE;
10129                         break;
10130                 case MONO_TYPE_PTR:
10131                         if (!can_access_type (access_klass, mono_class_from_mono_type (type->data.type)))
10132                                 return FALSE;
10133                         break;
10134                 case MONO_TYPE_CLASS:
10135                 case MONO_TYPE_VALUETYPE:
10136                 case MONO_TYPE_GENERICINST:
10137                         if (!can_access_type (access_klass, mono_class_from_mono_type (type)))
10138                                 return FALSE;
10139                 default:
10140                         break;
10141                 }
10142         }
10143         return TRUE;
10144 }
10145
10146 static gboolean
10147 can_access_type (MonoClass *access_klass, MonoClass *member_klass)
10148 {
10149         int access_level;
10150
10151         if (access_klass == member_klass)
10152                 return TRUE;
10153
10154         if (access_klass->image->assembly && access_klass->image->assembly->corlib_internal)
10155                 return TRUE;
10156
10157         if (access_klass->element_class && !access_klass->enumtype)
10158                 access_klass = access_klass->element_class;
10159
10160         if (member_klass->element_class && !member_klass->enumtype)
10161                 member_klass = member_klass->element_class;
10162
10163         access_level = mono_class_get_flags (member_klass) & TYPE_ATTRIBUTE_VISIBILITY_MASK;
10164
10165         if (member_klass->byval_arg.type == MONO_TYPE_VAR || member_klass->byval_arg.type == MONO_TYPE_MVAR)
10166                 return TRUE;
10167
10168         if (mono_class_is_ginst (member_klass) && !can_access_instantiation (access_klass, mono_class_get_generic_class (member_klass)->context.class_inst))
10169                 return FALSE;
10170
10171         if (is_nesting_type (access_klass, member_klass) || (access_klass->nested_in && is_nesting_type (access_klass->nested_in, member_klass)))
10172                 return TRUE;
10173
10174         if (member_klass->nested_in && !can_access_type (access_klass, member_klass->nested_in))
10175                 return FALSE;
10176
10177         /*Non nested type with nested visibility. We just fail it.*/
10178         if (access_level >= TYPE_ATTRIBUTE_NESTED_PRIVATE && access_level <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM && member_klass->nested_in == NULL)
10179                 return FALSE;
10180
10181         switch (access_level) {
10182         case TYPE_ATTRIBUTE_NOT_PUBLIC:
10183                 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
10184
10185         case TYPE_ATTRIBUTE_PUBLIC:
10186                 return TRUE;
10187
10188         case TYPE_ATTRIBUTE_NESTED_PUBLIC:
10189                 return TRUE;
10190
10191         case TYPE_ATTRIBUTE_NESTED_PRIVATE:
10192                 return is_nesting_type (member_klass, access_klass);
10193
10194         case TYPE_ATTRIBUTE_NESTED_FAMILY:
10195                 return mono_class_has_parent_and_ignore_generics (access_klass, member_klass->nested_in); 
10196
10197         case TYPE_ATTRIBUTE_NESTED_ASSEMBLY:
10198                 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
10199
10200         case TYPE_ATTRIBUTE_NESTED_FAM_AND_ASSEM:
10201                 return can_access_internals (access_klass->image->assembly, member_klass->nested_in->image->assembly) &&
10202                         mono_class_has_parent_and_ignore_generics (access_klass, member_klass->nested_in);
10203
10204         case TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM:
10205                 return can_access_internals (access_klass->image->assembly, member_klass->nested_in->image->assembly) ||
10206                         mono_class_has_parent_and_ignore_generics (access_klass, member_klass->nested_in);
10207         }
10208         return FALSE;
10209 }
10210
10211 /* FIXME: check visibility of type, too */
10212 static gboolean
10213 can_access_member (MonoClass *access_klass, MonoClass *member_klass, MonoClass* context_klass, int access_level)
10214 {
10215         MonoClass *member_generic_def;
10216         if (access_klass->image->assembly && access_klass->image->assembly->corlib_internal)
10217                 return TRUE;
10218
10219         MonoGenericClass *access_gklass = mono_class_try_get_generic_class (access_klass);
10220         if (((access_gklass && access_gklass->container_class) ||
10221                                         mono_class_is_gtd (access_klass)) && 
10222                         (member_generic_def = get_generic_definition_class (member_klass))) {
10223                 MonoClass *access_container;
10224
10225                 if (mono_class_is_gtd (access_klass))
10226                         access_container = access_klass;
10227                 else
10228                         access_container = access_gklass->container_class;
10229
10230                 if (can_access_member (access_container, member_generic_def, context_klass, access_level))
10231                         return TRUE;
10232         }
10233
10234         /* Partition I 8.5.3.2 */
10235         /* the access level values are the same for fields and methods */
10236         switch (access_level) {
10237         case FIELD_ATTRIBUTE_COMPILER_CONTROLLED:
10238                 /* same compilation unit */
10239                 return access_klass->image == member_klass->image;
10240         case FIELD_ATTRIBUTE_PRIVATE:
10241                 return access_klass == member_klass;
10242         case FIELD_ATTRIBUTE_FAM_AND_ASSEM:
10243                 if (is_valid_family_access (access_klass, member_klass, context_klass) &&
10244                     can_access_internals (access_klass->image->assembly, member_klass->image->assembly))
10245                         return TRUE;
10246                 return FALSE;
10247         case FIELD_ATTRIBUTE_ASSEMBLY:
10248                 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
10249         case FIELD_ATTRIBUTE_FAMILY:
10250                 if (is_valid_family_access (access_klass, member_klass, context_klass))
10251                         return TRUE;
10252                 return FALSE;
10253         case FIELD_ATTRIBUTE_FAM_OR_ASSEM:
10254                 if (is_valid_family_access (access_klass, member_klass, context_klass))
10255                         return TRUE;
10256                 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
10257         case FIELD_ATTRIBUTE_PUBLIC:
10258                 return TRUE;
10259         }
10260         return FALSE;
10261 }
10262
10263 /**
10264  * mono_method_can_access_field:
10265  * \param method Method that will attempt to access the field
10266  * \param field the field to access
10267  *
10268  * Used to determine if a method is allowed to access the specified field.
10269  *
10270  * \returns TRUE if the given \p method is allowed to access the \p field while following
10271  * the accessibility rules of the CLI.
10272  */
10273 gboolean
10274 mono_method_can_access_field (MonoMethod *method, MonoClassField *field)
10275 {
10276         /* FIXME: check all overlapping fields */
10277         int can = can_access_member (method->klass, field->parent, NULL, mono_field_get_type (field)->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10278         if (!can) {
10279                 MonoClass *nested = method->klass->nested_in;
10280                 while (nested) {
10281                         can = can_access_member (nested, field->parent, NULL, mono_field_get_type (field)->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10282                         if (can)
10283                                 return TRUE;
10284                         nested = nested->nested_in;
10285                 }
10286         }
10287         return can;
10288 }
10289
10290 /**
10291  * mono_method_can_access_method:
10292  * \param method Method that will attempt to access the other method
10293  * \param called the method that we want to probe for accessibility.
10294  *
10295  * Used to determine if the \p method is allowed to access the specified \p called method.
10296  *
10297  * \returns TRUE if the given \p method is allowed to invoke the \p called while following
10298  * the accessibility rules of the CLI.
10299  */
10300 gboolean
10301 mono_method_can_access_method (MonoMethod *method, MonoMethod *called)
10302 {
10303         method = mono_method_get_method_definition (method);
10304         called = mono_method_get_method_definition (called);
10305         return mono_method_can_access_method_full (method, called, NULL);
10306 }
10307
10308 /*
10309  * mono_method_can_access_method_full:
10310  * @method: The caller method 
10311  * @called: The called method 
10312  * @context_klass: The static type on stack of the owner @called object used
10313  * 
10314  * This function must be used with instance calls, as they have more strict family accessibility.
10315  * It can be used with static methods, but context_klass should be NULL.
10316  * 
10317  * Returns: TRUE if caller have proper visibility and acessibility to @called
10318  */
10319 gboolean
10320 mono_method_can_access_method_full (MonoMethod *method, MonoMethod *called, MonoClass *context_klass)
10321 {
10322         /* Wrappers are except from access checks */
10323         if (method->wrapper_type != MONO_WRAPPER_NONE || called->wrapper_type != MONO_WRAPPER_NONE)
10324                 return TRUE;
10325
10326         MonoClass *access_class = method->klass;
10327         MonoClass *member_class = called->klass;
10328         int can = can_access_member (access_class, member_class, context_klass, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
10329         if (!can) {
10330                 MonoClass *nested = access_class->nested_in;
10331                 while (nested) {
10332                         can = can_access_member (nested, member_class, context_klass, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
10333                         if (can)
10334                                 break;
10335                         nested = nested->nested_in;
10336                 }
10337         }
10338
10339         if (!can)
10340                 return FALSE;
10341
10342         can = can_access_type (access_class, member_class);
10343         if (!can) {
10344                 MonoClass *nested = access_class->nested_in;
10345                 while (nested) {
10346                         can = can_access_type (nested, member_class);
10347                         if (can)
10348                                 break;
10349                         nested = nested->nested_in;
10350                 }
10351         }
10352
10353         if (!can)
10354                 return FALSE;
10355
10356         if (called->is_inflated) {
10357                 MonoMethodInflated * infl = (MonoMethodInflated*)called;
10358                 if (infl->context.method_inst && !can_access_instantiation (access_class, infl->context.method_inst))
10359                         return FALSE;
10360         }
10361                 
10362         return TRUE;
10363 }
10364
10365
10366 /*
10367  * mono_method_can_access_field_full:
10368  * @method: The caller method 
10369  * @field: The accessed field
10370  * @context_klass: The static type on stack of the owner @field object used
10371  * 
10372  * This function must be used with instance fields, as they have more strict family accessibility.
10373  * It can be used with static fields, but context_klass should be NULL.
10374  * 
10375  * Returns: TRUE if caller have proper visibility and acessibility to @field
10376  */
10377 gboolean
10378 mono_method_can_access_field_full (MonoMethod *method, MonoClassField *field, MonoClass *context_klass)
10379 {
10380         MonoClass *access_class = method->klass;
10381         MonoClass *member_class = field->parent;
10382         /* FIXME: check all overlapping fields */
10383         int can = can_access_member (access_class, member_class, context_klass, field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10384         if (!can) {
10385                 MonoClass *nested = access_class->nested_in;
10386                 while (nested) {
10387                         can = can_access_member (nested, member_class, context_klass, field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10388                         if (can)
10389                                 break;
10390                         nested = nested->nested_in;
10391                 }
10392         }
10393
10394         if (!can)
10395                 return FALSE;
10396
10397         can = can_access_type (access_class, member_class);
10398         if (!can) {
10399                 MonoClass *nested = access_class->nested_in;
10400                 while (nested) {
10401                         can = can_access_type (nested, member_class);
10402                         if (can)
10403                                 break;
10404                         nested = nested->nested_in;
10405                 }
10406         }
10407
10408         if (!can)
10409                 return FALSE;
10410         return TRUE;
10411 }
10412
10413 /*
10414  * mono_class_can_access_class:
10415  * @source_class: The source class 
10416  * @target_class: The accessed class
10417  * 
10418  * This function returns is @target_class is visible to @source_class
10419  * 
10420  * Returns: TRUE if source have proper visibility and acessibility to target
10421  */
10422 gboolean
10423 mono_class_can_access_class (MonoClass *source_class, MonoClass *target_class)
10424 {
10425         return can_access_type (source_class, target_class);
10426 }
10427
10428 /**
10429  * mono_type_is_valid_enum_basetype:
10430  * \param type The MonoType to check
10431  * \returns TRUE if the type can be used as the basetype of an enum
10432  */
10433 gboolean mono_type_is_valid_enum_basetype (MonoType * type) {
10434         switch (type->type) {
10435         case MONO_TYPE_I1:
10436         case MONO_TYPE_U1:
10437         case MONO_TYPE_BOOLEAN:
10438         case MONO_TYPE_I2:
10439         case MONO_TYPE_U2:
10440         case MONO_TYPE_CHAR:
10441         case MONO_TYPE_I4:
10442         case MONO_TYPE_U4:
10443         case MONO_TYPE_I8:
10444         case MONO_TYPE_U8:
10445         case MONO_TYPE_I:
10446         case MONO_TYPE_U:
10447                 return TRUE;
10448         default:
10449                 return FALSE;
10450         }
10451 }
10452
10453 /**
10454  * mono_class_is_valid_enum:
10455  * \param klass An enum class to be validated
10456  *
10457  * This method verify the required properties an enum should have.
10458  *
10459  * FIXME: TypeBuilder enums are allowed to implement interfaces, but since they cannot have methods, only empty interfaces are possible
10460  * FIXME: enum types are not allowed to have a cctor, but mono_reflection_create_runtime_class sets has_cctor to 1 for all types
10461  * FIXME: TypeBuilder enums can have any kind of static fields, but the spec is very explicit about that (P II 14.3)
10462  *
10463  * \returns TRUE if the informed enum class is valid 
10464  */
10465 gboolean
10466 mono_class_is_valid_enum (MonoClass *klass)
10467 {
10468         MonoClassField * field;
10469         gpointer iter = NULL;
10470         gboolean found_base_field = FALSE;
10471
10472         g_assert (klass->enumtype);
10473         /* we cannot test against mono_defaults.enum_class, or mcs won't be able to compile the System namespace*/
10474         if (!klass->parent || strcmp (klass->parent->name, "Enum") || strcmp (klass->parent->name_space, "System") ) {
10475                 return FALSE;
10476         }
10477
10478         if (!mono_class_is_auto_layout (klass))
10479                 return FALSE;
10480
10481         while ((field = mono_class_get_fields (klass, &iter))) {
10482                 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
10483                         if (found_base_field)
10484                                 return FALSE;
10485                         found_base_field = TRUE;
10486                         if (!mono_type_is_valid_enum_basetype (field->type))
10487                                 return FALSE;
10488                 }
10489         }
10490
10491         if (!found_base_field)
10492                 return FALSE;
10493
10494         if (mono_class_get_method_count (klass) > 0)
10495                 return FALSE;
10496
10497         return TRUE;
10498 }
10499
10500 gboolean
10501 mono_generic_class_is_generic_type_definition (MonoGenericClass *gklass)
10502 {
10503         return gklass->context.class_inst == mono_class_get_generic_container (gklass->container_class)->context.class_inst;
10504 }
10505
10506 /*
10507  * mono_class_setup_interface_id:
10508  *
10509  * Initializes MonoClass::interface_id if required.
10510  *
10511  * LOCKING: Acquires the loader lock.
10512  */
10513 void
10514 mono_class_setup_interface_id (MonoClass *klass)
10515 {
10516         mono_loader_lock ();
10517         if (MONO_CLASS_IS_INTERFACE (klass) && !klass->interface_id)
10518                 klass->interface_id = mono_get_unique_iid (klass);
10519         mono_loader_unlock ();
10520 }
10521
10522 /*
10523  * mono_class_setup_interfaces:
10524  *
10525  *   Initialize klass->interfaces/interfaces_count.
10526  * LOCKING: Acquires the loader lock.
10527  * This function can fail the type.
10528  */
10529 void
10530 mono_class_setup_interfaces (MonoClass *klass, MonoError *error)
10531 {
10532         int i, interface_count;
10533         MonoClass **interfaces;
10534
10535         error_init (error);
10536
10537         if (klass->interfaces_inited)
10538                 return;
10539
10540         if (klass->rank == 1 && klass->byval_arg.type != MONO_TYPE_ARRAY) {
10541                 MonoType *args [1];
10542
10543                 /* generic IList, ICollection, IEnumerable */
10544                 interface_count = 2;
10545                 interfaces = (MonoClass **)mono_image_alloc0 (klass->image, sizeof (MonoClass*) * interface_count);
10546
10547                 args [0] = &klass->element_class->byval_arg;
10548                 interfaces [0] = mono_class_bind_generic_parameters (
10549                         mono_defaults.generic_ilist_class, 1, args, FALSE);
10550                 interfaces [1] = mono_class_bind_generic_parameters (
10551                            mono_defaults.generic_ireadonlylist_class, 1, args, FALSE);
10552         } else if (mono_class_is_ginst (klass)) {
10553                 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
10554
10555                 mono_class_setup_interfaces (gklass, error);
10556                 if (!mono_error_ok (error)) {
10557                         mono_class_set_type_load_failure (klass, "Could not setup the interfaces");
10558                         return;
10559                 }
10560
10561                 interface_count = gklass->interface_count;
10562                 interfaces = mono_class_new0 (klass, MonoClass *, interface_count);
10563                 for (i = 0; i < interface_count; i++) {
10564                         interfaces [i] = mono_class_inflate_generic_class_checked (gklass->interfaces [i], mono_generic_class_get_context (mono_class_get_generic_class (klass)), error);
10565                         if (!mono_error_ok (error)) {
10566                                 mono_class_set_type_load_failure (klass, "Could not setup the interfaces");
10567                                 return;
10568                         }
10569                 }
10570         } else {
10571                 interface_count = 0;
10572                 interfaces = NULL;
10573         }
10574
10575         mono_loader_lock ();
10576         if (!klass->interfaces_inited) {
10577                 klass->interface_count = interface_count;
10578                 klass->interfaces = interfaces;
10579
10580                 mono_memory_barrier ();
10581
10582                 klass->interfaces_inited = TRUE;
10583         }
10584         mono_loader_unlock ();
10585 }
10586
10587 static void
10588 mono_field_resolve_type (MonoClassField *field, MonoError *error)
10589 {
10590         MonoClass *klass = field->parent;
10591         MonoImage *image = klass->image;
10592         MonoClass *gtd = mono_class_is_ginst (klass) ? mono_class_get_generic_type_definition (klass) : NULL;
10593         MonoType *ftype;
10594         int field_idx = field - klass->fields;
10595
10596         error_init (error);
10597
10598         if (gtd) {
10599                 MonoClassField *gfield = &gtd->fields [field_idx];
10600                 MonoType *gtype = mono_field_get_type_checked (gfield, error);
10601                 if (!mono_error_ok (error)) {
10602                         char *full_name = mono_type_get_full_name (gtd);
10603                         mono_class_set_type_load_failure (klass, "Could not load generic type of field '%s:%s' (%d) due to: %s", full_name, gfield->name, field_idx, mono_error_get_message (error));
10604                         g_free (full_name);
10605                 }
10606
10607                 ftype = mono_class_inflate_generic_type_no_copy (image, gtype, mono_class_get_context (klass), error);
10608                 if (!mono_error_ok (error)) {
10609                         char *full_name = mono_type_get_full_name (klass);
10610                         mono_class_set_type_load_failure (klass, "Could not load instantiated type of field '%s:%s' (%d) due to: %s", full_name, field->name, field_idx, mono_error_get_message (error));
10611                         g_free (full_name);
10612                 }
10613         } else {
10614                 const char *sig;
10615                 guint32 cols [MONO_FIELD_SIZE];
10616                 MonoGenericContainer *container = NULL;
10617                 int idx = mono_class_get_first_field_idx (klass) + field_idx;
10618
10619                 /*FIXME, in theory we do not lazy load SRE fields*/
10620                 g_assert (!image_is_dynamic (image));
10621
10622                 if (mono_class_is_gtd (klass)) {
10623                         container = mono_class_get_generic_container (klass);
10624                 } else if (gtd) {
10625                         container = mono_class_get_generic_container (gtd);
10626                         g_assert (container);
10627                 }
10628
10629                 /* first_field_idx and idx points into the fieldptr table */
10630                 mono_metadata_decode_table_row (image, MONO_TABLE_FIELD, idx, cols, MONO_FIELD_SIZE);
10631
10632                 if (!mono_verifier_verify_field_signature (image, cols [MONO_FIELD_SIGNATURE], NULL)) {
10633                         char *full_name = mono_type_get_full_name (klass);
10634                         mono_error_set_type_load_class (error, klass, "Could not verify field '%s:%s' signature", full_name, field->name);;
10635                         mono_class_set_type_load_failure (klass, "%s", mono_error_get_message (error));
10636                         g_free (full_name);
10637                         return;
10638                 }
10639
10640                 sig = mono_metadata_blob_heap (image, cols [MONO_FIELD_SIGNATURE]);
10641
10642                 mono_metadata_decode_value (sig, &sig);
10643                 /* FIELD signature == 0x06 */
10644                 g_assert (*sig == 0x06);
10645
10646                 ftype = mono_metadata_parse_type_checked (image, container, cols [MONO_FIELD_FLAGS], FALSE, sig + 1, &sig, error);
10647                 if (!ftype) {
10648                         char *full_name = mono_type_get_full_name (klass);
10649                         mono_class_set_type_load_failure (klass, "Could not load type of field '%s:%s' (%d) due to: %s", full_name, field->name, field_idx, mono_error_get_message (error));
10650                         g_free (full_name);
10651                 }
10652         }
10653         mono_memory_barrier ();
10654         field->type = ftype;
10655 }
10656
10657 static guint32
10658 mono_field_resolve_flags (MonoClassField *field)
10659 {
10660         MonoClass *klass = field->parent;
10661         MonoImage *image = klass->image;
10662         MonoClass *gtd = mono_class_is_ginst (klass) ? mono_class_get_generic_type_definition (klass) : NULL;
10663         int field_idx = field - klass->fields;
10664
10665         if (gtd) {
10666                 MonoClassField *gfield = &gtd->fields [field_idx];
10667                 return mono_field_get_flags (gfield);
10668         } else {
10669                 int idx = mono_class_get_first_field_idx (klass) + field_idx;
10670
10671                 /*FIXME, in theory we do not lazy load SRE fields*/
10672                 g_assert (!image_is_dynamic (image));
10673
10674                 return mono_metadata_decode_table_row_col (image, MONO_TABLE_FIELD, idx, MONO_FIELD_FLAGS);
10675         }
10676 }
10677
10678 /**
10679  * mono_class_get_fields_lazy:
10680  * \param klass the MonoClass to act on
10681  *
10682  * This routine is an iterator routine for retrieving the fields in a class.
10683  * Only minimal information about fields are loaded. Accessors must be used
10684  * for all MonoClassField returned.
10685  *
10686  * You must pass a gpointer that points to zero and is treated as an opaque handle to
10687  * iterate over all of the elements.  When no more values are
10688  * available, the return value is NULL.
10689  *
10690  * \returns a \c MonoClassField* on each iteration, or NULL when no more fields are available.
10691  */
10692 MonoClassField*
10693 mono_class_get_fields_lazy (MonoClass* klass, gpointer *iter)
10694 {
10695         MonoClassField* field;
10696         if (!iter)
10697                 return NULL;
10698         if (!*iter) {
10699                 mono_class_setup_basic_field_info (klass);
10700                 if (!klass->fields)
10701                         return NULL;
10702                 /* start from the first */
10703                 if (mono_class_get_field_count (klass)) {
10704                         *iter = &klass->fields [0];
10705                         return (MonoClassField *)*iter;
10706                 } else {
10707                         /* no fields */
10708                         return NULL;
10709                 }
10710         }
10711         field = (MonoClassField *)*iter;
10712         field++;
10713         if (field < &klass->fields [mono_class_get_field_count (klass)]) {
10714                 *iter = field;
10715                 return (MonoClassField *)*iter;
10716         }
10717         return NULL;
10718 }
10719
10720 char*
10721 mono_class_full_name (MonoClass *klass)
10722 {
10723         return mono_type_full_name (&klass->byval_arg);
10724 }
10725
10726 /* Declare all shared lazy type lookup functions */
10727 GENERATE_TRY_GET_CLASS_WITH_CACHE (safehandle, "System.Runtime.InteropServices", "SafeHandle")
10728
10729 /**
10730  * mono_method_get_base_method:
10731  * \param method a method
10732  * \param definition if true, get the definition
10733  * \param error set on failure
10734  *
10735  * Given a virtual method associated with a subclass, return the corresponding
10736  * method from an ancestor.  If \p definition is FALSE, returns the method in the
10737  * superclass of the given method.  If \p definition is TRUE, return the method
10738  * in the ancestor class where it was first declared.  The type arguments will
10739  * be inflated in the ancestor classes.  If the method is not associated with a
10740  * class, or isn't virtual, returns the method itself.  On failure returns NULL
10741  * and sets \p error.
10742  */
10743 MonoMethod*
10744 mono_method_get_base_method (MonoMethod *method, gboolean definition, MonoError *error)
10745 {
10746         MonoClass *klass, *parent;
10747         MonoGenericContext *generic_inst = NULL;
10748         MonoMethod *result = NULL;
10749         int slot;
10750
10751         if (method->klass == NULL)
10752                 return method;
10753
10754         if (!(method->flags & METHOD_ATTRIBUTE_VIRTUAL) ||
10755             MONO_CLASS_IS_INTERFACE (method->klass) ||
10756             method->flags & METHOD_ATTRIBUTE_NEW_SLOT)
10757                 return method;
10758
10759         slot = mono_method_get_vtable_slot (method);
10760         if (slot == -1)
10761                 return method;
10762
10763         klass = method->klass;
10764         if (mono_class_is_ginst (klass)) {
10765                 generic_inst = mono_class_get_context (klass);
10766                 klass = mono_class_get_generic_class (klass)->container_class;
10767         }
10768
10769 retry:
10770         if (definition) {
10771                 /* At the end of the loop, klass points to the eldest class that has this virtual function slot. */
10772                 for (parent = klass->parent; parent != NULL; parent = parent->parent) {
10773                         /* on entry, klass is either a plain old non-generic class and generic_inst == NULL
10774                            or klass is the generic container class and generic_inst is the instantiation.
10775
10776                            when we go to the parent, if the parent is an open constructed type, we need to
10777                            replace the type parameters by the definitions from the generic_inst, and then take it
10778                            apart again into the klass and the generic_inst.
10779
10780                            For cases like this:
10781                            class C<T> : B<T, int> {
10782                                public override void Foo () { ... }
10783                            }
10784                            class B<U,V> : A<HashMap<U,V>> {
10785                                public override void Foo () { ... }
10786                            }
10787                            class A<X> {
10788                                public virtual void Foo () { ... }
10789                            }
10790
10791                            if at each iteration the parent isn't open, we can skip inflating it.  if at some
10792                            iteration the parent isn't generic (after possible inflation), we set generic_inst to
10793                            NULL;
10794                         */
10795                         MonoGenericContext *parent_inst = NULL;
10796                         if (mono_class_is_open_constructed_type (mono_class_get_type (parent))) {
10797                                 parent = mono_class_inflate_generic_class_checked (parent, generic_inst, error);
10798                                 return_val_if_nok  (error, NULL);
10799                         }
10800                         if (mono_class_is_ginst (parent)) {
10801                                 parent_inst = mono_class_get_context (parent);
10802                                 parent = mono_class_get_generic_class (parent)->container_class;
10803                         }
10804
10805                         mono_class_setup_vtable (parent);
10806                         if (parent->vtable_size <= slot)
10807                                 break;
10808                         klass = parent;
10809                         generic_inst = parent_inst;
10810                 }
10811         } else {
10812                 klass = klass->parent;
10813                 if (!klass)
10814                         return method;
10815                 if (mono_class_is_open_constructed_type (mono_class_get_type (klass))) {
10816                         klass = mono_class_inflate_generic_class_checked (klass, generic_inst, error);
10817                         return_val_if_nok (error, NULL);
10818
10819                         generic_inst = NULL;
10820                 }
10821                 if (mono_class_is_ginst (klass)) {
10822                         generic_inst = mono_class_get_context (klass);
10823                         klass = mono_class_get_generic_class (klass)->container_class;
10824                 }
10825
10826         }
10827
10828         if (generic_inst) {
10829                 klass = mono_class_inflate_generic_class_checked (klass, generic_inst, error);
10830                 return_val_if_nok (error, NULL);
10831         }
10832
10833         if (klass == method->klass)
10834                 return method;
10835
10836         /*This is possible if definition == FALSE.
10837          * Do it here to be really sure we don't read invalid memory.
10838          */
10839         if (slot >= klass->vtable_size)
10840                 return method;
10841
10842         mono_class_setup_vtable (klass);
10843
10844         result = klass->vtable [slot];
10845         if (result == NULL) {
10846                 /* It is an abstract method */
10847                 gboolean found = FALSE;
10848                 gpointer iter = NULL;
10849                 while ((result = mono_class_get_methods (klass, &iter))) {
10850                         if (result->slot == slot) {
10851                                 found = TRUE;
10852                                 break;
10853                         }
10854                 }
10855                 /* found might be FALSE if we looked in an abstract class
10856                  * that doesn't override an abstract method of its
10857                  * parent: 
10858                  *   abstract class Base {
10859                  *     public abstract void Foo ();
10860                  *   }
10861                  *   abstract class Derived : Base { }
10862                  *   class Child : Derived {
10863                  *     public override void Foo () { }
10864                  *  }
10865                  *
10866                  *  if m was Child.Foo and we ask for the base method,
10867                  *  then we get here with klass == Derived and found == FALSE
10868                  */
10869                 /* but it shouldn't be the case that if we're looking
10870                  * for the definition and didn't find a result; the
10871                  * loop above should've taken us as far as we could
10872                  * go! */
10873                 g_assert (!(definition && !found));
10874                 if (!found)
10875                         goto retry;
10876         }
10877
10878         g_assert (result != NULL);
10879         return result;
10880 }