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