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