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