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