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