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