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