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